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.
 
 
 
 
 
 

640 lines
16 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
faxui.c
Abstract:
Common routines for fax driver user interface
Environment:
Fax driver user interface
Revision History:
01/09/96 -davidx-
Created it.
mm/dd/yy -author-
description
--*/
#include "faxui.h"
#include "forms.h"
#include <delayimp.h>
CRITICAL_SECTION faxuiSemaphore; // Semaphore for protecting critical sections
HANDLE g_hModule; // DLL instance handle
HANDLE g_hResource; // Resource DLL instance handle
HANDLE g_hFxsApiModule = NULL; // FXSAPI.DLL instance handle
PDOCEVENTUSERMEM gDocEventUserMemList = NULL; // Global list of user mode memory structures
INT _debugLevel = 1; // for debuggping purposes
static BOOL gs_bfaxuiSemaphoreInit = FALSE; // Flag for faxuiSemaphore CS initialization
BOOL g_bSHFusionInitialized = FALSE; // Fusion initialized flag
CRITICAL_SECTION g_csInitializeDll; // DLL initialization critical sections
BOOL g_bInitDllCritSection = FALSE; // Critical sections initialization flag
BOOL g_bDllInitialied = FALSE; // TRUE if the DLL successfuly initialized
char g_szDelayLoadFxsApiName[64] = {0}; // Case sensitive name of FxsApi.dll for delay load mechanism
static HMODULE gs_hShlwapi = NULL; // Shlwapi.dll handle
PPATHISRELATIVEW g_pPathIsRelativeW = NULL;
PPATHMAKEPRETTYW g_pPathMakePrettyW = NULL;
PSHAUTOCOMPLETE g_pSHAutoComplete = NULL;
//
// Blocks the re-entrancy of FxsWzrd.dll
// TRUE when there is running Fax Send Wizard instance
// FALSE otherwise
//
BOOL g_bRunningWizard = FALSE;
//
// Protects the g_bRunningWizard global variable from being accessed by multiple threads simultaneously
//
CRITICAL_SECTION g_csRunningWizard;
BOOL g_bInitRunningWizardCS = FALSE;
PVOID
PrMemAlloc(
SIZE_T size
)
{
return (PVOID)LocalAlloc(LPTR, size);
}
PVOID
PrMemReAlloc(
HLOCAL hMem,
SIZE_T size
)
{
return (PVOID)LocalReAlloc(hMem, size, LMEM_ZEROINIT);
}
VOID
PrMemFree(
PVOID ptr
)
{
if (ptr)
{
LocalFree((HLOCAL) ptr);
}
}
FARPROC WINAPI DelayLoadHandler(unsigned dliNotify,PDelayLoadInfo pdli)
{
switch (dliNotify)
{
case dliNotePreLoadLibrary:
if (_strnicmp(pdli->szDll, FAX_API_MODULE_NAME_A, strlen(FAX_API_MODULE_NAME_A))==0)
{
//
// Save the sensitive name DLL name for later use
//
strncpy(g_szDelayLoadFxsApiName, pdli->szDll, ARR_SIZE(g_szDelayLoadFxsApiName)-1);
// trying to load FXSAPI.DLL
if(!g_hFxsApiModule)
{
Assert(FALSE);
}
return g_hFxsApiModule;
}
}
return 0;
}
PfnDliHook __pfnDliNotifyHook = DelayLoadHandler;
BOOL
DllMain(
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:
{
DWORD dwVersion = GetVersion();
if(4 == (LOBYTE(LOWORD(dwVersion))) && 0 == (HIBYTE(LOWORD(dwVersion))))
{
//
// The current OS is NT4
//
// Keep our driver UI dll always loaded in memory
// We need this for NT4 clients
//
TCHAR szDllName[MAX_PATH+1] = {0};
if (!GetModuleFileName(hModule, szDllName, ARR_SIZE(szDllName)-1))
{
Error(("GetModuleFileName() failed with %d\n", GetLastError()));
return FALSE;
}
if(!LoadLibrary(szDllName))
{
Error(("LoadLibrary() failed with %d\n", GetLastError()));
return FALSE;
}
} // NT4
if (!InitializeCriticalSectionAndSpinCount (&faxuiSemaphore, (DWORD)0x80000000))
{
return FALSE;
}
gs_bfaxuiSemaphoreInit = TRUE;
if (!InitializeCriticalSectionAndSpinCount (&g_csInitializeDll, (DWORD)0x80000000))
{
return FALSE;
}
g_bInitDllCritSection = TRUE;
if (!InitializeCriticalSectionAndSpinCount(&g_csRunningWizard, (DWORD)0x80000000))
{
Error(("InitializeCriticalSectionAndSpinCount(&g_csRunningWizard) failed with %d\n", GetLastError()));
return FALSE;
}
g_bInitRunningWizardCS = TRUE;
g_hModule = hModule;
g_hResource = GetResInstance(hModule);
if(!g_hResource)
{
return FALSE;
}
HeapInitialize( NULL, PrMemAlloc, PrMemFree, PrMemReAlloc );
DisableThreadLibraryCalls(hModule);
break;
}
case DLL_PROCESS_DETACH:
while (gDocEventUserMemList != NULL)
{
PDOCEVENTUSERMEM pDocEventUserMem;
pDocEventUserMem = gDocEventUserMemList;
gDocEventUserMemList = gDocEventUserMemList->pNext;
FreePDEVUserMem(pDocEventUserMem);
}
if (gs_bfaxuiSemaphoreInit)
{
DeleteCriticalSection(&faxuiSemaphore);
gs_bfaxuiSemaphoreInit = FALSE;
}
if (g_bInitDllCritSection)
{
DeleteCriticalSection(&g_csInitializeDll);
g_bInitDllCritSection = FALSE;
}
if (g_bInitRunningWizardCS)
{
DeleteCriticalSection(&g_csRunningWizard);
g_bInitRunningWizardCS = FALSE;
}
UnInitializeDll();
HeapCleanup();
FreeResInstance();
break;
}
return TRUE;
} // DllMain
BOOL
InitializeDll()
{
BOOL bRet = TRUE;
INITCOMMONCONTROLSEX CommonControlsEx = {sizeof(INITCOMMONCONTROLSEX),
ICC_WIN95_CLASSES|ICC_DATE_CLASSES};
if(!g_bInitDllCritSection)
{
Assert(FALSE);
return FALSE;
}
EnterCriticalSection(&g_csInitializeDll);
if(g_bDllInitialied)
{
//
// The DLL already initialized
//
goto exit;
}
if (!InitCommonControlsEx(&CommonControlsEx))
{
Verbose(("InitCommonControlsEx failed"));
bRet = FALSE;
goto exit;
}
//
// Load FXSAPI.DLL
// Used by Delay Load mechanism
//
g_hFxsApiModule = LoadLibraryFromLocalFolder(FAX_API_MODULE_NAME, g_hModule);
if(!g_hFxsApiModule)
{
bRet = FALSE;
goto exit;
}
if (IsWinXPOS())
{
//
// We use fusion only for WinXP/.NET operating systems
// We also explictly link against shlwapi.dll for these operating systems.
//
if (!SHFusionInitializeFromModuleID(g_hModule, SXS_MANIFEST_RESOURCE_ID))
{
Verbose(("SHFusionInitializeFromModuleID failed"));
}
else
{
g_bSHFusionInitialized = TRUE;
}
gs_hShlwapi = LoadLibrary (TEXT("shlwapi.dll"));
if (gs_hShlwapi)
{
g_pPathIsRelativeW = (PPATHISRELATIVEW)GetProcAddress (gs_hShlwapi, "PathIsRelativeW");
g_pPathMakePrettyW = (PPATHMAKEPRETTYW)GetProcAddress (gs_hShlwapi, "PathMakePrettyW");
g_pSHAutoComplete = (PSHAUTOCOMPLETE) GetProcAddress (gs_hShlwapi, "SHAutoComplete");
if (!g_pPathIsRelativeW || !g_pPathMakePrettyW || !g_pSHAutoComplete)
{
Verbose (("Failed to link with shlwapi.dll - %d", GetLastError()));
}
}
else
{
Verbose (("Failed to load shlwapi.dll - %d", GetLastError()));
}
}
g_bDllInitialied = TRUE;
exit:
LeaveCriticalSection(&g_csInitializeDll);
return bRet;
} // InitializeDll
VOID
UnInitializeDll()
{
if(!g_bDllInitialied)
{
//
// The DLL is not initialized
//
return;
}
if(g_hFxsApiModule)
{
//
// Explicitly Unloading a Delay-Loaded DLL
//
if(!__FUnloadDelayLoadedDLL2(g_szDelayLoadFxsApiName))
{
//
// The DLL wasn't used by delay load
//
FreeLibrary(g_hFxsApiModule);
}
g_hFxsApiModule = NULL;
}
if (IsWinXPOS())
{
//
// We use fusion only for WinXP/.NET operating systems
// We also explictly link against shlwapi.dll for these operating systems.
//
ReleaseActivationContext();
if (g_bSHFusionInitialized)
{
SHFusionUninitialize();
g_bSHFusionInitialized = FALSE;
}
if (gs_hShlwapi)
{
FreeLibrary (gs_hShlwapi);
gs_hShlwapi = NULL;
g_pPathIsRelativeW = NULL;
g_pPathMakePrettyW = NULL;
g_pSHAutoComplete = NULL;
}
}
g_bDllInitialied = FALSE;
} // UnInitializeDll
LONG
CallCompstui(
HWND hwndOwner,
PFNPROPSHEETUI pfnPropSheetUI,
LPARAM lParam,
PDWORD pResult
)
/*++
Routine Description:
Calling common UI DLL entry point dynamically
Arguments:
hwndOwner, pfnPropSheetUI, lParam, pResult - Parameters passed to common UI DLL
Return Value:
Return value from common UI library
--*/
{
HINSTANCE hInstCompstui;
FARPROC pProc;
LONG Result = ERR_CPSUI_GETLASTERROR;
//
// Only need to call the ANSI version of LoadLibrary
//
static const CHAR szCompstui[] = "compstui.dll";
static const CHAR szCommonPropSheetUI[] = "CommonPropertySheetUIW";
if ((hInstCompstui = LoadLibraryA(szCompstui)) &&
(pProc = GetProcAddress(hInstCompstui, szCommonPropSheetUI)))
{
Result = (LONG)(*pProc)(hwndOwner, pfnPropSheetUI, lParam, pResult);
}
if (hInstCompstui)
FreeLibrary(hInstCompstui);
return Result;
}
VOID
GetCombinedDevmode(
PDRVDEVMODE pdmOut,
PDEVMODE pdmIn,
HANDLE hPrinter,
PPRINTER_INFO_2 pPrinterInfo2,
BOOL publicOnly
)
/*++
Routine Description:
Combine DEVMODE information:
start with the driver default
then merge with the system default //@ not done
then merge with the user default //@ not done
finally merge with the input devmode
//@ The end result of this merge operation is a dev mode with default values for all the public
//@ fields that are not specified or not valid. Input values for all the specified fields in the
//@ input dev mode that were specified and valid. And default (or per user in W2K) values for the private fields.
Arguments:
pdmOut - Pointer to the output devmode buffer
pdmIn - Pointer to an input devmode
hPrinter - Handle to a printer object
pPrinterInfo2 - Point to a PRINTER_INFO_2 structure or NULL
publicOnly - Only merge the public portion of the devmode
Return Value:
TRUE
--*/
{
PPRINTER_INFO_2 pAlloced = NULL;
PDEVMODE pdmUser;
//
// Get a PRINTER_INFO_2 structure if one is not provided
//
if (! pPrinterInfo2)
pPrinterInfo2 = pAlloced = MyGetPrinter(hPrinter, 2);
//
// Start with driver default devmode
//
if (! publicOnly) {
//@ Generates the driver default dev mode by setting default values for the public fields
//@ and loading per user dev mode for the private fields (W2K only for NT4 it sets default
//@ values for the private fields too).
DriverDefaultDevmode(pdmOut,
pPrinterInfo2 ? pPrinterInfo2->pPrinterName : NULL,
hPrinter);
}
//
// Merge with the system default devmode and user default devmode
//
if (pPrinterInfo2) {
#if 0
//
// Since we have per-user devmode and there is no way to
// change the printer's default devmode, there is no need
// to merge it here.
//
if (! MergeDevmode(pdmOut, pPrinterInfo2->pDevMode, publicOnly))
Error(("Invalid system default devmode\n"));
#endif
if (pdmUser = GetPerUserDevmode(pPrinterInfo2->pPrinterName)) {
if (! MergeDevmode(pdmOut, pdmUser, publicOnly))
Error(("Invalid user devmode\n"));
MemFree(pdmUser);
}
}
MemFree(pAlloced);
//
// Merge with the input devmode
//
//@ The merge process wil copy the private data as is.
//@ for public data it will only consider the fields which are of interest to the fax printer.
//@ it will copy them to the destination if they are specified and valid.
//@ The end result of this merge operation is a dev mode with default values for all the public
//@ fields that are not specified or not valid. Input values for all the specified fields in the
//@ input dev mode that were specified and valid. And default (or per user in W2K) values for the private fields.
if (! MergeDevmode(pdmOut, pdmIn, publicOnly))
Error(("Invalid input devmode\n"));
}
PUIDATA
FillUiData(
HANDLE hPrinter,
PDEVMODE pdmInput
)
/*++
Routine Description:
Fill in the data structure used by the fax driver user interface
Arguments:
hPrinter - Handle to the printer
pdmInput - Pointer to input devmode, NULL if there is none
Return Value:
Pointer to UIDATA structure, NULL if error.
--*/
{
PRINTER_INFO_2 *pPrinterInfo2 = NULL;
PUIDATA pUiData = NULL;
HANDLE hheap = NULL;
//
// Create a heap to manage memory
// Allocate memory to hold UIDATA structure
// Get printer info from the spooler
// Copy the driver name
//
if (! (hheap = HeapCreate(0, 4096, 0)) ||
! (pUiData = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(UIDATA))) ||
! (pPrinterInfo2 = MyGetPrinter(hPrinter, 2)))
{
if (hheap)
HeapDestroy(hheap);
MemFree(pPrinterInfo2);
return NULL;
}
pUiData->startSign = pUiData->endSign = pUiData;
pUiData->hPrinter = hPrinter;
pUiData->hheap = hheap;
//
// Combine various devmode information
//
GetCombinedDevmode(&pUiData->devmode, pdmInput, hPrinter, pPrinterInfo2, FALSE);
//
// Validate the form requested by the input devmode
//
if (! ValidDevmodeForm(hPrinter, &pUiData->devmode.dmPublic, NULL))
Error(("Invalid form specification\n"));
MemFree(pPrinterInfo2);
return pUiData;
}
BOOL
DevQueryPrintEx(
PDEVQUERYPRINT_INFO pDQPInfo
)
/*++
Routine Description:
Implementation of DDI entry point DevQueryPrintEx. Even though we don't
really need this entry point, we must export it so that the spooler
will load our driver UI.
Arguments:
pDQPInfo - Points to a DEVQUERYPRINT_INFO structure
Return Value:
TRUE if there is no conflicts, FALSE otherwise
--*/
{
//
// Do not execute any code before this initialization
//
if(!InitializeDll())
{
return FALSE;
}
return TRUE;
}