~bzr-pqm/bzr/bzr.dev

4988.10.3 by John Arbash Meinel
Merge bzr.dev 5007, resolve conflict, update NEWS
1
# Copyright (C) 2005-2010 Canonical Ltd
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
2
#
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
16
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
17
"""Win32-specific helper functions
18
19
Only one dependency: ctypes should be installed.
20
"""
21
4786.1.1 by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows.
22
import glob
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
23
import os
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
24
import struct
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
25
import sys
26
4913.5.19 by Gordon Tyler
Moved UnicodeShlex, etc. to a new module, bzrlib.cmdline, and renamed it to Parser.
27
from bzrlib import cmdline
6138.3.4 by Jonathan Riddell
add gettext() to uses of trace.note()
28
from bzrlib.i18n import gettext
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
29
30
# Windows version
31
if sys.platform == 'win32':
32
    _major,_minor,_build,_platform,_text = sys.getwindowsversion()
2245.4.11 by Alexander Belchenko
Small fixes after John's review; added NEWS entry
33
    # from MSDN:
34
    # dwPlatformId
35
    #   The operating system platform.
36
    #   This member can be one of the following values.
37
    #   ==========================  ======================================
38
    #   Value                       Meaning
39
    #   --------------------------  --------------------------------------
40
    #   VER_PLATFORM_WIN32_NT       The operating system is Windows Vista,
41
    #   2                           Windows Server "Longhorn",
42
    #                               Windows Server 2003, Windows XP,
43
    #                               Windows 2000, or Windows NT.
44
    #
45
    #   VER_PLATFORM_WIN32_WINDOWS  The operating system is Windows Me,
46
    #   1                           Windows 98, or Windows 95.
47
    #   ==========================  ======================================
48
    if _platform == 2:
49
        winver = 'Windows NT'
50
    else:
51
        # don't care about real Windows name, just to force safe operations
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
52
        winver = 'Windows 98'
53
else:
54
    winver = None
55
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
56
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
57
# We can cope without it; use a separate variable to help pyflakes
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
58
try:
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
59
    import ctypes
60
    has_ctypes = True
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
61
except ImportError:
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
62
    has_ctypes = False
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
63
else:
64
    if winver == 'Windows 98':
65
        create_buffer = ctypes.create_string_buffer
66
        suffix = 'A'
67
    else:
68
        create_buffer = ctypes.create_unicode_buffer
69
        suffix = 'W'
3023.1.2 by Alexander Belchenko
Martin's review.
70
try:
4505.2.1 by Alexander Belchenko
Set hidden attribute on .bzr directory below unicode path should never fail with error. The operation should succeed even if bzr unable to set the attribute. (related to bug #335362).
71
    import pywintypes
6336.2.2 by Martin Packman
Tweak how pywin32 is imported in win32utils to fix test failure edge case
72
    has_pywintypes = True
73
except ImportError:
6336.2.3 by Martin Packman
Set all has_win32* to False if pywintypes can't be imported
74
    has_pywintypes = has_win32file = has_win32api = False
6336.2.2 by Martin Packman
Tweak how pywin32 is imported in win32utils to fix test failure edge case
75
else:
76
    try:
77
        import win32file
78
        has_win32file = True
79
    except ImportError:
80
        has_win32file = False
81
    try:
82
        import win32api
83
        has_win32api = True
84
    except ImportError:
85
        has_win32api = False
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
86
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
87
# pulling in win32com.shell is a bit of overhead, and normally we don't need
88
# it as ctypes is preferred and common.  lazy_imports and "optional"
89
# modules don't work well, so we do our own lazy thing...
90
has_win32com_shell = None # Set to True or False once we know for sure...
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
91
92
# Special Win32 API constants
93
# Handles of std streams
1704.2.3 by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander)
94
WIN32_STDIN_HANDLE = -10
95
WIN32_STDOUT_HANDLE = -11
96
WIN32_STDERR_HANDLE = -12
97
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
98
# CSIDL constants (from MSDN 2003)
99
CSIDL_APPDATA = 0x001A      # Application Data folder
3638.4.10 by Aaron Bentley
Correct spelling of 'Application Data'
100
CSIDL_LOCAL_APPDATA = 0x001c# <user name>\Local Settings\Application Data (non roaming)
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
101
CSIDL_PERSONAL = 0x0005     # My Documents folder
102
103
# from winapi C headers
104
MAX_PATH = 260
105
UNLEN = 256
106
MAX_COMPUTERNAME_LENGTH = 31
107
4476.2.1 by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ).
108
# Registry data type ids
109
REG_SZ = 1
110
REG_EXPAND_SZ = 2
111
1704.2.3 by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander)
112
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
113
def debug_memory_win32api(message='', short=True):
114
    """Use trace.note() to dump the running memory info."""
