00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 NTSTATUS xxxInitTerminal(
00027
PTERMINAL pTerm)
00028 {
00029
NTSTATUS Status;
00030
PKEVENT pEventTermInit;
00031 HANDLE hEventInputReady, hEventTermInit;
00032 HANDLE hThreadDesktop;
00033
00034
CheckCritIn();
00035
00036 UserAssert(!(pTerm->
dwTERMF_Flags &
TERMF_INITIALIZED));
00037
00038
if (pTerm->
pEventInputReady !=
NULL) {
00039
00040
00041
00042
00043
00044
00045 UserAssert(pTerm->
pEventTermInit !=
NULL);
00046
00047
00048
00049
00050
00051 pEventTermInit = pTerm->
pEventTermInit;
00052
00053
ObReferenceObject(pEventTermInit);
00054
00055
LeaveCrit();
00056
00057
goto Wait;
00058 }
00059
00060
00061
00062
00063
00064
Status = ZwCreateEvent(
00065 &hEventInputReady,
00066 EVENT_ALL_ACCESS,
00067
NULL,
00068 NotificationEvent,
00069
FALSE);
00070
00071
if (!
NT_SUCCESS(
Status))
00072
return Status;
00073
00074
Status =
ObReferenceObjectByHandle(
00075 hEventInputReady,
00076 EVENT_ALL_ACCESS,
00077 *
ExEventObjectType,
00078
KernelMode,
00079 &pTerm->
pEventInputReady,
NULL);
00080
00081 ZwClose(hEventInputReady);
00082
00083
if (!
NT_SUCCESS(
Status))
00084
return Status;
00085
00086
00087
00088
00089
00090
if (!(pTerm->
dwTERMF_Flags &
TERMF_NOIO)) {
00091
if (!
CreateTerminalInput(pTerm)) {
00092
ObDereferenceObject(pTerm->
pEventInputReady);
00093
return STATUS_NO_MEMORY;
00094 }
00095 }
00096
00097
00098
00099
00100
Status = ZwCreateEvent(
00101 &hEventTermInit,
00102 EVENT_ALL_ACCESS,
00103
NULL,
00104 NotificationEvent,
00105
FALSE);
00106
00107
if (!
NT_SUCCESS(
Status)) {
00108
ObDereferenceObject(pTerm->
pEventInputReady);
00109
return Status;
00110 }
00111
00112
Status =
ObReferenceObjectByHandle(
00113 hEventTermInit,
00114 EVENT_ALL_ACCESS,
00115 *
ExEventObjectType,
00116
KernelMode,
00117 &pTerm->
pEventTermInit,
NULL);
00118
00119 ZwClose(hEventTermInit);
00120
00121
if (!
NT_SUCCESS(
Status)) {
00122
ObDereferenceObject(pTerm->
pEventInputReady);
00123
return Status;
00124 }
00125
00126
00127
00128
00129
00130 pEventTermInit = pTerm->
pEventTermInit;
00131
00132
LeaveCrit();
00133
00134
00135
00136
00137
Status =
CreateSystemThread(
00138 (
PKSTART_ROUTINE)
xxxDesktopThread,
00139 pTerm,
00140 &hThreadDesktop);
00141
00142
if (!
NT_SUCCESS(
Status)) {
00143
EnterCrit();
00144
ObDereferenceObject(pTerm->
pEventInputReady);
00145
ObDereferenceObject(pEventTermInit);
00146
return STATUS_NO_MEMORY;
00147 }
00148
00149 ZwClose(hThreadDesktop);
00150
00151 Wait:
00152
KeWaitForSingleObject(pEventTermInit,
00153
WrUserRequest,
00154
KernelMode,
00155
FALSE,
00156
NULL);
00157
00158
EnterCrit();
00159
00160
00161
00162
00163
00164
ObDereferenceObject(pEventTermInit);
00165
00166 pTerm->
pEventTermInit =
NULL;
00167
00168
if (pTerm->
dwTERMF_Flags &
TERMF_DTINITFAILED) {
00169
return STATUS_NO_MEMORY;
00170 }
00171
00172 pTerm->
dwTERMF_Flags |=
TERMF_INITIALIZED;
00173
return STATUS_SUCCESS;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 static CONST LPCWSTR
lpszStdFormats[] = {
00188
L"StdExit",
00189
L"StdNewDocument",
00190
L"StdOpenDocument",
00191
L"StdEditDocument",
00192
L"StdNewfromTemplate",
00193
L"StdCloseDocument",
00194
L"StdShowItem",
00195
L"StdDoVerbItem",
00196
L"System",
00197
L"OLEsystem",
00198
L"StdDocumentName",
00199
L"Protocols",
00200
L"Topics",
00201
L"Formats",
00202
L"Status",
00203
L"EditEnvItems",
00204
L"True",
00205
L"False",
00206
L"Change",
00207
L"Save",
00208
L"Close",
00209
L"MSDraw"
00210 };
00211
00212 NTSTATUS CreateGlobalAtomTable(
00213 PVOID* ppAtomTable)
00214 {
00215
NTSTATUS Status;
00216 RTL_ATOM Atom;
00217 ULONG i;
00218
00219
Status =
RtlCreateAtomTable(0, ppAtomTable);
00220
00221
if (!
NT_SUCCESS(
Status)) {
00222 RIPMSG0(RIP_WARNING,
"Global atom table not created");
00223
return Status;
00224 }
00225
00226
for (i = 0; i <
ARRAY_SIZE(
lpszStdFormats); i++) {
00227
Status =
RtlAddAtomToAtomTable(*ppAtomTable,
00228 (PWSTR)
lpszStdFormats[i],
00229 &Atom);
00230
if (!
NT_SUCCESS(
Status)) {
00231 RIPMSG1(RIP_WARNING,
"RtlAddAtomToAtomTable failed to add atom %ws",
00232
lpszStdFormats[i]);
00233
00234
RtlDestroyAtomTable(*ppAtomTable);
00235
return Status;
00236 }
00237
00238
RtlPinAtomInAtomTable(*ppAtomTable, Atom);
00239 }
00240
return Status;
00241 }
00242
00243 HWINSTA
xxxCreateWindowStation(
00244 POBJECT_ATTRIBUTES ObjectAttributes,
00245 KPROCESSOR_MODE OwnershipMode,
00246 DWORD dwDesiredAccess,
00247 HANDLE hKbdLayoutFile,
00248 DWORD offTable,
00249 PCWSTR pwszKLID,
00250 UINT uKbdInputLocale)
00251 {
00252
PWINDOWSTATION pwinsta;
00253
PTHREADINFO ptiCurrent;
00254
PDESKTOP pdeskTemp;
00255 HDESK hdeskTemp;
00256 PSECURITY_DESCRIPTOR psd;
00257 PSECURITY_DESCRIPTOR psdCapture;
00258
PPROCESSINFO ppiSave;
00259
NTSTATUS Status;
00260 PACCESS_ALLOWED_ACE paceList =
NULL, pace;
00261 ULONG ulLength, ulLengthSid;
00262 HANDLE hEvent;
00263 HWINSTA hwinsta;
00264
DWORD dwDisableHooks;
00265
PTERMINAL pTerm =
NULL;
00266
PWND pwnd;
00267 WCHAR szBaseNamedObjectDirectory[
MAX_SESSION_PATH];
00268
00269 UserAssert(
IsWinEventNotifyDeferredOK());
00270
00271
00272
00273
00274
00275 psdCapture =
ObjectAttributes->SecurityDescriptor;
00276
00277
00278
00279
00280
00281
if (
grpWinStaList ==
NULL) {
00282
00283
00284
00285
00286 UserAssert(
PsGetCurrentProcess()->UniqueProcessId ==
gpidLogon);
00287
00288 pTerm = &
gTermIO;
00289 }
else {
00290 pTerm = &
gTermNOIO;
00291
00292 UserAssert(
grpWinStaList->
rpwinstaNext ==
NULL ||
00293 pTerm->
dwTERMF_Flags &
TERMF_NOIO);
00294
00295 pTerm->
dwTERMF_Flags |=
TERMF_NOIO;
00296 }
00297
00298
00299
00300
00301
Status =
ObCreateObject(
KernelMode, *
ExWindowStationObjectType,
00302
ObjectAttributes, OwnershipMode,
NULL,
sizeof(
WINDOWSTATION),
00303 0, 0, &pwinsta);
00304
00305
if (!
NT_SUCCESS(
Status)) {
00306 RIPNTERR0(
Status, RIP_WARNING,
"Failed to create windowstation");
00307
return NULL;
00308 }
00309
00310
00311
00312
00313 RtlZeroMemory(pwinsta,
sizeof(
WINDOWSTATION));
00314
00315
00316
00317
00318 pwinsta->
dwSessionId =
gSessionId;
00319
00320 pwinsta->
pTerm = pTerm;
00321
00322
00323
00324
00325
if (pTerm->
dwTERMF_Flags &
TERMF_NOIO) {
00326 pwinsta->
dwWSF_Flags =
WSF_NOIO;
00327 }
00328
00329
00330
00331
00332
00333
Status =
CreateGlobalAtomTable(&pwinsta->
pGlobalAtomTable);
00334
00335
if (pwinsta->
pGlobalAtomTable ==
NULL) {
00336 UserAssert(!
NT_SUCCESS(
Status));
00337 RIPNTERR0(
Status, RIP_WARNING,
"CreateGlobalAtomTable failed");
00338
goto create_error;
00339 }
00340
00341
00342
00343
00344
00345
if (!(pTerm->
dwTERMF_Flags &
TERMF_INITIALIZED)) {
00346
00347
Status =
xxxInitTerminal(pTerm);
00348
00349
if (!
NT_SUCCESS(
Status)) {
00350 RIPNTERR0(
Status, RIP_WARNING,
"xxxInitTerminal failed");
00351
goto create_error;
00352 }
00353 }
00354
00355
if (!(pwinsta->
dwWSF_Flags &
WSF_NOIO)) {
00356
if (!
xxxInitWindowStation(pwinsta)) {
00357 RIPNTERR0(STATUS_NO_MEMORY, RIP_WARNING,
"xxxInitWindowStation failed");
00358
goto create_error;
00359 }
00360 }
00361
00362
00363
00364
00365
if (pTerm->
spwndDesktopOwner ==
NULL) {
00366
00367
00368
00369
00370
00371 ptiCurrent =
PtiCurrent();
00372 ppiSave = ptiCurrent->
ppi;
00373 ptiCurrent->
ppi = pTerm->
ptiDesktop->
ppi;
00374
00375 UserAssert(pTerm->
ptiDesktop->
ppi->W32PF_Flags & W32PF_CLASSESREGISTERED);
00376
00377 pdeskTemp = ptiCurrent->
rpdesk;
00378 hdeskTemp = ptiCurrent->
hdesk;
00379
if (pdeskTemp) {
00380
ObReferenceObject(pdeskTemp);
00381
LogDesktop(pdeskTemp, LD_REF_FN_CREATEWINDOWSTATION,
TRUE, (ULONG_PTR)
PtiCurrent());
00382 }
00383
00384
00385
00386
00387
00388
00389
DeferWinEventNotify();
00390
BEGINATOMICCHECK();
00391
zzzSetDesktop(ptiCurrent,
NULL,
NULL);
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 dwDisableHooks = ptiCurrent->
TIF_flags &
TIF_DISABLEHOOKS;
00405 ptiCurrent->
TIF_flags |=
TIF_DISABLEHOOKS;
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 pwnd =
xxxCreateWindowEx(
00421 (
DWORD)0,
00422 (
PLARGE_STRING)
DESKTOPCLASS,
00423
NULL,
00424 (WS_POPUP | WS_CLIPCHILDREN),
00425 SHRT_MIN / 2,
00426 SHRT_MIN / 2,
00427 SHRT_MAX,
00428 SHRT_MAX,
00429
NULL,
00430
NULL,
00431
hModuleWin,
00432 (LPWSTR)
NULL,
00433
VER31
00434 );
00435
00436
if (pwnd ==
NULL) {
00437 RIPMSG0(RIP_WARNING,
"xxxCreateWindowStation: Failed to create mother desktop window");
00438
Status = STATUS_NO_MEMORY;
00439
EXITATOMICCHECK();
00440
zzzEndDeferWinEventNotify();
00441
00442
00443
00444 ptiCurrent->
ppi = ppiSave;
00445
00446
00447
00448
00449
zzzSetDesktop(ptiCurrent, pdeskTemp, hdeskTemp);
00450
00451
goto create_error;
00452 }
00453
00454
00455
00456
00457 {
00458
PHE phe;
00459
00460 UserAssert(ptiCurrent->
rpdesk ==
NULL);
00461
00462 phe =
HMPheFromObject(pwnd);
00463 phe->
bFlags |=
HANDLEF_POOL;
00464 }
00465
00466
Lock(&(pTerm->
spwndDesktopOwner), pwnd);
00467
00468 UserAssert(ptiCurrent->
TIF_flags &
TIF_DISABLEHOOKS);
00469 ptiCurrent->
TIF_flags = (ptiCurrent->
TIF_flags & ~
TIF_DISABLEHOOKS) | dwDisableHooks;
00470
00471
SetVisible(pTerm->
spwndDesktopOwner,
SV_SET);
00472
HMChangeOwnerThread(pTerm->
spwndDesktopOwner, pTerm->
ptiDesktop);
00473
00474
00475
00476
00477 ptiCurrent->
ppi = ppiSave;
00478
00479
00480
00481
00482
zzzSetDesktop(ptiCurrent, pdeskTemp, hdeskTemp);
00483
00484
ENDATOMICCHECK();
00485
zzzEndDeferWinEventNotify();
00486
00487
if (pdeskTemp) {
00488
LogDesktop(pdeskTemp, LD_DEREF_FN_CREATEWINDOWSTATION,
FALSE, (ULONG_PTR)
PtiCurrent());
00489
ObDereferenceObject(pdeskTemp);
00490 }
00491 }
00492
00493
00494
00495
00496
00497
00498
if (!(pwinsta->
dwWSF_Flags &
WSF_NOIO)) {
00499 UNICODE_STRING strName;
00500 HANDLE hRootDir;
00501 OBJECT_ATTRIBUTES obja;
00502
00503
00504
00505
00506 ulLengthSid =
RtlLengthSid(
SeExports->
SeWorldSid);
00507 ulLength = ulLengthSid +
sizeof(ACE_HEADER) +
sizeof(ACCESS_MASK);
00508
00509
00510
00511
00512 paceList = (PACCESS_ALLOWED_ACE)UserAllocPoolWithQuota(ulLength, TAG_SECURITY);
00513
00514
if (paceList ==
NULL) {
00515
Status = STATUS_NO_MEMORY;
00516
goto create_error;
00517 }
00518
00519
00520
00521
00522 pace = paceList;
00523 pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
00524 pace->Header.AceSize = (
USHORT)ulLength;
00525 pace->Header.AceFlags = 0;
00526 pace->Mask = SYNCHRONIZE;
00527
RtlCopySid(ulLengthSid, &pace->SidStart,
SeExports->
SeWorldSid);
00528
00529
00530
00531
00532 psd =
CreateSecurityDescriptor(paceList, ulLength,
FALSE);
00533
00534 UserFreePool(paceList);
00535
00536
if (psd ==
NULL) {
00537
Status = STATUS_NO_MEMORY;
00538
goto create_error;
00539 }
00540
00541
00542
00543
00544 UserAssert(
ghEventSwitchDesktop ==
NULL);
00545
00546
if (
gbRemoteSession) {
00547 swprintf(szBaseNamedObjectDirectory,
L"\\Sessions\\%ld\\BaseNamedObjects",
00548
gSessionId);
00549
RtlInitUnicodeString(&strName, szBaseNamedObjectDirectory);
00550 }
else {
00551
RtlInitUnicodeString(&strName,
L"\\BaseNamedObjects");
00552 }
00553
00554 InitializeObjectAttributes( &obja,
00555 &strName,
00556 OBJ_CASE_INSENSITIVE,
00557
NULL,
00558
NULL
00559 );
00560
Status = ZwOpenDirectoryObject( &hRootDir,
00561 DIRECTORY_ALL_ACCESS &
00562 ~(DELETE | WRITE_DAC | WRITE_OWNER),
00563 &obja
00564 );
00565
if (
NT_SUCCESS(
Status)) {
00566
RtlInitUnicodeString(&strName,
L"WinSta0_DesktopSwitch");
00567 InitializeObjectAttributes(&obja, &strName, OBJ_OPENIF, hRootDir, psd);
00568
Status = ZwCreateEvent(&hEvent, EVENT_ALL_ACCESS, &obja,
00569 NotificationEvent,
FALSE);
00570 ZwClose(hRootDir);
00571
00572
if (
NT_SUCCESS(
Status)) {
00573
Status =
ObReferenceObjectByHandle(hEvent, EVENT_ALL_ACCESS, *
ExEventObjectType,
00574
KernelMode, &
gpEventSwitchDesktop,
NULL);
00575
if (
NT_SUCCESS(
Status)) {
00576
00577
00578
00579
00580
00581
00582
00583
00584
KeAttachProcess(&
gpepCSRSS->
Pcb);
00585
00586
Status =
ObOpenObjectByPointer(
00587
gpEventSwitchDesktop,
00588 0,
00589
NULL,
00590 EVENT_ALL_ACCESS,
00591
NULL,
00592
KernelMode,
00593 &
ghEventSwitchDesktop);
00594
KeDetachProcess();
00595 }
00596 ZwClose(hEvent);
00597 }
00598 }
00599
if (!
NT_SUCCESS(
Status))
00600
goto create_error;
00601
00602 UserFreePool(psd);
00603 }
00604
00605
00606
00607
00608
Status =
ObInsertObject(pwinsta,
NULL, dwDesiredAccess, 1,
00609 &pwinsta, &hwinsta);
00610
00611
if (
Status == STATUS_OBJECT_NAME_EXISTS) {
00612
00613
00614
00615
00616
ObDereferenceObject(pwinsta);
00617
00618 }
else if (
NT_SUCCESS(
Status)) {
00619 PSECURITY_DESCRIPTOR psdParent, psdNew;
00620
SECURITY_SUBJECT_CONTEXT Context;
00621
POBJECT_DIRECTORY pParentDirectory;
00622 SECURITY_INFORMATION siNew;
00623
00624
00625
00626
00627
00628
00629
SeCaptureSubjectContext(&Context);
00630
SeLockSubjectContext(&Context);
00631
00632 pParentDirectory =
OBJECT_HEADER_TO_NAME_INFO(
00633
OBJECT_TO_OBJECT_HEADER(pwinsta))->Directory;
00634
if (pParentDirectory !=
NULL)
00635 psdParent =
OBJECT_TO_OBJECT_HEADER(pParentDirectory)->SecurityDescriptor;
00636
else
00637 psdParent =
NULL;
00638
00639
Status =
SeAssignSecurity(
00640 psdParent,
00641 psdCapture,
00642 &psdNew,
00643
TRUE,
00644 &Context,
00645 (PGENERIC_MAPPING)&
WinStaMapping,
00646
PagedPool);
00647
00648
SeUnlockSubjectContext(&Context);
00649
SeReleaseSubjectContext(&Context);
00650
00651
if (!
NT_SUCCESS(
Status)) {
00652
#if DBG
00653
if (
Status == STATUS_ACCESS_DENIED) {
00654 RIPNTERR0(
Status, RIP_WARNING,
"Access denied during object creation");
00655 }
else {
00656 RIPNTERR1(
Status, RIP_ERROR,
00657
"Can't create security descriptor! Status = %#lx",
00658
Status);
00659 }
00660
#endif
00661
}
else {
00662
00663
00664
00665
00666 siNew = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
00667 DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION);
00668
Status =
ObSetSecurityDescriptorInfo(
00669 pwinsta,
00670 &siNew,
00671 psdNew,
00672 &
OBJECT_TO_OBJECT_HEADER(pwinsta)->SecurityDescriptor,
00673
PagedPool,
00674 (PGENERIC_MAPPING)&
WinStaMapping);
00675
SeDeassignSecurity(&psdNew);
00676
00677
if (
NT_SUCCESS(
Status)) {
00678
00679
PWINDOWSTATION* ppwinsta;
00680
00681
00682
00683
00684 ppwinsta = &
grpWinStaList;
00685
while (*ppwinsta !=
NULL)
00686 ppwinsta = &(*ppwinsta)->
rpwinstaNext;
00687
LockWinSta(ppwinsta, pwinsta);
00688
00689
00690
00691
00692
00693
if (!(pwinsta->
dwWSF_Flags &
WSF_NOIO) && pwszKLID !=
NULL) {
00694
if (
xxxLoadKeyboardLayoutEx(
00695 pwinsta,
00696 hKbdLayoutFile,
00697 (HKL)
NULL,
00698 offTable,
00699 pwszKLID,
00700 uKbdInputLocale,
00701 KLF_ACTIVATE | KLF_INITTIME) ==
NULL) {
00702
Status = STATUS_UNSUCCESSFUL;
00703 }
00704 }
00705 }
00706 }
00707
ObDereferenceObject(pwinsta);
00708 }
00709
00710
if (!
NT_SUCCESS(
Status)) {
00711 RIPNTERR1(
Status,
00712 RIP_WARNING,
00713
"CreateWindowStation: Failed with Status 0x%x",
00714
Status);
00715
return NULL;
00716 }
00717
00718
return hwinsta;
00719
00720
00721
00722
00723 create_error:
00724
00725 RIPNTERR1(
Status,
00726 RIP_WARNING,
00727
"CreateWindowStation: Failed with Status 0x%x",
00728
Status);
00729
00730
ObDereferenceObject(pwinsta);
00731
00732
return NULL;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 VOID FreeWindowStation(
00746
PWINDOWSTATION pwinsta)
00747 {
00748 UserAssert(
OBJECT_TO_OBJECT_HEADER(pwinsta)->Type == *
ExWindowStationObjectType);
00749
00750
00751
00752
00753 UserAssert(!(pwinsta->
dwWSF_Flags &
WSF_DYING));
00754 pwinsta->
dwWSF_Flags |=
WSF_DYING;
00755
00756 UserAssert(pwinsta->
rpdeskList ==
NULL);
00757
00758
00759
00760
00761
00762
if (!(pwinsta->
dwWSF_Flags &
WSF_NOIO) && (
gpEventSwitchDesktop !=
NULL)) {
00763
KeSetEvent(
gpEventSwitchDesktop,
EVENT_INCREMENT,
FALSE);
00764
ObDereferenceObject(
gpEventSwitchDesktop);
00765
gpEventSwitchDesktop =
NULL;
00766 }
00767
00768 BEGIN_REENTERCRIT();
00769
00770
RtlDestroyAtomTable(pwinsta->
pGlobalAtomTable);
00771
00772
ForceEmptyClipboard(pwinsta);
00773
00774
00775
00776
00777
if (!(pwinsta->
dwWSF_Flags &
WSF_NOIO) && pwinsta->
spklList !=
NULL) {
00778
00779
PKL pkl = pwinsta->
spklList;
00780
PKL pklFirst = pkl;
00781
00782 RIPMSG2(RIP_WARNING,
"FreeWindowStation: pwinsta(%p)->spklList is not NULL, %p", pwinsta, pwinsta->
spklList);
00783
00784
do {
00785
PKL pklNext = pkl->
pklNext;
00786
00787
HMMarkObjectDestroy(pkl);
00788 pkl->
dwKL_Flags |=
KL_UNLOADED;
00789
00790
Lock(&pwinsta->
spklList, pklNext);
00791
00792 pkl = pklNext;
00793
00794 }
while (pkl != pkl->
pklNext && pkl != pklFirst);
00795
00796
Unlock(&pwinsta->
spklList);
00797
00798
HYDRA_HINT(
HH_KBDLYOUTFREEWINSTA);
00799
00800
00801
00802
00803 UserAssert(
gspwndLogonNotify ==
NULL);
00804 }
else {
00805 UserAssert(pwinsta->
spklList ==
NULL);
00806 }
00807
00808
00809
00810
00811
if (pwinsta->
psidUser !=
NULL) {
00812 UserFreePool(pwinsta->
psidUser);
00813 pwinsta->
psidUser =
NULL;
00814 }
00815
00816 END_REENTERCRIT();
00817 }
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 VOID DestroyWindowStation(
00831
PEPROCESS Process,
00832 PVOID pobj,
00833 ACCESS_MASK amGranted,
00834 ULONG cProcessHandles,
00835 ULONG cSystemHandles)
00836 {
00837
PWINDOWSTATION pwinsta = pobj;
00838
PWINDOWSTATION *ppwinsta;
00839
PDESKTOP pdesk;
00840
PDESKTOP pdeskLock =
NULL;
00841
00842 UserAssert(
OBJECT_TO_OBJECT_HEADER(pobj)->Type == *
ExWindowStationObjectType);
00843
00844
00845
00846
00847
if (cSystemHandles != 1)
00848
return;
00849
00850 BEGIN_REENTERCRIT();
00851
00852
00853
00854
00855
00856
for (ppwinsta = &
grpWinStaList;
00857 *ppwinsta !=
NULL && pwinsta != *ppwinsta;
00858 ppwinsta = &(*ppwinsta)->
rpwinstaNext)
00859 ;
00860
if (*ppwinsta !=
NULL) {
00861
UnlockWinSta(ppwinsta);
00862
00863
00864
00865 UserAssert(
OBJECT_TO_OBJECT_HEADER(pobj)->Type == *
ExWindowStationObjectType);
00866
00867 *ppwinsta = pwinsta->
rpwinstaNext;
00868
00869
00870
00871
00872 pwinsta->
rpwinstaNext =
NULL;
00873 }
00874
00875
00876
00877
00878
00879 pdesk = pwinsta->
rpdeskList;
00880
while (pdesk !=
NULL) {
00881
if (pdesk !=
grpdeskLogon && pdesk->
dwConsoleThreadId) {
00882
LockDesktop(&pdeskLock, pdesk, LDL_FN_DESTROYWINDOWSTATION, 0);
00883
TerminateConsole(pdesk);
00884
00885
00886
00887
00888 pdesk = pwinsta->
rpdeskList;
00889
UnlockDesktop(&pdeskLock, LDU_FN_DESTROYWINDOWSTATION, 0);
00890 }
else
00891 pdesk = pdesk->
rpdeskNext;
00892 }
00893
00894 END_REENTERCRIT();
00895
00896 UNREFERENCED_PARAMETER(Process);
00897 UNREFERENCED_PARAMETER(cProcessHandles);
00898 UNREFERENCED_PARAMETER(amGranted);
00899 }
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 NTSTATUS ParseWindowStation(
00912 PVOID pContainerObject,
00913
POBJECT_TYPE pObjectType,
00914
PACCESS_STATE pAccessState,
00915 KPROCESSOR_MODE AccessMode,
00916 ULONG Attributes,
00917 PUNICODE_STRING pstrCompleteName,
00918 PUNICODE_STRING pstrRemainingName,
00919 PVOID Context OPTIONAL,
00920 PSECURITY_QUALITY_OF_SERVICE pqos,
00921 PVOID *pObject)
00922 {
00923
PWINDOWSTATION pwinsta = pContainerObject;
00924
00925 UserAssert(
OBJECT_TO_OBJECT_HEADER(pContainerObject)->Type == *
ExWindowStationObjectType);
00926
00927
00928
00929
00930 *pObject =
NULL;
00931
if (pstrRemainingName->Length == 0) {
00932
if (pObjectType != *
ExWindowStationObjectType)
00933
return STATUS_OBJECT_TYPE_MISMATCH;
00934
00935
ObReferenceObject(pwinsta);
00936 *pObject = pwinsta;
00937
return STATUS_SUCCESS;
00938 }
00939
00940
00941
00942
00943
if (*(pstrRemainingName->Buffer) == OBJ_NAME_PATH_SEPARATOR) {
00944 pstrRemainingName->Buffer++;
00945 pstrRemainingName->Length -=
sizeof(WCHAR);
00946 pstrRemainingName->MaximumLength -=
sizeof(WCHAR);
00947 }
00948
00949
00950
00951
00952
if (wcschr(pstrRemainingName->Buffer,
L'\\'))
00953
return STATUS_OBJECT_PATH_INVALID;
00954
if (pObjectType == *
ExDesktopObjectType) {
00955
return ParseDesktop(
00956 pContainerObject,
00957 pObjectType,
00958 pAccessState,
00959 AccessMode,
00960 Attributes,
00961 pstrCompleteName,
00962 pstrRemainingName,
00963 Context,
00964 pqos,
00965 pObject);
00966 }
00967
00968
return STATUS_OBJECT_TYPE_MISMATCH;
00969 }
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 BOOLEAN
OkayToCloseWindowStation(
00982
PEPROCESS Process OPTIONAL,
00983 PVOID Object,
00984 HANDLE Handle)
00985 {
00986
PWINDOWSTATION pwinsta = (
PWINDOWSTATION)Object;
00987
00988 UNREFERENCED_PARAMETER(Process);
00989
00990 UserAssert(
OBJECT_TO_OBJECT_HEADER(Object)->Type == *
ExWindowStationObjectType);
00991
00992
00993
00994
00995
if (KeGetPreviousMode() ==
KernelMode) {
00996
return TRUE;
00997 }
00998
00999
01000
01001
01002
if (
CheckHandleInUse(
Handle) ||
CheckHandleFlag(
Handle,
HF_PROTECTED)) {
01003 RIPMSG1(RIP_WARNING,
"Trying to close windowstation %#p while still in use", pwinsta);
01004
return FALSE;
01005 }
01006
01007
return TRUE;
01008 }
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 HWINSTA
_OpenWindowStation(
01020 POBJECT_ATTRIBUTES pObjA,
01021 DWORD dwDesiredAccess,
01022 KPROCESSOR_MODE AccessMode)
01023 {
01024 HWINSTA hwinsta;
01025
NTSTATUS Status;
01026
01027
01028
01029
01030
01031
Status =
ObOpenObjectByName(
01032 pObjA,
01033 *
ExWindowStationObjectType,
01034 AccessMode,
01035
NULL,
01036 dwDesiredAccess,
01037
NULL,
01038 &hwinsta);
01039
if (!
NT_SUCCESS(
Status)) {
01040 RIPNTERR0(
Status, RIP_VERBOSE,
"");
01041 hwinsta =
NULL;
01042 }
01043
return hwinsta;
01044 }
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 BOOL _CloseWindowStation(
01056 HWINSTA hwinsta)
01057 {
01058 HWINSTA hwinstaCurrent;
01059
01060
_GetProcessWindowStation(&hwinstaCurrent);
01061
if (hwinsta != hwinstaCurrent) {
01062
return NT_SUCCESS(ZwClose(hwinsta));
01063 }
01064
return FALSE;
01065 }
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077 BOOL xxxSetProcessWindowStation(
01078 HWINSTA hwinsta,
01079 KPROCESSOR_MODE AccessMode)
01080 {
01081
PETHREAD Thread =
PsGetCurrentThread();
01082
PEPROCESS Process =
PsGetCurrentProcess();
01083 HWINSTA hwinstaDup;
01084
NTSTATUS Status;
01085
PPROCESSINFO ppi;
01086
PWINDOWSTATION pwinsta;
01087
PWINDOWSTATION pwinstaOld;
01088
OBJECT_HANDLE_INFORMATION ohi;
01089
OBJECT_HANDLE_INFORMATION ohiOld;
01090
01091
if (Process ==
NULL) {
01092 UserAssert(Process);
01093
return FALSE;
01094 }
01095
01096
if (Thread ==
NULL) {
01097 UserAssert(Thread);
01098
return FALSE;
01099 }
01100
01101 ppi =
PpiFromProcess(
THREAD_TO_PROCESS(Thread));
01102
01103
if (!
NT_SUCCESS(
ObReferenceObjectByHandle(
01104 hwinsta,
01105 0,
01106 *
ExWindowStationObjectType,
01107 AccessMode,
01108 &pwinsta,
01109 &ohi))) {
01110
return FALSE;
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
if (ppi->
hwinsta) {
01122
SetHandleFlag(ppi->
hwinsta,
HF_PROTECTED,
FALSE);
01123 }
01124
01125
01126
01127
01128
LockWinSta(&ppi->
rpwinsta, pwinsta);
01129
ObDereferenceObject(pwinsta);
01130 ppi->
hwinsta = hwinsta;
01131
01132
01133
01134
01135
SetHandleFlag(ppi->
hwinsta,
HF_PROTECTED,
TRUE);
01136
01137
01138
01139
01140
01141
if (Process->
Win32WindowStation) {
01142
01143
01144
01145
01146
Status =
ObReferenceObjectByHandle(
01147 Process->
Win32WindowStation,
01148 0,
01149 *
ExWindowStationObjectType,
01150 AccessMode,
01151 &pwinstaOld,
01152 &ohiOld);
01153
if (
NT_SUCCESS(
Status)) {
01154
01155
01156
01157
01158
if (pwinsta != pwinstaOld) {
01159 ZwClose(Process->
Win32WindowStation);
01160 Process->
Win32WindowStation =
NULL;
01161 }
01162
ObDereferenceObject(pwinstaOld);
01163
01164 }
else {
01165
01166
01167
01168 Process->
Win32WindowStation =
NULL;
01169
#if DBG
01170
RIPMSG2(RIP_WARNING,
01171
"SetProcessWindowStation: Couldn't reference old WindowStation (0x%X) Status=0x%X",
01172 Process->
Win32WindowStation,
01173
Status);
01174
#endif
01175
}
01176 }
01177
01178
01179
01180
01181
01182
01183
if (Process->
Win32WindowStation ==
NULL) {
01184
Status =
xxxUserDuplicateObject(
01185 NtCurrentProcess(),
01186 hwinsta,
01187 NtCurrentProcess(),
01188 &hwinstaDup,
01189 0,
01190 0,
01191 DUPLICATE_SAME_ACCESS);
01192
01193
if (
NT_SUCCESS(
Status)) {
01194 Process->
Win32WindowStation = hwinstaDup;
01195 }
01196
#if DBG
01197
else {
01198 RIPMSG2(RIP_WARNING,
01199
"SetProcessWindowStation: Couldn't duplicate WindowStation handle (0x%X) Status=0x%X",
01200 hwinsta,
01201
Status);
01202 }
01203
#endif
01204
}
01205
01206 ppi->
amwinsta = ohi.
GrantedAccess;
01207
01208
01209
01210
01211
if (pwinsta->
dwWSF_Flags &
WSF_NOIO) {
01212 ppi->W32PF_Flags &= ~W32PF_IOWINSTA;
01213 }
else {
01214 ppi->W32PF_Flags |= W32PF_IOWINSTA;
01215 }
01216
01217
01218
01219
01220
01221
if (
RtlAreAllAccessesGranted(ohi.
GrantedAccess, WINSTA_READSCREEN)) {
01222 ppi->W32PF_Flags |= W32PF_READSCREENACCESSGRANTED;
01223 }
else {
01224 ppi->W32PF_Flags &= ~W32PF_READSCREENACCESSGRANTED;
01225 }
01226
01227
return TRUE;
01228 }
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240 PWINDOWSTATION _GetProcessWindowStation(
01241 HWINSTA *phwinsta)
01242 {
01243
PPROCESSINFO ppi;
01244
01245 ppi =
PpiCurrent();
01246 UserAssert(ppi);
01247
01248
if (phwinsta)
01249 *phwinsta = ppi->
hwinsta;
01250
return ppi->
rpwinsta;
01251 }
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 NTSTATUS _BuildNameList(
01265
PWINDOWSTATION pwinsta,
01266
PNAMELIST ccxpNameList,
01267 UINT cbNameList,
01268 PUINT pcbNeeded)
01269 {
01270
PBYTE pobj;
01271 PWCHAR ccxpwchDest, ccxpwchMax;
01272 ACCESS_MASK amDesired;
01273
POBJECT_HEADER pHead;
01274
POBJECT_HEADER_NAME_INFO pNameInfo;
01275
DWORD iNext;
01276
NTSTATUS Status;
01277 CONST GENERIC_MAPPING *pGenericMapping;
01278
01279
01280
01281
01282
01283
try {
01284 ccxpNameList->
cNames = 0;
01285 } except (W32ExceptionHandler(
FALSE, RIP_WARNING)) {
01286
return STATUS_ACCESS_VIOLATION;
01287 }
01288
01289 ccxpwchDest = ccxpNameList->
awchNames;
01290 ccxpwchMax = (PWCHAR)((
PBYTE)ccxpNameList + cbNameList -
sizeof(WCHAR));
01291
01292
01293
01294
01295
01296
if (pwinsta ==
NULL) {
01297 pobj = (
PBYTE)
grpWinStaList;
01298 amDesired = WINSTA_ENUMERATE;
01299 pGenericMapping = &
WinStaMapping;
01300 iNext = FIELD_OFFSET(
WINDOWSTATION, rpwinstaNext);
01301 }
else {
01302 pobj = (
PBYTE)pwinsta->
rpdeskList;
01303 amDesired = DESKTOP_ENUMERATE;
01304 pGenericMapping = &
DesktopMapping;
01305 iNext = FIELD_OFFSET(
DESKTOP, rpdeskNext);
01306 }
01307
01308
Status = STATUS_SUCCESS;
01309 *pcbNeeded = 0;
01310
while (pobj !=
NULL) {
01311
01312
if (
AccessCheckObject(pobj, amDesired,
KernelMode, pGenericMapping)) {
01313
01314
01315
01316
01317 pHead =
OBJECT_TO_OBJECT_HEADER(pobj);
01318 pNameInfo =
OBJECT_HEADER_TO_NAME_INFO(pHead);
01319
01320
01321
01322
01323
01324
01325
if ((PWCHAR)((
PBYTE)ccxpwchDest + pNameInfo->
Name.Length +
01326
sizeof(WCHAR)) >= ccxpwchMax) {
01327 *pcbNeeded += (
UINT)((
PBYTE)ccxpwchDest - (
PBYTE)ccxpNameList);
01328 ccxpwchDest = ccxpNameList->
awchNames;
01329
Status = STATUS_BUFFER_TOO_SMALL;
01330 }
01331
01332
try {
01333 ccxpNameList->
cNames++;
01334
01335
01336
01337
01338 RtlCopyMemory(ccxpwchDest, pNameInfo->
Name.Buffer,
01339 pNameInfo->
Name.Length);
01340 (
PBYTE)ccxpwchDest += pNameInfo->
Name.Length;
01341 *ccxpwchDest++ = 0;
01342 } except (W32ExceptionHandler(
FALSE, RIP_WARNING)) {
01343
return STATUS_ACCESS_VIOLATION;
01344 }
01345 }
01346
01347 pobj = *(
PBYTE*)(pobj + iNext);
01348 }
01349
01350
01351
01352
01353
try {
01354 *ccxpwchDest++ = 0;
01355
01356 ccxpNameList->
cb = (
UINT)((
PBYTE)ccxpwchDest - (
PBYTE)ccxpNameList);
01357 } except (W32ExceptionHandler(
FALSE, RIP_WARNING)) {
01358
return STATUS_ACCESS_VIOLATION;
01359 }
01360
01361 *pcbNeeded += (
UINT)((
PBYTE)ccxpwchDest - (
PBYTE)ccxpNameList);
01362
01363
return Status;
01364 }
01365
01366 NTSTATUS ReferenceWindowStation(
01367
PETHREAD Thread,
01368 HWINSTA hwinsta,
01369 ACCESS_MASK amDesiredAccess,
01370
PWINDOWSTATION *ppwinsta,
01371 BOOL fUseDesktop)
01372 {
01373
PPROCESSINFO ppi;
01374
PTHREADINFO pti;
01375
PWINDOWSTATION pwinsta =
NULL;
01376
NTSTATUS Status;
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387 ppi =
PpiFromProcess(Thread->
ThreadsProcess);
01388 pti =
PtiFromThread(Thread);
01389
01390
01391
01392
01393
01394
if (ppi !=
NULL) {
01395
if (!fUseDesktop || pti ==
NULL || pti->
rpdesk ==
NULL ||
01396 ppi->
rpwinsta == pti->
rpdesk->
rpwinstaParent) {
01397
01398
01399
01400
01401 pwinsta = ppi->
rpwinsta;
01402
if (pwinsta !=
NULL) {
01403
RETURN_IF_ACCESS_DENIED(ppi->
amwinsta, amDesiredAccess,
01404 STATUS_ACCESS_DENIED);
01405 }
01406 }
01407
01408
01409
01410
01411
01412
if (pwinsta ==
NULL && pti !=
NULL && pti->
rpdesk !=
NULL) {
01413
01414
01415
01416
01417
01418 pwinsta = pti->
rpdesk->
rpwinstaParent;
01419
if (!
AccessCheckObject(pwinsta, amDesiredAccess,
KernelMode, &
WinStaMapping))
01420
return STATUS_ACCESS_DENIED;
01421 }
01422 }
01423
01424
01425
01426
01427
01428
if (pwinsta ==
NULL) {
01429
if (hwinsta !=
NULL) {
01430
Status =
ObReferenceObjectByHandle(
01431 hwinsta,
01432 amDesiredAccess,
01433 *
ExWindowStationObjectType,
01434
KernelMode,
01435 &pwinsta,
01436
NULL);
01437
if (!
NT_SUCCESS(
Status))
01438
return Status;
01439
ObDereferenceObject(pwinsta);
01440 }
else {
01441
return STATUS_NOT_FOUND;
01442 }
01443 }
01444
01445 *ppwinsta = pwinsta;
01446
01447
return STATUS_SUCCESS;
01448 }
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459 UINT _SetWindowStationUser(
01460
PWINDOWSTATION pwinsta,
01461 PLUID pluidUser,
01462 PSID ccxpsidUser,
01463 DWORD cbsidUser)
01464 {
01465
01466
01467
01468
01469
if (
GetCurrentProcessId() !=
gpidLogon) {
01470 RIPERR0(ERROR_ACCESS_DENIED,
01471 RIP_WARNING,
01472
"Access denied in _SetWindowStationUser: caller must be in the logon process");
01473
01474
return FALSE;
01475 }
01476
01477
if (pwinsta->
psidUser !=
NULL)
01478 UserFreePool(pwinsta->
psidUser);
01479
01480
if (ccxpsidUser !=
NULL) {
01481 pwinsta->
psidUser = UserAllocPoolWithQuota(cbsidUser, TAG_SECURITY);
01482
if (pwinsta->
psidUser ==
NULL) {
01483 RIPERR0(ERROR_OUTOFMEMORY,
01484 RIP_WARNING,
01485
"Memory allocation failed in _SetWindowStationUser");
01486
01487
return FALSE;
01488 }
01489
try {
01490 RtlCopyMemory(pwinsta->
psidUser, ccxpsidUser, cbsidUser);
01491 } except (W32ExceptionHandler(
TRUE, RIP_WARNING)) {
01492
01493 UserFreePool(pwinsta->
psidUser);
01494 pwinsta->
psidUser =
NULL;
01495
return FALSE;
01496 }
01497 }
else {
01498 pwinsta->
psidUser =
NULL;
01499 }
01500
01501 pwinsta->
luidUser = *pluidUser;
01502
01503
return TRUE;
01504 }
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517 BOOL _LockWorkStation(
01518 VOID)
01519 {
01520 UserAssert(
gspwndLogonNotify !=
NULL);
01521
01522
_PostMessage(
gspwndLogonNotify,
01523 WM_LOGONNOTIFY, LOGON_LOCKWORKSTATION, 0);
01524
01525
return TRUE;
01526 }
01527
01528
#ifdef LATER // HY
01529
BOOL _IsIoDesktop(
01530 HDESK hdesk)
01531 {
01532
BOOL fRet =
FALSE;
01533
NTSTATUS Status;
01534
PDESKTOP pdesk =
NULL;
01535
01536
Status =
ValidateHdesk(hdesk, UserMode, 0, &pdesk);
01537
if (
NT_SUCCESS(Status)) {
01538 UserAssert(pdesk && pdesk->
rpwinstaParent);
01539 fRet = (pdesk->
rpwinstaParent->
dwWSF_Flags &
WSF_NOIO) == 0;
01540
ObDereferenceObject(pdesk);
01541 }
01542
return fRet;
01543 }
01544
#endif
01545