ReactOS  0.4.14-dev-342-gdc047f9
xcv.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Local Port Monitor
3  * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE: Implementation of Xcv* and support functions
5  * COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 static DWORD
11 _HandleAddPort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
12 {
14 }
15 
34 static DWORD
35 _HandleConfigureLPTPortCommandOK(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
36 {
37  DWORD cbBuffer;
38  DWORD dwErrorCode;
39  HKEY hKey = NULL;
40  HKEY hToken = NULL;
41 
42  // Sanity checks
43  if (!pXcv || !pInputData || !pcbOutputNeeded)
44  {
45  dwErrorCode = ERROR_INVALID_PARAMETER;
46  goto Cleanup;
47  }
48 
49  *pcbOutputNeeded = 0;
50 
51  // This action can only happen at SERVER_ACCESS_ADMINISTER access level.
53  {
54  dwErrorCode = ERROR_ACCESS_DENIED;
55  goto Cleanup;
56  }
57 
58  // Switch to the SYSTEM context for modifying the registry.
59  hToken = RevertToPrinterSelf();
60  if (!hToken)
61  {
62  dwErrorCode = GetLastError();
63  ERR("RevertToPrinterSelf failed with error %lu!\n", dwErrorCode);
64  goto Cleanup;
65  }
66 
67  // Open the key where our value is stored.
68  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_SET_VALUE, &hKey);
69  if (dwErrorCode != ERROR_SUCCESS)
70  {
71  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
72  goto Cleanup;
73  }
74 
75  // We don't use cbInputData here, because the buffer pInputData could be bigger than the data it contains.
76  cbBuffer = (wcslen((PWSTR)pInputData) + 1) * sizeof(WCHAR);
77 
78  // Write the value to the registry.
79  dwErrorCode = (DWORD)RegSetValueExW(hKey, L"TransmissionRetryTimeout", 0, REG_SZ, pInputData, cbBuffer);
80  if (dwErrorCode != ERROR_SUCCESS)
81  {
82  ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode);
83  goto Cleanup;
84  }
85 
86 Cleanup:
87  if (hKey)
88  RegCloseKey(hKey);
89 
90  if (hToken)
92 
93  return dwErrorCode;
94 }
95 
96 static DWORD
97 _HandleDeletePort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
98 {
100 }
101 
123 static DWORD
124 _HandleGetDefaultCommConfig(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
125 {
126  // Sanity checks
127  if (!pInputData || !pcbOutputNeeded)
129 
130  *pcbOutputNeeded = sizeof(COMMCONFIG);
131 
132  // Check if the supplied buffer is large enough.
133  if (cbOutputData < *pcbOutputNeeded)
135 
136  // Finally get the port configuration.
137  if (!GetDefaultCommConfigW((PCWSTR)pInputData, (LPCOMMCONFIG)pOutputData, pcbOutputNeeded))
138  return GetLastError();
139 
140  return ERROR_SUCCESS;
141 }
142 
161 static DWORD
162 _HandleGetTransmissionRetryTimeout(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
163 {
165 
166  // Sanity checks
167  if (!pOutputData || !pcbOutputNeeded)
169 
170  *pcbOutputNeeded = sizeof(DWORD);
171 
172  // Check if the supplied buffer is large enough.
173  if (cbOutputData < *pcbOutputNeeded)
175 
176  // Retrieve and copy the number.
178  CopyMemory(pOutputData, &dwTimeout, sizeof(DWORD));
179  return ERROR_SUCCESS;
180 }
181 
199 static DWORD
200 _HandleMonitorUI(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
201 {
202  const WCHAR wszMonitorUI[] = L"LocalUI.dll";
203 
204  // Sanity checks
205  if (!pOutputData || !pcbOutputNeeded)
207 
208  *pcbOutputNeeded = sizeof(wszMonitorUI);
209 
210  // Check if the supplied buffer is large enough.
211  if (cbOutputData < *pcbOutputNeeded)
213 
214  // Copy the string.
215  CopyMemory(pOutputData, wszMonitorUI, sizeof(wszMonitorUI));
216  return ERROR_SUCCESS;
217 }
218 
239 static DWORD
240 _HandlePortExists(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
241 {
242  // Sanity checks
243  if (!pInputData || !pOutputData || !pcbOutputNeeded)
245 
246  *pcbOutputNeeded = sizeof(BOOL);
247 
248  // Check if the supplied buffer is large enough.
249  if (cbOutputData < *pcbOutputNeeded)
251 
252  // Return the check result and error code.
253  *(PBOOL)pOutputData = DoesPortExist((PCWSTR)pInputData);
254  return GetLastError();
255 }
256 
257 static DWORD
258 _HandlePortIsValid(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
259 {
261 }
262 
282 static DWORD
283 _HandleSetDefaultCommConfig(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
284 {
285  DWORD dwErrorCode;
286  HANDLE hToken = NULL;
287  LPCOMMCONFIG pCommConfig;
288  PWSTR pwszPortNameWithoutColon = NULL;
289 
290  // Sanity checks
291  // pwszObject needs to be at least 2 characters long to be a port name with a trailing colon.
292  if (!pXcv || !pXcv->pwszObject || !pXcv->pwszObject[0] || !pXcv->pwszObject[1] || !pInputData || !pcbOutputNeeded)
293  {
294  dwErrorCode = ERROR_INVALID_PARAMETER;
295  goto Cleanup;
296  }
297 
298  *pcbOutputNeeded = 0;
299 
300  // This action can only happen at SERVER_ACCESS_ADMINISTER access level.
302  {
303  dwErrorCode = ERROR_ACCESS_DENIED;
304  goto Cleanup;
305  }
306 
307  // SetDefaultCommConfigW needs the port name without colon.
308  dwErrorCode = GetPortNameWithoutColon(pXcv->pwszObject, &pwszPortNameWithoutColon);
309  if (dwErrorCode != ERROR_SUCCESS)
310  goto Cleanup;
311 
312  // Switch to the SYSTEM context for setting the port configuration.
313  hToken = RevertToPrinterSelf();
314  if (!hToken)
315  {
316  dwErrorCode = GetLastError();
317  ERR("RevertToPrinterSelf failed with error %lu!\n", dwErrorCode);
318  goto Cleanup;
319  }
320 
321  // Finally pass the parameters to SetDefaultCommConfigW.
322  pCommConfig = (LPCOMMCONFIG)pInputData;
323  if (!SetDefaultCommConfigW(pwszPortNameWithoutColon, pCommConfig, pCommConfig->dwSize))
324  {
325  dwErrorCode = GetLastError();
326  ERR("SetDefaultCommConfigW failed with error %lu!\n", dwErrorCode);
327  goto Cleanup;
328  }
329 
330  dwErrorCode = ERROR_SUCCESS;
331 
332 Cleanup:
333  if (hToken)
334  ImpersonatePrinterClient(hToken);
335 
336  if (pwszPortNameWithoutColon)
337  DllFreeSplMem(pwszPortNameWithoutColon);
338 
339  return dwErrorCode;
340 }
341 
342 BOOL WINAPI
344 {
346 
347  TRACE("LocalmonXcvClosePort(%p)\n", hXcv);
348 
349  // Sanity checks
350  if (!pXcv)
351  {
353  return FALSE;
354  }
355 
356  // Remove it from the list and free the memory.
357  RemoveEntryList(&pXcv->Entry);
358  DllFreeSplMem(pXcv);
359 
361  return TRUE;
362 }
363 
365 LocalmonXcvDataPort(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
366 {
367  TRACE("LocalmonXcvDataPort(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
368 
369  // Sanity checks
370  if (!pszDataName)
372 
373  // Call the appropriate handler for the requested data name.
374  if (wcscmp(pszDataName, L"AddPort") == 0)
375  return _HandleAddPort((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded);
376 
377  if (wcscmp(pszDataName, L"ConfigureLPTPortCommandOK") == 0)
378  return _HandleConfigureLPTPortCommandOK((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded);
379 
380  if (wcscmp(pszDataName, L"DeletePort") == 0)
381  return _HandleDeletePort((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded);
382 
383  if (wcscmp(pszDataName, L"GetDefaultCommConfig") == 0)
384  return _HandleGetDefaultCommConfig(pInputData, pOutputData, cbOutputData, pcbOutputNeeded);
385 
386  if (wcscmp(pszDataName, L"GetTransmissionRetryTimeout") == 0)
387  return _HandleGetTransmissionRetryTimeout(pOutputData, cbOutputData, pcbOutputNeeded);
388 
389  if (wcscmp(pszDataName, L"MonitorUI") == 0)
390  return _HandleMonitorUI(pOutputData, cbOutputData, pcbOutputNeeded);
391 
392  if (wcscmp(pszDataName, L"PortExists") == 0)
393  return _HandlePortExists(pInputData, pOutputData, cbOutputData, pcbOutputNeeded);
394 
395  if (wcscmp(pszDataName, L"PortIsValid") == 0)
396  return _HandlePortIsValid(pInputData, pOutputData, cbOutputData, pcbOutputNeeded);
397 
398  if (wcscmp(pszDataName, L"SetDefaultCommConfig") == 0)
399  return _HandleSetDefaultCommConfig((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded);
400 
402 }
403 
404 BOOL WINAPI
406 {
407  DWORD cbObject = 0;
408  DWORD dwErrorCode;
409  PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
410  PLOCALMON_XCV pXcv;
411 
412  TRACE("LocalmonXcvOpenPort(%p, %S, %lu, %p)\n", hMonitor, pwszObject, GrantedAccess, phXcv);
413 
414  // Sanity checks
415  if (!pLocalmon || !phXcv)
416  {
417  dwErrorCode = ERROR_INVALID_PARAMETER;
418  goto Cleanup;
419  }
420 
421  if (pwszObject)
422  cbObject = (wcslen(pwszObject) + 1) * sizeof(WCHAR);
423 
424  // Create a new LOCALMON_XCV structure and fill the relevant fields.
425  pXcv = DllAllocSplMem(sizeof(LOCALMON_XCV) + cbObject);
426  if (!pXcv)
427  {
428  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
429  ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
430  goto Cleanup;
431  }
432 
433  pXcv->pLocalmon = pLocalmon;
435 
436  if (cbObject)
437  {
438  pXcv->pwszObject = (PWSTR)((PBYTE)pXcv + sizeof(LOCALMON_XCV));
439  CopyMemory(pXcv->pwszObject, pwszObject, cbObject);
440  }
441 
442  InsertTailList(&pLocalmon->XcvHandles, &pXcv->Entry);
443 
444  // Return it as the Xcv handle.
445  *phXcv = (HANDLE)pXcv;
446  dwErrorCode = ERROR_SUCCESS;
447 
448 Cleanup:
449  SetLastError(dwErrorCode);
450  return (dwErrorCode == ERROR_SUCCESS);
451 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
struct _COMM_CONFIG COMMCONFIG
const uint16_t * PCWSTR
Definition: typedefs.h:55
struct _COMM_CONFIG * LPCOMMCONFIG
Definition: confdlg.c:35
#define TRUE
Definition: types.h:120
#define ERROR_SUCCESS
Definition: deptool.c:10
#define KEY_SET_VALUE
Definition: nt_native.h:1017
BOOL WINAPI SetDefaultCommConfigW(LPCWSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
Definition: comm.c:1338
struct _LOCALMON_XCV LOCALMON_XCV
static DWORD _HandleMonitorUI(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:200
uint16_t * PWSTR
Definition: typedefs.h:54
BOOL WINAPI DllFreeSplMem(PVOID pMem)
Definition: memory.c:112
LIST_ENTRY XcvHandles
Definition: precomp.h:40
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
DWORD WINAPI LocalmonXcvDataPort(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:365
static DWORD _HandleConfigureLPTPortCommandOK(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:35
#define InsertTailList(ListHead, Entry)
#define BOOL
Definition: nt_native.h:43
#define DWORD
Definition: nt_native.h:44
struct _LOCALMON_XCV * PLOCALMON_XCV
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
DWORD GetLPTTransmissionRetryTimeout(VOID)
Definition: tools.c:85
LIST_ENTRY Entry
Definition: precomp.h:74
static DWORD _HandleGetDefaultCommConfig(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:124
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
static DWORD _HandleDeletePort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:97
BOOL * PBOOL
Definition: windef.h:161
HANDLE WINAPI RevertToPrinterSelf(VOID)
Definition: context.c:64
static DWORD _HandleGetTransmissionRetryTimeout(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:162
BOOL WINAPI LocalmonXcvOpenPort(HANDLE hMonitor, PCWSTR pwszObject, ACCESS_MASK GrantedAccess, PHANDLE phXcv)
Definition: xcv.c:405
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4895
BOOL DoesPortExist(PCWSTR pwszPortName)
Definition: tools.c:24
#define TRACE(s)
Definition: solgame.cpp:4
__wchar_t WCHAR
Definition: xmlstorage.h:180
BOOL WINAPI GetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
Definition: comm.c:1398
#define WINAPI
Definition: msvc.h:8
#define CopyMemory
Definition: winbase.h:1640
static DWORD _HandlePortIsValid(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:258
PVOID HANDLE
Definition: typedefs.h:71
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:417
static const WCHAR L[]
Definition: oid.c:1250
DWORD dwSize
Definition: winbase.h:655
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
static const WCHAR Cleanup[]
Definition: register.c:80
#define ERR(fmt,...)
Definition: debug.h:109
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD dwTimeout
Definition: wincrypt.h:6081
BOOL WINAPI LocalmonXcvClosePort(HANDLE hXcv)
Definition: xcv.c:343
PWSTR pwszObject
Definition: precomp.h:77
static DWORD _HandleAddPort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:11
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
PLOCALMON_HANDLE pLocalmon
Definition: precomp.h:76
#define SERVER_ACCESS_ADMINISTER
Definition: winspool.h:1273
DWORD * PDWORD
Definition: pedump.c:68
static DWORD _HandlePortExists(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:240
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:92
BOOL WINAPI ImpersonatePrinterClient(_In_ HANDLE hToken)
PVOID WINAPI DllAllocSplMem(DWORD dwBytes)
Definition: memory.c:95
static HANDLE hXcv
Definition: localmon.c:73
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:13
BYTE * PBYTE
Definition: pedump.c:66
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
ULONG ACCESS_MASK
Definition: nt_native.h:40
struct _LOCALMON_HANDLE * PLOCALMON_HANDLE
DWORD GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR *ppwszPortNameWithoutColon)
Definition: tools.c:142
static DWORD _HandleSetDefaultCommConfig(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:283
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define REG_SZ
Definition: layer.c:22
ACCESS_MASK GrantedAccess
Definition: precomp.h:75