Skip to content

Commit

Permalink
Update to support Windbg from the App store. 2.2.13
Browse files Browse the repository at this point in the history
  • Loading branch information
dshikashio committed Dec 6, 2024
1 parent 49601ba commit 6f8a19b
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 7 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
## Current Changes
* 2.2.12
* Fix #22 - comtypes issue
* 2.2.13
* Improved discovery of Windbg installation detection. Works with App store installations now.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ Pybag provides helper functions on top of Python bindings for Microsoft Debug En

## Installation

Windows:

Install the Debugging Tools from the Windows SDK here: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ Note that neither of the versions of WinDbg from the Microsoft App Store nor the stand-alone installer are currently supported.
Install the Debugging Tools
* From the Windows SDK here: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
* From the App Store
* Directly: https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/#install-windbg-directly

```sh
python setup.py install
pip install pybag
```

## Usage example
Expand Down Expand Up @@ -57,6 +58,8 @@ k.attach("net:port=50000,key=1.2.3.4")


## Release History
* 2.2.13
* Improved discovery of Windbg installation detection. Works with App store installations now.
* 2.2.12
* Fix #22 - comtypes issue
* 2.2.11
Expand Down
79 changes: 79 additions & 0 deletions pybag/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,91 @@
import ctypes
import pathlib
import platform
import shutil
import os
import winreg

__all__ = ['UserDbg', 'KernelDbg', 'CrashDbg', 'DbgEng']

def get_arch():
if platform.architecture()[0] == '64bit':
return 'amd64'
else:
return 'x86'

def append_arch(dbgroot):
if platform.architecture()[0] == '64bit':
return os.path.join(dbgroot, r'Debuggers\x64')
else:
return os.path.join(dbgroot, r'Debuggers\x86')

def create_cachedir(cachedir, _dbg_dir):
'''Creates a cache of DLL files from WinDbg. Necessary for the version of WinDbg installed from
the Microsoft Store, due to file permission issues.'''

# Create the cache directory.
os.mkdir(cachedir)

# Copy the DLL files we need to the new cache dir.
shutil.copy(os.path.join(_dbg_dir, "dbgeng.dll"), cachedir)
shutil.copy(os.path.join(_dbg_dir, "dbghelp.dll"), cachedir)
shutil.copy(os.path.join(_dbg_dir, "dbgmodel.dll"), cachedir)

# Create version.txt in the cache dir with the full filesystem path that we copied the DLLs from.
# This way we can detect if the cache is stale and needs to be re-created (as the full source path
# contains the WinDbg version number).
with open(os.path.join(cachedir, "version.txt"), "w") as f:
f.write(_dbg_dir)


def get_appdir_cache():
appdir = find_app_install()
if not appdir:
return appdir

# For versions of WinDbg installed from the Microsoft Store, we need to copy the DLL files we need
# into a separate directory, otherwise permission problems will prevent us from loading them.
# We'll copy them to a folder named "pybag_cache" in the user's home directory.
cachedir = os.path.join(str(os.environ['LOCALAPPDATA']), "pybag_cache")
if not os.path.isdir(cachedir):
create_cachedir(cachedir, appdir)
else:
saved_dbgdir = ""
with open(os.path.join(cachedir, "version.txt"), "r") as f:
saved_dbgdir = f.read()
# If the full filesystem path of WinDbg differs from where the contents of the cache dir were
# obtained, then a newer version of WinDbg was installed on this system and the cache is stale.
# In that case we will re-build the cache entirely using the new version.
if saved_dbgdir != appdir:
shutil.rmtree(cachedir)
create_cachedir(cachedir, appdir)
return cachedir


def find_app_install():
# Loop through the keys in this registry path. Any key names that refer to WinDbg likely correspond
# to the install directory in C:\Program Files\WindowsApps\.
packages_key = winreg.OpenKey(
winreg.HKEY_CLASSES_ROOT,
r"Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\PackageRepository\Packages")
continue_flag = True
i = 0
while continue_flag:
try:
package_name = winreg.EnumKey(packages_key, i)
if package_name.find("WinDbg") != -1 and package_name.find("_neutral_") == -1:
dir = os.path.join("C:\\Program Files\\WindowsApps", package_name, get_arch())
if os.path.exists(dir):
winreg.CloseKey(packages_key)
return dir
except OSError: # No more subkeys exist.
continue_flag = False

i += 1

winreg.CloseKey(packages_key)
return ''


def find_dbgdir():
dbgdir = os.getenv('WINDBG_DIR')
Expand All @@ -33,6 +107,11 @@ def find_dbgdir():
dbgdir = append_arch(dbgroot)
if os.path.exists(dbgdir):
return dbgdir

dbgdir = get_appdir_cache()
if os.path.exists(dbgdir):
return dbgdir

raise RuntimeError("Windbg install directory not found!")


Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
README = (HERE / "README.md").read_text()

setup(name='Pybag',
version='2.2.12',
version='2.2.13',
description='Python wrappers for DbgEng from Windbg',
long_description=README,
long_description_content_type="text/markdown",
Expand Down

0 comments on commit 6f8a19b

Please sign in to comment.