~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/win32utils.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-06-05 04:05:05 UTC
  • mfrom: (3473.1.1 ianc-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20080605040505-i9kqxg2fps2qjdi0
Add the 'alias' command (Tim Penhey)

Show diffs side-by-side

added added

removed removed

Lines of Context:
69
69
    has_win32file = True
70
70
except ImportError:
71
71
    has_win32file = False
72
 
try:
73
 
    import win32api
74
 
    has_win32api = True
75
 
except ImportError:
76
 
    has_win32api = False
77
72
 
78
 
# pulling in win32com.shell is a bit of overhead, and normally we don't need
79
 
# it as ctypes is preferred and common.  lazy_imports and "optional"
80
 
# modules don't work well, so we do our own lazy thing...
81
 
has_win32com_shell = None # Set to True or False once we know for sure...
82
73
 
83
74
# Special Win32 API constants
84
75
# Handles of std streams
88
79
 
89
80
# CSIDL constants (from MSDN 2003)
90
81
CSIDL_APPDATA = 0x001A      # Application Data folder
91
 
CSIDL_LOCAL_APPDATA = 0x001c# <user name>\Local Settings\Application Data (non roaming)
92
82
CSIDL_PERSONAL = 0x0005     # My Documents folder
93
83
 
94
84
# from winapi C headers
124
114
        return (defaultx, defaulty)
125
115
 
126
116
 
127
 
def _get_sh_special_folder_path(csidl):
128
 
    """Call SHGetSpecialFolderPathW if available, or return None.
129
 
    
130
 
    Result is always unicode (or None).
131
 
    """
132
 
    if has_ctypes:
133
 
        try:
134
 
            SHGetSpecialFolderPath = \
135
 
                ctypes.windll.shell32.SHGetSpecialFolderPathW
136
 
        except AttributeError:
137
 
            pass
138
 
        else:
139
 
            buf = ctypes.create_unicode_buffer(MAX_PATH)
140
 
            if SHGetSpecialFolderPath(None,buf,csidl,0):
141
 
                return buf.value
142
 
 
143
 
    global has_win32com_shell
144
 
    if has_win32com_shell is None:
145
 
        try:
146
 
            from win32com.shell import shell
147
 
            has_win32com_shell = True
148
 
        except ImportError:
149
 
            has_win32com_shell = False
150
 
    if has_win32com_shell:
151
 
        # still need to bind the name locally, but this is fast.
152
 
        from win32com.shell import shell
153
 
        try:
154
 
            return shell.SHGetSpecialFolderPath(0, csidl, 0)
155
 
        except shell.error:
156
 
            # possibly E_NOTIMPL meaning we can't load the function pointer,
157
 
            # or E_FAIL meaning the function failed - regardless, just ignore it
158
 
            pass
159
 
    return None
160
 
 
161
 
 
162
117
def get_appdata_location():
163
118
    """Return Application Data location.
164
119
    Return None if we cannot obtain location.
165
120
 
166
 
    Windows defines two 'Application Data' folders per user - a 'roaming'
167
 
    one that moves with the user as they logon to different machines, and
168
 
    a 'local' one that stays local to the machine.  This returns the 'roaming'
169
 
    directory, and thus is suitable for storing user-preferences, etc.
170
 
 
171
 
    Returned value can be unicode or plain string.
 
121
    Returned value can be unicode or plain sring.
172
122
    To convert plain string to unicode use
173
 
    s.decode(osutils.get_user_encoding())
174
 
    (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
 
123
    s.decode(bzrlib.user_encoding)
175
124
    """
176
 
    appdata = _get_sh_special_folder_path(CSIDL_APPDATA)
177
 
    if appdata:
178
 
        return appdata
 
125
    if has_ctypes:
 
126
        try:
 
127
            SHGetSpecialFolderPath = \
 
128
                ctypes.windll.shell32.SHGetSpecialFolderPathW
 
129
        except AttributeError:
 
130
            pass
 
131
        else:
 
132
            buf = ctypes.create_unicode_buffer(MAX_PATH)
 
133
            if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
 
134
                return buf.value
179
135
    # from env variable
180
136
    appdata = os.environ.get('APPDATA')
181
137
    if appdata:
191
147
    return None
192
148
 
193
149
 
194
 
def get_local_appdata_location():
195
 
    """Return Local Application Data location.
196
 
    Return the same as get_appdata_location() if we cannot obtain location.
197
 
 
198
 
    Windows defines two 'Application Data' folders per user - a 'roaming'
199
 
    one that moves with the user as they logon to different machines, and
200
 
    a 'local' one that stays local to the machine.  This returns the 'local'
201
 
    directory, and thus is suitable for caches, temp files and other things
202
 
    which don't need to move with the user.
203
 
 
204
 
    Returned value can be unicode or plain string.
205
 
    To convert plain string to unicode use
206
 
    s.decode(bzrlib.user_encoding)
207
 
    (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
208
 
    """
209
 
    local = _get_sh_special_folder_path(CSIDL_LOCAL_APPDATA)
210
 
    if local:
211
 
        return local
212
 
    # Vista supplies LOCALAPPDATA, but XP and earlier do not.
213
 
    local = os.environ.get('LOCALAPPDATA')
214
 
    if local:
215
 
        return local
216
 
    return get_appdata_location()
217
 
 
218
 
 
219
150
def get_home_location():
220
151
    """Return user's home location.
221
152
    Assume on win32 it's the <My Documents> folder.
224
155
 
225
156
    Returned value can be unicode or plain sring.
226
157
    To convert plain string to unicode use
227
 
    s.decode(osutils.get_user_encoding())
 
158
    s.decode(bzrlib.user_encoding)
228
159
    """
229
 
    home = _get_sh_special_folder_path(CSIDL_PERSONAL)
230
 
    if home:
231
 
        return home
 
160
    if has_ctypes:
 
161
        try:
 
162
            SHGetSpecialFolderPath = \
 
163
                ctypes.windll.shell32.SHGetSpecialFolderPathW
 
164
        except AttributeError:
 
165
            pass
 
166
        else:
 
167
            buf = ctypes.create_unicode_buffer(MAX_PATH)
 
168
            if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0):
 
