~bzr-pqm/bzr/bzr.dev

2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
1
# Copyright (C) 2006, 2007 Canonical Ltd
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
22
import os
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
23
import struct
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
24
import sys
25
26
27
# Windows version
28
if sys.platform == 'win32':
29
    _major,_minor,_build,_platform,_text = sys.getwindowsversion()
2245.4.11 by Alexander Belchenko
Small fixes after John's review; added NEWS entry
30
    # from MSDN:
31
    # dwPlatformId
32
    #   The operating system platform.
33
    #   This member can be one of the following values.
34
    #   ==========================  ======================================
35
    #   Value                       Meaning
36
    #   --------------------------  --------------------------------------
37
    #   VER_PLATFORM_WIN32_NT       The operating system is Windows Vista,
38
    #   2                           Windows Server "Longhorn",
39
    #                               Windows Server 2003, Windows XP,
40
    #                               Windows 2000, or Windows NT.
41
    #
42
    #   VER_PLATFORM_WIN32_WINDOWS  The operating system is Windows Me,
43
    #   1                           Windows 98, or Windows 95.
44
    #   ==========================  ======================================
45
    if _platform == 2:
46
        winver = 'Windows NT'
47
    else:
48
        # 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
49
        winver = 'Windows 98'
50
else:
51
    winver = None
52
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
53
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
54
# 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
55
try:
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
56
    import ctypes
57
    has_ctypes = True
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
58
except ImportError:
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
59
    has_ctypes = False
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
60
else:
61
    if winver == 'Windows 98':
62
        create_buffer = ctypes.create_string_buffer
63
        suffix = 'A'
64
    else:
65
        create_buffer = ctypes.create_unicode_buffer
66
        suffix = 'W'
3023.1.2 by Alexander Belchenko
Martin's review.
67
try:
68
    import win32file
69
    has_win32file = True
70
except ImportError:
71
    has_win32file = False
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
72
try:
73
    import win32api
74
    has_win32api = True
75
except ImportError:
76
    has_win32api = False
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
77
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
78
# pulling in win32com.shell is a bit of overhead, and normally we don't need
79
# it as ctypes is preferred and common.  lazy_imports and "optional"
80
# modules don't work well, so we do our own lazy thing...
81
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
82
83
# Special Win32 API constants
84
# Handles of std streams
1704.2.3 by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander)
85
WIN32_STDIN_HANDLE = -10
86
WIN32_STDOUT_HANDLE = -11
87
WIN32_STDERR_HANDLE = -12
88
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
89
# CSIDL constants (from MSDN 2003)
90
CSIDL_APPDATA = 0x001A      # Application Data folder
3638.4.10 by Aaron Bentley
Correct spelling of 'Application Data'
91
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
92
CSIDL_PERSONAL = 0x0005     # My Documents folder
93
94
# from winapi C headers
95
MAX_PATH = 260
96
UNLEN = 256
97
MAX_COMPUTERNAME_LENGTH = 31
98
1704.2.3 by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander)
99
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
100
def debug_memory_win32api(message='', short=True):
101
    """Use trace.note() to dump the running memory info."""
102
    from bzrlib import trace
4011.1.2 by John Arbash Meinel
Fix some small bugs, and prefer the ctypes form.
103
    if has_ctypes:
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
104
        class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
105
            """Used by GetProcessMemoryInfo"""
