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