[REACTOS] Fix 64 bit build (#465)
[reactos.git] / modules / rosapps / drivers / vfd / vfddev.c
1 /*
2 vfddev.c
3
4 Virtual Floppy Drive for Windows NT platform
5 Kernel mode driver: device create/delete 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, VfdCreateDevice)
16 #pragma alloc_text(PAGE, VfdDeleteDevice)
17 #endif // ALLOC_PRAGMA
18
19 //
20 // Create a VFD device object
21 //
22 NTSTATUS
23 VfdCreateDevice(
24 IN PDRIVER_OBJECT DriverObject,
25 OUT PVOID Parameter)
26 {
27 NTSTATUS status;
28 ULONG physical_num;
29
30 UNICODE_STRING unicode_name;
31 WCHAR name_buffer[40];
32
33 PVFD_DRIVER_EXTENSION driver_extension = NULL;
34 PDEVICE_OBJECT device_object = NULL;
35 PDEVICE_EXTENSION device_extension = NULL;
36 HANDLE thread_handle = NULL;
37
38 VFDTRACE(VFDINFO | VFDDEV, ("[VFD] VfdCreateDevice - IN\n"));
39
40 #ifdef VFD_PNP
41
42 // Get the driver device_extension for the driver object
43 driver_extension = IoGetDriverObjectExtension(
44 DriverObject, VFD_DRIVER_EXTENSION_ID);
45
46 #else // VFD_PNP
47
48 // The driver device_extension is passed as the Parameter
49 driver_extension = (PVFD_DRIVER_EXTENSION)Parameter;
50
51 #endif // VFD_PNP
52
53 if (driver_extension == NULL) {
54 VFDTRACE(VFDERR, ("[VFD] Failed to get the driver extension\n"));
55 return STATUS_DRIVER_INTERNAL_ERROR;
56 }
57
58 //
59 // Create a device object
60 // \Device\Floppy<n>
61 //
62 physical_num = 0;
63
64 do {
65 #ifndef __REACTOS__
66 name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL;
67
68 _snwprintf(name_buffer, sizeof(name_buffer) - 1,
69 L"\\Device\\Floppy%lu", physical_num);
70 #else
71 name_buffer[ARRAYSIZE(name_buffer) - 1] = UNICODE_NULL;
72
73 _snwprintf(name_buffer, ARRAYSIZE(name_buffer) - 1,
74 L"\\Device\\Floppy%lu", physical_num);
75 #endif
76
77 RtlInitUnicodeString(&unicode_name, name_buffer);
78
79 status = IoCreateDevice(
80 DriverObject,
81 sizeof(DEVICE_EXTENSION),
82 &unicode_name,
83 FILE_DEVICE_DISK,
84 FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE | FILE_DEVICE_SECURE_OPEN,
85 FALSE,
86 &device_object);
87
88 if (status != STATUS_OBJECT_NAME_EXISTS &&
89 status != STATUS_OBJECT_NAME_COLLISION) {
90 break;
91 }
92 }
93 while (++physical_num < 100);
94
95 if (!NT_SUCCESS(status)) {
96 VFDTRACE(VFDERR,
97 ("[VFD] IoCreateDevice() %s\n",
98 GetStatusName(status)));
99 return status;
100 }
101
102 IoGetConfigurationInformation()->FloppyCount++;
103
104 VFDTRACE(VFDINFO | VFDDEV,
105 ("[VFD] Created a device object %ws\n", name_buffer));
106
107 //
108 // Initialize the device object / device extension
109 //
110
111 device_object->Flags |= DO_DIRECT_IO;
112
113 device_extension = (PDEVICE_EXTENSION)device_object->DeviceExtension;
114
115 RtlZeroMemory(device_extension, sizeof(DEVICE_EXTENSION));
116
117 // Store the back pointer to the device object
118
119 device_extension->DeviceObject = device_object;
120
121 // Store the logical device number
122
123 device_extension->DeviceNumber = driver_extension->NumberOfDevices;
124
125 // Store the device name
126
127 if (!VfdCopyUnicode(&(device_extension->DeviceName), &unicode_name)) {
128 VFDTRACE(VFDERR,
129 ("[VFD] Failed to allocate device name buffer\n"));
130 status = STATUS_INSUFFICIENT_RESOURCES;
131 goto cleanup;
132 }
133
134 // set the default disk geometry (3.5" 1.44M)
135
136 device_extension->Geometry = &geom_tbl[0];
137
138 // Create the interface link (\??\VirtualFD<n>)
139
140 #ifndef __REACTOS__
141 name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL;
142
143 _snwprintf(name_buffer, sizeof(name_buffer) - 1,
144 L"\\??\\" VFD_DEVICE_BASENAME L"%lu",
145 device_extension->DeviceNumber);
146 #else
147 name_buffer[ARRAYSIZE(name_buffer) - 1] = UNICODE_NULL;
148
149 _snwprintf(name_buffer, ARRAYSIZE(name_buffer) - 1,
150 L"\\??\\" VFD_DEVICE_BASENAME L"%lu",
151 device_extension->DeviceNumber);
152 #endif
153
154 RtlInitUnicodeString(&unicode_name, name_buffer);
155
156 status = IoCreateSymbolicLink(
157 &unicode_name, &device_extension->DeviceName);
158
159 if (!NT_SUCCESS(status)) {
160 VFDTRACE(VFDERR,
161 ("[VFD] IoCreateSymbolicLink(%ws) %s\n",
162 name_buffer, GetStatusName(status)));
163 goto cleanup;
164 }
165
166 VFDTRACE(VFDINFO|VFDDEV,
167 ("[VFD] Created a symbolic link %ws\n", name_buffer));
168
169 // Prepare the IRP queue list for the device thread
170
171 InitializeListHead(&device_extension->ListHead);
172
173 KeInitializeSpinLock(&device_extension->ListLock);
174
175 KeInitializeEvent(
176 &device_extension->RequestEvent,
177 SynchronizationEvent,
178 FALSE);
179
180 // Create the device thread
181
182 device_extension->TerminateThread = FALSE;
183
184 status = PsCreateSystemThread(
185 &thread_handle,
186 (ACCESS_MASK) 0L,
187 NULL,
188 NULL,
189 NULL,
190 VfdDeviceThread,
191 device_object);
192
193 if (!NT_SUCCESS(status)) {
194 VFDTRACE(VFDERR,
195 ("[VFD] PsCreateSystemThread() %s\n",
196 GetStatusName(status)));
197 goto cleanup;
198 }
199
200 // get a reference pointer to the thread
201
202 status = ObReferenceObjectByHandle(
203 thread_handle,
204 THREAD_ALL_ACCESS,
205 NULL,
206 KernelMode,
207 &device_extension->ThreadPointer,
208 NULL);
209
210 ZwClose(thread_handle);
211
212 if (!NT_SUCCESS(status)) {
213 VFDTRACE(VFDERR,
214 ("[VFD] ObReferenceObjectByHandle() %s\n",
215 GetStatusName(status)));
216 goto cleanup;
217 }
218
219 //
220 // Load the persistent drive letter from the registry
221 //
222 if (driver_extension->RegistryPath.Buffer) {
223 VfdLoadLink(device_extension,
224 driver_extension->RegistryPath.Buffer);
225 // error is not fatal here
226 }
227
228 // increment the number of devices in the driver extension
229
230 driver_extension->NumberOfDevices++;
231
232 if (DriverObject->DriverUnload) {
233 // not called from the DriverEntry routine
234 device_object->Flags &= ~DO_DEVICE_INITIALIZING;
235 }
236
237 #ifdef VFD_PNP
238 if (Parameter) {
239 // return the device object pointer
240 *(PDEVICE_OBJECT *)Parameter = device_object;
241 }
242 #else // VFD_PNP
243 device_extension->DriverExtension = driver_extension;
244 #endif // VFD_PNP
245
246 VFDTRACE(VFDINFO | VFDDEV, ("[VFD] VfdCreateDevice - OK\n"));
247
248 return STATUS_SUCCESS;
249
250 cleanup:
251 //
252 // Something went wrong at one point
253 // Delete all resources that might be created in this function
254 //
255 if (thread_handle) {
256
257 // terminate the device thread
258 device_extension->TerminateThread = TRUE;
259
260 KeSetEvent(
261 &device_extension->RequestEvent,
262 (KPRIORITY) 0,
263 FALSE);
264
265 if (device_extension->ThreadPointer) {
266 ObDereferenceObject(device_extension->ThreadPointer);
267 }
268 }
269
270 VFDTRACE(VFDINFO|VFDDEV,
271 ("[VFD] Deleting symbolic link %ws\n", name_buffer));
272
273 IoDeleteSymbolicLink(&unicode_name);
274
275 if (device_extension->DeviceName.Buffer) {
276 VFDTRACE(VFDINFO|VFDDEV, ("[VFD] Deleting device %ws\n",
277 device_extension->DeviceName.Buffer));
278
279 ExFreePool(device_extension->DeviceName.Buffer);
280 }
281
282 IoDeleteDevice(device_object);
283 IoGetConfigurationInformation()->FloppyCount--;
284
285 VFDTRACE(VFDINFO|VFDDEV,
286 ("[VFD] VfdCreateDevice - %s\n",
287 GetStatusName(status)));
288
289 return status;
290 }
291
292 //
293 // delete a VFD device object
294 //
295 VOID
296 VfdDeleteDevice(
297 IN PDEVICE_OBJECT DeviceObject)
298 {
299 PDEVICE_EXTENSION device_extension;
300 PVFD_DRIVER_EXTENSION driver_extension;
301 UNICODE_STRING unicode_name;
302 WCHAR name_buffer[40];
303
304 VFDTRACE(VFDINFO|VFDDEV, ("[VFD] VfdDeleteDevice - IN\n"));
305
306 device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
307
308 //
309 // decrement the number of device in the driver extension
310 //
311 #ifdef VFD_PNP
312 driver_extension = IoGetDriverObjectExtension(
313 DeviceObject->DriverObject, VFD_DRIVER_EXTENSION_ID);
314 #else // VFD_PNP
315 driver_extension = device_extension->DriverExtension;
316 #endif // VFD_PNP
317
318 if (driver_extension) {
319 driver_extension->NumberOfDevices--;
320 }
321
322 //
323 // cleanup the device object
324 //
325
326 // Terminate the device thread
327
328 device_extension->TerminateThread = TRUE;
329
330 KeSetEvent(
331 &device_extension->RequestEvent,
332 (KPRIORITY) 0,
333 FALSE);
334
335 KeWaitForSingleObject(
336 device_extension->ThreadPointer,
337 Executive,
338 KernelMode,
339 FALSE,
340 NULL);
341
342 ObDereferenceObject(
343 device_extension->ThreadPointer);
344
345 // Delete security context object
346
347 if (device_extension->SecurityContext) {
348 SeDeleteClientSecurity(device_extension->SecurityContext);
349 ExFreePool(device_extension->SecurityContext);
350 }
351
352 // Close the image file or free the image buffer
353
354 if (device_extension->FileHandle) {
355 ZwClose(device_extension->FileHandle);
356 }
357
358 if (device_extension->FileBuffer) {
359 ExFreePool(device_extension->FileBuffer);
360 }
361
362 // Release the image path buffer
363
364 if (device_extension->FileName.Buffer) {
365 ExFreePool(device_extension->FileName.Buffer);
366 }
367
368 // Remove the interface symbolic link
369
370 #ifndef __REACTOS__
371 name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL;
372
373 _snwprintf(name_buffer, sizeof(name_buffer) - 1,
374 L"\\??\\" VFD_DEVICE_BASENAME L"%lu",
375 device_extension->DeviceNumber);
376 #else
377 name_buffer[ARRAYSIZE(name_buffer) - 1] = UNICODE_NULL;
378
379 _snwprintf(name_buffer, ARRAYSIZE(name_buffer) - 1,
380 L"\\??\\" VFD_DEVICE_BASENAME L"%lu",
381 device_extension->DeviceNumber);
382 #endif
383
384 RtlInitUnicodeString(&unicode_name, name_buffer);
385
386 VFDTRACE(VFDINFO|VFDDEV,
387 ("[VFD] Deleting link %ws\n", name_buffer));
388
389 IoDeleteSymbolicLink(&unicode_name);
390
391 // Remove the persistent drive letter
392
393 if (device_extension->DriveLetter) {
394 #ifdef VFD_MOUNT_MANAGER
395 if (OsMajorVersion >= 5) {
396 // Request the mount manager to remove the drive letter.
397 // This will cause the mount manager to update its database
398 // and it won't arbitrarily assign the drive letter the next
399 // time the driver starts.
400 VfdMountMgrMountPoint(device_extension, 0);
401 }
402 else
403 #endif // VFD_MOUNT_MANAGER
404 {
405 // Windows NT style drive letter handling
406 // Simply remove the symbolic link
407 VfdSetLink(device_extension, 0);
408 }
409 }
410
411 // Release the device name buffer
412
413 if (device_extension->DeviceName.Buffer) {
414 VFDTRACE(VFDINFO|VFDDEV,
415 ("[VFD] Deleting device %ws\n",
416 device_extension->DeviceName.Buffer));
417
418 ExFreePool(device_extension->DeviceName.Buffer);
419 }
420
421 // Delete the device object
422
423 IoDeleteDevice(DeviceObject);
424 IoGetConfigurationInformation()->FloppyCount--;
425
426 VFDTRACE(VFDINFO|VFDDEV,
427 ("[VFD] VfdDeleteDevice - OUT\n"));
428
429 return;
430 }