2025-04-27 07:49:33 -04:00

130 lines
4.1 KiB
C

#include "precomp.h"
#include <pchrexec.h>
#include "reclient.h"
// ***************************************************************************
LPWSTR MarshallString(LPWSTR wszSrc, PBYTE pBase, ULONG cbMaxBuf,
PBYTE *ppToWrite, DWORD *pcbWritten)
{
DWORD cb;
PBYTE pwszNormalized;
cb = (wcslen(wszSrc) + 1) * sizeof(WCHAR);
if ((*pcbWritten + cb) > cbMaxBuf)
return NULL;
RtlMoveMemory(*ppToWrite, wszSrc, cb);
// the normalized ptr is the current count
pwszNormalized = (PBYTE)(*ppToWrite - pBase);
// cb is always a mutliple of sizeof(WHCAR) so the pointer addition below
// always produces a result that is 2byte aligned (assuming the input was
// 2byte aligned of course)
*ppToWrite += cb;
*pcbWritten += cb;
return (LPWSTR)pwszNormalized;
}
// ***************************************************************************
BOOL CreateRemoteProcessW(ULONG ulSessionId, HANDLE hToken, LPWSTR wszCmdLine,
DWORD fdwCreateFlags, LPSTARTUPINFOW psi,
LPPROCESS_INFORMATION ppi)
{
SPCHExecServRequest *pesreq;
SPCHExecServReply esrep;
DWORD cbWrote, cbRead, cbReq;
WCHAR wszPipeName[MAX_PATH];
BYTE Buf[HANGREP_EXECSVC_BUF_SIZE];
BYTE *pBuf;
BOOL fRet = FALSE;
// validate params
if (hToken == NULL || wszCmdLine == NULL || ppi == NULL || psi == NULL ||
psi->cb != sizeof(STARTUPINFOW))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
wcscpy(wszPipeName, HANGREP_EXECSVC_PIPENAME);
// setup the marshalling- make sure that pBuf is aligned on a 2byte
// boundary beacause we'll be writing WCHAR buffers to it.
ZeroMemory(Buf, sizeof(Buf));
pesreq = (SPCHExecServRequest *)Buf;
cbReq = ((sizeof(SPCHExecServRequest) * sizeof(WCHAR)) + sizeof(WCHAR) - 1) / sizeof(WCHAR);
pBuf = Buf + cbReq;
// set the basic parameters
pesreq->cbESR = sizeof(SPCHExecServRequest);
pesreq->pidReqProcess = GetCurrentProcessId();
pesreq->hToken = hToken;
pesreq->ulSessionId = ulSessionId;
pesreq->fdwCreateFlags = fdwCreateFlags;
// copy in the StartupInfo structure
RtlMoveMemory(&pesreq->si, psi, sizeof(pesreq->si));
// marshall all the strings we send across the wire.
// CommandLine
if (wszCmdLine != NULL)
{
pesreq->wszCmdLine = MarshallString(wszCmdLine, Buf, sizeof(Buf),
&pBuf, &cbReq);
if (pesreq->wszCmdLine == NULL)
goto done;
}
// Desktop
if (psi->lpDesktop)
{
pesreq->si.lpDesktop = MarshallString(psi->lpDesktop, Buf, sizeof(Buf),
&pBuf, &cbReq);
if (pesreq->si.lpDesktop == NULL)
goto done;
}
// Title
if (psi->lpTitle)
{
pesreq->si.lpTitle = MarshallString(psi->lpTitle, Buf, sizeof(Buf),
&pBuf, &cbReq);
if (pesreq->si.lpTitle == NULL)
goto done;
}
// this is always NULL
pesreq->si.lpReserved = NULL;
// set the total size of the message
pesreq->cbTotal = cbReq;
// Send the buffer out to the server- wait at most 2m for this to
// succeed. If it times out, bail.
fRet = CallNamedPipeW(wszPipeName, Buf, cbReq, &esrep, sizeof(esrep),
&cbRead, 120000);
if (fRet == FALSE)
goto done;
// Check the result
fRet = esrep.fRet;
if (fRet == FALSE)
{
SetLastError(esrep.dwErr);
goto done;
}
// We copy the PROCESS_INFO structure from the reply to the caller
// Note: the remote process has kindly duplicated the process & thread
// handles into us, so we can use the values returned as we normally
// would.
RtlMoveMemory(ppi, &esrep.pi, sizeof(PROCESS_INFORMATION));
done:
return fRet;
}