1 /* 2 * PROJECT: ReactOS Spooler API 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Functions related to Forms 5 * COPYRIGHT: Copyright 2017 Colin Finck (colin@reactos.org) 6 */ 7 8 #include "precomp.h" 9 #include <marshalling/forms.h> 10 11 BOOL WINAPI 12 AddFormA(HANDLE hPrinter, DWORD Level, PBYTE pForm) 13 { 14 FORM_INFO_2W pfi2W; 15 PFORM_INFO_2A pfi2A; 16 DWORD len; 17 BOOL res; 18 19 pfi2A = (PFORM_INFO_2A)pForm; 20 21 TRACE("AddFormA(%p, %lu, %p)\n", hPrinter, Level, pForm); 22 23 if ((Level < 1) || (Level > 2)) 24 { 25 ERR("Level = %d, unsupported!\n", Level); 26 SetLastError(ERROR_INVALID_LEVEL); 27 return FALSE; 28 } 29 30 if (!pfi2A) 31 { 32 SetLastError(ERROR_INVALID_PARAMETER); 33 return FALSE; 34 } 35 36 ZeroMemory(&pfi2W, sizeof(FORM_INFO_2W)); 37 38 if (pfi2A->pName) 39 { 40 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, NULL, 0); 41 pfi2W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 42 MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, pfi2W.pName, len); 43 } 44 45 pfi2W.Flags = pfi2A->Flags; 46 pfi2W.Size = pfi2A->Size; 47 pfi2W.ImageableArea = pfi2A->ImageableArea; 48 49 if (Level > 1) 50 { 51 if (pfi2A->pKeyword) 52 { 53 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, NULL, 0); 54 pfi2W.pKeyword = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 55 MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, (LPWSTR)pfi2W.pKeyword, len); 56 } 57 58 if (pfi2A->pMuiDll) 59 { 60 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, NULL, 0); 61 pfi2W.pMuiDll = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 62 MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, (LPWSTR)pfi2W.pMuiDll, len); 63 } 64 65 if (pfi2A->pDisplayName) 66 { 67 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, NULL, 0); 68 pfi2W.pDisplayName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 69 MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, (LPWSTR)pfi2W.pDisplayName, len); 70 } 71 pfi2W.StringType = pfi2A->StringType; 72 pfi2W.dwResourceId = pfi2A->dwResourceId; 73 pfi2W.wLangId = pfi2A->wLangId; 74 } 75 76 res = AddFormW( hPrinter, Level, (PBYTE)&pfi2W ); 77 78 if (pfi2W.pName) HeapFree(GetProcessHeap(), 0, pfi2W.pName); 79 if (pfi2W.pKeyword) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pKeyword); 80 if (pfi2W.pMuiDll) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pMuiDll); 81 if (pfi2W.pDisplayName) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pDisplayName); 82 83 return res; 84 } 85 86 BOOL WINAPI 87 AddFormW(HANDLE hPrinter, DWORD Level, PBYTE pForm) 88 { 89 DWORD dwErrorCode; 90 WINSPOOL_FORM_CONTAINER FormInfoContainer; 91 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 92 93 TRACE("AddFormW(%p, %lu, %p)\n", hPrinter, Level, pForm); 94 95 // Sanity checks. 96 if (!pHandle) 97 { 98 dwErrorCode = ERROR_INVALID_HANDLE; 99 return FALSE; 100 } 101 102 if ((Level < 1) || (Level > 2)) 103 { 104 ERR("Level = %d, unsupported!\n", Level); 105 SetLastError(ERROR_INVALID_LEVEL); 106 return FALSE; 107 } 108 109 FormInfoContainer.FormInfo.pFormInfo1 = (WINSPOOL_FORM_INFO_1*)pForm; 110 FormInfoContainer.Level = Level; 111 112 // Do the RPC call 113 RpcTryExcept 114 { 115 dwErrorCode = _RpcAddForm(pHandle->hPrinter, &FormInfoContainer); 116 } 117 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 118 { 119 dwErrorCode = RpcExceptionCode(); 120 ERR("_RpcAddForm failed with exception code %lu!\n", dwErrorCode); 121 } 122 RpcEndExcept; 123 124 SetLastError(dwErrorCode); 125 return (dwErrorCode == ERROR_SUCCESS); 126 } 127 128 BOOL WINAPI 129 DeleteFormA(HANDLE hPrinter, PSTR pFormName) 130 { 131 UNICODE_STRING FormNameW; 132 BOOL Ret; 133 134 TRACE("DeleteFormA(%p, %s)\n", hPrinter, pFormName); 135 136 AsciiToUnicode(&FormNameW, pFormName); 137 138 Ret = DeleteFormW( hPrinter, FormNameW.Buffer ); 139 140 RtlFreeUnicodeString(&FormNameW); 141 142 return Ret; 143 } 144 145 BOOL WINAPI 146 DeleteFormW(HANDLE hPrinter, PWSTR pFormName) 147 { 148 DWORD dwErrorCode; 149 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 150 151 TRACE("DeleteFormW(%p, %S)\n", hPrinter, pFormName); 152 153 // Sanity checks. 154 if (!pHandle) 155 { 156 dwErrorCode = ERROR_INVALID_HANDLE; 157 return FALSE; 158 } 159 160 // Do the RPC call 161 RpcTryExcept 162 { 163 dwErrorCode = _RpcDeleteForm(pHandle->hPrinter, pFormName); 164 } 165 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 166 { 167 dwErrorCode = RpcExceptionCode(); 168 ERR("_RpcDeleteForm failed with exception code %lu!\n", dwErrorCode); 169 } 170 RpcEndExcept; 171 172 SetLastError(dwErrorCode); 173 return (dwErrorCode == ERROR_SUCCESS); 174 } 175 176 BOOL WINAPI 177 EnumFormsA(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) 178 { 179 DWORD dwErrorCode, i; 180 PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm; 181 PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm; 182 183 TRACE("EnumFormsA(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); 184 185 if ( EnumFormsW( hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned ) ) 186 { 187 for ( i = 0; i < *pcReturned; i++ ) 188 { 189 switch ( Level ) 190 { 191 case 2: 192 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pKeyword); 193 if (dwErrorCode != ERROR_SUCCESS) 194 { 195 goto Cleanup; 196 } 197 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pMuiDll); 198 if (dwErrorCode != ERROR_SUCCESS) 199 { 200 goto Cleanup; 201 } 202 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pDisplayName); 203 if (dwErrorCode != ERROR_SUCCESS) 204 { 205 goto Cleanup; 206 } 207 dwErrorCode = UnicodeToAnsiInPlace(pfi2w[i].pName); 208 if (dwErrorCode != ERROR_SUCCESS) 209 { 210 goto Cleanup; 211 } 212 break; 213 case 1: 214 dwErrorCode = UnicodeToAnsiInPlace(pfi1w[i].pName); 215 if (dwErrorCode != ERROR_SUCCESS) 216 { 217 goto Cleanup; 218 } 219 } 220 } 221 return TRUE; 222 } 223 Cleanup: 224 return FALSE; 225 } 226 227 BOOL WINAPI 228 EnumFormsW(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) 229 { 230 DWORD dwErrorCode; 231 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 232 233 TRACE("EnumFormsW(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); 234 235 // Sanity checks. 236 if (!pHandle) 237 { 238 dwErrorCode = ERROR_INVALID_HANDLE; 239 goto Cleanup; 240 } 241 242 if ((Level < 1) || (Level > 2)) 243 { 244 ERR("Level = %d, unsupported!\n", Level); 245 dwErrorCode = ERROR_INVALID_LEVEL; 246 goto Cleanup; 247 } 248 249 // Do the RPC call 250 RpcTryExcept 251 { 252 dwErrorCode = _RpcEnumForms(pHandle->hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); 253 } 254 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 255 { 256 dwErrorCode = RpcExceptionCode(); 257 ERR("_RpcEnumForms failed with exception code %lu!\n", dwErrorCode); 258 } 259 RpcEndExcept; 260 261 if (dwErrorCode == ERROR_SUCCESS) 262 { 263 // Replace relative offset addresses in the output by absolute pointers. 264 ASSERT(Level >= 1 && Level <= 2); 265 MarshallUpStructuresArray(cbBuf, pForm, *pcReturned, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE); 266 } 267 268 Cleanup: 269 SetLastError(dwErrorCode); 270 return (dwErrorCode == ERROR_SUCCESS); 271 } 272 273 BOOL WINAPI 274 GetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded) 275 { 276 DWORD dwErrorCode, len; 277 LPWSTR FormNameW = NULL; 278 PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm; 279 PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm; 280 281 TRACE("GetFormA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded); 282 283 if (pFormName) 284 { 285 len = MultiByteToWideChar(CP_ACP, 0, pFormName, -1, NULL, 0); 286 FormNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 287 MultiByteToWideChar(CP_ACP, 0, pFormName, -1, FormNameW, len); 288 } 289 290 if ( GetFormW( hPrinter, FormNameW, Level, pForm, cbBuf, pcbNeeded ) ) 291 { 292 switch ( Level ) 293 { 294 case 2: 295 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pKeyword); 296 if (dwErrorCode != ERROR_SUCCESS) 297 { 298 goto Cleanup; 299 } 300 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pMuiDll); 301 if (dwErrorCode != ERROR_SUCCESS) 302 { 303 goto Cleanup; 304 } 305 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pDisplayName); 306 if (dwErrorCode != ERROR_SUCCESS) 307 { 308 goto Cleanup; 309 } 310 dwErrorCode = UnicodeToAnsiInPlace(pfi2w->pName); 311 if (dwErrorCode != ERROR_SUCCESS) 312 { 313 goto Cleanup; 314 } 315 break; 316 case 1: 317 dwErrorCode = UnicodeToAnsiInPlace(pfi1w->pName); 318 if (dwErrorCode != ERROR_SUCCESS) 319 { 320 goto Cleanup; 321 } 322 } 323 } 324 Cleanup: 325 if (FormNameW) HeapFree(GetProcessHeap(), 0, FormNameW); 326 return (dwErrorCode == ERROR_SUCCESS); 327 } 328 329 BOOL WINAPI 330 GetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded) 331 { 332 DWORD dwErrorCode; 333 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 334 335 TRACE("GetFormW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded); 336 337 // Sanity checks. 338 if (!pHandle) 339 { 340 dwErrorCode = ERROR_INVALID_HANDLE; 341 goto Cleanup; 342 } 343 344 // Dismiss invalid levels already at this point. 345 if ((Level < 1) || (Level > 2)) 346 { 347 ERR("Level = %d, unsupported!\n", Level); 348 dwErrorCode = ERROR_INVALID_LEVEL; 349 goto Cleanup; 350 } 351 352 if (cbBuf && pForm) 353 ZeroMemory(pForm, cbBuf); 354 355 // Do the RPC call 356 RpcTryExcept 357 { 358 dwErrorCode = _RpcGetForm(pHandle->hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded); 359 } 360 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 361 { 362 dwErrorCode = RpcExceptionCode(); 363 ERR("_RpcGetForm failed with exception code %lu!\n", dwErrorCode); 364 } 365 RpcEndExcept; 366 367 if (dwErrorCode == ERROR_SUCCESS) 368 { 369 // Replace relative offset addresses in the output by absolute pointers. 370 ASSERT(Level >= 1 && Level <= 2); 371 MarshallUpStructure(cbBuf, pForm, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE); 372 } 373 374 Cleanup: 375 SetLastError(dwErrorCode); 376 return (dwErrorCode == ERROR_SUCCESS); 377 } 378 379 BOOL WINAPI 380 SetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm) 381 { 382 FORM_INFO_2W pfi2W; 383 FORM_INFO_2A * pfi2A; 384 LPWSTR FormNameW = NULL; 385 DWORD len; 386 BOOL res; 387 388 pfi2A = (FORM_INFO_2A *) pForm; 389 390 TRACE("SetFormA(%p, %s, %lu, %p)\n", hPrinter, pFormName, Level, pForm); 391 392 if ((Level < 1) || (Level > 2)) 393 { 394 ERR("Level = %d, unsupported!\n", Level); 395 SetLastError(ERROR_INVALID_LEVEL); 396 return FALSE; 397 } 398 399 if (!pfi2A) 400 { 401 SetLastError(ERROR_INVALID_PARAMETER); 402 return FALSE; 403 } 404 405 if (pFormName) 406 { 407 len = MultiByteToWideChar(CP_ACP, 0, pFormName, -1, NULL, 0); 408 FormNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 409 MultiByteToWideChar(CP_ACP, 0, pFormName, -1, FormNameW, len); 410 } 411 412 ZeroMemory(&pfi2W, sizeof(FORM_INFO_2W)); 413 414 if (pfi2A->pName) 415 { 416 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, NULL, 0); 417 pfi2W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 418 MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, pfi2W.pName, len); 419 } 420 421 pfi2W.Flags = pfi2A->Flags; 422 pfi2W.Size = pfi2A->Size; 423 pfi2W.ImageableArea = pfi2A->ImageableArea; 424 425 if (Level > 1) 426 { 427 if (pfi2A->pKeyword) 428 { 429 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, NULL, 0); 430 pfi2W.pKeyword = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 431 MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, (LPWSTR)pfi2W.pKeyword, len); 432 } 433 434 if (pfi2A->pMuiDll) 435 { 436 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, NULL, 0); 437 pfi2W.pMuiDll = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 438 MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, (LPWSTR)pfi2W.pMuiDll, len); 439 } 440 441 if (pfi2A->pDisplayName) 442 { 443 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, NULL, 0); 444 pfi2W.pDisplayName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 445 MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, (LPWSTR)pfi2W.pDisplayName, len); 446 } 447 pfi2W.StringType = pfi2A->StringType; 448 pfi2W.dwResourceId = pfi2A->dwResourceId; 449 pfi2W.wLangId = pfi2A->wLangId; 450 } 451 452 res = SetFormW( hPrinter, FormNameW, Level, (PBYTE)&pfi2W ); 453 454 if (FormNameW) HeapFree(GetProcessHeap(), 0, FormNameW); 455 if (pfi2W.pName) HeapFree(GetProcessHeap(), 0, pfi2W.pName); 456 if (pfi2W.pKeyword) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pKeyword); 457 if (pfi2W.pMuiDll) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pMuiDll); 458 if (pfi2W.pDisplayName) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pDisplayName); 459 460 return res; 461 } 462 463 BOOL WINAPI 464 SetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm) 465 { 466 DWORD dwErrorCode; 467 WINSPOOL_FORM_CONTAINER FormInfoContainer; 468 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 469 470 TRACE("SetFormW(%p, %S, %lu, %p)\n", hPrinter, pFormName, Level, pForm); 471 472 // Sanity checks. 473 if (!pHandle) 474 { 475 ERR("Level = %d, unsupported!\n", Level); 476 dwErrorCode = ERROR_INVALID_HANDLE; 477 return FALSE; 478 } 479 480 FormInfoContainer.FormInfo.pFormInfo1 = (WINSPOOL_FORM_INFO_1*)pForm; 481 FormInfoContainer.Level = Level; 482 483 // Do the RPC call 484 RpcTryExcept 485 { 486 dwErrorCode = _RpcSetForm(pHandle->hPrinter, pFormName, &FormInfoContainer); 487 } 488 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 489 { 490 dwErrorCode = RpcExceptionCode(); 491 } 492 RpcEndExcept; 493 494 SetLastError(dwErrorCode); 495 return (dwErrorCode == ERROR_SUCCESS); 496 } 497