RDPWD!MCSAttachUserRequest函数分析之RDPWD!Domain结构中的ChannelList和UserAttachmentList

RDPWD!MCSAttachUserRequest函数分析之RDPWD!Domain结构中的ChannelList和UserAttachmentList

第一部分:

1: kd> kc

00 RDPWD!MCSAttachUserRequest
01 RDPWD!NM_Connect

02 RDPWD!SM_Connect

03 RDPWD!WDWConnect

04 RDPWD!WDWConfConnect

05 RDPWD!WD_Ioctl

06 termdd!_IcaCallSd

07 termdd!_IcaCallStack

08 termdd!IcaDeviceControlStack

09 termdd!IcaDeviceControl

0a termdd!IcaDispatch

0b nt!IofCallDriver

0c nt!IopSynchronousServiceTail

0d nt!IopXxxControlFile

0e nt!NtDeviceIoControlFile

0f nt!_KiSystemService

10 SharedUserData!SystemCallStub

11 ntdll!NtDeviceIoControlFile

12 icaapi!IcaIoControl

13 icaapi!_IcaStackIoControlWorker

14 icaapi!IcaStackIoControl

15 rdpwsx!TSrvInitWDConnectInfo

16 rdpwsx!TSrvInitWD

17 rdpwsx!TSrvConfCreateResp

18 rdpwsx!TSrvDoConnectResponse

19 rdpwsx!TSrvDoConnect

1a rdpwsx!TSrvStackConnect

1b rdpwsx!WsxIcaStackIoControl

1c termsrv!WsxStackIoControl

1d icaapi!_IcaStackIoControl

1e icaapi!_IcaStackWaitForIca

1f icaapi!IcaStackConnectionAccept

20 termsrv!TransferConnectionToIdleWinStation

21 termsrv!WinStationTransferThread

22 kernel32!BaseThreadStart

1: kd> dv

hDomain = 0xe1143540

UserCallback = 0xb9d34970

SDCallback = 0xb9d1e8f0

UserDefined = 0xe116ee30

phUser = 0xb9a103c8

pMaxSendSize = 0xb9a103ac

pbCompleted = 0xb9a103cf "???"

1: kd> dt RDPWD!Domain 0xe1143540

+0x000 pContext : 0x895b736c _SDCONTEXT

+0x004 StackClass : 0 ( Stack_Primary )

+0x008 StatusDead : 0 ''

+0x00c PseudoRefCount : 0n1

+0x010 StackMode : 0

+0x014 bChannelBound : 0y1

+0x014 bCanSendData : 0y1

+0x014 bT120StartReceived : 0y1

+0x014 bDPumReceivedNotInput : 0y0

+0x014 bEndConnectionPacketReceived : 0y0

+0x014 bTopProvider : 0y1

+0x014 bCurrentPacketFastPath : 0y0

+0x018 pSMData : 0xe116e7c8 Void

+0x01c ReceiveBufSize : 0x800

+0x020 pReassembleData : (null)

+0x024 StoredDataLength : 0

+0x028 PacketDataLength : 0

+0x02c PacketHeaderLength : 4

+0x030 pStat : 0x895efa58 _PROTOCOLSTATUS
+0x034 ChannelList : SList

+0x068 MaxX224DataSize : 0xfff8

+0x06c X224SourcePort : 0

+0x070 MaxSendSize : 0xffef
+0x074 UserAttachmentList : SList

+0x0a8 DomParams : DomainParameters
+0x0c8 NextAvailDynChannel : 0x3ea

+0x0cc State : 0n3

+0x0d0 DelayedDPumReason : 0

+0x0d4 pBrokenEvent : (null)

+0x0d8 shadowChannel : 0
+0x0dc PreallocUA : [2] UserAttachment
+0x174 PreallocChannel : [5] MCSChannel

+0x2b4 PacketBuf : [1] ""

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!SList *)0xe11435b4))

(*((RDPWD!SList *)0xe11435b4)) [Type: SList]

+0x000\] Hdr \[Type: _SListHeader

+0x014\] InitialList \[Type: _SListNode \[4\]

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListHeader *)0xe11435b4))

