62
55
def debug_memory_win32api(message='', short=True):
63
56
"""Use trace.note() to dump the running memory info."""
64
58
from breezy import trace
66
class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
67
"""Used by GetProcessMemoryInfo"""
68
_fields_ = [('cb', ctypes.c_ulong),
69
('PageFaultCount', ctypes.c_ulong),
70
('PeakWorkingSetSize', ctypes.c_size_t),
71
('WorkingSetSize', ctypes.c_size_t),
72
('QuotaPeakPagedPoolUsage', ctypes.c_size_t),
73
('QuotaPagedPoolUsage', ctypes.c_size_t),
74
('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t),
75
('QuotaNonPagedPoolUsage', ctypes.c_size_t),
76
('PagefileUsage', ctypes.c_size_t),
77
('PeakPagefileUsage', ctypes.c_size_t),
78
('PrivateUsage', ctypes.c_size_t),
80
cur_process = ctypes.windll.kernel32.GetCurrentProcess()
81
mem_struct = PROCESS_MEMORY_COUNTERS_EX()
82
ret = ctypes.windll.psapi.GetProcessMemoryInfo(
83
cur_process, ctypes.byref(mem_struct), ctypes.sizeof(mem_struct))
85
trace.note(gettext('Failed to GetProcessMemoryInfo()'))
87
info = {'PageFaultCount': mem_struct.PageFaultCount,
88
'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize,
89
'WorkingSetSize': mem_struct.WorkingSetSize,
90
'QuotaPeakPagedPoolUsage': mem_struct.QuotaPeakPagedPoolUsage,
91
'QuotaPagedPoolUsage': mem_struct.QuotaPagedPoolUsage,
92
'QuotaPeakNonPagedPoolUsage':
93
mem_struct.QuotaPeakNonPagedPoolUsage,
94
'QuotaNonPagedPoolUsage': mem_struct.QuotaNonPagedPoolUsage,
95
'PagefileUsage': mem_struct.PagefileUsage,
96
'PeakPagefileUsage': mem_struct.PeakPagefileUsage,
97
'PrivateUsage': mem_struct.PrivateUsage,
100
trace.note(gettext('Cannot debug memory on win32 without ctypes'
59
class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
60
"""Used by GetProcessMemoryInfo"""
61
_fields_ = [('cb', ctypes.c_ulong),
62
('PageFaultCount', ctypes.c_ulong),
63
('PeakWorkingSetSize', ctypes.c_size_t),
64
('WorkingSetSize', ctypes.c_size_t),
65
('QuotaPeakPagedPoolUsage', ctypes.c_size_t),
66
('QuotaPagedPoolUsage', ctypes.c_size_t),
67
('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t),
68
('QuotaNonPagedPoolUsage', ctypes.c_size_t),
69
('PagefileUsage', ctypes.c_size_t),
70
('PeakPagefileUsage', ctypes.c_size_t),
71
('PrivateUsage', ctypes.c_size_t),
73
cur_process = ctypes.windll.kernel32.GetCurrentProcess()
74
mem_struct = PROCESS_MEMORY_COUNTERS_EX()
75
ret = ctypes.windll.psapi.GetProcessMemoryInfo(
76
cur_process, ctypes.byref(mem_struct), ctypes.sizeof(mem_struct))
78
trace.note(gettext('Failed to GetProcessMemoryInfo()'))
80
info = {'PageFaultCount': mem_struct.PageFaultCount,
81
'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize,
82
'WorkingSetSize': mem_struct.WorkingSetSize,
83
'QuotaPeakPagedPoolUsage': mem_struct.QuotaPeakPagedPoolUsage,
84
'QuotaPagedPoolUsage': mem_struct.QuotaPagedPoolUsage,
85
'QuotaPeakNonPagedPoolUsage':
86
mem_struct.QuotaPeakNonPagedPoolUsage,
87
'QuotaNonPagedPoolUsage': mem_struct.QuotaNonPagedPoolUsage,
88
'PagefileUsage': mem_struct.PagefileUsage,
89
'PeakPagefileUsage': mem_struct.PeakPagefileUsage,
90
'PrivateUsage': mem_struct.PrivateUsage,
104
93
# using base-2 units (see HACKING.txt).
105
94
trace.note(gettext('WorkingSize {0:>7}KiB'
232
217
"""Return user name as login name.
233
218
If name cannot be obtained return None.
237
advapi32 = ctypes.windll.advapi32
238
GetUserName = getattr(advapi32, 'GetUserNameW')
239
except AttributeError:
242
buf = ctypes.create_unicode_buffer(UNLEN + 1)
243
n = ctypes.c_int(UNLEN + 1)
244
if GetUserName(buf, ctypes.byref(n)):
221
advapi32 = ctypes.windll.advapi32
222
GetUserName = getattr(advapi32, 'GetUserNameW')
223
except AttributeError:
226
buf = ctypes.create_unicode_buffer(UNLEN + 1)
227
n = ctypes.c_int(UNLEN + 1)
228
if GetUserName(buf, ctypes.byref(n)):
246
230
# otherwise try env variables
247
return get_environ_unicode('USERNAME')
231
return os.environ.get('USERNAME')
250
234
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
259
243
:return: A unicode string representing the host name.
263
kernel32 = ctypes.windll.kernel32
264
except AttributeError:
265
pass # Missing the module we need
267
buf = ctypes.create_unicode_buffer(MAX_COMPUTERNAME_LENGTH + 1)
268
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH + 1)
246
buf = ctypes.create_unicode_buffer(MAX_COMPUTERNAME_LENGTH + 1)
247
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH + 1)
270
# Try GetComputerNameEx which gives a proper Unicode hostname
271
GetComputerNameEx = getattr(kernel32, 'GetComputerNameExW', None)
272
if (GetComputerNameEx is not None
273
and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
274
buf, ctypes.byref(n))):
276
return get_environ_unicode('COMPUTERNAME')
249
# Try GetComputerNameEx which gives a proper Unicode hostname
250
GetComputerNameEx = getattr(
251
ctypes.windll.kernel32, 'GetComputerNameExW', None)
252
if (GetComputerNameEx is not None
253
and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
254
buf, ctypes.byref(n))):
256
return os.environ.get('COMPUTERNAME')
279
259
def _ensure_with_dir(path):
364
344
if type_id == REG_SZ:
366
if type_id == REG_EXPAND_SZ and has_win32api:
367
fullpath = win32api.ExpandEnvironmentStrings(path)
368
if len(fullpath) > 1 and fullpath[0] == '"' and fullpath[-1] == '"':
369
fullpath = fullpath[1:-1] # remove quotes around value
374
349
def set_file_attr_hidden(path):
375
350
"""Set file attributes to hidden if possible"""
376
if not has_ctypes_win32:
378
from ctypes.wintypes import BOOL, DWORD, LPCWSTR
379
_kernel32 = ctypes.windll.kernel32
351
from ctypes.wintypes import BOOL, DWORD, LPWSTR
380
353
# <https://docs.microsoft.com/windows/desktop/api/fileapi/nf-fileapi-setfileattributesw>
381
_SetFileAttributesW = ctypes.WINFUNCTYPE(BOOL, LPCWSTR, DWORD)(
382
("SetFileAttributesW", _kernel32))
354
SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW
355
SetFileAttributes.argtypes = LPWSTR, DWORD
356
SetFileAttributes.restype = BOOL
383
357
FILE_ATTRIBUTE_HIDDEN = 2
384
358
if not SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN):
385
359
e = ctypes.WinError()
433
def get_unicode_argv():
434
prototype = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
435
GetCommandLineW = prototype(("GetCommandLineW",
436
ctypes.windll.kernel32))
437
command_line = GetCommandLineW()
438
if command_line is None:
439
raise ctypes.WinError()
440
# Skip the first argument, since we only care about parameters
441
argv = _command_line_to_argv(command_line, sys.argv)[1:]
444
def get_environ_unicode(key, default=None):
445
"""Get `key` from environment as unicode or `default` if unset
447
The environment is natively unicode on modern windows versions but
448
Python 2 only accesses it through the legacy bytestring api.
450
Environmental variable names are case insenstive on Windows.
452
A large enough buffer will be allocated to retrieve the value, though
453
it may take two calls to the underlying library function.
455
cfunc = getattr(get_environ_unicode, "_c_function", None)
457
from ctypes.wintypes import DWORD, LPCWSTR, LPWSTR
458
cfunc = ctypes.WINFUNCTYPE(DWORD, LPCWSTR, LPWSTR, DWORD)(
459
("GetEnvironmentVariableW", ctypes.windll.kernel32))
460
get_environ_unicode._c_function = cfunc
461
buffer_size = 256 # heuristic, 256 characters often enough
463
buf = ctypes.create_unicode_buffer(buffer_size)
464
length = cfunc(key, buf, buffer_size)
466
code = ctypes.GetLastError()
467
if code == 203: # ERROR_ENVVAR_NOT_FOUND
469
raise ctypes.WinError(code)
470
if buffer_size > length:
476
from ctypes.wintypes import BOOL, DWORD, HANDLE
477
_kernel32 = ctypes.windll.kernel32
478
_CloseHandle = ctypes.WINFUNCTYPE(BOOL, HANDLE)(
479
("CloseHandle", _kernel32))
480
_OpenProcess = ctypes.WINFUNCTYPE(HANDLE, DWORD, BOOL, DWORD)(
481
("OpenProcess", _kernel32))
483
def _ctypes_is_local_pid_dead(pid):
484
"""True if pid doesn't correspond to live process on this machine"""
485
handle = _OpenProcess(1, False, pid) # PROCESS_TERMINATE
487
errorcode = ctypes.GetLastError()
488
if errorcode == 5: # ERROR_ACCESS_DENIED
489
# Probably something alive we're not allowed to kill
491
elif errorcode == 87: # ERROR_INVALID_PARAMETER
493
raise ctypes.WinError(errorcode)
497
is_local_pid_dead = _ctypes_is_local_pid_dead
406
def _ctypes_is_local_pid_dead(pid):
408
kernel32 = ctypes.wintypes.windll.kernel32
409
"""True if pid doesn't correspond to live process on this machine"""
410
handle = kernel32.OpenProcess(1, False, pid)
412
errorcode = ctypes.GetLastError()
413
if errorcode == 5: # ERROR_ACCESS_DENIED
414
# Probably something alive we're not allowed to kill
416
elif errorcode == 87: # ERROR_INVALID_PARAMETER
418
raise ctypes.WinError(errorcode)
419
Kernel32.CloseHandle(handle)
422
is_local_pid_dead = _ctypes_is_local_pid_dead