1 /* 2 * PROJECT: ReactOS Local Port Monitor 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 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(VOID) 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 } 167