Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

516 lines
18 KiB

  1. //************************************************************************
  2. // Generic Win 3.1 fax printer driver support. Helper functions which are
  3. // called in WOWFAXUI.C
  4. //
  5. // History:
  6. // 14-mar-95 reedb Created. Many of the functions were moved from
  7. // FAXCOMM.C, since they're no longer called
  8. // from WOWFAX.DLL.
  9. // 16-aug-95 reedb Move to kernel mode. Debug output and validate
  10. // functions moved from FAXCOMM.C.
  11. //
  12. //************************************************************************
  13. #include "wowfaxui.h"
  14. #include "dde.h"
  15. extern LPCRITICAL_SECTION lpCriticalSection;
  16. extern HINSTANCE ghInst;
  17. BOOL InSetupMode(void);
  18. #if DBG
  19. INT iFaxLogLevel = 20;
  20. INT iReqFaxLogLevel = 0;
  21. typedef PVOID HANDLE;
  22. //************************************************************************
  23. // faxlogprintf - Two different implementations. One for client side
  24. // debugging the other for server side.
  25. //
  26. //************************************************************************
  27. // For Debug logging.
  28. #define MAX_DISPLAY_LINE 256 // 128 characters.
  29. TCHAR szFaxLogFile[] = L"C:\\FAXLOG.LOG";
  30. HANDLE hfFaxLog = NULL;
  31. // Defines for iFaxLogMode
  32. #define NO_LOGGING 0
  33. #define LOG_TO_FILE 1
  34. #define OPEN_LOG_FILE 2
  35. #define CLOSE_LOG_FILE 3
  36. INT iFaxLogMode = NO_LOGGING;
  37. VOID faxlogprintf(LPTSTR pszFmt, ...)
  38. {
  39. DWORD lpBytesWritten;
  40. int len;
  41. TCHAR szText[1024];
  42. va_list arglist;
  43. va_start(arglist, pszFmt);
  44. len = wvsprintf(szText, pszFmt, arglist);
  45. if (iFaxLogMode > LOG_TO_FILE) {
  46. if (iFaxLogMode == OPEN_LOG_FILE) {
  47. if((hfFaxLog = CreateFile(szFaxLogFile,
  48. GENERIC_WRITE,
  49. FILE_SHARE_WRITE,
  50. NULL,
  51. CREATE_ALWAYS,
  52. FILE_ATTRIBUTE_NORMAL,
  53. NULL)) != INVALID_HANDLE_VALUE) {
  54. iFaxLogMode = LOG_TO_FILE;
  55. }
  56. else {
  57. hfFaxLog = NULL;
  58. iFaxLogMode = NO_LOGGING;
  59. OutputDebugString(L"Couldn't open fax log file!\n");
  60. }
  61. }
  62. else {
  63. FlushFileBuffers(hfFaxLog);
  64. CloseHandle(hfFaxLog);
  65. hfFaxLog = NULL;
  66. iFaxLogMode = NO_LOGGING;
  67. }
  68. }
  69. if (iFaxLogLevel >= iReqFaxLogLevel) {
  70. if (iFaxLogMode) {
  71. WriteFile(hfFaxLog, szText, len, &lpBytesWritten, NULL);
  72. }
  73. else {
  74. OutputDebugString(szText);
  75. }
  76. }
  77. }
  78. VOID LogWowFaxInfo(LPWOWFAXINFO lpWowFaxInfo)
  79. {
  80. faxlogprintf(L"\tlpWowFaxInfo (lpMap): %X\n", lpWowFaxInfo);
  81. faxlogprintf(L"\t\thwnd: %X\n", lpWowFaxInfo->hwnd);
  82. faxlogprintf(L"\t\ttid: %X\n", lpWowFaxInfo->tid);
  83. faxlogprintf(L"\t\tproc16: %X\n", lpWowFaxInfo->proc16);
  84. faxlogprintf(L"\t\tlpinfo16: %X\n", lpWowFaxInfo->lpinfo16);
  85. faxlogprintf(L"\t\tmsg: %X\n", lpWowFaxInfo->msg);
  86. faxlogprintf(L"\t\thdc: %X\n", lpWowFaxInfo->hdc);
  87. faxlogprintf(L"\t\twCmd: %X\n", lpWowFaxInfo->wCmd);
  88. faxlogprintf(L"\t\tcData: %X\n", lpWowFaxInfo->cData);
  89. faxlogprintf(L"\t\thwndui: %X\n", lpWowFaxInfo->hwndui);
  90. faxlogprintf(L"\t\tretvalue: %X\n", lpWowFaxInfo->retvalue);
  91. faxlogprintf(L"\t\tstatus: %X\n", lpWowFaxInfo->status);
  92. if (lpWowFaxInfo->lpDevice) {
  93. faxlogprintf(L"\t\tlpDevice: %s\n", lpWowFaxInfo->lpDevice);
  94. }
  95. else {
  96. faxlogprintf(L"\t\tlpDevice: %X\n", lpWowFaxInfo->lpDevice);
  97. }
  98. if (lpWowFaxInfo->lpDriverName) {
  99. faxlogprintf(L"\t\tlpDriverName: %s\n", lpWowFaxInfo->lpDriverName);
  100. }
  101. else {
  102. faxlogprintf(L"\t\tlpDriverName: %X\n", lpWowFaxInfo->lpDriverName);
  103. }
  104. if (lpWowFaxInfo->lpPortName) {
  105. faxlogprintf(L"\t\tlpPortName: %s\n", lpWowFaxInfo->lpPortName);
  106. }
  107. else {
  108. faxlogprintf(L"\t\tlpPortName: %X\n", lpWowFaxInfo->lpPortName);
  109. }
  110. faxlogprintf(L"\t\tlpIn: %X\n", lpWowFaxInfo->lpIn);
  111. faxlogprintf(L"\t\tlpOut: %X\n", lpWowFaxInfo->lpOut);
  112. if (lpWowFaxInfo->szDeviceName) {
  113. faxlogprintf(L"\t\tszDeviceName: %s\n", lpWowFaxInfo->szDeviceName);
  114. }
  115. else {
  116. faxlogprintf(L"\t\tszDeviceName: %X\n", lpWowFaxInfo->szDeviceName);
  117. }
  118. faxlogprintf(L"\t\tbmPixPerByte: %X\n", lpWowFaxInfo->bmPixPerByte);
  119. faxlogprintf(L"\t\tbmWidthBytes: %X\n", lpWowFaxInfo->bmWidthBytes);
  120. faxlogprintf(L"\t\tbmHeight: %X\n", lpWowFaxInfo->bmHeight);
  121. faxlogprintf(L"\t\tlpbits: %X\n", lpWowFaxInfo->lpbits);
  122. }
  123. VOID LogFaxDev(LPTSTR pszTitle, LPFAXDEV lpFaxDev)
  124. {
  125. DWORD dwTmp;
  126. CHAR cTmp0, cTmp1, cTmp2, cTmp3;
  127. faxlogprintf(L"WOWFAXUI!%s: %X\n", pszTitle, lpFaxDev);
  128. dwTmp = lpFaxDev->id;
  129. cTmp3 = (CHAR) dwTmp & 0xFF;
  130. cTmp2 = (CHAR) (dwTmp >> 8) & 0xFF;
  131. cTmp1 = (CHAR) (dwTmp >> 16) & 0xFF;
  132. cTmp0 = (CHAR) (dwTmp >> 24) & 0xFF;
  133. faxlogprintf(L"\tid: %c%c%c%c\n", cTmp3, cTmp2, cTmp1, cTmp0);
  134. faxlogprintf(L"\tlpNext: %X\n", lpFaxDev->lpNext);
  135. faxlogprintf(L"\tlpClient: %X\n", lpFaxDev->lpClient);
  136. faxlogprintf(L"\thdev: %X\n", lpFaxDev->hdev);
  137. faxlogprintf(L"\tidMap: %X\n", lpFaxDev->idMap);
  138. faxlogprintf(L"\tcbMapLow: %X\n", lpFaxDev->cbMapLow);
  139. faxlogprintf(L"\thMap: %X\n", lpFaxDev->hMap);
  140. faxlogprintf(L"\tszMap: %s\n", lpFaxDev->szMap);
  141. if (lpFaxDev->lpMap) {
  142. LogWowFaxInfo(lpFaxDev->lpMap);
  143. }
  144. else {
  145. faxlogprintf(L"\tlpMap: %X\n", lpFaxDev->lpMap);
  146. }
  147. faxlogprintf(L"\toffbits: %X\n", lpFaxDev->offbits);
  148. faxlogprintf(L"\thbm: %X\n", lpFaxDev->hbm);
  149. faxlogprintf(L"\tcPixPerByte: %X\n", lpFaxDev->cPixPerByte);
  150. faxlogprintf(L"\tbmFormat: %X\n", lpFaxDev->bmFormat);
  151. faxlogprintf(L"\tbmWidthBytes: %X\n", lpFaxDev->bmWidthBytes);
  152. faxlogprintf(L"\thbmSurf: %X\n", lpFaxDev->hbmSurf);
  153. faxlogprintf(L"\thwnd: %X\n", lpFaxDev->hwnd);
  154. faxlogprintf(L"\ttid: %X\n", lpFaxDev->tid);
  155. faxlogprintf(L"\tlpinfo16: %X\n", lpFaxDev->lpinfo16);
  156. faxlogprintf(L"\thDriver: %X\n", lpFaxDev->hDriver);
  157. faxlogprintf(L"\tStart of gdiinfo: %X\n", (DWORD)&(lpFaxDev->gdiinfo));
  158. faxlogprintf(L"\tStart of devinfo: %X\n", (DWORD)&(lpFaxDev->devinfo));
  159. faxlogprintf(L"\tpdevmode: %X\n", lpFaxDev->pdevmode);
  160. }
  161. #endif
  162. //************************************************************************
  163. // ValidateFaxDev - Validates the FAXDEV structure by checking the DWORD
  164. // signature, which is a known fixed value.
  165. //
  166. //************************************************************************
  167. BOOL ValidateFaxDev(LPFAXDEV lpFaxDev)
  168. {
  169. if (lpFaxDev) {
  170. if (lpFaxDev->id == FAXDEV_ID) {
  171. return TRUE;
  172. }
  173. LOGDEBUG(0, (L"ValidateFaxDev failed, bad id, lpFaxDev: %X\n", lpFaxDev));
  174. }
  175. else {
  176. LOGDEBUG(0, (L"ValidateFaxDev failed, lpFaxDev: NULL\n"));
  177. }
  178. return FALSE;
  179. }
  180. //***************************************************************************
  181. // WFLocalAlloc - Debug version of LocalAlloc.
  182. //***************************************************************************
  183. LPVOID WFLocalAlloc(DWORD dwBytes, LPWSTR lpszWhoCalled)
  184. {
  185. LPVOID lpTmp;
  186. lpTmp = LocalAlloc(LPTR, dwBytes);
  187. if (lpTmp == NULL){
  188. LOGDEBUG(0, (L"WOWFAXUI!%s, failed on memory allocation of %d bytes\n", lpszWhoCalled, dwBytes));
  189. }
  190. return(lpTmp);
  191. }
  192. //***************************************************************************
  193. // FindWowFaxWindow - Put up a message box if you can't.
  194. //***************************************************************************
  195. HWND FindWowFaxWindow(void)
  196. {
  197. HWND hwnd;
  198. PROCESS_INFORMATION ProcessInformation;
  199. STARTUPINFO StartupInfo;
  200. DWORD WaitStatus;
  201. TCHAR szMsg[WOWFAX_MAX_USER_MSG_LEN];
  202. TCHAR szTitle[WOWFAX_MAX_USER_MSG_LEN];
  203. WCHAR szWowExec[] = L"WOWEXEC";
  204. if ((hwnd = FindWindow(WOWFAX_CLASS, NULL)) == NULL) {
  205. // You can't find the WowFaxWindow, try to start WOW.
  206. RtlZeroMemory((PVOID)&StartupInfo, (DWORD)sizeof(StartupInfo));
  207. StartupInfo.cb = sizeof(StartupInfo);
  208. StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  209. StartupInfo.wShowWindow = SW_NORMAL;
  210. if (CreateProcess(NULL,
  211. szWowExec,
  212. NULL, // security
  213. NULL, // security
  214. FALSE, // inherit handles
  215. CREATE_NEW_CONSOLE | CREATE_DEFAULT_ERROR_MODE,
  216. NULL, // environment strings
  217. NULL, // current directory
  218. &StartupInfo,
  219. &ProcessInformation)) {
  220. WaitForInputIdle(ProcessInformation.hProcess, 120 * 1000);
  221. if ((hwnd = FindWindow(WOWFAX_CLASS, NULL)) != NULL) {
  222. return(hwnd);
  223. }
  224. }
  225. // If WOW failed to start -- let user know.
  226. // -- except during setup mode -- the spooler calls into every printer
  227. // driver to update the registry printer settings if needed.
  228. if(!InSetupMode()) {
  229. if (LoadString(ghInst, WOWFAX_NAME_STR, szTitle, WOWFAX_MAX_USER_MSG_LEN)) {
  230. if (LoadString(ghInst, WOWFAX_NOWOW_STR, szMsg, WOWFAX_MAX_USER_MSG_LEN)) {
  231. MessageBox(hwnd, szMsg, szTitle, MB_OK);
  232. }
  233. }
  234. }
  235. }
  236. return(hwnd);
  237. }
  238. //************************************************************************
  239. // DupTokenW - Helper for Get16BitDriverInfoFromRegistry. Allocate and
  240. // copy a token, wide format. Allocates storage for duplicate.
  241. // wcsdup is not present in the run-times we link to.
  242. //************************************************************************
  243. LPTSTR DupTokenW(LPTSTR lpTok)
  244. {
  245. LPTSTR lpRetVal = NULL;
  246. if (lpTok != NULL) {
  247. lpRetVal = WFLOCALALLOC((wcslen(lpTok) + 1) * sizeof(TCHAR), L"DupTokenW");
  248. if (lpRetVal) {
  249. wcscpy(lpRetVal, lpTok);
  250. }
  251. }
  252. return(lpRetVal);
  253. }
  254. //************************************************************************
  255. // Get16BitDriverInfoFromRegistry - Get the 16-bit driver info (name, port)
  256. // from the registry where it is written by the 16-bit fax driver
  257. // install program using an intercepted WriteProfileString. Storage is
  258. // allocated for the returned info, and must be freed by the caller
  259. // using Free16BitDriverInfo. See also Set16BitDriverInfoToRegistry
  260. // in WOW32FAX.C
  261. //************************************************************************
  262. LPREGFAXDRVINFO16 Get16BitDriverInfoFromRegistry(PWSTR pDeviceName)
  263. {
  264. TCHAR szRetBuf[MAX_PATH];
  265. HKEY hKey = 0;
  266. DWORD dwType, cbBufSize = MAX_PATH;
  267. LPTSTR lpTok, lpDevName;
  268. LPREGFAXDRVINFO16 lpRetVal = WFLOCALALLOC(sizeof(REGFAXDRVINFO16), L"Get16BitDriverInfoFromRegistry");
  269. if ((pDeviceName != NULL) && (lpRetVal != NULL)) {
  270. // Extract the 16-bit device name from pDeviceName.
  271. wcscpy(szRetBuf, pDeviceName);
  272. lpDevName = szRetBuf;
  273. while (lpTok = wcschr(lpDevName, '\\')) {
  274. lpDevName = ++lpTok;
  275. }
  276. if (lpTok = wcschr(lpDevName, ',')) {
  277. *lpTok = '\0';
  278. }
  279. if (lpRetVal->lpDeviceName = DupTokenW(lpDevName)) {
  280. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  281. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WOW\\WowFax\\devices",
  282. 0, KEY_READ, &hKey ) == ERROR_SUCCESS) {
  283. if (RegQueryValueEx(hKey, lpDevName, 0, &dwType, (LPBYTE)szRetBuf,
  284. &cbBufSize) == ERROR_SUCCESS) {
  285. // Parse registry data into driver name and port name.
  286. // Make wcstok multi-thread safe, it stores state.
  287. EnterCriticalSection(lpCriticalSection);
  288. lpTok = wcstok(szRetBuf, L",");
  289. lpRetVal->lpDriverName = DupTokenW(lpTok);
  290. lpTok = wcstok(NULL, L",");
  291. lpRetVal->lpPortName = DupTokenW(lpTok);
  292. LeaveCriticalSection(lpCriticalSection);
  293. }
  294. RegCloseKey(hKey);
  295. }
  296. }
  297. }
  298. if (lpRetVal && lpRetVal->lpDeviceName &&
  299. lpRetVal->lpDriverName && lpRetVal->lpPortName) {
  300. LOGDEBUG(1, (L"WOWFAXUI!Get16BitDriverInfoFromRegistry, Name: %s, Driver: %s, Port: %s\n", pDeviceName, lpRetVal->lpDriverName, lpRetVal->lpPortName));
  301. return(lpRetVal);
  302. }
  303. LOGDEBUG(0, (L"WOWFAXUI!Get16BitDriverInfoFromRegistry, failed\n"));
  304. Free16BitDriverInfo(lpRetVal);
  305. return(NULL);
  306. }
  307. //************************************************************************
  308. // Free16BitDriverInfo - Free the 16-bit driver info allocated by
  309. // Get16BitDriverInfoFromRegistry.
  310. //************************************************************************
  311. VOID Free16BitDriverInfo(LPREGFAXDRVINFO16 lpRegFaxDrvInfo16)
  312. {
  313. if (lpRegFaxDrvInfo16) {
  314. if (lpRegFaxDrvInfo16->lpDeviceName) {
  315. LocalFree(lpRegFaxDrvInfo16->lpDeviceName);
  316. }
  317. if (lpRegFaxDrvInfo16->lpDriverName) {
  318. LocalFree(lpRegFaxDrvInfo16->lpDriverName);
  319. }
  320. if (lpRegFaxDrvInfo16->lpPortName) {
  321. LocalFree(lpRegFaxDrvInfo16->lpPortName);
  322. }
  323. LocalFree(lpRegFaxDrvInfo16);
  324. return;
  325. }
  326. }
  327. //***************************************************************************
  328. // InterProcCommHandler - Handles inter-process communication between
  329. // WOWFAXUI-WOW32 and WOWFAX-WOW32.
  330. //***************************************************************************
  331. BOOL InterProcCommHandler(LPFAXDEV lpdev, UINT iAction)
  332. {
  333. LPWOWFAXINFO lpT = lpdev->lpMap;
  334. HANDLE hMap = 0;
  335. WNDPROC wndproc;
  336. MSG msg;
  337. switch (iAction)
  338. {
  339. case DRVFAX_SETMAPDATA:
  340. if (lpdev->lpMap) {
  341. // init map struct
  342. lpdev->lpMap->status = FALSE;
  343. lpdev->lpMap->retvalue = (DWORD)-1;
  344. lpdev->hwnd = FindWowFaxWindow();
  345. lpdev->lpMap->hwnd = lpdev->hwnd;
  346. lpdev->lpMap->msg = 0;
  347. lpdev->lpMap->hdc = (WPARAM)lpdev->idMap;
  348. (DWORD)lpdev->lpMap->lpinfo16 = lpdev->lpinfo16;
  349. }
  350. break;
  351. case DRVFAX_SENDTOWOW:
  352. if (lpdev->lpMap->hwnd) {
  353. SendMessage(lpdev->lpMap->hwnd, lpdev->lpMap->msg, (WPARAM)lpdev->idMap, 0);
  354. }
  355. else {
  356. LOGDEBUG(0, (L"WOWFAXUI!InterProcCommHandler, No hwnd to send to.\n"));
  357. }
  358. break;
  359. case DRVFAX_CALLWOW:
  360. if (lpdev->lpMap->hwnd) {
  361. wndproc = (WNDPROC) GetWindowLongA(lpdev->lpMap->hwnd, GWL_WNDPROC);
  362. CallWindowProc(wndproc, lpdev->lpMap->hwnd, lpdev->lpMap->msg, (WPARAM)lpdev->idMap, 0);
  363. }
  364. else {
  365. LOGDEBUG(0, (L"WOWFAXUI!InterProcCommHandler, No hwnd to call to.\n"));
  366. }
  367. break;
  368. case DRVFAX_SENDNOTIFYWOW:
  369. if (lpdev->lpMap->hwnd) {
  370. SendNotifyMessage(lpdev->lpMap->hwnd, lpdev->lpMap->msg, (WPARAM)lpdev->idMap, 0);
  371. // To simulate app-modal dialog, pass message's to this threads
  372. // windows to DefWndProc, until 16-bit fax driver UI is dismissed.
  373. while (!lpdev->lpMap->status) {
  374. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  375. // EasyFax ver2.0 & MyTalk ver 2.0
  376. // Also Procomm+ 3 cover sheets. Bug #305665
  377. if ((msg.message == WM_PAINT) ||
  378. (msg.message >= WM_USER) ||
  379. ((msg.message >= WM_DDE_FIRST) &&
  380. (msg.message <= WM_DDE_LAST) )) {
  381. DispatchMessage(&msg);
  382. }
  383. else {
  384. DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
  385. }
  386. }
  387. }
  388. }
  389. break;
  390. case DRVFAX_CREATEMAP:
  391. case DRVFAX_DESTROYMAP:
  392. if (lpdev->lpMap) {
  393. // destroys the current map - for both iActions
  394. UnmapViewOfFile(lpdev->lpMap);
  395. CloseHandle(lpdev->hMap);
  396. lpdev->lpMap = 0;
  397. lpdev->hMap = 0;
  398. lpT = 0;
  399. }
  400. if (iAction == DRVFAX_CREATEMAP) {
  401. // GetFaxDataMapName is WOWFAX_INC_COMMON_CODE in wowfax.h.
  402. GetFaxDataMapName((DWORD)lpdev->idMap, lpdev->szMap);
  403. hMap = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE,
  404. 0, lpdev->cbMapLow, lpdev->szMap);
  405. if (hMap) {
  406. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  407. CloseHandle(hMap);
  408. }
  409. else {
  410. lpT = (LPWOWFAXINFO)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
  411. if (lpT) {
  412. lpdev->hMap = hMap;
  413. lpdev->lpMap = lpT;
  414. }
  415. else {
  416. LOGDEBUG(0, (L"WOWFAXUI!InterProcCommHandler, MapViewOfFile failed, LastError = %ld\n", GetLastError()));
  417. CloseHandle(hMap);
  418. }
  419. }
  420. }
  421. else {
  422. LOGDEBUG(0, (L"WOWFAXUI!InterProcCommHandler, CreateFileMapping failed, LastError = %ld\n", GetLastError()));
  423. }
  424. }
  425. break;
  426. } //switch
  427. return((BOOL)lpT);
  428. }
  429. //************************************************************************
  430. // InSetupMode: Checks if this process is running during NT setup.
  431. //
  432. // return:
  433. // TRUE if in NT setup
  434. // FALSE otherwise
  435. //************************************************************************
  436. BOOL InSetupMode(void)
  437. {
  438. DWORD SetupMode = FALSE;
  439. LONG results;
  440. DWORD Type, Size = sizeof(DWORD);
  441. HKEY Key;
  442. results = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"System\\Setup", &Key );
  443. if (results != ERROR_SUCCESS) return FALSE;
  444. results = RegQueryValueExW(Key, L"SystemSetupInProgress",
  445. NULL, &Type, (PBYTE)&SetupMode, &Size);
  446. RegCloseKey(Key);
  447. return (!(SetupMode == 0));
  448. }