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]  ""
