1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
5 * Copyright (C) 2003-2004 Dom Lachowicz <cinamod@hotmail.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2.1 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
22 #include <gsf-config.h>
23 #include <gsf-win32/gsf-input-win32.h>
24 #include <gsf/gsf-input-impl.h>
25 #include <gsf/gsf-impl-utils.h>
28 struct _GsfInputIStream {
36 GsfInputClass input_class;
37 } GsfInputIStreamClass;
39 #define NEED_ISTREAM_MACROS
41 #ifdef NEED_ISTREAM_MACROS
42 #define IStream_AddRef(This) (This)->lpVtbl->AddRef(This)
43 #define IStream_Clone(This,ppstm) (This)->lpVtbl->Clone(This,ppstm)
44 #define IStream_Read(This,pv,cb,pcbRead) (This)->lpVtbl->Read(This,pv,cb,pcbRead)
45 #define IStream_Release(This) (This)->lpVtbl->Release(This)
46 #define IStream_Seek(This,dlibMove,dwOrigin,plibNewPosition) (This)->lpVtbl->Seek(This,dlibMove,dwOrigin,plibNewPosition)
47 #define IStream_Stat(This,pstatstg,grfStatFlag) (This)->lpVtbl->Stat(This,pstatstg,grfStatFlag)
50 gchar * gsf_win32_hresult_to_utf8 (HRESULT hr);
53 gsf_win32_hresult_to_utf8 (HRESULT hr)
61 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr,
62 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pMsgBuf, 0, NULL);
64 utf8_msg = g_locale_to_utf8 ((char const *)pMsgBuf, -1, NULL, NULL, NULL);
66 utf8_msg = g_strdup ("!SUCCEEDED (hr)");
74 hresult_to_gerror (HRESULT hr, GError ** err)
79 msg = gsf_win32_hresult_to_utf8 (hr);
82 *err = g_error_new (gsf_input_error_id (), 0, msg);
89 lpwstr_to_utf8 (LPWSTR str)
92 return g_utf16_to_utf8 (str, -1, NULL, NULL, NULL);
97 * gsf_input_istream_new :
98 * @stream : IStream stream
99 * @err : optionally %NULL.
101 * Returns: a new input object or %NULL.
104 gsf_input_istream_new (IStream * stream, GError **err)
106 GsfInputIStream *input;
111 if (stream == NULL) {
113 *err = g_error_new (gsf_input_error_id (), 0,
118 if (FAILED (hr = IStream_Stat (stream, &statbuf, STATFLAG_DEFAULT))) {
119 hresult_to_gerror (hr, err);
123 input = g_object_new (GSF_INPUT_ISTREAM_TYPE, NULL);
124 if (G_UNLIKELY (NULL == input)) {
125 IStream_Release (stream);
129 input->stream = stream;
133 IStream_AddRef (input->stream);
135 /* LowPart and HiPart are the low and high 32 bit UINT parts. The MSDN documentation
136 says to use QuadPart if your compiler supports 64 bit ints. gsf_off_t is a gint64 value.
137 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winprog/winprog/large_integer_str.asp
139 gsf_input_set_size (GSF_INPUT (input), (gsf_off_t) statbuf.cbSize.QuadPart);
141 name = lpwstr_to_utf8 (statbuf.pwcsName);
143 gsf_input_set_name (GSF_INPUT (input), name);
147 return GSF_INPUT(input);
151 gsf_input_istream_finalize (GObject *obj)
153 GObjectClass *parent_class;
154 GsfInputIStream *input = (GsfInputIStream *)obj;
156 IStream_Release (input->stream);
157 input->stream = NULL;
159 if (input->buf != NULL) {
165 parent_class = g_type_class_peek (GSF_INPUT_TYPE);
166 if (parent_class && parent_class->finalize)
167 parent_class->finalize (obj);
171 gsf_input_istream_dup (GsfInput *src_input, GError **err)
173 GsfInputIStream const *src = (GsfInputIStream *)src_input;
178 g_return_val_if_fail (src_input != NULL, NULL);
179 g_return_val_if_fail (src->stream != NULL, NULL);
181 if (SUCCEEDED (hr = IStream_Clone (src->stream, &clone))) {
182 dst = gsf_input_istream_new (clone, NULL);
183 IStream_Release (clone); /* gsf_input_istream_new() adds a ref */
187 hresult_to_gerror (hr, err);
191 static guint8 const *
192 gsf_input_istream_read (GsfInput *input, size_t num_bytes,
195 GsfInputIStream *istm = GSF_INPUT_ISTREAM (input);
197 ULONG nread, total_read = 0;
199 g_return_val_if_fail (istm != NULL, NULL);
200 g_return_val_if_fail (istm->stream != NULL, NULL);
202 if (buffer == NULL) {
203 if (istm->buf_size < num_bytes) {
204 istm->buf_size = num_bytes;
206 istm->buf = g_new (guint8, istm->buf_size);
213 hr = IStream_Read (istm->stream, (buffer + total_read), (ULONG)(num_bytes - total_read), &nread);
215 if (SUCCEEDED (hr)) {
217 if ((size_t) total_read == num_bytes) {
224 g_warning ("IStream read failed\n");
229 gsf_input_istream_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
231 GsfInputIStream *istm = GSF_INPUT_ISTREAM (input);
234 g_return_val_if_fail (istm != NULL, TRUE);
235 g_return_val_if_fail (istm->stream != NULL, TRUE);
239 dwhence = STREAM_SEEK_SET;
242 dwhence = STREAM_SEEK_CUR;
245 dwhence = STREAM_SEEK_END;
251 if(SUCCEEDED (IStream_Seek (istm->stream, *(LARGE_INTEGER *) &offset, dwhence, NULL)))
257 gsf_input_istream_init (GObject *obj)
259 GsfInputIStream *istm = GSF_INPUT_ISTREAM (obj);
267 gsf_input_istream_class_init (GObjectClass *gobject_class)
269 GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
271 gobject_class->finalize = gsf_input_istream_finalize;
272 input_class->Dup = gsf_input_istream_dup;
273 input_class->Read = gsf_input_istream_read;
274 input_class->Seek = gsf_input_istream_seek;
277 GSF_CLASS (GsfInputIStream, gsf_input_istream,
278 gsf_input_istream_class_init, gsf_input_istream_init, GSF_INPUT_TYPE)
280 /***************************************************************************/
281 /***************************************************************************/