Skip to content

Commit 1c99141

Browse files
committed
Merge branch 'master' into addonChangelog
2 parents 5d19654 + 47e6cf5 commit 1c99141

38 files changed

+1866
-376
lines changed

.github/workflows/testAndPublish.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,13 @@ jobs:
500500
# Used to protect branches/tags as a general status check so we can check a single job for all rulesets.
501501
name: Check if all tests pass
502502
runs-on: ubuntu-latest
503+
if: always()
503504
needs: [buildNVDA, typeCheck, checkPo, checkPot, licenseCheck, unitTests, createLauncher, systemTests, createSymbols]
504505
steps:
505506
- name: Check if all tests pass
506-
run: echo "All tests passed successfully."
507+
uses: re-actors/[email protected]
508+
with:
509+
jobs: ${{ toJSON(needs) }}
507510

508511
uploadSymbols:
509512
name: Upload symbols

source/IAccessibleHandler/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import weakref
2424
from ctypes import (
2525
wintypes,
26-
windll,
2726
byref,
2827
c_void_p,
2928
c_char,
@@ -1307,6 +1306,6 @@ def isMarshalledIAccessible(IAccessibleObject):
13071306
.contents.value
13081307
)
13091308
handle = HANDLE()
1310-
windll.kernel32.GetModuleHandleExW(6, addr, byref(handle))
1309+
winBindings.kernel32.GetModuleHandleEx(6, addr, byref(handle))
13111310
winBindings.kernel32.GetModuleFileName(handle, buf, 1024)
13121311
return not buf.value.lower().endswith("oleacc.dll")

source/NVDAHelper/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ def nvdaControllerInternal_inputLangChangeNotify(threadID, hkl, layoutString):
606606
import ui
607607

608608
buf = create_unicode_buffer(1024)
609-
res = windll.kernel32.GetLocaleInfoW(languageID, 2, buf, 1024)
609+
res = winBindings.kernel32.GetLocaleInfo(languageID, 2, buf, 1024)
610610
# Translators: the label for an unknown language when switching input methods.
611611
inputLanguageName = buf.value if res else _("unknown language")
612612
layoutStringCodes = []

source/NVDAObjects/IAccessible/winword.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
# See the file COPYING for more details.
55

66
from comtypes import COMError
7-
import ctypes
87
import operator
98
import uuid
109
from logHandler import log
10+
import winBindings.kernel32
1111
from winBindings import user32
1212
import speech
1313
import controlTypes
@@ -585,7 +585,7 @@ def event_gainFocus(self):
585585
return
586586
document = next((x for x in self.children if isinstance(x, WordDocument)), None)
587587
if document:
588-
curThreadID = ctypes.windll.kernel32.GetCurrentThreadId()
588+
curThreadID = winBindings.kernel32.GetCurrentThreadId()
589589
user32.AttachThreadInput(curThreadID, document.windowThreadID, True)
590590
user32.SetFocus(document.windowHandle)
591591
user32.AttachThreadInput(curThreadID, document.windowThreadID, False)

