~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/win32utils.py

  • Committer: John Arbash Meinel
  • Date: 2008-10-30 00:55:00 UTC
  • mto: (3815.2.5 prepare-1.9)
  • mto: This revision was merged to the branch mainline in revision 3811.
  • Revision ID: john@arbash-meinel.com-20081030005500-r5cej1cxflqhs3io
Switch so that we are using a simple timestamp as the first action.

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
72
77
 
 
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...
73
82
 
74
83
# Special Win32 API constants
75
84
# Handles of std streams
79
88
 
80
89
# CSIDL constants (from MSDN 2003)
81
90
CSIDL_APPDATA = 0x001A      # Application Data folder
 
91
CSIDL_LOCAL_APPDATA = 0x001c# <user name>\Local Settings\Application Data (non roaming)
82
92
CSIDL_PERSONAL = 0x0005     # My Documents folder
83
93
 
84
94
# from winapi C headers
114
124
        return (defaultx, defaulty)
115
125
 
116
126
 
 
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
 
117
162
def get_appdata_location():
118
163
    """Return Application Data location.
119
164
    Return None if we cannot obtain location.
120
165
 
121
 
    Returned value can be unicode or plain sring.
 
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.
122
172
    To convert plain string to unicode use
123
 
    s.decode(bzrlib.user_encoding)
 
173
    s.decode(osutils.get_user_encoding())
 
174
    (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
124
175
    """
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
 
176
    appdata = _get_sh_special_folder_path(CSIDL_APPDATA)
 
177
    if appdata:
 
178
        return appdata
135
179
    # from env variable
136
180
    appdata = os.environ.get('APPDATA')
137
181
    if appdata:
147
191
    return None
148
192
 
149
193
 
 
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
 
150
219
def get_home_location():
151
220
    """Return user's home location.
152
221
    Assume on win32 it's the <My Documents> folder.
155
224
 
156
225
    Returned value can be unicode or plain sring.
157
226
    To convert plain string to unicode use
158
 
    s.decode(bzrlib.user_encoding)
 
227
    s.decode(osutils.get_user_encoding())
159
228
    """
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
 
229
    home = _get_sh_special_folder_path(CSIDL_PERSONAL)
 
230
    if home:
 
231
        return home
170
232
    # try for HOME env variable
171
233
    home = os.path.expanduser('~')
172
234
    if home != '~':
185
247
 
186
248
    Returned value can be unicode or plain sring.
187
249
    To convert plain string to unicode use
188
 
    s.decode(bzrlib.user_encoding)
 
250
    s.decode(osutils.get_user_encoding())
189
251
    """
190
252
    if has_ctypes:
191
253
        try:
202
264
    return os.environ.get('USERNAME', None)
203
265
 
204
266
 
 
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
 
205
271
def get_host_name():
206
272
    """Return host machine name.
207
273
    If name cannot be obtained return None.
208
274
 
209
 
    Returned value can be unicode or plain sring.
210
 
    To convert plain string to unicode use
211
 
    s.decode(bzrlib.user_encoding)
 
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.
212
277
    """
 
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
213
284
    if has_ctypes:
214
285
        try:
215
286
            kernel32 = ctypes.windll.kernel32
216
 
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix)
217
287
        except AttributeError:
218
 
            pass
 
288
            pass # Missing the module we need
219
289
        else:
220
290
            buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
221
291
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
222
 
            if GetComputerName(buf, ctypes.byref(n)):
223
 
                return buf.value
224
 
    # otherwise try env variables
225
 
    return os.environ.get('COMPUTERNAME', None)
 
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
226
319
 
227
320
 
228
321
def _ensure_unicode(s):
 
322
    from bzrlib import osutils
229
323
    if s and type(s) != unicode:
230
 
        import bzrlib
231
 
        s = s.decode(bzrlib.user_encoding)
 
324
        from bzrlib import osutils
 
325
        s = s.decode(osutils.get_user_encoding())
232
326
    return s
233
 
    
 
327
 
234
328
 
235
329
def get_appdata_location_unicode():
236
330
    return _ensure_unicode(get_appdata_location())