1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Print Spooler DLL API Tests
3c2c66affSColin Finck * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4c2c66affSColin Finck * PURPOSE: Tests for GetPrinterData(Ex)A/GetPrinterData(Ex)W/SetPrinterData(Ex)A/SetPrinterData(Ex)W
5c2c66affSColin Finck * COPYRIGHT: Copyright 2017 Colin Finck (colin@reactos.org)
6c2c66affSColin Finck */
7c2c66affSColin Finck
8c2c66affSColin Finck #include <apitest.h>
9c2c66affSColin Finck
10c2c66affSColin Finck #define WIN32_NO_STATUS
11c2c66affSColin Finck #include <windef.h>
12c2c66affSColin Finck #include <winbase.h>
13c2c66affSColin Finck #include <wingdi.h>
14c2c66affSColin Finck #include <winspool.h>
15c2c66affSColin Finck #include <winreg.h>
16c2c66affSColin Finck
17c2c66affSColin Finck /* From printing/include/spoolss.h */
18c2c66affSColin Finck #define MAX_PRINTER_NAME 220
19c2c66affSColin Finck
20c2c66affSColin Finck typedef struct _SPLREG_VALUE
21c2c66affSColin Finck {
22c2c66affSColin Finck PSTR pszName;
23c2c66affSColin Finck PWSTR pwszName;
24c2c66affSColin Finck DWORD dwType;
25c2c66affSColin Finck DWORD cbNeededA;
26c2c66affSColin Finck BOOL bSettable;
27c2c66affSColin Finck }
28c2c66affSColin Finck SPLREG_VALUE, *PSPLREG_VALUE;
29c2c66affSColin Finck
30c2c66affSColin Finck SPLREG_VALUE SplRegValues[] = {
31c2c66affSColin Finck { "DefaultSpoolDirectory", L"DefaultSpoolDirectory", REG_SZ, 0xFFFFFFFF, TRUE },
32c2c66affSColin Finck { "PortThreadPriorityDefault", L"PortThreadPriorityDefault", REG_NONE, 4, FALSE },
33c2c66affSColin Finck { "PortThreadPriority", L"PortThreadPriority", REG_DWORD, 4, TRUE },
34c2c66affSColin Finck { "SchedulerThreadPriorityDefault", L"SchedulerThreadPriorityDefault", REG_NONE, 4, FALSE },
35c2c66affSColin Finck { "SchedulerThreadPriority", L"SchedulerThreadPriority", REG_DWORD, 4, TRUE },
36c2c66affSColin Finck { "BeepEnabled", L"BeepEnabled", REG_DWORD, 4, TRUE },
37c2c66affSColin Finck
38c2c66affSColin Finck /* These fail in Win8, probably removed since NT6:
39c2c66affSColin Finck
40c2c66affSColin Finck { "NetPopup", L"NetPopup", REG_DWORD, 4, TRUE },
41c2c66affSColin Finck { "RetryPopup", L"RetryPopup", REG_DWORD, 4, TRUE },
42c2c66affSColin Finck { "NetPopupToComputer", L"NetPopupToComputer", REG_DWORD, 4, TRUE },
43c2c66affSColin Finck
44c2c66affSColin Finck */
45c2c66affSColin Finck
46c2c66affSColin Finck { "EventLog", L"EventLog", REG_DWORD, 4, TRUE },
47c2c66affSColin Finck { "MajorVersion", L"MajorVersion", REG_NONE, 4, FALSE },
48c2c66affSColin Finck { "MinorVersion", L"MinorVersion", REG_NONE, 4, FALSE },
49c2c66affSColin Finck { "Architecture", L"Architecture", REG_NONE, 0xFFFFFFFF, FALSE },
50c2c66affSColin Finck { "OSVersion", L"OSVersion", REG_NONE, sizeof(OSVERSIONINFOA), FALSE },
51c2c66affSColin Finck { "OSVersionEx", L"OSVersionEx", REG_NONE, sizeof(OSVERSIONINFOEXA), FALSE },
52c2c66affSColin Finck #if 0
53c2c66affSColin Finck { "DsPresent", L"DsPresent", REG_DWORD, 4, FALSE },
54c2c66affSColin Finck { "DsPresentForUser", L"DsPresentForUser", REG_DWORD, 4, FALSE },
55c2c66affSColin Finck #endif
56c2c66affSColin Finck { "RemoteFax", L"RemoteFax", REG_NONE, 4, FALSE },
57c2c66affSColin Finck { "RestartJobOnPoolError", L"RestartJobOnPoolError", REG_DWORD, 4, TRUE },
58c2c66affSColin Finck { "RestartJobOnPoolEnabled", L"RestartJobOnPoolEnabled", REG_DWORD, 4, TRUE },
59*465745b6STimo Kreuzer #if 0 // FIXME: fails on WHS testbot with ERROR_INVALID_PARAMETER
60c2c66affSColin Finck { "DNSMachineName", L"DNSMachineName", REG_SZ, 0xFFFFFFFF, FALSE },
61*465745b6STimo Kreuzer #endif
62c2c66affSColin Finck { "AllowUserManageForms", L"AllowUserManageForms", REG_DWORD, 4, TRUE },
63c2c66affSColin Finck { NULL, NULL, 0, 0, FALSE }
64c2c66affSColin Finck };
65c2c66affSColin Finck
START_TEST(GetPrinterData)66c2c66affSColin Finck START_TEST(GetPrinterData)
67c2c66affSColin Finck {
68c2c66affSColin Finck DWORD cbNeeded;
69c2c66affSColin Finck DWORD cchDefaultPrinter;
70c2c66affSColin Finck DWORD dwReturnCode;
71c2c66affSColin Finck DWORD dwType;
72c2c66affSColin Finck HANDLE hPrinter;
73c2c66affSColin Finck PBYTE pDataA;
74c2c66affSColin Finck PBYTE pDataW;
75c2c66affSColin Finck PSPLREG_VALUE p;
76c2c66affSColin Finck WCHAR wszDefaultPrinter[MAX_PRINTER_NAME + 1];
77c2c66affSColin Finck
78c2c66affSColin Finck // Don't supply any parameters, this has to fail with ERROR_INVALID_HANDLE!
79c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(NULL, NULL, NULL, NULL, NULL, 0, NULL);
80c2c66affSColin Finck ok(dwReturnCode == ERROR_INVALID_HANDLE, "GetPrinterDataExW returns error %lu!\n", dwReturnCode);
81c2c66affSColin Finck
82c2c66affSColin Finck // Open a handle to the local print server.
83c2c66affSColin Finck if (!OpenPrinterW(NULL, &hPrinter, NULL))
84c2c66affSColin Finck {
85c2c66affSColin Finck skip("Could not retrieve a handle to the local print server!\n");
86c2c66affSColin Finck return;
87c2c66affSColin Finck }
88c2c66affSColin Finck
89c2c66affSColin Finck // Now try with valid handle, but leave remaining parameters NULL.
90c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(hPrinter, NULL, NULL, NULL, NULL, 0, NULL);
91c2c66affSColin Finck ok(dwReturnCode == RPC_X_NULL_REF_POINTER, "GetPrinterDataExW returns error %lu!\n", dwReturnCode);
92c2c66affSColin Finck
93c2c66affSColin Finck // Try all valid Print Server data values.
94c2c66affSColin Finck for (p = SplRegValues; p->pszName; p++)
95c2c66affSColin Finck {
96c2c66affSColin Finck // Try the ANSI version of the function.
97c2c66affSColin Finck dwType = 0xDEADBEEF;
98c2c66affSColin Finck dwReturnCode = GetPrinterDataExA(hPrinter, NULL, p->pszName, &dwType, NULL, 0, &cbNeeded);
99c2c66affSColin Finck ok(dwReturnCode == ERROR_MORE_DATA || dwReturnCode == ERROR_FILE_NOT_FOUND, "GetPrinterDataExA returns %lu for \"%s\"!\n", dwReturnCode, p->pszName);
100c2c66affSColin Finck if (dwReturnCode != ERROR_MORE_DATA)
101c2c66affSColin Finck continue;
102c2c66affSColin Finck
103c2c66affSColin Finck ok(dwType == p->dwType, "dwType is %lu for \"%s\"!\n", dwType, p->pszName);
104c2c66affSColin Finck
105c2c66affSColin Finck if (p->cbNeededA < 0xFFFFFFFF)
106c2c66affSColin Finck ok(cbNeeded == p->cbNeededA, "cbNeeded is %lu for \"%s\", but expected %lu!\n", cbNeeded, p->pszName, p->cbNeededA);
107c2c66affSColin Finck else
108c2c66affSColin Finck ok(cbNeeded > 0, "cbNeeded is 0 for \"%s\"!\n", p->pszName);
109c2c66affSColin Finck
110c2c66affSColin Finck pDataA = HeapAlloc(GetProcessHeap(), 0, cbNeeded);
111c2c66affSColin Finck dwReturnCode = GetPrinterDataExA(hPrinter, NULL, p->pszName, NULL, pDataA, cbNeeded, &cbNeeded);
112c2c66affSColin Finck ok(dwReturnCode == ERROR_SUCCESS, "GetPrinterDataExA returns %lu for \"%s\"!\n", dwReturnCode, p->pszName);
113c2c66affSColin Finck
114c2c66affSColin Finck // Try the Unicode version of the function too.
115c2c66affSColin Finck dwType = 0xDEADBEEF;
116c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(hPrinter, NULL, p->pwszName, &dwType, NULL, 0, &cbNeeded);
117c2c66affSColin Finck ok(dwReturnCode == ERROR_MORE_DATA, "GetPrinterDataExW returns %lu for \"%s\"!\n", dwReturnCode, p->pszName);
118c2c66affSColin Finck ok(dwType == p->dwType, "dwType is %lu for \"%s\"!\n", dwType, p->pszName);
119c2c66affSColin Finck
120c2c66affSColin Finck pDataW = HeapAlloc(GetProcessHeap(), 0, cbNeeded);
121c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(hPrinter, NULL, p->pwszName, NULL, pDataW, cbNeeded, &cbNeeded);
122c2c66affSColin Finck ok(dwReturnCode == ERROR_SUCCESS, "GetPrinterDataExW returns %lu for \"%s\"!\n", dwReturnCode, p->pszName);
123c2c66affSColin Finck
124c2c66affSColin Finck // Verify that OSVERSIONINFO structures are correctly returned.
125c2c66affSColin Finck if (strcmp(p->pszName, "OSVersion") == 0)
126c2c66affSColin Finck {
127c2c66affSColin Finck POSVERSIONINFOA pOSVersionInfoA = (POSVERSIONINFOA)pDataA;
128c2c66affSColin Finck POSVERSIONINFOW pOSVersionInfoW = (POSVERSIONINFOW)pDataW;
129c2c66affSColin Finck ok(pOSVersionInfoA->dwOSVersionInfoSize == sizeof(OSVERSIONINFOA), "dwOSVersionInfoSize is %lu!\n", pOSVersionInfoA->dwOSVersionInfoSize);
130c2c66affSColin Finck ok(pOSVersionInfoW->dwOSVersionInfoSize == sizeof(OSVERSIONINFOW), "dwOSVersionInfoSize is %lu!\n", pOSVersionInfoW->dwOSVersionInfoSize);
131c2c66affSColin Finck }
132c2c66affSColin Finck else if (strcmp(p->pszName, "OSVersionEx") == 0)
133c2c66affSColin Finck {
134c2c66affSColin Finck POSVERSIONINFOEXA pOSVersionInfoA = (POSVERSIONINFOEXA)pDataA;
135c2c66affSColin Finck POSVERSIONINFOEXW pOSVersionInfoW = (POSVERSIONINFOEXW)pDataW;
136c2c66affSColin Finck ok(pOSVersionInfoA->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA), "dwOSVersionInfoSize is %lu!\n", pOSVersionInfoA->dwOSVersionInfoSize);
137c2c66affSColin Finck ok(pOSVersionInfoW->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW), "dwOSVersionInfoSize is %lu!\n", pOSVersionInfoW->dwOSVersionInfoSize);
138c2c66affSColin Finck }
139c2c66affSColin Finck
140c2c66affSColin Finck // Shortly test SetPrinterDataExW by setting the same data we just retrieved.
141c2c66affSColin Finck if (p->bSettable)
142c2c66affSColin Finck {
143c2c66affSColin Finck dwReturnCode = SetPrinterDataExW(hPrinter, NULL, p->pwszName, dwType, pDataW, cbNeeded);
144c2c66affSColin Finck ok(dwReturnCode == ERROR_SUCCESS, "SetPrinterDataExW returns %lu for \"%s\"!\n", dwReturnCode, p->pszName);
145c2c66affSColin Finck }
146c2c66affSColin Finck
147c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, pDataA);
148c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, pDataW);
149c2c66affSColin Finck }
150c2c66affSColin Finck
151c2c66affSColin Finck // Try an invalid one.
152c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(hPrinter, NULL, L"Invalid", NULL, NULL, 0, &cbNeeded);
153c2c66affSColin Finck ok(dwReturnCode == ERROR_INVALID_PARAMETER, "GetPrinterDataExW returns %lu!\n", dwReturnCode);
154c2c66affSColin Finck
155c2c66affSColin Finck ClosePrinter(hPrinter);
156c2c66affSColin Finck
157c2c66affSColin Finck // Open a handle to the default printer.
158c2c66affSColin Finck cchDefaultPrinter = _countof(wszDefaultPrinter);
159c2c66affSColin Finck ok(GetDefaultPrinterW(wszDefaultPrinter, &cchDefaultPrinter), "GetDefaultPrinterW returns FALSE and requires %lu characters!\n", cchDefaultPrinter);
160c2c66affSColin Finck if (!OpenPrinterW(wszDefaultPrinter, &hPrinter, NULL))
161c2c66affSColin Finck {
162c2c66affSColin Finck skip("Could not retrieve a handle to the default printer!\n");
163c2c66affSColin Finck return;
164c2c66affSColin Finck }
165c2c66affSColin Finck
166c2c66affSColin Finck // Using NULL or L"" for pKeyName on a Printer handle yields ERROR_INVALID_PARAMETER.
167c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(hPrinter, NULL, L"Name", NULL, NULL, 0, &cbNeeded);
168c2c66affSColin Finck ok(dwReturnCode == ERROR_INVALID_PARAMETER, "GetPrinterDataExW returns %lu!\n", dwReturnCode);
169c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(hPrinter, L"", L"Name", NULL, NULL, 0, &cbNeeded);
170c2c66affSColin Finck ok(dwReturnCode == ERROR_INVALID_PARAMETER, "GetPrinterDataExW returns %lu!\n", dwReturnCode);
171c2c66affSColin Finck
172c2c66affSColin Finck // Using L"\\" allows us to examine the contents of the main printer key anyway.
173c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(hPrinter, L"\\", L"Name", &dwType, NULL, 0, &cbNeeded);
174c2c66affSColin Finck ok(dwReturnCode == ERROR_MORE_DATA, "GetPrinterDataExW returns %lu!\n", dwReturnCode);
175c2c66affSColin Finck ok(dwType == REG_SZ, "dwType is %lu!\n", dwType);
176c2c66affSColin Finck ok(cbNeeded > 0, "cbNeeded is 0!\n");
177c2c66affSColin Finck
178c2c66affSColin Finck pDataW = HeapAlloc(GetProcessHeap(), 0, cbNeeded);
179c2c66affSColin Finck dwReturnCode = GetPrinterDataExW(hPrinter, L"\\", L"Name", NULL, pDataW, cbNeeded, &cbNeeded);
180c2c66affSColin Finck ok(dwReturnCode == ERROR_SUCCESS, "GetPrinterDataExW returns %lu!\n", dwReturnCode);
181c2c66affSColin Finck
182c2c66affSColin Finck // The following test fails if the default printer is a remote printer.
183c2c66affSColin Finck ok(wcscmp((PWSTR)pDataW, wszDefaultPrinter) == 0, "pDataW is \"%S\", default printer is \"%S\"!\n", (PWSTR)pDataW, wszDefaultPrinter);
184c2c66affSColin Finck
185c2c66affSColin Finck // SetPrinterDataExW should return ERROR_ACCESS_DENIED when attempting to set the Name.
186c2c66affSColin Finck dwReturnCode = SetPrinterDataExW(hPrinter, L"\\", L"Name", REG_SZ, pDataW, cbNeeded);
187c2c66affSColin Finck ok(dwReturnCode == ERROR_ACCESS_DENIED, "SetPrinterDataExW returns %lu!\n", dwReturnCode);
188c2c66affSColin Finck
189c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, pDataW);
190c2c66affSColin Finck }
191