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