Staging
v0.5.1
https://github.com/python/cpython
Revision 911c35d5d334b8c148202f2a7a32b511958032fc authored by Miss Islington (bot) on 03 June 2020, 13:01:23 UTC, committed by GitHub on 03 June 2020, 13:01:23 UTC

Would be nice to backport to python 3.7+. I don't think it's worth the hassle to backport this all the way down to 3.10. But I'll let the maintainers decide.

This is hard to test because the test setup already includes this [environment variable](https://github.com/python/cpython/blob/master/Lib/test/pythoninfo.pyGH-L292)

Let me know if something doesn't match the PR guidelines. This is my first PR in the python source code.
(cherry picked from commit c822efeda9a0afe87cf3429724732fc8e19a01fb)

Co-authored-by: Jeremy Attali <jeremy.attali@gmail.com>
1 parent b640ca1
Raw File
Tip revision: 911c35d5d334b8c148202f2a7a32b511958032fc authored by Miss Islington (bot) on 03 June 2020, 13:01:23 UTC
bpo-40767: Allow pure Wayland to get default XDG web browser (GH-20382)
Tip revision: 911c35d
dl_nt.c
/*

Entry point for the Windows NT DLL.

About the only reason for having this, is so initall() can automatically
be called, removing that burden (and possible source of frustration if
forgotten) from the programmer.

*/

#include "Python.h"
#include "windows.h"

#ifdef Py_ENABLE_SHARED
#ifdef MS_DLL_ID
// The string is available at build, so fill the buffer immediately
char dllVersionBuffer[16] = MS_DLL_ID;
#else
char dllVersionBuffer[16] = ""; // a private buffer
#endif

// Python Globals
HMODULE PyWin_DLLhModule = NULL;
const char *PyWin_DLLVersionString = dllVersionBuffer;

#if HAVE_SXS
// Windows "Activation Context" work.
// Our .pyd extension modules are generally built without a manifest (ie,
// those included with Python and those built with a default distutils.
// This requires we perform some "activation context" magic when loading our
// extensions.  In summary:
// * As our DLL loads we save the context being used.
// * Before loading our extensions we re-activate our saved context.
// * After extension load is complete we restore the old context.
// As an added complication, this magic only works on XP or later - we simply
// use the existence (or not) of the relevant function pointers from kernel32.
// See bug 4566 (http://python.org/sf/4566) for more details.
// In Visual Studio 2010, side by side assemblies are no longer used by
// default.

typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *);
typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *);
typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);
typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE);
typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE);

// locals and function pointers for this activation context magic.
static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public
static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL;
static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL;
static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL;
static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL;
static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL;

void _LoadActCtxPointers()
{
    HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll");
    if (hKernel32)
        pfnGetCurrentActCtx = (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx");
    // If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest.
    if (pfnGetCurrentActCtx) {
        pfnActivateActCtx = (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx");
        pfnDeactivateActCtx = (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx");
        pfnAddRefActCtx = (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx");
        pfnReleaseActCtx = (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx");
    }
}

ULONG_PTR _Py_ActivateActCtx()
{
    ULONG_PTR ret = 0;
    if (PyWin_DLLhActivationContext && pfnActivateActCtx)
        if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) {
            OutputDebugString("Python failed to activate the activation context before loading a DLL\n");
            ret = 0; // no promise the failing function didn't change it!
        }
    return ret;
}

void _Py_DeactivateActCtx(ULONG_PTR cookie)
{
    if (cookie && pfnDeactivateActCtx)
        if (!(*pfnDeactivateActCtx)(0, cookie))
            OutputDebugString("Python failed to de-activate the activation context\n");
}
#endif /* HAVE_SXS */

BOOL    WINAPI  DllMain (HANDLE hInst,
                                                ULONG ul_reason_for_call,
                                                LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            PyWin_DLLhModule = hInst;
#ifndef MS_DLL_ID
            // If we have MS_DLL_ID, we don't need to load the string.
            // 1000 is a magic number I picked out of the air.  Could do with a #define, I spose...
            LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer));
#endif

#if HAVE_SXS
            // and capture our activation context for use when loading extensions.
            _LoadActCtxPointers();
            if (pfnGetCurrentActCtx && pfnAddRefActCtx)
                if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext))
                    if (!(*pfnAddRefActCtx)(PyWin_DLLhActivationContext))
                        OutputDebugString("Python failed to load the default activation context\n");
#endif
            break;

        case DLL_PROCESS_DETACH:
#if HAVE_SXS
            if (pfnReleaseActCtx)
                (*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
#endif
            break;
    }
    return TRUE;
}

#endif /* Py_ENABLE_SHARED */
back to top