Leaked source code of windows server 2003
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.

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