// Support back to Vista#define _WIN32_WINNT _WIN32_WINNT_VISTA#include <sdkddkver.h>// Use WRL to define a classic COM class#define __WRL_CLASSIC_COM__#include <wrl.h>#include <windows.h>#include <shlobj.h>#include <shlwapi.h>#include <olectl.h>#include <strsafe.h>#include "pyshellext_h.h"#define DDWM_UPDATEWINDOW (WM_USER+3)static HINSTANCE hModule;static CLIPFORMAT cfDropDescription;static CLIPFORMAT cfDragWindow;static const LPCWSTR CLASS_SUBKEY = L"Software\\Classes\\CLSID\\{BEA218D2-6950-497B-9434-61683EC065FE}";static const LPCWSTR DRAG_MESSAGE = L"Open with %1";using namespace Microsoft::WRL;HRESULT FilenameListCchLengthA(LPCSTR pszSource, size_t cchMax, size_t *pcchLength, size_t *pcchCount) {HRESULT hr = S_OK;size_t count = 0;size_t length = 0;while (pszSource && pszSource[0]) {size_t oneLength;hr = StringCchLengthA(pszSource, cchMax - length, &oneLength);if (FAILED(hr)) {return hr;}count += 1;length += oneLength + (strchr(pszSource, ' ') ? 3 : 1);pszSource = &pszSource[oneLength + 1];}*pcchCount = count;*pcchLength = length;return hr;}HRESULT FilenameListCchLengthW(LPCWSTR pszSource, size_t cchMax, size_t *pcchLength, size_t *pcchCount) {HRESULT hr = S_OK;size_t count = 0;size_t length = 0;while (pszSource && pszSource[0]) {size_t oneLength;hr = StringCchLengthW(pszSource, cchMax - length, &oneLength);if (FAILED(hr)) {return hr;}count += 1;length += oneLength + (wcschr(pszSource, ' ') ? 3 : 1);pszSource = &pszSource[oneLength + 1];}*pcchCount = count;*pcchLength = length;return hr;}HRESULT FilenameListCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, LPCSTR pszSource, LPCSTR pszSeparator) {HRESULT hr = S_OK;size_t count = 0;size_t length = 0;while (pszSource[0]) {STRSAFE_LPSTR newDest;hr = StringCchCopyExA(pszDest, cchDest, pszSource, &newDest, &cchDest, 0);if (FAILED(hr)) {return hr;}pszSource += (newDest - pszDest) + 1;pszDest = PathQuoteSpacesA(pszDest) ? newDest + 2 : newDest;if (pszSource[0]) {hr = StringCchCopyExA(pszDest, cchDest, pszSeparator, &newDest, &cchDest, 0);if (FAILED(hr)) {return hr;}pszDest = newDest;}}return hr;}HRESULT FilenameListCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, LPCWSTR pszSource, LPCWSTR pszSeparator) {HRESULT hr = S_OK;size_t count = 0;size_t length = 0;while (pszSource[0]) {STRSAFE_LPWSTR newDest;hr = StringCchCopyExW(pszDest, cchDest, pszSource, &newDest, &cchDest, 0);if (FAILED(hr)) {return hr;}pszSource += (newDest - pszDest) + 1;pszDest = PathQuoteSpacesW(pszDest) ? newDest + 2 : newDest;if (pszSource[0]) {hr = StringCchCopyExW(pszDest, cchDest, pszSeparator, &newDest, &cchDest, 0);if (FAILED(hr)) {return hr;}pszDest = newDest;}}return hr;}class PyShellExt : public RuntimeClass<RuntimeClassFlags<ClassicCom>,IDropTarget,IPersistFile>{LPOLESTR target, target_dir;DWORD target_mode;IDataObject *data_obj;public:PyShellExt() : target(NULL), target_dir(NULL), target_mode(0), data_obj(NULL) {OutputDebugString(L"PyShellExt::PyShellExt");}~PyShellExt() {if (target) {CoTaskMemFree(target);}if (target_dir) {CoTaskMemFree(target_dir);}if (data_obj) {data_obj->Release();}}private:HRESULT UpdateDropDescription(IDataObject *pDataObj) {STGMEDIUM medium;FORMATETC fmt = {cfDropDescription,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL};auto hr = pDataObj->GetData(&fmt, &medium);if (FAILED(hr)) {OutputDebugString(L"PyShellExt::UpdateDropDescription - failed to get DROPDESCRIPTION format");return hr;}if (!medium.hGlobal) {OutputDebugString(L"PyShellExt::UpdateDropDescription - DROPDESCRIPTION format had NULL hGlobal");ReleaseStgMedium(&medium);return E_FAIL;}auto dd = (DROPDESCRIPTION*)GlobalLock(medium.hGlobal);if (!dd) {OutputDebugString(L"PyShellExt::UpdateDropDescription - failed to lock DROPDESCRIPTION hGlobal");ReleaseStgMedium(&medium);return E_FAIL;}StringCchCopy(dd->szMessage, sizeof(dd->szMessage) / sizeof(dd->szMessage[0]), DRAG_MESSAGE);StringCchCopy(dd->szInsert, sizeof(dd->szInsert) / sizeof(dd->szInsert[0]), PathFindFileNameW(target));dd->type = DROPIMAGE_MOVE;GlobalUnlock(medium.hGlobal);ReleaseStgMedium(&medium);return S_OK;}HRESULT GetDragWindow(IDataObject *pDataObj, HWND *phWnd) {HRESULT hr;HWND *pMem;STGMEDIUM medium;FORMATETC fmt = {cfDragWindow,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL};hr = pDataObj->GetData(&fmt, &medium);if (FAILED(hr)) {OutputDebugString(L"PyShellExt::GetDragWindow - failed to get DragWindow format");return hr;}if (!medium.hGlobal) {OutputDebugString(L"PyShellExt::GetDragWindow - DragWindow format had NULL hGlobal");ReleaseStgMedium(&medium);return E_FAIL;}pMem = (HWND*)GlobalLock(medium.hGlobal);if (!pMem) {OutputDebugString(L"PyShellExt::GetDragWindow - failed to lock DragWindow hGlobal");ReleaseStgMedium(&medium);return E_FAIL;}*phWnd = *pMem;GlobalUnlock(medium.hGlobal);ReleaseStgMedium(&medium);return S_OK;}HRESULT GetArguments(IDataObject *pDataObj, LPCWSTR *pArguments) {HRESULT hr;DROPFILES *pdropfiles;STGMEDIUM medium;FORMATETC fmt = {CF_HDROP,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL};hr = pDataObj->GetData(&fmt, &medium);if (FAILED(hr)) {OutputDebugString(L"PyShellExt::GetArguments - failed to get CF_HDROP format");return hr;}if (!medium.hGlobal) {OutputDebugString(L"PyShellExt::GetArguments - CF_HDROP format had NULL hGlobal");ReleaseStgMedium(&medium);return E_FAIL;}pdropfiles = (DROPFILES*)GlobalLock(medium.hGlobal);if (!pdropfiles) {OutputDebugString(L"PyShellExt::GetArguments - failed to lock CF_HDROP hGlobal");ReleaseStgMedium(&medium);return E_FAIL;}if (pdropfiles->fWide) {LPCWSTR files = (LPCWSTR)((char*)pdropfiles + pdropfiles->pFiles);size_t len, count;hr = FilenameListCchLengthW(files, 32767, &len, &count);if (SUCCEEDED(hr)) {LPWSTR args = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (len + 1));if (args) {hr = FilenameListCchCopyW(args, 32767, files, L" ");if (SUCCEEDED(hr)) {*pArguments = args;} else {CoTaskMemFree(args);}} else {hr = E_OUTOFMEMORY;}}} else {LPCSTR files = (LPCSTR)((char*)pdropfiles + pdropfiles->pFiles);size_t len, count;hr = FilenameListCchLengthA(files, 32767, &len, &count);if (SUCCEEDED(hr)) {LPSTR temp = (LPSTR)CoTaskMemAlloc(sizeof(CHAR) * (len + 1));if (temp) {hr = FilenameListCchCopyA(temp, 32767, files, " ");if (SUCCEEDED(hr)) {int wlen = MultiByteToWideChar(CP_ACP, 0, temp, (int)len, NULL, 0);if (wlen) {LPWSTR args = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (wlen + 1));if (MultiByteToWideChar(CP_ACP, 0, temp, (int)len, args, wlen + 1)) {*pArguments = args;} else {OutputDebugString(L"PyShellExt::GetArguments - failed to convert multi-byte to wide-char path");CoTaskMemFree(args);hr = E_FAIL;}} else {OutputDebugString(L"PyShellExt::GetArguments - failed to get length of wide-char path");hr = E_FAIL;}}CoTaskMemFree(temp);} else {hr = E_OUTOFMEMORY;}}}GlobalUnlock(medium.hGlobal);ReleaseStgMedium(&medium);return hr;}HRESULT NotifyDragWindow(HWND hwnd) {LRESULT res;if (!hwnd) {return S_FALSE;}res = SendMessage(hwnd, DDWM_UPDATEWINDOW, 0, NULL);if (res) {OutputDebugString(L"PyShellExt::NotifyDragWindow - failed to post DDWM_UPDATEWINDOW");return E_FAIL;}return S_OK;}public:// IDropTarget implementationSTDMETHODIMP DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {HWND hwnd;OutputDebugString(L"PyShellExt::DragEnter");pDataObj->AddRef();data_obj = pDataObj;*pdwEffect = DROPEFFECT_MOVE;if (FAILED(UpdateDropDescription(data_obj))) {OutputDebugString(L"PyShellExt::DragEnter - failed to update drop description");}if (FAILED(GetDragWindow(data_obj, &hwnd))) {OutputDebugString(L"PyShellExt::DragEnter - failed to get drag window");}if (FAILED(NotifyDragWindow(hwnd))) {OutputDebugString(L"PyShellExt::DragEnter - failed to notify drag window");}return S_OK;}STDMETHODIMP DragLeave() {return S_OK;}STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {return S_OK;}STDMETHODIMP Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {LPCWSTR args;OutputDebugString(L"PyShellExt::Drop");*pdwEffect = DROPEFFECT_NONE;if (pDataObj != data_obj) {OutputDebugString(L"PyShellExt::Drop - unexpected data object");return E_FAIL;}data_obj->Release();data_obj = NULL;if (SUCCEEDED(GetArguments(pDataObj, &args))) {OutputDebugString(args);ShellExecute(NULL, NULL, target, args, target_dir, SW_NORMAL);CoTaskMemFree((LPVOID)args);} else {OutputDebugString(L"PyShellExt::Drop - failed to get launch arguments");}return S_OK;}// IPersistFile implementationSTDMETHODIMP GetCurFile(LPOLESTR *ppszFileName) {HRESULT hr;size_t len;if (!ppszFileName) {return E_POINTER;}hr = StringCchLength(target, STRSAFE_MAX_CCH - 1, &len);if (FAILED(hr)) {return E_FAIL;}*ppszFileName = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) * (len + 1));if (!*ppszFileName) {return E_OUTOFMEMORY;}hr = StringCchCopy(*ppszFileName, len + 1, target);if (FAILED(hr)) {CoTaskMemFree(*ppszFileName);*ppszFileName = NULL;return E_FAIL;}return S_OK;}STDMETHODIMP IsDirty() {return S_FALSE;}STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode) {HRESULT hr;size_t len;OutputDebugString(L"PyShellExt::Load");OutputDebugString(pszFileName);hr = StringCchLength(pszFileName, STRSAFE_MAX_CCH - 1, &len);if (FAILED(hr)) {OutputDebugString(L"PyShellExt::Load - failed to get string length");return hr;}if (target) {CoTaskMemFree(target);}if (target_dir) {CoTaskMemFree(target_dir);}target = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) * (len + 1));if (!target) {OutputDebugString(L"PyShellExt::Load - E_OUTOFMEMORY");return E_OUTOFMEMORY;}target_dir = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) * (len + 1));if (!target_dir) {OutputDebugString(L"PyShellExt::Load - E_OUTOFMEMORY");return E_OUTOFMEMORY;}hr = StringCchCopy(target, len + 1, pszFileName);if (FAILED(hr)) {OutputDebugString(L"PyShellExt::Load - failed to copy string");return hr;}hr = StringCchCopy(target_dir, len + 1, pszFileName);if (FAILED(hr)) {OutputDebugString(L"PyShellExt::Load - failed to copy string");return hr;}if (!PathRemoveFileSpecW(target_dir)) {OutputDebugStringW(L"PyShellExt::Load - failed to remove filespec from target");return E_FAIL;}OutputDebugString(target);target_mode = dwMode;OutputDebugString(L"PyShellExt::Load - S_OK");return S_OK;}STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember) {return E_NOTIMPL;}STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName) {return E_NOTIMPL;}STDMETHODIMP GetClassID(CLSID *pClassID) {*pClassID = CLSID_PyShellExt;return S_OK;}};CoCreatableClass(PyShellExt);STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv) {return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv);}STDAPI DllCanUnloadNow() {return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE;}STDAPI DllRegisterServer() {LONG res;SECURITY_ATTRIBUTES secattr = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };LPSECURITY_ATTRIBUTES psecattr = NULL;HKEY key, ipsKey;WCHAR modname[MAX_PATH];DWORD modname_len;OutputDebugString(L"PyShellExt::DllRegisterServer");if (!hModule) {OutputDebugString(L"PyShellExt::DllRegisterServer - module handle was not set");return SELFREG_E_CLASS;}modname_len = GetModuleFileName(hModule, modname, MAX_PATH);if (modname_len == 0 ||(modname_len == MAX_PATH && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {OutputDebugString(L"PyShellExt::DllRegisterServer - failed to get module file name");return SELFREG_E_CLASS;}DWORD disp;res = RegCreateKeyEx(HKEY_LOCAL_MACHINE, CLASS_SUBKEY, 0, NULL, 0,KEY_ALL_ACCESS, psecattr, &key, &disp);if (res == ERROR_ACCESS_DENIED) {OutputDebugString(L"PyShellExt::DllRegisterServer - failed to write per-machine registration. Attempting per-user instead.");res = RegCreateKeyEx(HKEY_CURRENT_USER, CLASS_SUBKEY, 0, NULL, 0,KEY_ALL_ACCESS, psecattr, &key, &disp);}if (res != ERROR_SUCCESS) {OutputDebugString(L"PyShellExt::DllRegisterServer - failed to create class key");return SELFREG_E_CLASS;}res = RegCreateKeyEx(key, L"InProcServer32", 0, NULL, 0,KEY_ALL_ACCESS, psecattr, &ipsKey, NULL);if (res != ERROR_SUCCESS) {RegCloseKey(key);OutputDebugString(L"PyShellExt::DllRegisterServer - failed to create InProcServer32 key");return SELFREG_E_CLASS;}res = RegSetValueEx(ipsKey, NULL, 0,REG_SZ, (LPBYTE)modname, modname_len * sizeof(modname[0]));if (res != ERROR_SUCCESS) {RegCloseKey(ipsKey);RegCloseKey(key);OutputDebugString(L"PyShellExt::DllRegisterServer - failed to set server path");return SELFREG_E_CLASS;}res = RegSetValueEx(ipsKey, L"ThreadingModel", 0,REG_SZ, (LPBYTE)(L"Apartment"), sizeof(L"Apartment"));RegCloseKey(ipsKey);RegCloseKey(key);if (res != ERROR_SUCCESS) {OutputDebugString(L"PyShellExt::DllRegisterServer - failed to set threading model");return SELFREG_E_CLASS;}SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);OutputDebugString(L"PyShellExt::DllRegisterServer - S_OK");return S_OK;}STDAPI DllUnregisterServer() {LONG res_lm, res_cu;res_lm = RegDeleteTree(HKEY_LOCAL_MACHINE, CLASS_SUBKEY);if (res_lm != ERROR_SUCCESS && res_lm != ERROR_FILE_NOT_FOUND) {OutputDebugString(L"PyShellExt::DllUnregisterServer - failed to delete per-machine registration");return SELFREG_E_CLASS;}res_cu = RegDeleteTree(HKEY_CURRENT_USER, CLASS_SUBKEY);if (res_cu != ERROR_SUCCESS && res_cu != ERROR_FILE_NOT_FOUND) {OutputDebugString(L"PyShellExt::DllUnregisterServer - failed to delete per-user registration");return SELFREG_E_CLASS;}if (res_lm == ERROR_FILE_NOT_FOUND && res_cu == ERROR_FILE_NOT_FOUND) {OutputDebugString(L"PyShellExt::DllUnregisterServer - extension was not registered");return SELFREG_E_CLASS;}SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);OutputDebugString(L"PyShellExt::DllUnregisterServer - S_OK");return S_OK;}STDAPI_(BOOL) DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*) {if (reason == DLL_PROCESS_ATTACH) {hModule = hinst;cfDropDescription = RegisterClipboardFormat(CFSTR_DROPDESCRIPTION);if (!cfDropDescription) {OutputDebugString(L"PyShellExt::DllMain - failed to get CFSTR_DROPDESCRIPTION format");}cfDragWindow = RegisterClipboardFormat(L"DragWindow");if (!cfDragWindow) {OutputDebugString(L"PyShellExt::DllMain - failed to get DragWindow format");}DisableThreadLibraryCalls(hinst);}return TRUE;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。