1 /*
2 * LICENSE: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/history.c
5 * PURPOSE: Console line input functions
6 * PROGRAMMERS: Jeffrey Morlan
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "consrv.h"
12 #include "popup.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 typedef struct _HISTORY_BUFFER
18 {
19 LIST_ENTRY ListEntry;
20 ULONG Position;
21 ULONG MaxEntries;
22 ULONG NumEntries;
23 UNICODE_STRING ExeName;
24 PUNICODE_STRING Entries;
25 } HISTORY_BUFFER, *PHISTORY_BUFFER;
26
27
28 BOOLEAN
29 ConvertInputAnsiToUnicode(PCONSRV_CONSOLE Console,
30 PVOID Source,
31 USHORT SourceLength,
32 // BOOLEAN IsUnicode,
33 PWCHAR* Target,
34 PUSHORT TargetLength);
35 BOOLEAN
36 ConvertInputUnicodeToAnsi(PCONSRV_CONSOLE Console,
37 PVOID Source,
38 USHORT SourceLength,
39 // BOOLEAN IsAnsi,
40 PCHAR/* * */ Target,
41 /*P*/USHORT TargetLength);
42
43
44 /* PRIVATE FUNCTIONS **********************************************************/
45
46 static PHISTORY_BUFFER
HistoryCurrentBuffer(IN PCONSRV_CONSOLE Console,IN PUNICODE_STRING ExeName)47 HistoryCurrentBuffer(
48 IN PCONSRV_CONSOLE Console,
49 IN PUNICODE_STRING ExeName)
50 {
51 PLIST_ENTRY Entry;
52 PHISTORY_BUFFER Hist;
53
54 for (Entry = Console->HistoryBuffers.Flink;
55 Entry != &Console->HistoryBuffers;
56 Entry = Entry->Flink)
57 {
58 Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
59 if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE))
60 return Hist;
61 }
62
63 /* Could not find the buffer, create a new one */
64
65 if (Console->NumberOfHistoryBuffers < Console->MaxNumberOfHistoryBuffers)
66 {
67 Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length);
68 if (!Hist) return NULL;
69 Hist->MaxEntries = Console->HistoryBufferSize;
70 Hist->NumEntries = 0;
71 Hist->Entries = ConsoleAllocHeap(0, Hist->MaxEntries * sizeof(UNICODE_STRING));
72 if (!Hist->Entries)
73 {
74 ConsoleFreeHeap(Hist);
75 return NULL;
76 }
77 Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length;
78 Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
79 RtlCopyMemory(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length);
80 InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
81 Console->NumberOfHistoryBuffers++;
82 return Hist;
83 }
84 else
85 {
86 // FIXME: TODO !!!!!!!
87 // Reuse an older history buffer, if possible with the same Exe name,
88 // otherwise take the oldest one and reset its contents.
89 // And move the history buffer back to the head of the list.
90 UNIMPLEMENTED;
91 return NULL;
92 }
93 }
94
95 static PHISTORY_BUFFER
HistoryFindBuffer(PCONSRV_CONSOLE Console,PVOID ExeName,USHORT ExeLength,BOOLEAN UnicodeExe)96 HistoryFindBuffer(PCONSRV_CONSOLE Console,
97 PVOID ExeName,
98 USHORT ExeLength,
99 BOOLEAN UnicodeExe)
100 {
101 UNICODE_STRING ExeNameU;
102
103 PLIST_ENTRY Entry;
104 PHISTORY_BUFFER Hist = NULL;
105
106 if (ExeName == NULL) return NULL;
107
108 if (UnicodeExe)
109 {
110 ExeNameU.Buffer = ExeName;
111 /* Length is in bytes */
112 ExeNameU.MaximumLength = ExeLength;
113 }
114 else
115 {
116 if (!ConvertInputAnsiToUnicode(Console,
117 ExeName, ExeLength,
118 &ExeNameU.Buffer, &ExeNameU.MaximumLength))
119 {
120 return NULL;
121 }
122 }
123 ExeNameU.Length = ExeNameU.MaximumLength;
124
125 for (Entry = Console->HistoryBuffers.Flink;
126 Entry != &Console->HistoryBuffers;
127 Entry = Entry->Flink)
128 {
129 Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
130
131 /* For the history APIs, the caller is allowed to give only part of the name */
132 if (RtlPrefixUnicodeString(&ExeNameU, &Hist->ExeName, TRUE))
133 {
134 if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
135 return Hist;
136 }
137 }
138
139 if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
140 return NULL;
141 }
142
143 static VOID
HistoryDeleteBuffer(PHISTORY_BUFFER Hist)144 HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
145 {
146 if (!Hist) return;
147
148 while (Hist->NumEntries != 0)
149 RtlFreeUnicodeString(&Hist->Entries[--Hist->NumEntries]);
150
151 ConsoleFreeHeap(Hist->Entries);
152 RemoveEntryList(&Hist->ListEntry);
153 ConsoleFreeHeap(Hist);
154 }
155
156 static NTSTATUS
HistoryResizeBuffer(IN PHISTORY_BUFFER Hist,IN ULONG NumCommands)157 HistoryResizeBuffer(
158 IN PHISTORY_BUFFER Hist,
159 IN ULONG NumCommands)
160 {
161 PUNICODE_STRING OldEntryList = Hist->Entries;
162 PUNICODE_STRING NewEntryList;
163
164 NewEntryList = ConsoleAllocHeap(0, NumCommands * sizeof(UNICODE_STRING));
165 if (!NewEntryList)
166 return STATUS_NO_MEMORY;
167
168 /* If necessary, shrink by removing oldest entries */
169 for (; Hist->NumEntries > NumCommands; Hist->NumEntries--)
170 {
171 RtlFreeUnicodeString(Hist->Entries++);
172 Hist->Position += (Hist->Position == 0);
173 }
174
175 Hist->MaxEntries = NumCommands;
176 RtlCopyMemory(NewEntryList, Hist->Entries,
177 Hist->NumEntries * sizeof(UNICODE_STRING));
178 Hist->Entries = NewEntryList;
179 ConsoleFreeHeap(OldEntryList);
180
181 return STATUS_SUCCESS;
182 }
183
184 VOID
HistoryAddEntry(PCONSRV_CONSOLE Console,PUNICODE_STRING ExeName,PUNICODE_STRING Entry)185 HistoryAddEntry(PCONSRV_CONSOLE Console,
186 PUNICODE_STRING ExeName,
187 PUNICODE_STRING Entry)
188 {
189 // UNICODE_STRING NewEntry;
190 PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
191
192 if (!Hist) return;
193
194 // NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR);
195 // NewEntry.Buffer = Console->LineBuffer;
196
197 /* Don't add blank or duplicate entries */
198 if (Entry->Length == 0 || Hist->MaxEntries == 0 ||
199 (Hist->NumEntries > 0 &&
200 RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], Entry, FALSE)))
201 {
202 return;
203 }
204
205 if (Console->HistoryNoDup)
206 {
207 INT i;
208
209 /* Check if this line has been entered before */
210 for (i = Hist->NumEntries - 1; i >= 0; i--)
211 {
212 if (RtlEqualUnicodeString(&Hist->Entries[i], Entry, FALSE))
213 {
214 UNICODE_STRING NewEntry;
215
216 /* Just rotate the list to bring this entry to the end */
217 NewEntry = Hist->Entries[i];
218 RtlMoveMemory(&Hist->Entries[i], &Hist->Entries[i + 1],
219 (Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING));
220 Hist->Entries[Hist->NumEntries - 1] = NewEntry;
221 Hist->Position = Hist->NumEntries - 1;
222 return;
223 }
224 }
225 }
226
227 if (Hist->NumEntries == Hist->MaxEntries)
228 {
229 /* List is full, remove oldest entry */
230 RtlFreeUnicodeString(&Hist->Entries[0]);
231 RtlMoveMemory(&Hist->Entries[0], &Hist->Entries[1],
232 --Hist->NumEntries * sizeof(UNICODE_STRING));
233 }
234
235 if (NT_SUCCESS(RtlDuplicateUnicodeString(0, Entry, &Hist->Entries[Hist->NumEntries])))
236 Hist->NumEntries++;
237 Hist->Position = Hist->NumEntries - 1;
238 }
239
240 VOID
HistoryGetCurrentEntry(PCONSRV_CONSOLE Console,PUNICODE_STRING ExeName,PUNICODE_STRING Entry)241 HistoryGetCurrentEntry(PCONSRV_CONSOLE Console,
242 PUNICODE_STRING ExeName,
243 PUNICODE_STRING Entry)
244 {
245 PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
246
247 if (!Hist || Hist->NumEntries == 0)
248 Entry->Length = 0;
249 else
250 *Entry = Hist->Entries[Hist->Position];
251 }
252
253 BOOL
HistoryRecallHistory(PCONSRV_CONSOLE Console,PUNICODE_STRING ExeName,INT Offset,PUNICODE_STRING Entry)254 HistoryRecallHistory(PCONSRV_CONSOLE Console,
255 PUNICODE_STRING ExeName,
256 INT Offset,
257 PUNICODE_STRING Entry)
258 {
259 PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
260 ULONG Position = 0;
261
262 if (!Hist || Hist->NumEntries == 0) return FALSE;
263
264 Position = Hist->Position + Offset;
265 Position = min(max(Position, 0), Hist->NumEntries - 1);
266 Hist->Position = Position;
267
268 *Entry = Hist->Entries[Hist->Position];
269 return TRUE;
270 }
271
272 BOOL
HistoryFindEntryByPrefix(PCONSRV_CONSOLE Console,PUNICODE_STRING ExeName,PUNICODE_STRING Prefix,PUNICODE_STRING Entry)273 HistoryFindEntryByPrefix(PCONSRV_CONSOLE Console,
274 PUNICODE_STRING ExeName,
275 PUNICODE_STRING Prefix,
276 PUNICODE_STRING Entry)
277 {
278 INT HistPos;
279
280 /* Search for history entries starting with input. */
281 PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
282 if (!Hist || Hist->NumEntries == 0) return FALSE;
283
284 /*
285 * Like Up/F5, on first time start from current (usually last) entry,
286 * but on subsequent times start at previous entry.
287 */
288 if (Console->LineUpPressed)
289 Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1;
290 Console->LineUpPressed = TRUE;
291
292 // Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR)
293 // Entry.Buffer = Console->LineBuffer;
294
295 /*
296 * Keep going backwards, even wrapping around to the end,
297 * until we get back to starting point.
298 */
299 HistPos = Hist->Position;
300 do
301 {
302 if (RtlPrefixUnicodeString(Prefix, &Hist->Entries[HistPos], FALSE))
303 {
304 Hist->Position = HistPos;
305 *Entry = Hist->Entries[HistPos];
306 return TRUE;
307 }
308 if (--HistPos < 0) HistPos += Hist->NumEntries;
309 } while (HistPos != Hist->Position);
310
311 return FALSE;
312 }
313
314 PPOPUP_WINDOW
HistoryDisplayCurrentHistory(PCONSRV_CONSOLE Console,PUNICODE_STRING ExeName)315 HistoryDisplayCurrentHistory(PCONSRV_CONSOLE Console,
316 PUNICODE_STRING ExeName)
317 {
318 PCONSOLE_SCREEN_BUFFER ActiveBuffer;
319 PPOPUP_WINDOW Popup;
320
321 SHORT xLeft, yTop;
322 SHORT Width, Height;
323
324 PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName);
325
326 if (!Hist) return NULL;
327 if (Hist->NumEntries == 0) return NULL;
328
329 if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER) return NULL;
330 ActiveBuffer = Console->ActiveBuffer;
331
332 Width = 40;
333 Height = 10;
334
335 /* Center the popup window on the screen */
336 xLeft = ActiveBuffer->ViewOrigin.X + (ActiveBuffer->ViewSize.X - Width ) / 2;
337 yTop = ActiveBuffer->ViewOrigin.Y + (ActiveBuffer->ViewSize.Y - Height) / 2;
338
339 /* Create the popup */
340 Popup = CreatePopupWindow(Console, ActiveBuffer,
341 xLeft, yTop, Width, Height);
342 if (Popup == NULL) return NULL;
343
344 Popup->PopupInputRoutine = NULL;
345
346 return Popup;
347 }
348
349 VOID
HistoryDeleteCurrentBuffer(PCONSRV_CONSOLE Console,PUNICODE_STRING ExeName)350 HistoryDeleteCurrentBuffer(PCONSRV_CONSOLE Console,
351 PUNICODE_STRING ExeName)
352 {
353 HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName));
354 }
355
356 VOID
HistoryDeleteBuffers(PCONSRV_CONSOLE Console)357 HistoryDeleteBuffers(PCONSRV_CONSOLE Console)
358 {
359 PLIST_ENTRY CurrentEntry;
360 PHISTORY_BUFFER HistoryBuffer;
361
362 while (!IsListEmpty(&Console->HistoryBuffers))
363 {
364 CurrentEntry = RemoveHeadList(&Console->HistoryBuffers);
365 HistoryBuffer = CONTAINING_RECORD(CurrentEntry, HISTORY_BUFFER, ListEntry);
366 HistoryDeleteBuffer(HistoryBuffer);
367 }
368 }
369
370 VOID
HistoryReshapeAllBuffers(IN PCONSRV_CONSOLE Console,IN ULONG HistoryBufferSize,IN ULONG MaxNumberOfHistoryBuffers,IN BOOLEAN HistoryNoDup)371 HistoryReshapeAllBuffers(
372 IN PCONSRV_CONSOLE Console,
373 IN ULONG HistoryBufferSize,
374 IN ULONG MaxNumberOfHistoryBuffers,
375 IN BOOLEAN HistoryNoDup)
376 {
377 PLIST_ENTRY Entry;
378 PHISTORY_BUFFER Hist;
379 NTSTATUS Status;
380
381 // ASSERT(Console->NumberOfHistoryBuffers <= Console->MaxNumberOfHistoryBuffers);
382 if (MaxNumberOfHistoryBuffers < Console->NumberOfHistoryBuffers)
383 {
384 /*
385 * Trim the history buffers list and reduce it up to MaxNumberOfHistoryBuffers.
386 * We loop the history buffers list backwards so as to trim the oldest
387 * buffers first.
388 */
389 while (!IsListEmpty(&Console->HistoryBuffers) &&
390 (Console->NumberOfHistoryBuffers > MaxNumberOfHistoryBuffers))
391 {
392 Entry = RemoveTailList(&Console->HistoryBuffers);
393 Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
394 HistoryDeleteBuffer(Hist);
395 Console->NumberOfHistoryBuffers--;
396 }
397 ASSERT(Console->NumberOfHistoryBuffers == MaxNumberOfHistoryBuffers);
398 ASSERT(((Console->NumberOfHistoryBuffers == 0) && IsListEmpty(&Console->HistoryBuffers)) ||
399 ((Console->NumberOfHistoryBuffers > 0) && !IsListEmpty(&Console->HistoryBuffers)));
400 }
401 Console->MaxNumberOfHistoryBuffers = MaxNumberOfHistoryBuffers;
402
403 /* Resize each history buffer */
404 for (Entry = Console->HistoryBuffers.Flink;
405 Entry != &Console->HistoryBuffers;
406 Entry = Entry->Flink)
407 {
408 Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
409 Status = HistoryResizeBuffer(Hist, HistoryBufferSize);
410 if (!NT_SUCCESS(Status))
411 {
412 DPRINT1("HistoryResizeBuffer(0x%p, %lu) failed, Status 0x%08lx\n",
413 Hist, HistoryBufferSize, Status);
414 }
415 }
416 Console->HistoryBufferSize = HistoryBufferSize;
417
418 /* No duplicates */
419 Console->HistoryNoDup = !!HistoryNoDup;
420 }
421
422
423 /* PUBLIC SERVER APIS *********************************************************/
424
425 /* API_NUMBER: ConsolepGetCommandHistory */
CON_API(SrvGetConsoleCommandHistory,CONSOLE_GETCOMMANDHISTORY,GetCommandHistoryRequest)426 CON_API(SrvGetConsoleCommandHistory,
427 CONSOLE_GETCOMMANDHISTORY, GetCommandHistoryRequest)
428 {
429 NTSTATUS Status = STATUS_SUCCESS;
430 ULONG BytesWritten = 0;
431 PHISTORY_BUFFER Hist;
432
433 if ( !CsrValidateMessageBuffer(ApiMessage,
434 (PVOID*)&GetCommandHistoryRequest->History,
435 GetCommandHistoryRequest->HistoryLength,
436 sizeof(BYTE)) ||
437 !CsrValidateMessageBuffer(ApiMessage,
438 (PVOID*)&GetCommandHistoryRequest->ExeName,
439 GetCommandHistoryRequest->ExeLength,
440 sizeof(BYTE)) )
441 {
442 return STATUS_INVALID_PARAMETER;
443 }
444
445 Hist = HistoryFindBuffer(Console,
446 GetCommandHistoryRequest->ExeName,
447 GetCommandHistoryRequest->ExeLength,
448 GetCommandHistoryRequest->Unicode2);
449 if (Hist)
450 {
451 ULONG i;
452
453 LPSTR TargetBufferA;
454 LPWSTR TargetBufferW;
455 ULONG BufferSize = GetCommandHistoryRequest->HistoryLength;
456
457 ULONG Offset = 0;
458 ULONG SourceLength;
459
460 if (GetCommandHistoryRequest->Unicode)
461 {
462 TargetBufferW = GetCommandHistoryRequest->History;
463 BufferSize /= sizeof(WCHAR);
464 }
465 else
466 {
467 TargetBufferA = GetCommandHistoryRequest->History;
468 }
469
470 for (i = 0; i < Hist->NumEntries; i++)
471 {
472 SourceLength = Hist->Entries[i].Length / sizeof(WCHAR);
473 if (Offset + SourceLength + 1 > BufferSize)
474 {
475 Status = STATUS_BUFFER_OVERFLOW;
476 break;
477 }
478
479 if (GetCommandHistoryRequest->Unicode)
480 {
481 RtlCopyMemory(&TargetBufferW[Offset], Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR));
482 Offset += SourceLength;
483 TargetBufferW[Offset++] = L'\0';
484 }
485 else
486 {
487 ConvertInputUnicodeToAnsi(Console,
488 Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR),
489 &TargetBufferA[Offset], SourceLength);
490 Offset += SourceLength;
491 TargetBufferA[Offset++] = '\0';
492 }
493 }
494
495 if (GetCommandHistoryRequest->Unicode)
496 BytesWritten = Offset * sizeof(WCHAR);
497 else
498 BytesWritten = Offset;
499 }
500
501 // GetCommandHistoryRequest->HistoryLength = TargetBuffer - (PBYTE)GetCommandHistoryRequest->History;
502 GetCommandHistoryRequest->HistoryLength = BytesWritten;
503
504 return Status;
505 }
506
507 /* API_NUMBER: ConsolepGetCommandHistoryLength */
CON_API(SrvGetConsoleCommandHistoryLength,CONSOLE_GETCOMMANDHISTORYLENGTH,GetCommandHistoryLengthRequest)508 CON_API(SrvGetConsoleCommandHistoryLength,
509 CONSOLE_GETCOMMANDHISTORYLENGTH, GetCommandHistoryLengthRequest)
510 {
511 PHISTORY_BUFFER Hist;
512 ULONG Length = 0;
513
514 if (!CsrValidateMessageBuffer(ApiMessage,
515 (PVOID*)&GetCommandHistoryLengthRequest->ExeName,
516 GetCommandHistoryLengthRequest->ExeLength,
517 sizeof(BYTE)))
518 {
519 return STATUS_INVALID_PARAMETER;
520 }
521
522 Hist = HistoryFindBuffer(Console,
523 GetCommandHistoryLengthRequest->ExeName,
524 GetCommandHistoryLengthRequest->ExeLength,
525 GetCommandHistoryLengthRequest->Unicode2);
526 if (Hist)
527 {
528 ULONG i;
529 for (i = 0; i < Hist->NumEntries; i++)
530 Length += Hist->Entries[i].Length + sizeof(WCHAR); // Each entry is returned NULL-terminated
531 }
532 /*
533 * Quick and dirty way of getting the number of bytes of the
534 * corresponding ANSI string from the one in UNICODE.
535 */
536 if (!GetCommandHistoryLengthRequest->Unicode)
537 Length /= sizeof(WCHAR);
538
539 GetCommandHistoryLengthRequest->HistoryLength = Length;
540
541 return STATUS_SUCCESS;
542 }
543
544 /* API_NUMBER: ConsolepExpungeCommandHistory */
CON_API(SrvExpungeConsoleCommandHistory,CONSOLE_EXPUNGECOMMANDHISTORY,ExpungeCommandHistoryRequest)545 CON_API(SrvExpungeConsoleCommandHistory,
546 CONSOLE_EXPUNGECOMMANDHISTORY, ExpungeCommandHistoryRequest)
547 {
548 PHISTORY_BUFFER Hist;
549
550 if (!CsrValidateMessageBuffer(ApiMessage,
551 (PVOID*)&ExpungeCommandHistoryRequest->ExeName,
552 ExpungeCommandHistoryRequest->ExeLength,
553 sizeof(BYTE)))
554 {
555 return STATUS_INVALID_PARAMETER;
556 }
557
558 Hist = HistoryFindBuffer(Console,
559 ExpungeCommandHistoryRequest->ExeName,
560 ExpungeCommandHistoryRequest->ExeLength,
561 ExpungeCommandHistoryRequest->Unicode2);
562 HistoryDeleteBuffer(Hist);
563
564 return STATUS_SUCCESS;
565 }
566
567 /* API_NUMBER: ConsolepSetNumberOfCommands */
CON_API(SrvSetConsoleNumberOfCommands,CONSOLE_SETHISTORYNUMBERCOMMANDS,SetHistoryNumberCommandsRequest)568 CON_API(SrvSetConsoleNumberOfCommands,
569 CONSOLE_SETHISTORYNUMBERCOMMANDS, SetHistoryNumberCommandsRequest)
570 {
571 NTSTATUS Status = STATUS_SUCCESS;
572 PHISTORY_BUFFER Hist;
573
574 if (!CsrValidateMessageBuffer(ApiMessage,
575 (PVOID*)&SetHistoryNumberCommandsRequest->ExeName,
576 SetHistoryNumberCommandsRequest->ExeLength,
577 sizeof(BYTE)))
578 {
579 return STATUS_INVALID_PARAMETER;
580 }
581
582 Hist = HistoryFindBuffer(Console,
583 SetHistoryNumberCommandsRequest->ExeName,
584 SetHistoryNumberCommandsRequest->ExeLength,
585 SetHistoryNumberCommandsRequest->Unicode2);
586 if (Hist)
587 {
588 Status = HistoryResizeBuffer(Hist, SetHistoryNumberCommandsRequest->NumCommands);
589 }
590
591 return Status;
592 }
593
594 /* API_NUMBER: ConsolepGetHistory */
CON_API_NOCONSOLE(SrvGetConsoleHistory,CONSOLE_GETSETHISTORYINFO,HistoryInfoRequest)595 CON_API_NOCONSOLE(SrvGetConsoleHistory,
596 CONSOLE_GETSETHISTORYINFO, HistoryInfoRequest)
597 {
598 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
599 NTSTATUS Status;
600 PCONSRV_CONSOLE Console;
601
602 Status = ConSrvGetConsole(ProcessData,
603 &Console, TRUE);
604 if (!NT_SUCCESS(Status))
605 return Status;
606
607 HistoryInfoRequest->HistoryBufferSize = Console->HistoryBufferSize;
608 HistoryInfoRequest->NumberOfHistoryBuffers = Console->MaxNumberOfHistoryBuffers;
609 HistoryInfoRequest->dwFlags = (Console->HistoryNoDup ? HISTORY_NO_DUP_FLAG : 0);
610
611 ConSrvReleaseConsole(Console, TRUE);
612 return Status;
613 #else
614 DPRINT1("%s not yet implemented\n", __FUNCTION__);
615 return STATUS_NOT_IMPLEMENTED;
616 #endif
617 }
618
619 /* API_NUMBER: ConsolepSetHistory */
CON_API_NOCONSOLE(SrvSetConsoleHistory,CONSOLE_GETSETHISTORYINFO,HistoryInfoRequest)620 CON_API_NOCONSOLE(SrvSetConsoleHistory,
621 CONSOLE_GETSETHISTORYINFO, HistoryInfoRequest)
622 {
623 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
624 NTSTATUS Status;
625 PCONSRV_CONSOLE Console;
626
627 Status = ConSrvGetConsole(ProcessData,
628 &Console, TRUE);
629 if (!NT_SUCCESS(Status))
630 return Status;
631
632 HistoryReshapeAllBuffers(Console,
633 HistoryInfoRequest->HistoryBufferSize,
634 HistoryInfoRequest->NumberOfHistoryBuffers,
635 !!(HistoryInfoRequest->dwFlags & HISTORY_NO_DUP_FLAG));
636
637 ConSrvReleaseConsole(Console, TRUE);
638 return STATUS_SUCCESS;
639 #else
640 DPRINT1("%s not yet implemented\n", __FUNCTION__);
641 return STATUS_NOT_IMPLEMENTED;
642 #endif
643 }
644
645 /* API_NUMBER: ConsolepSetCommandHistoryMode */
CON_API(SrvSetConsoleCommandHistoryMode,CONSOLE_SETHISTORYMODE,SetHistoryModeRequest)646 CON_API(SrvSetConsoleCommandHistoryMode,
647 CONSOLE_SETHISTORYMODE, SetHistoryModeRequest)
648 {
649 DPRINT("SrvSetConsoleCommandHistoryMode(Mode = %d) is not yet implemented\n",
650 SetHistoryModeRequest->Mode);
651
652 Console->InsertMode = !!(SetHistoryModeRequest->Mode & CONSOLE_OVERSTRIKE);
653 return STATUS_SUCCESS;
654 }
655
656 /* EOF */
657