(*((RDPWD!_SListHeader *)0xe11435b4)) [Type: _SListHeader]

+0x000\] NEntries : 0x0 \[Type: unsigned int

+0x004\] MaxEntries : 0x4 \[Type: unsigned int

+0x008\] HeadOffset : 0x0 \[Type: unsigned int

+0x00c\] CurrOffset : 0xffffffff \[Type: unsigned int

+0x010\] Entries : 0xe11435c8 \[Type: _SListNode \*

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!DomainParameters *)0xe11435e8))

(*((RDPWD!DomainParameters *)0xe11435e8)) [Type: DomainParameters]

+0x000\] MaxChannels : 0x22 \[Type: unsigned int

+0x004\] MaxUsers : 0x3 \[Type: unsigned int

+0x008\] MaxTokens : 0x0 \[Type: unsigned int

+0x00c\] NumPriorities : 0x1 \[Type: unsigned int

+0x010\] MinThroughput : 0x0 \[Type: unsigned int

+0x014\] MaxDomainHeight : 0x1 \[Type: unsigned int

+0x018\] MaxPDUSize : 0xfff8 \[Type: unsigned int

+0x01c\] ProtocolVersion : 0x2 \[Type: unsigned int

// Check against domain max users param.

if (SListGetEntries(&pDomain->UserAttachmentList) ==

pDomain->DomParams.MaxUsers) {

ErrOut(pDomain->pContext, "AttachUserReq(): Too many users");

return MCS_TOO_MANY_USERS;

}

#define SListGetEntries(pSL) ((pSL)->Hdr.NEntries)

NumPreallocUA domain.h (termsrv\drivers\rdp\inc)

// Primary remote user and local user.
#define NumPreallocUA 2

// Allocate a UserAttachment. Try the prealloc list first.

pUA = NULL;

for (i = 0; i < NumPreallocUA; i++) {

if (!pDomain->PreallocUA[i].bInUse) {

pUA = &pDomain->PreallocUA[i];

pUA->bInUse = TRUE;

}

}

1: kd> dt RDPWD!Domain 0xe1143540

+0x0dc PreallocUA : [2] UserAttachment

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!UserAttachment (*)[2])0xe114361c))

(*((RDPWD!UserAttachment (*)[2])0xe114361c)) [Type: UserAttachment [2]]

0\] \[Type: UserAttachment

1\] \[Type: UserAttachment

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!UserAttachment *)0xe114361c))

(*((RDPWD!UserAttachment *)0xe114361c)) [Type: UserAttachment]

+0x000\] pDomain : 0x0 \[Type: _Domain \*

+0x004\] bLocal : 0x0 \[Type: unsigned char

+0x005\] bPreallocated : 0x1 \[Type: unsigned char

+0x006\] bInUse : 0x0 \[Type: unsigned char\] //\[+0x006\] bInUse : 0x0 \[+0x008\] UserDefined : 0x0 \[Type: void \*

+0x00c\] UserID : 0x0 \[Type: unsigned int

+0x010\] JoinedChannelList \[Type: SList

+0x044\] Callback : 0x0 \[Type: void (\*)(void \*,unsigned int,void \*,void \*)

+0x048\] SDCallback : 0x0 \[Type: unsigned char (\*)(unsigned char \*,unsigned int,void \*,void \*,unsigned char,void \*,MCSPriority,unsigned int,unsigned int)

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!UserAttachment *)0xe1143668))

(*((RDPWD!UserAttachment *)0xe1143668)) [Type: UserAttachment]

+0x000\] pDomain : 0x0 \[Type: _Domain \*

+0x004\] bLocal : 0x0 \[Type: unsigned char

+0x005\] bPreallocated : 0x1 \[Type: unsigned char

+0x006\] bInUse : 0x0 \[Type: unsigned char\] //\[+0x006\] bInUse : 0x0 \[+0x008\] UserDefined : 0x0 \[Type: void \*

