Страницы

Поиск по вопросам

Показаны сообщения с ярлыком winapi. Показать все сообщения
Показаны сообщения с ярлыком winapi. Показать все сообщения

среда, 15 апреля 2020 г.

Инжект в чужой процесс системы Windows

#winapi #windows

                    
Здравствуйте!
Какой самый безопасный способ инжекта своего кода в процесс другого приложения?
Например, комбинации:

1) OpenProcess -> VirtualAllocEx -> SuspendThread -> GetThreadContext -> SetThreadContext
-> ResumeThread.

и

2) OpenProcess -> VirtualAllocEx -> WriteProcessMemoey -> CreateRemoteThread.

Палятся всеми современными антивирусами, вследствие чего, программа попадет в карантин,
так как её антивирь посчитает за вирус. Какие у вас есть предложения по этому поводу?
Спасибо!    


Ответы

Ответ 1



Все документированные способы инжектов, конечно же, известны антивирусам и палятся ими, универсального способа НЕдокументироавнного инжекта, подходящего для всех аверов, попросту нет! Кто-то повышает права сплоитом и подгружает свой драйвер, кто-то юзает малоизвестные фнукции OLE.

понедельник, 13 апреля 2020 г.

Как программно измененить громкость звука в Windows?

#c #windows #winapi #windows_7 #аудио

                    
Как программно измененить громкость звука в Windows?

Можете написать пример?
Желательно, чтобы скомпилился  на minGW.  
    


Ответы

Ответ 1



Нашел хороший пример на MSDN: How to Use Wave Audio Volume Control APIs, есть как получение громкости, так и установка. Данный пример дает нужный результат на версиях WIndows ниже Vista. В Windows Vista и 7 были представлены новые API для работы с аудио, для изменения громкости глобально нужно использовать интерфейс IAudioEndpointVolume. Небольшой пример использования есть также в MSDN и на CodeProject:

Ответ 2



Анимированое изменение звука системы Win7 C++ visual studio 10 #include #include #include #pragma comment(lib, "ole32.lib") //extern bool ChangeVolume(double nVolume,bool bScalar) { HRESULT hr=NULL; bool decibels = false; bool scalar = false; double newVolume=nVolume; CoInitialize(NULL); IMMDeviceEnumerator *deviceEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); IMMDevice *defaultDevice = NULL; hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); deviceEnumerator->Release(); deviceEnumerator = NULL; IAudioEndpointVolume *endpointVolume = NULL; hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume); defaultDevice->Release(); defaultDevice = NULL; // ------------------------- float currentVolume = 0; endpointVolume->GetMasterVolumeLevel(¤tVolume); //printf("Current volume in dB is: %f\n", currentVolume); hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume); //CString strCur=L""; //strCur.Format(L"%f",currentVolume); //AfxMessageBox(strCur); // printf("Current volume as a scalar is: %f\n", currentVolume); if (bScalar==false) { hr = endpointVolume->SetMasterVolumeLevel((float)newVolume, NULL); } else if (bScalar==true) { hr = endpointVolume->SetMasterVolumeLevelScalar((float)newVolume, NULL); } endpointVolume->Release(); CoUninitialize(); return FALSE; } float i = 0; int main() { float volume = 0; while(1) { i+=0.01; volume = (sin(i)+1)/2; ChangeVolume(volume,1); std::cout< #include #include #pragma comment(lib, "ole32.lib") //extern //Управление звуком class VolumeOS { public: HRESULT hr; bool decibels; bool scalar; double Volume; VolumeOS() { hr=NULL; decibels = false; scalar = false; CoInitialize(NULL); //newVolume=nVolume; } bool VolumeSET(double nVolume,bool bScalar) { double newVolume = nVolume; Volume = newVolume; IMMDeviceEnumerator *deviceEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); IMMDevice *defaultDevice = NULL; hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); deviceEnumerator->Release(); deviceEnumerator = NULL; IAudioEndpointVolume *endpointVolume = NULL; hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume); defaultDevice->Release(); defaultDevice = NULL; // ------------------------- float currentVolume = 0; endpointVolume->GetMasterVolumeLevel(¤tVolume); //printf("Current volume in dB is: %f\n", currentVolume); hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume); //CString strCur=L""; //strCur.Format(L"%f",currentVolume); //AfxMessageBox(strCur); // printf("Current volume as a scalar is: %f\n", currentVolume); if (bScalar==false) { hr = endpointVolume->SetMasterVolumeLevel((float)newVolume, NULL); } else if (bScalar==true) { hr = endpointVolume->SetMasterVolumeLevelScalar((float)newVolume, NULL); } endpointVolume->Release(); return FALSE; } ~VolumeOS() { CoUninitialize(); } }; float i = 0; int main() { VolumeOS A; float volume = 0; while(1) { i+=0.01; volume = (sin(i)+1)/2; A.VolumeSET(volume,true); std::cout<

суббота, 11 апреля 2020 г.

Winforms vs winapi

#winapi #winforms #cpp

                    
У меня старая ОС(windows xp) и компилятор(mvs 2010) на данный момент доступны только
две технологии писать свои форточки winforms и голый winapi, какую технологию лучше
выбрать после консольных приложений?    


Ответы

Ответ 1



Если для общего развития и речь именно о развитии в рамках С++, то, пожалуй, я бы предпочел WInAPI - там хотя бы именно С++ используется, в отличие от WInForms, где, насколько я знаю, задействован С++/CLI. Хотя на мой взгляд, и то и другое - не самое лучшее приложение сил. Если же вы планируете связать с какой-то из этих технологий дальнейшую профессиональную деятельность и тем самым зарабатывать, то я бы не советовал связываться ни с тем ни с другим - для создания оконных приложений под Win есть куда более адекватные альтернативы, се-таки на дворе XXI век как-никак.

четверг, 9 апреля 2020 г.

Сделать несворачивающееся окно (по Win+D) [not topmost]

#winapi

                    
Чисто WinAPI, язык не принципиален.

Ситуация такая: делаю окно, оно НЕ topmost, и оно должно оставаться на экране при
нажатии Win+M и Win+D. Сейчас проверяю на Win7, но должно работать для любой.
Win+M вроде победил, а вот со вторым... Не могу понять, как вообще работает Win+D
- окну не приходят сообщения, которые я логически ожидал при сворачивании/перемещении.
А если как-то и получается заметить что свернули - не выходит запретить сворачивание.
Есть стандартная программа, которая имеет нужное поведение, но Spy++ вообще не может
ничего в ней отловить, даже под админом (первый раз такое увидел).

