17db96d56Sopenharmony_ci// Support back to Vista 27db96d56Sopenharmony_ci#define _WIN32_WINNT _WIN32_WINNT_VISTA 37db96d56Sopenharmony_ci#include <sdkddkver.h> 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci// Use WRL to define a classic COM class 67db96d56Sopenharmony_ci#define __WRL_CLASSIC_COM__ 77db96d56Sopenharmony_ci#include <wrl.h> 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci#include <windows.h> 107db96d56Sopenharmony_ci#include <shlobj.h> 117db96d56Sopenharmony_ci#include <shlwapi.h> 127db96d56Sopenharmony_ci#include <olectl.h> 137db96d56Sopenharmony_ci#include <strsafe.h> 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci#define DDWM_UPDATEWINDOW (WM_USER+3) 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_cistatic HINSTANCE hModule; 187db96d56Sopenharmony_cistatic CLIPFORMAT cfDropDescription; 197db96d56Sopenharmony_cistatic CLIPFORMAT cfDragWindow; 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci#define CLASS_GUID "{BEA218D2-6950-497B-9434-61683EC065FE}" 227db96d56Sopenharmony_cistatic const LPCWSTR CLASS_SUBKEY = L"Software\\Classes\\CLSID\\" CLASS_GUID; 237db96d56Sopenharmony_cistatic const LPCWSTR DRAG_MESSAGE = L"Open with %1"; 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ciusing namespace Microsoft::WRL; 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ciHRESULT FilenameListCchLengthA(LPCSTR pszSource, size_t cchMax, size_t *pcchLength, size_t *pcchCount) { 287db96d56Sopenharmony_ci HRESULT hr = S_OK; 297db96d56Sopenharmony_ci size_t count = 0; 307db96d56Sopenharmony_ci size_t length = 0; 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci while (pszSource && pszSource[0]) { 337db96d56Sopenharmony_ci size_t oneLength; 347db96d56Sopenharmony_ci hr = StringCchLengthA(pszSource, cchMax - length, &oneLength); 357db96d56Sopenharmony_ci if (FAILED(hr)) { 367db96d56Sopenharmony_ci return hr; 377db96d56Sopenharmony_ci } 387db96d56Sopenharmony_ci count += 1; 397db96d56Sopenharmony_ci length += oneLength + (strchr(pszSource, ' ') ? 3 : 1); 407db96d56Sopenharmony_ci pszSource = &pszSource[oneLength + 1]; 417db96d56Sopenharmony_ci } 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci *pcchCount = count; 447db96d56Sopenharmony_ci *pcchLength = length; 457db96d56Sopenharmony_ci return hr; 467db96d56Sopenharmony_ci} 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ciHRESULT FilenameListCchLengthW(LPCWSTR pszSource, size_t cchMax, size_t *pcchLength, size_t *pcchCount) { 497db96d56Sopenharmony_ci HRESULT hr = S_OK; 507db96d56Sopenharmony_ci size_t count = 0; 517db96d56Sopenharmony_ci size_t length = 0; 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci while (pszSource && pszSource[0]) { 547db96d56Sopenharmony_ci size_t oneLength; 557db96d56Sopenharmony_ci hr = StringCchLengthW(pszSource, cchMax - length, &oneLength); 567db96d56Sopenharmony_ci if (FAILED(hr)) { 577db96d56Sopenharmony_ci return hr; 587db96d56Sopenharmony_ci } 597db96d56Sopenharmony_ci count += 1; 607db96d56Sopenharmony_ci length += oneLength + (wcschr(pszSource, ' ') ? 3 : 1); 617db96d56Sopenharmony_ci pszSource = &pszSource[oneLength + 1]; 627db96d56Sopenharmony_ci } 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci *pcchCount = count; 657db96d56Sopenharmony_ci *pcchLength = length; 667db96d56Sopenharmony_ci return hr; 677db96d56Sopenharmony_ci} 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ciHRESULT FilenameListCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, LPCSTR pszSource, LPCSTR pszSeparator) { 707db96d56Sopenharmony_ci HRESULT hr = S_OK; 717db96d56Sopenharmony_ci size_t count = 0; 727db96d56Sopenharmony_ci size_t length = 0; 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci while (pszSource[0]) { 757db96d56Sopenharmony_ci STRSAFE_LPSTR newDest; 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci hr = StringCchCopyExA(pszDest, cchDest, pszSource, &newDest, &cchDest, 0); 787db96d56Sopenharmony_ci if (FAILED(hr)) { 797db96d56Sopenharmony_ci return hr; 807db96d56Sopenharmony_ci } 817db96d56Sopenharmony_ci pszSource += (newDest - pszDest) + 1; 827db96d56Sopenharmony_ci pszDest = PathQuoteSpacesA(pszDest) ? newDest + 2 : newDest; 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci if (pszSource[0]) { 857db96d56Sopenharmony_ci hr = StringCchCopyExA(pszDest, cchDest, pszSeparator, &newDest, &cchDest, 0); 867db96d56Sopenharmony_ci if (FAILED(hr)) { 877db96d56Sopenharmony_ci return hr; 887db96d56Sopenharmony_ci } 897db96d56Sopenharmony_ci pszDest = newDest; 907db96d56Sopenharmony_ci } 917db96d56Sopenharmony_ci } 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci return hr; 947db96d56Sopenharmony_ci} 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ciHRESULT FilenameListCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, LPCWSTR pszSource, LPCWSTR pszSeparator) { 977db96d56Sopenharmony_ci HRESULT hr = S_OK; 987db96d56Sopenharmony_ci size_t count = 0; 997db96d56Sopenharmony_ci size_t length = 0; 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci while (pszSource[0]) { 1027db96d56Sopenharmony_ci STRSAFE_LPWSTR newDest; 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_ci hr = StringCchCopyExW(pszDest, cchDest, pszSource, &newDest, &cchDest, 0); 1057db96d56Sopenharmony_ci if (FAILED(hr)) { 1067db96d56Sopenharmony_ci return hr; 1077db96d56Sopenharmony_ci } 1087db96d56Sopenharmony_ci pszSource += (newDest - pszDest) + 1; 1097db96d56Sopenharmony_ci pszDest = PathQuoteSpacesW(pszDest) ? newDest + 2 : newDest; 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ci if (pszSource[0]) { 1127db96d56Sopenharmony_ci hr = StringCchCopyExW(pszDest, cchDest, pszSeparator, &newDest, &cchDest, 0); 1137db96d56Sopenharmony_ci if (FAILED(hr)) { 1147db96d56Sopenharmony_ci return hr; 1157db96d56Sopenharmony_ci } 1167db96d56Sopenharmony_ci pszDest = newDest; 1177db96d56Sopenharmony_ci } 1187db96d56Sopenharmony_ci } 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci return hr; 1217db96d56Sopenharmony_ci} 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ciclass DECLSPEC_UUID(CLASS_GUID) PyShellExt : public RuntimeClass< 1247db96d56Sopenharmony_ci RuntimeClassFlags<ClassicCom>, 1257db96d56Sopenharmony_ci IDropTarget, 1267db96d56Sopenharmony_ci IPersistFile 1277db96d56Sopenharmony_ci> 1287db96d56Sopenharmony_ci{ 1297db96d56Sopenharmony_ci LPOLESTR target, target_dir; 1307db96d56Sopenharmony_ci DWORD target_mode; 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci IDataObject *data_obj; 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_cipublic: 1357db96d56Sopenharmony_ci PyShellExt() : target(NULL), target_dir(NULL), target_mode(0), data_obj(NULL) { 1367db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::PyShellExt"); 1377db96d56Sopenharmony_ci } 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci ~PyShellExt() { 1407db96d56Sopenharmony_ci if (target) { 1417db96d56Sopenharmony_ci CoTaskMemFree(target); 1427db96d56Sopenharmony_ci } 1437db96d56Sopenharmony_ci if (target_dir) { 1447db96d56Sopenharmony_ci CoTaskMemFree(target_dir); 1457db96d56Sopenharmony_ci } 1467db96d56Sopenharmony_ci if (data_obj) { 1477db96d56Sopenharmony_ci data_obj->Release(); 1487db96d56Sopenharmony_ci } 1497db96d56Sopenharmony_ci } 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_ciprivate: 1527db96d56Sopenharmony_ci HRESULT UpdateDropDescription(IDataObject *pDataObj) { 1537db96d56Sopenharmony_ci STGMEDIUM medium; 1547db96d56Sopenharmony_ci FORMATETC fmt = { 1557db96d56Sopenharmony_ci cfDropDescription, 1567db96d56Sopenharmony_ci NULL, 1577db96d56Sopenharmony_ci DVASPECT_CONTENT, 1587db96d56Sopenharmony_ci -1, 1597db96d56Sopenharmony_ci TYMED_HGLOBAL 1607db96d56Sopenharmony_ci }; 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci auto hr = pDataObj->GetData(&fmt, &medium); 1637db96d56Sopenharmony_ci if (FAILED(hr)) { 1647db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::UpdateDropDescription - failed to get DROPDESCRIPTION format"); 1657db96d56Sopenharmony_ci return hr; 1667db96d56Sopenharmony_ci } 1677db96d56Sopenharmony_ci if (!medium.hGlobal) { 1687db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::UpdateDropDescription - DROPDESCRIPTION format had NULL hGlobal"); 1697db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 1707db96d56Sopenharmony_ci return E_FAIL; 1717db96d56Sopenharmony_ci } 1727db96d56Sopenharmony_ci auto dd = (DROPDESCRIPTION*)GlobalLock(medium.hGlobal); 1737db96d56Sopenharmony_ci if (!dd) { 1747db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::UpdateDropDescription - failed to lock DROPDESCRIPTION hGlobal"); 1757db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 1767db96d56Sopenharmony_ci return E_FAIL; 1777db96d56Sopenharmony_ci } 1787db96d56Sopenharmony_ci StringCchCopy(dd->szMessage, sizeof(dd->szMessage) / sizeof(dd->szMessage[0]), DRAG_MESSAGE); 1797db96d56Sopenharmony_ci StringCchCopy(dd->szInsert, sizeof(dd->szInsert) / sizeof(dd->szInsert[0]), PathFindFileNameW(target)); 1807db96d56Sopenharmony_ci dd->type = DROPIMAGE_MOVE; 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci GlobalUnlock(medium.hGlobal); 1837db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci return S_OK; 1867db96d56Sopenharmony_ci } 1877db96d56Sopenharmony_ci 1887db96d56Sopenharmony_ci HRESULT GetDragWindow(IDataObject *pDataObj, HWND *phWnd) { 1897db96d56Sopenharmony_ci HRESULT hr; 1907db96d56Sopenharmony_ci HWND *pMem; 1917db96d56Sopenharmony_ci STGMEDIUM medium; 1927db96d56Sopenharmony_ci FORMATETC fmt = { 1937db96d56Sopenharmony_ci cfDragWindow, 1947db96d56Sopenharmony_ci NULL, 1957db96d56Sopenharmony_ci DVASPECT_CONTENT, 1967db96d56Sopenharmony_ci -1, 1977db96d56Sopenharmony_ci TYMED_HGLOBAL 1987db96d56Sopenharmony_ci }; 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ci hr = pDataObj->GetData(&fmt, &medium); 2017db96d56Sopenharmony_ci if (FAILED(hr)) { 2027db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::GetDragWindow - failed to get DragWindow format"); 2037db96d56Sopenharmony_ci return hr; 2047db96d56Sopenharmony_ci } 2057db96d56Sopenharmony_ci if (!medium.hGlobal) { 2067db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::GetDragWindow - DragWindow format had NULL hGlobal"); 2077db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 2087db96d56Sopenharmony_ci return E_FAIL; 2097db96d56Sopenharmony_ci } 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci pMem = (HWND*)GlobalLock(medium.hGlobal); 2127db96d56Sopenharmony_ci if (!pMem) { 2137db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::GetDragWindow - failed to lock DragWindow hGlobal"); 2147db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 2157db96d56Sopenharmony_ci return E_FAIL; 2167db96d56Sopenharmony_ci } 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci *phWnd = *pMem; 2197db96d56Sopenharmony_ci 2207db96d56Sopenharmony_ci GlobalUnlock(medium.hGlobal); 2217db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ci return S_OK; 2247db96d56Sopenharmony_ci } 2257db96d56Sopenharmony_ci 2267db96d56Sopenharmony_ci HRESULT GetArguments(IDataObject *pDataObj, LPCWSTR *pArguments) { 2277db96d56Sopenharmony_ci HRESULT hr; 2287db96d56Sopenharmony_ci DROPFILES *pdropfiles; 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ci STGMEDIUM medium; 2317db96d56Sopenharmony_ci FORMATETC fmt = { 2327db96d56Sopenharmony_ci CF_HDROP, 2337db96d56Sopenharmony_ci NULL, 2347db96d56Sopenharmony_ci DVASPECT_CONTENT, 2357db96d56Sopenharmony_ci -1, 2367db96d56Sopenharmony_ci TYMED_HGLOBAL 2377db96d56Sopenharmony_ci }; 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ci hr = pDataObj->GetData(&fmt, &medium); 2407db96d56Sopenharmony_ci if (FAILED(hr)) { 2417db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::GetArguments - failed to get CF_HDROP format"); 2427db96d56Sopenharmony_ci return hr; 2437db96d56Sopenharmony_ci } 2447db96d56Sopenharmony_ci if (!medium.hGlobal) { 2457db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::GetArguments - CF_HDROP format had NULL hGlobal"); 2467db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 2477db96d56Sopenharmony_ci return E_FAIL; 2487db96d56Sopenharmony_ci } 2497db96d56Sopenharmony_ci 2507db96d56Sopenharmony_ci pdropfiles = (DROPFILES*)GlobalLock(medium.hGlobal); 2517db96d56Sopenharmony_ci if (!pdropfiles) { 2527db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::GetArguments - failed to lock CF_HDROP hGlobal"); 2537db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 2547db96d56Sopenharmony_ci return E_FAIL; 2557db96d56Sopenharmony_ci } 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ci if (pdropfiles->fWide) { 2587db96d56Sopenharmony_ci LPCWSTR files = (LPCWSTR)((char*)pdropfiles + pdropfiles->pFiles); 2597db96d56Sopenharmony_ci size_t len, count; 2607db96d56Sopenharmony_ci hr = FilenameListCchLengthW(files, 32767, &len, &count); 2617db96d56Sopenharmony_ci if (SUCCEEDED(hr)) { 2627db96d56Sopenharmony_ci LPWSTR args = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (len + 1)); 2637db96d56Sopenharmony_ci if (args) { 2647db96d56Sopenharmony_ci hr = FilenameListCchCopyW(args, 32767, files, L" "); 2657db96d56Sopenharmony_ci if (SUCCEEDED(hr)) { 2667db96d56Sopenharmony_ci *pArguments = args; 2677db96d56Sopenharmony_ci } else { 2687db96d56Sopenharmony_ci CoTaskMemFree(args); 2697db96d56Sopenharmony_ci } 2707db96d56Sopenharmony_ci } else { 2717db96d56Sopenharmony_ci hr = E_OUTOFMEMORY; 2727db96d56Sopenharmony_ci } 2737db96d56Sopenharmony_ci } 2747db96d56Sopenharmony_ci } else { 2757db96d56Sopenharmony_ci LPCSTR files = (LPCSTR)((char*)pdropfiles + pdropfiles->pFiles); 2767db96d56Sopenharmony_ci size_t len, count; 2777db96d56Sopenharmony_ci hr = FilenameListCchLengthA(files, 32767, &len, &count); 2787db96d56Sopenharmony_ci if (SUCCEEDED(hr)) { 2797db96d56Sopenharmony_ci LPSTR temp = (LPSTR)CoTaskMemAlloc(sizeof(CHAR) * (len + 1)); 2807db96d56Sopenharmony_ci if (temp) { 2817db96d56Sopenharmony_ci hr = FilenameListCchCopyA(temp, 32767, files, " "); 2827db96d56Sopenharmony_ci if (SUCCEEDED(hr)) { 2837db96d56Sopenharmony_ci int wlen = MultiByteToWideChar(CP_ACP, 0, temp, (int)len, NULL, 0); 2847db96d56Sopenharmony_ci if (wlen) { 2857db96d56Sopenharmony_ci LPWSTR args = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (wlen + 1)); 2867db96d56Sopenharmony_ci if (MultiByteToWideChar(CP_ACP, 0, temp, (int)len, args, wlen + 1)) { 2877db96d56Sopenharmony_ci *pArguments = args; 2887db96d56Sopenharmony_ci } else { 2897db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::GetArguments - failed to convert multi-byte to wide-char path"); 2907db96d56Sopenharmony_ci CoTaskMemFree(args); 2917db96d56Sopenharmony_ci hr = E_FAIL; 2927db96d56Sopenharmony_ci } 2937db96d56Sopenharmony_ci } else { 2947db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::GetArguments - failed to get length of wide-char path"); 2957db96d56Sopenharmony_ci hr = E_FAIL; 2967db96d56Sopenharmony_ci } 2977db96d56Sopenharmony_ci } 2987db96d56Sopenharmony_ci CoTaskMemFree(temp); 2997db96d56Sopenharmony_ci } else { 3007db96d56Sopenharmony_ci hr = E_OUTOFMEMORY; 3017db96d56Sopenharmony_ci } 3027db96d56Sopenharmony_ci } 3037db96d56Sopenharmony_ci } 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci GlobalUnlock(medium.hGlobal); 3067db96d56Sopenharmony_ci ReleaseStgMedium(&medium); 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ci return hr; 3097db96d56Sopenharmony_ci } 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ci HRESULT NotifyDragWindow(HWND hwnd) { 3127db96d56Sopenharmony_ci LRESULT res; 3137db96d56Sopenharmony_ci 3147db96d56Sopenharmony_ci if (!hwnd) { 3157db96d56Sopenharmony_ci return S_FALSE; 3167db96d56Sopenharmony_ci } 3177db96d56Sopenharmony_ci 3187db96d56Sopenharmony_ci res = SendMessage(hwnd, DDWM_UPDATEWINDOW, 0, NULL); 3197db96d56Sopenharmony_ci 3207db96d56Sopenharmony_ci if (res) { 3217db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::NotifyDragWindow - failed to post DDWM_UPDATEWINDOW"); 3227db96d56Sopenharmony_ci return E_FAIL; 3237db96d56Sopenharmony_ci } 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ci return S_OK; 3267db96d56Sopenharmony_ci } 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_cipublic: 3297db96d56Sopenharmony_ci // IDropTarget implementation 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci STDMETHODIMP DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { 3327db96d56Sopenharmony_ci HWND hwnd; 3337db96d56Sopenharmony_ci 3347db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DragEnter"); 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_ci pDataObj->AddRef(); 3377db96d56Sopenharmony_ci data_obj = pDataObj; 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_ci *pdwEffect = DROPEFFECT_MOVE; 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci if (FAILED(UpdateDropDescription(data_obj))) { 3427db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DragEnter - failed to update drop description"); 3437db96d56Sopenharmony_ci } 3447db96d56Sopenharmony_ci if (FAILED(GetDragWindow(data_obj, &hwnd))) { 3457db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DragEnter - failed to get drag window"); 3467db96d56Sopenharmony_ci } 3477db96d56Sopenharmony_ci if (FAILED(NotifyDragWindow(hwnd))) { 3487db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DragEnter - failed to notify drag window"); 3497db96d56Sopenharmony_ci } 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ci return S_OK; 3527db96d56Sopenharmony_ci } 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci STDMETHODIMP DragLeave() { 3557db96d56Sopenharmony_ci return S_OK; 3567db96d56Sopenharmony_ci } 3577db96d56Sopenharmony_ci 3587db96d56Sopenharmony_ci STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { 3597db96d56Sopenharmony_ci return S_OK; 3607db96d56Sopenharmony_ci } 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci STDMETHODIMP Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { 3637db96d56Sopenharmony_ci LPCWSTR args; 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Drop"); 3667db96d56Sopenharmony_ci *pdwEffect = DROPEFFECT_NONE; 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci if (pDataObj != data_obj) { 3697db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Drop - unexpected data object"); 3707db96d56Sopenharmony_ci return E_FAIL; 3717db96d56Sopenharmony_ci } 3727db96d56Sopenharmony_ci 3737db96d56Sopenharmony_ci data_obj->Release(); 3747db96d56Sopenharmony_ci data_obj = NULL; 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_ci if (SUCCEEDED(GetArguments(pDataObj, &args))) { 3777db96d56Sopenharmony_ci OutputDebugString(args); 3787db96d56Sopenharmony_ci ShellExecute(NULL, NULL, target, args, target_dir, SW_NORMAL); 3797db96d56Sopenharmony_ci 3807db96d56Sopenharmony_ci CoTaskMemFree((LPVOID)args); 3817db96d56Sopenharmony_ci } else { 3827db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Drop - failed to get launch arguments"); 3837db96d56Sopenharmony_ci } 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_ci return S_OK; 3867db96d56Sopenharmony_ci } 3877db96d56Sopenharmony_ci 3887db96d56Sopenharmony_ci // IPersistFile implementation 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName) { 3917db96d56Sopenharmony_ci HRESULT hr; 3927db96d56Sopenharmony_ci size_t len; 3937db96d56Sopenharmony_ci 3947db96d56Sopenharmony_ci if (!ppszFileName) { 3957db96d56Sopenharmony_ci return E_POINTER; 3967db96d56Sopenharmony_ci } 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_ci hr = StringCchLength(target, STRSAFE_MAX_CCH - 1, &len); 3997db96d56Sopenharmony_ci if (FAILED(hr)) { 4007db96d56Sopenharmony_ci return E_FAIL; 4017db96d56Sopenharmony_ci } 4027db96d56Sopenharmony_ci 4037db96d56Sopenharmony_ci *ppszFileName = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) * (len + 1)); 4047db96d56Sopenharmony_ci if (!*ppszFileName) { 4057db96d56Sopenharmony_ci return E_OUTOFMEMORY; 4067db96d56Sopenharmony_ci } 4077db96d56Sopenharmony_ci 4087db96d56Sopenharmony_ci hr = StringCchCopy(*ppszFileName, len + 1, target); 4097db96d56Sopenharmony_ci if (FAILED(hr)) { 4107db96d56Sopenharmony_ci CoTaskMemFree(*ppszFileName); 4117db96d56Sopenharmony_ci *ppszFileName = NULL; 4127db96d56Sopenharmony_ci return E_FAIL; 4137db96d56Sopenharmony_ci } 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci return S_OK; 4167db96d56Sopenharmony_ci } 4177db96d56Sopenharmony_ci 4187db96d56Sopenharmony_ci STDMETHODIMP IsDirty() { 4197db96d56Sopenharmony_ci return S_FALSE; 4207db96d56Sopenharmony_ci } 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ci STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode) { 4237db96d56Sopenharmony_ci HRESULT hr; 4247db96d56Sopenharmony_ci size_t len; 4257db96d56Sopenharmony_ci 4267db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Load"); 4277db96d56Sopenharmony_ci OutputDebugString(pszFileName); 4287db96d56Sopenharmony_ci 4297db96d56Sopenharmony_ci hr = StringCchLength(pszFileName, STRSAFE_MAX_CCH - 1, &len); 4307db96d56Sopenharmony_ci if (FAILED(hr)) { 4317db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Load - failed to get string length"); 4327db96d56Sopenharmony_ci return hr; 4337db96d56Sopenharmony_ci } 4347db96d56Sopenharmony_ci 4357db96d56Sopenharmony_ci if (target) { 4367db96d56Sopenharmony_ci CoTaskMemFree(target); 4377db96d56Sopenharmony_ci } 4387db96d56Sopenharmony_ci if (target_dir) { 4397db96d56Sopenharmony_ci CoTaskMemFree(target_dir); 4407db96d56Sopenharmony_ci } 4417db96d56Sopenharmony_ci 4427db96d56Sopenharmony_ci target = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) * (len + 1)); 4437db96d56Sopenharmony_ci if (!target) { 4447db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Load - E_OUTOFMEMORY"); 4457db96d56Sopenharmony_ci return E_OUTOFMEMORY; 4467db96d56Sopenharmony_ci } 4477db96d56Sopenharmony_ci target_dir = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) * (len + 1)); 4487db96d56Sopenharmony_ci if (!target_dir) { 4497db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Load - E_OUTOFMEMORY"); 4507db96d56Sopenharmony_ci return E_OUTOFMEMORY; 4517db96d56Sopenharmony_ci } 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci hr = StringCchCopy(target, len + 1, pszFileName); 4547db96d56Sopenharmony_ci if (FAILED(hr)) { 4557db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Load - failed to copy string"); 4567db96d56Sopenharmony_ci return hr; 4577db96d56Sopenharmony_ci } 4587db96d56Sopenharmony_ci 4597db96d56Sopenharmony_ci hr = StringCchCopy(target_dir, len + 1, pszFileName); 4607db96d56Sopenharmony_ci if (FAILED(hr)) { 4617db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Load - failed to copy string"); 4627db96d56Sopenharmony_ci return hr; 4637db96d56Sopenharmony_ci } 4647db96d56Sopenharmony_ci if (!PathRemoveFileSpecW(target_dir)) { 4657db96d56Sopenharmony_ci OutputDebugStringW(L"PyShellExt::Load - failed to remove filespec from target"); 4667db96d56Sopenharmony_ci return E_FAIL; 4677db96d56Sopenharmony_ci } 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_ci OutputDebugString(target); 4707db96d56Sopenharmony_ci target_mode = dwMode; 4717db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::Load - S_OK"); 4727db96d56Sopenharmony_ci return S_OK; 4737db96d56Sopenharmony_ci } 4747db96d56Sopenharmony_ci 4757db96d56Sopenharmony_ci STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember) { 4767db96d56Sopenharmony_ci return E_NOTIMPL; 4777db96d56Sopenharmony_ci } 4787db96d56Sopenharmony_ci 4797db96d56Sopenharmony_ci STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName) { 4807db96d56Sopenharmony_ci return E_NOTIMPL; 4817db96d56Sopenharmony_ci } 4827db96d56Sopenharmony_ci 4837db96d56Sopenharmony_ci STDMETHODIMP GetClassID(CLSID *pClassID) { 4847db96d56Sopenharmony_ci *pClassID = __uuidof(PyShellExt); 4857db96d56Sopenharmony_ci return S_OK; 4867db96d56Sopenharmony_ci } 4877db96d56Sopenharmony_ci}; 4887db96d56Sopenharmony_ci 4897db96d56Sopenharmony_ciCoCreatableClass(PyShellExt); 4907db96d56Sopenharmony_ci 4917db96d56Sopenharmony_ciSTDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv) { 4927db96d56Sopenharmony_ci return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv); 4937db96d56Sopenharmony_ci} 4947db96d56Sopenharmony_ci 4957db96d56Sopenharmony_ciSTDAPI DllCanUnloadNow() { 4967db96d56Sopenharmony_ci return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE; 4977db96d56Sopenharmony_ci} 4987db96d56Sopenharmony_ci 4997db96d56Sopenharmony_ciSTDAPI DllRegisterServer() { 5007db96d56Sopenharmony_ci LONG res; 5017db96d56Sopenharmony_ci SECURITY_ATTRIBUTES secattr = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; 5027db96d56Sopenharmony_ci LPSECURITY_ATTRIBUTES psecattr = NULL; 5037db96d56Sopenharmony_ci HKEY key, ipsKey; 5047db96d56Sopenharmony_ci WCHAR modname[MAX_PATH]; 5057db96d56Sopenharmony_ci DWORD modname_len; 5067db96d56Sopenharmony_ci 5077db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer"); 5087db96d56Sopenharmony_ci if (!hModule) { 5097db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer - module handle was not set"); 5107db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5117db96d56Sopenharmony_ci } 5127db96d56Sopenharmony_ci modname_len = GetModuleFileName(hModule, modname, MAX_PATH); 5137db96d56Sopenharmony_ci if (modname_len == 0 || 5147db96d56Sopenharmony_ci (modname_len == MAX_PATH && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { 5157db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer - failed to get module file name"); 5167db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5177db96d56Sopenharmony_ci } 5187db96d56Sopenharmony_ci 5197db96d56Sopenharmony_ci DWORD disp; 5207db96d56Sopenharmony_ci res = RegCreateKeyEx(HKEY_LOCAL_MACHINE, CLASS_SUBKEY, 0, NULL, 0, 5217db96d56Sopenharmony_ci KEY_ALL_ACCESS, psecattr, &key, &disp); 5227db96d56Sopenharmony_ci if (res == ERROR_ACCESS_DENIED) { 5237db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer - failed to write per-machine registration. Attempting per-user instead."); 5247db96d56Sopenharmony_ci res = RegCreateKeyEx(HKEY_CURRENT_USER, CLASS_SUBKEY, 0, NULL, 0, 5257db96d56Sopenharmony_ci KEY_ALL_ACCESS, psecattr, &key, &disp); 5267db96d56Sopenharmony_ci } 5277db96d56Sopenharmony_ci if (res != ERROR_SUCCESS) { 5287db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer - failed to create class key"); 5297db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5307db96d56Sopenharmony_ci } 5317db96d56Sopenharmony_ci 5327db96d56Sopenharmony_ci res = RegCreateKeyEx(key, L"InProcServer32", 0, NULL, 0, 5337db96d56Sopenharmony_ci KEY_ALL_ACCESS, psecattr, &ipsKey, NULL); 5347db96d56Sopenharmony_ci if (res != ERROR_SUCCESS) { 5357db96d56Sopenharmony_ci RegCloseKey(key); 5367db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer - failed to create InProcServer32 key"); 5377db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5387db96d56Sopenharmony_ci } 5397db96d56Sopenharmony_ci 5407db96d56Sopenharmony_ci res = RegSetValueEx(ipsKey, NULL, 0, 5417db96d56Sopenharmony_ci REG_SZ, (LPBYTE)modname, modname_len * sizeof(modname[0])); 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci if (res != ERROR_SUCCESS) { 5447db96d56Sopenharmony_ci RegCloseKey(ipsKey); 5457db96d56Sopenharmony_ci RegCloseKey(key); 5467db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer - failed to set server path"); 5477db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5487db96d56Sopenharmony_ci } 5497db96d56Sopenharmony_ci 5507db96d56Sopenharmony_ci res = RegSetValueEx(ipsKey, L"ThreadingModel", 0, 5517db96d56Sopenharmony_ci REG_SZ, (LPBYTE)(L"Apartment"), sizeof(L"Apartment")); 5527db96d56Sopenharmony_ci 5537db96d56Sopenharmony_ci RegCloseKey(ipsKey); 5547db96d56Sopenharmony_ci RegCloseKey(key); 5557db96d56Sopenharmony_ci if (res != ERROR_SUCCESS) { 5567db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer - failed to set threading model"); 5577db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5587db96d56Sopenharmony_ci } 5597db96d56Sopenharmony_ci 5607db96d56Sopenharmony_ci SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); 5617db96d56Sopenharmony_ci 5627db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllRegisterServer - S_OK"); 5637db96d56Sopenharmony_ci return S_OK; 5647db96d56Sopenharmony_ci} 5657db96d56Sopenharmony_ci 5667db96d56Sopenharmony_ciSTDAPI DllUnregisterServer() { 5677db96d56Sopenharmony_ci LONG res_lm, res_cu; 5687db96d56Sopenharmony_ci 5697db96d56Sopenharmony_ci res_lm = RegDeleteTree(HKEY_LOCAL_MACHINE, CLASS_SUBKEY); 5707db96d56Sopenharmony_ci if (res_lm != ERROR_SUCCESS && res_lm != ERROR_FILE_NOT_FOUND) { 5717db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllUnregisterServer - failed to delete per-machine registration"); 5727db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5737db96d56Sopenharmony_ci } 5747db96d56Sopenharmony_ci 5757db96d56Sopenharmony_ci res_cu = RegDeleteTree(HKEY_CURRENT_USER, CLASS_SUBKEY); 5767db96d56Sopenharmony_ci if (res_cu != ERROR_SUCCESS && res_cu != ERROR_FILE_NOT_FOUND) { 5777db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllUnregisterServer - failed to delete per-user registration"); 5787db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5797db96d56Sopenharmony_ci } 5807db96d56Sopenharmony_ci 5817db96d56Sopenharmony_ci if (res_lm == ERROR_FILE_NOT_FOUND && res_cu == ERROR_FILE_NOT_FOUND) { 5827db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllUnregisterServer - extension was not registered"); 5837db96d56Sopenharmony_ci return SELFREG_E_CLASS; 5847db96d56Sopenharmony_ci } 5857db96d56Sopenharmony_ci 5867db96d56Sopenharmony_ci SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); 5877db96d56Sopenharmony_ci 5887db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllUnregisterServer - S_OK"); 5897db96d56Sopenharmony_ci return S_OK; 5907db96d56Sopenharmony_ci} 5917db96d56Sopenharmony_ci 5927db96d56Sopenharmony_ciSTDAPI_(BOOL) DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*) { 5937db96d56Sopenharmony_ci if (reason == DLL_PROCESS_ATTACH) { 5947db96d56Sopenharmony_ci hModule = hinst; 5957db96d56Sopenharmony_ci 5967db96d56Sopenharmony_ci cfDropDescription = RegisterClipboardFormat(CFSTR_DROPDESCRIPTION); 5977db96d56Sopenharmony_ci if (!cfDropDescription) { 5987db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllMain - failed to get CFSTR_DROPDESCRIPTION format"); 5997db96d56Sopenharmony_ci } 6007db96d56Sopenharmony_ci cfDragWindow = RegisterClipboardFormat(L"DragWindow"); 6017db96d56Sopenharmony_ci if (!cfDragWindow) { 6027db96d56Sopenharmony_ci OutputDebugString(L"PyShellExt::DllMain - failed to get DragWindow format"); 6037db96d56Sopenharmony_ci } 6047db96d56Sopenharmony_ci 6057db96d56Sopenharmony_ci DisableThreadLibraryCalls(hinst); 6067db96d56Sopenharmony_ci } 6077db96d56Sopenharmony_ci return TRUE; 6087db96d56Sopenharmony_ci}