/* $Id$ * captive vfs 'directory' interface to reactos of sandbox slave * 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 "directory-slave.h" /* self */ #include "captive/client-directory.h" /* for CaptiveDirectoryObject */ #include "directory.h" /* for CaptiveDirectoryObject 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 "vfs-slave.h" #include "captive/rtl-time.h" static gpointer captive_directory_slave_object_parent_class=NULL; static GnomeVFSResult captive_directory_slave_close(CaptiveDirectoryObject *captive_directory_object); static GnomeVFSResult captive_directory_slave_read (CaptiveDirectoryObject *captive_directory_object,CaptiveFileInfoObject **captive_file_info_object_return); static GnomeVFSResult captive_directory_slave_remove(CaptiveDirectoryObject *captive_directory_object); static void captive_directory_slave_object_finalize(CaptiveDirectorySlaveObject *captive_directory_slave_object) { g_return_if_fail(captive_directory_slave_object!=NULL); captive_directory_slave_close(CAPTIVE_DIRECTORY_OBJECT(captive_directory_slave_object)); /* errors ignored */ G_OBJECT_CLASS(captive_directory_slave_object_parent_class)->finalize((GObject *)captive_directory_slave_object); } static void captive_directory_slave_object_class_init(CaptiveDirectorySlaveObjectClass *class) { GObjectClass *gobject_class=G_OBJECT_CLASS(class); CaptiveDirectoryObjectClass *captive_directory_object_class=CAPTIVE_DIRECTORY_OBJECT_CLASS(class); captive_directory_slave_object_parent_class=g_type_class_ref(g_type_parent(G_TYPE_FROM_CLASS(class))); gobject_class->finalize=(void (*)(GObject *object))captive_directory_slave_object_finalize; captive_directory_object_class->read=captive_directory_slave_read; captive_directory_object_class->remove=captive_directory_slave_remove; } static void captive_directory_slave_object_init(CaptiveDirectorySlaveObject *captive_directory_slave_object) { captive_directory_slave_object->dir_Handle=NULL; captive_directory_slave_object->read_first=TRUE; captive_directory_slave_object->CaptiveDirectorySlaveObject_QueryDirectory_type= CaptiveDirectorySlaveObject_QueryDirectory_type_FileIdBothDirInformation; } GType captive_directory_slave_object_get_type(void) { static GType captive_directory_slave_object_type=0; if (!captive_directory_slave_object_type) { static const GTypeInfo captive_directory_slave_object_info={ sizeof(CaptiveDirectorySlaveObjectClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc)captive_directory_slave_object_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof(CaptiveDirectorySlaveObject), 5, /* n_preallocs */ (GInstanceInitFunc)captive_directory_slave_object_init, }; captive_directory_slave_object_type=g_type_register_static(CAPTIVE_DIRECTORY_TYPE_OBJECT, "CaptiveDirectorySlaveObject",&captive_directory_slave_object_info,0); } return captive_directory_slave_object_type; } static GnomeVFSResult captive_directory_slave_new_internal (CaptiveDirectorySlaveObject *captive_directory_slave_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_slave_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_slave_object->dir_Handle=dir_Handle; return GNOME_VFS_OK; } GnomeVFSResult captive_directory_slave_new_open(CaptiveDirectoryObject **captive_directory_object_return, CaptiveVfsObject *captive_vfs_object,const gchar *pathname) { GnomeVFSResult r; CaptiveDirectorySlaveObject *captive_directory_slave_object; g_return_val_if_fail(captive_directory_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(CAPTIVE_VFS_SLAVE_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); captive_directory_slave_object=g_object_new( CAPTIVE_DIRECTORY_SLAVE_TYPE_OBJECT, /* object_type */ NULL); /* first_property_name; FIXME: support properties */ captive_directory_init(CAPTIVE_DIRECTORY_OBJECT(captive_directory_slave_object),captive_vfs_object); *captive_directory_object_return=CAPTIVE_DIRECTORY_OBJECT(captive_directory_slave_object); r=captive_directory_slave_new_internal(captive_directory_slave_object,pathname, FALSE, /* create */ 0); /* create_perm; ignored */ captive_leave(); if (r==GNOME_VFS_OK) captive_usecount(+1); else { g_object_unref(captive_directory_slave_object); *captive_directory_object_return=NULL; } return r; } GnomeVFSResult captive_directory_slave_new_make(CaptiveDirectoryObject **captive_directory_object_return, CaptiveVfsObject *captive_vfs_object,const gchar *pathname,guint perm) { GnomeVFSResult r; CaptiveDirectorySlaveObject *captive_directory_slave_object; g_return_val_if_fail(captive_directory_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(CAPTIVE_VFS_SLAVE_IS_OBJECT(captive_vfs_object),GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); captive_directory_slave_object=g_object_new( CAPTIVE_DIRECTORY_SLAVE_TYPE_OBJECT, /* object_type */ NULL); /* first_property_name; FIXME: support properties */ captive_directory_init(CAPTIVE_DIRECTORY_OBJECT(captive_directory_slave_object),captive_vfs_object); *captive_directory_object_return=CAPTIVE_DIRECTORY_OBJECT(captive_directory_slave_object); r=captive_directory_slave_new_internal(captive_directory_slave_object,pathname, TRUE, /* create */ perm); /* create_perm; ignored */ captive_leave(); if (r==GNOME_VFS_OK) captive_usecount(+1); else { g_object_unref(captive_directory_slave_object); *captive_directory_object_return=NULL; } return r; } static GnomeVFSResult FileIdBothDirInformation_to_CaptiveFileInfoObject( CaptiveFileInfoObject **captive_file_info_object_return, FILE_ID_BOTH_DIR_INFORMATION *FileIdBothDirInformation,IO_STATUS_BLOCK *IoStatusBlock) { UNICODE_STRING FileName_UnicodeString; GnomeVFSResult errvfsresult; CaptiveFileInfoObject *captive_file_info_object; g_return_val_if_fail(captive_file_info_object_return!=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); errvfsresult=captive_file_info_object_new(&captive_file_info_object); g_return_val_if_fail(GNOME_VFS_OK==errvfsresult,errvfsresult); 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); captive_file_info_object->p.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; captive_file_info_object->p.name=captive_UnicodeString_to_utf8_malloc(&FileName_UnicodeString); /* '->name' assumed for 'captive_file_info_object->p.valid_fields' */ /* FIXME: What is 'FILE_ATTRIBUTE_NORMAL'? */ switch (FileIdBothDirInformation->FileAttributes & (0 | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) { case 0: captive_file_info_object->p.type=GNOME_VFS_FILE_TYPE_REGULAR; break; case FILE_ATTRIBUTE_DIRECTORY: captive_file_info_object->p.type=GNOME_VFS_FILE_TYPE_DIRECTORY; break; case FILE_ATTRIBUTE_DEVICE: captive_file_info_object->p.type=GNOME_VFS_FILE_TYPE_SOCKET; /* or GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE or GNOME_VFS_FILE_TYPE_BLOCK_DEVICE ? */ break; default: captive_file_info_object->p.type=GNOME_VFS_FILE_TYPE_UNKNOWN; break; } captive_file_info_object->p.valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE; /* we use 0600 for r/w files, 0400 for FILE_ATTRIBUTE_READONLY */ captive_file_info_object->p.permissions=GNOME_VFS_PERM_USER_READ; if (captive_file_info_object->p.type==GNOME_VFS_FILE_TYPE_DIRECTORY) captive_file_info_object->p.permissions|=GNOME_VFS_PERM_USER_EXEC; if (!(FileIdBothDirInformation->FileAttributes & FILE_ATTRIBUTE_READONLY)) captive_file_info_object->p.permissions|=GNOME_VFS_PERM_USER_WRITE; captive_file_info_object->p.valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS; captive_file_info_object->p.size=FileIdBothDirInformation->EndOfFile.QuadPart; captive_file_info_object->p.valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE; captive_file_info_object->p.block_count=FileIdBothDirInformation->AllocationSize.QuadPart/512; captive_file_info_object->p.valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT; captive_file_info_object->p.flags=GNOME_VFS_FILE_FLAGS_LOCAL; captive_file_info_object->p.valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_FLAGS; if (FileIdBothDirInformation->LastAccessTime.QuadPart) { /* it may be 0 if not set */ struct timespec timespec; errvfsresult=Time_to_timespec(×pec,&FileIdBothDirInformation->LastAccessTime); g_return_val_if_fail(GNOME_VFS_OK==errvfsresult,errvfsresult); captive_file_info_object->p.atime=timespec.tv_sec; captive_file_info_object->atime_nsec=timespec.tv_nsec; captive_file_info_object->p.valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_ATIME; } /* it may be 0 if not set */ if (FileIdBothDirInformation->LastWriteTime.QuadPart || FileIdBothDirInformation->ChangeTime.QuadPart) { struct timespec timespec; errvfsresult=Time_to_timespec(×pec, /* take the more recent (==bigger) time: */ (FileIdBothDirInformation->LastWriteTime.QuadPart > FileIdBothDirInformation->ChangeTime.QuadPart ? &FileIdBothDirInformation->LastWriteTime : &FileIdBothDirInformation->ChangeTime)); g_return_val_if_fail(GNOME_VFS_OK==errvfsresult,errvfsresult); captive_file_info_object->p.mtime=timespec.tv_sec; captive_file_info_object->mtime_nsec=timespec.tv_nsec; captive_file_info_object->p.valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_MTIME; } if (FileIdBothDirInformation->CreationTime.QuadPart) { /* it may be 0 if not set */ struct timespec timespec; errvfsresult=Time_to_timespec(×pec,&FileIdBothDirInformation->CreationTime); g_return_val_if_fail(GNOME_VFS_OK==errvfsresult,errvfsresult); captive_file_info_object->p.ctime=timespec.tv_sec; captive_file_info_object->ctime_nsec=timespec.tv_nsec; captive_file_info_object->p.valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_CTIME; } *captive_file_info_object_return=captive_file_info_object; 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_slave_close(CaptiveDirectoryObject *captive_directory_object) { CaptiveDirectorySlaveObject *captive_directory_slave_object; NTSTATUS err; HANDLE dir_Handle; g_return_val_if_fail(CAPTIVE_DIRECTORY_SLAVE_IS_OBJECT(captive_directory_object),GNOME_VFS_ERROR_BAD_PARAMETERS); captive_directory_slave_object=CAPTIVE_DIRECTORY_SLAVE_OBJECT(captive_directory_object); if (captive_directory_slave_object->dir_Handle!=NULL) { /* not yet already closed */ captive_usecount(-1); /* close() errors notwithstanding */ dir_Handle=captive_directory_slave_object->dir_Handle; captive_directory_slave_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; } static GnomeVFSResult captive_directory_slave_read (CaptiveDirectoryObject *captive_directory_object,CaptiveFileInfoObject **captive_file_info_object_return) { CaptiveDirectorySlaveObject *captive_directory_slave_object; 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_SLAVE_IS_OBJECT(captive_directory_object),GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(captive_file_info_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); captive_directory_slave_object=CAPTIVE_DIRECTORY_SLAVE_OBJECT(captive_directory_object); g_return_val_if_fail(captive_directory_slave_object->dir_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); FileIdBothDirInformation=(void *)captive_directory_slave_object->QueryDirectory_buf.FileIdBothDirInformation; retry: switch (captive_directory_slave_object->CaptiveDirectorySlaveObject_QueryDirectory_type) { case CaptiveDirectorySlaveObject_QueryDirectory_type_FileIdBothDirInformation: err=NtQueryDirectoryFile( captive_directory_slave_object->dir_Handle, /* FileHandle */ NULL, /* PEvent; completion signalling; optional */ NULL, /* ApcRoutine; optional */ NULL, /* ApcContext; optional */ &dir_IoStatusBlock, /* IoStatusBlock */ (gpointer)captive_directory_slave_object->QueryDirectory_buf.FileIdBothDirInformation, /* FileInformation */ sizeof(captive_directory_slave_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_slave_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_slave_object->CaptiveDirectorySlaveObject_QueryDirectory_type= CaptiveDirectorySlaveObject_QueryDirectory_type_FileBothDirInformation; goto retry; } captive_directory_slave_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 CaptiveDirectorySlaveObject_QueryDirectory_type_FileBothDirInformation: FileBothDirInformation=(void *)captive_directory_slave_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_slave_object->dir_Handle, /* FileHandle */ NULL, /* PEvent; completion signalling; optional */ NULL, /* ApcRoutine; optional */ NULL, /* ApcContext; optional */ &dir_IoStatusBlock, /* IoStatusBlock */ (gpointer)captive_directory_slave_object->QueryDirectory_buf.FileBothDirInformation, /* FileInformation */ sizeof(captive_directory_slave_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_slave_object->read_first); /* RestartScan */ captive_directory_slave_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_CaptiveFileInfoObject(captive_file_info_object_return,FileIdBothDirInformation, &dir_IoStatusBlock); g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); captive_leave(); return GNOME_VFS_OK; } static GnomeVFSResult captive_directory_slave_remove(CaptiveDirectoryObject *captive_directory_object) { CaptiveDirectorySlaveObject *captive_directory_slave_object; NTSTATUS err; FILE_DISPOSITION_INFORMATION FileDispositionInformation_struct; IO_STATUS_BLOCK dir_IoStatusBlock; GnomeVFSResult errvfsresult; g_return_val_if_fail(CAPTIVE_DIRECTORY_SLAVE_IS_OBJECT(captive_directory_object),GNOME_VFS_ERROR_BAD_PARAMETERS); captive_directory_slave_object=CAPTIVE_DIRECTORY_SLAVE_OBJECT(captive_directory_object); g_return_val_if_fail(captive_directory_slave_object->dir_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); FileDispositionInformation_struct.DoDeleteFile=TRUE; err=NtSetInformationFile( captive_directory_slave_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; }