windows-nt/Source/XPSP1/NT/shell/ext/hnw/nconn32/hookui.cpp
2020-09-26 16:20:57 +08:00

232 lines
5.7 KiB
C++

//
// HookUI.cpp
//
// Code to hook the standard NetDI UI, so we can get progress
// notifications and warn the user if he clicks Cancel.
//
// History:
//
// 2/02/1999 KenSh Created for JetNet
// 9/29/1999 KenSh Repurposed for Home Networking Wizard
//
#include "stdafx.h"
#include "NetConn.h"
#include "TheApp.h"
#include "../NConn16/NConn16.h"
// Global data
//
BOOL g_bUserAbort;
// Local data
//
static HHOOK g_hHook;
static HWND g_hwndParent;
static HWND g_hwndCopyFiles;
static PROGRESS_CALLBACK g_pfnProgress;
static LPVOID g_pvProgressParam;
static WNDPROC g_pfnPrevCopyFilesWndProc;
static WNDPROC g_pfnPrevProgressWndProc;
// Local functions
//
LRESULT CALLBACK SubclassCopyFilesWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SubclassProgressWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WindowCreateHook(int nCode, WPARAM wParam, LPARAM lParam);
VOID BeginSuppressNetdiUI(HWND hwndParent, PROGRESS_CALLBACK pfnProgress, LPVOID pvProgressParam)
{
g_hwndParent = hwndParent;
g_pfnProgress = pfnProgress;
g_pvProgressParam = pvProgressParam;
g_hHook = SetWindowsHookEx(WH_CBT, WindowCreateHook, NULL, GetCurrentThreadId());
g_bUserAbort = FALSE;
}
VOID EndSuppressNetdiUI()
{
UnhookWindowsHookEx(g_hHook);
}
LRESULT CALLBACK SubclassCopyFilesWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
#if 0 // Code like this would help hide the progress bar from the user
LONG dwExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
dwExStyle |= WS_EX_TOOLWINDOW;
SetWindowLong(hwnd, GWL_EXSTYLE, dwExStyle);
SetParent(hwnd, NULL);
#endif
}
break;
#if 0 // Code like this would help hide the progress bar from the user
case WM_WINDOWPOSCHANGING:
{
LPWINDOWPOS lpwp = (LPWINDOWPOS)lParam;
RECT rcParent;
GetWindowRect(g_hwndParent, &rcParent);
lpwp->x = rcParent.left + 50;
lpwp->y = rcParent.top + 30;
lpwp->hwndInsertAfter = g_hwndParent;
lpwp->flags &= ~SWP_NOZORDER;
}
break;
#endif
case WM_COMMAND:
{
UINT uNotifyCode = HIWORD(wParam);
int idCtrl = (int)(UINT)LOWORD(wParam);
if (idCtrl == IDCANCEL)
{
// Check for a Cancel button with an "OK" label (yes, this happens)
// TODO: check if this is correct even in localized Windows
TCHAR szMsg[256];
GetDlgItemText(hwnd, IDCANCEL, szMsg, _countof(szMsg));
if (0 != lstrcmpi(szMsg, "OK"))
{
LoadString(g_hInstance, IDS_ASKCANCEL_NOTSAFE, szMsg, _countof(szMsg));
TCHAR szTitle[100];
LoadString(g_hInstance, IDS_APPTITLE, szTitle, _countof(szTitle));
int nResult = MessageBox(hwnd, szMsg, szTitle, MB_OKCANCEL | MB_ICONEXCLAMATION);
if (nResult == IDCANCEL)
return 0;
// Set a global (yuck) so we know for sure if the user clicked the
// Cancel button, rather than some other error
g_bUserAbort = TRUE;
}
}
}
break;
}
LRESULT lResult = CallWindowProc(g_pfnPrevCopyFilesWndProc, hwnd, message, wParam, lParam);
return lResult;
}
LRESULT CALLBACK SubclassProgressWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// TCHAR szBuf[512];
// wsprintf(szBuf, "Message %u, wParam = 0x%08x, lParam = 0x%08x\r\n", message, wParam, lParam);
// OutputDebugString(szBuf);
static DWORD dwMin = 0;
static DWORD dwMax = 0;
switch (message)
{
case (WM_USER+1):
dwMin = LOWORD(lParam);
dwMax = HIWORD(lParam);
break;
case (WM_USER+2):
{
DWORD dwCur = wParam;
if (g_pfnProgress != NULL)
{
if (!(*g_pfnProgress)(g_pvProgressParam, dwCur - dwMin, dwMax - dwMin))
{
// TODO: try to abort somehow - press the cancel button?
}
}
}
break;
}
return CallWindowProc(g_pfnPrevProgressWndProc, hwnd, message, wParam, lParam);
}
LRESULT CALLBACK WindowCreateHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_CREATEWND)
{
HWND hwnd = (HWND)wParam;
CBT_CREATEWND* pCW = (CBT_CREATEWND*)lParam;
if (g_hwndParent == pCW->lpcs->hwndParent)
{
g_hwndCopyFiles = hwnd;
// OutputDebugString("Found a copy-files window window, looking for progress bar...\r\n");
g_pfnPrevCopyFilesWndProc = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)SubclassCopyFilesWndProc);
// TODO: remove this test-only code
// if (cWindows < _countof(rgWindowTitles))
// {
// lstrcpyn(rgWindowTitles[cWindows], pCW->lpcs->lpszName, _countof(rgWindowTitles[cWindows]));
// cWindows += 1;
// }
}
else if (g_hwndCopyFiles != NULL && g_hwndCopyFiles == pCW->lpcs->hwndParent)
{
if (!lstrcmp(pCW->lpcs->lpszClass, "setupx_progress"))
{
// OutputDebugString("Found a progress bar!\r\n");
if (g_pfnProgress != NULL)
{
g_pfnPrevProgressWndProc = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)SubclassProgressWndProc);
}
}
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
// HresultFromCCI
//
// Given a return code from CallClassInstaller16, converts to a JetNet
// HRESULT return code.
//
HRESULT HresultFromCCI(DWORD dwErr)
{
HRESULT hr = NETCONN_SUCCESS;
if (dwErr == ICERR_NEED_RESTART || dwErr == ICERR_NEED_REBOOT)
{
hr = NETCONN_NEED_RESTART;
}
else if ((dwErr & ICERR_DI_ERROR) == ICERR_DI_ERROR)
{
dwErr &= ~ICERR_DI_ERROR;
// ks 8/4/99: we now use global g_bUserAbort to detect abort conditions
#if 0
// NetDI returns ERR_VCP_IOFAIL if the user clicks Cancel. Go figure.
// Or sometimes it returns ERR_NDI_INVALID_DRIVER_PROC. Really go figure.
if (dwErr == ERR_VCP_INTERRUPTED || dwErr == ERR_VCP_IOFAIL || dwErr == ERR_NDI_INVALID_DRIVER_PROC)
{
hr = JETNET_USER_ABORT;
}
else
#endif // 0
{
hr = NETCONN_UNKNOWN_ERROR;
}
}
else if ((LONG)dwErr < 0)
{
hr = NETCONN_UNKNOWN_ERROR;
}
return hr;
}