~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/win32utils.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-16 19:18:39 UTC
  • mto: This revision was merged to the branch mainline in revision 6391.
  • Revision ID: jelmer@samba.org-20111216191839-eg681lxqibi1qxu1
Fix remaining tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
"""
21
21
 
22
22
import glob
 
23
import operator
23
24
import os
24
25
import struct
25
26
import sys
26
27
 
27
 
from bzrlib import cmdline
 
28
from bzrlib import (
 
29
    cmdline,
 
30
    symbol_versioning,
 
31
    )
 
32
from bzrlib.i18n import gettext
28
33
 
29
34
# Windows version
30
35
if sys.platform == 'win32':
62
67
else:
63
68
    if winver == 'Windows 98':
64
69
        create_buffer = ctypes.create_string_buffer
 
70
        def extract_buffer(buf):
 
71
            return buf.value.decode("mbcs")
65
72
        suffix = 'A'
66
73
    else:
67
74
        create_buffer = ctypes.create_unicode_buffer
 
75
        extract_buffer = operator.attrgetter("value")
68
76
        suffix = 'W'
69
77
try:
70
 
    import win32file
71
78
    import pywintypes
72
 
    has_win32file = True
73
 
except ImportError:
74
 
    has_win32file = False
75
 
try:
76
 
    import win32api
77
 
    has_win32api = True
78
 
except ImportError:
79
 
    has_win32api = False
 
79
    has_pywintypes = True
 
80
except ImportError:
 
81
    has_pywintypes = has_win32file = has_win32api = False
 
82
else:
 
83
    try:
 
84
        import win32file
 
85
        has_win32file = True
 
86
    except ImportError:
 
87
        has_win32file = False
 
88
    try:
 
89
        import win32api
 
90
        has_win32api = True
 
91
    except ImportError:
 
92
        has_win32api = False
80
93
 
81
94
# pulling in win32com.shell is a bit of overhead, and normally we don't need
82
95
# it as ctypes is preferred and common.  lazy_imports and "optional"
128
141
            ctypes.byref(mem_struct),
129
142
            ctypes.sizeof(mem_struct))
130
143
        if not ret:
131
 
            trace.note('Failed to GetProcessMemoryInfo()')
 
144
            trace.note(gettext('Failed to GetProcessMemoryInfo()'))
132
145
            return
133
146
        info = {'PageFaultCount': mem_struct.PageFaultCount,
134
147
                'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize,
149
162
        proc = win32process.GetCurrentProcess()
150
163
        info = win32process.GetProcessMemoryInfo(proc)
151
164
    else:
152
 
        trace.note('Cannot debug memory on win32 without ctypes'
153
 
                   ' or win32process')
 
165
        trace.note(gettext('Cannot debug memory on win32 without ctypes'
 
166
                   ' or win32process'))
154
167
        return
155
168
    if short:
156
169
        # using base-2 units (see HACKING.txt).
157
 
        trace.note('WorkingSize %7dKiB'
158
 
                   '\tPeakWorking %7dKiB\t%s',
 
170
        trace.note(gettext('WorkingSize {0:>7}KiB'
 
171
                   '\tPeakWorking {1:>7}KiB\t{2}').format(
159
172
                   info['WorkingSetSize'] / 1024,
160
173
                   info['PeakWorkingSetSize'] / 1024,
161
 
                   message)
 
174
                   message))
162
175
        return
163
176
    if message:
164
177
        trace.note('%s', message)
165
 
    trace.note('WorkingSize       %8d KiB', info['WorkingSetSize'] / 1024)
166
 
    trace.note('PeakWorking       %8d KiB', info['PeakWorkingSetSize'] / 1024)
167
 
    trace.note('PagefileUsage     %8d KiB', info.get('PagefileUsage', 0) / 1024)
168
 
    trace.note('PeakPagefileUsage %8d KiB',
 
178
    trace.note(gettext('WorkingSize       %8d KiB'), info['WorkingSetSize'] / 1024)
 
179
    trace.note(gettext('PeakWorking       %8d KiB'), info['PeakWorkingSetSize'] / 1024)
 
180
    trace.note(gettext('PagefileUsage     %8d KiB'), info.get('PagefileUsage', 0) / 1024)
 
181
    trace.note(gettext('PeakPagefileUsage %8d KiB'),
169
182
               info.get('PeakPagefileUsage', 0) / 1024)
170
 
    trace.note('PrivateUsage      %8d KiB', info.get('PrivateUsage', 0) / 1024)
171
 
    trace.note('PageFaultCount    %8d', info.get('PageFaultCount', 0))
 
183
    trace.note(gettext('PrivateUsage      %8d KiB'), info.get('PrivateUsage', 0) / 1024)
 
184
    trace.note(gettext('PageFaultCount    %8d'), info.get('PageFaultCount', 0))
172
185
 
173
186
 
174
187
def get_console_size(defaultx=80, defaulty=25):
242
255
    one that moves with the user as they logon to different machines, and
243
256
    a 'local' one that stays local to the machine.  This returns the 'roaming'
244
257
    directory, and thus is suitable for storing user-preferences, etc.
245
 
 
246
 
    Returned value can be unicode or plain string.
247
 
    To convert plain string to unicode use
248
 
    s.decode(osutils.get_user_encoding())
249
 
    (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
250
258
    """
