Source code of Windows XP (NT5)
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.

716 lines
16 KiB

  1. /*****************************************************************************\
  2. * MODULE: splpjm.c
  3. *
  4. * This module contains the routines to deal with job-mapping list.
  5. *
  6. *
  7. * Copyright (C) 1996-1997 Microsoft Corporation
  8. * Copyright (C) 1996-1997 Hewlett Packard
  9. *
  10. * History:
  11. * 13-Jan-1997 ChrisWil Created.
  12. *
  13. \*****************************************************************************/
  14. #include "precomp.h"
  15. #include "priv.h"
  16. /*****************************************************************************\
  17. * pjm_OldEntry (Local Routine)
  18. *
  19. *
  20. \*****************************************************************************/
  21. _inline BOOL pjm_IsOldEntry(
  22. PJOBMAP pjm)
  23. {
  24. return !pjm->bRemoteJob && !pjmChkState(pjm, PJM_SPOOLING);
  25. }
  26. /*****************************************************************************\
  27. * pjm_IsLocalJob (Local Routine)
  28. *
  29. *
  30. \*****************************************************************************/
  31. _inline BOOL pjm_IsLocalJob(
  32. PJOBMAP pjm)
  33. {
  34. return !pjm->bRemoteJob && pjmChkState(pjm, PJM_SPOOLING);
  35. }
  36. /*****************************************************************************\
  37. * pjm_DelEntry (Local Routine)
  38. *
  39. *
  40. \*****************************************************************************/
  41. _inline VOID pjm_DelEntry(
  42. PJOBMAP pjm)
  43. {
  44. if (pjm->hSplFile)
  45. SplFree(pjm->hSplFile);
  46. if (pjm->lpszUri)
  47. memFreeStr(pjm->lpszUri);
  48. if (pjm->lpszUser)
  49. memFreeStr(pjm->lpszUser);
  50. memFree(pjm, sizeof(JOBMAP));
  51. }
  52. /*****************************************************************************\
  53. * pjmAdd
  54. *
  55. * Add a job-mapping to the list. Access to this list needs ownership of the
  56. * crit-sect.
  57. *
  58. \*****************************************************************************/
  59. PJOBMAP pjmAdd(
  60. PJOBMAP *pjmList,
  61. PCINETMONPORT pIniPort,
  62. LPCTSTR lpszUser,
  63. LPCTSTR lpszDocName)
  64. {
  65. PJOBMAP pjm = NULL;
  66. static DWORD s_idJobLocal = 0;
  67. semCheckCrit();
  68. if (pjmList) {
  69. // Add the new job-entry to the list.
  70. //
  71. if (pjm = (PJOBMAP)memAlloc(sizeof(JOBMAP))) {
  72. // Initialize our job-entry.
  73. //
  74. GetSystemTime (&pjm->SubmitTime);
  75. pjm->dwState = 0;
  76. pjm->pIniPort = pIniPort;
  77. pjm->idJobLocal = ++s_idJobLocal;
  78. pjm->idJobRemote = 0;
  79. pjm->lpszUri = NULL;
  80. pjm->lpszUser = memAllocStr(lpszUser);
  81. pjm->lpszDocName = memAllocStr(lpszDocName);
  82. pjm->hSplFile = NULL;
  83. pjm->dwLocalJobSize = 0;
  84. pjm->dwStatus = JOB_STATUS_SPOOLING;
  85. pjm->pNext = NULL;
  86. // Place it at the end of the list.
  87. //
  88. if (! *pjmList) {
  89. *pjmList = pjm;
  90. }
  91. else {
  92. for (PJOBMAP pjPtr = *pjmList; pjPtr->pNext; pjPtr = pjPtr->pNext);
  93. pjPtr->pNext = pjm;
  94. }
  95. }
  96. }
  97. return pjm;
  98. }
  99. /*****************************************************************************\
  100. * pjmDel
  101. *
  102. * Delete a job-mapping from the list. Access to this list needs owenership
  103. * of the crit-sect.
  104. *
  105. \*****************************************************************************/
  106. VOID pjmDel(
  107. PJOBMAP* pjmList,
  108. PJOBMAP pjm)
  109. {
  110. PJOBMAP pjPtr;
  111. PJOBMAP pjPrv;
  112. DWORD idx;
  113. semCheckCrit();
  114. if (pjmList) {
  115. for (pjPtr = *pjmList, idx = 0; pjPtr && (pjm != pjPtr); ) {
  116. // Reposition.
  117. //
  118. pjPrv = pjPtr;
  119. pjPtr = pjPtr->pNext;
  120. // If we've iterated 1000 jobs in this list, then we've
  121. // either got a very heavily taxed print-system, or we
  122. // may have an infinite loop.
  123. //
  124. if (idx++ >= g_dwJobLimit) {
  125. DBG_MSG(DBG_LEV_ERROR, (TEXT("Error: pjmDel : Looped 1000 jobs, possible infinite loop")));
  126. return;
  127. }
  128. }
  129. // If we found the entry, then delete it.
  130. //
  131. if (pjPtr) {
  132. if (pjPtr == *pjmList) {
  133. *pjmList = pjPtr->pNext;
  134. } else {
  135. pjPrv->pNext = pjPtr->pNext;
  136. }
  137. pjm_DelEntry(pjPtr);
  138. }
  139. }
  140. }
  141. /*****************************************************************************\
  142. * pjmCleanRemoteFlag
  143. *
  144. * Cleanup remote jobid from list. Access to this list needs ownership of the
  145. * crit-sect.
  146. *
  147. \*****************************************************************************/
  148. VOID pjmCleanRemoteFlag(
  149. PJOBMAP* pjmList)
  150. {
  151. PJOBMAP pjPtr = NULL;
  152. semCheckCrit();
  153. if (pjmList) {
  154. for (pjPtr = *pjmList; pjPtr; ) {
  155. pjPtr->bRemoteJob = FALSE;
  156. // Next item.
  157. //
  158. pjPtr = pjPtr->pNext;
  159. }
  160. }
  161. }
  162. /*****************************************************************************\
  163. * pjmGetLocalJobCount
  164. *
  165. * Locate number of job-entries from list. Access to this list needs ownership of the
  166. * crit-sect.
  167. *
  168. \*****************************************************************************/
  169. DWORD pjmGetLocalJobCount(
  170. PJOBMAP* pjmList,
  171. DWORD* pcbItems)
  172. {
  173. PJOBMAP pjPtr = NULL;
  174. DWORD idx = 0;
  175. semCheckCrit();
  176. *pcbItems = 0;
  177. if (pjmList) {
  178. for (pjPtr = *pjmList; pjPtr; ) {
  179. if (pjm_IsLocalJob (pjPtr)) {
  180. idx++;
  181. *pcbItems += sizeof (JOB_INFO_2) +
  182. utlStrSize (pjPtr->lpszDocName) +
  183. utlStrSize (pjPtr->lpszUser);
  184. }
  185. // Next item.
  186. //
  187. pjPtr = pjPtr->pNext;
  188. }
  189. }
  190. return idx;
  191. }
  192. /*****************************************************************************\
  193. * pjmFind
  194. *
  195. * Locate job-entry from list. Access to this list needs ownership of the
  196. * crit-sect. This will lookup either Local/Remote id's and return its
  197. * position.
  198. *
  199. \*****************************************************************************/
  200. PJOBMAP pjmFind(
  201. PJOBMAP* pjmList,
  202. DWORD fType,
  203. DWORD idJob)
  204. {
  205. PJOBMAP pjPtr = NULL;
  206. DWORD idx;
  207. semCheckCrit();
  208. if (pjmList) {
  209. // Search.
  210. //
  211. for (pjPtr = *pjmList, idx = 0; pjPtr && (pjmJobId(pjPtr, fType) != idJob); ) {
  212. // Next item.
  213. //
  214. pjPtr = pjPtr->pNext;
  215. // If we've iterated 1000 jobs in this list, then we've
  216. // either got a very heavily taxed print-system, or we
  217. // may have an infinite loop.
  218. //
  219. if (idx++ >= g_dwJobLimit) {
  220. DBG_MSG(DBG_LEV_ERROR, (TEXT("Error: pjmFind : Looped 1000 jobs, possible infinite loop")));
  221. return NULL;
  222. }
  223. }
  224. if (pjPtr && fType == PJM_REMOTEID) {
  225. pjPtr->bRemoteJob = TRUE;
  226. }
  227. }
  228. return pjPtr;
  229. }
  230. /*****************************************************************************\
  231. * pjmNextLocalJob
  232. *
  233. * Walk the list and look for any expired entries. Access to this list needs
  234. * ownership of the crit-sect.
  235. *
  236. \*****************************************************************************/
  237. PJOBMAP pjmNextLocalJob(
  238. PJOBMAP* pjmList,
  239. PJOB_INFO_2 pJobInfo2,
  240. PBOOL pbFound)
  241. {
  242. PJOBMAP pjPtr = NULL;
  243. DWORD idx;
  244. BOOL bFound = FALSE;
  245. semCheckCrit();
  246. if (pjmList) {
  247. for (pjPtr = *pjmList, idx = 0; pjPtr && !bFound; ) {
  248. // If we're spooling, then we can't be an old-job.
  249. //
  250. if (pjm_IsLocalJob (pjPtr)) {
  251. // It is a new entry
  252. //
  253. ZeroMemory (pJobInfo2, sizeof (JOB_INFO_2));
  254. pJobInfo2->JobId = pjPtr->idJobLocal;
  255. pJobInfo2->pDocument = pjPtr->lpszDocName;
  256. pJobInfo2->pUserName = pjPtr->lpszUser;
  257. pJobInfo2->Size = pjPtr->dwLocalJobSize;
  258. pJobInfo2->Submitted = pjPtr->SubmitTime;
  259. pJobInfo2->Status = pjPtr->dwStatus;
  260. if (pjmChkState (pjPtr, PJM_CANCEL)) {
  261. pJobInfo2->Status |= JOB_STATUS_DELETING;
  262. }
  263. bFound = TRUE;
  264. }
  265. // Next item.
  266. //
  267. pjPtr = pjPtr->pNext;
  268. }
  269. }
  270. *pbFound = bFound;
  271. return pjPtr;
  272. }
  273. /*****************************************************************************\
  274. * pjmRmoveOldEntries
  275. *
  276. * Walk the list and look for any expired entries. Access to this list needs
  277. * ownership of the crit-sect.
  278. *
  279. \*****************************************************************************/
  280. VOID pjmRemoveOldEntries(
  281. PJOBMAP *pjmList)
  282. {
  283. PJOBMAP pjPtr;
  284. PJOBMAP pjDel;
  285. PJOBMAP pjPrv;
  286. DWORD idx;
  287. semCheckCrit();
  288. for (pjPtr = *pjmList, pjPrv = *pjmList, idx = 0; pjPtr; ) {
  289. // If we're an old entry, then delete it.
  290. //
  291. if (pjm_IsOldEntry (pjPtr)) {
  292. // No remote job ID and the state is not spooling
  293. // It is an old entry, delete it
  294. pjDel = pjPtr;
  295. if (pjPtr == *pjmList) {
  296. *pjmList = pjPtr->pNext;
  297. pjPtr = *pjmList;
  298. pjPrv = *pjmList;
  299. } else {
  300. pjPrv->pNext = pjPtr->pNext;
  301. pjPtr = pjPrv->pNext;
  302. }
  303. pjm_DelEntry(pjDel);
  304. } else {
  305. pjPrv = pjPtr;
  306. pjPtr = pjPtr->pNext;
  307. }
  308. // If we've iterated 1000 jobs in this list, then we've
  309. // either got a very heavily taxed print-system, or we
  310. // may have an infinite loop.
  311. //
  312. if (idx++ >= g_dwJobLimit) {
  313. DBG_MSG(DBG_LEV_ERROR, (TEXT("Warn : pjmWalk : Looped 1000 jobs, possible infinite loop")));
  314. return;
  315. }
  316. }
  317. }
  318. /*****************************************************************************\
  319. * pjmDelList
  320. *
  321. *
  322. \*****************************************************************************/
  323. VOID pjmDelList(
  324. PJOBMAP pjmList)
  325. {
  326. PJOBMAP pjPtr;
  327. semCheckCrit();
  328. for (pjPtr = pjmList; pjPtr; ) {
  329. pjmList = pjPtr->pNext;
  330. pjm_DelEntry(pjPtr);
  331. pjPtr = pjmList;
  332. }
  333. }
  334. /*****************************************************************************\
  335. * pjmSetState
  336. *
  337. * Set the state of the job-entry. If we're setting this to spooling-state,
  338. * then we go through the extra-trouble of setting up a spool-file entry as
  339. * well.
  340. *
  341. \*****************************************************************************/
  342. BOOL pjmSetState(
  343. PJOBMAP pjm,
  344. DWORD dwState)
  345. {
  346. DWORD fType;
  347. BOOL bSet = FALSE;
  348. semCheckCrit();
  349. if (pjm) {
  350. // If the caller is setting the job into spooling-state, then
  351. // we need to create a spool-file. If this state is already
  352. // set, then ignore this particular call.
  353. //
  354. if ((dwState & PJM_SPOOLING) && !pjmChkState(pjm, PJM_SPOOLING)) {
  355. // Determine the type of spl-file to open. If PJM_NOOPEN
  356. // is specified, then we will close the file-handle so that
  357. // other processes can obtain exclusive access (i.e. AddJob,
  358. // and ScheduleJob require this).
  359. //
  360. fType = (dwState & PJM_NOOPEN ? SPLFILE_TMP : SPLFILE_SPL);
  361. // Allocate the spool-file, and close if necessary.
  362. //
  363. if (pjm->hSplFile = SplCreate(pjm->idJobLocal, fType)) {
  364. if (dwState & PJM_NOOPEN)
  365. SplClose(pjm->hSplFile);
  366. bSet = TRUE;
  367. } else {
  368. goto EndSet;
  369. }
  370. } else {
  371. bSet = TRUE;
  372. }
  373. // Set the state.
  374. //
  375. pjm->dwState |= dwState;
  376. }
  377. EndSet:
  378. return bSet;
  379. }
  380. /*****************************************************************************\
  381. * pjmClrState
  382. *
  383. * Clear the state specified in the job-entry. If we're turning of spooling,
  384. * then we need to free up the spool-file-object.
  385. *
  386. \*****************************************************************************/
  387. VOID pjmClrState(
  388. PJOBMAP pjm,
  389. DWORD dwState)
  390. {
  391. semCheckCrit();
  392. if (pjm) {
  393. // If the caller is turning off spooling, then we need to
  394. // clean our spool-file resources. If there is no spooling
  395. // going on, then ignore.
  396. //
  397. if ((dwState & PJM_SPOOLING) && pjmChkState(pjm, PJM_SPOOLING)) {
  398. // Clean our spooling-file resources.
  399. //
  400. SplFree(pjm->hSplFile);
  401. pjm->hSplFile = NULL;
  402. }
  403. // Clear the state.
  404. //
  405. pjm->dwState &= ~dwState;
  406. }
  407. }
  408. /*****************************************************************************\
  409. * pjmSetJobRemote
  410. *
  411. * Set the remote-job-id into the job-entry. This is usually called once
  412. * the job-id is obtained from the print-server. We will maintain this for
  413. * local/remote job-mapping.
  414. *
  415. \*****************************************************************************/
  416. VOID pjmSetJobRemote(
  417. PJOBMAP pjm,
  418. DWORD idJobRemote,
  419. LPCTSTR lpszUri)
  420. {
  421. semCheckCrit();
  422. if (pjm) {
  423. // If we had a previous job-url, then we need to free it
  424. // before reseting it with the new.
  425. //
  426. if (pjm->lpszUri)
  427. memFreeStr(pjm->lpszUri);
  428. // Store remote-job information.
  429. //
  430. pjm->idJobRemote = idJobRemote;
  431. pjm->lpszUri = memAllocStr(lpszUri);
  432. pjm->bRemoteJob = TRUE;
  433. }
  434. }
  435. /*****************************************************************************\
  436. * pjmAddJobSize
  437. *
  438. * Add the job size to the local job info. This is usually called by
  439. * PPWritePrinter
  440. *
  441. \*****************************************************************************/
  442. VOID pjmAddJobSize(
  443. PJOBMAP pjm,
  444. DWORD dwSize)
  445. {
  446. semCheckCrit();
  447. if (pjm) {
  448. pjm->dwLocalJobSize += dwSize;
  449. }
  450. }
  451. /*****************************************************************************\
  452. * pjmSplLock
  453. *
  454. * Lock the spool-file for reading. This returns a file-map pointer to the
  455. * caller.
  456. *
  457. \*****************************************************************************/
  458. CFileStream* pjmSplLock(
  459. PJOBMAP pjm)
  460. {
  461. CFileStream *pStream = NULL;
  462. semCheckCrit();
  463. if (pjm) {
  464. // If the state of our spool-object requires that we not
  465. // keep open-handles on the file, then we need to open
  466. // it here. This is closed at pjmSplUnlock().
  467. //
  468. if (pjmChkState(pjm, PJM_NOOPEN))
  469. SplOpen(pjm->hSplFile);
  470. pStream = SplLock(pjm->hSplFile);
  471. }
  472. return pStream;
  473. }
  474. /*****************************************************************************\
  475. * pjmSplUnlock
  476. *
  477. * This unlocks our file-mapped-pointer on the spool-file.
  478. *
  479. \*****************************************************************************/
  480. BOOL pjmSplUnlock(
  481. PJOBMAP pjm)
  482. {
  483. BOOL bRet = FALSE;
  484. semCheckCrit();
  485. // The spool-file must have already been locked in order to proceed
  486. // with this call.
  487. //
  488. if (pjm) {
  489. // Unlock the spool-file.
  490. //
  491. bRet = SplUnlock(pjm->hSplFile);
  492. // If the state of our spool-object requires that
  493. // we keep no open-handles, then we need to close
  494. // the spool-handle.
  495. //
  496. if (pjmChkState(pjm, PJM_NOOPEN))
  497. SplClose(pjm->hSplFile);
  498. }
  499. return bRet;
  500. }
  501. /*****************************************************************************\
  502. * pjmSplWrite
  503. *
  504. * Write out data to the spool-file.
  505. *
  506. \*****************************************************************************/
  507. BOOL pjmSplWrite(
  508. PJOBMAP pjm,
  509. LPVOID lpMem,
  510. DWORD cbMem,
  511. LPDWORD lpcbWr)
  512. {
  513. BOOL bRet = FALSE;
  514. semCheckCrit();
  515. if (pjm) {
  516. if (pjmChkState(pjm, PJM_NOOPEN))
  517. SplOpen(pjm->hSplFile);
  518. bRet = SplWrite(pjm->hSplFile, (LPBYTE) lpMem, cbMem, lpcbWr);
  519. if (pjmChkState(pjm, PJM_NOOPEN))
  520. SplClose(pjm->hSplFile);
  521. }
  522. return bRet;
  523. }
  524. /*****************************************************************************\
  525. * pjmSetState
  526. *
  527. * Set the status of the local job-entry.
  528. *
  529. \*****************************************************************************/
  530. VOID pjmUpdateLocalJobStatus(
  531. PJOBMAP pjm,
  532. DWORD dwStatus)
  533. {
  534. semCheckCrit();
  535. if (pjm) {
  536. pjm->dwStatus = dwStatus;
  537. }
  538. }