|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
faxcpl.c
Abstract:
Implementation of the control panel applet entry point
Environment:
Windows NT fax configuration applet
Revision History:
02/27/96 -davidx- Created it.
mm/dd/yy -author- description
--*/
#include "faxcpl.h"
#include <tapi.h>
#include "faxdev.h"
//
// Global variable definitions
//
HANDLE ghInstance = NULL; // Fax monitor DLL instance handle
PCONFIGDATA gConfigData = NULL; // Fax configuration data structure
INT _debugLevel = 1; // Control the amount of debug messages generated
//
// Setup API for determining whether the user has admin privilege on a machine
//
BOOL IsUserAdmin( VOID );
extern BOOL WINAPI _CRT_INIT(HANDLE, ULONG, PVOID);
BOOL DllEntryPoint( HANDLE hModule, ULONG ulReason, PCONTEXT pContext )
/*++
Routine Description:
DLL initialization procedure.
Arguments:
hModule - DLL instance handle ulReason - Reason for the call pContext - Pointer to context (not used by us)
Return Value:
TRUE if DLL is initialized successfully, FALSE otherwise.
--*/
{ switch (ulReason) {
case DLL_PROCESS_ATTACH: #if DBG
_CRT_INIT(hModule, ulReason, pContext); #endif
ghInstance = hModule; break;
case DLL_PROCESS_DETACH:
FaxConfigCleanup(); #if DBG
_CRT_INIT(hModule, ulReason, pContext); #endif
break; }
return TRUE; }
INT DetermineFaxConfigType( BOOL CplInit )
/*++
Routine Description:
Determine the type of fax installation
Arguments:
CplInit - if this is TRUE then don't display the message box
Return Value:
FAXCONFIG_CLIENT - client installation FAXCONFIG_WORKSTATION - workstation installation FAXCONFIG_SERVER - server installation
-1 if there is an error
--*/
{ HANDLE FaxHandle = NULL; DWORD InstallType; DWORD InstalledPlatforms; DWORD ProductType; HKEY hKey; DWORD Size; DWORD Type;
//
// look at the machine registry for an install type
// if the install type is for a network client, then
// that is the cpl that we present. if there is a
// network client and a server installed on this machine
// then the install type will contain a mask of those
// two values and this check will fail. this check
// is here so that on a network client only install
// we don't go off and try to talk to a server.
//
if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_FAX_SETUP, &hKey ) != ERROR_SUCCESS) { return -1; }
Size = sizeof(InstallType); if (RegQueryValueEx( hKey, REGVAL_FAXINSTALL_TYPE, NULL, &Type, (LPBYTE) &InstallType, &Size ) != ERROR_SUCCESS) { RegCloseKey( hKey ); return -1; }
RegCloseKey( hKey );
if (InstallType == FAX_INSTALL_NETWORK_CLIENT ) { return FAXCONFIG_CLIENT; }
if (CplInit) { goto noconnect; } //
// ask the server for the install type
//
if ((!FaxConnectFaxServer( gConfigData->pServerName, &FaxHandle)) || (!FaxGetInstallType( FaxHandle, &InstallType, &InstalledPlatforms, &ProductType ))) { if (FaxHandle) { FaxClose( FaxHandle ); }
DisplayMessageDialog( NULL, 0, 0, IDS_NULL_SERVICE_HANDLE );
return -1; }
FaxClose( FaxHandle );
noconnect: Verbose(("Fax installation type: 0x%x\n", InstallType));
if (InstallType & FAX_INSTALL_SERVER) InstallType = FAXCONFIG_SERVER; else if (InstallType & FAX_INSTALL_WORKSTATION) InstallType = FAXCONFIG_WORKSTATION; else InstallType = FAXCONFIG_CLIENT;
return InstallType; }
LPTSTR VerifyServerName( LPTSTR pServerName )
/*++
Routine Description:
Verify the server name is well-formed
Arguments:
pServerName - Specifies the input server name
Return Value:
Pointer to a copy of the verified server name NULL if there is an error
--*/
{ LPTSTR pVerifiedName;
Assert(pServerName != NULL);
if (pVerifiedName = MemAlloc(SizeOfString(pServerName) + 2*sizeof(TCHAR))) {
//
// Make sure the server name always starts with double backslash (\\)
//
pVerifiedName[0] = pVerifiedName[1] = TEXT(PATH_SEPARATOR);
while (*pServerName == TEXT(PATH_SEPARATOR)) pServerName++;
_tcscpy(pVerifiedName+2, pServerName); }
return pVerifiedName; }
INT FaxConfigInit( LPTSTR pServerName, BOOL CplInit )
/*++
Routine Description:
Initialize fax configuration DLL
Arguments:
pServerName - Specifies the name of the fax server machine. Pass NULL for local machine.
CplInit - TRUE if called due to CPL_INIT message
Return Value:
-1 - An error has occurred FAXCONFIG_CLIENT - FAXCONFIG_SERVER - FAXCONFIG_WORKSTATION - Indicates the type of configuration the user can run
--*/
{ //
// Allocate memory for the fax configuration data structure
//
Assert(gConfigData == NULL);
if (! (gConfigData = MemAllocZ(sizeof(CONFIGDATA)))) {
Error(("Memory allocation failed\n")); return -1; }
gConfigData->startSign = gConfigData->endSign = gConfigData;
//
// Make sure the server name is well-formed
// Determine the type of fax configuration to be run
//
if ((pServerName && !(gConfigData->pServerName = VerifyServerName(pServerName))) || (gConfigData->configType = DetermineFaxConfigType(CplInit)) < 0) { FaxConfigCleanup(); return -1; }
return gConfigData->configType; }
VOID FaxConfigCleanup( VOID )
/*++
Routine Description:
Deinitialize fax configuration DLL
Arguments:
NONE
Return Value:
NONE
--*/
{ if (gConfigData != NULL) {
Assert(ValidConfigData(gConfigData));
//
// Disconnect from the fax service if we're currently connected
//
if (gConfigData->hFaxSvc) FaxClose(gConfigData->hFaxSvc);
//
// Free up memory used to hold various information:
// printer information
// form information
// port information
//
FreeFaxDeviceAndConfigInfo();
FreeCoverPageInfo(gConfigData->pCPInfo); MemFree(gConfigData->pServerName); MemFree(gConfigData); gConfigData = NULL;
DeinitTapiService(); } }
//
// Information about each fax configuration page
//
typedef struct _FAXCFG_PAGEINFO {
INT dialogId; DLGPROC dialogProc;
} FAXCFG_PAGEINFO, *PFAXCFG_PAGEINFO;
static FAXCFG_PAGEINFO ClientConfigPageInfo[] = {
{ IDD_CLIENT_COVERPG, ClientCoverPageProc }, { IDD_USER_INFO, UserInfoProc } };
static FAXCFG_PAGEINFO ServerConfigPageInfo[] = {
{ IDD_SERVER_OPTIONS, ServerOptionsProc }, { IDD_SERVER_COVERPG, ServerCoverPageProc }, { IDD_SEND_OPTIONS, SendOptionsProc }, { IDD_RECEIVE_OPTIONS, ReceiveOptionsProc }, { IDD_DEVICE_PRIORITY, DevicePriorityProc }, { IDD_DEVICE_STATUS, DeviceStatusProc }, { IDD_LOGGING, DiagLogProc }, { IDD_SERVER_GENERAL, GeneralProc } };
static FAXCFG_PAGEINFO WorkstationConfigPageInfo[] = {
{ IDD_CLIENT_COVERPG, ClientCoverPageProc }, { IDD_USER_INFO, UserInfoProc },
{ IDD_SERVER_OPTIONS, ServerOptionsProc }, { IDD_SEND_OPTIONS, SendOptionsProc }, { IDD_RECEIVE_OPTIONS, ReceiveOptionsProc }, { IDD_LOGGING, DiagLogProc }, { IDD_STATUS_OPTIONS, StatusOptionsProc } };
#define MAX_CLIENT_PAGES (sizeof(ClientConfigPageInfo) / sizeof(FAXCFG_PAGEINFO))
#define MAX_SERVER_PAGES (sizeof(ServerConfigPageInfo) / sizeof(FAXCFG_PAGEINFO))
#define MAX_WORKSTATION_PAGES (sizeof(WorkstationConfigPageInfo) / sizeof(FAXCFG_PAGEINFO))
INT FaxConfigGetPageHandles( HPROPSHEETPAGE *phPropSheetPages, INT count, PFAXCFG_PAGEINFO pPageInfo, INT nPages )
{ //
// Zero-initialize the input buffer
//
if (count > 0) {
if (phPropSheetPages == NULL) {
SetLastError(ERROR_INVALID_PARAMETER); return -1; }
ZeroMemory(phPropSheetPages, sizeof(HPROPSHEETPAGE) * count); }
//
// Make sure the input buffer is large enough to hold all available pages
//
if (count >= nPages) {
PROPSHEETPAGE psp; INT index;
ZeroMemory(&psp, sizeof(psp)); psp.dwSize = sizeof(PROPSHEETPAGE); psp.hInstance = ghInstance; psp.lParam = (LPARAM) gConfigData;
for (index=0; index < nPages; index++) {
//
// Create property page handles
//
psp.pszTemplate = MAKEINTRESOURCE(pPageInfo[index].dialogId); psp.pfnDlgProc = pPageInfo[index].dialogProc;
if (! (phPropSheetPages[index] = CreatePropertySheetPage(&psp))) {
Error(("CreatePropertySheetPage failed: %d\n", GetLastError())); break; } }
//
// If we failed to create handles for all property pages,
// we must destroy any handles we already created.
//
if (index < nPages) {
while (--index >= 0) DestroyPropertySheetPage(phPropSheetPages[index]);
return -1; } }
return nPages; }
BOOL DoConnectFaxService( VOID )
/*++
Routine Description:
Connect to the fax service if necessary
Arguments:
NONE
Return Value:
TRUE if successful, FALSE otherwise
--*/
{ DWORD InstallType; DWORD InstalledPlatforms; DWORD ProductType;
Assert(ValidConfigData(gConfigData)); Assert(gConfigData->configType == FAXCONFIG_SERVER || gConfigData->configType == FAXCONFIG_WORKSTATION);
if ((! gConfigData->hFaxSvc && ! FaxConnectFaxServer(gConfigData->pServerName, &gConfigData->hFaxSvc)) || ! FaxGetInstallType( gConfigData->hFaxSvc, &InstallType, &InstalledPlatforms, &ProductType )) { DisplayMessageDialog(NULL, 0, 0, IDS_NO_FAX_SERVICE); gConfigData->hFaxSvc = NULL; }
return (gConfigData->hFaxSvc != NULL); }
//
// Get an array of handles to client/server/workstation configuration pages
//
// Parameters:
//
// phPropSheetPages - Specifies a buffer for storing property page handles
// count - Specifies the maximum number of handles the input buffer can hold
//
// Return value:
//
// -1 - An error has occurred
// >0 - Total number of configuration pages available
//
// Note:
//
// To figure out how large the input buffer should be, the caller can
// first call these functions with phPropSheetPages set to NULL and
// count set to 0.
//
INT FaxConfigGetClientPages( HPROPSHEETPAGE *phPropSheetPages, INT count )
{ //
// We can only display client pages for non-workstation configuration types
//
if (!ValidConfigData(gConfigData) || gConfigData->configType == FAXCONFIG_WORKSTATION) {
SetLastError(ERROR_INVALID_FUNCTION); return -1; }
return FaxConfigGetPageHandles(phPropSheetPages, count, ClientConfigPageInfo, MAX_CLIENT_PAGES); }
INT GetDeviceProviderPages( HPROPSHEETPAGE *phPropSheetPages, INT count ) { HKEY hKey, hKeyDev; DWORD PageCnt = 0; DWORD Index = 0; WCHAR KeyName[MAX_PATH+1]; WCHAR ImageName[MAX_PATH+1]; HMODULE hMod; PFAXDEVCONFIGURE pFaxDevConfigure; DWORD Size; DWORD Type;
if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_DEVICE_PROVIDER_KEY, &hKey ) != ERROR_SUCCESS) { return PageCnt; }
while( RegEnumKey( hKey, Index, KeyName, sizeof(KeyName)/sizeof(WCHAR) ) == ERROR_SUCCESS) {
if (RegOpenKey( hKey, KeyName, &hKeyDev ) == ERROR_SUCCESS) {
Size = sizeof(KeyName); if (RegQueryValueEx( hKeyDev, REGVAL_IMAGE_NAME, 0, &Type, (LPBYTE)KeyName, &Size ) == ERROR_SUCCESS) {
ExpandEnvironmentStrings( KeyName, ImageName, sizeof(ImageName)/sizeof(TCHAR) );
hMod = LoadLibrary( ImageName ); if (hMod) { pFaxDevConfigure = (PFAXDEVCONFIGURE) GetProcAddress( hMod, "FaxDevConfigure" ); if (pFaxDevConfigure) { //
// this device provider supports configuration
// lets call the dll and get the pages
//
if (pFaxDevConfigure( &phPropSheetPages[PageCnt] )) { PageCnt += 1; } } else { FreeLibrary( hMod ); } } } RegCloseKey( hKeyDev ); } if (PageCnt == (DWORD) count) { break; } Index += 1; }
RegCloseKey( hKey );
return PageCnt; }
INT FaxConfigGetServerPages( HPROPSHEETPAGE *phPropSheetPages, INT count )
{ DWORD DevPages = 0; DWORD SvrPages = 0;
//
// We can only display server pages for server configuration type
//
if (!ValidConfigData(gConfigData) || gConfigData->configType != FAXCONFIG_SERVER) {
SetLastError(ERROR_INVALID_FUNCTION); return -1; }
if (!DoConnectFaxService()) { return -1; }
SvrPages = FaxConfigGetPageHandles( phPropSheetPages, count, ServerConfigPageInfo, MAX_SERVER_PAGES ); if (SvrPages) { count -= SvrPages; phPropSheetPages += SvrPages; }
DevPages = GetDeviceProviderPages( phPropSheetPages, count ); if (DevPages) { count -= DevPages; phPropSheetPages += DevPages; }
return SvrPages + DevPages; }
INT FaxConfigGetWorkstationPages( HPROPSHEETPAGE *phPropSheetPages, INT count )
{ DWORD DevPages = 0; DWORD WksPages = 0;
//
// We can only display workstation pages for workstation configuration type
//
if (!ValidConfigData(gConfigData) || gConfigData->configType != FAXCONFIG_WORKSTATION) {
SetLastError(ERROR_INVALID_FUNCTION); return -1; }
if (! DoConnectFaxService()) return -1;
WksPages = FaxConfigGetPageHandles( phPropSheetPages, count, WorkstationConfigPageInfo, MAX_WORKSTATION_PAGES ); if (WksPages) { count -= WksPages; phPropSheetPages += WksPages; }
DevPages = GetDeviceProviderPages( phPropSheetPages, count ); if (DevPages) { count -= DevPages; phPropSheetPages += DevPages; }
return WksPages + DevPages; }
|