From: "Jeffrey Tan[MSFT]" on
Hi Dave,

Sorry for the late response. I am sick at home the whole last week.

Below is the further comment I got from the FS team:

"I was using the term "file" generically. I meant file or directory.

I think something else is going on here. First off, FILE_DELETE_ON_CLOSE
and FileDispositionInformation are NOT the same thing.

There are really two parts to delete. The first part is to logically
delete the file. This consists of the file system marking the file as
deleted and then waiting for the last handle to close. When a file is
marked as deleted, many operations (including new opens) fail. Once the
last handle as closed, the actual delete of the file can take place.

When you open a file with FILE_DELETE_ON_CLOSE, the file is left as is.
Neither part of delete is done. The only thing done is to remember that
when this handle is closed, the file should be deleted. All operations on
the file will proceed as normal. When the handle marked as delete on close
is closed, the file is logically deleted. If that handle was the last
handle, the file will also actually be deleted.

When you use FileDispositionInformation to set a file to deleted, the file
is logically deleted right then. Any new opens for the file and many other
operations will fail. The file system will not complete the actual removal
of the file until the last handle is closed, though.

So when you open a file with FILE_DELETE_ON_CLOSE, it should have no effect
on whether you can rename it. I cannot find any difference in this code
across the various versions of Windows. It seems like there is something
else happening on the XP SP2 system. Is there perhaps some other filter
driver that may be changing behavior? Or is there application maybe not
doing exactly what they are saying it is doing?"

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

From: Corinna Vinschen on
Hi Jeffrey,

Jeffrey Tan[MSFT] wrote:
> Hi Dave,

Last time I checked my name was still Corinna ;)

> Sorry for the late response. I am sick at home the whole last week.

No worries.

> Below is the further comment I got from the FS team:
>
> "I was using the term "file" generically. I meant file or directory.
>
> I think something else is going on here. First off, FILE_DELETE_ON_CLOSE
> and FileDispositionInformation are NOT the same thing.
>
> There are really two parts to delete. The first part is to logically
> delete the file. This consists of the file system marking the file as
> deleted and then waiting for the last handle to close. When a file is
> marked as deleted, many operations (including new opens) fail. Once the
> last handle as closed, the actual delete of the file can take place.
>
> When you open a file with FILE_DELETE_ON_CLOSE, the file is left as is.
> Neither part of delete is done. The only thing done is to remember that
> when this handle is closed, the file should be deleted. All operations on
> the file will proceed as normal. When the handle marked as delete on close
> is closed, the file is logically deleted. If that handle was the last
> handle, the file will also actually be deleted.
>
> When you use FileDispositionInformation to set a file to deleted, the file
> is logically deleted right then. Any new opens for the file and many other
> operations will fail. The file system will not complete the actual removal
> of the file until the last handle is closed, though.

Nice description. That's pretty much as I understood the delete
disposition vs. delete on close operations.

> So when you open a file with FILE_DELETE_ON_CLOSE, it should have no effect
> on whether you can rename it.

That's what I'd expect, too. But still...

> I cannot find any difference in this code
> across the various versions of Windows. It seems like there is something
> else happening on the XP SP2 system. Is there perhaps some other filter
> driver that may be changing behavior? Or is there application maybe not
> doing exactly what they are saying it is doing?"

Well, I think I can exclude special drivers or filter drivers from the
picture. I'm using a quite standard XP system with only selected
applications installed. There's no unusual driver installation besides
what's needed for operating the standard hardware (graphics, network,
disk, cd-rom).

What I did now is this. I created a test application which I attached
to this posting. The source code builds fine with gcc on Cygwin, but I
don't expect much problems building it using VC++ either, except, maybe
the include file paths.

Anyway, what the application does is, it creates three directories with
default permissions:

C:\srcdir
C:\srcdir\victim
C:\tgtdir

