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.

1568 lines
59 KiB

  1. //****************************************************************************
  2. // WOW32 fax support.
  3. //
  4. // History:
  5. // 02-jan-95 nandurir created.
  6. // 01-feb-95 reedb Clean-up, support printer install and bug fixes.
  7. //
  8. //****************************************************************************
  9. //****************************************************************************
  10. // This expalins how all this works (sort of) using WinFax as example.
  11. // Install:
  12. // 1. App calls WriteProfileString("devices","WINFAX","WINFAX,Com1:")
  13. // to register a "printer" in Win.ini a-la Win3.1
  14. // 2. Our thunks of WritexxxProfileString() look for the "devices" string
  15. // and pass the call to IsFaxPrinterWriteProfileString(lpszSection,lpszKey,
  16. // lpszString).
  17. // 3. If lpszKey ("WINFAX" in this case) is in our supported fax drivers list
  18. // (See Reg\SW\MS\WinNT\CurrentVersion\WOW\WOWFax\SupportedFaxDrivers)
  19. // (by call to IsFaxPrinterSupportedDevice()), we call InstallWowFaxPrinter
  20. // to add the printer the NT way -- via AddPrinter().
  21. // 4. To set up the call to AddPrinter, we copy WOWFAX.DLL and WOWFAXUI.DLL to
  22. // the print spooler driver directory (\NT\system32\spool\drivers\w32x86\2)
  23. // 5. We next call AddPrinterDriver to register the wowfax driver.
  24. // 6. We then call wow32!DoAddPrinterStuff which launches a new thread,
  25. // wow32!AddPrinterThread, which calls winspool.drv!AddPrinter() for us. The
  26. // PrinterInfo.pPrinterName = the 16-bit fax driver name,"WINFAX" in this
  27. // case. WinSpool.drv then does a RPC call into the spooler.
  28. // 7. During the AddPrinter() call, the spooler calls back into the driver to
  29. // get driver specific info. These callbacks are handled by our WOWFAX
  30. // driver in the spooler's process. They essentially callback into WOW
  31. // via wow32!WOWFaxWndProc().
  32. // 8. WOWFaxWndProc() passes the callback onto WOW32FaxHandler, which calls
  33. // back to wowexec!FaxWndProc().
  34. // 9. FaxWndProc then calls the 16-bit LoadLibrary() to open the 16-bit fax
  35. // driver (WinFax.drv in this case).
  36. // 10. The messages sent to FaxWndProc tell it which exported function it needs
  37. // call in the 16-bit driver on behalf of the spooler.
  38. // 11. Any info the spooler wants to pass to the 16-bit driver or get from it
  39. // essentially goes through the mechanism in steps 7 - 10.
  40. // Now you know (sort of).
  41. //****************************************************************************
  42. //
  43. // Notes on what allows us to support a 16-bit fax driver:
  44. // Essentially we have to know in advance which API's an app will call in the
  45. // driver so we can handle the thunks. It turns out that fax drivers only
  46. // need to export a small essential list of API's:
  47. // Control, Disable, Enable, BitBlt, ExtDeviceMode, DeviceCapabilities
  48. // (see mvdm\inc\wowfax.h\_WOWFAXINFO16 struct (all the PASCAL declarations)
  49. // and mvdm\wow16\test\shell\wowexfax.c\FaxWndProc() )
  50. // The list is way too big to support 16-bit printer & display drivers.
  51. // If a 16-bit fax driver exports these API's there's a pretty good chance
  52. // we can support it in WOW. Other issues to look into: the dlgproc's the
  53. // driver export's, any obsolete Win 3.0 API's that the NT spooler won't know
  54. // how to call.
  55. //
  56. //****************************************************************************
  57. #include "precomp.h"
  58. #pragma hdrstop
  59. #define WOWFAX_INC_COMMON_CODE
  60. #include "wowgdip.h"
  61. #define DEFINE_DDRV_DEBUG_STRINGS
  62. #include "wowfax.h"
  63. #include "winddi.h"
  64. #include "winspool.h"
  65. MODNAME(wowfax.c);
  66. typedef struct _WOWADDPRINTER {
  67. LPVOID pPrinterStuff;
  68. INT iCode;
  69. BOOL bRet;
  70. } WOWADDPRINTER, *PWOWADDPRINTER;
  71. //****************************************************************************
  72. // globals -
  73. //
  74. //****************************************************************************
  75. DWORD DeviceCapsHandler(LPWOWFAXINFO lpfaxinfo);
  76. DWORD ExtDevModeHandler(LPWOWFAXINFO lpfaxinfo);
  77. BOOL ConvertDevMode(PDEVMODE16 lpdm16, LPDEVMODEW lpdmW, BOOL fTo16);
  78. BOOL ConvertGdiInfo(LPGDIINFO16 lpginfo16, PGDIINFO lpginfo, BOOL fTo16);
  79. extern HANDLE hmodWOW32;
  80. LPWOWFAXINFO glpfaxinfoCur = 0;
  81. WOWFAXINFO gfaxinfo;
  82. UINT uNumSupFaxDrv;
  83. LPSTR *SupFaxDrv;
  84. //****************************************************************************
  85. // SortedInsert - Alpha sort.
  86. //****************************************************************************
  87. VOID SortedInsert(LPSTR lpElement, LPSTR *alpList)
  88. {
  89. LPSTR lpTmp, lpSwap;
  90. while (*alpList) {
  91. if (WOW32_stricmp(lpElement, *alpList) < 0) {
  92. break;
  93. }
  94. alpList++;
  95. }
  96. lpTmp = *alpList;
  97. *alpList++ = lpElement;
  98. while (lpTmp) {
  99. // SWAP(*alpList, lpTmp);
  100. lpSwap = *alpList; *alpList = lpTmp; lpTmp = lpSwap;
  101. alpList++;
  102. }
  103. }
  104. //****************************************************************************
  105. // BuildStrList - Find the starting point of strings in a list (lpList) of
  106. // NULL terminated strings which is double NULL terminated.
  107. // If a non-NULL alpList parameter is passed, it will be
  108. // filled with an array of pointers to the starting point
  109. // of each string in the list. The number of strings in the
  110. // list is always returned.
  111. //****************************************************************************
  112. UINT BuildStrList(LPSTR lpList, LPSTR *alpList)
  113. {
  114. LPSTR lp;
  115. TCHAR cLastChar = 1;
  116. UINT uCount = 0;
  117. lp = lpList;
  118. while ((cLastChar) || (*lp)) {
  119. if ((*lp == 0) && (lp != lpList)) {
  120. uCount++;
  121. }
  122. if ((lpList == lp) || (cLastChar == 0)) {
  123. if ((*lp) && (alpList)) {
  124. SortedInsert(lp, alpList);
  125. }
  126. }
  127. cLastChar = *lp++;
  128. }
  129. return uCount;
  130. }
  131. //****************************************************************************
  132. // GetSupportedFaxDrivers - Read in the SupFaxDrv name list from the
  133. // registry. This list is used to determine if we will
  134. // install a 16-bit fax printer driver during
  135. // WriteProfileString and WritePrivateProfileString.
  136. //****************************************************************************
  137. LPSTR *GetSupportedFaxDrivers(UINT *uCount)
  138. {
  139. HKEY hKey = 0;
  140. DWORD dwType;
  141. DWORD cbBufSize=0;
  142. LPSTR lpSupFaxDrvBuf;
  143. LPSTR *alpSupFaxDrvList = NULL;
  144. *uCount = 0;
  145. // Open the registry key.
  146. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  147. "Software\\Microsoft\\Windows NT\\CurrentVersion\\WOW\\WowFax\\SupportedFaxDrivers",
  148. 0, KEY_READ, &hKey ) != ERROR_SUCCESS) {
  149. goto GSFD_error;
  150. }
  151. // Query value for size of buffer and allocate.
  152. if (RegQueryValueEx(hKey, "DriverNames", 0, &dwType, NULL, &cbBufSize) != ERROR_SUCCESS) {
  153. goto GSFD_error;
  154. }
  155. if ((dwType != REG_MULTI_SZ) ||
  156. ((lpSupFaxDrvBuf = (LPSTR) malloc_w(cbBufSize)) == NULL)) {
  157. goto GSFD_error;
  158. }
  159. if (RegQueryValueEx(hKey, "DriverNames", 0, &dwType, lpSupFaxDrvBuf, &cbBufSize) != ERROR_SUCCESS) {
  160. goto GSFD_error;
  161. }
  162. // Get the number of elements in the list
  163. if (*uCount = BuildStrList(lpSupFaxDrvBuf, NULL)) {
  164. // Build an array of pointers to the start of the strings in the list.
  165. alpSupFaxDrvList = (LPSTR *) malloc_w(*uCount * sizeof(LPSTR));
  166. if (alpSupFaxDrvList) {
  167. // Fill the array with string starting points.
  168. RtlZeroMemory(alpSupFaxDrvList, *uCount * sizeof(LPSTR));
  169. BuildStrList(lpSupFaxDrvBuf, alpSupFaxDrvList);
  170. }
  171. else {
  172. goto GSFD_error;
  173. }
  174. }
  175. goto GSFD_exit;
  176. GSFD_error:
  177. LOGDEBUG(0,("WOW32!GetSupportedFaxDrivers failed!\n"));
  178. GSFD_exit:
  179. if (hKey) {
  180. RegCloseKey(hKey);
  181. }
  182. return alpSupFaxDrvList;
  183. }
  184. //****************************************************************************
  185. // WowFaxWndProc - This is the 32-bit WndProc which will SubClass the 16-bit
  186. // FaxWndProc in WOWEXEC.EXE. It's main function is to
  187. // convert 32-bit data passed from the WOW 32-bit generic
  188. // fax driver to 16-bit data to be used by the various 16-bit
  189. // fax printer drivers.
  190. //****************************************************************************
  191. LONG WowFaxWndProc(HWND hwnd, UINT uMsg, UINT uParam, LONG lParam)
  192. {
  193. TCHAR lpPath[MAX_PATH];
  194. HANDLE hMap;
  195. if ((uMsg >= WM_DDRV_FIRST) && (uMsg <= WM_DDRV_LAST)) {
  196. //
  197. // WM_DDRV_* message: uParam = idMap
  198. // lParam = unused.
  199. //
  200. // The corresponding data is obtained from the shared memory.
  201. //
  202. GetFaxDataMapName(uParam, lpPath);
  203. hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, lpPath);
  204. if (hMap) {
  205. LPWOWFAXINFO lpT;
  206. if (lpT = (LPWOWFAXINFO)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0)) {
  207. WOW32FaxHandler(lpT->msg, (LPSTR)lpT);
  208. // Set the status to TRUE indicating that the message
  209. // has been 'processed' by WOW. This doesnot indicate
  210. // the success or the failure of the actual processing
  211. // of the message.
  212. lpT->status = TRUE;
  213. UnmapViewOfFile(lpT);
  214. CloseHandle(hMap);
  215. return(TRUE);
  216. }
  217. CloseHandle(hMap);
  218. }
  219. LOGDEBUG(0,("WowFaxWndProc failed to setup shared data mapping!\n"));
  220. // WOW32ASSERT(FALSE); // turn this off - Procomm tries to install
  221. // this many times.
  222. }
  223. else {
  224. // Not a WM_DDRV_* message. Pass it on to the original proc.
  225. return CallWindowProc(gfaxinfo.proc16, hwnd, uMsg, uParam, lParam);
  226. }
  227. return(TRUE);
  228. }
  229. //**************************************************************************
  230. // WOW32FaxHandler -
  231. //
  232. // Handles various WowFax related operations.
  233. //
  234. //**************************************************************************
  235. ULONG WOW32FaxHandler(UINT iFun, LPSTR lpIn)
  236. {
  237. LPWOWFAXINFO lpT = (LPWOWFAXINFO)lpIn;
  238. LPWOWFAXINFO16 lpT16;
  239. HWND hwnd = gfaxinfo.hwnd;
  240. LPBYTE lpData;
  241. VPVOID vp;
  242. #ifdef DEBUG
  243. int DebugStringIndex = iFun - (WM_USER+0x100+1);
  244. if ((DebugStringIndex >= WM_DDRV_FIRST) && (DebugStringIndex <= WM_DDRV_LAST) ) {
  245. LOGDEBUG(0,("WOW32FaxHandler, %s, 0x%lX\n", (LPSTR)szWmDdrvDebugStrings[DebugStringIndex], (LPSTR) lpIn));
  246. }
  247. #endif
  248. switch (iFun) {
  249. case WM_DDRV_SUBCLASS:
  250. //
  251. // Subclass the window - This is so that we get a chance to
  252. // transform the 32bit data to 16bit data and vice versa. A
  253. // NULL HWND, passed in lpIn, indicates don't subclass.
  254. //
  255. if (gfaxinfo.hwnd = (HWND)lpIn) {
  256. gfaxinfo.proc16 = (WNDPROC)SetWindowLong((HWND)lpIn,
  257. GWL_WNDPROC, (DWORD)WowFaxWndProc);
  258. gfaxinfo.tid = GetWindowThreadProcessId((HWND)lpIn, NULL);
  259. }
  260. WOW32ASSERT(sizeof(DEVMODE16) + 4 == sizeof(DEVMODE31));
  261. //
  262. // Read in the SupFaxDrv name list from the registry.
  263. //
  264. SupFaxDrv = GetSupportedFaxDrivers(&uNumSupFaxDrv);
  265. break;
  266. case WM_DDRV_ENABLE:
  267. // Enable the driver:
  268. // . first intialize the 16bit faxinfo datastruct
  269. // . then inform the driver (dll name) to be loaded
  270. //
  271. // format of ddrv_message:
  272. // wParam = hdc (just a unique id)
  273. // lparam = 16bit faxinfo struct with relevant data
  274. // Must call 'callwindowproc' not 'sendmessage' because
  275. // WowFaxWndProc is a subclass of the 16-bit FaxWndProc.
  276. //
  277. WOW32ASSERT(lpT->lpinfo16 == (LPSTR)NULL);
  278. lpT->lpinfo16 = (LPSTR)CallWindowProc( gfaxinfo.proc16,
  279. hwnd, WM_DDRV_INITFAXINFO16, lpT->hdc, (LPARAM)0);
  280. if (lpT->lpinfo16) {
  281. vp = malloc16(lpT->cData);
  282. GETVDMPTR(vp, lpT->cData, lpData);
  283. if (lpData == 0) {
  284. break;
  285. }
  286. GETVDMPTR(lpT->lpinfo16, sizeof(WOWFAXINFO16), lpT16);
  287. if (lpT16) {
  288. if (lstrlenW(lpT->szDeviceName) < sizeof(lpT16->szDeviceName)) {
  289. WideCharToMultiByte(CP_ACP, 0,
  290. lpT->szDeviceName,
  291. lstrlenW(lpT->szDeviceName) + 1,
  292. lpT16->szDeviceName,
  293. sizeof(lpT16->szDeviceName),
  294. NULL, NULL);
  295. lpT16->lpDriverName = lpT->lpDriverName;
  296. if (lpT->lpDriverName) {
  297. lpT16->lpDriverName = (LPBYTE)vp + (DWORD)lpT->lpDriverName;
  298. WideCharToMultiByte(CP_ACP, 0,
  299. (PWSTR)((LPSTR)lpT + (DWORD)lpT->lpDriverName),
  300. lstrlenW((LPWSTR)((LPSTR)lpT + (DWORD)lpT->lpDriverName)) + 1,
  301. lpData + (DWORD)lpT->lpDriverName,
  302. lstrlenW((LPWSTR)((LPSTR)lpT + (DWORD)lpT->lpDriverName)) + 1,
  303. NULL, NULL);
  304. }
  305. lpT16->lpPortName = lpT->lpPortName;
  306. if (lpT->lpPortName) {
  307. lpT16->lpPortName = (LPBYTE)vp + (DWORD)lpT->lpPortName;
  308. WideCharToMultiByte(CP_ACP, 0,
  309. (PWSTR)((LPSTR)lpT + (DWORD)lpT->lpPortName),
  310. lstrlenW((LPWSTR)((LPSTR)lpT + (DWORD)lpT->lpPortName)) + 1,
  311. lpData + (DWORD)lpT->lpPortName,
  312. lstrlenW((LPWSTR)((LPSTR)lpT + (DWORD)lpT->lpPortName)) + 1,
  313. NULL, NULL);
  314. }
  315. lpT16->lpIn = lpT->lpIn;
  316. if (lpT->lpIn) {
  317. lpT16->lpIn = (LPBYTE)vp + (DWORD)lpT->lpIn;
  318. ConvertDevMode((PDEVMODE16)(lpData + (DWORD)lpT->lpIn),
  319. (LPDEVMODEW)((LPSTR)lpT + (DWORD)lpT->lpIn), TRUE);
  320. }
  321. WOW32ASSERT((sizeof(GDIINFO16) + sizeof(POINT16)) <= sizeof(GDIINFO));
  322. lpT16->lpOut = (LPBYTE)vp + (DWORD)lpT->lpOut;
  323. FREEVDMPTR(lpData);
  324. FREEVDMPTR(lpT16);
  325. lpT->retvalue = CallWindowProc( gfaxinfo.proc16,
  326. hwnd, lpT->msg, lpT->hdc, (LPARAM)lpT->lpinfo16);
  327. if (lpT->retvalue) {
  328. GETVDMPTR(vp, lpT->cData, lpData);
  329. ConvertGdiInfo((LPGDIINFO16)(lpData + (DWORD)lpT->lpOut),
  330. (PGDIINFO)((LPSTR)lpT + (DWORD)lpT->lpOut), FALSE);
  331. }
  332. }
  333. }
  334. free16(vp);
  335. }
  336. break;
  337. case WM_DDRV_ESCAPE:
  338. GETVDMPTR(lpT->lpinfo16, sizeof(WOWFAXINFO16), lpT16);
  339. if (lpT16) {
  340. lpT16->wCmd = lpT->wCmd;
  341. }
  342. FREEVDMPTR(lpT16);
  343. lpT->retvalue = CallWindowProc( gfaxinfo.proc16,
  344. hwnd, lpT->msg, lpT->hdc, (LPARAM)lpT->lpinfo16);
  345. break;
  346. case WM_DDRV_PRINTPAGE:
  347. //
  348. // set the global variable. When the 16bit driver calls DMBitBlt we
  349. // get the bitmap info from here. Since WOW is single threaded we
  350. // won't receive another printpage msg before we return from here.
  351. //
  352. // All pointers in the faxinfo structure are actually
  353. // 'offsets from the start of the mapfile' to relevant data.
  354. //
  355. glpfaxinfoCur = lpT;
  356. lpT->lpbits = (LPBYTE)lpT + (DWORD)lpT->lpbits;
  357. // fall through;
  358. case WM_DDRV_STARTDOC:
  359. // WowFax (EasyFax Ver2.0) support...
  360. GETVDMPTR(lpT->lpinfo16, sizeof(WOWFAXINFO16), lpT16);
  361. if (lpT16) {
  362. WideCharToMultiByte(CP_ACP, 0,
  363. lpT->szDocName,
  364. lstrlenW(lpT->szDocName) + 1,
  365. lpT16->szDocName,
  366. sizeof(lpT16->szDocName),
  367. NULL, NULL);
  368. }
  369. lpT->retvalue = CallWindowProc( gfaxinfo.proc16,
  370. hwnd, lpT->msg, lpT->hdc, (LPARAM)lpT->lpinfo16);
  371. break;
  372. case WM_DDRV_ENDDOC:
  373. lpT->retvalue = CallWindowProc( gfaxinfo.proc16,
  374. hwnd, lpT->msg, lpT->hdc, (LPARAM)lpT->lpinfo16);
  375. break;
  376. case WM_DDRV_DISABLE:
  377. CallWindowProc( gfaxinfo.proc16,
  378. hwnd, lpT->msg, lpT->hdc, (LPARAM)lpT->lpinfo16);
  379. lpT->retvalue = TRUE;
  380. break;
  381. case WM_DDRV_EXTDMODE:
  382. case WM_DDRV_DEVCAPS:
  383. WOW32ASSERT(lpT->lpinfo16 == (LPSTR)NULL);
  384. lpT->lpinfo16 = (LPSTR)CallWindowProc( gfaxinfo.proc16,
  385. hwnd, WM_DDRV_INITFAXINFO16, lpT->hdc, (LPARAM)0);
  386. if (lpT->lpinfo16) {
  387. vp = malloc16(lpT->cData);
  388. GETVDMPTR(vp, lpT->cData, lpData);
  389. if (lpData == 0) {
  390. break;
  391. }
  392. GETVDMPTR(lpT->lpinfo16, sizeof(WOWFAXINFO16), lpT16);
  393. if (lpT16) {
  394. if (lstrlenW(lpT->szDeviceName) < sizeof(lpT16->szDeviceName)) {
  395. WideCharToMultiByte(CP_ACP, 0,
  396. lpT->szDeviceName,
  397. lstrlenW(lpT->szDeviceName) + 1,
  398. lpT16->szDeviceName,
  399. sizeof(lpT16->szDeviceName),
  400. NULL, NULL);
  401. lpT16->lpDriverName = lpT->lpDriverName;
  402. if (lpT->lpDriverName) {
  403. lpT16->lpDriverName = (LPBYTE)vp + (DWORD)lpT->lpDriverName;
  404. WideCharToMultiByte(CP_ACP, 0,
  405. (PWSTR)((LPSTR)lpT + (DWORD)lpT->lpDriverName),
  406. lstrlenW((LPWSTR)((LPSTR)lpT + (DWORD)lpT->lpDriverName)) + 1,
  407. lpData + (DWORD)lpT->lpDriverName,
  408. lstrlenW((LPWSTR)((LPSTR)lpT + (DWORD)lpT->lpDriverName)) + 1,
  409. NULL, NULL);
  410. }
  411. FREEVDMPTR(lpData);
  412. FREEVDMPTR(lpT16);
  413. lpT->retvalue = CallWindowProc( gfaxinfo.proc16,
  414. hwnd, WM_DDRV_LOAD, lpT->hdc, (LPARAM)lpT->lpinfo16);
  415. if (lpT->retvalue) {
  416. lpT->retvalue = (iFun == WM_DDRV_DEVCAPS) ? DeviceCapsHandler(lpT) :
  417. ExtDevModeHandler(lpT) ;
  418. }
  419. CallWindowProc( gfaxinfo.proc16,
  420. hwnd, WM_DDRV_UNLOAD, lpT->hdc, (LPARAM)lpT->lpinfo16);
  421. }
  422. }
  423. free16(vp);
  424. }
  425. break;
  426. }
  427. return TRUE;
  428. }
  429. //**************************************************************************
  430. // gDC_CopySize -
  431. //
  432. // Indicates the size of a list item in bytes for use during
  433. // the DeviceCapsHandler thunk. A zero entry indicates that an
  434. // allocate and copy is not needed for the query.
  435. //
  436. //**************************************************************************
  437. BYTE gDC_ListItemSize[DC_COPIES + 1] = {
  438. 0,
  439. 0, // DC_FIELDS 1
  440. sizeof(WORD), // DC_PAPERS 2
  441. sizeof(POINT), // DC_PAPERSIZE 3
  442. sizeof(POINT), // DC_MINEXTENT 4
  443. sizeof(POINT), // DC_MAXEXTENT 5
  444. sizeof(WORD), // DC_BINS 6
  445. 0, // DC_DUPLEX 7
  446. 0, // DC_SIZE 8
  447. 0, // DC_EXTRA 9
  448. 0, // DC_VERSION 10
  449. 0, // DC_DRIVER 11
  450. 24, // DC_BINNAMES 12 //ANSI
  451. sizeof(LONG) * 2, // DC_ENUMRESOLUTIONS 13
  452. 64, // DC_FILEDEPENDENCIES 14 //ANSI
  453. 0, // DC_TRUETYPE 15
  454. 64, // DC_PAPERNAMES 16 //ANSI
  455. 0, // DC_ORIENTATION 17
  456. 0 // DC_COPIES 18
  457. };
  458. //**************************************************************************
  459. // DeviceCapsHandler -
  460. //
  461. // Makes a single call down to the 16-bit printer driver for queries
  462. // which don't need to allocate and copy. For queries which do, two
  463. // calls to the 16-bit printer driver are made. One to get the number
  464. // of items, and a second to get the actual data.
  465. //
  466. //**************************************************************************
  467. DWORD DeviceCapsHandler(LPWOWFAXINFO lpfaxinfo)
  468. {
  469. LPWOWFAXINFO16 lpWFI16;
  470. LPSTR lpSrc;
  471. LPBYTE lpDest;
  472. INT i;
  473. DWORD cbData16; // Size of data items.
  474. UINT cbUni;
  475. LOGDEBUG(0,("DeviceCapsHandler, lpfaxinfo: %X, wCmd: %X\n", lpfaxinfo, lpfaxinfo->wCmd));
  476. GETVDMPTR(lpfaxinfo->lpinfo16, sizeof(WOWFAXINFO16), lpWFI16);
  477. // Get the number of data items with a call to the 16-bit printer driver.
  478. lpWFI16->lpDriverName = 0;
  479. lpWFI16->lpPortName = 0;
  480. lpWFI16->wCmd = lpfaxinfo->wCmd;
  481. lpWFI16->cData = 0;
  482. lpWFI16->lpOut = 0;
  483. lpfaxinfo->cData = 0;
  484. lpfaxinfo->retvalue = CallWindowProc(gfaxinfo.proc16, gfaxinfo.hwnd,
  485. lpfaxinfo->msg, lpfaxinfo->hdc,
  486. (LPARAM)lpfaxinfo->lpinfo16);
  487. cbData16 = gDC_ListItemSize[lpfaxinfo->wCmd];
  488. if (lpfaxinfo->lpOut && cbData16 && lpfaxinfo->retvalue) {
  489. // We need to allocate and copy for this query
  490. lpWFI16->cData = cbData16 * lpfaxinfo->retvalue;
  491. // assert the size of output buffer - and set it the actual data size
  492. switch (lpfaxinfo->wCmd) {
  493. case DC_BINNAMES:
  494. case DC_PAPERNAMES:
  495. // These fields need extra room for ANSI to UNICODE conversion.
  496. WOW32ASSERT((lpfaxinfo->cData - (DWORD)lpfaxinfo->lpOut) >= lpWFI16->cData * sizeof(WCHAR));
  497. lpfaxinfo->cData = lpWFI16->cData * sizeof(WCHAR);
  498. break;
  499. default:
  500. WOW32ASSERT((lpfaxinfo->cData - (DWORD)lpfaxinfo->lpOut) >= lpWFI16->cData);
  501. lpfaxinfo->cData = lpWFI16->cData;
  502. break;
  503. }
  504. if ((lpWFI16->lpOut = (LPSTR)malloc16(lpWFI16->cData)) == NULL) {
  505. lpfaxinfo->retvalue = 0;
  506. goto LeaveDeviceCapsHandler;
  507. }
  508. // Get the list data with a call to the 16-bit printer driver.
  509. lpfaxinfo->retvalue = CallWindowProc(gfaxinfo.proc16, gfaxinfo.hwnd,
  510. lpfaxinfo->msg, lpfaxinfo->hdc,
  511. (LPARAM)lpfaxinfo->lpinfo16);
  512. GETVDMPTR(lpWFI16->lpOut, 0, lpSrc);
  513. lpDest = (LPBYTE)lpfaxinfo + (DWORD)lpfaxinfo->lpOut;
  514. switch (lpfaxinfo->wCmd) {
  515. case DC_BINNAMES:
  516. case DC_PAPERNAMES:
  517. for (i = 0; i < (INT)lpfaxinfo->retvalue; i++) {
  518. RtlMultiByteToUnicodeN((LPWSTR)lpDest,
  519. cbData16 * sizeof(WCHAR),
  520. (PULONG)&cbUni,
  521. (LPBYTE)lpSrc, cbData16);
  522. lpDest += cbData16 * sizeof(WCHAR);
  523. lpSrc += cbData16;
  524. }
  525. break;
  526. default:
  527. #ifdef FE_SB // for buggy fax driver such as CB-FAX Pro (Bother Corp.)
  528. try {
  529. RtlCopyMemory(lpDest, lpSrc, lpWFI16->cData);
  530. } except(EXCEPTION_EXECUTE_HANDLER) {
  531. // What can I do for the exception... ????
  532. // Anyway, we don't want to die.....
  533. #if DBG
  534. LOGDEBUG(0,("Exception during copying some data\n"));
  535. #endif
  536. }
  537. #else // !FE_SB
  538. RtlCopyMemory(lpDest, lpSrc, lpWFI16->cData);
  539. #endif // !FE_SB
  540. break;
  541. }
  542. free16((VPVOID)lpWFI16->lpOut);
  543. FREEVDMPTR(lpSrc);
  544. }
  545. LeaveDeviceCapsHandler:
  546. FREEVDMPTR(lpWFI16);
  547. return lpfaxinfo->retvalue;
  548. }
  549. //**************************************************************************
  550. // ExtDevModeHandler
  551. //
  552. //**************************************************************************
  553. DWORD ExtDevModeHandler(LPWOWFAXINFO lpfaxinfo)
  554. {
  555. LPWOWFAXINFO16 lpT16;
  556. LPSTR lpT;
  557. VPVOID vp;
  558. LOGDEBUG(0,("ExtDevModeHandler\n"));
  559. (LONG)lpfaxinfo->retvalue = -1;
  560. GETVDMPTR(lpfaxinfo->lpinfo16, sizeof(WOWFAXINFO16), lpT16);
  561. if (lpT16) {
  562. // assumption that 16bit data won't be larger than 32bit data.
  563. // this makes life easy in two ways; first we don't need to calculate
  564. // the exact size and secondly the 16bit pointers can be set to same
  565. // relative offsets as input(32 bit) pointers
  566. vp = malloc16(lpfaxinfo->cData);
  567. if (vp) {
  568. GETVDMPTR(vp, lpfaxinfo->cData, lpT);
  569. if (lpT) {
  570. lpT16->wCmd = lpfaxinfo->wCmd;
  571. lpT16->lpOut = (LPSTR)lpfaxinfo->lpOut;
  572. lpT16->lpIn = (LPSTR)lpfaxinfo->lpIn;
  573. lpT16->lpDriverName = (LPBYTE)vp + (DWORD)lpfaxinfo->lpDriverName;
  574. lpT16->lpPortName = (LPBYTE)vp + (DWORD)lpfaxinfo->lpPortName;
  575. WideCharToMultiByte(CP_ACP, 0,
  576. (PWSTR)((LPSTR)lpfaxinfo + (DWORD)lpfaxinfo->lpDriverName),
  577. lstrlenW((LPWSTR)((LPSTR)lpfaxinfo + (DWORD)lpfaxinfo->lpDriverName)) + 1,
  578. lpT + (DWORD)lpfaxinfo->lpDriverName,
  579. lstrlenW((LPWSTR)((LPSTR)lpfaxinfo + (DWORD)lpfaxinfo->lpDriverName)) + 1,
  580. NULL, NULL);
  581. WideCharToMultiByte(CP_ACP, 0,
  582. (PWSTR)((LPSTR)lpfaxinfo + (DWORD)lpfaxinfo->lpPortName),
  583. lstrlenW((LPWSTR)((LPSTR)lpfaxinfo + (DWORD)lpfaxinfo->lpPortName)) + 1,
  584. lpT + (DWORD)lpfaxinfo->lpPortName,
  585. lstrlenW((LPWSTR)((LPSTR)lpfaxinfo + (DWORD)lpfaxinfo->lpPortName)) + 1,
  586. NULL, NULL);
  587. if (lpfaxinfo->lpIn) {
  588. lpT16->lpIn = (LPBYTE)vp + (DWORD)lpfaxinfo->lpIn;
  589. ConvertDevMode((PDEVMODE16)(lpT + (DWORD)lpfaxinfo->lpIn),
  590. (LPDEVMODEW)((LPSTR)lpfaxinfo + (DWORD)lpfaxinfo->lpIn), TRUE);
  591. }
  592. if (lpfaxinfo->lpOut) {
  593. lpT16->lpOut = (LPBYTE)vp + (DWORD)lpfaxinfo->lpOut;
  594. }
  595. lpT16->hwndui = GETHWND16(lpfaxinfo->hwndui);
  596. FREEVDMPTR(lpT);
  597. lpfaxinfo->retvalue = CallWindowProc( gfaxinfo.proc16, gfaxinfo.hwnd,
  598. lpfaxinfo->msg, lpfaxinfo->hdc, (LPARAM)lpfaxinfo->lpinfo16);
  599. if ((lpfaxinfo->wCmd == 0) && (lpfaxinfo->retvalue > 0)) {
  600. // the 16bit driver has returned 16bit struct size. change
  601. // the return value to correspond to the devmodew struct.
  602. //
  603. // since devmode16 (the 3.0 version) is smaller than devmode31
  604. // the retvalue will take careof both win30/win31 devmode
  605. WOW32ASSERT(sizeof(DEVMODE16) < sizeof(DEVMODE31));
  606. lpfaxinfo->retvalue += (sizeof(DEVMODEW) - sizeof(DEVMODE16));
  607. }
  608. GETVDMPTR(vp, lpfaxinfo->cData, lpT);
  609. if ((lpfaxinfo->wCmd & DM_COPY) &&
  610. lpfaxinfo->lpOut && (lpfaxinfo->retvalue == IDOK)) {
  611. ConvertDevMode((PDEVMODE16)(lpT + (DWORD)lpfaxinfo->lpOut),
  612. (LPDEVMODEW)((LPSTR)lpfaxinfo + (DWORD)lpfaxinfo->lpOut), FALSE);
  613. }
  614. }
  615. free16(vp);
  616. }
  617. }
  618. FREEVDMPTR(lpT16);
  619. return lpfaxinfo->retvalue;
  620. }
  621. //***************************************************************************
  622. // ConvertDevMode
  623. //***************************************************************************
  624. BOOL ConvertDevMode(PDEVMODE16 lpdm16, LPDEVMODEW lpdmW, BOOL fTo16)
  625. {
  626. LOGDEBUG(0,("ConvertDevMode\n"));
  627. if (!lpdm16 || !lpdmW)
  628. return TRUE;
  629. if (fTo16) {
  630. RtlZeroMemory(lpdm16, sizeof(DEVMODE16));
  631. WideCharToMultiByte(CP_ACP, 0,
  632. lpdmW->dmDeviceName,
  633. sizeof(lpdmW->dmDeviceName) / sizeof(lpdmW->dmDeviceName[0]),
  634. lpdm16->dmDeviceName,
  635. sizeof(lpdm16->dmDeviceName) / sizeof(lpdm16->dmDeviceName[0]),
  636. NULL, NULL);
  637. lpdm16->dmSpecVersion = lpdmW->dmSpecVersion;
  638. lpdm16->dmDriverVersion = lpdmW->dmDriverVersion;
  639. lpdm16->dmSize = lpdmW->dmSize;
  640. lpdm16->dmDriverExtra = lpdmW->dmDriverExtra;
  641. lpdm16->dmFields = lpdmW->dmFields;
  642. lpdm16->dmOrientation = lpdmW->dmOrientation;
  643. lpdm16->dmPaperSize = lpdmW->dmPaperSize;
  644. lpdm16->dmPaperLength = lpdmW->dmPaperLength;
  645. lpdm16->dmPaperWidth = lpdmW->dmPaperWidth;
  646. lpdm16->dmScale = lpdmW->dmScale;
  647. lpdm16->dmCopies = lpdmW->dmCopies;
  648. lpdm16->dmDefaultSource = lpdmW->dmDefaultSource;
  649. lpdm16->dmPrintQuality = lpdmW->dmPrintQuality;
  650. lpdm16->dmColor = lpdmW->dmColor;
  651. lpdm16->dmDuplex = lpdmW->dmDuplex;
  652. // adjust lpdm16->dmSize (between win30 and win31 version)
  653. lpdm16->dmSize = (lpdm16->dmSpecVersion > 0x300) ? sizeof(DEVMODE31) :
  654. sizeof(DEVMODE16);
  655. if (lpdm16->dmSize >= sizeof(DEVMODE31)) {
  656. ((PDEVMODE31)lpdm16)->dmYResolution = lpdmW->dmYResolution;
  657. ((PDEVMODE31)lpdm16)->dmTTOption = lpdmW->dmTTOption;
  658. }
  659. RtlCopyMemory((LPBYTE)lpdm16 + (DWORD)lpdm16->dmSize, (lpdmW + 1),
  660. lpdmW->dmDriverExtra);
  661. }
  662. else {
  663. // LATER: should specversion be NT version rather than win30 driver version?
  664. MultiByteToWideChar(CP_ACP, 0,
  665. lpdm16->dmDeviceName,
  666. sizeof(lpdm16->dmDeviceName) / sizeof(lpdm16->dmDeviceName[0]),
  667. lpdmW->dmDeviceName,
  668. sizeof(lpdmW->dmDeviceName) / sizeof(lpdmW->dmDeviceName[0]));
  669. lpdmW->dmSpecVersion = lpdm16->dmSpecVersion;
  670. lpdmW->dmDriverVersion = lpdm16->dmDriverVersion;
  671. lpdmW->dmSize = lpdm16->dmSize;
  672. lpdmW->dmDriverExtra = lpdm16->dmDriverExtra;
  673. lpdmW->dmFields = lpdm16->dmFields;
  674. lpdmW->dmOrientation = lpdm16->dmOrientation;
  675. lpdmW->dmPaperSize = lpdm16->dmPaperSize;
  676. lpdmW->dmPaperLength = lpdm16->dmPaperLength;
  677. lpdmW->dmPaperWidth = lpdm16->dmPaperWidth;
  678. lpdmW->dmScale = lpdm16->dmScale;
  679. lpdmW->dmCopies = lpdm16->dmCopies;
  680. lpdmW->dmDefaultSource = lpdm16->dmDefaultSource;
  681. lpdmW->dmPrintQuality = lpdm16->dmPrintQuality;
  682. lpdmW->dmColor = lpdm16->dmColor;
  683. lpdmW->dmDuplex = lpdm16->dmDuplex;
  684. if (lpdm16->dmSize >= sizeof(DEVMODE31)) {
  685. lpdmW->dmYResolution = ((PDEVMODE31)lpdm16)->dmYResolution;
  686. lpdmW->dmTTOption = ((PDEVMODE31)lpdm16)->dmTTOption;
  687. }
  688. // 16bit world doesnot know anything about the fields like
  689. // formname etc.
  690. RtlCopyMemory(lpdmW + 1, (LPBYTE)lpdm16 + lpdm16->dmSize, lpdm16->dmDriverExtra);
  691. // adjust size for 32bit world
  692. lpdmW->dmSize = sizeof(*lpdmW);
  693. }
  694. return TRUE;
  695. }
  696. //**************************************************************************
  697. // ConvertGdiInfo
  698. //
  699. //**************************************************************************
  700. BOOL ConvertGdiInfo(LPGDIINFO16 lpginfo16, PGDIINFO lpginfo, BOOL fTo16)
  701. {
  702. LOGDEBUG(0,("ConvertGdiInfo\n"));
  703. if (!lpginfo16 || !lpginfo)
  704. return FALSE;
  705. if (!fTo16) {
  706. lpginfo->ulTechnology = lpginfo16->dpTechnology;
  707. lpginfo->ulLogPixelsX = lpginfo16->dpLogPixelsX;
  708. lpginfo->ulLogPixelsY = lpginfo16->dpLogPixelsY;
  709. lpginfo->ulDevicePelsDPI = lpginfo->ulLogPixelsX;
  710. lpginfo->ulHorzSize = lpginfo16->dpHorzSize;
  711. lpginfo->ulVertSize = lpginfo16->dpVertSize;
  712. lpginfo->ulHorzRes = lpginfo16->dpHorzRes;
  713. lpginfo->ulVertRes = lpginfo16->dpVertRes;
  714. lpginfo->cBitsPixel = lpginfo16->dpBitsPixel;
  715. lpginfo->cPlanes = lpginfo16->dpPlanes;
  716. lpginfo->ulNumColors = lpginfo16->dpNumColors;
  717. lpginfo->ptlPhysOffset.x = ((PPOINT16)(lpginfo16+1))->x;
  718. lpginfo->ptlPhysOffset.y = ((PPOINT16)(lpginfo16+1))->y;
  719. lpginfo->szlPhysSize.cx = lpginfo->ulHorzRes;
  720. lpginfo->szlPhysSize.cy = lpginfo->ulVertRes;
  721. lpginfo->ulPanningHorzRes = lpginfo->ulHorzRes;
  722. lpginfo->ulPanningVertRes = lpginfo->ulVertRes;
  723. lpginfo->ulAspectX = lpginfo16->dpAspectX;
  724. lpginfo->ulAspectY = lpginfo16->dpAspectY;
  725. lpginfo->ulAspectXY = lpginfo16->dpAspectXY;
  726. //
  727. // RASDD tries to be smart as to whether the x and y DPI are equal or
  728. // not. In the case of 200dpi in the x direction and 100dpi in the
  729. // y direction, you may want to adjust this to 2 for xStyleStep, 1 for
  730. // yStyleStep and dpi/50 for denStyleStep. This basicaly determines
  731. // how long dashes/dots will be when drawing with styled pens.
  732. // Since we just hard code denStyleStep to 3, we get different lines
  733. // at 100dpi vs 200dpi
  734. //
  735. lpginfo->xStyleStep = 1;
  736. lpginfo->yStyleStep = 1;
  737. lpginfo->denStyleStep = 3;
  738. }
  739. return TRUE;
  740. }
  741. //**************************************************************************
  742. // DMBitBlt -
  743. // The 16bit winfax.drv calls this , in response to a device driver
  744. // 'bitblt' call.
  745. //
  746. //**************************************************************************
  747. ULONG FASTCALL WG32DMBitBlt( PVDMFRAME pFrame)
  748. {
  749. register PDMBITBLT16 parg16;
  750. #ifdef DBCS /* wowfax support */
  751. register PDEV_BITMAP16 pbm16;
  752. #else // !DBCS
  753. register PBITMAP16 pbm16;
  754. #endif /* !DBCS */
  755. LPBYTE lpDest, lpSrc;
  756. UINT cBytes;
  757. LPBYTE lpbits, lpbitsEnd;
  758. LOGDEBUG(0,("WG32DMBitBlt\n"));
  759. GETARGPTR(pFrame, sizeof(DMBITBLT16), parg16);
  760. #ifdef DBCS /* wowfax support */
  761. GETVDMPTR(parg16->pbitmapdest, sizeof(DEV_BITMAP16), pbm16);
  762. #else // !DBCS
  763. GETVDMPTR(parg16->pbitmapdest, sizeof(BITMAP16), pbm16);
  764. #endif /* !DBCS */
  765. GETVDMPTR(pbm16->bmBits, 0, lpDest);
  766. WOW32ASSERT(glpfaxinfoCur != NULL);
  767. lpbits = glpfaxinfoCur->lpbits;
  768. lpbitsEnd = (LPBYTE)lpbits + glpfaxinfoCur->bmHeight *
  769. glpfaxinfoCur->bmWidthBytes;
  770. #ifdef DBCS /* wowfax support */
  771. lpSrc = (LPBYTE)lpbits + (parg16->srcx / glpfaxinfoCur->bmPixPerByte) +
  772. (parg16->srcy * glpfaxinfoCur->bmWidthBytes);
  773. if (lpSrc >= lpbits) {
  774. WORD extx,exty,srcx,srcy,desty,destx;
  775. extx = FETCHWORD(parg16->extx);
  776. exty = FETCHWORD(parg16->exty);
  777. srcx = FETCHWORD(parg16->srcx);
  778. srcy = FETCHWORD(parg16->srcy);
  779. destx = FETCHWORD(parg16->destx);
  780. desty = FETCHWORD(parg16->desty);
  781. #if DBG
  782. LOGDEBUG(10,("\n"));
  783. LOGDEBUG(10,("bmType = %d\n",pbm16->bmType));
  784. LOGDEBUG(10,("bmWidth = %d\n",pbm16->bmWidth));
  785. LOGDEBUG(10,("bmHeight = %d\n",pbm16->bmHeight));
  786. LOGDEBUG(10,("bmWidthBytes = %d\n",pbm16->bmWidthBytes));
  787. LOGDEBUG(10,("bmPlanes = %d\n",pbm16->bmPlanes));
  788. LOGDEBUG(10,("bmBitsPixel = %d\n",pbm16->bmBitsPixel));
  789. LOGDEBUG(10,("bmBits = %x\n",pbm16->bmBits));
  790. LOGDEBUG(10,("bmWidthPlances = %d\n",pbm16->bmWidthPlanes));
  791. LOGDEBUG(10,("bmlpPDevice = %x\n",pbm16->bmlpPDevice));
  792. LOGDEBUG(10,("bmSegmentIndex = %d\n",pbm16->bmSegmentIndex));
  793. LOGDEBUG(10,("bmScanSegment = %d\n",pbm16->bmScanSegment));
  794. LOGDEBUG(10,("bmFillBytes = %d\n",pbm16->bmFillBytes));
  795. LOGDEBUG(10,("\n"));
  796. LOGDEBUG(10,("bmWidthBytesSrc= %d\n",glpfaxinfoCur->bmWidthBytes));
  797. LOGDEBUG(10,("\n"));
  798. LOGDEBUG(10,("extx = %d\n",extx));
  799. LOGDEBUG(10,("exty = %d\n",exty));
  800. LOGDEBUG(10,("srcx = %d\n",srcx));
  801. LOGDEBUG(10,("srcy = %d\n",srcy));
  802. LOGDEBUG(10,("destx = %d\n",destx));
  803. LOGDEBUG(10,("desty = %d\n",desty));
  804. LOGDEBUG(10,("\n"));
  805. #endif
  806. if (pbm16->bmSegmentIndex) {
  807. SHORT WriteSegment;
  808. SHORT WriteOffset;
  809. SHORT Segment=0,SegmentMax=0;
  810. LPBYTE DstScan0,SrcScan0;
  811. UINT cBytesInLastSegment;
  812. INT RestLine = (INT) exty;
  813. WriteSegment = desty / pbm16->bmScanSegment;
  814. WriteOffset = desty % pbm16->bmScanSegment;
  815. if (WriteOffset) {
  816. WriteSegment += 1;
  817. }
  818. #if DBG
  819. LOGDEBUG(10,("WriteSegment = %d\n",WriteSegment));
  820. LOGDEBUG(10,("WriteOffset = %d\n",WriteOffset));
  821. LOGDEBUG(10,("\n"));
  822. LOGDEBUG(10,("lpDest = %x\n",lpDest));
  823. LOGDEBUG(10,("\n"));
  824. #endif
  825. SegmentMax = exty / pbm16->bmScanSegment;
  826. if ( exty % pbm16->bmScanSegment) {
  827. SegmentMax += 1;
  828. }
  829. cBytes = glpfaxinfoCur->bmWidthBytes * pbm16->bmScanSegment;
  830. lpDest = lpDest + destx + (WriteSegment * 0x10000L) +
  831. (WriteOffset * pbm16->bmWidthBytes);
  832. #if DBG
  833. LOGDEBUG(10,("SourceBitmap = %x\n",lpSrc));
  834. LOGDEBUG(10,("DestinationBitmap = %x\n",lpDest));
  835. LOGDEBUG(10,("SegmentMax = %d\n",SegmentMax));
  836. LOGDEBUG(10,("\n"));
  837. LOGDEBUG(10,("cBytes = %d\n",cBytes));
  838. LOGDEBUG(10,("\n"));
  839. #endif
  840. if ((DWORD)glpfaxinfoCur->bmWidthBytes == (DWORD)pbm16->bmWidthBytes) {
  841. try {
  842. for( Segment = 1,DstScan0 = lpDest,SrcScan0 = lpSrc;
  843. Segment < SegmentMax;
  844. Segment++,DstScan0 += 0x10000L,
  845. SrcScan0 += cBytes,RestLine -= pbm16->bmScanSegment ) {
  846. #if DBG
  847. LOGDEBUG(10,("%d ",Segment-1));
  848. #endif
  849. RtlCopyMemory(DstScan0,SrcScan0,cBytes);
  850. RtlZeroMemory(DstScan0+cBytes,pbm16->bmFillBytes);
  851. }
  852. #if DBG
  853. LOGDEBUG(10,("%d\n",Segment-1));
  854. #endif
  855. if( RestLine > 0 ) {
  856. cBytesInLastSegment = RestLine * pbm16->bmWidthBytes;
  857. #if DBG
  858. LOGDEBUG(10,("RestLine = %d\n",RestLine));
  859. LOGDEBUG(10,("cBytesInLastSegment = %d\n",cBytes));
  860. #endif
  861. // do for last segment..
  862. RtlCopyMemory(DstScan0,SrcScan0,cBytesInLastSegment);
  863. }
  864. } except(EXCEPTION_EXECUTE_HANDLER) {
  865. #if DBG
  866. LOGDEBUG(10,("Exception during copying image\n"));
  867. #endif
  868. }
  869. } else if ((DWORD)glpfaxinfoCur->bmWidthBytes > (DWORD)pbm16->bmWidthBytes) {
  870. SHORT Line;
  871. UINT cSrcAdvance = glpfaxinfoCur->bmWidthBytes;
  872. UINT cDstAdvance = pbm16->bmWidthBytes;
  873. try {
  874. for( Segment = 1,DstScan0 = lpDest,SrcScan0 = lpSrc;
  875. Segment < SegmentMax;
  876. Segment++,DstScan0 += 0x10000L,
  877. SrcScan0 += cBytes,RestLine -= pbm16->bmScanSegment ) {
  878. LPBYTE DstScanl = DstScan0;
  879. LPBYTE SrcScanl = SrcScan0;
  880. #if DBG
  881. LOGDEBUG(10,("%d ",Segment-1));
  882. #endif
  883. for( Line = 0;
  884. Line < pbm16->bmScanSegment;
  885. Line++,DstScanl += cDstAdvance,SrcScanl += cSrcAdvance ) {
  886. RtlCopyMemory(DstScanl,SrcScanl,cDstAdvance);
  887. }
  888. }
  889. #if DBG
  890. LOGDEBUG(10,("%d\n",Segment-1));
  891. #endif
  892. if( RestLine > 0 ) {
  893. LPBYTE DstScanl = DstScan0;
  894. LPBYTE SrcScanl = SrcScan0;
  895. for( Line = 0;
  896. Line < RestLine;
  897. Line++,DstScanl += cDstAdvance,SrcScanl += cSrcAdvance ) {
  898. RtlCopyMemory(DstScanl,SrcScanl,cDstAdvance);
  899. }
  900. }
  901. } except(EXCEPTION_EXECUTE_HANDLER) {
  902. #if DBG
  903. LOGDEBUG(10,("Exception during copying image\n"));
  904. #endif
  905. }
  906. } else {
  907. WOW32ASSERT(FALSE);
  908. }
  909. } else {
  910. lpDest = lpDest + destx + desty * pbm16->bmWidthBytes;
  911. if ((DWORD)glpfaxinfoCur->bmWidthBytes == (DWORD)pbm16->bmWidthBytes) {
  912. cBytes = parg16->exty * glpfaxinfoCur->bmWidthBytes;
  913. if (cBytes > (UINT)(pbm16->bmHeight * pbm16->bmWidthBytes)) {
  914. cBytes = pbm16->bmHeight * pbm16->bmWidthBytes;
  915. WOW32ASSERT(FALSE);
  916. }
  917. if ((lpSrc + cBytes) <= lpbitsEnd) {
  918. RtlCopyMemory(lpDest, lpSrc, cBytes);
  919. }
  920. } else {
  921. int i;
  922. // we need to transfer bits one partial scanline at a time
  923. WOW32ASSERT((DWORD)pbm16->bmHeight <= (DWORD)glpfaxinfoCur->bmHeight);
  924. WOW32ASSERT((DWORD)parg16->exty <= (DWORD)pbm16->bmHeight);
  925. cBytes = ((DWORD)pbm16->bmWidthBytes < (DWORD)glpfaxinfoCur->bmWidthBytes) ?
  926. pbm16->bmWidthBytes : glpfaxinfoCur->bmWidthBytes;
  927. for (i = 0; i < parg16->exty; i++) {
  928. if ((lpSrc + cBytes) <= lpbitsEnd) {
  929. RtlCopyMemory(lpDest, lpSrc, cBytes);
  930. }
  931. lpDest += pbm16->bmWidthBytes;
  932. lpSrc += glpfaxinfoCur->bmWidthBytes;
  933. }
  934. }
  935. }
  936. }
  937. #else // !DBCS
  938. lpDest = lpDest + parg16->destx + parg16->desty * pbm16->bmWidthBytes;
  939. lpSrc = (LPBYTE)lpbits + (parg16->srcx / glpfaxinfoCur->bmPixPerByte) +
  940. parg16->srcy * glpfaxinfoCur->bmWidthBytes;
  941. if (lpSrc >= lpbits) {
  942. if ((DWORD)glpfaxinfoCur->bmWidthBytes == (DWORD)pbm16->bmWidthBytes) {
  943. cBytes = parg16->exty * glpfaxinfoCur->bmWidthBytes;
  944. if (cBytes > (UINT)(pbm16->bmHeight * pbm16->bmWidthBytes)) {
  945. cBytes = pbm16->bmHeight * pbm16->bmWidthBytes;
  946. WOW32ASSERT(FALSE);
  947. }
  948. if ((lpSrc + cBytes) <= lpbitsEnd) {
  949. RtlCopyMemory(lpDest, lpSrc, cBytes);
  950. }
  951. }
  952. else if ((DWORD)glpfaxinfoCur->bmWidthBytes > (DWORD)pbm16->bmWidthBytes) {
  953. int i;
  954. // we need to transfer bits one partial scanline at a time
  955. WOW32ASSERT((DWORD)pbm16->bmHeight <= (DWORD)glpfaxinfoCur->bmHeight);
  956. WOW32ASSERT((DWORD)parg16->exty <= (DWORD)pbm16->bmHeight);
  957. for (i = 0; i < parg16->exty; i++) {
  958. if ((lpSrc + pbm16->bmWidthBytes) <= lpbitsEnd) {
  959. RtlCopyMemory(lpDest, lpSrc, pbm16->bmWidthBytes);
  960. }
  961. lpDest += pbm16->bmWidthBytes;
  962. lpSrc += glpfaxinfoCur->bmWidthBytes;
  963. }
  964. }
  965. else {
  966. WOW32ASSERT(FALSE);
  967. }
  968. }
  969. #endif /* !DBCS */
  970. return (ULONG)TRUE;
  971. }
  972. PSZ StrDup(PSZ szStr)
  973. {
  974. PSZ pszTmp;
  975. pszTmp = malloc_w(strlen(szStr)+1);
  976. if(pszTmp ) {
  977. return(strcpy(pszTmp, szStr));
  978. }
  979. return NULL;
  980. }
  981. PSZ BuildPath(PSZ szPath, PSZ szFileName)
  982. {
  983. char szTmp[MAX_PATH];
  984. strcpy(szTmp, szPath);
  985. strcat(szTmp, "\\");
  986. strcat(szTmp, szFileName);
  987. return(StrDup(szTmp));
  988. }
  989. //**************************************************************************
  990. // AddPrinterThread -
  991. //
  992. // Worker thread to make the AddPrinter call into the spooler.
  993. //
  994. //**************************************************************************
  995. VOID AddPrinterThread(PWOWADDPRINTER pWowAddPrinter)
  996. {
  997. if ((*spoolerapis[pWowAddPrinter->iCode].lpfn)(NULL, 2,
  998. pWowAddPrinter->pPrinterStuff)) {
  999. pWowAddPrinter->bRet = TRUE;
  1000. }
  1001. else {
  1002. if (GetLastError() == ERROR_PRINTER_ALREADY_EXISTS) {
  1003. pWowAddPrinter->bRet = TRUE;
  1004. }
  1005. else {
  1006. #ifdef DBG
  1007. LOGDEBUG(0,("AddPrinterThread, AddPrinterxxx call failed: 0x%X\n", GetLastError()));
  1008. #endif
  1009. pWowAddPrinter->bRet = FALSE;
  1010. }
  1011. }
  1012. }
  1013. //**************************************************************************
  1014. // DoAddPrinterStuff -
  1015. //
  1016. // Spin a worker thread to make the AddPrinterxxx calls into
  1017. // spooler. This is needed to prevent a deadlock when spooler
  1018. // RPC's to spoolss.
  1019. //
  1020. // This thread added for bug #107426.
  1021. //**************************************************************************
  1022. BOOL DoAddPrinterStuff(LPVOID pPrinterStuff, INT iCode)
  1023. {
  1024. WOWADDPRINTER WowAddPrinter;
  1025. HANDLE hWaitObjects;
  1026. DWORD dwEvent, dwUnused;
  1027. MSG msg;
  1028. // Spin the worker thread.
  1029. WowAddPrinter.pPrinterStuff = pPrinterStuff;
  1030. WowAddPrinter.iCode = iCode;
  1031. WowAddPrinter.bRet = FALSE;
  1032. if (hWaitObjects = CreateThread(NULL, 0,
  1033. (LPTHREAD_START_ROUTINE)AddPrinterThread,
  1034. &WowAddPrinter, 0, &dwUnused)) {
  1035. // Pump messages while we wait for AddPrinterThread to finish.
  1036. for (;;) {
  1037. dwEvent = MsgWaitForMultipleObjects(1,
  1038. &hWaitObjects,
  1039. FALSE,
  1040. INFINITE,
  1041. QS_ALLEVENTS | QS_SENDMESSAGE);
  1042. if (dwEvent == WAIT_OBJECT_0 + 0) {
  1043. // Worker thread done.
  1044. break;
  1045. }
  1046. else {
  1047. // pump messages so the callback into wowexec!FaxWndProc doesn't
  1048. // get hung
  1049. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  1050. TranslateMessage(&msg);
  1051. DispatchMessage(&msg);
  1052. }
  1053. }
  1054. }
  1055. CloseHandle(hWaitObjects);
  1056. }
  1057. else {
  1058. LOGDEBUG(0,
  1059. ("DoAddPrinterStuff, CreateThread on AddPrinterThread failed\n"));
  1060. }
  1061. return WowAddPrinter.bRet;
  1062. }
  1063. //**************************************************************************
  1064. // InstallWowFaxPrinter -
  1065. //
  1066. // Installs the WowFax 32-bit print driver when a 16-bit fax printer
  1067. // installation is detected.
  1068. //
  1069. //**************************************************************************
  1070. BOOL InstallWowFaxPrinter(PSZ szSection, PSZ szKey, PSZ szString)
  1071. {
  1072. CHAR szTmp[MAX_PATH];
  1073. PSZ szSrcPath;
  1074. DWORD dwNeeded;
  1075. DRIVER_INFO_2 DriverInfo;
  1076. PRINTER_INFO_2 PrinterInfo;
  1077. PORT_INFO_1 PortInfo;
  1078. HKEY hKey = 0, hSubKey = 0;
  1079. BOOL bRetVal=FALSE;
  1080. LOGDEBUG(0,("InstallWowFaxPrinter, Section = %s, Key = %s, String = %s\n", szSection, szKey, szString));
  1081. // Write the entry to the registry. We'll keep shadow entries
  1082. // in the registry for the WOW fax applications and drivers to
  1083. // read, since the entries that the spooler writes pertain
  1084. // to winspool, not the 16-bit fax driver.
  1085. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1086. "Software\\Microsoft\\Windows NT\\CurrentVersion\\WOW\\WowFax",
  1087. 0, KEY_WRITE, &hKey ) == ERROR_SUCCESS) {
  1088. if (RegCreateKey(hKey, szSection, &hSubKey) == ERROR_SUCCESS) {
  1089. RegSetValueEx(hSubKey, szKey, 0, REG_SZ, szString, strlen(szString)+1);
  1090. RegCloseKey(hKey);
  1091. RegCloseKey(hSubKey);
  1092. // Dynamically link to spooler API's
  1093. if (!(spoolerapis[WOW_GetPrinterDriverDirectory].lpfn)) {
  1094. if (!LoadLibraryAndGetProcAddresses("WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  1095. LOGDEBUG(0,("InstallWowFaxPrinter, Unable to load WINSPOOL API's\n"));
  1096. return(FALSE);
  1097. }
  1098. }
  1099. // Copy the printer driver files.
  1100. RtlZeroMemory(&DriverInfo, sizeof(DRIVER_INFO_2));
  1101. RtlZeroMemory(&PrinterInfo, sizeof(PRINTER_INFO_2));
  1102. if (!(*spoolerapis[WOW_GetPrinterDriverDirectory].lpfn)(NULL, NULL, 1, szTmp, MAX_PATH, &dwNeeded)) {
  1103. LOGDEBUG(0,("InstallWowFaxPrinter, GetPrinterDriverDirectory failed: 0x%X\n", GetLastError()));
  1104. return(FALSE);
  1105. }
  1106. // This is a dummy. We've no data file, but spooler won't take NULL.
  1107. DriverInfo.pDataFile = BuildPath(szTmp, WOWFAX_DLL_NAME_A);
  1108. if ( !DriverInfo.pDataFile ) {
  1109. goto IWFP_error;
  1110. }
  1111. DriverInfo.pDriverPath = BuildPath(szTmp, WOWFAX_DLL_NAME_A);
  1112. if ( !DriverInfo.pDriverPath ) {
  1113. goto IWFP_error;
  1114. }
  1115. LOGDEBUG(0,("InstallWowFaxPrinter, pDriverPath = %s\n", DriverInfo.pDataFile));
  1116. szSrcPath = BuildPath(pszSystemDirectory, WOWFAX_DLL_NAME_A);
  1117. if ( !szSrcPath ) {
  1118. goto IWFP_error;
  1119. }
  1120. CopyFile(szSrcPath, DriverInfo.pDriverPath, FALSE);
  1121. free_w(szSrcPath);
  1122. DriverInfo.pConfigFile = BuildPath(szTmp, WOWFAXUI_DLL_NAME_A);
  1123. szSrcPath = BuildPath(pszSystemDirectory, WOWFAXUI_DLL_NAME_A);
  1124. if ( !szSrcPath ) {
  1125. goto IWFP_error;
  1126. }
  1127. CopyFile(szSrcPath, DriverInfo.pConfigFile, FALSE);
  1128. free_w(szSrcPath);
  1129. // Install the printer driver.
  1130. DriverInfo.cVersion = 1;
  1131. DriverInfo.pName = "Windows 3.1 Compatible Fax Driver";
  1132. if ((bRetVal = DoAddPrinterStuff((LPVOID)&DriverInfo,
  1133. WOW_AddPrinterDriver)) == FALSE) {
  1134. // if the driver is already installed, it won't hurt to install
  1135. // it a second time. This might be necessary if the user is
  1136. // upgrading from WinFax Lite to WinFax Pro.
  1137. bRetVal = (GetLastError() == ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
  1138. }
  1139. if (bRetVal) {
  1140. // Parse out the printer name.
  1141. RtlZeroMemory(&PrinterInfo, sizeof(PRINTER_INFO_2));
  1142. PrinterInfo.pPrinterName = szKey;
  1143. LOGDEBUG(0,("InstallWowFaxPrinter, pPrinterName = %s\n", PrinterInfo.pPrinterName));
  1144. // Use private API to add a NULL port. Printer guys need to fix
  1145. // redirection to NULL bug.
  1146. RtlZeroMemory(&PortInfo, sizeof(PORT_INFO_1));
  1147. PrinterInfo.pPortName = "NULL";
  1148. PortInfo.pName = PrinterInfo.pPortName;
  1149. // Get "Local Port" string.
  1150. LoadString(hmodWOW32, iszWowFaxLocalPort, szTmp, sizeof szTmp);
  1151. (*spoolerapis[WOW_AddPortEx].lpfn)(NULL, 1, &PortInfo, szTmp);
  1152. // Set the other defaults and install the printer.
  1153. PrinterInfo.pDriverName = "Windows 3.1 Compatible Fax Driver";
  1154. PrinterInfo.pPrintProcessor = "WINPRINT";
  1155. PrinterInfo.pDatatype = "RAW";
  1156. bRetVal = DoAddPrinterStuff((LPVOID)&PrinterInfo,
  1157. WOW_AddPrinter);
  1158. #ifdef DBG
  1159. if (!bRetVal) {
  1160. LOGDEBUG(0,("InstallWowFaxPrinter, AddPrinter failed: 0x%X\n", GetLastError()));
  1161. }
  1162. #endif
  1163. }
  1164. else {
  1165. LOGDEBUG(0,("InstallWowFaxPrinter, AddPrinterDriver failed: 0x%X\n", GetLastError()));
  1166. }
  1167. IWFP_error:
  1168. if ( DriverInfo.pDataFile ) {
  1169. free_w(DriverInfo.pDataFile);
  1170. }
  1171. if ( DriverInfo.pDriverPath ) {
  1172. free_w(DriverInfo.pDriverPath);
  1173. }
  1174. if ( DriverInfo.pConfigFile) {
  1175. free_w(DriverInfo.pConfigFile);
  1176. }
  1177. return(bRetVal);
  1178. }
  1179. else {
  1180. LOGDEBUG(0,("InstallWowFaxPrinter, Unable to create Key: %s\n", szSection));
  1181. }
  1182. }
  1183. else {
  1184. LOGDEBUG(0,("InstallWowFaxPrinter, Unable to open key: HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\WOW\\WowFax\n"));
  1185. }
  1186. if (hKey) {
  1187. RegCloseKey(hKey);
  1188. if (hSubKey) {
  1189. RegCloseKey(hSubKey);
  1190. }
  1191. }
  1192. return(FALSE);
  1193. }
  1194. // Come here if szSection=="devices" or if gbWinFaxHack==TRUE
  1195. BOOL IsFaxPrinterWriteProfileString(PSZ szSection, PSZ szKey, PSZ szString)
  1196. {
  1197. BOOL Result = FALSE;
  1198. // Don't install if trying to clear an entry.
  1199. if (*szString == '\0') {
  1200. goto Done;
  1201. }
  1202. // Trying to install a fax printer?
  1203. LOGDEBUG(0,("IsFaxPrinterWriteProfileString, Section = devices, Key = %s\n", szKey));
  1204. // Is the WinFax Lite hack enabled?
  1205. if(gbWinFaxHack) {
  1206. // if ("WINFAX", "modem", "xxx") we know the WinFax install program
  1207. // has had a chance to copy "WinFax.drv" to the hard drive. So
  1208. // now we can call AddPrinter which can callback into WinFax.drv to
  1209. // its hearts content.
  1210. if(!WOW32_strcmp(szSection, szWINFAX) && !WOW32_stricmp(szKey, szModem)) {
  1211. // Our hack has run its course. We set this before making the call
  1212. // to AddPrinter because it calls back into WinFax.drv which calls
  1213. // WriteProfileString()!
  1214. gbWinFaxHack = FALSE;
  1215. // Call into the spooler to add our driver to the registry.
  1216. if (!InstallWowFaxPrinter(szDevices, szWINFAX, szWINFAXCOMx)) {
  1217. WOW32ASSERTMSG(FALSE,
  1218. "Install of generic fax printer failed.\n");
  1219. }
  1220. }
  1221. Result = TRUE;
  1222. goto Done;
  1223. }
  1224. // Is it one of the fax drivers we recognize?
  1225. if (IsFaxPrinterSupportedDevice(szKey)) {
  1226. // Time to enable the WinFax Lite hack?
  1227. // if("devices", "WINFAX", "WINFAX,COMx:") we need to avoid the call to
  1228. // InstallWOWFaxPrinter() at this time -- the install program hasn't
  1229. // copied the driver to the hard drive yet!! This causes loadLibrary
  1230. // of WinFax.drv to fail when the spooler tries to callback into it.
  1231. // We also don't want this particular call to WriteProfileString to
  1232. // really be written to the registry -- we let the later call to
  1233. // AddPrinter take care of all the registration stuff.
  1234. if(!WOW32_strcmp(szKey, szWINFAX) &&
  1235. !WOW32_strncmp(szString, szWINFAX, 6) &&
  1236. (szString[6] == ',')) {
  1237. VPVOID vpPathName;
  1238. PSZ pszPathName;
  1239. char szFileName[32];
  1240. // get the install program file name
  1241. // be sure allocation size matches stackfree16() size below
  1242. if(vpPathName = stackalloc16(MAX_PATH)) {
  1243. GetModuleFileName16(CURRENTPTD()->hMod16, vpPathName, MAX_PATH);
  1244. GETVDMPTR(vpPathName, MAX_PATH, pszPathName);
  1245. _splitpath(pszPathName,NULL,NULL,szFileName,NULL);
  1246. // WinFax Lite is "INSTALL", WinFax Pro 4.0 is "SETUP"
  1247. if(!WOW32_stricmp(szINSTALL, szFileName)) {
  1248. strcpy(szWINFAXCOMx, szString); // save the port string
  1249. gbWinFaxHack = TRUE; // enable the hack
  1250. Result = TRUE;
  1251. stackfree16(vpPathName, MAX_PATH);
  1252. goto Done; // skip the call to InstallWowFaxPrinter
  1253. }
  1254. // No hack needed for WinFax Pro 4.0, the driver is copied
  1255. // to the hard disk long before they update win.ini
  1256. else {
  1257. stackfree16(vpPathName, MAX_PATH);
  1258. }
  1259. }
  1260. }
  1261. if (!InstallWowFaxPrinter(szSection, szKey, szString)) {
  1262. WOW32ASSERTMSG(FALSE, "Install of generic fax printer failed.\n");
  1263. }
  1264. Result = TRUE;
  1265. }
  1266. Done:
  1267. return Result;
  1268. }
  1269. BOOL IsFaxPrinterSupportedDevice(PSZ pszDevice)
  1270. {
  1271. UINT i, iNotFound;
  1272. // Trying to read from a fax printer entry?
  1273. LOGDEBUG(0,("IsFaxPrinterSupportedDevice, Device = %s\n", pszDevice));
  1274. //If initialization of SupFaxDrv failed with memory exhaust
  1275. //which isn't very likely to happen
  1276. if (!SupFaxDrv ) {
  1277. return FALSE;
  1278. }
  1279. // Is it one of the fax drivers we recognize?
  1280. for (i = 0; i < uNumSupFaxDrv; i++) {
  1281. iNotFound = WOW32_stricmp(pszDevice, SupFaxDrv[i]);
  1282. if (iNotFound > 0) continue;
  1283. if (iNotFound == 0) {
  1284. LOGDEBUG(0,("IsFaxPrinterSupportedDevice returns TRUE\n"));
  1285. return(TRUE);
  1286. }
  1287. else {
  1288. break;
  1289. }
  1290. }
  1291. return(FALSE);
  1292. }
  1293. DWORD GetFaxPrinterProfileString(PSZ szSection, PSZ szKey, PSZ szDefault, PSZ szRetBuf, DWORD cbBufSize)
  1294. {
  1295. char szTmp[MAX_PATH];
  1296. HKEY hKey = 0;
  1297. DWORD dwType;
  1298. // Read the entry from the shadow entries in registry.
  1299. strcpy(szTmp, "Software\\Microsoft\\Windows NT\\CurrentVersion\\WOW\\WowFax\\");
  1300. strcat(szTmp, szSection);
  1301. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmp, 0, KEY_READ, &hKey ) == ERROR_SUCCESS) {
  1302. if (RegQueryValueEx(hKey, szKey, 0, &dwType, szRetBuf, &cbBufSize) == ERROR_SUCCESS) {
  1303. RegCloseKey(hKey);
  1304. return(cbBufSize);
  1305. }
  1306. }
  1307. if (hKey) {
  1308. RegCloseKey(hKey);
  1309. }
  1310. WOW32WARNMSG(FALSE, ("GetFaxPrinterProfileString Failed. Section = %s, Key = %s\n", szSection, szKey));
  1311. strcpy(szRetBuf, szDefault);
  1312. return(strlen(szDefault));
  1313. }