115
    from bzrlib import trace
4011.1.2 by John Arbash Meinel
Fix some small bugs, and prefer the ctypes form.
116
    if has_ctypes:
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
117
        class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
118
            """Used by GetProcessMemoryInfo"""
119
            _fields_ = [('cb', ctypes.c_ulong),
120
                        ('PageFaultCount', ctypes.c_ulong),
121
                        ('PeakWorkingSetSize', ctypes.c_size_t),
122
                        ('WorkingSetSize', ctypes.c_size_t),
123
                        ('QuotaPeakPagedPoolUsage', ctypes.c_size_t),
124
                        ('QuotaPagedPoolUsage', ctypes.c_size_t),
125
                        ('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t),
126
                        ('QuotaNonPagedPoolUsage', ctypes.c_size_t),
127
                        ('PagefileUsage', ctypes.c_size_t),
128
                        ('PeakPagefileUsage', ctypes.c_size_t),
129
                        ('PrivateUsage', ctypes.c_size_t),
130
                       ]
131
        cur_process = ctypes.windll.kernel32.GetCurrentProcess()
132
        mem_struct = PROCESS_MEMORY_COUNTERS_EX()
133
        ret = ctypes.windll.psapi.GetProcessMemoryInfo(cur_process,
134
            ctypes.byref(mem_struct),
135
            ctypes.sizeof(mem_struct))
136
        if not ret:
6138.3.4 by Jonathan Riddell
add gettext() to uses of trace.note()
137
            trace.note(gettext('Failed to GetProcessMemoryInfo()'))
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
138
            return
139
        info = {'PageFaultCount': mem_struct.PageFaultCount,
140
                'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize,
141
                'WorkingSetSize': mem_struct.WorkingSetSize,
142
                'QuotaPeakPagedPoolUsage': mem_struct.QuotaPeakPagedPoolUsage,
143
                'QuotaPagedPoolUsage': mem_struct.QuotaPagedPoolUsage,
4989.1.6 by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used.
144
                'QuotaPeakNonPagedPoolUsage':
145
                    mem_struct.QuotaPeakNonPagedPoolUsage,
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
146
                'QuotaNonPagedPoolUsage': mem_struct.QuotaNonPagedPoolUsage,
147
                'PagefileUsage': mem_struct.PagefileUsage,
148
                'PeakPagefileUsage': mem_struct.PeakPagefileUsage,
149
                'PrivateUsage': mem_struct.PrivateUsage,
150
               }
4011.1.2 by John Arbash Meinel
Fix some small bugs, and prefer the ctypes form.
151
    elif has_win32api:
152
        import win32process
153
        # win32process does not return PrivateUsage, because it doesn't use
154
        # PROCESS_MEMORY_COUNTERS_EX (it uses the one without _EX).
155
        proc = win32process.GetCurrentProcess()
156
        info = win32process.GetProcessMemoryInfo(proc)
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
157
    else:
6138.3.4 by Jonathan Riddell
add gettext() to uses of trace.note()
158
        trace.note(gettext('Cannot debug memory on win32 without ctypes'
159
                   ' or win32process'))
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
160
        return
4163.1.1 by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code.
161
    if short:
4989.1.6 by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used.
162
        # using base-2 units (see HACKING.txt).
6147.1.1 by Jonathan Riddell
use .format() instead of % for string formatting where there are multiple formats in one string to allow for translations
163
        trace.note(gettext('WorkingSize {0:>7}KiB'
164
                   '\tPeakWorking {1:>7}KiB\t{2}').format(
4163.1.1 by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code.
165
                   info['WorkingSetSize'] / 1024,
166
                   info['PeakWorkingSetSize'] / 1024,
6147.1.1 by Jonathan Riddell
use .format() instead of % for string formatting where there are multiple formats in one string to allow for translations
167
                   message))
4163.1.1 by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code.
168
        return
169
    if message:
170
        trace.note('%s', message)
6138.3.4 by Jonathan Riddell
add gettext() to uses of trace.note()
171
    trace.note(gettext('WorkingSize       %8d KiB'), info['WorkingSetSize'] / 1024)
172
    trace.note(gettext('PeakWorking       %8d KiB'), info['PeakWorkingSetSize'] / 1024)
173
    trace.note(gettext('PagefileUsage     %8d KiB'), info.get('PagefileUsage', 0) / 1024)
174
    trace.note(gettext('PeakPagefileUsage %8d KiB'),
4989.1.6 by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used.
175
               info.get('PeakPagefileUsage', 0) / 1024)
6138.3.4 by Jonathan Riddell
add gettext() to uses of trace.note()
176
    trace.note(gettext('PrivateUsage      %8d KiB'), info.get('PrivateUsage', 0) / 1024)
177
    trace.note(gettext('PageFaultCount    %8d'), info.get('PageFaultCount', 0))
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
178
179
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
180
def get_console_size(defaultx=80, defaulty=25):
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
181
    """Return size of current console.
182
183
    This function try to determine actual size of current working
184
    console window and return tuple (sizex, sizey) if success,
185
    or default size (defaultx, defaulty) otherwise.
186
    """
187
    if not has_ctypes:
188
        # no ctypes is found
189
        return (defaultx, defaulty)
190
191
    # To avoid problem with redirecting output via pipe
4747.3.6 by Vincent Ladeuil
terminal_width can now returns None.
192
    # we need to use stderr instead of stdout
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
193
    h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
194
    csbi = ctypes.create_string_buffer(22)
195
    res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
196
197
    if res:
198
        (bufx, bufy, curx, cury, wattr,
4989.1.6 by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used.
199
        left, top, right, bottom, maxx, maxy) = struct.unpack(
200
            "hhhhHhhhhhh", csbi.raw)
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
201
        sizex = right - left + 1
202
        sizey = bottom - top + 1
203
        return (sizex, sizey)
204
    else:
205
        return (defaultx, defaulty)
206
207
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
208
def _get_sh_special_folder_path(csidl):
209
    """Call SHGetSpecialFolderPathW if available, or return None.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
210
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
211
    Result is always unicode (or None).
212
    """
213
    if has_ctypes:
214
        try:
215
            SHGetSpecialFolderPath = \
216
                ctypes.windll.shell32.SHGetSpecialFolderPathW
217
        except AttributeError:
218
            pass
219
        else:
220
            buf = ctypes.create_unicode_buffer(MAX_PATH)
221
            if SHGetSpecialFolderPath(None,buf,csidl,0):
222
                return buf.value
223
224
    global has_win32com_shell
225
    if has_win32com_shell is None:
226
        try:
227
            from win32com.shell import shell
228
            has_win32com_shell = True
229
        except ImportError:
230
            has_win32com_shell = False
231
    if has_win32com_shell:
232
        # still need to bind the name locally, but this is fast.
233
        from win32com.shell import shell
234
        try:
235
            return shell.SHGetSpecialFolderPath(0, csidl, 0)
236
        except shell.error:
237
            # possibly E_NOTIMPL meaning we can't load the function pointer,
238
            # or E_FAIL meaning the function failed - regardless, just ignore it
239
            pass
240
    return None
241
242
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
243
def get_appdata_location():
244
    """Return Application Data location.
245
    Return None if we cannot obtain location.
246
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
247
    Windows defines two 'Application Data' folders per user - a 'roaming'
248
    one that moves with the user as they logon to different machines, and
249
    a 'local' one that stays local to the machine.  This returns the 'roaming'
250
    directory, and thus is suitable for storing user-preferences, etc.
251
252
    Returned value can be unicode or plain string.
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
253
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
254
    s.decode(osutils.get_user_encoding())
3638.4.2 by Mark Hammond
Add a reference to bug 262874 noting 'mbcs' may be the correct encoding.
255
    (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
256
    """
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
257
    appdata = _get_sh_special_folder_path(CSIDL_APPDATA)
258
    if appdata:
259
        return appdata
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
260
    # from env variable
261
    appdata = os.environ.get('APPDATA')
262
    if appdata:
263
        return appdata
264
    # if we fall to this point we on win98
265
    # at least try C:/WINDOWS/Application Data
266
    windir = os.environ.get('windir')
267
    if windir:
268
        appdata = os.path.join(windir, 'Application Data')
269
        if os.path.isdir(appdata):
270
            return appdata
271
    # did not find anything
272
    return None
273
274
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
275
def get_local_appdata_location():
276
    """Return Local Application Data location.
277
    Return the same as get_appdata_location() if we cannot obtain location.
278
279
    Windows defines two 'Application Data' folders per user - a 'roaming'
280
    one that moves with the user as they logon to different machines, and
281
    a 'local' one that stays local to the machine.  This returns the 'local'
282
    directory, and thus is suitable for caches, temp files and other things
283
    which don't need to move with the user.
284
285
    Returned value can be unicode or plain string.
286
    To convert plain string to unicode use
4385.4.1 by Alexander Belchenko
removed all references to bzrlib.user_encoding
287
    s.decode(osutils.get_user_encoding())
3638.4.2 by Mark Hammond
Add a reference to bug 262874 noting 'mbcs' may be the correct encoding.
288
    (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
289
    """
290
    local = _get_sh_special_folder_path(CSIDL_LOCAL_APPDATA)
291
    if local:
292
        return local
293
    # Vista supplies LOCALAPPDATA, but XP and earlier do not.
294
    local = os.environ.get('LOCALAPPDATA')
295
    if local:
296
        return local
297
    return get_appdata_location()
298
299
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
300
def get_home_location():
301
    """Return user's home location.
302
    Assume on win32 it's the <My Documents> folder.
303
    If location cannot be obtained return system drive root,
304
    i.e. C:\
305
4031.3.1 by Frank Aspell
Fixing various typos
306
    Returned value can be unicode or plain string.
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
307
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
308
    s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
309
    """
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
310
    home = _get_sh_special_folder_path(CSIDL_PERSONAL)
311
    if home:
312
        return home
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
313
    # try for HOME env variable
314
    home = os.path.expanduser('~')
315
    if home != '~':
316
        return home
317
    # at least return windows root directory
318
    windir = os.environ.get('windir')
319
    if windir:
2610.1.1 by Martin Pool
Fix get_home_location on Win98 (gzlist,r=john,r=alexander)
320
        return os.path.splitdrive(windir)[0] + '/'
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
321
    # otherwise C:\ is good enough for 98% users
322
    return 'C:/'
323
324
325
def get_user_name():
326
    """Return user name as login name.
327
    If name cannot be obtained return None.
328
4031.3.1 by Frank Aspell
Fixing various typos
329
    Returned value can be unicode or plain string.
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
330
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
331
    s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
332
    """
333
    if has_ctypes:
334
        try:
335
            advapi32 = ctypes.windll.advapi32
336
            GetUserName = getattr(advapi32, 'GetUserName'+suffix)
337
        except AttributeError:
338
            pass
339
        else:
340
            buf = create_buffer(UNLEN+1)
341
            n = ctypes.c_int(UNLEN+1)
342
            if GetUserName(buf, ctypes.byref(n)):
343
                return buf.value
344
    # otherwise try env variables
345
    return os.environ.get('USERNAME', None)
346
347
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
348
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
349
# computer or the cluster associated with the local computer."
350
_WIN32_ComputerNameDnsHostname = 1
351
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
352
def get_host_name():
353
    """Return host machine name.
354
    If name cannot be obtained return None.
355
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
356
    :return: A unicode string representing the host name. On win98, this may be
357
        a plain string as win32 api doesn't support unicode.
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
358
    """
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
359
    if has_win32api:
360
        try:
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
361
            return win32api.GetComputerNameEx(_WIN32_ComputerNameDnsHostname)
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
362
        except (NotImplementedError, win32api.error):
363
            # NotImplemented will happen on win9x...
364
            pass
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
365
    if has_ctypes:
366
        try:
367
            kernel32 = ctypes.windll.kernel32
368
        except AttributeError:
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
369
            pass # Missing the module we need
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
370
        else:
371
            buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
372
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
373
374
            # Try GetComputerNameEx which gives a proper Unicode hostname
375
            GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx'+suffix,
376
                                        None)
