1 /**
2  * WinPR: Windows Portable Runtime
3  * Path Functions
4  *
5  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <winpr/crt.h>
25 #include <winpr/heap.h>
26 #include <winpr/tchar.h>
27 
28 #include <winpr/path.h>
29 
30 #define PATH_SLASH_CHR '/'
31 #define PATH_SLASH_STR "/"
32 
33 #define PATH_BACKSLASH_CHR '\\'
34 #define PATH_BACKSLASH_STR "\\"
35 
36 #ifdef _WIN32
37 #define PATH_SLASH_STR_W L"/"
38 #define PATH_BACKSLASH_STR_W L"\\"
39 #else
40 #define PATH_SLASH_STR_W "/"
41 #define PATH_BACKSLASH_STR_W "\\"
42 #endif
43 
44 #ifdef _WIN32
45 #define PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
46 #define PATH_SEPARATOR_STR PATH_BACKSLASH_STR
47 #define PATH_SEPARATOR_STR_W PATH_BACKSLASH_STR_W
48 #else
49 #define PATH_SEPARATOR_CHR PATH_SLASH_CHR
50 #define PATH_SEPARATOR_STR PATH_SLASH_STR
51 #define PATH_SEPARATOR_STR_W PATH_SLASH_STR_W
52 #endif
53 
54 #define SHARED_LIBRARY_EXT_DLL "dll"
55 #define SHARED_LIBRARY_EXT_SO "so"
56 #define SHARED_LIBRARY_EXT_DYLIB "dylib"
57 
58 #ifdef _WIN32
59 #define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_DLL
60 #elif defined(__APPLE__)
61 #define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_DYLIB
62 #else
63 #define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_SO
64 #endif
65 
66 #include "../log.h"
67 #define TAG WINPR_TAG("path")
68 
69 /*
70  * PathCchAddBackslash
71  */
72 
73 /* Windows-style Paths */
74 
75 #define DEFINE_UNICODE FALSE
76 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
77 #define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA
78 #include "include/PathCchAddSeparator.c"
79 #undef DEFINE_UNICODE
80 #undef _PATH_SEPARATOR_CHR
81 #undef PATH_CCH_ADD_SEPARATOR
82 
83 #define DEFINE_UNICODE TRUE
84 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
85 #define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashW
86 #include "include/PathCchAddSeparator.c"
87 #undef DEFINE_UNICODE
88 #undef _PATH_SEPARATOR_CHR
89 #undef PATH_CCH_ADD_SEPARATOR
90 
91 /* Unix-style Paths */
92 
93 #define DEFINE_UNICODE FALSE
94 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
95 #define PATH_CCH_ADD_SEPARATOR PathCchAddSlashA
96 #include "include/PathCchAddSeparator.c"
97 #undef DEFINE_UNICODE
98 #undef _PATH_SEPARATOR_CHR
99 #undef PATH_CCH_ADD_SEPARATOR
100 
101 #define DEFINE_UNICODE TRUE
102 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
103 #define PATH_CCH_ADD_SEPARATOR PathCchAddSlashW
104 #include "include/PathCchAddSeparator.c"
105 #undef DEFINE_UNICODE
106 #undef _PATH_SEPARATOR_CHR
107 #undef PATH_CCH_ADD_SEPARATOR
108 
109 /* Native-style Paths */
110 
111 #define DEFINE_UNICODE FALSE
112 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
113 #define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorA
114 #include "include/PathCchAddSeparator.c"
115 #undef DEFINE_UNICODE
116 #undef _PATH_SEPARATOR_CHR
117 #undef PATH_CCH_ADD_SEPARATOR
118 
119 #define DEFINE_UNICODE TRUE
120 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
121 #define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorW
122 #include "include/PathCchAddSeparator.c"
123 #undef DEFINE_UNICODE
124 #undef _PATH_SEPARATOR_CHR
125 #undef PATH_CCH_ADD_SEPARATOR
126 
127 /*
128  * PathCchRemoveBackslash
129  */
130 
PathCchRemoveBackslashA(PSTR pszPath,size_t cchPath)131 HRESULT PathCchRemoveBackslashA(PSTR pszPath, size_t cchPath)
132 {
133 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
134 	return E_NOTIMPL;
135 }
136 
PathCchRemoveBackslashW(PWSTR pszPath,size_t cchPath)137 HRESULT PathCchRemoveBackslashW(PWSTR pszPath, size_t cchPath)
138 {
139 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
140 	return E_NOTIMPL;
141 }
142 
143 /*
144  * PathCchAddBackslashEx
145  */
146 
147 /* Windows-style Paths */
148 
149 #define DEFINE_UNICODE FALSE
150 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
151 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA
152 #include "include/PathCchAddSeparatorEx.c"
153 #undef DEFINE_UNICODE
154 #undef _PATH_SEPARATOR_CHR
155 #undef PATH_CCH_ADD_SEPARATOR_EX
156 
157 #define DEFINE_UNICODE TRUE
158 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
159 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExW
160 #include "include/PathCchAddSeparatorEx.c"
161 #undef DEFINE_UNICODE
162 #undef _PATH_SEPARATOR_CHR
163 #undef PATH_CCH_ADD_SEPARATOR_EX
164 
165 /* Unix-style Paths */
166 
167 #define DEFINE_UNICODE FALSE
168 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
169 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExA
170 #include "include/PathCchAddSeparatorEx.c"
171 #undef DEFINE_UNICODE
172 #undef _PATH_SEPARATOR_CHR
173 #undef PATH_CCH_ADD_SEPARATOR_EX
174 
175 #define DEFINE_UNICODE TRUE
176 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
177 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExW
178 #include "include/PathCchAddSeparatorEx.c"
179 #undef DEFINE_UNICODE
180 #undef _PATH_SEPARATOR_CHR
181 #undef PATH_CCH_ADD_SEPARATOR_EX
182 
183 /* Native-style Paths */
184 
185 #define DEFINE_UNICODE FALSE
186 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
187 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExA
188 #include "include/PathCchAddSeparatorEx.c"
189 #undef DEFINE_UNICODE
190 #undef _PATH_SEPARATOR_CHR
191 #undef PATH_CCH_ADD_SEPARATOR_EX
192 
193 #define DEFINE_UNICODE TRUE
194 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
195 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExW
196 #include "include/PathCchAddSeparatorEx.c"
197 #undef DEFINE_UNICODE
198 #undef _PATH_SEPARATOR_CHR
199 #undef PATH_CCH_ADD_SEPARATOR_EX
200 
PathCchRemoveBackslashExA(PSTR pszPath,size_t cchPath,PSTR * ppszEnd,size_t * pcchRemaining)201 HRESULT PathCchRemoveBackslashExA(PSTR pszPath, size_t cchPath, PSTR* ppszEnd,
202                                   size_t* pcchRemaining)
203 {
204 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
205 	return E_NOTIMPL;
206 }
207 
PathCchRemoveBackslashExW(PWSTR pszPath,size_t cchPath,PWSTR * ppszEnd,size_t * pcchRemaining)208 HRESULT PathCchRemoveBackslashExW(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd,
209                                   size_t* pcchRemaining)
210 {
211 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
212 	return E_NOTIMPL;
213 }
214 
215 /*
216  * PathCchAddExtension
217  */
218 
219 /* Windows-style Paths */
220 
221 #define DEFINE_UNICODE FALSE
222 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
223 #define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA
224 #include "include/PathCchAddExtension.c"
225 #undef DEFINE_UNICODE
226 #undef _PATH_SEPARATOR_CHR
227 #undef PATH_CCH_ADD_EXTENSION
228 
229 #define DEFINE_UNICODE TRUE
230 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
231 #define PATH_CCH_ADD_EXTENSION PathCchAddExtensionW
232 #include "include/PathCchAddExtension.c"
233 #undef DEFINE_UNICODE
234 #undef _PATH_SEPARATOR_CHR
235 #undef PATH_CCH_ADD_EXTENSION
236 
237 /* Unix-style Paths */
238 
239 #define DEFINE_UNICODE FALSE
240 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
241 #define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionA
242 #include "include/PathCchAddExtension.c"
243 #undef DEFINE_UNICODE
244 #undef _PATH_SEPARATOR_CHR
245 #undef PATH_CCH_ADD_EXTENSION
246 
247 #define DEFINE_UNICODE TRUE
248 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
249 #define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionW
250 #include "include/PathCchAddExtension.c"
251 #undef DEFINE_UNICODE
252 #undef _PATH_SEPARATOR_CHR
253 #undef PATH_CCH_ADD_EXTENSION
254 
255 /* Native-style Paths */
256 
257 #define DEFINE_UNICODE FALSE
258 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
259 #define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionA
260 #include "include/PathCchAddExtension.c"
261 #undef DEFINE_UNICODE
262 #undef _PATH_SEPARATOR_CHR
263 #undef PATH_CCH_ADD_EXTENSION
264 
265 #define DEFINE_UNICODE TRUE
266 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
267 #define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionW
268 #include "include/PathCchAddExtension.c"
269 #undef DEFINE_UNICODE
270 #undef _PATH_SEPARATOR_CHR
271 #undef PATH_CCH_ADD_EXTENSION
272 
273 /*
274  * PathCchAppend
275  */
276 
277 /* Windows-style Paths */
278 
279 #define DEFINE_UNICODE FALSE
280 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
281 #define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR
282 #define PATH_CCH_APPEND PathCchAppendA
283 #include "include/PathCchAppend.c"
284 #undef DEFINE_UNICODE
285 #undef _PATH_SEPARATOR_CHR
286 #undef _PATH_SEPARATOR_STR
287 #undef PATH_CCH_APPEND
288 
289 #define DEFINE_UNICODE TRUE
290 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
291 #define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
292 #define PATH_CCH_APPEND PathCchAppendW
293 #include "include/PathCchAppend.c"
294 #undef DEFINE_UNICODE
295 #undef _PATH_SEPARATOR_CHR
296 #undef _PATH_SEPARATOR_STR
297 #undef PATH_CCH_APPEND
298 
299 /* Unix-style Paths */
300 
301 #define DEFINE_UNICODE FALSE
302 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
303 #define _PATH_SEPARATOR_STR PATH_SLASH_STR
304 #define PATH_CCH_APPEND UnixPathCchAppendA
305 #include "include/PathCchAppend.c"
306 #undef DEFINE_UNICODE
307 #undef _PATH_SEPARATOR_CHR
308 #undef _PATH_SEPARATOR_STR
309 #undef PATH_CCH_APPEND
310 
311 #define DEFINE_UNICODE TRUE
312 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
313 #define _PATH_SEPARATOR_STR PATH_SLASH_STR_W
314 #define PATH_CCH_APPEND UnixPathCchAppendW
315 #include "include/PathCchAppend.c"
316 #undef DEFINE_UNICODE
317 #undef _PATH_SEPARATOR_CHR
318 #undef _PATH_SEPARATOR_STR
319 #undef PATH_CCH_APPEND
320 
321 /* Native-style Paths */
322 
323 #define DEFINE_UNICODE FALSE
324 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
325 #define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR
326 #define PATH_CCH_APPEND NativePathCchAppendA
327 #include "include/PathCchAppend.c"
328 #undef DEFINE_UNICODE
329 #undef _PATH_SEPARATOR_CHR
330 #undef _PATH_SEPARATOR_STR
331 #undef PATH_CCH_APPEND
332 
333 #define DEFINE_UNICODE TRUE
334 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
335 #define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
336 #define PATH_CCH_APPEND NativePathCchAppendW
337 #include "include/PathCchAppend.c"
338 #undef DEFINE_UNICODE
339 #undef _PATH_SEPARATOR_CHR
340 #undef _PATH_SEPARATOR_STR
341 #undef PATH_CCH_APPEND
342 
343 /*
344  * PathCchAppendEx
345  */
346 
PathCchAppendExA(PSTR pszPath,size_t cchPath,PCSTR pszMore,unsigned long dwFlags)347 HRESULT PathCchAppendExA(PSTR pszPath, size_t cchPath, PCSTR pszMore, unsigned long dwFlags)
348 {
349 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
350 	return E_NOTIMPL;
351 }
352 
PathCchAppendExW(PWSTR pszPath,size_t cchPath,PCWSTR pszMore,unsigned long dwFlags)353 HRESULT PathCchAppendExW(PWSTR pszPath, size_t cchPath, PCWSTR pszMore, unsigned long dwFlags)
354 {
355 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
356 	return E_NOTIMPL;
357 }
358 
359 /*
360  * PathCchCanonicalize
361  */
362 
PathCchCanonicalizeA(PSTR pszPathOut,size_t cchPathOut,PCSTR pszPathIn)363 HRESULT PathCchCanonicalizeA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn)
364 {
365 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
366 	return E_NOTIMPL;
367 }
368 
PathCchCanonicalizeW(PWSTR pszPathOut,size_t cchPathOut,PCWSTR pszPathIn)369 HRESULT PathCchCanonicalizeW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn)
370 {
371 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
372 	return E_NOTIMPL;
373 }
374 
375 /*
376  * PathCchCanonicalizeEx
377  */
378 
PathCchCanonicalizeExA(PSTR pszPathOut,size_t cchPathOut,PCSTR pszPathIn,unsigned long dwFlags)379 HRESULT PathCchCanonicalizeExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn,
380                                unsigned long dwFlags)
381 {
382 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
383 	return E_NOTIMPL;
384 }
385 
PathCchCanonicalizeExW(PWSTR pszPathOut,size_t cchPathOut,PCWSTR pszPathIn,unsigned long dwFlags)386 HRESULT PathCchCanonicalizeExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn,
387                                unsigned long dwFlags)
388 {
389 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
390 	return E_NOTIMPL;
391 }
392 
393 /*
394  * PathAllocCanonicalize
395  */
396 
PathAllocCanonicalizeA(PCSTR pszPathIn,unsigned long dwFlags,PSTR * ppszPathOut)397 HRESULT PathAllocCanonicalizeA(PCSTR pszPathIn, unsigned long dwFlags, PSTR* ppszPathOut)
398 {
399 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
400 	return E_NOTIMPL;
401 }
402 
PathAllocCanonicalizeW(PCWSTR pszPathIn,unsigned long dwFlags,PWSTR * ppszPathOut)403 HRESULT PathAllocCanonicalizeW(PCWSTR pszPathIn, unsigned long dwFlags, PWSTR* ppszPathOut)
404 {
405 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
406 	return E_NOTIMPL;
407 }
408 
409 /*
410  * PathCchCombine
411  */
412 
PathCchCombineA(PSTR pszPathOut,size_t cchPathOut,PCSTR pszPathIn,PCSTR pszMore)413 HRESULT PathCchCombineA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore)
414 {
415 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
416 	return E_NOTIMPL;
417 }
418 
PathCchCombineW(PWSTR pszPathOut,size_t cchPathOut,PCWSTR pszPathIn,PCWSTR pszMore)419 HRESULT PathCchCombineW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore)
420 {
421 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
422 	return E_NOTIMPL;
423 }
424 
425 /*
426  * PathCchCombineEx
427  */
428 
PathCchCombineExA(PSTR pszPathOut,size_t cchPathOut,PCSTR pszPathIn,PCSTR pszMore,unsigned long dwFlags)429 HRESULT PathCchCombineExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore,
430                           unsigned long dwFlags)
431 {
432 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
433 	return E_NOTIMPL;
434 }
435 
PathCchCombineExW(PWSTR pszPathOut,size_t cchPathOut,PCWSTR pszPathIn,PCWSTR pszMore,unsigned long dwFlags)436 HRESULT PathCchCombineExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore,
437                           unsigned long dwFlags)
438 {
439 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
440 	return E_NOTIMPL;
441 }
442 
443 /*
444  * PathAllocCombine
445  */
446 
447 /* Windows-style Paths */
448 
449 #define DEFINE_UNICODE FALSE
450 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
451 #define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR
452 #define PATH_ALLOC_COMBINE PathAllocCombineA
453 #include "include/PathAllocCombine.c"
454 #undef DEFINE_UNICODE
455 #undef _PATH_SEPARATOR_CHR
456 #undef _PATH_SEPARATOR_STR
457 #undef PATH_ALLOC_COMBINE
458 
459 #define DEFINE_UNICODE TRUE
460 #define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
461 #define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
462 #define PATH_ALLOC_COMBINE PathAllocCombineW
463 #include "include/PathAllocCombine.c"
464 #undef DEFINE_UNICODE
465 #undef _PATH_SEPARATOR_CHR
466 #undef _PATH_SEPARATOR_STR
467 #undef PATH_ALLOC_COMBINE
468 
469 /* Unix-style Paths */
470 
471 #define DEFINE_UNICODE FALSE
472 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
473 #define _PATH_SEPARATOR_STR PATH_SLASH_STR
474 #define PATH_ALLOC_COMBINE UnixPathAllocCombineA
475 #include "include/PathAllocCombine.c"
476 #undef DEFINE_UNICODE
477 #undef _PATH_SEPARATOR_CHR
478 #undef _PATH_SEPARATOR_STR
479 #undef PATH_ALLOC_COMBINE
480 
481 #define DEFINE_UNICODE TRUE
482 #define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
483 #define _PATH_SEPARATOR_STR PATH_SLASH_STR_W
484 #define PATH_ALLOC_COMBINE UnixPathAllocCombineW
485 #include "include/PathAllocCombine.c"
486 #undef DEFINE_UNICODE
487 #undef _PATH_SEPARATOR_CHR
488 #undef _PATH_SEPARATOR_STR
489 #undef PATH_ALLOC_COMBINE
490 
491 /* Native-style Paths */
492 
493 #define DEFINE_UNICODE FALSE
494 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
495 #define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR
496 #define PATH_ALLOC_COMBINE NativePathAllocCombineA
497 #include "include/PathAllocCombine.c"
498 #undef DEFINE_UNICODE
499 #undef _PATH_SEPARATOR_CHR
500 #undef _PATH_SEPARATOR_STR
501 #undef PATH_ALLOC_COMBINE
502 
503 #define DEFINE_UNICODE TRUE
504 #define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
505 #define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
506 #define PATH_ALLOC_COMBINE NativePathAllocCombineW
507 #include "include/PathAllocCombine.c"
508 #undef DEFINE_UNICODE
509 #undef _PATH_SEPARATOR_CHR
510 #undef _PATH_SEPARATOR_STR
511 #undef PATH_ALLOC_COMBINE
512 
513 /**
514  * PathCchFindExtension
515  */
516 
PathCchFindExtensionA(PCSTR pszPath,size_t cchPath,PCSTR * ppszExt)517 HRESULT PathCchFindExtensionA(PCSTR pszPath, size_t cchPath, PCSTR* ppszExt)
518 {
519 	char* p = (char*)pszPath;
520 
521 	if (!pszPath || !cchPath || !ppszExt)
522 		return E_INVALIDARG;
523 
524 	/* find end of string */
525 
526 	while (*p && --cchPath)
527 	{
528 		p++;
529 	}
530 
531 	if (*p)
532 	{
533 		/* pszPath is not null terminated within the cchPath range */
534 		return E_INVALIDARG;
535 	}
536 
537 	/* If no extension is found, ppszExt must point to the string's terminating null */
538 	*ppszExt = p;
539 
540 	/* search backwards for '.' */
541 
542 	while (p > pszPath)
543 	{
544 		if (*p == '.')
545 		{
546 			*ppszExt = (PCSTR)p;
547 			break;
548 		}
549 
550 		if ((*p == '\\') || (*p == '/') || (*p == ':'))
551 			break;
552 
553 		p--;
554 	}
555 
556 	return S_OK;
557 }
558 
PathCchFindExtensionW(PCWSTR pszPath,size_t cchPath,PCWSTR * ppszExt)559 HRESULT PathCchFindExtensionW(PCWSTR pszPath, size_t cchPath, PCWSTR* ppszExt)
560 {
561 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
562 	return E_NOTIMPL;
563 }
564 
565 /**
566  * PathCchRenameExtension
567  */
568 
PathCchRenameExtensionA(PSTR pszPath,size_t cchPath,PCSTR pszExt)569 HRESULT PathCchRenameExtensionA(PSTR pszPath, size_t cchPath, PCSTR pszExt)
570 {
571 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
572 	return E_NOTIMPL;
573 }
574 
PathCchRenameExtensionW(PWSTR pszPath,size_t cchPath,PCWSTR pszExt)575 HRESULT PathCchRenameExtensionW(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
576 {
577 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
578 	return E_NOTIMPL;
579 }
580 
581 /**
582  * PathCchRemoveExtension
583  */
584 
PathCchRemoveExtensionA(PSTR pszPath,size_t cchPath)585 HRESULT PathCchRemoveExtensionA(PSTR pszPath, size_t cchPath)
586 {
587 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
588 	return E_NOTIMPL;
589 }
590 
PathCchRemoveExtensionW(PWSTR pszPath,size_t cchPath)591 HRESULT PathCchRemoveExtensionW(PWSTR pszPath, size_t cchPath)
592 {
593 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
594 	return E_NOTIMPL;
595 }
596 
597 /**
598  * PathCchIsRoot
599  */
600 
PathCchIsRootA(PCSTR pszPath)601 BOOL PathCchIsRootA(PCSTR pszPath)
602 {
603 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
604 	return FALSE;
605 }
606 
PathCchIsRootW(PCWSTR pszPath)607 BOOL PathCchIsRootW(PCWSTR pszPath)
608 {
609 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
610 	return FALSE;
611 }
612 
613 /**
614  * PathIsUNCEx
615  */
616 
PathIsUNCExA(PCSTR pszPath,PCSTR * ppszServer)617 BOOL PathIsUNCExA(PCSTR pszPath, PCSTR* ppszServer)
618 {
619 	if (!pszPath)
620 		return FALSE;
621 
622 	if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
623 	{
624 		*ppszServer = &pszPath[2];
625 		return TRUE;
626 	}
627 
628 	return FALSE;
629 }
630 
PathIsUNCExW(PCWSTR pszPath,PCWSTR * ppszServer)631 BOOL PathIsUNCExW(PCWSTR pszPath, PCWSTR* ppszServer)
632 {
633 	if (!pszPath)
634 		return FALSE;
635 
636 	if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
637 	{
638 		*ppszServer = &pszPath[2];
639 		return TRUE;
640 	}
641 
642 	return FALSE;
643 }
644 
645 /**
646  * PathCchSkipRoot
647  */
648 
PathCchSkipRootA(PCSTR pszPath,PCSTR * ppszRootEnd)649 HRESULT PathCchSkipRootA(PCSTR pszPath, PCSTR* ppszRootEnd)
650 {
651 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
652 	return E_NOTIMPL;
653 }
654 
PathCchSkipRootW(PCWSTR pszPath,PCWSTR * ppszRootEnd)655 HRESULT PathCchSkipRootW(PCWSTR pszPath, PCWSTR* ppszRootEnd)
656 {
657 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
658 	return E_NOTIMPL;
659 }
660 
661 /**
662  * PathCchStripToRoot
663  */
664 
PathCchStripToRootA(PSTR pszPath,size_t cchPath)665 HRESULT PathCchStripToRootA(PSTR pszPath, size_t cchPath)
666 {
667 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
668 	return E_NOTIMPL;
669 }
670 
PathCchStripToRootW(PWSTR pszPath,size_t cchPath)671 HRESULT PathCchStripToRootW(PWSTR pszPath, size_t cchPath)
672 {
673 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
674 	return E_NOTIMPL;
675 }
676 
677 /**
678  * PathCchStripPrefix
679  */
680 
PathCchStripPrefixA(PSTR pszPath,size_t cchPath)681 HRESULT PathCchStripPrefixA(PSTR pszPath, size_t cchPath)
682 {
683 	BOOL hasPrefix;
684 
685 	if (!pszPath)
686 		return E_INVALIDARG;
687 
688 	if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
689 		return E_INVALIDARG;
690 
691 	hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') && (pszPath[2] == '?') &&
692 	             (pszPath[3] == '\\'))
693 	                ? TRUE
694 	                : FALSE;
695 
696 	if (hasPrefix)
697 	{
698 		if (cchPath < 6)
699 			return S_FALSE;
700 
701 		if (IsCharAlpha(pszPath[4]) && (pszPath[5] == ':')) /* like C: */
702 		{
703 			memmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4);
704 			/* since the passed pszPath must not necessarily be null terminated
705 			 * and we always have enough space after the strip we can always
706 			 * ensure the null termination of the stripped result
707 			 */
708 			pszPath[cchPath - 4] = 0;
709 			return S_OK;
710 		}
711 	}
712 
713 	return S_FALSE;
714 }
715 
PathCchStripPrefixW(PWSTR pszPath,size_t cchPath)716 HRESULT PathCchStripPrefixW(PWSTR pszPath, size_t cchPath)
717 {
718 	BOOL hasPrefix;
719 
720 	if (!pszPath)
721 		return E_INVALIDARG;
722 
723 	if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
724 		return E_INVALIDARG;
725 
726 	hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') && (pszPath[2] == '?') &&
727 	             (pszPath[3] == '\\'))
728 	                ? TRUE
729 	                : FALSE;
730 
731 	if (hasPrefix)
732 	{
733 		int rc;
734 		if (cchPath < 6)
735 			return S_FALSE;
736 
737 		rc = (lstrlenW(&pszPath[4]) + 1);
738 		if ((rc < 0) || ((INT64)cchPath < rc))
739 			return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
740 
741 		if (IsCharAlphaW(pszPath[4]) && (pszPath[5] == L':')) /* like C: */
742 		{
743 			wmemmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4);
744 			/* since the passed pszPath must not necessarily be null terminated
745 			 * and we always have enough space after the strip we can always
746 			 * ensure the null termination of the stripped result
747 			 */
748 			pszPath[cchPath - 4] = 0;
749 			return S_OK;
750 		}
751 	}
752 
753 	return S_FALSE;
754 }
755 
756 /**
757  * PathCchRemoveFileSpec
758  */
759 
PathCchRemoveFileSpecA(PSTR pszPath,size_t cchPath)760 HRESULT PathCchRemoveFileSpecA(PSTR pszPath, size_t cchPath)
761 {
762 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
763 	return E_NOTIMPL;
764 }
765 
PathCchRemoveFileSpecW(PWSTR pszPath,size_t cchPath)766 HRESULT PathCchRemoveFileSpecW(PWSTR pszPath, size_t cchPath)
767 {
768 	WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
769 	return E_NOTIMPL;
770 }
771 
772 /*
773  * Path Portability Functions
774  */
775 
776 /**
777  * PathCchConvertStyle
778  */
779 
PathCchConvertStyleA(PSTR pszPath,size_t cchPath,unsigned long dwFlags)780 HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags)
781 {
782 	size_t index;
783 
784 	if (dwFlags == PATH_STYLE_WINDOWS)
785 	{
786 		for (index = 0; index < cchPath; index++)
787 		{
788 			if (pszPath[index] == PATH_SLASH_CHR)
789 				pszPath[index] = PATH_BACKSLASH_CHR;
790 		}
791 	}
792 	else if (dwFlags == PATH_STYLE_UNIX)
793 	{
794 		for (index = 0; index < cchPath; index++)
795 		{
796 			if (pszPath[index] == PATH_BACKSLASH_CHR)
797 				pszPath[index] = PATH_SLASH_CHR;
798 		}
799 	}
800 	else if (dwFlags == PATH_STYLE_NATIVE)
801 	{
802 		if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
803 		{
804 			/* Unix-style to Windows-style */
805 
806 			for (index = 0; index < cchPath; index++)
807 			{
808 				if (pszPath[index] == PATH_SLASH_CHR)
809 					pszPath[index] = PATH_BACKSLASH_CHR;
810 			}
811 		}
812 		else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
813 		{
814 			/* Windows-style to Unix-style */
815 
816 			for (index = 0; index < cchPath; index++)
817 			{
818 				if (pszPath[index] == PATH_BACKSLASH_CHR)
819 					pszPath[index] = PATH_SLASH_CHR;
820 			}
821 		}
822 		else
823 		{
824 			/* Unexpected error */
825 			return E_FAIL;
826 		}
827 	}
828 	else
829 	{
830 		/* Gangnam style? */
831 		return E_FAIL;
832 	}
833 
834 	return S_OK;
835 }
836 
PathCchConvertStyleW(PWSTR pszPath,size_t cchPath,unsigned long dwFlags)837 HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags)
838 {
839 	size_t index;
840 
841 	if (dwFlags == PATH_STYLE_WINDOWS)
842 	{
843 		for (index = 0; index < cchPath; index++)
844 		{
845 			if (pszPath[index] == PATH_SLASH_CHR)
846 				pszPath[index] = PATH_BACKSLASH_CHR;
847 		}
848 	}
849 	else if (dwFlags == PATH_STYLE_UNIX)
850 	{
851 		for (index = 0; index < cchPath; index++)
852 		{
853 			if (pszPath[index] == PATH_BACKSLASH_CHR)
854 				pszPath[index] = PATH_SLASH_CHR;
855 		}
856 	}
857 	else if (dwFlags == PATH_STYLE_NATIVE)
858 	{
859 		if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
860 		{
861 			/* Unix-style to Windows-style */
862 
863 			for (index = 0; index < cchPath; index++)
864 			{
865 				if (pszPath[index] == PATH_SLASH_CHR)
866 					pszPath[index] = PATH_BACKSLASH_CHR;
867 			}
868 		}
869 		else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
870 		{
871 			/* Windows-style to Unix-style */
872 
873 			for (index = 0; index < cchPath; index++)
874 			{
875 				if (pszPath[index] == PATH_BACKSLASH_CHR)
876 					pszPath[index] = PATH_SLASH_CHR;
877 			}
878 		}
879 		else
880 		{
881 			/* Unexpected error */
882 			return E_FAIL;
883 		}
884 	}
885 	else
886 	{
887 		/* Gangnam style? */
888 		return E_FAIL;
889 	}
890 
891 	return S_OK;
892 }
893 
894 /**
895  * PathGetSeparator
896  */
897 
PathGetSeparatorA(unsigned long dwFlags)898 char PathGetSeparatorA(unsigned long dwFlags)
899 {
900 	char separator = PATH_SEPARATOR_CHR;
901 
902 	if (!dwFlags)
903 		dwFlags = PATH_STYLE_NATIVE;
904 
905 	if (dwFlags == PATH_STYLE_WINDOWS)
906 		separator = PATH_SEPARATOR_CHR;
907 	else if (dwFlags == PATH_STYLE_UNIX)
908 		separator = PATH_SEPARATOR_CHR;
909 	else if (dwFlags == PATH_STYLE_NATIVE)
910 		separator = PATH_SEPARATOR_CHR;
911 
912 	return separator;
913 }
914 
PathGetSeparatorW(unsigned long dwFlags)915 WCHAR PathGetSeparatorW(unsigned long dwFlags)
916 {
917 	WCHAR separator = PATH_SEPARATOR_CHR;
918 
919 	if (!dwFlags)
920 		dwFlags = PATH_STYLE_NATIVE;
921 
922 	if (dwFlags == PATH_STYLE_WINDOWS)
923 		separator = PATH_SEPARATOR_CHR;
924 	else if (dwFlags == PATH_STYLE_UNIX)
925 		separator = PATH_SEPARATOR_CHR;
926 	else if (dwFlags == PATH_STYLE_NATIVE)
927 		separator = PATH_SEPARATOR_CHR;
928 
929 	return separator;
930 }
931 
932 /**
933  * PathGetSharedLibraryExtension
934  */
935 
936 static const CHAR SharedLibraryExtensionDllA[] = "dll";
937 static const CHAR SharedLibraryExtensionSoA[] = "so";
938 static const CHAR SharedLibraryExtensionDylibA[] = "dylib";
939 
940 static const WCHAR SharedLibraryExtensionDllW[] = { 'd', 'l', 'l', '\0' };
941 static const WCHAR SharedLibraryExtensionSoW[] = { 's', 'o', '\0' };
942 static const WCHAR SharedLibraryExtensionDylibW[] = { 'd', 'y', 'l', 'i', 'b', '\0' };
943 
944 static const CHAR SharedLibraryExtensionDotDllA[] = ".dll";
945 static const CHAR SharedLibraryExtensionDotSoA[] = ".so";
946 static const CHAR SharedLibraryExtensionDotDylibA[] = ".dylib";
947 
948 static const WCHAR SharedLibraryExtensionDotDllW[] = { '.', 'd', 'l', 'l', '\0' };
949 static const WCHAR SharedLibraryExtensionDotSoW[] = { '.', 's', 'o', '\0' };
950 static const WCHAR SharedLibraryExtensionDotDylibW[] = { '.', 'd', 'y', 'l', 'i', 'b', '\0' };
951 
PathGetSharedLibraryExtensionA(unsigned long dwFlags)952 PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags)
953 {
954 	if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
955 	{
956 		if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
957 		{
958 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
959 				return SharedLibraryExtensionDotDllA;
960 
961 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
962 				return SharedLibraryExtensionDotSoA;
963 
964 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
965 				return SharedLibraryExtensionDotDylibA;
966 		}
967 		else
968 		{
969 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
970 				return SharedLibraryExtensionDllA;
971 
972 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
973 				return SharedLibraryExtensionSoA;
974 
975 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
976 				return SharedLibraryExtensionDylibA;
977 		}
978 	}
979 
980 	if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
981 	{
982 #ifdef _WIN32
983 		return SharedLibraryExtensionDotDllA;
984 #elif defined(__APPLE__)
985 		if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
986 			return SharedLibraryExtensionDotSoA;
987 		else
988 			return SharedLibraryExtensionDotDylibA;
989 #else
990 		return SharedLibraryExtensionDotSoA;
991 #endif
992 	}
993 	else
994 	{
995 #ifdef _WIN32
996 		return SharedLibraryExtensionDllA;
997 #elif defined(__APPLE__)
998 		if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
999 			return SharedLibraryExtensionSoA;
1000 		else
1001 			return SharedLibraryExtensionDylibA;
1002 #else
1003 		return SharedLibraryExtensionSoA;
1004 #endif
1005 	}
1006 
1007 	return NULL;
1008 }
1009 
PathGetSharedLibraryExtensionW(unsigned long dwFlags)1010 PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags)
1011 {
1012 	if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1013 	{
1014 		if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1015 		{
1016 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1017 				return SharedLibraryExtensionDotDllW;
1018 
1019 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1020 				return SharedLibraryExtensionDotSoW;
1021 
1022 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1023 				return SharedLibraryExtensionDotDylibW;
1024 		}
1025 		else
1026 		{
1027 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1028 				return SharedLibraryExtensionDllW;
1029 
1030 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1031 				return SharedLibraryExtensionSoW;
1032 
1033 			if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1034 				return SharedLibraryExtensionDylibW;
1035 		}
1036 	}
1037 
1038 	if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1039 	{
1040 #ifdef _WIN32
1041 		return SharedLibraryExtensionDotDllW;
1042 #elif defined(__APPLE__)
1043 		if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1044 			return SharedLibraryExtensionDotSoW;
1045 		else
1046 			return SharedLibraryExtensionDotDylibW;
1047 #else
1048 		return SharedLibraryExtensionDotSoW;
1049 #endif
1050 	}
1051 	else
1052 	{
1053 #ifdef _WIN32
1054 		return SharedLibraryExtensionDllW;
1055 #elif defined(__APPLE__)
1056 		if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1057 			return SharedLibraryExtensionSoW;
1058 		else
1059 			return SharedLibraryExtensionDylibW;
1060 #else
1061 		return SharedLibraryExtensionSoW;
1062 #endif
1063 	}
1064 
1065 	return NULL;
1066 }
1067