test: misc.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# misc.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: misc.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * This module contains citrix code.
    00007 *
    00008 \***************************************************************************/
    00009
    00010
    00011 #include "precomp.h"
    00012 #pragma hdrstop
    00013
    00014 /*
    00015  * All of the following are gotten from ICASRV
    00016  */
    00017
    00018 CACHE_STATISTICS ThinWireCache;
    00019
    00020 NTSTATUS RemoteConnect(
    00021     IN PDOCONNECTDATA pDoConnectData,
    00022     IN ULONG DisplayDriverNameLength,
    00023     IN PWCHAR DisplayDriverName)
    00024 {
    00025     NTSTATUS          Status = STATUS_SUCCESS;
    00026     PFILE_OBJECT      pFileObject = NULL;
    00027     PDEVICE_OBJECT    pDeviceObject = NULL;
    00028     PWCHAR            pSep;
    00029
    00030     TRACE_HYDAPI(("RemoteConnect: display %ws\n", DisplayDriverName));
    00031
    00032     HYDRA_HINT(HH_REMOTECONNECT);
    00033
    00034     UserAssert(ISCSRSS());
    00035
    00036     gpThinWireCache = &ThinWireCache;
    00037
    00038     if (pDoConnectData->fMouse) {
    00039         ghRemoteMouseChannel = pDoConnectData->IcaMouseChannel;
    00040     } else {
    00041         ghRemoteMouseChannel = NULL;
    00042     }
    00043
    00044     ghRemoteVideoChannel = pDoConnectData->IcaVideoChannel;
    00045     ghRemoteBeepChannel = pDoConnectData->IcaBeepChannel;
    00046     ghRemoteKeyboardChannel = pDoConnectData->IcaKeyboardChannel;
    00047     ghRemoteThinwireChannel = pDoConnectData->IcaThinwireChannel;
    00048
    00049     gRemoteClientKeyboardType = pDoConnectData->ClientKeyboardType;
    00050
    00051     gbClientDoubleClickSupport = pDoConnectData->fClientDoubleClickSupport;
    00052
    00053     gfEnableWindowsKey = pDoConnectData->fEnableWindowsKey;
    00054
    00055     RtlCopyMemory(gWinStationInfo.ProtocolName, pDoConnectData->ProtocolName,
    00056                   WPROTOCOLNAME_LENGTH * sizeof(WCHAR));
    00057
    00058     RtlCopyMemory(gWinStationInfo.AudioDriverName, pDoConnectData->AudioDriverName,
    00059                   WAUDIONAME_LENGTH * sizeof(WCHAR));
    00060
    00061     RtlZeroMemory(gstrBaseWinStationName,
    00062                   WINSTATIONNAME_LENGTH * sizeof(WCHAR));
    00063
    00064     RtlCopyMemory(gstrBaseWinStationName, pDoConnectData->WinStationName,
    00065                   min(WINSTATIONNAME_LENGTH * sizeof(WCHAR), sizeof(pDoConnectData->WinStationName)));
    00066
    00067     if (pSep = wcschr(gstrBaseWinStationName, L'#'))
    00068         *pSep = UNICODE_NULL;
    00069
    00070     /*
    00071      * Create the event that is signaled when a desktop does away
    00072      */
    00073     gpevtDesktopDestroyed = CreateKernelEvent(SynchronizationEvent, FALSE);
    00074     if (gpevtDesktopDestroyed == NULL) {
    00075         RIPMSG0(RIP_WARNING, "RemoteConnect couldn't create gpevtDesktopDestroyed");
    00076         return STATUS_NO_MEMORY;
    00077     }
    00078
    00079     gbConnected = TRUE;
    00080
    00081     /*
    00082      * WinStations must have the video device handle passed to them.
    00083      */
    00084     if (gbRemoteSession && !gVideoFileObject) {
    00085
    00086         PFILE_OBJECT    pFileObject = NULL;
    00087         PDEVICE_OBJECT  pDeviceObject = NULL;
    00088
    00089         //
    00090         // Dereference the file handle
    00091         // and obtain a pointer to the device object for the handle.
    00092         //
    00093
    00094         Status = ObReferenceObjectByHandle(ghRemoteVideoChannel,
    00095                                            0,
    00096                                            NULL,
    00097                                            KernelMode,
    00098                                            (PVOID*)&pFileObject,
    00099                                            NULL);
    00100         if (NT_SUCCESS(Status)) {
    00101
    00102             gVideoFileObject = pFileObject;
    00103
    00104             //
    00105             // Get a pointer to the device object for this file.
    00106             //
    00107             pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
    00108
    00109             Status = ObReferenceObjectByHandle(ghRemoteThinwireChannel,
    00110                                                0,
    00111                                                NULL,
    00112                                                KernelMode,
    00113                                                (PVOID*)&gThinwireFileObject,
    00114                                                NULL);
    00115
    00116             /*
    00117              * This must be done before any thinwire data.
    00118              */
    00119             if (NT_SUCCESS(Status)) {
    00120
    00121                 if (!GreMultiUserInitSession(ghRemoteThinwireChannel,
    00122                                              (PBYTE)gpThinWireCache,
    00123                                              gVideoFileObject,
    00124                                              gThinwireFileObject,
    00125                                              DisplayDriverNameLength,
    00126                                              DisplayDriverName)) {
    00127                     RIPMSG0(RIP_WARNING, "UserInit: GreMultiUserInitSession failed");
    00128                     Status = STATUS_UNSUCCESSFUL;
    00129                 } else {
    00130
    00131                     DWORD BytesReturned;
    00132
    00133                     Status = GreDeviceIoControl( pDeviceObject,
    00134                                  IOCTL_VIDEO_ICA_ENABLE_GRAPHICS,
    00135                                  NULL,
    00136                                  0,
    00137                                  NULL,
    00138                                  0,
    00139                                  &BytesReturned);
    00140                     if (!NT_SUCCESS(Status)) {
    00141                         RIPMSG1(RIP_WARNING, "UserInit: Enable graphics status %08lx",
    00142                                 Status);
    00143                     }
    00144                 }
    00145             }
    00146         }
    00147     }
    00148
    00149     if (!NT_SUCCESS(Status)) {
    00150         RIPMSG0(RIP_WARNING, "RemoteConnect failed");
    00151         return Status;
    00152     }
    00153
    00154     if (InitVideo(FALSE) == NULL) {
    00155         gbConnected = FALSE;
    00156         RIPMSG0(RIP_WARNING, "InitVideo failed");
    00157         return STATUS_UNSUCCESSFUL;
    00158     }
    00159
    00160     if (!LW_BrushInit()) {
    00161         RIPMSG0(RIP_WARNING, "LW_BrushInit failed");
    00162         return STATUS_NO_MEMORY;
    00163     }
    00164
    00165     InitLoadResources();
    00166
    00167     Status = ObReferenceObjectByHandle(ghRemoteBeepChannel,
    00168                                        0,
    00169                                        NULL,
    00170                                        KernelMode,
    00171                                        (PVOID*)&gpRemoteBeepDevice,
    00172                                        NULL);
    00173
    00174     /*
    00175      * video is initialized at this point
    00176      */
    00177     if (NT_SUCCESS(Status)) {
    00178         gbVideoInitialized = TRUE;
    00179     } else {
    00180         RIPMSG0(RIP_WARNING, "Bad Remote Beep Channel");
    00181     }
    00182
    00183     return Status;
    00184 }
    00185
    00186
    00187 NTSTATUS
    00188 xxxRemoteDisconnect(
    00189     VOID)
    00190 {
    00191     NTSTATUS      Status = STATUS_SUCCESS;
    00192     LARGE_INTEGER li;
    00193
    00194     TRACE_HYDAPI(("xxxRemoteDisconnect\n"));
    00195
    00196     /*
    00197      * Only allow CSRSS to do this
    00198      */
    00199     if (!ISCSRSS() || !ISTS()) {
    00200         return STATUS_ACCESS_DENIED;
    00201     }
    00202
    00203     HYDRA_HINT(HH_REMOTEDISCONNECT);
    00204
    00205     RtlZeroMemory(gstrBaseWinStationName,
    00206                   WINSTATIONNAME_LENGTH * sizeof(WCHAR));
    00207
    00208     UserAssert(gbConnected);
    00209
    00210     if (gspdeskDisconnect == NULL) {
    00211         /*
    00212          * Convert dwMilliseconds to a relative-time(i.e.  negative)
    00213          * LARGE_INTEGER.  NT Base calls take time values in 100 nanosecond
    00214          * units. Timeout after 5 minutes.
    00215          */
    00216         li.QuadPart = Int32x32To64(-10000, 300000);
    00217
    00218         KeWaitForSingleObject(gpEventDiconnectDesktop,
    00219                               WrUserRequest,
    00220                               KernelMode,
    00221                               FALSE,
    00222                               &li);
    00223     }
    00224
    00225
    00226     /*
    00227      * If the disconnected desktop has not yet be setup.  Do not do any
    00228      * disconnect processing.  It's better for the thinwire driver to try
    00229      * and write rather than for the transmit buffers to be freed (trap).
    00230      */
    00231     if (gspdeskDisconnect) {
    00232
    00233         /*
    00234          * Blank the screen
    00235          *
    00236          * No need to stop graphics mode for disconnects
    00237          */
    00238         Status = xxxRemoteStopScreenUpdates(FALSE);
    00239         if (!NT_SUCCESS(Status)) {
    00240             return Status;
    00241         }
    00242
    00243         /*
    00244          * If there are any shadow connections, then redraw the screen now.
    00245          */
    00246         if (gnShadowers)
    00247             RemoteRedrawScreen();
    00248     } else {
    00249         RIPMSG0(RIP_WARNING, "xxxRemoteDisconnect failed. The disconnect desktop was not created");
    00250         return STATUS_UNSUCCESSFUL;
    00251     }
    00252
    00253     /*
    00254      * Tell thinwire driver about this
    00255      */
    00256     bDrvDisconnect(gpDispInfo->hDev, ghRemoteThinwireChannel,
    00257                    gThinwireFileObject);
    00258
    00259
    00260     /*
    00261      * Tell winlogon about the disconnect
    00262      */
    00263     if (gspwndLogonNotify != NULL) {
    00264         _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, SESSION_DISCONNECTED, 0);
    00265     }
    00266
    00267     gbConnected = FALSE;
    00268
    00269     return Status;
    00270 }
    00271
    00272 NTSTATUS
    00273 xxxRemoteReconnect(
    00274     IN PDORECONNECTDATA pDoReconnectData)
    00275 {
    00276     NTSTATUS Status = STATUS_SUCCESS;
    00277     BOOL     fResult;
    00278     PWCHAR   pSep;
    00279
    00280     TRACE_HYDAPI(("xxxRemoteReconnect\n"));
    00281
    00282     /*
    00283      * Only allow CSRSS to do this
    00284      */
    00285     if (!ISCSRSS() || !ISTS()) {
    00286         return STATUS_ACCESS_DENIED;
    00287     }
    00288
    00289     HYDRA_HINT(HH_REMOTERECONNECT);
    00290
    00291     UserAssert(ISCSRSS());
    00292
    00293     gRemoteClientKeyboardType = pDoReconnectData->ClientKeyboardType;
    00294
    00295     gbClientDoubleClickSupport = pDoReconnectData->fClientDoubleClickSupport;
    00296
    00297     gfEnableWindowsKey = pDoReconnectData->fEnableWindowsKey;
    00298
    00299     RtlCopyMemory(gstrBaseWinStationName, pDoReconnectData->WinStationName,
    00300                   min(WINSTATIONNAME_LENGTH * sizeof(WCHAR), sizeof(pDoReconnectData->WinStationName)));
    00301
    00302     if (pSep = wcschr(gstrBaseWinStationName, L'#'))
    00303         *pSep = UNICODE_NULL;
    00304
    00305     if (gnShadowers)
    00306         xxxRemoteStopScreenUpdates(TRUE);
    00307
    00308
    00309     /*
    00310      * Call thinwire driver to check for thinwire mode compatibility
    00311      */
    00312     fResult = bDrvReconnect(gpDispInfo->hDev, ghRemoteThinwireChannel,
    00313                             gThinwireFileObject);
    00314
    00315     if (!fResult) {
    00316         if (gnShadowers)
    00317             RemoteRedrawScreen();
    00318
    00319         return STATUS_CTX_BAD_VIDEO_MODE;
    00320     }
    00321
    00322
    00323
    00324     /*
    00325      *  If instructed to do so, change Display mode before Reconnecting.
    00326      *  Use display resolution information from Reconnect data.
    00327      */
    00328
    00329     if (pDoReconnectData->fChangeDisplaySettings) {
    00330        DEVMODEW devmodew;
    00331        UNICODE_STRING ustrDeviceName;
    00332        PDEVMODEW pDevmodew = &devmodew;
    00333
    00334        RtlZeroMemory(pDevmodew, sizeof(DEVMODEW));
    00335        pDevmodew->dmPelsHeight = pDoReconnectData->drPelsHeight;
    00336        pDevmodew->dmPelsWidth  = pDoReconnectData->drPelsWidth;
    00337        pDevmodew->dmBitsPerPel = pDoReconnectData->drBitsPerPel;
    00338        pDevmodew->dmFields     = DM_BITSPERPEL  | DM_PELSWIDTH  | DM_PELSHEIGHT;
    00339        pDevmodew->dmSize       = sizeof(DEVMODEW);
    00340
    00341        RtlInitUnicodeString(&ustrDeviceName, L"\\\\.\\DISPLAY1");
    00342
    00343
    00344        Status = xxxUserChangeDisplaySettings(NULL, //&ustrDeviceName,
    00345                                             &devmodew,
    00346                                             NULL,
    00347                                             grpdeskRitInput,
    00348                                             0,
    00349                                             NULL,
    00350                                             KernelMode);
    00351        /*
    00352         * If Display settings change fails, let us disconnect the display driver
    00353         * as the reconnect is going to be failed anyway.
    00354         */
    00355
    00356
    00357        if (!NT_SUCCESS(Status)) {
    00358           bDrvDisconnect(gpDispInfo->hDev, ghRemoteThinwireChannel, gThinwireFileObject);
    00359           return Status;
    00360        }
    00361
    00362        /*
    00363         * Code in RemoteRedrawScreen() Expects gpDispInfo->pmdev to disabled, but
    00364         * it has been enabled by xxxUserChangeDisplaySettings(), so let's disable it
    00365         * before calling RemoteRedrawScreen().
    00366         */
    00367        DrvDisableMDEV(gpDispInfo->pmdev, TRUE);
    00368
    00369     }
    00370
    00371     /*
    00372      * Now we can swicth out from disconnected desktop, to normal
    00373      * desktop, in order to renable screen update.
    00374      */
    00375
    00376     RemoteRedrawScreen();
    00377
    00378     if (gspwndLogonNotify != NULL) {
    00379         _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY,
    00380                      SESSION_RECONNECTED, 0);
    00381     }
    00382
    00383     /*
    00384      * We need to re-init the mouse, especially since we may not have had one before.
    00385      */
    00386     UpdateMouseInfo();
    00387
    00388     /*
    00389      * Re-init'ing the keyboard may not be as neccessary.  Possibly the keyboard
    00390      * attributes have changed.
    00391      */
    00392     InitKeyboard();
    00393
    00394     /*
    00395      * This is neccessary to sync up the client and the host.
    00396      */
    00397     UpdateKeyLights(FALSE);
    00398
    00399     SetPointer(TRUE);
    00400
    00401     gbConnected = TRUE;
    00402
    00403
    00404
    00405     return Status;
    00406 }
    00407
    00408 /*
    00409  * This allows ICASRV to cleanly logoff the user.  We send a message to winlogon and let
    00410  * him do it.  We used to call ExitWindowsEx() directly, but that caused too many problems
    00411  * when it was called from CSRSS.
    00412  *
    00413  */
    00414 NTSTATUS
    00415 RemoteLogoff(
    00416     VOID)
    00417 {
    00418     NTSTATUS Status = STATUS_SUCCESS;
    00419
    00420     TRACE_HYDAPI(("RemoteLogoff\n"));
    00421
    00422     /*
    00423      * Only allow CSRSS to do this
    00424      */
    00425     if (!ISCSRSS() || !ISTS()) {
    00426         return STATUS_ACCESS_DENIED;
    00427     }
    00428
    00429     HYDRA_HINT(HH_REMOTELOGOFF);
    00430
    00431     UserAssert(ISCSRSS());
    00432
    00433     /*
    00434      * Tell winlogon about the logoff
    00435      */
    00436     if (gspwndLogonNotify != NULL) {
    00437         _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY,
    00438                      SESSION_LOGOFF, EWX_LOGOFF | EWX_FORCE);
    00439     }
    00440
    00441     return Status;
    00442 }
    00443
    00444
    00445 NTSTATUS
    00446 xxxRemoteStopScreenUpdates(
    00447     BOOL fDisableGraphics)
    00448 {
    00449     NTSTATUS Status = STATUS_SUCCESS;
    00450     NTSTATUS SaveStatus = STATUS_SUCCESS;
    00451     //ULONG BytesReturned;
    00452     WORD NewButtonState;
    00453
    00454     TRACE_HYDAPI(("xxxRemoteStopScreenUpdates fDisableGraphics %d\n", fDisableGraphics));
    00455
    00456     CheckCritIn();
    00457
    00458     UserAssert(ISCSRSS());
    00459
    00460     /*
    00461      * No need to do this multiple times.
    00462      */
    00463     if (gbFreezeScreenUpdates)
    00464         return STATUS_SUCCESS;
    00465
    00466     /*
    00467      * This could be called directly from the command channel.
    00468      */
    00469     if (!gspdeskDisconnect)
    00470         return STATUS_SUCCESS;
    00471
    00472     /*
    00473      * If not connected, forget it
    00474      */
    00475     if (ghRemoteVideoChannel == NULL)
    00476         return STATUS_NO_SUCH_DEVICE;
    00477
    00478     /*
    00479      * Mouse buttons up.
    00480      * (Ensures no mouse buttons are left in a down state)
    00481      */
    00482     NewButtonState = gwMKButtonState & ~gwMKCurrentButton;
    00483
    00484     if ((NewButtonState & MOUSE_BUTTON_LEFT) != (gwMKButtonState & MOUSE_BUTTON_LEFT)) {
    00485         xxxButtonEvent(MOUSE_BUTTON_LEFT, gptCursorAsync, TRUE, NtGetTickCount(),
    00486                     0L, 0L, FALSE);
    00487     }
    00488
    00489     if ((NewButtonState & MOUSE_BUTTON_RIGHT) != (gwMKButtonState & MOUSE_BUTTON_RIGHT)) {
    00490         xxxButtonEvent(MOUSE_BUTTON_RIGHT, gptCursorAsync, TRUE, NtGetTickCount(),
    00491                     0L, 0L, FALSE);
    00492     }
    00493     gwMKButtonState = NewButtonState;
    00494
    00495     /*
    00496      * Send shift key breaks to win32
    00497      * (Ensures no shift keys are left on)
    00498      */
    00499
    00500     // { 0, 0xb8, KEY_BREAK, 0, 0 },           // L alt
    00501     xxxPushKeyEvent(VK_LMENU, 0xb8, KEYEVENTF_KEYUP, 0);
    00502
    00503     // { 0, 0xb8, KEY_BREAK | KEY_E0, 0, 0 },  // R alt
    00504     xxxPushKeyEvent(VK_RMENU, 0xb8, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    00505
    00506     // { 0, 0x9d, KEY_BREAK, 0, 0 },           // L ctrl
    00507     xxxPushKeyEvent(VK_LCONTROL, 0x9d, KEYEVENTF_KEYUP, 0);
    00508
    00509     // { 0, 0x9d, KEY_BREAK | KEY_E0, 0, 0 },  // R ctrl
    00510     xxxPushKeyEvent(VK_RCONTROL, 0x9d, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    00511
    00512     // { 0, 0xaa, KEY_BREAK, 0, 0 },           // L shift
    00513     xxxPushKeyEvent(VK_LSHIFT, 0xaa, KEYEVENTF_KEYUP, 0);
    00514
    00515     // { 0, 0xb6, KEY_BREAK, 0, 0 }            // R shift
    00516     xxxPushKeyEvent(VK_RSHIFT, 0xb6, KEYEVENTF_KEYUP, 0);
    00517
    00518     Status = RemoteDisableScreen();
    00519
    00520     if (!NT_SUCCESS(Status)) {
    00521        return STATUS_NO_SUCH_DEVICE;
    00522     }
    00523
    00524     UserAssert(gspdeskDisconnect != NULL && grpdeskRitInput == gspdeskDisconnect);
    00525
    00526     gbFreezeScreenUpdates = TRUE;
    00527
    00528     return Status;
    00529     UNREFERENCED_PARAMETER(fDisableGraphics);
    00530 }
    00531
    00532 /*
    00533  * Taken from Internal Key Event.
    00534  * Minus any permissions checking.
    00535  */
    00536 VOID xxxPushKeyEvent(
    00537     BYTE  bVk,
    00538     BYTE  bScan,
    00539     DWORD dwFlags,
    00540     DWORD dwExtraInfo)
    00541 {
    00542     USHORT usFlaggedVK;
    00543
    00544     usFlaggedVK = (USHORT)bVk;
    00545
    00546     if (dwFlags & KEYEVENTF_KEYUP)
    00547         usFlaggedVK |= KBDBREAK;
    00548
    00549     // IanJa: not all extended keys are numpad, but this seems to work.
    00550     if (dwFlags & KEYEVENTF_EXTENDEDKEY)
    00551         usFlaggedVK |= KBDNUMPAD | KBDEXT;
    00552
    00553     xxxKeyEvent(usFlaggedVK, bScan, NtGetTickCount(), dwExtraInfo, FALSE);
    00554 }
    00555
    00556
    00557 NTSTATUS
    00558 RemoteThinwireStats(
    00559     OUT PVOID Stats)
    00560 {
    00561 static DWORD sThinwireStatsLength = sizeof(CACHE_STATISTICS);
    00562
    00563     TRACE_HYDAPI(("RemoteThinwireStats\n"));
    00564
    00565     /*
    00566      * Only allow CSRSS to do this
    00567      */
    00568     if (!ISCSRSS() || !ISTS()) {
    00569         return STATUS_ACCESS_DENIED;
    00570     }
    00571
    00572     UserAssert(ISCSRSS());
    00573     if (gpThinWireCache != NULL) {
    00574         RtlCopyMemory(Stats, gpThinWireCache, sThinwireStatsLength);
    00575         return STATUS_SUCCESS;
    00576     }
    00577     return STATUS_NO_SUCH_DEVICE;
    00578 }
    00579
    00580
    00581 NTSTATUS
    00582 RemoteNtSecurity(
    00583     VOID)
    00584 {
    00585     TRACE_HYDAPI(("RemoteNtSecurity\n"));
    00586
    00587     /*
    00588      * Only allow CSRSS to do this
    00589      */
    00590     if (!ISCSRSS() || !ISTS()) {
    00591         return STATUS_ACCESS_DENIED;
    00592     }
    00593
    00594     UserAssert(ISCSRSS());
    00595
    00596     UserAssert(gspwndLogonNotify != NULL);
    00597
    00598     if (gspwndLogonNotify != NULL) {
    00599         _PostMessage(gspwndLogonNotify, WM_HOTKEY, 0, 0);
    00600     }
    00601     return STATUS_SUCCESS;
    00602 }
    00603
    00604
    00605 NTSTATUS
    00606 xxxRemoteShadowSetup(
    00607     VOID)
    00608 {
    00609     NTSTATUS Status = STATUS_SUCCESS;
    00610
    00611     TRACE_HYDAPI(("xxxRemoteShadowSetup\n"));
    00612
    00613     /*
    00614      * Only allow CSRSS to do this
    00615      */
    00616     if (!ISCSRSS() || !ISTS()) {
    00617         return STATUS_ACCESS_DENIED;
    00618     }
    00619
    00620     UserAssert(ISCSRSS());
    00621
    00622     /*
    00623      * Blank the screen
    00624      */
    00625     if (gnShadowers || gbConnected)
    00626         xxxRemoteStopScreenUpdates(FALSE);
    00627
    00628     gnShadowers++;
    00629
    00630     return Status;
    00631 }
    00632
    00633
    00634 NTSTATUS
    00635 RemoteShadowStart(
    00636     IN PVOID pThinwireData,
    00637     ULONG ThinwireDataLength)
    00638 {
    00639     BOOL fResult;
    00640     NTSTATUS Status = STATUS_SUCCESS;
    00641
    00642     TRACE_HYDAPI(("RemoteShadowStart\n"));
    00643
    00644     /*
    00645      * Only allow CSRSS to do this
    00646      */
    00647     if (!ISCSRSS() || !ISTS()) {
    00648         return STATUS_ACCESS_DENIED;
    00649     }
    00650
    00651     UserAssert(ISCSRSS());
    00652
    00653     /*
    00654      * Call thinwire driver and check for thinwire mode compatibility
    00655      */
    00656     fResult = bDrvShadowConnect(gpDispInfo->hDev, pThinwireData,
    00657                                 ThinwireDataLength);
    00658
    00659     // Although originally defined as BOOL, allow more meaningful return codes.
    00660     if (!fResult) {
    00661         return STATUS_CTX_BAD_VIDEO_MODE;
    00662     }
    00663     else if (fResult != TRUE) {
    00664         return fResult;
    00665     }
    00666
    00667     RemoteRedrawScreen();
    00668
    00669     return Status;
    00670 }
    00671
    00672
    00673 NTSTATUS
    00674 xxxRemoteShadowStop(
    00675     VOID)
    00676 {
    00677     NTSTATUS Status = STATUS_SUCCESS;
    00678
    00679     TRACE_HYDAPI(("xxxRemoteShadowStop\n"));
    00680
    00681     /*
    00682      * Only allow CSRSS to do this
    00683      */
    00684     if (!ISCSRSS() || !ISTS()) {
    00685         return STATUS_ACCESS_DENIED;
    00686     }
    00687
    00688     UserAssert(ISCSRSS());
    00689
    00690     /*
    00691      * Blank the screen
    00692      */
    00693     xxxRemoteStopScreenUpdates(FALSE);
    00694
    00695     return Status;
    00696 }
    00697
    00698
    00699 NTSTATUS
    00700 RemoteShadowCleanup(
    00701     IN PVOID pThinwireData,
    00702     ULONG ThinwireDataLength)
    00703 {
    00704     NTSTATUS Status = STATUS_SUCCESS;
    00705
    00706     TRACE_HYDAPI(("RemoteShadowCleanup\n"));
    00707
    00708     /*
    00709      * Only allow CSRSS to do this
    00710      */
    00711     if (!ISCSRSS() || !ISTS()) {
    00712         return STATUS_ACCESS_DENIED;
    00713     }
    00714
    00715     UserAssert(ISCSRSS());
    00716
    00717     /*
    00718      * Tell the Thinwire driver about it
    00719      */
    00720     bDrvShadowDisconnect(gpDispInfo->hDev, pThinwireData,
    00721                          ThinwireDataLength);
    00722
    00723     if (gnShadowers > 0)
    00724         gnShadowers--;
    00725
    00726     if (gnShadowers || gbConnected) {
    00727         RemoteRedrawScreen();
    00728     }
    00729
    00730     return Status;
    00731 }
    00732
    00733
    00734 NTSTATUS
    00735 xxxRemotePassthruEnable(
    00736     VOID)
    00737 {
    00738     IO_STATUS_BLOCK IoStatus;
    00739 static BOOL KeyboardType101;
    00740
    00741     TRACE_HYDAPI(("xxxRemotePassthruEnable\n"));
    00742
    00743     /*
    00744      * Only allow CSRSS to do this
    00745      */
    00746     if (!ISCSRSS() || !ISTS()) {
    00747         return STATUS_ACCESS_DENIED;
    00748     }
    00749
    00750     UserAssert(gbConnected);
    00751     UserAssert(gnShadowers == 0);
    00752     UserAssert(ISCSRSS());
    00753
    00754     KeyboardType101 = !(gapulCvt_VK == gapulCvt_VK_84);
    00755
    00756     ZwDeviceIoControlFile(ghRemoteKeyboardChannel, NULL, NULL, NULL,
    00757                           &IoStatus, IOCTL_KEYBOARD_ICA_TYPE,
    00758                           &KeyboardType101, sizeof(KeyboardType101),
    00759                           NULL, 0);
    00760
    00761     if (guKbdTblSize != 0) {
    00762         ZwDeviceIoControlFile(ghRemoteKeyboardChannel, NULL, NULL, NULL,
    00763                               &IoStatus, IOCTL_KEYBOARD_ICA_LAYOUT,
    00764                               ghKbdTblBase, guKbdTblSize,
    00765                               gpKbdTbl, 0);
    00766     }
    00767
    00768     xxxRemoteStopScreenUpdates(FALSE);
    00769
    00770     /*
    00771      * Tell thinwire driver about this
    00772      */
    00773     bDrvDisconnect(gpDispInfo->hDev, ghRemoteThinwireChannel,
    00774                    gThinwireFileObject);
    00775
    00776     return STATUS_SUCCESS;
    00777 }
    00778
    00779
    00780 NTSTATUS
    00781 RemotePassthruDisable(
    00782     VOID)
    00783 {
    00784     BOOL fResult;
    00785
    00786     TRACE_HYDAPI(("RemotePassthruDisable\n"));
    00787
    00788     /*
    00789      * Only allow CSRSS to do this
    00790      */
    00791     if (!ISCSRSS() || !ISTS()) {
    00792         return STATUS_ACCESS_DENIED;
    00793     }
    00794
    00795     UserAssert(gnShadowers == 0);
    00796     UserAssert(ISCSRSS());
    00797
    00798     fResult = bDrvReconnect(gpDispInfo->hDev, ghRemoteThinwireChannel,
    00799                             gThinwireFileObject);
    00800     if (!fResult) {
    00801         return STATUS_CTX_BAD_VIDEO_MODE;
    00802     }
    00803
    00804     if (gbConnected) {
    00805         RemoteRedrawScreen();
    00806         UpdateKeyLights(FALSE); // Make sure LED's are correct
    00807     }
    00808
    00809     return STATUS_SUCCESS;
    00810 }
    00811
    00812
    00813 NTSTATUS
    00814 CtxDisplayIOCtl(
    00815     ULONG  DisplayIOCtlFlags,
    00816     PUCHAR pDisplayIOCtlData,
    00817     ULONG  cbDisplayIOCtlData)
    00818 {
    00819     BOOL fResult;
    00820
    00821     TRACE_HYDAPI(("CtxDisplayIOCtl\n"));
    00822
    00823     fResult = bDrvDisplayIOCtl(gpDispInfo->hDev, pDisplayIOCtlData, cbDisplayIOCtlData);
    00824
    00825     if (!fResult) {
    00826         return STATUS_CTX_BAD_VIDEO_MODE;
    00827     }
    00828
    00829     if ((DisplayIOCtlFlags & DISPLAY_IOCTL_FLAG_REDRAW)) {
    00830         RemoteRedrawRectangle(0,0,0xffff,0xffff);
    00831     }
    00832
    00833     return STATUS_SUCCESS;
    00834 }
    00835
    00836
    00837 /*
    00838  * This is for things like user32.dll init routines that don't want to use
    00839  * winsta.dll for queries.
    00840  *
    00841  */
    00842 DWORD
    00843 RemoteConnectState(
    00844     VOID)
    00845 {
    00846     DWORD state = 0;
    00847
    00848     if (!gbRemoteSession) {
    00849
    00850         state = CTX_W32_CONNECT_STATE_CONSOLE;
    00851
    00852     } else if (!gbVideoInitialized) {
    00853
    00854         state = CTX_W32_CONNECT_STATE_IDLE;
    00855
    00856     } else if (gbExitInProgress) {
    00857
    00858         state = CTX_W32_CONNECT_STATE_EXIT_IN_PROGRESS;
    00859
    00860     } else if (gbConnected) {
    00861
    00862         state = CTX_W32_CONNECT_STATE_CONNECTED;
    00863
    00864     } else {
    00865         state = CTX_W32_CONNECT_STATE_DISCONNECTED;
    00866     }
    00867
    00868     return state;
    00869 }
    00870
    00871 BOOL
    00872 _GetWinStationInfo(
    00873     WSINFO* pWsInfo)
    00874 {
    00875     CheckCritIn();
    00876
    00877     try {
    00878
    00879         ProbeForWrite(pWsInfo, sizeof(gWinStationInfo), DATAALIGN);
    00880         RtlCopyMemory(pWsInfo, &gWinStationInfo, sizeof(gWinStationInfo));
    00881
    00882     } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
    00883         return FALSE;
    00884     }
    00885
    00886     return TRUE;
    00887 }