Проблема, что при нажатии Win+D окна пропадают (сворачиваются). А не должны. Кто-то
сталкивался с вопросом?

P.S. Возможно следует использовать какие-то новые интерфейсы оболочки Shell или DWM,
но никак не найду какие. :(
    


Ответы

Ответ 1



Надо изменить родительское окно, чтобы оно принадлежало Рабочему столу. Также может понадобиться предварительно отключить его отображение на панели задач. SetWindowLongPtr Me.hWnd, GWLP_HWNDPARENT, &H800F0 Где &H800F0 - это хэндл рабочего стола. Обращаю внимание, что вариант SetParent Me.hWnd, &H800F0 не годится, поскольку он делает окно частью рабочего стола, и любые (даже неактивные) окна будут отображаться поверх него. PS: Проверял на VB6, пришлось ещё в дизайнере формы выставить ShowInTaskbar = False, в противном случае окно сворачивается. Хендл рабочего стола узнал при помощи Spy++.

вторник, 31 марта 2020 г.

Как получить информацию о подключенном устройстве?

#linux #windows #qt #winapi #usb


Я пишу на С++, использую Qt под Windows. Мне надо получить: название модели, изготовителя,
серийный номер устройства(видео камеры, фото , квадрокоптера , флешки или SD Card)
и путь до устройства. Желательно кроссплатформенное решение.


Есть ответ SetupDiGetDeviceProperty. Но тут не кроссплатформенное решение , к тому
же я не совсем понимаю как получить путь до устройства.
Читал о библиотеки libusb. Но тут не выводятся название модели, изготовителя, серийный
номер устройства. То что выводиться :

Dev (bus 2, device 0): 8086 - 1E31
Dev (bus 1, device 4): 04A9 - 1795
Dev (bus 1, device 3): A4Tech - USB Mouse
Dev (bus 3, device 0): 8086 - 1E26
Dev (bus 1, device 1): 8087 - 0024
Dev (bus 1, device 0): 8086 - 1E2D
Dev (bus 1, device 2): 0BDA - 0151
Dev (bus 1, device 6): Logitech Inc. - Logitech USB Headset H340
Dev (bus 3, device 2): 8087 - 0024
Dev (bus 3, device 3): Logitech - USB Keyboard
Dev (bus 3, device 1): 04A9 - 3206


Хотя была вставлена флешка и подключена камера.
Есть изящное решение этой задачи. Если кто сталкивался с такой задачей поделитесь
кодом пожалуйста.
    


Ответы

Ответ 1



К сожалению, используя библиотеку libusb под Windows нельзя вытянуть всю эту информацию без установки специального драйвера WinUSB. Можно только получить VID и PID (шестнадцатеричные значения типа 8086 - 1E31 в вашем примере), и по ним найти производителя и устройство в таблице известных идентификаторов, например здесь. Производителя и серийный номер можно получить, используя Setup API и IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION. Букву диска тоже можно получить только средствами Setup API, это несколько сложнее. Для этого нужно вначале построить таблицу номеров дисков для всех используемых букв дисков с помощью IOCTL_STORAGE_GET_DEVICE_NUMBER; затем открыть интересующее устройство (запоминающее устройство, которое является дочерним для USB-устройства), найти его номер тем же IOCTL, сравнить его со значениями из таблицы и таким образом определить букву. Как-то так: #include #include #include #include #include #include #include #undef LowSpeed #include #include #pragma comment(lib,"Setupapi.lib") void ErrorMes(LPCTSTR lpszFunction) { // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the error message lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen(lpszFunction) + 40) * sizeof(TCHAR)); wprintf(L"%s failed with error %d: %s", lpszFunction, dw, lpMsgBuf); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); } //Поиск номера диска для USB-устройства BOOL FindDiskNumber(LPCWSTR match, STORAGE_DEVICE_NUMBER* lpret){ BOOL retval = FALSE; DEVPROPTYPE dpt=0; wchar_t buffer[1024]=L""; TCHAR id_upper[1024]=L""; DWORD RequiredSize = 0; SP_DEVINFO_DATA devinfo = { 0 }; SP_DEVICE_INTERFACE_DATA deviceInterface = { 0 }; PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetail = NULL; BOOL res; HDEVINFO deviceInfoHandle = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (deviceInfoHandle != INVALID_HANDLE_VALUE) { int deviceIndex = 0; while (true) { ZeroMemory(&deviceInterface,sizeof(deviceInterface)); deviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); //получение всех дисков if (SetupDiEnumDeviceInterfaces(deviceInfoHandle, 0, &GUID_DEVINTERFACE_DISK, deviceIndex, &deviceInterface)) { DWORD cbRequired = 0; SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterface, 0, 0, &cbRequired, 0); if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { deviceInterfaceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(new char[cbRequired]); memset(deviceInterfaceDetail, 0, cbRequired); deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if (!SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterface, deviceInterfaceDetail, cbRequired, &cbRequired, 0)) { goto Next; } // Initialize the structure before using it. memset(deviceInterfaceDetail, 0, cbRequired); deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Call the API a second time to retrieve the actual // device path string. BOOL status = SetupDiGetDeviceInterfaceDetail( deviceInfoHandle, // Handle to device information set &deviceInterface, // Pointer to current node in devinfo set deviceInterfaceDetail, // Pointer to buffer to receive device path cbRequired, // Length of user-allocated buffer &cbRequired, // Pointer to arg to receive required buffer length NULL); // Not interested in additional data //получение информации о устройстве ZeroMemory(&devinfo,sizeof(devinfo)); devinfo.cbSize = sizeof(SP_DEVINFO_DATA); BOOL success = SetupDiEnumDeviceInfo(deviceInfoHandle, deviceIndex, &devinfo); if(success==FALSE){ErrorMes(L"SetupDiEnumDeviceInfo"); goto Next;} res=SetupDiGetDeviceProperty(deviceInfoHandle,&devinfo, &DEVPKEY_Device_Parent,&dpt,(PBYTE)buffer,1000,NULL,0); if(res==FALSE){ErrorMes(L"SetupDiGetDeviceProperty");goto Next;} int len = wcslen(buffer); for(int i=0;iDevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if(handle==INVALID_HANDLE_VALUE) { ErrorMes(L"CreateFile");goto Next; } STORAGE_DEVICE_NUMBER sdn = {0}; DWORD nbytes = 0; //получение номера диска res = DeviceIoControl(handle, // handle to device IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode NULL, // lpInBuffer 0, // nInBufferSize (LPVOID) &sdn, // output buffer (DWORD) sizeof(sdn), // size of output buffer (LPDWORD) &nbytes, // number of bytes returned NULL // OVERLAPPED structure ); CloseHandle(handle); if(res != FALSE){ //устройство найдено memcpy(lpret,&sdn,sizeof(sdn)); retval = TRUE; } else ErrorMes(L"DeviceIoControl"); } } } else { break; } Next: if(deviceInterfaceDetail != NULL){ delete[] deviceInterfaceDetail; deviceInterfaceDetail = NULL; } if(retval != FALSE) break; //устройство уже найдено deviceIndex++; //следующее устройство } SetupDiDestroyDeviceInfoList(deviceInfoHandle); } else ErrorMes(L"SetupDiGetClassDevs"); return retval; } //таблица номеров для всех дисков bool disk_IsUsed[30]={0}; STORAGE_DEVICE_NUMBER disk_number[30]={0}; int _tmain(int argc, _TCHAR* argv[]) { setlocale(LC_ALL,"Russian"); HANDLE hVol; DWORD nbytes; WCHAR letter; WCHAR volume[100]={0}; int i; STORAGE_DEVICE_NUMBER sdn={0}; //заполняем таблицу номеров для дисков for(i=0;i<30;i++){ letter = 'A' + i; wsprintf(volume,L"\\\\.\\%c:",letter); disk_IsUsed[i] = FALSE; hVol = CreateFile( volume, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(hVol == NULL || hVol == INVALID_HANDLE_VALUE){continue;} BOOL ret = DeviceIoControl(hVol, // handle to device IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode NULL, // lpInBuffer 0, // nInBufferSize (LPVOID) &(disk_number[i]), // output buffer (DWORD) sizeof(STORAGE_DEVICE_NUMBER), // size of output buffer (LPDWORD) &nbytes, // number of bytes returned NULL // OVERLAPPED structure ); CloseHandle(hVol); if(ret == FALSE){continue;} disk_IsUsed[i] = TRUE; } WCHAR match[1024]={0}; GUID guid = { 0xF18A0E88, 0xC30C, 0x11D0, { 0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8 } }; /*USB HUB Interface class GUID*/ HDEVINFO deviceInfoHandle = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (deviceInfoHandle != INVALID_HANDLE_VALUE) { int deviceIndex = 0; while (true) { SP_DEVICE_INTERFACE_DATA deviceInterface = { 0 }; deviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); //получение всех USB-концентраторов if (SetupDiEnumDeviceInterfaces(deviceInfoHandle, 0, &guid, deviceIndex, &deviceInterface)) { DWORD cbRequired = 0; SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterface, 0, 0, &cbRequired, 0); if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(new char[cbRequired]); memset(deviceInterfaceDetail, 0, cbRequired); deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if (!SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterface, deviceInterfaceDetail, cbRequired, &cbRequired, 0)) { delete[] deviceInterfaceDetail; deviceIndex++; continue; } // Initialize the structure before using it. memset(deviceInterfaceDetail, 0, cbRequired); deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Call the API a second time to retrieve the actual // device path string. BOOL status = SetupDiGetDeviceInterfaceDetail( deviceInfoHandle, // Handle to device information set &deviceInterface, // Pointer to current node in devinfo set deviceInterfaceDetail, // Pointer to buffer to receive device path cbRequired, // Length of user-allocated buffer &cbRequired, // Pointer to arg to receive required buffer length NULL); // Not interested in additional data BOOL res; /*Открываем устройство для отправки IOCTL*/ HANDLE handle = CreateFile(deviceInterfaceDetail->DevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if(handle!=INVALID_HANDLE_VALUE) { DWORD bytes_read=0; UINT ports = 0; USB_NODE_INFORMATION nodeinfo; USB_NODE_CONNECTION_INFORMATION_EX coninfo={0}; const UINT BUFSIZE = 1000; char buffer[BUFSIZE]={0}; USB_DESCRIPTOR_REQUEST* req = (USB_DESCRIPTOR_REQUEST*)&buffer; USB_STRING_DESCRIPTOR* desc; ZeroMemory(&nodeinfo,sizeof(nodeinfo)); nodeinfo.NodeType = UsbHub; //получаем число портов на концентраторе res=DeviceIoControl(handle,IOCTL_USB_GET_NODE_INFORMATION , &nodeinfo,sizeof(nodeinfo),&nodeinfo,sizeof(nodeinfo),&bytes_read,0); if(res==FALSE)ErrorMes(L"DeviceIoControl"); else ports = (UINT)nodeinfo.u.HubInformation.HubDescriptor.bNumberOfPorts; for(int j=1;j<=ports;j++){ ZeroMemory(&coninfo,sizeof(coninfo)); coninfo.ConnectionIndex=j; //получаем инфу о порте res=DeviceIoControl(handle,IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX , &coninfo,sizeof(coninfo),&coninfo,sizeof(coninfo),&bytes_read,0); if(res==FALSE){ErrorMes(L"DeviceIoControl");continue;} if(coninfo.ConnectionStatus==0) continue; //нет устройства printf("\n- Hub %2d, Port %2d: USB v%x device\n",deviceIndex, j,(int)coninfo.DeviceDescriptor.bcdUSB); printf("VID: %04X PID: %04X\n",(int)coninfo.DeviceDescriptor.idVendor ,(int)coninfo.DeviceDescriptor.idProduct); //формируем строку для поиска устройства wsprintf(match,L"VID_%04X&PID_%04X",(UINT)coninfo.DeviceDescriptor.idVendor ,(UINT)coninfo.DeviceDescriptor.idProduct); /*Serial number*/ ZeroMemory(buffer,BUFSIZE); req->ConnectionIndex=j; req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) + coninfo.DeviceDescriptor.iSerialNumber; req->SetupPacket.wLength = BUFSIZE - sizeof(USB_DESCRIPTOR_REQUEST); req->SetupPacket.wIndex = 0x409; //US English res=DeviceIoControl(handle,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION , &buffer,sizeof(buffer),&buffer,sizeof(buffer),&bytes_read,0); if(res==FALSE){ErrorMes(L"DeviceIoControl");continue;} desc = (USB_STRING_DESCRIPTOR*)(&req->Data[0]); wprintf(L"Serial: %s\n",desc->bString); /*Vendor*/ ZeroMemory(buffer,BUFSIZE); req->ConnectionIndex=j; req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) + coninfo.DeviceDescriptor.iManufacturer; req->SetupPacket.wLength = BUFSIZE - sizeof(USB_DESCRIPTOR_REQUEST); req->SetupPacket.wIndex = 0x409; //US English res=DeviceIoControl(handle,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION , &buffer,sizeof(buffer),&buffer,sizeof(buffer),&bytes_read,0); if(res==FALSE){ErrorMes(L"DeviceIoControl");continue;} desc = (USB_STRING_DESCRIPTOR*)(&req->Data[0]); wprintf(L"Vendor: %s\n",desc->bString); /*Product*/ ZeroMemory(buffer,BUFSIZE); req->ConnectionIndex=j; req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) + coninfo.DeviceDescriptor.iProduct; req->SetupPacket.wLength = BUFSIZE - sizeof(USB_DESCRIPTOR_REQUEST); req->SetupPacket.wIndex = 0x409; //US English res=DeviceIoControl(handle,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION , &buffer,sizeof(buffer),&buffer,sizeof(buffer),&bytes_read,0); if(res==FALSE){ErrorMes(L"DeviceIoControl");continue;} desc = (USB_STRING_DESCRIPTOR*)(&req->Data[0]); wprintf(L"Product: %s\n",desc->bString); /*Disk letter*/ res = FindDiskNumber(match,&sdn); if(res != FALSE) { for(i=0;i<30;i++) if( disk_IsUsed[i] !=FALSE && disk_number[i].DeviceNumber == sdn.DeviceNumber && disk_number[i].DeviceType == sdn.DeviceType) { letter = 'A' + i; printf("Disk letter: %c\n",letter); } } else printf("Disk letter not found\n"); } CloseHandle(handle); }else{ ErrorMes(L"CreateFile");//failed to open device }//endif delete[] deviceInterfaceDetail; } } else { break; } ++deviceIndex; } SetupDiDestroyDeviceInfoList(deviceInfoHandle); } else ErrorMes(L"SetupDiGetClassDevs"); system("PAUSE"); return 0; } Должно вывести подобный результат: ‐ Hub 3, Port 1: USB v200 device VID: 8564 PID: 1000 Serial: 5B94314A Vendor: JetFlash Product: Mass Storage Device Disk letter: G ‐ Hub 3, Port 4: USB v110 device VID: 09DA PID: 000A Serial: ? Vendor: A4Tech Product: USB Mouse Disk letter not found ‐ Hub 3, Port 6: USB v110 device VID: 046E PID: 5505 Serial: ? Vendor: BTC Product: USB Multimedia Keyboard Disk letter not found ‐ Hub 3, Port 10: USB v200 device VID: 04E8 PID: 689E Serial: 1234567890ABCDEF Vendor: SAMSUNG Electronics Co., Ltd. Product: Samsung Android USB Device Disk letter: H

Имитация нажатии клавиши

#cpp #qt #winapi #visual_cpp #qt5


Имитацию нажатии клавиши делаю так: 

keybd_event('C', 0,0,0);
keybd_event('C', 0,KEYEVENTF_KEYUP,0);


Как сделать что бы имитация нажатии клавиши было только в определенном окне
    


Ответы

Ответ 1



Нет Windows ОС под рукой, чтобы проверить, но все же, попробуйте. HWND wndHndl = FindWindow(_T("ApplicationName"), NULL); PostMessage(wndHndl, WM_KEYDOWN, VK_A, 0);

понедельник, 30 марта 2020 г.

Как сделать рекурсивный поиск по файлам только определенного расширения?

#cpp #winapi #файловая_система


void getFiles(const string& inpath, string outpath)
{
    string mask = inpath + "\\*";
    WIN32_FIND_DATA FindFileData;
    HANDLE hf;
    hf = FindFirstFile(mask.c_str(), &FindFileData);

    ofstream output;
    output.open(outpath + "\\data.txt", ios_base::app);

    if (hf != INVALID_HANDLE_VALUE)
    {
        do
        {
            if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                if (strcmp(FindFileData.cFileName, ".") == 0 ||
                    strcmp(FindFileData.cFileName, "..") == 0) continue;
                getFiles(inpath + "\\" + FindFileData.cFileName, outpath);
            }
            else
                output << inpath << "\\" << FindFileData.cFileName << endl;

        } while (FindNextFile(hf, &FindFileData) != 0);
        FindClose(hf);
    }

    output.close();
}


