Skip to content

Instantly share code, notes, and snippets.

@qwerty12
Created November 11, 2016 08:31
Show Gist options
  • Save qwerty12/6dbddf23f9ba2ba81319d6a4bfb97000 to your computer and use it in GitHub Desktop.
Save qwerty12/6dbddf23f9ba2ba81319d6a4bfb97000 to your computer and use it in GitHub Desktop.
#include <sdkddkver.h>
#include <windows.h>
#include <Shellapi.h>
#include <Shlobj.h>
#include <strsafe.h>
#include "extlib\MinHook.h"
#define WM_SHELLNOTIFY WM_USER+5
#define WM_TRAYCMD 0x800A
static ULONG g_changeNotifyRegisterId = 0;
static HHOOK g_hWndProcHook = NULL;
static PIDLIST_ABSOLUTE g_ppBitBucketidl = NULL;
static HWND g_MiniBin_TrayIconClass = NULL;
typedef HINSTANCE(WINAPI *P_SHELLEXECUTEW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT);
static P_SHELLEXECUTEW ShellExecuteWTramp = NULL;
static LPVOID ShellExecuteWOrig = NULL;
typedef UINT_PTR(WINAPI *P_SETTIMER)(HWND, UINT_PTR, UINT, TIMERPROC);
static P_SETTIMER SetTimerTramp = NULL;
static LPVOID SetTimerOrig = NULL;
typedef BOOL(WINAPI *P_KILLTIMER)(HWND, UINT_PTR);
static P_KILLTIMER KillTimerTramp = NULL;
static LPVOID KillTimerOrig = NULL;
typedef BOOL(WINAPI *P_GETPRIVATEPROFILEINTW)(LPCWSTR, LPCWSTR, INT, LPCWSTR);
static P_GETPRIVATEPROFILEINTW GetPrivateProfileIntWTramp = NULL;
static LPVOID GetPrivateProfileIntWOrig = NULL;
typedef INT (WINAPI *P_MESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT);
static P_MESSAGEBOXW MessageBoxWTramp = NULL;
static LPVOID MessageBoxWOrig = NULL;
static BOOL GetCachedIsIconsTwoStates()
{
static BOOL firstRun = TRUE, retval = TRUE;
if (firstRun) {
firstRun = FALSE;
WCHAR path[MAX_PATH];
DWORD st = GetModuleFileNameW(NULL, path, MAX_PATH);
if (st && st != MAX_PATH) {
for (LPWSTR i = path + st; *(i - 1) != L'\\'; *i = 0)
--i;
if (SUCCEEDED(StringCchCatW(path, MAX_PATH, L"minibin.ini")))
retval = !!GetPrivateProfileIntW(L"Configure", L"IconsTwoStates", retval, path);
}
}
return retval;
}
UINT WINAPI GetPrivateProfileIntWHook(_In_ LPCWSTR lpAppName, _In_ LPCWSTR lpKeyName, _In_ INT nDefault, _In_opt_ LPCWSTR lpFileName)
{
if (nDefault == 1 && lpAppName && lpKeyName && lpFileName && !wcscmp(lpKeyName, L"MaxFillSizeMB")) { /* !wcscmp(lpAppName, L"History") && wcsstr(lpFileName, L"minibin.ini")*/
static WCHAR volCRecycleKeyPath[MAX_PATH] = { '\0' };
if (!*volCRecycleKeyPath) {
WCHAR volCName[75];
if (GetVolumeNameForVolumeMountPoint(L"C:\\", volCName, _countof(volCName))) {
LPWSTR volCGuid = wcsstr(volCName, L"{");
if (volCGuid) {
LPWSTR end = wcsstr(volCGuid, L"}");
if (end && end + 1 != L'\0')
*(end + 1) = L'\0';
if (FAILED(StringCchCopyW(volCRecycleKeyPath, _countof(volCRecycleKeyPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket\\Volume\\")) || FAILED(StringCchCatW(volCRecycleKeyPath, _countof(volCRecycleKeyPath), volCGuid)))
volCRecycleKeyPath[0] = L'\0';
}
}
}
if (volCRecycleKeyPath) {
DWORD maxRecycleCSize = 0, maxRecycleCSizeSize = sizeof(maxRecycleCSize);
if (RegGetValue(HKEY_CURRENT_USER, volCRecycleKeyPath, L"MaxCapacity", RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY, NULL, &maxRecycleCSize, &maxRecycleCSizeSize) == ERROR_SUCCESS)
return maxRecycleCSize;
}
}
return GetPrivateProfileIntWTramp(lpAppName, lpKeyName, nDefault, lpFileName);
}
UINT_PTR WINAPI SetTimerHook(_In_opt_ HWND hWnd, _In_ UINT_PTR nIDEvent, _In_ UINT uElapse, _In_opt_ TIMERPROC lpTimerFunc)
{
if (g_MiniBin_TrayIconClass && g_MiniBin_TrayIconClass == hWnd && nIDEvent == 1)
return 0;
return SetTimerTramp(hWnd, nIDEvent, uElapse, lpTimerFunc);
}
BOOL WINAPI KillTimerHook(_In_opt_ HWND hWnd, _In_ UINT_PTR uIDEvent)
{
if (g_MiniBin_TrayIconClass && g_MiniBin_TrayIconClass == hWnd && uIDEvent == 1)
return TRUE;
return KillTimerTramp(hWnd, uIDEvent);
}
HINSTANCE WINAPI ShellExecuteWHook(_In_opt_ HWND hwnd, _In_opt_ LPCWSTR lpOperation, _In_ LPCWSTR lpFile, _In_opt_ LPCWSTR lpParameters, _In_opt_ LPCWSTR lpDirectory, _In_ INT nShowCmd)
{
if (!lpDirectory && nShowCmd == SW_SHOWNORMAL && !hwnd && lpOperation && lpFile && lpParameters && !wcscmp(lpOperation, L"open") && !wcscmp(lpFile, L"explorer.exe") && !wcscmp(lpParameters, L"::{645FF040-5081-101B-9F08-00AA002F954E}")) {
SHELLEXECUTEINFO ExecInfo = {
.cbSize = sizeof(ExecInfo),
.fMask = SEE_MASK_DEFAULT | SEE_MASK_IDLIST,
.nShow = SW_SHOWNORMAL,
.lpIDList = g_ppBitBucketidl
};
return (HINSTANCE)(ShellExecuteEx(&ExecInfo) + 32);
}
return ShellExecuteWTramp(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd);
}
INT WINAPI MessageBoxWHook(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
if (!hWnd && uType == 0x40124 && lpCaption && lpText && !wcscmp(lpCaption, L"MiniBin 6.6.0.0") && !wcscmp(lpText, L"Exit"))
return IDYES;
return MessageBoxWTramp(hWnd, lpText, lpCaption, uType);
}
LRESULT CALLBACK WndHook(INT nCode, WPARAM wParam, LPARAM lParam)
{
BOOL bPassToChain = TRUE;
PCWPSTRUCT msg = (PCWPSTRUCT)lParam;
if (nCode >= HC_ACTION) {
if (!g_MiniBin_TrayIconClass) {
if (msg->message == WM_CREATE) {
WCHAR name[23];
if (GetClassNameW(msg->hwnd, name, _countof(name) - 1) == 21 && !wcscmp(name, L"MiniBin_TrayIconClass")) {
g_MiniBin_TrayIconClass = msg->hwnd;
if (!g_ppBitBucketidl) {
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(SHGetKnownFolderIDList(&FOLDERID_RecycleBinFolder, KF_FLAG_DEFAULT | KF_FLAG_SIMPLE_IDLIST, NULL, &g_ppBitBucketidl))) {
MH_CreateHookApiEx(L"Shell32", "ShellExecuteW", &ShellExecuteWHook, (LPVOID*)&ShellExecuteWTramp, &ShellExecuteWOrig);
MH_CreateHookApiEx(L"User32", "SetTimer", &SetTimerHook, (LPVOID*)&SetTimerTramp, &SetTimerOrig);
MH_CreateHookApiEx(L"User32", "KillTimer", &KillTimerHook, (LPVOID*)&KillTimerTramp, &KillTimerOrig);
MH_CreateHookApiEx(L"User32", "MessageBoxW", &MessageBoxWHook, (LPVOID*)&MessageBoxWTramp, &MessageBoxWOrig);
MH_EnableHook(MH_ALL_HOOKS);
PostMessage(g_MiniBin_TrayIconClass, WM_TIMER, 1, 0);
SHChangeNotifyEntry scnIDL;
scnIDL.pidl = g_ppBitBucketidl;
scnIDL.fRecursive = FALSE;
LONG events = GetCachedIsIconsTwoStates() ? SHCNE_UPDATEIMAGE : SHCNE_CREATE | SHCNE_DELETE | SHCNE_MKDIR | SHCNE_RMDIR | SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED | SHCNE_DRIVEREMOVED | SHCNE_DRIVEADD | SHCNE_NETSHARE | SHCNE_NETUNSHARE | SHCNE_ATTRIBUTES | SHCNE_UPDATEDIR | SHCNE_UPDATEITEM | SHCNE_SERVERDISCONNECT | SHCNE_UPDATEIMAGE | SHCNE_DRIVEADDGUI | SHCNE_RENAMEFOLDER;
g_changeNotifyRegisterId = SHChangeNotifyRegister(g_MiniBin_TrayIconClass, SHCNRF_InterruptLevel | SHCNRF_ShellLevel, events, WM_SHELLNOTIFY, 1, &scnIDL);
if (!g_changeNotifyRegisterId) {
MH_DisableHook(&KillTimerOrig);
MH_DisableHook(&SetTimerOrig);
}
}
}
}
}
}
else if (msg->hwnd == g_MiniBin_TrayIconClass) {
if (msg->message == WM_SHELLNOTIFY) {
bPassToChain = FALSE;
PostMessage(g_MiniBin_TrayIconClass, WM_TIMER, 1, 0);
}
else if (msg->message == WM_TRAYCMD) {
if (msg->lParam == WM_MOUSEMOVE) {
bPassToChain = FALSE;
PostMessage(g_MiniBin_TrayIconClass, WM_TIMER, 1, 0);
}
}
}
}
if (bPassToChain) {
return CallNextHookEx(g_hWndProcHook, nCode, wParam, lParam);
} else {
msg->message = WM_NULL;
return FALSE;
}
}
BOOL WINAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
__security_init_cookie();
DisableThreadLibraryCalls(hinstDLL);
MH_Initialize();
MH_CreateHookApiEx(L"Kernel32", "GetPrivateProfileIntW", &GetPrivateProfileIntWHook, (LPVOID*)&GetPrivateProfileIntWTramp, &GetPrivateProfileIntWOrig);
g_hWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, WndHook, NULL, GetCurrentThreadId());
break;
case DLL_PROCESS_DETACH:
if (g_hWndProcHook) {
UnhookWindowsHookEx(g_hWndProcHook);
g_hWndProcHook = NULL;
}
MH_RemoveHook(GetPrivateProfileIntWOrig);
if (g_ppBitBucketidl) {
SHChangeNotifyDeregister(g_changeNotifyRegisterId);
g_changeNotifyRegisterId = 0;
MH_RemoveHook(ShellExecuteWOrig);
MH_RemoveHook(KillTimerOrig);
MH_RemoveHook(SetTimerOrig);
MH_RemoveHook(MessageBoxWOrig);
ILFree(g_ppBitBucketidl);
g_ppBitBucketidl = NULL;
CoUninitialize();
}
MH_Uninitialize();
break;
default:
break;
}
return TRUE;
}
__declspec(dllexport) BOOL dummyExport() { return FALSE; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment