[LOCALMON, LOCALSPL]
[reactos.git] / reactos / win32ss / printing / monitors / localmon / tools.c
1 /*
2 * PROJECT: ReactOS Local Port Monitor
3 * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
4 * PURPOSE: Various support functions shared by multiple files
5 * COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 /**
11 * @name DoesPortExist
12 *
13 * Checks all Port Monitors installed on the local system to find out if a given port already exists.
14 *
15 * @param pwszPortName
16 * The port name to check.
17 *
18 * @return
19 * TRUE if a port with that name already exists on the local system.
20 * If the return value is FALSE, either the port doesn't exist or an error occurred.
21 * Use GetLastError in this case to check the error case.
22 */
23 BOOL
24 DoesPortExist(PCWSTR pwszPortName)
25 {
26 BOOL bReturnValue = FALSE;
27 DWORD cbNeeded;
28 DWORD dwErrorCode;
29 DWORD dwReturned;
30 DWORD i;
31 PPORT_INFO_1W p;
32 PPORT_INFO_1W pPortInfo1 = NULL;
33
34 // Determine the required buffer size.
35 EnumPortsW(NULL, 1, NULL, 0, &cbNeeded, &dwReturned);
36 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
37 {
38 dwErrorCode = GetLastError();
39 ERR("EnumPortsW failed with error %lu!\n", dwErrorCode);
40 goto Cleanup;
41 }
42
43 // Allocate a buffer large enough.
44 pPortInfo1 = DllAllocSplMem(cbNeeded);
45 if (!pPortInfo1)
46 {
47 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
48 ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
49 goto Cleanup;
50 }
51
52 // Now get the actual port information.
53 if (!EnumPortsW(NULL, 1, (PBYTE)pPortInfo1, cbNeeded, &cbNeeded, &dwReturned))
54 {
55 dwErrorCode = GetLastError();
56 ERR("EnumPortsW failed with error %lu!\n", dwErrorCode);
57 goto Cleanup;
58 }
59
60 // We were successful! Loop through all returned ports.
61 dwErrorCode = ERROR_SUCCESS;
62 p = pPortInfo1;
63
64 for (i = 0; i < dwReturned; i++)
65 {
66 // Check if this existing port matches our queried one.
67 if (wcsicmp(p->pName, pwszPortName) == 0)
68 {
69 bReturnValue = TRUE;
70 goto Cleanup;
71 }
72
73 p++;
74 }
75
76 Cleanup:
77 if (pPortInfo1)
78 DllFreeSplMem(pPortInfo1);
79
80 SetLastError(dwErrorCode);
81 return bReturnValue;
82 }
83
84 DWORD
85 GetLPTTransmissionRetryTimeout()
86 {
87 DWORD cbBuffer;
88 DWORD dwReturnValue = 90; // Use 90 seconds as default if we fail to read from registry.
89 HKEY hKey;
90 LSTATUS lStatus;
91
92 // Six digits is the most you can enter in Windows' LocalUI.dll.
93 // Larger values make it crash, so introduce a limit here.
94 WCHAR wszBuffer[6 + 1];
95
96 // Open the key where our value is stored.
97 lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_READ, &hKey);
98 if (lStatus != ERROR_SUCCESS)
99 {
100 ERR("RegOpenKeyExW failed with status %ld!\n", lStatus);
101 goto Cleanup;
102 }
103
104 // Query the value.
105 cbBuffer = sizeof(wszBuffer);
106 lStatus = RegQueryValueExW(hKey, L"TransmissionRetryTimeout", NULL, NULL, (PBYTE)wszBuffer, &cbBuffer);
107 if (lStatus != ERROR_SUCCESS)
108 {
109 ERR("RegQueryValueExW failed with status %ld!\n", lStatus);
110 goto Cleanup;
111 }
112
113 // Return it converted to a DWORD.
114 dwReturnValue = wcstoul(wszBuffer, NULL, 10);
115
116 Cleanup:
117 if (hKey)
118 RegCloseKey(hKey);
119
120 return dwReturnValue;
121 }
122
123 /**
124 * @name GetPortNameWithoutColon
125 *
126 * Most of the time, we operate on port names with a trailing colon. But some functions require the name without the trailing colon.
127 * This function checks if the port has a trailing colon and if so, it returns the port name without the colon.
128 *
129 * @param pwszPortName
130 * The port name with colon
131 *
132 * @param ppwszPortNameWithoutColon
133 * Pointer to a PWSTR that will contain the port name without colon.
134 * You have to free this buffer using DllFreeSplMem.
135 *
136 * @return
137 * ERROR_SUCCESS if the port name without colon was successfully copied into the buffer.
138 * ERROR_INVALID_PARAMETER if this port name has no trailing colon.
139 * ERROR_NOT_ENOUGH_MEMORY if memory allocation failed.
140 */
141 DWORD
142 GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon)
143 {
144 DWORD cchPortNameWithoutColon;
145
146 // Compute the string length of pwszPortNameWithoutColon.
147 cchPortNameWithoutColon = wcslen(pwszPortName) - 1;
148
149 // Check if pwszPortName really has a colon as the last character.
150 if (pwszPortName[cchPortNameWithoutColon] != L':')
151 return ERROR_INVALID_PARAMETER;
152
153 // Allocate the output buffer.
154 *ppwszPortNameWithoutColon = DllAllocSplMem((cchPortNameWithoutColon + 1) * sizeof(WCHAR));
155 if (!*ppwszPortNameWithoutColon)
156 {
157 ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
158 return ERROR_NOT_ENOUGH_MEMORY;
159 }
160
161 // Copy the port name without colon into the buffer.
162 // The buffer is already zero-initialized, so no additional null-termination is necessary.
163 CopyMemory(*ppwszPortNameWithoutColon, pwszPortName, cchPortNameWithoutColon * sizeof(WCHAR));
164
165 return ERROR_SUCCESS;
166 }