ReactOS  0.4.15-dev-1070-ge1a01de
monitors.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Spooler API
3  * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE: Functions related to Print Monitors
5  * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 #include <marshalling/monitors.h>
10 
13 {
14  LPWSTR nameW = NULL;
15  INT len;
16  BOOL res;
17  LPMONITOR_INFO_2A mi2a;
18  MONITOR_INFO_2W mi2w;
19 
20  mi2a = (LPMONITOR_INFO_2A) pMonitors;
21  FIXME("AddMonitorA(%s, %d, %p) : %s %s %s\n", debugstr_a(pName), Level, pMonitors,
22  debugstr_a(mi2a ? mi2a->pName : NULL),
23  debugstr_a(mi2a ? mi2a->pEnvironment : NULL),
24  debugstr_a(mi2a ? mi2a->pDLLName : NULL));
25 
26  if (Level != 2)
27  {
28  ERR("Level = %d, unsupported!\n", Level);
30  return FALSE;
31  }
32 
33  /* XP: unchanged, win9x: ERROR_INVALID_ENVIRONMENT */
34  if (mi2a == NULL)
35  {
36  return FALSE;
37  }
38 
39  if (pName)
40  {
41  len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
42  nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
44  }
45 
46  memset(&mi2w, 0, sizeof(MONITOR_INFO_2W));
47  if (mi2a->pName)
48  {
49  len = MultiByteToWideChar(CP_ACP, 0, mi2a->pName, -1, NULL, 0);
50  mi2w.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
51  MultiByteToWideChar(CP_ACP, 0, mi2a->pName, -1, mi2w.pName, len);
52  }
53  if (mi2a->pEnvironment)
54  {
55  len = MultiByteToWideChar(CP_ACP, 0, mi2a->pEnvironment, -1, NULL, 0);
56  mi2w.pEnvironment = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
58  }
59  if (mi2a->pDLLName)
60  {
61  len = MultiByteToWideChar(CP_ACP, 0, mi2a->pDLLName, -1, NULL, 0);
62  mi2w.pDLLName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
63  MultiByteToWideChar(CP_ACP, 0, mi2a->pDLLName, -1, mi2w.pDLLName, len);
64  }
65 
66  res = AddMonitorW(nameW, Level, (LPBYTE) &mi2w);
67 
68  if (mi2w.pName) HeapFree(GetProcessHeap(), 0, mi2w.pName);
69  if (mi2w.pEnvironment) HeapFree(GetProcessHeap(), 0, mi2w.pEnvironment);
70  if (mi2w.pDLLName) HeapFree(GetProcessHeap(), 0, mi2w.pDLLName);
71  if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
72 
73  return (res);
74 }
75 
78 {
79  DWORD dwErrorCode;
80  WINSPOOL_MONITOR_CONTAINER MonitorInfoContainer;
81 
82  FIXME("AddMonitorW(%S, %lu, %p)\n", pName, Level, pMonitors);
83 
84  if (Level != 2)
85  {
86  ERR("Level = %d, unsupported!\n", Level);
88  return FALSE;
89  }
90 
91  MonitorInfoContainer.MonitorInfo.pMonitorInfo2 = (WINSPOOL_MONITOR_INFO_2*)pMonitors;
92  MonitorInfoContainer.Level = Level;
93 
94  // Do the RPC call
96  {
97  dwErrorCode = _RpcAddMonitor(pName, &MonitorInfoContainer);
98  }
100  {
101  dwErrorCode = RpcExceptionCode();
102  ERR("_RpcAddMonitor failed with exception code %lu!\n", dwErrorCode);
103  }
104  RpcEndExcept;
105 FIXME("AddMonitorW Error Code %lu\n", dwErrorCode);
106  SetLastError(dwErrorCode);
107  return (dwErrorCode == ERROR_SUCCESS);
108 }
109 
110 BOOL WINAPI
111 DeleteMonitorA(PSTR pName, PSTR pEnvironment, PSTR pMonitorName)
112 {
113  LPWSTR nameW = NULL;
114  LPWSTR EnvironmentW = NULL;
115  LPWSTR MonitorNameW = NULL;
116  BOOL res;
117  INT len;
118 
119  TRACE("DeleteMonitorA(%s, %s, %s)\n", pName, pEnvironment, pMonitorName);
120 
121  if (pName) {
122  len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
123  nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
125  }
126 
127  if (pEnvironment) {
128  len = MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, NULL, 0);
129  EnvironmentW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
130  MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, EnvironmentW, len);
131  }
132  if (pMonitorName) {
133  len = MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, NULL, 0);
134  MonitorNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
135  MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, MonitorNameW, len);
136  }
137 
138  res = DeleteMonitorW(nameW, EnvironmentW, MonitorNameW);
139 
140  if (MonitorNameW) HeapFree(GetProcessHeap(), 0, MonitorNameW);
141  if (EnvironmentW) HeapFree(GetProcessHeap(), 0, EnvironmentW);
142  if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
143 
144  return (res);
145 }
146 
147 BOOL WINAPI
148 DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
149 {
150  DWORD dwErrorCode;
151 
152  FIXME("DeleteMonitorW(%S, %S, %S)\n", pName, pEnvironment, pMonitorName);
153 
154  // Do the RPC call
156  {
157  dwErrorCode = _RpcDeleteMonitor(pName, pEnvironment, pMonitorName);
158  }
160  {
161  dwErrorCode = RpcExceptionCode();
162  ERR("_RpcDeleteMonitor failed with exception code %lu!\n", dwErrorCode);
163  }
164  RpcEndExcept;
165 
166  SetLastError(dwErrorCode);
167  return (dwErrorCode == ERROR_SUCCESS);
168 
169 }
170 
171 BOOL WINAPI
173 {
174  BOOL res;
175  LPBYTE bufferW = NULL;
176  LPWSTR nameW = NULL;
177  DWORD needed = 0;
178  DWORD numentries = 0;
179  INT len;
180 
181  FIXME("EnumMonitorsA(%s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
182 
183  if ( Level < 1 || Level > 2 )
184  {
185  ERR("Level = %d, unsupported!\n", Level);
187  return FALSE;
188  }
189 
190  /* convert servername to unicode */
191  if (pName)
192  {
193  len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
194  nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
196  }
197  /* alloc (userbuffersize*sizeof(WCHAR) and try to enum the monitors */
198  needed = cbBuf * sizeof(WCHAR);
199  if (needed) bufferW = HeapAlloc(GetProcessHeap(), 0, needed);
200  res = EnumMonitorsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned);
201 
203  {
204  if (pcbNeeded) needed = *pcbNeeded;
205  /* HeapReAlloc return NULL, when bufferW was NULL */
206  bufferW = (bufferW) ? HeapReAlloc(GetProcessHeap(), 0, bufferW, needed) :
207  HeapAlloc(GetProcessHeap(), 0, needed);
208 
209  /* Try again with the large Buffer */
210  res = EnumMonitorsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned);
211  }
212  numentries = pcReturned ? *pcReturned : 0;
213  needed = 0;
214  /*
215  W2k require the buffersize from EnumMonitorsW also for EnumMonitorsA.
216  We use the smaller Ansi-Size to avoid conflicts with fixed Buffers of old Apps.
217  */
218  if (res)
219  {
220  /* EnumMonitorsW collected all Data. Parse them to calculate ANSI-Size */
221  DWORD entrysize = 0;
222  DWORD index;
223  LPSTR ptr;
224  LPMONITOR_INFO_2W mi2w;
225  LPMONITOR_INFO_2A mi2a;
226 
227  /* MONITOR_INFO_*W and MONITOR_INFO_*A have the same size */
228  entrysize = (Level == 1) ? sizeof(MONITOR_INFO_1A) : sizeof(MONITOR_INFO_2A);
229 
230  /* First pass: calculate the size for all Entries */
231  mi2w = (LPMONITOR_INFO_2W) bufferW;
232  mi2a = (LPMONITOR_INFO_2A) pMonitors;
233  index = 0;
234  while (index < numentries)
235  {
236  index++;
237  needed += entrysize; /* MONITOR_INFO_?A */
238  TRACE("%p: parsing #%d (%s)\n", mi2w, index, debugstr_w(mi2w->pName));
239 
240  needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pName, -1,
241  NULL, 0, NULL, NULL);
242  if (Level > 1)
243  {
244  needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pEnvironment, -1,
245  NULL, 0, NULL, NULL);
246  needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pDLLName, -1,
247  NULL, 0, NULL, NULL);
248  }
249  /* use LPBYTE with entrysize to avoid double code (MONITOR_INFO_1 + MONITOR_INFO_2) */
250  mi2w = (LPMONITOR_INFO_2W) (((LPBYTE)mi2w) + entrysize);
251  mi2a = (LPMONITOR_INFO_2A) (((LPBYTE)mi2a) + entrysize);
252  }
253 
254  /* check for errors and quit on failure */
255  if (cbBuf < needed)
256  {
258  res = FALSE;
259  goto emA_cleanup;
260  }
261  len = entrysize * numentries; /* room for all MONITOR_INFO_?A */
262  ptr = (LPSTR) &pMonitors[len]; /* room for strings */
263  cbBuf -= len ; /* free Bytes in the user-Buffer */
264  mi2w = (LPMONITOR_INFO_2W) bufferW;
265  mi2a = (LPMONITOR_INFO_2A) pMonitors;
266  index = 0;
267  /* Second Pass: Fill the User Buffer (if we have one) */
268  while ((index < numentries) && pMonitors)
269  {
270  index++;
271  TRACE("%p: writing MONITOR_INFO_%dA #%d\n", mi2a, Level, index);
272  mi2a->pName = ptr;
273  len = WideCharToMultiByte(CP_ACP, 0, mi2w->pName, -1,
274  ptr, cbBuf , NULL, NULL);
275  ptr += len;
276  cbBuf -= len;
277  if (Level > 1)
278  {
279  mi2a->pEnvironment = ptr;
280  len = WideCharToMultiByte(CP_ACP, 0, mi2w->pEnvironment, -1,
281  ptr, cbBuf, NULL, NULL);
282  ptr += len;
283  cbBuf -= len;
284 
285  mi2a->pDLLName = ptr;
286  len = WideCharToMultiByte(CP_ACP, 0, mi2w->pDLLName, -1,
287  ptr, cbBuf, NULL, NULL);
288  ptr += len;
289  cbBuf -= len;
290  }
291  /* use LPBYTE with entrysize to avoid double code (MONITOR_INFO_1 + MONITOR_INFO_2) */
292  mi2w = (LPMONITOR_INFO_2W) (((LPBYTE)mi2w) + entrysize);
293  mi2a = (LPMONITOR_INFO_2A) (((LPBYTE)mi2a) + entrysize);
294  }
295  }
296 emA_cleanup:
297  if (pcbNeeded) *pcbNeeded = needed;
298  if (pcReturned) *pcReturned = (res) ? numentries : 0;
299 
300  if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
301  if (bufferW) HeapFree(GetProcessHeap(), 0, bufferW);
302 
303  FIXME("returning %d with %d (%d byte for %d entries)\n", (res), GetLastError(), needed, numentries);
304 
305  return (res);
306 
307 }
308 
309 BOOL WINAPI
311 {
312  DWORD dwErrorCode;
313 
314  FIXME("EnumMonitorsW(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
315 
316  if ( Level < 1 || Level > 2 )
317  {
318  ERR("Level = %d, unsupported!\n", Level);
320  return FALSE;
321  }
322 
323  // Do the RPC call
325  {
326  dwErrorCode = _RpcEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
327  }
329  {
330  dwErrorCode = RpcExceptionCode();
331  ERR("_RpcEnumMonitors failed with exception code %lu!\n", dwErrorCode);
332  }
333  RpcEndExcept;
334 
335  if (dwErrorCode == ERROR_SUCCESS)
336  {
337  // Replace relative offset addresses in the output by absolute pointers.
338  ASSERT(Level >= 1 && Level <= 2);
339  MarshallUpStructuresArray(cbBuf, pMonitors, *pcReturned, pMonitorInfoMarshalling[Level]->pInfo, pMonitorInfoMarshalling[Level]->cbStructureSize, TRUE);
340  }
341 
342  SetLastError(dwErrorCode);
343  return (dwErrorCode == ERROR_SUCCESS);
344 }
#define RpcEndExcept
Definition: rpc.h:128
#define ERROR_SUCCESS
Definition: deptool.c:10
#define WideCharToMultiByte
Definition: compat.h:111
union _WINSPOOL_MONITOR_CONTAINER::@3398 MonitorInfo
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
#define CP_ACP
Definition: compat.h:109
static const MARSHALLING * pMonitorInfoMarshalling[]
Definition: monitors.h:26
DWORD _RpcDeleteMonitor(WINSPOOL_HANDLE pName, WCHAR *pEnvironment, WCHAR *pMonitorName)
Definition: monitors.c:31
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
char * LPSTR
Definition: xmlstorage.h:182
int32_t INT
Definition: typedefs.h:58
LPWSTR pEnvironment
Definition: winspool.h:834
unsigned char * LPBYTE
Definition: typedefs.h:53
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:111
static PVOID ptr
Definition: dispmode.c:27
#define RpcTryExcept
Definition: rpc.h:126
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
WINSPOOL_MONITOR_INFO_2 * pMonitorInfo2
Definition: winspool.idl:656
BOOL WINAPI EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: monitors.c:77
BOOL WINAPI DeleteMonitorA(PSTR pName, PSTR pEnvironment, PSTR pMonitorName)
Definition: monitors.c:111
GLuint index
Definition: glext.h:6031
static const WCHAR nameW[]
Definition: main.c:46
#define RpcExceptionCode()
Definition: rpc.h:132
#define TRACE(s)
Definition: solgame.cpp:4
static LPSTR pName
Definition: security.c:75
#define GetProcessHeap()
Definition: compat.h:484
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define debugstr_a
Definition: kernel32.h:31
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:500
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LPWSTR pDLLName
Definition: winspool.h:835
#define index(s, c)
Definition: various.h:29
BOOL WINAPI EnumMonitorsA(PSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: monitors.c:172
GLenum GLsizei len
Definition: glext.h:6722
#define ERR(fmt,...)
Definition: debug.h:110
BOOL WINAPI AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors)
Definition: monitors.c:11
_In_ DWORD _Out_ PDWORD pcbNeeded
Definition: winddi.h:3827
#define HeapReAlloc
Definition: compat.h:482
signed char * PSTR
Definition: retypes.h:7
DWORD * PDWORD
Definition: pedump.c:68
#define MultiByteToWideChar
Definition: compat.h:110
struct _MONITOR_INFO_2A MONITOR_INFO_2A
GLuint res
Definition: glext.h:9613
struct _MONITOR_INFO_2A * LPMONITOR_INFO_2A
struct _MONITOR_INFO_2W * LPMONITOR_INFO_2W
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
WCHAR * LPWSTR
Definition: xmlstorage.h:184
DWORD _RpcEnumMonitors(WINSPOOL_HANDLE pName, DWORD Level, BYTE *pMonitor, DWORD cbBuf, DWORD *pcbNeeded, DWORD *pcReturned)
Definition: monitors.c:50
DWORD _RpcAddMonitor(WINSPOOL_HANDLE pName, WINSPOOL_MONITOR_CONTAINER *pMonitorContainer)
Definition: monitors.c:12
LPSTR pEnvironment
Definition: winspool.h:828
#define memset(x, y, z)
Definition: compat.h:39
BYTE * PBYTE
Definition: pedump.c:66
#define HeapFree(x, y, z)
Definition: compat.h:483
BOOL WINAPI DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
Definition: monitors.c:44
#define RpcExcept(expr)
Definition: rpc.h:127
BOOL WINAPI AddMonitorA(PSTR pName, DWORD Level, PBYTE pMonitors)
Definition: monitors.c:12
BOOL WINAPI MarshallUpStructuresArray(DWORD cbSize, PVOID pStructuresArray, DWORD cElements, const MARSHALLING_INFO *pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
Definition: marshalling.c:202
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10