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
9 /* INCLUDES *******************************************************************/
13 #include "include/conio.h"
14 #include "include/conio2.h"
19 typedef struct _HISTORY_BUFFER
25 PUNICODE_STRING Entries
;
26 UNICODE_STRING ExeName
;
27 } HISTORY_BUFFER
, *PHISTORY_BUFFER
;
30 /* PRIVATE FUNCTIONS **********************************************************/
32 static PHISTORY_BUFFER
33 HistoryCurrentBuffer(PCONSOLE Console
)
35 /* TODO: use actual EXE name sent from process that called ReadConsole */
36 UNICODE_STRING ExeName
= { 14, 14, L
"cmd.exe" };
37 PLIST_ENTRY Entry
= Console
->HistoryBuffers
.Flink
;
40 for (; Entry
!= &Console
->HistoryBuffers
; Entry
= Entry
->Flink
)
42 Hist
= CONTAINING_RECORD(Entry
, HISTORY_BUFFER
, ListEntry
);
43 if (RtlEqualUnicodeString(&ExeName
, &Hist
->ExeName
, FALSE
))
47 /* Couldn't find the buffer, create a new one */
48 Hist
= ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER
) + ExeName
.Length
);
49 if (!Hist
) return NULL
;
50 Hist
->MaxEntries
= Console
->HistoryBufferSize
;
52 Hist
->Entries
= ConsoleAllocHeap(0, Hist
->MaxEntries
* sizeof(UNICODE_STRING
));
55 ConsoleFreeHeap(Hist
);
58 Hist
->ExeName
.Length
= Hist
->ExeName
.MaximumLength
= ExeName
.Length
;
59 Hist
->ExeName
.Buffer
= (PWCHAR
)(Hist
+ 1);
60 memcpy(Hist
->ExeName
.Buffer
, ExeName
.Buffer
, ExeName
.Length
);
61 InsertHeadList(&Console
->HistoryBuffers
, &Hist
->ListEntry
);
66 HistoryAddEntry(PCONSOLE Console
)
68 UNICODE_STRING NewEntry
;
69 PHISTORY_BUFFER Hist
= HistoryCurrentBuffer(Console
);
74 NewEntry
.Length
= NewEntry
.MaximumLength
= Console
->LineSize
* sizeof(WCHAR
);
75 NewEntry
.Buffer
= Console
->LineBuffer
;
77 /* Don't add blank or duplicate entries */
78 if (NewEntry
.Length
== 0 || Hist
->MaxEntries
== 0 ||
79 (Hist
->NumEntries
> 0 &&
80 RtlEqualUnicodeString(&Hist
->Entries
[Hist
->NumEntries
- 1], &NewEntry
, FALSE
)))
85 if (Console
->HistoryNoDup
)
87 /* Check if this line has been entered before */
88 for (i
= Hist
->NumEntries
- 1; i
>= 0; i
--)
90 if (RtlEqualUnicodeString(&Hist
->Entries
[i
], &NewEntry
, FALSE
))
92 /* Just rotate the list to bring this entry to the end */
93 NewEntry
= Hist
->Entries
[i
];
94 memmove(&Hist
->Entries
[i
], &Hist
->Entries
[i
+ 1],
95 (Hist
->NumEntries
- (i
+ 1)) * sizeof(UNICODE_STRING
));
96 Hist
->Entries
[Hist
->NumEntries
- 1] = NewEntry
;
97 Hist
->Position
= Hist
->NumEntries
- 1;
103 if (Hist
->NumEntries
== Hist
->MaxEntries
)
105 /* List is full, remove oldest entry */
106 RtlFreeUnicodeString(&Hist
->Entries
[0]);
107 memmove(&Hist
->Entries
[0], &Hist
->Entries
[1],
108 --Hist
->NumEntries
* sizeof(UNICODE_STRING
));
111 if (NT_SUCCESS(RtlDuplicateUnicodeString(0, &NewEntry
, &Hist
->Entries
[Hist
->NumEntries
])))
113 Hist
->Position
= Hist
->NumEntries
- 1;
117 HistoryGetCurrentEntry(PCONSOLE Console
, PUNICODE_STRING Entry
)
119 PHISTORY_BUFFER Hist
= HistoryCurrentBuffer(Console
);
121 if (!Hist
|| Hist
->NumEntries
== 0)
124 *Entry
= Hist
->Entries
[Hist
->Position
];
127 static PHISTORY_BUFFER
128 HistoryFindBuffer(PCONSOLE Console
, PUNICODE_STRING ExeName
)
130 PLIST_ENTRY Entry
= Console
->HistoryBuffers
.Flink
;
131 while (Entry
!= &Console
->HistoryBuffers
)
133 /* For the history APIs, the caller is allowed to give only part of the name */
134 PHISTORY_BUFFER Hist
= CONTAINING_RECORD(Entry
, HISTORY_BUFFER
, ListEntry
);
135 if (RtlPrefixUnicodeString(ExeName
, &Hist
->ExeName
, TRUE
))
137 Entry
= Entry
->Flink
;
143 HistoryDeleteBuffer(PHISTORY_BUFFER Hist
)
147 while (Hist
->NumEntries
!= 0)
148 RtlFreeUnicodeString(&Hist
->Entries
[--Hist
->NumEntries
]);
150 ConsoleFreeHeap(Hist
->Entries
);
151 RemoveEntryList(&Hist
->ListEntry
);
152 ConsoleFreeHeap(Hist
);
156 HistoryDeleteBuffers(PCONSOLE Console
)
158 PLIST_ENTRY CurrentEntry
;
159 PHISTORY_BUFFER HistoryBuffer
;
161 while (!IsListEmpty(&Console
->HistoryBuffers
))
163 CurrentEntry
= RemoveHeadList(&Console
->HistoryBuffers
);
164 HistoryBuffer
= CONTAINING_RECORD(CurrentEntry
, HISTORY_BUFFER
, ListEntry
);
165 HistoryDeleteBuffer(HistoryBuffer
);
170 LineInputSetPos(PCONSOLE Console
, UINT Pos
)
172 if (Pos
!= Console
->LinePos
&& Console
->InputBuffer
.Mode
& ENABLE_ECHO_INPUT
)
174 PCONSOLE_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
175 SHORT OldCursorX
= Buffer
->CursorPosition
.X
;
176 SHORT OldCursorY
= Buffer
->CursorPosition
.Y
;
177 INT XY
= OldCursorY
* Buffer
->ScreenBufferSize
.X
+ OldCursorX
;
179 XY
+= (Pos
- Console
->LinePos
);
182 else if (XY
>= Buffer
->ScreenBufferSize
.Y
* Buffer
->ScreenBufferSize
.X
)
183 XY
= Buffer
->ScreenBufferSize
.Y
* Buffer
->ScreenBufferSize
.X
- 1;
185 Buffer
->CursorPosition
.X
= XY
% Buffer
->ScreenBufferSize
.X
;
186 Buffer
->CursorPosition
.Y
= XY
/ Buffer
->ScreenBufferSize
.X
;
187 ConioSetScreenInfo(Console
, Buffer
, OldCursorX
, OldCursorY
);
190 Console
->LinePos
= Pos
;
194 LineInputEdit(PCONSOLE Console
, UINT NumToDelete
, UINT NumToInsert
, WCHAR
*Insertion
)
196 PTEXTMODE_SCREEN_BUFFER ActiveBuffer
;
197 UINT Pos
= Console
->LinePos
;
198 UINT NewSize
= Console
->LineSize
- NumToDelete
+ NumToInsert
;
201 if (GetType(Console
->ActiveBuffer
) != TEXTMODE_BUFFER
) return;
202 ActiveBuffer
= (PTEXTMODE_SCREEN_BUFFER
)Console
->ActiveBuffer
;
204 /* Make sure there's always enough room for ending \r\n */
205 if (NewSize
+ 2 > Console
->LineMaxSize
)
208 memmove(&Console
->LineBuffer
[Pos
+ NumToInsert
],
209 &Console
->LineBuffer
[Pos
+ NumToDelete
],
210 (Console
->LineSize
- (Pos
+ NumToDelete
)) * sizeof(WCHAR
));
211 memcpy(&Console
->LineBuffer
[Pos
], Insertion
, NumToInsert
* sizeof(WCHAR
));
213 if (Console
->InputBuffer
.Mode
& ENABLE_ECHO_INPUT
)
215 for (i
= Pos
; i
< NewSize
; i
++)
217 ConioWriteConsole(Console
, ActiveBuffer
, &Console
->LineBuffer
[i
], 1, TRUE
);
219 for (; i
< Console
->LineSize
; i
++)
221 ConioWriteConsole(Console
, ActiveBuffer
, L
" ", 1, TRUE
);
223 Console
->LinePos
= i
;
226 Console
->LineSize
= NewSize
;
227 LineInputSetPos(Console
, Pos
+ NumToInsert
);
231 LineInputRecallHistory(PCONSOLE Console
, INT Offset
)
233 PHISTORY_BUFFER Hist
= HistoryCurrentBuffer(Console
);
236 if (!Hist
|| Hist
->NumEntries
== 0) return;
238 Position
= Hist
->Position
+ Offset
;
239 Position
= min(max(Position
, 0), Hist
->NumEntries
- 1);
240 Hist
->Position
= Position
;
242 LineInputSetPos(Console
, 0);
243 LineInputEdit(Console
, Console
->LineSize
,
244 Hist
->Entries
[Hist
->Position
].Length
/ sizeof(WCHAR
),
245 Hist
->Entries
[Hist
->Position
].Buffer
);
249 LineInputKeyDown(PCONSOLE Console
, KEY_EVENT_RECORD
*KeyEvent
)
251 UINT Pos
= Console
->LinePos
;
252 PHISTORY_BUFFER Hist
;
253 UNICODE_STRING Entry
;
256 switch (KeyEvent
->wVirtualKeyCode
)
259 /* Clear entire line */
260 LineInputSetPos(Console
, 0);
261 LineInputEdit(Console
, Console
->LineSize
, 0, NULL
);
264 /* Move to start of line. With ctrl, erase everything left of cursor */
265 LineInputSetPos(Console
, 0);
266 if (KeyEvent
->dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
267 LineInputEdit(Console
, Pos
, 0, NULL
);
270 /* Move to end of line. With ctrl, erase everything right of cursor */
271 if (KeyEvent
->dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
272 LineInputEdit(Console
, Console
->LineSize
- Pos
, 0, NULL
);
274 LineInputSetPos(Console
, Console
->LineSize
);
277 /* Move left. With ctrl, move to beginning of previous word */
278 if (KeyEvent
->dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
280 while (Pos
> 0 && Console
->LineBuffer
[Pos
- 1] == L
' ') Pos
--;
281 while (Pos
> 0 && Console
->LineBuffer
[Pos
- 1] != L
' ') Pos
--;
287 LineInputSetPos(Console
, Pos
);
291 /* Move right. With ctrl, move to beginning of next word */
292 if (KeyEvent
->dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
294 while (Pos
< Console
->LineSize
&& Console
->LineBuffer
[Pos
] != L
' ') Pos
++;
295 while (Pos
< Console
->LineSize
&& Console
->LineBuffer
[Pos
] == L
' ') Pos
++;
296 LineInputSetPos(Console
, Pos
);
301 /* Recall one character (but don't overwrite current line) */
302 HistoryGetCurrentEntry(Console
, &Entry
);
303 if (Pos
< Console
->LineSize
)
304 LineInputSetPos(Console
, Pos
+ 1);
305 else if (Pos
* sizeof(WCHAR
) < Entry
.Length
)
306 LineInputEdit(Console
, 0, 1, &Entry
.Buffer
[Pos
]);
310 /* Toggle between insert and overstrike */
311 Console
->LineInsertToggle
= !Console
->LineInsertToggle
;
312 ConioSetCursorInfo(Console
, Console
->ActiveBuffer
);
315 /* Remove character to right of cursor */
316 if (Pos
!= Console
->LineSize
)
317 LineInputEdit(Console
, 1, 0, NULL
);
320 /* Recall first history entry */
321 LineInputRecallHistory(Console
, -((WORD
)-1));
324 /* Recall last history entry */
325 LineInputRecallHistory(Console
, +((WORD
)-1));
329 /* Recall previous history entry. On first time, actually recall the
330 * current (usually last) entry; on subsequent times go back. */
331 LineInputRecallHistory(Console
, Console
->LineUpPressed
? -1 : 0);
332 Console
->LineUpPressed
= TRUE
;
335 /* Recall next history entry */
336 LineInputRecallHistory(Console
, +1);
339 /* Recall remainder of current history entry */
340 HistoryGetCurrentEntry(Console
, &Entry
);
341 if (Pos
* sizeof(WCHAR
) < Entry
.Length
)
343 UINT InsertSize
= (Entry
.Length
/ sizeof(WCHAR
) - Pos
);
344 UINT DeleteSize
= min(Console
->LineSize
- Pos
, InsertSize
);
345 LineInputEdit(Console
, DeleteSize
, InsertSize
, &Entry
.Buffer
[Pos
]);
349 /* Insert a ^Z character */
350 KeyEvent
->uChar
.UnicodeChar
= 26;
353 if (KeyEvent
->dwControlKeyState
& (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
354 HistoryDeleteBuffer(HistoryCurrentBuffer(Console
));
357 /* Search for history entries starting with input. */
358 Hist
= HistoryCurrentBuffer(Console
);
359 if (!Hist
|| Hist
->NumEntries
== 0) return;
361 /* Like Up/F5, on first time start from current (usually last) entry,
362 * but on subsequent times start at previous entry. */
363 if (Console
->LineUpPressed
)
364 Hist
->Position
= (Hist
->Position
? Hist
->Position
: Hist
->NumEntries
) - 1;
365 Console
->LineUpPressed
= TRUE
;
367 Entry
.Length
= Console
->LinePos
* sizeof(WCHAR
);
368 Entry
.Buffer
= Console
->LineBuffer
;
370 /* Keep going backwards, even wrapping around to the end,
371 * until we get back to starting point */
372 HistPos
= Hist
->Position
;
375 if (RtlPrefixUnicodeString(&Entry
, &Hist
->Entries
[HistPos
], FALSE
))
377 Hist
->Position
= HistPos
;
378 LineInputEdit(Console
, Console
->LineSize
- Pos
,
379 Hist
->Entries
[HistPos
].Length
/ sizeof(WCHAR
) - Pos
,
380 &Hist
->Entries
[HistPos
].Buffer
[Pos
]);
381 /* Cursor stays where it was */
382 LineInputSetPos(Console
, Pos
);
385 if (--HistPos
< 0) HistPos
+= Hist
->NumEntries
;
386 } while (HistPos
!= Hist
->Position
);
390 if (KeyEvent
->uChar
.UnicodeChar
== L
'\b' && Console
->InputBuffer
.Mode
& ENABLE_PROCESSED_INPUT
)
392 /* backspace handling - if processed input enabled then we handle it here
393 * otherwise we treat it like a normal char. */
396 LineInputSetPos(Console
, Pos
- 1);
397 LineInputEdit(Console
, 1, 0, NULL
);
400 else if (KeyEvent
->uChar
.UnicodeChar
== L
'\r')
402 HistoryAddEntry(Console
);
404 /* TODO: Expand aliases */
406 LineInputSetPos(Console
, Console
->LineSize
);
407 Console
->LineBuffer
[Console
->LineSize
++] = L
'\r';
408 if (Console
->InputBuffer
.Mode
& ENABLE_ECHO_INPUT
)
410 if (GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
412 ConioWriteConsole(Console
, (PTEXTMODE_SCREEN_BUFFER
)(Console
->ActiveBuffer
), L
"\r", 1, TRUE
);
416 /* Add \n if processed input. There should usually be room for it,
417 * but an exception to the rule exists: the buffer could have been
418 * pre-filled with LineMaxSize - 1 characters. */
419 if (Console
->InputBuffer
.Mode
& ENABLE_PROCESSED_INPUT
&&
420 Console
->LineSize
< Console
->LineMaxSize
)
422 Console
->LineBuffer
[Console
->LineSize
++] = L
'\n';
423 if (Console
->InputBuffer
.Mode
& ENABLE_ECHO_INPUT
)
425 if (GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
427 ConioWriteConsole(Console
, (PTEXTMODE_SCREEN_BUFFER
)(Console
->ActiveBuffer
), L
"\n", 1, TRUE
);
431 Console
->LineComplete
= TRUE
;
432 Console
->LinePos
= 0;
434 else if (KeyEvent
->uChar
.UnicodeChar
!= L
'\0')
436 if (KeyEvent
->uChar
.UnicodeChar
< 0x20 &&
437 Console
->LineWakeupMask
& (1 << KeyEvent
->uChar
.UnicodeChar
))
439 /* Control key client wants to handle itself (e.g. for tab completion) */
440 Console
->LineBuffer
[Console
->LineSize
++] = L
' ';
441 Console
->LineBuffer
[Console
->LinePos
] = KeyEvent
->uChar
.UnicodeChar
;
442 Console
->LineComplete
= TRUE
;
443 Console
->LinePos
= 0;
447 /* Normal character */
448 BOOL Overstrike
= Console
->LineInsertToggle
&& Console
->LinePos
!= Console
->LineSize
;
449 LineInputEdit(Console
, Overstrike
, 1, &KeyEvent
->uChar
.UnicodeChar
);
455 /* PUBLIC SERVER APIS *********************************************************/
457 CSR_API(SrvGetConsoleCommandHistory
)
459 PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetCommandHistoryRequest
;
460 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
463 PHISTORY_BUFFER Hist
;
464 PBYTE Buffer
= (PBYTE
)GetCommandHistoryRequest
->History
;
465 ULONG BufferSize
= GetCommandHistoryRequest
->Length
;
468 if ( !CsrValidateMessageBuffer(ApiMessage
,
469 (PVOID
*)&GetCommandHistoryRequest
->History
,
470 GetCommandHistoryRequest
->Length
,
472 !CsrValidateMessageBuffer(ApiMessage
,
473 (PVOID
*)&GetCommandHistoryRequest
->ExeName
.Buffer
,
474 GetCommandHistoryRequest
->ExeName
.Length
,
477 return STATUS_INVALID_PARAMETER
;
480 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
481 if (NT_SUCCESS(Status
))
483 Hist
= HistoryFindBuffer(Console
, &GetCommandHistoryRequest
->ExeName
);
486 for (i
= 0; i
< Hist
->NumEntries
; i
++)
488 if (BufferSize
< (Hist
->Entries
[i
].Length
+ sizeof(WCHAR
)))
490 Status
= STATUS_BUFFER_OVERFLOW
;
493 memcpy(Buffer
, Hist
->Entries
[i
].Buffer
, Hist
->Entries
[i
].Length
);
494 Buffer
+= Hist
->Entries
[i
].Length
;
495 *(PWCHAR
)Buffer
= L
'\0';
496 Buffer
+= sizeof(WCHAR
);
499 GetCommandHistoryRequest
->Length
= Buffer
- (PBYTE
)GetCommandHistoryRequest
->History
;
500 ConSrvReleaseConsole(Console
, TRUE
);
505 CSR_API(SrvGetConsoleCommandHistoryLength
)
507 PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetCommandHistoryLengthRequest
;
508 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
511 PHISTORY_BUFFER Hist
;
515 if (!CsrValidateMessageBuffer(ApiMessage
,
516 (PVOID
*)&GetCommandHistoryLengthRequest
->ExeName
.Buffer
,
517 GetCommandHistoryLengthRequest
->ExeName
.Length
,
520 return STATUS_INVALID_PARAMETER
;
523 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
524 if (NT_SUCCESS(Status
))
526 Hist
= HistoryFindBuffer(Console
, &GetCommandHistoryLengthRequest
->ExeName
);
529 for (i
= 0; i
< Hist
->NumEntries
; i
++)
530 Length
+= Hist
->Entries
[i
].Length
+ sizeof(WCHAR
);
532 GetCommandHistoryLengthRequest
->Length
= Length
;
533 ConSrvReleaseConsole(Console
, TRUE
);
538 CSR_API(SrvExpungeConsoleCommandHistory
)
540 PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ExpungeCommandHistoryRequest
;
541 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
543 PHISTORY_BUFFER Hist
;
546 if (!CsrValidateMessageBuffer(ApiMessage
,
547 (PVOID
*)&ExpungeCommandHistoryRequest
->ExeName
.Buffer
,
548 ExpungeCommandHistoryRequest
->ExeName
.Length
,
551 return STATUS_INVALID_PARAMETER
;
554 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
555 if (NT_SUCCESS(Status
))
557 Hist
= HistoryFindBuffer(Console
, &ExpungeCommandHistoryRequest
->ExeName
);
558 HistoryDeleteBuffer(Hist
);
559 ConSrvReleaseConsole(Console
, TRUE
);
564 CSR_API(SrvSetConsoleNumberOfCommands
)
566 PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetHistoryNumberCommandsRequest
;
567 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
569 PHISTORY_BUFFER Hist
;
571 UINT MaxEntries
= SetHistoryNumberCommandsRequest
->NumCommands
;
572 PUNICODE_STRING OldEntryList
, NewEntryList
;
574 if (!CsrValidateMessageBuffer(ApiMessage
,
575 (PVOID
*)&SetHistoryNumberCommandsRequest
->ExeName
.Buffer
,
576 SetHistoryNumberCommandsRequest
->ExeName
.Length
,
579 return STATUS_INVALID_PARAMETER
;
582 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
583 if (NT_SUCCESS(Status
))
585 Hist
= HistoryFindBuffer(Console
, &SetHistoryNumberCommandsRequest
->ExeName
);
588 OldEntryList
= Hist
->Entries
;
589 NewEntryList
= ConsoleAllocHeap(0, MaxEntries
* sizeof(UNICODE_STRING
));
592 Status
= STATUS_NO_MEMORY
;
596 /* If necessary, shrink by removing oldest entries */
597 for (; Hist
->NumEntries
> MaxEntries
; Hist
->NumEntries
--)
599 RtlFreeUnicodeString(Hist
->Entries
++);
600 Hist
->Position
+= (Hist
->Position
== 0);
603 Hist
->MaxEntries
= MaxEntries
;
604 Hist
->Entries
= memcpy(NewEntryList
, Hist
->Entries
,
605 Hist
->NumEntries
* sizeof(UNICODE_STRING
));
606 ConsoleFreeHeap(OldEntryList
);
609 ConSrvReleaseConsole(Console
, TRUE
);
614 CSR_API(SrvGetConsoleHistory
)
616 PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HistoryInfoRequest
;
618 NTSTATUS Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
619 if (NT_SUCCESS(Status
))
621 HistoryInfoRequest
->HistoryBufferSize
= Console
->HistoryBufferSize
;
622 HistoryInfoRequest
->NumberOfHistoryBuffers
= Console
->NumberOfHistoryBuffers
;
623 HistoryInfoRequest
->dwFlags
= Console
->HistoryNoDup
;
624 ConSrvReleaseConsole(Console
, TRUE
);
629 CSR_API(SrvSetConsoleHistory
)
631 PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.HistoryInfoRequest
;
633 NTSTATUS Status
= ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), &Console
, TRUE
);
634 if (NT_SUCCESS(Status
))
636 Console
->HistoryBufferSize
= HistoryInfoRequest
->HistoryBufferSize
;
637 Console
->NumberOfHistoryBuffers
= HistoryInfoRequest
->NumberOfHistoryBuffers
;
638 Console
->HistoryNoDup
= HistoryInfoRequest
->dwFlags
& HISTORY_NO_DUP_FLAG
;
639 ConSrvReleaseConsole(Console
, TRUE
);
644 CSR_API(SrvSetConsoleCommandHistoryMode
)
646 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
647 return STATUS_NOT_IMPLEMENTED
;