RE: Anything to be aware of when calling ZwOpenSemaphore, ZwOpenMutant, ZwOpenEvent?

Paul,

The headers that I reference come from Nebbett that should be correct.
For unexported api like ZwOpenSemaphore & ZwOpenMutex, I follow
Prasad Dabak’s suggestion - dynamically detects the IDs in an User-Mode
service, then use IOCTL send them to filter driver before use.

In Kernel, I define

_declspec(naked)
NTSTATUS NTAPI
ZwOpenSemaphore(

)
{
_asm {
mov eax, GlobalSemId
lea edx, [esp+4]
int 2eh,
ret 0Ch
}
}

I believe the above work without problem because using SoftICE to trace,
all return success status.

The page fault is guaranteed to happen I do not set breakpoint in the
suspected section of code. Let me explain how I use them as clearly as
possible here.

All the creation of memory mapped file, event, mutex, semaphoe object
are done in User-mode service. The kernel mode filter driver’s role is
to open or read these kernel objects.

The single writer multiple readers guard is implemented exactly as what
was in Advanced Windows 3rd SWMRG by replacing win32 api with related
native win32 api using conditional compilation.

typedef struct SingleWriterMultiReaderGuard {
HANDLE hMutex;
HANDLE hEvent;
HANDLE hSemaphore;
} SWMRG, *PSWMRG;

In the constructor of the object that govern the memory-mapped section
that shared by all clients including the filesystem filter driver,
I do SWMRGInitialize to intialize these kernel object and in
destructor, I do the reverse to close the handle. The SWMRG is a member
of that class.

Before access the section, a SWMRGWaitToRead is issued and after
that SWMRGDoneReading is issued. Again the filter driver is only
concerning reading the data out of the section.

I use the sample as provided in Nagar’s NT Filesystem Internals as my
template. The place that I use the above object is when I got an
IRP_MJ_CREATE and it is handled in SFilterCreate in the sample.

If the SWMRG is disabled using conditional compilation, the below
pseudo code does not present any problem. If enabled, the page fault
seems can happen anywhere after the MYCACHE creation, even after the
final block.

