xref: /reactos/modules/rosapps/drivers/vfd/vfdlink.c (revision 8786e12d)
1 /*
2 	vfdlink.c
3 
4 	Virtual Floppy Drive for Windows NT platform
5 	Kernel mode driver: persistent drive letter functions
6 
7 	Copyright (C) 2003-2005 Ken Kato
8 */
9 
10 #include "imports.h"
11 #include "vfddrv.h"
12 #include "vfddbg.h"
13 
14 #ifdef ALLOC_PRAGMA
15 #pragma alloc_text(PAGE, VfdSetLink)
16 #pragma alloc_text(PAGE, VfdLoadLink)
17 #pragma alloc_text(PAGE, VfdStoreLink)
18 #endif	// ALLOC_PRAGMA
19 
20 //
21 //	create or remove the persistent drive letter (Windows NT)
22 //
23 NTSTATUS
24 VfdSetLink(
25 	IN	PDEVICE_EXTENSION		DeviceExtension,
26 	IN	CHAR					DriveLetter)
27 {
28 	UNICODE_STRING				unicode_name;
29 	WCHAR						name_buf[15];
30 	NTSTATUS					status = STATUS_SUCCESS;
31 
32 	VFDTRACE(VFDINFO, ("[VFD] VfdSetLink - IN\n"));
33 
34 	//	convert lower case into upper case
35 
36 	if (DriveLetter >= 'a' && DriveLetter <= 'z') {
37 		DriveLetter -= ('a' - 'A');
38 	}
39 
40 	//	check the drive letter range
41 
42 	if (DriveLetter != 0 &&
43 		(DriveLetter < 'A' || DriveLetter > 'Z')) {
44 		return STATUS_INVALID_PARAMETER;
45 	}
46 
47 	if (DeviceExtension->DriveLetter &&
48 		DeviceExtension->DriveLetter != DriveLetter) {
49 		//
50 		//	Delete the old drive letter
51 		//
52 #ifndef __REACTOS__
53 		name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
54 #else
55 		name_buf[ARRAYSIZE(name_buf) - 1] = UNICODE_NULL;
56 #endif
57 
58 		_snwprintf(name_buf, sizeof(name_buf) - 1,
59 			L"\\??\\%wc:", DeviceExtension->DriveLetter);
60 
61 		RtlInitUnicodeString(&unicode_name, name_buf);
62 
63 		status = IoDeleteSymbolicLink(&unicode_name);
64 
65 		if (NT_SUCCESS(status)) {
66 			VFDTRACE(VFDINFO,
67 				("[VFD] Link %ws deleted\n", name_buf));
68 
69 			DeviceExtension->DriveLetter = 0;
70 		}
71 		else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
72 			//	the driver letter did not exist in the first place
73 
74 			VFDTRACE(VFDINFO,
75 				("[VFD] Link %ws not found\n", name_buf));
76 
77 			DeviceExtension->DriveLetter = 0;
78 			status = STATUS_SUCCESS;
79 		}
80 		else {
81 			VFDTRACE(VFDWARN,
82 				("[VFD] IoDeleteSymbolicLink %ws - %s\n",
83 				name_buf, GetStatusName(status)));
84 		}
85 	}
86 
87 	if (NT_SUCCESS(status) && DriveLetter) {
88 		//
89 		//	Create a new drive letter
90 		//
91 
92 #ifndef __REACTOS__
93 		name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
94 
95 		_snwprintf(name_buf, sizeof(name_buf) - 1,
96 			(OsMajorVersion >= 5) ?
97 			L"\\??\\Global\\%wc:" : L"\\??\\%wc:",
98 			DriveLetter);
99 #else
100 		name_buf[ARRAYSIZE(name_buf) - 1] = UNICODE_NULL;
101 
102 		_snwprintf(name_buf, ARRAYSIZE(name_buf) - 1,
103 			(OsMajorVersion >= 5) ?
104 			L"\\??\\Global\\%wc:" : L"\\??\\%wc:",
105 			DriveLetter);
106 #endif
107 
108 		RtlInitUnicodeString(&unicode_name, name_buf);
109 
110 		status = IoCreateSymbolicLink(
111 			&unicode_name, &(DeviceExtension->DeviceName));
112 
113 		if (NT_SUCCESS(status)) {
114 			VFDTRACE(VFDINFO, ("[VFD] Link %ws created\n", name_buf));
115 
116 			DeviceExtension->DriveLetter = DriveLetter;
117 		}
118 		else {
119 			VFDTRACE(VFDWARN,
120 				("[VFD] IoCreateSymbolicLink %ws - %s\n",
121 				name_buf, GetStatusName(status)));
122 		}
123 	}
124 
125 	VFDTRACE(VFDINFO,
126 		("[VFD] VfdSetLink - %s\n", GetStatusName(status)));
127 
128 	return status;
129 }
130 
131 //
132 //	load the persistent drive letter from the registry
133 //
134 NTSTATUS
135 VfdLoadLink(
136 	IN	PDEVICE_EXTENSION		DeviceExtension,
137 	IN	PWSTR					RegistryPath)
138 {
139 	RTL_QUERY_REGISTRY_TABLE	params[2];
140 	WCHAR						name_buf[20];
141 	ULONG						letter;
142 	ULONG						zero	= 0;
143 	NTSTATUS					status;
144 
145 	VFDTRACE(VFDINFO, ("[VFD] VfdLoadLink - IN\n"));
146 
147 	RtlZeroMemory(params, sizeof(params));
148 
149 #ifndef __REACTOS__
150 	name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
151 
152 	_snwprintf(name_buf, sizeof(name_buf) - 1,
153 		VFD_REG_DRIVE_LETTER L"%lu",
154 		DeviceExtension->DeviceNumber);
155 #else
156 	name_buf[ARRAYSIZE(name_buf) - 1] = UNICODE_NULL;
157 
158 	_snwprintf(name_buf, ARRAYSIZE(name_buf) - 1,
159 		VFD_REG_DRIVE_LETTER L"%lu",
160 		DeviceExtension->DeviceNumber);
161 #endif
162 
163 	params[0].Flags			= RTL_QUERY_REGISTRY_DIRECT;
164 	params[0].Name			= name_buf;
165 	params[0].EntryContext	= &letter;
166 	params[0].DefaultType	= REG_DWORD;
167 	params[0].DefaultData	= &zero;
168 	params[0].DefaultLength	= sizeof(ULONG);
169 
170 	status = RtlQueryRegistryValues(
171 		RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
172 		RegistryPath, &params[0], NULL, NULL);
173 
174 	VFDTRACE(VFDINFO,
175 		("[VFD] Drive letter '%wc' loaded from the registry\n",
176 		letter ? letter : ' '));
177 
178 	DeviceExtension->DriveLetter = (CHAR)letter;
179 
180 	VFDTRACE(VFDINFO,
181 		("[VFD] VfdLoadLink - %s\n", GetStatusName(status)));
182 
183 	return status;
184 }
185 
186 //
187 //	store the persistent drive letter into the registry
188 //
189 NTSTATUS
190 VfdStoreLink(
191 	IN	PDEVICE_EXTENSION		DeviceExtension)
192 {
193 	PVFD_DRIVER_EXTENSION		driver_extension;
194 	WCHAR						name_buf[20];
195 	ULONG						letter;
196 	NTSTATUS					status;
197 
198 	VFDTRACE(VFDINFO, ("[VFD] VfdStoreLink - IN\n"));
199 
200 #ifdef VFD_PNP
201 	driver_extension = IoGetDriverObjectExtension(
202 		DeviceExtension->device_object->DriverObject,
203 		VFD_DRIVER_EXTENSION_ID);
204 #else	// VFD_PNP
205 	driver_extension = DeviceExtension->DriverExtension;
206 #endif	// VFD_PNP
207 
208 	if (!driver_extension ||
209 		!driver_extension->RegistryPath.Buffer) {
210 
211 		VFDTRACE(VFDWARN, ("[VFD] Registry Path not present.\n"));
212 		VFDTRACE(VFDINFO, ("[VFD] VfdStoreLinks - OUT\n"));
213 		return STATUS_DRIVER_INTERNAL_ERROR;
214 	}
215 
216 #ifndef __REACTOS__
217 	name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
218 
219 	_snwprintf(name_buf, sizeof(name_buf) - 1,
220 		VFD_REG_DRIVE_LETTER L"%lu",
221 		DeviceExtension->DeviceNumber);
222 #else
223 	name_buf[ARRAYSIZE(name_buf) - 1] = UNICODE_NULL;
224 
225 	_snwprintf(name_buf, ARRAYSIZE(name_buf) - 1,
226 		VFD_REG_DRIVE_LETTER L"%lu",
227 		DeviceExtension->DeviceNumber);
228 #endif
229 
230 	letter = DeviceExtension->DriveLetter;
231 
232 	status = RtlWriteRegistryValue(
233 		RTL_REGISTRY_ABSOLUTE,
234 		driver_extension->RegistryPath.Buffer,
235 		name_buf,
236 		REG_DWORD,
237 		&letter,
238 		sizeof(ULONG));
239 
240 	if (!NT_SUCCESS(status)) {
241 		VFDTRACE(VFDWARN,
242 			("[VFD] RtlWriteRegistryValue - %s\n",
243 			GetStatusName(status)));
244 	}
245 	else {
246 		VFDTRACE(VFDINFO,
247 			("[VFD] Drive letter '%wc' stored into the registry\n",
248 			letter ? letter : L' '));
249 	}
250 
251 	VFDTRACE(VFDINFO,
252 		("[VFD] VfdStoreLink - %s\n", GetStatusName(status)));
253 
254 	return status;
255 }
256