377
            if (GetComputerNameEx is not None
378
                and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
379
                                      buf, ctypes.byref(n))):
380
                return buf.value
381
382
            # Try GetComputerName in case GetComputerNameEx wasn't found
383
            # It returns the NETBIOS name, which isn't as good, but still ok.
384
            # The first GetComputerNameEx might have changed 'n', so reset it
385
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
386
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix,
387
                                      None)
388
            if (GetComputerName is not None
389
                and GetComputerName(buf, ctypes.byref(n))):
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
390
                return buf.value
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
391
    # otherwise try env variables, which will be 'mbcs' encoded
392
    # on Windows (Python doesn't expose the native win32 unicode environment)
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
393
    # According to this:
394
    # http://msdn.microsoft.com/en-us/library/aa246807.aspx
395
    # environment variables should always be encoded in 'mbcs'.
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
396
    try:
397
        return os.environ['COMPUTERNAME'].decode("mbcs")
398
    except KeyError:
399
        return None
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
400
401
402
def _ensure_unicode(s):
403
    if s and type(s) != unicode:
3788.1.1 by John Arbash Meinel
Fix a missing import
404
        from bzrlib import osutils
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
405
        s = s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
406
    return s
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
407
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
408
409
def get_appdata_location_unicode():
410
    return _ensure_unicode(get_appdata_location())
