1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: dll/win32/kernel32/client/environ.c 5 * PURPOSE: Environment functions 6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) 7 * Emanuele Aliberti 8 * Thomas Weidenmueller 9 * UPDATE HISTORY: 10 * Created 01/11/98 11 */ 12 13 /* INCLUDES *******************************************************************/ 14 15 #include <k32.h> 16 17 #define NDEBUG 18 #include <debug.h> 19 20 /* FUNCTIONS ******************************************************************/ 21 22 /* 23 * @implemented 24 */ 25 DWORD 26 WINAPI 27 DECLSPEC_HOTPATCH 28 GetEnvironmentVariableA(IN LPCSTR lpName, 29 IN LPSTR lpBuffer, 30 IN DWORD nSize) 31 { 32 ANSI_STRING VarName, VarValue; 33 UNICODE_STRING VarNameU, VarValueU; 34 PWSTR Buffer; 35 ULONG Result = 0; 36 USHORT UniSize; 37 NTSTATUS Status; 38 39 /* Initialize all the strings */ 40 RtlInitAnsiString(&VarName, lpName); 41 RtlInitUnicodeString(&VarNameU, NULL); 42 RtlInitUnicodeString(&VarValueU, NULL); 43 Status = RtlAnsiStringToUnicodeString(&VarNameU, &VarName, TRUE); 44 if (!NT_SUCCESS(Status)) goto Quickie; 45 46 /* Check if the size is too big to fit */ 47 UniSize = UNICODE_STRING_MAX_CHARS - 2; 48 if (nSize <= UniSize) 49 { 50 /* It fits, but was there a string at all? */ 51 if (nSize) 52 { 53 /* Keep the given size, minus a NULL-char */ 54 UniSize = (USHORT)(nSize - 1); 55 } 56 else 57 { 58 /* No size */ 59 UniSize = 0; 60 } 61 } 62 else 63 { 64 /* String is too big, so we need to return a NULL char as well */ 65 UniSize--; 66 } 67 68 /* Allocate the value string buffer */ 69 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize * sizeof(WCHAR)); 70 if (!Buffer) 71 { 72 Status = STATUS_NO_MEMORY; 73 goto Quickie; 74 } 75 76 /* And initialize its string */ 77 RtlInitEmptyUnicodeString(&VarValueU, Buffer, UniSize * sizeof(WCHAR)); 78 79 /* Acquire the PEB lock since we'll be querying variables now */ 80 RtlAcquirePebLock(); 81 82 /* Query the variable */ 83 Status = RtlQueryEnvironmentVariable_U(NULL, &VarNameU, &VarValueU); 84 if ((NT_SUCCESS(Status)) && !(nSize)) Status = STATUS_BUFFER_TOO_SMALL; 85 86 /* Check if we didn't have enough space */ 87 if (Status == STATUS_BUFFER_TOO_SMALL) 88 { 89 /* Fixup the length that the API returned */ 90 VarValueU.MaximumLength = VarValueU.Length + sizeof(UNICODE_NULL); 91 92 /* Free old Unicode buffer */ 93 RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU.Buffer); 94 95 /* Allocate new one */ 96 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, VarValueU.MaximumLength); 97 if (Buffer) 98 { 99 /* Query the variable so we can know its size */ 100 VarValueU.Buffer = Buffer; 101 Status = RtlQueryEnvironmentVariable_U(NULL, &VarNameU, &VarValueU); 102 if (NT_SUCCESS(Status)) 103 { 104 /* Get the ASCII length of the variable */ 105 Result = RtlUnicodeStringToAnsiSize(&VarValueU); 106 } 107 } 108 else 109 { 110 /* Set failure status */ 111 Status = STATUS_NO_MEMORY; 112 VarValueU.Buffer = NULL; 113 } 114 } 115 else if (NT_SUCCESS(Status)) 116 { 117 /* Check if the size is too big to fit */ 118 UniSize = UNICODE_STRING_MAX_BYTES - 1; 119 if (nSize <= UniSize) UniSize = (USHORT)nSize; 120 121 /* Check the size */ 122 Result = RtlUnicodeStringToAnsiSize(&VarValueU); 123 if (Result <= UniSize) 124 { 125 /* Convert the string */ 126 RtlInitEmptyAnsiString(&VarValue, lpBuffer, UniSize); 127 Status = RtlUnicodeStringToAnsiString(&VarValue, &VarValueU, FALSE); 128 if (NT_SUCCESS(Status)) 129 { 130 /* NULL-terminate and set the final length */ 131 lpBuffer[VarValue.Length] = ANSI_NULL; 132 Result = VarValue.Length; 133 } 134 } 135 } 136 137 /* Release the lock */ 138 RtlReleasePebLock(); 139 140 Quickie: 141 /* Free the strings */ 142 RtlFreeUnicodeString(&VarNameU); 143 if (VarValueU.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU.Buffer); 144 145 /* Check if we succeeded */ 146 if (!NT_SUCCESS(Status)) 147 { 148 /* We did not, clear the result and set the error code */ 149 BaseSetLastNTError(Status); 150 Result = 0; 151 } 152 153 /* Return the result */ 154 return Result; 155 } 156 157 /* 158 * @implemented 159 */ 160 DWORD 161 WINAPI 162 DECLSPEC_HOTPATCH 163 GetEnvironmentVariableW(IN LPCWSTR lpName, 164 IN LPWSTR lpBuffer, 165 IN DWORD nSize) 166 { 167 UNICODE_STRING VarName, VarValue; 168 NTSTATUS Status; 169 USHORT UniSize; 170 171 if (nSize <= (UNICODE_STRING_MAX_CHARS - 1)) 172 { 173 if (nSize) 174 { 175 UniSize = (USHORT)nSize * sizeof(WCHAR) - sizeof(UNICODE_NULL); 176 } 177 else 178 { 179 UniSize = 0; 180 } 181 } 182 else 183 { 184 UniSize = UNICODE_STRING_MAX_BYTES - sizeof(UNICODE_NULL); 185 } 186 187 Status = RtlInitUnicodeStringEx(&VarName, lpName); 188 if (!NT_SUCCESS(Status)) 189 { 190 BaseSetLastNTError(Status); 191 return 0; 192 } 193 194 RtlInitEmptyUnicodeString(&VarValue, lpBuffer, UniSize); 195 196 Status = RtlQueryEnvironmentVariable_U(NULL, &VarName, &VarValue); 197 if (!NT_SUCCESS(Status)) 198 { 199 if (Status == STATUS_BUFFER_TOO_SMALL) 200 { 201 return (VarValue.Length / sizeof(WCHAR)) + sizeof(ANSI_NULL); 202 } 203 BaseSetLastNTError (Status); 204 return 0; 205 } 206 207 lpBuffer[VarValue.Length / sizeof(WCHAR)] = UNICODE_NULL; 208 209 return (VarValue.Length / sizeof(WCHAR)); 210 } 211 212 /* 213 * @implemented 214 */ 215 BOOL 216 WINAPI 217 DECLSPEC_HOTPATCH 218 SetEnvironmentVariableA(IN LPCSTR lpName, 219 IN LPCSTR lpValue) 220 { 221 ANSI_STRING VarName, VarValue; 222 UNICODE_STRING VarNameU, VarValueU; 223 NTSTATUS Status; 224 225 RtlInitAnsiString(&VarName, (LPSTR)lpName); 226 Status = RtlAnsiStringToUnicodeString(&VarNameU, &VarName, TRUE); 227 if (NT_SUCCESS(Status)) 228 { 229 if (lpValue) 230 { 231 RtlInitAnsiString(&VarValue, (LPSTR)lpValue); 232 Status = RtlAnsiStringToUnicodeString(&VarValueU, &VarValue, TRUE); 233 if (NT_SUCCESS(Status)) 234 { 235 Status = RtlSetEnvironmentVariable(NULL, &VarNameU, &VarValueU); 236 RtlFreeUnicodeString(&VarValueU); 237 } 238 } 239 else 240 { 241 Status = RtlSetEnvironmentVariable(NULL, &VarNameU, NULL); 242 } 243 244 RtlFreeUnicodeString(&VarNameU); 245 246 if (NT_SUCCESS(Status)) return TRUE; 247 } 248 249 BaseSetLastNTError(Status); 250 return FALSE; 251 } 252 253 /* 254 * @implemented 255 */ 256 BOOL 257 WINAPI 258 DECLSPEC_HOTPATCH 259 SetEnvironmentVariableW(IN LPCWSTR lpName, 260 IN LPCWSTR lpValue) 261 { 262 UNICODE_STRING VarName, VarValue; 263 NTSTATUS Status; 264 265 Status = RtlInitUnicodeStringEx(&VarName, lpName); 266 if (NT_SUCCESS(Status)) 267 { 268 if (lpValue) 269 { 270 Status = RtlInitUnicodeStringEx(&VarValue, lpValue); 271 if (NT_SUCCESS(Status)) 272 { 273 Status = RtlSetEnvironmentVariable(NULL, &VarName, &VarValue); 274 } 275 } 276 else 277 { 278 Status = RtlSetEnvironmentVariable(NULL, &VarName, NULL); 279 } 280 281 if (NT_SUCCESS(Status)) return TRUE; 282 } 283 284 BaseSetLastNTError(Status); 285 return FALSE; 286 } 287 288 /* 289 * @implemented 290 */ 291 LPSTR 292 WINAPI 293 GetEnvironmentStringsA(VOID) 294 { 295 ULONG Length, Size; 296 NTSTATUS Status; 297 PWCHAR Environment, p; 298 PCHAR Buffer = NULL; 299 300 RtlAcquirePebLock(); 301 p = Environment = NtCurrentPeb()->ProcessParameters->Environment; 302 303 do 304 { 305 p += wcslen(p) + 1; 306 } while (*p); 307 308 Length = p - Environment + 1; 309 310 Status = RtlUnicodeToMultiByteSize(&Size, Environment, Length * sizeof(WCHAR)); 311 if (NT_SUCCESS(Status)) 312 { 313 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size); 314 if (Buffer) 315 { 316 Status = RtlUnicodeToOemN(Buffer, Size, 0, Environment, Length * sizeof(WCHAR)); 317 if (!NT_SUCCESS(Status)) 318 { 319 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 320 Buffer = NULL; 321 322 BaseSetLastNTError(Status); 323 } 324 } 325 else 326 { 327 BaseSetLastNTError(STATUS_NO_MEMORY); 328 } 329 } 330 else 331 { 332 BaseSetLastNTError(Status); 333 } 334 335 RtlReleasePebLock(); 336 return Buffer; 337 } 338 339 /* 340 * @implemented 341 */ 342 LPWSTR 343 WINAPI 344 GetEnvironmentStringsW(VOID) 345 { 346 PWCHAR Environment, p; 347 ULONG Length; 348 349 RtlAcquirePebLock(); 350 351 p = Environment = NtCurrentPeb()->ProcessParameters->Environment; 352 353 do 354 { 355 p += wcslen(p) + 1; 356 } while (*p); 357 358 Length = p - Environment + 1; 359 360 p = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR)); 361 if (p) 362 { 363 RtlCopyMemory(p, Environment, Length * sizeof(WCHAR)); 364 } 365 else 366 { 367 BaseSetLastNTError(STATUS_NO_MEMORY); 368 } 369 370 RtlReleasePebLock(); 371 return p; 372 } 373 374 /* 375 * @implemented 376 */ 377 BOOL 378 WINAPI 379 FreeEnvironmentStringsA(IN LPSTR EnvironmentStrings) 380 { 381 return RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings); 382 } 383 384 /* 385 * @implemented 386 */ 387 BOOL 388 WINAPI 389 FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings) 390 { 391 return RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings); 392 } 393 394 /* 395 * @implemented 396 */ 397 DWORD 398 WINAPI 399 ExpandEnvironmentStringsA(IN LPCSTR lpSrc, 400 IN LPSTR lpDst, 401 IN DWORD nSize) 402 { 403 ANSI_STRING Source, Dest; 404 UNICODE_STRING SourceU, DestU; 405 PWSTR Buffer; 406 ULONG Result = 0, Length; 407 USHORT UniSize; 408 NTSTATUS Status; 409 410 /* Check if the size is too big to fit */ 411 UniSize = UNICODE_STRING_MAX_CHARS - 2; 412 if (nSize <= UniSize) UniSize = (USHORT)nSize; 413 414 /* Clear the input buffer */ 415 if (lpDst) *lpDst = ANSI_NULL; 416 417 /* Initialize all the strings */ 418 RtlInitAnsiString(&Source, lpSrc); 419 RtlInitUnicodeString(&SourceU, NULL); 420 RtlInitUnicodeString(&DestU, NULL); 421 Status = RtlAnsiStringToUnicodeString(&SourceU, &Source, TRUE); 422 if (!NT_SUCCESS(Status)) goto Quickie; 423 424 /* If the string fit in, make space for a NULL char */ 425 if (UniSize) 426 { 427 UniSize--; 428 } 429 else 430 { 431 /* No input size, so no string size */ 432 UniSize = 0; 433 } 434 435 /* Allocate the value string buffer */ 436 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize * sizeof(WCHAR)); 437 if (!Buffer) 438 { 439 Status = STATUS_NO_MEMORY; 440 goto Quickie; 441 } 442 443 /* And initialize its string */ 444 RtlInitEmptyUnicodeString(&DestU, Buffer, UniSize * sizeof(WCHAR)); 445 446 /* Query the variable */ 447 Length = 0; 448 Status = RtlExpandEnvironmentStrings_U(NULL, &SourceU, &DestU, &Length); 449 450 /* Check if we didn't have enough space */ 451 if (Status == STATUS_BUFFER_TOO_SMALL) 452 { 453 /* Fixup the length that the API returned */ 454 DestU.MaximumLength = (SHORT)Length; 455 456 /* Free old Unicode buffer */ 457 RtlFreeHeap(RtlGetProcessHeap(), 0, DestU.Buffer); 458 459 /* Allocate new one */ 460 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length); 461 if (Buffer) 462 { 463 /* Query the variable so we can know its size */ 464 DestU.Buffer = Buffer; 465 Status = RtlExpandEnvironmentStrings_U(NULL, &SourceU, &DestU, &Length); 466 if (NT_SUCCESS(Status)) 467 { 468 /* Get the ASCII length of the variable, add a byte for NULL */ 469 Result = RtlUnicodeStringToAnsiSize(&DestU) + sizeof(ANSI_NULL); 470 } 471 } 472 else 473 { 474 /* Set failure status */ 475 Status = STATUS_NO_MEMORY; 476 DestU.Buffer = NULL; 477 } 478 } 479 else if (NT_SUCCESS(Status)) 480 { 481 /* Check if the size is too big to fit */ 482 UniSize = UNICODE_STRING_MAX_BYTES - 1; 483 if (nSize <= UniSize) UniSize = (USHORT)nSize; 484 485 /* Check the size */ 486 Result = RtlUnicodeStringToAnsiSize(&DestU); 487 if (Result <= UniSize) 488 { 489 /* Convert the string */ 490 RtlInitEmptyAnsiString(&Dest, lpDst, UniSize); 491 Status = RtlUnicodeStringToAnsiString(&Dest, &DestU, FALSE); 492 493 /* Write a NULL-char in case of failure only */ 494 if (!NT_SUCCESS(Status)) *lpDst = ANSI_NULL; 495 } 496 } 497 Quickie: 498 /* Free the strings */ 499 RtlFreeUnicodeString(&SourceU); 500 if (DestU.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, DestU.Buffer); 501 502 /* Check if we succeeded */ 503 if (!NT_SUCCESS(Status)) 504 { 505 /* We did not, clear the result and set the error code */ 506 BaseSetLastNTError(Status); 507 Result = 0; 508 } 509 510 /* Return the result */ 511 return Result; 512 } 513 514 /* 515 * @implemented 516 */ 517 DWORD 518 WINAPI 519 ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, 520 IN LPWSTR lpDst, 521 IN DWORD nSize) 522 { 523 UNICODE_STRING Source, Destination; 524 NTSTATUS Status; 525 USHORT UniSize; 526 527 UniSize = min(nSize, UNICODE_STRING_MAX_CHARS - 2); 528 529 RtlInitUnicodeString(&Source, (LPWSTR)lpSrc); 530 RtlInitEmptyUnicodeString(&Destination, lpDst, UniSize * sizeof(WCHAR)); 531 532 Status = RtlExpandEnvironmentStrings_U(NULL, 533 &Source, 534 &Destination, 535 &nSize); 536 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL)) 537 { 538 return nSize / sizeof(WCHAR); 539 } 540 541 BaseSetLastNTError(Status); 542 return 0; 543 } 544 545 /* 546 * @implemented 547 */ 548 BOOL 549 WINAPI 550 SetEnvironmentStringsA(IN LPCH NewEnvironment) 551 { 552 STUB; 553 return FALSE; 554 } 555 556 /* 557 * @implemented 558 */ 559 BOOL 560 WINAPI 561 SetEnvironmentStringsW(IN LPWCH NewEnvironment) 562 { 563 STUB; 564 return FALSE; 565 } 566 567 /* EOF */ 568