WSAStartup(MAKEWORD(2,2), &Ws)
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(CientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
send(CientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
1. WSAStartup
准备模块
2. socket函数
调用WSASocketW(IN INT af,IN INT type, IN INT protocol, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, IN GROUP g, IN DWORD dwFlags)
在WSASocketW函数中:
if (!lpProtocolInfo)
{
lpProtocolInfo = &ProtocolInfo;
ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
ProtocolInfo.iAddressFamily = af;
ProtocolInfo.iSocketType = type;
ProtocolInfo.iProtocol = protocol;
}
PCATALOG_ENTRY Provider = LocateProvider(lpProtocolInfo); 查找provider所在的dll名
Status = LoadProvider(Provider, lpProtocolInfo);加载dll,并调用此dll的导出函数 WSPStartup()初始化provider
。。。
Socket = Provider->ProcTable.lpWSPSocket(af,type,protocol,lpProtocolInfo,g,dwFlags,&Status);
在catalog.c中,有 VOID CreateCatalog(VOID),其中有一句 Provider = CreateCatalogEntry(L"msafd.dll");目前provider只有这一个
在msafd.dll的dllmain.c中有SOCKET WSPAPI WSPSocket(int AddressFamily, int SocketType,
int Protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags, LPINT lpErrno)
在此函数中有 SockGetTdiName,它根据输入参数可取得&TransportName等值;此&TransportName是具体协议驱动的名称。
SockGetTdiName (&AddressFamily, &SocketType, &Protocol, g, dwFlags, &TransportName, &HelperDLLContext, &HelperData, &HelperEvents);
接着将取出来的驱动名放入EaBuffer中:
AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1);
RtlCopyMemory (AfdPacket->TransportName, TransportName.Buffer, TransportName.Length + sizeof(WCHAR));
构建一个内核对象:
RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint");
InitializeObjectAttributes (&Object,&DevName,OBJ_CASE_INSENSITIVE | OBJ_INHERIT,0,0);
打开驱动设备,取得驱动句柄放入sock中,注意EABuffer已经传入
Status = NtCreateFile(&Sock, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &Object, &IOSB, NULL,
0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, 0, EABuffer, SizeOfEA);
驱动层:
在afd驱动中有 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
case IRP_MJ_CREATE:
return AfdCreateSocket(DeviceObject, Irp, IrpSp);
case IOCTL_AFD_SEND_DATAGRAM:
return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
驱动中有 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,PIO_STACK_LOCATION IrpSp)
在此函数中EaBuffer被取出:
EaInfo = Irp->AssociatedIrp.SystemBuffer;
PAFD_CREATE_PACKET ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
随后TdiDeviceName被存入FCB中
RtlCopyMemory( FCB->TdiDeviceName.Buffer, ConnectInfo->TransportName, FCB->TdiDeviceName.Length );
然后FCB被存储到IrpSp
FileObject = IrpSp->FileObject;
FileObject->FsContext = FCB
至此,
传输层协议名被保存到了设备栈中。
在应用层:send()->WSPSendTo():
Status = NtDeviceIoControlFile((HANDLE)Handle, Event, APCFunction, APCContext, IOSB, IOCTL_AFD_SEND_DATAGRAM, &SendInfo, sizeof(SendInfo), NULL, 0);
说明发送数据的IO号是IOCTL_AFD_SEND_DATAGRAM,在afd驱动中找到它,
对应的是AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp )。在此函数中:
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
WarmSocketForBind( FCB );
而WarmSocketForBind函数是根据 TdiDeviceName取到FCB->AddressFile.Object文件对象的,在WarmSocketForBind函数中
TdiOpenAddressFile(&FCB->TdiDeviceName, FCB->LocalAddress, &FCB->AddressFile.Handle, &FCB->AddressFile.Object );
然后TdiOpenAddressFile继续调用:
TdiOpenDevice(DeviceName, EaLength, EaInfo, AddressHandle, AddressObject);
此函数再调用ZwCreateFile、ObReferenceObjectByHandle等函数取得AddressObject
继续AfdPacketSocketWriteData的执行,TdiSendDatagram被用来将数据包发给协议驱动
TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len,
TargetAddress, &FCB->SendIrp.Iosb, PacketSocketSendComplete, FCB);
TdiSendDatagram执行DeviceObject = IoGetRelatedDeviceObject(TransportObject);
和 TdiCall(*Irp, DeviceObject, NULL, Iosb);-> Status = IoCallDriver(DeviceObject, Irp);
总的来说,AfdPacketSocketWriteData通过FCB中的TdiDeviceName取到TransPortObject,然后再通过IoGetRelatedDeviceObject取得设备对象DeviceObject,
并将Irp发给此DeviceObject