ReactOS 0.4.16-dev-117-g38f21f9
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,
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
250cleanup:
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
261 &device_extension->RequestEvent,
262 (KPRIORITY) 0,
263 FALSE);
264
265 if (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//
295VOID
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
331 &device_extension->RequestEvent,
332 (KPRIORITY) 0,
333 FALSE);
334
336 device_extension->ThreadPointer,
337 Executive,
339 FALSE,
340 NULL);
341
343 device_extension->ThreadPointer);
344
345 // Delete security context object
346
347 if (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}
LONG NTSTATUS
Definition: precomp.h:26
struct _device_extension device_extension
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
LONG KPRIORITY
Definition: compat.h:803
static void cleanup(void)
Definition: main.c:1335
struct _BEEP_DEVICE_EXTENSION * PDEVICE_EXTENSION
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
#define SeDeleteClientSecurity(C)
Definition: imports.h:320
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
ULONG ACCESS_MASK
Definition: nt_native.h:40
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNICODE_NULL
@ SynchronizationEvent
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
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1904
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
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
#define L(x)
Definition: ntvdm.h:50
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:494
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
#define STATUS_SUCCESS
Definition: shellext.h:65
PVOID DeviceExtension
Definition: env_spec_w32.h:418
UNICODE_STRING RegistryPath
Definition: vfddrv.h:64
ULONG NumberOfDevices
Definition: vfddrv.h:65
Definition: ps.c:97
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_DRIVER_INTERNAL_ERROR
Definition: udferr_usr.h:177
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define VFDTRACE(LEVEL, STRING)
Definition: vfddbg.h:72
VOID VfdDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: vfddev.c:296
NTSTATUS VfdCreateDevice(IN PDRIVER_OBJECT DriverObject, OUT PVOID Parameter)
Definition: vfddev.c:23
VOID NTAPI VfdDeviceThread(IN PVOID ThreadContext)
Definition: vfddrv.c:404
PWSTR VfdCopyUnicode(PUNICODE_STRING dst, PUNICODE_STRING src)
Definition: vfddrv.c:489
ULONG OsMajorVersion
struct _VFD_DRIVER_EXTENSION * PVFD_DRIVER_EXTENSION
NTSTATUS VfdLoadLink(IN PDEVICE_EXTENSION DeviceExtension, IN PWSTR RegistryPath)
Definition: vfdlink.c:135
const DISK_GEOMETRY geom_tbl[VFD_MEDIA_MAX]
NTSTATUS VfdSetLink(IN PDEVICE_EXTENSION DeviceExtension, IN CHAR DriveLetter)
Definition: vfdlink.c:24
#define VFD_DEVICE_BASENAME
Definition: vfdio.h:35
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
@ Executive
Definition: ketypes.h:415
#define ObDereferenceObject
Definition: obfuncs.h:203
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336
__wchar_t WCHAR
Definition: xmlstorage.h:180