powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Серийный номер USB диска
3 сообщений из 3, страница 1 из 1
Серийный номер USB диска
    #38165572
Hisbreht Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вопрос достаточно популярный, широко освещенный, но тем не менее.
Есть задача - по букве диска получить серийный номер диска как физического устройства.
Есть куча методов, часть из которых вообще не работает, часть работает только под определенной версией ОС, часть работает только с одним типом устройств (флэшки, IDE или USB HDD).
Надо решить ее быстро (1-2 дня). Отсюда вопрос - существует ли гарантированно рабочее готовое бесплатное универсальное решение? Лучше в виде DLL, но можно и в виде кода на C++ или Delphi.

В принципе в качестве половинного, неполноценного, но вполне достаточного решения подойдет решение только для USB HDD.

Сейчас пинаю нижеследующий код, но он упорно выдает в качестве серийника полную чушь.
Чушь начинается с этого вызова
Код: sql
1.
2.
3.
  if (DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
        pConnectionInfo, sizeof(pbBuffer), pConnectionInfo, sizeof(pbBuffer), 
        &dwNumBytes, NULL))


До того вроде все корректно.
Может хоть тут кто что посоветует?

Код+
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
// getserial.cpp: определяет экспортированные функции для приложения DLL.
//
#include <windows.h>

#include <usbioctl.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <usbiodef.h>
#include <tchar.h>
#include <string>

typedef std::basic_string<TCHAR> tstring;

int GetDeviceNumber(const tstring& strDevicePath)
{
    int        iDeviceNumber = -1;
    HANDLE    hVolume;

    hVolume = CreateFile(strDevicePath.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hVolume != INVALID_HANDLE_VALUE)
    {
        STORAGE_DEVICE_NUMBER    deviceNumber;
        DWORD    dwNumBytes;
        
        if (DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, 
            NULL, 0, &deviceNumber, sizeof(deviceNumber), &dwNumBytes, NULL) != 0)
            iDeviceNumber = (deviceNumber.DeviceType << 8) + deviceNumber.DeviceNumber;
      
        CloseHandle(hVolume);
    }

    return iDeviceNumber;
}

bool FindDiskDevice(TCHAR DriveLetter, tstring& strHubDevicePath, 
    tstring& strInstanceID, tstring& strDeviceName, bool& bSerialNumber)
{
    bool    res = false;
    BOOL    bSuccess;
    int        iDeviceNumber;
    HDEVINFO    hSetup;
    int        i;
    DWORD    dwNumBytes;
    SP_DEVICE_INTERFACE_DATA    interfaceData;
    SP_DEVINFO_DATA    devinfoData;
    BYTE    pbBuffer[800];
    PSP_DEVICE_INTERFACE_DETAIL_DATA    pDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) &pbBuffer[0];
    tstring    strDevicePath = _T("\\\\.\\");


    bSerialNumber = false;

    strDevicePath += DriveLetter;
    strDevicePath += _T(':');
    iDeviceNumber = GetDeviceNumber(strDevicePath);
    if (iDeviceNumber == -1)
        return false;

    hSetup = SetupDiGetClassDevs((LPGUID) &GUID_DEVINTERFACE_DISK, 
        NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if (hSetup == INVALID_HANDLE_VALUE)
        return false;

    i = 0;
    while (true)
    {
        interfaceData.cbSize = sizeof(interfaceData);

        bSuccess = SetupDiEnumDeviceInterfaces(hSetup, NULL, 
            (LPGUID) &GUID_DEVINTERFACE_DISK, i, &interfaceData);

        if (!bSuccess)
            break;
         
        devinfoData.cbSize = sizeof(devinfoData);
        pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        if (SetupDiGetDeviceInterfaceDetail(hSetup, &interfaceData, pDetailData, 
            sizeof(pbBuffer), &dwNumBytes, &devinfoData) != 0)
        {
            if (GetDeviceNumber(pDetailData->DevicePath) == iDeviceNumber)
            {
                DEVINST    devPrev;
                tstring    strTemp, strGUID;
                int    j;
                DWORD    dwCap;

                if (SetupDiGetDeviceRegistryProperty(hSetup, &devinfoData, 
                    SPDRP_FRIENDLYNAME, NULL, (PBYTE) pbBuffer, sizeof(pbBuffer), &dwNumBytes))
                    strDeviceName = (TCHAR*) pbBuffer;

                if (SetupDiGetDeviceRegistryProperty(hSetup, &devinfoData, 
                    SPDRP_CAPABILITIES, NULL, (PBYTE) &dwCap, sizeof(dwCap), &dwNumBytes))
                    bSerialNumber = (dwCap & CM_DEVCAP_UNIQUEID) != 0;
                
                CM_Get_Parent(&devPrev, devinfoData.DevInst, 0);
                CM_Get_Device_ID(devPrev, (TCHAR*) pbBuffer, sizeof(pbBuffer)/sizeof(TCHAR), 0);
                strInstanceID = (TCHAR*) pbBuffer;

                CM_Get_Parent(&devPrev, devPrev, 0);
                CM_Get_Device_ID(devPrev, (TCHAR*) pbBuffer, sizeof(pbBuffer)/sizeof(TCHAR), 0);
                strTemp = (TCHAR*) pbBuffer;

                for (j=0; j < strTemp.length(); ++j)
                    if (strTemp[j] == _T('\\'))
                        strTemp[j] = _T('#');

				GUID devintusbhub={0xf18a0e88, 0xc30c, 0x11d0, 0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8};//GUID_DEVINTERFACE_USB_HUB;
				StringFromGUID2(devintusbhub, (LPOLESTR) pbBuffer, sizeof(pbBuffer) / sizeof(WCHAR));
				char Res[256];
				int rcnt;
				rcnt=WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,(WCHAR*)pbBuffer,wcslen((WCHAR*)pbBuffer),Res,256,NULL,NULL);
				Res[rcnt]=0;
                strGUID = (TCHAR*)Res;
					//(LPOLESTR) pbBuffer;

                strHubDevicePath = _T("\\\\.\\") + strTemp + _T("#") + strGUID;
                res = true;

                break;
            }
        }

        ++i;
    }

   SetupDiDestroyDeviceInfoList(hSetup);
   return res;
}

