Sync with trunk r58687.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 6 Apr 2013 15:28:22 +0000 (15:28 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 6 Apr 2013 15:28:22 +0000 (15:28 +0000)
svn path=/branches/ros-csrss/; revision=58690

243 files changed:
1  2 
base/applications/atactl/atactl.cpp
base/applications/calc/lang/el-GR.rc
base/applications/calc/lang/ko-KR.rc
base/applications/calc/lang/th-TH.rc
base/applications/network/wlanconf/lang/it-IT.rc
base/applications/rapps/lang/fr-FR.rc
base/applications/sndrec32/audio_resampler_acm.cpp
base/applications/sndrec32/audio_wavein.hpp
base/applications/sndrec32/audio_waveout.cpp
base/applications/sndrec32/lang/de-DE.rc
base/applications/sndrec32/lang/en-US.rc
base/applications/sndrec32/lang/es-ES.rc
base/services/eventlog/file.c
base/shell/cmd/copy.c
base/shell/cmd/del.c
base/shell/cmd/readme2.txt
base/shell/cmd/ren.c
base/shell/cmd/ren.txt
base/shell/cmd/todo.txt
boot/freeldr/freeldr/arch/amd64/winldr.c
boot/freeldr/freeldr/arch/i386/winldr.c
boot/freeldr/freeldr/arch/powerpc/mboot.c
boot/freeldr/freeldr/include/fs/ext2.h
boot/freeldr/freeldr/include/keycodes.h
boot/freeldr/freeldr/include/ui.h
boot/freeldr/freeldr/include/ui/gui.h
boot/freeldr/freeldr/include/ui/noui.h
boot/freeldr/freeldr/include/ui/tui.h
boot/freeldr/freeldr/ui/directui.c
boot/freeldr/freeldr/ui/gui.c
boot/freeldr/freeldr/ui/minitui.c
boot/freeldr/freeldr/ui/noui.c
boot/freeldr/freeldr/ui/tui.c
boot/freeldr/freeldr/ui/tuimenu.c
boot/freeldr/freeldr/ui/ui.c
cmake/CMakeMacros.cmake
cmake/Platform/Windows-MSVC.cmake
cmake/gcc.cmake
cmake/msvc.cmake
dll/directx/ksproxy/clockforward.cpp
dll/directx/ksproxy/input_pin.cpp
dll/directx/ksproxy/ksproxy.cpp
dll/directx/ksproxy/proxy.cpp
dll/directx/ksproxy/qualityforward.cpp
dll/directx/wine/wined3d/directx.c
dll/opengl/mesa/src/mesa/CMakeLists.txt
dll/win32/crypt32/CMakeLists.txt
dll/win32/crypt32/base64.c
dll/win32/crypt32/cert.c
dll/win32/crypt32/chain.c
dll/win32/crypt32/decode.c
dll/win32/crypt32/message.c
dll/win32/crypt32/msg.c
dll/win32/crypt32/object.c
dll/win32/crypt32/oid.c
dll/win32/crypt32/rootstore.c
dll/win32/crypt32/serialize.c
dll/win32/crypt32/sip.c
dll/win32/crypt32/store.c
dll/win32/jscript/CMakeLists.txt
dll/win32/jscript/activex.c
dll/win32/jscript/array.c
dll/win32/jscript/bool.c
dll/win32/jscript/compile.c
dll/win32/jscript/date.c
dll/win32/jscript/decode.c
dll/win32/jscript/dispex.c
dll/win32/jscript/engine.c
dll/win32/jscript/engine.h
dll/win32/jscript/error.c
dll/win32/jscript/function.c
dll/win32/jscript/global.c
dll/win32/jscript/jscript.c
dll/win32/jscript/jscript.h
dll/win32/jscript/jscript.rc
dll/win32/jscript/jscript.rgs
dll/win32/jscript/jscript_classes.idl
dll/win32/jscript/jscript_classes.rgs
dll/win32/jscript/jscript_main.c
dll/win32/jscript/jsregexp.c
dll/win32/jscript/jsstr.c
dll/win32/jscript/jsstr.h
dll/win32/jscript/jsutils.c
dll/win32/jscript/jsval.h
dll/win32/jscript/lex.c
dll/win32/jscript/math.c
dll/win32/jscript/number.c
dll/win32/jscript/object.c
dll/win32/jscript/parser.tab.c
dll/win32/jscript/parser.tab.h
dll/win32/jscript/parser.y
dll/win32/jscript/regexp.c
dll/win32/jscript/regexp.h
dll/win32/jscript/resource.h
dll/win32/jscript/rsrc.rc
dll/win32/jscript/string.c
dll/win32/jscript/vbarray.c
dll/win32/kernel32/client/path.c
dll/win32/kernel32/winnls/lang/de-DE.mc
dll/win32/msi/action.c
dll/win32/msi/automation.c
dll/win32/msi/custom.c
dll/win32/msi/dialog.c
dll/win32/msi/files.c
dll/win32/msi/msi.c
dll/win32/msi/msi.spec
dll/win32/msi/msipriv.h
dll/win32/msi/package.c
dll/win32/msi/record.c
dll/win32/msi/registry.c
dll/win32/msi/streams.c
dll/win32/msi/suminfo.c
dll/win32/msi/where.c
dll/win32/samsrv/samrpc.c
dll/win32/samsrv/samsrv.h
dll/win32/samsrv/setup.c
dll/win32/samsrv/user.c
dll/win32/shell32/dde.cpp
dll/win32/shell32/shellitem.cpp
dll/win32/shell32/shellitem.h
dll/win32/usp10/bidi.c
dll/win32/usp10/shape.c
dll/win32/usp10/usp10.c
dll/win32/xmllite/reader.c
dll/win32/xmllite/xmllite_main.c
drivers/filesystems/cdfs/cdfs.c
drivers/filesystems/fastfat/fastio.c
drivers/filesystems/fastfat_new/fastio.c
drivers/filesystems/mup/mup.c
drivers/filesystems/ntfs/ntfs.c
drivers/ksfilter/ks/api.c
drivers/multimedia/audio/mpu401_nt4/mpu401.c
drivers/multimedia/audio/sndblst.old/sndblst.c
drivers/multimedia/audio/sound/sb16.c
drivers/multimedia/audio/sound/sound.c
drivers/network/tcpip/datalink/lan.c
drivers/parallel/parallel/parallel.c
drivers/storage/class/cdrom/cdrom.c
drivers/storage/class/class2/class2.c
drivers/storage/classpnp/obsolete.c
drivers/storage/classpnp/power.c
drivers/storage/ide/uniata/atapi.h
drivers/storage/ide/uniata/bm_devs.h
drivers/storage/ide/uniata/id_ata.cpp
drivers/storage/ide/uniata/id_init.cpp
drivers/storage/ide/uniata/id_probe.cpp
drivers/storage/ide/uniata/id_sata.cpp
drivers/storage/ide/uniata/uniata_ver.h
drivers/usb/usbehci/hardware.cpp
drivers/usb/usbohci/hardware.cpp
drivers/usb/usbuhci/hardware.cpp
drivers/wdm/audio/CMakeLists.txt
drivers/wdm/audio/backpln/portcls/CMakeLists.txt
drivers/wdm/audio/backpln/portcls/guids.cpp
drivers/wdm/audio/drivers/CMIDriver/CHANGELOG.txt
drivers/wdm/audio/drivers/CMIDriver/CMakeLists.txt
drivers/wdm/audio/drivers/CMIDriver/adapter.cpp
drivers/wdm/audio/drivers/CMIDriver/adapter.hpp
drivers/wdm/audio/drivers/CMIDriver/cmicontrol/CMakeLists.txt
drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.cpp
drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.h
drivers/wdm/audio/drivers/CMIDriver/cmicontrol/resource.h
drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.rc
drivers/wdm/audio/drivers/CMIDriver/cmipci.rc
drivers/wdm/audio/drivers/CMIDriver/cmireg.hpp
drivers/wdm/audio/drivers/CMIDriver/common.cpp
drivers/wdm/audio/drivers/CMIDriver/common.hpp
drivers/wdm/audio/drivers/CMIDriver/cpl/CMakeLists.txt
drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.cpp
drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc
drivers/wdm/audio/drivers/CMIDriver/cpl/resource.h
drivers/wdm/audio/drivers/CMIDriver/debug.hpp
drivers/wdm/audio/drivers/CMIDriver/interfaces.hpp
drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp
drivers/wdm/audio/drivers/CMIDriver/mintopo.hpp
drivers/wdm/audio/drivers/CMIDriver/mintopotables.hpp
drivers/wdm/audio/drivers/CMIDriver/minwave.cpp
drivers/wdm/audio/drivers/CMIDriver/minwave.hpp
drivers/wdm/audio/drivers/CMIDriver/minwavetables.hpp
drivers/wdm/audio/drivers/CMIDriver/property.h
drivers/wdm/audio/drivers/CMakeLists.txt
hal/halppc/generic/display.c
hal/halppc/generic/dma.c
hal/halppc/up/halinit_up.c
hal/halx86/apic/apic.c
hal/halx86/apic/halinit_apic.c
hal/halx86/generic/dma.c
hal/halx86/mp/halinit_mp.c
hal/halx86/up/halinit_mini.c
hal/halx86/up/halinit_up.c
hal/halx86/xbox/halinit_xbox.c
include/ddk/dmusicks.h
include/ddk/dmusprop.h
include/ddk/portcls.h
include/ndk/iofuncs.h
include/psdk/dsound.h
include/psdk/kcom.h
include/psdk/ks.h
include/psdk/ksmedia.h
include/psdk/ksproxy.h
include/psdk/msi.h
include/psdk/ntdef.h
include/psdk/winioctl.h
include/psdk/winnt.h
include/reactos/idl/sam.idl
lib/cmlib/hiveinit.c
lib/drivers/libusb/common_interfaces.h
lib/drivers/libusb/hcd_controller.cpp
lib/drivers/libusb/hub_controller.cpp
lib/drivers/libusb/usb_device.cpp
lib/drivers/lwip/src/core/snmp/msg_out.c
lib/drivers/lwip/src/core/tcp_in.c
lib/drivers/sound/CMakeLists.txt
lib/drivers/sound/stdunk/CMakeLists.txt
lib/drivers/sound/stdunk/cunknown.cpp
lib/sdk/crt/include/internal/locale.h
lib/sdk/crt/include/internal/wine/msvcrt.h
lib/sdk/crt/locale/locale.c
lib/sdk/crt/mbstring/_setmbcp.c
lib/sdk/crt/misc/environ.c
lib/sdk/crt/stdio/stat.c
lib/smlib/smclient.c
media/doc/README.WINE
media/inf/syssetup.inf
ntoskrnl/ex/event.c
ntoskrnl/ex/evtpair.c
ntoskrnl/ex/mutant.c
ntoskrnl/ex/zone.c
ntoskrnl/io/iomgr/driver.c
ntoskrnl/io/iomgr/util.c
ntoskrnl/io/pnpmgr/pnputil.c
ntoskrnl/kd/kdio.c
ntoskrnl/ke/amd64/krnlinit.c
ntoskrnl/ke/i386/usercall_asm.S
ntoskrnl/ke/thrdobj.c
ntoskrnl/ke/timerobj.c
ntoskrnl/mm/ARM3/virtual.c
ntoskrnl/se/semgr.c
win32ss/drivers/font/ftfd/font.c
win32ss/user/ntuser/focus.c
win32ss/user/ntuser/winsta.c
win32ss/user/user32/windows/cursoricon.c
win32ss/user/user32/windows/cursoricon_new.c

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc cmake/gcc.cmake
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,10bed1c..10bed1c
mode 000000,100644..100644
--- /dev/null
Simple merge
index 0000000,bae0a39..bae0a39
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,eb8e158..eb8e158
mode 000000,100644..100644
--- /dev/null
index 0000000,b4da2b5..b4da2b5
mode 000000,100644..100644
--- /dev/null
Simple merge
index 0000000,09eaa7f..09eaa7f
mode 000000,100644..100644
--- /dev/null
index 0000000,48adf94..48adf94
mode 000000,100644..100644
--- /dev/null
index 0000000,c71cbea..c71cbea
mode 000000,100644..100644
--- /dev/null
Simple merge
index 0000000,963f59f..963f59f
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,de86aa2..de86aa2
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
index 0000000,593d62f..593d62f
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index df89854,0000000..08036c5
mode 100644,000000..100644
--- /dev/null
@@@ -1,168 -1,0 +1,168 @@@
-     /* Initalize this specific API's parameters */
 +/*
 + * PROJECT:         ReactOS Windows-Compatible Session Manager
 + * LICENSE:         BSD 2-Clause License
 + * FILE:            lib/smlib/smclient.c
 + * PURPOSE:         SMSS Client Library Stubs for calling SM APIs from a client
 + * PROGRAMMERS:     Alex Ionescu
 + */
 +
 +/* INCLUDES *******************************************************************/
 +
 +#include "precomp.h"
 +#include "sm/smmsg.h" // To go in precomp.h after
 +#define NDEBUG
 +#include "debug.h"
 +
 +/* FUNCTIONS ******************************************************************/
 +
 +NTSTATUS
 +NTAPI
 +SmExecPgm(IN HANDLE SmApiPort,
 +          IN PRTL_USER_PROCESS_INFORMATION ProcessInformation,
 +          IN BOOLEAN DebugFlag)
 +{
 +    NTSTATUS Status;
 +    SM_API_MSG SmApiMsg;
 +
 +#if 0 //def _WIN64 // You can take care of this Timo
 +    /* 64-bit SMSS needs to talk to 32-bit processes so do the LPC conversion */
 +    if (SmpIsWow64Process())
 +    {
 +        return SmpWow64ExecPgm(SmApiPort, ProcessInformation, DebugFlag);
 +    }
 +#endif
 +
 +    /* Initialize the generic LPC header */
 +    SmApiMsg.h.u2.ZeroInit = 0;
 +    SmApiMsg.h.u1.s1.DataLength = sizeof(SM_EXEC_PGM_MSG) + 8;
 +    SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg);
 +
++    /* Initialize this specific API's parameters */
 +    SmApiMsg.ApiNumber = SmpExecPgmApi;
 +    RtlCopyMemory(&SmApiMsg.u.ExecPgm.ProcessInformation,
 +                  ProcessInformation,
 +                  sizeof(SmApiMsg.u.ExecPgm.ProcessInformation));
 +    SmApiMsg.u.ExecPgm.DebugFlag = DebugFlag;
 +
 +    /* Send the message to SMSS */
 +    Status = NtRequestWaitReplyPort(SmApiPort, &SmApiMsg.h, &SmApiMsg.h);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        DPRINT1("SmExecPgm: NtRequestWaitReply Failed %lx\n", Status);
 +    }
 +    else
 +    {
 +        /* Upon success, we use the API's return value */
 +        Status = SmApiMsg.ReturnValue;
 +    }
 +
 +    /* Close the handles that the parent passed in and return status */
 +    NtClose(ProcessInformation->ProcessHandle);
 +    NtClose(ProcessInformation->ThreadHandle);
 +    return Status;
 +}
 +
 +NTSTATUS
 +NTAPI
 +SmConnectToSm(IN PUNICODE_STRING SbApiPortName,
 +              IN HANDLE SbApiPort,
 +              IN ULONG ImageType,
 +              IN HANDLE SmApiPort)
 +{
 +    NTSTATUS Status;
 +    SB_CONNECTION_INFO ConnectInfo;
 +    UNICODE_STRING DestinationString;
 +    SECURITY_QUALITY_OF_SERVICE SecurityQos;
 +    ULONG ConnectInfoLength = sizeof(ConnectInfo);
 +
 +    /* Setup the QoS structure */
 +    SecurityQos.ImpersonationLevel = SecurityIdentification;
 +    SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
 +    SecurityQos.EffectiveOnly = TRUE;
 +
 +    /* Set the SM API port name */
 +    RtlInitUnicodeString(&DestinationString, L"\\SmApiPort2");
 +
 +    /* Check if this is a client connecting to SMSS, or SMSS to itself */
 +    if (SbApiPortName)
 +    {
 +        /* A client SB port as well as an image type must be present */
 +        if (!(SbApiPort) || !(ImageType)) return STATUS_INVALID_PARAMETER_MIX;
 +
 +        /* Copy the client port name, and NULL-terminate it */
 +        RtlCopyMemory(ConnectInfo.SbApiPortName,
 +                      SbApiPortName->Buffer,
 +                      SbApiPortName->Length);
 +        ConnectInfo.SbApiPortName[SbApiPortName->Length /
 +                                  sizeof(WCHAR)] = UNICODE_NULL;
 +
 +        /* Save the subsystem type */
 +        ConnectInfo.SubsystemType = ImageType;
 +    }
 +    else
 +    {
 +        /* No client port, and the subsystem type is not set */
 +        ConnectInfo.SbApiPortName[0] = UNICODE_NULL;
 +        ConnectInfo.SubsystemType = IMAGE_SUBSYSTEM_UNKNOWN;
 +    }
 +
 +    /* Connect to SMSS and exchange connection information */
 +    Status = NtConnectPort(SmApiPort,
 +                           &DestinationString,
 +                           &SecurityQos,
 +                           NULL,
 +                           NULL,
 +                           NULL,
 +                           &ConnectInfo,
 +                           &ConnectInfoLength);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        DPRINT1("SmConnectToSm: Connect to Sm failed %lx\n", Status);
 +    }
 +    else
 +    {
 +        /* Treat a warning or informational status as success */
 +        Status = STATUS_SUCCESS;
 +    }
 +
 +    /* Return if the connection was successful or not */
 +    return Status;
 +}
 +
 +NTSTATUS
 +NTAPI
 +SmSessionComplete(IN HANDLE SmApiPort,
 +                  IN ULONG SessionId,
 +                  IN NTSTATUS SessionStatus)
 +{
 +    NTSTATUS Status;
 +    SM_API_MSG ApiMessage;
 +    PSM_SESSION_COMPLETE_MSG SessionComplete = &ApiMessage.u.SessionComplete;
 +
 +    /* Set the message data */
 +    SessionComplete->SessionId = SessionId;
 +    SessionComplete->SessionStatus = SessionStatus;
 +
 +    /* Set the API Message Port Message header */
 +    ApiMessage.ApiNumber = SmpSessionCompleteApi;
 +    ApiMessage.h.u1.s1.DataLength = sizeof(SM_SESSION_COMPLETE_MSG) + 8;
 +    ApiMessage.h.u1.s1.TotalLength = sizeof(SM_API_MSG);
 +    ApiMessage.h.u2.ZeroInit = 0;
 +
 +    /* Sent the message and wait for a reply */
 +    Status = NtRequestWaitReplyPort(SmApiPort,
 +                                    &ApiMessage.h,
 +                                    &ApiMessage.h);
 +    if (NT_SUCCESS(Status))
 +    {
 +        /* Return the real status */
 +        Status = ApiMessage.ReturnValue;
 +    }
 +    else
 +    {
 +        DPRINT1("SmCompleteSession: NtRequestWaitReply failed\n");
 +    }
 +
 +    /* Return status */
 +    return Status;
 +}
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index e1ce7e5,0000000..290b575
mode 100644,000000..100644
--- /dev/null
@@@ -1,1347 -1,0 +1,1347 @@@
- /* INITALIZATION FUNCTIONS ****************************************************/
 +/*
 + *  COPYRIGHT:        See COPYING in the top level directory
 + *  PROJECT:          ReactOS Win32k subsystem
 + *  PURPOSE:          Window stations
 + *  FILE:             subsystems/win32/win32k/ntuser/winsta.c
 + *  PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
 + *  TODO:             The process window station is created on
 + *                    the first USER32/GDI32 call not related
 + *                    to window station/desktop handling
 + */
 +
 +#include <win32k.h>
 +DBG_DEFAULT_CHANNEL(UserWinsta);
 +
 +/* GLOBALS *******************************************************************/
 +
 +/* Currently active window station */
 +PWINSTATION_OBJECT InputWindowStation = NULL;
 +
 +/* Winlogon SAS window */
 +HWND hwndSAS = NULL;
 +
 +/* Full path to WindowStations directory */
 +UNICODE_STRING gustrWindowStationsDir;
 +
