725 lines
21 KiB
C++
725 lines
21 KiB
C++
|
|
|||
|
//
|
|||
|
// includes
|
|||
|
//
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#define INCL_WINDOWS
|
|||
|
#define INCL_NETERRORS
|
|||
|
#define INCL_NETLIB
|
|||
|
#include "lmui.hxx"
|
|||
|
#define INCL_BLT_MISC
|
|||
|
#include "blt.hxx" // AUTO_CURSOR
|
|||
|
#include "dbgstr.hxx"
|
|||
|
#include "strnumer.hxx"
|
|||
|
#include "uiassert.hxx"
|
|||
|
#include "lmobj.hxx"
|
|||
|
#include "lmoenum.hxx" // SERVICE_ENUM
|
|||
|
#include "lmoesvc.hxx" // SERVICE_ENUM
|
|||
|
#include "regkey.hxx" // REG_KEY
|
|||
|
#include "lmobjrc.h" // IDS_PROFEXT_*
|
|||
|
|
|||
|
extern "C"
|
|||
|
{
|
|||
|
#include <prsht.h>
|
|||
|
#include "profext.h"
|
|||
|
#include <cfgmgr32.h> // CONFIGRET
|
|||
|
#include <regstr.h> // CSCONFIGFLAG_DISABLED
|
|||
|
// we have to do this for a clean compile
|
|||
|
#undef DBGOUT
|
|||
|
#include "sysdm.h" // IDH_HWPROFILE
|
|||
|
#include <regstr.h> // REGSTR_PATH_SERVICES
|
|||
|
#include <ntddndis.h> // NdisMedium* constants
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// global data
|
|||
|
//
|
|||
|
HINSTANCE hInst = NULL; // Module handle
|
|||
|
|
|||
|
static int HwProfileHelpIds[] = {
|
|||
|
IDC_DISABLE, IDH_HWPROFILE+IDC_DISABLE,
|
|||
|
IDC_ENABLE, IDH_HWPROFILE+IDC_ENABLE,
|
|||
|
IDC_NONET, IDH_HWPROFILE+IDC_NONET,
|
|||
|
IDC_ERROR, IDH_HWPROFILE+IDC_ERROR,
|
|||
|
0, 0
|
|||
|
};
|
|||
|
|
|||
|
#define SZ_NDIS SZ("NDIS")
|
|||
|
#define TCH_REGSEPERATOR TCH('\\')
|
|||
|
#define SZ_REGSEPERATOR SZ("\\")
|
|||
|
#define SZ_REGPARAMETERS SZ("\\Parameters")
|
|||
|
#define SZ_REGLINKAGE SZ("\\Linkage")
|
|||
|
#define SZ_REGMEDIATYPE SZ("MediaType")
|
|||
|
#define SZ_REGBIND SZ("Bind")
|
|||
|
|
|||
|
|
|||
|
APIERR MapCfgMgr32Error( CONFIGRET dwCfgMgr32Error )
|
|||
|
{
|
|||
|
APIERR err = IDS_CFGMGR32_BASE + dwCfgMgr32Error;
|
|||
|
switch (dwCfgMgr32Error)
|
|||
|
{
|
|||
|
|
|||
|
case CR_SUCCESS :
|
|||
|
// CR_NEED_RESTART is considered to be Success
|
|||
|
case CR_NEED_RESTART :
|
|||
|
err = NO_ERROR;
|
|||
|
break;
|
|||
|
|
|||
|
// Just use the CFGMGR out-of-memory error
|
|||
|
//
|
|||
|
// case CR_OUT_OF_MEMORY :
|
|||
|
// err = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
// break;
|
|||
|
|
|||
|
//
|
|||
|
// These are supposedly for Windows 95 only!
|
|||
|
//
|
|||
|
case CR_INVALID_ARBITRATOR :
|
|||
|
case CR_INVALID_NODELIST :
|
|||
|
case CR_DLVXD_NOT_FOUND :
|
|||
|
case CR_NOT_SYSTEM_VM :
|
|||
|
case CR_NO_ARBITRATOR :
|
|||
|
case CR_DEVLOADER_NOT_READY :
|
|||
|
ASSERT( FALSE );
|
|||
|
// fall through
|
|||
|
|
|||
|
default :
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HandleError( HWND hDlg, APIERR err, HWND hwndEdit = NULL )
|
|||
|
{
|
|||
|
NLS_STR nlsError, nlsTitle;
|
|||
|
if ( nlsError.QueryError() != NERR_Success
|
|||
|
|| nlsTitle.QueryError() != NERR_Success
|
|||
|
|| nlsError.Load( err ) != NERR_Success
|
|||
|
|| nlsTitle.Load( IDS_PROFEXT_ERROR ) != NERR_Success
|
|||
|
)
|
|||
|
{
|
|||
|
TRACEEOL( "PROFEXT.DLL: HandleError failure" );
|
|||
|
ASSERT( FALSE );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (hwndEdit != NULL)
|
|||
|
{
|
|||
|
::SetWindowText( hwndEdit, nlsError.QueryPch() );
|
|||
|
::ShowWindow( hwndEdit, SW_SHOW );
|
|||
|
}
|
|||
|
if (err != IDS_PROFEXT_NOADAPTERS)
|
|||
|
{
|
|||
|
REQUIRE( IDOK == ::MessageBox( hDlg,
|
|||
|
nlsError.QueryPch(),
|
|||
|
nlsTitle.QueryPch(),
|
|||
|
MB_ICONSTOP | MB_OK ) );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
APIERR
|
|||
|
IsDisabled( ULONG ulProfileID, DEVINSTID devinst, BOOL* pfIsDisabled )
|
|||
|
{
|
|||
|
TRACEEOL( "IsDisabled( " << ulProfileID << ", \"" << devinst << "\") " );
|
|||
|
ASSERT( pfIsDisabled != NULL );
|
|||
|
APIERR err = NERR_Success;
|
|||
|
ULONG ulValue = 0;
|
|||
|
CONFIGRET configret = ::CM_Get_HW_Prof_Flags(
|
|||
|
devinst,
|
|||
|
ulProfileID,
|
|||
|
&ulValue,
|
|||
|
0x0 );
|
|||
|
err = MapCfgMgr32Error( configret );
|
|||
|
if (err != NERR_Success)
|
|||
|
{
|
|||
|
TRACEEOL( "\terror " << configret );
|
|||
|
return err;
|
|||
|
}
|
|||
|
*pfIsDisabled = !!(ulValue & CSCONFIGFLAG_DISABLED);
|
|||
|
TRACEEOL( (CHAR*)((*pfIsDisabled)?"\tis disabled":"\tis enabled") );
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
APIERR
|
|||
|
Disable( ULONG ulProfileID, DEVINSTID devinst, BOOL fDisable )
|
|||
|
{
|
|||
|
APIERR err = NERR_Success;
|
|||
|
ULONG ulValue = 0;
|
|||
|
CONFIGRET configret = ::CM_Get_HW_Prof_Flags(
|
|||
|
devinst,
|
|||
|
ulProfileID,
|
|||
|
&ulValue,
|
|||
|
0x0 );
|
|||
|
err = MapCfgMgr32Error( configret );
|
|||
|
if (err != NERR_Success)
|
|||
|
{
|
|||
|
TRACEEOL( "\tEnable: CM_Get_HW_Prof_Flags error " << configret );
|
|||
|
return err;
|
|||
|
}
|
|||
|
if (fDisable)
|
|||
|
{
|
|||
|
if ( ulValue & CSCONFIGFLAG_DISABLED )
|
|||
|
{
|
|||
|
TRACEEOL( "Disable: \"" << devinst << "\" already disabled" );
|
|||
|
return err;
|
|||
|
}
|
|||
|
ulValue |= CSCONFIGFLAG_DISABLED;
|
|||
|
} else {
|
|||
|
if ( !(ulValue & CSCONFIGFLAG_DISABLED) )
|
|||
|
{
|
|||
|
TRACEEOL( "Disable: \"" << devinst << "\" already enabled" );
|
|||
|
return err;
|
|||
|
}
|
|||
|
ulValue &= ~CSCONFIGFLAG_DISABLED;
|
|||
|
}
|
|||
|
configret = ::CM_Set_HW_Prof_Flags(
|
|||
|
devinst,
|
|||
|
ulProfileID,
|
|||
|
ulValue,
|
|||
|
0x0 );
|
|||
|
err = MapCfgMgr32Error( configret );
|
|||
|
if (err != NERR_Success)
|
|||
|
{
|
|||
|
TRACEEOL( "\tDisable: CM_Set_HW_Prof_Flags error " << configret );
|
|||
|
} else {
|
|||
|
TRACEEOL( "\tDisable: \"" << devinst
|
|||
|
<< (CHAR*)((fDisable)?"\" now disabled":"\" now enabled") );
|
|||
|
}
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
APIERR BoundServiceIsWanMediaType( NLS_STR& nlsBoundService,
|
|||
|
BOOL* pfWANMediaType,
|
|||
|
REG_KEY& regkeyHKLM )
|
|||
|
{
|
|||
|
const TCHAR * pchBoundService = nlsBoundService.QueryPch();
|
|||
|
ISTR istrBoundService( nlsBoundService );
|
|||
|
if ( nlsBoundService.strrchr( &istrBoundService, TCH_REGSEPERATOR ) )
|
|||
|
{
|
|||
|
++istrBoundService;
|
|||
|
pchBoundService = nlsBoundService.QueryPch( istrBoundService );
|
|||
|
}
|
|||
|
|
|||
|
// open HKLM\CurrentControlSet\Services\<bound service>\Parameters key
|
|||
|
NLS_STR nlsRegPath( REGSTR_PATH_SERVICES );
|
|||
|
nlsRegPath += SZ_REGSEPERATOR;
|
|||
|
nlsRegPath += pchBoundService;
|
|||
|
nlsRegPath += SZ_REGPARAMETERS;
|
|||
|
APIERR err = nlsRegPath.QueryError();
|
|||
|
if ( err != NERR_Success )
|
|||
|
{
|
|||
|
DBGEOL( "BoundServiceIsWanMediaType: string error " << err );
|
|||
|
return err;
|
|||
|
}
|
|||
|
TRACEEOL( "BoundServiceIsWanMediaType: key \"" << nlsRegPath << "\"" );
|
|||
|
REG_KEY regkeyParameters(regkeyHKLM, nlsRegPath, KEY_READ);
|
|||
|
if ( (err = regkeyParameters.QueryError()) != NERR_Success )
|
|||
|
{
|
|||
|
TRACEEOL( "BoundServiceIsWanMediaType: key \"" << nlsRegPath <<
|
|||
|
"\" error " << err );
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
DWORD dwMediaType = 0;
|
|||
|
if ( (err = regkeyParameters.QueryValue( SZ_REGMEDIATYPE, &dwMediaType))
|
|||
|
!= NERR_Success )
|
|||
|
{
|
|||
|
TRACEEOL( "BoundServiceIsWanMediaType: mediatype error " << err );
|
|||
|
return err;
|
|||
|
}
|
|||
|
TRACEEOL( "BoundServiceIsWanMediaType: media type " << dwMediaType );
|
|||
|
switch (dwMediaType-1)
|
|||
|
{
|
|||
|
case NdisMedium802_3:
|
|||
|
case NdisMedium802_5:
|
|||
|
case NdisMediumFddi:
|
|||
|
case NdisMediumLocalTalk:
|
|||
|
case NdisMediumDix:
|
|||
|
case NdisMediumArcnetRaw:
|
|||
|
case NdisMediumArcnet878_2:
|
|||
|
case NdisMediumAtm:
|
|||
|
*pfWANMediaType = FALSE;
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMediumWan:
|
|||
|
case NdisMediumWirelessWan:
|
|||
|
case NdisMediumIrda:
|
|||
|
*pfWANMediaType = TRUE;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
DBGEOL( "BoundServiceIsWanMediaType: invalid media type "
|
|||
|
<< dwMediaType );
|
|||
|
*pfWANMediaType = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
APIERR IsWanMediaType( const TCHAR * pszServiceName, BOOL* pfWANMediaType)
|
|||
|
{
|
|||
|
TRACEEOL( "IsWanMediaType: checking \"" << pszServiceName << "\"" );
|
|||
|
|
|||
|
// open HKLM key
|
|||
|
REG_KEY regkeyHKLM(HKEY_LOCAL_MACHINE, NULL, KEY_READ);
|
|||
|
APIERR err = regkeyHKLM.QueryError();
|
|||
|
if ( err != NERR_Success )
|
|||
|
{
|
|||
|
DBGEOL( "IsWanMediaType: HKLM error " << err );
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
// open HKLM\CurrentControlSet\Services\<service>\Linkage key
|
|||
|
NLS_STR nlsRegPath( REGSTR_PATH_SERVICES );
|
|||
|
nlsRegPath += SZ_REGSEPERATOR;
|
|||
|
nlsRegPath += pszServiceName;
|
|||
|
nlsRegPath += SZ_REGLINKAGE;
|
|||
|
if ( (err = nlsRegPath.QueryError()) != NERR_Success )
|
|||
|
{
|
|||
|
DBGEOL( "IsWanMediaType: string error " << err );
|
|||
|
return err;
|
|||
|
}
|
|||
|
TRACEEOL( "IsWanMediaType: key \"" << nlsRegPath << "\"" );
|
|||
|
REG_KEY regkeyLinkage(regkeyHKLM, nlsRegPath, KEY_READ);
|
|||
|
if ( (err = regkeyLinkage.QueryError()) != NERR_Success )
|
|||
|
{
|
|||
|
TRACEEOL( "IsWanMediaType: key \"" << nlsRegPath <<
|
|||
|
"\" error " << err );
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
// get Bind parameter and extract service name(s)
|
|||
|
STRLIST* pstrlistBind = NULL;
|
|||
|
if ( (err = regkeyLinkage.QueryValue( SZ_REGBIND, &pstrlistBind ))
|
|||
|
!= NERR_Success
|
|||
|
|| (err = ((pstrlistBind != NULL)
|
|||
|
? NERR_Success : ERROR_NOT_ENOUGH_MEMORY)) != NERR_Success
|
|||
|
)
|
|||
|
{
|
|||
|
TRACEEOL( "IsWanMediaType: bind value error " << err );
|
|||
|
return err;
|
|||
|
}
|
|||
|
ITER_STRLIST iterslBind( *pstrlistBind );
|
|||
|
NLS_STR* pnlsBind = NULL;
|
|||
|
*pfWANMediaType = FALSE;
|
|||
|
while ( (pnlsBind = iterslBind.Next()) != NULL )
|
|||
|
{
|
|||
|
err = BoundServiceIsWanMediaType( *pnlsBind,
|
|||
|
pfWANMediaType,
|
|||
|
regkeyHKLM );
|
|||
|
if (err != NERR_Success || *pfWANMediaType )
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
delete pstrlistBind; // CODEWORK I have seen problems with this line
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* if fSet is FALSE, set *pfNoNetworkProfile to TRUE if no network
|
|||
|
* device is enabled, set to FALSE otherwise
|
|||
|
*
|
|||
|
* if fSet is TRUE and *pfNoNetworkProfile is FALSE,
|
|||
|
* enable all network devices
|
|||
|
*
|
|||
|
* if fSet is TRUE and *pfNoNetworkProfile is TRUE,
|
|||
|
* disable all network devices
|
|||
|
*/
|
|||
|
APIERR
|
|||
|
DoNetworkProfile( ULONG ulProfileID, BOOL fSet, BOOL* pfNoNetworkProfile )
|
|||
|
{
|
|||
|
AUTO_CURSOR autocur;
|
|||
|
|
|||
|
ASSERT( pfNoNetworkProfile != NULL );
|
|||
|
APIERR err = NERR_Success;
|
|||
|
if (!fSet)
|
|||
|
*pfNoNetworkProfile=TRUE;
|
|||
|
|
|||
|
do // false loop
|
|||
|
{
|
|||
|
TRACEEOL( "DoNetworkProfile: enumerating NDIS services");
|
|||
|
SERVICE_ENUM svcenum( NULL, TRUE, SERVICE_KERNEL_DRIVER, SZ_NDIS );
|
|||
|
if ( (err = svcenum.QueryError()) != NERR_Success
|
|||
|
|| (err = svcenum.GetInfo()) != NERR_Success
|
|||
|
)
|
|||
|
{
|
|||
|
TRACEEOL( "DoNetworkProfile: error " << err << " opening svcenum" );
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
BOOL fFoundAdapter = FALSE;
|
|||
|
SERVICE_ENUM_ITER svciter( svcenum );
|
|||
|
const SERVICE_ENUM_OBJ* psvc;
|
|||
|
while( ( psvc = svciter() ) != NULL )
|
|||
|
{
|
|||
|
const TCHAR* pszServiceName = psvc->QueryServiceName();
|
|||
|
if ( 0 == ::stricmpf( pszServiceName, SZ_NDIS ) )
|
|||
|
continue;
|
|||
|
|
|||
|
BOOL fWANMediaType = FALSE;
|
|||
|
if ( (err = IsWanMediaType(pszServiceName, &fWANMediaType))
|
|||
|
!= NERR_Success)
|
|||
|
{
|
|||
|
//
|
|||
|
// All errors are ignored, and we assume WAN MediaType
|
|||
|
//
|
|||
|
TRACEEOL( "DoNetworkProfile: ignoring error " << err <<
|
|||
|
" checking mediatype of \"" << pszServiceName <<
|
|||
|
"\"" );
|
|||
|
err = NERR_Success;
|
|||
|
continue;
|
|||
|
} else if (fWANMediaType) {
|
|||
|
TRACEEOL( "DoNetworkProfile: skipping service \"" <<
|
|||
|
pszServiceName << "\" due to mediatype" );
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
ULONG cch = 0;
|
|||
|
CONFIGRET configret = ::CM_Get_Device_ID_List_Size(
|
|||
|
&cch,
|
|||
|
pszServiceName,
|
|||
|
CM_GETIDLIST_FILTER_SERVICE );
|
|||
|
if ( (err = MapCfgMgr32Error( configret )) != NERR_Success )
|
|||
|
{
|
|||
|
TRACEEOL("DoNetworkProfile: Get_Device_ID_List_Size returned " << configret );
|
|||
|
if (configret == CR_NO_SUCH_VALUE)
|
|||
|
{
|
|||
|
ASSERT( FALSE );
|
|||
|
continue;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
BUFFER bufDeviceIDs( cch*sizeof(TCHAR) );
|
|||
|
if ( (err = bufDeviceIDs.QueryError()) != NERR_Success )
|
|||
|
break;
|
|||
|
do {
|
|||
|
configret = ::CM_Get_Device_ID_List(
|
|||
|
pszServiceName,
|
|||
|
(TCHAR *)(bufDeviceIDs.QueryPtr()),
|
|||
|
bufDeviceIDs.QuerySize() / sizeof(TCHAR),
|
|||
|
CM_GETIDLIST_FILTER_SERVICE );
|
|||
|
if (configret == CR_BUFFER_SMALL)
|
|||
|
{
|
|||
|
cch *= 2;
|
|||
|
if ( (err = bufDeviceIDs.Resize(cch*sizeof(TCHAR))) != NERR_Success )
|
|||
|
break;
|
|||
|
} else if (configret == CR_NO_SUCH_VALUE)
|
|||
|
{
|
|||
|
ASSERT( FALSE );
|
|||
|
continue;
|
|||
|
}
|
|||
|
} while (configret == CR_BUFFER_SMALL);
|
|||
|
const TCHAR * pchDeviceID = (const TCHAR *)bufDeviceIDs.QueryPtr();
|
|||
|
while ( *pchDeviceID != TCH('\0') )
|
|||
|
{
|
|||
|
fFoundAdapter = TRUE;
|
|||
|
DEVINSTID devinst = (DEVINSTID)pchDeviceID;
|
|||
|
if (fSet) {
|
|||
|
if ( (err = Disable( ulProfileID,
|
|||
|
devinst,
|
|||
|
*pfNoNetworkProfile)) != NERR_Success)
|
|||
|
break;
|
|||
|
} else {
|
|||
|
BOOL fIsDisabled = FALSE;
|
|||
|
if ( (err = IsDisabled( ulProfileID,
|
|||
|
devinst,
|
|||
|
&fIsDisabled)) != NERR_Success)
|
|||
|
break;
|
|||
|
if (!fIsDisabled)
|
|||
|
{
|
|||
|
*pfNoNetworkProfile = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pchDeviceID += ::strlenf(pchDeviceID) + 1;
|
|||
|
}
|
|||
|
}
|
|||
|
TRACEEOL( "DoNetworkProfile: enumerated NDIS services");
|
|||
|
|
|||
|
if ( !fFoundAdapter && err == NERR_Success )
|
|||
|
{
|
|||
|
TRACEEOL( "DoNetworkProfile: no adapters found" );
|
|||
|
err = IDS_PROFEXT_NOADAPTERS;
|
|||
|
}
|
|||
|
|
|||
|
} while (FALSE); // false loop
|
|||
|
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
DllMain(
|
|||
|
PVOID hModule,
|
|||
|
ULONG Reason,
|
|||
|
PCONTEXT pContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the standard DLL entrypoint routine, called whenever a process
|
|||
|
or thread attaches or detaches.
|
|||
|
Arguments:
|
|||
|
|
|||
|
hModule - PVOID parameter that specifies the handle of the DLL
|
|||
|
|
|||
|
Reason - ULONG parameter that specifies the reason this entrypoint
|
|||
|
was called (either PROCESS_ATTACH, PROCESS_DETACH,
|
|||
|
THREAD_ATTACH, or THREAD_DETACH).
|
|||
|
|
|||
|
pContext - ???
|
|||
|
|
|||
|
Return value:
|
|||
|
|
|||
|
Returns true if initialization compeleted successfully, false is not.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
hInst = (HINSTANCE)hModule;
|
|||
|
|
|||
|
DBG_UNREFERENCED_PARAMETER(pContext);
|
|||
|
|
|||
|
switch(Reason) {
|
|||
|
case DLL_PROCESS_ATTACH:
|
|||
|
DisableThreadLibraryCalls(hInst);
|
|||
|
case DLL_PROCESS_DETACH:
|
|||
|
case DLL_THREAD_ATTACH:
|
|||
|
case DLL_THREAD_DETACH:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
} // DllMain
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL CALLBACK
|
|||
|
ExtensionPropSheetPageProc(
|
|||
|
LPVOID lpv,
|
|||
|
LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc,
|
|||
|
LPARAM lParam
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpv Pointer to an application-defined value that
|
|||
|
describes an item for which a property sheet
|
|||
|
page is to be created. This parameter can be NULL.
|
|||
|
|
|||
|
lpfnAddPropSheetPageProc Pointer to the AddPropSheetPageProc function.
|
|||
|
The extension dynamic-link library (DLL) calls
|
|||
|
this function to add a page to the property sheet.
|
|||
|
|
|||
|
lParam Application-defined 32-bit value.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is TRUE.
|
|||
|
If the function fails, the return value is FALSE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PROPSHEETPAGE PropPage;
|
|||
|
HPROPSHEETPAGE hPropPage;
|
|||
|
|
|||
|
PropPage.dwSize = sizeof(PROPSHEETPAGE);
|
|||
|
PropPage.dwFlags = PSP_DEFAULT;
|
|||
|
PropPage.hInstance = hInst;
|
|||
|
PropPage.pszTemplate = MAKEINTRESOURCE(DLG_HWP_EXT);
|
|||
|
PropPage.pszIcon = NULL;
|
|||
|
PropPage.pszTitle = NULL;
|
|||
|
PropPage.pfnDlgProc = NetworkPropDlg;
|
|||
|
PropPage.lParam = lParam;
|
|||
|
PropPage.pfnCallback = NULL;
|
|||
|
|
|||
|
hPropPage = CreatePropertySheetPage(&PropPage);
|
|||
|
if (hPropPage == NULL) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
(lpfnAddPropSheetPageProc)(hPropPage, 0);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
} // ExtensionPropSheetPageProc
|
|||
|
|
|||
|
|
|||
|
typedef struct {
|
|||
|
LONG ulProfile;
|
|||
|
BOOL fNoNet;
|
|||
|
BOOL fError;
|
|||
|
} PROFEXT_INTERNAL;
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
APIENTRY
|
|||
|
NetworkPropDlg(
|
|||
|
HWND hDlg,
|
|||
|
UINT uMessage,
|
|||
|
WPARAM wParam,
|
|||
|
LPARAM lParam
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
ULONG ulProfile = 0;
|
|||
|
APIERR err = NERR_Success;
|
|||
|
|
|||
|
switch (uMessage)
|
|||
|
{
|
|||
|
case WM_INITDIALOG:
|
|||
|
{
|
|||
|
PROFEXT_INTERNAL* pprofext = new PROFEXT_INTERNAL;
|
|||
|
// CODEWORK I should free this at some point
|
|||
|
ASSERT( pprofext != NULL );
|
|||
|
::memsetf( pprofext, '\0', sizeof(PROFEXT_INTERNAL) );
|
|||
|
::SetWindowLong(hDlg, DWL_USER, (LONG)pprofext);
|
|||
|
//
|
|||
|
// on WM_INITDIALOG call, property sheet's lParam field
|
|||
|
// contains the profile ID, save it in window long word for
|
|||
|
// use with other messages later
|
|||
|
//
|
|||
|
ulProfile = (ULONG)((LPPROPSHEETPAGE)lParam)->lParam;
|
|||
|
ASSERT( (LONG)ulProfile >= 0 );
|
|||
|
pprofext->ulProfile = ulProfile;
|
|||
|
BOOL fNoNetworkProfile = FALSE;
|
|||
|
err = DoNetworkProfile( ulProfile,
|
|||
|
FALSE,
|
|||
|
&fNoNetworkProfile );
|
|||
|
if (err != NERR_Success) {
|
|||
|
HWND hwndEdit = ::GetDlgItem(hDlg, IDC_ERROR);
|
|||
|
ASSERT( hwndEdit != NULL );
|
|||
|
HandleError( hDlg, err, hwndEdit );
|
|||
|
pprofext->fError = TRUE;
|
|||
|
} else {
|
|||
|
pprofext->fNoNet = (fNoNetworkProfile)?1:0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Call CM_Get_Hardware_Profile_Info to get info about
|
|||
|
// the specified profile (ulProfile).
|
|||
|
//
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
case WM_NOTIFY:
|
|||
|
|
|||
|
if (!lParam) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
switch (((NMHDR *)lParam)->code) {
|
|||
|
|
|||
|
case PSN_SETACTIVE:
|
|||
|
{
|
|||
|
PROFEXT_INTERNAL* pprofext =
|
|||
|
(PROFEXT_INTERNAL*)::GetWindowLong(hDlg, DWL_USER);
|
|||
|
ASSERT( pprofext != NULL );
|
|||
|
HWND hwndCheckbox = ::GetDlgItem(hDlg, IDC_NONET);
|
|||
|
HWND hwndEnableText = ::GetDlgItem(hDlg, IDC_ENABLE);
|
|||
|
HWND hwndDisableText = ::GetDlgItem(hDlg, IDC_DISABLE);
|
|||
|
ASSERT( hwndCheckbox
|
|||
|
&& hwndEnableText && hwndDisableText );
|
|||
|
::EnableWindow(
|
|||
|
hwndEnableText,
|
|||
|
pprofext->fNoNet && !(pprofext->fError) );
|
|||
|
::EnableWindow(
|
|||
|
hwndDisableText,
|
|||
|
!(pprofext->fNoNet) && !(pprofext->fError) );
|
|||
|
if (pprofext->fError)
|
|||
|
{
|
|||
|
::EnableWindow( hwndCheckbox, FALSE );
|
|||
|
} else {
|
|||
|
::SendMessage( hwndCheckbox, BM_SETCHECK,
|
|||
|
(pprofext->fNoNet)?1:0, 0 );
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case PSN_KILLACTIVE:
|
|||
|
{
|
|||
|
PROFEXT_INTERNAL* pprofext =
|
|||
|
(PROFEXT_INTERNAL*)::GetWindowLong(hDlg, DWL_USER);
|
|||
|
ASSERT( pprofext != NULL );
|
|||
|
//
|
|||
|
// validate selections, this page is active until I return FALSE
|
|||
|
// in DWL_MSGRESULT
|
|||
|
//
|
|||
|
if (pprofext->fError)
|
|||
|
break; // error or no adapter as initial state
|
|||
|
TRACEEOL( "NetworkPropDlg: pprofext->fNoNet is "
|
|||
|
<< pprofext->fNoNet );
|
|||
|
HWND hwnd = ::GetDlgItem(hDlg, IDC_NONET);
|
|||
|
ASSERT( hwnd != NULL );
|
|||
|
BOOL fCurrentNoNet = (::SendMessage(hwnd, BM_GETCHECK, 0, 0) != 0)
|
|||
|
? TRUE : FALSE;
|
|||
|
TRACEEOL( "NetworkPropDlg: fCurrentNoNet is " << fCurrentNoNet );
|
|||
|
if (pprofext->fNoNet != fCurrentNoNet)
|
|||
|
{
|
|||
|
err = DoNetworkProfile(
|
|||
|
pprofext->ulProfile, TRUE, &fCurrentNoNet );
|
|||
|
if (err != NERR_Success) {
|
|||
|
HandleError( hDlg, err );
|
|||
|
::SetWindowLong(hDlg, DWL_MSGRESULT, TRUE); // TRUE if error
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pprofext->fNoNet = fCurrentNoNet;
|
|||
|
::SetWindowLong(hDlg, DWL_MSGRESULT, FALSE); // TRUE if error
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case PSN_RESET:
|
|||
|
//
|
|||
|
// user canceled the property sheet
|
|||
|
//
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
|
|||
|
case WM_HELP:
|
|||
|
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, HELP_FILE,
|
|||
|
HELP_WM_HELP, (DWORD)(LPTSTR)HwProfileHelpIds);
|
|||
|
break;
|
|||
|
|
|||
|
case WM_CONTEXTMENU:
|
|||
|
WinHelp((HWND)wParam, HELP_FILE, HELP_CONTEXTMENU,
|
|||
|
(DWORD)(LPTSTR)HwProfileHelpIds);
|
|||
|
break;
|
|||
|
|
|||
|
|
|||
|
case WM_COMMAND:
|
|||
|
default:
|
|||
|
return FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
} // NetworkPropDlg
|