Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTFSD
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


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

OSR_Community_UserOSR_Community_User Member Posts: 110,217
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: [email protected] [SMTP:[email protected]]
> > Odesl?no: 5. kv?tna 2000 18:29
> > Komu: File Systems Developers
> > Kopie: [email protected]
> > 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: [email protected]
> > To unsubscribe send a blank email to $subst('Email.Unsub')
>

Comments

  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    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: [email protected] [SMTP:[email protected]]
    > > Odesl?no: 5. kv?tna 2000 18:29
    > > Komu: File Systems Developers
    > > Kopie: [email protected]
    > > 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: [email protected]
    > > To unsubscribe send a blank email to $subst('Email.Unsub')
    >


    ---
    You are currently subscribed to ntfsd as: [email protected]
    To unsubscribe send a blank email to $subst('Email.Unsub')
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Writing WDF Drivers 7 Dec 2020 LIVE ONLINE
Internals & Software Drivers 25 Jan 2021 LIVE ONLINE
Developing Minifilters 8 March 2021 LIVE ONLINE