ReactOS  0.4.14-dev-49-gfb4591c
vfddev.c
Go to the documentation of this file.
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 //
26 {
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;
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"));
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 
81  sizeof(DEVICE_EXTENSION),
82  &unicode_name,
85  FALSE,
86  &device_object);
87 
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 
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 
114 
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"));
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 
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 
172 
174 
176  &device_extension->RequestEvent,
178  FALSE);
179 
180  // Create the device thread
181 
182  device_extension->TerminateThread = FALSE;
183 
185  &thread_handle,
186  (ACCESS_MASK) 0L,
187  NULL,
188  NULL,
189  NULL,
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 
203  thread_handle,
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) {
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);
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
298 {
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 
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 
336  device_extension->ThreadPointer,
337  Executive,
338  KernelMode,
339  FALSE,
340  NULL);
341 
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
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 
425 
426  VFDTRACE(VFDINFO|VFDDEV,
427  ("[VFD] VfdDeleteDevice - OUT\n"));
428 
429  return;
430 }
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
ULONG OsMajorVersion
#define IN
Definition: typedefs.h:38
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
VOID NTAPI VfdDeviceThread(IN PVOID ThreadContext)
Definition: vfddrv.c:404
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define TRUE
Definition: types.h:120
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Definition: iorsrce.c:830
NTSTATUS VfdLoadLink(IN PDEVICE_EXTENSION DeviceExtension, IN PWSTR RegistryPath)
Definition: vfdlink.c:135
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
struct _device_extension device_extension
VOID VfdDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: vfddev.c:296
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
LONG NTSTATUS
Definition: precomp.h:26
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
_In_ PVOID Parameter
Definition: ldrtypes.h:241
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
ULONG NumberOfDevices
Definition: vfddrv.h:65
LONG KPRIORITY
Definition: compat.h:454
NTSTATUS VfdCreateDevice(IN PDRIVER_OBJECT DriverObject, OUT PVOID Parameter)
Definition: vfddev.c:23
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
#define UNICODE_NULL
#define SeDeleteClientSecurity(C)
Definition: imports.h:320
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
PVOID DeviceExtension
Definition: env_spec_w32.h:418
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
smooth NULL
Definition: ftsmooth.c:416
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
PWSTR VfdCopyUnicode(PUNICODE_STRING dst, PUNICODE_STRING src)
Definition: vfddrv.c:489
#define VFDTRACE(LEVEL, STRING)
Definition: vfddbg.h:72
#define STATUS_DRIVER_INTERNAL_ERROR
Definition: udferr_usr.h:177
static const WCHAR L[]
Definition: oid.c:1250
NTSTATUS VfdSetLink(IN PDEVICE_EXTENSION DeviceExtension, IN CHAR DriveLetter)
Definition: vfdlink.c:24
PDRIVER_UNLOAD DriverUnload
Definition: iotypes.h:2180
const DISK_GEOMETRY geom_tbl[VFD_MEDIA_MAX]
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1842
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
UNICODE_STRING RegistryPath
Definition: vfddrv.h:64
#define OUT
Definition: typedefs.h:39
struct _VFD_DRIVER_EXTENSION * PVFD_DRIVER_EXTENSION
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
char * cleanup(char *str)
Definition: wpickclick.c:99
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
return STATUS_SUCCESS
Definition: btrfs.c:2966
static SERVICE_STATUS status
Definition: service.c:31
struct _BEEP_DEVICE_EXTENSION * PDEVICE_EXTENSION
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define VFD_DEVICE_BASENAME
Definition: vfdio.h:35
Definition: ps.c:97