106
            _fields_ = [('cb', ctypes.c_ulong),
107
                        ('PageFaultCount', ctypes.c_ulong),
108
                        ('PeakWorkingSetSize', ctypes.c_size_t),
109
                        ('WorkingSetSize', ctypes.c_size_t),
110
                        ('QuotaPeakPagedPoolUsage', ctypes.c_size_t),
111
                        ('QuotaPagedPoolUsage', ctypes.c_size_t),
112
                        ('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t),
113
                        ('QuotaNonPagedPoolUsage', ctypes.c_size_t),
114
                        ('PagefileUsage', ctypes.c_size_t),
115
                        ('PeakPagefileUsage', ctypes.c_size_t),
116
                        ('PrivateUsage', ctypes.c_size_t),
117
                       ]
118
        cur_process = ctypes.windll.kernel32.GetCurrentProcess()
119
        mem_struct = PROCESS_MEMORY_COUNTERS_EX()
120
        ret = ctypes.windll.psapi.GetProcessMemoryInfo(cur_process,
121
            ctypes.byref(mem_struct),
122
            ctypes.sizeof(mem_struct))
123
        if not ret:
124
            trace.note('Failed to GetProcessMemoryInfo()')
125
            return
126
        info = {'PageFaultCount': mem_struct.PageFaultCount,
127
                'PeakWorkingSetSize': mem_struct.PeakWorkingSetSize,
128
                'WorkingSetSize': mem_struct.WorkingSetSize,
129
                'QuotaPeakPagedPoolUsage': mem_struct.QuotaPeakPagedPoolUsage,
130
                'QuotaPagedPoolUsage': mem_struct.QuotaPagedPoolUsage,
131
                'QuotaPeakNonPagedPoolUsage': mem_struct.QuotaPeakNonPagedPoolUsage,
132
                'QuotaNonPagedPoolUsage': mem_struct.QuotaNonPagedPoolUsage,
133
                'PagefileUsage': mem_struct.PagefileUsage,
134
                'PeakPagefileUsage': mem_struct.PeakPagefileUsage,
135
                'PrivateUsage': mem_struct.PrivateUsage,
136
               }
4011.1.2 by John Arbash Meinel
Fix some small bugs, and prefer the ctypes form.
137
    elif has_win32api:
138
        import win32process
139
        # win32process does not return PrivateUsage, because it doesn't use
140
        # PROCESS_MEMORY_COUNTERS_EX (it uses the one without _EX).
141
        proc = win32process.GetCurrentProcess()
142
        info = win32process.GetProcessMemoryInfo(proc)
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
143
    else:
144
        trace.note('Cannot debug memory on win32 without ctypes'
145
                   ' or win32process')
146
        return
4163.1.1 by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code.
147
    if short:
4163.1.2 by John Arbash Meinel
Merge bzr.dev, which changed kB => KB.
148
        trace.note('WorkingSize %7dKB'
149
                   '\tPeakWorking %7dKB\t%s',
4163.1.1 by John Arbash Meinel
Some small fixes for the win32 'trace.debug_mem()' code.
150
                   info['WorkingSetSize'] / 1024,
151
                   info['PeakWorkingSetSize'] / 1024,
152
                   message)
153
        return
154
    if message:
155
        trace.note('%s', message)
4170.2.1 by Alexander Belchenko
Use KB not kB for 1024 bytes
156
    trace.note('WorkingSize       %8d KB', info['WorkingSetSize'] / 1024)
157
    trace.note('PeakWorking       %8d KB', info['PeakWorkingSetSize'] / 1024)
158
    trace.note('PagefileUsage     %8d KB', info.get('PagefileUsage', 0) / 1024)
159
    trace.note('PeakPagefileUsage %8d KB', info.get('PeakPagefileUsage', 0) / 1024)
160
    trace.note('PrivateUsage      %8d KB', info.get('PrivateUsage', 0) / 1024)
4011.1.1 by John Arbash Meinel
Implement -Dmemory for win32
161
    trace.note('PageFaultCount    %8d', info.get('PageFaultCount', 0))
162
163
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
164
def get_console_size(defaultx=80, defaulty=25):
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
165
    """Return size of current console.
166
167
    This function try to determine actual size of current working
168
    console window and return tuple (sizex, sizey) if success,
169
    or default size (defaultx, defaulty) otherwise.
170
    """
171
    if not has_ctypes:
172
        # no ctypes is found
173
        return (defaultx, defaulty)
174
175
    # To avoid problem with redirecting output via pipe
176
    # need to use stderr instead of stdout
177
    h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
178
    csbi = ctypes.create_string_buffer(22)
179
    res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
180
181
    if res:
182
        (bufx, bufy, curx, cury, wattr,
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
183
        left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
184
        sizex = right - left + 1
185
        sizey = bottom - top + 1
186
        return (sizex, sizey)
187
    else:
188
        return (defaultx, defaulty)
189
190
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
191
def _get_sh_special_folder_path(csidl):
192
    """Call SHGetSpecialFolderPathW if available, or return None.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
193
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
194
    Result is always unicode (or None).
195
    """
196
    if has_ctypes:
197
        try:
198
            SHGetSpecialFolderPath = \
199
                ctypes.windll.shell32.SHGetSpecialFolderPathW
200
        except AttributeError:
201
            pass
202
        else:
203
            buf = ctypes.create_unicode_buffer(MAX_PATH)
204
            if SHGetSpecialFolderPath(None,buf,csidl,0):
205
                return buf.value
206
207
    global has_win32com_shell
208
    if has_win32com_shell is None:
209
        try:
210
            from win32com.shell import shell
211
            has_win32com_shell = True
212
        except ImportError:
213
            has_win32com_shell = False
214
    if has_win32com_shell:
215
        # still need to bind the name locally, but this is fast.
216
        from win32com.shell import shell
217
        try:
218
            return shell.SHGetSpecialFolderPath(0, csidl, 0)
219
        except shell.error:
220
            # possibly E_NOTIMPL meaning we can't load the function pointer,
221
            # or E_FAIL meaning the function failed - regardless, just ignore it
222
            pass
223
    return None
224
225
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
226
def get_appdata_location():
227
    """Return Application Data location.
228
    Return None if we cannot obtain location.
229
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
230
    Windows defines two 'Application Data' folders per user - a 'roaming'
231
    one that moves with the user as they logon to different machines, and
232
    a 'local' one that stays local to the machine.  This returns the 'roaming'
233
    directory, and thus is suitable for storing user-preferences, etc.
234
235
    Returned value can be unicode or plain string.
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
236
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
237
    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.
238
    (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
239
    """
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
240
    appdata = _get_sh_special_folder_path(CSIDL_APPDATA)
241
    if appdata:
242
        return appdata
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
243
    # from env variable
244
    appdata = os.environ.get('APPDATA')
245
    if appdata:
246
        return appdata
247
    # if we fall to this point we on win98
248
    # at least try C:/WINDOWS/Application Data
249
    windir = os.environ.get('windir')
250
    if windir:
251
        appdata = os.path.join(windir, 'Application Data')
252
        if os.path.isdir(appdata):
253
            return appdata
254
    # did not find anything
255
    return None
256
257
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
258
def get_local_appdata_location():
259
    """Return Local Application Data location.
260
    Return the same as get_appdata_location() if we cannot obtain location.
261
262
    Windows defines two 'Application Data' folders per user - a 'roaming'
263
    one that moves with the user as they logon to different machines, and
264
    a 'local' one that stays local to the machine.  This returns the 'local'
265
    directory, and thus is suitable for caches, temp files and other things
266
    which don't need to move with the user.
267
268
    Returned value can be unicode or plain string.
269
    To convert plain string to unicode use
270
    s.decode(bzrlib.user_encoding)
3638.4.2 by Mark Hammond
Add a reference to bug 262874 noting 'mbcs' may be the correct encoding.
271
    (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
272
    """
273
    local = _get_sh_special_folder_path(CSIDL_LOCAL_APPDATA)
274
    if local:
275
        return local
276
    # Vista supplies LOCALAPPDATA, but XP and earlier do not.
277
    local = os.environ.get('LOCALAPPDATA')
278
    if local:
279
        return local
280
    return get_appdata_location()
281
282
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
283
def get_home_location():
284
    """Return user's home location.
285
    Assume on win32 it's the <My Documents> folder.
286
    If location cannot be obtained return system drive root,
287
    i.e. C:\
288
4031.3.1 by Frank Aspell
Fixing various typos
289
    Returned value can be unicode or plain string.
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
290
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
291
    s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
292
    """
3638.4.1 by Mark Hammond
Add win32utils.get_local_appdata_location() so bzr and plugins can
293
    home = _get_sh_special_folder_path(CSIDL_PERSONAL)
294
    if home:
295
        return home
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
296
    # try for HOME env variable
297
    home = os.path.expanduser('~')
298
    if home != '~':
299
        return home
300
    # at least return windows root directory
301
    windir = os.environ.get('windir')
302
    if windir:
2610.1.1 by Martin Pool
Fix get_home_location on Win98 (gzlist,r=john,r=alexander)
303
        return os.path.splitdrive(windir)[0] + '/'
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
304
    # otherwise C:\ is good enough for 98% users
305
    return 'C:/'
306
307
308
def get_user_name():
309
    """Return user name as login name.
310
    If name cannot be obtained return None.
311
4031.3.1 by Frank Aspell
Fixing various typos
312
    Returned value can be unicode or plain string.
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
313
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
314
    s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
315
    """
316
    if has_ctypes:
317
        try:
318
            advapi32 = ctypes.windll.advapi32
319
            GetUserName = getattr(advapi32, 'GetUserName'+suffix)
320
        except AttributeError:
321
            pass
322
        else:
323
            buf = create_buffer(UNLEN+1)
324
            n = ctypes.c_int(UNLEN+1)
325
            if GetUserName(buf, ctypes.byref(n)):
326
                return buf.value
327
    # otherwise try env variables
328
    return os.environ.get('USERNAME', None)
329
330
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
331
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
332
# computer or the cluster associated with the local computer."
333
_WIN32_ComputerNameDnsHostname = 1
334
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
335
def get_host_name():
336
    """Return host machine name.
337
    If name cannot be obtained return None.
338
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
339
    :return: A unicode string representing the host name. On win98, this may be
340
        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
341
    """
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
342
    if has_win32api:
343
        try:
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
344
            return win32api.GetComputerNameEx(_WIN32_ComputerNameDnsHostname)
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
345
        except (NotImplementedError, win32api.error):
346
            # NotImplemented will happen on win9x...
347
            pass
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
348
    if has_ctypes:
349
        try:
350
            kernel32 = ctypes.windll.kernel32
351
        except AttributeError:
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
352
            pass # Missing the module we need
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
353
        else:
354
            buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
355
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
356
357
            # Try GetComputerNameEx which gives a proper Unicode hostname
358
            GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx'+suffix,
359
                                        None)
360
            if (GetComputerNameEx is not None
361
                and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
362
                                      buf, ctypes.byref(n))):
