OSDN Git Service

Add WinMergePluginBase.h (2)
[winmerge-jp/winmerge-jp.git] / Src / PropShell.cpp
index b216d76..10958d4 100644 (file)
@@ -1,5 +1,5 @@
 /** 
- * @file  PropShell.h
+ * @file  PropShell.cpp
  *
  * @brief Implementation file for Shell Options dialog.
  *
@@ -7,12 +7,9 @@
 
 #include "stdafx.h"
 #include "PropShell.h"
-#include "Merge.h"
 #include "RegKey.h"
-#include "OptionsDef.h"
 #include "OptionsMgr.h"
 #include "OptionsPanel.h"
-#include "DDXHelper.h"
 #include "Constants.h"
 #include "Environment.h"
 #include "paths.h"
 static LPCTSTR f_RegValueEnabled = _T("ContextMenuEnabled");
 static LPCTSTR f_RegValuePath = _T("Executable");
 
-static bool IsShellExtensionRegistered()
+static bool IsShellExtensionRegistered(bool peruser)
 {
        HKEY hKey;
-       if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID\\{4E716236-AA30-4C65-B225-D68BBA81E9C2}"), 0, KEY_QUERY_VALUE, &hKey)) {
+#ifdef _WIN64
+       DWORD ulOptions = KEY_QUERY_VALUE;
+#else
+       auto Is64BitWindows = []() { BOOL f64 = FALSE; return IsWow64Process(GetCurrentProcess(), &f64) && f64; };
+       DWORD ulOptions = KEY_QUERY_VALUE | (Is64BitWindows() ? KEY_WOW64_64KEY : 0);
+#endif
+       if (ERROR_SUCCESS == RegOpenKeyEx(peruser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, _T("Software\\Classes\\CLSID\\{4E716236-AA30-4C65-B225-D68BBA81E9C2}"), 0, ulOptions, &hKey))
+       {
                RegCloseKey(hKey);
                return true;
        }
        return false;
 }
 
-static bool RegisterShellExtension(bool unregister)
+static bool RegisterShellExtension(bool unregister, bool peruser)
 {
        TCHAR szSystem32[260] = { 0 };
        TCHAR szSysWow64[260] = { 0 };
        GetSystemDirectory(szSystem32, sizeof(szSystem32) / sizeof(szSystem32[0]));
        GetSystemWow64Directory(szSysWow64, sizeof(szSysWow64) / sizeof(szSysWow64[0]));
 
-       String progpath = env_GetProgPath();
-       String regsvr32 = paths_ConcatPath(szSystem32, _T("regsvr32.exe"));
+       String progpath = env::GetProgPath();
+       String regsvr32 = paths::ConcatPath(szSystem32, _T("regsvr32.exe"));
        String args;
+       String options = (unregister ? _T("/s /u") : _T("/s"));
+       options += peruser ? _T(" /n /i:user") : _T("");
        SHELLEXECUTEINFO sei = { sizeof(sei) };
-       sei.lpVerb = _T("runas");
+       if (!peruser)
+               sei.lpVerb = _T("runas");
        if (szSysWow64[0])
        {
-               args = (unregister ? _T("/s /u \"") : _T("/s \"")) + paths_ConcatPath(progpath, _T("ShellExtensionX64.dll")) + _T("\"");
+               args = options + _T(" \"") + paths::ConcatPath(progpath, _T("ShellExtensionX64.dll")) + _T("\"");
+
                sei.lpFile = regsvr32.c_str();
                sei.lpParameters = args.c_str();
                ShellExecuteEx(&sei);
 
-               regsvr32 = paths_ConcatPath(szSysWow64, _T("regsvr32.exe"));
-               args = (unregister ? _T("/s /u \"") : _T("/s \"")) + paths_ConcatPath(progpath, _T("ShellExtensionU.dll")) + _T("\"");
+               regsvr32 = paths::ConcatPath(szSysWow64, _T("regsvr32.exe"));
+               args = options + _T("\"") + paths::ConcatPath(progpath, _T("ShellExtensionU.dll")) + _T("\"");
                sei.lpFile = regsvr32.c_str();
                sei.lpParameters = args.c_str();
                return !!ShellExecuteEx(&sei);
        }
        else
        {
-               args = (unregister ? _T("/s /u \"") : _T("/s \"")) + paths_ConcatPath(progpath, _T("ShellExtensionU.dll")) + _T("\"");
+               args = options + _T(" \"") + paths::ConcatPath(progpath, _T("ShellExtensionU.dll")) + _T("\"");
                sei.lpFile = regsvr32.c_str();
                sei.lpParameters = args.c_str();
                return !!ShellExecuteEx(&sei);
@@ -82,15 +90,14 @@ PropShell::PropShell(COptionsMgr *optionsMgr)
 
 BOOL PropShell::OnInitDialog()
 {
-       theApp.TranslateDialog(m_hWnd);
-       CPropertyPage::OnInitDialog();
+       OptionsPanel::OnInitDialog();
 
 #ifndef BCM_SETSHIELD
 #define BCM_SETSHIELD            (0x1600/*BCM_FIRST*/ + 0x000C)
 #endif
 
