From: a on

Hi

I suggest that you read the source code of CRT to understand the behavior:


int __cdecl _chdrive (
int drive
)
{
int retval;
char newdrive[3];

if (drive < 1 || drive > 26) {
_doserrno = ERROR_INVALID_DRIVE;
_VALIDATE_RETURN(("Invalid Drive Index",0), EACCES, -1);
}

_mlock( _ENV_LOCK );
__try {

newdrive[0] = (char)('A' + (char)drive - (char)1);
newdrive[1] = ':';
newdrive[2] = '\0';

/*
* Set new drive. If current directory on new drive exists, it
* will become the cwd. Otherwise defaults to root directory.
*/

if ( SetCurrentDirectory((LPSTR)newdrive) )
retval = 0;
else {
_dosmaperr(GetLastError());
retval = -1;
}

}
__finally {
_munlock( _ENV_LOCK );
}

return retval;
}



_TSCHAR * __cdecl _tgetdcwd (
int drive,
_TSCHAR *pnbuf,
int maxlen
)
{
_TSCHAR *p;
_TSCHAR drvstr[4];
int ret, count;
_TSCHAR *pname; /* only used as argument to GetFullPathName */

if ( drive != 0 ) {
/*
* Not the default drive - make sure it's valid.
*/
if ( !_validdrive(drive) ) {
_doserrno = ERROR_INVALID_DRIVE;
_VALIDATE_RETURN(("Invalid Drive",0), EACCES, NULL);
}
} else {
/* Get the drive index of the default drive */
drive = _getdrive();

}

/* If pnbuf is NULL, we pass 0 in both the 2nd & 3rd parameter
to find required length to allocate */

if(pnbuf)
{
_VALIDATE_RETURN( (maxlen > 0), EINVAL, NULL);
count = maxlen;
pnbuf[0] = 0;
}
else
count = 0;

/*
* Get the current directory string on that drive and its length
*/
if(drive!=0)
{
drvstr[0] = _T('A') - 1 + drive;
drvstr[1] = _T(':');
drvstr[2] = _T('.');
drvstr[3] = _T('\0');
}
else
{
drvstr[0] = _T('.');
drvstr[1] = _T('\0');
}

ret = GetFullPathName( drvstr, count, pnbuf, &pname );

if(ret == 0) {
_dosmaperr( GetLastError() );
return NULL;
}

if( pnbuf != NULL ) {
if(ret < count) {
/* GetFullPathName always returns a value less than that
passed in if successful i.e. we got the required dir */
return pnbuf;
}

errno = ERANGE;
*pnbuf = 0;
return NULL;
}

/* The code comes here only if pnbuf was NULL
Allocate the required memory & call GetFullPathName again*/

maxlen = __max(ret, maxlen) ;
#ifdef _DEBUG
if( (p = (_TSCHAR *)_calloc_dbg( maxlen, sizeof(_TSCHAR), nBlockUse,
szFileName, nLine)) == NULL) {
#else /* _DEBUG */
if( (p = (_TSCHAR *)calloc( maxlen, sizeof(_TSCHAR))) == NULL) {
#endif /* _DEBUG */
errno = ENOMEM;
_doserrno = E_nomem;
return NULL;
}


ret = GetFullPathName( drvstr, maxlen, p, &pname );

if(ret == 0 || ret >= maxlen) {
_dosmaperr( GetLastError() );
return NULL;
}

return p;

}
"David F." <df2705(a)community.nospam> wrote in message
news:DD36AA91-8089-4202-8163-B171DBDB80F8(a)microsoft.com...
> For an environment where that makes since .. I didn't want to have to
> getdrive / setdrive but I guess I'll have to do something like that.
>
> "Leo Davidson" <leonudeldavidson(a)googlemail.com> wrote in message
> news:610b6b83-125c-4698-b2f0-d34a9feab4d6(a)s29g2000yqd.googlegroups.com...
> On Apr 30, 7:57 pm, "David F." <df2...(a)community.nospam> wrote:
>
>
>> From Docs: "If a new drive letter is specified in dirname, the default
>> drive
>> letter is changed as well" ... I don't want it to do that.
>
> I think you'll have to _chdir to the new path, then _chdrive back to
> the old drive/path if you want to do that.
>
> I'm curious why you want to do an MS-DOS-style _chdir for a drive you
> are not using, and without affecting the actual current dir?
>
> Is this for your own code or is some other component forcing you to do
> these contortions?
>

From: Leo Davidson on
On May 3, 3:50 am, "a" <a...(a)a.com> wrote:
> I suggest that you read the source code of CRT to understand the behavior:

I always forget the CRT source is available. :)

The most interesting source is that of _chdir, which shows it is doing
extra bookkeeping beyond what SetCurrentDirectory does, as I suspected
(although the way the extra info is stored and the fact that other
Win32 APIs use it automatically did surprise me).

From chdir.c:

* If the new current directory path is NOT a UNC path, we must
* update the OS environment variable specifying the current
* directory for what is now current drive. To do this, get the
* full current directory, build the environment variable string
* and call SetEnvironmentVariable(). We need to do this because
* SetCurrentDirectory does not (i.e., does not update the
* current-directory-on-drive environment variables) and other
* functions (fullpath, spawn, etc) need them to be set.
*
* If associated with a 'drive', the current directory should
* have the form of the example below:
*
* D:\nt\private\mytests
*
* so that the environment variable should be of the form:
*
* =D:=D:\nt\private\mytests
From: Leo Davidson on
On May 3, 9:23 am, Leo Davidson <leonudeldavid...(a)googlemail.com>
wrote:

> * so that the environment variable should be of the form:
> *
> *  =D:=D:\nt\private\mytests

As luck would have it, Raymond Chen just posted some more info/history
about this stuff on his OldNewThing blog:

http://blogs.msdn.com/oldnewthing/archive/2010/05/06/10008132.aspx