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