Winsock kernel ? [ Question ]

how to construct Completion routine in winsock kernel ?
I found a code but i do want alternative solutions.
or Can anybody explain what’s happening ?

[Below Completion routine]
static
NTSTATUS
NTAPI
CompletionRoutine(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp,
__in PKEVENT CompletionEvent
)
{
ASSERT( CompletionEvent );

KeSetEvent(CompletionEvent, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

[Below actual function call]

KeInitializeEvent(&CompletionEvent, SynchronizationEvent, FALSE);

IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
IoSetCompletionRoutine(Irp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);

//
// Create the socket
//

Status = WskProvider->Dispatch->WskSocket(
WskProvider->Client,
AF_INET,
SOCK_STREAM,
IPPROTO_TCP,
WSK_FLAG_CONNECTION_SOCKET,
NULL,
NULL,
NULL,
NULL,
NULL,
Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}

if (!NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): WskSocket() failed with status 0x%08X\n”, Status);
return Status;
}

WskSocket = (PWSK_SOCKET)Irp->IoStatus.Information;
SocketDispatch = (PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch;

KeResetEvent(&CompletionEvent);
IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
IoSetCompletionRoutine(Irp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);

//
// Bind the socket
//

Status = SocketDispatch->WskBind(
WskSocket,
(PSOCKADDR)LocalAddress,
0,
Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}

if (!NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): WskBind() failed with status 0x%08X\n”, Status);
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}

DbgPrint(“MakeHttpRequest(): Connecting to the %u.%u.%u.%u:%u…\n”,
RemoteAddress->sin_addr.S_un.S_un_b.s_b1,
RemoteAddress->sin_addr.S_un.S_un_b.s_b2,
RemoteAddress->sin_addr.S_un.S_un_b.s_b3,
RemoteAddress->sin_addr.S_un.S_un_b.s_b4,
HTONS(RemoteAddress->sin_port));

KeResetEvent(&CompletionEvent);
IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
IoSetCompletionRoutine(Irp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);

//
// Establish a connection with the destination host
//

Status = SocketDispatch->WskConnect( // You can use WskSocketConnect() instead of sequence
WskSocket, // of WskSocket(), WskBind(), WskConnect() calls
(PSOCKADDR)RemoteAddress,
0,
Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}

if (!NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): WskConnect() failed with status 0x%08X\n”, Status);
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}

DbgPrint(“MakeHttpRequest(): Connected, sending the request…\n”);

KeResetEvent(&CompletionEvent);
IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
IoSetCompletionRoutine(Irp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);

//
// Now we can send the request
//

Status = SocketDispatch->WskSend(
WskSocket,
HttpRequest,
0,
Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}

if (!NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): WskSend() failed with status 0x%08X\n”, Status);
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}

if (Irp->IoStatus.Information != HttpRequest->Length) {
DbgPrint(“MakeHttpRequest(): Sent %u bytes of the request instead of %u bytes\n”,
Irp->IoStatus.Information, HttpRequest->Length);
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}

DbgPrint(“MakeHttpRequest(): %u bytes of the request sent successfully\n”, HttpRequest->Length);
DbgPrint(“MakeHttpRequest(): Receiving the answer…\n”);

//
// Receive the server’s answer
//

Status = ReceiveHttpResponse(SocketDispatch, WskSocket, HttpResponse);

if (NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): Received %u bytes of data\n”, HttpResponse->Length);
}

CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}

xxxxx@yopmail.com wrote:

how to construct Completion routine in winsock kernel ?
I found a code but i do want alternative solutions.
or Can anybody explain what’s happening ?

I’m not sure what you want to know. This is pretty standard completion
routine processing. It essentially makes the calls synchronous. After
every call they immediately block waiting for the event to fire, and the
only thing the completion routine does is fire the event. That lets the
original thread continue on to make the next call


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

is there any alternative ?

xxxxx@yopmail.com wrote:

is there any alternative ?

Why?

