Moved and renamed some ReactOS specific macros
[reactos.git] / reactos / drivers / fs / fs_rec / udfs.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: udfs.c,v 1.4 2003/11/17 02:12:49 hyperion Exp $
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: drivers/fs/fs_rec/udfs.c
24 * PURPOSE: Filesystem recognizer driver
25 * PROGRAMMER: Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <rosrtl/string.h>
32
33 #define NDEBUG
34 #include <debug.h>
35
36 #include "fs_rec.h"
37
38
39 #define UDFS_VRS_START_SECTOR 16
40 #define UDFS_AVDP_SECTOR 256
41
42 /* TYPES ********************************************************************/
43
44 typedef struct _TAG
45 {
46 USHORT Identifier;
47 USHORT Version;
48 UCHAR Checksum;
49 UCHAR Reserved;
50 USHORT SerialNumber;
51 USHORT Crc;
52 USHORT CrcLength;
53 ULONG Location;
54 } PACKED TAG, *PTAG;
55
56 typedef struct _EXTENT
57 {
58 ULONG Length;
59 ULONG Location;
60 } PACKED EXTENT, *PEXTENT;
61
62 typedef struct _AVDP
63 {
64 TAG DescriptorTag;
65 EXTENT MainVolumeDescriptorExtent;
66 EXTENT ReserveVolumeDescriptorExtent;
67 } PACKED AVDP, *PAVDP;
68
69 /* FUNCTIONS ****************************************************************/
70
71 static NTSTATUS
72 FsRecCheckVolumeRecognitionSequence(IN PDEVICE_OBJECT DeviceObject,
73 IN ULONG SectorSize)
74 {
75 PUCHAR Buffer;
76 ULONG Sector;
77 NTSTATUS Status;
78 ULONG State;
79
80 Buffer = ExAllocatePool(NonPagedPool,
81 SectorSize);
82 if (Buffer == NULL)
83 {
84 return(STATUS_INSUFFICIENT_RESOURCES);
85 }
86
87 State = 0;
88 Sector = UDFS_VRS_START_SECTOR;
89 while (TRUE)
90 {
91 Status = FsRecReadSectors(DeviceObject,
92 Sector,
93 1,
94 SectorSize,
95 Buffer);
96 if (!NT_SUCCESS(Status))
97 {
98 DPRINT ("FsRecReadSectors() failed (Status %lx)\n", Status);
99 break;
100 }
101
102 DPRINT ("Descriptor identifier: [%.5s]\n", Buffer + 1);
103
104 switch (State)
105 {
106 case 0:
107 if ((Sector == UDFS_VRS_START_SECTOR) &&
108 (Buffer[1] == 'B') &&
109 (Buffer[2] == 'E') &&
110 (Buffer[3] == 'A') &&
111 (Buffer[4] == '0') &&
112 (Buffer[5] == '1'))
113 {
114 State = 1;
115 }
116 else
117 {
118 DPRINT ("VRS start sector is not 'BEA01'\n");
119 ExFreePool(Buffer);
120 return(STATUS_UNRECOGNIZED_VOLUME);
121 }
122 break;
123
124 case 1:
125 if ((Buffer[1] == 'N') &&
126 (Buffer[2] == 'S') &&
127 (Buffer[3] == 'R') &&
128 (Buffer[4] == '0') &&
129 ((Buffer[5] == '2') || (Buffer[5] == '3')))
130 {
131 State = 2;
132 }
133 break;
134
135 case 2:
136 if ((Buffer[1] == 'T') &&
137 (Buffer[2] == 'E') &&
138 (Buffer[3] == 'A') &&
139 (Buffer[4] == '0') &&
140 (Buffer[5] == '1'))
141 {
142 DPRINT ("Found 'TEA01'\n");
143 ExFreePool(Buffer);
144 return(STATUS_SUCCESS);
145 }
146 break;
147 }
148
149 Sector++;
150 if (Sector == UDFS_AVDP_SECTOR)
151 {
152 DPRINT ("No 'TEA01' found\n");
153 ExFreePool(Buffer);
154 return(STATUS_UNRECOGNIZED_VOLUME);
155 }
156 }
157
158 ExFreePool(Buffer);
159
160 return(STATUS_UNRECOGNIZED_VOLUME);
161 }
162
163
164 static NTSTATUS
165 FsRecCheckAnchorVolumeDescriptorPointer(IN PDEVICE_OBJECT DeviceObject,
166 IN ULONG SectorSize)
167 {
168 PUCHAR Buffer;
169 ULONG Sector;
170 NTSTATUS Status;
171 PAVDP Avdp;
172
173 Buffer = ExAllocatePool(NonPagedPool,
174 SectorSize);
175 if (Buffer == NULL)
176 {
177 return(STATUS_INSUFFICIENT_RESOURCES);
178 }
179
180 Sector = UDFS_AVDP_SECTOR;
181 Status = FsRecReadSectors(DeviceObject,
182 Sector,
183 1,
184 SectorSize,
185 Buffer);
186 if (!NT_SUCCESS(Status))
187 {
188 DPRINT ("FsRecReadSectors() failed (Status %lx)\n", Status);
189 ExFreePool(Buffer);
190 return(Status);
191 }
192
193 Avdp = (PAVDP)Buffer;
194 DPRINT ("Descriptor identifier: %hu\n", Avdp->DescriptorTag.Identifier);
195
196 DPRINT ("Main volume descriptor sequence location: %lu\n",
197 Avdp->MainVolumeDescriptorExtent.Location);
198
199 DPRINT ("Main volume descriptor sequence length: %lu\n",
200 Avdp->MainVolumeDescriptorExtent.Length);
201
202 DPRINT ("Reserve volume descriptor sequence location: %lu\n",
203 Avdp->ReserveVolumeDescriptorExtent.Location);
204
205 DPRINT ("Reserve volume descriptor sequence length: %lu\n",
206 Avdp->ReserveVolumeDescriptorExtent.Length);
207
208 ExFreePool(Buffer);
209
210 // return(Status);
211 return(STATUS_SUCCESS);
212 }
213
214
215 static NTSTATUS
216 FsRecIsUdfsVolume(IN PDEVICE_OBJECT DeviceObject)
217 {
218 DISK_GEOMETRY DiskGeometry;
219 ULONG Size;
220 NTSTATUS Status;
221
222 Size = sizeof(DISK_GEOMETRY);
223 Status = FsRecDeviceIoControl(DeviceObject,
224 IOCTL_CDROM_GET_DRIVE_GEOMETRY,
225 NULL,
226 0,
227 &DiskGeometry,
228 &Size);
229 if (!NT_SUCCESS(Status))
230 {
231 DPRINT ("FsRecDeviceIoControl() failed (Status %lx)\n", Status);
232 return(Status);
233 }
234 DPRINT ("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
235
236 /* Check the volume recognition sequence */
237 Status = FsRecCheckVolumeRecognitionSequence(DeviceObject,
238 DiskGeometry.BytesPerSector);
239 if (!NT_SUCCESS(Status))
240 return(Status);
241
242 Status = FsRecCheckAnchorVolumeDescriptorPointer(DeviceObject,
243 DiskGeometry.BytesPerSector);
244 if (!NT_SUCCESS(Status))
245 return(Status);
246
247 return(STATUS_SUCCESS);
248 }
249
250
251 NTSTATUS
252 FsRecUdfsFsControl(IN PDEVICE_OBJECT DeviceObject,
253 IN PIRP Irp)
254 {
255 PIO_STACK_LOCATION Stack;
256 UNICODE_STRING RegistryPath;
257 NTSTATUS Status;
258
259 Stack = IoGetCurrentIrpStackLocation(Irp);
260
261 switch (Stack->MinorFunction)
262 {
263 case IRP_MN_MOUNT_VOLUME:
264 DPRINT("Udfs: IRP_MN_MOUNT_VOLUME\n");
265 Status = FsRecIsUdfsVolume(Stack->Parameters.MountVolume.DeviceObject);
266 if (NT_SUCCESS(Status))
267 {
268 DPRINT("Identified UDFS volume\n");
269 Status = STATUS_FS_DRIVER_REQUIRED;
270 }
271 break;
272
273 case IRP_MN_LOAD_FILE_SYSTEM:
274 DPRINT("Udfs: IRP_MN_LOAD_FILE_SYSTEM\n");
275 RtlRosInitUnicodeStringFromLiteral(&RegistryPath,
276 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Udfs");
277 Status = ZwLoadDriver(&RegistryPath);
278 if (!NT_SUCCESS(Status))
279 {
280 DPRINT("ZwLoadDriver failed (Status %x)\n", Status);
281 }
282 else
283 {
284 IoUnregisterFileSystem(DeviceObject);
285 }
286 break;
287
288 default:
289 DPRINT("Udfs: Unknown minor function %lx\n", Stack->MinorFunction);
290 Status = STATUS_INVALID_DEVICE_REQUEST;
291 break;
292 }
293 return(Status);
294 }
295
296 /* EOF */