| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | /* GIO - GLib Input, Output and Streaming Library
 | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * Copyright (C) 2006-2007 Red Hat, Inc. | 
					
						
							|  |  |  |  * Copyright (C) 2008 Hans Breuer | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2022-05-18 09:12:45 +01:00
										 |  |  |  * SPDX-License-Identifier: LGPL-2.1-or-later | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2017-05-27 18:21:30 +02:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General | 
					
						
							| 
									
										
										
										
											2014-01-23 12:58:29 +01:00
										 |  |  |  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Author: Alexander Larsson <alexl@redhat.com> | 
					
						
							|  |  |  |  *         David Zeuthen <davidz@redhat.com> | 
					
						
							|  |  |  |  *         Hans Breuer <hans@breuer.org> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-22 15:10:51 +00:00
										 |  |  | #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <glib.h>
 | 
					
						
							|  |  |  | #include "glibintl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gwin32volumemonitor.h"
 | 
					
						
							|  |  |  | #include "gwin32mount.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-02 01:54:16 +00:00
										 |  |  | #include "gmount.h"
 | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | #include "giomodule.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <windows.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _GWin32VolumeMonitor { | 
					
						
							|  |  |  |   GNativeVolumeMonitor parent; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define g_win32_volume_monitor_get_type _g_win32_volume_monitor_get_type
 | 
					
						
							|  |  |  | G_DEFINE_TYPE_WITH_CODE (GWin32VolumeMonitor, g_win32_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR, | 
					
						
							|  |  |  |                          g_io_extension_point_implement (G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME, | 
					
						
							|  |  |  | 							 g_define_type_id, | 
					
						
							|  |  |  | 							 "win32", | 
					
						
							|  |  |  | 							 0)); | 
					
						
							|  |  |  | 							  | 
					
						
							| 
									
										
										
										
											2014-08-18 14:08:41 +02:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |  * get_viewable_logical_drives: | 
					
						
							| 
									
										
										
										
											2009-11-29 22:54:16 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |  * Returns the list of logical and viewable drives as defined by | 
					
						
							|  |  |  |  * GetLogicalDrives() and the registry keys | 
					
						
							|  |  |  |  * Software\Microsoft\Windows\CurrentVersion\Policies\Explorer under | 
					
						
							|  |  |  |  * HKLM or HKCU. If neither key exists the result of | 
					
						
							|  |  |  |  * GetLogicalDrives() is returned. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-02-19 19:35:23 -05:00
										 |  |  |  * Returns: bitmask with same meaning as returned by GetLogicalDrives() | 
					
						
							| 
									
										
										
										
											2009-11-29 22:54:16 -05:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | static guint32  | 
					
						
							|  |  |  | get_viewable_logical_drives (void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   guint viewable_drives = GetLogicalDrives (); | 
					
						
							|  |  |  |   HKEY key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DWORD var_type = REG_DWORD; //the value's a REG_DWORD type
 | 
					
						
							|  |  |  |   DWORD no_drives_size = 4; | 
					
						
							|  |  |  |   DWORD no_drives; | 
					
						
							|  |  |  |   gboolean hklm_present = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-15 22:25:08 +02:00
										 |  |  |   if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, | 
					
						
							|  |  |  | 		     L"Software\\Microsoft\\Windows\\" | 
					
						
							|  |  |  | 		     L"CurrentVersion\\Policies\\Explorer", | 
					
						
							|  |  |  | 		     0, KEY_READ, &key) == ERROR_SUCCESS) | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-08-15 22:25:08 +02:00
										 |  |  |       if (RegQueryValueExW (key, L"NoDrives", NULL, &var_type, | 
					
						
							|  |  |  | 			    (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS) | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  /* We need the bits that are set in viewable_drives, and
 | 
					
						
							|  |  |  | 	   * unset in no_drives. | 
					
						
							|  |  |  | 	   */ | 
					
						
							|  |  |  | 	  viewable_drives = viewable_drives & ~no_drives; | 
					
						
							|  |  |  | 	  hklm_present = TRUE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       RegCloseKey (key); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If the key is present in HKLM then the one in HKCU should be ignored */ | 
					
						
							|  |  |  |   if (!hklm_present) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-08-15 22:25:08 +02:00
										 |  |  |       if (RegOpenKeyExW (HKEY_CURRENT_USER, | 
					
						
							|  |  |  | 			 L"Software\\Microsoft\\Windows\\" | 
					
						
							|  |  |  | 			 L"CurrentVersion\\Policies\\Explorer", | 
					
						
							|  |  |  | 			 0, KEY_READ, &key) == ERROR_SUCCESS) | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-08-15 22:25:08 +02:00
										 |  |  | 	  if (RegQueryValueExW (key, L"NoDrives", NULL, &var_type, | 
					
						
							|  |  |  | 			        (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS) | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      viewable_drives = viewable_drives & ~no_drives; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  RegCloseKey (key); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return viewable_drives;  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 14:02:30 +01:00
										 |  |  | /* deliver accessible (aka 'mounted') volumes */ | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | static GList * | 
					
						
							|  |  |  | get_mounts (GVolumeMonitor *volume_monitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DWORD   drives; | 
					
						
							|  |  |  |   gchar   drive[4] = "A:\\"; | 
					
						
							| 
									
										
										
										
											2019-02-13 13:55:11 +00:00
										 |  |  |   GQueue  queue = G_QUEUE_INIT; | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   drives = get_viewable_logical_drives (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!drives) | 
					
						
							|  |  |  |     g_warning ("get_viewable_logical_drives failed."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (drives && drive[0] <= 'Z') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (drives & 1) | 
					
						
							| 
									
										
										
										
											2019-02-13 13:55:11 +00:00
										 |  |  |         g_queue_push_tail (&queue, _g_win32_mount_new (volume_monitor, drive, NULL)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |       drives >>= 1; | 
					
						
							|  |  |  |       drive[0]++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-02-13 13:55:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return g_steal_pointer (&queue.head); | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* actually 'mounting' volumes is out of GIOs business on win32, so no volumes are delivered either */ | 
					
						
							|  |  |  | static GList * | 
					
						
							|  |  |  | get_volumes (GVolumeMonitor *volume_monitor) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-11-10 10:58:19 -05:00
										 |  |  |   return NULL; | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* real hardware */ | 
					
						
							|  |  |  | static GList * | 
					
						
							|  |  |  | get_connected_drives (GVolumeMonitor *volume_monitor) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-11-10 10:58:19 -05:00
										 |  |  |   GList *list = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |   HANDLE  find_handle; | 
					
						
							|  |  |  |   BOOL    found; | 
					
						
							|  |  |  |   wchar_t wc_name[MAX_PATH+1]; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   find_handle = FindFirstVolumeW (wc_name, MAX_PATH); | 
					
						
							|  |  |  |   found = (find_handle != INVALID_HANDLE_VALUE); | 
					
						
							|  |  |  |   while (found) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-08-08 05:36:56 +00:00
										 |  |  |       /* I don't know what this code is supposed to do; clearly it now
 | 
					
						
							|  |  |  |        * does nothing, the returned GList is always NULL. But what was | 
					
						
							|  |  |  |        * this code supposed to be a start of? The volume names that | 
					
						
							|  |  |  |        * the FindFirstVolume/FindNextVolume loop iterates over returns | 
					
						
							|  |  |  |        * device names like | 
					
						
							|  |  |  |        * | 
					
						
							|  |  |  |        *   \Device\HarddiskVolume1 | 
					
						
							|  |  |  |        *   \Device\HarddiskVolume2 | 
					
						
							|  |  |  |        *   \Device\CdRom0 | 
					
						
							|  |  |  |        * | 
					
						
							|  |  |  |        * No DOS devices there, so I don't see the point with the | 
					
						
							|  |  |  |        * QueryDosDevice call below. Probably this code is confusing volumes | 
					
						
							|  |  |  |        * with something else that does contain the mapping from DOS devices | 
					
						
							|  |  |  |        * to volumes. | 
					
						
							|  |  |  |        */ | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |       wchar_t wc_dev_name[MAX_PATH+1]; | 
					
						
							| 
									
										
										
										
											2008-08-08 05:36:56 +00:00
										 |  |  |       guint trailing = wcslen (wc_name) - 1; | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* remove trailing backslash and leading \\?\\ */ | 
					
						
							|  |  |  |       wc_name[trailing] = L'\0'; | 
					
						
							| 
									
										
										
										
											2008-08-08 05:36:56 +00:00
										 |  |  |       if (QueryDosDeviceW (&wc_name[4], wc_dev_name, MAX_PATH)) | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |           gchar *name = g_utf16_to_utf8 (wc_dev_name, -1, NULL, NULL, NULL); | 
					
						
							|  |  |  |           g_print ("%s\n", name); | 
					
						
							|  |  |  | 	  g_free (name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       found = FindNextVolumeW (find_handle, wc_name, MAX_PATH); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (find_handle != INVALID_HANDLE_VALUE) | 
					
						
							|  |  |  |     FindVolumeClose (find_handle); | 
					
						
							| 
									
										
										
										
											2008-08-08 05:36:56 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GVolume * | 
					
						
							|  |  |  | get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GMount * | 
					
						
							|  |  |  | get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | is_supported (void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GMount * | 
					
						
							|  |  |  | get_mount_for_mount_path (const char *mount_path, | 
					
						
							|  |  |  |                           GCancellable *cancellable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GWin32Mount *mount; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* TODO: Set mountable volume? */ | 
					
						
							|  |  |  |   mount = _g_win32_mount_new (NULL, mount_path, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return G_MOUNT (mount); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_win32_volume_monitor_class_init (GWin32VolumeMonitorClass *klass) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass); | 
					
						
							|  |  |  |   GNativeVolumeMonitorClass *native_class = G_NATIVE_VOLUME_MONITOR_CLASS (klass); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   monitor_class->get_mounts = get_mounts; | 
					
						
							|  |  |  |   monitor_class->get_volumes = get_volumes; | 
					
						
							|  |  |  |   monitor_class->get_connected_drives = get_connected_drives; | 
					
						
							|  |  |  |   monitor_class->get_volume_for_uuid = get_volume_for_uuid; | 
					
						
							|  |  |  |   monitor_class->get_mount_for_uuid = get_mount_for_uuid; | 
					
						
							|  |  |  |   monitor_class->is_supported = is_supported; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   native_class->get_mount_for_mount_path = get_mount_for_mount_path; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_win32_volume_monitor_init (GWin32VolumeMonitor *win32_monitor) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-12 14:02:30 +01:00
										 |  |  |   /* maybe we should setup a callback window to listen for WM_DEVICECHANGE ? */ | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  |   unix_monitor->mount_monitor = g_win32_mount_monitor_new (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_signal_connect (win32_monitor->mount_monitor, | 
					
						
							| 
									
										
										
										
											2008-08-11 19:45:08 +00:00
										 |  |  | 		    "mounts-changed", G_CALLBACK (mounts_changed), | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | 		    win32_monitor); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   g_signal_connect (win32_monitor->mount_monitor, | 
					
						
							| 
									
										
										
										
											2008-08-11 19:45:08 +00:00
										 |  |  | 		    "mountpoints-changed", G_CALLBACK (mountpoints_changed), | 
					
						
							| 
									
										
										
										
											2008-06-17 21:40:04 +00:00
										 |  |  | 		    win32_monitor); | 
					
						
							|  |  |  | 		     | 
					
						
							|  |  |  |   update_volumes (win32_monitor); | 
					
						
							|  |  |  |   update_mounts (win32_monitor); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } |