ReactOS 0.4.15-dev-5672-gf73ac17
vfdioctl.c
Go to the documentation of this file.
1/*
2 vfdioctl.c
3
4 Virtual Floppy Drive for Windows NT platform
5 Kernel mode driver: I/O control request handling
6
7 Copyright (C) 2003-2005 Ken Kato
8*/
9
10#include "imports.h"
11#include "vfddrv.h"
12#include "vfddbg.h"
13
14/*
15#include <initguid.h>
16DEFINE_GUID(VFD_GUID, 0x4563b3d8L, 0x936a, 0x4692,
17 0xb6, 0x0c, 0x16, 0xd3, 0xb2, 0x57, 0xbb, 0xf2);
18*/
19
20#define IO_INPUTLEN(p) (p)->Parameters.DeviceIoControl.InputBufferLength
21#define IO_OUTPUTLEN(p) (p)->Parameters.DeviceIoControl.OutputBufferLength
22#define IO_CTRLCODE(p) (p)->Parameters.DeviceIoControl.IoControlCode
23
24//
25// IOCTL commands handler
26//
31 IN PIRP Irp)
32{
34 PIO_STACK_LOCATION io_stack;
36
39
40 Irp->IoStatus.Information = 0;
41
42 VFDTRACE(VFDINFO, ("[VFD] %-40s %ws\n",
43 GetIoControlName(IO_CTRLCODE(io_stack)),
44 device_extension->DeviceName.Buffer));
45
46#ifdef VFD_PNP
48
49 if (!NT_SUCCESS(status)) {
50 VFDTRACE(0,
51 ("Acquire RemoveLock failed %s\n", NtStatusToStr(status)));
52
53 Irp->IoStatus.Status = status;
55 return status;
56 }
57#endif // VFD_PNP
58
59/*
60 // Check if volume verification is required
61
62 if ((DeviceObject->Flags & DO_VERIFY_VOLUME) &&
63 !(io_stack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) {
64
65 VFDTRACE(VFDWARN,
66 ("[VFD] %-40s - %s\n",
67 GetIoControlName(IO_CTRLCODE(io_stack)),
68 GetStatusName(STATUS_VERIFY_REQUIRED)));
69
70 Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
71
72 IoCompleteRequest(Irp, IO_NO_INCREMENT);
73
74 return STATUS_VERIFY_REQUIRED;
75 }
76*/
77
78 switch (IO_CTRLCODE(io_stack)) {
80 // Open an image file or create an empty RAM disk.
81 // Only a few checks are done here.
82 // Actual operation is done in device thread
83
86 (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer,
87 IO_INPUTLEN(io_stack));
88
89 if (!NT_SUCCESS(status)) {
90 break;
91 }
92
93 // Pass the task to the device thread
95 break;
96
100 // Close the current image file or delete the RAM disk
101 // Only status check is done here.
102 // Actual operation is done in device thread.
103
104 if (!device_extension->FileHandle &&
105 !device_extension->FileBuffer) {
107 break;
108 }
109
110 // Pass the task to the device thread
112 break;
113
115 // Returns current image file information
116
119 (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer,
120 IO_OUTPUTLEN(io_stack),
121 &Irp->IoStatus.Information);
122
123 break;
124
126 // Create / remove a persistent drive letter
127 // and store it in the registry
128
129 if (IO_INPUTLEN(io_stack) < sizeof(CHAR)) {
131 break;
132 }
133
134#ifdef VFD_MOUNT_MANAGER
135 if (OsMajorVersion >= 5) {
136 // Windows 2000/XP
137 // Create a drive letter via the mount manager
138
139 status = VfdMountMgrMountPoint(device_extension,
140 *(PCHAR)Irp->AssociatedIrp.SystemBuffer);
141
142 // The new drive letter will be stored in the device extension
143 // and the registry when IOCTL_MOUNTDEV_LINK_CREATED or
144 // IOCTL_MOUNTDEV_LINK_DELETED is issued from the mount manager.
145 }
146 else
147#else // VFD_MOUNT_MANAGER
148 {
149 // Windows NT style drive letter assignment
150 // Simply create a symbolic link and store the new value
151
153 *(PCHAR)Irp->AssociatedIrp.SystemBuffer);
154
155 if (NT_SUCCESS(status)) {
156 // Store the new drive letter into the registry
158 }
159 }
160#endif // VFD_MOUNT_MANAGER
161 break;
162
164 // Return the current persistent drive letter
165
166 if (IO_OUTPUTLEN(io_stack) < sizeof(CHAR)) {
168 break;
169 }
170
171 *(PCHAR)Irp->AssociatedIrp.SystemBuffer =
172 device_extension->DriveLetter;
173
174 Irp->IoStatus.Information = sizeof(CHAR);
176 break;
177
179 // Set media protect flag
180
181 if (!device_extension->FileHandle &&
182 !device_extension->FileBuffer) {
184 break;
185 }
186
189 break;
190
192 // Clear media protect flag
193
194 if (!device_extension->FileHandle &&
195 !device_extension->FileBuffer) {
197 break;
198 }
199
200 device_extension->MediaFlags &= ~VFD_FLAG_WRITE_PROTECTED;
202 break;
203
205 // Reset the data modify flag
206
207 if (!device_extension->FileHandle &&
208 !device_extension->FileBuffer) {
210 break;
211 }
212
213 device_extension->MediaFlags &= ~VFD_FLAG_DATA_MODIFIED;
215 break;
216
218 // Return VFD device number (\??\VirtualFD<n>)
219
220 if (IO_OUTPUTLEN(io_stack) < sizeof(ULONG)) {
222 break;
223 }
224
225 *(PULONG)Irp->AssociatedIrp.SystemBuffer=
226 device_extension->DeviceNumber;
227
228 Irp->IoStatus.Information = sizeof(ULONG);
230 break;
231
233 // Return VFD device name (\Device\Floppy<n>)
234 // counted unicode string (not null terminated)
235
236 if (IO_OUTPUTLEN(io_stack) < sizeof(USHORT)) {
238 break;
239 }
240
241 {
242 PUSHORT p = (PUSHORT)Irp->AssociatedIrp.SystemBuffer;
243
244 *p = device_extension->DeviceName.Length;
245
246 if (IO_OUTPUTLEN(io_stack) < sizeof(USHORT) + *p) {
247
248 Irp->IoStatus.Information = sizeof(USHORT);
250 break;
251 }
252
253 RtlCopyMemory(p + 1, device_extension->DeviceName.Buffer, *p);
254
255 Irp->IoStatus.Information = sizeof(USHORT) + *p;
256 }
257
259 break;
260
262 // Return the VFD driver version
263
264 if (IO_OUTPUTLEN(io_stack) < sizeof(ULONG)) {
266 break;
267 }
268
269 *(PULONG)Irp->AssociatedIrp.SystemBuffer =
271
272 Irp->IoStatus.Information = sizeof(ULONG);
274 break;
275
276 //
277 // standard disk and storage I/O control requests
278 //
279
283
284 if (IO_OUTPUTLEN(io_stack) >= sizeof(ULONG)) {
285
286 *(PULONG)Irp->AssociatedIrp.SystemBuffer =
287 device_extension->MediaChangeCount;
288
289 Irp->IoStatus.Information = sizeof(ULONG);
290 }
291
293 break;
294
297 // Only parameter checks are performed here
298 // Actual operation is done by the device thread
299
302 (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer,
303 IO_INPUTLEN(io_stack),
304 IO_CTRLCODE(io_stack));
305
306 if (!NT_SUCCESS(status)) {
307 break;
308 }
309
310 // Pass the task to the device thread
312 break;
313
315 // Returns the geometry of current media
316
317 if (!device_extension->FileHandle &&
318 !device_extension->FileBuffer) {
320 break;
321 }
322 // fall through
323
326 // Return *the last mounted* disk geometry, although xxx_GET_MEDIA_TYPES
327 // commands are supposed to return all supported media types.
328 // This makes the matter much simpler...;-)
329 // If no image has been mounted yet, 1.44MB media is assumed.
330
331 if (IO_OUTPUTLEN(io_stack) < sizeof(DISK_GEOMETRY)) {
333 }
334
335 // Copy appropriate DISK_GEOMETRY into the output buffer
336
337 if (device_extension->Geometry) {
339 Irp->AssociatedIrp.SystemBuffer,
340 device_extension->Geometry,
341 sizeof(DISK_GEOMETRY));
342 }
343 else {
344 // default = 3.5" 1.44 MB media
346 Irp->AssociatedIrp.SystemBuffer,
348 sizeof(DISK_GEOMETRY));
349 }
350 Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
351
353 break;
354
356 // Return disk length information
357 // (Windows XP requires this request to be handled)
358
359 if (!device_extension->FileHandle &&
360 !device_extension->FileBuffer) {
362 break;
363 }
364
365 if (IO_OUTPUTLEN(io_stack) < sizeof(GET_LENGTH_INFORMATION)) {
367 break;
368 }
369
370 ((PGET_LENGTH_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->Length.QuadPart =
372
373 Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
374
376 break;
377
379 // Checks if current media is writable
380
381 if (!device_extension->FileHandle &&
382 !device_extension->FileBuffer) {
384 }
385 else if (device_extension->MediaFlags & VFD_FLAG_WRITE_PROTECTED) {
387 }
388 else {
390 }
391 break;
392
393/*
394 case IOCTL_DISK_MEDIA_REMOVAL:
395 case IOCTL_STORAGE_MEDIA_REMOVAL:
396 // Since removal lock is irrelevant for virtual disks,
397 // there's really nothing to do here...
398
399 status = STATUS_SUCCESS;
400 break;
401
402 case IOCTL_STORAGE_GET_HOTPLUG_INFO:
403 {
404 PSTORAGE_HOTPLUG_INFO hotplug;
405
406 if (IO_OUTPUTLEN(io_stack) < sizeof(STORAGE_HOTPLUG_INFO)) {
407 status = STATUS_BUFFER_TOO_SMALL;
408 break;
409 }
410
411 hotplug = (PSTORAGE_HOTPLUG_INFO)Irp->AssociatedIrp.SystemBuffer;
412
413 RtlZeroMemory(hotplug, sizeof(STORAGE_HOTPLUG_INFO));
414
415 hotplug->Size = sizeof(STORAGE_HOTPLUG_INFO);
416 hotplug->MediaRemovable = 1;
417
418 Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO);
419 status = STATUS_SUCCESS;
420 }
421 break;
422*/
423
424#ifdef VFD_MOUNT_MANAGER
425 //
426 // IO control requests received from the mount manager
427 // (on Windows 2000 / XP)
428 //
429
431 // Returns a unique ID for the target device
432 status = VfdMountDevUniqueId(
434 Irp->AssociatedIrp.SystemBuffer,
435 IO_OUTPUTLEN(io_stack),
436 &Irp->IoStatus);
437 break;
438
439// case IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY:
440
442 // Returns the device name of the target device
443 status = VfdMountDevDeviceName(
445 Irp->AssociatedIrp.SystemBuffer,
446 IO_OUTPUTLEN(io_stack),
447 &Irp->IoStatus);
448 break;
449
451 // Returns the drive letter link which we want the mount manager
452 // to create. This request is issued in response to the volume
453 // arrival notification, and the mount manager will create the
454 // symbolic link.
455 status = VfdMountDevSuggestedLink(
457 Irp->AssociatedIrp.SystemBuffer,
458 IO_OUTPUTLEN(io_stack),
459 &Irp->IoStatus);
460 break;
461
464 // Issued after the mount manager created/deleted a symbolic link
465 status = VfdMountDevLinkModified(
467 Irp->AssociatedIrp.SystemBuffer,
468 IO_INPUTLEN(io_stack),
469 IO_CTRLCODE(io_stack));
470 break;
471
472/*
473 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
474 {
475 PMOUNTDEV_STABLE_GUID guid;
476
477 if (IO_OUTPUTLEN(io_stack) < sizeof(MOUNTDEV_STABLE_GUID)) {
478 status = STATUS_INVALID_PARAMETER;
479 break;
480 }
481
482 guid = Irp->AssociatedIrp.SystemBuffer;
483
484 RtlCopyMemory(
485 &guid->StableGuid, &VFD_GUID, sizeof(GUID));
486
487 Irp->IoStatus.Information = sizeof(guid);
488 status = STATUS_SUCCESS;
489 }
490 break;
491*/
492#endif // VFD_MOUNT_MANAGER
493
494 default:
495 // Unknown IOCTL request
497 break;
498 }
499
500#if DBG
501 if ((NT_SUCCESS(status) && (TraceFlags & VFDINFO) == VFDINFO) ||
502 (TraceFlags & VFDWARN) == VFDWARN) {
503 VFDTRACE(0,("[VFD] %-40s - %s\n",
504 GetIoControlName(IO_CTRLCODE(io_stack)),
505 GetStatusName(status)));
506 }
507#endif
508
509 if (status == STATUS_PENDING) {
510 // Let the device thread perform the operation
511
513
515 &device_extension->ListHead,
516 &Irp->Tail.Overlay.ListEntry,
517 &device_extension->ListLock);
518
520 &device_extension->RequestEvent,
521 (KPRIORITY) 0,
522 FALSE);
523 }
524 else {
525 // complete the operation
526
527 Irp->IoStatus.Status = status;
529
530#ifdef VFD_PNP
532#endif // VFD_PNP
533 }
534
535 return status;
536}
537
538//
539// Handle IO control requests in the device thread
540//
541VOID
543 IN PDEVICE_EXTENSION DeviceExtension,
544 IN PIRP Irp,
546{
547 switch (ControlCode) {
549 // open the file from the caller's security context
550 // -- this allows this driver to open network files
551 if (DeviceExtension->SecurityContext) {
552 SeImpersonateClient(DeviceExtension->SecurityContext, NULL);
553 }
554
555 Irp->IoStatus.Status = VfdOpenImage(DeviceExtension,
556 (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer);
557
559 break;
560
564 VfdCloseImage(DeviceExtension);
565 Irp->IoStatus.Status = STATUS_SUCCESS;
566 break;
567
570 Irp->IoStatus.Status = VfdFormatTrack(DeviceExtension,
571 (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer);
572 break;
573
574 default:
575 // This shouldn't happen...
576 VFDTRACE(0,
577 ("[VFD] %s passed to the device thread\n",
578 GetIoControlName(ControlCode)));
579
580 Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
581 }
582
583#if DBG
584 if ((NT_SUCCESS(Irp->IoStatus.Status) && (TraceFlags & VFDINFO) == VFDINFO) ||
585 (TraceFlags & VFDWARN) == VFDWARN) {
586 VFDTRACE(0,("[VFD] %-40s - %s\n",
587 GetIoControlName(ControlCode),
588 GetStatusName(Irp->IoStatus.Status)));
589 }
590#endif
591}
LONG NTSTATUS
Definition: precomp.h:26
struct _device_extension device_extension
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define IOCTL_DISK_FORMAT_TRACKS_EX
Definition: cdrw_usr.h:173
#define IOCTL_DISK_EJECT_MEDIA
Definition: cdrw_usr.h:177
#define IOCTL_DISK_GET_MEDIA_TYPES
Definition: cdrw_usr.h:182
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
#define IOCTL_DISK_FORMAT_TRACKS
Definition: cdrw_usr.h:171
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
LONG KPRIORITY
Definition: compat.h:803
struct _BEEP_DEVICE_EXTENSION * PDEVICE_EXTENSION
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
GLfloat GLfloat p
Definition: glext.h:8902
PLIST_ENTRY NTAPI ExInterlockedInsertTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:140
IoMarkIrpPending(Irp)
if(dx< 0)
Definition: linetemp.h:194
#define PCHAR
Definition: match.c:90
struct _GET_LENGTH_INFORMATION * PGET_LENGTH_INFORMATION
#define IOCTL_MOUNTDEV_LINK_CREATED
Definition: imports.h:106
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
NTKERNELAPI VOID NTAPI PsRevertToSelf(VOID)
Definition: security.c:556
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
NTKERNELAPI VOID NTAPI SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext, IN PETHREAD ServerThread OPTIONAL)
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
#define IOCTL_MOUNTDEV_LINK_DELETED
Definition: imports.h:112
struct _DISK_GEOMETRY DISK_GEOMETRY
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define IOCTL_STORAGE_GET_MEDIA_TYPES
Definition: ntddstor.h:131
#define IOCTL_STORAGE_EJECT_MEDIA
Definition: ntddstor.h:107
#define IoCompleteRequest
Definition: irp.c:1240
#define STATUS_PENDING
Definition: ntstatus.h:82
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
Definition: ps.c:97
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_DRIVER_INTERNAL_ERROR
Definition: udferr_usr.h:177
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define VFDTRACE(LEVEL, STRING)
Definition: vfddbg.h:72
ULONG OsMajorVersion
NTSTATUS VfdFormatTrack(IN PDEVICE_EXTENSION DeviceExtension, IN PFORMAT_PARAMETERS FormatParams)
Definition: vfdfmt.c:153
NTSTATUS VfdFormatCheck(IN PDEVICE_EXTENSION DeviceExtension, IN PFORMAT_PARAMETERS FormatParams, IN ULONG InputLength, IN ULONG ControlCode)
NTSTATUS VfdQueryImage(IN PDEVICE_EXTENSION DeviceExtension, OUT PVFD_IMAGE_INFO ImageInfo, IN ULONG BufferLength, OUT PULONG ReturnLength)
Definition: vfdimg.c:466
VOID VfdCloseImage(IN PDEVICE_EXTENSION DeviceExtension)
Definition: vfdimg.c:435
const DISK_GEOMETRY geom_tbl[VFD_MEDIA_MAX]
NTSTATUS VfdStoreLink(IN PDEVICE_EXTENSION DeviceExtension)
Definition: vfdlink.c:190
NTSTATUS VfdSetLink(IN PDEVICE_EXTENSION DeviceExtension, IN CHAR DriveLetter)
Definition: vfdlink.c:24
NTSTATUS VfdOpenImage(IN PDEVICE_EXTENSION DeviceExtension, IN PVFD_IMAGE_INFO ImageInfo)
Definition: vfdimg.c:104
NTSTATUS VfdOpenCheck(IN PDEVICE_EXTENSION DeviceExtension, IN PVFD_IMAGE_INFO ImageInfo, IN ULONG InputLength)
#define IOCTL_VFD_RESET_MODIFY
Definition: vfdio.h:299
#define IOCTL_VFD_QUERY_IMAGE
Definition: vfdio.h:163
#define IOCTL_VFD_SET_LINK
Definition: vfdio.h:194
#define IOCTL_VFD_CLOSE_IMAGE
Definition: vfdio.h:133
#define IOCTL_VFD_SET_PROTECT
Definition: vfdio.h:247
#define IOCTL_VFD_QUERY_LINK
Definition: vfdio.h:221
#define IOCTL_VFD_QUERY_VERSION
Definition: vfdio.h:387
#define IOCTL_VFD_CLEAR_PROTECT
Definition: vfdio.h:273
#define IOCTL_VFD_QUERY_NAME
Definition: vfdio.h:358
#define IOCTL_VFD_QUERY_NUMBER
Definition: vfdio.h:325
#define VFD_SECTOR_TO_BYTE(s)
Definition: vfdio.h:45
#define IOCTL_VFD_OPEN_IMAGE
Definition: vfdio.h:107
NTSTATUS NTAPI VfdDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: vfdioctl.c:29
#define IO_INPUTLEN(p)
Definition: vfdioctl.c:20
VOID VfdIoCtlThread(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN ULONG ControlCode)
Definition: vfdioctl.c:542
#define IO_CTRLCODE(p)
Definition: vfdioctl.c:22
#define IO_OUTPUTLEN(p)
Definition: vfdioctl.c:21
@ VFD_MEDIA_F3_1P4
Definition: vfdtypes.h:39
#define VFD_FLAG_WRITE_PROTECTED
Definition: vfdtypes.h:68
#define VFD_DRIVER_MINOR
Definition: vfdver.h:21
#define VFD_DEBUG_FLAG
Definition: vfdver.h:40
#define VFD_DRIVER_MAJOR
Definition: vfdver.h:20
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
#define IoAcquireRemoveLock(RemoveLock, Tag)
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define IoReleaseRemoveLock(_RemoveLock, _Tag)
Definition: iofuncs.h:2764
#define IO_NO_INCREMENT
Definition: iotypes.h:598
char CHAR
Definition: xmlstorage.h:175