ReactOS  0.4.14-dev-991-g696cdc6
printprocessors.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Local Spooler
3  * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE: Functions related to Print Processors
5  * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 
11 // Local Variables
13 
29 static DWORD
30 _OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
31 {
32  const WCHAR wszEnvironmentsKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\";
33  const DWORD cchEnvironmentsKey = _countof(wszEnvironmentsKey) - 1;
34 
35  DWORD cchEnvironment;
36  DWORD dwErrorCode;
37  PWSTR pwszEnvironmentKey = NULL;
38 
39  // Sanity checks
40  if (!pEnvironment)
41  {
42  dwErrorCode = ERROR_INVALID_ENVIRONMENT;
43  goto Cleanup;
44  }
45 
46  // Construct the registry key of the demanded environment.
47  cchEnvironment = wcslen(pEnvironment);
48  pwszEnvironmentKey = DllAllocSplMem((cchEnvironmentsKey + cchEnvironment + 1) * sizeof(WCHAR));
49  if (!pwszEnvironmentKey)
50  {
51  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
52  ERR("DllAllocSplMem failed!\n");
53  goto Cleanup;
54  }
55 
56  CopyMemory(pwszEnvironmentKey, wszEnvironmentsKey, cchEnvironmentsKey * sizeof(WCHAR));
57  CopyMemory(&pwszEnvironmentKey[cchEnvironmentsKey], pEnvironment, (cchEnvironment + 1) * sizeof(WCHAR));
58 
59  // Open the registry key.
60  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, pwszEnvironmentKey, 0, KEY_READ, hKey);
61  if (dwErrorCode == ERROR_FILE_NOT_FOUND)
62  {
63  dwErrorCode = ERROR_INVALID_ENVIRONMENT;
64  goto Cleanup;
65  }
66  else if (dwErrorCode != ERROR_SUCCESS)
67  {
68  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
69  goto Cleanup;
70  }
71 
72 Cleanup:
73  if (pwszEnvironmentKey)
74  DllFreeSplMem(pwszEnvironmentKey);
75 
76  return dwErrorCode;
77 }
78 
79 BOOL
80 FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype)
81 {
82  DWORD i;
83  PDATATYPES_INFO_1W pCurrentDatatype = pPrintProcessor->pDatatypesInfo1;
84 
85  TRACE("FindDatatype(%p, %S)\n", pPrintProcessor, pwszDatatype);
86 
87  if (!pwszDatatype)
88  return FALSE;
89 
90  for (i = 0; i < pPrintProcessor->dwDatatypeCount; i++)
91  {
92  if (wcsicmp(pCurrentDatatype->pName, pwszDatatype) == 0)
93  return TRUE;
94 
95  ++pCurrentDatatype;
96  }
97 
98  return FALSE;
99 }
100 
103 {
104  PLIST_ENTRY pEntry;
105  PLOCAL_PRINT_PROCESSOR pPrintProcessor;
106 
107  TRACE("FindPrintProcessor(%S)\n", pwszName);
108 
109  if (!pwszName)
110  return NULL;
111 
112  for (pEntry = _PrintProcessorList.Flink; pEntry != &_PrintProcessorList; pEntry = pEntry->Flink)
113  {
114  pPrintProcessor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_PROCESSOR, Entry);
115 
116  if (wcsicmp(pPrintProcessor->pwszName, pwszName) == 0)
117  return pPrintProcessor;
118  }
119 
120  return NULL;
121 }
122 
128 BOOL
130 {
131  DWORD cbDatatypes;
132  DWORD cbFileName;
133  DWORD cchPrintProcessorPath;
134  DWORD cchMaxSubKey;
135  DWORD cchPrintProcessorName;
136  DWORD dwErrorCode;
137  DWORD dwSubKeys;
138  DWORD i;
139  HINSTANCE hinstPrintProcessor;
140  HKEY hKey = NULL;
141  HKEY hSubKey = NULL;
142  HKEY hSubSubKey = NULL;
143  PLOCAL_PRINT_PROCESSOR pPrintProcessor = NULL;
145  WCHAR wszPrintProcessorPath[MAX_PATH];
146 
147  TRACE("InitializePrintProcessorList()\n");
148 
149  // Initialize an empty list for our Print Processors.
151 
152  // Prepare the path to the Print Processor directory.
153  if (!LocalGetPrintProcessorDirectory(NULL, (PWSTR)wszCurrentEnvironment, 1, (PBYTE)wszPrintProcessorPath, sizeof(wszPrintProcessorPath), &cchPrintProcessorPath))
154  {
155  dwErrorCode = GetLastError();
156  goto Cleanup;
157  }
158 
159  // LocalGetPrintProcessorDirectory returns the number of copied bytes. Convert this into a number of characters without the terminating null-character.
160  cchPrintProcessorPath /= sizeof(WCHAR);
161  --cchPrintProcessorPath;
162 
163  // Append a trailing backslash.
164  wszPrintProcessorPath[cchPrintProcessorPath] = L'\\';
165  ++cchPrintProcessorPath;
166 
167  // Open the environment registry key.
168  dwErrorCode = _OpenEnvironment(wszCurrentEnvironment, &hKey);
169  if (dwErrorCode != ERROR_SUCCESS)
170  goto Cleanup;
171 
172  // Open the "Print Processors" subkey.
173  dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey);
174  if (dwErrorCode != ERROR_SUCCESS)
175  {
176  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
177  goto Cleanup;
178  }
179 
180  // Get the number of Print Processors and maximum sub key length.
181  dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
182  if (dwErrorCode != ERROR_SUCCESS)
183  {
184  ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
185  goto Cleanup;
186  }
187 
188  // Loop through all available local Print Processors.
189  for (i = 0; i < dwSubKeys; i++)
190  {
191  // Cleanup tasks from the previous run
192  if (hSubSubKey)
193  {
194  RegCloseKey(hSubSubKey);
195  hSubSubKey = NULL;
196  }
197 
198  if (pPrintProcessor)
199  {
200  if (pPrintProcessor->pwszName)
201  DllFreeSplStr(pPrintProcessor->pwszName);
202 
203  if (pPrintProcessor->pDatatypesInfo1)
204  DllFreeSplMem(pPrintProcessor->pDatatypesInfo1);
205 
206  DllFreeSplMem(pPrintProcessor);
207  pPrintProcessor = NULL;
208  }
209 
210  // Create a new LOCAL_PRINT_PROCESSOR structure for it.
211  pPrintProcessor = DllAllocSplMem(sizeof(LOCAL_PRINT_PROCESSOR));
212  if (!pPrintProcessor)
213  {
214  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
215  ERR("DllAllocSplMem failed!\n");
216  goto Cleanup;
217  }
218 
219  // Allocate memory for the Print Monitor Name.
220  pPrintProcessor->pwszName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
221  if (!pPrintProcessor->pwszName)
222  {
223  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
224  ERR("DllAllocSplMem failed!\n");
225  goto Cleanup;
226  }
227 
228  // Get the name of this Print Processor.
229  cchPrintProcessorName = cchMaxSubKey + 1;
230  dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, pPrintProcessor->pwszName, &cchPrintProcessorName, NULL, NULL, NULL, NULL);
231  if (dwErrorCode != ERROR_SUCCESS)
232  {
233  ERR("RegEnumKeyExW failed with status %ld!\n", dwErrorCode);
234  continue;
235  }
236 
237  // Open this Print Processor's registry key.
238  dwErrorCode = (DWORD)RegOpenKeyExW(hSubKey, pPrintProcessor->pwszName, 0, KEY_READ, &hSubSubKey);
239  if (dwErrorCode != ERROR_SUCCESS)
240  {
241  ERR("RegOpenKeyExW failed for Print Processor \"%S\" with status %lu!\n", pPrintProcessor->pwszName, dwErrorCode);
242  continue;
243  }
244 
245  // Get the file name of the Print Processor.
246  cbFileName = sizeof(wszFileName);
247  dwErrorCode = (DWORD)RegQueryValueExW(hSubSubKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName);
248  if (dwErrorCode != ERROR_SUCCESS)
249  {
250  ERR("RegQueryValueExW failed for Print Processor \"%S\" with status %lu!\n", pPrintProcessor->pwszName, dwErrorCode);
251  continue;
252  }
253 
254  // Verify that our buffer is large enough.
255  if (cchPrintProcessorPath + cbFileName / sizeof(WCHAR) > MAX_PATH)
256  {
257  ERR("Print Processor directory \"%S\" for Print Processor \"%S\" is too long!\n", wszFileName, pPrintProcessor->pwszName);
258  continue;
259  }
260 
261  // Construct the full path to the Print Processor.
262  CopyMemory(&wszPrintProcessorPath[cchPrintProcessorPath], wszFileName, cbFileName);
263 
264  // Try to load it.
265  hinstPrintProcessor = LoadLibraryW(wszPrintProcessorPath);
266  if (!hinstPrintProcessor)
267  {
268  ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", wszPrintProcessorPath, GetLastError());
269  continue;
270  }
271 
272  // Get and verify all its function pointers.
273  pPrintProcessor->pfnClosePrintProcessor = (PClosePrintProcessor)GetProcAddress(hinstPrintProcessor, "ClosePrintProcessor");
274  if (!pPrintProcessor->pfnClosePrintProcessor)
275  {
276  ERR("Print Processor \"%S\" exports no ClosePrintProcessor!\n", wszPrintProcessorPath);
277  continue;
278  }
279 
280  pPrintProcessor->pfnControlPrintProcessor = (PControlPrintProcessor)GetProcAddress(hinstPrintProcessor, "ControlPrintProcessor");
281  if (!pPrintProcessor->pfnControlPrintProcessor)
282  {
283  ERR("Print Processor \"%S\" exports no ControlPrintProcessor!\n", wszPrintProcessorPath);
284  continue;
285  }
286 
287  pPrintProcessor->pfnEnumPrintProcessorDatatypesW = (PEnumPrintProcessorDatatypesW)GetProcAddress(hinstPrintProcessor, "EnumPrintProcessorDatatypesW");
288  if (!pPrintProcessor->pfnEnumPrintProcessorDatatypesW)
289  {
290  ERR("Print Processor \"%S\" exports no EnumPrintProcessorDatatypesW!\n", wszPrintProcessorPath);
291  continue;
292  }
293 
294  pPrintProcessor->pfnGetPrintProcessorCapabilities = (PGetPrintProcessorCapabilities)GetProcAddress(hinstPrintProcessor, "GetPrintProcessorCapabilities");
295  if (!pPrintProcessor->pfnGetPrintProcessorCapabilities)
296  {
297  ERR("Print Processor \"%S\" exports no GetPrintProcessorCapabilities!\n", wszPrintProcessorPath);
298  continue;
299  }
300 
301  pPrintProcessor->pfnOpenPrintProcessor = (POpenPrintProcessor)GetProcAddress(hinstPrintProcessor, "OpenPrintProcessor");
302  if (!pPrintProcessor->pfnOpenPrintProcessor)
303  {
304  ERR("Print Processor \"%S\" exports no OpenPrintProcessor!\n", wszPrintProcessorPath);
305  continue;
306  }
307 
308  pPrintProcessor->pfnPrintDocumentOnPrintProcessor = (PPrintDocumentOnPrintProcessor)GetProcAddress(hinstPrintProcessor, "PrintDocumentOnPrintProcessor");
309  if (!pPrintProcessor->pfnPrintDocumentOnPrintProcessor)
310  {
311  ERR("Print Processor \"%S\" exports no PrintDocumentOnPrintProcessor!\n", wszPrintProcessorPath);
312  continue;
313  }
314 
315  // Get all supported datatypes.
316  pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1, NULL, 0, &cbDatatypes, &pPrintProcessor->dwDatatypeCount);
317  pPrintProcessor->pDatatypesInfo1 = DllAllocSplMem(cbDatatypes);
318  if (!pPrintProcessor->pDatatypesInfo1)
319  {
320  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
321  ERR("DllAllocSplMem failed!\n");
322  goto Cleanup;
323  }
324 
325  if (!pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1, (PBYTE)pPrintProcessor->pDatatypesInfo1, cbDatatypes, &cbDatatypes, &pPrintProcessor->dwDatatypeCount))
326  {
327  ERR("EnumPrintProcessorDatatypesW failed for Print Processor \"%S\" with error %lu!\n", wszPrintProcessorPath, GetLastError());
328  continue;
329  }
330 
331  // Add the Print Processor to the list.
332  InsertTailList(&_PrintProcessorList, &pPrintProcessor->Entry);
333 
334  // Don't let the cleanup routines free this.
335  pPrintProcessor = NULL;
336  }
337 
338  dwErrorCode = ERROR_SUCCESS;
339 
340 Cleanup:
341  // Inside the loop
342  if (hSubSubKey)
343  RegCloseKey(hSubSubKey);
344 
345  if (pPrintProcessor)
346  {
347  if (pPrintProcessor->pwszName)
348  DllFreeSplStr(pPrintProcessor->pwszName);
349 
350  if (pPrintProcessor->pDatatypesInfo1)
351  DllFreeSplMem(pPrintProcessor->pDatatypesInfo1);
352 
353  DllFreeSplMem(pPrintProcessor);
354  }
355 
356  // Outside the loop
357  if (hSubKey)
358  RegCloseKey(hSubKey);
359 
360  if (hKey)
361  RegCloseKey(hKey);
362 
363  SetLastError(dwErrorCode);
364  return (dwErrorCode == ERROR_SUCCESS);
365 }
366 
401 BOOL WINAPI
402 LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
403 {
404  DWORD dwErrorCode;
405  PLOCAL_PRINT_PROCESSOR pPrintProcessor;
406 
407  TRACE("LocalEnumPrintProcessorDatatypes(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
408 
409  // Sanity checks
410  if (Level != 1)
411  {
412  dwErrorCode = ERROR_INVALID_LEVEL;
413  goto Cleanup;
414  }
415 
416  // Try to find the Print Processor.
417  pPrintProcessor = FindPrintProcessor(pPrintProcessorName);
418  if (!pPrintProcessor)
419  {
420  dwErrorCode = ERROR_UNKNOWN_PRINTPROCESSOR;
421  goto Cleanup;
422  }
423 
424  // Call its EnumPrintProcessorDatatypesW function.
425  if (pPrintProcessor->pfnEnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned))
426  dwErrorCode = ERROR_SUCCESS;
427  else
428  dwErrorCode = GetLastError();
429 
430 Cleanup:
431  SetLastError(dwErrorCode);
432  return (dwErrorCode == ERROR_SUCCESS);
433 }
434 
470 BOOL WINAPI
471 LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
472 {
473  DWORD cchMaxSubKey;
474  DWORD cchPrintProcessor;
475  DWORD dwErrorCode;
476  DWORD dwPrintProcessorCount;
477  DWORD i;
478  HKEY hKey = NULL;
479  HKEY hSubKey = NULL;
480  PBYTE pCurrentOutputPrintProcessor;
481  PBYTE pCurrentOutputPrintProcessorInfo;
482  PRINTPROCESSOR_INFO_1W PrintProcessorInfo1;
483  PWSTR pwszTemp = NULL;
484 
485  TRACE("LocalEnumPrintProcessors(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
486 
487  // Sanity checks
488  if (Level != 1)
489  {
490  dwErrorCode = ERROR_INVALID_LEVEL;
491  goto Cleanup;
492  }
493 
494  if (!pcbNeeded || !pcReturned)
495  {
496  // This error is also caught by RPC and returned as RPC_X_NULL_REF_POINTER.
497  dwErrorCode = ERROR_INVALID_PARAMETER;
498  goto Cleanup;
499  }
500 
501  // Verify pEnvironment and open its registry key.
502  // We use the registry and not the PrintProcessorList here, because the caller may request information about a different environment.
503  dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
504  if (dwErrorCode != ERROR_SUCCESS)
505  goto Cleanup;
506 
507  // Open the "Print Processors" subkey.
508  dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey);
509  if (dwErrorCode != ERROR_SUCCESS)
510  {
511  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
512  goto Cleanup;
513  }
514 
515  // Get the number of Print Processors and maximum sub key length.
516  dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwPrintProcessorCount, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
517  if (dwErrorCode != ERROR_SUCCESS)
518  {
519  ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
520  goto Cleanup;
521  }
522 
523  // Allocate a temporary buffer to let RegEnumKeyExW succeed.
524  pwszTemp = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
525  if (!pwszTemp)
526  {
527  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
528  ERR("DllAllocSplMem failed!\n");
529  goto Cleanup;
530  }
531 
532  // Determine the required size of the output buffer.
533  *pcbNeeded = 0;
534 
535  for (i = 0; i < dwPrintProcessorCount; i++)
536  {
537  // RegEnumKeyExW sucks! Unlike similar API functions, it only returns the actual numbers of characters copied when you supply a buffer large enough.
538  // So use pwszTemp with its size cchMaxSubKey for this.
539  cchPrintProcessor = cchMaxSubKey + 1;
540  dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, pwszTemp, &cchPrintProcessor, NULL, NULL, NULL, NULL);
541  if (dwErrorCode != ERROR_SUCCESS)
542  {
543  ERR("RegEnumKeyExW failed with status %lu!\n", dwErrorCode);
544  goto Cleanup;
545  }
546 
547  *pcbNeeded += sizeof(PRINTPROCESSOR_INFO_1W) + (cchPrintProcessor + 1) * sizeof(WCHAR);
548  }
549 
550  // Check if the supplied buffer is large enough.
551  if (cbBuf < *pcbNeeded)
552  {
553  dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
554  goto Cleanup;
555  }
556 
557  // Put the Print Processor strings right after the last PRINTPROCESSOR_INFO_1W structure.
558  pCurrentOutputPrintProcessorInfo = pPrintProcessorInfo;
559  pCurrentOutputPrintProcessor = pPrintProcessorInfo + dwPrintProcessorCount * sizeof(PRINTPROCESSOR_INFO_1W);
560 
561  // Copy over all Print Processors.
562  for (i = 0; i < dwPrintProcessorCount; i++)
563  {
564  // This isn't really correct, but doesn't cause any harm, because we've extensively checked the size of the supplied buffer above.
565  cchPrintProcessor = cchMaxSubKey + 1;
566 
567  // Copy the Print Processor name.
568  dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, (PWSTR)pCurrentOutputPrintProcessor, &cchPrintProcessor, NULL, NULL, NULL, NULL);
569  if (dwErrorCode != ERROR_SUCCESS)
570  {
571  ERR("RegEnumKeyExW failed with status %lu!\n", dwErrorCode);
572  goto Cleanup;
573  }
574 
575  // Fill and copy the PRINTPROCESSOR_INFO_1W structure belonging to this Print Processor.
576  PrintProcessorInfo1.pName = (PWSTR)pCurrentOutputPrintProcessor;
577  CopyMemory(pCurrentOutputPrintProcessorInfo, &PrintProcessorInfo1, sizeof(PRINTPROCESSOR_INFO_1W));
578 
579  // Advance to the next PRINTPROCESSOR_INFO_1W location and string location in the output buffer.
580  pCurrentOutputPrintProcessor += (cchPrintProcessor + 1) * sizeof(WCHAR);
581  pCurrentOutputPrintProcessorInfo += sizeof(PRINTPROCESSOR_INFO_1W);
582  }
583 
584  // We've finished successfully!
585  *pcReturned = dwPrintProcessorCount;
586  dwErrorCode = ERROR_SUCCESS;
587 
588 Cleanup:
589  if (pwszTemp)
590  DllFreeSplMem(pwszTemp);
591 
592  if (hSubKey)
593  RegCloseKey(hSubKey);
594 
595  if (hKey)
596  RegCloseKey(hKey);
597 
598  SetLastError(dwErrorCode);
599  return (dwErrorCode == ERROR_SUCCESS);
600 }
601 
632 BOOL WINAPI
634 {
635  const WCHAR wszPath[] = L"\\PRTPROCS\\";
636  const DWORD cchPath = _countof(wszPath) - 1;
637 
638  DWORD cbDirectoryName;
639  DWORD dwErrorCode;
640  HKEY hKey = NULL;
641  PWSTR pwszDirectory = (PWSTR)pPrintProcessorInfo;
642 
643  TRACE("LocalGetPrintProcessorDirectory(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
644 
645  // Verify pEnvironment and open its registry key.
646  dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
647  if (dwErrorCode != ERROR_SUCCESS)
648  {
649  ERR("_OpenEnvironment failed with error %lu!\n", dwErrorCode);
650  goto Cleanup;
651  }
652 
653  // Determine the size of the required buffer.
654  dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Directory", NULL, NULL, NULL, &cbDirectoryName);
655  if (dwErrorCode != ERROR_SUCCESS)
656  {
657  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
658  goto Cleanup;
659  }
660 
661  *pcbNeeded = (cchSpoolDirectory + cchPath) * sizeof(WCHAR) + cbDirectoryName;
662 
663  // Is the supplied buffer large enough?
664  if (cbBuf < *pcbNeeded)
665  {
666  dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
667  goto Cleanup;
668  }
669 
670  // Copy the path to the "prtprocs" directory into pPrintProcessorInfo
671  CopyMemory(pwszDirectory, wszSpoolDirectory, cchSpoolDirectory * sizeof(WCHAR));
672  CopyMemory(&pwszDirectory[cchSpoolDirectory], wszPath, cchPath * sizeof(WCHAR));
673 
674  // Get the directory name from the registry.
675  dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Directory", NULL, NULL, (PBYTE)&pwszDirectory[cchSpoolDirectory + cchPath], &cbDirectoryName);
676  if (dwErrorCode != ERROR_SUCCESS)
677  {
678  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
679  goto Cleanup;
680  }
681 
682  // We've finished successfully!
683  dwErrorCode = ERROR_SUCCESS;
684 
685 Cleanup:
686  if (hKey)
687  RegCloseKey(hKey);
688 
689  SetLastError(dwErrorCode);
690  return (dwErrorCode == ERROR_SUCCESS);
691 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static WCHAR wszFileName[MAX_PATH]
Definition: wordpad.c:72
const uint16_t * PCWSTR
Definition: typedefs.h:56
#define TRUE
Definition: types.h:120
#define ERROR_SUCCESS
Definition: deptool.c:10
PDATATYPES_INFO_1W pDatatypesInfo1
Definition: precomp.h:98
BOOL InitializePrintProcessorList(void)
PEnumPrintProcessorDatatypesW pfnEnumPrintProcessorDatatypesW
Definition: precomp.h:102
PPrintDocumentOnPrintProcessor pfnPrintDocumentOnPrintProcessor
Definition: precomp.h:105
#define KEY_READ
Definition: nt_native.h:1023
uint16_t * PWSTR
Definition: typedefs.h:55
#define _countof(array)
Definition: fontsub.cpp:30
BOOL WINAPI DllFreeSplMem(PVOID pMem)
Definition: memory.c:112
static LIST_ENTRY _PrintProcessorList
PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PCWSTR pwszName)
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static DWORD _OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
#define InsertTailList(ListHead, Entry)
#define DWORD
Definition: nt_native.h:44
struct _PRINTPROCESSOR_INFO_1W PRINTPROCESSOR_INFO_1W
BOOL WINAPI LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
DWORD(WINAPI * PGetPrintProcessorCapabilities)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD)
Definition: precomp.h:47
BOOL FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
const WCHAR wszCurrentEnvironment[]
Definition: prtprocenv.h:11
BOOL WINAPI LocalGetPrintProcessorDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded)
#define LoadLibraryW(x)
Definition: compat.h:412
smooth NULL
Definition: ftsmooth.c:416
DWORD cchSpoolDirectory
Definition: main.c:16
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
BOOL WINAPI LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
#define TRACE(s)
Definition: solgame.cpp:4
static LPSTR pName
Definition: security.c:75
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:6
#define CopyMemory
Definition: winbase.h:1640
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:417
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3686
static const WCHAR L[]
Definition: oid.c:1250
LIST_ENTRY Entry
Definition: precomp.h:96
PClosePrintProcessor pfnClosePrintProcessor
Definition: precomp.h:100
Definition: typedefs.h:118
static const WCHAR Cleanup[]
Definition: register.c:80
#define wcsicmp
Definition: string.h:1152
BOOL(WINAPI * PEnumPrintProcessorDatatypesW)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD)
BOOL(WINAPI * PControlPrintProcessor)(HANDLE, DWORD)
Definition: precomp.h:45
#define ERR(fmt,...)
Definition: debug.h:109
#define ERROR_UNKNOWN_PRINTPROCESSOR
Definition: winerror.h:1105
_In_ DWORD _Out_ PDWORD pcbNeeded
Definition: winddi.h:3827
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
PGetPrintProcessorCapabilities pfnGetPrintProcessorCapabilities
Definition: precomp.h:103
BOOL(WINAPI * PPrintDocumentOnPrintProcessor)(HANDLE, LPWSTR)
Definition: precomp.h:49
DWORD * PDWORD
Definition: pedump.c:68
BOOL WINAPI DllFreeSplStr(PWSTR pwszString)
Definition: memory.c:129
HANDLE(WINAPI * POpenPrintProcessor)(LPWSTR, PPRINTPROCESSOROPENDATA)
Definition: precomp.h:48
uint32_t * LPDWORD
Definition: typedefs.h:58
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
#define GetProcAddress(x, y)
Definition: compat.h:418
WCHAR wszSpoolDirectory[MAX_PATH]
Definition: main.c:15
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2527
PVOID WINAPI DllAllocSplMem(DWORD dwBytes)
Definition: memory.c:95
POpenPrintProcessor pfnOpenPrintProcessor
Definition: precomp.h:104
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
PControlPrintProcessor pfnControlPrintProcessor
Definition: precomp.h:101
WCHAR * LPWSTR
Definition: xmlstorage.h:184
BYTE * PBYTE
Definition: pedump.c:66
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
BOOL(WINAPI * PClosePrintProcessor)(HANDLE)
Definition: precomp.h:44
base of all file and directory entries
Definition: entries.h:82
#define ERROR_INVALID_ENVIRONMENT
Definition: winerror.h:1112
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10