[Printing] Fix ups and Implementations.
[reactos.git] / win32ss / printing / base / winspool / utils.c
1 /*
2 * PROJECT: ReactOS Spooler API
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Utility Functions related to Print Processors
5 * COPYRIGHT: Copyright 2020 Doug Lyons (douglyons@douglyons.com)
6 */
7
8 #include "precomp.h"
9
10 /*
11 * Converts an incoming Unicode string to an ANSI string.
12 * It is only useful for "in-place" conversions where the ANSI string goes
13 * back into the same place where the Unicode string came into this function.
14 *
15 * It returns an error code.
16 */
17 // TODO: It seems that many of the functions involving printing could use this.
18 DWORD UnicodeToAnsiInPlace(PWSTR pwszField)
19 {
20 PSTR pszTemp;
21 DWORD cch;
22
23 /*
24 * Map the incoming Unicode pwszField string to an ANSI one here so that we can do
25 * in-place conversion. We read the Unicode input and then we write back the ANSI
26 * conversion into the same buffer for use with our GetPrinterDriverA function
27 */
28 PSTR pszField = (PSTR)pwszField;
29
30 if (!pwszField)
31 {
32 return ERROR_SUCCESS;
33 }
34
35 cch = wcslen(pwszField);
36 if (cch == 0)
37 {
38 return ERROR_SUCCESS;
39 }
40
41 pszTemp = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
42 if (!pszTemp)
43 {
44 ERR("HeapAlloc failed!\n");
45 return ERROR_NOT_ENOUGH_MEMORY;
46 }
47
48 WideCharToMultiByte(CP_ACP, 0, pwszField, -1, pszTemp, cch + 1, NULL, NULL);
49 StringCchCopyA(pszField, cch + 1, pszTemp);
50
51 HeapFree(hProcessHeap, 0, pszTemp);
52
53 return ERROR_SUCCESS;
54 }
55
56 static int multi_sz_lenW(const WCHAR *str)
57 {
58 const WCHAR *ptr = str;
59 if (!str) return 0;
60 do
61 {
62 ptr += lstrlenW(ptr) + 1;
63 } while (*ptr);
64
65 return (ptr - str + 1);// * sizeof(WCHAR); wine does this.
66 }
67
68 DWORD UnicodeToAnsiZZInPlace(PWSTR pwszzField)
69 {
70 PSTR pszTemp;
71 INT len, lenW;
72 PSTR pszField = (PSTR)pwszzField;
73
74 lenW = multi_sz_lenW(pwszzField);
75 if (lenW == 0)
76 {
77 return ERROR_SUCCESS;
78 }
79
80 len = WideCharToMultiByte(CP_ACP, 0, pwszzField, lenW, NULL, 0, NULL, NULL);
81
82 pszTemp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
83
84 WideCharToMultiByte(CP_ACP, 0, pwszzField, lenW, pszTemp, len, NULL, NULL);
85
86 StringCchCopyA(pszField, len, pszTemp);
87
88 HeapFree(hProcessHeap, 0, pszTemp);
89
90 return ERROR_SUCCESS;
91 }
92
93 //
94 // Implement and simplify later.
95 //
96 LONG WINAPI
97 IntProtectHandle( HANDLE hSpooler, BOOL Close )
98 {
99 BOOL Bad = TRUE;
100 LONG Ret;
101 PSPOOLER_HANDLE pHandle;
102
103 EnterCriticalSection(&rtlCritSec);
104
105 _SEH2_TRY
106 {
107 pHandle = (PSPOOLER_HANDLE)hSpooler;
108 if ( pHandle && pHandle->Sig == SPOOLER_HANDLE_SIG )
109 {
110 Bad = FALSE; // Not bad.
111 }
112 }
113 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
114 {
115 }
116 _SEH2_END;
117
118 Ret = Bad; // Set return Level to 1 if we are BAD.
119
120 if ( Bad )
121 {
122 SetLastError(ERROR_INVALID_HANDLE);
123 ERR("IPH : Printer Handle failed!\n");
124 }
125 else
126 {
127 if ( Close )
128 {
129 if ( pHandle->bShared || pHandle->cCount != 0 )
130 {
131 pHandle->bShared = TRUE;
132 Ret = 2; // Return a high level and we are shared.
133 FIXME("IPH Close : We are shared\n");
134 }
135 else
136 {
137 pHandle->bClosed = TRUE;
138 FIXME("IPH Close : closing.\n");
139 }
140 }
141 }
142
143 if ( !Ret ) // Need to be Level 0.
144 {
145 pHandle->cCount++;
146 FIXME("IPH : Count %d\n",pHandle->cCount);
147 }
148
149 LeaveCriticalSection(&rtlCritSec);
150
151 // Return Level:
152 // 2 : Close and/or shared
153 // 1 : Failed Handle
154 // 0 : In use.
155 return Ret;
156 }
157 //
158 // This one too.
159 //
160 BOOL WINAPI
161 IntUnprotectHandle( HANDLE hSpooler )
162 {
163 BOOL Ret = FALSE;
164 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hSpooler;
165 EnterCriticalSection(&rtlCritSec);
166 if ( pHandle->bShared && --pHandle->cCount == 0 )
167 {
168 pHandle->bClosed = TRUE;
169 pHandle->bShared = FALSE;
170 Ret = TRUE;
171 }
172 LeaveCriticalSection(&rtlCritSec);
173 FIXME("IUH : Count %d\n",pHandle->cCount);
174 if ( Ret )
175 {
176 // ClosePrinterWorker( pHandle );
177 }
178 return Ret;
179 }
180
181 /**
182 * @name AllocSplStr
183 *
184 * Allocates memory for a Unicode string and copies the input string into it.
185 * Equivalent of wcsdup, but the returned buffer is allocated from the spooler heap and must be freed with DllFreeSplStr.
186 *
187 * @param pwszInput
188 * The input string to copy
189 *
190 * @return
191 * Pointer to the copied string or NULL if no memory could be allocated.
192 */
193 PWSTR WINAPI
194 AllocSplStr(PCWSTR pwszInput)
195 {
196 DWORD cbInput;
197 PWSTR pwszOutput;
198
199 // Sanity check
200 if (!pwszInput)
201 return NULL;
202
203 // Get the length of the input string.
204 cbInput = (wcslen(pwszInput) + 1) * sizeof(WCHAR);
205
206 // Allocate it. We don't use DllAllocSplMem here, because it unnecessarily zeroes the memory.
207 pwszOutput = HeapAlloc(hProcessHeap, 0, cbInput);
208 if (!pwszOutput)
209 {
210 ERR("HeapAlloc failed!\n");
211 return NULL;
212 }
213
214 // Copy the string and return it.
215 CopyMemory(pwszOutput, pwszInput, cbInput);
216 return pwszOutput;
217 }
218
219 /**
220 * @name DllAllocSplMem
221 *
222 * Allocate a block of zeroed memory.
223 * Windows allocates from a separate spooler heap here while we just use the process heap.
224 *
225 * @param dwBytes
226 * Number of bytes to allocate.
227 *
228 * @return
229 * A pointer to the allocated memory or NULL in case of an error.
230 * You have to free this memory using DllFreeSplMem.
231 */
232 PVOID WINAPI
233 DllAllocSplMem(DWORD dwBytes)
234 {
235 return HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, dwBytes);
236 }
237
238 /**
239 * @name DllFreeSplMem
240 *
241 * Frees the memory allocated with DllAllocSplMem.
242 *
243 * @param pMem
244 * Pointer to the allocated memory.
245 *
246 * @return
247 * TRUE in case of success, FALSE otherwise.
248 */
249 BOOL WINAPI
250 DllFreeSplMem(PVOID pMem)
251 {
252 if ( !pMem ) return TRUE;
253 return HeapFree(hProcessHeap, 0, pMem);
254 }
255
256 /**
257 * @name DllFreeSplStr
258 *
259 * Frees the string allocated with AllocSplStr.
260 *
261 * @param pwszString
262 * Pointer to the allocated string.
263 *
264 * @return
265 * TRUE in case of success, FALSE otherwise.
266 */
267 BOOL WINAPI
268 DllFreeSplStr(PWSTR pwszString)
269 {
270 if ( pwszString )
271 return HeapFree(hProcessHeap, 0, pwszString);
272 return FALSE;
273 }
274
275 SECURITY_DESCRIPTOR * get_sd( SECURITY_DESCRIPTOR *sd, DWORD *size )
276 {
277 PSID sid_group, sid_owner;
278 ACL *sacl, *dacl;
279 BOOL bSet = FALSE, bSetd = FALSE, bSets = FALSE;
280 PSECURITY_DESCRIPTOR absolute_sd, retsd;
281
282 if ( !IsValidSecurityDescriptor( sd ) )
283 {
284 return NULL;
285 }
286
287 InitializeSecurityDescriptor( &absolute_sd, SECURITY_DESCRIPTOR_REVISION );
288
289 if ( !GetSecurityDescriptorOwner( sd, &sid_owner, &bSet ) )
290 {
291 return NULL;
292 }
293
294 SetSecurityDescriptorOwner( &absolute_sd, sid_owner, bSet );
295
296 if ( !GetSecurityDescriptorGroup( sd, &sid_group, &bSet ) )
297 {
298 return NULL;
299 }
300
301 SetSecurityDescriptorGroup( &absolute_sd, sid_group, bSet );
302
303 if ( !GetSecurityDescriptorDacl( sd, &bSetd, &dacl, &bSet ) )
304 {
305 return NULL;
306 }
307
308 SetSecurityDescriptorDacl( &absolute_sd, bSetd, dacl, bSet );
309
310 if ( !GetSecurityDescriptorSacl( sd, &bSets, &sacl, &bSet ) )
311 {
312 return(NULL);
313 }
314
315 SetSecurityDescriptorSacl( &absolute_sd, bSets, sacl, bSet );
316
317 *size = GetSecurityDescriptorLength( &absolute_sd );
318
319 retsd = HeapAlloc( GetProcessHeap(), 0, *size );
320
321 if ( retsd )
322 {
323 if ( !MakeSelfRelativeSD( &absolute_sd, retsd, size ) )
324 {
325 HeapFree( GetProcessHeap(), 0, retsd );
326 retsd = NULL;
327 }
328 }
329
330 return retsd;
331 }
332