+0x00c\] UserID : 0x0 \[Type: unsigned int

+0x010\] JoinedChannelList \[Type: SList

+0x044\] Callback : 0x0 \[Type: void (\*)(void \*,unsigned int,void \*,void \*)

+0x048\] SDCallback : 0x0 \[Type: unsigned char (\*)(unsigned char \*,unsigned int,void \*,void \*,unsigned char,void \*,MCSPriority,unsigned int,unsigned int)

+0x010\] JoinedChannelList 1: kd\> dx -id 0,0,89515c28 -r1 (\*((RDPWD!SList \*)0xe1143678)) (\*((RDPWD!SList \*)0xe1143678)) \[Type: SList

+0x000\] Hdr \[Type: _SListHeader

+0x014\] InitialList \[Type: _SListNode \[4\]

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListHeader *)0xe1143678))

(*((RDPWD!_SListHeader *)0xe1143678)) [Type: _SListHeader]

+0x000\] NEntries : 0x0 \[Type: unsigned int

+0x004\] MaxEntries : 0x0 \[Type: unsigned int

+0x008\] HeadOffset : 0x0 \[Type: unsigned int

+0x00c\] CurrOffset : 0x0 \[Type: unsigned int

+0x010\] Entries : 0x0 \[Type: _SListNode \*

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListNode (*)[4])0xe114368c))

(*((RDPWD!_SListNode (*)[4])0xe114368c)) [Type: _SListNode [4]]

0\] \[Type: _SListNode

1\] \[Type: _SListNode

2\] \[Type: _SListNode

3\] \[Type: _SListNode

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListNode *)0xe114368c))

(*((RDPWD!_SListNode *)0xe114368c)) [Type: _SListNode]

+0x000\] Key : 0x0 \[Type: unsigned int

+0x004\] Value : 0x0 \[Type: void \*

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListNode *)0xe1143694))

(*((RDPWD!_SListNode *)0xe1143694)) [Type: _SListNode]

+0x000\] Key : 0x0 \[Type: unsigned int

+0x004\] Value : 0x0 \[Type: void \*

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListNode *)0xe114369c))

(*((RDPWD!_SListNode *)0xe114369c)) [Type: _SListNode]

+0x000\] Key : 0x0 \[Type: unsigned int

+0x004\] Value : 0x0 \[Type: void \*

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListNode *)0xe11436a4))

(*((RDPWD!_SListNode *)0xe11436a4)) [Type: _SListNode]

+0x000\] Key : 0x0 \[Type: unsigned int

+0x004\] Value : 0x0 \[Type: void \*

if (pUA != NULL) {

// Store info in UA.

pUA->UserDefined = UserDefined;

SListInit(&pUA->JoinedChannelList, DefaultNumChannels);

pUA->pDomain = pDomain;

pUA->Callback = UserCallback;

pUA->SDCallback = SDCallback;

}

void SListInit(PSList pSL, unsigned NItems)

{

// Initialize the private member variables. Use preallocated array for

// initial node array.

pSL->Hdr.NEntries = 0;

pSL->Hdr.MaxEntries = SListDefaultNumEntries;

pSL->Hdr.HeadOffset = 0;

pSL->Hdr.CurrOffset = 0xFFFFFFFF;

pSL->Hdr.Entries = pSL->InitialList;

}

第二部分:

// Allocate a UserAttachment. Try the prealloc list first.

pUA = NULL;

for (i = 0; i < NumPreallocUA; i++) {

if (!pDomain->PreallocUA[i].bInUse) {

pUA = &pDomain->PreallocUA[i];

pUA->bInUse = TRUE;

}

} //之后:

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!UserAttachment (*)[2])0xe114361c))

(*((RDPWD!UserAttachment (*)[2])0xe114361c)) [Type: UserAttachment [2]]

0\] \[Type: UserAttachment

1\] \[Type: UserAttachment

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!UserAttachment *)0xe114361c))

(*((RDPWD!UserAttachment *)0xe114361c)) [Type: UserAttachment]

