////////////////////////////////////////////////////////////////////////////// // // 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; dwIndexbValid)) { 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; }