251
259
    appdata = _get_sh_special_folder_path(CSIDL_APPDATA)
252
260
    if appdata:
253
261
        return appdata
254
 
    # from env variable
255
 
    appdata = os.environ.get('APPDATA')
256
 
    if appdata:
257
 
        return appdata
258
 
    # if we fall to this point we on win98
259
 
    # at least try C:/WINDOWS/Application Data
260
 
    windir = os.environ.get('windir')
261
 
    if windir:
262
 
        appdata = os.path.join(windir, 'Application Data')
263
 
        if os.path.isdir(appdata):
264
 
            return appdata
265
 
    # did not find anything
266
 
    return None
 
262
    # Use APPDATA if defined, will return None if not
 
263
    return get_environ_unicode('APPDATA')
267
264
 
268
265
 
269
266
def get_local_appdata_location():
275
272
    a 'local' one that stays local to the machine.  This returns the 'local'
276
273
    directory, and thus is suitable for caches, temp files and other things
277
274
    which don't need to move with the user.
278
 
 
279
 
    Returned value can be unicode or plain string.
280
 
    To convert plain string to unicode use
281
 
    s.decode(osutils.get_user_encoding())
282
 
    (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
283
275
    """
284
276
    local = _get_sh_special_folder_path(CSIDL_LOCAL_APPDATA)
285
277
    if local:
286
278
        return local
287
279
    # Vista supplies LOCALAPPDATA, but XP and earlier do not.
288
 
    local = os.environ.get('LOCALAPPDATA')
 
280
    local = get_environ_unicode('LOCALAPPDATA')
289
281
    if local:
290
282
        return local
291
283
    return get_appdata_location()
296
288
    Assume on win32 it's the <My Documents> folder.
297
289
    If location cannot be obtained return system drive root,
298
290
    i.e. C:\
299
 
 
300
 
    Returned value can be unicode or plain string.
301
 
    To convert plain string to unicode use
302
 
    s.decode(osutils.get_user_encoding())
303
291
    """
304
292
    home = _get_sh_special_folder_path(CSIDL_PERSONAL)
305
293
    if home:
306
294
        return home
307
 
    # try for HOME env variable
308
 
    home = os.path.expanduser('~')
309
 
    if home != '~':
 
295
    home = get_environ_unicode('HOME')
 
296
    if home is not None:
310
297
        return home
 
298
    homepath = get_environ_unicode('HOMEPATH')
 
299
    if homepath is not None:
 
300
        return os.path.join(get_environ_unicode('HOMEDIR', ''), home)
311
301
    # at least return windows root directory
312
 
    windir = os.environ.get('windir')
 
302
    windir = get_environ_unicode('WINDIR')
313
303
    if windir:
314
304
        return os.path.splitdrive(windir)[0] + '/'
315
305
    # otherwise C:\ is good enough for 98% users
316
 
    return 'C:/'
 
306
    return unicode('C:/')
317
307
 
318
308
 
319
309
def get_user_name():
320
310
    """Return user name as login name.
321
311
    If name cannot be obtained return None.
322
 
 
323
 
    Returned value can be unicode or plain string.
324
 
    To convert plain string to unicode use
325
 
    s.decode(osutils.get_user_encoding())
326
312
    """
327
313
    if has_ctypes:
328
314
        try:
334
320
            buf = create_buffer(UNLEN+1)
335
321
            n = ctypes.c_int(UNLEN+1)
336
322
            if GetUserName(buf, ctypes.byref(n)):
337
 
                return buf.value
 
323
                return extract_buffer(buf)
338
324
    # otherwise try env variables
339
 
    return os.environ.get('USERNAME', None)
 
325
    return get_environ_unicode('USERNAME')
340
326
 
341
327
 
342
328
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
347
333
    """Return host machine name.
348
334
    If name cannot be obtained return None.
349
335
 
350
 
    :return: A unicode string representing the host name. On win98, this may be
351
 
        a plain string as win32 api doesn't support unicode.
 
336
    :return: A unicode string representing the host name.
352
337
    """
353
338
    if has_win32api:
354
339
        try:
371
356
            if (GetComputerNameEx is not None
372
357
                and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
373
358
                                      buf, ctypes.byref(n))):