tstring GetDriverKeyName(const tstring& strHubPath, int iPortNumber)
{
    tstring    strDriverKeyName = _T("");
    HANDLE    hHub;
    DWORD    dwNumBytes;
    USB_NODE_CONNECTION_INFORMATION    nodeInfo;
    PBYTE    pbBuffer[500];

    hHub = CreateFile(strHubPath.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
        NULL, OPEN_EXISTING, 0, NULL);
    
    if (hHub != INVALID_HANDLE_VALUE)
    {
        nodeInfo.ConnectionIndex = iPortNumber;

        if (DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
            &nodeInfo, sizeof(nodeInfo), &nodeInfo, sizeof(nodeInfo), &dwNumBytes, NULL))
        {
            if (nodeInfo.ConnectionStatus == DeviceConnected)
            {
                PUSB_NODE_CONNECTION_DRIVERKEY_NAME    pDriverKeyName = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME) pbBuffer;
                
                pDriverKeyName->ConnectionIndex = iPortNumber;

                if (DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, 
                      pDriverKeyName, sizeof(pbBuffer), pDriverKeyName, 
				  	  sizeof(pbBuffer), &dwNumBytes, NULL)) {
  			        char Res[256];
		            int rcnt;
				    rcnt=WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,(WCHAR*)(pDriverKeyName->DriverKeyName),wcslen((WCHAR*)pDriverKeyName->DriverKeyName),Res,256,NULL,NULL);
				    Res[rcnt]=0;
                    strDriverKeyName = (TCHAR*)Res;
				}
            }
        }

        CloseHandle(hHub);
    }

    return strDriverKeyName;
}

