[Undocumented] Variables __CD__ & __APPDIR__

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
carlos
Expert
Posts: 501
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

[Undocumented] Variables __CD__ & __APPDIR__

#1 Post by carlos » 23 Dec 2014 14:07

Hello. I found a new undocumented variable, in addition to %__CD__% it is %__APPDIR__%

%__APPDIR__%
have the path (with a backlash at the end) where the application that request the variable is located.
For example, if we run C:\Windows\system32\cmd.exe , %__APPDIR__% will expand to C:\Windows\system32\
If we copy cmd to C:\dev\cmd.exe and run it %__APPDIR__% will expand to C:\dev\

Code: Select all

Echo %__APPDIR__%


Also I re document the %__CD__%

%__CD__%
have the current directory (with a backlash at the end) of the application that request the variable.

Code: Select all

Echo %__CD__%



Both, really are pseudo environment variables, found in the function RtlQueryEnvironmentVariable_U of windows in ntdll.dll
Last edited by carlos on 23 Dec 2014 14:51, edited 3 times in total.

carlos
Expert
Posts: 501
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: [Undocumented] Variables __CD__ & __APPDIR__

#2 Post by carlos » 23 Dec 2014 14:10

I found %__APPDIR__% investigating %__CD__%. I suspect that %__CD__% was unrelated to environment variables of cmd.exe, because I programming a c code, and inside this application I change the directory of my application (not the directory of cmd.exe).

This was my output:

Code: Select all

C:\dev>test.exe
ExpandEnvironmentStringsW("%__CD__%")=C:\dev\
GetEnvironmentVariableW("__CD__")=C:\dev\
Directory changed to C:\
ExpandEnvironmentStringsW("%__CD__%")=C:\
GetEnvironmentVariableW("__CD__")=C:\

C:\dev>


This was my code:
test.c

Code: Select all


#include <windows.h>
#include <stdio.h>

DWORD WINAPI ExpandEnvironmentStrings(LPCTSTR lpSrc, LPTSTR lpDst, DWORD nSize);
DWORD WINAPI GetEnvironmentVariable(LPCTSTR lpName, LPTSTR lpBuffer,DWORD nSize);

void print__cd__(void);
void print__appdir__(void);


int main(int argc, char ** argv)
{

   print__cd__();
   
   if (! SetCurrentDirectoryW(L"C:\\")) {
   wprintf(L"Cannot change to directory C:\\");
   return 1;
   }

   wprintf(L"Directory changed to C:\\\n");
   print__cd__();
   
   getchar();
   return 0;
}

void print__cd__()
{
   DWORD chrs;
   wchar_t buf[MAX_PATH];

   chrs = ExpandEnvironmentStringsW(L"%__CD__%", buf, MAX_PATH);
   buf[chrs] = 0;
   wprintf(L"ExpandEnvironmentStringsW(\"%%__CD__%%\")=%ls\n", buf);
   chrs = GetEnvironmentVariableW (L"__CD__", buf, MAX_PATH);
   buf[chrs] = 0;
   wprintf(L"GetEnvironmentVariableW(\"__CD__\")=%ls\n", buf);
}


and investigating I look the function RtlQueryEnvironmentVariable_U of windows in ntdll.dll and next to %__CD__% I found %__APPDIR__%

dbenham
Expert
Posts: 2398
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: [Undocumented] Variables __CD__ & __APPDIR__

#3 Post by dbenham » 23 Dec 2014 14:47

Very interesting. :!: :shock:
Another pseudo "environment variable" that operates at a very low level windows call.

Code: Select all

D:\test>echo %__appdir__%
C:\Windows\System32\

D:\test>set "__appdir__=override"

D:\test>set __
__appdir__=override

D:\test>echo %__appdir__%
C:\Windows\System32\


So a true environment variable can be defined, but you cannot retrieve the user specified value except via SET. This is showing the exact same behavior as %__CD__%. If so, than the behavior should be different on XP.

You may be interested in my StackOverflow Q&A: Why can't I access a variable named __CD__ on Windows 7?

I wonder if there are any more %__var__% variables yet to be discovered :?:


Dave Benham

penpen
Expert
Posts: 1864
Joined: 23 Jun 2013 06:15
Location: Germany

Re: [Undocumented] Variables __CD__ & __APPDIR__

#4 Post by penpen » 23 Dec 2014 15:45

The behaviour using winXp home 32 bit is this:

Code: Select all

Z:\>echo %__appdir__%
C:\WINDOWS\system32\

Z:\>set "__appdir__=override"

Z:\>set __
__appdir__=override

Z:\>echo %__appdir__%
override


penpen

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: [Undocumented] Variables __CD__ & __APPDIR__

#5 Post by Liviu » 23 Dec 2014 20:44

dbenham wrote:I wonder if there are any more %__var__% variables yet to be discovered :?:

It's not a "double-underscore" variable, but NUMBER_OF_PROCESSORS behaves the same way as __CD__ under Win7 (and, I assume, later).

