+support GnomeVFSMethod->get_file_info_from_handle()
[captive.git] / src / libcaptive / client / file.c
1 /* $Id$
2  * captive vfs 'file' interface to reactos
3  * Copyright (C) 2002-2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
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
8  * 
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.
13  * 
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
17  */
18
19
20 #include "config.h"
21
22 #include "captive/client-file.h"        /* self */
23 #include "lib.h"
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"
30 #include "result.h"
31
32
33 static gpointer captive_file_object_parent_class=NULL;
34
35
36 static GnomeVFSResult captive_file_close(CaptiveFileObject *captive_file_object);
37
38 static void captive_file_object_finalize(CaptiveFileObject *captive_file_object)
39 {
40 GnomeVFSResult errvfsresult;
41
42         g_return_if_fail(captive_file_object!=NULL);
43
44         errvfsresult=captive_file_close(captive_file_object);
45         g_assert(errvfsresult==GNOME_VFS_OK);
46
47         G_OBJECT_CLASS(captive_file_object_parent_class)->finalize((GObject *)captive_file_object);
48 }
49
50
51 static void captive_file_object_class_init(CaptiveFileObjectClass *class)
52 {
53 GObjectClass *gobject_class=G_OBJECT_CLASS(class);
54
55         captive_file_object_parent_class=g_type_class_ref(G_TYPE_OBJECT);
56         gobject_class->finalize=(void (*)(GObject *object))captive_file_object_finalize;
57 }
58
59
60 static void captive_file_object_init(CaptiveFileObject *captive_file_object)
61 {
62         captive_file_object->file_Handle=NULL;
63 }
64
65
66 GType captive_file_object_get_type(void)
67 {
68 static GType captive_file_object_type=0;
69
70         if (!captive_file_object_type) {
71 static const GTypeInfo captive_file_object_info={
72                                 sizeof(CaptiveFileObjectClass),
73                                 NULL,   /* base_init */
74                                 NULL,   /* base_finalize */
75                                 (GClassInitFunc)captive_file_object_class_init,
76                                 NULL,   /* class_finalize */
77                                 NULL,   /* class_data */
78                                 sizeof(CaptiveFileObject),
79                                 5,      /* n_preallocs */
80                                 (GInstanceInitFunc)captive_file_object_init,
81                                 };
82
83                 captive_file_object_type=g_type_register_static(G_TYPE_OBJECT,
84                                 "CaptiveFileObject",&captive_file_object_info,0);
85                 }
86
87         return captive_file_object_type;
88 }
89
90
91 static GnomeVFSResult captive_file_new_internal(CaptiveFileObject **captive_file_object_return,
92                 const gchar *pathname,GnomeVFSOpenMode mode,gboolean create,gboolean create_exclusive,guint create_perm)
93 {
94 IO_STATUS_BLOCK file_IoStatusBlock;
95 GnomeVFSResult errvfsresult;
96 OBJECT_ATTRIBUTES file_ObjectAttributes;
97 HANDLE file_Handle;
98 CaptiveFileObject *captive_file_object;
99 NTSTATUS err;
100
101         if (CAPTIVE_IS_SANDBOX_PARENT())
102                 return captive_sandbox_parent_file_new_open(captive_file_object_return,pathname,mode);
103
104         g_return_val_if_fail(captive_file_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
105         g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
106
107         *captive_file_object_return=NULL;
108
109         errvfsresult=captive_ObjectAttributes_init(pathname,&file_ObjectAttributes);
110         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
111         
112         /* open */
113         err=IoCreateFile(
114                         &file_Handle,   /* FileHandle */
115                         0
116                                         |(!(mode&GNOME_VFS_OPEN_READ ) ? 0 : FILE_READ_DATA)
117                                         |(!(mode&GNOME_VFS_OPEN_WRITE) ? 0 : FILE_WRITE_DATA | FILE_APPEND_DATA)
118                                         |(  mode!=0                    ? 0 : FILE_READ_ATTRIBUTES)
119                                         ,       /* DesiredAccess */
120                         &file_ObjectAttributes, /* ObjectAttributes */
121                         &file_IoStatusBlock,    /* IoStatusBlock */
122                         NULL,   /* AllocationSize; ignored for open */
123                         (!create || create_perm&0200 ? FILE_ATTRIBUTE_NORMAL: FILE_ATTRIBUTE_READONLY), /* FileAttributes; ignored for open */
124                         (!create || !create_exclusive ? FILE_SHARE_DELETE : 0), /* ShareAccess; 0 means exclusive */
125                         (!create ? FILE_OPEN : FILE_CREATE),    /* CreateDisposition */
126                         /* FILE_SYNCHRONOUS_IO_{,NON}ALERT: We need to allow W32 filesystem
127                                  * any waits to not to let it return STATUS_CANT_WAIT us.
128                                  * Alertability should have only effect on asynchronous events
129                                  * from KeWaitForSingleObject() by setting/clearing its parameter 'Alertable'.
130                                  */
131                         FILE_SYNCHRONOUS_IO_ALERT,      /* CreateOptions */
132                         NULL,   /* EaBuffer */
133                         0,      /* EaLength */
134                         CreateFileTypeNone,     /* CreateFileType */
135                         NULL,   /* ExtraCreateParameters */
136                         0);     /* Options */
137         g_free(file_ObjectAttributes.ObjectName);       /* left from captive_file_uri_parent_init() */
138         g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
139         if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err)))
140                 return errvfsresult;
141         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
142         g_return_val_if_fail(file_IoStatusBlock.Information
143                                         ==(!create ? FILE_OPENED : FILE_CREATED),
144                         GNOME_VFS_ERROR_GENERIC);
145
146         captive_file_object=g_object_new(
147                         CAPTIVE_FILE_TYPE_OBJECT,       /* object_type */
148                         NULL);  /* first_property_name; FIXME: support properties */
149
150         captive_file_object->file_Handle=file_Handle;
151         captive_file_object->offset=0;
152
153         *captive_file_object_return=captive_file_object;
154         return GNOME_VFS_OK;
155 }
156
157
158 GnomeVFSResult captive_file_new_open
159                 (CaptiveFileObject **captive_file_object_return,const gchar *pathname,GnomeVFSOpenMode mode)
160 {
161         g_return_val_if_fail(captive_file_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
162         g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
163
164         return captive_file_new_internal(captive_file_object_return,pathname,mode,
165                         FALSE,  /* create */
166                         FALSE,  /* create_exclusive; ignored */
167                         0);     /* create_perm; ignored */
168 }
169
170
171 GnomeVFSResult captive_file_new_create
172                 (CaptiveFileObject **captive_file_object_return,const gchar *pathname,GnomeVFSOpenMode mode,gboolean exclusive,guint perm)
173 {
174         g_return_val_if_fail(captive_file_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
175         g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
176
177         return captive_file_new_internal(captive_file_object_return,pathname,mode,
178                         TRUE,   /* create */
179                         exclusive,      /* create_exclusive */
180                         perm);  /* create_perm */
181 }
182
183
184 static GnomeVFSResult captive_file_close(CaptiveFileObject *captive_file_object)
185 {
186 NTSTATUS err;
187 HANDLE file_Handle;
188
189         if (CAPTIVE_IS_SANDBOX_PARENT())
190                 return captive_sandbox_parent_file_close(captive_file_object);
191
192         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
193         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);    /* already closed */
194
195         file_Handle=captive_file_object->file_Handle;
196         captive_file_object->file_Handle=NULL;
197         err=NtClose(file_Handle);
198         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
199
200         return GNOME_VFS_OK;
201 }
202
203
204 GnomeVFSResult captive_file_read(CaptiveFileObject *captive_file_object,
205                 gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return)
206 {
207 NTSTATUS err;
208 IO_STATUS_BLOCK file_IoStatusBlock;
209 LARGE_INTEGER file_offset;
210 GnomeVFSResult errvfsresult;
211
212         if (CAPTIVE_IS_SANDBOX_PARENT())
213                 return captive_sandbox_parent_file_read(captive_file_object,buffer,num_bytes,bytes_read_return);
214
215         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
216         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
217         g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
218         g_return_val_if_fail(bytes_read_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
219         g_return_val_if_fail(num_bytes==(ULONG)num_bytes,GNOME_VFS_ERROR_BAD_PARAMETERS);
220
221         file_offset.QuadPart=captive_file_object->offset;
222         err=NtReadFile(
223                         captive_file_object->file_Handle,       /* FileHandle */
224                         NULL,   /* EventHandle; completion signalling; optional */
225                         NULL,   /* ApcRoutine; optional */
226                         NULL,   /* ApcContext; optional */
227                         &file_IoStatusBlock,    /* IoStatusBlock */
228                         buffer, /* Buffer */
229                         num_bytes,      /* Length */
230                         &file_offset,   /* ByteOffset */
231                         NULL);  /* Key; NULL means no file locking key */
232         if (err==STATUS_END_OF_FILE) {
233                 g_return_val_if_fail(file_IoStatusBlock.Status==STATUS_END_OF_FILE,GNOME_VFS_ERROR_GENERIC);
234                 g_return_val_if_fail(file_IoStatusBlock.Information==0,GNOME_VFS_ERROR_GENERIC);
235                 *bytes_read_return=0;
236                 return GNOME_VFS_ERROR_EOF;
237                 }
238         if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err)))
239                 return errvfsresult;
240         g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
241         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
242         g_return_val_if_fail(file_IoStatusBlock.Information<=num_bytes,GNOME_VFS_ERROR_GENERIC);
243
244         captive_file_object->offset+=file_IoStatusBlock.Information;
245         *bytes_read_return=file_IoStatusBlock.Information;
246         return GNOME_VFS_OK;
247 }
248
249
250 GnomeVFSResult captive_file_write(CaptiveFileObject *captive_file_object,
251                 gconstpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_written_return)
252 {
253 NTSTATUS err;
254 IO_STATUS_BLOCK file_IoStatusBlock;
255 LARGE_INTEGER file_offset;
256
257         if (CAPTIVE_IS_SANDBOX_PARENT())
258                 return captive_sandbox_parent_file_write(captive_file_object,buffer,num_bytes,bytes_written_return);
259
260         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
261         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
262         g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
263         g_return_val_if_fail(bytes_written_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
264         g_return_val_if_fail(num_bytes==(ULONG)num_bytes,GNOME_VFS_ERROR_BAD_PARAMETERS);
265
266         file_offset.QuadPart=captive_file_object->offset;
267         err=NtWriteFile(
268                         captive_file_object->file_Handle,       /* FileHandle */
269                         NULL,   /* Event; completion signalling; optional */
270                         NULL,   /* ApcRoutine; optional */
271                         NULL,   /* ApcContext; optional */
272                         &file_IoStatusBlock,    /* IoStatusBlock */
273                         (gpointer /* de-const */ )buffer,       /* Buffer */
274                         num_bytes,      /* Length */
275                         &file_offset,   /* ByteOffset */
276                         NULL);  /* Key; NULL means no file locking key */
277         g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
278         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
279         g_return_val_if_fail(file_IoStatusBlock.Information==num_bytes,GNOME_VFS_ERROR_GENERIC);
280
281         captive_file_object->offset+=file_IoStatusBlock.Information;
282         *bytes_written_return=file_IoStatusBlock.Information;
283         return GNOME_VFS_OK;
284 }
285
286
287 GnomeVFSResult captive_file_seek
288                 (CaptiveFileObject *captive_file_object,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset)
289 {
290         if (CAPTIVE_IS_SANDBOX_PARENT())
291                 return captive_sandbox_parent_file_seek(captive_file_object,whence,offset);
292
293         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
294         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
295
296         switch (whence) {
297                 case GNOME_VFS_SEEK_START:
298                         captive_file_object->offset=offset;
299                         break;
300                 case GNOME_VFS_SEEK_CURRENT:
301                         if (0
302                                         || (offset>0 && (captive_file_object->offset+offset)<captive_file_object->offset)
303                                         || (offset<0 && (captive_file_object->offset+offset)>captive_file_object->offset))
304                                 return GNOME_VFS_ERROR_BAD_PARAMETERS;
305                         captive_file_object->offset+=offset;
306                         break;
307                 case GNOME_VFS_SEEK_END:
308                         g_assert_not_reached(); /* NOT IMPLEMENTED YET */
309                         break;
310                 default:
311                         g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS);
312                 }
313
314         return GNOME_VFS_OK;
315 }
316
317
318 GnomeVFSResult captive_file_tell(CaptiveFileObject *captive_file_object,GnomeVFSFileOffset *offset_return)
319 {
320         if (CAPTIVE_IS_SANDBOX_PARENT())
321                 return captive_sandbox_parent_file_tell(captive_file_object,offset_return);
322
323         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
324         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
325         g_return_val_if_fail(offset_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
326
327         *offset_return=captive_file_object->offset;
328         return GNOME_VFS_OK;
329 }
330
331
332 GnomeVFSResult captive_file_remove(CaptiveFileObject *captive_file_object)
333 {
334 NTSTATUS err;
335 FILE_DISPOSITION_INFORMATION FileDispositionInformation_struct;
336 IO_STATUS_BLOCK file_IoStatusBlock;
337 GnomeVFSResult errvfsresult;
338
339         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
340         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
341
342         FileDispositionInformation_struct.DoDeleteFile=TRUE;
343
344         err=NtSetInformationFile(
345                         captive_file_object->file_Handle,       /* FileHandle */
346                         &file_IoStatusBlock,    /* IoStatusBlock */
347                         &FileDispositionInformation_struct,     /* FileInformation */
348                         sizeof(FileDispositionInformation_struct),      /* Length */
349                         FileDispositionInformation);    /* FileInformationClass */
350         if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err)))
351                 return errvfsresult;
352         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
353
354         return GNOME_VFS_OK;
355 }
356
357
358 /* Use 'FileAllInformationStruct' identifier instead of the logical 'FileAllInformation'
359  * to prevent override of enum member 'FileAllInformation'
360  */
361 static GnomeVFSResult FileAllInformationStruct_to_GnomeVFSFileInfo(GnomeVFSFileInfo *file_info,
362                 FILE_ALL_INFORMATION *FileAllInformationStruct,IO_STATUS_BLOCK *IoStatusBlock)
363 {
364 UNICODE_STRING FileName_UnicodeString;
365 BOOLEAN errBOOLEAN;
366 ULONG tmp_ULONG;
367
368         g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_GENERIC);
369         g_return_val_if_fail(FileAllInformationStruct!=NULL,GNOME_VFS_ERROR_GENERIC);
370
371         g_return_val_if_fail(NT_SUCCESS(IoStatusBlock->Status),GNOME_VFS_ERROR_GENERIC);
372
373         file_info->valid_fields=0;
374
375         FileName_UnicodeString.Length=FileAllInformationStruct->NameInformation.FileNameLength;
376         FileName_UnicodeString.MaximumLength=FileAllInformationStruct->NameInformation.FileNameLength
377                         +sizeof(*FileAllInformationStruct->NameInformation.FileName);   /* 0-terminator */
378         g_assert((gpointer)(((char *)FileAllInformationStruct->NameInformation.FileName)+FileName_UnicodeString.Length)
379                         <=(gpointer)(((char *)FileAllInformationStruct)+IoStatusBlock->Information));
380                                         /* ensure we fit below '->IoStatusBlock->Information' at least without the 0-terminator */
381         FileAllInformationStruct->NameInformation.FileName[FileAllInformationStruct->NameInformation.FileNameLength
382                         /sizeof(*FileAllInformationStruct->NameInformation.FileName)]=0;        /* 0-terminate it */
383         FileName_UnicodeString.Buffer=FileAllInformationStruct->NameInformation.FileName;
384         file_info->name=captive_UnicodeString_to_utf8_malloc(&FileName_UnicodeString);
385         /* '->name' assumed for 'file_info->valid_fields' */
386
387         /* FIXME: What is 'FILE_ATTRIBUTE_NORMAL'? */
388         switch (FileAllInformationStruct->BasicInformation.FileAttributes & (0
389                         | FILE_ATTRIBUTE_DIRECTORY
390                         | FILE_ATTRIBUTE_DEVICE)) {
391                 case 0:                        file_info->type=GNOME_VFS_FILE_TYPE_REGULAR;   break;
392                 case FILE_ATTRIBUTE_DIRECTORY: file_info->type=GNOME_VFS_FILE_TYPE_DIRECTORY; break;
393                 case FILE_ATTRIBUTE_DEVICE:    file_info->type=GNOME_VFS_FILE_TYPE_SOCKET;
394                         /* or GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE or GNOME_VFS_FILE_TYPE_BLOCK_DEVICE ? */
395                         break;
396                 default:                       file_info->type=GNOME_VFS_FILE_TYPE_UNKNOWN;   break;
397                 }
398         file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_TYPE;
399
400         /* we use 0600 for r/w files, 0400 for FILE_ATTRIBUTE_READONLY */
401         file_info->permissions=GNOME_VFS_PERM_USER_READ;
402         if (file_info->type==GNOME_VFS_FILE_TYPE_DIRECTORY)
403                 file_info->permissions|=GNOME_VFS_PERM_USER_EXEC;
404         if (!(FileAllInformationStruct->BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY))
405                 file_info->permissions|=GNOME_VFS_PERM_USER_WRITE;
406         file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
407
408         file_info->size=FileAllInformationStruct->StandardInformation.EndOfFile.QuadPart;
409         file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_SIZE;
410
411         file_info->block_count=FileAllInformationStruct->StandardInformation.AllocationSize.QuadPart/512;
412         file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT;
413
414         file_info->flags=GNOME_VFS_FILE_FLAGS_LOCAL;
415         file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_FLAGS;
416
417         if (FileAllInformationStruct->BasicInformation.LastAccessTime.QuadPart) {       /* it may be 0 if not set */
418                 errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.LastAccessTime,&tmp_ULONG);
419                 g_assert(errBOOLEAN==TRUE);
420                 file_info->atime=tmp_ULONG;
421                 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_ATIME;
422                 }
423
424         /* it may be 0 if not set */
425         if (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart || FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart) {
426                 errBOOLEAN=RtlTimeToSecondsSince1970(
427                                 /* take the more recent (==bigger) time: */
428                                 (FileAllInformationStruct->BasicInformation.LastWriteTime.QuadPart > FileAllInformationStruct->BasicInformation.ChangeTime.QuadPart
429                                                 ? &FileAllInformationStruct->BasicInformation.LastWriteTime : &FileAllInformationStruct->BasicInformation.ChangeTime),
430                                 &tmp_ULONG);
431                 g_assert(errBOOLEAN==TRUE);
432                 file_info->mtime=tmp_ULONG;
433                 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_MTIME;
434                 }
435
436         if (FileAllInformationStruct->BasicInformation.CreationTime.QuadPart) { /* it may be 0 if not set */
437                 errBOOLEAN=RtlTimeToSecondsSince1970(&FileAllInformationStruct->BasicInformation.CreationTime,&tmp_ULONG);
438                 g_assert(errBOOLEAN==TRUE);
439                 file_info->ctime=tmp_ULONG;
440                 file_info->valid_fields|=GNOME_VFS_FILE_INFO_FIELDS_CTIME;
441                 }
442
443         return GNOME_VFS_OK;
444 }
445
446
447 GnomeVFSResult captive_file_file_info_get(CaptiveFileObject *captive_file_object,GnomeVFSFileInfo *file_info)
448 {
449 NTSTATUS err;
450 IO_STATUS_BLOCK file_IoStatusBlock;
451 FILE_ALL_INFORMATION *FileAllInformationStruct;
452 GnomeVFSResult errvfsresult;
453 char QueryFile_buf[sizeof(FILE_ALL_INFORMATION)
454                 +0x1000 /* max 'FileName' length, 255 should be enough */ * sizeof(WCHAR /* *FILE_ALL_INFORMATION.NameInformation.FileName */ )];
455
456         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
457         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
458         g_return_val_if_fail(file_info!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
459
460         /* query */
461         FileAllInformationStruct=(void *)QueryFile_buf;
462         err=NtQueryInformationFile(
463                         captive_file_object->file_Handle,       /* FileHandle */
464                         &file_IoStatusBlock,    /* IoStatusBlock */
465                         (gpointer)QueryFile_buf,        /* FileInformation */
466                         sizeof(QueryFile_buf)   /* Length */
467                                         -sizeof(*FileAllInformationStruct->NameInformation.FileName),   /* reserve space for 0-terminator */
468                         FileAllInformation);    /* FileInformationClass; =>FILE_ALL_INFORMATION */
469         if (GNOME_VFS_OK!=(errvfsresult=captive_NTSTATUS_to_GnomeVFSResult(err)))
470                 return errvfsresult;
471         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
472
473         /* process gathered info */
474         errvfsresult=FileAllInformationStruct_to_GnomeVFSFileInfo(file_info,FileAllInformationStruct,
475                         &file_IoStatusBlock);
476         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
477
478         return GNOME_VFS_OK;
479 }