/** * @brief Queries an environment variable. * @param[in] name the environment variable name. * @return The value of the environment variable. * NULL indicates failure. * @note The returned string should be freed * by the winx_free call after its use. */ wchar_t *winx_getenv(wchar_t *name) { wchar_t *value; UNICODE_STRING n, v; NTSTATUS status; DbgCheck1(name,NULL); value = winx_malloc(MAX_ENV_VALUE_LENGTH * sizeof(wchar_t)); RtlInitUnicodeString(&n,name); v.Buffer = value; v.Length = 0; v.MaximumLength = MAX_ENV_VALUE_LENGTH * sizeof(wchar_t); status = RtlQueryEnvironmentVariable_U(NULL,&n,&v); if(!NT_SUCCESS(status)){ strace(status,"cannot query %ws",name); winx_free(value); return NULL; } if(value[0] == 0){ winx_free(value); return NULL; } return value; }
/*********************************************************************** * GetEnvironmentVariableW (KERNEL32.@) */ DWORD WINAPI GetEnvironmentVariableW( LPCWSTR name, LPWSTR val, DWORD size ) { UNICODE_STRING us_name; UNICODE_STRING us_value; NTSTATUS status; unsigned len; TRACE("(%s %p %u)\n", debugstr_w(name), val, size); if (!name || !*name) { SetLastError(ERROR_ENVVAR_NOT_FOUND); return 0; } RtlInitUnicodeString(&us_name, name); us_value.Length = 0; us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR); us_value.Buffer = val; status = RtlQueryEnvironmentVariable_U(NULL, &us_name, &us_value); len = us_value.Length / sizeof(WCHAR); if (status != STATUS_SUCCESS) { SetLastError( RtlNtStatusToDosError(status) ); return (status == STATUS_BUFFER_TOO_SMALL) ? len + 1 : 0; } if (size) val[len] = '\0'; return us_value.Length / sizeof(WCHAR); }
static void set_registry_variables(WCHAR **env, HKEY hkey, DWORD type, BOOL set_path) { static const WCHAR SystemRootW[] = {'S','y','s','t','e','m','R','o','o','t',0}; static const WCHAR SystemDriveW[] = {'S','y','s','t','e','m','D','r','i','v','e',0}; static const WCHAR PATHW[] = {'P','A','T','H'}; UNICODE_STRING us_name, us_value; WCHAR name[1024], value[1024]; DWORD ret, index, size; for (index = 0; ; index++) { size = sizeof(name)/sizeof(WCHAR); ret = RegEnumValueW(hkey, index, name, &size, NULL, NULL, NULL, NULL); if (ret != ERROR_SUCCESS) break; if (!memicmpW(name, SystemRootW, sizeof(SystemRootW)/sizeof(WCHAR))) continue; if (!memicmpW(name, SystemDriveW, sizeof(SystemDriveW)/sizeof(WCHAR))) continue; RtlInitUnicodeString(&us_name, name); us_value.Buffer = value; us_value.MaximumLength = sizeof(value); if (!memicmpW(name, PATHW, sizeof(PATHW)/sizeof(WCHAR)) && !RtlQueryEnvironmentVariable_U(*env, &us_name, &us_value)) { if (!set_path) continue; size = strlenW(value)+1; if (!get_reg_value(*env, hkey, name, value+size, sizeof(value)-size*sizeof(WCHAR))) continue; value[size] = ';'; RtlInitUnicodeString(&us_value, value); RtlSetEnvironmentVariable(env, &us_name, &us_value); continue; } if (!get_reg_value(*env, hkey, name, value, sizeof(value))) continue; if(!value[0]) continue; RtlInitUnicodeString(&us_value, value); RtlSetEnvironmentVariable(env, &us_name, &us_value); } }
/* * @implemented */ DWORD WINAPI GetEnvironmentVariableW ( LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize ) { UNICODE_STRING VarName; UNICODE_STRING VarValue; NTSTATUS Status; RtlInitUnicodeString (&VarName, lpName); VarValue.Length = 0; VarValue.MaximumLength = (USHORT) (nSize ? nSize - 1 : 0) * sizeof(WCHAR); VarValue.Buffer = lpBuffer; Status = RtlQueryEnvironmentVariable_U (NULL, &VarName, &VarValue); if (!NT_SUCCESS(Status)) { if (Status == STATUS_BUFFER_TOO_SMALL) { return (VarValue.Length / sizeof(WCHAR)) + 1; } else { SetLastErrorByStatus (Status); return 0; } } if (nSize != 0) { /* make sure the string is NULL-terminated! RtlQueryEnvironmentVariable_U only terminates it if MaximumLength < Length */ lpBuffer[VarValue.Length / sizeof(WCHAR)] = L'\0'; } return (VarValue.Length / sizeof(WCHAR)); }
static BOOL AppendUserEnvironmentVariable(PWSTR* Environment, LPWSTR lpName, LPWSTR lpValue) { NTSTATUS Status; UNICODE_STRING Name, Value; RtlInitUnicodeString(&Name, lpName); Value.Length = 0; Value.MaximumLength = 1024 * sizeof(WCHAR); Value.Buffer = LocalAlloc(LPTR, Value.MaximumLength); if (Value.Buffer == NULL) return FALSE; Value.Buffer[0] = UNICODE_NULL; Status = RtlQueryEnvironmentVariable_U(*Environment, &Name, &Value); if (NT_SUCCESS(Status)) RtlAppendUnicodeToString(&Value, L";"); RtlAppendUnicodeToString(&Value, lpValue); Status = RtlSetEnvironmentVariable(Environment, &Name, &Value); LocalFree(Value.Buffer); if (!NT_SUCCESS(Status)) { DPRINT1("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status); return FALSE; } return TRUE; }
/* * @implemented */ DWORD WINAPI GetEnvironmentVariableA ( LPCSTR lpName, LPSTR lpBuffer, DWORD nSize ) { ANSI_STRING VarName; ANSI_STRING VarValue; UNICODE_STRING VarNameU; UNICODE_STRING VarValueU; NTSTATUS Status; /* initialize unicode variable name string */ RtlInitAnsiString (&VarName, (LPSTR)lpName); RtlAnsiStringToUnicodeString (&VarNameU, &VarName, TRUE); /* initialize ansi variable value string */ VarValue.Length = 0; VarValue.MaximumLength = (USHORT)nSize; VarValue.Buffer = lpBuffer; /* initialize unicode variable value string and allocate buffer */ VarValueU.Length = 0; if (nSize != 0) { VarValueU.MaximumLength = (USHORT)(nSize - 1) * sizeof(WCHAR); VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), 0, nSize * sizeof(WCHAR)); if (VarValueU.Buffer != NULL) { /* NULL-terminate the buffer in any case! RtlQueryEnvironmentVariable_U only terminates it if MaximumLength < Length! */ VarValueU.Buffer[nSize - 1] = L'\0'; } } else { VarValueU.MaximumLength = 0; VarValueU.Buffer = NULL; } if (VarValueU.Buffer != NULL || nSize == 0) { /* get unicode environment variable */ Status = RtlQueryEnvironmentVariable_U (NULL, &VarNameU, &VarValueU); if (!NT_SUCCESS(Status)) { /* free unicode buffer */ RtlFreeHeap (RtlGetProcessHeap (), 0, VarValueU.Buffer); /* free unicode variable name string */ RtlFreeUnicodeString (&VarNameU); SetLastErrorByStatus (Status); if (Status == STATUS_BUFFER_TOO_SMALL) { return (VarValueU.Length / sizeof(WCHAR)) + 1; } else { return 0; } } /* convert unicode value string to ansi */ RtlUnicodeStringToAnsiString (&VarValue, &VarValueU, FALSE); if (VarValueU.Buffer != NULL) { /* free unicode buffer */ RtlFreeHeap (RtlGetProcessHeap (), 0, VarValueU.Buffer); } /* free unicode variable name string */ RtlFreeUnicodeString (&VarNameU); return (VarValueU.Length / sizeof(WCHAR)); } else { SetLastError (ERROR_NOT_ENOUGH_MEMORY); return 0; } }
/* * @implemented */ NTSTATUS NTAPI RtlExpandEnvironmentStrings_U(PWSTR Environment, PUNICODE_STRING Source, PUNICODE_STRING Destination, PULONG Length) { UNICODE_STRING Variable; UNICODE_STRING Value; NTSTATUS ReturnStatus = STATUS_SUCCESS; NTSTATUS Status; PWSTR SourceBuffer; PWSTR DestBuffer; PWSTR CopyBuffer; PWSTR VariableEnd; ULONG SourceLength; ULONG DestMax; ULONG CopyLength; ULONG Tail; ULONG TotalLength = 1; /* for terminating NULL */ DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n", Environment, Source, Destination, Length); SourceLength = Source->Length / sizeof(WCHAR); SourceBuffer = Source->Buffer; DestMax = Destination->MaximumLength / sizeof(WCHAR); DestBuffer = Destination->Buffer; while (SourceLength) { if (*SourceBuffer != L'%') { CopyBuffer = SourceBuffer; CopyLength = 0; while (SourceLength != 0 && *SourceBuffer != L'%') { SourceBuffer++; CopyLength++; SourceLength--; } } else { /* Process environment variable. */ VariableEnd = SourceBuffer + 1; Tail = SourceLength - 1; while (*VariableEnd != L'%' && Tail != 0) { VariableEnd++; Tail--; } if (Tail != 0) { Variable.MaximumLength = Variable.Length = (USHORT)(VariableEnd - (SourceBuffer + 1)) * sizeof(WCHAR); Variable.Buffer = SourceBuffer + 1; Value.Length = 0; Value.MaximumLength = (USHORT)DestMax * sizeof(WCHAR); Value.Buffer = DestBuffer; Status = RtlQueryEnvironmentVariable_U(Environment, &Variable, &Value); if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) { SourceBuffer = VariableEnd + 1; SourceLength = Tail - 1; TotalLength += Value.Length / sizeof(WCHAR); if (Status != STATUS_BUFFER_TOO_SMALL) { DestBuffer += Value.Length / sizeof(WCHAR); DestMax -= Value.Length / sizeof(WCHAR); } else { DestMax = 0; ReturnStatus = STATUS_BUFFER_TOO_SMALL; } continue; } else { /* Variable not found. */ CopyBuffer = SourceBuffer; CopyLength = SourceLength - Tail + 1; SourceLength -= CopyLength; SourceBuffer += CopyLength; } } else { /* Unfinished variable name. */ CopyBuffer = SourceBuffer; CopyLength = SourceLength; SourceLength = 0; } } TotalLength += CopyLength; if (DestMax) { if (DestMax < CopyLength) { CopyLength = DestMax; ReturnStatus = STATUS_BUFFER_TOO_SMALL; } RtlCopyMemory(DestBuffer, CopyBuffer, CopyLength * sizeof(WCHAR)); DestMax -= CopyLength; DestBuffer += CopyLength; } } /* NULL-terminate the buffer. */ if (DestMax) *DestBuffer = 0; else ReturnStatus = STATUS_BUFFER_TOO_SMALL; Destination->Length = (USHORT)(DestBuffer - Destination->Buffer) * sizeof(WCHAR); if (Length != NULL) *Length = TotalLength * sizeof(WCHAR); DPRINT("Destination %wZ\n", Destination); return ReturnStatus; }
NTSTATUS Nt_CreateProcess( LPCWSTR ApplicationName, LPWSTR CommandLine, ULONG CreationFlags, LPCWSTR CurrentDirectory, LPSTARTUPINFO StartupInfo, LPPROCESS_INFORMATION ProcessInformation ) { NTSTATUS Status; WCHAR FullPathBuffer[MAX_PATH *2], DllPathBuffer[0x3000]; UNICODE_STRING PathVariableName, DllPath, ImagePathName; UNICODE_STRING _CommandLine, _CurrentDirectory; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; RTL_USER_PROCESS_INFORMATION ProcessInfo; if (!RtlDosPathNameToNtPathName_U(ApplicationName, &ImagePathName, NULL, NULL)) return STATUS_OBJECT_PATH_NOT_FOUND; RTL_CONST_STRING(PathVariableName, L"Path"); DllPath.Length = 0; DllPath.MaximumLength = sizeof(DllPathBuffer); DllPath.Buffer = DllPathBuffer; RtlQueryEnvironmentVariable_U(NULL, &PathVariableName, &DllPath); if (CommandLine != NULL) RtlInitUnicodeString(&_CommandLine, CommandLine); if (CurrentDirectory != NULL) RtlInitUnicodeString(&_CurrentDirectory, CurrentDirectory); Status = RtlCreateProcessParameters( &ProcessParameters, &ImagePathName, &DllPath, CurrentDirectory == NULL ? NULL : &_CurrentDirectory, CommandLine == NULL ? NULL : &_CommandLine, NULL, NULL, NULL, NULL, NULL ); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(&ImagePathName); return Status; } ProcessInfo.Size = sizeof(ProcessInfo); Status = RtlCreateUserProcess( &ImagePathName, OBJ_CASE_INSENSITIVE, ProcessParameters, NULL, NULL, NULL, FALSE, NULL, NULL, &ProcessInfo ); RtlDestroyProcessParameters(ProcessParameters); RtlFreeUnicodeString(&ImagePathName); if (!NT_SUCCESS(Status)) return Status; if (!FLAG_ON(CreationFlags, CREATE_SUSPENDED)) { NtResumeThread(ProcessInfo.ThreadHandle, NULL); } if (ProcessInformation == NULL) { NtClose(ProcessInfo.ProcessHandle); NtClose(ProcessInfo.ThreadHandle); return Status; } ProcessInformation->dwProcessId = (ULONG)ProcessInfo.ClientId.UniqueProcess; ProcessInformation->dwThreadId = (ULONG)ProcessInfo.ClientId.UniqueThread; ProcessInformation->hProcess = ProcessInfo.ProcessHandle; ProcessInformation->hThread = ProcessInfo.ThreadHandle; return Status; }