123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- #include "main.h"
- #include "./winampHook.h"
- #include "./ifc_winamphook.h"
- #include "../winamp/wa_ipc.h"
- #include <windows.h>
- #define WINAMP_REFRESHSKIN 40291
- #define WHPROCRECOVERY L"WaHookProcRecovery"
- static ATOM WAWNDATOM = 0;
- #define GetWinampHook(__hwnd) ((WinampHook*)GetProp((__hwnd), MAKEINTATOM(WAWNDATOM)))
- WinampHook::WinampHook(HWND hwndWinamp)
- : ref(1), hwnd(hwndWinamp), originalProc(NULL), flags(0), lastCookie(0)
- {
- }
- WinampHook::~WinampHook()
- {
- DetachFromWinamp();
- if (0 != WAWNDATOM)
- {
- GlobalDeleteAtom(WAWNDATOM);
- WAWNDATOM = 0;
- }
- }
- HRESULT WinampHook::CreateInstance(HWND hwndWinamp, WinampHook **instance)
- {
- if (NULL == instance) return E_POINTER;
- *instance = NULL;
- if (NULL == hwndWinamp || FALSE == IsWindow(hwndWinamp))
- return E_INVALIDARG;
- *instance = new WinampHook(hwndWinamp);
- if (NULL == *instance) return E_OUTOFMEMORY;
- return S_OK;
- }
- ULONG WinampHook::AddRef()
- {
- return InterlockedIncrement((LONG*)&ref);
- }
- ULONG WinampHook::Release()
- {
- if (0 == ref)
- return ref;
- LONG r = InterlockedDecrement((LONG*)&ref);
- if (0 == r)
- delete(this);
- return r;
- }
- HRESULT WinampHook::RegisterCallback(ifc_winamphook *callback, UINT *cookie)
- {
- if (NULL == cookie) return E_POINTER;
- *cookie = 0;
- if (NULL == callback) return E_INVALIDARG;
- if (FAILED(AttachToWinamp()))
- return E_UNEXPECTED;
- *cookie = ++lastCookie;
- callbackMap.insert({ *cookie, callback });
- callback->AddRef();
- return S_OK;
- }
- HRESULT WinampHook::UnregisterCallback(UINT cookie)
- {
- if (0 == cookie) return E_INVALIDARG;
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- {
- if (cookie == iter->first)
- {
- ifc_winamphook *hook = iter->second;
- callbackMap.erase(iter);
-
- if (NULL != hook)
- hook->Release();
- return S_OK;
- }
- }
- return S_FALSE;
- }
- HWND WinampHook::GetWinamp()
- {
- return hwnd;
- }
- LRESULT WinampHook::CallPrevWinampProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- if (NULL == originalProc || NULL == hwnd) return 0;
- return (0 != (flagUnicode & flags)) ?
- CallWindowProcW(originalProc, hwnd, uMsg, wParam, lParam) :
- CallWindowProcA(originalProc, hwnd, uMsg, wParam, lParam);
- }
- LRESULT WinampHook::CallDefWinampProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- if (NULL == hwnd) return 0;
- return (0 != (flagUnicode & flags)) ?
- DefWindowProcW(hwnd, uMsg, wParam, lParam) :
- DefWindowProcA(hwnd, uMsg, wParam, lParam);
- }
- HRESULT WinampHook::AttachToWinamp()
- {
- if (NULL == hwnd || !IsWindow(hwnd)) return E_UNEXPECTED;
- if (0 == WAWNDATOM)
- {
- WAWNDATOM = GlobalAddAtom(L"WinampHook");
- if (0 == WAWNDATOM) return E_FAIL;
- }
- WinampHook *hookInstance = GetWinampHook(hwnd);
- if (this == hookInstance) return S_FALSE;
- if (NULL != hookInstance || NULL != originalProc)
- return E_FAIL;
- flags = 0;
- if (IsWindowUnicode(hwnd)) flags |= flagUnicode;
- originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)WinampWindowProc);
- if (NULL == originalProc || FALSE == SetProp(hwnd, MAKEINTATOM(WAWNDATOM), this))
- {
- if (NULL != originalProc)
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)originalProc);
- return E_FAIL;
- }
- return S_OK;
- }
- HRESULT WinampHook::DetachFromWinamp()
- {
- if (NULL == hwnd || !IsWindow(hwnd)) return E_UNEXPECTED;
- if (0 == WAWNDATOM) return E_FAIL;
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- {
- if (NULL != iter->second)
- iter->second->Release();
- }
- callbackMap.clear();
- WinampHook *hookInstance = GetWinampHook(hwnd);
- if (this != hookInstance) return E_FAIL;
- RemoveProp(hwnd, MAKEINTATOM(WAWNDATOM));
- WNDPROC currentProc = (WNDPROC)(LONG_PTR)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
- if (currentProc == WinampWindowProc)
- {
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)originalProc);
- }
- else
- {
- SetProp(hwnd, WHPROCRECOVERY, (HANDLE)originalProc);
- }
- originalProc = NULL;
- flags = 0;
- return S_OK;
- }
- LRESULT WinampHook::OnWinampDestroy()
- {
- WNDPROC proc = originalProc;
- DetachFromWinamp();
- return (IsWindowUnicode(hwnd)) ?
- CallWindowProcW(proc, hwnd, WM_DESTROY, 0, 0L) :
- CallWindowProcA(proc, hwnd, WM_DESTROY, 0, 0L);
- }
- LRESULT WinampHook::OnWinampIPC(UINT commandId, WPARAM param)
- {
- switch(commandId)
- {
- case IPC_CB_RESETFONT:
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- if (NULL != iter->second) iter->second->ResetFont();
- break;
- case IPC_HOOK_OKTOQUIT:
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- if (NULL != iter->second && S_FALSE == iter->second->IsQuitAllowed()) return 0;
- break;
- case IPC_SKIN_CHANGED:
- {
- WCHAR szBuffer[MAX_PATH*2] = {0};
- SENDWAIPC(hwnd, IPC_GETSKINW, szBuffer);
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- if (NULL != iter->second) iter->second->SkinChanged(szBuffer);
- }
- break;
-
- case IPC_FF_ONCOLORTHEMECHANGED:
- if (FALSE != IS_INTRESOURCE(param))
- param = 0L;
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- if (NULL != iter->second) iter->second->SkinColorChange((LPCWSTR)param);
- break;
- case IPC_FILE_TAG_MAY_HAVE_UPDATED:
- {
- WCHAR szBuffer[MAX_PATH*2] = {0};
- param = (0 != MultiByteToWideChar(CP_ACP, 0, (char*)param, -1, szBuffer, ARRAYSIZE(szBuffer))) ?
- (WPARAM)szBuffer : 0L;
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- if (NULL != iter->second) iter->second->FileMetaChange((LPCWSTR)param);
- }
- break;
- case IPC_FILE_TAG_MAY_HAVE_UPDATEDW:
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- if (NULL != iter->second) iter->second->FileMetaChange((LPCWSTR)param);
- break;
- }
- return CallPrevWinampProc(WM_WA_IPC, param, (LPARAM)commandId);
- }
- void WinampHook::OnWinampCommand(UINT commandId, UINT controlId, HWND hControl)
- {
- switch(commandId)
- {
- case WINAMP_REFRESHSKIN:
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- if (NULL != iter->second) iter->second->SkinChanging();
- break;
- }
- }
- void WinampHook::OnSysColorChange()
- {
- for(CallbackMap::iterator iter = callbackMap.begin(); iter != callbackMap.end(); iter++)
- if (NULL != iter->second) iter->second->SysColorChange();
- }
- LRESULT WinampHook::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- switch(uMsg)
- {
- case WM_DESTROY: return OnWinampDestroy();
- case WM_WA_IPC: return OnWinampIPC((UINT)lParam, wParam);
- case WM_COMMAND: OnWinampCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
- case WM_SYSCOLORCHANGE: OnSysColorChange(); break;
- }
- return CallPrevWinampProc(uMsg, wParam, lParam);
- }
- static LRESULT CALLBACK WinampWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- WinampHook *hookInstance = GetWinampHook(hwnd);
- if (NULL == hookInstance)
- {
- WNDPROC recovery = (WNDPROC)GetProp(hwnd, WHPROCRECOVERY);
- if (NULL != recovery)
- {
- return (IsWindowUnicode(hwnd)) ?
- CallWindowProcW(recovery, hwnd, uMsg, wParam, lParam) :
- CallWindowProcA(recovery, hwnd, uMsg, wParam, lParam);
- }
- return (IsWindowUnicode(hwnd)) ?
- DefWindowProcW(hwnd, uMsg, wParam, lParam) :
- DefWindowProcA(hwnd, uMsg, wParam, lParam);
- }
- return hookInstance->WindowProc(uMsg, wParam, lParam);
- }
|