ReactOS 0.4.17-dev-357-ga8f14ff
path.c
Go to the documentation of this file.
1/*
2 * Path Functions
3 *
4 * Copyright 1999, 2000 Juergen Schmied
5 * Copyright 2001, 2002 Jon Griffiths
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include <stdarg.h>
23#include <string.h>
24#include <stdlib.h>
25
26#include "wine/unicode.h"
27#include "windef.h"
28#include "winbase.h"
29#include "wingdi.h"
30#include "winuser.h"
31#include "winreg.h"
32#include "winternl.h"
33#define NO_SHLWAPI_STREAM
34#include "shlwapi.h"
35#ifdef __REACTOS__
36#include "winnetwk.h"
37#endif
38#include "wine/debug.h"
39
41
42#ifdef __REACTOS__
43
44#include <shlobj.h>
45#include <shlwapi_undoc.h>
46
47int WINAPI IsNetDrive(int drive);
48
49#else
50
51/* Get a function pointer from a DLL handle */
52#define GET_FUNC(func, module, name, fail) \
53 do { \
54 if (!func) { \
55 if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
56 func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
57 if (!func) return fail; \
58 } \
59 } while (0)
60
61/* DLL handles for late bound calls */
63
64/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
67
68#endif /* __REACTOS__ */
69
71
72/*************************************************************************
73 * PathBuildRootA [SHLWAPI.@]
74 *
75 * Create a root drive string (e.g. "A:\") from a drive number.
76 *
77 * PARAMS
78 * lpszPath [O] Destination for the drive string
79 *
80 * RETURNS
81 * lpszPath
82 *
83 * NOTES
84 * If lpszPath is NULL or drive is invalid, nothing is written to lpszPath.
85 */
87{
88 TRACE("(%p,%d)\n", lpszPath, drive);
89
90 if (lpszPath && drive >= 0 && drive < 26)
91 {
92 lpszPath[0] = 'A' + drive;
93 lpszPath[1] = ':';
94 lpszPath[2] = '\\';
95 lpszPath[3] = '\0';
96 }
97 return lpszPath;
98}
99
100/*************************************************************************
101 * PathBuildRootW [SHLWAPI.@]
102 *
103 * See PathBuildRootA.
104 */
106{
107 TRACE("(%p,%d)\n", lpszPath, drive);
108
109 if (lpszPath && drive >= 0 && drive < 26)
110 {
111 lpszPath[0] = 'A' + drive;
112 lpszPath[1] = ':';
113 lpszPath[2] = '\\';
114 lpszPath[3] = '\0';
115 }
116 return lpszPath;
117}
118
119/*************************************************************************
120 * PathRemoveArgsA [SHLWAPI.@]
121 *
122 * Strip space separated arguments from a path.
123 *
124 * PARAMS
125 * lpszPath [I/O] Path to remove arguments from
126 *
127 * RETURNS
128 * Nothing.
129 */
131{
132 TRACE("(%s)\n",debugstr_a(lpszPath));
133
134 if(lpszPath)
135 {
136 LPSTR lpszArgs = PathGetArgsA(lpszPath);
137 if (*lpszArgs)
138 lpszArgs[-1] = '\0';
139 else
140 {
141 LPSTR lpszLastChar = CharPrevA(lpszPath, lpszArgs);
142 if(*lpszLastChar == ' ')
143 *lpszLastChar = '\0';
144 }
145 }
146}
147
148/*************************************************************************
149 * PathRemoveArgsW [SHLWAPI.@]
150 *
151 * See PathRemoveArgsA.
152 */
154{
155 TRACE("(%s)\n",debugstr_w(lpszPath));
156
157 if(lpszPath)
158 {
159 LPWSTR lpszArgs = PathGetArgsW(lpszPath);
160 if (*lpszArgs || (lpszArgs > lpszPath && lpszArgs[-1] == ' '))
161 lpszArgs[-1] = '\0';
162 }
163}
164
165/*************************************************************************
166 * @ [SHLWAPI.4]
167 *
168 * Unicode version of PathFileExistsDefExtA.
169 */
171{
172 static const WCHAR pszExts[][5] = { { '.', 'p', 'i', 'f', 0},
173 { '.', 'c', 'o', 'm', 0},
174 { '.', 'e', 'x', 'e', 0},
175 { '.', 'b', 'a', 't', 0},
176 { '.', 'l', 'n', 'k', 0},
177 { '.', 'c', 'm', 'd', 0},
178 { 0, 0, 0, 0, 0} };
179
180 TRACE("(%s,%ld)\n", debugstr_w(lpszPath), dwWhich);
181
182 if (!lpszPath || PathIsUNCServerW(lpszPath) || PathIsUNCServerShareW(lpszPath))
183 return FALSE;
184
185 if (dwWhich)
186 {
187 LPCWSTR szExt = PathFindExtensionW(lpszPath);
188#ifndef __REACTOS__
189 if (!*szExt || dwWhich & 0x40)
190#else
191 if (!*szExt || dwWhich & WHICH_OPTIONAL)
192#endif
193 {
194 size_t iChoose = 0;
195 int iLen = lstrlenW(lpszPath);
196 if (iLen > (MAX_PATH - 5))
197 return FALSE;
198#ifndef __REACTOS__
199 while ( (dwWhich & 0x1) && pszExts[iChoose][0] )
200#else
201 while (pszExts[iChoose][0])
202#endif
203 {
204#ifdef __REACTOS__
205 if (dwWhich & 0x1)
206 {
208#endif
209 lstrcpyW(lpszPath + iLen, pszExts[iChoose]);
210 if (PathFileExistsW(lpszPath))
211 return TRUE;
212#ifdef __REACTOS__
213 }
214#endif
215 iChoose++;
216 dwWhich >>= 1;
217 }
218 *(lpszPath + iLen) = (WCHAR)'\0';
219 return FALSE;
220 }
221 }
222 return PathFileExistsW(lpszPath);
223}
224
225/*************************************************************************
226 * @ [SHLWAPI.3]
227 *
228 * Determine if a file exists locally and is of an executable type.
229 *
230 * PARAMS
231 * lpszPath [I/O] File to search for
232 * dwWhich [I] Type of executable to search for
233 *
234 * RETURNS
235 * TRUE If the file was found. lpszPath contains the file name.
236 * FALSE Otherwise.
237 *
238 * NOTES
239 * lpszPath is modified in place and must be at least MAX_PATH in length.
240 * If the function returns FALSE, the path is modified to its original state.
241 * If the given path contains an extension or dwWhich is 0, executable
242 * extensions are not checked.
243 *
244 * Ordinals 3-6 are a classic case of MS exposing limited functionality to
245 * users (here through PathFindOnPathA()) and keeping advanced functionality for
246 * their own developers exclusive use. Monopoly, anyone?
247 */
249{
250 BOOL bRet = FALSE;
251
252 TRACE("(%s,%ld)\n", debugstr_a(lpszPath), dwWhich);
253
254 if (lpszPath)
255 {
258 bRet = PathFileExistsDefExtW(szPath, dwWhich);
259 if (bRet)
260 WideCharToMultiByte(CP_ACP,0,szPath,-1,lpszPath,MAX_PATH,0,0);
261 }
262 return bRet;
263}
264
265/*************************************************************************
266 * SHLWAPI_PathFindInOtherDirs
267 *
268 * Internal helper for SHLWAPI_PathFindOnPathExA/W.
269 */
271{
272 static const WCHAR szSystem[] = { 'S','y','s','t','e','m','\0'};
273 static const WCHAR szPath[] = { 'P','A','T','H','\0'};
274 DWORD dwLenPATH;
275 LPCWSTR lpszCurr;
276 WCHAR *lpszPATH;
278
279 TRACE("(%s,%08lx)\n", debugstr_w(lpszFile), dwWhich);
280
281 /* Try system directories */
283 if (!PathAppendW(buff, lpszFile))
284 return FALSE;
285 if (PathFileExistsDefExtW(buff, dwWhich))
286 {
287 lstrcpyW(lpszFile, buff);
288 return TRUE;
289 }
291 if (!PathAppendW(buff, szSystem ) || !PathAppendW(buff, lpszFile))
292 return FALSE;
293 if (PathFileExistsDefExtW(buff, dwWhich))
294 {
295 lstrcpyW(lpszFile, buff);
296 return TRUE;
297 }
299 if (!PathAppendW(buff, lpszFile))
300 return FALSE;
301 if (PathFileExistsDefExtW(buff, dwWhich))
302 {
303 lstrcpyW(lpszFile, buff);
304 return TRUE;
305 }
306 /* Try dirs listed in %PATH% */
308
309 if (!dwLenPATH || !(lpszPATH = malloc((dwLenPATH + 1) * sizeof (WCHAR))))
310 return FALSE;
311
312 GetEnvironmentVariableW(szPath, lpszPATH, dwLenPATH + 1);
313 lpszCurr = lpszPATH;
314 while (lpszCurr)
315 {
316 LPCWSTR lpszEnd = lpszCurr;
317 LPWSTR pBuff = buff;
318
319 while (*lpszEnd == ' ')
320 lpszEnd++;
321 while (*lpszEnd && *lpszEnd != ';')
322 *pBuff++ = *lpszEnd++;
323 *pBuff = '\0';
324
325 if (*lpszEnd)
326 lpszCurr = lpszEnd + 1;
327 else
328 lpszCurr = NULL; /* Last Path, terminate after this */
329
330 if (!PathAppendW(buff, lpszFile))
331 {
332 free(lpszPATH);
333 return FALSE;
334 }
335 if (PathFileExistsDefExtW(buff, dwWhich))
336 {
337 lstrcpyW(lpszFile, buff);
338 free(lpszPATH);
339 return TRUE;
340 }
341 }
342 free(lpszPATH);
343 return FALSE;
344}
345
346/*************************************************************************
347 * @ [SHLWAPI.5]
348 *
349 * Search a range of paths for a specific type of executable.
350 *
351 * PARAMS
352 * lpszFile [I/O] File to search for
353 * lppszOtherDirs [I] Other directories to look in
354 * dwWhich [I] Type of executable to search for
355 *
356 * RETURNS
357 * Success: TRUE. The path to the executable is stored in lpszFile.
358 * Failure: FALSE. The path to the executable is unchanged.
359 */
360BOOL WINAPI PathFindOnPathExA(LPSTR lpszFile,LPCSTR *lppszOtherDirs,DWORD dwWhich)
361{
362 WCHAR szFile[MAX_PATH];
364
365 TRACE("(%s,%p,%08lx)\n", debugstr_a(lpszFile), lppszOtherDirs, dwWhich);
366
367 if (!lpszFile || !PathIsFileSpecA(lpszFile))
368 return FALSE;
369
370 MultiByteToWideChar(CP_ACP,0,lpszFile,-1,szFile,MAX_PATH);
371
372 /* Search provided directories first */
373 if (lppszOtherDirs && *lppszOtherDirs)
374 {
375 WCHAR szOther[MAX_PATH];
376 LPCSTR *lpszOtherPath = lppszOtherDirs;
377
378 while (lpszOtherPath && *lpszOtherPath && (*lpszOtherPath)[0])
379 {
380 MultiByteToWideChar(CP_ACP,0,*lpszOtherPath,-1,szOther,MAX_PATH);
381 PathCombineW(buff, szOther, szFile);
382 if (PathFileExistsDefExtW(buff, dwWhich))
383 {
384 WideCharToMultiByte(CP_ACP,0,buff,-1,lpszFile,MAX_PATH,0,0);
385 return TRUE;
386 }
387 lpszOtherPath++;
388 }
389 }
390 /* Not found, try system and path dirs */
391 if (SHLWAPI_PathFindInOtherDirs(szFile, dwWhich))
392 {
393 WideCharToMultiByte(CP_ACP,0,szFile,-1,lpszFile,MAX_PATH,0,0);
394 return TRUE;
395 }
396 return FALSE;
397}
398
399/*************************************************************************
400 * @ [SHLWAPI.6]
401 *
402 * Unicode version of PathFindOnPathExA.
403 */
404BOOL WINAPI PathFindOnPathExW(LPWSTR lpszFile,LPCWSTR *lppszOtherDirs,DWORD dwWhich)
405{
407
408 TRACE("(%s,%p,%08lx)\n", debugstr_w(lpszFile), lppszOtherDirs, dwWhich);
409
410 if (!lpszFile || !PathIsFileSpecW(lpszFile))
411 return FALSE;
412
413 /* Search provided directories first */
414 if (lppszOtherDirs && *lppszOtherDirs)
415 {
416 LPCWSTR *lpszOtherPath = lppszOtherDirs;
417 while (lpszOtherPath && *lpszOtherPath && (*lpszOtherPath)[0])
418 {
419 PathCombineW(buff, *lpszOtherPath, lpszFile);
420 if (PathFileExistsDefExtW(buff, dwWhich))
421 {
422 lstrcpyW(lpszFile, buff);
423 return TRUE;
424 }
425 lpszOtherPath++;
426 }
427 }
428 /* Not found, try system and path dirs */
429 return SHLWAPI_PathFindInOtherDirs(lpszFile, dwWhich);
430}
431
432/*************************************************************************
433 * PathFindOnPathA [SHLWAPI.@]
434 *
435 * Search a range of paths for an executable.
436 *
437 * PARAMS
438 * lpszFile [I/O] File to search for
439 * lppszOtherDirs [I] Other directories to look in
440 *
441 * RETURNS
442 * Success: TRUE. The path to the executable is stored in lpszFile.
443 * Failure: FALSE. The path to the executable is unchanged.
444 */
445BOOL WINAPI PathFindOnPathA(LPSTR lpszFile, LPCSTR *lppszOtherDirs)
446{
447 TRACE("(%s,%p)\n", debugstr_a(lpszFile), lppszOtherDirs);
448 return PathFindOnPathExA(lpszFile, lppszOtherDirs, 0);
449 }
450
451/*************************************************************************
452 * PathFindOnPathW [SHLWAPI.@]
453 *
454 * See PathFindOnPathA.
455 */
456BOOL WINAPI PathFindOnPathW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs)
457{
458 TRACE("(%s,%p)\n", debugstr_w(lpszFile), lppszOtherDirs);
459 return PathFindOnPathExW(lpszFile,lppszOtherDirs, 0);
460}
461
462/*************************************************************************
463 * PathCompactPathExA [SHLWAPI.@]
464 *
465 * Compact a path into a given number of characters.
466 *
467 * PARAMS
468 * lpszDest [O] Destination for compacted path
469 * lpszPath [I] Source path
470 * cchMax [I] Maximum size of compacted path
471 * dwFlags [I] Reserved
472 *
473 * RETURNS
474 * Success: TRUE. The compacted path is written to lpszDest.
475 * Failure: FALSE. lpszPath is undefined.
476 *
477 * NOTES
478 * If cchMax is given as 0, lpszDest will still be NUL terminated.
479 *
480 * The Win32 version of this function contains a bug: When cchMax == 7,
481 * 8 bytes will be written to lpszDest. This bug is fixed in the Wine
482 * implementation.
483 *
484 * Some relative paths will be different when cchMax == 5 or 6. This occurs
485 * because Win32 will insert a "\" in lpszDest, even if one is
486 * not present in the original path.
487 */
490{
491 BOOL bRet = FALSE;
492
493 TRACE("(%p,%s,%d,0x%08lx)\n", lpszDest, debugstr_a(lpszPath), cchMax, dwFlags);
494
495 if (lpszPath && lpszDest)
496 {
498 WCHAR szDest[MAX_PATH];
499
501 szDest[0] = '\0';
502 bRet = PathCompactPathExW(szDest, szPath, cchMax, dwFlags);
504 }
505 return bRet;
506}
507
508/*************************************************************************
509 * PathCompactPathExW [SHLWAPI.@]
510 *
511 * See PathCompactPathExA.
512 */
515{
516 static const WCHAR szEllipses[] = { '.', '.', '.', '\0' };
517 LPCWSTR lpszFile;
518 DWORD dwLen, dwFileLen = 0;
519
520 TRACE("(%p,%s,%d,0x%08lx)\n", lpszDest, debugstr_w(lpszPath), cchMax, dwFlags);
521
522 if (!lpszPath)
523 return FALSE;
524
525 if (!lpszDest)
526 {
527 WARN("Invalid lpszDest would crash under Win32!\n");
528 return FALSE;
529 }
530
531 *lpszDest = '\0';
532
533 if (cchMax < 2)
534 return TRUE;
535
536 dwLen = lstrlenW(lpszPath) + 1;
537
538 if (dwLen < cchMax)
539 {
540 /* Don't need to compact */
541 memcpy(lpszDest, lpszPath, dwLen * sizeof(WCHAR));
542 return TRUE;
543 }
544
545 /* Path must be compacted to fit into lpszDest */
546 lpszFile = PathFindFileNameW(lpszPath);
547 dwFileLen = lpszPath + dwLen - lpszFile;
548
549 if (dwFileLen == dwLen)
550 {
551 /* No root in psth */
552 if (cchMax <= 4)
553 {
554 while (--cchMax > 0) /* No room left for anything but ellipses */
555 *lpszDest++ = '.';
556 *lpszDest = '\0';
557 return TRUE;
558 }
559 /* Compact the file name with ellipses at the end */
560 cchMax -= 4;
561 memcpy(lpszDest, lpszFile, cchMax * sizeof(WCHAR));
562 lstrcpyW(lpszDest + cchMax, szEllipses);
563 return TRUE;
564 }
565 /* We have a root in the path */
566 lpszFile--; /* Start compacted filename with the path separator */
567 dwFileLen++;
568
569 if (dwFileLen + 3 > cchMax)
570 {
571 /* Compact the file name */
572 if (cchMax <= 4)
573 {
574 while (--cchMax > 0) /* No room left for anything but ellipses */
575 *lpszDest++ = '.';
576 *lpszDest = '\0';
577 return TRUE;
578 }
579 lstrcpyW(lpszDest, szEllipses);
580 lpszDest += 3;
581 cchMax -= 4;
582 *lpszDest++ = *lpszFile++;
583 if (cchMax <= 4)
584 {
585 while (--cchMax > 0) /* No room left for anything but ellipses */
586 *lpszDest++ = '.';
587 *lpszDest = '\0';
588 return TRUE;
589 }
590 cchMax -= 4;
591 memcpy(lpszDest, lpszFile, cchMax * sizeof(WCHAR));
592 lstrcpyW(lpszDest + cchMax, szEllipses);
593 return TRUE;
594 }
595
596 /* Only the root needs to be Compacted */
597 dwLen = cchMax - dwFileLen - 3;
598 memcpy(lpszDest, lpszPath, dwLen * sizeof(WCHAR));
599 lstrcpyW(lpszDest + dwLen, szEllipses);
600 lstrcpyW(lpszDest + dwLen + 3, lpszFile);
601 return TRUE;
602}
603
604/*************************************************************************
605 * PathIsDirectoryA [SHLWAPI.@]
606 *
607 * Determine if a path is a valid directory
608 *
609 * PARAMS
610 * lpszPath [I] Path to check.
611 *
612 * RETURNS
613 * FILE_ATTRIBUTE_DIRECTORY if lpszPath exists and can be read (See Notes)
614 * FALSE if lpszPath is invalid or not a directory.
615 *
616 * NOTES
617 * Although this function is prototyped as returning a BOOL, it returns
618 * FILE_ATTRIBUTE_DIRECTORY for success. This means that code such as:
619 *
620 *| if (PathIsDirectoryA("c:\\windows\\") == TRUE)
621 *| ...
622 *
623 * will always fail.
624 */
626{
627 DWORD dwAttr;
628
629 TRACE("(%s)\n", debugstr_a(lpszPath));
630
631 if (!lpszPath || PathIsUNCServerA(lpszPath))
632 return FALSE;
633
634 if (PathIsUNCServerShareA(lpszPath))
635 {
636#ifdef __REACTOS__
637 LPSTR lpSystem = NULL;
638 BYTE buffer[512] = {0};
639 DWORD cbBuffer = sizeof(buffer);
641 DWORD dwError;
642
643 pNetRes->dwScope = RESOURCE_GLOBALNET;
644 pNetRes->dwType = RESOURCETYPE_ANY;
645 pNetRes->lpRemoteName = (LPSTR)lpszPath;
646
647 dwError = WNetGetResourceInformationA(pNetRes, pNetRes, &cbBuffer, &lpSystem);
648 if (dwError == NO_ERROR && pNetRes->dwDisplayType != RESOURCEDISPLAYTYPE_GENERIC)
649 {
650 return (pNetRes->dwDisplayType == RESOURCEDISPLAYTYPE_SHARE) &&
651 (pNetRes->dwType == RESOURCETYPE_ANY || pNetRes->dwType == RESOURCETYPE_DISK);
652 }
653#else
654 FIXME("UNC Server Share not yet supported - FAILING\n");
655 return FALSE;
656#endif
657 }
658
659 if ((dwAttr = GetFileAttributesA(lpszPath)) == INVALID_FILE_ATTRIBUTES)
660 return FALSE;
661 return dwAttr & FILE_ATTRIBUTE_DIRECTORY;
662}
663
664/*************************************************************************
665 * PathIsDirectoryW [SHLWAPI.@]
666 *
667 * See PathIsDirectoryA.
668 */
670{
671 DWORD dwAttr;
672
673 TRACE("(%s)\n", debugstr_w(lpszPath));
674
675 if (!lpszPath || PathIsUNCServerW(lpszPath))
676 return FALSE;
677
678 if (PathIsUNCServerShareW(lpszPath))
679 {
680#ifdef __REACTOS__
681 LPWSTR lpSystem = NULL;
682 BYTE buffer[1024] = {0};
683 DWORD cbBuffer = sizeof(buffer);
685 DWORD dwError;
686
687 pNetRes->dwScope = RESOURCE_GLOBALNET;
688 pNetRes->dwType = RESOURCETYPE_ANY;
689 pNetRes->lpRemoteName = (LPWSTR)lpszPath;
690
691 dwError = WNetGetResourceInformationW(pNetRes, pNetRes, &cbBuffer, &lpSystem);
692 if (dwError == NO_ERROR && pNetRes->dwDisplayType != RESOURCEDISPLAYTYPE_GENERIC)
693 {
694 return (pNetRes->dwDisplayType == RESOURCEDISPLAYTYPE_SHARE) &&
695 (pNetRes->dwType == RESOURCETYPE_ANY || pNetRes->dwType == RESOURCETYPE_DISK);
696 }
697#else
698 FIXME("UNC Server Share not yet supported - FAILING\n");
699 return FALSE;
700#endif
701 }
702
703 if ((dwAttr = GetFileAttributesW(lpszPath)) == INVALID_FILE_ATTRIBUTES)
704 return FALSE;
705 return dwAttr & FILE_ATTRIBUTE_DIRECTORY;
706}
707
708/*************************************************************************
709 * PathFileExistsAndAttributesA [SHLWAPI.445]
710 *
711 * Determine if a file exists.
712 *
713 * PARAMS
714 * lpszPath [I] Path to check
715 * dwAttr [O] attributes of file
716 *
717 * RETURNS
718 * TRUE If the file exists and is readable
719 * FALSE Otherwise
720 */
722{
723 UINT iPrevErrMode;
724 DWORD dwVal = 0;
725
726 TRACE("(%s %p)\n", debugstr_a(lpszPath), dwAttr);
727
728 if (dwAttr)
729 *dwAttr = INVALID_FILE_ATTRIBUTES;
730
731 if (!lpszPath)
732 return FALSE;
733
734 iPrevErrMode = SetErrorMode(SEM_FAILCRITICALERRORS);
735 dwVal = GetFileAttributesA(lpszPath);
736 SetErrorMode(iPrevErrMode);
737 if (dwAttr)
738 *dwAttr = dwVal;
739 return (dwVal != INVALID_FILE_ATTRIBUTES);
740}
741
742/*************************************************************************
743 * PathFileExistsAndAttributesW [SHLWAPI.446]
744 *
745 * See PathFileExistsA.
746 */
748{
749 UINT iPrevErrMode;
750 DWORD dwVal;
751
752 TRACE("(%s %p)\n", debugstr_w(lpszPath), dwAttr);
753
754 if (!lpszPath)
755 return FALSE;
756
757 iPrevErrMode = SetErrorMode(SEM_FAILCRITICALERRORS);
758 dwVal = GetFileAttributesW(lpszPath);
759 SetErrorMode(iPrevErrMode);
760 if (dwAttr)
761 *dwAttr = dwVal;
762 return (dwVal != INVALID_FILE_ATTRIBUTES);
763}
764
765/*************************************************************************
766 * PathIsContentTypeA [SHLWAPI.@]
767 *
768 * Determine if a file is of a given registered content type.
769 *
770 * PARAMS
771 * lpszPath [I] File to check
772 * lpszContentType [I] Content type to check for
773 *
774 * RETURNS
775 * TRUE If lpszPath is a given registered content type,
776 * FALSE Otherwise.
777 *
778 * NOTES
779 * This function looks up the registered content type for lpszPath. If
780 * a content type is registered, it is compared (case insensitively) to
781 * lpszContentType. Only if this matches does the function succeed.
782 */
784{
785 char buf[MAX_PATH];
786 DWORD size = sizeof(buf);
787 LPCSTR ext;
788
790
791 if(!path) return FALSE;
792 if(!(ext = PathFindExtensionA(path)) || !*ext) return FALSE;
793 if(SHGetValueA(HKEY_CLASSES_ROOT, ext, "Content Type", NULL, buf, &size)) return FALSE;
794 return !lstrcmpiA(content_type, buf);
795}
796
797/*************************************************************************
798 * PathIsContentTypeW [SHLWAPI.@]
799 *
800 * See PathIsContentTypeA.
801 */
802BOOL WINAPI PathIsContentTypeW(LPCWSTR lpszPath, LPCWSTR lpszContentType)
803{
804 static const WCHAR szContentType[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0' };
805 LPCWSTR szExt;
806 DWORD dwDummy;
807 WCHAR szBuff[MAX_PATH];
808
809 TRACE("(%s,%s)\n", debugstr_w(lpszPath), debugstr_w(lpszContentType));
810
811 if (lpszPath && (szExt = PathFindExtensionW(lpszPath)) && *szExt &&
812 !SHGetValueW(HKEY_CLASSES_ROOT, szExt, szContentType,
813 REG_NONE, szBuff, &dwDummy) &&
814 !wcsicmp(lpszContentType, szBuff))
815 {
816 return TRUE;
817 }
818 return FALSE;
819}
820
821/*************************************************************************
822 * PathIsSystemFolderA [SHLWAPI.@]
823 *
824 * Determine if a path or file attributes are a system folder.
825 *
826 * PARAMS
827 * lpszPath [I] Path to check.
828 * dwAttrib [I] Attributes to check, if lpszPath is NULL.
829 *
830 * RETURNS
831 * TRUE If lpszPath or dwAttrib are a system folder.
832 * FALSE If GetFileAttributesA() fails or neither parameter is a system folder.
833 */
835{
836 TRACE("(%s,0x%08lx)\n", debugstr_a(lpszPath), dwAttrib);
837
838 if (lpszPath && *lpszPath)
839 dwAttrib = GetFileAttributesA(lpszPath);
840
841 if (dwAttrib == INVALID_FILE_ATTRIBUTES || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY) ||
843 return FALSE;
844 return TRUE;
845}
846
847/*************************************************************************
848 * PathIsSystemFolderW [SHLWAPI.@]
849 *
850 * See PathIsSystemFolderA.
851 */
853{
854 TRACE("(%s,0x%08lx)\n", debugstr_w(lpszPath), dwAttrib);
855
856 if (lpszPath && *lpszPath)
857 dwAttrib = GetFileAttributesW(lpszPath);
858
859 if (dwAttrib == INVALID_FILE_ATTRIBUTES || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY) ||
861 return FALSE;
862 return TRUE;
863}
864
865/*************************************************************************
866 * PathMakePrettyA [SHLWAPI.@]
867 *
868 * Convert an uppercase DOS filename into lowercase.
869 *
870 * PARAMS
871 * lpszPath [I/O] Path to convert.
872 *
873 * RETURNS
874 * TRUE If the path was an uppercase DOS path and was converted,
875 * FALSE Otherwise.
876 */
878{
879 LPSTR pszIter = lpszPath;
880
881 TRACE("(%s)\n", debugstr_a(lpszPath));
882
883 if (!pszIter)
884 return FALSE;
885
886 if (*pszIter)
887 {
888 do
889 {
890 if (islower(*pszIter) || IsDBCSLeadByte(*pszIter))
891 return FALSE; /* Not DOS path */
892 pszIter++;
893 } while (*pszIter);
894 pszIter = lpszPath + 1;
895 while (*pszIter)
896 {
897 *pszIter = tolower(*pszIter);
898 pszIter++;
899 }
900 }
901 return TRUE;
902}
903
904/*************************************************************************
905 * PathMakePrettyW [SHLWAPI.@]
906 *
907 * See PathMakePrettyA.
908 */
910{
911 LPWSTR pszIter = lpszPath;
912
913 TRACE("(%s)\n", debugstr_w(lpszPath));
914
915 if (!pszIter)
916 return FALSE;
917
918 if (*pszIter)
919 {
920 do
921 {
922 if (iswlower(*pszIter))
923 return FALSE; /* Not DOS path */
924 pszIter++;
925 } while (*pszIter);
926 pszIter = lpszPath + 1;
927 while (*pszIter)
928 {
929 *pszIter = towlower(*pszIter);
930 pszIter++;
931 }
932 }
933 return TRUE;
934}
935
936/*************************************************************************
937 * PathCompactPathA [SHLWAPI.@]
938 *
939 * Make a path fit into a given width when printed to a DC.
940 *
941 * PARAMS
942 * hDc [I] Destination DC
943 * lpszPath [I/O] Path to be printed to hDc
944 * dx [I] Desired width
945 *
946 * RETURNS
947 * TRUE If the path was modified/went well.
948 * FALSE Otherwise.
949 */
951{
952 BOOL bRet = FALSE;
953
954 TRACE("(%p,%s,%d)\n", hDC, debugstr_a(lpszPath), dx);
955
956 if (lpszPath)
957 {
960 bRet = PathCompactPathW(hDC, szPath, dx);
961 WideCharToMultiByte(CP_ACP,0,szPath,-1,lpszPath,MAX_PATH,0,0);
962 }
963 return bRet;
964}
965
966/*************************************************************************
967 * PathCompactPathW [SHLWAPI.@]
968 *
969 * See PathCompactPathA.
970 */
972{
973 static const WCHAR szEllipses[] = { '.', '.', '.', '\0' };
974 BOOL bRet = TRUE;
975 HDC hdc = 0;
977 SIZE size;
978 DWORD dwLen;
979
980 TRACE("(%p,%s,%d)\n", hDC, debugstr_w(lpszPath), dx);
981
982 if (!lpszPath)
983 return FALSE;
984
985 if (!hDC)
986 hdc = hDC = GetDC(0);
987
988 /* Get the length of the whole path */
989 dwLen = lstrlenW(lpszPath);
990 GetTextExtentPointW(hDC, lpszPath, dwLen, &size);
991
992 if ((UINT)size.cx > dx)
993 {
994 /* Path too big, must reduce it */
995 LPWSTR sFile;
996 DWORD dwEllipsesLen = 0, dwPathLen = 0;
997
998 sFile = PathFindFileNameW(lpszPath);
999 if (sFile != lpszPath) sFile--;
1000
1001 /* Get the size of ellipses */
1002 GetTextExtentPointW(hDC, szEllipses, 3, &size);
1003 dwEllipsesLen = size.cx;
1004 /* Get the size of the file name */
1005 GetTextExtentPointW(hDC, sFile, lstrlenW(sFile), &size);
1006 dwPathLen = size.cx;
1007
1008 if (sFile != lpszPath)
1009 {
1010 LPWSTR sPath = sFile;
1011 BOOL bEllipses = FALSE;
1012
1013 /* The path includes a file name. Include as much of the path prior to
1014 * the file name as possible, allowing for the ellipses, e.g:
1015 * c:\some very long path\filename ==> c:\some v...\filename
1016 */
1017 lstrcpynW(buff, sFile, MAX_PATH);
1018
1019 do
1020 {
1021 DWORD dwTotalLen = bEllipses? dwPathLen + dwEllipsesLen : dwPathLen;
1022
1023 GetTextExtentPointW(hDC, lpszPath, sPath - lpszPath, &size);
1024 dwTotalLen += size.cx;
1025 if (dwTotalLen <= dx)
1026 break;
1027 sPath--;
1028 if (!bEllipses)
1029 {
1030 bEllipses = TRUE;
1031 sPath -= 2;
1032 }
1033 } while (sPath > lpszPath);
1034
1035 if (sPath > lpszPath)
1036 {
1037 if (bEllipses)
1038 {
1039 lstrcpyW(sPath, szEllipses);
1040 lstrcpyW(sPath+3, buff);
1041 }
1042 bRet = TRUE;
1043 goto end;
1044 }
1045 lstrcpyW(lpszPath, szEllipses);
1046 lstrcpyW(lpszPath+3, buff);
1047 bRet = FALSE;
1048 goto end;
1049 }
1050
1051 /* Trim the path by adding ellipses to the end, e.g:
1052 * A very long file name.txt ==> A very...
1053 */
1054 dwLen = lstrlenW(lpszPath);
1055
1056 if (dwLen > MAX_PATH - 3)
1057 dwLen = MAX_PATH - 3;
1058 lstrcpynW(buff, sFile, dwLen);
1059
1060 do {
1061 dwLen--;
1062 GetTextExtentPointW(hDC, buff, dwLen, &size);
1063 } while (dwLen && size.cx + dwEllipsesLen > dx);
1064
1065 if (!dwLen)
1066 {
1067 DWORD dwWritten = 0;
1068
1069 dwEllipsesLen /= 3; /* Size of a single '.' */
1070
1071 /* Write as much of the Ellipses string as possible */
1072 while (dwWritten + dwEllipsesLen < dx && dwLen < 3)
1073 {
1074 *lpszPath++ = '.';
1075 dwWritten += dwEllipsesLen;
1076 dwLen++;
1077 }
1078 *lpszPath = '\0';
1079 bRet = FALSE;
1080 }
1081 else
1082 {
1083 lstrcpyW(buff + dwLen, szEllipses);
1084 lstrcpyW(lpszPath, buff);
1085 }
1086 }
1087
1088end:
1089 if (hdc)
1090 ReleaseDC(0, hdc);
1091
1092 return bRet;
1093}
1094
1095/*************************************************************************
1096 * SHLWAPI_UseSystemForSystemFolders
1097 *
1098 * Internal helper for PathMakeSystemFolderW.
1099 */
1101{
1102 static BOOL bCheckedReg = FALSE;
1103 static BOOL bUseSystemForSystemFolders = FALSE;
1104
1105 if (!bCheckedReg)
1106 {
1107 bCheckedReg = TRUE;
1108
1109 /* Key tells Win what file attributes to use on system folders */
1111 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
1112 "UseSystemForSystemFolders", 0, 0, 0))
1113 bUseSystemForSystemFolders = TRUE;
1114 }
1115 return bUseSystemForSystemFolders;
1116}
1117
1118/*************************************************************************
1119 * PathMakeSystemFolderA [SHLWAPI.@]
1120 *
1121 * Set system folder attribute for a path.
1122 *
1123 * PARAMS
1124 * lpszPath [I] The path to turn into a system folder
1125 *
1126 * RETURNS
1127 * TRUE If the path was changed to/already was a system folder
1128 * FALSE If the path is invalid or SetFileAttributesA() fails
1129 */
1131{
1132 BOOL bRet = FALSE;
1133
1134 TRACE("(%s)\n", debugstr_a(lpszPath));
1135
1136 if (lpszPath && *lpszPath)
1137 {
1141 }
1142 return bRet;
1143}
1144
1145/*************************************************************************
1146 * PathMakeSystemFolderW [SHLWAPI.@]
1147 *
1148 * See PathMakeSystemFolderA.
1149 */
1151{
1152 DWORD dwDefaultAttr = FILE_ATTRIBUTE_READONLY, dwAttr;
1154
1155 TRACE("(%s)\n", debugstr_w(lpszPath));
1156
1157 if (!lpszPath || !*lpszPath)
1158 return FALSE;
1159
1160 /* If the directory is already a system directory, don't do anything */
1162 if (!wcscmp(buff, lpszPath))
1163 return TRUE;
1164
1166 if (!wcscmp(buff, lpszPath))
1167 return TRUE;
1168
1169 /* "UseSystemForSystemFolders" Tells Win what attributes to use */
1171 dwDefaultAttr = FILE_ATTRIBUTE_SYSTEM;
1172
1173 if ((dwAttr = GetFileAttributesW(lpszPath)) == INVALID_FILE_ATTRIBUTES)
1174 return FALSE;
1175
1176 /* Change file attributes to system attributes */
1178 return SetFileAttributesW(lpszPath, dwAttr | dwDefaultAttr);
1179}
1180
1181/*************************************************************************
1182 * PathUnmakeSystemFolderA [SHLWAPI.@]
1183 *
1184 * Remove the system folder attributes from a path.
1185 *
1186 * PARAMS
1187 * lpszPath [I] The path to remove attributes from
1188 *
1189 * RETURNS
1190 * Success: TRUE.
1191 * Failure: FALSE, if lpszPath is NULL, empty, not a directory, or calling
1192 * SetFileAttributesA() fails.
1193 */
1195{
1196 DWORD dwAttr;
1197
1198 TRACE("(%s)\n", debugstr_a(lpszPath));
1199
1200 if (!lpszPath || !*lpszPath || (dwAttr = GetFileAttributesA(lpszPath)) == INVALID_FILE_ATTRIBUTES ||
1201 !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
1202 return FALSE;
1203
1205 return SetFileAttributesA(lpszPath, dwAttr);
1206}
1207
1208/*************************************************************************
1209 * PathUnmakeSystemFolderW [SHLWAPI.@]
1210 *
1211 * See PathUnmakeSystemFolderA.
1212 */
1214{
1215 DWORD dwAttr;
1216
1217 TRACE("(%s)\n", debugstr_w(lpszPath));
1218
1219 if (!lpszPath || !*lpszPath || (dwAttr = GetFileAttributesW(lpszPath)) == INVALID_FILE_ATTRIBUTES ||
1220 !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
1221 return FALSE;
1222
1224 return SetFileAttributesW(lpszPath, dwAttr);
1225}
1226
1227
1228/*************************************************************************
1229 * PathSetDlgItemPathA [SHLWAPI.@]
1230 *
1231 * Set the text of a dialog item to a path, shrinking the path to fit
1232 * if it is too big for the item.
1233 *
1234 * PARAMS
1235 * hDlg [I] Dialog handle
1236 * id [I] ID of item in the dialog
1237 * lpszPath [I] Path to set as the items text
1238 *
1239 * RETURNS
1240 * Nothing.
1241 *
1242 * NOTES
1243 * If lpszPath is NULL, a blank string ("") is set (i.e. The previous
1244 * window text is erased).
1245 */
1247{
1249
1250 TRACE("(%p,%8x,%s)\n",hDlg, id, debugstr_a(lpszPath));
1251
1252 if (lpszPath)
1254 else
1255 szPath[0] = '\0';
1256 PathSetDlgItemPathW(hDlg, id, szPath);
1257}
1258
1259/*************************************************************************
1260 * PathSetDlgItemPathW [SHLWAPI.@]
1261 *
1262 * See PathSetDlgItemPathA.
1263 */
1265{
1266 WCHAR path[MAX_PATH + 1];
1267 HWND hwItem;
1268 RECT rect;
1269 HDC hdc;
1270 HGDIOBJ hPrevObj;
1271
1272 TRACE("(%p,%8x,%s)\n",hDlg, id, debugstr_w(lpszPath));
1273
1274 if (!(hwItem = GetDlgItem(hDlg, id)))
1275 return;
1276
1277 if (lpszPath)
1278 lstrcpynW(path, lpszPath, ARRAY_SIZE(path));
1279 else
1280 path[0] = '\0';
1281
1282 GetClientRect(hwItem, &rect);
1283 hdc = GetDC(hDlg);
1284 hPrevObj = SelectObject(hdc, (HGDIOBJ)SendMessageW(hwItem,WM_GETFONT,0,0));
1285
1286 if (hPrevObj)
1287 {
1289 SelectObject(hdc, hPrevObj);
1290 }
1291
1292 ReleaseDC(hDlg, hdc);
1293 SetWindowTextW(hwItem, path);
1294}
1295
1296/*************************************************************************
1297 * PathIsNetworkPathA [SHLWAPI.@]
1298 *
1299 * Determine if the given path is a network path.
1300 *
1301 * PARAMS
1302 * lpszPath [I] Path to check
1303 *
1304 * RETURNS
1305 * TRUE If lpszPath is a UNC share or mapped network drive, or
1306 * FALSE If lpszPath is a local drive or cannot be determined
1307 */
1309{
1310 int dwDriveNum;
1311
1312 TRACE("(%s)\n",debugstr_a(lpszPath));
1313
1314 if (!lpszPath)
1315 return FALSE;
1316 if (*lpszPath == '\\' && lpszPath[1] == '\\')
1317 return TRUE;
1318 dwDriveNum = PathGetDriveNumberA(lpszPath);
1319 if (dwDriveNum == -1)
1320 return FALSE;
1321#ifdef __REACTOS__
1322 return IsNetDrive(dwDriveNum);
1323#else
1324 GET_FUNC(pIsNetDrive, shell32, (LPCSTR)66, FALSE); /* ord 66 = shell32.IsNetDrive */
1325 return pIsNetDrive(dwDriveNum);
1326#endif
1327}
1328
1329/*************************************************************************
1330 * PathIsNetworkPathW [SHLWAPI.@]
1331 *
1332 * See PathIsNetworkPathA.
1333 */
1335{
1336 int dwDriveNum;
1337
1338 TRACE("(%s)\n", debugstr_w(lpszPath));
1339
1340 if (!lpszPath)
1341 return FALSE;
1342 if (*lpszPath == '\\' && lpszPath[1] == '\\')
1343 return TRUE;
1344 dwDriveNum = PathGetDriveNumberW(lpszPath);
1345 if (dwDriveNum == -1)
1346 return FALSE;
1347#ifdef __REACTOS__
1348 return IsNetDrive(dwDriveNum);
1349#else
1350 GET_FUNC(pIsNetDrive, shell32, (LPCSTR)66, FALSE); /* ord 66 = shell32.IsNetDrive */
1351 return pIsNetDrive(dwDriveNum);
1352#endif
1353}
1354
1355/*************************************************************************
1356 * PathIsDirectoryEmptyA [SHLWAPI.@]
1357 *
1358 * Determine if a given directory is empty.
1359 *
1360 * PARAMS
1361 * lpszPath [I] Directory to check
1362 *
1363 * RETURNS
1364 * TRUE If the directory exists and contains no files,
1365 * FALSE Otherwise
1366 */
1368{
1369 BOOL bRet = FALSE;
1370
1371 TRACE("(%s)\n",debugstr_a(lpszPath));
1372
1373 if (lpszPath)
1374 {
1378 }
1379 return bRet;
1380}
1381
1382/*************************************************************************
1383 * PathIsDirectoryEmptyW [SHLWAPI.@]
1384 *
1385 * See PathIsDirectoryEmptyA.
1386 */
1388{
1389 static const WCHAR szAllFiles[] = { '*', '.', '*', '\0' };
1390 WCHAR szSearch[MAX_PATH];
1391 DWORD dwLen;
1392 HANDLE hfind;
1393 BOOL retVal = TRUE;
1395
1396 TRACE("(%s)\n",debugstr_w(lpszPath));
1397
1398 if (!lpszPath || !PathIsDirectoryW(lpszPath))
1399 return FALSE;
1400
1401 lstrcpynW(szSearch, lpszPath, MAX_PATH);
1402 PathAddBackslashW(szSearch);
1403 dwLen = lstrlenW(szSearch);
1404 if (dwLen > MAX_PATH - 4)
1405 return FALSE;
1406
1407 lstrcpyW(szSearch + dwLen, szAllFiles);
1408 hfind = FindFirstFileW(szSearch, &find_data);
1409 if (hfind == INVALID_HANDLE_VALUE)
1410 return FALSE;
1411
1412 do
1413 {
1414 if (find_data.cFileName[0] == '.')
1415 {
1416 if (find_data.cFileName[1] == '\0') continue;
1417 if (find_data.cFileName[1] == '.' && find_data.cFileName[2] == '\0') continue;
1418 }
1419
1420 retVal = FALSE;
1421 break;
1422 }
1423 while (FindNextFileW(hfind, &find_data));
1424
1425 FindClose(hfind);
1426 return retVal;
1427}
1428
1429
1430/*************************************************************************
1431 * PathFindSuffixArrayA [SHLWAPI.@]
1432 *
1433 * Find a suffix string in an array of suffix strings
1434 *
1435 * PARAMS
1436 * lpszSuffix [I] Suffix string to search for
1437 * lppszArray [I] Array of suffix strings to search
1438 * dwCount [I] Number of elements in lppszArray
1439 *
1440 * RETURNS
1441 * Success: The index of the position of lpszSuffix in lppszArray
1442 * Failure: 0, if any parameters are invalid or lpszSuffix is not found
1443 *
1444 * NOTES
1445 * The search is case sensitive.
1446 * The match is made against the end of the suffix string, so for example:
1447 * lpszSuffix="fooBAR" matches "BAR", but lpszSuffix="fooBARfoo" does not.
1448 */
1449LPCSTR WINAPI PathFindSuffixArrayA(LPCSTR lpszSuffix, LPCSTR *lppszArray, int dwCount)
1450{
1451 size_t dwLen;
1452 int dwRet = 0;
1453
1454 TRACE("(%s,%p,%d)\n",debugstr_a(lpszSuffix), lppszArray, dwCount);
1455
1456 if (lpszSuffix && lppszArray && dwCount > 0)
1457 {
1458 dwLen = strlen(lpszSuffix);
1459
1460 while (dwRet < dwCount)
1461 {
1462 size_t dwCompareLen = strlen(*lppszArray);
1463 if (dwCompareLen < dwLen)
1464 {
1465 if (!strcmp(lpszSuffix + dwLen - dwCompareLen, *lppszArray))
1466 return *lppszArray; /* Found */
1467 }
1468 dwRet++;
1469 lppszArray++;
1470 }
1471 }
1472 return NULL;
1473}
1474
1475/*************************************************************************
1476 * PathFindSuffixArrayW [SHLWAPI.@]
1477 *
1478 * See PathFindSuffixArrayA.
1479 */
1480LPCWSTR WINAPI PathFindSuffixArrayW(LPCWSTR lpszSuffix, LPCWSTR *lppszArray, int dwCount)
1481{
1482 size_t dwLen;
1483 int dwRet = 0;
1484
1485 TRACE("(%s,%p,%d)\n",debugstr_w(lpszSuffix), lppszArray, dwCount);
1486
1487 if (lpszSuffix && lppszArray && dwCount > 0)
1488 {
1489 dwLen = lstrlenW(lpszSuffix);
1490
1491 while (dwRet < dwCount)
1492 {
1493 size_t dwCompareLen = lstrlenW(*lppszArray);
1494 if (dwCompareLen < dwLen)
1495 {
1496 if (!wcscmp(lpszSuffix + dwLen - dwCompareLen, *lppszArray))
1497 return *lppszArray; /* Found */
1498 }
1499 dwRet++;
1500 lppszArray++;
1501 }
1502 }
1503 return NULL;
1504}
1505
1506/*************************************************************************
1507 * PathUndecorateA [SHLWAPI.@]
1508 *
1509 * Undecorate a file path
1510 *
1511 * PARAMS
1512 * lpszPath [I/O] Path to remove any decoration from
1513 *
1514 * RETURNS
1515 * Nothing
1516 *
1517 * NOTES
1518 * A decorations form is "path[n].ext" where "n" is an optional decimal number.
1519 */
1521{
1522 char *ext, *skip;
1523
1524 TRACE("(%s)\n", debugstr_a(path));
1525
1526 if (!path) return;
1527
1529 if (ext == path || ext[-1] != ']') return;
1530
1531 skip = ext - 2;
1532 while (skip > path && '0' <= *skip && *skip <= '9')
1533 skip--;
1534
1535 if (skip > path && *skip == '[' && skip[-1] != '\\')
1536 memmove(skip, ext, strlen(ext) + 1);
1537}
1538
1539/*************************************************************************
1540 * PathUndecorateW [SHLWAPI.@]
1541 *
1542 * See PathUndecorateA.
1543 */
1545{
1546 WCHAR *ext, *skip;
1547
1548 TRACE("(%s)\n", debugstr_w(path));
1549
1550 if (!path) return;
1551
1553 if (ext == path || ext[-1] != ']') return;
1554
1555 skip = ext - 2;
1556 while (skip > path && '0' <= *skip && *skip <= '9')
1557 skip--;
1558
1559 if (skip > path && *skip == '[' && skip[-1] != '\\')
1560 memmove(skip, ext, (wcslen(ext) + 1) * sizeof(WCHAR));
1561}
1562
1563/*************************************************************************
1564 * @ [SHLWAPI.440]
1565 *
1566 * Find localised or default web content in "%WINDOWS%\web\".
1567 *
1568 * PARAMS
1569 * lpszFile [I] File name containing content to look for
1570 * lpszPath [O] Buffer to contain the full path to the file
1571 * dwPathLen [I] Length of lpszPath
1572 *
1573 * RETURNS
1574 * Success: S_OK. lpszPath contains the full path to the content.
1575 * Failure: E_FAIL. The content does not exist or lpszPath is too short.
1576 */
1578{
1579 WCHAR szFile[MAX_PATH], szPath[MAX_PATH];
1580 HRESULT hRet;
1581
1582 TRACE("(%s,%p,%ld)\n", lpszFile, lpszPath, dwPathLen);
1583
1584 MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, szFile, MAX_PATH);
1585 szPath[0] = '\0';
1586 hRet = SHGetWebFolderFilePathW(szFile, szPath, dwPathLen);
1587 WideCharToMultiByte(CP_ACP, 0, szPath, -1, lpszPath, dwPathLen, 0, 0);
1588 return hRet;
1589}
1590
1591/*************************************************************************
1592 * @ [SHLWAPI.441]
1593 *
1594 * Unicode version of SHGetWebFolderFilePathA.
1595 */
1597{
1598 static const WCHAR szWeb[] = {'\\','W','e','b','\\','\0'};
1599 static const WCHAR szWebMui[] = {'m','u','i','\\','%','0','4','x','\\','\0'};
1600 DWORD dwLen, dwFileLen;
1601 LANGID lidSystem, lidUser;
1602
1603 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszFile), lpszPath, dwPathLen);
1604
1605 /* Get base directory for web content */
1606 dwLen = GetSystemWindowsDirectoryW(lpszPath, dwPathLen);
1607 if (dwLen > 0 && lpszPath[dwLen-1] == '\\')
1608 dwLen--;
1609
1610 dwFileLen = lstrlenW(lpszFile);
1611
1612 if (dwLen + dwFileLen + ARRAY_SIZE(szWeb) >= dwPathLen)
1613 return E_FAIL; /* lpszPath too short */
1614
1615 lstrcpyW(lpszPath+dwLen, szWeb);
1616 dwLen += ARRAY_SIZE(szWeb);
1617 dwPathLen = dwPathLen - dwLen; /* Remaining space */
1618
1619 lidSystem = GetSystemDefaultUILanguage();
1620 lidUser = GetUserDefaultUILanguage();
1621
1622 if (lidSystem != lidUser)
1623 {
1624 if (dwFileLen + ARRAY_SIZE(szWebMui) < dwPathLen)
1625 {
1626 /* Use localised content in the users UI language if present */
1627 wsprintfW(lpszPath + dwLen, szWebMui, lidUser);
1628 lstrcpyW(lpszPath + dwLen + ARRAY_SIZE(szWebMui), lpszFile);
1629 if (PathFileExistsW(lpszPath))
1630 return S_OK;
1631 }
1632 }
1633
1634 /* Fall back to OS default installed content */
1635 lstrcpyW(lpszPath + dwLen, lpszFile);
1636 if (PathFileExistsW(lpszPath))
1637 return S_OK;
1638 return E_FAIL;
1639}
static HDC hDC
Definition: 3dtext.c:33
@ shell32
Definition: LocaleTests.cpp:20
UINT cchMax
WCHAR lpszDest[260]
#define islower(c)
Definition: acclib.h:72
#define skip(...)
Definition: atltest.h:64
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
RECT rect
Definition: combotst.c:67
#define NO_ERROR
Definition: dderror.h:5
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static int find_data(const struct Vector *v, const BYTE *pData, int size)
Definition: filtermapper.c:162
#define CP_ACP
Definition: compat.h:109
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR *const ext[]
Definition: module.c:53
UINT WINAPI SetErrorMode(IN UINT uMode)
Definition: except.c:751
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:636
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:778
BOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:760
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:620
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2232
UINT WINAPI GetSystemWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2316
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2271
BOOL WINAPI IsDBCSLeadByte(BYTE testchar)
Definition: locale.c:2126
LANGID WINAPI GetUserDefaultUILanguage(void)
Definition: locale.c:1380
LANGID WINAPI GetSystemDefaultUILanguage(void)
Definition: locale.c:1400
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4133
LPSTR WINAPI PathFindExtensionA(const char *path)
Definition: path.c:1229
int WINAPI PathGetDriveNumberW(const WCHAR *path)
Definition: path.c:1786
BOOL WINAPI PathIsUNCServerShareW(const WCHAR *path)
Definition: path.c:1040
BOOL WINAPI PathIsUNCServerA(const char *path)
Definition: path.c:1835
BOOL WINAPI PathIsFileSpecA(const char *path)
Definition: path.c:1801
WCHAR *WINAPI PathFindFileNameW(const WCHAR *path)
Definition: path.c:1677
char *WINAPI PathGetArgsA(const char *path)
Definition: path.c:1694
LPWSTR WINAPI PathFindExtensionW(const WCHAR *path)
Definition: path.c:1250
int WINAPI PathGetDriveNumberA(const char *path)
Definition: path.c:1774
BOOL WINAPI PathIsUNCServerW(const WCHAR *path)
Definition: path.c:1852
WCHAR *WINAPI PathGetArgsW(const WCHAR *path)
Definition: path.c:1716
BOOL WINAPI PathFileExistsW(const WCHAR *path)
Definition: path.c:2583
BOOL WINAPI PathIsFileSpecW(const WCHAR *path)
Definition: path.c:1818
BOOL WINAPI PathIsUNCServerShareA(const char *path)
Definition: path.c:1016
LPSTR WINAPI CharPrevA(const char *start, const char *ptr)
Definition: string.c:1172
int CDECL tolower(int c)
Definition: ctype.c:572
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1597
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3324
DWORD WINAPI SHGetValueW(HKEY hkey, const WCHAR *subkey, const WCHAR *value, DWORD *type, void *data, DWORD *data_len)
Definition: main.c:2222
DWORD WINAPI SHGetValueA(HKEY hkey, const char *subkey, const char *value, DWORD *type, void *data, DWORD *data_len)
Definition: main.c:2197
HRESULT WINAPI SHGetWebFolderFilePathA(LPCSTR lpszFile, LPSTR lpszPath, DWORD dwPathLen)
Definition: path.c:1577
void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
Definition: path.c:153
BOOL WINAPI PathFileExistsDefExtA(LPSTR lpszPath, DWORD dwWhich)
Definition: path.c:248
BOOL WINAPI PathIsDirectoryA(LPCSTR lpszPath)
Definition: path.c:625
BOOL WINAPI PathMakeSystemFolderA(LPCSTR lpszPath)
Definition: path.c:1130
BOOL WINAPI PathIsNetworkPathW(LPCWSTR lpszPath)
Definition: path.c:1334
LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive)
Definition: path.c:86
BOOL WINAPI PathMakeSystemFolderW(LPCWSTR lpszPath)
Definition: path.c:1150
BOOL(WINAPI * fnpIsNetDrive)(int)
Definition: path.c:65
BOOL WINAPI PathIsNetworkPathA(LPCSTR lpszPath)
Definition: path.c:1308
BOOL WINAPI PathFindOnPathExA(LPSTR lpszFile, LPCSTR *lppszOtherDirs, DWORD dwWhich)
Definition: path.c:360
void WINAPI PathRemoveArgsA(LPSTR lpszPath)
Definition: path.c:130
#define GET_FUNC(func, module, name, fail)
Definition: path.c:52
BOOL WINAPI PathFindOnPathW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs)
Definition: path.c:456
BOOL WINAPI PathIsDirectoryEmptyW(LPCWSTR lpszPath)
Definition: path.c:1387
BOOL WINAPI PathCompactPathExA(LPSTR lpszDest, LPCSTR lpszPath, UINT cchMax, DWORD dwFlags)
Definition: path.c:488
void WINAPI PathUndecorateW(WCHAR *path)
Definition: path.c:1544
BOOL WINAPI PathIsSystemFolderA(LPCSTR lpszPath, DWORD dwAttrib)
Definition: path.c:834
BOOL WINAPI PathCompactPathExW(LPWSTR lpszDest, LPCWSTR lpszPath, UINT cchMax, DWORD dwFlags)
Definition: path.c:513
static BOOL SHLWAPI_UseSystemForSystemFolders(void)
Definition: path.c:1100
void WINAPI PathUndecorateA(char *path)
Definition: path.c:1520
BOOL WINAPI PathMakePrettyW(LPWSTR lpszPath)
Definition: path.c:909
static BOOL SHLWAPI_PathFindInOtherDirs(LPWSTR lpszFile, DWORD dwWhich)
Definition: path.c:270
BOOL WINAPI PathCompactPathA(HDC hDC, LPSTR lpszPath, UINT dx)
Definition: path.c:950
BOOL WINAPI PathUnmakeSystemFolderW(LPCWSTR lpszPath)
Definition: path.c:1213
BOOL WINAPI PathFindOnPathA(LPSTR lpszFile, LPCSTR *lppszOtherDirs)
Definition: path.c:445
static fnpIsNetDrive pIsNetDrive
Definition: path.c:66
LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
Definition: path.c:105
BOOL WINAPI PathFileExistsAndAttributesA(LPCSTR lpszPath, DWORD *dwAttr)
Definition: path.c:721
static HMODULE SHLWAPI_hshell32
Definition: path.c:62
HRESULT WINAPI SHGetWebFolderFilePathW(LPCWSTR, LPWSTR, DWORD)
Definition: path.c:1596
VOID WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR lpszPath)
Definition: path.c:1246
BOOL WINAPI PathIsContentTypeW(LPCWSTR lpszPath, LPCWSTR lpszContentType)
Definition: path.c:802
BOOL WINAPI PathCompactPathW(HDC hDC, LPWSTR lpszPath, UINT dx)
Definition: path.c:971
BOOL WINAPI PathIsSystemFolderW(LPCWSTR lpszPath, DWORD dwAttrib)
Definition: path.c:852
BOOL WINAPI PathFindOnPathExW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs, DWORD dwWhich)
Definition: path.c:404
BOOL WINAPI PathMakePrettyA(LPSTR lpszPath)
Definition: path.c:877
LPCSTR WINAPI PathFindSuffixArrayA(LPCSTR lpszSuffix, LPCSTR *lppszArray, int dwCount)
Definition: path.c:1449
BOOL WINAPI PathUnmakeSystemFolderA(LPCSTR lpszPath)
Definition: path.c:1194
VOID WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR lpszPath)
Definition: path.c:1264
LPCWSTR WINAPI PathFindSuffixArrayW(LPCWSTR lpszSuffix, LPCWSTR *lppszArray, int dwCount)
Definition: path.c:1480
BOOL WINAPI PathFileExistsAndAttributesW(LPCWSTR lpszPath, DWORD *dwAttr)
Definition: path.c:747
BOOL WINAPI PathFileExistsDefExtW(LPWSTR lpszPath, DWORD dwWhich)
Definition: path.c:170
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:669
BOOL WINAPI PathIsDirectoryEmptyA(LPCSTR lpszPath)
Definition: path.c:1367
BOOL WINAPI PathIsContentTypeA(LPCSTR path, LPCSTR content_type)
Definition: path.c:783
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint end
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define S_OK
Definition: intsafe.h:52
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
USHORT LANGID
Definition: mui.h:9
GLint dx
Definition: linetemp.h:97
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
LPCWSTR szPath
Definition: env.c:37
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:88
static BSTR content_type
unsigned int UINT
Definition: ndis.h:50
#define SEM_FAILCRITICALERRORS
Definition: rtltypes.h:69
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define BOOL
Definition: nt_native.h:43
#define REG_NONE
Definition: nt_native.h:1495
#define PathCombineW
Definition: pathcch.h:318
#define PathAddBackslashW
Definition: pathcch.h:302
#define PathAppendW
Definition: pathcch.h:310
short WCHAR
Definition: pedump.c:58
#define iswlower(_c)
Definition: ctype.h:666
#define towlower(c)
Definition: wctype.h:97
static const char *static const char const char DWORD void DWORD *static const char const char DWORD void DWORD *static const char DWORD DWORD void * buff
Definition: shcore.c:41
EXTERN_C int WINAPI IsNetDrive(int drive)
Definition: shlfileop.cpp:2342
#define WHICH_OPTIONAL
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwDisplayType
Definition: winnetwk.h:169
DWORD dwScope
Definition: winnetwk.h:167
LPSTR lpRemoteName
Definition: winnetwk.h:172
DWORD dwType
Definition: winnetwk.h:168
DWORD dwType
Definition: winnetwk.h:178
DWORD dwDisplayType
Definition: winnetwk.h:179
DWORD dwScope
Definition: winnetwk.h:177
LPWSTR lpRemoteName
Definition: winnetwk.h:182
LONG right
Definition: windef.h:108
const char * LPCSTR
Definition: typedefs.h:52
const uint16_t * LPCWSTR
Definition: typedefs.h:57
uint16_t * LPWSTR
Definition: typedefs.h:56
char * LPSTR
Definition: typedefs.h:51
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define GetFileAttributes
Definition: winbase.h:3536
#define WINAPI
Definition: msvc.h:6
BOOL WINAPI GetTextExtentPointW(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE lpsz)
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
struct _NETRESOURCEA * LPNETRESOURCEA
#define RESOURCEDISPLAYTYPE_SHARE
Definition: winnetwk.h:78
#define RESOURCEDISPLAYTYPE_GENERIC
Definition: winnetwk.h:75
#define RESOURCETYPE_DISK
Definition: winnetwk.h:64
#define RESOURCETYPE_ANY
Definition: winnetwk.h:63
struct _NETRESOURCEW * LPNETRESOURCEW
#define RESOURCE_GLOBALNET
Definition: winnetwk.h:59
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define WM_GETFONT
Definition: winuser.h:1679
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
HDC WINAPI GetDC(_In_opt_ HWND)
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
DWORD WINAPI WNetGetResourceInformationA(LPNETRESOURCEA lpNetResource, LPVOID lpBuffer, LPDWORD cbBuffer, LPSTR *lplpSystem)
Definition: wnet.c:1822
DWORD WINAPI WNetGetResourceInformationW(LPNETRESOURCEW lpNetResource, LPVOID lpBuffer, LPDWORD cbBuffer, LPWSTR *lplpSystem)
Definition: wnet.c:1937
unsigned char BYTE
Definition: xxhash.c:193