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 = (TCHAR *) nssm_imagepath();
134 ZeroMemory(&si, sizeof(si));
136 PROCESS_INFORMATION pi;
137 ZeroMemory(&pi, sizeof(pi));
138 unsigned long flags = CREATE_SUSPENDED;
140 flags |= CREATE_UNICODE_ENVIRONMENT;
144 Try to relaunch ourselves but with the candidate environment set.
145 Assuming no solar flare activity, the only reason this would fail is if
146 the environment were invalid.
148 if (CreateProcess(0, path, 0, 0, 0, flags, env, 0, &si, &pi)) {
149 TerminateProcess(pi.hProcess, 0);
152 unsigned long error = GetLastError();
153 if (error == ERROR_INVALID_PARAMETER) return 1;
161 Duplicate an environment block returned by GetEnvironmentStrings().
162 Since such a block is by definition readonly, and duplicate_environment()
163 modifies its inputs, this function takes a copy of the input and operates
166 void duplicate_environment_strings(TCHAR *env) {
167 TCHAR *newenv = copy_environment_block(env);
168 if (! newenv) return;
170 duplicate_environment(newenv);
171 HeapFree(GetProcessHeap(), 0, newenv);