Skip to content

Commit

Permalink
partly fix issue with errant .md4 file association
Browse files Browse the repository at this point in the history
Recent versions of Windows make it difficult to remove associations from
programs which still exist. This update removes HashCheck as an option
for .md4 files for new users, but users who have previously selected it
as the default for .md4 files will remain unfortunately unchanged.
  • Loading branch information
gurnec committed Aug 31, 2016
1 parent 5c3bb24 commit 122a96f
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 28 deletions.
62 changes: 44 additions & 18 deletions HashCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
#include "libs/Wow64.h"
#include <Strsafe.h>

// Table of formerly supported Hash file extensions to be removed during install
LPCTSTR szFormerHashExtsTab[] = {
_T(".md4")
};

// Bookkeeping globals (declared as extern in globals.h)
HMODULE g_hModThisDll;
CREF g_cRefThisDll;
Expand Down Expand Up @@ -98,35 +103,35 @@ STDAPI DllRegisterServerEx( LPCTSTR lpszModuleName )
TCHAR szBuffer[MAX_PATH << 1];

// Register class
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("CLSID\\%s"), CLSID_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("CLSID\\%s"), CLSID_STR_HashCheck, TRUE))
{
RegSetSZ(hKey, NULL, CLSNAME_STR_HashCheck);
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\InprocServer32"), CLSID_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\InprocServer32"), CLSID_STR_HashCheck, TRUE))
{
RegSetSZ(hKey, NULL, lpszModuleName);
RegSetSZ(hKey, TEXT("ThreadingModel"), TEXT("Apartment"));
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

// Register context menu handler
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("AllFileSystemObjects\\ShellEx\\ContextMenuHandlers\\%s"), CLSNAME_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("AllFileSystemObjects\\ShellEx\\ContextMenuHandlers\\%s"), CLSNAME_STR_HashCheck, TRUE))
{
RegSetSZ(hKey, NULL, CLSID_STR_HashCheck);
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

// Register property sheet handler
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("AllFileSystemObjects\\ShellEx\\PropertySheetHandlers\\%s"), CLSNAME_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("AllFileSystemObjects\\ShellEx\\PropertySheetHandlers\\%s"), CLSNAME_STR_HashCheck, TRUE))
{
RegSetSZ(hKey, NULL, CLSID_STR_HashCheck);
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

// Register the HashCheck program ID
if (hKey = RegOpen(HKEY_CLASSES_ROOT, PROGID_STR_HashCheck, NULL))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, PROGID_STR_HashCheck, NULL, TRUE))
{
LoadString(g_hModThisDll, IDS_FILETYPE_DESC, szBuffer, countof(szBuffer));
RegSetSZ(hKey, NULL, szBuffer);
Expand All @@ -140,35 +145,35 @@ STDAPI DllRegisterServerEx( LPCTSTR lpszModuleName )
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\DefaultIcon"), PROGID_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\DefaultIcon"), PROGID_STR_HashCheck, TRUE))
{
StringCchPrintf(szBuffer, countof(szBuffer), TEXT("%s,-%u"), lpszModuleName, IDI_FILETYPE);
RegSetSZ(hKey, NULL, szBuffer);
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\shell\\open\\DropTarget"), PROGID_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\shell\\open\\DropTarget"), PROGID_STR_HashCheck, TRUE))
{
// The DropTarget will be the primary way in which we are invoked
RegSetSZ(hKey, TEXT("CLSID"), CLSID_STR_HashCheck);
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\shell\\open\\command"), PROGID_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\shell\\open\\command"), PROGID_STR_HashCheck, TRUE))
{
// This is a legacy fallback used only when DropTarget is unsupported
StringCchPrintf(szBuffer, countof(szBuffer), TEXT("rundll32.exe \"%s\",HashVerify_RunDLL %%1"), lpszModuleName, IDS_FILETYPE_DESC);
RegSetSZ(hKey, NULL, szBuffer);
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\shell\\edit\\command"), PROGID_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\shell\\edit\\command"), PROGID_STR_HashCheck, TRUE))
{
RegSetSZ(hKey, NULL, TEXT("notepad.exe %1"));
RegCloseKey(hKey);
} else return(SELFREG_E_CLASS);

