2 * PROJECT: ReactOS Local Spooler API Tests Injected DLL
3 * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
4 * PURPOSE: Tests for fpEnumPrinters
5 * COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
10 #define WIN32_NO_STATUS
18 #include "../localspl_apitest.h"
21 START_TEST(fpEnumPrinters
)
28 PInitializePrintProvidor pfnInitializePrintProvidor
;
30 PPRINTER_INFO_1W pPrinterInfo1
;
33 // Get us a handle to the loaded localspl.dll.
34 hLocalspl
= GetModuleHandleW(L
"localspl");
37 skip("GetModuleHandleW failed with error %lu!\n", GetLastError());
41 // Get a pointer to its InitializePrintProvidor function.
42 pfnInitializePrintProvidor
= (PInitializePrintProvidor
)GetProcAddress(hLocalspl
, "InitializePrintProvidor");
43 if (!pfnInitializePrintProvidor
)
45 skip("GetProcAddress failed with error %lu!\n", GetLastError());
49 // Get localspl's function pointers.
50 if (!pfnInitializePrintProvidor(&pp
, sizeof(pp
), NULL
))
52 skip("pfnInitializePrintProvidor failed with error %lu!\n", GetLastError());
56 // Verify that localspl only returns information about a single print provider (namely itself).
57 cbNeeded
= 0xDEADBEEF;
58 dwReturned
= 0xDEADBEEF;
59 SetLastError(0xDEADBEEF);
60 ok(!pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
| PRINTER_ENUM_NAME
, NULL
, 1, NULL
, 0, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns TRUE\n");
61 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "fpEnumPrinters returns error %lu!\n", GetLastError());
62 ok(cbNeeded
> 0, "cbNeeded is 0!\n");
63 ok(dwReturned
== 0, "dwReturned is %lu!\n", dwReturned
);
65 SetLastError(0xDEADBEEF);
66 pPrinterInfo1
= HeapAlloc(GetProcessHeap(), 0, cbNeeded
);
67 ok(pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
| PRINTER_ENUM_NAME
, NULL
, 1, (PBYTE
)pPrinterInfo1
, cbNeeded
, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns FALSE\n");
68 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu!\n", GetLastError());
69 ok(cbNeeded
> 0, "cbNeeded is 0!\n");
70 ok(dwReturned
== 1, "dwReturned is %lu!\n", dwReturned
);
72 // Verify the actual strings returned.
73 ok(wcscmp(pPrinterInfo1
->pName
, L
"Windows NT Local Print Providor") == 0, "pPrinterInfo1->pName is \"%S\"!\n", pPrinterInfo1
->pName
);
74 ok(wcscmp(pPrinterInfo1
->pDescription
, L
"Windows NT Local Printers") == 0, "pPrinterInfo1->pDescription is \"%S\"!\n", pPrinterInfo1
->pDescription
);
75 ok(wcscmp(pPrinterInfo1
->pComment
, L
"Locally connected Printers") == 0, "pPrinterInfo1->pComment is \"%S\"!\n", pPrinterInfo1
->pComment
);
77 // Level 7 is the highest supported for localspl under Windows Server 2003.
78 // Higher levels need to fail, but they don't set an error code, just cbNeeded to 0.
79 cbNeeded
= 0xDEADBEEF;
80 dwReturned
= 0xDEADBEEF;
81 SetLastError(0xDEADBEEF);
82 ok(!pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, 8, NULL
, 0, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns TRUE!\n");
83 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu!\n", GetLastError());
84 ok(cbNeeded
== 0, "cbNeeded is %lu!\n", cbNeeded
);
85 ok(dwReturned
== 0, "dwReturned is %lu!\n", dwReturned
);
87 // Verify that all valid levels work.
88 // In contrast to EnumPrintersW, which only accepts levels 0, 1, 2, 4 and 5, localspl returns information for level 0 to 7.
89 for (i
= 0; i
<= 7; i
++)
91 // FIXME: For some reason, using SEH here works only once.
92 // We experience a hang in the testing process when you run the test again for a second time without restarting spoolsv.
94 // Try with no valid arguments at all.
95 // This scenario is usually caugt by RPC, so it just raises an exception here.
99 pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, i
, NULL
, 0, NULL
, NULL
);
101 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
103 dwReturned
= _SEH2_GetExceptionCode();
107 ok(dwReturned
== EXCEPTION_ACCESS_VIOLATION
, "dwReturned is %lu for Level %lu!\n", dwReturned
, i
);
110 // Now get the required buffer size.
111 cbNeeded
= 0xDEADBEEF;
112 dwReturned
= 0xDEADBEEF;
113 SetLastError(0xDEADBEEF);
114 ok(!pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, i
, NULL
, 0, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns TRUE for Level %lu!\n", i
);
115 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i
);
116 ok(cbNeeded
> 0, "cbNeeded is 0 for Level %lu!\n", i
);
117 ok(dwReturned
== 0, "dwReturned is %lu for Level %lu!\n", dwReturned
, i
);
120 // Now provide the demanded size, but no buffer. This also mustn't touch cbNeeded.
121 // This scenario is also caught by RPC and we just have an exception here.
125 pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, i
, NULL
, cbNeeded
, &cbTemp
, &dwReturned
);
127 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
129 dwReturned
= _SEH2_GetExceptionCode();
133 ok(dwReturned
== EXCEPTION_ACCESS_VIOLATION
, "dwReturned is %lu for Level %lu!\n", dwReturned
, i
);
134 ok(cbNeeded
== cbTemp
, "cbNeeded is %lu, cbTemp is %lu for Level %lu!\n", cbNeeded
, cbTemp
, i
);
137 // Finally use the function as intended and aim for success!
138 pMem
= DllAllocSplMem(cbNeeded
);
139 SetLastError(0xDEADBEEF);
140 ok(pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, i
, pMem
, cbNeeded
, &cbTemp
, &dwReturned
), "fpEnumPrinters returns FALSE for Level %lu!\n", i
);
142 // This is crazy. For level 3, fpEnumPrinters always returns ERROR_INSUFFICIENT_BUFFER even if we supply a buffer large enough.
144 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i
);
146 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i
);
151 // fpEnumPrinters has to succeed independent of the level (valid or not) if we query no information.
152 for (i
= 0; i
< 10; i
++)
154 SetLastError(0xDEADBEEF);
155 ok(pp
.fpEnumPrinters(0, NULL
, i
, NULL
, 0, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns FALSE for Level %lu!\n", i
);
156 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i
);
157 ok(cbNeeded
== 0, "cbNeeded is %lu for Level %lu!\n", cbNeeded
, i
);
158 ok(dwReturned
== 0, "dwReturned is %lu for Level %lu!\n", dwReturned
, i
);