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.
 
 
 
 
 
 

683 lines
24 KiB

/*++
migrate.c
Copyright (c) 1997 Microsoft Corporation
This module performs Windows 95 to Windows XP fax migration.
Specifically, this file contains the Windows XP side of migration...
Author:
Brian Dewey (t-briand) 1997-7-14
Mooly Beery (moolyb) 2000-12-20
--*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <setupapi.h>
#include <shellapi.h>
#include <shlwapi.h>
#include <wchar.h>
#include <tchar.h>
#include "migrate.h" // Contains prototypes & version information.
#include "resource.h" // Resources.
#include <faxutil.h>
#include <faxreg.h>
// ------------------------------------------------------------
// Global data
// Wide names of the working & source directories.
static WCHAR lpWorkingDir[MAX_PATH];
HINSTANCE hinstMigDll;
static LPCTSTR REG_KEY_AWF = TEXT("SOFTWARE\\Microsoft\\At Work Fax");
// ------------------------------------------------------------
// Prototypes
static DWORD MigrateDevicesNT(IN HINF UnattendFile);
static DWORD CopyCoverPageFilesNT();
#define prv_DEBUG_FILE_NAME _T("%windir%\\FaxSetup.log")
extern "C"
BOOL WINAPI
DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
{
SET_DEBUG_PROPERTIES(DEBUG_ALL_MSG,DBG_PRNT_ALL_TO_FILE,DEBUG_CONTEXT_ALL);
OPEN_DEBUG_FILE(prv_DEBUG_FILE_NAME);
{
DEBUG_FUNCTION_NAME(_T("DllMain"));
if (dwReason == DLL_PROCESS_ATTACH)
{
DebugPrintEx(DEBUG_MSG,"Migration DLL attached.");
if (!DisableThreadLibraryCalls(hinstDll))
{
DebugPrintEx(DEBUG_ERR,"DisableThreadLibraryCalls failed (ec=%d)",GetLastError());
}
hinstMigDll = hinstDll;
}
return TRUE;
}
}
// InitializeNT
//
// This routine performs NT-side initialization.
//
// Parameters:
// Documented below.
//
// Returns:
// ERROR_SUCCESS.
//
// Author:
// Brian Dewey (t-briand) 1997-7-14
LONG
CALLBACK
InitializeNT
(
IN LPCWSTR WorkingDirectory, // Working directory for temporary files.
IN LPCWSTR SourceDirectory, // Directory of winNT source.
LPVOID Reserved // It's reserved.
)
{
int iErr = 0;
DEBUG_FUNCTION_NAME(_T("InitializeNT"));
DebugPrintEx(DEBUG_MSG,"Working directory is %s",WorkingDirectory);
DebugPrintEx(DEBUG_MSG,"Source directory is %s",SourceDirectory);
wcscpy(lpWorkingDir, WorkingDirectory);
return ERROR_SUCCESS; // A very confused return value.
}
// MigrateUserNT
//
// Sets up user information.
//
// Parameters:
// Documented below.
//
// Returns:
// ERROR_SUCCESS.
//
// Author:
// Brian Dewey (t-briand) 1997-7-14
LONG
CALLBACK
MigrateUserNT
(
IN HINF UnattendInfHandle, // Access to the unattend.txt file.
IN HKEY UserRegHandle, // Handle to registry settings for user.
IN LPCWSTR UserName, // Name of the user.
LPVOID Reserved
)
{
// our task: copy entries from szInfFileName to the registry.
LPTSTR lpNTOptions = TEXT("Software\\Microsoft\\Fax\\UserInfo");
HKEY hReg; // Registry key for user.
LPCTSTR alpKeys[] =
{ // This array defines what keys will be
TEXT("Address"), // copied from faxuser.ini into the registry.
TEXT("Company"),
TEXT("Department"),
TEXT("FaxNumber"),
TEXT("FullName"),
TEXT("HomePhone"),
TEXT("Mailbox"),
TEXT("Office"),
TEXT("OfficePhone"),
TEXT("Title")
};
INT iErr = 0;
UINT iCount, iMax; // used for looping through all the sections.
UINT i; // Used for converting doubled ';' to CR/LF pairs.
TCHAR szValue[MAX_PATH];
TCHAR szInfFileNameRes[MAX_PATH];
TCHAR szWorkingDirectory[MAX_PATH];
TCHAR szUser[MAX_PATH]; // TCHAR representation of the user name.
LONG lError; // Holds a returned error code.
DEBUG_FUNCTION_NAME(_T("MigrateUserNT"));
if(UserName == NULL)
{
// NULL means the logon user.
_tcscpy(szUser, lpLogonUser);// Get the logon user name for faxuser.ini
}
else
{
// We need to convert the wide UserName to the narrow szUser.
WideCharToMultiByte(
CP_ACP, // Convert to ANSI.
0, // No flags.
UserName, // The wide char set.
-1, // Null-terminated string.
szUser, // Holds the converted string.
sizeof(szUser), // Size of this buffer...
NULL, // Use default unmappable character.
NULL // I don't need to know if I used the default.
);
}
DebugPrintEx(DEBUG_MSG,"Migrating user '%s'.",szUser);
if (RegCreateKeyEx( UserRegHandle,
lpNTOptions,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hReg,
NULL)!=ERROR_SUCCESS)
{
// All I'm allowed to do is return obscure error codes...
// However, unless there's a hardware failure, I'm supposed to say
// everything's OK.
DebugPrintEx(DEBUG_ERR,"RegCreateKeyEx %s failed (ec=%d)",lpNTOptions,GetLastError());
return ERROR_SUCCESS;
}
iMax = sizeof(alpKeys) / sizeof(LPCTSTR);
iErr = WideCharToMultiByte( CP_ACP, // Convert to ANSI.
0, // No flags.
lpWorkingDir, // The wide char set.
-1, // Null-terminated string.
szWorkingDirectory, // Holds the converted string.
sizeof(szWorkingDirectory), // Size of this buffer...
NULL, // Use default unmappable character.
NULL); // I don't need to know if I used the default.
if (iErr==0)
{
DebugPrintEx(DEBUG_ERR,"WideCharToMultiByte failed (ec=%d)",iErr);
}
_stprintf(szInfFileNameRes, TEXT("%s\\migrate.inf"), szWorkingDirectory);
ExpandEnvironmentStrings(szInfFileNameRes, szInfFileName, ARR_SIZE(szInfFileName));
DebugPrintEx(DEBUG_MSG,"Reading from file %s.",szInfFileName);
for (iCount = 0; iCount < iMax; iCount++)
{
GetPrivateProfileString(szUser,
alpKeys[iCount],
TEXT(""),
szValue,
sizeof(szValue),
szInfFileName);
// If there was a CR/LF pair, the w95 side of things converted it
// to a doubled semicolon. So I'm going to look for doubled semicolons
// and convert them to CR/LF pairs.
i = 0;
while (szValue[i] != _T('\0'))
{
if ((szValue[i] == _T(';')) && (szValue[i+1] == _T(';')))
{
// Found a doubled semicolon.
szValue[i] = '\r';
szValue[i+1] = '\n';
DebugPrintEx(DEBUG_MSG,"Doing newline translation.");
}
i++;
}
lError = RegSetValueEx(hReg,
alpKeys[iCount],
0,
REG_SZ,
LPBYTE(szValue),
_tcslen(szValue)+1);
if (lError!=ERROR_SUCCESS)
{
DebugPrintEx(DEBUG_ERR,"RegSetValueEx %s failed (ec=%d)",alpKeys[iCount],GetLastError());
return lError;
}
DebugPrintEx(DEBUG_MSG,"%s = %s", alpKeys[iCount], szValue);
}
RegCloseKey(hReg);
return ERROR_SUCCESS; // A very confused return value.
}
// MigrateSystemNT
//
// Updates the system registry to associate 'awdvstub.exe' with the
// AWD extension.
//
// Parameters:
// Documented below.
//
// Returns:
// ERROR_SUCCESS.
//
// Author:
// Brian Dewey (t-briand) 1997-7-14
LONG
CALLBACK
MigrateSystemNT
(
IN HINF UnattendInfHandle, // Access to the unattend.txt file.
LPVOID Reserved
)
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR szExeFileName[MAX_PATH];
WCHAR szWindowsDir[MAX_PATH];
WCHAR szDestFile[MAX_PATH];
DEBUG_FUNCTION_NAME(_T("MigrateSystemNT"));
// first, copy 'awdvstub.exe' to %SystemRoot%\system32.
if (!GetWindowsDirectoryW(szWindowsDir, MAX_PATH))
{
DebugPrintEx(DEBUG_ERR, "GetWindowsDirectoryW failed (ec=%d)", GetLastError());
return GetLastError ();
}
swprintf(szExeFileName, L"%s\\%s", lpWorkingDir, L"awdvstub.exe");
swprintf(szDestFile, L"%s\\system32\\%s", szWindowsDir, L"awdvstub.exe");
if (!CopyFileW( szExeFileName,
szDestFile,
FALSE))
{
DebugPrintEx(DEBUG_ERR,"CopyFileW failed (ec=%d)",GetLastError());
}
else
{
DebugPrintEx(DEBUG_MSG,"CopyFileW success");
}
if (MigrateDevicesNT(UnattendInfHandle)!=ERROR_SUCCESS)
{
DebugPrintEx(DEBUG_ERR,"MigrateDevicesNT failed (ec=%d)",GetLastError());
}
if (CopyCoverPageFilesNT()!=ERROR_SUCCESS)
{
DebugPrintEx(DEBUG_ERR,"CopyCoverPageFilesNT failed (ec=%d)",GetLastError());
}
return ERROR_SUCCESS; // A very confused return value.
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// MigrateDevicesNT
//
// Purpose: Get the active device's settings from the INF
// Set the device info into the FAX key under HKLM
// verify there's only one device, otherwise do not migrate settings
//
// Params:
// IN HINF UnattendFile - handle to the answer file
//
// Return Value:
// Win32 Error code
//
// Author:
// Mooly Beery (MoolyB) 13-dec-2000
///////////////////////////////////////////////////////////////////////////////////////
typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXCONNECTFAXSERVERW) (LPCWSTR MachineName,LPHANDLE FaxHandle);
typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXENUMPORTSEXW) (HANDLE hFaxHandle,PFAX_PORT_INFO_EXW* ppPorts,PDWORD lpdwNumPorts);
typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXSETPORTEXW) (HANDLE hFaxHandle,DWORD dwDeviceId,PFAX_PORT_INFO_EXW pPortInfo);
typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXCLOSE) (HANDLE FaxHandle);
typedef WINFAXAPI VOID (WINAPI *FUNC_FAXFREEBUFFER) (LPVOID Buffer);
typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXGETOUTBOXCONFIGURATION) (HANDLE hFaxHandle,PFAX_OUTBOX_CONFIG *ppOutboxCfg);
typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXSETOUTBOXCONFIGURATION) (HANDLE hFaxHandle,CONST PFAX_OUTBOX_CONFIG pOutboxCfg);
static DWORD MigrateDevicesNT(IN HINF UnattendFile)
{
DWORD dwErr = ERROR_SUCCESS;
HMODULE hModule = 0;
HANDLE hFaxHandle = NULL;
CHAR szLocalID[MAX_PATH] = {0};
WCHAR wszLocalID[MAX_PATH] = {0};
CHAR szAnswerMode[32] = {0};
CHAR szRetries[32] = {0};
CHAR szRetriesDelay[32] = {0};
CHAR szNumRings[32] = {0};
FUNC_FAXCONNECTFAXSERVERW pfFaxConnectFaxServerW = NULL;
FUNC_FAXENUMPORTSEXW pfFaxEnumPortsExW = NULL;
FUNC_FAXSETPORTEXW pfFaxSetPortExW = NULL;
FUNC_FAXCLOSE pfFaxClose = NULL;
FUNC_FAXFREEBUFFER pfFaxFreeBuffer = NULL;
FUNC_FAXGETOUTBOXCONFIGURATION pfFaxGetOutboxConfiguration = NULL;
FUNC_FAXSETOUTBOXCONFIGURATION pfFaxSetOutboxConfiguration = NULL;
PFAX_PORT_INFO_EXW pFaxPortInfoExW = NULL;
PFAX_OUTBOX_CONFIG pFaxOutboxConfig = NULL;
DWORD dwNumPorts = 0;
INT iNumRings = 0;
INT iAnswerMode = 0;
DEBUG_FUNCTION_NAME(_T("MigrateDevicesNT"));
// load the FXSAPI.DLL
hModule = LoadLibrary(FAX_API_MODULE_NAME);
if (hModule==NULL)
{
DebugPrintEx(DEBUG_ERR,"LoadLibrary failed (ec=%d)",GetLastError());
goto exit;
}
// get the following functions:
// 1. FaxConnectFaxServer
// 2. FaxEnumPortsEx
// 3. FaxSetPortEx
// 4. FaxClose
// 5. FaxFreeBuffer
// 6. FaxGetOutboxConfiguration
// 7. FaxSetOutboxConfiguration
pfFaxConnectFaxServerW = (FUNC_FAXCONNECTFAXSERVERW)GetProcAddress(hModule,"FaxConnectFaxServerW");
if (pfFaxConnectFaxServerW==NULL)
{
DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxConnectFaxServerW failed (ec=%d)",GetLastError());
goto exit;
}
pfFaxEnumPortsExW = (FUNC_FAXENUMPORTSEXW)GetProcAddress(hModule,"FaxEnumPortsExW");
if (pfFaxEnumPortsExW==NULL)
{
DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxEnumPortsExW failed (ec=%d)",GetLastError());
goto exit;
}
pfFaxSetPortExW = (FUNC_FAXSETPORTEXW)GetProcAddress(hModule,"FaxSetPortExW");
if (pfFaxSetPortExW==NULL)
{
DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxSetPortExW failed (ec=%d)",GetLastError());
goto exit;
}
pfFaxClose = (FUNC_FAXCLOSE)GetProcAddress(hModule,"FaxClose");
if (pfFaxClose==NULL)
{
DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxClose failed (ec=%d)",GetLastError());
goto exit;
}
pfFaxFreeBuffer = (FUNC_FAXFREEBUFFER)GetProcAddress(hModule,"FaxFreeBuffer");
if (pfFaxFreeBuffer==NULL)
{
DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxFreeBuffer failed (ec=%d)",GetLastError());
goto exit;
}
pfFaxGetOutboxConfiguration = (FUNC_FAXGETOUTBOXCONFIGURATION)GetProcAddress(hModule,"FaxGetOutboxConfiguration");
if (pfFaxGetOutboxConfiguration==NULL)
{
DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxGetOutboxConfiguration failed (ec=%d)",GetLastError());
goto exit;
}
pfFaxSetOutboxConfiguration = (FUNC_FAXSETOUTBOXCONFIGURATION)GetProcAddress(hModule,"FaxSetOutboxConfiguration");
if (pfFaxSetOutboxConfiguration==NULL)
{
DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxSetOutboxConfiguration failed (ec=%d)",GetLastError());
goto exit;
}
// try to connect to the fax server
if (!(*pfFaxConnectFaxServerW)(NULL,&hFaxHandle))
{
DebugPrintEx(DEBUG_ERR,"pfFaxConnectFaxServerW failed (ec=%d)",GetLastError());
goto exit;
}
// call EnumPortsEx
if (!(*pfFaxEnumPortsExW)(hFaxHandle,&pFaxPortInfoExW,&dwNumPorts))
{
DebugPrintEx(DEBUG_ERR,"pfFaxConnectFaxServerW failed (ec=%d)",GetLastError());
goto exit;
}
if (dwNumPorts==0)
{
DebugPrintEx(DEBUG_MSG,"No devices are installed, no migration");
goto next;
}
else if (dwNumPorts>1)
{
DebugPrintEx(DEBUG_MSG,"%d devices are installed, no migration",dwNumPorts);
goto next;
}
// we have one device, get its FAX_PORT_INFOW, modify it and call FaxSetPortW
// TSID
if (SetupGetLineText( NULL,
UnattendFile,
"FAX",
INF_RULE_LOCAL_ID,
szLocalID,
sizeof(szLocalID),
NULL))
{
if (MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
szLocalID,
-1,
wszLocalID,
sizeof(wszLocalID)/sizeof(WCHAR)
))
{
pFaxPortInfoExW[0].lptstrTsid = wszLocalID;
pFaxPortInfoExW[0].lptstrCsid = wszLocalID;
DebugPrintEx(DEBUG_MSG,"new TSID & CSID is %s",szLocalID);
}
}
else
{
DebugPrintEx(DEBUG_ERR,"SetupGetLineText TSID failed (ec=%d)",GetLastError());
}
// Rings
if (SetupGetLineText( NULL,
UnattendFile,
"FAX",
INF_RULE_NUM_RINGS,
szNumRings,
sizeof(szNumRings),
NULL))
{
iNumRings = atoi(szNumRings);
if (iNumRings)
{
pFaxPortInfoExW[0].dwRings = iNumRings;
DebugPrintEx(DEBUG_MSG,"new Rings is %d",iNumRings);
}
}
else
{
DebugPrintEx(DEBUG_ERR,"GetPrivateProfileString NumRings failed (ec=%d)",GetLastError());
}
// Answer mode
pFaxPortInfoExW[0].bSend = TRUE;
if (SetupGetLineText( NULL,
UnattendFile,
"FAX",
INF_RULE_ANSWER_MODE,
szAnswerMode,
sizeof(szAnswerMode),
NULL))
{
iAnswerMode = atoi(szAnswerMode);
switch (iAnswerMode)
{
case 0: break;
case 1: pFaxPortInfoExW[0].ReceiveMode = FAX_DEVICE_RECEIVE_MODE_MANUAL;
DebugPrintEx(DEBUG_MSG,"setting flags to manual Receive");
break;
case 2: pFaxPortInfoExW[0].ReceiveMode = FAX_DEVICE_RECEIVE_MODE_AUTO;
DebugPrintEx(DEBUG_MSG,"setting flags to auto Receive");
break;
default: pFaxPortInfoExW[0].ReceiveMode = FAX_DEVICE_RECEIVE_MODE_OFF;
DebugPrintEx(DEBUG_MSG,"strange AnswerMode, just send enabled");
break;
}
}
else
{
DebugPrintEx(DEBUG_ERR,"GetPrivateProfileString AnswerMode failed (ec=%d)",GetLastError());
}
// call FaxSetPort
if (!(*pfFaxSetPortExW)(hFaxHandle,pFaxPortInfoExW[0].dwDeviceID,&(pFaxPortInfoExW[0])))
{
DebugPrintEx(DEBUG_ERR,"pfFaxSetPortExW failed (ec=%d)",GetLastError());
goto exit;
}
next:
// get the Outbox configuration
if (!(*pfFaxGetOutboxConfiguration)(hFaxHandle,&pFaxOutboxConfig))
{
DebugPrintEx(DEBUG_ERR,"pfFaxGetOutboxConfiguration failed (ec=%d)",GetLastError());
goto exit;
}
// get the retries and retry delay from INF
if (SetupGetLineText( NULL,
UnattendFile,
"FAX",
"NumberOfRetries",
szRetries,
sizeof(szRetries),
NULL))
{
pFaxOutboxConfig->dwRetries = atoi(szRetries);
}
if (SetupGetLineText( NULL,
UnattendFile,
"FAX",
"TimeBetweenRetries",
szRetriesDelay,
sizeof(szRetriesDelay),
NULL))
{
pFaxOutboxConfig->dwRetryDelay = atoi(szRetriesDelay);
}
// now set the outbox configuration
if (!(*pfFaxSetOutboxConfiguration)(hFaxHandle,pFaxOutboxConfig))
{
DebugPrintEx(DEBUG_ERR,"pfFaxSetOutboxConfiguration failed (ec=%d)",GetLastError());
goto exit;
}
exit:
if (hFaxHandle)
{
if (pfFaxClose)
{
(*pfFaxClose)(hFaxHandle);
}
if (pFaxPortInfoExW)
{
if(pfFaxFreeBuffer)
{
(*pfFaxFreeBuffer)(pFaxPortInfoExW);
}
}
if (pFaxOutboxConfig)
{
if(pfFaxFreeBuffer)
{
(*pfFaxFreeBuffer)(pFaxOutboxConfig);
}
}
}
if (hModule)
{
FreeLibrary(hModule);
}
return dwErr;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// CopyCoverPageFilesNT
//
// Purpose: Copy all of the *.CPE files from the temporary
// directory to the server cover pages dir
//
// Params:
// None
//
// Return Value:
// Win32 Error code
//
// Author:
// Mooly Beery (MoolyB) 13-dec-2000
///////////////////////////////////////////////////////////////////////////////////////
DWORD CopyCoverPageFilesNT()
{
DWORD dwErr = ERROR_SUCCESS;
INT iErr = 0;
CHAR szServerCpDir[MAX_PATH] = {0};
CHAR szWorkingDirectory[MAX_PATH] = {0};
SHFILEOPSTRUCT fileOpStruct;
DEBUG_FUNCTION_NAME(_T("CopyCoverPageFiles9X"));
ZeroMemory(&fileOpStruct, sizeof(SHFILEOPSTRUCT));
// Get the server cover pages directory
if (!GetServerCpDir(NULL,szServerCpDir,sizeof(szServerCpDir)))
{
dwErr = GetLastError();
DebugPrintEx(DEBUG_ERR,"GetServerCpDir failed (ec=%d)",dwErr);
goto exit;
}
iErr = WideCharToMultiByte( CP_ACP, // Convert to ANSI.
0, // No flags.
lpWorkingDir, // The wide char set.
-1, // Null-terminated string.
szWorkingDirectory, // Holds the converted string.
sizeof(szWorkingDirectory), // Size of this buffer...
NULL, // Use default unmappable character.
NULL); // I don't need to know if I used the default.
if (iErr==0)
{
DebugPrintEx(DEBUG_ERR,"WideCharToMultiByte failed (ec=%d)",iErr);
goto exit;
}
strcat(szWorkingDirectory,"\\*.cpe");
fileOpStruct.hwnd = NULL;
fileOpStruct.wFunc = FO_MOVE;
fileOpStruct.pFrom = szWorkingDirectory;
fileOpStruct.pTo = szServerCpDir;
fileOpStruct.fFlags =
FOF_FILESONLY | // Perform the operation on files only if a wildcard file name (*.*) is specified.
FOF_NOCONFIRMMKDIR | // Do not confirm the creation of a new directory if the operation requires one to be created.
FOF_NOCONFIRMATION | // Respond with "Yes to All" for any dialog box that is displayed.
FOF_NORECURSION | // Only operate in the local directory. Don't operate recursively into subdirectories.
FOF_SILENT | // Do not display a progress dialog box.
FOF_NOERRORUI; // Do not display a user interface if an error occurs.
fileOpStruct.fAnyOperationsAborted = FALSE;
fileOpStruct.hNameMappings = NULL;
fileOpStruct.lpszProgressTitle = NULL;
DebugPrintEx(DEBUG_MSG,
TEXT("Calling to SHFileOperation from %s to %s."),
fileOpStruct.pFrom,
fileOpStruct.pTo);
if (SHFileOperation(&fileOpStruct))
{
dwErr = GetLastError();
DebugPrintEx(DEBUG_ERR,"SHFileOperation failed (ec: %ld)",dwErr);
goto exit;
}
exit:
return dwErr;
}