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