From 72485b75682dc7f0ae6af52d86d41649c2d277b5 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sun, 11 Dec 2011 23:38:16 +0000 Subject: [PATCH] [misc] disable new drive notification while app is running * new drive notifications from explorer are annoying * use Local Group Policy to temporarily disable them * also fixed missing SetupDiDestroyDeviceInfoList call --- src/rufus.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/rufus.h | 6 ++- src/rufus.rc | 12 ++--- 3 files changed, 160 insertions(+), 8 deletions(-) diff --git a/src/rufus.c b/src/rufus.c index bc810b55..898a6244 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -556,6 +556,7 @@ static BOOL GetUSBDevices(void) } } } + SetupDiDestroyDeviceInfoList(dev_info); IGNORE_RETVAL(ComboBox_SetCurSel(hDeviceList, 0)); SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_DEVICE, 0); SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_FILESYSTEM, @@ -659,6 +660,146 @@ void UpdateProgress(int op, float percent) SendMessage(hProgress, PBM_SETPOS, (WPARAM)pos, 0); } +/* + * Set or restore a Local Group Policy DWORD key indexed by szPath/SzPolicy + */ +typedef enum _GROUP_POLICY_OBJECT_TYPE { + GPOTypeLocal = 0,GPOTypeRemote,GPOTypeDS +} GROUP_POLICY_OBJECT_TYPE,*PGROUP_POLICY_OBJECT_TYPE; + +#define REGISTRY_EXTENSION_GUID { 0x35378EAC,0x683F,0x11D2, {0xA8,0x9A,0x00,0xC0,0x4F,0xBB,0xCF,0xA2} } +#define GPO_OPEN_LOAD_REGISTRY 0x00000001 +#define GPO_SECTION_MACHINE 2 + +#undef INTERFACE +#define INTERFACE IGroupPolicyObject + DECLARE_INTERFACE_(IGroupPolicyObject,IUnknown) { + STDMETHOD(QueryInterface) (THIS_ REFIID riid,LPVOID *ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + STDMETHOD(New) (THIS_ LPOLESTR pszDomainName,LPOLESTR pszDisplayName,DWORD dwFlags) PURE; + STDMETHOD(OpenDSGPO) (THIS_ LPOLESTR pszPath,DWORD dwFlags) PURE; + STDMETHOD(OpenLocalMachineGPO) (THIS_ DWORD dwFlags) PURE; + STDMETHOD(OpenRemoteMachineGPO) (THIS_ LPOLESTR pszComputerName,DWORD dwFlags) PURE; + STDMETHOD(Save) (THIS_ BOOL bMachine, BOOL bAdd,GUID *pGuidExtension,GUID *pGuid) PURE; + STDMETHOD(Delete) (THIS) PURE; + STDMETHOD(GetName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; + STDMETHOD(GetDisplayName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; + STDMETHOD(SetDisplayName) (THIS_ LPOLESTR pszName) PURE; + STDMETHOD(GetPath) (THIS_ LPOLESTR pszPath,int cchMaxPath) PURE; + STDMETHOD(GetDSPath) (THIS_ DWORD dwSection,LPOLESTR pszPath,int cchMaxPath) PURE; + STDMETHOD(GetFileSysPath) (THIS_ DWORD dwSection,LPOLESTR pszPath,int cchMaxPath) PURE; + STDMETHOD(GetRegistryKey) (THIS_ DWORD dwSection,HKEY *hKey) PURE; + STDMETHOD(GetOptions) (THIS_ DWORD *dwOptions) PURE; + STDMETHOD(SetOptions) (THIS_ DWORD dwOptions,DWORD dwMask) PURE; + STDMETHOD(GetType) (THIS_ GROUP_POLICY_OBJECT_TYPE *gpoType) PURE; + STDMETHOD(GetMachineName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; + STDMETHOD(GetPropertySheetPages) (THIS_ HPROPSHEETPAGE **hPages,UINT *uPageCount) PURE; + }; + typedef IGroupPolicyObject *LPGROUPPOLICYOBJECT; + +BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwValue) +{ + OSVERSIONINFO os_version; + LONG r; + DWORD disp, regtype, val, val_size=sizeof(DWORD); + HRESULT hr; + IGroupPolicyObject* pLGPO; + // These statuc values are used to restore initial state + static BOOL key_was_present = FALSE; + static DWORD original_val; + HKEY path_key = NULL, policy_key = NULL; + // MSVC is finicky about these ones => redefine them + const IID my_IID_IGroupPolicyObject = + { 0xea502723, 0xa23d, 0x11d1, { 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } }; + const IID my_CLSID_GroupPolicyObject = + { 0xea502722, 0xa23d, 0x11d1, { 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } }; + GUID ext_guid = REGISTRY_EXTENSION_GUID; + // Can be anything really + GUID snap_guid = { 0x3D271CFC, 0x2BC6, 0x4AC2, {0xB6, 0x33, 0x3B, 0xDF, 0xF5, 0xBD, 0xAB, 0x2A} }; + + // Vista or later + // TODO: should we do this on XP too? + memset(&os_version, 0, sizeof(OSVERSIONINFO)); + os_version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if ((GetVersionEx(&os_version) != 0) && (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)) { + if (os_version.dwMajorVersion < 6) { + return TRUE; + } + } + + // We need an IGroupPolicyObject instance to set a Local Group Policy + hr = CoCreateInstance(&my_CLSID_GroupPolicyObject, NULL, CLSCTX_INPROC_SERVER, &my_IID_IGroupPolicyObject, (LPVOID*)&pLGPO); + if (FAILED(hr)) { + uprintf("SetLGP: CoCreateInstance failed; hr = %x\n", hr); + goto error; + } + + hr = pLGPO->lpVtbl->OpenLocalMachineGPO(pLGPO, GPO_OPEN_LOAD_REGISTRY); + if (FAILED(hr)) { + uprintf("SetLGP: OpenLocalMachineGPO failed - error %x\n", hr); + goto error; + } + + hr = pLGPO->lpVtbl->GetRegistryKey(pLGPO, GPO_SECTION_MACHINE, &path_key); + if (FAILED(hr)) { + uprintf("SetLGP: GetRegistryKey failed - error %x\n", hr); + goto error; + } + + // The DisableSystemRestore is set in Software\Policies\Microsoft\Windows\DeviceInstall\Settings + r = RegCreateKeyExA(path_key, szPath, 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, + NULL, &policy_key, &disp); + if (r != ERROR_SUCCESS) { + uprintf("SetLGP: Failed to open LGPO path %s - error %x\n", szPath, hr); + goto error; + } + + if ((disp == REG_OPENED_EXISTING_KEY) && (!bRestore) && (!key_was_present)) { + // backup existing value for restore + key_was_present = TRUE; + regtype = REG_DWORD; + r = RegQueryValueExA(policy_key, szPolicy, NULL, ®type, (LPBYTE)&original_val, &val_size); + if (r == ERROR_FILE_NOT_FOUND) { + // The Key exists but not its value, which is OK + key_was_present = FALSE; + } else if (r != ERROR_SUCCESS) { + uprintf("SetLGP: Failed to read original %s policy value - error %x\n", szPolicy, r); + } + } + + if ((!bRestore) || (key_was_present)) { + val = (bRestore)?original_val:dwValue; + r = RegSetValueExA(policy_key, szPolicy, 0, REG_DWORD, (BYTE*)&val, sizeof(val)); + } else { + r = RegDeleteValueA(policy_key, szPolicy); + } + if (r != ERROR_SUCCESS) { + uprintf("SetLGP: RegSetValueEx / RegDeleteValue failed - error %x\n", r); + } + RegCloseKey(policy_key); + policy_key = NULL; + + // Apply policy + hr = pLGPO->lpVtbl->Save(pLGPO, TRUE, (bRestore)?FALSE:TRUE, &ext_guid, &snap_guid); + if (r != S_OK) { + uprintf("SetLGP: Unable to apply %s policy - error %x\n", szPolicy, hr); + goto error; + } else { + uprintf("SetLGP: Successfully %s %s policy\n", (bRestore)?"restored":"disabled", szPolicy); + } + + RegCloseKey(path_key); + pLGPO->lpVtbl->Release(pLGPO); + return TRUE; + +error: + if (path_key != NULL) RegCloseKey(path_key); + if (policy_key != NULL) RegCloseKey(policy_key); + if (pLGPO != NULL) pLGPO->lpVtbl->Release(pLGPO); + return FALSE; +} + /* * Toggle controls according to operation */ @@ -917,6 +1058,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine // Initialize COM for folder selection CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); +#ifdef DISABLE_AUTORUN + // We use local group policies rather than direct registry manipulation + // 0x9e disables removable and fixed drive notifications + SetLGP(FALSE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutorun", 0x9e); +#endif + // Create the main Window if ( (hDlg = CreateDialogA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG), NULL, MainCallback)) == NULL ) { MessageBoxA(NULL, "Could not create Window", "DialogBox failure", MB_ICONSTOP); @@ -933,6 +1080,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine } out: +#ifdef DISABLE_AUTORUN + SetLGP(TRUE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutorun", 0); +#endif CloseHandle(mutex); uprintf("*** RUFUS EXIT ***\n"); diff --git a/src/rufus.h b/src/rufus.h index aea08af0..ab4aa0b5 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -16,11 +16,13 @@ * along with this program. If not, see . */ #include -#include // for DISK_GEOMETRY +#include // for DISK_GEOMETRY #pragma once -#define RUFUS_DEBUG +/* Program options */ +#define RUFUS_DEBUG // print debug info to Debug facility (use debugview to consult) +#define DISABLE_AUTORUN // disable new USB drive notification from explorer when application is running #define STR_NO_LABEL "NO_LABEL" #define RUFUS_CANCELBOX_TITLE "Rufus - Cancellation" diff --git a/src/rufus.rc b/src/rufus.rc index b11b5d83..576554bd 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 278 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.0.2.88 (Beta)" +CAPTION "Rufus v1.0.2.89 (Beta)" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,236,50,14 @@ -64,7 +64,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "http://rufus.akeo.ie",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.0.2 (Build 88)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.0.2 (Build 89)",IDC_STATIC,46,19,78,8 PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 @@ -163,8 +163,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,2,88 - PRODUCTVERSION 1,0,2,88 + FILEVERSION 1,0,2,89 + PRODUCTVERSION 1,0,2,89 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -181,13 +181,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.0.2.88" + VALUE "FileVersion", "1.0.2.89" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.0.2.88" + VALUE "ProductVersion", "1.0.2.89" END END BLOCK "VarFileInfo"