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.

728 lines
19 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. dosspool.c
  5. Abstract:
  6. Contains the entry points for the functions that live in a
  7. separate DLL. The entry points are made available here, but
  8. will not load the WINSPOOL.DRV until it is needed.
  9. Contains:
  10. Author:
  11. Congpa You (CongpaY) 22-Jan-1993
  12. Environment:
  13. Notes:
  14. Revision History:
  15. --*/
  16. #include <windows.h>
  17. #include <netdebug.h> // NetpAssert()
  18. #include "dosspool.h"
  19. #include "myspool.h"
  20. /*
  21. * global defines.
  22. */
  23. #define WINSPOOL_DLL_NAME TEXT("WINSPOOL.DRV")
  24. /*
  25. * global data.
  26. *
  27. * here we store handles to the MPRUI dll and pointers to the function
  28. * all of below is protect in multi threaded case with MprLoadLibSemaphore.
  29. */
  30. HINSTANCE vhWinspoolDll = NULL ;
  31. PF_ClosePrinter pfClosePrinter = NULL ;
  32. PF_EnumJobsA pfEnumJobsA = NULL ;
  33. PF_EnumPrintersA pfEnumPrintersA = NULL ;
  34. PF_GetJobA pfGetJobA = NULL ;
  35. PF_GetPrinterA pfGetPrinterA = NULL ;
  36. PF_OpenPrinterA pfOpenPrinterA = NULL ;
  37. PF_OpenPrinterW pfOpenPrinterW = NULL ;
  38. PF_SetJobA pfSetJobA = NULL ;
  39. PF_SetPrinterW pfSetPrinterW = NULL ;
  40. PF_GetPrinterDriverA pfGetPrinterDriverA = NULL;
  41. /*
  42. * global functions
  43. */
  44. BOOL MakeSureDllIsLoaded(void) ;
  45. /*******************************************************************
  46. NAME: GetFileNameA
  47. SYNOPSIS: Gets the filename part from a fully qualified path
  48. HISTORY:
  49. MuhuntS 06-Feb-1996 Created
  50. ********************************************************************/
  51. LPSTR
  52. GetFileNameA(
  53. LPSTR pPathName
  54. )
  55. {
  56. LPSTR pSlash = pPathName, pTemp;
  57. if ( pSlash ) {
  58. while ( pTemp = strchr(pSlash, '\\') )
  59. pSlash = pTemp+1;
  60. if ( !*pSlash )
  61. pSlash = NULL;
  62. NetpAssert(pSlash != NULL);
  63. }
  64. return pSlash;
  65. }
  66. /*******************************************************************
  67. NAME: GetDependentFileNameA
  68. SYNOPSIS: Gets the dependent filename to send to Win95. Normally just
  69. the file name part. But for ICM files this would be
  70. Color\<filename>
  71. HISTORY:
  72. MuhuntS 23-Apr-1997 Created
  73. ********************************************************************/
  74. LPSTR
  75. GetDependentFileNameA(
  76. LPSTR pPathName
  77. )
  78. {
  79. LPSTR pRet = GetFileNameA(pPathName), p;
  80. if (pRet)
  81. {
  82. DWORD dwLen = strlen(pRet);
  83. p = pRet+dwLen-4;
  84. if ( dwLen > 3 &&
  85. ( !_stricmp(p, ".ICM") ||
  86. !_stricmp(p, ".ICC") ) &&
  87. (p = pRet - 7) > pPathName &&
  88. !_strnicmp(p, "\\Color\\", 7) ) {
  89. pRet = p + 1;
  90. }
  91. }
  92. return pRet;
  93. }
  94. /*******************************************************************
  95. NAME: MyClosePrinter
  96. SYNOPSIS: calls thru to the superset function
  97. HISTORY:
  98. CongpaY 22-Jan-1993 Created
  99. ********************************************************************/
  100. BOOL MyClosePrinter (HANDLE hPrinter)
  101. {
  102. PF_ClosePrinter pfTemp;
  103. // if function has not been used before, get its address.
  104. if (pfClosePrinter == NULL)
  105. {
  106. // make sure DLL Is loaded
  107. if (!MakeSureDllIsLoaded())
  108. {
  109. return(FALSE) ;
  110. }
  111. pfTemp = (PF_ClosePrinter)
  112. GetProcAddress(vhWinspoolDll,
  113. "ClosePrinter") ;
  114. if (pfTemp == NULL)
  115. {
  116. return(FALSE);
  117. }
  118. else
  119. {
  120. pfClosePrinter = pfTemp;
  121. }
  122. }
  123. return ((*pfClosePrinter)(hPrinter));
  124. }
  125. /*******************************************************************
  126. NAME: MyEnumJobs
  127. SYNOPSIS: calls thru to the superset function
  128. NOTES: This is defined ANSI version. If change to UNICODE version
  129. in the future, you should change the code to make it call
  130. UNICODE version!!!
  131. HISTORY:
  132. CongpaY 22-Jan-1993 Created
  133. ********************************************************************/
  134. BOOL MyEnumJobs (HANDLE hPrinter,
  135. DWORD FirstJob,
  136. DWORD NoJobs,
  137. DWORD Level,
  138. LPBYTE pJob,
  139. DWORD cbBuf,
  140. LPDWORD pcbNeeded,
  141. LPDWORD pcReturned)
  142. {
  143. PF_EnumJobsA pfTemp;
  144. // if function has not been used before, get its address.
  145. if (pfEnumJobsA == NULL)
  146. {
  147. // make sure DLL Is loaded
  148. if (!MakeSureDllIsLoaded())
  149. {
  150. return(FALSE) ;
  151. }
  152. pfTemp = (PF_EnumJobsA)
  153. GetProcAddress(vhWinspoolDll,
  154. "EnumJobsA") ;
  155. if (pfTemp == NULL)
  156. {
  157. return(FALSE);
  158. }
  159. else
  160. {
  161. pfEnumJobsA = pfTemp;
  162. }
  163. }
  164. return ((*pfEnumJobsA)(hPrinter,
  165. FirstJob,
  166. NoJobs,
  167. Level,
  168. pJob,
  169. cbBuf,
  170. pcbNeeded,
  171. pcReturned));
  172. }
  173. /*******************************************************************
  174. NAME: MyEnumPrinters
  175. SYNOPSIS: calls thru to the superset function
  176. HISTORY:
  177. CongpaY 22-Jan-1993 Created
  178. ********************************************************************/
  179. BOOL MyEnumPrinters(DWORD Flags,
  180. LPSTR Name,
  181. DWORD Level,
  182. LPBYTE pPrinterEnum,
  183. DWORD cbBuf,
  184. LPDWORD pcbNeeded,
  185. LPDWORD pcReturned)
  186. {
  187. PF_EnumPrintersA pfTemp;
  188. // if function has not been used before, get its address.
  189. if (pfEnumPrintersA == NULL)
  190. {
  191. // make sure DLL Is loaded
  192. if (!MakeSureDllIsLoaded())
  193. {
  194. return(FALSE) ;
  195. }
  196. pfTemp = (PF_EnumPrintersA)
  197. GetProcAddress(vhWinspoolDll,
  198. "EnumPrintersA") ;
  199. if (pfTemp == NULL)
  200. {
  201. return(TRUE);
  202. }
  203. else
  204. pfEnumPrintersA = pfTemp;
  205. }
  206. return ((*pfEnumPrintersA)(Flags,
  207. Name,
  208. Level,
  209. pPrinterEnum,
  210. cbBuf,
  211. pcbNeeded,
  212. pcReturned));
  213. }
  214. /*******************************************************************
  215. NAME: MyGetJobA
  216. SYNOPSIS: calls thru to the superset function
  217. HISTORY:
  218. CongpaY 22-Jan-1993 Created
  219. ********************************************************************/
  220. BOOL MyGetJobA(HANDLE hPrinter,
  221. DWORD JobId,
  222. DWORD Level,
  223. LPBYTE pJob,
  224. DWORD cbBuf,
  225. LPDWORD pcbNeeded)
  226. {
  227. PF_GetJobA pfTemp;
  228. // if function has not been used before, get its address.
  229. if (pfGetJobA == NULL)
  230. {
  231. // make sure DLL Is loaded
  232. if (!MakeSureDllIsLoaded())
  233. {
  234. return(FALSE) ;
  235. }
  236. pfTemp = (PF_GetJobA)
  237. GetProcAddress(vhWinspoolDll,
  238. "GetJobA") ;
  239. if (pfTemp == NULL)
  240. {
  241. return(FALSE);
  242. }
  243. else
  244. pfGetJobA = pfTemp;
  245. }
  246. return ((*pfGetJobA)(hPrinter,
  247. JobId,
  248. Level,
  249. pJob,
  250. cbBuf,
  251. pcbNeeded));
  252. }
  253. /*******************************************************************
  254. NAME: MyGetPrinter
  255. SYNOPSIS: calls thru to the superset function
  256. HISTORY:
  257. CongpaY 22-Jan-1993 Created
  258. ********************************************************************/
  259. BOOL MyGetPrinter (HANDLE hPrinter,
  260. DWORD Level,
  261. LPBYTE pPrinter,
  262. DWORD cbBuf,
  263. LPDWORD pcbNeeded)
  264. {
  265. PF_GetPrinterA pfTemp;
  266. LPSTR pszDriverName = NULL;
  267. DWORD cbDriverName = 0;
  268. BOOL bRet;
  269. // if function has not been used before, get its address.
  270. if (pfGetPrinterA == NULL)
  271. {
  272. // make sure DLL Is loaded
  273. if (!MakeSureDllIsLoaded())
  274. {
  275. return(FALSE) ;
  276. }
  277. pfTemp = (PF_GetPrinterA)
  278. GetProcAddress(vhWinspoolDll,
  279. "GetPrinterA") ;
  280. if (pfTemp == NULL)
  281. {
  282. return(FALSE);
  283. }
  284. else
  285. pfGetPrinterA = pfTemp;
  286. }
  287. //
  288. // Win95 driver name could be different than NT. If it is different AND
  289. // the win95 driver with the different name is installed we want to send
  290. // that name to Win9x client
  291. //
  292. if ( Level == 2 ) {
  293. DWORD dwNeeded = 0;
  294. // Check the size of the name and make sure that we copy the printer driver name to the
  295. // beginning of the buffer. The previous code would let the GetPrinterDriver call determine
  296. // where to put it which could result in the strcpy copying data from one string on top of another
  297. // if the call used the end of the buffer like we plan on using. We address this by doing an STRNCPY to
  298. // make sure we don't start doing an infinite copy and also make sure our buffers don't overlap with
  299. // an assert.
  300. bRet = MyGetPrinterDriver(hPrinter,
  301. WIN95_ENVIRONMENT,
  302. 1,
  303. NULL,
  304. 0,
  305. &dwNeeded);
  306. if( dwNeeded <= cbBuf )
  307. {
  308. if( MyGetPrinterDriver( hPrinter,
  309. WIN95_ENVIRONMENT,
  310. 1,
  311. pPrinter,
  312. dwNeeded,
  313. pcbNeeded ))
  314. {
  315. pszDriverName = ((LPDRIVER_INFO_1A)pPrinter)->pName;
  316. cbDriverName = (strlen(pszDriverName) + 1) * sizeof(CHAR);
  317. NetpAssert( pszDriverName + cbDriverName < pPrinter + cbBuf - cbDriverName );
  318. strncpy((LPSTR)(pPrinter + cbBuf - cbDriverName), pszDriverName, cbDriverName);
  319. pszDriverName = (LPSTR)(pPrinter + cbBuf - cbDriverName);
  320. } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  321. {
  322. //
  323. // DRIVER_INFO_1 has pDriverName only. So if we fail with
  324. // insufficient buffer GetPrinter is guaranteed to fail too.
  325. // If we use a different level that may not be TRUE
  326. //
  327. cbDriverName = *pcbNeeded - sizeof(DRIVER_INFO_1A);
  328. }
  329. }
  330. else
  331. {
  332. cbDriverName = dwNeeded - sizeof(DRIVER_INFO_1A);
  333. }
  334. }
  335. if( cbBuf > cbDriverName )
  336. {
  337. bRet = pfGetPrinterA(hPrinter, Level, pPrinter, cbBuf-cbDriverName, pcbNeeded);
  338. }
  339. else
  340. {
  341. bRet = pfGetPrinterA(hPrinter, Level, pPrinter, 0, pcbNeeded);
  342. }
  343. if ( Level != 2 )
  344. return bRet;
  345. if ( bRet ) {
  346. if ( pszDriverName ) {
  347. ((LPPRINTER_INFO_2A)pPrinter)->pDriverName = pszDriverName;
  348. *pcbNeeded += cbDriverName;
  349. }
  350. } else if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
  351. *pcbNeeded += cbDriverName;
  352. }
  353. return bRet;
  354. }
  355. /*******************************************************************
  356. NAME: MyOpenPrinterA
  357. SYNOPSIS: calls thru to the superset function
  358. HISTORY:
  359. CongpaY 22-Jan-1993 Created
  360. ********************************************************************/
  361. BOOL MyOpenPrinterA(LPSTR pPrinterName,
  362. LPHANDLE phPrinter,
  363. LPPRINTER_DEFAULTSA pDefault)
  364. {
  365. PF_OpenPrinterA pfTemp;
  366. // if function has not been used before, get its address.
  367. if (pfOpenPrinterA == NULL)
  368. {
  369. // make sure DLL Is loaded
  370. if (!MakeSureDllIsLoaded())
  371. {
  372. return(FALSE) ;
  373. }
  374. pfTemp = (PF_OpenPrinterA)
  375. GetProcAddress(vhWinspoolDll,
  376. "OpenPrinterA") ;
  377. if (pfTemp == NULL)
  378. {
  379. return(FALSE);
  380. }
  381. else
  382. pfOpenPrinterA = pfTemp;
  383. }
  384. return ((*pfOpenPrinterA)(pPrinterName,
  385. phPrinter,
  386. pDefault));
  387. }
  388. /*******************************************************************
  389. NAME: MyOpenPrinterW
  390. SYNOPSIS: calls thru to the superset function
  391. HISTORY:
  392. CongpaY 22-Jan-1993 Created
  393. ********************************************************************/
  394. BOOL MyOpenPrinterW (LPWSTR pPrinterName,
  395. LPHANDLE phPrinter,
  396. LPPRINTER_DEFAULTSW pDefault)
  397. {
  398. PF_OpenPrinterW pfTemp;
  399. // if function has not been used before, get its address.
  400. if (pfOpenPrinterW == NULL)
  401. {
  402. // make sure DLL Is loaded
  403. if (!MakeSureDllIsLoaded())
  404. {
  405. return(FALSE) ;
  406. }
  407. pfTemp = (PF_OpenPrinterW)
  408. GetProcAddress(vhWinspoolDll,
  409. "OpenPrinterW") ;
  410. if (pfTemp == NULL)
  411. {
  412. return(FALSE);
  413. }
  414. else
  415. pfOpenPrinterW = pfTemp;
  416. }
  417. return ((*pfOpenPrinterW)(pPrinterName,
  418. phPrinter,
  419. pDefault));
  420. }
  421. /*******************************************************************
  422. NAME: MySetJobA
  423. SYNOPSIS: calls thru to the superset function
  424. HISTORY:
  425. CongpaY 22-Jan-1993 Created
  426. AlbertT 24-Mar-1995 AddedLevel and pJob
  427. ********************************************************************/
  428. BOOL MySetJobA (HANDLE hPrinter,
  429. DWORD JobId,
  430. DWORD Level,
  431. LPBYTE pJob,
  432. DWORD Command)
  433. {
  434. PF_SetJobA pfTemp;
  435. // if function has not been used before, get its address.
  436. if (pfSetJobA == NULL)
  437. {
  438. // make sure DLL Is loaded
  439. if (!MakeSureDllIsLoaded())
  440. {
  441. return(FALSE) ;
  442. }
  443. pfTemp = (PF_SetJobA)
  444. GetProcAddress(vhWinspoolDll,
  445. "SetJobA") ;
  446. if (pfTemp == NULL)
  447. {
  448. return(FALSE);
  449. }
  450. else
  451. pfSetJobA = pfTemp;
  452. }
  453. return ((*pfSetJobA)(hPrinter,
  454. JobId,
  455. Level,
  456. pJob,
  457. Command));
  458. }
  459. /*******************************************************************
  460. NAME: MySetPrinterW
  461. SYNOPSIS: calls thru to the superset function
  462. HISTORY:
  463. AlbertT 23-Mar-1995 Created
  464. ********************************************************************/
  465. BOOL MySetPrinterW(HANDLE hPrinter,
  466. DWORD Level,
  467. LPBYTE pPrinter,
  468. DWORD Command)
  469. {
  470. PF_SetPrinterW pfTemp;
  471. // if function has not been used before, get its address.
  472. if (pfSetPrinterW == NULL)
  473. {
  474. // make sure DLL Is loaded
  475. if (!MakeSureDllIsLoaded())
  476. {
  477. return(FALSE) ;
  478. }
  479. pfTemp = (PF_SetPrinterW)
  480. GetProcAddress(vhWinspoolDll,
  481. "SetPrinterW") ;
  482. if (pfTemp == NULL)
  483. {
  484. return(FALSE);
  485. }
  486. else
  487. pfSetPrinterW = pfTemp;
  488. }
  489. return ((*pfSetPrinterW)(hPrinter,
  490. Level,
  491. pPrinter,
  492. Command));
  493. }
  494. /*******************************************************************
  495. NAME: MyGetPrinterDriver
  496. SYNOPSIS: calls thru to the superset function
  497. HISTORY:
  498. MuhuntS 06-Feb-1996 Created
  499. ********************************************************************/
  500. BOOL
  501. MyGetPrinterDriver(
  502. HANDLE hPrinter,
  503. LPSTR pEnvironment,
  504. DWORD Level,
  505. LPBYTE pDriver,
  506. DWORD cbBuf,
  507. LPDWORD pcbNeeded
  508. )
  509. {
  510. //
  511. // if function has not been used before, get its address.
  512. //
  513. if ( !pfGetPrinterDriverA ) {
  514. //
  515. // If dll is not loaded yet load it
  516. //
  517. if ( !MakeSureDllIsLoaded() ) {
  518. return FALSE;
  519. }
  520. (FARPROC) pfGetPrinterDriverA = GetProcAddress(vhWinspoolDll,
  521. "GetPrinterDriverA");
  522. if ( !pfGetPrinterDriverA )
  523. return FALSE;
  524. }
  525. return ((*pfGetPrinterDriverA)(hPrinter,
  526. pEnvironment,
  527. Level,
  528. pDriver,
  529. cbBuf,
  530. pcbNeeded));
  531. }
  532. /*******************************************************************
  533. NAME: MakeSureDllIsLoaded
  534. SYNOPSIS: loads the WINSPOOL dll if need.
  535. EXIT: returns TRUE if dll already loaded, or loads
  536. successfully. Returns false otherwise. Caller
  537. should call GetLastError() to determine error.
  538. NOTES: it is up to the caller to call EnterLoadLibCritSect
  539. before he calls this.
  540. HISTORY:
  541. chuckc 29-Jul-1992 Created
  542. congpay 22-Jan-1993 Modified.
  543. ********************************************************************/
  544. BOOL MakeSureDllIsLoaded(void)
  545. {
  546. HINSTANCE handle ;
  547. // if already load, just return TRUE
  548. if (vhWinspoolDll != NULL)
  549. return TRUE ;
  550. // load the library. if it fails, it would have done a SetLastError.
  551. handle = LoadLibrary(WINSPOOL_DLL_NAME);
  552. if (handle == NULL)
  553. return FALSE ;
  554. // we are cool.
  555. vhWinspoolDll = handle ;
  556. return TRUE ;
  557. }