+0x000\] pDomain : 0x0 \[Type: _Domain \*

+0x004\] bLocal : 0x0 \[Type: unsigned char

+0x005\] bPreallocated : 0x1 \[Type: unsigned char

+0x006\] bInUse : 0x1 \[Type: unsigned char

+0x008\] UserDefined : 0x0 \[Type: void \*

+0x00c\] UserID : 0x0 \[Type: unsigned int

+0x010\] JoinedChannelList \[Type: SList

+0x044\] Callback : 0x0 \[Type: void (\*)(void \*,unsigned int,void \*,void \*)

+0x048\] SDCallback : 0x0 \[Type: unsigned char (\*)(unsigned char \*,unsigned int,void \*,void \*,unsigned char,void \*,MCSPriority,unsigned int,unsigned int)

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!UserAttachment *)0xe1143668))

(*((RDPWD!UserAttachment *)0xe1143668)) [Type: UserAttachment]

+0x000\] pDomain : 0x0 \[Type: _Domain \*

+0x004\] bLocal : 0x0 \[Type: unsigned char

+0x005\] bPreallocated : 0x1 \[Type: unsigned char

+0x006\] bInUse : 0x1 \[Type: unsigned char

+0x008\] UserDefined : 0x0 \[Type: void \*

+0x00c\] UserID : 0x0 \[Type: unsigned int

+0x010\] JoinedChannelList \[Type: SList

+0x044\] Callback : 0x0 \[Type: void (\*)(void \*,unsigned int,void \*,void \*)

+0x048\] SDCallback : 0x0 \[Type: unsigned char (\*)(unsigned char \*,unsigned int,void \*,void \*,unsigned char,void \*,MCSPriority,unsigned int,unsigned int)

1: kd> r

eax=e11436ba ebx=8947eef8 ecx=00000000 edx=e1143540 esi=e1143668 edi=e1143540

eip=b9d79909 esp=b9a10368 ebp=b9a10374 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

RDPWD!MCSAttachUserRequest+0x67:

b9d79909 85f6 test esi,esi

1: kd> dt UserAttachment e1143668

RDPWD!UserAttachment

+0x000 pDomain : (null)

+0x004 bLocal : 0 ''

+0x005 bPreallocated : 0x1 ''

+0x006 bInUse : 0x1 ''

+0x008 UserDefined : (null)

+0x00c UserID : 0

+0x010 JoinedChannelList : SList

+0x044 Callback : (null)

+0x048 SDCallback : (null)

if (pUA != NULL) {

// Store info in UA.

pUA->UserDefined = UserDefined;

SListInit(&pUA->JoinedChannelList, DefaultNumChannels);

pUA->pDomain = pDomain;

pUA->Callback = UserCallback;

pUA->SDCallback = SDCallback;

} //之后:

1: kd> dt UserAttachment e1143668

RDPWD!UserAttachment

+0x000 pDomain : (null)

+0x004 bLocal : 0 ''

+0x005 bPreallocated : 0x1 ''

+0x006 bInUse : 0x1 ''

+0x008 UserDefined : 0xe116ee30 Void

+0x00c UserID : 0

+0x010 JoinedChannelList : SList

+0x044 Callback : (null)

+0x048 SDCallback : (null)

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!SList *)0xe1143678))

(*((RDPWD!SList *)0xe1143678)) [Type: SList]

+0x000\] Hdr \[Type: _SListHeader

+0x014\] InitialList \[Type: _SListNode \[4\]

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListHeader *)0xe1143678))

(*((RDPWD!_SListHeader *)0xe1143678)) [Type: _SListHeader]

+0x000\] NEntries : 0x0 \[Type: unsigned int

+0x004\] MaxEntries : 0x4 \[Type: unsigned int

+0x008\] HeadOffset : 0x0 \[Type: unsigned int

+0x00c\] CurrOffset : 0xffffffff \[Type: unsigned int

+0x010\] Entries : 0xe114368c \[Type: _SListNode \*

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListNode (*)[4])0xe114368c))

(*((RDPWD!_SListNode (*)[4])0xe114368c)) [Type: _SListNode [4]]

