mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 04:33:32 +00:00
[LOCALMON]
My idea to just care about COM, FILE: and LPT ports was too short-sighted. Apart from selecting a FILE: port that prompts for the output filename at printing, you can also add a port "C:\bla.txt" to always output into that particular file. Even shared network printers can be added as a local port "\\COMPUTERNAME\PrinterName" (and Windows even does that when auto-adding printers found on the network). Note that this is the exception though, shared network printers are normally handled by a different component. Our localmon now handles all valid ports found in the registry. Port name checks were modified to be extra-picky and not let any false positives happen (e.g. trying to print into a file starting with "LPT" shouldn't be treated as printing to an LPT port) svn path=/branches/colins-printing-for-freedom/; revision=68402
This commit is contained in:
parent
1f52401541
commit
afb3ba35d8
5 changed files with 165 additions and 60 deletions
|
@ -38,6 +38,52 @@ static MONITOR2 _MonitorFunctions = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name _IsNEPort
|
||||||
|
*
|
||||||
|
* Checks if the given port name is a virtual Ne port.
|
||||||
|
* A virtual Ne port may appear in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports and can have the formats
|
||||||
|
* Ne00:, Ne01:, Ne-02:, Ne456:
|
||||||
|
* This check is extra picky to not cause false positives (like file name ports starting with "Ne").
|
||||||
|
*
|
||||||
|
* @param pwszPortName
|
||||||
|
* The port name to check.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* TRUE if this is definitely a virtual Ne port, FALSE if not.
|
||||||
|
*/
|
||||||
|
static __inline BOOL
|
||||||
|
_IsNEPort(PCWSTR pwszPortName)
|
||||||
|
{
|
||||||
|
PCWSTR p = pwszPortName;
|
||||||
|
|
||||||
|
// First character needs to be 'N' (uppercase or lowercase)
|
||||||
|
if (*p != L'N' && *p != L'n')
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Next character needs to be 'E' (uppercase or lowercase)
|
||||||
|
p++;
|
||||||
|
if (*p != L'E' && *p != L'e')
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// An optional hyphen may follow now.
|
||||||
|
p++;
|
||||||
|
if (*p == L'-')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
// Now an arbitrary number of digits may follow.
|
||||||
|
while (*p >= L'0' && *p <= L'9')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
// Finally, the virtual Ne port must be terminated by a colon.
|
||||||
|
if (*p != ':')
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// If this is the end of the string, we have a virtual Ne port.
|
||||||
|
p++;
|
||||||
|
return (*p == L'\0');
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_LoadResources(HINSTANCE hinstDLL)
|
_LoadResources(HINSTANCE hinstDLL)
|
||||||
{
|
{
|
||||||
|
@ -165,8 +211,16 @@ InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This Port Monitor supports COM, FILE and LPT ports. Skip all others.
|
// pwszPortName can be one of the following to be valid for this Port Monitor:
|
||||||
if (_wcsnicmp(pPort->pwszPortName, L"COM", 3) != 0 && _wcsicmp(pPort->pwszPortName, L"FILE:") != 0 && _wcsnicmp(pPort->pwszPortName, L"LPT", 3) != 0)
|
// COMx: - Physical COM port
|
||||||
|
// LPTx: - Physical LPT port (or redirected one using "net use LPT1 ...")
|
||||||
|
// FILE: - Opens a prompt that asks for an output filename
|
||||||
|
// C:\bla.txt - Redirection into the file "C:\bla.txt"
|
||||||
|
// \\COMPUTERNAME\PrinterName - Redirection to a shared network printer installed as a local port
|
||||||
|
//
|
||||||
|
// We can't detect valid and invalid ones by the name, so we can only exclude empty ports and the virtual "Ne00:", "Ne01:", ... ports.
|
||||||
|
// Skip the invalid ones here.
|
||||||
|
if (!cchPortName || _IsNEPort(pPort->pwszPortName))
|
||||||
{
|
{
|
||||||
DllFreeSplMem(pPort);
|
DllFreeSplMem(pPort);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -17,33 +17,76 @@ static const DWORD cchNonspooledPrefix = _countof(wszNonspooledPrefix) - 1;
|
||||||
* @name _GetNonspooledPortName
|
* @name _GetNonspooledPortName
|
||||||
*
|
*
|
||||||
* Prepends "NONSPOOLED_" to a port name without colon.
|
* Prepends "NONSPOOLED_" to a port name without colon.
|
||||||
* You have to free the returned buffer using DllFreeSplMem.
|
|
||||||
*
|
*
|
||||||
* @param pwszPortNameWithoutColon
|
* @param pwszPortNameWithoutColon
|
||||||
* Result of a previous GetPortNameWithoutColon call.
|
* Result of a previous GetPortNameWithoutColon call.
|
||||||
*
|
*
|
||||||
|
* @param ppwszNonspooledPortName
|
||||||
|
* Pointer to a buffer that will contain the NONSPOOLED port name.
|
||||||
|
* You have to free this buffer using DllFreeSplMem.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* Buffer containing the NONSPOOLED port name or NULL in case of failure.
|
* ERROR_SUCCESS if the NONSPOOLED port name was successfully copied into the buffer.
|
||||||
|
* ERROR_NOT_ENOUGH_MEMORY if memory allocation failed.
|
||||||
*/
|
*/
|
||||||
static __inline PWSTR
|
static __inline DWORD
|
||||||
_GetNonspooledPortName(PCWSTR pwszPortNameWithoutColon)
|
_GetNonspooledPortName(PCWSTR pwszPortNameWithoutColon, PWSTR* ppwszNonspooledPortName)
|
||||||
{
|
{
|
||||||
DWORD cchPortNameWithoutColon;
|
DWORD cchPortNameWithoutColon;
|
||||||
PWSTR pwszNonspooledPortName;
|
|
||||||
|
|
||||||
cchPortNameWithoutColon = wcslen(pwszPortNameWithoutColon);
|
cchPortNameWithoutColon = wcslen(pwszPortNameWithoutColon);
|
||||||
|
|
||||||
pwszNonspooledPortName = DllAllocSplMem((cchNonspooledPrefix + cchPortNameWithoutColon + 1) * sizeof(WCHAR));
|
*ppwszNonspooledPortName = DllAllocSplMem((cchNonspooledPrefix + cchPortNameWithoutColon + 1) * sizeof(WCHAR));
|
||||||
if (!pwszNonspooledPortName)
|
if (!*ppwszNonspooledPortName)
|
||||||
{
|
{
|
||||||
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
return NULL;
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory(pwszNonspooledPortName, wszNonspooledPrefix, cchNonspooledPrefix * sizeof(WCHAR));
|
CopyMemory(*ppwszNonspooledPortName, wszNonspooledPrefix, cchNonspooledPrefix * sizeof(WCHAR));
|
||||||
CopyMemory(&pwszNonspooledPortName[cchNonspooledPrefix], pwszPortNameWithoutColon, (cchPortNameWithoutColon + 1) * sizeof(WCHAR));
|
CopyMemory(&(*ppwszNonspooledPortName)[cchNonspooledPrefix], pwszPortNameWithoutColon, (cchPortNameWithoutColon + 1) * sizeof(WCHAR));
|
||||||
|
|
||||||
return pwszNonspooledPortName;
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name _IsLegacyPort
|
||||||
|
*
|
||||||
|
* Checks if the given port name is a legacy port (COM or LPT).
|
||||||
|
* This check is extra picky to not cause false positives (like file name ports starting with "COM" or "LPT").
|
||||||
|
*
|
||||||
|
* @param pwszPortName
|
||||||
|
* The port name to check.
|
||||||
|
*
|
||||||
|
* @param pwszPortType
|
||||||
|
* L"COM" or L"LPT"
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* TRUE if this is definitely the asked legacy port, FALSE if not.
|
||||||
|
*/
|
||||||
|
static __inline BOOL
|
||||||
|
_IsLegacyPort(PCWSTR pwszPortName, PCWSTR pwszPortType)
|
||||||
|
{
|
||||||
|
const DWORD cchPortType = 3;
|
||||||
|
PCWSTR p = pwszPortName;
|
||||||
|
|
||||||
|
// The port name must begin with pwszPortType.
|
||||||
|
if (_wcsnicmp(p, pwszPortType, cchPortType) != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
p += cchPortType;
|
||||||
|
|
||||||
|
// Now an arbitrary number of digits may follow.
|
||||||
|
while (*p >= L'0' && *p <= L'9')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
// Finally, the legacy port must be terminated by a colon.
|
||||||
|
if (*p != ':')
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// If this is the end of the string, we have a legacy port.
|
||||||
|
p++;
|
||||||
|
return (*p == L'\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,11 +121,9 @@ _ClosePortHandles(PLOCALMON_PORT pPort)
|
||||||
pPort->pwszMapping = NULL;
|
pPort->pwszMapping = NULL;
|
||||||
|
|
||||||
// Finally get the required strings and remove the DOS device definition for the NONSPOOLED port.
|
// Finally get the required strings and remove the DOS device definition for the NONSPOOLED port.
|
||||||
pwszPortNameWithoutColon = GetPortNameWithoutColon(pPort->pwszPortName);
|
if (GetPortNameWithoutColon(pPort->pwszPortName, &pwszPortNameWithoutColon) == ERROR_SUCCESS)
|
||||||
if (pwszPortNameWithoutColon)
|
|
||||||
{
|
{
|
||||||
pwszNonspooledPortName = _GetNonspooledPortName(pwszPortNameWithoutColon);
|
if (_GetNonspooledPortName(pwszPortNameWithoutColon, &pwszNonspooledPortName) == ERROR_SUCCESS)
|
||||||
if (pwszNonspooledPortName)
|
|
||||||
{
|
{
|
||||||
DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL);
|
DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL);
|
||||||
DllFreeSplMem(pwszNonspooledPortName);
|
DllFreeSplMem(pwszNonspooledPortName);
|
||||||
|
@ -105,8 +146,7 @@ _ClosePortHandles(PLOCALMON_PORT pPort)
|
||||||
* @return
|
* @return
|
||||||
* TRUE if a NONSPOOLED port was successfully created, FALSE otherwise.
|
* TRUE if a NONSPOOLED port was successfully created, FALSE otherwise.
|
||||||
* A more specific error code can be obtained through GetLastError.
|
* A more specific error code can be obtained through GetLastError.
|
||||||
* In particular, if the return value is FALSE and GetLastError returns ERROR_SUCCESS, no NONSPOOLED port is needed,
|
* In particular, if the return value is FALSE and GetLastError returns ERROR_SUCCESS, no NONSPOOLED port is needed for this port.
|
||||||
* because no system-wide device definition is available.
|
|
||||||
*/
|
*/
|
||||||
static BOOL
|
static BOOL
|
||||||
_CreateNonspooledPort(PLOCALMON_PORT pPort)
|
_CreateNonspooledPort(PLOCALMON_PORT pPort)
|
||||||
|
@ -129,10 +169,16 @@ _CreateNonspooledPort(PLOCALMON_PORT pPort)
|
||||||
PWSTR pwszPortNameWithoutColon = NULL;
|
PWSTR pwszPortNameWithoutColon = NULL;
|
||||||
|
|
||||||
// We need the port name without the trailing colon.
|
// We need the port name without the trailing colon.
|
||||||
pwszPortNameWithoutColon = GetPortNameWithoutColon(pPort->pwszPortName);
|
dwErrorCode = GetPortNameWithoutColon(pPort->pwszPortName, &pwszPortNameWithoutColon);
|
||||||
if (!pwszPortNameWithoutColon)
|
if (dwErrorCode == ERROR_INVALID_PARAMETER)
|
||||||
{
|
{
|
||||||
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
// This port has no trailing colon, so we also need no NONSPOOLED mapping for it.
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
else if (dwErrorCode != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
// Another unexpected failure.
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,12 +268,9 @@ _CreateNonspooledPort(PLOCALMON_PORT pPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We now want to create a DOS device "NONSPOOLED_<PortName>" to this mapping, so that we're able to open it through CreateFileW.
|
// We now want to create a DOS device "NONSPOOLED_<PortName>" to this mapping, so that we're able to open it through CreateFileW.
|
||||||
pwszNonspooledPortName = _GetNonspooledPortName(pwszPortNameWithoutColon);
|
dwErrorCode = _GetNonspooledPortName(pwszPortNameWithoutColon, &pwszNonspooledPortName);
|
||||||
if (!pwszNonspooledPortName)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
|
||||||
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
// Delete a possibly existing NONSPOOLED device before creating the new one, so we don't stack up device definitions.
|
// Delete a possibly existing NONSPOOLED device before creating the new one, so we don't stack up device definitions.
|
||||||
DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL);
|
DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL);
|
||||||
|
@ -493,7 +536,7 @@ LocalmonClosePort(HANDLE hPort)
|
||||||
pPort->hPrinter = NULL;
|
pPort->hPrinter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free virtual FILE ports which were created in LocalmonOpenPort.
|
// Free virtual FILE: ports which were created in LocalmonOpenPort.
|
||||||
if (pPort->PortType == PortType_FILE)
|
if (pPort->PortType == PortType_FILE)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&pPort->pLocalmon->Section);
|
EnterCriticalSection(&pPort->pLocalmon->Section);
|
||||||
|
@ -712,11 +755,8 @@ LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle)
|
||||||
// Even if this API is called OpenPort, port file handles aren't always opened here :-P
|
// Even if this API is called OpenPort, port file handles aren't always opened here :-P
|
||||||
// Windows only does this for physical LPT ports here to enable bidirectional communication with the printer outside of jobs (using ReadPort and WritePort).
|
// Windows only does this for physical LPT ports here to enable bidirectional communication with the printer outside of jobs (using ReadPort and WritePort).
|
||||||
// The others are only opened per job in StartDocPort.
|
// The others are only opened per job in StartDocPort.
|
||||||
if (_wcsnicmp(pName, L"LPT", 3) == 0)
|
if (_IsLegacyPort(pName, L"LPT"))
|
||||||
{
|
{
|
||||||
// Treat all ports as other LPT ports until we can definitely say that it's a physical one.
|
|
||||||
pPort->PortType = PortType_OtherLPT;
|
|
||||||
|
|
||||||
// Try to create a NONSPOOLED port and open it.
|
// Try to create a NONSPOOLED port and open it.
|
||||||
if (_CreateNonspooledPort(pPort))
|
if (_CreateNonspooledPort(pPort))
|
||||||
{
|
{
|
||||||
|
@ -740,9 +780,9 @@ LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (_IsLegacyPort(pName, L"COM"))
|
||||||
{
|
{
|
||||||
// This can only be a COM port.
|
// COM ports can't be redirected over the network, so this is a physical one.
|
||||||
pPort->PortType = PortType_PhysicalCOM;
|
pPort->PortType = PortType_PhysicalCOM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -948,13 +988,17 @@ LocalmonStartDocPort(HANDLE hPort, PWSTR pPrinterName, DWORD JobId, DWORD Level,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This is a COM port or a non-physical LPT port. We open NONSPOOLED ports for these per job.
|
// This can be:
|
||||||
|
// - a physical COM port
|
||||||
|
// - a non-physical LPT port (e.g. with "net use LPT1 ...")
|
||||||
|
// - any other port (e.g. a file or a shared printer installed as a local port)
|
||||||
|
//
|
||||||
|
// For all these cases, we try to create a NONSPOOLED port per job.
|
||||||
|
// If _CreateNonspooledPort reports that no NONSPOOLED port is necessary, we can just open the port name.
|
||||||
if (!_CreateNonspooledPort(pPort))
|
if (!_CreateNonspooledPort(pPort))
|
||||||
{
|
{
|
||||||
if (GetLastError() == ERROR_SUCCESS)
|
if (GetLastError() == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
// This is a user-local instead of a system-wide port.
|
|
||||||
// Such local ports haven't been remapped by the spooler, so we can just open them.
|
|
||||||
pPort->hFile = CreateFileW(pPort->pwszPortName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
|
pPort->hFile = CreateFileW(pPort->pwszPortName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
|
||||||
if (pPort->hFile == INVALID_HANDLE_VALUE)
|
if (pPort->hFile == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,8 +35,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(localmon);
|
||||||
typedef struct _LOCALMON_HANDLE
|
typedef struct _LOCALMON_HANDLE
|
||||||
{
|
{
|
||||||
CRITICAL_SECTION Section; /** Critical Section for modifying or reading the ports. */
|
CRITICAL_SECTION Section; /** Critical Section for modifying or reading the ports. */
|
||||||
LIST_ENTRY FilePorts; /** Virtual ports created for every document that's redirected to an output file. */
|
LIST_ENTRY FilePorts; /** Ports created when a document is printed on FILE: and the user entered a file name. */
|
||||||
LIST_ENTRY RegistryPorts; /** COM, FILE: and LPT ports loaded from the local registry. */
|
LIST_ENTRY RegistryPorts; /** Valid ports loaded from the local registry. */
|
||||||
LIST_ENTRY XcvHandles; /** Xcv handles created with LocalmonXcvOpenPort. */
|
LIST_ENTRY XcvHandles; /** Xcv handles created with LocalmonXcvOpenPort. */
|
||||||
}
|
}
|
||||||
LOCALMON_HANDLE, *PLOCALMON_HANDLE;
|
LOCALMON_HANDLE, *PLOCALMON_HANDLE;
|
||||||
|
@ -49,10 +49,10 @@ typedef struct _LOCALMON_PORT
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry;
|
||||||
enum {
|
enum {
|
||||||
PortType_FILE, /** A virtual port for redirecting the document into a file. */
|
PortType_Other = 0, /** Any port that doesn't belong into the other categories (default). */
|
||||||
|
PortType_FILE, /** A port created when a document is printed on FILE: and the user entered a file name. */
|
||||||
PortType_PhysicalCOM, /** A physical serial port (COM) */
|
PortType_PhysicalCOM, /** A physical serial port (COM) */
|
||||||
PortType_PhysicalLPT, /** A physical parallel port (LPT) */
|
PortType_PhysicalLPT /** A physical parallel port (LPT) */
|
||||||
PortType_OtherLPT /** A non-physical parallel port (e.g. a redirected one over network using "net use LPT1 ...") */
|
|
||||||
}
|
}
|
||||||
PortType;
|
PortType;
|
||||||
BOOL bStartedDoc; /** Whether a document has been started with StartDocPort. */
|
BOOL bStartedDoc; /** Whether a document has been started with StartDocPort. */
|
||||||
|
@ -99,7 +99,7 @@ BOOL WINAPI LocalmonWritePort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuf, PDWORD p
|
||||||
// tools.c
|
// tools.c
|
||||||
BOOL DoesPortExist(PCWSTR pwszPortName);
|
BOOL DoesPortExist(PCWSTR pwszPortName);
|
||||||
DWORD GetLPTTransmissionRetryTimeout();
|
DWORD GetLPTTransmissionRetryTimeout();
|
||||||
PWSTR GetPortNameWithoutColon(PCWSTR pwszPortName);
|
DWORD GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon);
|
||||||
|
|
||||||
// xcv.c
|
// xcv.c
|
||||||
BOOL WINAPI LocalmonXcvClosePort(HANDLE hXcv);
|
BOOL WINAPI LocalmonXcvClosePort(HANDLE hXcv);
|
||||||
|
|
|
@ -124,32 +124,42 @@ Cleanup:
|
||||||
* @name GetPortNameWithoutColon
|
* @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.
|
* 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 returns the port name without the colon. You have to free the returned buffer using DllFreeSplMem.
|
* This function checks if the port has a trailing colon and if so, it returns the port name without the colon.
|
||||||
*
|
*
|
||||||
* @param pwszPortName
|
* @param pwszPortName
|
||||||
* The port name with colon
|
* 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
|
* @return
|
||||||
* Buffer containing the port name without a colon or NULL in case of failure.
|
* 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.
|
||||||
*/
|
*/
|
||||||
PWSTR
|
DWORD
|
||||||
GetPortNameWithoutColon(PCWSTR pwszPortName)
|
GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon)
|
||||||
{
|
{
|
||||||
DWORD cchPortName;
|
DWORD cchPortName;
|
||||||
PWSTR pwszPortNameWithoutColon;
|
|
||||||
|
|
||||||
// Every port in our port list has a trailing colon, so we just need to remove the last character of the string.
|
// Compute the string length of pwszPortNameWithoutColon.
|
||||||
cchPortName = wcslen(pwszPortName) - 1;
|
cchPortName = wcslen(pwszPortName) - 1;
|
||||||
|
|
||||||
pwszPortNameWithoutColon = DllAllocSplMem((cchPortName + 1) * sizeof(WCHAR));
|
// Check if pwszPortName really has a colon as the last character.
|
||||||
if (!pwszPortNameWithoutColon)
|
if (pwszPortName[cchPortName] != L':')
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// It has, so allocate a buffer and copy the port name without colon into it.
|
||||||
|
*ppwszPortNameWithoutColon = DllAllocSplMem((cchPortName + 1) * sizeof(WCHAR));
|
||||||
|
if (!*ppwszPortNameWithoutColon)
|
||||||
{
|
{
|
||||||
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
return NULL;
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyMemory(pwszPortNameWithoutColon, pwszPortName, cchPortName * sizeof(WCHAR));
|
CopyMemory(*ppwszPortNameWithoutColon, pwszPortName, cchPortName * sizeof(WCHAR));
|
||||||
pwszPortNameWithoutColon[cchPortName] = 0;
|
*ppwszPortNameWithoutColon[cchPortName] = 0;
|
||||||
|
|
||||||
return pwszPortNameWithoutColon;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,12 +305,9 @@ _HandleSetDefaultCommConfig(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutp
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaultCommConfigW needs the port name without colon.
|
// SetDefaultCommConfigW needs the port name without colon.
|
||||||
pwszPortNameWithoutColon = GetPortNameWithoutColon(pXcv->pwszObject);
|
dwErrorCode = GetPortNameWithoutColon(pXcv->pwszObject, &pwszPortNameWithoutColon);
|
||||||
if (!pwszPortNameWithoutColon)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
|
||||||
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to the SYSTEM context for setting the port configuration.
|
// Switch to the SYSTEM context for setting the port configuration.
|
||||||
hToken = RevertToPrinterSelf();
|
hToken = RevertToPrinterSelf();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue