1
# Copyright (C) 2006, 2007 Canonical Ltd
 
 
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.
 
 
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.
 
 
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
 
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 
17
"""Win32-specific helper functions
 
 
19
Only one dependency: ctypes should be installed.
 
 
28
if sys.platform == 'win32':
 
 
29
    _major,_minor,_build,_platform,_text = sys.getwindowsversion()
 
 
32
    #   The operating system platform.
 
 
33
    #   This member can be one of the following values.
 
 
34
    #   ==========================  ======================================
 
 
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.
 
 
42
    #   VER_PLATFORM_WIN32_WINDOWS  The operating system is Windows Me,
 
 
43
    #   1                           Windows 98, or Windows 95.
 
 
44
    #   ==========================  ======================================
 
 
48
        # don't care about real Windows name, just to force safe operations
 
 
54
# We can cope without it; use a separate variable to help pyflakes
 
 
61
    if winver == 'Windows 98':
 
 
62
        create_buffer = ctypes.create_string_buffer
 
 
65
        create_buffer = ctypes.create_unicode_buffer
 
 
69
# Special Win32 API constants
 
 
70
# Handles of std streams
 
 
71
WIN32_STDIN_HANDLE = -10
 
 
72
WIN32_STDOUT_HANDLE = -11
 
 
73
WIN32_STDERR_HANDLE = -12
 
 
75
# CSIDL constants (from MSDN 2003)
 
 
76
CSIDL_APPDATA = 0x001A      # Application Data folder
 
 
77
CSIDL_PERSONAL = 0x0005     # My Documents folder
 
 
79
# from winapi C headers
 
 
82
MAX_COMPUTERNAME_LENGTH = 31
 
 
85
def get_console_size(defaultx=80, defaulty=25):
 
 
86
    """Return size of current console.
 
 
88
    This function try to determine actual size of current working
 
 
89
    console window and return tuple (sizex, sizey) if success,
 
 
90
    or default size (defaultx, defaulty) otherwise.
 
 
94
        return (defaultx, defaulty)
 
 
96
    # To avoid problem with redirecting output via pipe
 
 
97
    # need to use stderr instead of stdout
 
 
98
    h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
 
 
99
    csbi = ctypes.create_string_buffer(22)
 
 
100
    res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
 
 
103
        (bufx, bufy, curx, cury, wattr,
 
 
104
        left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
 
 
105
        sizex = right - left + 1
 
 
106
        sizey = bottom - top + 1
 
 
107
        return (sizex, sizey)
 
 
109
        return (defaultx, defaulty)
 
 
112
def get_appdata_location():
 
 
113
    """Return Application Data location.
 
 
114
    Return None if we cannot obtain location.
 
 
116
    Returned value can be unicode or plain sring.
 
 
117
    To convert plain string to unicode use
 
 
118
    s.decode(bzrlib.user_encoding)
 
 
122
            SHGetSpecialFolderPath = \
 
 
123
                ctypes.windll.shell32.SHGetSpecialFolderPathW
 
 
124
        except AttributeError:
 
 
127
            buf = ctypes.create_unicode_buffer(MAX_PATH)
 
 
128
            if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
 
 
131
    appdata = os.environ.get('APPDATA')
 
 
134
    # if we fall to this point we on win98
 
 
135
    # at least try C:/WINDOWS/Application Data
 
 
136
    windir = os.environ.get('windir')
 
 
138
        appdata = os.path.join(windir, 'Application Data')
 
 
139
        if os.path.isdir(appdata):
 
 
141
    # did not find anything
 
 
145
def get_home_location():
 
 
146
    """Return user's home location.
 
 
147
    Assume on win32 it's the <My Documents> folder.
 
 
148
    If location cannot be obtained return system drive root,
 
 
151
    Returned value can be unicode or plain sring.
 
 
152
    To convert plain string to unicode use
 
 
153
    s.decode(bzrlib.user_encoding)
 
 
157
            SHGetSpecialFolderPath = \
 
 
158
                ctypes.windll.shell32.SHGetSpecialFolderPathW
 
 
159
        except AttributeError:
 
 
162
            buf = ctypes.create_unicode_buffer(MAX_PATH)
 
 
163
            if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0):
 
 
165
    # try for HOME env variable
 
 
166
    home = os.path.expanduser('~')
 
 
169
    # at least return windows root directory
 
 
170
    windir = os.environ.get('windir')
 
 
172
        return os.path.splitdrive(windir) + '/'
 
 
173
    # otherwise C:\ is good enough for 98% users
 
 
178
    """Return user name as login name.
 
 
179
    If name cannot be obtained return None.
 
 
181
    Returned value can be unicode or plain sring.
 
 
182
    To convert plain string to unicode use
 
 
183
    s.decode(bzrlib.user_encoding)
 
 
187
            advapi32 = ctypes.windll.advapi32
 
 
188
            GetUserName = getattr(advapi32, 'GetUserName'+suffix)
 
 
189
        except AttributeError:
 
 
192
            buf = create_buffer(UNLEN+1)
 
 
193
            n = ctypes.c_int(UNLEN+1)
 
 
194
            if GetUserName(buf, ctypes.byref(n)):
 
 
196
    # otherwise try env variables
 
 
197
    return os.environ.get('USERNAME', None)
 
 
201
    """Return host machine name.
 
 
202
    If name cannot be obtained return None.
 
 
204
    Returned value can be unicode or plain sring.
 
 
205
    To convert plain string to unicode use
 
 
206
    s.decode(bzrlib.user_encoding)
 
 
210
            kernel32 = ctypes.windll.kernel32
 
 
211
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix)
 
 
212
        except AttributeError:
 
 
215
            buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
 
 
216
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
 
 
217
            if GetComputerName(buf, ctypes.byref(n)):
 
 
219
    # otherwise try env variables
 
 
220
    return os.environ.get('COMPUTERNAME', None)
 
 
223
def _ensure_unicode(s):
 
 
224
    if s and type(s) != unicode:
 
 
226
        s = s.decode(bzrlib.user_encoding)
 
 
230
def get_appdata_location_unicode():
 
 
231
    return _ensure_unicode(get_appdata_location())
 
 
233
def get_home_location_unicode():
 
 
234
    return _ensure_unicode(get_home_location())
 
 
236
def get_user_name_unicode():
 
 
237
    return _ensure_unicode(get_user_name())
 
 
239
def get_host_name_unicode():
 
 
240
    return _ensure_unicode(get_host_name())
 
 
243
def glob_expand(file_list):
 
 
244
    """Replacement for glob expansion by the shell.
 
 
246
    Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
 
 
249
    :param file_list: A list of filenames which may include shell globs.
 
 
250
    :return: An expanded list of filenames.
 
 
252
    Introduced in bzrlib 0.18.
 
 
257
    expanded_file_list = []
 
 
258
    for possible_glob in file_list:
 
 
259
        glob_files = glob.glob(possible_glob)
 
 
262
            # special case to let the normal code path handle
 
 
263
            # files that do not exists
 
 
264
            expanded_file_list.append(possible_glob)
 
 
266
            expanded_file_list += glob_files
 
 
267
    return expanded_file_list