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