3 /* Copy an environment block. */
4 TCHAR *copy_environment_block(TCHAR *env) {
8 for (len = 0; env[len]; len++) while (env[len]) len++;
11 TCHAR *newenv = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR));
13 log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("copy_environment_block()"), 0);
17 memmove(newenv, env, len * sizeof(TCHAR));
22 The environment block starts with variables of the form
23 =C:=C:\Windows\System32 which we ignore.
25 TCHAR *useful_environment(TCHAR *rawenv) {
29 while (*env == _T('=')) {
38 /* Expand an environment variable. Must call HeapFree() on the result. */
39 TCHAR *expand_environment_string(TCHAR *string) {
42 len = ExpandEnvironmentStrings(string, 0, 0);
44 log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, string, error_string(GetLastError()), 0);
48 TCHAR *ret = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR));
50 log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("ExpandEnvironmentStrings()"), _T("expand_environment_string"), 0);
54 if (! ExpandEnvironmentStrings(string, ret, len)) {
55 log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, string, error_string(GetLastError()), 0);
56 HeapFree(GetProcessHeap(), 0, ret);
64 Set all the environment variables from an environment block in the current
65 environment or remove all the variables in the block from the current
68 static int set_environment_block(TCHAR *env, bool set) {
72 for (s = env; *s; s++) {
73 for (t = s; *t && *t != _T('='); t++);
77 TCHAR *expanded = expand_environment_string(++t);
79 if (! SetEnvironmentVariable(s, expanded)) ret++;
80 HeapFree(GetProcessHeap(), 0, expanded);
83 if (! SetEnvironmentVariable(s, t)) ret++;
87 if (! SetEnvironmentVariable(s, NULL)) ret++;
97 int set_environment_block(TCHAR *env) {
98 return set_environment_block(env, true);
101 static int unset_environment_block(TCHAR *env) {
102 return set_environment_block(env, false);
105 /* Remove all variables from the process environment. */
106 int clear_environment() {
107 TCHAR *rawenv = GetEnvironmentStrings();
108 TCHAR *env = useful_environment(rawenv);
110 int ret = unset_environment_block(env);
112 if (rawenv) FreeEnvironmentStrings(rawenv);
117 /* Set the current environment to exactly duplicate an environment block. */
118 int duplicate_environment(TCHAR *rawenv) {
119 int ret = clear_environment();
120 TCHAR *env = useful_environment(rawenv);
121 ret += set_environment_block(env);
126 Verify an environment block.
127 Returns: 1 if environment is invalid.
128 0 if environment is OK.
131 int test_environment(TCHAR *env) {
132 TCHAR path[PATH_LENGTH];
133 GetModuleFileName(0, path, _countof(path));
135 ZeroMemory(&si, sizeof(si));
137 PROCESS_INFORMATION pi;
138 ZeroMemory(&pi, sizeof(pi));
139 unsigned long flags = CREATE_SUSPENDED;
141 flags |= CREATE_UNICODE_ENVIRONMENT;
145 Try to relaunch ourselves but with the candidate environment set.
146 Assuming no solar flare activity, the only reason this would fail is if
147 the environment were invalid.
149 if (CreateProcess(0, path, 0, 0, 0, flags, env, 0, &si, &pi)) {
150 TerminateProcess(pi.hProcess, 0);
153 unsigned long error = GetLastError();
154 if (error == ERROR_INVALID_PARAMETER) return 1;
162 Duplicate an environment block returned by GetEnvironmentStrings().
163 Since such a block is by definition readonly, and duplicate_environment()
164 modifies its inputs, this function takes a copy of the input and operates
167 void duplicate_environment_strings(TCHAR *env) {
168 TCHAR *newenv = copy_environment_block(env);
169 if (! newenv) return;
171 duplicate_environment(newenv);
172 HeapFree(GetProcessHeap(), 0, newenv);