411
412
def get_home_location_unicode():
413
    return _ensure_unicode(get_home_location())
414
415
def get_user_name_unicode():
416
    return _ensure_unicode(get_user_name())
417
418
def get_host_name_unicode():
419
    return _ensure_unicode(get_host_name())
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
420
421
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
422
def _ensure_with_dir(path):
4989.1.6 by Vincent Ladeuil
Add comments and update HACKING.txt about which units should be used.
423
    if (not os.path.split(path)[0] or path.startswith(u'*')
424
        or path.startswith(u'?')):
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
425
        return u'./' + path, True
426
    else:
427
        return path, False
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
428
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
429
def _undo_ensure_with_dir(path, corrected):
430
    if corrected:
431
        return path[2:]
432
    else:
433
        return path
434
435
436
4786.1.2 by John Arbash Meinel
Refactor the glob_expand code a bit, making the inner function more reusable.
437
def glob_one(possible_glob):
438
    """Same as glob.glob().
439
440
    work around bugs in glob.glob()
441
    - Python bug #1001604 ("glob doesn't return unicode with ...")
442
    - failing expansion for */* with non-iso-8859-* chars
443
    """
444
    corrected_glob, corrected = _ensure_with_dir(possible_glob)
445
    glob_files = glob.glob(corrected_glob)
