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() */
31 /* Use 'FileAllInformationStruct' identifier instead of the logical 'FileAllInformation'
32 * to prevent override of enum member 'FileAllInformation'
34 static GnomeVFSResult FileAllInformationStruct_to_GnomeVFSFileInfo(GnomeVFSFileInfo *file_info,
35 FILE_ALL_INFORMATION *FileAllInformationStruct,IO_STATUS_BLOCK *IoStatusBlock)
37 UNICODE_STRING FileName_UnicodeString;
41 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_GENERIC);
42 g_return_val_if_fail(FileAllInformationStruct!=NULL,GNOME_VFS_ERROR_GENERIC);
44 g_return_val_if_fail(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC);
46 file_info->valid_fields=0;
48 FileName_UnicodeString.Length=FileAllInformationStruct->NameInformation.FileNameLength;
49 FileName_UnicodeString.MaximumLength=FileAllInformationStruct->NameInformation.FileNameLength
50 +sizeof(*FileAllInformationStruct->NameInformation.FileName); /* 0-terminator */
51 g_assert((gpointer)(((char *)FileAllInformationStruct->NameInformation.FileName)+FileName_UnicodeString.Length)
52 <=(gpointer)(((char *)FileAllInformationStruct)+IoStatusBlock->Information));
53 /* ensure we fit below '->IoStatusBlock->Information' at least without the 0-terminator */
54 FileAllInformationStruct->NameInformation.FileName[FileAllInformationStruct->NameInformation.FileNameLength
55 /sizeof(*FileAllInformationStruct->NameInformation.FileName)]=0; /* 0-terminate it */
56 FileName_UnicodeString.Buffer=FileAllInformationStruct->NameInformation.FileName;
57 file_info->name=captive_UnicodeString_to_utf8_malloc(&FileName_UnicodeString);
58 /* '->name' assumed for 'file_info->valid_fields' */
60 /* FIXME: What is 'FILE_ATTRIBUTE_NORMAL'? */
61 switch (FileAllInformationStruct->BasicInformation.FileAttributes & (0
62 | FILE_ATTRIBUTE_DIRECTORY
63 | FILE_ATTRIBUTE_DEVICE)) {
64 case 0: file_info->type=GNOME_VFS_FILE_TYPE_REGULAR; break;
65 case FILE_ATTRIBUTE_DIRECTORY: file_info->type=GNOME_VFS_FILE_TYPE_DIRECTORY; break;
66 case FILE_ATTRIBUTE_DEVICE: file_info->type=GNOME_VFS_FILE_TYPE_SOCKET;
67 /* or GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE or GNOME_VFS_FILE_TYPE_BLOCK_DEVICE ? */
69 default: file_info->type=GNOME_VFS_FILE_TYPE_UNKNOWN; break;
71 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
73 /* we use 0600 for r/w files, 0400 for FILE_ATTRIBUTE_READONLY */
74 file_info->permissions=GNOME_VFS_PERM_USER_READ;
75 if (file_info->type==GNOME_VFS_FILE_TYPE_DIRECTORY)
76 file_info->permissions|=GNOME_VFS_PERM_USER_EXEC;
77 if (!(FileAllInformationStruct->BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY))
78 file_info->permissions=GNOME_VFS_PERM_USER_WRITE;
79 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
81 file_info->size=FileAllInformationStruct->StandardInformation.EndOfFile.QuadPart;
82 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE;
84 file_info->block_count=FileAllInformationStruct->StandardInformation.AllocationSize.QuadPart/512;
85 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT;
87 file_info->flags=GNOME_VFS_FILE_FLAGS_LOCAL;
88 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_FLAGS;
90 if (FileAllInformationStruct->BasicInformation.LastAccessTime.QuadPart) { /* it may be 0 if not set */
91 errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.LastAccessTime,&tmp_ULONG);
92 g_assert(errBOOLEAN==TRUE);
93 file_info->atime=tmp_ULONG;
94 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_ATIME;
97 /* it may be 0 if not set */
98 if (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart || FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart) {
99 errBOOLEAN=RtlTimeToSecondsSince1970(
100 /* take the more recent (==bigger) time: */
101 (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart > FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart
102 ? &FileAllInformationStruct->BasicInformation.LastWriteTime : &FileAllInformationStruct->BasicInformation.ChangeTime),
104 g_assert(errBOOLEAN==TRUE);
105 file_info->mtime=tmp_ULONG;
106 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_MTIME;
109 if (FileAllInformationStruct->BasicInformation.CreationTime.QuadPart) { /* it may be 0 if not set */
110 errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.CreationTime,&tmp_ULONG);
111 g_assert(errBOOLEAN==TRUE);
112 file_info->ctime=tmp_ULONG;
113 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_CTIME;
120 GnomeVFSResult captive_file_info_get(const gchar *pathname,GnomeVFSFileInfo *file_info)
123 IO_STATUS_BLOCK file_IoStatusBlock;
124 FILE_ALL_INFORMATION *FileAllInformationStruct;
125 GnomeVFSResult errvfsresult;
126 OBJECT_ATTRIBUTES file_ObjectAttributes;
128 char QueryFile_buf[sizeof(FILE_ALL_INFORMATION)
129 +0x1000 /* max 'FileName' length, 255 should be enough */ * sizeof(WCHAR /* *FILE_ALL_INFORMATION.NameInformation.FileName */ )];
131 if (CAPTIVE_IS_SANDBOX_PARENT())
132 return captive_sandbox_parent_file_info_get(pathname,file_info);
134 g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
135 g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
137 errvfsresult=captive_ObjectAttributes_init(pathname,&file_ObjectAttributes);
138 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
142 &file_Handle, /* FileHandle */
143 FILE_READ_ATTRIBUTES, /* DesiredAccess */
144 &file_ObjectAttributes, /* ObjectAttributes */
145 &file_IoStatusBlock, /* IoStatusBlock */
146 NULL, /* AllocationSize; ignored for open */
147 FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */
148 FILE_SHARE_WRITE, /* ShareAccess; 0 means exclusive */
149 FILE_OPEN, /* CreateDisposition */
150 /* FILE_SYNCHRONOUS_IO_{,NON}ALERT: We need to allow W32 filesystem
151 * any waits to not to let it return STATUS_CANT_WAIT us.
152 * Alertability should have only effect on asynchronous events
153 * from KeWaitForSingleObject() by setting/clearing its parameter 'Alertable'.
155 FILE_SYNCHRONOUS_IO_ALERT, /* CreateOptions */
158 CreateFileTypeNone, /* CreateFileType */
159 NULL, /* ExtraCreateParameters */
161 g_free(file_ObjectAttributes.ObjectName); /* left from captive_gnomevfs_uri_parent_init() */
162 g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
163 if (err==STATUS_OBJECT_NAME_NOT_FOUND)
164 return GNOME_VFS_ERROR_NOT_FOUND;
165 g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
166 g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC);
169 FileAllInformationStruct=(void *)QueryFile_buf;
170 err=NtQueryInformationFile(
171 file_Handle, /* FileHandle */
172 &file_IoStatusBlock, /* IoStatusBlock */
173 (gpointer)QueryFile_buf, /* FileInformation */
174 sizeof(QueryFile_buf) /* Length */
175 -sizeof(*FileAllInformationStruct->NameInformation.FileName), /* reserve space for 0-terminator */
176 FileAllInformation); /* FileInformationClass; =>FILE_ALL_INFORMATION */
177 if (!NT_SUCCESS(err)) {
178 g_assert_not_reached();
183 err=NtClose(file_Handle);
184 g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
186 /* process gathered info */
187 errvfsresult=FileAllInformationStruct_to_GnomeVFSFileInfo(file_info,FileAllInformationStruct,
188 &file_IoStatusBlock);
189 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
194 err=NtClose(file_Handle);
195 g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
197 g_return_val_if_reached(GNOME_VFS_ERROR_GENERIC);