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.

603 lines
20 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WGPRNSET.C
  8. * WOW32 printer setup support routines
  9. *
  10. * These routines help a Win 3.0 task to complete the printer set-up,
  11. * when a user initiates the printer setup from the file menu of an
  12. * application.
  13. *
  14. * History:
  15. * Created 18-Apr-1991 by Chandan Chauhan (ChandanC)
  16. --*/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. MODNAME(wgprnset.c);
  20. DLLENTRYPOINTS spoolerapis[WOW_SPOOLERAPI_COUNT] = {"EXTDEVICEMODE", NULL,
  21. "DEVICEMODE", NULL,
  22. "DEVICECAPABILITIES", NULL,
  23. "OpenPrinterA", NULL,
  24. "StartDocPrinterA", NULL,
  25. "StartPagePrinter", NULL,
  26. "EndPagePrinter", NULL,
  27. "EndDocPrinter", NULL,
  28. "ClosePrinter", NULL,
  29. "WritePrinter", NULL,
  30. "DeletePrinter", NULL,
  31. "GetPrinterDriverDirectoryA", NULL,
  32. "AddPrinterA", NULL,
  33. "AddPrinterDriverA", NULL,
  34. "AddPortExA",NULL};
  35. /****************************************************************************
  36. * *
  37. * ULONG FASTCALL WG32DeviceMode (PVDMFRAME pFrame) *
  38. * *
  39. * (hWnd, hModule, lpDeviceName, lpOutPut) *
  40. * *
  41. * This function passes WDevMode structure (which is per wow task) to *
  42. * Win32 printer driver ExtDeviceMode API. This structure is then *
  43. * initialized by the printer driver based on the user input. *
  44. * *
  45. * Later on, when a WOW task creates a dc (by CreateDC API), the device *
  46. * mode (WDevMode) structure associated with this wow task is passed along *
  47. * with the CreateDC API. Which contains the printer setup information *
  48. * needed to print the document. *
  49. * *
  50. ****************************************************************************/
  51. ULONG FASTCALL WG32DeviceMode (PVDMFRAME pFrame)
  52. {
  53. register PDEVICEMODE16 parg16;
  54. PSZ psz3 = NULL;
  55. PSZ psz4 = NULL;
  56. ULONG l = 0;
  57. HWND hwnd32;
  58. GETARGPTR(pFrame, sizeof(DEVICEMODE16), parg16);
  59. // copy all 16-bit params now since 16-bit memory may move if this calls
  60. // into a 16-bit fax driver
  61. hwnd32 = HWND32(parg16->f1);
  62. if(parg16->f3) {
  63. if(!(psz3 = malloc_w_strcpy_vp16to32(parg16->f3, FALSE, 0)))
  64. goto ExitPath;
  65. }
  66. if(parg16->f4) {
  67. if(!(psz4 = malloc_w_strcpy_vp16to32(parg16->f4, FALSE, 0)))
  68. goto ExitPath;
  69. }
  70. // invalidate all flat ptrs to 16:16 memory now!
  71. FREEARGPTR(parg16);
  72. if (!(spoolerapis[WOW_DEVICEMODE].lpfn)) {
  73. if (!LoadLibraryAndGetProcAddresses(L"WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  74. goto ExitPath;
  75. }
  76. }
  77. // this can callback into a 16-bit fax driver!
  78. (*spoolerapis[WOW_DEVICEMODE].lpfn)(hwnd32, NULL, psz3, psz4);
  79. l = 1;
  80. ExitPath:
  81. if(psz3) {
  82. free_w(psz3);
  83. }
  84. if(psz4) {
  85. free_w(psz4);
  86. }
  87. RETURN(l); // DeviceMode returns void. Charisma checks the return value!
  88. }
  89. /*****************************************************************************
  90. * *
  91. * ULONG FASTCALL WG32ExtDeviceMode (PVDMFRAME pFrame) *
  92. * *
  93. * INT (hWnd, hDriver, lpDevModeOutput, lpDeviceName, lpPort, *
  94. * lpDevModeInput, lpProfile, wMode) *
  95. * *
  96. * This function is same as DeviceMode except that the wow task supplies *
  97. * a DeviceMode structure. Apart from it, this API can be called in *
  98. * different modes. *
  99. * *
  100. *****************************************************************************/
  101. ULONG FASTCALL WG32ExtDeviceMode (PVDMFRAME pFrame)
  102. {
  103. UINT cb;
  104. LONG l = 0;
  105. HWND hWnd1;
  106. WORD wMode8;
  107. PSZ psz4 = NULL;
  108. PSZ psz5 = NULL;
  109. PSZ psz7 = NULL;
  110. VPVOID vpdm3, vpdm6;
  111. LPDEVMODE lpdmInput6;
  112. LPDEVMODE lpdmOutput3;
  113. register PEXTDEVICEMODE16 parg16;
  114. GETARGPTR(pFrame, sizeof(EXTDEVICEMODE16), parg16);
  115. // copy the 16-bit parameters into local vars since this may callback
  116. // into a 16-bit fax driver and cause 16-bit memory to move
  117. hWnd1 = HWND32(parg16->f1);
  118. vpdm3 = FETCHDWORD(parg16->f3);
  119. vpdm6 = FETCHDWORD(parg16->f6);
  120. wMode8 = FETCHWORD(parg16->f8);
  121. if(parg16->f4) {
  122. if(!(psz4 = malloc_w_strcpy_vp16to32(parg16->f4, FALSE, 0)))
  123. goto ExitPath;
  124. }
  125. if(parg16->f5) {
  126. if(!(psz5 = malloc_w_strcpy_vp16to32(parg16->f5, FALSE, 0)))
  127. goto ExitPath;
  128. }
  129. if(parg16->f7) {
  130. if(!(psz7 = malloc_w_strcpy_vp16to32(parg16->f7, FALSE, 0)))
  131. goto ExitPath;
  132. }
  133. FREEARGPTR(parg16);
  134. // all flat ptrs to 16:16 memory are now invalid!!
  135. if (!(spoolerapis[WOW_EXTDEVICEMODE].lpfn)) {
  136. if (!LoadLibraryAndGetProcAddresses(L"WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  137. goto ExitPath;
  138. }
  139. }
  140. lpdmInput6 = ThunkDevMode16to32(FETCHDWORD(vpdm6));
  141. /* if they want output buffer size OR they want to fill output buffer */
  142. if( (wMode8 == 0) || (wMode8 & DM_OUT_BUFFER) ) {
  143. /* get required size for output buffer */
  144. l = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(hWnd1,
  145. NULL,
  146. NULL,
  147. psz4,
  148. psz5,
  149. lpdmInput6,
  150. psz7,
  151. 0);
  152. // adjust size for WOW handling (see notes in wstruc.c)
  153. if(l > 0) {
  154. l += sizeof(WOWDM31);
  155. cb = (UINT)l;
  156. }
  157. /* if caller wants output buffer filled... */
  158. if( (wMode8 != 0) && (vpdm3 != 0L) && l > 0 ) {
  159. if( lpdmOutput3 = malloc_w(l) ) {
  160. l = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(hWnd1,
  161. NULL,
  162. lpdmOutput3,
  163. psz4,
  164. psz5,
  165. lpdmInput6,
  166. psz7,
  167. wMode8);
  168. /* Data in lpdmOutput3 is only valid with IDOK return. */
  169. if( l == IDOK ) {
  170. // do our WOW magic on this before we give it to the app
  171. ThunkDevMode32to16(vpdm3, lpdmOutput3, cb);
  172. }
  173. free_w(lpdmOutput3);
  174. }
  175. else {
  176. l = -1L;
  177. }
  178. }
  179. }
  180. /* else call for cases where they don't want to fill the output buffer */
  181. else {
  182. l = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(hWnd1,
  183. NULL,
  184. NULL,
  185. psz4,
  186. psz5,
  187. lpdmInput6,
  188. psz7,
  189. wMode8);
  190. }
  191. if( lpdmInput6 ) {
  192. free_w(lpdmInput6);
  193. }
  194. ExitPath:
  195. if(psz4) {
  196. free_w(psz4);
  197. }
  198. if(psz5) {
  199. free_w(psz5);
  200. }
  201. if(psz7) {
  202. free_w(psz7);
  203. }
  204. RETURN((ULONG)l);
  205. }
  206. ULONG FASTCALL WG32DeviceCapabilities (PVDMFRAME pFrame)
  207. {
  208. LONG l=0L, cb;
  209. WORD fwCap3;
  210. PBYTE pOutput4, pOutput32;
  211. VPVOID vpOutput4;
  212. PSZ psz1 = NULL;
  213. PSZ psz2 = NULL;
  214. LPDEVMODE lpdmInput5;
  215. DWORD dwDM5;
  216. register PDEVICECAPABILITIES16 parg16;
  217. GETARGPTR(pFrame, sizeof(DEVICECAPABILITIES16), parg16);
  218. // copy the 16-bit parameters into local vars since this may callback
  219. // into a 16-bit fax driver and cause 16-bit memory to move
  220. if(parg16->f1) {
  221. if(!(psz1 = malloc_w_strcpy_vp16to32(parg16->f1, FALSE, 0)))
  222. goto ExitPath;
  223. }
  224. if(parg16->f2) {
  225. if(!(psz2 = malloc_w_strcpy_vp16to32(parg16->f2, FALSE, 0)))
  226. goto ExitPath;
  227. }
  228. fwCap3 = FETCHWORD(parg16->f3);
  229. vpOutput4 = FETCHDWORD(parg16->f4);
  230. dwDM5 = FETCHDWORD(parg16->f5);
  231. FREEARGPTR(parg16);
  232. // all flat ptrs to 16:16 memory are now invalid!!
  233. if (!(spoolerapis[WOW_DEVICECAPABILITIES].lpfn)) {
  234. if (!LoadLibraryAndGetProcAddresses(L"WINSPOOL.DRV",
  235. spoolerapis,
  236. WOW_SPOOLERAPI_COUNT)) {
  237. goto ExitPath;
  238. }
  239. }
  240. lpdmInput5 = ThunkDevMode16to32(dwDM5);
  241. LOGDEBUG(LOG_TRACE, ("WG32DeviceCapabilities %d\n", fwCap3));
  242. switch (fwCap3) {
  243. // These ones do not fill up an output Buffer
  244. case DC_FIELDS:
  245. case DC_DUPLEX:
  246. case DC_SIZE:
  247. case DC_EXTRA:
  248. case DC_VERSION:
  249. case DC_DRIVER:
  250. case DC_TRUETYPE:
  251. case DC_ORIENTATION:
  252. case DC_COPIES:
  253. l = (*spoolerapis[WOW_DEVICECAPABILITIES].lpfn)(psz1,
  254. psz2,
  255. fwCap3,
  256. NULL,
  257. lpdmInput5);
  258. LOGDEBUG(LOG_TRACE, ("WG32DeviceCapabilities simple case returned %d\n", l));
  259. // adjust for WOW handling of devmodes // see notes in wstruc.c
  260. if(fwCap3 == DC_SIZE) {
  261. // we always convert NT DevModes to Win3.1 DevModes
  262. WOW32WARNMSGF((l==sizeof(DEVMODE)),
  263. ("WG32DeviceCapabilities: Unexpected DevMode size: %d\n",l));
  264. if(l == sizeof(DEVMODE)) {
  265. l = sizeof(DEVMODE31);
  266. }
  267. }
  268. // adjust DriverExtra to allow for difference between NT devmodes
  269. // & Win3.1 devmodes + our secret WOW stuff at the end
  270. else if(fwCap3 == DC_EXTRA) {
  271. l += WOW_DEVMODEEXTRA;
  272. }
  273. // we tell them Win3.1 for the spec version too
  274. else if(fwCap3 == DC_VERSION) {
  275. l = WOW_DEVMODE31SPEC; // tell 'em the spec version is Win3.1
  276. }
  277. break;
  278. #ifdef DBCS
  279. // not supported the following indexes.
  280. case DC_MINEXTENT:
  281. case DC_MAXEXTENT:
  282. #ifdef DBCS_LATER
  283. #if DBG
  284. LOGDEBUG(0,("WG32DeviceCapabilities more complicated:"));
  285. #endif
  286. pOutput = malloc_w(8);
  287. if (pOutput) {
  288. l = DEVICECAPABILITIES(psz1, psz2, parg16->f3, pOutput, pdmInput5);
  289. if (l >= 0) {
  290. #if DBG
  291. LOGDEBUG(0,("Copying %d points from %0x to %0x\n", l, pOutput, pb4));
  292. #endif
  293. putpoint16(parg16->f4, 1, pOutput);
  294. }
  295. free_w(pOutput);
  296. }
  297. else {
  298. l = -1;
  299. }
  300. #endif // DBCS_LATER
  301. l = -1; // always error return
  302. break;
  303. #endif // DBCS
  304. // These require an output buffer
  305. case DC_PAPERS:
  306. case DC_PAPERSIZE:
  307. #ifndef DBCS
  308. case DC_MINEXTENT:
  309. case DC_MAXEXTENT:
  310. #endif // !DBCS
  311. case DC_BINS:
  312. case DC_BINNAMES:
  313. case DC_ENUMRESOLUTIONS:
  314. case DC_FILEDEPENDENCIES:
  315. case DC_PAPERNAMES:
  316. LOGDEBUG(LOG_TRACE, ("WG32DeviceCapabilities more complicated:\n"));
  317. // We've got to figure out how much memory we will need
  318. GETMISCPTR(vpOutput4, pOutput4);
  319. if (pOutput4) {
  320. cb = (*spoolerapis[WOW_DEVICECAPABILITIES].lpfn)(psz1,
  321. psz2,
  322. fwCap3,
  323. NULL,
  324. lpdmInput5);
  325. FREEPSZPTR(pOutput4); // invalidate -16bit memory may have moved
  326. LOGDEBUG(LOG_TRACE, ("we need %d bytes ", cb));
  327. if (cb > 0) {
  328. switch (fwCap3) {
  329. case DC_PAPERS:
  330. cb *= 2;
  331. break;
  332. case DC_BINNAMES:
  333. cb *= 24;
  334. break;
  335. case DC_BINS:
  336. cb*=2;
  337. break;
  338. case DC_FILEDEPENDENCIES:
  339. case DC_PAPERNAMES:
  340. cb *= 64;
  341. break;
  342. case DC_MAXEXTENT:
  343. case DC_MINEXTENT:
  344. case DC_PAPERSIZE:
  345. cb *= 8;
  346. LOGDEBUG(LOG_TRACE, ("DC_PAPERSIZE called: Needed %d bytes\n", cb));
  347. break;
  348. case DC_ENUMRESOLUTIONS:
  349. cb *= sizeof(LONG)*2;
  350. break;
  351. } // end switch
  352. pOutput32 = malloc_w(cb);
  353. if (pOutput32) {
  354. l = (*spoolerapis[WOW_DEVICECAPABILITIES].lpfn)(psz1, psz2, fwCap3, pOutput32, lpdmInput5);
  355. if (l >= 0) {
  356. GETMISCPTR(vpOutput4, pOutput4);
  357. switch (fwCap3) {
  358. case DC_PAPERS:
  359. if (CURRENTPTD()->dwWOWCompatFlags &
  360. WOWCF_RESETPAPER29ANDABOVE) {
  361. // wordperfect for windows 5.2 GPs if
  362. // papertype is > 0x28. so reset such
  363. // paper types to 0x1. In particular
  364. // this happens if the selected printer
  365. // is Epson LQ-510.
  366. // - nanduri
  367. LONG i = l;
  368. while(i--) {
  369. if (((LPWORD)pOutput32)[i] > 0x28) {
  370. ((LPWORD)pOutput32)[i] = 0x1;
  371. }
  372. }
  373. } // end if
  374. RtlCopyMemory(pOutput4, pOutput32, cb);
  375. break;
  376. case DC_MAXEXTENT:
  377. case DC_MINEXTENT:
  378. case DC_PAPERSIZE:
  379. LOGDEBUG(LOG_TRACE, ("Copying %d points from %0x to %0x\n", l, pOutput32, pOutput4));
  380. putpoint16(vpOutput4, l,(LPPOINT)pOutput32);
  381. break;
  382. default:
  383. LOGDEBUG(LOG_TRACE, ("Copying %d bytes from %0x to %0x\n",cb, pOutput32, pOutput4));
  384. RtlCopyMemory(pOutput4, pOutput32, cb);
  385. break;
  386. } // end switch
  387. FLUSHVDMPTR(vpOutput4, (USHORT)cb, pOutput4);
  388. FREEPSZPTR(pOutput4);
  389. } // end if
  390. free_w(pOutput32);
  391. } else
  392. l = -1;
  393. } else
  394. l = cb;
  395. } else {
  396. l = (*spoolerapis[WOW_DEVICECAPABILITIES].lpfn)(psz1,
  397. psz2,
  398. fwCap3,
  399. NULL,
  400. lpdmInput5);
  401. LOGDEBUG(LOG_TRACE, ("No Output buffer specified: Returning %d\n", l));
  402. }
  403. break;
  404. default:
  405. LOGDEBUG(LOG_TRACE, ("!!!! WG32DeviceCapabilities unhandled %d\n", fwCap3));
  406. l = -1L;
  407. break;
  408. } // end switch
  409. if (lpdmInput5) {
  410. free_w(lpdmInput5);
  411. }
  412. ExitPath:
  413. if(psz1) {
  414. free_w(psz1);
  415. }
  416. if(psz2) {
  417. free_w(psz2);
  418. }
  419. RETURN(l);
  420. }
  421. // Note: This will only load from the system32 dir
  422. BOOL LoadLibraryAndGetProcAddresses(WCHAR *name, DLLENTRYPOINTS *p, int num)
  423. {
  424. int i;
  425. HINSTANCE hInst;
  426. if (!(hInst = SafeLoadLibrary (name))) {
  427. WOW32ASSERTMSGF (FALSE, ("WOW::LoadLibraryAndGetProcAddresses: LoadLibrary ('%ls') failed.\n", name));
  428. return FALSE;
  429. }
  430. for (i = 0; i < num ; i++) {
  431. p[i].lpfn = (void *) GetProcAddress (hInst, (p[i].name));
  432. WOW32ASSERTMSGF (p[i].lpfn, ("WOW::LoadLibraryAndGetProcAddresses: GetProcAddress(%ls, '%s') failed\n", name, p[i].name));
  433. }
  434. return TRUE;
  435. }
  436. /*
  437. * "Safe" version of LoadLibrary which preserves floating-point state
  438. * across the load. This is critical on x86 because the FP state being
  439. * preserved is the 16-bit app's state. MSVCRT.DLL is one offender which
  440. * changes the Precision bits in its Dll init routine.
  441. *
  442. * 02/03/27 Added new meaning for "Safe". This Function now also assures
  443. * that the .dll being loaded will be loaded only from the sys32 dir
  444. * to prevent spoofing the .dll being loaded.
  445. */
  446. HINSTANCE SafeLoadLibrary(WCHAR *pszFileNameW)
  447. {
  448. HINSTANCE h;
  449. HINSTANCE hInst = NULL;
  450. UNICODE_STRING UnicodeFileName;
  451. #ifdef i386
  452. BYTE FpuState[108];
  453. // Save the 487 state
  454. _asm {
  455. lea ecx, [FpuState]
  456. fsave [ecx]
  457. }
  458. #endif //i386
  459. RtlInitUnicodeString(&UnicodeFileName, pszFileNameW);
  460. WOW32ASSERTMSG((pszSystemDirectory),
  461. ("WOW::SafeLoadLibrary:pszSystemDirectory == NULL!"));
  462. if(NT_SUCCESS(LdrLoadDll(pszSystemDirectoryW, NULL, &UnicodeFileName, &h))){
  463. hInst = h;
  464. }
  465. #ifdef i386
  466. // Restore the 487 state
  467. _asm {
  468. lea ecx, [FpuState]
  469. frstor [ecx]
  470. }
  471. #endif //i386
  472. return hInst;
  473. }