[BTRFS] Fix booting with runtime checks
[reactos.git] / drivers / filesystems / cdfs / common.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003 ReactOS Team
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 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: drivers/filesystems/cdfs/common.c
23 * PURPOSE: CDROM (ISO 9660) filesystem driver
24 * PROGRAMMER: Art Yerkes
25 * Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include "cdfs.h"
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* FUNCTIONS ****************************************************************/
36
37 NTSTATUS
38 CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
39 IN ULONG DiskSector,
40 IN ULONG SectorCount,
41 IN OUT PUCHAR Buffer,
42 IN BOOLEAN Override)
43 {
44 PIO_STACK_LOCATION Stack;
45 IO_STATUS_BLOCK IoStatus;
46 LARGE_INTEGER Offset;
47 ULONG BlockSize;
48 KEVENT Event;
49 PIRP Irp;
50 NTSTATUS Status;
51 BOOLEAN LastChance = FALSE;
52
53 again:
54 KeInitializeEvent(&Event,
55 NotificationEvent,
56 FALSE);
57
58 Offset.u.LowPart = DiskSector << 11;
59 Offset.u.HighPart = DiskSector >> 21;
60
61 BlockSize = BLOCKSIZE * SectorCount;
62
63 DPRINT("CdfsReadSectors(DeviceObject %p, DiskSector %u, Buffer %p)\n",
64 DeviceObject, DiskSector, Buffer);
65 DPRINT("Offset %I64x BlockSize %u\n",
66 Offset.QuadPart,
67 BlockSize);
68
69 DPRINT("Building synchronous FSD Request...\n");
70 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
71 DeviceObject,
72 Buffer,
73 BlockSize,
74 &Offset,
75 &Event,
76 &IoStatus);
77 if (Irp == NULL)
78 {
79 DPRINT("IoBuildSynchronousFsdRequest failed\n");
80 return(STATUS_INSUFFICIENT_RESOURCES);
81 }
82
83 if (Override)
84 {
85 Stack = IoGetNextIrpStackLocation(Irp);
86 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
87 }
88
89 DPRINT("Calling IO Driver... with irp %p\n", Irp);
90 Status = IoCallDriver(DeviceObject, Irp);
91
92 DPRINT("Waiting for IO Operation for %p\n", Irp);
93 if (Status == STATUS_PENDING)
94 {
95 DPRINT("Operation pending\n");
96 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
97 DPRINT("Getting IO Status... for %p\n", Irp);
98 Status = IoStatus.Status;
99 }
100
101 if (!NT_SUCCESS(Status))
102 {
103 if (Status == STATUS_VERIFY_REQUIRED)
104 {
105 PDEVICE_OBJECT DeviceToVerify;
106
107 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
108 IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
109
110 Status = IoVerifyVolume(DeviceToVerify, FALSE);
111
112 if (NT_SUCCESS(Status) && !LastChance)
113 {
114 DPRINT("Volume verify succeeded; trying request again\n");
115 LastChance = TRUE;
116 goto again;
117 }
118 else if (NT_SUCCESS(Status))
119 {
120 DPRINT1("Failed to read after successful verify, aborting\n");
121 Status = STATUS_DEVICE_NOT_READY;
122 }
123 else
124 {
125 DPRINT1("IoVerifyVolume() failed (Status %lx)\n", Status);
126 }
127 }
128
129 DPRINT("CdfsReadSectors() failed (Status %x)\n", Status);
130 DPRINT("(DeviceObject %p, DiskSector %u, Buffer %p, Offset 0x%I64x)\n",
131 DeviceObject, DiskSector, Buffer,
132 Offset.QuadPart);
133 return(Status);
134 }
135
136 DPRINT("Block request succeeded for %p\n", Irp);
137
138 return(STATUS_SUCCESS);
139 }
140
141
142 NTSTATUS
143 CdfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
144 IN ULONG CtlCode,
145 IN PVOID InputBuffer,
146 IN ULONG InputBufferSize,
147 IN OUT PVOID OutputBuffer,
148 IN OUT PULONG OutputBufferSize,
149 IN BOOLEAN Override)
150 {
151 PIO_STACK_LOCATION Stack;
152 IO_STATUS_BLOCK IoStatus;
153 KEVENT Event;
154 PIRP Irp;
155 NTSTATUS Status;
156 BOOLEAN LastChance = FALSE;
157
158 DPRINT("CdfsDeviceIoControl(DeviceObject %p, CtlCode %u, "
159 "InputBuffer %p, InputBufferSize %u, OutputBuffer %p, "
160 "POutputBufferSize %p (%x)\n", DeviceObject, CtlCode,
161 InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize,
162 OutputBufferSize ? *OutputBufferSize : 0);
163
164 again:
165 KeInitializeEvent (&Event, NotificationEvent, FALSE);
166
167 DPRINT("Building device I/O control request ...\n");
168 Irp = IoBuildDeviceIoControlRequest(CtlCode,
169 DeviceObject,
170 InputBuffer,
171 InputBufferSize,
172 OutputBuffer,
173 (OutputBufferSize != NULL) ? *OutputBufferSize : 0,
174 FALSE,
175 &Event,
176 &IoStatus);
177 if (Irp == NULL)
178 {
179 DPRINT("IoBuildDeviceIoControlRequest failed\n");
180 return STATUS_INSUFFICIENT_RESOURCES;
181 }
182
183 if (Override)
184 {
185 Stack = IoGetNextIrpStackLocation(Irp);
186 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
187 }
188
189 DPRINT ("Calling IO Driver... with irp %p\n", Irp);
190 Status = IoCallDriver(DeviceObject, Irp);
191
192 DPRINT ("Waiting for IO Operation for %p\n", Irp);
193 if (Status == STATUS_PENDING)
194 {
195 DPRINT ("Operation pending\n");
196 KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
197 DPRINT ("Getting IO Status... for %p\n", Irp);
198
199 Status = IoStatus.Status;
200 }
201
202 if (OutputBufferSize != NULL)
203 {
204 *OutputBufferSize = IoStatus.Information;
205 }
206
207 if (Status == STATUS_VERIFY_REQUIRED)
208 {
209 PDEVICE_OBJECT DeviceToVerify;
210
211 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
212 IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
213
214 if (DeviceToVerify)
215 {
216 Status = IoVerifyVolume(DeviceToVerify, FALSE);
217 DPRINT("IoVerifyVolume() returned (Status %lx)\n", Status);
218 }
219
220 if (NT_SUCCESS(Status) && !LastChance)
221 {
222 DPRINT1("Volume verify succeeded; trying request again\n");
223 LastChance = TRUE;
224 goto again;
225 }
226 else if (NT_SUCCESS(Status))
227 {
228 DPRINT1("Failed to read after successful verify, aborting\n");
229 Status = STATUS_DEVICE_NOT_READY;
230 }
231 else
232 {
233 DPRINT1("IoVerifyVolume() failed (Status %lx)\n", Status);
234 }
235 }
236
237 DPRINT("Returning Status %x\n", Status);
238
239 return Status;
240 }
241
242 /* EOF */