https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ec91188fffe6df11881c2…
commit ec91188fffe6df11881c2c72b6a3cf98c18308c8
Author: Giannis Adamopoulos <gadamopoulos(a)reactos.org>
AuthorDate: Thu Feb 22 19:15:45 2018 +0200
Commit: Giannis Adamopoulos <gadamopoulos(a)reactos.org>
CommitDate: Mon Feb 26 16:51:59 2018 +0200
[WINSRV] Implement sending the hard error balloon package to explorer
[EXPLORER] Implement showing the hard error balloon
---
base/shell/explorer/syspager.cpp | 1 +
base/shell/explorer/taskswnd.cpp | 118 ++++++++++++++++++++++++++++++++
sdk/include/reactos/undocuser.h | 11 +++
win32ss/user/winsrv/usersrv/harderror.c | 83 ++++++++++++++++++++--
4 files changed, 209 insertions(+), 4 deletions(-)
diff --git a/base/shell/explorer/syspager.cpp b/base/shell/explorer/syspager.cpp
index 7be7eeb694..fa2aa73b36 100644
--- a/base/shell/explorer/syspager.cpp
+++ b/base/shell/explorer/syspager.cpp
@@ -1207,6 +1207,7 @@ void CNotifyToolbar::Initialize(HWND hWndParent, CBalloonQueue *
queue)
const WCHAR szSysPagerWndClass[] = L"SysPager";
CSysPagerWnd::CSysPagerWnd() {}
+
CSysPagerWnd::~CSysPagerWnd() {}
LRESULT CSysPagerWnd::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam,
BOOL& bHandled)
diff --git a/base/shell/explorer/taskswnd.cpp b/base/shell/explorer/taskswnd.cpp
index 590dc4062d..60b047a7dc 100644
--- a/base/shell/explorer/taskswnd.cpp
+++ b/base/shell/explorer/taskswnd.cpp
@@ -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)
diff --git a/sdk/include/reactos/undocuser.h b/sdk/include/reactos/undocuser.h
index dea855684c..dbe93b2ac9 100644
--- a/sdk/include/reactos/undocuser.h
+++ b/sdk/include/reactos/undocuser.h
@@ -204,6 +204,17 @@ BOOL WINAPI PaintMenuBar(HWND hWnd, HDC hDC, ULONG left, ULONG right,
ULONG top,
#define DrawCaptionTemp DrawCaptionTempA
#endif
+//
+// Hard error balloon package
+//
+typedef struct _BALLOON_HARD_ERROR_DATA
+{
+ DWORD cbHeaderSize;
+ DWORD Status;
+ DWORD dwType; /* any combination of the MB_ message box types */
+ ULONG_PTR TitleOffset;
+ ULONG_PTR MessageOffset;
+} BALLOON_HARD_ERROR_DATA, *PBALLOON_HARD_ERROR_DATA;
//
// User api hook
diff --git a/win32ss/user/winsrv/usersrv/harderror.c
b/win32ss/user/winsrv/usersrv/harderror.c
index 52e22a89d4..54d4b52764 100644
--- a/win32ss/user/winsrv/usersrv/harderror.c
+++ b/win32ss/user/winsrv/usersrv/harderror.c
@@ -439,6 +439,69 @@ UserpFormatMessages(
return Status;
}
+static BOOL
+UserpShowInformationBalloon(PWSTR Text,
+ PWSTR Caption,
+ PHARDERROR_MSG Message)
+{
+ HWND hwnd;
+ COPYDATASTRUCT CopyData;
+ PBALLOON_HARD_ERROR_DATA pdata;
+ DWORD dwSize, cchText, cchCaption;
+ PWCHAR pText, pCaption;
+ DWORD ret, dwResult;
+
+ hwnd = GetTaskmanWindow();
+ if (!hwnd)
+ {
+ DPRINT1("Failed to find Shell_TrayWnd\n");
+ return FALSE;
+ }
+
+ cchText = wcslen(Text);
+ cchCaption = wcslen(Caption);
+
+ dwSize = sizeof(BALLOON_HARD_ERROR_DATA);
+ dwSize += (cchText + 1) * sizeof(WCHAR);
+ dwSize += (cchCaption + 1) * sizeof(WCHAR);
+
+ pdata = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
+ if (!pdata)
+ {
+ DPRINT1("Failed to allocate balloon package\n");
+ return FALSE;
+ }
+
+ pdata->cbHeaderSize = sizeof(BALLOON_HARD_ERROR_DATA);
+ pdata->Status = Message->Status;
+ if (NT_SUCCESS(Message->Status))
+ pdata->dwType = MB_OK;
+ else if (Message->Status == STATUS_SERVICE_NOTIFICATION)
+ pdata->dwType = Message->Parameters[2];
+ else
+ pdata->dwType = MB_ICONINFORMATION;
+ pdata->TitleOffset = pdata->cbHeaderSize;
+ pdata->MessageOffset = pdata->TitleOffset;
+ pdata->MessageOffset += (cchCaption + 1) * sizeof(WCHAR);
+ pCaption = (PWCHAR)((ULONG_PTR)pdata + pdata->TitleOffset);
+ pText = (PWCHAR)((ULONG_PTR)pdata + pdata->MessageOffset);
+ wcscpy(pCaption, Caption);
+ wcscpy(pText, Text);
+
+ CopyData.dwData = RegisterWindowMessageW(L"HardError");
+ CopyData.cbData = dwSize;
+ CopyData.lpData = pdata;
+
+ dwResult = FALSE;
+
+ ret = SendMessageTimeoutW(hwnd, WM_COPYDATA, 0, (LPARAM)&CopyData,
+ SMTO_NORMAL | SMTO_ABORTIFHUNG, 3000, &dwResult);
+
+ RtlFreeHeap(RtlGetProcessHeap(), 0, pdata);
+
+ return (ret && dwResult) ? TRUE : FALSE;
+}
+
static
ULONG
UserpMessageBox(
@@ -475,10 +538,9 @@ UserpMessageBox(
break;
case OptionOkNoWait:
/*
- * This gives a balloon notification.
- * See rostests/kmtests/ntos_ex/ExHardError.c
+ * At that point showing the balloon failed. Is that correct?
*/
- Type = MB_YESNO; // FIXME!
+ Type = MB_OK; // FIXME!
break;
case OptionCancelTryContinue:
Type = MB_CANCELTRYCONTINUE;
@@ -583,6 +645,20 @@ UserServerHardError(
return;
}
+ if (Message->ValidResponseOptions == OptionOkNoWait)
+ {
+ /* Display the balloon */
+ if (UserpShowInformationBalloon(TextU.Buffer,
+ CaptionU.Buffer,
+ Message))
+ {
+ Message->Response = ResponseOk;
+ RtlFreeUnicodeString(&TextU);
+ RtlFreeUnicodeString(&CaptionU);
+ return;
+ }
+ }
+
/* Display the message box */
Message->Response = UserpMessageBox(TextU.Buffer,
CaptionU.Buffer,
@@ -591,7 +667,6 @@ UserServerHardError(
RtlFreeUnicodeString(&TextU);
RtlFreeUnicodeString(&CaptionU);
-
return;
}