Есть такая функция, которая ищет файлы в выбранном каталоге и его подкаталогах, а
потом записывает пути к файлам в data.txt. А как мне сделать так, чтобы эта функция
искала только файлы с определенным расширением, например, .xml?
    


Ответы

Ответ 1



Вызов поиска файлов несколько раз с разными расширениями - неверная концепция. Работа с таблицей файлов (на диске) медленнее, чем обработка строк. Поэтому соберите все расширения в хэш-таблицу, список, массив или даже в одну строку, просканируйте файлы единожды с универсальной маской *. Для каждого найденного файла выделите его расширение и проверьте, есть ли оно в выбранной структуре, хранящей нужные расширения.

Как избежать подвисания программы во время ожидания выполнения другой через CreateProcess?

#delphi #winapi


Запускаю программу Delphi, открывается форма, нажимаю на кнопку, происходит выполнение
команды через cmd.exe. Мне нужно дождаться завершения ее выполнения. И пока команда
не выполниться - у меня сама форма (программа) Delphi находится в замороженном состоянии.
Мне нужно, чтобы сама форма (программа) Delphi - не была в замороженном состоянии.
То есть её можно было передвигать. Как сделать, чтобы окно программы Delphi в процессе
выполнения CMD.exe не застывало? То есть обработка в отдельном потоке.

