VOID SpAdapterCleanup( IN PADAPTER_EXTENSION Adapter ) /*++ Routine Description: This routine cleans up the names associated with the specified adapter and the i/o system counts. Arguments: Adapter - Supplies a pointer to the device extension to be deleted. Return Value: None. --*/ { PCOMMON_EXTENSION commonExtension = &(Adapter->CommonExtension); PAGED_CODE(); // // If we assigned a port number to this adapter then attempt to delete the // symbolic links we created to it. // if(Adapter->PortNumber != -1) { PWCHAR wideNameStrings[] = {L"\\Device\\ScsiPort%d", L"\\DosDevices\\Scsi%d:"}; ULONG i; for(i = 0; i < (sizeof(wideNameStrings) / sizeof(PWCHAR)); i++) { WCHAR wideLinkName[64]; UNICODE_STRING unicodeLinkName; swprintf(wideLinkName, wideNameStrings[i], Adapter->PortNumber); RtlInitUnicodeString(&unicodeLinkName, wideLinkName); IoDeleteSymbolicLink(&unicodeLinkName); } Adapter->PortNumber = -1; // // Decrement the scsiport count. // IoGetConfigurationInformation()->ScsiPortCount--; } return; }
static BOOLEAN NTAPI AddControllers(PDRIVER_OBJECT DriverObject) /* * FUNCTION: Called on initialization to find our controllers and build device and controller objects for them * ARGUMENTS: * DriverObject: Our driver's DriverObject (so we can create devices against it) * RETURNS: * FALSE if we can't allocate a device, adapter, or interrupt object, or if we fail to find any controllers * TRUE otherwise (i.e. we have at least one fully-configured controller) * NOTES: * - Currently we only support ISA buses. * - BUG: Windows 2000 seems to clobber the response from the IoQueryDeviceDescription callback, so now we * just test a boolean value in the first object to see if it was completely populated. The same value * is tested for each controller before we build device objects for it. * TODO: * - Report resource usage to the HAL */ { INTERFACE_TYPE InterfaceType = Isa; CONFIGURATION_TYPE ControllerType = DiskController; CONFIGURATION_TYPE PeripheralType = FloppyDiskPeripheral; KAFFINITY Affinity; DEVICE_DESCRIPTION DeviceDescription; UCHAR i; UCHAR j; PAGED_CODE(); /* Find our controllers on all ISA buses */ IoQueryDeviceDescription(&InterfaceType, 0, &ControllerType, 0, &PeripheralType, 0, ConfigCallback, 0); /* * w2k breaks the return val from ConfigCallback, so we have to hack around it, rather than just * looking for a return value from ConfigCallback. We expect at least one controller. */ if(!gControllerInfo[0].Populated) { WARN_(FLOPPY, "AddControllers: failed to get controller info from registry\n"); return FALSE; } /* Now that we have a controller, set it up with the system */ for(i = 0; i < gNumberOfControllers; i++) { /* 0: Report resource usage to the kernel, to make sure they aren't assigned to anyone else */ /* FIXME: Implement me. */ /* 1: Set up interrupt */ gControllerInfo[i].MappedVector = HalGetInterruptVector(gControllerInfo[i].InterfaceType, gControllerInfo[i].BusNumber, gControllerInfo[i].Level, gControllerInfo[i].Vector, &gControllerInfo[i].MappedLevel, &Affinity); /* Must set up the DPC before we connect the interrupt */ KeInitializeDpc(&gControllerInfo[i].Dpc, DpcForIsr, &gControllerInfo[i]); INFO_(FLOPPY, "Connecting interrupt %d to controller%d (object 0x%p)\n", gControllerInfo[i].MappedVector, i, &gControllerInfo[i]); /* NOTE: We cannot share our interrupt, even on level-triggered buses. See Isr() for details. */ if(IoConnectInterrupt(&gControllerInfo[i].InterruptObject, Isr, &gControllerInfo[i], 0, gControllerInfo[i].MappedVector, gControllerInfo[i].MappedLevel, gControllerInfo[i].MappedLevel, gControllerInfo[i].InterruptMode, FALSE, Affinity, 0) != STATUS_SUCCESS) { WARN_(FLOPPY, "AddControllers: unable to connect interrupt\n"); continue; } /* 2: Set up DMA */ memset(&DeviceDescription, 0, sizeof(DeviceDescription)); DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; DeviceDescription.DmaChannel = gControllerInfo[i].Dma; DeviceDescription.InterfaceType = gControllerInfo[i].InterfaceType; DeviceDescription.BusNumber = gControllerInfo[i].BusNumber; DeviceDescription.MaximumLength = 2*18*512; /* based on a 1.44MB floppy */ /* DMA 0,1,2,3 are 8-bit; 4,5,6,7 are 16-bit (4 is chain i think) */ DeviceDescription.DmaWidth = gControllerInfo[i].Dma > 3 ? Width16Bits: Width8Bits; gControllerInfo[i].AdapterObject = HalGetAdapter(&DeviceDescription, &gControllerInfo[i].MapRegisters); if(!gControllerInfo[i].AdapterObject) { WARN_(FLOPPY, "AddControllers: unable to allocate an adapter object\n"); IoDisconnectInterrupt(gControllerInfo[i].InterruptObject); continue; } /* 2b: Initialize the new controller */ if(InitController(&gControllerInfo[i]) != STATUS_SUCCESS) { WARN_(FLOPPY, "AddControllers(): Unable to set up controller %d - initialization failed\n", i); IoDisconnectInterrupt(gControllerInfo[i].InterruptObject); continue; } /* 2c: Set the controller's initlized flag so we know to release stuff in Unload */ gControllerInfo[i].Initialized = TRUE; /* 3: per-drive setup */ for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++) { WCHAR DeviceNameBuf[MAX_DEVICE_NAME]; UNICODE_STRING DeviceName; UNICODE_STRING LinkName; UNICODE_STRING ArcPath; UCHAR DriveNumber; INFO_(FLOPPY, "AddControllers(): Configuring drive %d on controller %d\n", i, j); /* * 3a: create a device object for the drive * Controllers and drives are 0-based, so the combos are: * 0: 0,0 * 1: 0,1 * 2: 0,2 * 3: 0,3 * 4: 1,0 * 5: 1,1 * ... * 14: 3,2 * 15: 3,3 */ DriveNumber = (UCHAR)(i*4 + j); /* loss of precision is OK; there are only 16 of 'em */ RtlZeroMemory(&DeviceNameBuf, MAX_DEVICE_NAME * sizeof(WCHAR)); swprintf(DeviceNameBuf, L"\\Device\\Floppy%d", DriveNumber); RtlInitUnicodeString(&DeviceName, DeviceNameBuf); if(IoCreateDevice(DriverObject, sizeof(PVOID), &DeviceName, FILE_DEVICE_DISK, FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE, FALSE, &gControllerInfo[i].DriveInfo[j].DeviceObject) != STATUS_SUCCESS) { WARN_(FLOPPY, "AddControllers: unable to register a Device object\n"); IoDisconnectInterrupt(gControllerInfo[i].InterruptObject); continue; /* continue on to next drive */ } INFO_(FLOPPY, "AddControllers: New device: %S (0x%p)\n", DeviceNameBuf, gControllerInfo[i].DriveInfo[j].DeviceObject); /* 3b.5: Create an ARC path in case we're booting from this drive */ swprintf(gControllerInfo[i].DriveInfo[j].ArcPathBuffer, L"\\ArcName\\multi(%d)disk(%d)fdisk(%d)", gControllerInfo[i].BusNumber, i, DriveNumber); RtlInitUnicodeString(&ArcPath, gControllerInfo[i].DriveInfo[j].ArcPathBuffer); IoAssignArcName(&ArcPath, &DeviceName); /* 3c: Set flags up */ gControllerInfo[i].DriveInfo[j].DeviceObject->Flags |= DO_DIRECT_IO; /* 3d: Create a symlink */ swprintf(gControllerInfo[i].DriveInfo[j].SymLinkBuffer, L"\\DosDevices\\%c:", DriveNumber + 'A'); RtlInitUnicodeString(&LinkName, gControllerInfo[i].DriveInfo[j].SymLinkBuffer); if(IoCreateSymbolicLink(&LinkName, &DeviceName) != STATUS_SUCCESS) { WARN_(FLOPPY, "AddControllers: Unable to create a symlink for drive %d\n", DriveNumber); IoDisconnectInterrupt(gControllerInfo[i].InterruptObject); IoDeassignArcName(&ArcPath); continue; /* continue to next drive */ } /* 3e: Increase global floppy drives count */ IoGetConfigurationInformation()->FloppyCount++; /* 3f: Set up the DPC */ IoInitializeDpcRequest(gControllerInfo[i].DriveInfo[j].DeviceObject, (PIO_DPC_ROUTINE)DpcForIsr); /* 3g: Point the device extension at our DriveInfo struct */ gControllerInfo[i].DriveInfo[j].DeviceObject->DeviceExtension = &gControllerInfo[i].DriveInfo[j]; /* 3h: neat comic strip */ /* 3i: set the initial media type to unknown */ memset(&gControllerInfo[i].DriveInfo[j].DiskGeometry, 0, sizeof(DISK_GEOMETRY)); gControllerInfo[i].DriveInfo[j].DiskGeometry.MediaType = Unknown; /* 3j: Now that we're done, set the Initialized flag so we know to free this in Unload */ gControllerInfo[i].DriveInfo[j].Initialized = TRUE; /* 3k: Clear the DO_DEVICE_INITIALIZING flag */ gControllerInfo[i].DriveInfo[j].DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; } } INFO_(FLOPPY, "AddControllers: --------------------------------------------> finished adding controllers\n"); return TRUE; }
NTSTATUS DiskRemoveDevice( IN PDEVICE_OBJECT DeviceObject, IN UCHAR Type ) /*++ Routine Description: This routine will release any resources the device may have allocated for this device object and return. Arguments: DeviceObject - the device object being removed Return Value: status --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; PAGED_CODE(); // // Handle query and cancel // if((Type == IRP_MN_QUERY_REMOVE_DEVICE) || (Type == IRP_MN_CANCEL_REMOVE_DEVICE)) { return STATUS_SUCCESS; } // // Delete our object directory. // if(fdoExtension->DeviceDirectory != NULL) { ZwMakeTemporaryObject(fdoExtension->DeviceDirectory); ZwClose(fdoExtension->DeviceDirectory); fdoExtension->DeviceDirectory = NULL; } if(Type == IRP_MN_REMOVE_DEVICE) { FREE_POOL(fdoExtension->SenseData); IoGetConfigurationInformation()->DiskCount--; } DiskDeleteSymbolicLinks(DeviceObject); if (Type == IRP_MN_REMOVE_DEVICE) { ClassDeleteSrbLookasideList(commonExtension); } return STATUS_SUCCESS; }
NTSTATUS DiskAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject ) /*++ Routine Description: This routine gets a port drivers capabilities, obtains the inquiry data, searches the SCSI bus for the port driver and creates the device objects for the disks found. Arguments: DriverObject - Pointer to driver object created by system. Pdo - Device object use to send requests to port driver. Return Value: True is returned if one disk was found and successfully created. --*/ { ULONG rootPartitionMountable = FALSE; PCONFIGURATION_INFORMATION configurationInformation; ULONG diskCount; NTSTATUS status; PAGED_CODE(); // // See if we should be allowing file systems to mount on partition zero. // TRY { HANDLE deviceKey = NULL; UNICODE_STRING diskKeyName; OBJECT_ATTRIBUTES objectAttributes = {0}; HANDLE diskKey; RTL_QUERY_REGISTRY_TABLE queryTable[2] = { 0 }; status = IoOpenDeviceRegistryKey(PhysicalDeviceObject, PLUGPLAY_REGKEY_DEVICE, KEY_READ, &deviceKey); if(!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx opening device key " "for pdo %p\n", status, PhysicalDeviceObject)); LEAVE; } RtlInitUnicodeString(&diskKeyName, L"Disk"); InitializeObjectAttributes(&objectAttributes, &diskKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, deviceKey, NULL); status = ZwOpenKey(&diskKey, KEY_READ, &objectAttributes); ZwClose(deviceKey); if(!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx opening disk key " "for pdo %p device key %p\n", status, PhysicalDeviceObject, deviceKey)); LEAVE; } queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; queryTable[0].Name = L"RootPartitionMountable"; queryTable[0].EntryContext = &(rootPartitionMountable); #pragma prefast(suppress:6309, "We don't have QueryRoutine so Context doesn't make any sense") status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, diskKey, queryTable, NULL, NULL); if(!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx reading value from " "disk key %p for pdo %p\n", status, diskKey, PhysicalDeviceObject)); } ZwClose(diskKey); } FINALLY { // // Do nothing. // if(!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskAddDevice: Will %sallow file system to mount on " "partition zero of disk %p\n", (rootPartitionMountable ? "" : "not "), PhysicalDeviceObject)); } } // // Create device objects for disk // diskCount = 0; status = DiskCreateFdo( DriverObject, PhysicalDeviceObject, &diskCount, (BOOLEAN) !rootPartitionMountable ); // // Get the number of disks already initialized. // configurationInformation = IoGetConfigurationInformation(); if (NT_SUCCESS(status)) { // // Increment system disk device count. // configurationInformation->DiskCount++; } return status; } // end DiskAddDevice()
NTSTATUS NTAPI DiskRemoveDevice( IN PDEVICE_OBJECT DeviceObject, IN UCHAR Type ) /*++ Routine Description: This routine will release any resources the device may have allocated for this device object and return. Arguments: DeviceObject - the device object being removed Return Value: status --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; PDISK_DATA diskData = commonExtension->DriverData; PAGED_CODE(); // // Handle query and cancel // if((Type == IRP_MN_QUERY_REMOVE_DEVICE) || (Type == IRP_MN_CANCEL_REMOVE_DEVICE)) { return STATUS_SUCCESS; } if(commonExtension->IsFdo) { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; // // Purge the cached partition table (if any). // DiskAcquirePartitioningLock(fdoExtension); DiskInvalidatePartitionTable(fdoExtension, TRUE); DiskReleasePartitioningLock(fdoExtension); // // Delete our object directory. // if(fdoExtension->AdapterDescriptor) { ExFreePool(fdoExtension->AdapterDescriptor); fdoExtension->AdapterDescriptor = NULL; } if(fdoExtension->DeviceDescriptor) { ExFreePool(fdoExtension->DeviceDescriptor); fdoExtension->DeviceDescriptor = NULL; } if(fdoExtension->SenseData) { ExFreePool(fdoExtension->SenseData); fdoExtension->SenseData = NULL; } if(fdoExtension->DeviceDirectory != NULL) { ZwMakeTemporaryObject(fdoExtension->DeviceDirectory); ZwClose(fdoExtension->DeviceDirectory); fdoExtension->DeviceDirectory = NULL; } if(Type == IRP_MN_REMOVE_DEVICE) { IoGetConfigurationInformation()->DiskCount--; } } else { //PPHYSICAL_DEVICE_EXTENSION pdoExtension = DeviceObject->DeviceExtension; } DiskDeleteSymbolicLinks(DeviceObject); // // Release the mounted device interface if we've set it. // if(diskData->PartitionInterfaceString.Buffer != NULL) { IoSetDeviceInterfaceState(&(diskData->PartitionInterfaceString), FALSE); RtlFreeUnicodeString(&(diskData->PartitionInterfaceString)); RtlInitUnicodeString(&(diskData->PartitionInterfaceString), NULL); } if(diskData->DiskInterfaceString.Buffer != NULL) { IoSetDeviceInterfaceState(&(diskData->DiskInterfaceString), FALSE); RtlFreeUnicodeString(&(diskData->DiskInterfaceString)); RtlInitUnicodeString(&(diskData->DiskInterfaceString), NULL); } ClassDeleteSrbLookasideList(commonExtension); return STATUS_SUCCESS; }
//----- (08000DCF) -------------------------------------------------------- NTSTATUS HookDispatch( PDRIVER_OBJECT DriverObject, ULONG DiskIndex ) { PCONFIGURATION_INFORMATION ConfigInfo; NTSTATUS status; PIRP Irp; CHAR SourceString[64] = ""; STRING astr; UNICODE_STRING ustr; PFILE_OBJECT FileObject, FileObject1; PDEVICE_OBJECT DeviceObject, DeviceObject1; PDRIVE_LAYOUT_INFORMATION LayoutInfo; KEVENT Event; IO_STATUS_BLOCK iosb; OBJECT_ATTRIBUTES oa; HANDLE Handle; ULONG i, j; ConfigInfo = IoGetConfigurationInformation(); for(i = DiskIndex; i < ConfigInfo->DiskCount; i++) { sprintf(SourceString, "\\Device\\Harddisk%d\\Partition0", i); RtlInitAnsiString(&astr, SourceString); RtlAnsiStringToUnicodeString(&ustr, &astr, TRUE); status = IoGetDeviceObjectPointer(&ustr, 0x80, &FileObject, &DeviceObject); RtlFreeUnicodeString(&ustr); if (!NT_SUCCESS(status)) { continue; } AddDeviceToHookEntry(FileObject->DeviceObject, i, 0); LayoutInfo = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePool(0, 0x2000); if ( LayoutInfo ) { KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT, DeviceObject, NULL, 0, LayoutInfo, 0x2000, FALSE, &Event, &iosb); if ( Irp ) { status = IoCallDriver(DeviceObject, Irp); if ( status == STATUS_PENDING ) { KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); status = iosb.Status; } if ( NT_SUCCESS(status) ) { for(j = 1; j < LayoutInfo->PartitionCount; j++) { sprintf(SourceString, "\\Device\\Harddisk%d\\Partition%d", i, j); RtlInitAnsiString(&astr, SourceString); RtlAnsiStringToUnicodeString(&ustr, &astr, TRUE); status = IoGetDeviceObjectPointer(&ustr, 0x80, &FileObject1, &DeviceObject1); RtlFreeUnicodeString(&ustr); if (!NT_SUCCESS(status)) { continue; } AddDeviceToHookEntry(FileObject1->DeviceObject, i, j); ObfDereferenceObject(FileObject1); } } } ExFreePool(LayoutInfo); } ObfDereferenceObject(FileObject); } return status; }
NTSTATUS INIT_FUNCTION NTAPI IopCreateArcNamesDisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN BOOLEAN SingleDisk, IN PBOOLEAN FoundBoot) { PIRP Irp; PVOID Data; KEVENT Event; NTSTATUS Status; PLIST_ENTRY NextEntry; PFILE_OBJECT FileObject; DISK_GEOMETRY DiskGeometry; PDEVICE_OBJECT DeviceObject; LARGE_INTEGER StartingOffset; PULONG PartitionBuffer = NULL; IO_STATUS_BLOCK IoStatusBlock; CHAR Buffer[128], ArcBuffer[128]; BOOLEAN NotEnabledPresent = FALSE; STORAGE_DEVICE_NUMBER DeviceNumber; PARC_DISK_SIGNATURE ArcDiskSignature; PWSTR SymbolicLinkList, lSymbolicLinkList; PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL; UNICODE_STRING DeviceStringW, ArcNameStringW, HalPathStringW; ULONG DiskNumber, DiskCount, CheckSum, i, Signature, EnabledDisks = 0; PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation; ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA, HalPathStringA; /* Initialise device number */ DeviceNumber.DeviceNumber = 0xFFFFFFFF; /* Get all the disks present in the system */ DiskCount = IoGetConfigurationInformation()->DiskCount; /* Get enabled disks and check if result matches */ Status = IopFetchConfigurationInformation(&SymbolicLinkList, GUID_DEVINTERFACE_DISK, DiskCount, &EnabledDisks); if (!NT_SUCCESS(Status)) { NotEnabledPresent = TRUE; } /* Save symbolic link list address in order to free it after */ lSymbolicLinkList = SymbolicLinkList; /* Build the boot strings */ RtlInitAnsiString(&ArcBootString, LoaderBlock->ArcBootDeviceName); RtlInitAnsiString(&ArcSystemString, LoaderBlock->ArcHalDeviceName); /* If we have more enabled disks, take that into account */ if (EnabledDisks > DiskCount) { DiskCount = EnabledDisks; } /* If we'll have to browse for none enabled disks, fix higher count */ if (NotEnabledPresent && !EnabledDisks) { DiskCount += 20; } /* Finally, if in spite of all that work, we still don't have disks, leave */ if (!DiskCount) { goto Cleanup; } /* Start browsing disks */ for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++) { /* Check if we have an enabled disk */ if (lSymbolicLinkList && *lSymbolicLinkList != UNICODE_NULL) { /* Create its device name using first symbolic link */ RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList); /* Then, update symbolic links list */ lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); /* Get its associated device object and file object */ Status = IoGetDeviceObjectPointer(&DeviceStringW, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject); if (NT_SUCCESS(Status)) { /* Now, we'll ask the device its device number */ Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, DeviceObject, NULL, 0, &DeviceNumber, sizeof(STORAGE_DEVICE_NUMBER), FALSE, &Event, &IoStatusBlock); /* Missing resources is a shame... No need to go farther */ if (!Irp) { ObDereferenceObject(FileObject); Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } /* Call the driver, and wait for it if needed */ KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* If we didn't get the appriopriate data, just skip that disk */ if (!NT_SUCCESS(Status)) { ObDereferenceObject(FileObject); continue; } } /* End of enabled disks enumeration */ if (NotEnabledPresent && *lSymbolicLinkList == UNICODE_NULL) { /* No enabled disk worked, reset field */ if (DeviceNumber.DeviceNumber == 0xFFFFFFFF) { DeviceNumber.DeviceNumber = 0; } /* Update disk number to enable the following not enabled disks */ if (DeviceNumber.DeviceNumber > DiskNumber) { DiskNumber = DeviceNumber.DeviceNumber; } /* Increase a bit more */ DiskCount = DiskNumber + 20; } } else { /* Create device name for the disk */ sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber); RtlInitAnsiString(&DeviceStringA, Buffer); Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* Get its device object */ Status = IoGetDeviceObjectPointer(&DeviceStringW, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject); RtlFreeUnicodeString(&DeviceStringW); /* This is a security measure, to ensure DiskNumber will be used */ DeviceNumber.DeviceNumber = 0xFFFFFFFF; } /* Something failed somewhere earlier, just skip the disk */ if (!NT_SUCCESS(Status)) { continue; } /* Let's ask the disk for its geometry */ Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, DeviceObject, NULL, 0, &DiskGeometry, sizeof(DISK_GEOMETRY), FALSE, &Event, &IoStatusBlock); /* Missing resources is a shame... No need to go farther */ if (!Irp) { ObDereferenceObject(FileObject); Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } /* Call the driver, and wait for it if needed */ KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* Failure, skip disk */ if (!NT_SUCCESS(Status)) { ObDereferenceObject(FileObject); continue; } /* Read the partition table */ Status = IoReadPartitionTableEx(DeviceObject, &DriveLayout); if (!NT_SUCCESS(Status)) { ObDereferenceObject(FileObject); continue; } /* Ensure we have at least 512 bytes per sector */ if (DiskGeometry.BytesPerSector < 512) { DiskGeometry.BytesPerSector = 512; } /* Check MBR type against EZ Drive type */ StartingOffset.QuadPart = 0; HalExamineMBR(DeviceObject, DiskGeometry.BytesPerSector, 0x55, &Data); if (Data) { /* If MBR is of the EZ Drive type, we'll read after it */ StartingOffset.QuadPart = DiskGeometry.BytesPerSector; ExFreePool(Data); } /* Allocate for reading enough data for checksum */ PartitionBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, DiskGeometry.BytesPerSector, TAG_IO); if (!PartitionBuffer) { ObDereferenceObject(FileObject); Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } /* Read a sector for computing checksum */ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, PartitionBuffer, DiskGeometry.BytesPerSector, &StartingOffset, &Event, &IoStatusBlock); if (!Irp) { ObDereferenceObject(FileObject); Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } /* Call the driver to perform reading */ KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } if (!NT_SUCCESS(Status)) { ExFreePool(DriveLayout); ExFreePoolWithTag(PartitionBuffer, TAG_IO); ObDereferenceObject(FileObject); continue; } ObDereferenceObject(FileObject); /* Calculate checksum, that's an easy computation, just adds read data */ for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG) ; i++) { CheckSum += PartitionBuffer[i]; } /* Browse each ARC disk */ for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink; NextEntry != &ArcDiskInformation->DiskSignatureListHead; NextEntry = NextEntry->Flink) { ArcDiskSignature = CONTAINING_RECORD(NextEntry, ARC_DISK_SIGNATURE, ListEntry); /* If they matches, ie * - There's only one disk for both BIOS and detected/enabled * - Signatures are matching * - Checksums are matching * - This is MBR */ if (((SingleDisk && DiskCount == 1) || (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature) && (ArcDiskSignature->CheckSum + CheckSum == 0))) && (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)) { /* Create device name */ sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", (DeviceNumber.DeviceNumber != 0xFFFFFFFF) ? DeviceNumber.DeviceNumber : DiskNumber); RtlInitAnsiString(&DeviceStringA, Buffer); Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* Create ARC name */ sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName); RtlInitAnsiString(&ArcNameStringA, ArcBuffer); Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(&DeviceStringW); goto Cleanup; } /* Link both */ IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW); /* And release resources */ RtlFreeUnicodeString(&ArcNameStringW); RtlFreeUnicodeString(&DeviceStringW); /* Now, browse for every partition */ for (i = 1; i <= DriveLayout->PartitionCount; i++) { /* Create device name */ sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", (DeviceNumber.DeviceNumber != 0xFFFFFFFF) ? DeviceNumber.DeviceNumber : DiskNumber, i); RtlInitAnsiString(&DeviceStringA, Buffer); Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* Create partial ARC name */ sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, i); RtlInitAnsiString(&ArcNameStringA, ArcBuffer); /* Is that boot device? */ if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE)) { DPRINT("Found boot device\n"); *FoundBoot = TRUE; } /* Is that system partition? */ if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE)) { /* Create HAL path name */ RtlInitAnsiString(&HalPathStringA, LoaderBlock->NtHalPathName); Status = RtlAnsiStringToUnicodeString(&HalPathStringW, &HalPathStringA, TRUE); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(&DeviceStringW); goto Cleanup; } /* Then store those information to registry */ IopStoreSystemPartitionInformation(&DeviceStringW, &HalPathStringW); RtlFreeUnicodeString(&HalPathStringW); } /* Create complete ARC name */ sprintf(ArcBuffer, "\\ArcName\\%spartition(%lu)", ArcDiskSignature->ArcName, i); RtlInitAnsiString(&ArcNameStringA, ArcBuffer); Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(&DeviceStringW); goto Cleanup; } /* Link device name & ARC name */ IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW); /* Release strings */ RtlFreeUnicodeString(&ArcNameStringW); RtlFreeUnicodeString(&DeviceStringW); } } else { /* In case there's a valid partition, a matching signature, BUT a none matching checksum, or there's a duplicate signature, or even worse a virus played with partition table */ if (ArcDiskSignature->Signature == Signature && (ArcDiskSignature->CheckSum + CheckSum != 0) && ArcDiskSignature->ValidPartitionTable) { DPRINT("Be careful, or you have a duplicate disk signature, or a virus altered your MBR!\n"); } } } /* Release memory before jumping to next item */ ExFreePool(DriveLayout); DriveLayout = NULL; ExFreePoolWithTag(PartitionBuffer, TAG_IO); PartitionBuffer = NULL; } Status = STATUS_SUCCESS; Cleanup: if (SymbolicLinkList) { ExFreePool(SymbolicLinkList); } if (DriveLayout) { ExFreePool(DriveLayout); } if (PartitionBuffer) { ExFreePoolWithTag(PartitionBuffer, TAG_IO); } return Status; }
NTSTATUS INIT_FUNCTION NTAPI IopCreateArcNamesCd(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PIRP Irp; KEVENT Event; NTSTATUS Status; PLIST_ENTRY NextEntry; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; LARGE_INTEGER StartingOffset; IO_STATUS_BLOCK IoStatusBlock; PULONG PartitionBuffer = NULL; CHAR Buffer[128], ArcBuffer[128]; BOOLEAN NotEnabledPresent = FALSE; STORAGE_DEVICE_NUMBER DeviceNumber; ANSI_STRING DeviceStringA, ArcNameStringA; PWSTR SymbolicLinkList, lSymbolicLinkList; PARC_DISK_SIGNATURE ArcDiskSignature = NULL; UNICODE_STRING DeviceStringW, ArcNameStringW; ULONG DiskNumber, CdRomCount, CheckSum, i, EnabledDisks = 0; PARC_DISK_INFORMATION ArcDiskInformation = LoaderBlock->ArcDiskInformation; /* Get all the Cds present in the system */ CdRomCount = IoGetConfigurationInformation()->CdRomCount; /* Get enabled Cds and check if result matches * For the record, enabled Cds (or even disk) are Cds/disks * that have been successfully handled by MountMgr driver * and that already own their device name. This is the "new" way * to handle them, that came with NT5. * Currently, Windows 2003 provides an arc names creation based * on both enabled drives and not enabled drives (lack from * the driver). * Given the current Odyssey state, that's good for us. * To sum up, this is NOT a hack or whatsoever. */ Status = IopFetchConfigurationInformation(&SymbolicLinkList, GUID_DEVINTERFACE_CDROM, CdRomCount, &EnabledDisks); if (!NT_SUCCESS(Status)) { NotEnabledPresent = TRUE; } /* Save symbolic link list address in order to free it after */ lSymbolicLinkList = SymbolicLinkList; /* For the moment, we won't fail */ Status = STATUS_SUCCESS; /* Browse all the ARC devices trying to find the one matching boot device */ for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink; NextEntry != &ArcDiskInformation->DiskSignatureListHead; NextEntry = NextEntry->Flink) { ArcDiskSignature = CONTAINING_RECORD(NextEntry, ARC_DISK_SIGNATURE, ListEntry); if (strcmp(LoaderBlock->ArcBootDeviceName, ArcDiskSignature->ArcName) == 0) { break; } ArcDiskSignature = NULL; } /* Not found... Not booting from a Cd */ if (!ArcDiskSignature) { DPRINT("Failed finding a cd that could match current boot device\n"); goto Cleanup; } /* Allocate needed space for reading Cd */ PartitionBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 2048, TAG_IO); if (!PartitionBuffer) { DPRINT("Failed allocating resources!\n"); /* Here, we fail, BUT we return success, some Microsoft joke */ goto Cleanup; } /* If we have more enabled Cds, take that into account */ if (EnabledDisks > CdRomCount) { CdRomCount = EnabledDisks; } /* If we'll have to browse for none enabled Cds, fix higher count */ if (NotEnabledPresent && !EnabledDisks) { CdRomCount += 5; } /* Finally, if in spite of all that work, we still don't have Cds, leave */ if (!CdRomCount) { goto Cleanup; } /* Start browsing Cds */ for (DiskNumber = 0, EnabledDisks = 0; DiskNumber < CdRomCount; DiskNumber++) { /* Check if we have an enabled disk */ if (SymbolicLinkList && *SymbolicLinkList != UNICODE_NULL) { /* Create its device name using first symbolic link */ RtlInitUnicodeString(&DeviceStringW, lSymbolicLinkList); /* Then, update symbolic links list */ lSymbolicLinkList += wcslen(lSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); /* Get its associated device object and file object */ Status = IoGetDeviceObjectPointer(&DeviceStringW, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject); /* Failure? Good bye! */ if (!NT_SUCCESS(Status)) { goto Cleanup; } /* Now, we'll ask the device its device number */ Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, DeviceObject, NULL, 0, &DeviceNumber, sizeof(STORAGE_DEVICE_NUMBER), FALSE, &Event, &IoStatusBlock); /* Failure? Good bye! */ if (!Irp) { /* Dereference file object before leaving */ ObDereferenceObject(FileObject); Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } /* Call the driver, and wait for it if needed */ KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } if (!NT_SUCCESS(Status)) { ObDereferenceObject(FileObject); goto Cleanup; } /* Finally, build proper device name */ sprintf(Buffer, "\\Device\\CdRom%lu", DeviceNumber.DeviceNumber); RtlInitAnsiString(&DeviceStringA, Buffer); Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); if (!NT_SUCCESS(Status)) { ObDereferenceObject(FileObject); goto Cleanup; } } else { /* Create device name for the cd */ sprintf(Buffer, "\\Device\\CdRom%lu", EnabledDisks++); RtlInitAnsiString(&DeviceStringA, Buffer); Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* Get its device object */ Status = IoGetDeviceObjectPointer(&DeviceStringW, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(&DeviceStringW); goto Cleanup; } } /* Initiate data for reading cd and compute checksum */ StartingOffset.QuadPart = 0x8000; CheckSum = 0; Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, PartitionBuffer, 2048, &StartingOffset, &Event, &IoStatusBlock); if (Irp) { /* Call the driver, and wait for it if needed */ KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* Reading succeed, compute checksum by adding data, 2048 bytes checksum */ if (NT_SUCCESS(Status)) { for (i = 0; i < 2048 / sizeof(ULONG); i++) { CheckSum += PartitionBuffer[i]; } } } /* Dereference file object */ ObDereferenceObject(FileObject); /* If checksums are matching, we have the proper cd */ if (CheckSum + ArcDiskSignature->CheckSum == 0) { /* Create ARC name */ sprintf(ArcBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName); RtlInitAnsiString(&ArcNameStringA, ArcBuffer); Status = RtlAnsiStringToUnicodeString(&ArcNameStringW, &ArcNameStringA, TRUE); if (NT_SUCCESS(Status)) { /* Create symbolic link */ IoCreateSymbolicLink(&ArcNameStringW, &DeviceStringW); RtlFreeUnicodeString(&ArcNameStringW); DPRINT1("Boot device found\n"); } /* And quit, whatever happens */ RtlFreeUnicodeString(&DeviceStringW); goto Cleanup; } /* Free string before trying another disk */ RtlFreeUnicodeString(&DeviceStringW); } Cleanup: if (PartitionBuffer) { ExFreePoolWithTag(PartitionBuffer, TAG_IO); } if (SymbolicLinkList) { ExFreePool(SymbolicLinkList); } return Status; }
IN PULONG pComPortNumber OPTIONAL, OUT PDEVICE_OBJECT* pFdo OPTIONAL) { PDEVICE_OBJECT Fdo = NULL; PSERIAL_DEVICE_EXTENSION DeviceExtension = NULL; NTSTATUS Status; WCHAR DeviceNameBuffer[32]; UNICODE_STRING DeviceName; TRACE_(SERIAL, "SerialAddDeviceInternal()\n"); ASSERT(DriverObject); ASSERT(Pdo); /* Create new device object */ swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu", IoGetConfigurationInformation()->SerialCount); RtlInitUnicodeString(&DeviceName, DeviceNameBuffer); Status = IoCreateDevice(DriverObject, sizeof(SERIAL_DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_SERIAL_PORT, FILE_DEVICE_SECURE_OPEN, FALSE, &Fdo); if (!NT_SUCCESS(Status)) { WARN_(SERIAL, "IoCreateDevice() failed with status 0x%08x\n", Status); Fdo = NULL; goto ByeBye; } DeviceExtension = (PSERIAL_DEVICE_EXTENSION)Fdo->DeviceExtension;
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: This routine is called at system initialization time to initialize this driver. Arguments: DriverObject - Supplies the driver object. RegistryPath - Supplies the registry path for this driver. Return Value: STATUS_SUCCESS - We could initialize at least one device. STATUS_NO_SUCH_DEVICE - We could not initialize even one device. --*/ { ULONG i; // // allocate the mutex to protect driver reference count // OpenCloseMutex = ExAllocatePool(NonPagedPool, sizeof(FAST_MUTEX)); if (!OpenCloseMutex) { // // NOTE - we could probably do without bailing here and just // leave a note for ourselves to never page out, but since we // don't have enough memory to allocate a mutex we should probably // avoid leaving the driver paged in at all times // return STATUS_INSUFFICIENT_RESOURCES; } ExInitializeFastMutex(OpenCloseMutex); for (i = 0; i < IoGetConfigurationInformation()->ParallelCount; i++) { ParInitializeDeviceObject(DriverObject, i); } if (!DriverObject->DeviceObject) { return STATUS_NO_SUCH_DEVICE; } // // Initialize the Driver Object with driver's entry points // DriverObject->MajorFunction[IRP_MJ_CREATE] = ParCreateOpen; DriverObject->MajorFunction[IRP_MJ_CLOSE] = ParClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ParDeviceControl; DriverObject->DriverUnload = ParUnload; // // page out the driver if we can // ParReleaseDriver(); return STATUS_SUCCESS; }