请见代码分析
#include <windows.h> #include <winioctl.h> #include <stdio.h> #include <initguid.h> #include <setupapi.h> #include <string.h> #define MAX_DEVICE 256 wchar_t USBSerial[5][100] = {TEXT("")}; int gTag = 0; DEFINE_GUID(UsbClassGuid, 0xa5dcbf10L, 0x6530, 0x11d2, 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed); // SetupDiGetInterfaceDeviceDetail所需要的输出长度,定义足够大 #define INTERFACE_DETAIL_SIZE (1024) // IOCTL控制码 #define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) #pragma comment(lib,"setupapi.lib") //自动关机函数 void ExitWindowsCode() { OSVERSIONINFO stOSVI; ZeroMemory(&stOSVI , sizeof ( OSVERSIONINFO )) ; stOSVI.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO ) ; if (!GetVersionEx ( &stOSVI )) return; if ( ( VER_PLATFORM_WIN32_NT == stOSVI.dwPlatformId ) && ( 4 <= stOSVI.dwMajorVersion ) ) { HANDLE hToken; TOKEN_PRIVILEGES tkp; if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return; // Get the LUID for the shutdown privilege. LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; // one privilege to set tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES)NULL, 0); if (GetLastError() != ERROR_SUCCESS) return; if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE|EWX_POWEROFF, 0)) return; } else//WIN9X { ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE | EWX_POWEROFF, 0);// 关机 } } // 根据GUID获得设备路径,用来判断U盘设备 // lpGuid: GUID指针 // pszDevicePath: 设备路径指针的指针 // 返回: 成功得到的设备路径个数,可能不止1个 int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath) { HDEVINFO hDevInfoSet; //设备信息集句柄; SP_DEVICE_INTERFACE_DATA ifdata; PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail; int nCount; BOOL bResult; // 取得一个该GUID相关的设备信息集句柄 hDevInfoSet = ::SetupDiGetClassDevs((LPGUID)&UsbClassGuid, // class GUID NULL, // 无关键字 NULL, // 不指定父窗口句柄 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备 // 失败... if (hDevInfoSet == INVALID_HANDLE_VALUE) { return 0; } // 申请设备接口数据空间 pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE); pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); nCount = 0; bResult = TRUE; // 设备序号=0,1,2... 逐一测试设备接口,到失败为止 while (bResult) { ifdata.cbSize = sizeof(ifdata); // 枚举符合该GUID的设备接口 bResult = ::SetupDiEnumDeviceInterfaces( hDevInfoSet, // 设备信息集句柄 NULL, // 不需额外的设备描述 lpGuid, // GUID (ULONG)nCount, // 设备信息集里的设备序号 &ifdata); // 设备接口信息 if (bResult) { // 取得该设备接口的细节(设备路径) bResult = SetupDiGetInterfaceDeviceDetail( hDevInfoSet, // 设备信息集句柄 &ifdata, // 设备接口信息 pDetail, // 设备接口细节(设备路径) INTERFACE_DETAIL_SIZE, // 输出缓冲区大小 NULL, // 不需计算输出缓冲区大小(直接用设定值) NULL); // 不需额外的设备描述 if (bResult) { // 复制设备路径到输出缓冲区 wcscpy_s(pszDevicePath[nCount],wcslen(pDetail->DevicePath)+1, pDetail->DevicePath); // 调整计数值 nCount++; } } } // 释放设备接口数据空间 ::GlobalFree(pDetail); // 关闭设备信息集句柄 ::SetupDiDestroyDeviceInfoList(hDevInfoSet); return nCount; } // 返回U盘设备句柄 hDevice HANDLE OpenDevice(wchar_t* DevicePath) { HANDLE hDevice; hDevice = CreateFileW(DevicePath, GENERIC_READ && GENERIC_WRITE, FILE_SHARE_READ && FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); return hDevice; } int _stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { int i, nDevice; // nDevice 表示有多少个USB设备 int ndevice = 0; // 表示多少个U盘设备(可进行读写的设备) wchar_t* szDevicePath[MAX_DEVICE]; // 设备路径 HANDLE hDevice; // DWORD dwOutBytes; // IOCTL输出数据长度 // 定义一个 PSTORAGE_DEVICE_DESCRIPTOR 变量,存放设备属性 PSTORAGE_DEVICE_DESCRIPTOR DeviceDesc; // 变量初始化 DeviceDesc=(PSTORAGE_DEVICE_DESCRIPTOR)new BYTE[sizeof(STORAGE_DEVICE_DESCRIPTOR) + 512 - 1]; DeviceDesc->Size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 512 - 1; // 分配需要的空间 for (i = 0; i < MAX_DEVICE; i++) { szDevicePath[i] = new wchar_t[256]; } // 取设备路径 nDevice = ::GetDevicePath((LPGUID)&UsbClassGuid, szDevicePath); // 逐一获取设备信息 for (i = 0; i < nDevice; i++) { // 打开设备 hDevice = OpenDevice(szDevicePath[i]); if (hDevice != INVALID_HANDLE_VALUE) { for(int j = 0; j < 4; j++) { USBSerial[ndevice][j] = szDevicePath[i][j+12]; } for(int j = 4; j < 28; j++) { USBSerial[ndevice][j] = szDevicePath[i][j+22]; } //printf("U盘序列号为:"); //wprintf(L"%ws\n", USBSerial[ndevice]); ndevice ++; ::CloseHandle(hDevice); } } // 释放空间 for (i = 0; i < MAX_DEVICE; i++) { delete []szDevicePath[i]; } ////////////////// 文件操作 //////////////////////////////////////// HANDLE hFile; DWORD nBytesRead = 0, dwBytesWritten = 0; // 打开文件 hFile = CreateFile(TEXT("C:\\Windows\\system32\\USBID.ID"), // file to open GENERIC_READ | GENERIC_WRITE, // open for reading FILE_SHARE_READ | FILE_SHARE_WRITE, // share for reading NULL, // default security OPEN_EXISTING , // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if (hFile != INVALID_HANDLE_VALUE) { long nFileSize = GetFileSize(hFile, NULL); if (nFileSize == 0) { bool flag2 = CloseHandle(hFile); if(::SetFileAttributes(TEXT("C:\\Windows\\system32\\USBID.ID"),FILE_ATTRIBUTE_NORMAL)) { if (DeleteFile(TEXT("C:\\Windows\\system32\\USBID.ID"))) { //MessageBox(NULL,TEXT("oo"),TEXT("oo"),MB_OK); } } } } // 打开文件 hFile = CreateFile(TEXT("C:\\Windows\\system32\\USBID.ID"), // file to open GENERIC_READ | GENERIC_WRITE, // open for reading FILE_SHARE_READ | FILE_SHARE_WRITE, // share for reading NULL, // default security OPEN_EXISTING , // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if (hFile == INVALID_HANDLE_VALUE) { hFile = CreateFile(TEXT("C:\\Windows\\system32\\USBID.ID"), // file to create GENERIC_READ | GENERIC_WRITE, // open for writing FILE_SHARE_READ | FILE_SHARE_WRITE, // do not share NULL, // default security CREATE_ALWAYS, // overwrite existing FILE_ATTRIBUTE_NORMAL | // normal file FILE_ATTRIBUTE_NORMAL, // asynchronous I/O NULL); } else { if (ndevice < 1) { ExitWindowsCode(); } } long nFileSize = GetFileSize(hFile, NULL); wchar_t *tempbuf = new wchar_t[nFileSize] ; // 读文件内容 if (nFileSize == 0) { // 创建文件,并把序列号写入文件中 hFile = CreateFile(TEXT("C:\\Windows\\system32\\USBID.ID"), // file to create GENERIC_READ | GENERIC_WRITE, // open for writing FILE_SHARE_READ | FILE_SHARE_WRITE, // do not share NULL, // default security CREATE_ALWAYS, // overwrite existing FILE_ATTRIBUTE_NORMAL | // normal file FILE_ATTRIBUTE_NORMAL, // asynchronous I/O NULL); // no attr. template if (hFile == INVALID_HANDLE_VALUE) { return 0; } // 把序列号写入文件中 WriteFile(hFile, USBSerial, 2*wcslen(* USBSerial), &dwBytesWritten, NULL); nFileSize = GetFileSize(hFile, NULL); if (nFileSize == 0) { bool flag1 = CloseHandle(hFile); } else { if (ndevice < 1) { ExitWindowsCode(); } } } else { //进入比较序列号 ReadFile(hFile, tempbuf, nFileSize, &nBytesRead, NULL); // 比较已经有的序列号与新读的是否相等 for(int i = 0; i< ndevice; i ++) { for(int j = 0; j < nFileSize/2; j++) { if(tempbuf[j] == USBSerial[i][j]) gTag = 1; else { ExitWindowsCode(); } } if(gTag == 1) break; } delete tempbuf; } return 0; }