00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
#include "precomp.h"
00040
#pragma hdrstop
00041
00042 #define CTRL_BUT_NOT_ALT(n) \
00043
(((n) & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && \
00044
!((n) & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))
00045
00046
00047
00048
00049
00050
00051
00052 UINT ProgmanHandleMessage;
00053
00054 int DialogBoxCount;
00055
00056 LPTHREAD_START_ROUTINE
CtrlRoutine;
00057
00058 DWORD InputThreadTlsIndex;
00059
00060 #define MAX_CHARS_FROM_1_KEYSTROKE 6
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #define CONSOLE_FREE_KEY_INFO 0
00072 #define CONSOLE_MAX_KEY_INFO 32
00073
00074 typedef struct _CONSOLE_KEY_INFO {
00075 HWND
hWnd;
00076 WORD
wVirtualKeyCode;
00077 WORD
wVirtualScanCode;
00078 }
CONSOLE_KEY_INFO, *
PCONSOLE_KEY_INFO;
00079
00080 CONSOLE_KEY_INFO ConsoleKeyInfo[
CONSOLE_MAX_KEY_INFO];
00081
00082
VOID
00083
UserExitWorkerThread(VOID);
00084
00085
BOOL
00086
InitWindowClass( VOID );
00087
00088
#if !defined(FE_SB)
00089
NTSTATUS
00090
ReadBuffer(
00091 IN
PINPUT_INFORMATION InputInformation,
00092 OUT PVOID Buffer,
00093 IN ULONG Length,
00094 OUT PULONG EventsRead,
00095 IN BOOL Peek,
00096 IN BOOL StreamRead,
00097 OUT PBOOL ResetWaitEvent
00098 );
00099
#endif
00100
00101
00102
NTSTATUS
00103 CreateInputBuffer(
00104 IN ULONG NumberOfEvents OPTIONAL,
00105 IN
PINPUT_INFORMATION InputBufferInformation
00106 #
if defined(FE_SB)
00107 ,
00108 IN
PCONSOLE_INFORMATION Console
00109 #endif
00110 )
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 {
00131 ULONG
BufferSize;
00132
NTSTATUS Status;
00133
00134
if (NumberOfEvents == 0) {
00135 NumberOfEvents =
DEFAULT_NUMBER_OF_EVENTS;
00136 }
00137
00138
00139
00140
BufferSize =
sizeof(INPUT_RECORD) * (NumberOfEvents+1);
00141 InputBufferInformation->InputBuffer = (PINPUT_RECORD)
ConsoleHeapAlloc(
MAKE_TAG(
BUFFER_TAG ),
BufferSize);
00142
if (InputBufferInformation->InputBuffer ==
NULL) {
00143
return STATUS_NO_MEMORY;
00144 }
00145
Status =
NtCreateEvent(&InputBufferInformation->InputWaitEvent,
00146 EVENT_ALL_ACCESS,
NULL, NotificationEvent,
FALSE);
00147
if (!
NT_SUCCESS(
Status)) {
00148
ConsoleHeapFree(InputBufferInformation->InputBuffer);
00149
return STATUS_NO_MEMORY;
00150 }
00151 InitializeListHead(&InputBufferInformation->ReadWaitQueue);
00152
00153
00154
00155 InputBufferInformation->InputBufferSize = NumberOfEvents;
00156 InputBufferInformation->ShareAccess.OpenCount = 0;
00157 InputBufferInformation->ShareAccess.Readers = 0;
00158 InputBufferInformation->ShareAccess.Writers = 0;
00159 InputBufferInformation->ShareAccess.SharedRead = 0;
00160 InputBufferInformation->ShareAccess.SharedWrite = 0;
00161 InputBufferInformation->InputMode = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
00162 InputBufferInformation->AllocatedBufferSize =
BufferSize;
00163 InputBufferInformation->RefCount = 0;
00164 InputBufferInformation->First = (ULONG_PTR) InputBufferInformation->InputBuffer;
00165 InputBufferInformation->In = (ULONG_PTR) InputBufferInformation->InputBuffer;
00166 InputBufferInformation->Out = (ULONG_PTR) InputBufferInformation->InputBuffer;
00167 InputBufferInformation->Last = (ULONG_PTR) InputBufferInformation->InputBuffer +
BufferSize;
00168
#if defined(FE_SB)
00169
#if defined(FE_IME)
00170
InputBufferInformation->ImeMode.Disable =
FALSE;
00171 InputBufferInformation->ImeMode.Unavailable =
FALSE;
00172 InputBufferInformation->ImeMode.Open =
FALSE;
00173 InputBufferInformation->ImeMode.ReadyConversion =
FALSE;
00174
#endif // FE_IME
00175
InputBufferInformation->Console = Console;
00176 RtlZeroMemory(&InputBufferInformation->ReadConInpDbcsLeadByte,
sizeof(INPUT_RECORD));
00177 RtlZeroMemory(&InputBufferInformation->WriteConInpDbcsLeadByte,
sizeof(INPUT_RECORD));
00178
#endif
00179
00180
return STATUS_SUCCESS;
00181 }
00182
00183
NTSTATUS
00184 ReinitializeInputBuffer(
00185 OUT
PINPUT_INFORMATION InputBufferInformation
00186 )
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 {
00208
NtClearEvent(InputBufferInformation->InputWaitEvent);
00209 InputBufferInformation->ShareAccess.OpenCount = 0;
00210 InputBufferInformation->ShareAccess.Readers = 0;
00211 InputBufferInformation->ShareAccess.Writers = 0;
00212 InputBufferInformation->ShareAccess.SharedRead = 0;
00213 InputBufferInformation->ShareAccess.SharedWrite = 0;
00214 InputBufferInformation->InputMode = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
00215 InputBufferInformation->In = (ULONG_PTR) InputBufferInformation->InputBuffer;
00216 InputBufferInformation->Out = (ULONG_PTR) InputBufferInformation->InputBuffer;
00217
return STATUS_SUCCESS;
00218 }
00219
00220
VOID
00221 FreeInputBuffer(
00222 IN
PINPUT_INFORMATION InputBufferInformation
00223 )
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 {
00241
ASSERT(InputBufferInformation->RefCount == 0);
00242 CloseHandle(InputBufferInformation->InputWaitEvent);
00243
ConsoleHeapFree(InputBufferInformation->InputBuffer);
00244 }
00245
00246
00247
NTSTATUS
00248 WaitForMoreToRead(
00249 IN
PINPUT_INFORMATION InputInformation,
00250 IN PCSR_API_MSG Message OPTIONAL,
00251 IN CSR_WAIT_ROUTINE WaitRoutine OPTIONAL,
00252 IN PVOID WaitParameter OPTIONAL,
00253 IN ULONG WaitParameterLength OPTIONAL,
00254 IN BOOLEAN WaitBlockExists OPTIONAL
00255 )
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 {
00289 PVOID WaitParameterBuffer;
00290
00291
if (!WaitBlockExists) {
00292 WaitParameterBuffer = (PVOID)
ConsoleHeapAlloc(
MAKE_TAG(
WAIT_TAG ),WaitParameterLength);
00293
if (WaitParameterBuffer ==
NULL) {
00294
return STATUS_NO_MEMORY;
00295 }
00296 RtlCopyMemory(WaitParameterBuffer,WaitParameter,WaitParameterLength);
00297
#if defined(FE_SB)
00298
if (WaitParameterLength ==
sizeof(
COOKED_READ_DATA) &&
00299 InputInformation->Console->lpCookedReadData == WaitParameter) {
00300 InputInformation->Console->lpCookedReadData = WaitParameterBuffer;
00301 }
00302
#endif
00303
if (!CsrCreateWait(&InputInformation->ReadWaitQueue,
00304 WaitRoutine,
00305 CSR_SERVER_QUERYCLIENTTHREAD(),
00306 Message,
00307 WaitParameterBuffer,
00308
NULL
00309 )) {
00310
ConsoleHeapFree(WaitParameterBuffer);
00311
#if defined(FE_SB)
00312
InputInformation->Console->lpCookedReadData =
NULL;
00313
#endif
00314
return STATUS_NO_MEMORY;
00315 }
00316 }
00317
return CONSOLE_STATUS_WAIT;
00318 }
00319
00320
00321
VOID
00322 WakeUpReadersWaitingForData(
00323 IN
PCONSOLE_INFORMATION Console,
00324
PINPUT_INFORMATION InputInformation
00325 )
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 {
00346 BOOLEAN WaitSatisfied;
00347 WaitSatisfied = CsrNotifyWait(&InputInformation->
ReadWaitQueue,
00348
FALSE,
00349
NULL,
00350
NULL
00351 );
00352
if (WaitSatisfied) {
00353
00354
ASSERT ((Console->WaitQueue ==
NULL) ||
00355 (Console->WaitQueue == &InputInformation->
ReadWaitQueue));
00356 Console->WaitQueue = &InputInformation->
ReadWaitQueue;
00357 }
00358 }
00359
00360
00361
NTSTATUS
00362 GetNumberOfReadyEvents(
00363 IN
PINPUT_INFORMATION InputInformation,
00364 OUT PULONG NumberOfEvents
00365 )
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 {
00388
if (InputInformation->In < InputInformation->Out) {
00389 *NumberOfEvents = (ULONG)(InputInformation->Last - InputInformation->Out);
00390 *NumberOfEvents += (ULONG)(InputInformation->In - InputInformation->First);
00391 }
00392
else {
00393 *NumberOfEvents = (ULONG)(InputInformation->In - InputInformation->Out);
00394 }
00395 *NumberOfEvents /=
sizeof(INPUT_RECORD);
00396
00397
return STATUS_SUCCESS;
00398 }
00399
00400
NTSTATUS
00401 FlushAllButKeys(
00402
PINPUT_INFORMATION InputInformation
00403 )
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 {
00424 ULONG NumberOfEventsRead,i;
00425
NTSTATUS Status;
00426 PINPUT_RECORD TmpInputBuffer,InPtr,TmpInputBufferPtr;
00427 ULONG
BufferSize;
00428
BOOL Dummy;
00429
00430
if (InputInformation->
In != InputInformation->
Out) {
00431
00432
00433
00434
00435
00436
BufferSize =
sizeof(INPUT_RECORD) * (InputInformation->
InputBufferSize+1);
00437 TmpInputBuffer = (PINPUT_RECORD)
ConsoleHeapAlloc(
MAKE_TAG(
TMP_TAG ),
BufferSize);
00438
if (TmpInputBuffer ==
NULL) {
00439
return STATUS_NO_MEMORY;
00440 }
00441 TmpInputBufferPtr = TmpInputBuffer;
00442
00443
00444
00445
00446
00447
00448
Status =
ReadBuffer(InputInformation,
00449 TmpInputBuffer,
00450 InputInformation->
InputBufferSize,
00451 &NumberOfEventsRead,
00452
TRUE,
00453
FALSE,
00454 &Dummy
00455 #
if defined(FE_SB)
00456 ,
00457
TRUE
00458 #endif
00459 );
00460
00461
if (!
NT_SUCCESS(
Status)) {
00462
ConsoleHeapFree(TmpInputBuffer);
00463
return Status;
00464 }
00465
00466 InputInformation->
Out = (ULONG_PTR) InputInformation->
InputBuffer;
00467 InPtr = InputInformation->
InputBuffer;
00468
for (i=0;i<NumberOfEventsRead;i++) {
00469
if (TmpInputBuffer->EventType == KEY_EVENT) {
00470 *InPtr = *TmpInputBuffer;
00471 InPtr++;
00472 }
00473 TmpInputBuffer++;
00474 }
00475 InputInformation->
In = (ULONG_PTR) InPtr;
00476
if (InputInformation->
In == InputInformation->
Out) {
00477
NtClearEvent(InputInformation->
InputWaitEvent);
00478 }
00479
ConsoleHeapFree(TmpInputBufferPtr);
00480 }
00481
return STATUS_SUCCESS;
00482 }
00483
00484
NTSTATUS
00485 FlushInputBuffer(
00486
PINPUT_INFORMATION InputInformation
00487 )
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 {
00508 InputInformation->
In = (ULONG_PTR) InputInformation->
InputBuffer;
00509 InputInformation->
Out = (ULONG_PTR) InputInformation->
InputBuffer;
00510
NtClearEvent(InputInformation->
InputWaitEvent);
00511
return STATUS_SUCCESS;
00512 }
00513
00514
00515
NTSTATUS
00516 SetInputBufferSize(
00517 IN
PINPUT_INFORMATION InputInformation,
00518 IN ULONG Size
00519 )
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 {
00542 ULONG NumberOfEventsRead;
00543
NTSTATUS Status;
00544 PINPUT_RECORD InputBuffer;
00545 ULONG
BufferSize;
00546
BOOL Dummy;
00547
00548
#if DBG
00549
ULONG_PTR NumberOfEvents;
00550
if (InputInformation->In < InputInformation->Out) {
00551 NumberOfEvents = InputInformation->Last - InputInformation->Out;
00552 NumberOfEvents += InputInformation->In - InputInformation->First;
00553 }
00554
else {
00555 NumberOfEvents = InputInformation->In - InputInformation->Out;
00556 }
00557 NumberOfEvents /=
sizeof(INPUT_RECORD);
00558
#endif
00559
ASSERT(
Size > InputInformation->InputBufferSize );
00560
00561
00562
00563
00564
00565
BufferSize =
sizeof(INPUT_RECORD) * (
Size+1);
00566 InputBuffer = (PINPUT_RECORD)
ConsoleHeapAlloc(
MAKE_TAG(
BUFFER_TAG ),
BufferSize);
00567
if (InputBuffer ==
NULL) {
00568
return STATUS_NO_MEMORY;
00569 }
00570
00571
00572
00573
00574
00575
00576
Status =
ReadBuffer(InputInformation,
00577 InputBuffer,
00578
Size,
00579 &NumberOfEventsRead,
00580
TRUE,
00581
FALSE,
00582 &Dummy
00583 #
if defined(FE_SB)
00584 ,
00585
TRUE
00586 #endif
00587 );
00588
00589
if (!
NT_SUCCESS(
Status)) {
00590
ConsoleHeapFree(InputBuffer);
00591
return Status;
00592 }
00593 InputInformation->Out = (ULONG_PTR)InputBuffer;
00594 InputInformation->In = (ULONG_PTR)InputBuffer +
sizeof(INPUT_RECORD) * NumberOfEventsRead;
00595
00596
00597
00598
00599
00600 InputInformation->First = (ULONG_PTR) InputBuffer;
00601 InputInformation->Last = (ULONG_PTR) InputBuffer +
BufferSize;
00602
00603
00604
00605
00606
00607
ConsoleHeapFree(InputInformation->InputBuffer);
00608 InputInformation->InputBufferSize =
Size;
00609 InputInformation->AllocatedBufferSize =
BufferSize;
00610 InputInformation->InputBuffer = InputBuffer;
00611
return Status;
00612 }
00613
00614
00615
NTSTATUS
00616 ReadBuffer(
00617 IN
PINPUT_INFORMATION InputInformation,
00618 OUT PVOID Buffer,
00619 IN ULONG Length,
00620 OUT PULONG EventsRead,
00621 IN BOOL Peek,
00622 IN BOOL StreamRead,
00623 OUT PBOOL ResetWaitEvent
00624 #ifdef FE_SB
00625 , IN BOOLEAN Unicode
00626 #endif
00627 )
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 {
00663 ULONG TransferLength,OldTransferLength;
00664 ULONG BufferLengthInBytes;
00665
#ifdef FE_SB
00666
PCONSOLE_INFORMATION Console;
00667 ULONG Length2;
00668 PINPUT_RECORD BufferRecords;
00669 PINPUT_RECORD QueueRecords;
00670 WCHAR UniChar;
00671 WORD EventType;
00672
#endif
00673
00674
#ifdef FE_SB
00675
Console = InputInformation->Console;
00676
#endif
00677
*ResetWaitEvent =
FALSE;
00678
00679
00680
00681
00682
00683
00684
00685
00686
if (StreamRead &&
00687 ((PINPUT_RECORD)(InputInformation->Out))->EventType == KEY_EVENT) {
00688
00689
ASSERT(Length == 1);
00690
ASSERT(InputInformation->In != InputInformation->Out);
00691 RtlMoveMemory((
PBYTE)
Buffer,
00692 (
PBYTE)InputInformation->Out,
00693
sizeof(INPUT_RECORD)
00694 );
00695 InputInformation->Out +=
sizeof(INPUT_RECORD);
00696
if (InputInformation->Last == InputInformation->Out) {
00697 InputInformation->Out = InputInformation->First;
00698 }
00699
if (InputInformation->Out == InputInformation->In) {
00700 *ResetWaitEvent =
TRUE;
00701 }
00702 *EventsRead = 1;
00703
return STATUS_SUCCESS;
00704 }
00705
00706 BufferLengthInBytes = Length *
sizeof(INPUT_RECORD);
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
if (InputInformation->In > InputInformation->Out) {
00721
if ((InputInformation->In - InputInformation->Out) > BufferLengthInBytes) {
00722 TransferLength = BufferLengthInBytes;
00723 }
00724
else {
00725 TransferLength = (ULONG)(InputInformation->In - InputInformation->Out);
00726 }
00727
#ifdef FE_SB
00728
if (!
Unicode) {
00729 BufferLengthInBytes = 0;
00730 OldTransferLength = TransferLength /
sizeof(INPUT_RECORD);
00731 BufferRecords = (PINPUT_RECORD)
Buffer;
00732 QueueRecords = (PINPUT_RECORD)InputInformation->Out;
00733
00734
while (BufferLengthInBytes < Length &&
00735 OldTransferLength) {
00736 UniChar = QueueRecords->Event.KeyEvent.uChar.UnicodeChar;
00737 EventType = QueueRecords->EventType;
00738 *BufferRecords++ = *QueueRecords++;
00739
if (EventType == KEY_EVENT) {
00740
if (IsConsoleFullWidth(Console->
hDC,
00741 Console->
CP,
00742 UniChar)) {
00743 BufferLengthInBytes += 2;
00744 }
00745
else {
00746 BufferLengthInBytes++;
00747 }
00748 }
00749
else {
00750 BufferLengthInBytes++;
00751 }
00752 OldTransferLength--;
00753 }
00754
ASSERT(TransferLength >= OldTransferLength *
sizeof(INPUT_RECORD));
00755 TransferLength -= OldTransferLength *
sizeof(INPUT_RECORD);
00756 }
00757
else
00758
#endif
00759
{
00760 RtlMoveMemory((
PBYTE)
Buffer,
00761 (
PBYTE)InputInformation->Out,
00762 TransferLength
00763 );
00764 }
00765 *EventsRead = TransferLength /
sizeof(INPUT_RECORD);
00766
#ifdef FE_SB
00767
ASSERT(*EventsRead <= Length);
00768
#endif
00769
if (!Peek) {
00770 InputInformation->Out += TransferLength;
00771
#ifdef FE_SB
00772
ASSERT(InputInformation->Out <= InputInformation->Last);
00773
#endif
00774
}
00775
if (InputInformation->Out == InputInformation->In) {
00776 *ResetWaitEvent =
TRUE;
00777 }
00778
return STATUS_SUCCESS;
00779 }
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
else {
00796
00797
if ((InputInformation->Last - InputInformation->Out) > BufferLengthInBytes) {
00798 TransferLength = BufferLengthInBytes;
00799 }
00800
else {
00801 TransferLength = (ULONG)(InputInformation->Last - InputInformation->Out);
00802 }
00803
#ifdef FE_SB
00804
if (!
Unicode) {
00805 BufferLengthInBytes = 0;
00806 OldTransferLength = TransferLength /
sizeof(INPUT_RECORD);
00807 BufferRecords = (PINPUT_RECORD)
Buffer;
00808 QueueRecords = (PINPUT_RECORD)InputInformation->Out;
00809
00810
while (BufferLengthInBytes < Length &&
00811 OldTransferLength) {
00812 UniChar = QueueRecords->Event.KeyEvent.uChar.UnicodeChar;
00813 EventType = QueueRecords->EventType;
00814 *BufferRecords++ = *QueueRecords++;
00815
if (EventType == KEY_EVENT) {
00816
if (IsConsoleFullWidth(Console->
hDC,
00817 Console->
CP,
00818 UniChar)) {
00819 BufferLengthInBytes += 2;
00820 }
00821
else {
00822 BufferLengthInBytes++;
00823 }
00824 }
00825
else {
00826 BufferLengthInBytes++;
00827 }
00828 OldTransferLength--;
00829 }
00830
ASSERT(TransferLength >= OldTransferLength *
sizeof(INPUT_RECORD));
00831 TransferLength -= OldTransferLength *
sizeof(INPUT_RECORD);
00832 }
00833
else
00834
#endif
00835
{
00836 RtlMoveMemory((
PBYTE)
Buffer,
00837 (
PBYTE)InputInformation->Out,
00838 TransferLength
00839 );
00840 }
00841 *EventsRead = TransferLength /
sizeof(INPUT_RECORD);
00842
#ifdef FE_SB
00843
ASSERT(*EventsRead <= Length);
00844
#endif
00845
00846
if (!Peek) {
00847 InputInformation->Out += TransferLength;
00848
#ifdef FE_SB
00849
ASSERT(InputInformation->Out <= InputInformation->Last);
00850
#endif
00851
if (InputInformation->Out == InputInformation->Last) {
00852 InputInformation->Out = InputInformation->First;
00853 }
00854 }
00855
#ifdef FE_SB
00856
if (!
Unicode) {
00857
if (BufferLengthInBytes >= Length) {
00858
if (InputInformation->Out == InputInformation->In) {
00859 *ResetWaitEvent =
TRUE;
00860 }
00861
return STATUS_SUCCESS;
00862 }
00863 }
00864
else
00865
#endif
00866
if (*EventsRead == Length) {
00867
if (InputInformation->Out == InputInformation->In) {
00868 *ResetWaitEvent =
TRUE;
00869 }
00870
return STATUS_SUCCESS;
00871 }
00872
00873
00874
00875
00876
00877 OldTransferLength = TransferLength;
00878
#ifdef FE_SB
00879
Length2 = Length;
00880
if (!
Unicode) {
00881
ASSERT(Length > BufferLengthInBytes);
00882 Length -= BufferLengthInBytes;
00883
if (Length == 0) {
00884
if (InputInformation->Out == InputInformation->In) {
00885 *ResetWaitEvent =
TRUE;
00886 }
00887
return STATUS_SUCCESS;
00888 }
00889 BufferLengthInBytes = Length *
sizeof(INPUT_RECORD);
00890
00891
if ((InputInformation->In - InputInformation->First) > BufferLengthInBytes) {
00892 TransferLength = BufferLengthInBytes;
00893 }
00894
else {
00895 TransferLength = (ULONG)(InputInformation->In - InputInformation->First);
00896 }
00897 }
00898
else
00899
#endif
00900
if ((InputInformation->In - InputInformation->First) > (BufferLengthInBytes - OldTransferLength)) {
00901 TransferLength = BufferLengthInBytes - OldTransferLength;
00902 }
00903
else {
00904 TransferLength = (ULONG)(InputInformation->In - InputInformation->First);
00905 }
00906
#ifdef FE_SB
00907
if (!
Unicode) {
00908 BufferLengthInBytes = 0;
00909 OldTransferLength = TransferLength /
sizeof(INPUT_RECORD);
00910 QueueRecords = (PINPUT_RECORD)InputInformation->First;
00911
00912
while (BufferLengthInBytes < Length &&
00913 OldTransferLength) {
00914 UniChar = QueueRecords->Event.KeyEvent.uChar.UnicodeChar;
00915 EventType = QueueRecords->EventType;
00916 *BufferRecords++ = *QueueRecords++;
00917
if (EventType == KEY_EVENT) {
00918
if (IsConsoleFullWidth(Console->
hDC,
00919 Console->
CP,
00920 UniChar)) {
00921 BufferLengthInBytes += 2;
00922 }
00923
else {
00924 BufferLengthInBytes++;
00925 }
00926 }
00927
else {
00928 BufferLengthInBytes++;
00929 }
00930 OldTransferLength--;
00931 }
00932
ASSERT(TransferLength >= OldTransferLength *
sizeof(INPUT_RECORD));
00933 TransferLength -= OldTransferLength *
sizeof(INPUT_RECORD);
00934 }
00935
else
00936
#endif
00937
{
00938 RtlMoveMemory((
PBYTE)
Buffer+OldTransferLength,
00939 (
PBYTE)InputInformation->First,
00940 TransferLength
00941 );
00942 }
00943 *EventsRead += TransferLength /
sizeof(INPUT_RECORD);
00944
#ifdef FE_SB
00945
ASSERT(*EventsRead <= Length2);
00946
#endif
00947
if (!Peek) {
00948 InputInformation->Out = InputInformation->First + TransferLength;
00949 }
00950
if (InputInformation->Out == InputInformation->In) {
00951 *ResetWaitEvent =
TRUE;
00952 }
00953
return STATUS_SUCCESS;
00954 }
00955 }
00956
00957
00958
NTSTATUS
00959 ReadInputBuffer(
00960 IN
PINPUT_INFORMATION InputInformation,
00961 OUT PINPUT_RECORD lpBuffer,
00962 IN OUT PDWORD nLength,
00963 IN BOOL Peek,
00964 IN BOOL WaitForData,
00965 IN BOOL StreamRead,
00966 IN
PCONSOLE_INFORMATION Console,
00967 IN
PHANDLE_DATA HandleData OPTIONAL,
00968 IN PCSR_API_MSG Message OPTIONAL,
00969 IN CSR_WAIT_ROUTINE WaitRoutine OPTIONAL,
00970 IN PVOID WaitParameter OPTIONAL,
00971 IN ULONG WaitParameterLength OPTIONAL,
00972 IN BOOLEAN WaitBlockExists OPTIONAL
00973 #
if defined(FE_SB)
00974 ,
00975 IN BOOLEAN Unicode
00976 #endif
00977 )
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027 {
01028 ULONG EventsRead;
01029
NTSTATUS Status;
01030
BOOL ResetWaitEvent;
01031
01032
if (InputInformation->In == InputInformation->Out) {
01033
if (!WaitForData) {
01034 *nLength = 0;
01035
return STATUS_SUCCESS;
01036 }
01037
LockReadCount(HandleData);
01038 HandleData->InputReadData->ReadCount += 1;
01039
UnlockReadCount(HandleData);
01040
Status =
WaitForMoreToRead(InputInformation,
01041 Message,
01042 WaitRoutine,
01043 WaitParameter,
01044 WaitParameterLength,
01045 WaitBlockExists
01046 );
01047
01048
if (!
NT_SUCCESS(
Status)) {
01049
if (
Status !=
CONSOLE_STATUS_WAIT) {
01050
01051
01052
01053
LockReadCount(HandleData);
01054 HandleData->InputReadData->ReadCount -= 1;
01055
UnlockReadCount(HandleData);
01056 }
01057 *nLength = 0;
01058
return Status;
01059 }
01060
01061
01062
01063
01064
ASSERT(
FALSE);
01065
01066
LockConsole(Console);
01067 }
01068
01069
01070
01071
01072
01073
Status =
ReadBuffer(InputInformation,
01074 lpBuffer,
01075 *nLength,
01076 &EventsRead,
01077 Peek,
01078 StreamRead,
01079 &ResetWaitEvent
01080 #
if defined(FE_SB)
01081 ,
01082
Unicode
01083 #endif
01084 );
01085
if (ResetWaitEvent) {
01086
NtClearEvent(InputInformation->InputWaitEvent);
01087 }
01088
01089 *nLength = EventsRead;
01090
return Status;
01091 }
01092
01093
01094
NTSTATUS
01095 WriteBuffer(
01096 OUT
PINPUT_INFORMATION InputInformation,
01097 IN PVOID Buffer,
01098 IN ULONG Length,
01099 OUT PULONG EventsWritten,
01100 OUT PBOOL SetWaitEvent
01101 )
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 {
01133
NTSTATUS Status;
01134 ULONG TransferLength;
01135 ULONG BufferLengthInBytes;
01136
#if defined(FE_SB)
01137
PCONSOLE_INFORMATION Console = InputInformation->Console;
01138
#endif
01139
01140 *SetWaitEvent =
FALSE;
01141
01142
01143
01144
01145
01146
01147
if (Length == 1 && InputInformation->Out != InputInformation->In) {
01148 PINPUT_RECORD InputEvent=
Buffer;
01149
01150
if (InputEvent->EventType == MOUSE_EVENT &&
01151 InputEvent->Event.MouseEvent.dwEventFlags == MOUSE_MOVED) {
01152 PINPUT_RECORD LastInputEvent;
01153
01154
if (InputInformation->In == InputInformation->First) {
01155 LastInputEvent = (PINPUT_RECORD) (InputInformation->Last -
sizeof(INPUT_RECORD));
01156 }
01157
else {
01158 LastInputEvent = (PINPUT_RECORD) (InputInformation->In -
sizeof(INPUT_RECORD));
01159 }
01160
if (LastInputEvent->EventType == MOUSE_EVENT &&
01161 LastInputEvent->Event.MouseEvent.dwEventFlags == MOUSE_MOVED) {
01162 LastInputEvent->Event.MouseEvent.dwMousePosition.X =
01163 InputEvent->Event.MouseEvent.dwMousePosition.X;
01164 LastInputEvent->Event.MouseEvent.dwMousePosition.Y =
01165 InputEvent->Event.MouseEvent.dwMousePosition.Y;
01166 *EventsWritten = 1;
01167
return STATUS_SUCCESS;
01168 }
01169 }
01170
else if (InputEvent->EventType == KEY_EVENT &&
01171 InputEvent->Event.KeyEvent.bKeyDown) {
01172 PINPUT_RECORD LastInputEvent;
01173
if (InputInformation->In == InputInformation->First) {
01174 LastInputEvent = (PINPUT_RECORD) (InputInformation->Last -
sizeof(INPUT_RECORD));
01175 }
01176
else {
01177 LastInputEvent = (PINPUT_RECORD) (InputInformation->In -
sizeof(INPUT_RECORD));
01178 }
01179
#if defined(FE_SB)
01180
if (IsConsoleFullWidth(Console->
hDC,
01181 Console->
CP,InputEvent->Event.KeyEvent.uChar.UnicodeChar)) {
01182 ;
01183 }
01184
else
01185
if (InputEvent->Event.KeyEvent.dwControlKeyState & NLS_IME_CONVERSION) {
01186
if (LastInputEvent->EventType == KEY_EVENT &&
01187 LastInputEvent->Event.KeyEvent.bKeyDown &&
01188 (LastInputEvent->Event.KeyEvent.uChar.UnicodeChar ==
01189 InputEvent->Event.KeyEvent.uChar.UnicodeChar) &&
01190 (LastInputEvent->Event.KeyEvent.dwControlKeyState ==
01191 InputEvent->Event.KeyEvent.dwControlKeyState) ) {
01192 LastInputEvent->Event.KeyEvent.wRepeatCount +=
01193 InputEvent->Event.KeyEvent.wRepeatCount;
01194 *EventsWritten = 1;
01195
return STATUS_SUCCESS;
01196 }
01197 }
01198
else
01199
#endif
01200
if (LastInputEvent->EventType == KEY_EVENT &&
01201 LastInputEvent->Event.KeyEvent.bKeyDown &&
01202 (LastInputEvent->Event.KeyEvent.wVirtualScanCode ==
01203 InputEvent->Event.KeyEvent.wVirtualScanCode) &&
01204 (LastInputEvent->Event.KeyEvent.uChar.UnicodeChar ==
01205 InputEvent->Event.KeyEvent.uChar.UnicodeChar) &&
01206 (LastInputEvent->Event.KeyEvent.dwControlKeyState ==
01207 InputEvent->Event.KeyEvent.dwControlKeyState) ) {
01208 LastInputEvent->Event.KeyEvent.wRepeatCount +=
01209 InputEvent->Event.KeyEvent.wRepeatCount;
01210 *EventsWritten = 1;
01211
return STATUS_SUCCESS;
01212 }
01213 }
01214 }
01215
01216 BufferLengthInBytes = Length*
sizeof(INPUT_RECORD);
01217 *EventsWritten = 0;
01218
while (*EventsWritten < Length) {
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
if (InputInformation->Out > InputInformation->In) {
01234 TransferLength = BufferLengthInBytes;
01235
if ((InputInformation->Out - InputInformation->In -
sizeof(INPUT_RECORD))
01236 < BufferLengthInBytes) {
01237
Status =
SetInputBufferSize(InputInformation,
01238 InputInformation->InputBufferSize+Length+
INPUT_BUFFER_SIZE_INCREMENT);
01239
if (!
NT_SUCCESS(
Status)) {
01240 KdPrint((
"CONSRV: Couldn't grow input buffer, Status == %lX\n",
Status));
01241 TransferLength = (ULONG)(InputInformation->Out - InputInformation->In -
sizeof(INPUT_RECORD));
01242
if (TransferLength == 0) {
01243
return Status;
01244 }
01245 }
else {
01246
goto OutPath;
01247 }
01248 }
01249 RtlMoveMemory((
PBYTE)InputInformation->In,
01250 (
PBYTE)
Buffer,
01251 TransferLength
01252 );
01253
Buffer = (PVOID) (((
PBYTE)
Buffer)+TransferLength);
01254 *EventsWritten += TransferLength/
sizeof(INPUT_RECORD);
01255 BufferLengthInBytes -= TransferLength;
01256 InputInformation->In += TransferLength;
01257 }
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
else {
01274
if (InputInformation->Out == InputInformation->In) {
01275 *SetWaitEvent =
TRUE;
01276 }
01277 OutPath:
01278
if ((InputInformation->Last - InputInformation->In) > BufferLengthInBytes) {
01279 TransferLength = BufferLengthInBytes;
01280 }
01281
else {
01282
if (InputInformation->First == InputInformation->Out &&
01283 InputInformation->In == (InputInformation->Last-
sizeof(INPUT_RECORD))) {
01284 TransferLength = BufferLengthInBytes;
01285
Status =
SetInputBufferSize(InputInformation,
01286 InputInformation->InputBufferSize+Length+
INPUT_BUFFER_SIZE_INCREMENT);
01287
if (!
NT_SUCCESS(
Status)) {
01288 KdPrint((
"CONSRV: Couldn't grow input buffer, Status == %lX\n",
Status));
01289
return Status;
01290 }
01291 }
01292
else {
01293 TransferLength = (ULONG)(InputInformation->Last - InputInformation->In);
01294
if (InputInformation->First == InputInformation->Out) {
01295 TransferLength -=
sizeof(INPUT_RECORD);
01296 }
01297 }
01298 }
01299 RtlMoveMemory((
PBYTE)InputInformation->In,
01300 (
PBYTE)
Buffer,
01301 TransferLength
01302 );
01303
Buffer = (PVOID) (((
PBYTE)
Buffer)+TransferLength);
01304 *EventsWritten += TransferLength/
sizeof(INPUT_RECORD);
01305 BufferLengthInBytes -= TransferLength;
01306 InputInformation->In += TransferLength;
01307
if (InputInformation->In == InputInformation->Last) {
01308 InputInformation->In = InputInformation->First;
01309 }
01310 }
01311
if (TransferLength == 0) {
01312
ASSERT (
FALSE);
01313 }
01314 }
01315
return STATUS_SUCCESS;
01316 }
01317
01318
01319 __inline
BOOL
01320 IsSystemKey(
01321 WORD wVirtualKeyCode
01322 )
01323 {
01324
switch (wVirtualKeyCode) {
01325
case VK_SHIFT:
01326
case VK_CONTROL:
01327
case VK_MENU:
01328
case VK_PAUSE:
01329
case VK_CAPITAL:
01330
case VK_LWIN:
01331
case VK_RWIN:
01332
case VK_NUMLOCK:
01333
case VK_SCROLL:
01334
return TRUE;
01335 }
01336
return FALSE;
01337 }
01338
01339
DWORD
01340 PreprocessInput(
01341 IN
PCONSOLE_INFORMATION Console,
01342 IN PINPUT_RECORD InputEvent,
01343 IN DWORD nLength
01344 )
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370 {
01371 ULONG NumEvents;
01372
01373
01374
for (NumEvents = nLength; NumEvents != 0; NumEvents--) {
01375
if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown) {
01376
01377
01378
01379
01380
if ((Console->Flags &
CONSOLE_SUSPENDED) &&
01381 !
IsSystemKey(InputEvent->Event.KeyEvent.wVirtualKeyCode)) {
01382
01383
UnblockWriteConsole(Console,
CONSOLE_OUTPUT_SUSPENDED);
01384 RtlMoveMemory(InputEvent, InputEvent + 1, (NumEvents - 1) *
sizeof(INPUT_RECORD));
01385 nLength--;
01386
continue;
01387 }
01388
01389
01390
01391
01392
01393
if ((Console->InputBuffer.InputMode & ENABLE_LINE_INPUT) &&
01394 (InputEvent->Event.KeyEvent.wVirtualKeyCode == VK_PAUSE ||
01395
IsPauseKey(&InputEvent->Event.KeyEvent))) {
01396
01397 Console->Flags |=
CONSOLE_OUTPUT_SUSPENDED;
01398 RtlMoveMemory(InputEvent, InputEvent + 1, (NumEvents - 1) *
sizeof(INPUT_RECORD));
01399 nLength--;
01400
continue;
01401 }
01402 }
01403 InputEvent++;
01404 }
01405
return nLength;
01406 }
01407
01408
01409
DWORD
01410 PrependInputBuffer(
01411 IN
PCONSOLE_INFORMATION Console,
01412 IN
PINPUT_INFORMATION InputInformation,
01413 IN PINPUT_RECORD lpBuffer,
01414 IN DWORD nLength
01415 )
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 {
01441
NTSTATUS Status;
01442 ULONG EventsWritten,EventsRead;
01443
BOOL SetWaitEvent;
01444 ULONG NumExistingEvents;
01445 PINPUT_RECORD pExistingEvents;
01446
BOOL Dummy;
01447
01448 nLength =
PreprocessInput(Console, lpBuffer, nLength);
01449
if (nLength == 0) {
01450
return 0;
01451 }
01452
01453
Status =
GetNumberOfReadyEvents(InputInformation,
01454 &NumExistingEvents
01455 );
01456
01457
if (NumExistingEvents) {
01458
01459 pExistingEvents =
ConsoleHeapAlloc(
MAKE_TAG(
BUFFER_TAG ),NumExistingEvents *
sizeof(INPUT_RECORD));
01460
if (pExistingEvents ==
NULL)
01461
return (
DWORD)STATUS_NO_MEMORY;
01462
Status =
ReadBuffer(InputInformation,
01463 pExistingEvents,
01464 NumExistingEvents,
01465 &EventsRead,
01466
FALSE,
01467
FALSE,
01468 &Dummy
01469 #
if defined(FE_SB)
01470 ,
01471
TRUE
01472 #endif
01473 );
01474
01475
if (!
NT_SUCCESS(
Status)) {
01476
ConsoleHeapFree(pExistingEvents);
01477
return Status;
01478 }
01479 }
else {
01480 pExistingEvents =
NULL;
01481 }
01482
01483
01484
01485
01486
01487
Status =
WriteBuffer(InputInformation,
01488 lpBuffer,
01489 nLength,
01490 &EventsWritten,
01491 &SetWaitEvent
01492 );
01493
01494
01495
01496
01497
01498
if (pExistingEvents) {
01499
Status =
WriteBuffer(InputInformation,
01500 pExistingEvents,
01501 EventsRead,
01502 &EventsWritten,
01503 &Dummy
01504 );
01505
ConsoleHeapFree(pExistingEvents);
01506 }
01507
01508
if (SetWaitEvent) {
01509
NtSetEvent(InputInformation->InputWaitEvent,
NULL);
01510 }
01511
01512
01513
01514
01515
01516
WakeUpReadersWaitingForData(Console,InputInformation);
01517
01518
return nLength;
01519 }
01520
01521
DWORD
01522 WriteInputBuffer(
01523 IN
PCONSOLE_INFORMATION Console,
01524 IN
PINPUT_INFORMATION InputInformation,
01525 IN PINPUT_RECORD lpBuffer,
01526 IN DWORD nLength
01527 )
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552 {
01553 ULONG EventsWritten;
01554
BOOL SetWaitEvent;
01555
01556 nLength =
PreprocessInput(Console, lpBuffer, nLength);
01557
if (nLength == 0) {
01558
return 0;
01559 }
01560
01561
01562
01563
01564
01565
WriteBuffer(InputInformation,
01566 lpBuffer,
01567 nLength,
01568 &EventsWritten,
01569 &SetWaitEvent
01570 );
01571
01572
if (SetWaitEvent) {
01573
NtSetEvent(InputInformation->InputWaitEvent,
NULL);
01574 }
01575
01576
01577
01578
01579
01580
WakeUpReadersWaitingForData(Console,InputInformation);
01581
01582
01583
return EventsWritten;
01584 }
01585
01586
VOID
01587 StoreKeyInfo(
01588 IN PMSG msg
01589 )
01590 {
01591
int i;
01592
01593
for (i=0;i<
CONSOLE_MAX_KEY_INFO;i++) {
01594
if (
ConsoleKeyInfo[i].
hWnd ==
CONSOLE_FREE_KEY_INFO ||
01595
ConsoleKeyInfo[i].
hWnd ==
msg->hwnd) {
01596
break;
01597 }
01598 }
01599
if (i!=
CONSOLE_MAX_KEY_INFO) {
01600
ConsoleKeyInfo[i].
hWnd =
msg->hwnd;
01601
ConsoleKeyInfo[i].
wVirtualKeyCode = LOWORD(
msg->wParam);
01602
ConsoleKeyInfo[i].
wVirtualScanCode = (
BYTE)(HIWORD(
msg->lParam));
01603 }
else {
01604 KdPrint((
"CONSRV: ConsoleKeyInfo buffer is full\n"));
01605 }
01606 }
01607
01608
VOID
01609 RetrieveKeyInfo(
01610 IN HWND hWnd,
01611 OUT PWORD pwVirtualKeyCode,
01612 OUT PWORD pwVirtualScanCode,
01613 IN BOOL FreeKeyInfo
01614 )
01615 {
01616
int i;
01617
01618
for (i=0;i<
CONSOLE_MAX_KEY_INFO;i++) {
01619
if (
ConsoleKeyInfo[i].
hWnd ==
hWnd) {
01620
break;
01621 }
01622 }
01623
if (i!=
CONSOLE_MAX_KEY_INFO) {
01624 *pwVirtualKeyCode =
ConsoleKeyInfo[i].
wVirtualKeyCode;
01625 *pwVirtualScanCode =
ConsoleKeyInfo[i].
wVirtualScanCode;
01626
if (FreeKeyInfo)
01627
ConsoleKeyInfo[i].
hWnd =
CONSOLE_FREE_KEY_INFO;
01628 }
else {
01629 *pwVirtualKeyCode = (WORD)
MapVirtualKey(*pwVirtualScanCode, 3);
01630 }
01631 }
01632
01633
VOID
01634 ClearKeyInfo(
01635 IN HWND hWnd
01636 )
01637 {
01638
int i;
01639
01640
for (i=0;i<
CONSOLE_MAX_KEY_INFO;i++) {
01641
if (
ConsoleKeyInfo[i].
hWnd ==
hWnd) {
01642
ConsoleKeyInfo[i].
hWnd =
CONSOLE_FREE_KEY_INFO;
01643 }
01644 }
01645 }
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
VOID
01657 ProcessCreateConsoleWindow(
01658 IN LPMSG lpMsg
01659 )
01660 {
01661
NTSTATUS Status;
01662
01663
PCONSOLE_INFORMATION pConsole;
01664
01665
if (
NT_SUCCESS(
RevalidateConsole((HANDLE)lpMsg->wParam, &pConsole))) {
01666
01667
01668
01669
01670
01671
if (pConsole->
hWnd) {
01672 RIPMSG1(RIP_WARNING,
"Console %#p already has a window", pConsole);
01673
UnlockConsole(pConsole);
01674
return;
01675 }
01676
01677 pConsole->
InputThreadInfo = TlsGetValue(
InputThreadTlsIndex);
01678
DBGPRINT((
"Before CreateWindowsWindow cWindows = %d\n",
01679 pConsole->
InputThreadInfo->
WindowCount));
01680
01681
Status =
CreateWindowsWindow(pConsole);
01682
DBGPRINT((
"After CreateWindowsWindow cWindows = %d\n",
01683 pConsole->
InputThreadInfo->
WindowCount));
01684
switch (
Status) {
01685
case STATUS_SUCCESS:
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
if ((pConsole->
Flags &
CONSOLE_DEFAULT_BUFFER_SIZE) && (
DialogBoxCount < 8)) {
01696 WCHAR ItemString[120];
01697 WCHAR Title[120];
01698 HWND
hWnd = pConsole->
hWnd;
01699 ULONG TitleLength =
min(
sizeof(Title)-
sizeof(WCHAR), pConsole->
TitleLength);
01700 RtlCopyMemory(Title, pConsole->
Title, TitleLength);
01701 Title[TitleLength/
sizeof(WCHAR)] = 0;
01702
UnlockConsole(pConsole);
01703 LoadString(
ghInstance,
msgBufferTooBig,ItemString,
NELEM(ItemString));
01704
DialogBoxCount++;
01705 MessageBox(
hWnd, ItemString, Title, MB_OK);
01706
DialogBoxCount--;
01707
break;
01708 }
01709
01710
case STATUS_NO_MEMORY:
01711
UnlockConsole(pConsole);
01712
break;
01713
case STATUS_INVALID_HANDLE:
01714
01715
break;
01716
default:
01717 KdPrint((
"CONSRV: CreateWindowsWindow returned %x\n",
Status));
01718
ASSERT(
FALSE);
01719
break;
01720 }
01721 }
01722 }
01723
01724
01725 LRESULT
01726 DialogHookProc(
01727
int nCode,
01728 WPARAM wParam,
01729 LPARAM lParam
01730 )
01731
01732
01733
01734
01735 {
01736 MSG *pmsg = (PMSG)lParam;
01737
01738 UNREFERENCED_PARAMETER(wParam);
01739
01740
if (pmsg->message ==
CM_CREATE_CONSOLE_WINDOW) {
01741
ProcessCreateConsoleWindow(pmsg);
01742
return TRUE;
01743 }
01744
01745
if (
CONSOLE_IS_IME_ENABLED()) {
01746
if (pmsg->message ==
CM_CONSOLE_INPUT_THREAD_MSG) {
01747
PINPUT_THREAD_INFO pThreadInfo = TlsGetValue(
InputThreadTlsIndex);
01748 MSG
msg;
01749
01750
ASSERT(pThreadInfo);
01751
01752
if (
UnqueueThreadMessage(pThreadInfo->
ThreadId, &
msg.message, &
msg.wParam, &
msg.lParam)) {
01753 RIPMSG3(RIP_WARNING,
"DialogHookProc: %04x (%08x, %08x)",
msg.message,
msg.wParam,
msg.lParam);
01754
switch (
msg.message) {
01755
case CM_CONIME_CREATE:
01756 ProcessCreateConsoleIME(&
msg, pThreadInfo->
ThreadId);
01757
return TRUE;
01758
case CM_WAIT_CONIME_PROCESS:
01759 WaitConsoleIMEStuff((HDESK)
msg.wParam, (HANDLE)
msg.lParam);
01760
return TRUE;
01761
case CM_SET_CONSOLEIME_WINDOW:
01762 pThreadInfo->hWndConsoleIME = (HWND)
msg.wParam;
01763
return TRUE;
01764
default:
01765 RIPMSG1(RIP_WARNING,
"DialogHookProc: invalid thread message(%04x) !!",
msg.message);
01766
break;
01767 }
01768 }
01769
else {
01770 RIPMSG0(RIP_WARNING,
"DialogHookProc: bogus thread message is posted. ignored");
01771 }
01772 }
01773 }
01774
01775
if (nCode == MSGF_DIALOGBOX) {
01776
if (pmsg->message >= WM_KEYFIRST &&
01777 pmsg->message <= WM_KEYLAST) {
01778
if (pmsg->message != WM_CHAR &&
01779 pmsg->message != WM_DEADCHAR &&
01780 pmsg->message != WM_SYSCHAR &&
01781 pmsg->message != WM_SYSDEADCHAR) {
01782
01783
01784
if (
GetWindowLongPtr(pmsg->hwnd, GWLP_HWNDPARENT) == 0) {
01785
StoreKeyInfo(pmsg);
01786 }
01787 }
01788 }
01789 }
01790
return 0;
01791 }
01792
01793
#undef DbgPrint // Need this to build on free systems
01794
01795 ULONG
InputExceptionFilter(
01796 PEXCEPTION_POINTERS pexi)
01797 {
01798
NTSTATUS Status;
01799 SYSTEM_KERNEL_DEBUGGER_INFORMATION KernelDebuggerInfo;
01800
01801
if (pexi->ExceptionRecord->ExceptionCode != STATUS_PORT_DISCONNECTED) {
01802
Status =
NtQuerySystemInformation( SystemKernelDebuggerInformation,
01803 &KernelDebuggerInfo,
01804
sizeof(KernelDebuggerInfo),
01805
NULL
01806 );
01807
01808
if (
NT_SUCCESS(
Status) && KernelDebuggerInfo.KernelDebuggerEnabled) {
01809
DbgPrint(
"Unhandled Exception hit in csrss.exe InputExceptionFilter\n");
01810
DbgPrint(
"first, enter !exr %p for the exception record\n", pexi->ExceptionRecord);
01811
DbgPrint(
"next, enter !cxr %p for the context\n", pexi->ContextRecord);
01812
DbgPrint(
"then !kb to get the faulting stack\n");
01813 DbgBreakPoint();
01814 }
01815 }
01816
01817
return EXCEPTION_EXECUTE_HANDLER;
01818 }
01819
01821
01822
01824
01825 LIST_ENTRY
gInputThreadMsg;
01826 CRITICAL_SECTION
gInputThreadMsgLock;
01827
01828
VOID
01829 InitializeThreadMessages()
01830 {
01831 RtlEnterCriticalSection(&
gInputThreadMsgLock);
01832 InitializeListHead(&
gInputThreadMsg);
01833 RtlLeaveCriticalSection(&
gInputThreadMsgLock);
01834 }
01835
01836
VOID
01837 CleanupInputThreadMessages(
01838 DWORD dwThreadId)
01839 {
01840
UINT message;
01841 WPARAM wParam;
01842 LPARAM lParam;
01843
01844
ASSERT(dwThreadId);
01845
01846
while (
UnqueueThreadMessage(dwThreadId, &message, &wParam, &lParam)) {
01847 RIPMSG3(RIP_WARNING,
"CleanupInputThreadMessages: %04x (%08x, %08x)", message, wParam, lParam);
01848 }
01849 }
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
NTSTATUS
01860 QueueThreadMessage(
01861 DWORD dwThreadId,
01862 UINT message,
01863 WPARAM wParam,
01864 LPARAM lParam)
01865 {
01866
PCONSOLE_THREAD_MSG pConMsg;
01867
01868
01869 RIPMSG4(RIP_VERBOSE,
"QueueThreadMessage: TID=%08x msg:%04x (%08x, %08x)",
01870 dwThreadId, message, wParam, lParam);
01871
01872 pConMsg =
ConsoleHeapAlloc(
MAKE_TAG(
TMP_TAG),
sizeof *pConMsg);
01873
if (pConMsg ==
NULL) {
01874 RIPMSG0(RIP_WARNING,
"QueueThreadMessage: failed to allocate pConMsg");
01875
return STATUS_NO_MEMORY;
01876 }
01877
01878 pConMsg->dwThreadId = dwThreadId;
01879 pConMsg->Message = message;
01880 pConMsg->wParam = wParam;
01881 pConMsg->lParam = lParam;
01882
01883 RtlEnterCriticalSection(&
gInputThreadMsgLock);
01884 InsertHeadList(&
gInputThreadMsg, &pConMsg->ListLink);
01885 RtlLeaveCriticalSection(&
gInputThreadMsgLock);
01886
01887
if (!
PostThreadMessage(dwThreadId,
CM_CONSOLE_INPUT_THREAD_MSG, 0, 0)) {
01888 RIPMSG1(RIP_WARNING,
"QueueThreadMessage: failed to post thread msg(%04x)", message);
01889 RtlEnterCriticalSection(&
gInputThreadMsgLock);
01890 RemoveEntryList(&pConMsg->ListLink);
01891 RtlLeaveCriticalSection(&
gInputThreadMsgLock);
01892
ConsoleHeapFree(pConMsg);
01893
return STATUS_UNSUCCESSFUL;
01894 }
01895
01896
return STATUS_SUCCESS;
01897 }
01898
01899
01900
01901
01902
01903
01904
01905
01906 BOOL UnqueueThreadMessage(
01907 DWORD dwThreadId,
01908 UINT* pMessage,
01909 WPARAM* pwParam,
01910 LPARAM* plParam)
01911 {
01912
BOOL fResult =
FALSE;
01913 PLIST_ENTRY pEntry;
01914
01915
ASSERT(dwThreadId);
01916
01917 RtlEnterCriticalSection(&
gInputThreadMsgLock);
01918
01919
01920
01921
01922 pEntry =
gInputThreadMsg.Blink;
01923
01924
while (pEntry != &
gInputThreadMsg) {
01925
PCONSOLE_THREAD_MSG pConMsg = CONTAINING_RECORD(pEntry,
CONSOLE_THREAD_MSG, ListLink);
01926
01927
if (pConMsg->
dwThreadId == dwThreadId) {
01928 *pMessage = pConMsg->Message;
01929 *pwParam = pConMsg->wParam;
01930 *plParam = pConMsg->lParam;
01931
01932 RemoveEntryList(pEntry);
01933
ConsoleHeapFree(pConMsg);
01934 fResult =
TRUE;
01935
break;
01936 }
01937 pEntry = pEntry->Blink;
01938 }
01939
01940 RtlLeaveCriticalSection(&
gInputThreadMsgLock);
01941
01942
return fResult;
01943 }
01944
01945
VOID
01946 ConsoleInputThread(
01947
PINPUT_THREAD_INIT_INFO pInputThreadInitInfo)
01948 {
01949 MSG
msg;
01950 PTEB Teb;
01951 PCSR_THREAD pcsrt =
NULL;
01952
INPUT_THREAD_INFO ThreadInfo;
01953
int i;
01954 HANDLE hThread =
NULL;
01955 HHOOK hhook =
NULL;
01956
BOOL fQuit =
FALSE;
01957 CONSOLEDESKTOPCONSOLETHREAD ConsoleDesktopInfo;
01958
NTSTATUS Status;
01959
01960
01961
01962
01963
01964 Teb = NtCurrentTeb();
01965
01966
try {
01967
01968
01969
01970
01971
01972
01973
01974
01975 ThreadInfo.
Desktop = pInputThreadInitInfo->
DesktopHandle;
01976 ThreadInfo.
WindowCount = 0;
01977 ThreadInfo.
ThreadHandle = pInputThreadInitInfo->
ThreadHandle;
01978 ThreadInfo.
ThreadId = HandleToUlong(Teb->ClientId.UniqueThread);
01979
#if defined(FE_IME)
01980
ThreadInfo.hWndConsoleIME =
NULL;
01981
#endif
01982
TlsSetValue(
InputThreadTlsIndex, &ThreadInfo);
01983 ConsoleDesktopInfo.hdesk = pInputThreadInitInfo->
DesktopHandle;
01984 ConsoleDesktopInfo.dwThreadId = HandleToUlong(Teb->ClientId.UniqueThread);
01985
Status =
NtUserConsoleControl(ConsoleDesktopConsoleThread, &ConsoleDesktopInfo,
01986
sizeof(ConsoleDesktopInfo));
01987
if (
NT_SUCCESS(
Status)) {
01988
01989
01990
01991
01992
01993
01994 pcsrt = CsrConnectToUser();
01995
if (pcsrt ==
NULL ||
01996 !SetThreadDesktop(pInputThreadInitInfo->
DesktopHandle)) {
01997
Status = STATUS_UNSUCCESSFUL;
01998 }
else {
01999
02000
02001
02002
02003
02004 hThread = pcsrt->ThreadHandle;
02005
02006
if (!
fOneTimeInitialized) {
02007
02008
InitializeCustomCP();
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
EnumerateFonts(
EF_DEFFACE);
02019
02020
InitializeScreenInfo();
02021
02022
if (!
InitWindowClass())
02023
Status = STATUS_UNSUCCESSFUL;
02024
02025
for (i=0;i<
CONSOLE_MAX_KEY_INFO;i++) {
02026
ConsoleKeyInfo[i].
hWnd =
CONSOLE_FREE_KEY_INFO;
02027 }
02028
02029
ProgmanHandleMessage =
RegisterWindowMessage(TEXT(CONSOLE_PROGMAN_HANDLE_MESSAGE));
02030 }
02031 }
02032 }
02033
02034
02035
02036
02037
02038
02039 pInputThreadInitInfo->
InitStatus =
Status;
02040
NtSetEvent(pInputThreadInitInfo->
InitCompleteEventHandle,
NULL);
02041
02042
if (!
NT_SUCCESS(
Status))
02043
RtlRaiseStatus(STATUS_PORT_DISCONNECTED);
02044
02045 hhook = SetWindowsHookEx(WH_MSGFILTER,
DialogHookProc,
NULL,
02046 HandleToUlong(Teb->ClientId.UniqueThread));
02047
02048
while (
TRUE) {
02049
02050
02051
02052
02053
02054
02055
if (fQuit && ThreadInfo.
WindowCount == 0)
02056
break;
02057
02058
02059
02060
02061
02062
ASSERT(NtCurrentTeb()->CountOfOwnedCriticalSections == 0);
02063
02064
GetMessage(&
msg,
NULL, 0, 0);
02065
02066
02067
02068
02069
02070
if (
msg.message ==
CM_CREATE_CONSOLE_WINDOW) {
02071
ProcessCreateConsoleWindow(&
msg);
02072
continue;
02073 }
else if (
msg.message == WM_QUIT) {
02074
02075
02076
02077
02078
02079
02080 fQuit =
TRUE;
02081
02082
02083
02084
02085
02086
if (ThreadInfo.
WindowCount == 0) {
02087
break;
02088 }
02089 KdPrint((
"WM_QUIT received by console with windows\n"));
02090
continue;
02091 }
02092
else if (
CONSOLE_IS_IME_ENABLED()) {
02093
if (
msg.message ==
CM_CONSOLE_INPUT_THREAD_MSG) {
02094 MSG
msg;
02095
02096
if (
UnqueueThreadMessage(ThreadInfo.
ThreadId, &
msg.message, &
msg.wParam, &
msg.lParam)) {
02097
02098 RIPMSG3(RIP_VERBOSE,
"InputThread: Unqueue: msg=%04x (%08x, %08x)",
02099
msg.message,
msg.wParam,
msg.lParam);
02100
switch (
msg.message) {
02101
case CM_CONIME_CREATE:
02102 ProcessCreateConsoleIME(&
msg, ThreadInfo.
ThreadId);
02103
continue;
02104
case CM_WAIT_CONIME_PROCESS:
02105 WaitConsoleIMEStuff((HDESK)
msg.wParam, (HANDLE)
msg.lParam);
02106
continue;
02107
case CM_SET_CONSOLEIME_WINDOW:
02108 ThreadInfo.hWndConsoleIME = (HWND)
msg.wParam;
02109
continue;
02110
default:
02111 RIPMSG1(RIP_WARNING,
"ConsoleInputThread: invalid thread message(%04x) !!",
msg.message);
02112
break;
02113 }
02114 }
02115
else {
02116 RIPMSG0(RIP_WARNING,
"ConsoleInputThread: bogus thread message is post. ignored");
02117
continue;
02118 }
02119 }
02120 }
02121
02122
if (!
TranslateMessageEx(&
msg, TM_POSTCHARBREAKS)) {
02123
DispatchMessage(&
msg);
02124 }
else {
02125
02126
if (
msg.message == WM_SYSKEYDOWN &&
02127
msg.wParam == VK_TAB &&
02128 (
msg.lParam & 0x20000000) ) {
02129
DispatchMessage(&
msg);
02130 }
else {
02131
StoreKeyInfo(&
msg);
02132 }
02133 }
02134 }
02135
02136
02137
02138
02139
CleanupInputThreadMessages(ThreadInfo.
ThreadId);
02140
02141
RtlRaiseStatus(STATUS_PORT_DISCONNECTED);
02142
02143 } except (
InputExceptionFilter(GetExceptionInformation())) {
02144
BOOL fSuccess;
02145
02146
02147
02148
02149
02150
if (hhook !=
NULL)
02151
UnhookWindowsHookEx(hhook);
02152 ConsoleDesktopInfo.dwThreadId = 0;
02153
NtUserConsoleControl(ConsoleDesktopConsoleThread,
02154 &ConsoleDesktopInfo,
sizeof(ConsoleDesktopInfo));
02155
02156
02157
02158
02159
02160
02161
02162 fSuccess = CloseDesktop(ThreadInfo.
Desktop);
02163
ASSERT(fSuccess);
02164
02165
02166
02167
02168
02169
if (hThread !=
NULL)
02170 pcsrt->ThreadHandle = hThread;
02171 }
02172
02173
if (pcsrt !=
NULL)
02174 CsrDereferenceThread(pcsrt);
02175
UserExitWorkerThread();
02176 }
02177
02178 ULONG
02179 GetControlKeyState(
02180 LPARAM lParam
02181 )
02182 {
02183 ULONG ControlKeyState=0;
02184
02185
if (
GetKeyState(VK_LMENU) &
KEY_PRESSED) {
02186 ControlKeyState |= LEFT_ALT_PRESSED;
02187 }
02188
if (
GetKeyState(VK_RMENU) &
KEY_PRESSED) {
02189 ControlKeyState |= RIGHT_ALT_PRESSED;
02190 }
02191
if (
GetKeyState(VK_LCONTROL) &
KEY_PRESSED) {
02192 ControlKeyState |= LEFT_CTRL_PRESSED;
02193 }
02194
if (
GetKeyState(VK_RCONTROL) &
KEY_PRESSED) {
02195 ControlKeyState |= RIGHT_CTRL_PRESSED;
02196 }
02197
if (
GetKeyState(VK_SHIFT) &
KEY_PRESSED) {
02198 ControlKeyState |= SHIFT_PRESSED;
02199 }
02200
if (
GetKeyState(VK_NUMLOCK) &
KEY_TOGGLED) {
02201 ControlKeyState |= NUMLOCK_ON;
02202 }
02203
if (
GetKeyState(
VK_OEM_SCROLL) &
KEY_TOGGLED) {
02204 ControlKeyState |= SCROLLLOCK_ON;
02205 }
02206
if (
GetKeyState(VK_CAPITAL) &
KEY_TOGGLED) {
02207 ControlKeyState |= CAPSLOCK_ON;
02208 }
02209
if (lParam &
KEY_ENHANCED) {
02210 ControlKeyState |= ENHANCED_KEY;
02211 }
02212 ControlKeyState |= (lParam & ALTNUMPAD_BIT);
02213
return ControlKeyState;
02214 }
02215
02216 ULONG
02217 ConvertMouseButtonState(
02218 IN ULONG Flag,
02219 IN ULONG State
02220 )
02221 {
02222
if (State & MK_LBUTTON) {
02223 Flag |= FROM_LEFT_1ST_BUTTON_PRESSED;
02224 }
02225
if (State & MK_MBUTTON) {
02226 Flag |= FROM_LEFT_2ND_BUTTON_PRESSED;
02227 }
02228
if (State & MK_RBUTTON) {
02229 Flag |= RIGHTMOST_BUTTON_PRESSED;
02230 }
02231
return Flag;
02232 }
02233
02234
VOID
02235 TerminateRead(
02236 IN
PCONSOLE_INFORMATION Console,
02237 IN
PINPUT_INFORMATION InputInfo,
02238 IN DWORD Flag
02239 )
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256 {
02257 BOOLEAN WaitSatisfied;
02258 WaitSatisfied = CsrNotifyWait(&InputInfo->ReadWaitQueue,
02259
TRUE,
02260
NULL,
02261 (PVOID)Flag
02262 );
02263
if (WaitSatisfied) {
02264
02265
ASSERT ((Console->WaitQueue ==
NULL) ||
02266 (Console->WaitQueue == &InputInfo->ReadWaitQueue));
02267 Console->WaitQueue = &InputInfo->ReadWaitQueue;
02268 }
02269 }
02270
02271
BOOL
02272 HandleSysKeyEvent(
02273 IN
PCONSOLE_INFORMATION Console,
02274 IN HWND hWnd,
02275 IN UINT Message,
02276 IN WPARAM wParam,
02277 IN LPARAM lParam
02278 )
02279
02280
02281
02282
02283
02284
02285
02286 {
02287 WORD VirtualKeyCode;
02288
BOOL bCtrlDown;
02289
02290
#if defined (FE_IME)
02291
02292
if (Message == WM_SYSCHAR || Message == WM_SYSDEADCHAR ||
02293 Message == WM_SYSCHAR+
CONIME_KEYDATA || Message == WM_SYSDEADCHAR+
CONIME_KEYDATA)
02294
#else
02295
if (Message == WM_SYSCHAR || Message == WM_SYSDEADCHAR)
02296
#endif
02297
{
02298 VirtualKeyCode = (WORD)
MapVirtualKey(
LOBYTE(HIWORD(lParam)), 1);
02299 }
else {
02300 VirtualKeyCode = LOWORD(wParam);
02301 }
02302
02303
02304
02305
02306 bCtrlDown =
GetKeyState(VK_CONTROL) &
KEY_PRESSED;
02307
02308
if (VirtualKeyCode == VK_ESCAPE &&
02309 bCtrlDown &&
02310 !(
GetKeyState(VK_MENU) &
KEY_PRESSED) &&
02311 !(
GetKeyState(VK_SHIFT) &
KEY_PRESSED) &&
02312 !(Console->ReserveKeys & CONSOLE_CTRLESC) ) {
02313
return TRUE;
02314 }
02315
02316
if ((lParam & 0x20000000) == 0) {
02317
02318
02319
02320
02321
02322
02323
if (VirtualKeyCode == VK_RETURN && !(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
02324
02325
return TRUE;
02326 }
else {
02327
HandleKeyEvent(Console,
02328
hWnd,
02329 Message,
02330 wParam,
02331 lParam
02332 );
02333
return FALSE;
02334 }
02335 }
02336
02337
if (VirtualKeyCode == VK_RETURN && !bCtrlDown &&
02338 !(Console->ReserveKeys & CONSOLE_ALTENTER)) {
02339
#ifdef i386
02340
if (!(Message &
KEY_UP_TRANSITION)) {
02341
if (
FullScreenInitialized) {
02342
if (Console->FullScreenFlags == 0) {
02343
ConvertToFullScreen(Console);
02344 Console->FullScreenFlags = CONSOLE_FULLSCREEN;
02345
02346
ChangeDispSettings(Console, Console->hWnd,CDS_FULLSCREEN);
02347 }
else {
02348
ConvertToWindowed(Console);
02349 Console->FullScreenFlags &= ~CONSOLE_FULLSCREEN;
02350
02351
ChangeDispSettings(Console, Console->hWnd,0);
02352
02353
ShowWindow(Console->hWnd, SW_RESTORE);
02354 }
02355 }
else {
02356 WCHAR ItemString[70];
02357 LoadString(
ghInstance,
msgNoFullScreen,ItemString,70);
02358 MessageBoxEx(Console->hWnd,
02359 ItemString,
02360 Console->Title,
02361 MB_SYSTEMMODAL | MB_OK,
02362 0
L
02363 );
02364 }
02365 }
02366
#endif
02367
return FALSE;
02368 }
02369
02370
02371
02372
02373
02374
02375
if (!(
GetKeyState(VK_CONTROL) &
KEY_PRESSED)) {
02376
if (VirtualKeyCode == VK_SPACE && !(Console->ReserveKeys & CONSOLE_ALTSPACE)) {
02377
return TRUE;
02378 }
02379
02380
if (VirtualKeyCode == VK_ESCAPE && !(Console->ReserveKeys & CONSOLE_ALTESC)) {
02381
return TRUE;
02382 }
02383
if (VirtualKeyCode == VK_TAB && !(Console->ReserveKeys & CONSOLE_ALTTAB)) {
02384
return TRUE;
02385 }
02386 }
02387
HandleKeyEvent(Console,
02388
hWnd,
02389 Message,
02390 wParam,
02391 lParam
02392 );
02393
return FALSE;
02394 }
02395
02396
VOID
02397 HandleKeyEvent(
02398 IN
PCONSOLE_INFORMATION Console,
02399 IN HWND hWnd,
02400 IN UINT Message,
02401 IN WPARAM wParam,
02402 IN LPARAM lParam
02403 )
02404 {
02405 INPUT_RECORD InputEvent;
02406 BOOLEAN ContinueProcessing;
02407 ULONG EventsWritten;
02408 WORD VirtualKeyCode;
02409 ULONG ControlKeyState;
02410
BOOL bKeyDown;
02411
BOOL bGenerateBreak=
FALSE;
02412
#ifdef FE_SB
02413
BOOL KeyMessageFromConsoleIME;
02414
#endif
02415
02416
#ifdef FE_SB
02417
02418
if ((WM_KEYFIRST+
CONIME_KEYDATA) <= Message && Message <= (WM_KEYLAST+
CONIME_KEYDATA)) {
02419 Message -=
CONIME_KEYDATA ;
02420 KeyMessageFromConsoleIME =
TRUE ;
02421 }
02422
else {
02423 KeyMessageFromConsoleIME =
FALSE ;
02424 }
02425
#endif
02426
02427
02428
02429 VirtualKeyCode = LOWORD(wParam);
02430 ControlKeyState =
GetControlKeyState(lParam);
02431 bKeyDown = !(lParam &
KEY_TRANSITION_UP);
02432
02433
02434
02435
02436
02437
02438 InputEvent.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
02439 InputEvent.Event.KeyEvent.wVirtualScanCode = (
BYTE)(HIWORD(lParam));
02440
if (Message == WM_CHAR || Message == WM_SYSCHAR ||
02441 Message == WM_DEADCHAR || Message == WM_SYSDEADCHAR) {
02442
RetrieveKeyInfo(
hWnd,
02443 &InputEvent.Event.KeyEvent.wVirtualKeyCode,
02444 &InputEvent.Event.KeyEvent.wVirtualScanCode,
02445 !(Console->InputBuffer.ImeMode.Open ^ KeyMessageFromConsoleIME));
02446 VirtualKeyCode = InputEvent.Event.KeyEvent.wVirtualKeyCode;
02447 }
02448
02449
02450
02451
02452
02453
02454
02455
02456
if (Console->Flags &
CONSOLE_IGNORE_NEXT_KEYUP) {
02457 Console->Flags &= ~
CONSOLE_IGNORE_NEXT_KEYUP;
02458
if (!bKeyDown)
02459
return;
02460 }
02461
02462
#ifdef FE_SB
02463
02464
if (KeyMessageFromConsoleIME) {
02465
goto FromConsoleIME ;
02466 }
02467
#endif
02468
02469
if (Console->Flags &
CONSOLE_SELECTING) {
02470
02471
if (!bKeyDown) {
02472
return;
02473 }
02474
02475
02476
02477
02478
02479
if (!(Console->SelectionFlags &
CONSOLE_MOUSE_DOWN) ) {
02480
if (VirtualKeyCode == VK_ESCAPE ||
02481 (VirtualKeyCode ==
'C' &&
02482 (
GetKeyState(VK_CONTROL) &
KEY_PRESSED) )) {
02483
ClearSelection(Console);
02484
return;
02485 }
else if (VirtualKeyCode == VK_RETURN) {
02486
02487
02488
02489
DoCopy(Console);
02490
return;
02491 }
02492 }
02493
if (!(Console->SelectionFlags &
CONSOLE_MOUSE_SELECTION)) {
02494
if ((Console->CurrentScreenBuffer->Flags &
CONSOLE_TEXTMODE_BUFFER) &&
02495 (VirtualKeyCode == VK_RIGHT ||
02496 VirtualKeyCode == VK_LEFT ||
02497 VirtualKeyCode == VK_UP ||
02498 VirtualKeyCode == VK_DOWN ||
02499 VirtualKeyCode == VK_NEXT ||
02500 VirtualKeyCode == VK_PRIOR ||
02501 VirtualKeyCode == VK_END ||
02502 VirtualKeyCode == VK_HOME
02503 ) ) {
02504
PSCREEN_INFORMATION ScreenInfo;
02505
#ifdef FE_SB
02506
SHORT RowIndex;
02507
PROW Row;
02508
BYTE KAttrs;
02509
SHORT NextRightX;
02510
SHORT NextLeftX;
02511
#endif
02512
02513 ScreenInfo = Console->CurrentScreenBuffer;
02514
02515
02516
02517
02518
02519
02520
02521
ConsoleHideCursor(ScreenInfo);
02522
#ifdef FE_SB
02523
RowIndex = (ScreenInfo->
BufferInfo.TextInfo.FirstRow+ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y) % ScreenInfo->
ScreenBufferSize.Y;
02524 Row = &ScreenInfo->
BufferInfo.TextInfo.Rows[RowIndex];
02525
02526
if (CONSOLE_IS_DBCS_OUTPUTCP(Console))
02527 {
02528 KAttrs = Row->
CharRow.KAttrs[ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X];
02529
if (KAttrs & ATTR_LEADING_BYTE)
02530 NextRightX = 2;
02531
else
02532 NextRightX = 1;
02533 }
02534
else
02535 {
02536 NextRightX = 1;
02537 }
02538
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X > 0) {
02539
if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
02540 KAttrs = Row->
CharRow.KAttrs[ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X-1];
02541
if (KAttrs & ATTR_TRAILING_BYTE)
02542 NextLeftX = 2;
02543
else if (KAttrs & ATTR_LEADING_BYTE) {
02544
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X-1 > 0) {
02545 KAttrs = Row->
CharRow.KAttrs[ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X-2];
02546
if (KAttrs & ATTR_TRAILING_BYTE)
02547 NextLeftX = 3;
02548
else
02549 NextLeftX = 2;
02550 }
02551
else
02552 NextLeftX = 1;
02553 }
02554
else
02555 NextLeftX = 1;
02556 }
02557
else
02558 NextLeftX = 1;
02559 }
02560
02561
switch (VirtualKeyCode) {
02562
case VK_RIGHT:
02563
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X+NextRightX < ScreenInfo->
ScreenBufferSize.X) {
02564 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X+=NextRightX;
02565 }
02566
break;
02567
case VK_LEFT:
02568
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X > 0) {
02569 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X-=NextLeftX;
02570 }
02571
break;
02572
case VK_UP:
02573
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y > 0) {
02574 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y-=1;
02575 }
02576
break;
02577
case VK_DOWN:
02578
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y+1 < ScreenInfo->
ScreenBufferSize.Y) {
02579 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y+=1;
02580 }
02581
break;
02582
case VK_NEXT:
02583 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y +=
CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-1;
02584
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y >= ScreenInfo->
ScreenBufferSize.Y) {
02585 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y = ScreenInfo->
ScreenBufferSize.Y-1;
02586 }
02587
break;
02588
case VK_PRIOR:
02589 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y -=
CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-1;
02590
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y < 0) {
02591 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y = 0;
02592 }
02593
break;
02594
case VK_END:
02595 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y = ScreenInfo->
ScreenBufferSize.Y-
CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
02596
break;
02597
case VK_HOME:
02598 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X = 0;
02599 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y = 0;
02600
break;
02601
default:
02602
ASSERT(
FALSE);
02603 }
02604
#else // FE_SB
02605
switch (VirtualKeyCode) {
02606
case VK_RIGHT:
02607
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X+1 < ScreenInfo->
ScreenBufferSize.X) {
02608 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X+=1;
02609 }
02610
break;
02611
case VK_LEFT:
02612
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X > 0) {
02613 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X-=1;
02614 }
02615
break;
02616
case VK_UP:
02617
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y > 0) {
02618 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y-=1;
02619 }
02620
break;
02621
case VK_DOWN:
02622
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y+1 < ScreenInfo->
ScreenBufferSize.Y) {
02623 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y+=1;
02624 }
02625
break;
02626
case VK_NEXT:
02627 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y +=
CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-1;
02628
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y >= ScreenInfo->
ScreenBufferSize.Y) {
02629 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y = ScreenInfo->
ScreenBufferSize.Y-1;
02630 }
02631
break;
02632
case VK_PRIOR:
02633 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y -=
CONSOLE_WINDOW_SIZE_Y(ScreenInfo)-1;
02634
if (ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y < 0) {
02635 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y = 0;
02636 }
02637
break;
02638
case VK_END:
02639 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y = ScreenInfo->
ScreenBufferSize.Y-
CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
02640
break;
02641
case VK_HOME:
02642 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.X = 0;
02643 ScreenInfo->
BufferInfo.TextInfo.CursorPosition.Y = 0;
02644
break;
02645
default:
02646
ASSERT(
FALSE);
02647 }
02648
#endif // FE_SB
02649
ConsoleShowCursor(ScreenInfo);
02650
if (
GetKeyState(VK_SHIFT) &
KEY_PRESSED) {
02651 {
02652
ExtendSelection(Console,ScreenInfo->
BufferInfo.TextInfo.CursorPosition);
02653 }
02654 }
else {
02655
if (Console->SelectionFlags &
CONSOLE_SELECTION_NOT_EMPTY) {
02656
MyInvert(Console,&Console->SelectionRect);
02657 Console->SelectionFlags &= ~
CONSOLE_SELECTION_NOT_EMPTY;
02658
ConsoleShowCursor(ScreenInfo);
02659 }
02660 Console->SelectionAnchor = ScreenInfo->
BufferInfo.TextInfo.CursorPosition;
02661
MakeCursorVisible(ScreenInfo,Console->SelectionAnchor);
02662 Console->SelectionRect.Left = Console->SelectionRect.Right = Console->SelectionAnchor.X;
02663 Console->SelectionRect.Top = Console->SelectionRect.Bottom = Console->SelectionAnchor.Y;
02664 }
02665
return;
02666 }
02667 }
else if (!(Console->SelectionFlags &
CONSOLE_MOUSE_DOWN)) {
02668
02669
02670
02671
02672
02673
if (!
IsSystemKey(VirtualKeyCode)) {
02674
ClearSelection(Console);
02675 }
02676 }
02677 }
else if (Console->Flags &
CONSOLE_SCROLLING) {
02678
02679
if (!bKeyDown) {
02680
return;
02681 }
02682
02683
02684
02685
02686
02687
if (VirtualKeyCode == VK_ESCAPE ||
02688 VirtualKeyCode == VK_RETURN ||
02689 (VirtualKeyCode ==
'C' &&
02690 (
GetKeyState(VK_CONTROL) &
KEY_PRESSED) )) {
02691
ClearScroll(Console);
02692 }
else {
02693 WORD ScrollCommand;
02694
BOOL Horizontal=
FALSE;
02695
switch (VirtualKeyCode) {
02696
case VK_UP:
02697 ScrollCommand = SB_LINEUP;
02698
break;
02699
case VK_DOWN:
02700 ScrollCommand = SB_LINEDOWN;
02701
break;
02702
case VK_LEFT:
02703 ScrollCommand = SB_LINEUP;
02704 Horizontal=
TRUE;
02705
break;
02706
case VK_RIGHT:
02707 ScrollCommand = SB_LINEDOWN;
02708 Horizontal=
TRUE;
02709
break;
02710
case VK_NEXT:
02711 ScrollCommand = SB_PAGEDOWN;
02712
break;
02713
case VK_PRIOR:
02714 ScrollCommand = SB_PAGEUP;
02715
break;
02716
case VK_END:
02717 ScrollCommand = SB_PAGEDOWN;
02718 Horizontal=
TRUE;
02719
break;
02720
case VK_HOME:
02721 ScrollCommand = SB_PAGEUP;
02722 Horizontal=
TRUE;
02723
break;
02724
case VK_SHIFT:
02725
case VK_CONTROL:
02726
case VK_MENU:
02727
return;
02728
default:
02729 Beep(800, 200);
02730
return;
02731 }
02732
if (Horizontal)
02733
HorizontalScroll(Console->CurrentScreenBuffer, ScrollCommand, 0);
02734
else
02735
VerticalScroll(Console, Console->CurrentScreenBuffer,ScrollCommand,0);
02736 }
02737
return;
02738 }
02739
02740
02741
02742
02743
02744
if ((Console->Flags & (
CONSOLE_SELECTING |
CONSOLE_SCROLLING |
CONSOLE_SCROLLBAR_TRACKING)) &&
02745 bKeyDown &&
02746 !
IsSystemKey(VirtualKeyCode)) {
02747 Beep(800, 200);
02748
return;
02749 }
02750
02751
02752
02753
02754
02755
#ifdef LATER
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
#endif
02778
02779
if (Message != WM_CHAR && Message != WM_SYSCHAR &&
02780 VirtualKeyCode == VK_SNAPSHOT &&
02781 !(Console->ReserveKeys & (CONSOLE_ALTPRTSC | CONSOLE_PRTSC )) ) {
02782
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
02783 Console->SelectionFlags |=
CONSOLE_SELECTION_NOT_EMPTY;
02784 Console->SelectionRect = Console->CurrentScreenBuffer->Window;
02785
StoreSelection(Console);
02786 Console->SelectionFlags &= ~
CONSOLE_SELECTION_NOT_EMPTY;
02787 }
02788
return;
02789 }
02790
02791
02792
02793
02794
if (!(Console->Flags &
CONSOLE_VDM_REGISTERED)) {
02795 LPARAM lParamForHotKey ;
02796
DWORD HotkeyID ;
02797 lParamForHotKey = lParam ;
02798
02799 HotkeyID =
NtUserCheckImeHotKey( (VirtualKeyCode & 0x00ff),lParamForHotKey) ;
02800
02801
02802
02803
02804
if (HotkeyID >= IME_HOTKEY_DSWITCH_FIRST && HotkeyID <= IME_HOTKEY_DSWITCH_LAST) {
02805
UINT uModifier, uVkey;
02806 HKL hkl;
02807
02808 RIPMSG1(RIP_VERBOSE,
"HandleKeyEvent: handling IME HOTKEY id=%x", HotkeyID);
02809
if (
NtUserGetImeHotKey(HotkeyID, &uModifier, &uVkey, &hkl) && hkl !=
NULL) {
02810
BYTE bCharSetSys =
CodePageToCharSet(GetACP());
02811 WPARAM wpSysChar = 0;
02812 CHARSETINFO cs;
02813
02814
if (TranslateCharsetInfo((LPDWORD)LOWORD(hkl), &cs, TCI_SRCLOCALE)) {
02815
if (bCharSetSys == cs.ciCharset) {
02816 wpSysChar = INPUTLANGCHANGE_SYSCHARSET;
02817 }
02818 }
02819
PostMessage(
hWnd, WM_INPUTLANGCHANGEREQUEST, wpSysChar, (LPARAM)hkl);
02820 }
02821
return;
02822 }
02823
02824
if (!(Console->InputBuffer.ImeMode.Disable) &&
CONSOLE_IS_IME_ENABLED()) {
02825
02826
if (HotkeyID != IME_INVALID_HOTKEY) {
02827
switch(HotkeyID) {
02828
case IME_JHOTKEY_CLOSE_OPEN:
02829 {
02830
BOOL fOpen = Console->InputBuffer.ImeMode.Open;
02831
if (!bKeyDown)
02832
break ;
02833
02834 Console->InputBuffer.ImeMode.Open = !fOpen ;
02835
if (!
NT_SUCCESS(ConsoleImeMessagePump(Console,
02836
CONIME_HOTKEY,
02837 (WPARAM)Console->ConsoleHandle,
02838 HotkeyID))) {
02839
break;
02840 }
02841
02842
02843 GetImeKeyState(Console,
NULL);
02844
02845
break ;
02846 }
02847
case IME_CHOTKEY_IME_NONIME_TOGGLE:
02848
case IME_THOTKEY_IME_NONIME_TOGGLE:
02849
case IME_CHOTKEY_SHAPE_TOGGLE:
02850
case IME_THOTKEY_SHAPE_TOGGLE:
02851
case IME_CHOTKEY_SYMBOL_TOGGLE:
02852
case IME_THOTKEY_SYMBOL_TOGGLE:
02853
case IME_KHOTKEY_SHAPE_TOGGLE:
02854
case IME_KHOTKEY_HANJACONVERT:
02855
case IME_KHOTKEY_ENGLISH:
02856
case IME_ITHOTKEY_RESEND_RESULTSTR:
02857
case IME_ITHOTKEY_PREVIOUS_COMPOSITION:
02858
case IME_ITHOTKEY_UISTYLE_TOGGLE:
02859
default:
02860 {
02861
if (!
NT_SUCCESS(ConsoleImeMessagePump(Console,
02862
CONIME_HOTKEY,
02863 (WPARAM)Console->ConsoleHandle,
02864 HotkeyID))) {
02865
break;
02866 }
02867
02868
02869 GetImeKeyState(Console,
NULL);
02870
02871
break ;
02872 }
02873 }
02874
return ;
02875 }
02876
02877
if (
CTRL_BUT_NOT_ALT(ControlKeyState) &&
02878 (bKeyDown) ) {
02879
if (VirtualKeyCode ==
'C' &&
02880 Console->InputBuffer.InputMode & ENABLE_PROCESSED_INPUT) {
02881
goto FromConsoleIME ;
02882 }
02883
else if (VirtualKeyCode == VK_CANCEL) {
02884
goto FromConsoleIME ;
02885 }
02886
else if (VirtualKeyCode ==
'S'){
02887
goto FromConsoleIME ;
02888 }
02889 }
02890
else if (VirtualKeyCode == VK_PAUSE ){
02891
goto FromConsoleIME ;
02892 }
02893
else if ( ((VirtualKeyCode == VK_SHIFT) ||
02894 (VirtualKeyCode == VK_CONTROL) ||
02895 (VirtualKeyCode == VK_CAPITAL) ||
02896 (VirtualKeyCode == VK_KANA) ||
02897 (VirtualKeyCode == VK_JUNJA) ||
02898 (VirtualKeyCode == VK_HANJA) ||
02899 (VirtualKeyCode == VK_NUMLOCK) ||
02900 (VirtualKeyCode == VK_SCROLL) )
02901 &&
02902 !(Console->InputBuffer.ImeMode.Unavailable) &&
02903 !(Console->InputBuffer.ImeMode.Open)
02904 )
02905 {
02906
if (!
NT_SUCCESS(ConsoleImeMessagePump(Console,
02907 Message+
CONIME_KEYDATA,
02908 (WPARAM)LOWORD(wParam)<<16|LOWORD(VirtualKeyCode),
02909 lParam
02910 ))) {
02911
return;
02912 }
02913
goto FromConsoleIME ;
02914 }
02915
02916
if (!Console->InputBuffer.ImeMode.Unavailable && Console->InputBuffer.ImeMode.Open) {
02917
if (! (HIWORD(lParam) & KF_REPEAT))
02918 {
02919
if (PRIMARYLANGID(LOWORD(Console->hklActive)) == LANG_JAPANESE &&
02920 (
BYTE)wParam == VK_KANA) {
02921
if (!
NT_SUCCESS(ConsoleImeMessagePump(Console,
02922
CONIME_NOTIFY_VK_KANA,
02923 0,
02924 0
02925 ))) {
02926
return;
02927 }
02928 }
02929 }
02930
02931 ConsoleImeMessagePump(Console,
02932 Message+
CONIME_KEYDATA,
02933 LOWORD(wParam)<<16|LOWORD(VirtualKeyCode),
02934 lParam
02935 );
02936
return ;
02937 }
02938 }
02939 }
02940 FromConsoleIME:
02941
02942
02943
02944
02945
02946
02947
if (
DialogBoxCount > 0) {
02948
if (Message != WM_CHAR && Message != WM_SYSCHAR && Message != WM_DEADCHAR && Message != WM_SYSDEADCHAR) {
02949 WCHAR awch[
MAX_CHARS_FROM_1_KEYSTROKE];
02950
int cwch;
02951
BYTE KeyState[256];
02952
02953
GetKeyboardState(KeyState);
02954 cwch =
ToUnicodeEx((
UINT)wParam,HIWORD(lParam),KeyState,awch,
02955
MAX_CHARS_FROM_1_KEYSTROKE,
02956
02957 TM_POSTCHARBREAKS,
02958 (HKL)
NULL);
02959
if (cwch != 0) {
02960
return;
02961 }
02962 }
else {
02963
02964
if (Message == WM_CHAR) {
02965 bGenerateBreak=
TRUE;
02966 }
02967 }
02968 }
02969
02970
#ifdef FE_IME
02971
02972
if (Console->InputBuffer.hWndConsoleIME)
02973
return;
02974
#endif
02975
02976 InputEvent.EventType = KEY_EVENT;
02977 InputEvent.Event.KeyEvent.bKeyDown = bKeyDown;
02978 InputEvent.Event.KeyEvent.wRepeatCount = LOWORD(lParam);
02979
02980
if (Message == WM_CHAR || Message == WM_SYSCHAR || Message == WM_DEADCHAR || Message == WM_SYSDEADCHAR) {
02981
02982
if (lParam & 0x02000000) {
02983 InputEvent.Event.KeyEvent.wVirtualScanCode = 0;
02984 }
02985 InputEvent.Event.KeyEvent.dwControlKeyState =
GetControlKeyState(lParam);
02986
if (Message == WM_CHAR || Message == WM_SYSCHAR) {
02987 InputEvent.Event.KeyEvent.uChar.UnicodeChar = (WCHAR)wParam;
02988 }
else {
02989 InputEvent.Event.KeyEvent.uChar.UnicodeChar = (WCHAR)0;
02990 }
02991 }
else {
02992
02993
if (lParam & 0x02000000) {
02994
return;
02995 }
02996 InputEvent.Event.KeyEvent.dwControlKeyState = ControlKeyState;
02997 InputEvent.Event.KeyEvent.uChar.UnicodeChar = 0;
02998 }
02999
03000
#ifdef FE_IME
03001
if (
CONSOLE_IS_IME_ENABLED()) {
03002
03003
DWORD dwConversion;
03004
03005
if (!
NT_SUCCESS(GetImeKeyState(Console, &dwConversion))) {
03006
return;
03007 }
03008
03009 InputEvent.Event.KeyEvent.dwControlKeyState |=
ImmConversionToConsole(dwConversion);
03010 }
03011
#endif
03012
03013 ContinueProcessing=
TRUE;
03014
03015
if (
CTRL_BUT_NOT_ALT(InputEvent.Event.KeyEvent.dwControlKeyState) &&
03016 InputEvent.Event.KeyEvent.bKeyDown) {
03017
03018
03019
03020
03021
03022
if (InputEvent.Event.KeyEvent.wVirtualKeyCode ==
'C' &&
03023 Console->InputBuffer.InputMode & ENABLE_PROCESSED_INPUT) {
03024
HandleCtrlEvent(Console,CTRL_C_EVENT);
03025
if (!Console->PopupCount)
03026
TerminateRead(Console,&Console->InputBuffer,
CONSOLE_CTRL_C_SEEN);
03027
if (!(Console->Flags &
CONSOLE_SUSPENDED)) {
03028 ContinueProcessing=
FALSE;
03029 }
03030 }
03031
03032
03033
03034
03035
03036
else if (InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL) {
03037
FlushInputBuffer(&Console->InputBuffer);
03038
HandleCtrlEvent(Console,CTRL_BREAK_EVENT);
03039
if (!Console->PopupCount)
03040
TerminateRead(Console,&Console->InputBuffer,
CONSOLE_CTRL_BREAK_SEEN);
03041
if (!(Console->Flags &
CONSOLE_SUSPENDED)) {
03042 ContinueProcessing=
FALSE;
03043 }
03044 }
03045
03046
03047
03048
03049
03050
else if (InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE &&
03051 !(Console->ReserveKeys & CONSOLE_CTRLESC)) {
03052 ContinueProcessing=
FALSE;
03053 }
03054 }
else if (InputEvent.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) &&
03055 InputEvent.Event.KeyEvent.bKeyDown &&
03056 InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE &&
03057 !(Console->ReserveKeys & CONSOLE_ALTESC)) {
03058 ContinueProcessing=
FALSE;
03059 }
03060
03061
if (ContinueProcessing) {
03062 EventsWritten =
WriteInputBuffer( Console,
03063 &Console->InputBuffer,
03064 &InputEvent,
03065 1
03066 );
03067
if (EventsWritten && bGenerateBreak) {
03068 InputEvent.Event.KeyEvent.bKeyDown =
FALSE;
03069
WriteInputBuffer( Console,
03070 &Console->InputBuffer,
03071 &InputEvent,
03072 1
03073 );
03074 }
03075 }
03076
return;
03077 }
03078
03079
BOOL
03080 HandleMouseEvent(
03081 IN
PCONSOLE_INFORMATION Console,
03082 IN
PSCREEN_INFORMATION ScreenInfo,
03083 IN UINT Message,
03084 IN WPARAM wParam,
03085 IN LPARAM lParam
03086 )
03087
03088
03089
03090
03091
03092
03093 {
03094 ULONG ButtonFlags,EventFlags;
03095 INPUT_RECORD InputEvent;
03096 ULONG EventsWritten;
03097 COORD MousePosition;
03098
SHORT RowIndex;
03099
PROW Row;
03100
03101
if (!(Console->Flags &
CONSOLE_HAS_FOCUS) &&
03102 !(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) &&
03103 !(Console->SelectionFlags &
CONSOLE_MOUSE_DOWN)) {
03104
return TRUE;
03105 }
03106
03107
if (Console->Flags &
CONSOLE_IGNORE_NEXT_MOUSE_INPUT) {
03108
03109
if (Message != WM_LBUTTONDOWN &&
03110 Message != WM_MBUTTONDOWN &&
03111 Message != WM_RBUTTONDOWN) {
03112 Console->Flags &= ~
CONSOLE_IGNORE_NEXT_MOUSE_INPUT;
03113
return FALSE;
03114 }
03115
return TRUE;
03116 }
03117
03118
03119
03120
03121
03122 MousePosition.X = LOWORD(lParam);
03123 MousePosition.Y = HIWORD(lParam);
03124
if (ScreenInfo->Flags &
CONSOLE_TEXTMODE_BUFFER) {
03125 MousePosition.X /=
SCR_FONTSIZE(ScreenInfo).X;
03126 MousePosition.Y /=
SCR_FONTSIZE(ScreenInfo).Y;
03127 }
03128 MousePosition.X += ScreenInfo->Window.Left;
03129 MousePosition.Y += ScreenInfo->Window.Top;
03130
03131
03132
03133
03134
03135
if (MousePosition.X < 0) {
03136 MousePosition.X = 0;
03137 }
else if (MousePosition.X >= ScreenInfo->ScreenBufferSize.X) {
03138 MousePosition.X = ScreenInfo->ScreenBufferSize.X-1;
03139 }
03140
if (MousePosition.Y < 0) {
03141 MousePosition.Y = 0;
03142 }
else if (MousePosition.Y >= ScreenInfo->ScreenBufferSize.Y) {
03143 MousePosition.Y = ScreenInfo->ScreenBufferSize.Y-1;
03144 }
03145
03146
if (Console->Flags &
CONSOLE_SELECTING ||
03147 ((Console->Flags &
CONSOLE_QUICK_EDIT_MODE) &&
03148 (Console->FullScreenFlags == 0)) ) {
03149
if (Message == WM_LBUTTONDOWN) {
03150
03151
03152
03153
03154
03155
if (!(
GetKeyState(VK_LBUTTON) &
KEY_PRESSED)) {
03156
return FALSE;
03157 }
03158
03159
if (Console->Flags &
CONSOLE_QUICK_EDIT_MODE &&
03160 !(Console->Flags &
CONSOLE_SELECTING)) {
03161 Console->Flags |=
CONSOLE_SELECTING;
03162 Console->SelectionFlags =
CONSOLE_MOUSE_SELECTION |
CONSOLE_MOUSE_DOWN |
CONSOLE_SELECTION_NOT_EMPTY;
03163
03164
03165
03166
03167
03168 Console->SelectionAnchor = MousePosition;
03169 Console->SelectionRect.Left =Console->SelectionRect.Right = Console->SelectionAnchor.X;
03170 Console->SelectionRect.Top = Console->SelectionRect.Bottom = Console->SelectionAnchor.Y;
03171
MyInvert(Console,&Console->SelectionRect);
03172
SetWinText(Console,
msgSelectMode,
TRUE);
03173
SetCapture(Console->hWnd);
03174 }
else {
03175
03176
03177
03178
03179
03180
03181
03182
if (Console->SelectionFlags &
CONSOLE_MOUSE_SELECTION) {
03183
03184
03185
03186
03187
03188
if (
GetKeyState(VK_SHIFT) &
KEY_PRESSED) {
03189 Console->SelectionFlags |=
CONSOLE_MOUSE_DOWN;
03190
SetCapture(Console->hWnd);
03191
ExtendSelection(Console,
03192 MousePosition
03193 );
03194 }
else {
03195
03196
03197
03198
03199
03200
03201
MyInvert(Console,&Console->SelectionRect);
03202 Console->SelectionFlags |=
CONSOLE_MOUSE_DOWN;
03203
SetCapture(Console->hWnd);
03204 Console->SelectionAnchor = MousePosition;
03205 Console->SelectionRect.Left =Console->SelectionRect.Right = Console->SelectionAnchor.X;
03206 Console->SelectionRect.Top = Console->SelectionRect.Bottom = Console->SelectionAnchor.Y;
03207
MyInvert(Console,&Console->SelectionRect);
03208 }
03209 }
else {
03210
ConvertToMouseSelect(Console,
03211 MousePosition
03212 );
03213 }
03214 }
03215 }
else if (Message == WM_LBUTTONUP) {
03216
if (Console->SelectionFlags &
CONSOLE_MOUSE_SELECTION) {
03217 Console->SelectionFlags &= ~
CONSOLE_MOUSE_DOWN;
03218
ReleaseCapture();
03219 }
03220 }
else if (Message == WM_LBUTTONDBLCLK) {
03221
if ((MousePosition.X == Console->SelectionAnchor.X) &&
03222 (MousePosition.Y == Console->SelectionAnchor.Y)) {
03223 RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+MousePosition.Y) % ScreenInfo->ScreenBufferSize.Y;
03224 Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
03225
while (Console->SelectionAnchor.X > 0) {
03226
if (
IS_WORD_DELIM(Row->
CharRow.
Chars[Console->SelectionAnchor.X - 1]))
03227
break;
03228 Console->SelectionAnchor.X--;
03229 }
03230
while (MousePosition.X < ScreenInfo->ScreenBufferSize.X) {
03231
if (
IS_WORD_DELIM(Row->
CharRow.
Chars[MousePosition.X]))
03232
break;
03233 MousePosition.X++;
03234 }
03235
if (
gfTrimLeadingZeros) {
03236
03237
03238
03239
03240
if (MousePosition.X > Console->SelectionAnchor.X + 2 &&
03241 Row->
CharRow.
Chars[Console->SelectionAnchor.X + 1] !=
L'x' &&
03242 Row->
CharRow.
Chars[Console->SelectionAnchor.X + 1] !=
L'X') {
03243
03244
while (Row->
CharRow.
Chars[Console->SelectionAnchor.X] ==
L'0' && Console->SelectionAnchor.X < MousePosition.X - 1) {
03245 Console->SelectionAnchor.X++;
03246 }
03247 }
03248 }
03249
ExtendSelection(Console, MousePosition);
03250 }
03251 }
else if ((Message == WM_RBUTTONDOWN) || (Message == WM_RBUTTONDBLCLK)) {
03252
if (!(Console->SelectionFlags &
CONSOLE_MOUSE_DOWN)) {
03253
if (Console->Flags &
CONSOLE_SELECTING) {
03254
DoCopy(Console);
03255 }
else if (Console->Flags &
CONSOLE_QUICK_EDIT_MODE) {
03256
DoPaste(Console);
03257 }
03258 Console->Flags |=
CONSOLE_IGNORE_NEXT_MOUSE_INPUT;
03259 }
03260 }
else if (Message == WM_MOUSEMOVE) {
03261
if (Console->SelectionFlags &
CONSOLE_MOUSE_DOWN) {
03262
ExtendSelection(Console,
03263 MousePosition
03264 );
03265 }
03266 }
else if (Message == WM_MOUSEWHEEL) {
03267
return TRUE;
03268 }
03269
return FALSE;
03270 }
03271
03272
if (!(Console->InputBuffer.InputMode & ENABLE_MOUSE_INPUT)) {
03273
ReleaseCapture();
03274
if (Console->FullScreenFlags == 0) {
03275
return TRUE;
03276 }
03277
return FALSE;
03278 }
03279
03280
03281 InputEvent.Event.MouseEvent.dwControlKeyState =
GetControlKeyState(0);
03282
03283
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
03284
if (MousePosition.X > ScreenInfo->Window.Right) {
03285 MousePosition.X = ScreenInfo->Window.Right;
03286 }
03287
if (MousePosition.Y > ScreenInfo->Window.Bottom) {
03288 MousePosition.Y = ScreenInfo->Window.Bottom;
03289 }
03290 }
03291
switch (Message) {
03292
case WM_LBUTTONDOWN:
03293
SetCapture(Console->hWnd);
03294 ButtonFlags = FROM_LEFT_1ST_BUTTON_PRESSED;
03295 EventFlags = 0;
03296
break;
03297
case WM_LBUTTONUP:
03298
ReleaseCapture();
03299 ButtonFlags = 0;
03300 EventFlags = 0;
03301
break;
03302
case WM_RBUTTONDOWN:
03303
SetCapture(Console->hWnd);
03304 ButtonFlags = RIGHTMOST_BUTTON_PRESSED;
03305 EventFlags = 0;
03306
break;
03307
case WM_RBUTTONUP:
03308
ReleaseCapture();
03309 ButtonFlags = 0;
03310 EventFlags = 0;
03311
break;
03312
case WM_MBUTTONDOWN:
03313
SetCapture(Console->hWnd);
03314 ButtonFlags = FROM_LEFT_2ND_BUTTON_PRESSED;
03315 EventFlags = 0;
03316
break;
03317
case WM_MBUTTONUP:
03318
ReleaseCapture();
03319 ButtonFlags = 0;
03320 EventFlags = 0;
03321
break;
03322
case WM_MOUSEMOVE:
03323 ButtonFlags = 0;
03324 EventFlags = MOUSE_MOVED;
03325
break;
03326
case WM_LBUTTONDBLCLK:
03327 ButtonFlags = FROM_LEFT_1ST_BUTTON_PRESSED;
03328 EventFlags = DOUBLE_CLICK;
03329
break;
03330
case WM_RBUTTONDBLCLK:
03331 ButtonFlags = RIGHTMOST_BUTTON_PRESSED;
03332 EventFlags = DOUBLE_CLICK;
03333
break;
03334
case WM_MBUTTONDBLCLK:
03335 ButtonFlags = FROM_LEFT_2ND_BUTTON_PRESSED;
03336 EventFlags = DOUBLE_CLICK;
03337
break;
03338
case WM_MOUSEWHEEL:
03339 ButtonFlags = ((
UINT)wParam & 0xFFFF0000);
03340 EventFlags = MOUSE_WHEELED;
03341
break;
03342
default:
03343
ASSERT(
FALSE);
03344 }
03345 InputEvent.EventType = MOUSE_EVENT;
03346 InputEvent.Event.MouseEvent.dwMousePosition = MousePosition;
03347 InputEvent.Event.MouseEvent.dwEventFlags = EventFlags;
03348 InputEvent.Event.MouseEvent.dwButtonState =
03349
ConvertMouseButtonState(ButtonFlags,(
UINT)wParam);
03350 EventsWritten =
WriteInputBuffer( Console,
03351 &Console->InputBuffer,
03352 &InputEvent,
03353 1
03354 );
03355
#if DBG
03356
if (EventsWritten != 1) {
03357 OutputDebugStringA(
"PutInputInBuffer: EventsWritten != 1, 1 expected\n");
03358 }
03359
#endif
03360
#ifdef i386
03361
if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
03362
UpdateMousePosition(ScreenInfo,InputEvent.Event.MouseEvent.dwMousePosition);
03363 }
03364
#endif
03365
return FALSE;
03366 }
03367
03368
VOID
03369 HandleFocusEvent(
03370 IN
PCONSOLE_INFORMATION Console,
03371 IN BOOL bSetFocus
03372 )
03373 {
03374 INPUT_RECORD InputEvent;
03375 ULONG EventsWritten;
03376 USERTHREAD_FLAGS Flags;
03377
03378 InputEvent.EventType = FOCUS_EVENT;
03379 InputEvent.Event.FocusEvent.bSetFocus = bSetFocus;
03380
03381 Flags.dwFlags = 0;
03382
if (bSetFocus) {
03383
if (Console->Flags &
CONSOLE_VDM_REGISTERED) {
03384 Flags.dwFlags |=
TIF_VDMAPP;
03385 }
03386
if (Console->Flags &
CONSOLE_CONNECTED_TO_EMULATOR) {
03387 Flags.dwFlags |=
TIF_DOSEMULATOR;
03388 }
03389 }
03390
03391 Flags.dwMask = (
TIF_VDMAPP |
TIF_DOSEMULATOR);
03392
NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
03393 UserThreadFlags, &Flags,
sizeof(Flags));
03394 EventsWritten =
WriteInputBuffer( Console,
03395 &Console->InputBuffer,
03396 &InputEvent,
03397 1
03398 );
03399
#if DBG
03400
if (EventsWritten != 1) {
03401 OutputDebugStringA(
"PutInputInBuffer: EventsWritten != 1, 1 expected\n");
03402 }
03403
#endif
03404
}
03405
03406
VOID
03407 HandleMenuEvent(
03408 IN
PCONSOLE_INFORMATION Console,
03409 IN DWORD wParam
03410 )
03411 {
03412 INPUT_RECORD InputEvent;
03413 ULONG EventsWritten;
03414
03415 InputEvent.EventType = MENU_EVENT;
03416 InputEvent.Event.MenuEvent.dwCommandId = wParam;
03417 EventsWritten =
WriteInputBuffer( Console,
03418 &Console->InputBuffer,
03419 &InputEvent,
03420 1
03421 );
03422
#if DBG
03423
if (EventsWritten != 1) {
03424 OutputDebugStringA(
"PutInputInBuffer: EventsWritten != 1, 1 expected\n");
03425 }
03426
#endif
03427
}
03428
03429
VOID
03430 HandleCtrlEvent(
03431 IN
PCONSOLE_INFORMATION Console,
03432 IN DWORD EventType
03433 )
03434 {
03435
switch (EventType) {
03436
case CTRL_C_EVENT:
03437 Console->CtrlFlags |=
CONSOLE_CTRL_C_FLAG;
03438
break;
03439
case CTRL_BREAK_EVENT:
03440 Console->CtrlFlags |=
CONSOLE_CTRL_BREAK_FLAG;
03441
break;
03442
case CTRL_CLOSE_EVENT:
03443 Console->CtrlFlags |=
CONSOLE_CTRL_CLOSE_FLAG;
03444
break;
03445
default:
03446
ASSERT (
FALSE);
03447 }
03448 }
03449
03450
VOID
03451 KillProcess(
03452
PCONSOLE_PROCESS_TERMINATION_RECORD ProcessHandleRecord,
03453 ULONG_PTR ProcessId
03454 )
03455 {
03456
NTSTATUS status;
03457
03458
03459
03460
03461
03462 status =
NtTerminateProcess(ProcessHandleRecord->
ProcessHandle,
03463 ProcessHandleRecord->
bDebugee ? DBG_TERMINATE_PROCESS : CONTROL_C_EXIT);
03464
03465
#if DBG
03466
if (status != STATUS_SUCCESS &&
03467 status != STATUS_PROCESS_IS_TERMINATING &&
03468 status != STATUS_THREAD_WAS_SUSPENDED &&
03469 !(status == STATUS_ACCESS_DENIED && ProcessHandleRecord->
bDebugee)) {
03470
DbgPrint(
"NtTerminateProcess failed - status = %x\n", status);
03471 DbgBreakPoint();
03472 }
03473
#endif
03474
03475
03476
03477
03478
03479
if (ProcessId)
03480
BoostHardError(ProcessId,
BHE_FORCE);
03481
03482
03483
03484
03485
03486
if (
NT_SUCCESS(status)) {
03487 LARGE_INTEGER li;
03488
03489 li.QuadPart = (LONGLONG)-10000 *
CMSHUNGAPPTIMEOUT;
03490 status =
NtWaitForSingleObject(ProcessHandleRecord->
ProcessHandle,
03491
FALSE,
03492 &li);
03493
if (status != STATUS_WAIT_0) {
03494 RIPMSG2(RIP_WARNING,
03495
"KillProcess: wait for process %x failed with status %x",
03496 ProcessId, status);
03497 }
03498 }
03499 }
03500
03501
int
03502 CreateCtrlThread(
03503 IN
PCONSOLE_PROCESS_TERMINATION_RECORD ProcessHandleList,
03504 IN ULONG ProcessHandleListLength,
03505 IN PWCHAR Title,
03506 IN DWORD EventType,
03507 IN BOOL fForce
03508 )
03509
03510
03511
03512
03513 {
03514 HANDLE Thread;
03515
DWORD Status;
03516
NTSTATUS status;
03517
DWORD ShutdownFlags;
03518
int Success=
CONSOLE_SHUTDOWN_SUCCEEDED;
03519 ULONG i;
03520
DWORD EventFlags;
03521 PROCESS_BASIC_INFORMATION BasicInfo;
03522 PCSR_PROCESS Process;
03523
BOOL fForceProcess;
03524
BOOL fExitProcess;
03525
BOOL fFirstPass=
TRUE;
03526
BOOL fSecondPassNeeded=
FALSE;
03527
BOOL fHasError;
03528
BOOL fFirstWait;
03529
BOOL fEventProcessed;
03530
BOOL fBreakEvent;
03531
03532 BigLoop:
03533
for (i=0;i<ProcessHandleListLength;i++) {
03534
03535
03536
03537
03538
03539
03540
if (Success ==
CONSOLE_SHUTDOWN_FAILED) {
03541
break;
03542 }
03543
03544
03545
03546
03547
03548
03549 status =
NtQueryInformationProcess(
03550 ProcessHandleList[i].ProcessHandle,
03551 ProcessBasicInformation,
03552 &BasicInfo,
03553
sizeof(BasicInfo),
03554
NULL);
03555
03556
03557
03558
03559
03560
03561 ProcessHandleList[i].bDebugee =
FALSE;
03562 ShutdownFlags = 0;
03563
if (
NT_SUCCESS(status)) {
03564 CsrLockProcessByClientId(
03565 (HANDLE)BasicInfo.UniqueProcessId, &Process);
03566
if (Process ==
NULL) {
03567
KillProcess(&ProcessHandleList[i],
03568 BasicInfo.UniqueProcessId);
03569
continue;
03570 }
03571 }
else {
03572
KillProcess(&ProcessHandleList[i], 0);
03573
continue;
03574 }
03575 ShutdownFlags = Process->ShutdownFlags;
03576 ProcessHandleList[i].bDebugee = Process->DebugUserInterface.UniqueProcess!=
NULL;
03577 CsrUnlockProcess(Process);
03578
03579
if (!ProcessHandleList[i].bDebugee) {
03580 HANDLE
DebugPort;
03581
03582
03583
DebugPort = (HANDLE)
NULL;
03584 status =
NtQueryInformationProcess(
03585 ProcessHandleList[i].ProcessHandle,
03586 ProcessDebugPort,
03587 (PVOID)&
DebugPort,
03588
sizeof(
DebugPort),
03589
NULL
03590 );
03591
if (
NT_SUCCESS(status) &&
DebugPort ) {
03592 ProcessHandleList[i].bDebugee =
TRUE;
03593 }
03594 }
03595
if (EventType != CTRL_C_EVENT && EventType != CTRL_BREAK_EVENT) {
03596 fBreakEvent =
FALSE;
03597
if (fFirstPass) {
03598
if (ProcessHandleList[i].bDebugee) {
03599 fSecondPassNeeded =
TRUE;
03600
continue;
03601 }
03602 }
else {
03603
if (!ProcessHandleList[i].bDebugee) {
03604
continue;
03605 }
03606 }
03607 }
else {
03608 fBreakEvent =
TRUE;
03609 fFirstPass=
FALSE;
03610 }
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620 fForceProcess = fForce || (ShutdownFlags & SHUTDOWN_NORETRY);
03621
03622
03623
03624
03625
03626
03627 fExitProcess =
TRUE;
03628 EventFlags = 0;
03629
if (ShutdownFlags & (SHUTDOWN_SYSTEMCONTEXT | SHUTDOWN_OTHERCONTEXT)) {
03630
03631
03632
03633
03634
03635
03636 fExitProcess =
FALSE;
03637 fForceProcess =
TRUE;
03638
03639
03640
03641
03642
03643
03644
03645 EventFlags = 0x80000000;
03646 }
03647
03648
03649
03650
03651
03652 fFirstWait =
TRUE;
03653 fEventProcessed =
FALSE;
03654
03655
while (!fEventProcessed) {
03656
DWORD ThreadExitCode;
03657
DWORD ProcessExitCode;
03658
DWORD cMsTimeout;
03659
03660 Thread =
InternalCreateCallbackThread(
03661 ProcessHandleList[i].ProcessHandle,
03662 (ULONG_PTR)ProcessHandleList[i].
CtrlRoutine,
03663 EventType | EventFlags);
03664
03665
03666
03667
03668
03669
if (Thread ==
NULL) {
03670 KdPrint((
"CONSRV: CreateRemoteThread failed %x\n",GetLastError()));
03671
break;
03672 }
03673
03674
03675
03676
03677
03678 fEventProcessed =
TRUE;
03679
03680
03681
03682
03683
03684
03685
03686
if (EventType == CTRL_CLOSE_EVENT) {
03687 cMsTimeout =
gCmsHungAppTimeout;
03688 }
else if (EventType == CTRL_LOGOFF_EVENT) {
03689 cMsTimeout =
gCmsWaitToKillTimeout;
03690 }
else if (EventType == CTRL_SHUTDOWN_EVENT) {
03691
03692
03693
03694
03695
03696
03697
if (fFirstWait && BasicInfo.UniqueProcessId ==
gdwServicesProcessId) {
03698 cMsTimeout =
gdwServicesWaitToKillTimeout;
03699 }
else {
03700 cMsTimeout =
gCmsWaitToKillTimeout;
03701 }
03702 }
else {
03703 CloseHandle(Thread);
03704 fExitProcess =
FALSE;
03705
break;
03706 }
03707
03708
while (
TRUE) {
03709 fHasError =
BoostHardError(BasicInfo.UniqueProcessId,
03710 (fForceProcess ?
BHE_FORCE :
BHE_ACTIVATE));
03711
03712
03713
03714
03715
03716
03717
Status =
InternalWaitCancel(Thread,
03718 (fHasError && fForceProcess) ? 1000 : cMsTimeout);
03719
if (
Status == WAIT_TIMEOUT) {
03720
int Action;
03721
03722
03723
03724
03725
03726
if (fHasError && fForceProcess) {
03727
continue;
03728 }
03729
03730
if (!fForceProcess) {
03731
03732
03733
03734
03735
03736
03737
DialogBoxCount++;
03738
Action =
ThreadShutdownNotify(
WMCS_CONSOLE, (ULONG_PTR)Thread, (LPARAM)Title);
03739
DialogBoxCount--;
03740
03741
03742
03743
03744
03745
03746
if (
Action ==
TSN_USERSAYSCANCEL) {
03747 Success =
CONSOLE_SHUTDOWN_FAILED;
03748 }
03749 }
03750 }
else if (
Status == 0) {
03751 ThreadExitCode = 0;
03752 GetExitCodeThread(Thread,&ThreadExitCode);
03753 GetExitCodeProcess(ProcessHandleList[i].ProcessHandle,
03754 &ProcessExitCode);
03755
03756
03757
03758
03759
03760
03761
03762
if (fHasError || (ThreadExitCode == EventType &&
03763 ProcessExitCode == STILL_ACTIVE)) {
03764
int Action;
03765
03766
if (!fForceProcess) {
03767
03768
03769
03770
03771
03772
03773
Status =
InternalWaitCancel(ProcessHandleList[i].ProcessHandle,
03774 (fHasError || fFirstWait) ? 1000 : cMsTimeout);
03775
if (
Status == 0) {
03776
03777
03778
03779
03780
03781 fExitProcess =
FALSE;
03782 }
else if (
Status == WAIT_TIMEOUT) {
03783
DialogBoxCount++;
03784
Action =
ThreadShutdownNotify(
WMCS_CONSOLE,
03785 (ULONG_PTR)ProcessHandleList[i].ProcessHandle,
03786 (LPARAM)Title);
03787
DialogBoxCount--;
03788
03789
if (
Action ==
TSN_USERSAYSCANCEL) {
03790 Success =
CONSOLE_SHUTDOWN_FAILED;
03791 }
03792 }
03793 }
03794 }
else {
03795
03796
03797
03798
03799
03800 fExitProcess =
FALSE;
03801 }
03802 }
03803
03804
03805
03806
03807
03808
03809
break;
03810 }
03811
03812 CloseHandle(Thread);
03813 }
03814
03815
03816
03817
03818
03819
03820
03821
if (!fBreakEvent &&
03822 !(ShutdownFlags & (SHUTDOWN_SYSTEMCONTEXT | SHUTDOWN_OTHERCONTEXT)) &&
03823 Success ==
CONSOLE_SHUTDOWN_SUCCEEDED) {
03824 CsrLockProcessByClientId(
03825 (HANDLE)BasicInfo.UniqueProcessId, &Process);
03826
if (Process) {
03827 Process->Flags |= CSR_PROCESS_TERMINATED;
03828 CsrUnlockProcess(Process);
03829 }
03830
03831
03832
03833
03834
03835
if (fExitProcess) {
03836
KillProcess(&ProcessHandleList[i],
03837 BasicInfo.UniqueProcessId);
03838 }
else {
03839
BoostHardError(BasicInfo.UniqueProcessId,
BHE_FORCE);
03840 }
03841 }
03842 }
03843
03844
03845
03846
03847
03848
03849
03850
if (fFirstPass && fSecondPassNeeded) {
03851 fFirstPass =
FALSE;
03852
goto BigLoop;
03853 }
03854
03855
03856
03857
03858
if (ShutdownFlags & (SHUTDOWN_SYSTEMCONTEXT | SHUTDOWN_OTHERCONTEXT)) {
03859
return CONSOLE_SHUTDOWN_SYSTEM;
03860 }
03861
return Success;
03862 }
03863
03864
int
03865 ProcessCtrlEvents(
03866 IN
PCONSOLE_INFORMATION Console
03867 )
03868
03869 {
03870 PWCHAR Title;
03871
CONSOLE_PROCESS_TERMINATION_RECORD ProcessHandles[2];
03872
PCONSOLE_PROCESS_TERMINATION_RECORD ProcessHandleList;
03873 ULONG ProcessHandleListLength,i;
03874 ULONG CtrlFlags;
03875 PLIST_ENTRY ListHead, ListNext;
03876
BOOL FreeTitle;
03877
int Success;
03878
PCONSOLE_PROCESS_HANDLE ProcessHandleRecord;
03879
DWORD EventType;
03880
DWORD LimitingProcessId;
03881
NTSTATUS Status;
03882
03883
03884
03885
03886
03887
if (Console->Flags &
CONSOLE_IN_DESTRUCTION) {
03888
DestroyConsole(Console);
03889
return CONSOLE_SHUTDOWN_FAILED;
03890 }
03891
03892
03893
03894
03895
03896
03897
if (Console->Flags &
CONSOLE_TERMINATING) {
03898 Console->CtrlFlags = 0;
03899 }
03900
03901
if (Console->CtrlFlags == 0) {
03902 RtlLeaveCriticalSection(&Console->ConsoleLock);
03903
return CONSOLE_SHUTDOWN_FAILED;
03904 }
03905
03906
03907
03908
03909
03910 LimitingProcessId = Console->LimitingProcessId;
03911 Console->LimitingProcessId = 0;
03912
03913 ListHead = &Console->ProcessHandleList;
03914 ListNext = ListHead->Flink;
03915 ProcessHandleListLength = 0;
03916
while (ListNext != ListHead) {
03917 ProcessHandleRecord = CONTAINING_RECORD( ListNext,
CONSOLE_PROCESS_HANDLE, ListLink );
03918 ListNext = ListNext->Flink;
03919
if ( LimitingProcessId ) {
03920
if ( ProcessHandleRecord->
Process->ProcessGroupId == LimitingProcessId ) {
03921 ProcessHandleListLength += 1;
03922 }
03923 }
else {
03924 ProcessHandleListLength += 1;
03925 }
03926 }
03927
03928
03929
03930
03931
03932
03933
if (ProcessHandleListLength <=
NELEM(ProcessHandles)) {
03934 ProcessHandleList = ProcessHandles;
03935 }
else {
03936 ProcessHandleList = (
PCONSOLE_PROCESS_TERMINATION_RECORD)
ConsoleHeapAlloc(
MAKE_TAG(
TMP_TAG ),ProcessHandleListLength *
sizeof(
CONSOLE_PROCESS_TERMINATION_RECORD));
03937
if (ProcessHandleList ==
NULL) {
03938 RtlLeaveCriticalSection(&Console->ConsoleLock);
03939
return CONSOLE_SHUTDOWN_FAILED;
03940 }
03941 }
03942
03943 ListNext = ListHead->Flink;
03944 i=0;
03945
while (ListNext != ListHead) {
03946 BOOLEAN ProcessIsIn;
03947
03948
ASSERT(i<=ProcessHandleListLength);
03949 ProcessHandleRecord = CONTAINING_RECORD( ListNext,
CONSOLE_PROCESS_HANDLE, ListLink );
03950 ListNext = ListNext->Flink;
03951
03952
if ( LimitingProcessId ) {
03953
if ( ProcessHandleRecord->
Process->ProcessGroupId == LimitingProcessId ) {
03954 ProcessIsIn =
TRUE;
03955 }
else {
03956 ProcessIsIn =
FALSE;
03957 }
03958 }
else {
03959 ProcessIsIn =
TRUE;
03960 }
03961
03962
if ( ProcessIsIn ) {
03963 Success = (
int)DuplicateHandle(NtCurrentProcess(),
03964 ProcessHandleRecord->
ProcessHandle,
03965 NtCurrentProcess(),
03966 &ProcessHandleList[i].ProcessHandle,
03967 0,
03968
FALSE,
03969 DUPLICATE_SAME_ACCESS);
03970
03971
03972
03973
03974
03975
03976
if (!Success) {
03977 KdPrint((
"CONSRV: dup handle failed for %d of %d in %lx\n",
03978 i, ProcessHandleListLength, Console));
03979
continue;
03980 }
03981
03982
if (Console->CtrlFlags &
CONSOLE_CTRL_CLOSE_FLAG) {
03983 ProcessHandleRecord->
TerminateCount++;
03984 }
else {
03985 ProcessHandleRecord->
TerminateCount = 0;
03986 }
03987 ProcessHandleList[i].
TerminateCount = ProcessHandleRecord->
TerminateCount;
03988
03989
if (ProcessHandleRecord->
CtrlRoutine) {
03990 ProcessHandleList[i].
CtrlRoutine = ProcessHandleRecord->
CtrlRoutine;
03991 }
else {
03992 ProcessHandleList[i].
CtrlRoutine =
CtrlRoutine;
03993 }
03994
03995
03996
03997
03998
03999
04000
if (i > 0 && Console->VDMProcessId && Console->VDMProcessId ==
04001 ProcessHandleRecord->
Process->ClientId.UniqueProcess &&
04002 ProcessHandleRecord->
TerminateCount > 0) {
04003
CONSOLE_PROCESS_TERMINATION_RECORD ProcessHandle;
04004 ProcessHandle = ProcessHandleList[0];
04005 ProcessHandleList[0] = ProcessHandleList[i];
04006 ProcessHandleList[i] = ProcessHandle;
04007 }
04008
04009 i++;
04010 }
04011 }
04012 ProcessHandleListLength = i;
04013
ASSERT(ProcessHandleListLength > 0);
04014
04015
04016
04017 Title = (PWCHAR)
ConsoleHeapAlloc(
MAKE_TAG(
TITLE_TAG ),Console->TitleLength+
sizeof(WCHAR));
04018
if (Title) {
04019 FreeTitle =
TRUE;
04020 RtlCopyMemory(Title,Console->Title,Console->TitleLength+
sizeof(WCHAR));
04021 }
else {
04022 FreeTitle =
FALSE;
04023 Title =
L"Command Window";
04024 }
04025
04026
04027
04028 CtrlFlags = Console->CtrlFlags;
04029
ASSERT( !((CtrlFlags & (
CONSOLE_CTRL_CLOSE_FLAG |
CONSOLE_CTRL_BREAK_FLAG |
CONSOLE_CTRL_C_FLAG)) &&
04030 (CtrlFlags & (
CONSOLE_CTRL_LOGOFF_FLAG |
CONSOLE_CTRL_SHUTDOWN_FLAG)) ));
04031
04032 Console->CtrlFlags = 0;
04033
04034 RtlLeaveCriticalSection(&Console->ConsoleLock);
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047 Success =
CONSOLE_SHUTDOWN_FAILED;
04048
04049 EventType = (
DWORD)-1;
04050
switch (CtrlFlags & (
CONSOLE_CTRL_CLOSE_FLAG |
CONSOLE_CTRL_BREAK_FLAG |
04051
CONSOLE_CTRL_C_FLAG |
CONSOLE_CTRL_LOGOFF_FLAG |
04052
CONSOLE_CTRL_SHUTDOWN_FLAG)) {
04053
04054
case CONSOLE_CTRL_CLOSE_FLAG:
04055 EventType = CTRL_CLOSE_EVENT;
04056
break;
04057
04058
case CONSOLE_CTRL_BREAK_FLAG:
04059 EventType = CTRL_BREAK_EVENT;
04060
break;
04061
04062
case CONSOLE_CTRL_C_FLAG:
04063 EventType = CTRL_C_EVENT;
04064
break;
04065
04066
case CONSOLE_CTRL_LOGOFF_FLAG:
04067 EventType = CTRL_LOGOFF_EVENT;
04068
break;
04069
04070
case CONSOLE_CTRL_SHUTDOWN_FLAG:
04071 EventType = CTRL_SHUTDOWN_EVENT;
04072
break;
04073 }
04074
04075
if (EventType != (
DWORD)-1) {
04076
04077 Success =
CreateCtrlThread(ProcessHandleList,
04078 ProcessHandleListLength,
04079 Title,
04080 EventType,
04081 (CtrlFlags &
CONSOLE_FORCE_SHUTDOWN_FLAG) != 0
04082 );
04083 }
04084
04085
if (FreeTitle) {
04086
ConsoleHeapFree(Title);
04087 }
04088
04089
for (i=0;i<ProcessHandleListLength;i++) {
04090
Status =
NtClose(ProcessHandleList[i].ProcessHandle);
04091
ASSERT(
NT_SUCCESS(
Status));
04092 }
04093
04094
if (ProcessHandleList != ProcessHandles) {
04095
ConsoleHeapFree(ProcessHandleList);
04096 }
04097
04098
return Success;
04099 }
04100
04101
04102
VOID
04103 UnlockConsole(
04104 IN
PCONSOLE_INFORMATION Console
04105 )
04106 {
04107 LIST_ENTRY WaitQueue;
04108
04109
04110
04111
04112
ASSERT(
NT_SUCCESS(
ValidateConsole(Console)));
04113
04114
#ifdef i386
04115
04116
04117
04118
04119
if (
ConsoleVDMOnSwitching == Console &&
04120
ConsoleVDMOnSwitching->
VDMProcessId ==
CONSOLE_CLIENTPROCESSID()) {
04121 KdPrint((
" UnlockConsole - Thread %lx is leaving VDM CritSec\n", GetCurrentThreadId()));
04122 RtlLeaveCriticalSection(&
ConsoleVDMCriticalSection);
04123
return;
04124 }
04125
#endif
04126
04127
04128
04129
04130
04131
04132
04133
#if defined(_X86_)
04134
if (Console->ConsoleLock.RecursionCount == 1) {
04135
#endif
04136
#if defined(_MIPS_) || defined(_ALPHA_) || defined(_PPC_) || defined(_IA64_)
04137
if (Console->ConsoleLock.RecursionCount == 0) {
04138
#endif
04139
InitializeListHead(&WaitQueue);
04140
if (Console->WaitQueue) {
04141 CsrMoveSatisfiedWait(&WaitQueue, Console->WaitQueue);
04142 Console->WaitQueue =
NULL;
04143 }
04144
ProcessCtrlEvents(Console);
04145
04146
04147
04148
04149
if (!IsListEmpty(&WaitQueue)) {
04150 CsrDereferenceWait(&WaitQueue);
04151 }
04152 }
else {
04153 RtlLeaveCriticalSection(&Console->ConsoleLock);
04154 }
04155 }
04156
04157 ULONG
04158
ShutdownConsole(
04159 IN HANDLE ConsoleHandle,
04160 IN
DWORD dwFlags
04161 )
04162
04163
04164
04165
04166
04167
04168 {
04169
DWORD EventFlag;
04170
int WaitForShutdown;
04171
PCONSOLE_INFORMATION Console;
04172
04173 EventFlag = 0;
04174
04175
04176
04177
04178
04179
04180
if (
dwFlags & EWX_FORCE)
04181 EventFlag |=
CONSOLE_FORCE_SHUTDOWN_FLAG;
04182
04183
04184
04185
04186
04187
if (
dwFlags & EWX_SHUTDOWN) {
04188 EventFlag |=
CONSOLE_CTRL_SHUTDOWN_FLAG;
04189 }
else {
04190 EventFlag |=
CONSOLE_CTRL_LOGOFF_FLAG;
04191 }
04192
04193
04194
04195
04196
04197
if (!
NT_SUCCESS(
RevalidateConsole(ConsoleHandle, &Console))) {
04198 KdPrint((
"CONSRV: Shutting down terminating console\n"));
04199
return SHUTDOWN_KNOWN_PROCESS;
04200 }
04201
04202 Console->
Flags |=
CONSOLE_SHUTTING_DOWN;
04203 Console->
CtrlFlags = EventFlag;
04204 Console->
LimitingProcessId = 0;
04205
04206 WaitForShutdown =
ProcessCtrlEvents(Console);
04207
if (WaitForShutdown ==
CONSOLE_SHUTDOWN_SUCCEEDED) {
04208
return (ULONG)STATUS_PROCESS_IS_TERMINATING;
04209 }
else {
04210
if (!
NT_SUCCESS(
RevalidateConsole(ConsoleHandle, &Console))) {
04211
return SHUTDOWN_KNOWN_PROCESS;
04212 }
04213 Console->
Flags &= ~
CONSOLE_SHUTTING_DOWN;
04214
UnlockConsole(Console);
04215
if (WaitForShutdown ==
CONSOLE_SHUTDOWN_SYSTEM) {
04216
return SHUTDOWN_KNOWN_PROCESS;
04217 }
else {
04218
return SHUTDOWN_CANCEL;
04219 }
04220 }
04221 }
04222
04223
VOID UserExitWorkerThread(
VOID)
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248 {
04249 MEMORY_BASIC_INFORMATION MemInfo;
04250
NTSTATUS st;
04251
VOID SwitchStackThenTerminate(PVOID CurrentStack, PVOID NewStack,
DWORD ExitCode);
04252
04253 st =
NtQueryVirtualMemory(
04254 NtCurrentProcess(),
04255 NtCurrentTeb()->NtTib.StackLimit,
04256 MemoryBasicInformation,
04257 (PVOID)&MemInfo,
04258
sizeof(MemInfo),
04259
NULL
04260 );
04261
if ( !
NT_SUCCESS(st) ) {
04262
RtlRaiseStatus(st);
04263 }
04264
04265 SwitchStackThenTerminate(
04266 MemInfo.AllocationBase,
04267 &NtCurrentTeb()->UserReserved[0],
04268 0
04269 );
04270 }
04271
04272
VOID FreeStackAndTerminate(
04273 IN PVOID OldStack,
04274 IN
DWORD ExitCode)
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296 {
04297
NTSTATUS Status;
04298 SIZE_T
Zero;
04299 PVOID BaseAddress;
04300
04301
Zero = 0;
04302 BaseAddress = OldStack;
04303
04304
Status =
NtFreeVirtualMemory(
04305 NtCurrentProcess(),
04306 &BaseAddress,
04307 &
Zero,
04308 MEM_RELEASE
04309 );
04310
ASSERT(
NT_SUCCESS(
Status));
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
NtTerminateThread(
NULL,(
NTSTATUS)ExitCode);
04322 }