var
  LCmd: string;
  LInfo: TStartupInfo;
  LPI: TProcessInformation;
begin
  // Заполняем структуры
  LCmd := 'cmd.exe ' + SPar;
  FillChar(LInfo, SizeOf(LInfo), 0);
  LInfo.cb := SizeOf(LInfo);
  LInfo.dwFlags := STARTF_USESHOWWINDOW;
  LInfo.wShowWindow := SW_HIDE;
  // Запускаем программу
  Win32Check(CreateProcess(
    'cmd.exe',        // lpApplicationName,
    PChar(LCmd),      // lpCommandLine,
    nil,              // lpProcessAttributes,
    nil,              // lpThreadAttributes,
    False,            // bInheritHandles,
    CREATE_NO_WINDOW, // dwCreationFlags,
    nil,              // lpEnvironment,
    nil,              // lpCurrentDirectory,
    LInfo,            // lpStartupInfo,
    LPI               // lpProcessInformation
  ));
  try
    // Закрываем хендл главного потока (он нам не нужен)
    CloseHandle(LPI.hThread);
    // Ждем завершения процесса
    Win32Check(WaitForSingleObject(LPI.hProcess, INFINITE) <> WAIT_FAILED);
  finally
    // Закрываем хендл процесса
    CloseHandle(LPI.hProcess);
  end;
  ShowMessage('Программа завершена');
