You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
5.9 KiB
231 lines
5.9 KiB
//
|
|
// 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;
|
|
}
|
|
|
|
|