/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: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2020-06-11 16:46:46 UTC
  • mfrom: (7512.1.1 drop-travis-appveyor)
  • Revision ID: breezy.the.bot@gmail.com-20200611164646-w4tufva3jchfv1mn
Drop appveyor + travis configuration.

Merged from https://code.launchpad.net/~jelmer/brz/drop-travis-appveyor/+merge/385578

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
    )
30
30
from breezy.i18n import gettext
31
31
 
32
 
has_ctypes_win32 = False
33
 
if sys.platform == 'win32':
34
 
    try:
35
 
        import ctypes
36
 
    except ImportError:
37
 
        has_ctypes_win32 = False
38
 
 
39
32
 
40
33
# Special Win32 API constants
41
34
# Handles of std streams
61
54
 
62
55
def debug_memory_win32api(message='', short=True):
63
56
    """Use trace.note() to dump the running memory info."""
 
57
    import ctypes
64
58
    from breezy import trace
65
 
    if has_ctypes_win32:
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),
79
 
                        ]
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))
84
 
        if not ret:
85
 
            trace.note(gettext('Failed to GetProcessMemoryInfo()'))
86
 
            return
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,
98
 
                }
99
 
    else:
100
 
        trace.note(gettext('Cannot debug memory on win32 without ctypes'
101
 
                           ' or win32process'))
 
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),
 
72
                    ]
 
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))
 
77
    if not ret:
 
78
        trace.note(gettext('Failed to GetProcessMemoryInfo()'))
102
79
        return
 
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,
 
91
            }
103
92
    if short:
104
93
        # using base-2 units (see HACKING.txt).
