mirror of
https://github.com/reactos/reactos.git
synced 2024-11-30 23:13:31 +08:00
[WINSRV] Implement sending the hard error balloon package to explorer
[EXPLORER] Implement showing the hard error balloon
This commit is contained in:
parent
40bd09a2ce
commit
ec91188fff
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user