Advertisement
Week045

LAB5

Nov 29th, 2023
895
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.53 KB | None | 0 0
  1. #include <windows.h>
  2. #include <dbt.h>
  3. #include <iostream>
  4. #include <initguid.h>
  5. #include <Usbiodef.h>
  6. #include <SetupAPI.h>
  7. #include <vector>
  8. #include <Cfgmgr32.h>
  9. #include <conio.h>
  10. #include <string>
  11.  
  12. #pragma comment (lib, "user32.lib" )
  13. #pragma comment (lib, "Setupapi.lib")
  14.  
  15. using namespace std;
  16.  
  17. #define CLS_NAME "WindowClass"
  18.  
  19. struct USB
  20. {
  21.     DEVINST devInst;
  22.     string friendlyName;
  23.     wstring name;
  24.     HANDLE handle;
  25.     bool safety;
  26.     bool removable;
  27. };
  28.  
  29. vector<USB> deviceArray;
  30.  
  31. bool StringComparator(wstring s1, wstring s2)
  32. {
  33.     if (s1.size() != s2.size())
  34.         return false;
  35.     for (int i = 0; i < s1.size(); i++)
  36.         if (toupper(s1[i]) != toupper(s2[i]))
  37.             return false;
  38.     return true;
  39. }
  40.  
  41. string handleToFriendlyName(HANDLE handle)
  42. {
  43.     for (auto it : deviceArray)
  44.         if (it.handle == handle)
  45.             return it.friendlyName;
  46. }
  47.  
  48. bool GetSafety(wstring name)
  49. {
  50.     for (auto it : deviceArray)
  51.         if (StringComparator(it.name, name))
  52.             return it.safety;
  53.     return false;
  54. }
  55.  
  56. void SetSafety(HANDLE handle, bool safety)
  57. {
  58.     for (int i = 0; i < deviceArray.size(); i++)
  59.         if (deviceArray[i].handle == handle)
  60.             deviceArray[i].safety = safety;
  61. }
  62.  
  63. void deleteByName(wstring name)
  64. {
  65.     for (int i = 0; i < deviceArray.size(); i++)
  66.         if (StringComparator(deviceArray[i].name, name))
  67.         {
  68.             deviceArray.erase(deviceArray.begin() + i);
  69.             return;
  70.         }
  71. }
  72.  
  73.  
  74. string getFriendlyName(wchar_t* name)
  75. {
  76.     HDEVINFO deviceList = SetupDiCreateDeviceInfoList(NULL, NULL);
  77.     SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
  78.     SetupDiOpenDeviceInterfaceW(deviceList, name, NULL, &deviceInterfaceData);
  79.     SP_DEVINFO_DATA deviceInfo;
  80.     ZeroMemory(&deviceInfo, sizeof(SP_DEVINFO_DATA));
  81.     deviceInfo.cbSize = sizeof(SP_DEVINFO_DATA);
  82.     SetupDiEnumDeviceInfo(deviceList, 0, &deviceInfo);
  83.     DWORD size = 0;
  84.     SetupDiGetDeviceRegistryPropertyA(deviceList, &deviceInfo, SPDRP_DEVICEDESC, NULL, NULL, NULL, &size);
  85.     BYTE* buffer = new BYTE[size];
  86.     SetupDiGetDeviceRegistryPropertyA(deviceList, &deviceInfo, SPDRP_DEVICEDESC, NULL, buffer, size, NULL);
  87.     string deviceDesc = (char*)buffer;
  88.     delete[] buffer;
  89.  
  90.     return deviceDesc;
  91. }
  92.  
  93. bool getRemoveability(wchar_t* name)
  94. {
  95.     HDEVINFO deviceList = SetupDiCreateDeviceInfoList(NULL, NULL);
  96.     SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
  97.     SetupDiOpenDeviceInterfaceW(deviceList, name, NULL, &deviceInterfaceData);
  98.     SP_DEVINFO_DATA deviceInfo;
  99.     ZeroMemory(&deviceInfo, sizeof(SP_DEVINFO_DATA));
  100.     deviceInfo.cbSize = sizeof(SP_DEVINFO_DATA);
  101.     SetupDiEnumDeviceInfo(deviceList, 0, &deviceInfo);
  102.     DWORD properties;
  103.     SetupDiGetDeviceRegistryPropertyA(deviceList, &deviceInfo, SPDRP_CAPABILITIES, NULL, (PBYTE)&properties, sizeof(DWORD), NULL);
  104.     return properties & CM_DEVCAP_REMOVABLE;
  105. }
  106.  
  107. string getFriendlyName(PDEV_BROADCAST_DEVICEINTERFACE_A info)
  108. {
  109.     wchar_t* name = (wchar_t*)info->dbcc_name;
  110.     return getFriendlyName(name);
  111. }
  112.  
  113. string getInstId(const wchar_t* name)
  114. {
  115.     HDEVINFO deviceList = SetupDiCreateDeviceInfoList(NULL, NULL);
  116.     SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
  117.     SetupDiOpenDeviceInterfaceW(deviceList, name, NULL, &deviceInterfaceData);
  118.     SP_DEVINFO_DATA deviceInfo;
  119.     ZeroMemory(&deviceInfo, sizeof(SP_DEVINFO_DATA));
  120.     deviceInfo.cbSize = sizeof(SP_DEVINFO_DATA);
  121.     SetupDiEnumDeviceInfo(deviceList, 0, &deviceInfo);
  122.     BYTE buffer[BUFSIZ];
  123.     SetupDiGetDeviceInstanceIdA(deviceList, &deviceInfo, (PSTR)buffer, BUFSIZ, NULL);
  124.     return (char*)buffer;
  125. }
  126.  
  127. LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
  128.  
  129.     bool result = false;
  130.     if (message == WM_DEVICECHANGE)
  131.     {
  132.         if (wParam == DBT_DEVICEARRIVAL)
  133.         {
  134.             PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
  135.             if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
  136.             {
  137.                 PDEV_BROADCAST_DEVICEINTERFACE_A info = (PDEV_BROADCAST_DEVICEINTERFACE_A)lpdb;
  138.                 cout << "Новое устройство: \"" << getFriendlyName(info) << "\"" << endl;
  139.  
  140.                 HANDLE deviceHandle = CreateFileW((wchar_t*)info->dbcc_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  141.                 DEV_BROADCAST_HANDLE deviceFilter;
  142.                 deviceFilter.dbch_size = sizeof(deviceFilter);
  143.                 deviceFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  144.                 deviceFilter.dbch_handle = deviceHandle;
  145.                 HDEVNOTIFY notifyHandle = RegisterDeviceNotificationW(hWnd, &deviceFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
  146.                 CloseHandle(deviceHandle);
  147.  
  148.                 DEVINST devInst;
  149.                 CM_Locate_DevNodeA(&devInst, (DEVINSTID_A)getInstId((wchar_t*)info->dbcc_name).c_str(), CM_LOCATE_DEVNODE_NORMAL);
  150.  
  151.                 USB tempDesc;
  152.                 tempDesc.devInst = devInst;
  153.                 tempDesc.handle = deviceHandle;
  154.                 tempDesc.name = (wchar_t*)info->dbcc_name;
  155.                 tempDesc.safety = false;
  156.                 tempDesc.friendlyName = getFriendlyName(info);
  157.                 tempDesc.removable = getRemoveability((wchar_t*)info->dbcc_name);
  158.                 deviceArray.push_back(tempDesc);
  159.             }
  160.         }
  161.         if (wParam == DBT_DEVICEQUERYREMOVEFAILED)
  162.         {
  163.             PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
  164.             if (lpdb->dbch_devicetype == DBT_DEVTYP_HANDLE)
  165.             {
  166.                 PDEV_BROADCAST_HANDLE info = (PDEV_BROADCAST_HANDLE)lpdb;
  167.                 cout << "Не удалось извлечь устройство \"" << handleToFriendlyName(info->dbch_handle) << "\"" << endl;
  168.                 SetSafety(info->dbch_handle, false);
  169.             }
  170.         }
  171.         if (wParam == DBT_DEVICEREMOVECOMPLETE)
  172.         {
  173.             PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
  174.             if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
  175.             {
  176.                 PDEV_BROADCAST_DEVICEINTERFACE_A info = (PDEV_BROADCAST_DEVICEINTERFACE_A)lpdb;
  177.                 cout << "Устройство \"" << getFriendlyName(info) << "\" было извлечено "
  178.                     << (GetSafety((wchar_t*)info->dbcc_name) ? " в активном режиме!" : "не безапасно!") << '\n';
  179.  
  180.                 deleteByName((wchar_t*)info->dbcc_name);
  181.             }
  182.             if (lpdb->dbch_devicetype == DBT_DEVTYP_HANDLE)
  183.             {
  184.                 PDEV_BROADCAST_HANDLE info = (PDEV_BROADCAST_HANDLE)lpdb;
  185.                 UnregisterDeviceNotification(info->dbch_hdevnotify);
  186.             }
  187.         }
  188.         if (wParam == DBT_DEVICEQUERYREMOVE)
  189.         {
  190.             PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
  191.             cout << "Устройство извлечено в безопастном режиме" << endl;
  192.             if (lpdb->dbch_devicetype == DBT_DEVTYP_HANDLE)
  193.             {
  194.                 PDEV_BROADCAST_HANDLE info = (PDEV_BROADCAST_HANDLE)lpdb;
  195.                 SetSafety(info->dbch_handle, true);
  196.             }
  197.             else
  198.             {  
  199.                 return BROADCAST_QUERY_DENY;
  200.             }
  201.         }
  202.     }
  203.     return DefWindowProc(hWnd, message, wParam, lParam);
  204. }
  205.  
  206. DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) {
  207.     HWND hWnd = NULL;
  208.     WNDCLASSEX wx;  
  209.     ZeroMemory(&wx, sizeof(wx));
  210.  
  211.     wx.cbSize = sizeof(WNDCLASSEX);
  212.     wx.lpfnWndProc = (WNDPROC)(WndProc);
  213.     wx.lpszClassName = (LPCWSTR)CLS_NAME;
  214.  
  215.     GUID guid = GUID_DEVINTERFACE_USB_DEVICE;
  216.  
  217.     if (RegisterClassExW(&wx))
  218.         hWnd = CreateWindow((LPCWSTR)CLS_NAME, (LPCWSTR)("DeviceNotificationWindow"), WS_ICONIC, 0, 0, CW_USEDEFAULT, 0, 0, NULL, GetModuleHandle(0), (void*)&guid);  
  219.  
  220.     DEV_BROADCAST_DEVICEINTERFACE_A filter;
  221.     filter.dbcc_size = sizeof(filter);
  222.     filter.dbcc_classguid = guid;
  223.     filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  224.     RegisterDeviceNotificationW(hWnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
  225.  
  226.     HDEVINFO devicesHandle = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  227.     DWORD deviceNumber = 0;
  228.     SP_DEVICE_INTERFACE_DATA devinterfaceData;
  229.     devinterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  230.  
  231.     while (SetupDiEnumDeviceInterfaces(devicesHandle, NULL, &GUID_DEVINTERFACE_USB_DEVICE, deviceNumber++, &devinterfaceData)) {
  232.         DWORD bufSize = 0;
  233.         SetupDiGetDeviceInterfaceDetailW(devicesHandle, &devinterfaceData, NULL, NULL, &bufSize, NULL);
  234.         BYTE* buffer = new BYTE[bufSize];
  235.         PSP_DEVICE_INTERFACE_DETAIL_DATA_W devinterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)buffer;
  236.         devinterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
  237.         SetupDiGetDeviceInterfaceDetailW(devicesHandle, &devinterfaceData, devinterfaceDetailData, bufSize, NULL, NULL);
  238.        
  239.         wchar_t* path = devinterfaceDetailData->DevicePath;
  240.  
  241.         DEVINST devInst;
  242.         CM_Locate_DevNodeA(&devInst, (DEVINSTID_A)getInstId(devinterfaceDetailData->DevicePath).c_str(), CM_LOCATE_DEVNODE_NORMAL);
  243.  
  244.         HANDLE deviceHandle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  245.         DEV_BROADCAST_HANDLE deviceFilter;
  246.         deviceFilter.dbch_size = sizeof(deviceFilter);
  247.         deviceFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  248.         deviceFilter.dbch_handle = deviceHandle;
  249.         HDEVNOTIFY notifyHandle = RegisterDeviceNotificationW(hWnd, &deviceFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
  250.         CloseHandle(deviceHandle);
  251.  
  252.         USB tmpUsbDev;
  253.         tmpUsbDev.devInst = devInst;
  254.         tmpUsbDev.friendlyName = getFriendlyName(path);
  255.         tmpUsbDev.handle = deviceHandle;
  256.         tmpUsbDev.name = path;
  257.         tmpUsbDev.safety = false;
  258.         tmpUsbDev.removable = getRemoveability(path);
  259.         deviceArray.push_back(tmpUsbDev);
  260.     }
  261.  
  262.     MSG msg;
  263.     while (GetMessageW(&msg, hWnd, 0, 0))
  264.     {
  265.         TranslateMessage(&msg);
  266.         DispatchMessage(&msg);
  267.     }
  268.     return 0;
  269. }
  270.  
  271. void printDeviceArray() {
  272.     int id = 1;
  273.     cout << endl << "Обнаруженные USB устройства:" << endl;
  274.     for (auto it : deviceArray)
  275.         cout << id++ << " - " << it.friendlyName << (it.removable ? " (Можно извлечь)" : "") << endl;
  276.     cout << endl;
  277. }
  278.  
  279. int main()
  280. {
  281.     setlocale(LC_ALL, "Russian");
  282.     CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
  283.  
  284.     int choise = -1;
  285.     while (true) {
  286.         cout << "1 - Список устройств" << endl << "2 - Безопастное извлечение" << endl << "0 - Выход" << endl;
  287.         cin >> choise;
  288.         if (choise == 1) {
  289.             printDeviceArray();
  290.         }
  291.         else if (choise == 2) {
  292.             printDeviceArray();
  293.             cout << "Введите номер устройства из списка для безопастного извлечения: ";
  294.             int choise = 0;
  295.             while (!(cin >> choise))
  296.             {
  297.                 cin.clear();
  298.                 rewind(stdin);
  299.             }
  300.             if (choise > deviceArray.size() || choise <= 0)
  301.             {
  302.                 cout << "Нет подключенных устройств с номером " << choise << "!" << endl;
  303.                 continue;
  304.             }
  305.             if (deviceArray[choise - 1].removable)
  306.                 CM_Request_Device_EjectW(deviceArray[choise - 1].devInst, NULL, NULL, NULL, NULL);
  307.             else
  308.                 cout << "Устройство с номером " << choise << " не удалось извлечь!" << endl;
  309.         }
  310.         else if (choise == 0) {
  311.             return 0;
  312.             ::system("CLS");
  313.         }
  314.         rewind(stdin);
  315.         _getch();
  316.         ::system("CLS");
  317.     }
  318. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement