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 #define MAX_GETPRINTER_SIZE 4096 - MAX_PATH
13 typedef void (WINAPI
*PPfpSHChangeNotify
)(LONG wEventId
, UINT uFlags
, LPCVOID dwItem1
, LPCVOID dwItem2
);
15 static HMODULE hShell32
= (HMODULE
)-1;
19 * Converts an incoming Unicode string to an ANSI string.
20 * It is only useful for "in-place" conversions where the ANSI string goes
21 * back into the same place where the Unicode string came into this function.
23 * It returns an error code.
25 // TODO: It seems that many of the functions involving printing could use this.
26 DWORD
UnicodeToAnsiInPlace(PWSTR pwszField
)
32 * Map the incoming Unicode pwszField string to an ANSI one here so that we can do
33 * in-place conversion. We read the Unicode input and then we write back the ANSI
34 * conversion into the same buffer for use with our GetPrinterDriverA function
36 PSTR pszField
= (PSTR
)pwszField
;
43 cch
= wcslen(pwszField
);
49 pszTemp
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(CHAR
));
52 ERR("HeapAlloc failed!\n");
53 return ERROR_NOT_ENOUGH_MEMORY
;
56 WideCharToMultiByte(CP_ACP
, 0, pwszField
, -1, pszTemp
, cch
+ 1, NULL
, NULL
);
57 StringCchCopyA(pszField
, cch
+ 1, pszTemp
);
59 HeapFree(hProcessHeap
, 0, pszTemp
);
64 static int multi_sz_lenW(const WCHAR
*str
)
66 const WCHAR
*ptr
= str
;
70 ptr
+= lstrlenW(ptr
) + 1;
73 return (ptr
- str
+ 1);// * sizeof(WCHAR); wine does this.
76 DWORD
UnicodeToAnsiZZInPlace(PWSTR pwszzField
)
80 PSTR pszField
= (PSTR
)pwszzField
;
82 lenW
= multi_sz_lenW(pwszzField
);
88 len
= WideCharToMultiByte(CP_ACP
, 0, pwszzField
, lenW
, NULL
, 0, NULL
, NULL
);
90 pszTemp
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
92 WideCharToMultiByte(CP_ACP
, 0, pwszzField
, lenW
, pszTemp
, len
, NULL
, NULL
);
94 StringCchCopyA(pszField
, len
, pszTemp
);
96 HeapFree(hProcessHeap
, 0, pszTemp
);
102 // Implement and simplify later.
105 IntProtectHandle( HANDLE hSpooler
, BOOL Close
)
109 PSPOOLER_HANDLE pHandle
;
111 EnterCriticalSection(&rtlCritSec
);
115 pHandle
= (PSPOOLER_HANDLE
)hSpooler
;
116 if ( pHandle
&& pHandle
->Sig
== SPOOLER_HANDLE_SIG
)
118 Bad
= FALSE
; // Not bad.
121 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
126 Ret
= Bad
; // Set return Level to 1 if we are BAD.
130 SetLastError(ERROR_INVALID_HANDLE
);
131 ERR("IPH : Printer Handle failed!\n");
137 if ( pHandle
->bShared
|| pHandle
->cCount
!= 0 )
139 pHandle
->bShared
= TRUE
;
140 Ret
= 2; // Return a high level and we are shared.
141 FIXME("IPH Close : We are shared\n");
145 pHandle
->bClosed
= TRUE
;
146 FIXME("IPH Close : closing.\n");
151 if ( !Ret
) // Need to be Level 0.
154 FIXME("IPH : Count %d\n",pHandle
->cCount
);
157 LeaveCriticalSection(&rtlCritSec
);
160 // 2 : Close and/or shared
169 IntUnprotectHandle( HANDLE hSpooler
)
172 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hSpooler
;
173 EnterCriticalSection(&rtlCritSec
);
174 if ( pHandle
->bShared
&& --pHandle
->cCount
== 0 )
176 pHandle
->bClosed
= TRUE
;
177 pHandle
->bShared
= FALSE
;
180 LeaveCriticalSection(&rtlCritSec
);
181 FIXME("IUH : Count %d\n",pHandle
->cCount
);
184 // ClosePrinterWorker( pHandle );
192 * Allocates memory for a Unicode string and copies the input string into it.
193 * Equivalent of wcsdup, but the returned buffer is allocated from the spooler heap and must be freed with DllFreeSplStr.
196 * The input string to copy
199 * Pointer to the copied string or NULL if no memory could be allocated.
202 AllocSplStr(PCWSTR pwszInput
)
211 // Get the length of the input string.
212 cbInput
= (wcslen(pwszInput
) + 1) * sizeof(WCHAR
);
214 // Allocate it. We don't use DllAllocSplMem here, because it unnecessarily zeroes the memory.
215 pwszOutput
= HeapAlloc(hProcessHeap
, 0, cbInput
);
218 ERR("HeapAlloc failed!\n");
222 // Copy the string and return it.
223 CopyMemory(pwszOutput
, pwszInput
, cbInput
);
228 * @name DllAllocSplMem
230 * Allocate a block of zeroed memory.
231 * Windows allocates from a separate spooler heap here while we just use the process heap.
234 * Number of bytes to allocate.
237 * A pointer to the allocated memory or NULL in case of an error.
238 * You have to free this memory using DllFreeSplMem.
241 DllAllocSplMem(DWORD dwBytes
)
243 return HeapAlloc(hProcessHeap
, HEAP_ZERO_MEMORY
, dwBytes
);
247 * @name DllFreeSplMem
249 * Frees the memory allocated with DllAllocSplMem.
252 * Pointer to the allocated memory.
255 * TRUE in case of success, FALSE otherwise.
258 DllFreeSplMem(PVOID pMem
)
260 if ( !pMem
) return TRUE
;
261 return HeapFree(hProcessHeap
, 0, pMem
);
265 * @name DllFreeSplStr
267 * Frees the string allocated with AllocSplStr.
270 * Pointer to the allocated string.
273 * TRUE in case of success, FALSE otherwise.
276 DllFreeSplStr(PWSTR pwszString
)
279 return HeapFree(hProcessHeap
, 0, pwszString
);
283 SECURITY_DESCRIPTOR
* get_sd( SECURITY_DESCRIPTOR
*sd
, DWORD
*size
)
285 PSID sid_group
, sid_owner
;
287 BOOL bSet
= FALSE
, bSetd
= FALSE
, bSets
= FALSE
;
288 PSECURITY_DESCRIPTOR absolute_sd
, retsd
;
290 if ( !IsValidSecurityDescriptor( sd
) )
295 InitializeSecurityDescriptor( &absolute_sd
, SECURITY_DESCRIPTOR_REVISION
);
297 if ( !GetSecurityDescriptorOwner( sd
, &sid_owner
, &bSet
) )
302 SetSecurityDescriptorOwner( &absolute_sd
, sid_owner
, bSet
);
304 if ( !GetSecurityDescriptorGroup( sd
, &sid_group
, &bSet
) )
309 SetSecurityDescriptorGroup( &absolute_sd
, sid_group
, bSet
);
311 if ( !GetSecurityDescriptorDacl( sd
, &bSetd
, &dacl
, &bSet
) )
316 SetSecurityDescriptorDacl( &absolute_sd
, bSetd
, dacl
, bSet
);
318 if ( !GetSecurityDescriptorSacl( sd
, &bSets
, &sacl
, &bSet
) )
323 SetSecurityDescriptorSacl( &absolute_sd
, bSets
, sacl
, bSet
);
325 *size
= GetSecurityDescriptorLength( &absolute_sd
);
327 retsd
= HeapAlloc( GetProcessHeap(), 0, *size
);
331 if ( !MakeSelfRelativeSD( &absolute_sd
, retsd
, size
) )
333 HeapFree( GetProcessHeap(), 0, retsd
);
342 UpdateTrayIcon( HANDLE hPrinter
, DWORD JobId
)
344 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hPrinter
;
345 SHCNF_PRINTJOB_INFO spji
;
346 PRINTER_INFO_1W pi1w
[MAX_GETPRINTER_SIZE
] = {0};
348 PPfpSHChangeNotify fpFunction
;
350 pHandle
->bTrayIcon
= TRUE
;
354 if (!GetPrinterW( hPrinter
, 1, (PBYTE
)&pi1w
, MAX_GETPRINTER_SIZE
, &cbNeeded
) )
356 ERR("UpdateTrayIcon : GetPrinterW cbNeeded %d\n");
360 if ( hShell32
== (HMODULE
)-1 )
362 hShell32
= LoadLibraryW(L
"shell32.dll");
367 fpFunction
= (PPfpSHChangeNotify
)GetProcAddress( hShell32
, "SHChangeNotify" );
371 fpFunction( SHCNE_CREATE
, (SHCNF_FLUSHNOWAIT
|SHCNF_FLUSH
|SHCNF_PRINTJOBW
), pi1w
->pName
, &spji
);
376 ERR("UpdateTrayIcon : No Shell32!\n");