363
                return buf.value
364
365
            # Try GetComputerName in case GetComputerNameEx wasn't found
366
            # It returns the NETBIOS name, which isn't as good, but still ok.
367
            # The first GetComputerNameEx might have changed 'n', so reset it
368
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
369
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix,
370
                                      None)
371
            if (GetComputerName is not None
372
                and GetComputerName(buf, ctypes.byref(n))):
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
373
                return buf.value
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
374
    # otherwise try env variables, which will be 'mbcs' encoded
375
    # on Windows (Python doesn't expose the native win32 unicode environment)
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
376
    # According to this:
377
    # http://msdn.microsoft.com/en-us/library/aa246807.aspx
378
    # environment variables should always be encoded in 'mbcs'.
3626.1.2 by skip
win32utils.get_host_name() uses 'mbcs' encoding when decoding env vars
379
    try:
380
        return os.environ['COMPUTERNAME'].decode("mbcs")
381
    except KeyError:
382
        return None
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
383
384
385
def _ensure_unicode(s):
3794.1.1 by Martin Pool
Update osutils imports to fix setup.py on Windows
386
    from bzrlib import osutils
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
387
    if s and type(s) != unicode:
3788.1.1 by John Arbash Meinel
Fix a missing import
388
        from bzrlib import osutils
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
389
        s = s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
