[REACTOS] Fix a number of MSVC warnings
[reactos.git] / drivers / storage / floppy / floppy / ioctl.c
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
38 NTSTATUS NTAPI
39 DeviceIoctl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
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 {
53 ASSERT(DeviceObject);
54 ASSERT(Irp);
55
56 Irp->Tail.Overlay.DriverContext[0] = DeviceObject;
57 IoCsqInsertIrp(&Csq, Irp, NULL);
58
59 return STATUS_PENDING;
60 }
61
62
63 VOID NTAPI
64 DeviceIoctlPassive(PDRIVE_INFO DriveInfo, PIRP Irp)
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 {
72 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
73 ULONG OutputLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
74 PVOID OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
75 ULONG Code = Stack->Parameters.DeviceIoControl.IoControlCode;
76 BOOLEAN DiskChanged;
77 PMOUNTDEV_NAME Name;
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 */
87 if(Code == IOCTL_DISK_GET_MEDIA_TYPES)
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;
96 IoCompleteRequest(Irp, IO_NO_INCREMENT);
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");
112 IoCompleteRequest(Irp, IO_NO_INCREMENT);
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;
131 IoCompleteRequest(Irp, IO_NO_INCREMENT);
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;
148 IoCompleteRequest(Irp, IO_NO_INCREMENT);
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 SignalMediaChanged(DriveInfo->DeviceObject, Irp);
157
158 /*
159 * Just guessing here - I have a choice of returning NO_MEDIA or VERIFY_REQUIRED. If there's
160 * really no disk in the drive, I'm thinking I can save time by just reporting that fact, rather
161 * than forcing windows to ask me twice. If this doesn't work, we'll need to split this up and
162 * handle the CHECK_VERIFY IOCTL separately.
163 */
164 if(ResetChangeFlag(DriveInfo) == STATUS_NO_MEDIA_IN_DEVICE)
165 Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
166
167 IoCompleteRequest(Irp, IO_NO_INCREMENT);
168 StopMotor(DriveInfo->ControllerInfo);
169 return;
170 }
171
172 switch(Code)
173 {
174 case IOCTL_DISK_IS_WRITABLE:
175 {
176 UCHAR Status;
177
178 INFO_(FLOPPY, "IOCTL_DISK_IS_WRITABLE Called\n");
179
180 /* This IRP always has 0 information */
181 Irp->IoStatus.Information = 0;
182
183 if(HwSenseDriveStatus(DriveInfo) != STATUS_SUCCESS)
184 {
185 WARN_(FLOPPY, "IoctlDiskIsWritable(): unable to sense drive status\n");
186 Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
187 break;
188 }
189
190 /* Now, read the drive's status back */
191 if(HwSenseDriveStatusResult(DriveInfo->ControllerInfo, &Status) != STATUS_SUCCESS)
192 {
193 WARN_(FLOPPY, "IoctlDiskIsWritable(): unable to read drive status result\n");
194 Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
195 break;
196 }
197
198 /* Check to see if the write flag is set. */
199 if(Status & SR3_WRITE_PROTECT_STATUS_SIGNAL)
200 {
201 INFO_(FLOPPY, "IOCTL_DISK_IS_WRITABLE: disk is write protected\n");
202 Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;
203 }
204 else
205 Irp->IoStatus.Status = STATUS_SUCCESS;
206 }
207 break;
208
209 case IOCTL_DISK_CHECK_VERIFY:
210 INFO_(FLOPPY, "IOCTL_DISK_CHECK_VERIFY called\n");
211 if (OutputLength != 0)
212 {
213 if (OutputLength < sizeof(ULONG))
214 {
215 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
216 Irp->IoStatus.Information = 0;
217 }
218 else
219 {
220 *((PULONG)OutputBuffer) = DriveInfo->DiskChangeCount;
221 Irp->IoStatus.Status = STATUS_SUCCESS;
222 Irp->IoStatus.Information = sizeof(ULONG);
223 }
224 }
225 else
226 {
227 Irp->IoStatus.Status = STATUS_SUCCESS;
228 Irp->IoStatus.Information = 0;
229 }
230 break;
231
232 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
233 {
234 INFO_(FLOPPY, "IOCTL_DISK_GET_DRIVE_GEOMETRY Called\n");
235 if(OutputLength < sizeof(DISK_GEOMETRY))
236 {
237 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
238 break;
239 }
240
241 /* This still works right even if DriveInfo->DiskGeometry->MediaType = Unknown */
242 memcpy(OutputBuffer, &DriveInfo->DiskGeometry, sizeof(DISK_GEOMETRY));
243 Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
244 break;
245 }
246
247 case IOCTL_DISK_FORMAT_TRACKS:
248 case IOCTL_DISK_FORMAT_TRACKS_EX:
249 ERR_(FLOPPY, "Format called; not supported yet\n");
250 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
251 Irp->IoStatus.Information = 0;
252 break;
253
254 case IOCTL_DISK_GET_PARTITION_INFO:
255 INFO_(FLOPPY, "IOCTL_DISK_GET_PARTITION_INFO Called; not supported by a floppy driver\n");
256 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
257 Irp->IoStatus.Information = 0;
258 break;
259
260 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
261 if(OutputLength < sizeof(MOUNTDEV_UNIQUE_ID))
262 {
263 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
264 Irp->IoStatus.Information = 0;
265 break;
266 }
267
268 UniqueId = Irp->AssociatedIrp.SystemBuffer;
269 UniqueId->UniqueIdLength = (USHORT)wcslen(&DriveInfo->DeviceNameBuffer[0]) * sizeof(WCHAR);
270
271 if(OutputLength < FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + UniqueId->UniqueIdLength)
272 {
273 Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
274 Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
275 break;
276 }
277
278 RtlCopyMemory(UniqueId->UniqueId, &DriveInfo->DeviceNameBuffer[0],
279 UniqueId->UniqueIdLength);
280
281 Irp->IoStatus.Status = STATUS_SUCCESS;
282 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + UniqueId->UniqueIdLength;
283 break;
284
285 case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
286 if(OutputLength < sizeof(MOUNTDEV_NAME))
287 {
288 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
289 Irp->IoStatus.Information = 0;
290 break;
291 }
292
293 Name = Irp->AssociatedIrp.SystemBuffer;
294 Name->NameLength = (USHORT)wcslen(&DriveInfo->DeviceNameBuffer[0]) * sizeof(WCHAR);
295
296 if(OutputLength < FIELD_OFFSET(MOUNTDEV_NAME, Name) + Name->NameLength)
297 {
298 Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
299 Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
300 break;
301 }
302
303 RtlCopyMemory(Name->Name, &DriveInfo->DeviceNameBuffer[0],
304 Name->NameLength);
305
306 Irp->IoStatus.Status = STATUS_SUCCESS;
307 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_NAME, Name) + Name->NameLength;
308 break;
309
310 default:
311 ERR_(FLOPPY, "UNKNOWN IOCTL CODE: 0x%x\n", Code);
312 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
313 Irp->IoStatus.Information = 0;
314 break;
315 }
316
317 INFO_(FLOPPY, "ioctl: completing with status 0x%x\n", Irp->IoStatus.Status);
318 IoCompleteRequest(Irp, IO_NO_INCREMENT);
319
320 StopMotor(DriveInfo->ControllerInfo);
321 return;
322 }