if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\shell"), PROGID_STR_HashCheck))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, TEXT("%s\\shell"), PROGID_STR_HashCheck, TRUE))
{
RegSetSZ(hKey, NULL, TEXT("open"));
RegCloseKey(hKey);
Expand All @@ -178,7 +183,7 @@ STDAPI DllRegisterServerEx( LPCTSTR lpszModuleName )
// will be handled by DllInstall, not DllRegisterServer.

// Register approval
if (hKey = RegOpen(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), NULL))
if (hKey = RegOpen(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), NULL, TRUE))
{
RegSetSZ(hKey, CLSID_STR_HashCheck, CLSNAME_STR_HashCheck);
RegCloseKey(hKey);
Expand Down Expand Up @@ -229,7 +234,7 @@ STDAPI DllUnregisterServer( )
}

// Unregister approval
if (hKey = RegOpen(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), NULL))
if (hKey = RegOpen(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), NULL, FALSE))
{
LONG lResult = RegDeleteValue(hKey, CLSID_STR_HashCheck);
bApprovalRemoved = (lResult == ERROR_SUCCESS || lResult == ERROR_FILE_NOT_FOUND);
Expand Down Expand Up @@ -299,12 +304,12 @@ HRESULT Install( BOOL bRegisterUninstaller, BOOL bCopyFile )
// Associate file extensions
for (UINT i = 0; i < countof(g_szHashExtsTab); ++i)
{
if (hKey = RegOpen(HKEY_CLASSES_ROOT, g_szHashExtsTab[i], NULL))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, g_szHashExtsTab[i], NULL, TRUE))
{
RegSetSZ(hKey, NULL, PROGID_STR_HashCheck);
RegSetSZ(hKey, TEXT("PerceivedType"), TEXT("text"));

if (hKeySub = RegOpen(hKey, TEXT("PersistentHandler"), NULL))
if (hKeySub = RegOpen(hKey, TEXT("PersistentHandler"), NULL, TRUE))
{
RegSetSZ(hKeySub, NULL, TEXT("{5e941d80-bf96-11cd-b579-08002b30bfeb}"));
RegCloseKey(hKeySub);
Expand All @@ -314,10 +319,29 @@ HRESULT Install( BOOL bRegisterUninstaller, BOOL bCopyFile )
}
}

// Disassociate former file extensions; see the comment in DllUnregisterServer for
// why this step is skipped for Wow64 processes
if (!Wow64CheckProcess())
{
for (UINT i = 0; i < countof(szFormerHashExtsTab); ++i)
{
HKEY hKey;

if (hKey = RegOpen(HKEY_CLASSES_ROOT, szFormerHashExtsTab[i], NULL, FALSE))
{
TCHAR szTemp[countof(PROGID_STR_HashCheck)];
RegGetSZ(hKey, NULL, szTemp, sizeof(szTemp));
if (_tcscmp(szTemp, PROGID_STR_HashCheck) == 0)
RegDeleteValue(hKey, NULL);
RegCloseKey(hKey);
}
}
}

