How to share a KSEMAPHORE?

Hi,I want to share a semaphore between user mode application and driver.
1.I create a semaphore in user mode app
hSemaphore = CreateSemaphore(NULL,0,10,NULL);
2.I send it using DeviceIoControl
DeviceIoControl(hdevice,IOCTL_REGISTER_EVENT,&hSemaphore,sizeof(hSemaphore),NULL,0,&junk,NULL)
3.I get it in driver
handle = *(PHANDLE) Irp->AssociatedIrp.SystemBuffer;
4.try to convert it
status = ObReferenceObjectByHandle(handle, GENERIC_ALL, *ExEventObjectType,Irp->RequestorMode, (PVOID*)&psemaphore, NULL);

but I got STATUS_OBJECT_TYPE_MISMATCH in status.
When I sharing a KEVENT it works,but not works when i share KSEMAPHORE.
Any suggestion?Thank you!

xxxxx@yahoo.com.cn wrote:

status = ObReferenceObjectByHandle(handle, GENERIC_ALL,

*ExEventObjectType,
This line says to check the parameter to make sure the user passed in a
handle to a KEVENT, if you want to make sure it is a KSEMAPHORE, change
this line accordingly.

Irp->RequestorMode, (PVOID*)&psemaphore, NULL);


Jakob Bøhm, M.Sc.Eng. * xxxxx@danware.dk * direct tel:+45-45-90-25-33
Danware Data A/S * Bregnerodvej 127 * DK-3460 Birkerod * DENMARK
http://www.netop.com * tel:+45-45-90-25-25 * fax tel:+45-45-90-25-26
Information in this mail is hasty, not binding and may not be right

This is a really stupid idea, fortunately it will not work since KSEMAPHORE
is not the semaphore that CreateSemaphore creates. Forget this approach,
and use something like an inverted call to both pass the data nad
synchronize the driver and the app.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntdev…
> Hi,I want to share a semaphore between user mode application and driver.
> 1.I create a semaphore in user mode app
> hSemaphore = CreateSemaphore(NULL,0,10,NULL);
> 2.I send it using DeviceIoControl
> DeviceIoControl(hdevice,IOCTL_REGISTER_EVENT,&hSemaphore,sizeof(hSemaphore),NULL,0,&junk,NULL)
> 3.I get it in driver
> handle = *(PHANDLE) Irp->AssociatedIrp.SystemBuffer;
> 4.try to convert it
> status = ObReferenceObjectByHandle(handle, GENERIC_ALL,
> ExEventObjectType,Irp->RequestorMode, (PVOID)&psemaphore, NULL);
>
> but I got STATUS_OBJECT_TYPE_MISMATCH in status.
> When I sharing a KEVENT it works,but not works when i share KSEMAPHORE.
> Any suggestion?Thank you!
>
>

J Bohm:
I change it to IoFileObjectType, but it did’nt work.
Don Burn:
Thank you. But is there any other way to synchronize the driver and the app just like semaphore?

No there is not a way to synchronize an application and driver like a
semaphore. But using events or a semaphore like approach is a bad thing.
For instance lets say you have a semaphore that indicates a buffer is
available from a driver, how are you going to get the buffer? Either you
have to call in, which defeats the value of the semaphore, or you have to
have some way to share the buffers which adds complexity. Doing things
like this means you have to engineer mechanism for determining the
application has failed, and a handling other problems.

Unless you are talking close to a 100MB/sec or more for performance there
is little reason not to use the standard mechansims of Windows such as
pending overlapped I/O for later use.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntdev…
>J Bohm:
> I change it to IoFileObjectType, but it did’nt work.
> Don Burn:
> Thank you. But is there any other way to synchronize the driver and the
> app just like semaphore?
>

xxxxx@yahoo.com.cn wrote:

J Bohm:
I change it to IoFileObjectType, but it did’nt work.

What on earth led you to that choice, instead of, say,
ExSemaphoreObjectType?


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

Don Burn wrote:

This is a really stupid idea, fortunately it will not work since KSEMAPHORE
is not the semaphore that CreateSemaphore creates. Forget this approach,
and use something like an inverted call to both pass the data nad
synchronize the driver and the app.

Don, I appreciate curmudgeonliness as much as the next guy, but perhaps
you could elucidate on why you think this is a “really stupid idea”. I
mean, it’s one thing to say “you might have better luck using another
approach”, but it’s quite another to dismiss the whole concept with a
condescending brush of the hand.


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