NTSTATUS SFilterCreate(…)
{
__try {
…some standard stuff
ExAcquireResourceExclusiveLite(&(pDevExt->DevExtRes),TRUE);
AcquiredExtension = TRUE;

//my stuff is plugged below
if (IRP is directed to attached device)
{
bool bCheck = false;

//object to open the section and initialize SWMRG
MYCACHE* pmc = new MYCACHE(…);
if (pmc && mc->search(…)) {
bCheck = true; // continue to check
}
if (pmc)
delete pmc;

if (bCheck)
{
KeAcquireSpinLock(&(GlobalData.FilterSpinLock), &oldIrql);
// In SuspendCreate routine, I do the following
// pIrpList = allocate nonpagedpool space
// IoSetCancelRoutine(Irp, MyCancelRoutine);
// pIrpList = Irp;
// store pIrpList into internal queue
// Irp->IoStatus.Status = STATUS_PENDING;
// IoMarkIrpPending(Irp);
SuspendCreate(…);

// In ServeRequest routine, I do the following
// pIrpList = dequeue an IRP stored by the User-Mode service
// copy info into pIrpList->pIrp->AssociatedIrp.SystemBuffer
// pIrpList->pIrp->IoStatus.Status = STATUS_SUCCESS;
// pIrpList->pIrp->IoStatus.Information = …datasize;
// IoCompleteRequest(pIrpList->pIrp, IO_NO_INCREMENT);
// pIrpList->pIrp=0;
// ExFreePool(pIrpList);
ServeRequest(…);

KeReleaseSpinLock(&(GlobalData.FilterSpinLock), oldIrql);
RC = STATUS_PENDING;
}
if (AcquiredExtension)
{
SFilterReleaseResource(…);
AcquiredExtension = FALSE;
}
if (!bCheck)
{
// for request that is not queued, send to lower driver
RC = SFilterDefaultDispatch(DeviceObject, Irp);
}
} else if (target to filter driver itself) {
// I don’t care
CompleteIrp = TRUE;
RC = STATUS_SUCCESS;
} else {
CompleteIrp = TRUE;
RC = STATUS_INVALID_DEVICE_REQUEST;
}
} __finally {
if (AcquiredExtension) {…proper cleanup}
if (CompleteIrp) {
Irp->IoStatus.Status = RC;
Irp->IoStatus.Information = ReturnedInformation;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
}

I hope I’ve condensed my code to a reasonable form and let me know
if you need me to provide any more details.

I appreciate your patience and help !

Thanx,

Jack Cheng
(Curriculum Corp.)

On Tue, 9 May 2000, Pavel Hrdina wrote:

Have you proper headers of this routines?
Another question: could you show me how you’re using them?

Example:
HANDLE Handle;
NTSTATUS Status;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjAttr;

RtlInitUnicodeString(&Name, L"\NameOfSemaphore");
InitializeObjectAttributes(&ObjAttr, &Name, 0, NULL, NULL);

Status = NtOpenSemaphore(&Handle, SEMAPHORE_ALL_ACCESS, &ObjAttr);
if (!NT_SUCCESS(Status)) …

My definitions are here:
<>
> Paul
> > -----P?vodn? zpr?va-----
> > Od: xxxxx@erinet.com [SMTP:xxxxx@erinet.com]
> > Odesl?no: 5. kv?tna 2000 18:29
> > Komu: File Systems Developers
> > Kopie: xxxxx@curriculum.com
> > P?edm?t: [ntfsd] Anything to be aware of when calling
> > ZwOpenSemaphore, ZwOpenMutant, ZwOpenEvent?
> >
> > Hi all,
> >
> > I have a memory mapped object protected by an implementation using
> > the above to implement single writer multiple readers.
> >
> > This object is shared by both kernel mode driver and multiple user
> > mode applications.
> >
> > Right now if I enable these Native API synchronization calls, I got
> > random page fault that I was unable to pinpoint the exact location
> > of the fault.
> >
> > If I disable these calls, then everything is fine.
> >
> > I am suspecting these calls may somehow raise IRQL that cause the
> > problem.
> >
> > I am looking for possible causes and workaround !
> >
> > Thanks,
> >
> > Jack Cheng
> > (curriculum corp.)
> >
> >
> > —
> > You are currently subscribed to ntfsd as: xxxxx@sodatsw.cz
> > To unsubscribe send a blank email to $subst(‘Email.Unsub’)
>

Paul,

The headers that I reference come from Nebbett that should be correct.
For unexported api like ZwOpenSemaphore & ZwOpenMutex, I follow
Prasad Dabak’s suggestion - dynamically detects the IDs in an User-Mode
service, then use IOCTL send them to filter driver before use.

In Kernel, I define

_declspec(naked)
NTSTATUS NTAPI
ZwOpenSemaphore(

)
{
_asm {
mov eax, GlobalSemId
lea edx, [esp+4]
int 2eh,
ret 0Ch
}
}

I believe the above work without problem because using SoftICE to trace,
all return success status.

The page fault is guaranteed to happen I do not set breakpoint in the
suspected section of code. Let me explain how I use them as clearly as
possible here.

All the creation of memory mapped file, event, mutex, semaphoe object
are done in User-mode service. The kernel mode filter driver’s role is
to open or read these kernel objects.

The single writer multiple readers guard is implemented exactly as what
was in Advanced Windows 3rd SWMRG by replacing win32 api with related
native win32 api using conditional compilation.

typedef struct SingleWriterMultiReaderGuard {
HANDLE hMutex;
HANDLE hEvent;
HANDLE hSemaphore;
} SWMRG, *PSWMRG;

In the constructor of the object that govern the memory-mapped section
that shared by all clients including the filesystem filter driver,
I do SWMRGInitialize to intialize these kernel object and in
destructor, I do the reverse to close the handle. The SWMRG is a member
of that class.

Before access the section, a SWMRGWaitToRead is issued and after
that SWMRGDoneReading is issued. Again the filter driver is only
concerning reading the data out of the section.

I use the sample as provided in Nagar’s NT Filesystem Internals as my
template. The place that I use the above object is when I got an
IRP_MJ_CREATE and it is handled in SFilterCreate in the sample.

If the SWMRG is disabled using conditional compilation, the below
pseudo code does not present any problem. If enabled, the page fault
seems can happen anywhere after the MYCACHE creation, even after the
final block.

NTSTATUS SFilterCreate(…)
{
__try {
…some standard stuff
ExAcquireResourceExclusiveLite(&(pDevExt->DevExtRes),TRUE);
AcquiredExtension = TRUE;

//my stuff is plugged below
if (IRP is directed to attached device)
{
bool bCheck = false;

//object to open the section and initialize SWMRG
MYCACHE* pmc = new MYCACHE(…);
if (pmc && mc->search(…)) {
bCheck = true; // continue to check
}
if (pmc)
delete pmc;

if (bCheck)
{
KeAcquireSpinLock(&(GlobalData.FilterSpinLock), &oldIrql);
// In SuspendCreate routine, I do the following
// pIrpList = allocate nonpagedpool space
// IoSetCancelRoutine(Irp, MyCancelRoutine);
// pIrpList = Irp;
// store pIrpList into internal queue
// Irp->IoStatus.Status = STATUS_PENDING;
// IoMarkIrpPending(Irp);
SuspendCreate(…);

// In ServeRequest routine, I do the following
// pIrpList = dequeue an IRP stored by the User-Mode service
// copy info into pIrpList->pIrp->AssociatedIrp.SystemBuffer
// pIrpList->pIrp->IoStatus.Status = STATUS_SUCCESS;
// pIrpList->pIrp->IoStatus.Information = …datasize;
// IoCompleteRequest(pIrpList->pIrp, IO_NO_INCREMENT);
// pIrpList->pIrp=0;
// ExFreePool(pIrpList);
ServeRequest(…);

KeReleaseSpinLock(&(GlobalData.FilterSpinLock), oldIrql);
RC = STATUS_PENDING;
}
if (AcquiredExtension)
{
SFilterReleaseResource(…);
AcquiredExtension = FALSE;
}
if (!bCheck)
{
// for request that is not queued, send to lower driver
RC = SFilterDefaultDispatch(DeviceObject, Irp);
}
} else if (target to filter driver itself) {
// I don’t care
CompleteIrp = TRUE;
RC = STATUS_SUCCESS;
} else {
CompleteIrp = TRUE;
RC = STATUS_INVALID_DEVICE_REQUEST;
}
} __finally {
if (AcquiredExtension) {…proper cleanup}
if (CompleteIrp) {
Irp->IoStatus.Status = RC;
Irp->IoStatus.Information = ReturnedInformation;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
}

I hope I’ve condensed my code to a reasonable form and let me know
if you need me to provide any more details.

I appreciate your patience and help !

Thanx,

Jack Cheng
(Curriculum Corp.)

On Tue, 9 May 2000, Pavel Hrdina wrote:

Have you proper headers of this routines?
Another question: could you show me how you’re using them?

Example:
HANDLE Handle;
NTSTATUS Status;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjAttr;

RtlInitUnicodeString(&Name, L"\NameOfSemaphore");
InitializeObjectAttributes(&ObjAttr, &Name, 0, NULL, NULL);

Status = NtOpenSemaphore(&Handle, SEMAPHORE_ALL_ACCESS, &ObjAttr);
if (!NT_SUCCESS(Status)) …

My definitions are here:
<>
> Paul
> > -----P?vodn? zpr?va-----
> > Od: xxxxx@erinet.com [SMTP:xxxxx@erinet.com]
> > Odesl?no: 5. kv?tna 2000 18:29
> > Komu: File Systems Developers
> > Kopie: xxxxx@curriculum.com
> > P?edm?t: [ntfsd] Anything to be aware of when calling
> > ZwOpenSemaphore, ZwOpenMutant, ZwOpenEvent?
> >
> > Hi all,
> >
> > I have a memory mapped object protected by an implementation using
> > the above to implement single writer multiple readers.
> >
> > This object is shared by both kernel mode driver and multiple user
> > mode applications.
> >
> > Right now if I enable these Native API synchronization calls, I got
> > random page fault that I was unable to pinpoint the exact location
> > of the fault.
> >
> > If I disable these calls, then everything is fine.
> >
> > I am suspecting these calls may somehow raise IRQL that cause the
> > problem.
> >
> > I am looking for possible causes and workaround !
> >
> > Thanks,
> >
> > Jack Cheng
> > (curriculum corp.)
> >
> >
> > —
> > You are currently subscribed to ntfsd as: xxxxx@sodatsw.cz
> > To unsubscribe send a blank email to $subst(‘Email.Unsub’)
>


You are currently subscribed to ntfsd as: xxxxx@arrakis.es
To unsubscribe send a blank email to $subst(‘Email.Unsub’)