Skip to content

Commit 09c64b5

Browse files
HBeluscaJoachimHenze
authored andcommitted
[0.4.9] cherry-pick [CMD] Improve the situations when the console title can be changed.
- Introduce two small helpers to change and restore the console title. - Console title can change even when internal commands are executed. - Note that when commands are run from within batch files, title is unchanged. - When "cmd.exe /c command" is run, the console title is unchanged; however when "cmd.exe /k command" is run, the console title changes. (cherry picked from commit a165999) picked to fix CORE-14648 which was the last puzzle-piece to build ros on ros
1 parent 9a6be75 commit 09c64b5

File tree

2 files changed

+70
-27
lines changed

2 files changed

+70
-27
lines changed

base/shell/cmd/cmd.c

Lines changed: 68 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -149,21 +149,23 @@ typedef NTSTATUS (WINAPI *NtQueryInformationProcessProc)(HANDLE, PROCESSINFOCLAS
149149
PVOID, ULONG, PULONG);
150150
typedef NTSTATUS (WINAPI *NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, ULONG, PULONG);
151151

152-
BOOL bExit = FALSE; /* indicates EXIT was typed */
153-
BOOL bCanExit = TRUE; /* indicates if this shell is exitable */
152+
BOOL bExit = FALSE; /* Indicates EXIT was typed */
153+
BOOL bCanExit = TRUE; /* Indicates if this shell is exitable */
154154
BOOL bCtrlBreak = FALSE; /* Ctrl-Break or Ctrl-C hit */
155155
BOOL bIgnoreEcho = FALSE; /* Set this to TRUE to prevent a newline, when executing a command */
156-
static BOOL bWaitForCommand = FALSE; /* When we are executing something passed on the commandline after /c or /k */
156+
static BOOL fSingleCommand = 0; /* When we are executing something passed on the command line after /C or /K */
157157
INT nErrorLevel = 0; /* Errorlevel of last launched external program */
158158
CRITICAL_SECTION ChildProcessRunningLock;
159159
BOOL bDisableBatchEcho = FALSE;
160160
BOOL bEnableExtensions = TRUE;
161161
BOOL bDelayedExpansion = FALSE;
162-
BOOL bTitleSet = FALSE;
163162
DWORD dwChildProcessId = 0;
164163
LPTSTR lpOriginalEnvironment;
165164
HANDLE CMD_ModuleHandle;
166165

166+
BOOL bTitleSet = FALSE; /* Indicates whether the console title has been changed and needs to be restored later */
167+
TCHAR szCurTitle[MAX_PATH];
168+
167169
static NtQueryInformationProcessProc NtQueryInformationProcessPtr = NULL;
168170
static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr = NULL;
169171

@@ -302,23 +304,51 @@ HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
302304
}
303305

304306

307+
static VOID
308+
SetConTitle(LPCTSTR pszTitle)
309+
{
310+
TCHAR szNewTitle[MAX_PATH];
311+
312+
if (!pszTitle)
313+
return;
314+
315+
/* Don't do anything if we run inside a batch file, or we are just running a single command */
316+
if (bc || (fSingleCommand == 1))
317+
return;
318+
319+
/* Save the original console title and build a new one */
320+
GetConsoleTitle(szCurTitle, ARRAYSIZE(szCurTitle));
321+
StringCchPrintf(szNewTitle, ARRAYSIZE(szNewTitle),
322+
_T("%s - %s"), szCurTitle, pszTitle);
323+
bTitleSet = TRUE;
324+
ConSetTitle(szNewTitle);
325+
}
326+
327+
static VOID
328+
ResetConTitle(VOID)
329+
{
330+
/* Restore the original console title */
331+
if (!bc && bTitleSet)
332+
{
333+
ConSetTitle(szCurTitle);
334+
bTitleSet = FALSE;
335+
}
336+
}
305337

306338
/*
307-
* This command (in first) was not found in the command table
339+
* This command (in First) was not found in the command table
308340
*
309-
* Full - buffer to hold whole command line
341+
* Full - output buffer to hold whole command line
310342
* First - first word on command line
311343
* Rest - rest of command line
312344
*/
313345
static INT
314346
Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
315347
{
316-
TCHAR szFullName[MAX_PATH];
317348
TCHAR *first, *rest, *dot;
318-
TCHAR szWindowTitle[MAX_PATH];
319-
TCHAR szNewTitle[MAX_PATH*2];
320349
DWORD dwExitCode = 0;
321350
TCHAR *FirstEnd;
351+
TCHAR szFullName[MAX_PATH];
322352
TCHAR szFullCmdLine[CMDLINE_LENGTH];
323353

324354
TRACE ("Execute: \'%s\' \'%s\'\n", debugstr_aw(First), debugstr_aw(Rest));
@@ -344,10 +374,10 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
344374
}
345375

346376
/* Copy the new first/rest into the buffer */
347-
first = Full;
348377
rest = &Full[FirstEnd - First + 1];
349378
_tcscpy(rest, FirstEnd);
350379
_tcscat(rest, Rest);
380+
first = Full;
351381
*FirstEnd = _T('\0');
352382
_tcscpy(first, First);
353383