ExSemaphoreObjectType is not exported probably, so, you’re stuck with the
event.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> Hi,I want to share a semaphore between user mode application and driver.
> 1.I create a semaphore in user mode app
> hSemaphore = CreateSemaphore(NULL,0,10,NULL);
> 2.I send it using DeviceIoControl
>
DeviceIoControl(hdevice,IOCTL_REGISTER_EVENT,&hSemaphore,sizeof(hSemaphore),NUL
L,0,&junk,NULL)
> 3.I get it in driver
> handle = *(PHANDLE) Irp->AssociatedIrp.SystemBuffer;
> 4.try to convert it
> status = ObReferenceObjectByHandle(handle, GENERIC_ALL,
ExEventObjectType,Irp->RequestorMode, (PVOID)&psemaphore, NULL);
>
> but I got STATUS_OBJECT_TYPE_MISMATCH in status.
> When I sharing a KEVENT it works,but not works when i share KSEMAPHORE.
> Any suggestion?Thank you!
>
>

Don,

it will not work since KSEMAPHORE is not the semaphore that CreateSemaphore creates.

What makes you believe so??? CreateSemaphore() calls NtCreateSemaphore() behind the scenes, and this call results in the one to KeInitializeSemaphore(). Therefore, KSEMAPHORE object is behind the semaphore that CreateSemaphore() creates …

Anton Bassov

Doing so is dangerous. You should not cause kernel mode code to block on
user mode code, as a rule of thumb; you don’t something like your user mode
helper process being terminated to cause your driver to get stuck.

About the only valid use of synchronization object sharing between user mode
/ kernel mode in third party drivers is to provide a way for the driver to
wake up a user mode program so that it can read some status information or
the like. Even then, you are almost always better off just pending an
overlapped IOCTL request, especially as that allows you to both wake the
program and return information to it in one atomic package.


Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
wrote in message news:xxxxx@ntdev…
>J Bohm:
> I change it to IoFileObjectType, but it did’nt work.
> Don Burn:
> Thank you. But is there any other way to synchronize the driver and the
> app just like semaphore?
>

Well no another valid reason to use a synchronization object or objects is to implement a shared memory transfer mechanism such as a ring buffer.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-284913-
xxxxx@lists.osr.com] On Behalf Of Skywing
Sent: Saturday, April 28, 2007 1:08 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] How to share a KSEMAPHORE?

Doing so is dangerous. You should not cause kernel mode code to block
on
user mode code, as a rule of thumb; you don’t something like your user
mode
helper process being terminated to cause your driver to get stuck.

About the only valid use of synchronization object sharing between user
mode
/ kernel mode in third party drivers is to provide a way for the driver
to
wake up a user mode program so that it can read some status information
or
the like. Even then, you are almost always better off just pending an
overlapped IOCTL request, especially as that allows you to both wake
the
program and return information to it in one atomic package.


Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
wrote in message news:xxxxx@ntdev…
> >J Bohm:
> > I change it to IoFileObjectType, but it did’nt work.
> > Don Burn:
> > Thank you. But is there any other way to synchronize the driver and
> the
> > app just like semaphore?
> >
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

wrote in message news:xxxxx@ntdev…
> Don,
>
>> it will not work since KSEMAPHORE is not the semaphore that
>> CreateSemaphore creates.
>
> What makes you believe so??? CreateSemaphore() calls NtCreateSemaphore()
> behind the scenes, and this call results in the one to
> KeInitializeSemaphore(). Therefore, KSEMAPHORE object is behind the
> semaphore that CreateSemaphore() creates …

Anton,

True buried in the semaphore object is the KSEMAPHORE, but you have no
guarantee that it will remain a KSEMAPHORE, or that it will be the
beginning of the object. Now you could use the various ZwXXXSemaphore
calls, but they are not exported in the kernel, so you are hacking the
system call table. So to do this you have a choice of relying on an
undocumented hack that KSEMAPHORE is the beginning of the semaphore object
(and nothing else is important in the object) or using undocumented calls
through a hack to reference the system call table.

The real problem with this techinuque is that sharing synchronization
objects adds a lot of complexity most developers forget for designs that in
many cases decrease performance.

If you use a shared synchronization object you have to worry about
determining if there are problems on either end. If the application went
away the driver needs to detect this, and stop what it is doing for the
application. If the driver is stopped, the application needs to know so it
does not sit there forever. Now if you use the standard Windows model of
pending overlapped I/O the notification is handled for you. If the
application goes away the request is cancelled. The driver cannot go away
without completing the requests so even a forced unload us going to have to
notify the application.

The other problem with shared synchronization objects is once you
recieve the signal how do you get the data. It amazes me how many
applications using shared sync recieve the event and then call the with an
IOCTL to get the data. Gee lets reinvent the pended I/O model with the
driver having to do all the work! The shared synchronization object can be
teamed up with shared memory but now you have made things even more
complex. Yes such a design is needed for extremely high performance
communications, but this is typically over 100MB/sec and most people are
not doing this level of performance.

