mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
3ca217621d
Fix WinSpool API regressions. Fix typos and debug prints.
612 lines
18 KiB
C
612 lines
18 KiB
C
/*
|
|
* PROJECT: ReactOS Local Port Monitor
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Implementation of Xcv* and support functions
|
|
* COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
static DWORD
|
|
_HandleAddPort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
DWORD res, cbPortName;
|
|
HKEY hroot;
|
|
HKEY hToken = NULL;
|
|
PLOCALMON_PORT pPort;
|
|
PLOCALMON_HANDLE pLocalmon = pXcv->pLocalmon;
|
|
PWSTR PortName = (PWSTR)pInputData;
|
|
|
|
FIXME("LcmXcvAddPort : %s\n", debugstr_w( (LPWSTR) PortName ) );
|
|
|
|
if (!pLocalmon )
|
|
{
|
|
res = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// This action can only happen at SERVER_ACCESS_ADMINISTER access level.
|
|
if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
|
|
{
|
|
res = ERROR_ACCESS_DENIED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Switch to the SYSTEM context for modifying the registry.
|
|
hToken = RevertToPrinterSelf();
|
|
if (!hToken)
|
|
{
|
|
res = GetLastError();
|
|
ERR("RevertToPrinterSelf failed with error %lu!\n", res);
|
|
goto Cleanup;
|
|
}
|
|
|
|
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
|
|
if (res == ERROR_SUCCESS)
|
|
{
|
|
if ( DoesPortExist( PortName ) )
|
|
{
|
|
RegCloseKey(hroot);
|
|
FIXME("=> %u\n", ERROR_ALREADY_EXISTS);
|
|
res = ERROR_ALREADY_EXISTS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
cbPortName = (wcslen( PortName ) + 1) * sizeof(WCHAR);
|
|
|
|
// Create a new LOCALMON_PORT structure for it.
|
|
pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + cbPortName);
|
|
if (!pPort)
|
|
{
|
|
res = ERROR_NOT_ENOUGH_MEMORY;
|
|
RegCloseKey( hroot );
|
|
goto Cleanup;
|
|
}
|
|
memset( pPort, 0, sizeof(LOCALMON_PORT) + cbPortName );
|
|
|
|
pPort->hFile = INVALID_HANDLE_VALUE;
|
|
pPort->pLocalmon = pLocalmon;
|
|
pPort->pwszPortName = wcscpy( (PWSTR)(pPort+1), PortName );
|
|
|
|
// Insert it into the Registry list.
|
|
InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry);
|
|
|
|
res = RegSetValueExW(hroot, PortName, 0, REG_SZ, (const BYTE *) L"", sizeof(L""));
|
|
RegCloseKey(hroot);
|
|
}
|
|
|
|
FIXME("=> %u\n", res);
|
|
|
|
Cleanup:
|
|
if (hToken) ImpersonatePrinterClient(hToken);
|
|
SetLastError(res);
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* @name _HandleConfigureLPTPortCommandOK
|
|
*
|
|
* Writes the value for "TransmissionRetryTimeout" to the registry. Checks for granted SERVER_ACCESS_ADMINISTER access.
|
|
* Actually the opposite of _HandleGetTransmissionRetryTimeout, but name kept for compatibility.
|
|
*
|
|
* @param pXcv
|
|
* Pointer to the LOCALMON_XCV structure of the currently opened Xcv port.
|
|
*
|
|
* @param pInputData
|
|
* Pointer to a Unicode string containing the value to be written to the registry.
|
|
*
|
|
* @param pcbOutputNeeded
|
|
* Pointer to a DWORD that will be zeroed on return.
|
|
*
|
|
* @return
|
|
* An error code indicating success or failure.
|
|
*/
|
|
static DWORD
|
|
_HandleConfigureLPTPortCommandOK(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
DWORD cbBuffer;
|
|
DWORD dwErrorCode;
|
|
HKEY hKey = NULL;
|
|
HKEY hToken = NULL;
|
|
|
|
// Sanity checks
|
|
if (!pXcv || !pInputData || !pcbOutputNeeded)
|
|
{
|
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*pcbOutputNeeded = 0;
|
|
|
|
// This action can only happen at SERVER_ACCESS_ADMINISTER access level.
|
|
if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
|
|
{
|
|
dwErrorCode = ERROR_ACCESS_DENIED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Switch to the SYSTEM context for modifying the registry.
|
|
hToken = RevertToPrinterSelf();
|
|
if (!hToken)
|
|
{
|
|
dwErrorCode = GetLastError();
|
|
ERR("RevertToPrinterSelf failed with error %lu!\n", dwErrorCode);
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Open the key where our value is stored.
|
|
dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_SET_VALUE, &hKey);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
|
|
goto Cleanup;
|
|
}
|
|
|
|
// We don't use cbInputData here, because the buffer pInputData could be bigger than the data it contains.
|
|
cbBuffer = (wcslen((PWSTR)pInputData) + 1) * sizeof(WCHAR);
|
|
|
|
// Write the value to the registry.
|
|
dwErrorCode = (DWORD)RegSetValueExW(hKey, L"TransmissionRetryTimeout", 0, REG_SZ, pInputData, cbBuffer);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode);
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
|
|
if (hToken)
|
|
ImpersonatePrinterClient(hToken);
|
|
|
|
return dwErrorCode;
|
|
}
|
|
|
|
static DWORD
|
|
_HandleDeletePort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
DWORD res;
|
|
HKEY hroot;
|
|
HKEY hToken = NULL;
|
|
PLOCALMON_HANDLE pLocalmon = pXcv->pLocalmon;
|
|
PLOCALMON_PORT pPort = NULL;
|
|
PLIST_ENTRY pEntry;
|
|
PWSTR pPortName = (PWSTR)pInputData;
|
|
|
|
FIXME("LcmXcvDeletePort : %s\n", debugstr_w( pPortName ) );
|
|
|
|
if (!pLocalmon )
|
|
{
|
|
res = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// This action can only happen at SERVER_ACCESS_ADMINISTER access level.
|
|
if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
|
|
{
|
|
res = ERROR_ACCESS_DENIED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Switch to the SYSTEM context for modifying the registry.
|
|
hToken = RevertToPrinterSelf();
|
|
if (!hToken)
|
|
{
|
|
res = GetLastError();
|
|
ERR("RevertToPrinterSelf failed with error %lu!\n", res);
|
|
goto Cleanup;
|
|
}
|
|
|
|
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", &hroot);
|
|
if ( res == ERROR_SUCCESS )
|
|
{
|
|
res = RegDeleteValueW(hroot, pPortName );
|
|
|
|
RegCloseKey(hroot);
|
|
|
|
if ( res == ERROR_SUCCESS )
|
|
{
|
|
EnterCriticalSection(&pLocalmon->Section);
|
|
|
|
if (!IsListEmpty(&pLocalmon->RegistryPorts) )
|
|
{
|
|
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
|
|
{
|
|
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
|
|
|
|
if (wcscmp(pPort->pwszPortName, pPortName) == 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&pLocalmon->Section);
|
|
|
|
if ( pPort )
|
|
{
|
|
FIXME("LcmXcvDeletePort removed Port Entry\n");
|
|
EnterCriticalSection(&pPort->pLocalmon->Section);
|
|
RemoveEntryList(&pPort->Entry);
|
|
LeaveCriticalSection(&pPort->pLocalmon->Section);
|
|
|
|
DllFreeSplMem(pPort);
|
|
}
|
|
}
|
|
FIXME("LcmXcvDeletePort => %u with %u\n", res, GetLastError() );
|
|
}
|
|
|
|
Cleanup:
|
|
if (hToken) ImpersonatePrinterClient(hToken);
|
|
SetLastError(res);
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* @name _HandleGetDefaultCommConfig
|
|
*
|
|
* Gets the default configuration of a legacy port.
|
|
* The opposite function is _HandleSetDefaultCommConfig.
|
|
*
|
|
* @param pInputData
|
|
* The port name (without colon!) whose default configuration you want to get.
|
|
*
|
|
* @param pOutputData
|
|
* Pointer to a COMMCONFIG structure that will receive the configuration information.
|
|
*
|
|
* @param cbOutputData
|
|
* Size of the variable pointed to by pOutputData.
|
|
*
|
|
* @param pcbOutputNeeded
|
|
* Pointer to a DWORD that contains the required size for pOutputData on return.
|
|
*
|
|
* @return
|
|
* An error code indicating success or failure.
|
|
*/
|
|
static DWORD
|
|
_HandleGetDefaultCommConfig(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
// Sanity checks
|
|
if (!pInputData || !pcbOutputNeeded)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
*pcbOutputNeeded = sizeof(COMMCONFIG);
|
|
|
|
// Check if the supplied buffer is large enough.
|
|
if (cbOutputData < *pcbOutputNeeded)
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
// Finally get the port configuration.
|
|
if (!GetDefaultCommConfigW((PCWSTR)pInputData, (LPCOMMCONFIG)pOutputData, pcbOutputNeeded))
|
|
return GetLastError();
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @name _HandleGetTransmissionRetryTimeout
|
|
*
|
|
* Reads the value for "TransmissionRetryTimeout" from the registry and converts it to a DWORD.
|
|
* The opposite function is _HandleConfigureLPTPortCommandOK.
|
|
*
|
|
* @param pOutputData
|
|
* Pointer to a DWORD that will receive the timeout value.
|
|
*
|
|
* @param cbOutputData
|
|
* Size of the variable pointed to by pOutputData.
|
|
*
|
|
* @param pcbOutputNeeded
|
|
* Pointer to a DWORD that contains the required size for pOutputData on return.
|
|
*
|
|
* @return
|
|
* An error code indicating success or failure.
|
|
*/
|
|
static DWORD
|
|
_HandleGetTransmissionRetryTimeout(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
DWORD dwTimeout;
|
|
|
|
// Sanity checks
|
|
if (!pOutputData || !pcbOutputNeeded)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
*pcbOutputNeeded = sizeof(DWORD);
|
|
|
|
// Check if the supplied buffer is large enough.
|
|
if (cbOutputData < *pcbOutputNeeded)
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
// Retrieve and copy the number.
|
|
dwTimeout = GetLPTTransmissionRetryTimeout();
|
|
CopyMemory(pOutputData, &dwTimeout, sizeof(DWORD));
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @name _HandleMonitorUI
|
|
*
|
|
* Returns the filename of the associated UI DLL for this Port Monitor.
|
|
*
|
|
* @param pOutputData
|
|
* Pointer to a Unicode string that will receive the DLL filename.
|
|
*
|
|
* @param cbOutputData
|
|
* Size of the variable pointed to by pOutputData.
|
|
*
|
|
* @param pcbOutputNeeded
|
|
* Pointer to a DWORD that contains the required size for pOutputData on return.
|
|
*
|
|
* @return
|
|
* An error code indicating success or failure.
|
|
*/
|
|
static DWORD
|
|
_HandleMonitorUI(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
const WCHAR wszMonitorUI[] = L"LocalUI.dll";
|
|
|
|
// Sanity checks
|
|
if (!pcbOutputNeeded)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
*pcbOutputNeeded = sizeof(wszMonitorUI);
|
|
|
|
// Check if the supplied buffer is large enough.
|
|
if (cbOutputData < *pcbOutputNeeded)
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
if (!pOutputData)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
// Copy the string.
|
|
CopyMemory(pOutputData, wszMonitorUI, sizeof(wszMonitorUI));
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @name _HandlePortExists
|
|
*
|
|
* Checks all Port Monitors installed on the local system to find out if a given port already exists.
|
|
*
|
|
* @param pInputData
|
|
* Pointer to a Unicode string specifying the port name to check.
|
|
*
|
|
* @param pOutputData
|
|
* Pointer to a BOOL that receives the result of the check.
|
|
*
|
|
* @param cbOutputData
|
|
* Size of the variable pointed to by pOutputData.
|
|
*
|
|
* @param pcbOutputNeeded
|
|
* Pointer to a DWORD that contains the required size for pOutputData on return.
|
|
*
|
|
* @return
|
|
* An error code indicating success or failure.
|
|
*/
|
|
static DWORD
|
|
_HandlePortExists(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
// Sanity checks
|
|
if (!pInputData || !pOutputData || !pcbOutputNeeded)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
*pcbOutputNeeded = sizeof(BOOL);
|
|
|
|
// Check if the supplied buffer is large enough.
|
|
if (cbOutputData < *pcbOutputNeeded)
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
// Return the check result and error code.
|
|
*(PBOOL)pOutputData = DoesPortExist((PCWSTR)pInputData);
|
|
return GetLastError();
|
|
}
|
|
|
|
static DWORD
|
|
_HandlePortIsValid(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
DWORD res;
|
|
|
|
TRACE("HandlePortIsValid : pInputData %s\n", debugstr_w( (LPWSTR) pInputData));
|
|
|
|
res = GetTypeFromName((LPCWSTR) pInputData);
|
|
|
|
TRACE("HandlePortIsValid : detected as %u\n", res);
|
|
|
|
/* names, that we have recognized, are valid */
|
|
if (res) return ERROR_SUCCESS;
|
|
|
|
TRACE("=> %u\n", GetLastError());
|
|
|
|
/* ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND or something else */
|
|
return GetLastError();
|
|
}
|
|
|
|
/**
|
|
* @name _HandleSetDefaultCommConfig
|
|
*
|
|
* Sets the default configuration of a legacy port. Checks for granted SERVER_ACCESS_ADMINISTER access.
|
|
* You have to supply the port name (with colon!) in XcvOpenPort.
|
|
* The opposite function is _HandleGetDefaultCommConfig.
|
|
*
|
|
* @param pXcv
|
|
* Pointer to the LOCALMON_XCV structure of the currently opened Xcv port.
|
|
*
|
|
* @param pInputData
|
|
* Pointer to the COMMCONFIG structure that shall be passed to SetDefaultCommConfigW.
|
|
*
|
|
* @param pcbOutputNeeded
|
|
* Pointer to a DWORD that will be zeroed on return.
|
|
*
|
|
* @return
|
|
* An error code indicating success or failure.
|
|
*/
|
|
static DWORD
|
|
_HandleSetDefaultCommConfig(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
DWORD dwErrorCode;
|
|
HANDLE hToken = NULL;
|
|
LPCOMMCONFIG pCommConfig;
|
|
PWSTR pwszPortNameWithoutColon = NULL;
|
|
|
|
// Sanity checks
|
|
// pwszObject needs to be at least 2 characters long to be a port name with a trailing colon.
|
|
if (!pXcv || !pXcv->pwszObject || !pXcv->pwszObject[0] || !pXcv->pwszObject[1] || !pInputData || !pcbOutputNeeded)
|
|
{
|
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*pcbOutputNeeded = 0;
|
|
|
|
// This action can only happen at SERVER_ACCESS_ADMINISTER access level.
|
|
if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER))
|
|
{
|
|
dwErrorCode = ERROR_ACCESS_DENIED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// SetDefaultCommConfigW needs the port name without colon.
|
|
dwErrorCode = GetPortNameWithoutColon(pXcv->pwszObject, &pwszPortNameWithoutColon);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
goto Cleanup;
|
|
|
|
// Switch to the SYSTEM context for setting the port configuration.
|
|
hToken = RevertToPrinterSelf();
|
|
if (!hToken)
|
|
{
|
|
dwErrorCode = GetLastError();
|
|
ERR("RevertToPrinterSelf failed with error %lu!\n", dwErrorCode);
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Finally pass the parameters to SetDefaultCommConfigW.
|
|
pCommConfig = (LPCOMMCONFIG)pInputData;
|
|
if (!SetDefaultCommConfigW(pwszPortNameWithoutColon, pCommConfig, pCommConfig->dwSize))
|
|
{
|
|
dwErrorCode = GetLastError();
|
|
ERR("SetDefaultCommConfigW failed with error %lu!\n", dwErrorCode);
|
|
goto Cleanup;
|
|
}
|
|
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
|
|
Cleanup:
|
|
if (hToken)
|
|
ImpersonatePrinterClient(hToken);
|
|
|
|
if (pwszPortNameWithoutColon)
|
|
DllFreeSplMem(pwszPortNameWithoutColon);
|
|
|
|
return dwErrorCode;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
LocalmonXcvClosePort(HANDLE hXcv)
|
|
{
|
|
PLOCALMON_XCV pXcv = (PLOCALMON_XCV)hXcv;
|
|
|
|
TRACE("LocalmonXcvClosePort(%p)\n", hXcv);
|
|
|
|
// Sanity checks
|
|
if (!pXcv)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
// Remove it from the list and free the memory.
|
|
EnterCriticalSection(&pXcv->pLocalmon->Section);
|
|
RemoveEntryList(&pXcv->Entry);
|
|
LeaveCriticalSection(&pXcv->pLocalmon->Section);
|
|
DllFreeSplMem(pXcv);
|
|
|
|
SetLastError(ERROR_SUCCESS);
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
LocalmonXcvDataPort(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
|
|
{
|
|
FIXME("LocalmonXcvDataPort(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
|
|
|
|
// Sanity checks
|
|
if (!pszDataName)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
// Call the appropriate handler for the requested data name.
|
|
if (wcscmp(pszDataName, L"AddPort") == 0)
|
|
return _HandleAddPort((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded);
|
|
|
|
if (wcscmp(pszDataName, L"ConfigureLPTPortCommandOK") == 0)
|
|
return _HandleConfigureLPTPortCommandOK((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded);
|
|
|
|
if (wcscmp(pszDataName, L"DeletePort") == 0)
|
|
return _HandleDeletePort((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded);
|
|
|
|
if (wcscmp(pszDataName, L"GetDefaultCommConfig") == 0)
|
|
return _HandleGetDefaultCommConfig(pInputData, pOutputData, cbOutputData, pcbOutputNeeded);
|
|
|
|
if (wcscmp(pszDataName, L"GetTransmissionRetryTimeout") == 0)
|
|
return _HandleGetTransmissionRetryTimeout(pOutputData, cbOutputData, pcbOutputNeeded);
|
|
|
|
if (wcscmp(pszDataName, L"MonitorUI") == 0)
|
|
return _HandleMonitorUI(pOutputData, cbOutputData, pcbOutputNeeded);
|
|
|
|
if (wcscmp(pszDataName, L"PortExists") == 0)
|
|
return _HandlePortExists(pInputData, pOutputData, cbOutputData, pcbOutputNeeded);
|
|
|
|
if (wcscmp(pszDataName, L"PortIsValid") == 0)
|
|
return _HandlePortIsValid(pInputData, pOutputData, cbOutputData, pcbOutputNeeded);
|
|
|
|
if (wcscmp(pszDataName, L"SetDefaultCommConfig") == 0)
|
|
return _HandleSetDefaultCommConfig((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded);
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
LocalmonXcvOpenPort(HANDLE hMonitor, PCWSTR pwszObject, ACCESS_MASK GrantedAccess, PHANDLE phXcv)
|
|
{
|
|
DWORD cbObject = 0;
|
|
DWORD dwErrorCode;
|
|
PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
|
|
PLOCALMON_XCV pXcv;
|
|
|
|
FIXME("LocalmonXcvOpenPort(%p, %S, %lu, %p)\n", hMonitor, pwszObject, GrantedAccess, phXcv);
|
|
|
|
// Sanity checks
|
|
if (!pLocalmon || !phXcv)
|
|
{
|
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (pwszObject)
|
|
cbObject = (wcslen(pwszObject) + 1) * sizeof(WCHAR);
|
|
|
|
// Create a new LOCALMON_XCV structure and fill the relevant fields.
|
|
pXcv = DllAllocSplMem(sizeof(LOCALMON_XCV) + cbObject);
|
|
if (!pXcv)
|
|
{
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
|
goto Cleanup;
|
|
}
|
|
|
|
pXcv->pLocalmon = pLocalmon;
|
|
pXcv->GrantedAccess = GrantedAccess;
|
|
|
|
if (cbObject)
|
|
{
|
|
pXcv->pwszObject = (PWSTR)((PBYTE)pXcv + sizeof(LOCALMON_XCV));
|
|
CopyMemory(pXcv->pwszObject, pwszObject, cbObject);
|
|
}
|
|
|
|
InsertTailList(&pLocalmon->XcvHandles, &pXcv->Entry);
|
|
|
|
// Return it as the Xcv handle.
|
|
*phXcv = (HANDLE)pXcv;
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
|
|
Cleanup:
|
|
SetLastError(dwErrorCode);
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
}
|