446
447
    if not glob_files:
448
        # special case to let the normal code path handle
449
        # files that do not exist, etc.
450
        glob_files = [possible_glob]
451
    elif corrected:
452
        glob_files = [_undo_ensure_with_dir(elem, corrected)
453
                      for elem in glob_files]
454
    return [elem.replace(u'\\', u'/') for elem in glob_files]
455
456
2598.3.1 by Kuno Meyer
fix method rename glob_expand_for_win32 -> win32utils.glob_expand
457
def glob_expand(file_list):
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
458
    """Replacement for glob expansion by the shell.
459
460
    Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
461
    here.
462
463
    :param file_list: A list of filenames which may include shell globs.
464
    :return: An expanded list of filenames.
465
466
    Introduced in bzrlib 0.18.
467
    """
468
    if not file_list:
469
        return []
470
    expanded_file_list = []
471
    for possible_glob in file_list:
4786.1.2 by John Arbash Meinel
Refactor the glob_expand code a bit, making the inner function more reusable.
472
        expanded_file_list.extend(glob_one(possible_glob))
473
    return expanded_file_list
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
474
475
476
def get_app_path(appname):
5891.1.2 by Andrew Bennetts
Fix a bunch of docstring formatting nits, making pydoctor a bit happier.
477
    r"""Look up in Windows registry for full path to application executable.
4031.3.1 by Frank Aspell
Fixing various typos
478
    Typically, applications create subkey with their basename
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
479
    in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
480
481
    :param  appname:    name of application (if no filename extension
482
                        is specified, .exe used)
483
    :return:    full path to aplication executable from registry,
484
                or appname itself if nothing found.
485
    """
2681.4.3 by Alexander Belchenko
move import _winreg into function get_app_path to avoid ImportError on non-win32 platforms
486
    import _winreg
4476.2.1 by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ).
487
488
    basename = appname
489
    if not os.path.splitext(basename)[1]:
490
        basename = appname + '.exe'
491
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
492
    try:
493
        hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
4476.2.1 by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ).
494
            'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\' +