0\] \[Type: _SListNode

1\] \[Type: _SListNode

2\] \[Type: _SListNode

3\] \[Type: _SListNode

参考:

BOOL RDPCALL NM_Connect(PVOID pNMHandle, PRNS_UD_CS_NET pUserDataIn)

{

MCSErr = MCSAttachUserRequest(pRealNMHandle->hDomain,

NM_MCSUserCallback,

SM_MCSSendDataCallback,

pNMHandle,

&UserHandleTemp,

&MaxSendSizeTemp,

(BOOLEAN *)(&bCompleted));

参考:

typedef struct tagNM_HANDLE_DATA

{

/************************************************************************/

/* pSMHandle MUST be first here to allow SM_MCSSendDataCallback() to */

/* get its context pointer through double-indirection. */

/************************************************************************/

PVOID pSMHandle;

PTSHARE_WD pWDHandle;

PSDCONTEXT pContext;

UserHandle hUser;

ChannelID channelID;

ChannelHandle hChannel;

DomainHandle hDomain;

UINT32 connectStatus;

UINT32 userID;

UINT32 maxPDUSize;

BOOL dead;

/************************************************************************/

/* Virtual channel information */

/* - channelCount - number of channels in this session */

/* - channelArrayCount - number of entries in the array */

/* - channelData - information held for each channel */

/* */

/* Channel 7 is used by RDPDD. I want to use the virtual channel ID as */

/* an index into channelData, hence entry 7 is left blank. If there are */

/* more than 7 channels, channelArrayCount will be channelCount + 1. */

/************************************************************************/

UINT channelCount;

UINT channelArrayCount;

NM_CHANNEL_DATA channelData[VIRTUAL_MAXIMUM];

} NM_HANDLE_DATA, *PNM_HANDLE_DATA;

1: kd> dv

hDomain = 0xe1143540

UserCallback = 0xb9d34970

SDCallback = 0xb9d1e8f0

UserDefined = 0xe116ee30

// Allocate new UserID.
pUA->UserID = GetNewDynamicChannel(pDomain);

if (pUA->UserID == 0) {

ErrOut(pDomain->pContext, "AttachUser: Unable to get new dyn channel");

MCSErr = MCS_TOO_MANY_CHANNELS;

goto PostAllocUA;

}

// Gets a new dynamic channel number, but does not add it to channel list.

// Returns 0 if none available.

ChannelID GetNewDynamicChannel(Domain *pDomain)

{

if (SListGetEntries(&pDomain->ChannelList) >=

pDomain->DomParams.MaxChannels)

return 0;

pDomain->NextAvailDynChannel++;

ASSERT(pDomain->NextAvailDynChannel <= 65535);

return (pDomain->NextAvailDynChannel - 1);

}

1: kd> dt RDPWD!Domain 0xe1143540

+0x000 pContext : 0x895b736c _SDCONTEXT

+0x004 StackClass : 0 ( Stack_Primary )

+0x008 StatusDead : 0 ''

+0x00c PseudoRefCount : 0n1

+0x010 StackMode : 0

+0x014 bChannelBound : 0y1

+0x014 bCanSendData : 0y1

+0x014 bT120StartReceived : 0y1

+0x014 bDPumReceivedNotInput : 0y0

+0x014 bEndConnectionPacketReceived : 0y0

+0x014 bTopProvider : 0y1

+0x014 bCurrentPacketFastPath : 0y0

+0x018 pSMData : 0xe116e7c8 Void

+0x01c ReceiveBufSize : 0x800

+0x020 pReassembleData : (null)

+0x024 StoredDataLength : 0

+0x028 PacketDataLength : 0

+0x02c PacketHeaderLength : 4

+0x030 pStat : 0x895efa58 _PROTOCOLSTATUS

+0x034 ChannelList : SList

+0x068 MaxX224DataSize : 0xfff8

+0x06c X224SourcePort : 0

+0x070 MaxSendSize : 0xffef

+0x074 UserAttachmentList : SList

+0x0a8 DomParams : DomainParameters

+0x0c8 NextAvailDynChannel : 0x3ea //pDomain->NextAvailDynChannel

+0x0cc State : 0n3

+0x0d0 DelayedDPumReason : 0

+0x0d4 pBrokenEvent : (null)

+0x0d8 shadowChannel : 0

+0x0dc PreallocUA : [2] UserAttachment

+0x174 PreallocChannel : [5] MCSChannel

+0x2b4 PacketBuf : [1] ""

1: kd> dt UserAttachment e1143668

RDPWD!UserAttachment

+0x000 pDomain : 0xe1143540 _Domain

+0x004 bLocal : 0x1 ''

+0x005 bPreallocated : 0x1 ''

+0x006 bInUse : 0x1 ''

+0x008 UserDefined : 0xe116ee30 Void
+0x00c UserID : 0x3ea //+0x00c UserID : 0x3ea

+0x010 JoinedChannelList : SList

+0x044 Callback : 0xb9d34970 void RDPWD!NM_MCSUserCallback+0

+0x048 SDCallback : 0xb9d1e8f0 unsigned char RDPWD!SM_MCSSendDataCallback+0

1: kd> dt RDPWD!Domain 0xe1143540

+0x000 pContext : 0x895b736c _SDCONTEXT

+0x004 StackClass : 0 ( Stack_Primary )

+0x0c8 NextAvailDynChannel : 0x3eb

// Allocate a Channel. Try the prealloc list first.

pMCSChannel = NULL;

for (i = 0; i < NumPreallocChannel; i++) {

if (!pDomain->PreallocChannel[i].bInUse) {

pMCSChannel = &pDomain->PreallocChannel[i];

pMCSChannel->bInUse = TRUE;

}

}

// Primary remote user and local user.

#define NumPreallocUA 2

// One channel for each of remote and local user, plus share, clipboard, and

// printer redir channels.

#define NumPreallocChannel (NumPreallocUA + 3)

1: kd> dt RDPWD!Domain 0xe1143540

+0x0dc PreallocUA : [2] UserAttachment

+0x174 PreallocChannel : [5] MCSChannel

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel (*)[5])0xe11436b4))