@@ -356,8 +386,8 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
356386
{
357387
BOOL working = TRUE;
358388
if (!SetCurrentDirectory(first))
359-
/* Guess they changed disc or something, handle that gracefully and get to root */
360389
{
390+
/* Guess they changed disc or something, handle that gracefully and get to root */
361391
TCHAR str[4];
362392
str[0]=first[0];
363393
str[1]=_T(':');
@@ -379,19 +409,19 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
379409
return 1;
380410
}
381411

382-
/* Save the original console title and build a new one */
383-
GetConsoleTitle(szWindowTitle, ARRAYSIZE(szWindowTitle));
384-
bTitleSet = FALSE;
385-
StringCchPrintf(szNewTitle, ARRAYSIZE(szNewTitle),
386-
_T("%s - %s%s"), szWindowTitle, First, Rest);
387-
ConSetTitle(szNewTitle);
412+
/* Set the new console title */
413+
FirstEnd = first + (FirstEnd - First); /* Point to the separating NULL in the full built string */
414+
*FirstEnd = _T(' ');
415+
SetConTitle(Full);
388416

389417
/* check if this is a .BAT or .CMD file */
390418
dot = _tcsrchr (szFullName, _T('.'));
391419
if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
392420
{
393421
while (*rest == _T(' '))
394422
rest++;
423+
424+
*FirstEnd = _T('\0');
395425
TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
396426
dwExitCode = Batch(szFullName, first, rest, Cmd);
397427
}
@@ -402,7 +432,7 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
402432
STARTUPINFO stui;
403433

404434
/* build command line for CreateProcess(): FullName + " " + rest */
405-
BOOL quoted = !!_tcschr(First, ' ');
435+
BOOL quoted = !!_tcschr(First, _T(' '));
406436
_tcscpy(szFullCmdLine, quoted ? _T("\"") : _T(""));
407437
_tcsncat(szFullCmdLine, First, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
408438
_tcsncat(szFullCmdLine, quoted ? _T("\"") : _T(""), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
@@ -416,8 +446,9 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
416446
TRACE ("[EXEC: %s]\n", debugstr_aw(szFullCmdLine));
417447

418448
/* fill startup info */
419-
memset (&stui, 0, sizeof (STARTUPINFO));
420-
stui.cb = sizeof (STARTUPINFO);
449+
memset(&stui, 0, sizeof(stui));
450+
stui.cb = sizeof(stui);
451+
stui.lpTitle = Full;
421452
stui.dwFlags = STARTF_USESHOWWINDOW;
422453
stui.wShowWindow = SW_SHOWDEFAULT;
423454

@@ -448,9 +479,11 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
448479
SW_SHOWNORMAL);
449480
}
450481

482+
*FirstEnd = _T('\0');
483+
451484
if (prci.hProcess != NULL)
452485
{
453-
if (bc != NULL || bWaitForCommand || IsConsoleProcess(prci.hProcess))
486+
if (bc != NULL || fSingleCommand != 0 || IsConsoleProcess(prci.hProcess))
454487
{
455488
/* when processing a batch file or starting console processes: execute synchronously */
456489
EnterCriticalSection(&ChildProcessRunningLock);
@@ -501,8 +534,7 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
501534
}
502535

503536
/* Restore the original console title */
504-
if (!bTitleSet)
505-
ConSetTitle(szWindowTitle);
537+
ResetConTitle();
506538

507539
return dwExitCode;
508540
}
@@ -568,9 +600,19 @@ DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
568600

569601
/* Skip over whitespace to rest of line, exclude 'echo' command */
570602
if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
603+
{
571604
while (_istspace(*param))
572605
param++;
606+
}
607+
608+
/* Set the new console title */
609+
SetConTitle(com);
610+
573611
ret = cmdptr->func(param);
612+
613+
/* Restore the original console title */
614+
ResetConTitle();
615+
574616
cmd_free(com);
575617
return ret;
576618
}
@@ -1896,6 +1938,7 @@ Initialize(VOID)
18961938
else if (option == _T('C') || option == _T('K') || option == _T('R'))
18971939
{
18981940
/* Remainder of command line is a command to be run */
1941+
fSingleCommand = ((option == _T('K')) << 1) | 1;
18991942
break;
19001943
}
19011944
else if (option == _T('D'))
@@ -1983,14 +2026,13 @@ Initialize(VOID)
19832026
{
19842027
/* Do the /C or /K command */
19852028
GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
1986-
bWaitForCommand = TRUE;
19872029
/* nExitCode = */ ParseCommandLine(commandline);
1988-
bWaitForCommand = FALSE;
1989-
if (option != _T('K'))
2030+
if (fSingleCommand == 1)
19902031
{
19912032
// nErrorLevel = nExitCode;
19922033
bExit = TRUE;
19932034
}
2035+
fSingleCommand = 0;
19942036
}
19952037
}
19962038

base/shell/cmd/title.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ INT cmd_title(LPTSTR param)
2828
return 0;
2929
}
3030

31-
bTitleSet = TRUE;
31+
/* Set the new console title, and tell CMD to not reset it */
32+
bTitleSet = FALSE;
3233
return ConSetTitle(param);
3334
}
3435

0 commit comments

Comments
 (0)