summaryrefslogtreecommitdiff
path: root/catchcopy-windows-explorer-plugin/Reg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'catchcopy-windows-explorer-plugin/Reg.cpp')
-rwxr-xr-xcatchcopy-windows-explorer-plugin/Reg.cpp403
1 files changed, 403 insertions, 0 deletions
diff --git a/catchcopy-windows-explorer-plugin/Reg.cpp b/catchcopy-windows-explorer-plugin/Reg.cpp
new file mode 100755
index 0000000..37f7cc1
--- /dev/null
+++ b/catchcopy-windows-explorer-plugin/Reg.cpp
@@ -0,0 +1,403 @@
+#include "Reg.h"
+#include <strsafe.h>
+
+//
+// FUNCTION: SetHKCRRegistryKeyAndValue
+//
+// PURPOSE: The function creates a HKCR registry key and sets the specified
+// registry value.
+//
+// PARAMETERS:
+// * pszSubKey - specifies the registry key under HKCR. If the key does not
+// exist, the function will create the registry key.
+// * pszValueName - specifies the registry value to be set. If pszValueName
+// is NULL, the function will set the default value.
+// * pszData - specifies the string data of the registry value.
+//
+// RETURN VALUE:
+// If the function succeeds, it returns S_OK. Otherwise, it returns an
+// HRESULT error code.
+//
+HRESULT SetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName,
+ PCWSTR pszData)
+{
+ HRESULT hr;
+ HKEY hKey = NULL;
+
+ // Creates the specified registry key. If the key already exists, the
+ // function opens it.
+ hr = HRESULT_FROM_WIN32(RegCreateKeyEx(
+ #ifdef CATCHCOPY_ROOT_MODE
+ HKEY_CLASSES_ROOT
+ #else
+ HKEY_CURRENT_USER
+ #endif
+ , pszSubKey, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &hKey, NULL));
+
+ if (SUCCEEDED(hr))
+ {
+ if (pszData != NULL)
+ {
+ // Set the specified value of the key.
+ DWORD cbData = lstrlen(pszData) * sizeof(*pszData);
+ hr = HRESULT_FROM_WIN32(RegSetValueEx(hKey, pszValueName, 0,
+ REG_SZ, reinterpret_cast<const BYTE *>(pszData), cbData));
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ return hr;
+}
+
+LONG RecursiveDeleteKey(HKEY hKeyParent, PCWSTR szKeyChild)
+{
+ // Open the child.
+ HKEY hKeyChild ;
+ LONG lRes = RegOpenKeyEx(hKeyParent, szKeyChild, 0,
+ KEY_ALL_ACCESS | KEY_WOW64_64KEY, &hKeyChild) ;
+ if (lRes != ERROR_SUCCESS)
+ {
+ return lRes ;
+ }
+ // Enumerate all of the decendents of this child.
+ FILETIME time ;
+ wchar_t szBuffer[MAX_PATH];
+ DWORD dwSize = MAX_PATH ;
+ while (RegEnumKeyEx(hKeyChild, 0, (LPWSTR)szBuffer, &dwSize, NULL,
+ NULL, NULL, &time) == ERROR_SUCCESS)
+ {
+ // Delete the decendents of this child.
+ lRes = RecursiveDeleteKey(hKeyChild, (PCWSTR)szBuffer) ;
+ if (lRes != ERROR_SUCCESS)
+ {
+ // Cleanup before exiting.
+ RegCloseKey(hKeyChild) ;
+ return lRes;
+ }
+ dwSize = MAX_PATH ;
+ }
+
+ // Close the child.
+ RegCloseKey(hKeyChild) ;
+
+ // Delete this child.
+ return RegDeleteKey(hKeyParent, szKeyChild) ;
+}
+
+//
+// FUNCTION: GetHKCRRegistryKeyAndValue
+//
+// PURPOSE: The function opens a HKCR registry key and gets the data for the
+// specified registry value name.
+//
+// PARAMETERS:
+// * pszSubKey - specifies the registry key under HKCR. If the key does not
+// exist, the function returns an error.
+// * pszValueName - specifies the registry value to be retrieved. If
+// pszValueName is NULL, the function will get the default value.
+// * pszData - a pointer to a buffer that receives the value's string data.
+// * cbData - specifies the size of the buffer in bytes.
+//
+// RETURN VALUE:
+// If the function succeeds, it returns S_OK. Otherwise, it returns an
+// HRESULT error code. For example, if the specified registry key does not
+// exist or the data for the specified value name was not set, the function
+// returns COR_E_FILENOTFOUND (0x80070002).
+//
+HRESULT GetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName,
+ PWSTR pszData, DWORD cbData)
+{
+ HRESULT hr;
+ HKEY hKey = NULL;
+
+ // Try to open the specified registry key.
+ hr = HRESULT_FROM_WIN32(RegOpenKeyEx(
+ #ifdef CATCHCOPY_ROOT_MODE
+ HKEY_CLASSES_ROOT
+ #else
+ HKEY_CURRENT_USER
+ #endif
+ , pszSubKey, 0,
+ KEY_READ, &hKey));
+
+ if (SUCCEEDED(hr))
+ {
+ // Get the data for the specified value name.
+ hr = HRESULT_FROM_WIN32(RegQueryValueEx(hKey, pszValueName, NULL,
+ NULL, reinterpret_cast<LPBYTE>(pszData), &cbData));
+
+ RegCloseKey(hKey);
+ }
+
+ return hr;
+}
+
+//
+// FUNCTION: RegisterInprocServer
+//
+// PURPOSE: Register the in-process component in the registry.
+//
+// PARAMETERS:
+// * pszModule - Path of the module that contains the component
+// * clsid - Class ID of the component
+// * pszFriendlyName - Friendly name
+// * pszThreadModel - Threading model
+//
+// NOTE: The function creates the HKCR\CLSID\{<CLSID>} key in the registry.
+//
+// HKCR
+// {
+// NoRemove CLSID
+// {
+// ForceRemove {<CLSID>} = s '<Friendly Name>'
+// {
+// InprocServer32 = s '%MODULE%'
+// {
+// val ThreadingModel = s '<Thread Model>'
+// }
+// }
+// }
+// }
+//
+HRESULT RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid, PCWSTR pszFriendlyName, PCWSTR pszThreadModel)
+{
+ if (pszModule == NULL || pszThreadModel == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // Create the HKCR\CLSID\{<CLSID>} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"CLSID\\%s"
+ #else
+ L"Software\\Classes\\CLSID\\%s"
+ #endif
+ , szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszFriendlyName);
+
+ // Create the HKCR\CLSID\{<CLSID>}\InprocServer32 key.
+ if (SUCCEEDED(hr))
+ {
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"CLSID\\%s\\InprocServer32"
+ #else
+ L"Software\\Classes\\CLSID\\%s\\InprocServer32"
+ #endif
+ , szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ // Set the default value of the InprocServer32 key to the
+ // path of the COM module.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszModule);
+ if (SUCCEEDED(hr))
+ {
+ // Set the threading model of the component.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, L"ThreadingModel", pszThreadModel);
+ }
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+//
+// FUNCTION: UnregisterInprocServer
+//
+// PURPOSE: Unegister the in-process component in the registry.
+//
+// PARAMETERS:
+// * clsid - Class ID of the component
+//
+// NOTE: The function deletes the HKCR\CLSID\{<CLSID>} key in the registry.
+//
+HRESULT UnregisterInprocServer(const CLSID& clsid)
+{
+ HRESULT hr = S_OK;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // Delete the HKCR\CLSID\{<CLSID>} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"CLSID\\%s"
+ #else
+ L"Software\\Classes\\CLSID\\%s"
+ #endif
+ , szCLSID);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = HRESULT_FROM_WIN32(RecursiveDeleteKey(
+ #ifdef CATCHCOPY_ROOT_MODE
+ HKEY_CLASSES_ROOT
+ #else
+ HKEY_CURRENT_USER
+ #endif
+ , szSubkey));
+ }
+
+ return hr;
+}
+//
+// FUNCTION: RegisterShellExtContextMenuHandler
+//
+// PURPOSE: Register the context menu handler.
+//
+// PARAMETERS:
+// * pszFileType - The file type that the context menu handler is
+// associated with. For example, '*' means all file types; '.txt' means
+// all .txt files. The parameter must not be NULL.
+// * clsid - Class ID of the component
+// * pszFriendlyName - Friendly name
+//
+// NOTE: The function creates the following key in the registry.
+//
+// HKCR
+// {
+// NoRemove <File Type>
+// {
+// NoRemove shellex
+// {
+// NoRemove ContextMenuHandlers
+// {
+// {<CLSID>} = s '<Friendly Name>'
+// }
+// }
+// }
+// }
+//
+HRESULT RegisterShellExtContextMenuHandler(
+ PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName)
+{
+ if (pszFileType == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // If pszFileType starts with '.', try to read the default value of the
+ // HKCR\<File Type> key which contains the ProgID to which the file type
+ // is linked.
+ if (*pszFileType == L'.')
+ {
+ wchar_t szDefaultVal[260];
+ hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
+ sizeof(szDefaultVal));
+
+ // If the key exists and its default value is not empty, use the
+ // ProgID as the file type.
+ if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
+ {
+ pszFileType = szDefaultVal;
+ }
+ }
+
+ // Create the key HKCR\<File Type>\shellex\DragDropHandlers\{<CLSID>}
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"%s\\shellex\\DragDropHandlers\\%s"
+ #else
+ L"Software\\Classes\\%s\\shellex\\DragDropHandlers\\%s"
+ #endif
+ , pszFileType, szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ // Set the default value of the key.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszFriendlyName);
+ }
+
+ return hr;
+}
+
+
+//
+// FUNCTION: UnregisterShellExtContextMenuHandler
+//
+// PURPOSE: Unregister the context menu handler.
+//
+// PARAMETERS:
+// * pszFileType - The file type that the context menu handler is
+// associated with. For example, '*' means all file types; '.txt' means
+// all .txt files. The parameter must not be NULL.
+// * clsid - Class ID of the component
+//
+// NOTE: The function removes the {<CLSID>} key under
+// HKCR\<File Type>\shellex\ContextMenuHandlers in the registry.
+//
+HRESULT UnregisterShellExtContextMenuHandler(
+ PCWSTR pszFileType, const CLSID& clsid)
+{
+ if (pszFileType == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // If pszFileType starts with '.', try to read the default value of the
+ // HKCR\<File Type> key which contains the ProgID to which the file type
+ // is linked.
+ if (*pszFileType == L'.')
+ {
+ wchar_t szDefaultVal[260];
+ hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
+ sizeof(szDefaultVal));
+
+ // If the key exists and its default value is not empty, use the
+ // ProgID as the file type.
+ if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
+ {
+ pszFileType = szDefaultVal;
+ }
+ }
+
+ // Remove the HKCR\<File Type>\shellex\DragDropHandlers\{<CLSID>} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"%s\\shellex\\DragDropHandlers\\%s"
+ #else
+ L"Software\\Classes\\%s\\shellex\\DragDropHandlers\\%s"
+ #endif
+ , pszFileType, szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ hr = HRESULT_FROM_WIN32(RecursiveDeleteKey(
+ #ifdef CATCHCOPY_ROOT_MODE
+ HKEY_CLASSES_ROOT
+ #else
+ HKEY_CURRENT_USER
+ #endif
+ , szSubkey));
+ }
+
+ return hr;
+}