Home | History | Annotate | Download | only in gio
      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 (at) redhat.com>
     22  *         David Zeuthen <davidz (at) redhat.com>
     23  *         Hans Breuer <hans (at) 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 "gmount.h"
     36 #include "gfile.h"
     37 #include "gmountprivate.h"
     38 #include "gvolumemonitor.h"
     39 #include "gthemedicon.h"
     40 #include "gsimpleasyncresult.h"
     41 #include "glibintl.h"
     42 
     43 #include "gioalias.h"
     44 
     45 struct _GWin32Mount {
     46   GObject parent;
     47 
     48   GVolumeMonitor   *volume_monitor;
     49 
     50   GWin32Volume      *volume; /* owned by volume monitor */
     51   int   drive_type;
     52 
     53   /* why does all this stuff need to be duplicated? It is in volume already! */
     54   char *name;
     55   GIcon *icon;
     56   char *mount_path;
     57 
     58   gboolean can_eject;
     59 };
     60 
     61 static void g_win32_mount_mount_iface_init (GMountIface *iface);
     62 
     63 #define g_win32_mount_get_type _g_win32_mount_get_type
     64 G_DEFINE_TYPE_WITH_CODE (GWin32Mount, g_win32_mount, G_TYPE_OBJECT,
     65 			 G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT,
     66 						g_win32_mount_mount_iface_init))
     67 
     68 
     69 static void
     70 g_win32_mount_finalize (GObject *object)
     71 {
     72   GWin32Mount *mount;
     73 
     74   mount = G_WIN32_MOUNT (object);
     75 
     76   if (mount->volume_monitor != NULL)
     77     g_object_unref (mount->volume_monitor);
     78 #if 0
     79   if (mount->volume)
     80     _g_win32_volume_unset_mount (mount->volume, mount);
     81 #endif
     82   /* TODO: g_warn_if_fail (volume->volume == NULL); */
     83 
     84   if (mount->icon != NULL)
     85     g_object_unref (mount->icon);
     86 
     87   g_free (mount->name);
     88   g_free (mount->mount_path);
     89 
     90   if (G_OBJECT_CLASS (g_win32_mount_parent_class)->finalize)
     91     (*G_OBJECT_CLASS (g_win32_mount_parent_class)->finalize) (object);
     92 }
     93 
     94 static void
     95 g_win32_mount_class_init (GWin32MountClass *klass)
     96 {
     97   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     98 
     99   gobject_class->finalize = g_win32_mount_finalize;
    100 }
    101 
    102 static void
    103 g_win32_mount_init (GWin32Mount *win32_mount)
    104 {
    105 }
    106 
    107 gchar *
    108 _win32_get_displayname (const char *drive)
    109 {
    110   gunichar2 *wdrive = g_utf8_to_utf16 (drive, -1, NULL, NULL, NULL);
    111   gchar *name = NULL;
    112   SHFILEINFOW sfi;
    113   if (SHGetFileInfoW(wdrive, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME))
    114     name = g_utf16_to_utf8 (sfi.szDisplayName, -1, NULL, NULL, NULL);
    115 
    116   g_free (wdrive);
    117   return name ? name : g_strdup (drive);
    118 }
    119 
    120 /**
    121  * _g_win32_mount_new:
    122  * @volume_monitor: a #GVolumeMonitor.
    123  * @path: a win32 path.
    124  * @volume: ususally NULL
    125  *
    126  * Returns: a #GWin32Mount for the given win32 path.
    127  **/
    128 GWin32Mount *
    129 _g_win32_mount_new (GVolumeMonitor  *volume_monitor,
    130                     const char      *path,
    131                     GWin32Volume    *volume)
    132 {
    133   GWin32Mount *mount;
    134   const gchar *drive = path; //fixme
    135 
    136 #if 0
    137   /* No volume for mount: Ignore internal things */
    138   if (volume == NULL && !g_win32_mount_guess_should_display (mount_entry))
    139     return NULL;
    140 #endif
    141 
    142   mount = g_object_new (G_TYPE_WIN32_MOUNT, NULL);
    143   mount->volume_monitor = volume_monitor != NULL ? g_object_ref (volume_monitor) : NULL;
    144   mount->mount_path = g_strdup (path);
    145   mount->drive_type = GetDriveType (drive);
    146   mount->can_eject = FALSE; /* TODO */
    147   mount->name = _win32_get_displayname (drive);
    148 
    149   /* need to do this last */
    150   mount->volume = volume;
    151 #if 0
    152   if (volume != NULL)
    153     _g_win32_volume_set_mount (volume, mount);
    154 #endif
    155   return mount;
    156 }
    157 
    158 void
    159 _g_win32_mount_unmounted (GWin32Mount *mount)
    160 {
    161   if (mount->volume != NULL)
    162     {
    163 #if 0
    164       _g_win32_volume_unset_mount (mount->volume, mount);
    165 #endif
    166       mount->volume = NULL;
    167       g_signal_emit_by_name (mount, "changed");
    168       /* there's really no need to emit mount_changed on the volume monitor
    169        * as we're going to be deleted.. */
    170     }
    171 }
    172 
    173 void
    174 _g_win32_mount_unset_volume (GWin32Mount  *mount,
    175 			     GWin32Volume *volume)
    176 {
    177   if (mount->volume == volume)
    178     {
    179       mount->volume = NULL;
    180       /* TODO: Emit changed in idle to avoid locking issues */
    181       g_signal_emit_by_name (mount, "changed");
    182       if (mount->volume_monitor != NULL)
    183         g_signal_emit_by_name (mount->volume_monitor, "mount-changed", mount);
    184     }
    185 }
    186 
    187 static GFile *
    188 g_win32_mount_get_root (GMount *mount)
    189 {
    190   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
    191 
    192   return g_file_new_for_path (win32_mount->mount_path);
    193 }
    194 
    195 const char *
    196 _win32_drive_type_to_icon (int type)
    197 {
    198   switch (type)
    199   {
    200   case DRIVE_REMOVABLE : return "gtk-floppy";
    201   case DRIVE_FIXED : return "gtk-harddisk";
    202   case DRIVE_REMOTE : return "gtk-network";
    203   case DRIVE_CDROM : return "gtk-cdrom";
    204   default : return "gtk-directory";
    205   }
    206 }
    207 
    208 static GIcon *
    209 g_win32_mount_get_icon (GMount *mount)
    210 {
    211   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
    212 
    213   g_return_val_if_fail (win32_mount->mount_path != NULL, NULL);
    214 
    215   /* lazy creation */
    216   if (!win32_mount->icon)
    217     {
    218       SHFILEINFOW shfi;
    219       wchar_t *wfn = g_utf8_to_utf16 (win32_mount->mount_path, -1, NULL, NULL, NULL);
    220 
    221       if (SHGetFileInfoW (wfn, 0, &shfi, sizeof (shfi), SHGFI_ICONLOCATION))
    222         {
    223 	  gchar *name = g_utf16_to_utf8 (shfi.szDisplayName, -1, NULL, NULL, NULL);
    224 	  gchar *id = g_strdup_printf ("%s,%i", name, shfi.iIcon);
    225 	  win32_mount->icon = g_themed_icon_new (id);
    226 	  g_free (name);
    227 	  g_free (id);
    228 	}
    229       else
    230         {
    231           win32_mount->icon = g_themed_icon_new_with_default_fallbacks (
    232 	                        _win32_drive_type_to_icon (win32_mount->drive_type));
    233 	}
    234     }
    235 
    236   return g_object_ref (win32_mount->icon);
    237 }
    238 
    239 static char *
    240 g_win32_mount_get_uuid (GMount *mount)
    241 {
    242   return NULL;
    243 }
    244 
    245 static char *
    246 g_win32_mount_get_name (GMount *mount)
    247 {
    248   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
    249 
    250   return g_strdup (win32_mount->name);
    251 }
    252 
    253 static GDrive *
    254 g_win32_mount_get_drive (GMount *mount)
    255 {
    256   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
    257 
    258   if (win32_mount->volume != NULL)
    259     return g_volume_get_drive (G_VOLUME (win32_mount->volume));
    260 
    261   return NULL;
    262 }
    263 
    264 static GVolume *
    265 g_win32_mount_get_volume (GMount *mount)
    266 {
    267   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
    268 
    269   if (win32_mount->volume)
    270     return G_VOLUME (g_object_ref (win32_mount->volume));
    271 
    272   return NULL;
    273 }
    274 
    275 static gboolean
    276 g_win32_mount_can_unmount (GMount *mount)
    277 {
    278   return FALSE;
    279 }
    280 
    281 static gboolean
    282 g_win32_mount_can_eject (GMount *mount)
    283 {
    284   GWin32Mount *win32_mount = G_WIN32_MOUNT (mount);
    285   return win32_mount->can_eject;
    286 }
    287 
    288 
    289 typedef struct {
    290   GWin32Mount *win32_mount;
    291   GAsyncReadyCallback callback;
    292   gpointer user_data;
    293   GCancellable *cancellable;
    294   int error_fd;
    295   GIOChannel *error_channel;
    296   guint error_channel_source_id;
    297   GString *error_string;
    298 } UnmountEjectOp;
    299 
    300 static void
    301 g_win32_mount_unmount (GMount              *mount,
    302 		       GMountUnmountFlags   flags,
    303 		       GCancellable        *cancellable,
    304 		       GAsyncReadyCallback  callback,
    305 		       gpointer             user_data)
    306 {
    307 }
    308 
    309 static gboolean
    310 g_win32_mount_unmount_finish (GMount        *mount,
    311 			      GAsyncResult  *result,
    312 			      GError       **error)
    313 {
    314   return FALSE;
    315 }
    316 
    317 static void
    318 g_win32_mount_eject (GMount              *mount,
    319 		     GMountUnmountFlags   flags,
    320 		     GCancellable        *cancellable,
    321 		     GAsyncReadyCallback  callback,
    322 		     gpointer             user_data)
    323 {
    324 }
    325 
    326 static gboolean
    327 g_win32_mount_eject_finish (GMount        *mount,
    328 			    GAsyncResult  *result,
    329 			    GError       **error)
    330 {
    331   return FALSE;
    332 }
    333 
    334 static void
    335 g_win32_mount_mount_iface_init (GMountIface *iface)
    336 {
    337   iface->get_root = g_win32_mount_get_root;
    338   iface->get_name = g_win32_mount_get_name;
    339   iface->get_icon = g_win32_mount_get_icon;
    340   iface->get_uuid = g_win32_mount_get_uuid;
    341   iface->get_drive = g_win32_mount_get_drive;
    342   iface->get_volume = g_win32_mount_get_volume;
    343   iface->can_unmount = g_win32_mount_can_unmount;
    344   iface->can_eject = g_win32_mount_can_eject;
    345   iface->unmount = g_win32_mount_unmount;
    346   iface->unmount_finish = g_win32_mount_unmount_finish;
    347   iface->eject = g_win32_mount_eject;
    348   iface->eject_finish = g_win32_mount_eject_finish;
    349 }
    350