Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Coming in build 312, as yet unreleased
--------------------------------------

* Fixed missing version stamp on built `.dll` and `.exe` files (mhammond#2647, [@Avasam][Avasam])
* Removed considerations for Windows 2000 and Windows Vista (mhammond#2667, [@Avasam][Avasam])
* This mostly updates obsolete documentation and tests
* Removed considerations for Windows 95/98/ME (mhammond#2400, [@Avasam][Avasam])
This removes the following constants:
* `win32con.FILE_ATTRIBUTE_ATOMIC_WRITE`
Expand Down
8 changes: 5 additions & 3 deletions com/help/active_directory.html
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,11 @@ <h2><a name="getobj">Getting Active Directory Objects</a></h2>

<h3><a name="discovery">Discovery</a></h3>
<p>
A tool that can be of a great help is ADSIedit which is in the Windows
2000 support tools on the Windows 2000 server cdrom. It gives you the
raw ldap view of active directory.</p>
A tool that can be of a great help is the ADSI Edit MMC snap-in, aka <b>ADSIEdit.msc</b>. See
<a href="https://www.microsoft.com/en-us/download/details.aspx?id=45520"
>Remote Server Administration Tools for Windows 10</a> for installation instructions.
It gives you the raw ldap view of active directory.
Note that it is not available for the Home edition of Windows.</p>
<code>
def discover():
Here is a function that helps you determine the active directory ldap strings that you can actually use.
Expand Down
14 changes: 4 additions & 10 deletions com/win32com/server/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import os
import sys
import tempfile

import pythoncom
import win32api
Expand Down Expand Up @@ -541,8 +542,6 @@ def UnregisterInfoClasses(*classes, **flags):

# Attempt to 're-execute' our current process with elevation.
def ReExecuteElevated(flags):
import tempfile

import win32console
import win32event # we've already checked we are running XP above
import win32process
Expand Down Expand Up @@ -646,14 +645,9 @@ def UseCommandLine(*classes, **flags):
else:
RegisterClasses(*classes, **flags)
except win32api.error as exc:
# If we are on xp+ and have "access denied", retry using
# ShellExecuteEx with 'runas' verb to force elevation (vista) and/or
# admin login dialog (vista/xp)
if (
flags["unattended"]
or exc.winerror != winerror.ERROR_ACCESS_DENIED
or sys.getwindowsversion()[0] < 5
):
# If we have "access denied", retry using
# ShellExecuteEx with 'runas' verb to force elevation
if flags["unattended"] or exc.winerror != winerror.ERROR_ACCESS_DENIED:
raise
ReExecuteElevated(flags)

Expand Down
2 changes: 0 additions & 2 deletions com/win32com/src/PythonCOM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ extern LONG _PyCom_GetGatewayCount(void);
typedef HRESULT(STDAPICALLTYPE *CreateURLMonikerExfunc)(LPMONIKER, LPCWSTR, LPMONIKER *, DWORD);
static CreateURLMonikerExfunc pfnCreateURLMonikerEx = NULL;

// Win2k or later
typedef HRESULT(STDAPICALLTYPE *CoWaitForMultipleHandlesfunc)(DWORD dwFlags, DWORD dwTimeout, ULONG cHandles,
LPHANDLE pHandles, LPDWORD lpdwindex);
static CoWaitForMultipleHandlesfunc pfnCoWaitForMultipleHandles = NULL;
Expand All @@ -104,7 +103,6 @@ typedef HRESULT(STDAPICALLTYPE *CoSetCancelObjectfunc)(IUnknown *);
static CoSetCancelObjectfunc pfnCoSetCancelObject = NULL;

// typedefs for the function pointers are in OleAcc.h
// WinXP or later
LPFNOBJECTFROMLRESULT pfnObjectFromLresult = NULL;

typedef HRESULT(STDAPICALLTYPE *CoCreateInstanceExfunc)(REFCLSID, IUnknown *, DWORD, COSERVERINFO *, ULONG, MULTI_QI *);
Expand Down
27 changes: 3 additions & 24 deletions com/win32comext/propsys/src/propsys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
// $Id$

// Implements wrappers for the Property System functions and interfaces.
// These interfaces are present on Windows Vista and later, but can also
// be installed on XP with Desktop Search 3.
// However, this module doeen't dynamically load any libraries or functions,
// so it will fail to import if the components are not installed.

// This source file contains autoduck documentation.
// @doc
Expand Down Expand Up @@ -38,13 +34,6 @@
#include "propvarutil.h"
#include "Shobjidl.h"

#define CHECK_PFN(fname) \
if (pfn##fname == NULL) \
return PyErr_Format(PyExc_NotImplementedError, "%s is not available on this platform", #fname);
// Not available on Vista or earlier
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't hate these comments because they help explain why there is a function pointer used. Removing the comment removes all context. I'm fine with updating the comment to be current and supply the context, or to remove the function pointer entirely.

Copy link
Collaborator Author

@Avasam Avasam Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add back or modify the comment.
Edit: this file only contained a single CHECK_PFN usage, removed along with comment.

Anyway I realized it later, but I think all these CHECK_PFN macros can be removed (looks like they're all for functions that should now always exist at build and runtime).

But I'd do that in its own PR. The main concern there will be to not accidentally remove cygwin workaround/support.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway I realized it later, but I think all these CHECK_PFN macros can be removed (looks like they're all for functions that should now always exist at build and runtime).

Right - I was trying to suggest that this means we can remove the function pointers entirely rather than just the null checks.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right - I was trying to suggest that this means we can remove the function pointers entirely rather than just the null checks.

that's what I ended up doing. Which rendered the line CHECK_PFN(SHGetPropertyStoreForWindow) dead code, so I removed it. Making the macro CHECK_PFN (in this file) unused, so I removed it.

typedef HRESULT(WINAPI *PFNSHGetPropertyStoreForWindow)(HWND, REFIID, void **);
static PFNSHGetPropertyStoreForWindow pfnSHGetPropertyStoreForWindow = NULL;

// @object PyPROPERTYKEY|A tuple of a fmtid and property id (IID, int) that uniquely identifies a property
BOOL PyWinObject_AsPROPERTYKEY(PyObject *obkey, PROPERTYKEY *pkey)
{
Expand Down Expand Up @@ -390,12 +379,10 @@ static PyObject *PyPSLookupPropertyHandlerCLSID(PyObject *self, PyObject *args)
};

// @pymethod <o PyIPropertyStore>|propsys|SHGetPropertyStoreForWindow|Retrieves a collection of a window's properties
// @comm Requires Windows 7 or later.
// @rdesc The returned store can be used to set the System.AppUserModel.ID property that determines how windows
// are grouped on the taskbar
static PyObject *PySHGetPropertyStoreForWindow(PyObject *self, PyObject *args)
{
CHECK_PFN(SHGetPropertyStoreForWindow);
HWND hwnd;
IID riid = IID_IPropertyStore;
void *ret;
Expand All @@ -407,7 +394,7 @@ static PyObject *PySHGetPropertyStoreForWindow(PyObject *self, PyObject *args)

HRESULT hr;
PY_INTERFACE_PRECALL;
hr = (*pfnSHGetPropertyStoreForWindow)(hwnd, riid, &ret);
hr = SHGetPropertyStoreForWindow(hwnd, riid, &ret);
PY_INTERFACE_POSTCALL;
if (FAILED(hr))
return PyCom_BuildPyException(hr);
Expand Down Expand Up @@ -546,7 +533,7 @@ static PyObject *PySHSetDefaultProperties(PyObject *self, PyObject *args)
}

/* List of module functions */
// @module propsys|A module, encapsulating the Vista Property System interfaces
// @module propsys|A module, encapsulating the Property System interfaces
static struct PyMethodDef propsys_methods[] = {
// { "SHGetPropertyStoreFromIDList", PySHGetPropertyStoreFromIDList, 1 }, // @pymeth
// SHGetPropertyStoreFromIDList|Retrieves the property store from an absolute ID list
Expand Down Expand Up @@ -618,10 +605,7 @@ static const PyCom_InterfaceSupportInfo g_interfaceSupportData[] = {
/* Module initialisation */
PYWIN_MODULE_INIT_FUNC(propsys)
{
PYWIN_MODULE_INIT_PREPARE(propsys, propsys_methods,
"A module, encapsulating the Property System interfaces."
"Available on Windows Vista and later, but can also be used"
"on XP if Desktop Search 3 is installed.");
PYWIN_MODULE_INIT_PREPARE(propsys, propsys_methods, "A module, encapsulating the Property System interfaces.");

if (PyDict_SetItemString(dict, "error", PyWinExc_COMError) == -1)
PYWIN_MODULE_INIT_RETURN_ERROR;
Expand All @@ -636,10 +620,5 @@ PYWIN_MODULE_INIT_FUNC(propsys)
sizeof(g_interfaceSupportData) / sizeof(PyCom_InterfaceSupportInfo)) != 0)
PYWIN_MODULE_INIT_RETURN_ERROR;

HMODULE hmod = GetModuleHandle(L"shell32.dll");
if (hmod)
pfnSHGetPropertyStoreForWindow =
(PFNSHGetPropertyStoreForWindow)GetProcAddress(hmod, "SHGetPropertyStoreForWindow");

PYWIN_MODULE_INIT_RETURN_SUCCESS;
}
2 changes: 1 addition & 1 deletion com/win32comext/shell/demos/explorer_browser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# A sample of using Vista's IExplorerBrowser interfaces...
# A sample of using IExplorerBrowser interfaces...
# Currently doesn't quite work:
# * CPU sits at 100% while running.

Expand Down
9 changes: 4 additions & 5 deletions com/win32comext/shell/demos/servers/context_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,11 @@ def InvokeCommand(self, ci):
mask, hwnd, verb, params, dir, nShow, hotkey, hicon = ci
win32gui.MessageBox(hwnd, "Hello", "Wow", win32con.MB_OK)

def GetCommandString(self, cmd, typ):
def GetCommandString(self, cmd: int, typ):
# If GetCommandString returns the same string for all items then
# the shell seems to ignore all but one. This is even true in
# Win7 etc where there is no status bar (and hence this string seems
# ignored)
return "Hello from Python (cmd=%d)!!" % (cmd,)
# the shell seems to ignore all but one. This is even true if the
# status bar is turned off (and hence this string seems ignored).
return f"Hello from Python ({cmd=})!!"


def DllRegisterServer():
Expand Down
12 changes: 2 additions & 10 deletions com/win32comext/shell/demos/servers/folder_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import os
import pickle
import random
import sys
import struct
import winreg

import commctrl
import pythoncom
Expand Down Expand Up @@ -796,12 +797,6 @@ def get_schema_fname():


def DllRegisterServer():
import winreg

if sys.getwindowsversion()[0] < 6:
print("This sample only works on Vista")
sys.exit(1)

key = winreg.CreateKey(
winreg.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
Expand All @@ -816,7 +811,6 @@ def DllRegisterServer():
attr = (
shellcon.SFGAO_FOLDER | shellcon.SFGAO_HASSUBFOLDER | shellcon.SFGAO_BROWSABLE
)
import struct

s = struct.pack("i", attr)
winreg.SetValueEx(key, "Attributes", 0, winreg.REG_BINARY, s)
Expand All @@ -832,8 +826,6 @@ def DllRegisterServer():


def DllUnregisterServer():
import winreg

paths = [
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\Namespace\\"
+ ShellFolder._reg_clsid_,
Expand Down
1 change: 0 additions & 1 deletion com/win32comext/shell/src/PyIFileOperation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,6 @@ PyObject *PyIFileOperation::GetAnyOperationsAborted(PyObject *self, PyObject *ar
// performed by the shell as a unit. Serves as a replacement for <om shell.SHFileOperation>.
// <nl>No changes are actually made until PerformOperations is called.
// <nl>Progress can be monitored by implementing <o PyGFileOperationProgressSink>.
// <nl>Requires Vista or later.
static struct PyMethodDef PyIFileOperation_methods[] = {
{"Advise", PyIFileOperation::Advise, 1}, // @pymeth Advise|Connects an event sink to receive updates
{"Unadvise", PyIFileOperation::Unadvise, 1}, // @pymeth Unadvise|Disconnects a progress sink
Expand Down
1 change: 0 additions & 1 deletion com/win32comext/shell/src/PyIKnownFolder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ PyObject *PyIKnownFolder::GetFolderDefinition(PyObject *self, PyObject *args)

// @object PyIKnownFolder|Interface representing a known folder that serves
// as a replacement for the numeric CSIDL definitions and API functions.
// Requires Vista or later.
static struct PyMethodDef PyIKnownFolder_methods[] = {
{"GetId", PyIKnownFolder::GetId, 1}, // @pymeth GetId|Returns the id of the folder
{"GetCategory", PyIKnownFolder::GetCategory,
Expand Down
3 changes: 1 addition & 2 deletions com/win32comext/shell/src/PyIShellFolder2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ PyObject *PyIShellFolder2::GetDetailsOf(PyObject *self, PyObject *args)
}

// @pymethod <o SHCOLUMNID>|PyIShellFolder2|MapColumnToSCID|Returns the unique identifier (FMTID, pid) of a column
// @rdesc On XP and earlier, this is the Column Id as provided by <o PyIColumnProvider>.
// For Vista and later, this is the Property Key used with the property system interfaces.
// @rdesc This is the Property Key used with the property system interfaces.
PyObject *PyIShellFolder2::MapColumnToSCID(PyObject *self, PyObject *args)
{
IShellFolder2 *pISF2 = GetI(self);
Expand Down
Loading