2025-04-27 07:49:33 -04:00

287 lines
7.4 KiB
C++

#include "windows.h"
#include "shellapi.h"
#include "wchar.h"
#include "stdio.h"
#include <initguid.h>
#include "hangcom.h"
#include "resource.h"
enum EHangToUse
{
htuLoop = IDC_LOOP,
htuEvent = IDC_EVENT,
htuPipe = IDC_PIPE,
htuCOM = IDC_COM,
};
struct SDlgInit
{
EHangToUse htu;
HANDLE hev;
LPWSTR wsz;
};
BOOL g_fImmediate = FALSE;
// **************************************************************************
void HangmeSleepLoop(HANDLE hevUnhang)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
DWORD dw = 0;
for(;;)
{
dw += 1;
dw *= 2;
dw %= 101;
dw /= 2;
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
}
// **************************************************************************
void HangmeEvent(HANDLE hevUnhang)
{
HANDLE hev = NULL;
HANDLE rghWait[2] = { NULL, NULL };
DWORD cWait;
hev = CreateEventW(NULL, FALSE, FALSE, NULL);
if (hev == NULL)
return;
rghWait[0] = hev;
cWait = 1;
if (hevUnhang)
{
rghWait[1] = hevUnhang;
cWait = 2;
}
WaitForMultipleObjects(cWait, rghWait, FALSE, INFINITE);
CloseHandle(hev);
return;
}
// **************************************************************************
void HangmePipe(HANDLE hevUnhang)
{
OVERLAPPED ol;
HANDLE hpipe = NULL, hev = NULL;
HANDLE rghWait[2] = { NULL, NULL };
DWORD cWait, dwMsg;
BOOL fRet;
hev = CreateEventW(NULL, FALSE, FALSE, NULL);
if (hev == NULL)
return;
hpipe = CreateNamedPipeW(L"\\\\.\\pipe\\ERHangTestPipeThisIsOnlyATest",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1, sizeof(dwMsg), sizeof(dwMsg),
60000, NULL);
if (hpipe == NULL)
return;
ZeroMemory(&ol, sizeof(ol));
ol.hEvent = hev;
fRet = ConnectNamedPipe(hpipe, &ol);
if (GetLastError() != ERROR_IO_PENDING)
SetEvent(ol.hEvent);
rghWait[0] = hev;
cWait = 1;
if (hevUnhang)
{
rghWait[1] = hevUnhang;
cWait = 2;
}
WaitForMultipleObjects(cWait, rghWait, FALSE, INFINITE);
CloseHandle(hev);
return;
}
// **************************************************************************
void HangmeCOM(HANDLE hevUnhang)
{
HRESULT hr;
IHang *pHang = NULL;
hr = CoInitialize(NULL);
if (FAILED(hr))
return;
hr = CoCreateInstance(CLSID_Hang, NULL, CLSCTX_SERVER, IID_IHang,
(LPVOID *)&pHang);
if (FAILED(hr))
{
CoUninitialize();
return;
}
hr = pHang->DoHang((UINT64)hevUnhang, GetCurrentProcessId());
CoUninitialize();
return;
}
// **************************************************************************
INT_PTR CALLBACK dlgFn(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SDlgInit *pdlginit;
WCHAR wszBuffer[1024];
HWND hwnd;
switch(uMsg)
{
case WM_PAINT:
if (g_fImmediate)
{
g_fImmediate = FALSE;
PostMessage(hdlg, WM_COMMAND, IDC_HANG, 0);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hdlg, LOWORD(wParam));
break;
case IDC_HANG:
// do this so that this message will return
PostMessage(hdlg, WM_APP, 0, 0);
break;
default:
break;
}
break;
case WM_INITDIALOG:
pdlginit = (SDlgInit *)lParam;
SetWindowLongPtr(hdlg, GWLP_USERDATA, lParam);
CheckRadioButton(hdlg, IDC_LOOP, IDC_COM, (int)pdlginit->htu);
// set the notify field
if (pdlginit->wsz != NULL)
{
wsprintfW(wszBuffer, L"Click the 'Hang' Button below to hang this window. The dialog will not repaint while hung .\nExecute 'unhang.exe %ls' to reawaken the app.", pdlginit->wsz);
hwnd = GetDlgItem(hdlg, IDC_MYTEXT);
SetWindowTextW(hwnd, wszBuffer);
}
break;
case WM_APP:
pdlginit = (SDlgInit *)GetWindowLongPtr(hdlg, GWLP_USERDATA);
if (IsDlgButtonChecked(hdlg, IDC_COM) == BST_CHECKED)
HangmeCOM(pdlginit->hev);
else if (IsDlgButtonChecked(hdlg, IDC_PIPE) == BST_CHECKED)
HangmePipe(pdlginit->hev);
else if (IsDlgButtonChecked(hdlg, IDC_EVENT) == BST_CHECKED)
HangmeEvent(pdlginit->hev);
else if (IsDlgButtonChecked(hdlg, IDC_LOOP) == BST_CHECKED)
HangmeSleepLoop(pdlginit->hev);
break;
}
return FALSE;
}
// **************************************************************************
extern "C" int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int)
{
SDlgInit sdi;
WCHAR **argv, *wszCmdLine, *wszEvent = NULL;
int argc, i;
wszCmdLine = GetCommandLineW();
argv = CommandLineToArgvW(wszCmdLine, &argc);
ZeroMemory(&sdi, sizeof(sdi));
sdi.htu = htuLoop;
if (argc == 2 && argv[1][0] != L'/' && argv[1][0] != L'-')
{
wszEvent = argv[1];
}
else
{
for(i = 1; i < argc; i++)
{
if (argv[i][0] == L'/' || argv[i][0] == L'-')
{
switch(argv[i][1])
{
case L'L':
case L'l':
sdi.htu = htuLoop;
break;
case L'E':
case L'e':
sdi.htu = htuEvent;
break;
case L'C':
case L'c':
sdi.htu = htuCOM;
break;
case L'P':
case L'p':
sdi.htu = htuPipe;
break;
case L'U':
case L'u':
if (i + 1 < argc)
wszEvent = argv[++i];
break;
case L'G':
case L'g':
g_fImmediate = TRUE;
break;
}
}
}
}
if (wszEvent != NULL)
{
sdi.hev = CreateEventW(NULL, TRUE, FALSE, wszEvent);
if (sdi.hev == NULL)
{
WCHAR wszBuf[256];
wsprintfW(wszBuf, L"Unable to create event %ls.", wszEvent);
MessageBoxW(NULL, wszBuf, NULL, MB_OK);
}
else
{
sdi.wsz = wszEvent;
}
}
DialogBoxParamW(hInstance, MAKEINTRESOURCEW(IDD_HANG), NULL, dlgFn, (LPARAM)&sdi);
if (sdi.hev !=- NULL)
CloseHandle(sdi.hev);
return 0;
}