Reactos
at master 153 lines 4.8 kB view raw
1/*** 2*fullpath.c - 3* 4* Copyright (c) Microsoft Corporation. All rights reserved. 5* 6*Purpose: contains the function _fullpath which makes an absolute path out 7* of a relative path. i.e. ..\pop\..\main.c => c:\src\main.c if the 8* current directory is c:\src\src 9* 10*******************************************************************************/ 11 12#include <stdio.h> 13#include <direct.h> 14#include <errno.h> 15#include <stdlib.h> 16#include <corecrt_internal_traits.h> 17#include <windows.h> 18 19/*** 20*_TCHAR *_fullpath( _TCHAR *buf, const _TCHAR *path, maxlen ); 21* 22*Purpose: 23* 24* _fullpath - combines the current directory with path to form 25* an absolute path. i.e. _fullpath takes care of .\ and ..\ 26* in the path. 27* 28* The result is placed in buf. If the length of the result 29* is greater than maxlen nullptr is returned, otherwise 30* the address of buf is returned. 31* 32* If buf is nullptr then a buffer is malloc'ed and maxlen is 33* ignored. If there are no errors then the address of this 34* buffer is returned. 35* 36* If path specifies a drive, the curent directory of this 37* drive is combined with path. If the drive is not valid 38* and _fullpath needs the current directory of this drive 39* then nullptr is returned. If the current directory of this 40* non existant drive is not needed then a proper value is 41* returned. 42* For example: path = "z:\\pop" does not need z:'s current 43* directory but path = "z:pop" does. 44* 45* 46* 47*Entry: 48* _TCHAR *buf - pointer to a buffer maintained by the user; 49* _TCHAR *path - path to "add" to the current directory 50* int maxlen - length of the buffer pointed to by buf 51* 52*Exit: 53* Returns pointer to the buffer containing the absolute path 54* (same as buf if non-nullptr; otherwise, malloc is 55* used to allocate a buffer) 56* 57*Exceptions: 58* 59*******************************************************************************/ 60 61template <typename Character> 62_Success_(return != 0) 63static Character* __cdecl common_fullpath( 64 _Out_writes_z_(max_count) Character* const user_buffer, 65 Character const* const path, 66 size_t const max_count, 67 int const block_use, 68 char const* const file_name, 69 int const line_number 70 ) throw() 71{ 72 // These are referenced only in the Debug CRT build 73 UNREFERENCED_PARAMETER(block_use); 74 UNREFERENCED_PARAMETER(file_name); 75 UNREFERENCED_PARAMETER(line_number); 76 77 typedef __crt_char_traits<Character> traits; 78 79 // If the path is empty, we have no work to do: 80 if (path == nullptr || path[0] == '\0') 81 { 82#pragma warning(suppress:__WARNING_POSTCONDITION_NULLTERMINATION_VIOLATION) // 26036 Prefast does not understand perfect forwarding. 83 return traits::tgetcwd(user_buffer, static_cast<int>(__min(max_count, INT_MAX))); 84 } 85 86 if (user_buffer != nullptr) { 87 // Using user buffer. Fail if not enough space. 88 __crt_no_alloc_win32_buffer<Character> buffer(user_buffer, max_count); 89 if (!traits::get_full_path_name(path, buffer)) { 90 return user_buffer; 91 } else { 92 return nullptr; 93 } 94 } else { 95 // Always new memory suitable for debug mode and releasing to the user. 96 __crt_public_win32_buffer<Character> buffer( 97 __crt_win32_buffer_debug_info(block_use, file_name, line_number) 98 ); 99 traits::get_full_path_name(path, buffer); 100 return buffer.detach(); 101 } 102} 103 104 105 106extern "C" char* __cdecl _fullpath( 107 char* const user_buffer, 108 char const* const path, 109 size_t const max_count 110 ) 111{ 112 return common_fullpath(user_buffer, path, max_count, _NORMAL_BLOCK, nullptr, 0); 113} 114 115extern "C" wchar_t* __cdecl _wfullpath( 116 wchar_t* const user_buffer, 117 wchar_t const* const path, 118 size_t const max_count 119 ) 120{ 121 return common_fullpath(user_buffer, path, max_count, _NORMAL_BLOCK, nullptr, 0); 122} 123 124#ifdef _DEBUG 125 126#undef _fullpath_dbg 127#undef _wfullpath_dbg 128 129extern "C" char* __cdecl _fullpath_dbg( 130 char* const user_buffer, 131 char const* const path, 132 size_t const max_count, 133 int const block_use, 134 char const* const file_name, 135 int const line_number 136 ) 137{ 138 return common_fullpath(user_buffer, path, max_count, block_use, file_name, line_number); 139} 140 141extern "C" wchar_t* __cdecl _wfullpath_dbg( 142 wchar_t* const user_buffer, 143 wchar_t const* const path, 144 size_t const max_count, 145 int const block_use, 146 char const* const file_name, 147 int const line_number 148 ) 149{ 150 return common_fullpath(user_buffer, path, max_count, block_use, file_name, line_number); 151} 152 153#endif // _DEBUG