Reactos
at master 265 lines 8.1 kB view raw
1/*** 2*getcwd.cpp - get current working directory 3* 4* Copyright (c) Microsoft Corporation. All rights reserved. 5* 6*Purpose: 7* 8* contains functions _getcwd, _getdcwd and _getcdrv for getting the 9* current working directory. getcwd gets the c.w.d. for the default disk 10* drive, whereas _getdcwd allows one to get the c.w.d. for whatever disk 11* drive is specified. _getcdrv gets the current drive. 12* 13*******************************************************************************/ 14#include <corecrt_internal.h> 15#include <corecrt_internal_traits.h> 16#include <direct.h> 17#include <errno.h> 18#include <malloc.h> 19#include <stdlib.h> 20 21 22 23// Tests whether the specified drive number is valid. Returns zero if the drive 24// does not exist; returns one if the drive exists. Pass zero as an argument to 25// check the default drive. 26static int __cdecl is_valid_drive(unsigned const drive_number) throw() 27{ 28 if (drive_number > 26) 29 { 30 _doserrno = ERROR_INVALID_DRIVE; 31 _VALIDATE_RETURN(("Invalid Drive Index" ,0), EACCES, 0); 32 } 33 34 if (drive_number == 0) 35 return 1; 36 37#pragma warning(suppress:__WARNING_UNUSED_ASSIGNMENT) // 28931 38 wchar_t const drive_letter = static_cast<wchar_t>(L'A' + drive_number - 1); 39 wchar_t const drive_string[] = { drive_letter, L':', L'\\', L'\0' }; 40 41 UINT const drive_type = GetDriveTypeW(drive_string); 42 if (drive_type == DRIVE_UNKNOWN || drive_type == DRIVE_NO_ROOT_DIR) 43 return 0; 44 45 return 1; 46} 47 48 49 50/*** 51*_TSCHAR *_getcwd(pnbuf, maxlen) - get current working directory of default drive 52* 53*Purpose: 54* _getcwd gets the current working directory for the user, 55* placing it in the buffer pointed to by pnbuf. If the length 56* of the string exceeds the length of the buffer, maxlen, 57* then nullptr is returned. If pnbuf = nullptr, a buffer of at 58* least size maxlen is automatically allocated using 59* malloc() -- a pointer to which is returned by _getcwd(). 60* An entry point "_getdcwd()" is defined which takes the above 61* parameters, plus a drive number. "_getcwd()" is implemented 62* as a call to "_getdcwd()" with the default drive (0). 63* 64* side effects: no global data is used or affected 65* 66*Entry: 67* _TSCHAR *pnbuf = pointer to a buffer maintained by the user; 68* int maxlen = length of the buffer pointed to by pnbuf; 69* 70*Exit: 71* Returns pointer to the buffer containing the c.w.d. name 72* (same as pnbuf if non-nullptr; otherwise, malloc is 73* used to allocate a buffer) 74* 75*Exceptions: 76* 77*******************************************************************************/ 78 79/*** 80*_TSCHAR *_getdcwd(drive, pnbuf, maxlen) - get c.w.d. for given drive 81* 82*Purpose: 83* _getdcwd gets the current working directory for the user, 84* placing it in the buffer pointed to by pnbuf. If the length 85* of the string exceeds the length of the buffer, maxlen, 86* then nullptr is returned. If pnbuf = nullptr, a buffer of at 87* least size maxlen is automatically allocated using 88* malloc() -- a pointer to which is returned by _getdcwd(). 89* 90* side effects: no global data is used or affected 91* 92*Entry: 93* int drive - number of the drive being inquired about 94* 0 = default, 1 = 'a:', 2 = 'b:', etc. 95* _TSCHAR *pnbuf - pointer to a buffer maintained by the user; 96* int maxlen - length of the buffer pointed to by pnbuf; 97* 98*Exit: 99* Returns pointer to the buffer containing the c.w.d. name 100* (same as pnbuf if non-nullptr; otherwise, malloc is 101* used to allocate a buffer) 102* 103*Exceptions: 104* 105*******************************************************************************/ 106 107template <typename Character> 108_Success_(return != 0) 109_Ret_z_ 110static Character* __cdecl common_getdcwd( 111 int drive_number, 112 _Out_writes_opt_z_(max_count) Character* user_buffer, 113 int const max_count, 114 int const block_use, 115 _In_opt_z_ char const* const file_name, 116 int const line_number 117 ) throw() 118{ 119 typedef __crt_char_traits<Character> traits; 120 121 _VALIDATE_RETURN(max_count >= 0, EINVAL, nullptr); 122 123 if (drive_number != 0) 124 { 125 // A drive other than the default drive was requested; make sure it 126 // is a valid drive number: 127 if (!is_valid_drive(drive_number)) 128 { 129 _doserrno = ERROR_INVALID_DRIVE; 130 _VALIDATE_RETURN(("Invalid Drive", 0), EACCES, nullptr); 131 } 132 } 133 else 134 { 135 // Otherwise, get the drive number of the default drive: 136 drive_number = _getdrive(); 137 } 138 139 Character drive_string[4]; 140 if (drive_number != 0) 141 { 142 drive_string[0] = static_cast<Character>('A' - 1 + drive_number); 143 drive_string[1] = ':'; 144 drive_string[2] = '.'; 145 drive_string[3] = '\0'; 146 } 147 else 148 { 149 drive_string[0] = '.'; 150 drive_string[1] = '\0'; 151 } 152 153 if (user_buffer == nullptr) 154 { // Always new memory suitable for debug mode and releasing to the user. 155 __crt_public_win32_buffer<Character> buffer( 156 __crt_win32_buffer_debug_info(block_use, file_name, line_number) 157 ); 158 buffer.allocate(max_count); 159 if (!traits::get_full_path_name(drive_string, buffer)) 160 { 161 return buffer.detach(); 162 } 163 return nullptr; 164 } 165 166 // Using user buffer. Fail if not enough space. 167 _VALIDATE_RETURN(max_count > 0, EINVAL, nullptr); 168 user_buffer[0] = '\0'; 169 170 __crt_no_alloc_win32_buffer<Character> buffer(user_buffer, max_count); 171 if (!traits::get_full_path_name(drive_string, buffer)) 172 { 173 return user_buffer; 174 } 175 return nullptr; 176}; 177 178 179 180extern "C" char* __cdecl _getcwd( 181 char* const user_buffer, 182 int const max_length 183 ) 184{ 185 return common_getdcwd(0, user_buffer, max_length, _NORMAL_BLOCK, nullptr, 0); 186} 187 188extern "C" wchar_t* __cdecl _wgetcwd( 189 wchar_t* const user_buffer, 190 int const max_length 191 ) 192{ 193 return common_getdcwd(0, user_buffer, max_length, _NORMAL_BLOCK, nullptr, 0); 194} 195 196extern "C" char* __cdecl _getdcwd( 197 int const drive_number, 198 char* const user_buffer, 199 int const max_length 200 ) 201{ 202 return common_getdcwd(drive_number, user_buffer, max_length, _NORMAL_BLOCK, nullptr, 0); 203} 204 205extern "C" wchar_t* __cdecl _wgetdcwd( 206 int const drive_number, 207 wchar_t* const user_buffer, 208 int const max_length 209 ) 210{ 211 return common_getdcwd(drive_number, user_buffer, max_length, _NORMAL_BLOCK, nullptr, 0); 212} 213 214#ifdef _DEBUG 215 216#undef _getcwd_dbg 217#undef _getdcwd_dbg 218 219extern "C" char* __cdecl _getcwd_dbg( 220 char* const user_buffer, 221 int const max_length, 222 int const block_use, 223 char const* const file_name, 224 int const line_number 225 ) 226{ 227 return common_getdcwd(0, user_buffer, max_length, block_use, file_name, line_number); 228} 229 230extern "C" wchar_t* __cdecl _wgetcwd_dbg( 231 wchar_t* const user_buffer, 232 int const max_length, 233 int const block_use, 234 char const* const file_name, 235 int const line_number 236 ) 237{ 238 return common_getdcwd(0, user_buffer, max_length, block_use, file_name, line_number); 239} 240 241extern "C" char* __cdecl _getdcwd_dbg( 242 int const drive_number, 243 char* const user_buffer, 244 int const max_length, 245 int const block_use, 246 char const* const file_name, 247 int const line_number 248 ) 249{ 250 return common_getdcwd(drive_number, user_buffer, max_length, block_use, file_name, line_number); 251} 252 253extern "C" wchar_t* __cdecl _wgetdcwd_dbg( 254 int const drive_number, 255 wchar_t* const user_buffer, 256 int const max_length, 257 int const block_use, 258 char const* const file_name, 259 int const line_number 260 ) 261{ 262 return common_getdcwd(drive_number, user_buffer, max_length, block_use, file_name, line_number); 263} 264 265#endif // _DEBUG