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.

635 lines
16 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WSPOOL.C
  8. * WOW32 printer spooler support routines
  9. *
  10. * These routines help a Win 3.0 task to use the print spooler apis. These
  11. * apis were exposed by DDK in Win 3.1.
  12. *
  13. * History:
  14. * Created 1-July-1993 by Chandan Chauhan (ChandanC)
  15. *
  16. --*/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. #include <winspool.h>
  20. extern WORD gUser16hInstance;
  21. VOID WOWSpoolerThread(WOWSPOOL *lpwowSpool);
  22. WORD gprn16 = 0x100; // Global spooler job # (can be anything > 0)
  23. MODNAME(wspool.c);
  24. LPDEVMODE GetDefaultDevMode32(LPSTR szDriver)
  25. {
  26. LONG cbDevMode;
  27. LPDEVMODE lpDevMode = NULL;
  28. if (szDriver != NULL) {
  29. if (!(spoolerapis[WOW_EXTDEVICEMODE].lpfn)) {
  30. if (!LoadLibraryAndGetProcAddresses(L"WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  31. goto LeaveGetDefaultDevMode32;
  32. }
  33. }
  34. if ((cbDevMode = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(NULL, NULL, NULL, szDriver, NULL, NULL, NULL, 0)) > 0) {
  35. if ((lpDevMode = (LPDEVMODE) malloc_w(cbDevMode)) != NULL) {
  36. if ((*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(NULL, NULL, lpDevMode, szDriver, NULL, NULL, NULL, DM_COPY) != IDOK) {
  37. free_w(lpDevMode);
  38. lpDevMode = NULL;
  39. }
  40. }
  41. }
  42. LeaveGetDefaultDevMode32:
  43. if (!lpDevMode) {
  44. LOGDEBUG(0,("WOW::GetDefaultDevMode32: Unable to get default DevMode\n"));
  45. }
  46. }
  47. return(lpDevMode);
  48. }
  49. ULONG FASTCALL WG32OpenJob (PVDMFRAME pFrame)
  50. {
  51. INT len;
  52. PSZ psz1 = NULL;
  53. PSZ psz2 = NULL;
  54. PSZ pszDriver = NULL;
  55. ULONG ul=0;
  56. DOC_INFO_1 DocInfo1;
  57. HANDLE hnd;
  58. register POPENJOB16 parg16;
  59. PRINTER_DEFAULTS PrinterDefault;
  60. PPRINTER_DEFAULTS pPrinterDefault = NULL;
  61. GETARGPTR(pFrame, sizeof(OPENJOB16), parg16);
  62. // save off the 16-bit params now since this could callback into a 16-bit
  63. // fax driver & cause 16-bit memory to move.
  64. if(parg16->f1) {
  65. if(psz1 = malloc_w_strcpy_vp16to32(parg16->f1, FALSE, 0)) {
  66. len = strlen(psz1)+1;
  67. len = max(len, 40);
  68. pszDriver = malloc_w(len);
  69. }
  70. }
  71. if(parg16->f2) {
  72. psz2 = malloc_w_strcpy_vp16to32(parg16->f2, FALSE, 0);
  73. }
  74. FREEARGPTR(parg16);
  75. // all 16-bit pointers are now invalid!!
  76. // this implies that psz1 may also be bad
  77. if(!pszDriver) {
  78. goto exitpath;
  79. }
  80. if (!(spoolerapis[WOW_OpenPrinterA].lpfn)) {
  81. if (!LoadLibraryAndGetProcAddresses(L"WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  82. goto exitpath;
  83. }
  84. }
  85. if (GetDriverName(psz1, pszDriver, len)) {
  86. if((PrinterDefault.pDevMode = GetDefaultDevMode32(pszDriver)) != NULL) {
  87. PrinterDefault.pDatatype = NULL;
  88. PrinterDefault.DesiredAccess = 0;
  89. pPrinterDefault = &PrinterDefault;
  90. if ((*spoolerapis[WOW_OpenPrinterA].lpfn) (pszDriver,
  91. &hnd,
  92. pPrinterDefault)) {
  93. DocInfo1.pDocName = psz2;
  94. DocInfo1.pOutputFile = psz1;
  95. DocInfo1.pDatatype = NULL;
  96. if (ul = (*spoolerapis[WOW_StartDocPrinterA].lpfn) (hnd, 1, (LPBYTE)&DocInfo1)) {
  97. ul = GetPrn16(hnd);
  98. }
  99. else {
  100. ul = GetLastError();
  101. }
  102. }
  103. else {
  104. ul = GetLastError();
  105. }
  106. }
  107. }
  108. LOGDEBUG(0,("WOW::WG32OpenJob: ul = %x\n", ul));
  109. if (pPrinterDefault) {
  110. free_w(PrinterDefault.pDevMode);
  111. }
  112. exitpath:
  113. if(psz1) {
  114. free_w(psz1);
  115. }
  116. if(psz2) {
  117. free_w(psz2);
  118. }
  119. if(pszDriver) {
  120. free_w(pszDriver);
  121. }
  122. RETURN(ul);
  123. }
  124. ULONG FASTCALL WG32StartSpoolPage (PVDMFRAME pFrame)
  125. {
  126. ULONG ul=0;
  127. register PSTARTSPOOLPAGE16 parg16;
  128. GETARGPTR(pFrame, sizeof(STARTSPOOLPAGE16), parg16);
  129. if (!(ul = (*spoolerapis[WOW_StartPagePrinter].lpfn) (Prn32(parg16->f1)))) {
  130. ul = GetLastError();
  131. }
  132. LOGDEBUG(0,("WOW::WG32StartSpoolPage: ul = %x\n", ul));
  133. FREEARGPTR(parg16);
  134. RETURN(ul);
  135. }
  136. ULONG FASTCALL WG32EndSpoolPage (PVDMFRAME pFrame)
  137. {
  138. ULONG ul=0;
  139. register PENDSPOOLPAGE16 parg16;
  140. GETARGPTR(pFrame, sizeof(ENDSPOOLPAGE16), parg16);
  141. if (!(ul = (*spoolerapis[WOW_EndPagePrinter].lpfn) (Prn32(parg16->f1)))) {
  142. ul = GetLastError();
  143. }
  144. LOGDEBUG(0,("WOW::WG32EndSpoolPage: ul = %x\n", ul));
  145. FREEARGPTR(parg16);
  146. RETURN(ul);
  147. }
  148. ULONG FASTCALL WG32CloseJob (PVDMFRAME pFrame)
  149. {
  150. ULONG ul=0;
  151. register PCLOSEJOB16 parg16;
  152. GETARGPTR(pFrame, sizeof(CLOSEJOB16), parg16);
  153. if (!(ul = (*spoolerapis[WOW_EndDocPrinter].lpfn) (Prn32(parg16->f1)))) {
  154. ul = GetLastError();
  155. }
  156. if (!(ul = (*spoolerapis[WOW_ClosePrinter].lpfn) (Prn32(parg16->f1)))) {
  157. ul = GetLastError();
  158. }
  159. if (ul) {
  160. FreePrn(parg16->f1);
  161. }
  162. LOGDEBUG(0,("WOW::WG32CloseJob: ul = %x\n", ul));
  163. FREEARGPTR(parg16);
  164. RETURN(ul);
  165. }
  166. ULONG FASTCALL WG32WriteSpool (PVDMFRAME pFrame)
  167. {
  168. DWORD dwWritten;
  169. ULONG ul=0;
  170. register PWRITESPOOL16 parg16;
  171. LPVOID pBuf;
  172. GETARGPTR(pFrame, sizeof(WRITESPOOL16), parg16);
  173. GETMISCPTR (parg16->f2, pBuf);
  174. if (ul = (*spoolerapis[WOW_WritePrinter].lpfn) (Prn32(parg16->f1), pBuf,
  175. FETCHWORD(parg16->f3), &dwWritten)) {
  176. ul = FETCHWORD(parg16->f3);
  177. }
  178. else {
  179. ul = GetLastError();
  180. }
  181. LOGDEBUG(0,("WOW::WG32WriteSpool: ul = %x\n", ul));
  182. FREEMISCPTR(pBuf);
  183. FREEARGPTR(parg16);
  184. RETURN(ul);
  185. }
  186. ULONG FASTCALL WG32DeleteJob (PVDMFRAME pFrame)
  187. {
  188. ULONG ul = 0;
  189. register PDELETEJOB16 parg16;
  190. GETARGPTR(pFrame, sizeof(DELETEJOB16), parg16);
  191. if (!(ul = (*spoolerapis[WOW_DeletePrinter].lpfn) (Prn32(parg16->f1)))) {
  192. ul = GetLastError();
  193. }
  194. LOGDEBUG(0,("WOW::WG32DeleteJob: ul = %x\n", ul));
  195. FREEARGPTR(parg16);
  196. RETURN(ul);
  197. }
  198. ULONG FASTCALL WG32SpoolFile (PVDMFRAME pFrame)
  199. {
  200. INT len;
  201. PSZ psz2 = NULL;
  202. PSZ psz3 = NULL;
  203. PSZ psz4 = NULL;
  204. PSZ pszDriver = NULL;
  205. LONG ul = -1; // SP_ERROR
  206. HANDLE hFile = NULL;
  207. HANDLE hPrinter = NULL;
  208. HANDLE hThread = NULL;
  209. WOWSPOOL *lpwowSpool = NULL;
  210. DOC_INFO_1 DocInfo1;
  211. DWORD dwUnused;
  212. register PSPOOLFILE16 parg16;
  213. GETARGPTR(pFrame, sizeof(SPOOLFILE16), parg16);
  214. // save off the 16-bit params now since this could callback into a 16-bit
  215. // fax driver & cause 16-bit memory to move.
  216. // ignore psz1 (printer name)
  217. // get the port name and the associated driver name
  218. if(parg16->f2) {
  219. if(!(psz2 = malloc_w_strcpy_vp16to32(parg16->f2, FALSE, 0))) {
  220. goto exitpath;
  221. }
  222. len = strlen(psz2)+1;
  223. len = max(len, 40);
  224. if(!(pszDriver = malloc_w(len))) {
  225. goto exitpath;
  226. }
  227. if(!GetDriverName(psz2, pszDriver, len)) {
  228. goto exitpath;
  229. }
  230. }
  231. // get the Job Title
  232. if(parg16->f3) {
  233. if(!(psz3 = malloc_w_strcpy_vp16to32(parg16->f3, FALSE, 0))) {
  234. goto exitpath;
  235. }
  236. }
  237. // get the file name
  238. if(parg16->f4) {
  239. if(!(psz4 = malloc_w_strcpy_vp16to32(parg16->f4, FALSE, 0))) {
  240. goto exitpath;
  241. }
  242. }
  243. FREEARGPTR(parg16);
  244. // all 16-bit pointers are now invalid!!
  245. // all fields of this struct are initially zero
  246. if(!(lpwowSpool = (WOWSPOOL *)malloc_w_zero(sizeof(WOWSPOOL)))) {
  247. goto exitpath;
  248. }
  249. if(!(spoolerapis[WOW_OpenPrinterA].lpfn)) {
  250. if(!LoadLibraryAndGetProcAddresses(L"WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
  251. goto exitpath;
  252. }
  253. }
  254. // open the specified file
  255. if((hFile = DPM_CreateFile(psz4,
  256. GENERIC_READ,
  257. 0,
  258. NULL,
  259. OPEN_EXISTING,
  260. FILE_FLAG_SEQUENTIAL_SCAN,
  261. NULL)) == INVALID_HANDLE_VALUE) {
  262. goto exitpath;
  263. }
  264. // create the WOWSpoolerThread to handle the "spooling"
  265. if(!(hThread = CreateThread(NULL,
  266. 16384,
  267. (LPTHREAD_START_ROUTINE)WOWSpoolerThread,
  268. lpwowSpool,
  269. CREATE_SUSPENDED,
  270. (LPDWORD)&dwUnused))) {
  271. goto exitpath;
  272. }
  273. // open the printer
  274. if((*spoolerapis[WOW_OpenPrinterA].lpfn)(pszDriver, &hPrinter, NULL)) {
  275. DocInfo1.pDocName = psz3;
  276. DocInfo1.pOutputFile = NULL;
  277. DocInfo1.pDatatype = "RAW";
  278. // start a doc
  279. if(!(*spoolerapis[WOW_StartDocPrinterA].lpfn)(hPrinter,
  280. 1,
  281. (LPBYTE)&DocInfo1)) {
  282. goto ClosePrinter;
  283. }
  284. // start a page
  285. if((*spoolerapis[WOW_StartPagePrinter].lpfn)(hPrinter)) {
  286. // tell the WOWSpoolerThread that it's OK to do its thing
  287. lpwowSpool->fOK = TRUE;
  288. lpwowSpool->hFile = hFile;
  289. lpwowSpool->hPrinter = hPrinter;
  290. lpwowSpool->prn16 = gprn16;
  291. // tell the app that everything is hunky dory
  292. ul = (LONG)gprn16++;
  293. // make sure this doesn't go negative (-> an error ret to the app)
  294. if(gprn16 & 0x8000) {
  295. gprn16 = 0x100;
  296. }
  297. }
  298. // error path
  299. else {
  300. (*spoolerapis[WOW_EndDocPrinter].lpfn) (hPrinter);
  301. ClosePrinter:
  302. // note: hPrinter is freed by WOW_ClosePrinter
  303. (*spoolerapis[WOW_ClosePrinter].lpfn) (hPrinter);
  304. }
  305. }
  306. exitpath:
  307. LOGDEBUG(2,("WOW::WG32SpoolFile: ul = %x\n", ul));
  308. if(psz2) {
  309. free_w(psz2);
  310. }
  311. if(psz3) {
  312. free_w(psz3);
  313. }
  314. if(psz4) {
  315. free_w(psz4);
  316. }
  317. if(pszDriver) {
  318. free_w(pszDriver);
  319. }
  320. // give the spooler thread a kick start then close the thread handle
  321. // (note: the thread will still be active)
  322. if(hThread) {
  323. ResumeThread(hThread);
  324. CloseHandle(hThread);
  325. }
  326. // clean up if there was an error -- otherwise the thread will clean up
  327. if(ul == -1) {
  328. if(hFile) {
  329. DPM_CloseHandle(hFile);
  330. }
  331. if(lpwowSpool) {
  332. free_w(lpwowSpool);
  333. }
  334. // note: hPrinter is freed by WOW_ClosePrinter
  335. }
  336. return((ULONG)ul);
  337. }
  338. #define SPOOL_BUFF_SIZE 4096
  339. VOID WOWSpoolerThread(WOWSPOOL *lpwowSpool)
  340. {
  341. DWORD dwBytes;
  342. DWORD dwWritten;
  343. BYTE buf[SPOOL_BUFF_SIZE];
  344. // this thread will only do something if fOK is TRUE
  345. if(lpwowSpool && lpwowSpool->fOK) {
  346. do {
  347. // this is a sequential read
  348. if(DPM_ReadFile(lpwowSpool->hFile, buf, SPOOL_BUFF_SIZE, &dwBytes, NULL)) {
  349. // if dwBytes==0 --> EOF
  350. if(dwBytes) {
  351. //
  352. if(!(*spoolerapis[WOW_WritePrinter].lpfn)(lpwowSpool->hPrinter,
  353. buf,
  354. dwBytes,
  355. &dwWritten)) {
  356. LOGDEBUG(0,("WOW::WOWSpoolerThread:WritePrinter ERROR!\n"));
  357. break;
  358. }
  359. else if(dwBytes != dwWritten) {
  360. LOGDEBUG(0,("WOW::WOWSpoolerThread:WritePrinter error!\n"));
  361. break;
  362. }
  363. }
  364. }
  365. } while (dwBytes == SPOOL_BUFF_SIZE);
  366. // shut down the print job
  367. (*spoolerapis[WOW_EndPagePrinter].lpfn) (lpwowSpool->hPrinter);
  368. (*spoolerapis[WOW_EndDocPrinter].lpfn) (lpwowSpool->hPrinter);
  369. // note: hPrinter is freed by WOW_ClosePrinter
  370. (*spoolerapis[WOW_ClosePrinter].lpfn) (lpwowSpool->hPrinter);
  371. // clean up
  372. if(lpwowSpool->hFile) {
  373. DPM_CloseHandle(lpwowSpool->hFile);
  374. }
  375. if(lpwowSpool) {
  376. free_w(lpwowSpool);
  377. }
  378. } // end if
  379. ExitThread(0);
  380. }
  381. WORD GetPrn16(HANDLE h32)
  382. {
  383. HANDLE hnd;
  384. VPVOID vp;
  385. LPBYTE lpMem16;
  386. hnd = LocalAlloc16(LMEM_MOVEABLE, sizeof(HANDLE), (HANDLE) gUser16hInstance);
  387. vp = LocalLock16(hnd);
  388. if (vp) {
  389. GETMISCPTR (vp, lpMem16);
  390. if (lpMem16) {
  391. *((PDWORD16)lpMem16) = (DWORD) h32;
  392. FREEMISCPTR(lpMem16);
  393. LocalUnlock16(hnd);
  394. }
  395. }
  396. else {
  397. LOGDEBUG (0, ("WOW::GETPRN16: Can't allocate a 16 bit handle\n"));
  398. }
  399. return (LOWORD(hnd));
  400. }
  401. HANDLE Prn32(WORD h16)
  402. {
  403. VPVOID vp;
  404. HANDLE h32 = NULL;
  405. LPBYTE lpMem16;
  406. vp = LocalLock16 ((HANDLE) MAKELONG(h16, gUser16hInstance));
  407. if (vp) {
  408. GETMISCPTR (vp, lpMem16);
  409. if (lpMem16) {
  410. h32 = (HANDLE) *((PDWORD16)lpMem16);
  411. FREEMISCPTR(lpMem16);
  412. }
  413. LocalUnlock16 ((HANDLE) MAKELONG(h16, gUser16hInstance));
  414. }
  415. return (h32);
  416. }
  417. VOID FreePrn (WORD h16)
  418. {
  419. LocalFree16 ((HANDLE) MAKELONG(h16, gUser16hInstance));
  420. }
  421. BOOL GetDriverName (char *psz, char *pszDriver, int cbDriver)
  422. {
  423. CHAR szAllDevices[1024];
  424. CHAR *szNextDevice;
  425. CHAR szPrinter[64];
  426. CHAR *szOutput;
  427. UINT len;
  428. if(!psz || (*psz == '\0')) {
  429. return FALSE;
  430. }
  431. len = strlen(psz);
  432. szAllDevices[0]='\0';
  433. GetProfileString ("devices", NULL, "", szAllDevices, sizeof(szAllDevices));
  434. szNextDevice = szAllDevices;
  435. LOGDEBUG(6,("WOW::GetDriverName: szAllDevices = %s\n", szAllDevices));
  436. // strings from win.ini will be of the form "PS Printer=PSCRIPT,LPT1:"
  437. while (*szNextDevice) {
  438. szPrinter[0]='\0';
  439. GetProfileString ("devices", szNextDevice, "", szPrinter, sizeof(szPrinter));
  440. if (*szPrinter) {
  441. if (szOutput = WOW32_strchr (szPrinter, ',')) {
  442. szOutput++;
  443. while (*szOutput == ' ') {
  444. szOutput++;
  445. }
  446. if (!WOW32_stricmp(psz, szOutput)) {
  447. break; // found it!
  448. }
  449. // some apps pass "LPT1" without the ':' -- account for that
  450. // if the app passed "LPT1" and ...
  451. if (psz[len-1] != ':') {
  452. // ...strlen(szOutput) == 5 && szOutput[4] == ':' ...
  453. if((strlen(szOutput) == len+1) && (szOutput[len] == ':')) {
  454. // ...clobber the ':' char ...
  455. szOutput[len] = '\0';
  456. // ...and see if the strings match now
  457. if (!WOW32_stricmp(psz, szOutput)) {
  458. break; // found it!
  459. }
  460. }
  461. }
  462. }
  463. }
  464. if (szNextDevice = WOW32_strchr (szNextDevice, '\0')) {
  465. szNextDevice++;
  466. }
  467. else {
  468. szNextDevice = "";
  469. break;
  470. }
  471. }
  472. if (*szNextDevice) {
  473. LOGDEBUG(0,("WOW::GetDriverName: szNextDevice = %s\n", szNextDevice));
  474. if (lstrcpyn (pszDriver, szNextDevice, cbDriver)) {
  475. pszDriver[cbDriver-1] = '\0';
  476. return TRUE;
  477. }
  478. }
  479. // else they may have specified a network printer eg. "\\msprint44\corpk"
  480. // in which case we'll assume it's all right (since it will fail once the
  481. // WOW functions that call into this will fail when they call into the
  482. // driver with a bogus driver name)
  483. if(psz[0] == '\\' && psz[1] == '\\') {
  484. strncpy(pszDriver, psz, cbDriver);
  485. pszDriver[cbDriver-1] = '\0';
  486. return TRUE;
  487. }
  488. return FALSE;
  489. }