strange OPLOCK BREAK~

I developped a filter.In the IRP_MJ_CREATE,I will ZwCreateFile(by Shadow DO),QueryInformation,Read some Data,and ZwClose.
It works well in local system and RDR.
But if it works in win2K3(as the file server),the client save a doc file,it will fail.
I observed these:
if my filter didn’t work,everything is OK.
if my filter worked on the file server(win2K3),the client save a doc file will fail.

the OK case:
System:4 IRP_MJ_CREATE D:\Test\test.doc SUCCESS Options: OverwriteIf Access: All
System:4 IRP_MJ_CREATE D:\Test\test.doc OPLOCK BREAK Options: Open Access: All
System:4 FSCTL_OPLOCK_BREAK_NOTIFY D:\Test\test.doc SUCCESS
System:4 IRP_MJ_CLEANUP D:\Test\test.doc SUCCESS
System:4 IRP_MJ_CLOSE D:\Test\test.doc SUCCESS

the failed case:
System:4 IRP_MJ_CREATE D:\Test\test.doc SUCCESS Options: OverwriteIf Access: All
…the IRP_MJ_CREATE from my filter is to Shadow DO,so can’t see it…
…the IRP_MJ_CLEANUP and IRP_MJ_CLOSE from my filter…
System:4 IRP_MJ_CREATE D:\Test\test.doc SHARING VIOLATION Options: Open Access: All

Any body can explain it?and what should I do?thanks ~~~~

the code frag from my filter described my behavior before original IRP_MJ_CREATE:


Status = ZwCreateFile(&hFile, // returned file handle
(SYNCHRONIZE | FILE_READ_ATTRIBUTES), // desired access
&ObjectAttributes, // ptr to object attributes
&IoStatus, // ptr to I/O status block
NULL, // alloc size = none
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, // eabuffer
0 ); // ealength
if(!NT_SUCCESS(Status)) return;
…ZwQueryInformationFile…
Status=ZwClose(hFile);

//
//if (pOriginalIrpStack->Parameters.Create.Options) & FILE_COMPLETE_IF_OPLOCKED ,
//then options=FILE_SYNCHRONOUS_IO_NONALERT | FILE_COMPLETE_IF_OPLOCKED;
//else options=FILE_SYNCHRONOUS_IO_NONALERT;
//
Status = ZwCreateFile(&hFile, // returned file handle
(SYNCHRONIZE | FILE_READ_DATA), // desired access
&ObjectAttributes, // ptr to object attributes
&IoStatus, // ptr to I/O status block
NULL, // alloc size = none
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
options, //please see the above comments
NULL, // eabuffer
0 ); // ealength
if(!NT_SUCCESS(Status)) return;
if (Status==STATUS_OPLOCK_BREAK_IN_PROGRESS) return;
…ZwQueryInformationFile and ZwReadFile…
Status=ZwClose(hFile);

> if(!NT_SUCCESS(Status)) return;

if (Status==STATUS_OPLOCK_BREAK_IN_PROGRESS) return;
…ZwQueryInformationFile and ZwReadFile…
Status=ZwClose(hFile);

STATUS_OPLOCK_BREAK_IN_PROGRESS is a successful code, you must wait for an
oplock break using FSCTL_OPLOCK_BREAK_NOTIFY.


Slava Imameyev, xxxxx@hotmail.com

