//************************************************************************ // 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" #include "dde.h" extern LPCRITICAL_SECTION lpCriticalSection; extern HINSTANCE ghInst; BOOL InSetupMode(void); #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, 120 * 1000); if ((hwnd = FindWindow(WOWFAX_CLASS, NULL)) != NULL) { return(hwnd); } } // If WOW failed to start -- let user know. // -- except during setup mode -- the spooler calls into every printer // driver to update the registry printer settings if needed. if(!InSetupMode()) { 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[MAX_PATH]; HKEY hKey = 0; DWORD dwType, cbBufSize = MAX_PATH; LPTSTR lpTok, lpDevName; LPREGFAXDRVINFO16 lpRetVal = WFLOCALALLOC(sizeof(REGFAXDRVINFO16), L"Get16BitDriverInfoFromRegistry"); if ((pDeviceName != NULL) && (lpRetVal != NULL)) { // Extract the 16-bit device name from pDeviceName. wcsncpy(szRetBuf, pDeviceName, sizeof(szRetBuf)/sizeof(TCHAR)); szRetBuf[(sizeof(szRetBuf)/sizeof(TCHAR))-1] = '\0'; lpDevName = szRetBuf; while (lpTok = wcschr(lpDevName, '\\')) { lpDevName = ++lpTok; } if (lpTok = wcschr(lpDevName, ',')) { *lpTok = '\0'; } if (lpRetVal->lpDeviceName = DupTokenW(lpDevName)) { if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WOW\\WowFax\\devices", 0, KEY_READ, &hKey ) == ERROR_SUCCESS) { if (RegQueryValueEx(hKey, lpDevName, 0, &dwType, (LPBYTE)szRetBuf, &cbBufSize) == ERROR_SUCCESS) { // Parse registry data into driver name and port name. // Make wcstok multi-thread safe, it stores state. EnterCriticalSection(lpCriticalSection); lpTok = wcstok(szRetBuf, L","); lpRetVal->lpDriverName = DupTokenW(lpTok); lpTok = wcstok(NULL, L","); lpRetVal->lpPortName = DupTokenW(lpTok); LeaveCriticalSection(lpCriticalSection); } RegCloseKey(hKey); } } } if (lpRetVal && lpRetVal->lpDeviceName && lpRetVal->lpDriverName && lpRetVal->lpPortName) { LOGDEBUG(1, (L"WOWFAXUI!Get16BitDriverInfoFromRegistry, Name: %s, Driver: %s, Port: %s\n", pDeviceName, lpRetVal->lpDriverName, lpRetVal->lpPortName)); return(lpRetVal); } LOGDEBUG(0, (L"WOWFAXUI!Get16BitDriverInfoFromRegistry, failed\n")); Free16BitDriverInfo(lpRetVal); return(NULL); } //************************************************************************ // Free16BitDriverInfo - Free the 16-bit driver info allocated by // Get16BitDriverInfoFromRegistry. //************************************************************************ VOID Free16BitDriverInfo(LPREGFAXDRVINFO16 lpRegFaxDrvInfo16) { if (lpRegFaxDrvInfo16) { if (lpRegFaxDrvInfo16->lpDeviceName) { LocalFree(lpRegFaxDrvInfo16->lpDeviceName); } 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)) { // EasyFax ver2.0 & MyTalk ver 2.0 // Also Procomm+ 3 cover sheets. Bug #305665 if ((msg.message == WM_PAINT) || (msg.message >= WM_USER) || ((msg.message >= WM_DDE_FIRST) && (msg.message <= WM_DDE_LAST) )) { DispatchMessage(&msg); } else { DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam); } } } } 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); } //************************************************************************ // InSetupMode: Checks if this process is running during NT setup. // // return: // TRUE if in NT setup // FALSE otherwise //************************************************************************ BOOL InSetupMode(void) { DWORD SetupMode = FALSE; LONG results; DWORD Type, Size = sizeof(DWORD); HKEY Key; results = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"System\\Setup", &Key ); if (results != ERROR_SUCCESS) return FALSE; results = RegQueryValueExW(Key, L"SystemSetupInProgress", NULL, &Type, (PBYTE)&SetupMode, &Size); RegCloseKey(Key); return (!(SetupMode == 0)); }