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.

886 lines
31 KiB

  1. //************************************************************************
  2. // Generic Win 3.1 fax printer driver support. User Interface functions
  3. // which are called by WINSPOOL.
  4. //
  5. // I don't think performance is a big issue here. - nandurir
  6. //
  7. // History:
  8. // 02-jan-95 nandurir created.
  9. // 01-feb-95 reedb Clean-up, support printer install and bug fixes.
  10. // 14-mar-95 reedb Use GDI hooks to move most functionality to UI.
  11. //
  12. //************************************************************************
  13. #define WOWFAX_INC_COMMON_CODE
  14. #include "windows.h"
  15. #include "wowfaxui.h"
  16. #include "winspool.h"
  17. #define DEF_DRV_DOCUMENT_EVENT_DBG_STR
  18. #include "gdispool.h"
  19. #include "winddiui.h"
  20. //************************************************************************
  21. // Globals
  22. //************************************************************************
  23. HINSTANCE ghInst;
  24. FAXDEV gdev;
  25. WORD gdmDriverExtra = sizeof(DEVMODEW);
  26. DEVMODEW gdmDefaultDevMode;
  27. CRITICAL_SECTION CriticalSection;
  28. LPCRITICAL_SECTION lpCriticalSection = &CriticalSection;
  29. //************************************************************************
  30. // DllInitProc
  31. //************************************************************************
  32. BOOL DllInitProc(HMODULE hModule, DWORD Reason, PCONTEXT pContext)
  33. {
  34. UNREFERENCED_PARAMETER(pContext);
  35. if (Reason == DLL_PROCESS_ATTACH) {
  36. DisableThreadLibraryCalls(hModule);
  37. }
  38. InitializeCriticalSection(lpCriticalSection);
  39. ghInst = (HINSTANCE) hModule;
  40. return(TRUE);
  41. }
  42. //************************************************************************
  43. // PrinterProperties
  44. //************************************************************************
  45. BOOL PrinterProperties(HWND hwnd, HANDLE hPrinter)
  46. {
  47. TCHAR szMsg[WOWFAX_MAX_USER_MSG_LEN];
  48. TCHAR szTitle[WOWFAX_MAX_USER_MSG_LEN];
  49. if (LoadString(ghInst, WOWFAX_NAME_STR, szTitle, WOWFAX_MAX_USER_MSG_LEN)) {
  50. if (LoadString(ghInst, WOWFAX_SELF_CONFIG_STR, szMsg, WOWFAX_MAX_USER_MSG_LEN)) {
  51. MessageBox(hwnd, szMsg, szTitle, MB_OK);
  52. }
  53. }
  54. return TRUE;
  55. }
  56. //************************************************************************
  57. // SetupFaxDev - Do some common FaxDev setup: Calculate the size of the
  58. // mapped file section for use by the inter-process communication
  59. // handler. Create and set the mapped section. Get the 16-bit driver
  60. // info from the registry and copy it into the mapped section. Build
  61. // pointers for variable length stuff we copied to the mapped section.
  62. // Return zero on failure, or current offset into mapped section.
  63. //************************************************************************
  64. UINT SetupFaxDev(PWSTR pDeviceName, LPFAXDEV lpdev)
  65. {
  66. LPREGFAXDRVINFO16 lpRegFaxDrvInfo16;
  67. DWORD iOffset = 0;
  68. // Get the driver and port names from the registry where they were written
  69. // by the 16-bit fax driver install program using WriteProfileString.
  70. if ((lpRegFaxDrvInfo16 = Get16BitDriverInfoFromRegistry(pDeviceName))) {
  71. //
  72. // Count dmDriverExtra twice, once for each devmode. Use cached
  73. // gdmDriverExtra value. Normally winspool/common dialogs and others,
  74. // call the DocumentProperties with fMode = 0 to get the size. So we
  75. // update gdmDriverExtra when such a call is made. We leave extra
  76. // room to DWORD align both In and Out pointers.
  77. //
  78. lpdev->cbMapLow = sizeof(FAXDEV);
  79. lpdev->cbMapLow += sizeof(DEVMODE) * 2;
  80. lpdev->cbMapLow += gdmDriverExtra * 2;
  81. lpdev->cbMapLow += sizeof(DWORD) * 2; // Leave room for DWORD align.
  82. lpdev->cbMapLow += (lstrlen(lpRegFaxDrvInfo16->lpDriverName) + 1) * sizeof(TCHAR);
  83. lpdev->cbMapLow += (lstrlen(lpRegFaxDrvInfo16->lpPortName) + 1) * sizeof(TCHAR);
  84. lpdev->idMap = GetCurrentThreadId();
  85. if (InterProcCommHandler(lpdev, DRVFAX_CREATEMAP)) {
  86. if (InterProcCommHandler(lpdev, DRVFAX_SETMAPDATA)) {
  87. // Copy the printer/device name to the WOWFAXINFO struct.
  88. lstrcpy(lpdev->lpMap->szDeviceName,
  89. lpRegFaxDrvInfo16->lpDeviceName);
  90. // Calculate the pointers into the mapped file section and copy
  91. // the variable length data to the mapped file section.
  92. // Printer driver and port names.
  93. iOffset = sizeof(*lpdev->lpMap);
  94. lpdev->lpMap->lpDriverName = (LPTSTR) iOffset;
  95. (PWSTR)iOffset += lstrlen(lpRegFaxDrvInfo16->lpDriverName) + 1;
  96. lstrcpy((PWSTR)((LPBYTE)lpdev->lpMap + (DWORD)lpdev->lpMap->lpDriverName), lpRegFaxDrvInfo16->lpDriverName);
  97. lpdev->lpMap->lpPortName = (LPTSTR) iOffset;
  98. (PWSTR)iOffset += lstrlen(lpRegFaxDrvInfo16->lpPortName) + 1;
  99. lstrcpy((PWSTR)((LPBYTE)lpdev->lpMap + (DWORD)lpdev->lpMap->lpPortName), lpRegFaxDrvInfo16->lpPortName);
  100. }
  101. }
  102. Free16BitDriverInfo(lpRegFaxDrvInfo16);
  103. }
  104. return iOffset;
  105. }
  106. //************************************************************************
  107. // DrvDocumentProperties
  108. //************************************************************************
  109. LONG DrvDocumentProperties(HWND hwnd, HANDLE hPrinter, PWSTR pDeviceName,
  110. PDEVMODE pdmOut, PDEVMODE pdmIn, DWORD fMode)
  111. {
  112. FAXDEV dev = gdev;
  113. LPFAXDEV lpdev = &dev;
  114. LONG lRet = -1;
  115. DWORD iOffset;
  116. DWORD cbT;
  117. DWORD dwWowProcID, dwCallerProcID;
  118. PRINTER_INFO_2 *pPrinterInfo2 = NULL;
  119. LOGDEBUG(1, (L"WOWFAXUI!DrvDocumentProperties, pdmOut: %X, pdmIn: %X, fMode: %X\n", pdmOut, pdmIn, fMode));
  120. // Check for get default devmode case, use spooler to get it if possible.
  121. if (!pdmIn && pdmOut && !(fMode & DM_IN_PROMPT)) {
  122. if (pPrinterInfo2 = MyGetPrinter(hPrinter, 2)) {
  123. if (pPrinterInfo2->pDevMode) {
  124. LOGDEBUG(1, (L" Using spooler default devmode\n"));
  125. cbT = pPrinterInfo2->pDevMode->dmSize +
  126. pPrinterInfo2->pDevMode->dmDriverExtra;
  127. memcpy(pdmOut, pPrinterInfo2->pDevMode, cbT);
  128. lRet = IDOK;
  129. goto LeaveDDP;
  130. }
  131. }
  132. }
  133. if (iOffset = SetupFaxDev(pDeviceName, lpdev)) {
  134. lpdev->lpMap->msg = WM_DDRV_EXTDMODE;
  135. // Calculate the pointers into the mapped file section and copy
  136. // the variable length data to the mapped file section.
  137. DRVFAX_DWORDALIGN(iOffset);
  138. lpdev->lpMap->lpIn = (LPDEVMODEW)((pdmIn) ? iOffset : 0);
  139. iOffset += sizeof(*pdmIn) + gdmDriverExtra;
  140. DRVFAX_DWORDALIGN(iOffset);
  141. lpdev->lpMap->lpOut = (LPDEVMODEW)((pdmOut) ? iOffset : 0);
  142. iOffset += sizeof(*pdmOut) + gdmDriverExtra;
  143. //
  144. // if Input is non-null copy the data even if fMode doesn't
  145. // have the appropriate flag.
  146. //
  147. if (pdmIn) {
  148. // apps don't pass DM_MODIFY even if they mean it - ie
  149. // pdmIn will be non-null but they won't or this flag.
  150. // The 32bit rasdd extracts data from pdmIn even if the
  151. // DM_MODIFY flag is not set. So we need to do the same
  152. if (fMode != 0) {
  153. fMode |= DM_IN_BUFFER;
  154. }
  155. iOffset = (DWORD)lpdev->lpMap + (DWORD)lpdev->lpMap->lpIn;
  156. RtlCopyMemory((LPVOID)iOffset, pdmIn,
  157. sizeof(*pdmIn) + min(gdmDriverExtra, pdmIn->dmDriverExtra));
  158. // reset dmDriverExtra in pdmIn.
  159. ((LPDEVMODE)iOffset)->dmDriverExtra =
  160. min(gdmDriverExtra, pdmIn->dmDriverExtra);
  161. }
  162. if (!(fMode & (DM_COPY | DM_OUT_BUFFER))) {
  163. lpdev->lpMap->lpOut = 0;
  164. }
  165. lpdev->lpMap->wCmd = (WORD)fMode;
  166. // valid size of this map
  167. lpdev->lpMap->cData = lpdev->cbMapLow;
  168. lpdev->lpMap->hwndui = hwnd;
  169. if (fMode & DM_IN_PROMPT) {
  170. GetWindowThreadProcessId(hwnd, &dwCallerProcID);
  171. GetWindowThreadProcessId(lpdev->lpMap->hwnd, &dwWowProcID);
  172. if (dwWowProcID == dwCallerProcID) {
  173. // If the calling process is the same as the 'wowfaxclass' window
  174. // (WOW/WOWEXEC) use CallWindow instead of SendMessage so we don't
  175. // deadlock WOW when trying to put up the 16-bit fax driver UI.
  176. InterProcCommHandler(lpdev, DRVFAX_CALLWOW);
  177. }
  178. else {
  179. InterProcCommHandler(lpdev, DRVFAX_SENDNOTIFYWOW);
  180. }
  181. }
  182. else {
  183. InterProcCommHandler(lpdev, DRVFAX_SENDTOWOW);
  184. }
  185. lRet = (lpdev->lpMap->status) ? (LONG)lpdev->lpMap->retvalue : lRet;
  186. if (lRet > 0) {
  187. if ((fMode & DM_OUT_BUFFER) && (lRet == IDOK) && pdmOut) {
  188. iOffset = (DWORD)lpdev->lpMap + (DWORD)lpdev->lpMap->lpOut;
  189. RtlCopyMemory(pdmOut, (LPDEVMODE)iOffset,
  190. sizeof(*pdmOut)+ ((LPDEVMODE)iOffset)->dmDriverExtra);
  191. // LATER : what about the formname etc. fields - new on NT
  192. }
  193. else if (fMode == 0) {
  194. // update our dmDriverExtra
  195. gdmDriverExtra = (WORD)max(lRet, gdmDriverExtra);
  196. }
  197. }
  198. else {
  199. LOGDEBUG(0, (L"WOWFAXUI!DrvDocumentProperties failed, lpdev->lpMap->status: %X, lpdev->lpMap->retvalue: %X\n", lpdev->lpMap->status, (LONG)lpdev->lpMap->retvalue));
  200. }
  201. InterProcCommHandler(lpdev, DRVFAX_DESTROYMAP);
  202. }
  203. LeaveDDP:
  204. if (pPrinterInfo2) {
  205. LocalFree(pPrinterInfo2);
  206. }
  207. LOGDEBUG(1, (L"WOWFAXUI!DrvDocumentProperties returning: %X, pdmOut: %X, pdmIn: %X\n", lRet, pdmOut, pdmIn));
  208. return(lRet);
  209. }
  210. //************************************************************************
  211. // DrvAdvancedDocumentProperties
  212. //************************************************************************
  213. LONG DrvAdvancedDocumentProperties(HWND hwnd, HANDLE hPrinter, PWSTR pDeviceName,
  214. PDEVMODE pdmOut, PDEVMODE pdmIn)
  215. {
  216. // for 16bit drivers this is a NOP.
  217. return 0;
  218. }
  219. //************************************************************************
  220. // DevQueryPrintEx
  221. //************************************************************************
  222. BOOL DevQueryPrintEx(PDEVQUERYPRINT_INFO pDQPInfo)
  223. {
  224. return TRUE;
  225. }
  226. //************************************************************************
  227. // DrvDeviceCapabilities
  228. //************************************************************************
  229. DWORD DrvDeviceCapabilities(HANDLE hPrinter, PWSTR pDeviceName,
  230. WORD iDevCap, VOID *pOut, PDEVMODE pdmIn)
  231. {
  232. FAXDEV dev = gdev;
  233. LPFAXDEV lpdev = &dev;
  234. LONG lRet = -1;
  235. DWORD iOffset;
  236. LPBYTE lpSrc;
  237. LOGDEBUG(1, (L"WOWFAXUI!DrvDeviceCapabilities, iDevCap: %X, pdmIn: %X\n", iDevCap, pdmIn));
  238. if (iDevCap == DC_SIZE) {
  239. return sizeof(DEVMODEW);
  240. }
  241. if (iOffset = SetupFaxDev(pDeviceName, lpdev)) {
  242. lpdev->lpMap->msg = WM_DDRV_DEVCAPS;
  243. // Calculate the pointers into the mapped file section and copy
  244. // the variable length data to the mapped file section.
  245. lpdev->lpMap->lpIn = (LPDEVMODEW)((pdmIn) ? iOffset : 0);
  246. iOffset += sizeof(*pdmIn) + gdmDriverExtra;
  247. // output in lpout: make this the last pointer in the
  248. // data so that we can use the rest of the mapped area for copy
  249. // on output.
  250. lpdev->lpMap->lpOut = (LPDEVMODEW)((pOut) ? iOffset : 0);
  251. iOffset += sizeof(*pdmIn) + gdmDriverExtra;
  252. if (pdmIn) {
  253. iOffset = (DWORD)lpdev->lpMap + (DWORD)lpdev->lpMap->lpIn;
  254. RtlCopyMemory((LPVOID)iOffset, pdmIn,
  255. sizeof(*pdmIn) + min(gdmDriverExtra, pdmIn->dmDriverExtra));
  256. // reset dmDriverExtra in pdmIn.
  257. ((LPDEVMODE)iOffset)->dmDriverExtra =
  258. min(gdmDriverExtra, pdmIn->dmDriverExtra);
  259. }
  260. lpdev->lpMap->wCmd = iDevCap;
  261. // valid size of this map
  262. lpdev->lpMap->cData = lpdev->cbMapLow;
  263. InterProcCommHandler(lpdev, DRVFAX_SENDTOWOW);
  264. lRet = (lpdev->lpMap->status) ? (LONG)lpdev->lpMap->retvalue : lRet;
  265. // on return cData is the number of bytes to copy
  266. if (lpdev->lpMap->lpOut && lpdev->lpMap->cData && lpdev->lpMap->retvalue) {
  267. lpSrc = (LPBYTE)lpdev->lpMap + (DWORD)lpdev->lpMap->lpOut;
  268. switch (lpdev->lpMap->wCmd) {
  269. case DC_PAPERSIZE:
  270. case DC_MINEXTENT:
  271. case DC_MAXEXTENT:
  272. ((LPPOINT)pOut)->x = ((LPPOINTS)lpSrc)->x;
  273. ((LPPOINT)pOut)->y = ((LPPOINTS)lpSrc)->y;
  274. break;
  275. default:
  276. RtlCopyMemory(pOut, lpSrc, lpdev->lpMap->cData);
  277. break;
  278. }
  279. }
  280. InterProcCommHandler(lpdev, DRVFAX_DESTROYMAP);
  281. }
  282. if (lRet < 0) {
  283. LOGDEBUG(0, (L"WOWFAXUI!DrvDeviceCapabilities Failing\n"));
  284. }
  285. LOGDEBUG(1, (L"WOWFAXUI!DrvDeviceCapabilities, returning pOut: %X\n", pOut));
  286. return(lRet);
  287. }
  288. //************************************************************************
  289. // DrvUpgradePrinter - Called in the system context by the spooler.
  290. // Drivers will really only be updated the first time the spooler is
  291. // started after an upgrade. Calls DoUpgradePrinter to do the work.
  292. //************************************************************************
  293. BOOL DrvUpgradePrinter(DWORD dwLevel, LPBYTE lpDrvUpgradeInfo)
  294. {
  295. static BOOL bDrvUpgradePrinterLock = FALSE;
  296. BOOL bRet;
  297. LOGDEBUG(1, (L"WOWFAXUI!DrvUpgradePrinter, dwLevel: %X, lpDrvUpgradeInfo: %X\n", dwLevel, lpDrvUpgradeInfo));
  298. // DrvUpgradePrinter is called during AddPrinterDriver. Don't allow
  299. // recursion. Protect lock from other threads.
  300. EnterCriticalSection(lpCriticalSection);
  301. if (bDrvUpgradePrinterLock) {
  302. LeaveCriticalSection(lpCriticalSection);
  303. return(TRUE);
  304. }
  305. bDrvUpgradePrinterLock = TRUE;
  306. LeaveCriticalSection(lpCriticalSection);
  307. bRet = DoUpgradePrinter(dwLevel, (LPDRIVER_UPGRADE_INFO_1W)lpDrvUpgradeInfo);
  308. EnterCriticalSection(lpCriticalSection);
  309. bDrvUpgradePrinterLock = FALSE;
  310. LeaveCriticalSection(lpCriticalSection);
  311. return(bRet);
  312. }
  313. //************************************************************************
  314. // DrvDocumentEvent - This exported function is used to hook the GDI
  315. // Display Driver functions. It unpacks and validates the parameters,
  316. // then dispatches to the appropriate handler, based on the passed
  317. // iEsc value. The following table provides a mapping of the
  318. // DrvDocumentEvent escapes to the server side display driver
  319. // callbacks, and gives the call time relative to the callback:
  320. //
  321. // DOCUMENTEVENT_CREATEDCPRE DrvEnablePDEV, before
  322. // DOCUMENTEVENT_CREATEDCPOST DrvEnablePDEV, after
  323. // DOCUMENTEVENT_RESETDCPRE DrvRestartPDEV, before
  324. // DOCUMENTEVENT_RESETDCPOST DrvRestartPDEV, after
  325. // DOCUMENTEVENT_STARTDOC DrvStartDoc, before
  326. // DOCUMENTEVENT_STARTPAGE DrvStartPage, before
  327. // DOCUMENTEVENT_ENDPAGE DrvSendPage, before
  328. // DOCUMENTEVENT_ENDDOC DrvEndDoc, before
  329. // DOCUMENTEVENT_ABORTDOC DrvEndDoc, before
  330. // DOCUMENTEVENT_DELETEDC DrvDisablePDEV, before
  331. //
  332. //************************************************************************
  333. int DrvDocumentEvent(
  334. HANDLE hPrinter,
  335. HDC hdc,
  336. int iEsc,
  337. ULONG cbIn,
  338. PULONG pjIn,
  339. ULONG cbOut,
  340. PULONG pjOut
  341. )
  342. {
  343. int iRet = DOCUMENTEVENT_FAILURE;
  344. if (iEsc < DOCUMENTEVENT_LAST) {
  345. LOGDEBUG(1, (L"WOWFAXUI!DrvDocumentEvent, iEsc: %s, hdc: %X\n", szDrvDocumentEventDbgStrings[iEsc], hdc));
  346. }
  347. // Validate HDC for some of the escapes.
  348. if ((iEsc >= DOCUMENTEVENT_HDCFIRST) && (iEsc < DOCUMENTEVENT_HDCLAST)) {
  349. if (hdc == NULL) {
  350. LOGDEBUG(0, (L"WOWFAXUI!DrvDocumentEvent NULL HDC for escape: %X\n", iEsc));
  351. return(iRet);
  352. }
  353. }
  354. switch (iEsc)
  355. {
  356. case DOCUMENTEVENT_CREATEDCPRE:
  357. iRet = DocEvntCreateDCpre((LPWSTR)*(pjIn+1),
  358. (DEVMODEW*)*(pjIn+2),
  359. (DEVMODEW**)pjOut);
  360. break;
  361. case DOCUMENTEVENT_CREATEDCPOST:
  362. iRet = DocEvntCreateDCpost(hdc, (DEVMODEW*)*pjIn);
  363. break;
  364. case DOCUMENTEVENT_RESETDCPRE:
  365. iRet = DocEvntResetDCpre(hdc, (DEVMODEW*)*(pjIn),
  366. (DEVMODEW**)pjOut);
  367. break;
  368. case DOCUMENTEVENT_RESETDCPOST:
  369. iRet = DocEvntResetDCpost(hdc, (DEVMODEW*)*pjIn);
  370. break;
  371. case DOCUMENTEVENT_STARTDOC:
  372. // WowFax (EasyFax Ver2.0) support.
  373. // Also Procomm+ 3 cover sheets. Bug #305665
  374. iRet = DocEvntStartDoc(hdc, (DOCINFOW*)*pjIn);
  375. break;
  376. case DOCUMENTEVENT_DELETEDC:
  377. iRet = DocEvntDeleteDC(hdc);
  378. break;
  379. case DOCUMENTEVENT_ENDDOC:
  380. iRet = DocEvntEndDoc(hdc);
  381. break;
  382. case DOCUMENTEVENT_ENDPAGE:
  383. iRet = DocEvntEndPage(hdc);
  384. break;
  385. // The following require no client side processing:
  386. case DOCUMENTEVENT_ESCAPE:
  387. case DOCUMENTEVENT_ABORTDOC:
  388. case DOCUMENTEVENT_STARTPAGE:
  389. // No Client side processing needed.
  390. goto docevnt_unsupported;
  391. default :
  392. LOGDEBUG(0, (L"WOWFAXUI!DrvDocumentEvent unknown escape: %X\n", iEsc));
  393. docevnt_unsupported:
  394. iRet = DOCUMENTEVENT_UNSUPPORTED;
  395. } // switch
  396. LOGDEBUG(1, (L"WOWFAXUI!DrvDocumentEvent return: %X\n", iRet));
  397. return(iRet);
  398. }
  399. //***************************************************************************
  400. // DocEvntCreateDCpre - Allocate a DEVMODE which contains a FAXDEV as the
  401. // dmDriverExtra portion. This DEVMODE will be passed to the
  402. // DrvEnablePDEV function on the server side.
  403. //***************************************************************************
  404. int DocEvntCreateDCpre(
  405. LPWSTR lpszDevice,
  406. DEVMODEW *pDevModIn,
  407. DEVMODEW **pDevModOut
  408. )
  409. {
  410. DWORD iOffset = 0;
  411. LPFAXDEV lpFaxDev;
  412. PGDIINFO pGdiInfo;
  413. DEVMODEW *pTmpDevMode;
  414. LPREGFAXDRVINFO16 lpRegFaxDrvInfo16;
  415. int iRet = DOCUMENTEVENT_FAILURE;
  416. if ((lpszDevice == NULL) || (pDevModOut == NULL)) {
  417. LOGDEBUG(0, (L"WOWFAXUI!DocEvntCreateDCpre, failed, NULL parameters\n"));
  418. goto DocEvntCreateDCpreFailed;
  419. }
  420. LOGDEBUG(1, (L"WOWFAXUI!DocEvntCreateDCpre, Device: %s, pDevModIn: %X pDevModOut: %X\n", lpszDevice, pDevModIn, pDevModOut));
  421. // Use our global default devmode if a NULL devmode is passed in from the app.
  422. if (pDevModIn == NULL) {
  423. gdmDefaultDevMode.dmSize = sizeof(DEVMODEW);
  424. pDevModIn = &gdmDefaultDevMode;
  425. }
  426. pTmpDevMode = (DEVMODEW*)WFLOCALALLOC(sizeof(FAXDEV) + sizeof(DEVMODEW),
  427. L"DocEvntCreateDCpre");
  428. LOGDEBUG(2, (L"WOWFAXUI!DocEvntCreateDCpre, pTmpDevMode: %X\n", pTmpDevMode));
  429. if (pTmpDevMode == NULL) {
  430. goto DocEvntCreateDCpreFailed;
  431. }
  432. // Copy pDevModIn to the new DEVMODE.
  433. RtlCopyMemory(pTmpDevMode, pDevModIn, sizeof(*pTmpDevMode));
  434. pTmpDevMode->dmDriverExtra = sizeof(FAXDEV);
  435. pTmpDevMode->dmSize = sizeof(DEVMODEW);
  436. // Setup some handy pointers.
  437. lpFaxDev = (LPFAXDEV) (pTmpDevMode + 1);
  438. pGdiInfo = &(lpFaxDev->gdiinfo);
  439. lpFaxDev->id = FAXDEV_ID;
  440. // Save a client side pointer to the new DEVMODE and it's embeded FAXDEV.
  441. // We'll use ExtEscape to get these pointers back any time we need to
  442. // associate driver context with an HDC.
  443. lpFaxDev->pdevmode = pTmpDevMode;
  444. lpFaxDev->lpClient = lpFaxDev;
  445. // Get the driver and port names from the registry where they were written
  446. // by the 16-bit fax driver install program using WriteProfileString.
  447. if ((lpRegFaxDrvInfo16 = Get16BitDriverInfoFromRegistry(lpszDevice)) == NULL) {
  448. goto DocEvntCreateDCpreFailed;
  449. }
  450. if ((lpFaxDev->hwnd = FindWowFaxWindow()) == NULL) {
  451. goto DocEvntCreateDCpreFailed;
  452. }
  453. lpFaxDev->tid = GetWindowThreadProcessId(lpFaxDev->hwnd, 0);
  454. lpFaxDev->idMap = (DWORD)lpFaxDev;
  455. // Calculate the size of the mapped file section for inter process communication.
  456. lpFaxDev->cbMapLow = sizeof(DWORD) + // leave room for DWORD align
  457. sizeof(*lpFaxDev->lpMap) +
  458. sizeof(GDIINFO) +
  459. (lstrlen(lpRegFaxDrvInfo16->lpDriverName) + 1) * sizeof(TCHAR) +
  460. (lstrlen(lpRegFaxDrvInfo16->lpPortName) + 1) * sizeof(TCHAR) +
  461. sizeof(*pDevModIn) +
  462. ((pDevModIn) ? pDevModIn->dmDriverExtra : 0);
  463. DRVFAX_DWORDALIGN(lpFaxDev->cbMapLow);
  464. InterProcCommHandler(lpFaxDev, DRVFAX_CREATEMAP);
  465. if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
  466. lpFaxDev->lpMap->msg = WM_DDRV_ENABLE;
  467. // Copy the printer/device name to the WOWFAXINFO struct.
  468. lstrcpy(lpFaxDev->lpMap->szDeviceName, lpszDevice);
  469. // Calculate the pointers into the mapped file section and copy
  470. // the variable length data to the mapped file section.
  471. // output : gdiinfo
  472. lpFaxDev->lpMap->lpOut = (LPDEVMODE)(sizeof(*lpFaxDev->lpMap));
  473. iOffset = sizeof(*lpFaxDev->lpMap) + sizeof(GDIINFO);
  474. // Device (printer) and port names.
  475. lpFaxDev->lpMap->lpDriverName = (LPSTR) iOffset;
  476. (PWSTR)iOffset += lstrlen(lpRegFaxDrvInfo16->lpDriverName) + 1;
  477. lstrcpy((PWSTR)((LPBYTE)lpFaxDev->lpMap + (DWORD)lpFaxDev->lpMap->lpDriverName), lpRegFaxDrvInfo16->lpDriverName);
  478. lpFaxDev->lpMap->lpPortName = (LPVOID) iOffset;
  479. (PWSTR)iOffset += lstrlen(lpRegFaxDrvInfo16->lpPortName) + 1;
  480. lstrcpy((PWSTR)((LPBYTE)lpFaxDev->lpMap + (DWORD)lpFaxDev->lpMap->lpPortName), lpRegFaxDrvInfo16->lpPortName);
  481. // input: devmode
  482. DRVFAX_DWORDALIGN(iOffset);
  483. lpFaxDev->lpMap->lpIn = (LPDEVMODE)((pDevModIn) ? iOffset : 0);
  484. iOffset += ((pDevModIn) ? sizeof(*pDevModIn) + pDevModIn->dmDriverExtra : 0);
  485. if (pDevModIn) {
  486. RtlCopyMemory((LPBYTE)lpFaxDev->lpMap + (DWORD)lpFaxDev->lpMap->lpIn,
  487. pDevModIn, sizeof(*pDevModIn) + pDevModIn->dmDriverExtra);
  488. }
  489. // set the total byte count of data.
  490. lpFaxDev->lpMap->cData = iOffset;
  491. // all done - switch to wow
  492. InterProcCommHandler(lpFaxDev, DRVFAX_SENDTOWOW);
  493. // values returned from wow.
  494. lpFaxDev->lpinfo16 = (DWORD)lpFaxDev->lpMap->lpinfo16;
  495. iRet = lpFaxDev->lpMap->status && lpFaxDev->lpMap->retvalue;
  496. if (iRet) {
  497. // Copy GDIINFO from WOW to the client side FAXDEV.
  498. RtlCopyMemory(pGdiInfo,
  499. (LPBYTE)lpFaxDev->lpMap + (DWORD)lpFaxDev->lpMap->lpOut,
  500. sizeof(GDIINFO));
  501. // Fill in some misc. fields in the client FAXDEV.
  502. pGdiInfo->ulHTPatternSize = HT_PATSIZE_DEFAULT;
  503. pGdiInfo->ulHTOutputFormat = HT_FORMAT_1BPP;
  504. lpFaxDev->bmWidthBytes = pGdiInfo->szlPhysSize.cx / 0x8;
  505. DRVFAX_DWORDALIGN(lpFaxDev->bmWidthBytes);
  506. lpFaxDev->bmFormat = BMF_1BPP;
  507. lpFaxDev->cPixPerByte = 0x8;
  508. // Here if success, make pDevModOut point to the new DEVMODE.
  509. *pDevModOut = pTmpDevMode;
  510. }
  511. else {
  512. LOGDEBUG(0, (L"WOWFAXUI!DocEvntCreateDCpre, WOW returned error\n"));
  513. }
  514. }
  515. if (iRet) {
  516. goto DocEvntCreateDCpreSuccess;
  517. }
  518. else {
  519. iRet = DOCUMENTEVENT_FAILURE;
  520. }
  521. DocEvntCreateDCpreFailed:
  522. LOGDEBUG(0, (L"WOWFAXUI!DocEvntCreateDCpre, failed!\n"));
  523. DocEvntCreateDCpreSuccess:
  524. LOGDEBUG(1, (L"WOWFAXUI!DocEvntCreateDCpre, iRet: %X\n", iRet));
  525. Free16BitDriverInfo(lpRegFaxDrvInfo16);
  526. return(iRet);
  527. }
  528. //***************************************************************************
  529. // DocEvntResetDCpre -
  530. //***************************************************************************
  531. int DocEvntResetDCpre(
  532. HDC hdc,
  533. DEVMODEW *pDevModIn,
  534. DEVMODEW **pDevModOut
  535. )
  536. {
  537. return(DOCUMENTEVENT_FAILURE);
  538. }
  539. //***************************************************************************
  540. // DocEvntResetDCpost -
  541. //***************************************************************************
  542. int DocEvntResetDCpost(
  543. HDC hdc,
  544. DEVMODEW *pDevModIn
  545. )
  546. {
  547. return(DOCUMENTEVENT_SUCCESS);
  548. }
  549. //***************************************************************************
  550. // DocEvntCreateDCpost -
  551. //***************************************************************************
  552. int DocEvntCreateDCpost(
  553. HDC hdc,
  554. DEVMODEW *pDevModIn
  555. )
  556. {
  557. LOGDEBUG(1, (L"WOWFAXUI!DocEvntCreateDCpost, hdc: %X, pDevModIn: %X\n", hdc, pDevModIn));
  558. // hdc was zero indicates DrvEnablePDEV failed. Cleanup.
  559. if (hdc == NULL) {
  560. if (pDevModIn) {
  561. LocalFree(pDevModIn);
  562. LOGDEBUG(1, (L"WOWFAXUI!DocEvntCreateDCpost, Cleaning up\n"));
  563. }
  564. }
  565. return(DOCUMENTEVENT_SUCCESS);
  566. }
  567. //***************************************************************************
  568. // DocEvntStartDoc - hdc was validated by DrvDocumentEvent.
  569. //***************************************************************************
  570. int DocEvntStartDoc(
  571. HDC hdc,
  572. DOCINFOW *pDocInfoW
  573. )
  574. {
  575. LPFAXDEV lpFaxDev = 0;
  576. HBITMAP hbm = 0;
  577. DWORD cbOld;
  578. int iRet = 0;
  579. lpFaxDev = (LPFAXDEV)ExtEscape(hdc, DRV_ESC_GET_FAXDEV_PTR, 0, NULL, 0, NULL);
  580. if (ValidateFaxDev(lpFaxDev)) {
  581. if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
  582. lpFaxDev->lpMap->msg = WM_DDRV_STARTDOC;
  583. // WowFax (EasyFax Ver2.0) support.
  584. // Also Procomm+ 3 cover sheets. Bug #305665.
  585. if (pDocInfoW && pDocInfoW->lpszDocName)
  586. lstrcpyW(lpFaxDev->lpMap->szDocName,pDocInfoW->lpszDocName);
  587. else
  588. lstrcpyW(lpFaxDev->lpMap->szDocName,L"");
  589. InterProcCommHandler(lpFaxDev, DRVFAX_SENDNOTIFYWOW);
  590. iRet = ((LONG)lpFaxDev->lpMap->retvalue > 0);
  591. // Calculate new mapsize - the bitmap bits will be written into
  592. // this map with a call to ExtEscape - thus allowing easy access
  593. // to the bits from WOW.
  594. cbOld = lpFaxDev->cbMapLow;
  595. lpFaxDev->cbMapLow += lpFaxDev->bmWidthBytes *
  596. lpFaxDev->gdiinfo.szlPhysSize.cy;
  597. if (InterProcCommHandler(lpFaxDev, DRVFAX_CREATEMAP)) {
  598. lpFaxDev->offbits = cbOld;
  599. goto DocEvntStartDocSuccess;
  600. }
  601. }
  602. }
  603. LOGDEBUG(1, (L"WOWFAXUI!DocEvntStartDoc, failed\n"));
  604. DocEvntStartDocSuccess:
  605. if (iRet == 0) {
  606. iRet = DOCUMENTEVENT_FAILURE;
  607. }
  608. return iRet;
  609. }
  610. //***************************************************************************
  611. // DocEvntDeleteDC - hdc was validated by DrvDocumentEvent.
  612. //***************************************************************************
  613. int DocEvntDeleteDC(
  614. HDC hdc
  615. )
  616. {
  617. LPFAXDEV lpFaxDev;
  618. DEVMODEW *lpDevMode;
  619. int iRet = DOCUMENTEVENT_FAILURE;
  620. lpFaxDev = (LPFAXDEV)ExtEscape(hdc, DRV_ESC_GET_FAXDEV_PTR, 0, NULL, 0, NULL);
  621. if (ValidateFaxDev(lpFaxDev)) {
  622. // Validate 16-bit FaxWndProc window handle before sending a message.
  623. if (lpFaxDev->tid == GetWindowThreadProcessId(lpFaxDev->hwnd, 0)) {
  624. if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
  625. lpFaxDev->lpMap->msg = WM_DDRV_DISABLE;
  626. InterProcCommHandler(lpFaxDev, DRVFAX_SENDTOWOW);
  627. }
  628. }
  629. else {
  630. LOGDEBUG(0, (L"WOWFAXUI!DocEvntDeleteDC, unable to validate FaxWndProc\n"));
  631. }
  632. InterProcCommHandler(lpFaxDev, DRVFAX_DESTROYMAP);
  633. }
  634. else {
  635. LOGDEBUG(0, (L"WOWFAXUI!DocEvntDeleteDC, unable to get lpFaxDev\n"));
  636. }
  637. lpDevMode = (DEVMODEW*)ExtEscape(hdc, DRV_ESC_GET_DEVMODE_PTR, 0, NULL, 0, NULL);
  638. if (lpDevMode) {
  639. LocalFree(lpDevMode);
  640. iRet = DOCUMENTEVENT_SUCCESS;
  641. }
  642. else {
  643. LOGDEBUG(0, (L"WOWFAXUI!DocEvntDeleteDC, unable to get lpDevMode\n"));
  644. }
  645. return iRet;
  646. }
  647. //***************************************************************************
  648. // DocEvntEndDoc - hdc was validated by DrvDocumentEvent.
  649. //***************************************************************************
  650. int DocEvntEndDoc(
  651. HDC hdc
  652. )
  653. {
  654. LPFAXDEV lpFaxDev;
  655. DEVMODEW *lpDevMode;
  656. int iRet = DOCUMENTEVENT_FAILURE;
  657. lpFaxDev = (LPFAXDEV)ExtEscape(hdc, DRV_ESC_GET_FAXDEV_PTR, 0, NULL, 0, NULL);
  658. if (ValidateFaxDev(lpFaxDev)) {
  659. if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
  660. lpFaxDev->lpMap->msg = WM_DDRV_ENDDOC;
  661. InterProcCommHandler(lpFaxDev, DRVFAX_SENDTOWOW);
  662. iRet = lpFaxDev->lpMap->status && ((LONG)lpFaxDev->lpMap->retvalue > 0);
  663. goto DocEvntEndDocSuccess;
  664. }
  665. }
  666. LOGDEBUG(1, (L"WOWFAXUI!DocEvntEndDoc, failed\n"));
  667. DocEvntEndDocSuccess:
  668. if (iRet == 0) {
  669. iRet = DOCUMENTEVENT_FAILURE;
  670. }
  671. return iRet;
  672. }
  673. //***************************************************************************
  674. // DocEvntEndPage - hdc was validated by DrvDocumentEvent.
  675. //***************************************************************************
  676. int DocEvntEndPage(
  677. HDC hdc
  678. )
  679. {
  680. LPFAXDEV lpFaxDev;
  681. LONG lDelta;
  682. ULONG cjBits;
  683. int iRet = DOCUMENTEVENT_FAILURE;
  684. lpFaxDev = (LPFAXDEV)ExtEscape(hdc, DRV_ESC_GET_FAXDEV_PTR, 0, NULL, 0, NULL);
  685. if (ValidateFaxDev(lpFaxDev)) {
  686. if (InterProcCommHandler(lpFaxDev, DRVFAX_SETMAPDATA)) {
  687. lpFaxDev->lpMap->msg = WM_DDRV_PRINTPAGE;
  688. // Get Surface info, cjBits and lDelta.
  689. cjBits = ExtEscape(hdc, DRV_ESC_GET_SURF_INFO, 0, NULL,
  690. 4, (PVOID)&lDelta);
  691. if (cjBits) {
  692. lpFaxDev->lpMap->bmWidthBytes = lDelta;
  693. lpFaxDev->lpMap->bmHeight = cjBits / lDelta;
  694. lpFaxDev->lpMap->bmPixPerByte = lpFaxDev->cPixPerByte;
  695. (DWORD)lpFaxDev->lpMap->lpbits = lpFaxDev->offbits;
  696. if (ExtEscape(hdc, DRV_ESC_GET_BITMAP_BITS, 0, NULL, cjBits,
  697. (LPBYTE)lpFaxDev->lpMap + lpFaxDev->offbits)) {
  698. InterProcCommHandler(lpFaxDev, DRVFAX_SENDTOWOW);
  699. iRet = lpFaxDev->lpMap->status &&
  700. ((LONG)lpFaxDev->lpMap->retvalue > 0);
  701. }
  702. goto DocEvntEndPageSuccess;
  703. }
  704. }
  705. }
  706. LOGDEBUG(1, (L"WOWFAXUI!DocEvntEndPage, failed\n"));
  707. DocEvntEndPageSuccess:
  708. if (iRet == 0) {
  709. iRet = DOCUMENTEVENT_FAILURE;
  710. }
  711. return iRet;
  712. }