Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenenv.c
Go to the documentation of this file.
00001 /* COPYRIGHT: See COPYING in the top level directory 00002 * PROJECT: ReactOS system libraries 00003 * FILE: lib/rtl/env.c 00004 * PURPOSE: Environment functions 00005 * PROGRAMMER: Eric Kohl 00006 */ 00007 00008 /* INCLUDES ******************************************************************/ 00009 00010 #include <rtl.h> 00011 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* FUNCTIONS *****************************************************************/ 00016 00017 /* 00018 * @implemented 00019 */ 00020 NTSTATUS NTAPI 00021 RtlCreateEnvironment(BOOLEAN Inherit, 00022 PWSTR *Environment) 00023 { 00024 MEMORY_BASIC_INFORMATION MemInfo; 00025 PVOID EnvPtr = NULL; 00026 NTSTATUS Status = STATUS_SUCCESS; 00027 SIZE_T RegionSize = PAGE_SIZE; 00028 00029 if (Inherit == TRUE) 00030 { 00031 RtlAcquirePebLock(); 00032 00033 if (NtCurrentPeb()->ProcessParameters->Environment != NULL) 00034 { 00035 Status = NtQueryVirtualMemory(NtCurrentProcess(), 00036 NtCurrentPeb()->ProcessParameters->Environment, 00037 MemoryBasicInformation, 00038 &MemInfo, 00039 sizeof(MEMORY_BASIC_INFORMATION), 00040 NULL); 00041 if (!NT_SUCCESS(Status)) 00042 { 00043 RtlReleasePebLock(); 00044 *Environment = NULL; 00045 return(Status); 00046 } 00047 00048 RegionSize = MemInfo.RegionSize; 00049 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 00050 &EnvPtr, 00051 0, 00052 &RegionSize, 00053 MEM_RESERVE | MEM_COMMIT, 00054 PAGE_READWRITE); 00055 if (!NT_SUCCESS(Status)) 00056 { 00057 RtlReleasePebLock(); 00058 *Environment = NULL; 00059 return(Status); 00060 } 00061 00062 memmove(EnvPtr, 00063 NtCurrentPeb ()->ProcessParameters->Environment, 00064 MemInfo.RegionSize); 00065 00066 *Environment = EnvPtr; 00067 } 00068 00069 RtlReleasePebLock (); 00070 } 00071 else 00072 { 00073 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 00074 &EnvPtr, 00075 0, 00076 &RegionSize, 00077 MEM_RESERVE | MEM_COMMIT, 00078 PAGE_READWRITE); 00079 if (NT_SUCCESS(Status)) 00080 { 00081 memset(EnvPtr, 00082 0, 00083 RegionSize); 00084 *Environment = EnvPtr; 00085 } 00086 } 00087 00088 return(Status); 00089 } 00090 00091 00092 /* 00093 * @implemented 00094 */ 00095 VOID NTAPI 00096 RtlDestroyEnvironment(PWSTR Environment) 00097 { 00098 SIZE_T Size = 0; 00099 00100 NtFreeVirtualMemory(NtCurrentProcess(), 00101 (PVOID)&Environment, 00102 &Size, 00103 MEM_RELEASE); 00104 } 00105 00106 00107 /* 00108 * @implemented 00109 */ 00110 NTSTATUS NTAPI 00111 RtlExpandEnvironmentStrings_U(PWSTR Environment, 00112 PUNICODE_STRING Source, 00113 PUNICODE_STRING Destination, 00114 PULONG Length) 00115 { 00116 UNICODE_STRING Variable; 00117 UNICODE_STRING Value; 00118 NTSTATUS ReturnStatus = STATUS_SUCCESS; 00119 NTSTATUS Status; 00120 PWSTR SourceBuffer; 00121 PWSTR DestBuffer; 00122 PWSTR CopyBuffer; 00123 PWSTR VariableEnd; 00124 ULONG SourceLength; 00125 ULONG DestMax; 00126 ULONG CopyLength; 00127 ULONG Tail; 00128 ULONG TotalLength = 1; /* for terminating NULL */ 00129 00130 DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n", 00131 Environment, Source, Destination, Length); 00132 00133 SourceLength = Source->Length / sizeof(WCHAR); 00134 SourceBuffer = Source->Buffer; 00135 DestMax = Destination->MaximumLength / sizeof(WCHAR); 00136 DestBuffer = Destination->Buffer; 00137 00138 while (SourceLength) 00139 { 00140 if (*SourceBuffer != L'%') 00141 { 00142 CopyBuffer = SourceBuffer; 00143 CopyLength = 0; 00144 while (SourceLength != 0 && *SourceBuffer != L'%') 00145 { 00146 SourceBuffer++; 00147 CopyLength++; 00148 SourceLength--; 00149 } 00150 } 00151 else 00152 { 00153 /* Process environment variable. */ 00154 00155 VariableEnd = SourceBuffer + 1; 00156 Tail = SourceLength - 1; 00157 while (*VariableEnd != L'%' && Tail != 0) 00158 { 00159 VariableEnd++; 00160 Tail--; 00161 } 00162 00163 if (Tail != 0) 00164 { 00165 Variable.MaximumLength = 00166 Variable.Length = (USHORT)(VariableEnd - (SourceBuffer + 1)) * sizeof(WCHAR); 00167 Variable.Buffer = SourceBuffer + 1; 00168 00169 Value.Length = 0; 00170 Value.MaximumLength = (USHORT)DestMax * sizeof(WCHAR); 00171 Value.Buffer = DestBuffer; 00172 00173 Status = RtlQueryEnvironmentVariable_U(Environment, &Variable, 00174 &Value); 00175 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) 00176 { 00177 SourceBuffer = VariableEnd + 1; 00178 SourceLength = Tail - 1; 00179 TotalLength += Value.Length / sizeof(WCHAR); 00180 if (Status != STATUS_BUFFER_TOO_SMALL) 00181 { 00182 DestBuffer += Value.Length / sizeof(WCHAR); 00183 DestMax -= Value.Length / sizeof(WCHAR); 00184 } 00185 else 00186 { 00187 DestMax = 0; 00188 ReturnStatus = STATUS_BUFFER_TOO_SMALL; 00189 } 00190 continue; 00191 } 00192 else 00193 { 00194 /* Variable not found. */ 00195 CopyBuffer = SourceBuffer; 00196 CopyLength = SourceLength - Tail + 1; 00197 SourceLength -= CopyLength; 00198 SourceBuffer += CopyLength; 00199 } 00200 } 00201 else 00202 { 00203 /* Unfinished variable name. */ 00204 CopyBuffer = SourceBuffer; 00205 CopyLength = SourceLength; 00206 SourceLength = 0; 00207 } 00208 } 00209 00210 TotalLength += CopyLength; 00211 if (DestMax) 00212 { 00213 if (DestMax < CopyLength) 00214 { 00215 CopyLength = DestMax; 00216 ReturnStatus = STATUS_BUFFER_TOO_SMALL; 00217 } 00218 RtlCopyMemory(DestBuffer, CopyBuffer, CopyLength * sizeof(WCHAR)); 00219 DestMax -= CopyLength; 00220 DestBuffer += CopyLength; 00221 } 00222 } 00223 00224 /* NULL-terminate the buffer. */ 00225 if (DestMax) 00226 *DestBuffer = 0; 00227 else 00228 ReturnStatus = STATUS_BUFFER_TOO_SMALL; 00229 00230 Destination->Length = (USHORT)(DestBuffer - Destination->Buffer) * sizeof(WCHAR); 00231 if (Length != NULL) 00232 *Length = TotalLength * sizeof(WCHAR); 00233 00234 DPRINT("Destination %wZ\n", Destination); 00235 00236 return ReturnStatus; 00237 } 00238 00239 00240 /* 00241 * @implemented 00242 */ 00243 VOID NTAPI 00244 RtlSetCurrentEnvironment(PWSTR NewEnvironment, 00245 PWSTR *OldEnvironment) 00246 { 00247 PVOID EnvPtr; 00248 00249 DPRINT("NewEnvironment 0x%p OldEnvironment 0x%p\n", 00250 NewEnvironment, OldEnvironment); 00251 00252 RtlAcquirePebLock(); 00253 00254 EnvPtr = NtCurrentPeb()->ProcessParameters->Environment; 00255 NtCurrentPeb()->ProcessParameters->Environment = NewEnvironment; 00256 00257 if (OldEnvironment != NULL) 00258 *OldEnvironment = EnvPtr; 00259 00260 RtlReleasePebLock(); 00261 } 00262 00263 00264 /* 00265 * @implemented 00266 */ 00267 NTSTATUS NTAPI 00268 RtlSetEnvironmentVariable(PWSTR *Environment, 00269 PUNICODE_STRING Name, 00270 PUNICODE_STRING Value) 00271 { 00272 MEMORY_BASIC_INFORMATION mbi; 00273 UNICODE_STRING var; 00274 size_t hole_len, new_len, env_len = 0; 00275 WCHAR *new_env = 0, *env_end = 0, *wcs, *env, *val = 0, *tail = 0, *hole = 0; 00276 PWSTR head = NULL; 00277 SIZE_T size = 0, new_size; 00278 LONG f = 1; 00279 NTSTATUS Status = STATUS_SUCCESS; 00280 00281 DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n", 00282 Environment, Name, Value); 00283 00284 /* Variable name must not be empty */ 00285 if (Name->Length < sizeof(WCHAR)) 00286 return STATUS_INVALID_PARAMETER; 00287 00288 /* Variable names can't contain a '=' except as a first character. */ 00289 for (wcs = Name->Buffer + 1; 00290 wcs < Name->Buffer + (Name->Length / sizeof(WCHAR)); 00291 wcs++) 00292 { 00293 if (*wcs == L'=') 00294 return STATUS_INVALID_PARAMETER; 00295 } 00296 00297 if (Environment) 00298 { 00299 env = *Environment; 00300 } 00301 else 00302 { 00303 RtlAcquirePebLock(); 00304 env = NtCurrentPeb()->ProcessParameters->Environment; 00305 } 00306 00307 if (env) 00308 { 00309 /* get environment length */ 00310 wcs = env_end = env; 00311 do 00312 { 00313 env_end += wcslen(env_end) + 1; 00314 } 00315 while (*env_end); 00316 env_end++; 00317 env_len = env_end - env; 00318 DPRINT("environment length %ld characters\n", env_len); 00319 00320 /* find where to insert */ 00321 while (*wcs) 00322 { 00323 var.Buffer = wcs++; 00324 wcs = wcschr(wcs, L'='); 00325 if (wcs == NULL) 00326 { 00327 wcs = var.Buffer + wcslen(var.Buffer); 00328 } 00329 if (*wcs) 00330 { 00331 var.Length = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR); 00332 var.MaximumLength = var.Length; 00333 val = ++wcs; 00334 wcs += wcslen(wcs); 00335 f = RtlCompareUnicodeString(&var, Name, TRUE); 00336 if (f >= 0) 00337 { 00338 if (f) /* Insert before found */ 00339 { 00340 hole = tail = var.Buffer; 00341 } 00342 else /* Exact match */ 00343 { 00344 head = var.Buffer; 00345 tail = ++wcs; 00346 hole = val; 00347 } 00348 goto found; 00349 } 00350 } 00351 wcs++; 00352 } 00353 hole = tail = wcs; /* Append to environment */ 00354 } 00355 00356 found: 00357 if (Value != NULL && Value->Buffer != NULL) 00358 { 00359 hole_len = tail - hole; 00360 /* calculate new environment size */ 00361 new_size = Value->Length + sizeof(WCHAR); 00362 /* adding new variable */ 00363 if (f) 00364 new_size += Name->Length + sizeof(WCHAR); 00365 new_len = new_size / sizeof(WCHAR); 00366 if (hole_len < new_len) 00367 { 00368 /* enlarge environment size */ 00369 /* check the size of available memory */ 00370 new_size += (env_len - hole_len) * sizeof(WCHAR); 00371 new_size = ROUND_UP(new_size, PAGE_SIZE); 00372 mbi.RegionSize = 0; 00373 DPRINT("new_size %lu\n", new_size); 00374 00375 if (env) 00376 { 00377 Status = NtQueryVirtualMemory(NtCurrentProcess(), 00378 env, 00379 MemoryBasicInformation, 00380 &mbi, 00381 sizeof(MEMORY_BASIC_INFORMATION), 00382 NULL); 00383 if (!NT_SUCCESS(Status)) 00384 { 00385 if (Environment == NULL) 00386 { 00387 RtlReleasePebLock(); 00388 } 00389 return(Status); 00390 } 00391 } 00392 00393 if (new_size > mbi.RegionSize) 00394 { 00395 /* reallocate memory area */ 00396 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 00397 (PVOID)&new_env, 00398 0, 00399 &new_size, 00400 MEM_RESERVE | MEM_COMMIT, 00401 PAGE_READWRITE); 00402 if (!NT_SUCCESS(Status)) 00403 { 00404 if (Environment == NULL) 00405 { 00406 RtlReleasePebLock(); 00407 } 00408 return(Status); 00409 } 00410 00411 if (env) 00412 { 00413 memmove(new_env, 00414 env, 00415 (hole - env) * sizeof(WCHAR)); 00416 hole = new_env + (hole - env); 00417 } 00418 else 00419 { 00420 /* absolutely new environment */ 00421 tail = hole = new_env; 00422 *hole = 0; 00423 env_end = hole + 1; 00424 } 00425 } 00426 } 00427 00428 /* move tail */ 00429 memmove (hole + new_len, tail, (env_end - tail) * sizeof(WCHAR)); 00430 00431 if (new_env) 00432 { 00433 /* we reallocated environment, let's free the old one */ 00434 if (Environment) 00435 *Environment = new_env; 00436 else 00437 NtCurrentPeb()->ProcessParameters->Environment = new_env; 00438 00439 if (env) 00440 { 00441 size = 0; 00442 NtFreeVirtualMemory(NtCurrentProcess(), 00443 (PVOID)&env, 00444 &size, 00445 MEM_RELEASE); 00446 } 00447 } 00448 00449 /* and now copy given stuff */ 00450 if (f) 00451 { 00452 /* copy variable name and '=' character */ 00453 memmove(hole, 00454 Name->Buffer, 00455 Name->Length); 00456 hole += Name->Length / sizeof(WCHAR); 00457 *hole++ = L'='; 00458 } 00459 00460 /* copy value */ 00461 memmove(hole, 00462 Value->Buffer, 00463 Value->Length); 00464 hole += Value->Length / sizeof(WCHAR); 00465 *hole = 0; 00466 } 00467 else 00468 { 00469 /* remove the environment variable */ 00470 if (f == 0) 00471 { 00472 memmove(head, 00473 tail, 00474 (env_end - tail) * sizeof(WCHAR)); 00475 } 00476 } 00477 00478 if (Environment == NULL) 00479 { 00480 RtlReleasePebLock(); 00481 } 00482 00483 return(Status); 00484 } 00485 00486 00487 /* 00488 * @implemented 00489 */ 00490 NTSTATUS NTAPI 00491 RtlQueryEnvironmentVariable_U(PWSTR Environment, 00492 PUNICODE_STRING Name, 00493 PUNICODE_STRING Value) 00494 { 00495 NTSTATUS Status; 00496 PWSTR wcs; 00497 UNICODE_STRING var; 00498 PWSTR val; 00499 BOOLEAN SysEnvUsed = FALSE; 00500 00501 DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n", 00502 Environment, Name, Value); 00503 00504 if (Environment == NULL) 00505 { 00506 PPEB Peb = RtlGetCurrentPeb(); 00507 if (Peb) { 00508 Environment = Peb->ProcessParameters->Environment; 00509 SysEnvUsed = TRUE; 00510 } 00511 } 00512 00513 if (Environment == NULL) 00514 { 00515 return(STATUS_VARIABLE_NOT_FOUND); 00516 } 00517 00518 Value->Length = 0; 00519 if (SysEnvUsed == TRUE) 00520 RtlAcquirePebLock(); 00521 00522 wcs = Environment; 00523 DPRINT("Starting search at :%p\n", wcs); 00524 while (*wcs) 00525 { 00526 var.Buffer = wcs++; 00527 wcs = wcschr(wcs, L'='); 00528 if (wcs == NULL) 00529 { 00530 wcs = var.Buffer + wcslen(var.Buffer); 00531 DPRINT("Search at :%S\n", wcs); 00532 } 00533 if (*wcs) 00534 { 00535 var.Length = var.MaximumLength = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR); 00536 val = ++wcs; 00537 wcs += wcslen(wcs); 00538 DPRINT("Search at :%S\n", wcs); 00539 00540 if (RtlEqualUnicodeString(&var, Name, TRUE)) 00541 { 00542 Value->Length = (USHORT)(wcs - val) * sizeof(WCHAR); 00543 if (Value->Length <= Value->MaximumLength) 00544 { 00545 memcpy(Value->Buffer, val, 00546 min(Value->Length + sizeof(WCHAR), Value->MaximumLength)); 00547 DPRINT("Value %S\n", val); 00548 DPRINT("Return STATUS_SUCCESS\n"); 00549 Status = STATUS_SUCCESS; 00550 } 00551 else 00552 { 00553 DPRINT("Return STATUS_BUFFER_TOO_SMALL\n"); 00554 Status = STATUS_BUFFER_TOO_SMALL; 00555 } 00556 00557 if (SysEnvUsed == TRUE) 00558 RtlReleasePebLock(); 00559 00560 return(Status); 00561 } 00562 } 00563 wcs++; 00564 } 00565 00566 if (SysEnvUsed == TRUE) 00567 RtlReleasePebLock(); 00568 00569 DPRINT("Return STATUS_VARIABLE_NOT_FOUND: %wZ\n", Name); 00570 return(STATUS_VARIABLE_NOT_FOUND); 00571 } 00572 00573 /* EOF */ Generated on Mon May 28 2012 04:36:13 for ReactOS by
1.7.6.1
|