1677 lines
36 KiB
C
1677 lines
36 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
util.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Misc. utility functions used by the fax configuration applet
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Fax configuration applet
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
03/13/96 -davidx-
|
|||
|
Created it.
|
|||
|
|
|||
|
mm/dd/yy -author-
|
|||
|
description
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "faxcpl.h"
|
|||
|
#include "forms.h"
|
|||
|
#include "cfghelp.h"
|
|||
|
#include <shlobj.h>
|
|||
|
#include <mapicode.h>
|
|||
|
#include <winsprlp.h>
|
|||
|
|
|||
|
//
|
|||
|
// A flag to indicate whether we're inside SetDlgItemText call.
|
|||
|
// This is a kluge but we have no other way of telling whether
|
|||
|
// an EN_CHANGE message is caused by user action or by us calling
|
|||
|
// SetDlgItemText.
|
|||
|
//
|
|||
|
|
|||
|
BOOL insideSetDlgItemText = FALSE;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SetChangedFlag(
|
|||
|
HWND hDlg,
|
|||
|
INT pageIndex,
|
|||
|
BOOL changed
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Enable or disable the Apply button in the property sheet
|
|||
|
depending on if any of the dialog contents was changed
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Handle to the property page window
|
|||
|
pageIndex - Specifies the index of current property page
|
|||
|
changed - Specifies whether the Apply button should be enabled
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HWND hwndPropSheet;
|
|||
|
INT pageMask = (1 << pageIndex);
|
|||
|
|
|||
|
//
|
|||
|
// Enable or disable the Apply button as appropriate
|
|||
|
//
|
|||
|
|
|||
|
hwndPropSheet = GetParent(hDlg);
|
|||
|
|
|||
|
if (changed) {
|
|||
|
|
|||
|
PropSheet_Changed(hwndPropSheet, hDlg);
|
|||
|
gConfigData->changeFlag |= pageMask;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
gConfigData->changeFlag &= ~pageMask;
|
|||
|
|
|||
|
if (gConfigData->changeFlag == 0) {
|
|||
|
|
|||
|
PropSheet_UnChanged(hwndPropSheet, hDlg);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
GetMapiProfiles(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Connect to the server and get its MAPI profiles.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE if not
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if (gConfigData->pMapiProfiles)
|
|||
|
return TRUE;
|
|||
|
|
|||
|
if (!FaxGetMapiProfiles(gConfigData->hFaxSvc, (LPBYTE*) &gConfigData->pMapiProfiles))
|
|||
|
{
|
|||
|
gConfigData->pMapiProfiles = NULL;
|
|||
|
Error(("Cannot retrieve MapiProfiles: %d\n", GetLastError()));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PVOID
|
|||
|
MyEnumPrinters(
|
|||
|
LPTSTR pServerName,
|
|||
|
DWORD level,
|
|||
|
PDWORD pcPrinters,
|
|||
|
DWORD dwFlags
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Wrapper function for spooler API EnumPrinters
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pServerName - Specifies the name of the print server
|
|||
|
level - Level of PRINTER_INFO_x structure
|
|||
|
pcPrinters - Returns the number of printers enumerated
|
|||
|
dwFlags - Flag bits passed to EnumPrinters
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to an array of PRINTER_INFO_x structures
|
|||
|
NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PBYTE pPrinterInfo = NULL;
|
|||
|
DWORD cb;
|
|||
|
|
|||
|
if (! EnumPrinters(dwFlags, pServerName, level, NULL, 0, &cb, pcPrinters) &&
|
|||
|
GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
|
|||
|
(pPrinterInfo = MemAlloc(cb)) &&
|
|||
|
EnumPrinters(dwFlags, pServerName, level, pPrinterInfo, cb, &cb, pcPrinters))
|
|||
|
{
|
|||
|
return pPrinterInfo;
|
|||
|
}
|
|||
|
|
|||
|
Error(("EnumPrinters failed: %d\n", GetLastError()));
|
|||
|
MemFree(pPrinterInfo);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LPTSTR
|
|||
|
MakePortNameString(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compose a port name string consisting of all available fax devices
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to a list of comma-separated port names
|
|||
|
NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPTSTR pPortName, p;
|
|||
|
INT index, cb;
|
|||
|
|
|||
|
//
|
|||
|
// Connect to the fax service and retrieve the list of fax devices
|
|||
|
//
|
|||
|
|
|||
|
GetFaxDeviceAndConfigInfo();
|
|||
|
|
|||
|
//
|
|||
|
// Figure out the total size of port name string
|
|||
|
//
|
|||
|
|
|||
|
for (index=cb=0; index < gConfigData->cDevices; index++)
|
|||
|
cb += SizeOfString(gConfigData->pDevInfo[index].DeviceName);
|
|||
|
|
|||
|
if (cb == 0 || !(p = pPortName = MemAlloc(cb)))
|
|||
|
return NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Compose the port name string
|
|||
|
//
|
|||
|
|
|||
|
for (index=0; index < gConfigData->cDevices; index++) {
|
|||
|
|
|||
|
if (p != pPortName)
|
|||
|
*p++ = PORTNAME_SEPARATOR;
|
|||
|
|
|||
|
_tcscpy(p, gConfigData->pDevInfo[index].DeviceName);
|
|||
|
p += _tcslen(p);
|
|||
|
}
|
|||
|
|
|||
|
return pPortName;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
CheckFaxServerType(
|
|||
|
HWND hDlg,
|
|||
|
LPTSTR pPrinterName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Make sure the print server has fax server software installed
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Handle to the currently active property page
|
|||
|
pPrinterName - Specifies the name of the shared printer
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the fax server software is installed
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HANDLE hServer;
|
|||
|
LPTSTR p, pNoRemoteDrivers;
|
|||
|
INT status = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Derived the server name from the share name
|
|||
|
//
|
|||
|
|
|||
|
Assert(_tcsncmp(pPrinterName, TEXT("\\\\"), 2) == EQUAL_STRING);
|
|||
|
p = pPrinterName + 2;
|
|||
|
|
|||
|
if (p = _tcschr(p, TEXT(PATH_SEPARATOR))) {
|
|||
|
|
|||
|
*p = NUL;
|
|||
|
|
|||
|
if (OpenPrinter(pPrinterName, &hServer, NULL)) {
|
|||
|
|
|||
|
|
|||
|
if (pNoRemoteDrivers = GetPrinterDataStr(hServer, SPLREG_NO_REMOTE_PRINTER_DRIVERS)) {
|
|||
|
|
|||
|
if (_tcsstr(pNoRemoteDrivers, DRIVER_NAME) != NULL)
|
|||
|
status = IDS_NO_FAXSERVER;
|
|||
|
|
|||
|
MemFree(pNoRemoteDrivers);
|
|||
|
}
|
|||
|
|
|||
|
ClosePrinter(hServer);
|
|||
|
|
|||
|
} else
|
|||
|
status = IDS_SERVER_NOTALIVE;
|
|||
|
|
|||
|
*p = TEXT(PATH_SEPARATOR);
|
|||
|
|
|||
|
} else
|
|||
|
status = IDS_INVALID_SHARENAME;
|
|||
|
|
|||
|
if (status != 0)
|
|||
|
DisplayMessageDialog(hDlg, 0, 0, status);
|
|||
|
|
|||
|
return (status == 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PVOID
|
|||
|
FaxSvcEnumPorts(
|
|||
|
HANDLE hFaxSvc,
|
|||
|
PDWORD pcPorts
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Wrapper function for fax service API FaxEnumPorts
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hFaxSvc - Specifies a coneection handle to the fax service
|
|||
|
DWORD - Specifies the level of FAX_PORT_INFO structure desired
|
|||
|
pcPorts - Returns the number of devices managed by the fax service
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to an array of FAX_PORT_INFO_x structures
|
|||
|
NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PVOID pSvcPortInfo = NULL;
|
|||
|
|
|||
|
|
|||
|
if (!FaxEnumPorts(hFaxSvc, (PFAX_PORT_INFO*) &pSvcPortInfo, pcPorts)) {
|
|||
|
Error(("FaxEnumPorts failed: %d\n", GetLastError()));
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
return pSvcPortInfo;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
GetFaxDeviceAndConfigInfo(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Get a list of fax devices available on the system and
|
|||
|
retrieve fax configuration information from the service
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFAX_PORT_INFO pSvcPortInfo;
|
|||
|
PFAX_PORT_INFO pSvcPort;
|
|||
|
PCONFIG_PORT_INFO_2 pDevInfo;
|
|||
|
DWORD index;
|
|||
|
DWORD cPorts;
|
|||
|
DWORD cb;
|
|||
|
HANDLE FaxPortHandle;
|
|||
|
LPBYTE RoutingInfo;
|
|||
|
|
|||
|
|
|||
|
Verbose(("Enumerating fax ports ...\n"));
|
|||
|
Assert(ValidConfigData(gConfigData));
|
|||
|
|
|||
|
if (gConfigData->pDevInfo)
|
|||
|
return TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate memory to hold information about fax devices
|
|||
|
//
|
|||
|
|
|||
|
Assert(gConfigData->hFaxSvc != NULL);
|
|||
|
Assert(gConfigData->cDevices == 0);
|
|||
|
|
|||
|
if (! (pSvcPortInfo = FaxSvcEnumPorts(gConfigData->hFaxSvc, &cPorts)) ||
|
|||
|
! (gConfigData->pDevInfo = pDevInfo = MemAllocZ(sizeof(CONFIG_PORT_INFO_2) * cPorts)))
|
|||
|
{
|
|||
|
FaxFreeBuffer(pSvcPortInfo);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Collect information about each fax device. Here we're depending on the fact that
|
|||
|
// fax devices are enumerated in reverse priority order, i.e. the lowest priority
|
|||
|
// device is enumerated first.
|
|||
|
//
|
|||
|
|
|||
|
Verbose(("Available fax devices:\n"));
|
|||
|
|
|||
|
for (index=0; index < cPorts; index++, pDevInfo++) {
|
|||
|
|
|||
|
pSvcPort = &pSvcPortInfo[cPorts - index - 1];
|
|||
|
|
|||
|
Verbose(( " %ws\n", pSvcPort->DeviceName ));
|
|||
|
|
|||
|
pDevInfo->SizeOfStruct = pSvcPort->SizeOfStruct;
|
|||
|
pDevInfo->DeviceId = pSvcPort->DeviceId;
|
|||
|
pDevInfo->State = pSvcPort->State;
|
|||
|
pDevInfo->Flags = pSvcPort->Flags;
|
|||
|
pDevInfo->Rings = pSvcPort->Rings;
|
|||
|
pDevInfo->Priority = pSvcPort->Priority;
|
|||
|
pDevInfo->DeviceName = DuplicateString( pSvcPort->DeviceName );
|
|||
|
pDevInfo->CSID = DuplicateString( pSvcPort->Csid);
|
|||
|
pDevInfo->TSID = DuplicateString( pSvcPort->Tsid);
|
|||
|
pDevInfo->Mask = 0;
|
|||
|
pDevInfo->ProfileName = NULL;
|
|||
|
pDevInfo->PrinterName = NULL;
|
|||
|
pDevInfo->DirStore = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// open the fax port for query so we can get the routing info
|
|||
|
//
|
|||
|
|
|||
|
if (FaxOpenPort(gConfigData->hFaxSvc, pDevInfo->DeviceId, PORT_OPEN_QUERY, &FaxPortHandle )) {
|
|||
|
|
|||
|
//
|
|||
|
// get the store dir
|
|||
|
//
|
|||
|
|
|||
|
if (FaxGetRoutingInfo( FaxPortHandle, REGVAL_RM_FOLDER_GUID, &RoutingInfo, &cb )) {
|
|||
|
if (*((LPDWORD)RoutingInfo)) {
|
|||
|
pDevInfo->Mask |= LR_STORE;
|
|||
|
pDevInfo->DirStore = DuplicateString( (LPWSTR)(RoutingInfo+sizeof(DWORD)) );
|
|||
|
}
|
|||
|
|
|||
|
FaxFreeBuffer( RoutingInfo );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// get the printer name
|
|||
|
//
|
|||
|
|
|||
|
if (FaxGetRoutingInfo( FaxPortHandle, REGVAL_RM_PRINTING_GUID, &RoutingInfo, &cb )) {
|
|||
|
if (*((LPDWORD)RoutingInfo)) {
|
|||
|
pDevInfo->Mask |= LR_PRINT;
|
|||
|
pDevInfo->PrinterName = DuplicateString( (LPWSTR)(RoutingInfo+sizeof(DWORD)) );
|
|||
|
}
|
|||
|
|
|||
|
FaxFreeBuffer( RoutingInfo );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// get the email profile name
|
|||
|
//
|
|||
|
|
|||
|
if (FaxGetRoutingInfo( FaxPortHandle, REGVAL_RM_EMAIL_GUID, &RoutingInfo, &cb )) {
|
|||
|
if (*((LPDWORD)RoutingInfo)) {
|
|||
|
pDevInfo->Mask |= LR_EMAIL;
|
|||
|
pDevInfo->ProfileName = DuplicateString( (LPWSTR)(RoutingInfo+sizeof(DWORD)) );
|
|||
|
}
|
|||
|
|
|||
|
FaxFreeBuffer( RoutingInfo );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// get the inbox profile name
|
|||
|
//
|
|||
|
|
|||
|
if (FaxGetRoutingInfo( FaxPortHandle, REGVAL_RM_INBOX_GUID, &RoutingInfo, &cb )) {
|
|||
|
if (*((LPDWORD)RoutingInfo)) {
|
|||
|
pDevInfo->Mask |= LR_INBOX;
|
|||
|
MemFree( pDevInfo->ProfileName );
|
|||
|
pDevInfo->ProfileName = DuplicateString( (LPWSTR)(RoutingInfo+sizeof(DWORD)) );
|
|||
|
}
|
|||
|
|
|||
|
FaxFreeBuffer( RoutingInfo );
|
|||
|
}
|
|||
|
|
|||
|
FaxClose( FaxPortHandle );
|
|||
|
}
|
|||
|
|
|||
|
gConfigData->cDevices++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Retrieve fax configuration information from the service
|
|||
|
//
|
|||
|
|
|||
|
Assert( gConfigData->pFaxConfig == NULL );
|
|||
|
|
|||
|
if (!FaxGetConfiguration(gConfigData->hFaxSvc, &gConfigData->pFaxConfig)) {
|
|||
|
Error(("Cannot retrieve fax configuration information: %d\n", GetLastError()));
|
|||
|
gConfigData->pFaxConfig = NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Retrieve the logging categories
|
|||
|
//
|
|||
|
|
|||
|
Assert( gConfigData->pFaxLogging == NULL );
|
|||
|
|
|||
|
if (!FaxGetLoggingCategories( gConfigData->hFaxSvc, &gConfigData->pFaxLogging, &gConfigData->NumberCategories )) {
|
|||
|
Error(("Cannot retrieve fax logging category information: %d\n", GetLastError()));
|
|||
|
gConfigData->pFaxLogging = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
SaveFaxDeviceAndConfigInfo(
|
|||
|
HWND hDlg,
|
|||
|
INT pageIndex
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Save fax device and configuration information
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Handle to the currently active property page
|
|||
|
pageIndex - Specifies the currently active page index
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#define FAIL_SAVE_FAX_CONFIG(err) { errorId = err; goto ExitSaveFaxConfig; }
|
|||
|
|
|||
|
{
|
|||
|
PCONFIG_PORT_INFO_2 pDevInfo;
|
|||
|
FAX_PORT_INFO SvcPort;
|
|||
|
DWORD ec;
|
|||
|
INT index = 0;
|
|||
|
INT errorId = 0;
|
|||
|
DWORD cb;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Check if we're on the last page that has settable fax configuration info
|
|||
|
//
|
|||
|
|
|||
|
if ((gConfigData->changeFlag & CONFIGPAGE_MASK) != (1 << pageIndex)) {
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
if (gConfigData->hFaxSvc == NULL) {
|
|||
|
FAIL_SAVE_FAX_CONFIG(IDS_NULL_SERVICE_HANDLE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Save fax configuration information
|
|||
|
//
|
|||
|
|
|||
|
if (gConfigData->pFaxConfig &&
|
|||
|
! FaxSetConfiguration(gConfigData->hFaxSvc, gConfigData->pFaxConfig))
|
|||
|
{
|
|||
|
ec = GetLastError();
|
|||
|
Error(("FaxSetConfiguration failed: %d\n", ec));
|
|||
|
FAIL_SAVE_FAX_CONFIG((ec == ERROR_ACCESS_DENIED ? IDS_NO_AUTHORITY : IDS_FAXSETCONFIG_FAILED));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Save fax device information
|
|||
|
// NOTE: Here, we're calling FaxSetPort on every device which may be
|
|||
|
// a little redundant. But it shouldn't hurt anything.
|
|||
|
//
|
|||
|
|
|||
|
pDevInfo = gConfigData->pDevInfo;
|
|||
|
|
|||
|
for (index=0; index < gConfigData->cDevices; index++, pDevInfo++) {
|
|||
|
|
|||
|
HANDLE FaxPortHandle;
|
|||
|
LPBYTE RoutingInfo;
|
|||
|
|
|||
|
if (!FaxOpenPort(gConfigData->hFaxSvc, pDevInfo->DeviceId, PORT_OPEN_MODIFY, &FaxPortHandle )) {
|
|||
|
DisplayMessageDialog(hDlg, 0, 0, IDS_DEVICE_BUSY, pDevInfo->DeviceName);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
SvcPort.SizeOfStruct = pDevInfo->SizeOfStruct;
|
|||
|
SvcPort.DeviceId = pDevInfo->DeviceId;
|
|||
|
SvcPort.State = pDevInfo->State;
|
|||
|
SvcPort.Flags = pDevInfo->Flags;
|
|||
|
SvcPort.Rings = pDevInfo->Rings;
|
|||
|
SvcPort.Priority = pDevInfo->Priority;
|
|||
|
|
|||
|
SvcPort.DeviceName = pDevInfo->DeviceName;
|
|||
|
SvcPort.Tsid = pDevInfo->TSID;
|
|||
|
SvcPort.Csid = pDevInfo->CSID;
|
|||
|
|
|||
|
if (! FaxSetPort(FaxPortHandle, &SvcPort)) {
|
|||
|
|
|||
|
ec = GetLastError();
|
|||
|
Error(("FaxSetPort failed: %d\n", ec));
|
|||
|
FAIL_SAVE_FAX_CONFIG((ec == ERROR_ACCESS_DENIED ? IDS_NO_AUTHORITY : IDS_FAXSETPORT_FAILED));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// change the routing information
|
|||
|
//
|
|||
|
|
|||
|
cb = 4096;
|
|||
|
RoutingInfo = (LPBYTE) MemAllocZ( cb );
|
|||
|
if (!RoutingInfo) {
|
|||
|
Error(("Memory allocation failed: %d\n", GetLastError()));
|
|||
|
goto ExitSaveFaxConfig;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// set the store dir
|
|||
|
//
|
|||
|
|
|||
|
*((LPDWORD)RoutingInfo) = (pDevInfo->Mask & LR_STORE) > 0;
|
|||
|
if (pDevInfo->Mask & LR_STORE) {
|
|||
|
_tcscpy( (LPTSTR) (RoutingInfo+sizeof(DWORD)), pDevInfo->DirStore );
|
|||
|
}
|
|||
|
|
|||
|
if (!FaxSetRoutingInfo( FaxPortHandle, REGVAL_RM_FOLDER_GUID, RoutingInfo, cb )) {
|
|||
|
Error(("FaxSetRoutingInfo failed: %d\n", GetLastError()));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// set the printer name
|
|||
|
//
|
|||
|
|
|||
|
*((LPDWORD)RoutingInfo) = (pDevInfo->Mask & LR_PRINT) > 0;
|
|||
|
if (pDevInfo->Mask & LR_PRINT) {
|
|||
|
_tcscpy( (LPTSTR) (RoutingInfo+sizeof(DWORD)), pDevInfo->PrinterName ? pDevInfo->PrinterName : TEXT("") );
|
|||
|
}
|
|||
|
|
|||
|
if (!FaxSetRoutingInfo( FaxPortHandle, REGVAL_RM_PRINTING_GUID, RoutingInfo, cb )) {
|
|||
|
Error(("FaxSetRoutingInfo failed: %d\n", GetLastError()));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// set the email profile name
|
|||
|
//
|
|||
|
|
|||
|
*((LPDWORD)RoutingInfo) = (pDevInfo->Mask & LR_EMAIL) > 0;
|
|||
|
if (pDevInfo->Mask & LR_EMAIL) {
|
|||
|
_tcscpy( (LPTSTR) (RoutingInfo+sizeof(DWORD)), pDevInfo->ProfileName ? pDevInfo->ProfileName : TEXT("") );
|
|||
|
}
|
|||
|
|
|||
|
if (!FaxSetRoutingInfo( FaxPortHandle, REGVAL_RM_EMAIL_GUID, RoutingInfo, cb )) {
|
|||
|
Error(("FaxSetRoutingInfo failed: %d\n", GetLastError()));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// set the inbox profile name
|
|||
|
//
|
|||
|
|
|||
|
*((LPDWORD)RoutingInfo) = (pDevInfo->Mask & LR_INBOX) > 0;
|
|||
|
if (pDevInfo->Mask & LR_INBOX) {
|
|||
|
_tcscpy( (LPTSTR) (RoutingInfo+sizeof(DWORD)), pDevInfo->ProfileName ? pDevInfo->ProfileName : TEXT("") );
|
|||
|
}
|
|||
|
|
|||
|
if (!FaxSetRoutingInfo( FaxPortHandle, REGVAL_RM_INBOX_GUID, RoutingInfo, cb )) {
|
|||
|
Error(("FaxSetRoutingInfo failed: %d\n", GetLastError()));
|
|||
|
}
|
|||
|
|
|||
|
MemFree( RoutingInfo );
|
|||
|
|
|||
|
FaxClose( FaxPortHandle );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// save the logging categories
|
|||
|
//
|
|||
|
|
|||
|
if (!FaxSetLoggingCategories( gConfigData->hFaxSvc, gConfigData->pFaxLogging, gConfigData->NumberCategories )) {
|
|||
|
Error(("Cannot change fax logging category information: %d\n", GetLastError()));
|
|||
|
}
|
|||
|
|
|||
|
ExitSaveFaxConfig:
|
|||
|
|
|||
|
//
|
|||
|
// If an error was encountered, display a message box and return FALSE.
|
|||
|
// Otherwise, return TRUE to indicate success.
|
|||
|
//
|
|||
|
|
|||
|
if (errorId != 0) {
|
|||
|
|
|||
|
DisplayMessageDialog(hDlg, 0, 0, errorId);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (gConfigData->priorityChanged) {
|
|||
|
|
|||
|
DisplayMessageDialog(hDlg,
|
|||
|
MB_OK | MB_ICONINFORMATION,
|
|||
|
IDS_PRIORITY_CHANGE_TITLE,
|
|||
|
IDS_PRIORITY_CHANGE_MESSAGE);
|
|||
|
|
|||
|
gConfigData->priorityChanged = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
FreeFaxDeviceAndConfigInfo(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Dispose of fax device and configuration information
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PCONFIG_PORT_INFO_2 pDevInfo = gConfigData->pDevInfo;
|
|||
|
|
|||
|
while (gConfigData->cDevices > 0) {
|
|||
|
|
|||
|
MemFree(pDevInfo->DeviceName);
|
|||
|
MemFree(pDevInfo->TSID);
|
|||
|
MemFree(pDevInfo->PrinterName);
|
|||
|
MemFree(pDevInfo->DirStore);
|
|||
|
MemFree(pDevInfo->ProfileName);
|
|||
|
MemFree(pDevInfo->CSID);
|
|||
|
|
|||
|
gConfigData->cDevices--;
|
|||
|
pDevInfo++;
|
|||
|
}
|
|||
|
|
|||
|
MemFree(gConfigData->pDevInfo);
|
|||
|
gConfigData->pDevInfo = NULL;
|
|||
|
gConfigData->cDevices = 0;
|
|||
|
|
|||
|
FaxFreeBuffer(gConfigData->pFaxConfig);
|
|||
|
gConfigData->pFaxConfig = NULL;
|
|||
|
|
|||
|
FaxFreeBuffer(gConfigData->pMapiProfiles);
|
|||
|
gConfigData->pMapiProfiles = NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LPTSTR
|
|||
|
DuplicateString(
|
|||
|
LPCTSTR pSrcStr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Make a duplicate of the specified character string
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pSrcStr - Specifies the source string to be duplicated
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to the duplicated string, NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPTSTR pDestStr;
|
|||
|
INT size;
|
|||
|
|
|||
|
if (pSrcStr == NULL)
|
|||
|
return NULL;
|
|||
|
|
|||
|
size = SizeOfString(pSrcStr);
|
|||
|
|
|||
|
if (pDestStr = MemAlloc(size))
|
|||
|
CopyMemory(pDestStr, pSrcStr, size);
|
|||
|
else
|
|||
|
Error(("Couldn't duplicate string: %ws\n", pSrcStr));
|
|||
|
|
|||
|
return pDestStr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
EnableControls(
|
|||
|
HWND hDlg,
|
|||
|
INT *pCtrlIds,
|
|||
|
BOOL enabled
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Enable or disable a set of controls in a dialog
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwnd - Specifies the handle to the dialog window
|
|||
|
pCtrlIds - Array of control IDs to be enabled or disabled (0 terminated)
|
|||
|
enabled - Whether to enable or disable the specified controls
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
while (*pCtrlIds) {
|
|||
|
|
|||
|
EnableWindow(GetDlgItem(hDlg, *pCtrlIds), enabled);
|
|||
|
pCtrlIds++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ShowControls(
|
|||
|
HWND hDlg,
|
|||
|
INT *pCtrlIds,
|
|||
|
BOOL visible
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Show or hide a set of controls in a dialog
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwnd - Specifies the handle to the dialog window
|
|||
|
pCtrlIds - Array of control IDs to be shown or hidden (0 terminated)
|
|||
|
visible - Whether to show or hide the specified controls
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
INT nCmdShow = visible ? SW_SHOW : SW_HIDE;
|
|||
|
|
|||
|
while (*pCtrlIds) {
|
|||
|
|
|||
|
ShowWindow(GetDlgItem(hDlg, *pCtrlIds), nCmdShow);
|
|||
|
pCtrlIds++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
LimitTextFields(
|
|||
|
HWND hDlg,
|
|||
|
INT *pLimitInfo
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Limit the maximum length for a number of text fields
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Specifies the handle to the dialog window
|
|||
|
pLimitInfo - Array of text field control IDs and their maximum length
|
|||
|
ID for the 1st text field, maximum length for the 1st text field
|
|||
|
ID for the 2nd text field, maximum length for the 2nd text field
|
|||
|
...
|
|||
|
0
|
|||
|
Note: The maximum length counts the NUL-terminator.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
while (*pLimitInfo != 0) {
|
|||
|
|
|||
|
SendDlgItemMessage(hDlg, pLimitInfo[0], EM_SETLIMITTEXT, pLimitInfo[1]-1, 0);
|
|||
|
pLimitInfo += 2;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INT
|
|||
|
DisplayMessageDialog(
|
|||
|
HWND hwndParent,
|
|||
|
UINT type,
|
|||
|
INT titleStrId,
|
|||
|
INT formatStrId,
|
|||
|
...
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Display a message dialog box
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwndParent - Specifies a parent window for the error message dialog
|
|||
|
type - Specifies the type of message box to be displayed
|
|||
|
titleStrId - Title string (could be a string resource ID)
|
|||
|
formatStrId - Message format string (could be a string resource ID)
|
|||
|
...
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Same as the return value from MessageBox
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPTSTR pTitle, pFormat, pMessage;
|
|||
|
INT result;
|
|||
|
va_list ap;
|
|||
|
|
|||
|
pTitle = pFormat = pMessage = NULL;
|
|||
|
|
|||
|
if ((pTitle = AllocStringZ(MAX_TITLE_LEN)) &&
|
|||
|
(pFormat = AllocStringZ(MAX_STRING_LEN)) &&
|
|||
|
(pMessage = AllocStringZ(MAX_MESSAGE_LEN)))
|
|||
|
{
|
|||
|
//
|
|||
|
// Load dialog box title string resource
|
|||
|
//
|
|||
|
|
|||
|
if (titleStrId == 0)
|
|||
|
titleStrId = IDS_ERROR_DLGTITLE;
|
|||
|
|
|||
|
LoadString(ghInstance, titleStrId, pTitle, MAX_TITLE_LEN);
|
|||
|
|
|||
|
//
|
|||
|
// Load message format string resource
|
|||
|
//
|
|||
|
|
|||
|
LoadString(ghInstance, formatStrId, pFormat, MAX_STRING_LEN);
|
|||
|
|
|||
|
//
|
|||
|
// Compose the message string
|
|||
|
//
|
|||
|
|
|||
|
va_start(ap, formatStrId);
|
|||
|
wvsprintf(pMessage, pFormat, ap);
|
|||
|
va_end(ap);
|
|||
|
|
|||
|
//
|
|||
|
// Display the message box
|
|||
|
//
|
|||
|
|
|||
|
if (type == 0)
|
|||
|
type = MB_OK | MB_ICONERROR;
|
|||
|
|
|||
|
result = MessageBox(hwndParent, pMessage, pTitle, type);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
MessageBeep(MB_ICONHAND);
|
|||
|
result = 0;
|
|||
|
}
|
|||
|
|
|||
|
MemFree(pTitle);
|
|||
|
MemFree(pFormat);
|
|||
|
MemFree(pMessage);
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ToggleListViewCheckbox(
|
|||
|
HWND hwndLV,
|
|||
|
INT index
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Toggle the checkbox associated with the specified list view item
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwndLV - Handle to the list view control
|
|||
|
index - Specifies the index of the interested item
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT state;
|
|||
|
|
|||
|
if (IsListViewItemChecked(hwndLV, index))
|
|||
|
state = UNCHECKED_STATE;
|
|||
|
else
|
|||
|
state = CHECKED_STATE;
|
|||
|
|
|||
|
ListView_SetItemState(hwndLV, index, state, LVIS_STATEIMAGEMASK);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
InitFaxDeviceListView(
|
|||
|
HWND hwndLV,
|
|||
|
DWORD flags,
|
|||
|
PCOLUMNINFO pColumnInfo
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialize the fax device list view
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwndLV - Handle to the fax device list view
|
|||
|
flags - Miscellaneous flag bits
|
|||
|
pColumnInfo - Specifies columns to be displayed and their relative widths
|
|||
|
ID for the 1st column, relative width for the 1st column
|
|||
|
ID for the 2nd column, relative width for the 2nd column
|
|||
|
...
|
|||
|
0, 0
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Column header string resource IDs
|
|||
|
//
|
|||
|
|
|||
|
static INT columnHeaderIDs[MAX_COLUMNS] = {
|
|||
|
0,
|
|||
|
IDS_DEVICE_NAME_COLUMN,
|
|||
|
IDS_CSID_COLUMN,
|
|||
|
IDS_TSID_COLUMN,
|
|||
|
IDS_STATUS_COLUMN,
|
|||
|
};
|
|||
|
|
|||
|
INT index, nColumns, widthDenom, lvWidth;
|
|||
|
RECT rect;
|
|||
|
LV_COLUMN lvc;
|
|||
|
LV_ITEM lvi;
|
|||
|
TCHAR buffer[MAX_TITLE_LEN];
|
|||
|
|
|||
|
//
|
|||
|
// Count the number of columns
|
|||
|
//
|
|||
|
|
|||
|
if (hwndLV == NULL)
|
|||
|
return;
|
|||
|
|
|||
|
nColumns = widthDenom = 0;
|
|||
|
|
|||
|
while (pColumnInfo[nColumns].columnId) {
|
|||
|
|
|||
|
widthDenom += pColumnInfo[nColumns].columnWidth;
|
|||
|
nColumns++;
|
|||
|
}
|
|||
|
|
|||
|
Assert(nColumns > 0 && nColumns <= MAX_COLUMNS);
|
|||
|
Assert(pColumnInfo[0].columnId == COLUMN_DEVICE_NAME);
|
|||
|
|
|||
|
lvc.mask = LVCF_TEXT;
|
|||
|
lvc.pszText = buffer;
|
|||
|
lvc.cchTextMax = MAX_TITLE_LEN;
|
|||
|
|
|||
|
if (ListView_GetColumn(hwndLV, 0, &lvc) && ! IsEmptyString(buffer)) {
|
|||
|
|
|||
|
//
|
|||
|
// The columns have already be inserted
|
|||
|
//
|
|||
|
|
|||
|
ListView_DeleteAllItems(hwndLV);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// This is the first time and the list view is not initialized
|
|||
|
// Insert the specified columns into the list view
|
|||
|
//
|
|||
|
|
|||
|
GetClientRect(hwndLV, &rect);
|
|||
|
lvWidth = rect.right - rect.left;
|
|||
|
|
|||
|
//
|
|||
|
// Insert a column of check boxes if requested
|
|||
|
//
|
|||
|
|
|||
|
if (flags & LV_HASCHECKBOX) {
|
|||
|
|
|||
|
HBITMAP hbmp;
|
|||
|
HIMAGELIST himl;
|
|||
|
|
|||
|
if (hbmp = LoadBitmap(ghInstance, MAKEINTRESOURCE(IDB_CHECKSTATES))) {
|
|||
|
|
|||
|
if (himl = ImageList_Create(16, 16, TRUE, 2, 0)) {
|
|||
|
|
|||
|
ImageList_AddMasked(himl, hbmp, RGB(255, 0, 0));
|
|||
|
ListView_SetImageList(hwndLV, himl, LVSIL_STATE);
|
|||
|
|
|||
|
} else
|
|||
|
Error(("LoadBitmap failed: %d\n", GetLastError()));
|
|||
|
|
|||
|
DeleteObject(hbmp);
|
|||
|
|
|||
|
} else
|
|||
|
Error(("LoadBitmap failed: %d\n", GetLastError()));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Insert list view columns
|
|||
|
//
|
|||
|
|
|||
|
ZeroMemory(&lvc, sizeof(lvc));
|
|||
|
|
|||
|
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
|||
|
lvc.fmt = LVCFMT_LEFT;
|
|||
|
lvc.pszText = buffer;
|
|||
|
|
|||
|
for (index=0; index < nColumns; index++) {
|
|||
|
|
|||
|
lvc.cx = lvWidth * pColumnInfo[index].columnWidth / widthDenom;
|
|||
|
lvc.iSubItem = index;
|
|||
|
|
|||
|
if (index == nColumns-1)
|
|||
|
lvc.cx -= GetSystemMetrics(SM_CXVSCROLL);
|
|||
|
|
|||
|
LoadString(ghInstance,
|
|||
|
columnHeaderIDs[pColumnInfo[index].columnId],
|
|||
|
buffer,
|
|||
|
MAX_TITLE_LEN);
|
|||
|
|
|||
|
if (ListView_InsertColumn(hwndLV, index, &lvc) == -1)
|
|||
|
Error(("ListView_InsertColumn failed\n"));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Insert list view items list view content
|
|||
|
//
|
|||
|
|
|||
|
ZeroMemory(&lvi, sizeof(lvi));
|
|||
|
lvi.iSubItem = 0;
|
|||
|
lvi.mask = LVIF_STATE | LVIF_TEXT;
|
|||
|
|
|||
|
if (flags & LV_HASCHECKBOX) {
|
|||
|
|
|||
|
lvi.state = UNCHECKED_STATE;
|
|||
|
lvi.stateMask = LVIS_STATEIMAGEMASK;
|
|||
|
}
|
|||
|
|
|||
|
for (index = 0; index < gConfigData->cDevices; index ++) {
|
|||
|
|
|||
|
//
|
|||
|
// The first column is always the device name
|
|||
|
//
|
|||
|
|
|||
|
lvi.iItem = index;
|
|||
|
lvi.pszText = gConfigData->pDevInfo[index].DeviceName;
|
|||
|
|
|||
|
if (ListView_InsertItem(hwndLV, &lvi) == -1) {
|
|||
|
|
|||
|
Error(("ListView_InsertItem failed\n"));
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Display the remaining columns
|
|||
|
//
|
|||
|
|
|||
|
UpdateFaxDeviceListViewColumns(hwndLV, pColumnInfo, 1);
|
|||
|
|
|||
|
//
|
|||
|
// The initial selection is the first fax device in the list
|
|||
|
//
|
|||
|
|
|||
|
ListView_SetItemState(hwndLV, 0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LPTSTR
|
|||
|
MakeDeviceStatusString(
|
|||
|
DWORD state
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Assemble fax device status string
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
state - Current state of the fax device
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to the device status string, NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
static struct _STATEBITINFO {
|
|||
|
|
|||
|
DWORD bitFlag;
|
|||
|
INT stringId;
|
|||
|
|
|||
|
} stateBitInfo[] = {
|
|||
|
|
|||
|
FPS_AVAILABLE, IDS_STATUS_AVAILABLE,
|
|||
|
FPS_UNAVAILABLE, IDS_STATUS_UNAVAILABLE,
|
|||
|
FPS_SENDING, IDS_STATUS_SENDING,
|
|||
|
FPS_RECEIVING, IDS_STATUS_RECEIVING,
|
|||
|
FPS_ABORTING, IDS_STATUS_ABORTING,
|
|||
|
FPS_ROUTING, IDS_STATUS_ROUTING,
|
|||
|
FPS_DIALING, IDS_STATUS_DIALING,
|
|||
|
FPS_COMPLETED, IDS_STATUS_COMPLETED,
|
|||
|
FPS_HANDLED, IDS_STATUS_HANDLED,
|
|||
|
FPS_BUSY, IDS_STATUS_BUSY,
|
|||
|
FPS_NO_ANSWER, IDS_STATUS_NO_ANSWER,
|
|||
|
FPS_BAD_ADDRESS, IDS_STATUS_BAD_ADDRESS,
|
|||
|
FPS_NO_DIAL_TONE, IDS_STATUS_NO_DIAL_TONE,
|
|||
|
FPS_DISCONNECTED, IDS_STATUS_DISCONNECTED,
|
|||
|
FPS_FATAL_ERROR, IDS_STATUS_FATAL_ERROR,
|
|||
|
FPS_NOT_FAX_CALL, IDS_STATUS_NOT_FAX_CALL,
|
|||
|
FPS_CALL_DELAYED, IDS_STATUS_CALL_DELAYED,
|
|||
|
FPS_CALL_BLACKLISTED, IDS_STATUS_CALL_BLACKLISTED,
|
|||
|
FPS_INITIALIZING, IDS_STATUS_INITIALIZING,
|
|||
|
FPS_OFFLINE, IDS_STATUS_OFFLINE,
|
|||
|
FPS_ANSWERED, IDS_STATUS_ANSWERED
|
|||
|
};
|
|||
|
|
|||
|
LPTSTR pBuffer, p;
|
|||
|
INT index, count, statusLen, separatorLen;
|
|||
|
BOOL appendSeparator = FALSE;
|
|||
|
TCHAR separator[MAX_TITLE_LEN];
|
|||
|
|
|||
|
//
|
|||
|
// Load the string that's used separated status fields
|
|||
|
//
|
|||
|
|
|||
|
if (! LoadString(ghInstance, IDS_STATUS_SEPARATOR, separator, MAX_TITLE_LEN))
|
|||
|
_tcscpy(separator, TEXT(", "));
|
|||
|
|
|||
|
separatorLen = _tcslen(separator);
|
|||
|
|
|||
|
//
|
|||
|
// Calculate how much space we need
|
|||
|
//
|
|||
|
|
|||
|
count = sizeof(stateBitInfo) / sizeof(struct _STATEBITINFO);
|
|||
|
|
|||
|
for (index=statusLen=0; index < count; index++) {
|
|||
|
|
|||
|
if ((state & stateBitInfo[index].bitFlag) == stateBitInfo[index].bitFlag) {
|
|||
|
|
|||
|
TCHAR buffer[MAX_TITLE_LEN];
|
|||
|
INT length;
|
|||
|
|
|||
|
length = LoadString(ghInstance,
|
|||
|
stateBitInfo[index].stringId,
|
|||
|
buffer,
|
|||
|
MAX_TITLE_LEN);
|
|||
|
|
|||
|
if (length == 0) {
|
|||
|
|
|||
|
Error(("LoadString failed: %d\n", GetLastError()));
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
statusLen += (length + separatorLen);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Assemble the status string
|
|||
|
//
|
|||
|
|
|||
|
if (p = pBuffer = MemAllocZ((statusLen + 1) * sizeof(TCHAR))) {
|
|||
|
|
|||
|
for (index=0; index < count; index++) {
|
|||
|
|
|||
|
if ((state & stateBitInfo[index].bitFlag) == stateBitInfo[index].bitFlag) {
|
|||
|
|
|||
|
if (appendSeparator) {
|
|||
|
|
|||
|
_tcscpy(p, separator);
|
|||
|
p += separatorLen;
|
|||
|
appendSeparator = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
statusLen = LoadString(ghInstance,
|
|||
|
stateBitInfo[index].stringId,
|
|||
|
p,
|
|||
|
MAX_TITLE_LEN);
|
|||
|
|
|||
|
if (statusLen > 0) {
|
|||
|
|
|||
|
p += statusLen;
|
|||
|
appendSeparator = TRUE;
|
|||
|
|
|||
|
} else
|
|||
|
Error(("LoadString failed: %d\n", GetLastError()));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return pBuffer;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
UpdateFaxDeviceListViewColumns(
|
|||
|
HWND hwndLV,
|
|||
|
PCOLUMNINFO pColumnInfo,
|
|||
|
INT startColumn
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Refresh columns in the fax device list view
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwndLV - Handle to the fax device list view
|
|||
|
pColumnInfo - Specifies columns to be redisplayed
|
|||
|
startColumn - Specifies the first column index
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPTSTR pBuffer, pColumnStr;
|
|||
|
LV_ITEM lvi;
|
|||
|
INT item, nItems, column, nColumns;
|
|||
|
|
|||
|
//
|
|||
|
// Count the number of items in the list view
|
|||
|
//
|
|||
|
|
|||
|
if ((hwndLV == NULL) ||
|
|||
|
(nItems = ListView_GetItemCount(hwndLV)) < 0 ||
|
|||
|
(nItems > gConfigData->cDevices))
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Count the total number of columns
|
|||
|
//
|
|||
|
|
|||
|
for (nColumns=0; pColumnInfo[nColumns].columnId; nColumns++)
|
|||
|
NULL;
|
|||
|
|
|||
|
ZeroMemory(&lvi, sizeof(lvi));
|
|||
|
lvi.mask = LVIF_TEXT;
|
|||
|
|
|||
|
//
|
|||
|
// Go through each item in the list view
|
|||
|
//
|
|||
|
|
|||
|
for (item=0; item < nItems; item++) {
|
|||
|
|
|||
|
PCONFIG_PORT_INFO_2 pDevInfo = gConfigData->pDevInfo + item;
|
|||
|
|
|||
|
lvi.iItem = item;
|
|||
|
|
|||
|
//
|
|||
|
// Go through each column for every list view item
|
|||
|
//
|
|||
|
|
|||
|
for (column=startColumn; column < nColumns; column++) {
|
|||
|
|
|||
|
pBuffer = pColumnStr = NULL;
|
|||
|
|
|||
|
switch (pColumnInfo[column].columnId) {
|
|||
|
|
|||
|
case COLUMN_CSID:
|
|||
|
|
|||
|
pColumnStr = pDevInfo->CSID;
|
|||
|
break;
|
|||
|
|
|||
|
case COLUMN_TSID:
|
|||
|
|
|||
|
pColumnStr = pDevInfo->TSID;
|
|||
|
break;
|
|||
|
|
|||
|
case COLUMN_STATUS:
|
|||
|
|
|||
|
pBuffer = pColumnStr = MakeDeviceStatusString(pDevInfo->State);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
Assert(FALSE);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
lvi.iSubItem = column;
|
|||
|
lvi.pszText = pColumnStr ? pColumnStr : TEXT("");
|
|||
|
|
|||
|
if (! ListView_SetItem(hwndLV, &lvi))
|
|||
|
Error(("ListView_SetItem failed\n"));
|
|||
|
|
|||
|
MemFree(pBuffer);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INT
|
|||
|
BrowseCallbackProc(
|
|||
|
HWND hwnd,
|
|||
|
UINT uMsg,
|
|||
|
LPARAM lParam,
|
|||
|
LPARAM lpData
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Callback function for SHBrowseForFolder
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwnd - Handle to the browse dialog box
|
|||
|
uMsg - Identifying the reason for the callback
|
|||
|
lParam - Message parameter
|
|||
|
lpData - Application-defined value given in BROWSEINFO.lParam
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
0
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
if (uMsg == BFFM_INITIALIZED)
|
|||
|
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
DoBrowseForDirectory(
|
|||
|
HWND hDlg,
|
|||
|
INT textFieldId,
|
|||
|
INT titleStrId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Browse for a directory
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg - Specifies the dialog window on which the Browse button is displayed
|
|||
|
textFieldId - Specifies the text field adjacent to the Browse button
|
|||
|
titleStrId - Specifies the title to be displayed in the browse window
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if successful, FALSE if the user presses Cancel
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPITEMIDLIST pidl;
|
|||
|
TCHAR buffer[MAX_PATH];
|
|||
|
TCHAR title[MAX_TITLE_LEN];
|
|||
|
VOID SHFree(LPVOID);
|
|||
|
BOOL result = FALSE;
|
|||
|
|
|||
|
BROWSEINFO bi = {
|
|||
|
|
|||
|
hDlg,
|
|||
|
NULL,
|
|||
|
buffer,
|
|||
|
title,
|
|||
|
BIF_RETURNONLYFSDIRS,
|
|||
|
BrowseCallbackProc,
|
|||
|
(LPARAM) buffer,
|
|||
|
};
|
|||
|
|
|||
|
if (! LoadString(ghInstance, titleStrId, title, MAX_TITLE_LEN))
|
|||
|
title[0] = NUL;
|
|||
|
|
|||
|
if (! GetDlgItemText(hDlg, textFieldId, buffer, MAX_PATH))
|
|||
|
buffer[0] = NUL;
|
|||
|
|
|||
|
if (pidl = SHBrowseForFolder(&bi)) {
|
|||
|
|
|||
|
if (SHGetPathFromIDList(pidl, buffer)) {
|
|||
|
|
|||
|
if (_tcslen(buffer) > MAX_ARCHIVE_DIR)
|
|||
|
DisplayMessageDialog(hDlg, 0, 0, IDS_DIR_TOO_LONG);
|
|||
|
else {
|
|||
|
|
|||
|
MySetDlgItemText(hDlg, textFieldId, buffer);
|
|||
|
result = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SHFree(pidl);
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
HandleHelpPopup(
|
|||
|
HWND hDlg,
|
|||
|
UINT message,
|
|||
|
UINT wParam,
|
|||
|
LPARAM lParam,
|
|||
|
INT pageIndex
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Handle context-sensitive help in property sheet pages
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hDlg, message, wParam, lParam - Parameters passed to the dialog procedure
|
|||
|
pageIndex - Specifies the index of the current property sheet page
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the message is handle, FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
static LPDWORD arrayHelpIDs[MAX_PAGES] = {
|
|||
|
|
|||
|
clientOptionsHelpIDs,
|
|||
|
personalCoverPageHelpIDs,
|
|||
|
userInfoHelpIDs,
|
|||
|
|
|||
|
serverOptionsHelpIDs,
|
|||
|
serverCoverPageHelpIDs,
|
|||
|
sendOptionsHelpIDs,
|
|||
|
receiveOptionsHelpIDs,
|
|||
|
devicePriorityHelpIDs,
|
|||
|
deviceStatusHelpIDs,
|
|||
|
loggingHelpIDs,
|
|||
|
NULL,
|
|||
|
statusMonitorHelpIDs
|
|||
|
};
|
|||
|
|
|||
|
Assert(pageIndex >= 0 && pageIndex < MAX_PAGES);
|
|||
|
|
|||
|
if (message == WM_HELP) {
|
|||
|
|
|||
|
WinHelp(((LPHELPINFO) lParam)->hItemHandle,
|
|||
|
FAXCFG_HELP_FILENAME,
|
|||
|
HELP_WM_HELP,
|
|||
|
(DWORD) arrayHelpIDs[pageIndex]);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
WinHelp((HWND) wParam,
|
|||
|
FAXCFG_HELP_FILENAME,
|
|||
|
HELP_CONTEXTMENU,
|
|||
|
(DWORD) arrayHelpIDs[pageIndex]);
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PFAX_DEVICE_STATUS
|
|||
|
FaxSvcGetDeviceStatus(
|
|||
|
HANDLE hFaxSvc,
|
|||
|
DWORD DeviceId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Wrapper function for fax service API FaxGetDeviceStatus
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hFaxSvc - Specifies a coneection handle to the fax service
|
|||
|
DeviceId - Specifies the ID of the interested device
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Pointer to a FAX_DEVICE_STATUS structure,
|
|||
|
NULL if there is an error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PBYTE pFaxStatus = NULL;
|
|||
|
HANDLE FaxPortHandle = NULL;
|
|||
|
|
|||
|
|
|||
|
if ((hFaxSvc == NULL) ||
|
|||
|
FaxOpenPort(hFaxSvc, DeviceId, PORT_OPEN_QUERY, &FaxPortHandle) == FALSE ||
|
|||
|
!FaxGetDeviceStatus(FaxPortHandle, (PFAX_DEVICE_STATUS*)&pFaxStatus))
|
|||
|
{
|
|||
|
Error(("FaxGetDeviceStatus failed: %d\n", GetLastError()));
|
|||
|
pFaxStatus = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (FaxPortHandle) {
|
|||
|
FaxClose( FaxPortHandle );
|
|||
|
}
|
|||
|
|
|||
|
return (PFAX_DEVICE_STATUS) pFaxStatus;
|
|||
|
}
|