From: short <> Date: Sat, 11 Jan 2003 18:23:28 +0000 (+0000) Subject: libcaptive-gnomevfs.so separated to Gnome-VFS vs. reactos specific parts X-Git-Tag: captive-0_2~367 X-Git-Url: http://git.jankratochvil.net/?a=commitdiff_plain;h=a6bbf241da9447587253dc9b44e0845bebdbe9f1;p=captive.git libcaptive-gnomevfs.so separated to Gnome-VFS vs. reactos specific parts - Gnome-VFS part remains in src/client/libcaptive-gnomevfs/ - reactos part implemented by "captive/client-*.h" and "libcaptive/client/*.c" --- diff --git a/src/client/libcaptive-gnomevfs/gnome-vfs-method.c b/src/client/libcaptive-gnomevfs/gnome-vfs-method.c index ed26d6b..759c79f 100644 --- a/src/client/libcaptive-gnomevfs/gnome-vfs-method.c +++ b/src/client/libcaptive-gnomevfs/gnome-vfs-method.c @@ -22,15 +22,11 @@ #include "giognomevfs.h" #include #include -#include -#include "reactos/ntos/types.h" /* for HANDLE */ -#include "reactos/ddk/iotypes.h" /* for IO_STATUS_BLOCK */ #include "captive/macros.h" -#include "reactos/ddk/rtl.h" /* for InitializeObjectAttributes() */ -#include "captive/unicode.h" -#include "reactos/ddk/iofuncs.h" /* for IoCreateFile() */ #include "gnome-vfs-module.h" -#include /* for gnome_vfs_unescape_string() */ +#include "captive/client-directory.h" +#include "captive/client-file.h" +#include "captive/client-file_info.h" static GnomeVFSMethod GnomeVFSMethod_static; @@ -44,13 +40,10 @@ static gchar *captive_gnomevfs_uri_parent_fs_path; static struct captive_gnomevfs_giognomevfs *captive_gnomevfs_uri_parent_giognomevfs; -/* function will leave g_malloc()ed 'ObjectAttributes->ObjectName' if ObjectAttributes ! - */ -static GnomeVFSResult captive_gnomevfs_uri_parent_init(GnomeVFSURI *uri,OBJECT_ATTRIBUTES *ObjectAttributes) +static GnomeVFSResult captive_gnomevfs_uri_parent_init(GnomeVFSURI *uri) { gchar *uri_parent_string; GnomeVFSResult errvfsresult; -gchar *w32_path,*s,*d,*vfs_path; g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_INVALID_URI); @@ -74,218 +67,45 @@ gchar *w32_path,*s,*d,*vfs_path; } G_UNLOCK(captive_gnomevfs_uri_parent); - if (ObjectAttributes) { - /* Do not open "\Cdfs"(anything) as it is just the filesystem implementation. - * ntoskrnl/io/fs.c/IoMountVolume() will map - * FILE_DEVICE_CD_ROM -> FILE_DEVICE_CD_ROM_FILE_SYSTEM - * for us automatically when opening the device itself. - * If you put some trailing content (such as "\\.") there - * IoCreateFile()->ObCreateObject()->ObFindObject() - * will not leave 'ObCreateObject::RemainingPath' as NULL - * and later IopCreateFile() would not consider it FO_DIRECT_DEVICE_OPEN (e.g. w/o any direct mount!). - * On the other side it will somehow get managed automatically and it works even - * without the trailing "\\." for root directory open - don't ask me why. :-) - */ - vfs_path=gnome_vfs_unescape_string( /* decode %xy escaping */ - uri->text, /* escaped */ - NULL); /* illegal_characters */ - w32_path=(gchar *)/* de-const it as we can modify it but we must not free() it */ - captive_printf_alloca("\\Device\\CdRom0\\%s",vfs_path); - g_free(vfs_path); - /* translate '/' -> '\' */ - for (s=w32_path;(s=strchr(s,'/'));s++) - *s='\\'; - /* collapse multiple sequences of '\' as it is a no-no for W32 */ - for (s=d=w32_path;*s;s++) - if (d==w32_path || !(*s=='\\' && d[-1]=='\\')) - *d++=*s; - *d=0; - G_LOCK(libcaptive); - InitializeObjectAttributes( - ObjectAttributes, /* InitializedAttributes */ - captive_utf8_to_UnicodeString_malloc(w32_path), /* ObjectName */ - 0, /* Attributes; I hope no OBJ_KERNEL_HANDLE as we are 'system process' */ - NULL, /* RootDirectory */ - NULL); /* SecurityDescriptor; ignored */ - G_UNLOCK(libcaptive); - } - return GNOME_VFS_OK; } -struct captive_gnomevfs_directory_handle { - HANDLE dir_Handle; - gboolean read_first; - /* 'QueryDirectory_buf' for NtQueryDirectoryFile() must be persistent - * to keep the state if !read_first - */ - char QueryDirectory_buf[sizeof(FILE_ID_BOTH_DIR_INFORMATION) - +0x1000 /* max 'FileName' length, 255 should be enough */ * sizeof(WCHAR /* *FILE_ID_BOTH_DIR_INFORMATION.FileName */ )]; - }; - static GnomeVFSResult captive_gnomevfs_open_directory(GnomeVFSMethod *method, GnomeVFSMethodHandle **method_handle,GnomeVFSURI *uri,GnomeVFSFileInfoOptions options,GnomeVFSContext *context) { GnomeVFSResult errvfsresult; -OBJECT_ATTRIBUTES dir_ObjectAttributes; -HANDLE dir_Handle; -IO_STATUS_BLOCK dir_IoStatusBlock; -NTSTATUS err; -struct captive_gnomevfs_directory_handle *directory_handle; +CaptiveDirectoryObject *captive_directory_object; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); - errvfsresult=captive_gnomevfs_uri_parent_init(uri,&dir_ObjectAttributes); + errvfsresult=captive_gnomevfs_uri_parent_init(uri); g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); - - /* wanted: * IoCreateFile()->ObCreateObject(,,,IoFileObjectType)-> - * ->(IoFileObjectType->Create==IopCreateFile)()->IoMountVolume() - */ + G_LOCK(libcaptive); - err=IoCreateFile( - &dir_Handle, /* FileHandle */ - FILE_LIST_DIRECTORY, /* DesiredAccess */ - &dir_ObjectAttributes, /* ObjectAttributes */ - &dir_IoStatusBlock, /* IoStatusBlock */ - NULL, /* AllocationSize; ignored for open */ - FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */ - FILE_SHARE_WRITE, /* ShareAccess; 0 means exclusive */ - FILE_OPEN, /* 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 */ + errvfsresult=captive_directory_new_open( + &captive_directory_object, /* captive_directory_object_return */ + uri->text); /* pathname */ G_UNLOCK(libcaptive); - 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); - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); - g_return_val_if_fail(dir_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC); - - captive_new(directory_handle); - directory_handle->dir_Handle=dir_Handle; - directory_handle->read_first=TRUE; - *method_handle=(GnomeVFSMethodHandle *)directory_handle; - return GNOME_VFS_OK; + *method_handle=(GnomeVFSMethodHandle *)captive_directory_object; + return errvfsresult; } static GnomeVFSResult captive_gnomevfs_close_directory(GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context) { -struct captive_gnomevfs_directory_handle *directory_handle; -NTSTATUS err; +CaptiveDirectoryObject *captive_directory_object; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + captive_directory_object=(CaptiveDirectoryObject *)method_handle; + g_return_val_if_fail(CAPTIVE_DIRECTORY_IS_OBJECT(captive_directory_object),GNOME_VFS_ERROR_BAD_PARAMETERS); - directory_handle=(struct captive_gnomevfs_directory_handle *)method_handle; G_LOCK(libcaptive); - err=NtClose(directory_handle->dir_Handle); + g_object_unref(captive_directory_object); G_UNLOCK(libcaptive); - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); - - g_free(directory_handle); - return GNOME_VFS_OK; -} - - -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(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC); - /* do not exceed the returned buffer by this record; - * '->NextEntryOffset' is ==0 as we used 'ReturnSingleEntry==TRUE' - */ - g_assert((gpointer)(((char *)FileIdBothDirInformation)+FileIdBothDirInformation->NextEntryOffset) - <=(gpointer)(((char *)FileIdBothDirInformation)+IoStatusBlock->Information)); - - 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; } @@ -294,125 +114,56 @@ ULONG tmp_ULONG; static GnomeVFSResult captive_gnomevfs_read_directory(GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle,GnomeVFSFileInfo *file_info,GnomeVFSContext *context) { -struct captive_gnomevfs_directory_handle *directory_handle; -NTSTATUS err; -IO_STATUS_BLOCK dir_IoStatusBlock; -FILE_ID_BOTH_DIR_INFORMATION *FileIdBothDirInformation; GnomeVFSResult errvfsresult; +CaptiveDirectoryObject *captive_directory_object; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + captive_directory_object=(CaptiveDirectoryObject *)method_handle; + g_return_val_if_fail(CAPTIVE_DIRECTORY_IS_OBJECT(captive_directory_object),GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); - directory_handle=(struct captive_gnomevfs_directory_handle *)method_handle; - - FileIdBothDirInformation=(void *)directory_handle->QueryDirectory_buf; G_LOCK(libcaptive); - err=NtQueryDirectoryFile( - directory_handle->dir_Handle, /* FileHandle */ - NULL, /* PEvent; completion signalling; optional */ - NULL, /* ApcRoutine; optional */ - NULL, /* ApcContext; optional */ - &dir_IoStatusBlock, /* IoStatusBlock */ - (gpointer)directory_handle->QueryDirectory_buf, /* FileInformation */ - sizeof(directory_handle->QueryDirectory_buf) /* Length */ - -sizeof(*FileIdBothDirInformation->FileName), /* reserve space for 0-terminator */ - FileIdBothDirectoryInformation, /* FileInformationClass; =>FILE_ID_BOTH_DIR_INFORMATION */ - TRUE, /* ReturnSingleEntry */ - NULL, /* FileName; wildcards possible; optional */ - directory_handle->read_first); /* RestartScan */ + errvfsresult=captive_directory_read(captive_directory_object,file_info); G_UNLOCK(libcaptive); - directory_handle->read_first=FALSE; - if (err==STATUS_NO_MORE_FILES) - return GNOME_VFS_ERROR_EOF; - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); - errvfsresult=FileIdBothDirInformation_to_GnomeVFSFileInfo(file_info,FileIdBothDirInformation, - &dir_IoStatusBlock); - g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); - - return GNOME_VFS_OK; + return errvfsresult; } -struct captive_gnomevfs_file_handle { - HANDLE file_Handle; - GnomeVFSFileOffset offset; - }; - static GnomeVFSResult captive_gnomevfs_open(GnomeVFSMethod *method, GnomeVFSMethodHandle **method_handle_return,GnomeVFSURI *uri,GnomeVFSOpenMode mode,GnomeVFSContext *context) { -IO_STATUS_BLOCK file_IoStatusBlock; GnomeVFSResult errvfsresult; -OBJECT_ATTRIBUTES file_ObjectAttributes; -HANDLE file_Handle; -struct captive_gnomevfs_file_handle *file_handle; -NTSTATUS err; +CaptiveFileObject *captive_file_object; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(method_handle_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); - /* init */ - errvfsresult=captive_gnomevfs_uri_parent_init(uri,&file_ObjectAttributes); + errvfsresult=captive_gnomevfs_uri_parent_init(uri); g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); - - /* open */ + G_LOCK(libcaptive); - err=IoCreateFile( - &file_Handle, /* FileHandle */ - 0 - |(!(mode&GNOME_VFS_OPEN_READ ) ? 0 : FILE_READ_DATA) - |(!(mode&GNOME_VFS_OPEN_WRITE) ? 0 : FILE_WRITE_DATA | FILE_APPEND_DATA) - , /* DesiredAccess */ - &file_ObjectAttributes, /* ObjectAttributes */ - &file_IoStatusBlock, /* IoStatusBlock */ - NULL, /* AllocationSize; ignored for open */ - FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */ - FILE_SHARE_WRITE, /* ShareAccess; 0 means exclusive */ - FILE_OPEN, /* 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_SYNCHRONOUS_IO_ALERT, /* CreateOptions */ - NULL, /* EaBuffer */ - 0, /* EaLength */ - CreateFileTypeNone, /* CreateFileType */ - NULL, /* ExtraCreateParameters */ - 0); /* Options */ + errvfsresult=captive_file_new_open(&captive_file_object,uri->text,mode); G_UNLOCK(libcaptive); - g_free(file_ObjectAttributes.ObjectName); /* left from captive_gnomevfs_uri_parent_init() */ - g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC); - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); - g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC); - - captive_new(file_handle); - file_handle->file_Handle=file_Handle; - file_handle->offset=0; - *method_handle_return=(GnomeVFSMethodHandle *)file_handle; - return GNOME_VFS_OK; + *method_handle_return=(GnomeVFSMethodHandle *)captive_file_object; + return errvfsresult; } static GnomeVFSResult captive_gnomevfs_close(GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle,GnomeVFSContext *context) { -struct captive_gnomevfs_file_handle *file_handle; -NTSTATUS err; +CaptiveFileObject *captive_file_object; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + captive_file_object=(CaptiveFileObject *)method_handle; + g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS); - file_handle=(struct captive_gnomevfs_file_handle *)method_handle; G_LOCK(libcaptive); - err=NtClose(file_handle->file_Handle); + g_object_unref(captive_file_object); G_UNLOCK(libcaptive); - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); - g_free(file_handle); return GNOME_VFS_OK; } @@ -420,89 +171,56 @@ NTSTATUS err; static GnomeVFSResult captive_gnomevfs_read(GnomeVFSMethod *method,GnomeVFSMethodHandle *method_handle, gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return,GnomeVFSContext *context) { -struct captive_gnomevfs_file_handle *file_handle; -NTSTATUS err; -IO_STATUS_BLOCK file_IoStatusBlock; -LARGE_INTEGER file_offset; +GnomeVFSResult errvfsresult; +CaptiveFileObject *captive_file_object; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + captive_file_object=(CaptiveFileObject *)method_handle; + g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(bytes_read_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail(num_bytes==(ULONG)num_bytes,GNOME_VFS_ERROR_BAD_PARAMETERS); - file_handle=(struct captive_gnomevfs_file_handle *)method_handle; - file_offset.QuadPart=file_handle->offset; G_LOCK(libcaptive); - err=NtReadFile( - file_handle->file_Handle, /* FileHandle */ - NULL, /* EventHandle; completion signalling; optional */ - NULL, /* ApcRoutine; optional */ - NULL, /* ApcContext; optional */ - &file_IoStatusBlock, /* IoStatusBlock */ - buffer, /* Buffer */ - num_bytes, /* Length */ - &file_offset, /* ByteOffset */ - NULL); /* Key; NULL means no file locking key */ + errvfsresult=captive_file_read(captive_file_object,buffer,num_bytes,bytes_read_return); G_UNLOCK(libcaptive); - if (err==STATUS_END_OF_FILE) { - g_return_val_if_fail(file_IoStatusBlock.Status==STATUS_END_OF_FILE,GNOME_VFS_ERROR_GENERIC); - g_return_val_if_fail(file_IoStatusBlock.Information==0,GNOME_VFS_ERROR_GENERIC); - *bytes_read_return=0; - return GNOME_VFS_ERROR_EOF; - } - g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC); - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); - g_return_val_if_fail(file_IoStatusBlock.Information<=num_bytes,GNOME_VFS_ERROR_GENERIC); - file_handle->offset+=file_IoStatusBlock.Information; - *bytes_read_return=file_IoStatusBlock.Information; - return GNOME_VFS_OK; + return errvfsresult; } static GnomeVFSResult captive_gnomevfs_seek(GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset,GnomeVFSContext *context) { -struct captive_gnomevfs_file_handle *file_handle; +GnomeVFSResult errvfsresult; +CaptiveFileObject *captive_file_object; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + captive_file_object=(CaptiveFileObject *)method_handle; + g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS); - file_handle=(struct captive_gnomevfs_file_handle *)method_handle; - switch (whence) { - case GNOME_VFS_SEEK_START: - file_handle->offset=offset; - break; - case GNOME_VFS_SEEK_CURRENT: - if (0 - || (offset>0 && (file_handle->offset+offset)offset) - || (offset<0 && (file_handle->offset+offset)>file_handle->offset)) - return GNOME_VFS_ERROR_BAD_PARAMETERS; - file_handle->offset+=offset; - break; - case GNOME_VFS_SEEK_END: - g_assert_not_reached(); /* NOT IMPLEMENTED YET */ - break; - default: - g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS); - } + G_LOCK(libcaptive); + errvfsresult=captive_file_seek(captive_file_object,whence,offset); + G_UNLOCK(libcaptive); - return GNOME_VFS_OK; + return errvfsresult; } static GnomeVFSResult captive_gnomevfs_tell(GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle,GnomeVFSFileOffset *offset_return) { -struct captive_gnomevfs_file_handle *file_handle; +GnomeVFSResult errvfsresult; +CaptiveFileObject *captive_file_object; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); - g_return_val_if_fail(method_handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + captive_file_object=(CaptiveFileObject *)method_handle; + g_return_val_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object),GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(offset_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); - file_handle=(struct captive_gnomevfs_file_handle *)method_handle; - *offset_return=file_handle->offset; - return GNOME_VFS_OK; + G_LOCK(libcaptive); + errvfsresult=captive_file_tell(captive_file_object,offset_return); + G_UNLOCK(libcaptive); + + return errvfsresult; } @@ -523,181 +241,23 @@ static gboolean captive_gnomevfs_is_local(GnomeVFSMethod *method,const GnomeVFSU } -/* Use 'FileAllInformationStruct' identifier instead of the logical 'FileAllInformation' - * to prevent override of enum member 'FileAllInformation' - */ -static GnomeVFSResult FileAllInformationStruct_to_GnomeVFSFileInfo(GnomeVFSFileInfo *file_info, - FILE_ALL_INFORMATION *FileAllInformationStruct,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(FileAllInformationStruct!=NULL,GNOME_VFS_ERROR_GENERIC); - - g_return_val_if_fail(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC); - - file_info->valid_fields=0; - - FileName_UnicodeString.Length=FileAllInformationStruct->NameInformation.FileNameLength; - FileName_UnicodeString.MaximumLength=FileAllInformationStruct->NameInformation.FileNameLength - +sizeof(*FileAllInformationStruct->NameInformation.FileName); /* 0-terminator */ - g_assert((gpointer)(((char *)FileAllInformationStruct->NameInformation.FileName)+FileName_UnicodeString.Length) - <=(gpointer)(((char *)FileAllInformationStruct)+IoStatusBlock->Information)); - /* ensure we fit below '->IoStatusBlock->Information' at least without the 0-terminator */ - FileAllInformationStruct->NameInformation.FileName[FileAllInformationStruct->NameInformation.FileNameLength - /sizeof(*FileAllInformationStruct->NameInformation.FileName)]=0; /* 0-terminate it */ - FileName_UnicodeString.Buffer=FileAllInformationStruct->NameInformation.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 (FileAllInformationStruct->BasicInformation.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 (!(FileAllInformationStruct->BasicInformation.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=FileAllInformationStruct->StandardInformation.EndOfFile.QuadPart; - file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE; - - file_info->block_count=FileAllInformationStruct->StandardInformation.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 (FileAllInformationStruct->BasicInformation.LastAccessTime.QuadPart) { /* it may be 0 if not set */ - errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.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 (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart || FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart) { - errBOOLEAN=RtlTimeToSecondsSince1970( - /* take the more recent (==bigger) time: */ - (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart > FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart - ? &FileAllInformationStruct->BasicInformation.LastWriteTime : &FileAllInformationStruct->BasicInformation.ChangeTime), - &tmp_ULONG); - g_assert(errBOOLEAN==TRUE); - file_info->mtime=tmp_ULONG; - file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_MTIME; - } - - if (FileAllInformationStruct->BasicInformation.CreationTime.QuadPart) { /* it may be 0 if not set */ - errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.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 captive_gnomevfs_get_file_info(GnomeVFSMethod *method, GnomeVFSURI *uri,GnomeVFSFileInfo *file_info,GnomeVFSFileInfoOptions options,GnomeVFSContext *context) { -NTSTATUS err; -IO_STATUS_BLOCK file_IoStatusBlock; -FILE_ALL_INFORMATION *FileAllInformationStruct; GnomeVFSResult errvfsresult; -OBJECT_ATTRIBUTES file_ObjectAttributes; -HANDLE file_Handle; -char QueryFile_buf[sizeof(FILE_ALL_INFORMATION) - +0x1000 /* max 'FileName' length, 255 should be enough */ * sizeof(WCHAR /* *FILE_ALL_INFORMATION.NameInformation.FileName */ )]; g_return_val_if_fail(method==&GnomeVFSMethod_static,GNOME_VFS_ERROR_BAD_PARAMETERS); g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); /* handle 'options & GNOME_VFS_FILE_INFO_GET_MIME_TYPE'? */ - /* init */ - errvfsresult=captive_gnomevfs_uri_parent_init(uri,&file_ObjectAttributes); + errvfsresult=captive_gnomevfs_uri_parent_init(uri); g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); - - /* open */ - G_LOCK(libcaptive); - err=IoCreateFile( - &file_Handle, /* FileHandle */ - FILE_READ_ATTRIBUTES, /* DesiredAccess */ - &file_ObjectAttributes, /* ObjectAttributes */ - &file_IoStatusBlock, /* IoStatusBlock */ - NULL, /* AllocationSize; ignored for open */ - FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */ - FILE_SHARE_WRITE, /* ShareAccess; 0 means exclusive */ - FILE_OPEN, /* 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_SYNCHRONOUS_IO_ALERT, /* CreateOptions */ - NULL, /* EaBuffer */ - 0, /* EaLength */ - CreateFileTypeNone, /* CreateFileType */ - NULL, /* ExtraCreateParameters */ - 0); /* Options */ - G_UNLOCK(libcaptive); - g_free(file_ObjectAttributes.ObjectName); /* left from captive_gnomevfs_uri_parent_init() */ - g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC); - if (err==STATUS_OBJECT_NAME_NOT_FOUND) - return GNOME_VFS_ERROR_NOT_FOUND; - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); - g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC); - - /* query */ - FileAllInformationStruct=(void *)QueryFile_buf; - G_LOCK(libcaptive); - err=NtQueryInformationFile( - file_Handle, /* FileHandle */ - &file_IoStatusBlock, /* IoStatusBlock */ - (gpointer)QueryFile_buf, /* FileInformation */ - sizeof(QueryFile_buf) /* Length */ - -sizeof(*FileAllInformationStruct->NameInformation.FileName), /* reserve space for 0-terminator */ - FileAllInformation); /* FileInformationClass; =>FILE_ALL_INFORMATION */ - G_UNLOCK(libcaptive); - if (!NT_SUCCESS(err)) { - g_assert_not_reached(); - goto err_close; - } - /* close */ G_LOCK(libcaptive); - err=NtClose(file_Handle); + errvfsresult=captive_file_info_get(uri->text,file_info); G_UNLOCK(libcaptive); - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); - - /* process gathered info */ - errvfsresult=FileAllInformationStruct_to_GnomeVFSFileInfo(file_info,FileAllInformationStruct, - &file_IoStatusBlock); - g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); - return GNOME_VFS_OK; - -err_close: - G_LOCK(libcaptive); - err=NtClose(file_Handle); - G_UNLOCK(libcaptive); - g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); -/* err: */ - g_return_val_if_reached(GNOME_VFS_ERROR_GENERIC); + return errvfsresult; } diff --git a/src/libcaptive/client/Makefile.am b/src/libcaptive/client/Makefile.am index 5808019..6fc288b 100644 --- a/src/libcaptive/client/Makefile.am +++ b/src/libcaptive/client/Makefile.am @@ -21,4 +21,8 @@ include $(top_srcdir)/src/libcaptive/Makefile-libcaptive.am noinst_LTLIBRARIES=libclient.la libclient_la_SOURCES= \ - init.c + init.c \ + lib.c \ + directory.c \ + file.c \ + file_info.c diff --git a/src/libcaptive/client/directory.c b/src/libcaptive/client/directory.c new file mode 100644 index 0000000..41ed664 --- /dev/null +++ b/src/libcaptive/client/directory.c @@ -0,0 +1,298 @@ +/* $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 "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() */ + + +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) +{ +GnomeVFSResult errvfsresult; + + g_return_if_fail(captive_directory_object!=NULL); + + errvfsresult=captive_directory_close(captive_directory_object); + g_assert(errvfsresult==GNOME_VFS_OK); + + 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; +} + + +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; +} + + +GnomeVFSResult captive_directory_new_open(CaptiveDirectoryObject **captive_directory_object_return,const gchar *pathname) +{ +GnomeVFSResult errvfsresult; +OBJECT_ATTRIBUTES dir_ObjectAttributes; +HANDLE dir_Handle; +IO_STATUS_BLOCK dir_IoStatusBlock; +NTSTATUS err; +CaptiveDirectoryObject *captive_directory_object; + + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_directory_new_open(captive_directory_object_return,pathname); + + g_return_val_if_fail(captive_directory_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + + *captive_directory_object_return=NULL; + + 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 */ + FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */ + FILE_SHARE_WRITE, /* ShareAccess; 0 means exclusive */ + FILE_OPEN, /* 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); + g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); + g_return_val_if_fail(dir_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC); + + captive_directory_object=g_object_new( + CAPTIVE_DIRECTORY_TYPE_OBJECT, /* object_type */ + NULL); /* first_property_name; FIXME: support properties */ + + captive_directory_object->dir_Handle=dir_Handle; + + *captive_directory_object_return=captive_directory_object; + return GNOME_VFS_OK; +} + + +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(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC); + /* do not exceed the returned buffer by this record; + * '->NextEntryOffset' is ==0 as we used 'ReturnSingleEntry==TRUE' + */ + g_assert((gpointer)(((char *)FileIdBothDirInformation)+FileIdBothDirInformation->NextEntryOffset) + <=(gpointer)(((char *)FileIdBothDirInformation)+IoStatusBlock->Information)); + + 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 captive_directory_close(CaptiveDirectoryObject *captive_directory_object) +{ +NTSTATUS err; +HANDLE dir_Handle; + + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_directory_close(captive_directory_object); + + g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(captive_directory_object->dir_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); /* already closed */ + + 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); + + 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; +GnomeVFSResult errvfsresult; + + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_directory_read(captive_directory_object,file_info); + + g_return_val_if_fail(captive_directory_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(captive_directory_object->dir_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + + FileIdBothDirInformation=(void *)captive_directory_object->QueryDirectory_buf; + 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, /* FileInformation */ + sizeof(captive_directory_object->QueryDirectory_buf) /* 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 */ + captive_directory_object->read_first=FALSE; + if (err==STATUS_NO_MORE_FILES) + return GNOME_VFS_ERROR_EOF; + g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); + + errvfsresult=FileIdBothDirInformation_to_GnomeVFSFileInfo(file_info,FileIdBothDirInformation, + &dir_IoStatusBlock); + g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); + + return GNOME_VFS_OK; +} diff --git a/src/libcaptive/client/file.c b/src/libcaptive/client/file.c new file mode 100644 index 0000000..bbabcee --- /dev/null +++ b/src/libcaptive/client/file.c @@ -0,0 +1,256 @@ +/* $Id$ + * captive vfs 'file' 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-file.h" /* self */ +#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() */ + + +static gpointer captive_file_object_parent_class=NULL; + + +static GnomeVFSResult captive_file_close(CaptiveFileObject *captive_file_object); + +static void captive_file_object_finalize(CaptiveFileObject *captive_file_object) +{ +GnomeVFSResult errvfsresult; + + g_return_if_fail(captive_file_object!=NULL); + + errvfsresult=captive_file_close(captive_file_object); + g_assert(errvfsresult==GNOME_VFS_OK); + + G_OBJECT_CLASS(captive_file_object_parent_class)->finalize((GObject *)captive_file_object); +} + + +static void captive_file_object_class_init(CaptiveFileObjectClass *class) +{ +GObjectClass *gobject_class=G_OBJECT_CLASS(class); + + captive_file_object_parent_class=g_type_class_ref(G_TYPE_OBJECT); + gobject_class->finalize=(void (*)(GObject *object))captive_file_object_finalize; +} + + +static void captive_file_object_init(CaptiveFileObject *captive_file_object) +{ + captive_file_object->file_Handle=NULL; +} + + +GType captive_file_object_get_type(void) +{ +static GType captive_file_object_type=0; + + if (!captive_file_object_type) { +static const GTypeInfo captive_file_object_info={ + sizeof(CaptiveFileObjectClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)captive_file_object_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(CaptiveFileObject), + 5, /* n_preallocs */ + (GInstanceInitFunc)captive_file_object_init, + }; + + captive_file_object_type=g_type_register_static(G_TYPE_OBJECT, + "CaptiveFileObject",&captive_file_object_info,0); + } + + return captive_file_object_type; +} + + +GnomeVFSResult captive_file_new_open + (CaptiveFileObject **captive_file_object_return,const gchar *pathname,GnomeVFSOpenMode mode) +{ +IO_STATUS_BLOCK file_IoStatusBlock; +GnomeVFSResult errvfsresult; +OBJECT_ATTRIBUTES file_ObjectAttributes; +HANDLE file_Handle; +CaptiveFileObject *captive_file_object; +NTSTATUS err; + + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_file_new_open(captive_file_object_return,pathname,mode); + + g_return_val_if_fail(captive_file_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + + *captive_file_object_return=NULL; + + errvfsresult=captive_ObjectAttributes_init(pathname,&file_ObjectAttributes); + g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); + + /* open */ + err=IoCreateFile( + &file_Handle, /* FileHandle */ + 0 + |(!(mode&GNOME_VFS_OPEN_READ ) ? 0 : FILE_READ_DATA) + |(!(mode&GNOME_VFS_OPEN_WRITE) ? 0 : FILE_WRITE_DATA | FILE_APPEND_DATA) + , /* DesiredAccess */ + &file_ObjectAttributes, /* ObjectAttributes */ + &file_IoStatusBlock, /* IoStatusBlock */ + NULL, /* AllocationSize; ignored for open */ + FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */ + FILE_SHARE_WRITE, /* ShareAccess; 0 means exclusive */ + FILE_OPEN, /* 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_SYNCHRONOUS_IO_ALERT, /* CreateOptions */ + NULL, /* EaBuffer */ + 0, /* EaLength */ + CreateFileTypeNone, /* CreateFileType */ + NULL, /* ExtraCreateParameters */ + 0); /* Options */ + g_free(file_ObjectAttributes.ObjectName); /* left from captive_file_uri_parent_init() */ + g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC); + g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); + g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC); + + captive_file_object=g_object_new( + CAPTIVE_FILE_TYPE_OBJECT, /* object_type */ + NULL); /* first_property_name; FIXME: support properties */ + + captive_file_object->file_Handle=file_Handle; + captive_file_object->offset=0; + + *captive_file_object_return=captive_file_object; + return GNOME_VFS_OK; +} + + +static GnomeVFSResult captive_file_close(CaptiveFileObject *captive_file_object) +{ +NTSTATUS err; +HANDLE file_Handle; + + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_file_close(captive_file_object); + + g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); /* already closed */ + + file_Handle=captive_file_object->file_Handle; + captive_file_object->file_Handle=NULL; + err=NtClose(file_Handle); + g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); + + return GNOME_VFS_OK; +} + + +GnomeVFSResult captive_file_read + (CaptiveFileObject *captive_file_object,gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return) +{ +NTSTATUS err; +IO_STATUS_BLOCK file_IoStatusBlock; +LARGE_INTEGER file_offset; + + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_file_read(captive_file_object,buffer,num_bytes,bytes_read_return); + + g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(bytes_read_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(num_bytes==(ULONG)num_bytes,GNOME_VFS_ERROR_BAD_PARAMETERS); + + file_offset.QuadPart=captive_file_object->offset; + err=NtReadFile( + captive_file_object->file_Handle, /* FileHandle */ + NULL, /* EventHandle; completion signalling; optional */ + NULL, /* ApcRoutine; optional */ + NULL, /* ApcContext; optional */ + &file_IoStatusBlock, /* IoStatusBlock */ + buffer, /* Buffer */ + num_bytes, /* Length */ + &file_offset, /* ByteOffset */ + NULL); /* Key; NULL means no file locking key */ + if (err==STATUS_END_OF_FILE) { + g_return_val_if_fail(file_IoStatusBlock.Status==STATUS_END_OF_FILE,GNOME_VFS_ERROR_GENERIC); + g_return_val_if_fail(file_IoStatusBlock.Information==0,GNOME_VFS_ERROR_GENERIC); + *bytes_read_return=0; + return GNOME_VFS_ERROR_EOF; + } + g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC); + g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); + g_return_val_if_fail(file_IoStatusBlock.Information<=num_bytes,GNOME_VFS_ERROR_GENERIC); + + captive_file_object->offset+=file_IoStatusBlock.Information; + *bytes_read_return=file_IoStatusBlock.Information; + return GNOME_VFS_OK; +} + + +GnomeVFSResult captive_file_seek + (CaptiveFileObject *captive_file_object,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset) +{ + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_file_seek(captive_file_object,whence,offset); + + g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + + switch (whence) { + case GNOME_VFS_SEEK_START: + captive_file_object->offset=offset; + break; + case GNOME_VFS_SEEK_CURRENT: + if (0 + || (offset>0 && (captive_file_object->offset+offset)offset) + || (offset<0 && (captive_file_object->offset+offset)>captive_file_object->offset)) + return GNOME_VFS_ERROR_BAD_PARAMETERS; + captive_file_object->offset+=offset; + break; + case GNOME_VFS_SEEK_END: + g_assert_not_reached(); /* NOT IMPLEMENTED YET */ + break; + default: + g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS); + } + + return GNOME_VFS_OK; +} + + +GnomeVFSResult captive_file_tell(CaptiveFileObject *captive_file_object,GnomeVFSFileOffset *offset_return) +{ + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_file_tell(captive_file_object,offset_return); + + g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(offset_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + + *offset_return=captive_file_object->offset; + return GNOME_VFS_OK; +} diff --git a/src/libcaptive/client/file_info.c b/src/libcaptive/client/file_info.c new file mode 100644 index 0000000..97a0703 --- /dev/null +++ b/src/libcaptive/client/file_info.c @@ -0,0 +1,198 @@ +/* $Id$ + * captive vfs 'file' 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-file_info.h" /* self */ +#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() */ + + +/* Use 'FileAllInformationStruct' identifier instead of the logical 'FileAllInformation' + * to prevent override of enum member 'FileAllInformation' + */ +static GnomeVFSResult FileAllInformationStruct_to_GnomeVFSFileInfo(GnomeVFSFileInfo *file_info, + FILE_ALL_INFORMATION *FileAllInformationStruct,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(FileAllInformationStruct!=NULL,GNOME_VFS_ERROR_GENERIC); + + g_return_val_if_fail(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC); + + file_info->valid_fields=0; + + FileName_UnicodeString.Length=FileAllInformationStruct->NameInformation.FileNameLength; + FileName_UnicodeString.MaximumLength=FileAllInformationStruct->NameInformation.FileNameLength + +sizeof(*FileAllInformationStruct->NameInformation.FileName); /* 0-terminator */ + g_assert((gpointer)(((char *)FileAllInformationStruct->NameInformation.FileName)+FileName_UnicodeString.Length) + <=(gpointer)(((char *)FileAllInformationStruct)+IoStatusBlock->Information)); + /* ensure we fit below '->IoStatusBlock->Information' at least without the 0-terminator */ + FileAllInformationStruct->NameInformation.FileName[FileAllInformationStruct->NameInformation.FileNameLength + /sizeof(*FileAllInformationStruct->NameInformation.FileName)]=0; /* 0-terminate it */ + FileName_UnicodeString.Buffer=FileAllInformationStruct->NameInformation.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 (FileAllInformationStruct->BasicInformation.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 (!(FileAllInformationStruct->BasicInformation.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=FileAllInformationStruct->StandardInformation.EndOfFile.QuadPart; + file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE; + + file_info->block_count=FileAllInformationStruct->StandardInformation.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 (FileAllInformationStruct->BasicInformation.LastAccessTime.QuadPart) { /* it may be 0 if not set */ + errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.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 (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart || FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart) { + errBOOLEAN=RtlTimeToSecondsSince1970( + /* take the more recent (==bigger) time: */ + (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart > FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart + ? &FileAllInformationStruct->BasicInformation.LastWriteTime : &FileAllInformationStruct->BasicInformation.ChangeTime), + &tmp_ULONG); + g_assert(errBOOLEAN==TRUE); + file_info->mtime=tmp_ULONG; + file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_MTIME; + } + + if (FileAllInformationStruct->BasicInformation.CreationTime.QuadPart) { /* it may be 0 if not set */ + errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.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; +} + + +GnomeVFSResult captive_file_info_get(const gchar *pathname,GnomeVFSFileInfo *file_info) +{ +NTSTATUS err; +IO_STATUS_BLOCK file_IoStatusBlock; +FILE_ALL_INFORMATION *FileAllInformationStruct; +GnomeVFSResult errvfsresult; +OBJECT_ATTRIBUTES file_ObjectAttributes; +HANDLE file_Handle; +char QueryFile_buf[sizeof(FILE_ALL_INFORMATION) + +0x1000 /* max 'FileName' length, 255 should be enough */ * sizeof(WCHAR /* *FILE_ALL_INFORMATION.NameInformation.FileName */ )]; + + if (CAPTIVE_IS_SANDBOX_PARENT()) + return captive_sandbox_parent_file_info_get(pathname,file_info); + + g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + + errvfsresult=captive_ObjectAttributes_init(pathname,&file_ObjectAttributes); + g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); + + /* open */ + err=IoCreateFile( + &file_Handle, /* FileHandle */ + FILE_READ_ATTRIBUTES, /* DesiredAccess */ + &file_ObjectAttributes, /* ObjectAttributes */ + &file_IoStatusBlock, /* IoStatusBlock */ + NULL, /* AllocationSize; ignored for open */ + FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */ + FILE_SHARE_WRITE, /* ShareAccess; 0 means exclusive */ + FILE_OPEN, /* 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_SYNCHRONOUS_IO_ALERT, /* CreateOptions */ + NULL, /* EaBuffer */ + 0, /* EaLength */ + CreateFileTypeNone, /* CreateFileType */ + NULL, /* ExtraCreateParameters */ + 0); /* Options */ + g_free(file_ObjectAttributes.ObjectName); /* left from captive_gnomevfs_uri_parent_init() */ + g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC); + if (err==STATUS_OBJECT_NAME_NOT_FOUND) + return GNOME_VFS_ERROR_NOT_FOUND; + g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); + g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC); + + /* query */ + FileAllInformationStruct=(void *)QueryFile_buf; + err=NtQueryInformationFile( + file_Handle, /* FileHandle */ + &file_IoStatusBlock, /* IoStatusBlock */ + (gpointer)QueryFile_buf, /* FileInformation */ + sizeof(QueryFile_buf) /* Length */ + -sizeof(*FileAllInformationStruct->NameInformation.FileName), /* reserve space for 0-terminator */ + FileAllInformation); /* FileInformationClass; =>FILE_ALL_INFORMATION */ + if (!NT_SUCCESS(err)) { + g_assert_not_reached(); + goto err_close; + } + + /* close */ + err=NtClose(file_Handle); + g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); + + /* process gathered info */ + errvfsresult=FileAllInformationStruct_to_GnomeVFSFileInfo(file_info,FileAllInformationStruct, + &file_IoStatusBlock); + g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult); + + return GNOME_VFS_OK; + +err_close: + err=NtClose(file_Handle); + g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC); +/* err: */ + g_return_val_if_reached(GNOME_VFS_ERROR_GENERIC); +} diff --git a/src/libcaptive/client/lib.c b/src/libcaptive/client/lib.c new file mode 100644 index 0000000..ed4ef28 --- /dev/null +++ b/src/libcaptive/client/lib.c @@ -0,0 +1,70 @@ +/* $Id$ + * captive vfs utility functions for 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 "lib.h" /* self */ +#include +#include +#include "captive/macros.h" +#include "reactos/ddk/rtl.h" /* for InitializeObjectAttributes() */ +#include "captive/unicode.h" +#include /* for gnome_vfs_unescape_string() */ +#include + + +/* function will leave g_malloc()ed 'ObjectAttributes->ObjectName'! + */ +GnomeVFSResult captive_ObjectAttributes_init(const gchar *pathname,OBJECT_ATTRIBUTES *ObjectAttributes) +{ +gchar *w32_path,*s,*d; + + g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + g_return_val_if_fail(ObjectAttributes!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS); + + /* Do not open "\Cdfs"(anything) as it is just the filesystem implementation. + * ntoskrnl/io/fs.c/IoMountVolume() will map + * FILE_DEVICE_CD_ROM -> FILE_DEVICE_CD_ROM_FILE_SYSTEM + * for us automatically when opening the device itself. + * If you put some trailing content (such as "\\.") there + * IoCreateFile()->ObCreateObject()->ObFindObject() + * will not leave 'ObCreateObject::RemainingPath' as NULL + * and later IopCreateFile() would not consider it FO_DIRECT_DEVICE_OPEN (e.g. w/o any direct mount!). + * On the other side it will somehow get managed automatically and it works even + * without the trailing "\\." for root directory open - don't ask me why. :-) + */ + w32_path=(gchar *)/* de-const it as we can modify it but we must not free() it */ + captive_printf_alloca("\\Device\\CdRom0\\%s",pathname); + /* translate '/' -> '\' */ + for (s=w32_path;(s=strchr(s,'/'));s++) + *s='\\'; + /* collapse multiple sequences of '\' as it is a no-no for W32 */ + for (s=d=w32_path;*s;s++) + if (d==w32_path || !(*s=='\\' && d[-1]=='\\')) + *d++=*s; + *d=0; + InitializeObjectAttributes( + ObjectAttributes, /* InitializedAttributes */ + captive_utf8_to_UnicodeString_malloc(w32_path), /* ObjectName */ + 0, /* Attributes; I hope no OBJ_KERNEL_HANDLE as we are 'system process' */ + NULL, /* RootDirectory */ + NULL); /* SecurityDescriptor; ignored */ + + return GNOME_VFS_OK; +} diff --git a/src/libcaptive/client/lib.h b/src/libcaptive/client/lib.h new file mode 100644 index 0000000..73aeba8 --- /dev/null +++ b/src/libcaptive/client/lib.h @@ -0,0 +1,36 @@ +/* $Id$ + * Include file for captive vfs utility functions for interface to reactos + * Copyright (C) 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 + */ + + +#ifndef _CAPTIVE_CLIENT_LIB_H +#define _CAPTIVE_CLIENT_LIB_H 1 + + +#include +#include "reactos/ddk/obtypes.h" /* for OBJECT_ATTRIBUTES */ +#include + + +G_BEGIN_DECLS + +GnomeVFSResult captive_ObjectAttributes_init(const gchar *pathname,OBJECT_ATTRIBUTES *ObjectAttributes); + +G_END_DECLS + + +#endif /* _CAPTIVE_CLIENT_LIB_H */ diff --git a/src/libcaptive/include/captive/Makefile.am b/src/libcaptive/include/captive/Makefile.am index 6648e51..87ecf8d 100644 --- a/src/libcaptive/include/captive/Makefile.am +++ b/src/libcaptive/include/captive/Makefile.am @@ -22,12 +22,16 @@ include $(top_srcdir)/src/libcaptive/Makefile-libcaptive.am pkginclude_HEADERS+= \ calltype_reactos.h \ client.h \ - file.h \ + client-directory.h \ + client-file.h \ + client-file_info.h \ ldr.h \ ldr_exports.h \ macros.h \ mm.h \ ps_reactos.h \ + rtl-file.h \ + sandbox.h \ signal.h \ storage.h \ unicode.h \ diff --git a/src/libcaptive/include/captive/client-directory.h b/src/libcaptive/include/captive/client-directory.h new file mode 100644 index 0000000..221b013 --- /dev/null +++ b/src/libcaptive/include/captive/client-directory.h @@ -0,0 +1,66 @@ +/* $Id$ + * Include file with client-application 'directory' access to libcaptive + * Copyright (C) 2002 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 + */ + + +#ifndef _CAPTIVE_CLIENT_DIRECTORY_H +#define _CAPTIVE_CLIENT_DIRECTORY_H 1 + + +#include +#include +#include "reactos/ntos/types.h" /* for HANDLE */ +#include "reactos/ddk/zwtypes.h" /* for FILE_ID_BOTH_DIR_INFORMATION */ +#include /* for GnomeVFSFileInfo */ + + +G_BEGIN_DECLS + +#define CAPTIVE_DIRECTORY_TYPE_OBJECT (captive_directory_object_get_type()) +#define CAPTIVE_DIRECTORY_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST((object),CAPTIVE_DIRECTORY_TYPE_OBJECT,CaptiveDirectoryObject)) +#define CAPTIVE_DIRECTORY_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),CAPTIVE_DIRECTORY_TYPE_OBJECT,CaptiveDirectoryObjectClass)) +#define CAPTIVE_DIRECTORY_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object),CAPTIVE_DIRECTORY_TYPE_OBJECT)) +#define CAPTIVE_DIRECTORY_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),CAPTIVE_DIRECTORY_TYPE_OBJECT)) +#define CAPTIVE_DIRECTORY_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),CAPTIVE_DIRECTORY_TYPE_OBJECT,CaptiveDirectoryObjectClass)) +typedef struct _CaptiveDirectoryObject CaptiveDirectoryObject; +typedef struct _CaptiveDirectoryObjectClass CaptiveDirectoryObjectClass; +struct _CaptiveDirectoryObject { + GObject parent_instance; + + /*< private >*/ + HANDLE dir_Handle; + gboolean read_first; + /* 'QueryDirectory_buf' for NtQueryDirectoryFile() must be persistent + * to keep the state if !read_first + */ + char QueryDirectory_buf[sizeof(FILE_ID_BOTH_DIR_INFORMATION) + +0x1000 /* max 'FileName' length, 255 should be enough */ * sizeof(WCHAR /* *FILE_ID_BOTH_DIR_INFORMATION.FileName */ )]; + }; +struct _CaptiveDirectoryObjectClass { + GObjectClass parent_class; + }; + +GType captive_directory_object_get_type(void); + +GnomeVFSResult captive_directory_new_open(CaptiveDirectoryObject **captive_directory_object_return,const gchar *pathname); +GnomeVFSResult captive_directory_read(CaptiveDirectoryObject *captive_directory_object,GnomeVFSFileInfo *file_info); + + +G_END_DECLS + + +#endif /* _CAPTIVE_CLIENT_DIRECTORY_H */ diff --git a/src/libcaptive/include/captive/client-file.h b/src/libcaptive/include/captive/client-file.h new file mode 100644 index 0000000..1125439 --- /dev/null +++ b/src/libcaptive/include/captive/client-file.h @@ -0,0 +1,65 @@ +/* $Id$ + * Include file with client-application 'file' access to libcaptive + * Copyright (C) 2002 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 + */ + + +#ifndef _CAPTIVE_CLIENT_FILE_H +#define _CAPTIVE_CLIENT_FILE_H 1 + + +#include +#include +#include "reactos/ntos/types.h" /* for HANDLE */ +#include "reactos/ddk/zwtypes.h" /* for FILE_ID_BOTH_DIR_INFORMATION */ +#include /* for GnomeVFSOpenMode */ + + +G_BEGIN_DECLS + +#define CAPTIVE_FILE_TYPE_OBJECT (captive_file_object_get_type()) +#define CAPTIVE_FILE_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST((object),CAPTIVE_FILE_TYPE_OBJECT,CaptiveFileObject)) +#define CAPTIVE_FILE_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),CAPTIVE_FILE_TYPE_OBJECT,CaptiveFileObjectClass)) +#define CAPTIVE_FILE_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object),CAPTIVE_FILE_TYPE_OBJECT)) +#define CAPTIVE_FILE_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),CAPTIVE_FILE_TYPE_OBJECT)) +#define CAPTIVE_FILE_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),CAPTIVE_FILE_TYPE_OBJECT,CaptiveFileObjectClass)) +typedef struct _CaptiveFileObject CaptiveFileObject; +typedef struct _CaptiveFileObjectClass CaptiveFileObjectClass; +struct _CaptiveFileObject { + GObject parent_instance; + + /*< private >*/ + HANDLE file_Handle; + GnomeVFSFileOffset offset; + }; +struct _CaptiveFileObjectClass { + GObjectClass parent_class; + }; + +GType captive_file_object_get_type(void); + +GnomeVFSResult captive_file_new_open + (CaptiveFileObject **captive_file_object_return,const gchar *pathname,GnomeVFSOpenMode mode); +GnomeVFSResult captive_file_read + (CaptiveFileObject *captive_file_object,gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return); +GnomeVFSResult captive_file_seek + (CaptiveFileObject *captive_file_object,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset); +GnomeVFSResult captive_file_tell(CaptiveFileObject *captive_file_object,GnomeVFSFileOffset *offset_return); + +G_END_DECLS + + +#endif /* _CAPTIVE_CLIENT_FILE_H */ diff --git a/src/libcaptive/include/captive/client-file_info.h b/src/libcaptive/include/captive/client-file_info.h new file mode 100644 index 0000000..56a4a71 --- /dev/null +++ b/src/libcaptive/include/captive/client-file_info.h @@ -0,0 +1,36 @@ +/* $Id$ + * Include file with client-application 'GnomeVFSFileInfo' access to libcaptive + * Copyright (C) 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 + */ + + +#ifndef _CAPTIVE_CLIENT_FILE_INFO_H +#define _CAPTIVE_CLIENT_FILE_INFO_H 1 + + +#include +#include /* for GnomeVFSResult */ +#include /* for GnomeVFSFileInfo */ + + +G_BEGIN_DECLS + +GnomeVFSResult captive_file_info_get(const gchar *pathname,GnomeVFSFileInfo *file_info); + +G_END_DECLS + + +#endif /* _CAPTIVE_CLIENT_FILE_INFO_H */