/*++ 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\ blob.. // // AddrEntry serves as a header for the entire block of data in the // 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\ 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; }