Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1027 lines
39 KiB

/****************************** Module Header ******************************\
* Module Name: ssend.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* Server side sending stubs
*
* 07-06-91 ScottLu Created.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
#define CALLBACKPROC 1
#define SERVERSIDE 1
#include "callback.h"
#define SENDSIDE 1
#define CBBUFSIZE 512
#define PADSIZE (sizeof(ULONG_PTR) - 1)
/*
* Callback setup and control macros
*/
#define SMESSAGECALL(api) \
LRESULT Sfn ## api( \
PWND pwnd, \
UINT msg, \
WPARAM wParam, \
LPARAM lParam, \
ULONG_PTR xParam, \
PROC xpfnProc, \
DWORD dwSCMSFlags, \
PSMS psms)
#define SETUP(api) \
api ## MSG m; \
api ## MSG *mp = &m; \
BYTE Buffer[CBBUFSIZE]; \
PCALLBACKSTATUS pcbs; \
ULONG cbCBStatus; \
ULONG_PTR retval; \
NTSTATUS Status;
#define SETUPDC(api) \
SETUP(api) \
int iDC = 0; \
HDC hdcUse; \
HBITMAP hbmDCGray = NULL;
#define SETUPPWND(api) \
api ## MSG m; \
api ## MSG *mp = &m; \
BYTE Buffer[CBBUFSIZE]; \
PCALLBACKSTATUS pcbs; \
ULONG cbCBStatus; \
ULONG_PTR retval; \
NTSTATUS Status; \
TL tlpwnd; \
CALLBACKWND cbwin; \
PTHREADINFO pti = PtiCurrent(); \
PWND pwndClient = pwnd ? (PWND)((PBYTE)pwnd - pti->ulClientDelta) : NULL; \
UserAssert(pti->ulClientDelta != 0);
#define CALC_SIZE_IN(cb, pstr) \
cb = (pstr)->Length + sizeof(WCHAR); \
if ((pstr)->bAnsi && !fAnsiReceiver) \
cb *= sizeof(WCHAR);
#define CALC_SIZE_OUT(cb, pstr) \
cb = (pstr)->MaximumLength + sizeof(WCHAR); \
if ((pstr)->bAnsi && !fAnsiReceiver) \
cb *= sizeof(WCHAR);
#ifdef FE_SB // CALC_SIZE_OUT_STRING()
#define CALC_SIZE_OUT_STRING(cb, pstr) \
cb = (pstr)->MaximumLength + sizeof(WCHAR); \
if (!(PtiCurrent()->TIF_flags & TIF_ANSILENGTH)) { \
if ((pstr)->bAnsi && !fAnsiReceiver) \
cb *= sizeof(WCHAR); \
}
#endif // FE_SB
#ifdef FE_SB // CALC_SIZE_STRING_OUT()
#define CALC_SIZE_STRING_OUT(cchText) \
try { \
(cchText) = CalcOutputStringSize(pcbs,(cchText),fAnsiSender,fAnsiReceiver); \
} except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
(cchText) = 0; \
MSGERROR(); \
}
#endif // FE_SB
#define BEGINSEND(api) \
mp = &m; \
Buffer; \
{
#define BEGINSENDCAPTURE(api, cCapturePointers, cCaptureBytes, fInput) \
if (cCapturePointers) { \
mp = AllocCallbackMessage(sizeof(m), \
(cCapturePointers), \
(cCaptureBytes), \
Buffer, \
fInput); \
if (mp == NULL) \
goto errorexitnofreemp; \
} else { \
m.CaptureBuf.cbCallback = sizeof(m); \
m.CaptureBuf.cbCapture = 0; \
m.CaptureBuf.cCapturedPointers = 0; \
mp = &m; \
} \
{ \
PTHREADINFO ptiCurrent = PtiCurrent(); \
TL tlPool; \
\
if (mp != &m && (PVOID)mp != (PVOID)Buffer) \
ThreadLockPool(ptiCurrent, mp, &tlPool);
#define BEGINSENDCAPTUREVOIDDC(api, cCapturePointers, cCaptureBytes, fInput) \
hdcUse = CreateCompatiblePublicDC(hdc,&hbmDCGray); \
if (hdcUse == (HDC)NULL) { \
return; \
} \
BEGINSENDCAPTURE(api, cCapturePointers, cCaptureBytes, fInput); \
#define BEGINSENDCAPTUREDC(api, cCapturePointers, nCount, fInput) \
hdcUse = CreateCompatiblePublicDC(hdc,&hbmDCGray); \
if (hdcUse == (HDC)NULL) { \
return FALSE; \
} \
BEGINSENDCAPTURE(api, cCapturePointers, max(pstrSrc->MaximumLength, \
((nCount + 1) * sizeof(WCHAR))), fInput); \
#define LOCKPWND() \
ThreadLock(pwnd, &tlpwnd); \
try { \
cbwin = pti->pClientInfo->CallbackWnd; \
pti->pClientInfo->CallbackWnd.pwnd = pwndClient; \
pti->pClientInfo->CallbackWnd.hwnd = HW(pwnd); \
pti->pClientInfo->CallbackWnd.pActCtx = ((pwnd == NULL) ? NULL : pwnd->pActCtx); \
} except (W32ExceptionHandler(TRUE, RIP_WARNING)) { \
ThreadUnlock(&tlpwnd); \
MSGERROR(); \
}
#define UNLOCKPWND() \
ThreadUnlock(&tlpwnd); \
try { \
pti->pClientInfo->CallbackWnd = cbwin; \
} except (W32ExceptionHandler(TRUE, RIP_WARNING)) { \
MSGERROR(); \
}
#define MAKECALL(api) \
UserAssert(!(PtiCurrent()->TIF_flags & TIF_INCLEANUP)); \
LeaveCrit(); \
Status = KeUserModeCallback( \
FI_ ## api, \
mp, \
sizeof(*mp), \
&pcbs, \
&cbCBStatus); \
EnterCrit();
#define MAKECALLCAPTURE(api) \
UserAssert(!(PtiCurrent()->TIF_flags & TIF_INCLEANUP)); \
LeaveCrit(); \
Status = (DWORD)KeUserModeCallback( \
FI_ ## api, \
mp, \
mp->CaptureBuf.cbCallback, \
&pcbs, \
&cbCBStatus); \
EnterCrit();
#define MAKECALLCAPTUREDC(api) \
iDC = GreSaveDC(hdc); \
MAKECALLCAPTURE(api) \
GreRestoreDC(hdc, iDC); \
iDC = 0; \
if ((hdcUse != hdc) && NT_SUCCESS(Status)) { \
GreBitBlt(hdc, \
0, \
0, \
gpDispInfo->cxGray, \
gpDispInfo->cyGray, \
hdcUse, \
0, \
0, \
SRCCOPY, \
0); \
}
#define CHECKRETURN() \
if (!NT_SUCCESS(Status) || \
cbCBStatus != sizeof(*pcbs)) { \
goto errorexit; \
} \
try { \
retval = ProbeAndReadStructure(&pcbs->retval, ULONG_PTR); \
} except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
MSGERROR(); \
}
#define ENDSEND(type, error) \
return (type)retval; \
goto errorexit; \
} \
errorexit: \
return (type)error
#define CLEANUPSENDCAPTURECOMMONDC() \
if(iDC) { \
GreRestoreDC(hdc, iDC); \
} \
if (hdcUse != hdc) { \
GreDeleteDC(hdcUse); \
GreDeleteObject(hbmDCGray); \
} \
#define BEGIN_ENDSENDCAPTURE(type, error) \
exit:
#define _ENDSENDCAPTURE(type, error) \
if (mp != &m && (PVOID)mp != (PVOID)Buffer) { \
if (mp->CaptureBuf.pvVirtualAddress) { \
NTSTATUS Status; \
SIZE_T ulRegionSize = 0; \
\
Status = ZwFreeVirtualMemory(NtCurrentProcess(),\
&mp->CaptureBuf.pvVirtualAddress, \
&ulRegionSize, \
MEM_RELEASE); \
UserAssert(NT_SUCCESS(Status)); \
} \
ThreadUnlockAndFreePool(ptiCurrent, &tlPool); \
} \
return (type)retval; \
goto errorexit; \
} \
errorexit: \
retval = error; \
goto exit; \
errorexitnofreemp:
#define END_ENDSENDCAPTURE(type, error) \
return (type)error
#define ENDSENDCAPTUREDC(type, error) \
BEGIN_ENDSENDCAPTURE(type, error); \
CLEANUPSENDCAPTURECOMMONDC(); \
_ENDSENDCAPTURE(type, error); \
CLEANUPSENDCAPTURECOMMONDC(); \
END_ENDSENDCAPTURE(type, error)
#define ENDSENDCAPTURE(type, error) \
BEGIN_ENDSENDCAPTURE(type, error); \
_ENDSENDCAPTURE(type, error); \
END_ENDSENDCAPTURE(type, error)
#ifdef FE_SB // ENDSENDCAPTUREOUTSTRING()
#define ENDSENDCAPTUREOUTSTRING(type, error) \
exit: \
if (mp != &m && (PVOID)mp != (PVOID)Buffer) { \
if (mp->CaptureBuf.pvVirtualAddress) { \
NTSTATUS Status; \
SIZE_T ulRegionSize = 0; \
\
Status = ZwFreeVirtualMemory(NtCurrentProcess(),\
&mp->CaptureBuf.pvVirtualAddress, \
&ulRegionSize, \
MEM_RELEASE); \
UserAssert(NT_SUCCESS(Status)); \
} \
ThreadUnlockAndFreePool(ptiCurrent, &tlPool); \
} \
if (bInflateWParam) \
PtiCurrent()->TIF_flags &= ~TIF_ANSILENGTH; \
return (type)retval; \
goto errorexit; \
} \
errorexit: \
retval = error; \
goto exit; \
errorexitnofreemp: \
if (bInflateWParam) \
PtiCurrent()->TIF_flags &= ~TIF_ANSILENGTH; \
return (type)error
#endif // FE_SB
#define BEGIN_ENDSENDCAPTUREVOID() \
errorexit:
#define _ENDSENDCAPTUREVOID() \
if (mp != &m && (PVOID)mp != (PVOID)Buffer) { \
if (mp->CaptureBuf.pvVirtualAddress) { \
NTSTATUS Status; \
SIZE_T ulRegionSize = 0; \
\
Status = ZwFreeVirtualMemory(NtCurrentProcess(),\
&mp->CaptureBuf.pvVirtualAddress, \
&ulRegionSize, \
MEM_RELEASE); \
UserAssert(NT_SUCCESS(Status)); \
} \
ThreadUnlockAndFreePool(ptiCurrent, &tlPool); \
} \
return; \
} \
errorexitnofreemp:
#define END_ENDSENDCAPTUREVOID() \
return
#define ENDSENDCAPTUREVOIDDC() \
BEGIN_ENDSENDCAPTUREVOID(); \
CLEANUPSENDCAPTURECOMMONDC(); \
_ENDSENDCAPTUREVOID(); \
CLEANUPSENDCAPTURECOMMONDC(); \
END_ENDSENDCAPTUREVOID()
#define ENDSENDCAPTUREVOID() \
BEGIN_ENDSENDCAPTUREVOID(); \
CLEANUPSENDCAPTURECOMMON(); \
_ENDSENDCAPTUREVOID(); \
CLEANUPSENDCAPTURECOMMON(); \
END_ENDSENDCAPTUREVOID()
#define ENDSENDVOID() \
} \
return
#define MSGERROR() goto errorexit
#ifdef FE_SB // CHECKRETURN1() & ENDSEND1()
#define CHECKRETURN1() \
if (!NT_SUCCESS(Status) || \
cbCBStatus != sizeof(*pcbs)) { \
goto errorexit1; \
} \
try { \
retval = ProbeAndReadStructure(&pcbs->retval, ULONG_PTR); \
} except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
MSGERROR(); \
}
#define ENDSEND1(type, error) \
return (type)retval; \
goto errorexit1; \
} \
errorexit1: \
return (type)error
#define MSGERROR1() goto errorexit1
#endif // FE_SB
/*
* Callback IN parameter macros
*/
#define MSGDATA() (mp)
#define COPYSTRUCTOPT(x) \
MSGDATA()->p ## x = (p ## x); \
if (p ## x) MSGDATA()->x = *(p ## x);
#define COPYCONSTRECTSTRUCTOPT(x) \
MSGDATA()->p ## x = (LPRECT)(p ## x); \
if (p ## x) MSGDATA()->x = *(p ## x);
#define COPYBYTES(p, cb) \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, p, cb, &mp->p))) \
goto errorexit;
#define COPYBYTESOPT(p, cb) \
if (p) { \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, p, cb, &mp->p))) \
goto errorexit; \
} else { \
mp->p = NULL; \
}
#define LARGECOPYBYTES(p, cb) \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, p, cb, &mp->p))) \
goto errorexit;
#define LARGECOPYBYTES2(src, cb, dest) \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, src, cb, &mp->dest))) \
goto errorexit;
#define COPYSTRING(s) \
mp->s.Length = (p ## s)->Length; \
mp->s.MaximumLength = (p ## s)->MaximumLength; \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
(p ## s)->Buffer, \
(p ## s)->Length + sizeof(WCHAR), \
&mp->s.Buffer))) \
goto errorexit;
#define COPYSTRINGOPT(s) \
if (p ## s) { \
mp->s.Length = (p ## s)->Length; \
mp->s.MaximumLength = (p ## s)->MaximumLength; \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
(p ## s)->Buffer, \
(p ## s)->Length + sizeof(WCHAR), \
&mp->s.Buffer))) \
goto errorexit; \
} else { \
mp->s.Length = 0; \
mp->s.Buffer = NULL; \
}
#define COPYSTRINGID(s) \
mp->s.Length = (p ## s)->Length; \
mp->s.MaximumLength = (p ## s)->MaximumLength; \
if (mp->s.MaximumLength) { \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
(p ## s)->Buffer, \
(p ## s)->Length + sizeof(WCHAR), \
&mp->s.Buffer))) \
goto errorexit; \
} else { \
mp->s.Buffer = (p ## s)->Buffer; \
}
#define LARGECOPYSTRINGLPWSTR(ps, psz) \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
(ps)->Buffer, \
(ps)->Length + sizeof(WCHAR), \
(PVOID *)&mp->psz))) \
goto errorexit;
#define LARGECOPYSTRINGLPSTR(ps, psz) \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
(ps)->Buffer, \
(ps)->Length + 1, \
(PVOID *)&mp->psz))) \
goto errorexit;
#define LARGECOPYSTRINGLPWSTRA(ps, psz) \
if (!NT_SUCCESS(CaptureAnsiCallbackData(&mp->CaptureBuf, \
(ps)->Buffer, \
((ps)->Length / sizeof(WCHAR)) + 1, \
(PVOID *)&mp->psz))) \
goto errorexit;
#define LARGECOPYSTRINGLPSTRW(ps, psz) \
if (!NT_SUCCESS(CaptureUnicodeCallbackData(&mp->CaptureBuf, \
(ps)->Buffer, \
((ps)->Length + 1) * sizeof(WCHAR), \
(PVOID *)&mp->psz))) \
goto errorexit; \
#define LARGECOPYSTRINGLPWSTROPT(ps, psz) \
if (ps) { \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
(ps)->Buffer, \
(ps)->Length + sizeof(WCHAR), \
(PVOID *)&mp->psz))) \
goto errorexit; \
} else { \
mp->psz = NULL; \
}
#define LARGECOPYSTRINGLPSTROPT(ps, psz) \
if (ps) { \
if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
(ps)->Buffer, \
(ps)->Length + sizeof(UCHAR), \
(PVOID *)&mp->psz))) \
goto errorexit; \
} else { \
mp->psz = NULL; \
}
#define LARGECOPYSTRINGLPWSTROPTA(ps, psz) \
if (ps) { \
if (!NT_SUCCESS(CaptureAnsiCallbackData(&mp->CaptureBuf, \
(ps)->Buffer, \
((ps)->Length / sizeof(WCHAR)) + 1, \
(PVOID *)&mp->psz))) \
goto errorexit; \
} else { \
mp->psz = NULL; \
}
/*
* Wrappers to determine whether copy out should be done.
*/
#define BEGINCOPYOUT() \
if ((psms == NULL || ((psms->flags & (SMF_SENDERDIED | SMF_REPLY)) == 0)) \
&& !(dwSCMSFlags & SCMS_FLAGS_INONLY)) {
#define ENDCOPYOUT() \
}
/*
* Callback OUT paramter macros
*/
#define OUTSTRUCT(pstruct, type) \
try { \
*(pstruct) = ProbeAndReadStructure(((type *)pcbs->pOutput), type); \
} except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
MSGERROR(); \
}
/*
* flags field with mask (propagate back bits in mask only)
*/
#define OUTBITMASK(pstruct, type, mask) \
try { \
type flags = ProbeAndReadStructure(((type *)pcbs->pOutput), type); \
COPY_FLAG(*(pstruct), flags, mask); \
} except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
MSGERROR(); \
}
#ifdef FE_SB // COPYOUTLPWSTRLIMIT()
// should we insert IS_DBCS_ENABLED() in COPYOUTLPWSTRLIMIT ?
#define COPYOUTLPWSTRLIMIT(pstr, cch) \
try { \
retval = CalcOutputStringSize(pcbs,(DWORD)retval,pstr->bAnsi,fAnsiReceiver); \
CopyOutputString(pcbs, pstr, cch, fAnsiReceiver); \
} except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
MSGERROR(); \
}
#else
#define COPYOUTLPWSTRLIMIT(pstr, cch) \
try { \
CopyOutputString(pcbs, pstr, cch, fAnsiReceiver); \
} except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
MSGERROR(); \
}
#endif // FE_SB
#define RESERVEBYTES(cb, dest, cbdest) \
if (!NT_SUCCESS(AllocateCallbackData(&mp->CaptureBuf, \
cb, (PVOID *)&mp->dest))) \
goto errorexit; \
mp->cbdest = cb;
/***************************************************************************\
* AllocCallbackMessage
*
* Allocates a callback message from pool memory and reserves space
* for arguments to captured later.
*
* 03-13-95 JimA Created.
\***************************************************************************/
PVOID AllocCallbackMessage(
DWORD cbBaseMsg,
DWORD cPointers,
SIZE_T cbCapture,
PBYTE pStackBuffer,
BOOL fInput)
{
PCAPTUREBUF pcb;
if (cPointers == 0)
return NULL;
/*
* Compute allocation sizes
*/
cbBaseMsg = (cbBaseMsg + PADSIZE) & ~PADSIZE;
cbBaseMsg += (cPointers * sizeof(PVOID));
cbCapture = (cbCapture + (PADSIZE * cPointers)) & ~PADSIZE;
/*
* If the captured data is greater than a page, place it
* in a section. Otherwise, put the message and the
* data in a single block of pool
*/
if (cbCapture > CALLBACKSTACKLIMIT) {
NTSTATUS Status;
/*
* Allocate the message buffer
*/
pcb = UserAllocPoolWithQuota(cbBaseMsg, TAG_CALLBACK);
if (pcb == NULL)
return NULL;
/*
* Allocate the virtual memory
*/
pcb->pvVirtualAddress = NULL;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
&pcb->pvVirtualAddress, 0, &cbCapture,
MEM_COMMIT, PAGE_READWRITE);
if (!NT_SUCCESS(Status)) {
RIPMSG2(RIP_WARNING, "AllocCallbackMessage: ZwAllocateVirtualMemory failed. Status:%#lx. Size:%#lx",
Status, cbCapture);
UserFreePool(pcb);
return NULL;
}
pcb->pbFree = pcb->pvVirtualAddress;
pcb->cbCallback = cbBaseMsg;
} else {
/*
* If the message is too big to save on the stack, allocate
* the buffer from pool.
*/
if (cbBaseMsg + cbCapture > CBBUFSIZE) {
pcb = UserAllocPoolWithQuota((ULONG)(cbBaseMsg + cbCapture), TAG_CALLBACK);
if (pcb == NULL)
return NULL;
} else {
pcb = (PCAPTUREBUF)pStackBuffer;
}
pcb->pbFree = (PBYTE)pcb + cbBaseMsg;
pcb->pvVirtualAddress = NULL;
/*
* If this callback is passing data to the client, include the
* captured data in the message. Otherwise, only pass the message.
*/
if (fInput)
pcb->cbCallback = cbBaseMsg + (ULONG)cbCapture;
else
pcb->cbCallback = cbBaseMsg;
}
/*
* Initialize the capture buffer
*/
pcb->cbCapture = (ULONG)cbCapture;
pcb->cCapturedPointers = 0;
pcb->offPointers = cbBaseMsg - (cPointers * sizeof(PVOID));
return (PVOID)pcb;
}
/***************************************************************************\
* CaptureCallbackData
*
* Captures data into a callback structure.
*
* 03-13-95 JimA Created.
\***************************************************************************/
NTSTATUS CaptureCallbackData(
PCAPTUREBUF pcb,
PVOID pData,
DWORD cbData,
PVOID *ppDest)
{
PBYTE pbBuffer;
/*
* If the data pointer is NULL, the out pointer will be
* NULL
*/
if (pData == NULL) {
*ppDest = NULL;
return STATUS_SUCCESS;
}
/*
* Allocate space from the message buffer
*/
if (cbData > pcb->cbCapture) {
return STATUS_BUFFER_OVERFLOW;
}
pbBuffer = pcb->pbFree;
pcb->pbFree = pbBuffer + ((cbData + PADSIZE) & ~PADSIZE);
try {
RtlCopyMemory(pbBuffer, pData, cbData);
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
return STATUS_ACCESS_VIOLATION;
}
/*
* Fix up offsets to data. If the data is going into a section
* use the real pointer and don't compute offsets.
*/
if (pcb->pvVirtualAddress)
*ppDest = pbBuffer;
else {
*ppDest = (PBYTE)(pbBuffer - (PBYTE)pcb);
((LPDWORD)((PBYTE)pcb + pcb->offPointers))[pcb->cCapturedPointers++] =
(DWORD)((PBYTE)ppDest - (PBYTE)pcb);
}
return STATUS_SUCCESS;
}
/***************************************************************************\
* AllocateCallbackData
*
* Allocates space from a callback structure.
*
* 05-08-95 JimA Created.
\***************************************************************************/
NTSTATUS AllocateCallbackData(
PCAPTUREBUF pcb,
DWORD cbData,
PVOID *ppDest)
{
PBYTE pbBuffer;
/*
* Allocate space from the message buffer
*/
if (cbData > pcb->cbCapture) {
return STATUS_BUFFER_OVERFLOW;
}
pbBuffer = pcb->pbFree;
pcb->pbFree = pbBuffer + ((cbData + PADSIZE) & ~PADSIZE);
/*
* Fix up offsets to data. If the data is going into a section
* use the real pointer and don't compute offsets.
*/
if (pcb->pvVirtualAddress)
*ppDest = pbBuffer;
else {
*ppDest = (PBYTE)(pbBuffer - (PBYTE)pcb);
((LPDWORD)((PBYTE)pcb + pcb->offPointers))[pcb->cCapturedPointers++] =
(DWORD)((PBYTE)ppDest - (PBYTE)pcb);
}
return STATUS_SUCCESS;
}
/***************************************************************************\
* CaptureAnsiCallbackData
*
* Converts Unicode to ANSI data and captures the result
* into a callback structure.
*
* 03-13-95 JimA Created.
\***************************************************************************/
NTSTATUS CaptureAnsiCallbackData(
PCAPTUREBUF pcb,
PVOID pData,
DWORD cbData,
PVOID *ppDest)
{
PBYTE pbBuffer;
ULONG nCharsInAnsiString;
/*
* If the data pointer is NULL, the out pointer will be
* NULL
*/
if (pData == NULL) {
*ppDest = NULL;
return STATUS_SUCCESS;
}
/*
* Allocate space from the message buffer
*/
#ifdef FE_SB // CaptureAnsiCallbackData()
/*
* Reserve enough space for DBCS.
*/
if ((cbData * sizeof(WORD)) > pcb->cbCapture) {
#else
if (cbData > pcb->cbCapture) {
#endif // FE_SB
return STATUS_BUFFER_OVERFLOW;
}
pbBuffer = pcb->pbFree;
/*
* Convert the unicode string to ANSI
*/
try {
#ifdef FE_SB // CaptureAnsiCallbackData()
/*
* Enough space for keep DBCS string.
*/
if (!NT_SUCCESS(RtlUnicodeToMultiByteN(
(PCH)pbBuffer,
IS_DBCS_ENABLED() ? cbData * DBCS_CHARSIZE : cbData,
&nCharsInAnsiString,
(PWCH)pData,
cbData * sizeof(WCHAR)
))) {
#else
if (!NT_SUCCESS(RtlUnicodeToMultiByteN(
(PCH)pbBuffer,
cbData,
&nCharsInAnsiString,
(PWCH)pData,
cbData * sizeof(WCHAR)
))) {
#endif // FE_SB
return STATUS_UNSUCCESSFUL;
}
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
return STATUS_ACCESS_VIOLATION;
}
/*
* Translation succeeded.
*/
#ifdef FE_SB // CaptureAnsiCallbackData()
/*
* nCharsInAnsiString is actual bytes wriiten in message area.
*/
pcb->pbFree = pbBuffer + ((nCharsInAnsiString + PADSIZE) & ~PADSIZE);
pcb->cbCapture -= nCharsInAnsiString;
#else
pcb->pbFree = pbBuffer + ((cbData + PADSIZE) & ~PADSIZE);
pcb->cbCapture -= cbData;
#endif // FE_SB
/*
* Fix up offsets to data. If the data is going into a section
* use the real pointer and don't compute offsets.
*/
if (pcb->pvVirtualAddress)
*ppDest = pbBuffer;
else {
*ppDest = (PBYTE)(pbBuffer - (PBYTE)pcb);
((LPDWORD)((PBYTE)pcb + pcb->offPointers))[pcb->cCapturedPointers++] =
(DWORD)((PBYTE)ppDest - (PBYTE)pcb);
}
return STATUS_SUCCESS;
}
/***************************************************************************\
* CaptureUnicodeCallbackData
*
* Converts ANSI to Unicode data and captures the result
* into a callback structure.
*
* 03-31-95 JimA Created.
\***************************************************************************/
NTSTATUS CaptureUnicodeCallbackData(
PCAPTUREBUF pcb,
PVOID pData,
DWORD cbData,
PVOID *ppDest)
{
PBYTE pbBuffer;
ULONG nCharsInUnicodeString;
/*
* If the data pointer is NULL, the out pointer will be
* NULL
*/
if (pData == NULL) {
*ppDest = NULL;
return STATUS_SUCCESS;
}
/*
* Allocate space from the message buffer
*/
if (cbData > pcb->cbCapture) {
return STATUS_BUFFER_OVERFLOW;
}
pbBuffer = pcb->pbFree;
/*
* Convert the ANSI string to unicode
*/
try {
if (!NT_SUCCESS(RtlMultiByteToUnicodeN(
(PWCH)pbBuffer,
cbData,
&nCharsInUnicodeString,
(PCH)pData,
cbData / sizeof(WCHAR)
))) {
return STATUS_UNSUCCESSFUL;
}
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
return STATUS_ACCESS_VIOLATION;
}
/*
* Translation succeeded.
*/
pcb->pbFree = pbBuffer + ((cbData + PADSIZE) & ~PADSIZE);
pcb->cbCapture -= cbData;
/*
* Fix up offsets to data. If the data is going into a section
* use the real pointer and don't compute offsets.
*/
if (pcb->pvVirtualAddress)
*ppDest = pbBuffer;
else {
*ppDest = (PBYTE)(pbBuffer - (PBYTE)pcb);
((LPDWORD)((PBYTE)pcb + pcb->offPointers))[pcb->cCapturedPointers++] =
(DWORD)((PBYTE)ppDest - (PBYTE)pcb);
}
return STATUS_SUCCESS;
}
/***************************************************************************\
* CopyOutputString
*
* Copies a callback output string to the output buffer and performs
* any necessary ANSI/Unicode translation.
*
* Copies up to cchLimit characters, possibly including a null terminator.
*
* A null terminator is placed in pstr->Buffer only if the number of (non-null)
* characters obtained is less than cchLimit.
* pstr->Length may be set larger than necessary: ie: it may sometimes indicate
* a string longer than that which is null terminated. This is a deficiency in
* the current implementation.
*
* 05-08-95 JimA Created.
\***************************************************************************/
VOID CopyOutputString(
PCALLBACKSTATUS pcbs,
PLARGE_STRING pstr,
UINT cchLimit,
BOOL fAnsi)
{
UINT cch;
ProbeForRead(pcbs->pOutput, pcbs->cbOutput,
fAnsi ? sizeof(BYTE) : sizeof(WORD));
if (!pstr->bAnsi) {
if (fAnsi) {
cch = MBToWCS((LPSTR)pcbs->pOutput, (UINT)pcbs->retval,
(LPWSTR *)&pstr->Buffer, cchLimit, FALSE);
if (cch < cchLimit) {
/*
* Add a null terminator and ensure an accurate pstr->Length
*/
((LPWSTR)pstr->Buffer)[cch] = 0;
cchLimit = cch;
}
} else {
cchLimit = wcsncpycch(pstr->Buffer, (LPWSTR)pcbs->pOutput, cchLimit);
// wcsncpy(pstr->Buffer, (LPWSTR)pcbs->pOutput, cchLimit);
}
pstr->Length = cchLimit * sizeof(WCHAR);
} else {
if (fAnsi) {
cchLimit = strncpycch((LPSTR)pstr->Buffer,
// strncpy((LPSTR)pstr->Buffer,
(LPSTR)pcbs->pOutput, cchLimit);
} else {
cch = WCSToMB((LPWSTR)pcbs->pOutput, (UINT)pcbs->retval,
(LPSTR *)&pstr->Buffer, cchLimit, FALSE);
if (cch < cchLimit) {
/*
* Add a null terminator and ensure an accurate pstr->Length
*/
((LPSTR)pstr->Buffer)[cch] = 0;
cchLimit = cch;
}
}
pstr->Length = cchLimit;
}
}
#ifdef FE_SB // CalcOutputStringSize()
/***************************************************************************\
* CalcOutputStringSize()
*
* Copies a callback output string to the output buffer and performs
* any necessary ANSI/Unicode translation.
*
* 03-14-96 HideyukN Created.
\***************************************************************************/
DWORD CalcOutputStringSize(
PCALLBACKSTATUS pcbs,
DWORD cchText,
BOOL fAnsiSender,
BOOL fAnsiReceiver)
{
ULONG cch;
ProbeForRead(pcbs->pOutput, pcbs->cbOutput,
fAnsiReceiver ? sizeof(BYTE) : sizeof(WORD));
if (!fAnsiSender) {
if (fAnsiReceiver) {
RtlMultiByteToUnicodeSize(&cch,(LPSTR)pcbs->pOutput,cchText);
cch /= sizeof(WCHAR);
} else {
cch = cchText;
}
} else {
if (fAnsiReceiver) {
cch = cchText;
} else {
RtlUnicodeToMultiByteSize(&cch,(LPWSTR)pcbs->pOutput,cchText * sizeof(WCHAR));
}
}
return ((DWORD)cch);
}
#endif // FE_SB
/**************************************************************************\
*
* include the stub definition file
*
\**************************************************************************/
#include "ntcb.h"