32
33
from breezy.i18n import gettext
34
has_ctypes_win32 = False
35
if sys.platform == 'win32':
39
has_ctypes_win32 = False
35
# We can cope without it; use a separate variable to help pyflakes
42
create_buffer = ctypes.create_unicode_buffer
43
extract_buffer = operator.attrgetter("value")
49
has_pywintypes = has_win32file = has_win32api = False
62
# pulling in win32com.shell is a bit of overhead, and normally we don't need
63
# it as ctypes is preferred and common. lazy_imports and "optional"
64
# modules don't work well, so we do our own lazy thing...
65
has_win32com_shell = None # Set to True or False once we know for sure...
42
67
# Special Win32 API constants
43
68
# Handles of std streams
64
89
def debug_memory_win32api(message='', short=True):
65
90
"""Use trace.note() to dump the running memory info."""
66
91
from breezy import trace
68
93
class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
69
94
"""Used by GetProcessMemoryInfo"""
70
95
_fields_ = [('cb', ctypes.c_ulong),
98
123
'PeakPagefileUsage': mem_struct.PeakPagefileUsage,
99
124
'PrivateUsage': mem_struct.PrivateUsage,
128
# win32process does not return PrivateUsage, because it doesn't use
129
# PROCESS_MEMORY_COUNTERS_EX (it uses the one without _EX).
130
proc = win32process.GetCurrentProcess()
131
info = win32process.GetProcessMemoryInfo(proc)
102
133
trace.note(gettext('Cannot debug memory on win32 without ctypes'
103
134
' or win32process'))
132
163
console window and return tuple (sizex, sizey) if success,
133
164
or default size (defaultx, defaulty) otherwise.
135
if not has_ctypes_win32:
136
167
# no ctypes is found
137
168
return (defaultx, defaulty)
168
199
buf = ctypes.create_unicode_buffer(MAX_PATH)
169
200
if SHGetSpecialFolderPath(None, buf, csidl, 0):
203
global has_win32com_shell
204
if has_win32com_shell is None:
206
from win32com.shell import shell
207
has_win32com_shell = True
209
has_win32com_shell = False
210
if has_win32com_shell:
211
# still need to bind the name locally, but this is fast.
212
from win32com.shell import shell
214
return shell.SHGetSpecialFolderPath(0, csidl, 0)
216
# possibly E_NOTIMPL meaning we can't load the function pointer,
217
# or E_FAIL meaning the function failed - regardless, just ignore it
234
282
"""Return user name as login name.
235
283
If name cannot be obtained return None.
239
287
advapi32 = ctypes.windll.advapi32
240
GetUserName = getattr(advapi32, 'GetUserNameW')
288
GetUserName = getattr(advapi32, 'GetUserName' + suffix)
241
289
except AttributeError:
244
buf = ctypes.create_unicode_buffer(UNLEN + 1)
292
buf = create_buffer(UNLEN + 1)
245
293
n = ctypes.c_int(UNLEN + 1)
246
294
if GetUserName(buf, ctypes.byref(n)):
295
return extract_buffer(buf)
248
296
# otherwise try env variables
249
297
return get_environ_unicode('USERNAME')
261
309
:return: A unicode string representing the host name.
313
return win32api.GetComputerNameEx(_WIN32_ComputerNameDnsHostname)
314
except (NotImplementedError, win32api.error):
315
# NotImplemented will happen on win9x...
265
319
kernel32 = ctypes.windll.kernel32
266
320
except AttributeError:
267
321
pass # Missing the module we need
269
buf = ctypes.create_unicode_buffer(MAX_COMPUTERNAME_LENGTH + 1)
323
buf = create_buffer(MAX_COMPUTERNAME_LENGTH + 1)
270
324
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH + 1)
272
326
# Try GetComputerNameEx which gives a proper Unicode hostname
273
GetComputerNameEx = getattr(kernel32, 'GetComputerNameExW', None)
327
GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx' + suffix,
274
329
if (GetComputerNameEx is not None
275
330
and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
276
331
buf, ctypes.byref(n))):
332
return extract_buffer(buf)
334
# Try GetComputerName in case GetComputerNameEx wasn't found
335
# It returns the NETBIOS name, which isn't as good, but still ok.
336
# The first GetComputerNameEx might have changed 'n', so reset it
337
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH + 1)
338
GetComputerName = getattr(kernel32, 'GetComputerName' + suffix,
340
if (GetComputerName is not None
341
and GetComputerName(buf, ctypes.byref(n))):
342
return extract_buffer(buf)
278
343
return get_environ_unicode('COMPUTERNAME')
376
441
def set_file_attr_hidden(path):
377
442
"""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
382
# <https://docs.microsoft.com/windows/desktop/api/fileapi/nf-fileapi-setfileattributesw>
383
_SetFileAttributesW = ctypes.WINFUNCTYPE(BOOL, LPCWSTR, DWORD)(
384
("SetFileAttributesW", _kernel32))
385
FILE_ATTRIBUTE_HIDDEN = 2
386
if not SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN):
387
e = ctypes.WinError()
389
trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
444
SetFileAttributes = win32file.SetFileAttributesW
446
SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)
447
except pywintypes.error as e:
449
trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
392
452
def _command_line_to_argv(command_line, argv, single_quotes_allowed=False):
454
514
A large enough buffer will be allocated to retrieve the value, though
455
515
it may take two calls to the underlying library function.
517
This needs ctypes because pywin32 does not expose the wide version.
457
519
cfunc = getattr(get_environ_unicode, "_c_function", None)
458
520
if cfunc is None:
462
524
get_environ_unicode._c_function = cfunc
463
525
buffer_size = 256 # heuristic, 256 characters often enough
465
buf = ctypes.create_unicode_buffer(buffer_size)
466
length = cfunc(key, buf, buffer_size)
527
buffer = ctypes.create_unicode_buffer(buffer_size)
528
length = cfunc(key, buffer, buffer_size)
468
530
code = ctypes.GetLastError()
469
531
if code == 203: # ERROR_ENVVAR_NOT_FOUND
471
533
raise ctypes.WinError(code)
472
534
if buffer_size > length:
535
return buffer[:length]
474
536
buffer_size = length
540
def _pywin32_is_local_pid_dead(pid):
541
"""True if pid doesn't correspond to live process on this machine"""
543
handle = win32api.OpenProcess(1, False, pid) # PROCESS_TERMINATE
544
except pywintypes.error as e:
545
if e[0] == 5: # ERROR_ACCESS_DENIED
546
# Probably something alive we're not allowed to kill
548
elif e[0] == 87: # ERROR_INVALID_PARAMETER
553
is_local_pid_dead = _pywin32_is_local_pid_dead
554
elif has_ctypes and sys.platform == 'win32':
478
555
from ctypes.wintypes import BOOL, DWORD, HANDLE
479
556
_kernel32 = ctypes.windll.kernel32
480
557
_CloseHandle = ctypes.WINFUNCTYPE(BOOL, HANDLE)(
495
572
raise ctypes.WinError(errorcode)
496
573
_CloseHandle(handle)
499
575
is_local_pid_dead = _ctypes_is_local_pid_dead
578
def _is_pywintypes_error(evalue):
579
"""True if exception instance is an error from pywin32"""
580
if has_pywintypes and isinstance(evalue, pywintypes.error):