/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/win32utils.py

  • Committer: Jelmer Vernooij
  • Date: 2019-05-20 03:57:29 UTC
  • mto: This revision was merged to the branch mainline in revision 7328.
  • Revision ID: jelmer@jelmer.uk-20190520035729-9rxvefxkvbbivygy
use default_user_agent function.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
from __future__ import absolute_import
23
23
 
24
24
import glob
 
25
import operator
25
26
import os
26
27
import struct
27
28
import sys
31
32
    )
32
33
from breezy.i18n import gettext
33
34
 
34
 
has_ctypes_win32 = False
35
 
if sys.platform == 'win32':
36
 
    try:
37
 
        import ctypes
38
 
    except ImportError:
39
 
        has_ctypes_win32 = False
 
35
# We can cope without it; use a separate variable to help pyflakes
 
36
try:
 
37
    import ctypes
 
38
    has_ctypes = True
 
39
except ImportError:
 
40
    has_ctypes = False
 
41
else:
 
42
    create_buffer = ctypes.create_unicode_buffer
 
43
    extract_buffer = operator.attrgetter("value")
 
44
    suffix = 'W'
 
45
try:
 
46
    import pywintypes
 
47
    has_pywintypes = True
 
48
except ImportError:
 
49
    has_pywintypes = has_win32file = has_win32api = False
 
50
else:
 
51
    try:
 
52
        import win32file
 
53
        has_win32file = True
 
54
    except ImportError:
 
55
        has_win32file = False
 
56
    try:
 
57
        import win32api
 
58
        has_win32api = True
 
59
    except ImportError:
 
60
        has_win32api = False
40
61
 
 
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...
41
66
 
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
67
 
    if has_ctypes_win32:
 
92
    if has_ctypes:
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,
100
125
                }
 
126
    elif has_win32api:
 
127
        import win32process
 
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)
101
132
    else:
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.
134
165
    """
135
 
    if not has_ctypes_win32:
 
166
    if not has_ctypes:
136
167
        # no ctypes is found
137
168
        return (defaultx, defaulty)
138
169
 
158
189
 
159
190
    Result is always unicode (or None).
160
191
    """
161
 
    if has_ctypes_win32:
 
192
    if has_ctypes:
162
193
        try:
163
194
            SHGetSpecialFolderPath = \
164
195
                ctypes.windll.shell32.SHGetSpecialFolderPathW
168
199
            buf = ctypes.create_unicode_buffer(MAX_PATH)
169
200
            if SHGetSpecialFolderPath(None, buf, csidl, 0):
170
201
                return buf.value
 
202
 
 
203
    global has_win32com_shell
 
204
    if has_win32com_shell is None:
 
205
        try:
 
206
            from win32com.shell import shell
 
207
            has_win32com_shell = True
 
208
        except ImportError:
 
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
 
213
        try:
 
214
            return shell.SHGetSpecialFolderPath(0, csidl, 0)
 
215
        except shell.error:
 
216
            # possibly E_NOTIMPL meaning we can't load the function pointer,
 
217
            # or E_FAIL meaning the function failed - regardless, just ignore it
 
218
            pass
171
219
    return None
172
220
 
173
221
 
234
282
    """Return user name as login name.
235
283
    If name cannot be obtained return None.
236
284
    """
237
 
    if has_ctypes_win32:
 
285
    if has_ctypes:
238
286
        try:
239
287
            advapi32 = ctypes.windll.advapi32
240
 
            GetUserName = getattr(advapi32, 'GetUserNameW')
 
288
            GetUserName = getattr(advapi32, 'GetUserName' + suffix)
241
289
        except AttributeError:
242
290
            pass
243
291
        else:
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)):
247
 
                return buf.value
 
295
                return extract_buffer(buf)
248
296
    # otherwise try env variables
249
297
    return get_environ_unicode('USERNAME')
250
298
 
260
308
 
261
309
    :return: A unicode string representing the host name.
262
310
    """
263
 
    if has_ctypes_win32:
 
311
    if has_win32api:
 
312
        try:
 
313
            return win32api.GetComputerNameEx(_WIN32_ComputerNameDnsHostname)
 
314
        except (NotImplementedError, win32api.error):
 
315
            # NotImplemented will happen on win9x...
 
316
            pass
 
317
    if has_ctypes:
264
318
        try:
265
319
            kernel32 = ctypes.windll.kernel32
266
320
        except AttributeError:
267
321
            pass  # Missing the module we need
268
322
        else:
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)
271
325
 
272
326
            # Try GetComputerNameEx which gives a proper Unicode hostname
273
 
            GetComputerNameEx = getattr(kernel32, 'GetComputerNameExW', None)
 
327
            GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx' + suffix,
 
328
                                        None)
274
329
            if (GetComputerNameEx is not None
275
330
                and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
276
331
                                      buf, ctypes.byref(n))):
277
 
                return buf.value
 
332
                return extract_buffer(buf)
 
333
 
 
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,
 
339
                                      None)
 
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')
279
344
 
280
345
 
375
440
 
376
441
def set_file_attr_hidden(path):
377
442
    """Set file attributes to hidden if possible"""
378
 
    if not has_ctypes_win32:
379
 
        return
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()
388
 
        from . import trace
389
 
        trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
 
443
    if has_win32file:
 
444
        SetFileAttributes = win32file.SetFileAttributesW
 
445
        try:
 
446
            SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)
 
447
        except pywintypes.error as e:
 
448
            from . import trace
 
449
            trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
390
450
 
391
451
 
392
452
def _command_line_to_argv(command_line, argv, single_quotes_allowed=False):
431
491
    return args
432
492
 
433
493
 
434
 
if has_ctypes_win32:
 
494
if has_ctypes:
435
495
    def get_unicode_argv():
436
496
        prototype = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
437
497
        GetCommandLineW = prototype(("GetCommandLineW",
453
513
 
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.
 
516
 
 
517
        This needs ctypes because pywin32 does not expose the wide version.
456
518
        """
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
464
526
        while True:
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)
467
529
            if not length:
468
530
                code = ctypes.GetLastError()
469
531
                if code == 203:  # ERROR_ENVVAR_NOT_FOUND
470
532
                    return default
471
533
                raise ctypes.WinError(code)
472
534
            if buffer_size > length:
473
 
                return buf[:length]
 
535
                return buffer[:length]
474
536
            buffer_size = length
475
537
 
476
538
 
477
 
if has_ctypes_win32:
 
539
if has_win32api:
 
540
    def _pywin32_is_local_pid_dead(pid):
 
541
        """True if pid doesn't correspond to live process on this machine"""
 
542
        try:
 
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
 
547
                return False
 
548
            elif e[0] == 87:  # ERROR_INVALID_PARAMETER
 
549
                return True
 
550
            raise
 
551
        handle.close()
 
552
        return False
 
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)
497
574
        return False
498
 
 
499
575
    is_local_pid_dead = _ctypes_is_local_pid_dead
 
576
 
 
577
 
 
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):
 
581
        return True
 
582
    return False