ReactOS 0.4.15-dev-7961-gdcf9eb0
pathcch.c File Reference
#include <stdarg.h>
#include <string.h>
#include <windef.h>
#include <winbase.h>
#include <pathcch.h>
#include <strsafe.h>
#include "wine/debug.h"
Include dependency graph for pathcch.c:

Go to the source code of this file.

Macros

#define STATIC_PATHCCH
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (path)
 
static BOOL is_drive_spec (const WCHAR *str)
 
static BOOL is_prefixed_unc (const WCHAR *string)
 
static BOOL is_prefixed_disk (const WCHAR *string)
 
static BOOL is_prefixed_volume (const WCHAR *string)
 
static BOOL get_next_segment (const WCHAR *next, const WCHAR **next_segment)
 
static const WCHARget_root_end (const WCHAR *path)
 
HRESULT WINAPI PathAllocCanonicalize (const WCHAR *path_in, DWORD flags, WCHAR **path_out)
 
HRESULT WINAPI PathAllocCombine (const WCHAR *path1, const WCHAR *path2, DWORD flags, WCHAR **out)
 
HRESULT WINAPI PathCchAddBackslash (WCHAR *path, SIZE_T size)
 
HRESULT WINAPI PathCchAddBackslashEx (WCHAR *path, SIZE_T size, WCHAR **endptr, SIZE_T *remaining)
 
HRESULT WINAPI PathCchAddExtension (WCHAR *path, SIZE_T size, const WCHAR *extension)
 
HRESULT WINAPI PathCchAppend (WCHAR *path1, SIZE_T size, const WCHAR *path2)
 
HRESULT WINAPI PathCchAppendEx (WCHAR *path1, SIZE_T size, const WCHAR *path2, DWORD flags)
 
HRESULT WINAPI PathCchCanonicalize (WCHAR *out, SIZE_T size, const WCHAR *in)
 
HRESULT WINAPI PathCchCanonicalizeEx (WCHAR *out, SIZE_T size, const WCHAR *in, DWORD flags)
 
HRESULT WINAPI PathCchCombine (WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2)
 
HRESULT WINAPI PathCchCombineEx (WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2, DWORD flags)
 
HRESULT WINAPI PathCchFindExtension (const WCHAR *path, SIZE_T size, const WCHAR **extension)
 
BOOL WINAPI PathCchIsRoot (const WCHAR *path)
 
HRESULT WINAPI PathCchRemoveBackslash (WCHAR *path, SIZE_T path_size)
 
HRESULT WINAPI PathCchRemoveBackslashEx (WCHAR *path, SIZE_T path_size, WCHAR **path_end, SIZE_T *free_size)
 
HRESULT WINAPI PathCchRemoveExtension (WCHAR *path, SIZE_T size)
 
HRESULT WINAPI PathCchRemoveFileSpec (WCHAR *path, SIZE_T size)
 
HRESULT WINAPI PathCchRenameExtension (WCHAR *path, SIZE_T size, const WCHAR *extension)
 
HRESULT WINAPI PathCchSkipRoot (const WCHAR *path, const WCHAR **root_end)
 
HRESULT WINAPI PathCchStripPrefix (WCHAR *path, SIZE_T size)
 
HRESULT WINAPI PathCchStripToRoot (WCHAR *path, SIZE_T size)
 
BOOL WINAPI PathIsUNCEx (const WCHAR *path, const WCHAR **server)
 

Macro Definition Documentation

◆ STATIC_PATHCCH

#define STATIC_PATHCCH

Definition at line 39 of file pathcch.c.

Function Documentation

◆ get_next_segment()

static BOOL get_next_segment ( const WCHAR next,
const WCHAR **  next_segment 
)
static

Definition at line 122 of file pathcch.c.

123{
124 while (*next && *next != '\\') next++;
125 if (*next == '\\')
126 {
127 *next_segment = next + 1;
128 return TRUE;
129 }
130 else
131 {
132 *next_segment = next;
133 return FALSE;
134 }
135}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static unsigned __int64 next
Definition: rand_nt.c:6

Referenced by PathCchIsRoot(), PathCchSkipRoot(), and PathCchStripToRoot().

◆ get_root_end()

static const WCHAR * get_root_end ( const WCHAR path)
static

Definition at line 138 of file pathcch.c.

139{
140 /* Find path root */
142 return path[48] == '\\' ? path + 48 : path + 47;
143 else if (is_prefixed_unc(path))
144 return path + 7;
145 else if (is_prefixed_disk(path))
146 return path[6] == '\\' ? path + 6 : path + 5;
147 /* \\ */
148 else if (path[0] == '\\' && path[1] == '\\')
149 return path + 1;
150 /* \ */
151 else if (path[0] == '\\')
152 return path;
153 /* X:\ */
154 else if (is_drive_spec( path ))
155 return path[2] == '\\' ? path + 2 : path + 1;
156 else
157 return NULL;
158}
#define NULL
Definition: types.h:112
static BOOL is_prefixed_unc(const WCHAR *string)
Definition: pathcch.c:75
static BOOL is_prefixed_volume(const WCHAR *string)
Definition: pathcch.c:85
static BOOL is_prefixed_disk(const WCHAR *string)
Definition: pathcch.c:80
static BOOL is_drive_spec(const WCHAR *str)
Definition: pathcch.c:63

Referenced by PathAllocCanonicalize(), PathCchIsRoot(), PathCchRemoveBackslashEx(), and PathCchSkipRoot().

◆ is_drive_spec()

static BOOL is_drive_spec ( const WCHAR str)
static

Definition at line 63 of file pathcch.c.

64{
65 return isalpha( str[0] ) && str[1] == ':';
66}
#define isalpha(c)
Definition: acclib.h:74
const WCHAR * str

Referenced by get_root_end(), is_prefixed_disk(), PathAllocCanonicalize(), PathAllocCombine(), PathCchCanonicalize(), and PathCchCanonicalizeEx().

◆ is_prefixed_disk()

static BOOL is_prefixed_disk ( const WCHAR string)
static

Definition at line 80 of file pathcch.c.

81{
82 return !wcsncmp(string, L"\\\\?\\", 4) && is_drive_spec( string + 4 );
83}
#define L(x)
Definition: ntvdm.h:50
_Check_return_ _CRTIMP int __cdecl wcsncmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)

Referenced by get_root_end(), PathAllocCombine(), PathCchSkipRoot(), and PathCchStripPrefix().

◆ is_prefixed_unc()

static BOOL is_prefixed_unc ( const WCHAR string)
static

Definition at line 75 of file pathcch.c.

76{
77 return !wcsnicmp(string, L"\\\\?\\UNC\\", 8 );
78}
#define wcsnicmp
Definition: compat.h:14

Referenced by get_root_end(), PathCchIsRoot(), PathCchRemoveFileSpec(), PathCchSkipRoot(), PathCchStripPrefix(), PathCchStripToRoot(), and PathIsUNCEx().

◆ is_prefixed_volume()

static BOOL is_prefixed_volume ( const WCHAR string)
static

Definition at line 85 of file pathcch.c.

86{
87 const WCHAR *guid;
88 INT i = 0;
89
90 if (wcsnicmp( string, L"\\\\?\\Volume", 10 )) return FALSE;
91
92 guid = string + 10;
93
94 while (i <= 37)
95 {
96 switch (i)
97 {
98 case 0:
99 if (guid[i] != '{') return FALSE;
100 break;
101 case 9:
102 case 14:
103 case 19:
104 case 24:
105 if (guid[i] != '-') return FALSE;
106 break;
107 case 37:
108 if (guid[i] != '}') return FALSE;
109 break;
110 default:
111 if (!isxdigit(guid[i])) return FALSE;
112 break;
113 }
114 i++;
115 }
116
117 return TRUE;
118}
#define isxdigit(c)
Definition: acclib.h:70
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const GUID * guid
int32_t INT
Definition: typedefs.h:58
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by get_root_end(), and PathCchSkipRoot().

◆ PathAllocCanonicalize()

HRESULT WINAPI PathAllocCanonicalize ( const WCHAR path_in,
DWORD  flags,
WCHAR **  path_out 
)

Definition at line 168 of file pathcch.c.

170{
171 WCHAR *buffer, *dst;
172 const WCHAR *src;
173 const WCHAR *root_end;
175
176 TRACE("%s %#lx %p\n", debugstr_w(path_in), flags, path_out);
177
178 if (!path_in || !path_out
183 {
184 if (path_out) *path_out = NULL;
185 return E_INVALIDARG;
186 }
187
188 length = lstrlenW(path_in);
190 || (length + 1 > PATHCCH_MAX_CCH))
191 {
192 *path_out = NULL;
194 }
195
196 /* PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH implies PATHCCH_DO_NOT_NORMALIZE_SEGMENTS */
198
199 /* path length + possible \\?\ addition + possible \ addition + NUL */
200 buffer_size = (length + 6) * sizeof(WCHAR);
202 if (!buffer)
203 {
204 *path_out = NULL;
205 return E_OUTOFMEMORY;
206 }
207
208 src = path_in;
209 dst = buffer;
210
211 root_end = get_root_end(path_in);
212 if (root_end) root_end = buffer + (root_end - path_in);
213
214 /* Copy path root */
215 if (root_end)
216 {
217 memcpy(dst, src, (root_end - buffer + 1) * sizeof(WCHAR));
218 src += root_end - buffer + 1;
219 if(PathCchStripPrefix(dst, length + 6) == S_OK)
220 {
221 /* Fill in \ in X:\ if the \ is missing */
222 if (is_drive_spec( dst ) && dst[2]!= '\\')
223 {
224 dst[2] = '\\';
225 dst[3] = 0;
226 }
228 root_end = dst;
229 }
230 else
231 dst += root_end - buffer + 1;
232 }
233
234 while (*src)
235 {
236 if (src[0] == '.')
237 {
238 if (src[1] == '.')
239 {
240 /* Keep one . after * */
241 if (dst > buffer && dst[-1] == '*')
242 {
243 *dst++ = *src++;
244 continue;
245 }
246
247 /* Keep the .. if not surrounded by \ */
248 if ((src[2] != '\\' && src[2]) || (dst > buffer && dst[-1] != '\\'))
249 {
250 *dst++ = *src++;
251 *dst++ = *src++;
252 continue;
253 }
254
255 /* Remove the \ before .. if the \ is not part of root */
256 if (dst > buffer && dst[-1] == '\\' && (!root_end || dst - 1 > root_end))
257 {
258 *--dst = '\0';
259 /* Remove characters until a \ is encountered */
260 while (dst > buffer)
261 {
262 if (dst[-1] == '\\')
263 {
264 *--dst = 0;
265 break;
266 }
267 else
268 *--dst = 0;
269 }
270 }
271 /* Remove the extra \ after .. if the \ before .. wasn't deleted */
272 else if (src[2] == '\\')
273 src++;
274
275 src += 2;
276 }
277 else
278 {
279 /* Keep the . if not surrounded by \ */
280 if ((src[1] != '\\' && src[1]) || (dst > buffer && dst[-1] != '\\'))
281 {
282 *dst++ = *src++;
283 continue;
284 }
285
286 /* Remove the \ before . if the \ is not part of root */
287 if (dst > buffer && dst[-1] == '\\' && (!root_end || dst - 1 > root_end)) dst--;
288 /* Remove the extra \ after . if the \ before . wasn't deleted */
289 else if (src[1] == '\\')
290 src++;
291
292 src++;
293 }
294
295 /* If X:\ is not complete, then complete it */
296 if (is_drive_spec( buffer ) && buffer[2] != '\\')
297 {
298 root_end = buffer + 2;
299 dst = buffer + 3;
300 buffer[2] = '\\';
301 /* If next character is \, use the \ to fill in */
302 if (src[0] == '\\') src++;
303 }
304 }
305 /* Copy over */
306 else
307 *dst++ = *src++;
308 }
309 /* End the path */
310 *dst = 0;
311
312 /* Strip multiple trailing . */
314 {
315 while (dst > buffer && dst[-1] == '.')
316 {
317 /* Keep a . after * */
318 if (dst - 1 > buffer && dst[-2] == '*')
319 break;
320 /* If . follow a : at the second character, remove the . and add a \ */
321 else if (dst - 1 > buffer && dst[-2] == ':' && dst - 2 == buffer + 1)
322 *--dst = '\\';
323 else
324 *--dst = 0;
325 }
326 }
327
328 /* If result path is empty, fill in \ */
329 if (!*buffer)
330 {
331 buffer[0] = '\\';
332 buffer[1] = 0;
333 }
334
335 /* Extend the path if needed */
337 if (((length + 1 > MAX_PATH && is_drive_spec( buffer ))
340 {
341 memmove(buffer + 4, buffer, (length + 1) * sizeof(WCHAR));
342 buffer[0] = '\\';
343 buffer[1] = '\\';
344 buffer[2] = '?';
345 buffer[3] = '\\';
346 }
347
348 /* Add a trailing backslash to the path if needed */
351
352 *path_out = buffer;
353 return S_OK;
354}
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define MAX_PATH
Definition: compat.h:34
#define lstrlenW
Definition: compat.h:750
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
#define S_OK
Definition: intsafe.h:52
#define debugstr_w
Definition: kernel32.h:32
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
HRESULT WINAPI PathCchStripPrefix(WCHAR *path, SIZE_T size)
Definition: pathcch.c:1005
static const WCHAR * get_root_end(const WCHAR *path)
Definition: pathcch.c:138
HRESULT WINAPI PathCchAddBackslash(WCHAR *path, SIZE_T size)
Definition: pathcch.c:431
#define PATHCCH_ENSURE_TRAILING_SLASH
Definition: pathcch.h:45
#define PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS
Definition: pathcch.h:41
#define PATHCCH_ALLOW_LONG_PATHS
Definition: pathcch.h:40
#define PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH
Definition: pathcch.h:44
#define PATHCCH_MAX_CCH
Definition: pathcch.h:51
#define PATHCCH_DO_NOT_NORMALIZE_SEGMENTS
Definition: pathcch.h:43
#define PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS
Definition: pathcch.h:42
#define TRACE(s)
Definition: solgame.cpp:4
static void buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
Definition: swimpl.c:888
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define LMEM_ZEROINIT
Definition: winbase.h:375
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92

Referenced by PathAllocCombine(), and PathCchCanonicalizeEx().

◆ PathAllocCombine()

HRESULT WINAPI PathAllocCombine ( const WCHAR path1,
const WCHAR path2,
DWORD  flags,
WCHAR **  out 
)

Definition at line 365 of file pathcch.c.

367{
368 SIZE_T combined_length, length2;
369 WCHAR *combined_path;
370 BOOL add_backslash = FALSE;
371 HRESULT hr;
372
373 TRACE("%s %s %#lx %p\n", wine_dbgstr_w(path1), wine_dbgstr_w(path2), flags, out);
374
375 if ((!path1 && !path2) || !out)
376 {
377 if (out) *out = NULL;
378 return E_INVALIDARG;
379 }
380
381 if (!path1 || !path2) return PathAllocCanonicalize(path1 ? path1 : path2, flags, out);
382
383 /* If path2 is fully qualified, use path2 only */
384 if (is_drive_spec( path2 ) || (path2[0] == '\\' && path2[1] == '\\'))
385 {
386 path1 = path2;
387 path2 = NULL;
388 add_backslash = (is_drive_spec(path1) && !path1[2])
389 || (is_prefixed_disk(path1) && !path1[6]);
390 }
391
392 length2 = path2 ? lstrlenW(path2) : 0;
393 /* path1 length + path2 length + possible backslash + NULL */
394 combined_length = lstrlenW(path1) + length2 + 2;
395
396 combined_path = HeapAlloc(GetProcessHeap(), 0, combined_length * sizeof(WCHAR));
397 if (!combined_path)
398 {
399 *out = NULL;
400 return E_OUTOFMEMORY;
401 }
402
403 lstrcpyW(combined_path, path1);
404 PathCchStripPrefix(combined_path, combined_length);
405 if (add_backslash) PathCchAddBackslashEx(combined_path, combined_length, NULL, NULL);
406
407 if (path2 && path2[0])
408 {
409 if (path2[0] == '\\' && path2[1] != '\\')
410 {
411 PathCchStripToRoot(combined_path, combined_length);
412 path2++;
413 }
414
415 PathCchAddBackslashEx(combined_path, combined_length, NULL, NULL);
416 lstrcatW(combined_path, path2);
417 }
418
419 hr = PathAllocCanonicalize(combined_path, flags, out);
420 HeapFree(GetProcessHeap(), 0, combined_path);
421 return hr;
422}
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
unsigned int BOOL
Definition: ntddk_ex.h:94
#define wine_dbgstr_w
Definition: kernel32.h:34
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
static const WCHAR path1[]
Definition: path.c:28
static const WCHAR path2[]
Definition: path.c:29
HRESULT WINAPI PathCchAddBackslashEx(WCHAR *path, SIZE_T size, WCHAR **endptr, SIZE_T *remaining)
Definition: pathcch.c:446
HRESULT WINAPI PathCchStripToRoot(WCHAR *path, SIZE_T size)
Definition: pathcch.c:1037
HRESULT WINAPI PathAllocCanonicalize(const WCHAR *path_in, DWORD flags, WCHAR **path_out)
Definition: pathcch.c:168
static FILE * out
Definition: regtests2xml.c:44
HRESULT hr
Definition: shlfolder.c:183

Referenced by PathCchCombineEx().

◆ PathCchAddBackslash()

HRESULT WINAPI PathCchAddBackslash ( WCHAR path,
SIZE_T  size 
)

Definition at line 431 of file pathcch.c.

433{
435}
GLsizeiptr size
Definition: glext.h:5919

Referenced by PathAllocCanonicalize().

◆ PathCchAddBackslashEx()

HRESULT WINAPI PathCchAddBackslashEx ( WCHAR path,
SIZE_T  size,
WCHAR **  endptr,
SIZE_T remaining 
)

Definition at line 446 of file pathcch.c.

448{
449 BOOL needs_termination;
451
452 TRACE("%s, %Iu, %p, %p\n", debugstr_w(path), size, endptr, remaining);
453
455 needs_termination = size && length && path[length - 1] != '\\';
456
457 if (length >= (needs_termination ? size - 1 : size))
458 {
459 if (endptr) *endptr = NULL;
460 if (remaining) *remaining = 0;
462 }
463
464 if (!needs_termination)
465 {
466 if (endptr) *endptr = path + length;
467 if (remaining) *remaining = size - length;
468 return S_FALSE;
469 }
470
471 path[length++] = '\\';
472 path[length] = 0;
473
474 if (endptr) *endptr = path + length;
475 if (remaining) *remaining = size - length;
476
477 return S_OK;
478}
#define STRSAFE_E_INSUFFICIENT_BUFFER
Definition: strsafe.h:103
#define S_FALSE
Definition: winerror.h:2357

Referenced by PathAllocCombine(), and PathCchAddBackslash().

◆ PathCchAddExtension()

HRESULT WINAPI PathCchAddExtension ( WCHAR path,
SIZE_T  size,
const WCHAR extension 
)

Definition at line 488 of file pathcch.c.

490{
491 const WCHAR *existing_extension, *next;
492 SIZE_T path_length, extension_length, dot_length;
493 BOOL has_dot;
494 HRESULT hr;
495
496 TRACE("%s %Iu %s\n", wine_dbgstr_w(path), size, wine_dbgstr_w(extension));
497
498 if (!path || !size || size > PATHCCH_MAX_CCH || !extension) return E_INVALIDARG;
499
500 next = extension;
501 while (*next)
502 {
503 if ((*next == '.' && next > extension) || *next == ' ' || *next == '\\') return E_INVALIDARG;
504 next++;
505 }
506
507 has_dot = extension[0] == '.';
508
509 hr = PathCchFindExtension(path, size, &existing_extension);
510 if (FAILED(hr)) return hr;
511 if (*existing_extension) return S_FALSE;
512
513 path_length = wcsnlen(path, size);
514 dot_length = has_dot ? 0 : 1;
515 extension_length = lstrlenW(extension);
516
517 if (path_length + dot_length + extension_length + 1 > size) return STRSAFE_E_INSUFFICIENT_BUFFER;
518
519 /* If extension is empty or only dot, return S_OK with path unchanged */
520 if (!extension[0] || (extension[0] == '.' && !extension[1])) return S_OK;
521
522 if (!has_dot)
523 {
524 path[path_length] = '.';
525 path_length++;
526 }
527
528 lstrcpyW(path + path_length, extension);
529 return S_OK;
530}
static long path_length
Definition: maze.c:116
#define FAILED(hr)
Definition: intsafe.h:51
HRESULT WINAPI PathCchFindExtension(const WCHAR *path, SIZE_T size, const WCHAR **extension)
Definition: pathcch.c:720

Referenced by PathCchRenameExtension().

◆ PathCchAppend()

HRESULT WINAPI PathCchAppend ( WCHAR path1,
SIZE_T  size,
const WCHAR path2 
)

Definition at line 540 of file pathcch.c.

542{
543 TRACE("%s %Iu %s\n", wine_dbgstr_w(path1), size, wine_dbgstr_w(path2));
544
546}
HRESULT WINAPI PathCchAppendEx(WCHAR *path1, SIZE_T size, const WCHAR *path2, DWORD flags)
Definition: pathcch.c:557
#define PATHCCH_NONE
Definition: pathcch.h:39

◆ PathCchAppendEx()

HRESULT WINAPI PathCchAppendEx ( WCHAR path1,
SIZE_T  size,
const WCHAR path2,
DWORD  flags 
)

Definition at line 557 of file pathcch.c.

559{
560 HRESULT hr;
561 WCHAR *result;
562
563 TRACE("%s %Iu %s %#lx\n", wine_dbgstr_w(path1), size, wine_dbgstr_w(path2), flags);
564
565 if (!path1 || !size) return E_INVALIDARG;
566
567 /* Create a temporary buffer for result because we need to keep path1 unchanged if error occurs.
568 * And PathCchCombineEx writes empty result if there is error so we can't just use path1 as output
569 * buffer for PathCchCombineEx */
570 result = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
571 if (!result) return E_OUTOFMEMORY;
572
573 /* Avoid the single backslash behavior with PathCchCombineEx when appending */
574 if (path2 && path2[0] == '\\' && path2[1] != '\\') path2++;
575
577 if (SUCCEEDED(hr)) memcpy(path1, result, size * sizeof(WCHAR));
578
580 return hr;
581}
GLuint64EXT * result
Definition: glext.h:11304
#define SUCCEEDED(hr)
Definition: intsafe.h:50
HRESULT WINAPI PathCchCombineEx(WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2, DWORD flags)
Definition: pathcch.c:679

Referenced by PathCchAppend().

◆ PathCchCanonicalize()

HRESULT WINAPI PathCchCanonicalize ( WCHAR out,
SIZE_T  size,
const WCHAR in 
)

Definition at line 591 of file pathcch.c.

593{
594 TRACE("%p %Iu %s\n", out, size, wine_dbgstr_w(in));
595
596 /* Not X:\ and path > MAX_PATH - 4, return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) */
597 if (lstrlenW(in) > MAX_PATH - 4 && !(is_drive_spec( in ) && in[2] == '\\'))
599
601}
GLuint in
Definition: glext.h:9616
HRESULT WINAPI PathCchCanonicalizeEx(WCHAR *out, SIZE_T size, const WCHAR *in, DWORD flags)
Definition: pathcch.c:612

◆ PathCchCanonicalizeEx()

HRESULT WINAPI PathCchCanonicalizeEx ( WCHAR out,
SIZE_T  size,
const WCHAR in,
DWORD  flags 
)

Definition at line 612 of file pathcch.c.

614{
615 WCHAR *buffer;
617 HRESULT hr;
618
619 TRACE("%p %Iu %s %#lx\n", out, size, wine_dbgstr_w(in), flags);
620
621 if (!size) return E_INVALIDARG;
622
624 if (FAILED(hr)) return hr;
625
627 if (size < length + 1)
628 {
629 /* No root and path > MAX_PATH - 4, return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) */
630 if (length > MAX_PATH - 4 && !(in[0] == '\\' || (is_drive_spec( in ) && in[2] == '\\')))
632 else
634 }
635
636 if (SUCCEEDED(hr))
637 {
638 memcpy(out, buffer, (length + 1) * sizeof(WCHAR));
639
640 /* Fill a backslash at the end of X: */
641 if (is_drive_spec( out ) && !out[2] && size > 3)
642 {
643 out[2] = '\\';
644 out[3] = 0;
645 }
646 }
647
649 return hr;
650}
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594

Referenced by PathCchCanonicalize().

◆ PathCchCombine()

HRESULT WINAPI PathCchCombine ( WCHAR out,
SIZE_T  size,
const WCHAR path1,
const WCHAR path2 
)

Definition at line 661 of file pathcch.c.

663{
664 TRACE("%p %s %s\n", out, wine_dbgstr_w(path1), wine_dbgstr_w(path2));
665
667}

◆ PathCchCombineEx()

HRESULT WINAPI PathCchCombineEx ( WCHAR out,
SIZE_T  size,
const WCHAR path1,
const WCHAR path2,
DWORD  flags 
)

Definition at line 679 of file pathcch.c.

681{
682 HRESULT hr;
683 WCHAR *buffer;
685
686 TRACE("%p %s %s %#lx\n", out, wine_dbgstr_w(path1), wine_dbgstr_w(path2), flags);
687
688 if (!out || !size || size > PATHCCH_MAX_CCH) return E_INVALIDARG;
689
691 if (FAILED(hr))
692 {
693 out[0] = 0;
694 return hr;
695 }
696
698 if (length + 1 > size)
699 {
700 out[0] = 0;
703 }
704 else
705 {
706 memcpy(out, buffer, (length + 1) * sizeof(WCHAR));
708 return S_OK;
709 }
710}
HRESULT WINAPI PathAllocCombine(const WCHAR *path1, const WCHAR *path2, DWORD flags, WCHAR **out)
Definition: pathcch.c:365

Referenced by PathCchAppendEx(), and PathCchCombine().

◆ PathCchFindExtension()

HRESULT WINAPI PathCchFindExtension ( const WCHAR path,
SIZE_T  size,
const WCHAR **  extension 
)

Definition at line 720 of file pathcch.c.

722{
723 const WCHAR *lastpoint = NULL;
724 SIZE_T counter = 0;
725
726 TRACE("%s %Iu %p\n", wine_dbgstr_w(path), size, extension);
727
728 if (!path || !size || size > PATHCCH_MAX_CCH)
729 {
730 *extension = NULL;
731 return E_INVALIDARG;
732 }
733
734 while (*path)
735 {
736 if (*path == '\\' || *path == ' ')
737 lastpoint = NULL;
738 else if (*path == '.')
739 lastpoint = path;
740
741 path++;
742 counter++;
743 if (counter == size || counter == PATHCCH_MAX_CCH)
744 {
745 *extension = NULL;
746 return E_INVALIDARG;
747 }
748 }
749
750 *extension = lastpoint ? lastpoint : path;
751 return S_OK;
752}

Referenced by PathCchAddExtension(), and PathCchRemoveExtension().

◆ PathCchIsRoot()

BOOL WINAPI PathCchIsRoot ( const WCHAR path)

Definition at line 760 of file pathcch.c.

762{
763 const WCHAR *root_end;
764 const WCHAR *next;
765 BOOL is_unc;
766
767 TRACE("%s\n", wine_dbgstr_w(path));
768
769 if (!path || !*path) return FALSE;
770
771 root_end = get_root_end(path);
772 if (!root_end) return FALSE;
773
774 if ((is_unc = is_prefixed_unc(path)) || (path[0] == '\\' && path[1] == '\\' && path[2] != '?'))
775 {
776 next = root_end + 1;
777 /* No extra segments */
778 if ((is_unc && !*next) || (!is_unc && !*next)) return TRUE;
779
780 /* Has first segment with an ending backslash but no remaining characters */
781 if (get_next_segment(next, &next) && !*next) return FALSE;
782 /* Has first segment with no ending backslash */
783 else if (!*next)
784 return TRUE;
785 /* Has first segment with an ending backslash and has remaining characters*/
786 else
787 {
788 next++;
789 /* Second segment must have no backslash and no remaining characters */
790 return !get_next_segment(next, &next) && !*next;
791 }
792 }
793 else if (*root_end == '\\' && !root_end[1])
794 return TRUE;
795 else
796 return FALSE;
797}
static BOOL get_next_segment(const WCHAR *next, const WCHAR **next_segment)
Definition: pathcch.c:122

Referenced by PathCchRemoveFileSpec().

◆ PathCchRemoveBackslash()

HRESULT WINAPI PathCchRemoveBackslash ( WCHAR path,
SIZE_T  path_size 
)

Definition at line 806 of file pathcch.c.

808{
809 WCHAR *path_end;
810 SIZE_T free_size;
811
812 TRACE("%s %Iu\n", debugstr_w(path), path_size);
813
814 return PathCchRemoveBackslashEx(path, path_size, &path_end, &free_size);
815}
HRESULT WINAPI PathCchRemoveBackslashEx(WCHAR *path, SIZE_T path_size, WCHAR **path_end, SIZE_T *free_size)
Definition: pathcch.c:826

◆ PathCchRemoveBackslashEx()

HRESULT WINAPI PathCchRemoveBackslashEx ( WCHAR path,
SIZE_T  path_size,
WCHAR **  path_end,
SIZE_T free_size 
)

Definition at line 826 of file pathcch.c.

828{
829 const WCHAR *root_end;
831
832 TRACE("%s %Iu %p %p\n", debugstr_w(path), path_size, path_end, free_size);
833
834 if (!path_size || !path_end || !free_size)
835 {
836 if (path_end) *path_end = NULL;
837 if (free_size) *free_size = 0;
838 return E_INVALIDARG;
839 }
840
841 path_length = wcsnlen(path, path_size);
842 if (path_length == path_size && !path[path_length]) return E_INVALIDARG;
843
844 root_end = get_root_end(path);
845 if (path_length > 0 && path[path_length - 1] == '\\')
846 {
847 *path_end = path + path_length - 1;
848 *free_size = path_size - path_length + 1;
849 /* If the last character is beyond end of root */
850 if (!root_end || path + path_length - 1 > root_end)
851 {
852 path[path_length - 1] = 0;
853 return S_OK;
854 }
855 else
856 return S_FALSE;
857 }
858 else
859 {
860 *path_end = path + path_length;
861 *free_size = path_size - path_length;
862 return S_FALSE;
863 }
864}

Referenced by PathCchRemoveBackslash().

◆ PathCchRemoveExtension()

HRESULT WINAPI PathCchRemoveExtension ( WCHAR path,
SIZE_T  size 
)

Definition at line 873 of file pathcch.c.

875{
876 const WCHAR *extension;
877 WCHAR *next;
878 HRESULT hr;
879
880 TRACE("%s %Iu\n", wine_dbgstr_w(path), size);
881
882 if (!path || !size || size > PATHCCH_MAX_CCH) return E_INVALIDARG;
883
884 hr = PathCchFindExtension(path, size, &extension);
885 if (FAILED(hr)) return hr;
886
887 next = path + (extension - path);
888 while (next - path < size && *next) *next++ = 0;
889
890 return next == extension ? S_FALSE : S_OK;
891}

Referenced by PathCchRenameExtension().

◆ PathCchRemoveFileSpec()

HRESULT WINAPI PathCchRemoveFileSpec ( WCHAR path,
SIZE_T  size 
)

Definition at line 900 of file pathcch.c.

902{
903 const WCHAR *root_end = NULL;
905 WCHAR *last;
906
907 TRACE("%s %Iu\n", wine_dbgstr_w(path), size);
908
909 if (!path || !size || size > PATHCCH_MAX_CCH) return E_INVALIDARG;
910
911 if (PathCchIsRoot(path)) return S_FALSE;
912
913 PathCchSkipRoot(path, &root_end);
914
915 /* The backslash at the end of UNC and \\* are not considered part of root in this case */
916 if (root_end && root_end > path && root_end[-1] == '\\'
917 && (is_prefixed_unc(path) || (path[0] == '\\' && path[1] == '\\' && path[2] != '?')))
918 root_end--;
919
921 last = path + length - 1;
922 while (last >= path && (!root_end || last >= root_end))
923 {
924 if (last - path >= size) return E_INVALIDARG;
925
926 if (*last == '\\')
927 {
928 *last-- = 0;
929 break;
930 }
931
932 *last-- = 0;
933 }
934
935 return last != path + length - 1 ? S_OK : S_FALSE;
936}
static UINT UINT last
Definition: font.c:45
BOOL WINAPI PathCchIsRoot(const WCHAR *path)
Definition: pathcch.c:760
HRESULT WINAPI PathCchSkipRoot(const WCHAR *path, const WCHAR **root_end)
Definition: pathcch.c:967

◆ PathCchRenameExtension()

HRESULT WINAPI PathCchRenameExtension ( WCHAR path,
SIZE_T  size,
const WCHAR extension 
)

Definition at line 946 of file pathcch.c.

948{
949 HRESULT hr;
950
951 TRACE("%s %Iu %s\n", wine_dbgstr_w(path), size, wine_dbgstr_w(extension));
952
954 if (FAILED(hr)) return hr;
955
956 hr = PathCchAddExtension(path, size, extension);
957 return FAILED(hr) ? hr : S_OK;
958}
HRESULT WINAPI PathCchRemoveExtension(WCHAR *path, SIZE_T size)
Definition: pathcch.c:873
HRESULT WINAPI PathCchAddExtension(WCHAR *path, SIZE_T size, const WCHAR *extension)
Definition: pathcch.c:488

◆ PathCchSkipRoot()

HRESULT WINAPI PathCchSkipRoot ( const WCHAR path,
const WCHAR **  root_end 
)

Definition at line 967 of file pathcch.c.

969{
970 TRACE("%s %p\n", debugstr_w(path), root_end);
971
972 if (!path || !path[0] || !root_end
973 || (!wcsnicmp(path, L"\\\\?", 3) && !is_prefixed_volume(path) && !is_prefixed_unc(path)
975 return E_INVALIDARG;
976
977 *root_end = get_root_end(path);
978 if (*root_end)
979 {
980 (*root_end)++;
982 {
983 get_next_segment(*root_end, root_end);
984 get_next_segment(*root_end, root_end);
985 }
986 else if (path[0] == '\\' && path[1] == '\\' && path[2] != '?')
987 {
988 /* Skip share server */
989 get_next_segment(*root_end, root_end);
990 /* If mount point is empty, don't skip over mount point */
991 if (**root_end != '\\') get_next_segment(*root_end, root_end);
992 }
993 }
994
995 return *root_end ? S_OK : E_INVALIDARG;
996}

Referenced by PathCchRemoveFileSpec(), and PathCchStripToRoot().

◆ PathCchStripPrefix()

HRESULT WINAPI PathCchStripPrefix ( WCHAR path,
SIZE_T  size 
)

Definition at line 1005 of file pathcch.c.

1007{
1008 TRACE("%s %Iu\n", wine_dbgstr_w(path), size);
1009
1010 if (!path || !size || size > PATHCCH_MAX_CCH) return E_INVALIDARG;
1011
1012 if (is_prefixed_unc(path))
1013 {
1014 /* \\?\UNC\a -> \\a */
1015 if (size < lstrlenW(path + 8) + 3) return E_INVALIDARG;
1016 lstrcpyW(path + 2, path + 8);
1017 return S_OK;
1018 }
1019 else if (is_prefixed_disk(path))
1020 {
1021 /* \\?\C:\ -> C:\ */
1022 if (size < lstrlenW(path + 4) + 1) return E_INVALIDARG;
1023 lstrcpyW(path, path + 4);
1024 return S_OK;
1025 }
1026 else
1027 return S_FALSE;
1028}

Referenced by PathAllocCanonicalize(), and PathAllocCombine().

◆ PathCchStripToRoot()

HRESULT WINAPI PathCchStripToRoot ( WCHAR path,
SIZE_T  size 
)

Definition at line 1037 of file pathcch.c.

1039{
1040 const WCHAR *root_end;
1041 WCHAR *segment_end;
1042 BOOL is_unc;
1043
1044 TRACE("%s %Iu\n", wine_dbgstr_w(path), size);
1045
1046 if (!path || !*path || !size || size > PATHCCH_MAX_CCH) return E_INVALIDARG;
1047
1048 /* \\\\?\\UNC\\* and \\\\* have to have at least two extra segments to be striped,
1049 * e.g. \\\\?\\UNC\\a\\b\\c -> \\\\?\\UNC\\a\\b
1050 * \\\\a\\b\\c -> \\\\a\\b */
1051 if ((is_unc = is_prefixed_unc(path)) || (path[0] == '\\' && path[1] == '\\' && path[2] != '?'))
1052 {
1053 root_end = is_unc ? path + 8 : path + 3;
1054 if (!get_next_segment(root_end, &root_end)) return S_FALSE;
1055 if (!get_next_segment(root_end, &root_end)) return S_FALSE;
1056
1057 if (root_end - path >= size) return E_INVALIDARG;
1058
1059 segment_end = path + (root_end - path) - 1;
1060 *segment_end = 0;
1061 return S_OK;
1062 }
1063 else if (PathCchSkipRoot(path, &root_end) == S_OK)
1064 {
1065 if (root_end - path >= size) return E_INVALIDARG;
1066
1067 segment_end = path + (root_end - path);
1068 if (!*segment_end) return S_FALSE;
1069
1070 *segment_end = 0;
1071 return S_OK;
1072 }
1073 else
1074 return E_INVALIDARG;
1075}

Referenced by PathAllocCombine().

◆ PathIsUNCEx()

BOOL WINAPI PathIsUNCEx ( const WCHAR path,
const WCHAR **  server 
)

Definition at line 1084 of file pathcch.c.

1086{
1087 const WCHAR *result = NULL;
1088
1089 TRACE("%s %p\n", wine_dbgstr_w(path), server);
1090
1091 if (is_prefixed_unc(path))
1092 result = path + 8;
1093 else if (path[0] == '\\' && path[1] == '\\' && path[2] != '?')
1094 result = path + 2;
1095
1096 if (server) *server = result;
1097 return !!result;
1098}
static rfbScreenInfoPtr server
Definition: vnc.c:74

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( path  )