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)
10 #include <undocshell.h>
12 #include <pseh/pseh2.h>
14 #define MAX_GETPRINTER_SIZE 4096 - MAX_PATH
15 typedef void (WINAPI
*PPfpSHChangeNotify
)(LONG wEventId
, UINT uFlags
, LPCVOID dwItem1
, LPCVOID dwItem2
);
17 static HMODULE hShell32
= (HMODULE
)-1;
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.
25 * It returns an error code.
27 // TODO: It seems that many of the functions involving printing could use this.
28 DWORD
UnicodeToAnsiInPlace(PWSTR pwszField
)
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
38 PSTR pszField
= (PSTR
)pwszField
;
45 cch
= wcslen(pwszField
);
51 pszTemp
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(CHAR
));
54 ERR("HeapAlloc failed!\n");
55 return ERROR_NOT_ENOUGH_MEMORY
;
58 WideCharToMultiByte(CP_ACP
, 0, pwszField
, -1, pszTemp
, cch
+ 1, NULL
, NULL
);
59 StringCchCopyA(pszField
, cch
+ 1, pszTemp
);
61 HeapFree(hProcessHeap
, 0, pszTemp
);
66 static int multi_sz_lenW(const WCHAR
*str
)
68 const WCHAR
*ptr
= str
;
72 ptr
+= lstrlenW(ptr
) + 1;
75 return (ptr
- str
+ 1);// * sizeof(WCHAR); wine does this.
78 DWORD
UnicodeToAnsiZZInPlace(PWSTR pwszzField
)
82 PSTR pszField
= (PSTR
)pwszzField
;
84 lenW
= multi_sz_lenW(pwszzField
);
90 len
= WideCharToMultiByte(CP_ACP
, 0, pwszzField
, lenW
, NULL
, 0, NULL
, NULL
);
92 pszTemp
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
94 WideCharToMultiByte(CP_ACP
, 0, pwszzField
, lenW
, pszTemp
, len
, NULL
, NULL
);
96 StringCchCopyA(pszField
, len
, pszTemp
);
98 HeapFree(hProcessHeap
, 0, pszTemp
);
100 return ERROR_SUCCESS
;
104 // Implement and simplify later.
107 IntProtectHandle( HANDLE hSpooler
, BOOL Close
)
111 PSPOOLER_HANDLE pHandle
;
113 EnterCriticalSection(&rtlCritSec
);
117 pHandle
= (PSPOOLER_HANDLE
)hSpooler
;
118 if ( pHandle
&& pHandle
->Sig
== SPOOLER_HANDLE_SIG
)
120 Bad
= FALSE
; // Not bad.
123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
128 Ret
= Bad
; // Set return Level to 1 if we are BAD.
132 SetLastError(ERROR_INVALID_HANDLE
);
133 ERR("IPH : Printer Handle failed!\n");
139 if ( pHandle
->bShared
|| pHandle
->cCount
!= 0 )
141 pHandle
->bShared
= TRUE
;
142 Ret
= 2; // Return a high level and we are shared.
143 FIXME("IPH Close : We are shared\n");
147 pHandle
->bClosed
= TRUE
;
148 FIXME("IPH Close : closing.\n");
153 if ( !Ret
) // Need to be Level 0.
156 FIXME("IPH : Count %d\n",pHandle
->cCount
);
159 LeaveCriticalSection(&rtlCritSec
);
162 // 2 : Close and/or shared
171 IntUnprotectHandle( HANDLE hSpooler
)
174 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hSpooler
;
175 EnterCriticalSection(&rtlCritSec
);
176 if ( pHandle
->bShared
&& --pHandle
->cCount
== 0 )
178 pHandle
->bClosed
= TRUE
;
179 pHandle
->bShared
= FALSE
;
182 LeaveCriticalSection(&rtlCritSec
);
183 FIXME("IUH : Count %d\n",pHandle
->cCount
);
186 // ClosePrinterWorker( pHandle );
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.
198 * The input string to copy
201 * Pointer to the copied string or NULL if no memory could be allocated.
204 AllocSplStr(PCWSTR pwszInput
)
213 // Get the length of the input string.
214 cbInput
= (wcslen(pwszInput
) + 1) * sizeof(WCHAR
);
216 // Allocate it. We don't use DllAllocSplMem here, because it unnecessarily zeroes the memory.
217 pwszOutput
= HeapAlloc(hProcessHeap
, 0, cbInput
);
220 ERR("HeapAlloc failed!\n");
224 // Copy the string and return it.
225 CopyMemory(pwszOutput
, pwszInput
, cbInput
);
230 * @name DllAllocSplMem
232 * Allocate a block of zeroed memory.
233 * Windows allocates from a separate spooler heap here while we just use the process heap.
236 * Number of bytes to allocate.
239 * A pointer to the allocated memory or NULL in case of an error.
240 * You have to free this memory using DllFreeSplMem.
243 DllAllocSplMem(DWORD dwBytes
)
245 return HeapAlloc(hProcessHeap
, HEAP_ZERO_MEMORY
, dwBytes
);
249 * @name DllFreeSplMem
251 * Frees the memory allocated with DllAllocSplMem.
254 * Pointer to the allocated memory.
257 * TRUE in case of success, FALSE otherwise.
260 DllFreeSplMem(PVOID pMem
)
262 if ( !pMem
) return TRUE
;
263 return HeapFree(hProcessHeap
, 0, pMem
);
267 * @name DllFreeSplStr
269 * Frees the string allocated with AllocSplStr.
272 * Pointer to the allocated string.
275 * TRUE in case of success, FALSE otherwise.
278 DllFreeSplStr(PWSTR pwszString
)
281 return HeapFree(hProcessHeap
, 0, pwszString
);
285 SECURITY_DESCRIPTOR
* get_sd( SECURITY_DESCRIPTOR
*sd
, DWORD
*size
)
287 PSID sid_group
, sid_owner
;
289 BOOL bSet
= FALSE
, bSetd
= FALSE
, bSets
= FALSE
;
290 PSECURITY_DESCRIPTOR absolute_sd
, retsd
;
292 if ( !IsValidSecurityDescriptor( sd
) )
297 InitializeSecurityDescriptor( &absolute_sd
, SECURITY_DESCRIPTOR_REVISION
);
299 if ( !GetSecurityDescriptorOwner( sd
, &sid_owner
, &bSet
) )
304 SetSecurityDescriptorOwner( &absolute_sd
, sid_owner
, bSet
);
306 if ( !GetSecurityDescriptorGroup( sd
, &sid_group
, &bSet
) )
311 SetSecurityDescriptorGroup( &absolute_sd
, sid_group
, bSet
);
313 if ( !GetSecurityDescriptorDacl( sd
, &bSetd
, &dacl
, &bSet
) )
318 SetSecurityDescriptorDacl( &absolute_sd
, bSetd
, dacl
, bSet
);
320 if ( !GetSecurityDescriptorSacl( sd
, &bSets
, &sacl
, &bSet
) )
325 SetSecurityDescriptorSacl( &absolute_sd
, bSets
, sacl
, bSet
);
327 *size
= GetSecurityDescriptorLength( &absolute_sd
);
329 retsd
= HeapAlloc( GetProcessHeap(), 0, *size
);
333 if ( !MakeSelfRelativeSD( &absolute_sd
, retsd
, size
) )
335 HeapFree( GetProcessHeap(), 0, retsd
);
344 UpdateTrayIcon( HANDLE hPrinter
, DWORD JobId
)
346 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hPrinter
;
347 SHCNF_PRINTJOB_INFO spji
;
348 PRINTER_INFO_1W pi1w
[MAX_GETPRINTER_SIZE
] = {0};
350 PPfpSHChangeNotify fpFunction
;
352 pHandle
->bTrayIcon
= TRUE
;
356 if (!GetPrinterW( hPrinter
, 1, (PBYTE
)&pi1w
, MAX_GETPRINTER_SIZE
, &cbNeeded
) )
358 ERR("UpdateTrayIcon : GetPrinterW cbNeeded %d\n");
362 if ( hShell32
== (HMODULE
)-1 )
364 hShell32
= LoadLibraryW(L
"shell32.dll");
369 fpFunction
= (PPfpSHChangeNotify
)GetProcAddress( hShell32
, "SHChangeNotify" );
373 fpFunction( SHCNE_CREATE
, (SHCNF_FLUSHNOWAIT
|SHCNF_FLUSH
|SHCNF_PRINTJOBW
), pi1w
->pName
, &spji
);
378 ERR("UpdateTrayIcon : No Shell32!\n");