* FILE: win32ss/user/winsrv/consrv/lineinput.c
* PURPOSE: Console line input functions
* PROGRAMMERS: Jeffrey Morlan
- *
- * NOTE: It's something frontend-related... (--> read my mind... ;) )
*/
/* INCLUDES *******************************************************************/
UINT Position;
UINT MaxEntries;
UINT NumEntries;
- PUNICODE_STRING Entries;
UNICODE_STRING ExeName;
+ PUNICODE_STRING Entries;
} HISTORY_BUFFER, *PHISTORY_BUFFER;
+BOOLEAN
+ConvertInputAnsiToUnicode(PCONSOLE Console,
+ PVOID Source,
+ USHORT SourceLength,
+ // BOOLEAN IsUnicode,
+ PWCHAR* Target,
+ PUSHORT TargetLength);
+BOOLEAN
+ConvertInputUnicodeToAnsi(PCONSOLE Console,
+ PVOID Source,
+ USHORT SourceLength,
+ // BOOLEAN IsAnsi,
+ PCHAR/* * */ Target,
+ /*P*/USHORT TargetLength);
+
+
/* PRIVATE FUNCTIONS **********************************************************/
static PHISTORY_BUFFER
-HistoryCurrentBuffer(PCONSOLE Console)
+HistoryCurrentBuffer(PCONSOLE Console,
+ PUNICODE_STRING ExeName)
{
- /* TODO: use actual EXE name sent from process that called ReadConsole */
- UNICODE_STRING ExeName = { 14, 14, L"cmd.exe" };
PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
PHISTORY_BUFFER Hist;
for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
{
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
- if (RtlEqualUnicodeString(&ExeName, &Hist->ExeName, FALSE))
+ if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE))
return Hist;
}
/* Couldn't find the buffer, create a new one */
- Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName.Length);
+ Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length);
if (!Hist) return NULL;
Hist->MaxEntries = Console->HistoryBufferSize;
Hist->NumEntries = 0;
ConsoleFreeHeap(Hist);
return NULL;
}
- Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName.Length;
+ Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length;
Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
- memcpy(Hist->ExeName.Buffer, ExeName.Buffer, ExeName.Length);
+ memcpy(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length);
InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
return Hist;
}
static VOID
-HistoryAddEntry(PCONSOLE Console)
+HistoryAddEntry(PCONSOLE Console,
+ PUNICODE_STRING ExeName)
{
UNICODE_STRING NewEntry;
- PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+ PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
INT i;
if (!Hist) return;
}
static VOID
-HistoryGetCurrentEntry(PCONSOLE Console, PUNICODE_STRING Entry)
+HistoryGetCurrentEntry(PCONSOLE Console,
+ PUNICODE_STRING ExeName,
+ PUNICODE_STRING Entry)
{
- PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+ PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
if (!Hist || Hist->NumEntries == 0)
Entry->Length = 0;
}
static PHISTORY_BUFFER
-HistoryFindBuffer(PCONSOLE Console, PUNICODE_STRING ExeName)
+HistoryFindBuffer(PCONSOLE Console,
+ PVOID ExeName,
+ USHORT ExeLength,
+ BOOLEAN UnicodeExe)
{
- PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
+ UNICODE_STRING ExeNameU;
+
+ PLIST_ENTRY Entry;
+ PHISTORY_BUFFER Hist = NULL;
+
+ if (ExeName == NULL) return NULL;
+
+ if (UnicodeExe)
+ {
+ ExeNameU.Buffer = ExeName;
+ /* Length is in bytes */
+ ExeNameU.MaximumLength = ExeLength;
+ }
+ else
+ {
+ if (!ConvertInputAnsiToUnicode(Console,
+ ExeName, ExeLength,
+ &ExeNameU.Buffer, &ExeNameU.MaximumLength))
+ {
+ return NULL;
+ }
+ }
+ ExeNameU.Length = ExeNameU.MaximumLength;
+
+ Entry = Console->HistoryBuffers.Flink;
while (Entry != &Console->HistoryBuffers)
{
+ Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
+
/* For the history APIs, the caller is allowed to give only part of the name */
- PHISTORY_BUFFER Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
- if (RtlPrefixUnicodeString(ExeName, &Hist->ExeName, TRUE))
+ if (RtlPrefixUnicodeString(&ExeNameU, &Hist->ExeName, TRUE))
+ {
+ if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
return Hist;
+ }
+
Entry = Entry->Flink;
}
+
+ if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
return NULL;
}
}
static VOID
-LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Insertion)
+LineInputEdit(PCONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHAR Insertion)
{
PTEXTMODE_SCREEN_BUFFER ActiveBuffer;
UINT Pos = Console->LinePos;
}
static VOID
-LineInputRecallHistory(PCONSOLE Console, INT Offset)
+LineInputRecallHistory(PCONSOLE Console,
+ PUNICODE_STRING ExeName,
+ INT Offset)
{
- PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console);
+ PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
UINT Position = 0;
if (!Hist || Hist->NumEntries == 0) return;
}
VOID
-LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
+LineInputKeyDown(PCONSOLE Console,
+ PUNICODE_STRING ExeName,
+ KEY_EVENT_RECORD *KeyEvent)
{
UINT Pos = Console->LinePos;
PHISTORY_BUFFER Hist;
else
{
/* Recall one character (but don't overwrite current line) */
- HistoryGetCurrentEntry(Console, &Entry);
+ HistoryGetCurrentEntry(Console, ExeName, &Entry);
if (Pos < Console->LineSize)
LineInputSetPos(Console, Pos + 1);
else if (Pos * sizeof(WCHAR) < Entry.Length)
return;
case VK_PRIOR:
/* Recall first history entry */
- LineInputRecallHistory(Console, -((WORD)-1));
+ LineInputRecallHistory(Console, ExeName, -((WORD)-1));
return;
case VK_NEXT:
/* Recall last history entry */
- LineInputRecallHistory(Console, +((WORD)-1));
+ LineInputRecallHistory(Console, ExeName, +((WORD)-1));
return;
case VK_UP:
case VK_F5:
/* Recall previous history entry. On first time, actually recall the
* current (usually last) entry; on subsequent times go back. */
- LineInputRecallHistory(Console, Console->LineUpPressed ? -1 : 0);
+ LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0);
Console->LineUpPressed = TRUE;
return;
case VK_DOWN:
/* Recall next history entry */
- LineInputRecallHistory(Console, +1);
+ LineInputRecallHistory(Console, ExeName, +1);
return;
case VK_F3:
/* Recall remainder of current history entry */
- HistoryGetCurrentEntry(Console, &Entry);
+ HistoryGetCurrentEntry(Console, ExeName, &Entry);
if (Pos * sizeof(WCHAR) < Entry.Length)
{
UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos);
break;
case VK_F7:
if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
- HistoryDeleteBuffer(HistoryCurrentBuffer(Console));
+ HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName));
return;
case VK_F8:
/* Search for history entries starting with input. */
- Hist = HistoryCurrentBuffer(Console);
+ Hist = HistoryCurrentBuffer(Console, ExeName);
if (!Hist || Hist->NumEntries == 0) return;
/* Like Up/F5, on first time start from current (usually last) entry,
}
else if (KeyEvent->uChar.UnicodeChar == L'\r')
{
- HistoryAddEntry(Console);
+ HistoryAddEntry(Console, ExeName);
/* TODO: Expand aliases */
NTSTATUS Status;
PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest;
PCONSOLE Console;
+ ULONG BytesWritten = 0;
PHISTORY_BUFFER Hist;
- UNICODE_STRING ExeName;
- PBYTE Buffer = (PBYTE)GetCommandHistoryRequest->History;
- ULONG BufferSize = GetCommandHistoryRequest->HistoryLength;
- UINT i;
+
+ DPRINT1("SrvGetConsoleCommandHistory entered\n");
if ( !CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&GetCommandHistoryRequest->History,
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- // FIXME: convert to UNICODE if Unicode(2) == FALSE
- ExeName.Length = ExeName.MaximumLength = GetCommandHistoryRequest->ExeLength;
- ExeName.Buffer = GetCommandHistoryRequest->ExeName;
-
- Hist = HistoryFindBuffer(Console, &ExeName);
+ Hist = HistoryFindBuffer(Console,
+ GetCommandHistoryRequest->ExeName,
+ GetCommandHistoryRequest->ExeLength,
+ GetCommandHistoryRequest->Unicode2);
if (Hist)
{
+ UINT i;
+
+ LPSTR TargetBufferA;
+ LPWSTR TargetBufferW;
+ ULONG BufferSize = GetCommandHistoryRequest->HistoryLength;
+
+ UINT Offset = 0;
+ UINT SourceLength;
+
+ if (GetCommandHistoryRequest->Unicode)
+ {
+ TargetBufferW = GetCommandHistoryRequest->History;
+ BufferSize /= sizeof(WCHAR);
+ }
+ else
+ {
+ TargetBufferA = GetCommandHistoryRequest->History;
+ }
+
for (i = 0; i < Hist->NumEntries; i++)
{
- if (BufferSize < (Hist->Entries[i].Length + sizeof(WCHAR)))
+ SourceLength = Hist->Entries[i].Length / sizeof(WCHAR);
+ if (Offset + SourceLength + 1 > BufferSize)
{
Status = STATUS_BUFFER_OVERFLOW;
break;
}
- // FIXME: convert to UNICODE if Unicode == FALSE
- memcpy(Buffer, Hist->Entries[i].Buffer, Hist->Entries[i].Length);
- Buffer += Hist->Entries[i].Length;
- *(PWCHAR)Buffer = L'\0';
- Buffer += sizeof(WCHAR);
-
- // {
- // WideCharToMultiByte(CP_ACP, 0,
- // GetCommandHistoryRequest->History,
- // GetCommandHistoryRequest->HistoryLength / sizeof(WCHAR),
- // lpHistory,
- // cbHistory,
- // NULL, NULL);
- // }
+ if (GetCommandHistoryRequest->Unicode)
+ {
+ RtlCopyMemory(&TargetBufferW[Offset], Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR));
+ Offset += SourceLength;
+ TargetBufferW[Offset++] = L'\0';
+ }
+ else
+ {
+ ConvertInputUnicodeToAnsi(Console,
+ Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR),
+ &TargetBufferA[Offset], SourceLength);
+ Offset += SourceLength;
+ TargetBufferA[Offset++] = '\0';
+ }
}
+
+ if (GetCommandHistoryRequest->Unicode)
+ BytesWritten = Offset * sizeof(WCHAR);
+ else
+ BytesWritten = Offset;
}
- // FIXME: convert to UNICODE if Unicode == FALSE
- GetCommandHistoryRequest->HistoryLength = Buffer - (PBYTE)GetCommandHistoryRequest->History;
+
+ // GetCommandHistoryRequest->HistoryLength = TargetBuffer - (PBYTE)GetCommandHistoryRequest->History;
+ GetCommandHistoryRequest->HistoryLength = BytesWritten;
ConSrvReleaseConsole(Console, TRUE);
return Status;
PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryLengthRequest;
PCONSOLE Console;
PHISTORY_BUFFER Hist;
- UNICODE_STRING ExeName;
ULONG Length = 0;
UINT i;
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- // FIXME: convert to UNICODE if Unicode(2) == FALSE
- ExeName.Length = ExeName.MaximumLength = GetCommandHistoryLengthRequest->ExeLength;
- ExeName.Buffer = GetCommandHistoryLengthRequest->ExeName;
-
- Hist = HistoryFindBuffer(Console, &ExeName);
+ Hist = HistoryFindBuffer(Console,
+ GetCommandHistoryLengthRequest->ExeName,
+ GetCommandHistoryLengthRequest->ExeLength,
+ GetCommandHistoryLengthRequest->Unicode2);
if (Hist)
{
for (i = 0; i < Hist->NumEntries; i++)
- Length += Hist->Entries[i].Length + sizeof(WCHAR);
+ Length += Hist->Entries[i].Length + sizeof(WCHAR); // Each entry is returned NULL-terminated
}
- GetCommandHistoryLengthRequest->HistoryLength = Length;
-
/*
* Quick and dirty way of getting the number of bytes of the
* corresponding ANSI string from the one in UNICODE.
*/
if (!GetCommandHistoryLengthRequest->Unicode)
- GetCommandHistoryLengthRequest->HistoryLength /= sizeof(WCHAR);
+ Length /= sizeof(WCHAR);
+
+ GetCommandHistoryLengthRequest->HistoryLength = Length;
ConSrvReleaseConsole(Console, TRUE);
return Status;
PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ExpungeCommandHistoryRequest;
PCONSOLE Console;
PHISTORY_BUFFER Hist;
- UNICODE_STRING ExeName;
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&ExpungeCommandHistoryRequest->ExeName,
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- // FIXME: convert to UNICODE if Unicode(2) == FALSE
- ExeName.Length = ExeName.MaximumLength = ExpungeCommandHistoryRequest->ExeLength;
- ExeName.Buffer = ExpungeCommandHistoryRequest->ExeName;
-
- Hist = HistoryFindBuffer(Console, &ExeName);
+ Hist = HistoryFindBuffer(Console,
+ ExpungeCommandHistoryRequest->ExeName,
+ ExpungeCommandHistoryRequest->ExeLength,
+ ExpungeCommandHistoryRequest->Unicode2);
HistoryDeleteBuffer(Hist);
ConSrvReleaseConsole(Console, TRUE);
PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryNumberCommandsRequest;
PCONSOLE Console;
PHISTORY_BUFFER Hist;
- UINT MaxEntries = SetHistoryNumberCommandsRequest->NumCommands;
- UNICODE_STRING ExeName;
- PUNICODE_STRING OldEntryList, NewEntryList;
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&SetHistoryNumberCommandsRequest->ExeName,
Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (!NT_SUCCESS(Status)) return Status;
- // FIXME: convert to UNICODE if Unicode(2) == FALSE
- ExeName.Length = ExeName.MaximumLength = SetHistoryNumberCommandsRequest->ExeLength;
- ExeName.Buffer = SetHistoryNumberCommandsRequest->ExeName;
-
- Hist = HistoryFindBuffer(Console, &ExeName);
+ Hist = HistoryFindBuffer(Console,
+ SetHistoryNumberCommandsRequest->ExeName,
+ SetHistoryNumberCommandsRequest->ExeLength,
+ SetHistoryNumberCommandsRequest->Unicode2);
if (Hist)
{
- OldEntryList = Hist->Entries;
- NewEntryList = ConsoleAllocHeap(0, MaxEntries * sizeof(UNICODE_STRING));
+ UINT MaxEntries = SetHistoryNumberCommandsRequest->NumCommands;
+ PUNICODE_STRING OldEntryList = Hist->Entries;
+ PUNICODE_STRING NewEntryList = ConsoleAllocHeap(0, MaxEntries * sizeof(UNICODE_STRING));
if (!NewEntryList)
{
Status = STATUS_NO_MEMORY;
CSR_API(SrvGetConsoleHistory)
{
+#if 0 // Vista+
PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest;
PCONSOLE Console;
NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
ConSrvReleaseConsole(Console, TRUE);
}
return Status;
+#else
+ DPRINT1("%s not yet implemented\n", __FUNCTION__);
+ return STATUS_NOT_IMPLEMENTED;
+#endif
}
CSR_API(SrvSetConsoleHistory)
{
+#if 0 // Vista+
PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest;
PCONSOLE Console;
NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
ConSrvReleaseConsole(Console, TRUE);
}
return Status;
+#else
+ DPRINT1("%s not yet implemented\n", __FUNCTION__);
+ return STATUS_NOT_IMPLEMENTED;
+#endif
}
CSR_API(SrvSetConsoleCommandHistoryMode)