2015-07-17 10:57:10 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Spooler API
|
2017-09-29 17:18:19 +00:00
|
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
2015-07-17 10:57:10 +00:00
|
|
|
* PURPOSE: Functions related to Ports
|
2018-01-17 11:52:12 +00:00
|
|
|
* COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org)
|
2015-07-17 10:57:10 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
2018-01-17 11:52:12 +00:00
|
|
|
#include <marshalling/ports.h>
|
2015-07-17 10:57:10 +00:00
|
|
|
|
2020-08-04 02:07:58 +00:00
|
|
|
typedef struct _PORTTHREADINFO
|
|
|
|
{
|
|
|
|
LPWSTR pName;
|
|
|
|
HWND hWnd;
|
|
|
|
LPWSTR pPortName;
|
|
|
|
FARPROC fpFunction;
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
HANDLE hEvent;
|
|
|
|
} PORTTHREADINFO, *PPORTTHREADINFO;
|
|
|
|
|
|
|
|
VOID WINAPI
|
|
|
|
IntPortThread( PPORTTHREADINFO pPortThreadInfo )
|
|
|
|
{
|
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
pPortThreadInfo->dwErrorCode = (*pPortThreadInfo->fpFunction)( pPortThreadInfo->pName, pPortThreadInfo->hWnd, pPortThreadInfo->pPortName);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
pPortThreadInfo->dwErrorCode = RpcExceptionCode();
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
SetEvent( pPortThreadInfo->hEvent );
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Start a thread to wait on a printer port.
|
|
|
|
//
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
2020-08-04 02:07:58 +00:00
|
|
|
StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
|
2017-12-09 12:35:42 +00:00
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
PORTTHREADINFO PortThreadInfo;
|
|
|
|
HANDLE htHandle;
|
|
|
|
MSG Msg;
|
|
|
|
DWORD tid;
|
|
|
|
|
|
|
|
if ( hWnd ) EnableWindow( hWnd, FALSE );
|
|
|
|
|
|
|
|
PortThreadInfo.pName = pName;
|
|
|
|
PortThreadInfo.hWnd = hWnd;
|
|
|
|
PortThreadInfo.pPortName = pPortName;
|
|
|
|
PortThreadInfo.fpFunction = fpFunction;
|
|
|
|
PortThreadInfo.dwErrorCode = ERROR_SUCCESS;
|
|
|
|
PortThreadInfo.hEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
|
|
|
|
|
|
|
|
htHandle = CreateThread( NULL,
|
|
|
|
32*1024,
|
|
|
|
(LPTHREAD_START_ROUTINE)IntPortThread,
|
|
|
|
&PortThreadInfo,
|
|
|
|
0,
|
|
|
|
&tid );
|
|
|
|
|
|
|
|
CloseHandle( htHandle );
|
|
|
|
|
|
|
|
while ( MsgWaitForMultipleObjects( 1, &PortThreadInfo.hEvent, FALSE, INFINITE, QS_SENDMESSAGE|QS_ALLEVENTS ) == 1 )
|
|
|
|
{
|
|
|
|
while ( PeekMessageW( &Msg, NULL, 0, 0, PM_REMOVE ) )
|
|
|
|
{
|
|
|
|
TranslateMessage( &Msg );
|
|
|
|
DispatchMessageW( &Msg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle( PortThreadInfo.hEvent );
|
|
|
|
|
|
|
|
if ( hWnd )
|
|
|
|
{
|
|
|
|
EnableWindow(hWnd, TRUE);
|
|
|
|
SetForegroundWindow(hWnd);
|
|
|
|
SetFocus(hWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetLastError(PortThreadInfo.dwErrorCode);
|
|
|
|
return (PortThreadInfo.dwErrorCode == ERROR_SUCCESS);
|
2017-12-09 12:35:42 +00:00
|
|
|
}
|
|
|
|
|
2020-08-04 02:07:58 +00:00
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
2020-08-04 02:07:58 +00:00
|
|
|
AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName)
|
2017-12-09 12:35:42 +00:00
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
LPWSTR nameW = NULL;
|
|
|
|
LPWSTR monitorW = NULL;
|
|
|
|
DWORD len;
|
|
|
|
BOOL res;
|
|
|
|
|
|
|
|
TRACE("AddPortA(%s, %p, %s)\n",debugstr_a(pName), hWnd, debugstr_a(pMonitorName));
|
|
|
|
|
|
|
|
if (pName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
|
|
|
|
nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pMonitorName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, NULL, 0);
|
|
|
|
monitorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, monitorW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
res = AddPortW(nameW, hWnd, monitorW);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, nameW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, monitorW);
|
|
|
|
|
|
|
|
return res;
|
2017-12-09 12:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
AddPortExW(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
|
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
WINSPOOL_PORT_CONTAINER PortInfoContainer;
|
|
|
|
WINSPOOL_PORT_VAR_CONTAINER PortVarContainer;
|
|
|
|
WINSPOOL_PORT_INFO_FF *pPortInfoFF;
|
|
|
|
|
|
|
|
TRACE("AddPortExW(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName);
|
|
|
|
|
|
|
|
switch (Level)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
// FIXME!!!! Only Level 1 is supported? See note in wine winspool test info.c : line 575.
|
|
|
|
PortInfoContainer.PortInfo.pPortInfo1 = (WINSPOOL_PORT_INFO_1*)lpBuffer;
|
|
|
|
PortInfoContainer.Level = Level;
|
|
|
|
PortVarContainer.cbMonitorData = 0;
|
|
|
|
PortVarContainer.pMonitorData = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xFFFFFFFF:
|
|
|
|
pPortInfoFF = (WINSPOOL_PORT_INFO_FF*)lpBuffer;
|
|
|
|
PortInfoContainer.PortInfo.pPortInfoFF = pPortInfoFF;
|
|
|
|
PortInfoContainer.Level = Level;
|
|
|
|
PortVarContainer.cbMonitorData = pPortInfoFF->cbMonitorData;
|
|
|
|
PortVarContainer.pMonitorData = pPortInfoFF->pMonitorData;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ERR("Level = %d, unsupported!\n", Level);
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcAddPortEx(pName, &PortInfoContainer, &PortVarContainer, lpMonitorName);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
AddPortExA(PSTR pName, DWORD Level, PBYTE lpBuffer, PSTR lpMonitorName)
|
|
|
|
{
|
|
|
|
PORT_INFO_1W pi1W;
|
|
|
|
PORT_INFO_1A * pi1A;
|
|
|
|
LPWSTR nameW = NULL;
|
|
|
|
LPWSTR monitorW = NULL;
|
|
|
|
DWORD len;
|
|
|
|
BOOL res = FALSE;
|
|
|
|
WINSPOOL_PORT_INFO_FF *pPortInfoFF, PortInfoFF;
|
|
|
|
|
|
|
|
pi1A = (PORT_INFO_1A *)lpBuffer;
|
|
|
|
pPortInfoFF = (WINSPOOL_PORT_INFO_FF*)lpBuffer;
|
|
|
|
|
|
|
|
TRACE("AddPortExA(%s, %d, %p, %s): %s\n", debugstr_a(pName), Level, lpBuffer, debugstr_a(lpMonitorName), debugstr_a(pi1A ? pi1A->pName : NULL));
|
|
|
|
|
|
|
|
if ( !lpBuffer || !lpMonitorName )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
|
|
|
|
nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpMonitorName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, lpMonitorName, -1, NULL, 0);
|
|
|
|
monitorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, lpMonitorName, -1, monitorW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
pi1W.pName = NULL;
|
|
|
|
ZeroMemory( &PortInfoFF, sizeof(WINSPOOL_PORT_INFO_FF));
|
|
|
|
|
|
|
|
switch ( Level )
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
if ( pi1A->pName )
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pi1A->pName, -1, NULL, 0);
|
|
|
|
pi1W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pi1A->pName, -1, pi1W.pName, len);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xFFFFFFFF:
|
|
|
|
//
|
|
|
|
// Remember the calling parameter is Ansi.
|
|
|
|
//
|
|
|
|
if ( !pPortInfoFF->pPortName || !(PCHAR)pPortInfoFF->pPortName )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pPortInfoFF->pPortName, -1, NULL, 0);
|
|
|
|
PortInfoFF.pPortName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pPortInfoFF->pPortName, -1, (LPWSTR)PortInfoFF.pPortName, len);
|
|
|
|
|
|
|
|
PortInfoFF.cbMonitorData = pPortInfoFF->cbMonitorData;
|
|
|
|
PortInfoFF.pMonitorData = pPortInfoFF->pMonitorData;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ERR("Level = %d, unsupported!\n", Level);
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = AddPortExW( nameW, Level, Level == 1 ? (PBYTE)&pi1W : (PBYTE)&PortInfoFF, monitorW );
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (nameW) HeapFree(GetProcessHeap(), 0, nameW);
|
|
|
|
if (monitorW) HeapFree(GetProcessHeap(), 0, monitorW);
|
|
|
|
if (pi1W.pName) HeapFree(GetProcessHeap(), 0, pi1W.pName);
|
|
|
|
if (PortInfoFF.pPortName) HeapFree(GetProcessHeap(), 0, PortInfoFF.pPortName);
|
|
|
|
|
|
|
|
return res;
|
2017-12-09 12:35:42 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 17:59:46 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
AddPortW(PWSTR pName, HWND hWnd, PWSTR pMonitorName)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("AddPortW(%S, %p, %S)\n", pName, hWnd, pMonitorName);
|
2020-08-04 02:07:58 +00:00
|
|
|
return StartPortThread(pName, hWnd, pMonitorName, (FARPROC)_RpcAddPort);
|
2015-07-22 17:59:46 +00:00
|
|
|
}
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
ConfigurePortA(PSTR pName, HWND hWnd, PSTR pPortName)
|
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
LPWSTR nameW = NULL;
|
|
|
|
LPWSTR portW = NULL;
|
|
|
|
INT len;
|
|
|
|
DWORD res;
|
|
|
|
|
|
|
|
TRACE("ConfigurePortA(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName));
|
|
|
|
|
|
|
|
/* convert servername to unicode */
|
|
|
|
if (pName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
|
|
|
|
nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert portname to unicode */
|
|
|
|
if (pPortName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pPortName, -1, NULL, 0);
|
|
|
|
portW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pPortName, -1, portW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
res = ConfigurePortW(nameW, hWnd, portW);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, nameW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, portW);
|
|
|
|
|
|
|
|
return res;
|
2017-12-09 12:35:42 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 17:59:46 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
ConfigurePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("ConfigurePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
|
2020-08-04 02:07:58 +00:00
|
|
|
return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcConfigurePort);
|
2015-07-22 17:59:46 +00:00
|
|
|
}
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName)
|
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
LPWSTR nameW = NULL;
|
|
|
|
LPWSTR portW = NULL;
|
|
|
|
INT len;
|
|
|
|
DWORD res;
|
|
|
|
|
|
|
|
TRACE("DeletePortA(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName));
|
|
|
|
|
|
|
|
/* convert servername to unicode */
|
|
|
|
if (pName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
|
|
|
|
nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert portname to unicode */
|
|
|
|
if (pPortName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pPortName, -1, NULL, 0);
|
|
|
|
portW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pPortName, -1, portW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
res = DeletePortW(nameW, hWnd, portW);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, nameW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, portW);
|
|
|
|
|
|
|
|
return res;
|
2017-12-09 12:35:42 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 17:59:46 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
DeletePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("DeletePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
|
2020-08-04 02:07:58 +00:00
|
|
|
return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcDeletePort);
|
2015-07-22 17:59:46 +00:00
|
|
|
}
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
EnumPortsA(PSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
BOOL res;
|
|
|
|
LPBYTE bufferW = NULL;
|
|
|
|
LPWSTR nameW = NULL;
|
|
|
|
DWORD needed = 0;
|
|
|
|
DWORD numentries = 0;
|
|
|
|
INT len;
|
|
|
|
|
|
|
|
TRACE("EnumPortsA(%s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), Level, pPorts, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
|
|
|
|
/* convert servername to unicode */
|
|
|
|
if (pName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
|
|
|
|
nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len);
|
|
|
|
}
|
|
|
|
/* alloc (userbuffersize*sizeof(WCHAR) and try to enum the Ports */
|
|
|
|
needed = cbBuf * sizeof(WCHAR);
|
|
|
|
if (needed) bufferW = HeapAlloc(GetProcessHeap(), 0, needed);
|
|
|
|
res = EnumPortsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned);
|
|
|
|
|
|
|
|
if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
|
|
|
|
{
|
|
|
|
if (pcbNeeded) needed = *pcbNeeded;
|
|
|
|
/* HeapReAlloc return NULL, when bufferW was NULL */
|
|
|
|
bufferW = (bufferW) ? HeapReAlloc(GetProcessHeap(), 0, bufferW, needed) :
|
|
|
|
HeapAlloc(GetProcessHeap(), 0, needed);
|
|
|
|
|
|
|
|
/* Try again with the large Buffer */
|
|
|
|
res = EnumPortsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned);
|
|
|
|
}
|
|
|
|
needed = pcbNeeded ? *pcbNeeded : 0;
|
|
|
|
numentries = pcReturned ? *pcReturned : 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
W2k require the buffersize from EnumPortsW also for EnumPortsA.
|
|
|
|
We use the smaller Ansi-Size to avoid conflicts with fixed Buffers of old Apps.
|
|
|
|
*/
|
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
/* EnumPortsW collected all Data. Parse them to calculate ANSI-Size */
|
|
|
|
DWORD entrysize = 0;
|
|
|
|
DWORD index;
|
|
|
|
LPSTR ptr;
|
|
|
|
LPPORT_INFO_2W pi2w;
|
|
|
|
LPPORT_INFO_2A pi2a;
|
|
|
|
|
|
|
|
needed = 0;
|
|
|
|
entrysize = (Level == 1) ? sizeof(PORT_INFO_1A) : sizeof(PORT_INFO_2A);
|
|
|
|
|
|
|
|
/* First pass: calculate the size for all Entries */
|
|
|
|
pi2w = (LPPORT_INFO_2W) bufferW;
|
|
|
|
pi2a = (LPPORT_INFO_2A) pPorts;
|
|
|
|
index = 0;
|
|
|
|
while (index < numentries)
|
|
|
|
{
|
|
|
|
index++;
|
|
|
|
needed += entrysize; /* PORT_INFO_?A */
|
|
|
|
TRACE("%p: parsing #%d (%s)\n", pi2w, index, debugstr_w(pi2w->pPortName));
|
|
|
|
|
|
|
|
needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pPortName, -1,
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
if (Level > 1)
|
|
|
|
{
|
|
|
|
needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pMonitorName, -1,
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pDescription, -1,
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
}
|
|
|
|
/* use LPBYTE with entrysize to avoid double code (PORT_INFO_1 + PORT_INFO_2) */
|
|
|
|
pi2w = (LPPORT_INFO_2W) (((LPBYTE)pi2w) + entrysize);
|
|
|
|
pi2a = (LPPORT_INFO_2A) (((LPBYTE)pi2a) + entrysize);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for errors and quit on failure */
|
|
|
|
if (cbBuf < needed)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
res = FALSE;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
len = entrysize * numentries; /* room for all PORT_INFO_?A */
|
|
|
|
ptr = (LPSTR) &pPorts[len]; /* room for strings */
|
|
|
|
cbBuf -= len ; /* free Bytes in the user-Buffer */
|
|
|
|
pi2w = (LPPORT_INFO_2W) bufferW;
|
|
|
|
pi2a = (LPPORT_INFO_2A) pPorts;
|
|
|
|
index = 0;
|
|
|
|
/* Second Pass: Fill the User Buffer (if we have one) */
|
|
|
|
while ((index < numentries) && pPorts)
|
|
|
|
{
|
|
|
|
index++;
|
|
|
|
TRACE("%p: writing PORT_INFO_%dA #%d\n", pi2a, Level, index);
|
|
|
|
pi2a->pPortName = ptr;
|
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, pi2w->pPortName, -1,
|
|
|
|
ptr, cbBuf , NULL, NULL);
|
|
|
|
ptr += len;
|
|
|
|
cbBuf -= len;
|
|
|
|
if (Level > 1)
|
|
|
|
{
|
|
|
|
pi2a->pMonitorName = ptr;
|
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, pi2w->pMonitorName, -1,
|
|
|
|
ptr, cbBuf, NULL, NULL);
|
|
|
|
ptr += len;
|
|
|
|
cbBuf -= len;
|
|
|
|
|
|
|
|
pi2a->pDescription = ptr;
|
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, pi2w->pDescription, -1,
|
|
|
|
ptr, cbBuf, NULL, NULL);
|
|
|
|
ptr += len;
|
|
|
|
cbBuf -= len;
|
|
|
|
|
|
|
|
pi2a->fPortType = pi2w->fPortType;
|
|
|
|
pi2a->Reserved = 0; /* documented: "must be zero" */
|
|
|
|
|
|
|
|
}
|
|
|
|
/* use LPBYTE with entrysize to avoid double code (PORT_INFO_1 + PORT_INFO_2) */
|
|
|
|
pi2w = (LPPORT_INFO_2W) (((LPBYTE)pi2w) + entrysize);
|
|
|
|
pi2a = (LPPORT_INFO_2A) (((LPBYTE)pi2a) + entrysize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (pcbNeeded) *pcbNeeded = needed;
|
|
|
|
if (pcReturned) *pcReturned = (res) ? numentries : 0;
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, nameW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, bufferW);
|
|
|
|
|
|
|
|
TRACE("returning %d with %d (%d byte for %d of %d entries)\n",
|
|
|
|
(res), GetLastError(), needed, (res)? numentries : 0, numentries);
|
|
|
|
|
|
|
|
return (res);
|
2017-12-09 12:35:42 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 10:57:10 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
|
|
{
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("EnumPortsW(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
|
2015-07-17 10:57:10 +00:00
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcEnumPorts failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
// Replace relative offset addresses in the output by absolute pointers.
|
2018-01-17 11:52:12 +00:00
|
|
|
ASSERT(Level >= 1 && Level <= 2);
|
|
|
|
MarshallUpStructuresArray(cbBuf, pPorts, *pcReturned, pPortInfoMarshalling[Level]->pInfo, pPortInfoMarshalling[Level]->cbStructureSize, TRUE);
|
2015-07-17 10:57:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
|
|
}
|
2017-12-09 12:35:42 +00:00
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
SetPortA(PSTR pName, PSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
|
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
LPWSTR NameW = NULL;
|
|
|
|
LPWSTR PortNameW = NULL;
|
|
|
|
PORT_INFO_3W pi3W;
|
|
|
|
PORT_INFO_3A *pi3A;
|
|
|
|
DWORD len;
|
|
|
|
BOOL res;
|
|
|
|
|
2020-08-04 03:23:07 +00:00
|
|
|
pi3A = (PORT_INFO_3A*)pPortInfo;
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
TRACE("SetPortA(%s, %s, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo);
|
2020-08-04 02:07:58 +00:00
|
|
|
|
|
|
|
if ( dwLevel != 3 )
|
|
|
|
{
|
|
|
|
ERR("Level = %d, unsupported!\n", dwLevel);
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0);
|
|
|
|
NameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pName, -1, NameW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pPortName)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pPortName, -1, NULL, 0);
|
|
|
|
PortNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pPortName, -1, PortNameW, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pi3A->pszStatus)
|
|
|
|
{
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, pi3A->pszStatus, -1, NULL, 0);
|
|
|
|
pi3W.pszStatus = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pi3A->pszStatus, -1, pi3W.pszStatus, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
pi3W.dwStatus = pi3A->dwStatus;
|
|
|
|
pi3W.dwSeverity = pi3A->dwSeverity;
|
|
|
|
|
|
|
|
res = SetPortW( NameW, PortNameW, dwLevel, (PBYTE)&pi3W );
|
|
|
|
|
|
|
|
if (NameW) HeapFree(GetProcessHeap(), 0, NameW);
|
|
|
|
if (PortNameW) HeapFree(GetProcessHeap(), 0, PortNameW);
|
|
|
|
if (pi3W.pszStatus) HeapFree(GetProcessHeap(), 0, pi3W.pszStatus);
|
|
|
|
|
|
|
|
return res;
|
2017-12-09 12:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
SetPortW(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
|
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
WINSPOOL_PORT_CONTAINER PortInfoContainer;
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
TRACE("SetPortW(%S, %S, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo);
|
2020-08-04 02:07:58 +00:00
|
|
|
|
|
|
|
if ( dwLevel != 3 )
|
|
|
|
{
|
|
|
|
ERR("Level = %d, unsupported!\n", dwLevel);
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PortInfoContainer.PortInfo.pPortInfo3 = (WINSPOOL_PORT_INFO_3*)pPortInfo;
|
|
|
|
PortInfoContainer.Level = dwLevel;
|
|
|
|
|
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcSetPort(pName, pPortName, &PortInfoContainer);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2017-12-09 12:35:42 +00:00
|
|
|
}
|