(*((RDPWD!MCSChannel (*)[5])0xe11436b4)) [Type: MCSChannel [5]]

0\] \[Type: MCSChannel

1\] \[Type: MCSChannel

2\] \[Type: MCSChannel

3\] \[Type: MCSChannel

4\] \[Type: MCSChannel

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe11436b4))

(*((RDPWD!MCSChannel *)0xe11436b4)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x0 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe11436f4))

(*((RDPWD!MCSChannel *)0xe11436f4)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x0 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe1143774))

(*((RDPWD!MCSChannel *)0xe1143774)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x0 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe1143774))

(*((RDPWD!MCSChannel *)0xe1143774)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x0 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe11437b4))

(*((RDPWD!MCSChannel *)0xe11437b4)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x0 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

// Allocate a Channel. Try the prealloc list first.

pMCSChannel = NULL;

for (i = 0; i < NumPreallocChannel; i++) {

if (!pDomain->PreallocChannel[i].bInUse) {

pMCSChannel = &pDomain->PreallocChannel[i];

pMCSChannel->bInUse = TRUE;

}

}//之后:

+0x174 PreallocChannel : [5] MCSChannel

+0x2b4 PacketBuf : [1] ""

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel (*)[5])0xe11436b4))

(*((RDPWD!MCSChannel (*)[5])0xe11436b4)) [Type: MCSChannel [5]]

0\] \[Type: MCSChannel

1\] \[Type: MCSChannel

2\] \[Type: MCSChannel

3\] \[Type: MCSChannel

4\] \[Type: MCSChannel

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe11436b4))

(*((RDPWD!MCSChannel *)0xe11436b4)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x1 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe11436f4))

(*((RDPWD!MCSChannel *)0xe11436f4)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x1 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe1143734))

(*((RDPWD!MCSChannel *)0xe1143734)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x1 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe1143774))

(*((RDPWD!MCSChannel *)0xe1143774)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x1 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe11437b4))

(*((RDPWD!MCSChannel *)0xe11437b4)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 0 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x1 \[Type: unsigned char

+0x03c\] ID : 0x0 \[Type: unsigned int

1: kd> r

eax=e114382d ebx=e11437b4 ecx=00000000 edx=e1143540 esi=e1143668 edi=e1143540

eip=b9d799a1 esp=b9a10368 ebp=b9a10374 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

RDPWD!MCSAttachUserRequest+0xff:

b9d799a1 85db test ebx,ebx

pMCSChanne=ebx=e11437b4 最后一个

if (pMCSChannel != NULL) {

pMCSChannel->Type = Channel_UserID;

pMCSChannel->ID = pUA->UserID;

SListInit(&pMCSChannel->UserList, DefaultNumChannels);

}

// Types of channels possible in the MCSChannel struct below.

#define Channel_Unused 0

#define Channel_Static 1
#define Channel_UserID 2

#define Channel_Assigned 3

#define Channel_Convened 4

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!MCSChannel *)0xe11437b4))

