NTSTATUS FFSInitializeVcb( IN PFFS_IRP_CONTEXT IrpContext, IN PFFS_VCB Vcb, IN PFFS_SUPER_BLOCK FFSSb, IN PDEVICE_OBJECT TargetDevice, IN PDEVICE_OBJECT VolumeDevice, IN PVPB Vpb) { BOOLEAN VcbResourceInitialized = FALSE; USHORT VolumeLabelLength; ULONG IoctlSize; BOOLEAN NotifySyncInitialized = FALSE; LONGLONG DiskSize; LONGLONG PartSize; NTSTATUS Status = STATUS_UNSUCCESSFUL; UNICODE_STRING RootNode; USHORT Buffer[2]; ULONG ChangeCount; __try { if (!Vpb) { Status = STATUS_DEVICE_NOT_READY; __leave; } Buffer[0] = L'\\'; Buffer[1] = 0; RootNode.Buffer = Buffer; RootNode.MaximumLength = RootNode.Length = 2; Vcb->McbTree = FFSAllocateMcb(Vcb, &RootNode, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL); if (!Vcb->McbTree) { __leave; } #if FFS_READ_ONLY SetFlag(Vcb->Flags, VCB_READ_ONLY); #endif //READ_ONLY if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA)) { SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA); } if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) { SetFlag(Vcb->Flags, VCB_FLOPPY_DISK); } #if 0 if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING)) { if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING)) { ClearFlag(Vcb->Flags, VCB_READ_ONLY); } else { SetFlag(Vcb->Flags, VCB_READ_ONLY); } } else #endif { SetFlag(Vcb->Flags, VCB_READ_ONLY); } ExInitializeResourceLite(&Vcb->MainResource); ExInitializeResourceLite(&Vcb->PagingIoResource); ExInitializeResourceLite(&Vcb->McbResource); VcbResourceInitialized = TRUE; Vcb->McbTree->Inode = FFS_ROOT_INO; Vcb->Vpb = Vpb; Vcb->RealDevice = Vpb->RealDevice; Vpb->DeviceObject = VolumeDevice; { UNICODE_STRING LabelName; OEM_STRING OemName; LabelName.MaximumLength = 16 * 2; LabelName.Length = 0; LabelName.Buffer = Vcb->Vpb->VolumeLabel; RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength); VolumeLabelLength = 16; while((VolumeLabelLength > 0) && ((FFSSb->fs_volname[VolumeLabelLength-1] == 0x00) || (FFSSb->fs_volname[VolumeLabelLength-1] == 0x20))) { VolumeLabelLength--; } OemName.Buffer = FFSSb->fs_volname; OemName.MaximumLength = 16; OemName.Length = VolumeLabelLength; Status = FFSOEMToUnicode(&LabelName, &OemName); if (!NT_SUCCESS(Status)) { __leave; } Vpb->VolumeLabelLength = LabelName.Length; } Vpb->SerialNumber = ((ULONG*)FFSSb->fs_id)[0] + ((ULONG*)FFSSb->fs_id)[1] + ((ULONG*)FFSSb->fs_id)[2]; Vcb->StreamObj = IoCreateStreamFileObject(NULL, Vcb->Vpb->RealDevice); if (Vcb->StreamObj) { Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject); Vcb->StreamObj->Vpb = Vcb->Vpb; Vcb->StreamObj->ReadAccess = TRUE; if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) { Vcb->StreamObj->WriteAccess = TRUE; Vcb->StreamObj->DeleteAccess = TRUE; } else { Vcb->StreamObj->WriteAccess = TRUE; Vcb->StreamObj->DeleteAccess = TRUE; } Vcb->StreamObj->FsContext = (PVOID) Vcb; Vcb->StreamObj->FsContext2 = NULL; Vcb->StreamObj->Vpb = Vcb->Vpb; SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING); } else { __leave; } InitializeListHead(&Vcb->FcbList); InitializeListHead(&Vcb->NotifyList); FsRtlNotifyInitializeSync(&Vcb->NotifySync); NotifySyncInitialized = TRUE; Vcb->DeviceObject = VolumeDevice; Vcb->TargetDeviceObject = TargetDevice; Vcb->OpenFileHandleCount = 0; Vcb->ReferenceCount = 0; Vcb->ffs_super_block = FFSSb; Vcb->Header.NodeTypeCode = (USHORT) FFSVCB; Vcb->Header.NodeByteSize = sizeof(FFS_VCB); Vcb->Header.IsFastIoPossible = FastIoIsNotPossible; Vcb->Header.Resource = &(Vcb->MainResource); Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource); Vcb->Vpb->SerialNumber = 'PS'; DiskSize = Vcb->DiskGeometry.Cylinders.QuadPart * Vcb->DiskGeometry.TracksPerCylinder * Vcb->DiskGeometry.SectorsPerTrack * Vcb->DiskGeometry.BytesPerSector; IoctlSize = sizeof(PARTITION_INFORMATION); Status = FFSDiskIoControl( TargetDevice, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &Vcb->PartitionInformation, &IoctlSize); PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart; if (!NT_SUCCESS(Status)) { Vcb->PartitionInformation.StartingOffset.QuadPart = 0; Vcb->PartitionInformation.PartitionLength.QuadPart = DiskSize; PartSize = DiskSize; Status = STATUS_SUCCESS; } IoctlSize = sizeof(ULONG); Status = FFSDiskIoControl( TargetDevice, IOCTL_DISK_CHECK_VERIFY, NULL, 0, &ChangeCount, &IoctlSize); if (!NT_SUCCESS(Status)) { __leave; } Vcb->ChangeCount = ChangeCount; Vcb->Header.AllocationSize.QuadPart = Vcb->Header.FileSize.QuadPart = PartSize; Vcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff); /* Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(ffs_super_block->s_blocks_count - ffs_super_block->s_free_blocks_count) * (FFS_MIN_BLOCK << ffs_super_block->s_log_block_size); Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart; Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart; */ { CC_FILE_SIZES FileSizes; FileSizes.AllocationSize.QuadPart = FileSizes.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart; FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff); CcInitializeCacheMap(Vcb->StreamObj, &FileSizes, TRUE, &(FFSGlobal->CacheManagerNoOpCallbacks), Vcb); } #if 0 // LoadGroup XXX if (!FFSLoadGroup(Vcb)) { Status = STATUS_UNSUCCESSFUL; __leave; } #endif FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool); InitializeListHead(&(Vcb->McbList)); if (IsFlagOn(FFSGlobal->Flags, FFS_CHECKING_BITMAP)) { FFSCheckBitmapConsistency(IrpContext, Vcb); } { ULONG dwData[FFS_BLOCK_TYPES] = {NDADDR, 1, 1, 1}; ULONG dwMeta[FFS_BLOCK_TYPES] = {0, 0, 0, 0}; ULONG i; if (FS_VERSION == 1) { for (i = 0; i < FFS_BLOCK_TYPES; i++) { dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i); if (i > 0) { dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2)); } Vcb->dwData[i] = dwData[i]; Vcb->dwMeta[i] = dwMeta[i]; } } else { for (i = 0; i < FFS_BLOCK_TYPES; i++) { dwData[i] = dwData[i] << ((BLOCK_BITS - 3) * i); if (i > 0) { dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 3)); } Vcb->dwData[i] = dwData[i]; Vcb->dwMeta[i] = dwMeta[i]; } } } SetFlag(Vcb->Flags, VCB_INITIALIZED); } __finally { if (!NT_SUCCESS(Status)) { if (NotifySyncInitialized) { FsRtlNotifyUninitializeSync(&Vcb->NotifySync); } if (Vcb->ffs_super_block) { ExFreePool(Vcb->ffs_super_block); Vcb->ffs_super_block = NULL; } if (VcbResourceInitialized) { ExDeleteResourceLite(&Vcb->MainResource); ExDeleteResourceLite(&Vcb->PagingIoResource); } } } return Status; }
NTSTATUS DokanCreateDiskDevice(__in PDRIVER_OBJECT DriverObject, __in ULONG MountId, __in PWCHAR MountPoint, __in PWCHAR UNCName, __in PWCHAR BaseGuid, __in PDOKAN_GLOBAL DokanGlobal, __in DEVICE_TYPE DeviceType, __in ULONG DeviceCharacteristics, __in BOOLEAN UseMountManager, __out PDokanDCB *Dcb) { WCHAR diskDeviceNameBuf[MAXIMUM_FILENAME_LENGTH]; WCHAR symbolicLinkNameBuf[MAXIMUM_FILENAME_LENGTH]; WCHAR mountPointBuf[MAXIMUM_FILENAME_LENGTH]; PDEVICE_OBJECT diskDeviceObject; PDEVICE_OBJECT volDeviceObject; PDokanDCB dcb; PDokanVCB vcb; UNICODE_STRING diskDeviceName; NTSTATUS status; BOOLEAN isNetworkFileSystem = (DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM); DOKAN_CONTROL dokanControl; // make DeviceName and SymboliLink if (isNetworkFileSystem) { #ifdef DOKAN_NET_PROVIDER RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME); RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_SYMBOLIC_LINK_NAME); #else RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME); RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_SYMBOLIC_LINK_NAME); RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); #endif } else { RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_DISK_DEVICE_NAME); RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_SYMBOLIC_LINK_NAME); RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); } RtlInitUnicodeString(&diskDeviceName, diskDeviceNameBuf); // // Create DeviceObject for the Disk Device // if (!isNetworkFileSystem) { status = IoCreateDeviceSecure(DriverObject, // DriverObject sizeof(DokanDCB), // DeviceExtensionSize &diskDeviceName, // DeviceName FILE_DEVICE_DISK, // DeviceType DeviceCharacteristics, // DeviceCharacteristics FALSE, // Not Exclusive &sddl, // Default SDDL String NULL, // Device Class GUID &diskDeviceObject); // DeviceObject } else { status = IoCreateDevice(DriverObject, // DriverObject sizeof(DokanDCB), // DeviceExtensionSize NULL, // DeviceName FILE_DEVICE_UNKNOWN, // DeviceType DeviceCharacteristics, // DeviceCharacteristics FALSE, // Not Exclusive &diskDeviceObject); // DeviceObject } if (!NT_SUCCESS(status)) { DDbgPrint(" %s failed: 0x%x\n", isNetworkFileSystem ? "IoCreateDevice(FILE_DEVICE_UNKNOWN)" : "IoCreateDeviceSecure(FILE_DEVICE_DISK)", status); return status; } // // Initialize the device extension. // dcb = diskDeviceObject->DeviceExtension; *Dcb = dcb; dcb->DeviceObject = diskDeviceObject; dcb->Global = DokanGlobal; dcb->Identifier.Type = DCB; dcb->Identifier.Size = sizeof(DokanDCB); dcb->MountId = MountId; dcb->DeviceType = FILE_DEVICE_DISK; dcb->DeviceCharacteristics = DeviceCharacteristics; KeInitializeEvent(&dcb->KillEvent, NotificationEvent, FALSE); // // Establish user-buffer access method. // diskDeviceObject->Flags |= DO_DIRECT_IO; // initialize Event and Event queue DokanInitIrpList(&dcb->PendingIrp); DokanInitIrpList(&dcb->PendingEvent); DokanInitIrpList(&dcb->NotifyEvent); KeInitializeEvent(&dcb->ReleaseEvent, NotificationEvent, FALSE); // "0" means not mounted dcb->Mounted = 0; ExInitializeResourceLite(&dcb->Resource); dcb->CacheManagerNoOpCallbacks.AcquireForLazyWrite = &DokanNoOpAcquire; dcb->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &DokanNoOpRelease; dcb->CacheManagerNoOpCallbacks.AcquireForReadAhead = &DokanNoOpAcquire; dcb->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &DokanNoOpRelease; dcb->UseMountManager = UseMountManager; if (wcscmp(MountPoint, L"") != 0) { RtlStringCchCopyW(mountPointBuf, MAXIMUM_FILENAME_LENGTH, L"\\DosDevices\\"); if (wcslen(MountPoint) < 4) { mountPointBuf[12] = towupper(MountPoint[0]); mountPointBuf[13] = L':'; mountPointBuf[14] = L'\0'; if (isNetworkFileSystem) { dcb->UseMountManager = FALSE; } } else { dcb->UseMountManager = FALSE; RtlStringCchCatW(mountPointBuf, MAXIMUM_FILENAME_LENGTH, MountPoint); } } else { RtlStringCchCopyW(mountPointBuf, MAXIMUM_FILENAME_LENGTH, L""); } dcb->DiskDeviceName = DokanAllocateUnicodeString(diskDeviceNameBuf); dcb->SymbolicLinkName = DokanAllocateUnicodeString(symbolicLinkNameBuf); dcb->MountPoint = DokanAllocateUnicodeString(mountPointBuf); if (UNCName != NULL) { dcb->UNCName = DokanAllocateUnicodeString(UNCName); } if (dcb->DiskDeviceName == NULL || dcb->SymbolicLinkName == NULL || dcb->MountPoint == NULL || (dcb->UNCName == NULL && UNCName != NULL)) { DDbgPrint(" Failed to allocate memory for device naming"); FreeDcbNames(dcb); ExDeleteResourceLite(&dcb->Resource); IoDeleteDevice(diskDeviceObject); return STATUS_INSUFFICIENT_RESOURCES; } DDbgPrint("DiskDeviceName: %wZ - SymbolicLinkName: %wZ - MountPoint: %wZ\n", dcb->DiskDeviceName, dcb->SymbolicLinkName, dcb->MountPoint); DDbgPrint(" IoCreateDevice DeviceType: %d\n", DeviceType); // Directly create volume device and init vcb here because it has strong // dependency with fs/disk // Otherwise we would have done this work when mounting the volume if (!isNetworkFileSystem) { status = IoCreateDevice(DriverObject, // DriverObject sizeof(DokanVCB), // DeviceExtensionSize NULL, // DeviceName DeviceType, // DeviceType DeviceCharacteristics, // DeviceCharacteristics FALSE, // Not Exclusive &volDeviceObject); // DeviceObject } else { status = IoCreateDeviceSecure(DriverObject, // DriverObject sizeof(DokanVCB), // DeviceExtensionSize &diskDeviceName, // DeviceName DeviceType, // DeviceType DeviceCharacteristics, // DeviceCharacteristics FALSE, // Not Exclusive &sddl, // Default SDDL String NULL, // Device Class GUID &volDeviceObject); // DeviceObject } if (!NT_SUCCESS(status)) { DDbgPrint(" IoCreateDevice failed: 0x%x\n", status); ExDeleteResourceLite(&dcb->Resource); IoDeleteDevice(diskDeviceObject); FreeDcbNames(dcb); return status; } vcb = volDeviceObject->DeviceExtension; vcb->Identifier.Type = VCB; vcb->Identifier.Size = sizeof(DokanVCB); vcb->DeviceObject = volDeviceObject; vcb->Dcb = dcb; dcb->Vcb = vcb; InitializeListHead(&vcb->NextFCB); InitializeListHead(&vcb->DirNotifyList); FsRtlNotifyInitializeSync(&vcb->NotifySync); ExInitializeFastMutex(&vcb->AdvancedFCBHeaderMutex); #if _WIN32_WINNT >= 0x0501 FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader, &vcb->AdvancedFCBHeaderMutex); #else if (DokanFsRtlTeardownPerStreamContexts) { FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader, &vcb->AdvancedFCBHeaderMutex); } #endif // // Create a symbolic link for userapp to interact with the driver. // status = IoCreateSymbolicLink(dcb->SymbolicLinkName, dcb->DiskDeviceName); if (!NT_SUCCESS(status)) { ExDeleteResourceLite(&dcb->Resource); IoDeleteDevice(diskDeviceObject); FreeDcbNames(dcb); DDbgPrint(" IoCreateSymbolicLink returned 0x%x\n", status); return status; } DDbgPrint("SymbolicLink: %wZ -> %wZ created\n", dcb->SymbolicLinkName, dcb->DiskDeviceName); // // Establish user-buffer access method. // volDeviceObject->Flags |= DO_DIRECT_IO; DokanInitVpb(diskDeviceObject->Vpb, diskDeviceObject, volDeviceObject); // Mark devices as initialized diskDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; volDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; ObReferenceObject(volDeviceObject); ObReferenceObject(diskDeviceObject); // DokanRegisterMountedDeviceInterface(diskDeviceObject, dcb); // Save to the global mounted list RtlZeroMemory(&dokanControl, sizeof(dokanControl)); RtlStringCchCopyW(dokanControl.DeviceName, sizeof(dokanControl.DeviceName) / sizeof(WCHAR), diskDeviceNameBuf); RtlStringCchCopyW(dokanControl.MountPoint, sizeof(dokanControl.MountPoint) / sizeof(WCHAR), mountPointBuf); dokanControl.Type = DeviceType; dokanControl.DeviceObject = volDeviceObject; InsertMountEntry(DokanGlobal, &dokanControl); dcb->Mounted = 1; if (dcb->UseMountManager) { status = DokanSendVolumeArrivalNotification(dcb->DiskDeviceName); if (!NT_SUCCESS(status)) { DDbgPrint(" DokanSendVolumeArrivalNotification failed: 0x%x\n", status); if (diskDeviceObject->Vpb) { diskDeviceObject->Vpb->DeviceObject = NULL; diskDeviceObject->Vpb->RealDevice = NULL; diskDeviceObject->Vpb->Flags = 0; } ExDeleteResourceLite(&dcb->Resource); IoDeleteDevice(diskDeviceObject); FreeDcbNames(dcb); return status; } } DokanCreateMountPoint(dcb); if (isNetworkFileSystem) { // Run FsRtlRegisterUncProvider in System thread. HANDLE handle; PKTHREAD thread; OBJECT_ATTRIBUTES objectAttribs; InitializeObjectAttributes(&objectAttribs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); status = PsCreateSystemThread( &handle, THREAD_ALL_ACCESS, &objectAttribs, NULL, NULL, (PKSTART_ROUTINE)DokanRegisterUncProvider, dcb); if (!NT_SUCCESS(status)) { DDbgPrint("PsCreateSystemThread failed: 0x%X\n", status); } else { ObReferenceObjectByHandle(handle, THREAD_ALL_ACCESS, NULL, KernelMode, &thread, NULL); ZwClose(handle); KeWaitForSingleObject(thread, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(thread); } } // DokanRegisterDeviceInterface(DriverObject, diskDeviceObject, dcb); return STATUS_SUCCESS; }
PREADONLY Readonly_Create ( IN PLFS_DEVICE_EXTENSION LfsDeviceExt ) { NTSTATUS status; PREADONLY readonly; OBJECT_ATTRIBUTES objectAttributes; LARGE_INTEGER timeOut; readonly = ExAllocatePoolWithTag( NonPagedPool, sizeof(READONLY), LFS_ALLOC_TAG ); if (readonly == NULL) { NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES ); return NULL; } RtlZeroMemory( readonly, sizeof(READONLY) ); readonly->Flags = READONLY_FLAG_INITIALIZING; #if 0 ExInitializeResourceLite( &readonly->RecoveryResource ); ExInitializeResourceLite( &readonly->Resource ); ExInitializeResourceLite( &readonly->SessionResource ); ExInitializeResourceLite( &readonly->CreateResource ); #endif ExInitializeFastMutex( &readonly->FastMutex ); readonly->ReferenceCount = 1; LfsDeviceExt_Reference( LfsDeviceExt ); readonly->LfsDeviceExt = LfsDeviceExt; readonly->ThreadHandle = NULL; InitializeListHead( &readonly->FcbQueue ); KeInitializeSpinLock( &readonly->FcbQSpinLock ); InitializeListHead( &readonly->CcbQueue ); ExInitializeFastMutex( &readonly->CcbQMutex ); #if 0 InitializeListHead( &readonly->RecoveryCcbQueue ); ExInitializeFastMutex( &readonly->RecoveryCcbQMutex ); InitializeListHead( &readonly->DeletedFcbQueue ); #endif KeQuerySystemTime( &readonly->TryCloseTime ); #if 0 readonly->TryCloseWorkItem = IoAllocateWorkItem( (PDEVICE_OBJECT)VolDo ); #endif KeInitializeEvent( &readonly->ReadyEvent, NotificationEvent, FALSE ); InitializeListHead( &readonly->RequestQueue ); KeInitializeSpinLock( &readonly->RequestQSpinLock ); KeInitializeEvent( &readonly->RequestEvent, NotificationEvent, FALSE ); #if 0 //////////////////////////////////////// InitializeListHead( &readonly->FcbQueue ); ExInitializeFastMutex( &readonly->FcbQMutex ); ///////////////////////////////////////// #endif KeInitializeEvent( &readonly->DiskmountReadyEvent, NotificationEvent, FALSE ); InitializeListHead( &readonly->DirNotifyList ); FsRtlNotifyInitializeSync( &readonly->NotifySync ); InitializeObjectAttributes( &objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL ); readonly->SessionId = 0; status = PsCreateSystemThread( &readonly->ThreadHandle, THREAD_ALL_ACCESS, &objectAttributes, NULL, NULL, ReadonlyThreadProc, readonly ); if (!NT_SUCCESS(status)) { ASSERT( LFS_UNEXPECTED ); Readonly_Close( readonly ); return NULL; } status = ObReferenceObjectByHandle( readonly->ThreadHandle, FILE_READ_DATA, NULL, KernelMode, &readonly->ThreadObject, NULL ); if (!NT_SUCCESS(status)) { NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES ); Readonly_Close( readonly ); return NULL; } readonly->SessionId ++; timeOut.QuadPart = -LFS_TIME_OUT; status = KeWaitForSingleObject( &readonly->ReadyEvent, Executive, KernelMode, FALSE, &timeOut ); if (status != STATUS_SUCCESS) { NDAS_ASSERT( FALSE ); Readonly_Close( readonly ); return NULL; } KeClearEvent( &readonly->ReadyEvent ); ExAcquireFastMutex( &readonly->FastMutex ); if (!FlagOn(readonly->Thread.Flags, READONLY_THREAD_FLAG_START) || FlagOn(readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED)) { if (readonly->Thread.SessionStatus != STATUS_DISK_CORRUPT_ERROR && readonly->Thread.SessionStatus != STATUS_UNRECOGNIZED_VOLUME) { ExReleaseFastMutex( &readonly->FastMutex ); Readonly_Close( readonly ); return NULL; } } ExReleaseFastMutex( &readonly->FastMutex ); ClearFlag( readonly->Flags, READONLY_FLAG_INITIALIZING ); SetFlag( readonly->Flags, READONLY_FLAG_START ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("Readonly_Create: The client thread are ready readonly = %p\n", readonly) ); return readonly; }
/* * FUNCTION: Mount the filesystem */ static NTSTATUS VfatMount( PVFAT_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject = NULL; PDEVICE_EXTENSION DeviceExt = NULL; BOOLEAN RecognizedFS; NTSTATUS Status; PVFATFCB Fcb = NULL; PVFATFCB VolumeFcb = NULL; PVFATCCB Ccb = NULL; PDEVICE_OBJECT DeviceToMount; PVPB Vpb; UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$"); UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$"); ULONG HashTableSize; ULONG eocMark; FATINFO FatInfo; DPRINT("VfatMount(IrpContext %p)\n", IrpContext); ASSERT(IrpContext); if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; goto ByeBye; } DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject; Vpb = IrpContext->Stack->Parameters.MountVolume.Vpb; Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &FatInfo); if (!NT_SUCCESS(Status)) { goto ByeBye; } if (RecognizedFS == FALSE) { DPRINT("VFAT: Unrecognized Volume\n"); Status = STATUS_UNRECOGNIZED_VOLUME; goto ByeBye; } /* Use prime numbers for the table size */ if (FatInfo.FatType == FAT12) { HashTableSize = 4099; // 4096 = 4 * 1024 } else if (FatInfo.FatType == FAT16 || FatInfo.FatType == FATX16) { HashTableSize = 16411; // 16384 = 16 * 1024 } else { HashTableSize = 65537; // 65536 = 64 * 1024; } HashTableSize = FCB_HASH_TABLE_SIZE; DPRINT("VFAT: Recognized volume\n"); Status = IoCreateDevice(VfatGlobalData->DriverObject, ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize, NULL, FILE_DEVICE_DISK_FILE_SYSTEM, DeviceToMount->Characteristics, FALSE, &DeviceObject); if (!NT_SUCCESS(Status)) { goto ByeBye; } DeviceExt = DeviceObject->DeviceExtension; RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize); DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG))); DeviceExt->HashTableSize = HashTableSize; DeviceExt->VolumeDevice = DeviceObject; /* use same vpb as device disk */ DeviceObject->Vpb = Vpb; DeviceToMount->Vpb = Vpb; Status = VfatMountDevice(DeviceExt, DeviceToMount); if (!NT_SUCCESS(Status)) { /* FIXME: delete device object */ goto ByeBye; } DPRINT("BytesPerSector: %u\n", DeviceExt->FatInfo.BytesPerSector); DPRINT("SectorsPerCluster: %u\n", DeviceExt->FatInfo.SectorsPerCluster); DPRINT("FATCount: %u\n", DeviceExt->FatInfo.FATCount); DPRINT("FATSectors: %u\n", DeviceExt->FatInfo.FATSectors); DPRINT("RootStart: %u\n", DeviceExt->FatInfo.rootStart); DPRINT("DataStart: %u\n", DeviceExt->FatInfo.dataStart); if (DeviceExt->FatInfo.FatType == FAT32) { DPRINT("RootCluster: %u\n", DeviceExt->FatInfo.RootCluster); } switch (DeviceExt->FatInfo.FatType) { case FAT12: DeviceExt->GetNextCluster = FAT12GetNextCluster; DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster; DeviceExt->WriteCluster = FAT12WriteCluster; DeviceExt->CleanShutBitMask = 0; break; case FAT16: case FATX16: DeviceExt->GetNextCluster = FAT16GetNextCluster; DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster; DeviceExt->WriteCluster = FAT16WriteCluster; DeviceExt->CleanShutBitMask = 0x8000; break; case FAT32: case FATX32: DeviceExt->GetNextCluster = FAT32GetNextCluster; DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster; DeviceExt->WriteCluster = FAT32WriteCluster; DeviceExt->CleanShutBitMask = 0x80000000; break; } if (DeviceExt->FatInfo.FatType == FATX16 || DeviceExt->FatInfo.FatType == FATX32) { DeviceExt->Flags |= VCB_IS_FATX; DeviceExt->GetNextDirEntry = FATXGetNextDirEntry; DeviceExt->BaseDateYear = 2000; } else { DeviceExt->GetNextDirEntry = FATGetNextDirEntry; DeviceExt->BaseDateYear = 1980; } DeviceExt->StorageDevice = DeviceToMount; DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject; DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; DPRINT("FsDeviceObject %p\n", DeviceObject); /* Initialize this resource early ... it's used in VfatCleanup */ ExInitializeResourceLite(&DeviceExt->DirResource); DeviceExt->IoVPB = DeviceObject->Vpb; DeviceExt->SpareVPB = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), TAG_VFAT); if (DeviceExt->SpareVPB == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); Fcb = vfatNewFCB(DeviceExt, &NameU); if (Fcb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } Ccb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList); if (Ccb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } RtlZeroMemory(Ccb, sizeof (VFATCCB)); DeviceExt->FATFileObject->FsContext = Fcb; DeviceExt->FATFileObject->FsContext2 = Ccb; DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; DeviceExt->FATFileObject->PrivateCacheMap = NULL; DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb; Fcb->FileObject = DeviceExt->FATFileObject; Fcb->Flags |= FCB_IS_FAT; Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector; Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize; Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize; _SEH2_TRY { CcInitializeCacheMap(DeviceExt->FATFileObject, (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), TRUE, &VfatGlobalData->CacheMgrCallbacks, Fcb); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); goto ByeBye; } _SEH2_END; DeviceExt->LastAvailableCluster = 2; ExInitializeResourceLite(&DeviceExt->FatResource); InitializeListHead(&DeviceExt->FcbListHead); VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU); if (VolumeFcb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } VolumeFcb->Flags = FCB_IS_VOLUME; VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector; VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize; VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize; DeviceExt->VolumeFcb = VolumeFcb; ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE); InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry); ExReleaseResourceLite(&VfatGlobalData->VolumeListLock); /* read serial number */ DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID; /* read volume label */ ReadVolumeLabel(DeviceExt, DeviceObject->Vpb); /* read clean shutdown bit status */ Status = GetNextCluster(DeviceExt, 1, &eocMark); if (NT_SUCCESS(Status)) { if (eocMark & DeviceExt->CleanShutBitMask) { /* unset clean shutdown bit */ eocMark &= ~DeviceExt->CleanShutBitMask; WriteCluster(DeviceExt, 1, eocMark); VolumeFcb->Flags |= VCB_CLEAR_DIRTY; } } VolumeFcb->Flags |= VCB_IS_DIRTY; FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT); FsRtlNotifyInitializeSync(&DeviceExt->NotifySync); InitializeListHead(&DeviceExt->NotifyList); DPRINT("Mount success\n"); Status = STATUS_SUCCESS; ByeBye: if (!NT_SUCCESS(Status)) { /* Cleanup */ if (DeviceExt && DeviceExt->FATFileObject) ObDereferenceObject (DeviceExt->FATFileObject); if (DeviceExt && DeviceExt->SpareVPB) ExFreePoolWithTag(DeviceExt->SpareVPB, TAG_VFAT); if (Fcb) vfatDestroyFCB(Fcb); if (Ccb) vfatDestroyCCB(Ccb); if (DeviceObject) IoDeleteDevice(DeviceObject); } return Status; }
static NTSTATUS CdfsMountVolume(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDEVICE_EXTENSION DeviceExt = NULL; PDEVICE_OBJECT NewDeviceObject = NULL; PDEVICE_OBJECT DeviceToMount; PIO_STACK_LOCATION Stack; PFCB Fcb = NULL; PCCB Ccb = NULL; PVPB Vpb; NTSTATUS Status; CDINFO CdInfo; DPRINT("CdfsMountVolume() called\n"); if (DeviceObject != CdfsGlobalData->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; goto ByeBye; } Stack = IoGetCurrentIrpStackLocation(Irp); DeviceToMount = Stack->Parameters.MountVolume.DeviceObject; Vpb = Stack->Parameters.MountVolume.Vpb; Status = CdfsGetVolumeData(DeviceToMount, &CdInfo); if (!NT_SUCCESS(Status)) { goto ByeBye; } Status = IoCreateDevice(CdfsGlobalData->DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_CD_ROM_FILE_SYSTEM, DeviceToMount->Characteristics, FALSE, &NewDeviceObject); if (!NT_SUCCESS(Status)) goto ByeBye; NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO; NewDeviceObject->Flags &= ~DO_VERIFY_VOLUME; DeviceExt = (PVOID)NewDeviceObject->DeviceExtension; RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION)); Vpb->SerialNumber = CdInfo.SerialNumber; Vpb->VolumeLabelLength = CdInfo.VolumeLabelLength; RtlCopyMemory(Vpb->VolumeLabel, CdInfo.VolumeLabel, CdInfo.VolumeLabelLength); RtlCopyMemory(&DeviceExt->CdInfo, &CdInfo, sizeof(CDINFO)); NewDeviceObject->Vpb = DeviceToMount->Vpb; DeviceExt->VolumeDevice = NewDeviceObject; DeviceExt->StorageDevice = DeviceToMount; DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject; DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; NewDeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; /* Close (and cleanup) might be called from IoCreateStreamFileObject * but we use this resource from CdfsCleanup, therefore it should be * initialized no later than this. */ ExInitializeResourceLite(&DeviceExt->DirResource); DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); Fcb = CdfsCreateFCB(NULL); if (Fcb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB); if (Ccb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } RtlZeroMemory(Ccb, sizeof(CCB)); DeviceExt->StreamFileObject->ReadAccess = TRUE; DeviceExt->StreamFileObject->WriteAccess = FALSE; DeviceExt->StreamFileObject->DeleteAccess = FALSE; DeviceExt->StreamFileObject->FsContext = Fcb; DeviceExt->StreamFileObject->FsContext2 = Ccb; DeviceExt->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; DeviceExt->StreamFileObject->PrivateCacheMap = NULL; DeviceExt->StreamFileObject->Vpb = DeviceExt->Vpb; Ccb->PtrFileObject = DeviceExt->StreamFileObject; Fcb->FileObject = DeviceExt->StreamFileObject; Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; Fcb->Flags = FCB_IS_VOLUME_STREAM; Fcb->RFCB.FileSize.QuadPart = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE; Fcb->RFCB.ValidDataLength = Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize; Fcb->Entry.ExtentLocationL = 0; Fcb->Entry.DataLengthL = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE; CcInitializeCacheMap(DeviceExt->StreamFileObject, (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), TRUE, &(CdfsGlobalData->CacheMgrCallbacks), Fcb); ExInitializeResourceLite(&DeviceExt->VcbResource); KeInitializeSpinLock(&DeviceExt->FcbListLock); InitializeListHead(&DeviceExt->FcbListHead); FsRtlNotifyInitializeSync(&DeviceExt->NotifySync); InitializeListHead(&DeviceExt->NotifyList); Status = STATUS_SUCCESS; ByeBye: if (!NT_SUCCESS(Status)) { /* Cleanup */ if (DeviceExt && DeviceExt->StreamFileObject) ObDereferenceObject(DeviceExt->StreamFileObject); if (Fcb) ExFreePool(Fcb); if (NewDeviceObject) IoDeleteDevice(NewDeviceObject); } DPRINT("CdfsMountVolume() done (Status: %lx)\n", Status); return(Status); }
NTSTATUS DokanCreateDiskDevice( __in PDRIVER_OBJECT DriverObject, __in ULONG MountId, __in PWCHAR BaseGuid, __in PDOKAN_GLOBAL DokanGlobal, __in DEVICE_TYPE DeviceType, __in ULONG DeviceCharacteristics, __out PDokanDCB* Dcb ) { WCHAR diskDeviceNameBuf[MAXIMUM_FILENAME_LENGTH]; WCHAR fsDeviceNameBuf[MAXIMUM_FILENAME_LENGTH]; WCHAR symbolicLinkNameBuf[MAXIMUM_FILENAME_LENGTH]; PDEVICE_OBJECT diskDeviceObject; PDEVICE_OBJECT fsDeviceObject; PDokanDCB dcb; PDokanVCB vcb; UNICODE_STRING diskDeviceName; NTSTATUS status; BOOLEAN isNetworkFileSystem = (DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM); // make DeviceName and SymboliLink if (isNetworkFileSystem) { #ifdef DOKAN_NET_PROVIDER RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME); RtlStringCchCopyW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME); RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_SYMBOLIC_LINK_NAME); #else RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME); RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); RtlStringCchCopyW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_DEVICE_NAME); RtlStringCchCatW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_NET_SYMBOLIC_LINK_NAME); RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); #endif } else { RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_DISK_DEVICE_NAME); RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); RtlStringCchCopyW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_FS_DEVICE_NAME); RtlStringCchCatW(fsDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, DOKAN_SYMBOLIC_LINK_NAME); RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid); } RtlInitUnicodeString(&diskDeviceName, diskDeviceNameBuf); // // make a DeviceObject for Disk Device // if (!isNetworkFileSystem) { status = IoCreateDeviceSecure( DriverObject, // DriverObject sizeof(DokanDCB), // DeviceExtensionSize &diskDeviceName, // DeviceName FILE_DEVICE_DISK, // DeviceType DeviceCharacteristics, // DeviceCharacteristics FALSE, // Not Exclusive &sddl, // Default SDDL String NULL, // Device Class GUID &diskDeviceObject); // DeviceObject } else { status = IoCreateDevice( DriverObject, // DriverObject sizeof(DokanDCB), // DeviceExtensionSize NULL, // DeviceName FILE_DEVICE_UNKNOWN, // DeviceType DeviceCharacteristics, // DeviceCharacteristics FALSE, // Not Exclusive &diskDeviceObject); // DeviceObject } if (!NT_SUCCESS(status)) { DDbgPrint(" IoCreateDevice (DISK_DEVICE) failed: 0x%x\n", status); return status; } DDbgPrint("DokanDiskDevice: %wZ created\n", &diskDeviceName); // // Initialize the device extension. // dcb = diskDeviceObject->DeviceExtension; *Dcb = dcb; dcb->DeviceObject = diskDeviceObject; dcb->Global = DokanGlobal; dcb->Identifier.Type = DCB; dcb->Identifier.Size = sizeof(DokanDCB); dcb->MountId = MountId; dcb->DeviceType = FILE_DEVICE_DISK; dcb->DeviceCharacteristics = DeviceCharacteristics; KeInitializeEvent(&dcb->KillEvent, NotificationEvent, FALSE); // // Establish user-buffer access method. // diskDeviceObject->Flags |= DO_DIRECT_IO; // initialize Event and Event queue DokanInitIrpList(&dcb->PendingIrp); DokanInitIrpList(&dcb->PendingEvent); DokanInitIrpList(&dcb->NotifyEvent); KeInitializeEvent(&dcb->ReleaseEvent, NotificationEvent, FALSE); // "0" means not mounted dcb->Mounted = 0; ExInitializeResourceLite(&dcb->Resource); dcb->CacheManagerNoOpCallbacks.AcquireForLazyWrite = &DokanNoOpAcquire; dcb->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &DokanNoOpRelease; dcb->CacheManagerNoOpCallbacks.AcquireForReadAhead = &DokanNoOpAcquire; dcb->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &DokanNoOpRelease; dcb->SymbolicLinkName = AllocateUnicodeString(symbolicLinkNameBuf); dcb->DiskDeviceName = AllocateUnicodeString(diskDeviceNameBuf); dcb->FileSystemDeviceName = AllocateUnicodeString(fsDeviceNameBuf); status = IoCreateDeviceSecure( DriverObject, // DriverObject sizeof(DokanVCB), // DeviceExtensionSize dcb->FileSystemDeviceName, // DeviceName DeviceType, // DeviceType DeviceCharacteristics, // DeviceCharacteristics FALSE, // Not Exclusive &sddl, // Default SDDL String NULL, // Device Class GUID &fsDeviceObject); // DeviceObject if (!NT_SUCCESS(status)) { DDbgPrint(" IoCreateDevice (FILE_SYSTEM_DEVICE) failed: 0x%x\n", status); IoDeleteDevice(diskDeviceObject); return status; } DDbgPrint("DokanFileSystemDevice: %wZ created\n", dcb->FileSystemDeviceName); vcb = fsDeviceObject->DeviceExtension; vcb->Identifier.Type = VCB; vcb->Identifier.Size = sizeof(DokanVCB); vcb->DeviceObject = fsDeviceObject; vcb->Dcb = dcb; dcb->Vcb = vcb; InitializeListHead(&vcb->NextFCB); InitializeListHead(&vcb->DirNotifyList); FsRtlNotifyInitializeSync(&vcb->NotifySync); ExInitializeFastMutex(&vcb->AdvancedFCBHeaderMutex); #if _WIN32_WINNT >= 0x0501 FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader, &vcb->AdvancedFCBHeaderMutex); #else if (DokanFsRtlTeardownPerStreamContexts) { FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader, &vcb->AdvancedFCBHeaderMutex); } #endif // // Establish user-buffer access method. // fsDeviceObject->Flags |= DO_DIRECT_IO; if (diskDeviceObject->Vpb) { // NOTE: This can be done by IoRegisterFileSystem + IRP_MN_MOUNT_VOLUME, // however that causes BSOD inside filter manager on Vista x86 after mount // (mouse hover on file). // Probably FS_FILTER_CALLBACKS.PreAcquireForSectionSynchronization is // not correctly called in that case. diskDeviceObject->Vpb->DeviceObject = fsDeviceObject; diskDeviceObject->Vpb->RealDevice = fsDeviceObject; diskDeviceObject->Vpb->Flags |= VPB_MOUNTED; diskDeviceObject->Vpb->VolumeLabelLength = (USHORT)wcslen(VOLUME_LABEL) * sizeof(WCHAR); RtlStringCchCopyW(diskDeviceObject->Vpb->VolumeLabel, sizeof(diskDeviceObject->Vpb->VolumeLabel) / sizeof(WCHAR), VOLUME_LABEL); diskDeviceObject->Vpb->SerialNumber = 0x19831116; } ObReferenceObject(fsDeviceObject); ObReferenceObject(diskDeviceObject); // // Create a symbolic link for userapp to interact with the driver. // status = IoCreateSymbolicLink(dcb->SymbolicLinkName, dcb->DiskDeviceName); if (!NT_SUCCESS(status)) { if (diskDeviceObject->Vpb) { diskDeviceObject->Vpb->DeviceObject = NULL; diskDeviceObject->Vpb->RealDevice = NULL; diskDeviceObject->Vpb->Flags = 0; } IoDeleteDevice(diskDeviceObject); IoDeleteDevice(fsDeviceObject); DDbgPrint(" IoCreateSymbolicLink returned 0x%x\n", status); return status; } DDbgPrint("SymbolicLink: %wZ -> %wZ created\n", dcb->SymbolicLinkName, dcb->DiskDeviceName); // Mark devices as initialized diskDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; fsDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; //IoRegisterFileSystem(fsDeviceObject); if (isNetworkFileSystem) { // Run FsRtlRegisterUncProvider in System thread. HANDLE handle; PKTHREAD thread; OBJECT_ATTRIBUTES objectAttribs; InitializeObjectAttributes( &objectAttribs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); status = PsCreateSystemThread(&handle, THREAD_ALL_ACCESS, &objectAttribs, NULL, NULL, (PKSTART_ROUTINE)DokanRegisterUncProvider, dcb); if (!NT_SUCCESS(status)) { DDbgPrint("PsCreateSystemThread failed: 0x%X\n", status); } else { ObReferenceObjectByHandle(handle, THREAD_ALL_ACCESS, NULL, KernelMode, &thread, NULL); ZwClose(handle); KeWaitForSingleObject(thread, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(thread); } } //DokanRegisterMountedDeviceInterface(diskDeviceObject, dcb); dcb->Mounted = 1; //DokanSendVolumeArrivalNotification(&deviceName); //DokanRegisterDeviceInterface(DriverObject, diskDeviceObject, dcb); return STATUS_SUCCESS; }
NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt; ULONG ulTimeIncrement = 0; UNICODE_STRING uniSymLinkName; UNICODE_STRING uniDeviceName; ULONG ulIndex = 0; ULONG ulValue = 0; UNICODE_STRING uniValueName; BOOLEAN bExit = FALSE; UNICODE_STRING uniRoutine; RTL_OSVERSIONINFOW sysVersion; UNICODE_STRING uniPsSetCreateProcessNotifyRoutineEx; PsSetCreateProcessNotifyRoutineEx_t pPsSetCreateProcessNotifyRoutineEx = NULL; __try { DbgPrint("AFSRedirFs DriverEntry Initialization build %s:%s\n", __DATE__, __TIME__); // // Initialize some local variables for easier processing // uniSymLinkName.Buffer = NULL; AFSDumpFileLocation.Length = 0; AFSDumpFileLocation.MaximumLength = 0; AFSDumpFileLocation.Buffer = NULL; AFSDumpFileName.Length = 0; AFSDumpFileName.Buffer = NULL; AFSDumpFileName.MaximumLength = 0; ExInitializeResourceLite( &AFSDbgLogLock); // // Initialize the server name // AFSReadServerName(); RtlZeroMemory( &sysVersion, sizeof( RTL_OSVERSIONINFOW)); sysVersion.dwOSVersionInfoSize = sizeof( RTL_OSVERSIONINFOW); RtlGetVersion( &sysVersion); RtlInitUnicodeString( &uniRoutine, L"ZwSetInformationToken"); AFSSetInformationToken = (PAFSSetInformationToken)MmGetSystemRoutineAddress( &uniRoutine); if( AFSSetInformationToken == NULL) { #ifndef AMD64 AFSSrvcTableEntry *pServiceTable = NULL; pServiceTable = (AFSSrvcTableEntry *)KeServiceDescriptorTable; // // Only perform this lookup for Windows XP. // if( pServiceTable != NULL && sysVersion.dwMajorVersion == 5 && sysVersion.dwMinorVersion == 1) { AFSSetInformationToken = (PAFSSetInformationToken)pServiceTable->ServiceTable[ 0xE6]; } #endif } // // And the global root share name // RtlInitUnicodeString( &AFSGlobalRootName, AFS_GLOBAL_ROOT_SHARE_NAME); RtlZeroMemory( &AFSNoPAGAuthGroup, sizeof( GUID)); // // Our backdoor to not let the driver load // if( bExit) { try_return( ntStatus); } // // Perform some initialization // AFSDriverObject = DriverObject; ntStatus = AFSReadRegistry( RegistryPath); if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFS DriverEntry: Failed to read registry Status %08lX\n", ntStatus); ntStatus = STATUS_SUCCESS; } // // Initialize the debug log and dump file interface // AFSInitializeDbgLog(); AFSInitializeDumpFile(); #if DBG if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_BREAK_ON_ENTRY)) { DbgPrint("AFSRedirFs DriverEntry - Break on entry\n"); AFSBreakPoint(); if ( bExit) { // // Just as above // try_return( ntStatus = STATUS_UNSUCCESSFUL); } } #endif if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN) && !BooleanFlagOn( AFSDebugFlags, AFS_DBG_CLEAN_SHUTDOWN)) { AFSPrint("AFS DriverEntry: Failed to shutdown clean, exiting\n"); try_return( ntStatus = STATUS_UNSUCCESSFUL); } // // Setup the registry string // AFSRegistryPath.MaximumLength = RegistryPath->MaximumLength; AFSRegistryPath.Length = RegistryPath->Length; AFSRegistryPath.Buffer = (PWSTR)ExAllocatePoolWithTag( PagedPool, AFSRegistryPath.Length, AFS_GENERIC_MEMORY_18_TAG); if( AFSRegistryPath.Buffer == NULL) { DbgPrint("AFSRedirFs DriverEntry Failed to allocate registry path buffer\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( AFSRegistryPath.Buffer, RegistryPath->Buffer, RegistryPath->Length); if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN)) { // // Update the shutdown flag // ulValue = (ULONG)-1; RtlInitUnicodeString( &uniValueName, AFS_REG_SHUTDOWN_STATUS); AFSUpdateRegistryParameter( &uniValueName, REG_DWORD, &ulValue, sizeof( ULONG)); } RtlInitUnicodeString( &uniDeviceName, AFS_CONTROL_DEVICE_NAME); ntStatus = IoCreateDeviceSecure( DriverObject, sizeof( AFSDeviceExt), &uniDeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, 0, FALSE, &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX, (LPCGUID)&GUID_SD_AFS_REDIRECTOR_CONTROL_OBJECT, &AFSDeviceObject); if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFS DriverEntry - Failed to allocate device control object Status %08lX\n", ntStatus); try_return( ntStatus); } // // Setup the device extension // pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; InitializeListHead( &pDeviceExt->Specific.Control.DirNotifyList); FsRtlNotifyInitializeSync( &pDeviceExt->Specific.Control.NotifySync); // // Now initialize the control device // ntStatus = AFSInitializeControlDevice(); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } // // Allocate our symbolic link for service communication // RtlInitUnicodeString( &uniSymLinkName, AFS_SYMLINK_NAME); ntStatus = IoCreateSymbolicLink( &uniSymLinkName, &uniDeviceName); if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFS DriverEntry - Failed to create symbolic link Status %08lX\n", ntStatus); // // OK, no one can communicate with us so fail // try_return( ntStatus); } // // Fill in the dispatch table // for( ulIndex = 0; ulIndex <= IRP_MJ_MAXIMUM_FUNCTION; ulIndex++) { DriverObject->MajorFunction[ ulIndex] = AFSDefaultDispatch; } DriverObject->MajorFunction[IRP_MJ_CREATE] = AFSCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = AFSClose; DriverObject->MajorFunction[IRP_MJ_READ] = AFSRead; DriverObject->MajorFunction[IRP_MJ_WRITE] = AFSWrite; DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = AFSQueryFileInfo; DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = AFSSetFileInfo; DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = AFSQueryEA; DriverObject->MajorFunction[IRP_MJ_SET_EA] = AFSSetEA; DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = AFSFlushBuffers; DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = AFSQueryVolumeInfo; DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = AFSSetVolumeInfo; DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = AFSDirControl; DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = AFSFSControl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AFSDevControl; DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = AFSInternalDevControl; DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = AFSShutdown; DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = AFSLockControl; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AFSCleanup; DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = AFSQuerySecurity; DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = AFSSetSecurity; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = AFSSystemControl; //DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] = AFSQueryQuota; //DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] = AFSSetQuota; // // Since we are not a true FSD then we are not controlling a device and hence these will not be needed // #ifdef FSD_NOT_USED DriverObject->MajorFunction[IRP_MJ_POWER] = AFSPower; DriverObject->MajorFunction[IRP_MJ_PNP] = AFSPnP; #endif // // Fast IO Dispatch table // DriverObject->FastIoDispatch = &AFSFastIoDispatch; RtlZeroMemory( &AFSFastIoDispatch, sizeof( AFSFastIoDispatch)); // // Again, since we are not a registered FSD many of these are not going to be called. They are here // for completeness. // AFSFastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH); AFSFastIoDispatch.FastIoCheckIfPossible = AFSFastIoCheckIfPossible; // CheckForFastIo AFSFastIoDispatch.FastIoRead = AFSFastIoRead; // Read AFSFastIoDispatch.FastIoWrite = AFSFastIoWrite; // Write AFSFastIoDispatch.FastIoQueryBasicInfo = AFSFastIoQueryBasicInfo; // QueryBasicInfo AFSFastIoDispatch.FastIoQueryStandardInfo = AFSFastIoQueryStandardInfo; // QueryStandardInfo AFSFastIoDispatch.FastIoLock = AFSFastIoLock; // Lock AFSFastIoDispatch.FastIoUnlockSingle = AFSFastIoUnlockSingle; // UnlockSingle AFSFastIoDispatch.FastIoUnlockAll = AFSFastIoUnlockAll; // UnlockAll AFSFastIoDispatch.FastIoUnlockAllByKey = AFSFastIoUnlockAllByKey; // UnlockAllByKey AFSFastIoDispatch.FastIoQueryNetworkOpenInfo = AFSFastIoQueryNetworkOpenInfo; AFSFastIoDispatch.AcquireForCcFlush = AFSFastIoAcquireForCCFlush; AFSFastIoDispatch.ReleaseForCcFlush = AFSFastIoReleaseForCCFlush; AFSFastIoDispatch.FastIoDeviceControl = AFSFastIoDevCtrl; AFSFastIoDispatch.AcquireFileForNtCreateSection = AFSFastIoAcquireFile; AFSFastIoDispatch.ReleaseFileForNtCreateSection = AFSFastIoReleaseFile; AFSFastIoDispatch.FastIoDetachDevice = AFSFastIoDetachDevice; //AFSFastIoDispatch.AcquireForModWrite = AFSFastIoAcquireForModWrite; //AFSFastIoDispatch.ReleaseForModWrite = AFSFastIoReleaseForModWrite; AFSFastIoDispatch.MdlRead = AFSFastIoMdlRead; AFSFastIoDispatch.MdlReadComplete = AFSFastIoMdlReadComplete; AFSFastIoDispatch.PrepareMdlWrite = AFSFastIoPrepareMdlWrite; AFSFastIoDispatch.MdlWriteComplete = AFSFastIoMdlWriteComplete; AFSFastIoDispatch.FastIoReadCompressed = AFSFastIoReadCompressed; AFSFastIoDispatch.FastIoWriteCompressed = AFSFastIoWriteCompressed; AFSFastIoDispatch.MdlReadCompleteCompressed = AFSFastIoMdlReadCompleteCompressed; AFSFastIoDispatch.MdlWriteCompleteCompressed = AFSFastIoMdlWriteCompleteCompressed; AFSFastIoDispatch.FastIoQueryOpen = AFSFastIoQueryOpen; // // Cache manager callback routines. // AFSCacheManagerCallbacks.AcquireForLazyWrite = &AFSAcquireFcbForLazyWrite; AFSCacheManagerCallbacks.ReleaseFromLazyWrite = &AFSReleaseFcbFromLazyWrite; AFSCacheManagerCallbacks.AcquireForReadAhead = &AFSAcquireFcbForReadAhead; AFSCacheManagerCallbacks.ReleaseFromReadAhead = &AFSReleaseFcbFromReadAhead; // // System process. // AFSSysProcess = PsGetCurrentProcessId(); // // Register for shutdown notification // IoRegisterShutdownNotification( AFSDeviceObject); // // Initialize the system process cb // AFSInitializeProcessCB( 0, (ULONGLONG)AFSSysProcess); // // Initialize the redirector device // ntStatus = AFSInitRDRDevice(); if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFS DriverEntry Failed to initialize redirector device Status %08lX\n"); try_return( ntStatus); } // // Initialize some server name based strings // AFSInitServerStrings(); // // Register the call back for process creation and tear down. // On Vista SP1 and above, PsSetCreateProcessNotifyRoutineEx // will be used. This function returns STATUS_ACCESS_DENIED // if there is a signing error. In that case, the AFSProcessNotifyEx // routine has not been registered and we can fallback to the // Windows 2000 interface and AFSProcessNotify. // RtlInitUnicodeString( &uniPsSetCreateProcessNotifyRoutineEx, L"PsSetCreateProcessNotifyRoutineEx"); pPsSetCreateProcessNotifyRoutineEx = (PsSetCreateProcessNotifyRoutineEx_t)MmGetSystemRoutineAddress(&uniPsSetCreateProcessNotifyRoutineEx); ntStatus = STATUS_ACCESS_DENIED; if ( pPsSetCreateProcessNotifyRoutineEx) { ntStatus = pPsSetCreateProcessNotifyRoutineEx( AFSProcessNotifyEx, FALSE); } if ( ntStatus == STATUS_ACCESS_DENIED) { ntStatus = PsSetCreateProcessNotifyRoutine( AFSProcessNotify, FALSE); } ntStatus = STATUS_SUCCESS; try_exit: if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFSRedirFs DriverEntry failed to initialize %08lX\n", ntStatus); if( AFSRegistryPath.Buffer != NULL) { ExFreePool( AFSRegistryPath.Buffer); } if( uniSymLinkName.Buffer != NULL) { IoDeleteSymbolicLink( &uniSymLinkName); } if( AFSDeviceObject != NULL) { AFSRemoveControlDevice(); FsRtlNotifyUninitializeSync( &pDeviceExt->Specific.Control.NotifySync); IoUnregisterShutdownNotification( AFSDeviceObject); IoDeleteDevice( AFSDeviceObject); } AFSTearDownDbgLog(); ExDeleteResourceLite( &AFSDbgLogLock); } } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSRedirFs DriverEntry\n"); AFSDumpTraceFilesFnc(); } return ntStatus; }