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 "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 45struct _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 61static void g_win32_mount_mount_iface_init (GMountIface *iface); 62 63#define g_win32_mount_get_type _g_win32_mount_get_type 64G_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 69static void 70g_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 94static void 95g_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 102static void 103g_win32_mount_init (GWin32Mount *win32_mount) 104{ 105} 106 107gchar * 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 **/ 128GWin32Mount * 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 158void 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 173void 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 187static GFile * 188g_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 195const 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 208static GIcon * 209g_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 239static char * 240g_win32_mount_get_uuid (GMount *mount) 241{ 242 return NULL; 243} 244 245static char * 246g_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 253static GDrive * 254g_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 264static GVolume * 265g_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 275static gboolean 276g_win32_mount_can_unmount (GMount *mount) 277{ 278 return FALSE; 279} 280 281static gboolean 282g_win32_mount_can_eject (GMount *mount) 283{ 284 GWin32Mount *win32_mount = G_WIN32_MOUNT (mount); 285 return win32_mount->can_eject; 286} 287 288 289typedef 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 300static void 301g_win32_mount_unmount (GMount *mount, 302 GMountUnmountFlags flags, 303 GCancellable *cancellable, 304 GAsyncReadyCallback callback, 305 gpointer user_data) 306{ 307} 308 309static gboolean 310g_win32_mount_unmount_finish (GMount *mount, 311 GAsyncResult *result, 312 GError **error) 313{ 314 return FALSE; 315} 316 317static void 318g_win32_mount_eject (GMount *mount, 319 GMountUnmountFlags flags, 320 GCancellable *cancellable, 321 GAsyncReadyCallback callback, 322 gpointer user_data) 323{ 324} 325 326static gboolean 327g_win32_mount_eject_finish (GMount *mount, 328 GAsyncResult *result, 329 GError **error) 330{ 331 return FALSE; 332} 333 334static void 335g_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