Leaked source code of windows server 2003
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.

362 lines
12 KiB

  1. // Ruler
  2. // 1 2 3 4 5 6 7 8
  3. //345678901234567890123456789012345678901234567890123456789012345678901234567890
  4. /********************************************************************/
  5. /* */
  6. /* The standard layout. */
  7. /* */
  8. /* The standard layout for 'cpp' files in this code is as */
  9. /* follows: */
  10. /* */
  11. /* 1. Include files. */
  12. /* 2. Constants local to the class. */
  13. /* 3. Data structures local to the class. */
  14. /* 4. Data initializations. */
  15. /* 5. Static functions. */
  16. /* 6. Class functions. */
  17. /* */
  18. /* The constructor is typically the first function, class */
  19. /* member functions appear in alphabetical order with the */
  20. /* destructor appearing at the end of the file. Any section */
  21. /* or function this is not required is simply omitted. */
  22. /* */
  23. /********************************************************************/
  24. #include "LibraryPCH.hpp"
  25. #include "Environment.hpp"
  26. #include "Spinlock.hpp"
  27. /********************************************************************/
  28. /* */
  29. /* Constants local to the class. */
  30. /* */
  31. /* The enviroment class slaves various information to speed */
  32. /* up access to it. */
  33. /* */
  34. /********************************************************************/
  35. CONST SBIT16 EnvironmentCacheSize = 16;
  36. CONST SBIT32 SizeOfName = 256;
  37. /********************************************************************/
  38. /* */
  39. /* Static member initialization. */
  40. /* */
  41. /* Static member initialization sets the initial value for all */
  42. /* static members. */
  43. /* */
  44. /********************************************************************/
  45. #pragma init_seg(lib)
  46. SBIT32 ENVIRONMENT::Activations = 0;
  47. SBIT32 ENVIRONMENT::AllocationGranularity = 0;
  48. SBIT16 ENVIRONMENT::NumberOfProcessors = 0;
  49. SBIT32 ENVIRONMENT::SizeOfMemory = 0;
  50. SBIT32 ENVIRONMENT::SizeOfPage = 0;
  51. #ifndef DISABLE_ENVIRONMENT_VARIABLES
  52. CHAR *ENVIRONMENT::ProgramName = NULL;
  53. CHAR *ENVIRONMENT::ProgramPath = NULL;
  54. SBIT32 ENVIRONMENT::MaxVariables = 0;
  55. SBIT32 ENVIRONMENT::VariablesUsed = 0;
  56. ENVIRONMENT::VARIABLE *ENVIRONMENT::Variables = NULL;
  57. #endif
  58. /********************************************************************/
  59. /* */
  60. /* Class constructor. */
  61. /* */
  62. /* Create a new environment and initialize it if needed. This */
  63. /* call is not thread safe and should only be made in a single */
  64. /* thread environment. */
  65. /* */
  66. /********************************************************************/
  67. ENVIRONMENT::ENVIRONMENT( VOID )
  68. {
  69. if ( AtomicIncrement( & Activations ) == 1 )
  70. {
  71. #ifndef DISABLE_ENVIRONMENT_VARIABLES
  72. AUTO CHAR ProgramFullName[ SizeOfName ];
  73. #endif
  74. AUTO MEMORYSTATUS MemoryStatus;
  75. AUTO SYSTEM_INFO SystemInformation;
  76. //
  77. // Initialize the class members to reasonable default values.
  78. //
  79. GetSystemInfo( & SystemInformation );
  80. GlobalMemoryStatus( & MemoryStatus );
  81. AllocationGranularity =
  82. ((SBIT32) SystemInformation.dwAllocationGranularity);
  83. NumberOfProcessors =
  84. ((SBIT16) SystemInformation.dwNumberOfProcessors);
  85. SizeOfMemory =
  86. ((SBIT32) MemoryStatus.dwTotalPhys);
  87. SizeOfPage =
  88. ((SBIT32) SystemInformation.dwPageSize);
  89. #ifndef DISABLE_ENVIRONMENT_VARIABLES
  90. //
  91. // Slave interesting values like the program name and path variable.
  92. //
  93. ProgramName = NULL;
  94. ProgramPath = NULL;
  95. MaxVariables = 0;
  96. VariablesUsed = 0;
  97. Variables = NULL;
  98. //
  99. // Get the complete file name for the current program.
  100. //
  101. if ( GetModuleFileName( NULL,ProgramFullName,SizeOfName ) > 0 )
  102. {
  103. REGISTER SBIT16 Count = (SBIT16) strlen( (char*) ProgramFullName );
  104. REGISTER CHAR *Characters = & ProgramFullName[ Count ];
  105. //
  106. // Scan backwards looking for the first directory seperator.
  107. // There is guaranteed to be at least one.
  108. //
  109. for
  110. (
  111. /* void */;
  112. ((Count > 0) && ((*Characters) != (*DirectorySeperator())));
  113. Count --, Characters --
  114. );
  115. (*(Characters ++)) = '\0';
  116. //
  117. // Allocate space for the directory path and copy the
  118. // path into the newly allocated area.
  119. //
  120. ProgramPath = new CHAR [ (strlen( ((char*) ProgramFullName) )+1) ];
  121. if ( ProgramPath != NULL )
  122. {
  123. (VOID) strcpy
  124. (
  125. ((char*) ProgramPath),
  126. ((char*) ProgramFullName)
  127. );
  128. }
  129. //
  130. // Scan the program name backwards looking for a '.'.
  131. //
  132. for
  133. (
  134. Count = (SBIT16) strlen( (char*) Characters );
  135. ((Count > 0) && (Characters[ Count ] != '.'));
  136. Count --
  137. );
  138. //
  139. // Remove any trailing suffix from the program name
  140. // (i.e. '*.EXE').
  141. //
  142. if ( Count > 0 )
  143. { Characters[ Count ] = '\0'; }
  144. //
  145. // Allocate space for the program name and copy the name
  146. // into the newly allocated area.
  147. //
  148. ProgramName = new CHAR [ (strlen( ((char*) Characters) )+1) ];
  149. if ( ProgramName != NULL )
  150. {
  151. (void) strcpy
  152. (
  153. ((char*) ProgramName),
  154. ((char*) Characters)
  155. );
  156. }
  157. }
  158. #endif
  159. }
  160. }
  161. #ifndef DISABLE_ENVIRONMENT_VARIABLES
  162. /********************************************************************/
  163. /* */
  164. /* Read an environment variable. */
  165. /* */
  166. /* When we read an environment value we want to make sure that */
  167. /* it never changes and gets slaved in memory. This routine */
  168. /* implements this functionality. */
  169. /* */
  170. /********************************************************************/
  171. CONST CHAR *ENVIRONMENT::ReadEnvironmentVariable( CONST CHAR *Name )
  172. {
  173. if ( Activations > 0 )
  174. {
  175. REGISTER SBIT32 Count;
  176. REGISTER SBIT32 SizeOfName = (SBIT32) strlen( (char*) Name );
  177. REGISTER VARIABLE *Variable;
  178. STATIC SPINLOCK Spinlock;
  179. //
  180. // The environment variables can only be scanned by one CPU at
  181. // a time because a second CPU might reallocate the storage
  182. // and cause the first CPU to fail.
  183. //
  184. Spinlock.ClaimLock();
  185. //
  186. // Examine all existing environment variables looking for a
  187. // match. If a match is found return it to the caller.
  188. //
  189. for
  190. (
  191. Count = VariablesUsed, Variable = Variables;
  192. Count > 0;
  193. Count --, Variable ++
  194. )
  195. {
  196. if
  197. (
  198. (SizeOfName == Variable -> SizeOfName)
  199. &&
  200. (strcmp( (char*) Name,(char*) Variable -> Name ) == 0)
  201. )
  202. {
  203. Spinlock.ReleaseLock();
  204. return (Variable -> Value);
  205. }
  206. }
  207. //
  208. // If we have filled up our array so we need to make it bigger.
  209. // So lets check for this now.
  210. //
  211. if ( VariablesUsed >= MaxVariables )
  212. {
  213. REGISTER VARIABLE *PreviousAllocation = Variables;
  214. if ( MaxVariables > 0 )
  215. {
  216. Variables =
  217. (
  218. (VARIABLE*) realloc
  219. (
  220. (VOID*) Variables,
  221. ((MaxVariables *= ExpandStore) * sizeof(VARIABLE))
  222. )
  223. );
  224. }
  225. else
  226. { Variables = new VARIABLE [ EnvironmentCacheSize ]; }
  227. //
  228. // Lets make sure we were successful. If not we restore
  229. // the previous pointer as it is still valid.
  230. //
  231. if ( Variables == NULL )
  232. {
  233. Variables = PreviousAllocation;
  234. Failure( "Expand memory in ReadEnvironmentVariable" );
  235. }
  236. }
  237. //
  238. // We know that we have enough memory to allocate another element and
  239. // that we are the only CPU in this section of code so just add the
  240. // new variable.
  241. //
  242. Variable = & Variables[ VariablesUsed ++ ];
  243. Variable -> SizeOfName =
  244. (SBIT32) strlen( (char*) Name );
  245. Variable -> SizeOfValue =
  246. (SBIT32) GetEnvironmentVariable( (char*) Name,"",0 );
  247. Variable -> Name = new CHAR [ (Variable -> SizeOfName + 1) ];
  248. (VOID) strcpy( (char*) Variable -> Name,(char*) Name );
  249. if ( Variable -> SizeOfValue > 0 )
  250. {
  251. Variable -> Value = new CHAR [ (Variable -> SizeOfValue + 1) ];
  252. (VOID) GetEnvironmentVariable
  253. (
  254. (char*) Name,
  255. (char*) Variable -> Value,
  256. (int) (Variable -> SizeOfValue + 1)
  257. );
  258. }
  259. else
  260. { Variable -> Value = NULL; }
  261. Spinlock.ReleaseLock();
  262. return (Variable -> Value);
  263. }
  264. else
  265. { return NULL; }
  266. }
  267. #endif
  268. /********************************************************************/
  269. /* */
  270. /* Class destructor. */
  271. /* */
  272. /* Destory an environment. This call is not thread safe and */
  273. /* should only be made in a single thread environment. */
  274. /* */
  275. /********************************************************************/
  276. ENVIRONMENT::~ENVIRONMENT( VOID )
  277. {
  278. if ( AtomicDecrement( & Activations ) == 0 )
  279. {
  280. #ifndef DISABLE_ENVIRONMENT_VARIABLES
  281. REGISTER SBIT32 Count;
  282. //
  283. // Delete all of the environment variable names
  284. // and values.
  285. //
  286. for ( Count = 0;Count < VariablesUsed;Count ++ )
  287. {
  288. REGISTER VARIABLE *Variable = & Variables[ Count ];
  289. delete [] Variable -> Name;
  290. if ( Variable -> Value != NULL )
  291. { delete [] Variable -> Value; }
  292. }
  293. //
  294. // Delete the environment array.
  295. //
  296. delete [] Variables;
  297. Variables = NULL;
  298. //
  299. // Delete the program name and path.
  300. //
  301. if ( ProgramPath != NULL )
  302. {
  303. delete [] ProgramPath;
  304. ProgramPath = NULL;
  305. }
  306. if ( ProgramName != NULL )
  307. {
  308. delete [] ProgramName;
  309. ProgramName = NULL;
  310. }
  311. #endif
  312. }
  313. }