2 * LICENSE: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/lineinput.c
5 * PURPOSE: Console line input functions
6 * PROGRAMMERS: Jeffrey Morlan
8 * NOTE: It's something frontend-related... (--> read my mind... ;) )
11 /* INCLUDES *******************************************************************/
18 typedef struct _HISTORY_BUFFER
24 PUNICODE_STRING Entries
;
25 UNICODE_STRING ExeName
;
26 } HISTORY_BUFFER
, *PHISTORY_BUFFER
;
29 /* PRIVATE FUNCTIONS **********************************************************/
31 static PHISTORY_BUFFER
32 HistoryCurrentBuffer(PCONSOLE Console
)
34 /* TODO: use actual EXE name sent from process that called ReadConsole */
35 UNICODE_STRING ExeName
= { 14, 14, L
"cmd.exe" };
36 PLIST_ENTRY Entry
= Console
->HistoryBuffers
.Flink
;
39 for (; Entry
!= &Console
->HistoryBuffers
; Entry
= Entry
->Flink
)
41 Hist
= CONTAINING_RECORD(Entry
, HISTORY_BUFFER
, ListEntry
);
42 if (RtlEqualUnicodeString(&ExeName
, &Hist
->ExeName
, FALSE
))
46 /* Couldn't find the buffer, create a new one */
47 Hist
= ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER
) + ExeName
.Length
);
48 if (!Hist
) return NULL
;
49 Hist
->MaxEntries
= Console
->HistoryBufferSize
;
51 Hist
->Entries
= ConsoleAllocHeap(0, Hist
->MaxEntries
* sizeof(UNICODE_STRING
));
54 ConsoleFreeHeap(Hist
);
57 Hist
->ExeName
.Length
= Hist
->ExeName
.MaximumLength
= ExeName
.Length
;
58 Hist
->ExeName
.Buffer
= (PWCHAR
)(Hist
+ 1);
59 memcpy(Hist
->ExeName
.Buffer
, ExeName
.Buffer
, ExeName
.Length
);
60 InsertHeadList(&Console
->HistoryBuffers
, &Hist
->ListEntry
);
65 HistoryAddEntry(PCONSOLE Console
)
67 UNICODE_STRING NewEntry
;
68 PHISTORY_BUFFER Hist
= HistoryCurrentBuffer(Console
);
73 NewEntry
.Length
= NewEntry
.MaximumLength
= Console
->LineSize
* sizeof(WCHAR
);
74 NewEntry
.Buffer
= Console
->LineBuffer
;
76 /* Don't add blank or duplicate entries */
77 if (NewEntry
.Length
== 0 || Hist
->MaxEntries
== 0 ||
78 (Hist
->NumEntries
> 0 &&
79 RtlEqualUnicodeString(&Hist
->Entries
[Hist
->NumEntries
- 1], &NewEntry
, FALSE
)))
84 if (Console
->HistoryNoDup
)
86 /* Check if this line has been entered before */
87 for (i
= Hist
->NumEntries
- 1; i
>= 0; i
--)
89 if (RtlEqualUnicodeString(&Hist
->Entries
[i
], &NewEntry
, FALSE
))
91 /* Just rotate the list to bring this entry to the end */
92 NewEntry
= Hist
->Entries
[i
];
93 memmove(&Hist
->Entries
[i
], &Hist
->Entries
[i
+ 1],
94 (Hist
->NumEntries
- (i
+ 1)) * sizeof(UNICODE_STRING
));
95 Hist
->Entries
[Hist
->NumEntries
- 1] = NewEntry
;
96 Hist
->Position
= Hist
->NumEntries
- 1;
102 if (Hist
->NumEntries
== Hist
->MaxEntries
)
104 /* List is full, remove oldest entry */
105 RtlFreeUnicodeString(&Hist
->Entries
[0]);
106 memmove(&Hist
->Entries
[0], &Hist
->Entries
[1],
107 --Hist
->NumEntries
* sizeof(UNICODE_STRING
));
110 if (NT_SUCCESS(RtlDuplicateUnicodeString(0, &NewEntry
, &Hist
->Entries
[Hist
->NumEntries
])))
112 Hist
->Position
= Hist
->NumEntries
- 1;
116 HistoryGetCurrentEntry(PCONSOLE Console
, PUNICODE_STRING Entry
)
118 PHISTORY_BUFFER Hist
= HistoryCurrentBuffer(Console
);
120 if (!Hist
|| Hist
->NumEntries
== 0)
123 *Entry
= Hist
->Entries
[Hist
->Position
];
126 static PHISTORY_BUFFER
127 HistoryFindBuffer(PCONSOLE Console
, PUNICODE_STRING ExeName
)
129 PLIST_ENTRY Entry
= Console
->HistoryBuffers
.Flink
;
130 while (Entry
!= &Console
->HistoryBuffers
)
132 /* For the history APIs, the caller is allowed to give only part of the name */
133 PHISTORY_BUFFER Hist
= CONTAINING_RECORD(Entry
, HISTORY_BUFFER
, ListEntry
);
134 if (RtlPrefixUnicodeString(ExeName
, &Hist
->ExeName
, TRUE
))
136 Entry
= Entry
->Flink
;
142 HistoryDeleteBuffer(PHISTORY_BUFFER Hist
)
146 while (Hist
->NumEntries
!= 0)
147 RtlFreeUnicodeString(&Hist
->Entries
[--Hist
->NumEntries
]);
149 ConsoleFreeHeap(Hist
->Entries
);
150 RemoveEntryList(&Hist
->ListEntry
);
151 ConsoleFreeHeap(Hist
);
155 HistoryDeleteBuffers(PCONSOLE Console
)
157 PLIST_ENTRY CurrentEntry
;
158 PHISTORY_BUFFER HistoryBuffer
;
160 while (!IsListEmpty(&Console
->HistoryBuffers
))
162 CurrentEntry
= RemoveHeadList(&Console
->HistoryBuffers
);
163 HistoryBuffer
= CONTAINING_RECORD(CurrentEntry
, HISTORY_BUFFER
, ListEntry
);
164 HistoryDeleteBuffer(HistoryBuffer
);
169 LineInputSetPos(PCONSOLE Console
, UINT Pos
)
171 if (Pos
!= Console
->LinePos
&& Console
->InputBuffer
.Mode
& ENABLE_ECHO_INPUT
)
173 PCONSOLE_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
174 SHORT OldCursorX
= Buffer
->CursorPosition
.X
;
175 SHORT OldCursorY
= Buffer
->CursorPosition
.Y
;
176 INT XY
= OldCursorY
* Buffer
->ScreenBufferSize
.X
+ OldCursorX
;
178 XY
+= (Pos
- Console
->LinePos
);
181 else if (XY
>= Buffer
->ScreenBufferSize
.Y
* Buffer
->ScreenBufferSize
.X
)
182 XY
= Buffer
->ScreenBufferSize
.Y
* Buffer
->ScreenBufferSize
.X
- 1;
184 Buffer
->CursorPosition
.X
= XY
% Buffer
->ScreenBufferSize
.X
;
185 Buffer
->CursorPosition
.Y
= XY
/ Buffer
->ScreenBufferSize
.X
;
186 TermSetScreenInfo(Console
, Buffer
, OldCursorX
, OldCursorY
);
189 Console
->LinePos
= Pos
;
193 LineInputEdit(PCONSOLE Console
, UINT NumToDelete
, UINT NumToInsert
, WCHAR
*Insertion
)
195 PTEXTMODE_SCREEN_BUFFER ActiveBuffer
;
196 UINT Pos
= Console
->LinePos
;
197 UINT NewSize
= Console
->LineSize
- NumToDelete
+ NumToInsert
;
200 if (GetType(Console
->ActiveBuffer
) != TEXTMODE_BUFFER
) return;
201 ActiveBuffer
= (PTEXTMODE_SCREEN_BUFFER
)Console
->ActiveBuffer
;
203 /* Make sure there's always enough room for ending \r\n */
204 if (NewSize
+ 2 > Console
->LineMaxSize
)
207 memmove(&Console
->LineBuffer
[Pos
+ NumToInsert
],
208 &Console
->LineBuffer
[Pos
+ NumToDelete
],
209 (Console
->LineSize
- (Pos
+ NumToDelete
)) * sizeof(WCHAR
));
210 memcpy(&Console
->LineBuffer
[Pos
], Insertion
, NumToInsert
* sizeof(WCHAR
));
212 if (Console
->InputBuffer
.Mode
& ENABLE_ECHO_INPUT
)
214 for (i
= Pos
; i
< NewSize
; i
++)
216 ConioWriteConsole(Console
, ActiveBuffer
, &Console
->LineBuffer
[i
], 1, TRUE
);
218 for (; i
< Console
->LineSize
; i
++)
220 ConioWriteConsole(Console
, ActiveBuffer
, L
" ", 1, TRUE
);
222 Console
->LinePos
= i
;
225 Console
->LineSize
= NewSize
;
226 LineInputSetPos(Console
, Pos
+ NumToInsert
);
230 LineInputRecallHistory(PCONSOLE Console
, INT Offset
)
232 PHISTORY_BUFFER Hist
= HistoryCurrentBuffer(Console
);
235 if (!Hist
|| Hist
->NumEntries
== 0) return;
237 Position
= Hist
->Position
+ Offset
;
238 Position
= min(max(Position
, 0), Hist
->NumEntries
- 1);
239 Hist
->Position
= Position
;
241 LineInputSetPos(Console
, 0);
242 LineInputEdit(Console
, Console
->LineSize
,
243 Hist
->Entries
[Hist
->Position
].Length
/ sizeof(WCHAR
),
244 Hist
->Entries
[Hist
->Position
].Buffer
);
248 LineInputKeyDown(PCONSOLE Console
, KEY_EVENT_RECORD
*KeyEvent
)
250 UINT Pos
= Console
->LinePos
;
251 PHISTORY_BUFFER Hist
;
252 UNICODE_STRING Entry
;
255 switch (KeyEvent
->wVirtualKeyCode
)
258 /* Clear entire line */
259 LineInputSetPos(Console
, 0);
260 LineInputEdit(Console
, Console
->LineSize
, 0, NULL
);
263 /* Move to start of line. With ctrl, erase everything left of cursor */
264 LineInputSetPos(Console
, 0);
265 if (KeyEvent
->dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
266 LineInputEdit(Console
, Pos
, 0, NULL
);
269 /* Move to end of line. With ctrl, erase everything right of cursor */
270 if (KeyEvent
->dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
271 LineInputEdit(Console
, Console
->LineSize
- Pos
, 0, NULL
);
273 LineInputSetPos(Console
, Console
->LineSize
);
276 /* Move left. With ctrl, move to beginning of previous word */
277 if (KeyEvent
->dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
279 while (Pos
> 0 && Console
->LineBuffer
[Pos
- 1] == L
' ') Pos
--;
280 while (Pos
> 0 && Console
->LineBuffer
[Pos
- 1] != L
' ') Pos
--;
286 LineInputSetPos(Console
, Pos
);
290 /* Move right. With ctrl, move to beginning of next word */
291 if (KeyEvent
->dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
293 while (Pos
< Console
->LineSize
&& Console
->LineBuffer
[Pos
] != L
' ') Pos
++;
294 while (Pos
< Console
->LineSize
&& Console
->LineBuffer
[Pos
] == L
' ') Pos
++;
295 LineInputSetPos(Console
, Pos
);
300 /* Recall one character (but don't overwrite current line) */
301 HistoryGetCurrentEntry(Console
, &Entry
);
302 if (Pos
< Console
->LineSize
)
303 LineInputSetPos(Console
, Pos
+ 1);
304 else if (Pos
* sizeof(WCHAR
) < Entry
.Length
)
305 LineInputEdit(Console
, 0, 1, &Entry
.Buffer
[Pos
]);
309 /* Toggle between insert and overstrike */
310 Console
->LineInsertToggle
= !Console
->LineInsertToggle
;
311 TermSetCursorInfo(Console
, Console
->ActiveBuffer
);
314 /* Remove character to right of cursor */
315 if (Pos
!= Console
->LineSize
)
316 LineInputEdit(Console
, 1, 0, NULL
);
319 /* Recall first history entry */
320 LineInputRecallHistory(Console
, -((WORD
)-1));
323 /* Recall last history entry */
324 LineInputRecallHistory(Console
, +((WORD
)-1));
328 /* Recall previous history entry. On first time, actually recall the
329 * current (usually last) entry; on subsequent times go back. */
330 LineInputRecallHistory(Console
, Console
->LineUpPressed
? -1 : 0);
331 Console
->LineUpPressed
= TRUE
;
334 /* Recall next history entry */
335 LineInputRecallHistory(Console
, +1);
338 /* Recall remainder of current history entry */
339 HistoryGetCurrentEntry(Console
, &Entry
);
340 if (Pos
* sizeof(WCHAR
) < Entry
.Length
)
342 UINT InsertSize
= (Entry
.Length
/ sizeof(WCHAR
) - Pos
);
343 UINT DeleteSize
= min(Console
->LineSize
- Pos
, InsertSize
);
344 LineInputEdit(Console
, DeleteSize
, InsertSize
, &Entry
.Buffer
[Pos
]);
348 /* Insert a ^Z character */
349 KeyEvent
->uChar
.UnicodeChar
= 26;
352 if (KeyEvent
->dwControlKeyState
& (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
353 HistoryDeleteBuffer(HistoryCurrentBuffer(Console
));
356 /* Search for history entries starting with input. */
357 Hist
= HistoryCurrentBuffer(Console
);
358 if (!Hist
|| Hist
->NumEntries
== 0) return;
360 /* Like Up/F5, on first time start from current (usually last) entry,
361 * but on subsequent times start at previous entry. */
362 if (Console
->LineUpPressed
)
363 Hist
->Position
= (Hist
->Position
? Hist
->Position
: Hist
->NumEntries
) - 1;
364 Console
->LineUpPressed
= TRUE
;
366 Entry
.Length
= Console
->LinePos
* sizeof(WCHAR
);
367 Entry
.Buffer
= Console
->LineBuffer
;
369 /* Keep going backwards, even wrapping around to the end,
370 * until we get back to starting point */
371 HistPos
= Hist
->Position
;
374 if (RtlPrefixUnicodeString(&Entry
, &Hist
->Entries
[HistPos
], FALSE
))
376 Hist
->Position
= HistPos
;
377 LineInputEdit(Console
, Console
->LineSize
- Pos
,
378 Hist
->Entries
[HistPos
].Length
/ sizeof(WCHAR
) - Pos
,
379 &Hist
->Entries
[HistPos
].Buffer
[Pos
]);
380 /* Cursor stays where it was */
381 LineInputSetPos(Console
, Pos
);
384 if (--HistPos
< 0) HistPos
+= Hist
->NumEntries
;
385 } while (HistPos
!= Hist
->Position
);
389 if (KeyEvent
->uChar
.UnicodeChar
== L
'\b' && Console
->InputBuffer
.Mode
& ENABLE_PROCESSED_INPUT
)
391 /* backspace handling - if processed input enabled then we handle it here
392 * otherwise we treat it like a normal char. */
395 LineInputSetPos(Console
, Pos
- 1);
396 LineInputEdit(Console
, 1, 0, NULL
);
399 else if (KeyEvent
->uChar
.UnicodeChar
== L
'\r')
401 HistoryAddEntry(Console
);
403 /* TODO: Expand aliases */
405 LineInputSetPos(Console
, Console
->LineSize
);
406 Console
->LineBuffer
[Console
->LineSize
++] = L
'\r';
407 if (Console
->InputBuffer
.Mode
& ENABLE_ECHO_INPUT
)
409 if (GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
411 ConioWriteConsole(Console
, (PTEXTMODE_SCREEN_BUFFER
)(Console
->ActiveBuffer
), L
"\r", 1, TRUE
);
415 /* Add \n if processed input. There should usually be room for it,
416 * but an exception to the rule exists: the buffer could have been
417 * pre-filled with LineMaxSize - 1 characters. */
418 if (Console
->InputBuffer
.Mode
& ENABLE_PROCESSED_INPUT
&&
419 Console
->LineSize
< Console
->LineMaxSize
)
421 Console
->LineBuffer
[Console
->LineSize
++] = L
'\n';
422 if (Console
->InputBuffer
.Mode
& ENABLE_ECHO_INPUT
)
424 if (GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
426 ConioWriteConsole(Console
, (PTEXTMODE_SCREEN_BUFFER
)(Console
->ActiveBuffer
), L
"\n", 1, TRUE
);
430 Console
->LineComplete
= TRUE
;
431 Console
->LinePos
= 0;
433 else if (KeyEvent
->uChar
.UnicodeChar
!= L
'\0')
435 if (KeyEvent
->uChar
.UnicodeChar
< 0x20 &&
436 Console
->LineWakeupMask
& (1 << KeyEvent
->uChar
.UnicodeChar
))
438 /* Control key client wants to handle itself (e.g. for tab completion) */
439 Console
->LineBuffer
[Console
->LineSize
++] = L
' ';
440 Console
->LineBuffer
[Console
->LinePos
] = KeyEvent
->uChar
.UnicodeChar
;
441 Console
->LineComplete
= TRUE
;
442 Console
->LinePos
= 0;
446 /* Normal character */
447 BOOL Overstrike
= !Console
->LineInsertToggle
&& (Console
->LinePos
!= Console
->LineSize
);
448 LineInputEdit(Console
, (Overstrike
? 1 : 0), 1, &KeyEvent
->uChar
.UnicodeChar
);
454 /* PUBLIC SERVER APIS *********************************************************/
456 CSR_API(SrvGetConsoleCommandHistory
)
458 PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetCommandHistoryRequest
;
459 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
462 PHISTORY_BUFFER Hist
;
463 PBYTE Buffer
= (PBYTE
)GetCommandHistoryRequest
->History
;
464 ULONG BufferSize
= GetCommandHistoryRequest
->Length
;
467 if ( !CsrValidateMessageBuffer(ApiMessage
,
468 (PVOID
*)&GetCommandHistoryRequest
->History
,
469 GetCommandHistoryRequest
->Length
,
471 !CsrValidateMessageBuffer(ApiMessage
,
472 (PVOID
*)&GetCommandHistoryRequest
->ExeName
.Buffer
,
473 GetCommandHistoryRequest
->ExeName
.Length
,
476 return STATUS_INVALID_PARAMETER
;
479 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
480 if (NT_SUCCESS(Status
))
482 Hist
= HistoryFindBuffer(Console
, &GetCommandHistoryRequest
->ExeName
);
485 for (i
= 0; i
< Hist
->NumEntries
; i
++)
487 if (BufferSize
< (Hist
->Entries
[i
].Length
+ sizeof(WCHAR
)))
489 Status
= STATUS_BUFFER_OVERFLOW
;
492 memcpy(Buffer
, Hist
->Entries
[i
].Buffer
, Hist
->Entries
[i
].Length
);
493 Buffer
+= Hist
->Entries
[i
].Length
;
494 *(PWCHAR
)Buffer
= L
'\0';
495 Buffer
+= sizeof(WCHAR
);
498 GetCommandHistoryRequest
->Length
= Buffer
- (PBYTE
)GetCommandHistoryRequest
->History
;
499 ConSrvReleaseConsole(Console
, TRUE
);
504 CSR_API(SrvGetConsoleCommandHistoryLength
)
506 PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetCommandHistoryLengthRequest
;
507 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
510 PHISTORY_BUFFER Hist
;
514 if (!CsrValidateMessageBuffer(ApiMessage
,
515 (PVOID
*)&GetCommandHistoryLengthRequest
->ExeName
.Buffer
,
516 GetCommandHistoryLengthRequest
->ExeName
.Length
,
519 return STATUS_INVALID_PARAMETER
;
522 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
523 if (NT_SUCCESS(Status
))
525 Hist
= HistoryFindBuffer(Console
, &GetCommandHistoryLengthRequest
->ExeName
);
528 for (i
= 0; i
< Hist
->NumEntries
; i
++)
529 Length
+= Hist
->Entries
[i
].Length
+ sizeof(WCHAR
);
531 GetCommandHistoryLengthRequest
->Length
= Length
;
532 ConSrvReleaseConsole(Console
, TRUE
);
537 CSR_API(SrvExpungeConsoleCommandHistory
)
539 PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ExpungeCommandHistoryRequest
;
540 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
542 PHISTORY_BUFFER Hist
;
545 if (!CsrValidateMessageBuffer(ApiMessage
,
546 (PVOID
*)&ExpungeCommandHistoryRequest
->ExeName
.Buffer
,
547 ExpungeCommandHistoryRequest
->ExeName
.Length
,
550 return STATUS_INVALID_PARAMETER
;
553 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
554 if (NT_SUCCESS(Status
))
556 Hist
= HistoryFindBuffer(Console
, &ExpungeCommandHistoryRequest
->ExeName
);
557 HistoryDeleteBuffer(Hist
);
558 ConSrvReleaseConsole(Console
, TRUE
);
563 CSR_API(SrvSetConsoleNumberOfCommands
)
565 PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetHistoryNumberCommandsRequest
;
566 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
568 PHISTORY_BUFFER Hist
;
570 UINT MaxEntries
= SetHistoryNumberCommandsRequest
->NumCommands
;
571 PUNICODE_STRING OldEntryList
, NewEntryList
;
573 if (!CsrValidateMessageBuffer(ApiMessage
,
574 (PVOID
*)&SetHistoryNumberCommandsRequest
->ExeName
.Buffer
,
575 SetHistoryNumberCommandsRequest
->ExeName
.Length
,
578 return STATUS_INVALID_PARAMETER
;
581 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
582 if (NT_SUCCESS(Status
))
584 Hist
= HistoryFindBuffer(Console
, &SetHistoryNumberCommandsRequest
->ExeName
);
587 OldEntryList
= Hist
->Entries
;
588 NewEntryList
= ConsoleAllocHeap(0, MaxEntries
* sizeof(UNICODE_STRING
));
591 Status
= STATUS_NO_MEMORY
;
595 /* If necessary, shrink by removing oldest entries */
596 for (; Hist
->NumEntries
> MaxEntries
; Hist
->NumEntries
--)
598 RtlFreeUnicodeString(Hist
->Entries
++);
599 Hist
->Position
+= (Hist
->Position
== 0);
602 Hist
->MaxEntries
= MaxEntries
;
603 Hist
->Entries
= memcpy(NewEntryList
, Hist
->Entries
,
604 Hist
->NumEntries
* sizeof(UNICODE_STRING
));
605 ConsoleFreeHeap(OldEntryList
);
608 ConSrvReleaseConsole(Console
, TRUE
);
613 CSR_API(SrvGetConsoleHistory
)
615 PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HistoryInfoRequest
;
617 NTSTATUS Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
618 if (NT_SUCCESS(Status
))
620 HistoryInfoRequest
->HistoryBufferSize
= Console
->HistoryBufferSize
;
621 HistoryInfoRequest
->NumberOfHistoryBuffers
= Console
->NumberOfHistoryBuffers
;
622 HistoryInfoRequest
->dwFlags
= Console
->HistoryNoDup
;
623 ConSrvReleaseConsole(Console
, TRUE
);
628 CSR_API(SrvSetConsoleHistory
)
630 PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HistoryInfoRequest
;
632 NTSTATUS Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
633 if (NT_SUCCESS(Status
))
635 Console
->HistoryBufferSize
= HistoryInfoRequest
->HistoryBufferSize
;
636 Console
->NumberOfHistoryBuffers
= HistoryInfoRequest
->NumberOfHistoryBuffers
;
637 Console
->HistoryNoDup
= HistoryInfoRequest
->dwFlags
& HISTORY_NO_DUP_FLAG
;
638 ConSrvReleaseConsole(Console
, TRUE
);
643 CSR_API(SrvSetConsoleCommandHistoryMode
)
645 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
646 return STATUS_NOT_IMPLEMENTED
;