(*((RDPWD!MCSChannel *)0xe11437b4)) [Type: MCSChannel]

+0x000\] UserList \[Type: SList

+0x034\] Type : 2 \[Type: int

+0x038\] bPreallocated : 0x1 \[Type: unsigned char

+0x039\] bInUse : 0x1 \[Type: unsigned char

+0x03c\] ID : 0x3ea \[Type: unsigned int

1: kd> dt RDPWD!MCSChannel 0xe11437b4

+0x000 UserList : SList
+0x034 Type : 0n2

+0x038 bPreallocated : 0x1 ''

+0x039 bInUse : 0x1 ''
+0x03c ID : 0x3ea

if (SListAppend(&pDomain->ChannelList, pMCSChannel->ID, pMCSChannel)) {

// Add user attachment to attachment list.

第三部分:

/*

* Append

* Inserts a value at the end of a list. Returns FALSE on error.

*/

BOOLEAN SListAppend(PSList pSL, UINT_PTR NewKey, void *NewValue)

{

unsigned Temp;

if (pSL->Hdr.NEntries < pSL->Hdr.MaxEntries ||

(pSL->Hdr.NEntries >= pSL->Hdr.MaxEntries && SListExpand(pSL))) {

Temp = pSL->Hdr.HeadOffset + pSL->Hdr.NEntries;

if (Temp >= pSL->Hdr.MaxEntries)

Temp -= pSL->Hdr.MaxEntries;

pSL->Hdr.Entries[Temp].Key = NewKey;

pSL->Hdr.Entries[Temp].Value = NewValue;

pSL->Hdr.NEntries++;

return TRUE;

}

else {

return FALSE;

}

}

1: kd> dt RDPWD!Domain 0xe1143540

+0x034 ChannelList : SList

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!SList *)0xe1143574))

(*((RDPWD!SList *)0xe1143574)) [Type: SList]

+0x000\] Hdr \[Type: _SListHeader

+0x014\] InitialList \[Type: _SListNode \[4\]

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListHeader *)0xe1143574))

(*((RDPWD!_SListHeader *)0xe1143574)) [Type: _SListHeader]

+0x000\] NEntries : 0x0 \[Type: unsigned int

+0x004\] MaxEntries : 0x4 \[Type: unsigned int

+0x008\] HeadOffset : 0x0 \[Type: unsigned int

+0x00c\] CurrOffset : 0xffffffff \[Type: unsigned int

+0x010\] Entries : 0xe1143588 \[Type: _SListNode \*

1: kd> dx -id 0,0,89515c28 -r1 ((RDPWD!_SListNode *)0xe1143588)

((RDPWD!_SListNode *)0xe1143588) : 0xe1143588 [Type: _SListNode *]

+0x000\] Key : 0x0 \[Type: unsigned int

+0x004\] Value : 0x0 \[Type: void \*

SListAppend(&pDomain->ChannelList, pMCSChannel->ID, pMCSChannel) 之后:

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!SList *)0xe1143574))

(*((RDPWD!SList *)0xe1143574)) [Type: SList]

+0x000\] Hdr \[Type: _SListHeader

+0x014\] InitialList \[Type: _SListNode \[4\]

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListHeader *)0xe1143574))

(*((RDPWD!_SListHeader *)0xe1143574)) [Type: _SListHeader]