end;

    


Ответы

Ответ 1



Чтобы дождаться завершения программы не замораживая интерфейс, нужно делать ожидание в отдельном потоке. А потом уведомить основной поток о завершении операции type TWaitThread = class(TThread) private FWaitHandle: THandle; protected procedure Execute; override; public constructor Create(ACreateSuspended: Boolean; AWaitHandle: THandle); destructor Destroy; override; end; constructor TWaitThread.Create(ACreateSuspended: Boolean; AWaitHandle: THandle); begin inherited Create(ACreateSuspended); FWaitHandle := AWaitHandle; end; destructor TWaitThread.Destroy; begin CloseHandle(FWaitHandle); inherited Destroy; end; procedure TWaitThread.Execute; begin // Ждем завершения процессса Win32Check(WaitForSingleObject(FWaitHandle, INFINITE) <> WAIT_FAILED); end; // И использование var .......... LPI: TProcessInformation; LThread: TThread; begin .......... Win32Check(CreateProcess(......, LPI)); CloseHandle(LPI.hThread); // Создаем ждущий поток LThread := TWaitThread.Create(True, LPI.hProcess); // Поток удалится при завершении LThread.FreeOnTerminate := True; // После завершения вызвать процедуру EndWait LThread.OnTerminate := EndWait; // Запускаем поток LThread.Start; end; procedure TForm1.EndWait(Sender: TObject); begin ShowMessage('Программа завершена'); end;

Как оживить кнопки? Win32

#cpp #winapi


Создал окно программы с пунктами и подпунктами. Каким образом можно оживить Кнопки?
Например как сделать чтобы по нажатию на "Файл">"Выход" программа закрывалась? Я в
этом очень плохо что понимаю, скорее даже ничего...

 #include "stdafx.h"
#include 
#include 
#define IDM_SHOW      1001
#define IDM_ERASE     1002
#define IDM_EXIT      1003
#pragma comment(lib, "ComCtl32.lib")

TCHAR czClassName[] = L"myClass";
TCHAR czFormName[] = L"Это мое окно";
HWND hwndA;
const WCHAR wString[] = L"Hello";
#define countof(a) (sizeof(a)/sizeof(*(a)))
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hDeviceContext;
    PAINTSTRUCT paintStruct;
    RECT rectPlace;
    HFONT hFont;
    static char text[2] = { ' ','\0' };
    switch (message)
    {
    case WM_COMMAND:
        if (HIWORD(wParam) == 0 && lParam == 0) {    // If a menu item has been selected
            switch (LOWORD(wParam)) {
            case IDM_SHOW:
                MessageBox(NULL,
                    L"Покулитый Руслан",
                    L"121-18ск-1", MB_ICONASTERISK | MB_OK);
                break;


            case IDM_ERASE:
                ::SendMessage(hwnd, WM_CLOSE, 0, 0);

                    break;


            case IDM_EXIT:
                PostQuitMessage(0);
                break;
            }
            break;

    default: return DefWindowProc(hwnd, message, wParam, lParam); break;
        }
    }
}

ATOM myRegistryClass(HINSTANCE hInst, int cmdMode)
{
    WNDCLASS cw;

    cw.style = CS_VREDRAW | CS_HREDRAW;
    cw.cbClsExtra = 0;
    cw.cbWndExtra = 0;
    cw.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
    cw.hCursor = LoadCursor(NULL, IDC_ARROW);
    cw.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    cw.hInstance = hInst;
    cw.lpfnWndProc = WndProc;
    cw.lpszClassName = czClassName;
    cw.lpszMenuName = NULL;

    RegisterClass(&cw);

    return 0;
}


BOOL InitInstance(HINSTANCE hInst, int Mode)
{


    hwndA = CreateWindow(
        czClassName,
        czFormName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInst,
        NULL);

    ShowWindow(hwndA, Mode);
    UpdateWindow(hwndA);

    return TRUE;
}


/*Главная функция*/
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR IpszCmdParam,
int cmdShow)
{
    MSG msg;

    myRegistryClass(hInst, cmdShow);
    InitInstance(hInst, cmdShow);

    InitCommonControls();

    /*Создание строки состояния*/
    HWND hStatusWindow = CreateStatusWindow(WS_CHILD | WS_VISIBLE, L"", hwndA, 5000);

    HMENU hmenu1;
    hmenu1 = CreateMenu();

    HMENU hMainMenu = CreateMenu();
    HMENU hPopMenuFile = CreatePopupMenu();
    HMENU hPopMenuPravka = CreatePopupMenu();
    HMENU hPopMenuPomosh = CreatePopupMenu();

    AppendMenu(hMainMenu, MF_STRING | MF_POPUP, (UINT)hPopMenuFile, L"Файл");
    AppendMenu(hMainMenu, MF_STRING | MF_POPUP, (UINT)hPopMenuPravka, L"Правка");
    AppendMenu(hMainMenu, MF_STRING | MF_POPUP, (UINT)hPopMenuPomosh, L"Помощь");


    AppendMenu(hPopMenuFile, MF_STRING, 1001, L"Показать");
    AppendMenu(hPopMenuFile, MF_STRING, 1003, L"Выход");
    AppendMenu(hPopMenuPravka, MF_STRING, 1002, L"Стереть");

    SetMenu(hwndA, hMainMenu);
    SetMenu(hwndA, hPopMenuFile);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

    


Ответы

Ответ 1



Во-первых, у вас ошибка в AppendMenu - две разные команды имеют один и тот же идентификатор 1001. Во-вторых, меню, акселераторы, кнопки, и прочие экранные элементы при активации генерируют сообщение WM_COMMAND. Для обработки команд меню в вашу оконную процедуру надо добавить примерно такой код (я добавил символьные идентификаторы для ваших команд): #define IDM_SHOW 1001 #define IDM_ERASE 1002 #define IDM_EXIT 1003 switch (message) { . . . case WM_COMMAND: if (HIWORD(wParam) == 0 && lParam == 0) { // If a menu item has been selected switch (LOWORD(wParam)) { case IDM_SHOW: . . . break; case IDM_ERASE: . . . break; case IDM_EXIT: ::SendMessage(hwnd, WM_CLOSE, 0, 0); break; } } break;

воскресенье, 15 марта 2020 г.

Реализация condition variables

#cpp #windows #winapi


Подскажите правильную реализацию condition variables. Реализовал на WaitForMultipleObjects()
и PulseEvent() , и получил баг, когда поток не просыпался, оказалось это проблема в
PulseEvent(). Подскажите правильную реализацию в которой поток будет точно просыпаться
и работать как надо.
    


Ответы

Ответ 1



Начиная с Vista, WinAPI содержит синхронизационные примитивы наподобие CONDITION_VARIABLE, которые делают именно то, что вам нужно. Вот пример использования (из официальной документации): CONDITION_VARIABLE cv; CRITICAL_SECTION lock; InitializeConditionVariable (&cv); InitializeCriticalSection (&lock); ... // ожидание EnterCriticalSection(&lock); while (!(условие)) // защищаемся от spurious wakeup SleepConditionVariableCS(&cv, &lock, INFINITE); // работать с данными можно только внутри критической секции // и при выполнении условия работаем_с_данными(); LeaveCriticalSection(&lock);

пятница, 13 марта 2020 г.

Использование “красивых” стилей элементов окна

#cpp #winapi #mingw


Пытаюсь в окне сделать кнопку.

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    HFONT hFont;
    HWND hButton;
    switch(message) {
    case WM_CREATE:
        hButton = CreateWindow("button", "Press me!",
                               WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                               5, 5, 100, 100,
                               hWnd, (HMENU)(1),
                               (HINSTANCE)GetWindowLong(hWnd, -6), NULL);
        hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
        SendMessage(hButton, WM_SETFONT, (WPARAM)hFont, 1);
        return 0 ;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, message, wParam, lParam) ;
}


