ReactOS  0.4.15-dev-1150-g593bcce
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  LocalmonAddPort, // pfnAddPort moved to localui.dll since w2k, but~
28  LocalmonAddPortEx, // pfnAddPortEx
29  LocalmonConfigurePort, // pfnConfigurePort moved to localui.dll since w2k, but~
30  LocalmonDeletePort, // pfnDeletePort moved to localui.dll since w2k, but~
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  PLIST_ENTRY pEntry;
118 
119  TRACE("LocalmonShutdown(%p)\n", hMonitor);
120 
121  pLocalmon = (PLOCALMON_HANDLE)hMonitor;
122 
123  if ( pLocalmon->Sig != SIGLCMMON )
124  {
125  ERR("LocalmonShutdown : Invalid Monitor Handle\n",hMonitor);
126  return;
127  }
128 
129  // Close all virtual file ports.
130  if (!IsListEmpty(&pLocalmon->FilePorts))
131  {
132  for (pEntry = pLocalmon->FilePorts.Flink; pEntry != &pLocalmon->FilePorts; pEntry = pEntry->Flink)
133  {
134  pPort = CONTAINING_RECORD(&pLocalmon->FilePorts.Flink, LOCALMON_PORT, Entry);
135  LocalmonClosePort((HANDLE)pPort);
136  }
137  }
138 
139  // Do the same for the open Xcv ports.
140  if (!IsListEmpty(&pLocalmon->XcvHandles))
141  {
142  for (pEntry = pLocalmon->XcvHandles.Flink; pEntry != &pLocalmon->XcvHandles; pEntry = pEntry->Flink)
143  {
144  pXcv = CONTAINING_RECORD(pEntry, LOCALMON_XCV, Entry);
146  }
147  }
148 
149  // Now close all registry ports, remove them from the list and free their memory.
150  if (!IsListEmpty(&pLocalmon->RegistryPorts))
151  {
152  for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
153  {
154  pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
155  if ( LocalmonClosePort((HANDLE)pPort) ) continue;
156  RemoveEntryList(&pPort->Entry);
157  DllFreeSplMem(pPort);
158  }
159  }
160 
161  // Finally clean the LOCALMON_HANDLE structure itself.
162  DeleteCriticalSection(&pLocalmon->Section);
163  DllFreeSplMem(pLocalmon);
164 }
165 
168 {
169  DWORD cchMaxPortName;
170  DWORD cchPortName;
171  DWORD dwErrorCode;
172  DWORD dwPortCount;
173  DWORD i;
174  HKEY hKey;
175  PMONITOR2 pReturnValue = NULL;
176  PLOCALMON_HANDLE pLocalmon;
177  PLOCALMON_PORT pPort = NULL;
178 
179  TRACE("InitializePrintMonitor2(%p, %p)\n", pMonitorInit, phMonitor);
180 
181  // Create a new LOCALMON_HANDLE structure.
182  pLocalmon = DllAllocSplMem(sizeof(LOCALMON_HANDLE));
183  pLocalmon->Sig = SIGLCMMON;
184  InitializeCriticalSection(&pLocalmon->Section);
185  InitializeListHead(&pLocalmon->FilePorts);
186  InitializeListHead(&pLocalmon->RegistryPorts);
187  InitializeListHead(&pLocalmon->XcvHandles);
188 
189  // The Local Spooler Port Monitor doesn't need to care about the given registry key and functions.
190  // Instead it uses a well-known registry key for getting its information about local ports. Open this one.
191  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", 0, KEY_READ, &hKey);
192  if (dwErrorCode != ERROR_SUCCESS)
193  {
194  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
195  goto Cleanup;
196  }
197 
198  // Get the number of ports and the length of the largest port name.
199  dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwPortCount, &cchMaxPortName, NULL, NULL, NULL);
200  if (dwErrorCode != ERROR_SUCCESS)
201  {
202  ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
203  goto Cleanup;
204  }
205 
206  // Loop through all ports.
207  for (i = 0; i < dwPortCount; i++)
208  {
209  // Allocate memory for a new LOCALMON_PORT structure and its name.
210  pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + (cchMaxPortName + 1) * sizeof(WCHAR));
211  if (!pPort)
212  {
213  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
214  ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
215  goto Cleanup;
216  }
217 
218  pPort->Sig = SIGLCMPORT;
219  pPort->pLocalmon = pLocalmon;
220  pPort->hFile = INVALID_HANDLE_VALUE;
221  pPort->pwszPortName = (PWSTR)(pPort+1);
222 
223  // Get the port name.
224  cchPortName = cchMaxPortName + 1;
225  dwErrorCode = (DWORD)RegEnumValueW(hKey, i, pPort->pwszPortName, &cchPortName, NULL, NULL, NULL, NULL);
226  if (dwErrorCode != ERROR_SUCCESS)
227  {
228  ERR("RegEnumValueW failed with status %lu!\n", dwErrorCode);
229  goto Cleanup;
230  }
231 
232  // pwszPortName can be one of the following to be valid for this Port Monitor:
233  // COMx: - Physical COM port
234  // LPTx: - Physical LPT port (or redirected one using "net use LPT1 ...")
235  // FILE: - Opens a prompt that asks for an output filename
236  // C:\bla.txt - Redirection into the file "C:\bla.txt"
237  // \\COMPUTERNAME\PrinterName - Redirection to a shared network printer installed as a local port
238  //
239  // We can't detect valid and invalid ones by the name, so we can only exclude empty ports and the virtual "Ne00:", "Ne01:", ... ports.
240  // Skip the invalid ones here.
241  if (!cchPortName || _IsNEPort(pPort->pwszPortName))
242  {
243  DllFreeSplMem(pPort);
244  pPort = NULL;
245  continue;
246  }
247 
248  // Add it to the list.
249  InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
250  TRACE("InitializePrintMonitor2 Port : %s \n",debugstr_w(pPort->pwszPortName));
251 
252  // Don't let the cleanup routine free this.
253  pPort = NULL;
254  }
255 
256  // Return our handle and the Print Monitor functions.
257  *phMonitor = (HANDLE)pLocalmon;
258  pReturnValue = &_MonitorFunctions;
259  dwErrorCode = ERROR_SUCCESS;
260 
261 Cleanup:
262  if (pPort)
263  DllFreeSplMem(pPort);
264 
265  SetLastError(dwErrorCode);
266  return pReturnValue;
267 }
BOOL WINAPI LocalmonXcvOpenPort(HANDLE hMonitor, PCWSTR pszObject, ACCESS_MASK GrantedAccess, PHANDLE phXcv)
Definition: xcv.c:566
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define ERROR_SUCCESS
Definition: deptool.c:10
LIST_ENTRY Entry
Definition: precomp.h:54
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
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:456
LIST_ENTRY XcvHandles
Definition: precomp.h:44
BOOL WINAPI LocalmonWritePort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuf, PDWORD pcbWritten)
Definition: ports.c:996
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:479
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
void WINAPI LocalmonShutdown(HANDLE hMonitor)
Definition: main.c:112
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
DWORD cbLocalPort
Definition: main.c:12
#define InsertTailList(ListHead, Entry)
BOOL WINAPI LocalmonSetPortTimeOuts(HANDLE hPort, LPCOMMTIMEOUTS lpCTO, DWORD Reserved)
Definition: ports.c:789
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
DWORD Sig
Definition: precomp.h:57
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
#define FALSE
Definition: types.h:117
#define IDS_LOCAL_MONITOR
Definition: resource.h:11
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI LocalmonDeletePort(HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName)
Definition: ports.c:1197
#define debugstr_w
Definition: kernel32.h:32
BOOL WINAPI LocalmonGetPrinterDataFromPort(HANDLE hPort, DWORD ControlID, PWSTR pValueName, PWSTR lpInBuffer, DWORD cbInBuffer, PWSTR lpOutBuffer, DWORD cbOutBuffer, PDWORD lpcbReturned)
Definition: ports.c:630
BOOL WINAPI LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle)
Definition: ports.c:684
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
#define SIGLCMPORT
Definition: precomp.h:31
static HANDLE(WINAPI *pGetProcessHandleFromHwnd)(HWND)
BOOL WINAPI LocalmonAddPort(HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pMonitorName)
Definition: ports.c:1137
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:896
LIST_ENTRY FilePorts
Definition: precomp.h:42
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY RegistryPorts
Definition: precomp.h:43
#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:530
PWSTR pwszPortName
Definition: precomp.h:55
__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:56
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:500
CRITICAL_SECTION Section
Definition: precomp.h:40
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:454
#define SIGLCMMON
Definition: precomp.h:30
Definition: typedefs.h:119
static const WCHAR Cleanup[]
Definition: register.c:80
HANDLE hFile
Definition: precomp.h:67
PCWSTR pwszLocalPort
Definition: main.c:14
#define ERR(fmt,...)
Definition: debug.h:110
BOOL WINAPI LocalmonConfigurePort(HANDLE hMonitor, LPWSTR pName, HWND hWnd, LPWSTR pPortName)
Definition: ports.c:1189
#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:167
BOOL WINAPI LocalmonXcvClosePort(HANDLE hXcv)
Definition: xcv.c:502
BOOL WINAPI LocalmonEndDocPort(HANDLE hPort)
Definition: ports.c:493
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 LocalmonAddPortEx(HANDLE hMonitor, LPWSTR pName, DWORD Level, LPBYTE lpBuffer, LPWSTR lpMonitorName)
Definition: ports.c:1054
BOOL WINAPI LocalmonReadPort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuffer, PDWORD pcbRead)
Definition: ports.c:843
GLfloat GLfloat p
Definition: glext.h:8902
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:526