ReactOS  0.4.14-dev-831-gef8c9239
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 
25 const 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  NULL, // fpAddPrinterDriver
45  NULL, // fpEnumPrinterDrivers
46  LocalGetPrinterDriver, // fpGetPrinterDriver
47  NULL, // 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  NULL, // fpAddForm
68  NULL, // fpDeleteForm
69  NULL, // fpGetForm
70  NULL, // fpSetForm
71  NULL, // fpEnumForms
72  LocalEnumMonitors, // fpEnumMonitors
73  LocalEnumPorts, // fpEnumPorts
74  NULL, // fpAddPort
75  NULL, // fpConfigurePort
76  NULL, // fpDeletePort
77  NULL, // fpCreatePrinterIC
78  NULL, // fpPlayGdiScriptOnPrinterIC
79  NULL, // fpDeletePrinterIC
80  NULL, // fpAddPrinterConnection
81  NULL, // fpDeletePrinterConnection
82  NULL, // fpPrinterMessageBox
83  NULL, // fpAddMonitor
84  NULL, // fpDeleteMonitor
85  NULL, // fpResetPrinter
86  NULL, // fpGetPrinterDriverEx
87  NULL, // fpFindFirstPrinterChangeNotification
88  NULL, // fpFindClosePrinterChangeNotification
89  NULL, // fpAddPortEx
90  NULL, // fpShutDown
91  NULL, // fpRefreshPrinterChangeNotification
92  NULL, // fpOpenPrinterEx
93  NULL, // fpAddPrinterEx
94  NULL, // 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  NULL, // fpXcvData
112  NULL, // fpAddPrinterDriverEx
113  NULL, // fpSplReadPrinter
114  NULL, // fpDriverUnloadComplete
115  NULL, // fpGetSpoolFileInfo
116  NULL, // fpCommitSpoolData
117  NULL, // fpCloseSpoolFileHandle
118  NULL, // fpFlushPrinter
119  NULL, // fpSendRecvBidiData
120  NULL, // fpAddDriverCatalog
121 };
122 
123 static 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 
215  if (!InitializePrinterList())
216  goto Cleanup;
217 
219  goto Cleanup;
220 
221  // Local Spooler Initialization finished successfully!
222  bReturnValue = TRUE;
223 
224 Cleanup:
225  if (hKey)
226  RegCloseKey(hKey);
227 
228  return bReturnValue;
229 }
230 
231 BOOL WINAPI
232 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
233 {
234  switch (fdwReason)
235  {
236  case DLL_PROCESS_ATTACH:
237  DisableThreadLibraryCalls(hinstDLL);
238  return _InitializeLocalSpooler();
239 
240  default:
241  return TRUE;
242  }
243 }
244 
245 BOOL WINAPI
246 InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
247 {
248  TRACE("InitializePrintProvidor(%p, %lu, %S)\n", pPrintProvidor, cbPrintProvidor, pFullRegistryPath);
249 
250  CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR)));
251 
253  return TRUE;
254 }
BOOL WINAPI LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
Definition: jobs.c:1022
DWORD WINAPI LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
Definition: printerdata.c:314
const uint16_t * PCWSTR
Definition: typedefs.h:55
PCWSTR wszPrintProviderInfo[3]
Definition: main.c:27
#define TRUE
Definition: types.h:120
static const PRINTPROVIDOR _PrintProviderFunctions
Definition: main.c:34
BOOL InitializePrintMonitorList(void)
Definition: monitors.c:50
BOOL InitializeGlobalJobList(void)
Definition: jobs.c:161
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL WINAPI InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
Definition: main.c:246
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define _countof(array)
Definition: fontsub.cpp:30
BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
Definition: printers.c:865
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
HKEY hPrintKey
Definition: main.c:11
#define DLL_PROCESS_ATTACH
Definition: compat.h:120
HKEY hPrintersKey
Definition: main.c:12
DWORD WINAPI LocalSetPrinterDataEx(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
const DWORD dwSpoolerMinorVersion
Definition: main.c:23
#define DWORD
Definition: nt_native.h:44
#define REG_OPTION_CREATE_LINK
Definition: nt_native.h:1063
BOOL InitializePrinterList(void)
Definition: printers.c:107
static IN DWORD IN LPVOID lpvReserved
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:1091
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
#define SPLREG_DEFAULT_SPOOL_DIRECTORY
Definition: winspool.h:1249
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
Definition: printers.c:1499
BOOL WINAPI LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID)
Definition: jobs.c:1112
smooth NULL
Definition: ftsmooth.c:416
DWORD cchSpoolDirectory
Definition: main.c:16
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
BOOL WINAPI LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: jobs.c:655
static BOOL _InitializeLocalSpooler(void)
Definition: main.c:124
BOOL WINAPI LocalAddJob(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded)
Definition: jobs.c:380
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:4895
BOOL WINAPI LocalWritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten)
DWORD WINAPI LocalSetPrinterData(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
Definition: printerdata.c:361
BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: monitors.c:311
#define REG_LINK
Definition: nt_native.h:1500
#define TRACE(s)
Definition: solgame.cpp:4
BOOL WINAPI LocalStartPagePrinter(HANDLE hPrinter)
Definition: printers.c:1689
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
const DWORD dwSpoolerMajorVersion
Definition: main.c:22
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:6
#define CopyMemory
Definition: winbase.h:1640
DWORD cchJobDirectory
Definition: main.c:14
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL WINAPI LocalEndPagePrinter(HANDLE hPrinter)
Definition: printers.c:1799
BOOL WINAPI LocalEndDocPrinter(HANDLE hPrinter)
Definition: printers.c:1822
#define SetLastError(x)
Definition: compat.h:417
BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
BOOL WINAPI LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
static const WCHAR L[]
Definition: oid.c:1250
BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE *phPrinter, PPRINTER_DEFAULTSW pDefault)
Definition: printers.c:1364
BOOL InitializePrintProcessorList(void)
DWORD WINAPI LocalGetPrinterData(HANDLE hPrinter, PWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
Definition: printerdata.c:11
static const WCHAR Cleanup[]
Definition: register.c:80
#define ERR(fmt,...)
Definition: debug.h:109
BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: ports.c:141
BOOL WINAPI LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define KEY_CREATE_LINK
Definition: nt_native.h:1021
WCHAR wszJobDirectory[MAX_PATH]
Definition: main.c:13
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2312
BOOL WINAPI LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded)
#define min(a, b)
Definition: monoChain.cc:55
BOOL WINAPI LocalClosePrinter(HANDLE hPrinter)
Definition: printers.c:1923
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
WCHAR wszSpoolDirectory[MAX_PATH]
Definition: main.c:15
BOOL WINAPI LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: printers.c:966
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
BOOL WINAPI LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
Definition: jobs.c:949
WCHAR * LPWSTR
Definition: xmlstorage.h:184
BOOL InitializePortList(void)
Definition: ports.c:37
BYTE * PBYTE
Definition: pedump.c:66
const WCHAR wszDefaultDocumentName[]
Definition: main.c:25
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
Definition: main.c:26
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define REG_SZ
Definition: layer.c:22