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
74
# Special Win32 API constants
75
# Handles of std streams
76
WIN32_STDIN_HANDLE = -10
77
WIN32_STDOUT_HANDLE = -11
78
WIN32_STDERR_HANDLE = -12
80
# CSIDL constants (from MSDN 2003)
81
CSIDL_APPDATA = 0x001A # Application Data folder
82
CSIDL_PERSONAL = 0x0005 # My Documents folder
84
# from winapi C headers
87
MAX_COMPUTERNAME_LENGTH = 31
90
def get_console_size(defaultx=80, defaulty=25):
91
"""Return size of current console.
93
This function try to determine actual size of current working
94
console window and return tuple (sizex, sizey) if success,
95
or default size (defaultx, defaulty) otherwise.
99
return (defaultx, defaulty)
101
# To avoid problem with redirecting output via pipe
102
# need to use stderr instead of stdout
103
h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
104
csbi = ctypes.create_string_buffer(22)
105
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
108
(bufx, bufy, curx, cury, wattr,
109
left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
110
sizex = right - left + 1
111
sizey = bottom - top + 1
112
return (sizex, sizey)
114
return (defaultx, defaulty)
117
def get_appdata_location():
118
"""Return Application Data location.
119
Return None if we cannot obtain location.
121
Returned value can be unicode or plain sring.
122
To convert plain string to unicode use
123
s.decode(osutils.get_user_encoding())
127
SHGetSpecialFolderPath = \
128
ctypes.windll.shell32.SHGetSpecialFolderPathW
129
except AttributeError:
132
buf = ctypes.create_unicode_buffer(MAX_PATH)
133
if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
136
appdata = os.environ.get('APPDATA')
139
# if we fall to this point we on win98
140
# at least try C:/WINDOWS/Application Data
141
windir = os.environ.get('windir')
143
appdata = os.path.join(windir, 'Application Data')
144
if os.path.isdir(appdata):
146
# did not find anything
150
def get_home_location():
151
"""Return user's home location.
152
Assume on win32 it's the <My Documents> folder.
153
If location cannot be obtained return system drive root,
156
Returned value can be unicode or plain sring.
157
To convert plain string to unicode use
158
s.decode(osutils.get_user_encoding())
162
SHGetSpecialFolderPath = \
163
ctypes.windll.shell32.SHGetSpecialFolderPathW
164
except AttributeError:
167
buf = ctypes.create_unicode_buffer(MAX_PATH)
168
if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0):
170
# try for HOME env variable
171
home = os.path.expanduser('~')
174
# at least return windows root directory
175
windir = os.environ.get('windir')
177
return os.path.splitdrive(windir)[0] + '/'
178
# otherwise C:\ is good enough for 98% users
183
"""Return user name as login name.
184
If name cannot be obtained return None.
186
Returned value can be unicode or plain sring.
187
To convert plain string to unicode use
188
s.decode(osutils.get_user_encoding())
192
advapi32 = ctypes.windll.advapi32
193
GetUserName = getattr(advapi32, 'GetUserName'+suffix)
194
except AttributeError:
197
buf = create_buffer(UNLEN+1)
198
n = ctypes.c_int(UNLEN+1)
199
if GetUserName(buf, ctypes.byref(n)):
201
# otherwise try env variables
202
return os.environ.get('USERNAME', None)
206
"""Return host machine name.
207
If name cannot be obtained return None.
209
Returned value can be unicode or plain sring.
210
To convert plain string to unicode use
211
s.decode(osutils.get_user_encoding())
215
kernel32 = ctypes.windll.kernel32
216
GetComputerName = getattr(kernel32, 'GetComputerName'+suffix)
217
except AttributeError:
220
buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
221
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
222
if GetComputerName(buf, ctypes.byref(n)):
224
# otherwise try env variables
225
return os.environ.get('COMPUTERNAME', None)
228
def _ensure_unicode(s):
229
if s and type(s) != unicode:
230
s = s.decode(osutils.get_user_encoding())
234
def get_appdata_location_unicode():
235
return _ensure_unicode(get_appdata_location())
237
def get_home_location_unicode():
238
return _ensure_unicode(get_home_location())
240
def get_user_name_unicode():
241
return _ensure_unicode(get_user_name())
243
def get_host_name_unicode():
244
return _ensure_unicode(get_host_name())
247
def _ensure_with_dir(path):
248
if not os.path.split(path)[0] or path.startswith(u'*') or path.startswith(u'?'):
249
return u'./' + path, True
253
def _undo_ensure_with_dir(path, corrected):
261
def glob_expand(file_list):
262
"""Replacement for glob expansion by the shell.
264
Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
267
:param file_list: A list of filenames which may include shell globs.
268
:return: An expanded list of filenames.
270
Introduced in bzrlib 0.18.
275
expanded_file_list = []
276
for possible_glob in file_list:
278
# work around bugs in glob.glob()
279
# - Python bug #1001604 ("glob doesn't return unicode with ...")
280
# - failing expansion for */* with non-iso-8859-* chars
281
possible_glob, corrected = _ensure_with_dir(possible_glob)
282
glob_files = glob.glob(possible_glob)
285
# special case to let the normal code path handle
286
# files that do not exists
287
expanded_file_list.append(
288
_undo_ensure_with_dir(possible_glob, corrected))
290
glob_files = [_undo_ensure_with_dir(elem, corrected) for elem in glob_files]
291
expanded_file_list += glob_files
293
return [elem.replace(u'\\', u'/') for elem in expanded_file_list]
296
def get_app_path(appname):
297
"""Look up in Windows registry for full path to application executable.
298
Typicaly, applications create subkey with their basename
299
in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
301
:param appname: name of application (if no filename extension
302
is specified, .exe used)
303
:return: full path to aplication executable from registry,
304
or appname itself if nothing found.
308
hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
309
r'SOFTWARE\Microsoft\Windows'
310
r'\CurrentVersion\App Paths')
311
except EnvironmentError:
315
if not os.path.splitext(basename)[1]:
316
basename = appname + '.exe'
319
fullpath = _winreg.QueryValue(hkey, basename)
323
_winreg.CloseKey(hkey)
328
def set_file_attr_hidden(path):
329
"""Set file attributes to hidden if possible"""
331
win32file.SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)