int GetPortCount(const tstring& strHubDevicePath)
{
    int    nCount = 0;
    HANDLE    hHub;
    DWORD    dwNumBytes;
    USB_NODE_INFORMATION    nodeInfo;

    hHub = CreateFile(strHubDevicePath.c_str(), GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

    if (hHub== INVALID_HANDLE_VALUE)
        return nCount;

    nodeInfo.NodeType = UsbHub;

    if (DeviceIoControl(hHub, IOCTL_USB_GET_NODE_INFORMATION, &nodeInfo,
        sizeof(nodeInfo), &nodeInfo, sizeof(nodeInfo), &dwNumBytes, NULL))
        nCount = nodeInfo.u.HubInformation.HubDescriptor.bNumberOfPorts;

    CloseHandle(hHub);
    return nCount;
}

tstring FindInstanceIDByKeyName(const tstring& strDriverKeyName, tstring& strHardwareID)
{
    tstring    strInstanceID = _T("");
    HDEVINFO    hDevInfo;
    BOOL    bSuccess;
    int        i = 0;
    tstring    strKeyName;
    SP_DEVINFO_DATA    devinfoData;
    DWORD    dwNumBytes;
    BYTE    pbBuffer[500];


    strHardwareID = _T("");

    hDevInfo = SetupDiGetClassDevs(0, _T("USB"), NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
    if (hDevInfo == INVALID_HANDLE_VALUE)
        return strInstanceID;

    while (true)
    {
        devinfoData.cbSize = sizeof(devinfoData);
        bSuccess = SetupDiEnumDeviceInfo(hDevInfo, i, &devinfoData);

        if (!bSuccess)
            break;

        strKeyName = _T("");
        if (SetupDiGetDeviceRegistryProperty(hDevInfo, &devinfoData, SPDRP_DRIVER, NULL, pbBuffer,
            sizeof(pbBuffer), &dwNumBytes))
            strKeyName = (TCHAR*) pbBuffer;

        if (strKeyName == strDriverKeyName)
        {
           SetupDiGetDeviceInstanceId(hDevInfo, &devinfoData, (TCHAR*) pbBuffer, sizeof(pbBuffer), &dwNumBytes);
           strInstanceID = (TCHAR*) pbBuffer;

            if (SetupDiGetDeviceRegistryProperty(hDevInfo, &devinfoData, SPDRP_HARDWAREID, NULL, pbBuffer,
                sizeof(pbBuffer), &dwNumBytes))
                strHardwareID = (TCHAR*) pbBuffer;

           break;
        }

        ++i;
    }

    SetupDiDestroyDeviceInfoList(hDevInfo);
    return strInstanceID;
}

void GetDeviceDescriptor(const tstring& strHubPath, int iPortNumber, 
    PUSB_DEVICE_DESCRIPTOR pDeviceDescriptor)
{
    HANDLE    hHub;
    BYTE    pbBuffer[500];
    PUSB_NODE_CONNECTION_INFORMATION    pConnectionInfo = (PUSB_NODE_CONNECTION_INFORMATION) pbBuffer;
	PUSB_DEVICE_DESCRIPTOR pDescriptor = (PUSB_DEVICE_DESCRIPTOR) pbBuffer;
    DWORD    dwNumBytes;


    memset(pDeviceDescriptor, 0, sizeof(USB_DEVICE_DESCRIPTOR));
    memset(pbBuffer, 0, sizeof(pbBuffer));

    hHub = CreateFile(strHubPath.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING, 0, NULL);
    if (hHub == INVALID_HANDLE_VALUE)
        return;

    pConnectionInfo->ConnectionIndex = iPortNumber;

    if (DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
        pConnectionInfo, sizeof(pbBuffer), pConnectionInfo, sizeof(pbBuffer), 
        &dwNumBytes, NULL))
//    if (DeviceIoControl(hHub, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
//        pConnectionInfo, sizeof(pbBuffer), pDescriptor, sizeof(pbBuffer), 
//        &dwNumBytes, NULL))
		
        memcpy(pDeviceDescriptor, &pConnectionInfo->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
//        memcpy(pDeviceDescriptor, &pConnectionInfo, sizeof(USB_DEVICE_DESCRIPTOR));

    CloseHandle(hHub);
}

tstring GetStringDescriptor(const tstring& strHubPath, int iPortNumber, int iIndex)
{
    tstring    strValue;
    HANDLE    hHub;
    BOOL    bSuccess;
    ULONG    nBytes;
    ULONG    nBytesReturned;
    UCHAR    stringDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + MAXIMUM_USB_STRING_LENGTH];
    PUSB_DESCRIPTOR_REQUEST    pStringDescReq;
    PUSB_STRING_DESCRIPTOR    pStringDesc;


    hHub = CreateFile(strHubPath.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING, 0, NULL);
    if (hHub == INVALID_HANDLE_VALUE)
        return strValue;

    nBytes = sizeof(stringDescReqBuf);

    pStringDescReq = (PUSB_DESCRIPTOR_REQUEST)stringDescReqBuf;
    pStringDesc = (PUSB_STRING_DESCRIPTOR)(pStringDescReq + 1);

    // Zero fill the entire request structure
    memset(pStringDescReq, 0, nBytes);

    // Indicate the port from which the descriptor will be requested
    pStringDescReq->ConnectionIndex = iPortNumber;

    // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
    // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
    //
    // USBD will automatically initialize these fields:
    //     bmRequest = 0x80
    //     bRequest  = 0x06
    //
    // We must inititialize these fields:
    //     wValue    = Descriptor Type (high) and Descriptor Index (low byte)
    //     wIndex    = Zero (or Language ID for String Descriptors)
    //     wLength   = Length of descriptor buffer
    pStringDescReq->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) | iIndex;
    pStringDescReq->SetupPacket.wIndex = 0x409;
    pStringDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));

    // Now issue the get descriptor request.
    bSuccess = DeviceIoControl(hHub, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
        pStringDescReq, nBytes, pStringDescReq, nBytes, &nBytesReturned, NULL);

    CloseHandle(hHub);

    // Do some sanity checks on the return from the get descriptor request.
    if (!bSuccess)
        return strValue;
    if (nBytesReturned < 2)
        return strValue;
    if (pStringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE)
        return strValue;
    if (pStringDesc->bLength != nBytesReturned - sizeof(USB_DESCRIPTOR_REQUEST))
        return strValue;
    if (pStringDesc->bLength % 2 != 0)
        return strValue;
    
    strValue = (WCHAR)pStringDesc->bString;

    return strValue;
}

