#include "precomp.h" #include // ¸¸¾à Çì´õ°¡ ¾ø¾î¼­ ÄÄÆÄÀÏ ¿¡·¯°¡ ³­´Ù¸é ¾Æ·¡ ÁÖ¼®À» ÇØÁ¦ÇÏ¿© »ç¿ëÇϼ¼¿ä. /* DEFINE_DEVPROPKEY(DEVPKEY_Device_InstanceId, 0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57, 256); */ NTSTATUS GetPhysicalDiskDeviceObject( __in PDEVICE_OBJECT VolumeDeviceObject, __out PDEVICE_OBJECT* PhysicalDiskDeviceObject ) { NTSTATUS status; PIRP Irp; KEVENT Event; IO_STATUS_BLOCK Iosb; PVOLUME_DISK_EXTENTS pDiskExtents = NULL; // ³Ë³ËÇÏ°Ô 4°³ Á¤µµÀÇ Extent °ø°£ È®º¸ ULONG extentsSize = sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * 4); UNICODE_STRING physicalDiskName; WCHAR nameBuffer[64] = { 0 }; PFILE_OBJECT pFileObject = NULL; PDEVICE_OBJECT pDevObj = NULL; *PhysicalDiskDeviceObject = NULL; // 1. ¸Þ¸ð¸® ÇÒ´ç pDiskExtents = (PVOLUME_DISK_EXTENTS)ExAllocatePoolWithTag(NonPagedPool, extentsSize, 'dExt'); if (!pDiskExtents) return STATUS_INSUFFICIENT_RESOURCES; // ¸Þ¸ð¸® ÃʱâÈ­ (Áß¿ä) RtlZeroMemory(pDiskExtents, extentsSize); KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = IoBuildDeviceIoControlRequest( IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, VolumeDeviceObject, NULL, 0, pDiskExtents, extentsSize, FALSE, &Event, &Iosb ); if (!Irp) { ExFreePoolWithTag(pDiskExtents, 'dExt'); return STATUS_INSUFFICIENT_RESOURCES; } status = IoCallDriver(VolumeDeviceObject, Irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); status = Iosb.Status; } if (!NT_SUCCESS(status)) { ExFreePoolWithTag(pDiskExtents, 'dExt'); return status; } // [BSOD ¹æÁö ÇÙ½É] Extents °³¼ö È®ÀÎ! if (pDiskExtents->NumberOfDiskExtents == 0) { KLogEx(DEBUG_TRACE_INFO, "No Disk Extents found.\n"); ExFreePoolWithTag(pDiskExtents, 'dExt'); return STATUS_UNSUCCESSFUL; } __try { // 2. ¹°¸® µð½ºÅ© À̸§ »ý¼º ULONG diskNumber = pDiskExtents->Extents[0].DiskNumber; // ¾ÈÀüÇÑ ¹®ÀÚ¿­ ÇÔ¼ö »ç¿ë if (!NT_SUCCESS(RtlStringCbPrintfW(nameBuffer, sizeof(nameBuffer), L"\\Device\\Harddisk%u\\DR0", diskNumber))) { status = STATUS_BUFFER_OVERFLOW; __leave; } RtlInitUnicodeString(&physicalDiskName, nameBuffer); KLogEx(DEBUG_TRACE_INFO, "Trying to open: %S\n", nameBuffer); // 3. µð¹ÙÀ̽º Æ÷ÀÎÅÍ È¹µæ (°¡Àå À§ÇèÇÑ ±¸°£) // InstanceSetup¿¡¼­ ÀÌ È£ÃâÀÌ À§ÇèÇÒ ¼ö ÀÖÀ¸¹Ç·Î ½ÇÆÐ ½Ã Áï½Ã ºüÁ®³ª¿È status = IoGetDeviceObjectPointer( &physicalDiskName, FILE_READ_ATTRIBUTES, // ±ÇÇÑ ÃÖ¼ÒÈ­ &pFileObject, &pDevObj ); if (NT_SUCCESS(status)) { ObReferenceObject(pDevObj); // µð¹ÙÀ̽º °´Ã¼ ÂüÁ¶ ObDereferenceObject(pFileObject); // ÆÄÀÏ °´Ã¼ ´Ý±â *PhysicalDiskDeviceObject = pDevObj; } else { KLogEx(DEBUG_TRACE_ERROR, "IoGetDeviceObjectPointer Failed: 0x%x\n", status); } } __except (EXCEPTION_EXECUTE_HANDLER) { KLogEx(DEBUG_TRACE_ERROR, "Exception in GetPhysicalDiskDeviceObject\n"); status = STATUS_UNHANDLED_EXCEPTION; } ExFreePoolWithTag(pDiskExtents, 'dExt'); return status; } NTSTATUS QueryDeviceProperty( __in PDEVICE_OBJECT pDevice, __in DEVICE_REGISTRY_PROPERTY DevProperty, __out PVOID* ppBuffer, __out PULONG pResultLength ) { NTSTATUS status; PVOID pBuffer = NULL; ULONG BufferSize = 0; PDEVICE_OBJECT pdo = NULL; ASSERT(ARGUMENT_PRESENT(pDevice)); // sskim - 171122 Added. // FltGetDiskDeviceObject·Î ±¸ÇÑ pDevice´Â PDO¿©¼­ Verifier¿¡¼­ ÅÍÁü (FDO·Î °¡Á®¿À°Ô Ãß°¡) pdo = IoGetDeviceAttachmentBaseRef(pDevice); status = IoGetDeviceProperty( pdo, DevProperty, BufferSize, NULL, &BufferSize ); if (NT_SUCCESS(status)) { ObDereferenceObject(pdo); return STATUS_NOT_SUPPORTED; } while (status == STATUS_BUFFER_TOO_SMALL) { pBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, _ALLOC_TAG); if (!pBuffer) { ObDereferenceObject(pdo); return STATUS_NO_MEMORY; } status = IoGetDeviceProperty( pdo, DevProperty, BufferSize, pBuffer, &BufferSize ); if (NT_SUCCESS(status)) { *ppBuffer = pBuffer; *pResultLength = BufferSize; ObDereferenceObject(pdo); return status; } ExFreePool(pBuffer); pBuffer = NULL; } ASSERT(!pBuffer); ObDereferenceObject(pdo); return status; } //#define QUERY_BUFFER_SIZE 0x2000 //NTSTATUS SafeSetVolumContextParam(PUCHAR pucDest, DWORD dwSize, PUCHAR pucSrc, DWORD dwOffset) //{ // int size = 0; // PCHAR pszName = NULL; // // if (dwOffset == 0) // return STATUS_UNSUCCESSFUL; // // if (dwOffset >= dwSize) // return STATUS_UNSUCCESSFUL; // // if (dwOffset >= (QUERY_BUFFER_SIZE - 10)) // return STATUS_UNSUCCESSFUL; // // pszName = (char*)GetPtr(pucSrc, dwOffset); // size = (int)strlen(pszName); // // KLogEx(DEBUG_TRACE_INFO, "SafeSetVolumContextParam, size(%d)\n", size); // // if (size > VOLUME_DESCRIPTION_LENGTH) // { // size = VOLUME_DESCRIPTION_LENGTH - 1; // } // // RtlCopyMemory(pucDest, pszName, size); // return STATUS_SUCCESS; //} // ¸ÅÅ©·Î Á¤ÀÇ (¾ø´Ù¸é Ãß°¡ ÇÊ¿ä) #ifndef QUERY_BUFFER_SIZE #define QUERY_BUFFER_SIZE 0x2000 #endif // ¾ÈÀüÇÑ Æ÷ÀÎÅÍ °è»ê ¹× º¹»ç ÇÔ¼ö (´ë¹®ÀÚ º¯È¯ Æ÷ÇÔ) NTSTATUS SafeSetVolumContextParam( __in PUCHAR pucDest, // ´ë»ó ¹öÆÛ (Context ³» º¯¼ö) __in ULONG ulSrcTotalSize, // ¿øº» Àüü ¹öÆÛ Å©±â (pDesc->Size) __in PUCHAR pucSrcBase, // ¿øº» ¹öÆÛ ½ÃÀÛ ÁÖ¼Ò (pDesc) __in ULONG ulOffset // ¹®ÀÚ¿­ ¿ÀÇÁ¼Â ) { ULONG i = 0; ULONG destIndex = 0; PCHAR pSrcStr = NULL; BOOLEAN bLeadingSpace = TRUE; // ¾Õ °ø¹é ¿©ºÎ Ç÷¡±× ULONG lastNonSpaceIndex = 0; // ¸¶Áö¸·À¸·Î °ø¹éÀÌ ¾Æ´Ñ ¹®ÀÚÀÇ À妽º // 1. ¿ÀÇÁ¼Â À¯È¿¼º °Ë»ç if (ulOffset == 0 || ulOffset >= ulSrcTotalSize) { if (pucDest) pucDest[0] = 0; return STATUS_SUCCESS; } // 2. ¹®ÀÚ¿­ ½ÃÀÛ Æ÷ÀÎÅÍ °è»ê pSrcStr = (PCHAR)(pucSrcBase + ulOffset); // 3. º¹»ç ·çÇÁ (´ë¹®ÀÚ º¯È¯ + ¾Õ °ø¹é Á¦°Å) for (i = 0; i < VOLUME_DESCRIPTION_LENGTH - 1; i++) { // A. ¿øº» ¹öÆÛ ¹üÀ§ üũ (Overflow ¹æÁö) if ((ULONG_PTR)(pSrcStr + i) >= (ULONG_PTR)(pucSrcBase + ulSrcTotalSize)) break; // B. ¿øº» ¹®ÀÚ¿­ ³¡(NULL) üũ if (pSrcStr[i] == 0) break; // ¹®ÀÚ °¡Á®¿À±â CHAR c = pSrcStr[i]; // [Trim Start] ¾ÕÂÊ °ø¹é Á¦°Å ·ÎÁ÷ if (bLeadingSpace) { if (c == ' ' || c == '\t' || c == '\r' || c == '\n') { continue; // ¾ÕÂÊ °ø¹éÀº °Ç³Ê¶Ü } else { bLeadingSpace = FALSE; // °ø¹éÀÌ ¾Æ´Ñ ¹®ÀÚ¸¦ óÀ½ ¸¸³² -> ÀÌÁ¦ºÎÅÍ º¹»ç ½ÃÀÛ } } // [´ë¹®ÀÚ º¯È¯] ¹× º¹»ç pucDest[destIndex] = RtlUpperChar(c); // [Trim End Áغñ] °ø¹éÀÌ ¾Æ´Ñ ¹®ÀÚÀÇ À§Ä¡¸¦ ±â¾ï if (pucDest[destIndex] != ' ' && pucDest[destIndex] != '\t' && pucDest[destIndex] != '\r' && pucDest[destIndex] != '\n') { lastNonSpaceIndex = destIndex; } destIndex++; } // 4. [Trim End] µÚÂÊ °ø¹é Á¦°Å ¹× NULL Termination // º¹»çµÈ ³»¿ëÀÌ Çϳª¶óµµ ÀÖ´Ù¸é, ¸¶Áö¸· °ø¹éÀÌ ¾Æ´Ñ ¹®ÀÚ ´ÙÀ½À» NULL·Î ¸¸µê if (destIndex > 0 && !bLeadingSpace) { pucDest[lastNonSpaceIndex + 1] = 0; } else { // °ø¹é¸¸ ÀÖ¾ú°Å³ª ºó ¹®ÀÚ¿­ÀÎ °æ¿ì pucDest[0] = 0; } KLogEx(DEBUG_TRACE_INFO, "Copied Length(%d), Content(%s)\n", lastNonSpaceIndex + 1, pucDest); return STATUS_SUCCESS; } typedef struct _STORAGE_DEVICE_ID_DESCRIPTOR { ULONG Version; ULONG Size; ULONG NumberOfIdentifiers; UCHAR Identifiers[1]; // °¡º¯ ±æÀÌ ¹®ÀÚ¿­ ¹è¿­ } STORAGE_DEVICE_ID_DESCRIPTOR, * PSTORAGE_DEVICE_ID_DESCRIPTOR; NTSTATUS GetStorageDeviceId( __in PDEVICE_OBJECT DeviceObject, __out PWCHAR* OutInstanceId ) { NTSTATUS status = STATUS_SUCCESS; PIRP Irp; KEVENT Event; IO_STATUS_BLOCK Iosb; STORAGE_PROPERTY_QUERY PropQuery = { 0 }; PSTORAGE_DEVICE_ID_DESCRIPTOR pDesc = NULL; PVOID QueryBuffer = NULL; ULONG QuerySize = 1024; // ³Ë³ËÇÏ°Ô ÀâÀ½ PDEVICE_OBJECT pTopDevice = NULL; *OutInstanceId = NULL; pTopDevice = IoGetAttachedDeviceReference(DeviceObject); // 1. ¸Þ¸ð¸® ÇÒ´ç QueryBuffer = ExAllocatePoolWithTag(PagedPool, QuerySize, 'StoI'); if (!QueryBuffer) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(QueryBuffer, QuerySize); // 2. Äõ¸® ¼³Á¤: StorageDeviceIdProperty (Áß¿ä!) PropQuery.PropertyId = StorageDeviceIdProperty; // enum °ª: 2 PropQuery.QueryType = PropertyStandardQuery; KeInitializeEvent(&Event, NotificationEvent, FALSE); // 3. IRP »ý¼º ¹× Àü¼Û Irp = IoBuildDeviceIoControlRequest( IOCTL_STORAGE_QUERY_PROPERTY, pTopDevice, &PropQuery, sizeof(PropQuery), QueryBuffer, QuerySize, FALSE, &Event, &Iosb ); if (!Irp) { ExFreePoolWithTag(QueryBuffer, 'StoI'); return STATUS_INSUFFICIENT_RESOURCES; } status = IoCallDriver(pTopDevice, Irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); status = Iosb.Status; } // 4. °á°ú ÆÄ½Ì if (NT_SUCCESS(status) && Iosb.Information > sizeof(STORAGE_DEVICE_ID_DESCRIPTOR)) { pDesc = (PSTORAGE_DEVICE_ID_DESCRIPTOR)QueryBuffer; if (pDesc->NumberOfIdentifiers > 0) { // Identifiers´Â Null·Î ±¸ºÐµÈ ANSI ¹®ÀÚ¿­µéÀÇ ¹è¿­ÀÔ´Ï´Ù. // ù ¹øÂ° ¹®ÀÚ¿­ÀÌ º¸Åë °¡Àå ±¸Ã¼ÀûÀÎ PnP ID (Hardware ID)ÀÔ´Ï´Ù. PCHAR pAnsiId = (PCHAR)pDesc->Identifiers; // ANSI String -> Unicode String º¯È¯ ÇÊ¿ä ANSI_STRING ansiStr; UNICODE_STRING uniStr; RtlInitAnsiString(&ansiStr, pAnsiId); status = RtlAnsiStringToUnicodeString(&uniStr, &ansiStr, TRUE); // TRUE: Allocate Memory if (NT_SUCCESS(status)) { // È£ÃâÀÚ¿¡°Ô Àü´Þ (È£ÃâÀÚ°¡ ³ªÁß¿¡ ExFreePool ÇØ¾ß ÇÔ) // RtlAnsiStringToUnicodeStringÀÌ ÇÒ´çÇÑ ¹öÆÛ´Â PagedPoolÀÔ´Ï´Ù. // ¿©±â¼­´Â È£ÃâÀÚ°¡ ÆíÇÏ°Ô ¾²µµ·Ï »õ ¹öÆÛ¿¡ º¹»çÇϰųª, uniStr.Buffer¸¦ ±×´ë·Î ÁÝ´Ï´Ù. // ¾ÈÀüÇÏ°Ô º¹»çº»À» ¸¸µé¾î ¸®ÅÏ (NonPagedPool ±ÇÀå ½Ã) ULONG uniSize = uniStr.Length + sizeof(WCHAR); PWCHAR pResult = ExAllocatePoolWithTag(NonPagedPool, uniSize, 'IDst'); if (pResult) { RtlZeroMemory(pResult, uniSize); RtlCopyMemory(pResult, uniStr.Buffer, uniStr.Length); *OutInstanceId = pResult; } RtlFreeUnicodeString(&uniStr); // Àӽà º¯È¯ ¹öÆÛ ÇØÁ¦ } } } ExFreePoolWithTag(QueryBuffer, 'StoI'); return status; } NTSTATUS GetStorageProperty( __in PDEVICE_OBJECT device_object, __in PVOLUME_CONTEXT pVolumeContext ) { PIRP Irp; KEVENT Event; NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK Iosb; STORAGE_PROPERTY_QUERY PropQuery = { 0, }; PVOID QueryBuffer = NULL; ULONG QuerySize = QUERY_BUFFER_SIZE; PSTORAGE_DEVICE_DESCRIPTOR pDesc; //PDEVICE_OBJECT pTopDevice = NULL; //ULONG size = 0; __try { //pTopDevice = IoGetAttachedDeviceReference(device_object); QueryBuffer = ExAllocatePoolWithTag(PagedPool, QuerySize, _ALLOC_TAG); if (!QueryBuffer) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } RtlZeroMemory(&PropQuery, sizeof(PropQuery)); RtlZeroMemory(QueryBuffer, QuerySize); PropQuery.PropertyId = StorageDeviceProperty; PropQuery.QueryType = PropertyStandardQuery; KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = IoBuildDeviceIoControlRequest( IOCTL_STORAGE_QUERY_PROPERTY, device_object, &PropQuery, sizeof(PropQuery), QueryBuffer, QuerySize, FALSE, &Event, &Iosb ); if (!Irp) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } status = IoCallDriver(device_object, Irp); if (status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL ); status = Iosb.Status; } if (!NT_SUCCESS(status)) { __leave; } if (Iosb.Information < sizeof(STORAGE_DEVICE_DESCRIPTOR)) { status = STATUS_UNSUCCESSFUL; __leave; } pDesc = (PSTORAGE_DEVICE_DESCRIPTOR)QueryBuffer; if (!pDesc) __leave; if (pDesc->Size > Iosb.Information) { if (pDesc->Size > QuerySize) pDesc->Size = (ULONG)Iosb.Information; } KLogEx(DEBUG_TRACE_INFO, "Version(%x),Size(%x),DeviceType(%x),DeviceTypeModifier(%x)\n", pDesc->Version, pDesc->Size, pDesc->DeviceType, pDesc->DeviceTypeModifier); KLogEx(DEBUG_TRACE_INFO, "bustype(%d),Removal(%d),vidoffset(%x),pidoffset(%x)\n", pDesc->BusType, pDesc->RemovableMedia, pDesc->VendorIdOffset, pDesc->ProductIdOffset); KLogEx(DEBUG_TRACE_INFO, "ProductRevisionOffset(%d),SerialNumberOffset(%d)\n", pDesc->ProductRevisionOffset, pDesc->SerialNumberOffset); pVolumeContext->bustype = pDesc->BusType; SafeSetVolumContextParam(pVolumeContext->vendorid, pDesc->Size, (PUCHAR)pDesc, pDesc->VendorIdOffset); SafeSetVolumContextParam(pVolumeContext->productid, pDesc->Size, (PUCHAR)pDesc, pDesc->ProductIdOffset); SafeSetVolumContextParam(pVolumeContext->productrevisionlevel, pDesc->Size, (PUCHAR)pDesc, pDesc->ProductRevisionOffset); SafeSetVolumContextParam(pVolumeContext->vendorspecific, pDesc->Size, (PUCHAR)pDesc, pDesc->SerialNumberOffset); } __finally { if (QueryBuffer) { ExFreePoolWithTag(QueryBuffer, _ALLOC_TAG); QueryBuffer = NULL; } } return status; } typedef struct _GET_ID_WORK_CONTEXT { PFLT_FILTER Filter; PFLT_INSTANCE Instance; // ÀνºÅϽº ÇÚµé (ÄÁÅØ½ºÆ® Á¢±Ù¿ë) PDEVICE_OBJECT VolumeDeviceObject; // º¼·ý µð¹ÙÀ̽º } GET_ID_WORK_CONTEXT, * PGET_ID_WORK_CONTEXT; // [ÀÛ¾÷ÀÚ ½º·¹µå ÇÔ¼ö] ¿©±â¼­ ¾ÈÀüÇÏ°Ô Hardware ID¸¦ ±¸ÇÕ´Ï´Ù. VOID Bs1FltGetHardwareIdWorker( __in PFLT_GENERIC_WORKITEM FltWorkItem, __in PVOID ConnectionCookie, __in PVOID Context_ ) { PGET_ID_WORK_CONTEXT pWorkCtx = (PGET_ID_WORK_CONTEXT)Context_; PVOLUME_CONTEXT pVolumeCtx = NULL; PDEVICE_OBJECT pPhysicalDisk = NULL; PDEVICE_OBJECT pPhysicalPDO = NULL; NTSTATUS status; PWCHAR pHardwareId = NULL; ULONG PropertySize = 0; UNREFERENCED_PARAMETER(ConnectionCookie); KLogEx(DEBUG_TRACE_INFO, "[Worker] Starting to query Hardware ID async...\n"); // 1. ÀνºÅϽº ÄÁÅØ½ºÆ® °¡Á®¿À±â status = FltGetInstanceContext(pWorkCtx->Instance, &pVolumeCtx); if (NT_SUCCESS(status)) { // 2. ¹°¸® µð½ºÅ© °´Ã¼ ±¸Çϱâ (ÀÌÁ¦ ¾ÈÀüÇÔ!) // (ÀÌÀü¿¡ ¸¸µç GetPhysicalDiskDeviceObject ÇÔ¼ö »ç¿ë) status = GetPhysicalDiskDeviceObject(pWorkCtx->VolumeDeviceObject, &pPhysicalDisk); if (NT_SUCCESS(status) && pPhysicalDisk != NULL) { // 3. PDO ã±â pPhysicalPDO = IoGetDeviceAttachmentBaseRef(pPhysicalDisk); if (pPhysicalPDO) { // 4. Hardware ID Äõ¸® status = QueryDeviceProperty(pPhysicalPDO, DevicePropertyHardwareID, &pHardwareId, &PropertySize); if (NT_SUCCESS(status) && pHardwareId) { KLogEx(DEBUG_TRACE_INFO, "[Worker] Found Real Hardware ID: %S\n", pHardwareId); // TODO: pVolumeCtx¿¡ ID ÀúÀå (ÇÊ¿ä½Ã ÆÄ½Ì) // ¿¹: RtlStringCbCopyW(pVolumeCtx->HardwareId, ...); ExFreePool(pHardwareId); } ObDereferenceObject(pPhysicalPDO); } ObDereferenceObject(pPhysicalDisk); } else { KLogEx(DEBUG_TRACE_INFO, "[Worker] Failed to get Physical Disk: 0x%x\n", status); } // ÄÁÅØ½ºÆ® ÇØÁ¦ FltReleaseContext(pVolumeCtx); } // 3. Á¤¸® ObDereferenceObject(pWorkCtx->VolumeDeviceObject); FltObjectDereference(pWorkCtx->Instance); // ÀνºÅϽº ÂüÁ¶ ÇØÁ¦ FltFreeGenericWorkItem(FltWorkItem); ExFreePool(pWorkCtx); } NTSTATUS GetVolumeProperties( __in PCFLT_RELATED_OBJECTS FltObjects, __in PVOLUME_CONTEXT pVolumeContext ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT pDevice = NULL; PVOID pBuffer = NULL; ULONG PropertySize = 0; //PWCHAR pDeviceId = NULL; //PDEVICE_OBJECT physicalDeviceObject = NULL; ASSERT(ARGUMENT_PRESENT(pVolumeContext)); __try { status = FltGetDiskDeviceObject(FltObjects->Volume, &pDevice); if (!NT_SUCCESS(status)) { pDevice = NULL; __leave; } //status = GetPhysicalDiskDeviceObject((PDEVICE_OBJECT)FltObjects->Volume, &pDevice); status = GetStorageProperty(pDevice, pVolumeContext); status = QueryDeviceProperty(pDevice, DevicePropertyRemovalPolicy, &pBuffer, &PropertySize); if (NT_SUCCESS(status)) { PDEVICE_REMOVAL_POLICY pRemovalPolicy = (PDEVICE_REMOVAL_POLICY)pBuffer; pVolumeContext->removalpolicy = *pRemovalPolicy; //pVolumeContext->device_object = pDevice; KLogEx(DEBUG_TRACE_INFO, " REMOVAL_POLICY pDevice(%p),removalpolicy(%d)\n", pDevice, pVolumeContext->removalpolicy); ExFreePoolWithTag(pBuffer, _ALLOC_TAG); pBuffer = NULL; } else { KLogEx(DEBUG_TRACE_INFO, "Query DevicePropertyRemovalPolicy Failed 0x%x\n", status); } status = QueryDeviceProperty(pDevice, DevicePropertyFriendlyName, &pBuffer, &PropertySize); if (NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_INFO, "DevicePropertyFriendlyName(%S)\n", (wchar_t*)pBuffer); ExFreePoolWithTag(pBuffer, _ALLOC_TAG); pBuffer = NULL; } else { KLogEx(DEBUG_TRACE_INFO, "Query DevicePropertyRemovalPolicy Failed 0x%x\n", status); } status= QueryDeviceProperty(pDevice, DevicePropertyDeviceDescription, &pBuffer, &PropertySize); if (NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_INFO, "DevicePropertyDeviceDescription(%S)\n", (wchar_t*)pBuffer); ExFreePoolWithTag(pBuffer, _ALLOC_TAG); pBuffer = NULL; } else { KLogEx(DEBUG_TRACE_INFO, "Query DevicePropertyRemovalPolicy Failed 0x%x\n", status); } status = QueryDeviceProperty(pDevice, DevicePropertyHardwareID, &pBuffer, &PropertySize); if (NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_INFO, "DevicePropertyHardwareID(%S)\n", (wchar_t*)pBuffer); ExFreePoolWithTag(pBuffer, _ALLOC_TAG); pBuffer = NULL; } else { KLogEx(DEBUG_TRACE_INFO, "Query DevicePropertyRemovalPolicy Failed 0x%x\n", status); } status = QueryDeviceProperty(pDevice, DevicePropertyEnumeratorName, &pBuffer, &PropertySize); if (NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_INFO, "DevicePropertyEnumeratorName(%S)\n", (wchar_t*)pBuffer); ExFreePoolWithTag(pBuffer, _ALLOC_TAG); pBuffer = NULL; } else { KLogEx(DEBUG_TRACE_INFO, "Query DevicePropertyRemovalPolicy Failed 0x%x\n", status); } //status = GetStorageDeviceId(pDevice, &pDeviceId); //if (NT_SUCCESS(status) && pDeviceId != NULL) //{ // KLogEx(DEBUG_TRACE_INFO, "Found Device ID: %S\n", pDeviceId); // // °á°ú ¿¹½Ã: "USB\VID_346D&PID_5678&REV_0100" // // ¿©±â¼­ ¹®ÀÚ¿­ ÆÄ½ÌÇÏ¿© Á¤Ã¥ Àû¿ë // ExFreePoolWithTag(pDeviceId, 'IDst'); //} //else //{ // KLogEx(DEBUG_TRACE_INFO, "[IOCTL] Failed 0x%x. Trying PnP Query...\n", status); // // ================================================================= // // ½Ãµµ 2: PnP ¹æ½Ä (PDO¿¡°Ô ¿äû) - HardwareID / InstanceID // // ================================================================= // // IOCTLÀ» ó¸®ÇÏ´Â FDOÀÇ °¡Àå ¹Ø¹Ù´Ú(PDO)À» ±¸ÇÕ´Ï´Ù. // physicalDeviceObject = IoGetDeviceAttachmentBaseRef(pDevice); // if (physicalDeviceObject) // { // // PnP Äõ¸®´Â PDO¿¡°Ô ÇØ¾ß ÇÕ´Ï´Ù. // // DevicePropertyHardwareID (¸®½ºÆ®) ¶Ç´Â DevicePropertyInstanceID (´ÜÀÏ) ½Ãµµ // PWCHAR pHardwareId = NULL; // // º¸Åë HardwareID°¡ °¡Àå È®½ÇÇÏ°Ô Á¤º¸(VID/PID)¸¦ ÁÝ´Ï´Ù. // // HardwareID´Â MULTI_SZ Çü½ÄÀ̹ǷΠù ¹øÂ° ¹®ÀÚ¿­¸¸ ¾²¸é µË´Ï´Ù. // status = QueryDeviceProperty(physicalDeviceObject, DevicePropertyHardwareID, &pHardwareId, &PropertySize); // if (NT_SUCCESS(status) && pHardwareId) // { // KLogEx(DEBUG_TRACE_INFO, "[PnP] Hardware ID: %S\n", pHardwareId); // ExFreePoolWithTag(pHardwareId, _ALLOC_TAG); // } // else // { // KLogEx(DEBUG_TRACE_INFO, "[PnP] Query DevicePropertyHardwareID Failed 0x%x\n", status); // } // ObDereferenceObject(physicalDeviceObject); // } //} status = STATUS_SUCCESS; } __finally { if (pDevice) ObDereferenceObject(pDevice); } return status; } // ----------------------------------------------------------------------------- // Helper: PnP ¼Ó¼º(Registry Property) Á¶È¸ ÇÔ¼ö // ÁÖÀÇ: ¹Ýµå½Ã PDO(Physical Device Object)¸¦ ³Ñ°ÜÁà¾ß Á¤È®ÇÑ °ªÀÌ ³ª¿É´Ï´Ù. // ----------------------------------------------------------------------------- NTSTATUS QueryDeviceRegistryProperty( __in PDEVICE_OBJECT pPdo, __in DEVICE_REGISTRY_PROPERTY DeviceProperty, __out PWCHAR pBuffer, __in ULONG BufferLength ) { NTSTATUS status; ULONG ResultLength = 0; // ¹öÆÛ ÃʱâÈ­ RtlZeroMemory(pBuffer, BufferLength); status = IoGetDeviceProperty( pPdo, DeviceProperty, BufferLength, pBuffer, &ResultLength ); return status; } // ----------------------------------------------------------------------------- // Helper: ½ºÅ丮Áö ¼Ó¼º(IOCTL) Á¶È¸ ÇÔ¼ö // ÁÖÀÇ: IOCTLÀ» ó¸®ÇÒ ¼ö ÀÖ´Â ½ºÅà »ó´Ü(Top Device) ȤÀº FDO¿¡ º¸³»¾ß ÇÕ´Ï´Ù. // ----------------------------------------------------------------------------- NTSTATUS GetStorageHardwareProperty( __in PDEVICE_OBJECT pDeviceObject, __inout PFULL_DISK_INFO pInfo ) { NTSTATUS status = STATUS_SUCCESS; PIRP Irp; KEVENT Event; IO_STATUS_BLOCK Iosb; STORAGE_PROPERTY_QUERY Query = { 0 }; PSTORAGE_DEVICE_DESCRIPTOR pDesc = NULL; PVOID pBuffer = NULL; ULONG BufferSize = 1024; // ³Ë³ËÇÏ°Ô ÀâÀ½ // ¹öÆÛ ÇÒ´ç pBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, _ALLOC_TAG); if (!pBuffer) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(pBuffer, BufferSize); // Äõ¸® ¼³Á¤ Query.PropertyId = StorageDeviceProperty; Query.QueryType = PropertyStandardQuery; KeInitializeEvent(&Event, NotificationEvent, FALSE); // IOCTL »ý¼º Irp = IoBuildDeviceIoControlRequest( IOCTL_STORAGE_QUERY_PROPERTY, pDeviceObject, &Query, sizeof(Query), pBuffer, BufferSize, FALSE, &Event, &Iosb ); if (!Irp) { ExFreePoolWithTag(pBuffer, _ALLOC_TAG); return STATUS_INSUFFICIENT_RESOURCES; } // µå¶óÀ̹ö È£Ãâ status = IoCallDriver(pDeviceObject, Irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); status = Iosb.Status; } if (NT_SUCCESS(status)) { pDesc = (PSTORAGE_DEVICE_DESCRIPTOR)pBuffer; pInfo->BusType = pDesc->BusType; pInfo->RemovableMedia = pDesc->RemovableMedia; SafeSetVolumContextParam((PUCHAR)pInfo->VendorId, pDesc->Size, (PUCHAR)pDesc, pDesc->VendorIdOffset); SafeSetVolumContextParam((PUCHAR)pInfo->ProductId, pDesc->Size, (PUCHAR)pDesc, pDesc->ProductIdOffset); SafeSetVolumContextParam((PUCHAR)pInfo->Productrevisionlevel, pDesc->Size, (PUCHAR)pDesc, pDesc->ProductRevisionOffset); SafeSetVolumContextParam((PUCHAR)pInfo->SerialNumber, pDesc->Size, (PUCHAR)pDesc, pDesc->SerialNumberOffset); } ExFreePoolWithTag(pBuffer, _ALLOC_TAG); return status; } NTSTATUS GetDeviceInstanceId( __in PDEVICE_OBJECT pDeviceObject, __in const DEVPROPKEY* pKey, __out PWCHAR pBuffer, __in ULONG BufferLength ) { NTSTATUS status; //PDEVICE_OBJECT pPdo = NULL; ULONG returnLength = 0; DEVPROPTYPE propType; //// 1. PDO ±¸Çϱâ (Çʼö) //pPdo = IoGetDeviceAttachmentBaseRef(pDeviceObject); //if (pPdo == NULL) //{ // return STATUS_NO_SUCH_DEVICE; //} // 2. IoGetDevicePropertyData È£Ãâ (Vista ÀÌ»ó Áö¿ø) // DEVPKEY_Device_InstanceId ۸¦ »ç¿ëÇÏ¿© ÀνºÅϽº °æ·Î¸¦ ¿äûÇÕ´Ï´Ù. status = IoGetDevicePropertyData( pDeviceObject, pKey, LOCALE_NEUTRAL, 0, BufferLength, pBuffer, &returnLength, &propType ); // 3. ÂüÁ¶ ÇØÁ¦ //ObDereferenceObject(pPdo); return status; } NTSTATUS GetUsbIdFromVolume( __in PDEVICE_OBJECT pVolumeDeviceObject, __out PWCHAR pBuffer, __in ULONG BufferLength ) { NTSTATUS status; PIRP pIrp; KEVENT event; IO_STATUS_BLOCK ioStatus; PVOLUME_DISK_EXTENTS pExtents = NULL; ULONG extentsSize = sizeof(VOLUME_DISK_EXTENTS) + sizeof(DISK_EXTENT) * 4; // ³Ë³ËÇÏ°Ô ÀâÀ½ UNICODE_STRING diskName; WCHAR nameBuffer[64]; PFILE_OBJECT pDiskFileObject = NULL; PDEVICE_OBJECT pDiskDeviceObject = NULL; PDEVICE_OBJECT pDiskPdo = NULL; // --------------------------------------------------------- // 1´Ü°è: º¼·ýÀÌ À§Ä¡ÇÑ µð½ºÅ© ¹øÈ£ ¾Ë¾Æ³»±â (IOCTL) // --------------------------------------------------------- pExtents = (PVOLUME_DISK_EXTENTS)ExAllocatePoolWithTag(NonPagedPool, extentsSize, 'Tag1'); if (!pExtents) return STATUS_INSUFFICIENT_RESOURCES; KeInitializeEvent(&event, NotificationEvent, FALSE); // º¼·ý µå¶óÀ̹ö ½ºÅÃÀÇ ÃÖ»ó´Ü ÀåÄ¡ ±¸Çϱâ (IOCTL Àü¼Û¿ë) PDEVICE_OBJECT pTopDevice = IoGetAttachedDeviceReference(pVolumeDeviceObject); pIrp = IoBuildDeviceIoControlRequest( IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, pTopDevice, NULL, 0, pExtents, extentsSize, FALSE, &event, &ioStatus ); if (pIrp == NULL) { ObDereferenceObject(pTopDevice); ExFreePool(pExtents); return STATUS_INSUFFICIENT_RESOURCES; } status = IoCallDriver(pTopDevice, pIrp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = ioStatus.Status; } ObDereferenceObject(pTopDevice); // ÂüÁ¶ ÇØÁ¦ if (!NT_SUCCESS(status) || pExtents->NumberOfDiskExtents == 0) { ExFreePool(pExtents); return status; // µð½ºÅ© Á¤º¸¸¦ ¾òÀ» ¼ö ¾øÀ½ } // --------------------------------------------------------- // 2´Ü°è: µð½ºÅ© ¹øÈ£·Î ¹°¸® µð½ºÅ© ÀåÄ¡ °´Ã¼(Pointer) ¾ò±â // --------------------------------------------------------- // º¸Åë ù ¹øÂ° Extent°¡ ÇØ´ç µð½ºÅ©ÀÔ´Ï´Ù. ULONG diskNumber = pExtents->Extents[0].DiskNumber; ExFreePool(pExtents); // ´õ ÀÌ»ó ÇÊ¿ä ¾øÀ½ // µð½ºÅ© ÀåÄ¡ À̸§ »ý¼º (¿¹: \Device\Harddisk2\DR2) RtlStringCchPrintfW(nameBuffer, 64, L"\\Device\\Harddisk%d\\DR%d", diskNumber, diskNumber); RtlInitUnicodeString(&diskName, nameBuffer); status = IoGetDeviceObjectPointer(&diskName, FILE_READ_ATTRIBUTES, &pDiskFileObject, &pDiskDeviceObject); if (!NT_SUCCESS(status)) { return status; } // --------------------------------------------------------- // 3´Ü°è: ¹°¸® µð½ºÅ©ÀÇ PDO ±¸Çϱâ (ÇÙ½É) // --------------------------------------------------------- pDiskPdo = IoGetDeviceAttachmentBaseRef(pDiskDeviceObject); // IoGetDeviceObjectPointer·Î ¾òÀº FileObject´Â ÇØÁ¦ÇØ¾ß ÇÔ ObDereferenceObject(pDiskFileObject); if (!pDiskPdo) { return STATUS_NO_SUCH_DEVICE; } // --------------------------------------------------------- // 4´Ü°è: µåµð¾î! USB\VID... ÁøÂ¥ ID Äõ¸® // --------------------------------------------------------- // ±âÁ¸¿¡ ¸¸µå½Å ÇÔ¼ö³ª Á÷Á¢ È£Ãâ »ç¿ë // ¿©±â¼­´Â Á÷Á¢ È£Ãâ ¿¹½Ã: ULONG returnLength = 0; DEVPROPTYPE propType; status = IoGetDevicePropertyData( pDiskPdo, &DEVPKEY_Device_InstanceId, // USB\VID_...°¡ µé¾îÀִ Ű LOCALE_NEUTRAL, 0, BufferLength, pBuffer, &returnLength, &propType ); // PDO ÂüÁ¶ ÇØÁ¦ ObDereferenceObject(pDiskPdo); return status; } NTSTATUS GetIdFromDiskDeviceObject( __in PDEVICE_OBJECT pDiskDeviceObject, __out PWCHAR pBuffer, __in ULONG BufferLength ) { NTSTATUS status; PDEVICE_OBJECT pDiskPdo = NULL; ULONG returnLength = 0; DEVPROPTYPE propType; // 1. µð½ºÅ© ½ºÅÃÀÇ ÃÖÇÏ´Ü PDO (USBSTOR µî) ±¸Çϱâ pDiskPdo = IoGetDeviceAttachmentBaseRef(pDiskDeviceObject); if (!pDiskPdo) { return STATUS_NO_SUCH_DEVICE; } // 2. PDO¿¡°Ô Instance ID ¹°¾îº¸±â status = IoGetDevicePropertyData( pDiskPdo, &DEVPKEY_Device_InstanceId, LOCALE_NEUTRAL, 0, BufferLength, pBuffer, &returnLength, &propType ); // 3. ÂüÁ¶ ÇØÁ¦ ObDereferenceObject(pDiskPdo); return status; } VOID SafeQueryIdRoutine( _In_ PFLT_GENERIC_WORKITEM FltWorkItem, _In_ PFLT_FILTER Filter, _In_ PVOID Context ) { PFLT_VOLUME Volume = (PFLT_VOLUME)Context; PDEVICE_OBJECT pVolumeDeviceObject = NULL; NTSTATUS status; WCHAR buffer[200]; PDEVICE_OBJECT pDiskPdo = NULL; ULONG returnLength = 0; DEVPROPTYPE propType; UNREFERENCED_PARAMETER(Filter); // 1. º¼·ýÀÇ DeviceObject ¾ò±â status = FltGetDiskDeviceObject(Volume, &pVolumeDeviceObject); if (NT_SUCCESS(status)) { pDiskPdo = IoGetDeviceAttachmentBaseRef(pVolumeDeviceObject); if (pDiskPdo) { status = IoGetDevicePropertyData( pDiskPdo, &DEVPKEY_Device_InstanceId, LOCALE_NEUTRAL, 0, sizeof(buffer), buffer, &returnLength, &propType ); if (NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_INFO, "USB ID Found: %ws\n", buffer); // TODO: º¼·ý ÄÁÅØ½ºÆ®¿¡ ID ÀúÀå } else { KLogEx(DEBUG_TRACE_INFO, "DEVPKEY_Device_InstanceId fail : %x\n", status); } status = IoGetDevicePropertyData( pDiskPdo, &DEVPKEY_Device_Parent, // ºÎ¸ð Ű »ç¿ë LOCALE_NEUTRAL, 0, sizeof(buffer), buffer, &returnLength, &propType ); if (NT_SUCCESS(status)) { KLogEx(DEBUG_TRACE_INFO, "[Bs1Flt] Parent ID: %ws\n", buffer); // °á°ú ¿¹½Ã: USB\VID_346D&PID_5678\8328501217610604362 } else { KLogEx(DEBUG_TRACE_INFO, "[Bs1Flt] DEVPKEY_Device_Parent Failed: 0x%08x\n", status); } ObDereferenceObject(pDiskPdo); } //status = GetUsbIdFromVolume(pVolumeDeviceObject, buffer, sizeof(buffer)); //if (NT_SUCCESS(status)) { // KLogEx(DEBUG_TRACE_INFO, "USB ID Found: %ws\n", buffer); // // TODO: º¼·ý ÄÁÅØ½ºÆ®¿¡ ID ÀúÀå //} //else //{ // KLogEx(DEBUG_TRACE_INFO, "GetUsbIdFromVolume : %x\n", status); //} //status = GetIdFromDiskDeviceObject(pVolumeDeviceObject, buffer, sizeof(buffer)); //if (NT_SUCCESS(status)) { // KLogEx(DEBUG_TRACE_INFO, "[Bs1Flt] USB ID Found: %ws\n", buffer); // // TODO: ¿©±â¼­ Àü¿ª ¸®½ºÆ®³ª Context¿¡ ID¸¦ ÀúÀåÇϰí Á¤Ã¥ Àû¿ë // // CheckUsbPolicy(instanceId); //} //else { // KLogEx(DEBUG_TRACE_INFO, "[Bs1Flt] Failed to query ID from PDO: 0x%08x\n", status); //} ObDereferenceObject(pVolumeDeviceObject); } // 3. Á¤¸® FltObjectDereference(Volume); // ÂüÁ¶ ÇØÁ¦ FltFreeGenericWorkItem(FltWorkItem); } // [ÇïÆÛ ÇÔ¼ö] ÁøÂ¥ PDO¸¦ ±¸ÇÏ´Â ÇÔ¼ö (Çʼö Ãß°¡) PDEVICE_OBJECT GetPdoFromDeviceObject(PDEVICE_OBJECT DeviceObject) { PDEVICE_OBJECT pdo = NULL; PDEVICE_RELATIONS deviceRelations = NULL; IO_STATUS_BLOCK ioStatus; KEVENT event; PIRP irp; NTSTATUS status; if (!DeviceObject) return NULL; KeInitializeEvent(&event, NotificationEvent, FALSE); // ½ºÅÃÀÇ ÃÖ»ó´Ü µð¹ÙÀ̽º¸¦ ±¸Çؼ­ IRP¸¦ º¸³À´Ï´Ù. PDEVICE_OBJECT targetDevice = IoGetAttachedDeviceReference(DeviceObject); irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, targetDevice, NULL, 0, NULL, &event, &ioStatus); if (!irp) { ObDereferenceObject(targetDevice); return NULL; } irp->IoStatus.Status = STATUS_NOT_SUPPORTED; PIO_STACK_LOCATION irpSp = IoGetNextIrpStackLocation(irp); irpSp->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS; irpSp->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation; status = IoCallDriver(targetDevice, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = ioStatus.Status; } if (NT_SUCCESS(status) && ioStatus.Information) { deviceRelations = (PDEVICE_RELATIONS)ioStatus.Information; if (deviceRelations->Count > 0) { pdo = deviceRelations->Objects[0]; // À̰ÍÀÌ ÁøÂ¥ PDO KLogEx(DEBUG_TRACE_ERROR, "deviceRelations->Count(% d)\n", deviceRelations->Count); // ¸¸¾à Count°¡ 1º¸´Ù Å©¸é ³ª¸ÓÁö´Â ÇØÁ¦ (¸Å¿ì µå¹® ÄÉÀ̽º) for (ULONG i = 1; i < deviceRelations->Count; i++) { ObDereferenceObject(deviceRelations->Objects[i]); } } ExFreePool(deviceRelations); } ObDereferenceObject(targetDevice); return pdo; } // ----------------------------------------------------------------------------- // [MAIN] µð½ºÅ© Á¤º¸ ÅëÇÕ ¼öÁý ÇÔ¼ö // pDeviceObject: ¹Ì´ÏÇÊÅÍ¿¡¼­ FltGetDiskDeviceObject µîÀ¸·Î ±¸ÇÑ µð¹ÙÀ̽º °´Ã¼ // ----------------------------------------------------------------------------- NTSTATUS CollectAllDiskInfo( __in PDEVICE_OBJECT pDeviceObject, __out PFULL_DISK_INFO pOutInfo ) { //NTSTATUS status; PDEVICE_OBJECT pPdo = NULL; PDEVICE_OBJECT pTopDevice = NULL; RtlZeroMemory(pOutInfo, sizeof(FULL_DISK_INFO)); // PDO ±¸Çϱâ (QueryDeviceProperty¿ë) // IoGetDeviceAttachmentBaseRef´Â ½ºÅÃÀÇ ÃÖÇÏ´Ü(PDO)À» ¹ÝȯÇÏ¸ç ·¹ÆÛ·±½º Ä«¿îÆ®¸¦ Áõ°¡½Ãŵ´Ï´Ù. //pPdo = IoGetDeviceAttachmentBaseRef(pDeviceObject); pPdo = GetPdoFromDeviceObject(pDeviceObject); if (!pPdo) { return STATUS_NO_SUCH_DEVICE; } // Top Device ±¸Çϱâ (GetStorageProperty¿ë) // IOCTLÀº ½ºÅÃÀÇ ÃÖ»ó´ÜÀ¸·Î º¸³»´Â °ÍÀÌ °¡Àå ¾ÈÀüÇÕ´Ï´Ù. pTopDevice = IoGetAttachedDeviceReference(pDeviceObject); if (!pTopDevice) { ObDereferenceObject(pPdo); return STATUS_NO_SUCH_DEVICE; } __try { // ================================================================= // PnP ·¹Áö½ºÆ®¸® ¼Ó¼º ¼öÁý (PDO »ç¿ë) // ================================================================= if (pPdo != NULL) { QueryDeviceRegistryProperty(pPdo, DevicePropertyFriendlyName, pOutInfo->FriendlyName, sizeof(pOutInfo->FriendlyName)); QueryDeviceRegistryProperty(pPdo, DevicePropertyDeviceDescription, pOutInfo->Description, sizeof(pOutInfo->Description)); QueryDeviceRegistryProperty(pPdo, DevicePropertyHardwareID, pOutInfo->HardwareId, sizeof(pOutInfo->HardwareId)); QueryDeviceRegistryProperty(pPdo, DevicePropertyEnumeratorName, pOutInfo->EnumeratorName, sizeof(pOutInfo->EnumeratorName)); GetDeviceInstanceId(pPdo, &DEVPKEY_Device_InstanceId, pOutInfo->InstanceId, sizeof(pOutInfo->InstanceId)); } else { // PDO¸¦ ¸ø ±¸ÇÑ °æ¿ì (°¡»ó µå¶óÀÌºê µî) ·Î±× ³²±è KLogEx(DEBUG_TRACE_ERROR, "CollectAllDiskInfo: No valid PDO found. Skipping PnP props.\n"); } //GetDeviceInstanceId(pPdo, &DEVPKEY_Device_Parent, pOutInfo->ParentId, sizeof(pOutInfo->ParentId)); //DEVPKEY_Device_Parent // DEVPKEY_Device_InstanceId // ================================================================= // Çϵå¿þ¾î ¹°¸® ¼Ó¼º ¼öÁý (Top Device »ç¿ë) // ================================================================= GetStorageHardwareProperty(pTopDevice, pOutInfo); } __finally { // »ç¿ëÇÑ °´Ã¼ ÂüÁ¶ ÇØÁ¦ (Çʼö) if (pPdo) ObDereferenceObject(pPdo); if (pTopDevice) ObDereferenceObject(pTopDevice); } return STATUS_SUCCESS; }