Index: src/chext/DropMenuExt.cpp =================================================================== diff -u -N -rcd5a36f1507a4131ce652879565c0770b36dd953 -r0373359eff650e8cf04a5992711ef9f20347536f --- src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision cd5a36f1507a4131ce652879565c0770b36dd953) +++ src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -28,14 +28,10 @@ extern CSharedConfigStruct* g_pscsShared; -#define DE_COPY 0 -#define DE_MOVE 1 -#define DE_SPECIAL 2 -#define DE_AUTO 3 - CDropMenuExt::CDropMenuExt() : m_piShellExtControl(NULL) { + m_szDstPath[0] = _T('\0'); CoCreateInstance(CLSID_CShellExtControl, NULL, CLSCTX_ALL, IID_IShellExtControl, (void**)&m_piShellExtControl); } @@ -48,8 +44,68 @@ } } -STDMETHODIMP CDropMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) +HRESULT CDropMenuExt::ReadFileData(IDataObject* piDataObject) { + _ASSERTE(piDataObject); + if(!piDataObject) + return E_INVALIDARG; + + // retrieve some informations from the data object + STGMEDIUM medium; + FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + + // retrieve the CF_HDROP-type data from data object + HRESULT hResult = piDataObject->QueryGetData(&fe); + if(hResult != S_OK) + return hResult; + hResult = piDataObject->GetData(&fe, &medium); + if(SUCCEEDED(hResult)) + GetDataFromClipboard(static_cast(medium.hGlobal), m_szDstPath, &m_bBuffer.m_pszFiles, &m_bBuffer.m_iDataSize); + + ReleaseStgMedium(&medium); + + return hResult; +} + +STDMETHODIMP CDropMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/) +{ + ATLTRACE(_T("CDropMenuExt::Initialize()\n")); + if(!piDataObject) + return E_FAIL; + + // remember the keyboard state for later + m_asSelector.ResetState(); + m_asSelector.ReadKeyboardState(); + + // check if this extension is enabled + HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); + if(FAILED(hResult) || hResult == S_FALSE) + return hResult; + + // find window + HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if(hWnd == NULL) + return E_FAIL; + + // retrieve config from CH + ::SendMessage(hWnd, WM_GETCONFIG, GC_DRAGDROP, 0); + + // get dest folder + m_szDstPath[0]=_T('\0'); + if(!SHGetPathFromIDList(pidlFolder, m_szDstPath)) + return E_FAIL; + + // now retrieve the preferred drop effect from IDataObject + hResult = m_asSelector.ReadStateFromDataObject(piDataObject, m_szDstPath); + if(SUCCEEDED(hResult)) + hResult = ReadFileData(piDataObject); + + return hResult; +} + +STDMETHODIMP CDropMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT uFlags) +{ + ATLTRACE(_T("CDropMenuExt::QueryContextMenu()\n")); // check options HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult) || hResult == S_FALSE) @@ -58,73 +114,59 @@ // find CH's window HWND hWnd; hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd) - { - // get state of keys - bool bShift=(GetKeyState(VK_SHIFT) & 0x80) != 0; - bool bCtrl=(GetKeyState(VK_CONTROL) & 0x80) != 0; - bool bAlt=(GetKeyState(VK_MENU) & 0x80) != 0; + if(!hWnd) + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); -/* OTF2("CDropMenuExt::QueryContextMenu - uFlags=%lu (", uFlags); - if (uFlags & CMF_CANRENAME) - OTF2("CMF_CANRENAME "); - if (uFlags & CMF_DEFAULTONLY) - OTF2("CMF_DEFAULTONLY "); - if (uFlags & CMF_EXPLORE) - OTF2("CMF_EXPLORE "); - if (uFlags & CMF_EXTENDEDVERBS) - OTF2("CMF_EXTENDEDVERBS "); - if (uFlags & CMF_INCLUDESTATIC) - OTF2("CMF_INCLUDESTATIC "); - if (uFlags & CMF_NODEFAULT) - OTF2("CMF_NODEFAULT "); - if (uFlags & CMF_NORMAL) - OTF2("CMF_NORMAL "); - if (uFlags & CMF_NOVERBS) - OTF2("CMF_NOVERBS "); - if (uFlags & CMF_VERBSONLY) - OTF2("CMF_VERBSONLY "); - OTF2(")\r\n"); - OTF2("Keys State: Shift:%u, ctrl:%u, alt:%u\r\n", bShift, bCtrl, bAlt); -*/ - // got a config - _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); - int iCommandCount=0; + // retrieve the default menu item; if not available, fallback to the default heuristics + m_asSelector.ReadStateFromMenu(hmenu); - if (g_pscsShared->uiFlags & DD_COPY_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+0, pCommand[0].szCommand); - if (g_pscsShared->bOverrideDefault) - ::SetMenuDefaultItem(hmenu, idCmdFirst+0, FALSE); - iCommandCount++; - } + // retrieve the action information to be performed + ulong_t ulActionSource = m_asSelector.GetActionSource(); - if (g_pscsShared->uiFlags & DD_MOVE_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+1, pCommand[1].szCommand); - if (g_pscsShared->bOverrideDefault && (bShift || (m_uiDropEffect == DE_MOVE && (m_bExplorer || !bCtrl))) ) - ::SetMenuDefaultItem(hmenu, idCmdFirst+1, FALSE); - iCommandCount++; - } + // determine if we want to perform override based on user options and detected action source + bool bIntercept = (g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptDragAndDrop && ulActionSource & TActionSelector::eSrc_DropMenu || + g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptKeyboardActions && ulActionSource & TActionSelector::eSrc_Keyboard || + g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptCtxMenuActions && ulActionSource & TActionSelector::eSrc_CtxMenu); - if (g_pscsShared->uiFlags & DD_COPYMOVESPECIAL_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+2, pCommand[2].szCommand); - if (g_pscsShared->bOverrideDefault && (bAlt || (bCtrl && bShift) || m_uiDropEffect == DE_SPECIAL) && !(m_uiDropEffect == DE_MOVE)) - ::SetMenuDefaultItem(hmenu, idCmdFirst+2, FALSE); - iCommandCount++; - } - - if (iCommandCount) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_SEPARATOR, idCmdFirst+3, NULL); - iCommandCount++; - } + // now convert our information to the + // got a config + _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); + int iCommandCount=0; - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 4); + // ad new menu items, depending on the received configuration + if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_COPY_FLAG) + { + ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+0, pCommand[0].szCommand); + if(bIntercept && ulActionSource & TActionSelector::eAction_Copy) + ::SetMenuDefaultItem(hmenu, idCmdFirst+0, FALSE); + iCommandCount++; } - else - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); + + if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_MOVE_FLAG) + { + ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+1, pCommand[1].szCommand); + if(bIntercept && ulActionSource & TActionSelector::eAction_Move) + ::SetMenuDefaultItem(hmenu, idCmdFirst+1, FALSE); + iCommandCount++; + } + + if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG) + { + ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+2, pCommand[2].szCommand); +/* + if(g_pscsShared->bOverrideDefault && m_eDropEffect == eEffect_Special) + ::SetMenuDefaultItem(hmenu, idCmdFirst+2, FALSE); +*/ + iCommandCount++; + } + + if(iCommandCount) + { + ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_SEPARATOR, idCmdFirst+3, NULL); + iCommandCount++; + } + + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 4); } STDMETHODIMP CDropMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) @@ -137,14 +179,14 @@ return hResult; } - if (uFlags == GCS_HELPTEXTW) + if(uFlags == GCS_HELPTEXTW) { USES_CONVERSION; // find CH's window HWND hWnd; hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd) + if(hWnd) { _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); @@ -166,13 +208,13 @@ else wcsncpy(reinterpret_cast(pszName), L"", cchMax); } - if (uFlags == GCS_HELPTEXTA) + if(uFlags == GCS_HELPTEXTA) { // find CH's window HWND hWnd; hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd) + if(hWnd) { _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); @@ -198,156 +240,16 @@ return S_OK; } -STDMETHODIMP CDropMenuExt::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY /*hkeyProgID*/) -{ -// OTF2("Initialize cdropmenuext\r\n"); - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return hResult; - - // find window - HWND hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd == NULL) - return E_FAIL; - - // gets the config from CH - ::SendMessage(hWnd, WM_GETCONFIG, GC_DRAGDROP, 0); - -// OTF2("========================================================\r\n"); -// OTF2("Initialize drag&drop context menu handler pidlFolder=%lu, lpdobj=%lu\r\n", pidlFolder, lpdobj); - - // get dest folder - m_szDstPath[0]=_T('\0'); - if (!SHGetPathFromIDList(pidlFolder, m_szDstPath)) - return E_FAIL; - - // get data from IDataObject - files to copy/move - if (lpdobj) - { -// ReportAvailableFormats(lpdobj); - // file list - STGMEDIUM medium; - FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; - - HRESULT hr = lpdobj->GetData(&fe, &medium); - if (FAILED(hr)) - return E_FAIL; - - GetDataFromClipboard(static_cast(medium.hGlobal), m_szDstPath, &m_bBuffer.m_pszFiles, &m_bBuffer.m_iDataSize); - - // set std text - switch (g_pscsShared->uiDefaultAction) - { - case 1: - // move action - m_uiDropEffect=DE_MOVE; - break; - case 2: - // special operation - m_uiDropEffect=DE_SPECIAL; - break; - case 3: - { - // autodetecting - copy or move - check the last path - UINT uiCount=DragQueryFile((HDROP)medium.hGlobal, 0xffffffff, NULL, 0); - TCHAR szPath[_MAX_PATH]; - if (DragQueryFile((HDROP)medium.hGlobal, uiCount-1, szPath, _MAX_PATH)) - { - if (_tcsncmp(szPath, _T("\\\\"), 2) == 0) - { - TCHAR* pFnd=_tcsstr(szPath+2, _T("\\")); - - if (pFnd) - { - int iCount; - // find another - TCHAR *pSecond=_tcsstr(pFnd+1, _T("\\")); - if (pSecond) - { - iCount=pSecond-szPath; -// OTF2("Counted: %lu\r\n", iCount); - } - else - iCount=_tcslen(szPath); - - // found - compare -// OTF2("Compare %s and %s\r\n", szPath, m_szDstPath); - if (_tcsnicmp(szPath, m_szDstPath, iCount) == 0) - { -// OTF2("OP: MOVE\r\n"); - m_uiDropEffect=DE_MOVE; - } - else - { -// OTF2("OP: COPY\r\n"); - m_uiDropEffect=DE_COPY; - } - } - else - m_uiDropEffect=DE_COPY; - - } - else - { - // local path - check drive letter - if (m_szDstPath[0] == szPath[0]) - m_uiDropEffect=DE_MOVE; - else - m_uiDropEffect=DE_COPY; - } - } - else - m_uiDropEffect=DE_COPY; - } - break; - - default: - m_uiDropEffect=DE_COPY; // std copying - break; - } - - ReleaseStgMedium(&medium); - - // get operation type - UINT cf=RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); - fe.cfFormat=(unsigned short)cf; - - // if explorer knows better - change effect - m_bExplorer=false; - hr=lpdobj->GetData(&fe, &medium); - if (SUCCEEDED(hr)) - { - // specify operation - LPVOID lpv=GlobalLock(medium.hGlobal); - if (lpv) - { - UINT uiDrop=*((DWORD*)lpv); - if (uiDrop & DROPEFFECT_MOVE) - m_uiDropEffect=DE_MOVE; - else - m_uiDropEffect=DE_COPY; - m_bExplorer=true; - -// OTF2("Detected operation %lu\r\n", m_uiDropEffect); - GlobalUnlock(medium.hGlobal); - } - - ReleaseStgMedium(&medium); - } - } - - return S_OK; -} - STDMETHODIMP CDropMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { + ATLTRACE(_T("CDropMenuExt::InvokeCommand()\n")); HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult) || hResult == S_FALSE) return E_FAIL; // required to process other InvokeCommand handlers. // find window HWND hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd == NULL) + if(hWnd == NULL) return E_FAIL; // commands @@ -365,4 +267,15 @@ m_bBuffer.Destroy(); return S_OK; -} \ No newline at end of file +} + +STDMETHODIMP CDropMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return HandleMenuMsg2(uMsg, wParam, lParam, NULL); +} + +STDMETHODIMP CDropMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult) +{ + ATLTRACE(_T("CDropMenuExt::HandleMenuMsg2(): uMsg = %lu, wParam = %lu, lParam = %lu\n"), uMsg, wParam, lParam); + return S_FALSE; +}