mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 00:43:21 +00:00
7bffb70353
WinSpool : Implement missing API. Sync/Port from wine. Setting it to fast track for needed testing of the later GDI code. Leaving Fix-me debug prints on. Local tree has WinSpool_winetest turned on. So no debug noise during normal ReactOS operation. SpoolSS : Reordered header types. Have more Spl function to be added while SpoolSV is being coded to forward to LocalSpl. Based on wine and old research from the GDI code.
596 lines
18 KiB
C
596 lines
18 KiB
C
/*
|
|
* PROJECT: ReactOS Spooler API
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Functions related to Ports
|
|
* COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
#include <marshalling/ports.h>
|
|
|
|
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.
|
|
//
|
|
BOOL WINAPI
|
|
StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
|
|
{
|
|
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);
|
|
}
|
|
|
|
|
|
BOOL WINAPI
|
|
AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName)
|
|
{
|
|
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;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
AddPortExW(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
|
|
{
|
|
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;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
AddPortW(PWSTR pName, HWND hWnd, PWSTR pMonitorName)
|
|
{
|
|
TRACE("AddPortW(%S, %p, %S)\n", pName, hWnd, pMonitorName);
|
|
return StartPortThread(pName, hWnd, pMonitorName, (FARPROC)_RpcAddPort);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
ConfigurePortA(PSTR pName, HWND hWnd, PSTR pPortName)
|
|
{
|
|
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;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
ConfigurePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
|
|
{
|
|
TRACE("ConfigurePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
|
|
return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcConfigurePort);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName)
|
|
{
|
|
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;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
DeletePortW(PWSTR pName, HWND hWnd, PWSTR pPortName)
|
|
{
|
|
TRACE("DeletePortW(%S, %p, %S)\n", pName, hWnd, pPortName);
|
|
return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcDeletePort);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
EnumPortsA(PSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
{
|
|
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);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
{
|
|
DWORD dwErrorCode;
|
|
|
|
TRACE("EnumPortsW(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
// 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.
|
|
ASSERT(Level >= 1 && Level <= 2);
|
|
MarshallUpStructuresArray(cbBuf, pPorts, *pcReturned, pPortInfoMarshalling[Level]->pInfo, pPortInfoMarshalling[Level]->cbStructureSize, TRUE);
|
|
}
|
|
|
|
SetLastError(dwErrorCode);
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
SetPortA(PSTR pName, PSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
|
|
{
|
|
LPWSTR NameW = NULL;
|
|
LPWSTR PortNameW = NULL;
|
|
PORT_INFO_3W pi3W;
|
|
PORT_INFO_3A *pi3A;
|
|
DWORD len;
|
|
BOOL res;
|
|
|
|
TRACE("SetPortA(%s, %s, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo);
|
|
|
|
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;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
SetPortW(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
|
|
{
|
|
DWORD dwErrorCode;
|
|
WINSPOOL_PORT_CONTAINER PortInfoContainer;
|
|
|
|
TRACE("SetPortW(%S, %S, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo);
|
|
|
|
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);
|
|
}
|