The bottom line is the Windows development team created a good fast
model for I/O and sticking to that model is a wise idea for almost every
case. Even if you are happy with your design, consider the next poor guy
who picks up your driver, they are going to have to decode what you did to
share the syncronization object, share the memory segment, detect the
application failed, etc. If you are doing this driver commercially, you
have just added to the support costs with this learning time, versus using
a standard model every experience Windows device driver writer has seen.

As someone who has developed several implementations that the customer
was told by Microsoft “you can’t do that with Windows” it is nice that
Windows is such a powerful and flexible system to have techniques like
shared synchronization objects when you really need them. But, using a
non-standard technique when you do not need it is a very bad idea.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

Don,

I am afraid you got me wrong - the idea of sharing *SEMAPHORE* between app and driver is pretty ridiculous, and I am not arguing with you here. There are some rare cases when you may want to share a synchronization object between app and driver, but I just cannot imagine a scenario when this synchronization object has to be a semaphore (for the practical purposes, synchronization events seem to be sufficient practically in all cases).

The only thing I argued about was the statement that semaphore, created by CreateSemaphore() call, does not have its corresponding KSEMAPHORE object in the kernel. More on it below

you have no guarantee that it will remain a KSEMAPHORE, or that it will be the
beginning of the object.

Taking into consideration that CreateSemaphore() returns a HANDLE, I believe we can assume the model that holds true for all handles ( at least for the ones that are not managed by win32k.sys), i.e. a handle just holds info that is necessary for locating a pointer to the object’s body in the handle table. Therefore, a call to ObReferenceObjectByHandle() should return a pointer to the object’s body,
which, in this particular case, has to be KSEMAPHORE.

Now you could use the various ZwXXXSemaphore calls, but they are not exported in the kernel,
so you are hacking the system call table.

Actually, I thought the OP was not going to create a semaphore in the kernel mode - I thought he was about to do it in the user mode, and then pass a handle to a driver, which it can obtain a pointer to KSEMAPHORE from this handle by ObReferenceObjectByHandle() call. Trying to use Zw… routines that are not exported by ntoskrnl.exe from the kernel mode is not a good idea, softly speaking (actually, I am not sure that this call will be successfull, in the first place - probably, the system checks the previous mode of the calling thread). However, even if it works, it is going to be
a rather fragile solution that can get broken by any system update…

Anton Bassov

wrote in message news:xxxxx@ntdev…
> Taking into consideration that CreateSemaphore() returns a HANDLE, I
> believe we can assume the model that holds true for all handles ( at
> least for the ones that are not managed by win32k.sys), i.e. a handle
> just holds info that is necessary for locating a pointer to the object’s
> body in the handle table. Therefore, a call to
> ObReferenceObjectByHandle() should return a pointer to the object’s body,
> which, in this particular case, has to be KSEMAPHORE.

How do you know it is a KSEMAPHORE? It turns out in this case it is at
least for today. But consider for instance over the years I have seen a lot
of people think a kernel mutex is the same as a user-mode mutex (which in
the kernel is known as a mutant!). Very bad things happen if you get the
object pointer and try to issue a kernel mutex call on a mutant.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

Don,

But consider for instance over the years I have seen a lot
of people think a kernel mutex is the same as a user-mode mutex (which in
the kernel is known as a mutant!). Very bad things happen if you get the
object pointer and try to issue a kernel mutex call on a mutant.

AFAIK, mutex and mutant are 2 different things (drivers can call KeInitializeMutex() but KeInitializeMutant() is reserved for the system use). Therefore, confusing the two must have rather negative consequences for the target machine…

Anton Bassov

Anton,

three quotes on mutex/mutant that somehow clarify the relationship.

Mark’s bible:
The dispatcher objects include the kernel thread, mutex (called mutant internally), …
and
Note Externally in the Windows API, mutants are called mutexes. Internally, the kernel object that underlies mutexes is called a mutant.

From http://blogs.msdn.com/larryosterman/archive/2004/09/24/233969.aspx:

Oh, and mutexes are known as Mutants internally (you can see this if you double click on a mutex object using the WinObj tool) Why are they called mutants? Well, it’s sort-of an in joke. As Helen Custers put it in “Inside Windows NT”:
The name mutant has a colorful history. Early in Windows NT’s development, Dave Cutler created a kernel mutex object that implemented low-level mutual exclusion. Later he discovered that OS/2 required a version of the mutual exclusion semaphore with additional semantics, which Dave considered “brain-damaged” and which was incompatible with the original object. (Specifically, a thread could abandon the object and leave it inaccessible.) So he created an OS/2 version of the mutex and gave it the name mutant. Later Dave modified the mutant object to remove the OS/2 semantics, allowing the Win32 subsystem to use the object. The Win32 API calls the modified object mutex, but the native services retain the name mutant.

-------------- Original message --------------
From: xxxxx@hotmail.com

Don,

