1 /*
2  * PROJECT:     ReactOS Print Spooler Service
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Functions related to Printer Drivers
5  * COPYRIGHT:   Copyright 2015 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 #include "marshalling/printerdrivers.h"
10 
11 DWORD
12 _RpcAddPrinterDriver(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer)
13 {
14     DWORD dwErrorCode;
15     PBYTE pDriverInfo = NULL;
16 
17     switch ( pDriverContainer->Level )
18     {
19         case 8:
20         {
21             WINSPOOL_DRIVER_INFO_8 *pdi = pDriverContainer->DriverInfo.Level8;
22             PDRIVER_INFO_8W pdi8w = DllAllocSplMem(sizeof(DRIVER_INFO_8W));
23             pDriverInfo = (PBYTE)pdi8w;
24 
25             pdi8w->pszPrintProcessor           = pdi->pPrintProcessor;
26             pdi8w->pszVendorSetup              = pdi->pVendorSetup;
27             pdi8w->pszzColorProfiles           = pdi->pszzColorProfiles;
28             pdi8w->pszInfPath                  = pdi->pInfPath;
29             pdi8w->pszzCoreDriverDependencies  = pdi->pszzCoreDriverDependencies;
30             pdi8w->ftMinInboxDriverVerDate     = pdi->ftMinInboxDriverVerDate;
31             pdi8w->dwlMinInboxDriverVerVersion = pdi->dwlMinInboxDriverVerVersion;
32         }
33         case 6:
34         {
35             WINSPOOL_DRIVER_INFO_6 *pdi = pDriverContainer->DriverInfo.Level6;
36             PDRIVER_INFO_6W pdi6w;
37 
38             if ( pDriverInfo == NULL )
39             {
40                 pdi6w = DllAllocSplMem(sizeof(DRIVER_INFO_6W));
41                 pDriverInfo = (PBYTE)pdi6w;
42             }
43             else
44             {
45                 pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
46             }
47 
48             pdi6w->pszMfgName       = pdi->pMfgName;
49             pdi6w->pszOEMUrl        = pdi->pOEMUrl;
50             pdi6w->pszHardwareID    = pdi->pHardwareID;
51             pdi6w->pszProvider      = pdi->pProvider;
52             pdi6w->ftDriverDate     = pdi->ftDriverDate;
53             pdi6w->dwlDriverVersion = pdi->dwlDriverVersion;
54         }
55         case 4:
56         {
57             WINSPOOL_DRIVER_INFO_4 *pdi = pDriverContainer->DriverInfo.Level4;
58             PDRIVER_INFO_4W pdi4w;
59 
60             if ( pDriverInfo == NULL )
61             {
62                 pdi4w = DllAllocSplMem(sizeof(DRIVER_INFO_4W));
63                 pDriverInfo = (PBYTE)pdi4w;
64             }
65             else
66             {
67                 pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
68             }
69 
70             pdi4w->pszzPreviousNames = pdi->pszzPreviousNames;
71         }
72         case 3:
73         {
74             WINSPOOL_DRIVER_INFO_3 *pdi = pDriverContainer->DriverInfo.Level3;
75             PDRIVER_INFO_3W pdi3w;
76 
77             if ( pDriverInfo == NULL )
78             {
79                 pdi3w = DllAllocSplMem(sizeof(DRIVER_INFO_3W));
80                 pDriverInfo = (PBYTE)pdi3w;
81             }
82             else
83             {
84                 pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
85             }
86 
87             pdi3w->pHelpFile        = pdi->pHelpFile;
88             pdi3w->pDependentFiles  = pdi->pDependentFiles;
89             pdi3w->pMonitorName     = pdi->pMonitorName;
90             pdi3w->pDefaultDataType = pdi->pDefaultDataType;
91             pdi3w->pDependentFiles  = pdi->pDependentFiles;
92         }
93         case 2:
94         {
95             WINSPOOL_DRIVER_INFO_2 *pdi = pDriverContainer->DriverInfo.Level2;
96             PDRIVER_INFO_2W pdi2w;
97 
98             if ( pDriverInfo == NULL )
99             {
100                 pdi2w = DllAllocSplMem(sizeof(DRIVER_INFO_2W));
101                 pDriverInfo = (PBYTE)pdi2w;
102             }
103             else
104             {
105                 pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
106             }
107 
108             pdi2w->pName        = pdi->pName;
109             pdi2w->pEnvironment = pdi->pEnvironment;
110             pdi2w->pDriverPath  = pdi->pDriverPath;
111             pdi2w->pDataFile    = pdi->pDataFile;
112             pdi2w->pConfigFile  = pdi->pConfigFile;
113         }
114             break;
115         //
116         // At this point pDriverInfo is null.
117         //
118         default:
119             return ERROR_INVALID_LEVEL;
120     }
121 
122     dwErrorCode = RpcImpersonateClient(NULL);
123     if (dwErrorCode != ERROR_SUCCESS)
124     {
125         ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
126         return dwErrorCode;
127     }
128 
129     if (!AddPrinterDriverW( pName, pDriverContainer->Level, pDriverInfo ))
130         dwErrorCode = GetLastError();
131 
132     if ( pDriverInfo ) DllFreeSplMem( pDriverInfo );
133 
134     RpcRevertToSelf();
135     return dwErrorCode;
136 }
137 
138 DWORD
139 _RpcAddPrinterDriverEx(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer, DWORD dwFileCopyFlags)
140 {
141     DWORD dwErrorCode;
142     PBYTE pDriverInfo = NULL;
143 
144     switch ( pDriverContainer->Level )
145     {
146         case 8:
147         {
148             WINSPOOL_DRIVER_INFO_8 *pdi = pDriverContainer->DriverInfo.Level8;
149             PDRIVER_INFO_8W pdi8w = DllAllocSplMem(sizeof(DRIVER_INFO_8W));
150             pDriverInfo = (PBYTE)pdi8w;
151 
152             pdi8w->pszPrintProcessor           = pdi->pPrintProcessor;
153             pdi8w->pszVendorSetup              = pdi->pVendorSetup;
154             pdi8w->pszzColorProfiles           = pdi->pszzColorProfiles;
155             pdi8w->pszInfPath                  = pdi->pInfPath;
156             pdi8w->pszzCoreDriverDependencies  = pdi->pszzCoreDriverDependencies;
157             pdi8w->ftMinInboxDriverVerDate     = pdi->ftMinInboxDriverVerDate;
158             pdi8w->dwlMinInboxDriverVerVersion = pdi->dwlMinInboxDriverVerVersion;
159         }
160         case 6:
161         {
162             WINSPOOL_DRIVER_INFO_6 *pdi = pDriverContainer->DriverInfo.Level6;
163             PDRIVER_INFO_6W pdi6w;
164 
165             if ( pDriverInfo == NULL )
166             {
167                 pdi6w = DllAllocSplMem(sizeof(DRIVER_INFO_6W));
168                 pDriverInfo = (PBYTE)pdi6w;
169             }
170             else
171             {
172                 pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
173             }
174 
175             pdi6w->pszMfgName       = pdi->pMfgName;
176             pdi6w->pszOEMUrl        = pdi->pOEMUrl;
177             pdi6w->pszHardwareID    = pdi->pHardwareID;
178             pdi6w->pszProvider      = pdi->pProvider;
179             pdi6w->ftDriverDate     = pdi->ftDriverDate;
180             pdi6w->dwlDriverVersion = pdi->dwlDriverVersion;
181         }
182         case 4:
183         {
184             WINSPOOL_DRIVER_INFO_4 *pdi = pDriverContainer->DriverInfo.Level4;
185             PDRIVER_INFO_4W pdi4w;
186 
187             if ( pDriverInfo == NULL )
188             {
189                 pdi4w = DllAllocSplMem(sizeof(DRIVER_INFO_4W));
190                 pDriverInfo = (PBYTE)pdi4w;
191             }
192             else
193             {
194                 pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
195             }
196 
197             pdi4w->pszzPreviousNames = pdi->pszzPreviousNames;
198         }
199         case 3:
200         {
201             WINSPOOL_DRIVER_INFO_3 *pdi = pDriverContainer->DriverInfo.Level3;
202             PDRIVER_INFO_3W pdi3w;
203 
204             if ( pDriverInfo == NULL )
205             {
206                 pdi3w = DllAllocSplMem(sizeof(DRIVER_INFO_3W));
207                 pDriverInfo = (PBYTE)pdi3w;
208             }
209             else
210             {
211                 pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
212             }
213 
214             pdi3w->pHelpFile        = pdi->pHelpFile;
215             pdi3w->pDependentFiles  = pdi->pDependentFiles;
216             pdi3w->pMonitorName     = pdi->pMonitorName;
217             pdi3w->pDefaultDataType = pdi->pDefaultDataType;
218             pdi3w->pDependentFiles  = pdi->pDependentFiles;
219         }
220         case 2:
221         {
222             WINSPOOL_DRIVER_INFO_2 *pdi = pDriverContainer->DriverInfo.Level2;
223             PDRIVER_INFO_2W pdi2w;
224 
225             if ( pDriverInfo == NULL )
226             {
227                 pdi2w = DllAllocSplMem(sizeof(DRIVER_INFO_2W));
228                 pDriverInfo = (PBYTE)pdi2w;
229             }
230             else
231             {
232                 pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
233             }
234 
235             pdi2w->pName        = pdi->pName;
236             pdi2w->pEnvironment = pdi->pEnvironment;
237             pdi2w->pDriverPath  = pdi->pDriverPath;
238             pdi2w->pDataFile    = pdi->pDataFile;
239             pdi2w->pConfigFile  = pdi->pConfigFile;
240         }
241             break;
242         //
243         // At this point pDriverInfo is null.
244         //
245         default:
246             return ERROR_INVALID_LEVEL;
247     }
248 
249     dwErrorCode = RpcImpersonateClient(NULL);
250     if (dwErrorCode != ERROR_SUCCESS)
251     {
252         ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
253         return dwErrorCode;
254     }
255 
256     if (!AddPrinterDriverExW( pName, pDriverContainer->Level, pDriverInfo, dwFileCopyFlags ))
257         dwErrorCode = GetLastError();
258 
259     if ( pDriverInfo ) DllFreeSplMem( pDriverInfo );
260 
261     RpcRevertToSelf();
262     return dwErrorCode;
263 }
264 
265 DWORD
266 _RpcDeletePrinterDriver(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pDriverName)
267 {
268     DWORD dwErrorCode;
269 
270     dwErrorCode = RpcImpersonateClient(NULL);
271     if (dwErrorCode != ERROR_SUCCESS)
272     {
273         ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
274         return dwErrorCode;
275     }
276 
277     if (!DeletePrinterDriverW(pName, pEnvironment, pDriverName))
278         dwErrorCode = GetLastError();
279 
280     RpcRevertToSelf();
281     return dwErrorCode;
282 }
283 
284 DWORD
285 _RpcDeletePrinterDriverEx(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pDriverName, DWORD dwDeleteFlag, DWORD dwVersionNum)
286 {
287     DWORD dwErrorCode;
288 
289     dwErrorCode = RpcImpersonateClient(NULL);
290     if (dwErrorCode != ERROR_SUCCESS)
291     {
292         ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
293         return dwErrorCode;
294     }
295 
296     if (!DeletePrinterDriverExW(pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionNum))
297         dwErrorCode = GetLastError();
298 
299     RpcRevertToSelf();
300     return dwErrorCode;
301 }
302 
303 DWORD
304 _RpcEnumPrinterDrivers(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pDrivers, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
305 {
306     DWORD dwErrorCode;
307     PBYTE pPrinterDriversEnumAligned;
308 
309     dwErrorCode = RpcImpersonateClient(NULL);
310     if (dwErrorCode != ERROR_SUCCESS)
311     {
312         ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
313         return dwErrorCode;
314     }
315 
316     pPrinterDriversEnumAligned = AlignRpcPtr(pDrivers, &cbBuf);
317 
318     if (EnumPrinterDriversW(pName, pEnvironment, Level, pPrinterDriversEnumAligned, cbBuf, pcbNeeded, pcReturned))
319     {
320         // Replace absolute pointer addresses in the output by relative offsets.
321         ASSERT(Level <= 6 || Level == 8);
322         MarshallDownStructuresArray(pPrinterDriversEnumAligned, *pcReturned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
323     }
324     else
325     {
326         dwErrorCode = GetLastError();
327     }
328 
329     RpcRevertToSelf();
330     UndoAlignRpcPtr(pDrivers, pPrinterDriversEnumAligned, cbBuf, pcbNeeded);
331 
332     return dwErrorCode;
333 }
334 
335 DWORD
336 _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level, BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded)
337 {
338     DWORD dwErrorCode;
339     PBYTE pDriverAligned;
340 
341     TRACE("_RpcGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded);
342 
343     dwErrorCode = RpcImpersonateClient(NULL);
344     if (dwErrorCode != ERROR_SUCCESS)
345     {
346         ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
347         return dwErrorCode;
348     }
349 
350     pDriverAligned = AlignRpcPtr(pDriver, &cbBuf);
351 
352     if (GetPrinterDriverW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded))
353     {
354         // Replace relative offset addresses in the output by absolute pointers.
355         ASSERT(Level <= 6 || Level == 8);
356         MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
357     }
358     else
359     {
360         dwErrorCode = GetLastError();
361     }
362 
363     RpcRevertToSelf();
364     UndoAlignRpcPtr(pDriver, pDriverAligned, cbBuf, pcbNeeded);
365 
366     return dwErrorCode;
367 }
368 
369 BOOL WINAPI YGetPrinterDriver2(
370     HANDLE hPrinter,
371     LPWSTR pEnvironment,
372     DWORD Level,
373     LPBYTE pDriver,
374     DWORD cbBuf,
375     LPDWORD pcbNeeded,
376     DWORD dwClientMajorVersion,
377     DWORD dwClientMinorVersion,
378     PDWORD pdwServerMajorVersion,
379     PDWORD pdwServerMinorVersion,
380     BOOL bRPC )                    // Seems that all Y fuctions have this.
381 {
382     DWORD dwErrorCode;
383     PBYTE pDriverAligned;
384 
385     FIXME("_Rpc(Y)GetPrinterDriver2(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion);
386 
387     if ( bRPC )
388     {
389         dwErrorCode = RpcImpersonateClient(NULL);
390         if (dwErrorCode != ERROR_SUCCESS)
391         {
392             ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
393             return dwErrorCode;
394         }
395     }
396 
397     pDriverAligned = AlignRpcPtr(pDriver, &cbBuf);
398 
399     if (GetPrinterDriverExW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion))
400     {
401         // Replace relative offset addresses in the output by absolute pointers.
402         ASSERT(Level <= 6 || Level == 8);
403         MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
404     }
405     else
406     {
407         dwErrorCode = GetLastError();
408     }
409 
410     if ( bRPC ) RpcRevertToSelf();
411     UndoAlignRpcPtr(pDriver, pDriverAligned, cbBuf, pcbNeeded);
412 
413     return dwErrorCode;
414 }
415 
416 DWORD
417 _RpcGetPrinterDriver2(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level, BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded, DWORD dwClientMajorVersion, DWORD dwClientMinorVersion, DWORD* pdwServerMaxVersion, DWORD* pdwServerMinVersion)
418 {
419     DWORD dwErrorCode;
420     PBYTE pDriverAligned;
421 
422     FIXME("_RpcGetPrinterDriver2(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMaxVersion, pdwServerMinVersion);
423 
424     dwErrorCode = RpcImpersonateClient(NULL);
425     if (dwErrorCode != ERROR_SUCCESS)
426     {
427         ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
428         return dwErrorCode;
429     }
430 
431     pDriverAligned = AlignRpcPtr(pDriver, &cbBuf);
432 
433     if (GetPrinterDriverExW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMaxVersion, pdwServerMinVersion))
434     {
435         // Replace relative offset addresses in the output by absolute pointers.
436         ASSERT(Level <= 6 || Level == 8);
437         MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
438     }
439     else
440     {
441         dwErrorCode = GetLastError();
442     }
443 
444     RpcRevertToSelf();
445     UndoAlignRpcPtr(pDriver, pDriverAligned, cbBuf, pcbNeeded);
446 
447     return dwErrorCode;
448 }
449 
450 DWORD
451 _RpcGetPrinterDriverDirectory(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pDriverDirectory, DWORD cbBuf, DWORD* pcbNeeded)
452 {
453     DWORD dwErrorCode;
454 
455     dwErrorCode = RpcImpersonateClient(NULL);
456     if (dwErrorCode != ERROR_SUCCESS)
457     {
458         ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
459         return dwErrorCode;
460     }
461 
462     if (!GetPrinterDriverDirectoryW(pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded))
463         dwErrorCode = GetLastError();
464 
465     RpcRevertToSelf();
466     return dwErrorCode;
467 }
468