Получается такая:



А как сделать кнопку, по стилю как в остальных приложениях (такую, например: ). Система
Windows 7, компилятор gcc.exe (tdm64-1) 5.1.0.
    


Ответы

Ответ 1



Действительно, как сказал Abyx, надо было добавить манифест (я надеялся, что есть путь проще). В итоге порядок действий: Создать файл Application.manifest (например в директории с main.c): Just button. Создать файл ресурсов resources.rc в той же директории, что и манифест, в которой будет одна строка: 1 24 "Application.manifest" Далее нужно скомпилировать файл ресурсов (выполнить команду в командной строке): windres resources.rc -o resources.o Нужно добавить некоторый код в main.cpp: #define _WIN32_WINNT 0x0600 //для запуска нужна система Vista или новее #include #include int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { INITCOMMONCONTROLSEX icex; icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_STANDARD_CLASSES; InitCommonControlsEx(&icex); /* Далее код создания окна и все остальное */ } Ну и теперь нужно непосредственно скомпилировать программу (естественно надо не забыть про библиотеку): g++ -o program.exe main.cpp resources.o -lcomctl32 -mwindows

понедельник, 9 марта 2020 г.

Обработчик нажатия правой кнопки мыши

#cpp #c #winapi


На winApi пишу сапер. 

Имеется массив кнопок, и нужно для каждой кнопки установить обработчик нажатия правой
клавиши мыши над ней. Можно ли это реализовать? Каким образом?
    


Ответы

Ответ 1