Look, here’s the problem with your question. You have code that works,
that demonstrates how this kind of thing has been done. The rest of us
do things that way, because that’s the way it’s done. Is that the ONLY
way to do it? Of course not, but if there’s something you don’t like in
that method, then you need to tell us what it is you don’t like. It’s
possible that you simply misunderstand what’s going on. If you tell us
your concerns, we can either ease your concerns, or suggest another path.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

@Tim Roberts
Thank you for your kind reply.
The problem i am facing with the “Event” as you mentioned above “firing the event”.
And i need something with “Completion Routine” by wsk.
My problem with IoSetCompletionRoutine… 3rd Argument. and looking for any other way to do it.

> My problem with IoSetCompletionRoutine… 3rd Argument. and looking for any other way to do it.

You can pass any structure of your own in the CR’s 3rd Argument, not necessary KEVENT


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

xxxxx@yopmail.com wrote:

The problem i am facing with the “Event” as you mentioned above “firing the event”.

WHAT problem? The caller creates a KEVENT and passes it, the completion
routine sets the event, the caller waits for it.

And i need something with “Completion Routine” by wsk.

That’s what you have, right?

My problem with IoSetCompletionRoutine… 3rd Argument. and looking for any other way to do it.

You have still not explained why the code you have is not working for you.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

It confused me because the Completion routine documented in msdn is not like the code i have posted.
https://msdn.microsoft.com/en-us/library/windows/hardware/ff543841(v=vs.85).aspx

Thanks all guys for helping out. You all amazing.

xxxxx@yopmail.com wrote:

It confused me because the Completion routine documented in msdn is not like the code i have posted.
https://msdn.microsoft.com/en-us/library/windows/hardware/ff543841(v=vs.85).aspx

That’s an “asynchronous” example. They just fire off the request and
return. The processing to finish the request then has to be done in the
completion routine, because there’s nobody waiting for an event.

Synchronous is somewhat more natural, because things in your request
routine happen in natural order. It all depends on what you need.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Is this the conclusion ?

Before every action in WSK ( such : Create, Bind, send. Receive ) there is an Event which indeed
blocking the actions and releasing or permitting the actions will occur one after another simultaneously ?

Can you give me reference to learn about “asynchronous” ?

Thanks

xxxxx@yopmail.com wrote:

Is this the conclusion ?
> Before every action in WSK ( such : Create, Bind, send. Receive ) there is an Event which indeed
> blocking the actions and releasing or permitting the actions will occur one after another simultaneously ?

It is horribly impolite of me to point this out, but I had to chuckle at
your wording, “one after another simultaneously”. Those are two
directly opposing concepts.

In fact, “one after another” is the definition of “synchronous” and
“simultaneously” is the definition of “asynchronous”.

The user-mode socket operations become I/O requests in the kernel, where
they flow down the various driver layers until they make their way to a
cable. The Windows Filtering Platform lets you insert filter drivers at
several places in the driver stack, where you can monitor, approve, or
veto those operations.

> Can you give me reference to learn about “asynchronous” ?

Did you look it up? It is a fundamental concept. When you submit a
kernel request, the lowest level driver often has to wait for some piece
of hardware to respond. Rather than holding you up, that driver stores
your request for later processing and returns to you, so you can do
something else. Later, when the operation has actually finished, it
will call your completion handler. That is “asynchronous” processing
(meaning “not in time”).

In your first example, even though the requests are literally
asynchronous, the completion handler and the event are being used to
simulate synchronous (“in time”) processing. The main flow will pause
to wait for the request to complete, at which time it moves on to the
next step.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

@Tim Roberts
Thanks

> It confused me because the Completion routine documented in msdn is not like the code i have

posted.

NTSTATUS YourCR(DEVICE_OBJECT DO, PIRP Irp, PVOID Context)

NTSTATUS here is actually a BOOLEAN, only STATUS_SUCCESS or STATUS_MORE_PROCESSING_REQUIRED are allowed

PDEVICE_OBJECT is the irpSp->DeviceObject, or NULL if there is no irpSp. To avoid the latter, allocate the IRP with +1 stack location, and call IoSetNextIrpStackLocation immediately after allocation.

Context is any item of your own provided by you in IoSetCompletionRoutine


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com