summaryrefslogtreecommitdiffstats
path: root/private/mvdm/fax/wowfaxui/wowfaxui.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/fax/wowfaxui/wowfaxui.c')
-rw-r--r--private/mvdm/fax/wowfaxui/wowfaxui.c874
1 files changed, 874 insertions, 0 deletions
diff --git a/private/mvdm/fax/wowfaxui/wowfaxui.c b/private/mvdm/fax/wowfaxui/wowfaxui.c
new file mode 100644
index 000000000..bace4cff2
--- /dev/null
+++ b/private/mvdm/fax/wowfaxui/wowfaxui.c
@@ -0,0 +1,874 @@
+//************************************************************************
+// Generic Win 3.1 fax printer driver support. User Interface functions
+// which are called by WINSPOOL.
+//
+// I don't think performance is a big issue here. - nandurir
+//
+// History:
+// 02-jan-95 nandurir created.
+// 01-feb-95 reedb Clean-up, support printer install and bug fixes.
+// 14-mar-95 reedb Use GDI hooks to move most functionality to UI.
+//
+//************************************************************************
+
+#define WOWFAX_INC_COMMON_CODE
+
+#include "windows.h"
+#include "wowfaxui.h"
+#include "winspool.h"
+
+#define DEF_DRV_DOCUMENT_EVENT_DBG_STR
+#include "gdispool.h"
+#include "winddiui.h"
+
+//************************************************************************
+// Globals
+//************************************************************************
+
+HINSTANCE ghInst;
+FAXDEV gdev;
+WORD gdmDriverExtra = sizeof(DEVMODEW);
+
+DEVMODEW gdmDefaultDevMode;
+
+CRITICAL_SECTION CriticalSection;
+LPCRITICAL_SECTION lpCriticalSection = &CriticalSection;
+
+//************************************************************************
+// DllInitProc
+//************************************************************************
+
+BOOL DllInitProc(HMODULE hModule, DWORD Reason, PCONTEXT pContext)
+{
+ UNREFERENCED_PARAMETER(pContext);
+
+ if (Reason == DLL_PROCESS_ATTACH) {
+ DisableThreadLibraryCalls(hModule);
+ }
+ InitializeCriticalSection(lpCriticalSection);
+ ghInst = (HINSTANCE) hModule;
+
+ return(TRUE);
+}
+
+//************************************************************************
+// PrinterProperties
+//************************************************************************
+
+BOOL PrinterProperties(HWND hwnd, HANDLE hPrinter)
+{
+ TCHAR szMsg[WOWFAX_MAX_USER_MSG_LEN];
+ TCHAR szTitle[WOWFAX_MAX_USER_MSG_LEN];
+
+ if (LoadString(ghInst, WOWFAX_NAME_STR, szTitle, WOWFAX_MAX_USER_MSG_LEN)) {
+ if (LoadString(ghInst, WOWFAX_SELF_CONFIG_STR, szMsg, WOWFAX_MAX_USER_MSG_LEN)) {
+ MessageBox(hwnd, szMsg, szTitle, MB_OK);
+ }
+ }
+ return TRUE;
+}
+
+//************************************************************************
+// SetupFaxDev - Do some common FaxDev setup: Calculate the size of the
+// mapped file section for use by the inter-process communication
+// handler. Create and set the mapped section. Get the 16-bit driver
+// info from the registry and copy it into the mapped section. Build
+// pointers for variable length stuff we copied to the mapped section.
+// Return zero on failure, or current offset into mapped section.
+//************************************************************************
+
+UINT SetupFaxDev(PWSTR pDeviceName, LPFAXDEV lpdev)
+{
+ LPREGFAXDRVINFO16 lpRegFaxDrvInfo16;
+ DWORD iOffset = 0;
+
+ // Get the driver and port names from the registry where they were written
+ // by the 16-bit fax driver install program using WriteProfileString.
+ if ((lpRegFaxDrvInfo16 = Get16BitDriverInfoFromRegistry(pDeviceName))) {
+
+ //
+ // Count dmDriverExtra twice, once for each devmode. Use cached
+ // gdmDriverExtra value. Normally winspool/common dialogs and others,
+ // call the DocumentProperties with fMode = 0 to get the size. So we
+ // update gdmDriverExtra when such a call is made. We leave extra
+ // room to DWORD align both In and Out pointers.
+ //
+
+ lpdev->cbMapLow = sizeof(FAXDEV);
+ lpdev->cbMapLow += sizeof(DEVMODE) * 2;
+ lpdev->cbMapLow += gdmDriverExtra * 2;
+ lpdev->cbMapLow += sizeof(DWORD) * 2; // Leave room for DWORD align.
+ lpdev->cbMapLow += (lstrlen(lpRegFaxDrvInfo16->lpDriverName) + 1) * sizeof(TCHAR);
+ lpdev->cbMapLow += (lstrlen(lpRegFaxDrvInfo16->lpPortName) + 1) * sizeof(TCHAR);
+
+ lpdev->idMap = GetCurrentThreadId();
+
+ if (InterProcCommHandler(lpdev, DRVFAX_CREATEMAP)) {
+ if (InterProcCommHandler(lpdev, DRVFAX_SETMAPDATA)) {
+
+ // Copy the printer/device name to the WOWFAXINFO struct.
+ lstrcpy(lpdev->lpMap->szDeviceName, pDeviceName);
+
+ // Calculate the pointers into the mapped file section and copy
+ // the variable length data to the mapped file section.
+
+ // Printer driver and port names.
+ iOffset = sizeof(*lpdev->lpMap);
+ lpdev->lpMap->lpDriverName = (LPTSTR) iOffset;
+ (PWSTR)iOffset += lstrlen(lpRegFaxDrvInfo16->lpDriverName) + 1;
+ lstrcpy((PWSTR)((LPBYTE)lpdev->lpMap + (DWORD)lpdev->lpMap->lpDriverName), lpRegFaxDrvInfo16->lpDriverName);
+ lpdev->lpMap->lpPortName = (LPTSTR) iOffset;
+ (PWSTR)iOffset += lstrlen(lpRegFaxDrvInfo16->lpPortName) + 1;
+ lstrcpy((PWSTR)((LPBYTE)lpdev->lpMap + (DWORD)lpdev->lpMap->lpPortName), lpRegFaxDrvInfo16->lpPortName);
+ }
+ }
+ Free16BitDriverInfo(lpRegFaxDrvInfo16);
+ }
+ return iOffset;
+}
+
+//************************************************************************
+// DrvDocumentProperties
+//************************************************************************
+
+LONG DrvDocumentProperties(HWND hwnd, HANDLE hPrinter, PWSTR pDeviceName,
+ PDEVMODE pdmOut, PDEVMODE pdmIn, DWORD fMode)
+{
+ FAXDEV dev = gdev;
+ LPFAXDEV lpdev = &dev;
+ LONG lRet = -1;
+ DWORD iOffset;
+ DWORD cbT;
+ DWORD dwWowProcID, dwCallerProcID;
+ PRINTER_INFO_2 *pPrinterInfo2 = NULL;
+
+ LOGDEBUG(1, (L"WOWFAXUI!DrvDocumentProperties, pdmOut: %X, pdmIn: %X, fMode: %X\n", pdmOut, pdmIn, fMode));
+
+ // Check for get default devmode case, use spooler to get it if possible.
+ if (!pdmIn && pdmOut && !(fMode & DM_IN_PROMPT)) {
+ if (pPrinterInfo2 = MyGetPrinter(hPrinter, 2)) {
+ if (pPrinterInfo2->pDevMode) {
+ LOGDEBUG(1, (L" Using spooler default devmode\n"));
+ cbT = pPrinterInfo2->pDevMode->dmSize +
+ pPrinterInfo2->pDevMode->dmDriverExtra;
+
+ memcpy(pdmOut, pPrinterInfo2->pDevMode, cbT);
+ lRet = IDOK;
+ goto LeaveDDP;
+ }
+ }
+ }
+
+ if (iOffset = SetupFaxDev(pDeviceName, lpdev)) {
+ lpdev->lpMap->msg = WM_DDRV_EXTDMODE;
+
+ // Calculate the pointers into the mapped file section and copy
+ // the variable length data to the mapped file section.
+ DRVFAX_DWORDALIGN(iOffset);
+ lpdev->lpMap->lpIn = (LPDEVMODEW)((pdmIn) ? iOffset : 0);
+ iOffset += sizeof(*pdmIn) + gdmDriverExtra;
+
+ DRVFAX_DWORDALIGN(iOffset);
+ lpdev->lpMap->lpOut = (LPDEVMODEW)((pdmOut) ? iOffset : 0);
+ iOffset += sizeof(*pdmOut) + gdmDriverExtra;
+
+ //
+ // if Input is non-null copy the data even if fMode doesn't
+ // have the appropriate flag.
+ //
+
+ if (pdmIn) {
+ // apps don't pass DM_MODIFY even if they mean it - ie
+ // pdmIn will be non-null but they won't or this flag.
+ // The 32bit rasdd extracts data from pdmIn even if the
+ // DM_MODIFY flag is not set. So we need to do the same
+
+ if (fMode != 0) {
+ fMode |= DM_IN_BUFFER;
+ }
+
+ iOffset = (DWORD)lpdev->lpMap + (DWORD)lpdev->lpMap->lpIn;
+ RtlCopyMemory((LPVOID)iOffset, pdmIn,
+ sizeof(*pdmIn) + min(gdmDriverExtra, pdmIn->dmDriverExtra));
+
+ // reset dmDriverExtra in pdmIn.
+ ((LPDEVMODE)iOffset)->dmDriverExtra =
+ min(gdmDriverExtra, pdmIn->dmDriverExtra);
+ }
+
+ if (!(fMode & (DM_COPY | DM_OUT_BUFFER))) {
+ lpdev->lpMap->lpOut = 0;
+ }
+
+ lpdev->lpMap->wCmd = (WORD)fMode;
+
+ // valid size of this map
+ lpdev->lpMap->cData = lpdev->cbMapLow;
+
+
+ lpdev->lpMap->hwndui = hwnd;
+ if (fMode & DM_IN_PROMPT) {
+ GetWindowThreadProcessId(hwnd, &dwCallerProcID);
+ GetWindowThreadProcessId(lpdev->lpMap->hwnd, &dwWowProcID);
+
+ if (dwWowProcID == dwCallerProcID) {
+
+ // If the calling process is the same as the 'wowfaxclass' window
+ // (WOW/WOWEXEC) use CallWindow instead of SendMessage so we don't
+ // deadlock WOW when trying to put up the 16-bit fax driver UI.
+
+ InterProcCommHandler(lpdev, DRVFAX_CALLWOW);
+ }
+ else {
+ InterProcCommHandler(lpdev, DRVFAX_SENDNOTIFYWOW);
+ }
+ }
+ else {
+ InterProcCommHandler(lpdev, DRVFAX_SENDTOWOW);
+ }
+
+ lRet = (lpdev->lpMap->status) ? (LONG)lpdev->lpMap->retvalue : lRet;
+ if (lRet > 0) {
+ if ((fMode & DM_OUT_BUFFER) && (lRet == IDOK) && pdmOut) {
+ iOffset = (DWORD)lpdev->lpMap + (DWORD)lpdev->lpMap->lpOut;
+ RtlCopyMemory(pdmOut, (LPDEVMODE)iOffset,
+ sizeof(*pdmOut)+ ((LPDEVMODE)iOffset)->dmDriverExtra);
+
+ // LATER : what about the formname etc. fields - new on NT
+ }
+ else if (fMode == 0) {
+ // update our dmDriverExtra
+ gdmDriverExtra = max(lRet, gdmDriverExtra);
+ }
+ }
+ else {
+ LOGDEBUG(0, (L"WOWFAXUI!DrvDocumentProperties failed, lpdev->lpMap->status: %X, lpdev->lpMap->retvalue: %X\n", lpdev->lpMap->status, (LONG)lpdev->lpMap->retvalue));
+ }
+ InterProcCommHandler(lpdev, DRVFAX_DESTROYMAP);
+ }
+
+LeaveDDP:
+ if (pPrinterInfo2) {
+ LocalFree(pPrinterInfo2);
+ }
+
+ LOGDEBUG(1, (L"WOWFAXUI!DrvDocumentProperties returning: %X, pdmOut: %X, pdmIn: %X\n", lRet, pdmOut, pdmIn));
+
+ return(lRet);
+}
+
+//************************************************************************
+// DrvAdvancedDocumentProperties
+//************************************************************************
+
+LONG DrvAdvancedDocumentProperties(HWND hwnd, HANDLE hPrinter, PWSTR pDeviceName,
+ PDEVMODE pdmOut, PDEVMODE pdmIn)
+{
+ // for 16bit drivers this is a NOP.
+
+ return 0;
+}
+
+//************************************************************************
+// DevQueryPrintEx
+//************************************************************************
+
+BOOL DevQueryPrintEx(PDEVQUERYPRINT_INFO pDQPInfo)
+{
+ return TRUE;
+}
+
+//************************************************************************
+// DrvDeviceCapabilities
+//************************************************************************
+
+DWORD DrvDeviceCapabilities(HANDLE hPrinter, PWSTR pDeviceName,
+ WORD iDevCap, VOID *pOut, PDEVMODE pdmIn)
+{
+ FAXDEV dev = gdev;
+ LPFAXDEV lpdev = &dev;
+ LONG lRet = -1;
+ DWORD iOffset;
+ LPBYTE lpSrc;
+
+ LOGDEBUG(1, (L"WOWFAXUI!DrvDeviceCapabilities, iDevCap: %X, pdmIn: %X\n", iDevCap, pdmIn));
+
+ if (iDevCap == DC_SIZE) {
+ return sizeof(DEVMODEW);
+ }
+
+ if (iOffset = SetupFaxDev(pDeviceName, lpdev)) {
+ lpdev->lpMap->msg = WM_DDRV_DEVCAPS;
+
+ // Calculate the pointers into the mapped file section and copy
+ // the variable length data to the mapped file section.
+
+ lpdev->lpMap->lpIn = (LPDEVMODEW)((pdmIn) ? iOffset : 0);
+ iOffset += sizeof(*pdmIn) + gdmDriverExtra;
+
+ // output in lpout: make this the last pointer in the
+ // data so that we can use the rest of the mapped area for copy
+ // on output.
+
+ lpdev->lpMap->lpOut = (LPDEVMODEW)((pOut) ? iOffset : 0);
+ iOffset += sizeof(*pdmIn) + gdmDriverExtra;
+
+
+ if (pdmIn) {
+ iOffset = (DWORD)lpdev->lpMap + (DWORD)lpdev->lpMap->lpIn;
+ RtlCopyMemory((LPVOID)iOffset, pdmIn,
+ sizeof(*pdmIn) + min(gdmDriverExtra, pdmIn->dmDriverExtra));
+
+ // reset dmDriverExtra in pdmIn.
+ ((LPDEVMODE)iOffset)->dmDriverExtra =
+ min(gdmDriverExtra, pdmIn->dmDriverExtra);
+ }
+
+ lpdev->lpMap->wCmd = iDevCap;
+ // valid size of this map
+ lpdev->lpMap->cData = lpdev->cbMapLow;
+
+ InterProcCommHandler(lpdev, DRVFAX_SENDTOWOW);
+ lRet = (lpdev->lpMap->status) ? (LONG)lpdev->lpMap->retvalue : lRet;
+
+ // on return cData is the number of bytes to copy
+
+ if (lpdev->lpMap->lpOut && lpdev->lpMap->cData && lpdev->lpMap->retvalue) {
+ lpSrc = (LPBYTE)lpdev->lpMap + (DWORD)lpdev->lpMap->lpOut;
+ switch (lpdev->lpMap->wCmd) {
+ case DC_PAPERSIZE:
+ case DC_MINEXTENT:
+ case DC_MAXEXTENT:
+ ((LPPOINT)pOut)->x = ((LPPOINTS)lpSrc)->x;
+ ((LPPOINT)pOut)->y = ((LPPOINTS)lpSrc)->y;
+ break;
+
+ default:
+ RtlCopyMemory(pOut, lpSrc, lpdev->lpMap->cData);
+ break;
+ }
+ }
+ InterProcCommHandler(lpdev, DRVFAX_DESTROYMAP);
+ }
+
+ if (lRet < 0) {
+ LOGDEBUG(0, (L"WOWFAXUI!DrvDeviceCapabilities Failing\n"));
+ }
+
+ LOGDEBUG(1, (L"WOWFAXUI!DrvDeviceCapabilities, returning pOut: %X\n", pOut));
+
+ return(lRet);
+}
+
+//************************************************************************
+// DrvUpgradePrinter - Called in the system context by the spooler.
+// Drivers will really only be updated the first time the spooler is
+// started after an upgrade. Calls DoUpgradePrinter to do the work.
+//************************************************************************
+
+BOOL DrvUpgradePrinter(DWORD dwLevel, LPBYTE lpDrvUpgradeInfo)
+{
+ static BOOL bDrvUpgradePrinterLock = FALSE;
+ BOOL bRet;
+
+ LOGDEBUG(1, (L"WOWFAXUI!DrvUpgradePrinter, dwLevel: %X, lpDrvUpgradeInfo: %X\n", dwLevel, lpDrvUpgradeInfo));
+
+ // DrvUpgradePrinter is called during AddPrinterDriver. Don't allow
+ // recursion. Protect lock from other threads.
+ EnterCriticalSection(lpCriticalSection);
+ if (bDrvUpgradePrinterLock) {
+ LeaveCriticalSection(lpCriticalSection);
+ return(TRUE);
+ }
+
+ bDrvUpgradePrinterLock = TRUE;
+ LeaveCriticalSection(lpCriticalSection);
+
+ bRet = DoUpgradePrinter(dwLevel, (LPDRIVER_UPGRADE_INFO_1W)lpDrvUpgradeInfo);
+
+ EnterCriticalSection(lpCriticalSection);
+ bDrvUpgradePrinterLock = FALSE;
+ LeaveCriticalSection(lpCriticalSection);
+
+ return(bRet);
+}
+
+//************************************************************************
+// DrvDocumentEvent - This exported function is used to hook the GDI
+// Display Driver functions. It unpacks and validates the parameters,
+// then dispatches to the appropriate handler, based on the passed
+// iEsc value. The following table provides a mapping of the
+// DrvDocumentEvent escapes to the server side display driver
+// callbacks, and gives the call time relative to the callback:
+//
+// DOCUMENTEVENT_CREATEDCPRE DrvEnablePDEV, before
+// DOCUMENTEVENT_CREATEDCPOST DrvEnablePDEV, after
+// DOCUMENTEVENT_RESETDCPRE DrvRestartPDEV, before
+// DOCUMENTEVENT_RESETDCPOST DrvRestartPDEV, after
+// DOCUMENTEVENT_STARTDOC DrvStartDoc, before
+// DOCUMENTEVENT_STARTPAGE DrvStartPage, before
+// DOCUMENTEVENT_ENDPAGE DrvSendPage, before
+// DOCUMENTEVENT_ENDDOC DrvEndDoc, before
+// DOCUMENTEVENT_ABORTDOC DrvEndDoc, before
+// DOCUMENTEVENT_DELETEDC DrvDisablePDEV, before
+//
+//************************************************************************
+
+int DrvDocumentEvent(
+ HANDLE hPrinter,
+ HDC hdc,
+ int iEsc,
+ ULONG cbIn,
+ PULONG pjIn,
+ ULONG cbOut,
+ PULONG pjOut
+)
+{
+ int iRet = DOCUMENTEVENT_FAILURE;
+
+ if (iEsc < DOCUMENTEVENT_LAST) {
+ LOGDEBUG(1, (L"WOWFAXUI!DrvDocumentEvent, iEsc: %s, hdc: %X\n", szDrvDocumentEventDbgStrings[iEsc], hdc));
+ }
+
+ // Validate HDC for some of the escapes.
+ if ((iEsc >= DOCUMENTEVENT_HDCFIRST) && (iEsc < DOCUMENTEVENT_HDCLAST)) {
+ if (hdc == NULL) {
+ LOGDEBUG(0, (L"WOWFAXUI!DrvDocumentEvent NULL HDC for escape: %X\n", iEsc));
+ return(iRet);
+ }
+ }
+
+ switch (iEsc)
+ {
+ case DOCUMENTEVENT_CREATEDCPRE:
+ iRet = DocEvntCreateDCpre((LPWSTR)*(pjIn+1),
+ (DEVMODEW*)*(pjIn+2),
+ (DEVMODEW**)pjOut);
+ break;
+
+ case DOCUMENTEVENT_CREATEDCPOST:
+ iRet = DocEvntCreateDCpost(hdc, (DEVMODEW*)*pjIn);
+ break;
+
+ case DOCUMENTEVENT_RESETDCPRE:
+ iRet = DocEvntResetDCpre(hdc, (DEVMODEW*)*(pjIn),
+ (DEVMODEW**)pjOut);
+ break;
+
+ case DOCUMENTEVENT_RESETDCPOST:
+ iRet = DocEvntResetDCpost(hdc, (DEVMODEW*)*pjIn);
+ break;
+
+ case DOCUMENTEVENT_STARTDOC:
+ iRet = DocEvntStartDoc(hdc);
+ break;
+
+ case DOCUMENTEVENT_DELETEDC:
+ iRet = DocEvntDeleteDC(hdc);
+ break;
+
+ case DOCUMENTEVENT_ENDDOC:
+ iRet = DocEvntEndDoc(hdc);
+ break;
+
+ case DOCUMENTEVENT_ENDPAGE:
+ iRet = DocEvntEndPage(hdc);
+ break;
+
+ // The following require no client side processing:
+ case DOCUMENTEVENT_ESCAPE:
+ case DOCUMENTEVENT_ABORTDOC:
+ case DOCUMENTEVENT_STARTPAGE:
+ // No Client side processing needed.
+ goto docevnt_unsupported;
+
+ default :
+ LOGDEBUG(0, (L"WOWFAXUI!DrvDocumentEvent unknown escape: %X\n", iEsc));
+docevnt_unsupported:
+ iRet = DOCUMENTEVENT_UNSUPPORTED;
+
+ } // switch
+
+ LOGDEBUG(1, (L"WOWFAXUI!DrvDocumentEvent return: %X\n", iRet));
+ return(iRet);
+
+}
+
+//***************************************************************************
+// DocEvntCreateDCpre - Allocate a DEVMODE which contains a FAXDEV as the
+// dmDriverExtra portion. This DEVMODE will be passed to the
+// DrvEnablePDEV function on the server side.
+//***************************************************************************
+
+int DocEvntCreateDCpre(
+ LPWSTR lpszDevice,
+ DEVMODEW *pDevModIn,
+ DEVMODEW **pDevModOut
+)
+{
+ DWORD iOffset = 0;
+ LPFAXDEV lpFaxDev;
+ PGDIINFO pGdiInfo;
+ DEVMODEW *pTmpDevMode;
+
+ LPREGFAXDRVINFO16 lpRegFaxDrvInfo16;
+
+ int iRet = DOCUMENTEVENT_FAILURE;
+
+ if ((lpszDevice == NULL) || (pDevModOut == NULL)) {
+ LOGDEBUG(0, (L"WOWFAXUI!DocEvntCreateDCpre, failed, NULL parameters\n"));
+ goto DocEvntCreateDCpreFailed;
+ }
+
+ LOGDEBUG(1, (L"WOWFAXUI!DocEvntCreateDCpre, Device: %s, pDevModIn: %X pDevModOut: %X\n", lpszDevice, pDevModIn, pDevModOut));
+
+ // Use our global default devmode if a NULL devmode is passed in from the app.
+ if (pDevModIn == NULL) {
+ gdmDefaultDevMode.dmSize = sizeof(DEVMODEW);
+ pDevModIn = &gdmDefaultDevMode;
+ }
+
+ pTmpDevMode = (DEVMODEW*)WFLOCALALLOC(sizeof(FAXDEV) + sizeof(DEVMODEW),
+ L"DocEvntCreateDCpre");
+
+ LOGDEBUG(2, (L"WOWFAXUI!DocEvntCreateDCpre, pTmpDevMode: %X\n", pTmpDevMode));
+
+ if (pTmpDevMode == NULL) {
+ goto DocEvntCreateDCpreFailed;
+ }
+
+ // Copy pDevModIn to the new DEVMODE.
+ RtlCopyMemory(pTmpDevMode, pDevModIn, sizeof(*pTmpDevMode));
+ pTmpDevMode->dmDriverExtra = sizeof(FAXDEV);
+ pTmpDevMode->dmSize = sizeof(DEVMODEW);
+
+ // Setup some handy pointers.
+ lpFaxDev = (LPFAXDEV) (pTmpDevMode + 1);
+ pGdiInfo = &(lpFaxDev->gdiinfo);
+
+ lpFaxDev->id = FAXDEV_ID;
+
+ // Save a client side pointer to the new DEVMODE and it's embeded FAXDEV.
+ // We'll use ExtEscape to get these pointers back any time we need to
+ // associate driver context with an HDC.
+
+ lpFaxDev->pdevmode = pTmpDevMode;
+ lpFaxDev->lpClient = lpFaxDev;
+
+ // Get the driver and port names from the registry where they were written
+ // by the 16-bit fax driver install program using WriteProfileString.
+
+ if ((lpRegFaxDrvInfo16 = Get16BitDriverInfoFromRegistry(lpszDevice)) == NULL) {
+ goto DocEvntCreateDCpreFailed;
+ }
+
+ if ((lpFaxDev->hwnd = FindWowFaxWindow()) == NULL) {
+ goto DocEvntCreateDCpreFailed;
+ }
+ lpFaxDev->tid = GetWindowThreadProcessId(lpFaxDev->hwnd, 0);
+ lpFaxDev->idMap = (DWORD)lpFaxDev;
+
+ // Calculate the size of the mapped file section for inter process communication.
+ lpFaxDev->cbMapLow = sizeof(DWORD) + // leave room for DWORD align
+ sizeof(*lpFaxDev->lpMap) +
+ sizeof(GDIINFO) +
+ (lstrlen(lpRegFaxDrvInfo16->lpDriverName) + 1) * sizeof(TCHAR) +
+ (lstrlen(lpRegFaxDrvInfo16->lpPortName) + 1) * sizeof(TCHAR) +
+ sizeof(*pDevModIn) +
+ ((pDevModIn) ? pDevModIn->dmDriverExtra : 0);
+ DRVFAX_DWORDALIGN(lpFaxDev->cbMapLow);
+
+ InterProcCommHandler(lpFaxDev, DRVFAX_CREATEMAP);
+
+ if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
+ lpFaxDev->lpMap->msg = WM_DDRV_ENABLE;
+
+ // Copy the printer/device name to the WOWFAXINFO struct.
+ lstrcpy(lpFaxDev->lpMap->szDeviceName, lpszDevice);
+
+ // Calculate the pointers into the mapped file section and copy
+ // the variable length data to the mapped file section.
+
+ // output : gdiinfo
+
+ lpFaxDev->lpMap->lpOut = (LPDEVMODE)(sizeof(*lpFaxDev->lpMap));
+ iOffset = sizeof(*lpFaxDev->lpMap) + sizeof(GDIINFO);
+
+ // Device (printer) and port names.
+
+ lpFaxDev->lpMap->lpDriverName = (LPSTR) iOffset;
+ (PWSTR)iOffset += lstrlen(lpRegFaxDrvInfo16->lpDriverName) + 1;
+ lstrcpy((PWSTR)((LPBYTE)lpFaxDev->lpMap + (DWORD)lpFaxDev->lpMap->lpDriverName), lpRegFaxDrvInfo16->lpDriverName);
+ lpFaxDev->lpMap->lpPortName = (LPVOID) iOffset;
+ (PWSTR)iOffset += lstrlen(lpRegFaxDrvInfo16->lpPortName) + 1;
+ lstrcpy((PWSTR)((LPBYTE)lpFaxDev->lpMap + (DWORD)lpFaxDev->lpMap->lpPortName), lpRegFaxDrvInfo16->lpPortName);
+
+ // input: devmode
+
+ DRVFAX_DWORDALIGN(iOffset);
+ lpFaxDev->lpMap->lpIn = (LPDEVMODE)((pDevModIn) ? iOffset : 0);
+ iOffset += ((pDevModIn) ? sizeof(*pDevModIn) + pDevModIn->dmDriverExtra : 0);
+
+ if (pDevModIn) {
+ RtlCopyMemory((LPBYTE)lpFaxDev->lpMap + (DWORD)lpFaxDev->lpMap->lpIn,
+ pDevModIn, sizeof(*pDevModIn) + pDevModIn->dmDriverExtra);
+ }
+
+ // set the total byte count of data.
+
+ lpFaxDev->lpMap->cData = iOffset;
+
+ // all done - switch to wow
+ InterProcCommHandler(lpFaxDev, DRVFAX_SENDTOWOW);
+ // values returned from wow.
+ lpFaxDev->lpinfo16 = (DWORD)lpFaxDev->lpMap->lpinfo16;
+ iRet = lpFaxDev->lpMap->status && lpFaxDev->lpMap->retvalue;
+ if (iRet) {
+ // Copy GDIINFO from WOW to the client side FAXDEV.
+ RtlCopyMemory(pGdiInfo,
+ (LPBYTE)lpFaxDev->lpMap + (DWORD)lpFaxDev->lpMap->lpOut,
+ sizeof(GDIINFO));
+
+ // Fill in some misc. fields in the client FAXDEV.
+ pGdiInfo->ulHTPatternSize = HT_PATSIZE_DEFAULT;
+ pGdiInfo->ulHTOutputFormat = HT_FORMAT_1BPP;
+
+ lpFaxDev->bmWidthBytes = pGdiInfo->szlPhysSize.cx / 0x8;
+ DRVFAX_DWORDALIGN(lpFaxDev->bmWidthBytes);
+
+ lpFaxDev->bmFormat = BMF_1BPP;
+ lpFaxDev->cPixPerByte = 0x8;
+
+ // Here if success, make pDevModOut point to the new DEVMODE.
+ *pDevModOut = pTmpDevMode;
+
+ }
+ else {
+ LOGDEBUG(0, (L"WOWFAXUI!DocEvntCreateDCpre, WOW returned error\n"));
+ }
+ }
+
+ if (iRet) {
+ goto DocEvntCreateDCpreSuccess;
+ }
+ else {
+ iRet = DOCUMENTEVENT_FAILURE;
+ }
+
+DocEvntCreateDCpreFailed:
+ LOGDEBUG(0, (L"WOWFAXUI!DocEvntCreateDCpre, failed!\n"));
+
+DocEvntCreateDCpreSuccess:
+ LOGDEBUG(1, (L"WOWFAXUI!DocEvntCreateDCpre, iRet: %X\n", iRet));
+ Free16BitDriverInfo(lpRegFaxDrvInfo16);
+ return(iRet);
+}
+
+//***************************************************************************
+// DocEvntResetDCpre -
+//***************************************************************************
+
+int DocEvntResetDCpre(
+ HDC hdc,
+ DEVMODEW *pDevModIn,
+ DEVMODEW **pDevModOut
+)
+{
+ return(DOCUMENTEVENT_FAILURE);
+}
+
+//***************************************************************************
+// DocEvntResetDCpost -
+//***************************************************************************
+
+int DocEvntResetDCpost(
+ HDC hdc,
+ DEVMODEW *pDevModIn
+)
+{
+ return(DOCUMENTEVENT_SUCCESS);
+}
+
+//***************************************************************************
+// DocEvntCreateDCpost -
+//***************************************************************************
+
+int DocEvntCreateDCpost(
+ HDC hdc,
+ DEVMODEW *pDevModIn
+)
+{
+ LOGDEBUG(1, (L"WOWFAXUI!DocEvntCreateDCpost, hdc: %X, pDevModIn: %X\n", hdc, pDevModIn));
+
+ // hdc was zero indicates DrvEnablePDEV failed. Cleanup.
+ if (hdc == NULL) {
+ if (pDevModIn) {
+ LocalFree(pDevModIn);
+ LOGDEBUG(1, (L"WOWFAXUI!DocEvntCreateDCpost, Cleaning up\n"));
+ }
+ }
+ return(DOCUMENTEVENT_SUCCESS);
+}
+
+//***************************************************************************
+// DocEvntStartDoc - hdc was validated by DrvDocumentEvent.
+//***************************************************************************
+
+int DocEvntStartDoc(
+HDC hdc
+)
+{
+ LPFAXDEV lpFaxDev = 0;
+ HBITMAP hbm = 0;
+ DWORD cbOld;
+ int iRet = 0;
+
+ lpFaxDev = (LPFAXDEV)ExtEscape(hdc, DRV_ESC_GET_FAXDEV_PTR, 0, NULL, 0, NULL);
+ if (ValidateFaxDev(lpFaxDev)) {
+ if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
+ lpFaxDev->lpMap->msg = WM_DDRV_STARTDOC;
+ InterProcCommHandler(lpFaxDev, DRVFAX_SENDNOTIFYWOW);
+
+ iRet = ((LONG)lpFaxDev->lpMap->retvalue > 0);
+
+ // Calculate new mapsize - the bitmap bits will be written into
+ // this map with a call to ExtEscape - thus allowing easy access
+ // to the bits from WOW.
+
+ cbOld = lpFaxDev->cbMapLow;
+ lpFaxDev->cbMapLow += lpFaxDev->bmWidthBytes *
+ lpFaxDev->gdiinfo.szlPhysSize.cy;
+ if (InterProcCommHandler(lpFaxDev, DRVFAX_CREATEMAP)) {
+ lpFaxDev->offbits = cbOld;
+ goto DocEvntStartDocSuccess;
+ }
+ }
+ }
+ LOGDEBUG(1, (L"WOWFAXUI!DocEvntStartDoc, failed\n"));
+
+DocEvntStartDocSuccess:
+ if (iRet == 0) {
+ iRet = DOCUMENTEVENT_FAILURE;
+ }
+ return iRet;
+}
+
+//***************************************************************************
+// DocEvntDeleteDC - hdc was validated by DrvDocumentEvent.
+//***************************************************************************
+
+int DocEvntDeleteDC(
+ HDC hdc
+)
+{
+ LPFAXDEV lpFaxDev;
+ DEVMODEW *lpDevMode;
+
+ int iRet = DOCUMENTEVENT_FAILURE;
+
+ lpFaxDev = (LPFAXDEV)ExtEscape(hdc, DRV_ESC_GET_FAXDEV_PTR, 0, NULL, 0, NULL);
+ if (ValidateFaxDev(lpFaxDev)) {
+ // Validate 16-bit FaxWndProc window handle before sending a message.
+ if (lpFaxDev->tid == GetWindowThreadProcessId(lpFaxDev->hwnd, 0)) {
+ if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
+ lpFaxDev->lpMap->msg = WM_DDRV_DISABLE;
+ InterProcCommHandler(lpFaxDev, DRVFAX_SENDTOWOW);
+ }
+ }
+ else {
+ LOGDEBUG(0, (L"WOWFAXUI!DocEvntDeleteDC, unable to validate FaxWndProc\n"));
+ }
+
+ InterProcCommHandler(lpFaxDev, DRVFAX_DESTROYMAP);
+ }
+ else {
+ LOGDEBUG(0, (L"WOWFAXUI!DocEvntDeleteDC, unable to get lpFaxDev\n"));
+ }
+
+ lpDevMode = (DEVMODEW*)ExtEscape(hdc, DRV_ESC_GET_DEVMODE_PTR, 0, NULL, 0, NULL);
+ if (lpDevMode) {
+ LocalFree(lpDevMode);
+ iRet = DOCUMENTEVENT_SUCCESS;
+ }
+ else {
+ LOGDEBUG(0, (L"WOWFAXUI!DocEvntDeleteDC, unable to get lpDevMode\n"));
+ }
+
+ return iRet;
+}
+
+//***************************************************************************
+// DocEvntEndDoc - hdc was validated by DrvDocumentEvent.
+//***************************************************************************
+
+int DocEvntEndDoc(
+HDC hdc
+)
+{
+ LPFAXDEV lpFaxDev;
+ DEVMODEW *lpDevMode;
+
+ int iRet = DOCUMENTEVENT_FAILURE;
+
+ lpFaxDev = (LPFAXDEV)ExtEscape(hdc, DRV_ESC_GET_FAXDEV_PTR, 0, NULL, 0, NULL);
+ if (ValidateFaxDev(lpFaxDev)) {
+ if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
+ lpFaxDev->lpMap->msg = WM_DDRV_ENDDOC;
+ InterProcCommHandler(lpFaxDev, DRVFAX_SENDTOWOW);
+ iRet = lpFaxDev->lpMap->status && ((LONG)lpFaxDev->lpMap->retvalue > 0);
+ goto DocEvntEndDocSuccess;
+ }
+ }
+ LOGDEBUG(1, (L"WOWFAXUI!DocEvntEndDoc, failed\n"));
+
+DocEvntEndDocSuccess:
+ if (iRet == 0) {
+ iRet = DOCUMENTEVENT_FAILURE;
+ }
+ return iRet;
+}
+
+//***************************************************************************
+// DocEvntEndPage - hdc was validated by DrvDocumentEvent.
+//***************************************************************************
+
+int DocEvntEndPage(
+ HDC hdc
+)
+{
+ LPFAXDEV lpFaxDev;
+ LONG lDelta;
+ ULONG cjBits;
+ int iRet = DOCUMENTEVENT_FAILURE;
+
+ lpFaxDev = (LPFAXDEV)ExtEscape(hdc, DRV_ESC_GET_FAXDEV_PTR, 0, NULL, 0, NULL);
+ if (ValidateFaxDev(lpFaxDev)) {
+ if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
+ lpFaxDev->lpMap->msg = WM_DDRV_PRINTPAGE;
+
+ // Get Surface info, cjBits and lDelta.
+ cjBits = ExtEscape(hdc, DRV_ESC_GET_SURF_INFO, 0, NULL,
+ 4, (PVOID)&lDelta);
+ if (cjBits) {
+ lpFaxDev->lpMap->bmWidthBytes = lDelta;
+ lpFaxDev->lpMap->bmHeight = cjBits / lDelta;
+ lpFaxDev->lpMap->bmPixPerByte = lpFaxDev->cPixPerByte;
+ (DWORD)lpFaxDev->lpMap->lpbits = lpFaxDev->offbits;
+ if (ExtEscape(hdc, DRV_ESC_GET_BITMAP_BITS, 0, NULL, cjBits,
+ (LPBYTE)lpFaxDev->lpMap + lpFaxDev->offbits)) {
+ InterProcCommHandler(lpFaxDev, DRVFAX_SENDTOWOW);
+ iRet = lpFaxDev->lpMap->status &&
+ ((LONG)lpFaxDev->lpMap->retvalue > 0);
+ }
+ goto DocEvntEndPageSuccess;
+ }
+ }
+ }
+ LOGDEBUG(1, (L"WOWFAXUI!DocEvntEndPage, failed\n"));
+
+DocEvntEndPageSuccess:
+ if (iRet == 0) {
+ iRet = DOCUMENTEVENT_FAILURE;
+ }
+ return iRet;
+}