|
|
//
// 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; }
|