2 * PROJECT: ReactOS Local Spooler API Tests Injected DLL
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Tests for fpEnumPrinters
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
10 #define WIN32_NO_STATUS
18 #include "../localspl_apitest.h"
21 extern BOOL
GetLocalsplFuncs(LPPRINTPROVIDOR pp
);
23 START_TEST(fpEnumPrinters
)
32 PPRINTER_INFO_1W pPrinterInfo1
;
35 if (!GetLocalsplFuncs(&pp
))
38 // Verify that fpEnumPrinters returns success and zeros cbNeeded and dwReturned (but not TempBuffer!) if no flag has been specified.
39 memset(TempBuffer
, 0xDE, sizeof(TempBuffer
));
40 memset(ZeroBuffer
, 0, sizeof(ZeroBuffer
));
41 cbNeeded
= 0xDEADBEEF;
42 dwReturned
= 0xDEADBEEF;
43 SetLastError(0xDEADBEEF);
44 ok(pp
.fpEnumPrinters(0, NULL
, 1, TempBuffer
, sizeof(TempBuffer
), &cbNeeded
, &dwReturned
), "fpEnumPrinters returns FALSE\n");
45 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu!\n", GetLastError());
46 ok(memcmp(TempBuffer
, ZeroBuffer
, sizeof(TempBuffer
)) != 0, "TempBuffer has been zeroed!\n");
47 ok(cbNeeded
== 0, "cbNeeded is %lu!\n", cbNeeded
);
48 ok(dwReturned
== 0, "dwReturned is %lu!\n", dwReturned
);
50 // Verify that localspl only returns information about a single print provider (namely itself).
51 cbNeeded
= 0xDEADBEEF;
52 dwReturned
= 0xDEADBEEF;
53 SetLastError(0xDEADBEEF);
54 ok(!pp
.fpEnumPrinters(PRINTER_ENUM_NAME
, NULL
, 1, NULL
, 0, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns TRUE\n");
55 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "fpEnumPrinters returns error %lu!\n", GetLastError());
56 ok(cbNeeded
> 0, "cbNeeded is 0!\n");
57 ok(dwReturned
== 0, "dwReturned is %lu!\n", dwReturned
);
59 SetLastError(0xDEADBEEF);
60 pPrinterInfo1
= HeapAlloc(GetProcessHeap(), 0, cbNeeded
);
61 ok(pp
.fpEnumPrinters(PRINTER_ENUM_NAME
, NULL
, 1, (PBYTE
)pPrinterInfo1
, cbNeeded
, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns FALSE\n");
62 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu!\n", GetLastError());
63 ok(cbNeeded
> 0, "cbNeeded is 0!\n");
64 ok(dwReturned
== 1, "dwReturned is %lu!\n", dwReturned
);
66 // Verify the actual strings returned.
67 ok(wcscmp(pPrinterInfo1
->pName
, L
"Windows NT Local Print Providor") == 0, "pPrinterInfo1->pName is \"%S\"!\n", pPrinterInfo1
->pName
);
68 ok(wcscmp(pPrinterInfo1
->pDescription
, L
"Windows NT Local Printers") == 0, "pPrinterInfo1->pDescription is \"%S\"!\n", pPrinterInfo1
->pDescription
);
69 ok(wcscmp(pPrinterInfo1
->pComment
, L
"Locally connected Printers") == 0, "pPrinterInfo1->pComment is \"%S\"!\n", pPrinterInfo1
->pComment
);
71 // Level 7 is the highest supported for localspl under Windows Server 2003.
72 // Higher levels need to fail, but they don't set an error code, just cbNeeded to 0.
73 cbNeeded
= 0xDEADBEEF;
74 dwReturned
= 0xDEADBEEF;
75 SetLastError(0xDEADBEEF);
76 ok(!pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, 8, NULL
, 0, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns TRUE!\n");
77 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu!\n", GetLastError());
78 ok(cbNeeded
== 0, "cbNeeded is %lu!\n", cbNeeded
);
79 ok(dwReturned
== 0, "dwReturned is %lu!\n", dwReturned
);
81 // Verify that all valid levels work.
82 // In contrast to EnumPrintersW, which only accepts levels 0, 1, 2, 4 and 5, localspl returns information for level 0 to 7.
83 for (i
= 0; i
<= 7; i
++)
85 // Try with no valid arguments at all.
86 // This scenario is usually caugt by RPC, so it just raises an exception here.
90 pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, i
, NULL
, 0, NULL
, NULL
);
92 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
94 dwReturned
= _SEH2_GetExceptionCode();
98 ok(dwReturned
== EXCEPTION_ACCESS_VIOLATION
, "dwReturned is %lu for Level %lu!\n", dwReturned
, i
);
100 // Now get the required buffer size.
101 cbNeeded
= 0xDEADBEEF;
102 dwReturned
= 0xDEADBEEF;
103 SetLastError(0xDEADBEEF);
104 ok(!pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, i
, NULL
, 0, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns TRUE for Level %lu!\n", i
);
105 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i
);
106 ok(cbNeeded
> 0, "cbNeeded is 0 for Level %lu!\n", i
);
107 ok(dwReturned
== 0, "dwReturned is %lu for Level %lu!\n", dwReturned
, i
);
109 // This test corrupts something inside spoolsv so that it's only runnable once without restarting spoolsv. Therefore it's disabled.
111 // Now provide the demanded size, but no buffer. This also mustn't touch cbNeeded.
112 // This scenario is also caught by RPC and we just have an exception here.
116 pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, i
, NULL
, cbNeeded
, &cbTemp
, &dwReturned
);
118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
120 dwReturned
= _SEH2_GetExceptionCode();
124 ok(dwReturned
== EXCEPTION_ACCESS_VIOLATION
, "dwReturned is %lu for Level %lu!\n", dwReturned
, i
);
125 ok(cbNeeded
== cbTemp
, "cbNeeded is %lu, cbTemp is %lu for Level %lu!\n", cbNeeded
, cbTemp
, i
);
128 // Finally use the function as intended and aim for success!
129 pMem
= DllAllocSplMem(cbNeeded
);
130 SetLastError(0xDEADBEEF);
131 ok(pp
.fpEnumPrinters(PRINTER_ENUM_LOCAL
, NULL
, i
, pMem
, cbNeeded
, &cbTemp
, &dwReturned
), "fpEnumPrinters returns FALSE for Level %lu!\n", i
);
133 // This is crazy. For level 3, fpEnumPrinters always returns ERROR_INSUFFICIENT_BUFFER even if we supply a buffer large enough.
135 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i
);
137 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i
);
142 // fpEnumPrinters has to succeed independent of the level (valid or not) if we query no information.
143 for (i
= 0; i
< 10; i
++)
145 SetLastError(0xDEADBEEF);
146 ok(pp
.fpEnumPrinters(0, NULL
, i
, NULL
, 0, &cbNeeded
, &dwReturned
), "fpEnumPrinters returns FALSE for Level %lu!\n", i
);
147 ok(GetLastError() == ERROR_SUCCESS
, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i
);
148 ok(cbNeeded
== 0, "cbNeeded is %lu for Level %lu!\n", cbNeeded
, i
);
149 ok(dwReturned
== 0, "dwReturned is %lu for Level %lu!\n", dwReturned
, i
);