Reputation: 841
The following code works well in Python 2:
import ctypes
def test():
OpenSCManager = ctypes.windll.advapi32.OpenSCManagerA
CloseServiceHandle = ctypes.windll.advapi32.CloseServiceHandle
handle = OpenSCManager(None, None, 0)
print(hex(handle))
assert handle, ctypes.GetLastError()
assert CloseServiceHandle(handle), ctypes.GetLastError()
test()
It does not work in Python 3:
0x40d88f90
Traceback (most recent call last):
File ".\test1.py", line 12, in <module>
test()
File ".\test1.py", line 10, in test
assert CloseServiceHandle(handle), ctypes.GetLastError()
AssertionError: 6
6 means invalid handle.
It seems that in addition, the handles retrieved in Python 2 are smaller numbers, such as 0x100ffc0. It isn't something specific with CloseServiceHandle
. This handle cannot be used with any service function.
Both Python versions are 64 bit native Windows Python.
Upvotes: 1
Views: 670
Reputation: 8166
You should use argtypes
and restype
otherwise all argument default to int and are truncated in 64-bit. Also you shouldn't call GetLastError
directly but use ctypes.get_last_error()
which cache the last error code (there might have been windows APIs called by the interpreter after you perform a call, you can't be sure).
Here's a working example:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import ctypes
def test():
advapi32 = ctypes.WinDLL("advapi32", use_last_error=True)
OpenSCManager = advapi32.OpenSCManagerA
OpenSCManager.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_ulong]
OpenSCManager.restype = ctypes.c_void_p
CloseServiceHandle = advapi32.CloseServiceHandle
CloseServiceHandle.argtypes = [ctypes.c_void_p]
CloseServiceHandle.restype = ctypes.c_long
handle = OpenSCManager(None, None, 0)
if not handle:
raise ctypes.WinError(ctypes.get_last_error())
print(f"handle: {handle:#x}")
result = CloseServiceHandle(handle)
if result == 0:
raise ctypes.WinError(ctypes.get_last_error())
def main():
test()
if __name__ == "__main__":
sys.exit(main())
Upvotes: 4