EXTERN_C __declspec(dllexport) int GetSerialNumber(TCHAR DriveLetter, char* pcDeviceName, char* pcSerial, int size)
{
    int    iCounter = 15;
    tstring strDeviceName=pcDeviceName;

    while (iCounter)
    {
        tstring    strSerialNumber, strHardwareID;
        tstring    strInstanceID;
        tstring    strHubDevicePath;
        tstring    strDriverKeyName;
        int    i, nPortCount;
        USB_DEVICE_DESCRIPTOR    deviceDesc;
        bool    bSerialNumber;

        if (!FindDiskDevice(DriveLetter, strHubDevicePath, strInstanceID, 
            strDeviceName, bSerialNumber))
        {
            strSerialNumber = _T("");
            strcpy(pcSerial,strSerialNumber.c_str());
            return (0);
        }
        
        if (strInstanceID.find(_T("USB\\")) == 0)
        {
            nPortCount = GetPortCount(strHubDevicePath);
			if (nPortCount == 0){
                strcpy(pcSerial,strSerialNumber.c_str());
                return (0);
			}
            for (i=1; i <= nPortCount; ++i)
            {
                strDriverKeyName = GetDriverKeyName(strHubDevicePath, i);
                if (FindInstanceIDByKeyName(strDriverKeyName, strHardwareID) == strInstanceID)
                {
                    strSerialNumber = _T("HardwareID:");
                    strSerialNumber += strHardwareID;

                    GetDeviceDescriptor(strHubDevicePath, i, &deviceDesc);

                    if (deviceDesc.iSerialNumber > 0)
                    {
                        strSerialNumber = GetStringDescriptor(strHubDevicePath, i, deviceDesc.iSerialNumber);
                        break;
                    }
                }
            }
        }

        if (strSerialNumber.empty())
        {
            --iCounter;
            continue;
        }

        if (!strSerialNumber.empty())
            _tcsupr((TCHAR*) strSerialNumber.c_str());

        strcpy(pcSerial,strSerialNumber.c_str());
        return (1);
    }

    strcpy(pcSerial,"");
    return (0);
}


В исходном примере, который лег в основу, было, правда,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, но по причине отсутствия в доступном SDK этого дела EX пришлось отрезать.

Виктор
...
Рейтинг: 0 / 0
Серийный номер USB диска
    #38167169
Hisbreht Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вопрос снимается. Разобрался в коде. Там просто закралась маленькая ошибка с преобразованием строк из уникода в ANSI. Работает нормально.
...
Рейтинг: 0 / 0
Серийный номер USB диска
    #38172725
Hisbreht Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А "здесь не все так просто, как на самом деле".
Код: sql
1.
2.
   bSuccess = DeviceIoControl(hHub, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
        pStringDescReq, nBytes, pStringDescReq, nBytes, &nBytesReturned, NULL);


Периодически не возвращает дескриптор. Приходится повторять. Иногда несколько раз, чтобы вернуло.
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Серийный номер USB диска
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]