64
55
def debug_memory_win32api(message='', short=True):
65
56
"""Use trace.note() to dump the running memory info."""
66
58
from breezy import trace
68
class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
69
"""Used by GetProcessMemoryInfo"""
70
_fields_ = [('cb', ctypes.c_ulong),
71
('PageFaultCount', ctypes.c_ulong),
72
('PeakWorkingSetSize', ctypes.c_size_t),
73
('WorkingSetSize', ctypes.c_size_t),
74
('QuotaPeakPagedPoolUsage', ctypes.c_size_t),
75
('QuotaPagedPoolUsage', ctypes.c_size_t),
76
('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t),
77
('QuotaNonPagedPoolUsage', ctypes.c_size_t),
78
('PagefileUsage', ctypes.c_size_t),
79
('PeakPagefileUsage', ctypes.c_size_t),
80
('PrivateUsage', ctypes.c_size_t),
82
cur_process = ctypes.windll.kernel32.GetCurrentProcess()
83
mem_struct = PROCESS_MEMORY_COUNTERS_EX()
84
ret = ctypes.windll.psapi.GetProcessMemoryInfo(
85
cur_process, ctypes.byref(mem_struct), ctypes.sizeof(mem_struct))
87
trace.note(gettext('Failed to GetProcessMemoryInfo()'))
89
info = {'PageFaultCount': mem_struct.PageFaultCount,
90
'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize,
91
'WorkingSetSize': mem_struct.WorkingSetSize,
92
'QuotaPeakPagedPoolUsage': mem_struct.QuotaPeakPagedPoolUsage,
93
'QuotaPagedPoolUsage': mem_struct.QuotaPagedPoolUsage,
94
'QuotaPeakNonPagedPoolUsage':
95
mem_struct.QuotaPeakNonPagedPoolUsage,
96
'QuotaNonPagedPoolUsage': mem_struct.QuotaNonPagedPoolUsage,
97
'PagefileUsage': mem_struct.PagefileUsage,
98
'PeakPagefileUsage': mem_struct.PeakPagefileUsage,
99
'PrivateUsage': mem_struct.PrivateUsage,
102
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,
106
93
# using base-2 units (see HACKING.txt).
107
94
trace.note(gettext('WorkingSize {0:>7}KiB'
234
217
"""Return user name as login name.
235
218
If name cannot be obtained return None.
239
advapi32 = ctypes.windll.advapi32
240
GetUserName = getattr(advapi32, 'GetUserNameW')
241
except AttributeError:
244
buf = ctypes.create_unicode_buffer(UNLEN + 1)
245
n = ctypes.c_int(UNLEN + 1)
246
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)):
248
230
# otherwise try env variables
249
return get_environ_unicode('USERNAME')
231
return os.environ.get('USERNAME')
252
234
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
261
243
:return: A unicode string representing the host name.
265
kernel32 = ctypes.windll.kernel32
266
except AttributeError:
267
pass # Missing the module we need
269
buf = ctypes.create_unicode_buffer(MAX_COMPUTERNAME_LENGTH + 1)
270
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)
272
# Try GetComputerNameEx which gives a proper Unicode hostname
273
GetComputerNameEx = getattr(kernel32, 'GetComputerNameExW', None)
274
if (GetComputerNameEx is not None
275
and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
276
buf, ctypes.byref(n))):
278
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')
281
259
def _ensure_with_dir(path):
366
344
if type_id == REG_SZ:
368
if type_id == REG_EXPAND_SZ and has_win32api:
369
fullpath = win32api.ExpandEnvironmentStrings(path)
370
if len(fullpath) > 1 and fullpath[0] == '"' and fullpath[-1] == '"':
371
fullpath = fullpath[1:-1] # remove quotes around value
376
349
def set_file_attr_hidden(path):
377
350
"""Set file attributes to hidden if possible"""
378
if not has_ctypes_win32:
380
from ctypes.wintypes import BOOL, DWORD, LPCWSTR
381
_kernel32 = ctypes.windll.kernel32
351
from ctypes.wintypes import BOOL, DWORD, LPWSTR
382
353
# <https://docs.microsoft.com/windows/desktop/api/fileapi/nf-fileapi-setfileattributesw>
383
_SetFileAttributesW = ctypes.WINFUNCTYPE(BOOL, LPCWSTR, DWORD)(
384
("SetFileAttributesW", _kernel32))
354
SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW
355
SetFileAttributes.argtypes = LPWSTR, DWORD
356
SetFileAttributes.restype = BOOL
385
357
FILE_ATTRIBUTE_HIDDEN = 2
386
358
if not SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN):
387
359
e = ctypes.WinError()
435
def get_unicode_argv():
436
prototype = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
437
GetCommandLineW = prototype(("GetCommandLineW",
438
ctypes.windll.kernel32))
439
command_line = GetCommandLineW()
440
if command_line is None:
441
raise ctypes.WinError()
442
# Skip the first argument, since we only care about parameters
443
argv = _command_line_to_argv(command_line, sys.argv)[1:]
446
def get_environ_unicode(key, default=None):
447
"""Get `key` from environment as unicode or `default` if unset
449
The environment is natively unicode on modern windows versions but
450
Python 2 only accesses it through the legacy bytestring api.
452
Environmental variable names are case insenstive on Windows.
454
A large enough buffer will be allocated to retrieve the value, though
455
it may take two calls to the underlying library function.
457
cfunc = getattr(get_environ_unicode, "_c_function", None)
459
from ctypes.wintypes import DWORD, LPCWSTR, LPWSTR
460
cfunc = ctypes.WINFUNCTYPE(DWORD, LPCWSTR, LPWSTR, DWORD)(
461
("GetEnvironmentVariableW", ctypes.windll.kernel32))
462
get_environ_unicode._c_function = cfunc
463
buffer_size = 256 # heuristic, 256 characters often enough
465
buf = ctypes.create_unicode_buffer(buffer_size)
466
length = cfunc(key, buf, buffer_size)
468
code = ctypes.GetLastError()
469
if code == 203: # ERROR_ENVVAR_NOT_FOUND
471
raise ctypes.WinError(code)
472
if buffer_size > length:
478
from ctypes.wintypes import BOOL, DWORD, HANDLE
479
_kernel32 = ctypes.windll.kernel32
480
_CloseHandle = ctypes.WINFUNCTYPE(BOOL, HANDLE)(
481
("CloseHandle", _kernel32))
482
_OpenProcess = ctypes.WINFUNCTYPE(HANDLE, DWORD, BOOL, DWORD)(
483
("OpenProcess", _kernel32))
485
def _ctypes_is_local_pid_dead(pid):
486
"""True if pid doesn't correspond to live process on this machine"""
487
handle = _OpenProcess(1, False, pid) # PROCESS_TERMINATE
489
errorcode = ctypes.GetLastError()
490
if errorcode == 5: # ERROR_ACCESS_DENIED
491
# Probably something alive we're not allowed to kill
493
elif errorcode == 87: # ERROR_INVALID_PARAMETER
495
raise ctypes.WinError(errorcode)
499
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