reactos/win32ss/printing/monitors/localmon/tools.c

166 lines
4.9 KiB
C

/*
* PROJECT: ReactOS Local Port Monitor
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Various support functions shared by multiple files
* COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
/**
* @name DoesPortExist
*
* Checks all Port Monitors installed on the local system to find out if a given port already exists.
*
* @param pwszPortName
* The port name to check.
*
* @return
* TRUE if a port with that name already exists on the local system.
* If the return value is FALSE, either the port doesn't exist or an error occurred.
* Use GetLastError in this case to check the error case.
*/
BOOL
DoesPortExist(PCWSTR pwszPortName)
{
BOOL bReturnValue = FALSE;
DWORD cbNeeded;
DWORD dwErrorCode;
DWORD dwReturned;
DWORD i;
PPORT_INFO_1W p;
PPORT_INFO_1W pPortInfo1 = NULL;
// Determine the required buffer size.
EnumPortsW(NULL, 1, NULL, 0, &cbNeeded, &dwReturned);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
dwErrorCode = GetLastError();
ERR("EnumPortsW failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// Allocate a buffer large enough.
pPortInfo1 = DllAllocSplMem(cbNeeded);
if (!pPortInfo1)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
goto Cleanup;
}
// Now get the actual port information.
if (!EnumPortsW(NULL, 1, (PBYTE)pPortInfo1, cbNeeded, &cbNeeded, &dwReturned))
{
dwErrorCode = GetLastError();
ERR("EnumPortsW failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// We were successful! Loop through all returned ports.
dwErrorCode = ERROR_SUCCESS;
p = pPortInfo1;
for (i = 0; i < dwReturned; i++)
{
// Check if this existing port matches our queried one.
if (wcsicmp(p->pName, pwszPortName) == 0)
{
bReturnValue = TRUE;
goto Cleanup;
}
p++;
}
Cleanup:
if (pPortInfo1)
DllFreeSplMem(pPortInfo1);
SetLastError(dwErrorCode);
return bReturnValue;
}
DWORD
GetLPTTransmissionRetryTimeout(VOID)
{
DWORD cbBuffer;
DWORD dwReturnValue = 90; // Use 90 seconds as default if we fail to read from registry.
HKEY hKey;
LSTATUS lStatus;
// Six digits is the most you can enter in Windows' LocalUI.dll.
// Larger values make it crash, so introduce a limit here.
WCHAR wszBuffer[6 + 1];
// Open the key where our value is stored.
lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_READ, &hKey);
if (lStatus != ERROR_SUCCESS)
{
ERR("RegOpenKeyExW failed with status %ld!\n", lStatus);
goto Cleanup;
}
// Query the value.
cbBuffer = sizeof(wszBuffer);
lStatus = RegQueryValueExW(hKey, L"TransmissionRetryTimeout", NULL, NULL, (PBYTE)wszBuffer, &cbBuffer);
if (lStatus != ERROR_SUCCESS)
{
ERR("RegQueryValueExW failed with status %ld!\n", lStatus);
goto Cleanup;
}
// Return it converted to a DWORD.
dwReturnValue = wcstoul(wszBuffer, NULL, 10);
Cleanup:
if (hKey)
RegCloseKey(hKey);
return dwReturnValue;
}
/**
* @name GetPortNameWithoutColon
*
* Most of the time, we operate on port names with a trailing colon. But some functions require the name without the trailing colon.
* This function checks if the port has a trailing colon and if so, it returns the port name without the colon.
*
* @param pwszPortName
* The port name with colon
*
* @param ppwszPortNameWithoutColon
* Pointer to a PWSTR that will contain the port name without colon.
* You have to free this buffer using DllFreeSplMem.
*
* @return
* ERROR_SUCCESS if the port name without colon was successfully copied into the buffer.
* ERROR_INVALID_PARAMETER if this port name has no trailing colon.
* ERROR_NOT_ENOUGH_MEMORY if memory allocation failed.
*/
DWORD
GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon)
{
DWORD cchPortNameWithoutColon;
// Compute the string length of pwszPortNameWithoutColon.
cchPortNameWithoutColon = wcslen(pwszPortName) - 1;
// Check if pwszPortName really has a colon as the last character.
if (pwszPortName[cchPortNameWithoutColon] != L':')
return ERROR_INVALID_PARAMETER;
// Allocate the output buffer.
*ppwszPortNameWithoutColon = DllAllocSplMem((cchPortNameWithoutColon + 1) * sizeof(WCHAR));
if (!*ppwszPortNameWithoutColon)
{
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
return ERROR_NOT_ENOUGH_MEMORY;
}
// Copy the port name without colon into the buffer.
// The buffer is already zero-initialized, so no additional null-termination is necessary.
CopyMemory(*ppwszPortNameWithoutColon, pwszPortName, cchPortNameWithoutColon * sizeof(WCHAR));
return ERROR_SUCCESS;
}