1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2009-2014, Mario Vilas
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10#     * Redistributions of source code must retain the above copyright notice,
11#       this list of conditions and the following disclaimer.
12#     * Redistributions in binary form must reproduce the above copyright
13#       notice,this list of conditions and the following disclaimer in the
14#       documentation and/or other materials provided with the distribution.
15#     * Neither the name of the copyright holder nor the names of its
16#       contributors may be used to endorse or promote products derived from
17#       this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29# POSSIBILITY OF SUCH DAMAGE.
30
31"""
32Wrapper for shlwapi.dll in ctypes.
33"""
34
35__revision__ = "$Id$"
36
37from winappdbg.win32.defines import *
38from winappdbg.win32.kernel32 import *
39
40#==============================================================================
41# This is used later on to calculate the list of exported symbols.
42_all = None
43_all = set(vars().keys())
44#==============================================================================
45
46OS_WINDOWS                  = 0
47OS_NT                       = 1
48OS_WIN95ORGREATER           = 2
49OS_NT4ORGREATER             = 3
50OS_WIN98ORGREATER           = 5
51OS_WIN98_GOLD               = 6
52OS_WIN2000ORGREATER         = 7
53OS_WIN2000PRO               = 8
54OS_WIN2000SERVER            = 9
55OS_WIN2000ADVSERVER         = 10
56OS_WIN2000DATACENTER        = 11
57OS_WIN2000TERMINAL          = 12
58OS_EMBEDDED                 = 13
59OS_TERMINALCLIENT           = 14
60OS_TERMINALREMOTEADMIN      = 15
61OS_WIN95_GOLD               = 16
62OS_MEORGREATER              = 17
63OS_XPORGREATER              = 18
64OS_HOME                     = 19
65OS_PROFESSIONAL             = 20
66OS_DATACENTER               = 21
67OS_ADVSERVER                = 22
68OS_SERVER                   = 23
69OS_TERMINALSERVER           = 24
70OS_PERSONALTERMINALSERVER   = 25
71OS_FASTUSERSWITCHING        = 26
72OS_WELCOMELOGONUI           = 27
73OS_DOMAINMEMBER             = 28
74OS_ANYSERVER                = 29
75OS_WOW6432                  = 30
76OS_WEBSERVER                = 31
77OS_SMALLBUSINESSSERVER      = 32
78OS_TABLETPC                 = 33
79OS_SERVERADMINUI            = 34
80OS_MEDIACENTER              = 35
81OS_APPLIANCE                = 36
82
83#--- shlwapi.dll --------------------------------------------------------------
84
85# BOOL IsOS(
86#     DWORD dwOS
87# );
88def IsOS(dwOS):
89    try:
90        _IsOS = windll.shlwapi.IsOS
91        _IsOS.argtypes = [DWORD]
92        _IsOS.restype  = bool
93    except AttributeError:
94        # According to MSDN, on Windows versions prior to Vista
95        # this function is exported only by ordinal number 437.
96        # http://msdn.microsoft.com/en-us/library/bb773795%28VS.85%29.aspx
97        _GetProcAddress = windll.kernel32.GetProcAddress
98        _GetProcAddress.argtypes = [HINSTANCE, DWORD]
99        _GetProcAddress.restype  = LPVOID
100        _IsOS = windll.kernel32.GetProcAddress(windll.shlwapi._handle, 437)
101        _IsOS = WINFUNCTYPE(bool, DWORD)(_IsOS)
102    return _IsOS(dwOS)
103
104# LPTSTR PathAddBackslash(
105#     LPTSTR lpszPath
106# );
107def PathAddBackslashA(lpszPath):
108    _PathAddBackslashA = windll.shlwapi.PathAddBackslashA
109    _PathAddBackslashA.argtypes = [LPSTR]
110    _PathAddBackslashA.restype  = LPSTR
111
112    lpszPath = ctypes.create_string_buffer(lpszPath, MAX_PATH)
113    retval = _PathAddBackslashA(lpszPath)
114    if retval == NULL:
115        raise ctypes.WinError()
116    return lpszPath.value
117
118def PathAddBackslashW(lpszPath):
119    _PathAddBackslashW = windll.shlwapi.PathAddBackslashW
120    _PathAddBackslashW.argtypes = [LPWSTR]
121    _PathAddBackslashW.restype  = LPWSTR
122
123    lpszPath = ctypes.create_unicode_buffer(lpszPath, MAX_PATH)
124    retval = _PathAddBackslashW(lpszPath)
125    if retval == NULL:
126        raise ctypes.WinError()
127    return lpszPath.value
128
129PathAddBackslash = GuessStringType(PathAddBackslashA, PathAddBackslashW)
130
131# BOOL PathAddExtension(
132#     LPTSTR pszPath,
133#     LPCTSTR pszExtension
134# );
135def PathAddExtensionA(lpszPath, pszExtension = None):
136    _PathAddExtensionA = windll.shlwapi.PathAddExtensionA
137    _PathAddExtensionA.argtypes = [LPSTR, LPSTR]
138    _PathAddExtensionA.restype  = bool
139    _PathAddExtensionA.errcheck = RaiseIfZero
140
141    if not pszExtension:
142        pszExtension = None
143    lpszPath = ctypes.create_string_buffer(lpszPath, MAX_PATH)
144    _PathAddExtensionA(lpszPath, pszExtension)
145    return lpszPath.value
146
147def PathAddExtensionW(lpszPath, pszExtension = None):
148    _PathAddExtensionW = windll.shlwapi.PathAddExtensionW
149    _PathAddExtensionW.argtypes = [LPWSTR, LPWSTR]
150    _PathAddExtensionW.restype  = bool
151    _PathAddExtensionW.errcheck = RaiseIfZero
152
153    if not pszExtension:
154        pszExtension = None
155    lpszPath = ctypes.create_unicode_buffer(lpszPath, MAX_PATH)
156    _PathAddExtensionW(lpszPath, pszExtension)
157    return lpszPath.value
158
159PathAddExtension = GuessStringType(PathAddExtensionA, PathAddExtensionW)
160
161# BOOL PathAppend(
162#     LPTSTR pszPath,
163#     LPCTSTR pszMore
164# );
165def PathAppendA(lpszPath, pszMore = None):
166    _PathAppendA = windll.shlwapi.PathAppendA
167    _PathAppendA.argtypes = [LPSTR, LPSTR]
168    _PathAppendA.restype  = bool
169    _PathAppendA.errcheck = RaiseIfZero
170
171    if not pszMore:
172        pszMore = None
173    lpszPath = ctypes.create_string_buffer(lpszPath, MAX_PATH)
174    _PathAppendA(lpszPath, pszMore)
175    return lpszPath.value
176
177def PathAppendW(lpszPath, pszMore = None):
178    _PathAppendW = windll.shlwapi.PathAppendW
179    _PathAppendW.argtypes = [LPWSTR, LPWSTR]
180    _PathAppendW.restype  = bool
181    _PathAppendW.errcheck = RaiseIfZero
182
183    if not pszMore:
184        pszMore = None
185    lpszPath = ctypes.create_unicode_buffer(lpszPath, MAX_PATH)
186    _PathAppendW(lpszPath, pszMore)
187    return lpszPath.value
188
189PathAppend = GuessStringType(PathAppendA, PathAppendW)
190
191# LPTSTR PathCombine(
192#     LPTSTR lpszDest,
193#     LPCTSTR lpszDir,
194#     LPCTSTR lpszFile
195# );
196def PathCombineA(lpszDir, lpszFile):
197    _PathCombineA = windll.shlwapi.PathCombineA
198    _PathCombineA.argtypes = [LPSTR, LPSTR, LPSTR]
199    _PathCombineA.restype  = LPSTR
200
201    lpszDest = ctypes.create_string_buffer("", max(MAX_PATH, len(lpszDir) + len(lpszFile) + 1))
202    retval = _PathCombineA(lpszDest, lpszDir, lpszFile)
203    if retval == NULL:
204        return None
205    return lpszDest.value
206
207def PathCombineW(lpszDir, lpszFile):
208    _PathCombineW = windll.shlwapi.PathCombineW
209    _PathCombineW.argtypes = [LPWSTR, LPWSTR, LPWSTR]
210    _PathCombineW.restype  = LPWSTR
211
212    lpszDest = ctypes.create_unicode_buffer(u"", max(MAX_PATH, len(lpszDir) + len(lpszFile) + 1))
213    retval = _PathCombineW(lpszDest, lpszDir, lpszFile)
214    if retval == NULL:
215        return None
216    return lpszDest.value
217
218PathCombine = GuessStringType(PathCombineA, PathCombineW)
219
220# BOOL PathCanonicalize(
221#     LPTSTR lpszDst,
222#     LPCTSTR lpszSrc
223# );
224def PathCanonicalizeA(lpszSrc):
225    _PathCanonicalizeA = windll.shlwapi.PathCanonicalizeA
226    _PathCanonicalizeA.argtypes = [LPSTR, LPSTR]
227    _PathCanonicalizeA.restype  = bool
228    _PathCanonicalizeA.errcheck = RaiseIfZero
229
230    lpszDst = ctypes.create_string_buffer("", MAX_PATH)
231    _PathCanonicalizeA(lpszDst, lpszSrc)
232    return lpszDst.value
233
234def PathCanonicalizeW(lpszSrc):
235    _PathCanonicalizeW = windll.shlwapi.PathCanonicalizeW
236    _PathCanonicalizeW.argtypes = [LPWSTR, LPWSTR]
237    _PathCanonicalizeW.restype  = bool
238    _PathCanonicalizeW.errcheck = RaiseIfZero
239
240    lpszDst = ctypes.create_unicode_buffer(u"", MAX_PATH)
241    _PathCanonicalizeW(lpszDst, lpszSrc)
242    return lpszDst.value
243
244PathCanonicalize = GuessStringType(PathCanonicalizeA, PathCanonicalizeW)
245
246# BOOL PathRelativePathTo(
247#   _Out_  LPTSTR pszPath,
248#   _In_   LPCTSTR pszFrom,
249#   _In_   DWORD dwAttrFrom,
250#   _In_   LPCTSTR pszTo,
251#   _In_   DWORD dwAttrTo
252# );
253def PathRelativePathToA(pszFrom = None, dwAttrFrom = FILE_ATTRIBUTE_DIRECTORY, pszTo = None, dwAttrTo = FILE_ATTRIBUTE_DIRECTORY):
254    _PathRelativePathToA = windll.shlwapi.PathRelativePathToA
255    _PathRelativePathToA.argtypes = [LPSTR, LPSTR, DWORD, LPSTR, DWORD]
256    _PathRelativePathToA.restype  = bool
257    _PathRelativePathToA.errcheck = RaiseIfZero
258
259    # Make the paths absolute or the function fails.
260    if pszFrom:
261        pszFrom = GetFullPathNameA(pszFrom)[0]
262    else:
263        pszFrom = GetCurrentDirectoryA()
264    if pszTo:
265        pszTo = GetFullPathNameA(pszTo)[0]
266    else:
267        pszTo = GetCurrentDirectoryA()
268
269    # Argh, this function doesn't receive an output buffer size!
270    # We'll try to guess the maximum possible buffer size.
271    dwPath = max((len(pszFrom) + len(pszTo)) * 2 + 1, MAX_PATH + 1)
272    pszPath = ctypes.create_string_buffer('', dwPath)
273
274    # Also, it doesn't set the last error value.
275    # Whoever coded it must have been drunk or tripping on acid. Or both.
276    # The only failure conditions I've seen were invalid paths, paths not
277    # on the same drive, or the path is not absolute.
278    SetLastError(ERROR_INVALID_PARAMETER)
279
280    _PathRelativePathToA(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo)
281    return pszPath.value
282
283def PathRelativePathToW(pszFrom = None, dwAttrFrom = FILE_ATTRIBUTE_DIRECTORY, pszTo = None, dwAttrTo = FILE_ATTRIBUTE_DIRECTORY):
284    _PathRelativePathToW = windll.shlwapi.PathRelativePathToW
285    _PathRelativePathToW.argtypes = [LPWSTR, LPWSTR, DWORD, LPWSTR, DWORD]
286    _PathRelativePathToW.restype  = bool
287    _PathRelativePathToW.errcheck = RaiseIfZero
288
289    # Refer to PathRelativePathToA to know why this code is so ugly.
290    if pszFrom:
291        pszFrom = GetFullPathNameW(pszFrom)[0]
292    else:
293        pszFrom = GetCurrentDirectoryW()
294    if pszTo:
295        pszTo = GetFullPathNameW(pszTo)[0]
296    else:
297        pszTo = GetCurrentDirectoryW()
298    dwPath = max((len(pszFrom) + len(pszTo)) * 2 + 1, MAX_PATH + 1)
299    pszPath = ctypes.create_unicode_buffer(u'', dwPath)
300    SetLastError(ERROR_INVALID_PARAMETER)
301    _PathRelativePathToW(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo)
302    return pszPath.value
303
304PathRelativePathTo = GuessStringType(PathRelativePathToA, PathRelativePathToW)
305
306# BOOL PathFileExists(
307#     LPCTSTR pszPath
308# );
309def PathFileExistsA(pszPath):
310    _PathFileExistsA = windll.shlwapi.PathFileExistsA
311    _PathFileExistsA.argtypes = [LPSTR]
312    _PathFileExistsA.restype  = bool
313    return _PathFileExistsA(pszPath)
314
315def PathFileExistsW(pszPath):
316    _PathFileExistsW = windll.shlwapi.PathFileExistsW
317    _PathFileExistsW.argtypes = [LPWSTR]
318    _PathFileExistsW.restype  = bool
319    return _PathFileExistsW(pszPath)
320
321PathFileExists = GuessStringType(PathFileExistsA, PathFileExistsW)
322
323# LPTSTR PathFindExtension(
324#     LPCTSTR pszPath
325# );
326def PathFindExtensionA(pszPath):
327    _PathFindExtensionA = windll.shlwapi.PathFindExtensionA
328    _PathFindExtensionA.argtypes = [LPSTR]
329    _PathFindExtensionA.restype  = LPSTR
330    pszPath = ctypes.create_string_buffer(pszPath)
331    return _PathFindExtensionA(pszPath)
332
333def PathFindExtensionW(pszPath):
334    _PathFindExtensionW = windll.shlwapi.PathFindExtensionW
335    _PathFindExtensionW.argtypes = [LPWSTR]
336    _PathFindExtensionW.restype  = LPWSTR
337    pszPath = ctypes.create_unicode_buffer(pszPath)
338    return _PathFindExtensionW(pszPath)
339
340PathFindExtension = GuessStringType(PathFindExtensionA, PathFindExtensionW)
341
342# LPTSTR PathFindFileName(
343#     LPCTSTR pszPath
344# );
345def PathFindFileNameA(pszPath):
346    _PathFindFileNameA = windll.shlwapi.PathFindFileNameA
347    _PathFindFileNameA.argtypes = [LPSTR]
348    _PathFindFileNameA.restype  = LPSTR
349    pszPath = ctypes.create_string_buffer(pszPath)
350    return _PathFindFileNameA(pszPath)
351
352def PathFindFileNameW(pszPath):
353    _PathFindFileNameW = windll.shlwapi.PathFindFileNameW
354    _PathFindFileNameW.argtypes = [LPWSTR]
355    _PathFindFileNameW.restype  = LPWSTR
356    pszPath = ctypes.create_unicode_buffer(pszPath)
357    return _PathFindFileNameW(pszPath)
358
359PathFindFileName = GuessStringType(PathFindFileNameA, PathFindFileNameW)
360
361# LPTSTR PathFindNextComponent(
362#     LPCTSTR pszPath
363# );
364def PathFindNextComponentA(pszPath):
365    _PathFindNextComponentA = windll.shlwapi.PathFindNextComponentA
366    _PathFindNextComponentA.argtypes = [LPSTR]
367    _PathFindNextComponentA.restype  = LPSTR
368    pszPath = ctypes.create_string_buffer(pszPath)
369    return _PathFindNextComponentA(pszPath)
370
371def PathFindNextComponentW(pszPath):
372    _PathFindNextComponentW = windll.shlwapi.PathFindNextComponentW
373    _PathFindNextComponentW.argtypes = [LPWSTR]
374    _PathFindNextComponentW.restype  = LPWSTR
375    pszPath = ctypes.create_unicode_buffer(pszPath)
376    return _PathFindNextComponentW(pszPath)
377
378PathFindNextComponent = GuessStringType(PathFindNextComponentA, PathFindNextComponentW)
379
380# BOOL PathFindOnPath(
381#     LPTSTR pszFile,
382#     LPCTSTR *ppszOtherDirs
383# );
384def PathFindOnPathA(pszFile, ppszOtherDirs = None):
385    _PathFindOnPathA = windll.shlwapi.PathFindOnPathA
386    _PathFindOnPathA.argtypes = [LPSTR, LPSTR]
387    _PathFindOnPathA.restype  = bool
388
389    pszFile = ctypes.create_string_buffer(pszFile, MAX_PATH)
390    if not ppszOtherDirs:
391        ppszOtherDirs = None
392    else:
393        szArray = ""
394        for pszOtherDirs in ppszOtherDirs:
395            if pszOtherDirs:
396                szArray = "%s%s\0" % (szArray, pszOtherDirs)
397        szArray = szArray + "\0"
398        pszOtherDirs = ctypes.create_string_buffer(szArray)
399        ppszOtherDirs = ctypes.pointer(pszOtherDirs)
400    if _PathFindOnPathA(pszFile, ppszOtherDirs):
401        return pszFile.value
402    return None
403
404def PathFindOnPathW(pszFile, ppszOtherDirs = None):
405    _PathFindOnPathW = windll.shlwapi.PathFindOnPathA
406    _PathFindOnPathW.argtypes = [LPWSTR, LPWSTR]
407    _PathFindOnPathW.restype  = bool
408
409    pszFile = ctypes.create_unicode_buffer(pszFile, MAX_PATH)
410    if not ppszOtherDirs:
411        ppszOtherDirs = None
412    else:
413        szArray = u""
414        for pszOtherDirs in ppszOtherDirs:
415            if pszOtherDirs:
416                szArray = u"%s%s\0" % (szArray, pszOtherDirs)
417        szArray = szArray + u"\0"
418        pszOtherDirs = ctypes.create_unicode_buffer(szArray)
419        ppszOtherDirs = ctypes.pointer(pszOtherDirs)
420    if _PathFindOnPathW(pszFile, ppszOtherDirs):
421        return pszFile.value
422    return None
423
424PathFindOnPath = GuessStringType(PathFindOnPathA, PathFindOnPathW)
425
426# LPTSTR PathGetArgs(
427#     LPCTSTR pszPath
428# );
429def PathGetArgsA(pszPath):
430    _PathGetArgsA = windll.shlwapi.PathGetArgsA
431    _PathGetArgsA.argtypes = [LPSTR]
432    _PathGetArgsA.restype  = LPSTR
433    pszPath = ctypes.create_string_buffer(pszPath)
434    return _PathGetArgsA(pszPath)
435
436def PathGetArgsW(pszPath):
437    _PathGetArgsW = windll.shlwapi.PathGetArgsW
438    _PathGetArgsW.argtypes = [LPWSTR]
439    _PathGetArgsW.restype  = LPWSTR
440    pszPath = ctypes.create_unicode_buffer(pszPath)
441    return _PathGetArgsW(pszPath)
442
443PathGetArgs = GuessStringType(PathGetArgsA, PathGetArgsW)
444
445# BOOL PathIsContentType(
446#     LPCTSTR pszPath,
447#     LPCTSTR pszContentType
448# );
449def PathIsContentTypeA(pszPath, pszContentType):
450    _PathIsContentTypeA = windll.shlwapi.PathIsContentTypeA
451    _PathIsContentTypeA.argtypes = [LPSTR, LPSTR]
452    _PathIsContentTypeA.restype  = bool
453    return _PathIsContentTypeA(pszPath, pszContentType)
454
455def PathIsContentTypeW(pszPath, pszContentType):
456    _PathIsContentTypeW = windll.shlwapi.PathIsContentTypeW
457    _PathIsContentTypeW.argtypes = [LPWSTR, LPWSTR]
458    _PathIsContentTypeW.restype  = bool
459    return _PathIsContentTypeW(pszPath, pszContentType)
460
461PathIsContentType = GuessStringType(PathIsContentTypeA, PathIsContentTypeW)
462
463# BOOL PathIsDirectory(
464#     LPCTSTR pszPath
465# );
466def PathIsDirectoryA(pszPath):
467    _PathIsDirectoryA = windll.shlwapi.PathIsDirectoryA
468    _PathIsDirectoryA.argtypes = [LPSTR]
469    _PathIsDirectoryA.restype  = bool
470    return _PathIsDirectoryA(pszPath)
471
472def PathIsDirectoryW(pszPath):
473    _PathIsDirectoryW = windll.shlwapi.PathIsDirectoryW
474    _PathIsDirectoryW.argtypes = [LPWSTR]
475    _PathIsDirectoryW.restype  = bool
476    return _PathIsDirectoryW(pszPath)
477
478PathIsDirectory = GuessStringType(PathIsDirectoryA, PathIsDirectoryW)
479
480# BOOL PathIsDirectoryEmpty(
481#     LPCTSTR pszPath
482# );
483def PathIsDirectoryEmptyA(pszPath):
484    _PathIsDirectoryEmptyA = windll.shlwapi.PathIsDirectoryEmptyA
485    _PathIsDirectoryEmptyA.argtypes = [LPSTR]
486    _PathIsDirectoryEmptyA.restype  = bool
487    return _PathIsDirectoryEmptyA(pszPath)
488
489def PathIsDirectoryEmptyW(pszPath):
490    _PathIsDirectoryEmptyW = windll.shlwapi.PathIsDirectoryEmptyW
491    _PathIsDirectoryEmptyW.argtypes = [LPWSTR]
492    _PathIsDirectoryEmptyW.restype  = bool
493    return _PathIsDirectoryEmptyW(pszPath)
494
495PathIsDirectoryEmpty = GuessStringType(PathIsDirectoryEmptyA, PathIsDirectoryEmptyW)
496
497# BOOL PathIsNetworkPath(
498#     LPCTSTR pszPath
499# );
500def PathIsNetworkPathA(pszPath):
501    _PathIsNetworkPathA = windll.shlwapi.PathIsNetworkPathA
502    _PathIsNetworkPathA.argtypes = [LPSTR]
503    _PathIsNetworkPathA.restype  = bool
504    return _PathIsNetworkPathA(pszPath)
505
506def PathIsNetworkPathW(pszPath):
507    _PathIsNetworkPathW = windll.shlwapi.PathIsNetworkPathW
508    _PathIsNetworkPathW.argtypes = [LPWSTR]
509    _PathIsNetworkPathW.restype  = bool
510    return _PathIsNetworkPathW(pszPath)
511
512PathIsNetworkPath = GuessStringType(PathIsNetworkPathA, PathIsNetworkPathW)
513
514# BOOL PathIsRelative(
515#     LPCTSTR lpszPath
516# );
517def PathIsRelativeA(pszPath):
518    _PathIsRelativeA = windll.shlwapi.PathIsRelativeA
519    _PathIsRelativeA.argtypes = [LPSTR]
520    _PathIsRelativeA.restype  = bool
521    return _PathIsRelativeA(pszPath)
522
523def PathIsRelativeW(pszPath):
524    _PathIsRelativeW = windll.shlwapi.PathIsRelativeW
525    _PathIsRelativeW.argtypes = [LPWSTR]
526    _PathIsRelativeW.restype  = bool
527    return _PathIsRelativeW(pszPath)
528
529PathIsRelative = GuessStringType(PathIsRelativeA, PathIsRelativeW)
530
531# BOOL PathIsRoot(
532#     LPCTSTR pPath
533# );
534def PathIsRootA(pszPath):
535    _PathIsRootA = windll.shlwapi.PathIsRootA
536    _PathIsRootA.argtypes = [LPSTR]
537    _PathIsRootA.restype  = bool
538    return _PathIsRootA(pszPath)
539
540def PathIsRootW(pszPath):
541    _PathIsRootW = windll.shlwapi.PathIsRootW
542    _PathIsRootW.argtypes = [LPWSTR]
543    _PathIsRootW.restype  = bool
544    return _PathIsRootW(pszPath)
545
546PathIsRoot = GuessStringType(PathIsRootA, PathIsRootW)
547
548# BOOL PathIsSameRoot(
549#     LPCTSTR pszPath1,
550#     LPCTSTR pszPath2
551# );
552def PathIsSameRootA(pszPath1, pszPath2):
553    _PathIsSameRootA = windll.shlwapi.PathIsSameRootA
554    _PathIsSameRootA.argtypes = [LPSTR, LPSTR]
555    _PathIsSameRootA.restype  = bool
556    return _PathIsSameRootA(pszPath1, pszPath2)
557
558def PathIsSameRootW(pszPath1, pszPath2):
559    _PathIsSameRootW = windll.shlwapi.PathIsSameRootW
560    _PathIsSameRootW.argtypes = [LPWSTR, LPWSTR]
561    _PathIsSameRootW.restype  = bool
562    return _PathIsSameRootW(pszPath1, pszPath2)
563
564PathIsSameRoot = GuessStringType(PathIsSameRootA, PathIsSameRootW)
565
566# BOOL PathIsUNC(
567#     LPCTSTR pszPath
568# );
569def PathIsUNCA(pszPath):
570    _PathIsUNCA = windll.shlwapi.PathIsUNCA
571    _PathIsUNCA.argtypes = [LPSTR]
572    _PathIsUNCA.restype  = bool
573    return _PathIsUNCA(pszPath)
574
575def PathIsUNCW(pszPath):
576    _PathIsUNCW = windll.shlwapi.PathIsUNCW
577    _PathIsUNCW.argtypes = [LPWSTR]
578    _PathIsUNCW.restype  = bool
579    return _PathIsUNCW(pszPath)
580
581PathIsUNC = GuessStringType(PathIsUNCA, PathIsUNCW)
582
583# XXX WARNING
584# PathMakePretty turns filenames into all lowercase.
585# I'm not sure how well that might work on Wine.
586
587# BOOL PathMakePretty(
588#     LPCTSTR pszPath
589# );
590def PathMakePrettyA(pszPath):
591    _PathMakePrettyA = windll.shlwapi.PathMakePrettyA
592    _PathMakePrettyA.argtypes = [LPSTR]
593    _PathMakePrettyA.restype  = bool
594    _PathMakePrettyA.errcheck = RaiseIfZero
595
596    pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH)
597    _PathMakePrettyA(pszPath)
598    return pszPath.value
599
600def PathMakePrettyW(pszPath):
601    _PathMakePrettyW = windll.shlwapi.PathMakePrettyW
602    _PathMakePrettyW.argtypes = [LPWSTR]
603    _PathMakePrettyW.restype  = bool
604    _PathMakePrettyW.errcheck = RaiseIfZero
605
606    pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH)
607    _PathMakePrettyW(pszPath)
608    return pszPath.value
609
610PathMakePretty = GuessStringType(PathMakePrettyA, PathMakePrettyW)
611
612# void PathRemoveArgs(
613#     LPTSTR pszPath
614# );
615def PathRemoveArgsA(pszPath):
616    _PathRemoveArgsA = windll.shlwapi.PathRemoveArgsA
617    _PathRemoveArgsA.argtypes = [LPSTR]
618
619    pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH)
620    _PathRemoveArgsA(pszPath)
621    return pszPath.value
622
623def PathRemoveArgsW(pszPath):
624    _PathRemoveArgsW = windll.shlwapi.PathRemoveArgsW
625    _PathRemoveArgsW.argtypes = [LPWSTR]
626
627    pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH)
628    _PathRemoveArgsW(pszPath)
629    return pszPath.value
630
631PathRemoveArgs = GuessStringType(PathRemoveArgsA, PathRemoveArgsW)
632
633# void PathRemoveBackslash(
634#     LPTSTR pszPath
635# );
636def PathRemoveBackslashA(pszPath):
637    _PathRemoveBackslashA = windll.shlwapi.PathRemoveBackslashA
638    _PathRemoveBackslashA.argtypes = [LPSTR]
639
640    pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH)
641    _PathRemoveBackslashA(pszPath)
642    return pszPath.value
643
644def PathRemoveBackslashW(pszPath):
645    _PathRemoveBackslashW = windll.shlwapi.PathRemoveBackslashW
646    _PathRemoveBackslashW.argtypes = [LPWSTR]
647
648    pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH)
649    _PathRemoveBackslashW(pszPath)
650    return pszPath.value
651
652PathRemoveBackslash = GuessStringType(PathRemoveBackslashA, PathRemoveBackslashW)
653
654# void PathRemoveExtension(
655#     LPTSTR pszPath
656# );
657def PathRemoveExtensionA(pszPath):
658    _PathRemoveExtensionA = windll.shlwapi.PathRemoveExtensionA
659    _PathRemoveExtensionA.argtypes = [LPSTR]
660
661    pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH)
662    _PathRemoveExtensionA(pszPath)
663    return pszPath.value
664
665def PathRemoveExtensionW(pszPath):
666    _PathRemoveExtensionW = windll.shlwapi.PathRemoveExtensionW
667    _PathRemoveExtensionW.argtypes = [LPWSTR]
668
669    pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH)
670    _PathRemoveExtensionW(pszPath)
671    return pszPath.value
672
673PathRemoveExtension = GuessStringType(PathRemoveExtensionA, PathRemoveExtensionW)
674
675# void PathRemoveFileSpec(
676#     LPTSTR pszPath
677# );
678def PathRemoveFileSpecA(pszPath):
679    _PathRemoveFileSpecA = windll.shlwapi.PathRemoveFileSpecA
680    _PathRemoveFileSpecA.argtypes = [LPSTR]
681
682    pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH)
683    _PathRemoveFileSpecA(pszPath)
684    return pszPath.value
685
686def PathRemoveFileSpecW(pszPath):
687    _PathRemoveFileSpecW = windll.shlwapi.PathRemoveFileSpecW
688    _PathRemoveFileSpecW.argtypes = [LPWSTR]
689
690    pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH)
691    _PathRemoveFileSpecW(pszPath)
692    return pszPath.value
693
694PathRemoveFileSpec = GuessStringType(PathRemoveFileSpecA, PathRemoveFileSpecW)
695
696# BOOL PathRenameExtension(
697#     LPTSTR pszPath,
698#     LPCTSTR pszExt
699# );
700def PathRenameExtensionA(pszPath, pszExt):
701    _PathRenameExtensionA = windll.shlwapi.PathRenameExtensionA
702    _PathRenameExtensionA.argtypes = [LPSTR, LPSTR]
703    _PathRenameExtensionA.restype  = bool
704
705    pszPath = ctypes.create_string_buffer(pszPath, MAX_PATH)
706    if _PathRenameExtensionA(pszPath, pszExt):
707        return pszPath.value
708    return None
709
710def PathRenameExtensionW(pszPath, pszExt):
711    _PathRenameExtensionW = windll.shlwapi.PathRenameExtensionW
712    _PathRenameExtensionW.argtypes = [LPWSTR, LPWSTR]
713    _PathRenameExtensionW.restype  = bool
714
715    pszPath = ctypes.create_unicode_buffer(pszPath, MAX_PATH)
716    if _PathRenameExtensionW(pszPath, pszExt):
717        return pszPath.value
718    return None
719
720PathRenameExtension = GuessStringType(PathRenameExtensionA, PathRenameExtensionW)
721
722# BOOL PathUnExpandEnvStrings(
723#     LPCTSTR pszPath,
724#     LPTSTR pszBuf,
725#     UINT cchBuf
726# );
727def PathUnExpandEnvStringsA(pszPath):
728    _PathUnExpandEnvStringsA = windll.shlwapi.PathUnExpandEnvStringsA
729    _PathUnExpandEnvStringsA.argtypes = [LPSTR, LPSTR]
730    _PathUnExpandEnvStringsA.restype  = bool
731    _PathUnExpandEnvStringsA.errcheck = RaiseIfZero
732
733    cchBuf = MAX_PATH
734    pszBuf = ctypes.create_string_buffer("", cchBuf)
735    _PathUnExpandEnvStringsA(pszPath, pszBuf, cchBuf)
736    return pszBuf.value
737
738def PathUnExpandEnvStringsW(pszPath):
739    _PathUnExpandEnvStringsW = windll.shlwapi.PathUnExpandEnvStringsW
740    _PathUnExpandEnvStringsW.argtypes = [LPWSTR, LPWSTR]
741    _PathUnExpandEnvStringsW.restype  = bool
742    _PathUnExpandEnvStringsW.errcheck = RaiseIfZero
743
744    cchBuf = MAX_PATH
745    pszBuf = ctypes.create_unicode_buffer(u"", cchBuf)
746    _PathUnExpandEnvStringsW(pszPath, pszBuf, cchBuf)
747    return pszBuf.value
748
749PathUnExpandEnvStrings = GuessStringType(PathUnExpandEnvStringsA, PathUnExpandEnvStringsW)
750
751#==============================================================================
752# This calculates the list of exported symbols.
753_all = set(vars().keys()).difference(_all)
754__all__ = [_x for _x in _all if not _x.startswith('_')]
755__all__.sort()
756#==============================================================================
757