2 * captive vfs 'file' interface to reactos
3 * Copyright (C) 2002-2003 Jan Kratochvil <project-captive@jankratochvil.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; exactly version 2 of June 1991 is required
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "captive/client-file_info.h" /* self */
24 #include <glib/gmessages.h>
25 #include "captive/unicode.h"
26 #include "reactos/ntos/types.h" /* for HANDLE */
27 #include "reactos/ddk/iotypes.h" /* for IO_STATUS_BLOCK */
28 #include "reactos/ddk/iofuncs.h" /* for IoCreateFile() */
29 #include "captive/sandbox.h"
33 /* Use 'FileAllInformationStruct' identifier instead of the logical 'FileAllInformation'
34 * to prevent override of enum member 'FileAllInformation'
36 static GnomeVFSResult FileAllInformationStruct_to_GnomeVFSFileInfo(GnomeVFSFileInfo *file_info,
37 FILE_ALL_INFORMATION *FileAllInformationStruct,IO_STATUS_BLOCK *IoStatusBlock)
39 UNICODE_STRING FileName_UnicodeString;
43 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_GENERIC);
44 g_return_val_if_fail(FileAllInformationStruct!=NULL,GNOME_VFS_ERROR_GENERIC);
46 g_return_val_if_fail(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC);
48 file_info->valid_fields=0;
50 FileName_UnicodeString.Length=FileAllInformationStruct->NameInformation.FileNameLength;
51 FileName_UnicodeString.MaximumLength=FileAllInformationStruct->NameInformation.FileNameLength
52 +sizeof(*FileAllInformationStruct->NameInformation.FileName); /* 0-terminator */
53 g_assert((gpointer)(((char *)FileAllInformationStruct->NameInformation.FileName)+FileName_UnicodeString.Length)
54 <=(gpointer)(((char *)FileAllInformationStruct)+IoStatusBlock->Information));
55 /* ensure we fit below '->IoStatusBlock->Information' at least without the 0-terminator */
56 FileAllInformationStruct->NameInformation.FileName[FileAllInformationStruct->NameInformation.FileNameLength
57 /sizeof(*FileAllInformationStruct->NameInformation.FileName)]=0; /* 0-terminate it */
58 FileName_UnicodeString.Buffer=FileAllInformationStruct->NameInformation.FileName;
59 file_info->name=captive_UnicodeString_to_utf8_malloc(&FileName_UnicodeString);
60 /* '->name' assumed for 'file_info->valid_fields' */
62 /* FIXME: What is 'FILE_ATTRIBUTE_NORMAL'? */
63 switch (FileAllInformationStruct->BasicInformation.FileAttributes & (0
64 | FILE_ATTRIBUTE_DIRECTORY
65 | FILE_ATTRIBUTE_DEVICE)) {
66 case 0: file_info->type=GNOME_VFS_FILE_TYPE_REGULAR; break;
67 case FILE_ATTRIBUTE_DIRECTORY: file_info->type=GNOME_VFS_FILE_TYPE_DIRECTORY; break;
68 case FILE_ATTRIBUTE_DEVICE: file_info->type=GNOME_VFS_FILE_TYPE_SOCKET;
69 /* or GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE or GNOME_VFS_FILE_TYPE_BLOCK_DEVICE ? */
71 default: file_info->type=GNOME_VFS_FILE_TYPE_UNKNOWN; break;
73 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
75 /* we use 0600 for r/w files, 0400 for FILE_ATTRIBUTE_READONLY */
76 file_info->permissions=GNOME_VFS_PERM_USER_READ;
77 if (file_info->type==GNOME_VFS_FILE_TYPE_DIRECTORY)
78 file_info->permissions|=GNOME_VFS_PERM_USER_EXEC;
79 if (!(FileAllInformationStruct->BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY))
80 file_info->permissions|=GNOME_VFS_PERM_USER_WRITE;
81 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
83 file_info->size=FileAllInformationStruct->StandardInformation.EndOfFile.QuadPart;
84 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE;
86 file_info->block_count=FileAllInformationStruct->StandardInformation.AllocationSize.QuadPart/512;
87 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT;
89 file_info->flags=GNOME_VFS_FILE_FLAGS_LOCAL;
90 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_FLAGS;
92 if (FileAllInformationStruct->BasicInformation.LastAccessTime.QuadPart) { /* it may be 0 if not set */
93 errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.LastAccessTime,&tmp_ULONG);
94 g_assert(errBOOLEAN==TRUE);
95 file_info->atime=tmp_ULONG;
96 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_ATIME;
99 /* it may be 0 if not set */
100 if (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart || FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart) {
101 errBOOLEAN=RtlTimeToSecondsSince1970(
102 /* take the more recent (==bigger) time: */
103 (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart > FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart
104 ? &FileAllInformationStruct->BasicInformation.LastWriteTime : &FileAllInformationStruct->BasicInformation.ChangeTime),
106 g_assert(errBOOLEAN==TRUE);
107 file_info->mtime=tmp_ULONG;
108 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_MTIME;
111 if (FileAllInformationStruct->BasicInformation.CreationTime.QuadPart) { /* it may be 0 if not set */
112 errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.CreationTime,&tmp_ULONG);
113 g_assert(errBOOLEAN==TRUE);
114 file_info->ctime=tmp_ULONG;
115 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_CTIME;
122 GnomeVFSResult captive_file_info_get(const gchar *pathname,GnomeVFSFileInfo *file_info)
125 IO_STATUS_BLOCK file_IoStatusBlock;
126 FILE_ALL_INFORMATION *FileAllInformationStruct;
127 GnomeVFSResult errvfsresult;
128 OBJECT_ATTRIBUTES file_ObjectAttributes;
130 char QueryFile_buf[sizeof(FILE_ALL_INFORMATION)
131 +0x1000 /* max 'FileName' length, 255 should be enough */ * sizeof(WCHAR /* *FILE_ALL_INFORMATION.NameInformation.FileName */ )];
133 if (CAPTIVE_IS_SANDBOX_PARENT())
134 return captive_sandbox_parent_file_info_get(pathname,file_info);
136 g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
137 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
139 errvfsresult=captive_ObjectAttributes_init(pathname,&file_ObjectAttributes);
140 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
144 &file_Handle, /* FileHandle */
145 FILE_READ_ATTRIBUTES, /* DesiredAccess */
146 &file_ObjectAttributes, /* ObjectAttributes */
147 &file_IoStatusBlock, /* IoStatusBlock */
148 NULL, /* AllocationSize; ignored for open */
149 FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */
150 FILE_SHARE_WRITE, /* ShareAccess; 0 means exclusive */
151 FILE_OPEN, /* CreateDisposition */
152 /* FILE_SYNCHRONOUS_IO_{,NON}ALERT: We need to allow W32 filesystem
153 * any waits to not to let it return STATUS_CANT_WAIT us.
154 * Alertability should have only effect on asynchronous events
155 * from KeWaitForSingleObject() by setting/clearing its parameter 'Alertable'.
157 FILE_SYNCHRONOUS_IO_ALERT, /* CreateOptions */
160 CreateFileTypeNone, /* CreateFileType */
161 NULL, /* ExtraCreateParameters */
163 g_free(file_ObjectAttributes.ObjectName); /* left from captive_gnomevfs_uri_parent_init() */
164 g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
165 if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err)))
167 g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
168 g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC);
171 FileAllInformationStruct=(void *)QueryFile_buf;
172 err=NtQueryInformationFile(
173 file_Handle, /* FileHandle */
174 &file_IoStatusBlock, /* IoStatusBlock */
175 (gpointer)QueryFile_buf, /* FileInformation */
176 sizeof(QueryFile_buf) /* Length */
177 -sizeof(*FileAllInformationStruct->NameInformation.FileName), /* reserve space for 0-terminator */
178 FileAllInformation); /* FileInformationClass; =>FILE_ALL_INFORMATION */
179 if (!NT_SUCCESS(err)) {
180 g_assert_not_reached();
185 err=NtClose(file_Handle);
186 g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
188 /* process gathered info */
189 errvfsresult=FileAllInformationStruct_to_GnomeVFSFileInfo(file_info,FileAllInformationStruct,
190 &file_IoStatusBlock);
191 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
196 err=NtClose(file_Handle);
197 g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
199 g_return_val_if_reached(GNOME_VFS_ERROR_GENERIC);