Cosmetic: Fixed missing #include file
[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
31
32 static gpointer captive_file_object_parent_class=NULL;
33
34
35 static GnomeVFSResult captive_file_close(CaptiveFileObject *captive_file_object);
36
37 static void captive_file_object_finalize(CaptiveFileObject *captive_file_object)
38 {
39 GnomeVFSResult errvfsresult;
40
41         g_return_if_fail(captive_file_object!=NULL);
42
43         errvfsresult=captive_file_close(captive_file_object);
44         g_assert(errvfsresult==GNOME_VFS_OK);
45
46         G_OBJECT_CLASS(captive_file_object_parent_class)->finalize((GObject *)captive_file_object);
47 }
48
49
50 static void captive_file_object_class_init(CaptiveFileObjectClass *class)
51 {
52 GObjectClass *gobject_class=G_OBJECT_CLASS(class);
53
54         captive_file_object_parent_class=g_type_class_ref(G_TYPE_OBJECT);
55         gobject_class->finalize=(void (*)(GObject *object))captive_file_object_finalize;
56 }
57
58
59 static void captive_file_object_init(CaptiveFileObject *captive_file_object)
60 {
61         captive_file_object->file_Handle=NULL;
62 }
63
64
65 GType captive_file_object_get_type(void)
66 {
67 static GType captive_file_object_type=0;
68
69         if (!captive_file_object_type) {
70 static const GTypeInfo captive_file_object_info={
71                                 sizeof(CaptiveFileObjectClass),
72                                 NULL,   /* base_init */
73                                 NULL,   /* base_finalize */
74                                 (GClassInitFunc)captive_file_object_class_init,
75                                 NULL,   /* class_finalize */
76                                 NULL,   /* class_data */
77                                 sizeof(CaptiveFileObject),
78                                 5,      /* n_preallocs */
79                                 (GInstanceInitFunc)captive_file_object_init,
80                                 };
81
82                 captive_file_object_type=g_type_register_static(G_TYPE_OBJECT,
83                                 "CaptiveFileObject",&captive_file_object_info,0);
84                 }
85
86         return captive_file_object_type;
87 }
88
89
90 GnomeVFSResult captive_file_new_open
91                 (CaptiveFileObject **captive_file_object_return,const gchar *pathname,GnomeVFSOpenMode mode)
92 {
93 IO_STATUS_BLOCK file_IoStatusBlock;
94 GnomeVFSResult errvfsresult;
95 OBJECT_ATTRIBUTES file_ObjectAttributes;
96 HANDLE file_Handle;
97 CaptiveFileObject *captive_file_object;
98 NTSTATUS err;
99
100         if (CAPTIVE_IS_SANDBOX_PARENT())
101                 return captive_sandbox_parent_file_new_open(captive_file_object_return,pathname,mode);
102
103         g_return_val_if_fail(captive_file_object_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
104         g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
105
106         *captive_file_object_return=NULL;
107
108         errvfsresult=captive_ObjectAttributes_init(pathname,&file_ObjectAttributes);
109         g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
110         
111         /* open */
112         err=IoCreateFile(
113                         &file_Handle,   /* FileHandle */
114                         0
115                                         |(!(mode&GNOME_VFS_OPEN_READ ) ? 0 : FILE_READ_DATA)
116                                         |(!(mode&GNOME_VFS_OPEN_WRITE) ? 0 : FILE_WRITE_DATA | FILE_APPEND_DATA)
117                                         ,       /* DesiredAccess */
118                         &file_ObjectAttributes, /* ObjectAttributes */
119                         &file_IoStatusBlock,    /* IoStatusBlock */
120                         NULL,   /* AllocationSize; ignored for open */
121                         FILE_ATTRIBUTE_NORMAL,  /* FileAttributes; ignored for open */
122                         FILE_SHARE_WRITE,       /* ShareAccess; 0 means exclusive */
123                         FILE_OPEN,      /* CreateDisposition */
124                         /* FILE_SYNCHRONOUS_IO_{,NON}ALERT: We need to allow W32 filesystem
125                                  * any waits to not to let it return STATUS_CANT_WAIT us.
126                                  * Alertability should have only effect on asynchronous events
127                                  * from KeWaitForSingleObject() by setting/clearing its parameter 'Alertable'.
128                                  */
129                         FILE_SYNCHRONOUS_IO_ALERT,      /* CreateOptions */
130                         NULL,   /* EaBuffer */
131                         0,      /* EaLength */
132                         CreateFileTypeNone,     /* CreateFileType */
133                         NULL,   /* ExtraCreateParameters */
134                         0);     /* Options */
135         g_free(file_ObjectAttributes.ObjectName);       /* left from captive_file_uri_parent_init() */
136         g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
137         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
138         g_return_val_if_fail(file_IoStatusBlock.Information==FILE_OPENED,GNOME_VFS_ERROR_GENERIC);
139
140         captive_file_object=g_object_new(
141                         CAPTIVE_FILE_TYPE_OBJECT,       /* object_type */
142                         NULL);  /* first_property_name; FIXME: support properties */
143
144         captive_file_object->file_Handle=file_Handle;
145         captive_file_object->offset=0;
146
147         *captive_file_object_return=captive_file_object;
148         return GNOME_VFS_OK;
149 }
150
151
152 static GnomeVFSResult captive_file_close(CaptiveFileObject *captive_file_object)
153 {
154 NTSTATUS err;
155 HANDLE file_Handle;
156
157         if (CAPTIVE_IS_SANDBOX_PARENT())
158                 return captive_sandbox_parent_file_close(captive_file_object);
159
160         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
161         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);    /* already closed */
162
163         file_Handle=captive_file_object->file_Handle;
164         captive_file_object->file_Handle=NULL;
165         err=NtClose(file_Handle);
166         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
167
168         return GNOME_VFS_OK;
169 }
170
171
172 GnomeVFSResult captive_file_read
173                 (CaptiveFileObject *captive_file_object,gpointer buffer,GnomeVFSFileSize num_bytes,GnomeVFSFileSize *bytes_read_return)
174 {
175 NTSTATUS err;
176 IO_STATUS_BLOCK file_IoStatusBlock;
177 LARGE_INTEGER file_offset;
178
179         if (CAPTIVE_IS_SANDBOX_PARENT())
180                 return captive_sandbox_parent_file_read(captive_file_object,buffer,num_bytes,bytes_read_return);
181
182         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
183         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
184         g_return_val_if_fail(buffer!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
185         g_return_val_if_fail(bytes_read_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
186         g_return_val_if_fail(num_bytes==(ULONG)num_bytes,GNOME_VFS_ERROR_BAD_PARAMETERS);
187
188         file_offset.QuadPart=captive_file_object->offset;
189         err=NtReadFile(
190                         captive_file_object->file_Handle,       /* FileHandle */
191                         NULL,   /* EventHandle; completion signalling; optional */
192                         NULL,   /* ApcRoutine; optional */
193                         NULL,   /* ApcContext; optional */
194                         &file_IoStatusBlock,    /* IoStatusBlock */
195                         buffer, /* Buffer */
196                         num_bytes,      /* Length */
197                         &file_offset,   /* ByteOffset */
198                         NULL);  /* Key; NULL means no file locking key */
199         if (err==STATUS_END_OF_FILE) {
200                 g_return_val_if_fail(file_IoStatusBlock.Status==STATUS_END_OF_FILE,GNOME_VFS_ERROR_GENERIC);
201                 g_return_val_if_fail(file_IoStatusBlock.Information==0,GNOME_VFS_ERROR_GENERIC);
202                 *bytes_read_return=0;
203                 return GNOME_VFS_ERROR_EOF;
204                 }
205         g_return_val_if_fail(NT_SUCCESS(err)==NT_SUCCESS(file_IoStatusBlock.Status),GNOME_VFS_ERROR_GENERIC);
206         g_return_val_if_fail(NT_SUCCESS(err),GNOME_VFS_ERROR_GENERIC);
207         g_return_val_if_fail(file_IoStatusBlock.Information<=num_bytes,GNOME_VFS_ERROR_GENERIC);
208
209         captive_file_object->offset+=file_IoStatusBlock.Information;
210         *bytes_read_return=file_IoStatusBlock.Information;
211         return GNOME_VFS_OK;
212 }
213
214
215 GnomeVFSResult captive_file_seek
216                 (CaptiveFileObject *captive_file_object,GnomeVFSSeekPosition whence,GnomeVFSFileOffset offset)
217 {
218         if (CAPTIVE_IS_SANDBOX_PARENT())
219                 return captive_sandbox_parent_file_seek(captive_file_object,whence,offset);
220
221         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
222         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
223
224         switch (whence) {
225                 case GNOME_VFS_SEEK_START:
226                         captive_file_object->offset=offset;
227                         break;
228                 case GNOME_VFS_SEEK_CURRENT:
229                         if (0
230                                         || (offset>0 && (captive_file_object->offset+offset)<captive_file_object->offset)
231                                         || (offset<0 && (captive_file_object->offset+offset)>captive_file_object->offset))
232                                 return GNOME_VFS_ERROR_BAD_PARAMETERS;
233                         captive_file_object->offset+=offset;
234                         break;
235                 case GNOME_VFS_SEEK_END:
236                         g_assert_not_reached(); /* NOT IMPLEMENTED YET */
237                         break;
238                 default:
239                         g_return_val_if_reached(GNOME_VFS_ERROR_BAD_PARAMETERS);
240                 }
241
242         return GNOME_VFS_OK;
243 }
244
245
246 GnomeVFSResult captive_file_tell(CaptiveFileObject *captive_file_object,GnomeVFSFileOffset *offset_return)
247 {
248         if (CAPTIVE_IS_SANDBOX_PARENT())
249                 return captive_sandbox_parent_file_tell(captive_file_object,offset_return);
250
251         g_return_val_if_fail(captive_file_object!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
252         g_return_val_if_fail(captive_file_object->file_Handle!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
253         g_return_val_if_fail(offset_return!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
254
255         *offset_return=captive_file_object->offset;
256         return GNOME_VFS_OK;
257 }