ReactOS 0.4.16-dev-197-g92996da
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
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 {
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 */
159 ResetChangeFlag(DriveInfo);
160
162 StopMotor(DriveInfo->ControllerInfo);
163 return;
164 }
165
166 switch(Code)
167 {
169 {
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}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
struct NameRec_ * Name
Definition: cdprocs.h:460
LONG NTSTATUS
Definition: precomp.h:26
#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_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
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
IO_CSQ Csq
Definition: csqrtns.c:46
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define NULL
Definition: types.h:112
#define TRACE_(x)
Definition: compat.h:76
NTSTATUS NTAPI HwSenseDriveStatusResult(PCONTROLLER_INFO ControllerInfo, PUCHAR Status)
Definition: hardware.c:836
NTSTATUS NTAPI HwDiskChanged(PDRIVE_INFO DriveInfo, PBOOLEAN DiskChanged)
Definition: hardware.c:785
NTSTATUS NTAPI HwSenseDriveStatus(PDRIVE_INFO DriveInfo)
Definition: hardware.c:287
#define SR3_WRITE_PROTECT_STATUS_SIGNAL
Definition: hardware.h:161
VOID NTAPI DeviceIoctlPassive(PDRIVE_INFO DriveInfo, PIRP Irp)
Definition: ioctl.c:64
DRIVER_DISPATCH DeviceIoctl
Definition: ioctl.h:29
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
NTSTATUS NTAPI ResetChangeFlag(PDRIVE_INFO DriveInfo)
Definition: floppy.c:291
VOID NTAPI SignalMediaChanged(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: floppy.c:1097
VOID NTAPI StartMotor(PDRIVE_INFO DriveInfo)
Definition: floppy.c:96
VOID NTAPI StopMotor(PCONTROLLER_INFO ControllerInfo)
Definition: floppy.c:135
Status
Definition: gdiplustypes.h:25
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
struct _MOUNTDEV_NAME MOUNTDEV_NAME
struct _MOUNTDEV_UNIQUE_ID MOUNTDEV_UNIQUE_ID
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:91
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:78
struct _DISK_GEOMETRY DISK_GEOMETRY
@ F3_1Pt44_512
Definition: ntdddisk.h:373
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
#define IoCompleteRequest
Definition: irp.c:1240
unsigned short USHORT
Definition: pedump.c:61
#define INFO_(ch,...)
Definition: debug.h:159
#define ERR_(ch,...)
Definition: debug.h:156
#define WARN_(ch,...)
Definition: debug.h:157
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
MEDIA_TYPE MediaType
Definition: ntdddisk.h:401
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:400
ULONG TracksPerCylinder
Definition: ntdddisk.h:402
ULONG SectorsPerTrack
Definition: ntdddisk.h:403
ULONG BytesPerSector
Definition: ntdddisk.h:404
struct _CONTROLLER_INFO * ControllerInfo
Definition: fdc.h:23
PDEVICE_OBJECT DeviceObject
Definition: fdc.h:26
ULONG DiskChangeCount
Definition: floppy.h:53
WCHAR DeviceNameBuffer[MAX_DEVICE_NAME]
Definition: floppy.h:52
DISK_GEOMETRY DiskGeometry
Definition: floppy.h:49
USHORT UniqueIdLength
Definition: imports.h:136
UCHAR UniqueId[1]
Definition: imports.h:137
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1701
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define IO_NO_INCREMENT
Definition: iotypes.h:598
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180