374
 
                return buf.value
 
359
                return extract_buffer(buf)
375
360
 
376
361
            # Try GetComputerName in case GetComputerNameEx wasn't found
377
362
            # It returns the NETBIOS name, which isn't as good, but still ok.
381
366
                                      None)
382
367
            if (GetComputerName is not None
383
368
                and GetComputerName(buf, ctypes.byref(n))):
384
 
                return buf.value
385
 
    # otherwise try env variables, which will be 'mbcs' encoded
386
 
    # on Windows (Python doesn't expose the native win32 unicode environment)
387
 
    # According to this:
388
 
    # http://msdn.microsoft.com/en-us/library/aa246807.aspx
389
 
    # environment variables should always be encoded in 'mbcs'.
390
 
    try:
391
 
        return os.environ['COMPUTERNAME'].decode("mbcs")
392
 
    except KeyError:
393
 
        return None
394
 
 
395
 
 
 
369
                return extract_buffer(buf)
 
370
    return get_environ_unicode('COMPUTERNAME')
 
371
 
 
372
 
 
373
@symbol_versioning.deprecated_method(
 
374
    symbol_versioning.deprecated_in((2, 5, 0)))
396
375
def _ensure_unicode(s):
397
376
    if s and type(s) != unicode:
398
377
        from bzrlib import osutils
400
379
    return s
401
380
 
402
381
 
403
 
def get_appdata_location_unicode():
404
 
    return _ensure_unicode(get_appdata_location())
405
 
 
406
 
def get_home_location_unicode():
407
 
    return _ensure_unicode(get_home_location())
408
 
 
409
 
def get_user_name_unicode():
410
 
    return _ensure_unicode(get_user_name())
411
 
 
412
 
def get_host_name_unicode():
413
 
    return _ensure_unicode(get_host_name())
 
382
get_appdata_location_unicode = symbol_versioning.deprecated_method(
 
383
    symbol_versioning.deprecated_in((2, 5, 0)))(get_appdata_location)
 
384
 
 
385
get_home_location_unicode = symbol_versioning.deprecated_method(
 
386
    symbol_versioning.deprecated_in((2, 5, 0)))(get_home_location)
 
387
 
 
388
get_user_name_unicode = symbol_versioning.deprecated_method(
 
389
    symbol_versioning.deprecated_in((2, 5, 0)))(get_user_name)
 
390
 
 
391
get_host_name_unicode = symbol_versioning.deprecated_method(
 
392
    symbol_versioning.deprecated_in((2, 5, 0)))(get_host_name)
414
393
 
415
394
 
416
395
def _ensure_with_dir(path):
427
406
        return path
428
407
 
429
408
 
430
 
 
431
409
def glob_one(possible_glob):
432
410
    """Same as glob.glob().
433
411
 
468
446
 
469
447
 
470
448
def get_app_path(appname):
471
 
    """Look up in Windows registry for full path to application executable.
 
449
    r"""Look up in Windows registry for full path to application executable.
472
450
    Typically, applications create subkey with their basename
473
451
    in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
474
452
 
563
541
    return args
564
542
 
565
543
 
566
 
if has_ctypes and winver != 'Windows 98':
 
544
if has_ctypes and winver == 'Windows NT':
567
545
    def get_unicode_argv():
568
546
        prototype = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
569
547
        GetCommandLineW = prototype(("GetCommandLineW",
574
552
        # Skip the first argument, since we only care about parameters
575
553
        argv = _command_line_to_argv(command_line, sys.argv)[1:]
576
554
        return argv
 
555
    
 
556
 
 
557
    def get_environ_unicode(key, default=None):
 
558
        """Get `key` from environment as unicode or `default` if unset
 
