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.
 
 
 
 
 
 

2179 lines
55 KiB

/*
* Control Panel routines for modems including the listbox dialog
*
* Microsoft Confidential
* Copyright (c) Microsoft Corporation 1993-1995
* All rights reserved
*
*/
#include "proj.h"
#include <cpl.h>
#define INITGUID
#include <initguid.h>
#include <devguid.h>
// Column subitems
#define ICOL_MODEM 0
#define ICOL_PORT 1
#define LV_APPEND 0x7fffffff
// Global flags. See cpl\modem.h for their values.
int g_iCPLFlags = 0;
int g_CurrentSubItemToSort = ICOL_MODEM;
// Map driver type values to imagelist index
struct
{
BYTE nDeviceType; // DT_ value
UINT idi; // icon resource ID
int index; // imagelist index
} g_rgmapdt[] = {
{ DT_NULL_MODEM, IDI_NULL_MODEM, 0 },
{ DT_EXTERNAL_MODEM, IDI_EXTERNAL_MODEM, 0 },
{ DT_INTERNAL_MODEM, IDI_INTERNAL_MODEM, 0 },
{ DT_PCMCIA_MODEM, IDI_PCMCIA_MODEM, 0 },
{ DT_PARALLEL_PORT, IDI_NULL_MODEM, 0 },
{ DT_PARALLEL_MODEM, IDI_EXTERNAL_MODEM, 0 } };
// This structure is private data for the main modem dialog
typedef struct tagMODEMDLG
{
HDEVINFO hdi;
int cSel;
} MODEMDLG, FAR * LPMODEMDLG;
#ifdef INSTANT_DEVICE_ACTIVATION
void
HandleDeviceChange(
IN DWORD dwDeviceFlags,
IN HWND hWnd );
BOOL
RestartComputerDlg(
IN HWND hwndOwner );
BOOL
RestartComputer();
#endif // INSTANT_DEVICE_ACTIVATION
// This structure is used to represent each modem item
// in the listview
typedef struct tagMODEMITEM
{
SP_DEVINFO_DATA devData;
MODEM_PRIV_PROP mpp;
} MODEMITEM, FAR * PMODEMITEM;
// Special-case alphanumeric stringcmp.
int my_lstrcmp_an(LPTSTR lptsz1, LPTSTR lptsz2);
HIMAGELIST g_himl;
#pragma data_seg(DATASEG_READONLY)
TCHAR const FAR c_szWinHelpFile[] = TEXT("windows.hlp");
TCHAR const FAR c_szFriendlyName[] = REGSTR_VAL_FRIENDLYNAME;
TCHAR const FAR c_szHardwareID[] = REGSTR_VAL_HARDWAREID;
// Strings for invoking the modem cpl
TCHAR const FAR c_szRunOnce[] = TEXT("RunOnce");
TCHAR const FAR c_szRunWizard[] = TEXT("add");
TCHAR const FAR c_szAddCables[] = TEXT("addcables");
TCHAR const FAR c_szNoUI[] = TEXT("noui");
TCHAR const FAR c_szOnePort[] = TEXT("port");
TCHAR const FAR c_szInfName[] = TEXT("inf");
TCHAR const FAR c_szInfSection[] = TEXT("sect");
// Hardcoded hardware IDs for cable connection
TCHAR const FAR c_szHardwareIDSerial[] = TEXT("PNPC031");
TCHAR const FAR c_szHardwareIDParallel[] = TEXT("PNPC032");
TCHAR const FAR c_szInfSerial[] = TEXT("M2700");
TCHAR const FAR c_szInfParallel[] = TEXT("M2701");
// File names
#ifdef WINNT
TCHAR const FAR c_szTapiDLL[] = TEXT("TAPI32.DLL");
#else
TCHAR const FAR c_szTapiDLL[] = TEXT("TAPI.DLL");
#endif
LPGUID g_pguidModem = (LPGUID)&GUID_DEVCLASS_MODEM;
#pragma data_seg()
BOOL CALLBACK ModemCplDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void
PRIVATE
ModemCpl_SortColumn(
IN HWND hwndCtl,
IN int icol);
/*----------------------------------------------------------
Purpose: Runs the device installer wizard
Returns: --
Cond: --
*/
void
PRIVATE
DoWizard(
IN HWND hwnd,
IN HDEVINFO hdi)
{
BOOL bRet;
SP_INSTALLWIZARD_DATA iwd;
DBG_ENTER(DoWizard);
ASSERT(hdi && INVALID_HANDLE_VALUE != hdi);
ZeroInit(&iwd);
CplInitClassInstallHeader(&iwd, DIF_INSTALLWIZARD);
iwd.hwndWizardDlg = hwnd;
bRet = CplDiSetClassInstallParams(hdi, NULL, PCIPOfPtr(&iwd), sizeof(iwd));
if (bRet)
{
// Invoke the wizard
CplDiCallClassInstaller(DIF_INSTALLWIZARD, hdi, NULL);
// Clean up
CplDiCallClassInstaller(DIF_DESTROYWIZARDDATA, hdi, NULL);
}
DBG_EXIT(DoWizard);
}
/*----------------------------------------------------------
Purpose: Show the Modem dialog
Returns: --
Cond: --
*/
void
PRIVATE
DoModem(
IN HWND hwnd,
IN OUT HDEVINFO * phdi)
{
PROPSHEETHEADER psh;
PROPSHEETPAGE rgpsp[2];
MODEMDLG md;
DBG_ENTER(DoModem);
md.hdi = *phdi;
md.cSel = 0;
// Property page header
psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW | PSH_PROPSHEETPAGE;
psh.hwndParent = hwnd;
psh.hInstance = g_hinst;
psh.pszCaption = MAKEINTRESOURCE(IDS_CPLNAME);
#ifdef DIAGNOSTIC
psh.nPages = 2;
#else
psh.nPages = 1;
#endif //DIAGNOSTIC
psh.nStartPage = 0;
psh.ppsp = rgpsp;
// Pages
rgpsp[0].dwSize = sizeof(PROPSHEETPAGE);
rgpsp[0].dwFlags = PSP_DEFAULT;
rgpsp[0].hInstance = g_hinst;
rgpsp[0].pszTemplate = MAKEINTRESOURCE(IDD_MODEM);
rgpsp[0].pfnDlgProc = ModemCplDlgProc;
rgpsp[0].lParam = (LPARAM)&md;
#ifdef DIAGNOSTIC
rgpsp[1].dwSize = sizeof(PROPSHEETPAGE);
rgpsp[1].dwFlags = PSP_DEFAULT;
rgpsp[1].hInstance = g_hinst;
rgpsp[1].pszTemplate = MAKEINTRESOURCE(IDD_MODEMTEST);
rgpsp[1].pfnDlgProc = MdmDiagDlgProc;
rgpsp[1].lParam = (LPARAM)&md;
#endif //DIAGNOSTIC
PropertySheet(&psh);
*phdi = md.hdi;
DBG_EXIT(DoModem);
}
/*----------------------------------------------------------
Purpose: Gets the index to the appropriate image in the modem imagelist
WITHOUT searching the registry.
Returns: --
Cond: --
*/
void PUBLIC GetModemImageIndex(
BYTE nDeviceType,
int FAR * pindex)
{
int i;
for (i = 0; i < ARRAYSIZE(g_rgmapdt); i++)
{
if (nDeviceType == g_rgmapdt[i].nDeviceType)
{
*pindex = g_rgmapdt[i].index;
return;
}
}
ASSERT(0); // We should never get here
}
/*----------------------------------------------------------
Purpose: Gets the modem image list
Returns: TRUE on success
Cond: --
*/
BOOL NEAR PASCAL GetModemImageList(
HIMAGELIST FAR * phiml)
{
BOOL bRet = FALSE;
ASSERT(phiml);
if (NULL == g_himl)
{
g_himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
ILC_MASK, 1, 1);
if (NULL != g_himl)
{
// The MODEMUI.DLL contains the icons from which we derive the list
HINSTANCE hinst = LoadLibrary(TEXT("MODEMUI.DLL"));
ImageList_SetBkColor(g_himl, GetSysColor(COLOR_WINDOW));
if (ISVALIDHINSTANCE(hinst))
{
HICON hicon;
int i;
for (i = 0; i < ARRAYSIZE(g_rgmapdt); i++)
{
hicon = LoadIcon(hinst, MAKEINTRESOURCE(g_rgmapdt[i].idi));
g_rgmapdt[i].index = ImageList_AddIcon(g_himl, hicon);
}
FreeLibrary(hinst);
*phiml = g_himl;
bRet = TRUE;
}
}
}
else
{
*phiml = g_himl;
bRet = TRUE;
}
return bRet;
}
/*----------------------------------------------------------
Purpose: Determine if user is an admin, and records this in
a global g_iCPLFlags.
Returns: --
Cond: --
*/
VOID NEAR PASCAL CheckIfAdminUser()
{
HKEY hkey;
if(IsAdminUser())
{
g_iCPLFlags |= FLAG_USER_IS_ADMIN;
}
else
{
g_iCPLFlags &= (~FLAG_USER_IS_ADMIN);
}
}
/*----------------------------------------------------------
Purpose: Invokes the modem control panel.
fWizard=TRUE ==> run wizard, even if there are alreay devices installed
fWizard=FALSE ==> run wizard only if there are no devices installed.
fCpl=TRUE ==> run CPL
fCpl=FALSE ==> don't run CPL
Returns: --
Cond: --
*/
void NEAR PASCAL InvokeControlPanel(HWND hwnd, BOOL fCpl, BOOL fWizard)
{
HDEVINFO hdi=NULL;
BOOL bInstalled;
SP_DEVINFO_DATA devData;
if (!CplDiGetModemDevs(&hdi, hwnd, DIGCF_PRESENT, &bInstalled))
{
hdi=NULL;
goto end;
}
// Are there any modems installed? (or we are we asked to invoke
// the wizard)
if ( !bInstalled || fWizard)
{
// If the user isn't an admin, there's nothing else
// they can do. If they are, run the installation wizard.
if (!USER_IS_ADMIN())
{
LPTSTR lptsz = MAKEINTRESOURCE(
(bInstalled)
? IDS_ERR_NOT_ADMIN
: IDS_ERR_NOMODEM_NOT_ADMIN
);
MsgBox( g_hinst,
hwnd,
lptsz,
MAKEINTRESOURCE(IDS_CAP_MODEMSETUP),
NULL,
MB_OK | MB_ICONERROR );
goto end;
}
DoWizard(hwnd, hdi);
}
if (fCpl)
{
// Check again
devData.cbSize = sizeof(devData);
if (CplDiEnumDeviceInfo(hdi, 0, &devData))
{
// Yes; start up the cpl
DoModem(hwnd, &hdi);
}
}
// fall through
end:
if (hdi)
{
CplDiDestroyDeviceInfoList(hdi);
}
return;
}
/*----------------------------------------------------------
Purpose: Fetch the value of a command line parameter. Also
writes a '\0' over the '=' that precedes the value.
Returns: NULL if there was no "=" in the string, otherwise
a pointer to the character following the next '='.
Cond: --
*/
LPTSTR
PRIVATE
GetValuePtr(LPTSTR lpsz)
{
LPTSTR lpszEqual;
if ((lpszEqual = AnsiChr(lpsz, '=')) != NULL)
{
lpsz = CharNext(lpszEqual);
lstrcpy(lpszEqual, TEXT("\0"));
}
return(lpszEqual ? lpsz : NULL);
}
/*----------------------------------------------------------
Purpose: Parse the command line. Set flags and collect
parameters based on its contents.
Returns: --
Cond: --
*/
VOID
PRIVATE
ParseCmdLine(LPTSTR szCmdLine, LPINSTALLPARAMS lpip)
{
LPTSTR lpszParam, lpszSpace, lpszValue;
ZeroMemory(lpip, sizeof(INSTALLPARAMS));
while (szCmdLine && (!IsSzEqual(szCmdLine, TEXT("\0"))))
{
lpszParam = szCmdLine;
if ((lpszSpace = AnsiChr(szCmdLine, ' ')) != NULL)
{
szCmdLine = CharNext(lpszSpace);
lstrcpy(lpszSpace, TEXT("\0"));
}
else szCmdLine = NULL;
// interpret any "directive" parameters
if (IsSzEqual(lpszParam, c_szNoUI))
{
g_iCPLFlags |= FLAG_INSTALL_NOUI;
}
else if (lpszValue = GetValuePtr(lpszParam))
{
// interpret any "value" parameters (have a value following '=')
if (IsSzEqual(lpszParam, c_szOnePort))
{
if (lstrlen(lpszValue) < sizeof(lpip->szPort))
lstrcpy(lpip->szPort, CharUpper(lpszValue));
}
else if (IsSzEqual(lpszParam, c_szInfName))
{
if (lstrlen(lpszValue) < sizeof(lpip->szInfName))
lstrcpy(lpip->szInfName, lpszValue);
}
else if (IsSzEqual(lpszParam, c_szInfSection))
{
if (lstrlen(lpszValue) < sizeof(lpip->szInfSect))
lstrcpy(lpip->szInfSect, lpszValue);
}
}
else
{
// ignore any parameter that wasn't recognized & skip to the next
// parameter if there is one
if (szCmdLine)
{
if ((szCmdLine = AnsiChr(szCmdLine, ' ')) != NULL)
szCmdLine = CharNext(szCmdLine);
}
}
}
}
/*----------------------------------------------------------
Purpose: Entry-point for control panel applet
Returns: varies
Cond: --
*/
LONG
CALLBACK
CPlApplet(
HWND hwnd,
UINT Msg,
LPARAM lParam1,
LPARAM lParam2 )
{
LPNEWCPLINFO lpCPlInfo;
LPCPLINFO lpOldCPlInfo;
LPTSTR lpszParam;
HDEVINFO hdi;
BOOL bRet;
BOOL bInstalled;
INSTALLPARAMS InstallParams;
switch (Msg)
{
case CPL_INIT:
CheckIfAdminUser();
gDeviceFlags =0;
return TRUE;
case CPL_GETCOUNT:
return 1;
case CPL_INQUIRE:
lpOldCPlInfo = (LPCPLINFO)lParam2;
lpOldCPlInfo->idIcon = IDI_MODEM;
lpOldCPlInfo->idName = IDS_CPLNAME;
lpOldCPlInfo->idInfo = IDS_CPLINFO;
lpOldCPlInfo->lData = 1;
break;
case CPL_SELECT:
// Applet has been selected, do nothing.
break;
case CPL_NEWINQUIRE:
lpCPlInfo = (LPNEWCPLINFO)lParam2;
lpCPlInfo->hIcon = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_MODEM));
LoadString(g_hinst, IDS_CPLNAME, lpCPlInfo->szName, SIZECHARS(lpCPlInfo->szName));
LoadString(g_hinst, IDS_CPLINFO, lpCPlInfo->szInfo, SIZECHARS(lpCPlInfo->szInfo));
lpCPlInfo->dwSize = sizeof(NEWCPLINFO);
lpCPlInfo->lData = 1;
break;
case CPL_STARTWPARMS:
lpszParam = (LPTSTR)lParam2;
ParseCmdLine((LPTSTR)lParam2, &InstallParams);
if (INSTALL_NOUI())
{
UnattendedInstall(hwnd, &InstallParams);
}
else
if (IsSzEqual(lpszParam, c_szRunOnce))
{
// run-once
InvokeControlPanel(hwnd,FALSE,FALSE);
}
else if (IsSzEqual(lpszParam, c_szRunWizard))
{
// run wizard
InvokeControlPanel(hwnd,FALSE,TRUE);
}
else
{
InvokeControlPanel(hwnd,TRUE,FALSE);
}
break;
case CPL_DBLCLK:
InvokeControlPanel(hwnd, TRUE, FALSE);
break;
case CPL_STOP:
// Sent once for each applet prior to the CPL_EXIT msg.
// Perform applet specific cleanup.
break;
case CPL_EXIT:
// Last message, sent once only, before the shell calls
break;
default:
break;
}
return TRUE;
}
//****************************************************************************
//
//****************************************************************************
#define KERNEL_SUPPORT
#if !defined(KERNEL_SUPPORT)
#undef CommConfigDialog
#undef GetDefaultCommConfig
#undef SetDefaultCommConfig
#define CommConfigDialog MyCommConfigDialog
#define GetDefaultCommConfig MyGetDefaultCommConfig
#define SetDefaultCommConfig MySetDefaultCommConfig
typedef DWORD (WINAPI FAR * COMMCONFIGDIALOGPROC)(LPCTSTR pszName, HWND hwnd, LPCOMMCONFIG pcc);
typedef DWORD (WINAPI FAR * GETDEFAULTCOMMCONFIGPROC)(LPCTSTR pszName, LPCOMMCONFIG pcc, LPDWORD pcbSize);
typedef DWORD (WINAPI FAR * SETDEFAULTCOMMCONFIGPROC)(LPCTSTR pszName, LPCOMMCONFIG pcc, DWORD cbSize);
#ifdef UNICODE
#define DRV_COMMCFGDLG_FUNC "drvCommConfigDialogW"
#define DRV_GETDEFCOMMCFG_FUNC "drvGetDefaultCommConfigW"
#define DRV_SETDEFCOMMCFG_FUNC "drvSetDefaultCommConfigW"
#else
#define DRV_COMMCFGDLG_FUNC "drvCommConfigDialogA"
#define DRV_GETDEFCOMMCFG_FUNC "drvGetDefaultCommConfigA"
#define DRV_SETDEFCOMMCFG_FUNC "drvSetDefaultCommConfigA"
#endif // UNICODE
/*----------------------------------------------------------
Purpose: Temporary function
Returns:
Cond: --
*/
BOOL PUBLIC MyCommConfigDialog(
LPTSTR pszName,
HWND hwndOwner,
LPCOMMCONFIG pcc)
{
BOOL bRet = FALSE;
HINSTANCE hinst;
COMMCONFIGDIALOGPROC pfn;
hinst = LoadLibrary(TEXT("MODEMUI.DLL"));
if (ISVALIDHINSTANCE(hinst))
{
pfn = (COMMCONFIGDIALOGPROC)GetProcAddress(hinst, DRV_COMMCFGDLG_FUNC);
if (pfn)
{
bRet = (NO_ERROR == pfn(pszName, hwndOwner, pcc));
}
FreeLibrary(hinst);
}
return bRet;
}
/*----------------------------------------------------------
Purpose: Temporary function
Returns:
Cond: --
*/
BOOL PUBLIC MyGetDefaultCommConfig(
LPTSTR pszName,
LPCOMMCONFIG pcc,
LPDWORD pcbSize)
{
BOOL bRet = FALSE;
HINSTANCE hinst;
GETDEFAULTCOMMCONFIGPROC pfn;
hinst = LoadLibrary(TEXT("MODEMUI.DLL"));
if (ISVALIDHINSTANCE(hinst))
{
pfn = (GETDEFAULTCOMMCONFIGPROC)GetProcAddress(hinst, DRV_GETDEFCOMMCFG_FUNC);
if (pfn)
{
bRet = (NO_ERROR == pfn(pszName, pcc, pcbSize));
}
FreeLibrary(hinst);
}
return bRet;
}
/*----------------------------------------------------------
Purpose: Temporary function
Returns:
Cond: --
*/
BOOL PUBLIC MySetDefaultCommConfig(
LPTSTR pszName,
LPCOMMCONFIG pcc,
DWORD cbSize)
{
BOOL bRet = FALSE;
HINSTANCE hinst;
SETDEFAULTCOMMCONFIGPROC pfn;
hinst = LoadLibrary(TEXT("MODEMUI.DLL"));
if (ISVALIDHINSTANCE(hinst))
{
pfn = (SETDEFAULTCOMMCONFIGPROC)GetProcAddress(hinst, DRV_SETDEFCOMMCFG_FUNC);
if (pfn)
{
bRet = (NO_ERROR == pfn(pszName, pcc, cbSize));
}
FreeLibrary(hinst);
}
return bRet;
}
#endif
/*----------------------------------------------------------
Purpose: Brings up the property sheet for the modem
Returns: IDOK or IDCANCEL
Cond: --
*/
int
PRIVATE
DoModemProperties(
IN HWND hDlg,
IN HDEVINFO hdi)
{
int idRet = IDCANCEL;
HWND hwndCtl = GetDlgItem(hDlg, IDC_MODEMLV);
LV_ITEM lvi;
int iSel;
iSel = ListView_GetNextItem(hwndCtl, -1, LVNI_SELECTED);
if (-1 != iSel)
{
COMMCONFIG ccDummy;
COMMCONFIG * pcc;
DWORD dwSize;
HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
PMODEMITEM pitem;
// Get the selection
lvi.mask = LVIF_PARAM;
lvi.iItem = iSel;
lvi.iSubItem = 0;
ListView_GetItem(hwndCtl, &lvi);
pitem = (PMODEMITEM)lvi.lParam;
ccDummy.dwProviderSubType = PST_MODEM;
dwSize = sizeof(COMMCONFIG);
GetDefaultCommConfig(pitem->mpp.szFriendlyName, &ccDummy, &dwSize);
pcc = (COMMCONFIG *)LocalAlloc(LPTR, (UINT)dwSize);
if (pcc)
{
pcc->dwProviderSubType = PST_MODEM;
if (GetDefaultCommConfig(pitem->mpp.szFriendlyName, pcc, &dwSize))
{
COMMCONFIG *pccOld =
(COMMCONFIG *)LocalAlloc(LPTR, (UINT)dwSize);
if (pccOld) {CopyMemory(pccOld, pcc, dwSize);}
SetCursor(hcur);
hcur = NULL;
if (CommConfigDialog(pitem->mpp.szFriendlyName, hDlg, pcc))
{
SetDefaultCommConfig(pitem->mpp.szFriendlyName, pcc, dwSize);
// Notify TSP only if a setting has changed.
if (pccOld)
{
if (memcmp(pccOld, pcc, dwSize))
{
NotifyTSP_NewCommConfig(pitem->mpp.szFriendlyName);
}
}
idRet = IDOK;
// Update our item data (the port may have changed)
CplDiGetPrivateProperties(hdi, &pitem->devData, &pitem->mpp);
ListView_Update(hwndCtl, iSel);
}
if (pccOld)
{
LocalFree(pccOld);
pccOld=NULL;
}
}
else
{
MsgBox(g_hinst,
hDlg,
MAKEINTRESOURCE(IDS_ERR_PROPERTIES),
MAKEINTRESOURCE(IDS_CAP_MODEM),
NULL,
MB_OK | MB_ICONEXCLAMATION);
}
LocalFree((HLOCAL)pcc);
}
if (hcur)
SetCursor(hcur);
}
return idRet;
}
/*----------------------------------------------------------
Purpose: Free resources associated with the modem list
Returns:
Cond: --
*/
void
PRIVATE
FreeModemListData(
IN HWND hLV)
{
LV_ITEM lvi;
DWORD iIndex, cItems;
PMODEMITEM pitem;
// Get the modem count
cItems = ListView_GetItemCount(hLV);
for (iIndex = 0; iIndex < cItems; iIndex++)
{
lvi.mask = LVIF_PARAM;
lvi.iItem = iIndex;
lvi.iSubItem = 0;
ListView_GetItem(hLV, &lvi);
if(NULL != (pitem = (PMODEMITEM)lvi.lParam))
{
LocalFree(pitem);
}
}
}
/*----------------------------------------------------------
Purpose: Fills the lisbox with the list of modems
Returns:
Cond: --
*/
VOID
PRIVATE
FillModemLB(
IN HWND hDlg,
IN HDEVINFO hdi,
IN int iSel, // preferred item to select
IN int iSubItemToSort // preferred sorting order. (ICOL_*)
)
{
SP_DEVINFO_DATA devData;
PMODEMITEM pitem;
HWND hwndCtl = GetDlgItem(hDlg, IDC_MODEMLV);
LV_ITEM lviItem;
DWORD iIndex;
int iCount;
SetWindowRedraw(hwndCtl, FALSE);
// Remove all the old items and associated resources
FreeModemListData(hwndCtl);
ListView_DeleteAllItems(hwndCtl);
// Re-enumerate the modems
iIndex = 0;
devData.cbSize = sizeof(devData);
while (CplDiEnumDeviceInfo(hdi, iIndex++, &devData))
{
// We have a modem, allocate the SP_DEVICEINFO_DATA struct for it
pitem = (PMODEMITEM)LocalAlloc(LPTR, sizeof(*pitem));
if (pitem)
{
BOOL bShow = !CplDiIsLocalConnection(hdi, &devData, NULL);
// Get the device information
BltByte(&pitem->devData, &devData, sizeof(devData));
// Get the private properties of the modem
pitem->mpp.cbSize = sizeof(pitem->mpp);
pitem->mpp.dwMask = (MPPM_FRIENDLY_NAME | MPPM_DEVICE_TYPE | MPPM_PORT);
if (bShow &&
CplDiGetPrivateProperties(hdi, &devData, &pitem->mpp) &&
IsFlagSet(pitem->mpp.dwMask, MPPM_FRIENDLY_NAME | MPPM_DEVICE_TYPE | MPPM_PORT))
{
int index;
GetModemImageIndex(LOBYTE(LOWORD(pitem->mpp.nDeviceType)), &index);
// Insert the modem name
lviItem.mask = LVIF_ALL;
lviItem.iItem = LV_APPEND;
lviItem.iSubItem = ICOL_MODEM;
lviItem.state = 0;
lviItem.stateMask = 0;
lviItem.iImage = index;
lviItem.pszText = LPSTR_TEXTCALLBACK;
lviItem.lParam = (LPARAM)pitem;
// (Reuse the index variable)
index = ListView_InsertItem(hwndCtl, &lviItem);
// Set the port column value
lviItem.mask = LVIF_TEXT;
lviItem.iItem = index;
lviItem.iSubItem = ICOL_PORT;
lviItem.pszText = LPSTR_TEXTCALLBACK;
ListView_SetItem(hwndCtl, &lviItem);
}
else
{
LocalFree(LOCALOF(pitem));
}
}
}
// Sort by the requested default
ASSERT(iSubItemToSort==ICOL_PORT || iSubItemToSort==ICOL_MODEM);
ModemCpl_SortColumn(hwndCtl, iSubItemToSort);
// Select the requested one
iCount = ListView_GetItemCount(hwndCtl);
if (0 < iCount)
{
if (iSel>=iCount) iSel = iCount-1;
if (iSel<0) iSel = 0;
lviItem.mask = LVIF_STATE;
lviItem.iItem = iSel;
lviItem.iSubItem = 0;
lviItem.state = LVIS_SELECTED|LVIS_FOCUSED;
lviItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
ListView_SetItem(hwndCtl, &lviItem);
ListView_EnsureVisible(hwndCtl, iSel, FALSE);
}
SetWindowRedraw(hwndCtl, TRUE);
}
/*----------------------------------------------------------
Purpose: Clone a modem
Returns: --
Cond: --
*/
void
PRIVATE
CloneModem(
IN HWND hDlg,
IN LPMODEMDLG lpmd)
{
int iSel;
PMODEMITEM pitem;
LV_ITEM lvi;
HWND hwndCtl = GetDlgItem(hDlg, IDC_MODEMLV);
iSel = ListView_GetNextItem(hwndCtl, -1, LVNI_SELECTED);
if (-1 != iSel)
{
HDEVINFO hdi = lpmd->hdi;
LPSETUPINFO psi;
lvi.mask = LVIF_PARAM;
lvi.iItem = iSel;
lvi.iSubItem = 0;
ListView_GetItem(hwndCtl, &lvi);
pitem = (PMODEMITEM)lvi.lParam;
if (NO_ERROR != SetupInfo_Create(&psi, hdi, &pitem->devData, NULL, NULL))
{
// Out of memory
MsgBox(g_hinst, hDlg,
MAKEINTRESOURCE(IDS_OOM_CLONE),
MAKEINTRESOURCE(IDS_CAP_MODEMSETUP),
NULL,
MB_OK | MB_ICONERROR);
}
else
{
if (IDOK == DialogBoxParam(g_hinst,
MAKEINTRESOURCE(IDD_CLONE),
hDlg,
CloneDlgProc,
(LPARAM)psi))
{
BOOL bRet;
HCURSOR hcurSav = SetCursor(LoadCursor(NULL, IDC_WAIT));
LPCTSTR pszPort;
// Clone this modem for all the ports in the port list
ASSERT(psi->pszPortList);
bRet = CplDiBuildModemDriverList(hdi, &pitem->devData);
SetCursor(hcurSav);
if (bRet)
{
// Install a device for each port in the port list
CplDiInstallModemFromDriver(hdi, hDlg,
&psi->pszPortList,
IMF_DEFAULT);
}
FillModemLB(hDlg, hdi, 0, ICOL_MODEM);
}
SetupInfo_Destroy(psi);
}
}
}
/*----------------------------------------------------------
Purpose: Removes a modem from the modem list
Returns: --
Cond: --
*/
void
PRIVATE
RemoveModem(
IN HWND hDlg,
IN LPMODEMDLG lpmd)
{
int iSel;
PMODEMITEM pitem;
LV_ITEM lvi;
HWND hwndCtl = GetDlgItem(hDlg, IDC_MODEMLV);
iSel = ListView_GetNextItem(hwndCtl, -1, LVNI_SELECTED);
if (-1 != iSel)
{
HDEVINFO hdi = lpmd->hdi;
HCURSOR hcurSav;
lvi.mask = LVIF_PARAM;
lvi.iItem = iSel;
lvi.iSubItem = 0;
ListView_GetItem(hwndCtl, &lvi);
hcurSav = SetCursor(LoadCursor(NULL, IDC_WAIT));
pitem = (PMODEMITEM)lvi.lParam;
// Ask the user first
if (IDYES == MsgBox(g_hinst, hDlg,
MAKEINTRESOURCE(IDS_WRN_CONFIRMDELETE),
MAKEINTRESOURCE(IDS_CAP_MODEMSETUP),
NULL,
MB_YESNO | MB_QUESTION,
pitem->mpp.szFriendlyName))
{
// Get the name of the common driver key for this driver, in
// preparation for calling DeleteCommonDriverKeyByName() after the
// device is successfully removed.
HKEY hkey = NULL;
TCHAR szComDrv[MAX_REG_KEY_LEN];
hkey = CplDiOpenDevRegKey(hdi, &pitem->devData,
DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ);
if (hkey == INVALID_HANDLE_VALUE)
{
TRACE_MSG(TF_ERROR, "CplDiOpenDevRegKey() returned error %#08lx", GetLastError());
}
if (!FindCommonDriverKeyName(hkey, sizeof(szComDrv), szComDrv))
{
TRACE_MSG(TF_ERROR, "GetCommonDriverKeyName() FAILED.");
szComDrv[0] = 0;
}
if (hkey)
RegCloseKey(hkey);
if (!CplDiRemoveDevice(hdi, &pitem->devData))
{
MsgBox(g_hinst, hDlg,
MAKEINTRESOURCE(IDS_ERR_CANT_DEL_MODEM),
MAKEINTRESOURCE(IDS_CAP_MODEMSETUP),
NULL,
MB_OK | MB_ERROR,
pitem->mpp.szFriendlyName, pitem->mpp.szPort);
}
else
{
gDeviceFlags |= fDF_DEVICE_REMOVED;
if (szComDrv[0] != 0)
{
if (!DeleteCommonDriverKeyByName(szComDrv))
{
TRACE_MSG(TF_ERROR, "DeleteCommonDriverKey() FAILED.");
}
}
}
FillModemLB(hDlg, hdi, iSel, g_CurrentSubItemToSort);
}
SetCursor(hcurSav);
}
}
#ifdef TAPI_WORKS
#define LOCATION_GROW 4
#define TAPI_API_VERSION 0x00010004 // Per BernieM
/*----------------------------------------------------------
Purpose: Gets the appropriately sized translate caps structure
from TAPI. Return TRUE if successful
Returns: see above
Cond: --
*/
BOOL
PRIVATE
GetTranslateCaps(
OUT LPLINETRANSLATECAPS FAR * pptc)
{
LONG lineErr;
LPLINETRANSLATECAPS ptc;
DWORD cbSize;
cbSize = sizeof(*ptc) * LOCATION_GROW;
ptc = (LPLINETRANSLATECAPS)GlobalAllocPtr(GPTR, cbSize);
if (ptc)
{
// Get the translate devcaps
ptc->dwTotalSize = cbSize;
lineErr = lineGetTranslateCaps(NULL, TAPI_API_VERSION, ptc);
if (LINEERR_STRUCTURETOOSMALL == lineErr ||
ptc->dwNeededSize > ptc->dwTotalSize)
{
// Provided structure was too small, resize and try again
cbSize = ptc->dwNeededSize;
GlobalFreePtr(ptc);
ptc = (LPLINETRANSLATECAPS)GlobalAllocPtr(GPTR, cbSize);
if (ptc)
{
ptc->dwTotalSize = cbSize;
lineErr = lineGetTranslateCaps(NULL, TAPI_API_VERSION, ptc);
if (0 != lineErr)
{
// Failure
GlobalFreePtr(ptc);
ptc = NULL;
}
}
}
else if (0 != lineErr)
{
// Failure
GlobalFreePtr(ptc);
ptc = NULL;
}
}
*pptc = ptc;
return NULL != *pptc;
}
/*----------------------------------------------------------
Purpose: Initialize the Dialing locations listbox
Returns: --
Cond: --
*/
void
PRIVATE
SetCurrentLocation(
IN HWND hdlg)
{
LPLINETRANSLATECAPS ptc;
HWND hwndLoc = GetDlgItem(hdlg, IDC_LOC);
if (GetTranslateCaps(&ptc))
{
DWORD i;
LPLINELOCATIONENTRY ple;
DWORD dwCurLocID = ptc->dwCurrentLocationID;
// Find the current location
ple = (LPLINELOCATIONENTRY)((LPBYTE)ptc + ptc->dwLocationListOffset);
for (i = 0; i < ptc->dwNumLocations; i++, ple++)
{
if (dwCurLocID == ple->dwPermanentLocationID)
{
LPTSTR pszName = (LPTSTR)((LPBYTE)ptc +
ple->dwLocationNameOffset);
SetWindowText(hwndLoc, pszName);
break;
}
}
GlobalFreePtr(ptc);
}
}
#endif
/*----------------------------------------------------------
Purpose: WM_INITDIALOG handler
Returns: FALSE when we assign the control focus
Cond: --
*/
BOOL
PRIVATE
ModemCpl_OnInitDialog(
IN HWND hDlg,
IN HWND hwndFocus,
IN LPARAM lParam)
{
HIMAGELIST himl;
LV_COLUMN lvcol;
LPMODEMDLG lpmd;
TCHAR sz[MAX_BUF];
HWND hwndCtl;
if (!USER_IS_ADMIN())
{
// Don't let the non-admin user add modems
HWND hwndAdd = GetDlgItem(hDlg, IDC_ADD);
Button_Enable(hwndAdd, FALSE);
}
SetWindowLong(hDlg, DWL_USER, ((LPPROPSHEETPAGE)lParam)->lParam);
lpmd = (LPMODEMDLG)((LPPROPSHEETPAGE)lParam)->lParam;
lpmd->cSel = 0;
hwndCtl = GetDlgItem(hDlg, IDC_MODEMLV);
// Use the "full line highlight" feature to highlight across all columns
SendMessage(hwndCtl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
// Get the modem icon image list
if (GetModemImageList(&himl))
{
ListView_SetImageList(hwndCtl, himl, TRUE);
}
else
{
MsgBox(g_hinst,
hDlg,
MAKEINTRESOURCE(IDS_OOM_OPENCPL),
MAKEINTRESOURCE(IDS_CAP_MODEM),
NULL,
MB_OK | MB_ICONEXCLAMATION);
PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
}
// Insert the modem column. The widths are calculated in ModemFillLB.
lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
lvcol.fmt = LVCFMT_LEFT;
lvcol.cx = 0;
lvcol.iSubItem = ICOL_MODEM;
lvcol.pszText = SzFromIDS(g_hinst, IDS_MODEM, sz, sizeof(sz));
ListView_InsertColumn(hwndCtl, ICOL_MODEM, &lvcol);
// Insert the port column
lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
lvcol.fmt = LVCFMT_LEFT;
lvcol.cx = 0;
lvcol.iSubItem = ICOL_PORT;
lvcol.pszText = SzFromIDS(g_hinst, IDS_PORT, sz, sizeof(sz));
ListView_InsertColumn(hwndCtl, ICOL_PORT, &lvcol);
FillModemLB(hDlg, lpmd->hdi, 0, ICOL_MODEM);
// Set the column widths. Try to fit both columns on the
// control without requiring horizontal scrolling.
ListView_SetColumnWidth(hwndCtl, ICOL_MODEM, LVSCW_AUTOSIZE_USEHEADER);
ListView_SetColumnWidth(hwndCtl, ICOL_PORT, LVSCW_AUTOSIZE_USEHEADER);
PropSheet_CancelToClose(GetParent(hDlg));
return TRUE;
}
/*----------------------------------------------------------
Purpose: WM_COMMAND Handler
Returns: --
Cond: --
*/
void
PRIVATE
ModemCpl_OnCommand(
IN HWND hDlg,
IN int id,
IN HWND hwndCtl,
IN UINT uNotifyCode)
{
LPMODEMDLG lpmd = (LPMODEMDLG)GetWindowLong(hDlg, DWL_USER);
switch (id)
{
case IDC_ADD:
// Kick off the modem wizard.
DoWizard(hDlg, lpmd->hdi);
FillModemLB(hDlg, lpmd->hdi, 0, ICOL_MODEM);
break;
case MIDM_REMOVE:
case IDC_REMOVE:
RemoveModem(hDlg, lpmd);
break;
case MIDM_PROPERTIES:
case IDC_PROPERTIES:
DoModemProperties(hDlg, lpmd->hdi);
break;
case MIDM_CLONE:
CloneModem(hDlg, lpmd);
break;
#ifdef TAPI_WORKS
case IDC_DIALPROP:
DoDialingProperties(hDlg, FALSE, FALSE);
SetCurrentLocation(hDlg);
break;
#endif
}
}
// This structure is used by the ModemCpl_Compare function to
// sort the listview columns
typedef struct tagSORTPARAMS
{
int icol;
BOOL bAscending;
} SORTPARAMS, FAR* PSORTPARAMS;
/*----------------------------------------------------------
Purpose: Comparison function for sorting columns
Returns:
Cond: --
*/
int
CALLBACK
ModemCpl_Compare(
IN LPARAM lparam1,
IN LPARAM lparam2,
IN LPARAM lparamSort)
{
int iRet;
PMODEMITEM pitem1 = (PMODEMITEM)lparam1;
PMODEMITEM pitem2 = (PMODEMITEM)lparam2;
PSORTPARAMS pparams = (PSORTPARAMS)lparamSort;
switch (pparams->icol)
{
case ICOL_MODEM:
//iRet = lstrcmp(pitem1->mpp.szFriendlyName, pitem2->mpp.szFriendlyName);
iRet = my_lstrcmp_an(pitem1->mpp.szFriendlyName, pitem2->mpp.szFriendlyName);
break;
case ICOL_PORT:
// iRet = lstrcmp(pitem1->mpp.szPort, pitem2->mpp.szPort);
iRet = my_lstrcmp_an(pitem1->mpp.szPort, pitem2->mpp.szPort);
break;
}
return iRet;
}
/*----------------------------------------------------------
Purpose: Sorts one of the listview columns
Returns: --
Cond: --
*/
void
PRIVATE
ModemCpl_SortColumn(
IN HWND hwndCtl,
IN int icol)
{
SORTPARAMS params;
params.icol = icol;
params.bAscending = TRUE;
ListView_SortItems(hwndCtl, ModemCpl_Compare, (LPARAM)&params);
g_CurrentSubItemToSort = icol;
}
/*----------------------------------------------------------
Purpose: Show the context menu
Returns: --
Cond: --
*/
void
PRIVATE
ModemCpl_DoContextMenu(
IN HWND hDlg,
IN LPPOINT ppt)
{
HMENU hmenu = LoadMenu(g_hinst, MAKEINTRESOURCE(POPUP_CONTEXT));
if (hmenu)
{
HMENU hmenuContext = GetSubMenu(hmenu, 0);
TrackPopupMenu(hmenuContext, TPM_LEFTALIGN | TPM_RIGHTBUTTON,
ppt->x, ppt->y, 0, hDlg, NULL);
DestroyMenu(hmenu);
}
}
/*----------------------------------------------------------
Purpose: WM_NOTIFY handler
Returns: varies
Cond: --
*/
LRESULT
PRIVATE
ModemCpl_OnNotify(
IN HWND hDlg,
IN int idFrom,
IN NMHDR FAR * lpnmhdr)
{
LRESULT lRet = 0;
LPMODEMDLG lpmd = (LPMODEMDLG)GetWindowLong(hDlg, DWL_USER);
HWND hwndFocus;
switch (lpnmhdr->code)
{
case PSN_SETACTIVE:
#ifdef TAPI_WORKS
SetCurrentLocation(hDlg);
#endif
break;
case PSN_KILLACTIVE:
// N.b. This message is not sent if user clicks Cancel!
// N.b. This message is sent prior to PSN_APPLY
//
break;
case PSN_APPLY:
break;
case NM_RCLICK:
if (IDC_MODEMLV == lpnmhdr->idFrom)
{
// Was an item clicked?
HWND hwndCtl = lpnmhdr->hwndFrom;
LV_HITTESTINFO ht;
POINT pt;
GetCursorPos(&pt);
ht.pt = pt;
ScreenToClient(hwndCtl, &ht.pt);
ListView_HitTest(hwndCtl, &ht);
if (ht.flags & LVHT_ONITEM)
{
// Yes: don't bring up the menu if it's a non-Admin user.
// They're not allowed to do any of these operations.
if (USER_IS_ADMIN())
ModemCpl_DoContextMenu(hDlg, &pt);
}
}
break;
case NM_RETURN:
SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_PROPERTIES, BN_CLICKED),
(LPARAM)GetDlgItem(hDlg, IDC_PROPERTIES));
break;
case LVN_KEYDOWN:
{
NM_LISTVIEW FAR * lpnm_lv = (NM_LISTVIEW FAR *)lpnmhdr;
switch (((LV_KEYDOWN FAR *)lpnm_lv)->wVKey)
{
case VK_DELETE:
RemoveModem(hDlg, lpmd);
break;
case VK_F10:
// Shift-F10 brings up the context menu
// Is the shift down?
if ( !(0x8000 & GetKeyState(VK_SHIFT)) )
{
// No; break
break;
}
// Yes; fall thru
case VK_APPS: { // Context menu
HWND hwndCtl = lpnmhdr->hwndFrom;
int iSel;
iSel = ListView_GetNextItem(hwndCtl, -1, LVNI_SELECTED);
if (-1 != iSel)
{
RECT rc;
POINT pt;
ListView_GetItemRect(hwndCtl, iSel, &rc, LVIR_ICON);
pt.x = rc.left + ((rc.right - rc.left) / 2);
pt.y = rc.top + ((rc.bottom - rc.top) / 2);
ClientToScreen(hwndCtl, &pt);
ModemCpl_DoContextMenu(hDlg, &pt);
}
}
break;
}
}
break;
case LVN_COLUMNCLICK:
{
NM_LISTVIEW FAR * lpnm_lv = (NM_LISTVIEW FAR *)lpnmhdr;
ModemCpl_SortColumn(lpnmhdr->hwndFrom, lpnm_lv->iSubItem);
}
break;
case LVN_GETDISPINFO:
{
LV_ITEM FAR * plvitem = &((LV_DISPINFO FAR *)lpnmhdr)->item;
// Getting the display text for the item?
if (IsFlagSet(plvitem->mask, LVIF_TEXT))
{
// Yes
PMODEMITEM pitem = (PMODEMITEM)plvitem->lParam;
if (ICOL_MODEM == plvitem->iSubItem)
{
#ifdef UNDER_CONTRUCTION
TCHAR rgchDisplayName[MAX_BUF_REG];
// Add prefix spaces to get the list box sort order
// to work right (display COM2 before COM12, etc).
ASSERT(sizeof(rgchDisplayName)==sizeof(pitem->mpp.szFriendlyName));
FormatFriendlyNameForDisplay
(
pitem->mpp.szFriendlyName,
rgchDisplayName,
sizeof(rgchDisplayName)/sizeof(TCHAR)
);
lstrcpyn(plvitem->pszText, rgchDisplayName, plvitem->cchTextMax);
#else //!UNDER_CONTRUCTION
lstrcpyn(plvitem->pszText, pitem->mpp.szFriendlyName, plvitem->cchTextMax);
#endif //!UNDER_CONSTRUCTION
}
else if (ICOL_PORT == plvitem->iSubItem)
{
#ifdef UNDER_CONTRUCTION
TCHAR rgchDisplayName[MAX_BUF_REG];
ASSERT(sizeof(rgchDisplayName)==sizeof(pitem->mpp.szPort));
// Add prefix spaces to get the list box sort order
// to work right (display COM2 before COM12, etc).
FormatPortForDisplay
(
pitem->mpp.szPort,
rgchDisplayName,
sizeof(rgchDisplayName)/sizeof(TCHAR)
);
lstrcpyn(plvitem->pszText, rgchDisplayName, plvitem->cchTextMax);
#else //!UNDER_CONTRUCTION
lstrcpyn(plvitem->pszText, pitem->mpp.szPort, plvitem->cchTextMax);
#endif //!UNDER_CONTRUCTION
}
}
}
break;
case LVN_ITEMCHANGED:
{
NM_LISTVIEW FAR * lpnm_lv = (NM_LISTVIEW FAR *)lpnmhdr;
if (IsFlagSet(lpnm_lv->uChanged, LVIF_STATE))
{
// Disable/enable buttons based on selection change
HWND hwndProp = GetDlgItem(hDlg, IDC_PROPERTIES);
HWND hwndDel = GetDlgItem(hDlg, IDC_REMOVE);
if (IsFlagClear(lpnm_lv->uOldState, LVIS_SELECTED) &&
IsFlagSet(lpnm_lv->uNewState, LVIS_SELECTED))
{
lpmd->cSel++;
}
else if (IsFlagSet(lpnm_lv->uOldState, LVIS_SELECTED) &&
IsFlagClear(lpnm_lv->uNewState, LVIS_SELECTED))
{
lpmd->cSel--;
}
// Avoid flash
if (0 == lpmd->cSel && TRUE == IsWindowEnabled(hwndProp))
{
hwndFocus = GetFocus();
Button_Enable(hwndProp, FALSE);
Button_Enable(hwndDel, FALSE);
if ( !hwndFocus || !IsWindowEnabled(hwndFocus) )
{
SetFocus(GetDlgItem(hDlg, IDC_ADD));
SendMessage(hDlg, DM_SETDEFID, IDC_ADD, 0);
}
}
else if (1 == lpmd->cSel && FALSE == IsWindowEnabled(hwndProp))
{
Button_Enable(hwndProp, USER_IS_ADMIN());
Button_Enable(hwndDel, USER_IS_ADMIN());
}
}
}
break;
case LVN_DELETEALLITEMS:
hwndFocus = GetFocus();
Button_Enable(GetDlgItem(hDlg, IDC_PROPERTIES), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_REMOVE), FALSE);
lpmd->cSel = 0;
if ( !hwndFocus || !IsWindowEnabled(hwndFocus) )
{
SetFocus(GetDlgItem(hDlg, IDC_ADD));
SendMessage(hDlg, DM_SETDEFID, IDC_ADD, 0);
}
break;
default:
break;
}
return lRet;
}
/*----------------------------------------------------------
Purpose: WM_DEVICECHANGE handler
Returns: --
Cond: --
*/
void
PRIVATE
ModemCpl_OnDeviceChange(
IN HWND hDlg,
IN UINT nDbt)
{
#ifdef FULL_PNP
if (DBT_DEVNODES_CHANGED == uDbt)
{
// Refresh listview
CplDiDestroyDeviceInfoList(lpmd->hdi);
CplDiGetModemDevs(&lpmd->hdi, hDlg, DIGCF_PRESENT, NULL);
FillModemLB(hDlg, lpmd->hdi, 0, ICOL_MODEM);
}
return FALSE;
#endif //FULL_PNP
}
/*----------------------------------------------------------
Purpose: WM_DESTROY handler
Returns: --
Cond: --
*/
void
PRIVATE
ModemCpl_OnDestroy(
IN HWND hDlg)
{
#ifdef INSTANT_DEVICE_ACTIVATION
if (DEVICE_CHANGED(gDeviceFlags))
{
HandleDeviceChange(gDeviceFlags, GetDesktopWindow() );
}
#endif // INSTANT_DEVICE_ACTIVATION
// Need to free the device info structs for each modem
FreeModemListData((HWND)GetDlgItem(hDlg, IDC_MODEMLV));
}
/*----------------------------------------------------------
Purpose: Dialog proc for main modem CPL dialog
Returns: varies
Cond: --
*/
BOOL CALLBACK ModemCplDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
#pragma data_seg(DATASEG_READONLY)
const static DWORD rgHelpIDs[] = {
(UINT)IDC_STATIC, IDH_MODEM_INSTALLED,
IDC_CLASSICON, IDH_MODEM_INSTALLED,
IDC_MODEMLV, IDH_MODEM_INSTALLED,
IDC_ADD, IDH_MODEM_ADD,
IDC_REMOVE, IDH_MODEM_REMOVE,
IDC_PROPERTIES, IDH_MODEM_PROPERTIES,
IDC_DIALPROP, IDH_MODEM_DIALING_PROPERTIES,
IDC_LOC, IDH_MODEM_DIALING_PROPERTIES,
0, 0 };
#pragma data_seg()
switch (message)
{
HANDLE_MSG(hDlg, WM_INITDIALOG, ModemCpl_OnInitDialog);
HANDLE_MSG(hDlg, WM_DESTROY, ModemCpl_OnDestroy);
HANDLE_MSG(hDlg, WM_COMMAND, ModemCpl_OnCommand);
HANDLE_MSG(hDlg, WM_NOTIFY, ModemCpl_OnNotify);
case WM_DEVICECHANGE:
ModemCpl_OnDeviceChange(hDlg, (UINT)wParam);
break;
case WM_HELP:
WinHelp(((LPHELPINFO)lParam)->hItemHandle, c_szWinHelpFile, HELP_WM_HELP, (DWORD)(LPVOID)rgHelpIDs);
break;
case WM_CONTEXTMENU:
// Don't bring up help context menu on list view control - it
// already has a popup menu on the right mouse click.
if (GetWindowLong((HWND)wParam, GWL_ID) != IDC_MODEMLV)
WinHelp((HWND)wParam, c_szWinHelpFile, HELP_CONTEXTMENU, (DWORD)(LPVOID)rgHelpIDs);
break;
}
return FALSE;
}
#ifdef INSTANT_DEVICE_ACTIVATION
BOOL IsRasInstalled(void);
DWORD LaunchRasCpl(BOOL fInstall, HWND hWndOwner);
void HandleDeviceChange(DWORD dwDeviceFlags, HWND hWndOwner)
{
HDEVINFO hdi=NULL;
BOOL bInstalled=FALSE;
DBG_ENTER(HandleDeviceChange);
// BUG BUG -- if a device is added the class instaler (ci.c) will
// notify the TSP -- so if a device is both added and removed, the TSP
// will be notified twice. The tsp will probably enumerate the modems
// twice. This may be quite OK.
if (DEVICE_REMOVED(dwDeviceFlags))
{
NotifyTSP_ReEnum();
}
//
if (DEVICE_CHANGED(dwDeviceFlags) && IsRasInstalled())
{
TRACE_MSG(TF_GENERAL, "Ras is installed");
if (IDYES == MsgBox(g_hinst, hWndOwner,
MAKEINTRESOURCE(IDS_NT_CONFIG_RAS),
MAKEINTRESOURCE(IDS_CAP_MODEMSETUP),
NULL,
MB_YESNO | MB_QUESTION))
{
LaunchRasCpl(FALSE, hWndOwner);
}
}
DBG_EXIT(HandleDeviceChange);
}
/* Returns true if RAS is installed, false if not.
*/
BOOL IsRasInstalled(void)
{
HKEY hkey;
BOOL fInstalled;
if (RegOpenKey( HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\RAS"), &hkey ) == 0)
{
RegCloseKey( hkey );
return TRUE;
}
return FALSE;
}
DWORD
(* fNetSetupReviewBindings) (
HWND hwndParent,
DWORD Reserved
);
/* Runs the RAS install program.
**
** Returns 0 if successful, or an error code.
*/
DWORD LaunchRasCpl(BOOL fInstall, HWND hWndOwner)
{
DWORD dwExitCode;
TCHAR szCmd[ (MAX_PATH * 2) + 50 + 1 ];
TCHAR szSysDir[ MAX_PATH + 1 ];
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL f;
char *apszArgs[3];
char *pszResult;
char buffer[32];
HMODULE hModule;
/* Determine if user is an admin so we know which menu to present.
*/
{
// +++ Removed code --
}
szSysDir[ 0 ] = TEXT('\0');
GetSystemDirectory( szSysDir, MAX_PATH );
wsprintf( szCmd, TEXT("%s\\setup.exe /F /I %s\\oemnsvra.inf /W %d /T RAS_INSTALL_MODE = %s"),
szSysDir, szSysDir, hWndOwner,
(fInstall)?TEXT("Install"):TEXT("Configure"));
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
si.lpTitle = NULL;
TRACE_MSG(TF_GENERAL, "InstallCmd=%s",szCmd);
f = CreateProcess(
NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );
WaitForSingleObject( pi.hProcess, INFINITE );
if (f)
{
GetExitCodeProcess( pi.hProcess, &dwExitCode );
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
else
dwExitCode = GetLastError();
#if 1
if (dwExitCode == 1) {
hModule = LoadLibrary( TEXT("NETCFG.DLL") );
if( hModule == NULL )
{
dwExitCode = GetLastError();
return dwExitCode;
}
fNetSetupReviewBindings = (PVOID)GetProcAddress( hModule, "NetSetupReviewBindings" );
if( fNetSetupReviewBindings == NULL )
{
dwExitCode = GetLastError();
return dwExitCode;
}
TRACE_MSG(TF_GENERAL, "Install: Calling NetSetupReviewBindings");
if(( dwExitCode = (*fNetSetupReviewBindings)( hWndOwner, 0)) != ERROR_SUCCESS )
{
return dwExitCode;
}
TRACE_MSG(TF_GENERAL, "Install: Returned from NetSetupReviewBindings");
if (RestartComputerDlg( NULL ))
{
RestartComputer();
}
dwExitCode = 0;
}
TRACE_MSG(TF_GENERAL, "InstallCmd=%d", dwExitCode);
#endif
return dwExitCode;
}
BOOL ConfigureModemSys(BOOL fModemsPresent)
{
SC_HANDLE schModemSys=NULL;
SC_HANDLE schSCManager=NULL;
SERVICE_STATUS ServiceStatus;
BOOL fRet=FALSE;
LPQUERY_SERVICE_CONFIG lpQSC=NULL;
DWORD dwcbNeeded=0;
DWORD dwStartType=0;
schSCManager=OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!schSCManager)
{
TRACE_MSG(TF_GENERAL, "OpenSCManager() failed!");
goto end;
}
schModemSys=OpenService(
schSCManager,
TEXT("modem"),
SERVICE_CHANGE_CONFIG|
SERVICE_QUERY_CONFIG|
SERVICE_QUERY_STATUS
);
if (!schModemSys)
{
TRACE_MSG(TF_GENERAL, "OpenService() for modem.sys failed!");
goto end;
}
//fRet=QueryServiceStatus(
// schModemSys,
// &ServiceStatus
// );
fRet=QueryServiceConfig(
schModemSys,
NULL,
0,
&dwcbNeeded
);
if ((!fRet && GetLastError()!=ERROR_INSUFFICIENT_BUFFER)||!dwcbNeeded)
{
TRACE_MSG(TF_GENERAL, "Totally wierd!");
goto end;
}
lpQSC = LocalAlloc(LPTR, dwcbNeeded);
if (!lpQSC)
{
goto end;
}
fRet=QueryServiceConfig(
schModemSys,
lpQSC,
dwcbNeeded,
&dwcbNeeded
);
if (!fRet)
{
TRACE_MSG(TF_GENERAL, "QueryServiceConfig failed 2nd time!");
goto end;
}
TRACE_MSG(TF_GENERAL, "Service: Type=%lx; Start=%lx; Err=%lx",
lpQSC->dwServiceType,
lpQSC->dwStartType,
lpQSC->dwErrorControl
);
if (fModemsPresent)
{
if (lpQSC->dwServiceType==SERVICE_KERNEL_DRIVER
|| lpQSC->dwServiceType==SERVICE_FILE_SYSTEM_DRIVER)
{
TRACE_MSG(TF_GENERAL, "Service: Setting SystemStartup");
dwStartType = SERVICE_SYSTEM_START;
}
else
{
TRACE_MSG(TF_GENERAL, "Service: Setting Auto Startup");
dwStartType = SERVICE_AUTO_START;
}
}
else
{
dwStartType = SERVICE_DEMAND_START;
}
fRet=ChangeServiceConfig(
schModemSys,
SERVICE_NO_CHANGE,
dwStartType,
SERVICE_NO_CHANGE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
lpQSC->lpDisplayName
);
if (!fRet)
{
TRACE_MSG(TF_GENERAL, "ServiceConfig returns err %08lx",
GetLastError());
}
// fall through...
end:
if (schModemSys) CloseServiceHandle(schModemSys);
if (schSCManager) CloseServiceHandle(schSCManager);
if (lpQSC) LocalFree(lpQSC);
return fRet;
}
BOOL
RestartComputerDlg(
IN HWND hwndOwner )
/* Popup that asks the user to restart. 'HwndOwner' is the owning window.
**
** Returns true if user selects "Yes", false otherwise.
*/
{
int nStatus=FALSE;
TRACE_MSG(TF_GENERAL, "RestartComputerDlg");
#if 0
nStatus =
(BOOL )DialogBoxParam(
g_hinst,
MAKEINTRESOURCE( DID_RC_Restart ),
hwndOwner,
RcDlgProc,
(LPARAM )NULL );
if (nStatus == -1)
nStatus = FALSE;
#else // 0
// Ask the user first
if (IDYES == MsgBox(g_hinst, hwndOwner,
MAKEINTRESOURCE(IDS_ASK_REBOOTNOW),
MAKEINTRESOURCE(IDS_CAP_RASCONFIG),
NULL,
MB_YESNO | MB_ICONEXCLAMATION))
{
nStatus = TRUE;
}
#endif // 0
return (BOOL )nStatus;
}
BOOL
RestartComputer()
/* Called if user chooses to shut down the computer.
**
** Return false if failure, true otherwise
*/
{
HANDLE hToken; /* handle to process token */
TOKEN_PRIVILEGES tkp; /* ptr. to token structure */
BOOL fResult; /* system shutdown flag */
TRACE_MSG(TF_GENERAL, "RestartComputer");
/* Enable the shutdown privilege */
if (!OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
return FALSE;
/* Get the LUID for shutdown privilege. */
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; /* one privilege to set */
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
/* Get shutdown privilege for this process. */
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
/* Cannot test the return value of AdjustTokenPrivileges. */
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
if( !ExitWindowsEx(EWX_REBOOT, 0))
return FALSE;
/* Disable shutdown privilege. */
tkp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
return TRUE;
}
#endif // INSTANT_DEVICE_ACTIVATION
int my_atol(LPTSTR lptsz);
// Special-case alphanumeric stringcmp.
//
// The function returns for various combinations of input are give below.
// Note that it only does a numeric comparison for the tail end of the string.
// So, for example, it claims "2a" > "12". It also claims "a2 > a01". Big deal.
// The following data was actually generated by calling this function.
//
// fn("","")=0 fn("a","a")=0 fn("1","11")=-1 fn("a2","a12")=-990
// fn("","1")=-1 fn("1","1")=0 fn("11","1")=1 fn("a12","a2")=990
// fn("1","")=1 fn("a","1")=1 fn("1","12")=-1 fn("12a","2a")=-1
// fn("","a")=-1 fn("1","a")=-1 fn("12","1")=1 fn("2a","12a")=1
// fn("a","")=1 fn("a","b")=-1 fn("2","12")=-990 fn("a2","a01")=-879
// fn("b","a")=1 fn("12","2")=990 fn("101","12")=879
// fn("1","2")=-11 fn("2","1")=11
//
int my_lstrcmp_an(LPTSTR lptsz1, LPTSTR lptsz2)
{
int i1, i2;
// Skip common prefix
while(*lptsz1 && *lptsz1==*lptsz2)
{
lptsz1++;
lptsz2++;
}
i1 = my_atol(lptsz1);
i2 = my_atol(lptsz2);
if (i1==MAXDWORD || i2==MAXDWORD) return lstrcmp(lptsz1, lptsz2);
else return i1-i2;
}
int my_atol(LPTSTR lptsz)
{
int i = (int) *lptsz;
int iRet=1;
if (!i) goto bail;
do
{
if (i<'0' || i>'9') goto bail;
iRet*=10;
iRet+=i-'0';
i = (int) *lptsz++;
} while(i);
return iRet;
bail:
return MAXDWORD;
}