Include "config.h" instead of <config.h> Command used: find -name
[platform/upstream/glib.git] / gio / gwin32mount.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  * Copyright (C) 2008 Hans Breuer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General
17  * Public License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * Author: Alexander Larsson <alexl@redhat.com>
22  *         David Zeuthen <davidz@redhat.com>
23  *         Hans Breuer <hans@breuer.org>
24  */
25
26 #include "config.h"
27
28 #include <string.h>
29 #define WIN32_MEAN_AND_LEAN
30 #include <windows.h>
31
32 #include <glib.h>
33 #include "gwin32volumemonitor.h"
34 #include "gwin32mount.h"
35 #include "gmountprivate.h"
36 #include "gvolumemonitor.h"
37 #include "gthemedicon.h"
38 #include "gsimpleasyncresult.h"
39 #include "glibintl.h"
40
41 #include "gioalias.h"
42
43 struct _GWin32Mount {
44   GObject parent;
45
46   GVolumeMonitor   *volume_monitor;
47
48   GWin32Volume      *volume; /* owned by volume monitor */
49   int   drive_type;
50
51   /* why does all this stuff need to be duplicated? It is in volume already! */
52   char *name;
53   GIcon *icon;
54   char *mount_path;
55
56   gboolean can_eject;
57 };
58
59 static void g_win32_mount_mount_iface_init (GMountIface *iface);
60
61 #define g_win32_mount_get_type _g_win32_mount_get_type
62 G_DEFINE_TYPE_WITH_CODE (GWin32Mount, g_win32_mount, G_TYPE_OBJECT,
63                          G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT,
64                                                 g_win32_mount_mount_iface_init))
65
66
67 static void
68 g_win32_mount_finalize (GObject *object)
69 {
70   GWin32Mount *mount;
71   
72   mount = G_WIN32_MOUNT (object);
73
74   if (mount->volume_monitor != NULL)
75     g_object_unref (mount->volume_monitor);
76 #if 0
77   if (mount->volume)
78     _g_win32_volume_unset_mount (mount->volume, mount);
79 #endif
80   /* TODO: g_warn_if_fail (volume->volume == NULL); */
81   g_object_unref (mount->icon);
82   g_free (mount->name);
83   g_free (mount->mount_path);
84   
85   if (G_OBJECT_CLASS (g_win32_mount_parent_class)->finalize)
86     (*G_OBJECT_CLASS (g_win32_mount_parent_class)->finalize) (object);
87 }
88
89 static void
90 g_win32_mount_class_init (GWin32MountClass *klass)
91 {
92   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
93
94   gobject_class->finalize = g_win32_mount_finalize;
95 }
96
97 static void
98 g_win32_mount_init (GWin32Mount *win32_mount)
99 {
100 }
101
102 gchar *
103 _win32_get_displayname (const char *drive)
104 {
105   gunichar2 *wdrive = g_utf8_to_utf16 (drive, -1, NULL, NULL, NULL);
106   gchar *name = NULL;
107   SHFILEINFOW sfi;
108   if (SHGetFileInfoW(wdrive, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME))
109     name = g_utf16_to_utf8 (sfi.szDisplayName, -1, NULL, NULL, NULL);
110
111   g_free (wdrive);
112   return name ? name : g_strdup (drive);
113 }
114
115 /**
116  * _g_win32_mount_new:
117  * @volume_monitor: a #GVolumeMonitor.
118  * @path: a win32 path.
119  * @volume: ususally NULL
120  * 
121  * Returns: a #GWin32Mount for the given win32 path.
122  **/
123 GWin32Mount *
124 _g_win32_mount_new (GVolumeMonitor  *volume_monitor,
125                     const char       *path,
126                     GWin32Volume     *volume)
127 {
128   GWin32Mount *mount;
129   const gchar *drive = path; //fixme
130
131 #if 0  
132   /* No volume for mount: Ignore internal things */
133   if (volume == NULL && !g_win32_mount_guess_should_display (mount_entry))
134     return NULL;
135 #endif
136
137   mount = g_object_new (G_TYPE_WIN32_MOUNT, NULL);
138   mount->volume_monitor = volume_monitor != NULL ? g_object_ref (volume_monitor) : NULL;
139   mount->mount_path = g_strdup (path);
140   mount->drive_type = GetDriveType (drive);
141   mount->can_eject = FALSE; /* TODO */
142   mount->name = _win32_get_displayname (drive);
143
144   /* need to do this last */
145   mount->volume = volume;
146 #if 0
147   if (volume != NULL)
148     _g_win32_volume_set_mount (volume, mount);
149 #endif
150   return mount;
151 }
152
153 void
154 _g_win32_mount_unmounted (GWin32Mount *mount)
155 {
156   if (mount->volume != NULL)
157     {
158 #if 0
159       _g_win32_volume_unset_mount (mount->volume, mount);
160 #endif
161       mount->volume = NULL;
162       g_signal_emit_by_name (mount, "changed");
163       /* there's really no need to emit mount_changed on the volume monitor 
164        * as we're going to be deleted.. */
165     }
166 }
167
168 void
169 _g_win32_mount_unset_volume (GWin32Mount *mount,
170                             GWin32Volume  *volume)
171 {
172   if (mount->volume == volume)
173     {
174       mount->volume = NULL;
175       /* TODO: Emit changed in idle to avoid locking issues */
176       g_signal_emit_by_name (mount, "changed");
177       if (mount->volume_monitor != NULL)
178         g_signal_emit_by_name (mount->volume_monitor, "mount_changed", mount);
179     }
180 }
181
182 static GFile *
183 g_win32_mount_get_root (GMount *mount)
184 {
185   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
186
187   return g_file_new_for_path (win32_mount->mount_path);
188 }
189
190 const char *
191 _win32_drive_type_to_icon (int type)
192 {
193   switch (type)
194   {
195   case DRIVE_REMOVABLE : return "gtk-floppy";
196   case DRIVE_FIXED : return "gtk-harddisk";
197   case DRIVE_REMOTE : return "gtk-network"; 
198   case DRIVE_CDROM : return "gtk-cdrom";
199   default : return "gtk-directory";
200   }
201 }
202
203 static GIcon *
204 g_win32_mount_get_icon (GMount *mount)
205 {
206   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
207
208   g_return_val_if_fail (win32_mount->mount_path != NULL, NULL);
209
210   /* lazy creation */
211   if (!win32_mount->icon)
212     {
213       SHFILEINFOW shfi;
214       wchar_t *wfn = g_utf8_to_utf16 (win32_mount->mount_path, -1, NULL, NULL, NULL);
215
216       if (SHGetFileInfoW (wfn, 0, &shfi, sizeof (shfi), SHGFI_ICONLOCATION))
217         {
218           gchar *name = g_utf16_to_utf8 (shfi.szDisplayName, -1, NULL, NULL, NULL);
219           gchar *id = g_strdup_printf ("%s,%i", name, shfi.iIcon);
220           win32_mount->icon = g_themed_icon_new (id);
221           g_free (name);
222           g_free (id);
223         }
224       else
225         {
226           win32_mount->icon = g_themed_icon_new_with_default_fallbacks (
227                                 _win32_drive_type_to_icon (win32_mount->drive_type));
228         }
229     }
230
231   return g_object_ref (win32_mount->icon);
232 }
233
234 static char *
235 g_win32_mount_get_uuid (GMount *mount)
236 {
237   return NULL;
238 }
239
240 static char *
241 g_win32_mount_get_name (GMount *mount)
242 {
243   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
244   
245   return g_strdup (win32_mount->name);
246 }
247
248 static GDrive *
249 g_win32_mount_get_drive (GMount *mount)
250 {
251   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
252
253   if (win32_mount->volume != NULL)
254     return g_volume_get_drive (G_VOLUME (win32_mount->volume));
255
256   return NULL;
257 }
258
259 static GVolume *
260 g_win32_mount_get_volume (GMount *mount)
261 {
262   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
263
264   if (win32_mount->volume)
265     return G_VOLUME (g_object_ref (win32_mount->volume));
266   
267   return NULL;
268 }
269
270 static gboolean
271 g_win32_mount_can_unmount (GMount *mount)
272 {
273   return FALSE;
274 }
275
276 static gboolean
277 g_win32_mount_can_eject (GMount *mount)
278 {
279   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
280   return win32_mount->can_eject;
281 }
282
283
284 typedef struct {
285   GWin32Mount *win32_mount;
286   GAsyncReadyCallback callback;
287   gpointer user_data;
288   GCancellable *cancellable;
289   int error_fd;
290   GIOChannel *error_channel;
291   guint error_channel_source_id;
292   GString *error_string;
293 } UnmountEjectOp;
294
295 static void 
296 eject_unmount_cb (GPid pid, gint status, gpointer user_data)
297 {
298   UnmountEjectOp *data = user_data;
299   GSimpleAsyncResult *simple;
300
301 #if 0  
302   if (WEXITSTATUS (status) != 0)
303     {
304       GError *error;
305       error = g_error_new_literal (G_IO_ERROR, 
306                                    G_IO_ERROR_FAILED,
307                                    data->error_string->str);
308       simple = g_simple_async_result_new_from_error (G_OBJECT (data->win32_mount),
309                                                      data->callback,
310                                                      data->user_data,
311                                                      error);
312       g_error_free (error);
313     }
314   else
315     {
316       simple = g_simple_async_result_new (G_OBJECT (data->win32_mount),
317                                           data->callback,
318                                           data->user_data,
319                                           NULL);
320     }
321
322   g_simple_async_result_complete (simple);
323   g_object_unref (simple);
324
325   g_source_remove (data->error_channel_source_id);
326   g_io_channel_unref (data->error_channel);
327   g_string_free (data->error_string, TRUE);
328   close (data->error_fd);
329   g_spawn_close_pid (pid);
330   g_free (data);
331 #endif
332 }
333
334 static gboolean
335 eject_unmount_read_error (GIOChannel *channel,
336                     GIOCondition condition,
337                     gpointer user_data)
338 {
339   char *str;
340   gsize str_len;
341   UnmountEjectOp *data = user_data;
342
343   g_io_channel_read_to_end (channel, &str, &str_len, NULL);
344   g_string_append (data->error_string, str);
345   g_free (str);
346   return TRUE;
347 }
348
349 static void
350 eject_unmount_do (GMount              *mount,
351                   GCancellable        *cancellable,
352                   GAsyncReadyCallback  callback,
353                   gpointer             user_data,
354                   char               **argv)
355 {
356   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
357 }
358
359 static void
360 g_win32_mount_unmount (GMount             *mount,
361                       GMountUnmountFlags flags,
362                       GCancellable        *cancellable,
363                       GAsyncReadyCallback  callback,
364                       gpointer             user_data)
365 {
366   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
367 }
368
369 static gboolean
370 g_win32_mount_unmount_finish (GMount       *mount,
371                              GAsyncResult  *result,
372                              GError       **error)
373 {
374   return FALSE;
375 }
376
377 static void
378 g_win32_mount_eject (GMount             *mount,
379                     GMountUnmountFlags flags,
380                     GCancellable        *cancellable,
381                     GAsyncReadyCallback  callback,
382                     gpointer             user_data)
383 {
384   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
385 }
386
387 static gboolean
388 g_win32_mount_eject_finish (GMount       *mount,
389                            GAsyncResult  *result,
390                            GError       **error)
391 {
392   return FALSE;
393 }
394
395 static void
396 g_win32_mount_mount_iface_init (GMountIface *iface)
397 {
398   iface->get_root = g_win32_mount_get_root;
399   iface->get_name = g_win32_mount_get_name;
400   iface->get_icon = g_win32_mount_get_icon;
401   iface->get_uuid = g_win32_mount_get_uuid;
402   iface->get_drive = g_win32_mount_get_drive;
403   iface->get_volume = g_win32_mount_get_volume;
404   iface->can_unmount = g_win32_mount_can_unmount;
405   iface->can_eject = g_win32_mount_can_eject;
406   iface->unmount = g_win32_mount_unmount;
407   iface->unmount_finish = g_win32_mount_unmount_finish;
408   iface->eject = g_win32_mount_eject;
409   iface->eject_finish = g_win32_mount_eject_finish;
410 }