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.
29
if sys.platform == 'win32':
30
_major,_minor,_build,_platform,_text = sys.getwindowsversion()
33
# The operating system platform.
34
# This member can be one of the following values.
35
# ========================== ======================================
37
# -------------------------- --------------------------------------
38
# VER_PLATFORM_WIN32_NT The operating system is Windows Vista,
39
# 2 Windows Server "Longhorn",
40
# Windows Server 2003, Windows XP,
41
# Windows 2000, or Windows NT.
43
# VER_PLATFORM_WIN32_WINDOWS The operating system is Windows Me,
44
# 1 Windows 98, or Windows 95.
45
# ========================== ======================================
49
# don't care about real Windows name, just to force safe operations
55
# We can cope without it; use a separate variable to help pyflakes
62
if winver == 'Windows 98':
63
create_buffer = ctypes.create_string_buffer
66
create_buffer = ctypes.create_unicode_buffer
70
# Special Win32 API constants
71
# Handles of std streams
72
WIN32_STDIN_HANDLE = -10
73
WIN32_STDOUT_HANDLE = -11
74
WIN32_STDERR_HANDLE = -12
76
# CSIDL constants (from MSDN 2003)
77
CSIDL_APPDATA = 0x001A # Application Data folder
78
CSIDL_PERSONAL = 0x0005 # My Documents folder
80
# from winapi C headers
83
MAX_COMPUTERNAME_LENGTH = 31
86
def get_console_size(defaultx=80, defaulty=25):
87
"""Return size of current console.
89
This function try to determine actual size of current working
90
console window and return tuple (sizex, sizey) if success,
91
or default size (defaultx, defaulty) otherwise.
95
return (defaultx, defaulty)
97
# To avoid problem with redirecting output via pipe
98
# need to use stderr instead of stdout
99
h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
100
csbi = ctypes.create_string_buffer(22)
101
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
104
(bufx, bufy, curx, cury, wattr,
105
left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
106
sizex = right - left + 1
107
sizey = bottom - top + 1
108
return (sizex, sizey)
110
return (defaultx, defaulty)
113
def get_appdata_location():
114
"""Return Application Data location.
115
Return None if we cannot obtain location.
117
Returned value can be unicode or plain sring.
118
To convert plain string to unicode use
119
s.decode(bzrlib.user_encoding)
123
SHGetSpecialFolderPath = \
124
ctypes.windll.shell32.SHGetSpecialFolderPathW
125
except AttributeError:
128
buf = ctypes.create_unicode_buffer(MAX_PATH)
129
if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
132
appdata = os.environ.get('APPDATA')
135
# if we fall to this point we on win98
136
# at least try C:/WINDOWS/Application Data
137
windir = os.environ.get('windir')
139
appdata = os.path.join(windir, 'Application Data')
140
if os.path.isdir(appdata):
142
# did not find anything
146
def get_home_location():
147
"""Return user's home location.
148
Assume on win32 it's the <My Documents> folder.
149
If location cannot be obtained return system drive root,
152
Returned value can be unicode or plain sring.
153
To convert plain string to unicode use
154
s.decode(bzrlib.user_encoding)
158
SHGetSpecialFolderPath = \
159
ctypes.windll.shell32.SHGetSpecialFolderPathW
160
except AttributeError:
163
buf = ctypes.create_unicode_buffer(MAX_PATH)
164
if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0):
166
# try for HOME env variable
167
home = os.path.expanduser('~')
170
# at least return windows root directory
171
windir = os.environ.get('windir')
173
return os.path.splitdrive(windir)[0] + '/'
174
# otherwise C:\ is good enough for 98% users
179
"""Return user name as login name.
180
If name cannot be obtained return None.
182
Returned value can be unicode or plain sring.
183
To convert plain string to unicode use
184
s.decode(bzrlib.user_encoding)
188
advapi32 = ctypes.windll.advapi32
189
GetUserName = getattr(advapi32, 'GetUserName'+suffix)
190
except AttributeError:
193
buf = create_buffer(UNLEN+1)
194
n = ctypes.c_int(UNLEN+1)
195
if GetUserName(buf, ctypes.byref(n)):
197
# otherwise try env variables
198
return os.environ.get('USERNAME', None)
202
"""Return host machine name.
203
If name cannot be obtained return None.
205
Returned value can be unicode or plain sring.
206
To convert plain string to unicode use
207
s.decode(bzrlib.user_encoding)
211
kernel32 = ctypes.windll.kernel32
212
GetComputerName = getattr(kernel32, 'GetComputerName'+suffix)
213
except AttributeError:
216
buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
217
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
218
if GetComputerName(buf, ctypes.byref(n)):
220
# otherwise try env variables
221
return os.environ.get('COMPUTERNAME', None)
224
def _ensure_unicode(s):
225
if s and type(s) != unicode:
227
s = s.decode(bzrlib.user_encoding)
231
def get_appdata_location_unicode():
232
return _ensure_unicode(get_appdata_location())
234
def get_home_location_unicode():
235
return _ensure_unicode(get_home_location())
237
def get_user_name_unicode():
238
return _ensure_unicode(get_user_name())
240
def get_host_name_unicode():
241
return _ensure_unicode(get_host_name())
244
def _ensure_with_dir(path):
245
if not os.path.split(path)[0] or path.startswith(u'*') or path.startswith(u'?'):
246
return u'./' + path, True
250
def _undo_ensure_with_dir(path, corrected):
258
def glob_expand(file_list):
259
"""Replacement for glob expansion by the shell.
261
Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
264
:param file_list: A list of filenames which may include shell globs.
265
:return: An expanded list of filenames.
267
Introduced in bzrlib 0.18.
272
expanded_file_list = []
273
for possible_glob in file_list:
275
# work around bugs in glob.glob()
276
# - Python bug #1001604 ("glob doesn't return unicode with ...")
277
# - failing expansion for */* with non-iso-8859-* chars
278
possible_glob, corrected = _ensure_with_dir(possible_glob)
279
glob_files = glob.glob(possible_glob)
282
# special case to let the normal code path handle
283
# files that do not exists
284
expanded_file_list.append(
285
_undo_ensure_with_dir(possible_glob, corrected))
287
glob_files = [_undo_ensure_with_dir(elem, corrected) for elem in glob_files]
288
expanded_file_list += glob_files
290
return [elem.replace(u'\\', u'/') for elem in expanded_file_list]
293
def get_app_path(appname):
294
"""Look up in Windows registry for full path to application executable.
295
Typicaly, applications create subkey with their basename
296
in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
298
:param appname: name of application (if no filename extension
299
is specified, .exe used)
300
:return: full path to aplication executable from registry,
301
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)