> But consider for instance over the years I have seen a lot
> of people think a kernel mutex is the same as a user-mode mutex (which in
> the kernel is known as a mutant!). Very bad things happen if you get the
> object pointer and try to issue a kernel mutex call on a mutant.

AFAIK, mutex and mutant are 2 different things (drivers can call
KeInitializeMutex() but KeInitializeMutant() is reserved for the system use).
Therefore, confusing the two must have rather negative consequences for the
target machine…

Anton Bassov


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Alex,

Let me clarify things a little bit. Basically, there are 2 types of mutexes, i.e. kernel-mode and user-mode ones. User-mode mutex is, indeed, internally known as a mutant. However, kernel-mode mutex is *NOT* the same thing as mutant, although they rely upon the same binary structure - unlike mutant that is always created in non-signalled state, kernel-mode mutex is originally signalled. This is why the reserved ‘Level’ parameter, although meaningfull to KeInitializeMutant(), is simply ignored by KeInitializeMutex() - it indicates whether the calling thread is a mutex/mutant owner, which is just meaninless for the kernel-mode mutex (because it is in the signalled state anyway).

I hope by now you understand why confusing kernel-mode mutex with mutant may have rather negative consequences…

Anton Bassov

> I hope by now you understand why confusing kernel-mode mutex with mutant may

have rather negative consequences…
Not that I had any doubts about that before…

Maybe I was not reading the thread carefully but I thought the OP used terms “mutex” and “mutant” intercangeably meaning user mode objects vs kernel mode ones, not kernel vs kernel.

In any case, the history quote from Helen looked interesting.

-------------- Original message --------------
From: xxxxx@hotmail.com

Alex,

Let me clarify things a little bit. Basically, there are 2 types of mutexes,
i.e. kernel-mode and user-mode ones. User-mode mutex is, indeed, internally
known as a mutant. However, kernel-mode mutex is *NOT* the same thing as mutant,
although they rely upon the same binary structure - unlike mutant that is always
created in non-signalled state, kernel-mode mutex is originally signalled. This
is why the reserved ‘Level’ parameter, although meaningfull to
KeInitializeMutant(), is simply ignored by KeInitializeMutex() - it indicates
whether the calling thread is a mutex/mutant owner, which is just meaninless for
the kernel-mode mutex (because it is in the signalled state anyway).

I hope by now you understand why confusing kernel-mode mutex with mutant may
have rather negative consequences…

Anton Bassov


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

You are missing the point of this, you stated:

“Therefore, a call to ObReferenceObjectByHandle() should return a pointer
to the object’s body,
which, in this particular case, has to be KSEMAPHORE.”

You are making an assumption that because today it is a KSEMAPHORE it will
always be one. It could change tommorrow. The mutex/mutant discussion was
to show an example of how faulty reasoning like above can get developers in
a lot of trouble.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntdev…
> Don,
>
>> But consider for instance over the years I have seen a lot
>> of people think a kernel mutex is the same as a user-mode mutex (which
>> in
>> the kernel is known as a mutant!). Very bad things happen if you get
>> the
>> object pointer and try to issue a kernel mutex call on a mutant.
>
> AFAIK, mutex and mutant are 2 different things (drivers can call
> KeInitializeMutex() but KeInitializeMutant() is reserved for the system
> use). Therefore, confusing the two must have rather negative consequences
> for the target machine…
>
> Anton Bassov
>

Don,

You are missing the point of this, you stated:

“Therefore, a call to ObReferenceObjectByHandle() should return a pointer to the object’s body,
which, in this particular case, has to be KSEMAPHORE.”

You are making an assumption that because today it is a KSEMAPHORE it will always be one.
It could change tommorrow.

Well, such change seems to be rather illogical. There is a different possible problem here - after all, even if the binary object behind both kernel-mode and user-mode semaphores is guaranteed to be KSEMAPHORE (and, to be honest, I don’t see any reason why it may get changed), it still does not mean that the whole thing will work. Your example with mutex/mutant illustrates this.

The mutex/mutant discussion was to show an example of how faulty reasoning like above
can get developers in a lot of trouble.

The trouble that you have mentioned has nothing to do with the above reasoning - after all,
binary layout of an object ObReferenceObjectByHandle() is the same for both kernel-mode mutex and mutant (KMUTANT and KMUTEX are just typedefs for _KMUTANT structure), so that, from this perspective, there is no difference between them whatsoever. The difference comes into play when this structure starts getting processed, and it gets processed a bit differently for kernel-mode and user-mode callers. This is why kernel-mode mutex and mutant are two different things that should not be used interchangeably. Therefore, your example illustrates quite a different danger - it may well happen that KSEMAPHORE structure starts getting processed differently for the kernel-mode and user-mode callers (actually, I am not sure it is processed the same way for kernel-mode and user-mode callers even under currently existing OS versions, so that I am not sure the whole thing will work even now)…

Anton Bassov