ReactOS 0.4.15-dev-7788-g1ad9096
main.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: Main functions
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
6 */
7
8#include "precomp.h"
9
10// Global Variables
17
18// Global Constants
19#include <prtprocenv.h>
20
24
25const WCHAR wszDefaultDocumentName[] = L"Local Downlevel Document";
26
28 L"Windows NT Local Print Providor", // Name
29 L"Locally connected Printers", // Comment
30 L"Windows NT Local Printers" // Description
31};
32
33// Local Constants
35 LocalOpenPrinter, // fpOpenPrinter
36 LocalSetJob, // fpSetJob
37 LocalGetJob, // fpGetJob
38 LocalEnumJobs, // fpEnumJobs
39 NULL, // fpAddPrinter
40 NULL, // fpDeletePrinter
41 NULL, // fpSetPrinter
42 LocalGetPrinter, // fpGetPrinter
43 LocalEnumPrinters, // fpEnumPrinters
44 LocalAddPrinterDriver, // fpAddPrinterDriver
45 LocalEnumPrinterDrivers, // fpEnumPrinterDrivers
46 LocalGetPrinterDriver, // fpGetPrinterDriver
47 LocalGetPrinterDriverDirectory, // fpGetPrinterDriverDirectory
48 NULL, // fpDeletePrinterDriver
49 NULL, // fpAddPrintProcessor
50 LocalEnumPrintProcessors, // fpEnumPrintProcessors
51 LocalGetPrintProcessorDirectory, // fpGetPrintProcessorDirectory
52 NULL, // fpDeletePrintProcessor
53 LocalEnumPrintProcessorDatatypes, // fpEnumPrintProcessorDatatypes
54 LocalStartDocPrinter, // fpStartDocPrinter
55 LocalStartPagePrinter, // fpStartPagePrinter
56 LocalWritePrinter, // fpWritePrinter
57 LocalEndPagePrinter, // fpEndPagePrinter
58 NULL, // fpAbortPrinter
59 LocalReadPrinter, // fpReadPrinter
60 LocalEndDocPrinter, // fpEndDocPrinter
61 LocalAddJob, // fpAddJob
62 LocalScheduleJob, // fpScheduleJob
63 LocalGetPrinterData, // fpGetPrinterData
64 LocalSetPrinterData, // fpSetPrinterData
65 NULL, // fpWaitForPrinterChange
66 LocalClosePrinter, // fpClosePrinter
67 LocalAddForm, // fpAddForm
68 LocalDeleteForm, // fpDeleteForm
69 LocalGetForm, // fpGetForm
70 LocalSetForm, // fpSetForm
71 LocalEnumForms, // fpEnumForms
72 LocalEnumMonitors, // fpEnumMonitors
73 LocalEnumPorts, // fpEnumPorts
74 LocalAddPort, // fpAddPort
75 LocalConfigurePort, // fpConfigurePort
76 LocalDeletePort, // fpDeletePort
77 NULL, // fpCreatePrinterIC
78 NULL, // fpPlayGdiScriptOnPrinterIC
79 NULL, // fpDeletePrinterIC
80 NULL, // fpAddPrinterConnection
81 NULL, // fpDeletePrinterConnection
82 LocalPrinterMessageBox, // fpPrinterMessageBox
83 LocalAddMonitor, // fpAddMonitor
84 LocalDeleteMonitor, // fpDeleteMonitor
85 NULL, // fpResetPrinter
86 LocalGetPrinterDriverEx, // fpGetPrinterDriverEx
87 NULL, // fpFindFirstPrinterChangeNotification
88 NULL, // fpFindClosePrinterChangeNotification
89 LocalAddPortEx, // fpAddPortEx
90 NULL, // fpShutDown
91 NULL, // fpRefreshPrinterChangeNotification
92 NULL, // fpOpenPrinterEx
93 NULL, // fpAddPrinterEx
94 LocalSetPort, // fpSetPort
95 NULL, // fpEnumPrinterData
96 NULL, // fpDeletePrinterData
97 NULL, // fpClusterSplOpen
98 NULL, // fpClusterSplClose
99 NULL, // fpClusterSplIsAlive
100 LocalSetPrinterDataEx, // fpSetPrinterDataEx
101 LocalGetPrinterDataEx, // fpGetPrinterDataEx
102 NULL, // fpEnumPrinterDataEx
103 NULL, // fpEnumPrinterKey
104 NULL, // fpDeletePrinterDataEx
105 NULL, // fpDeletePrinterKey
106 NULL, // fpSeekPrinter
107 NULL, // fpDeletePrinterDriverEx
108 NULL, // fpAddPerMachineConnection
109 NULL, // fpDeletePerMachineConnection
110 NULL, // fpEnumPerMachineConnections
111 LocalXcvData, // fpXcvData
112 LocalAddPrinterDriverEx, // fpAddPrinterDriverEx
113 NULL, // fpSplReadPrinter
114 NULL, // fpDriverUnloadComplete
115 LocalGetSpoolFileInfo, // fpGetSpoolFileInfo
116 LocalCommitSpoolData, // fpCommitSpoolData
117 LocalCloseSpoolFileHandle, // fpCloseSpoolFileHandle
118 NULL, // fpFlushPrinter
119 NULL, // fpSendRecvBidiData
120 NULL, // fpAddDriverCatalog
121};
122
123static BOOL
125{
126 const WCHAR wszPrintersPath[] = L"\\PRINTERS";
127 const DWORD cchPrintersPath = _countof(wszPrintersPath) - 1;
128 const WCHAR wszSpoolPath[] = L"\\spool";
129 const DWORD cchSpoolPath = _countof(wszSpoolPath) - 1;
130 const WCHAR wszSymbolicLinkValue[] = L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers";
131 const DWORD cbSymbolicLinkValue = sizeof(wszSymbolicLinkValue) - sizeof(WCHAR);
132
133 BOOL bReturnValue = FALSE;
134 DWORD cbData;
135 DWORD dwErrorCode;
136 HKEY hKey = NULL;
137
138 // On startup, always create a volatile symbolic link in the registry if it doesn't exist yet.
139 // "SYSTEM\CurrentControlSet\Control\Print\Printers" -> "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers"
140 //
141 // According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51
142 // this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive.
143 dwErrorCode = (DWORD)RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers", 0, NULL, REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK, KEY_CREATE_LINK | KEY_SET_VALUE, NULL, &hKey, NULL);
144 if (dwErrorCode == ERROR_SUCCESS)
145 {
146 // Note that wszSymbolicLink has to be stored WITHOUT the terminating null character for the symbolic link to work!
147 // See cbSymbolicLinkValue above.
148 dwErrorCode = (DWORD)RegSetValueExW(hKey, L"SymbolicLinkValue", 0, REG_LINK, (PBYTE)wszSymbolicLinkValue, cbSymbolicLinkValue);
149 if (dwErrorCode != ERROR_SUCCESS)
150 {
151 ERR("RegSetValueExW failed for the Printers symlink with error %lu!\n", dwErrorCode);
152 goto Cleanup;
153 }
154 }
155 else if (dwErrorCode != ERROR_ALREADY_EXISTS)
156 {
157 ERR("RegCreateKeyExW failed for the Printers symlink with error %lu!\n", dwErrorCode);
158 goto Cleanup;
159 }
160
161 // Open some registry keys and leave them open. We need them multiple times throughout the Local Spooler.
162 dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print", 0, KEY_ALL_ACCESS, &hPrintKey);
163 if (dwErrorCode != ERROR_SUCCESS)
164 {
165 ERR("RegOpenKeyExW failed for \"Print\" with error %lu!\n", dwErrorCode);
166 goto Cleanup;
167 }
168
169 dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers", 0, KEY_ALL_ACCESS, &hPrintersKey);
170 if (dwErrorCode != ERROR_SUCCESS)
171 {
172 ERR("RegOpenKeyExW failed for \"Printers\" with error %lu!\n", dwErrorCode);
173 goto Cleanup;
174 }
175
176 // Construct the path to "%SystemRoot%\system32\spool".
177 // Forget about length checks here. If this doesn't fit into MAX_PATH, our OS has more serious problems...
179 CopyMemory(&wszSpoolDirectory[cchSpoolDirectory], wszSpoolPath, (cchSpoolPath + 1) * sizeof(WCHAR));
180 cchSpoolDirectory += cchSpoolPath;
181
182 // Query the job directory.
183 cbData = sizeof(wszJobDirectory);
185 if (dwErrorCode == ERROR_SUCCESS)
186 {
187 cchJobDirectory = cbData / sizeof(WCHAR) - 1;
188 }
189 else if (dwErrorCode == ERROR_FILE_NOT_FOUND)
190 {
191 // Use the default "%SystemRoot%\system32\spool\PRINTERS".
193 CopyMemory(&wszJobDirectory[cchSpoolDirectory], wszPrintersPath, (cchPrintersPath + 1) * sizeof(WCHAR));
194 cchJobDirectory = cchSpoolDirectory + cchPrintersPath;
195
196 // Save this for next time.
198 }
199 else
200 {
201 ERR("RegQueryValueExW failed for \"%S\" with error %lu!\n", SPLREG_DEFAULT_SPOOL_DIRECTORY, dwErrorCode);
202 goto Cleanup;
203 }
204
205 // Initialize all lists.
207 goto Cleanup;
208
209 if (!InitializePortList())
210 goto Cleanup;
211
213 goto Cleanup;
214
216 goto Cleanup;
217
219 goto Cleanup;
220
221 if (!InitializeFormList())
222 goto Cleanup;
223
225 goto Cleanup;
226
227 // Local Spooler Initialization finished successfully!
228 bReturnValue = TRUE;
229
230Cleanup:
231 if (hKey)
233
234 return bReturnValue;
235}
236
239{
240 switch (fdwReason)
241 {
245
246 default:
247 return TRUE;
248 }
249}
250
252InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
253{
254 TRACE("InitializePrintProvidor(%p, %lu, %S)\n", pPrintProvidor, cbPrintProvidor, pFullRegistryPath);
255
256 CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR)));
257
259 return TRUE;
260}
#define ERR(fmt,...)
Definition: debug.h:110
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
Definition: main.c:26
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3362
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4911
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4132
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define SetLastError(x)
Definition: compat.h:752
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
static const WCHAR Cleanup[]
Definition: register.c:80
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
#define REG_SZ
Definition: layer.c:22
static IN DWORD IN LPVOID lpvReserved
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define min(a, b)
Definition: monoChain.cc:55
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define REG_OPTION_CREATE_LINK
Definition: nt_native.h:1063
#define REG_LINK
Definition: nt_native.h:1500
#define DWORD
Definition: nt_native.h:44
#define KEY_CREATE_LINK
Definition: nt_native.h:1021
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define L(x)
Definition: ntvdm.h:50
BYTE * PBYTE
Definition: pedump.c:66
BOOL WINAPI LocalSetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm)
Definition: forms.c:682
BOOL WINAPI LocalAddForm(HANDLE hPrinter, DWORD Level, PBYTE pForm)
Definition: forms.c:409
BOOL InitializeFormList(VOID)
Definition: forms.c:228
BOOL WINAPI LocalEnumForms(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: forms.c:549
BOOL WINAPI LocalGetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
Definition: forms.c:624
BOOL WINAPI LocalDeleteForm(HANDLE hPrinter, PWSTR pFormName)
Definition: forms.c:499
BOOL WINAPI LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: jobs.c:655
BOOL InitializeGlobalJobList(void)
Definition: jobs.c:161
BOOL WINAPI LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID)
Definition: jobs.c:1112
BOOL WINAPI LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
Definition: jobs.c:949
BOOL WINAPI LocalAddJob(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded)
Definition: jobs.c:380
BOOL WINAPI LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
Definition: jobs.c:1022
BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: monitors.c:396
BOOL InitializePrintMonitorList(void)
Definition: monitors.c:126
BOOL WINAPI LocalDeleteMonitor(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
Definition: monitors.c:724
BOOL WINAPI LocalAddMonitor(PWSTR pName, DWORD Level, PBYTE pMonitors)
Definition: monitors.c:636
#define _countof(array)
Definition: sndvol32.h:68
#define TRACE(s)
Definition: solgame.cpp:4
const uint16_t * PCWSTR
Definition: typedefs.h:57
BOOL WINAPI InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
Definition: main.c:252
const WCHAR wszDefaultDocumentName[]
Definition: main.c:25
DWORD cchJobDirectory
Definition: main.c:14
const DWORD dwSpoolerMajorVersion
Definition: main.c:22
static const PRINTPROVIDOR _PrintProviderFunctions
Definition: main.c:34
WCHAR wszJobDirectory[MAX_PATH]
Definition: main.c:13
HKEY hPrintKey
Definition: main.c:11
HKEY hPrintersKey
Definition: main.c:12
DWORD cchSpoolDirectory
Definition: main.c:16
WCHAR wszSpoolDirectory[MAX_PATH]
Definition: main.c:15
const DWORD dwSpoolerMinorVersion
Definition: main.c:23
PCWSTR wszPrintProviderInfo[3]
Definition: main.c:27
static BOOL _InitializeLocalSpooler(void)
Definition: main.c:124
BOOL WINAPI LocalSetPort(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
Definition: ports.c:460
BOOL WINAPI LocalConfigurePort(PWSTR pName, HWND hWnd, PWSTR pPortName)
Definition: ports.c:361
BOOL WINAPI LocalAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName)
Definition: ports.c:286
BOOL InitializePortList(void)
Definition: ports.c:60
BOOL WINAPI LocalDeletePort(PWSTR pName, HWND hWnd, PWSTR pPortName)
Definition: ports.c:411
BOOL WINAPI LocalAddPortEx(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
Definition: ports.c:217
BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: ports.c:164
BOOL InitializePrintProcessorList(void)
BOOL WINAPI LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
BOOL WINAPI LocalCloseSpoolFileHandle(HANDLE hPrinter)
Definition: spoolfile.c:30
BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
Definition: printers.c:884
DWORD WINAPI LocalPrinterMessageBox(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
Definition: printers.c:1391
BOOL WINAPI LocalAddPrinterDriver(LPWSTR pName, DWORD level, LPBYTE pDriverInfo)
BOOL WINAPI LocalAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
DWORD WINAPI LocalSetPrinterDataEx(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
BOOL WINAPI LocalWritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten)
BOOL WINAPI LocalXcvData(HANDLE hXcv, const WCHAR *pszDataName, BYTE *pInputData, DWORD cbInputData, BYTE *pOutputData, DWORD cbOutputData, DWORD *pcbOutputNeeded, DWORD *pdwStatus)
Definition: xcv.c:140
BOOL InitializePrinterList(void)
Definition: printers.c:107
DWORD WINAPI LocalGetPrinterData(HANDLE hPrinter, PWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
Definition: printerdata.c:11
BOOL WINAPI LocalEndPagePrinter(HANDLE hPrinter)
Definition: printers.c:1834
DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
BOOL WINAPI LocalStartPagePrinter(HANDLE hPrinter)
Definition: printers.c:1724
DWORD WINAPI LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
Definition: printerdata.c:314
BOOL WINAPI LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded)
BOOL WINAPI LocalCommitSpoolData(HANDLE hPrinter, DWORD cbCommit)
Definition: spoolfile.c:23
BOOL WINAPI LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
Definition: printers.c:1534
BOOL InitializePrinterDrivers(VOID)
BOOL WINAPI LocalGetSpoolFileInfo(HANDLE hPrinter, LPWSTR *pSpoolDir, LPHANDLE phFile, HANDLE hSpoolerProcess, HANDLE hAppProcess)
Definition: spoolfile.c:11
BOOL WINAPI LocalClosePrinter(HANDLE hPrinter)
Definition: printers.c:1960
BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE *phPrinter, PPRINTER_DEFAULTSW pDefault)
Definition: printers.c:1398
DWORD WINAPI LocalSetPrinterData(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
Definition: printerdata.c:361
BOOL WINAPI LocalGetPrinterDriverDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded)
BOOL WINAPI LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: printers.c:985
BOOL WINAPI LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
BOOL WINAPI LocalGetPrinterDriverEx(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded, DWORD dwClientMajorVersion, DWORD dwClientMinorVersion, PDWORD pdwServerMajorVersion, PDWORD pdwServerMinorVersion)
BOOL WINAPI LocalEnumPrinterDrivers(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
BOOL WINAPI LocalEndDocPrinter(HANDLE hPrinter)
Definition: printers.c:1857
#define CopyMemory
Definition: winbase.h:1710
#define WINAPI
Definition: msvc.h:6
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define SPLREG_DEFAULT_SPOOL_DIRECTORY
Definition: winspool.h:1342
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184