ReactOS  0.4.14-dev-49-gfb4591c
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 
79  TRACE_(FLOPPY, "DeviceIoctl called\n");
80  Irp->IoStatus.Status = STATUS_SUCCESS;
81  Irp->IoStatus.Information = 0;
82 
83  /*
84  * First the non-change-sensitive ioctls
85  */
87  {
88  PDISK_GEOMETRY Geometry = OutputBuffer;
89  INFO_(FLOPPY, "IOCTL_DISK_GET_MEDIA_TYPES Called\n");
90 
91  if(OutputLength < sizeof(DISK_GEOMETRY))
92  {
93  INFO_(FLOPPY, "IOCTL_DISK_GET_MEDIA_TYPES: insufficient buffer; returning STATUS_INVALID_PARAMETER\n");
94  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
96  return;
97  }
98 
99  /*
100  * for now, this driver only supports 3.5" HD media
101  */
102  Geometry->MediaType = F3_1Pt44_512;
103  Geometry->Cylinders.QuadPart = 80;
104  Geometry->TracksPerCylinder = 2 * 18;
105  Geometry->SectorsPerTrack = 18;
106  Geometry->BytesPerSector = 512;
107 
108  Irp->IoStatus.Status = STATUS_SUCCESS;
109  Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
110  INFO_(FLOPPY, "Ioctl: completing with STATUS_SUCCESS\n");
112 
113  return;
114  }
115 
116  /*
117  * Now, check to see if the volume needs to be verified. If so,
118  * return STATUS_VERIFY_REQUIRED.
119  *
120  * NOTE: This code, which is outside of the switch and if/else blocks,
121  * will implicity catch and correctly service IOCTL_DISK_CHECK_VERIFY.
122  * Therefore if we see one below in the switch, we can return STATUS_SUCCESS
123  * immediately.
124  */
125  if(DriveInfo->DeviceObject->Flags & DO_VERIFY_VOLUME && !(Stack->Flags & SL_OVERRIDE_VERIFY_VOLUME))
126  {
127  INFO_(FLOPPY, "DeviceIoctl(): completing with STATUS_VERIFY_REQUIRED\n");
128  Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
129  Irp->IoStatus.Information = 0;
131  return;
132  }
133 
134  /*
135  * Start the drive to see if the disk has changed
136  */
137  StartMotor(DriveInfo);
138 
139  /*
140  * Check the change line, and if it's set, return
141  */
142  if(HwDiskChanged(DriveInfo, &DiskChanged) != STATUS_SUCCESS)
143  {
144  WARN_(FLOPPY, "DeviceIoctl(): unable to sense disk change; completing with STATUS_UNSUCCESSFUL\n");
145  Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
146  Irp->IoStatus.Information = 0;
148  StopMotor(DriveInfo->ControllerInfo);
149  return;
150  }
151 
152  if(DiskChanged)
153  {
154  INFO_(FLOPPY, "DeviceIoctl(): detected disk changed; signalling media change and completing\n");
155  SignalMediaChanged(DriveInfo->DeviceObject, Irp);
156 
157  /*
158  * Just guessing here - I have a choice of returning NO_MEDIA or VERIFY_REQUIRED. If there's
159  * really no disk in the drive, I'm thinking I can save time by just reporting that fact, rather
160  * than forcing windows to ask me twice. If this doesn't work, we'll need to split this up and
161  * handle the CHECK_VERIFY IOCTL separately.
162  */
164  Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
165 
167  StopMotor(DriveInfo->ControllerInfo);
168  return;
169  }
170 
171  switch(Code)
172  {
174  {
175  UCHAR Status;
176 
177  INFO_(FLOPPY, "IOCTL_DISK_IS_WRITABLE Called\n");
178 
179  /* This IRP always has 0 information */
180  Irp->IoStatus.Information = 0;
181 
182  if(HwSenseDriveStatus(DriveInfo) != STATUS_SUCCESS)
183  {
184  WARN_(FLOPPY, "IoctlDiskIsWritable(): unable to sense drive status\n");
185  Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
186  break;
187  }
188 
189  /* Now, read the drive's status back */
191  {
192  WARN_(FLOPPY, "IoctlDiskIsWritable(): unable to read drive status result\n");
193  Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
194  break;
195  }
196 
197  /* Check to see if the write flag is set. */
199  {
200  INFO_(FLOPPY, "IOCTL_DISK_IS_WRITABLE: disk is write protected\n");
201  Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;
202  }
203  else
204  Irp->IoStatus.Status = STATUS_SUCCESS;
205  }
206  break;
207 
209  INFO_(FLOPPY, "IOCTL_DISK_CHECK_VERIFY called\n");
210  if (OutputLength != 0)
211  {
212  if (OutputLength < sizeof(ULONG))
213  {
214  Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
215  Irp->IoStatus.Information = 0;
216  }
217  else
218  {
219  *((PULONG)OutputBuffer) = DriveInfo->DiskChangeCount;
220  Irp->IoStatus.Status = STATUS_SUCCESS;
221  Irp->IoStatus.Information = sizeof(ULONG);
222  }
223  }
224  else
225  {
226  Irp->IoStatus.Status = STATUS_SUCCESS;
227  Irp->IoStatus.Information = 0;
228  }
229  break;
230 
232  {
233  INFO_(FLOPPY, "IOCTL_DISK_GET_DRIVE_GEOMETRY Called\n");
234  if(OutputLength < sizeof(DISK_GEOMETRY))
235  {
236  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
237  break;
238  }
239 
240  /* This still works right even if DriveInfo->DiskGeometry->MediaType = Unknown */
241  memcpy(OutputBuffer, &DriveInfo->DiskGeometry, sizeof(DISK_GEOMETRY));
242  Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
243  break;
244  }
245 
248  ERR_(FLOPPY, "Format called; not supported yet\n");
249  Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
250  Irp->IoStatus.Information = 0;
251  break;
252 
254  INFO_(FLOPPY, "IOCTL_DISK_GET_PARTITION_INFO Called; not supported by a floppy driver\n");
255  Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
256  Irp->IoStatus.Information = 0;
257  break;
258 
260  if (OutputLength < sizeof(MOUNTDEV_NAME)) {
261  Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
262  Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
263  break;
264  }
265 
266  Name = Irp->AssociatedIrp.SystemBuffer;
267  Name->NameLength = wcslen(&DriveInfo->SymLinkBuffer[0]) * sizeof(WCHAR);
268 
269  if (OutputLength < sizeof(USHORT) + Name->NameLength) {
270  Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
271  Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
272  break;
273  }
274 
275  RtlCopyMemory(Name->Name, &DriveInfo->SymLinkBuffer[0],
276  Name->NameLength);
277 
278  Irp->IoStatus.Status = STATUS_SUCCESS;
279  Irp->IoStatus.Information = sizeof(USHORT) + Name->NameLength;
280  break;
281 
282  default:
283  ERR_(FLOPPY, "UNKNOWN IOCTL CODE: 0x%x\n", Code);
284  Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
285  Irp->IoStatus.Information = 0;
286  break;
287  }
288 
289  INFO_(FLOPPY, "ioctl: completing with status 0x%x\n", Irp->IoStatus.Status);
291 
292  StopMotor(DriveInfo->ControllerInfo);
293  return;
294 }
WCHAR SymLinkBuffer[MAX_DEVICE_NAME]
Definition: floppy.h:51
ULONG DiskChangeCount
Definition: floppy.h:53
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define INFO_(ch,...)
Definition: debug.h:159
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
_In_ PIRP Irp
Definition: csq.h:116
#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
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
NTSTATUS NTAPI HwDiskChanged(PDRIVE_INFO DriveInfo, PBOOLEAN DiskChanged)
Definition: hardware.c:785
VOID NTAPI StopMotor(PCONTROLLER_INFO ControllerInfo)
Definition: floppy.c:135
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, PIRP Irp)
Definition: ioctl.c:64
ULONG BytesPerSector
Definition: ntdddisk.h:376
ULONG TracksPerCylinder
Definition: ntdddisk.h:374
#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:64
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
PDEVICE_OBJECT DeviceObject
Definition: fdc.h:26
#define SR3_WRITE_PROTECT_STATUS_SIGNAL
Definition: hardware.h:161
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
#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
struct NameRec_ * Name
Definition: cdprocs.h:464
struct _MOUNTDEV_NAME MOUNTDEV_NAME
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1780
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
NTSTATUS NTAPI HwSenseDriveStatusResult(PCONTROLLER_INFO ControllerInfo, PUCHAR Status)
Definition: hardware.c:836
#define IOCTL_DISK_GET_MEDIA_TYPES
Definition: cdrw_usr.h:182
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
#define Code
Definition: deflate.h:80
#define TRACE_(x)
Definition: compat.h:66
NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo)
Definition: floppy.c:291
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define STATUS_PENDING
Definition: ntstatus.h:82
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:372
ULONG SectorsPerTrack
Definition: ntdddisk.h:375
MEDIA_TYPE MediaType
Definition: ntdddisk.h:373
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:88
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
DISK_GEOMETRY DiskGeometry
Definition: floppy.h:49
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
struct _DISK_GEOMETRY DISK_GEOMETRY
NTSTATUS NTAPI DeviceIoctl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: ioctl.c:39
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
unsigned short USHORT
Definition: pedump.c:61
unsigned int * PULONG
Definition: retypes.h:1
#define IOCTL_DISK_FORMAT_TRACKS_EX
Definition: cdrw_usr.h:173
IO_CSQ Csq
Definition: csqrtns.c:46
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
NTSTATUS NTAPI HwSenseDriveStatus(PDRIVE_INFO DriveInfo)
Definition: hardware.c:287
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define WARN_(ch,...)
Definition: debug.h:157
VOID NTAPI SignalMediaChanged(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: floppy.c:1010
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
VOID NTAPI StartMotor(PDRIVE_INFO DriveInfo)
Definition: floppy.c:96
LONGLONG QuadPart
Definition: typedefs.h:112