~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/win32utils.py

Merge landed readdir acceleration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
75
75
except ImportError:
76
76
    has_win32api = False
77
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...
78
82
 
79
83
# Special Win32 API constants
80
84
# Handles of std streams
84
88
 
85
89
# CSIDL constants (from MSDN 2003)
86
90
CSIDL_APPDATA = 0x001A      # Application Data folder
 
91
CSIDL_LOCAL_APPDATA = 0x001c# <user name>\Local Settings\Application Data (non roaming)
87
92
CSIDL_PERSONAL = 0x0005     # My Documents folder
88
93
 
89
94
# from winapi C headers
119
124
        return (defaultx, defaulty)
120
125
 
121
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
 
122
162
def get_appdata_location():
123
163
    """Return Application Data location.
124
164
    Return None if we cannot obtain location.
125
165
 
126
 
    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.
127
172
    To convert plain string to unicode use
128
173
    s.decode(bzrlib.user_encoding)
 
174
    (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
129
175
    """
130
 
    if has_ctypes:
131
 
        try:
132
 
            SHGetSpecialFolderPath = \
133
 
                ctypes.windll.shell32.SHGetSpecialFolderPathW
134
 
        except AttributeError:
135
 
            pass
136
 
        else:
137
 
            buf = ctypes.create_unicode_buffer(MAX_PATH)
138
 
            if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
139
 
                return buf.value
 
176
    appdata = _get_sh_special_folder_path(CSIDL_APPDATA)
 
177
    if appdata:
 
178
        return appdata
140
179
    # from env variable
141
180
    appdata = os.environ.get('APPDATA')
142
181
    if appdata:
152
191
    return None
153
192
 
154
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
 
155
219
def get_home_location():
156
220
    """Return user's home location.
157
221
    Assume on win32 it's the <My Documents> folder.
162
226
    To convert plain string to unicode use
163
227
    s.decode(bzrlib.user_encoding)
164
228
    """
165
 
    if has_ctypes:
166
 
        try:
167
 
            SHGetSpecialFolderPath = \
168
 
                ctypes.windll.shell32.SHGetSpecialFolderPathW
169
 
        except AttributeError:
170
 
            pass
171
 
        else:
172
 
            buf = ctypes.create_unicode_buffer(MAX_PATH)
173
 
            if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0):
174
 
                return buf.value
 
229
    home = _get_sh_special_folder_path(CSIDL_PERSONAL)
 
230
    if home:
 
231
        return home
175
232
    # try for HOME env variable
176
233
    home = os.path.expanduser('~')
177
234
    if home != '~':