https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ec91188fffe6df11881c2c...
commit ec91188fffe6df11881c2c72b6a3cf98c18308c8 Author: Giannis Adamopoulos gadamopoulos@reactos.org AuthorDate: Thu Feb 22 19:15:45 2018 +0200 Commit: Giannis Adamopoulos gadamopoulos@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; }