Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
11 KiB

  1. /***
  2. *getcwd.c - get current working directory
  3. *
  4. * Copyright (c) 1985-2001, 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. *Revision History:
  14. * 09-09-83 RKW created
  15. * 05-??-84 DCW added conditional compilation to handle case of library
  16. * where SS != DS (can't take address of a stack variable).
  17. * 09-??-84 DCW changed comparison of path length to maxlen to take the
  18. * terminating null character into account.
  19. * 11-28-84 DCW changed to return errno values compatibly with the
  20. * System 3 version.
  21. * 05-19-86 SKS adapted for OS/2
  22. * 11-19-86 SKS if pnbuf==NULL, maxlen is ignored;
  23. * eliminated use of intermediate buffer "buf[]"; added
  24. * entry point "_getdcwd()" which takes a drive number.
  25. * 12-03-86 SKS if pnbuf==NULL, maxlen is the minimum allocation size
  26. * 02-05-87 BCM fixed comparison in _getdcwd,
  27. * (unsigned)(len+3) > (int)(maxlen), to handle maxlen < 0,
  28. * since implicit cast to (unsigned) was occurring.
  29. * 12-11-87 JCR Added "_LOAD_DS" to declaration
  30. * 12-21-87 WAJ Added _getcdrv()
  31. * 06-22-88 WAJ _getcdrv() is now made for all OS/2 libs
  32. * 10-03-88 JCR 386: Change DOS calls to SYS calls
  33. * 10-04-88 JCR 386: Removed 'far' keyword
  34. * 10-10-88 GJF Made API names match DOSCALLS.H
  35. * 01-31-89 JCR Remove _getcdrv(), which has been renamed _getdrive()
  36. * 04-12-89 JCR Use new OS/2 system calls
  37. * 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
  38. * 11-27-89 JCR Corrected ERRNO values
  39. * 12-12-89 JCR Fixed bogus syscall introduced in previous fix (oops)
  40. * 03-07-90 GJF Replaced _LOAD_DS by _CALLTYPE1, added #include
  41. * <cruntime.h>, removed #include <register.h>, removed
  42. * some leftover 16-bit support and fixed the copyright.
  43. * Also, cleaned up the formatting a bit.
  44. * 07-24-90 SBM Compiles cleanly with -W3 (removed unreferenced
  45. * variable), removed redundant includes, removed
  46. * '32' from API names
  47. * 08-10-90 SBM Compiles cleanly with -W3 with new build of compiler
  48. * 09-27-90 GJF New-style function declarator.
  49. * 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
  50. * 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
  51. * 01-16-91 GJF ANSI naming.
  52. * 08-21-91 JCR Test DOSQUERYCURRENTDIR call for error return (bug fix)
  53. * 04-23-92 GJF Fixed initialization of DriveVar[].
  54. * 04-28-92 GJF Revised Win32 version.
  55. * 12-09-92 PLM Removed _getdcwd (Mac version only)
  56. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  57. * Change _ValidDrive to _validdrive
  58. * 04-19-93 SKS Move _validdrive to this module
  59. * 04-26-93 SKS Set _doserrno on invalid drive
  60. * 05-26-93 SKS Change _getdcwd to call GetFullPathName() instead of
  61. * reading a current directory environment variable.
  62. * 09-30-93 GJF Removed #include <error.h> (thereby getting rid of a
  63. * bunch of compiler warnings). Also, MTHREAD -> _MT.
  64. * 11-01-93 CFW Enable Unicode variant.
  65. * 12-21-93 CFW Fix API failure error handling.
  66. * 01-04-94 CFW Fix API failure error handling correctly.
  67. * 08-11-94 GJF Revised _validdrive() to use GetDriveType (suggestion
  68. * from Richard Shupak).
  69. * 08-18-94 GJF Revised _validdrive() logic slightly per suggestion
  70. * of Richard Shupak.
  71. * 02-08-95 JWM Spliced _WIN32 & Mac versions.
  72. * 07-01-96 GJF Replaced defined(_WIN32) with !defined(_MAC). Also,
  73. * detab-ed and cleaned up the format a bit.
  74. * 12-17-97 GJF Exception-safe locking.
  75. * 05-17-99 PML Remove all Macintosh support.
  76. *
  77. *******************************************************************************/
  78. #include <cruntime.h>
  79. #include <mtdll.h>
  80. #include <msdos.h>
  81. #include <errno.h>
  82. #include <malloc.h>
  83. #include <oscalls.h>
  84. #include <stdlib.h>
  85. #include <internal.h>
  86. #include <direct.h>
  87. #include <tchar.h>
  88. /***
  89. *_TSCHAR *_getcwd(pnbuf, maxlen) - get current working directory of default drive
  90. *
  91. *Purpose:
  92. * _getcwd gets the current working directory for the user,
  93. * placing it in the buffer pointed to by pnbuf. It returns
  94. * the length of the string put in the buffer. If the length
  95. * of the string exceeds the length of the buffer, maxlen,
  96. * then NULL is returned. If pnbuf = NULL, maxlen is ignored.
  97. * An entry point "_getdcwd()" is defined with takes the above
  98. * parameters, plus a drive number. "_getcwd()" is implemented
  99. * as a call to "_getcwd()" with the default drive (0).
  100. *
  101. * If pnbuf = NULL, maxlen is ignored, and a buffer is automatically
  102. * allocated using malloc() -- a pointer to which is returned by
  103. * _getcwd().
  104. *
  105. * side effects: no global data is used or affected
  106. *
  107. *Entry:
  108. * _TSCHAR *pnbuf = pointer to a buffer maintained by the user;
  109. * int maxlen = length of the buffer pointed to by pnbuf;
  110. *
  111. *Exit:
  112. * Returns pointer to the buffer containing the c.w.d. name
  113. * (same as pnbuf if non-NULL; otherwise, malloc is
  114. * used to allocate a buffer)
  115. *
  116. *Exceptions:
  117. *
  118. *******************************************************************************/
  119. _TSCHAR * __cdecl _tgetcwd (
  120. _TSCHAR *pnbuf,
  121. int maxlen
  122. )
  123. {
  124. _TSCHAR *retval;
  125. #ifdef _MT
  126. _mlock( _ENV_LOCK );
  127. __try {
  128. #endif
  129. #ifdef WPRFLAG
  130. retval = _wgetdcwd_lk(0, pnbuf, maxlen);
  131. #else
  132. retval = _getdcwd_lk(0, pnbuf, maxlen);
  133. #endif
  134. #ifdef _MT
  135. }
  136. __finally {
  137. _munlock( _ENV_LOCK );
  138. }
  139. #endif
  140. return retval;
  141. }
  142. /***
  143. *_TSCHAR *_getdcwd(drive, pnbuf, maxlen) - get c.w.d. for given drive
  144. *
  145. *Purpose:
  146. * _getdcwd gets the current working directory for the user,
  147. * placing it in the buffer pointed to by pnbuf. It returns
  148. * the length of the string put in the buffer. If the length
  149. * of the string exceeds the length of the buffer, maxlen,
  150. * then NULL is returned. If pnbuf = NULL, maxlen is ignored,
  151. * and a buffer is automatically allocated using malloc() --
  152. * a pointer to which is returned by _getdcwd().
  153. *
  154. * side effects: no global data is used or affected
  155. *
  156. *Entry:
  157. * int drive - number of the drive being inquired about
  158. * 0 = default, 1 = 'a:', 2 = 'b:', etc.
  159. * _TSCHAR *pnbuf - pointer to a buffer maintained by the user;
  160. * int maxlen - length of the buffer pointed to by pnbuf;
  161. *
  162. *Exit:
  163. * Returns pointer to the buffer containing the c.w.d. name
  164. * (same as pnbuf if non-NULL; otherwise, malloc is
  165. * used to allocate a buffer)
  166. *
  167. *Exceptions:
  168. *
  169. *******************************************************************************/
  170. #ifdef _MT
  171. _TSCHAR * __cdecl _tgetdcwd (
  172. int drive,
  173. _TSCHAR *pnbuf,
  174. int maxlen
  175. )
  176. {
  177. _TSCHAR *retval;
  178. #ifdef _MT
  179. _mlock( _ENV_LOCK );
  180. __try {
  181. #endif
  182. #ifdef WPRFLAG
  183. retval = _wgetdcwd_lk(drive, pnbuf, maxlen);
  184. #else
  185. retval = _getdcwd_lk(drive, pnbuf, maxlen);
  186. #endif
  187. #ifdef _MT
  188. }
  189. _finally {
  190. _munlock( _ENV_LOCK );
  191. }
  192. #endif
  193. return retval;
  194. }
  195. #ifdef WPRFLAG
  196. wchar_t * __cdecl _wgetdcwd_lk (
  197. #else
  198. char * __cdecl _getdcwd_lk (
  199. #endif
  200. int drive,
  201. _TSCHAR *pnbuf,
  202. int maxlen
  203. )
  204. #else
  205. _TSCHAR * __cdecl _tgetdcwd (
  206. int drive,
  207. _TSCHAR *pnbuf,
  208. int maxlen
  209. )
  210. #endif
  211. {
  212. _TSCHAR *p;
  213. _TSCHAR dirbuf[_MAX_PATH];
  214. _TSCHAR drvstr[4];
  215. int len;
  216. _TSCHAR *pname; /* only used as argument to GetFullPathName */
  217. /*
  218. * GetCurrentDirectory only works for the default drive in Win32
  219. */
  220. if ( drive != 0 ) {
  221. /*
  222. * Not the default drive - make sure it's valid.
  223. */
  224. if ( !_validdrive(drive) ) {
  225. _doserrno = ERROR_INVALID_DRIVE;
  226. errno = EACCES;
  227. return NULL;
  228. }
  229. /*
  230. * Get the current directory string on that drive and its length
  231. */
  232. drvstr[0] = _T('A') - 1 + drive;
  233. drvstr[1] = _T(':');
  234. drvstr[2] = _T('.');
  235. drvstr[3] = _T('\0');
  236. len = GetFullPathName( drvstr,
  237. sizeof(dirbuf) / sizeof(_TSCHAR),
  238. dirbuf,
  239. &pname );
  240. } else {
  241. /*
  242. * Get the current directory string and its length
  243. */
  244. len = GetCurrentDirectory( sizeof(dirbuf) / sizeof(_TSCHAR),
  245. (LPTSTR)dirbuf );
  246. }
  247. /* API call failed, or buffer not large enough */
  248. if ( len == 0 || ++len > sizeof(dirbuf)/sizeof(_TSCHAR) )
  249. return NULL;
  250. /*
  251. * Set up the buffer.
  252. */
  253. if ( (p = pnbuf) == NULL ) {
  254. /*
  255. * Allocate a buffer for the user.
  256. */
  257. if ( (p = (_TSCHAR *)malloc(__max(len, maxlen) * sizeof(_TSCHAR)))
  258. == NULL )
  259. {
  260. errno = ENOMEM;
  261. return NULL;
  262. }
  263. }
  264. else if ( len > maxlen ) {
  265. /*
  266. * Won't fit in the user-supplied buffer!
  267. */
  268. errno = ERANGE; /* Won't fit in user buffer */
  269. return NULL;
  270. }
  271. /*
  272. * Place the current directory string into the user buffer
  273. */
  274. return _tcscpy(p, dirbuf);
  275. }
  276. #ifndef WPRFLAG
  277. /***
  278. *int _validdrive( unsigned drive ) -
  279. *
  280. *Purpose: returns non zero if drive is a valid drive number.
  281. *
  282. *Entry: drive = 0 => default drive, 1 => a:, 2 => b: ...
  283. *
  284. *Exit: 0 => drive does not exist.
  285. *
  286. *Exceptions:
  287. *
  288. *******************************************************************************/
  289. int __cdecl _validdrive (
  290. unsigned drive
  291. )
  292. {
  293. unsigned retcode;
  294. char drvstr[4];
  295. if ( drive == 0 )
  296. return 1;
  297. drvstr[0] = 'A' + drive - 1;
  298. drvstr[1] = ':';
  299. drvstr[2] = '\\';
  300. drvstr[3] = '\0';
  301. if ( ((retcode = GetDriveType( drvstr )) == DRIVE_UNKNOWN) ||
  302. (retcode == DRIVE_NO_ROOT_DIR) )
  303. return 0;
  304. return 1;
  305. }
  306. #endif /* WPRFLAG */