Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
13 changes: 2 additions & 11 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 @@ -41,7 +37,6 @@
#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;

Expand Down Expand Up @@ -390,7 +385,6 @@ 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)
Expand Down Expand Up @@ -546,7 +540,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 +612,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 Down
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
73 changes: 0 additions & 73 deletions com/win32comext/shell/src/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,6 @@ static PyObject *PySHGetFolderPath(PyObject *self, PyObject *args)
}

// @pymethod |shell|SHSetFolderPath|Sets the location of one of the special folders
// @comm This function is only available on Windows 2000 or later
static PyObject *PySHSetFolderPath(PyObject *self, PyObject *args)
{
int csidl;
Expand Down Expand Up @@ -2631,11 +2630,6 @@ static PyObject *PyAssocCreate(PyObject *self, PyObject *args)
// interface.
static PyObject *PyAssocCreateForClasses(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
Copy link
Owner

Choose a reason for hiding this comment

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

kinda like the above, I think I'd rather just avoid using the function pointer entirely (and ditto below)

// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnAssocCreateForClasses == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *obClasses, *obiid;
if (!PyArg_ParseTuple(args, "OO:AssocCreateForClasses", &obClasses, &obiid))
Expand Down Expand Up @@ -2803,11 +2797,6 @@ done: {
// defaults can be further configured via the IDefaultExtractIconInit interface.
static PyObject *PySHCreateDefaultExtractIcon(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateDefaultExtractIcon == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

// be lazy - don't take IID as a param!
if (!PyArg_ParseTuple(args, ":SHCreateDefaultExtractIcon"))
return NULL;
Expand All @@ -2825,11 +2814,6 @@ static PyObject *PySHCreateDefaultExtractIcon(PyObject *self, PyObject *args)
// @pymethod <o PyIUnknown>|shell|SHCreateDataObject|
static PyObject *PySHCreateDataObject(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateDataObject == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *obParent;
PyObject *obChildren;
Expand Down Expand Up @@ -2879,11 +2863,6 @@ static PyObject *PySHCreateDataObject(PyObject *self, PyObject *args)
// @pymethod <o PyIUnknown>|shell|SHCreateDefaultContextMenu|
static PyObject *PySHCreateDefaultContextMenu(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateDefaultContextMenu == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *obdcm, *obiid;
IID iid = IID_IContextMenu;
Expand Down Expand Up @@ -2917,10 +2896,6 @@ static PyObject *PySHCreateDefaultContextMenu(PyObject *self, PyObject *args)
// @pymethod str|shell|SHGetNameFromIDList|Retrieves the display name of an item from an ID list.
static PyObject *PySHGetNameFromIDList(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHGetNameFromIDList == NULL)
return PyCom_BuildPyException(E_NOTIMPL);
PyObject *ret = NULL;
PyObject *obpidl;
SIGDN flags;
Expand Down Expand Up @@ -2954,11 +2929,6 @@ static PyObject *PySHGetNameFromIDList(PyObject *self, PyObject *args)
// @pymethod <o PyIShellItemArray>|shell|SHCreateShellItemArray|Creates a Shell item array object.
static PyObject *PySHCreateShellItemArray(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateShellItemArray == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *obParent;
PyObject *obChildren;
Expand Down Expand Up @@ -3006,11 +2976,6 @@ static PyObject *PySHCreateShellItemArray(PyObject *self, PyObject *args)
// interface that contains a list of items (eg CF_HDROP)
static PyObject *PySHCreateShellItemArrayFromDataObject(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateShellItemArrayFromDataObject == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *obdo;
PyObject *obiid = Py_None;
Expand Down Expand Up @@ -3046,11 +3011,6 @@ static PyObject *PySHCreateShellItemArrayFromDataObject(PyObject *self, PyObject
// item identifiers
static PyObject *PySHCreateShellItemArrayFromIDLists(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateShellItemArrayFromIDLists == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *obpidls;
PCIDLIST_ABSOLUTE_ARRAY pidls = NULL;
Expand Down Expand Up @@ -3084,11 +3044,6 @@ static PyObject *PySHCreateShellItemArrayFromIDLists(PyObject *self, PyObject *a
// item
static PyObject *PySHCreateShellItemArrayFromShellItem(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateShellItemArrayFromShellItem == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *obsi;
IShellItem *isi = NULL;
IID iid = IID_IShellItemArray;
Expand Down Expand Up @@ -3116,10 +3071,6 @@ static PyObject *PySHCreateShellItemArrayFromShellItem(PyObject *self, PyObject
// object from a PIDL. Can also create <o PyIShellItem2> objects.
static PyObject *PySHCreateItemFromIDList(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateItemFromIDList == NULL)
return PyCom_BuildPyException(E_NOTIMPL);
PyObject *ret = NULL;
PyObject *obpidl;
IID iid = IID_IShellItem;
Expand Down Expand Up @@ -3151,11 +3102,6 @@ static PyObject *PySHCreateItemFromIDList(PyObject *self, PyObject *args)
// parsing name.
static PyObject *PySHCreateItemFromParsingName(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateItemFromParsingName == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *obname, *obctx, *obiid;
// @pyparm str|name||The display name of the item to create, eg a file path
Expand Down Expand Up @@ -3203,11 +3149,6 @@ static PyObject *PySHCreateItemFromParsingName(PyObject *self, PyObject *args)
// relative parsing name.
static PyObject *PySHCreateItemFromRelativeName(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateItemFromRelativeName == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *obname, *obctx, *obiid, *obparent;
// @pyparm <o PyIShellItem>|Parent||Shell item interface on the parent folder
Expand Down Expand Up @@ -3267,11 +3208,6 @@ static PyObject *PySHCreateItemFromRelativeName(PyObject *self, PyObject *args)
// inside a known folder.
static PyObject *PySHCreateItemInKnownFolder(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateItemInKnownFolder == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

DWORD flags;
PyObject *obname;
IID riid = IID_IShellItem;
Expand Down Expand Up @@ -3302,10 +3238,6 @@ static PyObject *PySHCreateItemInKnownFolder(PyObject *self, PyObject *args)
// ID.
static PyObject *PySHCreateItemWithParent(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHCreateItemWithParent == NULL)
return PyCom_BuildPyException(E_NOTIMPL);
PyObject *ret = NULL;
PyObject *obpidlparent, *obsfparent, *obpidl;
IID riid = IID_IShellItem;
Expand Down Expand Up @@ -3352,11 +3284,6 @@ static PyObject *PySHCreateItemWithParent(PyObject *self, PyObject *args)
// @pymethod <o PyIDL>|shell|SHGetIDListFromObject|Retrieves the PIDL of an object.
static PyObject *PySHGetIDListFromObject(PyObject *self, PyObject *args)
{
// @comm This function is only available on Vista and later; a
// COM exception with E_NOTIMPL will be thrown if the function can't be located.
if (pfnSHGetIDListFromObject == NULL)
return PyCom_BuildPyException(E_NOTIMPL);

PyObject *ret = NULL;
PyObject *ob;

Expand Down
Loading