495
            basename)
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
496
    except EnvironmentError:
497
        return appname
498
499
    try:
500
        try:
4476.2.1 by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ).
501
            path, type_id = _winreg.QueryValueEx(hkey, '')
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
502
        except WindowsError:
4476.2.1 by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ).
503
            return appname
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
504
    finally:
505
        _winreg.CloseKey(hkey)
506
4476.2.1 by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ).
507
    if type_id == REG_SZ:
508
        return path
509
    if type_id == REG_EXPAND_SZ and has_win32api:
510
        fullpath = win32api.ExpandEnvironmentStrings(path)
4476.2.2 by Alexander Belchenko
remove quotes around value only if there is pair of quotes (igc review)
511
        if len(fullpath) > 1 and fullpath[0] == '"' and fullpath[-1] == '"':
4476.2.1 by Alexander Belchenko
win32utils.py: get_app_path() can read path for wordpad.exe (data type_id is REG_EXPAND_SZ).
512
            fullpath = fullpath[1:-1]   # remove quotes around value
513
        return fullpath
514
    return appname
3023.1.2 by Alexander Belchenko
Martin's review.
515
516
517
def set_file_attr_hidden(path):
518
    """Set file attributes to hidden if possible"""
519
    if has_win32file:
4505.2.1 by Alexander Belchenko
Set hidden attribute on .bzr directory below unicode path should never fail with error. The operation should succeed even if bzr unable to set the attribute. (related to bug #335362).
520
        if winver != 'Windows 98':
521
            SetFileAttributes = win32file.SetFileAttributesW
522
        else:
523
            SetFileAttributes = win32file.SetFileAttributes
524
        try:
525
            SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)
526
        except pywintypes.error, e:
4505.2.2 by Alexander Belchenko
forgotten import
527
            from bzrlib import trace
