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 #ifdef __REACTOS__
30 NTSTATUS NTAPI
31 #else
32 NTSTATUS
33 #endif
34 DriverEntry(
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
49 DECLARE_INIT(journal_init);
50 DECLARE_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__
61 VOID NTAPI
62 #else
63 VOID
64 #endif
DriverUnload(IN PDRIVER_OBJECT DriverObject)65 DriverUnload (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__
111 NTSTATUS NTAPI
112 #else
113 NTSTATUS
114 #endif
Ext2RegistryQueryCallback(IN PWSTR ValueName,IN ULONG ValueType,IN PVOID ValueData,IN ULONG ValueLength,IN PVOID Context,IN PVOID EntryContext)115 Ext2RegistryQueryCallback(
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
198 NTSTATUS
Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath)199 Ext2QueryGlobalParameters(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
304 BOOLEAN
Ext2QueryRegistrySettings(IN PUNICODE_STRING RegistryPath)305 Ext2QueryRegistrySettings(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
435 VOID
Ext2EresourceAlignmentChecking()436 Ext2EresourceAlignmentChecking()
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__
464 NTSTATUS NTAPI
465 #else
466 NTSTATUS
467 #endif
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)468 DriverEntry (
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
816 errorout:
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 }
855