wrote in message news:xxxxx@ntfsd…
>I developped a filter.In the IRP_MJ_CREATE,I will ZwCreateFile(by Shadow
>DO),QueryInformation,Read some Data,and ZwClose.
> It works well in local system and RDR.
> But if it works in win2K3(as the file server),the client save a doc
> file,it will fail.
> I observed these:
> if my filter didn’t work,everything is OK.
> if my filter worked on the file server(win2K3),the client save a doc file
> will fail.
>
> the OK case:
> System:4 IRP_MJ_CREATE D:\Test\test.doc SUCCESS Options: OverwriteIf
> Access: All
> System:4 IRP_MJ_CREATE D:\Test\test.doc OPLOCK BREAK Options: Open
> Access: All
> System:4 FSCTL_OPLOCK_BREAK_NOTIFY D:\Test\test.doc SUCCESS
> System:4 IRP_MJ_CLEANUP D:\Test\test.doc SUCCESS
> System:4 IRP_MJ_CLOSE D:\Test\test.doc SUCCESS
>
> the failed case:
> System:4 IRP_MJ_CREATE D:\Test\test.doc SUCCESS Options: OverwriteIf
> Access: All
> …the IRP_MJ_CREATE from my filter is to Shadow DO,so can’t see
> it…
> …the IRP_MJ_CLEANUP and IRP_MJ_CLOSE from my
> filter…
> System:4 IRP_MJ_CREATE D:\Test\test.doc SHARING VIOLATION Options: Open
> Access: All
>
> Any body can explain it?and what should I do?thanks ~~~~
>
> the code frag from my filter described my behavior before original
> IRP_MJ_CREATE:
>
> …
> Status = ZwCreateFile(&hFile, // returned file handle
> (SYNCHRONIZE | FILE_READ_ATTRIBUTES), // desired access
> &ObjectAttributes, // ptr to object attributes
> &IoStatus, // ptr to I/O status block
> NULL, // alloc size = none
> FILE_ATTRIBUTE_NORMAL,
> FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
> FILE_OPEN,
> FILE_SYNCHRONOUS_IO_NONALERT,
> NULL, // eabuffer
> 0 ); // ealength
> if(!NT_SUCCESS(Status)) return;
> …ZwQueryInformationFile…
> Status=ZwClose(hFile);
> …
> //
> //if (pOriginalIrpStack->Parameters.Create.Options) &
> FILE_COMPLETE_IF_OPLOCKED ,
> //then options=FILE_SYNCHRONOUS_IO_NONALERT | FILE_COMPLETE_IF_OPLOCKED;
> //else options=FILE_SYNCHRONOUS_IO_NONALERT;
> //
> Status = ZwCreateFile(&hFile, // returned file handle
> (SYNCHRONIZE | FILE_READ_DATA), // desired access
> &ObjectAttributes, // ptr to object attributes
> &IoStatus, // ptr to I/O status block
> NULL, // alloc size = none
> FILE_ATTRIBUTE_NORMAL,
> FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
> FILE_OPEN,
> options, //please see the above comments
> NULL, // eabuffer
> 0 ); // ealength
> if(!NT_SUCCESS(Status)) return;
> if (Status==STATUS_OPLOCK_BREAK_IN_PROGRESS) return;
> …ZwQueryInformationFile and ZwReadFile…
> Status=ZwClose(hFile);
> …
>
>

I fixed my code,but it can’t works.
When I meet a IRP_MJ_CREATE,I do my ZwCreateFile before call down it.And if the original IRP_MJ_CREATE is with FILE_COMPLETE_IF_OPLOCKED,I add this option to my ZwCreateFile(by Shadow DO).And if returns STATUS_OPLOCK_BREAK_IN_PROGRESS,I just wait for the FSCTL_OPLOCK_BREAK_NOTIFY.
I have filter the IRP_MJ_FILE_SYSTEM_CONTROL,but when I’m waitting for my FSCTL_OPLOCK_BREAK_NOTIFY,I can’t see it.

the code about IRP_MJ_CREATE:

if (g_bOplockBreak) LOCK_Oplock_Process();
Status = ZwCreateFile(&hFile, // returned file handle
(SYNCHRONIZE | FILE_READ_DATA), // desired access
&ObjectAttributes, // ptr to object attributes
&IoStatus, // ptr to I/O status block
NULL, // alloc size = none
FILE_ATTRIBUTE_NORMAL,
open_share_flags,
FILE_OPEN,
options,
NULL, // eabuffer
0 ); // ealength
if(!NT_SUCCESS(Status))
{
if (g_bOplockBreak) UNLOCK_Oplock_Process();
return ;
}
if (Status==STATUS_OPLOCK_BREAK_IN_PROGRESS)
{
g_pFCBOplocked=(PFSRTL_COMMON_FCB_HEADER) MyGetFCB(hFile);
if (g_pFCBOplocked!=NULL)
{
if (g_bOplockBreak) UNLOCK_Oplock_Process();
LOCK_Oplock_Complete();
g_pFCBOplocked=NULL;
}
else
{
if (g_bOplockBreak) UNLOCK_Oplock_Process();
g_pFCBOplocked=NULL;
}
}
else
{
if (g_bOplockBreak) UNLOCK_Oplock_Process();
}