source/UIAHandler/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import ctypes
77
import ctypes.wintypes
88
from ctypes import (
9-
windll,
109
POINTER,
1110
CFUNCTYPE, # noqa: F401
1211
c_voidp, # noqa: F401
@@ -456,7 +455,7 @@ def terminate(self):
456455

457456
# Terminate the MTA thread
458457
MTAThreadHandle = ctypes.wintypes.HANDLE(
459-
windll.kernel32.OpenThread(
458+
winBindings.kernel32.OpenThread(
460459
winKernel.SYNCHRONIZE,
461460
False,
462461
self.MTAThread.ident,

source/addonAPIVersion.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import buildVersion
88
import re
9-
from logHandler import log
9+
1010

1111
"""
1212
This module contains add-on API version information for this build of NVDA. This file provides information on
@@ -83,5 +83,7 @@ def formatForGUI(versionTuple: AddonApiVersionT) -> str:
8383
# than an exception and unusable dialog.
8484
# Translators: shown when an addon API version string is unknown
8585
default = _("unknown")
86+
from logHandler import log
87+
8688
log.error("Unable to format versionTuple: {}".format(repr(versionTuple)), exc_info=True)
8789
return default

source/addonHandler/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import config
3535
import languageHandler
3636
from logHandler import log
37-
import winKernel
37+
import winBindings.kernel32
3838
import addonAPIVersion
3939
import importlib
4040
import NVDAState
@@ -950,7 +950,8 @@ def extract(self, addonPath: Optional[str] = None):
950950
# #2505: Handle non-Unicode file names.
951951
# Most archivers seem to use the local OEM code page, even though the spec says only cp437.
952952
# HACK: Overriding info.filename is a bit ugly, but it avoids a lot of code duplication.
953-
info.filename = info.filename.decode("cp%d" % winKernel.kernel32.GetOEMCP())
953+
oemcp = winBindings.kernel32.GetOEMCP()
954+
info.filename = info.filename.decode(f"cp{oemcp}")
954955
z.extract(info, addonPath)
955956

956957
@property

source/appModuleHandler.py

Lines changed: 35 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
import sys
1717
from types import ModuleType
1818
from typing import (
19-
Any,
2019
Dict,
2120
List,
2221
Optional,
2322
Tuple,
2423
)
2524

25+
import winBindings.kernel32
2626
import winVersion
2727
import importlib
2828
import importlib.util
@@ -32,7 +32,6 @@
3232
import baseObject
3333
from logHandler import log
3434
import NVDAHelper
35-
import NVDAState
3635
import winKernel
3736
import config
3837
import NVDAObjects # Catches errors before loading default appModule
@@ -50,6 +49,24 @@
5049
)
5150
from comInterfaces import UIAutomationClient as UIA
5251
import winBindings.rpcrt4
52+
from utils import _deprecate
53+
54+
55+
__getattr__ = _deprecate.handleDeprecations(
56+
_deprecate.MovedSymbol(
57+
"processEntry32W",
58+
"winBindings.kernel32",
59+
),
60+
_deprecate.MovedSymbol(
61+
"_PROCESS_MACHINE_INFORMATION",
62+
"winBindings.kernel32",
63+
),
64+
_deprecate.MovedSymbol(
65+
"NVDAProcessID",
66+
"globalVars",
67+
"appPid",
68+
),
69+
)
5370

5471

5572
# Dictionary of processID:appModule pairs used to hold the currently running modules
@@ -69,47 +86,6 @@
6986
"""
7087

7188

72-
class processEntry32W(ctypes.Structure):
73-
"""See https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/ns-tlhelp32-processentry32w"""
74-
75-
_fields_ = [
76-
("dwSize", ctypes.wintypes.DWORD),
77-
("cntUsage", ctypes.wintypes.DWORD),
78-
("th32ProcessID", ctypes.wintypes.DWORD),
79-
("th32DefaultHeapID", ctypes.wintypes.PULONG),
80-
("th32ModuleID", ctypes.wintypes.DWORD),
81-
("cntThreads", ctypes.wintypes.DWORD),
82-
("th32ParentProcessID", ctypes.wintypes.DWORD),
83-
("pcPriClassBase", ctypes.c_long),
84-
("dwFlags", ctypes.wintypes.DWORD),
85-
("szExeFile", ctypes.c_wchar * 260),
86-
]
87-
88-
89-
class _PROCESS_MACHINE_INFORMATION(ctypes.Structure):
90-
_fields_ = [
91-
("ProcessMachine", ctypes.wintypes.USHORT),
92-
("Res0", ctypes.wintypes.USHORT),
93-
("MachineAttributes", ctypes.wintypes.DWORD),
94-
]
95-
96-
97-
def __getattr__(attrName: str) -> Any:
98-
"""Module level `__getattr__` used to preserve backward compatibility.
99-
The module level variable `NVDAProcessID` is deprecated
100-
and usages should be replaced with `globalVars.appPid`.
101-
We cannot simply assign the value from `globalVars` to the old attribute
102-
since add-ons are initialized before `appModuleHandler`
103-
and when `appModuleHandler` was not yet initialized the variable was set to `None`.
104-
"""
105-
if attrName == "NVDAProcessID" and NVDAState._allowDeprecatedAPI():
106-
log.warning("appModuleHandler.NVDAProcessID is deprecated, use globalVars.appPid instead.")
107-
if initialize._alreadyInitialized:
108-
return globalVars.appPid
109-
return None
110-
raise AttributeError(f"module {repr(__name__)} has no attribute {repr(attrName)}")
111-
112-
11389
def registerExecutableWithAppModule(executableName: str, appModName: str) -> None:
11490
"""Registers appModule to be used for a given executable."""
11591
_executableNamesToAppModsAddons[executableName] = appModName
@@ -181,17 +157,17 @@ def getAppNameFromProcessID(processID: int, includeExt: bool = False) -> str:
181157
"""
182158
if processID == globalVars.appPid:
183159
return "nvda.exe" if includeExt else "nvda"
184-
FSnapshotHandle = winKernel.kernel32.CreateToolhelp32Snapshot(2, 0)
185-
FProcessEntry32 = processEntry32W()
186-
FProcessEntry32.dwSize = ctypes.sizeof(processEntry32W)
187-
ContinueLoop = winKernel.kernel32.Process32FirstW(FSnapshotHandle, ctypes.byref(FProcessEntry32))
160+
FSnapshotHandle = winBindings.kernel32.CreateToolhelp32Snapshot(2, 0)
161+
FProcessEntry32 = winBindings.kernel32.PROCESSENTRY32W()
162+
FProcessEntry32.dwSize = ctypes.sizeof(FProcessEntry32)
163+
ContinueLoop = winBindings.kernel32.Process32First(FSnapshotHandle, ctypes.byref(FProcessEntry32))
188164
appName = str()
189165
while ContinueLoop:
190166
if FProcessEntry32.th32ProcessID == processID:
191167
appName = FProcessEntry32.szExeFile
192168
break
193-
ContinueLoop = winKernel.kernel32.Process32NextW(FSnapshotHandle, ctypes.byref(FProcessEntry32))
194-
winKernel.kernel32.CloseHandle(FSnapshotHandle)
169+
ContinueLoop = winBindings.kernel32.Process32Next(FSnapshotHandle, ctypes.byref(FProcessEntry32))
170+
winBindings.kernel32.CloseHandle(FSnapshotHandle)
195171
if not includeExt:
196172
appName = os.path.splitext(appName)[0].lower()
197173
if not appName:
@@ -548,7 +524,7 @@ def _get_processExecutablePath(self) -> str:
548524
# Create the buffer to get the executable name
549525
exeFileName = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
550526
length = ctypes.wintypes.DWORD(ctypes.wintypes.MAX_PATH)
551-
if not ctypes.windll.Kernel32.QueryFullProcessImageNameW(
527+
if not winBindings.kernel32.QueryFullProcessImageName(
552528
self.processHandle,
553529
0,
554530
exeFileName,
@@ -571,10 +547,10 @@ def _getImmersivePackageInfo(self):
571547
# Some apps such as File Explorer says it is an immersive process but error 15700 is shown.
572548
# Others such as Store version of Office are not truly hosted apps but are distributed via Store.
573549
length = ctypes.c_uint()
574-
ctypes.windll.kernel32.GetPackageFullName(self.processHandle, ctypes.byref(length), None)
550+
winBindings.kernel32.GetPackageFullName(self.processHandle, ctypes.byref(length), None)
575551
packageFullName = ctypes.create_unicode_buffer(length.value)
576552
if (
577-
ctypes.windll.kernel32.GetPackageFullName(
553+
winBindings.kernel32.GetPackageFullName(
578554
self.processHandle,
579555
ctypes.byref(length),
580556
packageFullName,
@@ -675,7 +651,7 @@ def _get_appPath(self):
675651
"""
676652
size = ctypes.wintypes.DWORD(ctypes.wintypes.MAX_PATH)
677653
path = ctypes.create_unicode_buffer(size.value)
678-
winKernel.kernel32.QueryFullProcessImageNameW(self.processHandle, 0, path, ctypes.byref(size))
654+
winBindings.kernel32.QueryFullProcessImageName(self.processHandle, 0, path, ctypes.byref(size))
679655
self.appPath = path.value if path else None
680656
return self.appPath
681657

@@ -691,7 +667,7 @@ def _get_is64BitProcess(self) -> bool:
691667
# We need IsWow64Process2 to detect WOW64 on ARM64.
692668
processMachine = ctypes.wintypes.USHORT()
693669
if (
694-
ctypes.windll.kernel32.IsWow64Process2(
670+
winBindings.kernel32.IsWow64Process2(
695671
self.processHandle,
696672
ctypes.byref(processMachine),
697673
None,
@@ -706,7 +682,7 @@ def _get_is64BitProcess(self) -> bool:
706682
# IsWow64Process2 is only supported on Windows 10 version 1511 and later.
707683
# Fall back to IsWow64Process.
708684
res = ctypes.wintypes.BOOL()
709-
if ctypes.windll.kernel32.IsWow64Process(self.processHandle, ctypes.byref(res)) == 0:
685+
if winBindings.kernel32.IsWow64Process(self.processHandle, ctypes.byref(res)) == 0:
710686
self.is64BitProcess = False
711687
return False
712688
self.is64BitProcess = not res
@@ -764,15 +740,15 @@ def _get_appArchitecture(self) -> str:
764740
}
765741
# #14403: GetProcessInformation can be called from Windows 11 and later to obtain process machine.
766742
if winVersion.getWinVer() >= winVersion.WIN11:
767-
processMachineInfo = _PROCESS_MACHINE_INFORMATION()
743+
processMachineInfo = winBindings.kernel32._PROCESS_MACHINE_INFORMATION()
768744
# Constant comes from PROCESS_INFORMATION_CLASS enumeration.
769745
ProcessMachineTypeInfo = 9
770746
# Sometimes getProcessInformation may fail, so say "unknown".
771-
if not ctypes.windll.kernel32.GetProcessInformation(
747+
if not winBindings.kernel32.GetProcessInformation(
772748
self.processHandle,
773749
ProcessMachineTypeInfo,
774750
ctypes.byref(processMachineInfo),
775-
ctypes.sizeof(_PROCESS_MACHINE_INFORMATION),
751+
ctypes.sizeof(processMachineInfo),
776752
):
777753
self.appArchitecture = "unknown"
778754
else:
@@ -784,7 +760,7 @@ def _get_appArchitecture(self) -> str:
784760
try:
785761
# If a native app is running (such as x64 app on x64 machines), app architecture value is not set.
786762
processMachine = ctypes.wintypes.USHORT()
787-
ctypes.windll.kernel32.IsWow64Process2(self.processHandle, ctypes.byref(processMachine), None)
763+
winBindings.kernel32.IsWow64Process2(self.processHandle, ctypes.byref(processMachine), None)
788764
if not processMachine.value:
789765
self.appArchitecture = winVersion.getWinVer().processorArchitecture
790766
else:

source/appModules/outlook.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import comtypes.automation
1111
import ctypes
1212
from scriptHandler import script
13+
import winBindings.kernel32
1314
import winKernel
1415
import comHelper
1516
import NVDAHelper
@@ -430,7 +431,7 @@ def _generateCategoriesText(appointment):
430431
bufLength = 4
431432
separatorBuf = ctypes.create_unicode_buffer(bufLength)
432433
if (
433-
ctypes.windll.kernel32.GetLocaleInfoW(
434+
winBindings.kernel32.GetLocaleInfo(
434435
languageHandler.LOCALE_USER_DEFAULT,
435436
languageHandler.LOCALE.SLIST,
436437
separatorBuf,

source/appModules/wwahost.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# A part of NonVisual Desktop Access (NVDA)
22
# This file is covered by the GNU General Public License.
33
# See the file COPYING for more details.
4-
# Copyright (C) 2012-2020 NV Access Limited, Joseph Lee
4+
# Copyright (C) 2012-2025 NV Access Limited, Joseph Lee
55

66
"""App module host for Windows 8.x and 10 apps hosted by wwahost.exe.
77
In Windows 8, apps written in Javascript are executed inside WWAHost, including some WinRT apps.
@@ -11,6 +11,7 @@
1111

1212
import ctypes
1313
import appModuleHandler
14+
import winBindings.kernel32
1415
import winKernel
1516

1617

@@ -23,9 +24,9 @@ def getAppNameFromHost(processId):
2324
processId,
2425
)
2526
length = ctypes.c_uint()
26-
winKernel.kernel32.GetApplicationUserModelId(processHandle, ctypes.byref(length), None)
27+
winBindings.kernel32.GetApplicationUserModelId(processHandle, ctypes.byref(length), None)
2728
appModel = ctypes.create_unicode_buffer(length.value)
28-
winKernel.kernel32.GetApplicationUserModelId(processHandle, ctypes.byref(length), appModel)
29+
winBindings.kernel32.GetApplicationUserModelId(processHandle, ctypes.byref(length), appModel)
2930
winKernel.closeHandle(processHandle)
3031
# Sometimes app model might be empty, so raise errors and fall back to wwahost.
3132
if not appModel.value:

0 commit comments

Comments
 (0)