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