169
                return buf.value
232
170
    # try for HOME env variable
233
171
    home = os.path.expanduser('~')
234
172
    if home != '~':
247
185
 
248
186
    Returned value can be unicode or plain sring.
249
187
    To convert plain string to unicode use
250
 
    s.decode(osutils.get_user_encoding())
 
188
    s.decode(bzrlib.user_encoding)
251
189
    """
252
190
    if has_ctypes:
253
191
        try:
264
202
    return os.environ.get('USERNAME', None)
265
203
 
266
204
 
267
 
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
268
 
# computer or the cluster associated with the local computer."
269
 
_WIN32_ComputerNameDnsHostname = 1
270
 
 
271
205
def get_host_name():
272
206
    """Return host machine name.
273
207
    If name cannot be obtained return None.
274
208
 
275
 
    :return: A unicode string representing the host name. On win98, this may be
276
 
        a plain string as win32 api doesn't support unicode.
 
209
    Returned value can be unicode or plain sring.
 
210
    To convert plain string to unicode use
 
211
    s.decode(bzrlib.user_encoding)
277
212
    """
278
 
    if has_win32api:
279
 
        try:
280
 
            return win32api.GetComputerNameEx(_WIN32_ComputerNameDnsHostname)
281
 
        except (NotImplementedError, win32api.error):
282
 
            # NotImplemented will happen on win9x...
283
 
            pass
284
213
    if has_ctypes:
285
214
        try:
286
215
            kernel32 = ctypes.windll.kernel32
 
216
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix)
287
217
        except AttributeError:
288
 
            pass # Missing the module we need
 
218
            pass
289
219
        else:
290
220
            buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
291
221
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
292
 
 
293
 
            # Try GetComputerNameEx which gives a proper Unicode hostname
294
 
            GetComputerNameEx = getattr(kernel32, 'GetComputerNameEx'+suffix,
295
 
                                        None)
296
 
            if (GetComputerNameEx is not None
297
 
                and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
298
 
                                      buf, ctypes.byref(n))):
299
 
                return buf.value
300
 
 
301
 
            # Try GetComputerName in case GetComputerNameEx wasn't found
302
 
            # It returns the NETBIOS name, which isn't as good, but still ok.
303
 
            # The first GetComputerNameEx might have changed 'n', so reset it
304
 
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
305
 
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix,
306
 
                                      None)
307
 
            if (GetComputerName is not None
308
 
                and GetComputerName(buf, ctypes.byref(n))):
309
 
                return buf.value
310
 
    # otherwise try env variables, which will be 'mbcs' encoded
311
 
    # on Windows (Python doesn't expose the native win32 unicode environment)
312
 
    # According to this:
313
 
    # http://msdn.microsoft.com/en-us/library/aa246807.aspx
314
 
    # environment variables should always be encoded in 'mbcs'.
315
 
    try:
316
 
        return os.environ['COMPUTERNAME'].decode("mbcs")
317
 
    except KeyError:
318
 
        return None
 
222
            if GetComputerName(buf, ctypes.byref(n)):
 
223
                return buf.value
 
224
    # otherwise try env variables
 
225
    return os.environ.get('COMPUTERNAME', None)
319
226
 
320
227
 
321
228
def _ensure_unicode(s):
322
 
    from bzrlib import osutils
323
229
    if s and type(s) != unicode:
324
 
        from bzrlib import osutils
325
 
        s = s.decode(osutils.get_user_encoding())
 
230
        import bzrlib
 
231
        s = s.decode(bzrlib.user_encoding)
326
232
    return s
327
 
 
 
233
    
328
234
 
329
235
def get_appdata_location_unicode():
330
236
    return _ensure_unicode(get_appdata_location())