xref: /reactos/win32ss/printing/base/winspool/utils.c (revision 41805926)
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 
333