105
94
        trace.note(gettext('WorkingSize {0:>7}KiB'
130
119
    console window and return tuple (sizex, sizey) if success,
131
120
    or default size (defaultx, defaulty) otherwise.
132
121
    """
133
 
    if not has_ctypes_win32:
134
 
        # no ctypes is found
135
 
        return (defaultx, defaulty)
136
 
 
 
122
    import ctypes
137
123
    # To avoid problem with redirecting output via pipe
138
124
    # we need to use stderr instead of stdout
139
125
    h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
156
142
 
157
143
    Result is always unicode (or None).
158
144
    """
159
 
    if has_ctypes_win32:
160
 
        try:
161
 
            SHGetSpecialFolderPath = \
162
 
                ctypes.windll.shell32.SHGetSpecialFolderPathW
163
 
        except AttributeError:
164
 
            pass
165
 
        else:
166
 
            buf = ctypes.create_unicode_buffer(MAX_PATH)
167
 
            if SHGetSpecialFolderPath(None, buf, csidl, 0):
168
 
                return buf.value
169
 
    return None
 
145
    import ctypes
 
146
    try:
 
147
        SHGetSpecialFolderPath = \
 
148
            ctypes.windll.shell32.SHGetSpecialFolderPathW
 
149
    except AttributeError:
 
150
        pass
 
151
    else:
 
152
        buf = ctypes.create_unicode_buffer(MAX_PATH)
 
153
        if SHGetSpecialFolderPath(None, buf, csidl, 0):
 
154
            return buf.value
170
155
 
171
156
 
172
157
def get_appdata_location():
182
167
    if appdata:
183
168
        return appdata
184
169
    # Use APPDATA if defined, will return None if not
185
 
    return get_environ_unicode('APPDATA')
 
170
    return os.environ.get('APPDATA')
186
171
 
187
172
 
188
173
def get_local_appdata_location():
199
184
    if local:
200
185
        return local
201
186
    # Vista supplies LOCALAPPDATA, but XP and earlier do not.
202
 
    local = get_environ_unicode('LOCALAPPDATA')
 
187
    local = os.environ.get('LOCALAPPDATA')
203
188
    if local:
204
189
        return local
205
190
    return get_appdata_location()
214
199
    home = _get_sh_special_folder_path(CSIDL_PERSONAL)
215
200
    if home:
216
201
        return home
217
 
    home = get_environ_unicode('HOME')
 
202
    home = os.environ.get('HOME')
218
203
    if home is not None:
219
204
        return home
220
 
    homepath = get_environ_unicode('HOMEPATH')
 
205
    homepath = os.environ.get('HOMEPATH')
221
206
    if homepath is not None:
222
 
        return os.path.join(get_environ_unicode('HOMEDIR', ''), home)
 
207
        return os.path.join(os.environ.get('HOMEDIR', ''), home)
223
208
    # at least return windows root directory
224
 
    windir = get_environ_unicode('WINDIR')
 
209
    windir = os.environ.get('WINDIR')
225
210
    if windir:
226
211
        return os.path.splitdrive(windir)[0] + '/'
227
212
    # otherwise C:\ is good enough for 98% users
232
217
    """Return user name as login name.
233
218
    If name cannot be obtained return None.
234
219
    """
235
 
    if has_ctypes_win32:
236
 
        try:
237
 
            advapi32 = ctypes.windll.advapi32
238
 
            GetUserName = getattr(advapi32, 'GetUserNameW')
239
 
        except AttributeError:
240
 
            pass
241
 
        else:
242
 
            buf = ctypes.create_unicode_buffer(UNLEN + 1)
243
 
            n = ctypes.c_int(UNLEN + 1)
244
 
            if GetUserName(buf, ctypes.byref(n)):
245
 
                return buf.value
 
220
    try:
 
221
        advapi32 = ctypes.windll.advapi32
 
222
        GetUserName = getattr(advapi32, 'GetUserNameW')
 
223
    except AttributeError:
 
224
        pass
 
225
    else:
 
226
        buf = ctypes.create_unicode_buffer(UNLEN + 1)
 
227
        n = ctypes.c_int(UNLEN + 1)
 
228
        if GetUserName(buf, ctypes.byref(n)):
 
229
            return buf.value
246
230
    # otherwise try env variables
247
 
    return get_environ_unicode('USERNAME')
 
231
    return os.environ.get('USERNAME')
248
232
 
249
233
 
250
234
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
258
242
 
259
243
    :return: A unicode string representing the host name.
260
244
    """
261
 
    if has_ctypes_win32:
262
 
        try:
263
 
            kernel32 = ctypes.windll.kernel32
264
 
        except AttributeError:
265
 
            pass  # Missing the module we need
266
 
        else:
267
 
            buf = ctypes.create_unicode_buffer(MAX_COMPUTERNAME_LENGTH + 1)
268
 
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH + 1)
 
245
    import ctypes
 
246
    buf = ctypes.create_unicode_buffer(MAX_COMPUTERNAME_LENGTH + 1)
 
247
    n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH + 1)
269
248
 
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))):
275
 
                return buf.value
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))):
 
255
        return buf.value
 
256
    return os.environ.get('COMPUTERNAME')
277
257
 
278
258
 
279
259
def _ensure_with_dir(path):
363
343
 
364
344
    if type_id == REG_SZ:
365
345
        return path
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
370
 
        return fullpath
371
346
    return appname
372
347
 
373
348
 
374
349
def set_file_attr_hidden(path):
375
350
    """Set file attributes to hidden if possible"""
376
 
    if not has_ctypes_win32:
377
 
        return
378
 
    from ctypes.wintypes import BOOL, DWORD, LPCWSTR
379
 
    _kernel32 = ctypes.windll.kernel32
 
351
    from ctypes.wintypes import BOOL, DWORD, LPWSTR
 
352
    import ctypes
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()
429
403
    return args
430
404
 
431
405
 
432
 
if has_ctypes_win32:
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:]
442
 
        return argv
443
 
 
444
 
    def get_environ_unicode(key, default=None):
445
 
        """Get `key` from environment as unicode or `default` if unset
446
 
 
447
 
        The environment is natively unicode on modern windows versions but
448
 
        Python 2 only accesses it through the legacy bytestring api.
449
 
 
450
 
        Environmental variable names are case insenstive on Windows.
451
 
 
452
 
        A large enough buffer will be allocated to retrieve the value, though
453
 
        it may take two calls to the underlying library function.
454
 
        """
455
 
        cfunc = getattr(get_environ_unicode, "_c_function", None)
456
 
        if cfunc is 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
462
 
        while True:
463
 
            buf = ctypes.create_unicode_buffer(buffer_size)
464
 
            length = cfunc(key, buf, buffer_size)
465
 
            if not length:
466
 
                code = ctypes.GetLastError()
467
 
                if code == 203:  # ERROR_ENVVAR_NOT_FOUND
468
 
                    return default
469
 
                raise ctypes.WinError(code)
470
 
            if buffer_size > length:
471
 
                return buf[:length]
472
 
            buffer_size = length
473
 
 
474
 
 
475
 
if has_ctypes_win32:
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))
482
 
 
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
486
 
        if not handle:
487
 
            errorcode = ctypes.GetLastError()
488
 
            if errorcode == 5:  # ERROR_ACCESS_DENIED
489
 
                # Probably something alive we're not allowed to kill
490
 
                return False
491
 
            elif errorcode == 87:  # ERROR_INVALID_PARAMETER
492
 
                return True
493
 
            raise ctypes.WinError(errorcode)
494
 
        _CloseHandle(handle)
495
 
        return False
496
 
 
497
 
    is_local_pid_dead = _ctypes_is_local_pid_dead
 
406
def _ctypes_is_local_pid_dead(pid):
 
407
    import ctypes
 
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)
 
411
    if not handle:
 
412
        errorcode = ctypes.GetLastError()
 
413
        if errorcode == 5:  # ERROR_ACCESS_DENIED
 
414
            # Probably something alive we're not allowed to kill
 
415
            return False
 
416
        elif errorcode == 87:  # ERROR_INVALID_PARAMETER
 
417
            return True
 
418
        raise ctypes.WinError(errorcode)
 
419
    Kernel32.CloseHandle(handle)
 
420
    return False
 
421
 
 
422
is_local_pid_dead = _ctypes_is_local_pid_dead