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.

530 lines
11 KiB

  1. /*++
  2. Copyright (c) 1990-1994 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 net print vs. UNICODE.
  12. July 1994 MattFe Caching
  13. --*/
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <ntddrdr.h>
  18. #include <windows.h>
  19. #include <winspool.h>
  20. #include <lm.h>
  21. #include <w32types.h>
  22. #include <local.h>
  23. #include <winsplp.h>
  24. #include <splcom.h> // DBGMSG
  25. #include <winerror.h>
  26. #include <string.h>
  27. #define NOTIFY_TIMEOUT 10000
  28. DWORD
  29. LMStartDocPrinter(
  30. HANDLE hPrinter,
  31. DWORD Level,
  32. LPBYTE pDocInfo
  33. )
  34. {
  35. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  36. WCHAR szFileName[MAX_PATH];
  37. PDOC_INFO_1 pDocInfo1=(PDOC_INFO_1)pDocInfo;
  38. QUERY_PRINT_JOB_INFO JobInfo;
  39. IO_STATUS_BLOCK Iosb;
  40. VALIDATEW32HANDLE( pSpool );
  41. if (pSpool->Status) {
  42. SetLastError(ERROR_INVALID_PARAMETER);
  43. return FALSE;
  44. }
  45. pSpool->Status |= WSPOOL_STATUS_STARTDOC;
  46. if(StrNCatBuff(szFileName,
  47. COUNTOF(szFileName),
  48. pSpool->pServer,
  49. L"\\",
  50. pSpool->pShare,
  51. NULL) != ERROR_SUCCESS)
  52. {
  53. return FALSE;
  54. }
  55. pSpool->hFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL,
  56. OPEN_ALWAYS,
  57. FILE_ATTRIBUTE_NORMAL |
  58. FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  59. if (pSpool->hFile == INVALID_HANDLE_VALUE) {
  60. EnterSplSem();
  61. DeleteEntryfromLMCache(pSpool->pServer, pSpool->pShare);
  62. LeaveSplSem();
  63. DBGMSG( DBG_WARNING, ("Failed to open %ws\n", szFileName));
  64. pSpool->Status &= ~WSPOOL_STATUS_STARTDOC;
  65. SetLastError(ERROR_INVALID_NAME);
  66. return FALSE;
  67. }
  68. if (pDocInfo1 && pDocInfo1->pDocName && (wcslen(pDocInfo1->pDocName) < MAX_PATH)) {
  69. if (NtFsControlFile(pSpool->hFile,
  70. NULL,
  71. NULL,
  72. NULL,
  73. &Iosb,
  74. FSCTL_GET_PRINT_ID,
  75. NULL, 0,
  76. &JobInfo, sizeof(JobInfo)) == ERROR_SUCCESS){
  77. RxPrintJobSetInfo(pSpool->pServer,
  78. JobInfo.JobId,
  79. 3,
  80. (LPBYTE)pDocInfo1->pDocName,
  81. wcslen(pDocInfo1->pDocName)*sizeof(WCHAR) + sizeof(WCHAR),
  82. PRJ_COMMENT_PARMNUM);
  83. }
  84. else
  85. {
  86. DBGMSG( DBG_WARN, ("NtFsControlFile failed %ws\n", szFileName));
  87. }
  88. }
  89. return TRUE;
  90. }
  91. BOOL
  92. LMStartPagePrinter(
  93. HANDLE hPrinter
  94. )
  95. {
  96. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  97. VALIDATEW32HANDLE( pSpool );
  98. return FALSE;
  99. }
  100. BOOL
  101. LMWritePrinter(
  102. HANDLE hPrinter,
  103. LPVOID pBuf,
  104. DWORD cbBuf,
  105. LPDWORD pcWritten
  106. )
  107. {
  108. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  109. DWORD cWritten, cTotal;
  110. DWORD rc;
  111. LPBYTE pByte=pBuf;
  112. VALIDATEW32HANDLE( pSpool );
  113. if (!(pSpool->Status & WSPOOL_STATUS_STARTDOC)) {
  114. SetLastError(ERROR_INVALID_PARAMETER);
  115. return FALSE;
  116. }
  117. if (pSpool->hFile == INVALID_HANDLE_VALUE) {
  118. *pcWritten = 0;
  119. SetLastError(ERROR_INVALID_HANDLE);
  120. return FALSE;
  121. }
  122. cWritten = cTotal = 0;
  123. while (cbBuf) {
  124. rc = WriteFile(pSpool->hFile, pByte, cbBuf, &cWritten, NULL);
  125. if (!rc) {
  126. rc = GetLastError();
  127. DBGMSG(DBG_WARNING, ("Win32 Spooler: Error writing to server, Error %d\n", rc));
  128. cTotal+=cWritten;
  129. *pcWritten=cTotal;
  130. return FALSE;
  131. } else if (!cWritten) {
  132. DBGMSG(DBG_ERROR, ("Spooler: Amount written is zero !!!\n"));
  133. }
  134. cTotal+=cWritten;
  135. cbBuf-=cWritten;
  136. pByte+=cWritten;
  137. }
  138. *pcWritten = cTotal;
  139. return TRUE;
  140. }
  141. BOOL
  142. LMEndPagePrinter(
  143. HANDLE hPrinter
  144. )
  145. {
  146. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  147. VALIDATEW32HANDLE( pSpool );
  148. return FALSE;
  149. }
  150. BOOL
  151. LMAbortPrinter(
  152. HANDLE hPrinter
  153. )
  154. {
  155. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  156. VALIDATEW32HANDLE( pSpool );
  157. // Abort Printer remoteley won't work until we maintain state information
  158. // on a per handle basis. For PDK, this is good enough
  159. #ifdef LATER
  160. WORD parm = 0;
  161. PRIDINFO PridInfo;
  162. DosDevIOCtl(&PridInfo, (LPSTR)&parm, SPOOL_LMGetPrintId, SPOOL_LMCAT,
  163. hSpooler);
  164. RxPrintJobDel(NULL, PridInfo.uJobId);
  165. #endif
  166. return TRUE;
  167. }
  168. BOOL
  169. LMReadPrinter(
  170. HANDLE hPrinter,
  171. LPVOID pBuf,
  172. DWORD cbBuf,
  173. LPDWORD pNoBytesRead
  174. )
  175. {
  176. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  177. VALIDATEW32HANDLE( pSpool );
  178. return 0;
  179. UNREFERENCED_PARAMETER(pBuf);
  180. UNREFERENCED_PARAMETER(pNoBytesRead);
  181. }
  182. BOOL
  183. LMEndDocPrinter(
  184. HANDLE hPrinter
  185. )
  186. {
  187. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  188. VALIDATEW32HANDLE( pSpool );
  189. if (!(pSpool->Status & WSPOOL_STATUS_STARTDOC)) {
  190. SetLastError(ERROR_INVALID_HANDLE);
  191. return FALSE;
  192. }
  193. pSpool->Status &= ~WSPOOL_STATUS_STARTDOC;
  194. if (pSpool->hFile != INVALID_HANDLE_VALUE) {
  195. CloseHandle(pSpool->hFile);
  196. pSpool->hFile = INVALID_HANDLE_VALUE;
  197. }
  198. return TRUE;
  199. }
  200. BOOL
  201. LMAddJob(
  202. HANDLE hPrinter,
  203. DWORD Level,
  204. LPBYTE pData,
  205. DWORD cbBuf,
  206. LPDWORD pcbNeeded
  207. )
  208. {
  209. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  210. DWORD cb;
  211. WCHAR szFileName[MAX_PATH];
  212. LPBYTE pEnd;
  213. LPADDJOB_INFO_1 pAddJob=(LPADDJOB_INFO_1)pData;
  214. VALIDATEW32HANDLE( pSpool );
  215. if(StrNCatBuff(szFileName,
  216. COUNTOF(szFileName),
  217. pSpool->pServer,
  218. L"\\",
  219. pSpool->pShare,
  220. NULL) != ERROR_SUCCESS)
  221. {
  222. return(FALSE);
  223. }
  224. cb = wcslen(szFileName)*sizeof(WCHAR) + sizeof(WCHAR) + sizeof(ADDJOB_INFO_1);
  225. if (cb > cbBuf) {
  226. *pcbNeeded=cb;
  227. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  228. return(FALSE);
  229. }
  230. pEnd = (LPBYTE)pAddJob+cbBuf;
  231. pEnd -= wcslen(szFileName)*sizeof(WCHAR)+sizeof(WCHAR);
  232. pAddJob->Path = wcscpy((LPWSTR)pEnd, szFileName);
  233. pAddJob->JobId = (DWORD)-1;
  234. return TRUE;
  235. }
  236. BOOL
  237. LMScheduleJob(
  238. HANDLE hPrinter,
  239. DWORD JobId
  240. )
  241. {
  242. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  243. VALIDATEW32HANDLE( pSpool );
  244. JobId = JobId;
  245. return TRUE;
  246. }
  247. DWORD
  248. LMGetPrinterData(
  249. HANDLE hPrinter,
  250. LPTSTR pValueName,
  251. LPDWORD pType,
  252. LPBYTE pData,
  253. DWORD nSize,
  254. LPDWORD pcbNeeded
  255. )
  256. {
  257. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  258. VALIDATEW32HANDLE( pSpool );
  259. return FALSE;
  260. }
  261. DWORD
  262. LMSetPrinterData(
  263. HANDLE hPrinter,
  264. LPTSTR pValueName,
  265. DWORD Type,
  266. LPBYTE pData,
  267. DWORD cbData
  268. )
  269. {
  270. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  271. VALIDATEW32HANDLE( pSpool );
  272. return FALSE;
  273. }
  274. BOOL
  275. LMClosePrinter(
  276. HANDLE hPrinter
  277. )
  278. {
  279. PWSPOOL pSpool=(PWSPOOL)hPrinter;
  280. PLMNOTIFY pLMNotify = &pSpool->LMNotify;
  281. BOOL bReturnValue = FALSE;
  282. VALIDATEW32HANDLE( pSpool );
  283. EnterSplSem();
  284. if (pSpool->Status & WSPOOL_STATUS_STARTDOC)
  285. EndDocPrinter(hPrinter);
  286. if (pLMNotify->ChangeEvent) {
  287. if (pLMNotify->ChangeEvent != INVALID_HANDLE_VALUE) {
  288. CloseHandle(pLMNotify->ChangeEvent);
  289. } else {
  290. LMFindClosePrinterChangeNotification(hPrinter);
  291. }
  292. }
  293. FreepSpool( pSpool );
  294. bReturnValue = TRUE;
  295. LeaveSplSem();
  296. return bReturnValue;
  297. }
  298. DWORD
  299. LMWaitForPrinterChange(
  300. HANDLE hPrinter,
  301. DWORD Flags
  302. )
  303. {
  304. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  305. PLMNOTIFY pLMNotify = &pSpool->LMNotify;
  306. HANDLE ChangeEvent;
  307. DWORD bReturnValue = FALSE;
  308. EnterSplSem();
  309. //
  310. // !! LATER !!
  311. //
  312. // We have no synchronization code in win32spl. This opens us
  313. // up to AVs if same handle is used (ResetPrinter validates;
  314. // Close closes; ResetPrinter tries to use handle boom.)
  315. // Here's one more case:
  316. //
  317. if (pLMNotify->ChangeEvent) {
  318. SetLastError(ERROR_ALREADY_WAITING);
  319. goto Error;
  320. }
  321. // Allocate memory for ChangeEvent for LanMan Printers
  322. // This event is pulsed by LMSetJob and any othe LM
  323. // function that modifies the printer/job status
  324. // LMWaitForPrinterChange waits on this event
  325. // being pulsed.
  326. ChangeEvent = CreateEvent(NULL,
  327. FALSE,
  328. FALSE,
  329. NULL);
  330. if (!ChangeEvent) {
  331. DBGMSG(DBG_WARNING, ("CreateEvent( ChangeEvent ) failed: Error %d\n",
  332. GetLastError()));
  333. goto Error;
  334. }
  335. pLMNotify->ChangeEvent = ChangeEvent;
  336. LeaveSplSem();
  337. WaitForSingleObject(pLMNotify->ChangeEvent, NOTIFY_TIMEOUT);
  338. CloseHandle(ChangeEvent);
  339. //
  340. // !! LATER !!
  341. //
  342. // We shouldn't return that everything changed; we should
  343. // return what did.
  344. //
  345. return Flags;
  346. Error:
  347. LeaveSplSem();
  348. return 0;
  349. }
  350. BOOL
  351. LMFindFirstPrinterChangeNotification(
  352. HANDLE hPrinter,
  353. DWORD fdwFlags,
  354. DWORD fdwOptions,
  355. HANDLE hNotify,
  356. PDWORD pfdwStatus)
  357. {
  358. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  359. PLMNOTIFY pLMNotify = &pSpool->LMNotify;
  360. EnterSplSem();
  361. pLMNotify->hNotify = hNotify;
  362. pLMNotify->fdwChangeFlags = fdwFlags;
  363. pLMNotify->ChangeEvent = INVALID_HANDLE_VALUE;
  364. *pfdwStatus = PRINTER_NOTIFY_STATUS_ENDPOINT | PRINTER_NOTIFY_STATUS_POLL;
  365. LeaveSplSem();
  366. return TRUE;
  367. }
  368. BOOL
  369. LMFindClosePrinterChangeNotification(
  370. HANDLE hPrinter)
  371. {
  372. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  373. PLMNOTIFY pLMNotify = &pSpool->LMNotify;
  374. SplInSem();
  375. if (pLMNotify->ChangeEvent != INVALID_HANDLE_VALUE) {
  376. SetLastError(ERROR_INVALID_HANDLE);
  377. return FALSE;
  378. }
  379. pLMNotify->hNotify = NULL;
  380. pLMNotify->ChangeEvent = NULL;
  381. return TRUE;
  382. }
  383. VOID
  384. LMSetSpoolChange(
  385. PWSPOOL pSpool)
  386. {
  387. PLMNOTIFY pLMNotify;
  388. pLMNotify = &pSpool->LMNotify;
  389. EnterSplSem();
  390. if (pLMNotify->ChangeEvent) {
  391. if (pLMNotify->ChangeEvent == INVALID_HANDLE_VALUE) {
  392. //
  393. // FindFirstPrinterChangeNotification used.
  394. //
  395. ReplyPrinterChangeNotification(pLMNotify->hNotify,
  396. pLMNotify->fdwChangeFlags,
  397. NULL,
  398. NULL);
  399. } else {
  400. SetEvent(pLMNotify->ChangeEvent);
  401. }
  402. }
  403. LeaveSplSem();
  404. }