390
    return s
3626.1.3 by John Arbash Meinel
Use GetComputerNameEx from ctypes when available.
391
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
392
393
def get_appdata_location_unicode():
394
    return _ensure_unicode(get_appdata_location())
395
396
def get_home_location_unicode():
397
    return _ensure_unicode(get_home_location())
398
399
def get_user_name_unicode():
400
    return _ensure_unicode(get_user_name())
401
402
def get_host_name_unicode():
403
    return _ensure_unicode(get_host_name())
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
404
405
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
406
def _ensure_with_dir(path):
407
    if not os.path.split(path)[0] or path.startswith(u'*') or path.startswith(u'?'):
408
        return u'./' + path, True
409
    else:
410
        return path, False
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
411
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
412
def _undo_ensure_with_dir(path, corrected):
413
    if corrected:
414
        return path[2:]
415
    else:
416
        return path
417
418
419
2598.3.1 by Kuno Meyer
fix method rename glob_expand_for_win32 -> win32utils.glob_expand
420
def glob_expand(file_list):
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
421
    """Replacement for glob expansion by the shell.
422
423
    Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
424
    here.
425
426
    :param file_list: A list of filenames which may include shell globs.
427
    :return: An expanded list of filenames.
428
429
    Introduced in bzrlib 0.18.
430
    """
431
    if not file_list:
432
        return []
433
    import glob
434
    expanded_file_list = []
435
    for possible_glob in file_list:
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
436
        # work around bugs in glob.glob()
