[EXT2]
[reactos.git] / reactos / drivers / filesystems / ext2 / src / init.c
1 /*
2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4 * FILE: init.c
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "ext2fs.h"
13
14 /* GLOBALS ***************************************************************/
15
16 PEXT2_GLOBAL Ext2Global = NULL;
17
18 /*
19 * Ext2Fsd version, building date/time
20 */
21
22 CHAR gVersion[] = EXT2FSD_VERSION;
23 CHAR gTime[] = __TIME__;
24 CHAR gDate[] = __DATE__;
25
26
27 /* DEFINITIONS ***********************************************************/
28
29 NTSTATUS NTAPI
30 DriverEntry(
31 IN PDRIVER_OBJECT DriverObject,
32 IN PUNICODE_STRING RegistryPath );
33
34 #ifdef ALLOC_PRAGMA
35 #pragma alloc_text(INIT, Ext2QueryGlobalParameters)
36 #pragma alloc_text(INIT, Ext2QueryRegistrySettings)
37 #pragma alloc_text(INIT, DriverEntry)
38 #if EXT2_UNLOAD
39 #pragma alloc_text(PAGE, DriverUnload)
40 #endif
41 #endif
42
43 /* FUNCTIONS ***************************************************************/
44
45 DECLARE_INIT(journal_init);
46 DECLARE_EXIT(journal_exit);
47
48 #if EXT2_UNLOAD
49
50 /*
51 * FUNCTION: Called by the system to unload the driver
52 * ARGUMENTS:
53 * DriverObject = object describing this driver
54 * RETURNS: None
55 */
56
57 VOID NTAPI
58 DriverUnload (IN PDRIVER_OBJECT DriverObject)
59 {
60
61 UNICODE_STRING DosDeviceName;
62
63 DEBUG(DL_FUN, ( "Ext2Fsd: Unloading routine.\n"));
64
65 /*
66 * stop reaper thread ...
67 */
68
69
70 /*
71 * removing memory allocations and objects
72 */
73
74 RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME);
75 IoDeleteSymbolicLink(&DosDeviceName);
76
77 Ext2UnloadAllNls();
78
79 ExDeleteResourceLite(&Ext2Global->Resource);
80
81 ExDeleteNPagedLookasideList(&(Ext2Global->Ext2DentryLookasideList));
82 ExDeleteNPagedLookasideList(&(Ext2Global->Ext2ExtLookasideList));
83 ExDeleteNPagedLookasideList(&(Ext2Global->Ext2McbLookasideList));
84 ExDeleteNPagedLookasideList(&(Ext2Global->Ext2CcbLookasideList));
85 ExDeleteNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList));
86 ExDeleteNPagedLookasideList(&(Ext2Global->Ext2IrpContextLookasideList));
87
88 ObDereferenceObject(Ext2Global->DiskdevObject);
89 ObDereferenceObject(Ext2Global->CdromdevObject);
90
91 /* cleanup journal related caches */
92 UNLOAD_MODULE(journal_exit);
93
94 /* cleanup linux lib */
95 ext2_destroy_linux();
96
97 Ext2FreePool(Ext2Global, 'LG2E');
98 Ext2Global = NULL;
99 }
100
101 #endif
102
103 NTSTATUS NTAPI
104 Ext2RegistryQueryCallback(
105 IN PWSTR ValueName,
106 IN ULONG ValueType,
107 IN PVOID ValueData,
108 IN ULONG ValueLength,
109 IN PVOID Context,
110 IN PVOID EntryContext
111 )
112 {
113 ULONG i = 0;
114 BYTE *s, *t;
115
116 if (NULL == ValueName || NULL == ValueData)
117 return STATUS_SUCCESS;
118
119 if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(WRITING_SUPPORT) &&
120 _wcsnicmp(ValueName, WRITING_SUPPORT, wcslen(WRITING_SUPPORT)) == 0) {
121
122 if (ValueData && ValueLength == sizeof(DWORD)) {
123 if (*((PULONG)ValueData)) {
124 SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
125 } else {
126 ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
127 }
128 }
129 } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(CHECKING_BITMAP) &&
130 _wcsnicmp(ValueName, CHECKING_BITMAP, wcslen(CHECKING_BITMAP)) == 0) {
131
132 if (ValueData && ValueLength == sizeof(DWORD)) {
133 if (*((PULONG)ValueData)) {
134 SetLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
135 } else {
136 ClearLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
137 }
138 }
139 } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(EXT3_FORCEWRITING) &&
140 _wcsnicmp(ValueName, EXT3_FORCEWRITING, wcslen(EXT3_FORCEWRITING)) == 0) {
141
142 if (ValueData && ValueLength == sizeof(DWORD)) {
143 if (*((PULONG)ValueData)) {
144 SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
145 SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
146 } else {
147 ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
148 }
149 }
150 } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(AUTO_MOUNT) &&
151 _wcsnicmp(ValueName, AUTO_MOUNT, wcslen(AUTO_MOUNT)) == 0) {
152
153 if (ValueData && ValueLength == sizeof(DWORD)) {
154 if (*((PULONG)ValueData)) {
155 SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
156 } else {
157 ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
158 }
159 }
160 } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(CODEPAGE_NAME) &&
161 _wcsnicmp(ValueName, CODEPAGE_NAME, wcslen(CODEPAGE_NAME)) == 0) {
162
163 if (ValueData && ValueLength <= sizeof(WCHAR) * CODEPAGE_MAXLEN) {
164 RtlCopyMemory(&Ext2Global->Codepage.PageName[0],
165 ValueData, ValueLength);
166 }
167 } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_PREFIX) &&
168 _wcsnicmp(ValueName, HIDING_PREFIX, wcslen(HIDING_PREFIX)) == 0) {
169
170 if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) {
171 RtlCopyMemory(&Ext2Global->wHidingPrefix[0],
172 ValueData, ValueLength);
173 }
174 } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_SUFFIX) &&
175 _wcsnicmp(ValueName, HIDING_SUFFIX, wcslen(HIDING_SUFFIX)) == 0) {
176
177 if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) {
178 RtlCopyMemory(&Ext2Global->wHidingSuffix[0],
179 ValueData, ValueLength);
180 }
181 }
182
183
184 return STATUS_SUCCESS;
185 }
186
187 NTSTATUS
188 Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath)
189 {
190 RTL_QUERY_REGISTRY_TABLE QueryTable[8];
191 int i = 0;
192 NTSTATUS Status;
193
194 RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 8);
195
196 /*
197 * 1 writing support
198 */
199 QueryTable[i].Flags = 0;
200 QueryTable[0].Name = WRITING_SUPPORT;
201 QueryTable[i].DefaultType = REG_NONE;
202 QueryTable[i].DefaultLength = 0;
203 QueryTable[i].DefaultData = NULL;
204 QueryTable[i].EntryContext = NULL;
205 QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
206 i++;
207
208 /*
209 * 2 checking bitmap
210 */
211 QueryTable[i].Flags = 0;
212 QueryTable[i].Name = CHECKING_BITMAP;
213 QueryTable[i].DefaultType = REG_NONE;
214 QueryTable[i].DefaultLength = 0;
215 QueryTable[i].DefaultData = NULL;
216 QueryTable[i].EntryContext = NULL;
217 QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
218 i++;
219
220 /*
221 * 3 force writing
222 */
223 QueryTable[i].Flags = 0;
224 QueryTable[i].Name = EXT3_FORCEWRITING;
225 QueryTable[i].DefaultType = REG_NONE;
226 QueryTable[i].DefaultLength = 0;
227 QueryTable[i].DefaultData = NULL;
228 QueryTable[i].EntryContext = NULL;
229 QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
230 i++;
231
232 /*
233 * 4 automount
234 */
235 QueryTable[i].Flags = 0;
236 QueryTable[i].Name = AUTO_MOUNT;
237 QueryTable[i].DefaultType = REG_NONE;
238 QueryTable[i].DefaultLength = 0;
239 QueryTable[i].DefaultData = NULL;
240 QueryTable[i].EntryContext = NULL;
241 QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
242 i++;
243
244 /*
245 * 5 codepage
246 */
247 QueryTable[i].Flags = 0;
248 QueryTable[i].Name = CODEPAGE_NAME;
249 QueryTable[i].DefaultType = REG_NONE;
250 QueryTable[i].DefaultLength = 0;
251 QueryTable[i].DefaultData = NULL;
252 QueryTable[i].EntryContext = NULL;
253 QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
254 i++;
255
256 /*
257 * 6 hidden prefix
258 */
259 QueryTable[i].Flags = 0;
260 QueryTable[i].Name = HIDING_PREFIX;
261 QueryTable[i].DefaultType = REG_NONE;
262 QueryTable[i].DefaultLength = 0;
263 QueryTable[i].DefaultData = NULL;
264 QueryTable[i].EntryContext = NULL;
265 QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
266 i++;
267
268
269 /*
270 * 7 hidden suffix
271 */
272 QueryTable[i].Flags = 0;
273 QueryTable[i].Name = HIDING_SUFFIX;
274 QueryTable[i].DefaultType = REG_NONE;
275 QueryTable[i].DefaultLength = 0;
276 QueryTable[i].DefaultData = NULL;
277 QueryTable[i].EntryContext = NULL;
278 QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
279 i++;
280
281 Status = RtlQueryRegistryValues(
282 RTL_REGISTRY_ABSOLUTE,
283 RegistryPath->Buffer,
284 &QueryTable[0],
285 NULL,
286 NULL
287 );
288
289 return NT_SUCCESS(Status);
290 }
291
292
293 BOOLEAN
294 Ext2QueryRegistrySettings(IN PUNICODE_STRING RegistryPath)
295 {
296 UNICODE_STRING ParameterPath;
297 UNICODE_STRING UniName;
298 ANSI_STRING AnsiName;
299
300 ULONG WritingSupport = 0;
301 ULONG CheckingBitmap = 0;
302 ULONG Ext3ForceWriting = 0;
303 ULONG AutoMount = 0;
304
305 WCHAR UniBuffer[CODEPAGE_MAXLEN];
306 USHORT Buffer[HIDINGPAT_LEN];
307
308 NTSTATUS Status;
309
310 ParameterPath.Length = 0;
311 ParameterPath.MaximumLength =
312 RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR);
313 ParameterPath.Buffer =
314 (PWSTR) Ext2AllocatePool(
315 PagedPool,
316 ParameterPath.MaximumLength,
317 'LG2E'
318 );
319 if (!ParameterPath.Buffer) {
320 DbgBreak();
321 DEBUG(DL_ERR, ( "Ex2QueryParameters: failed to allocate Parameters...\n"));
322 return FALSE;
323 }
324
325 RtlCopyUnicodeString(&ParameterPath, RegistryPath);
326 RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY);
327
328 /* enable automount of ext2/3/4 volumes */
329 SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
330
331 /* query parameter settings from registry */
332 Ext2QueryGlobalParameters(&ParameterPath);
333
334 /* set global codepage settings */
335 if (wcslen(&Ext2Global->Codepage.PageName[0])) {
336 UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->Codepage.PageName[0]);
337 UniName.MaximumLength = CODEPAGE_MAXLEN * sizeof(WCHAR);
338 UniName.Buffer = &Ext2Global->Codepage.PageName[0];
339 AnsiName.MaximumLength = CODEPAGE_MAXLEN;
340 AnsiName.Length = 0;
341 AnsiName.Buffer = &Ext2Global->Codepage.AnsiName[0];
342 Status = RtlUnicodeStringToAnsiString(
343 &AnsiName,
344 &UniName,
345 FALSE);
346 if (!NT_SUCCESS(Status)) {
347 DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong CodePage %wZ ...\n", &UniName));
348 RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8);
349 }
350 } else {
351 DEBUG(DL_ERR, ( "Ext2QueryParameters: CodePage not specified.\n"));
352 RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8);
353 }
354 Ext2Global->Codepage.AnsiName[CODEPAGE_MAXLEN - 1] = 0;
355
356
357 /* set global hidden prefix pattern */
358 if (wcslen(&Ext2Global->wHidingPrefix[0])) {
359 UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingPrefix[0]);
360 UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
361 UniName.Buffer = &Ext2Global->wHidingPrefix[0];
362 AnsiName.MaximumLength = HIDINGPAT_LEN;
363 AnsiName.Length = 0;
364 AnsiName.Buffer = &(Ext2Global->sHidingPrefix[0]);
365
366 Status = RtlUnicodeStringToAnsiString(
367 &AnsiName,
368 &UniName,
369 FALSE);
370 if (NT_SUCCESS(Status)) {
371 Ext2Global->bHidingPrefix = TRUE;
372 } else {
373 DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingPrefix ...\n"));
374 }
375 } else {
376 DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingPrefix not specified.\n"));
377 }
378 Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;
379
380
381 /* set global hidden suffix pattern */
382 if (wcslen(&Ext2Global->wHidingSuffix[0])) {
383 UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingSuffix[0]);
384 UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
385 UniName.Buffer = &Ext2Global->wHidingSuffix[0];
386 AnsiName.MaximumLength = HIDINGPAT_LEN;
387 AnsiName.Length = 0;
388 AnsiName.Buffer = &(Ext2Global->sHidingSuffix[0]);
389
390 Status = RtlUnicodeStringToAnsiString(
391 &AnsiName,
392 &UniName,
393 FALSE);
394 if (NT_SUCCESS(Status)) {
395 Ext2Global->bHidingSuffix = TRUE;
396 } else {
397 DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingSuffix ...\n"));
398 }
399 } else {
400 DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingSuffix not specified.\n"));
401 }
402 Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;
403
404 Ext2Global->RegistryPath.Buffer = ParameterPath.Buffer;
405 Ext2Global->RegistryPath.Length = 0;
406 Ext2Global->RegistryPath.MaximumLength = ParameterPath.MaximumLength;
407 RtlCopyUnicodeString(&Ext2Global->RegistryPath, RegistryPath);
408 RtlAppendUnicodeToString(&Ext2Global->RegistryPath, VOLUMES_KEY);
409
410 return TRUE;
411 }
412
413
414 #define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo)
415
416 #ifndef __REACTOS__
417 #define FsRtlIsLeadDbcsCharacter(DBCS_CHAR) ( \
418 (BOOLEAN)((UCHAR)(DBCS_CHAR) < 0x80 ? FALSE : \
419 (NLS_MB_CODE_PAGE_TAG && \
420 (NLS_OEM_LEAD_BYTE_INFO[(UCHAR)(DBCS_CHAR)] != 0))) \
421 )
422 #endif
423
424 VOID
425 Ext2EresourceAlignmentChecking()
426 {
427 /* Verify ERESOURCE alignment in structures */
428 CL_ASSERT((FIELD_OFFSET(EXT2_GLOBAL, Resource) & 7) == 0);
429 CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MainResource) & 7) == 0);
430 CL_ASSERT((FIELD_OFFSET(EXT2_VCB, PagingIoResource) & 7) == 0);
431 CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaInode) & 7) == 0);
432 CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaBlock) & 7) == 0);
433 CL_ASSERT((FIELD_OFFSET(EXT2_VCB, McbLock) & 7) == 0);
434 CL_ASSERT((FIELD_OFFSET(EXT2_VCB, bd.bd_bh_lock) & 7) == 0);
435 CL_ASSERT((FIELD_OFFSET(EXT2_VCB, sbi.s_gd_lock) & 7) == 0);
436 CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0);
437 CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, PagingIoResource) & 7) == 0);
438 CL_ASSERT((FIELD_OFFSET(EXT2_FCB, MainResource) & 7) == 0);
439 CL_ASSERT((FIELD_OFFSET(EXT2_FCB, PagingIoResource) & 7) == 0);
440 }
441
442 /*
443 * NAME: DriverEntry
444 * FUNCTION: Called by the system to initalize the driver
445 *
446 * ARGUMENTS:
447 * DriverObject = object describing this driver
448 * RegistryPath = path to our configuration entries
449 * RETURNS: Success or failure
450 */
451 NTSTATUS NTAPI
452 DriverEntry (
453 IN PDRIVER_OBJECT DriverObject,
454 IN PUNICODE_STRING RegistryPath
455 )
456 {
457 PDEVICE_OBJECT DiskdevObject = NULL;
458 PDEVICE_OBJECT CdromdevObject = NULL;
459 UNICODE_STRING DeviceName;
460 UNICODE_STRING DosDeviceName;
461
462 PFAST_IO_DISPATCH FastIoDispatch;
463 PCACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
464
465 NTSTATUS Status;
466
467 int rc = 0;
468 BOOLEAN linux_lib_inited = FALSE;
469 BOOLEAN journal_module_inited = FALSE;
470
471 /* Verity super block ... */
472 ASSERT(sizeof(EXT2_SUPER_BLOCK) == 1024);
473 ASSERT(FIELD_OFFSET(EXT2_SUPER_BLOCK, s_magic) == 56);
474
475 DbgPrint(
476 "Ext2Fsd --"
477 #ifdef _WIN2K_TARGET_
478 " Win2k --"
479 #endif
480 " Version "
481 EXT2FSD_VERSION
482 #if EXT2_DEBUG
483 " Checked"
484 #else
485 " Free"
486 #endif
487 " -- "
488 __DATE__ " "
489 __TIME__ ".\n");
490
491 DEBUG(DL_FUN, ( "Ext2 DriverEntry ...\n"));
492
493 /* initialize winlib structures */
494 if (ext2_init_linux()) {
495 Status = STATUS_INSUFFICIENT_RESOURCES;
496 goto errorout;
497 }
498 linux_lib_inited = TRUE;
499
500 /* initialize journal module structures */
501 LOAD_MODULE(journal_init);
502 if (rc != 0) {
503 Status = STATUS_INSUFFICIENT_RESOURCES;
504 goto errorout;
505 }
506 journal_module_inited = TRUE;
507
508 /* allocate memory for Ext2Global */
509 Ext2Global = Ext2AllocatePool(NonPagedPool, sizeof(EXT2_GLOBAL), 'LG2E');
510 if (!Ext2Global) {
511 Status = STATUS_INSUFFICIENT_RESOURCES;
512 goto errorout;
513 }
514
515 /* initialize Ext2Global */
516 RtlZeroMemory(Ext2Global, sizeof(EXT2_GLOBAL));
517 Ext2Global->Identifier.Type = EXT2FGD;
518 Ext2Global->Identifier.Size = sizeof(EXT2_GLOBAL);
519
520 InitializeListHead(&(Ext2Global->VcbList));
521 ExInitializeResourceLite(&(Ext2Global->Resource));
522
523 /* query registry settings */
524 Ext2QueryRegistrySettings(RegistryPath);
525
526 /* create Ext2Fsd cdrom fs deivce */
527 RtlInitUnicodeString(&DeviceName, CDROM_NAME);
528 Status = IoCreateDevice(
529 DriverObject,
530 0,
531 &DeviceName,
532 FILE_DEVICE_CD_ROM_FILE_SYSTEM,
533 0,
534 FALSE,
535 &CdromdevObject );
536
537 if (!NT_SUCCESS(Status)) {
538 DEBUG(DL_ERR, ( "IoCreateDevice cdrom device object error.\n"));
539 goto errorout;
540 }
541
542 /* create Ext2Fsd disk fs deivce */
543 RtlInitUnicodeString(&DeviceName, DEVICE_NAME);
544 Status = IoCreateDevice(
545 DriverObject,
546 0,
547 &DeviceName,
548 FILE_DEVICE_DISK_FILE_SYSTEM,
549 0,
550 FALSE,
551 &DiskdevObject );
552
553 if (!NT_SUCCESS(Status)) {
554 DEBUG(DL_ERR, ( "IoCreateDevice disk device object error.\n"));
555 goto errorout;
556 }
557
558 /* start resource reaper thread */
559 Status= Ext2StartReaper(
560 &Ext2Global->McbReaper,
561 Ext2McbReaperThread);
562 if (!NT_SUCCESS(Status)) {
563 goto errorout;
564 }
565
566 Status= Ext2StartReaper(
567 &Ext2Global->bhReaper,
568 Ext2bhReaperThread);
569 if (!NT_SUCCESS(Status)) {
570 Ext2StopReaper(&Ext2Global->McbReaper);
571 goto errorout;
572 }
573
574 /* initializing */
575 Ext2Global->DiskdevObject = DiskdevObject;
576 Ext2Global->CdromdevObject = CdromdevObject;
577
578 DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2BuildRequest;
579 DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2BuildRequest;
580 DriverObject->MajorFunction[IRP_MJ_READ] = Ext2BuildRequest;
581 DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2BuildRequest;
582
583 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = Ext2BuildRequest;
584 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Ext2BuildRequest;
585
586 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = Ext2BuildRequest;
587 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = Ext2BuildRequest;
588
589 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = Ext2BuildRequest;
590 DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = Ext2BuildRequest;
591
592 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = Ext2BuildRequest;
593 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = Ext2BuildRequest;
594 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Ext2BuildRequest;
595 DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = Ext2BuildRequest;
596
597 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Ext2BuildRequest;
598
599 #if (_WIN32_WINNT >= 0x0500)
600 DriverObject->MajorFunction[IRP_MJ_PNP] = Ext2BuildRequest;
601 #endif //(_WIN32_WINNT >= 0x0500)
602
603 #if EXT2_UNLOAD
604 DriverObject->DriverUnload = DriverUnload;
605 #else
606 DriverObject->DriverUnload = NULL;
607 #endif
608
609 //
610 // Initialize the fast I/O entry points
611 //
612
613 FastIoDispatch = &(Ext2Global->FastIoDispatch);
614
615 FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
616 FastIoDispatch->FastIoCheckIfPossible = Ext2FastIoCheckIfPossible;
617 FastIoDispatch->FastIoRead = Ext2FastIoRead;
618 FastIoDispatch->FastIoWrite = Ext2FastIoWrite;
619 FastIoDispatch->FastIoQueryBasicInfo = Ext2FastIoQueryBasicInfo;
620 FastIoDispatch->FastIoQueryStandardInfo = Ext2FastIoQueryStandardInfo;
621 FastIoDispatch->FastIoLock = Ext2FastIoLock;
622 FastIoDispatch->FastIoUnlockSingle = Ext2FastIoUnlockSingle;
623 FastIoDispatch->FastIoUnlockAll = Ext2FastIoUnlockAll;
624 FastIoDispatch->FastIoUnlockAllByKey = Ext2FastIoUnlockAllByKey;
625 FastIoDispatch->FastIoQueryNetworkOpenInfo = Ext2FastIoQueryNetworkOpenInfo;
626
627 FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite;
628 FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite;
629 FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite;
630 FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite;
631 FastIoDispatch->AcquireForCcFlush = Ext2AcquireFileForCcFlush;
632 FastIoDispatch->ReleaseForCcFlush = Ext2ReleaseFileForCcFlush;
633 FastIoDispatch->AcquireFileForNtCreateSection = Ext2AcquireForCreateSection;
634 FastIoDispatch->ReleaseFileForNtCreateSection = Ext2ReleaseForCreateSection;
635
636 DriverObject->FastIoDispatch = FastIoDispatch;
637
638 //
639 // initializing structure sizes for statistics
640 // 1 means flexible/not fixed for all allocations (for different volumes).
641 //
642 Ext2Global->PerfStat.Magic = EXT2_PERF_STAT_MAGIC;
643 Ext2Global->PerfStat.Version = EXT2_PERF_STAT_VER2;
644 Ext2Global->PerfStat.Length = sizeof(EXT2_PERF_STATISTICS_V2);
645
646 Ext2Global->PerfStat.Unit.Slot[PS_IRP_CONTEXT] = sizeof(EXT2_IRP_CONTEXT); /* 0 */
647 Ext2Global->PerfStat.Unit.Slot[PS_VCB] = sizeof(EXT2_VCB); /* 1 */
648 Ext2Global->PerfStat.Unit.Slot[PS_FCB] = sizeof(EXT2_FCB); /* 2 */
649 Ext2Global->PerfStat.Unit.Slot[PS_CCB] = sizeof(EXT2_CCB); /* 3 */
650 Ext2Global->PerfStat.Unit.Slot[PS_MCB] = sizeof(EXT2_MCB); /* 4 */
651 Ext2Global->PerfStat.Unit.Slot[PS_EXTENT] = sizeof(EXT2_EXTENT); /* 5 */
652 Ext2Global->PerfStat.Unit.Slot[PS_RW_CONTEXT] = sizeof(EXT2_RW_CONTEXT); /* 6 */
653 Ext2Global->PerfStat.Unit.Slot[PS_VPB] = sizeof(VPB); /* 7 */
654 Ext2Global->PerfStat.Unit.Slot[PS_FILE_NAME] = 1; /* 8 */
655 Ext2Global->PerfStat.Unit.Slot[PS_MCB_NAME] = 1; /* 9 */
656 Ext2Global->PerfStat.Unit.Slot[PS_INODE_NAME] = 1; /* a */
657 Ext2Global->PerfStat.Unit.Slot[PS_DIR_ENTRY] = sizeof(EXT2_DIR_ENTRY2); /* b */
658 Ext2Global->PerfStat.Unit.Slot[PS_DIR_PATTERN] = 1; /* c */
659 Ext2Global->PerfStat.Unit.Slot[PS_DISK_EVENT] = sizeof(KEVENT); /* d */
660 Ext2Global->PerfStat.Unit.Slot[PS_DISK_BUFFER] = 1; /* e */
661 Ext2Global->PerfStat.Unit.Slot[PS_BLOCK_DATA] = 1; /* f */
662 Ext2Global->PerfStat.Unit.Slot[PS_EXT2_INODE] = 1; /* 10 */
663 Ext2Global->PerfStat.Unit.Slot[PS_DENTRY] = sizeof(struct dentry); /* 11 */
664 Ext2Global->PerfStat.Unit.Slot[PS_BUFF_HEAD] = sizeof(struct buffer_head); /* 12 */
665
666 switch ( MmQuerySystemSize() ) {
667
668 case MmSmallSystem:
669
670 Ext2Global->MaxDepth = 64;
671 break;
672
673 case MmMediumSystem:
674
675 Ext2Global->MaxDepth = 128;
676 break;
677
678 case MmLargeSystem:
679
680 Ext2Global->MaxDepth = 256;
681 break;
682 }
683
684 //
685 // Initialize the Cache Manager callbacks
686 //
687
688 CacheManagerCallbacks = &(Ext2Global->CacheManagerCallbacks);
689 CacheManagerCallbacks->AcquireForLazyWrite = Ext2AcquireForLazyWrite;
690 CacheManagerCallbacks->ReleaseFromLazyWrite = Ext2ReleaseFromLazyWrite;
691 CacheManagerCallbacks->AcquireForReadAhead = Ext2AcquireForReadAhead;
692 CacheManagerCallbacks->ReleaseFromReadAhead = Ext2ReleaseFromReadAhead;
693
694 Ext2Global->CacheManagerNoOpCallbacks.AcquireForLazyWrite = Ext2NoOpAcquire;
695 Ext2Global->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = Ext2NoOpRelease;
696 Ext2Global->CacheManagerNoOpCallbacks.AcquireForReadAhead = Ext2NoOpAcquire;
697 Ext2Global->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = Ext2NoOpRelease;
698
699
700 #ifndef _WIN2K_TARGET_
701 //
702 // Initialize FS Filter callbacks
703 //
704
705 RtlZeroMemory(&Ext2Global->FilterCallbacks, sizeof(FS_FILTER_CALLBACKS));
706 Ext2Global->FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
707 Ext2Global->FilterCallbacks.PreAcquireForSectionSynchronization = Ext2PreAcquireForCreateSection;
708 FsRtlRegisterFileSystemFilterCallbacks(DriverObject, &Ext2Global->FilterCallbacks );
709
710 #endif
711
712 //
713 // Initialize the global data
714 //
715
716 ExInitializeNPagedLookasideList( &(Ext2Global->Ext2IrpContextLookasideList),
717 NULL,
718 NULL,
719 0,
720 sizeof(EXT2_IRP_CONTEXT),
721 'PRIE',
722 0 );
723
724 ExInitializeNPagedLookasideList( &(Ext2Global->Ext2FcbLookasideList),
725 NULL,
726 NULL,
727 0,
728 sizeof(EXT2_FCB),
729 'BCFE',
730 0 );
731
732 ExInitializeNPagedLookasideList( &(Ext2Global->Ext2CcbLookasideList),
733 NULL,
734 NULL,
735 0,
736 sizeof(EXT2_CCB),
737 'BCCE',
738 0 );
739
740 ExInitializeNPagedLookasideList( &(Ext2Global->Ext2McbLookasideList),
741 NULL,
742 NULL,
743 0,
744 sizeof(EXT2_MCB),
745 'BCME',
746 0 );
747
748 ExInitializeNPagedLookasideList( &(Ext2Global->Ext2ExtLookasideList),
749 NULL,
750 NULL,
751 0,
752 sizeof(EXT2_EXTENT),
753 'STXE',
754 0 );
755
756 ExInitializeNPagedLookasideList( &(Ext2Global->Ext2DentryLookasideList),
757 NULL,
758 NULL,
759 0,
760 sizeof(struct dentry),
761 'TNED',
762 0 );
763
764 RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME);
765 IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
766
767 #if EXT2_DEBUG
768 ProcessNameOffset = Ext2GetProcessNameOffset();
769 #endif
770
771 Ext2LoadAllNls();
772
773 Ext2Global->Codepage.PageTable =
774 load_nls(Ext2Global->Codepage.AnsiName);
775
776 /* register file system devices for disk and cdrom */
777 IoRegisterFileSystem(DiskdevObject);
778 ObReferenceObject(DiskdevObject);
779
780 IoRegisterFileSystem(CdromdevObject);
781 ObReferenceObject(CdromdevObject);
782
783 errorout:
784
785 if (!NT_SUCCESS(Status)) {
786
787 /*
788 * stop reaper thread ...
789 */
790
791
792 /*
793 * cleanup resources ...
794 */
795
796 if (Ext2Global) {
797 ExDeleteResourceLite(&Ext2Global->Resource);
798 Ext2FreePool(Ext2Global, 'LG2E');
799 }
800
801 if (CdromdevObject) {
802 IoDeleteDevice(CdromdevObject);
803 }
804
805 if (DiskdevObject) {
806 IoDeleteDevice(DiskdevObject);
807 }
808
809 if (journal_module_inited) {
810 /* cleanup journal related caches */
811 UNLOAD_MODULE(journal_exit);
812 }
813
814 if (linux_lib_inited) {
815 /* cleanup linux lib */
816 ext2_destroy_linux();
817 }
818 }
819
820 return Status;
821 }