Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1722 lines
50 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
fxocUpgrade.cpp
Abstract:
Implementation of the Upgrade process
Author:
Iv Garber (IvG) Mar, 2001
Revision History:
--*/
#include "faxocm.h"
#pragma hdrstop
#include <setuputil.h>
#include <shlwapi.h> // For SHCopyKey
DWORD g_LastUniqueLineId = 0;
//
// EnumDevicesType is used to call prv_StoreDevices() callback function during the Enumeration of
// Devices in the Registry.
//
typedef enum prv_EnumDevicesType
{
edt_None = 0x00,
edt_PFWDevices = 0x02, // Enumerate W2K Fax Devices
edt_Inbox = 0x04 // Find List of Inbox Folders for W2K Fax
};
//
// Local Static Variable, to store data between OS Manager calls
//
static struct prv_Data
{
DWORD dwFaxInstalledPriorUpgrade; // bit-wise combination of fxState_UpgradeApp_e values to define
// which fax clients were installed on the machine prior to upgrade
//
// data for PFW
//
TCHAR tszCommonCPDir[MAX_PATH]; // Folder for Common Cover Pages
LPTSTR *plptstrInboxFolders; // Array of different Inbox Folders
DWORD dwInboxFoldersCount; // number of Inbox Folders in the plptstrInboxFolders array
} prv_Data =
{
FXSTATE_NONE, // no fax client applications is installed by default
{0}, // tszCommonCPDir
NULL, // plptstrInboxFolders
0 // dwInboxFoldersCount
};
//
// Internal assisting functions
//
BOOL prv_StoreDevices(HKEY hKey, LPWSTR lpwstrKeyName, DWORD dwIndex, LPVOID lpContext);
static DWORD prv_MoveCoverPages(LPTSTR lptstrSourceDir, LPTSTR lptstrDestDir, LPTSTR lptstrPrefix);
static DWORD prv_GetPFWCommonCPDir(void);
static DWORD prv_GetSBSServerCPDir(LPTSTR lptstrCPDir) {return NO_ERROR; };
static DWORD prv_SaveArchives(void);
DWORD fxocUpg_WhichFaxWasUninstalled(
DWORD dwFaxAppList
)
/*++
Routine name : fxocUpg_WhichFaxWasUninstalled
Routine description:
Set flags regarding fax applications installed before upgrade. Called from SaveUnattendedData() if
the corresponding data is found in the Answer File.
Author:
Iv Garber (IvG), May, 2001
Arguments:
FaxApp [in] - the combination of the applications that were installed before the upgrade
Return Value:
Standard Win32 error code
--*/
{
DWORD dwReturn = NO_ERROR;
DBG_ENTER(_T("fxocUpg_WhichFaxWasUninstalled"), dwReturn);
prv_Data.dwFaxInstalledPriorUpgrade = dwFaxAppList;
return dwReturn;
}
DWORD fxocUpg_GetUpgradeApp(void)
/*++
Routine name : fxocUpg_GetUpgradeApp
Routine description:
Return type of the upgrade, which indicates which fax applications were installed before the upgrade.
Author:
Iv Garber (IvG), May, 2001
Return Value:
The type of the upgrade
--*/
{
DBG_ENTER(_T("fxocUpg_GetUpgradeApp"), prv_Data.dwFaxInstalledPriorUpgrade);
return prv_Data.dwFaxInstalledPriorUpgrade;
}
DWORD fxocUpg_Init(void)
/*++
Routine name : fxocUpg_Init
Routine description:
checks which Fax applications are installed on the machine,
and set global flags in prv_Data.
Author:
Iv Garber (IvG), May, 2001
Return Value:
DWORD - failure or success
--*/
{
DWORD dwReturn = NO_ERROR;
bool bInstalled = false;
DBG_ENTER(_T("fxocUpg_Init"), dwReturn);
//
// Clear the SBS 5.0 Server flag
//
prv_Data.dwFaxInstalledPriorUpgrade = FXSTATE_NONE;
//
// Check presence of the SBS 5.0 Server
//
dwReturn = WasSBS2000FaxServerInstalled(&bInstalled);
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING, _T("CheckInstalledFax() failed, ec=%ld."), dwReturn);
}
if (bInstalled)
{
prv_Data.dwFaxInstalledPriorUpgrade |= FXSTATE_SBS5_SERVER;
}
return dwReturn;
}
DWORD fxocUpg_SaveSettings(void)
/*++
Routine name : fxocUpg_SaveSettings
Routine description:
Save settings of SBS 5.0 Server to allow smooth migration to the Windows XP Fax.
Device Settings should be stored BEFORE handling of the Registry ( which deletes the Devices key )
and BEFORE the Service Start ( which creates new devices and uses settings that are stored here ).
Author:
Iv Garber (IvG), May, 2001
Return Value:
DWORD - failure or success
--*/
{
DWORD dwReturn = NO_ERROR;
DWORD dwEnumType = edt_None;
DBG_ENTER(_T("fxocUpg_SaveSettings"), dwReturn);
//
// Handle Upgrade from W2K/PFW Fax
//
if (fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_W2K)
{
//
// Save its Common CP Dir. This should be done BEFORE Copy/Delete Files of Windows XPFax.
//
dwReturn = prv_GetPFWCommonCPDir();
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING, _T("prv_GetPFWCommonCPDir() failed, ec=%ld."), dwReturn);
}
//
// Store Device Settings of PFW -- if SBS 5.0 Server is not present on the machine.
// Also, find Inbox Folders List of the PFW Devices.
//
HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_READ);
if (!hKey)
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("Failed to open Registry for Fax, ec = %ld."), dwReturn);
return dwReturn;
}
if (prv_Data.dwFaxInstalledPriorUpgrade & FXSTATE_SBS5_SERVER)
{
//
// Devices already enumerated, through SBS 5.0 Server
// Enumerate only Inbox Folders
//
dwEnumType = edt_Inbox;
}
else
{
//
// Full Enumeration for PFW Devices : Devices Settings + Inbox Folders
//
dwEnumType = edt_PFWDevices | edt_Inbox;
}
dwReturn = EnumerateRegistryKeys(hKey, REGKEY_DEVICES, FALSE, prv_StoreDevices, &dwEnumType);
VERBOSE(DBG_MSG, _T("For PFW, enumerated %ld devices."), dwReturn);
RegCloseKey(hKey);
//
// prv_StoreDevices stored list of PFW's Inbox Folders in prv_Data.
// Now save the Inbox Folders List and SentItems Folder
//
dwReturn = prv_SaveArchives();
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING, _T("prv_SaveArchives() failed, ec=%ld."), dwReturn);
}
dwReturn = NO_ERROR;
}
return dwReturn;
}
BOOL
prv_StoreDevices(HKEY hDeviceKey,
LPWSTR lpwstrKeyName,
DWORD dwIndex,
LPVOID lpContextData
)
/*++
Routine name : prv_StoreDevices
Routine description:
Callback function used in enumeration of devices in the registry.
Stores device's data in the Registry, under Setup/Original Setup Data.
Creates List of Inbox Folders ( used for PFW ) and saves it in the prv_Data.
Used when upgrading from PFW/SBS 5.0 Server to Windows XP Fax.
Author:
Iv Garber (IvG), Mar, 2001
Arguments:
hKey [in] - current key
lpwstrKeyName [in] - name of the current key, if exists
dwIndex [in] - count of all the subkeys for the given key / index of the current key
lpContextData [in] - NULL, not used
Return Value:
TRUE if success, FALSE otherwise.
--*/
{
HKEY hSetupKey = NULL;
DWORD dwReturn = NO_ERROR;
DWORD dwNumber = 0;
TCHAR tszNewKeyName[MAX_PATH] = {0};
LPTSTR lptstrString = NULL;
DWORD *pdwEnumType = NULL;
DBG_ENTER(_T("prv_StoreDevices"));
if (lpwstrKeyName == NULL)
{
//
// This is the SubKey we started at ( i.e. Devices )
//
// If InboxFolders should be stored, then allocate
// enough memory for prv_Data.plptstrInboxFolders.
// dwIndex contains TOTAL number of subkeys ( Devices ).
//
pdwEnumType = (DWORD *)lpContextData;
if ( (*pdwEnumType & edt_Inbox) == edt_Inbox )
{
prv_Data.plptstrInboxFolders = (LPTSTR *)MemAlloc(sizeof(LPTSTR) * dwIndex);
if (prv_Data.plptstrInboxFolders)
{
ZeroMemory(prv_Data.plptstrInboxFolders, sizeof(LPTSTR) * dwIndex);
}
else
{
//
// Not enough memory
//
VERBOSE(DBG_WARNING, _T("Not enough memory to store the Inbox Folders."));
}
}
return TRUE;
}
//
// The per Device section
//
//
// Store Device's Inbox Folder
//
if (prv_Data.plptstrInboxFolders)
{
//
// we are here only when lpContextData contains edt_InboxFolders
// and the memory allocation succeded.
//
//
// Open Routing SubKey
//
hSetupKey = OpenRegistryKey(hDeviceKey, REGKEY_PFW_ROUTING, FALSE, KEY_READ);
if (!hSetupKey)
{
//
// Failed to open Routing Subkey
//
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("Failed to open 'Registry' Key for Device #ld, ec = %ld."), dwIndex, dwReturn);
goto ContinueStoreDevice;
}
//
// Take 'Store Directory' Value
//
lptstrString = GetRegistryString(hSetupKey, REGVAL_PFW_INBOXDIR, EMPTY_STRING);
if ((!lptstrString) || (_tcslen(lptstrString) == 0))
{
//
// Failed to take the value
//
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("Failed to get StoreDirectory value for Device #ld, ec = %ld."), dwIndex, dwReturn);
goto ContinueStoreDevice;
}
//
// Check if it is already present
//
DWORD dwI;
for ( dwI = 0 ; dwI < prv_Data.dwInboxFoldersCount ; dwI++ )
{
if (prv_Data.plptstrInboxFolders[dwI])
{
if (_tcscmp(prv_Data.plptstrInboxFolders[dwI], lptstrString) == 0)
{
//
// String found
//
goto ContinueStoreDevice;
}
}
}
//
// String was NOT found between all already registered string, so add it
//
prv_Data.plptstrInboxFolders[dwI] = LPTSTR(MemAlloc(sizeof(TCHAR) * (_tcslen(lptstrString) + 1)));
if (prv_Data.plptstrInboxFolders[dwI])
{
//
// copy string & update the counter
//
_tcscpy(prv_Data.plptstrInboxFolders[dwI], lptstrString);
prv_Data.dwInboxFoldersCount++;
}
else
{
//
// Not enough memory
//
VERBOSE(DBG_WARNING, _T("Not enough memory to store the Inbox Folders."));
}
ContinueStoreDevice:
if (hSetupKey)
{
RegCloseKey(hSetupKey);
hSetupKey = NULL;
}
MemFree(lptstrString);
lptstrString = NULL;
}
//
// Check whether to store Device's Data and how
//
pdwEnumType = (DWORD *)lpContextData;
if ((*pdwEnumType & edt_PFWDevices) == edt_PFWDevices)
{
//
// Store PFW Devices Data
//
lptstrString = REGVAL_PERMANENT_LINEID;
}
else
{
//
// no need to save any Device Data
//
return TRUE;
}
//
// Take Device's Permanent Line Id
//
dwReturn = GetRegistryDwordEx(hDeviceKey, lptstrString, &dwNumber);
if (dwReturn != ERROR_SUCCESS)
{
//
// Cannot find TAPI Permanent LineId --> This is invalid Device Registry
//
return TRUE;
}
VERBOSE(DBG_MSG, _T("Current Tapi Line Id = %ld"), dwNumber);
//
// Create a SubKey Name from it
//
_sntprintf(
tszNewKeyName,
ARR_SIZE(tszNewKeyName) -1,
TEXT("%s\\%010d"),
REGKEY_FAX_SETUP_ORIG,
dwNumber);
hSetupKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, tszNewKeyName, TRUE, 0);
if (!hSetupKey)
{
//
// Failed to create registry key
//
dwReturn = GetLastError();
VERBOSE(DBG_WARNING,
_T("Failed to create a SubKey for the Original Setup Data of the Device, ec = %ld."),
dwReturn);
//
// Continue to the next device
//
return TRUE;
}
//
// Set the Flags for the newly created key
//
dwNumber = GetRegistryDword(hDeviceKey, REGVAL_FLAGS);
SetRegistryDword(hSetupKey, REGVAL_FLAGS, dwNumber);
VERBOSE(DBG_MSG, _T("Flags are : %ld"), dwNumber);
//
// Set the Rings for the newly created key
//
dwNumber = GetRegistryDword(hDeviceKey, REGVAL_RINGS);
SetRegistryDword(hSetupKey, REGVAL_RINGS, dwNumber);
VERBOSE(DBG_MSG, _T("Rings are : %ld"), dwNumber);
//
// Set the TSID for the newly created key
//
lptstrString = GetRegistryString(hDeviceKey, REGVAL_ROUTING_TSID, REGVAL_DEFAULT_TSID);
SetRegistryString(hSetupKey, REGVAL_ROUTING_TSID, lptstrString);
VERBOSE(DBG_MSG, _T("TSID is : %s"), lptstrString);
MemFree(lptstrString);
//
// Set the CSID for the newly created key
//
lptstrString = GetRegistryString(hDeviceKey, REGVAL_ROUTING_CSID, REGVAL_DEFAULT_CSID);
SetRegistryString(hSetupKey, REGVAL_ROUTING_CSID, lptstrString);
VERBOSE(DBG_MSG, _T("CSID is : %s"), lptstrString);
MemFree(lptstrString);
RegCloseKey(hSetupKey);
return TRUE;
}
DWORD fxocUpg_RestoreSettings(void)
/*++
Routine name : fxocUpg_RestoreSettings
Routine description:
Restore settings that were stored at the SaveSettings().
Author:
Iv Garber (IvG), Feb, 2001
Return Value:
DWORD - failure or success
--*/
{
DWORD dwReturn = NO_ERROR;
HANDLE hPrinter = NULL;
DBG_ENTER(_T("fxocUpg_RestoreSettings"), dwReturn);
return dwReturn;
}
DWORD fxocUpg_MoveFiles(void)
/*++
Routine name : fxocUpg_MoveFiles
Routine description:
Move files from the folders that should be deleted.
Should be called BEFORE directories delete.
Author:
Iv Garber (IvG), Feb, 2001
Return Value:
DWORD - failure or success
--*/
{
DWORD dwReturn = NO_ERROR;
TCHAR tszDestination[MAX_PATH] = {0};
LPTSTR lptstrCPDir = NULL;
DBG_ENTER(_T("fxocUpg_MoveFiles"), dwReturn);
if ( (fxState_IsUpgrade() != FXSTATE_UPGRADE_TYPE_W2K) &&
!(prv_Data.dwFaxInstalledPriorUpgrade & FXSTATE_SBS5_SERVER) )
{
//
// This is not PFW / SBS 5.0 Server upgrade. Do nothing
//
VERBOSE(DBG_MSG, _T("No need to Move any Files from any Folders."));
return dwReturn;
}
//
// Find Destination Folder : COMMON APP DATA + ServiceCPDir from the Registry
//
if (!GetServerCpDir(NULL, tszDestination, MAX_PATH))
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("GetServerCPDir() failed, ec=%ld."), dwReturn);
return dwReturn;
}
if (fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_W2K)
{
//
// PFW Server CP Dir is stored at SaveSettings() in prv_Data.lptstrPFWCommonCPDir
//
dwReturn = prv_MoveCoverPages(prv_Data.tszCommonCPDir, tszDestination, CP_PREFIX_W2K);
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING, _T("prv_MoveCoverPages() for Win2K failed, ec = %ld"), dwReturn);
}
}
if (prv_Data.dwFaxInstalledPriorUpgrade & FXSTATE_SBS5_SERVER)
{
//
// Get SBS Server CP Dir
//
dwReturn = prv_GetSBSServerCPDir(lptstrCPDir);
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING, _T("prv_GetSBSServerCPDir() failed, ec=%ld"), dwReturn);
return dwReturn;
}
//
// Move Cover Pages
//
dwReturn = prv_MoveCoverPages(lptstrCPDir, tszDestination, CP_PREFIX_SBS);
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING, _T("prv_MoveCoverPages() for SBS failed, ec = %ld"), dwReturn);
}
MemFree(lptstrCPDir);
}
return dwReturn;
}
static DWORD
prv_MoveCoverPages(
LPTSTR lptstrSourceDir,
LPTSTR lptstrDestDir,
LPTSTR lptstrPrefix
)
/*++
Routine name : prv_MoveCoverPages
Routine description:
Move all the Cover Pages from Source folder to Destination folder
and add a prefix to all the Cover Page names.
Author:
Iv Garber (IvG), Mar, 2001
Arguments:
lptstrSourceDir [IN] - Source Directory where Cover Pages are reside before the upgrade
lptstrDestDir [IN] - where the Cover Pages should reside after the upgrade
lptstrPrefix [IN] - prefix that should be added to the Cover Page file names
Return Value:
Success or Failure Error Code.
--*/
{
DWORD dwReturn = ERROR_SUCCESS;
TCHAR szSearch[MAX_PATH] = {0};
HANDLE hFind = NULL;
WIN32_FIND_DATA FindFileData = {0};
TCHAR szFrom[MAX_PATH] = {0};
TCHAR szTo[MAX_PATH] = {0};
DBG_ENTER(_T("prv_MoveCoverPages"), dwReturn);
if ((!lptstrSourceDir) || (_tcslen(lptstrSourceDir) == 0))
{
//
// we do not know from where to take Cover Pages
//
dwReturn = ERROR_INVALID_PARAMETER;
VERBOSE(DBG_WARNING, _T("SourceDir is NULL. Cannot move Cover Pages. Exiting..."));
return dwReturn;
}
if ((!lptstrDestDir) || (_tcslen(lptstrDestDir) == 0))
{
//
// we do not know where to put the Cover Pages
//
dwReturn = ERROR_INVALID_PARAMETER;
VERBOSE(DBG_WARNING, _T("DestDir is NULL. Cannot move Cover Pages. Exiting..."));
return dwReturn;
}
//
// Find all Cover Page files in the given Source Directory
//
_sntprintf(
szSearch,
ARR_SIZE(szSearch) -1,
_T("%s\\*.cov"),
lptstrSourceDir);
hFind = FindFirstFile(szSearch, &FindFileData);
if (INVALID_HANDLE_VALUE == hFind)
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING,
_T("FindFirstFile() on %s folder for Cover Pages is failed, ec = %ld"),
lptstrSourceDir,
dwReturn);
return dwReturn;
}
//
// Go for each Cover Page
//
do
{
//
// This is full current Cover Page file name
//
_sntprintf(szFrom, ARR_SIZE(szFrom) -1, _T("%s\\%s"), lptstrSourceDir, FindFileData.cFileName);
//
// This is full new Cover Page file name
//
_sntprintf(szTo, ARR_SIZE(szTo) -1, _T("%s\\%s_%s"), lptstrDestDir, lptstrPrefix, FindFileData.cFileName);
//
// Move the file
//
if (!MoveFile(szFrom, szTo))
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("MoveFile() for %s Cover Page failed, ec=%ld"), szFrom, dwReturn);
}
} while(FindNextFile(hFind, &FindFileData));
VERBOSE(DBG_MSG, _T("last call to FindNextFile() returns %ld."), GetLastError());
//
// Close Handle
//
FindClose(hFind);
return dwReturn;
}
static DWORD prv_GetPFWCommonCPDir(
)
/*++
Routine name : prv_GetPFWCommonCPDir
Routine description:
Return Folder for Common Cover Pages used for PFW.
This Folder is equal to : CSIDL_COMMON_DOCUMENTS + Localized Dir
This Localized Dir name we can take from the Resource of Win2K's FaxOcm.Dll.
So, this function should be called BEFORE Copy/Delete Files of Install that will remove old FaxOcm.Dll.
Currently it is called at SaveSettings(), which IS called before CopyFiles.
Author:
Iv Garber (IvG), Mar, 2001
Return Value:
static DWORD -- failure or success
--*/
{
DWORD dwReturn = NO_ERROR;
HMODULE hModule = NULL;
TCHAR tszName[MAX_PATH] = {0};
DBG_ENTER(_T("prv_GetPFWCommonCPDir"), dwReturn);
//
// find full path to FaxOcm.Dll
//
if (!GetSpecialPath(CSIDL_SYSTEM, tszName, ARR_SIZE(tszName)))
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("GetSpecialPath(CSIDL_SYSTEM) failed, ec = %ld"), dwReturn);
return dwReturn;
}
if ((_tcslen(tszName) + _tcslen(FAXOCM_NAME) + 1 ) >= ARR_SIZE(tszName)) // 1 for '\'
{
//
// not enough place
//
dwReturn = ERROR_OUTOFMEMORY;
VERBOSE(DBG_WARNING, _T("FaxOcm.Dll path is too long, ec = %ld"), dwReturn);
return dwReturn;
}
_tcscat(tszName, _T("\\"));
_tcscat(tszName, FAXOCM_NAME);
VERBOSE(DBG_MSG, _T("Full Name of FaxOcm is %s"), tszName);
hModule = LoadLibraryEx(tszName, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (!hModule)
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("LoadLibrary(%s) failed, ec = %ld."), tszName, dwReturn);
return dwReturn;
}
dwReturn = LoadString(hModule, CPDIR_RESOURCE_ID, tszName, MAX_PATH);
if (dwReturn == 0)
{
//
// Resource string is not found
//
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("LoadString() failed, ec = %ld."), dwReturn);
goto Exit;
}
VERBOSE(DBG_MSG, _T("FaxOcm returned '%s'"), tszName);
//
// Take the Base part of the Folder name
//
if (!GetSpecialPath(CSIDL_COMMON_DOCUMENTS, prv_Data.tszCommonCPDir,ARR_SIZE(prv_Data.tszCommonCPDir)))
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("GetSpecialPath(CSIDL_COMMON_DOCUMENTS) failed, ec = %ld"), dwReturn);
prv_Data.tszCommonCPDir[0] = _T('\0');
goto Exit;
}
//
// Combine the full Folder name
//
if ((_tcslen(tszName) + _tcslen(prv_Data.tszCommonCPDir) + 1) >= ARR_SIZE(prv_Data.tszCommonCPDir)) // 1 for '\'
{
//
// not enough place
//
dwReturn = ERROR_OUTOFMEMORY;
VERBOSE(DBG_WARNING, _T("Full path to the Common CP dir for PFW is too long, ec = %ld"), dwReturn);
goto Exit;
}
_tcscat(prv_Data.tszCommonCPDir,_T("\\"));
_tcscat(prv_Data.tszCommonCPDir, tszName);
VERBOSE(DBG_MSG, _T("Full path for Common PFW Cover Pages is '%s'"), prv_Data.tszCommonCPDir);
Exit:
if (hModule)
{
FreeLibrary(hModule);
}
return dwReturn;
}
static DWORD prv_SaveArchives(
)
/*++
Routine name : prv_SaveArchives
Routine description:
Store PFW SentItems & Inbox Archive Folder.
SentItems is taken from Registry : under Fax/Archive Directory.
Inbox Folders List is created by prv_StoreDevices(), that should be called before and that fills
prv_Data.plptstrInboxFolder with an array of Inbox Folders.
This function transforms the data in prv_Data.plptstrInboxFolders into the required format,
and stores in the Registry.
Frees the prv_Data.plptstrInboxFolders.
Author:
Iv Garber (IvG), Mar, 2001
Return Value:
static DWORD -- failure or success
--*/
{
DWORD dwReturn = NO_ERROR;
DWORD dwListLen = 0;
DWORD dwI = 0;
HKEY hFromKey = NULL;
HKEY hToKey = NULL;
LPTSTR lptstrFolder = NULL;
LPTSTR lptstrCursor = NULL;
DBG_ENTER(_T("prv_SaveArchives"), dwReturn);
//
// Open Registry Key to read the ArchiveDirectory value
//
hFromKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, KEY_READ);
if (!hFromKey)
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("Failed to open Registry for Fax, ec = %ld."), dwReturn);
goto Exit;
}
//
// Open Registry Key to write the Archive values
//
hToKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_FAX_SETUP, FALSE, KEY_SET_VALUE);
if (!hToKey)
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("Failed to open Registry for Fax/Setup, ec = %ld."), dwReturn);
goto Exit;
}
//
// Read & Write Outgoing Archive Folder
//
lptstrFolder = GetRegistryString(hFromKey, REGVAL_PFW_OUTBOXDIR, EMPTY_STRING);
VERBOSE(DBG_MSG, _T("Outgoing Archive Folder is : %s"), lptstrFolder);
SetRegistryString(hToKey, REGVAL_W2K_SENT_ITEMS, lptstrFolder);
MemFree(lptstrFolder);
lptstrFolder = NULL;
//
// Create valid REG_MULTI_SZ string from List of Inbox Folders
//
if (!prv_Data.plptstrInboxFolders || prv_Data.dwInboxFoldersCount == 0)
{
//
// no Inbox Folders found
//
goto Exit;
}
//
// Calculate the length of the string
//
for ( dwI = 0 ; dwI < prv_Data.dwInboxFoldersCount ; dwI++ )
{
dwListLen += _tcslen(prv_Data.plptstrInboxFolders[dwI]) + 1;
}
//
// Allocate that string
//
lptstrFolder = LPTSTR(MemAlloc((dwListLen + 1) * sizeof(TCHAR)));
if (!lptstrFolder)
{
//
// Not enough memory
//
VERBOSE(DBG_WARNING, _T("Not enough memory to store the Inbox Folders."));
goto Exit;
}
ZeroMemory(lptstrFolder, ((dwListLen + 1) * sizeof(TCHAR)));
lptstrCursor = lptstrFolder;
//
// Fill with the Inbox Folders
//
for ( dwI = 0 ; dwI < prv_Data.dwInboxFoldersCount ; dwI++ )
{
if (prv_Data.plptstrInboxFolders[dwI])
{
_tcscpy(lptstrCursor, prv_Data.plptstrInboxFolders[dwI]);
lptstrCursor += _tcslen(prv_Data.plptstrInboxFolders[dwI]) + 1;
MemFree(prv_Data.plptstrInboxFolders[dwI]);
}
}
MemFree(prv_Data.plptstrInboxFolders);
prv_Data.plptstrInboxFolders = NULL;
prv_Data.dwInboxFoldersCount = 0;
//
// Additional NULL at the end
//
*lptstrCursor = _T('\0');
if (!SetRegistryStringMultiSz(hToKey, REGVAL_W2K_INBOX, lptstrFolder, ((dwListLen + 1) * sizeof(TCHAR))))
{
//
// Failed to store Inbox Folders
//
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("Failed to SetRegistryStringMultiSz() for W2K_Inbox, ec = %ld."), dwReturn);
}
Exit:
if (hFromKey)
{
RegCloseKey(hFromKey);
}
if (hToKey)
{
RegCloseKey(hToKey);
}
MemFree(lptstrFolder);
if (prv_Data.plptstrInboxFolders)
{
for ( dwI = 0 ; dwI < prv_Data.dwInboxFoldersCount ; dwI++ )
{
MemFree(prv_Data.plptstrInboxFolders[dwI]);
}
MemFree(prv_Data.plptstrInboxFolders);
prv_Data.plptstrInboxFolders = NULL;
}
prv_Data.dwInboxFoldersCount = 0;
return dwReturn;
}
/*++
Routine description:
Copy a content of one registry key into another, using shlwapi.dll
Arguments:
hkeyDest [in] - handle for destination registry key
lpszDestSubKeyName [in] - name of destination subkey
hkeySrc [in] - handle for source registry key
lpszSrcSubKeyName [in] - name of source subkey
Return Value: Win32 Error code
Note:
If you already have an open handle to the source\dest, you can provide
them are hKeySrc/hKeyDest, and set the approriate name to "".
--*/
DWORD
CopyRegistrySubkeys2(
HKEY hKeyDest,
LPCTSTR lpszDestSubKeyName,
HKEY hKeySrc,
LPCTSTR lpszSrcSubKeyName
)
{
DWORD ec = ERROR_SUCCESS;
HKEY hKeyDestReal = NULL;
// Create destination Key
hKeyDestReal = OpenRegistryKey(
hKeyDest,
lpszDestSubKeyName,
TRUE, // create
KEY_WRITE);
if (!hKeyDestReal)
{
ec = GetLastError();
goto exit;
}
//
// copy subkeys recursively
//
ec = SHCopyKey(hKeySrc, lpszSrcSubKeyName, hKeyDestReal, 0);
if (ERROR_SUCCESS != ec)
{
goto exit;
}
exit:
if (NULL != hKeyDestReal)
{
RegCloseKey(hKeyDestReal);
}
return ec;
} // FaxCopyRegSubkeys
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// FixupDevice
//
// Purpose:
// This functions handles the adaptation of a device
// in the registry from the format used in SBS2000 to the format
// used by Server 2003 fax.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code otherwise
//
// Author:
// Mooly Beery (MoolyB) 18-Dec-2001
///////////////////////////////////////////////////////////////////////////////////////
BOOL FixupDevice(HKEY hKey, LPWSTR lpwstrKeyName, DWORD dwIndex, LPVOID lpContext)
{
WCHAR wszDeviceId[32] = {0};
DWORD dwRet = ERROR_SUCCESS;
BOOL bRet = TRUE;
DWORD dwDeviceId = 0;
HKEY hDevices = NULL;
HKEY hDevice = NULL;
DBG_ENTER(_T("FixupDevice"),dwRet);
if (lpwstrKeyName==NULL)
{
goto exit;
}
if (wcscmp(lpwstrKeyName,REGKEY_UNASSOC_EXTENSION_DATA)==0)
{
VERBOSE(DBG_MSG, _T("No migration for UnassociatedExtensionData"));
goto exit;
}
VERBOSE(DBG_MSG, _T("Migrating the %s device"),lpwstrKeyName);
// convert the key name from Hex to Decimal
dwDeviceId = wcstol(lpwstrKeyName,NULL,16);
if (dwDeviceId==0)
{
VERBOSE(SETUP_ERR, _T("converting the device ID to decimal failed"));
bRet = FALSE;
goto exit;
}
if (dwDeviceId>g_LastUniqueLineId)
{
g_LastUniqueLineId = dwDeviceId;
}
if (wsprintf(wszDeviceId,L"%010d",dwDeviceId)==0)
{
VERBOSE(SETUP_ERR, _T("wsprintf failed"));
bRet = FALSE;
goto exit;
}
// create the new device key
hDevices = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_DEVICES,TRUE,KEY_WRITE);
if (hDevices==NULL)
{
VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_FAX_DEVICES failed (ec=%ld)"),GetLastError());
bRet = FALSE;
goto exit;
}
// create a key under HKLM\Sw\Ms\Fax\Devices\wszDeviceId
hDevice = OpenRegistryKey(hDevices,wszDeviceId,TRUE,KEY_WRITE);
if (hDevice==NULL)
{
VERBOSE(SETUP_ERR, _T("OpenRegistryKey %s failed (ec=%ld)"),wszDeviceId,GetLastError());
bRet = FALSE;
goto exit;
}
// set the 'Permanent Lineid' REG_DWORD
if (!SetRegistryDword(hDevice,REGVAL_PERMANENT_LINEID,dwDeviceId))
{
VERBOSE(SETUP_ERR, _T("SetRegistryDword REGVAL_PERMANENT_LINEID failed (ec=%ld)"),GetLastError());
bRet = FALSE;
goto exit;
}
// create an entry under the service GUID for the device.
// and copy the rest of the setting to the new location
dwRet = CopyRegistrySubkeys2(hDevice, REGKEY_FAXSVC_DEVICE_GUID ,hKey,_T(""));
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("CopyRegistrySubkeys() failed, ec = %ld."), dwRet);
goto exit;
}
exit:
if (hDevices)
{
RegCloseKey(hDevices);
}
if (hDevice)
{
RegCloseKey(hDevice);
}
return bRet;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// FixupDevicesNode
//
// Purpose:
// This functions handles the adaptation of the devices
// in the registry from the format used in SBS2000 to the format
// used by Server 2003 fax.
// Each device is copied but the structure in the registry in
// a little different. specifically, the device data is kept
// under a GUID.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code otherwise
//
// Author:
// Mooly Beery (MoolyB) 18-Dec-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD FixupDevicesNode()
{
HKEY hFax = NULL;
DWORD dwRet = ERROR_SUCCESS;
DBG_ENTER(_T("FixupDevicesNode"),dwRet);
// enumerate all the devices, and for each, move its key under its GUID
dwRet = EnumerateRegistryKeys( HKEY_LOCAL_MACHINE,
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_DEVICES,
FALSE,
FixupDevice,
NULL);
VERBOSE(DBG_MSG, _T("For SBS 5.0 Server, enumerated %ld devices."), dwRet);
// write the LastUniqueLineId to HKLM\Sw\Ms\Fax.
hFax = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAXSERVER,TRUE,KEY_WRITE);
if (hFax==NULL)
{
dwRet = GetLastError();
VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_FAXSERVER failed (ec=%ld)"),dwRet);
return dwRet;
}
if (!SetRegistryDword(hFax,REGVAL_LAST_UNIQUE_LINE_ID,g_LastUniqueLineId+1))
{
dwRet = GetLastError();
VERBOSE(SETUP_ERR, _T("SetRegistryDword REGVAL_LAST_UNIQUE_LINE_ID failed (ec=%ld)"),dwRet);
return dwRet;
}
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// FixupDeviceProvider
//
// Purpose:
// This functions handles the adaptation of a device provider
// in the registry from the format used in SBS2000 to the format
// used by Server 2003 fax.
// The 'Microsoft Modem Device Provider' is not copied.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code otherwise
//
// Author:
// Mooly Beery (MoolyB) 18-Dec-2001
///////////////////////////////////////////////////////////////////////////////////////
BOOL FixupDeviceProvider(HKEY hKey, LPWSTR lpwstrKeyName, DWORD dwIndex, LPVOID lpContext)
{
DWORD dwRet = ERROR_SUCCESS;
BOOL bRet = TRUE;
HKEY hDeviceProviders = NULL;
DBG_ENTER(_T("FixupDeviceProvider"),dwRet);
if (lpwstrKeyName==NULL)
{
goto exit;
}
if (wcscmp(lpwstrKeyName,REGKEY_MODEM_PROVIDER)==0)
{
VERBOSE(DBG_MSG, _T("No migration for the Microsoft Modem Device Provider"));
goto exit;
}
VERBOSE(DBG_MSG, _T("Migrating the %s Device provider"),lpwstrKeyName);
// create a key under HKLM\Sw\Ms\Fax\Device Providers
hDeviceProviders = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_DEVICE_PROVIDER_KEY,TRUE,KEY_WRITE);
if (hDeviceProviders==NULL)
{
VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_DEVICE_PROVIDER_KEY failed (ec=%ld)"),GetLastError());
bRet = FALSE;
goto exit;
}
// create a key under HKLM\Sw\Ms\Fax\Device Providers\name
dwRet = CopyRegistrySubkeys2(hDeviceProviders,lpwstrKeyName,hKey,_T(""));
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("CopyRegistrySubkeys() failed, ec = %ld."), dwRet);
goto exit;
}
exit:
if (hDeviceProviders)
{
RegCloseKey(hDeviceProviders);
}
return bRet;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// FixupDeviceProvidersNode
//
// Purpose:
// This functions handles the adaptation of the device providers
// in the registry from the format used in SBS2000 to the format
// used by Server 2003 fax.
// The 'Microsoft Modem Device Provider' is not copied and as for
// other FSPs, the key under which they are registered is changed
// to hold the GUID of the FSP.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code otherwise
//
// Author:
// Mooly Beery (MoolyB) 18-Dec-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD FixupDeviceProvidersNode()
{
DWORD dwRet = ERROR_SUCCESS;
DBG_ENTER(_T("FixupDeviceProvidersNode"),dwRet);
// enumerate the rest of the FSPs, and for each, move its key under its GUID
dwRet = EnumerateRegistryKeys( HKEY_LOCAL_MACHINE,
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_DEVICE_PROVIDERS,
FALSE,
FixupDeviceProvider,
NULL);
VERBOSE(DBG_MSG, _T("For SBS 5.0 Server, enumerated %ld device providers."), dwRet);
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// FixupRoutingExtension
//
// Purpose:
// This functions handles the adaptation of a routing extension
// in the registry from the format used in SBS2000 to the format
// used by Server 2003 fax.
// The 'Microsoft Routing Extension' is not copied and as for
// other Routing extensions, they're copied as is.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code otherwise
//
// Author:
// Mooly Beery (MoolyB) 18-Dec-2001
///////////////////////////////////////////////////////////////////////////////////////
BOOL FixupRoutingExtension(HKEY hKey, LPWSTR lpwstrKeyName, DWORD dwIndex, LPVOID lpContext)
{
DWORD dwRet = ERROR_SUCCESS;
BOOL bRet = TRUE;
HKEY hRoutingExtensions = NULL;
DBG_ENTER(_T("FixupRoutingExtension"),dwRet);
if (lpwstrKeyName==NULL)
{
goto exit;
}
if (wcscmp(lpwstrKeyName,REGKEY_ROUTING_EXTENSION)==0)
{
VERBOSE(DBG_MSG, _T("No migration for the Microsoft Routing Extension"));
goto exit;
}
VERBOSE(DBG_MSG, _T("Migrating the %s Routing extension"),lpwstrKeyName);
// create a key under HKLM\Sw\Ms\Fax\Routing Extensions
hRoutingExtensions = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_ROUTING_EXTENSION_KEY,TRUE,KEY_WRITE);
if (hRoutingExtensions==NULL)
{
VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_ROUTING_EXTENSIONS failed (ec=%ld)"),GetLastError());
bRet = FALSE;
goto exit;
}
// create a key under HKLM\Sw\Ms\Fax\Routing Extensions\name
dwRet = CopyRegistrySubkeys2(hRoutingExtensions,lpwstrKeyName,hKey,_T(""));
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("CopyRegistrySubkeys() failed, ec = %ld."), dwRet);
goto exit;
}
exit:
if (hRoutingExtensions)
{
RegCloseKey(hRoutingExtensions);
}
return bRet;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// FixupRoutingExtensionsNode
//
// Purpose:
// This functions handles the adaptation of the routing extension
// in the registry from the format used in SBS2000 to the format
// used by Server 2003 fax.
// The 'Microsoft Routing Extension' is not copied to the destination.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code otherwise
//
// Author:
// Mooly Beery (MoolyB) 18-Dec-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD FixupRoutingExtensionsNode()
{
DWORD dwRet = ERROR_SUCCESS;
DBG_ENTER(_T("FixupRoutingExtensionsNode"),dwRet);
// enumerate the rest of the Routing Extension, and for each decide whether to copy or not.
dwRet = EnumerateRegistryKeys( HKEY_LOCAL_MACHINE,
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_ROUTING_EXTENSIONS,
FALSE,
FixupRoutingExtension,
NULL);
VERBOSE(DBG_MSG, _T("For SBS 5.0 Server, enumerated %ld routing extensions."), dwRet);
return ERROR_SUCCESS;
}
struct REG_KEY_PAIR
{
LPCTSTR lpctstrSourceKey;
LPCTSTR lpctstrDestinationKey;
} g_RegKeyPairs[] =
{
{ REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_ACTIVITY_LOG_CONFIG,
REGKEY_FAXSERVER _T("\\") REGKEY_ACTIVITY_LOG_CONFIG
},
{ REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_DEVICES _T("\\") REGKEY_UNASSOC_EXTENSION_DATA,
REGKEY_FAXSERVER _T("\\") REGKEY_DEVICES _T("\\") REGKEY_UNASSOC_EXTENSION_DATA
},
{
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_LOGGING,
REGKEY_FAXSERVER _T("\\") REGKEY_LOGGING
},
{
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_ARCHIVE_INBOX_CONFIG,
REGKEY_FAXSERVER _T("\\") REGKEY_ARCHIVE_INBOX_CONFIG
},
{
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_OUTBOUND_ROUTING,
REGKEY_FAXSERVER _T("\\") REGKEY_OUTBOUND_ROUTING
},
{
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_RECEIPTS_CONFIG,
REGKEY_FAXSERVER _T("\\") REGKEY_RECEIPTS_CONFIG
},
{
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_SECURITY_CONFIG,
REGKEY_FAXSERVER _T("\\") REGKEY_SECURITY_CONFIG
},
{
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_ARCHIVE_SENTITEMS_CONFIG,
REGKEY_FAXSERVER _T("\\") REGKEY_ARCHIVE_SENTITEMS_CONFIG
},
{
REGKEY_SBS2000_FAX_BACKUP _T("\\") REGKEY_TAPIDEVICES_CONFIG,
REGKEY_FAXSERVER _T("\\") REGKEY_TAPIDEVICES_CONFIG
}
};
const INT iCopyKeys = sizeof(g_RegKeyPairs)/sizeof(g_RegKeyPairs[0]);
LPCTSTR lpctstrValuesToCopy[] =
{
REGVAL_BRANDING,
REGVAL_DIRTYDAYS,
REGVAL_RETRIES,
REGVAL_RETRYDELAY,
REGVAL_SERVERCP,
REGVAL_STARTCHEAP,
REGVAL_STOPCHEAP,
REGVAL_USE_DEVICE_TSID
};
const INT iCopyValues = sizeof(lpctstrValuesToCopy)/sizeof(lpctstrValuesToCopy[0]);
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// fxocUpg_MoveRegistry
//
// Purpose:
// When a machine running SBS2000 server was upgraded to Windows Server 2003
// we migrate the existing registry from SBS to the fax service.
// For most registry entries, the existing format is still compatible with
// the format used by SBS2000 so we just 'move' the registry around from
// one place to the other.
// This function is responsible for moving the following subkeys under Fax:
// ActivityLogging
// Device Providers\<any other than 'Microsoft Modem Device Provider'>
// Devices\UnassociatedExtensionData
// Logging
// Inbox
// Outbound Routing
// Receipts
// Routing Extensions\<any other than 'Microsoft Routing Extension'>
// Security
// SentItems
// TAPIDevices
//
// After moving the registry, some fixup to the registry takes place in order
// to make modifications from the format used in SBS2000 to the one used
// in Server 2003 Fax.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code otherwise
//
// Author:
// Mooly Beery (MoolyB) 17-Dec-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD fxocUpg_MoveRegistry(void)
{
INT iCount = 0;
DWORD dwRet = NO_ERROR;
HKEY hDotNetFax = NULL;
HKEY hSbsFax = NULL;
DBG_ENTER(_T("fxocUpg_MoveRegistry"),dwRet);
if ( !(prv_Data.dwFaxInstalledPriorUpgrade & FXSTATE_SBS5_SERVER) )
{
VERBOSE(DBG_MSG, _T("SBS2000 was not installed, nothing to migrate"));
goto exit;
}
// Share the printer (unless printer sharing rule was specified in unattended file)
if (IsFaxShared() && !fxUnatnd_IsPrinterRuleDefined())
{
VERBOSE(DBG_MSG, _T("SBS2000 was installed, sharing printer"));
fxocPrnt_SetFaxPrinterShared(TRUE);
}
// first, we copy all the above mentioned registry from HKLM\\Sw\\Ms\\SharedFax to HKLM\\Sw\\Ms\\Fax
for (iCount=0; iCount<iCopyKeys; iCount++)
{
VERBOSE(DBG_MSG,
_T("Copying %s from %s."),
g_RegKeyPairs[iCount].lpctstrDestinationKey,
g_RegKeyPairs[iCount].lpctstrSourceKey );
dwRet = CopyRegistrySubkeys2(
HKEY_LOCAL_MACHINE, g_RegKeyPairs[iCount].lpctstrDestinationKey,
HKEY_LOCAL_MACHINE, g_RegKeyPairs[iCount].lpctstrSourceKey);
if (dwRet == ERROR_FILE_NOT_FOUND)
{
// Some reg keys may not exist. For example, TAPIDevices is created
// after first use only. So, don't fail on this error.
VERBOSE(DBG_WARNING, _T("g_RegKeyPairs[iCount].lpctstrSourceKey was not found, continuing"), g_RegKeyPairs[iCount].lpctstrSourceKey);
}
else if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("CopyRegistrySubkeys() failed, ec = %ld."), dwRet);
goto exit;
}
}
// second, copy specific values
hDotNetFax = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAXSERVER,TRUE,KEY_WRITE);
if (hDotNetFax==NULL)
{
dwRet = GetLastError();
VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_FAXSERVER failed (ec=%ld)"),dwRet);
goto exit;
}
hSbsFax = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_SBS2000_FAX_BACKUP,TRUE,KEY_READ);
if (hSbsFax==NULL)
{
dwRet = GetLastError();
VERBOSE(SETUP_ERR, _T("OpenRegistryKey REGKEY_SBS2000_FAX_BACKUP failed (ec=%ld)"),dwRet);
goto exit;
}
for (iCount=0; iCount<iCopyValues; iCount++)
{
DWORD dwVal = 0;
VERBOSE(DBG_MSG,_T("Copying %s."),lpctstrValuesToCopy[iCount]);
dwVal = GetRegistryDword(hSbsFax,lpctstrValuesToCopy[iCount]);
if (!SetRegistryDword(hDotNetFax,lpctstrValuesToCopy[iCount],dwVal))
{
dwRet = GetLastError();
VERBOSE(SETUP_ERR, _T("SetRegistryDword %s failed (ec=%ld)"),lpctstrValuesToCopy[iCount],dwRet);
goto exit;
}
}
// now, we have to fixup items that are not compatible
dwRet = FixupDeviceProvidersNode();
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("FixupDeviceProvidersNode() failed, ec = %ld."), dwRet);
goto exit;
}
dwRet = FixupDevicesNode();
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("FixupDevicesNode() failed, ec = %ld."), dwRet);
goto exit;
}
dwRet = FixupRoutingExtensionsNode();
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("FixupRoutingExtensionsNode() failed, ec = %ld."), dwRet);
goto exit;
}
// Set security on Inbox, SentItems and ActivityLog dirs
dwRet = SetDirSecurityFromReg(REGKEY_SOFTWARE TEXT("\\") REGKEY_ACTIVITY_LOG_CONFIG, REGVAL_ACTIVITY_LOG_DB, SD_FAX_FOLDERS);
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
goto exit;
}
dwRet = SetDirSecurityFromReg(REGKEY_SOFTWARE TEXT("\\") REGKEY_ARCHIVE_SENTITEMS_CONFIG, REGVAL_ARCHIVE_FOLDER, SD_FAX_FOLDERS);
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
goto exit;
}
dwRet = SetDirSecurityFromReg(REGKEY_SOFTWARE TEXT("\\") REGKEY_ARCHIVE_INBOX_CONFIG, REGVAL_ARCHIVE_FOLDER, SD_FAX_FOLDERS);
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
goto exit;
}
// last, let's delete the SharedFaxBackup key from the registry.
if (!DeleteRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_SBS2000_FAX_BACKUP))
{
dwRet = GetLastError();
VERBOSE(DBG_WARNING, _T("DeleteRegistryKey() failed, ec = %ld."), dwRet);
goto exit;
}
exit:
if (hSbsFax)
{
RegCloseKey(hSbsFax);
}
if (hDotNetFax)
{
RegCloseKey(hDotNetFax);
}
return dwRet;
}