第-1部分:分析的源码
分析1:
/****************************************************************************/
// WD_Ioctl
//
// Query/Set configuration information for the WD.
/****************************************************************************/
NTSTATUS WD_Ioctl(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
{
NTSTATUS status = STATUS_SUCCESS;
UINT32 bufferLen;
unsigned fn;
PVIDEO_MODE_INFORMATION pVidInfo;
DC_BEGIN_FN("WD_Ioctl");
分析2:
else {
// Non-perf path IOCTLs.
fn = WDW_IOCTL_FUNCTION(pSdIoctl->IoControlCode);
TRC_NRM((TB, "%s (%d)",
fn == 6 ? "IOCTL_VIDEO_ENUM_MONITOR_PDO" :
fn < 49 ? wdIoctlA[fn] :
fn < 50 ? "Unknown Ioctl" :
fn < 77 ? wdIoctlB[fn - 50] :
fn < 0x100 ? "Unknown Ioctl" :
fn < 0x11f ? wdIoctlC[fn - 0x100] :
fn < 0x200 ? "Unknown Ioctl" :
fn < 0x204 ? wdIoctlD[fn - 0x200] :
fn == 0x300 ? "IOCTL_MOUSE_ICA_INPUT" :
fn < 0x400 ? "Unknown Ioctl" :
fn < 0x412 ? wdIoctlE[fn - 0x400] :
fn == 0x500 ? "IOCTL_T120_REQUEST" : //需要选择这一行
fn < 0x510 ? "Unknown Ioctl" :
fn < 0x520 ? wdIoctlTsh[fn - 0x510] :
fn == 0x900 ? "IOCTL_TSHARE_CONF_CONNECT" :
fn == 0x901 ? "IOCTL_TSHARE_CONF_DISCONNECT" :
fn == 0x903 ? "IOCTL_TSHARE_USER_LOGON" :
fn == 0x904 ? "IOCTL_TSHARE_GET_SEC_DATA" :
fn == 0x905 ? "IOCTL_TSHARE_SET_SEC_DATA" :
fn == 0x906 ? "IOCTL_TSHARE_SET_NO_ENCRYPT" :
fn == 0x907 ? "IOCTL_TSHARE_QUERY_CHANNELS" :
fn == 0x908 ? "IOCTL_TSHARE_CONSOLE_CONNECT" :
fn == 0x909 ? "IOCTL_TSHARE_SEND_CERT_DATA" :
fn == 0x90A ? "IOCTL_TSHARE_GET_CERT_DATA" :
fn == 0x90B ? "IOCTL_TSHARE_SEND_CLIENT_RANDOM" :
fn == 0x90C ? "IOCTL_TSHARE_GET_CLIENT_RANDOM" :
fn == 0x90D ? "IOCTL_TSHARE_SHADOW_CONNECT" :
fn == 0x90E ? "IOCTL_TSHARE_SET_ERROR_INFO" :
"Unknown Ioctl",
fn));
}
分析3:
switch ( pSdIoctl->IoControlCode ) {
/********************************************************************/
/* T.120 request from user mode - pass it on */
/********************************************************************/
case IOCTL_T120_REQUEST:
{
status = MCSIcaT120Request(pTSWd->hDomainKernel, pSdIoctl);
}
break;
第0部分:
20:33:22.171 89C6060C.E18BA820 GCC: GCCConferenceCreateResponse entry
20:33:22.171 89C6060C.E18BA820 GCC: gccEncodeUserData entry
20:33:22.171 89C6060C.E18BA820 GCC: gccEncodeUserData exit - 0x0
20:33:22.171 89C6060C.E18BA820 GCC: Calling MCSConnectProviderResponse - hDomain 0xd737a8, result 0x0, pUserData 0xd73318, UserDataLength 0x11b
Breakpoint 20 hit
RDPWD!SendOutBuf:
b975a0d2 55 push ebp
0: kd> kc
00 RDPWD!SendOutBuf
01 RDPWD!ConnectProviderResponseFunc
02 RDPWD!MCSIcaT120Request
03 RDPWD!WD_Ioctl
04 termdd!_IcaCallSd
05 termdd!_IcaCallStack
06 termdd!IcaDeviceControlStack
07 termdd!IcaDeviceControl
08 termdd!IcaDispatch
09 nt!IofCallDriver
0a nt!IopSynchronousServiceTail
0b nt!IopXxxControlFile
0c nt!NtDeviceIoControlFile
0d nt!_KiSystemService
0e SharedUserData!SystemCallStub
0f ntdll!NtDeviceIoControlFile
10 ICAAPI!IcaIoControl
11 ICAAPI!_IcaStackIoControlWorker
12 ICAAPI!IcaStackIoControl
13 rdpwsx!SendConnectProviderResponse
14 rdpwsx!MCSConnectProviderResponse
15 rdpwsx!GCCConferenceCreateResponse
16 rdpwsx!TSrvConfCreateResp
17 rdpwsx!TSrvDoConnectResponse
18 rdpwsx!TSrvDoConnect
19 rdpwsx!TSrvStackConnect
1a rdpwsx!WsxIcaStackIoControl
1b termsrv!WsxStackIoControl
1c ICAAPI!_IcaStackIoControl
1d ICAAPI!_IcaStackWaitForIca
1e ICAAPI!IcaStackConnectionAccept
1f termsrv!TransferConnectionToIdleWinStation
20 termsrv!WinStationTransferThread
21 kernel32!BaseThreadStart
0: kd> g
20:33:22.171 89C6060C.E18BA820 TermDD: IcaDeviceControlStack, fc 1280, 0x0
Breakpoint 20 hit
RDPWD!SendOutBuf:
b975a0d2 55 push ebp
0: kd> kc
00 RDPWD!SendOutBuf
01 RDPWD!HandleAttachUserReq
02 RDPWD!RecognizeMCSFrame
03 RDPWD!MCSIcaRawInput
04 termdd!IcaRawInput
05 TDTCP!TdInputThread
06 termdd!_IcaDriverThread
07 nt!PspSystemThreadStartup
08 nt!KiThreadStartup
0: kd> g
20:33:22.171 89C6060C.E18BA820 GCC: MCSConnectProviderResponse - MCSError 0x0 (MCS_NO_ERROR)
20:33:22.171 89C6060C.E18BA820 GCC: gccMapMcsError: mcsError 0x0 (MCS_NO_ERROR), gbbError 0x0 (GCC_NO_ERROR)
GCCError
APIENTRY
GCCConferenceCreateResponse(GCCNumericString conference_modifier,
DomainHandle hDomain,
T120Boolean use_password_in_the_clear,
DomainParameters *domain_parameters,
USHORT number_of_network_addresses,
GCCNetworkAddress **local_network_address_list,
USHORT number_of_user_data_members,
GCCUserData **user_data_list,
GCCResult result)
{
MCSError mcsError;
GCCError gccError;
PBYTE pUserData;
UINT UserDataLength;
TRACE((DEBUG_GCC_DBFLOW,
"GCC: GCCConferenceCreateResponse entry\n"));
if (gccIsInitialized(&gccError))
{
mcsError = gccEncodeUserData(number_of_user_data_members,
user_data_list,
&pUserData,
&UserDataLength);
if (mcsError == MCS_NO_ERROR)
{
TRACE((DEBUG_GCC_DBDEBUG,
"GCC: Calling MCSConnectProviderResponse - hDomain 0x%x, result 0x%x, "
"pUserData 0x%x, UserDataLength 0x%x\n",
hDomain, result, pUserData, UserDataLength));
TS_ASSERT(hDomain);
mcsError = MCSConnectProviderResponse(hDomain, result, pUserData, UserDataLength);
gccDumpMCSErrorDetails(mcsError,
"MCSConnectProviderResponse");
if (pUserData)
TShareFree(pUserData);
}
gccError = gccMapMcsError(mcsError);
}
TRACE((DEBUG_GCC_DBFLOW,
"GCC: GCCConferenceCreateResponse exit - 0x%x\n",
gccError));
return (gccError);
}
第一部分:
21:19:13.937 892767D4.E11B61D0 GCC: GCCConferenceCreateResponse entry
21:19:13.937 892767D4.E11B61D0 GCC: gccEncodeUserData entry
21:19:13.937 892767D4.E11B61D0 GCC: gccEncodeUserData exit - 0x0
21:19:13.937 892767D4.E11B61D0 GCC: Calling MCSConnectProviderResponse - hDomain 0xd75c98, result 0x0, pUserData 0xd73318, UserDataLength 0x11b
21:19:13.937 892767D4.E11B61D0 TermDD: IcaDeviceControlStack, fc 1280 (enter)
21:19:13.937 892767D4.E11B61D0 RDP E10C2010 WD_Ioctl 0489 IOCTL_T120_REQUEST (1280) //重点关注这一行
21:19:13.937 892767D4.E11B61D0 TermDD: IcaBufferAlloc: 0x892c6bf8, Status=0x0
21:19:13.937 892767D4.E11B61D0 TermDD: IcaCallNextDriver, ProcIndex=2 (enter)
21:19:13.937 892767D4.E11B61D0 TdRawWrite 0333, 892c6bf8
21:19:13.937 892767D4.E11B61D0 TermDD: IcaDeviceControlStack, fc 1280, 0x0
21:19:13.937 89DD11FC.00000000 _TdWriteCompleteWorker: 892c6bf8
21:19:13.953 89DD11FC.00000000 TermDD: IcaBufferFree: 0x892c6bf8
21:19:13.953 892767D4.E11B61D0 GCC: MCSConnectProviderResponse - MCSError 0x0 (MCS_NO_ERROR)
21:19:13.953 892767D4.E11B61D0 GCC: gccMapMcsError: mcsError 0x0 (MCS_NO_ERROR), gbbError 0x0 (GCC_NO_ERROR)
21:19:13.953 892767D4.E11B61D0 GCC: GCCConferenceCreateResponse exit - 0x0
第二部分:
下面是这一行的解释:
21:19:13.937 892767D4.E11B61D0 RDP E10C2010 WD_Ioctl 0489 IOCTL_T120_REQUEST (1280)
/*
* T.120 IOCTLs.
*/
#define IOCTL_T120_BASE (0x500) 0x500=0n1280
// Used by MCSMUX to signal on a stack IOCTL that the included data is an MCS
// request/response. An MCSXxxYyyIoctl struct is expected as the
// pSdIoctl->InputBuffer; the Header.Type value in the struct will be used
// to determine the type of the request.
#define IOCTL_T120_REQUEST _ICA_CTL_CODE (IOCTL_T120_BASE, METHOD_NEITHER)
}
else {
// Non-perf path IOCTLs.
fn = WDW_IOCTL_FUNCTION(pSdIoctl->IoControlCode);
TRC_NRM((TB, "%s (%d)",
fn == 6 ? "IOCTL_VIDEO_ENUM_MONITOR_PDO" :
fn < 49 ? wdIoctlA[fn] :
fn < 50 ? "Unknown Ioctl" :
fn < 77 ? wdIoctlB[fn - 50] :
fn < 0x100 ? "Unknown Ioctl" :
fn < 0x11f ? wdIoctlC[fn - 0x100] :
fn < 0x200 ? "Unknown Ioctl" :
fn < 0x204 ? wdIoctlD[fn - 0x200] :
fn == 0x300 ? "IOCTL_MOUSE_ICA_INPUT" :
fn < 0x400 ? "Unknown Ioctl" :
fn < 0x412 ? wdIoctlE[fn - 0x400] :
fn == 0x500 ? "IOCTL_T120_REQUEST" : //对应这一行!!!
fn < 0x510 ? "Unknown Ioctl" :
fn < 0x520 ? wdIoctlTsh[fn - 0x510] :
fn == 0x900 ? "IOCTL_TSHARE_CONF_CONNECT" :
fn == 0x901 ? "IOCTL_TSHARE_CONF_DISCONNECT" :
fn == 0x903 ? "IOCTL_TSHARE_USER_LOGON" :
fn == 0x904 ? "IOCTL_TSHARE_GET_SEC_DATA" :
fn == 0x905 ? "IOCTL_TSHARE_SET_SEC_DATA" :
fn == 0x906 ? "IOCTL_TSHARE_SET_NO_ENCRYPT" :
fn == 0x907 ? "IOCTL_TSHARE_QUERY_CHANNELS" :
fn == 0x908 ? "IOCTL_TSHARE_CONSOLE_CONNECT" :
fn == 0x909 ? "IOCTL_TSHARE_SEND_CERT_DATA" :
fn == 0x90A ? "IOCTL_TSHARE_GET_CERT_DATA" :
fn == 0x90B ? "IOCTL_TSHARE_SEND_CLIENT_RANDOM" :
fn == 0x90C ? "IOCTL_TSHARE_GET_CLIENT_RANDOM" :
fn == 0x90D ? "IOCTL_TSHARE_SHADOW_CONNECT" :
fn == 0x90E ? "IOCTL_TSHARE_SET_ERROR_INFO" :
"Unknown Ioctl",
fn));
} //文件中的489行
第三部分:
/*
* Callout from WD upon reception of a IOCTL_T120_REQUEST, i.e. a user-mode
* ioctl.
*/
NTSTATUS MCSIcaT120Request(DomainHandle hDomain, PSD_IOCTL pSdIoctl)
{
Domain *pDomain;
IoctlHeader *pHeader;
pDomain = (Domain *)hDomain;
// Get the request type.
ASSERT(pSdIoctl->InputBufferLength >= sizeof(IoctlHeader));
pHeader = (IoctlHeader *)pSdIoctl->InputBuffer;
// Make sure request within bounds.
if (pHeader->Type < MCS_ATTACH_USER_REQUEST ||
pHeader->Type > MCS_T120_START) {
ErrOut(pDomain->pContext, "Invalid IOCTL_T120_REQUEST type");
return STATUS_INVALID_DEVICE_REQUEST;
}
// Check that request is supported.
if (g_T120RequestDispatch[pHeader->Type] == NULL) {
ErrOut(pDomain->pContext, "IOCTL_T120_REQUEST type unsupported");
return STATUS_INVALID_DEVICE_REQUEST;
}
// Make the call. The entry points are defined in MCSIoctl.c.
return (g_T120RequestDispatch[pHeader->Type])(pDomain, pSdIoctl);
}
/*
* Globals
*/
// Table of function entry points for ChannelWrite() request calls.
// These entry points correspond to request defines in MCSIOCTL.h.
// NULL means unsupported, which will be handled by dispatch code in
// PdChannelWrite() in PDAPI.c.
const PT120RequestFunc g_T120RequestDispatch[] =
{
AttachUserRequestFunc,
DetachUserRequestFunc,
ChannelJoinRequestFunc,
ChannelLeaveRequestFunc,
SendDataRequestFunc, // Handles both uniform and regular.
SendDataRequestFunc, // Handles both uniform and regular.
NULL, // MCS_CHANNEL_CONVENE_REQUEST unsupported.
NULL, // MCS_CHANNEL_DISBAND_REQUEST unsupported.
NULL, // MCS_CHANNEL_ADMIT_REQUEST unsupported.
NULL, // MCS_CHANNEL_EXPEL_REQUEST unsupported.
NULL, // MCS_TOKEN_GRAB_REQUEST unsupported.
NULL, // MCS_TOKEN_INHIBIT_REQUEST unsupported.
NULL, // MCS_TOKEN_GIVE_REQUEST unsupported.
NULL, // MCS_TOKEN_GIVE_RESPONSE unsupported.
NULL, // MCS_TOKEN_PLEASE_REQUEST unsupported.
NULL, // MCS_TOKEN_RELEASE_REQUEST unsupported.
NULL, // MCS_TOKEN_TEST_REQUEST unsupported.
NULL, // MCS_CONNECT_PROVIDER_REQUEST unsupported.
ConnectProviderResponseFunc,
DisconnectProviderRequestFunc,
T120StartFunc,
};
参考:调用栈
Breakpoint 20 hit
RDPWD!SendOutBuf:
b975a0d2 55 push ebp
0: kd> kc
00 RDPWD!SendOutBuf
01 RDPWD!ConnectProviderResponseFunc
02 RDPWD!MCSIcaT120Request
03 RDPWD!WD_Ioctl
参考:调用栈 上一次是用的T120StartFunc
第四部分:
/*
* Connect provider response - ChannelWrite() request. Requires filler bytes
* in MCSConnectProviderResponseIoctl to make sure we use at least 54 bytes
* for the struct so we can reuse the OutBuf here. User data must start
* at (pSdIoctl->pBuffer + sizeof(MCSConnectProviderResponseIoctl)).
*/
NTSTATUS ConnectProviderResponseFunc(
PDomain pDomain,
PSD_IOCTL pSdIoctl)
{
POUTBUF pOutBuf;
NTSTATUS Status;
ConnectProviderResponseIoctl *pCPrs;
ASSERT(pSdIoctl->InputBufferLength ==
sizeof(ConnectProviderResponseIoctl));
pCPrs = (ConnectProviderResponseIoctl *)pSdIoctl->InputBuffer;
ASSERT(pCPrs->Header.Type == MCS_CONNECT_PROVIDER_RESPONSE);
// Verify that we are actually waiting for a CP response.
if (pDomain->State != State_ConnectProvIndPending) {
ErrOut(pDomain->pContext, "Connect-provider response call received, "
"we are in wrong state, ignoring");
return STATUS_INVALID_DOMAIN_STATE;
}
// Alloc OutBuf for sending PDU.
// This allocation is vital to the session and must succeed.
do {
Status = IcaBufferAlloc(pDomain->pContext, FALSE, TRUE,
ConnectResponseHeaderSize + pCPrs->UserDataLength, NULL,
&pOutBuf);
if (Status != STATUS_SUCCESS)
ErrOut(pDomain->pContext, "Could not allocate an OutBuf for a "
"connect-response PDU, retrying");
} while (Status != STATUS_SUCCESS);
// Encode PDU header. Param 2, the called connect ID, does not need to be
// anything special because we do not allow extra sockets to be opened
// for other data priorities.
CreateConnectResponseHeader(pDomain->pContext, pCPrs->Result, 0,
&pDomain->DomParams, pCPrs->UserDataLength, pOutBuf->pBuffer,
&pOutBuf->ByteCount);
// Copy the user data after the header.
RtlCopyMemory(pOutBuf->pBuffer + pOutBuf->ByteCount, pCPrs->pUserData,
pCPrs->UserDataLength);
pOutBuf->ByteCount += pCPrs->UserDataLength;
// Send the new PDU OutBuf down to the TD for sending out.
//MCS FUTURE: Needs to change for multiple connections.
Status = SendOutBuf(pDomain, pOutBuf);
if (!NT_SUCCESS(Status)) {
ErrOut(pDomain->pContext, "Could not send connect-response PDU OutBuf "
"to TD");
// Ignore errors here -- this should only occur if stack is going down.
return Status;
}
// Transition state depending on Result.
if (pCPrs->Result == RESULT_SUCCESSFUL) {
pDomain->State = State_MCS_Connected;
}
else {
TraceOut(pDomain->pContext, "ConnectProviderRespFunc(): Node "
"controller returned error in response, destroying call "
"data");
pDomain->State = State_Disconnected;
// Detach any users that attached during domain setup.
DisconnectProvider(pDomain, TRUE, REASON_PROVIDER_INITIATED);
}
return STATUS_SUCCESS;
}
NTSTATUS IcaBufferAlloc(
IN PSDCONTEXT pContext,
IN BOOLEAN fWait,
IN BOOLEAN fControl,
IN ULONG ByteCount,
IN POUTBUF pOutBufOrig,
OUT POUTBUF *ppOutBuf)
{
PSDLINK pSdLink;
PICA_STACK pStack;
NTSTATUS Status;
/*
* Use SD passed context to get the SDLINK pointer.
*/
pSdLink = CONTAINING_RECORD(pContext, SDLINK, SdContext);
pStack = pSdLink->pStack;
ASSERT(pSdLink->pStack->Header.Type == IcaType_Stack);
ASSERT(pSdLink->pStack->Header.pDispatchTable == IcaStackDispatchTable);
ASSERT(ExIsResourceAcquiredExclusiveLite( &pStack->Resource));
/*
* Walk up the SDLINK list looking for a driver which has specified
* a BufferAlloc callup routine. If we find one, then call the
* driver BufferAlloc routine to let it handle the call.
*/
while ((pSdLink = IcaGetPreviousSdLink(pSdLink)) != NULL) {
ASSERT( pSdLink->pStack == pStack );
if (pSdLink->SdContext.pCallup->pSdBufferAlloc) {
IcaReferenceSdLink(pSdLink);
Status = (pSdLink->SdContext.pCallup->pSdBufferAlloc)(
pSdLink->SdContext.pContext,
fWait,
fControl,
ByteCount,
pOutBufOrig,
ppOutBuf);
IcaDereferenceSdLink(pSdLink);
return Status;
}
}
/*
* We didn't find a callup routine to handle the request,
* so we'll process it here.
*/
Status = IcaBufferAllocInternal(pContext, fWait, fControl, ByteCount,
pOutBufOrig, ppOutBuf);
TRACESTACK((pStack, TC_ICADD, TT_API3,
"TermDD: IcaBufferAlloc: 0x%08x, Status=0x%x\n", *ppOutBuf,
Status));
return Status;
}
21:19:13.937 892767D4.E11B61D0 TermDD: IcaBufferAlloc: 0x892c6bf8, Status=0x0
第五部分:
void CreateConnectResponseHeader(
PSDCONTEXT pContext, // For tracing.
MCSResult Result,
int CalledConnectID,
DomainParameters *pDomParams,
unsigned UserDataLength,
BYTE *pBuffer,
unsigned *pNBytesConsumed)
{
BYTE *OutFrame, *newFrame;
unsigned NBytesConsumed, TotalSize, EncodeLength;
// Set up for creating the PDU.
OutFrame = pBuffer + X224_DataHeaderSize;
NBytesConsumed = 0;
// Encode the BER prefix, PDU type, and leave space for the PDU length.
// Note that the length is the number of bytes following this length
// indicator.
// The most-oft-encountered case is where the PDU length is less than 128
// bytes. So, special-case larger sizes at the end of the function
// when we know the total size.
OutFrame[0] = MCS_CONNECT_PDU;
OutFrame[1] = MCS_CONNECT_RESPONSE_ENUM;
// Skip OutFrame[2] for the default 1-byte (<= 128) size.
OutFrame += 3;
TotalSize = 3;
// Encode Result, CalledConnectID, DomParams. We use OutFrame
// as a current pointer.
EncodeTagBER(pContext, OutFrame, TagType_Enumeration, 0, Result,
&NBytesConsumed, &newFrame);
TotalSize += NBytesConsumed;
OutFrame = newFrame;
EncodeTagBER(pContext, OutFrame, TagType_Integer, 0, CalledConnectID,
&NBytesConsumed, &newFrame);
TotalSize += NBytesConsumed;
OutFrame = newFrame;
EncodeDomainParameters(pContext, OutFrame, &NBytesConsumed, pDomParams,
&newFrame);
TotalSize += NBytesConsumed;
OutFrame = newFrame;
// Encode only the length bytes, not the user data body.
EncodeTagBER(pContext, OutFrame, TagType_OctetString, UserDataLength,
(UINT_PTR)NULL, &NBytesConsumed, &newFrame);
TotalSize += NBytesConsumed;
OutFrame = newFrame;
// Encode the final size. Here we special-case a too-large size by
// shifting data around. The large size is the exceptional case.
EncodeLength = TotalSize - 3 + UserDataLength;
if (EncodeLength < 128) {
pBuffer[2 + X224_DataHeaderSize] = (BYTE)EncodeLength;
}
else {
unsigned i, Len = 0;
WarnOut(pContext, "CreateConnRespHeader(): Perf hit from too-large "
"PDU size");
// Since we can only send up to 64K bytes, the length determinant
// cannot be any more than 3 bytes long.
ASSERT(EncodeLength < 65535);
if (EncodeLength < 0x8000)
Len = 2;
else if (EncodeLength < 0x800000)
Len = 3;
else
ASSERT(FALSE);
// Size escape comes first.
pBuffer[2 + X224_DataHeaderSize] = LengthModifier_2 + Len - 2;
RtlMoveMemory(pBuffer + 3 + X224_DataHeaderSize + Len,
pBuffer + 3 + X224_DataHeaderSize, EncodeLength - 3);
for (i = 1; i <= Len; i++) {
pBuffer[3 + X224_DataHeaderSize + Len - i] = (BYTE)EncodeLength;
EncodeLength >>= 8;
}
// We already included one byte of the length encoding above, but
// now we need to also skip the length escape and the encoded length.
TotalSize += Len;
}
// Set up X224 header based on the final size of the packet.
CreateX224DataHeader(pBuffer, TotalSize + UserDataLength, TRUE);
*pNBytesConsumed = X224_DataHeaderSize + TotalSize;
}
第六部分:从TDTCP!TdRawWrite函数到tcpip!TCPSendData函数
D:\123>grep "TdRawWrite" -nr D:\srv03rtm\termsrv
D:\srv03rtm\termsrv/drivers/rdp/rdpwd/asmapi.c:879: // 254514 STRESS: TS: Tdtcp!TdRawWrite needs synchronization with the write complete routine
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:53:NTSTATUS TdRawWrite( PTD, PSD_RAWWRITE );
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:110: TdRawWrite,
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:394: * TdRawWrite
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:413:NTSTATUS TdRawWrite(PTD pTd, PSD_RAWWRITE pSdRawWrite)
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:454: "TdRawWrite : No memory to allocate WorkItem. Removing Outbuf from the list %04u, %p\n",
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:485: "TdRawWrite %04u, %08x\n",
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:513: "TdRawWrite: WriteErrorThreshold exceeded\n"));
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:519: TRACE((pTd->pContext, TC_TD, TT_API2, "TdRawWrite: closing\n"));
D:\srv03rtm\termsrv/drivers/td/common/tdapi.c:542: TRACE(( pTd->pContext, TC_TD, TT_OUT1, "TdRawWrite, Status=0x%x\n", Status ));
D:\srv03rtm\termsrv/drivers/termdd/buffer.c:15: * (This size will be checked by the TdRawWrite routine.)
参考:
21:56:30.609 89617F7C.E192A9F8 GCC: GCCConferenceCreateResponse entry
21:56:30.609 89617F7C.E192A9F8 GCC: gccEncodeUserData entry
21:56:30.609 89617F7C.E192A9F8 GCC: gccEncodeUserData exit - 0x0
21:56:30.609 89617F7C.E192A9F8 GCC: Calling MCSConnectProviderResponse - hDomain 0xd63f88, result 0x0, pUserData 0xd635e0, UserDataLength 0x11b
21:56:30.609 89617F7C.E192A9F8 TermDD: IcaDeviceControlStack, fc 1280 (enter)
21:56:30.609 89617F7C.E192A9F8 RDP E1026010 WD_Ioctl 0489 IOCTL_T120_REQUEST (1280)
21:56:30.609 89617F7C.E192A9F8 TermDD: IcaBufferAlloc: 0x897a9020, Status=0x0
21:56:30.609 89617F7C.E192A9F8 TermDD: IcaCallNextDriver, ProcIndex=2 (enter)
Breakpoint 10 hit
TDTCP!TdRawWrite:
b9ebfcd6 55 push ebp
0: kd> kc
00 TDTCP!TdRawWrite
01 termdd!_IcaCallSd
02 termdd!IcaCallNextDriver
03 RDPWD!SendOutBuf
04 RDPWD!ConnectProviderResponseFunc
05 RDPWD!MCSIcaT120Request
06 RDPWD!WD_Ioctl
参考:
NTSTATUS TdRawWrite(PTD pTd, PSD_RAWWRITE pSdRawWrite)
{
// Call the device driver
// From this point on we must NOT free the outbuf.
// It will be free'd by the write complete routine.
Status = IoCallDriver(pTd->pDeviceObject, pOutBuf->pIrp);
if (NT_SUCCESS(Status)) {
// Update output counters
pTd->pStatus->Output.Bytes += pOutBuf->ByteCount;
pTd->pStatus->Output.Frames++;
TRACE((pTd->pContext, TC_TD, TT_OUT1,
"TdRawWrite %04u, %08x\n",
pOutBuf->ByteCount, pOutBuf));
TRACEBUF((pTd->pContext, TC_TD, TT_ORAW,
pOutBuf->pBuffer, pOutBuf->ByteCount));
21:19:13.937 892767D4.E11B61D0 TdRawWrite 0333, 892c6bf8
21:55:25.125 8959EAD4.E18646A0 TShrSRV: Accepting conference domain 00D644D0
21:55:25.125 8959EAD4.E18646A0 GCC: GCCConferenceCreateResponse entry
21:55:25.125 8959EAD4.E18646A0 GCC: gccEncodeUserData entry
21:55:25.125 8959EAD4.E18646A0 GCC: gccEncodeUserData exit - 0x0
21:55:25.125 8959EAD4.E18646A0 GCC: Calling MCSConnectProviderResponse - hDomain 0xd644d0, result 0x0, pUserData 0xd635e0, UserDataLength 0x11b
Breakpoint 10 hit
TDTCP!TdRawWrite:
b9ebfcd6 55 push ebp
0: kd> kc
00 TDTCP!TdRawWrite
01 termdd!_IcaCallSd
02 termdd!IcaCallNextDriver
03 RDPWD!SendOutBuf
04 RDPWD!ConnectProviderResponseFunc
05 RDPWD!MCSIcaT120Request
06 RDPWD!WD_Ioctl
07 termdd!_IcaCallSd
08 termdd!_IcaCallStack
09 termdd!IcaDeviceControlStack
0a termdd!IcaDeviceControl
0b termdd!IcaDispatch
0c nt!IofCallDriver
0d nt!IopSynchronousServiceTail
0e nt!IopXxxControlFile
0f nt!NtDeviceIoControlFile
10 nt!_KiSystemService
11 SharedUserData!SystemCallStub
12 ntdll!NtDeviceIoControlFile
13 icaapi!IcaIoControl
14 icaapi!_IcaStackIoControlWorker
15 icaapi!IcaStackIoControl
16 rdpwsx!SendConnectProviderResponse
17 rdpwsx!MCSConnectProviderResponse
18 rdpwsx!GCCConferenceCreateResponse
19 rdpwsx!TSrvConfCreateResp
1a rdpwsx!TSrvDoConnectResponse
1b rdpwsx!TSrvDoConnect
1c rdpwsx!TSrvStackConnect
1d rdpwsx!WsxIcaStackIoControl
1e termsrv!WsxStackIoControl
1f icaapi!_IcaStackIoControl
20 icaapi!_IcaStackWaitForIca
21 icaapi!IcaStackConnectionAccept
22 termsrv!TransferConnectionToIdleWinStation
23 termsrv!WinStationTransferThread
24 kernel32!BaseThreadStart
0: kd> dv
pTd = 0x89432b90
pSdRawWrite = 0xb9ba0458
Status = 0n-1178991528
oldIrql = 0xb9 ''
pWorkItem = 0x00000008
0: kd> dx -r1 ((TDTCP!_SD_RAWWRITE *)0xb9ba0458)
((TDTCP!_SD_RAWWRITE *)0xb9ba0458) : 0xb9ba0458 [Type: _SD_RAWWRITE *]
+0x000\] pOutBuf : 0x897a9020 \[Type: _OUTBUF \*
+0x004\] pBuffer : 0x0 \[Type: unsigned char \*
+0x008\] ByteCount : 0x0 \[Type: unsigned long
0: kd> db 0x897a9020
897a9020 51 01 00 00 00 00 00 00-28 90 7a 89 28 90 7a 89 Q.......(.z.(.z.
897a9030 88 91 7a 89 4d 01 00 00-51 01 00 00 00 10 03 f7 ..z.M...Q.......
897a9040 58 90 7a 89 60 91 7a 89-90 2b 43 89 00 00 00 00 X.z.`.z..+C.....
897a9050 00 00 00 00 4a 90 7a 89-06 00 08 01 00 00 00 00 ....J.z.........
897a9060 00 00 00 00 00 00 00 00-68 90 7a 89 68 90 7a 89 ........h.z.h.z.
897a9070 00 00 00 00 00 00 00 00-00 00 04 05 00 00 00 00 ................
897a9080 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
897a9090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0: kd> p
_TdCancelReceiveQueue [00000000]: Endpoint 0x8941DF40
TDTCP!TdRawWrite+0x4:
b9ebfcda 8b450c mov eax,dword ptr [ebp+0Ch]
0: kd> p
TDTCP!TdRawWrite+0x10:
b9ebfce6 85ff test edi,edi
0: kd> p
TDTCP!TdRawWrite+0x2a:
b9ebfd00 8b7508 mov esi,dword ptr [ebp+8]
0: kd> p
TDTCP!TdRawWrite+0x34:
b9ebfd0a 57 push edi
0: kd> p
TDTCP!TdRawWrite+0x53:
b9ebfd29 85c0 test eax,eax
0: kd> p
TDTCP!TdRawWrite+0x5a:
b9ebfd30 57 push edi
0: kd> p
TDTCP!TdRawWrite+0x61:
b9ebfd37 85c0 test eax,eax
0: kd> p
TDTCP!TdRawWrite+0x68:
b9ebfd3e 8b4724 mov eax,dword ptr [edi+24h]
0: kd> p
TDTCP!TdRawWrite+0x71:
b9ebfd47 897728 mov dword ptr [edi+28h],esi
0: kd> p
TDTCP!TdRawWrite+0x74:
b9ebfd4a 8d867c020000 lea eax,[esi+27Ch]
0: kd> dv
pTd = 0x89432b90
pSdRawWrite = 0x00000000
Status = 0n0
oldIrql = 0x00 ''
pWorkItem = 0x00000000
0: kd> dx -r1 ((TDTCP!_OUTBUF *)0x897a9020)
((TDTCP!_OUTBUF *)0x897a9020) : 0x897a9020 [Type: _OUTBUF *]
+0x000\] OutBufLength : 0x151 \[Type: unsigned long
+0x004\] PoolIndex : 0 \[Type: int
+0x008\] Links \[Type: _LIST_ENTRY
+0x010\] pBuffer : 0x897a9188 : 0x3 \[Type: unsigned char \*
+0x014\] ByteCount : 0x14d \[Type: unsigned long
+0x018\] MaxByteCount : 0x151 \[Type: unsigned long
+0x01c\] ThreadId : 0xf7031000 \[Type: _ETHREAD \*
+0x020\] pIrp : 0x897a9058 \[Type: _IRP \*
+0x024\] pMdl : 0x897a9160 \[Type: _MDL \*
+0x028\] pPrivate : 0x89432b90 \[Type: void \*
+0x02c\] StartTime : 0x0 \[Type: unsigned long
+0x030\] Sequence : 0x0 \[Type: unsigned char
+0x031\] Fragment : 0x0 \[Type: unsigned char
+0x034 ( 0: 0)\] fWait : 0x0 \[Type: unsigned long
+0x034 ( 1: 1)\] fControl : 0x1 \[Type: unsigned long
+0x034 ( 2: 2)\] fRetransmit : 0x0 \[Type: unsigned long
+0x034 ( 3: 3)\] fCompress : 0x1 \[Type: unsigned long
+0x034 ( 4: 4)\] fIrpCompleted : 0x0 \[Type: unsigned long
0: kd> p
TDTCP!TdRawWrite+0x8a:
b9ebfd60 8d45fc lea eax,[ebp-4]
0: kd> p
TDTCP!TdRawWrite+0x199:
b9ebfe6f 8b5720 mov edx,dword ptr [edi+20h]
0: kd> t
nt!IofCallDriver:
80a266fa 55 push ebp
0: kd> p
nt!IofCallDriver+0x1:
80a266fb 8bec mov ebp,esp
0: kd> p
nt!IofCallDriver+0x5c:
80a26756 56 push esi
0: kd> p
nt!IofCallDriver+0x5d:
80a26757 57 push edi
0: kd> p
nt!IofCallDriver+0x5e:
80a26758 ff548138 call dword ptr [ecx+eax*4+38h]
0: kd> r
eax=0000000f ebx=00000000 ecx=8980c468 edx=897a9058 esi=897a9058 edi=895d2540
eip=80a26758 esp=b9ba03d8 ebp=b9ba03ec iopl=0 nv up ei ng nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000282
nt!IofCallDriver+0x5e:
80a26758 ff548138 call dword ptr [ecx+eax*4+38h] ds:0023:8980c4dc={tcpip!TCPDispatchInternalDeviceControl (baa180ec)}
0: kd> t
tcpip!TCPDispatchInternalDeviceControl:
baa180ec 55 push ebp
0: kd> p
tcpip!TCPDispatchInternalDeviceControl+0x3:
baa180ef a1206ca3ba mov eax,dword ptr [tcpip!DbgSettingsLevel (baa36c20)]
0: kd> p
tcpip!TCPDispatchInternalDeviceControl+0x36:
baa18122 8b5d08 mov ebx,dword ptr [ebp+8]
0: kd> p
tcpip!TCPDispatchInternalDeviceControl+0x4f:
baa1813b 3b1d206da3ba cmp ebx,dword ptr [tcpip!IPDeviceObject (baa36d20)]
0: kd> p
tcpip!TCPDispatchInternalDeviceControl+0x5b:
baa18147 8b750c mov esi,dword ptr [ebp+0Ch]
0: kd> p
tcpip!TCPDispatchInternalDeviceControl+0x61:
baa1814d 8b4718 mov eax,dword ptr [edi+18h]
0: kd> p
tcpip!TCPDispatchInternalDeviceControl+0x6f:
baa1815b 8a4701 mov al,byte ptr [edi+1]
0: kd> p
tcpip!TCPDispatchInternalDeviceControl+0x76:
baa18162 57 push edi
0: kd> t
tcpip!TCPSendData:
baa162de 55 push ebp
0: kd> kc
00 tcpip!TCPSendData
01 tcpip!TCPDispatchInternalDeviceControl
02 nt!IofCallDriver
03 TDTCP!TdRawWrite
04 termdd!_IcaCallSd
05 termdd!IcaCallNextDriver
06 RDPWD!SendOutBuf
07 RDPWD!ConnectProviderResponseFunc
08 RDPWD!MCSIcaT120Request
09 RDPWD!WD_Ioctl
0a termdd!_IcaCallSd
0b termdd!_IcaCallStack
0c termdd!IcaDeviceControlStack
0d termdd!IcaDeviceControl
0e termdd!IcaDispatch
0f nt!IofCallDriver
10 nt!IopSynchronousServiceTail
11 nt!IopXxxControlFile
12 nt!NtDeviceIoControlFile
13 nt!_KiSystemService
14 SharedUserData!SystemCallStub
15 ntdll!NtDeviceIoControlFile
16 icaapi!IcaIoControl
17 icaapi!_IcaStackIoControlWorker
18 icaapi!IcaStackIoControl
19 rdpwsx!SendConnectProviderResponse
1a rdpwsx!MCSConnectProviderResponse
1b rdpwsx!GCCConferenceCreateResponse
1c rdpwsx!TSrvConfCreateResp
1d rdpwsx!TSrvDoConnectResponse
1e rdpwsx!TSrvDoConnect
1f rdpwsx!TSrvStackConnect
20 rdpwsx!WsxIcaStackIoControl
21 termsrv!WsxStackIoControl
22 icaapi!_IcaStackIoControl
23 icaapi!_IcaStackWaitForIca
24 icaapi!IcaStackConnectionAccept
25 termsrv!TransferConnectionToIdleWinStation
26 termsrv!WinStationTransferThread
27 kernel32!BaseThreadStart
21:56:30.609 89617F7C.E192A9F8 GCC: GCCConferenceCreateResponse entry
21:56:30.609 89617F7C.E192A9F8 GCC: gccEncodeUserData entry
21:56:30.609 89617F7C.E192A9F8 GCC: gccEncodeUserData exit - 0x0
21:56:30.609 89617F7C.E192A9F8 GCC: Calling MCSConnectProviderResponse - hDomain 0xd63f88, result 0x0, pUserData 0xd635e0, UserDataLength 0x11b
21:56:30.609 89617F7C.E192A9F8 TermDD: IcaDeviceControlStack, fc 1280 (enter)
21:56:30.609 89617F7C.E192A9F8 RDP E1026010 WD_Ioctl 0489 IOCTL_T120_REQUEST (1280)
21:56:30.609 89617F7C.E192A9F8 TermDD: IcaBufferAlloc: 0x897a9020, Status=0x0
21:56:30.609 89617F7C.E192A9F8 TermDD: IcaCallNextDriver, ProcIndex=2 (enter)
Breakpoint 10 hit
TDTCP!TdRawWrite:
b9ebfcd6 55 push ebp
0: kd> kc
00 TDTCP!TdRawWrite
01 termdd!_IcaCallSd
02 termdd!IcaCallNextDriver
03 RDPWD!SendOutBuf
04 RDPWD!ConnectProviderResponseFunc
05 RDPWD!MCSIcaT120Request
06 RDPWD!WD_Ioctl
07 termdd!_IcaCallSd
08 termdd!_IcaCallStack
09 termdd!IcaDeviceControlStack
0a termdd!IcaDeviceControl
0b termdd!IcaDispatch
0c nt!IofCallDriver
0d nt!IopSynchronousServiceTail
0e nt!IopXxxControlFile
0f nt!NtDeviceIoControlFile
10 nt!_KiSystemService
11 SharedUserData!SystemCallStub
12 ntdll!NtDeviceIoControlFile
13 icaapi!IcaIoControl
14 icaapi!_IcaStackIoControlWorker
15 icaapi!IcaStackIoControl
16 rdpwsx!SendConnectProviderResponse
17 rdpwsx!MCSConnectProviderResponse
18 rdpwsx!GCCConferenceCreateResponse
19 rdpwsx!TSrvConfCreateResp
1a rdpwsx!TSrvDoConnectResponse
1b rdpwsx!TSrvDoConnect
1c rdpwsx!TSrvStackConnect
1d rdpwsx!WsxIcaStackIoControl
1e termsrv!WsxStackIoControl
1f icaapi!_IcaStackIoControl
20 icaapi!_IcaStackWaitForIca
21 icaapi!IcaStackConnectionAccept
22 termsrv!TransferConnectionToIdleWinStation
23 termsrv!WinStationTransferThread
24 kernel32!BaseThreadStart
0: kd> g
21:56:30.609 89617F7C.E192A9F8 TdRawWrite 0333, 897a9020