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.
 
 
 
 
 
 

1220 lines
45 KiB

//////////////////////////////////////////////////////////////////////////////
//
// File Name: fxUnatnd.cpp
//
// Abstract: Fax OCM Setup unattended file processing
//
// Environment: Windows XP / User Mode
//
// Copyright (c) 2000 Microsoft Corporation
//
// Revision History:
//
// Date: Developer: Comments:
// ----- ---------- ---------
// 27-Mar-2000 Oren Rosenbloom (orenr) Created
//////////////////////////////////////////////////////////////////////////////
#include "faxocm.h"
#pragma hdrstop
static DWORD SaveSettingsFromAnswerFile();
#define prv_VALID_BOOL_VALUE_YES _T("yes")
#define prv_VALID_BOOL_VALUE_NO _T("no")
#define prv_VALID_BOOL_VALUE_TRUE _T("true")
#define prv_VALID_BOOL_VALUE_FALSE _T("false")
#define prv_HKLM HKEY_LOCAL_MACHINE
#define prv_HKCU HKEY_CURRENT_USER
///////////////////////////////
// prv_GVAR
//
// This is used as temporary
// storage so that we can
// reference the individual
// fields in the prv_UnattendedRules
// table below.
//
static struct prv_GVAR
{
fxUnatnd_UnattendedData_t UnattendedData;
} prv_GVAR;
///////////////////////////////
// prv_UnattendedRule_t
//
// Structure used as a table
// entry below.
//
typedef struct prv_UnattendedRule_t
{
DWORD dwType;
const TCHAR *pszFromInfKeyName;
HKEY hKeyTo;
const TCHAR *pszToRegPath;
const TCHAR *pszToRegKey;
void *pData;
BOOL bValid;
} prv_UnattendedRule_t;
#define RULE_CSID _T("Csid")
#define RULE_TSID _T("Tsid")
#define RULE_RINGS _T("Rings")
#define RULE_SENDFAXES _T("SendFaxes")
#define RULE_RECEIVEFAXES _T("ReceiveFaxes")
#define RULE_SUPPRESSCONFIGURATIONWIZARD _T("SkipConfigWizardDeviceSettings")
// this is added here since this was the rule's name at the time we shipped XP.
#define RULE_SUPPRESSCONFIGWIZARD_LEGACY _T("SuppressConfigurationWizard")
//
#define RULE_ARCHIVEINCOMING _T("ArchiveIncoming")
#define RULE_ARCHIVEINCOMINGFOLDERNAME _T("ArchiveIncomingFolderName")
#define RULE_ARCHIVEOUTGOING _T("ArchiveOutgoing")
#define RULE_ARCHIVEFOLDERNAME _T("ArchiveFolderName")
#define RULE_ARCHIVEOUTGOINGFOLDERNAME _T("ArchiveOutgoingFolderName")
#define RULE_FAXUSERNAME _T("FaxUserName")
#define RULE_FAXUSERPASSWORD _T("FaxUserPassword")
#define RULE_SMTPNOTIFICATIONSENABLED _T("SmtpNotificationsEnabled")
#define RULE_SMTPSENDERADDRESS _T("SmtpSenderAddress")
#define RULE_SMTPSERVERADDRESS _T("SmtpServerAddress")
#define RULE_SMTPSERVERPORT _T("SmtpServerPort")
#define RULE_SMTPSERVERAUTHENTICATIONMECHANISM _T("SmtpServerAuthenticationMechanism")
#define RULE_FAXPRINTERNAME _T("FaxPrinterName")
#define RULE_FAXPRINTERSHARED _T("FaxPrinterIsShared")
#define RULE_ROUTETOPRINTER _T("RouteToPrinter")
#define RULE_ROUTEPRINTERNAME _T("RoutePrinterName")
#define RULE_ROUTETOEMAIL _T("RouteToEmail")
#define RULE_ROUTETOEMAILRECIPIENT _T("RouteToEmailRecipient")
#define RULE_ROUTETOFOLDER _T("RouteToFolder")
#define RULE_ROUTEFOLDERNAME _T("RouteFolderName")
#define ANSWER_ANONYMOUS _T("Anonymous")
#define ANSWER_BASIC _T("Basic")
#define ANSWER_WINDOWSSECURITY _T("WindowsSecurity")
///////////////////////////////
// prv_UnattendedRules
//
// Simply put, these rules describe
// what registry values to set
// based on keywords found in an
// unattended file.
//
// The format of these rules is
// self explanatory after looking
// at the structure definition above.
// Basically, we read in a value from
// the unattended file which is specified
// in the 'pszFromInfKeyName'. This is
// then stored in 'pData'. Once
// "SaveUnattendedData" is called, 'pData'
// is committed to the registry location
// specified by 'hKeyTo' and 'pszToRegPath'
// and 'pszToRegKey'.
//
static prv_UnattendedRule_t prv_UnattendedRules[] =
{
{REG_SZ, RULE_CSID, prv_HKLM, REGKEY_FAX_SETUP_ORIG, REGVAL_ROUTING_CSID, prv_GVAR.UnattendedData.szCSID, FALSE},
{REG_SZ, RULE_TSID, prv_HKLM, REGKEY_FAX_SETUP_ORIG, REGVAL_ROUTING_TSID, prv_GVAR.UnattendedData.szTSID, FALSE},
{REG_DWORD, RULE_RINGS, prv_HKLM, REGKEY_FAX_SETUP_ORIG, REGVAL_RINGS, &prv_GVAR.UnattendedData.dwRings, FALSE},
{REG_DWORD, RULE_SENDFAXES, NULL, NULL, NULL, &prv_GVAR.UnattendedData.dwSendFaxes, FALSE},
{REG_DWORD, RULE_RECEIVEFAXES, NULL, NULL, NULL, &prv_GVAR.UnattendedData.dwReceiveFaxes, FALSE},
// should we run the configuration wizard for this unattended installation
{REG_DWORD, RULE_SUPPRESSCONFIGURATIONWIZARD, prv_HKLM, REGKEY_FAX_CLIENT, REGVAL_CFGWZRD_DEVICE, &prv_GVAR.UnattendedData.dwSuppressConfigurationWizard, TRUE},
{REG_DWORD, RULE_SUPPRESSCONFIGWIZARD_LEGACY, prv_HKLM, REGKEY_FAX_CLIENT, REGVAL_CFGWZRD_DEVICE, &prv_GVAR.UnattendedData.dwSuppressConfigurationWizard, FALSE},
// Inbox configuration.
{REG_DWORD, RULE_ARCHIVEINCOMING, prv_HKLM, REGKEY_FAX_INBOX, REGVAL_ARCHIVE_USE, &prv_GVAR.UnattendedData.bArchiveIncoming, FALSE},
{REG_SZ, RULE_ARCHIVEINCOMINGFOLDERNAME, prv_HKLM, REGKEY_FAX_INBOX, REGVAL_ARCHIVE_FOLDER, prv_GVAR.UnattendedData.szArchiveIncomingDir, FALSE},
// save outgoing faxes in a directory.
{REG_DWORD, RULE_ARCHIVEOUTGOING, prv_HKLM, REGKEY_FAX_SENTITEMS, REGVAL_ARCHIVE_USE, &prv_GVAR.UnattendedData.bArchiveOutgoing, FALSE},
{REG_SZ, RULE_ARCHIVEFOLDERNAME, prv_HKLM, REGKEY_FAX_SENTITEMS, REGVAL_ARCHIVE_FOLDER, prv_GVAR.UnattendedData.szArchiveOutgoingDir, FALSE},
{REG_SZ, RULE_ARCHIVEOUTGOINGFOLDERNAME, prv_HKLM, REGKEY_FAX_SENTITEMS, REGVAL_ARCHIVE_FOLDER, prv_GVAR.UnattendedData.szArchiveOutgoingDir, FALSE},
// SMTP receipts and server configuration
{REG_SZ, RULE_FAXUSERNAME, prv_HKLM, REGKEY_FAX_RECEIPTS, REGVAL_RECEIPTS_USER, prv_GVAR.UnattendedData.szFaxUserName, FALSE},
{REG_BINARY, RULE_FAXUSERPASSWORD, prv_HKLM, REGKEY_FAX_RECEIPTS, REGVAL_RECEIPTS_PASSWORD, prv_GVAR.UnattendedData.szFaxUserPassword, FALSE},
{REG_DWORD, RULE_SMTPNOTIFICATIONSENABLED, NULL, NULL, NULL, &prv_GVAR.UnattendedData.bSmtpNotificationsEnabled, FALSE},
{REG_SZ, RULE_SMTPSENDERADDRESS, prv_HKLM, REGKEY_FAX_RECEIPTS, REGVAL_RECEIPTS_FROM, prv_GVAR.UnattendedData.szSmtpSenderAddress, FALSE},
{REG_SZ, RULE_SMTPSERVERADDRESS, prv_HKLM, REGKEY_FAX_RECEIPTS, REGVAL_RECEIPTS_SERVER, prv_GVAR.UnattendedData.szSmptServerAddress, FALSE},
{REG_DWORD, RULE_SMTPSERVERPORT, prv_HKLM, REGKEY_FAX_RECEIPTS, REGVAL_RECEIPTS_PORT, &prv_GVAR.UnattendedData.dwSmtpServerPort, FALSE},
{REG_SZ, RULE_SMTPSERVERAUTHENTICATIONMECHANISM, NULL, NULL, NULL, prv_GVAR.UnattendedData.szSmtpServerAuthenticationMechanism, FALSE},
// user information.
{REG_SZ, RULE_FAXPRINTERNAME, NULL, NULL, NULL, prv_GVAR.UnattendedData.szFaxPrinterName, FALSE},
{REG_DWORD, RULE_FAXPRINTERSHARED, prv_HKLM, REGKEY_FAX_SETUP, REGVAL_IS_SHARED_FAX_PRINTER, &prv_GVAR.UnattendedData.dwIsFaxPrinterShared, FALSE},
// route to printer information.
{REG_DWORD, RULE_ROUTETOPRINTER, NULL, NULL, NULL, &prv_GVAR.UnattendedData.bRouteToPrinter, FALSE},
{REG_BINARY, RULE_ROUTEPRINTERNAME, prv_HKLM, REGKEY_FAX_UNASS_DATA, REGVAL_RM_PRINTING_GUID, prv_GVAR.UnattendedData.szRoutePrinterName, FALSE},
// route to email information.
{REG_DWORD, RULE_ROUTETOEMAIL, NULL, NULL, NULL, &prv_GVAR.UnattendedData.bRouteToEmail, FALSE},
{REG_BINARY, RULE_ROUTETOEMAILRECIPIENT, prv_HKLM, REGKEY_FAX_UNASS_DATA, REGVAL_RM_EMAIL_GUID, prv_GVAR.UnattendedData.szRouteEmailName, FALSE},
// route to a specific directory
{REG_DWORD, RULE_ROUTETOFOLDER, NULL, NULL, NULL, &prv_GVAR.UnattendedData.bRouteToDir, FALSE},
{REG_BINARY, RULE_ROUTEFOLDERNAME, prv_HKLM, REGKEY_FAX_UNASS_DATA, REGVAL_RM_FOLDER_GUID, prv_GVAR.UnattendedData.szRouteDir, FALSE},
// Fax Applications uninstalled during Upgrade
{REG_DWORD, UNINSTALLEDFAX_INFKEY, NULL, NULL, NULL, &prv_GVAR.UnattendedData.dwUninstalledFaxApps, FALSE}
};
#define prv_NUM_UNATTENDED_RULES sizeof(prv_UnattendedRules) / sizeof(prv_UnattendedRules[0])
///////////////////////// Static Function Prototypes ///////////////////////
static BOOL prv_FindKeyName(const TCHAR *pszID,
prv_UnattendedRule_t **ppUnattendedKey);
static BOOL prv_SaveKeyValue(prv_UnattendedRule_t *pUnattendedKey,
TCHAR *pszValue);
///////////////////////////////
// fxUnatnd_Init
//
// Initialize the unattended
// subsystem
//
// Params:
// - void.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxUnatnd_Init(void)
{
prv_UnattendedRule_t *pUnattendedKey = NULL;
DWORD dwRes = NO_ERROR;
DBG_ENTER(_T("Init Unattended module"),dwRes);
memset(&prv_GVAR, 0, sizeof(prv_GVAR));
// this is always valid, and defaults to false.
if (prv_FindKeyName(RULE_SUPPRESSCONFIGURATIONWIZARD, &pUnattendedKey))
{
if (!prv_SaveKeyValue(pUnattendedKey,_T("1")))
{
CALL_FAIL (GENERAL_ERR, TEXT("prv_SaveKeyValue"), GetLastError());
pUnattendedKey->bValid = FALSE;
}
}
else
{
CALL_FAIL (GENERAL_ERR, TEXT("prv_FindKeyName RULE_SUPPRESSCONFIGURATIONWIZARD"), GetLastError());
}
return dwRes;
}
///////////////////////////////
// fxUnatnd_Term
//
// Terminate the unattended subsystem
//
// Params:
// - void.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxUnatnd_Term(void)
{
DWORD dwRes = NO_ERROR;
DBG_ENTER(_T("Term Unattended module"),dwRes);
return dwRes;
}
///////////////////////////////
// fxUnatnd_LoadUnattendedData
//
// Load the unattended data found
// in the unattended file according
// to the rules table above.
//
// Basically we look in the unattended
// file for the keywords in the rule
// table above, and read them into the
// passed in parameter.
//
// Params:
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxUnatnd_LoadUnattendedData()
{
DWORD dwReturn = NO_ERROR;
BOOL bSuccess = TRUE;
HINF hInf = faxocm_GetComponentInf();
HINF hUnattendInf = INVALID_HANDLE_VALUE;
OCMANAGER_ROUTINES *pHelpers = faxocm_GetComponentHelperRoutines();
INFCONTEXT Context;
prv_UnattendedRule_t *pUnattendedKey = NULL;
TCHAR szKeyName[255 + 1];
TCHAR szValue[255 + 1];
TCHAR szUnattendFile[MAX_PATH] = {0};
DBG_ENTER(_T("fxUnatnd_LoadUnattendedData"),dwReturn);
if ((hInf == NULL) || (hInf == INVALID_HANDLE_VALUE) || (pHelpers == NULL))
{
return ERROR_INVALID_PARAMETER;
}
faxocm_GetComponentUnattendFile(szUnattendFile,sizeof(szUnattendFile)/sizeof(szUnattendFile[0]));
hUnattendInf = SetupOpenInfFile (szUnattendFile, NULL, INF_STYLE_WIN4 | INF_STYLE_OLDNT, NULL);
if (hUnattendInf == INVALID_HANDLE_VALUE)
{
VERBOSE(SETUP_ERR,
_T("LoadUnattendData, Unattended ")
_T("mode, but could not get Unattended file INF ")
_T("handle. ec=%d"), GetLastError());
return NO_ERROR;
}
VERBOSE(DBG_MSG, _T("Succeded to open setup unattended mode file."));
if (dwReturn == NO_ERROR)
{
bSuccess = ::SetupFindFirstLine(hUnattendInf,
UNATTEND_FAX_SECTION,
NULL,
&Context);
if (bSuccess)
{
VERBOSE(DBG_MSG,
_T("Found '%s' section in unattended file, ")
_T("beginning unattended file processing"),
UNATTEND_FAX_SECTION);
while (bSuccess)
{
// get the keyname of the first line in the fax section of the
// INF file. (Note index #0 specified in the
// 'SetupGetStringField' API will actually get us the key name.
// Index 1 will be the first value found after the '=' sign.
memset(szKeyName, 0, sizeof(szKeyName));
bSuccess = ::SetupGetStringField(
&Context,
0,
szKeyName,
sizeof(szKeyName)/sizeof(TCHAR),
NULL);
if (bSuccess)
{
// find the key in our unattended table above.
pUnattendedKey = NULL;
bSuccess = prv_FindKeyName(szKeyName, &pUnattendedKey);
}
if (bSuccess)
{
VERBOSE(DBG_MSG, _T("Found '%s' key in 'Fax' section."), szKeyName);
//
// get the keyname's value. Notice now we get index #1
// which is the first value found after the '=' sign.
//
memset(szValue, 0, sizeof(szValue));
bSuccess = ::SetupGetStringField(
&Context,
1,
szValue,
sizeof(szValue)/sizeof(TCHAR),
NULL);
VERBOSE(DBG_MSG, _T("The value we read is : %s."), szValue);
}
if (bSuccess)
{
//
// save the keyname's value in the dataptr
//
bSuccess = prv_SaveKeyValue(pUnattendedKey, szValue);
}
// move to the next line in the unattended file fax section.
bSuccess = ::SetupFindNextLine(&Context, &Context);
}
}
else
{
dwReturn = GetLastError();
VERBOSE(DBG_WARNING, _T("::SetupFindFirstLine() failed, ec = %ld"), dwReturn);
}
}
SetupCloseInfFile(hUnattendInf);
return dwReturn;
}
///////////////////////////////
// fxUnatnd_SaveUnattendedData
//
// Commit the unattended data
// we read from the file to the
// registry.
//
// Params:
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxUnatnd_SaveUnattendedData()
{
DWORD dwReturn = NO_ERROR;
DWORD i = 0;
HKEY hKey = NULL;
DWORD dwDataSize = 0;
LRESULT lResult = ERROR_SUCCESS;
prv_UnattendedRule_t *pRule = NULL;
DWORD dwDisposition;
DBG_ENTER(_T("fxUnatnd_SaveUnattendedData"),dwReturn);
// Iterate through each unattended rule.
// If the hKeyTo is not NULL, then write the value of pData to the
// specified registry location.
for (i = 0; i < prv_NUM_UNATTENDED_RULES; i++)
{
pRule = &prv_UnattendedRules[i];
if ((pRule->hKeyTo != NULL) && (pRule->bValid))
{
lResult = ::RegCreateKeyEx(
pRule->hKeyTo, // handle to open key
pRule->pszToRegPath, // subkey name
0, // reserved
NULL, // class string
REG_OPTION_NON_VOLATILE, // special options
KEY_WRITE, // desired security access
NULL, // inheritance
&hKey, // key handle
&dwDisposition // disposition value buffer
);
if (lResult == ERROR_SUCCESS)
{
dwDataSize = 0;
if (pRule->dwType == REG_SZ ||
pRule->dwType == REG_BINARY) // Binary data must be NULL terminated.
{
dwDataSize = sizeof(TCHAR) * (StringSize((TCHAR*) pRule->pData));
// write the value to the registry.
lResult = ::RegSetValueEx(hKey,
pRule->pszToRegKey,
0,
pRule->dwType,
(BYTE*) pRule->pData,
dwDataSize);
}
else if (pRule->dwType == REG_DWORD)
{
dwDataSize = sizeof(DWORD);
// write the value to the registry.
lResult = ::RegSetValueEx(hKey,
pRule->pszToRegKey,
0,
pRule->dwType,
(BYTE*) &(pRule->pData),
dwDataSize);
}
else
{
VERBOSE(SETUP_ERR,
_T("SaveUnattendedData ")
_T("do not recognize data type = '%lu'"),
pRule->dwType);
}
if (ERROR_SUCCESS != lResult)
{
VERBOSE(SETUP_ERR,_T("RegSetValueEx failed (ec=%d). value name :%s"),lResult, pRule->pszToRegKey);
}
}
else
{
VERBOSE(SETUP_ERR,_T("RegCreateKeyEx failed (ec=%d). Key:%s"),lResult, pRule->pszToRegPath);
}
if (hKey)
{
::RegCloseKey(hKey);
}
}
}
// now save dynamic data...
lResult = SaveSettingsFromAnswerFile();
if (lResult!=ERROR_SUCCESS)
{
VERBOSE(SETUP_ERR,_T("SaveSettingsFromAnswerFile failed (ec=%d)"),GetLastError());
}
//
// Mark which Fax Applications were installed before the upgrade
//
prv_UnattendedRule_t* pUnattendedKey = NULL;
if ((prv_FindKeyName(UNINSTALLEDFAX_INFKEY, &pUnattendedKey)) && (pUnattendedKey->bValid))
{
fxocUpg_WhichFaxWasUninstalled((DWORD)(PtrToUlong(pUnattendedKey->pData)));
}
return dwReturn;
}
TCHAR* fxUnatnd_GetPrinterName()
{
TCHAR* retValue = NULL;
prv_UnattendedRule_t* pUnattendedKey = NULL;
if (prv_FindKeyName(
RULE_FAXPRINTERNAME,
&pUnattendedKey))
{
retValue = (TCHAR *) (pUnattendedKey->pData);
}
return retValue;
}
/*++
Return value:
TRUE - FaxPrinterIsShared was defined in answer file
FALSE - FaxPrinterIsShared was not defined in answer file
--*/
BOOL fxUnatnd_IsPrinterRuleDefined()
{
prv_UnattendedRule_t* pUnattendedKey = NULL;
return (prv_FindKeyName(RULE_FAXPRINTERSHARED,&pUnattendedKey) && (pUnattendedKey->bValid));
}
/*++
Return value:
TRUE - Printer should be shared (because FaxPrinterIsShared was defined
in answer file as true/etc.)
FALSE - Printer should not be shared (because FaxPrinterIsShared was defined in answer
file as false/etc., or because FaxPrinterIsShared was not defined at all)
--*/
BOOL fxUnatnd_GetIsPrinterShared()
{
prv_UnattendedRule_t* pUnattendedKey = NULL;
if (prv_FindKeyName(RULE_FAXPRINTERSHARED,&pUnattendedKey) && (pUnattendedKey->bValid))
{
return (BOOL)PtrToUlong(pUnattendedKey->pData);
}
return FALSE;
}
///////////////////////////////
// prv_FindKeyName
//
// Find specified key name in our table
//
// Params:
// - pszKeyName - key name to search for.
// - ppUnattendedKey - OUT - rule we found.
// Returns:
// - TRUE if we found the keyname
// - FALSE otherwise.
//
static BOOL prv_FindKeyName(const TCHAR *pszKeyName,
prv_UnattendedRule_t **ppUnattendedKey)
{
BOOL bFound = FALSE;
DWORD i = 0;
if ((pszKeyName == NULL) ||
(ppUnattendedKey == NULL))
{
return FALSE;
}
for (i = 0; (i < prv_NUM_UNATTENDED_RULES) && (!bFound); i++)
{
if (_tcsicmp(pszKeyName, prv_UnattendedRules[i].pszFromInfKeyName) == 0)
{
bFound = TRUE;
*ppUnattendedKey = &prv_UnattendedRules[i];
}
}
return bFound;
}
///////////////////////////////
// prv_SaveKeyValue
//
// Store the specified value
// with the specified rule
//
// Params:
// - pUnattendedKey - rule where the value will be stored
// - pszValue - value to store.
// Returns:
// - TRUE on success.
// - FALSE otherwise.
//
static BOOL prv_SaveKeyValue(prv_UnattendedRule_t *pUnattendedKey,
TCHAR *pszValue)
{
BOOL bSuccess = TRUE;
//DWORD dwBufferSize = 0;
DBG_ENTER(_T("prv_SaveKeyValue"), bSuccess);
if ((pUnattendedKey == NULL) ||
(pszValue == NULL))
{
return ERROR_INVALID_PARAMETER;
}
if (bSuccess)
{
switch (pUnattendedKey->dwType)
{
case REG_SZ:
case REG_BINARY: // binary data must be NULL terminated.
_tcsncpy((TCHAR*) pUnattendedKey->pData,
pszValue,
_MAX_PATH
);
break;
case REG_DWORD:
// check if we got a true/false, or yes/no.
if ((!_tcsicmp(pszValue, prv_VALID_BOOL_VALUE_YES)) ||
(!_tcsicmp(pszValue, prv_VALID_BOOL_VALUE_TRUE)))
{
pUnattendedKey->pData = (void*) TRUE;
}
else if ((!_tcsicmp(pszValue, prv_VALID_BOOL_VALUE_NO)) ||
(!_tcsicmp(pszValue, prv_VALID_BOOL_VALUE_FALSE)))
{
pUnattendedKey->pData = (void*) FALSE;
}
else
{
// assume the value if an integer.
pUnattendedKey->pData = ULongToPtr(_tcstoul(pszValue, NULL, 10));
}
break;
}
}
pUnattendedKey->bValid = TRUE;
return bSuccess;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// ConfigureSMTPFromAnswerFile
//
// Purpose: Get all the answers that are applicable for SMTP
// receipts and try to set the server configuration
//
// Params:
// HANDLE hFaxHandle - handle from FaxConnectFaxServer
//
// Return Value:
// Win32 Error code
//
// Author:
// Mooly Beery (MoolyB) 22-Apr-2001
///////////////////////////////////////////////////////////////////////////////////////
BOOL ConfigureSMTPFromAnswerFile(HANDLE hFaxHandle)
{
BOOL bRet = TRUE;
DWORD dwErr = NO_ERROR;
PFAX_RECEIPTS_CONFIGW pFaxReceiptsConfigW = NULL;
prv_UnattendedRule_t* pUnattendedKey = NULL;
DWORD dwSMTPAuthOption = 0xffffffff;
BOOL bAllowEmail = FALSE;
HKEY hKey = NULL;
DBG_ENTER(_T("ConfigureSMTPFromAnswerFile"),bRet);
// get SmtpServerAuthenticationMechanism
if ((prv_FindKeyName(RULE_SMTPSERVERAUTHENTICATIONMECHANISM,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
if (_tcsicmp((TCHAR*)pUnattendedKey->pData,ANSWER_ANONYMOUS)==0)
{
dwSMTPAuthOption = FAX_SMTP_AUTH_ANONYMOUS;
}
else if (_tcsicmp((TCHAR*)pUnattendedKey->pData,ANSWER_BASIC)==0)
{
dwSMTPAuthOption = FAX_SMTP_AUTH_BASIC;
}
else if (_tcsicmp((TCHAR*)pUnattendedKey->pData,ANSWER_WINDOWSSECURITY)==0)
{
dwSMTPAuthOption = FAX_SMTP_AUTH_NTLM;
}
}
// get SmtpNotificationsEnabled
if ((prv_FindKeyName(RULE_SMTPNOTIFICATIONSENABLED,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
bAllowEmail = TRUE;
}
if (NULL == hFaxHandle)
{
//
// No connection to the fax service.
// The unattended data is stored directly in the registry.
// Just add the data that could not be written in the general section of fxUnatnd_SaveUnattendedData()
// Open the Receipts registry key
hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_FAX_RECEIPTS, FALSE, KEY_READ | KEY_WRITE);
if (NULL == hKey)
{
VERBOSE(SETUP_ERR,_T("OpenRegistryKey failed (ec=%d)"),GetLastError());
goto exit;
}
// write the values to the registry
if (0xffffffff != dwSMTPAuthOption)
{
// write the value to the registry.
if (!SetRegistryDword(hKey,
REGVAL_RECEIPTS_SMTP_AUTH_TYPE,
dwSMTPAuthOption))
{
VERBOSE(SETUP_ERR,_T("SetRegistryDword failed (ec=%d)"),GetLastError());
goto exit;
}
}
if (TRUE == bAllowEmail)
{
DWORD dwReceiptType;
//
// Add DRT_EMAIL to the current settings
//
dwErr = GetRegistryDwordEx(hKey,
REGVAL_RECEIPTS_TYPE,
&dwReceiptType);
if (ERROR_SUCCESS != dwErr)
{
VERBOSE(SETUP_ERR,_T("GetRegistryDwordEx failed (ec=%d)"),dwErr);
goto exit;
}
dwReceiptType |= DRT_EMAIL;
// write the value to the registry.
if (!SetRegistryDword(hKey,
REGVAL_RECEIPTS_TYPE,
dwReceiptType))
{
VERBOSE(SETUP_ERR,_T("SetRegistryDword failed (ec=%d)"),dwErr);
goto exit;
}
}
}
else
{
//
// We have a connection to the fax service.
// Use it to configure the server.
//
// call FaxGetReceiptsConfiguration
if (!FaxGetReceiptsConfiguration(hFaxHandle,&pFaxReceiptsConfigW))
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,_T("FaxGetReceiptsConfigurationW failed (ec=%d)"),dwErr);
goto exit;
}
// get FaxUserName, this is the lptstrSMTPUserName member of PFAX_RECEIPTS_CONFIGW
if ((prv_FindKeyName(RULE_FAXUSERNAME,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxReceiptsConfigW->lptstrSMTPUserName = (TCHAR*)pUnattendedKey->pData;
}
// get FaxUserPassword, this is the lptstrSMTPPassword member of PFAX_RECEIPTS_CONFIGW
if ((prv_FindKeyName(RULE_FAXUSERPASSWORD,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxReceiptsConfigW->lptstrSMTPPassword = (TCHAR*)pUnattendedKey->pData;
}
// get SmtpNotificationsEnabled, this is part of dwAllowedReceipts member of PFAX_RECEIPTS_CONFIGW
if (TRUE == bAllowEmail)
{
pFaxReceiptsConfigW->dwAllowedReceipts |= DRT_EMAIL;
}
// get SmtpSenderAddress, this is the lptstrSMTPFrom member of PFAX_RECEIPTS_CONFIGW
if ((prv_FindKeyName(RULE_SMTPSENDERADDRESS,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxReceiptsConfigW->lptstrSMTPFrom = (TCHAR*)pUnattendedKey->pData;
}
// get SmptServerAddress, this is the lptstrSMTPServer member of PFAX_RECEIPTS_CONFIGW
if ((prv_FindKeyName(RULE_SMTPSERVERADDRESS,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxReceiptsConfigW->lptstrSMTPServer = (TCHAR*)pUnattendedKey->pData;
}
// get SmtpServerPort, this is the dwSMTPPort member of PFAX_RECEIPTS_CONFIGW
if ((prv_FindKeyName(RULE_SMTPSERVERPORT,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxReceiptsConfigW->dwSMTPPort = (DWORD)(PtrToUlong(pUnattendedKey->pData));
}
// get SmtpServerAuthenticationMechanism, this is the SMTPAuthOption member of PFAX_RECEIPTS_CONFIGW
if (0xffffffff != dwSMTPAuthOption)
{
pFaxReceiptsConfigW->SMTPAuthOption = (FAX_ENUM_SMTP_AUTH_OPTIONS)dwSMTPAuthOption;
}
// now set the new configuration
if (!FaxSetReceiptsConfiguration(hFaxHandle,pFaxReceiptsConfigW))
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,_T("FaxSetReceiptsConfigurationW failed (ec=%d)"),dwErr);
goto exit;
}
}
exit:
if (pFaxReceiptsConfigW)
{
FaxFreeBuffer(pFaxReceiptsConfigW);
}
if (hKey)
{
::RegCloseKey(hKey);
}
return bRet;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// ConfigureArchivesFromAnswerFile
//
// Purpose: Get all the answers that are applicable for Archives
// and try to set the server configuration
//
// Params:
// HANDLE hFaxHandle - handle from FaxConnectFaxServer
//
// Return Value:
// Win32 Error code
//
// Author:
// Mooly Beery (MoolyB) 22-Apr-2001
///////////////////////////////////////////////////////////////////////////////////////
BOOL ConfigureArchivesFromAnswerFile(HANDLE hFaxHandle)
{
BOOL bRet = TRUE;
DWORD dwErr = NO_ERROR;
PFAX_ARCHIVE_CONFIGW pFaxInboxArchiveConfigW = NULL;
PFAX_ARCHIVE_CONFIGW pFaxSentItemsArchiveConfigW = NULL;
prv_UnattendedRule_t* pUnattendedKey = NULL;
DBG_ENTER(_T("ConfigureArchivesFromAnswerFile"),bRet);
if (NULL == hFaxHandle)
{
return bRet; // All data is conifigured directly to the registry.
}
// call FaxGetArchiveConfiguration to get the inbox configuration
if (FaxGetArchiveConfiguration(hFaxHandle,FAX_MESSAGE_FOLDER_INBOX,&pFaxInboxArchiveConfigW))
{
// Inbox enable
if ((prv_FindKeyName(RULE_ARCHIVEINCOMING,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxInboxArchiveConfigW->bUseArchive= (BOOL)PtrToUlong(pUnattendedKey->pData);
}
// Inbox folder
if ((prv_FindKeyName(RULE_ARCHIVEINCOMINGFOLDERNAME,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxInboxArchiveConfigW->lpcstrFolder= (TCHAR*)(pUnattendedKey->pData);
}
// now set the new configuration
if (FaxSetArchiveConfiguration(hFaxHandle,FAX_MESSAGE_FOLDER_INBOX,pFaxInboxArchiveConfigW))
{
dwErr = GetLastError();
VERBOSE(DBG_WARNING,_T("FaxSetArchiveConfigurationW FAX_MESSAGE_FOLDER_INBOX failed (ec=%d)"),dwErr);
}
}
else
{
dwErr = GetLastError();
VERBOSE(DBG_WARNING,_T("FaxGetArchiveConfigurationW FAX_MESSAGE_FOLDER_INBOX failed (ec=%d)"),dwErr);
}
// call FaxGetArchiveConfiguration to get the SentItems configuration
if (FaxGetArchiveConfiguration(hFaxHandle,FAX_MESSAGE_FOLDER_SENTITEMS,&pFaxSentItemsArchiveConfigW))
{
// SentItems enable
if ((prv_FindKeyName(RULE_ARCHIVEOUTGOING,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxSentItemsArchiveConfigW->bUseArchive= (BOOL)PtrToUlong(pUnattendedKey->pData);
}
// SentItems folder
if ((prv_FindKeyName(RULE_ARCHIVEFOLDERNAME,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxSentItemsArchiveConfigW->lpcstrFolder= (TCHAR*)(pUnattendedKey->pData);
}
// SentItems folder could also come from this rule
if ((prv_FindKeyName(RULE_ARCHIVEOUTGOINGFOLDERNAME,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxSentItemsArchiveConfigW->lpcstrFolder= (TCHAR*)(pUnattendedKey->pData);
}
// now set the new configuration
if (FaxSetArchiveConfiguration(hFaxHandle,FAX_MESSAGE_FOLDER_SENTITEMS,pFaxSentItemsArchiveConfigW))
{
dwErr = GetLastError();
VERBOSE(DBG_WARNING,_T("FaxSetArchiveConfigurationW FAX_MESSAGE_FOLDER_INBOX failed (ec=%d)"),dwErr);
}
}
else
{
dwErr = GetLastError();
VERBOSE(DBG_WARNING,_T("FaxGetArchiveConfigurationW FAX_MESSAGE_FOLDER_INBOX failed (ec=%d)"),dwErr);
}
if (pFaxInboxArchiveConfigW)
{
FaxFreeBuffer(pFaxInboxArchiveConfigW);
}
if (pFaxSentItemsArchiveConfigW)
{
FaxFreeBuffer(pFaxSentItemsArchiveConfigW);
}
return bRet;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// SetPerDeviceConfigFromAnswerFile
//
// Purpose: Get all the answers that are applicable for device
// settings and routing extension settings
// and set all the existing devices.
//
// Params:
// HANDLE hFaxHandle - handle from FaxConnectFaxServer
//
// Return Value:
// Win32 Error code
//
// Author:
// Mooly Beery (MoolyB) 12-mar-2001
///////////////////////////////////////////////////////////////////////////////////////
static DWORD SetPerDeviceConfigFromAnswerFile(HANDLE hFaxHandle)
{
DWORD dwErr = ERROR_SUCCESS;
PFAX_PORT_INFO_EXW pFaxPortInfoExW = NULL;
DWORD dwNumPorts = 0;
DWORD dwIndex = 0;
DWORD dwFlags = 0;
prv_UnattendedRule_t* pUnattendedKey = NULL;
HKEY hKey = NULL;
DBG_ENTER(_T("SetPerDeviceConfigFromAnswerFile"),dwErr);
// handle Route to Folder, printer and Email- enable
if ((prv_FindKeyName(RULE_ROUTETOPRINTER,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
dwFlags |= ((BOOL)PtrToUlong(pUnattendedKey->pData)) ? LR_PRINT : 0;
}
if ((prv_FindKeyName(RULE_ROUTETOFOLDER,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
dwFlags |= ((BOOL) PtrToUlong(pUnattendedKey->pData)) ? LR_STORE : 0;
}
if (!IsDesktopSKU())
{
if ((prv_FindKeyName(RULE_ROUTETOEMAIL,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
dwFlags |= ((BOOL) PtrToUlong(pUnattendedKey->pData)) ? LR_EMAIL : 0;
}
}
if (NULL == hFaxHandle)
{
//
// No connection to the fax service.
// The unattended data is stored directly in the registry.
// Just add the data that could not be written in the general section of fxUnatnd_SaveUnattendedData()
// Open the Receipts registry key
hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_FAX_UNASS_DATA, FALSE, KEY_WRITE);
if (NULL == hKey)
{
VERBOSE(SETUP_ERR,_T("OpenRegistryKey failed (ec=%d)"),GetLastError());
goto exit;
}
// write the values to the registry
if (0 != dwFlags)
{
// write the value to the registry.
if (!SetRegistryBinary(hKey,
REGVAL_RM_FLAGS_GUID,
(BYTE*)&dwFlags,
sizeof(dwFlags)))
{
VERBOSE(SETUP_ERR,_T("SetRegistryBinary failed (ec=%d)"),GetLastError());
goto exit;
}
}
}
else
{
// call EnumPortsEx
if (!FaxEnumPortsEx(hFaxHandle,&pFaxPortInfoExW,&dwNumPorts))
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,_T("FaxEnumPortsEx failed (ec=%d)"),dwErr);
goto exit;
}
for (dwIndex=0; dwIndex<dwNumPorts; dwIndex++)
{
// handle CSID
if ((prv_FindKeyName(RULE_CSID,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxPortInfoExW[dwIndex].lptstrCsid = (TCHAR*)pUnattendedKey->pData;
}
// handle TSID
if ((prv_FindKeyName(RULE_TSID,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxPortInfoExW[dwIndex].lptstrTsid = (TCHAR*)pUnattendedKey->pData;
}
// handle Rings
if ((prv_FindKeyName(RULE_RINGS,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxPortInfoExW[dwIndex].dwRings = (DWORD)(PtrToUlong(pUnattendedKey->pData));
}
// handle Flags
if ((prv_FindKeyName(RULE_SENDFAXES,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxPortInfoExW[dwIndex].bSend = ((BOOL)PtrToUlong(pUnattendedKey->pData));
}
if ((prv_FindKeyName(RULE_RECEIVEFAXES,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
pFaxPortInfoExW[dwIndex].ReceiveMode = ((BOOL)PtrToUlong(pUnattendedKey->pData)) ? FAX_DEVICE_RECEIVE_MODE_AUTO : FAX_DEVICE_RECEIVE_MODE_OFF;
}
// Set CSID, TSID and Rings
if(!FaxSetPortEx(hFaxHandle, pFaxPortInfoExW[dwIndex].dwDeviceID, &pFaxPortInfoExW[dwIndex]))
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,_T("Can't save fax port data. Error code is %d."),dwErr);
// nothing to worry about, let's try some other answers...
dwErr = ERROR_SUCCESS;
}
// handle Route to Folder - folder name
if ((prv_FindKeyName(RULE_ROUTEFOLDERNAME,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
if(!FaxSetExtensionData(hFaxHandle,
pFaxPortInfoExW[dwIndex].dwDeviceID,
REGVAL_RM_FOLDER_GUID,
(LPBYTE)pUnattendedKey->pData,
StringSize((TCHAR*)(pUnattendedKey->pData))) )
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,
_T("FaxSetExtensionData failed: Device Id=%d, routing GUID=%s, error=%d."),
pFaxPortInfoExW[dwIndex].dwDeviceID,
REGVAL_RM_FOLDER_GUID,
dwErr);
// nothing to worry about, let's try some other answers...
dwErr = ERROR_SUCCESS;
}
}
// handle Route to Printer - printer name
if ((prv_FindKeyName(RULE_ROUTEPRINTERNAME,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
if(!FaxSetExtensionData(hFaxHandle,
pFaxPortInfoExW[dwIndex].dwDeviceID,
REGVAL_RM_PRINTING_GUID,
(LPBYTE)pUnattendedKey->pData,
StringSize((TCHAR*)(pUnattendedKey->pData))) )
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,
_T("FaxSetExtensionData failed: Device Id=%d, routing GUID=%s, error=%d."),
pFaxPortInfoExW[dwIndex].dwDeviceID,
REGVAL_RM_FOLDER_GUID,
dwErr);
// nothing to worry about, let's try some other answers...
dwErr = ERROR_SUCCESS;
}
}
if (!IsDesktopSKU())
{
// handle Route to Email - email name
if ((prv_FindKeyName(RULE_ROUTETOEMAILRECIPIENT,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
if(!FaxSetExtensionData(hFaxHandle,
pFaxPortInfoExW[dwIndex].dwDeviceID,
REGVAL_RM_EMAIL_GUID,
(LPBYTE)pUnattendedKey->pData,
StringSize((TCHAR*)(pUnattendedKey->pData))) )
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,
_T("FaxSetExtensionData failed: Device Id=%d, routing GUID=%s, error=%d."),
pFaxPortInfoExW[dwIndex].dwDeviceID,
REGVAL_RM_EMAIL_GUID,
dwErr);
// nothing to worry about, let's try some other answers...
dwErr = ERROR_SUCCESS;
}
}
}
// handle Route to Folder, printer and Email- enable
if(!FaxSetExtensionData(hFaxHandle,
pFaxPortInfoExW[dwIndex].dwDeviceID,
REGVAL_RM_FLAGS_GUID,
(LPBYTE)&dwFlags,
sizeof(DWORD)) )
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,
_T("FaxSetExtensionData failed: Device Id=%d, routing GUID=%s, error=%d."),
pFaxPortInfoExW[dwIndex].dwDeviceID,
REGVAL_RM_FOLDER_GUID,
dwErr);
// nothing to worry about, let's try some other answers...
dwErr = ERROR_SUCCESS;
}
}
}
exit:
if (pFaxPortInfoExW)
{
FaxFreeBuffer(pFaxPortInfoExW);
}
if(hKey)
{
::RegCloseKey (hKey);
}
return dwErr;
}
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// SaveSettingsFromAnswerFile
//
// Purpose: Get all the answers that are applicable for device
// settings and routing extension settings
// and set all the existing devices.
//
// Params:
// None
//
// Return Value:
// Win32 Error code
//
// Author:
// Mooly Beery (MoolyB) 12-mar-2001
///////////////////////////////////////////////////////////////////////////////////////
static DWORD SaveSettingsFromAnswerFile()
{
DWORD dwErr = ERROR_SUCCESS;
HANDLE hFaxHandle = NULL;
prv_UnattendedRule_t* pUnattendedKey = NULL;
DBG_ENTER(_T("SaveSettingsFromAnswerFile"),dwErr);
if (fxState_IsStandAlone())
{
//
// This is a stand alone installation. Connect to the fax service and use it to configure the dynamic data.
//
if (!FaxConnectFaxServer(NULL,&hFaxHandle))
{
dwErr = GetLastError();
VERBOSE(SETUP_ERR,_T("FaxConnectFaxServer failed (ec=%d)"),dwErr);
goto exit;
}
}
else
{
//
// We are in GUI mode setup, and we should not start the service as not all system resources are available.
// Use the registry to configure the fax service.
// The fax service will read the data when it is first started after reboot (at the end of GUI mode).
//
}
// set the SMTP server configuration, on Server SKUs only
if (!IsDesktopSKU())
{
if (!ConfigureSMTPFromAnswerFile(hFaxHandle))
{
dwErr = GetLastError();
VERBOSE(DBG_WARNING,_T("ConfigureSMTPFromAnswerFile failed (ec=%d)"),dwErr);
// this is not fatal, continue...
}
}
if (!ConfigureArchivesFromAnswerFile(hFaxHandle))
{
dwErr = GetLastError();
VERBOSE(DBG_WARNING,_T("ConfigureArchivesFromAnswerFile failed (ec=%d)"),dwErr);
// this is not fatal, continue...
}
if (SetPerDeviceConfigFromAnswerFile(hFaxHandle)!=NO_ERROR)
{
dwErr = GetLastError();
VERBOSE(DBG_WARNING,_T("SetPerDeviceConfigFromAnswerFile failed (ec=%d)"),dwErr);
// this is not fatal, continue...
}
// finally set HKLM... Fax\Setup\Original Setup Data REG_DWORD Flags to configure any future device.
HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP_ORIG,FALSE,KEY_WRITE);
if (hKey)
{
BOOL bFound = FALSE;
DWORD dwFlags = 0;
if ((prv_FindKeyName(RULE_SENDFAXES,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
dwFlags |= ((BOOL)PtrToUlong(pUnattendedKey->pData)) ? FPF_SEND : 0;
bFound = TRUE;
}
if ((prv_FindKeyName(RULE_RECEIVEFAXES,&pUnattendedKey)) && (pUnattendedKey->bValid))
{
dwFlags |= ((BOOL)PtrToUlong(pUnattendedKey->pData)) ? FPF_RECEIVE : 0;
bFound = TRUE;
}
if (bFound)
{
if (!SetRegistryDword(hKey,REGVAL_FLAGS,dwFlags))
{
CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryDword(REGVAL_FLAGS)"), GetLastError());
}
}
RegCloseKey(hKey);
}
else
{
CALL_FAIL(SETUP_ERR,TEXT("OpenRegistryKey"),GetLastError());
}
exit:
if (hFaxHandle)
{
FaxClose(hFaxHandle);
}
return dwErr;
}