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 
     30 #include <glib.h>
     31 #include "glibintl.h"
     32 
     33 #include "gwin32volumemonitor.h"
     34 #include "gwin32mount.h"
     35 #include "gmount.h"
     36 #include "giomodule.h"
     37 #include "gioalias.h"
     38 
     39 #define _WIN32_WINNT 0x0500
     40 #include <windows.h>
     41 
     42 struct _GWin32VolumeMonitor {
     43   GNativeVolumeMonitor parent;
     44 
     45   GList *volumes;
     46   GList *mounts;
     47 };
     48 
     49 #define g_win32_volume_monitor_get_type _g_win32_volume_monitor_get_type
     50 G_DEFINE_TYPE_WITH_CODE (GWin32VolumeMonitor, g_win32_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR,
     51                          g_io_extension_point_implement (G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME,
     52 							 g_define_type_id,
     53 							 "win32",
     54 							 0));
     55 
     56 static void
     57 g_win32_volume_monitor_finalize (GObject *object)
     58 {
     59   GWin32VolumeMonitor *monitor;
     60 
     61   monitor = G_WIN32_VOLUME_MONITOR (object);
     62 
     63   if (G_OBJECT_CLASS (g_win32_volume_monitor_parent_class)->finalize)
     64     (*G_OBJECT_CLASS (g_win32_volume_monitor_parent_class)->finalize) (object);
     65 }
     66 
     67 /**
     68  * get_viewable_logical_drives:
     69  *
     70  * Returns the list of logical and viewable drives as defined by
     71  * GetLogicalDrives() and the registry keys
     72  * Software\Microsoft\Windows\CurrentVersion\Policies\Explorer under
     73  * HKLM or HKCU. If neither key exists the result of
     74  * GetLogicalDrives() is returned.
     75  *
     76  * Return value: bitmask with same meaning as returned by GetLogicalDrives()
     77 **/
     78 static guint32
     79 get_viewable_logical_drives (void)
     80 {
     81   guint viewable_drives = GetLogicalDrives ();
     82   HKEY key;
     83 
     84   DWORD var_type = REG_DWORD; //the value's a REG_DWORD type
     85   DWORD no_drives_size = 4;
     86   DWORD no_drives;
     87   gboolean hklm_present = FALSE;
     88 
     89   if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
     90 		    "Software\\Microsoft\\Windows\\"
     91 		    "CurrentVersion\\Policies\\Explorer",
     92 		    0, KEY_READ, &key) == ERROR_SUCCESS)
     93     {
     94       if (RegQueryValueEx (key, "NoDrives", NULL, &var_type,
     95 			   (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS)
     96 	{
     97 	  /* We need the bits that are set in viewable_drives, and
     98 	   * unset in no_drives.
     99 	   */
    100 	  viewable_drives = viewable_drives & ~no_drives;
    101 	  hklm_present = TRUE;
    102 	}
    103       RegCloseKey (key);
    104     }
    105 
    106   /* If the key is present in HKLM then the one in HKCU should be ignored */
    107   if (!hklm_present)
    108     {
    109       if (RegOpenKeyEx (HKEY_CURRENT_USER,
    110 			"Software\\Microsoft\\Windows\\"
    111 			"CurrentVersion\\Policies\\Explorer",
    112 			0, KEY_READ, &key) == ERROR_SUCCESS)
    113 	{
    114 	  if (RegQueryValueEx (key, "NoDrives", NULL, &var_type,
    115 			       (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS)
    116 	    {
    117 	      viewable_drives = viewable_drives & ~no_drives;
    118 	    }
    119 	  RegCloseKey (key);
    120 	}
    121     }
    122 
    123   return viewable_drives;
    124 }
    125 
    126 /* deliver accesible (aka 'mounted') volumes */
    127 static GList *
    128 get_mounts (GVolumeMonitor *volume_monitor)
    129 {
    130   GWin32VolumeMonitor *monitor;
    131   DWORD   drives;
    132   gchar   drive[4] = "A:\\";
    133   GList *list = NULL;
    134 
    135   monitor = G_WIN32_VOLUME_MONITOR (volume_monitor);
    136 
    137   drives = get_viewable_logical_drives ();
    138 
    139   if (!drives)
    140     g_warning ("get_viewable_logical_drives failed.");
    141 
    142   while (drives && drive[0] <= 'Z')
    143     {
    144       if (drives & 1)
    145       {
    146 	list = g_list_prepend (list, _g_win32_mount_new (volume_monitor, drive, NULL));
    147       }
    148       drives >>= 1;
    149       drive[0]++;
    150     }
    151   return list;
    152 }
    153 
    154 /* actually 'mounting' volumes is out of GIOs business on win32, so no volumes are delivered either */
    155 static GList *
    156 get_volumes (GVolumeMonitor *volume_monitor)
    157 {
    158   GWin32VolumeMonitor *monitor;
    159   GList *l = NULL;
    160 
    161   monitor = G_WIN32_VOLUME_MONITOR (volume_monitor);
    162 
    163   return l;
    164 }
    165 
    166 /* real hardware */
    167 static GList *
    168 get_connected_drives (GVolumeMonitor *volume_monitor)
    169 {
    170   GWin32VolumeMonitor *monitor;
    171   HANDLE  find_handle;
    172   BOOL    found;
    173   wchar_t wc_name[MAX_PATH+1];
    174   GList *list = NULL;
    175 
    176   monitor = G_WIN32_VOLUME_MONITOR (volume_monitor);
    177 
    178 #if 0
    179   find_handle = FindFirstVolumeW (wc_name, MAX_PATH);
    180   found = (find_handle != INVALID_HANDLE_VALUE);
    181   while (found)
    182     {
    183       /* I don't know what this code is supposed to do; clearly it now
    184        * does nothing, the returned GList is always NULL. But what was
    185        * this code supposed to be a start of? The volume names that
    186        * the FindFirstVolume/FindNextVolume loop iterates over returns
    187        * device names like
    188        *
    189        *   \Device\HarddiskVolume1
    190        *   \Device\HarddiskVolume2
    191        *   \Device\CdRom0
    192        *
    193        * No DOS devices there, so I don't see the point with the
    194        * QueryDosDevice call below. Probably this code is confusing volumes
    195        * with something else that does contain the mapping from DOS devices
    196        * to volumes.
    197        */
    198       wchar_t wc_dev_name[MAX_PATH+1];
    199       guint trailing = wcslen (wc_name) - 1;
    200 
    201       /* remove trailing backslash and leading \\?\\ */
    202       wc_name[trailing] = L'\0';
    203       if (QueryDosDeviceW (&wc_name[4], wc_dev_name, MAX_PATH))
    204         {
    205           gchar *name = g_utf16_to_utf8 (wc_dev_name, -1, NULL, NULL, NULL);
    206           g_print ("%s\n", name);
    207 	  g_free (name);
    208 	}
    209 
    210       found = FindNextVolumeW (find_handle, wc_name, MAX_PATH);
    211     }
    212   if (find_handle != INVALID_HANDLE_VALUE)
    213     FindVolumeClose (find_handle);
    214 #endif
    215 
    216   return list;
    217 }
    218 
    219 static GVolume *
    220 get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
    221 {
    222   return NULL;
    223 }
    224 
    225 static GMount *
    226 get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
    227 {
    228   return NULL;
    229 }
    230 
    231 static gboolean
    232 is_supported (void)
    233 {
    234   return TRUE;
    235 }
    236 
    237 static GMount *
    238 get_mount_for_mount_path (const char *mount_path,
    239                           GCancellable *cancellable)
    240 {
    241   GWin32Mount *mount;
    242 
    243   /* TODO: Set mountable volume? */
    244   mount = _g_win32_mount_new (NULL, mount_path, NULL);
    245 
    246   return G_MOUNT (mount);
    247 }
    248 
    249 static void
    250 g_win32_volume_monitor_class_init (GWin32VolumeMonitorClass *klass)
    251 {
    252   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
    253   GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
    254   GNativeVolumeMonitorClass *native_class = G_NATIVE_VOLUME_MONITOR_CLASS (klass);
    255 
    256   gobject_class->finalize = g_win32_volume_monitor_finalize;
    257 
    258   monitor_class->get_mounts = get_mounts;
    259   monitor_class->get_volumes = get_volumes;
    260   monitor_class->get_connected_drives = get_connected_drives;
    261   monitor_class->get_volume_for_uuid = get_volume_for_uuid;
    262   monitor_class->get_mount_for_uuid = get_mount_for_uuid;
    263   monitor_class->is_supported = is_supported;
    264 
    265   native_class->get_mount_for_mount_path = get_mount_for_mount_path;
    266 }
    267 
    268 static void
    269 g_win32_volume_monitor_init (GWin32VolumeMonitor *win32_monitor)
    270 {
    271   /* maybe we shoud setup a callback window to listern for WM_DEVICECHANGE ? */
    272 #if 0
    273   unix_monitor->mount_monitor = g_win32_mount_monitor_new ();
    274 
    275   g_signal_connect (win32_monitor->mount_monitor,
    276 		    "mounts-changed", G_CALLBACK (mounts_changed),
    277 		    win32_monitor);
    278 
    279   g_signal_connect (win32_monitor->mount_monitor,
    280 		    "mountpoints-changed", G_CALLBACK (mountpoints_changed),
    281 		    win32_monitor);
    282 
    283   update_volumes (win32_monitor);
    284   update_mounts (win32_monitor);
    285 #endif
    286 }
    287