[SPOOLSV, WINSPOOL]
[reactos.git] / reactos / win32ss / printing / base / winspool / jobs.c
1 /*
2 * PROJECT: ReactOS Spooler API
3 * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
4 * PURPOSE: Functions for managing print jobs
5 * COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 static void
11 _MarshallUpAddJobInfo(PADDJOB_INFO_1W pAddJobInfo1)
12 {
13 // Replace relative offset addresses in the output by absolute pointers.
14 pAddJobInfo1->Path = (PWSTR)((ULONG_PTR)pAddJobInfo1->Path + (ULONG_PTR)pAddJobInfo1);
15 }
16
17 static void
18 _MarshallUpJobInfo(PBYTE pJobInfo, DWORD Level)
19 {
20 PJOB_INFO_1W pJobInfo1;
21 PJOB_INFO_2W pJobInfo2;
22
23 // Replace relative offset addresses in the output by absolute pointers.
24 if (Level == 1)
25 {
26 pJobInfo1 = (PJOB_INFO_1W)pJobInfo;
27 pJobInfo1->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo1->pDatatype + (ULONG_PTR)pJobInfo1);
28 pJobInfo1->pDocument = (PWSTR)((ULONG_PTR)pJobInfo1->pDocument + (ULONG_PTR)pJobInfo1);
29 pJobInfo1->pMachineName = (PWSTR)((ULONG_PTR)pJobInfo1->pMachineName + (ULONG_PTR)pJobInfo1);
30 pJobInfo1->pPrinterName = (PWSTR)((ULONG_PTR)pJobInfo1->pPrinterName + (ULONG_PTR)pJobInfo1);
31
32 if (pJobInfo1->pStatus)
33 pJobInfo1->pStatus = (PWSTR)((ULONG_PTR)pJobInfo1->pStatus + (ULONG_PTR)pJobInfo1);
34
35 pJobInfo1->pUserName = (PWSTR)((ULONG_PTR)pJobInfo1->pUserName + (ULONG_PTR)pJobInfo1);
36 }
37 else if (Level == 2)
38 {
39 pJobInfo2 = (PJOB_INFO_2W)pJobInfo;
40 pJobInfo2->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo2->pDatatype + (ULONG_PTR)pJobInfo2);
41 pJobInfo2->pDevMode = (PDEVMODEW)((ULONG_PTR)pJobInfo2->pDevMode + (ULONG_PTR)pJobInfo2);
42 pJobInfo2->pDocument = (PWSTR)((ULONG_PTR)pJobInfo2->pDocument + (ULONG_PTR)pJobInfo2);
43 pJobInfo2->pDriverName = (PWSTR)((ULONG_PTR)pJobInfo2->pDriverName + (ULONG_PTR)pJobInfo2);
44 pJobInfo2->pMachineName = (PWSTR)((ULONG_PTR)pJobInfo2->pMachineName + (ULONG_PTR)pJobInfo2);
45 pJobInfo2->pNotifyName = (PWSTR)((ULONG_PTR)pJobInfo2->pNotifyName + (ULONG_PTR)pJobInfo2);
46 pJobInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pJobInfo2->pPrinterName + (ULONG_PTR)pJobInfo2);
47 pJobInfo2->pPrintProcessor = (PWSTR)((ULONG_PTR)pJobInfo2->pPrintProcessor + (ULONG_PTR)pJobInfo2);
48
49 if (pJobInfo2->pParameters)
50 pJobInfo2->pParameters = (PWSTR)((ULONG_PTR)pJobInfo2->pParameters + (ULONG_PTR)pJobInfo2);
51
52 if (pJobInfo2->pStatus)
53 pJobInfo2->pStatus = (PWSTR)((ULONG_PTR)pJobInfo2->pStatus + (ULONG_PTR)pJobInfo2);
54
55 pJobInfo2->pUserName = (PWSTR)((ULONG_PTR)pJobInfo2->pUserName + (ULONG_PTR)pJobInfo2);
56 }
57 }
58
59 BOOL WINAPI
60 AddJobA(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded)
61 {
62 UNIMPLEMENTED;
63 return FALSE;
64 }
65
66 BOOL WINAPI
67 AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded)
68 {
69 DWORD dwErrorCode;
70 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
71
72 if (!pHandle)
73 {
74 dwErrorCode = ERROR_INVALID_HANDLE;
75 goto Cleanup;
76 }
77
78 // Do the RPC call
79 RpcTryExcept
80 {
81 dwErrorCode = _RpcAddJob(pHandle->hPrinter, Level, pData, cbBuf, pcbNeeded);
82 }
83 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
84 {
85 dwErrorCode = RpcExceptionCode();
86 ERR("_RpcAddJob failed with exception code %lu!\n", dwErrorCode);
87 }
88 RpcEndExcept;
89
90 if (dwErrorCode == ERROR_SUCCESS)
91 _MarshallUpAddJobInfo((PADDJOB_INFO_1W)pData);
92
93 Cleanup:
94 SetLastError(dwErrorCode);
95 return (dwErrorCode == ERROR_SUCCESS);
96 }
97
98 BOOL WINAPI
99 EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
100 {
101 UNIMPLEMENTED;
102 return FALSE;
103 }
104
105 BOOL WINAPI
106 EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
107 {
108 DWORD dwErrorCode;
109 DWORD i;
110 PBYTE p = pJob;
111 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
112
113 if (!pHandle)
114 {
115 dwErrorCode = ERROR_INVALID_HANDLE;
116 goto Cleanup;
117 }
118
119 // Do the RPC call
120 RpcTryExcept
121 {
122 dwErrorCode = _RpcEnumJobs(pHandle->hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned);
123 }
124 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
125 {
126 dwErrorCode = RpcExceptionCode();
127 ERR("_RpcEnumJobs failed with exception code %lu!\n", dwErrorCode);
128 }
129 RpcEndExcept;
130
131 if (dwErrorCode == ERROR_SUCCESS)
132 {
133 // Replace relative offset addresses in the output by absolute pointers.
134 for (i = 0; i < *pcReturned; i++)
135 {
136 _MarshallUpJobInfo(p, Level);
137
138 if (Level == 1)
139 p += sizeof(JOB_INFO_1W);
140 else if (Level == 2)
141 p += sizeof(JOB_INFO_2W);
142 }
143 }
144
145 Cleanup:
146 SetLastError(dwErrorCode);
147 return (dwErrorCode == ERROR_SUCCESS);
148 }
149
150 BOOL WINAPI
151 GetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded)
152 {
153 UNIMPLEMENTED;
154 return FALSE;
155 }
156
157 BOOL WINAPI
158 GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded)
159 {
160 DWORD dwErrorCode;
161 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
162
163 if (!pHandle)
164 {
165 dwErrorCode = ERROR_INVALID_HANDLE;
166 goto Cleanup;
167 }
168
169 // Do the RPC call
170 RpcTryExcept
171 {
172 dwErrorCode = _RpcGetJob(pHandle->hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
173 }
174 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
175 {
176 dwErrorCode = RpcExceptionCode();
177 ERR("_RpcGetJob failed with exception code %lu!\n", dwErrorCode);
178 }
179 RpcEndExcept;
180
181 if (dwErrorCode == ERROR_SUCCESS)
182 {
183 // Replace relative offset addresses in the output by absolute pointers.
184 _MarshallUpJobInfo(pJob, Level);
185 }
186
187 Cleanup:
188 SetLastError(dwErrorCode);
189 return (dwErrorCode == ERROR_SUCCESS);
190 }
191
192 BOOL WINAPI
193 ScheduleJob(HANDLE hPrinter, DWORD dwJobID)
194 {
195 DWORD dwErrorCode;
196 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
197
198 if (!pHandle)
199 {
200 dwErrorCode = ERROR_INVALID_HANDLE;
201 goto Cleanup;
202 }
203
204 // Do the RPC call
205 RpcTryExcept
206 {
207 dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, dwJobID);
208 }
209 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
210 {
211 dwErrorCode = RpcExceptionCode();
212 ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode);
213 }
214 RpcEndExcept;
215
216 Cleanup:
217 SetLastError(dwErrorCode);
218 return (dwErrorCode == ERROR_SUCCESS);
219 }
220
221 BOOL WINAPI
222 SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
223 {
224 UNIMPLEMENTED;
225 return FALSE;
226 }
227
228 BOOL WINAPI
229 SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
230 {
231 DWORD dwErrorCode;
232 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
233 WINSPOOL_JOB_CONTAINER JobContainer;
234
235 if (!pHandle)
236 {
237 dwErrorCode = ERROR_INVALID_HANDLE;
238 goto Cleanup;
239 }
240
241 // pJobContainer->JobInfo is a union of pointers, so we can just set any element to our BYTE pointer.
242 JobContainer.Level = Level;
243 JobContainer.JobInfo.Level1 = (WINSPOOL_JOB_INFO_1*)pJobInfo;
244
245 // Do the RPC call
246 RpcTryExcept
247 {
248 dwErrorCode = _RpcSetJob(pHandle->hPrinter, JobId, &JobContainer, Command);
249 }
250 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
251 {
252 dwErrorCode = RpcExceptionCode();
253 ERR("_RpcSetJob failed with exception code %lu!\n", dwErrorCode);
254 }
255 RpcEndExcept;
256
257 Cleanup:
258 SetLastError(dwErrorCode);
259 return (dwErrorCode == ERROR_SUCCESS);
260 }