-       ::SendMessage(GetDlgItem(IDC_REGISTER_SHELLEXTENSION)->m_hWnd, BCM_SETSHIELD, 0, TRUE);
-       ::SendMessage(GetDlgItem(IDC_UNREGISTER_SHELLEXTENSION)->m_hWnd, BCM_SETSHIELD, 0, TRUE);
+       SendDlgItemMessage(IDC_REGISTER_SHELLEXTENSION, BCM_SETSHIELD, 0, TRUE);
+       SendDlgItemMessage(IDC_UNREGISTER_SHELLEXTENSION, BCM_SETSHIELD, 0, TRUE);
 
        // Update shell extension checkboxes
        UpdateButtons();
@@ -98,7 +105,7 @@ BOOL PropShell::OnInitDialog()
        AdvancedContextMenuCheck();
        UpdateData(FALSE);
 
-       SetTimer(0, 1000, NULL);
+       SetTimer(0, 1000, nullptr);
 
        return TRUE;  // return TRUE  unless you set the focus to a control
 }
@@ -112,11 +119,13 @@ void PropShell::DoDataExchange(CDataExchange* pDX)
        //}}AFX_DATA_MAP
 }
 
-BEGIN_MESSAGE_MAP(PropShell, CPropertyPage)
+BEGIN_MESSAGE_MAP(PropShell, OptionsPanel)
        //{{AFX_MSG_MAP(PropShell)
        ON_BN_CLICKED(IDC_EXPLORER_CONTEXT, OnAddToExplorer)
        ON_BN_CLICKED(IDC_REGISTER_SHELLEXTENSION, OnRegisterShellExtension)
        ON_BN_CLICKED(IDC_UNREGISTER_SHELLEXTENSION, OnUnregisterShellExtension)
+       ON_BN_CLICKED(IDC_REGISTER_SHELLEXTENSION_PERUSER, OnRegisterShellExtensionPerUser)
+       ON_BN_CLICKED(IDC_UNREGISTER_SHELLEXTENSION_PERUSER, OnUnregisterShellExtensionPerUser)
        ON_WM_TIMER()
        //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
@@ -145,8 +154,8 @@ void PropShell::GetContextRegValues()
        retVal = reg.Open(HKEY_CURRENT_USER, RegDir);
        if (retVal != ERROR_SUCCESS)
        {
-               String msg = string_format(_T("Failed to open registry key HKCU/%s:\n\t%d : %s"),
-                       RegDir, retVal, GetSysError(retVal).c_str());
+               String msg = strutils::format(_T("Failed to open registry key HKCU/%s:\n\t%d : %s"),
+                       RegDir, retVal, GetSysError(retVal));
                LogErrorString(msg);
                return;
        }