Code: Select all

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\>echo %NUMBER_OF_PROCESSORS%
4

C:\>set NUMBER_OF_PROCESSORS
NUMBER_OF_PROCESSORS=4

C:\>set NUMBER_OF_PROCESSORS=1

C:\>echo %NUMBER_OF_PROCESSORS%
4

C:\>set NUMBER_OF_PROCESSORS
NUMBER_OF_PROCESSORS=1

C:\>

It also behaves like __CD__ under XP, too, where explicitly setting it _is_ reflected in both 'echo %var%' and 'set var' afterwards.

Liviu

dbenham
Expert
Posts: 2398
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: [Undocumented] Variables __CD__ & __APPDIR__

#6 Post by dbenham » 23 Dec 2014 21:58

Whoa :shock:

That is a shocker :!:

carlos
Expert
Posts: 501
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: [Undocumented] Variables __CD__ & __APPDIR__

#7 Post by carlos » 23 Dec 2014 23:27

Thanks Liviu.

NUMBER_OF_PROCESSORS in windows 8 is a pseudo variable (the unicode text "NUMBER_OF_PROCESSORS" is present in ntdll.dll), but in windows xp, it is not present in ntdll.dll, if you do this in xp:

Code: Select all

C:\dev>SET "NUMBER_OF_PROCESSORS="

C:\dev>ECHO %NUMBER_OF_PROCESSORS%
%NUMBER_OF_PROCESSORS%



but if you do the same on windows 8:

Code: Select all

C:\dev>SET "NUMBER_OF_PROCESSORS="

C:\dev>ECHO %NUMBER_OF_PROCESSORS%
4



In windows xp, NUMBER_OF_PROCESSORS is a real environment variable, and in windows 7 is a pseudo variable.

Thus, in windows xp are present the next pseudovariable:

Code: Select all

%__CD__%
%__APPDIR__%


and in windows 7:

Code: Select all

%__CD__%
%__APPDIR__%
%NUMBER_OF_PROCESSORS%

npocmaka_
Posts: 498
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: [Undocumented] Variables __CD__ & __APPDIR__

#8 Post by npocmaka_ » 24 Dec 2014 10:09

Great ! :D

Just took a look at ntdll.dll and its strings.

Found this:

Code: Select all

E:\>echo %FIRMWARE_TYPE%
Legacy


EDIT.

it's not presented on my XP image.Probably only from windows 8 and above - http://msdn.microsoft.com/en-us/library ... 20(v=vs.85).aspx

Squashman
Expert
Posts: 4198
Joined: 23 Dec 2011 13:59

Re: [Undocumented] Variables __CD__ & __APPDIR__

#9 Post by Squashman » 24 Dec 2014 11:04

I used the Sysinternals STRINGS.exe to see what I else we could dump from that DLL. I couldn't see much more.

Code: Select all

for /F "delims=" %G in ('strings -u -q ntdll.dll') do @if defined %G echo %G

output

Code: Select all

NUMBER_OF_PROCESSORS
__APPDIR__
__CD__
PROCESSOR_ARCHITECTURE
CommonProgramW6432
CommonProgramFiles(x86)
CommonProgramFiles
ProgramW6432
ProgramFiles(x86)
ProgramFiles
tmp

Squashman
Expert
Posts: 4198
Joined: 23 Dec 2011 13:59

Re: [Undocumented] Variables __CD__ & __APPDIR__

#10 Post by Squashman » 24 Dec 2014 11:22

npocmaka_ wrote:Great ! :D

Just took a look at ntdll.dll and its strings.

Found this:

Code: Select all

E:\>echo %FIRMWARE_TYPE%
Legacy


EDIT.

it's not presented on my XP image.Probably only from windows 8 and above - http://msdn.microsoft.com/en-us/library ... 20(v=vs.85).aspx

Not in Windows 7.

npocmaka_
Posts: 498
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: [Undocumented] Variables __CD__ & __APPDIR__

#11 Post by npocmaka_ » 26 Dec 2014 15:13

Squashman wrote:I used the Sysinternals STRINGS.exe to see what I else we could dump from that DLL. I couldn't see much more.

Code: Select all

for /F "delims=" %G in ('strings -u -q ntdll.dll') do @if defined %G echo %G

output


Be braver :

Code: Select all

@echo off
pushd %windir%\system32
for %%# in (*.dll *.exe) do (
   rem echo ##  %%#  ##
   for /F "delims=" %%G in ('strings -n 7  %%#') do (
      @if defined %%G if /i %%G neq "temp" echo %%G
   )   
)
POPD


Have found this:

Code: Select all

echo %USERDOMAIN_ROAMINGPROFILE%


Again not available on the XP image .But not sure if its only on my machine.
It's visible with SET USERDOMAIN so it's not dynamic pseudo variable , just cant find a documentation for it (only this).

Post Reply