1258 lines
38 KiB
C
1258 lines
38 KiB
C
/*++
|
|
|
|
Copyright (c) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ras.c
|
|
|
|
Abstract:
|
|
|
|
ras.c runs as a part of w95upg.dll in winnt32.exe during Win9x migrations.
|
|
Saves connectoid information for later retrieval during Guimode setup.
|
|
|
|
Author:
|
|
|
|
Marc R. Whitten (marcw) 23-Nov-1997
|
|
|
|
Revision History:
|
|
|
|
Marc R. Whitten marcw 23-Jul-1998 - Major cleanup.
|
|
Jeff Sigman 09-Apr-2001 - Whistler cleanup.
|
|
|
|
Whistler bugs:
|
|
34270 Win9x: Upgrade: Require Data Encryption setting for VPN
|
|
connections is not migrated
|
|
125693 UpgLab9x: DUN Connectoids don't migrate selected modem properly
|
|
from Win9x
|
|
208318 Win9x Upg: Username and Password for DUN connectoid not migrated
|
|
from Win9x to Whistler
|
|
|
|
--*/
|
|
|
|
#include "pch.h" // Pre-compiled
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
#define PAESMMCFG(pAE) ((PSMMCFG)(((PBYTE)pAE)+(pAE->uOffSMMCfg)))
|
|
#define PAESMM(pAE) ((PSTR)(((PBYTE)pAE)+(pAE->uOffSMM)))
|
|
#define PAEDI(pAE) ((PDEVICEINFO)(((PBYTE)pAE)+(pAE->uOffDI )))
|
|
#define PAEAREA(pAE) ((PSTR)(((PBYTE)pAE)+(pAE->uOffArea)))
|
|
#define PAEPHONE(pAE) ((PSTR)(((PBYTE)pAE)+(pAE->uOffPhone)))
|
|
#define DECRYPTENTRY(x, y, z) EnDecryptEntry(x, (LPBYTE)y, z)
|
|
|
|
typedef LPVOID HPWL;
|
|
typedef HPWL* LPHPWL;
|
|
|
|
typedef struct {
|
|
DWORD Size;
|
|
DWORD Unknown1;
|
|
DWORD ModemUiOptions; // num seconds in high byte.
|
|
DWORD Unknown3; // 0 = Not Set.
|
|
DWORD Unknown4;
|
|
DWORD Unknown5;
|
|
DWORD ConnectionSpeed;
|
|
DWORD UnknownFlowControlData; //Somehow related to flow control.
|
|
DWORD Unknown8;
|
|
DWORD Unknown9;
|
|
DWORD Unknown10;
|
|
DWORD Unknown11;
|
|
DWORD Unknown12;
|
|
DWORD Unknown13;
|
|
DWORD Unknown14;
|
|
DWORD Unknown15;
|
|
DWORD Unknown16;
|
|
DWORD Unknown17;
|
|
DWORD Unknown18;
|
|
DWORD dwCallSetupFailTimer; // Num seconds to wait before cancel if not
|
|
// connected. (0xFF equals off.)
|
|
DWORD dwInactivityTimeout; // 0 = Not Set.
|
|
DWORD Unknown21;
|
|
DWORD SpeakerVolume; // 0|1
|
|
DWORD ConfigOptions;
|
|
DWORD Unknown24;
|
|
DWORD Unknown25;
|
|
DWORD Unknown26;
|
|
} MODEMDEVINFO, *PMODEMDEVINFO;
|
|
|
|
DEFINE_GUID(GUID_DEVCLASS_MODEM,
|
|
0x4d36e96dL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 );
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
POOLHANDLE g_RasPool;
|
|
BOOL g_RasInstalled = FALSE;
|
|
BOOL g_MultilinkEnabled;
|
|
HINSTANCE g_RasApi32 = NULL;
|
|
|
|
DWORD (* g_RnaGetDefaultAutodialConnection) (
|
|
LPBYTE lpBuf,
|
|
DWORD cb,
|
|
LPDWORD lpdwOptions
|
|
);
|
|
|
|
//
|
|
// Routines and structures for dealing with the Addresses\<entry> blob..
|
|
//
|
|
// AddrEntry serves as a header for the entire block of data in the <entry>
|
|
// blob. entries in it are offsets to the strings which follow it..in many
|
|
// cases (i.e. all of the *Off* members...)
|
|
//
|
|
typedef struct _AddrEntry {
|
|
DWORD dwVersion;
|
|
DWORD dwCountryCode;
|
|
UINT uOffArea;
|
|
UINT uOffPhone;
|
|
DWORD dwCountryID;
|
|
UINT uOffSMMCfg;
|
|
UINT uOffSMM;
|
|
UINT uOffDI;
|
|
} ADDRENTRY, *PADDRENTRY;
|
|
|
|
typedef struct _SubConnEntry {
|
|
DWORD dwSize;
|
|
DWORD dwFlags;
|
|
char szDeviceType[RAS_MaxDeviceType+1];
|
|
char szDeviceName[RAS_MaxDeviceName+1];
|
|
char szLocal[RAS_MaxPhoneNumber+1];
|
|
} SUBCONNENTRY, *PSUBCONNENTRY;
|
|
|
|
typedef struct _IPData {
|
|
DWORD dwSize;
|
|
DWORD fdwTCPIP;
|
|
DWORD dwIPAddr;
|
|
DWORD dwDNSAddr;
|
|
DWORD dwDNSAddrAlt;
|
|
DWORD dwWINSAddr;
|
|
DWORD dwWINSAddrAlt;
|
|
} IPDATA, *PIPDATA;
|
|
|
|
typedef struct _DEVICEINFO {
|
|
DWORD dwVersion;
|
|
UINT uSize;
|
|
char szDeviceName[RAS_MaxDeviceName+1];
|
|
char szDeviceType[RAS_MaxDeviceType+1];
|
|
} DEVICEINFO, *PDEVICEINFO;
|
|
|
|
typedef struct _SMMCFG {
|
|
DWORD dwSize;
|
|
DWORD fdwOptions;
|
|
DWORD fdwProtocols;
|
|
} SMMCFG, *PSMMCFG;
|
|
|
|
static BYTE NEAR PASCAL GenerateEncryptKey (LPSTR szKey)
|
|
{
|
|
BYTE bKey;
|
|
LPBYTE lpKey;
|
|
|
|
for (bKey = 0, lpKey = (LPBYTE)szKey; *lpKey != 0; lpKey++)
|
|
{
|
|
bKey += *lpKey;
|
|
};
|
|
|
|
return bKey;
|
|
}
|
|
|
|
DWORD NEAR PASCAL
|
|
EnDecryptEntry (
|
|
LPSTR szEntry,
|
|
LPBYTE lpEnt,
|
|
DWORD cb
|
|
)
|
|
{
|
|
BYTE bKey;
|
|
|
|
//
|
|
// Generate the encryption key from the entry name
|
|
//
|
|
bKey = GenerateEncryptKey(szEntry);
|
|
//
|
|
// Encrypt the address entry one byte at a time
|
|
//
|
|
for (;cb > 0; cb--, lpEnt++)
|
|
{
|
|
*lpEnt ^= bKey;
|
|
};
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Find out if current connection is the default connection for current user
|
|
//
|
|
// Whistler 417479 RAS upgrade code does not migrate the default
|
|
// internet connection setting from WinME to XP
|
|
//
|
|
BOOL
|
|
IsDefInternetCon(
|
|
IN PCTSTR szEntry
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
if (g_RnaGetDefaultAutodialConnection && szEntry)
|
|
{
|
|
DWORD dwAutodialOptions;
|
|
UCHAR szDefEntry[MAX_PATH + 1];
|
|
|
|
//
|
|
// Whistler bug: 417745 INTL:Win9x Upg: DBCS chars cause User,Domain,
|
|
// Passwrds to not be migrated for DUN
|
|
//
|
|
if (!g_RnaGetDefaultAutodialConnection(szDefEntry, MAX_PATH,
|
|
&dwAutodialOptions) && StringIMatch (szEntry, szDefEntry))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
HKEY
|
|
FindCurrentKey (
|
|
IN HKEY hkKey,
|
|
IN PCTSTR pszString,
|
|
IN PCTSTR pszPath
|
|
)
|
|
{
|
|
HKEY hkResult = NULL;
|
|
HKEY hkTemp = hkKey;
|
|
TCHAR szPath[MAX_PATH + 1];
|
|
PTSTR pszTemp = NULL;
|
|
REGKEY_ENUM e;
|
|
|
|
do
|
|
{
|
|
pszTemp = GetRegValueString (hkTemp, S_FRIENDLYNAME);
|
|
if (pszTemp && StringIMatch (pszString, pszTemp))
|
|
{
|
|
hkResult = hkTemp;
|
|
hkTemp = NULL;
|
|
break;
|
|
}
|
|
|
|
if (!EnumFirstRegKey (&e, hkTemp)) {break;}
|
|
|
|
do
|
|
{
|
|
if (pszTemp)
|
|
{
|
|
MemFree (g_hHeap, 0, pszTemp);
|
|
pszTemp = NULL;
|
|
}
|
|
|
|
if (hkResult)
|
|
{
|
|
CloseRegKey(hkResult);
|
|
hkResult = NULL;
|
|
}
|
|
|
|
sprintf(szPath, "%s\\%s", pszPath, e.SubKeyName );
|
|
hkResult = OpenRegKeyStr (szPath);
|
|
if (!hkResult) {break;}
|
|
|
|
pszTemp = GetRegValueString (hkResult, S_FRIENDLYNAME);
|
|
if (pszTemp && StringIMatch (pszString, pszTemp))
|
|
{
|
|
// Success
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
CloseRegKey(hkResult);
|
|
hkResult = NULL;
|
|
}
|
|
|
|
} while (EnumNextRegKey (&e));
|
|
|
|
} while (FALSE);
|
|
//
|
|
// Clean up
|
|
//
|
|
if (pszTemp)
|
|
{
|
|
MemFree (g_hHeap, 0, pszTemp);
|
|
}
|
|
if (hkTemp)
|
|
{
|
|
CloseRegKey(hkTemp);
|
|
}
|
|
|
|
return hkResult;
|
|
}
|
|
|
|
PTSTR
|
|
GetInfoFromFriendlyName (
|
|
IN PCTSTR pszFriendlyName,
|
|
IN BOOL bType
|
|
)
|
|
{
|
|
HKEY hkEnum = NULL;
|
|
DWORD i = 0;
|
|
TCHAR szData[MAX_PATH + 1];
|
|
TCHAR szPath[MAX_PATH + 1];
|
|
PTSTR pszTemp = NULL;
|
|
PTSTR pszReturn = NULL;
|
|
LPGUID pguidModem = (LPGUID)&GUID_DEVCLASS_MODEM;
|
|
HDEVINFO hdi;
|
|
SP_DEVINFO_DATA devInfoData = {sizeof (devInfoData), 0};
|
|
|
|
hdi = SetupDiGetClassDevs (pguidModem, NULL, NULL, DIGCF_PRESENT);
|
|
if (INVALID_HANDLE_VALUE == hdi)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
while (SetupDiEnumDeviceInfo (hdi, i++, &devInfoData))
|
|
{
|
|
if (!SetupDiGetDeviceRegistryProperty (
|
|
hdi, &devInfoData, SPDRP_FRIENDLYNAME,
|
|
NULL, (PBYTE)szData, MAX_PATH, NULL) ||
|
|
lstrcmp (szData, pszFriendlyName) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!SetupDiGetDeviceRegistryProperty (
|
|
hdi, &devInfoData, SPDRP_HARDWAREID,
|
|
NULL, (PBYTE)szData, MAX_PATH, NULL) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
sprintf(szPath, "%s\\%s", S_ENUM, szData );
|
|
hkEnum = OpenRegKeyStr (szPath);
|
|
if (!hkEnum) {break;}
|
|
|
|
hkEnum = FindCurrentKey (hkEnum, pszFriendlyName, szPath);
|
|
if (!hkEnum) {break;}
|
|
|
|
if (bType)
|
|
{
|
|
pszTemp = GetRegValueString (hkEnum, S_PARENTDEVNODE);
|
|
if (pszTemp)
|
|
{
|
|
pszReturn = PoolMemDuplicateString (g_RasPool, pszTemp);
|
|
break;
|
|
}
|
|
|
|
pszReturn = PoolMemDuplicateString (g_RasPool, szData);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pszTemp = GetRegValueString (hkEnum, S_ATTACHEDTO);
|
|
if (pszTemp)
|
|
{
|
|
pszReturn = PoolMemDuplicateString (g_RasPool, pszTemp);
|
|
break;
|
|
}
|
|
|
|
pszTemp = GetRegValueString (hkEnum, S_DRIVER);
|
|
if (pszTemp)
|
|
{
|
|
HKEY key = NULL;
|
|
PTSTR pszAttach = NULL;
|
|
|
|
sprintf(szPath, "%s\\%s", S_SERVICECLASS, pszTemp);
|
|
key = OpenRegKeyStr (szPath);
|
|
if (!key) {break;}
|
|
|
|
pszAttach = GetRegValueString (key, S_ATTACHEDTO);
|
|
if (!pszAttach)
|
|
{
|
|
CloseRegKey(key);
|
|
break;
|
|
}
|
|
|
|
pszReturn = PoolMemDuplicateString (g_RasPool, pszAttach);
|
|
MemFree (g_hHeap, 0, pszAttach);
|
|
CloseRegKey(key);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Clean up
|
|
//
|
|
if (bType && pszReturn)
|
|
{
|
|
BOOL bFisrt = FALSE;
|
|
PTSTR p;
|
|
|
|
for (p = pszReturn; '\0' != *p; p++ )
|
|
{
|
|
if (*p != '\\') {continue;}
|
|
|
|
if (!bFisrt)
|
|
{
|
|
bFisrt = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Remove rest of PnpId string, not needed
|
|
//
|
|
*p = '\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pszTemp)
|
|
{
|
|
MemFree (g_hHeap, 0, pszTemp);
|
|
}
|
|
|
|
if (hkEnum)
|
|
{
|
|
CloseRegKey(hkEnum);
|
|
}
|
|
|
|
if (INVALID_HANDLE_VALUE != hdi)
|
|
{
|
|
SetupDiDestroyDeviceInfoList (hdi);
|
|
}
|
|
|
|
return pszReturn;
|
|
}
|
|
|
|
PTSTR
|
|
GetComPort (
|
|
IN PCTSTR DriverDesc
|
|
)
|
|
{
|
|
PTSTR rPort = NULL;
|
|
|
|
rPort = GetInfoFromFriendlyName(DriverDesc, FALSE);
|
|
|
|
if (!rPort)
|
|
{
|
|
rPort = S_EMPTY;
|
|
DEBUGMSG ((DBG_WARNING, "Could not find com port for device %s."));
|
|
}
|
|
|
|
return rPort;
|
|
}
|
|
|
|
VOID
|
|
pInitLibs (
|
|
VOID
|
|
)
|
|
{
|
|
do {
|
|
//
|
|
// Load in rasapi32.dll, not fatal if we fail
|
|
//
|
|
// Whistler 417479 RAS upgrade code does not migrate the default
|
|
// internet connection setting from WinME to XP
|
|
//
|
|
g_RasApi32 = LoadLibrary(S_RASAPI32LIB);
|
|
if (!g_RasApi32) {
|
|
|
|
g_RnaGetDefaultAutodialConnection = NULL;
|
|
DEBUGMSG((S_DBG_RAS,"Migrate Ras: could not load library %s. Default Internet Connection will not be migrated.",
|
|
S_RASAPI32LIB));
|
|
}
|
|
//
|
|
// RASAPI32 was loaded..now, get the relevant apis, not fatal if we fail
|
|
//
|
|
else
|
|
{
|
|
(FARPROC) g_RnaGetDefaultAutodialConnection = GetProcAddress(
|
|
g_RasApi32,
|
|
S_RNAGETDEFAUTODIALCON
|
|
);
|
|
if (!g_RnaGetDefaultAutodialConnection) {
|
|
|
|
DEBUGMSG((S_DBG_RAS,"Migrate Ras: could not load Procedure %s. Default Internet Connection will not be migrated.",
|
|
S_RNAGETDEFAUTODIALCON));
|
|
}
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
pCleanUpLibs (
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Whistler 417479 RAS upgrade code does not migrate the default
|
|
// internet connection setting from WinME to XP
|
|
//
|
|
if (g_RasApi32) {
|
|
FreeLibrary(g_RasApi32);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
pSaveConnectionDataToMemDb (
|
|
IN PCTSTR User,
|
|
IN PCTSTR Entry,
|
|
IN PCTSTR ValueName,
|
|
IN DWORD ValueType,
|
|
IN PBYTE Value
|
|
)
|
|
{
|
|
DWORD offset;
|
|
TCHAR key[MEMDB_MAX];
|
|
|
|
MemDbBuildKey (key, MEMDB_CATEGORY_RAS_INFO, User, Entry, ValueName);
|
|
|
|
switch (ValueType) {
|
|
|
|
case REG_SZ:
|
|
case REG_MULTI_SZ:
|
|
case REG_EXPAND_SZ:
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "String Data - %s = %s", ValueName,
|
|
(PCTSTR) Value));
|
|
|
|
if (!MemDbSetValueEx (MEMDB_CATEGORY_RAS_DATA, (PCTSTR) Value,
|
|
NULL, NULL, 0, &offset)) {
|
|
DEBUGMSG ((DBG_ERROR, "Error saving ras data into memdb."));
|
|
}
|
|
|
|
if (!MemDbSetValueAndFlags (key, offset, (WORD) REG_SZ, 0)) {
|
|
DEBUGMSG ((DBG_ERROR, "Error saving ras data into memdb."));
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case REG_DWORD:
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "DWORD Data - %s = %u", ValueName,
|
|
(DWORD) Value));
|
|
|
|
if (!MemDbSetValueAndFlags (key, (DWORD)Value, (WORD)ValueType,0)){
|
|
DEBUGMSG ((DBG_ERROR, "Error saving ras data into memdb."));
|
|
}
|
|
|
|
break;
|
|
|
|
case REG_BINARY:
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "Binary data for %s.", ValueName));
|
|
|
|
if (StringIMatch (S_IPINFO, ValueName)) {
|
|
//
|
|
// Save IP address information.
|
|
//
|
|
pSaveConnectionDataToMemDb (User, Entry, S_IP_FTCPIP,
|
|
REG_DWORD, (PBYTE) ((PIPDATA) Value)->fdwTCPIP);
|
|
pSaveConnectionDataToMemDb (User, Entry, S_IP_IPADDR,
|
|
REG_DWORD, (PBYTE) ((PIPDATA) Value)->dwIPAddr);
|
|
pSaveConnectionDataToMemDb (User, Entry, S_IP_DNSADDR,
|
|
REG_DWORD, (PBYTE) ((PIPDATA) Value)->dwDNSAddr);
|
|
pSaveConnectionDataToMemDb (User, Entry, S_IP_DNSADDR2,
|
|
REG_DWORD, (PBYTE) ((PIPDATA) Value)->dwDNSAddrAlt);
|
|
pSaveConnectionDataToMemDb (User, Entry, S_IP_WINSADDR,
|
|
REG_DWORD, (PBYTE) ((PIPDATA) Value)->dwWINSAddr);
|
|
pSaveConnectionDataToMemDb (User, Entry, S_IP_WINSADDR2,
|
|
REG_DWORD, (PBYTE) ((PIPDATA) Value)->dwWINSAddrAlt);
|
|
|
|
} else if (StringIMatch (S_TERMINAL, ValueName)) {
|
|
//
|
|
// save information on the showcmd state. This will tell us how
|
|
// to set the ui display.
|
|
//
|
|
pSaveConnectionDataToMemDb (User, Entry, ValueName, REG_DWORD,
|
|
(PBYTE) ((PWINDOWPLACEMENT) Value)->showCmd);
|
|
|
|
} else if (StringIMatch (S_MODE, ValueName)) {
|
|
//
|
|
// This value tells what to do with scripting.
|
|
//
|
|
pSaveConnectionDataToMemDb (User, Entry, ValueName, REG_DWORD,
|
|
(PBYTE) *((PDWORD) Value));
|
|
|
|
} else if (StringIMatch (S_MULTILINK, ValueName)) {
|
|
//
|
|
// Save wether or not multilink is enabled.
|
|
//
|
|
pSaveConnectionDataToMemDb (User, Entry, ValueName, REG_DWORD,
|
|
(PBYTE) *((PDWORD) Value));
|
|
//
|
|
// Whistler bug: 417745 INTL:Win9x Upg: DBCS chars cause User,
|
|
// Domain, Passwrds to not be migrated for DUN
|
|
//
|
|
} else if (StringIMatch (S_PBE_REDIALATTEMPTS, ValueName)) {
|
|
//
|
|
// Save the number of redial attempts
|
|
//
|
|
pSaveConnectionDataToMemDb (User, Entry, S_REDIAL_TRY, REG_DWORD,
|
|
(PBYTE) *((PDWORD) Value));
|
|
//
|
|
// Whistler bug: 417745 INTL:Win9x Upg: DBCS chars cause User,
|
|
// Domain, Passwrds to not be migrated for DUN
|
|
//
|
|
} else if (StringIMatch (S_REDIAL_WAIT, ValueName)) {
|
|
//
|
|
// Save the number of seconds to wait for redial
|
|
//
|
|
pSaveConnectionDataToMemDb (User, Entry, ValueName, REG_DWORD,
|
|
(PBYTE) *((PDWORD) Value));
|
|
|
|
} ELSE_DEBUGMSG ((DBG_WARNING, "Don't know how to handle binary data %s. It will be ignored.",
|
|
ValueName));
|
|
|
|
break;
|
|
|
|
default:
|
|
DEBUGMSG ((DBG_WHOOPS, "Unknown type of registry data found in RAS settings. %s",
|
|
ValueName));
|
|
break;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
pGetRasEntrySettings (
|
|
IN PUSERENUM EnumPtr,
|
|
IN HKEY Key,
|
|
IN PCTSTR EntryName
|
|
)
|
|
{
|
|
REGVALUE_ENUM e;
|
|
PBYTE curData = NULL;
|
|
BOOL rSuccess = TRUE;
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "---Processing %s's entry settings: %s---",
|
|
EnumPtr->FixedUserName, EntryName));
|
|
|
|
if (EnumFirstRegValue (&e, Key)) {
|
|
|
|
do {
|
|
//
|
|
// Get the data for this entry.
|
|
//
|
|
curData = GetRegValueData (Key, e.ValueName);
|
|
|
|
if (curData) {
|
|
//
|
|
// Whistler bug: 417745 INTL:Win9x Upg: DBCS chars cause User,
|
|
// Domain, Passwrds to not be migrated for DUN
|
|
//
|
|
if (StringIMatch (S_MULTILINK, e.ValueName) &&
|
|
!g_MultilinkEnabled) {
|
|
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, e.ValueName, REG_DWORD, 0);
|
|
}
|
|
else {
|
|
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, e.ValueName, e.Type,
|
|
e.Type == REG_DWORD ? (PBYTE) (*((PDWORD)curData)) :
|
|
curData);
|
|
}
|
|
|
|
MemFree (g_hHeap, 0, curData);
|
|
}
|
|
|
|
} while (EnumNextRegValue (&e));
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
BOOL
|
|
pGetRasEntryAddressInfo (
|
|
IN PUSERENUM EnumPtr,
|
|
IN HKEY Key,
|
|
IN PCTSTR EntryName
|
|
)
|
|
{
|
|
BOOL rSuccess = TRUE;
|
|
HKEY subEntriesKey = NULL;
|
|
UINT count = 0, type = 0, sequencer = 0;
|
|
PBYTE data = NULL;
|
|
PTSTR subEntriesKeyStr = NULL;
|
|
TCHAR buffer[MAX_TCHAR_PATH];
|
|
PCTSTR group;
|
|
PSMMCFG smmCfg = NULL;
|
|
PADDRENTRY entry = NULL;
|
|
PDEVICEINFO devInfo = NULL;
|
|
REGVALUE_ENUM e, eSubEntries;
|
|
PSUBCONNENTRY subEntry = NULL;
|
|
PMODEMDEVINFO modemInfo;
|
|
|
|
//
|
|
// First we have to get the real entry name. It must match exactly even
|
|
// case. Unfortunately, it isn't neccessarily a given that the case between
|
|
// HKR\RemoteAccess\Profiles\<Foo> and HKR\RemoteAccess\Addresses\[Foo] is
|
|
// the same. The registry apis will of course work fine because they work
|
|
// case insensitively. However, I will be unable to decrypt the value if I
|
|
// use the wrong name.
|
|
//
|
|
if (EnumFirstRegValue (&e, Key)) {
|
|
|
|
do {
|
|
|
|
if (StringIMatch (e.ValueName, EntryName)) {
|
|
//
|
|
// Found the correct entry. Use it.
|
|
//
|
|
data = GetRegValueBinary (Key, e.ValueName);
|
|
|
|
if (data) {
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "-----Processing entry: %s-----",
|
|
e.ValueName));
|
|
//
|
|
// Whistler 417479 RAS upgrade code does not migrate the default
|
|
// internet connection setting from WinME to XP
|
|
//
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_DEFINTERNETCON,
|
|
REG_DWORD, (PBYTE) IsDefInternetCon(EntryName));
|
|
|
|
entry = (PADDRENTRY) data;
|
|
DECRYPTENTRY(e.ValueName, entry, e.DataSize);
|
|
|
|
smmCfg = PAESMMCFG(entry);
|
|
devInfo = PAEDI(entry);
|
|
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_PHONE_NUMBER,
|
|
REG_SZ, (PBYTE) PAEPHONE(entry));
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_AREA_CODE, REG_SZ,
|
|
(PBYTE) PAEAREA(entry));
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_SMM, REG_SZ,
|
|
(PBYTE) PAESMM(entry));
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_COUNTRY_CODE,
|
|
REG_DWORD, (PBYTE) entry->dwCountryCode);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_COUNTRY_ID,
|
|
REG_DWORD, (PBYTE) entry->dwCountryID);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_DEVICE_NAME,
|
|
REG_SZ, (PBYTE) devInfo->szDeviceName);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_DEVICE_TYPE,
|
|
REG_SZ, (PBYTE) devInfo->szDeviceType);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_PROTOCOLS,
|
|
REG_DWORD, (PBYTE) smmCfg->fdwProtocols);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, S_SMM_OPTIONS,
|
|
REG_DWORD, (PBYTE) smmCfg->fdwOptions);
|
|
//
|
|
// Save device information away.
|
|
//
|
|
if (StringIMatch (devInfo->szDeviceType, S_MODEM)) {
|
|
|
|
PTSTR pszPnpId = NULL;
|
|
|
|
pszPnpId = GetInfoFromFriendlyName(
|
|
devInfo->szDeviceName, TRUE);
|
|
if (pszPnpId)
|
|
{
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName,
|
|
S_DEVICE_ID, REG_SZ, (PBYTE) pszPnpId);
|
|
}
|
|
|
|
modemInfo = (PMODEMDEVINFO) (devInfo->szDeviceType +
|
|
RAS_MaxDeviceType + 3);
|
|
|
|
if (modemInfo->Size >= sizeof (MODEMDEVINFO)) {
|
|
DEBUGMSG_IF ((modemInfo->Size >
|
|
sizeof (MODEMDEVINFO), S_DBG_RAS,
|
|
"Structure size larger than our known size."));
|
|
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, S_MODEM_UI_OPTIONS, REG_DWORD,
|
|
(PBYTE) modemInfo->ModemUiOptions);
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, S_MODEM_SPEED, REG_DWORD,
|
|
(PBYTE) modemInfo->ConnectionSpeed);
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, S_MODEM_SPEAKER_VOLUME, REG_DWORD,
|
|
(PBYTE) modemInfo->SpeakerVolume);
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, S_MODEM_IDLE_DISCONNECT_SECONDS,
|
|
REG_DWORD,
|
|
(PBYTE) modemInfo->dwInactivityTimeout);
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, S_MODEM_CANCEL_SECONDS, REG_DWORD,
|
|
(PBYTE) modemInfo->dwCallSetupFailTimer);
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, S_MODEM_CFG_OPTIONS, REG_DWORD,
|
|
(PBYTE) modemInfo->ConfigOptions);
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, S_MODEM_COM_PORT, REG_SZ,
|
|
(PBYTE) GetComPort (devInfo->szDeviceName));
|
|
}
|
|
ELSE_DEBUGMSG ((DBG_WHOOPS, "No modem configuration data saved. Size smaller than known structure. Investigate."));
|
|
}
|
|
//
|
|
// If SMM is not SLIP, CSLIP or PPP, we need to add a
|
|
// message to the upgrade report.
|
|
//
|
|
if (!StringIMatch (PAESMM(entry), S_SLIP)&&
|
|
!StringIMatch (PAESMM(entry), S_PPP) &&
|
|
!StringIMatch (PAESMM(entry), S_CSLIP)) {
|
|
//
|
|
// Add message for this connection entry.
|
|
//
|
|
group = BuildMessageGroup (
|
|
MSG_LOSTSETTINGS_ROOT,
|
|
MSG_CONNECTION_BADPROTOCOL_SUBGROUP,
|
|
EntryName
|
|
);
|
|
|
|
if (group) {
|
|
|
|
MsgMgr_ObjectMsg_Add (
|
|
EntryName,
|
|
group,
|
|
S_EMPTY
|
|
);
|
|
|
|
FreeText (group);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Check to see if there are any sub-entries for this
|
|
// connection (MULTILINK settings..)
|
|
//
|
|
// Luckily, we don't have to do the same enumeration of these
|
|
// entries as we had to above to get around the case
|
|
// sensitivity bug. the 9x code uses the address key name above
|
|
// for encryption/decryption.
|
|
//
|
|
sequencer = 1;
|
|
g_MultilinkEnabled = FALSE;
|
|
|
|
if (data && !StringIMatch (PAESMM(entry), S_PPP))
|
|
{
|
|
DEBUGMSG ((S_DBG_RAS, "Not using PPP, disabling Multi-Link"));
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName,
|
|
EntryName, S_DEVICECOUNT, REG_DWORD,
|
|
(PBYTE) sequencer);
|
|
|
|
MemFree (g_hHeap, 0, data);
|
|
data = NULL;
|
|
break;
|
|
}
|
|
|
|
subEntriesKeyStr = JoinPaths (S_SUBENTRIES, e.ValueName);
|
|
if (subEntriesKeyStr)
|
|
{
|
|
subEntriesKey = OpenRegKey (Key, subEntriesKeyStr);
|
|
FreePathString (subEntriesKeyStr);
|
|
}
|
|
|
|
if (subEntriesKey) {
|
|
DEBUGMSG ((S_DBG_RAS, "Multi-Link Subentries found for entry %s. Processing.",
|
|
e.ValueName));
|
|
g_MultilinkEnabled = TRUE;
|
|
|
|
if (EnumFirstRegValue (&eSubEntries, subEntriesKey)) {
|
|
|
|
do {
|
|
|
|
data = GetRegValueBinary (subEntriesKey,
|
|
eSubEntries.ValueName);
|
|
|
|
if (data) {
|
|
PTSTR pszPnpId = NULL;
|
|
|
|
subEntry = (PSUBCONNENTRY) data;
|
|
DECRYPTENTRY (e.ValueName, subEntry,
|
|
eSubEntries.DataSize);
|
|
|
|
wsprintf (buffer, "ml%d%s",sequencer,
|
|
S_DEVICE_TYPE);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, buffer,
|
|
REG_SZ, (PBYTE) subEntry->szDeviceType);
|
|
|
|
wsprintf (buffer, "ml%d%s",sequencer,
|
|
S_DEVICE_NAME);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, buffer,
|
|
REG_SZ, (PBYTE) subEntry->szDeviceName);
|
|
|
|
pszPnpId = GetInfoFromFriendlyName(
|
|
subEntry->szDeviceName, TRUE);
|
|
if (pszPnpId)
|
|
{
|
|
wsprintf (buffer, "ml%d%s",sequencer,
|
|
S_DEVICE_ID);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName,
|
|
buffer, REG_SZ, (PBYTE) pszPnpId);
|
|
}
|
|
|
|
wsprintf (buffer, "ml%d%s",sequencer,
|
|
S_PHONE_NUMBER);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, buffer,
|
|
REG_SZ, (PBYTE) subEntry->szLocal);
|
|
|
|
wsprintf (buffer, "ml%d%s",sequencer,
|
|
S_MODEM_COM_PORT);
|
|
pSaveConnectionDataToMemDb (
|
|
EnumPtr->FixedUserName, EntryName, buffer,
|
|
REG_SZ, (PBYTE)
|
|
GetComPort (subEntry->szDeviceName));
|
|
|
|
MemFree (g_hHeap, 0, data);
|
|
data = NULL;
|
|
}
|
|
|
|
sequencer++;
|
|
|
|
} while (EnumNextRegValue (&eSubEntries));
|
|
}
|
|
|
|
CloseRegKey (subEntriesKey);
|
|
}
|
|
//
|
|
// Save away the number of devices associated with this
|
|
// connection
|
|
//
|
|
pSaveConnectionDataToMemDb (EnumPtr->FixedUserName, EntryName,
|
|
S_DEVICECOUNT, REG_DWORD, (PBYTE) sequencer);
|
|
//
|
|
// We're done. Break out of the enumeration.
|
|
//
|
|
break;
|
|
}
|
|
|
|
} while (EnumNextRegValue (&e));
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
BOOL
|
|
pGetPerConnectionSettings (
|
|
IN PUSERENUM EnumPtr
|
|
)
|
|
{
|
|
HKEY profileKey;
|
|
HKEY entryKey = NULL;
|
|
HKEY addressKey = NULL;
|
|
BOOL rSuccess = TRUE;
|
|
REGVALUE_ENUM e;
|
|
|
|
DEBUGMSG((S_DBG_RAS, "Gathering per-connection RAS Setting Information"));
|
|
|
|
//
|
|
// Open needed registry keys.
|
|
//
|
|
profileKey = OpenRegKey (EnumPtr->UserRegKey, S_PROFILE_KEY);
|
|
addressKey = OpenRegKey (EnumPtr->UserRegKey, S_ADDRESSES_KEY);
|
|
|
|
if (addressKey) {
|
|
//
|
|
// Enumerate each entry for this user.
|
|
//
|
|
if (EnumFirstRegValue (&e, addressKey)) {
|
|
do {
|
|
//
|
|
// Get base connection info -- stored as binary blob under
|
|
// address key. All connections will have this info -- It
|
|
// contains such things as the phone number, area code, dialing
|
|
// rules, etc.. It does not matter wether the connection has
|
|
// been used or not.
|
|
//
|
|
rSuccess &= pGetRasEntryAddressInfo (EnumPtr,
|
|
addressKey, e.ValueName );
|
|
|
|
if (profileKey) {
|
|
//
|
|
// Under the profile key are negotiated options for the
|
|
// connection. This key will only exist if the entry has
|
|
// actually been connected to by the user.
|
|
//
|
|
entryKey = OpenRegKey (profileKey, e.ValueName);
|
|
|
|
if (entryKey) {
|
|
|
|
rSuccess &= pGetRasEntrySettings ( EnumPtr, entryKey,
|
|
e.ValueName );
|
|
CloseRegKey (entryKey);
|
|
}
|
|
}
|
|
|
|
} while (EnumNextRegValue (&e));
|
|
}
|
|
}
|
|
ELSE_DEBUGMSG ((DBG_WARNING, "pGetPerConnectionSettings: Unable to access needed registry info for user %s.",
|
|
EnumPtr->FixedUserName));
|
|
//
|
|
// Clean up resources.
|
|
//
|
|
if (addressKey) {
|
|
CloseRegKey (addressKey);
|
|
}
|
|
|
|
if (profileKey) {
|
|
CloseRegKey (profileKey);
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
BOOL
|
|
pGetPerUserSettings (
|
|
IN PUSERENUM EnumPtr
|
|
)
|
|
{
|
|
HKEY settingsKey;
|
|
PDWORD data;
|
|
BOOL rSuccess = TRUE;
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "Gathering per-user RAS data for %s.",
|
|
EnumPtr->UserName));
|
|
|
|
settingsKey = OpenRegKey (EnumPtr->UserRegKey, S_REMOTE_ACCESS_KEY);
|
|
|
|
if (settingsKey) {
|
|
//
|
|
// Get UI settings.
|
|
//
|
|
data = (PDWORD) GetRegValueBinary (settingsKey, S_DIALUI);
|
|
//
|
|
// Save Dial User Interface info into memdb for this user.
|
|
//
|
|
if (data) {
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "DWORD Data - %s = %u", S_DIALUI, *data));
|
|
|
|
rSuccess &= MemDbSetValueEx (
|
|
MEMDB_CATEGORY_RAS_INFO,
|
|
MEMDB_FIELD_USER_SETTINGS,
|
|
EnumPtr->FixedUserName,
|
|
S_DIALUI,
|
|
*data,
|
|
NULL
|
|
);
|
|
|
|
MemFree (g_hHeap, 0, data);
|
|
}
|
|
ELSE_DEBUGMSG ((S_DBG_RAS, "No user UI settings found for %s.",
|
|
EnumPtr->UserName));
|
|
//
|
|
// Get Redial information.
|
|
//
|
|
data = (PDWORD) GetRegValueBinary (settingsKey, S_ENABLE_REDIAL);
|
|
|
|
if (data) {
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "DWORD Data - %s = %u", S_ENABLE_REDIAL,
|
|
*data));
|
|
|
|
rSuccess &= MemDbSetValueEx (
|
|
MEMDB_CATEGORY_RAS_INFO,
|
|
MEMDB_FIELD_USER_SETTINGS,
|
|
EnumPtr->FixedUserName,
|
|
S_ENABLE_REDIAL,
|
|
*data,
|
|
NULL
|
|
);
|
|
|
|
MemFree (g_hHeap, 0, data);
|
|
}
|
|
ELSE_DEBUGMSG ((S_DBG_RAS, "No user redial information found for %s.",
|
|
EnumPtr->UserName));
|
|
|
|
data = (PDWORD) GetRegValueBinary (settingsKey, S_REDIAL_TRY);
|
|
|
|
if (data) {
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "DWORD Data - %s = %u", S_REDIAL_TRY,
|
|
*data));
|
|
|
|
rSuccess &= MemDbSetValueEx (
|
|
MEMDB_CATEGORY_RAS_INFO,
|
|
MEMDB_FIELD_USER_SETTINGS,
|
|
EnumPtr->FixedUserName,
|
|
S_REDIAL_TRY,
|
|
*data,
|
|
NULL
|
|
);
|
|
|
|
MemFree (g_hHeap, 0, data);
|
|
}
|
|
ELSE_DEBUGMSG ((S_DBG_RAS, "No user redial information found for %s.",
|
|
EnumPtr->UserName));
|
|
|
|
data = (PDWORD) GetRegValueBinary (settingsKey, S_REDIAL_WAIT);
|
|
|
|
if (data) {
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "DWORD Data - %s = %u", S_REDIAL_WAIT,
|
|
HIWORD(*data) * 60 + LOWORD(*data)));
|
|
|
|
MemDbSetValueEx (
|
|
MEMDB_CATEGORY_RAS_INFO,
|
|
MEMDB_FIELD_USER_SETTINGS,
|
|
EnumPtr->FixedUserName,
|
|
S_REDIAL_WAIT,
|
|
HIWORD(*data) * 60 + LOWORD(*data),
|
|
NULL
|
|
);
|
|
|
|
MemFree (g_hHeap, 0, data);
|
|
}
|
|
ELSE_DEBUGMSG ((S_DBG_RAS, "No user redial information found for %s.",
|
|
EnumPtr->UserName));
|
|
//
|
|
// Get implicit connection information. (Controls wether connection ui
|
|
// should be displayed or not)
|
|
//
|
|
data = (PDWORD) GetRegValueBinary (settingsKey, S_ENABLE_IMPLICIT);
|
|
|
|
if (data) {
|
|
|
|
DEBUGMSG ((S_DBG_RAS, "DWORD Data - %s = %u", S_ENABLE_IMPLICIT,
|
|
*data));
|
|
|
|
MemDbSetValueEx (
|
|
MEMDB_CATEGORY_RAS_INFO,
|
|
MEMDB_FIELD_USER_SETTINGS,
|
|
EnumPtr->FixedUserName,
|
|
S_ENABLE_IMPLICIT,
|
|
*data,
|
|
NULL
|
|
);
|
|
|
|
MemFree(g_hHeap,0,data);
|
|
}
|
|
ELSE_DEBUGMSG ((S_DBG_RAS, "No user implicit connection information found for %s.",
|
|
EnumPtr->UserName));
|
|
|
|
CloseRegKey(settingsKey);
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|
|
|
|
DWORD
|
|
ProcessRasSettings (
|
|
IN DWORD Request,
|
|
IN PUSERENUM EnumPtr
|
|
)
|
|
{
|
|
DWORD rc = ERROR_SUCCESS;
|
|
|
|
switch (Request) {
|
|
|
|
case REQUEST_QUERYTICKS:
|
|
|
|
return TICKS_RAS_PREPARE_REPORT;
|
|
|
|
case REQUEST_BEGINUSERPROCESSING:
|
|
//
|
|
// We are about to be called for each user. Do necessary
|
|
// initialization.
|
|
//
|
|
// Initialize our pool and get information from libraries.
|
|
//
|
|
g_RasPool = PoolMemInitNamedPool (TEXT("RAS - Win9x Side"));
|
|
MYASSERT( g_RasPool);
|
|
|
|
pInitLibs();
|
|
g_RasInstalled = IsRasInstalled();
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
case REQUEST_RUN:
|
|
//
|
|
// Gather RAS information for this user.
|
|
//
|
|
if (g_RasInstalled && EnumPtr -> AccountType & NAMED_USER) {
|
|
|
|
__try {
|
|
|
|
pGetPerUserSettings (EnumPtr);
|
|
pGetPerConnectionSettings (EnumPtr);
|
|
}
|
|
__except (TRUE) {
|
|
DEBUGMSG ((DBG_WHOOPS, "Caught an exception while processing ras settings."));
|
|
}
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
case REQUEST_ENDUSERPROCESSING:
|
|
//
|
|
// Clean up our resources.
|
|
//
|
|
pCleanUpLibs();
|
|
PoolMemDestroyPool(g_RasPool);
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
default:
|
|
|
|
DEBUGMSG ((DBG_ERROR, "Bad parameter in Ras_PrepareReport"));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
IsRasInstalled (
|
|
void
|
|
)
|
|
{
|
|
HKEY testKey = NULL;
|
|
BOOL rf = FALSE;
|
|
|
|
testKey = OpenRegKeyStr(S_SERVICEREMOTEACCESS);
|
|
|
|
if (testKey) {
|
|
//
|
|
// Open key succeeded. Assume RAS is installed.
|
|
//
|
|
rf = TRUE;
|
|
CloseRegKey(testKey);
|
|
}
|
|
|
|
return rf;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
Ras_Entry (
|
|
IN HINSTANCE hinstDLL,
|
|
IN DWORD dwReason,
|
|
IN LPVOID lpv
|
|
)
|
|
{
|
|
BOOL rSuccess = TRUE;
|
|
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
//
|
|
// Clean up resources that we used.
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
return rSuccess;
|
|
}
|