aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/ole.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/ole.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/ole.cpp')
-rw-r--r--Src/Winamp/ole.cpp431
1 files changed, 431 insertions, 0 deletions
diff --git a/Src/Winamp/ole.cpp b/Src/Winamp/ole.cpp
new file mode 100644
index 00000000..b8039668
--- /dev/null
+++ b/Src/Winamp/ole.cpp
@@ -0,0 +1,431 @@
+/** (c) Nullsoft, Inc. C O N F I D E N T I A L
+ ** Filename:
+ ** Project:
+ ** Description:
+ ** Author:
+ ** Created:
+ **/
+#include "main.h"
+#include "../nu/AutoWide.h"
+#include "../nu/AutoWideFn.h"
+extern "C"
+{
+ extern int g_has_deleted_current;
+};
+#include "shlobj.h"
+#include "../Plugins/General/gen_ff/ff_ipc.h"
+
+ bool refuseDrops = false;
+class DropTarget: public IDropTarget
+{
+public:
+ DropTarget(int enqueue, int isshell)
+ { m_enqueue = enqueue; m_isshell = isshell; }
+
+ STDMETHODIMP QueryInterface (REFIID riid, LPVOID * ppvObj)
+ {
+ if (riid == IID_IDropTarget || riid == IID_IUnknown)
+ {
+ *ppvObj = this;
+ return S_OK;
+ }
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+ STDMETHODIMP_(ULONG) AddRef ()
+ { return 0; }
+ STDMETHODIMP_(ULONG) Release ()
+ { return 0; }
+
+ STDMETHODIMP DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
+ {
+ if (pdwEffect)
+ {
+ if (refuseDrops && !m_isshell)
+ *pdwEffect = DROPEFFECT_NONE;
+ else
+ *pdwEffect = DROPEFFECT_COPY;
+ }
+
+ return S_OK;
+ }
+ STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
+ {
+
+ if (pdwEffect)
+ {
+ if (refuseDrops && !m_isshell)
+ *pdwEffect = DROPEFFECT_NONE;
+ }
+
+ return S_OK;
+ }
+ STDMETHODIMP DragLeave()
+ {
+ return 0;
+ }
+
+ STDMETHODIMP Drop(IDataObject * pDataObj, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
+ {
+ POINT p = {pt.x, pt.y};
+ HWND wnd;
+ int pl_forceappend = 0;
+ int is_main = 0;
+ int is_pe = 0;
+ int pe_insert = 0;
+ if (m_isshell)
+ {
+ is_main = 1;
+ wnd = hMainWindow;
+ if (m_enqueue == 2)
+ {
+ pe_insert = !SendMessageW(hMainWindow, WM_WA_IPC, PlayList_getlength(), IPC_SHELL_ACTION_START);
+ }
+ }
+ else
+ {
+ wnd = WindowFromPoint(p);
+
+ HWND child=0;
+ do
+ {
+ RECT r;
+ GetWindowRect(wnd, &r);
+ POINT offset = p;
+ offset.x -= r.left;
+ offset.y -= r.top;
+ child = ChildWindowFromPoint(wnd, offset);
+ if (child == wnd)
+ child = 0;
+ else if (child)
+ wnd = child;
+ } while (child);
+
+ HWND par = wnd;
+ HWND pledit_poopie = NULL;
+ while (par && !(GetWindowLongW(par, GWL_EXSTYLE) & WS_EX_ACCEPTFILES))
+ {
+ par = GetParent(par);
+ }
+ if (par) wnd = par;
+
+ if (wnd == hMainWindow || IsChild(hMainWindow, wnd)
+ || (HWND)SendMessageW(hMainWindow, WM_WA_IPC, (WPARAM)wnd, IPC_FF_GETCONTENTWND) == hMainWindow)
+ {
+ is_main = 1;
+ }
+ else if (wnd == hPLWindow || IsChild(hPLWindow, wnd) || GetParent(hPLWindow) && IsChild(wnd, hPLWindow) ||
+ (pledit_poopie = (HWND)SendMessageW(hMainWindow, WM_WA_IPC, (WPARAM)wnd, IPC_FF_GETCONTENTWND)) == hPLWindow)
+ {
+ is_pe = 1;
+ if (pledit_poopie) pl_forceappend = 1; // if we got here because we're hosting the pledit, but not actually
+ // parenting it (meaning we are windowshaded playlist)
+ }
+ else
+ {
+ EnterCriticalSection(&embedcs);
+ {
+ embedWindowState *p = embedwndlist;
+ while (p)
+ {
+ if (IsChild(p->me, wnd) || (GetParent(p->me) && IsChild(wnd, p->me))) break;
+ p = p->link;
+ }
+ if (p)
+ {
+ if (wnd == p->me || IsChild(wnd, p->me) || !(GetWindowLongW(wnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)) // if this window accepts files, dont fuck it up
+ {
+ HWND wnd2 = FindWindowExW(p->me, NULL, NULL, NULL);
+ if (!(GetWindowLongW(wnd2, GWL_EXSTYLE)&WS_EX_ACCEPTFILES)) is_main = 1;
+ else
+ {
+ HWND h = GetParent(p->me);
+ char buf[128] = {0};
+ // see if we are (AVS) docked to the main (modern) window
+ if (h && (h = GetParent(h)) && GetWindowTextA(h, buf, sizeof(buf)) && !_stricmp(buf, "Player Window"))
+ is_main = 1;
+ else wnd = wnd2;
+ }
+ }
+ }
+ else is_main = 1;
+ }
+ LeaveCriticalSection(&embedcs);
+ }
+
+ if (is_main) wnd = hMainWindow;
+ if (is_pe) wnd = hPLWindow;
+ }
+
+ HRESULT hr = S_OK;
+ if (pDataObj)
+ {
+ // Important: these strings need to be non-Unicode (don't compile UNICODE)
+ unsigned short cp_format_url = (unsigned short)RegisterClipboardFormat(CFSTR_SHELLURL);
+ //Set up format structure for the descriptor and contents
+ FORMATETC format_url =
+ {cp_format_url, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ FORMATETC format_file =
+ {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ // Check for URL
+ hr = pDataObj->QueryGetData(&format_url);
+ if (hr == S_OK)
+ {
+ // Get the descriptor information
+ STGMEDIUM storage = {0, 0, 0};
+ hr = pDataObj->GetData(&format_url, &storage);
+ char* url = (char *)GlobalLock(storage.hGlobal);
+ if (url)
+ {
+ if (is_pe || is_main || m_isshell)
+ {
+ int t, lp, a;
+ int del = is_main && !(GetAsyncKeyState(VK_SHIFT) & (1 << 15));
+ if (del) PlayList_delete();
+ else if (!is_main && !m_isshell) // playlist
+ {
+ RECT r;
+ POINT dp;
+ GetWindowRect(wnd, &r);
+ dp.x = pt.x - r.left;
+ dp.y = pt.y - r.top;
+ if (config_pe_height == 14 || pl_forceappend) t = PlayList_getlength();
+ else
+ {
+ t = (dp.y - 20) / pe_fontheight;
+ if (t < 0) t = 0;
+ else if (t > (config_pe_height - 38 - 20 - 2) / pe_fontheight) t = PlayList_getlength();
+ else t += pledit_disp_offs;
+ }
+ a = PlayList_getlength();
+ PlayList_saveend(t);
+ lp = PlayList_getPosition();
+ }
+
+ if(!PathIsURLA(url))
+ {
+ // if it's not reported as an url, try to treat it like
+ // a filepath which has been url-encoded and insert it
+ // though if it fails to be converted then revert to it
+ // just being added to the playlist without processing.
+ char url2[FILENAME_SIZE] = {"file:///"};
+ strncat(url2, url, FILENAME_SIZE);
+ DWORD len = lstrlenA(url2);
+ if(SUCCEEDED(PathCreateFromUrlA(url2, url2, &len, 0)))
+ {
+ PlayList_appendthing(AutoWideFn(url2), 0, 0);
+ }
+ else
+ {
+ PlayList_appendthing(AutoWideFn(url), 0, 0);
+ }
+ }
+ else
+ {
+ PlayList_appendthing(AutoWideFn(url), 0, 0);
+ }
+
+ if (del) StartPlaying();
+ else if (!is_main && !m_isshell) // playlist
+ {
+ PlayList_restoreend();
+ if (t <= PlayList_getPosition())
+ {
+ PlayList_setposition(lp + PlayList_getlength() - a);
+ if (!g_has_deleted_current)
+ {
+ PlayList_getcurrent(FileName, FileTitle, FileTitleNum);
+ draw_songname(FileTitle, &ui_songposition, playing ? in_getlength() : PlayList_getcurrentlength());
+ }
+ }
+ plEditRefresh();
+ }
+ }
+ else // fucko: pass url to 'wnd' somehow?
+ {}
+ }
+ GlobalUnlock(url);
+ GlobalFree(url);
+ }
+ else
+ {
+ // check for file
+ hr = pDataObj->QueryGetData(&format_file);
+ if (hr == S_OK)
+ {
+ STGMEDIUM medium;
+ pDataObj->GetData (&format_file, &medium);
+ wchar_t temp[FILENAME_SIZE] = {0};
+ if (m_enqueue)
+ {
+ HDROP hdrop = (HDROP)medium.hGlobal;
+ int y = DragQueryFileW(hdrop, 0xffffffff, temp, FILENAME_SIZE);
+ int current = PlayList_getPosition();
+ for (int x = 0; x < y; x ++)
+ {
+ DragQueryFileW(hdrop, x, temp, FILENAME_SIZE);
+ if (!pe_insert)
+ PlayList_appendthing(temp, 0, 0);
+ else
+ {
+ PlayList_insert(++current, temp);
+ }
+ }
+ DragFinish(hdrop);
+
+ plEditRefresh();
+ }
+ else
+ {
+ int skinLoad = -2;
+ int langLoad = -2;
+ RECT r;
+ GetWindowRect(wnd, &r);
+ LPDROPFILES d = (LPDROPFILES)GlobalLock(medium.hGlobal);
+ d->pt.x = pt.x - r.left;
+ if (pl_forceappend)
+ d->pt.y = r.bottom - r.top;
+ else d->pt.y = pt.y - r.top;
+ d->fNC = FALSE;
+
+ GlobalUnlock(d);
+
+ // check for the file being a skin or language pack
+ // being dropped so we can intercept and not add it
+ // into the pledit but can instead prompt for install
+ DragQueryFileW((HDROP)medium.hGlobal, 0, temp, FILENAME_SIZE);
+ CheckSkin(temp, hMainWindow, &skinLoad);
+ CheckLang(temp, hMainWindow, &langLoad);
+
+ if(!skinLoad && !langLoad)
+ {
+ PostMessageW(wnd, WM_DROPFILES, (WPARAM)medium.hGlobal, 0);
+ }
+ }
+ }
+ }
+ }
+
+ if (m_isshell && (m_enqueue == 2))
+ {
+ SendMessageW(hMainWindow, WM_WA_IPC, PlayList_getlength(), IPC_SHELL_ACTION_END);
+ }
+ return S_OK;
+ }
+public:
+ int m_enqueue;
+ int m_isshell;
+};
+
+static DropTarget m_target(0, 0);
+
+class ClassFactory : public IClassFactory
+{
+public:
+ ClassFactory(int enqueue) { m_drop = new DropTarget(enqueue, 1); }
+ ~ClassFactory() { delete(m_drop); }
+
+ STDMETHODIMP QueryInterface (REFIID riid, LPVOID * ppvObj)
+ {
+ if (riid == IID_IClassFactory || riid == IID_IUnknown)
+ {
+ *ppvObj = this;
+ return S_OK;
+ }
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+ STDMETHODIMP_(ULONG) AddRef ()
+ { return 0; }
+ STDMETHODIMP_(ULONG) Release ()
+ { return 0; }
+
+ STDMETHODIMP CreateInstance(IUnknown * pUnkOuter, REFIID riid, void ** ppvObject)
+ {
+ if (pUnkOuter != NULL)
+ {
+ return CLASS_E_NOAGGREGATION;
+ }
+ if (riid == IID_IDropTarget || riid == IID_IUnknown)
+ {
+ *ppvObject = m_drop;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+ }
+ STDMETHODIMP LockServer(BOOL fLock)
+ {
+ return S_OK;
+ }
+private:
+ DropTarget *m_drop;
+};
+
+static ClassFactory m_playCF(0);
+static ClassFactory m_enqueueCF(1);
+static ClassFactory m_enqueuePlayCF(2);
+
+static DWORD m_exposePlayHandle = NULL, m_exposeEnqueueHandle = NULL, m_exposeEnqueuePlayHandle = NULL;
+
+extern "C"
+{
+
+ void InitDragDrops()
+ {
+ SetWindowLong(hMainWindow, GWL_EXSTYLE, GetWindowLongW(hMainWindow, GWL_EXSTYLE)|(WS_EX_ACCEPTFILES));
+
+ refuseDrops = false;
+ }
+
+ void Ole_initDragDrop()
+ {
+ OleInitialize(NULL);
+ RegisterDragDrop(hMainWindow, &m_target);
+ RegisterDragDrop(hPLWindow, &m_target);
+ if (hVideoWindow) RegisterDragDrop(hVideoWindow, &m_target);
+
+ // {46986115-84D6-459c-8F95-52DD653E532E}
+ static const GUID playGuid =
+ { 0x46986115, 0x84D6, 0x459c, { 0x8f, 0x95, 0x52, 0xdd, 0x65, 0x3e, 0x53, 0x2e } };
+ if (CoRegisterClassObject(playGuid, &m_playCF, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &m_exposePlayHandle) != S_OK)
+ m_exposePlayHandle = NULL;
+
+ // {77A366BA-2BE4-4a1e-9263-7734AA3E99A2}
+ static const GUID enqueueGuid =
+ { 0x77A366BA, 0x2BE4, 0x4a1e, { 0x92, 0x63, 0x77, 0x34, 0xAA, 0x3e, 0x99, 0xa2 } };
+ if (CoRegisterClassObject(enqueueGuid, &m_enqueueCF, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &m_exposeEnqueueHandle) != S_OK)
+ m_exposeEnqueueHandle = NULL;
+
+ // {ED50B649-42B0-4153-9E99-54C45F6BD708}
+ static const GUID enqueuePlayGuid =
+ { 0xed50b649, 0x42b0, 0x4153, { 0x9e, 0x99, 0x54, 0xc4, 0x5f, 0x6b, 0xd7, 0x8 } };
+ if (CoRegisterClassObject(enqueuePlayGuid, &m_enqueuePlayCF, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &m_exposeEnqueuePlayHandle) != S_OK)
+ m_exposeEnqueuePlayHandle = NULL;
+ }
+
+ void UninitDragDrops()
+ {
+ SetWindowLong(hMainWindow, GWL_EXSTYLE, GetWindowLongW(hMainWindow, GWL_EXSTYLE)&~(WS_EX_ACCEPTFILES));
+ refuseDrops = true;
+ }
+
+ void Ole_uninitDragDrop()
+ {
+ if (hVideoWindow) RevokeDragDrop(hVideoWindow);
+ RevokeDragDrop(hPLWindow);
+ RevokeDragDrop(hMainWindow);
+
+ if (m_exposePlayHandle)
+ CoRevokeClassObject(m_exposePlayHandle);
+ if (m_exposeEnqueueHandle)
+ CoRevokeClassObject(m_exposeEnqueueHandle);
+ if (m_exposeEnqueuePlayHandle)
+ CoRevokeClassObject(m_exposeEnqueuePlayHandle);
+ OleUninitialize();
+ }
+
+ void *Ole_getDropTarget()
+ {
+ return (void *)&m_target;
+ }
+}; \ No newline at end of file