[WINSRV] Implement sending the hard error balloon package to explorer

[EXPLORER] Implement showing the hard error balloon
This commit is contained in:
Giannis Adamopoulos 2018-02-22 19:15:45 +02:00
parent 40bd09a2ce
commit ec91188fff
4 changed files with 209 additions and 4 deletions

View file

@ -99,6 +99,103 @@ typedef struct _TASK_ITEM
};
} TASK_ITEM, *PTASK_ITEM;
class CHardErrorThread
{
DWORD m_ThreadId;
HANDLE m_hThread;
LONG m_bThreadRunning;
DWORD m_Status;
DWORD m_dwType;
CStringW m_Title;
CStringW m_Text;
public:
CHardErrorThread():
m_ThreadId(0),
m_hThread(NULL),
m_bThreadRunning(FALSE),
m_Status(NULL),
m_dwType(NULL)
{
}
~CHardErrorThread()
{
if (m_bThreadRunning)
{
/* Try to unstuck Show */
PostThreadMessage(m_ThreadId, WM_QUIT, 0, 0);
DWORD ret = WaitForSingleObject(m_hThread, 3*1000);
if (ret == WAIT_TIMEOUT)
TerminateThread(m_hThread, 0);
CloseHandle(m_hThread);
}
}
HRESULT ThreadProc()
{
HRESULT hr;
CComPtr<IUserNotification> pnotification;
hr = OleInitialize(NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = CoCreateInstance(CLSID_UserNotification,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IUserNotification, &pnotification));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pnotification->SetBalloonInfo(m_Title, m_Text, NIIF_WARNING);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pnotification->SetIconInfo(NULL, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
/* Show will block until the balloon closes */
hr = pnotification->Show(NULL, 0);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return S_OK;
}
static DWORD CALLBACK s_HardErrorThreadProc(IN OUT LPVOID lpParameter)
{
CHardErrorThread* pThis = reinterpret_cast<CHardErrorThread*>(lpParameter);
pThis->ThreadProc();
CloseHandle(pThis->m_hThread);
OleUninitialize();
InterlockedExchange(&pThis->m_bThreadRunning, FALSE);
return 0;
}
void StartThread(PBALLOON_HARD_ERROR_DATA pData)
{
BOOL bIsRunning = InterlockedExchange(&m_bThreadRunning, TRUE);
/* Ignore the new message if we are already showing one */
if (bIsRunning)
return;
m_Status = pData->Status;
m_dwType = pData->dwType;
m_Title = (PWCHAR)((ULONG_PTR)pData + pData->TitleOffset);
m_Text = (PWCHAR)((ULONG_PTR)pData + pData->MessageOffset);
m_hThread = CreateThread(NULL, 0, s_HardErrorThreadProc, this, 0, &m_ThreadId);
if (!m_hThread)
{
m_bThreadRunning = FALSE;
CloseHandle(m_hThread);
}
}
};
class CTaskToolbar :
public CWindowImplBaseT< CToolbar<TASK_ITEM>, CControlWinTraits >
{
@ -222,6 +319,9 @@ class CTaskSwitchWnd :
SIZE m_ButtonSize;
UINT m_uHardErrorMsg;
CHardErrorThread m_HardErrorThread;
public:
CTaskSwitchWnd() :
m_ShellHookMsg(NULL),
@ -238,6 +338,7 @@ public:
m_IsDestroying(FALSE)
{
ZeroMemory(&m_ButtonSize, sizeof(m_ButtonSize));
m_uHardErrorMsg = RegisterWindowMessageW(L"HardError");
}
virtual ~CTaskSwitchWnd() { }
@ -1821,6 +1922,22 @@ public:
return 0;
}
LRESULT OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
PCOPYDATASTRUCT cpData = (PCOPYDATASTRUCT)lParam;
if (cpData->dwData == m_uHardErrorMsg)
{
/* A hard error balloon message */
PBALLOON_HARD_ERROR_DATA pData = (PBALLOON_HARD_ERROR_DATA)cpData->lpData;
ERR("Got balloon data 0x%x, 0x%x, %S, %S!\n", pData->Status, pData->dwType, (WCHAR*)((ULONG_PTR)pData + pData->TitleOffset), (WCHAR*)((ULONG_PTR)pData + pData->MessageOffset));
if (pData->cbHeaderSize == sizeof(BALLOON_HARD_ERROR_DATA))
m_HardErrorThread.StartThread(pData);
return TRUE;
}
return FALSE;
}
HRESULT Initialize(IN HWND hWndParent, IN OUT ITrayWindow *tray)
{
m_Tray = tray;
@ -1864,6 +1981,7 @@ public:
MESSAGE_HANDLER(m_ShellHookMsg, OnShellHook)
MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
MESSAGE_HANDLER(WM_KLUDGEMINRECT, OnKludgeItemRect)
MESSAGE_HANDLER(WM_COPYDATA, OnCopyData)
END_MSG_MAP()
DECLARE_NOT_AGGREGATABLE(CTaskSwitchWnd)