559
 
 
560
        The environment is natively unicode on modern windows versions but
 
561
        Python 2 only accesses it through the legacy bytestring api.
 
562
 
 
563
        Environmental variable names are case insenstive on Windows.
 
564
 
 
565
        A large enough buffer will be allocated to retrieve the value, though
 
566
        it may take two calls to the underlying library function.
 
567
 
 
568
        This needs ctypes because pywin32 does not expose the wide version.
 
569
        """
 
570
        cfunc = getattr(get_environ_unicode, "_c_function", None)
 
571
        if cfunc is None:
 
572
            from ctypes.wintypes import DWORD, LPCWSTR, LPWSTR
 
573
            cfunc = ctypes.WINFUNCTYPE(DWORD, LPCWSTR, LPWSTR, DWORD)(
 
574
                ("GetEnvironmentVariableW", ctypes.windll.kernel32))
 
575
            get_environ_unicode._c_function = cfunc
 
576
        buffer_size = 256 # heuristic, 256 characters often enough
 
577
        while True:
 
578
            buffer = ctypes.create_unicode_buffer(buffer_size)
 
579
            length = cfunc(key, buffer, buffer_size)
 
580
            if not length:
 
581
                code = ctypes.GetLastError()
 
582
                if code == 203: # ERROR_ENVVAR_NOT_FOUND
 
583
                    return default
 
584
                raise ctypes.WinError(code)
 
585
            if buffer_size > length:
 
586
                return buffer[:length]
 
587
            buffer_size = length
577
588
else:
578
589
    get_unicode_argv = None
 
590
    def get_environ_unicode(key, default=None):
 
591
        """Get `key` from environment as unicode or `default` if unset
 
592
 
 
593
        Fallback version that should basically never be needed.
 
594
        """
 
595
        try:
 
596
            return os.environ[key].decode("mbcs")
 
597
        except KeyError:
 
598
            return default
 
599
 
 
600
 
 
601
if has_win32api:
 
602
    def _pywin32_is_local_pid_dead(pid):
 
603
        """True if pid doesn't correspond to live process on this machine"""
 
604
        try:
 
605
            handle = win32api.OpenProcess(1, False, pid) # PROCESS_TERMINATE
 
606
        except pywintypes.error, e:
 
607
            if e[0] == 5: # ERROR_ACCESS_DENIED
 
608
                # Probably something alive we're not allowed to kill
 
609
                return False
 
610
            elif e[0] == 87: # ERROR_INVALID_PARAMETER
 
611
                return True
 
612
            raise
 
613
        handle.close()
 
614
        return False
 
615
    is_local_pid_dead = _pywin32_is_local_pid_dead
 
616
elif has_ctypes and sys.platform == 'win32':
 
617
    from ctypes.wintypes import BOOL, DWORD, HANDLE
 
618
    _kernel32 = ctypes.windll.kernel32
 
619
    _CloseHandle = ctypes.WINFUNCTYPE(BOOL, HANDLE)(
 
620
        ("CloseHandle", _kernel32))
 
621
    _OpenProcess = ctypes.WINFUNCTYPE(HANDLE, DWORD, BOOL, DWORD)(
 
622
        ("OpenProcess", _kernel32))
 
623
    def _ctypes_is_local_pid_dead(pid):
 
624
        """True if pid doesn't correspond to live process on this machine"""
 
625
        handle = _OpenProcess(1, False, pid) # PROCESS_TERMINATE
 
626
        if not handle:
 
627
            errorcode = ctypes.GetLastError()
 
628
            if errorcode == 5: # ERROR_ACCESS_DENIED
 
629
                # Probably something alive we're not allowed to kill
 
630
                return False
 
631
            elif errorcode == 87: # ERROR_INVALID_PARAMETER
 
632
                return True
 
633
            raise ctypes.WinError(errorcode)
 
634
        _CloseHandle(handle)
 
635
        return False
 
636
    is_local_pid_dead = _ctypes_is_local_pid_dead
 
637
 
 
638
 
 
639
def _is_pywintypes_error(evalue):
 
640
    """True if exception instance is an error from pywin32"""
 
641
    if has_pywintypes and isinstance(evalue, pywintypes.error):
 
642
        return True
 
643
    return False