Смотря, что за кнопка. Если кнопка - отдельное окно, то обрабатывайте сообщения мыши в WndProc. Создайте массив типа HWND и заполните его окнами(которые будете использовать, как кнопки), у которых один общий WndProc.Идентифицируйте, какая кнопка нажата с помощью цикла.Ниже код HWND hwnds[100]={NULL}; hwnds[0]=CreateWindow(...); hwnds[1]=CreateWindow(...); LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wp,LPARAM lp) { switch(message) { case WM_RBUTTONDOWN: for(int i(0);i<100;i++) if(hwnds[i]==NULL) { break; } else if(hwnd==hwnds[i]) { ...//Окно найдено } break; } } Если кнопка стандартная, Шиндоусовская(но это тоже окно, насколько я помню), то через WM_COMMAND.Не пользуюсь, этим убожеством, поэтому код подсказать не могу. Но дам ссылку http://www.firststeps.ru/mfc/winapi/r.php?62 Бонус Рисуете прямоугольник, который будет Вашей кнопкой. При нажатии на окно(на котором Вы нарисовали прямоугольник) обрабатываете WM_RBUTTONDOWN\UP. Если коодрдинаты клика подходят, значит - кнопка нажата. Как это сделать: LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wp,LPARAM lp) { POINT cp; GetCursorPos(&cp);//ну Вы поняли switch(message) { case WM_PAINT: ... Rectangle(hdc,10,10,50,30); ... break; case WM_RBUTTONUP: {//не забудьте про скобки, если хотите объявить переменные внутри case`a RECT r; GetWindowRect(hwnd,&r); int x=cp.x-r.left;//делаем координаты клика, относительно окна int y=cp.y-r.top;//делаем координаты клика, относительно окна if(x>10 && x<50 && y>10 && y<30) { ...//тык } } break; } }

Узнать относительный адрес внутри проекции PE-файла

#cpp #winapi #pe


Есть один известный крэкми. После его изучения оказывается, что для его взлома достаточно
пропатчить два байта по адресу 40138B (забить условный переход NOP'ами) и два байта
по адресу 401243 (прописать там безусловный переход). Я хочу написать программу, которая
делает это автоматически.

#include 
#include 
#include 
#include 

enum {OK, CANT_OPEN};

int patch (TCHAR* fname)
{
    char first_patch[2]  = {0x90, 0x90};    // NOP NOP
    char second_patch[2] = {0xEB, 0x07};    // JMP 40124C
    HANDLE hFile = CreateFile(fname,
                              FILE_ALL_ACCESS, NULL,
                              NULL, OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
        return CANT_OPEN;

    int SizeFile  = GetFileSize(hFile, NULL);
    HANDLE MhFile = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, SizeFile, 0);
    HANDLE View   = MapViewOfFile(MhFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);

    UnmapViewOfFile(View);
    CloseHandle(hFile);
    CloseHandle(MhFile);
    return OK;
}

int main (int argc, char *argv[])
{
    TCHAR* default_fname = "CRACKME.EXE";

    if (argc > 1)
    {
        default_fname = argv[1];
    }

    patch(default_fname);

    std::cout << default_fname << std::endl;
    return 0;
}


Я спроецировал исполняемый файл в адресное пространство процесса и получил адрес
этой проекции. Теперь надо пропатчить этот образ, после чего процедура UnmapViewOfFile
сохранит изменения на диск.

Как в этой проекции найти адреса типа 40138B и 401243? Где можно посмотреть теорию
и примеры по редактированию PE-файлов?

Далее пишу хрень, можно не читать.
Успешно напечатал сигнатуру MZ, это значит, что при помощи View можно заполнять структуры
заголовков, используя, возможно, для выравнивания макросы Криса Касперски.

char M = *((char *) View);
char Z = *((char *) View + 1);
std::cout << M << Z << std::endl;


Проверка того, что заголовок дос успешно загружен. Потом добавлю код для отлавливания
возможных ошибок.

unsigned myRVAtoRAW(HANDLE pe_image, unsigned rva)
{
    IMAGE_DOS_HEADER dos_header;
    std::memcpy(reinterpret_cast(&dos_header), pe_image, sizeof(dos_header));

    std::cout << (dos_header.e_magic == 'ZM') << std::endl;
    return 0;
}

    


Ответы

Ответ 1



Можно пойти двумя путями: Разобраться и написать самому. Тогда рекомендую почитать статью: Разработка функций RvaToRaw и RawToRva. Либо воспользоваться функций из известной dbghelp.dll. Я бы посоветовал разобраться, благо это не сложно. Также следует отметить знаменитую статью Об упаковщиках в последний раз: Часть первая - теоретическая

Ответ 2



Что касаемо патчинга: int main() { HWND hWnd = FindWindow(0, "Calculator"); if(hWnd == 0){ MessageBox(0, "Error cannot find window.", "Error", MB_OK|MB_ICONERROR); } else { DWORD proccess_ID; GetWindowThreadProcessId(hWnd, &proccess_ID); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proccess_ID); if(!hProcess){ MessageBox(0, "Could not open the process!", "Error!", MB_OK|MB_ICONERROR); } else { DWORD newdatasize = sizeof(newdata); if(WriteProcessMemory(hProcess, (LPVOID)0x40138B , "0x90", newdatasize, NULL)){ MessageBox(NULL, "WriteProcessMemory worked.", "Success", MB_OK + MB_ICONINFORMATION); } else { MessageBox(NULL, "Error cannot WriteProcessMemory!", "Error", MB_OK + MB_ICONERROR); } CloseHandle(hProcess); } } return 0; } Адреса искать по паттерну(уникальной сигнатуре), сделать ее можно в любом отладчике

суббота, 7 марта 2020 г.

Зачем windows позволяет создавать приватные кучи?

#winapi #memory #memory_management


Каждый процесс в ОС Windows имеет по умолчанию свою кучу, размер которой в будущем
может быть изменен. Более того, каждый процесс способен так же создавать кучу с определенным,
наперед заданным начальным и максимальным размером (такая куча будет называться приватной).
Зачем такая возможность существует в Windows? Чтобы оптимизировать реаллокации? Но
тогда не достаточно ли в таком случае использования обычной кучи по умолчанию?
    


Ответы

Ответ 1



При создании кучи можно задавать наличие следующих параметров: HEAP_CREATE_ENABLE_EXECUTE — разместить кучу на страницах с правом на исполнение. Подобное можно использовать для JIT-компиляции небольших фрагментов кода, когда выделение целой 4КБ страницы на фрагмент было бы излишним. HEAP_GENERATE_EXCEPTIONS — выбрасывать SEH-исключения из функций управления кучей. HEAP_NO_SERIALIZE — разменять поддержку многоточности на скорость выделения/высвобождения блоков кучи. В куче по умолчанию ничего из вышеперечисленного не включено.

четверг, 5 марта 2020 г.

Буфер — это обязательно Heap?

#winapi #ассемблер #указатели


Здравствуйте, скажите пожалуйста, вот во многих (по крайне мере которые я встречал)
строковых-winapi'шных функциях следует передавать указатель на некий буфер, буфер обязательно
должен быть заранее выделенной кучей (Heap)? Можно отправить указатель например на
заранее зарезервированный массив байт?
    


Ответы

Ответ 1



Лишь бы эта память была корректна во время работы с ней (ну и, конечно же, доступна для записи-чтения :)). Например, при выделении памяти в стеке следует не забывать, что она будет корректна только до окончания вызова функции. А так - что выделите, то и годится :)

Как получит HWND окна при наведении на него курсора мыши?

#cpp #qt #winapi


Как получить HWND окна при наведении на него курсора мыши С++ WinApi32 или Qt?
    


Ответы

Ответ 1



Функция HWNDWindowFromPoint(POINT Point) поможет вам.

среда, 4 марта 2020 г.

Узнать загруженность CPU C++

#cpp #c #windows #winapi


Здравствуйте, пытаюсь разбираться с WIN32 API, реши написать что-то на подобии диспетчера
задач, но никак не могу понять как узнать нагруженность CPU и его температуру(если
это возможно)... 
Понял как узнать архитектуру процессора : 

LPCSTR getArchitecture()
{
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    LPCSTR architecture;

    switch (sysInfo.wProcessorArchitecture)
    {
    case PROCESSOR_ARCHITECTURE_INTEL :
        architecture = "Intel x86";
        break;
    case PROCESSOR_ARCHITECTURE_IA64 :
        architecture = "Intel x64";
        break;
    case PROCESSOR_ARCHITECTURE_AMD64 :
        architecture = "AMD x64";
        break;
    case PROCESSOR_AMD_X8664:
        architecture = "AMD x86";
        break;
    default:
        architecture = "Unknow";
        break;  
    }

    return architecture;
}


Также понял, как узнать количество ядер процессора:

UINT const getCountCernels() 
{
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    return sysInfo.dwNumberOfProcessors;
}


Хотелось бы получить внятный ответ как можно узнать нагруженность процессора желательно
для каждого ядра... 
    


Ответы

Ответ 1



Температуру процессора вряд ли получится узнать без проблем, можно сделать WMI запрос по MSAcpi_ThermalZoneTemperature, но это даст только температуру где - то на материнской плате (это может быть далеко от процессора), и то, этого может не быть в материнке вообще. Правильным решением будет писать драйвера. Для этого нужно с помощью инструкции rdmsr получить IA32_THERM_STATUS, если мы говорим о 32 - bit Intel Architecture, для этого надо будет получить доступ в kernel space (ring 0 права)

Ответ 2



Через PDH-функции, в общих чертах, загрузка ядра добывается так: Через PdhOpenQuery создается PDH_HQUERY Через PdhAddEnglishCounter с использованием запроса из п.1 инициализируются счетчики. Путь к счетчику - "\\Processor(0)\\%% Idle Time", где 0 - номер ядра Через PdhCollectQueryData получаются данные PdhGetFormattedCounterValue получает из счетчика значение. Нужно указать тип PDH_FMT_DOUBLE. Из 100 нужно вычесть полученное в п.5 значение ... PROFIT!

воскресенье, 1 марта 2020 г.

Как лучше всего проверить, что окно существует?

#c_sharp #windows #visual_studio #winapi


Допустим, я пишу функцию, которая по значению дескриптора должна вернуть логическое
значение, существует ли окно с таким дескриптором. Я представляю огромное количество
реализаций - от перебора всех окон через GetProcesses или EnumWindow и до вызова какой-нибудь
функции, принимающей hwnd, и возвращающую результат. А может я все усложняю, а такая
функция входит в user32. В общем, как будет лучше и быстрее?
    


Ответы

Ответ 1



Есть WinApi функция IsWindow, но как пишут в этом ответе хендл может переназначаться => если вы пасете определенное окно и хотите проверить его существование, то окно может быть уже закрыто, но хендл с таким же номером был создан для другого окна. [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool IsWindow(IntPtr hWnd); Получается, что имеет смысл воспользоваться вот этой функцией, если у окна есть специфическое название GetWindowText , она вернет Caption окна и можно удостоверится, что именно желаемое окно живо. Через WinApi я думаю, что быстрее. Что лучше? Все зависит от того, как часто вы это собираетесь делать. Если не часто, то я бы не заморачивался и выполнял итерацию по процессам.

пятница, 28 февраля 2020 г.

Ошибка при вызове WSAPoll()

#cpp #c #winapi #клиент_сервер #winsock


Пишу простой UDP сервер под Windows, который принимает сообщения от клиентов. По
заданию сокеты должны работать в неблокирующем режиме и обязательно нужно использовать
WSAPoll для параллельного обслуживания клиентов. Написал небольшую обертку для сокета:

class _socket
{
private:
    SOCKET      sock;
    sockaddr_in addr;
public:
    _socket(int port);
    _socket(const _socket & other);
    ~_socket();

    SOCKET GetSocket();
    bool   Generate();
    bool   Bind();
};

_socket::~_socket() 
{
    if (sock != INVALID_SOCKET) 
    {
        closesocket(sock); 
    } 
}

_socket::_socket(int port) : sock(INVALID_SOCKET) 
{
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port); 
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
}

_socket::_socket(const _socket & other)
{
    this->sock = other.sock;
    this->addr = other.addr;
}

SOCKET _socket::GetSocket()
{
     return (this->sock); 
}
bool _socket::Generate()
{
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        return false;
    }
    else
    {
        unsigned long mode = 1;
        return (ioctlsocket(sock, FIONBIO, &mode) != SOCKET_ERROR);
    }
}
bool _socket::Bind()
{
    return (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) >= 0);
}


