13 #define MAX_STRING 2000
14 WCHAR szStringBuf
[MAX_STRING
];
15 LPWSTR pszExeName
= L
"cmd.exe";
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
);
23 GetConsoleCommandHistoryW_t pGetConsoleCommandHistoryW
;
24 GetConsoleCommandHistoryLengthW_t pGetConsoleCommandHistoryLengthW
;
25 SetConsoleNumberOfCommandsW_t pSetConsoleNumberOfCommandsW
;
26 ExpungeConsoleCommandHistoryW_t pExpungeConsoleCommandHistoryW
;
28 static VOID
SetInsert(DWORD dwFlag
)
31 HANDLE hConsole
= GetStdHandle(STD_INPUT_HANDLE
);
32 GetConsoleMode(hConsole
, &dwMode
);
33 dwMode
|= ENABLE_EXTENDED_FLAGS
;
34 SetConsoleMode(hConsole
, (dwMode
& ~ENABLE_INSERT_MODE
) | dwFlag
);
37 static VOID
PrintHistory(VOID
)
39 DWORD Length
= pGetConsoleCommandHistoryLengthW(pszExeName
);
44 HistBuf
= HeapAlloc(GetProcessHeap(),
48 Hist
= (WCHAR
*)HistBuf
;
49 HistEnd
= (WCHAR
*)&HistBuf
[Length
];
51 if (pGetConsoleCommandHistoryW(Hist
, Length
, pszExeName
))
52 for (; Hist
< HistEnd
; Hist
+= wcslen(Hist
) + 1)
53 wprintf(L
"%s\n", Hist
);
55 HeapFree(GetProcessHeap(), 0, HistBuf
);
58 static INT
SetMacro(LPWSTR definition
)
60 WCHAR
*name
, *nameend
, *text
, temp
;
66 /* error if no '=' found */
67 if ((nameend
= wcschr(name
, L
'=')) != NULL
)
73 while (nameend
> name
&& nameend
[-1] == L
' ')
76 /* Split rest into name and substitute */
79 /* Don't allow spaces in the name, since such a macro would be unusable */
80 if (!wcschr(name
, L
' ') && AddConsoleAliasW(name
, text
, pszExeName
))
85 LoadStringW(GetModuleHandle(NULL
), IDS_INVALID_MACRO_DEF
, szStringBuf
, MAX_STRING
);
86 wprintf(szStringBuf
, definition
);
90 static VOID
PrintMacros(LPWSTR pszExeName
, LPWSTR Indent
)
92 DWORD Length
= GetConsoleAliasesLengthW(pszExeName
);
97 AliasBuf
= HeapAlloc(GetProcessHeap(),
99 Length
* sizeof(BYTE
));
100 if (!AliasBuf
) return;
101 Alias
= (WCHAR
*)AliasBuf
;
102 AliasEnd
= (WCHAR
*)&AliasBuf
[Length
];
104 if (GetConsoleAliasesW(Alias
, Length
* sizeof(BYTE
), pszExeName
))
105 for (; Alias
< AliasEnd
; Alias
+= wcslen(Alias
) + 1)
106 wprintf(L
"%s%s\n", Indent
, Alias
);
108 HeapFree(GetProcessHeap(), 0, AliasBuf
);
111 static VOID
PrintAllMacros(VOID
)
113 DWORD Length
= GetConsoleAliasExesLength();
118 ExeNameBuf
= HeapAlloc(GetProcessHeap(),
120 Length
* sizeof(BYTE
));
121 if (!ExeNameBuf
) return;
122 ExeName
= (WCHAR
*)ExeNameBuf
;
123 ExeNameEnd
= (WCHAR
*)&ExeNameBuf
[Length
];
125 if (GetConsoleAliasExesW(ExeName
, Length
* sizeof(BYTE
)))
127 for (; ExeName
< ExeNameEnd
; ExeName
+= wcslen(ExeName
) + 1)
129 wprintf(L
"[%s]\n", ExeName
);
130 PrintMacros(ExeName
, L
" ");
135 HeapFree(GetProcessHeap(), 0, ExeNameBuf
);
138 static VOID
ReadFromFile(LPWSTR param
)
141 WCHAR line
[MAX_PATH
];
143 fp
= _wfopen(param
, L
"r");
150 while ( fgetws(line
, MAX_PATH
, fp
) != NULL
)
152 /* Remove newline character */
153 WCHAR
*end
= &line
[wcslen(line
) - 1];
165 /* Get the start and end of the next command-line argument. */
166 static BOOL
GetArg(WCHAR
**pStart
, WCHAR
**pEnd
)
168 BOOL bInQuotes
= FALSE
;
170 p
+= wcsspn(p
, L
" \t");
176 if (!bInQuotes
&& (*p
== L
' ' || *p
== L
'\t'))
178 bInQuotes
^= (*p
++ == L
'"');
184 /* Remove starting and ending quotes from a string, if present */
185 static LPWSTR
RemoveQuotes(LPWSTR str
)
188 if (*str
== L
'"' && *(end
= str
+ wcslen(str
) - 1) == L
'"')
203 setlocale(LC_ALL
, "");
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");
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");
216 assert(pGetConsoleCommandHistoryW
&& pGetConsoleCommandHistoryLengthW
&&
217 pSetConsoleNumberOfCommandsW
&& pExpungeConsoleCommandHistoryW
);
219 /* Skip the application name */
220 GetArg(&pArgStart
, &pArgEnd
);
222 while (GetArg(&pArgStart
, &pArgEnd
))
224 /* NUL-terminate this argument to make processing easier */
225 WCHAR tmp
= *pArgEnd
;
228 if (!wcscmp(pArgStart
, L
"/?"))
230 LoadStringW(GetModuleHandle(NULL
), IDS_HELP
, szStringBuf
, MAX_STRING
);
231 wprintf(szStringBuf
);
234 else if (!_wcsnicmp(pArgStart
, L
"/EXENAME=", 9))
236 pszExeName
= RemoveQuotes(pArgStart
+ 9);
238 else if (!wcsicmp(pArgStart
, L
"/H") ||
239 !wcsicmp(pArgStart
, L
"/HISTORY"))
243 else if (!_wcsnicmp(pArgStart
, L
"/LISTSIZE=", 10))
245 pSetConsoleNumberOfCommandsW(_wtoi(pArgStart
+ 10), pszExeName
);
247 else if (!wcsicmp(pArgStart
, L
"/REINSTALL"))
249 pExpungeConsoleCommandHistoryW(pszExeName
);
251 else if (!wcsicmp(pArgStart
, L
"/INSERT"))
253 SetInsert(ENABLE_INSERT_MODE
);
255 else if (!wcsicmp(pArgStart
, L
"/OVERSTRIKE"))
259 else if (!wcsicmp(pArgStart
, L
"/M") ||
260 !wcsicmp(pArgStart
, L
"/MACROS"))
262 PrintMacros(pszExeName
, L
"");
264 else if (!_wcsnicmp(pArgStart
, L
"/M:", 3) ||
265 !_wcsnicmp(pArgStart
, L
"/MACROS:", 8))
267 LPWSTR exe
= RemoveQuotes(wcschr(pArgStart
, L
':') + 1);
268 if (!wcsicmp(exe
, L
"ALL"))
271 PrintMacros(exe
, L
"");
273 else if (!_wcsnicmp(pArgStart
, L
"/MACROFILE=", 11))
275 ReadFromFile(RemoveQuotes(pArgStart
+ 11));
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. */
283 return SetMacro(pArgStart
);