the code for FSCTL_OPLOCK_BREAK_NOTIFY:
NTSTATUS MyFsControlUserFSRequest(IN PDEVICE_OBJECT pDevObj,IN PIRP Irp)
{
NTSTATUS Status;
ULONG FsControlCode;
PFSRTL_COMMON_FCB_HEADER pFCB=NULL;
BOOLS bFinded=FALSE;

PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;

if (FsControlCode==FSCTL_OPLOCK_BREAK_NOTIFY)
{
LOCK_Oplock_Process();
PFILE_OBJECT pFileObject=IrpSp->FileObject;
if (pFileObject!=NULL)
pFCB=(PFSRTL_COMMON_FCB_HEADER)(pFileObject->FsContext);
if (pFCB!=NULL)
{
if (pFCB==g_pFCBOplocked) bFinded=TRUE;
}

UNLOCK_Oplock_Process();
if (bFinded)
{
g_pFCBOplocked=NULL;
UNLOCK_Oplock_Complete();
}
}
return MyPassThrough(pDevObj,Irp);
}

The problem is that SRV needs to process the oplock break, but won’t do
so until you return to it. You’ll have to wait for the break notify in
the fsctl function, not in the create path.

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Saturday, September 02, 2006 8:47 AM
To: ntfsd redirect
Subject: RE:[ntfsd] strange OPLOCK BREAK~

I fixed my code,but it can’t works.
When I meet a IRP_MJ_CREATE,I do my ZwCreateFile before call down it.And
if the original IRP_MJ_CREATE is with FILE_COMPLETE_IF_OPLOCKED,I add
this option to my ZwCreateFile(by Shadow DO).And if returns
STATUS_OPLOCK_BREAK_IN_PROGRESS,I just wait for the
FSCTL_OPLOCK_BREAK_NOTIFY.
I have filter the IRP_MJ_FILE_SYSTEM_CONTROL,but when I’m waitting for
my FSCTL_OPLOCK_BREAK_NOTIFY,I can’t see it.

the code about IRP_MJ_CREATE:

if (g_bOplockBreak) LOCK_Oplock_Process();
Status = ZwCreateFile(&hFile, // returned file
handle
(SYNCHRONIZE | FILE_READ_DATA), // desired access
&ObjectAttributes, // ptr to object attributes
&IoStatus, // ptr to I/O status block
NULL, // alloc size = none
FILE_ATTRIBUTE_NORMAL,
open_share_flags,
FILE_OPEN,
options,
NULL, // eabuffer
0 ); // ealength
if(!NT_SUCCESS(Status))
{
if (g_bOplockBreak) UNLOCK_Oplock_Process();
return ;
}
if (Status==STATUS_OPLOCK_BREAK_IN_PROGRESS)
{
g_pFCBOplocked=(PFSRTL_COMMON_FCB_HEADER) MyGetFCB(hFile);
if (g_pFCBOplocked!=NULL)
{
if (g_bOplockBreak) UNLOCK_Oplock_Process();
LOCK_Oplock_Complete();
g_pFCBOplocked=NULL;
}
else
{
if (g_bOplockBreak) UNLOCK_Oplock_Process();
g_pFCBOplocked=NULL;
}
}
else
{
if (g_bOplockBreak) UNLOCK_Oplock_Process();
}

the code for FSCTL_OPLOCK_BREAK_NOTIFY:
NTSTATUS MyFsControlUserFSRequest(IN PDEVICE_OBJECT pDevObj,IN PIRP Irp)
{
NTSTATUS Status;
ULONG FsControlCode;
PFSRTL_COMMON_FCB_HEADER pFCB=NULL;
BOOLS bFinded=FALSE;

PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
FsControlCode =
IrpSp->Parameters.FileSystemControl.FsControlCode;

if (FsControlCode==FSCTL_OPLOCK_BREAK_NOTIFY)
{
LOCK_Oplock_Process();
PFILE_OBJECT pFileObject=IrpSp->FileObject;
if (pFileObject!=NULL)

pFCB=(PFSRTL_COMMON_FCB_HEADER)(pFileObject->FsContext);
if (pFCB!=NULL)
{
if (pFCB==g_pFCBOplocked) bFinded=TRUE;
}

UNLOCK_Oplock_Process();
if (bFinded)
{
g_pFCBOplocked=NULL;
UNLOCK_Oplock_Complete();
}
}
return MyPassThrough(pDevObj,Irp);
}


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Thanks,Tony~~~
I have analyzed it,you can see it in http://www.osronline.com/showthread.cfm?link=97076
But the trouble is:
If I return to the SRV in my Create Dispath,I must adjust my code hugely.
Can I do it by this:
Create Dispath:

if (Status==STATUS_OPLOCK_BREAK_IN_PROGRESS)
{
return Status;
}

FSCTL Dispatch:

if (bFinded)
{
ZwCreateFile(…);
}

Yes, I saw the earlier analysis - but the bottom line I was emphasizing
is that you MUST return to SRV in order to process the oplock break.

If you defer your own work into FSCTL it seems (from a quick
consideration) that it seems like it should work. However, I’ve never
done it the way you suggest, so you’ll have to try and see if it works
for you. At least you’ll know it is safe to block and wait at that
point.

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Saturday, September 02, 2006 8:16 PM
To: ntfsd redirect
Subject: RE:[ntfsd] strange OPLOCK BREAK~

Thanks,Tony~~~
I have analyzed it,you can see it in
http://www.osronline.com/showthread.cfm?link=97076
But the trouble is:
If I return to the SRV in my Create Dispath,I must adjust my code
hugely.
Can I do it by this:
Create Dispath:

if (Status==STATUS_OPLOCK_BREAK_IN_PROGRESS)
{
return Status;
}

FSCTL Dispatch:

if (bFinded)
{
ZwCreateFile(…);
}


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

I’m very curious about it:
Pre-Create is very common(call ZwCreateFile before call down IRP_MJ_CREATE).If it is FILE_COMPLETE_IF_OPLOCKED,what is the common solution?
Just returns to SRV when ZwCreateFile returns STATUS_OPLOCK_BREAK_IN_PROGRESS?It’s not enough!After this ZwCreateFile,of course need some ZwReadFile or other operation for make some judgement.
So,what is the common solution?

OK,assuming that should be post-Create.the same question:
when the original IRP_MJ_CREATE returns STATUS_OPLOCK_BREAK_IN_PROGRESS,I must retuns to the SRV.And I must do some IO after call down the IRP_MJ_CREATE!
wait for FSCTL_OPLOCK_BREAK_NOTIFY?But I have return to SRV in IRP_MJ_CREATE,I have missed the chance to do some IO after IRP_MJ_CREATE,and missed the chance for deny the IRP_MJ_CREATE(you know,I will make some judgement.If I think I must deny this operation,I should deny this IRP_MJ_CREATE).

What is the common solution?
thanks,tony~

I’ve seen something like a dozen solutions to this problem. It is a
common problem and there are quite a few different ways to work around
the issue. Since I know nothing about your product, your experience, or
the specific circumstances around your issue, I’m not in a position to
do more than suggest a general approach.

Were I solving this issue, I’d do it by constructing my filter to handle
the FSCTL path - but then I’d have designed it with that in mind in the
first place. Moving a create into this path should be sufficient since
the second open should not cause a second oplock break.

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Saturday, September 02, 2006 9:39 PM
To: ntfsd redirect
Subject: RE:[ntfsd] strange OPLOCK BREAK~

I’m very curious about it:
Pre-Create is very common(call ZwCreateFile before call down
IRP_MJ_CREATE).If it is FILE_COMPLETE_IF_OPLOCKED,what is the common
solution?
Just returns to SRV when ZwCreateFile returns
STATUS_OPLOCK_BREAK_IN_PROGRESS?It’s not enough!After this
ZwCreateFile,of course need some ZwReadFile or other operation for make
some judgement.
So,what is the common solution?

OK,assuming that should be post-Create.the same question:
when the original IRP_MJ_CREATE returns
STATUS_OPLOCK_BREAK_IN_PROGRESS,I must retuns to the SRV.And I must do
some IO after call down the IRP_MJ_CREATE!
wait for FSCTL_OPLOCK_BREAK_NOTIFY?But I have return to SRV in
IRP_MJ_CREATE,I have missed the chance to do some IO after
IRP_MJ_CREATE,and missed the chance for deny the IRP_MJ_CREATE(you
know,I will make some judgement.If I think I must deny this operation,I
should deny this IRP_MJ_CREATE).