Then it opens the directory C:\srcdir\victim and tries to rename it to
C:\tgtdir\victim. After this rename operation, regardless if it
succeeded or not, it waits 15 seconds so that the caller can inspect the
C:\srcdir and c:\tgtdir directories. Just make sure the C:\srcdir and
C:\tgtdir directories don't exist before starting the testcase.

There's a difference in behaviour, whether or not you call the testcase
with or without command line argument.

Without an command line argument, the victim directory is opened
normally -- without DELETE_ON_CLOSE that is -- and after the rename
operation the victim is deleted using thr delete disposition operation.

With any argument on the command line, the victim directory is opened
with DELETE_ON_CLOSE and the delete disposition operation is skipped.

The open/move/delete/close works on all OSes.

The open-with-del-on-close/move/close works on all OSes, except on XP.

I tested my below attached testcase on NT4 SP6, 2000 SP4, XP SP2, 2003
SP1 and Vista. As a sanity check I tested this additionally on a very
standard XP SP2 installation in a virtual machine. The result is the
same. So, as far as my testing goes, there *is* a difference in
behaviour on XP.


Hope that helps,
Corinna


==== SNIP TESTCASE ====
#include <stdio.h>
#include <windows.h>
#include <ddk/ntifs.h>
#include <ddk/winddk.h>
#include <wchar.h>

#define SRCDIR L"\\??\\C:\\srcdir"
#define TGTDIR L"\\??\\C:\\tgtdir"
#define SRCVICTIM L"\\??\\C:\\srcdir\\victim"
#define TGTVICTIM L"\\??\\C:\\tgtdir\\victim"

int
create_dir (WCHAR *dirname)
{
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
HANDLE h;
ULONG len = wcslen (dirname) * 2;
UNICODE_STRING dpath = { len, len + sizeof (WCHAR), dirname };
InitializeObjectAttributes (&attr, &dpath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
NULL, NULL);

status = ZwCreateFile (&h,
FILE_LIST_DIRECTORY | SYNCHRONIZE
| FILE_OPEN_FOR_BACKUP_INTENT,
&attr,
&io,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_CREATE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS (status))
{
fprintf (stderr, "Creating directory failed: status 0x%08lx (win32: %lu)\n",
status, RtlNtStatusToDosError (status));
return -1;
}
ZwClose (h);
return 0;
}

int
prepare ()
{
int ret = 0;
ret |= create_dir (SRCDIR);
ret |= create_dir (SRCVICTIM);
ret |= create_dir (TGTDIR);
if (ret)
exit (1);
}

main (int argc, char **argv)
{
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
HANDLE h;
UNICODE_STRING spath;
PFILE_RENAME_INFORMATION pfri;

prepare ();

ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT;

/* If argc > 1, add the delete-on-close flag. */
if (argc > 1)
{
flags |= FILE_DELETE_ON_CLOSE;
fprintf (stderr, "Open WITH delete-on-close\n");
}
else
fprintf (stderr, "Open WITHOUT delete-on-close\n");

/* Open directory */
RtlInitUnicodeString (&spath, SRCVICTIM);
InitializeObjectAttributes (&attr, &spath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
NULL, NULL);
status = ZwOpenFile (&h, DELETE, &attr, &io,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
flags);
if (!NT_SUCCESS (status))
{
if (status == STATUS_DELETE_PENDING)
{
fprintf (stderr, "Delete is already pending\n");
return 0;
}
fprintf (stderr, "Opening dir failed: status 0x%08lx (win32: %lu)\n",
status, RtlNtStatusToDosError (status));
}

/* Try to move */
pfri = (PFILE_RENAME_INFORMATION) alloca (256); /* Big enough here. */
pfri->ReplaceIfExists = TRUE;
pfri->RootDirectory = NULL;
wcscpy (pfri->FileName, TGTVICTIM);
pfri->FileNameLength = wcslen (TGTVICTIM) * 2;
status = ZwSetInformationFile (h, &io, pfri, 256, FileRenameInformation);
if (!NT_SUCCESS (status))
fprintf (stderr, "Moving dir failed: status 0x%08lx (win32: %lu)\n",
status, RtlNtStatusToDosError (status));
else
{
fprintf (stderr, "Moving dir succeeded. Waiting 15 secs to give time "
"to examine c:\\srcdir and c:\\tgtdir\n");
Sleep (15000L);
}

/* If no arg was given, delete by setting disposition. */
if (argc <= 1)
{
FILE_DISPOSITION_INFORMATION disp = { TRUE };
status = ZwSetInformationFile (h, &io, &disp, sizeof disp,
FileDispositionInformation);
if (!NT_SUCCESS (status))
fprintf (stderr, "Set disposition information failed: "
"status 0x%08lx (win32: %lu)\n",
status, RtlNtStatusToDosError (status));
}

/* Get rid of handle. */
ZwClose (h);
return 0;
}
==== SNAP TESTCASE ====


