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)[0] + '/'
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 _ensure_with_dir(path):
244
if not os.path.split(path)[0] or path.startswith(u'*') or path.startswith(u'?'):
245
return u'./' + path, True
249
def _undo_ensure_with_dir(path, corrected):
257
def glob_expand(file_list):
258
"""Replacement for glob expansion by the shell.
260
Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
263
:param file_list: A list of filenames which may include shell globs.
264
:return: An expanded list of filenames.
266
Introduced in bzrlib 0.18.
271
expanded_file_list = []
272
for possible_glob in file_list:
274
# work around bugs in glob.glob()
275
# - Python bug #1001604 ("glob doesn't return unicode with ...")
276
# - failing expansion for */* with non-iso-8859-* chars
277
possible_glob, corrected = _ensure_with_dir(possible_glob)
278
glob_files = glob.glob(possible_glob)
281
# special case to let the normal code path handle
282
# files that do not exists
283
expanded_file_list.append(
284
_undo_ensure_with_dir(possible_glob, corrected))
286
glob_files = [_undo_ensure_with_dir(elem, corrected) for elem in glob_files]
287
expanded_file_list += glob_files
289
return [elem.replace(u'\\', u'/') for elem in expanded_file_list]
292
def get_app_path(appname):
293
"""Look up in Windows registry for full path to application executable.
294
Typicaly, applications create subkey with their basename
295
in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
297
:param appname: name of application (if no filename extension
298
is specified, .exe used)
299
:return: full path to aplication executable from registry,
300
or appname itself if nothing found.
304
hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
305
r'SOFTWARE\Microsoft\Windows'
306
r'\CurrentVersion\App Paths')
307
except EnvironmentError:
311
if not os.path.splitext(basename)[1]:
312
basename = appname + '.exe'
315
fullpath = _winreg.QueryValue(hkey, basename)
319
_winreg.CloseKey(hkey)