diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/fax/wowfaxui | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/mvdm/fax/wowfaxui')
-rw-r--r-- | private/mvdm/fax/wowfaxui/makefile | 6 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/sources | 60 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/wfhelper.c | 467 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/wfsheets.c | 405 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/wfsheets.h | 33 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/wfupgrad.c | 264 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/wowfaxui.c | 874 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/wowfaxui.def | 16 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/wowfaxui.h | 164 | ||||
-rw-r--r-- | private/mvdm/fax/wowfaxui/wowfaxui.rc | 45 |
10 files changed, 2334 insertions, 0 deletions
diff --git a/private/mvdm/fax/wowfaxui/makefile b/private/mvdm/fax/wowfaxui/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/mvdm/fax/wowfaxui/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/mvdm/fax/wowfaxui/sources b/private/mvdm/fax/wowfaxui/sources new file mode 100644 index 000000000..9763e73c2 --- /dev/null +++ b/private/mvdm/fax/wowfaxui/sources @@ -0,0 +1,60 @@ +!IF 0 + +Copyright (c) 1989 - 1991 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=windows +MINORCOMP=wowfaxui + +TARGETNAME=wowfaxui +TARGETPATH=$(BASEDIR)\public\sdk\lib +TARGETTYPE=DYNLINK +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\gdi32.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\winspool.lib \ + $(BASEDIR)\public\sdk\lib\*\shell32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib + +C_DEFINES=-DUNICODE + +DLLENTRY=DllInitProc + +GDIDIR=$(BASEDIR)\private\ntos\w32\ntgdi +PRINTERS=$(BASEDIR)\private\ntos\w32\ntgdi\printers + +!IFNDEF MSC_WARNING_LEVEL +MSC_WARNING_LEVEL=/W3 +!ENDIF +MSC_WARNING_LEVEL=$(MSC_WARNING_LEVEL) /WX + +INCLUDES=..;..\wowfax;..\..\inc;$(GDIDIR)\inc;..\..\..\windows\inc;$(PRINTERS)\lib + +SOURCES=wfhelper.c \ + wfsheets.c \ + wfupgrad.c \ + wowfaxui.c \ + wowfaxui.rc + +UMTYPE=windows +UMTEST= + diff --git a/private/mvdm/fax/wowfaxui/wfhelper.c b/private/mvdm/fax/wowfaxui/wfhelper.c new file mode 100644 index 000000000..69a3833c4 --- /dev/null +++ b/private/mvdm/fax/wowfaxui/wfhelper.c @@ -0,0 +1,467 @@ +//************************************************************************ +// Generic Win 3.1 fax printer driver support. Helper functions which are +// called in WOWFAXUI.C +// +// History: +// 14-mar-95 reedb Created. Many of the functions were moved from +// FAXCOMM.C, since they're no longer called +// from WOWFAX.DLL. +// 16-aug-95 reedb Move to kernel mode. Debug output and validate +// functions moved from FAXCOMM.C. +// +//************************************************************************ + +#include "wowfaxui.h" + +extern LPCRITICAL_SECTION lpCriticalSection; +extern HINSTANCE ghInst; + +#if DBG + +INT iFaxLogLevel = 20; +INT iReqFaxLogLevel = 0; + +typedef PVOID HANDLE; + + +//************************************************************************ +// faxlogprintf - Two different implementations. One for client side +// debugging the other for server side. +// +//************************************************************************ + + +// For Debug logging. +#define MAX_DISPLAY_LINE 256 // 128 characters. + +TCHAR szFaxLogFile[] = L"C:\\FAXLOG.LOG"; +HANDLE hfFaxLog = NULL; + +// Defines for iFaxLogMode +#define NO_LOGGING 0 +#define LOG_TO_FILE 1 +#define OPEN_LOG_FILE 2 +#define CLOSE_LOG_FILE 3 + +INT iFaxLogMode = NO_LOGGING; + +VOID faxlogprintf(LPTSTR pszFmt, ...) +{ + DWORD lpBytesWritten; + int len; + TCHAR szText[1024]; + va_list arglist; + + va_start(arglist, pszFmt); + len = wvsprintf(szText, pszFmt, arglist); + + if (iFaxLogMode > LOG_TO_FILE) { + if (iFaxLogMode == OPEN_LOG_FILE) { + if((hfFaxLog = CreateFile(szFaxLogFile, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL)) != INVALID_HANDLE_VALUE) { + iFaxLogMode = LOG_TO_FILE; + } + else { + hfFaxLog = NULL; + iFaxLogMode = NO_LOGGING; + OutputDebugString(L"Couldn't open fax log file!\n"); + } + } + else { + FlushFileBuffers(hfFaxLog); + CloseHandle(hfFaxLog); + hfFaxLog = NULL; + iFaxLogMode = NO_LOGGING; + } + } + + if (iFaxLogLevel >= iReqFaxLogLevel) { + if (iFaxLogMode) { + WriteFile(hfFaxLog, szText, len, &lpBytesWritten, NULL); + } + else { + OutputDebugString(szText); + } + } +} + + +VOID LogWowFaxInfo(LPWOWFAXINFO lpWowFaxInfo) +{ + faxlogprintf(L"\tlpWowFaxInfo (lpMap): %X\n", lpWowFaxInfo); + faxlogprintf(L"\t\thwnd: %X\n", lpWowFaxInfo->hwnd); + faxlogprintf(L"\t\ttid: %X\n", lpWowFaxInfo->tid); + faxlogprintf(L"\t\tproc16: %X\n", lpWowFaxInfo->proc16); + faxlogprintf(L"\t\tlpinfo16: %X\n", lpWowFaxInfo->lpinfo16); + faxlogprintf(L"\t\tmsg: %X\n", lpWowFaxInfo->msg); + faxlogprintf(L"\t\thdc: %X\n", lpWowFaxInfo->hdc); + faxlogprintf(L"\t\twCmd: %X\n", lpWowFaxInfo->wCmd); + faxlogprintf(L"\t\tcData: %X\n", lpWowFaxInfo->cData); + faxlogprintf(L"\t\thwndui: %X\n", lpWowFaxInfo->hwndui); + faxlogprintf(L"\t\tretvalue: %X\n", lpWowFaxInfo->retvalue); + faxlogprintf(L"\t\tstatus: %X\n", lpWowFaxInfo->status); + if (lpWowFaxInfo->lpDevice) { + faxlogprintf(L"\t\tlpDevice: %s\n", lpWowFaxInfo->lpDevice); + } + else { + faxlogprintf(L"\t\tlpDevice: %X\n", lpWowFaxInfo->lpDevice); + } + if (lpWowFaxInfo->lpDriverName) { + faxlogprintf(L"\t\tlpDriverName: %s\n", lpWowFaxInfo->lpDriverName); + } + else { + faxlogprintf(L"\t\tlpDriverName: %X\n", lpWowFaxInfo->lpDriverName); + } + if (lpWowFaxInfo->lpPortName) { + faxlogprintf(L"\t\tlpPortName: %s\n", lpWowFaxInfo->lpPortName); + } + else { + faxlogprintf(L"\t\tlpPortName: %X\n", lpWowFaxInfo->lpPortName); + } + faxlogprintf(L"\t\tlpIn: %X\n", lpWowFaxInfo->lpIn); + faxlogprintf(L"\t\tlpOut: %X\n", lpWowFaxInfo->lpOut); + if (lpWowFaxInfo->szDeviceName) { + faxlogprintf(L"\t\tszDeviceName: %s\n", lpWowFaxInfo->szDeviceName); + } + else { + faxlogprintf(L"\t\tszDeviceName: %X\n", lpWowFaxInfo->szDeviceName); + } + faxlogprintf(L"\t\tbmPixPerByte: %X\n", lpWowFaxInfo->bmPixPerByte); + faxlogprintf(L"\t\tbmWidthBytes: %X\n", lpWowFaxInfo->bmWidthBytes); + faxlogprintf(L"\t\tbmHeight: %X\n", lpWowFaxInfo->bmHeight); + faxlogprintf(L"\t\tlpbits: %X\n", lpWowFaxInfo->lpbits); +} + +VOID LogFaxDev(LPTSTR pszTitle, LPFAXDEV lpFaxDev) +{ + DWORD dwTmp; + CHAR cTmp0, cTmp1, cTmp2, cTmp3; + + faxlogprintf(L"WOWFAXUI!%s: %X\n", pszTitle, lpFaxDev); + dwTmp = lpFaxDev->id; + cTmp3 = (CHAR) dwTmp & 0xFF; + cTmp2 = (CHAR) (dwTmp >> 8) & 0xFF; + cTmp1 = (CHAR) (dwTmp >> 16) & 0xFF; + cTmp0 = (CHAR) (dwTmp >> 24) & 0xFF; + faxlogprintf(L"\tid: %c%c%c%c\n", cTmp3, cTmp2, cTmp1, cTmp0); + faxlogprintf(L"\tlpNext: %X\n", lpFaxDev->lpNext); + faxlogprintf(L"\tlpClient: %X\n", lpFaxDev->lpClient); + faxlogprintf(L"\thdev: %X\n", lpFaxDev->hdev); + faxlogprintf(L"\tidMap: %X\n", lpFaxDev->idMap); + faxlogprintf(L"\tcbMapLow: %X\n", lpFaxDev->cbMapLow); + faxlogprintf(L"\thMap: %X\n", lpFaxDev->hMap); + faxlogprintf(L"\tszMap: %s\n", lpFaxDev->szMap); + if (lpFaxDev->lpMap) { + LogWowFaxInfo(lpFaxDev->lpMap); + } + else { + faxlogprintf(L"\tlpMap: %X\n", lpFaxDev->lpMap); + } + faxlogprintf(L"\toffbits: %X\n", lpFaxDev->offbits); + faxlogprintf(L"\thbm: %X\n", lpFaxDev->hbm); + faxlogprintf(L"\tcPixPerByte: %X\n", lpFaxDev->cPixPerByte); + faxlogprintf(L"\tbmFormat: %X\n", lpFaxDev->bmFormat); + faxlogprintf(L"\tbmWidthBytes: %X\n", lpFaxDev->bmWidthBytes); + faxlogprintf(L"\thbmSurf: %X\n", lpFaxDev->hbmSurf); + faxlogprintf(L"\thwnd: %X\n", lpFaxDev->hwnd); + faxlogprintf(L"\ttid: %X\n", lpFaxDev->tid); + faxlogprintf(L"\tlpinfo16: %X\n", lpFaxDev->lpinfo16); + faxlogprintf(L"\thDriver: %X\n", lpFaxDev->hDriver); + faxlogprintf(L"\tStart of gdiinfo: %X\n", (DWORD)&(lpFaxDev->gdiinfo)); + faxlogprintf(L"\tStart of devinfo: %X\n", (DWORD)&(lpFaxDev->devinfo)); + faxlogprintf(L"\tpdevmode: %X\n", lpFaxDev->pdevmode); +} +#endif + +//************************************************************************ +// ValidateFaxDev - Validates the FAXDEV structure by checking the DWORD +// signature, which is a known fixed value. +// +//************************************************************************ + +BOOL ValidateFaxDev(LPFAXDEV lpFaxDev) +{ + if (lpFaxDev) { + if (lpFaxDev->id == FAXDEV_ID) { + return TRUE; + } + LOGDEBUG(0, (L"ValidateFaxDev failed, bad id, lpFaxDev: %X\n", lpFaxDev)); + } + else { + LOGDEBUG(0, (L"ValidateFaxDev failed, lpFaxDev: NULL\n")); + } + return FALSE; +} + +//*************************************************************************** +// WFLocalAlloc - Debug version of LocalAlloc. +//*************************************************************************** + +LPVOID WFLocalAlloc(DWORD dwBytes, LPWSTR lpszWhoCalled) +{ + LPVOID lpTmp; + + lpTmp = LocalAlloc(LPTR, dwBytes); + + if (lpTmp == NULL){ + LOGDEBUG(0, (L"WOWFAXUI!%s, failed on memory allocation of %d bytes\n", lpszWhoCalled, dwBytes)); + } + return(lpTmp); +} + +//*************************************************************************** +// FindWowFaxWindow - Put up a message box if you can't. +//*************************************************************************** +HWND FindWowFaxWindow(void) +{ + HWND hwnd; + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO StartupInfo; + DWORD WaitStatus; + TCHAR szMsg[WOWFAX_MAX_USER_MSG_LEN]; + TCHAR szTitle[WOWFAX_MAX_USER_MSG_LEN]; + WCHAR szWowExec[] = L"WOWEXEC"; + + if ((hwnd = FindWindow(WOWFAX_CLASS, NULL)) == NULL) { + // You can't find the WowFaxWindow, try to start WOW. + RtlZeroMemory((PVOID)&StartupInfo, (DWORD)sizeof(StartupInfo)); + StartupInfo.cb = sizeof(StartupInfo); + StartupInfo.dwFlags = STARTF_USESHOWWINDOW; + StartupInfo.wShowWindow = SW_NORMAL; + + if (CreateProcess(NULL, + szWowExec, + NULL, // security + NULL, // security + FALSE, // inherit handles + CREATE_NEW_CONSOLE | CREATE_DEFAULT_ERROR_MODE, + NULL, // environment strings + NULL, // current directory + &StartupInfo, + &ProcessInformation)) { + + WaitForInputIdle(ProcessInformation.hProcess, 10*1000); + + if ((hwnd = FindWindow(WOWFAX_CLASS, NULL)) != NULL) { + return(hwnd); + } + } + + // WOW failed to start. Let user know. + if (LoadString(ghInst, WOWFAX_NAME_STR, szTitle, WOWFAX_MAX_USER_MSG_LEN)) { + if (LoadString(ghInst, WOWFAX_NOWOW_STR, szMsg, WOWFAX_MAX_USER_MSG_LEN)) { + MessageBox(hwnd, szMsg, szTitle, MB_OK); + } + } + } + return(hwnd); +} + +//************************************************************************ +// DupTokenW - Helper for Get16BitDriverInfoFromRegistry. Allocate and +// copy a token, wide format. Allocates storage for duplicate. +// wcsdup is not present in the run-times we link to. +//************************************************************************ + +LPTSTR DupTokenW(LPTSTR lpTok) +{ + LPTSTR lpRetVal = NULL; + + if (lpTok != NULL) { + lpRetVal = WFLOCALALLOC((wcslen(lpTok) + 1) * sizeof(TCHAR), L"DupTokenW"); + if (lpRetVal) { + wcscpy(lpRetVal, lpTok); + } + } + return(lpRetVal); +} + +//************************************************************************ +// Get16BitDriverInfoFromRegistry - Get the 16-bit driver info (name, port) +// from the registry where it is written by the 16-bit fax driver +// install program using an intercepted WriteProfileString. Storage is +// allocated for the returned info, and must be freed by the caller +// using Free16BitDriverInfo. See also Set16BitDriverInfoToRegistry +// in WOW32FAX.C +//************************************************************************ + +LPREGFAXDRVINFO16 Get16BitDriverInfoFromRegistry(PWSTR pDeviceName) +{ + TCHAR szRetBuf[256]; + HKEY hKey = 0; + DWORD dwType, cbBufSize = 256; + LPTSTR lpTok; + + LPREGFAXDRVINFO16 lpRetVal = WFLOCALALLOC(sizeof(REGFAXDRVINFO16), L"Get16BitDriverInfoFromRegistry"); + + if ((pDeviceName != NULL) && (lpRetVal != NULL)) { + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, + L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WOW\\WowFax\\devices", + 0, KEY_READ, &hKey ) == ERROR_SUCCESS) { + + if (RegQueryValueEx(hKey, pDeviceName, 0, &dwType, (LPBYTE)szRetBuf, &cbBufSize) == ERROR_SUCCESS) { + RegCloseKey(hKey); + + // Make wcstok multi-thread safe, it stores state. + EnterCriticalSection(lpCriticalSection); + lpTok = wcstok(szRetBuf, L","); + LeaveCriticalSection(lpCriticalSection); + + if ((lpRetVal->lpDriverName = DupTokenW(lpTok)) != NULL) { + EnterCriticalSection(lpCriticalSection); + lpTok = wcstok(NULL, L","); + LeaveCriticalSection(lpCriticalSection); + lpRetVal->lpPortName = DupTokenW(lpTok); + LOGDEBUG(1, (L"WOWFAXUI!Get16BitDriverInfoFromRegistry, Name: %s, Driver: %s, Port: %s\n", pDeviceName, lpRetVal->lpDriverName, lpRetVal->lpPortName)); + return(lpRetVal); + } + } + RegCloseKey(hKey); + } + } + + if (pDeviceName) { + LOGDEBUG(0, (L"WOWFAXUI!Get16BitDriverInfoFromRegistry, failed Name: %s\n", pDeviceName)); + } + else { + LOGDEBUG(0, (L"WOWFAXUI!Get16BitDriverInfoFromRegistry, failed Name: NULL\n")); + } + + Free16BitDriverInfo(lpRetVal); + return(NULL); +} + +//************************************************************************ +// Free16BitDriverInfo - Free the 16-bit driver info allocated by +// Get16BitDriverInfoFromRegistry. +//************************************************************************ + +VOID Free16BitDriverInfo(LPREGFAXDRVINFO16 lpRegFaxDrvInfo16) +{ + if (lpRegFaxDrvInfo16) { + if (lpRegFaxDrvInfo16->lpDriverName) { + LocalFree(lpRegFaxDrvInfo16->lpDriverName); + } + if (lpRegFaxDrvInfo16->lpPortName) { + LocalFree(lpRegFaxDrvInfo16->lpPortName); + } + LocalFree(lpRegFaxDrvInfo16); + return; + } +} + +//*************************************************************************** +// InterProcCommHandler - Handles inter-process communication between +// WOWFAXUI-WOW32 and WOWFAX-WOW32. +//*************************************************************************** + +BOOL InterProcCommHandler(LPFAXDEV lpdev, UINT iAction) +{ + LPWOWFAXINFO lpT = lpdev->lpMap; + HANDLE hMap = 0; + WNDPROC wndproc; + MSG msg; + + switch (iAction) + { + case DRVFAX_SETMAPDATA: + if (lpdev->lpMap) { + // init map struct + lpdev->lpMap->status = FALSE; + lpdev->lpMap->retvalue = (DWORD)-1; + lpdev->hwnd = FindWowFaxWindow(); + lpdev->lpMap->hwnd = lpdev->hwnd; + lpdev->lpMap->msg = 0; + lpdev->lpMap->hdc = (WPARAM)lpdev->idMap; + (DWORD)lpdev->lpMap->lpinfo16 = lpdev->lpinfo16; + } + break; + + case DRVFAX_SENDTOWOW: + if (lpdev->lpMap->hwnd) { + SendMessage(lpdev->lpMap->hwnd, lpdev->lpMap->msg, (WPARAM)lpdev->idMap, 0); + } + else { + LOGDEBUG(0, (L"WOWFAXUI!InterProcCommHandler, No hwnd to send to.\n")); + } + break; + + case DRVFAX_CALLWOW: + if (lpdev->lpMap->hwnd) { + wndproc = (WNDPROC) GetWindowLongA(lpdev->lpMap->hwnd, GWL_WNDPROC); + CallWindowProc(wndproc, lpdev->lpMap->hwnd, lpdev->lpMap->msg, (WPARAM)lpdev->idMap, 0); + } + else { + LOGDEBUG(0, (L"WOWFAXUI!InterProcCommHandler, No hwnd to call to.\n")); + } + break; + + case DRVFAX_SENDNOTIFYWOW: + if (lpdev->lpMap->hwnd) { + SendNotifyMessage(lpdev->lpMap->hwnd, lpdev->lpMap->msg, (WPARAM)lpdev->idMap, 0); + + // To simulate app-modal dialog, pass message's to this threads + // windows to DefWndProc, until 16-bit fax driver UI is dismissed. + while (!lpdev->lpMap->status) { + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (msg.message != WM_PAINT) { + DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam); + } + else { + DispatchMessage(&msg); + } + } + } + } + break; + + case DRVFAX_CREATEMAP: + case DRVFAX_DESTROYMAP: + if (lpdev->lpMap) { + + // destroys the current map - for both iActions + UnmapViewOfFile(lpdev->lpMap); + CloseHandle(lpdev->hMap); + lpdev->lpMap = 0; + lpdev->hMap = 0; + lpT = 0; + } + + if (iAction == DRVFAX_CREATEMAP) { + // GetFaxDataMapName is WOWFAX_INC_COMMON_CODE in wowfax.h. + GetFaxDataMapName((DWORD)lpdev->idMap, lpdev->szMap); + hMap = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, + 0, lpdev->cbMapLow, lpdev->szMap); + if (hMap) { + if (GetLastError() == ERROR_ALREADY_EXISTS) { + CloseHandle(hMap); + } + else { + lpT = (LPWOWFAXINFO)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); + if (lpT) { + lpdev->hMap = hMap; + lpdev->lpMap = lpT; + } + else { + LOGDEBUG(0, (L"WOWFAXUI!InterProcCommHandler, MapViewOfFile failed, LastError = %ld\n", GetLastError())); + CloseHandle(hMap); + } + } + } + else { + LOGDEBUG(0, (L"WOWFAXUI!InterProcCommHandler, CreateFileMapping failed, LastError = %ld\n", GetLastError())); + } + } + break; + + } //switch + + return((BOOL)lpT); +} + + diff --git a/private/mvdm/fax/wowfaxui/wfsheets.c b/private/mvdm/fax/wowfaxui/wfsheets.c new file mode 100644 index 000000000..f5526faed --- /dev/null +++ b/private/mvdm/fax/wowfaxui/wfsheets.c @@ -0,0 +1,405 @@ +//************************************************************************ +// Generic Win 3.1 fax printer driver support. User Interface functions +// which are called by WINSPOOL. Support for Two new entry points required +// by the Win 95 printer UI, DrvDocumentPropertySheets and +// DrvDevicePropertySheets +// +// History: +// 24-Apr-96 reedb created. +// +//************************************************************************ + +#include "windows.h" +#include "wowfaxui.h" +#include "wfsheets.h" +#include "winspool.h" + +//************************************************************************ +// Globals +//************************************************************************ + +extern HINSTANCE ghInst; + +DEVMODEW gdmDefaultDevMode; + +LONG DrvDocumentProperties(HWND hwnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODE pdmOut, PDEVMODE pdmIn, DWORD fMode); +LONG SimpleDocumentProperties(PDOCUMENTPROPERTYHEADER pDPHdr); + +//************************************************************************ +// NullDlgProc - Procedure for handling "Printer Properties" property +// sheet page +//************************************************************************ + +BOOL NullDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam) +{ + return FALSE; +} + +//************************************************************************ +// FaxOptionsProc - Procedure for handling "Fax Options" property +// sheet page +//************************************************************************ + +BOOL FaxOptionsProc(HWND hDlg, UINT message, UINT wParam, LONG lParam) +{ + PDEVMODE pdmOut = NULL; + PDEVMODE pdmIn = NULL; + PUIDATA pUiData; + TCHAR szFeedBack[WOWFAX_MAX_USER_MSG_LEN]; + + switch (message) { + case WM_INITDIALOG: + SetWindowLong(hDlg, DWL_USER, ((PROPSHEETPAGE *) lParam)->lParam); + return TRUE; + + case WM_COMMAND: + if (wParam == IDOK) { + SetWindowText(GetDlgItem(hDlg, IDC_FEEDBACK), L""); + + pUiData = (PUIDATA) GetWindowLong(hDlg, DWL_USER); + DrvDocumentProperties(hDlg, + pUiData->hPrinter, + pUiData->pDeviceName, + pUiData->pdmOut, + pUiData->pdmIn, + pUiData->fMode); + + // + // Provide user with feedback text. + // + if (LoadString(ghInst, WOWFAX_ENABLE_CONFIG_STR, + szFeedBack, sizeof(szFeedBack))) { + SetWindowText(GetDlgItem(hDlg, IDC_FEEDBACK), szFeedBack); + } + } + break; + + case WM_NOTIFY: + + if (((NMHDR *) lParam)->code == PSN_APPLY) { + + pUiData = (PUIDATA) GetWindowLong(hDlg, DWL_USER); + + // + // HACK: Inform common UI library that user has pressed OK + // + + pUiData->pfnComPropSheet(pUiData->hComPropSheet, + CPSFUNC_SET_RESULT, + (LONG) pUiData->hFaxOptsPage, + CPSUI_OK); + return TRUE; + + } + break; + } + + return FALSE; +} + +//************************************************************************ +// AddDocPropPages -Add our "Document Properties" pages to the property +// sheet. Returns RUE if successful, FALSE otherwise. +//************************************************************************ + +BOOL AddDocPropPages(PUIDATA pUiData) +{ + PROPSHEETPAGE psp; + LONG result; + + // + // "Document Properties" dialog only has one tab - "Fax Options" + // + + memset(&psp, 0, sizeof(psp)); + psp.dwSize = sizeof(PROPSHEETPAGE); + psp.dwFlags = 0; + psp.hInstance = ghInst; + psp.lParam = (LPARAM) pUiData; + psp.pszTemplate = MAKEINTRESOURCE(IDD_DOCPROP); + psp.pfnDlgProc = FaxOptionsProc; + + pUiData->hFaxOptsPage = (HANDLE) + pUiData->pfnComPropSheet(pUiData->hComPropSheet, + CPSFUNC_ADD_PROPSHEETPAGE, + (LPARAM) &psp, + 0); + + return (pUiData->hFaxOptsPage != NULL); +} + + +//************************************************************************ +// MyGetPrinter - Wrapper function for GetPrinter spooler API. Returns +// Pointer to a PRINTER_INFO_x structure, NULL if there is an error +//************************************************************************ + +PVOID MyGetPrinter(HANDLE hPrinter, DWORD level) +{ + PBYTE pPrinterInfo = NULL; + DWORD cbNeeded; + + if (!GetPrinter(hPrinter, level, NULL, 0, &cbNeeded) && + GetLastError() == ERROR_INSUFFICIENT_BUFFER && + (pPrinterInfo = LocalAlloc(LPTR, cbNeeded)) && + GetPrinter(hPrinter, level, pPrinterInfo, cbNeeded, &cbNeeded)) + { + return pPrinterInfo; + } + + LOGDEBUG(0, (L"GetPrinter failed\n")); + LocalFree(pPrinterInfo); + return NULL; +} + +//************************************************************************ +// FreeUiData - Free the data structure used by the fax driver user +// interface. +//************************************************************************ + +PUIDATA FreeUiData(PUIDATA pUiData) +{ + if (pUiData) { + if (pUiData->pDeviceName) LocalFree(pUiData->pDeviceName); + if (pUiData->pDriverName) LocalFree(pUiData->pDriverName); + } + return NULL; +} + +//************************************************************************ +// FillUiData - Fill in the data structure used by the fax driver user +// interface. Returns pointer to UIDATA structure, NULL if error. +//************************************************************************ + +PUIDATA FillUiData(HANDLE hPrinter, PDEVMODE pdmInput, PDEVMODE pdmOutput, DWORD fMode) +{ + PRINTER_INFO_2 *pPrinterInfo2; + PUIDATA pUiData; + + // + // Allocate memory to hold UIDATA structure + // Get printer info from the spooler. Copy the driver name. + // + + if (! (pUiData = LocalAlloc(LPTR, sizeof(UIDATA))) || + ! (pPrinterInfo2 = MyGetPrinter(hPrinter, 2)) || + ! (pUiData->pDeviceName = DupTokenW(pPrinterInfo2->pPrinterName)) || + ! (pUiData->pDriverName = DupTokenW(pPrinterInfo2->pDriverName))) { + + pUiData = FreeUiData(pUiData); + } + else { + pUiData->pdmIn = pdmInput; + pUiData->pdmOut = pdmOutput; + pUiData->fMode = fMode; + + pUiData->startUiData = pUiData->endUiData = pUiData; + pUiData->hPrinter = hPrinter; + } + + if (pPrinterInfo2) + LocalFree(pPrinterInfo2); + + return pUiData; +} + +//************************************************************************ +// DrvDocumentPropertySheets - Display "Document Properties" property +// sheets. Return > 0 if successful, <= 0 if failed. +//************************************************************************ + +LONG DrvDocumentPropertySheets(PPROPSHEETUI_INFO pPSUIInfo, LPARAM lParam) +{ + PDOCUMENTPROPERTYHEADER pDPHdr; + PCOMPROPSHEETUI pCompstui; + PUIDATA pUiData; + LONG result; + + // + // Validate input parameters + // + if (! (pDPHdr = (PDOCUMENTPROPERTYHEADER) (pPSUIInfo ? pPSUIInfo->lParamInit : lParam))) { + return -1; + } + + if (pPSUIInfo == NULL) { + return SimpleDocumentProperties(pDPHdr); + } + + // + // Create a UIDATA structure if necessary + // + + pUiData = (pPSUIInfo->Reason == PROPSHEETUI_REASON_INIT) ? + FillUiData(pDPHdr->hPrinter, pDPHdr->pdmIn, pDPHdr->pdmOut, pDPHdr->fMode) : + (PUIDATA) pPSUIInfo->UserData; + + if (! ValidUiData(pUiData)) + return -1; + + // + // Handle various cases for which this function might be called + // + + switch (pPSUIInfo->Reason) { + + case PROPSHEETUI_REASON_INIT: + + pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet; + pUiData->hComPropSheet = pPSUIInfo->hComPropSheet; + + // + // Add our page to the property sheet + // + + if (AddDocPropPages(pUiData)) { + + pPSUIInfo->UserData = (DWORD) pUiData; + pPSUIInfo->Result = CPSUI_CANCEL; + return 1; + } + + // + // Clean up properly in case of an error + // + + FreeUiData(pUiData); + break; + + case PROPSHEETUI_REASON_GET_INFO_HEADER: + + { PPROPSHEETUI_INFO_HEADER pPSUIHdr; + + pPSUIHdr = (PPROPSHEETUI_INFO_HEADER) lParam; + pPSUIHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW; + pPSUIHdr->pTitle = pDPHdr->pszPrinterName; + pPSUIHdr->hInst = ghInst; + pPSUIHdr->IconID = IDI_CPSUI_PRINTER2; + } + return 1; + + case PROPSHEETUI_REASON_SET_RESULT: + + pPSUIInfo->Result = ((PSETRESULT_INFO) lParam)->Result; + return 1; + + case PROPSHEETUI_REASON_DESTROY: + + // + // Cleanup properly before exiting + // + + FreeUiData(pUiData); + return 1; + } + return -1; +} + +//************************************************************************ +// DrvDevicePropertySheets - Display "Printer Properties" dialog. +// Return > 0 if successful, <= 0 if failed. +//************************************************************************ + +LONG DrvDevicePropertySheets(PPROPSHEETUI_INFO pPSUIInfo, LPARAM lParam) +{ + PDEVICEPROPERTYHEADER pDPHdr; + PCOMPROPSHEETUI pCompstui; + PROPSHEETPAGE psp; + LONG result; + + // + // Validate input parameters + // + LOGDEBUG(1,(L"DrvDevicePropertySheets: %d\n", pPSUIInfo->Reason)); + + if (!pPSUIInfo || !(pDPHdr = (PDEVICEPROPERTYHEADER) pPSUIInfo->lParamInit)) { + return -1; + } + + // + // Handle various cases for which this function might be called + // + + switch (pPSUIInfo->Reason) { + + case PROPSHEETUI_REASON_INIT: + // + // "Printer Properties" dialog only has one dummy tab + // + + memset(&psp, 0, sizeof(psp)); + psp.dwSize = sizeof(PROPSHEETPAGE); + psp.dwFlags = 0; + psp.hInstance = ghInst; + + psp.pszTemplate = MAKEINTRESOURCE(IDD_NULLPROP); + psp.pfnDlgProc = NullDlgProc; + + if (pPSUIInfo->pfnComPropSheet(pPSUIInfo->hComPropSheet, + CPSFUNC_ADD_PROPSHEETPAGE, + (LPARAM) &psp, + 0)) + { + pPSUIInfo->Result = CPSUI_CANCEL; + return 1; + } + break; + + case PROPSHEETUI_REASON_GET_INFO_HEADER: + { PPROPSHEETUI_INFO_HEADER pPSUIHdr; + + pPSUIHdr = (PPROPSHEETUI_INFO_HEADER) lParam; + pPSUIHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW; + pPSUIHdr->pTitle = pDPHdr->pszPrinterName; + pPSUIHdr->hInst = ghInst; + pPSUIHdr->IconID = IDI_CPSUI_FAX; + } + return 1; + + case PROPSHEETUI_REASON_SET_RESULT: + pPSUIInfo->Result = ((PSETRESULT_INFO) lParam)->Result; + return 1; + + case PROPSHEETUI_REASON_DESTROY: + return 1; + } + + return -1; +} + +LONG +SimpleDocumentProperties(PDOCUMENTPROPERTYHEADER pDPHdr) + +/*++ + +Routine Description: + + Handle simple "Document Properties" where we don't need to display + a dialog and therefore don't have to have common UI library involved + +Arguments: + + pDPHdr - Points to a DOCUMENTPROPERTYHEADER structure + +Return Value: + + > 0 if successful, <= 0 otherwise + +--*/ + +{ + LONG lRet; + + lRet = DrvDocumentProperties(NULL, + pDPHdr->hPrinter, + pDPHdr->pszPrinterName, + pDPHdr->pdmOut, + pDPHdr->pdmIn, + pDPHdr->fMode); + + if (pDPHdr->fMode == 0 || pDPHdr->pdmOut == NULL) { + pDPHdr->cbOut = lRet; + } + + return lRet; +} diff --git a/private/mvdm/fax/wowfaxui/wfsheets.h b/private/mvdm/fax/wowfaxui/wfsheets.h new file mode 100644 index 000000000..2f59f0293 --- /dev/null +++ b/private/mvdm/fax/wowfaxui/wfsheets.h @@ -0,0 +1,33 @@ +//************************************************************************ +// Generic Win 3.1 fax printer driver support. User Interface functions +// which are called by WINSPOOL. Support for Two new entry points required +// by the Win 95 printer UI, DrvDocumentPropertySheets and +// DrvDevicePropertySheets +// +// History: +// 24-Apr-96 reedb created. +// +//************************************************************************ + +#include "winddiui.h" + +// Data structure maintained by the fax driver user interface +typedef struct { + + PVOID startUiData; + HANDLE hPrinter; + PDEVMODE pdmIn; + PDEVMODE pdmOut; + DWORD fMode; + LPTSTR pDriverName; + LPTSTR pDeviceName; + PFNCOMPROPSHEET pfnComPropSheet; + HANDLE hComPropSheet; + HANDLE hFaxOptsPage; + PVOID endUiData; + +} UIDATA, *PUIDATA; + +#define ValidUiData(pUiData) \ + ((pUiData) && (pUiData) == (pUiData)->startUiData && (pUiData) == (pUiData)->endUiData) + diff --git a/private/mvdm/fax/wowfaxui/wfupgrad.c b/private/mvdm/fax/wowfaxui/wfupgrad.c new file mode 100644 index 000000000..b382d605e --- /dev/null +++ b/private/mvdm/fax/wowfaxui/wfupgrad.c @@ -0,0 +1,264 @@ +//************************************************************************ +// Generic Win 3.1 fax printer driver support. User Interface helper +// functions which are called in WOWFAXUI.C, helpers used during upgrade. +// +// History: +// 14-mar-95 reedb Created. These were moved from WOWFAXUI.C. +// +//************************************************************************ + +#include "windows.h" +#include "wowfaxui.h" +#include "winspool.h" + +extern LPCRITICAL_SECTION lpCriticalSection; +extern HINSTANCE ghInst; + +//************************************************************************ +// AllocPathW - Helper for DrvUpgradePrinter and friends. +//************************************************************************ + +PWSTR AllocPathW(VOID) +{ + PWSTR szTmp; + + szTmp = WFLOCALALLOC((MAX_PATH+1) * sizeof(TCHAR), L"AllocPathW"); + return(szTmp); +} + +//************************************************************************ +// BuildPathW - Helper for DrvUpgradePrinter and friends. +//************************************************************************ + +PWSTR BuildPathW(PWSTR szPath, PWSTR szFileName) +{ + PWSTR szTmp; + + if ((szTmp = WFLOCALALLOC((MAX_PATH+1) * sizeof(TCHAR), L"BuildPathW")) != NULL) { + wcscpy(szTmp, szPath); + wcscat(szTmp, L"\\"); + wcscat(szTmp, szFileName); + return(szTmp); + } + else { + return(NULL); + } +} + +//************************************************************************ +// MyGetFileTime - Helper for DrvUpgradePrinter and friends. +//************************************************************************ + +BOOL MyGetFileTime(PWSTR szDir, PWSTR szName, LPFILETIME lpFileTime) +{ + LPWIN32_FIND_DATA lpfd; + HANDLE hfd; + PWSTR szTmp; + BOOL bRet = FALSE; + + + szTmp = BuildPathW(szDir, szName); + lpfd = WFLOCALALLOC(sizeof(WIN32_FIND_DATA), L"MyGetFileTime"); + + if ((szTmp) && (lpfd)) { + LOGDEBUG(1, (L"WOWFAXUI!GetFileTime, szTmp: %s\n", szTmp)); + if ((hfd = FindFirstFile(szTmp, lpfd)) != INVALID_HANDLE_VALUE) { + memcpy(lpFileTime, &(lpfd->ftLastWriteTime), sizeof(FILETIME)); + FindClose(hfd); + bRet = TRUE; + LOGDEBUG(1, (L"WOWFAXUI!GetFileTime, FileTimeHi: %X FileTimeLo: %X\n", lpFileTime->dwHighDateTime, lpFileTime->dwLowDateTime)); + } + else { + LOGDEBUG(0, (L"WOWFAXUI!GetFileTime, file not found: %s\n", szTmp)); + } + } + + if (szTmp) { + LocalFree(szTmp); + } + if (lpfd) { + LocalFree(lpfd); + } + return(bRet); +} + +//************************************************************************ +// CheckForNewerFiles - Helper for DrvUpgradePrinter. Compares the date/time +// of wowfaxui.dll and wowfax.dll in the two passed directories. Returns +// FALSE if files in szOldDriverDir are the same or newer than those +// in szSysDir. Otherwise returns non-zero. +//************************************************************************ + +BOOL CheckForNewerFiles(PWSTR szOldDriverDir, PWSTR szSysDir) +{ + FILETIME ftSourceDriver, ftCurrentDriver; + BOOL bRet = FALSE; + + if ((szOldDriverDir) && (szSysDir)) { + if (MyGetFileTime(szOldDriverDir, L"wowfax.dll", &ftCurrentDriver)) { + if (MyGetFileTime(szSysDir, L"wowfax.dll", &ftSourceDriver)) { + // Check time/date to see if we need to update the drivers. + if (CompareFileTime(&ftSourceDriver, &ftCurrentDriver) > 0) { + bRet = TRUE; + } + } + } + if (MyGetFileTime(szOldDriverDir, L"wowfaxui.dll", &ftCurrentDriver)) { + if (MyGetFileTime(szSysDir, L"wowfaxui.dll", &ftSourceDriver)) { + if (CompareFileTime(&ftSourceDriver, &ftCurrentDriver) > 0) { + bRet = TRUE; + } + } + } + } + else { + LOGDEBUG(0, (L"WOWFAXUI!CheckForNewerFiles: NULL directory parameters\n")); + } + + return(bRet); +} + +//************************************************************************ +// DoUpgradePrinter - Called by DrvUpgradePrinter which is called in the +// system context by the spooler. +//************************************************************************ + +BOOL DoUpgradePrinter(DWORD dwLevel, LPDRIVER_UPGRADE_INFO_1W lpDrvUpgradeInfo) +{ + static BOOL bDrvUpgradePrinterLock = FALSE; + HANDLE hPrinter = NULL; + DRIVER_INFO_2 DriverInfo, *pDriverInfo = NULL; + DWORD dwNeeded = 0; + PWSTR szSysDir = NULL; + PWSTR szDstDir = NULL; + PWSTR szSrcPath = NULL; + PWCHAR pwc; + BOOL bRet = FALSE; + TCHAR szName[WOWFAX_MAX_USER_MSG_LEN] = L""; + + // Check for correct level for upgrade. + if (dwLevel != 1) { + LOGDEBUG(0, (L"WOWFAXUI!DrvUpgradePrinter, Bad input Level\n")); + SetLastError(ERROR_INVALID_LEVEL); + goto DoUpgradePrinterExit; + } + + szDstDir = AllocPathW(); + szSysDir = AllocPathW(); + if (!szDstDir || !szSysDir) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, work space allocation failed\n")); + goto DoUpgradePrinterExit; + } + + if (!GetSystemDirectory(szSysDir, MAX_PATH+1)) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, GetSystemDirectory failed\n")); + goto DoUpgradePrinterExit; + } + + if (!lpDrvUpgradeInfo->pPrinterName) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, pPrinterName is NULL\n")); + goto DoUpgradePrinterExit; + } + + // Get the paths to the old printer drivers. + if (!OpenPrinter(lpDrvUpgradeInfo->pPrinterName, &hPrinter, NULL)) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, Unable to open: %s\n", lpDrvUpgradeInfo->pPrinterName)); + goto DoUpgradePrinterExit; + } + + GetPrinterDriver(hPrinter, NULL, 2, (LPBYTE) pDriverInfo, 0, &dwNeeded); + + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, GetPrinterDriver failed\n")); + goto DoUpgradePrinterExit; + } + + if ((pDriverInfo = WFLOCALALLOC(dwNeeded, L"DoUpgradePrinter")) == NULL) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, work space allocation failed\n")); + goto DoUpgradePrinterExit; + } + + if (!GetPrinterDriver(hPrinter, NULL, 2, (LPBYTE) pDriverInfo, dwNeeded, &dwNeeded)) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, GetPrinterDriver failed, GetLastError: %d\n", GetLastError())); + goto DoUpgradePrinterExit; + } + ClosePrinter(hPrinter); + + // Strip off the file name. + if ((pwc = wcsrchr(pDriverInfo->pDriverPath, L'\\')) == NULL) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, unable to strip file name\n")); + goto DoUpgradePrinterExit; + } + *pwc = UNICODE_NULL; + + // Install new printer driver if it's more recent than the old one. + if (CheckForNewerFiles(pDriverInfo->pDriverPath, szSysDir)) { + LOGDEBUG(1, (L"WOWFAXUI!DoUpgradePrinter, Doing driver update\n")); + memset(&DriverInfo, 0, sizeof(DRIVER_INFO_2)); + + if (!GetPrinterDriverDirectory(NULL, NULL, 1, (LPBYTE) szDstDir, MAX_PATH, &dwNeeded)) { + LOGDEBUG(0, (L"WOWFAXUI!DoUpgradePrinter, GetPrinterDriverDirectory failed\n")); + goto DoUpgradePrinterExit; + } + + // This is a dummy. We've no data file, but spooler won't take NULL. + DriverInfo.pDataFile = BuildPathW(szDstDir, WOWFAX_DLL_NAME); + DriverInfo.pDriverPath = BuildPathW(szDstDir, WOWFAX_DLL_NAME); + LOGDEBUG(1, (L"WOWFAXUI!DoUpgradePrinter, pDriverPath = %s\n", DriverInfo.pDataFile)); + if (DriverInfo.pDriverPath) { + szSrcPath = BuildPathW(szSysDir, WOWFAX_DLL_NAME); + if (szSrcPath) { + CopyFile(szSrcPath, DriverInfo.pDriverPath, FALSE); + LocalFree(szSrcPath); + } + } + + DriverInfo.pConfigFile = BuildPathW(szDstDir, WOWFAXUI_DLL_NAME); + szSrcPath = BuildPathW(szSysDir, WOWFAXUI_DLL_NAME); + if (DriverInfo.pConfigFile) { + if (szSrcPath) { + CopyFile(szSrcPath, DriverInfo.pConfigFile, FALSE); + LocalFree(szSrcPath); + } + } + + // Install the printer driver. + DriverInfo.cVersion = 1; + if (LoadString(ghInst, WOWFAX_NAME_STR, szName, WOWFAX_MAX_USER_MSG_LEN)) { + DriverInfo.pName = szName; + if (AddPrinterDriver(NULL, 2, (LPBYTE) &DriverInfo) == FALSE) { + bRet = (GetLastError() == ERROR_PRINTER_DRIVER_ALREADY_INSTALLED); + } + else { + bRet = TRUE; + } + } + if (DriverInfo.pDataFile) { + LocalFree(DriverInfo.pDataFile); + } + if (DriverInfo.pDriverPath) { + LocalFree(DriverInfo.pDriverPath); + } + if (DriverInfo.pConfigFile) { + LocalFree(DriverInfo.pConfigFile); + } + } + else { + LOGDEBUG(1, (L"WOWFAXUI!DoUpgradePrinter, No driver update\n")); + bRet = TRUE; + } + +DoUpgradePrinterExit: + if (szDstDir) { + LocalFree(szDstDir); + } + if (szSysDir) { + LocalFree(szSysDir); + } + if (pDriverInfo) { + LocalFree(pDriverInfo); + } + + return(bRet); +} + 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; +} diff --git a/private/mvdm/fax/wowfaxui/wowfaxui.def b/private/mvdm/fax/wowfaxui/wowfaxui.def new file mode 100644 index 000000000..95bdf76d0 --- /dev/null +++ b/private/mvdm/fax/wowfaxui/wowfaxui.def @@ -0,0 +1,16 @@ +LIBRARY wowfaxui + +DESCRIPTION 'wow fax driver ui (rasddui)' + + +EXPORTS + DllInitProc + PrinterProperties + DrvDocumentProperties + DrvAdvancedDocumentProperties + DevQueryPrintEx + DrvDeviceCapabilities + DrvUpgradePrinter + DrvDocumentEvent + DrvDocumentPropertySheets + DrvDevicePropertySheets diff --git a/private/mvdm/fax/wowfaxui/wowfaxui.h b/private/mvdm/fax/wowfaxui/wowfaxui.h new file mode 100644 index 000000000..1cca71d96 --- /dev/null +++ b/private/mvdm/fax/wowfaxui/wowfaxui.h @@ -0,0 +1,164 @@ +//**************************************************************************** +// Generic Win 3.1 fax printer driver support +// +// 02-jan-95 nandurir created. +// 14-mar-95 reedb Use GDI hooks to move most functionality to UI. +// 16-aug-95 reedb Move to kernel mode. Many declarations and +// definitions moved from FAXCOMM.H to this file. +// +//**************************************************************************** + +#include "stddef.h" +#include "windows.h" +#include "winddi.h" + +#include "faxcomm.h" +#include "winspool.h" + +// The following include is to pickup the definitions for +// the DrvUpgradePrinter private API. These definitions should be in public. + +#include "..\..\..\windows\spooler\inc\splapip.h" + +// WOWFAX component file names. +#define WOWFAX_DLL_NAME L"WOWFAX.DLL" +#define WOWFAXUI_DLL_NAME L"WOWFAXUI.DLL" + +// String table constants: +#define WOWFAX_MAX_USER_MSG_LEN 256 + +#define WOWFAX_UNKNOWN_PROB_STR 0x100 +#define WOWFAX_NAME_STR 0x101 +#define WOWFAX_NOWOW_STR 0x102 +#define WOWFAX_SELF_CONFIG_STR 0x103 +#define WOWFAX_ENABLE_CONFIG_STR 0x104 + +// Dialog constants: +#define IDD_NULLPROP 0x200 +#define IDD_DOCPROP 0x201 + +// Text control constants: +#define IDC_STATIC -1 +#define IDC_FEEDBACK 0x300 + +// InterProcCommHandler command constants +#define DRVFAX_SETMAPDATA 0x1 +#define DRVFAX_SENDTOWOW 0x2 +#define DRVFAX_SENDNOTIFYWOW 0x3 +#define DRVFAX_CREATEMAP 0x4 +#define DRVFAX_DESTROYMAP 0x5 +#define DRVFAX_CALLWOW 0x6 + +// Logging macros +/* XLATOFF */ +// #define IFLOG(l) if (l==iFaxLogLevel && (iFaxLogLevel&1) || l<=iFaxLogLevel && !(iFaxLogLevel&1) || l == 0) + +#undef LOG +#ifdef NOLOG +#define LOG(l,args) +#define SETREQLOG(l) +#else +#define SETREQLOG(l) iReqFaxLogLevel = l +#define LOG(l,args) {SETREQLOG(l) ; faxlogprintf args;} +#endif + +#if DBG +extern INT iReqFaxLogLevel; +#define LOGDEBUG(l,args) LOG(l,args) +#else +#define LOGDEBUG(l,args) +#endif +/* XLATON */ + + +// +// This structure is used to hold 16-bit fax driver data stored +// in the registry. +// + +typedef struct _REGFAXDRVINFO16 { + LPTSTR lpDriverName; + LPTSTR lpPortName; +} REGFAXDRVINFO16, *LPREGFAXDRVINFO16; + +// The the escapes in the following escape range all need a valid HDC. +// Range is inclusive lower, exclusive upper bound. See GDISPOOL.H for +// the actual escape definitions. + +#define DOCUMENTEVENT_HDCFIRST 5 +#define DOCUMENTEVENT_HDCLAST 11 + +// Prototypes for public functions implemented in WFSHEETS.C: +PVOID MyGetPrinter(HANDLE hPrinter, DWORD level); + +// Prototypes for public functions implemented in WFUPGRAD.C: + +BOOL DoUpgradePrinter(DWORD dwLevel, LPDRIVER_UPGRADE_INFO_1W lpDrvUpgradeInfo); + +// Prototypes for public functions implemented in WFHELPERS.C: + +LPREGFAXDRVINFO16 Get16BitDriverInfoFromRegistry(PWSTR pDeviceName); + +VOID faxlogprintf(LPTSTR pszFmt, ...); +VOID LogFaxDev(LPTSTR pszTitle, LPFAXDEV lpFaxDev); +VOID LogWowFaxInfo(LPWOWFAXINFO lpWowFaxInfo); +BOOL ValidateFaxDev(LPFAXDEV lpFaxDev); +VOID Free16BitDriverInfo(LPREGFAXDRVINFO16 lpRegFaxDrvInfo16); +BOOL FaxMapHandler(LPFAXDEV lpdev, UINT iAction); +BOOL InterProcCommHandler(LPFAXDEV lpdev, UINT iAction); +LPVOID WFHeapAlloc(DWORD dwBytes, LPWSTR lpszWhoCalled); +LPVOID WFLocalAlloc(DWORD dwBytes, LPWSTR lpszWhoCalled); +HWND FindWowFaxWindow(void); +LPTSTR DupTokenW(LPTSTR lpTok); + +// Prototypes for functions which DrvDocumentEvent dispatches, +// implemented in WOWFAXUI.C: + +int DocEvntCreateDCpre( + LPWSTR lpszDevice, + DEVMODEW *pDevModIn, + DEVMODEW **pDevModOut +); + +int DocEvntResetDCpre( + HDC hdc, + DEVMODEW *pDevModIn, + DEVMODEW **pDevModOut +); + +int DocEvntCreateDCpost( + HDC hdc, + DEVMODEW *pDevModIn +); + +int DocEvntResetDCpost( + HDC hdc, + DEVMODEW *pDevModIn +); + +int DocEvntStartDoc( +HDC hdc +); + +int DocEvntDeleteDC( + HDC hdc +); + +int DocEvntEndPage( + HDC hdc +); + +int DocEvntEndDoc( +HDC hdc +); + +// +// Memory allocation macro. +// + +#if DBG +#define WFLOCALALLOC(dwBytes, lpszWhoCalled) WFLocalAlloc(dwBytes, lpszWhoCalled) +#else +#define WFLOCALALLOC(dwBytes, lpszWhoCalled) LocalAlloc(LPTR, dwBytes) +#endif + diff --git a/private/mvdm/fax/wowfaxui/wowfaxui.rc b/private/mvdm/fax/wowfaxui/wowfaxui.rc new file mode 100644 index 000000000..6eaa838ab --- /dev/null +++ b/private/mvdm/fax/wowfaxui/wowfaxui.rc @@ -0,0 +1,45 @@ +#include <windows.h> +#include "wowfaxui.h" + +STRINGTABLE + +BEGIN + WOWFAX_UNKNOWN_PROB_STR "Unknown print problem" + WOWFAX_SELF_CONFIG_STR "This driver is self configuring. No setup is needed." + WOWFAX_NAME_STR "Windows 3.1 Compatible Fax Driver" + WOWFAX_NOWOW_STR "Unable to start WOW. Verify the ability to run a Win 16 application and retry." + WOWFAX_ENABLE_CONFIG_STR "Please click the OK button to enable the configuration settings for the 16-bit Fax Driver." +END + +IDD_DOCPROP DIALOG DISCARDABLE 0, 0, 252, 216 +STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION +CAPTION "WowFax Options" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Please press the Configure button to set default options for the 16-bit Fax Driver.",IDC_STATIC,8,12,240,24 + LTEXT "", IDC_FEEDBACK, 8, 84, 240, 24 + PUSHBUTTON "Configure", IDOK, 8, 48, 64, 14, WS_GROUP | WS_TABSTOP + +END + +IDD_NULLPROP DIALOG DISCARDABLE 0, 0, 252, 216 +STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION +CAPTION "WowFax" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Global configuration of 16-bit fax drivers is not supported", + IDC_STATIC,10,15,230,32 +END + + +#include <ntverp.h> +#define VER_FILEVERSION 0, 2, 0, 0 +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_PRINTER +#define VER_FILEDESCRIPTION_STR "Windows 3.1 Compatible Fax Driver UI DLL" +#define VER_INTERNALNAME_STR "wowfaxui.dll" +#define VER_ORIGINALFILENAME_STR "wowfaxui.dll" + +#include "common.ver" + + |