[Printing] Update and Add Functions
[reactos.git] / win32ss / printing / providers / localspl / printerdrivers.c
1 /*
2 * PROJECT: ReactOS Local Spooler
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions for printer driver information
5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
6 * Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7 */
8
9 #include "precomp.h"
10 #include <strsafe.h>
11
12 typedef struct {
13 WCHAR src[MAX_PATH+MAX_PATH];
14 WCHAR dst[MAX_PATH+MAX_PATH];
15 DWORD srclen;
16 DWORD dstlen;
17 DWORD copyflags;
18 BOOL lazy;
19 } apd_data_t;
20
21 static const WCHAR backslashW[] = {'\\',0};
22 static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0};
23 static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0};
24 static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0};
25 static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0};
26 static const WCHAR driverW[] = {'D','r','i','v','e','r',0};
27 static const WCHAR emptyW[] = {0};
28 static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\',
29 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
30 'c','o','n','t','r','o','l','\\',
31 'P','r','i','n','t','\\',
32 'E','n','v','i','r','o','n','m','e','n','t','s','\\',
33 '%','s','\\','D','r','i','v','e','r','s','%','s',0 };
34 static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0};
35 static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0};
36
37 static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0};
38
39 static const WCHAR spoolW[] = {'\\','s','p','o','o','l',0};
40 static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0};
41 static const WCHAR ia64_envnameW[] = {'W','i','n','d','o','w','s',' ','I','A','6','4',0};
42 static const WCHAR ia64_subdirW[] = {'i','a','6','4',0};
43 static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0};
44 static const WCHAR version3_subdirW[] = {'\\','3',0};
45 static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0};
46 static const WCHAR version0_subdirW[] = {'\\','0',0};
47 static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0};
48 static const WCHAR x64_envnameW[] = {'W','i','n','d','o','w','s',' ','x','6','4',0};
49 static const WCHAR x64_subdirW[] = {'x','6','4',0};
50 static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0};
51 static const WCHAR x86_subdirW[] = {'w','3','2','x','8','6',0};
52 static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0};
53 static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0};
54
55 static PRINTENV_T env_ia64 = {ia64_envnameW, ia64_subdirW, 3, version3_regpathW, version3_subdirW};
56
57 static PRINTENV_T env_x86 = {x86_envnameW, x86_subdirW, 3, version3_regpathW, version3_subdirW};
58
59 static PRINTENV_T env_x64 = {x64_envnameW, x64_subdirW, 3, version3_regpathW, version3_subdirW};
60
61 static PRINTENV_T env_win40 = {win40_envnameW, win40_subdirW, 0, version0_regpathW, version0_subdirW};
62
63 static PPRINTENV_T all_printenv[] = {&env_x86, &env_x64, &env_ia64, &env_win40};
64
65 static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W),
66 sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W),
67 sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W),
68 0, sizeof(DRIVER_INFO_8W)};
69
70 static WCHAR wszScratchPad[MAX_PATH] = L"";
71
72 static WCHAR wszLocalSplFile[MAX_PATH] = L"";
73 static WCHAR wszPrintUiFile[MAX_PATH] = L"";
74 static WCHAR wszDriverPath[MAX_PATH] = L"";
75
76 BOOL
77 InitializePrinterDrivers(VOID)
78 {
79 WCHAR szSysDir[MAX_PATH];
80 DWORD cbBuf;
81
82 if (wszLocalSplFile[0] && wszPrintUiFile[0])
83 return TRUE;
84
85 if (!GetSystemDirectoryW(szSysDir, _countof(szSysDir)))
86 {
87 ERR("GetSystemDirectoryW failed\n");
88 return FALSE;
89 }
90
91 StringCbCopyW(wszLocalSplFile, sizeof(wszLocalSplFile), szSysDir);
92 StringCbCatW(wszLocalSplFile, sizeof(wszLocalSplFile), L"\\localspl.dll");
93
94 StringCbCopyW(wszPrintUiFile, sizeof(wszPrintUiFile), szSysDir);
95 StringCbCatW(wszPrintUiFile, sizeof(wszPrintUiFile), L"\\printui.dll");
96
97 if (!LocalGetPrinterDriverDirectory( NULL, (PWSTR)wszCurrentEnvironment, 1, (PBYTE)szSysDir, cbBuf, &cbBuf ) )
98 {
99 ERR("LocalGetPrinterDriverDirectory failed\n");
100 return FALSE;
101 }
102
103 StringCbCopyW(wszDriverPath, sizeof(wszDriverPath), szSysDir);
104 StringCbCatW(wszDriverPath, sizeof(wszDriverPath), version3_subdirW);
105 StringCbCatW(wszDriverPath, sizeof(wszDriverPath), backslashW);
106
107 // HAX! need to get it from the Reg Key L"Driver"!
108 StringCbCatW(wszDriverPath, sizeof(wszDriverPath), L"UniDrv.dll");
109
110 FIXME("DriverPath : %S\n",wszDriverPath);
111
112 return TRUE;
113 }
114
115 // Local Constants
116 static DWORD dwDriverInfo1Offsets[] = {
117 FIELD_OFFSET(DRIVER_INFO_1W, pName),
118 MAXDWORD
119 };
120
121 static DWORD dwDriverInfo2Offsets[] = {
122 FIELD_OFFSET(DRIVER_INFO_2W, pName),
123 FIELD_OFFSET(DRIVER_INFO_2W, pEnvironment),
124 FIELD_OFFSET(DRIVER_INFO_2W, pDriverPath),
125 FIELD_OFFSET(DRIVER_INFO_2W, pDataFile),
126 FIELD_OFFSET(DRIVER_INFO_2W, pConfigFile),
127 MAXDWORD
128 };
129
130 static DWORD dwDriverInfo3Offsets[] = {
131 FIELD_OFFSET(DRIVER_INFO_3W, pName),
132 FIELD_OFFSET(DRIVER_INFO_3W, pEnvironment),
133 FIELD_OFFSET(DRIVER_INFO_3W, pDriverPath),
134 FIELD_OFFSET(DRIVER_INFO_3W, pDataFile),
135 FIELD_OFFSET(DRIVER_INFO_3W, pConfigFile),
136 FIELD_OFFSET(DRIVER_INFO_3W, pHelpFile),
137 FIELD_OFFSET(DRIVER_INFO_3W, pDependentFiles),
138 FIELD_OFFSET(DRIVER_INFO_3W, pMonitorName),
139 FIELD_OFFSET(DRIVER_INFO_3W, pDefaultDataType),
140 MAXDWORD
141 };
142
143 static DWORD dwDriverInfo4Offsets[] = {
144 FIELD_OFFSET(DRIVER_INFO_4W, pName),
145 FIELD_OFFSET(DRIVER_INFO_4W, pEnvironment),
146 FIELD_OFFSET(DRIVER_INFO_4W, pDriverPath),
147 FIELD_OFFSET(DRIVER_INFO_4W, pDataFile),
148 FIELD_OFFSET(DRIVER_INFO_4W, pConfigFile),
149 FIELD_OFFSET(DRIVER_INFO_4W, pHelpFile),
150 FIELD_OFFSET(DRIVER_INFO_4W, pDependentFiles),
151 FIELD_OFFSET(DRIVER_INFO_4W, pMonitorName),
152 FIELD_OFFSET(DRIVER_INFO_4W, pDefaultDataType),
153 FIELD_OFFSET(DRIVER_INFO_4W, pszzPreviousNames),
154 MAXDWORD
155 };
156
157 static DWORD dwDriverInfo5Offsets[] = {
158 FIELD_OFFSET(DRIVER_INFO_5W, pName),
159 FIELD_OFFSET(DRIVER_INFO_5W, pEnvironment),
160 FIELD_OFFSET(DRIVER_INFO_5W, pDriverPath),
161 FIELD_OFFSET(DRIVER_INFO_5W, pDataFile),
162 FIELD_OFFSET(DRIVER_INFO_5W, pConfigFile),
163 MAXDWORD
164 };
165
166 static DWORD dwDriverInfo6Offsets[] = {
167 FIELD_OFFSET(DRIVER_INFO_6W, pName),
168 FIELD_OFFSET(DRIVER_INFO_6W, pEnvironment),
169 FIELD_OFFSET(DRIVER_INFO_6W, pDriverPath),
170 FIELD_OFFSET(DRIVER_INFO_6W, pDataFile),
171 FIELD_OFFSET(DRIVER_INFO_6W, pConfigFile),
172 FIELD_OFFSET(DRIVER_INFO_6W, pHelpFile),
173 FIELD_OFFSET(DRIVER_INFO_6W, pDependentFiles),
174 FIELD_OFFSET(DRIVER_INFO_6W, pMonitorName),
175 FIELD_OFFSET(DRIVER_INFO_6W, pDefaultDataType),
176 FIELD_OFFSET(DRIVER_INFO_6W, pszzPreviousNames),
177 FIELD_OFFSET(DRIVER_INFO_6W, pszMfgName),
178 FIELD_OFFSET(DRIVER_INFO_6W, pszOEMUrl),
179 FIELD_OFFSET(DRIVER_INFO_6W, pszHardwareID),
180 FIELD_OFFSET(DRIVER_INFO_6W, pszProvider),
181 MAXDWORD
182 };
183
184 static DWORD dwDriverInfo8Offsets[] = {
185 FIELD_OFFSET(DRIVER_INFO_8W, pName),
186 FIELD_OFFSET(DRIVER_INFO_8W, pEnvironment),
187 FIELD_OFFSET(DRIVER_INFO_8W, pDriverPath),
188 FIELD_OFFSET(DRIVER_INFO_8W, pDataFile),
189 FIELD_OFFSET(DRIVER_INFO_8W, pConfigFile),
190 FIELD_OFFSET(DRIVER_INFO_8W, pHelpFile),
191 FIELD_OFFSET(DRIVER_INFO_8W, pDependentFiles),
192 FIELD_OFFSET(DRIVER_INFO_8W, pMonitorName),
193 FIELD_OFFSET(DRIVER_INFO_8W, pDefaultDataType),
194 FIELD_OFFSET(DRIVER_INFO_8W, pszzPreviousNames),
195 FIELD_OFFSET(DRIVER_INFO_8W, pszMfgName),
196 FIELD_OFFSET(DRIVER_INFO_8W, pszOEMUrl),
197 FIELD_OFFSET(DRIVER_INFO_8W, pszHardwareID),
198 FIELD_OFFSET(DRIVER_INFO_8W, pszProvider),
199 FIELD_OFFSET(DRIVER_INFO_8W, pszPrintProcessor),
200 FIELD_OFFSET(DRIVER_INFO_8W, pszVendorSetup),
201 FIELD_OFFSET(DRIVER_INFO_8W, pszzColorProfiles),
202 FIELD_OFFSET(DRIVER_INFO_8W, pszInfPath),
203 FIELD_OFFSET(DRIVER_INFO_8W, pszzCoreDriverDependencies),
204 MAXDWORD
205 };
206
207 static void
208 ToMultiSz(LPWSTR pString)
209 {
210 while (*pString)
211 {
212 if (*pString == '|')
213 *pString = '\0';
214 pString++;
215 }
216 }
217
218 static void
219 _LocalGetPrinterDriverLevel1(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_1W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
220 {
221 DWORD n;
222 PCWSTR pwszStrings[1];
223
224 /* This value is only here to send something, I have not verified if it is actually correct */
225 pwszStrings[0] = pPrinter->pwszPrinterDriver;
226
227 // Calculate the string lengths.
228 if (!ppDriverInfo)
229 {
230 for (n = 0; n < _countof(pwszStrings); ++n)
231 {
232 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
233 }
234
235 *pcbNeeded += sizeof(DRIVER_INFO_1W);
236 return;
237 }
238
239 // Finally copy the structure and advance to the next one in the output buffer.
240 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo1Offsets, *ppDriverInfoEnd);
241 (*ppDriverInfo)++;
242 }
243
244 static void
245 _LocalGetPrinterDriverLevel2(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_2W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
246 {
247 DWORD n;
248 PCWSTR pwszStrings[5];
249
250 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
251 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
252 pwszStrings[2] = wszDriverPath; // pDriverPath
253 pwszStrings[3] = wszLocalSplFile; // pDataFile
254 pwszStrings[4] = wszPrintUiFile; // pConfigFile
255
256 // Calculate the string lengths.
257 if (!ppDriverInfo)
258 {
259 for (n = 0; n < _countof(pwszStrings); ++n)
260 {
261 if (pwszStrings[n])
262 {
263 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
264 }
265 }
266
267 *pcbNeeded += sizeof(DRIVER_INFO_2W);
268 return;
269 }
270
271 (*ppDriverInfo)->cVersion = 3;
272
273 // Finally copy the structure and advance to the next one in the output buffer.
274 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo2Offsets, *ppDriverInfoEnd);
275 (*ppDriverInfo)++;
276 }
277
278 static void
279 _LocalGetPrinterDriverLevel3(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_3W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
280 {
281 DWORD n;
282 PCWSTR pwszStrings[9];
283
284 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
285 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
286 pwszStrings[2] = wszDriverPath; // pDriverPath
287 pwszStrings[3] = wszLocalSplFile; // pDataFile
288 pwszStrings[4] = wszPrintUiFile; // pConfigFile
289 pwszStrings[5] = L""; // pHelpFile
290 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
291 pwszStrings[7] = NULL;
292 if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor)
293 {
294 pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName;
295 }
296 pwszStrings[8] = pPrinter->pwszDefaultDatatype;
297
298
299 // Calculate the string lengths.
300 if (!ppDriverInfo)
301 {
302 for (n = 0; n < _countof(pwszStrings); ++n)
303 {
304 if (pwszStrings[n])
305 {
306 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
307 }
308 }
309
310 *pcbNeeded += sizeof(DRIVER_INFO_3W);
311 return;
312 }
313
314 (*ppDriverInfo)->cVersion = 3;
315
316 // Finally copy the structure and advance to the next one in the output buffer.
317 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo3Offsets, *ppDriverInfoEnd);
318 ToMultiSz((*ppDriverInfo)->pDependentFiles);
319 (*ppDriverInfo)++;
320 }
321
322 static void
323 _LocalGetPrinterDriverLevel4(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_4W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
324 {
325 DWORD n;
326 PCWSTR pwszStrings[10];
327
328 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
329 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
330 pwszStrings[2] = wszDriverPath; // pDriverPath
331 pwszStrings[3] = wszLocalSplFile; // pDataFile
332 pwszStrings[4] = wszPrintUiFile; // pConfigFile
333 pwszStrings[5] = L""; // pHelpFile
334 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
335 pwszStrings[7] = NULL;
336 if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor)
337 {
338 pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName;
339 }
340 pwszStrings[8] = pPrinter->pwszDefaultDatatype;
341 pwszStrings[9] = NULL; // pszzPreviousNames
342
343 // Calculate the string lengths.
344 if (!ppDriverInfo)
345 {
346 for (n = 0; n < _countof(pwszStrings); ++n)
347 {
348 if (pwszStrings[n])
349 {
350 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
351 }
352 }
353
354 *pcbNeeded += sizeof(DRIVER_INFO_4W);
355 return;
356 }
357
358 (*ppDriverInfo)->cVersion = 3;
359
360 // Finally copy the structure and advance to the next one in the output buffer.
361 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo4Offsets, *ppDriverInfoEnd);
362 ToMultiSz((*ppDriverInfo)->pDependentFiles);
363 (*ppDriverInfo)++;
364 }
365
366 static void
367 _LocalGetPrinterDriverLevel5(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_5W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
368 {
369 DWORD n;
370 PCWSTR pwszStrings[5];
371
372 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
373 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
374 pwszStrings[2] = wszDriverPath; // pDriverPath UniDrv.dll
375 pwszStrings[3] = wszLocalSplFile; // pDataFile.ppd
376 pwszStrings[4] = wszPrintUiFile; // pConfigFile UniDrvUI.dll
377
378 // Calculate the string lengths.
379 if (!ppDriverInfo)
380 {
381 for (n = 0; n < _countof(pwszStrings); ++n)
382 {
383 if (pwszStrings[n])
384 {
385 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
386 }
387 }
388
389 *pcbNeeded += sizeof(DRIVER_INFO_5W);
390 return;
391 }
392
393 (*ppDriverInfo)->cVersion = 3;
394 // Driver attributes, like UMPD/KMPD.
395 (*ppDriverInfo)->dwDriverAttributes = 0; // UMPD/KMPD, So where are they?
396 // Number of times the configuration file for this driver has been upgraded or downgraded since the last spooler restart.
397 (*ppDriverInfo)->dwConfigVersion = 1;
398 // Number of times the driver file for this driver has been upgraded or downgraded since the last spooler restart.
399 (*ppDriverInfo)->dwDriverVersion = 1;
400
401 // Finally copy the structure and advance to the next one in the output buffer.
402 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo5Offsets, *ppDriverInfoEnd);
403 (*ppDriverInfo)++;
404 }
405
406
407 static void
408 _LocalGetPrinterDriverLevel6(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_6W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
409 {
410 DWORD n;
411 PCWSTR pwszStrings[14];
412
413 StringCbCopyW(wszScratchPad, sizeof(wszPrintProviderInfo[1]), wszPrintProviderInfo[1]); // Provider Name
414
415 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
416 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
417 pwszStrings[2] = wszDriverPath; // pDriverPath
418 pwszStrings[3] = wszLocalSplFile; // pDataFile
419 pwszStrings[4] = wszPrintUiFile; // pConfigFile
420 pwszStrings[5] = L""; // pHelpFile
421 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
422 pwszStrings[7] = NULL;
423 if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor)
424 {
425 pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName;
426 }
427 pwszStrings[8] = pPrinter->pwszDefaultDatatype;
428 pwszStrings[9] = NULL; // pszzPreviousNames
429 pwszStrings[10] = NULL; // pszMfgName
430 pwszStrings[11] = NULL; // pszOEMUrl
431 pwszStrings[12] = NULL; // pszHardwareID
432 pwszStrings[13] = wszScratchPad;
433
434 // Calculate the string lengths.
435 if (!ppDriverInfo)
436 {
437 for (n = 0; n < _countof(pwszStrings); ++n)
438 {
439 if (pwszStrings[n])
440 {
441 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
442 }
443 }
444
445 *pcbNeeded += sizeof(DRIVER_INFO_6W);
446 return;
447 }
448
449 (*ppDriverInfo)->cVersion = 3;
450
451 // Finally copy the structure and advance to the next one in the output buffer.
452 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo6Offsets, *ppDriverInfoEnd);
453 ToMultiSz((*ppDriverInfo)->pDependentFiles);
454 (*ppDriverInfo)++;
455 }
456
457 static void
458 _LocalGetPrinterDriverLevel8(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_8W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
459 {
460 DWORD n;
461 PCWSTR pwszStrings[19];
462
463 StringCbCopyW(wszScratchPad, sizeof(wszPrintProviderInfo[1]), wszPrintProviderInfo[1]); // Provider Name
464
465 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName
466 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
467 pwszStrings[2] = wszDriverPath; // pDriverPath
468 pwszStrings[3] = wszLocalSplFile; // pDataFile
469 pwszStrings[4] = wszPrintUiFile; // pConfigFile
470 pwszStrings[5] = L""; // pHelpFile
471 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
472 pwszStrings[7] = NULL;
473 if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor)
474 {
475 pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName;
476 }
477 pwszStrings[8] = pPrinter->pwszDefaultDatatype;
478 pwszStrings[9] = NULL; // pszzPreviousNames
479 pwszStrings[10] = NULL; // pszMfgName
480 pwszStrings[11] = NULL; // pszOEMUrl
481 pwszStrings[12] = NULL; // pszHardwareID
482 pwszStrings[13] = wszScratchPad;
483 pwszStrings[14] = NULL;
484 if ( pPrinter->pPrintProcessor )
485 {
486 pwszStrings[14] = pPrinter->pPrintProcessor->pwszName;
487 }
488 pwszStrings[15] = NULL; // pszVendorSetup
489 pwszStrings[16] = NULL; // pszzColorProfiles
490 pwszStrings[17] = NULL; // pszInfPath
491 pwszStrings[18] = NULL; // pszzCoreDriverDependencies
492
493 // Calculate the string lengths.
494 if (!ppDriverInfo)
495 {
496 for (n = 0; n < _countof(pwszStrings); ++n)
497 {
498 if (pwszStrings[n])
499 {
500 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
501 }
502 }
503
504 *pcbNeeded += sizeof(DRIVER_INFO_8W);
505 return;
506 }
507
508 (*ppDriverInfo)->cVersion = 3;
509
510 // Finally copy the structure and advance to the next one in the output buffer.
511 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo8Offsets, *ppDriverInfoEnd);
512 ToMultiSz((*ppDriverInfo)->pDependentFiles);
513 (*ppDriverInfo)++;
514 }
515
516 typedef void (*PLocalPrinterDriverLevelFunc)(PLOCAL_PRINTER, PVOID, PBYTE*, PDWORD);
517
518 static const PLocalPrinterDriverLevelFunc pfnPrinterDriverLevels[] = {
519 NULL,
520 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel1,
521 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel2,
522 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel3,
523 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel4,
524 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel5,
525 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel6,
526 NULL,
527 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel8
528 };
529
530 BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
531 {
532 DWORD dwErrorCode;
533 PBYTE pEnd = &pDriverInfo[cbBuf];
534 PLOCAL_HANDLE pHandle;
535 PLOCAL_PRINTER_HANDLE pPrinterHandle;
536
537 TRACE("LocalGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
538
539 // Check if this is a printer handle.
540 pHandle = (PLOCAL_HANDLE)hPrinter;
541 if (pHandle->HandleType != HandleType_Printer)
542 {
543 dwErrorCode = ERROR_INVALID_HANDLE;
544 goto Cleanup;
545 }
546
547 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
548
549 // Only support 8 levels and not 7
550 if (Level < 1 || Level == 7 || Level > 8)
551 {
552 // The caller supplied an invalid level.
553 dwErrorCode = ERROR_INVALID_LEVEL;
554 goto Cleanup;
555 }
556
557 // Count the required buffer size.
558 *pcbNeeded = 0;
559
560 pfnPrinterDriverLevels[Level](pPrinterHandle->pPrinter, NULL, NULL, pcbNeeded);
561
562 // Check if the supplied buffer is large enough.
563 if (cbBuf < *pcbNeeded)
564 {
565 ERR("Insuffisient Buffer size\n");
566 dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
567 goto Cleanup;
568 }
569
570 // Copy over the information.
571 pEnd = &pDriverInfo[*pcbNeeded];
572
573 pfnPrinterDriverLevels[Level](pPrinterHandle->pPrinter, &pDriverInfo, &pEnd, NULL);
574
575 dwErrorCode = ERROR_SUCCESS;
576
577 Cleanup:
578 SetLastError(dwErrorCode);
579 return (dwErrorCode == ERROR_SUCCESS);
580 }
581
582 BOOL WINAPI LocalGetPrinterDriverEx(
583 HANDLE hPrinter,
584 LPWSTR pEnvironment,
585 DWORD Level,
586 LPBYTE pDriverInfo,
587 DWORD cbBuf,
588 LPDWORD pcbNeeded,
589 DWORD dwClientMajorVersion,
590 DWORD dwClientMinorVersion,
591 PDWORD pdwServerMajorVersion,
592 PDWORD pdwServerMinorVersion )
593 {
594 FIXME("LocalGetPrinterDriverEx(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion);
595 //// HACK-plement
596 return LocalGetPrinterDriver( hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded );
597 }
598
599 BOOL WINAPI
600 LocalEnumPrinterDrivers(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
601 {
602 DWORD dwErrorCode;
603 PSKIPLIST_NODE pNode;
604 PBYTE pEnd;
605 PLOCAL_PRINTER pPrinter;
606
607 FIXME("LocalEnumPrinterDrivers(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned);
608
609 // Only support 8 levels and not 7
610 if (Level < 1 || Level == 7 || Level > 8)
611 {
612 // The caller supplied an invalid level.
613 dwErrorCode = ERROR_INVALID_LEVEL;
614 goto Cleanup;
615 }
616
617 // Count the required buffer size.
618 *pcbNeeded = 0;
619
620 // Count the required buffer size and the number of printers.
621 for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
622 {
623 pPrinter = (PLOCAL_PRINTER)pNode->Element;
624
625 pfnPrinterDriverLevels[Level](pPrinter, NULL, NULL, pcbNeeded);
626 }
627
628 // Check if the supplied buffer is large enough.
629 if (cbBuf < *pcbNeeded)
630 {
631 dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
632 goto Cleanup;
633 }
634
635 // Copy over the Printer information.
636 pEnd = &pDriverInfo[*pcbNeeded];
637
638 for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
639 {
640 pPrinter = (PLOCAL_PRINTER)pNode->Element;
641
642 pfnPrinterDriverLevels[Level](pPrinter, &pDriverInfo, &pEnd, NULL);
643 (*pcReturned)++;
644 }
645
646 dwErrorCode = ERROR_SUCCESS;
647
648 Cleanup:
649 SetLastError(dwErrorCode);
650 return (dwErrorCode == ERROR_SUCCESS);
651 }
652
653 /******************************************************************
654 * Return the number of bytes for an multi_sz string.
655 * The result includes all \0s
656 * (specifically the extra \0, that is needed as multi_sz terminator).
657 */
658 static int multi_sz_lenW(const WCHAR *str)
659 {
660 const WCHAR *ptr = str;
661 if (!str) return 0;
662 do
663 {
664 ptr += lstrlenW(ptr) + 1;
665 } while (*ptr);
666
667 return (ptr - str + 1) * sizeof(WCHAR);
668 }
669
670
671 /******************************************************************
672 * validate_envW [internal]
673 *
674 * validate the user-supplied printing-environment
675 *
676 * PARAMS
677 * env [I] PTR to Environment-String or NULL
678 *
679 * RETURNS
680 * Success: PTR to printenv_t
681 * Failure: NULL and ERROR_INVALID_ENVIRONMENT
682 *
683 * NOTES
684 * An empty string is handled the same way as NULL.
685 *
686 */
687 PPRINTENV_T validate_envW(LPCWSTR env)
688 {
689 PPRINTENV_T result = NULL;
690 unsigned int i;
691
692 TRACE("(%s)\n", debugstr_w(env));
693 if (env && env[0])
694 {
695 for (i = 0; i < ARRAYSIZE(all_printenv); i++)
696 {
697 if (lstrcmpiW(env, all_printenv[i]->envname) == 0)
698 {
699 result = all_printenv[i];
700 break;
701 }
702 }
703 if (result == NULL)
704 {
705 FIXME("unsupported Environment: %s\n", debugstr_w(env));
706 SetLastError(ERROR_INVALID_ENVIRONMENT);
707 }
708 /* on win9x, only "Windows 4.0" is allowed, but we ignore this */
709 }
710 else
711 {
712 result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86;
713 }
714
715 TRACE("=> using %p: %s\n", result, debugstr_w(result ? result->envname : NULL));
716 return result;
717 }
718
719 /*****************************************************************************
720 * open_driver_reg [internal]
721 *
722 * opens the registry for the printer drivers depending on the given input
723 * variable pEnvironment
724 *
725 * RETURNS:
726 * Success: the opened hkey
727 * Failure: NULL
728 */
729 HKEY open_driver_reg(LPCWSTR pEnvironment)
730 {
731 HKEY retval = NULL;
732 LPWSTR buffer;
733 const PRINTENV_T * env;
734
735 TRACE("(%s)\n", debugstr_w(pEnvironment));
736
737 env = validate_envW(pEnvironment);
738 if (!env) return NULL;
739
740 buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(fmt_driversW) +
741 (lstrlenW(env->envname) + lstrlenW(env->versionregpath)) * sizeof(WCHAR));
742
743 if (buffer)
744 {
745 wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath);
746 RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval);
747 HeapFree(GetProcessHeap(), 0, buffer);
748 }
749 return retval;
750 }
751
752
753 /******************************************************************************
754 * LocalGetPrintProcessorDirectory [exported through PRINTPROVIDOR]
755 *
756 * Return the PATH for the Print-Processors
757 *
758 * PARAMS
759 * pName [I] Servername or NULL (this computer)
760 * pEnvironment [I] Printing-Environment or NULL (Default)
761 * level [I] Structure-Level (must be 1)
762 * pPPInfo [O] PTR to Buffer that receives the Result
763 * cbBuf [I] Size of Buffer at pPPInfo
764 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPPInfo
765 *
766 * RETURNS
767 * Success: TRUE
768 * Failure: FALSE and in pcbNeeded the Bytes required for pPPInfo, if cbBuf is too small
769 *
770 * Native Values returned in pPPInfo on Success for this computer:
771 *| NT(Windows x64): "%winsysdir%\\spool\\PRTPROCS\\x64"
772 *| NT(Windows NT x86): "%winsysdir%\\spool\\PRTPROCS\\w32x86"
773 *| NT(Windows 4.0): "%winsysdir%\\spool\\PRTPROCS\\win40"
774 *
775 * "%winsysdir%" is the Value from GetSystemDirectoryW()
776 *
777 */
778 BOOL WINAPI LocalGetPrinterDriverDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded)
779 {
780 DWORD needed;
781 const PRINTENV_T * env = NULL;
782 WCHAR * const dir = (WCHAR *)pDriverDirectory;
783
784 FIXME("LocalGetPrinterDriverDirectory(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded);
785
786 if (pName != NULL && pName[0])
787 {
788 FIXME("server %s not supported\n", debugstr_w(pName));
789 SetLastError(ERROR_INVALID_PARAMETER);
790 return FALSE;
791 }
792
793 env = validate_envW(pEnvironment);
794 if (!env) return FALSE; /* pEnvironment invalid or unsupported */
795
796 /* GetSystemDirectoryW returns number of WCHAR including the '\0' */
797 needed = GetSystemDirectoryW(NULL, 0);
798 /* add the Size for the Subdirectories */
799 needed += lstrlenW(spoolW);
800 needed += lstrlenW(driversW);
801 needed += lstrlenW(env->subdir);
802 needed *= sizeof(WCHAR); /* return-value is size in Bytes */
803
804 *pcbNeeded = needed;
805
806 if (needed > cbBuf)
807 {
808 SetLastError(ERROR_INSUFFICIENT_BUFFER);
809 return FALSE;
810 }
811
812 if (dir == NULL)
813 {
814 /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */
815 SetLastError(ERROR_INVALID_USER_BUFFER);
816 return FALSE;
817 }
818
819 GetSystemDirectoryW( dir, cbBuf / sizeof(WCHAR) );
820 /* add the Subdirectories */
821 lstrcatW( dir, spoolW );
822 CreateDirectoryW( dir, NULL );
823 lstrcatW( dir, driversW );
824 CreateDirectoryW( dir, NULL );
825 lstrcatW( dir, env->subdir );
826 CreateDirectoryW( dir, NULL );
827
828 FIXME( "=> %s\n", debugstr_w( dir ) );
829 return TRUE;
830 }
831
832 /******************************************************************
833 * apd_copyfile [internal]
834 *
835 * Copy a file from the driverdirectory to the versioned directory
836 *
837 * RETURNS
838 * Success: TRUE
839 * Failure: FALSE
840 *
841 */
842 static BOOL apd_copyfile( WCHAR *pathname, WCHAR *file_part, apd_data_t *apd )
843 {
844 WCHAR *srcname;
845 BOOL res;
846
847 apd->src[apd->srclen] = '\0';
848 apd->dst[apd->dstlen] = '\0';
849
850 if (!pathname || !pathname[0]) {
851 /* nothing to copy */
852 return TRUE;
853 }
854
855 if (apd->copyflags & APD_COPY_FROM_DIRECTORY)
856 srcname = pathname;
857 else
858 {
859 srcname = apd->src;
860 lstrcatW( srcname, file_part );
861 }
862 lstrcatW( apd->dst, file_part );
863
864 FIXME("%s => %s\n", debugstr_w(srcname), debugstr_w(apd->dst));
865
866 /* FIXME: handle APD_COPY_NEW_FILES */
867 res = CopyFileW(srcname, apd->dst, FALSE);
868 FIXME("got %d with %u\n", res, GetLastError());
869
870 return apd->lazy || res;
871 }
872
873 /******************************************************************
874 * driver_load [internal]
875 *
876 * load a driver user interface dll
877 *
878 * On failure, NULL is returned
879 *
880 */
881
882 static HMODULE driver_load(const PRINTENV_T * env, LPWSTR dllname)
883 {
884 WCHAR fullname[MAX_PATH];
885 HMODULE hui;
886 DWORD len;
887
888 FIXME("(%p, %s)\n", env, debugstr_w(dllname));
889
890 /* build the driverdir */
891 len = sizeof(fullname) - (lstrlenW(env->versionsubdir) + 1 + lstrlenW(dllname) + 1) * sizeof(WCHAR);
892
893 if (!LocalGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, (LPBYTE) fullname, len, &len))
894 {
895 /* Should never fail */
896 SetLastError(ERROR_BUFFER_OVERFLOW);
897 return NULL;
898 }
899
900 lstrcatW(fullname, env->versionsubdir);
901 lstrcatW(fullname, backslashW);
902 lstrcatW(fullname, dllname);
903
904 hui = LoadLibraryW(fullname);
905 FIXME("%p: LoadLibrary(%s) %d\n", hui, debugstr_w(fullname), GetLastError());
906
907 return hui;
908 }
909
910 static inline WCHAR *get_file_part( WCHAR *name )
911 {
912 WCHAR *ptr = wcsrchr( name, '\\' );
913 if (ptr) return ptr + 1;
914 return name;
915 }
916
917 /******************************************************************************
918 * myAddPrinterDriverEx [internal]
919 *
920 * Install a Printer Driver with the Option to upgrade / downgrade the Files
921 * and a special mode with lazy error checking.
922 *
923 */
924 BOOL myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags, BOOL lazy)
925 {
926 const PRINTENV_T *env;
927 apd_data_t apd;
928 DRIVER_INFO_8W di;
929 BOOL (WINAPI *pDrvDriverEvent)(DWORD, DWORD, LPBYTE, LPARAM);
930 HMODULE hui;
931 WCHAR *file;
932 HKEY hroot;
933 HKEY hdrv;
934 DWORD disposition;
935 DWORD len;
936 LONG lres;
937 BOOL res;
938
939 /* we need to set all entries in the Registry, independent from the Level of
940 DRIVER_INFO, that the caller supplied */
941
942 ZeroMemory(&di, sizeof(di));
943 if (pDriverInfo && (level < ARRAYSIZE(di_sizeof)))
944 {
945 memcpy(&di, pDriverInfo, di_sizeof[level]);
946 }
947
948 /* dump the most used infos */
949 FIXME("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion);
950 FIXME("%p: .pName : %s\n", di.pName, debugstr_w(di.pName));
951 FIXME("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment));
952 FIXME("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath));
953 FIXME("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile));
954 FIXME("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile));
955 FIXME("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile));
956 /* dump only the first of the additional Files */
957 FIXME("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles));
958
959
960 /* check environment */
961 env = validate_envW(di.pEnvironment);
962 if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */
963
964 /* fill the copy-data / get the driverdir */
965 len = sizeof(apd.src) - sizeof(version3_subdirW) - sizeof(WCHAR);
966 if (!LocalGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, (LPBYTE) apd.src, len, &len))
967 {
968 /* Should never fail */
969 return FALSE;
970 }
971 memcpy(apd.dst, apd.src, len);
972 lstrcatW(apd.src, backslashW);
973 apd.srclen = lstrlenW(apd.src);
974 lstrcatW(apd.dst, env->versionsubdir);
975 lstrcatW(apd.dst, backslashW);
976 apd.dstlen = lstrlenW(apd.dst);
977 apd.copyflags = dwFileCopyFlags;
978 apd.lazy = lazy;
979 CreateDirectoryW(apd.src, NULL);
980 CreateDirectoryW(apd.dst, NULL);
981
982 hroot = open_driver_reg(env->envname);
983 if (!hroot)
984 {
985 ERR("Can't create Drivers key\n");
986 return FALSE;
987 }
988
989 /* Fill the Registry for the Driver */
990 if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE,
991 KEY_WRITE | KEY_QUERY_VALUE, NULL,
992 &hdrv, &disposition)) != ERROR_SUCCESS)
993 {
994 ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres);
995 RegCloseKey(hroot);
996 SetLastError(lres);
997 return FALSE;
998 }
999 RegCloseKey(hroot);
1000
1001 /* Verified with the Adobe PS Driver, that w2k does not use di.Version */
1002 RegSetValueExW(hdrv, versionW, 0, REG_DWORD, (const BYTE*) &env->driverversion,
1003 sizeof(DWORD));
1004
1005 file = get_file_part( di.pDriverPath );
1006 RegSetValueExW( hdrv, driverW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) );
1007 apd_copyfile( di.pDriverPath, file, &apd );
1008
1009 file = get_file_part( di.pDataFile );
1010 RegSetValueExW( hdrv, data_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) );
1011 apd_copyfile( di.pDataFile, file, &apd );
1012
1013 file = get_file_part( di.pConfigFile );
1014 RegSetValueExW( hdrv, configuration_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) );
1015 apd_copyfile( di.pConfigFile, file, &apd );
1016
1017 /* settings for level 3 */
1018 if (di.pHelpFile)
1019 {
1020 file = get_file_part( di.pHelpFile );
1021 RegSetValueExW( hdrv, help_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) );
1022 apd_copyfile( di.pHelpFile, file, &apd );
1023 }
1024 else
1025 RegSetValueExW( hdrv, help_fileW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW) );
1026
1027 if (di.pDependentFiles && *di.pDependentFiles)
1028 {
1029 WCHAR *reg, *reg_ptr, *in_ptr;
1030 reg = reg_ptr = HeapAlloc( GetProcessHeap(), 0, multi_sz_lenW( di.pDependentFiles ) );
1031
1032 for (in_ptr = di.pDependentFiles; *in_ptr; in_ptr += lstrlenW( in_ptr ) + 1)
1033 {
1034 file = get_file_part( in_ptr );
1035 len = lstrlenW( file ) + 1;
1036 memcpy( reg_ptr, file, len * sizeof(WCHAR) );
1037 reg_ptr += len;
1038 apd_copyfile( in_ptr, file, &apd );
1039 }
1040 *reg_ptr = 0;
1041
1042 RegSetValueExW( hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE)reg, (reg_ptr - reg + 1) * sizeof(WCHAR) );
1043 HeapFree( GetProcessHeap(), 0, reg );
1044 }
1045 else
1046 RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW));
1047
1048 /* The language-Monitor was already copied by the caller to "%SystemRoot%\system32" */
1049 if (di.pMonitorName)
1050 RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName,
1051 (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR));
1052 else
1053 RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW));
1054
1055 if (di.pDefaultDataType)
1056 RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType,
1057 (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR));
1058 else
1059 RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW));
1060
1061 /* settings for level 4 */
1062 if (di.pszzPreviousNames)
1063 RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames,
1064 multi_sz_lenW(di.pszzPreviousNames));
1065 else
1066 RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW));
1067
1068 if (level > 5) FIXME("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName));
1069
1070 RegCloseKey(hdrv);
1071
1072 //
1073 // Locate driver and send the event.
1074 //
1075
1076 hui = driver_load(env, di.pConfigFile);
1077
1078 pDrvDriverEvent = (void *)GetProcAddress(hui, "DrvDriverEvent");
1079
1080 if (hui && pDrvDriverEvent)
1081 {
1082 /* Support for DrvDriverEvent is optional */
1083 TRACE("DRIVER_EVENT_INITIALIZE for %s (%s)\n", debugstr_w(di.pName), debugstr_w(di.pConfigFile));
1084 /* MSDN: level for DRIVER_INFO is 1 to 3 */
1085 res = pDrvDriverEvent(DRIVER_EVENT_INITIALIZE, 3, (LPBYTE) &di, 0);
1086 TRACE("got %d from DRIVER_EVENT_INITIALIZE\n", res);
1087 }
1088 FreeLibrary(hui);
1089
1090 FIXME("=> TRUE with %u\n", GetLastError());
1091 return TRUE;
1092 }
1093
1094 /******************************************************************************
1095 * AddPrinterDriverEx [exported through PRINTPROVIDOR]
1096 *
1097 * Install a Printer Driver with the Option to upgrade / downgrade the Files
1098 *
1099 * PARAMS
1100 * pName [I] Servername or NULL (local Computer)
1101 * level [I] Level for the supplied DRIVER_INFO_*W struct
1102 * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter
1103 * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files
1104 *
1105 * RESULTS
1106 * Success: TRUE
1107 * Failure: FALSE
1108 *
1109 */
1110 BOOL WINAPI LocalAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
1111 {
1112 LONG lres;
1113
1114 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
1115
1116 lres = copy_servername_from_name(pName, NULL);
1117
1118 if (lres)
1119 {
1120 FIXME("server %s not supported\n", debugstr_w(pName));
1121 SetLastError(ERROR_ACCESS_DENIED);
1122 return FALSE;
1123 }
1124
1125 if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES)
1126 {
1127 TRACE("Flags 0x%x ignored (using APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY);
1128 }
1129
1130 return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE);
1131 }
1132
1133 BOOL WINAPI LocalAddPrinterDriver(LPWSTR pName, DWORD level, LPBYTE pDriverInfo)
1134 {
1135 LONG lres;
1136
1137 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo);
1138
1139 lres = copy_servername_from_name(pName, NULL);
1140
1141 if (lres)
1142 {
1143 FIXME("server %s not supported\n", debugstr_w(pName));
1144 SetLastError(ERROR_ACCESS_DENIED);
1145 return FALSE;
1146 }
1147
1148 // Should be APD_COPY_NEW_FILES. Cheap wine.
1149
1150 return myAddPrinterDriverEx(level, pDriverInfo, APD_COPY_NEW_FILES, TRUE);
1151 }