@@ -179,8 +188,8 @@ void PropShell::SaveMergePath()
        retVal = reg.Open(HKEY_CURRENT_USER, RegDir);
        if (retVal != ERROR_SUCCESS)
        {
-               String msg = string_format(_T("Failed to open registry key HKCU/%s:\n\t%d : %s"),
-                       RegDir, retVal, GetSysError(retVal).c_str());
+               String msg = strutils::format(_T("Failed to open registry key HKCU/%s:\n\t%d : %s"),
+                       RegDir, retVal, GetSysError(retVal));
                LogErrorString(msg);
                return;
        }
@@ -189,8 +198,8 @@ void PropShell::SaveMergePath()
        retVal = reg.WriteString(f_RegValuePath, temp);
        if (retVal != ERROR_SUCCESS)
        {
-               String msg = string_format(_T("Failed to set registry value %s:\n\t%d : %s"),
-                       f_RegValuePath, retVal, GetSysError(retVal).c_str());
+               String msg = strutils::format(_T("Failed to set registry value %s:\n\t%d : %s"),
+                       f_RegValuePath, retVal, GetSysError(retVal));
                LogErrorString(msg);
        }
 
@@ -209,8 +218,8 @@ void PropShell::SaveMergePath()
        retVal = reg.WriteDword(f_RegValueEnabled, dwContextEnabled);
        if (retVal != ERROR_SUCCESS)
        {
-               String msg = string_format(_T("Failed to set registry value %s to %d:\n\t%d : %s"),
-                       f_RegValueEnabled, dwContextEnabled, retVal, GetSysError(retVal).c_str());
+               String msg = strutils::format(_T("Failed to set registry value %s to %d:\n\t%d : %s"),
+                       f_RegValueEnabled, dwContextEnabled, retVal, GetSysError(retVal));
                LogErrorString(msg);
        }
 }
@@ -227,22 +236,35 @@ void PropShell::AdvancedContextMenuCheck()
 
 void PropShell::UpdateButtons()
 {
-       bool registered = IsShellExtensionRegistered();
-       GetDlgItem(IDC_EXPLORER_CONTEXT)->EnableWindow(registered);
-       GetDlgItem(IDC_REGISTER_SHELLEXTENSION)->EnableWindow(!registered);
-       GetDlgItem(IDC_UNREGISTER_SHELLEXTENSION)->EnableWindow(registered);
-       GetDlgItem(IDC_EXPLORER_ADVANCED)->EnableWindow(
-               GetDlgItem(IDC_EXPLORER_CONTEXT)->IsWindowEnabled() && IsDlgButtonChecked(IDC_EXPLORER_CONTEXT));
+       bool registered = IsShellExtensionRegistered(false);
+       bool registeredPerUser = IsShellExtensionRegistered(true);
+       EnableDlgItem(IDC_EXPLORER_CONTEXT, registered || registeredPerUser);
+       EnableDlgItem(IDC_REGISTER_SHELLEXTENSION, !registered);
+       EnableDlgItem(IDC_UNREGISTER_SHELLEXTENSION, registered);
+       EnableDlgItem(IDC_REGISTER_SHELLEXTENSION_PERUSER, !registeredPerUser);
+       EnableDlgItem(IDC_UNREGISTER_SHELLEXTENSION_PERUSER, registeredPerUser);
+       EnableDlgItem(IDC_EXPLORER_ADVANCED, 
+               (registered || registeredPerUser) && IsDlgButtonChecked(IDC_EXPLORER_CONTEXT));
 }
 
 void PropShell::OnRegisterShellExtension()
 {
-       RegisterShellExtension(false);
+       RegisterShellExtension(false, false);
 }
 
 void PropShell::OnUnregisterShellExtension()
 {
-       RegisterShellExtension(true);
+       RegisterShellExtension(true, false);
+}
+
+void PropShell::OnRegisterShellExtensionPerUser()
+{
+       RegisterShellExtension(false, true);
+}
+
+void PropShell::OnUnregisterShellExtensionPerUser()
+{
+       RegisterShellExtension(true, true);
 }
 
 void PropShell::OnTimer(UINT_PTR nIDEvent)