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