/* $Id$ * captive vfs 'directory' interface to reactos * Copyright (C) 2002-2003 Jan Kratochvil * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; exactly version 2 of June 1991 is required * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "captive/client-directory.h" /* self */ #include "directory.h" /* self-priv */ #include "lib.h" #include #include "captive/unicode.h" #include "reactos/ntos/types.h" /* for HANDLE */ #include "reactos/ddk/iotypes.h" /* for IO_STATUS_BLOCK */ #include "reactos/ddk/iofuncs.h" /* for IoCreateFile() */ #include "result.h" #include "captive/leave.h" #include "captive/usecount.h" #include "vfs.h" #include "captive/parent-Directory.h" static gpointer captive_directory_object_parent_class=NULL; static GnomeVFSResult captive_directory_close(CaptiveDirectoryObject *captive_directory_object); static void captive_directory_object_finalize(CaptiveDirectoryObject *captive_directory_object) { g_return_if_fail(captive_directory_object!=NULL); captive_directory_close(captive_directory_object); /* errors ignored */ G_OBJECT_CLASS(captive_directory_object_parent_class)->finalize((GObject *)captive_directory_object); } static void captive_directory_object_class_init(CaptiveDirectoryObjectClass *class) { GObjectClass *gobject_class=G_OBJECT_CLASS(class); captive_directory_object_parent_class=g_type_class_ref(G_TYPE_OBJECT); gobject_class->finalize=(void (*)(GObject *object))captive_directory_object_finalize; } static void captive_directory_object_init(CaptiveDirectoryObject *captive_directory_object) { captive_directory_object->dir_Handle=NULL; captive_directory_object->read_first=TRUE; captive_directory_object->CaptiveDirectoryObject_QueryDirectory_type= CaptiveDirectoryObject_QueryDirectory_type_FileIdBothDirInformation; } GType captive_directory_object_get_type(void) { static GType captive_directory_object_type=0; if (!captive_directory_object_type) { static const GTypeInfo captive_directory_object_info={ sizeof(CaptiveDirectoryObjectClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc)captive_directory_object_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof(CaptiveDirectoryObject), 5, /* n_preallocs */ (GInstanceInitFunc)captive_directory_object_init, }; captive_directory_object_type=g_type_register_static(G_TYPE_OBJECT, "CaptiveDirectoryObject",&captive_directory_object_info,0); } return captive_directory_object_type; } static GnomeVFSResult captive_directory_new_internal (CaptiveDirectoryObject *captive_directory_object,const gchar *pathname,gboolean create,guint create_perm) { GnomeVFSResult errvfsresult; OBJECT_ATTRIBUTES dir_ObjectAttributes; HANDLE dir_Handle; IO_STATUS_BLOCK dir_IoStatusBlock; NTSTATUS err; g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); errvfsresult=captive_ObjectAttributes_init(pathname,&dir_ObjectAttributes); g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); /* wanted: * IoCreateFile()->ObCreateObject(,,,IoFileObjectType)-> * ->(IoFileObjectType->Create==IopCreateFile)()->IoMountVolume() */ err=IoCreateFile( &dir_Handle, /* FileHandle */ FILE_LIST_DIRECTORY, /* DesiredAccess */ &dir_ObjectAttributes, /* ObjectAttributes */ &dir_IoStatusBlock, /* IoStatusBlock */ NULL, /* AllocationSize; ignored for open */ (!create || create_perm&0200 ? FILE_ATTRIBUTE_NORMAL: FILE_ATTRIBUTE_READONLY), /* FileAttributes; ignored for open */ (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), /* ShareAccess; 0 means exclusive */ (!create ? FILE_OPEN : FILE_CREATE), /* CreateDisposition */ /* FILE_SYNCHRONOUS_IO_{,NON}ALERT: We need to allow W32 filesystem * any waits to not to let it return STATUS_CANT_WAIT us. * Alertability should have only effect on asynchronous events * from KeWaitForSingleObject() by setting/clearing its parameter 'Alertable'. */ FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_ALERT, /* CreateOptions */ NULL, /* EaBuffer */ 0, /* EaLength */ CreateFileTypeNone, /* CreateFileType */ NULL, /* ExtraCreateParameters */ 0); /* Options */ g_free(dir_ObjectAttributes.ObjectName); /* left from captive_gnomevfs_uri_parent_init() */ g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(dir_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC); if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err))) return errvfsresult; g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); g_return_val_if_fail(dir_IoStatusBlock.Information ==(!create ? FILE_OPENED : FILE_CREATED), GNOME_VFS_ERROR_GENERIC); captive_directory_object->dir_Handle=dir_Handle; return GNOME_VFS_OK; } GnomeVFSResult captive_directory_new_open(CaptiveDirectoryObject **captive_directory_object_return, CaptiveVfsObject *captive_vfs_object,const gchar *pathname) { GnomeVFSResult r; CaptiveDirectoryObject *captive_directory_object; g_return_val_if_fail(captive_directory_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(captive_vfs_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); captive_directory_object=g_object_new( CAPTIVE_DIRECTORY_TYPE_OBJECT, /* object_type */ NULL); /* first_property_name; FIXME: support properties */ captive_directory_object->dir_Handle=NULL; captive_directory_object->vfs=captive_vfs_object; *captive_directory_object_return=captive_directory_object; if (captive_vfs_object->is_sandbox_parent) return captive_sandbox_parent_directory_new_open(captive_directory_object,pathname); r=captive_directory_new_internal(captive_directory_object,pathname, FALSE, /* create */ 0); /* create_perm; ignored */ captive_leave(); if (r==GNOME_VFS_OK) captive_usecount(+1); else { g_object_unref(captive_directory_object); *captive_directory_object_return=NULL; } return r; } GnomeVFSResult captive_directory_new_make(CaptiveDirectoryObject **captive_directory_object_return, CaptiveVfsObject *captive_vfs_object,const gchar *pathname,guint perm) { GnomeVFSResult r; CaptiveDirectoryObject *captive_directory_object; g_return_val_if_fail(captive_directory_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(captive_vfs_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); captive_directory_object=g_object_new( CAPTIVE_DIRECTORY_TYPE_OBJECT, /* object_type */ NULL); /* first_property_name; FIXME: support properties */ captive_directory_object->dir_Handle=NULL; captive_directory_object->vfs=captive_vfs_object; *captive_directory_object_return=captive_directory_object; if (captive_vfs_object->is_sandbox_parent) return captive_sandbox_parent_directory_new_make(captive_directory_object,pathname,perm); r=captive_directory_new_internal(captive_directory_object,pathname, TRUE, /* create */ perm); /* create_perm; ignored */ captive_leave(); if (r==GNOME_VFS_OK) captive_usecount(+1); else { g_object_unref(captive_directory_object); *captive_directory_object_return=NULL; } return r; } static GnomeVFSResult FileIdBothDirInformation_to_GnomeVFSFileInfo(GnomeVFSFileInfo *file_info, FILE_ID_BOTH_DIR_INFORMATION *FileIdBothDirInformation,IO_STATUS_BLOCK *IoStatusBlock) { UNICODE_STRING FileName_UnicodeString; BOOLEAN errBOOLEAN; ULONG tmp_ULONG; g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_GENERIC); g_return_val_if_fail(FileIdBothDirInformation!=NULL,GNOME_VFS_ERROR_GENERIC); g_return_val_if_fail(IoStatusBlock!=NULL,GNOME_VFS_ERROR_GENERIC); g_return_val_if_fail(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC); /* do not exceed the returned buffer by this record; Redundant now, see below. */ g_assert((gpointer)(((char *)FileIdBothDirInformation)+FileIdBothDirInformation->NextEntryOffset) <=(gpointer)(((char *)FileIdBothDirInformation)+IoStatusBlock->Information)); /* '->NextEntryOffset' is ==0 as we used 'ReturnSingleEntry==TRUE' */ g_assert(FileIdBothDirInformation->NextEntryOffset==0); file_info->valid_fields=0; FileName_UnicodeString.Length=FileIdBothDirInformation->FileNameLength; FileName_UnicodeString.MaximumLength=FileIdBothDirInformation->FileNameLength +sizeof(*FileIdBothDirInformation->FileName); /* 0-terminator */ g_assert((gpointer)(((char *)FileIdBothDirInformation->FileName)+FileName_UnicodeString.Length) <=(gpointer)(((char *)FileIdBothDirInformation)+IoStatusBlock->Information)); /* ensure we fit below '->IoStatusBlock->Information' at least without the 0-terminator */ FileIdBothDirInformation->FileName[FileIdBothDirInformation->FileNameLength /sizeof(*FileIdBothDirInformation->FileName)]=0; /* 0-terminate it */ FileName_UnicodeString.Buffer=FileIdBothDirInformation->FileName; file_info->name=captive_UnicodeString_to_utf8_malloc(&FileName_UnicodeString); /* '->name' assumed for 'file_info->valid_fields' */ /* FIXME: What is 'FILE_ATTRIBUTE_NORMAL'? */ switch (FileIdBothDirInformation->FileAttributes & (0 | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) { case 0: file_info->type=GNOME_VFS_FILE_TYPE_REGULAR; break; case FILE_ATTRIBUTE_DIRECTORY: file_info->type=GNOME_VFS_FILE_TYPE_DIRECTORY; break; case FILE_ATTRIBUTE_DEVICE: file_info->type=GNOME_VFS_FILE_TYPE_SOCKET; /* or GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE or GNOME_VFS_FILE_TYPE_BLOCK_DEVICE ? */ break; default: file_info->type=GNOME_VFS_FILE_TYPE_UNKNOWN; break; } file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE; /* we use 0600 for r/w files, 0400 for FILE_ATTRIBUTE_READONLY */ file_info->permissions=GNOME_VFS_PERM_USER_READ; if (file_info->type==GNOME_VFS_FILE_TYPE_DIRECTORY) file_info->permissions|=GNOME_VFS_PERM_USER_EXEC; if (!(FileIdBothDirInformation->FileAttributes & FILE_ATTRIBUTE_READONLY)) file_info->permissions|=GNOME_VFS_PERM_USER_WRITE; file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS; file_info->size=FileIdBothDirInformation->EndOfFile.QuadPart; file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE; file_info->block_count=FileIdBothDirInformation->AllocationSize.QuadPart/512; file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT; file_info->flags=GNOME_VFS_FILE_FLAGS_LOCAL; file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_FLAGS; if (FileIdBothDirInformation->LastAccessTime.QuadPart) { /* it may be 0 if not set */ errBOOLEAN=RtlTimeToSecondsSince1970(&FileIdBothDirInformation->LastAccessTime,&tmp_ULONG); g_assert(errBOOLEAN==TRUE); file_info->atime=tmp_ULONG; file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_ATIME; } /* it may be 0 if not set */ if (FileIdBothDirInformation->LastWriteTime.QuadPart || FileIdBothDirInformation->ChangeTime.QuadPart) { errBOOLEAN=RtlTimeToSecondsSince1970( /* take the more recent (==bigger) time: */ (FileIdBothDirInformation->LastWriteTime.QuadPart > FileIdBothDirInformation->ChangeTime.QuadPart ? &FileIdBothDirInformation->LastWriteTime : &FileIdBothDirInformation->ChangeTime), &tmp_ULONG); g_assert(errBOOLEAN==TRUE); file_info->mtime=tmp_ULONG; file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_MTIME; } if (FileIdBothDirInformation->CreationTime.QuadPart) { /* it may be 0 if not set */ errBOOLEAN=RtlTimeToSecondsSince1970(&FileIdBothDirInformation->CreationTime,&tmp_ULONG); g_assert(errBOOLEAN==TRUE); file_info->ctime=tmp_ULONG; file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_CTIME; } return GNOME_VFS_OK; } static GnomeVFSResult FileBothDirInformation_to_FileIdBothDirInformation(FILE_ID_BOTH_DIR_INFORMATION *FileIdBothDirInformation, FILE_BOTH_DIR_INFORMATION *FileBothDirInformation,IO_STATUS_BLOCK *IoStatusBlock) { static LARGE_INTEGER FileId_counter; g_return_val_if_fail(FileIdBothDirInformation!=NULL,GNOME_VFS_ERROR_GENERIC); g_return_val_if_fail(FileBothDirInformation!=NULL,GNOME_VFS_ERROR_GENERIC); g_return_val_if_fail(IoStatusBlock!=NULL,GNOME_VFS_ERROR_GENERIC); g_return_val_if_fail(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC); /* do not exceed the returned buffer by this record; Redundant now, see below. */ g_assert((gpointer)(((char *)FileBothDirInformation)+FileBothDirInformation->NextEntryOffset) <=(gpointer)(((char *)FileBothDirInformation)+IoStatusBlock->Information)); /* '->NextEntryOffset' is ==0 as we used 'ReturnSingleEntry==TRUE' */ g_assert(FileBothDirInformation->NextEntryOffset==0); g_assert((gpointer)(((char *)FileBothDirInformation->FileName)+FileBothDirInformation->FileNameLength) <=(gpointer)(((char *)FileBothDirInformation)+IoStatusBlock->Information)); /* ensure we fit below '->IoStatusBlock->Information' at least without the 0-terminator */ memcpy(FileIdBothDirInformation->FileName,FileBothDirInformation->FileName, FileBothDirInformation->FileNameLength); /* NextEntryOffset already handled */ FileIdBothDirInformation->FileIndex =FileBothDirInformation->FileIndex; FileIdBothDirInformation->CreationTime =FileBothDirInformation->CreationTime; FileIdBothDirInformation->LastAccessTime =FileBothDirInformation->LastAccessTime; FileIdBothDirInformation->LastWriteTime =FileBothDirInformation->LastWriteTime; FileIdBothDirInformation->ChangeTime =FileBothDirInformation->ChangeTime; FileIdBothDirInformation->EndOfFile =FileBothDirInformation->EndOfFile; FileIdBothDirInformation->AllocationSize =FileBothDirInformation->AllocationSize; FileIdBothDirInformation->FileAttributes =FileBothDirInformation->FileAttributes; FileIdBothDirInformation->FileNameLength =FileBothDirInformation->FileNameLength; FileIdBothDirInformation->EaSize =FileBothDirInformation->EaSize; FileIdBothDirInformation->ShortNameLength=FileBothDirInformation->ShortNameLength; g_assert(sizeof(FileIdBothDirInformation->ShortName)==sizeof(FileBothDirInformation->ShortName)); memcpy(FileIdBothDirInformation->ShortName,FileBothDirInformation->ShortName, sizeof(FileBothDirInformation->ShortName)); /* FIXME: Register filenames for uniqueness; * Not needed now as 'FileId' field not used by libcaptive anywhere anyway. */ FileIdBothDirInformation->FileId.QuadPart=FileId_counter.QuadPart++; /* FileName already handled */ IoStatusBlock->Information=sizeof(*FileIdBothDirInformation)+FileIdBothDirInformation->FileNameLength; /* '->NextEntryOffset' is ==0 as we used 'ReturnSingleEntry==TRUE' */ FileIdBothDirInformation->NextEntryOffset=0; return GNOME_VFS_OK; } static GnomeVFSResult captive_directory_close(CaptiveDirectoryObject *captive_directory_object) { NTSTATUS err; HANDLE dir_Handle; g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); if (captive_directory_object->vfs->is_sandbox_parent) return captive_sandbox_parent_directory_close(captive_directory_object); if (captive_directory_object->dir_Handle!=NULL) { /* not yet already closed */ captive_usecount(-1); /* close() errors notwithstanding */ dir_Handle=captive_directory_object->dir_Handle; captive_directory_object->dir_Handle=NULL; err=NtClose(dir_Handle); g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); } captive_leave(); return GNOME_VFS_OK; } GnomeVFSResult captive_directory_read(CaptiveDirectoryObject *captive_directory_object,GnomeVFSFileInfo *file_info) { NTSTATUS err; IO_STATUS_BLOCK dir_IoStatusBlock; FILE_ID_BOTH_DIR_INFORMATION *FileIdBothDirInformation; FILE_BOTH_DIR_INFORMATION *FileBothDirInformation; GnomeVFSResult errvfsresult; g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); if (captive_directory_object->vfs->is_sandbox_parent) return captive_sandbox_parent_directory_read(captive_directory_object,file_info); g_return_val_if_fail(captive_directory_object->dir_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); FileIdBothDirInformation=(void *)captive_directory_object->QueryDirectory_buf.FileIdBothDirInformation; retry: switch (captive_directory_object->CaptiveDirectoryObject_QueryDirectory_type) { case CaptiveDirectoryObject_QueryDirectory_type_FileIdBothDirInformation: err=NtQueryDirectoryFile( captive_directory_object->dir_Handle, /* FileHandle */ NULL, /* PEvent; completion signalling; optional */ NULL, /* ApcRoutine; optional */ NULL, /* ApcContext; optional */ &dir_IoStatusBlock, /* IoStatusBlock */ (gpointer)captive_directory_object->QueryDirectory_buf.FileIdBothDirInformation, /* FileInformation */ sizeof(captive_directory_object->QueryDirectory_buf.FileIdBothDirInformation) /* Length */ -sizeof(*FileIdBothDirInformation->FileName), /* reserve space for 0-terminator */ FileIdBothDirectoryInformation, /* FileInformationClass; =>FILE_ID_BOTH_DIR_INFORMATION */ TRUE, /* ReturnSingleEntry */ NULL, /* FileName; wildcards possible; optional */ captive_directory_object->read_first); /* RestartScan */ if (err==STATUS_NO_SUCH_FILE) { /* 'FileIdBothDirInformation' not supported at least by ext2fsd.sys. * Emulate it from 'FileBothDirectoryInformation' here. */ captive_directory_object->CaptiveDirectoryObject_QueryDirectory_type= CaptiveDirectoryObject_QueryDirectory_type_FileBothDirInformation; goto retry; } captive_directory_object->read_first=FALSE; if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err))) return errvfsresult; g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); break; case CaptiveDirectoryObject_QueryDirectory_type_FileBothDirInformation: FileBothDirInformation=(void *)captive_directory_object->QueryDirectory_buf.FileBothDirInformation; /* SL_INDEX_SPECIFIED is forbidden for ext2fsd.sys-V0.10A although * IIRC it was required for the native W32 filesystems. * Fortunately 'FileBothDirInformation' is just a workaround for ext2fsd.sys-V0.10A * which is not used for the native W32 filesystems and therefore it should be safe. * WARNING: Hack with 'FileIndex==0' to prevent SL_INDEX_SPECIFIED is just libcaptive * specific hack of reactos! See also NtQueryDirectoryFile(). */ FileBothDirInformation->FileIndex=0; err=NtQueryDirectoryFile( captive_directory_object->dir_Handle, /* FileHandle */ NULL, /* PEvent; completion signalling; optional */ NULL, /* ApcRoutine; optional */ NULL, /* ApcContext; optional */ &dir_IoStatusBlock, /* IoStatusBlock */ (gpointer)captive_directory_object->QueryDirectory_buf.FileBothDirInformation, /* FileInformation */ sizeof(captive_directory_object->QueryDirectory_buf.FileBothDirInformation) /* Length */ -sizeof(*FileBothDirInformation->FileName), /* reserve space for 0-terminator */ FileBothDirectoryInformation, /* FileInformationClass; =>FILE_BOTH_DIR_INFORMATION */ TRUE, /* ReturnSingleEntry */ NULL, /* FileName; wildcards possible; optional */ captive_directory_object->read_first); /* RestartScan */ captive_directory_object->read_first=FALSE; if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err))) { /* Do not reset 'read_first' on 'STATUS_NO_SUCH_FILE' to leave us stuck at EOF - GnomeVFS behaves that way. */ return errvfsresult; } g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); errvfsresult=FileBothDirInformation_to_FileIdBothDirInformation(FileIdBothDirInformation,FileBothDirInformation, &dir_IoStatusBlock); g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); break; default: g_assert_not_reached(); } errvfsresult=FileIdBothDirInformation_to_GnomeVFSFileInfo(file_info,FileIdBothDirInformation, &dir_IoStatusBlock); g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); captive_leave(); return GNOME_VFS_OK; } GnomeVFSResult captive_directory_remove(CaptiveDirectoryObject *captive_directory_object) { NTSTATUS err; FILE_DISPOSITION_INFORMATION FileDispositionInformation_struct; IO_STATUS_BLOCK dir_IoStatusBlock; GnomeVFSResult errvfsresult; g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); if (captive_directory_object->vfs->is_sandbox_parent) return captive_sandbox_parent_directory_remove(captive_directory_object); g_return_val_if_fail(captive_directory_object->dir_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); FileDispositionInformation_struct.DoDeleteFile=TRUE; err=NtSetInformationFile( captive_directory_object->dir_Handle, /* FileHandle */ &dir_IoStatusBlock, /* IoStatusBlock */ &FileDispositionInformation_struct, /* FileInformation */ sizeof(FileDispositionInformation_struct), /* Length */ FileDispositionInformation); /* FileInformationClass */ if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err))) return errvfsresult; g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); captive_leave(); return GNOME_VFS_OK; }