Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1898 lines
48 KiB

/*
* UI.C -- Contains all UI code for modem setup.
*
* Microsoft Confidential
* Copyright (c) Microsoft Corporation 1993-1994
* All rights reserved
*
*/
#include "proj.h"
// Instance data structure for the Port_Add callback
typedef struct tagPORTINFO
{
HWND hwndLB;
DWORD dwFlags; // FP_*
TCHAR szPortExclude[MAX_BUF_REG];
} PORTINFO, FAR * LPPORTINFO;
// Flags for PORTINFO
#define FP_PARALLEL 0x00000001
#define FP_SERIAL 0x00000002
#define FP_MODEM 0x00000004
#define Wiz_SetPtr(hDlg, lParam) SetWindowLong(hDlg, DWL_USER, ((LPPROPSHEETPAGE)lParam)->lParam)
#define SetDlgFocus(hDlg, idc) SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, idc), 1L)
#define WM_STARTDETECT (WM_USER + 0x0700)
#define WM_STARTINSTALL (WM_USER + 0x0701)
#define WM_PRESSFINISH (WM_USER + 0x0702)
#ifdef PROFILE_MASSINSTALL
extern DWORD g_dwTimeBegin;
DWORD g_dwTimeAtStartInstall;
#endif
/*----------------------------------------------------------
Purpose: This function retrieves the wizard page shared
instance data. This is a SETUPINFO structure.
Returns:
Cond: --
*/
LPSETUPINFO
PRIVATE
Wiz_GetPtr(
HWND hDlg)
{
LPSETUPINFO psi = (LPSETUPINFO)GetWindowLong(hDlg, DWL_USER);
return psi;
}
/*----------------------------------------------------------
Purpose: This function does the right things to leave the
wizard when something goes wrong.
Returns: --
Cond: --
*/
void
PRIVATE
Wiz_Bail(
IN HWND hDlg,
IN LPSETUPINFO psi)
{
ASSERT(psi);
LeaveInsideWizard(hDlg);
PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
// Don't say the user cancelled. If this wizard is inside another,
// we want the calling wizard to continue.
psi->miw.ExitButton = PSBTN_NEXT;
}
/*----------------------------------------------------------
Purpose: Sets the custom modem select param strings
Returns: --
Cond: --
*/
void
PRIVATE
Wiz_SetSelectParams(
LPSETUPINFO psi)
{
SP_DEVINSTALL_PARAMS devParams;
// Get the DeviceInstallParams
devParams.cbSize = sizeof(devParams);
if (CplDiGetDeviceInstallParams(psi->hdi, psi->pdevData, &devParams))
{
PSP_CLASSINSTALL_HEADER pclassInstallParams = PCIPOfPtr(&psi->selParams);
// The SelectParams are already set and stored in the
// SETUPINFO instance data.
SetFlag(devParams.Flags, DI_USECI_SELECTSTRINGS | DI_SHOWOEM);
// Specify using our GUID to make things a little faster.
SetFlag(devParams.FlagsEx, DI_FLAGSEX_USECLASSFORCOMPAT);
// Set the Select Device parameters
CplDiSetDeviceInstallParams(psi->hdi, psi->pdevData, &devParams);
CplDiSetClassInstallParams(psi->hdi, psi->pdevData, pclassInstallParams,
sizeof(psi->selParams));
}
}
/*----------------------------------------------------------
Purpose: Returns TRUE if the TAPI dial info page should be shown
Returns: see above
Cond: --
*/
BOOL
PRIVATE
Wiz_InitDialInfo(
IN LPSETUPINFO psi)
{
BOOL bRet = FALSE;
ASSERT(psi);
try
{
if (psi->pfnDialInited)
{
// Did the function succeed?
DWORD dwInited;
if (0 == psi->pfnDialInited(&dwInited))
{
// Yes
bRet = (0 == dwInited);
}
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
ASSERT(0); // Uh oh
bRet = FALSE;
psi->pfnDialInited = NULL;
}
return bRet;
}
/*----------------------------------------------------------
Purpose: Select previous page junction dialog
Returns: varies
Cond: --
*/
BOOL
CALLBACK
SelPrevPageDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG:
Wiz_SetPtr(hDlg, lParam);
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE:
// This dialog has no UI. It is simply used as a junction
// to the intro page or the "no modem found" page.
SetDlgMsgResult(hDlg, message,
IsFlagSet(psi->dwFlags, SIF_JUMPED_TO_SELECTPAGE) ?
IDD_WIZ_INTRO :
IDD_WIZ_NOMODEM);
return TRUE;
case PSN_KILLACTIVE:
case PSN_HELP:
case PSN_WIZBACK:
case PSN_WIZNEXT:
break;
default:
return FALSE;
}
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Intro dialog
Returns: varies
Cond: --
*/
BOOL
CALLBACK
IntroDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG:
Wiz_SetPtr(hDlg, lParam);
psi = Wiz_GetPtr(hDlg);
// Restore the cursor from startup hourglass
SetCursor(LoadCursor(NULL, IDC_ARROW));
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE: {
DWORD dwFlags = PSWIZB_NEXT;
// Is this wizard inside another wizard?
if (IsFlagSet(psi->miw.Flags, MIWF_INSET_WIZARD))
{
// Yes; hide the outside wizard
EnterInsideWizard(hDlg);
// Show the Back button on the first page
SetFlag(dwFlags, PSWIZB_BACK);
}
PropSheet_SetWizButtons(GetParent(hDlg), dwFlags);
// Is this wizard being entered thru the last page?
if (IsFlagSet(psi->miw.Flags, MIWF_BACKDOOR))
{
// Yes; skip to the last page
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
}
}
break;
case PSN_KILLACTIVE:
break;
case PSN_HELP:
break;
case PSN_WIZBACK:
if (IsFlagSet(psi->miw.Flags, MIWF_INSET_WIZARD))
{
PostMessage(hDlg, WM_PRESSFINISH, 0, 0);
}
break;
case PSN_WIZNEXT: {
ULONG uNextDlg;
// Go to the last page?
if (IsFlagSet(psi->miw.Flags, MIWF_BACKDOOR))
{
// Yes
uNextDlg = IDD_WIZ_DONE;
}
// Skip the rest of the detection dialogs?
else if (IsDlgButtonChecked(hDlg, IDC_SKIPDETECT))
{
// Yes; go to Select Device page
SetFlag(psi->dwFlags, SIF_JUMPED_TO_SELECTPAGE);
Wiz_SetSelectParams(psi);
uNextDlg = IDD_DYNAWIZ_SELECTDEV_PAGE;
}
else
{
// No; go to detection page
ClearFlag(psi->dwFlags, SIF_JUMPED_TO_SELECTPAGE);
// Are there enough ports on the system to indicate
// we should treat this like a multi-modem install?
if (IsFlagSet(psi->dwFlags, SIF_PORTS_GALORE))
{
// Yes
uNextDlg = IDD_WIZ_SELQUERYPORT;
}
else
{
// No
uNextDlg = IDD_WIZ_DETECT;
}
}
SetDlgMsgResult(hDlg, message, uNextDlg);
break;
}
default:
return FALSE;
}
break;
case WM_PRESSFINISH:
ASSERT(IsFlagSet(psi->miw.Flags, MIWF_INSET_WIZARD));
psi->miw.ExitButton = PSBTN_BACK;
LeaveInsideWizard(hDlg);
PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Status callback used during detection
Returns: varies
Cond: --
*/
BOOL
CALLBACK
Detect_StatusCallback(
IN DWORD nMsg,
IN LPARAM lParam,
IN LPARAM lParamUser) OPTIONAL
{
HWND hDlg = (HWND)lParamUser;
LPSETUPINFO psi;
TCHAR sz[MAX_BUF];
#pragma data_seg(DATASEG_READONLY)
static UINT s_mpstatus[] =
{
0, IDS_DETECT_CHECKFORMODEM, IDS_DETECT_QUERYING, IDS_DETECT_MATCHING,
IDS_DETECT_FOUNDAMODEM, IDS_DETECT_NOMODEM, IDS_DETECT_COMPLETE,
};
#pragma data_seg()
switch (nMsg)
{
case DSPM_SETPORT:
psi = Wiz_GetPtr(hDlg);
if (psi && sizeof(*psi) == psi->cbSize)
{
LPTSTR pszName = (LPTSTR)lParam;
// Is there a friendly name?
if ( !PortMap_GetFriendly(psi->hportmap, pszName, sz, SIZECHARS(sz)) )
{
// No; use port name
lstrcpy(sz, pszName);
}
SetDlgItemText(hDlg, IDC_CHECKING_PORT, sz);
}
break;
case DSPM_SETSTATUS:
if (ARRAYSIZE(s_mpstatus) > lParam)
{
TCHAR szbuf[128];
UINT ids = s_mpstatus[lParam];
if (0 < ids)
LoadString(g_hinst, ids, szbuf, SIZECHARS(szbuf));
else
*szbuf = (TCHAR)0;
SetDlgItemText(hDlg, IDC_DETECT_STATUS, szbuf);
}
break;
case DSPM_QUERYCANCEL:
psi = Wiz_GetPtr(hDlg);
MyYield();
if (psi && sizeof(*psi) == psi->cbSize)
{
return IsFlagSet(psi->dwFlags, SIF_DETECT_CANCEL);
}
return FALSE;
default:
ASSERT(0);
break;
}
return TRUE;
}
/*----------------------------------------------------------
Purpose: WM_STARTDETECT handler
Returns: --
Cond: --
*/
void
PRIVATE
Detect_OnStartDetect(
HWND hDlg,
LPSETUPINFO psi)
{
HDEVINFO hdi;
DWORD dwFlags;
DETECT_DATA dd;
// Cause the page to be painted right away before we start detection
InvalidateRect(hDlg, NULL, FALSE);
UpdateWindow(hDlg);
// Assume no modem was detected
ClearFlag(psi->dwFlags, SIF_DETECTED_MODEM);
// Set the detection parameters
ZeroInit(&dd);
CplInitClassInstallHeader(&dd, DIF_DETECT);
dd.dwFlags = DDF_CONFIRM | DDF_USECALLBACK;
dd.hwndOutsideWizard = GetParent(hDlg);
dd.pfnCallback = Detect_StatusCallback;
dd.lParam = (LPARAM)hDlg;
if (IsFlagSet(psi->dwFlags, SIF_PORTS_GALORE))
{
dd.dwFlags |= DDF_QUERY_SINGLE;
lstrcpy(dd.szPortQuery, psi->szPortQuery);
}
// Run detection
SetFlag(psi->dwFlags, SIF_DETECTING);
dwFlags = DMF_DEFAULT;
CplDiDetectModem(psi->hdi, &dd, hDlg, &dwFlags);
ClearFlag(psi->dwFlags, SIF_DETECTING);
if (IsFlagClear(dwFlags, DMF_CANCELLED))
{
// Say detection is finished and enable next/back buttons
ShowWindow(GetDlgItem(hDlg, IDC_ST_CHECKING_PORT), SW_HIDE);
ShowWindow(GetDlgItem(hDlg, IDC_CHECKING_PORT), SW_HIDE);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
}
if (IsFlagSet(dwFlags, DMF_DETECTED_MODEM))
{
SetFlag(psi->dwFlags, SIF_DETECTED_MODEM);
}
// Did the detection fail?
if (IsFlagClear(dwFlags, DMF_GOTO_NEXT_PAGE))
{
// Yes; don't bother going thru the rest of the wizard
Wiz_Bail(hDlg, psi);
}
else
{
// No; automatically go to next page
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
}
}
/*----------------------------------------------------------
Purpose: Detect dialog
Returns: varies
Cond: --
*/
BOOL CALLBACK DetectDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG:
Wiz_SetPtr(hDlg, lParam);
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), 0);
// Reset the status controls
ShowWindow(GetDlgItem(hDlg, IDC_ST_CHECKING_PORT), SW_SHOW);
SetDlgItemText(hDlg, IDC_DETECT_STATUS, TEXT(""));
ShowWindow(GetDlgItem(hDlg, IDC_CHECKING_PORT), SW_SHOW);
PostMessage(hDlg, WM_STARTDETECT, 0, 0);
break;
case PSN_KILLACTIVE:
case PSN_HELP:
case PSN_WIZBACK:
break;
case PSN_WIZNEXT: {
ULONG uNextDlg;
// Was a modem detected?
if (IsFlagSet(psi->dwFlags, SIF_DETECTED_MODEM))
{
// Yes; is this a multi-modem case?
if (IsFlagSet(psi->dwFlags, SIF_PORTS_GALORE))
{
// Yes
uNextDlg = IDD_WIZ_PORTDETECT;
}
else
{
// No
uNextDlg = IDD_WIZ_INSTALL;
}
}
else
{
// No
uNextDlg = IDD_WIZ_NOMODEM;
}
SetDlgMsgResult(hDlg, message, uNextDlg);
break;
}
case PSN_QUERYCANCEL:
if (IsFlagSet(psi->dwFlags, SIF_DETECTING))
{
SetFlag(psi->dwFlags, SIF_DETECT_CANCEL);
return PSNRET_INVALID;
}
// FALLTHROUGH
default:
return FALSE;
}
break;
case WM_STARTDETECT:
Detect_OnStartDetect(hDlg, psi);
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: No Modem dialog
Returns: varies
Cond: --
*/
BOOL CALLBACK NoModemDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG:
Wiz_SetPtr(hDlg, lParam);
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
break;
case PSN_KILLACTIVE:
case PSN_HELP:
break;
case PSN_WIZBACK:
// Go back to the page that precedes the detection
// page
if (IsFlagSet(psi->dwFlags, SIF_PORTS_GALORE))
{
SetDlgMsgResult(hDlg, message, IDD_WIZ_SELQUERYPORT);
}
else
{
SetDlgMsgResult(hDlg, message, IDD_WIZ_INTRO);
}
break;
case PSN_WIZNEXT:
Wiz_SetSelectParams(psi);
SetDlgMsgResult(hDlg, message, IDD_DYNAWIZ_SELECTDEV_PAGE);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Starts the browser dialog. The selected modem is returned
in psi->lpdiSelected.
Returns: --
Cond: --
*/
BOOL
PRIVATE
SelectNewDriver(
IN HWND hDlg,
IN HDEVINFO hdi,
IN PSP_DEVINFO_DATA pdevData)
{
BOOL bRet = FALSE;
DWORD cbSize;
PSP_CLASSINSTALL_HEADER pparamsSave;
SP_DEVINSTALL_PARAMS devParams;
SP_DEVINSTALL_PARAMS devParamsSave;
SP_SELECTDEVICE_PARAMS sdp;
DBG_ENTER(SelectNewDriver);
ASSERT(hdi && INVALID_HANDLE_VALUE != hdi);
ASSERT(pdevData);
// Determine size of buffer to save current class install params
CplDiGetClassInstallParams(hdi, pdevData, NULL, 0, &cbSize);
// Anything to save?
if (0 == cbSize)
{
// No
pparamsSave = NULL;
}
else
{
// Yes
pparamsSave = (PSP_CLASSINSTALL_HEADER)LocalAlloc(LPTR, cbSize);
if (pparamsSave)
{
pparamsSave->cbSize = sizeof(*pparamsSave);
// Save the current class install params
CplDiGetClassInstallParams(hdi, pdevData, pparamsSave, cbSize, NULL);
}
}
// Set the install params field so the class installer will show
// custom instructions.
CplInitClassInstallHeader(&sdp, DIF_SELECTDEVICE);
CplDiSetClassInstallParams(hdi, pdevData, PCIPOfPtr(&sdp), sizeof(sdp));
// Set the flag to show the Other... button
devParams.cbSize = sizeof(devParams);
if (CplDiGetDeviceInstallParams(hdi, pdevData, &devParams))
{
// Save the current parameters
BltByte(&devParamsSave, &devParams, sizeof(devParamsSave));
SetFlag(devParams.Flags, DI_SHOWOEM);
devParams.hwndParent = hDlg;
// Set the Select Device parameters
CplDiSetDeviceInstallParams(hdi, pdevData, &devParams);
}
bRet = CplDiCallClassInstaller(DIF_SELECTDEVICE, hdi, pdevData);
// Restore the parameters
CplDiSetDeviceInstallParams(hdi, pdevData, &devParamsSave);
if (pparamsSave)
{
// Restore the class install params
CplDiSetClassInstallParams(hdi, pdevData, pparamsSave, cbSize);
LocalFree(LOCALOF(pparamsSave));
}
DBG_EXIT(SelectNewDriver);
return bRet;
}
/*----------------------------------------------------------
Purpose: Sets the static fields for the Found dialog
Returns: --
Cond: --
*/
void
PRIVATE
Found_SetFields(
IN HWND hDlg,
IN LPCTSTR pszPort,
IN LPCTSTR pszDescription,
IN UINT ids,
IN UINT idsInstruct)
{
TCHAR sz[MAX_BUF];
LPTSTR psz;
// Port name
if (ConstructMessage(&psz, g_hinst, MAKEINTRESOURCE(ids), pszPort))
{
SetDlgItemText(hDlg, IDC_ST_PORT, psz);
GFree(psz);
}
// Modem name
SetDlgItemText(hDlg, IDC_NAME, pszDescription);
// Extra instructions
LoadString(g_hinst, idsInstruct, sz, sizeof(sz));
SetDlgItemText(hDlg, IDC_ST_INSTRUCT, sz);
}
/*----------------------------------------------------------
Purpose: Found dialog
Returns: varies
Cond: --
*/
BOOL
CALLBACK
FoundDlgProc(
IN HWND hDlg,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG: {
BOOL bRet;
SP_DRVINFO_DATA drvData;
UINT ids;
UINT idsInstruct;
Wiz_SetPtr(hDlg, lParam);
psi = (LPSETUPINFO)((LPPROPSHEETPAGE)lParam)->lParam;
// Was the modem *accurately* detected?
if (IsFlagClear(psi->dwFlags, SIF_DETECTED_GENERIC))
{
// Yes
ids = IDS_ST_MODEMFOUND;
idsInstruct = IDS_ST_FOUND_INSTRUCT;
}
else
{
// No; detected generic
ids = IDS_ST_NOTDETECTED;
idsInstruct = IDS_ST_GENERIC_INSTRUCT;
}
drvData.cbSize = sizeof(drvData);
bRet = CplDiGetSelectedDriver(psi->hdi, psi->pdevData, &drvData);
if ( !bRet )
{
// This should never happen
ASSERT(0);
Wiz_Bail(hDlg, psi);
}
else
{
// Display only the first (and only) port in the port list
Found_SetFields(hDlg, psi->pszPortList, drvData.Description, ids, idsInstruct);
}
return FALSE;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE:
EnterInsideWizard(hDlg);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
break;
case PSN_KILLACTIVE:
break;
case PSN_HELP:
break;
case PSN_WIZBACK:
break;
case PSN_WIZNEXT:
// Post this message since the property sheet manager
// isn't very good about handling recursive PressButton
// calls.
PostMessage(hDlg, WM_PRESSFINISH, 0, 0);
break;
default:
return FALSE;
}
break;
case WM_PRESSFINISH:
psi->miw.ExitButton = PSBTN_FINISH;
LeaveInsideWizard(hDlg);
PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_CHANGE:
// Bring up the device installer browser to allow the user
// to select a different modem.
if (SelectNewDriver(hDlg, psi->hdi, psi->pdevData))
{
SP_DRVINFO_DATA drvData;
drvData.cbSize = sizeof(drvData);
bRet = CplDiGetSelectedDriver(psi->hdi, psi->pdevData, &drvData);
if ( !bRet )
{
// This should never happen
ASSERT(0);
}
else
{
Found_SetFields(hDlg, psi->pszPortList,
drvData.Description,
IDS_ST_MODEMCHANGED, IDS_ST_FOUND_INSTRUCT);
}
}
break;
}
break;
}
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Get the port filtering flags, based on the selected
driver.
The filtering flags indicate whether to include
serial or parallel ports in the list.
Returns: FP_* bitfield
Cond: --
*/
DWORD
PRIVATE
GetPortFilterFlags(
IN HDEVINFO hdi,
IN PSP_DEVINFO_DATA pdevData,
IN PSP_DRVINFO_DATA pdrvData)
{
DWORD dwRet = FP_SERIAL | FP_PARALLEL | FP_MODEM;
PSP_DRVINFO_DETAIL_DATA pdrvDetail;
SP_DRVINFO_DETAIL_DATA drvDetailDummy;
DWORD cbSize;
drvDetailDummy.cbSize = sizeof(drvDetailDummy);
CplDiGetDriverInfoDetail(hdi, pdevData, pdrvData, &drvDetailDummy,
sizeof(drvDetailDummy), &cbSize);
ASSERT(0 < cbSize); // This should always be okay
pdrvDetail = (PSP_DRVINFO_DETAIL_DATA)LocalAlloc(LPTR, cbSize);
if (pdrvDetail)
{
pdrvDetail->cbSize = sizeof(*pdrvDetail);
if (CplDiGetDriverInfoDetail(hdi, pdevData, pdrvData, pdrvDetail,
cbSize, NULL))
{
LPTSTR pszSection = pdrvDetail->SectionName;
// If the section name indicates the type of port,
// then filter out the other port types since it would
// be ridiculous to list ports that don't match the
// port subclass.
if (IsSzEqual(pszSection, c_szInfSerial))
{
dwRet = FP_SERIAL;
}
else if (IsSzEqual(pszSection, c_szInfParallel))
{
dwRet = FP_PARALLEL;
}
}
LocalFree(LOCALOF(pdrvDetail));
}
return dwRet;
}
/*----------------------------------------------------------
Purpose: Device enumerator callback. Adds another port to the
listbox.
Returns: TRUE to continue enumeration
Cond: --
*/
BOOL
CALLBACK
Port_Add(
HPORTDATA hportdata,
LPARAM lParam)
{
BOOL bRet;
PORTDATA pd;
pd.cbSize = sizeof(pd);
bRet = PortData_GetProperties(hportdata, &pd);
if (bRet)
{
HWND hwndLB = ((LPPORTINFO)lParam)->hwndLB;
DWORD dwFlags = ((LPPORTINFO)lParam)->dwFlags;
LPTSTR pszPortExclude = ((LPPORTINFO)lParam)->szPortExclude;
#pragma data_seg(DATASEG_READONLY)
const static DWORD c_mpsubclass[3] = { FP_PARALLEL, FP_SERIAL, FP_MODEM };
#pragma data_seg()
ASSERT(0 == PORT_SUBCLASS_PARALLEL);
ASSERT(1 == PORT_SUBCLASS_SERIAL);
// Does this port qualify to be listed AND
// is the portname *not* the port that a mouse
// is connected to?
if (0 <= pd.nSubclass && pd.nSubclass <= 2 && // safety harness
(c_mpsubclass[pd.nSubclass] & dwFlags) &&
!IsSzEqual(pd.szPort, pszPortExclude))
{
// Yes; add the friendly name to the list
TCHAR rgchPortDisplayName[MAX_BUF];
ASSERT(sizeof(rgchPortDisplayName)==sizeof(pd.szFriendly));
// Add prefix spaces to get the list box sort order
// to work right (display COM2 before COM12, etc).
FormatPortForDisplay
(
pd.szFriendly,
rgchPortDisplayName,
sizeof(rgchPortDisplayName)/sizeof(TCHAR)
);
ListBox_AddString(hwndLB, rgchPortDisplayName);
}
}
return bRet;
}
/*----------------------------------------------------------
Purpose: Handles WM_COMMAND for the specific controls used
with the port listbox (like the radio buttons).
Returns: --
Cond: --
*/
void
PRIVATE
Port_OnCommand(
IN HWND hDlg,
IN WPARAM wParam,
IN LPARAM lParam,
IN BOOL bWizard)
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_PORTS:
// Did a listbox selection change?
if (LBN_SELCHANGE == GET_WM_COMMAND_CMD(wParam, lParam))
{
// Yes
BOOL bEnable;
HWND hwndCtl = GET_WM_COMMAND_HWND(wParam, lParam);
int cSel = ListBox_GetSelCount(hwndCtl);
int id;
// Enable OK or Next button if there is at least one selection
bEnable = (0 < cSel);
if (bWizard)
{
if (bEnable)
{
PropSheet_SetWizButtons(GetParent(hDlg),
PSWIZB_BACK | PSWIZB_NEXT);
}
else
{
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
}
}
else
{
Button_Enable(GetDlgItem(hDlg, IDOK), bEnable);
}
// Choose the "Select All" button if all the entries
// are selected
if (cSel>1 && ListBox_GetCount(hwndCtl) == cSel)
{
id = IDC_ALL;
}
else
{
id = IDC_SELECTED;
}
CheckRadioButton(hDlg, IDC_ALL, IDC_SELECTED, id);
}
break;
case IDC_ALL:
if (BN_CLICKED == GET_WM_COMMAND_CMD(wParam, lParam))
{
// Select everything in the listbox
HWND hwndCtl = GetDlgItem(hDlg, IDC_PORTS);
int cItems = ListBox_GetCount(hwndCtl);
ListBox_SelItemRange(hwndCtl, TRUE, 0, cItems);
if (bWizard)
{
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
}
else
{
Button_Enable(GetDlgItem(hDlg, IDOK), TRUE);
}
}
break;
case IDC_SELECTED:
if (BN_CLICKED == GET_WM_COMMAND_CMD(wParam, lParam))
{
HWND hwndCtl = GetDlgItem(hDlg, IDC_PORTS);
int cItems = ListBox_GetCount(hwndCtl);
// Deselect everything only if everything is currently
// selected
if (ListBox_GetSelCount(hwndCtl) == cItems)
{
ListBox_SelItemRange(hwndCtl, FALSE, 0, cItems);
if (bWizard)
{
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
}
else
{
Button_Enable(GetDlgItem(hDlg, IDOK), FALSE);
}
}
}
break;
}
}
/*----------------------------------------------------------
Purpose: Handle when the Next button is clicked (or the OK button).
Returns: --
Cond: --
*/
void
PRIVATE
Port_OnWizNext(
IN HWND hDlg,
IN LPSETUPINFO psi)
{
HWND hwndLB = GetDlgItem(hDlg, IDC_PORTS);
int cSel = ListBox_GetSelCount(hwndLB);
// Remember the selected port for the next page
if (0 >= cSel)
{
// This should never happen
ASSERT(0);
}
else
{
TCHAR sz[MAX_BUF];
LPINT piSel;
piSel = (LPINT)LocalAlloc(LMEM_FIXED, cSel * sizeof(*piSel));
if (piSel)
{
int i;
ListBox_GetSelItems(hwndLB, cSel, piSel);
// Free whatever list we have; we're starting over
CatMultiString(&psi->pszPortList, NULL);
for (i = 0; i < cSel; i++)
{
// Get the selected port (which is a friendly name)
ListBox_GetText(hwndLB, piSel[i], sz);
// Strip off prefix spaces added to get the list box sort order
// to work right (display COM2 before COM12, etc).
UnformatAfterDisplay(sz);
// Convert the friendly name to a port name
PortMap_GetPortName(psi->hportmap, sz, sz,
SIZECHARS(sz));
// Don't worry if this fails, we'll just install
// whatever could be added
CatMultiString(&psi->pszPortList, sz);
}
LocalFree(LOCALOF(piSel));
}
}
}
/*----------------------------------------------------------
Purpose: Port dialog. Allows the user to select a port.
Returns: varies
Cond: --
*/
BOOL CALLBACK PortManualDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG:
Wiz_SetPtr(hDlg, lParam);
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE:
{
SP_DRVINFO_DATA drvData;
PORTINFO portinfo;
// This page will get activated invisibly if the user
// cancels from the dial info page. In this condition,
// the selected device and selected driver may be NULL.
//
// [ LONG: by design the propsheet mgr switches to the
// previous page in the array when it needs to remove
// a page that is currently active. We hit this code
// path when the user clicks Cancel in the dial info
// page because ClassInstall_OnDestroyWizard explicitly
// removes that page while it is currently active. ]
//
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
// The user selected a modem from the Select Device page.
// Get the selected driver
drvData.cbSize = sizeof(drvData);
if (CplDiGetSelectedDriver(psi->hdi, psi->pdevData, &drvData))
{
// Start off by selecting only the selected ports
CheckRadioButton(hDlg, IDC_ALL, IDC_SELECTED, IDC_SELECTED);
// Modem name
SetDlgItemText(hDlg, IDC_NAME, drvData.Description);
// Fill the port listbox; special-case the parallel and
// serial cable connections so we don't look stupid
portinfo.dwFlags = GetPortFilterFlags(psi->hdi, psi->pdevData, &drvData);
portinfo.hwndLB = GetDlgItem(hDlg, IDC_PORTS);
#ifdef SKIP_MOUSE_PORT
lstrcpy(portinfo.szPortExclude, g_szMouseComPort);
#else
*portinfo.szPortExclude = 0;
#endif
ListBox_ResetContent(portinfo.hwndLB);
EnumeratePorts(Port_Add, (LPARAM)&portinfo);
}
break;
}
case PSN_KILLACTIVE:
case PSN_HELP:
break;
case PSN_WIZBACK:
Wiz_SetSelectParams(psi);
SetDlgMsgResult(hDlg, message, IDD_DYNAWIZ_SELECTDEV_PAGE);
break;
case PSN_WIZNEXT:
#ifdef PROFILE_MASSINSTALL
g_dwTimeBegin = GetTickCount();
#endif
Port_OnWizNext(hDlg, psi);
SetDlgMsgResult(hDlg, message, IDD_WIZ_INSTALL);
break;
default:
return FALSE;
}
break;
case WM_COMMAND:
Port_OnCommand(hDlg, wParam, lParam, TRUE);
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Port detection dialog. Allows the user to select a
single port to interrogate.
Returns: varies
Cond: --
*/
BOOL
CALLBACK
SelQueryPortDlgProc(
IN HWND hDlg,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG: {
PORTINFO portinfo;
Wiz_SetPtr(hDlg, lParam);
psi = (LPSETUPINFO)lParam;
// Fill the port listbox
portinfo.dwFlags = FP_SERIAL;
portinfo.hwndLB = GetDlgItem(hDlg, IDC_PORTS);
#ifdef SKIP_MOUSE_PORT
lstrcpy(portinfo.szPortExclude, g_szMouseComPort);
#else
*portinfo.szPortExclude = 0;
#endif
ListBox_ResetContent(portinfo.hwndLB);
EnumeratePorts(Port_Add, (LPARAM)&portinfo);
}
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE: {
DWORD dwFlags;
LPTSTR psz;
dwFlags = PSWIZB_BACK;
if (LB_ERR != ListBox_GetCurSel(GetDlgItem(hDlg, IDC_PORTS)))
{
dwFlags |= PSWIZB_NEXT;
}
PropSheet_SetWizButtons(GetParent(hDlg), dwFlags);
// Explanation of why we're at this page
if (ConstructMessage(&psz, g_hinst, MAKEINTRESOURCE(IDS_LOTSAPORTS),
PortMap_GetCount(psi->hportmap)))
{
SetDlgItemText(hDlg, IDC_NAME, psz);
GFree(psz);
}
break;
}
case PSN_KILLACTIVE:
case PSN_HELP:
break;
case PSN_WIZBACK:
break;
case PSN_WIZNEXT: {
HWND hwndCtl = GetDlgItem(hDlg, IDC_PORTS);
int iSel = ListBox_GetCurSel(hwndCtl);
ASSERT(LB_ERR != iSel);
ListBox_GetText(hwndCtl, iSel, psi->szPortQuery);
// Strip off prefix spaces added to get the list box sort order
// to work right (display COM2 before COM12, etc).
UnformatAfterDisplay(psi->szPortQuery);
PortMap_GetPortName(psi->hportmap, psi->szPortQuery,
psi->szPortQuery,
SIZECHARS(psi->szPortQuery));
}
break;
default:
return FALSE;
}
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_PORTS:
// Did a listbox selection change?
if (LBN_SELCHANGE == GET_WM_COMMAND_CMD(wParam, lParam))
{
// Yes
DWORD dwFlags = PSWIZB_BACK;
HWND hwndCtl = GET_WM_COMMAND_HWND(wParam, lParam);
if (LB_ERR != ListBox_GetCurSel(hwndCtl))
{
dwFlags |= PSWIZB_NEXT;
}
PropSheet_SetWizButtons(GetParent(hDlg), dwFlags);
}
break;
}
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Port installation dialog. Allows the user to select
the ports to install the detected modem on.
Returns: varies
Cond: --
*/
BOOL
CALLBACK
PortDetectDlgProc(
IN HWND hDlg,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG: {
PORTINFO portinfo;
Wiz_SetPtr(hDlg, lParam);
psi = (LPSETUPINFO)lParam;
// Start off by selecting only the selected ports
CheckRadioButton(hDlg, IDC_ALL, IDC_SELECTED, IDC_SELECTED);
// Fill the port listbox
portinfo.dwFlags = FP_SERIAL;
portinfo.hwndLB = GetDlgItem(hDlg, IDC_PORTS);
#ifdef SKIP_MOUSE_PORT
lstrcpy(portinfo.szPortExclude, g_szMouseComPort);
#else
*portinfo.szPortExclude = 0;
#endif
ListBox_ResetContent(portinfo.hwndLB);
EnumeratePorts(Port_Add, (LPARAM)&portinfo);
}
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE: {
DWORD dwFlags = PSWIZB_BACK;
if (0 < ListBox_GetSelCount(GetDlgItem(hDlg, IDC_PORTS)))
{
dwFlags |= PSWIZB_NEXT;
}
PropSheet_SetWizButtons(GetParent(hDlg), dwFlags);
}
break;
case PSN_KILLACTIVE:
case PSN_HELP:
break;
case PSN_WIZBACK:
SetDlgMsgResult(hDlg, message, IDD_WIZ_SELQUERYPORT);
break;
case PSN_WIZNEXT:
Port_OnWizNext(hDlg, psi);
break;
default:
return FALSE;
}
break;
case WM_COMMAND:
Port_OnCommand(hDlg, wParam, lParam, TRUE);
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Start installing the modems.
Returns: --
Cond: --
*/
void
PRIVATE
Install_OnStartInstall(
IN HWND hDlg,
IN LPSETUPINFO psi)
{
BOOL bRet;
DBG_ENTER(Install_OnStartInstall);
#ifdef PROFILE_MASSINSTALL
g_dwTimeAtStartInstall = GetTickCount();
#endif
ASSERT(hDlg);
ASSERT(psi);
// Cause the page to be painted right away before we start installation
InvalidateRect(hDlg, NULL, FALSE);
UpdateWindow(hDlg);
// Was the modem detected and is this the non-multi-port
// case?
if (IsFlagSet(psi->dwFlags, SIF_DETECTED_MODEM) &&
IsFlagClear(psi->dwFlags, SIF_PORTS_GALORE))
{
// Yes; install the modem(s) that may have been detected
bRet = CplDiInstallModem(psi->hdi, NULL, FALSE);
}
else
{
// No; we are either in the manual-select case or the
// multi-modem detection case. These are the same.
if ( !psi->pszPortList )
{
ASSERT(0); // out of memory
bRet = FALSE;
}
else
{
DWORD dwFlags = IMF_DEFAULT;
if (IsFlagClear(psi->dwFlags, SIF_DETECTED_MODEM))
{
SetFlag(dwFlags, IMF_CONFIRM);
}
bRet = CplDiInstallModemFromDriver(psi->hdi, hDlg,
&psi->pszPortList, dwFlags);
// Free the list
CatMultiString(&psi->pszPortList, NULL);
}
}
// Did the user cancel during install?
if (FALSE == bRet)
{
// Yes; don't bother going thru the rest of the
// wizard
Wiz_Bail(hDlg, psi);
}
else
{
// No; automatically go to next page
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
}
DBG_EXIT(Install_OnStartInstall);
#ifdef PROFILE_MASSINSTALL
TRACE_MSG(TF_GENERAL, "****** modem installation took %lu ms total. ******",
GetTickCount() - g_dwTimeAtStartInstall);
#endif
}
/*----------------------------------------------------------
Purpose: Install a manually selected or detected modem.
Installation can take some time, so we display this
page to tell the user to take a coffee break.
Returns: varies
Cond: --
*/
BOOL CALLBACK InstallDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG:
Wiz_SetPtr(hDlg, lParam);
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE:
// Disable the buttons since we cannot do anything while
// this page does the installation.
PropSheet_SetWizButtons(GetParent(hDlg), 0);
EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), FALSE);
PostMessage(hDlg, WM_STARTINSTALL, 0, 0);
break;
case PSN_KILLACTIVE:
case PSN_HELP:
case PSN_WIZBACK:
break;
case PSN_WIZNEXT: {
ULONG uNextDlg;
// Set the buttons to at least go forward and cancel
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), TRUE);
// No; has the default location been initialized yet?
if (Wiz_InitDialInfo(psi))
{
// No; show the mini-dial helper
uNextDlg = IDD_WIZ_DIALINFO;
}
else
{
// Yes
uNextDlg = IDD_WIZ_DONE;
}
SetDlgMsgResult(hDlg, message, uNextDlg);
}
break;
default:
return FALSE;
}
break;
case WM_STARTINSTALL:
Install_OnStartInstall(hDlg, psi);
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Done dialog
Returns: varies
Cond: --
*/
BOOL CALLBACK DoneDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = Wiz_GetPtr(hDlg);
switch(message)
{
case WM_INITDIALOG:
Wiz_SetPtr(hDlg, lParam);
break;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_SETACTIVE:
if (IsFlagSet(psi->miw.Flags, MIWF_INSET_WIZARD))
{
// Replace the Finish button with the Next button to
// make this wizard look like it is part of the calling
// wizard.
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
}
else
{
// Last page, show the Finish button
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
// and disable the Cancel button, since it's too late to cancel
EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), FALSE);
}
// Skip showing this page?
if (IsFlagSet(psi->dwFlags, SIF_JUMP_PAST_DONE))
{
// Yes
psi->miw.ExitButton = PSBTN_NEXT;
PostMessage(hDlg, WM_PRESSFINISH, 0, 0);
}
else
{
psi->miw.ExitButton = PSBTN_FINISH;
}
break;
case PSN_KILLACTIVE:
case PSN_HELP:
case PSN_WIZBACK:
break;
case PSN_WIZNEXT:
PostMessage(hDlg, WM_PRESSFINISH, 0, 0);
break;
case PSN_WIZFINISH:
// Is this wizard inside another wizard?
if (IsFlagSet(psi->miw.Flags, MIWF_INSET_WIZARD))
{
// Yes; prepare to show the outside wizard again
LeaveInsideWizard(hDlg);
}
break;
default:
return FALSE;
}
break;
case WM_PRESSFINISH:
PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
/*----------------------------------------------------------
Purpose: Port dialog. Allows the user to select a port.
Returns: varies
Cond: --
*/
BOOL
CALLBACK
CloneDlgProc(
IN HWND hDlg,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam)
{
NMHDR FAR *lpnm;
LPSETUPINFO psi = (LPSETUPINFO)GetWindowLong(hDlg, DWL_USER);
switch(message)
{
case WM_INITDIALOG:
{
HWND hwndCtl = GetDlgItem(hDlg, IDC_PORTS);
PORTINFO portinfo;
MODEM_PRIV_PROP mpp;
psi = (LPSETUPINFO)lParam;
// Start off by selecting all the ports
CheckRadioButton(hDlg, IDC_ALL, IDC_SELECTED, IDC_ALL);
// Get the name and device type
mpp.cbSize = sizeof(mpp);
mpp.dwMask = MPPM_FRIENDLY_NAME | MPPM_DEVICE_TYPE | MPPM_PORT;
if (CplDiGetPrivateProperties(psi->hdi, psi->pdevData, &mpp))
{
int cItems;
LPTSTR psz;
// Modem name
if (ConstructMessage(&psz, g_hinst, MAKEINTRESOURCE(IDS_SELECTTODUP),
mpp.szFriendlyName))
{
SetDlgItemText(hDlg, IDC_NAME, psz);
GFree(psz);
}
// Fill the port listbox; special-case the parallel and
// serial cable connections so we don't look stupid
switch (mpp.nDeviceType)
{
case DT_PARALLEL_PORT:
portinfo.dwFlags = FP_PARALLEL;
break;
case DT_PARALLEL_MODEM:
portinfo.dwFlags = FP_PARALLEL | FP_MODEM;
break;
default:
portinfo.dwFlags = FP_SERIAL | FP_MODEM;
break;
}
portinfo.hwndLB = GetDlgItem(hDlg, IDC_PORTS);
lstrcpy(portinfo.szPortExclude, mpp.szPort);
ListBox_ResetContent(portinfo.hwndLB);
EnumeratePorts(Port_Add, (LPARAM)&portinfo);
cItems = ListBox_GetCount(hwndCtl);
ListBox_SelItemRange(hwndCtl, TRUE, 0, cItems);
}
else
{
// Error
MsgBox(g_hinst, hDlg,
MAKEINTRESOURCE(IDS_OOM_CLONE),
MAKEINTRESOURCE(IDS_CAP_MODEMSETUP),
NULL,
MB_OK | MB_ICONERROR);
EndDialog(hDlg, -1);
}
// Play it safe; was there no selection made?
if (ListBox_GetSelCount(hwndCtl) == 0)
{
// Yes; disable OK button
Button_Enable(GetDlgItem(hDlg, IDOK), FALSE);
}
SetWindowLong(hDlg, DWL_USER, lParam);
}
break;
case WM_COMMAND:
Port_OnCommand(hDlg, wParam, lParam, FALSE);
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
Port_OnWizNext(hDlg, psi);
// Fall thru
// | |
// v v
case IDCANCEL:
EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam));
break;
}
break;
default:
return FALSE;
} // end of switch on message
return TRUE;
}
void PUBLIC Install_SetStatus(
IN HWND hDlg,
IN LPCTSTR lpctszStatus
)
{
if (hDlg && lpctszStatus)
{
SetDlgItemText(hDlg, IDC_ST_INSTALLING, lpctszStatus);
UpdateWindow(hDlg);
}
}