ReactOS  0.4.14-dev-317-g96040ec
main.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: Main functions
5  * COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 // Global Variables
15 
16 // Local Constants
18  sizeof(MONITOR2), // cbSize
19  LocalmonEnumPorts, // pfnEnumPorts
20  LocalmonOpenPort, // pfnOpenPort
21  NULL, // pfnOpenPortEx
22  LocalmonStartDocPort, // pfnStartDocPort
23  LocalmonWritePort, // pfnWritePort
24  LocalmonReadPort, // pfnReadPort
25  LocalmonEndDocPort, // pfnEndDocPort
26  LocalmonClosePort, // pfnClosePort
27  NULL, // pfnAddPort
28  NULL, // pfnAddPortEx
29  NULL, // pfnConfigurePort
30  NULL, // pfnDeletePort
31  LocalmonGetPrinterDataFromPort, // pfnGetPrinterDataFromPort
32  LocalmonSetPortTimeOuts, // pfnSetPortTimeOuts
33  LocalmonXcvOpenPort, // pfnXcvOpenPort
34  LocalmonXcvDataPort, // pfnXcvDataPort
35  LocalmonXcvClosePort, // pfnXcvClosePort
36  LocalmonShutdown, // pfnShutdown
37  NULL, // pfnSendRecvBidiDataFromPort
38 };
39 
40 
55 static __inline BOOL
56 _IsNEPort(PCWSTR pwszPortName)
57 {
58  PCWSTR p = pwszPortName;
59 
60  // First character needs to be 'N' (uppercase or lowercase)
61  if (*p != L'N' && *p != L'n')
62  return FALSE;
63 
64  // Next character needs to be 'E' (uppercase or lowercase)
65  p++;
66  if (*p != L'E' && *p != L'e')
67  return FALSE;
68 
69  // An optional hyphen may follow now.
70  p++;
71  if (*p == L'-')
72  p++;
73 
74  // Now an arbitrary number of digits may follow.
75  while (*p >= L'0' && *p <= L'9')
76  p++;
77 
78  // Finally, the virtual Ne port must be terminated by a colon.
79  if (*p != ':')
80  return FALSE;
81 
82  // If this is the end of the string, we have a virtual Ne port.
83  p++;
84  return (*p == L'\0');
85 }
86 
87 static void
89 {
91  cbLocalMonitor = (wcslen(pwszLocalMonitor) + 1) * sizeof(WCHAR);
92 
94  cbLocalPort = (wcslen(pwszLocalPort) + 1) * sizeof(WCHAR);
95 }
96 
98 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
99 {
100  switch (fdwReason)
101  {
102  case DLL_PROCESS_ATTACH:
103  DisableThreadLibraryCalls(hinstDLL);
104  _LoadResources(hinstDLL);
105  break;
106  }
107 
108  return TRUE;
109 }
110 
111 void WINAPI
113 {
114  PLOCALMON_HANDLE pLocalmon;
115  PLOCALMON_PORT pPort;
116  PLOCALMON_XCV pXcv;
117 
118  TRACE("LocalmonShutdown(%p)\n", hMonitor);
119 
120  pLocalmon = (PLOCALMON_HANDLE)hMonitor;
121 
122  // Close all virtual file ports.
123  while (!IsListEmpty(&pLocalmon->FilePorts))
124  {
125  pPort = CONTAINING_RECORD(&pLocalmon->FilePorts.Flink, LOCALMON_PORT, Entry);
126  LocalmonClosePort((HANDLE)pPort);
127  }
128 
129  // Do the same for the open Xcv ports.
130  while (!IsListEmpty(&pLocalmon->XcvHandles))
131  {
132  pXcv = CONTAINING_RECORD(&pLocalmon->XcvHandles.Flink, LOCALMON_XCV, Entry);
134  }
135 
136  // Now close all registry ports, remove them from the list and free their memory.
137  while (!IsListEmpty(&pLocalmon->RegistryPorts))
138  {
140  LocalmonClosePort((HANDLE)pPort);
141  RemoveEntryList(&pPort->Entry);
142  DllFreeSplMem(pPort);
143  }
144 
145  // Finally clean the LOCALMON_HANDLE structure itself.
146  DeleteCriticalSection(&pLocalmon->Section);
147  DllFreeSplMem(pLocalmon);
148 }
149 
152 {
153  DWORD cchMaxPortName;
154  DWORD cchPortName;
155  DWORD dwErrorCode;
156  DWORD dwPortCount;
157  DWORD i;
158  HKEY hKey;
159  PMONITOR2 pReturnValue = NULL;
160  PLOCALMON_HANDLE pLocalmon;
161  PLOCALMON_PORT pPort = NULL;
162 
163  TRACE("InitializePrintMonitor2(%p, %p)\n", pMonitorInit, phMonitor);
164 
165  // Create a new LOCALMON_HANDLE structure.
166  pLocalmon = DllAllocSplMem(sizeof(LOCALMON_HANDLE));
167  InitializeCriticalSection(&pLocalmon->Section);
168  InitializeListHead(&pLocalmon->FilePorts);
169  InitializeListHead(&pLocalmon->RegistryPorts);
170  InitializeListHead(&pLocalmon->XcvHandles);
171 
172  // The Local Spooler Port Monitor doesn't need to care about the given registry key and functions.
173  // Instead it uses a well-known registry key for getting its information about local ports. Open this one.
174  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", 0, KEY_READ, &hKey);
175  if (dwErrorCode != ERROR_SUCCESS)
176  {
177  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
178  goto Cleanup;
179  }
180 
181  // Get the number of ports and the length of the largest port name.
182  dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwPortCount, &cchMaxPortName, NULL, NULL, NULL);
183  if (dwErrorCode != ERROR_SUCCESS)
184  {
185  ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
186  goto Cleanup;
187  }
188 
189  // Loop through all ports.
190  for (i = 0; i < dwPortCount; i++)
191  {
192  // Allocate memory for a new LOCALMON_PORT structure and its name.
193  pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + (cchMaxPortName + 1) * sizeof(WCHAR));
194  if (!pPort)
195  {
196  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
197  ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
198  goto Cleanup;
199  }
200 
201  pPort->pLocalmon = pLocalmon;
202  pPort->hFile = INVALID_HANDLE_VALUE;
203  pPort->pwszPortName = (PWSTR)((PBYTE)pPort + sizeof(LOCALMON_PORT));
204 
205  // Get the port name.
206  cchPortName = cchMaxPortName + 1;
207  dwErrorCode = (DWORD)RegEnumValueW(hKey, i, pPort->pwszPortName, &cchPortName, NULL, NULL, NULL, NULL);
208  if (dwErrorCode != ERROR_SUCCESS)
209  {
210  ERR("RegEnumValueW failed with status %lu!\n", dwErrorCode);
211  goto Cleanup;
212  }
213 
214  // pwszPortName can be one of the following to be valid for this Port Monitor:
215  // COMx: - Physical COM port
216  // LPTx: - Physical LPT port (or redirected one using "net use LPT1 ...")
217  // FILE: - Opens a prompt that asks for an output filename
218  // C:\bla.txt - Redirection into the file "C:\bla.txt"
219  // \\COMPUTERNAME\PrinterName - Redirection to a shared network printer installed as a local port
220  //
221  // We can't detect valid and invalid ones by the name, so we can only exclude empty ports and the virtual "Ne00:", "Ne01:", ... ports.
222  // Skip the invalid ones here.
223  if (!cchPortName || _IsNEPort(pPort->pwszPortName))
224  {
225  DllFreeSplMem(pPort);
226  pPort = NULL;
227  continue;
228  }
229 
230  // Add it to the list.
231  InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
232 
233  // Don't let the cleanup routine free this.
234  pPort = NULL;
235  }
236 
237  // Return our handle and the Print Monitor functions.
238  *phMonitor = (HANDLE)pLocalmon;
239  pReturnValue = &_MonitorFunctions;
240  dwErrorCode = ERROR_SUCCESS;
241 
242 Cleanup:
243  if (pPort)
244  DllFreeSplMem(pPort);
245 
246  SetLastError(dwErrorCode);
247  return pReturnValue;
248 }
BOOL WINAPI LocalmonXcvOpenPort(HANDLE hMonitor, PCWSTR pszObject, ACCESS_MASK GrantedAccess, PHANDLE phXcv)
Definition: xcv.c:405
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define TRUE
Definition: types.h:120
#define ERROR_SUCCESS
Definition: deptool.c:10
LIST_ENTRY Entry
Definition: precomp.h:50
#define KEY_READ
Definition: nt_native.h:1023
uint16_t * PWSTR
Definition: typedefs.h:54
static void _LoadResources(HINSTANCE hinstDLL)
Definition: main.c:88
BOOL WINAPI DllFreeSplMem(PVOID pMem)
Definition: memory.c:112
BOOL WINAPI LocalmonClosePort(HANDLE hPort)
Definition: ports.c:457
LIST_ENTRY XcvHandles
Definition: precomp.h:40
BOOL WINAPI LocalmonWritePort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuf, PDWORD pcbWritten)
Definition: ports.c:997
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
struct _MONITOR2 MONITOR2
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
void WINAPI LocalmonShutdown(HANDLE hMonitor)
Definition: main.c:112
#define DLL_PROCESS_ATTACH
Definition: compat.h:120
DWORD cbLocalPort
Definition: main.c:12
#define InsertTailList(ListHead, Entry)
BOOL WINAPI LocalmonSetPortTimeOuts(HANDLE hPort, LPCOMMTIMEOUTS lpCTO, DWORD Reserved)
Definition: ports.c:790
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define DWORD
Definition: nt_native.h:44
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static IN DWORD IN LPVOID lpvReserved
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _LOCALMON_PORT LOCALMON_PORT
#define IDS_LOCAL_MONITOR
Definition: resource.h:11
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI LocalmonGetPrinterDataFromPort(HANDLE hPort, DWORD ControlID, PWSTR pValueName, PWSTR lpInBuffer, DWORD cbInBuffer, PWSTR lpOutBuffer, DWORD cbOutBuffer, PDWORD lpcbReturned)
Definition: ports.c:631
BOOL WINAPI LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle)
Definition: ports.c:685
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2853
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
static HANDLE(WINAPI *pGetProcessHandleFromHwnd)(HWND)
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
BOOL WINAPI LocalmonStartDocPort(HANDLE hPort, PWSTR pPrinterName, DWORD JobId, DWORD Level, PBYTE pDocInfo)
Definition: ports.c:897
LIST_ENTRY FilePorts
Definition: precomp.h:38
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
LIST_ENTRY RegistryPorts
Definition: precomp.h:39
#define TRACE(s)
Definition: solgame.cpp:4
BOOL WINAPI LocalmonEnumPorts(HANDLE hMonitor, PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: ports.c:531
PWSTR pwszPortName
Definition: precomp.h:64
__wchar_t WCHAR
Definition: xmlstorage.h:180
static __inline BOOL _IsNEPort(PCWSTR pwszPortName)
Definition: main.c:56
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
PLOCALMON_HANDLE pLocalmon
Definition: precomp.h:62
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:409
CRITICAL_SECTION Section
Definition: precomp.h:37
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3686
static const WCHAR L[]
Definition: oid.c:1250
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
static const WCHAR Cleanup[]
Definition: register.c:80
HANDLE hFile
Definition: precomp.h:60
PCWSTR pwszLocalPort
Definition: main.c:14
#define ERR(fmt,...)
Definition: debug.h:109
#define IDS_LOCAL_PORT
Definition: resource.h:10
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
PCWSTR pwszLocalMonitor
Definition: main.c:13
PMONITOR2 WINAPI InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor)
Definition: main.c:151
BOOL WINAPI LocalmonXcvClosePort(HANDLE hXcv)
Definition: xcv.c:343
BOOL WINAPI LocalmonEndDocPort(HANDLE hPort)
Definition: ports.c:494
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
PVOID WINAPI DllAllocSplMem(DWORD dwBytes)
Definition: memory.c:95
BOOL WINAPI LocalmonReadPort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuffer, PDWORD pcbRead)
Definition: ports.c:844
GLfloat GLfloat p
Definition: glext.h:8902
BYTE * PBYTE
Definition: pedump.c:66
DWORD cbLocalMonitor
Definition: main.c:11
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
base of all file and directory entries
Definition: entries.h:82
struct _LOCALMON_HANDLE * PLOCALMON_HANDLE
static MONITOR2 _MonitorFunctions
Definition: main.c:17
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
Definition: main.c:26
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
DWORD WINAPI LocalmonXcvDataPort(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
Definition: xcv.c:365