Вот так работаю с ним в main (через argv передаю диапазон портов):

int main(int argc, const char *argv[])
{
    std::vector<_socket>        sockets;
    std::map clients;

    if (argc < 3)
    {
        return ErrorPrint("Too low arguments");
    }
    if (!Init())
    {
        return ErrorPrint("Error starting WSA");
    }

    for (int i = atoi(argv[1]); i <= atoi(argv[2]); i++)
    {
        _socket s(i);
        if (!s.Generate())
        {
            return ErrorPrint("Cannot create socket");
        }
        if (!s.Bind())
        {
            return ErrorPrint("Cannot bind socket");
        }
        sockets.push_back(s);
    }

    WSAPOLLFD *pfd = (WSAPOLLFD*)malloc(sockets.size() * sizeof(WSAPOLLFD));

    for (int i = 0; i < sockets.size(); i++)
    {
        pfd[i].fd      = sockets[i].GetSocket();
        pfd[i].events  = POLLIN | POLLOUT;
        pfd[i].revents = 0;
    }

    while (true)
    {
        int ev_cnt = WSAPoll(pfd, sockets.size(), 1000);
        if (ev_cnt > 0)
        {
            for (int i = 0; i < sockets.size(); i++)
            {
                if (pfd[i].revents & POLLERR)
                {

                }
                if (pfd[i].revents & POLLIN)
                {

                }
                if (pfd[i].revents & POLLOUT)
                {

                }
            }
        }
        else if (ev_cnt == SOCKET_ERROR)
        {
            std::cout << "Error WSAPoll: " << WSAGetLastError() << std::endl; //
Постоянно попадаю сюда
        }
        else
        {
            std::cout << "waiting..." << std::endl;
        }
    }

    return (EXIT_SUCCESS);
}


При вызове WSAPoll постоянно получаю ошибку WSAENOTSOCK (10038), которая говорит
мне, что я пытаюсь выполнить операцию, предназначенную для сокета на чем-то, что им
не является. Прочитал спецификации к WSAPoll - вроде все делаю правильно, никак не
могу понять, что сделал не так.
    


Ответы

Ответ 1



У вас реализован конструктор копирования после выполнения которого в двух экземплярах класса будет хранится один и тот же дескриптор сокета. После разрушения одного из экземпляров второй останется с невалидным дескриптором. Следовало реализовать конструктор перемещения (и перемещающий оператор присваивания): _socket(const _socket & other) = delete; _socket(_socket && other) : sock{other.sock} , addr{other.addr} { other.sock = INVALID_SOCKET; ::std::memset(::std::addressof(other.addr), 0, sizeof(other.addr)); } Сокеты на самом деле можно дублировать используя WSADuplicateSocket, но обычно это не нужно.

WINAPI GetMessageW не перестает принимать сообщения после вызова PostQuitMessage

#cpp #c #winapi


По каким причинам происходит следующее, если в функцию GetMessageW, 2м параметром
передать HWND окна, при вызове PostQuitMessage в процедуре окна при получении сообщения
WM_DESTROY, окно просто закрывается, но не уничтожается, и цикл обработки сообщений
окна продолжает работать? При это, если передать NULL или nullptr, то при таком раскладе
все отрабатывает нормально?

Так работает нормально

MSG msg{};
while (GetMessageW(&msg, nullptr, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessageW(&msg);
}


Но вот так, уже не завершится цикл.

MSG msg{};
while (GetMessageW(&msg, m_window_handle_, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessageW(&msg);
}


Помимо GetMessageW, c PeekMessageW происходит та же ситуация, т.е. сообщение WM_QUIT
не доходит.
    


Ответы

Ответ 1



Если получен WM_DESTROY, то окно уничтожается, его дескриптор становится невалидным, а функция GetMessageW будет продолжать вызываться с невалидным параметром и возвращать ошибку, но так как проверка возвращаемого значения сделана неверно, то цикл будет продолжать крутится. В документации прямо сказано, что так делать не стоит: Because the return value can be nonzero, zero, or -1, avoid code like this: while (GetMessage( lpMsg, hWnd, 0, 0)) ...