+0x000\] NEntries : 0x1 \[Type: unsigned int

+0x004\] MaxEntries : 0x4 \[Type: unsigned int

+0x008\] HeadOffset : 0x0 \[Type: unsigned int

+0x00c\] CurrOffset : 0xffffffff \[Type: unsigned int

+0x010\] Entries : 0xe1143588 \[Type: _SListNode \*

1: kd> dx -id 0,0,89515c28 -r1 ((RDPWD!_SListNode *)0xe1143588)

((RDPWD!_SListNode *)0xe1143588) : 0xe1143588 [Type: _SListNode *]

+0x000\] Key : 0x3ea \[Type: unsigned int

+0x004\] Value : 0xe11437b4 \[Type: void \*

if (SListAppend(&pDomain->UserAttachmentList, (UINT_PTR)pUA, pUA)) {

之后:

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!SList *)0xe11435b4))

(*((RDPWD!SList *)0xe11435b4)) [Type: SList]

+0x000\] Hdr \[Type: _SListHeader

+0x014\] InitialList \[Type: _SListNode \[4\]

1: kd> dx -id 0,0,89515c28 -r1 (*((RDPWD!_SListHeader *)0xe11435b4))

(*((RDPWD!_SListHeader *)0xe11435b4)) [Type: _SListHeader]

+0x000\] NEntries : 0x1 \[Type: unsigned int

+0x004\] MaxEntries : 0x4 \[Type: unsigned int

+0x008\] HeadOffset : 0x0 \[Type: unsigned int

+0x00c\] CurrOffset : 0xffffffff \[Type: unsigned int

+0x010\] Entries : 0xe11435c8 \[Type: _SListNode \*

1: kd> dx -id 0,0,89515c28 -r1 ((RDPWD!_SListNode *)0xe11435c8)

((RDPWD!_SListNode *)0xe11435c8) : 0xe11435c8 [Type: _SListNode *]

+0x000\] Key : 0xe1143668 \[Type: unsigned int

+0x004\] Value : 0xe1143668 \[Type: void \*

*phUser = pUA;

1: kd> dv

hDomain = 0xe1143574

UserCallback = 0xb9d34970

SDCallback = 0xb9d1e8f0

UserDefined = 0xe116ee30

phUser = 0xb9a103c8

pMaxSendSize = 0xb9a103ac

pbCompleted = 0xb9a103cf ""

1: kd> dx -r1 ((RDPWD!void * *)0xb9a103c8)

((RDPWD!void * *)0xb9a103c8) : 0xb9a103c8 [Type: void * *]

0xe1143668 [Type: void *]

if (pDomain->bTopProvider) {

// The action is complete, there is no need for a callback.

*pbCompleted = TRUE;

}

总结:下面的结构修改了5处:

1: kd> dt RDPWD!Domain 0xe1143540

+0x000 pContext : 0x895b736c _SDCONTEXT

+0x004 StackClass : 0 ( Stack_Primary )

+0x008 StatusDead : 0 ''

+0x00c PseudoRefCount : 0n1

+0x010 StackMode : 0

+0x014 bChannelBound : 0y1

+0x014 bCanSendData : 0y1

+0x014 bT120StartReceived : 0y1

+0x014 bDPumReceivedNotInput : 0y0

+0x014 bEndConnectionPacketReceived : 0y0

+0x014 bTopProvider : 0y1

+0x014 bCurrentPacketFastPath : 0y0

+0x018 pSMData : 0xe116e7c8 Void

+0x01c ReceiveBufSize : 0x800

+0x020 pReassembleData : (null)

+0x024 StoredDataLength : 0

+0x028 PacketDataLength : 0

+0x02c PacketHeaderLength : 4

+0x030 pStat : 0x895efa58 _PROTOCOLSTATUS

+0x034 ChannelList : SList //第1处

+0x068 MaxX224DataSize : 0xfff8

+0x06c X224SourcePort : 0

+0x070 MaxSendSize : 0xffef

+0x074 UserAttachmentList : SList //第2处

+0x0a8 DomParams : DomainParameters

+0x0c8 NextAvailDynChannel : 0x3eb //第3处

+0x0cc State : 0n3

+0x0d0 DelayedDPumReason : 0

+0x0d4 pBrokenEvent : (null)

+0x0d8 shadowChannel : 0

+0x0dc PreallocUA : [2] UserAttachment //第4处

+0x174 PreallocChannel : [5] MCSChannel //第5处

+0x2b4 PacketBuf : [1] ""