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
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;
|
|
}
|