[STORAHCI] Merge Storport Miniport driver by Aman Priyadarshi in GSoC.
[reactos.git] / rostests / apitests / localspl / dll / fpEnumPrinters.c
1 /*
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>
6 */
7
8 #include <apitest.h>
9
10 #define WIN32_NO_STATUS
11 #include <windef.h>
12 #include <winbase.h>
13 #include <wingdi.h>
14 #include <winreg.h>
15 #include <winspool.h>
16 #include <winsplp.h>
17
18 #include "../localspl_apitest.h"
19 #include <spoolss.h>
20
21 extern BOOL GetLocalsplFuncs(LPPRINTPROVIDOR pp);
22
23 START_TEST(fpEnumPrinters)
24 {
25 DWORD cbNeeded;
26 DWORD cbTemp;
27 DWORD dwReturned;
28 DWORD i;
29 PRINTPROVIDOR pp;
30 PPRINTER_INFO_1W pPrinterInfo1;
31 PVOID pMem;
32
33 if (!GetLocalsplFuncs(&pp))
34 return;
35
36 // Verify that localspl only returns information about a single print provider (namely itself).
37 cbNeeded = 0xDEADBEEF;
38 dwReturned = 0xDEADBEEF;
39 SetLastError(0xDEADBEEF);
40 ok(!pp.fpEnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME, NULL, 1, NULL, 0, &cbNeeded, &dwReturned), "fpEnumPrinters returns TRUE\n");
41 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "fpEnumPrinters returns error %lu!\n", GetLastError());
42 ok(cbNeeded > 0, "cbNeeded is 0!\n");
43 ok(dwReturned == 0, "dwReturned is %lu!\n", dwReturned);
44
45 SetLastError(0xDEADBEEF);
46 pPrinterInfo1 = HeapAlloc(GetProcessHeap(), 0, cbNeeded);
47 ok(pp.fpEnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME, NULL, 1, (PBYTE)pPrinterInfo1, cbNeeded, &cbNeeded, &dwReturned), "fpEnumPrinters returns FALSE\n");
48 ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu!\n", GetLastError());
49 ok(cbNeeded > 0, "cbNeeded is 0!\n");
50 ok(dwReturned == 1, "dwReturned is %lu!\n", dwReturned);
51
52 // Verify the actual strings returned.
53 ok(wcscmp(pPrinterInfo1->pName, L"Windows NT Local Print Providor") == 0, "pPrinterInfo1->pName is \"%S\"!\n", pPrinterInfo1->pName);
54 ok(wcscmp(pPrinterInfo1->pDescription, L"Windows NT Local Printers") == 0, "pPrinterInfo1->pDescription is \"%S\"!\n", pPrinterInfo1->pDescription);
55 ok(wcscmp(pPrinterInfo1->pComment, L"Locally connected Printers") == 0, "pPrinterInfo1->pComment is \"%S\"!\n", pPrinterInfo1->pComment);
56
57 // Level 7 is the highest supported for localspl under Windows Server 2003.
58 // Higher levels need to fail, but they don't set an error code, just cbNeeded to 0.
59 cbNeeded = 0xDEADBEEF;
60 dwReturned = 0xDEADBEEF;
61 SetLastError(0xDEADBEEF);
62 ok(!pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, 8, NULL, 0, &cbNeeded, &dwReturned), "fpEnumPrinters returns TRUE!\n");
63 ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu!\n", GetLastError());
64 ok(cbNeeded == 0, "cbNeeded is %lu!\n", cbNeeded);
65 ok(dwReturned == 0, "dwReturned is %lu!\n", dwReturned);
66
67 // Verify that all valid levels work.
68 // In contrast to EnumPrintersW, which only accepts levels 0, 1, 2, 4 and 5, localspl returns information for level 0 to 7.
69 for (i = 0; i <= 7; i++)
70 {
71 // Try with no valid arguments at all.
72 // This scenario is usually caugt by RPC, so it just raises an exception here.
73 _SEH2_TRY
74 {
75 dwReturned = 0;
76 pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, i, NULL, 0, NULL, NULL);
77 }
78 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
79 {
80 dwReturned = _SEH2_GetExceptionCode();
81 }
82 _SEH2_END;
83
84 ok(dwReturned == EXCEPTION_ACCESS_VIOLATION, "dwReturned is %lu for Level %lu!\n", dwReturned, i);
85
86 // Now get the required buffer size.
87 cbNeeded = 0xDEADBEEF;
88 dwReturned = 0xDEADBEEF;
89 SetLastError(0xDEADBEEF);
90 ok(!pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, i, NULL, 0, &cbNeeded, &dwReturned), "fpEnumPrinters returns TRUE for Level %lu!\n", i);
91 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i);
92 ok(cbNeeded > 0, "cbNeeded is 0 for Level %lu!\n", i);
93 ok(dwReturned == 0, "dwReturned is %lu for Level %lu!\n", dwReturned, i);
94
95 // This test corrupts something inside spoolsv so that it's only runnable once without restarting spoolsv. Therefore it's disabled.
96 #if 0
97 // Now provide the demanded size, but no buffer. This also mustn't touch cbNeeded.
98 // This scenario is also caught by RPC and we just have an exception here.
99 _SEH2_TRY
100 {
101 dwReturned = 0;
102 pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, i, NULL, cbNeeded, &cbTemp, &dwReturned);
103 }
104 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
105 {
106 dwReturned = _SEH2_GetExceptionCode();
107 }
108 _SEH2_END;
109
110 ok(dwReturned == EXCEPTION_ACCESS_VIOLATION, "dwReturned is %lu for Level %lu!\n", dwReturned, i);
111 ok(cbNeeded == cbTemp, "cbNeeded is %lu, cbTemp is %lu for Level %lu!\n", cbNeeded, cbTemp, i);
112 #endif
113
114 // Finally use the function as intended and aim for success!
115 pMem = DllAllocSplMem(cbNeeded);
116 SetLastError(0xDEADBEEF);
117 ok(pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, i, pMem, cbNeeded, &cbTemp, &dwReturned), "fpEnumPrinters returns FALSE for Level %lu!\n", i);
118
119 // This is crazy. For level 3, fpEnumPrinters always returns ERROR_INSUFFICIENT_BUFFER even if we supply a buffer large enough.
120 if (i == 3)
121 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i);
122 else
123 ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i);
124
125 DllFreeSplMem(pMem);
126 }
127
128 // fpEnumPrinters has to succeed independent of the level (valid or not) if we query no information.
129 for (i = 0; i < 10; i++)
130 {
131 SetLastError(0xDEADBEEF);
132 ok(pp.fpEnumPrinters(0, NULL, i, NULL, 0, &cbNeeded, &dwReturned), "fpEnumPrinters returns FALSE for Level %lu!\n", i);
133 ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i);
134 ok(cbNeeded == 0, "cbNeeded is %lu for Level %lu!\n", cbNeeded, i);
135 ok(dwReturned == 0, "dwReturned is %lu for Level %lu!\n", dwReturned, i);
136 }
137 }