1 /*
2  * PROJECT:     ReactOS Print Spooler Service
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Xcv* functions
5  * COPYRIGHT:   Copyright 2020 ReactOS
6  */
7 
8 #include "precomp.h"
9 
10 static DWORD
11 _HandleAddPort(HANDLE hXcv, PBYTE pInputData, PDWORD pcbOutputNeeded, DWORD* pdwStatus)
12 {
13     DWORD res;
14     PLOCAL_PRINT_MONITOR pPrintMonitor;
15     PLOCAL_XCV_HANDLE pXcv;
16     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hXcv;
17     PWSTR pPortName = (PWSTR)pInputData;
18 
19     FIXME("LocalXcvAddPort : %s\n", debugstr_w( pPortName ) );
20 
21     // Check if this is a printer handle.
22     if (pHandle->HandleType != HandleType_Xcv)
23     {
24         ERR("LocalXcvAddPort : Invalid XCV Handle\n");
25         res = ERROR_INVALID_HANDLE;
26         goto Cleanup;
27     }
28 
29     pXcv = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle;
30 
31     pPrintMonitor = pXcv->pPrintMonitor;
32     if (!pPrintMonitor )
33     {
34         res = ERROR_INVALID_PARAMETER;
35         goto Cleanup;
36     }
37 
38     // Sanity checks
39     if (!pInputData || !pcbOutputNeeded)
40     {
41         res = ERROR_INVALID_PARAMETER;
42         goto Cleanup;
43     }
44 
45     pPrintMonitor->refcount++;
46     if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort )
47     {
48         res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort(pXcv->hXcv, L"AddPort", pInputData, 0, NULL, 0, pcbOutputNeeded);
49     }
50     else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort )
51     {
52         res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort(pXcv->hXcv, L"AddPort", pInputData, 0, NULL, 0, pcbOutputNeeded);
53     }
54     pPrintMonitor->refcount--;
55 
56     if ( res == ERROR_SUCCESS )
57     {
58         CreatePortEntry( pPortName, pPrintMonitor );
59     }
60 
61     FIXME("=> %u\n", res);
62 
63 Cleanup:
64     if (pdwStatus) *pdwStatus = res;
65     return res;
66 }
67 
68 static DWORD
69 _HandleDeletePort(HANDLE hXcv, PBYTE pInputData, PDWORD pcbOutputNeeded, DWORD* pdwStatus)
70 {
71     DWORD res;
72     PLOCAL_PRINT_MONITOR pPrintMonitor;
73     PLOCAL_XCV_HANDLE pXcv;
74     PLOCAL_PORT pPort;
75     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hXcv;
76     PWSTR pPortName = (PWSTR)pInputData;
77 
78     FIXME("LocalXcvDeletePort : %s\n", debugstr_w( pPortName ) );
79 
80     // Check if this is a printer handle.
81     if (pHandle->HandleType != HandleType_Xcv)
82     {
83         ERR("LocalXcvDeletePort : Invalid XCV Handle\n");
84         res = ERROR_INVALID_HANDLE;
85         goto Cleanup;
86     }
87 
88     pXcv = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle;
89 
90     pPrintMonitor = pXcv->pPrintMonitor;
91     if (!pPrintMonitor )
92     {
93         res = ERROR_INVALID_PARAMETER;
94         goto Cleanup;
95     }
96 
97     // Sanity checks
98     if (!pInputData || !pcbOutputNeeded)
99     {
100         res = ERROR_INVALID_PARAMETER;
101         goto Cleanup;
102     }
103 
104 
105     pPrintMonitor->refcount++;
106     //
107     //  Call back to monitor, update the Registry and Registry List.
108     //
109     if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort )
110     {
111         res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort(pXcv->hXcv, L"DeletePort", pInputData, 0, NULL, 0, pcbOutputNeeded);
112     }
113     else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort )
114     {
115         res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort(pXcv->hXcv, L"DeletePort", pInputData, 0, NULL, 0, pcbOutputNeeded);
116     }
117     pPrintMonitor->refcount--;
118     //
119     //  Now find and remove Local Port data.
120     //
121     if ( res == ERROR_SUCCESS )
122     {
123         pPort = FindPort( pPortName );
124         if (pPort )
125         {
126             FIXME("LocalXcvDeletePort removed Port Entry\n");
127             RemoveEntryList(&pPort->Entry);
128 
129             DllFreeSplMem(pPort);
130         }
131         FIXME("=> %u with %u\n", res, GetLastError() );
132     }
133 
134 Cleanup:
135     if (pdwStatus) *pdwStatus = res;
136     return res;
137 }
138 
139 BOOL WINAPI
140 LocalXcvData(HANDLE hXcv, const WCHAR* pszDataName, BYTE* pInputData, DWORD cbInputData, BYTE* pOutputData, DWORD cbOutputData, DWORD* pcbOutputNeeded, DWORD* pdwStatus)
141 {
142     DWORD res;
143     PLOCAL_PRINT_MONITOR pPrintMonitor;
144     PLOCAL_XCV_HANDLE pXcv;
145     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hXcv;
146 
147     FIXME("LocalXcvData(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
148 
149     // Sanity checks
150     if (!pszDataName)
151     {
152         res = ERROR_INVALID_PARAMETER;
153         goto Cleanup;
154     }
155 
156     // Call the appropriate handler for the requested data name.
157     if (wcscmp(pszDataName, L"AddPort") == 0)
158         return _HandleAddPort(hXcv, pInputData, pcbOutputNeeded, pdwStatus);
159 
160     if (wcscmp(pszDataName, L"DeletePort") == 0)
161         return _HandleDeletePort(hXcv, pInputData, pcbOutputNeeded, pdwStatus);
162 
163     //
164     // After the two Intercept Handlers, defer call back to Monitor.
165     //
166 
167     // Check if this is a printer handle.
168     if (pHandle->HandleType != HandleType_Xcv)
169     {
170         ERR("LocalXcvData : Invalid XCV Handle\n");
171         res = ERROR_INVALID_HANDLE;
172         goto Cleanup;
173     }
174 
175     pXcv = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle;
176 
177     pPrintMonitor = pXcv->pPrintMonitor;
178     if (!pPrintMonitor )
179     {
180         res = ERROR_INVALID_PARAMETER;
181         goto Cleanup;
182     }
183 
184     pPrintMonitor->refcount++;
185     if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort )
186     {
187         res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvDataPort(pXcv->hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
188     }
189     else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort )
190     {
191         res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvDataPort(pXcv->hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
192     }
193     pPrintMonitor->refcount--;
194 
195 Cleanup:
196     SetLastError(res);
197     if (pdwStatus) *pdwStatus = res;
198     return res;
199 }
200