4505.2.1 by Alexander Belchenko
Set hidden attribute on .bzr directory below unicode path should never fail with error. The operation should succeed even if bzr unable to set the attribute. (related to bug #335362).
528
            trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
4355.2.1 by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments.
529
530
5274.4.12 by Martin
Change interface of _command_line_to_argv so old tests can still be used with new stripping logic
531
def _command_line_to_argv(command_line, argv, single_quotes_allowed=False):
4913.5.2 by Gordon Tyler
Changed shlex_split_unicode to prevent wildcard expansion in the win32 codepath.
532
    """Convert a Unicode command line into a list of argv arguments.
533
4913.5.25 by Gordon Tyler
Simplified win32utils.command_line_to_argv and made it private since it's no longer used outside of the module.
534
    It performs wildcard expansion to make wildcards act closer to how they
535
    work in posix shells, versus how they work by default on Windows. Quoted
536
    arguments are left untouched.
4913.5.2 by Gordon Tyler
Changed shlex_split_unicode to prevent wildcard expansion in the win32 codepath.
537
538
    :param command_line: The unicode string to split into an arg list.
4913.5.11 by Gordon Tyler
Added optional single quote support to UnicodeShlex and thus command_line_to_argv (defaults to disabled).
539
    :param single_quotes_allowed: Whether single quotes are accepted as quoting
540
                                  characters like double quotes. False by
541
                                  default.
4913.5.2 by Gordon Tyler
Changed shlex_split_unicode to prevent wildcard expansion in the win32 codepath.
542
    :return: A list of unicode strings.
4786.1.1 by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows.
543
    """
5274.4.1 by Jason Spashett
Initial Fix for 587868
544
    # First, spit the command line
4913.5.23 by Gordon Tyler
Renamed cmdline.Parser to Splitter to better match its usage.
545
    s = cmdline.Splitter(command_line, single_quotes_allowed=single_quotes_allowed)
5274.4.1 by Jason Spashett
Initial Fix for 587868
546
    
5274.4.8 by Jason Spashett
Reverse merge -r 5280..5279
547
    # Bug #587868 Now make sure that the length of s agrees with sys.argv 
548
    # we do this by simply counting the number of arguments in each. The counts should 
549
    # agree no matter what encoding sys.argv is in (AFAIK) 
550
    # len(arguments) < len(sys.argv) should be an impossibility since python gets 
551
    # args from the very same PEB as does GetCommandLineW
552
    arguments = list(s)
553
    
554
    # Now shorten the command line we get from GetCommandLineW to match sys.argv
5274.4.12 by Martin
Change interface of _command_line_to_argv so old tests can still be used with new stripping logic
555
    if len(arguments) < len(argv):
5274.4.11 by Martin
Minor cleanup, use plain AssertionError and revert needless variable rename
556
        raise AssertionError("Split command line can't be shorter than argv")
5274.4.12 by Martin
Change interface of _command_line_to_argv so old tests can still be used with new stripping logic
557
    arguments = arguments[len(arguments) - len(argv):]
5274.4.8 by Jason Spashett
Reverse merge -r 5280..5279
558
    
5274.4.2 by Jason Spashett
Tidied up fix for 587868. Put assert in for impossible case in command line lengths.
559
    # Carry on to process globs (metachars) in the command line
5274.4.1 by Jason Spashett
Initial Fix for 587868
560
    # expand globs if necessary
4786.1.1 by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows.
561
    # TODO: Use 'globbing' instead of 'glob.glob', this gives us stuff like
562
    #       '**/' style globs
5274.4.11 by Martin
Minor cleanup, use plain AssertionError and revert needless variable rename
563
    args = []
5274.4.8 by Jason Spashett
Reverse merge -r 5280..5279
564
    for is_quoted, arg in arguments:
4913.5.25 by Gordon Tyler
Simplified win32utils.command_line_to_argv and made it private since it's no longer used outside of the module.
565
        if is_quoted or not glob.has_magic(arg):
5274.4.11 by Martin
Minor cleanup, use plain AssertionError and revert needless variable rename
566
            args.append(arg)
4786.1.1 by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows.
567
        else:
5274.4.11 by Martin
Minor cleanup, use plain AssertionError and revert needless variable rename
568
            args.extend(glob_one(arg))
569
    return args
5274.4.3 by Jason Spashett
Merge from lp:bzr. Remove code for fix 588277 (revs 5274.3.1 - 5274.3.2) as this bug also fixes that issue. Make changes as per code review.
570
4786.1.1 by John Arbash Meinel
Work on doing globbing, etc for all commands on Windows.
571
6339.2.4 by Martin Packman
Bind name get_environ_unicode to None if function is unsupported
572
if has_ctypes and winver == 'Windows NT':
4355.2.1 by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments.
573
    def get_unicode_argv():
4913.5.15 by Gordon Tyler
Python < 2.6 doesn't support use_last_error.
574
        prototype = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
4913.5.1 by Gordon Tyler
Changed shlex_split_unicode in commands.py to use win32utils.command_line_to_argv on win32 and cleaned up win32utils.get_unicode_argv.
575
        GetCommandLineW = prototype(("GetCommandLineW",
576
                                     ctypes.windll.kernel32))
577
        command_line = GetCommandLineW()
578
        if command_line is None:
579
            raise ctypes.WinError()
5274.4.8 by Jason Spashett
Reverse merge -r 5280..5279
580
        # Skip the first argument, since we only care about parameters
5274.4.12 by Martin
Change interface of _command_line_to_argv so old tests can still be used with new stripping logic
581
        argv = _command_line_to_argv(command_line, sys.argv)[1:]
4355.2.1 by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments.
582
        return argv
6339.2.1 by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access
583
    
584
6339.2.3 by Martin Packman
Remove ability to specify a maximum buffer size as it serves no particular purpose
585
    def get_environ_unicode(key, default=None):
6339.2.1 by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access
586
        """Get `key` from environment as unicode or `default` if unset
587
6339.2.3 by Martin Packman
Remove ability to specify a maximum buffer size as it serves no particular purpose
588
        A large enough buffer will be allocated to retrieve the value, though
589
        it may take two calls to the underlying library function.
6339.2.1 by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access
590
591
        This needs ctypes because pywin32 does not expose the wide version.
592
        """
6339.2.2 by Martin Packman
Variable name changes and docstring fix suggested by vila in review
593
        cfunc = getattr(get_environ_unicode, "_c_function", None)
594
        if cfunc is None:
6339.2.1 by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access
595
            from ctypes.wintypes import DWORD, LPCWSTR, LPWSTR
6339.2.2 by Martin Packman
Variable name changes and docstring fix suggested by vila in review
596
            cfunc = ctypes.WINFUNCTYPE(DWORD, LPCWSTR, LPWSTR, DWORD)(
6339.2.1 by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access
597
                ("GetEnvironmentVariableW", ctypes.windll.kernel32))
6339.2.2 by Martin Packman
Variable name changes and docstring fix suggested by vila in review
598
            get_environ_unicode._c_function = cfunc
6339.2.3 by Martin Packman
Remove ability to specify a maximum buffer size as it serves no particular purpose
599
        buffer_size = 256 # heuristic, 256 characters often enough
6339.2.1 by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access
600
        while True:
601
            buffer = ctypes.create_unicode_buffer(buffer_size)
6339.2.2 by Martin Packman
Variable name changes and docstring fix suggested by vila in review
602
            length = cfunc(key, buffer, buffer_size)
6339.2.1 by Martin Packman
Add wrapper for GetEnvironmentVariableW on windows for unicode environ access
603
            if not length:
604
                code = ctypes.GetLastError()
605
                if code == 203: # ERROR_ENVVAR_NOT_FOUND
606
                    return default
607
                raise ctypes.WinError(code)
608
            if buffer_size > length:
609
                return buffer[:length]
610
            buffer_size = length
4355.2.2 by Alexander Belchenko
osutils.py: get_unicode_argv function (to obtain unicode command line arguments from sys.argv) moved to the beginning of module based on suggestions from review of John Meinel.
611
else:
6339.2.4 by Martin Packman
Bind name get_environ_unicode to None if function is unsupported
612
    get_unicode_argv = get_environ_unicode = None
5425.5.5 by Martin
Quick implementation of dead process detection on win32
613
614
615
if has_win32api:
616
    def _pywin32_is_local_pid_dead(pid):
617
        """True if pid doesn't correspond to live process on this machine"""
618
        try:
619
            handle = win32api.OpenProcess(1, False, pid) # PROCESS_TERMINATE
620
        except pywintypes.error, e:
5425.5.7 by Martin
Get the code for ERROR_ACCESS_DENIED right
621
            if e[0] == 5: # ERROR_ACCESS_DENIED
5425.5.5 by Martin
Quick implementation of dead process detection on win32
622
                # Probably something alive we're not allowed to kill
623
                return False
624
            elif e[0] == 87: # ERROR_INVALID_PARAMETER
625
                return True
626
            raise
627
        handle.close()
628
        return False
629
    is_local_pid_dead = _pywin32_is_local_pid_dead
5425.4.29 by Martin Pool
Don't try to get ctypes access to OpenProcess on non-win32 platforms
630
elif has_ctypes and sys.platform == 'win32':
5425.5.5 by Martin
Quick implementation of dead process detection on win32
631
    from ctypes.wintypes import BOOL, DWORD, HANDLE
632
    _kernel32 = ctypes.windll.kernel32
633
    _CloseHandle = ctypes.WINFUNCTYPE(BOOL, HANDLE)(
634
        ("CloseHandle", _kernel32))
635
    _OpenProcess = ctypes.WINFUNCTYPE(HANDLE, DWORD, BOOL, DWORD)(
636
        ("OpenProcess", _kernel32))
637
    def _ctypes_is_local_pid_dead(pid):
638
        """True if pid doesn't correspond to live process on this machine"""
639
        handle = _OpenProcess(1, False, pid) # PROCESS_TERMINATE
640
        if not handle:
641
            errorcode = ctypes.GetLastError()
5425.5.7 by Martin
Get the code for ERROR_ACCESS_DENIED right
642
            if errorcode == 5: # ERROR_ACCESS_DENIED
5425.5.5 by Martin
Quick implementation of dead process detection on win32
643
                # Probably something alive we're not allowed to kill
644
                return False
645
            elif errorcode == 87: # ERROR_INVALID_PARAMETER
646
                return True
647
            raise ctypes.WinError(errorcode)
648
        _CloseHandle(handle)
649
        return False
650
    is_local_pid_dead = _ctypes_is_local_pid_dead
6336.2.1 by Martin Packman
Add is_environment_error() and switch trace to using it
651
652
653
def _is_pywintypes_error(evalue):
6336.2.2 by Martin Packman
Tweak how pywin32 is imported in win32utils to fix test failure edge case
654
    """True if exception instance is an error from pywin32"""
655
    if has_pywintypes and isinstance(evalue, pywintypes.error):
6336.2.1 by Martin Packman
Add is_environment_error() and switch trace to using it
656
        return True
657
    return False