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 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 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 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 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 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 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