[DCOMLAUNCH] Add a DcomLaunch service stub
[reactos.git] / base / shell / cmd / setlocal.c
1 /*
2 * SETLOCAL.C - setlocal and endlocal internal batch commands.
3 *
4 * History:
5 *
6 * 1 Feb 2008 (Christoph von Wittich)
7 * started.
8 */
9
10 #include "precomp.h"
11
12 typedef struct _SETLOCAL
13 {
14 struct _SETLOCAL *Prev;
15 BOOL EnableExtensions;
16 BOOL DelayedExpansion;
17 LPTSTR Environment;
18 } SETLOCAL;
19
20 /* Create a copy of the current environment */
21 LPTSTR
22 DuplicateEnvironment(VOID)
23 {
24 LPTSTR Environ = GetEnvironmentStrings();
25 LPTSTR End, EnvironCopy;
26
27 if (!Environ) return NULL;
28
29 for (End = Environ; *End; End += _tcslen(End) + 1) ;
30 EnvironCopy = cmd_alloc((End + 1 - Environ) * sizeof(TCHAR));
31
32 if (EnvironCopy)
33 memcpy(EnvironCopy, Environ, (End + 1 - Environ) * sizeof(TCHAR));
34
35 FreeEnvironmentStrings(Environ);
36 return EnvironCopy;
37 }
38
39 INT cmd_setlocal(LPTSTR param)
40 {
41 SETLOCAL *Saved;
42 LPTSTR *arg;
43 INT argc, i;
44
45 /* SETLOCAL only works inside a batch file */
46 if (!bc)
47 return 0;
48
49 Saved = cmd_alloc(sizeof(SETLOCAL));
50 if (!Saved)
51 {
52 WARN("Cannot allocate memory for Saved!\n");
53 error_out_of_memory();
54 return 1;
55 }
56 Saved->Prev = bc->setlocal;
57 Saved->EnableExtensions = bEnableExtensions;
58 Saved->DelayedExpansion = bDelayedExpansion;
59 Saved->Environment = DuplicateEnvironment();
60 if (!Saved->Environment)
61 {
62 error_out_of_memory();
63 cmd_free(Saved);
64 return 1;
65 }
66 bc->setlocal = Saved;
67
68 nErrorLevel = 0;
69
70 arg = splitspace(param, &argc);
71 for (i = 0; i < argc; i++)
72 {
73 if (!_tcsicmp(arg[i], _T("enableextensions")))
74 /* FIXME: not implemented! */
75 bEnableExtensions = TRUE;
76 else if (!_tcsicmp(arg[i], _T("disableextensions")))
77 /* FIXME: not implemented! */
78 bEnableExtensions = FALSE;
79 else if (!_tcsicmp(arg[i], _T("enabledelayedexpansion")))
80 bDelayedExpansion = TRUE;
81 else if (!_tcsicmp(arg[i], _T("disabledelayedexpansion")))
82 bDelayedExpansion = FALSE;
83 else
84 {
85 error_invalid_parameter_format(arg[i]);
86 break;
87 }
88 }
89 freep(arg);
90
91 return nErrorLevel;
92 }
93
94 /* endlocal doesn't take any params */
95 INT cmd_endlocal(LPTSTR param)
96 {
97 LPTSTR Environ, Name, Value;
98 SETLOCAL *Saved;
99
100 /* Pop a SETLOCAL struct off of this batch file's stack */
101 if (!bc || !(Saved = bc->setlocal))
102 return 0;
103 bc->setlocal = Saved->Prev;
104
105 bEnableExtensions = Saved->EnableExtensions;
106 bDelayedExpansion = Saved->DelayedExpansion;
107
108 /* First, clear out the environment. Since making any changes to the
109 * environment invalidates pointers obtained from GetEnvironmentStrings(),
110 * we must make a copy of it and get the variable names from that */
111 Environ = DuplicateEnvironment();
112 if (Environ)
113 {
114 for (Name = Environ; *Name; Name += _tcslen(Name) + 1)
115 {
116 if (!(Value = _tcschr(Name + 1, _T('='))))
117 continue;
118 *Value++ = _T('\0');
119 SetEnvironmentVariable(Name, NULL);
120 Name = Value;
121 }
122 cmd_free(Environ);
123 }
124
125 /* Now, restore variables from the copy saved by cmd_setlocal */
126 for (Name = Saved->Environment; *Name; Name += _tcslen(Name) + 1)
127 {
128 if (!(Value = _tcschr(Name + 1, _T('='))))
129 continue;
130 *Value++ = _T('\0');
131 SetEnvironmentVariable(Name, Value);
132 Name = Value;
133 }
134
135 cmd_free(Saved->Environment);
136 cmd_free(Saved);
137 return 0;
138 }