|
|
/****************************************************************************
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 <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <stdlib.h>
// 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; dwCount<dwCountPhase1; dwCount++) { pdwRenameEntryPhase1++; dwLocationIDTmp = *pdwRenameEntryPhase1++;
if(dwLocationIDTmp & TEMPORARY_ID_FLAG) { wsprintf(Location, _T("%s%d"), gszLocation, dwLocationIDTmp);
dwLocationID = dwLocationIDTmp & ~TEMPORARY_ID_FLAG; wsprintf(NewLocation, _T("%s%d"), gszLocation, dwLocationID);
dwError = RegRenameKey( hLocations, Location, NewLocation ); EXIT_IF_DWERROR(); *pdwRenameEntry++ = dwLocationIDTmp; *pdwRenameEntry++ = dwLocationID; dwRenameEntryCount++; DBGOUT ((9, "Renamed to permanent ID %d", dwLocationID)); } }
// delete the DisableCallWaiting value
RegDeleteValue( hLocations, gszDisableCallWaiting );
// delete the NumEntries value. We don't need it any more
RegDeleteValue( hLocations, gszNumEntries);
// add the rename history
dwError = RegSetValueEx( hLocations, gszKeyRenameHistory, 0, REG_BINARY, (PBYTE)pdwRenameList, dwRenameEntryCount*2*sizeof(DWORD) ); EXIT_IF_DWERROR();
// add the versioning value
dwValue = TAPI_LOCATION_LIST_VERSION; dwError = RegSetValueEx( hLocations, gszLocationListVersion, 0, REG_DWORD, (PBYTE)&dwValue, sizeof(dwValue) ); EXIT_IF_DWERROR();
forced_exit:
if(hLocation) RegCloseKey(hLocation); if(hLocations) RegCloseKey(hLocations); if(pdwRenameList) GlobalFree(pdwRenameList);
DBGOUT((9, "ConvertLocations - Exit %xh", dwError));
return dwError;
}
//***************************************************************************
//
// ConvertOneLocation - convert one location
// hLocation is the handle of the LocationX key
// Note The key rename according to location ID is executed in ConvertLocations
PRIVATE DWORD ConvertOneLocation( HKEY hLocation) { DWORD dwError = ERROR_SUCCESS; LPTSTR pTollList = NULL; LPBYTE pNoPrefAC = NULL; TCHAR *pCrt; TCHAR AreaCode[MAXLEN_AREACODE]; DWORD dwFlags; DWORD dwCountryID; DWORD dwType; DWORD dwLength; DWORD dwTollListLength; DWORD dwDisp; HKEY hAreaCodeRules = NULL; int iRuleNumber;
DBGOUT((9, "ConvertOneLocation - Enter"));
assert(hLocation);
// Read the current location flags
dwLength = sizeof(dwFlags); dwError = RegQueryValueEx( hLocation, gszFlags, NULL, &dwType, (BYTE *)&dwFlags, &dwLength ); if(dwError==ERROR_SUCCESS && dwType != REG_DWORD) { dwError=ERROR_INVALID_DATA; assert(FALSE); }
EXIT_IF_DWERROR();
//Read the current Area Code
dwLength = sizeof(AreaCode); dwError = RegQueryValueEx( hLocation, gszAreaCode, NULL, &dwType, (BYTE *)AreaCode, &dwLength ); if(dwError==ERROR_SUCCESS && dwType != REG_SZ) { dwError=ERROR_INVALID_DATA; assert(FALSE); }
EXIT_IF_DWERROR();
//Read the current Country ID
dwLength = sizeof(dwCountryID); dwError = RegQueryValueEx( hLocation, gszCountry, NULL, &dwType, (BYTE *)&dwCountryID, &dwLength ); if(dwError==ERROR_SUCCESS && dwType != REG_DWORD) { dwError=ERROR_INVALID_DATA; assert(FALSE); }
EXIT_IF_DWERROR();
// create the AreaCodeRules subkey
dwError = RegCreateKeyEx( hLocation, gszAreaCodeRules, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hAreaCodeRules, &dwDisp ); if(dwError==ERROR_SUCCESS && dwDisp != REG_CREATED_NEW_KEY) { dwError=ERROR_INVALID_DATA; assert(FALSE); } EXIT_IF_DWERROR();
iRuleNumber = 0;
// Create a rule for "Always Include Area Code" flag..
if(dwFlags & OLDFLAG_LOCATION_ALWAYSINCLUDEAREACODE) { dwError = CreateAreaCodeRule( hAreaCodeRules, iRuleNumber++, AreaCode, gszEmpty, (LPBYTE)gszMultiEmpty, sizeof(gszMultiEmpty), AREACODERULE_DIALAREACODE | AREACODERULE_INCLUDEALLPREFIXES ); EXIT_IF_DWERROR();
// update the location flag
dwFlags &= ~OLDFLAG_LOCATION_ALWAYSINCLUDEAREACODE; dwLength = sizeof(dwFlags); dwError = RegSetValueEx( hLocation, gszFlags, 0, REG_DWORD, (CONST BYTE *)&dwFlags, dwLength ); EXIT_IF_DWERROR(); }
// The TollList and NoPrefAC were valid only in countries with Country=1 (US, Canada)
// Ignore them if other country
if(US_COUNTRY_CODE(dwCountryID)) { // Translate TollList
// Length...
dwError = RegQueryValueEx( hLocation, gszTollList, NULL, NULL, NULL, &dwTollListLength); if(dwError == ERROR_SUCCESS) {
pTollList=GlobalAlloc(GPTR, dwTollListLength+sizeof(TCHAR)); // We'll convert in place to a
// REG_MULTI_SZ, so reserve an extra space for safety
dwError = pTollList!=NULL ? ERROR_SUCCESS : ERROR_OUTOFMEMORY; EXIT_IF_DWERROR();
// ..and read
dwError = RegQueryValueEx( hLocation, gszTollList, NULL, &dwType, (BYTE *)pTollList, &dwTollListLength ); if(dwError == ERROR_SUCCESS && dwType != REG_SZ) { dwError = ERROR_INVALID_DATA; assert(FALSE); } EXIT_IF_DWERROR();
// try to find one toll prefix
pCrt = pTollList; //skip any unwanted commas
while(*pCrt==_T(',')) { pCrt++; dwTollListLength -= sizeof(TCHAR); }
if(*pCrt) { TCHAR * pOut = pCrt;
// convert inplace to a REG_MULTI_SZ
while(*pCrt) { while(*pCrt && *pCrt!=_T(',')) { pCrt++; } if(!*pCrt) { // incorrect string (does not end with a comma)
pCrt++; *pCrt = _T('\0'); dwTollListLength+=sizeof(TCHAR); } else *pCrt++ = _T('\0'); } // Create one rule for all the prefixes
dwError = CreateAreaCodeRule( hAreaCodeRules, iRuleNumber++, AreaCode, gszUSLDSpecifier, (BYTE *)pOut, dwTollListLength, AREACODERULE_DIALAREACODE | AREACODERULE_DIALNUMBERTODIAL ); EXIT_IF_DWERROR(); } }
DBGOUT((9, "ConvertOneLocation - Success TollList"));
// Translate NoPrefAC
// Length...
dwError = RegQueryValueEx( hLocation, gszNoPrefAC, NULL, NULL, NULL, &dwLength);
if(dwError== ERROR_SUCCESS && dwLength>0) {
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; dwCount<dwLength; dwCount++) { dwOldID = *pdwRenameEntry++; dwNewID = *pdwRenameEntry++; if(dwNewID != dwOldID) { wsprintf(Location, _T("%s%d"), gszLocation, dwOldID); wsprintf(NewLocation, _T("%s%d"), gszLocation, dwNewID);
dwError = RegRenameKey( hLocations, Location, NewLocation ); if(dwError==ERROR_SUCCESS) { DBGOUT ((8, "Renamed user location number from %d to %d", dwOldID, dwNewID)); } // ignore the errors - the key could be missing
} } } // add the versioning value
dwValue = TAPI_LOCATION_LIST_VERSION; dwError = RegSetValueEx( hLocations, gszLocationListVersion, 0, REG_DWORD, (PBYTE)&dwValue, sizeof(dwValue) ); EXIT_IF_DWERROR(); forced_exit: DBGOUT((8, "ConvertUserLocations - Exit %xh", dwError)); if(hMachineLocations) RegCloseKey(hMachineLocations); if(hLocations) RegCloseKey(hLocations); if(pdwRenameList) GlobalFree(pdwRenameList);
return dwError;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
//
// ConvertCallingCards - convert the telephony calling cards to the new format
// The parameter should be HKEY_CURRENT_USER or the handle of HKU\.Default
//
// see nt\private\tapi\dev\docs\dialrules.doc
//
DWORD ConvertCallingCards(HKEY hUser) { TCHAR Card[sizeof(gszCard)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN]; TCHAR NewCard[sizeof(gszCard)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN]; DWORD dwError = ERROR_SUCCESS; HKEY hCards = NULL; HKEY hCard = NULL; DWORD dwNumCards; DWORD dwCardID; DWORD dwCardIDTmp; DWORD dwCount; DWORD dwLength; DWORD dwType; DWORD dwValue; BOOL bCryptInitialized; PDWORD pdwRenameList = NULL; PDWORD pdwRenameEntry; DWORD dwRenameEntryCount;
#ifdef BACKUP_OLD_KEYS
TCHAR szPath[MAX_PATH+1]; #endif
DBGOUT((8, "ConvertCallingCards - Enter")); assert(hUser); bCryptInitialized = FALSE;
// Open the key
dwError = RegOpenKeyEx( hUser, gszCardsPath, 0, KEY_READ | KEY_WRITE, &hCards );
if(dwError == ERROR_FILE_NOT_FOUND) { DBGOUT((1, "Cards key not present, so there's nothing to convert")); //Nothing to convert
return ERROR_SUCCESS; }
EXIT_IF_DWERROR();
// Version check
if(!IsCardListInOldFormat(hCards)) { //Nothing to convert
DBGOUT((1, "Cards key is already in the new format")); RegCloseKey(hCards); return ERROR_SUCCESS; }
#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_CARDS); SaveKey(hCards, szPath); } else DBGOUT((1, "Cannot get windows directory (?!?)"));
dwError = ERROR_SUCCESS;
#endif
// Read number of cards
dwLength = sizeof(dwNumCards); dwError = RegQueryValueEx( hCards, gszNumEntries, NULL, &dwType, (BYTE *)&dwNumCards, &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) dwNumCards = 0;
// Alloc storage for a list of card temp IDs
if(dwNumCards>0) { 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<dwRenameEntryCount; dwCount++) { dwCardIDTmp = *pdwRenameEntry++;
wsprintf(Card, _T("%s%d"), gszCard, dwCardIDTmp);
dwCardID = dwCardIDTmp & ~TEMPORARY_ID_FLAG; wsprintf(NewCard, _T("%s%d"), gszCard, dwCardID);
dwError = RegRenameKey( hCards, Card, NewCard ); EXIT_IF_DWERROR(); DBGOUT ((8, "Renamed to permanent ID %d", dwCardID)); }
// delete the NumEntries value. We don't need it any more
RegDeleteValue( hCards, gszNumEntries);
// add the versioning value
dwValue = TAPI_CARD_LIST_VERSION; dwError = RegSetValueEx( hCards, gszCardListVersion, 0, REG_DWORD, (PBYTE)&dwValue, sizeof(dwValue) ); EXIT_IF_DWERROR();
forced_exit:
if(hCard) RegCloseKey(hCard); if(hCards) RegCloseKey(hCards); if(bCryptInitialized) TapiCryptUninitialize(); if(pdwRenameList) GlobalFree(pdwRenameList);
DBGOUT((8, "ConvertCallingCards - Exit %xh", dwError));
return dwError;
}
//***************************************************************************
//
// ConvertOneCard - convert one calling card
// hCard is the handle of the CardX key
// Note The key rename according to card ID is executed in ConvertCallingCards
DWORD ConvertOneCard(HKEY hCard, DWORD dwCardID) { DWORD dwError = ERROR_SUCCESS;
DBGOUT((9, "ConvertOneCard - Enter"));
assert(hCard);
dwError = SplitCallingCardRule( hCard, gszLocalRule, gszLocalAccessNumber); // ignore any error
dwError = SplitCallingCardRule( hCard, gszLDRule, gszLDAccessNumber); // ignore any error
dwError = SplitCallingCardRule( hCard, gszInternationalRule, gszInternationalAccessNumber); // ignore any error
dwError = RegSetValueEx( hCard, gszAccountNumber, 0, REG_SZ, (BYTE *)gszEmpty, sizeof(TCHAR) ); // Converts the PIN number to a better encrypted form
dwError = ConvertPIN(hCard, dwCardID);
// delete the ID Value
RegDeleteValue( hCard, gszID );
//forced_exit:
DBGOUT((9, "ConvertOneCard - Exit %xh", dwError));
return dwError; }
//***************************************************************************
//
// ConvertPIN - better encryption of the PIN number
// hCard is the handle of the CardX key
//
DWORD ConvertPIN(HKEY hCard, DWORD dwCardID) { WCHAR szOldPIN[MAXLEN_PIN+1]; PWSTR pszNewPIN = NULL; DWORD dwError; DWORD dwLength; DWORD dwLength2; DWORD dwLength3; DWORD dwType;
// Read the old PIN with a UNICODE version of RegQuery..
dwLength = sizeof(szOldPIN); dwError = RegQueryValueExW( hCard, gwszPIN, NULL, &dwType, (BYTE *)szOldPIN, &dwLength ); if(dwError==ERROR_SUCCESS) { if(*szOldPIN==L'\0') { // Nothing to do !
return ERROR_SUCCESS; } // Decrypts inplace
dwError = TapiDecrypt(szOldPIN, dwCardID, szOldPIN, &dwLength2); if(dwError==ERROR_SUCCESS) { assert(dwLength2 == dwLength/sizeof(WCHAR)); // Find the space needed for the encrypted result
dwError = TapiEncrypt(szOldPIN, dwCardID, NULL, &dwLength2); if(dwError == ERROR_SUCCESS) { // If the length is the same with the original, we have no conversion
if(dwLength2 > 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<dwNumValues; dwIndex++) { // read one value
dwValueNameLength = dwMaxValueNameLength + 1; dwValueLength = dwMaxValueLength;
dwError = RegEnumValue( hSrcKey, dwIndex, pszValueName, &dwValueNameLength, NULL, &dwType, pbValue, &dwValueLength ); EXIT_IF_DWERROR();
// write it
dwError = RegSetValueEx(hDestKey, pszValueName, 0, dwType, pbValue, dwValueLength ); EXIT_IF_DWERROR(); }
// enumerate and copy the subkeys
for(dwIndex=0; dwIndex<dwNumSubkeys; dwIndex++) { // read a subkey
dwSubkeyLength = dwMaxSubkeyLength +1; dwError = RegEnumKeyEx( hSrcKey, dwIndex, pszSubkey, &dwSubkeyLength, NULL, NULL, NULL, NULL ); EXIT_IF_DWERROR();
// copy it
dwError = RegCopyKeyRecursive( hSrcKey, pszSubkey, hDestKey, pszSubkey ); EXIT_IF_DWERROR(); }
forced_exit:
if(hSrcKey) RegCloseKey(hSrcKey); if(hDestKey) RegCloseKey(hDestKey);
if(pszSubkey) GlobalFree(pszSubkey); if(pszValueName) GlobalFree(pszValueName); if(pbValue) GlobalFree(pbValue);
return dwError; }
DWORD RegDeleteKeyRecursive (HKEY hParentKey, LPCTSTR pszKeyName) { HKEY hKey = NULL; DWORD dwError; DWORD dwIndex; DWORD dwSubKeyCount; LPTSTR pszSubKeyName; DWORD dwSubKeyNameLength; // in characters
DWORD dwSubKeyNameLengthBytes; // in bytes
DWORD dwMaxSubKeyLength;;
dwError = RegOpenKeyEx (hParentKey, pszKeyName, 0, KEY_READ | KEY_WRITE, &hKey); if (dwError != ERROR_SUCCESS) return dwError;
dwError = RegQueryInfoKey ( hKey, // key in question
NULL, NULL, // class
NULL, // reserved
&dwSubKeyCount, // number of subkeys
&dwMaxSubKeyLength, // maximum length of subkey name
NULL, // max class length
NULL, // number of values
NULL, // max value name len
NULL, // max value len
NULL, // security descriptor
NULL); // last write time
if (dwError != ERROR_SUCCESS) { RegCloseKey (hKey); return dwError; }
if (dwSubKeyCount > 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
|