++/* INITIALIZATION FUNCTIONS ****************************************************/
 +
 +INIT_FUNCTION
 +NTSTATUS
 +NTAPI
 +InitWindowStationImpl(VOID)
 +{
 +   GENERIC_MAPPING IntWindowStationMapping = { WINSTA_READ,
 +                                               WINSTA_WRITE,
 +                                               WINSTA_EXECUTE,
 +                                               WINSTA_ACCESS_ALL};
 +
 +   /* Set Winsta Object Attributes */
 +   ExWindowStationObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(WINSTATION_OBJECT);
 +   ExWindowStationObjectType->TypeInfo.GenericMapping = IntWindowStationMapping;
 +   ExWindowStationObjectType->TypeInfo.ValidAccessMask = WINSTA_ACCESS_ALL;
 +
 +   return STATUS_SUCCESS;
 +}
 +
 +NTSTATUS
 +NTAPI
 +UserCreateWinstaDirectory()
 +{
 +    PPEB Peb;
 +    NTSTATUS Status;
 +    WCHAR wstrWindowStationsDir[MAX_PATH];
 +    OBJECT_ATTRIBUTES ObjectAttributes;
 +    HANDLE hWinstaDir;
 +
 +    /* Create the WindowStations directory and cache its path for later use */
 +    Peb = NtCurrentPeb();
 +    if(Peb->SessionId == 0)
 +    {
 +        if (!RtlCreateUnicodeString(&gustrWindowStationsDir, WINSTA_OBJ_DIR))
 +        {
 +            return STATUS_INSUFFICIENT_RESOURCES;
 +        }
 +    }
 +    else
 +    {
 +        swprintf(wstrWindowStationsDir,
 +                 L"%ws\\%ld%ws",
 +                 SESSION_DIR,
 +                 Peb->SessionId,
 +                 WINSTA_OBJ_DIR);
 +
 +        if (!RtlCreateUnicodeString(&gustrWindowStationsDir, wstrWindowStationsDir))
 +        {
 +            return STATUS_INSUFFICIENT_RESOURCES;
 +        }
 +    }
 +
 +   InitializeObjectAttributes(&ObjectAttributes,
 +                              &gustrWindowStationsDir,
 +                              0,
 +                              NULL,
 +                              NULL);
 +   Status = ZwCreateDirectoryObject(&hWinstaDir, 0, &ObjectAttributes);
 +   if (!NT_SUCCESS(Status))
 +   {
 +       ERR("Could not create %wZ directory (Status 0x%X)\n", &gustrWindowStationsDir,  Status);
 +      return Status;
 +   }
 +
 +   TRACE("Created directory %wZ for session %d\n", &gustrWindowStationsDir, Peb->SessionId);
 +
 +   return Status;
 +}
 +
 +/* OBJECT CALLBACKS  **********************************************************/
 +
 +VOID APIENTRY
 +IntWinStaObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters)
 +{
 +   PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)Parameters->Object;
 +
 +   TRACE("Deleting window station (0x%X)\n", WinSta);
 +
 +   UserEmptyClipboardData(WinSta);
 +
 +   RtlDestroyAtomTable(WinSta->AtomTable);
 +
 +   RtlFreeUnicodeString(&WinSta->Name);
 +}
 +
 +NTSTATUS
 +APIENTRY
 +IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters)
 +{
 +    PUNICODE_STRING RemainingName = Parameters->RemainingName;
 +
 +    /* Assume we don't find anything */
 +    *Parameters->Object = NULL;
 +
 +    /* Check for an empty name */
 +    if (!RemainingName->Length)
 +    {
 +        /* Make sure this is a window station, can't parse a desktop now */
 +        if (Parameters->ObjectType != ExWindowStationObjectType)
 +        {
 +            /* Fail */
 +            return STATUS_OBJECT_TYPE_MISMATCH;
 +        }
 +
 +        /* Reference the window station and return */
 +        ObReferenceObject(Parameters->ParseObject);
 +        *Parameters->Object = Parameters->ParseObject;
 +        return STATUS_SUCCESS;
 +    }
 +
 +    /* Check for leading slash */
 +    if (RemainingName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
 +    {
 +        /* Skip it */
 +        RemainingName->Buffer++;
 +        RemainingName->Length -= sizeof(WCHAR);
 +        RemainingName->MaximumLength -= sizeof(WCHAR);
 +    }
 +
 +    /* Check if there is still a slash */
 +    if (wcschr(RemainingName->Buffer, OBJ_NAME_PATH_SEPARATOR))
 +    {
 +        /* In this case, fail */
 +        return STATUS_OBJECT_PATH_INVALID;
 +    }
 +
 +    /*
 +     * Check if we are parsing a desktop.
 +     */
 +    if (Parameters->ObjectType == ExDesktopObjectType)
 +    {
 +        /* Then call the desktop parse routine */
 +        return IntDesktopObjectParse(Parameters->ParseObject,
 +                                     Parameters->ObjectType,
 +                                     Parameters->AccessState,
 +                                     Parameters->AccessMode,
 +                                     Parameters->Attributes,
 +                                     Parameters->CompleteName,
 +                                     RemainingName,
 +                                     Parameters->Context,
 +                                     Parameters->SecurityQos,
 +                                     Parameters->Object);
 +    }
 +
 +    /* Should hopefully never get here */
 +    return STATUS_OBJECT_TYPE_MISMATCH;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IntWinstaOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters)
 +{
 +    PPROCESSINFO ppi;
 +
 +    ppi = PsGetCurrentProcessWin32Process();
 +
 +    if(ppi && (Parameters->Handle == ppi->hwinsta))
 +    {
 +        return STATUS_ACCESS_DENIED;
 +    }
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +/* PRIVATE FUNCTIONS **********************************************************/
 +
 +/*
 + * IntValidateWindowStationHandle
 + *
 + * Validates the window station handle.
 + *
 + * Remarks
 + *    If the function succeeds, the handle remains referenced. If the
 + *    fucntion fails, last error is set.
 + */
 +
 +NTSTATUS FASTCALL
 +IntValidateWindowStationHandle(
 +   HWINSTA WindowStation,
 +   KPROCESSOR_MODE AccessMode,
 +   ACCESS_MASK DesiredAccess,
 +   PWINSTATION_OBJECT *Object)
 +{
 +   NTSTATUS Status;
 +
 +   if (WindowStation == NULL)
 +   {
 +      ERR("Invalid window station handle\n");
 +      EngSetLastError(ERROR_INVALID_HANDLE);
 +      return STATUS_INVALID_HANDLE;
 +   }
 +
 +   Status = ObReferenceObjectByHandle(
 +               WindowStation,
 +               DesiredAccess,
 +               ExWindowStationObjectType,
 +               AccessMode,
 +               (PVOID*)Object,
 +               NULL);
 +
 +   if (!NT_SUCCESS(Status))
 +      SetLastNtError(Status);
 +
 +   return Status;
 +}
 +
 +BOOL FASTCALL
 +co_IntInitializeDesktopGraphics(VOID)
 +{
 +   TEXTMETRICW tmw;
 +   UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY");
 +
 +   ScreenDeviceContext = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
 +   if (NULL == ScreenDeviceContext)
 +   {
 +      IntDestroyPrimarySurface();
 +      return FALSE;
 +   }
 +   GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_PUBLIC);
 +
 +   if (! IntCreatePrimarySurface())
 +   {
 +      return FALSE;
 +   }
 +
 +   /* Setup the cursor */
 +   co_IntLoadDefaultCursors();
 +
 +   hSystemBM = NtGdiCreateCompatibleDC(ScreenDeviceContext);
 +
 +   NtGdiSelectFont(hSystemBM, NtGdiGetStockObject(SYSTEM_FONT));
 +   GreSetDCOwner(hSystemBM, GDI_OBJ_HMGR_PUBLIC);
 +
 +   // FIXME: Move these to a update routine.
 +   gpsi->Planes        = NtGdiGetDeviceCaps(ScreenDeviceContext, PLANES);
 +   gpsi->BitsPixel     = NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL);
 +   gpsi->BitCount      = gpsi->Planes * gpsi->BitsPixel;
 +   gpsi->dmLogPixels   = NtGdiGetDeviceCaps(ScreenDeviceContext, LOGPIXELSY);
 +   if (NtGdiGetDeviceCaps(ScreenDeviceContext, RASTERCAPS) & RC_PALETTE)
 +   {
 +      gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY;
 +   }
 +   else
 +      gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY;
 +   // Font is realized and this dc was previously set to internal DC_ATTR.
 +   gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw, (DWORD*)&gpsi->cySysFontChar);
 +   gpsi->tmSysFont     = tmw;
 +
 +   return TRUE;
 +}
 +
 +VOID FASTCALL
 +IntEndDesktopGraphics(VOID)
 +{
 +   if (NULL != ScreenDeviceContext)
 +   {  // No need to allocate a new dcattr.
 +      GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_POWNED);
 +      GreDeleteObject(ScreenDeviceContext);
 +      ScreenDeviceContext = NULL;
 +   }
 +   IntHideDesktop(IntGetActiveDesktop());
 +   IntDestroyPrimarySurface();
 +}
 +
 +HDC FASTCALL
 +IntGetScreenDC(VOID)
 +{
 +   return ScreenDeviceContext;
 +}
 +
 +/* PUBLIC FUNCTIONS ***********************************************************/
 +
 +/*
 + * NtUserCreateWindowStation
 + *
 + * Creates a new window station.
 + *
 + * Parameters
 + *    lpszWindowStationName
 + *       Pointer to a null-terminated string specifying the name of the
 + *       window station to be created. Window station names are
 + *       case-insensitive and cannot contain backslash characters (\).
 + *       Only members of the Administrators group are allowed to specify a
 + *       name.
 + *
 + *    dwDesiredAccess
 + *       Requested type of access
 + *
 + *    lpSecurity
 + *       Security descriptor
 + *
 + *    Unknown3, Unknown4, Unknown5
 + *       Unused
 + *
 + * Return Value
 + *    If the function succeeds, the return value is a handle to the newly
 + *    created window station. If the specified window station already
 + *    exists, the function succeeds and returns a handle to the existing
 + *    window station. If the function fails, the return value is NULL.
 + *
 + * Todo
 + *    Correct the prototype to match the Windows one (with 7 parameters
 + *    on Windows XP).
 + *
 + * Status
 + *    @implemented
 + */
 +
 +HWINSTA APIENTRY
 +NtUserCreateWindowStation(
 +   POBJECT_ATTRIBUTES ObjectAttributes,
 +   ACCESS_MASK dwDesiredAccess,
 +   DWORD Unknown2,
 +   DWORD Unknown3,
 +   DWORD Unknown4,
 +   DWORD Unknown5,
 +   DWORD Unknown6)
 +{
 +   UNICODE_STRING WindowStationName;
 +   PWINSTATION_OBJECT WindowStationObject;
 +   HWINSTA WindowStation;
 +   NTSTATUS Status;
 +
 +   TRACE("NtUserCreateWindowStation called\n");
 +
 +   Status = ObOpenObjectByName(
 +               ObjectAttributes,
 +               ExWindowStationObjectType,
 +               UserMode,
 +               NULL,
 +               dwDesiredAccess,
 +               NULL,
 +               (PVOID*)&WindowStation);
 +
 +   if (NT_SUCCESS(Status))
 +   {
 +       TRACE("NtUserCreateWindowStation opened window station %wZ\n", ObjectAttributes->ObjectName);
 +       return (HWINSTA)WindowStation;
 +   }
 +
 +   /*
 +    * No existing window station found, try to create new one
 +    */
 +
 +   /* Capture window station name */
 +   _SEH2_TRY
 +   {
 +      ProbeForRead( ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 1);
 +      Status = IntSafeCopyUnicodeStringTerminateNULL(&WindowStationName, ObjectAttributes->ObjectName);
 +   }
 +   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +   {
 +      Status =_SEH2_GetExceptionCode();
 +   }
 +   _SEH2_END
 +
 +   if (! NT_SUCCESS(Status))
 +   {
 +      ERR("Failed reading capturing window station name\n");
 +      SetLastNtError(Status);
 +      return NULL;
 +   }
 +
 +   /* Create the window station object */
 +   Status = ObCreateObject(
 +               UserMode,
 +               ExWindowStationObjectType,
 +               ObjectAttributes,
 +               UserMode,
 +               NULL,
 +               sizeof(WINSTATION_OBJECT),
 +               0,
 +               0,
 +               (PVOID*)&WindowStationObject);
 +
 +   if (!NT_SUCCESS(Status))
 +   {
 +      ERR("ObCreateObject failed for window station %wZ\n", &WindowStationName);
 +      ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING);
 +      SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
 +      return 0;
 +   }
 +
 +   Status = ObInsertObject(
 +               (PVOID)WindowStationObject,
 +               NULL,
 +               dwDesiredAccess,
 +               0,
 +               NULL,
 +               (PVOID*)&WindowStation);
 +
 +   if (!NT_SUCCESS(Status))
 +   {
 +      ERR("ObInsertObject failed for window station %wZ\n", &WindowStationName);
 +      ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING);
 +      SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
 +      ObDereferenceObject(WindowStationObject);
 +      return 0;
 +   }
 +
 +   /* Initialize the window station */
 +   RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT));
 +
 +   KeInitializeSpinLock(&WindowStationObject->Lock);
 +   InitializeListHead(&WindowStationObject->DesktopListHead);
 +   Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
 +   WindowStationObject->SystemMenuTemplate = (HANDLE)0;
 +   WindowStationObject->Name = WindowStationName;
 +   WindowStationObject->dwSessionId = NtCurrentPeb()->SessionId;
 +
 +   if (InputWindowStation == NULL)
 +   {
 +       TRACE("Initializeing input window station\n");
 +      InputWindowStation = WindowStationObject;
 +
 +      InitCursorImpl();
 +   }
 +
 +   TRACE("NtUserCreateWindowStation created object 0x%x with name %wZ handle 0x%x\n",
 +          WindowStation, &WindowStationObject->Name, WindowStation);
 +   return WindowStation;
 +}
 +
 +/*
 + * NtUserOpenWindowStation
 + *
 + * Opens an existing window station.
 + *
 + * Parameters
 + *    lpszWindowStationName
 + *       Name of the existing window station.
 + *
 + *    dwDesiredAccess
 + *       Requested type of access.
 + *
 + * Return Value
 + *    If the function succeeds, the return value is the handle to the
 + *    specified window station. If the function fails, the return value
 + *    is NULL.
 + *
 + * Remarks
 + *    The returned handle can be closed with NtUserCloseWindowStation.
 + *
 + * Status
 + *    @implemented
 + */
 +
 +HWINSTA APIENTRY
 +NtUserOpenWindowStation(
 +   POBJECT_ATTRIBUTES ObjectAttributes,
 +   ACCESS_MASK dwDesiredAccess)
 +{
 +   HWINSTA hwinsta;
 +   NTSTATUS Status;
 +
 +   Status = ObOpenObjectByName(
 +               ObjectAttributes,
 +               ExWindowStationObjectType,
 +               UserMode,
 +               NULL,
 +               dwDesiredAccess,
 +               NULL,
 +               (PVOID*)&hwinsta);
 +
 +   if (!NT_SUCCESS(Status))
 +   {
 +       ERR("NtUserOpenWindowStation failed\n");
 +      SetLastNtError(Status);
 +      return 0;
 +   }
 +
 +   TRACE("Opened window station %wZ with handle 0x%x\n", ObjectAttributes->ObjectName, hwinsta);
 +
 +   return hwinsta;
 +}
 +
 +/*
 + * NtUserCloseWindowStation
 + *
 + * Closes a window station handle.
 + *
 + * Parameters
 + *    hWinSta
 + *       Handle to the window station.
 + *
 + * Return Value
 + *    Status
 + *
 + * Remarks
 + *    The window station handle can be created with NtUserCreateWindowStation
 + *    or NtUserOpenWindowStation. Attemps to close a handle to the window
 + *    station assigned to the calling process will fail.
 + *
 + * Status
 + *    @implemented
 + */
 +
 +BOOL
 +APIENTRY
 +NtUserCloseWindowStation(
 +   HWINSTA hWinSta)
 +{
 +   PWINSTATION_OBJECT Object;
 +   NTSTATUS Status;
 +
 +   TRACE("NtUserCloseWindowStation called (0x%x)\n", hWinSta);
 +
 +      if (hWinSta == UserGetProcessWindowStation())
 +      {
 +        ERR("Attempted to close process window station\n");
 +              return FALSE;
 +      }
 +
 +   Status = IntValidateWindowStationHandle(
 +               hWinSta,
 +               KernelMode,
 +               0,
 +               &Object);
 +
 +   if (!NT_SUCCESS(Status))
 +   {
 +      ERR("Validation of window station handle (0x%x) failed\n", hWinSta);
 +      return FALSE;
 +   }
 +
 +   ObDereferenceObject(Object);
 +
 +   TRACE("Closing window station handle (0x%x)\n", hWinSta);
 +
 +   Status = ObCloseHandle(hWinSta, UserMode);
 +   if (!NT_SUCCESS(Status))
 +   {
 +      SetLastNtError(Status);
 +      return FALSE;
 +   }
 +
 +   return TRUE;
 +}
 +
 +/*
 + * NtUserGetObjectInformation
 + *
 + * The NtUserGetObjectInformation function retrieves information about a
 + * window station or desktop object.
 + *
 + * Parameters
 + *    hObj
 + *       Handle to the window station or desktop object for which to
 + *       return information. This can be a handle of type HDESK or HWINSTA
 + *       (for example, a handle returned by NtUserCreateWindowStation,
 + *       NtUserOpenWindowStation, NtUserCreateDesktop, or NtUserOpenDesktop).
 + *
 + *    nIndex
 + *       Specifies the object information to be retrieved.
 + *
 + *    pvInfo
 + *       Pointer to a buffer to receive the object information.
 + *
 + *    nLength
 + *       Specifies the size, in bytes, of the buffer pointed to by the
 + *       pvInfo parameter.
 + *
 + *    lpnLengthNeeded
 + *       Pointer to a variable receiving the number of bytes required to
 + *       store the requested information. If this variable's value is
 + *       greater than the value of the nLength parameter when the function
 + *       returns, the function returns FALSE, and none of the information
 + *       is copied to the pvInfo buffer. If the value of the variable pointed
 + *       to by lpnLengthNeeded is less than or equal to the value of nLength,
 + *       the entire information block is copied.
 + *
 + * Return Value
 + *    If the function succeeds, the return value is nonzero. If the function
 + *    fails, the return value is zero.
 + *
 + * Status
 + *    @unimplemented
 + */
 +
 +BOOL APIENTRY
 +NtUserGetObjectInformation(
 +   HANDLE hObject,
 +   DWORD nIndex,
 +   PVOID pvInformation,
 +   DWORD nLength,
 +   PDWORD nLengthNeeded)
 +{
 +   PWINSTATION_OBJECT WinStaObject = NULL;
 +   PDESKTOP DesktopObject = NULL;
 +   NTSTATUS Status;
 +   PVOID pvData = NULL;
 +   DWORD nDataSize = 0;
 +
 +   /* try windowstation */
 +   TRACE("Trying to open window station 0x%x\n", hObject);
 +   Status = ObReferenceObjectByHandle(
 +               hObject,
 +               0,
 +               ExWindowStationObjectType,
 +               UserMode,
 +               (PVOID*)&WinStaObject,
 +               NULL);
 +
 +   if (Status == STATUS_OBJECT_TYPE_MISMATCH)
 +   {
 +      /* try desktop */
 +      TRACE("Trying to open desktop 0x%x\n", hObject);
 +      Status = IntValidateDesktopHandle(
 +                  hObject,
 +                  UserMode,
 +                  0,
 +                  &DesktopObject);
 +   }
 +
 +   if (!NT_SUCCESS(Status))
 +   {
 +      ERR("Failed: 0x%x\n", Status);
 +      SetLastNtError(Status);
 +      return FALSE;
 +   }
 +
 +   TRACE("WinSta or Desktop opened!!\n");
 +
 +   /* get data */
 +   switch (nIndex)
 +   {
 +      case UOI_FLAGS:
 +         Status = STATUS_NOT_IMPLEMENTED;
 +         ERR("UOI_FLAGS unimplemented!\n");
 +         break;
 +
 +      case UOI_NAME:
 +         if (WinStaObject != NULL)
 +         {
 +             pvData = WinStaObject->Name.Buffer;
 +             nDataSize = WinStaObject->Name.Length + sizeof(WCHAR);
 +            Status = STATUS_SUCCESS;
 +         }
 +         else if (DesktopObject != NULL)
 +         {
 +             pvData = DesktopObject->pDeskInfo->szDesktopName;
 +            nDataSize = (wcslen(DesktopObject->pDeskInfo->szDesktopName) + 1) * sizeof(WCHAR);
 +            Status = STATUS_SUCCESS;
 +         }
 +         else
 +            Status = STATUS_INVALID_PARAMETER;
 +         break;
 +
 +      case UOI_TYPE:
 +         if (WinStaObject != NULL)
 +         {
 +            pvData = L"WindowStation";
 +            nDataSize = sizeof(L"WindowStation");
 +            Status = STATUS_SUCCESS;
 +         }
 +         else if (DesktopObject != NULL)
 +         {
 +            pvData = L"Desktop";
 +            nDataSize = sizeof(L"Desktop");
 +            Status = STATUS_SUCCESS;
 +         }
 +         else
 +            Status = STATUS_INVALID_PARAMETER;
 +         break;
 +
 +      case UOI_USER_SID:
 +         Status = STATUS_NOT_IMPLEMENTED;
 +         ERR("UOI_USER_SID unimplemented!\n");
 +         break;
 +
 +      default:
 +         Status = STATUS_INVALID_PARAMETER;
 +         break;
 +   }
 +
 +   /* try to copy data to caller */
 +   if (Status == STATUS_SUCCESS)
 +   {
 +      TRACE("Trying to copy data to caller (len = %d, len needed = %d)\n", nLength, nDataSize);
 +      *nLengthNeeded = nDataSize;
 +      if (nLength >= nDataSize)
 +         Status = MmCopyToCaller(pvInformation, pvData, nDataSize);
 +      else
 +         Status = STATUS_BUFFER_TOO_SMALL;
 +   }
 +
 +   /* release objects */
 +   if (WinStaObject != NULL)
 +      ObDereferenceObject(WinStaObject);
 +   if (DesktopObject != NULL)
 +      ObDereferenceObject(DesktopObject);
 +
 +   if (!NT_SUCCESS(Status))
 +   {
 +      SetLastNtError(Status);
 +      return FALSE;
 +   }
 +
 +   return TRUE;
 +}
 +
 +/*
 + * NtUserSetObjectInformation
 + *
 + * The NtUserSetObjectInformation function sets information about a
 + * window station or desktop object.
 + *
 + * Parameters
 + *    hObj
 + *       Handle to the window station or desktop object for which to set
 + *       object information. This value can be a handle of type HDESK or
 + *       HWINSTA.
 + *
 + *    nIndex
 + *       Specifies the object information to be set.
 + *
 + *    pvInfo
 + *       Pointer to a buffer containing the object information.
 + *
 + *    nLength
 + *       Specifies the size, in bytes, of the information contained in the
 + *       buffer pointed to by pvInfo.
 + *
 + * Return Value
 + *    If the function succeeds, the return value is nonzero. If the function
 + *    fails the return value is zero.
 + *
 + * Status
 + *    @unimplemented
 + */
 +
 +BOOL
 +APIENTRY
 +NtUserSetObjectInformation(
 +   HANDLE hObject,
 +   DWORD nIndex,
 +   PVOID pvInformation,
 +   DWORD nLength)
 +{
 +   /* FIXME: ZwQueryObject */
 +   /* FIXME: ZwSetInformationObject */
 +   SetLastNtError(STATUS_UNSUCCESSFUL);
 +   return FALSE;
 +}
 +
 +
 +
 +
 +HWINSTA FASTCALL
 +UserGetProcessWindowStation(VOID)
 +{
 +    PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
 +
 +    return ppi->hwinsta;
 +}
 +
 +
 +/*
 + * NtUserGetProcessWindowStation
 + *
 + * Returns a handle to the current process window station.
 + *
 + * Return Value
 + *    If the function succeeds, the return value is handle to the window
 + *    station assigned to the current process. If the function fails, the
 + *    return value is NULL.
 + *
 + * Status
 + *    @implemented
 + */
 +
 +HWINSTA APIENTRY
 +NtUserGetProcessWindowStation(VOID)
 +{
 +   return UserGetProcessWindowStation();
 +}
 +
 +BOOL FASTCALL
 +UserSetProcessWindowStation(HWINSTA hWindowStation)
 +{
 +    PPROCESSINFO ppi;
 +    NTSTATUS Status;
 +    HWINSTA hwinstaOld;
 +    PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
 +
 +    ppi = PsGetCurrentProcessWin32Process();
 +
 +    /* Reference the new window station */
 +    if(hWindowStation !=NULL)
 +    {
 +        Status = IntValidateWindowStationHandle( hWindowStation,
 +                                                 KernelMode,
 +                                                 0,
 +                                                 &NewWinSta);
 +       if (!NT_SUCCESS(Status))
 +       {
 +          TRACE("Validation of window station handle (0x%X) failed\n",
 +                 hWindowStation);
 +          SetLastNtError(Status);
 +          return FALSE;
 +       }
 +    }
 +
 +   OldWinSta = ppi->prpwinsta;
 +   hwinstaOld = PsGetProcessWin32WindowStation(ppi->peProcess);
 +
 +   /* Dereference the previous window station */
 +   if(OldWinSta != NULL)
 +   {
 +       ObDereferenceObject(OldWinSta);
 +   }
 +
 +   /* Check if we have a stale handle (it should happen for console apps) */
 +   if(hwinstaOld != ppi->hwinsta)
 +   {
 +       ObCloseHandle(hwinstaOld, UserMode);
 +   }
 +
 +   /*
 +    * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects.
 +    */
 +
 +   PsSetProcessWindowStation(ppi->peProcess, hWindowStation);
 +
 +   ppi->prpwinsta = NewWinSta;
 +   ppi->hwinsta = hWindowStation;
 +
 +   return TRUE;
 +}
 +
 +/*
 + * NtUserSetProcessWindowStation
 + *
 + * Assigns a window station to the current process.
 + *
 + * Parameters
 + *    hWinSta
 + *       Handle to the window station.
 + *
 + * Return Value
 + *    Status
 + *
 + * Status
 + *    @implemented
 + */
 +
 +BOOL APIENTRY
 +NtUserSetProcessWindowStation(HWINSTA hWindowStation)
 +{
 +    BOOL ret;
 +
 +    UserEnterExclusive();
 +
 +    ret = UserSetProcessWindowStation(hWindowStation);
 +
 +    UserLeave();
 +
 +    return ret;
 +}
 +
 +/*
 + * NtUserLockWindowStation
 + *
 + * Locks switching desktops. Only the logon application is allowed to call this function.
 + *
 + * Status
 + *    @implemented
 + */
 +
 +BOOL APIENTRY
 +NtUserLockWindowStation(HWINSTA hWindowStation)
 +{
 +   PWINSTATION_OBJECT Object;
 +   NTSTATUS Status;
 +
 +   TRACE("About to set process window station with handle (0x%X)\n",
 +          hWindowStation);
 +
 +   if(PsGetCurrentProcessWin32Process() != LogonProcess)
 +   {
 +      ERR("Unauthorized process attempted to lock the window station!\n");
 +      EngSetLastError(ERROR_ACCESS_DENIED);
 +      return FALSE;
 +   }
 +
 +   Status = IntValidateWindowStationHandle(
 +               hWindowStation,
 +               KernelMode,
 +               0,
 +               &Object);
 +   if (!NT_SUCCESS(Status))
 +   {
 +      TRACE("Validation of window station handle (0x%X) failed\n",
 +             hWindowStation);
 +      SetLastNtError(Status);
 +      return FALSE;
 +   }
 +
 +   Object->Flags |= WSS_LOCKED;
 +
 +   ObDereferenceObject(Object);
 +   return TRUE;
 +}
 +
 +/*
 + * NtUserUnlockWindowStation
 + *
 + * Unlocks switching desktops. Only the logon application is allowed to call this function.
 + *
 + * Status
 + *    @implemented
 + */
 +
 +BOOL APIENTRY
 +NtUserUnlockWindowStation(HWINSTA hWindowStation)
 +{
 +   PWINSTATION_OBJECT Object;
 +   NTSTATUS Status;
 +   BOOL Ret;
 +
 +   TRACE("About to set process window station with handle (0x%X)\n",
 +          hWindowStation);
 +
 +   if(PsGetCurrentProcessWin32Process() != LogonProcess)
 +   {
 +      ERR("Unauthorized process attempted to unlock the window station!\n");
 +      EngSetLastError(ERROR_ACCESS_DENIED);
 +      return FALSE;
 +   }
 +
 +   Status = IntValidateWindowStationHandle(
 +               hWindowStation,
 +               KernelMode,
 +               0,
 +               &Object);
 +   if (!NT_SUCCESS(Status))
 +   {
 +      TRACE("Validation of window station handle (0x%X) failed\n",
 +             hWindowStation);
 +      SetLastNtError(Status);
 +      return FALSE;
 +   }
 +
 +   Ret = (Object->Flags & WSS_LOCKED) == WSS_LOCKED;
 +   Object->Flags &= ~WSS_LOCKED;
 +
 +   ObDereferenceObject(Object);
 +   return Ret;
 +}
 +
 +static NTSTATUS FASTCALL
 +BuildWindowStationNameList(
 +   ULONG dwSize,
 +   PVOID lpBuffer,
 +   PULONG pRequiredSize)
 +{
 +   OBJECT_ATTRIBUTES ObjectAttributes;
 +   NTSTATUS Status;
 +   HANDLE DirectoryHandle;
 +   char InitialBuffer[256], *Buffer;
 +   ULONG Context, ReturnLength, BufferSize;
 +   DWORD EntryCount;
 +   POBJECT_DIRECTORY_INFORMATION DirEntry;
 +   WCHAR NullWchar;
 +
 +   /*
 +    * Try to open the directory.
 +    */
 +   InitializeObjectAttributes(
 +      &ObjectAttributes,
 +      &gustrWindowStationsDir,
 +      OBJ_CASE_INSENSITIVE,
 +      NULL,
 +      NULL);
 +
 +   Status = ZwOpenDirectoryObject(
 +               &DirectoryHandle,
 +               DIRECTORY_QUERY,
 +               &ObjectAttributes);
 +
 +   if (!NT_SUCCESS(Status))
 +   {
 +      return Status;
 +   }
 +
 +   /* First try to query the directory using a fixed-size buffer */
 +   Context = 0;
 +   Buffer = NULL;
 +   Status = ZwQueryDirectoryObject(DirectoryHandle, InitialBuffer, sizeof(InitialBuffer),
 +                                   FALSE, TRUE, &Context, &ReturnLength);
 +   if (NT_SUCCESS(Status))
 +   {
 +      if (STATUS_NO_MORE_ENTRIES == ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
 +            FALSE, &Context, NULL))
 +      {
 +         /* Our fixed-size buffer is large enough */
 +         Buffer = InitialBuffer;
 +      }
 +   }
 +
 +   if (NULL == Buffer)
 +   {
 +      /* Need a larger buffer, check how large exactly */
 +      Status = ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, TRUE, &Context,
 +                                      &ReturnLength);
 +      if (STATUS_BUFFER_TOO_SMALL == Status)
 +      {
 +         ObDereferenceObject(DirectoryHandle);
 +         return STATUS_NO_MEMORY;
 +      }
 +
 +      BufferSize = ReturnLength;
 +      Buffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_WINSTA);
 +      if (NULL == Buffer)
 +      {
 +         ObDereferenceObject(DirectoryHandle);
 +         return STATUS_NO_MEMORY;
 +      }
 +
 +      /* We should have a sufficiently large buffer now */
 +      Context = 0;
 +      Status = ZwQueryDirectoryObject(DirectoryHandle, Buffer, BufferSize,
 +                                      FALSE, TRUE, &Context, &ReturnLength);
 +      if (! NT_SUCCESS(Status) ||
 +            STATUS_NO_MORE_ENTRIES != ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
 +                  FALSE, &Context, NULL))
 +      {
 +         /* Something went wrong, maybe someone added a directory entry? Just give up. */
 +         ExFreePoolWithTag(Buffer, TAG_WINSTA);
 +         ObDereferenceObject(DirectoryHandle);
 +         return NT_SUCCESS(Status) ? STATUS_INTERNAL_ERROR : Status;
 +      }
 +   }
 +
 +   ZwClose(DirectoryHandle);
 +
 +   /*
 +    * Count the required size of buffer.
 +    */
 +   ReturnLength = sizeof(DWORD);
 +   EntryCount = 0;
 +   for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->Name.Length;
 +         DirEntry++)
 +   {
 +      ReturnLength += DirEntry->Name.Length + sizeof(WCHAR);
 +      EntryCount++;
 +   }
 +   TRACE("Required size: %d Entry count: %d\n", ReturnLength, EntryCount);
 +   if (NULL != pRequiredSize)
 +   {
 +      Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
 +      if (! NT_SUCCESS(Status))
 +      {
 +         if (Buffer != InitialBuffer)
 +         {
 +            ExFreePoolWithTag(Buffer, TAG_WINSTA);
 +         }
 +         return STATUS_BUFFER_TOO_SMALL;
 +      }
 +   }
 +
 +   /*
 +    * Check if the supplied buffer is large enough.
 +    */
 +   if (dwSize < ReturnLength)
 +   {
 +      if (Buffer != InitialBuffer)
 +      {
 +         ExFreePoolWithTag(Buffer, TAG_WINSTA);
 +      }
 +      return STATUS_BUFFER_TOO_SMALL;
 +   }
 +
 +   /*
 +    * Generate the resulting buffer contents.
 +    */
 +   Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
 +   if (! NT_SUCCESS(Status))
 +   {
 +      if (Buffer != InitialBuffer)
 +      {
 +         ExFreePoolWithTag(Buffer, TAG_WINSTA);
 +      }
 +      return Status;
 +   }
 +   lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
 +
 +   NullWchar = L'\0';
 +   for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->Name.Length;
 +         DirEntry++)
 +   {
 +      Status = MmCopyToCaller(lpBuffer, DirEntry->Name.Buffer, DirEntry->Name.Length);
 +      if (! NT_SUCCESS(Status))
 +      {
 +         if (Buffer != InitialBuffer)
 +         {
 +            ExFreePoolWithTag(Buffer, TAG_WINSTA);
 +         }
 +         return Status;
 +      }
 +      lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->Name.Length);
 +      Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
 +      if (! NT_SUCCESS(Status))
 +      {
 +         if (Buffer != InitialBuffer)
 +         {
 +            ExFreePoolWithTag(Buffer, TAG_WINSTA);
 +         }
 +         return Status;
 +      }
 +      lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
 +   }
 +
 +   /*
 +    * Clean up
 +    */
 +   if (Buffer != InitialBuffer)
 +   {
 +      ExFreePoolWithTag(Buffer, TAG_WINSTA);
 +   }
 +
 +   return STATUS_SUCCESS;
 +}
 +
 +static NTSTATUS FASTCALL
 +BuildDesktopNameList(
 +   HWINSTA hWindowStation,
 +   ULONG dwSize,
 +   PVOID lpBuffer,
 +   PULONG pRequiredSize)
 +{
 +   NTSTATUS Status;
 +   PWINSTATION_OBJECT WindowStation;
 +   KIRQL OldLevel;
 +   PLIST_ENTRY DesktopEntry;
 +   PDESKTOP DesktopObject;
 +   DWORD EntryCount;
 +   ULONG ReturnLength;
 +   WCHAR NullWchar;
 +   PUNICODE_STRING DesktopName;
 +
 +   Status = IntValidateWindowStationHandle(hWindowStation,
 +                                           KernelMode,
 +                                           0,
 +                                           &WindowStation);
 +   if (! NT_SUCCESS(Status))
 +   {
 +      return Status;
 +   }
 +
 +   KeAcquireSpinLock(&WindowStation->Lock, &OldLevel);
 +
 +   /*
 +    * Count the required size of buffer.
 +    */
 +   ReturnLength = sizeof(DWORD);
 +   EntryCount = 0;
 +   for (DesktopEntry = WindowStation->DesktopListHead.Flink;
 +         DesktopEntry != &WindowStation->DesktopListHead;
 +         DesktopEntry = DesktopEntry->Flink)
 +   {
 +      DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry);
 +      DesktopName = GET_DESKTOP_NAME(DesktopObject);
 +      if (DesktopName) ReturnLength += DesktopName->Length + sizeof(WCHAR);
 +      EntryCount++;
 +   }
 +   TRACE("Required size: %d Entry count: %d\n", ReturnLength, EntryCount);
 +   if (NULL != pRequiredSize)
 +   {
 +      Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
 +      if (! NT_SUCCESS(Status))
 +      {
 +         KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
 +         ObDereferenceObject(WindowStation);
 +         return STATUS_BUFFER_TOO_SMALL;
 +      }
 +   }
 +
 +   /*
 +    * Check if the supplied buffer is large enough.
 +    */
 +   if (dwSize < ReturnLength)
 +   {
 +      KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
 +      ObDereferenceObject(WindowStation);
 +      return STATUS_BUFFER_TOO_SMALL;
 +   }
 +
 +   /*
 +    * Generate the resulting buffer contents.
 +    */
 +   Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
 +   if (! NT_SUCCESS(Status))
 +   {
 +      KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
 +      ObDereferenceObject(WindowStation);
 +      return Status;
 +   }
 +   lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
 +
 +   NullWchar = L'\0';
 +   for (DesktopEntry = WindowStation->DesktopListHead.Flink;
 +         DesktopEntry != &WindowStation->DesktopListHead;
 +         DesktopEntry = DesktopEntry->Flink)
 +   {
 +      DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry);
 +      _PRAGMA_WARNING_SUPPRESS(__WARNING_DEREF_NULL_PTR)
 +      DesktopName = GET_DESKTOP_NAME(DesktopObject);/// @todo Don't mess around with the object headers!
 +      if (!DesktopName) continue;
 +
 +      Status = MmCopyToCaller(lpBuffer, DesktopName->Buffer, DesktopName->Length);
 +      if (! NT_SUCCESS(Status))
 +      {
 +         KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
 +         ObDereferenceObject(WindowStation);
 +         return Status;
 +      }
 +      lpBuffer = (PVOID) ((PCHAR)lpBuffer + DesktopName->Length);
 +      Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
 +      if (! NT_SUCCESS(Status))
 +      {
 +         KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
 +         ObDereferenceObject(WindowStation);
 +         return Status;
 +      }
 +      lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
 +   }
 +
 +   /*
 +    * Clean up
 +    */
 +   KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
 +   ObDereferenceObject(WindowStation);
 +
 +   return STATUS_SUCCESS;
 +}
 +
 +/*
 + * NtUserBuildNameList
 + *
 + * Function used for enumeration of desktops or window stations.
 + *
 + * Parameters
 + *    hWinSta
 + *       For enumeration of window stations this parameter must be set to
 + *       zero. Otherwise it's handle for window station.
 + *
 + *    dwSize
 + *       Size of buffer passed by caller.
 + *
 + *    lpBuffer
 + *       Buffer passed by caller. If the function succedes, the buffer is
 + *       filled with window station/desktop count (in first DWORD) and
 + *       NULL-terminated window station/desktop names.
 + *
 + *    pRequiredSize
 + *       If the function suceedes, this is the number of bytes copied.
 + *       Otherwise it's size of buffer needed for function to succeed.
 + *
 + * Status
 + *    @implemented
 + */
 +
 +NTSTATUS APIENTRY
 +NtUserBuildNameList(
 +   HWINSTA hWindowStation,
 +   ULONG dwSize,
 +   PVOID lpBuffer,
 +   PULONG pRequiredSize)
 +{
 +   /* The WindowStation name list and desktop name list are build in completely
 +      different ways. Call the appropriate function */
 +   return NULL == hWindowStation ? BuildWindowStationNameList(dwSize, lpBuffer, pRequiredSize) :
 +          BuildDesktopNameList(hWindowStation, dwSize, lpBuffer, pRequiredSize);
 +}
 +
 +/*
 + * @implemented
 + */
 +BOOL APIENTRY
 +NtUserSetLogonNotifyWindow(HWND hWnd)
 +{
 +    if(LogonProcess != PsGetCurrentProcessWin32Process())
 +    {
 +        return FALSE;
 +    }
 +
 +    if(!IntIsWindow(hWnd))
 +    {
 +        return FALSE;
 +    }
 +
 +    hwndSAS = hWnd;
 +
 +    return TRUE;
 +}
 +
 +BOOL
 +APIENTRY
 +NtUserLockWorkStation(VOID)
 +{
 +    BOOL ret;
 +    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
 +
 +    UserEnterExclusive();
 +
 +    if (pti->rpdesk == IntGetActiveDesktop())
 +    {
 +        ret = UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_LOCK_WORKSTATION, 0);
 +    }
 +    else
 +    {
 +        ret = FALSE;
 +    }
 +
 +    UserLeave();
 +
 +   return ret;
 +}
 +
 +/* EOF */