437
        # - Python bug #1001604 ("glob doesn't return unicode with ...")
438
        # - failing expansion for */* with non-iso-8859-* chars
439
        possible_glob, corrected = _ensure_with_dir(possible_glob)
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
440
        glob_files = glob.glob(possible_glob)
441
442
        if glob_files == []:
443
            # special case to let the normal code path handle
444
            # files that do not exists
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
445
            expanded_file_list.append(
446
                _undo_ensure_with_dir(possible_glob, corrected))
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
447
        else:
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
448
            glob_files = [_undo_ensure_with_dir(elem, corrected) for elem in glob_files]
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
449
            expanded_file_list += glob_files
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
450
451
    return [elem.replace(u'\\', u'/') for elem in expanded_file_list]
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
452
453
454
def get_app_path(appname):
455
    """Look up in Windows registry for full path to application executable.
4031.3.1 by Frank Aspell
Fixing various typos
456
    Typically, applications create subkey with their basename
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
457
    in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
458
459
    :param  appname:    name of application (if no filename extension
460
                        is specified, .exe used)
461
    :return:    full path to aplication executable from registry,
462
                or appname itself if nothing found.
463
    """
2681.4.3 by Alexander Belchenko
move import _winreg into function get_app_path to avoid ImportError on non-win32 platforms
464
    import _winreg
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
465
    try:
466
        hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
467
                               r'SOFTWARE\Microsoft\Windows'
468
                               r'\CurrentVersion\App Paths')
469
    except EnvironmentError:
470
        return appname
471
472
    basename = appname
473
    if not os.path.splitext(basename)[1]:
474
        basename = appname + '.exe'
475
    try:
476
        try:
477
            fullpath = _winreg.QueryValue(hkey, basename)
478
        except WindowsError:
479
            fullpath = appname
480
    finally:
481
        _winreg.CloseKey(hkey)
482
483
    return fullpath
3023.1.2 by Alexander Belchenko
Martin's review.
484
485
486
def set_file_attr_hidden(path):
487
    """Set file attributes to hidden if possible"""
488
    if has_win32file:
489
        win32file.SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)
4355.2.1 by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments.
490
491
492
if has_ctypes and winver != 'Windows 98':
493
    def get_unicode_argv():
494
        LPCWSTR = ctypes.c_wchar_p
495
        INT = ctypes.c_int
496
        POINTER = ctypes.POINTER
497
        prototype = ctypes.WINFUNCTYPE(LPCWSTR)
498
        GetCommandLine = prototype(("GetCommandLineW",
499
                                    ctypes.windll.kernel32))
500
        prototype = ctypes.WINFUNCTYPE(POINTER(LPCWSTR), LPCWSTR, POINTER(INT))
501
        CommandLineToArgv = prototype(("CommandLineToArgvW",
502
                                       ctypes.windll.shell32))
503
        c = INT(0)
504
        pargv = CommandLineToArgv(GetCommandLine(), ctypes.byref(c))
4355.2.4 by Alexander Belchenko
win32utils.py: get_unicode_argv: get bzr options as tail of argv list based on the number of items in sys.argv[1:] list.
505
        # Skip the first argument, since we only care about parameters
4355.2.1 by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments.
506
        argv = [pargv[i] for i in range(1, c.value)]
507
        if getattr(sys, 'frozen', None) is None:
4355.2.4 by Alexander Belchenko
win32utils.py: get_unicode_argv: get bzr options as tail of argv list based on the number of items in sys.argv[1:] list.
508
            # Invoked via 'python.exe' which takes the form:
509
            #   python.exe [PYTHON_OPTIONS] C:\Path\bzr [BZR_OPTIONS]
510
            # we need to get only BZR_OPTIONS part,
4355.2.5 by Alexander Belchenko
improve comment
511
            # so let's using sys.argv[1:] as reference to get the tail
512
            # of unicode argv
4355.2.4 by Alexander Belchenko
win32utils.py: get_unicode_argv: get bzr options as tail of argv list based on the number of items in sys.argv[1:] list.
513
            tail_len = len(sys.argv[1:])
514
            ix = len(argv) - tail_len
515
            argv = argv[ix:]
4355.2.1 by Alexander Belchenko
Using unicode Windows API to obtain command-line arguments.
516
        return argv
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.
517
else:
518
    get_unicode_argv = None