2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
1 |
# Copyright (C) 2006, 2007 Canonical Ltd
|
2 |
#
|
|
3 |
# Author: Alexander Belchenko
|
|
2052.3.1
by John Arbash Meinel
Add tests to cleanup the copyright of all source files |
4 |
#
|
5 |
# This program is free software; you can redistribute it and/or modify
|
|
6 |
# it under the terms of the GNU General Public License as published by
|
|
7 |
# the Free Software Foundation; either version 2 of the License, or
|
|
8 |
# (at your option) any later version.
|
|
9 |
#
|
|
10 |
# This program is distributed in the hope that it will be useful,
|
|
11 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
# GNU General Public License for more details.
|
|
14 |
#
|
|
15 |
# You should have received a copy of the GNU General Public License
|
|
16 |
# along with this program; if not, write to the Free Software
|
|
17 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
19 |
"""Win32-specific helper functions
|
20 |
||
21 |
Only one dependency: ctypes should be installed.
|
|
22 |
"""
|
|
23 |
||
24 |
import os |
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
25 |
import struct |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
26 |
import sys |
27 |
||
28 |
||
29 |
# Windows version
|
|
30 |
if sys.platform == 'win32': |
|
31 |
_major,_minor,_build,_platform,_text = sys.getwindowsversion() |
|
32 |
if _platform == 0: |
|
33 |
raise Exception('This platform does not supported!') |
|
34 |
elif _platform == 1: |
|
35 |
winver = 'Windows 98' |
|
36 |
else: |
|
37 |
winver = 'Windows NT' |
|
38 |
else: |
|
39 |
winver = None |
|
40 |
||
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
41 |
|
1773.4.1
by Martin Pool
Add pyflakes makefile target; fix many warnings |
42 |
# 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 |
43 |
try: |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
44 |
import ctypes |
45 |
has_ctypes = True |
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
46 |
except ImportError: |
1773.4.1
by Martin Pool
Add pyflakes makefile target; fix many warnings |
47 |
has_ctypes = False |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
48 |
else: |
49 |
if winver == 'Windows 98': |
|
50 |
create_buffer = ctypes.create_string_buffer |
|
51 |
suffix = 'A' |
|
52 |
else: |
|
53 |
create_buffer = ctypes.create_unicode_buffer |
|
54 |
suffix = 'W' |
|
55 |
||
56 |
||
57 |
# Special Win32 API constants
|
|
58 |
# Handles of std streams
|
|
1704.2.3
by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander) |
59 |
WIN32_STDIN_HANDLE = -10 |
60 |
WIN32_STDOUT_HANDLE = -11 |
|
61 |
WIN32_STDERR_HANDLE = -12 |
|
62 |
||
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
63 |
# CSIDL constants (from MSDN 2003)
|
64 |
CSIDL_APPDATA = 0x001A # Application Data folder |
|
65 |
CSIDL_PERSONAL = 0x0005 # My Documents folder |
|
66 |
||
67 |
# from winapi C headers
|
|
68 |
MAX_PATH = 260 |
|
69 |
UNLEN = 256 |
|
70 |
MAX_COMPUTERNAME_LENGTH = 31 |
|
71 |
||
1704.2.3
by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander) |
72 |
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
73 |
def get_console_size(defaultx=80, defaulty=25): |
2245.4.1
by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes |
74 |
"""Return size of current console.
|
75 |
||
76 |
This function try to determine actual size of current working
|
|
77 |
console window and return tuple (sizex, sizey) if success,
|
|
78 |
or default size (defaultx, defaulty) otherwise.
|
|
79 |
"""
|
|
80 |
if not has_ctypes: |
|
81 |
# no ctypes is found
|
|
82 |
return (defaultx, defaulty) |
|
83 |
||
84 |
# To avoid problem with redirecting output via pipe
|
|
85 |
# need to use stderr instead of stdout
|
|
86 |
h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE) |
|
87 |
csbi = ctypes.create_string_buffer(22) |
|
88 |
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) |
|
89 |
||
90 |
if res: |
|
91 |
(bufx, bufy, curx, cury, wattr, |
|
1185.16.86
by mbp at sourcefrog
- win32 get_console_size from Alexander |
92 |
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 |
93 |
sizex = right - left + 1 |
94 |
sizey = bottom - top + 1 |
|
95 |
return (sizex, sizey) |
|
96 |
else: |
|
97 |
return (defaultx, defaulty) |
|
98 |
||
99 |
||
100 |
def get_appdata_location(): |
|
101 |
"""Return Application Data location.
|
|
102 |
Return None if we cannot obtain location.
|
|
103 |
||
104 |
Returned value can be unicode or plain sring.
|
|
105 |
To convert plain string to unicode use
|
|
106 |
s.decode(bzrlib.user_encoding)
|
|
107 |
"""
|
|
108 |
if has_ctypes: |
|
109 |
try: |
|
110 |
SHGetSpecialFolderPath = \ |
|
111 |
ctypes.windll.shell32.SHGetSpecialFolderPathW |
|
112 |
except AttributeError: |
|
113 |
pass
|
|
114 |
else: |
|
115 |
buf = ctypes.create_unicode_buffer(MAX_PATH) |
|
116 |
if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0): |
|
117 |
return buf.value |
|
118 |
# from env variable
|
|
119 |
appdata = os.environ.get('APPDATA') |
|
120 |
if appdata: |
|
121 |
return appdata |
|
122 |
# if we fall to this point we on win98
|
|
123 |
# at least try C:/WINDOWS/Application Data
|
|
124 |
windir = os.environ.get('windir') |
|
125 |
if windir: |
|
126 |
appdata = os.path.join(windir, 'Application Data') |
|
127 |
if os.path.isdir(appdata): |
|
128 |
return appdata |
|
129 |
# did not find anything
|
|
130 |
return None |
|
131 |
||
132 |
||
133 |
def get_home_location(): |
|
134 |
"""Return user's home location.
|
|
135 |
Assume on win32 it's the <My Documents> folder.
|
|
136 |
If location cannot be obtained return system drive root,
|
|
137 |
i.e. C:\
|
|
138 |
||
139 |
Returned value can be unicode or plain sring.
|
|
140 |
To convert plain string to unicode use
|
|
141 |
s.decode(bzrlib.user_encoding)
|
|
142 |
"""
|
|
143 |
if has_ctypes: |
|
144 |
try: |
|
145 |
SHGetSpecialFolderPath = \ |
|
146 |
ctypes.windll.shell32.SHGetSpecialFolderPathW |
|
147 |
except AttributeError: |
|
148 |
pass
|
|
149 |
else: |
|
150 |
buf = ctypes.create_unicode_buffer(MAX_PATH) |
|
151 |
if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0): |
|
152 |
return buf.value |
|
153 |
# try for HOME env variable
|
|
154 |
home = os.path.expanduser('~') |
|
155 |
if home != '~': |
|
156 |
return home |
|
157 |
# at least return windows root directory
|
|
158 |
windir = os.environ.get('windir') |
|
159 |
if windir: |
|
160 |
return os.path.splitdrive(windir) + '/' |
|
161 |
# otherwise C:\ is good enough for 98% users
|
|
162 |
return 'C:/' |
|
163 |
||
164 |
||
165 |
def get_user_name(): |
|
166 |
"""Return user name as login name.
|
|
167 |
If name cannot be obtained return None.
|
|
168 |
||
169 |
Returned value can be unicode or plain sring.
|
|
170 |
To convert plain string to unicode use
|
|
171 |
s.decode(bzrlib.user_encoding)
|
|
172 |
"""
|
|
173 |
if has_ctypes: |
|
174 |
try: |
|
175 |
advapi32 = ctypes.windll.advapi32 |
|
176 |
GetUserName = getattr(advapi32, 'GetUserName'+suffix) |
|
177 |
except AttributeError: |
|
178 |
pass
|
|
179 |
else: |
|
180 |
buf = create_buffer(UNLEN+1) |
|
181 |
n = ctypes.c_int(UNLEN+1) |
|
182 |
if GetUserName(buf, ctypes.byref(n)): |
|
183 |
return buf.value |
|
184 |
# otherwise try env variables
|
|
185 |
return os.environ.get('USERNAME', None) |
|
186 |
||
187 |
||
188 |
def get_host_name(): |
|
189 |
"""Return host machine name.
|
|
190 |
If name cannot be obtained return None.
|
|
191 |
||
192 |
Returned value can be unicode or plain sring.
|
|
193 |
To convert plain string to unicode use
|
|
194 |
s.decode(bzrlib.user_encoding)
|
|
195 |
"""
|
|
196 |
if has_ctypes: |
|
197 |
try: |
|
198 |
kernel32 = ctypes.windll.kernel32 |
|
199 |
GetComputerName = getattr(kernel32, 'GetComputerName'+suffix) |
|
200 |
except AttributeError: |
|
201 |
pass
|
|
202 |
else: |
|
203 |
buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1) |
|
204 |
n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1) |
|
205 |
if GetComputerName(buf, ctypes.byref(n)): |
|
206 |
return buf.value |
|
207 |
# otherwise try env variables
|
|
208 |
return os.environ.get('COMPUTERNAME', None) |
|
209 |
||
210 |
||
211 |
def _ensure_unicode(s): |
|
212 |
if s and type(s) != unicode: |
|
213 |
import bzrlib |
|
214 |
s = s.decode(bzrlib.user_encoding) |
|
215 |
return s |
|
216 |
||
217 |
||
218 |
def get_appdata_location_unicode(): |
|
219 |
return _ensure_unicode(get_appdata_location()) |
|
220 |
||
221 |
def get_home_location_unicode(): |
|
222 |
return _ensure_unicode(get_home_location()) |
|
223 |
||
224 |
def get_user_name_unicode(): |
|
225 |
return _ensure_unicode(get_user_name()) |
|
226 |
||
227 |
def get_host_name_unicode(): |
|
228 |
return _ensure_unicode(get_host_name()) |