Issue #27469: Adds a shell extension to the launcher so that drag and drop works correctly.
This commit is contained in:
commit
edddc2704c
|
@ -244,6 +244,12 @@ Build
|
||||||
|
|
||||||
- Don't use largefile support for GNU/Hurd.
|
- Don't use largefile support for GNU/Hurd.
|
||||||
|
|
||||||
|
Windows
|
||||||
|
-------
|
||||||
|
|
||||||
|
- Issue #27469: Adds a shell extension to the launcher so that drag and drop
|
||||||
|
works correctly.
|
||||||
|
|
||||||
Tools/Demos
|
Tools/Demos
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,605 @@
|
||||||
|
// 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);
|
||||||
|
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 implementation
|
||||||
|
|
||||||
|
STDMETHODIMP 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 implementation
|
||||||
|
|
||||||
|
STDMETHODIMP 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;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
LIBRARY "pyshellext"
|
||||||
|
EXPORTS
|
||||||
|
DllRegisterServer PRIVATE
|
||||||
|
DllUnregisterServer PRIVATE
|
||||||
|
DllGetClassObject PRIVATE
|
||||||
|
DllCanUnloadNow PRIVATE
|
|
@ -0,0 +1,12 @@
|
||||||
|
import "ocidl.idl";
|
||||||
|
|
||||||
|
[uuid(44039A76-3BDD-41C1-A31B-71C00202CE81), version(1.0)]
|
||||||
|
library PyShellExtLib
|
||||||
|
{
|
||||||
|
[uuid(BEA218D2-6950-497B-9434-61683EC065FE), version(1.0)]
|
||||||
|
coclass PyShellExt
|
||||||
|
{
|
||||||
|
[default] interface IDropTarget;
|
||||||
|
interface IPersistFile;
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "python_ver_rc.h"
|
||||||
|
|
||||||
|
// Include the manifest file that indicates we support all
|
||||||
|
// current versions of Windows.
|
||||||
|
#include <winuser.h>
|
||||||
|
1 RT_MANIFEST "python.manifest"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION PYVERSION64
|
||||||
|
PRODUCTVERSION PYVERSION64
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS VOS__WINDOWS32
|
||||||
|
FILETYPE VFT_APP
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "000004b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", PYTHON_COMPANY "\0"
|
||||||
|
VALUE "FileDescription", "Python\0"
|
||||||
|
VALUE "FileVersion", PYTHON_VERSION
|
||||||
|
VALUE "InternalName", "Python Launcher Shell Extension\0"
|
||||||
|
VALUE "LegalCopyright", PYTHON_COPYRIGHT "\0"
|
||||||
|
VALUE "OriginalFilename", "pyshellext" PYTHON_DEBUG_EXT ".dll\0"
|
||||||
|
VALUE "ProductName", "Python\0"
|
||||||
|
VALUE "ProductVersion", PYTHON_VERSION
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x0, 1200
|
||||||
|
END
|
||||||
|
END
|
|
@ -0,0 +1,6 @@
|
||||||
|
LIBRARY "pyshellext_d"
|
||||||
|
EXPORTS
|
||||||
|
DllRegisterServer PRIVATE
|
||||||
|
DllUnregisterServer PRIVATE
|
||||||
|
DllGetClassObject PRIVATE
|
||||||
|
DllCanUnloadNow PRIVATE
|
|
@ -46,6 +46,8 @@
|
||||||
<Projects Include="python3dll.vcxproj" />
|
<Projects Include="python3dll.vcxproj" />
|
||||||
<!-- py[w].exe -->
|
<!-- py[w].exe -->
|
||||||
<Projects Include="pylauncher.vcxproj;pywlauncher.vcxproj" />
|
<Projects Include="pylauncher.vcxproj;pywlauncher.vcxproj" />
|
||||||
|
<!-- pyshellext.dll -->
|
||||||
|
<Projects Include="pyshellext.vcxproj" />
|
||||||
<!-- _freeze_importlib -->
|
<!-- _freeze_importlib -->
|
||||||
<Projects Include="_freeze_importlib.vcxproj" />
|
<Projects Include="_freeze_importlib.vcxproj" />
|
||||||
<!-- Extension modules -->
|
<!-- Extension modules -->
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 14.0.22823.1
|
VisualStudioVersion = 14.0.25123.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{553EC33E-9816-4996-A660-5D6186A0B0B3}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{553EC33E-9816-4996-A660-5D6186A0B0B3}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
@ -63,8 +63,14 @@ EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testbuffer", "_testbuffer.vcxproj", "{A2697BD3-28C1-4AEC-9106-8B748639FD16}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testbuffer", "_testbuffer.vcxproj", "{A2697BD3-28C1-4AEC-9106-8B748639FD16}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pylauncher", "pylauncher.vcxproj", "{7B2727B5-5A3F-40EE-A866-43A13CD31446}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pylauncher", "pylauncher.vcxproj", "{7B2727B5-5A3F-40EE-A866-43A13CD31446}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782} = {0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pywlauncher", "pywlauncher.vcxproj", "{1D4B18D3-7C12-4ECB-9179-8531FF876CE6}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pywlauncher", "pywlauncher.vcxproj", "{1D4B18D3-7C12-4ECB-9179-8531FF876CE6}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{7B2727B5-5A3F-40EE-A866-43A13CD31446} = {7B2727B5-5A3F-40EE-A866-43A13CD31446}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_freeze_importlib", "_freeze_importlib.vcxproj", "{19C0C13F-47CA-4432-AFF3-799A296A4DDC}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_freeze_importlib", "_freeze_importlib.vcxproj", "{19C0C13F-47CA-4432-AFF3-799A296A4DDC}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -84,6 +90,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libeay", "libeay.vcxproj",
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssleay", "ssleay.vcxproj", "{10615B24-73BF-4EFA-93AA-236916321317}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssleay", "ssleay.vcxproj", "{10615B24-73BF-4EFA-93AA-236916321317}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pyshellext", "pyshellext.vcxproj", "{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
|
@ -684,6 +692,22 @@ Global
|
||||||
{10615B24-73BF-4EFA-93AA-236916321317}.Release|Win32.Build.0 = Release|Win32
|
{10615B24-73BF-4EFA-93AA-236916321317}.Release|Win32.Build.0 = Release|Win32
|
||||||
{10615B24-73BF-4EFA-93AA-236916321317}.Release|x64.ActiveCfg = Release|x64
|
{10615B24-73BF-4EFA-93AA-236916321317}.Release|x64.ActiveCfg = Release|x64
|
||||||
{10615B24-73BF-4EFA-93AA-236916321317}.Release|x64.Build.0 = Release|x64
|
{10615B24-73BF-4EFA-93AA-236916321317}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGInstrument|Win32.Build.0 = PGInstrument|Win32
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGInstrument|x64.ActiveCfg = PGInstrument|x64
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGInstrument|x64.Build.0 = PGInstrument|x64
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|Win32.Build.0 = PGUpdate|Win32
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|x64.ActiveCfg = PGUpdate|x64
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|x64.Build.0 = PGUpdate|x64
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -83,8 +83,9 @@
|
||||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
<TargetEnvironment>Win32</TargetEnvironment>
|
<TargetEnvironment>Win32</TargetEnvironment>
|
||||||
<TargetEnvironment Condition="'$(Platform)' == 'x64'">X64</TargetEnvironment>
|
<TargetEnvironment Condition="'$(Platform)' == 'x64'">X64</TargetEnvironment>
|
||||||
<TypeLibraryName>$(OutDir)%(Filename).tlb</TypeLibraryName>
|
<OutputDirectory>$(IntDir)</OutputDirectory>
|
||||||
<HeaderFileName>$(IntDir)%(Filename)_h.h</HeaderFileName>
|
<InterfaceIdentifierFileName>$(MSBuildProjectName)_i.c</InterfaceIdentifierFileName>
|
||||||
|
<ProxyFileName>$(MSBuildProjectName)_p.c</ProxyFileName>
|
||||||
</Midl>
|
</Midl>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="PGInstrument|Win32">
|
||||||
|
<Configuration>PGInstrument</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="PGInstrument|x64">
|
||||||
|
<Configuration>PGInstrument</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="PGUpdate|Win32">
|
||||||
|
<Configuration>PGUpdate</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="PGUpdate|x64">
|
||||||
|
<Configuration>PGUpdate</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}</ProjectGuid>
|
||||||
|
<RootNamespace>pyshellext</RootNamespace>
|
||||||
|
<TargetName>pyshellext</TargetName>
|
||||||
|
<SupportPGO>false</SupportPGO>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="python.props" />
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<MakeVersionInfoBeforeTarget>ClCompile</MakeVersionInfoBeforeTarget>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="pyproject.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>version.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<ModuleDefinitionFile>..\PC\pyshellext$(PyDebugExt).def</ModuleDefinitionFile>
|
||||||
|
</Link>
|
||||||
|
<Midl>
|
||||||
|
<CompileInterface>true</CompileInterface>
|
||||||
|
</Midl>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\PC\pyshellext.cpp" />
|
||||||
|
<Midl Include="..\PC\pyshellext.idl" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\PC\pyshellext.def" />
|
||||||
|
<None Include="..\PC\pyshellext_d.def" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\PC\pyshellext.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\PC\pyshellext.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Midl Include="..\PC\pyshellext.idl">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</Midl>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\PC\pyshellext.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\PC\pyshellext.def">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="..\PC\pyshellext_d.def">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -7,6 +7,7 @@
|
||||||
<OutputType>Package</OutputType>
|
<OutputType>Package</OutputType>
|
||||||
<DefineConstants>UpgradeCode=1B68A0EC-4DD3-5134-840E-73854B0863F1;$(DefineConstants)</DefineConstants>
|
<DefineConstants>UpgradeCode=1B68A0EC-4DD3-5134-840E-73854B0863F1;$(DefineConstants)</DefineConstants>
|
||||||
<IgnoreCommonWxlTemplates>true</IgnoreCommonWxlTemplates>
|
<IgnoreCommonWxlTemplates>true</IgnoreCommonWxlTemplates>
|
||||||
|
<SuppressICEs>ICE80</SuppressICEs>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="..\msi.props" />
|
<Import Project="..\msi.props" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -18,5 +19,18 @@
|
||||||
<EmbeddedResource Include="*.wxl" />
|
<EmbeddedResource Include="*.wxl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="_EnsurePyEx86" Condition="!Exists('$(BuildPath32)py.exe')" BeforeTargets="PrepareForBuild">
|
||||||
|
<MSBuild Projects="$(PySourcePath)PCBuild\pylauncher.vcxproj" Properties="Platform=Win32" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="_EnsurePywEx86" Condition="!Exists('$(BuildPath32)pyw.exe')" BeforeTargets="PrepareForBuild">
|
||||||
|
<MSBuild Projects="$(PySourcePath)PCBuild\pywlauncher.vcxproj" Properties="Platform=Win32" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="_EnsurePyShellExt86" Condition="!Exists('$(BuildPath32)pyshellext.dll')" BeforeTargets="PrepareForBuild">
|
||||||
|
<MSBuild Projects="$(PySourcePath)PCBuild\pyshellext.vcxproj" Properties="Platform=Win32" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="_EnsurePyShellExt64" Condition="!Exists('$(BuildPath64)pyshellext.dll')" BeforeTargets="PrepareForBuild">
|
||||||
|
<MSBuild Projects="$(PySourcePath)PCBuild\pyshellext.vcxproj" Properties="Platform=x64" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
<Import Project="..\msi.targets" />
|
<Import Project="..\msi.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
<RemoveExistingProducts After="InstallValidate">UPGRADE or REMOVE_350_LAUNCHER</RemoveExistingProducts>
|
<RemoveExistingProducts After="InstallValidate">UPGRADE or REMOVE_350_LAUNCHER</RemoveExistingProducts>
|
||||||
</InstallExecuteSequence>
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
<!-- Python 3.5.0 shipped with a different UpgradeCode -->
|
<!-- Python 3.5.0 shipped with a different UpgradeCode -->
|
||||||
<Upgrade Id="A71530B9-E89D-53DB-9C2D-C6D7551876D8">
|
<Upgrade Id="A71530B9-E89D-53DB-9C2D-C6D7551876D8">
|
||||||
<UpgradeVersion Minimum="0.0.0.0" Property="REMOVE_350_LAUNCHER" />
|
<UpgradeVersion Minimum="0.0.0.0" Property="REMOVE_350_LAUNCHER" />
|
||||||
|
|
|
@ -20,6 +20,19 @@
|
||||||
<Condition>ALLUSERS=1</Condition>
|
<Condition>ALLUSERS=1</Condition>
|
||||||
<RegistryValue KeyPath="yes" Root="HKMU" Key="Software\Python\PyLauncher" Name="InstallDir" Value="[LauncherInstallDirectory]" Type="string" />
|
<RegistryValue KeyPath="yes" Root="HKMU" Key="Software\Python\PyLauncher" Name="InstallDir" Value="[LauncherInstallDirectory]" Type="string" />
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
|
<Component Id="pyshellext_amd64.dll" Directory="LauncherInstallDirectory" Guid="{E7411EFD-F1DD-40EB-B0C7-4BA02BF3E75F}" Win64="yes">
|
||||||
|
<Condition>VersionNT64</Condition>
|
||||||
|
<File Id="pyshellext_amd64.dll" Name="pyshellext.amd64.dll" Source="!(bindpath.Build64)\pyshellext.dll">
|
||||||
|
<Class Id="{BEA218D2-6950-497B-9434-61683EC065FE}" Advertise="no" Context="InprocServer32" ThreadingModel="apartment" />
|
||||||
|
</File>
|
||||||
|
</Component>
|
||||||
|
<Component Id="pyshellext_win32.dll" Directory="LauncherInstallDirectory" Guid="{C5936696-9A5A-45A0-A830-D172C3329282}">
|
||||||
|
<Condition>NOT VersionNT64</Condition>
|
||||||
|
<File Id="pyshellext_win32.dll" Name="pyshellext.win32.dll" Source="!(bindpath.Build32)\pyshellext.dll">
|
||||||
|
<Class Id="{BEA218D2-6950-497B-9434-61683EC065FE}" Advertise="no" Context="InprocServer32" ThreadingModel="apartment" />
|
||||||
|
</File>
|
||||||
|
</Component>
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
</Wix>
|
</Wix>
|
||||||
|
|
|
@ -10,14 +10,14 @@
|
||||||
<Verb Id="open" TargetFile="py.exe" Argument=""%L" %*" />
|
<Verb Id="open" TargetFile="py.exe" Argument=""%L" %*" />
|
||||||
</Extension>
|
</Extension>
|
||||||
</ProgId>
|
</ProgId>
|
||||||
<RegistryValue Root="HKCR" Key="Python.File\shellex\DropHandler" Value="{60254CA5-953B-11CF-8C96-00AA00B8708C}" Type="string" />
|
<RegistryValue Root="HKCR" Key="Python.File\shellex\DropHandler" Value="{BEA218D2-6950-497B-9434-61683EC065FE}" Type="string" />
|
||||||
|
|
||||||
<ProgId Id="Python.NoConFile" Description="!(loc.PythonNoConFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1">
|
<ProgId Id="Python.NoConFile" Description="!(loc.PythonNoConFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1">
|
||||||
<Extension Id="pyw" ContentType="text/plain">
|
<Extension Id="pyw" ContentType="text/plain">
|
||||||
<Verb Id="open" TargetFile="pyw.exe" Argument=""%L" %*" />
|
<Verb Id="open" TargetFile="pyw.exe" Argument=""%L" %*" />
|
||||||
</Extension>
|
</Extension>
|
||||||
</ProgId>
|
</ProgId>
|
||||||
<RegistryValue Root="HKCR" Key="Python.NoConFile\shellex\DropHandler" Value="{60254CA5-953B-11CF-8C96-00AA00B8708C}" Type="string" />
|
<RegistryValue Root="HKCR" Key="Python.NoConFile\shellex\DropHandler" Value="{BEA218D2-6950-497B-9434-61683EC065FE}" Type="string" />
|
||||||
|
|
||||||
<ProgId Id="Python.CompiledFile" Description="!(loc.PythonCompiledFileDescription)" Advertise="no" Icon="py.exe" IconIndex="2">
|
<ProgId Id="Python.CompiledFile" Description="!(loc.PythonCompiledFileDescription)" Advertise="no" Icon="py.exe" IconIndex="2">
|
||||||
<Extension Id="pyc">
|
<Extension Id="pyc">
|
||||||
|
@ -25,21 +25,21 @@
|
||||||
</Extension>
|
</Extension>
|
||||||
<Extension Id="pyo" />
|
<Extension Id="pyo" />
|
||||||
</ProgId>
|
</ProgId>
|
||||||
<RegistryValue Root="HKCR" Key="Python.CompiledFile\shellex\DropHandler" Value="{60254CA5-953B-11CF-8C96-00AA00B8708C}" Type="string" />
|
<RegistryValue Root="HKCR" Key="Python.CompiledFile\shellex\DropHandler" Value="{BEA218D2-6950-497B-9434-61683EC065FE}" Type="string" />
|
||||||
|
|
||||||
<ProgId Id="Python.ArchiveFile" Description="!(loc.PythonArchiveFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1">
|
<ProgId Id="Python.ArchiveFile" Description="!(loc.PythonArchiveFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1">
|
||||||
<Extension Id="pyz" ContentType="application/x-zip-compressed">
|
<Extension Id="pyz" ContentType="application/x-zip-compressed">
|
||||||
<Verb Id="open" TargetFile="py.exe" Argument=""%L" %*" />
|
<Verb Id="open" TargetFile="py.exe" Argument=""%L" %*" />
|
||||||
</Extension>
|
</Extension>
|
||||||
</ProgId>
|
</ProgId>
|
||||||
<RegistryValue Root="HKCR" Key="Python.ArchiveFile\shellex\DropHandler" Value="{60254CA5-953B-11CF-8C96-00AA00B8708C}" Type="string" />
|
<RegistryValue Root="HKCR" Key="Python.ArchiveFile\shellex\DropHandler" Value="{BEA218D2-6950-497B-9434-61683EC065FE}" Type="string" />
|
||||||
|
|
||||||
<ProgId Id="Python.NoConArchiveFile" Description="!(loc.PythonNoConArchiveFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1">
|
<ProgId Id="Python.NoConArchiveFile" Description="!(loc.PythonNoConArchiveFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1">
|
||||||
<Extension Id="pyzw" ContentType="application/x-zip-compressed">
|
<Extension Id="pyzw" ContentType="application/x-zip-compressed">
|
||||||
<Verb Id="open" TargetFile="pyw.exe" Argument=""%L" %*" />
|
<Verb Id="open" TargetFile="pyw.exe" Argument=""%L" %*" />
|
||||||
</Extension>
|
</Extension>
|
||||||
</ProgId>
|
</ProgId>
|
||||||
<RegistryValue Root="HKCR" Key="Python.NoConArchiveFile\shellex\DropHandler" Value="{60254CA5-953B-11CF-8C96-00AA00B8708C}" Type="string" />
|
<RegistryValue Root="HKCR" Key="Python.NoConArchiveFile\shellex\DropHandler" Value="{BEA218D2-6950-497B-9434-61683EC065FE}" Type="string" />
|
||||||
</Component>
|
</Component>
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
Loading…
Reference in New Issue