//************************************************************************ // 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); } else if (Reason == DLL_PROCESS_DETACH) { DeleteCriticalSection(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]; UNREFERENCED_PARAMETER(hPrinter); 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, lpRegFaxDrvInfo16->lpDeviceName); // 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 = (WORD)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: // WowFax (EasyFax Ver2.0) support. // Also Procomm+ 3 cover sheets. Bug #305665 iRet = DocEvntStartDoc(hdc, (DOCINFOW*)*pjIn); 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: case DOCUMENTEVENT_QUERYFILTER: // 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 = NULL; 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)); if(lpRegFaxDrvInfo16) { 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, DOCINFOW *pDocInfoW ) { 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; // WowFax (EasyFax Ver2.0) support. // Also Procomm+ 3 cover sheets. Bug #305665. if (pDocInfoW && pDocInfoW->lpszDocName) lstrcpyW(lpFaxDev->lpMap->szDocName,pDocInfoW->lpszDocName); else lstrcpyW(lpFaxDev->lpMap->szDocName,L""); 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; }