ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

env.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.