// Uninstaller entries
RegDelete(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s"), CLSNAME_STR_HashCheck);

if (bRegisterUninstaller && (hKey = RegOpen(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s"), CLSNAME_STR_HashCheck)))
if (bRegisterUninstaller && (hKey = RegOpen(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s"), CLSNAME_STR_HashCheck, TRUE)))
{
TCHAR szUninstall[MAX_PATH << 1];
StringCchPrintf(szUninstall, countof(szUninstall), TEXT("regsvr32.exe /u /i /n \"%s\""), lpszTargetPath);
Expand Down Expand Up @@ -463,10 +487,12 @@ HRESULT Uninstall( )
{
HKEY hKey;

if (hKey = RegOpen(HKEY_CLASSES_ROOT, g_szHashExtsTab[i], NULL))
if (hKey = RegOpen(HKEY_CLASSES_ROOT, g_szHashExtsTab[i], NULL, FALSE))
{
RegDeleteValue(hKey, NULL);
RegCloseKey(hKey);
RegGetSZ(hKey, NULL, szTemp, sizeof(szTemp));
if (_tcscmp(szTemp, PROGID_STR_HashCheck) == 0)
RegDeleteValue(hKey, NULL);
RegCloseKey(hKey);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion HashCheckOptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ VOID __fastcall OptionsSave( PHASHCHECKOPTIONS popt )
if (popt->dwFlags == 0)
return;

if (hKey = RegOpen(HKEY_CURRENT_USER, OPTIONS_KEYNAME, NULL))
if (hKey = RegOpen(HKEY_CURRENT_USER, OPTIONS_KEYNAME, NULL, TRUE))
{
if (popt->dwFlags & HCOF_FILTERINDEX)
RegSetDW(hKey, TEXT("FilterIndex"), popt->dwFilterIndex);
Expand Down
10 changes: 8 additions & 2 deletions RegHelpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@

#define countof(x) (sizeof(x)/sizeof(x[0]))

HKEY WINAPI RegOpen( HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpSubst )
HKEY WINAPI RegOpen( HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpSubst, BOOL bCreate )
{
HKEY hKeyRet = NULL;
TCHAR szJoinedKey[0x7F];
if (lpSubst) StringCchPrintf(szJoinedKey, countof(szJoinedKey), lpSubKey, lpSubst);

if (RegCreateKeyEx(hKey, (lpSubst) ? szJoinedKey : lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKeyRet, NULL) == ERROR_SUCCESS)
LONG lResult;
if (bCreate)
lResult = RegCreateKeyEx(hKey, (lpSubst) ? szJoinedKey : lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKeyRet, NULL);
else
lResult = RegOpenKeyEx(hKey, (lpSubst) ? szJoinedKey : lpSubKey, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKeyRet);

if (lResult == ERROR_SUCCESS)
{
Wow64DisableRegReflection(hKeyRet);
return(hKeyRet);
Expand Down
2 changes: 1 addition & 1 deletion RegHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extern "C" {
#include <windows.h>
#include <shlwapi.h>

HKEY WINAPI RegOpen( HKEY, LPCTSTR, LPCTSTR );
HKEY WINAPI RegOpen( HKEY, LPCTSTR, LPCTSTR, BOOL );
BOOL WINAPI RegDelete( HKEY, LPCTSTR, LPCTSTR );
BOOL WINAPI RegSetSZ( HKEY, LPCTSTR, LPCTSTR );
BOOL WINAPI RegSetDW( HKEY, LPCTSTR, DWORD );
Expand Down
8 changes: 4 additions & 4 deletions installer/HashCheck.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Unicode true

Name "HashCheck"
OutFile "HashCheckSetup-v2.4.0.39-beta.exe"
OutFile "HashCheckSetup-v2.4.0.40-beta.exe"

RequestExecutionLevel admin
ManifestSupportedOS all
Expand Down Expand Up @@ -53,15 +53,15 @@ FunctionEnd
!insertmacro MUI_LANGUAGE "Ukrainian"
!insertmacro MUI_LANGUAGE "Catalan"

VIProductVersion "2.4.0.39-beta"
VIProductVersion "2.4.0.40-beta"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "HashCheck Shell Extension"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "2.4.0.39-beta"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "2.4.0.40-beta"
VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "Installer distributed from https://github.com/gurnec/HashCheck/releases"
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" ""
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalTrademarks" ""
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright © Kai Liu, Christopher Gurnee, Tim Schlueter, et al. All rights reserved."
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "Installer (x86/x64) from https://github.com/gurnec/HashCheck/releases"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "2.4.0.39-beta"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "2.4.0.40-beta"

; With solid compression, files that are required before the
; actual installation should be stored first in the data block,
Expand Down
4 changes: 2 additions & 2 deletions version.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
#define HASHCHECK_NAME_STR "HashCheck Shell Extension"

// Full version: MUST be in the form of major,minor,revision,build
#define HASHCHECK_VERSION_FULL 2,4,0,39
#define HASHCHECK_VERSION_FULL 2,4,0,40

// String version: May be any suitable string
#define HASHCHECK_VERSION_STR "2.4.0.39-beta"
#define HASHCHECK_VERSION_STR "2.4.0.40-beta"

#ifdef _USRDLL
// PE version: MUST be in the form of major.minor
Expand Down

0 comments on commit 122a96f

Please sign in to comment.