--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat
From: Corinna Vinschen on
Corinna Vinschen wrote:
> The open/move/delete/close works on all OSes.
>
> The open-with-del-on-close/move/close works on all OSes, except on XP.
>
> I tested my below attached testcase on NT4 SP6, 2000 SP4, XP SP2, 2003
> SP1 and Vista. As a sanity check I tested this additionally on a very
> standard XP SP2 installation in a virtual machine. The result is the
> same. So, as far as my testing goes, there *is* a difference in
> behaviour on XP.

As additional data points, I tested this now in WOW64 on the 64 bit
versions of XP, 2003 and Vista.

The open/move/delete/close works on all 64 bit OSes.

The open-with-del-on-close/move/close works on all 64 bit OSes, except
on XP 64.

The status code returned by ZwSetFileInformation on XP and XP 64 is in
all cases 0xC0000022, STATUS_ACCESS_DENIED.

It's really a surprise that it doesn't work in 64 bit XP, given that
it claims to have the same kernel as 2003 (OS version 5.2).

A third 32 bit XP shows the same problem, btw.


Corinna

--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat
From: "Jeffrey Tan[MSFT]" on
Hi Corinna,

Thanks for your feedback and kindly understanding!

It is awesome you did such detailed testing for this issue even including
WOW64. You are really an experience customer I met :-).

However, this issue's complexity has somewhat gone beyond the support
boundary of MSDN newsgroup. Also, understanding the undocumented API and
finding the root cause of this complex issue has exceeded my ability and
experience. So this issue is not suitable for the official newsgroup
support now. Thanks very much for your understanding.

Anyway, if you really wanted to find more information on this topic, you
may try to contact Microsoft PSS for a case support. The PSS case support
engineer has some more official channel to contact the product team.

You can contact Microsoft Product Support directly to discuss additional
support options you may have available, by contacting us at 1-(800)936-5800
or by choosing one of the options listed at:
http://www.microsoft.com/services/microsoftservices/srv_support.mspx

Again, thanks for your understanding.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.


From: Corinna Vinschen on
Hi Jeffery,

"Jeffrey Tan[MSFT]" wrote:
> However, this issue's complexity has somewhat gone beyond the support
> boundary of MSDN newsgroup. Also, understanding the undocumented API and
> finding the root cause of this complex issue has exceeded my ability and
> experience. So this issue is not suitable for the official newsgroup
> support now. Thanks very much for your understanding.
>
> Anyway, if you really wanted to find more information on this topic, you
> may try to contact Microsoft PSS for a case support. The PSS case support
> engineer has some more official channel to contact the product team.

I'm not sure I get the point here.

I have provided a source code testcase which allows your engineer to
reproduce the bug which I could reproduce now on five different XP
systems. So, just send the testcase to your engineer together with my
description. That should do it to either fix the bug or to ignore it,
which is your decision.

Personally I'm interested to hear what's coming out of it but I have
certasinly no intention to create a support case. I have a working
workaround for this XP bug. The workaround is even demonstrated in my
testcase as well. I will have to use this workaround in the long run
anyway to support Cygwin users running XP without the potential fix.


Corinna

--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat