ReactOS  0.4.15-dev-5452-g3c95c95
ioctl.c
Go to the documentation of this file.
1 /*
2  * ReactOS Floppy Driver
3  * Copyright (C) 2004, Vizzini (vizzini@plasmic.com)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * PROJECT: ReactOS Floppy Driver
20  * FILE: ioctl.c
21  * PURPOSE: IOCTL Routines
22  * PROGRAMMER: Vizzini (vizzini@plasmic.com)
23  * REVISIONS:
24  * 15-Feb-2004 vizzini - Created
25  * NOTES:
26  * - All IOCTL documentation taken from the DDK
27  * - This driver tries to support all of the IOCTLs that the DDK floppy
28  * sample does
29  *
30  * TODO: Add support to GET_MEDIA_TYPES for non-1.44 disks
31  * TODO: Implement format
32  */
33 
34 #include "precomp.h"
35 
36 #include <debug.h>
37 
40 /*
41  * FUNCTION: Queue IOCTL IRPs
42  * ARGUMENTS:
43  * DeviceObject: DeviceObject that is the target of the IRP
44  * Irp: IRP to process
45  * RETURNS:
46  * STATUS_SUCCESS in all cases, so far
47  * NOTES:
48  * - We can't just service these immediately because, even though some
49  * are able to run at DISPATCH, they'll get out of sync with other
50  * read/write or ioctl irps.
51  */
52 {
54  ASSERT(Irp);
55 
56  Irp->Tail.Overlay.DriverContext[0] = DeviceObject;
58 
59  return STATUS_PENDING;
60 }
61 
62 
63 VOID NTAPI
65 /*
66  * FUNCTION: Handles IOCTL requests at PASSIVE_LEVEL
67  * ARGUMENTS:
68  * DriveInfo: Drive that the IOCTL is directed at
69  * Irp: IRP with the request in it
70  */
71 {
73  ULONG OutputLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
74  PVOID OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
75  ULONG Code = Stack->Parameters.DeviceIoControl.IoControlCode;
76  BOOLEAN DiskChanged;
78  PMOUNTDEV_UNIQUE_ID UniqueId;
79 
80  TRACE_(FLOPPY, "DeviceIoctl called\n");
81  Irp->IoStatus.Status = STATUS_SUCCESS;
82  Irp->IoStatus.Information = 0;
83 
84  /*
85  * First the non-change-sensitive ioctls
86  */
88  {
89  PDISK_GEOMETRY Geometry = OutputBuffer;
90  INFO_(FLOPPY, "IOCTL_DISK_GET_MEDIA_TYPES Called\n");
91 
92  if(OutputLength < sizeof(DISK_GEOMETRY))
93  {
94  INFO_(FLOPPY, "IOCTL_DISK_GET_MEDIA_TYPES: insufficient buffer; returning STATUS_INVALID_PARAMETER\n");
95  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
97  return;
98  }
99 
100  /*
101  * for now, this driver only supports 3.5" HD media
102  */
103  Geometry->MediaType = F3_1Pt44_512;
104  Geometry->Cylinders.QuadPart = 80;
105  Geometry->TracksPerCylinder = 2 * 18;
106  Geometry->SectorsPerTrack = 18;
107  Geometry->BytesPerSector = 512;
108 
109  Irp->IoStatus.Status = STATUS_SUCCESS;
110  Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
111  INFO_(FLOPPY, "Ioctl: completing with STATUS_SUCCESS\n");
113 
114  return;
115  }
116 
117  /*
118  * Now, check to see if the volume needs to be verified. If so,
119  * return STATUS_VERIFY_REQUIRED.
120  *
121  * NOTE: This code, which is outside of the switch and if/else blocks,
122  * will implicity catch and correctly service IOCTL_DISK_CHECK_VERIFY.
123  * Therefore if we see one below in the switch, we can return STATUS_SUCCESS
124  * immediately.
125  */
126  if(DriveInfo->DeviceObject->Flags & DO_VERIFY_VOLUME && !(Stack->Flags & SL_OVERRIDE_VERIFY_VOLUME))
127  {
128  INFO_(FLOPPY, "DeviceIoctl(): completing with STATUS_VERIFY_REQUIRED\n");
129  Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
130  Irp->IoStatus.Information = 0;
132  return;
133  }
134 
135  /*
136  * Start the drive to see if the disk has changed
137  */
138  StartMotor(DriveInfo);
139 
140  /*
141  * Check the change line, and if it's set, return
142  */
143  if(HwDiskChanged(DriveInfo, &DiskChanged) != STATUS_SUCCESS)
144  {
145  WARN_(FLOPPY, "DeviceIoctl(): unable to sense disk change; completing with STATUS_UNSUCCESSFUL\n");
146  Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
147  Irp->IoStatus.Information = 0;
149  StopMotor(DriveInfo->ControllerInfo);
150  return;
151  }
152 
153  if(DiskChanged)
154  {
155  INFO_(FLOPPY, "DeviceIoctl(): detected disk changed; signalling media change and completing\n");
156 
157  /* The following call sets IoStatus.Status and IoStatus.Information */
158  SignalMediaChanged(DriveInfo->DeviceObject, Irp);
159  ResetChangeFlag(DriveInfo);
160 
162  StopMotor(DriveInfo->ControllerInfo);
163  return;
164  }
165 
166  switch(Code)
167  {
169  {
170  UCHAR Status;
171 
172  INFO_(FLOPPY, "IOCTL_DISK_IS_WRITABLE Called\n");
173 
174  /* This IRP always has 0 information */
175  Irp->IoStatus.Information = 0;
176 
177  if(HwSenseDriveStatus(DriveInfo) != STATUS_SUCCESS)
178  {
179  WARN_(FLOPPY, "IoctlDiskIsWritable(): unable to sense drive status\n");
180  Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
181  break;
182  }
183 
184  /* Now, read the drive's status back */
186  {
187  WARN_(FLOPPY, "IoctlDiskIsWritable(): unable to read drive status result\n");
188  Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
189  break;
190  }
191 
192  /* Check to see if the write flag is set. */
194  {
195  INFO_(FLOPPY, "IOCTL_DISK_IS_WRITABLE: disk is write protected\n");
196  Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;
197  }
198  else
199  Irp->IoStatus.Status = STATUS_SUCCESS;
200  }
201  break;
202 
204  INFO_(FLOPPY, "IOCTL_DISK_CHECK_VERIFY called\n");
205  if (OutputLength != 0)
206  {
207  if (OutputLength < sizeof(ULONG))
208  {
209  Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
210  Irp->IoStatus.Information = 0;
211  }
212  else
213  {
214  *((PULONG)OutputBuffer) = DriveInfo->DiskChangeCount;
215  Irp->IoStatus.Status = STATUS_SUCCESS;
216  Irp->IoStatus.Information = sizeof(ULONG);
217  }
218  }
219  else
220  {
221  Irp->IoStatus.Status = STATUS_SUCCESS;
222  Irp->IoStatus.Information = 0;
223  }
224  break;
225 
227  {
228  INFO_(FLOPPY, "IOCTL_DISK_GET_DRIVE_GEOMETRY Called\n");
229  if(OutputLength < sizeof(DISK_GEOMETRY))
230  {
231  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
232  break;
233  }
234 
235  /* This still works right even if DriveInfo->DiskGeometry->MediaType = Unknown */
236  memcpy(OutputBuffer, &DriveInfo->DiskGeometry, sizeof(DISK_GEOMETRY));
237  Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
238  break;
239  }
240 
243  ERR_(FLOPPY, "Format called; not supported yet\n");
244  Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
245  Irp->IoStatus.Information = 0;
246  break;
247 
249  INFO_(FLOPPY, "IOCTL_DISK_GET_PARTITION_INFO Called; not supported by a floppy driver\n");
250  Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
251  Irp->IoStatus.Information = 0;
252  break;
253 
255  if(OutputLength < sizeof(MOUNTDEV_UNIQUE_ID))
256  {
257  Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
258  Irp->IoStatus.Information = 0;
259  break;
260  }
261 
262  UniqueId = Irp->AssociatedIrp.SystemBuffer;
263  UniqueId->UniqueIdLength = (USHORT)wcslen(&DriveInfo->DeviceNameBuffer[0]) * sizeof(WCHAR);
264 
265  if(OutputLength < FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + UniqueId->UniqueIdLength)
266  {
267  Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
268  Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
269  break;
270  }
271 
272  RtlCopyMemory(UniqueId->UniqueId, &DriveInfo->DeviceNameBuffer[0],
273  UniqueId->UniqueIdLength);
274 
275  Irp->IoStatus.Status = STATUS_SUCCESS;
276  Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + UniqueId->UniqueIdLength;
277  break;
278 
280  if(OutputLength < sizeof(MOUNTDEV_NAME))
281  {
282  Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
283  Irp->IoStatus.Information = 0;
284  break;
285  }
286 
287  Name = Irp->AssociatedIrp.SystemBuffer;
288  Name->NameLength = (USHORT)wcslen(&DriveInfo->DeviceNameBuffer[0]) * sizeof(WCHAR);
289 
290  if(OutputLength < FIELD_OFFSET(MOUNTDEV_NAME, Name) + Name->NameLength)
291  {
292  Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
293  Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
294  break;
295  }
296 
297  RtlCopyMemory(Name->Name, &DriveInfo->DeviceNameBuffer[0],
298  Name->NameLength);
299 
300  Irp->IoStatus.Status = STATUS_SUCCESS;
301  Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_NAME, Name) + Name->NameLength;
302  break;
303 
304  default:
305  ERR_(FLOPPY, "UNKNOWN IOCTL CODE: 0x%x\n", Code);
306  Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
307  Irp->IoStatus.Information = 0;
308  break;
309  }
310 
311  INFO_(FLOPPY, "ioctl: completing with status 0x%x\n", Irp->IoStatus.Status);
313 
314  StopMotor(DriveInfo->ControllerInfo);
315  return;
316 }
return STATUS_NOT_SUPPORTED
ULONG DiskChangeCount
Definition: floppy.h:53
VOID NTAPI StopMotor(PCONTROLLER_INFO ControllerInfo)
Definition: floppy.c:135
#define INFO_(ch,...)
Definition: debug.h:159
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTKERNELAPI VOID NTAPI IoCsqInsertIrp(_Inout_ PIO_CSQ Csq, _Inout_ PIRP Irp, _Out_opt_ PIO_CSQ_IRP_CONTEXT Context)
Insert an IRP into the CSQ.
Definition: csq.c:177
#define ERR_(ch,...)
Definition: debug.h:156
LONG NTSTATUS
Definition: precomp.h:26
USHORT UniqueIdLength
Definition: imports.h:138
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
ULONG BytesPerSector
Definition: ntdddisk.h:409
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
struct _CONTROLLER_INFO * ControllerInfo
Definition: fdc.h:23
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
PDEVICE_OBJECT DeviceObject
Definition: fdc.h:26
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
return STATUS_NOT_IMPLEMENTED
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
#define IOCTL_DISK_FORMAT_TRACKS
Definition: cdrw_usr.h:171
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, PIRP Irp)
Definition: ioctl.c:64
#define SR3_WRITE_PROTECT_STATUS_SIGNAL
Definition: hardware.h:161
_In_ PIRP Irp
Definition: csq.h:116
struct NameRec_ * Name
Definition: cdprocs.h:459
struct _MOUNTDEV_NAME MOUNTDEV_NAME
unsigned char BOOLEAN
#define IoCompleteRequest
Definition: irp.c:1240
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define IOCTL_DISK_GET_MEDIA_TYPES
Definition: cdrw_usr.h:182
NTSTATUS NTAPI HwSenseDriveStatus(PDRIVE_INFO DriveInfo)
Definition: hardware.c:287
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:859
Status
Definition: gdiplustypes.h:24
#define TRACE_(x)
Definition: compat.h:76
struct _MOUNTDEV_UNIQUE_ID MOUNTDEV_UNIQUE_ID
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define STATUS_PENDING
Definition: ntstatus.h:82
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:405
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1697
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
DISK_GEOMETRY DiskGeometry
Definition: floppy.h:49
NTSTATUS NTAPI HwDiskChanged(PDRIVE_INFO DriveInfo, PBOOLEAN DiskChanged)
Definition: hardware.c:785
NTSTATUS NTAPI DeviceIoctl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: ioctl.c:39
NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo)
Definition: floppy.c:291
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
struct _DISK_GEOMETRY DISK_GEOMETRY
VOID NTAPI StartMotor(PDRIVE_INFO DriveInfo)
Definition: floppy.c:96
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
unsigned short USHORT
Definition: pedump.c:61
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define IOCTL_DISK_FORMAT_TRACKS_EX
Definition: cdrw_usr.h:173
VOID NTAPI SignalMediaChanged(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: floppy.c:1090
IO_CSQ Csq
Definition: csqrtns.c:46
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
NTSTATUS NTAPI HwSenseDriveStatusResult(PCONTROLLER_INFO ControllerInfo, PUCHAR Status)
Definition: hardware.c:836
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#define WARN_(ch,...)
Definition: debug.h:157
UCHAR UniqueId[1]
Definition: imports.h:139
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
LONGLONG QuadPart
Definition: typedefs.h:114
WCHAR DeviceNameBuffer[MAX_DEVICE_NAME]
Definition: floppy.h:52