xref: /reactos/modules/rosapps/drivers/vfd/vfdlink.c (revision 3c774903)
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 		name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
53 
54 		_snwprintf(name_buf, sizeof(name_buf) - 1,
55 			L"\\??\\%wc:", DeviceExtension->DriveLetter);
56 
57 		RtlInitUnicodeString(&unicode_name, name_buf);
58 
59 		status = IoDeleteSymbolicLink(&unicode_name);
60 
61 		if (NT_SUCCESS(status)) {
62 			VFDTRACE(VFDINFO,
63 				("[VFD] Link %ws deleted\n", name_buf));
64 
65 			DeviceExtension->DriveLetter = 0;
66 		}
67 		else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
68 			//	the driver letter did not exist in the first place
69 
70 			VFDTRACE(VFDINFO,
71 				("[VFD] Link %ws not found\n", name_buf));
72 
73 			DeviceExtension->DriveLetter = 0;
74 			status = STATUS_SUCCESS;
75 		}
76 		else {
77 			VFDTRACE(VFDWARN,
78 				("[VFD] IoDeleteSymbolicLink %ws - %s\n",
79 				name_buf, GetStatusName(status)));
80 		}
81 	}
82 
83 	if (NT_SUCCESS(status) && DriveLetter) {
84 		//
85 		//	Create a new drive letter
86 		//
87 
88 		name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
89 
90 		_snwprintf(name_buf, sizeof(name_buf) - 1,
91 			(OsMajorVersion >= 5) ?
92 			L"\\??\\Global\\%wc:" : L"\\??\\%wc:",
93 			DriveLetter);
94 
95 		RtlInitUnicodeString(&unicode_name, name_buf);
96 
97 		status = IoCreateSymbolicLink(
98 			&unicode_name, &(DeviceExtension->DeviceName));
99 
100 		if (NT_SUCCESS(status)) {
101 			VFDTRACE(VFDINFO, ("[VFD] Link %ws created\n", name_buf));
102 
103 			DeviceExtension->DriveLetter = DriveLetter;
104 		}
105 		else {
106 			VFDTRACE(VFDWARN,
107 				("[VFD] IoCreateSymbolicLink %ws - %s\n",
108 				name_buf, GetStatusName(status)));
109 		}
110 	}
111 
112 	VFDTRACE(VFDINFO,
113 		("[VFD] VfdSetLink - %s\n", GetStatusName(status)));
114 
115 	return status;
116 }
117 
118 //
119 //	load the persistent drive letter from the registry
120 //
121 NTSTATUS
122 VfdLoadLink(
123 	IN	PDEVICE_EXTENSION		DeviceExtension,
124 	IN	PWSTR					RegistryPath)
125 {
126 	RTL_QUERY_REGISTRY_TABLE	params[2];
127 	WCHAR						name_buf[20];
128 	ULONG						letter;
129 	ULONG						zero	= 0;
130 	NTSTATUS					status;
131 
132 	VFDTRACE(VFDINFO, ("[VFD] VfdLoadLink - IN\n"));
133 
134 	RtlZeroMemory(params, sizeof(params));
135 
136 	name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
137 
138 	_snwprintf(name_buf, sizeof(name_buf) - 1,
139 		VFD_REG_DRIVE_LETTER L"%lu",
140 		DeviceExtension->DeviceNumber);
141 
142 	params[0].Flags			= RTL_QUERY_REGISTRY_DIRECT;
143 	params[0].Name			= name_buf;
144 	params[0].EntryContext	= &letter;
145 	params[0].DefaultType	= REG_DWORD;
146 	params[0].DefaultData	= &zero;
147 	params[0].DefaultLength	= sizeof(ULONG);
148 
149 	status = RtlQueryRegistryValues(
150 		RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
151 		RegistryPath, &params[0], NULL, NULL);
152 
153 	VFDTRACE(VFDINFO,
154 		("[VFD] Drive letter '%wc' loaded from the registry\n",
155 		letter ? letter : ' '));
156 
157 	DeviceExtension->DriveLetter = (CHAR)letter;
158 
159 	VFDTRACE(VFDINFO,
160 		("[VFD] VfdLoadLink - %s\n", GetStatusName(status)));
161 
162 	return status;
163 }
164 
165 //
166 //	store the persistent drive letter into the registry
167 //
168 NTSTATUS
169 VfdStoreLink(
170 	IN	PDEVICE_EXTENSION		DeviceExtension)
171 {
172 	PVFD_DRIVER_EXTENSION		driver_extension;
173 	WCHAR						name_buf[20];
174 	ULONG						letter;
175 	NTSTATUS					status;
176 
177 	VFDTRACE(VFDINFO, ("[VFD] VfdStoreLink - IN\n"));
178 
179 #ifdef VFD_PNP
180 	driver_extension = IoGetDriverObjectExtension(
181 		DeviceExtension->device_object->DriverObject,
182 		VFD_DRIVER_EXTENSION_ID);
183 #else	// VFD_PNP
184 	driver_extension = DeviceExtension->DriverExtension;
185 #endif	// VFD_PNP
186 
187 	if (!driver_extension ||
188 		!driver_extension->RegistryPath.Buffer) {
189 
190 		VFDTRACE(VFDWARN, ("[VFD] Registry Path not present.\n"));
191 		VFDTRACE(VFDINFO, ("[VFD] VfdStoreLinks - OUT\n"));
192 		return STATUS_DRIVER_INTERNAL_ERROR;
193 	}
194 
195 	name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
196 
197 	_snwprintf(name_buf, sizeof(name_buf) - 1,
198 		VFD_REG_DRIVE_LETTER L"%lu",
199 		DeviceExtension->DeviceNumber);
200 
201 	letter = DeviceExtension->DriveLetter;
202 
203 	status = RtlWriteRegistryValue(
204 		RTL_REGISTRY_ABSOLUTE,
205 		driver_extension->RegistryPath.Buffer,
206 		name_buf,
207 		REG_DWORD,
208 		&letter,
209 		sizeof(ULONG));
210 
211 	if (!NT_SUCCESS(status)) {
212 		VFDTRACE(VFDWARN,
213 			("[VFD] RtlWriteRegistryValue - %s\n",
214 			GetStatusName(status)));
215 	}
216 	else {
217 		VFDTRACE(VFDINFO,
218 			("[VFD] Drive letter '%wc' stored into the registry\n",
219 			letter ? letter : L' '));
220 	}
221 
222 	VFDTRACE(VFDINFO,
223 		("[VFD] VfdStoreLink - %s\n", GetStatusName(status)));
224 
225 	return status;
226 }
227