What is the common solution?
thanks,tony~


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

My production:on-the-fly encryption
In Pre-Create:

  1. I do ZwCreateFile(by Shadow DO) with just READ_ATTRIBUTES,to find this file is exist or not.
  2. if exist,I do ZwCreateFile (by ShadowDO) with READ_DATA,to read the file data.If the data include my signname,I will find I can decrypt the file or not(because maybe I have correct password).
    If I Can(have correct password),I will call down this IRP_MJ_CREATE.
    If I can’t (I haven’t correct password),I will deny this IPR_MJ_CREATE.

that’s all.
So,I must do ZwCreateFile and READ in pre-create.

sorry,tony~~~I can’t understand your words:

>Were I solving this issue, I’d do it by constructing my filter to handle
the FSCTL path - but then I’d have designed it with that in mind in the
first place. Moving a create into this path should be sufficient since
the second open should not cause a second oplock break.

sorry for clear a question:
we say “return to SRV”,what is the precise means?
1.complete the IRP,don’t “return status from my IRP_MJ_CREATE dispatch”.
if I complete the IRP,SRV will do right thing(oplock break process).
we don’t need return from my dispatch.
2.complete the IRP,and “return status from my IRP_MJ_CREATE dispatch”.
we must complete the IRP and return from my dispatch,SRV will do right thing.
You know,If I return from my dispatch,I will lose control,I need do other thing.

The point then is that your existing approach to the problem is
fundamentally flawed - the file is ALREADY opened (otherwise there
couldn’t be an oplock on it) but in order to make your decision you have
to open it again BEFORE you allow the return to SRV (LanManager).
However, to break the oplock requires that you allow the return to SRV.

Thus, SRV needs to regain control to process the oplock break, and you
need to prevent SRV from regaining control to decide if you wish to
allow the open to proceed.

I’m sorry that this problem is not something that you expected - it is
certainly something we’ve been talking about on NTFSD for at least 10
years now, but it is just one of the many complex special issues that
must be addressed in a file system and file system filter driver.

Since the file has already been opened, perhaps you can rely upon the
information that you previously determined for the file, thus obviating
the need to open the file.

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Sunday, September 03, 2006 2:48 AM
To: ntfsd redirect
Subject: RE:[ntfsd] strange OPLOCK BREAK~

sorry for clear a question:
we say “return to SRV”,what is the precise means?
1.complete the IRP,don’t “return status from my IRP_MJ_CREATE dispatch”.
if I complete the IRP,SRV will do right thing(oplock break process).
we don’t need return from my dispatch.
2.complete the IRP,and “return status from my IRP_MJ_CREATE dispatch”.
we must complete the IRP and return from my dispatch,SRV will do right
thing.
You know,If I return from my dispatch,I will lose control,I need do
other thing.


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

thanks,tony,your words helps me very much.
My solution for the question :
1.Very dirty solution.
I just deny all request for Level 1 oplock and batch oplock.
If I meet a FSCTL_REQUEST_OPLOCK_LEVEL_1 or a FSCTL_REQUEST_BATCH_OPLOCK,I just return STATUS_OPLOCK_NOT_GRANTED.
So,I will not meet the IRP_MJ_CREATE that returns STATUS_OPLOCK_BREAK_IN_PROGRESS.
2.rely on the previous info
Yes,I can do it by the previous info.
But,my solution is:
I still call ZwCreateFile with FILE_COMPLETE_IF_OPLOCKED.
if it returns STATUS_OPLOCK_BREAK_IN_PROGRESS,en,I know the file has been opened by others.So,I can decide to deny or passthrough the original IRP_MJ_CREATE.OK,I can returns to the SRV.
But there are two problem on it:
A. You know,I have called ZwCreateFile,so I must call ZwClose in my FSCTL dispatch when I meet FSCTL_OPLOCK_BREAK_NOTIFY.Can it works?
B. I decide to deny or passthrough the original IRP_MJ_CREATE.What should I do?
if I want to deny,I just complete the IRP with STATUS_ACCESS_DENIED ?
If I want to pass,I just call down it?
You know,I return to the SRV is just for that SRV do oplock break;
But now,I returns STATUS_ACCESS_DENIED or the status for calldown the original IRP.SRV can works?

oh,god!This is a big problem for me.