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.
 
 
 
 
 
 

1577 lines
42 KiB

/*++
Copyright (c) 1999 - 2000 Microsoft Corporation
Module Name:
wizard.c
Abstract:
Fax configuration wizard main function
Environment:
Fax configuration wizard
Revision History:
03/13/00 -taoyuan-
Created it.
mm/dd/yy -author-
description
--*/
#include "faxcfgwz.h"
#include <shfusion.h>
HANDLE g_hFaxSvcHandle = NULL;
LIST_ENTRY g_PageList; // to keep track of the previous page.
BOOL g_bShowDevicePages = TRUE;
BOOL g_bShowUserInfo = TRUE;
WIZARDDATA g_wizData = {0};
extern PPRINTER_NAMES g_pPrinterNames;
extern DWORD g_dwNumPrinters;
const LPCTSTR g_RoutingGuids[RM_COUNT] =
{
REGVAL_RM_FOLDER_GUID, // RM_FOLDER
REGVAL_RM_PRINTING_GUID // RM_PRINT
};
typedef struct _WIZARDPAGEINFO
{
INT pageId; // page dialog id
DLGPROC dlgProc; // page dialog callback function
BOOL bSelected; // Whether this page is selected in the wizard
INT Title; // title id from the resource file
INT SubTitle; // sub title id from the resource file
} WIZARDPAGEINFO, *PWIZARDPAGEINFO;
//
// all configuration pages are false here, they will be initialized by FaxConfigWizard()
//
static WIZARDPAGEINFO g_FaxWizardPage[] =
{
{ IDD_CFG_WIZARD_WELCOME, WelcomeDlgProc, TRUE, 0, 0 },
{ IDD_WIZARD_USER_INFO, UserInfoDlgProc, FALSE, IDS_WIZ_USER_INFO_TITLE, IDS_WIZ_USER_INFO_SUB },
{ IDD_DEVICE_LIMIT_SELECT, DevLimitDlgProc, FALSE, IDS_DEVICE_LIMIT_TITLE, IDS_DEVICE_LIMIT_SUB },
{ IDD_ONE_DEVICE_LIMIT, OneDevLimitDlgProc, FALSE, IDS_ONE_DEVICE_TITLE, IDS_ONE_DEVICE_SUB },
{ IDD_WIZARD_SEND_SELECT_DEVICES, SendDeviceDlgProc, FALSE, IDS_WIZ_SEND_DEVICE_TITLE, IDS_WIZ_SEND_DEVICE_SUB },
{ IDD_WIZARD_SEND_TSID, SendTsidDlgProc, FALSE, IDS_WIZ_SEND_TSID_TITLE, IDS_WIZ_SEND_TSID_SUB },
{ IDD_WIZARD_RECV_SELECT_DEVICES, RecvDeviceDlgProc, FALSE, IDS_WIZ_RECV_DEVICE_TITLE, IDS_WIZ_RECV_DEVICE_SUB },
{ IDD_WIZARD_RECV_CSID, RecvCsidDlgProc, FALSE, IDS_WIZ_RECV_CSID_TITLE, IDS_WIZ_RECV_CSID_SUB },
{ IDD_WIZARD_RECV_ROUTE, RecvRouteDlgProc, FALSE, IDS_WIZ_RECV_ROUTE_TITLE, IDS_WIZ_RECV_ROUTE_SUB },
{ IDD_WIZARD_COMPLETE, CompleteDlgProc, TRUE, 0, 0 }
};
#define TIME_TO_WAIT_FOR_CONVERSTION 25000
#define NUM_PAGES (sizeof(g_FaxWizardPage)/sizeof(WIZARDPAGEINFO))
enum WIZARD_PAGE
{
WELCOME = 0,
USER_INFO,
DEV_LIMIT,
ONE_DEV_LIMIT,
SEND_DEVICE,
TSID,
RECV_DEVICE,
CSID,
ROUTE
};
#define TITLE_SIZE 600
BOOL LoadDeviceData();
BOOL SaveDeviceData();
void FreeDeviceData();
DWORD ConvertCpeFilesToCov();
BOOL
FillInPropertyPage(
PROPSHEETPAGE *psp,
PWIZARDPAGEINFO pPageInfo
)
/*++
Routine Description:
Fill out a PROPSHEETPAGE structure with the supplied parameters
Arguments:
psp - Points to the PROPSHEETPAGE structure to be filled out
pData - Pointer to the shared data structure
Return Value:
NONE
--*/
{
LPTSTR pWizardTitle = NULL;
LPTSTR pWizardSubTitle = NULL;
DEBUG_FUNCTION_NAME(TEXT("FillInPropertyPage()"));
Assert(psp);
DebugPrintEx(DEBUG_MSG, TEXT("FillInPropertyPage %d"), pPageInfo->pageId);
psp->dwSize = sizeof(PROPSHEETPAGE);
//
// Don't show titles if it's the first or last page
//
if (0 == pPageInfo->Title && 0 == pPageInfo->SubTitle)
{
psp->dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
}
else
{
psp->dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
}
psp->hInstance = g_hResource;
psp->pszTemplate = MAKEINTRESOURCE(pPageInfo->pageId);
psp->pfnDlgProc = pPageInfo->dlgProc;
if (pPageInfo->Title)
{
pWizardTitle = (LPTSTR)MemAlloc(TITLE_SIZE*sizeof(TCHAR));
if(!pWizardTitle)
{
DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed"));
goto error;;
}
if (!LoadString(g_hResource, pPageInfo->Title, pWizardTitle, TITLE_SIZE))
{
DebugPrintEx(DEBUG_ERR,
TEXT("LoadString failed. string ID=%d, error=%d"),
pPageInfo->Title,
GetLastError());
goto error;
}
}
if (pPageInfo->SubTitle)
{
pWizardSubTitle = (LPTSTR)MemAlloc(TITLE_SIZE*sizeof(TCHAR) );
if(!pWizardSubTitle)
{
DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed"));
goto error;
}
ZeroMemory(pWizardSubTitle, TITLE_SIZE*sizeof(TCHAR));
if(IDS_DEVICE_LIMIT_SUB == pPageInfo->SubTitle && g_wizData.dwDeviceLimit != INFINITE)
{
//
// Format limit device selection page subtitle
//
TCHAR tszBuffer[MAX_PATH];
if (!LoadString(g_hResource, pPageInfo->SubTitle, tszBuffer, MAX_PATH))
{
DebugPrintEx(DEBUG_ERR,
TEXT("LoadString failed. string ID=%d, error=%d"),
pPageInfo->SubTitle,
GetLastError());
goto error;
}
_sntprintf(pWizardSubTitle, TITLE_SIZE-1, tszBuffer, g_wizData.dwDeviceLimit);
}
else if (!LoadString(g_hResource, pPageInfo->SubTitle, pWizardSubTitle, TITLE_SIZE))
{
DebugPrintEx(DEBUG_ERR,
TEXT("LoadString failed. string ID=%d, error=%d"),
pPageInfo->SubTitle,
GetLastError());
goto error;
}
}
psp->pszHeaderTitle = pWizardTitle;
psp->pszHeaderSubTitle = pWizardSubTitle;
return TRUE;
error:
MemFree(pWizardTitle);
MemFree(pWizardSubTitle);
return FALSE;
}
BOOL
FaxConfigWizard(
BOOL bExplicitLaunch,
LPBOOL lpbAbort
)
/*++
Routine Description:
Present the Fax Configuration Wizard to the user.
Arguments:
bExplicitLaunch - [in] Fax Config Wizard was launched explicitly
lpbAbort - [out] TRUE if the user refused to enter a dialing location and the calling process should abort.
Return Value:
TRUE if successful, FALSE if there is an error or the user pressed Cancel.
--*/
{
HWND hWnd; // window handle of the calling method
PROPSHEETPAGE psp[NUM_PAGES] = {0};
PROPSHEETPAGE* pspSaved;
PROPSHEETHEADER psh = {0};
BOOL bResult = FALSE;
HDC hdc = NULL;
DWORD i = 0;
DWORD dwPageCount = 0;
LPTSTR lptstrResource = NULL;
BOOL bLinkWindowRegistered = FALSE;
int nRes;
BOOL bSHFusionInitialized = FALSE;
INITCOMMONCONTROLSEX CommonControlsEx = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES };
DEBUG_FUNCTION_NAME(TEXT("FaxConfigWizard()"));
//
// initialize the link list for tracing pages
//
InitializeListHead(&g_PageList);
//
// Enable SHAutoComplete
//
CoInitialize(NULL);
//
// Fusion Initialize
//
if (!SHFusionInitializeFromModuleID(g_hModule, SXS_MANIFEST_RESOURCE_ID))
{
DebugPrintEx(DEBUG_ERR, TEXT("SHFusionInitializeFromModuleID failed."));
}
else
{
bSHFusionInitialized = TRUE;
}
if (!InitCommonControlsEx(&CommonControlsEx))
{
DebugPrintEx(DEBUG_ERR, TEXT("InitCommonControlsEx failed"));
goto exit;
}
hWnd = GetActiveWindow();
g_wizData.hWndParent = hWnd;
//
// On first time, convert CPE files from CSIDL_COMMON_APPDATA\Microsoft\Windows NT\MSFax\Common Coverpages
// to the user personal cover page directory: CSIDL_PERSONAL\Fax\Personal Coverpages
//
if (ConvertCpeFilesToCov() != ERROR_SUCCESS)
{
DebugPrintEx(DEBUG_ERR, TEXT("ConvertCpeFilesToCov failed, continue anyways"));
}
//
// Check if the user has run this wizard before
//
if(!bExplicitLaunch)
{
BOOL bDeviceConfigured = FALSE;
BOOL bExistsPrinterConnection = FALSE;
TCHAR tszPrnName[MAX_PATH];
//
// Is the user info already configured?
//
if(IsUserInfoConfigured())
{
g_bShowUserInfo = FALSE;
}
//
// Are fax devices already configured?
//
if(!FaxGetConfigWizardUsed(&bDeviceConfigured))
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxGetConfigWizardUsed failed. ec = %d"), GetLastError());
goto exit;
}
//
//Are there any printer connections installed?
//
if (GetFirstRemoteFaxPrinterName(tszPrnName,MAX_PATH))
{
bExistsPrinterConnection = TRUE;
}
if(bDeviceConfigured || bExistsPrinterConnection)
{
g_bShowDevicePages = FALSE;
}
}
if(!g_bShowUserInfo && !g_bShowDevicePages)
{
//
// No pages to show - no error
//
bResult = TRUE;
goto exit;
}
//
// We're going to call into the local fax server - connect to it now.
//
if(!Connect())
{
if(bExplicitLaunch)
{
DisplayMessageDialog(hWnd, 0, 0, IDS_ERR_CANT_CONNECT);
}
DebugPrintEx(DEBUG_ERR, TEXT("Can't connect to fax server. ec = %d"), GetLastError());
goto exit;
}
*lpbAbort = FALSE;
if(g_bShowDevicePages)
{
if(FaxAccessCheckEx(g_hFaxSvcHandle, FAX_ACCESS_MANAGE_CONFIG, NULL))
{
//
// IsFaxDeviceInstalled() prompts to install a device if needed
//
if(!IsFaxDeviceInstalled(g_wizData.hWndParent, lpbAbort))
{
g_bShowDevicePages = FALSE;
}
}
else
{
//
// the user has no manage access
//
g_bShowDevicePages = FALSE;
}
}
if (*lpbAbort)
{
//
// the user refused to enter a dialing location and the calling process should abort.
//
DebugPrintEx(DEBUG_MSG,
TEXT("The user refused to enter a dialing location and the calling process should abort"));
return FALSE;
}
if(g_bShowDevicePages)
{
TCHAR tszPrnName[MAX_PATH];
if(GetFirstLocalFaxPrinterName(tszPrnName, MAX_PATH-1))
{
// TODO: suggest install printer
}
}
if(!g_bShowUserInfo && !g_bShowDevicePages)
{
//
// no pages to show - no error
//
bResult = TRUE;
goto exit;
}
//
// Load shared data
//
if(!LoadWizardData())
{
DebugPrintEx(DEBUG_ERR, TEXT("Load data error."));
goto exit;
}
//
// Set page information depending on user selection as well as checking user access right
//
if(g_bShowUserInfo)
{
g_FaxWizardPage[USER_INFO].bSelected = TRUE;
}
if(g_bShowDevicePages)
{
HKEY hRegKey;
DWORD dwDisableRouting = 0;
Assert(g_wizData.dwDeviceCount);
if(1 == g_wizData.dwDeviceLimit)
{
g_FaxWizardPage[ONE_DEV_LIMIT].bSelected = TRUE;
}
else if(g_wizData.dwDeviceLimit < g_wizData.dwDeviceCount)
{
g_FaxWizardPage[DEV_LIMIT].bSelected = TRUE;
}
g_FaxWizardPage[SEND_DEVICE].bSelected = (1 < g_wizData.dwDeviceLimit);
g_FaxWizardPage[TSID].bSelected = TRUE;
g_FaxWizardPage[RECV_DEVICE].bSelected = (1 < g_wizData.dwDeviceLimit);
g_FaxWizardPage[CSID].bSelected = TRUE;
hRegKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_FAXSERVER, FALSE, KEY_READ);
if(hRegKey)
{
dwDisableRouting = GetRegistryDword(hRegKey, REGVAL_CFGWZRD_DISABLE_ROUTING);
RegCloseKey(hRegKey);
}
g_FaxWizardPage[ROUTE].bSelected = dwDisableRouting ? FALSE : TRUE;
}
//
// Register the link window class
//
bLinkWindowRegistered = LinkWindow_RegisterClass();
if(!bLinkWindowRegistered)
{
DebugPrintEx(DEBUG_ERR, TEXT("LinkWindow_RegisterClass() failed - unable to register link window class"));
}
//
// Fill out one PROPSHEETPAGE structure for every page:
// The first page is a welcome page
// The last page is a complete page
//
pspSaved = psp;
for(i = 0; i < NUM_PAGES; i++)
{
if(g_FaxWizardPage[i].bSelected)
{
if(!FillInPropertyPage(pspSaved++, &g_FaxWizardPage[i]))
{
DebugPrintEx(DEBUG_ERR, TEXT("FillInPropertyPage failed"));
goto exit;
}
dwPageCount++;
}
}
//
// Fill out the PROPSHEETHEADER structure
//
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
psh.hwndParent = hWnd;
psh.hInstance = g_hResource;
psh.hIcon = NULL;
psh.pszCaption = TEXT("");
psh.nPages = dwPageCount;
psh.nStartPage = 0;
psh.ppsp = psp;
if(hdc = GetDC(NULL))
{
if(GetDeviceCaps(hdc, BITSPIXEL) >= 8)
{
lptstrResource = MAKEINTRESOURCE(IDB_FAXWIZ_WATERMARK_256);
}
else
{
lptstrResource = MAKEINTRESOURCE(IDB_FAXWIZ_WATERMARK_16);
}
ReleaseDC(NULL,hdc);
hdc = NULL;
}
psh.pszbmHeader = MAKEINTRESOURCE(IDB_CFG_WIZ_BITMAP);
psh.pszbmWatermark = lptstrResource;
//
// Display the wizard pages
//
nRes = (int)PropertySheet(&psh);
if (nRes > 0 && g_wizData.bFinishPressed)
{
//
// Save new settings here
//
if(!SaveWizardData())
{
DisplayMessageDialog(hWnd, MB_ICONERROR, 0, IDS_ERR_NOT_SAVE);
DebugPrintEx(DEBUG_ERR, TEXT("Can't save wizard data."));
goto exit;
}
}
else if(0 == nRes && !bExplicitLaunch) // Cancel
{
if(IDNO == DisplayMessageDialog(hWnd,
MB_YESNO | MB_ICONQUESTION,
0,
IDS_SHOW_NEXT_TIME))
{
if (g_bShowUserInfo)
{
DWORD dwRes;
HKEY hRegKey = OpenRegistryKey(HKEY_CURRENT_USER,
REGKEY_FAX_SETUP,
TRUE,
KEY_ALL_ACCESS);
if(hRegKey)
{
SetRegistryDword(hRegKey, REGVAL_CFGWZRD_USER_INFO, TRUE);
dwRes = RegCloseKey(hRegKey);
if(ERROR_SUCCESS != dwRes)
{
Assert(FALSE);
DebugPrintEx(DEBUG_ERR, TEXT("RegCloseKey failed: error=%d"), dwRes);
}
}
else
{
DebugPrintEx(DEBUG_ERR,
TEXT("OpenRegistryKey failed: error=%d"),
GetLastError());
}
}
if (g_bShowDevicePages ||
FaxAccessCheckEx(g_hFaxSvcHandle, FAX_ACCESS_MANAGE_CONFIG, NULL))
{
//
// If the user has manage access and does not have a fax device
// it's mean she refused to install it.
// So, we should not disturb her
// with implicit invocation of the Configuration Wizard.
//
if(!FaxSetConfigWizardUsed(g_hFaxSvcHandle, TRUE))
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxSetConfigWizardUsed failed with %d"), GetLastError());
}
}
}
}
else if(nRes < 0)
{
DebugPrintEx(DEBUG_ERR, TEXT("PropertySheet() failed (ec: %ld)"), GetLastError());
}
bResult = TRUE;
exit:
//
// Cleanup properly before exiting
//
for (i = 0; i< dwPageCount; i++)
{
MemFree((PVOID)psp[i].pszHeaderTitle );
MemFree((PVOID)psp[i].pszHeaderSubTitle );
}
FreeWizardData();
ClearPageList();
if( bLinkWindowRegistered )
{
LinkWindow_UnregisterClass( g_hResource );
}
DisConnect();
if (g_pPrinterNames)
{
ReleasePrinterNames (g_pPrinterNames, g_dwNumPrinters);
g_pPrinterNames = NULL;
}
if (bSHFusionInitialized)
{
SHFusionUninitialize();
}
CoUninitialize();
return bResult;
} // FaxConfigWizard
BOOL
LoadWizardData()
/*++
Routine Description:
Load the wizard data from the system.
If there are more than one device, we load the data for the first available device.
Arguments:
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DEBUG_FUNCTION_NAME(TEXT("LoadWizardData()"));
if (g_bShowUserInfo)
{
if(!LoadUserInfo())
{
//
// no user info
//
DebugPrintEx(DEBUG_MSG, TEXT("LoadUserInfo: failed: error=%d"), GetLastError());
}
}
//
// get the large fonts for wizard97
//
if(!LoadWizardFont())
{
DebugPrintEx(DEBUG_MSG, TEXT("LoadWizardFont: failed."));
goto error;
}
if (g_bShowDevicePages)
{
if(!LoadDeviceData())
{
DebugPrintEx(DEBUG_MSG, TEXT("LoadDeviceData: failed."));
goto error;
}
}
return TRUE;
error:
FreeWizardData();
return FALSE;
} // LoadWizardData
BOOL
LoadWizardFont()
/*++
Routine Description:
Load the wizard font for the title.
Arguments:
pData - Points to the user mode memory structure
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
HDC hdc = NULL;
LOGFONT lfTitleFont = {0};
NONCLIENTMETRICS ncm = {0};
TCHAR szFontName[MAX_PATH];
INT iFontSize = 12; // fixed large font size, which is 12
DEBUG_FUNCTION_NAME(TEXT("LoadWizardFont()"));
//
// get the large fonts for wizard97
//
ncm.cbSize = sizeof(ncm);
if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
{
DebugPrintEx(DEBUG_ERR, TEXT("SystemParametersInfo failed. ec = 0x%X"), GetLastError());
goto Error;
}
else
{
CopyMemory((LPVOID* )&lfTitleFont, (LPVOID *)&ncm.lfMessageFont, sizeof(lfTitleFont));
if (!LoadString(g_hResource, IDS_WIZ_LARGE_FONT_NAME, szFontName, MAX_PATH ))
{
DebugPrintEx(DEBUG_ERR,
TEXT("LoadString failed: string ID=%d, error=%d"),
IDS_WIZ_LARGE_FONT_NAME,
GetLastError());
goto Error;
}
lfTitleFont.lfWeight = FW_BOLD;
hdc = GetDC(NULL);
if (!hdc)
{
DebugPrintEx(DEBUG_ERR, TEXT("GetDC() failed (ec: ld)"), GetLastError());
goto Error;
}
lfTitleFont.lfHeight = 0 - (GetDeviceCaps(hdc, LOGPIXELSY) * iFontSize / 72);
g_wizData.hTitleFont = CreateFontIndirect(&lfTitleFont);
if (!g_wizData.hTitleFont)
{
DebugPrintEx(DEBUG_ERR,
TEXT("CreateFontIndirect(&lfTitleFont) failed (ec: %ld)"),
GetLastError());
goto Error;
}
ReleaseDC( NULL, hdc);
hdc = NULL;
}
return TRUE;
Error:
//
// Cleanup properly before exiting
//
if (hdc)
{
ReleaseDC( NULL, hdc);
hdc = NULL;
}
return FALSE;
} // LoadWizardFont
BOOL
SaveWizardData()
/*++
Routine Description:
Save the wizard data to the system.
If there are more than one device, all enabled devices will have the same settings.
Arguments:
pData - Points to the user memory structure
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
HKEY hRegKey = 0;
DEBUG_FUNCTION_NAME(TEXT("SaveConfigData()"));
if(!g_hFaxSvcHandle)
{
Assert(FALSE);
return FALSE;
}
//
// save user info
//
if (g_bShowUserInfo)
{
if(!SaveUserInfo())
{
DebugPrintEx(DEBUG_ERR, TEXT("SaveUserInfo failed"));
return FALSE;
}
}
//
// save device info
//
if (g_bShowDevicePages)
{
if(!SaveDeviceData())
{
DebugPrintEx(DEBUG_ERR, TEXT("SaveDeviceData failed"));
return FALSE;
}
}
if (g_bShowDevicePages ||
FaxAccessCheckEx(g_hFaxSvcHandle, FAX_ACCESS_MANAGE_CONFIG, NULL))
{
//
// If the user has manage access and does not have a fax device
// it's mean she refused to install it.
// So, we should not disturb her
// with implicit invocation of the Configuration Wizard.
//
if(!FaxSetConfigWizardUsed(g_hFaxSvcHandle, TRUE))
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxSetConfigWizardUsed failed with %d"), GetLastError());
}
}
return TRUE;
} // SaveWizardData
VOID
FreeWizardData()
/*++
Routine Description:
Free the wizard data and release the memory.
Arguments:
pData - Pointer to the receive data structure
Return Value:
None.
--*/
{
DEBUG_FUNCTION_NAME(TEXT("FreeWizardData()"));
if(g_wizData.hTitleFont)
{
DeleteObject(g_wizData.hTitleFont);
}
FreeUserInfo();
FreeDeviceData();
return;
} // FreeWizardData
BOOL
SetLastPage(
INT pageId
)
/*++
Routine Description:
Add one page to the link list to keep track of "go back" information
Arguments:
pageId - Page id of the page to be added.
Return Value:
TRUE if successful, FALSE for failure.
--*/
{
PPAGE_INFO pPageInfo;
DEBUG_FUNCTION_NAME(TEXT("SetLastPage()"));
pPageInfo = (PPAGE_INFO)MemAlloc(sizeof(PAGE_INFO));
if(pPageInfo == NULL)
{
LPCTSTR faxDbgFunction = TEXT("SetLastPage()");
DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed."));
Assert(FALSE);
return FALSE;
}
pPageInfo->pageId = pageId;
//
// add current page as the last page of the list
//
InsertTailList(&g_PageList, &pPageInfo->ListEntry);
return TRUE;
}
BOOL
ClearPageList(
VOID
)
/*++
Routine Description:
Clear the page list and release the allocated memory
Arguments:
None.
Return Value:
True if success, false if fails.
--*/
{
PLIST_ENTRY Last; // the last page information
PPAGE_INFO pPageInfo = NULL;
DEBUG_FUNCTION_NAME(TEXT("ClearPageList()"));
while(!IsListEmpty(&g_PageList))
{
Last = g_PageList.Blink;
pPageInfo = CONTAINING_RECORD( Last, PAGE_INFO, ListEntry );
if(pPageInfo)
{
RemoveEntryList(&pPageInfo->ListEntry);
MemFree(pPageInfo);
}
}
return TRUE;
}
BOOL
RemoveLastPage(
HWND hwnd
)
/*++
Routine Description:
Removes last page from the link list to keep track of "go back" information
Arguments:
hwnd - window handle
Return Value:
TRUE if successful, FALSE for failure.
--*/
{
PPAGE_INFO pPageInfo = NULL;
DEBUG_FUNCTION_NAME(TEXT("RemoveLastPage()"));
Assert(hwnd);
if(!g_PageList.Blink)
{
return FALSE;
}
pPageInfo = CONTAINING_RECORD( g_PageList.Blink, PAGE_INFO, ListEntry );
if(!pPageInfo)
{
return FALSE;
}
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, pPageInfo->pageId);
RemoveEntryList(&pPageInfo->ListEntry);
MemFree(pPageInfo);
return TRUE;
}
BOOL
LoadDeviceData()
/*++
Routine Description:
Load the fax devices information.
If there are more than one device, we load the data for the first available device.
Arguments:
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DWORD dwPorts = 0;
BOOL bRes = FALSE;
DWORD dw;
DWORD dwGroups; // group number
DWORD dwGroupIndex;
DWORD dwSndDevIndex=0; // index of the last send enabled device
DWORD dwRcvDevIndex=0; // index of the last receive enabled device
DWORD dwCurrentRM;
LPBYTE pRoutingInfoBuffer;
DWORD dwRoutingInfoBufferSize = 0;
PFAX_PORT_INFO_EX pPortsInfo = NULL; // for FaxEnumPortsEx
PFAX_OUTBOUND_ROUTING_GROUP pFaxRoutingGroup = NULL;
DEBUG_FUNCTION_NAME(TEXT("LoadDeviceData()"));
g_wizData.dwDeviceLimit = GetDeviceLimit();
g_wizData.pdwSendDevOrder = NULL;
g_wizData.szCsid = NULL;
g_wizData.szTsid = NULL;
g_wizData.dwDeviceCount = 0;
g_wizData.pDevInfo = NULL;
if(!FaxEnumPortsEx(g_hFaxSvcHandle, &pPortsInfo, &dwPorts))
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxEnumPortsEx failed: error=%d."), GetLastError());
goto exit;
}
if(!dwPorts)
{
Assert(dwPorts);
DebugPrintEx(DEBUG_ERR, TEXT("No available ports."));
goto exit;
}
g_wizData.dwDeviceCount = dwPorts;
g_wizData.pDevInfo = (PDEVICEINFO)MemAlloc(dwPorts * sizeof(DEVICEINFO));
if(!g_wizData.pDevInfo)
{
Assert(FALSE);
DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc() failed."));
goto exit;
}
ZeroMemory(g_wizData.pDevInfo, dwPorts * sizeof(DEVICEINFO));
//
// pick up the first available device, if no one is available
// choose the first device
//
for(dw = 0; dw < dwPorts; ++dw)
{
//
// copy other device info for each device
//
g_wizData.pDevInfo[dw].bSend = pPortsInfo[dw].bSend;
g_wizData.pDevInfo[dw].ReceiveMode = pPortsInfo[dw].ReceiveMode;
g_wizData.pDevInfo[dw].dwDeviceId = pPortsInfo[dw].dwDeviceID;
g_wizData.pDevInfo[dw].szDeviceName = StringDup(pPortsInfo[dw].lpctstrDeviceName);
if(!g_wizData.pDevInfo[dw].szDeviceName)
{
DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed.") );
goto exit;
}
if(pPortsInfo[dw].bSend)
{
dwSndDevIndex = dw;
}
if(FAX_DEVICE_RECEIVE_MODE_OFF != pPortsInfo[dw].ReceiveMode)
{
dwRcvDevIndex = dw;
}
g_wizData.pDevInfo[dw].bSelected = TRUE;
}
//
// Copy TSID
//
g_wizData.szTsid = StringDup(pPortsInfo[dwSndDevIndex].lptstrTsid);
if(!g_wizData.szTsid)
{
DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed.") );
goto exit;
}
//
// Copy CSID and rings number
//
g_wizData.dwRingCount = pPortsInfo[dwRcvDevIndex].dwRings;
g_wizData.szCsid = StringDup(pPortsInfo[dwRcvDevIndex].lptstrCsid);
if(!g_wizData.szCsid)
{
DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed.") );
goto exit;
}
if (!IsDesktopSKU())
{
//
// get device order
//
if(!FaxEnumOutboundGroups(g_hFaxSvcHandle, &pFaxRoutingGroup, &dwGroups))
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxEnumOutboundGroups failed: error=%d."), GetLastError());
Assert(FALSE);
goto exit;
}
for(dwGroupIndex = 0; dwGroupIndex < dwGroups; dwGroupIndex++)
{
// search the <All Devices> group
if(!lstrcmp(pFaxRoutingGroup[dwGroupIndex].lpctstrGroupName, ROUTING_GROUP_ALL_DEVICES))
{
// device number must be the same as port number
Assert(dwPorts == pFaxRoutingGroup[dwGroupIndex].dwNumDevices);
DebugPrintEx(DEBUG_MSG, TEXT("Total device number is %d."), pFaxRoutingGroup[dwGroupIndex].dwNumDevices);
DebugPrintEx(DEBUG_MSG, TEXT("Group status is %d."), pFaxRoutingGroup[dwGroupIndex].Status);
// collecting device Id
g_wizData.pdwSendDevOrder = MemAlloc(pFaxRoutingGroup[dwGroupIndex].dwNumDevices * sizeof(DWORD));
if(!g_wizData.pdwSendDevOrder)
{
DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed."));
goto exit;
}
memcpy(g_wizData.pdwSendDevOrder,
pFaxRoutingGroup[dwGroupIndex].lpdwDevices,
pFaxRoutingGroup[dwGroupIndex].dwNumDevices * sizeof(DWORD));
break;
}
}
if(!g_wizData.pdwSendDevOrder)
{
DebugPrintEx(DEBUG_ERR, TEXT("No device order information."));
goto exit;
}
}
//
// load routing methods
// the size of each routing methods should not be larger than INFO_SIZE
// fortunately, it is gurranteed by other fax programs
//
for (dwCurrentRM = 0; dwCurrentRM < RM_COUNT; ++dwCurrentRM)
{
LPTSTR lpCurSel;
//
// Check the validity first in the loop,
// then save the routing info
//
lpCurSel = g_wizData.pRouteInfo[dwCurrentRM].tszCurSel;
g_wizData.pRouteInfo[dwCurrentRM].bEnabled = FaxDeviceEnableRoutingMethod(
g_hFaxSvcHandle,
g_wizData.pDevInfo[dwRcvDevIndex].dwDeviceId,
g_RoutingGuids[dwCurrentRM],
QUERY_STATUS );
if(FaxGetExtensionData( g_hFaxSvcHandle,
g_wizData.pDevInfo[dwRcvDevIndex].dwDeviceId,
g_RoutingGuids[dwCurrentRM],
&pRoutingInfoBuffer,
&dwRoutingInfoBufferSize))
{
// only copy the first MAX_PATH - 1 characters
CopyMemory((LPBYTE)lpCurSel,
pRoutingInfoBuffer,
dwRoutingInfoBufferSize < MAX_PATH * sizeof(TCHAR) ?
dwRoutingInfoBufferSize : (MAX_PATH - 1) * sizeof(TCHAR));
FaxFreeBuffer(pRoutingInfoBuffer);
}
}
bRes = TRUE;
exit:
//
// Clean up
//
if(pPortsInfo)
{
FaxFreeBuffer(pPortsInfo);
}
if(pFaxRoutingGroup)
{
FaxFreeBuffer(pFaxRoutingGroup);
}
if(!bRes)
{
FreeDeviceData();
}
return bRes;
} // LoadDeviceData
BOOL
SaveSingleDeviceData (
PDEVICEINFO pDeviceInfo
)
{
BOOL bRes = TRUE;
DWORD dwCurrentRM;
PFAX_PORT_INFO_EX pPortInfo = NULL; // stores device info
DEBUG_FUNCTION_NAME(TEXT("SaveSingleDeviceData"));
if(FaxGetPortEx(g_hFaxSvcHandle, pDeviceInfo->dwDeviceId, &pPortInfo))
{
//
// Save the data to all devices and enable/disable FPF_RECEIVE depending on the data
//
pPortInfo->bSend = pDeviceInfo->bSend;
pPortInfo->ReceiveMode = pDeviceInfo->ReceiveMode;
pPortInfo->lptstrCsid = g_wizData.szCsid;
pPortInfo->lptstrTsid = g_wizData.szTsid;
pPortInfo->dwRings = g_wizData.dwRingCount;
if(!FaxSetPortEx(g_hFaxSvcHandle, pDeviceInfo->dwDeviceId, pPortInfo))
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxSetPortEx() failed with %d."), GetLastError());
bRes = FALSE;
}
FaxFreeBuffer(pPortInfo);
}
else
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxGetPortEx() failed with %d."), GetLastError());
bRes = FALSE;
}
//
// Save routing methods
//
for (dwCurrentRM = 0; dwCurrentRM < RM_COUNT; dwCurrentRM++)
{
LPTSTR lpCurSel;
LPCWSTR lpcwstrPrinterPath;
BOOL bEnabled;
//
// Check the validity first in the loop,
// then save the routing info
//
lpCurSel = g_wizData.pRouteInfo[dwCurrentRM].tszCurSel;
bEnabled = g_wizData.pRouteInfo[dwCurrentRM].bEnabled;
if ((RM_PRINT == dwCurrentRM) && bEnabled)
{
//
// Attempt to convert printer display name to printer path before we pass it on to the server
//
lpcwstrPrinterPath = FindPrinterPathFromName (g_pPrinterNames, g_dwNumPrinters, lpCurSel);
if (lpcwstrPrinterPath)
{
//
// We have a matching path - replace name with path.
//
lstrcpyn (lpCurSel, lpcwstrPrinterPath, MAX_PATH);
}
}
if(!FaxSetExtensionData(g_hFaxSvcHandle,
pDeviceInfo->dwDeviceId,
g_RoutingGuids[dwCurrentRM],
(LPBYTE)lpCurSel,
MAX_PATH * sizeof(TCHAR)) )
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxSetExtensionData() failed with %d."), GetLastError());
bRes = FALSE;
}
if(!FaxDeviceEnableRoutingMethod(g_hFaxSvcHandle,
pDeviceInfo->dwDeviceId,
g_RoutingGuids[dwCurrentRM],
bEnabled ? STATUS_ENABLE : STATUS_DISABLE ) )
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxDeviceEnableRoutingMethod() failed with %d."), GetLastError());
bRes = FALSE;
}
}
return bRes;
} // SaveSingleDeviceData
BOOL
SaveDeviceData()
/*++
Routine Description:
Save the fax devices configuration.
If there are more than one device, all enabled devices will be set
to current settings, except whether they are enabled to send/receive faxes.
Arguments:
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DWORD dw;
BOOL bRes = TRUE;
FAX_OUTBOUND_ROUTING_GROUP outRoutGr = {0};
DEBUG_FUNCTION_NAME(TEXT("SaveDeviceData"));
//
// 1st iteration - save disabled devices only
//
for(dw = 0; dw < g_wizData.dwDeviceCount; ++dw)
{
if (g_wizData.pDevInfo[dw].bSend || (FAX_DEVICE_RECEIVE_MODE_OFF != g_wizData.pDevInfo[dw].ReceiveMode))
{
//
// Device is active - skip it now
//
continue;
}
if (!SaveSingleDeviceData(&(g_wizData.pDevInfo[dw])))
{
bRes = FALSE;
}
}
//
// 2nd iteration - save enabled devices only
//
for(dw = 0; dw < g_wizData.dwDeviceCount; ++dw)
{
if (!g_wizData.pDevInfo[dw].bSend && (FAX_DEVICE_RECEIVE_MODE_OFF == g_wizData.pDevInfo[dw].ReceiveMode))
{
//
// Device is inactive - skip it
//
continue;
}
if (!SaveSingleDeviceData(&(g_wizData.pDevInfo[dw])))
{
bRes = FALSE;
}
}
if (!IsDesktopSKU ())
{
//
// Set device order for send
//
outRoutGr.dwSizeOfStruct = sizeof(outRoutGr);
outRoutGr.lpctstrGroupName = ROUTING_GROUP_ALL_DEVICES;
outRoutGr.dwNumDevices = g_wizData.dwDeviceCount;
outRoutGr.lpdwDevices = g_wizData.pdwSendDevOrder;
outRoutGr.Status = FAX_GROUP_STATUS_ALL_DEV_VALID;
if(!FaxSetOutboundGroup(g_hFaxSvcHandle, &outRoutGr))
{
DebugPrintEx(DEBUG_ERR, TEXT("FaxSetOutboundGroup() failed with %d."), GetLastError());
bRes = FALSE;
}
}
return bRes;
} // SaveDeviceData
void
FreeDeviceData()
/*++
Routine Description:
Free the devices data and release the memory.
Arguments:
Return Value:
none
--*/
{
DWORD dw;
DEBUG_FUNCTION_NAME(TEXT("FreeDeviceData()"));
MemFree(g_wizData.szCsid);
g_wizData.szCsid = NULL;
MemFree(g_wizData.szTsid);
g_wizData.szTsid = NULL;
MemFree(g_wizData.pdwSendDevOrder);
g_wizData.pdwSendDevOrder = NULL;
if (g_wizData.pDevInfo)
{
for(dw = 0; dw < g_wizData.dwDeviceCount; ++dw)
{
MemFree(g_wizData.pDevInfo[dw].szDeviceName);
g_wizData.pDevInfo[dw].szDeviceName = NULL;
}
MemFree(g_wizData.pDevInfo);
g_wizData.pDevInfo = NULL;
}
} // FreeDeviceData
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// ConvertCpeFilesToCov
//
// Purpose: Convert all of the *.CPE files from CSIDL_COMMON_APPDATA\Microsoft\Windows NT\MSFax\Common Coverpages
// directory to COV files at CSIDL_PERSONAL\Fax\Personal Coverpages.
// Mark that the conversion took place in the registry under HKCU so it will happen exactly once per user.
//
// Params:
// None
//
// Return Value:
// Win32 Error code
//
// Author:
//
///////////////////////////////////////////////////////////////////////////////////////
DWORD ConvertCpeFilesToCov()
{
DWORD dwErr = ERROR_SUCCESS;
INT iErr = 0;
WIN32_FIND_DATA FindFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
TCHAR szServerCpDir[2*MAX_PATH] = {0};
TCHAR szSearch[MAX_PATH] = {0};
HKEY hRegKey = NULL;
DWORD dwConverted = 0;
DEBUG_FUNCTION_NAME(_T("ConvertCpeFilesToCov"));
//
// Check whether this is the first time the current user call to this function
//
hRegKey = OpenRegistryKey(
HKEY_CURRENT_USER,
REGKEY_FAX_SETUP,
TRUE,
KEY_ALL_ACCESS);
if(hRegKey)
{
dwConverted = GetRegistryDword(hRegKey, REGVAL_CPE_CONVERT);
if (0 == dwConverted)
{
SetRegistryDword(hRegKey, REGVAL_CPE_CONVERT, TRUE);
}
RegCloseKey(hRegKey);
}
if (dwConverted) // We don't have to convert the cpe files, we did already
return ERROR_SUCCESS;
//
// the CPE files are in the server cover page directory
//
if ( !GetServerCpDir(NULL,szServerCpDir,ARR_SIZE(szServerCpDir)) )
{
dwErr = GetLastError();
DebugPrintEx(DEBUG_ERR,_T("GetServerCpDir failed (ec=%d)"),dwErr);
return dwErr;
}
//
// first we're going to convert the CPEs to COV.
// this is done by running FXSCOVER.EXE /CONVERT <CPE filename>
//
_sntprintf(szSearch, ARR_SIZE(szSearch)-1, _T("%s\\*.cpe"), szServerCpDir);
hFind = FindFirstFile(szSearch, &FindFileData);
if (hFind==INVALID_HANDLE_VALUE)
{
DebugPrintEx(DEBUG_MSG,_T("No CPEs exist in %s, exit function"),szServerCpDir);
return NO_ERROR;
}
//
// Go for each Cover Page
//
do
{
//
// FindFileData.cFileName
//
TCHAR szCmdLineParams[MAX_PATH*2] = {0};
SHELLEXECUTEINFO sei = {0};
_sntprintf(szCmdLineParams,ARR_SIZE(szCmdLineParams),_T("/CONVERT \"%s\\%s\""),szServerCpDir,FindFileData.cFileName);
sei.cbSize = sizeof (SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb = TEXT("open");
sei.lpFile = FAX_COVER_IMAGE_NAME;
sei.lpParameters = szCmdLineParams;
sei.lpDirectory = TEXT(".");
sei.nShow = SW_HIDE;
//
// Execute FXSCOVER.EXE and wait for it to end
//
if(!ShellExecuteEx(&sei))
{
dwErr = GetLastError();
DebugPrintEx(DEBUG_ERR, TEXT("ShellExecuteEx failed %d"), dwErr);
break; // don't try to continue with other files
}
dwErr = WaitForSingleObject(sei.hProcess, TIME_TO_WAIT_FOR_CONVERSTION);
CloseHandle(sei.hProcess);
if (WAIT_OBJECT_0 == dwErr)
{
//
// Shell execute completed successfully
//
dwErr = ERROR_SUCCESS;
continue;
}
else
{
DebugPrintEx(DEBUG_ERR, TEXT("WaitForSingleObject failed with %d"), dwErr);
DebugPrintEx(DEBUG_ERR, TEXT("WaitForSingleObject failed GetLastError=%d"), GetLastError());
break; // don't try to continue with other files
}
} while(FindNextFile(hFind, &FindFileData));
DebugPrintEx(DEBUG_MSG, _T("last call to FindNextFile() returns %ld."), GetLastError());
//
// Close Handle
//
FindClose(hFind);
return dwErr;
}