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