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.

605 lines
14 KiB

  1. /*++
  2. Copyright (c) 1990-1992 Microsoft Corporation
  3. Module Name:
  4. local.c
  5. Abstract:
  6. This module provides all the public exported APIs relating to Printer
  7. and Job management for the Local Print Providor
  8. Author:
  9. Dave Snipp (DaveSn) 15-Mar-1991
  10. Revision History:
  11. 16-Jun-1992 JohnRo
  12. RAID 10324: net print vs. UNICODE.
  13. --*/
  14. #include "precomp.h"
  15. BOOL
  16. LMSetJob(
  17. HANDLE hPrinter,
  18. DWORD JobId,
  19. DWORD Level,
  20. LPBYTE pJob,
  21. DWORD Command
  22. )
  23. /*++
  24. Routine Description:
  25. This function will modify the settings of the specified Print Job.
  26. Arguments:
  27. lpJob - Points to a valid JOB structure containing at least a valid
  28. lpPrinter, and JobId.
  29. Command - Specifies the operation to perform on the specified Job. A value
  30. of FALSE indicates that only the elements of the JOB structure are to
  31. be examined and set.
  32. Return Value:
  33. TRUE - The operation was successful.
  34. FALSE/NULL - The operation failed. Extended error status is available
  35. using GetLastError.
  36. --*/
  37. {
  38. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  39. DWORD uRetCode;
  40. LPWSTR pszDocument;
  41. LPWSTR pszDatatype;
  42. VALIDATEW32HANDLE( pSpool );
  43. switch (Command) {
  44. case 0:
  45. break;
  46. case JOB_CONTROL_PAUSE:
  47. if (uRetCode = RxPrintJobPause(pSpool->pServer, JobId)) {
  48. SetLastError(uRetCode);
  49. return(FALSE);
  50. }
  51. break;
  52. case JOB_CONTROL_RESUME:
  53. if (uRetCode = RxPrintJobContinue(pSpool->pServer, JobId)) {
  54. SetLastError(uRetCode);
  55. return(FALSE);
  56. }
  57. break;
  58. case JOB_CONTROL_CANCEL:
  59. case JOB_CONTROL_DELETE:
  60. if (uRetCode = RxPrintJobDel(pSpool->pServer, JobId)) {
  61. SetLastError(uRetCode);
  62. return(FALSE);
  63. }
  64. break;
  65. case JOB_CONTROL_RESTART:
  66. break;
  67. default:
  68. SetLastError(ERROR_INVALID_PARAMETER);
  69. return FALSE;
  70. }
  71. // We only support setting of the document name on SetJob to OS/2.
  72. switch (Level) {
  73. case 0:
  74. break;
  75. case 1:
  76. case 2:
  77. switch (Level) {
  78. case 1:
  79. pszDatatype = ((JOB_INFO_1 *)pJob)->pDatatype;
  80. pszDocument = ((JOB_INFO_1 *)pJob)->pDocument;
  81. break;
  82. case 2:
  83. pszDatatype = ((JOB_INFO_2 *)pJob)->pDatatype;
  84. pszDocument = ((JOB_INFO_2 *)pJob)->pDocument;
  85. break;
  86. }
  87. //
  88. // If the datatype is non-NULL and anything other than
  89. // a RAW datatype, then fail.
  90. //
  91. if( pszDatatype && !ValidRawDatatype( pszDatatype )){
  92. SetLastError( ERROR_INVALID_DATATYPE );
  93. return FALSE;
  94. }
  95. //
  96. // Special handling for pszDocument == NULL
  97. // if pszDocument == NULL, set it to a pointer to ""
  98. //
  99. if (pszDocument == NULL)
  100. pszDocument = L"";
  101. else
  102. {
  103. if(wcslen(pszDocument) > (MAX_PATH-1))
  104. {
  105. SetLastError( ERROR_INVALID_PARAMETER );
  106. return (FALSE);
  107. }
  108. }
  109. if (uRetCode = RxPrintJobSetInfo(pSpool->pServer,
  110. JobId,
  111. 3,
  112. (PBYTE)pszDocument,
  113. wcslen(pszDocument)*sizeof(WCHAR) +
  114. sizeof(WCHAR),
  115. PRJ_COMMENT_PARMNUM)) {
  116. SetLastError(uRetCode);
  117. return FALSE;
  118. }
  119. break;
  120. default:
  121. SetLastError(ERROR_INVALID_LEVEL);
  122. return FALSE;
  123. }
  124. //
  125. // We successfully performed a 'LMSetJob' - pulse the ChangeEvent
  126. // or send the notification.
  127. //
  128. LMSetSpoolChange(pSpool);
  129. return TRUE;
  130. }
  131. #define Nullstrlen(psz) ((psz) ? wcslen(psz)*sizeof(WCHAR)+sizeof(WCHAR) : 0)
  132. DWORD
  133. GetPrjInfoSize(
  134. PWSPOOL pSpool,
  135. DWORD Level,
  136. PRJINFO *pPrjInfo
  137. )
  138. {
  139. DWORD cb;
  140. switch (Level) {
  141. case 1:
  142. cb = sizeof(JOB_INFO_1) +
  143. wcslen(pSpool->pShare)*sizeof(WCHAR) + sizeof(WCHAR) +
  144. Nullstrlen(pPrjInfo->szUserName) +
  145. Nullstrlen(pPrjInfo->pszComment) +
  146. Nullstrlen(pPrjInfo->pszStatus);
  147. break;
  148. case 2:
  149. cb = sizeof(JOB_INFO_2) +
  150. wcslen(pSpool->pShare)*sizeof(WCHAR) + sizeof(WCHAR) +
  151. Nullstrlen(pPrjInfo->szUserName) +
  152. Nullstrlen(pPrjInfo->pszComment) +
  153. Nullstrlen(pPrjInfo->szNotifyName) +
  154. Nullstrlen(pPrjInfo->szDataType) +
  155. Nullstrlen(pPrjInfo->pszParms) +
  156. Nullstrlen(pPrjInfo->pszStatus);
  157. break;
  158. default:
  159. cb = 0;
  160. break;
  161. }
  162. return cb;
  163. }
  164. BOOL
  165. ConvertDosTimeToSystemTime(
  166. ULONG Time,
  167. PSYSTEMTIME pst
  168. )
  169. {
  170. LARGE_INTEGER li;
  171. FILETIME ft;
  172. li.QuadPart = Time;
  173. li.QuadPart += 11644473600;
  174. li.QuadPart *= 10000000;
  175. ft.dwLowDateTime = li.LowPart;
  176. ft.dwHighDateTime = li.HighPart;
  177. return FileTimeToSystemTime( &ft, pst );
  178. }
  179. LPBYTE
  180. CopyPrjInfoToJob(
  181. PWSPOOL pSpool,
  182. PRJINFO *pPrjInfo,
  183. DWORD Level,
  184. LPBYTE pJobInfo,
  185. LPBYTE pEnd
  186. )
  187. {
  188. LPWSTR *pSourceStrings, *SourceStrings;
  189. LPJOB_INFO_2 pJob = (PJOB_INFO_2)pJobInfo;
  190. LPJOB_INFO_2 pJob2 = (PJOB_INFO_2)pJobInfo;
  191. LPJOB_INFO_1 pJob1 = (PJOB_INFO_1)pJobInfo;
  192. DWORD i, Status;
  193. DWORD *pOffsets;
  194. switch (Level) {
  195. case 1:
  196. pOffsets = JobInfo1Strings;
  197. break;
  198. case 2:
  199. pOffsets = JobInfo2Strings;
  200. break;
  201. default:
  202. return pEnd;
  203. }
  204. switch (pPrjInfo->fsStatus) {
  205. case PRJ_QS_PAUSED:
  206. Status = JOB_STATUS_PAUSED;
  207. break;
  208. case PRJ_QS_SPOOLING:
  209. Status = JOB_STATUS_SPOOLING;
  210. break;
  211. case PRJ_QS_PRINTING:
  212. Status = JOB_STATUS_PRINTING;
  213. break;
  214. default:
  215. Status = 0;
  216. break;
  217. }
  218. for (i=0; pOffsets[i] != -1; i++) {
  219. }
  220. SourceStrings = pSourceStrings = AllocSplMem(i * sizeof(LPWSTR));
  221. if (!SourceStrings)
  222. return NULL;
  223. switch (Level) {
  224. case 1:
  225. *pSourceStrings++=pSpool->pShare;
  226. *pSourceStrings++=NULL;
  227. *pSourceStrings++=pPrjInfo->szUserName;
  228. *pSourceStrings++=pPrjInfo->pszComment;
  229. *pSourceStrings++=NULL;
  230. if (pPrjInfo->pszStatus && *pPrjInfo->pszStatus)
  231. *pSourceStrings++=pPrjInfo->pszStatus;
  232. else
  233. *pSourceStrings++=NULL;
  234. /* PRJINFO doesn't contain uPriority.
  235. * PRJINFO2 does, but doesn't contain some of the things
  236. * that PRJINFO has.
  237. * We'd need to pass a PRJINFO3 structure to get everything we need,
  238. * but DosPrintJobEnum doesn't support level 3.
  239. * For now, set it to 0. Print Manager will display nothing for this.
  240. */
  241. pJob1->Priority=0;
  242. pJob1->Position=pPrjInfo->uPosition;
  243. pJob1->Status=Status;
  244. pJob1->JobId = pPrjInfo->uJobId;
  245. break;
  246. case 2:
  247. *pSourceStrings++=pSpool->pShare;
  248. *pSourceStrings++=NULL;
  249. *pSourceStrings++=pPrjInfo->szUserName;
  250. *pSourceStrings++=pPrjInfo->pszComment;
  251. *pSourceStrings++=pPrjInfo->szNotifyName;
  252. *pSourceStrings++=pPrjInfo->szDataType;
  253. *pSourceStrings++=NULL;
  254. *pSourceStrings++=pPrjInfo->pszParms;
  255. *pSourceStrings++=NULL;
  256. if (pPrjInfo->pszStatus && *pPrjInfo->pszStatus)
  257. *pSourceStrings++=pPrjInfo->pszStatus;
  258. else
  259. *pSourceStrings++=NULL;
  260. pJob2->pDevMode=0;
  261. pJob2->Priority=0;
  262. pJob2->Position=pPrjInfo->uPosition;
  263. pJob2->StartTime=0;
  264. pJob2->UntilTime=0;
  265. pJob2->TotalPages=0;
  266. pJob2->Size=pPrjInfo->ulSize;
  267. ConvertDosTimeToSystemTime(pPrjInfo->ulSubmitted, &pJob2->Submitted);
  268. memset((LPBYTE)&pJob2->Time, 0, sizeof(pJob2->Time));
  269. pJob2->Status=Status;
  270. pJob2->JobId = pPrjInfo->uJobId;
  271. break;
  272. default:
  273. return pEnd;
  274. }
  275. pEnd = PackStrings(SourceStrings, pJobInfo, pOffsets, pEnd);
  276. FreeSplMem(SourceStrings);
  277. return pEnd;
  278. }
  279. BOOL
  280. LMGetJob(
  281. HANDLE hPrinter,
  282. DWORD JobId,
  283. DWORD Level,
  284. LPBYTE pJob,
  285. DWORD cbBuf,
  286. LPDWORD pcbNeeded
  287. )
  288. /*++
  289. Routine Description:
  290. This function will retrieve the settings of the specified Print Job.
  291. Arguments:
  292. lpJob - Points to a valid JOB structure containing at least a valid
  293. lpPrinter, and JobId.
  294. Return Value:
  295. TRUE - The operation was successful.
  296. FALSE/NULL - The operation failed. Extended error status is available
  297. using GetLastError.
  298. --*/
  299. {
  300. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  301. PPRJINFO pPrjInfo;
  302. PPRQINFO pPrqInfo;
  303. DWORD cbBuffer;
  304. DWORD rc;
  305. DWORD cbNeeded;
  306. DWORD cb;
  307. DWORD cJobs;
  308. VALIDATEW32HANDLE( pSpool );
  309. //
  310. // Fail if out of range.
  311. //
  312. if (JobId > (WORD)-1) {
  313. SetLastError(ERROR_INVALID_PARAMETER);
  314. return FALSE;
  315. }
  316. cbBuffer = 100;
  317. if (!(pPrjInfo = AllocSplMem(cbBuffer)))
  318. return FALSE;
  319. rc = RxPrintJobGetInfo(pSpool->pServer,
  320. (WORD)JobId,
  321. 1,
  322. (PBYTE)pPrjInfo,
  323. cbBuffer,
  324. &cbNeeded);
  325. if (rc == ERROR_MORE_DATA || rc == NERR_BufTooSmall) {
  326. if (!(pPrjInfo=ReallocSplMem(pPrjInfo, 0, cbNeeded)))
  327. return FALSE;
  328. cbBuffer=cbNeeded;
  329. if (rc = RxPrintJobGetInfo(pSpool->pServer,
  330. (WORD)JobId,
  331. 1,
  332. (PBYTE)pPrjInfo,
  333. cbBuffer,
  334. &cbNeeded)) {
  335. FreeSplMem(pPrjInfo);
  336. SetLastError(rc);
  337. return FALSE;
  338. }
  339. } else {
  340. //
  341. // Free the buffer.
  342. //
  343. FreeSplMem(pPrjInfo);
  344. if (rc == ERROR_NOT_SUPPORTED) {
  345. cbBuffer = 64*1024;
  346. if (!(pPrqInfo = AllocSplMem(cbBuffer)))
  347. return FALSE;
  348. if (!(rc = RxPrintQGetInfo(pSpool->pServer,
  349. pSpool->pShare,
  350. 2,
  351. (PBYTE)pPrqInfo,
  352. cbBuffer,
  353. &cbNeeded))) {
  354. rc = ERROR_INVALID_PARAMETER;
  355. cJobs = (DWORD)pPrqInfo->cJobs;
  356. for (pPrjInfo = (PRJINFO *)(pPrqInfo+1);
  357. cJobs;
  358. cJobs--, pPrjInfo++) {
  359. if (JobId == (DWORD)pPrjInfo->uJobId) {
  360. cb = GetPrjInfoSize(pSpool, Level, pPrjInfo);
  361. if (cb <= cbBuf) {
  362. CopyPrjInfoToJob(pSpool,
  363. pPrjInfo,
  364. Level,
  365. pJob,
  366. pJob + cbBuf);
  367. rc = ERROR_SUCCESS;
  368. } else {
  369. *pcbNeeded=cb;
  370. rc = ERROR_INSUFFICIENT_BUFFER;
  371. }
  372. }
  373. }
  374. }
  375. FreeSplMem(pPrqInfo);
  376. }
  377. if (rc) {
  378. SetLastError(rc);
  379. return FALSE;
  380. }
  381. return TRUE;
  382. }
  383. cb=GetPrjInfoSize(pSpool, Level, pPrjInfo);
  384. *pcbNeeded=cb;
  385. if (cb > cbBuf) {
  386. FreeSplMem(pPrjInfo);
  387. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  388. return FALSE;
  389. }
  390. if (CopyPrjInfoToJob(pSpool, pPrjInfo, Level, pJob, (LPBYTE)pJob+cbBuf)) {
  391. FreeSplMem(pPrjInfo);
  392. return TRUE;
  393. } else {
  394. FreeSplMem(pPrjInfo);
  395. return FALSE;
  396. }
  397. }
  398. /* Get all the Job Ids first, then get individual info on each */
  399. BOOL
  400. LMEnumJobs(
  401. HANDLE hPrinter,
  402. DWORD FirstJob,
  403. DWORD NoJobs,
  404. DWORD Level,
  405. LPBYTE pJob,
  406. DWORD cbBuf,
  407. LPDWORD pcbNeeded,
  408. LPDWORD pcReturned
  409. )
  410. {
  411. PPRJINFO pPrjInfo;
  412. PPRQINFO pPrqInfo;
  413. DWORD rc=0;
  414. DWORD cb=0;
  415. DWORD cJobs;
  416. DWORD cbNeeded;
  417. LPBYTE pEnd;
  418. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  419. DWORD cbBuffer = 100;
  420. VALIDATEW32HANDLE( pSpool );
  421. cbBuffer = 64*1024;
  422. pEnd = pJob + cbBuf;
  423. if (!(pPrqInfo = AllocSplMem(cbBuffer)))
  424. return FALSE;
  425. *pcReturned=0;
  426. if (!(rc = RxPrintQGetInfo(pSpool->pServer, pSpool->pShare, 2,
  427. (PBYTE)pPrqInfo, cbBuffer, &cbNeeded))) {
  428. pPrjInfo = (PRJINFO *)(pPrqInfo+1);
  429. if (FirstJob > pPrqInfo->cJobs) {
  430. FreeSplMem(pPrqInfo);
  431. return TRUE;
  432. }
  433. cJobs = (DWORD)min(NoJobs, pPrqInfo->cJobs - FirstJob);
  434. for (pPrjInfo=pPrjInfo+FirstJob; cJobs; cJobs--, pPrjInfo++) {
  435. cb+=GetPrjInfoSize(pSpool, Level, pPrjInfo);
  436. if (cb <= cbBuf) {
  437. pEnd = CopyPrjInfoToJob(pSpool, pPrjInfo, Level, pJob, pEnd);
  438. (*pcReturned)++;
  439. switch (Level) {
  440. case 1:
  441. pJob+=sizeof(JOB_INFO_1);
  442. break;
  443. case 2:
  444. pJob+=sizeof(JOB_INFO_2);
  445. break;
  446. }
  447. } else
  448. rc=ERROR_INSUFFICIENT_BUFFER;
  449. }
  450. }
  451. FreeSplMem(pPrqInfo);
  452. *pcbNeeded=cb;
  453. if (rc) {
  454. SetLastError(rc);
  455. return FALSE;
  456. }
  457. return TRUE;
  458. }