Minor changes for ATAPI Srb Functions
[reactos.git] / base / applications / cmdutils / doskey / doskey.c
1 #include <stdarg.h>
2 #include <windef.h>
3 #include <winbase.h>
4 #include <winuser.h>
5 #include <wincon.h>
6 #include <stdio.h>
7 #include <wchar.h>
8 #include <assert.h>
9 #include <locale.h>
10
11 #include "doskey.h"
12
13 #define MAX_STRING 2000
14 WCHAR szStringBuf[MAX_STRING];
15 LPWSTR pszExeName = L"cmd.exe";
16
17 /* Function pointers */
18 typedef DWORD (WINAPI *GetConsoleCommandHistoryW_t) (LPWSTR sCommands, DWORD nBufferLength, LPWSTR sExeName);
19 typedef DWORD (WINAPI *GetConsoleCommandHistoryLengthW_t) (LPWSTR sExeName);
20 typedef BOOL (WINAPI *SetConsoleNumberOfCommandsW_t)(DWORD nNumber, LPWSTR sExeName);
21 typedef VOID (WINAPI *ExpungeConsoleCommandHistoryW_t)(LPWSTR sExeName);
22
23 GetConsoleCommandHistoryW_t pGetConsoleCommandHistoryW;
24 GetConsoleCommandHistoryLengthW_t pGetConsoleCommandHistoryLengthW;
25 SetConsoleNumberOfCommandsW_t pSetConsoleNumberOfCommandsW;
26 ExpungeConsoleCommandHistoryW_t pExpungeConsoleCommandHistoryW;
27
28 static VOID SetInsert(DWORD dwFlag)
29 {
30 DWORD dwMode;
31 HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
32 GetConsoleMode(hConsole, &dwMode);
33 dwMode |= ENABLE_EXTENDED_FLAGS;
34 SetConsoleMode(hConsole, (dwMode & ~ENABLE_INSERT_MODE) | dwFlag);
35 }
36
37 static VOID PrintHistory(VOID)
38 {
39 DWORD Length = pGetConsoleCommandHistoryLengthW(pszExeName);
40 PBYTE HistBuf;
41 WCHAR *Hist;
42 WCHAR *HistEnd;
43
44 HistBuf = HeapAlloc(GetProcessHeap(),
45 HEAP_ZERO_MEMORY,
46 Length);
47 if (!HistBuf) return;
48 Hist = (WCHAR *)HistBuf;
49 HistEnd = (WCHAR *)&HistBuf[Length];
50
51 if (pGetConsoleCommandHistoryW(Hist, Length, pszExeName))
52 for (; Hist < HistEnd; Hist += wcslen(Hist) + 1)
53 wprintf(L"%s\n", Hist);
54
55 HeapFree(GetProcessHeap(), 0, HistBuf);
56 }
57
58 static INT SetMacro(LPWSTR definition)
59 {
60 WCHAR *name, *nameend, *text, temp;
61
62 name = definition;
63 while (*name == L' ')
64 name++;
65
66 /* error if no '=' found */
67 if ((nameend = wcschr(name, L'=')) != NULL)
68 {
69 text = nameend + 1;
70 while (*text == L' ')
71 text++;
72
73 while (nameend > name && nameend[-1] == L' ')
74 nameend--;
75
76 /* Split rest into name and substitute */
77 temp = *nameend;
78 *nameend = L'\0';
79 /* Don't allow spaces in the name, since such a macro would be unusable */
80 if (!wcschr(name, L' ') && AddConsoleAliasW(name, text, pszExeName))
81 return 0;
82 *nameend = temp;
83 }
84
85 LoadStringW(GetModuleHandle(NULL), IDS_INVALID_MACRO_DEF, szStringBuf, MAX_STRING);
86 wprintf(szStringBuf, definition);
87 return 1;
88 }
89
90 static VOID PrintMacros(LPWSTR pszExeName, LPWSTR Indent)
91 {
92 DWORD Length = GetConsoleAliasesLengthW(pszExeName);
93 PBYTE AliasBuf;
94 WCHAR *Alias;
95 WCHAR *AliasEnd;
96
97 AliasBuf = HeapAlloc(GetProcessHeap(),
98 HEAP_ZERO_MEMORY,
99 Length * sizeof(BYTE));
100 if (!AliasBuf) return;
101 Alias = (WCHAR *)AliasBuf;
102 AliasEnd = (WCHAR *)&AliasBuf[Length];
103
104 if (GetConsoleAliasesW(Alias, Length * sizeof(BYTE), pszExeName))
105 for (; Alias < AliasEnd; Alias += wcslen(Alias) + 1)
106 wprintf(L"%s%s\n", Indent, Alias);
107
108 HeapFree(GetProcessHeap(), 0, AliasBuf);
109 }
110
111 static VOID PrintAllMacros(VOID)
112 {
113 DWORD Length = GetConsoleAliasExesLength();
114 PBYTE ExeNameBuf;
115 WCHAR *ExeName;
116 WCHAR *ExeNameEnd;
117
118 ExeNameBuf = HeapAlloc(GetProcessHeap(),
119 HEAP_ZERO_MEMORY,
120 Length * sizeof(BYTE));
121 if (!ExeNameBuf) return;
122 ExeName = (WCHAR *)ExeNameBuf;
123 ExeNameEnd = (WCHAR *)&ExeNameBuf[Length];
124
125 if (GetConsoleAliasExesW(ExeName, Length * sizeof(BYTE)))
126 {
127 for (; ExeName < ExeNameEnd; ExeName += wcslen(ExeName) + 1)
128 {
129 wprintf(L"[%s]\n", ExeName);
130 PrintMacros(ExeName, L" ");
131 wprintf(L"\n");
132 }
133 }
134
135 HeapFree(GetProcessHeap(), 0, ExeNameBuf);
136 }
137
138 static VOID ReadFromFile(LPWSTR param)
139 {
140 FILE* fp;
141 WCHAR line[MAX_PATH];
142
143 fp = _wfopen(param, L"r");
144 if (!fp)
145 {
146 _wperror(param);
147 return;
148 }
149
150 while ( fgetws(line, MAX_PATH, fp) != NULL)
151 {
152 /* Remove newline character */
153 WCHAR *end = &line[wcslen(line) - 1];
154 if (*end == L'\n')
155 *end = L'\0';
156
157 if (*line)
158 SetMacro(line);
159 }
160
161 fclose(fp);
162 return;
163 }
164
165 /* Get the start and end of the next command-line argument. */
166 static BOOL GetArg(WCHAR **pStart, WCHAR **pEnd)
167 {
168 BOOL bInQuotes = FALSE;
169 WCHAR *p = *pEnd;
170 p += wcsspn(p, L" \t");
171 if (!*p)
172 return FALSE;
173 *pStart = p;
174 do
175 {
176 if (!bInQuotes && (*p == L' ' || *p == L'\t'))
177 break;
178 bInQuotes ^= (*p++ == L'"');
179 } while (*p);
180 *pEnd = p;
181 return TRUE;
182 }
183
184 /* Remove starting and ending quotes from a string, if present */
185 static LPWSTR RemoveQuotes(LPWSTR str)
186 {
187 WCHAR *end;
188 if (*str == L'"' && *(end = str + wcslen(str) - 1) == L'"')
189 {
190 str++;
191 *end = L'\0';
192 }
193 return str;
194 }
195
196 int
197 wmain(VOID)
198 {
199 WCHAR *pArgStart;
200 WCHAR *pArgEnd;
201 HMODULE hKernel32;
202
203 setlocale(LC_ALL, "");
204
205 /* Get the full command line using GetCommandLine(). We can't just use argv,
206 * because then a parameter like "gotoroot=cd \" wouldn't be passed completely. */
207 pArgEnd = GetCommandLineW();
208 hKernel32 = LoadLibraryW(L"kernel32.dll");
209
210 /* Get function pointers */
211 pGetConsoleCommandHistoryW = (GetConsoleCommandHistoryW_t)GetProcAddress( hKernel32, "GetConsoleCommandHistoryW");
212 pGetConsoleCommandHistoryLengthW = (GetConsoleCommandHistoryLengthW_t)GetProcAddress( hKernel32, "GetConsoleCommandHistoryLengthW");
213 pSetConsoleNumberOfCommandsW = (SetConsoleNumberOfCommandsW_t)GetProcAddress( hKernel32, "SetConsoleNumberOfCommandsW");
214 pExpungeConsoleCommandHistoryW = (ExpungeConsoleCommandHistoryW_t)GetProcAddress( hKernel32, "ExpungeConsoleCommandHistoryW");
215
216 assert(pGetConsoleCommandHistoryW && pGetConsoleCommandHistoryLengthW &&
217 pSetConsoleNumberOfCommandsW && pExpungeConsoleCommandHistoryW);
218
219 /* Skip the application name */
220 GetArg(&pArgStart, &pArgEnd);
221
222 while (GetArg(&pArgStart, &pArgEnd))
223 {
224 /* NUL-terminate this argument to make processing easier */
225 WCHAR tmp = *pArgEnd;
226 *pArgEnd = L'\0';
227
228 if (!wcscmp(pArgStart, L"/?"))
229 {
230 LoadStringW(GetModuleHandle(NULL), IDS_HELP, szStringBuf, MAX_STRING);
231 wprintf(szStringBuf);
232 break;
233 }
234 else if (!_wcsnicmp(pArgStart, L"/EXENAME=", 9))
235 {
236 pszExeName = RemoveQuotes(pArgStart + 9);
237 }
238 else if (!wcsicmp(pArgStart, L"/H") ||
239 !wcsicmp(pArgStart, L"/HISTORY"))
240 {
241 PrintHistory();
242 }
243 else if (!_wcsnicmp(pArgStart, L"/LISTSIZE=", 10))
244 {
245 pSetConsoleNumberOfCommandsW(_wtoi(pArgStart + 10), pszExeName);
246 }
247 else if (!wcsicmp(pArgStart, L"/REINSTALL"))
248 {
249 pExpungeConsoleCommandHistoryW(pszExeName);
250 }
251 else if (!wcsicmp(pArgStart, L"/INSERT"))
252 {
253 SetInsert(ENABLE_INSERT_MODE);
254 }
255 else if (!wcsicmp(pArgStart, L"/OVERSTRIKE"))
256 {
257 SetInsert(0);
258 }
259 else if (!wcsicmp(pArgStart, L"/M") ||
260 !wcsicmp(pArgStart, L"/MACROS"))
261 {
262 PrintMacros(pszExeName, L"");
263 }
264 else if (!_wcsnicmp(pArgStart, L"/M:", 3) ||
265 !_wcsnicmp(pArgStart, L"/MACROS:", 8))
266 {
267 LPWSTR exe = RemoveQuotes(wcschr(pArgStart, L':') + 1);
268 if (!wcsicmp(exe, L"ALL"))
269 PrintAllMacros();
270 else
271 PrintMacros(exe, L"");
272 }
273 else if (!_wcsnicmp(pArgStart, L"/MACROFILE=", 11))
274 {
275 ReadFromFile(RemoveQuotes(pArgStart + 11));
276 }
277 else
278 {
279 /* This is the beginning of a macro definition. It includes
280 * the entire remainder of the line, so first put back the
281 * character that we replaced with NUL. */
282 *pArgEnd = tmp;
283 return SetMacro(pArgStart);
284 }
285
286 if (!tmp) break;
287 pArgEnd++;
288 }
289
290 return 0;
291 }