/**************************************************************************** Copyright (c) 1998-1999 Microsoft Corporation Module Name: tregupr2.c Abstract: Upgrades the telephony registry settings to the post NT5b2 format Author: radus - 09/11/98 Notes: stolen from \Nt\Private\tapi\dev\apps\tapiupr\tapiupr.c Rev History: ****************************************************************************/ #define STRICT #include #include #include #include // from the old version of loc_comn.h #define MAXLEN_AREACODE 16 #define OLDFLAG_LOCATION_ALWAYSINCLUDEAREACODE 0x00000008 // #include "tregupr2.h" #include "debug.h" #define BACKUP_OLD_KEYS #define BACKUP_FILE_LOCATIONS _T("REGLOCS.OLD") #define BACKUP_FILE_USER_LOCATIONS _T("REGULOCS.OLD") #define BACKUP_FILE_CARDS _T("REGCARDS.OLD") #define AREACODERULE_INCLUDEALLPREFIXES 0x00000001 #define AREACODERULE_DIALAREACODE 0x00000002 #define AREACODERULE_DIALNUMBERTODIAL 0x00000004 #define US_COUNTRY_CODE(x) ((x) == 1 || \ (x >= 100 && x < 200)) #define MAXLEN_NUMBER_LEN 12 #define MAXLEN_RULE 128 #define MAXLEN_ACCESS_NUMBER 128 #define MAXLEN_PIN 128 #define TEMPORARY_ID_FLAG 0x80000000 #define PRIVATE static PRIVATE DWORD ConvertOneLocation( HKEY hLocation); PRIVATE DWORD CreateAreaCodeRule( HKEY hParent, int iRuleNumber, LPCTSTR pszAreaCodeToCall, LPCTSTR pszNumberToDial, LPBYTE pbPrefixes, DWORD dwPrefixesLength, DWORD dwFlags ); PRIVATE DWORD ConvertOneCard(HKEY hCard, DWORD); PRIVATE DWORD ConvertPIN(HKEY hCard, DWORD); PRIVATE BOOL IsTelephonyDigit(TCHAR ); PRIVATE DWORD SplitCallingCardRule(HKEY hCard, LPCTSTR pszRuleName, LPCTSTR pszAccessNumberName); PRIVATE DWORD RegRenameKey( HKEY hParentKey, LPCTSTR pszOldName, LPCTSTR pszNewName); PRIVATE DWORD RegCopyKeyRecursive(HKEY hSrcParentKey, LPCTSTR pszSrcName, HKEY hDestParentKey, LPCTSTR pszDestName); #ifdef BACKUP_OLD_KEYS #ifdef WINNT PRIVATE BOOL EnablePrivilege( PTSTR PrivilegeName, BOOL Enable, BOOL *Old ); #endif // WINNT PRIVATE BOOL SaveKey( HKEY hKey, LPCTSTR pszFileName ); #endif // BACKUP_OLD_KEYS PRIVATE const TCHAR gszName[] = _T("Name"); PRIVATE const TCHAR gszID[] = _T("ID"); PRIVATE const TCHAR gszAreaCode[] = _T("AreaCode"); PRIVATE const TCHAR gszAreaCodeRules[] = _T("AreaCodeRules"); PRIVATE const TCHAR gszCountry[] = _T("Country"); PRIVATE const TCHAR gszFlags[] = _T("Flags"); PRIVATE const TCHAR gszDisableCallWaiting[] = _T("DisableCallWaiting"); PRIVATE const TCHAR gszTollList[] = _T("TollList"); PRIVATE const TCHAR gszNoPrefAC[] = _T("NoPrefAC"); PRIVATE const TCHAR gszPrefixes[] = _T("Prefixes"); PRIVATE const TCHAR gszRules[] = _T("Rules"); PRIVATE const TCHAR gszRule[] = _T("Rule"); PRIVATE const TCHAR gszAreaCodeToCall[] = _T("AreaCodeToCall"); PRIVATE const TCHAR gszNumberToDial[] = _T("NumberToDial"); PRIVATE const TCHAR gszCard[] = _T("Card"); PRIVATE const TCHAR gszCards[] = _T("Cards"); PRIVATE const TCHAR gszLocalRule[] = _T("LocalRule"); PRIVATE const TCHAR gszLDRule[] = _T("LDRule"); PRIVATE const TCHAR gszInternationalRule[] = _T("InternationalRule"); PRIVATE const TCHAR gszLocalAccessNumber[] = _T("LocalAccessNumber"); PRIVATE const TCHAR gszLDAccessNumber[] = _T("LDAccessNumber"); PRIVATE const TCHAR gszInternationalAccessNumber[] = _T("InternationalAccessNumber"); PRIVATE const TCHAR gszAccountNumber[] = _T("AccountNumber"); PRIVATE const WCHAR gwszPIN[] = L"PIN"; PRIVATE const TCHAR gszNumEntries[] = _T("NumEntries"); PRIVATE const TCHAR gszEmpty[] = _T(""); PRIVATE const TCHAR gszMultiEmpty[] = _T("\0"); PRIVATE const TCHAR gszLocations[] = _T("Locations"); PRIVATE const TCHAR gszLocation[] = _T("Location"); PRIVATE const TCHAR gszLocationsPath[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations"); PRIVATE const TCHAR gszCardsPath[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Cards"); PRIVATE const TCHAR gszUSLDSpecifier[] = _T("1"); PRIVATE const TCHAR gszLocationListVersion[] = _T("LocationListVersion"); PRIVATE const TCHAR gszCardListVersion[] = _T("CardListVersion"); PRIVATE const TCHAR gszKeyRenameHistory[] = _T("KeyRenameHistory"); #pragma check_stack ( off ) //*************************************************************************** //*************************************************************************** //*************************************************************************** // // ConvertLocations - convert the telephony locations to the new format. // see nt\private\tapi\dev\docs\dialrules.doc // DWORD ConvertLocations(void) { TCHAR Location[sizeof(gszLocation)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN]; TCHAR NewLocation[sizeof(gszLocation)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN]; DWORD dwError = ERROR_SUCCESS; HKEY hLocations = NULL; HKEY hLocation = NULL; DWORD dwNumEntries; DWORD dwCount; DWORD dwRenameEntryCount; DWORD dwCountPhase1; DWORD dwLength; DWORD dwType; DWORD dwLocationID; DWORD dwLocationIDTmp; DWORD dwValue; PDWORD pdwRenameList = NULL; PDWORD pdwRenameEntry; PDWORD pdwRenameEntryPhase1; #ifdef BACKUP_OLD_KEYS TCHAR szPath[MAX_PATH+1]; #endif DBGOUT((9, "ConvertLocations - Enter")); dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, gszLocationsPath, 0, KEY_READ | KEY_WRITE, &hLocations ); if(dwError == ERROR_FILE_NOT_FOUND) { DBGOUT((1, "Locations key not present, so there's nothing to convert")); //Nothing to convert return ERROR_SUCCESS; } EXIT_IF_DWERROR(); // Version check if(!IsLocationListInOldFormat(hLocations)) { //Nothing to convert DBGOUT((1, "Locations key is already in the new format")); RegCloseKey(hLocations); return ERROR_SUCCESS; } #ifdef BACKUP_OLD_KEYS // Try to save the old key dwError = GetWindowsDirectory(szPath, MAX_PATH - 12); // a 8+3 name if(dwError) { if(szPath[3] != _T('\0')) lstrcat(szPath, _T("\\")); lstrcat(szPath, BACKUP_FILE_LOCATIONS); SaveKey(hLocations, szPath); } else DBGOUT((1, "Cannot get windows directory (?!?)")); dwError = ERROR_SUCCESS; #endif // Read number of entries dwLength = sizeof(dwNumEntries); dwError = RegQueryValueEx( hLocations, gszNumEntries, NULL, &dwType, (BYTE *)&dwNumEntries, &dwLength ); if(dwError==ERROR_SUCCESS && dwType != REG_DWORD) { dwError = ERROR_INVALID_DATA; assert(FALSE); } // The value could be missing in an empty key if(dwError != ERROR_SUCCESS) dwNumEntries = 0; // Alloc a rename list for the worst case (all key to be renamed using temporary IDs) if(dwNumEntries>0) { pdwRenameList = (PDWORD)GlobalAlloc(GPTR, dwNumEntries*4*sizeof(DWORD) ); if(pdwRenameList==NULL) { DBGOUT((1, "Cannot allocate the Rename List")); dwError = ERROR_OUTOFMEMORY; goto forced_exit; } } pdwRenameEntry = pdwRenameList; dwRenameEntryCount = 0; // Convert from end to the begining in order to avoid name conflicts during the key renames for(dwCount = dwNumEntries-1; (LONG)dwCount>=0; dwCount--) { wsprintf(Location, _T("%s%d"), gszLocation, dwCount); dwError = RegOpenKeyEx( hLocations, Location, 0, KEY_READ | KEY_WRITE, &hLocation ); if(dwError == ERROR_FILE_NOT_FOUND) { DBGOUT((1, "Cannot open old %s", Location)); // Try to recover - skip to the next entry continue; } EXIT_IF_DWERROR(); // Read the ID for later usage dwLength = sizeof(dwLocationID); dwError = RegQueryValueEx( hLocation, gszID, NULL, &dwType, (LPBYTE)&dwLocationID, &dwLength ); if(dwError == ERROR_SUCCESS) { // Convert the location to the new format dwError = ConvertOneLocation(hLocation); if(dwError != ERROR_SUCCESS) { DBGOUT((1, "%s conversion failed with error %d. Trying to continue...", Location, dwError)); } RegCloseKey(hLocation); hLocation = NULL; // Rename the key if it is necessary if(dwLocationID != dwCount) { wsprintf(NewLocation, _T("%s%d"), gszLocation, dwLocationID); // Check the destination for an old key still present. It may be possible to find one if // the original TAPI version was TELEPHON.INI-based. assert(!(dwLocationID & TEMPORARY_ID_FLAG)); dwLocationIDTmp = dwLocationID; dwError = RegOpenKeyEx( hLocations, NewLocation, 0, KEY_READ, &hLocation ); if(dwError==ERROR_SUCCESS) { // use a temporary ID dwLocationIDTmp |= TEMPORARY_ID_FLAG; wsprintf(NewLocation, _T("%s%d"), gszLocation, dwLocationIDTmp); } if(hLocation) { RegCloseKey(hLocation); hLocation = NULL; } dwError = RegRenameKey( hLocations, Location, NewLocation ); EXIT_IF_DWERROR(); // trace the rename. It will be useful when we try to upgrade the HKEY_CURRENT_USER/../Locations key *pdwRenameEntry++ = dwCount; *pdwRenameEntry++ = dwLocationIDTmp; dwRenameEntryCount++; } DBGOUT ((9, "Converted location %d (ID %d)", dwCount, dwLocationID)); } } dwError = ERROR_SUCCESS; // Rewalk the list for renaming the keys with temporary IDs pdwRenameEntryPhase1 = pdwRenameList; dwCountPhase1 = dwRenameEntryCount; for(dwCount=0; dwCount0) { int iCount; DWORD *pValue; TCHAR AreaCodeToCall[MAXLEN_NUMBER_LEN]; pNoPrefAC=GlobalAlloc(GPTR, dwLength); dwError = pNoPrefAC!=NULL ? ERROR_SUCCESS : ERROR_OUTOFMEMORY; EXIT_IF_DWERROR(); // ..and read dwError = RegQueryValueEx( hLocation, gszNoPrefAC, NULL, &dwType, pNoPrefAC, &dwLength ); if(dwError == ERROR_SUCCESS && dwType != REG_BINARY) { dwError = ERROR_INVALID_DATA; assert(FALSE); } EXIT_IF_DWERROR(); iCount = dwLength/4; pValue = (DWORD *)pNoPrefAC; while(iCount--) { // Create one rule for each area code _itot(*pValue, AreaCodeToCall, 10); dwError = CreateAreaCodeRule( hAreaCodeRules, iRuleNumber++, AreaCodeToCall, gszEmpty, (LPBYTE)gszMultiEmpty, sizeof(gszMultiEmpty), AREACODERULE_DIALAREACODE | AREACODERULE_INCLUDEALLPREFIXES ); EXIT_IF_DWERROR(); pValue++; } } DBGOUT((9, "ConvertOneLocation - Success NoPrefAC")); } dwError = ERROR_SUCCESS; // delete the TollList Value RegDeleteValue( hLocation, gszTollList ); // delete the NoPrefAC Value RegDeleteValue( hLocation, gszNoPrefAC ); // delete the ID Value RegDeleteValue( hLocation, gszID ); forced_exit: if(hAreaCodeRules) RegCloseKey(hAreaCodeRules); if(pTollList) GlobalFree(pTollList); if(pNoPrefAC) GlobalFree(pNoPrefAC); DBGOUT((9, "ConvertOneLocation - Exit %xh", dwError)); return dwError; } //*************************************************************************** // // CreateAreaCodeRule - creates an area code rule key // hParent = handle of the AreaCodeRules key // iRuleNumber = rule number // pszAreaCodeToCall, pszNumberToDial & dwFlags = rule values // pbPrefixes - prefixes // dwPrefixesLength - length of the prefixes in bytes (including the NULL characters) PRIVATE DWORD CreateAreaCodeRule( HKEY hParent, int iRuleNumber, LPCTSTR pszAreaCodeToCall, LPCTSTR pszNumberToDial, LPBYTE pbPrefixes, DWORD dwPrefixesLength, DWORD dwFlags ) { TCHAR szBuffer[MAXLEN_NUMBER_LEN + sizeof(gszRule)/sizeof(TCHAR)]; DWORD dwError = ERROR_SUCCESS; DWORD dwDisp; DWORD dwLength; HKEY hRule = NULL; DBGOUT((10, "CreateAreaCodeRule - Enter")); assert(hParent); assert(pszNumberToDial); assert(pszAreaCodeToCall); assert(pbPrefixes); // Find the rule key name wsprintf(szBuffer, _T("%s%d"), gszRule, iRuleNumber); // Create the key dwError = RegCreateKeyEx( hParent, szBuffer, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRule, &dwDisp ); EXIT_IF_DWERROR(); assert(dwDisp==REG_CREATED_NEW_KEY); // AreaCodeToCall value dwLength = (_tcslen(pszAreaCodeToCall)+1)*sizeof(TCHAR); dwError = RegSetValueEx( hRule, gszAreaCodeToCall, 0, REG_SZ, (CONST BYTE *)pszAreaCodeToCall, dwLength ); EXIT_IF_DWERROR(); // NumberToDial value dwLength = (_tcslen(pszNumberToDial)+1)*sizeof(TCHAR); dwError = RegSetValueEx( hRule, gszNumberToDial, 0, REG_SZ, (CONST BYTE *)pszNumberToDial, dwLength ); EXIT_IF_DWERROR(); // Flags value dwLength = sizeof(dwFlags); dwError = RegSetValueEx( hRule, gszFlags, 0, REG_DWORD, (CONST BYTE *)&dwFlags, dwLength ); EXIT_IF_DWERROR(); // Prefixes value dwError = RegSetValueEx( hRule, gszPrefixes, 0, REG_MULTI_SZ, (CONST BYTE *)pbPrefixes, dwPrefixesLength ); EXIT_IF_DWERROR(); forced_exit: if(hRule) RegCloseKey(hRule); DBGOUT((10, "CreateAreaCodeRule - Exit %xh", dwError)); return dwError; } //*************************************************************************** //*************************************************************************** //*************************************************************************** // // ConvertUserLocations - convert the telephony locations stored in a per user way // The parameter should be HKEY_CURRENT_USER // // // DWORD ConvertUserLocations(HKEY hUser) { TCHAR Location[sizeof(gszLocation)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN]; TCHAR NewLocation[sizeof(gszLocation)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN]; DWORD dwError = ERROR_SUCCESS; HKEY hMachineLocations = NULL; HKEY hLocations = NULL; DWORD dwOldID; DWORD dwNewID; DWORD dwCount; DWORD dwLength; DWORD dwType; DWORD dwValue; PDWORD pdwRenameList = NULL; PDWORD pdwRenameEntry; #ifdef BACKUP_OLD_KEYS TCHAR szPath[MAX_PATH+1]; #endif DBGOUT((8, "ConvertUserLocations - Enter")); assert(hUser); dwError = RegOpenKeyEx( hUser, gszLocationsPath, 0, KEY_READ | KEY_WRITE, &hLocations ); if(dwError == ERROR_FILE_NOT_FOUND) { DBGOUT((1, "Locations key not present, so there's nothing to convert")); //Nothing to convert return ERROR_SUCCESS; } EXIT_IF_DWERROR(); #ifdef BACKUP_OLD_KEYS // Try to save the old key // We DON'T use different files for different users dwError = GetWindowsDirectory(szPath, MAX_PATH - 12); // a 8+3 name if(dwError) { if(szPath[3] != _T('\0')) lstrcat(szPath, _T("\\")); lstrcat(szPath, BACKUP_FILE_USER_LOCATIONS); SaveKey(hLocations, szPath); } else DBGOUT((1, "Cannot get windows directory (?!?)")); dwError = ERROR_SUCCESS; #endif // Version check if(!IsLocationListInOldFormat(hLocations)) { //Nothing to convert DBGOUT((1, "User Locations key is already in the new format")); RegCloseKey(hLocations); return ERROR_SUCCESS; } // Open the Machine Locations key dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, gszLocationsPath, 0, KEY_QUERY_VALUE, &hMachineLocations ); if(dwError == ERROR_FILE_NOT_FOUND) { DBGOUT((1, "Locations key not present, so there's nothing to convert in User Locations")); //Nothing to convert return ERROR_SUCCESS; } EXIT_IF_DWERROR(); // query info about the rename history value dwError = RegQueryValueEx( hMachineLocations, gszKeyRenameHistory, NULL, &dwType, NULL, &dwLength ); if(dwError==ERROR_SUCCESS && dwType!=REG_BINARY) { // strange value dwError = ERROR_INVALID_DATA; } if(dwError==ERROR_FILE_NOT_FOUND) { dwError = ERROR_SUCCESS; dwLength = 0; } EXIT_IF_DWERROR(); if(dwLength>0) { pdwRenameList = (PDWORD)GlobalAlloc(GPTR, dwLength); if(pdwRenameList == NULL) { DBGOUT((1, "Cannot allocate the Rename List")); dwError = ERROR_OUTOFMEMORY; goto forced_exit; } // Read the list dwError = RegQueryValueEx( hMachineLocations, gszKeyRenameHistory, NULL, NULL, (PBYTE)pdwRenameList, &dwLength); EXIT_IF_DWERROR(); // RegCloseKey(hMachineLocations); hMachineLocations = NULL; // convert dwLength to the number of entries dwLength /= 2*sizeof(DWORD); pdwRenameEntry = pdwRenameList; for(dwCount = 0; dwCount0) { pdwRenameList = (PDWORD)GlobalAlloc(GPTR, dwNumCards*sizeof(DWORD) ); if(pdwRenameList==NULL) { DBGOUT((1, "Cannot allocate the temp IDs List")); dwError = ERROR_OUTOFMEMORY; goto forced_exit; } } pdwRenameEntry = pdwRenameList; dwRenameEntryCount = 0; // Initialize the cryptographic part dwError = TapiCryptInitialize(); bCryptInitialized = TRUE; // whatever the result was if(dwError != ERROR_SUCCESS) { DBGOUT((8, "ConvertCallingCards - Cannot init Crypt %xh", dwError)); // Make it not fatal dwError = ERROR_SUCCESS; } // Convert from end to the begining in order to avoid name conflicts during the key renames for(dwCount = dwNumCards-1; (LONG)dwCount>=0; dwCount--) { wsprintf(Card, _T("%s%d"), gszCard, dwCount); dwError = RegOpenKeyEx( hCards, Card, 0, KEY_READ | KEY_WRITE, &hCard ); if(dwError == ERROR_FILE_NOT_FOUND) { DBGOUT((1, "Cannot open old %s", Card)); // Try to recover - skip to the next entry continue; } EXIT_IF_DWERROR(); // Read the ID for later usage dwLength = sizeof(dwCardID); dwError = RegQueryValueEx( hCard, gszID, NULL, &dwType, (LPBYTE)&dwCardID, &dwLength ); if(dwError == ERROR_SUCCESS) { // Convert the card to the new format dwError = ConvertOneCard(hCard, dwCardID); EXIT_IF_DWERROR(); RegCloseKey(hCard); hCard = NULL; // Rename the key if it is necessary if(dwCardID != dwCount) { wsprintf(NewCard, _T("%s%d"), gszCard, dwCardID); // Check the destination for an old key still present. It may be possible to find one if // the original TAPI version was TELEPHON.INI-based. assert(!(dwCardID & TEMPORARY_ID_FLAG)); dwCardIDTmp = dwCardID; dwError = RegOpenKeyEx( hCards, NewCard, 0, KEY_READ, &hCard ); if(dwError==ERROR_SUCCESS) { // use a temporary ID dwCardIDTmp |= TEMPORARY_ID_FLAG; wsprintf(NewCard, _T("%s%d"), gszCard, dwCardIDTmp); *pdwRenameEntry++ = dwCardIDTmp; dwRenameEntryCount++; } if(hCard) { RegCloseKey(hCard); hCard = NULL; } dwError = RegRenameKey( hCards, Card, NewCard ); EXIT_IF_DWERROR(); } DBGOUT ((8, "Converted card %d (ID %d)", dwCount, dwCardID)); } } dwError = ERROR_SUCCESS; // Rewalk the list for renaming the keys with temporary IDs pdwRenameEntry = pdwRenameList; for(dwCount=0; dwCount dwLength/sizeof(WCHAR)) { pszNewPIN = (PWSTR)GlobalAlloc(GMEM_FIXED, dwLength2*sizeof(WCHAR)); if(pszNewPIN==NULL) { return ERROR_OUTOFMEMORY; } dwError = TapiEncrypt(szOldPIN, dwCardID, pszNewPIN, &dwLength3); if(dwError == ERROR_SUCCESS) { assert(dwLength3<=dwLength2); // Write the new PIN dwError = RegSetValueExW( hCard, gwszPIN, 0, REG_SZ, (BYTE *)pszNewPIN, dwLength3*sizeof(WCHAR) ); // TEST /* ZeroMemory(szOldPIN, sizeof(szOldPIN)); dwError = TapiDecrypt(pszNewPIN, dwCardID, szOldPIN, &dwLength3); if(dwError==ERROR_SUCCESS) DBGOUT((5, "TEST Decrypt Card %d - PIN # %S, Length=%d", dwCardID, szOldPIN, dwLength3)); else DBGOUT((5, "TEST Decrypt Card %d - Error 0x%x", dwCardID, dwError)); */ } GlobalFree(pszNewPIN); } else { DBGOUT((5, "PIN for card %d not converted", dwCardID)); } } } else { // Strange, shouldn't happen assert(FALSE); } } return dwError; } //*************************************************************************** // // Version Check BOOL IsLocationListInOldFormat(HKEY hLocations) // for both user & machine { return (ERROR_SUCCESS != RegQueryValueEx( hLocations, gszLocationListVersion, NULL, NULL, NULL, NULL )); } BOOL IsCardListInOldFormat(HKEY hCards) { return (ERROR_SUCCESS != RegQueryValueEx( hCards, gszCardListVersion, NULL, NULL, NULL, NULL )); } //*************************************************************************** // // IsTelephonyDigit - test range 0123456789#*ABCD PRIVATE BOOL IsTelephonyDigit(TCHAR c) { return _istdigit(c) || c==_T('*') || c==_T('#') || c==_T('A') || c==_T('B') || c==_T('C') || c==_T('D'); } //*************************************************************************** // // SplitCallingCardRule - tries to find the access numbers and updates the coresponding values PRIVATE DWORD SplitCallingCardRule(HKEY hCard, LPCTSTR pszRuleName, LPCTSTR pszAccessNumberName) { TCHAR OldRule[MAXLEN_RULE]; TCHAR NewRule[MAXLEN_RULE]; TCHAR AccessNumber[MAXLEN_ACCESS_NUMBER]; TCHAR * pOld; TCHAR * pNew; TCHAR * pNr; DWORD dwLength; DWORD dwError = ERROR_SUCCESS; DWORD dwType; // read the local rule dwLength = sizeof(OldRule); dwError = RegQueryValueEx( hCard, pszRuleName, NULL, &dwType, (BYTE *)OldRule, &dwLength ); if(dwError==ERROR_SUCCESS && dwType != REG_SZ) { dwError = ERROR_INVALID_DATA; assert(FALSE); } if(dwError==ERROR_SUCCESS) { // Parse the old rule pOld = OldRule; pNew = NewRule; pNr = AccessNumber; while(*pOld && IsTelephonyDigit(*pOld)) *pNr++ = *pOld++; if(pNr!=AccessNumber) *pNew++ = _T('J'); while(*pOld) *pNew++ = *pOld++; *pNew = _T('\0'); *pNr = _T('\0'); dwLength = (_tcslen(AccessNumber)+1)*sizeof(TCHAR); dwError = RegSetValueEx( hCard, pszAccessNumberName, 0, REG_SZ, (BYTE *)AccessNumber, dwLength ); EXIT_IF_DWERROR(); dwLength = (_tcslen(NewRule)+1)*sizeof(TCHAR); dwError = RegSetValueEx( hCard, pszRuleName, 0, REG_SZ, (BYTE *)NewRule, dwLength ); EXIT_IF_DWERROR(); } forced_exit: return dwError; } //*************************************************************************** //*************************************************************************** //*************************************************************************** // Helper functions for renaming the registry keys PRIVATE DWORD RegRenameKey( HKEY hParentKey, LPCTSTR pszOldName, LPCTSTR pszNewName) { DWORD dwError; assert(pszOldName); assert(pszNewName); DBGOUT((15, "RegRenameKey - Start, from %s to %s", pszOldName, pszNewName)); assert(hParentKey); assert(_tcscmp(pszOldName, pszNewName)!=0); dwError = RegCopyKeyRecursive( hParentKey, pszOldName, hParentKey, pszNewName ); EXIT_IF_DWERROR(); dwError = RegDeleteKeyRecursive(hParentKey, pszOldName); EXIT_IF_DWERROR(); forced_exit: DBGOUT((15, "RegRenameKey - Exit %xh", dwError)); return dwError; } PRIVATE DWORD RegCopyKeyRecursive(HKEY hSrcParentKey, LPCTSTR pszSrcName, HKEY hDestParentKey, LPCTSTR pszDestName) { HKEY hSrcKey = NULL; HKEY hDestKey = NULL; DWORD dwError = ERROR_SUCCESS; DWORD dwDisp; DWORD dwMaxSubkeyLength; DWORD dwMaxValueNameLength; DWORD dwMaxValueLength; DWORD dwNumValues; DWORD dwNumSubkeys; DWORD dwIndex; DWORD dwType; DWORD dwValueLength; DWORD dwValueNameLength; DWORD dwSubkeyLength; LPTSTR pszSubkey = NULL; LPTSTR pszValueName = NULL; LPBYTE pbValue = NULL; assert(hSrcParentKey); assert(hDestParentKey); assert(pszSrcName); assert(pszDestName); // open source key dwError = RegOpenKeyEx( hSrcParentKey, pszSrcName, 0, KEY_READ, &hSrcKey ); EXIT_IF_DWERROR(); // create destination key dwError = RegCreateKeyEx( hDestParentKey, pszDestName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hDestKey, &dwDisp ); EXIT_IF_DWERROR(); assert(dwDisp==REG_CREATED_NEW_KEY); // query some info about the source key in order to allocate memory dwError = RegQueryInfoKey( hSrcKey, NULL, NULL, NULL, &dwNumSubkeys, &dwMaxSubkeyLength, NULL, &dwNumValues, &dwMaxValueNameLength, &dwMaxValueLength, NULL, NULL ); EXIT_IF_DWERROR(); pszSubkey = (LPTSTR)GlobalAlloc(GMEM_FIXED, (dwMaxSubkeyLength+1)*sizeof(TCHAR)); if(pszSubkey==NULL) dwError = ERROR_OUTOFMEMORY; EXIT_IF_DWERROR(); pszValueName = (LPTSTR)GlobalAlloc(GMEM_FIXED, (dwMaxValueNameLength+1)*sizeof(TCHAR)); if(pszValueName==NULL) dwError = ERROR_OUTOFMEMORY; EXIT_IF_DWERROR(); pbValue = (LPBYTE)GlobalAlloc(GMEM_FIXED, dwMaxValueLength); if(pbValue==NULL) dwError = ERROR_OUTOFMEMORY; EXIT_IF_DWERROR(); // enumerate and copy the values for(dwIndex=0; dwIndex 0) { // at least one subkey dwSubKeyNameLengthBytes = sizeof (TCHAR) * (dwMaxSubKeyLength + 1); pszSubKeyName = (LPTSTR) GlobalAlloc (GMEM_FIXED, dwSubKeyNameLengthBytes); if (pszSubKeyName) { // delete from end to beginning, to avoid quadratic performance // ignore deletion errors for (dwIndex = dwSubKeyCount; dwIndex > 0; dwIndex--) { dwSubKeyNameLength = dwMaxSubKeyLength + 1; dwError = RegEnumKeyEx (hKey, dwIndex - 1, pszSubKeyName, &dwSubKeyNameLength, NULL, NULL, NULL, NULL); if (dwError == ERROR_SUCCESS) { RegDeleteKeyRecursive (hKey, pszSubKeyName); } } // clean up any stragglers for (;;) { dwSubKeyNameLength = dwMaxSubKeyLength + 1; dwError = RegEnumKeyEx (hKey, 0, pszSubKeyName, &dwSubKeyNameLength, NULL, NULL, NULL, NULL); if (dwError == ERROR_SUCCESS) RegDeleteKeyRecursive (hKey, pszSubKeyName); else break; } GlobalFree (pszSubKeyName); } } RegCloseKey (hKey); return RegDeleteKey (hParentKey, pszKeyName); } #ifdef BACKUP_OLD_KEYS #ifdef WINNT PRIVATE BOOL EnablePrivilege( PTSTR PrivilegeName, BOOL Enable, BOOL *Old ) { HANDLE Token; BOOL b; TOKEN_PRIVILEGES NewPrivileges, OldPrivileges; // place for one priv LUID Luid; DWORD Length; if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY ,&Token)) { return(FALSE); } if(!LookupPrivilegeValue(NULL,PrivilegeName,&Luid)) { CloseHandle(Token); return(FALSE); } NewPrivileges.PrivilegeCount = 1; NewPrivileges.Privileges[0].Luid = Luid; NewPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0; b = AdjustTokenPrivileges( Token, FALSE, &NewPrivileges, sizeof(OldPrivileges), // it has a place for one luid &OldPrivileges, &Length ); CloseHandle(Token); if(b) { if(OldPrivileges.PrivilegeCount==0) *Old = Enable; else *Old = (OldPrivileges.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) ? TRUE : FALSE; } else DBGOUT((1, "Cannot change SeBackupPrivilege - Error %d", GetLastError())); return(b); } #endif // WINNT PRIVATE BOOL SaveKey( HKEY hKey, LPCTSTR pszFileName ) { DWORD dwError; #ifdef WINNT BOOL bOldBackupPriv = FALSE; #endif // Delete the file if exists (ignore errors) DeleteFile(pszFileName); #ifdef WINNT // Enable the BACKUP privilege (ignore errors) EnablePrivilege(SE_BACKUP_NAME, TRUE, &bOldBackupPriv); #endif // Save the key dwError = RegSaveKey( hKey, pszFileName, NULL ); if(dwError==ERROR_SUCCESS) DBGOUT((9, "Old Telephony key saved")) ; else DBGOUT((1, "Cannot save old Telephony key - Error %d", dwError)); #ifdef WINNT // Restore the BACKUP privilege (ignore errors) EnablePrivilege(SE_BACKUP_NAME, bOldBackupPriv, &bOldBackupPriv); #endif return (dwError == ERROR_SUCCESS); } #endif // BACKUP_OLD_KEYS