[Printing] Update and Add Functions
[reactos.git] / win32ss / printing / base / winspool / printerdrivers.c
1 /*
2 * PROJECT: ReactOS Spooler API
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions related to Printer Drivers
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
6 */
7
8 #include "precomp.h"
9 #include <marshalling/printerdrivers.h>
10
11 extern const WCHAR wszCurrentEnvironment[];
12
13 static int multi_sz_lenA(const char *str)
14 {
15 const char *ptr = str;
16 if(!str) return 0;
17 do
18 {
19 ptr += lstrlenA(ptr) + 1;
20 } while(*ptr);
21
22 return ptr - str + 1;
23 }
24
25 static int multi_sz_lenW(const WCHAR *str)
26 {
27 const WCHAR *ptr = str;
28 if (!str) return 0;
29 do
30 {
31 ptr += lstrlenW(ptr) + 1;
32 } while (*ptr);
33
34 return (ptr - str + 1);
35 }
36
37 BOOL WINAPI
38 AddPrinterDriverA(PSTR pName, DWORD Level, PBYTE pDriverInfo)
39 {
40 TRACE("AddPrinterDriverA(%s, %lu, %p)\n", pName, Level, pDriverInfo);
41 return AddPrinterDriverExA(pName, Level, pDriverInfo, APD_COPY_NEW_FILES);
42 }
43
44 BOOL WINAPI
45 AddPrinterDriverExA(PSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags)
46 {
47 PDRIVER_INFO_8A pdiA;
48 DRIVER_INFO_8W diW;
49 LPWSTR nameW = NULL;
50 DWORD lenA;
51 DWORD len;
52 BOOL res = FALSE;
53
54 TRACE("AddPrinterDriverExA(%s, %d, %p, 0x%x)\n", debugstr_a(pName), Level, pDriverInfo, dwFileCopyFlags);
55
56 pdiA = (DRIVER_INFO_8A *) pDriverInfo;
57 ZeroMemory(&diW, sizeof(diW));
58
59 if (Level < 2 || Level == 5 || Level == 7 || Level > 8)
60 {
61 SetLastError(ERROR_INVALID_LEVEL);
62 return FALSE;
63 }
64
65 if (pdiA == NULL)
66 {
67 SetLastError(ERROR_INVALID_PARAMETER);
68 return FALSE;
69 }
70
71 /* convert servername to unicode */
72 if (pName)
73 {
74 len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
75 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
76 MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len);
77 }
78
79 /* common fields */
80 diW.cVersion = pdiA->cVersion;
81
82 if (pdiA->pName)
83 {
84 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pName, -1, NULL, 0);
85 diW.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
86 MultiByteToWideChar(CP_ACP, 0, pdiA->pName, -1, diW.pName, len);
87 }
88
89 if (pdiA->pEnvironment)
90 {
91 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pEnvironment, -1, NULL, 0);
92 diW.pEnvironment = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
93 MultiByteToWideChar(CP_ACP, 0, pdiA->pEnvironment, -1, diW.pEnvironment, len);
94 }
95
96 if (pdiA->pDriverPath)
97 {
98 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pDriverPath, -1, NULL, 0);
99 diW.pDriverPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
100 MultiByteToWideChar(CP_ACP, 0, pdiA->pDriverPath, -1, diW.pDriverPath, len);
101 }
102
103 if (pdiA->pDataFile)
104 {
105 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pDataFile, -1, NULL, 0);
106 diW.pDataFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
107 MultiByteToWideChar(CP_ACP, 0, pdiA->pDataFile, -1, diW.pDataFile, len);
108 }
109
110 if (pdiA->pConfigFile)
111 {
112 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pConfigFile, -1, NULL, 0);
113 diW.pConfigFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
114 MultiByteToWideChar(CP_ACP, 0, pdiA->pConfigFile, -1, diW.pConfigFile, len);
115 }
116
117 if ((Level > 2) && pdiA->pHelpFile)
118 {
119 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pHelpFile, -1, NULL, 0);
120 diW.pHelpFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
121 MultiByteToWideChar(CP_ACP, 0, pdiA->pHelpFile, -1, diW.pHelpFile, len);
122 }
123
124 if ((Level > 2) && pdiA->pDependentFiles)
125 {
126 lenA = multi_sz_lenA(pdiA->pDependentFiles);
127 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pDependentFiles, lenA, NULL, 0);
128 diW.pDependentFiles = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
129 MultiByteToWideChar(CP_ACP, 0, pdiA->pDependentFiles, lenA, diW.pDependentFiles, len);
130 }
131
132 if ((Level > 2) && pdiA->pMonitorName)
133 {
134 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pMonitorName, -1, NULL, 0);
135 diW.pMonitorName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
136 MultiByteToWideChar(CP_ACP, 0, pdiA->pMonitorName, -1, diW.pMonitorName, len);
137 }
138
139 if ((Level > 2) && pdiA->pDefaultDataType)
140 {
141 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pDefaultDataType, -1, NULL, 0);
142 diW.pDefaultDataType = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
143 MultiByteToWideChar(CP_ACP, 0, pdiA->pDefaultDataType, -1, diW.pDefaultDataType, len);
144 }
145
146 if ((Level > 3) && pdiA->pszzPreviousNames)
147 {
148 lenA = multi_sz_lenA(pdiA->pszzPreviousNames);
149 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszzPreviousNames, lenA, NULL, 0);
150 diW.pszzPreviousNames = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
151 MultiByteToWideChar(CP_ACP, 0, pdiA->pszzPreviousNames, lenA, diW.pszzPreviousNames, len);
152 }
153
154 if (Level > 5)
155 {
156 diW.ftDriverDate = pdiA->ftDriverDate;
157 diW.dwlDriverVersion = pdiA->dwlDriverVersion;
158 }
159
160 if ((Level > 5) && pdiA->pszMfgName)
161 {
162 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszMfgName, -1, NULL, 0);
163 diW.pszMfgName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
164 MultiByteToWideChar(CP_ACP, 0, pdiA->pszMfgName, -1, diW.pszMfgName, len);
165 }
166
167 if ((Level > 5) && pdiA->pszOEMUrl)
168 {
169 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszOEMUrl, -1, NULL, 0);
170 diW.pszOEMUrl = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
171 MultiByteToWideChar(CP_ACP, 0, pdiA->pszOEMUrl, -1, diW.pszOEMUrl, len);
172 }
173
174 if ((Level > 5) && pdiA->pszHardwareID)
175 {
176 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszHardwareID, -1, NULL, 0);
177 diW.pszHardwareID = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
178 MultiByteToWideChar(CP_ACP, 0, pdiA->pszHardwareID, -1, diW.pszHardwareID, len);
179 }
180
181 if ((Level > 5) && pdiA->pszProvider)
182 {
183 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszProvider, -1, NULL, 0);
184 diW.pszProvider = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
185 MultiByteToWideChar(CP_ACP, 0, pdiA->pszProvider, -1, diW.pszProvider, len);
186 }
187
188 if ((Level > 7) && pdiA->pszPrintProcessor)
189 {
190 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszPrintProcessor, -1, NULL, 0);
191 diW.pszPrintProcessor = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
192 MultiByteToWideChar(CP_ACP, 0, pdiA->pszPrintProcessor, -1, diW.pszPrintProcessor, len);
193 }
194
195 if ((Level > 7) && pdiA->pszVendorSetup)
196 {
197 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszVendorSetup, -1, NULL, 0);
198 diW.pszVendorSetup = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
199 MultiByteToWideChar(CP_ACP, 0, pdiA->pszVendorSetup, -1, diW.pszVendorSetup, len);
200 }
201
202 if ((Level > 7) && pdiA->pszzColorProfiles)
203 {
204 lenA = multi_sz_lenA(pdiA->pszzColorProfiles);
205 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszzColorProfiles, lenA, NULL, 0);
206 diW.pszzColorProfiles = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
207 MultiByteToWideChar(CP_ACP, 0, pdiA->pszzColorProfiles, lenA, diW.pszzColorProfiles, len);
208 }
209
210 if ((Level > 7) && pdiA->pszInfPath)
211 {
212 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszInfPath, -1, NULL, 0);
213 diW.pszInfPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
214 MultiByteToWideChar(CP_ACP, 0, pdiA->pszInfPath, -1, diW.pszInfPath, len);
215 }
216
217 if ((Level > 7) && pdiA->pszzCoreDriverDependencies)
218 {
219 lenA = multi_sz_lenA(pdiA->pszzCoreDriverDependencies);
220 len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszzCoreDriverDependencies, lenA, NULL, 0);
221 diW.pszzCoreDriverDependencies = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
222 MultiByteToWideChar(CP_ACP, 0, pdiA->pszzCoreDriverDependencies, lenA, diW.pszzCoreDriverDependencies, len);
223 }
224
225 if (Level > 7)
226 {
227 diW.dwPrinterDriverAttributes = pdiA->dwPrinterDriverAttributes;
228 diW.ftMinInboxDriverVerDate = pdiA->ftMinInboxDriverVerDate;
229 diW.dwlMinInboxDriverVerVersion = pdiA->dwlMinInboxDriverVerVersion;
230 }
231
232 res = AddPrinterDriverExW(nameW, Level, (LPBYTE) &diW, dwFileCopyFlags);
233
234 TRACE("got %u with %u\n", res, GetLastError());
235 if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
236 if (diW.pName) HeapFree(GetProcessHeap(), 0, diW.pName);
237 if (diW.pEnvironment) HeapFree(GetProcessHeap(), 0, diW.pEnvironment);
238 if (diW.pDriverPath) HeapFree(GetProcessHeap(), 0, diW.pDriverPath);
239 if (diW.pDataFile) HeapFree(GetProcessHeap(), 0, diW.pDataFile);
240 if (diW.pConfigFile) HeapFree(GetProcessHeap(), 0, diW.pConfigFile);
241 if (diW.pHelpFile) HeapFree(GetProcessHeap(), 0, diW.pHelpFile);
242 if (diW.pDependentFiles) HeapFree(GetProcessHeap(), 0, diW.pDependentFiles);
243 if (diW.pMonitorName) HeapFree(GetProcessHeap(), 0, diW.pMonitorName);
244 if (diW.pDefaultDataType) HeapFree(GetProcessHeap(), 0, diW.pDefaultDataType);
245 if (diW.pszzPreviousNames) HeapFree(GetProcessHeap(), 0, diW.pszzPreviousNames);
246 if (diW.pszMfgName) HeapFree(GetProcessHeap(), 0, diW.pszMfgName);
247 if (diW.pszOEMUrl) HeapFree(GetProcessHeap(), 0, diW.pszOEMUrl);
248 if (diW.pszHardwareID) HeapFree(GetProcessHeap(), 0, diW.pszHardwareID);
249 if (diW.pszProvider) HeapFree(GetProcessHeap(), 0, diW.pszProvider);
250 if (diW.pszPrintProcessor) HeapFree(GetProcessHeap(), 0, diW.pszPrintProcessor);
251 if (diW.pszVendorSetup) HeapFree(GetProcessHeap(), 0, diW.pszVendorSetup);
252 if (diW.pszzColorProfiles) HeapFree(GetProcessHeap(), 0, diW.pszzColorProfiles);
253 if (diW.pszInfPath) HeapFree(GetProcessHeap(), 0, diW.pszInfPath);
254 if (diW.pszzCoreDriverDependencies) HeapFree(GetProcessHeap(), 0, diW.pszzCoreDriverDependencies);
255
256 TRACE("=> %u with %u\n", res, GetLastError());
257 return res;
258 }
259
260 BOOL WINAPI
261 AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags)
262 {
263 DWORD dwErrorCode = ERROR_SUCCESS;
264 WINSPOOL_DRIVER_INFO_8 * pdi = NULL;
265 WINSPOOL_DRIVER_CONTAINER pDriverContainer;
266
267 TRACE("AddPrinterDriverExW(%S, %lu, %p, %lu)\n", pName, Level, pDriverInfo, dwFileCopyFlags);
268
269 pDriverContainer.Level = Level;
270
271 switch (Level)
272 {
273 case 8:
274 {
275 PDRIVER_INFO_8W pdi8w = (PDRIVER_INFO_8W)pDriverInfo;
276 pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_8));
277
278 pdi->pPrintProcessor = pdi8w->pszPrintProcessor;
279 pdi->pVendorSetup = pdi8w->pszVendorSetup;
280
281 pdi->pszzColorProfiles = pdi8w->pszzColorProfiles;
282 pdi->cchColorProfiles = 0;
283 if ( pdi8w->pszzColorProfiles && *pdi8w->pszzColorProfiles )
284 {
285 pdi->cchColorProfiles = multi_sz_lenW( pdi8w->pszzColorProfiles );
286 }
287
288 pdi->pInfPath = pdi8w->pszInfPath;
289
290 pdi->pszzCoreDriverDependencies = pdi8w->pszzCoreDriverDependencies;
291 pdi->cchCoreDependencies = 0;
292 if ( pdi8w->pszzCoreDriverDependencies && *pdi8w->pszzCoreDriverDependencies )
293 {
294 pdi->cchCoreDependencies = multi_sz_lenW( pdi8w->pszzCoreDriverDependencies );
295 }
296
297 pdi->ftMinInboxDriverVerDate = pdi8w->ftMinInboxDriverVerDate;
298 pdi->dwlMinInboxDriverVerVersion = pdi8w->dwlMinInboxDriverVerVersion;
299 }
300 case 6:
301 {
302 PDRIVER_INFO_6W pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
303 if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_6));
304
305 pdi->pMfgName = pdi6w->pszMfgName;
306 pdi->pOEMUrl = pdi6w->pszOEMUrl;
307 pdi->pHardwareID = pdi6w->pszHardwareID;
308 pdi->pProvider = pdi6w->pszProvider;
309 pdi->ftDriverDate = pdi6w->ftDriverDate;
310 pdi->dwlDriverVersion = pdi6w->dwlDriverVersion;
311 }
312 case 4:
313 {
314 PDRIVER_INFO_4W pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
315 if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_4));
316
317 pdi->pszzPreviousNames = pdi4w->pszzPreviousNames;
318 pdi->cchPreviousNames = 0;
319 if ( pdi4w->pDependentFiles && *pdi4w->pDependentFiles )
320 {
321 pdi->cchPreviousNames = multi_sz_lenW( pdi4w->pDependentFiles );
322 }
323 }
324 case 3:
325 {
326 PDRIVER_INFO_3W pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
327 if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_3));
328
329 pdi->pHelpFile = pdi3w->pHelpFile;
330 pdi->pDependentFiles = pdi3w->pDependentFiles;
331 pdi->pMonitorName = pdi3w->pMonitorName;
332 pdi->pDefaultDataType = pdi3w->pDefaultDataType;
333
334 pdi->pDependentFiles = pdi3w->pDependentFiles;
335 pdi->cchDependentFiles = 0;
336 if ( pdi3w->pDependentFiles && *pdi3w->pDependentFiles )
337 {
338 pdi->cchDependentFiles = multi_sz_lenW( pdi3w->pDependentFiles );
339 }
340 }
341 case 2:
342 {
343 PDRIVER_INFO_2W pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
344 if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_2));
345
346 pdi->pName = pdi2w->pName;
347
348 pdi->pEnvironment = pdi2w->pEnvironment;
349 if ( !pdi2w->pEnvironment || !*pdi2w->pEnvironment )
350 {
351 pdi2w->pEnvironment = (PWSTR)wszCurrentEnvironment;
352 }
353
354 pdi->pDriverPath = pdi2w->pDriverPath;
355 pdi->pDataFile = pdi2w->pDataFile;
356 pdi->pConfigFile = pdi2w->pConfigFile;
357 }
358 break;
359
360 default:
361 SetLastError(ERROR_INVALID_LEVEL);
362 return FALSE;
363 }
364
365 pDriverContainer.DriverInfo.Level8 = pdi;
366
367 RpcTryExcept
368 {
369 dwErrorCode = _RpcAddPrinterDriverEx( pName, &pDriverContainer, dwFileCopyFlags );
370 }
371 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
372 {
373 dwErrorCode = RpcExceptionCode();
374 ERR("_RpcAddPrinterDriverEx failed with exception code %lu!\n", dwErrorCode);
375 }
376 RpcEndExcept;
377
378 if ( pdi ) HeapFree( GetProcessHeap(), 0, pdi );
379
380 SetLastError(dwErrorCode);
381 return (dwErrorCode == ERROR_SUCCESS);
382 }
383
384 BOOL WINAPI
385 AddPrinterDriverW(PWSTR pName, DWORD Level, PBYTE pDriverInfo)
386 {
387 TRACE("AddPrinterDriverW(%S, %lu, %p)\n", pName, Level, pDriverInfo);
388 return AddPrinterDriverExW(pName, Level, pDriverInfo, APD_COPY_NEW_FILES);
389 }
390
391 BOOL WINAPI
392 DeletePrinterDriverA(PSTR pName, PSTR pEnvironment, PSTR pDriverName)
393 {
394 TRACE("DeletePrinterDriverA(%s, %s, %s)\n", pName, pEnvironment, pDriverName);
395 return DeletePrinterDriverExA(pName, pEnvironment, pDriverName, 0, 0);
396 }
397
398 BOOL WINAPI
399 DeletePrinterDriverExA(PSTR pName, PSTR pEnvironment, PSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag)
400 {
401 DWORD dwErrorCode;
402 UNICODE_STRING NameW, EnvW, DriverW;
403 BOOL ret;
404
405 TRACE("DeletePrinterDriverExA(%s, %s, %s, %lu, %lu)\n", pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag);
406
407 AsciiToUnicode(&NameW, pName);
408 AsciiToUnicode(&EnvW, pEnvironment);
409 AsciiToUnicode(&DriverW, pDriverName);
410
411 ret = DeletePrinterDriverExW(NameW.Buffer, EnvW.Buffer, DriverW.Buffer, dwDeleteFlag, dwVersionFlag);
412
413 dwErrorCode = GetLastError();
414
415 RtlFreeUnicodeString(&DriverW);
416 RtlFreeUnicodeString(&EnvW);
417 RtlFreeUnicodeString(&NameW);
418
419 SetLastError(dwErrorCode);
420 return ret;
421 }
422
423 BOOL WINAPI
424 DeletePrinterDriverExW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag)
425 {
426 DWORD dwErrorCode;
427
428 TRACE("DeletePrinterDriverExW(%S, %S, %S, %lu, %lu)\n", pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag);
429
430 if ( !pDriverName || !*pDriverName )
431 {
432 SetLastError(ERROR_INVALID_PARAMETER);
433 return FALSE;
434 }
435
436 if ( !pEnvironment || !*pEnvironment )
437 {
438 pEnvironment = (PWSTR)wszCurrentEnvironment;
439 }
440
441 // Do the RPC call.
442 RpcTryExcept
443 {
444 dwErrorCode = _RpcDeletePrinterDriverEx(pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag);
445 }
446 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
447 {
448 dwErrorCode = RpcExceptionCode();
449 ERR("_RpcDeletePrinterDriverEx failed with exception code %lu!\n", dwErrorCode);
450 }
451 RpcEndExcept;
452
453 SetLastError(dwErrorCode);
454 return (dwErrorCode == ERROR_SUCCESS);
455
456 }
457
458 BOOL WINAPI
459 DeletePrinterDriverW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName)
460 {
461 TRACE("DeletePrinterDriverW(%S, %S, %S)\n", pName, pEnvironment, pDriverName);
462 return DeletePrinterDriverExW(pName, pEnvironment, pDriverName, 0, 0);
463 }
464
465 BOOL WINAPI
466 EnumPrinterDriversA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
467 {
468 BOOL ret = FALSE;
469 DWORD dwErrorCode, i;
470 UNICODE_STRING pNameW, pEnvironmentW;
471 PWSTR pwstrNameW, pwstrEnvironmentW;
472 PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo;
473 PDRIVER_INFO_8W pdi8w = (PDRIVER_INFO_8W)pDriverInfo;
474
475 FIXME("EnumPrinterDriversA(%s, %s, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
476
477 pwstrNameW = AsciiToUnicode(&pNameW, pName);
478 pwstrEnvironmentW = AsciiToUnicode(&pEnvironmentW, pEnvironment);
479
480 ret = EnumPrinterDriversW( pwstrNameW, pwstrEnvironmentW, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned );
481
482 dwErrorCode = GetLastError();
483
484 if (ret)
485 {
486 for ( i = 0; i < *pcReturned; i++ )
487 {
488 switch (Level)
489 {
490 case 1:
491 {
492 dwErrorCode = UnicodeToAnsiInPlace(pdi1w[i].pName);
493 if (dwErrorCode != ERROR_SUCCESS)
494 {
495 goto Cleanup;
496 }
497 break;
498 }
499 case 8:
500 {
501 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszPrintProcessor);
502 if (dwErrorCode != ERROR_SUCCESS)
503 {
504 goto Cleanup;
505 }
506 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszVendorSetup);
507 if (dwErrorCode != ERROR_SUCCESS)
508 {
509 goto Cleanup;
510 }
511 dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w[i].pszzColorProfiles);
512 if (dwErrorCode != ERROR_SUCCESS)
513 {
514 goto Cleanup;
515 }
516 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszInfPath);
517 if (dwErrorCode != ERROR_SUCCESS)
518 {
519 goto Cleanup;
520 }
521 dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w[i].pszzCoreDriverDependencies);
522 if (dwErrorCode != ERROR_SUCCESS)
523 {
524 goto Cleanup;
525 }
526 }
527 case 6:
528 {
529 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszMfgName);
530 if (dwErrorCode != ERROR_SUCCESS)
531 {
532 goto Cleanup;
533 }
534
535 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszOEMUrl);
536 if (dwErrorCode != ERROR_SUCCESS)
537 {
538 goto Cleanup;
539 }
540
541 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszHardwareID);
542 if (dwErrorCode != ERROR_SUCCESS)
543 {
544 goto Cleanup;
545 }
546
547 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszProvider);
548 if (dwErrorCode != ERROR_SUCCESS)
549 {
550 goto Cleanup;
551 }
552 }
553 case 4:
554 {
555 dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w[i].pszzPreviousNames);
556 if (dwErrorCode != ERROR_SUCCESS)
557 {
558 goto Cleanup;
559 }
560 }
561 case 3:
562 {
563 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pHelpFile);
564 if (dwErrorCode != ERROR_SUCCESS)
565 {
566 goto Cleanup;
567 }
568
569 dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w[i].pDependentFiles);
570 if (dwErrorCode != ERROR_SUCCESS)
571 {
572 goto Cleanup;
573 }
574
575 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pMonitorName);
576 if (dwErrorCode != ERROR_SUCCESS)
577 {
578 goto Cleanup;
579 }
580
581 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pDefaultDataType);
582 if (dwErrorCode != ERROR_SUCCESS)
583 {
584 goto Cleanup;
585 }
586 }
587 case 2:
588 case 5:
589 {
590 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pName);
591 if (dwErrorCode != ERROR_SUCCESS)
592 {
593 goto Cleanup;
594 }
595
596 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pEnvironment);
597 if (dwErrorCode != ERROR_SUCCESS)
598 {
599 goto Cleanup;
600 }
601
602 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pDriverPath);
603 if (dwErrorCode != ERROR_SUCCESS)
604 {
605 goto Cleanup;
606 }
607
608 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pDataFile);
609 if (dwErrorCode != ERROR_SUCCESS)
610 {
611 goto Cleanup;
612 }
613
614 dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pConfigFile);
615 if (dwErrorCode != ERROR_SUCCESS)
616 {
617 goto Cleanup;
618 }
619 }
620 }
621 }
622 dwErrorCode = ERROR_SUCCESS;
623 }
624 Cleanup:
625 RtlFreeUnicodeString(&pNameW);
626 RtlFreeUnicodeString(&pEnvironmentW);
627 SetLastError(dwErrorCode);
628 FIXME("EnumPrinterDriversA Exit %d Err %d\n",ret,GetLastError());
629 return ret;
630 }
631
632 BOOL WINAPI
633 EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
634 {
635 DWORD dwErrorCode;
636
637 FIXME("EnumPrinterDriversW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
638
639 // Dismiss invalid levels already at this point.
640 if (Level < 1 || Level == 7 || Level > 8)
641 {
642 dwErrorCode = ERROR_INVALID_LEVEL;
643 goto Cleanup;
644 }
645
646 if ( !pEnvironment || !*pEnvironment )
647 {
648 pEnvironment = (PWSTR)wszCurrentEnvironment;
649 }
650
651 if (cbBuf && pDriverInfo)
652 ZeroMemory(pDriverInfo, cbBuf);
653
654 // Do the RPC call
655 RpcTryExcept
656 {
657 dwErrorCode = _RpcEnumPrinterDrivers( pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned );
658 }
659 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
660 {
661 dwErrorCode = RpcExceptionCode();
662 ERR("_RpcEnumPrinterDrivers failed with exception code %lu!\n", dwErrorCode);
663 }
664 RpcEndExcept;
665
666 if (dwErrorCode == ERROR_SUCCESS)
667 {
668 // Replace relative offset addresses in the output by absolute pointers.
669 ASSERT(Level <= 6 || Level == 8);
670 MarshallUpStructuresArray(cbBuf, pDriverInfo, *pcReturned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
671 }
672
673 Cleanup:
674 SetLastError(dwErrorCode); FIXME("EnumPrinterDriversW Exit Err %d\n",dwErrorCode);
675 return (dwErrorCode == ERROR_SUCCESS);
676
677 }
678
679 BOOL WINAPI
680 GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
681 {
682 DWORD dwErrorCode;
683 /*
684 * We are mapping multiple different pointers to the same pDriverInfo pointer here so that
685 * we can use the same incoming pointer for different Levels
686 */
687 PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo;
688 PDRIVER_INFO_8W pdi8w = (PDRIVER_INFO_8W)pDriverInfo;
689
690 DWORD cch;
691 PWSTR pwszEnvironment = NULL;
692
693 TRACE("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
694
695 // Check for invalid levels here for early error return. Should be 1-6 & 8.
696 if (Level < 1 || Level == 7 || Level > 8)
697 {
698 dwErrorCode = ERROR_INVALID_LEVEL;
699 ERR("Invalid Level! %d\n",Level);
700 goto Cleanup;
701 }
702
703 if (pEnvironment)
704 {
705 // Convert pEnvironment to a Unicode string pwszEnvironment.
706 cch = strlen(pEnvironment);
707
708 pwszEnvironment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
709 if (!pwszEnvironment)
710 {
711 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
712 ERR("HeapAlloc failed!\n");
713 goto Cleanup;
714 }
715
716 MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, pwszEnvironment, cch + 1);
717 }
718
719 if (!GetPrinterDriverW(hPrinter, pwszEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded))
720 {
721 dwErrorCode = GetLastError();
722 goto Cleanup;
723 }
724
725 // Do Unicode to ANSI conversions for strings based on Level
726 switch (Level)
727 {
728 case 1:
729 {
730 dwErrorCode = UnicodeToAnsiInPlace(pdi1w->pName);
731 if (dwErrorCode != ERROR_SUCCESS)
732 {
733 goto Cleanup;
734 }
735 break;
736 }
737 case 8:
738 {
739 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszPrintProcessor);
740 if (dwErrorCode != ERROR_SUCCESS)
741 {
742 goto Cleanup;
743 }
744 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszVendorSetup);
745 if (dwErrorCode != ERROR_SUCCESS)
746 {
747 goto Cleanup;
748 }
749 dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w->pszzColorProfiles);
750 if (dwErrorCode != ERROR_SUCCESS)
751 {
752 goto Cleanup;
753 }
754 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszInfPath);
755 if (dwErrorCode != ERROR_SUCCESS)
756 {
757 goto Cleanup;
758 }
759 dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w->pszzCoreDriverDependencies);
760 if (dwErrorCode != ERROR_SUCCESS)
761 {
762 goto Cleanup;
763 }
764 }
765 case 6:
766 {
767 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszMfgName);
768 if (dwErrorCode != ERROR_SUCCESS)
769 {
770 goto Cleanup;
771 }
772
773 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszOEMUrl);
774 if (dwErrorCode != ERROR_SUCCESS)
775 {
776 goto Cleanup;
777 }
778
779 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszHardwareID);
780 if (dwErrorCode != ERROR_SUCCESS)
781 {
782 goto Cleanup;
783 }
784
785 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszProvider);
786 if (dwErrorCode != ERROR_SUCCESS)
787 {
788 goto Cleanup;
789 }
790 }
791 case 4:
792 {
793 dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w->pszzPreviousNames);
794 if (dwErrorCode != ERROR_SUCCESS)
795 {
796 goto Cleanup;
797 }
798 }
799 case 3:
800 {
801 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pHelpFile);
802 if (dwErrorCode != ERROR_SUCCESS)
803 {
804 goto Cleanup;
805 }
806
807 dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w->pDependentFiles);
808 if (dwErrorCode != ERROR_SUCCESS)
809 {
810 goto Cleanup;
811 }
812
813 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pMonitorName);
814 if (dwErrorCode != ERROR_SUCCESS)
815 {
816 goto Cleanup;
817 }
818
819 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDefaultDataType);
820 if (dwErrorCode != ERROR_SUCCESS)
821 {
822 goto Cleanup;
823 }
824 }
825 case 2:
826 case 5:
827 {
828 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pConfigFile);
829 if (dwErrorCode != ERROR_SUCCESS)
830 {
831 goto Cleanup;
832 }
833 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDataFile);
834
835 if (dwErrorCode != ERROR_SUCCESS)
836 {
837 goto Cleanup;
838 }
839
840 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDriverPath);
841 if (dwErrorCode != ERROR_SUCCESS)
842 {
843 goto Cleanup;
844 }
845
846 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pEnvironment);
847 if (dwErrorCode != ERROR_SUCCESS)
848 {
849 goto Cleanup;
850 }
851
852 dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pName);
853 if (dwErrorCode != ERROR_SUCCESS)
854 {
855 goto Cleanup;
856 }
857 }
858 }
859
860 dwErrorCode = ERROR_SUCCESS;
861
862 Cleanup:
863 if (pwszEnvironment)
864 {
865 HeapFree(hProcessHeap, 0, pwszEnvironment);
866 }
867
868 SetLastError(dwErrorCode);
869 return (dwErrorCode == ERROR_SUCCESS);
870 }
871
872 BOOL WINAPI
873 GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
874 {
875 DWORD dwErrorCode;
876 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
877
878 TRACE("GetPrinterDriverW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
879
880 // Sanity checks.
881 if (!pHandle)
882 {
883 dwErrorCode = ERROR_INVALID_HANDLE;
884 goto Cleanup;
885 }
886
887 // Dismiss invalid levels already at this point.
888 if (Level > 8 || Level == 7 || Level < 1)
889 {
890 dwErrorCode = ERROR_INVALID_LEVEL;
891 goto Cleanup;
892 }
893
894 if ( !pEnvironment || !*pEnvironment )
895 {
896 pEnvironment = (PWSTR)wszCurrentEnvironment;
897 }
898
899 if (cbBuf && pDriverInfo)
900 ZeroMemory(pDriverInfo, cbBuf);
901
902 // Do the RPC call
903 RpcTryExcept
904 {
905 dwErrorCode = _RpcGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
906 }
907 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
908 {
909 dwErrorCode = RpcExceptionCode();
910 ERR("_RpcGetPrinterDriver failed with exception code %lu!\n", dwErrorCode);
911 }
912 RpcEndExcept;
913
914 if (dwErrorCode == ERROR_SUCCESS)
915 {
916 // Replace relative offset addresses in the output by absolute pointers.
917 ASSERT(Level <= 6 || Level == 8);
918 MarshallUpStructure(cbBuf, pDriverInfo, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
919 }
920
921 Cleanup:
922 SetLastError(dwErrorCode);
923 return (dwErrorCode == ERROR_SUCCESS);
924 }
925
926 BOOL WINAPI
927 GetPrinterDriverDirectoryA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded)
928 {
929 UNICODE_STRING nameW, environmentW;
930 BOOL ret;
931 DWORD pcbNeededW;
932 INT len = cbBuf * sizeof(WCHAR)/sizeof(CHAR);
933 WCHAR *driverDirectoryW = NULL;
934
935 TRACE("GetPrinterDriverDirectoryA(%s, %s, %d, %p, %d, %p)\n", debugstr_a(pName), debugstr_a(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
936
937 if (len) driverDirectoryW = HeapAlloc( GetProcessHeap(), 0, len );
938
939 if (pName)
940 {
941 RtlCreateUnicodeStringFromAsciiz(&nameW, pName);
942 }
943 else
944 {
945 nameW.Buffer = NULL;
946 }
947 if (pEnvironment)
948 {
949 RtlCreateUnicodeStringFromAsciiz(&environmentW, pEnvironment);
950 }
951 else
952 {
953 environmentW.Buffer = NULL;
954 }
955
956 ret = GetPrinterDriverDirectoryW( nameW.Buffer, environmentW.Buffer, Level, (LPBYTE)driverDirectoryW, len, &pcbNeededW );
957
958 if (ret)
959 {
960 DWORD needed = WideCharToMultiByte( CP_ACP, 0, driverDirectoryW, -1, (LPSTR)pDriverDirectory, cbBuf, NULL, NULL);
961
962 if ( pcbNeeded )
963 *pcbNeeded = needed;
964
965 ret = needed <= cbBuf;
966 }
967 else
968 {
969 if (pcbNeeded) *pcbNeeded = pcbNeededW * sizeof(CHAR)/sizeof(WCHAR);
970 }
971
972 TRACE("required: 0x%x/%d\n", pcbNeeded ? *pcbNeeded : 0, pcbNeeded ? *pcbNeeded : 0);
973
974 HeapFree( GetProcessHeap(), 0, driverDirectoryW );
975 RtlFreeUnicodeString(&environmentW);
976 RtlFreeUnicodeString(&nameW);
977
978 return ret;
979 }
980
981 BOOL WINAPI
982 GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded)
983 {
984 DWORD dwErrorCode;
985
986 TRACE("GetPrinterDriverDirectoryW(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded);
987
988 if (Level != 1)
989 {
990 dwErrorCode = ERROR_INVALID_LEVEL;
991 goto Cleanup;
992 }
993
994 if ( !pEnvironment || !*pEnvironment )
995 {
996 pEnvironment = (PWSTR)wszCurrentEnvironment;
997 }
998
999 // Do the RPC call.
1000 RpcTryExcept
1001 {
1002 dwErrorCode = _RpcGetPrinterDriverDirectory(pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded);
1003 }
1004 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1005 {
1006 dwErrorCode = RpcExceptionCode();
1007 ERR("_RpcGetPrinterDriverDirectory failed with exception code %lu!\n", dwErrorCode);
1008 }
1009 RpcEndExcept;
1010
1011 Cleanup:
1012 SetLastError(dwErrorCode);
1013 return (dwErrorCode == ERROR_SUCCESS);
1014 }