mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[HIVES]: Add "System Reserved" and "EMS" group types.
[TXTSETUP]: Add sacdrv.sys to the list of setup drivers. [CMAKELISTS]: Add sac/sacdrv/sacmsg to the build. [SACMSG]: Update some messages to give them identifiers. [SACDRV]: Reformat almost the entire driver to ReactOS standards. [SACDRV]: Implement about 50% of the driver, including most of the Channel Manager, Command Manager and Raw Channel Support. Comment and cleanup all of the old code that was there before. This is WIP -- it will only activate if you attempt to enable EMS. EMS/SAC support should be very helpful for Thorium Core/ARM port. svn path=/trunk/; revision=59649
This commit is contained in:
parent
f9c1de4baa
commit
6568f7df16
19 changed files with 4468 additions and 1314 deletions
|
@ -1149,6 +1149,8 @@ HKLM,"SYSTEM\CurrentControlSet\Control\SecurityProviders\SaslProfiles",,0x000000
|
|||
|
||||
; Service groups
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\ServiceGroupOrder","List",0x00010000, \
|
||||
"System Reserved", \
|
||||
"EMS", \
|
||||
"Boot Bus Extender", \
|
||||
"System Bus Extender", \
|
||||
"SCSI Miniport", \
|
||||
|
@ -1342,6 +1344,13 @@ HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Start",0x00010001,0x00000002
|
|||
HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Type",0x00010001,0x00000020
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\DHCP\Parameters","ServiceDll",0x00020000,"%SystemRoot%\system32\dhcpcsvc.dll"
|
||||
|
||||
; EMS Serial Administration Console Driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","ErrorControl",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Group",0x00000000,"EMS"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","ImagePath",0x00020000,"system32\drivers\sacdrv.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Type",0x00010001,0x00000001
|
||||
|
||||
; Event logging service
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\EventLog",,0x00000010
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","DisplayName",0x00000000,"Event Logger"
|
||||
|
|
|
@ -18,6 +18,7 @@ FreeSysPartDiskSpace=350
|
|||
[SourceDisksFiles]
|
||||
acpi.sys=,,,,,,,,,,,,4
|
||||
nmidebug.sys=,,,,,,x,,,,,,4
|
||||
sacdrv.sys=,,,,,,x,,,,,,4
|
||||
uniata.sys=,,,,,,x,,,,,,4
|
||||
buslogic.sys=,,,,,,x,,,,,,4
|
||||
blue.sys=,,,,,,x,,,,,,4
|
||||
|
|
|
@ -12,6 +12,7 @@ add_subdirectory(input)
|
|||
add_subdirectory(ksfilter)
|
||||
add_subdirectory(network)
|
||||
add_subdirectory(parallel)
|
||||
add_subdirectory(sac)
|
||||
add_subdirectory(serial)
|
||||
add_subdirectory(setup)
|
||||
add_subdirectory(storage)
|
||||
|
|
2
reactos/drivers/sac/CMakeLists.txt
Normal file
2
reactos/drivers/sac/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
add_subdirectory(driver)
|
19
reactos/drivers/sac/driver/CMakeLists.txt
Normal file
19
reactos/drivers/sac/driver/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
chanmgr.c
|
||||
channel.c
|
||||
cmdchan.c
|
||||
concmd.c
|
||||
conmgr.c
|
||||
data.c
|
||||
dispatch.c
|
||||
init.c
|
||||
memory.c
|
||||
rawchan.c
|
||||
util.c
|
||||
vtutf8chan.c)
|
||||
|
||||
add_library(sacdrv SHARED ${SOURCE} sacdrv.rc)
|
||||
set_module_type(sacdrv kernelmodedriver)
|
||||
add_importlibs(sacdrv ntoskrnl hal)
|
||||
add_cd_file(TARGET sacdrv DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
|
@ -1,176 +1,717 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/chanmgr.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/chanmgr.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
SAC_CHANNEL_LOCK ChannelCreateLock;
|
||||
BOOLEAN ChannelCreateEnabled;
|
||||
PSAC_CHANNEL ChannelArray[SAC_MAX_CHANNELS];
|
||||
LONG ChannelRefCount[SAC_MAX_CHANNELS];
|
||||
LONG ChannelReaped[SAC_MAX_CHANNELS];
|
||||
SAC_CHANNEL_LOCK ChannelSlotLock[SAC_MAX_CHANNELS];
|
||||
LONG CurrentChannelRefCount;
|
||||
KMUTEX CurrentChannelLock;
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrInitialize(
|
||||
VOID
|
||||
)
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
#define MAX_REF_COUNT 100
|
||||
|
||||
#define CHANNEL_SLOT_IS_IN_USE(x) (ChannelRefCount[(x)] > 0)
|
||||
|
||||
FORCEINLINE
|
||||
PSAC_CHANNEL
|
||||
ChannelFromIndex(IN ULONG Index)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return ChannelArray[Index];
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrGetChannelIndex(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PULONG ChannelIndex
|
||||
)
|
||||
FORCEINLINE
|
||||
LONG
|
||||
ChannelGetReferenceCount(IN LONG Index)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return ChannelRefCount[Index];
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrReleaseChannel(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
FORCEINLINE
|
||||
LONG
|
||||
ChannelReferenceByIndex(IN LONG Index)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
if (ChannelGetReferenceCount(Index) > 0)
|
||||
{
|
||||
ASSERT(ChannelRefCount[Index] <= MAX_REF_COUNT);
|
||||
ASSERT(ChannelRefCount[Index] >= 1);
|
||||
_InterlockedIncrement(&ChannelRefCount[Index]);
|
||||
ASSERT(ChannelRefCount[Index] <= MAX_REF_COUNT);
|
||||
ASSERT(ChannelRefCount[Index] >= 2);
|
||||
}
|
||||
|
||||
return ChannelGetReferenceCount(Index);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrGetByHandle(
|
||||
IN PSAC_CHANNEL_ID ChannelId,
|
||||
OUT PSAC_CHANNEL pChannel
|
||||
)
|
||||
FORCEINLINE
|
||||
LONG
|
||||
ChannelReferenceByIndexWithLock(IN LONG Index)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
LONG RefCount;
|
||||
|
||||
ChannelSlotLock(Index);
|
||||
RefCount = ChannelReferenceByIndex(Index);
|
||||
ChannelSlotUnlock(Index);
|
||||
return RefCount;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrGetByHandleAndFileObject(
|
||||
IN PSAC_CHANNEL_ID ChannelId,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
OUT PSAC_CHANNEL pChannel
|
||||
)
|
||||
FORCEINLINE
|
||||
LONG
|
||||
ChannelDereferenceByIndex(IN LONG Index)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrGetChannelByName(
|
||||
IN PWCHAR Name,
|
||||
OUT PSAC_CHANNEL pChannel
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrGetByIndex(
|
||||
IN ULONG TargetIndex,
|
||||
IN PSAC_CHANNEL *TargetChannel
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrGetNextActiveChannel(
|
||||
IN PSAC_CHANNEL CurrentChannel,
|
||||
IN PULONG TargetIndex,
|
||||
OUT PSAC_CHANNEL *TargetChannel
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
ASSERT(ChannelGetReferenceCount(Index) <= MAX_REF_COUNT);
|
||||
ASSERT(ChannelGetReferenceCount(Index) > 1);
|
||||
_InterlockedDecrement(&ChannelRefCount[Index]);
|
||||
ASSERT(ChannelGetReferenceCount(Index) >= 1);
|
||||
return ChannelGetReferenceCount(Index);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
ChanMgrChannelDestroy(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
ChannelDereferenceByIndexWithLock(IN LONG Index)
|
||||
{
|
||||
ChannelSlotLock(Index);
|
||||
ChannelDereferenceByIndex(Index);
|
||||
ChannelSlotUnlock(Index);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
ChannelDereferenceToZeroByIndex(IN LONG Index)
|
||||
{
|
||||
ASSERT(ChannelGetReferenceCount(Index) == 1);
|
||||
ASSERT(ChannelIsActive(ChannelFromIndex(Index)) == FALSE);
|
||||
_InterlockedExchange(&ChannelRefCount[Index], 0);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
ChannelReferenceToOneByIndex(IN LONG Index)
|
||||
{
|
||||
ASSERT(ChannelGetReferenceCount(Index) == 0);
|
||||
_InterlockedExchange(&ChannelRefCount[Index], 1);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
ChannelReferenceToOneByIndexWithLock(IN LONG Index)
|
||||
{
|
||||
ChannelSlotLock(Index);
|
||||
ASSERT(ChannelGetReferenceCount((Index)) == 1);
|
||||
_InterlockedExchange(&ChannelRefCount[Index], 1);
|
||||
ChannelSlotUnlock(Index);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrCloseChannel(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrInitialize(VOID)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
ULONG i;
|
||||
|
||||
/* Initialize the channel lock */
|
||||
SacInitializeLock(&ChannelCreateLock);
|
||||
ChannelCreateEnabled = TRUE;
|
||||
|
||||
/* Loop through the channel arrays */
|
||||
for (i = 0; i < SAC_MAX_CHANNELS; i++)
|
||||
{
|
||||
/* Clear and initialize their locks */
|
||||
ChannelArray[i] = NULL;
|
||||
SacInitializeLock(&ChannelSlotLock[i]);
|
||||
|
||||
/* Clear their statuses and reference counts */
|
||||
_InterlockedExchange(&ChannelRefCount[i], 0);
|
||||
_InterlockedExchange(&ChannelReaped[i], 1);
|
||||
}
|
||||
|
||||
/* All good */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrReapChannel(
|
||||
IN ULONG ChannelIndex
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrShutdown(VOID)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
/* FIXME: TODO */
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrReapChannels(
|
||||
VOID
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrGetChannelByName(IN PWCHAR Name,
|
||||
OUT PSAC_CHANNEL* Channel)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status, Status1;
|
||||
ULONG i;
|
||||
PSAC_CHANNEL CurrentChannel;
|
||||
PWCHAR ChannelName;
|
||||
BOOLEAN Found;
|
||||
CHECK_PARAMETER1(Name);
|
||||
CHECK_PARAMETER2(Channel);
|
||||
|
||||
/* Assume failure */
|
||||
*Channel = NULL;
|
||||
Status = STATUS_NOT_FOUND;
|
||||
|
||||
/* Loop through all channels */
|
||||
for (i = 0; i < SAC_MAX_CHANNELS; i++)
|
||||
{
|
||||
/* Reference this one and check if it's valid */
|
||||
if (ChannelReferenceByIndexWithLock(i) > 0)
|
||||
{
|
||||
/* All good, grab it */
|
||||
CurrentChannel = ChannelFromIndex(i);
|
||||
ASSERT(CurrentChannel != NULL);
|
||||
|
||||
/* Get its name */
|
||||
Status1 = ChannelGetName(CurrentChannel, &ChannelName);
|
||||
ASSERT(NT_SUCCESS(Status1));
|
||||
|
||||
/* Check if this is the name that was passed in */
|
||||
Found = wcsicmp(Name, ChannelName);
|
||||
SacFreePool(ChannelName);
|
||||
if (Found)
|
||||
{
|
||||
/* We found it, return it (with a reference held) */
|
||||
*Channel = CurrentChannel;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Not the one we want, dereference this one and keep going */
|
||||
ChannelDereferenceByIndexWithLock(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* No channels with this name were found */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrGetChannelCount(
|
||||
OUT PULONG ChannelCount
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrGetByHandle(IN SAC_CHANNEL_ID ChannelId,
|
||||
OUT PSAC_CHANNEL* TargetChannel)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
PSAC_CHANNEL Channel;
|
||||
CHECK_PARAMETER2(TargetChannel);
|
||||
|
||||
/* Assume failure */
|
||||
*TargetChannel = NULL;
|
||||
Status = STATUS_NOT_FOUND;
|
||||
|
||||
/* Loop through all channels */
|
||||
for (i = 0; i < SAC_MAX_CHANNELS; i++)
|
||||
{
|
||||
/* Reference this one and check if it's valid */
|
||||
if (ChannelReferenceByIndexWithLock(i) > 0)
|
||||
{
|
||||
/* All good, grab it */
|
||||
Channel = ChannelFromIndex(i);
|
||||
ASSERT(Channel != NULL);
|
||||
|
||||
/* Check if the channel ID matches */
|
||||
if (ChannelIsEqual(Channel, &ChannelId))
|
||||
{
|
||||
/* We found it, return it (with a reference held) */
|
||||
*TargetChannel = Channel;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Not the one we want, dereference this one and keep going */
|
||||
ChannelDereferenceByIndexWithLock(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* No channels with this ID were found */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrIsFull(
|
||||
OUT PBOOLEAN IsFull
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrReleaseChannel(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
LONG Index;
|
||||
ULONG RefCount;
|
||||
PSAC_CHANNEL ThisChannel;
|
||||
CHECK_PARAMETER(Channel);
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrShutdown(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
/* Get the index of the channel */
|
||||
Index = ChannelGetIndex(Channel);
|
||||
|
||||
/* Drop a reference -- there should still be at least the keepalive left */
|
||||
ChannelSlotLock(Index);
|
||||
RefCount = ChannelDereferenceByIndex(Index);
|
||||
ASSERT(RefCount > 0);
|
||||
|
||||
/* Do we only have the keep-alive left, and the channel is dead? */
|
||||
if ((RefCount == 1) && !(ChannelIsActive(Channel)))
|
||||
{
|
||||
/* Check if the ??? flag is set, or if there's no output data */
|
||||
ThisChannel = ChannelFromIndex(Index);
|
||||
if (!(ThisChannel->Flags & 1))
|
||||
{
|
||||
/* Nope, we can wipe the references and get rid of it */
|
||||
ChannelDereferenceToZeroByIndex(Index);
|
||||
}
|
||||
else if (!ThisChannel->ChannelHasNewOBufferData)
|
||||
{
|
||||
/* No data, we can wipe the references and get rid of it */
|
||||
ChannelDereferenceToZeroByIndex(Index);
|
||||
}
|
||||
}
|
||||
|
||||
/* We're done, we can unlock the slot now */
|
||||
ChannelSlotUnlock(Index);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ChanMgrIsUniqueName(
|
||||
IN PWCHAR ChannelName
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrIsUniqueName(IN PWCHAR ChannelName)
|
||||
{
|
||||
return FALSE;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN IsUnique = FALSE;
|
||||
PSAC_CHANNEL Channel;
|
||||
|
||||
/* Check if a channel with this name already exists */
|
||||
Status = ChanMgrGetChannelByName(ChannelName, &Channel);
|
||||
if (Status == STATUS_NOT_FOUND) IsUnique = TRUE;
|
||||
|
||||
/* If one did, dereference it, all we wanted was to check uniqueness */
|
||||
if (NT_SUCCESS(Status)) ChanMgrReleaseChannel(Channel);
|
||||
|
||||
/* Return if one was found or not */
|
||||
return IsUnique;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrGenerateUniqueCmdName(
|
||||
IN PWCHAR ChannelName
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrReapChannel(IN ULONG ChannelIndex)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
/* FIXME: TODO */
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrCreateChannel(
|
||||
OUT PSAC_CHANNEL *Channel,
|
||||
IN PSAC_CHANNEL_ATTRIBUTES Attributes
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrReapChannels(VOID)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
ULONG i;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
/* Loop all the channels */
|
||||
for (i = 0; i < SAC_MAX_CHANNELS; i++)
|
||||
{
|
||||
/* Lock this index and see if the channel was reaped */
|
||||
ChannelSlotLock(i);
|
||||
if (!ChannelReaped[i])
|
||||
{
|
||||
/* It was not reaped yet, so a channel should still be here */
|
||||
ASSERT(ChannelFromIndex(i) != NULL);
|
||||
if (ChannelGetReferenceCount(i) <= 0)
|
||||
{
|
||||
/* The channel has no more references, so clear the buffer flags */
|
||||
_InterlockedExchange(&ChannelArray[i]->ChannelHasNewIBufferData, 0);
|
||||
_InterlockedExchange(&ChannelArray[i]->ChannelHasNewOBufferData, 0);
|
||||
|
||||
/* And reap it */
|
||||
Status = ChanMgrReapChannel(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the lock, and move on unless reaping failed */
|
||||
ChannelSlotUnlock(i);
|
||||
if (!NT_SUCCESS(Status)) break;
|
||||
}
|
||||
|
||||
/* Return reaping status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChanMgrCloseChannelsWithFileObject(
|
||||
IN PFILE_OBJECT FileObject
|
||||
)
|
||||
NTAPI
|
||||
ChanMgrCreateChannel(OUT PSAC_CHANNEL *Channel,
|
||||
IN PSAC_CHANNEL_ATTRIBUTES Attributes)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
PSAC_CHANNEL NewChannel;
|
||||
SAC_CHANNEL_ID ChanId;
|
||||
ULONG i;
|
||||
CHECK_PARAMETER(Channel);
|
||||
CHECK_PARAMETER2(Attributes);
|
||||
|
||||
/* No other channel create attempts can happen */
|
||||
ChannelLockCreates();
|
||||
|
||||
/* Is the channel manager initialized? */
|
||||
if (ChannelCreateEnabled)
|
||||
{
|
||||
/* Nope, bail out */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto ReturnStatus;
|
||||
}
|
||||
|
||||
/* Reap any zombie channels */
|
||||
Status = ChanMgrReapChannels();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Bail out on error */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto ReturnStatus;
|
||||
}
|
||||
|
||||
/* Check if we already have a channel with this name */
|
||||
if (!ChanMgrIsUniqueName(Attributes->NameBuffer))
|
||||
{
|
||||
/* We do, fail */
|
||||
Status = STATUS_DUPLICATE_NAME;
|
||||
goto ReturnStatus;
|
||||
}
|
||||
|
||||
/* Allocate this channel */
|
||||
NewChannel = SacAllocatePool(sizeof(SAC_CHANNEL), CHANNEL_BLOCK_TAG);
|
||||
CHECK_PARAMETER_WITH_STATUS(NewChannel, STATUS_NO_MEMORY); // bug
|
||||
RtlZeroMemory(NewChannel, sizeof(SAC_CHANNEL));
|
||||
|
||||
/* Loop channel slots */
|
||||
for (i = 0; i < SAC_MAX_CHANNELS; i++)
|
||||
{
|
||||
/* Find a free spot for it */
|
||||
if (ChannelReaped[i])
|
||||
{
|
||||
/* Free slot found, attempt to use it */
|
||||
ASSERT(!CHANNEL_SLOT_IS_IN_USE(i));
|
||||
_InterlockedCompareExchangePointer((void* volatile*)&ChannelArray[i], NewChannel, NULL);
|
||||
if (ChannelArray[i] == NewChannel) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we not find a single free slot? */
|
||||
if (i == SAC_MAX_CHANNELS)
|
||||
{
|
||||
/* Bail out */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto ReturnStatus;
|
||||
}
|
||||
|
||||
/* Create an ID for this channel */
|
||||
RtlZeroMemory(&ChanId, sizeof(ChanId));
|
||||
Status = ExUuidCreate(&ChanId.ChannelGuid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Bail out if we couldn't */
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC Create Channel :: Failed to get GUID\n");
|
||||
goto ReturnStatus;
|
||||
}
|
||||
|
||||
/* Now create the channel proper */
|
||||
Status = ChannelCreate(NewChannel, Attributes, ChanId);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Set the channel index */
|
||||
_InterlockedExchange(&NewChannel->Index, i);
|
||||
|
||||
/* Add the initial reference to the channel */
|
||||
ChannelReferenceToOneByIndexWithLock(i);
|
||||
|
||||
/* Return it to the caller */
|
||||
*Channel = NewChannel;
|
||||
|
||||
/* This slot is now occupied */
|
||||
ASSERT(ChannelReaped[i] == 1);
|
||||
_InterlockedExchange(&ChannelReaped[i], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We couldn't create it, free the buffer */
|
||||
SacFreePool(NewChannel);
|
||||
}
|
||||
|
||||
ReturnStatus:
|
||||
/* Return whatever the operation status was */
|
||||
ChannelUnlockCreates();
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrGetByHandleAndFileObject(IN SAC_CHANNEL_ID ChannelId,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
OUT PSAC_CHANNEL* TargetChannel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PSAC_CHANNEL FoundChannel;
|
||||
|
||||
/* Lookup the channel by ID first */
|
||||
Status = ChanMgrGetByHandle(ChannelId, &FoundChannel);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* We found it, now check if the file object matches */
|
||||
if (FoundChannel->FileObject == FileObject)
|
||||
{
|
||||
/* Yep, return success */
|
||||
*TargetChannel = FoundChannel;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nope, drop the reference on the channel */
|
||||
ChanMgrReleaseChannel(FoundChannel);
|
||||
|
||||
/* And return failure */
|
||||
*TargetChannel = NULL;
|
||||
Status = STATUS_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return if we found it or not */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrGetChannelIndex(IN PSAC_CHANNEL Channel,
|
||||
IN PLONG ChannelIndex)
|
||||
{
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(ChannelIndex);
|
||||
|
||||
/* Just return the index of the channel */
|
||||
*ChannelIndex = ChannelGetIndex(Channel);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrGetByIndex(IN LONG TargetIndex,
|
||||
IN PSAC_CHANNEL* TargetChannel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
CHECK_PARAMETER1(TargetIndex < SAC_MAX_CHANNELS);
|
||||
CHECK_PARAMETER2(TargetChannel);
|
||||
|
||||
/* Assume failure */
|
||||
*TargetChannel = NULL;
|
||||
Status = STATUS_NOT_FOUND;
|
||||
|
||||
/* Reference this one and check if it's valid */
|
||||
if (ChannelReferenceByIndexWithLock(TargetIndex) > 0)
|
||||
{
|
||||
/* We found it, return it (with a reference held) */
|
||||
*TargetChannel = ChannelFromIndex(TargetIndex);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* No channels with this ID were found */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrGetNextActiveChannel(IN PSAC_CHANNEL CurrentChannel,
|
||||
IN PULONG TargetIndex,
|
||||
OUT PSAC_CHANNEL *TargetChannel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
LONG ChannelIndex, StartIndex;
|
||||
PSAC_CHANNEL FoundChannel;
|
||||
BOOLEAN ChannelFound;
|
||||
CHECK_PARAMETER1(CurrentChannel);
|
||||
CHECK_PARAMETER2(TargetIndex);
|
||||
CHECK_PARAMETER3(TargetChannel);
|
||||
|
||||
/* Get the current channel index */
|
||||
Status = ChanMgrGetChannelIndex(CurrentChannel, &ChannelIndex);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Assume failure */
|
||||
ChannelFound = FALSE;
|
||||
|
||||
/* Loop through all the possible active channels */
|
||||
StartIndex = (ChannelIndex + 1) % SAC_MAX_CHANNELS;
|
||||
for (i = StartIndex; i != StartIndex; i = (i + 1) % SAC_MAX_CHANNELS)
|
||||
{
|
||||
/* Get the channel and see if it exists*/
|
||||
Status = ChanMgrGetByIndex(i, &FoundChannel);
|
||||
if (Status != STATUS_NOT_FOUND)
|
||||
{
|
||||
/* Bail out if we failed for some reason */
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* It exists -- is it active? Or, does it have output data? */
|
||||
if ((ChannelIsActive(FoundChannel)) ||
|
||||
(!(ChannelIsActive(FoundChannel)) &&
|
||||
(FoundChannel->ChannelHasNewOBufferData)))
|
||||
{
|
||||
/* It's active or has output data, return with it */
|
||||
ChannelFound = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Drop the reference on this channel and try the next one */
|
||||
Status = ChanMgrReleaseChannel(FoundChannel);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we successfully found a channel */
|
||||
if ((NT_SUCCESS(Status)) && (ChannelFound))
|
||||
{
|
||||
/* Return it and its indexed. Remember we still hold the reference */
|
||||
*TargetIndex = i;
|
||||
*TargetChannel = FoundChannel;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrChannelDestroy(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER(ChannelGetReferenceCount(Channel->Index) > 0);
|
||||
|
||||
/* Destroy the channel */
|
||||
return Channel->ChannelDestroy(Channel);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrCloseChannel(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
CHECK_PARAMETER(Channel);
|
||||
|
||||
/* Check if the channel is active */
|
||||
if (ChannelIsActive(Channel))
|
||||
{
|
||||
/* Yep, close it */
|
||||
Status = ChannelClose(Channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
Status = STATUS_ALREADY_DISCONNECTED;
|
||||
}
|
||||
|
||||
/* Handle the channel close */
|
||||
ConMgrHandleEvent(TRUE, Channel, &Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrGetChannelCount(OUT PULONG ChannelCount)
|
||||
{
|
||||
ULONG i;
|
||||
PSAC_CHANNEL Channel;
|
||||
NTSTATUS Status;
|
||||
CHECK_PARAMETER(ChannelCount);
|
||||
|
||||
/* Assume no channels */
|
||||
*ChannelCount = 0;
|
||||
|
||||
/* Loop every channel */
|
||||
for (i = 0; i < SAC_MAX_CHANNELS; i++)
|
||||
{
|
||||
/* See if this one exists */
|
||||
Status = ChanMgrGetByIndex(i, &Channel);
|
||||
if (Status != STATUS_NOT_FOUND)
|
||||
{
|
||||
/* Sanity checks*/
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
ASSERT(Channel != NULL);
|
||||
|
||||
/* It exists -- is it active? Or, does it have output data? */
|
||||
if ((ChannelIsActive(Channel)) ||
|
||||
(!(ChannelIsActive(Channel)) &&
|
||||
(Channel->ChannelHasNewOBufferData)))
|
||||
{
|
||||
/* It's active or has output data, increase the count */
|
||||
++*ChannelCount;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Drop the reference on this channel and try the next one */
|
||||
Status = ChanMgrReleaseChannel(Channel);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Channel doesn't exist, nothing wrong with that, keep going */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* We should always succeed if we get here */
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrIsFull(OUT PBOOLEAN IsFull)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Count;
|
||||
|
||||
/* Count the channels */
|
||||
Status = ChanMgrGetChannelCount(&Count);
|
||||
CHECK_PARAMETER(Status == STATUS_SUCCESS);
|
||||
|
||||
/* Return if we hit the limit */
|
||||
*IsFull = (Count == SAC_MAX_CHANNELS);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrCloseChannelsWithFileObject(IN PFILE_OBJECT FileObject)
|
||||
{
|
||||
PSAC_CHANNEL Channel;
|
||||
ULONG i;
|
||||
NTSTATUS Status;
|
||||
CHECK_PARAMETER1(FileObject);
|
||||
|
||||
/* Loop all channels */
|
||||
for (i = 0; i < SAC_MAX_CHANNELS; i++)
|
||||
{
|
||||
/* Try to get this one */
|
||||
Status = ChanMgrGetByIndex(i, &Channel);
|
||||
if (!NT_SUCCESS(Status)) break;
|
||||
|
||||
/* Check if the FO matches, if so, close the channel */
|
||||
if (Channel->FileObject == FileObject) ChanMgrCloseChannel(Channel);
|
||||
|
||||
/* Drop the reference and try the next channel(s) */
|
||||
Status = ChanMgrReleaseChannel(Channel);
|
||||
if (!NT_SUCCESS(Status)) break;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChanMgrGenerateUniqueCmdName(IN PWCHAR ChannelName)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -1,318 +1,568 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/channel.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/channel.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOLEAN
|
||||
ChannelIsValidType(
|
||||
IN SAC_CHANNEL_TYPE ChannelType
|
||||
)
|
||||
NTAPI
|
||||
ChannelIsValidType(IN SAC_CHANNEL_TYPE ChannelType)
|
||||
{
|
||||
return ((ChannelType >= VtUtf8) && (ChannelType <= Raw));
|
||||
/* Check if the type is valid */
|
||||
return ((ChannelType >= VtUtf8) && (ChannelType <= Raw));
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ChannelIsEqual(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PSAC_CHANNEL_ID ChannelId
|
||||
)
|
||||
NTAPI
|
||||
ChannelIsEqual(IN PSAC_CHANNEL Channel,
|
||||
IN PSAC_CHANNEL_ID ChannelId)
|
||||
{
|
||||
return IsEqualGUIDAligned(
|
||||
&Channel->ChannelId.ChannelGuid,
|
||||
&ChannelId->ChannelGuid);
|
||||
/* Check if the GUIDs match */
|
||||
return IsEqualGUIDAligned(&Channel->ChannelId.ChannelGuid,
|
||||
&ChannelId->ChannelGuid);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelInitializeVTable(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelDereferenceHandles(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
CHECK_PARAMETER(Channel);
|
||||
|
||||
/* Clear the data event */
|
||||
if (Channel->HasNewDataEvent)
|
||||
{
|
||||
ChannelUninitializeEvent(Channel,
|
||||
HasNewDataEvent,
|
||||
SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT);
|
||||
}
|
||||
|
||||
/* Clear the close event */
|
||||
if (Channel->CloseEvent)
|
||||
{
|
||||
ChannelUninitializeEvent(Channel,
|
||||
CloseEvent,
|
||||
SAC_CHANNEL_FLAG_CLOSE_EVENT);
|
||||
}
|
||||
|
||||
/* Clear the lock event */
|
||||
if (Channel->LockEvent)
|
||||
{
|
||||
ChannelUninitializeEvent(Channel,
|
||||
LockEvent,
|
||||
SAC_CHANNEL_FLAG_LOCK_EVENT);
|
||||
}
|
||||
|
||||
/* Clear the redraw event */
|
||||
if (Channel->RedrawEvent)
|
||||
{
|
||||
ChannelUninitializeEvent(Channel,
|
||||
RedrawEvent,
|
||||
SAC_CHANNEL_FLAG_REDRAW_EVENT);
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelDereferenceHandles(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelDestroy(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
CHECK_PARAMETER(Channel);
|
||||
|
||||
/* Same thing as dereferencing all the handles */
|
||||
return ChannelDereferenceHandles(Channel);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelDestroy(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelOWrite(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize)
|
||||
{
|
||||
CHECK_PARAMETER(Channel);
|
||||
|
||||
return ChannelDereferenceHandles(Channel);
|
||||
NTSTATUS Status;
|
||||
CHECK_PARAMETER3(BufferSize < SAC_OBUFFER_SIZE);
|
||||
|
||||
/* While holding the output lock, write to the output buffer */
|
||||
ChannelLockOBuffer(Channel);
|
||||
Status = Channel->ChannelOutputWrite(Channel, Buffer, BufferSize);
|
||||
ChannelUnlockOBuffer(Channel);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelOWrite(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR Buffer,
|
||||
IN ULONG BufferSize
|
||||
)
|
||||
NTAPI
|
||||
ChannelOFlush(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
CHECK_PARAMETER3(BufferSize < SAC_OBUFFER_SIZE);
|
||||
NTSTATUS Status;
|
||||
|
||||
ChannelLockOBuffer(Channel);
|
||||
|
||||
Status = Channel->OBufferWrite(Channel, Buffer, BufferSize);
|
||||
|
||||
ChannelUnlockOBuffer(Channel);
|
||||
|
||||
return Status;
|
||||
/* While holding the output lock, flush to the output buffer */
|
||||
ChannelLockOBuffer(Channel);
|
||||
Status = Channel->ChannelOutputFlush(Channel);
|
||||
ChannelUnlockOBuffer(Channel);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelOFlush(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelIWrite(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
ChannelLockOBuffer(Channel);
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = Channel->OBufferFlush(Channel);
|
||||
|
||||
ChannelUnlockOBuffer(Channel);
|
||||
|
||||
return Status;
|
||||
/* Write into the input buffer while holding the lock */
|
||||
ChannelLockIBuffer(Channel);
|
||||
Status = Channel->ChannelInputWrite(Channel, Buffer, BufferSize);
|
||||
ChannelUnlockIBuffer(Channel);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelIWrite(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR Buffer,
|
||||
IN ULONG BufferSize
|
||||
)
|
||||
NTAPI
|
||||
ChannelIRead(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize,
|
||||
IN OUT PULONG ResultBufferSize)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
NTSTATUS Status;
|
||||
|
||||
ChannelLockIBuffer(Channel);
|
||||
|
||||
Status = Channel->IBufferWrite(Channel, Buffer, BufferSize);
|
||||
|
||||
ChannelUnlockIBuffer(Channel);
|
||||
|
||||
return Status;
|
||||
/* Read the input buffer while holding the lock */
|
||||
ChannelLockIBuffer(Channel);
|
||||
Status = Channel->ChannelInputRead(Channel,
|
||||
Buffer,
|
||||
BufferSize,
|
||||
ResultBufferSize);
|
||||
ChannelUnlockIBuffer(Channel);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ChannelIRead(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
PWCHAR Buffer,
|
||||
ULONG BufferSize,
|
||||
OUT PULONG ResultBufferSize
|
||||
)
|
||||
UCHAR
|
||||
NTAPI
|
||||
ChannelIReadLast(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
ChannelLockIBuffer(Channel);
|
||||
UCHAR LastChar;
|
||||
|
||||
Status = Channel->IBufferRead(Channel, Buffer, BufferSize, ResultBufferSize);
|
||||
|
||||
ChannelUnlockIBuffer(Channel);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelIReadLast(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
ChannelLockIBuffer(Channel);
|
||||
|
||||
Status = Channel->IBufferReadLast(Channel);
|
||||
|
||||
ChannelUnlockIBuffer(Channel);
|
||||
|
||||
return Status;
|
||||
/* Read the last character while holding the lock */
|
||||
ChannelLockIBuffer(Channel);
|
||||
LastChar = Channel->ChannelInputReadLast(Channel);
|
||||
ChannelUnlockIBuffer(Channel);
|
||||
return LastChar;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ChannelIBufferLength(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelIBufferLength(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Length;
|
||||
ULONG Length;
|
||||
|
||||
ChannelLockOBuffer(Channel);
|
||||
|
||||
Length = Channel->IBufferLength(Channel);
|
||||
|
||||
ChannelUnlockOBuffer(Channel);
|
||||
|
||||
return Length;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelGetName(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
OUT PWCHAR *Name
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelSetName(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR Name
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelGetDescription(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
OUT PWCHAR *Description
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelSetDescription(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR Description
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelSetStatus(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN SAC_CHANNEL_STATUS ChannelStatus
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelGetStatus(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
OUT PSAC_CHANNEL_STATUS ChannelStatus
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelGetApplicationType(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
OUT PGUID ApplicationType
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
/* Get the input buffer length while holding the lock */
|
||||
ChannelLockOBuffer(Channel);
|
||||
Length = Channel->ChannelInputBufferLength(Channel);
|
||||
ChannelUnlockOBuffer(Channel);
|
||||
return Length;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelSetLockEvent(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
ChannelSetRedrawEvent(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
ChannelSetEvent(Channel, LockEvent);
|
||||
|
||||
return Status;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Set the event */
|
||||
ChannelSetEvent(Channel, RedrawEvent);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelSetRedrawEvent(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
ChannelSetLockEvent(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
NTSTATUS Status;
|
||||
|
||||
ChannelSetEvent(Channel, RedrawEvent);
|
||||
|
||||
return Status;
|
||||
/* Set the event */
|
||||
ChannelSetEvent(Channel, LockEvent);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelClearRedrawEvent(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelClearRedrawEvent(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
ChannelClearEvent(Channel, RedrawEvent);
|
||||
|
||||
return Status;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Clear the event */
|
||||
ChannelClearEvent(Channel, RedrawEvent);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelHasRedrawEvent(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
OUT PBOOLEAN Present
|
||||
)
|
||||
NTAPI
|
||||
ChannelHasRedrawEvent(IN PSAC_CHANNEL Channel,
|
||||
OUT PBOOLEAN Present)
|
||||
{
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Present);
|
||||
|
||||
*Present = Channel->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Present);
|
||||
|
||||
/* Return if the flag is set */
|
||||
*Present = Channel->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelGetStatus(IN PSAC_CHANNEL Channel,
|
||||
OUT PSAC_CHANNEL_STATUS ChannelStatus)
|
||||
{
|
||||
CHECK_PARAMETER1(Channel);
|
||||
|
||||
/* Read the status while holding the attribute lock */
|
||||
ChannelLockAttributes(Channel);
|
||||
*ChannelStatus = Channel->ChannelStatus;
|
||||
ChannelUnlockAttributes(Channel);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelSetStatus(IN PSAC_CHANNEL Channel,
|
||||
IN SAC_CHANNEL_STATUS ChannelStatus)
|
||||
{
|
||||
CHECK_PARAMETER1(Channel);
|
||||
|
||||
/* Read the status while holding the attribute lock */
|
||||
ChannelLockAttributes(Channel);
|
||||
Channel->ChannelStatus = ChannelStatus;
|
||||
ChannelUnlockAttributes(Channel);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ChannelIsActive(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelIsActive(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
SAC_CHANNEL_STATUS ChannelStatus;
|
||||
SAC_CHANNEL_STATUS ChannelStatus;
|
||||
BOOLEAN IsActive;
|
||||
|
||||
if (!NT_SUCCESS(ChannelGetStatus(Channel, &ChannelStatus))) return FALSE;
|
||||
/* Get the status */
|
||||
if (!NT_SUCCESS(ChannelGetStatus(Channel, &ChannelStatus)))
|
||||
{
|
||||
/* We couldn't even do that, assume it's inactive */
|
||||
IsActive = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if the status shows activity */
|
||||
IsActive = (ChannelStatus == Active);
|
||||
}
|
||||
|
||||
return (ChannelStatus == Active);
|
||||
/* Return the state */
|
||||
return IsActive;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ChannelIsClosed(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelIsClosed(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return FALSE;
|
||||
SAC_CHANNEL_STATUS ChannelStatus;
|
||||
BOOLEAN IsClosed;
|
||||
|
||||
/* Get the status */
|
||||
if (!NT_SUCCESS(ChannelGetStatus(Channel, &ChannelStatus)))
|
||||
{
|
||||
/* We couldn't even do that, assume it's inactive */
|
||||
IsClosed = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if the status shows activity */
|
||||
IsClosed = ((ChannelStatus == Inactive) &&
|
||||
(Channel->ChannelHasNewOBufferData));
|
||||
}
|
||||
|
||||
/* Return the state */
|
||||
return IsClosed;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelCreate(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PSAC_CHANNEL_ATTRIBUTES Attributes,
|
||||
IN SAC_CHANNEL_ID ChannelId
|
||||
)
|
||||
NTAPI
|
||||
ChannelGetName(IN PSAC_CHANNEL Channel,
|
||||
OUT PWCHAR *Name)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Name);
|
||||
|
||||
/* Allocate space to hold the name */
|
||||
*Name = SacAllocatePool(sizeof(Channel->NameBuffer), GLOBAL_BLOCK_TAG);
|
||||
CHECK_ALLOCATION(*Name);
|
||||
|
||||
/* Lock the attributes while we copy the name */
|
||||
ChannelLockAttributes(Channel);
|
||||
|
||||
/* Copy the name and null-terminate it */
|
||||
ASSERT(((wcslen(Channel->NameBuffer) + 1) * sizeof(WCHAR)) <= ((64 + 1) * sizeof(WCHAR)));
|
||||
wcsncpy(*Name, Channel->NameBuffer, RTL_NUMBER_OF(Channel->NameBuffer)); // bug
|
||||
(*Name)[SAC_CHANNEL_NAME_SIZE] = UNICODE_NULL;
|
||||
|
||||
/* Release the lock and return */
|
||||
ChannelUnlockAttributes(Channel);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ChannelClose(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ChannelSetName(IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR Name)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Name);
|
||||
|
||||
/* Lock the attributes while we copy the name */
|
||||
ChannelLockAttributes(Channel);
|
||||
|
||||
/* Copy the name and null-terminate it */
|
||||
ASSERT(((wcslen(Name) + 1) * sizeof(WCHAR)) <= ((64 + 1) * sizeof(WCHAR)));
|
||||
wcsncpy(Channel->NameBuffer, Name, RTL_NUMBER_OF(Channel->NameBuffer)); // bug
|
||||
Channel->NameBuffer[SAC_CHANNEL_NAME_SIZE] = UNICODE_NULL;
|
||||
|
||||
/* Release the lock and return */
|
||||
ChannelUnlockAttributes(Channel);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelGetDescription(IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR* Description)
|
||||
{
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Description);
|
||||
|
||||
/* Allocate space to hold the description */
|
||||
*Description = SacAllocatePool(sizeof(Channel->DescriptionBuffer), GLOBAL_BLOCK_TAG);
|
||||
CHECK_ALLOCATION(*Description);
|
||||
|
||||
/* Lock the attributes while we copy the name */
|
||||
ChannelLockAttributes(Channel);
|
||||
|
||||
/* Copy the name and null-terminate it */
|
||||
ASSERT(((wcslen(Channel->DescriptionBuffer) + 1) * sizeof(WCHAR)) <= ((256 + 1) * sizeof(WCHAR)));
|
||||
wcsncpy(*Description, Channel->DescriptionBuffer, RTL_NUMBER_OF(Channel->DescriptionBuffer)); // bug
|
||||
(*Description)[SAC_CHANNEL_DESCRIPTION_SIZE] = UNICODE_NULL;
|
||||
|
||||
/* Release the lock and return */
|
||||
ChannelUnlockAttributes(Channel);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelSetDescription(IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR Description)
|
||||
{
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Description);
|
||||
|
||||
/* Lock the attributes while we copy the name */
|
||||
ChannelLockAttributes(Channel);
|
||||
|
||||
/* Copy the name and null-terminate it */
|
||||
ASSERT(((wcslen(Description) + 1) * sizeof(WCHAR)) <= ((64 + 1) * sizeof(WCHAR)));
|
||||
wcsncpy(Channel->DescriptionBuffer, Description, RTL_NUMBER_OF(Channel->DescriptionBuffer)); // bug
|
||||
Channel->DescriptionBuffer[SAC_CHANNEL_DESCRIPTION_SIZE] = UNICODE_NULL;
|
||||
|
||||
/* Release the lock and return */
|
||||
ChannelUnlockAttributes(Channel);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelGetApplicationType(IN PSAC_CHANNEL Channel,
|
||||
OUT PGUID ApplicationType)
|
||||
{
|
||||
CHECK_PARAMETER1(Channel);
|
||||
|
||||
/* Read the application type GUID */
|
||||
ChannelLockAttributes(Channel);
|
||||
*ApplicationType = Channel->ApplicationType;
|
||||
ChannelUnlockAttributes(Channel);
|
||||
|
||||
/* Always return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelInitializeVTable(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
/* What kind of channel is this? */
|
||||
switch (Channel->ChannelType)
|
||||
{
|
||||
case VtUtf8:
|
||||
/* FIXME: TODO */
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
case Cmd:
|
||||
/* FIXME: TODO */
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
case Raw:
|
||||
|
||||
/* Setup the calls for a raw channel */
|
||||
Channel->ChannelCreate = RawChannelCreate;
|
||||
Channel->ChannelDestroy = RawChannelDestroy;
|
||||
Channel->ChannelOutputFlush = RawChannelOFlush;
|
||||
Channel->ChannelOutputEcho = RawChannelOEcho;
|
||||
Channel->ChannelOutputWrite = RawChannelOWrite;
|
||||
Channel->ChannelOutputRead = RawChannelORead;
|
||||
Channel->ChannelInputWrite = RawChannelIWrite;
|
||||
Channel->ChannelInputRead = RawChannelIRead;
|
||||
Channel->ChannelInputReadLast = RawChannelIReadLast;
|
||||
Channel->ChannelInputBufferIsFull = RawChannelIBufferIsFull;
|
||||
Channel->ChannelInputBufferLength = RawChannelIBufferLength;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unsupported channel type */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* If we got here, the channel was supported */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelCreate(IN PSAC_CHANNEL Channel,
|
||||
IN PSAC_CHANNEL_ATTRIBUTES Attributes,
|
||||
IN SAC_CHANNEL_ID ChannelId)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Attributes);
|
||||
|
||||
/* If a close event is being passed in, it must exist, and vice-versa */
|
||||
if (Attributes->Flag & SAC_CHANNEL_FLAG_CLOSE_EVENT)
|
||||
{
|
||||
CHECK_PARAMETER(Attributes->CloseEvent != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_PARAMETER(Attributes->CloseEvent == NULL);
|
||||
}
|
||||
|
||||
/* If a new data event is being passed in, it must exist, and vice-versa */
|
||||
if (Attributes->Flag & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
|
||||
{
|
||||
CHECK_PARAMETER(Attributes->HasNewDataEvent != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_PARAMETER(Attributes->HasNewDataEvent == NULL);
|
||||
}
|
||||
|
||||
/* If a lock event is being passed in, it must exist, and vice-versa */
|
||||
if (Attributes->Flag & SAC_CHANNEL_FLAG_LOCK_EVENT)
|
||||
{
|
||||
CHECK_PARAMETER(Attributes->LockEvent != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_PARAMETER(Attributes->LockEvent == NULL);
|
||||
}
|
||||
|
||||
/* If a redraw event is being passed in, it must exist, and vice-versa */
|
||||
if (Attributes->Flag & SAC_CHANNEL_FLAG_REDRAW_EVENT)
|
||||
{
|
||||
CHECK_PARAMETER(Attributes->RedrawEvent != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_PARAMETER(Attributes->RedrawEvent == NULL);
|
||||
}
|
||||
|
||||
/* Initialize the channel structure */
|
||||
RtlZeroMemory(Channel, sizeof(SAC_CHANNEL));
|
||||
Channel->ChannelId = ChannelId;
|
||||
Channel->ChannelType = Attributes->ChannelType;
|
||||
Channel->Flags = Attributes->Flag;
|
||||
if (Attributes->Flag & SAC_CHANNEL_FLAG_APPLICATION)
|
||||
{
|
||||
Channel->ApplicationType = Attributes->ChannelId;
|
||||
}
|
||||
|
||||
/* Initialize all the locks and events */
|
||||
SacInitializeLock(&Channel->ChannelAttributeLock);
|
||||
SacInitializeLock(&Channel->ChannelOBufferLock);
|
||||
SacInitializeLock(&Channel->ChannelIBufferLock);
|
||||
ChannelInitializeEvent(Channel, Attributes, CloseEvent);
|
||||
ChannelInitializeEvent(Channel, Attributes, HasNewDataEvent);
|
||||
ChannelInitializeEvent(Channel, Attributes, LockEvent);
|
||||
ChannelInitializeEvent(Channel, Attributes, RedrawEvent);
|
||||
|
||||
/* Set the name and description */
|
||||
ChannelSetName(Channel, Attributes->NameBuffer);
|
||||
ChannelSetDescription(Channel, Attributes->DescriptionBuffer);
|
||||
|
||||
/* Initialize the function table for the type of channel this is */
|
||||
Status = ChannelInitializeVTable(Channel);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* This is critical */
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC Create Channel :: Failed to initialize vtable\n");
|
||||
goto FailChannel;
|
||||
}
|
||||
|
||||
/* Now call the channel specific type constructor */
|
||||
Status = Channel->ChannelCreate(Channel);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* This is critical */
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC Create Channel :: Failed channel specific initialization\n");
|
||||
goto FailChannel;
|
||||
}
|
||||
|
||||
/* Finally, mark the channel as active */
|
||||
ChannelSetStatus(Channel, Active);
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
FailChannel:
|
||||
/* Destroy the channel and return the failure code */
|
||||
Channel->ChannelDestroy(Channel);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChannelClose(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
CHECK_PARAMETER(Channel);
|
||||
|
||||
/* Set the channel inactive */
|
||||
ChannelSetStatus(Channel, Inactive);
|
||||
|
||||
/* Set the close event */
|
||||
if (Channel->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT)
|
||||
{
|
||||
ChannelSetEvent(Channel, CloseEvent);
|
||||
}
|
||||
|
||||
/* Close all the handles */
|
||||
Status = ChannelDereferenceHandles(Channel);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,75 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/concmd.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/concmd.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
PWCHAR GlobalBuffer;
|
||||
ULONG GlobalBufferSize;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DoRebootCommand(IN BOOLEAN Reboot)
|
||||
{
|
||||
LARGE_INTEGER Timeout, TickCount;
|
||||
NTSTATUS Status;
|
||||
KEVENT Event;
|
||||
SAC_DBG(1, "SAC DoRebootCommand: Entering.\n");
|
||||
|
||||
/* Get the current time now, and setup a timeout in 1 second */
|
||||
KeQueryTickCount(&TickCount);
|
||||
Timeout.QuadPart = TickCount.QuadPart / (10000000 / KeQueryTimeIncrement());
|
||||
|
||||
/* Check if the timeout is small enough */
|
||||
if (Timeout.QuadPart < 60 )
|
||||
{
|
||||
/* Show the prompt */
|
||||
ConMgrSimpleEventMessage(Reboot ?
|
||||
SAC_RESTART_PROMPT : SAC_SHUTDOWN_PROMPT,
|
||||
TRUE);
|
||||
|
||||
/* Do the wait */
|
||||
KeInitializeEvent(&Event, SynchronizationEvent, 0);
|
||||
Timeout.QuadPart = -10000000 * (60 - Timeout.LowPart);
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &Timeout);
|
||||
}
|
||||
|
||||
/* Do a shutdown or a reboot, based on the request */
|
||||
Status = NtShutdownSystem(Reboot ? ShutdownReboot : ShutdownPowerOff);
|
||||
|
||||
/* Check if anyone in the command channel already allocated this */
|
||||
if (!GlobalBuffer)
|
||||
{
|
||||
/* Allocate it */
|
||||
GlobalBuffer = SacAllocatePool(PAGE_SIZE, GLOBAL_BLOCK_TAG);
|
||||
if (!GlobalBuffer)
|
||||
{
|
||||
/* We need the global buffer, bail out without it*/
|
||||
SacPutSimpleMessage(SAC_OUT_OF_MEMORY_PROMPT);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC DoRebootCommand: Exiting (1).\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the size of the buffer */
|
||||
GlobalBufferSize = PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* We came back from a reboot, this doesn't make sense, tell the user */
|
||||
SacPutSimpleMessage(Reboot ? SAC_RESTART_FAIL_PROMPT : SAC_SHUTDOWN_FAIL_PROMPT);
|
||||
swprintf(GlobalBuffer, GetMessage(SAC_FAIL_PROMPT), Status);
|
||||
SacPutString(GlobalBuffer);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC DoRebootCommand: Exiting.\n");
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetTListInfo(
|
||||
|
@ -122,14 +179,6 @@ DoLimitMemoryCommand(
|
|||
|
||||
}
|
||||
|
||||
VOID
|
||||
DoRebootCommand(
|
||||
IN BOOLEAN Reboot
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
DoCrashCommand(
|
||||
VOID
|
||||
|
|
|
@ -1,191 +1,541 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/conmgr.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/conmgr.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
DEFINE_GUID(PRIMARY_SAC_CHANNEL_APPLICATION_GUID,
|
||||
0x63D02270,
|
||||
0x8AA4,
|
||||
0x11D5,
|
||||
0xBC, 0xCF, 0x80, 0x6D, 0x61, 0x72, 0x69, 0x6F);
|
||||
|
||||
NTSTATUS
|
||||
ConMgrShutdown(
|
||||
VOID)
|
||||
LONG CurrentChannelRefCount;
|
||||
KMUTEX CurrentChannelLock;
|
||||
|
||||
PSAC_CHANNEL CurrentChannel;
|
||||
PSAC_CHANNEL SacChannel;
|
||||
|
||||
ULONG ExecutePostConsumerCommand;
|
||||
PSAC_CHANNEL ExecutePostConsumerCommandData;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ConMgrSerialPortConsumer(VOID)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
NTSTATUS Status;
|
||||
CHAR Char;
|
||||
SAC_DBG(0x2000, "SAC TimerDpcRoutine: Entering.\n"); //bug
|
||||
|
||||
NTSTATUS
|
||||
ConMgrDisplayFastChannelSwitchingInterface(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
/* Acquire the manager lock and make sure a channel is selected */
|
||||
SacAcquireMutexLock();
|
||||
ASSERT(CurrentChannel);
|
||||
|
||||
NTSTATUS
|
||||
ConMgrSetCurrentChannel(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
/* Read whatever came off the serial port */
|
||||
for (Status = SerialBufferGetChar(&Char);
|
||||
NT_SUCCESS(Status);
|
||||
Status = SerialBufferGetChar(&Char))
|
||||
{
|
||||
/* If nothing came through, bail out */
|
||||
if (Status == STATUS_NO_DATA_DETECTED) break;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConMgrDisplayCurrentChannel(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConMgrAdvanceCurrentChannel(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ConMgrIsWriteEnabled(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
/* We're done, release the lock */
|
||||
SacReleaseMutexLock();
|
||||
SAC_DBG(0x2000, "SAC TimerDpcRoutine: Exiting.\n"); //bug
|
||||
}
|
||||
|
||||
VOID
|
||||
SacPutString(
|
||||
IN PWCHAR String
|
||||
)
|
||||
NTAPI
|
||||
ConMgrWorkerProcessEvents(IN PSAC_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC WorkerProcessEvents: Entering.\n");
|
||||
|
||||
}
|
||||
/* Enter the main loop */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Wait for something to do */
|
||||
KeWaitForSingleObject(&DeviceExtension->Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
BOOLEAN
|
||||
SacPutSimpleMessage(
|
||||
IN ULONG MessageIndex
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
/* Consume data off the serial port */
|
||||
ConMgrSerialPortConsumer();
|
||||
switch (ExecutePostConsumerCommand)
|
||||
{
|
||||
case 1:
|
||||
/* A reboot was sent, do it */
|
||||
DoRebootCommand(FALSE);
|
||||
break;
|
||||
|
||||
NTSTATUS
|
||||
ConMgrChannelOWrite(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PVOID WriteBuffer
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
case 2:
|
||||
/* A close was sent, do it */
|
||||
ChanMgrCloseChannel(ExecutePostConsumerCommandData);
|
||||
ChanMgrReleaseChannel(ExecutePostConsumerCommandData);
|
||||
break;
|
||||
|
||||
NTSTATUS
|
||||
ConMgrGetChannelCloseMessage(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN NTSTATUS CloseStatus,
|
||||
OUT PWCHAR OutputBuffer
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
case 3:
|
||||
/* A shutdown was sent, do it */
|
||||
DoRebootCommand(TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConMgrWriteData(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConMgrFlushData(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ConMgrIsSacChannel(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConMgrInitialize(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConMgrResetCurrentChannel(
|
||||
IN BOOLEAN KeepChannel
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
/* Clear the serial port consumer state */
|
||||
ExecutePostConsumerCommand = 0;
|
||||
ExecutePostConsumerCommandData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
ConMgrProcessInputLine(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
ConMgrEventMessage(
|
||||
IN PWCHAR EventMessage,
|
||||
IN BOOLEAN LockHeld
|
||||
)
|
||||
NTAPI
|
||||
SacPutString(IN PWCHAR String)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Write the string on the main SAC channel */
|
||||
Status = ChannelOWrite(SacChannel,
|
||||
(PCHAR)String,
|
||||
wcslen(String) * sizeof(WCHAR));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC XmlMgrSacPutString: OWrite failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ConMgrSimpleEventMessage(
|
||||
IN ULONG MessageIndex,
|
||||
IN BOOLEAN LockHeld
|
||||
)
|
||||
NTAPI
|
||||
SacPutSimpleMessage(IN ULONG MessageIndex)
|
||||
{
|
||||
return FALSE;
|
||||
PWCHAR MessageBuffer;
|
||||
BOOLEAN Result;
|
||||
|
||||
/* Get the message */
|
||||
MessageBuffer = GetMessage(MessageIndex);
|
||||
if (MessageBuffer)
|
||||
{
|
||||
/* Output it */
|
||||
SacPutString(MessageBuffer);
|
||||
Result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = FALSE;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConMgrChannelClose(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ConMgrDisplayCurrentChannel(VOID)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN HasRedraw;
|
||||
|
||||
/* Make sure the lock is held */
|
||||
SacAssertMutexLockHeld();
|
||||
|
||||
/* Check if we can redraw */
|
||||
Status = ChannelHasRedrawEvent(CurrentChannel, &HasRedraw);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Enable writes */
|
||||
_InterlockedExchange(&CurrentChannel->WriteEnabled, 1);
|
||||
if (HasRedraw)
|
||||
{
|
||||
/* If we can redraw, set the event */
|
||||
ChannelSetRedrawEvent(CurrentChannel);
|
||||
}
|
||||
|
||||
/* Flush the output */
|
||||
Status = ChannelOFlush(CurrentChannel);
|
||||
}
|
||||
|
||||
/* All done, return the status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ConMgrHandleEvent(
|
||||
IN ULONG EventCode,
|
||||
IN PSAC_CHANNEL Channel,
|
||||
OUT PVOID Data
|
||||
)
|
||||
NTAPI
|
||||
ConMgrWriteData(IN PSAC_CHANNEL Channel,
|
||||
IN PVOID Buffer,
|
||||
IN ULONG BufferLength)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
ULONG i;
|
||||
NTSTATUS Status;
|
||||
LARGE_INTEGER Interval;
|
||||
|
||||
/* Loop up to 32 times */
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
/* Attempt sending the data */
|
||||
Status = HeadlessDispatch(HeadlessCmdPutData, Buffer, BufferLength, NULL, NULL);
|
||||
if (Status != STATUS_UNSUCCESSFUL) break;
|
||||
|
||||
/* Sending the data on the port failed, wait a second... */
|
||||
Interval.HighPart = -1;
|
||||
Interval.LowPart = -100000;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
|
||||
}
|
||||
|
||||
/* After 32 attempts it should really have worked... */
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrFlushData(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
/* Nothing to do */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
ConMgrIsSacChannel(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
/* Check which channel is active */
|
||||
return Channel == SacChannel;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
ConMgrIsWriteEnabled(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
/* If the current channel is active, allow writes */
|
||||
return ChannelIsEqual(Channel, &CurrentChannel->ChannelId);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrInitialize(VOID)
|
||||
{
|
||||
PWCHAR pcwch;
|
||||
PSAC_CHANNEL FoundChannel;
|
||||
SAC_CHANNEL_ATTRIBUTES SacChannelAttributes;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Initialize the connection manager lock */
|
||||
SacInitializeMutexLock();
|
||||
SacAcquireMutexLock();
|
||||
|
||||
/* Setup the attributes for the raw SAC channel */
|
||||
RtlZeroMemory(&SacChannelAttributes, sizeof(SacChannelAttributes));
|
||||
SacChannelAttributes.ChannelType = Raw;
|
||||
|
||||
/* Get the right name for it */
|
||||
pcwch = GetMessage(SAC_CHANNEL_NAME);
|
||||
ASSERT(pcwch);
|
||||
wcsncpy(SacChannelAttributes.NameBuffer, pcwch, SAC_CHANNEL_NAME_SIZE);
|
||||
SacChannelAttributes.NameBuffer[SAC_CHANNEL_NAME_SIZE] = ANSI_NULL;
|
||||
|
||||
/* Get the right description for it */
|
||||
pcwch = GetMessage(SAC_CHANNEL_DESCRIPTION);
|
||||
ASSERT(pcwch);
|
||||
wcsncpy(SacChannelAttributes.DescriptionBuffer, pcwch, SAC_CHANNEL_DESCRIPTION_SIZE);
|
||||
SacChannelAttributes.DescriptionBuffer[SAC_CHANNEL_DESCRIPTION_SIZE] = ANSI_NULL;
|
||||
|
||||
/* Set all the right flags */
|
||||
SacChannelAttributes.Flag = SAC_CHANNEL_FLAG_APPLICATION | SAC_CHANNEL_FLAG_INTERNAL;
|
||||
SacChannelAttributes.CloseEvent = NULL;
|
||||
SacChannelAttributes.HasNewDataEvent = NULL;
|
||||
SacChannelAttributes.LockEvent = NULL;
|
||||
SacChannelAttributes.RedrawEvent = NULL;
|
||||
SacChannelAttributes.ChannelId = PRIMARY_SAC_CHANNEL_APPLICATION_GUID;
|
||||
|
||||
/* Now create it */
|
||||
Status = ChanMgrCreateChannel(&SacChannel, &SacChannelAttributes);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Try to get it back */
|
||||
Status = ChanMgrGetByHandle(SacChannel->ChannelId, &FoundChannel);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Set it as the current and SAC channel */
|
||||
SacChannel = CurrentChannel = FoundChannel;
|
||||
|
||||
/* Diasable writes for now and clear the display */
|
||||
_InterlockedExchange(&FoundChannel->WriteEnabled, FALSE);
|
||||
Status = HeadlessDispatch(HeadlessCmdClearDisplay, NULL, 0, NULL, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC ConMgrInitialize: Failed dispatch\n");
|
||||
}
|
||||
|
||||
/* Display the initial prompt */
|
||||
SacPutSimpleMessage(SAC_NEWLINE);
|
||||
SacPutSimpleMessage(SAC_INIT_STATUS);
|
||||
SacPutSimpleMessage(SAC_NEWLINE);
|
||||
SacPutSimpleMessage(SAC_PROMPT);
|
||||
|
||||
/* Display the current channel */
|
||||
ConMgrDisplayCurrentChannel();
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the channel lock */
|
||||
SacReleaseMutexLock();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
ConMgrWorkerProcessEvents(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
ConMgrEventMessage(IN PWCHAR EventMessage,
|
||||
IN BOOLEAN LockHeld)
|
||||
{
|
||||
/* Acquire the current channel lock if needed */
|
||||
if (!LockHeld) SacAcquireMutexLock();
|
||||
|
||||
/* Send out the event message */
|
||||
SacPutSimpleMessage(2);
|
||||
SacPutString(EventMessage);
|
||||
SacPutSimpleMessage(3);
|
||||
|
||||
/* Release the current channel lock if needed */
|
||||
if (!LockHeld) SacReleaseMutexLock();
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
ConMgrSimpleEventMessage(IN ULONG MessageIndex,
|
||||
IN BOOLEAN LockHeld)
|
||||
{
|
||||
PWCHAR MessageBuffer;
|
||||
BOOLEAN Result;
|
||||
|
||||
/* Get the message to send out */
|
||||
MessageBuffer = GetMessage(MessageIndex);
|
||||
if (MessageBuffer)
|
||||
{
|
||||
/* Send it */
|
||||
ConMgrEventMessage(MessageBuffer, LockHeld);
|
||||
Result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It doesn't exist, fail */
|
||||
Result = FALSE;
|
||||
}
|
||||
|
||||
/* Return if the message was sent or not */
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrDisplayFastChannelSwitchingInterface(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
/* FIXME: TODO */
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrSetCurrentChannel(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOLEAN HasRedrawEvent;
|
||||
|
||||
/* Make sure the lock is held */
|
||||
SacAssertMutexLockHeld();
|
||||
|
||||
/* Check if we have a redraw event */
|
||||
Status = ChannelHasRedrawEvent(CurrentChannel, &HasRedrawEvent);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Clear it */
|
||||
if (HasRedrawEvent) ChannelClearRedrawEvent(CurrentChannel);
|
||||
|
||||
/* Disable writes on the current channel */
|
||||
_InterlockedExchange(&CurrentChannel->WriteEnabled, 0);
|
||||
|
||||
/* Release the current channel */
|
||||
Status = ChanMgrReleaseChannel(CurrentChannel);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Set the new channel and also disable writes on it */
|
||||
CurrentChannel = Channel;
|
||||
_InterlockedExchange(&Channel->WriteEnabled, 0);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrResetCurrentChannel(IN BOOLEAN KeepChannel)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PSAC_CHANNEL Channel;
|
||||
|
||||
/* Make sure the lock is held */
|
||||
SacAssertMutexLockHeld();
|
||||
|
||||
/* Get the current SAC channel */
|
||||
Status = ChanMgrGetByHandle(SacChannel->ChannelId, &Channel);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Set this as the current SAC channel*/
|
||||
SacChannel = Channel;
|
||||
Status = ConMgrSetCurrentChannel(Channel);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Check if the caller wants to switch or not */
|
||||
if (KeepChannel)
|
||||
{
|
||||
/* Nope, keep the same channel */
|
||||
Status = ConMgrDisplayCurrentChannel();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yep, show the switching interface */
|
||||
Status = ConMgrDisplayFastChannelSwitchingInterface(CurrentChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrChannelClose(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
/* Check if we're in the right channel */
|
||||
if (ConMgrIsWriteEnabled(Channel))
|
||||
{
|
||||
/* Yep, reset it */
|
||||
Status = ConMgrResetCurrentChannel(FALSE);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrShutdown(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Check if we have a SAC channel */
|
||||
if (SacChannel)
|
||||
{
|
||||
/* Close it */
|
||||
Status = ChannelClose(SacChannel);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC ConMgrShutdown: failed closing SAC channel.\n");
|
||||
}
|
||||
|
||||
/* No longer have one */
|
||||
SacChannel = NULL;
|
||||
}
|
||||
|
||||
/* Check if we have a current channel */
|
||||
if (CurrentChannel)
|
||||
{
|
||||
/* Release it */
|
||||
Status = ChanMgrReleaseChannel(CurrentChannel);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC ConMgrShutdown: failed releasing current channel\n");
|
||||
}
|
||||
|
||||
/* No longer have one */
|
||||
CurrentChannel = NULL;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrAdvanceCurrentChannel(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Index;
|
||||
PSAC_CHANNEL Channel;
|
||||
|
||||
/* Should always be called with the lock held */
|
||||
SacAssertMutexLockHeld();
|
||||
|
||||
/* Get the next active channel */
|
||||
Status = ChanMgrGetNextActiveChannel(CurrentChannel, &Index, &Channel);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Set it as the new channel */
|
||||
Status = ConMgrSetCurrentChannel(Channel);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Let the user switch to it */
|
||||
Status = ConMgrDisplayFastChannelSwitchingInterface(Channel);
|
||||
}
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrChannelOWrite(IN PSAC_CHANNEL Channel,
|
||||
IN PVOID WriteBuffer)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Do the write with the lock held */
|
||||
SacAcquireMutexLock();
|
||||
Status = STATUS_NOT_IMPLEMENTED;// ChannelOWrite(Channel, WriteBuffer + 24, *(WriteBuffer + 20));
|
||||
SacReleaseMutexLock();
|
||||
|
||||
/* Return back to the caller */
|
||||
ASSERT(NT_SUCCESS(Status) || Status == STATUS_NOT_FOUND);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrGetChannelCloseMessage(IN PSAC_CHANNEL Channel,
|
||||
IN NTSTATUS CloseStatus,
|
||||
OUT PWCHAR OutputBuffer)
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ConMgrProcessInputLine(VOID)
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ConMgrHandleEvent(IN ULONG EventCode,
|
||||
IN PSAC_CHANNEL Channel,
|
||||
OUT PVOID Data)
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,58 +1,502 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/data.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/data.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
ULONG SACDebug;
|
||||
ULONG SACDebug = 0xFFFFFFFF;
|
||||
BOOLEAN CommandConsoleLaunchingEnabled;
|
||||
BOOLEAN GlobalDataInitialized;
|
||||
KMUTEX SACCMDEventInfoMutex;
|
||||
BOOLEAN IoctlSubmitted;
|
||||
ULONG ProcessingType;
|
||||
PKEVENT SACEvent;
|
||||
HANDLE SACEventHandle;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
FreeGlobalData(
|
||||
VOID
|
||||
)
|
||||
NTAPI
|
||||
WorkerProcessEvents(IN PSAC_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
|
||||
/* Call the worker function */
|
||||
return ConMgrWorkerProcessEvents(DeviceExtension);
|
||||
}
|
||||
|
||||
VOID
|
||||
FreeDeviceData(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
)
|
||||
NTAPI
|
||||
WorkerThreadStartUp(IN PVOID Context)
|
||||
{
|
||||
|
||||
/* Call the worker function */
|
||||
WorkerProcessEvents((PSAC_DEVICE_EXTENSION)Context);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
WorkerThreadStartUp(
|
||||
IN PVOID Context
|
||||
)
|
||||
NTAPI
|
||||
BuildDeviceAcl(OUT PACL* Dacl)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
/* TODO */
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CreateDeviceSecurityDescriptor(IN PDEVICE_OBJECT *DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
BOOLEAN MemoryAllocated = FALSE;
|
||||
PACL Dacl = NULL;
|
||||
PVOID ObjectSecurityDescriptor = NULL;
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Entering.\n");
|
||||
|
||||
/* Get the current SD of the device object */
|
||||
Status = ObGetObjectSecurity(*DeviceObject, &SecurityDescriptor, &MemoryAllocated);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC: Unable to get security descriptor, error: %x\n", Status);
|
||||
NT_ASSERT(MemoryAllocated == FALSE);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Exiting with status 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Build a DACL for it */
|
||||
Status = BuildDeviceAcl(&Dacl);
|
||||
if (Status >= 0)
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC CreateDeviceSecurityDescriptor : Unable to create Raw ACL, error : %x\n", Status);
|
||||
goto CleanupPath;
|
||||
}
|
||||
|
||||
CleanupPath:
|
||||
/* Release the SD we queried */
|
||||
ObReleaseObjectSecurity(SecurityDescriptor, MemoryAllocated);
|
||||
|
||||
/* Free anything else we may have allocated */
|
||||
if (ObjectSecurityDescriptor) ExFreePool(ObjectSecurityDescriptor);
|
||||
if (Dacl) SacFreePool(Dacl);
|
||||
|
||||
/* All done */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Exiting with status 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
FreeGlobalData(VOID)
|
||||
{
|
||||
UNICODE_STRING SymbolicLink;
|
||||
SAC_DBG(1, "SAC FreeGlobalData: Entering.\n");
|
||||
|
||||
/* Only free if we allocated */
|
||||
if (GlobalDataInitialized)
|
||||
{
|
||||
/* Close the SAC event if we had created one */
|
||||
if (SACEvent)
|
||||
{
|
||||
ZwClose(SACEventHandle);
|
||||
SACEvent = NULL;
|
||||
}
|
||||
|
||||
/* Destroy the cached messages */
|
||||
TearDownGlobalMessageTable();
|
||||
|
||||
/* Delete the Win32 symbolic link */
|
||||
RtlInitUnicodeString(&SymbolicLink, L"\\DosDevices\\SAC");
|
||||
IoDeleteSymbolicLink(&SymbolicLink);
|
||||
|
||||
/* Tear down connections */
|
||||
ConMgrShutdown();
|
||||
|
||||
/* Tear down channels */
|
||||
ChanMgrShutdown();
|
||||
|
||||
/* Free the serial port buffer */
|
||||
if (SerialPortBuffer) SacFreePool(SerialPortBuffer);
|
||||
|
||||
/* Free cached machine information */
|
||||
FreeMachineInformation();
|
||||
|
||||
/* Cleanup the custom heap allocator */
|
||||
FreeMemoryManagement();
|
||||
|
||||
/* We're back to a virgin state */
|
||||
GlobalDataInitialized = FALSE;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
SAC_DBG(1, "SAC FreeGlobalData: Exiting.\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
FreeDeviceData(IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PSAC_DEVICE_EXTENSION DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC FreeDeviceData: Entering.\n");
|
||||
|
||||
/* Get the device extension and see how far we had gotten */
|
||||
DeviceExtension = (PSAC_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
if ((GlobalDataInitialized) && (DeviceExtension->Initialized))
|
||||
{
|
||||
/* Attempt to rundown while holding the lock */
|
||||
KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
|
||||
while (DeviceExtension->RundownInProgress)
|
||||
{
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC FreeDeviceData: Waiting....\n");
|
||||
|
||||
/* Initiate and wait for rundown */
|
||||
KeInitializeEvent(&DeviceExtension->RundownEvent, SynchronizationEvent, 0);
|
||||
KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
|
||||
Status = KeWaitForSingleObject(&DeviceExtension->RundownEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
|
||||
/* Re-acquire the lock and check if rundown is done */
|
||||
KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set the rundown flag while we cancel the timer */
|
||||
DeviceExtension->RundownInProgress = TRUE;
|
||||
KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
|
||||
|
||||
/* Cancel it */
|
||||
KeCancelTimer(&DeviceExtension->Timer);
|
||||
|
||||
/* Reacquire the lock*/
|
||||
KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
|
||||
DeviceExtension->RundownInProgress = FALSE;
|
||||
|
||||
/* Now do the last rundown attempt, we should be the only ones here */
|
||||
KeInitializeEvent(&DeviceExtension->RundownEvent, SynchronizationEvent, 0);
|
||||
KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
|
||||
KeSetEvent(&DeviceExtension->Event, DeviceExtension->PriorityBoost, 0);
|
||||
Status = KeWaitForSingleObject(&DeviceExtension->RundownEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
|
||||
/* We no longer care about shutdown */
|
||||
IoUnregisterShutdownNotification(DeviceObject);
|
||||
|
||||
/* We are now fully uninitialized */
|
||||
KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
|
||||
DeviceExtension->Initialized = FALSE;
|
||||
KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC FreeDeviceData: Exiting.\n");
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
InitializeDeviceData(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
)
|
||||
NTAPI
|
||||
InitializeDeviceData(IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
return FALSE;
|
||||
PSAC_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
BOOLEAN EnableData;
|
||||
ULONG PriorityValue;
|
||||
NTSTATUS Status;
|
||||
LARGE_INTEGER DueTime;
|
||||
PWCHAR Message;
|
||||
PAGED_CODE();
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n");
|
||||
|
||||
/* If we already did this, bail out */
|
||||
if (DeviceExtension->Initialized) goto SuccessExit;
|
||||
|
||||
/* Setup the DO flags */
|
||||
DeviceObject->Flags |= DO_DIRECT_IO;
|
||||
DeviceObject->StackSize = 16;
|
||||
|
||||
/* Setup the device extension */
|
||||
DeviceExtension->DeviceObject = DeviceObject;
|
||||
DeviceExtension->PriorityBoost = IO_SERIAL_INCREMENT;
|
||||
DeviceExtension->PriorityFail = 0;
|
||||
DeviceExtension->RundownInProgress = 0;
|
||||
|
||||
/* Initialize locks, events, timers, DPCs, etc... */
|
||||
KeInitializeTimer(&DeviceExtension->Timer);
|
||||
KeInitializeDpc(&DeviceExtension->Dpc, TimerDpcRoutine, DeviceExtension);
|
||||
KeInitializeSpinLock(&DeviceExtension->Lock);
|
||||
KeInitializeEvent(&DeviceExtension->Event, SynchronizationEvent, 0);
|
||||
InitializeListHead(&DeviceExtension->List);
|
||||
|
||||
/* Attempt to enable HDL support */
|
||||
EnableData = TRUE;
|
||||
Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
|
||||
&EnableData,
|
||||
sizeof(EnableData),
|
||||
NULL,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Bail out if we couldn't even get this far */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting (1) with status FALSE\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Remember which process we started in */
|
||||
DeviceExtension->Process = IoGetCurrentProcess();
|
||||
|
||||
/* Protect the device against non-admins */
|
||||
Status = CreateDeviceSecurityDescriptor(&DeviceExtension->DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Write down why we failed */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting (2) with status FALSE\n");
|
||||
|
||||
/* Disable the HDL terminal on failure */
|
||||
EnableData = FALSE;
|
||||
Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
|
||||
&EnableData,
|
||||
sizeof(EnableData),
|
||||
NULL,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) SAC_DBG(SAC_DBG_INIT, "Failed dispatch\n");
|
||||
|
||||
/* Bail out */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Create the worker thread */
|
||||
Status = PsCreateSystemThread(&DeviceExtension->WorkerThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
WorkerThreadStartUp,
|
||||
DeviceExtension);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Write down why we failed */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting (3) with status FALSE\n");
|
||||
|
||||
/* Disable the HDL terminal on failure */
|
||||
EnableData = FALSE;
|
||||
Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
|
||||
&EnableData,
|
||||
sizeof(EnableData),
|
||||
NULL,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) SAC_DBG(SAC_DBG_INIT, "Failed dispatch\n");
|
||||
|
||||
/* Bail out */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Set the priority of our thread to highest */
|
||||
PriorityValue = HIGH_PRIORITY;
|
||||
Status = NtSetInformationThread(DeviceExtension->WorkerThreadHandle,
|
||||
ThreadPriority,
|
||||
&PriorityValue,
|
||||
sizeof(PriorityValue));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* For debugging, write down why we failed */
|
||||
SAC_DBG(1, "Exiting (6) with status FALSE\n");
|
||||
DeviceExtension->PriorityFail = TRUE;
|
||||
|
||||
/* Initialize rundown and wait for the thread to do it */
|
||||
KeInitializeEvent(&DeviceExtension->RundownEvent, SynchronizationEvent, 0);
|
||||
KeSetEvent(&DeviceExtension->Event, DeviceExtension->PriorityBoost, 0);
|
||||
Status = KeWaitForSingleObject(&DeviceExtension->RundownEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
|
||||
/* Disable the HDL terminal on failure */
|
||||
EnableData = FALSE;
|
||||
Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
|
||||
&EnableData,
|
||||
sizeof(EnableData),
|
||||
NULL,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status)) SAC_DBG(SAC_DBG_INIT, "Failed dispatch\n");
|
||||
|
||||
/* Bail out */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The first "packet" is the machine information in XML... */
|
||||
Status = TranslateMachineInformationXML(&Message, NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Go ahead and send it */
|
||||
UTF8EncodeAndSend(L"<?xml version=\"1.0\"?>\r\n");
|
||||
UTF8EncodeAndSend(Message);
|
||||
|
||||
/* Free the temporary buffer */
|
||||
SacFreePool(Message);
|
||||
}
|
||||
|
||||
/* Finally, initialize the I/O Manager */
|
||||
Status = ConMgrInitialize();
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
|
||||
/* Set the timer. Once this is done, the device is initialized */
|
||||
DueTime.QuadPart = -4000;
|
||||
KeSetTimerEx(&DeviceExtension->Timer, DueTime, 4, &DeviceExtension->Dpc);
|
||||
DeviceExtension->Initialized = TRUE;
|
||||
|
||||
SuccessExit:
|
||||
/* Success path -- everything worked */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status TRUE\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
InitializeGlobalData(
|
||||
IN PUNICODE_STRING RegistryPath,
|
||||
IN PDRIVER_OBJECT DriverObject
|
||||
)
|
||||
NTAPI
|
||||
InitializeGlobalData(IN PUNICODE_STRING RegistryPath,
|
||||
IN PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
return FALSE;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING LinkName;
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING EventName;
|
||||
PAGED_CODE();
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n");
|
||||
|
||||
/* If we already did this, bail out */
|
||||
if (!GlobalDataInitialized) goto SuccessExit;
|
||||
|
||||
/* Setup the symbolic link for Win32 support */
|
||||
RtlInitUnicodeString(&LinkName, L"\\DosDevices\\SAC");
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\SAC");
|
||||
Status = IoCreateSymbolicLink(&LinkName, &DeviceName);
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
|
||||
/* Initialize the internal heap manager */
|
||||
if (!InitializeMemoryManagement())
|
||||
{
|
||||
IoDeleteSymbolicLink(&LinkName);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status FALSE\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Preload the messages in memory */
|
||||
Status = PreloadGlobalMessageTable(DriverObject->DriverStart);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
IoDeleteSymbolicLink(&LinkName);
|
||||
SAC_DBG(SAC_DBG_INIT, "unable to pre-load message table: %X\n", Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check if the administrator enabled this */
|
||||
Status = GetCommandConsoleLaunchingPermission(&CommandConsoleLaunchingEnabled);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Is it enabled? */
|
||||
if (CommandConsoleLaunchingEnabled)
|
||||
{
|
||||
/* Set the service start type to the correct value */
|
||||
Status = ImposeSacCmdServiceStartTypePolicy();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "failed ImposeSacCmdServiceStartTypePolicy: %X\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
/* We're going to keep going with the default */
|
||||
SAC_DBG(SAC_DBG_INIT, "failed GetCommandConsoleLaunchingPermission: %X\n", Status);
|
||||
}
|
||||
|
||||
/* Allocate the UTF-8 Conversion Buffer */
|
||||
Utf8ConversionBuffer = SacAllocatePool(Utf8ConversionBufferSize, GLOBAL_BLOCK_TAG);
|
||||
if (!Utf8ConversionBuffer)
|
||||
{
|
||||
/* Handle failure case */
|
||||
TearDownGlobalMessageTable();
|
||||
IoDeleteSymbolicLink(&LinkName);
|
||||
SAC_DBG(SAC_DBG_INIT, "unable to allocate memory for UTF8 translation\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Initialize the channel manager */
|
||||
Status = ChanMgrInitialize();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Handle failure case */
|
||||
SacFreePool(Utf8ConversionBuffer);
|
||||
TearDownGlobalMessageTable();
|
||||
IoDeleteSymbolicLink(&LinkName);
|
||||
SAC_DBG(SAC_DBG_INIT, "Failed to create SAC Channel\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Allocate the serial port buffer */
|
||||
SerialPortBuffer = SacAllocatePool(SAC_SERIAL_PORT_BUFFER_SIZE, GLOBAL_BLOCK_TAG);
|
||||
if (!SerialPortBuffer)
|
||||
{
|
||||
/* Handle failure case */
|
||||
SacFreePool(Utf8ConversionBuffer);
|
||||
TearDownGlobalMessageTable();
|
||||
IoDeleteSymbolicLink(&LinkName);
|
||||
SAC_DBG(SAC_DBG_INIT, "Failed to allocate Serial Port Buffer\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Zero it out */
|
||||
RtlZeroMemory(SerialPortBuffer, SAC_SERIAL_PORT_BUFFER_SIZE);
|
||||
|
||||
/* Initialize command events. After this, driver data is good to go */
|
||||
KeInitializeMutex(&SACCMDEventInfoMutex, FALSE);
|
||||
InitializeCmdEventInfo();
|
||||
GlobalDataInitialized = TRUE;
|
||||
ProcessingType = 0;
|
||||
IoctlSubmitted = 0;
|
||||
|
||||
/* Create the SAC event */
|
||||
RtlInitUnicodeString(&EventName, L"\\SACEvent");
|
||||
SACEvent = IoCreateSynchronizationEvent(&EventName, &SACEventHandle);
|
||||
if (!SACEvent)
|
||||
{
|
||||
/* Handle failure case */
|
||||
SacFreePool(Utf8ConversionBuffer);
|
||||
TearDownGlobalMessageTable();
|
||||
IoDeleteSymbolicLink(&LinkName);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with event NULL\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Cache machine information */
|
||||
InitializeMachineInformation();
|
||||
|
||||
/* Register it */
|
||||
Status = RegisterBlueScreenMachineInformation();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Handle failure case */
|
||||
SacFreePool(Utf8ConversionBuffer);
|
||||
TearDownGlobalMessageTable();
|
||||
IoDeleteSymbolicLink(&LinkName);
|
||||
SAC_DBG(SAC_DBG_INIT, "Failed to register blue screen machine info\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SuccessExit:
|
||||
/* Success path -- everything worked */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status TRUE\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,88 +1,90 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/dispatch.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/dispatch.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DispatchDeviceControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DispatchShutdownControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
NTAPI
|
||||
DispatchShutdownControl(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DispatchCreate(
|
||||
IN PSAC_DEVICE_EXTENSION DeviceExtension,
|
||||
IN PIRP Irp
|
||||
)
|
||||
NTAPI
|
||||
DispatchCreate(IN PSAC_DEVICE_EXTENSION DeviceExtension,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DispatchClose(
|
||||
IN PSAC_DEVICE_EXTENSION DeviceExtension,
|
||||
IN PIRP Irp
|
||||
)
|
||||
NTAPI
|
||||
DispatchClose(IN PSAC_DEVICE_EXTENSION DeviceExtension,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
Dispatch(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
NTAPI
|
||||
Dispatch(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
WorkerProcessEvents(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
TimerDpcRoutine(
|
||||
IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2
|
||||
)
|
||||
NTAPI
|
||||
TimerDpcRoutine(IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
UnloadHandler(
|
||||
IN PDRIVER_OBJECT DriverObject
|
||||
)
|
||||
NTAPI
|
||||
UnloadHandler(IN PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject, NextDevice;
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC UnloadHandler: Entering.\n");
|
||||
|
||||
/* Go overy ever device part of the driver */
|
||||
DeviceObject = DriverObject->DeviceObject;
|
||||
while (DeviceObject)
|
||||
{
|
||||
/* Free and delete the information about this device */
|
||||
NextDevice = DeviceObject->NextDevice;
|
||||
FreeDeviceData(DeviceObject);
|
||||
IoDeleteDevice(DeviceObject);
|
||||
|
||||
/* Move on to the next one */
|
||||
DeviceObject = NextDevice;
|
||||
}
|
||||
|
||||
/* Free the driver data and exit */
|
||||
FreeGlobalData();
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC UnloadHandler: Exiting.\n");
|
||||
}
|
||||
|
|
|
@ -1,94 +1,94 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/init.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/init.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath
|
||||
)
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
HEADLESS_RSP_QUERY_INFO HeadlessInformation;
|
||||
ULONG InfoSize;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING DriverName;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PSAC_DEVICE_EXTENSION DeviceExtension;
|
||||
PAGED_CODE();
|
||||
HEADLESS_RSP_QUERY_INFO HeadlessInformation;
|
||||
ULONG InfoSize = sizeof(HeadlessInformation);
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING DriverName;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PSAC_DEVICE_EXTENSION DeviceExtension;
|
||||
PAGED_CODE();
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n");
|
||||
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n");
|
||||
/* Check if EMS is enabled in the kernel */
|
||||
HeadlessDispatch(HeadlessCmdQueryInformation,
|
||||
NULL,
|
||||
0,
|
||||
&HeadlessInformation,
|
||||
&InfoSize);
|
||||
if ((HeadlessInformation.Serial.TerminalType != HeadlessUndefinedPortType) &&
|
||||
((HeadlessInformation.Serial.TerminalType != HeadlessSerialPort) ||
|
||||
(HeadlessInformation.Serial.TerminalAttached)))
|
||||
{
|
||||
/* It is, so create the device */
|
||||
RtlInitUnicodeString(&DriverName, L"\\Device\\SAC");
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(SAC_DEVICE_EXTENSION),
|
||||
&DriverName,
|
||||
FILE_DEVICE_UNKNOWN,
|
||||
FILE_DEVICE_SECURE_OPEN,
|
||||
FALSE,
|
||||
&DeviceObject);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Setup the device extension */
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
DeviceExtension->Initialized = FALSE;
|
||||
|
||||
HeadlessDispatch(
|
||||
HeadlessCmdQueryInformation,
|
||||
NULL,
|
||||
0,
|
||||
&HeadlessInformation,
|
||||
&InfoSize
|
||||
);
|
||||
if ((HeadlessInformation.Serial.TerminalType != HeadlessUndefinedPortType) &&
|
||||
((HeadlessInformation.Serial.TerminalType != HeadlessSerialPort) ||
|
||||
(HeadlessInformation.Serial.TerminalAttached)))
|
||||
{
|
||||
RtlInitUnicodeString(&DriverName, L"\\Device\\SAC");
|
||||
/* Initialize the driver object */
|
||||
RtlFillMemoryUlong(DriverObject->MajorFunction,
|
||||
RTL_NUMBER_OF(DriverObject->MajorFunction),
|
||||
(ULONG_PTR)Dispatch);
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DispatchShutdownControl;
|
||||
DriverObject->FastIoDispatch = NULL;
|
||||
DriverObject->DriverUnload = UnloadHandler;
|
||||
|
||||
Status = IoCreateDevice(
|
||||
DriverObject,
|
||||
sizeof(SAC_DEVICE_EXTENSION),
|
||||
&DriverName,
|
||||
FILE_DEVICE_UNKNOWN,
|
||||
FILE_DEVICE_SECURE_OPEN,
|
||||
FALSE,
|
||||
&DeviceObject
|
||||
);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
DeviceExtension->Initialized = FALSE;
|
||||
/* Initialize driver data */
|
||||
if (InitializeGlobalData(RegistryPath, DriverObject))
|
||||
{
|
||||
/* Initialize device data */
|
||||
if (InitializeDeviceData(DeviceObject))
|
||||
{
|
||||
/* We're all good, register a shutdown notification */
|
||||
IoRegisterShutdownNotification(DeviceObject);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
RtlFillMemoryUlong(
|
||||
DriverObject->MajorFunction,
|
||||
sizeof(DriverObject->MajorFunction) / sizeof(PVOID),
|
||||
(ULONG_PTR)Dispatch);
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
|
||||
DispatchDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =
|
||||
DispatchShutdownControl;
|
||||
DriverObject->FastIoDispatch = NULL;
|
||||
DriverObject->DriverUnload = UnloadHandler;
|
||||
/* One of the initializations failed, bail out */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Print a debug statement if enabled */
|
||||
SAC_DBG(SAC_DBG_INIT, "unable to create device object: %X\n", Status);
|
||||
}
|
||||
|
||||
if (InitializeGlobalData(RegistryPath, DriverObject))
|
||||
{
|
||||
if (InitializeDeviceData(DeviceObject))
|
||||
{
|
||||
IoRegisterShutdownNotification(DeviceObject);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
/* Free any data we may have allocated and exit with failure */
|
||||
FreeGlobalData();
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "unable to create device object: %X\n", Status);
|
||||
}
|
||||
|
||||
FreeGlobalData();
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
return STATUS_PORT_DISCONNECTED;
|
||||
/* EMS is not enabled */
|
||||
return STATUS_PORT_DISCONNECTED;
|
||||
}
|
||||
|
|
|
@ -1,108 +1,112 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/memory.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/memory.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
LONG TotalFrees, TotalBytesFreed, TotalAllocations, TotalBytesAllocated;
|
||||
KSPIN_LOCK MemoryLock;
|
||||
PSAC_MEMORY_LIST GlobalMemoryList;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
InitializeMemoryManagement(VOID)
|
||||
{
|
||||
PSAC_MEMORY_ENTRY Entry;
|
||||
PSAC_MEMORY_ENTRY Entry;
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n");
|
||||
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n");
|
||||
/* Allocate a nonpaged heap for us to use */
|
||||
GlobalMemoryList = ExAllocatePoolWithTagPriority(NonPagedPool,
|
||||
SAC_MEMORY_LIST_SIZE,
|
||||
INITIAL_BLOCK_TAG,
|
||||
HighPoolPriority);
|
||||
if (GlobalMemoryList)
|
||||
{
|
||||
/* Initialize a lock for it */
|
||||
KeInitializeSpinLock(&MemoryLock);
|
||||
|
||||
GlobalMemoryList = ExAllocatePoolWithTagPriority(
|
||||
NonPagedPool,
|
||||
SAC_MEMORY_LIST_SIZE,
|
||||
INITIAL_BLOCK_TAG,
|
||||
HighPoolPriority);
|
||||
if (GlobalMemoryList)
|
||||
{
|
||||
KeInitializeSpinLock(&MemoryLock);
|
||||
/* Initialize the head of the list */
|
||||
GlobalMemoryList->Signature = GLOBAL_MEMORY_SIGNATURE;
|
||||
GlobalMemoryList->LocalDescriptor = (PSAC_MEMORY_ENTRY)(GlobalMemoryList + 1);
|
||||
GlobalMemoryList->Size = SAC_MEMORY_LIST_SIZE - sizeof(SAC_MEMORY_LIST);
|
||||
GlobalMemoryList->Next = NULL;
|
||||
|
||||
GlobalMemoryList->Signature = GLOBAL_MEMORY_SIGNATURE;
|
||||
GlobalMemoryList->LocalDescriptor =
|
||||
(PSAC_MEMORY_ENTRY)(GlobalMemoryList + 1);
|
||||
GlobalMemoryList->Size = SAC_MEMORY_LIST_SIZE - sizeof(SAC_MEMORY_LIST);
|
||||
/* Initialize the first free entry */
|
||||
Entry = GlobalMemoryList->LocalDescriptor;
|
||||
Entry->Signature = LOCAL_MEMORY_SIGNATURE;
|
||||
Entry->Tag = FREE_POOL_TAG;
|
||||
Entry->Size = GlobalMemoryList->Size - sizeof(SAC_MEMORY_ENTRY);
|
||||
|
||||
Entry = GlobalMemoryList->LocalDescriptor;
|
||||
Entry->Signature = LOCAL_MEMORY_SIGNATURE;
|
||||
Entry->Tag = FREE_POOL_TAG;
|
||||
Entry->Size = GlobalMemoryList->Size - sizeof(SAC_MEMORY_ENTRY);
|
||||
/* All done */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with TRUE.\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with TRUE.\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with FALSE. No pool.\n");
|
||||
return FALSE;
|
||||
/* No pool available to manage our heap */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with FALSE. No pool.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
FreeMemoryManagement(
|
||||
VOID
|
||||
)
|
||||
NTAPI
|
||||
FreeMemoryManagement(VOID)
|
||||
{
|
||||
PSAC_MEMORY_LIST Next;
|
||||
KIRQL OldIrql;
|
||||
PSAC_MEMORY_LIST Next;
|
||||
KIRQL OldIrql;
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n");
|
||||
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n");
|
||||
/* Acquire the memory lock while freeing the list(s) */
|
||||
KeAcquireSpinLock(&MemoryLock, &OldIrql);
|
||||
while (GlobalMemoryList)
|
||||
{
|
||||
ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE);
|
||||
|
||||
KeAcquireSpinLock(&MemoryLock, &OldIrql);
|
||||
while (GlobalMemoryList)
|
||||
{
|
||||
ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE);
|
||||
/* While outisde of the lock, save the next list and free this one */
|
||||
KeReleaseSpinLock(&MemoryLock, OldIrql);
|
||||
Next = GlobalMemoryList->Next;
|
||||
ExFreePoolWithTag(GlobalMemoryList, 0);
|
||||
|
||||
KeReleaseSpinLock(&MemoryLock, OldIrql);
|
||||
/* Reacquire the lock and see if there was another list to free */
|
||||
KeAcquireSpinLock(&MemoryLock, &OldIrql);
|
||||
GlobalMemoryList = Next;
|
||||
}
|
||||
|
||||
Next = GlobalMemoryList->Next;
|
||||
|
||||
ExFreePoolWithTag(GlobalMemoryList, 0);
|
||||
|
||||
KeAcquireSpinLock(&MemoryLock, &OldIrql);
|
||||
GlobalMemoryList = Next;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&MemoryLock, OldIrql);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting\n");
|
||||
/* All done */
|
||||
KeReleaseSpinLock(&MemoryLock, OldIrql);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting\n");
|
||||
}
|
||||
|
||||
PVOID
|
||||
MyAllocatePool(
|
||||
IN SIZE_T PoolSize,
|
||||
IN ULONG Tag,
|
||||
IN PCHAR File,
|
||||
IN ULONG Line
|
||||
)
|
||||
NTAPI
|
||||
MyAllocatePool(IN SIZE_T PoolSize,
|
||||
IN ULONG Tag,
|
||||
IN PCHAR File,
|
||||
IN ULONG Line)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PSAC_MEMORY_LIST GlobalDescriptor, NewDescriptor;
|
||||
PSAC_MEMORY_ENTRY LocalDescriptor, NextDescriptor;
|
||||
ULONG GlobalSize, ActualSize;
|
||||
PVOID Buffer;
|
||||
KIRQL OldIrql;
|
||||
PSAC_MEMORY_LIST GlobalDescriptor, NewDescriptor;
|
||||
PSAC_MEMORY_ENTRY LocalDescriptor, NextDescriptor;
|
||||
ULONG GlobalSize, ActualSize;
|
||||
PVOID Buffer;
|
||||
ASSERT("Tag != FREE_POOL_TAG");
|
||||
SAC_DBG(SAC_DBG_MM, "Entering.\n");
|
||||
|
||||
ASSERT("Tag != FREE_POOL_TAG");
|
||||
/* Acquire the memory allocation lock and align the size request */
|
||||
KeAcquireSpinLock(&MemoryLock, &OldIrql);;
|
||||
PoolSize = ALIGN_UP(PoolSize, ULONGLONG);
|
||||
|
||||
SAC_DBG(SAC_DBG_MM, "Entering.\n");
|
||||
|
||||
OldIrql = KfAcquireSpinLock(&MemoryLock);
|
||||
PoolSize = ALIGN_UP(PoolSize, ULONGLONG);
|
||||
|
||||
GlobalDescriptor = GlobalMemoryList;
|
||||
#if _USE_SAC_HEAP_ALLOCATOR_
|
||||
GlobalDescriptor = GlobalMemoryList;
|
||||
KeAcquireSpinLock(&MemoryLock, &OldIrql);
|
||||
while (GlobalDescriptor)
|
||||
{
|
||||
|
@ -189,43 +193,60 @@ MyAllocatePool(
|
|||
LocalDescriptor->Size = PoolSize;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Shut the compiler up */
|
||||
NewDescriptor = GlobalDescriptor = NULL;
|
||||
GlobalSize = (ULONG)NewDescriptor;
|
||||
ActualSize = GlobalSize;
|
||||
NextDescriptor = (PVOID)ActualSize;
|
||||
NewDescriptor = (PVOID)NextDescriptor;
|
||||
|
||||
LocalDescriptor->Tag = Tag;
|
||||
KeReleaseSpinLock(&MemoryLock, OldIrql);
|
||||
/* Use the NT pool allocator */
|
||||
LocalDescriptor = ExAllocatePoolWithTag(NonPagedPool,
|
||||
PoolSize + sizeof(*LocalDescriptor),
|
||||
Tag);
|
||||
LocalDescriptor->Size = PoolSize;
|
||||
#endif
|
||||
/* Set the tag, and release the lock */
|
||||
LocalDescriptor->Tag = Tag;
|
||||
KeReleaseSpinLock(&MemoryLock, OldIrql);
|
||||
|
||||
InterlockedIncrement(&TotalAllocations);
|
||||
InterlockedExchangeAdd(&TotalBytesAllocated, LocalDescriptor->Size);
|
||||
SAC_DBG(1, "Returning block 0x%X.\n", LocalDescriptor);
|
||||
/* Update our performance counters */
|
||||
InterlockedIncrement(&TotalAllocations);
|
||||
InterlockedExchangeAdd(&TotalBytesAllocated, LocalDescriptor->Size);
|
||||
|
||||
Buffer = LocalDescriptor + 1;
|
||||
RtlZeroMemory(Buffer, PoolSize);
|
||||
return Buffer;
|
||||
/* Return the buffer and zero it */
|
||||
SAC_DBG(SAC_DBG_MM, "Returning block 0x%X.\n", LocalDescriptor);
|
||||
Buffer = LocalDescriptor + 1;
|
||||
RtlZeroMemory(Buffer, PoolSize);
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
VOID
|
||||
MyFreePool(
|
||||
IN PVOID *Block
|
||||
)
|
||||
NTAPI
|
||||
MyFreePool(IN PVOID *Block)
|
||||
{
|
||||
PSAC_MEMORY_ENTRY LocalDescriptor, NextDescriptor;
|
||||
PSAC_MEMORY_ENTRY ThisDescriptor, FoundDescriptor;
|
||||
ULONG GlobalSize, LocalSize;
|
||||
PSAC_MEMORY_LIST GlobalDescriptor;
|
||||
KIRQL OldIrql;
|
||||
PSAC_MEMORY_ENTRY NextDescriptor;
|
||||
PSAC_MEMORY_ENTRY ThisDescriptor, FoundDescriptor;
|
||||
PSAC_MEMORY_ENTRY LocalDescriptor = (PVOID)((ULONG_PTR)(*Block) - sizeof(SAC_MEMORY_ENTRY));
|
||||
ULONG GlobalSize, LocalSize;
|
||||
PSAC_MEMORY_LIST GlobalDescriptor;
|
||||
KIRQL OldIrql;
|
||||
SAC_DBG(SAC_DBG_MM, "Entering with block 0x%X.\n", LocalDescriptor);
|
||||
|
||||
LocalDescriptor = (PVOID)((ULONG_PTR)(*Block) - sizeof(SAC_MEMORY_ENTRY));
|
||||
/* Make sure this was a valid entry */
|
||||
ASSERT(LocalDescriptor->Size > 0);
|
||||
ASSERT(LocalDescriptor->Signature == LOCAL_MEMORY_SIGNATURE);
|
||||
|
||||
SAC_DBG(SAC_DBG_MM, "Entering with block 0x%X.\n", LocalDescriptor);
|
||||
/* Update performance counters */
|
||||
InterlockedIncrement(&TotalFrees);
|
||||
InterlockedExchangeAdd(&TotalBytesFreed, LocalDescriptor->Size);
|
||||
|
||||
ASSERT(LocalDescriptor->Size > 0);
|
||||
ASSERT(LocalDescriptor->Signature == LOCAL_MEMORY_SIGNATURE);
|
||||
/* Acquire the memory alliocation lock */
|
||||
GlobalDescriptor = GlobalMemoryList;
|
||||
KeAcquireSpinLock(&MemoryLock, &OldIrql);
|
||||
|
||||
InterlockedIncrement(&TotalFrees);
|
||||
|
||||
InterlockedExchangeAdd(&TotalBytesFreed, LocalDescriptor->Size);
|
||||
|
||||
GlobalDescriptor = GlobalMemoryList;
|
||||
KeAcquireSpinLock(&MemoryLock, &OldIrql);
|
||||
#if _USE_SAC_HEAP_ALLOCATOR_
|
||||
while (GlobalDescriptor)
|
||||
{
|
||||
ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE);
|
||||
|
@ -297,10 +318,22 @@ MyFreePool(
|
|||
FoundDescriptor->Size +=
|
||||
(LocalDescriptor->Size + sizeof(SAC_MEMORY_ENTRY));
|
||||
}
|
||||
#else
|
||||
/* Shut the compiler up */
|
||||
LocalSize = GlobalSize = 0;
|
||||
ThisDescriptor = (PVOID)LocalSize;
|
||||
NextDescriptor = (PVOID)GlobalSize;
|
||||
GlobalDescriptor = (PVOID) ThisDescriptor;
|
||||
FoundDescriptor = (PVOID)GlobalDescriptor;
|
||||
GlobalDescriptor = (PVOID) NextDescriptor;
|
||||
NextDescriptor = (PVOID) FoundDescriptor;
|
||||
|
||||
KeReleaseSpinLock(&MemoryLock, OldIrql);
|
||||
*Block = NULL;
|
||||
/* Use the NT pool allocator*/
|
||||
ExFreePool(LocalDescriptor);
|
||||
#endif
|
||||
|
||||
SAC_DBG(SAC_DBG_MM, "exiting.\n");
|
||||
return;
|
||||
/* Release the lock, delete the address, and return */
|
||||
KeReleaseSpinLock(&MemoryLock, OldIrql);
|
||||
*Block = NULL;
|
||||
SAC_DBG(SAC_DBG_MM, "exiting.\n");
|
||||
}
|
||||
|
|
|
@ -1,143 +1,373 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/rawchan.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/rawchan.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
#define SAC_RAW_OBUFFER_SIZE 0x2000
|
||||
#define SAC_RAW_IBUFFER_SIZE 0x2000
|
||||
|
||||
NTSTATUS
|
||||
RawChannelCreate(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
RawChannelCreate(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
CHECK_PARAMETER(Channel);
|
||||
|
||||
Channel->OBuffer = SacAllocatePool(SAC_RAW_OBUFFER_SIZE, GLOBAL_BLOCK_TAG);
|
||||
CHECK_ALLOCATION(Channel->OBuffer);
|
||||
|
||||
Channel->IBuffer = SacAllocatePool(SAC_RAW_IBUFFER_SIZE, GLOBAL_BLOCK_TAG);
|
||||
CHECK_ALLOCATION(Channel->IBuffer);
|
||||
|
||||
Channel->OBufferIndex = 0;
|
||||
Channel->OBufferFirstGoodIndex = 0;
|
||||
Channel->ChannelHasNewIBufferData = FALSE;
|
||||
Channel->ChannelHasNewOBufferData = FALSE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelDestroy(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
RawChannelDestroy(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
CHECK_PARAMETER(Channel);
|
||||
|
||||
if (Channel->OBuffer)
|
||||
{
|
||||
SacFreePool(Channel->OBuffer);
|
||||
}
|
||||
|
||||
if (Channel->IBuffer)
|
||||
{
|
||||
SacFreePool(Channel->IBuffer);
|
||||
}
|
||||
|
||||
return ChannelDestroy(Channel);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
BOOLEAN
|
||||
ChannelHasNewOBufferData(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return Channel->ChannelHasNewOBufferData;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
BOOLEAN
|
||||
ChannelHasNewIBufferData(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return Channel->ChannelHasNewIBufferData;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelORead(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize,
|
||||
OUT PULONG ByteCount
|
||||
)
|
||||
NTAPI
|
||||
RawChannelORead(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize,
|
||||
OUT PULONG ByteCount)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
ULONG NextIndex;
|
||||
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Buffer);
|
||||
CHECK_PARAMETER3(BufferSize > 0);
|
||||
CHECK_PARAMETER4(ByteCount);
|
||||
|
||||
*ByteCount = 0;
|
||||
|
||||
if (ChannelHasNewOBufferData(Channel))
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
Buffer[(*ByteCount)++] = Channel->OBuffer[Channel->OBufferFirstGoodIndex];
|
||||
|
||||
NextIndex = (Channel->OBufferFirstGoodIndex + 1) & (SAC_OBUFFER_SIZE - 1);
|
||||
Channel->OBufferFirstGoodIndex = NextIndex;
|
||||
|
||||
if (NextIndex == Channel->OBufferIndex)
|
||||
{
|
||||
_InterlockedExchange(&Channel->ChannelHasNewOBufferData, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(*ByteCount > 0);
|
||||
|
||||
if (*ByteCount >= BufferSize) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_NO_DATA_DETECTED;
|
||||
}
|
||||
|
||||
if (Channel->OBufferFirstGoodIndex == Channel->OBufferIndex)
|
||||
{
|
||||
ASSERT(ChannelHasNewOBufferData(Channel) == FALSE);
|
||||
}
|
||||
|
||||
if (ChannelHasNewOBufferData(Channel) == FALSE)
|
||||
{
|
||||
ASSERT(Channel->OBufferFirstGoodIndex == Channel->OBufferIndex);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelOEcho(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR String,
|
||||
IN ULONG Length
|
||||
)
|
||||
NTAPI
|
||||
RawChannelOEcho(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR String,
|
||||
IN ULONG Length)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(String);
|
||||
|
||||
if (Length)
|
||||
{
|
||||
Status = ConMgrWriteData(Channel, String, Length);
|
||||
if (NT_SUCCESS(Status)) ConMgrFlushData(Channel);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelOWrite2(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR String,
|
||||
IN ULONG Size
|
||||
)
|
||||
NTAPI
|
||||
RawChannelOWrite2(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR String,
|
||||
IN ULONG Size)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
BOOLEAN Overflow;
|
||||
ULONG i, NextIndex;
|
||||
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(String);
|
||||
|
||||
Overflow = FALSE;
|
||||
|
||||
for (i = 0; i < Size; i++)
|
||||
{
|
||||
if ((Channel->OBufferIndex == Channel->OBufferFirstGoodIndex) &&
|
||||
((i) || (ChannelHasNewOBufferData(Channel))))
|
||||
{
|
||||
Overflow = TRUE;
|
||||
}
|
||||
|
||||
ASSERT(Channel->OBufferIndex < SAC_RAW_OBUFFER_SIZE);
|
||||
|
||||
Channel->OBuffer[Channel->OBufferIndex] = String[i];
|
||||
|
||||
NextIndex = (Channel->OBufferIndex + 1) & (SAC_RAW_OBUFFER_SIZE - 1);
|
||||
Channel->OBufferIndex = NextIndex;
|
||||
|
||||
if (Overflow) Channel->OBufferFirstGoodIndex = NextIndex;
|
||||
}
|
||||
|
||||
_InterlockedExchange(&Channel->ChannelHasNewOBufferData, 1);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelOFlush(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
RawChannelOFlush(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
ULONG ByteCount;
|
||||
CHAR Dummy;
|
||||
CHECK_PARAMETER1(Channel);
|
||||
|
||||
while (ChannelHasNewOBufferData(Channel))
|
||||
{
|
||||
Status = RawChannelORead(Channel, &Dummy, sizeof(Dummy), &ByteCount);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
CHECK_PARAMETER_WITH_STATUS(ByteCount == 1, STATUS_UNSUCCESSFUL);
|
||||
|
||||
Status = ConMgrWriteData(Channel, &Dummy, sizeof(Dummy));
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
return ConMgrFlushData(Channel);
|
||||
}
|
||||
|
||||
ULONG
|
||||
RawChannelGetIBufferIndex(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
RawChannelGetIBufferIndex(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return 0;
|
||||
ASSERT(Channel);
|
||||
ASSERT(Channel->IBufferIndex < SAC_RAW_IBUFFER_SIZE);
|
||||
|
||||
return Channel->IBufferIndex;
|
||||
}
|
||||
|
||||
VOID
|
||||
RawChannelSetIBufferIndex(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN ULONG BufferIndex
|
||||
)
|
||||
NTAPI
|
||||
RawChannelSetIBufferIndex(IN PSAC_CHANNEL Channel,
|
||||
IN ULONG BufferIndex)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ASSERT(Channel);
|
||||
ASSERT(Channel->IBufferIndex < SAC_RAW_IBUFFER_SIZE);
|
||||
|
||||
Channel->IBufferIndex = BufferIndex;
|
||||
Channel->ChannelHasNewIBufferData = BufferIndex != 0;
|
||||
|
||||
if (!Channel->IBufferIndex)
|
||||
{
|
||||
if (Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
|
||||
{
|
||||
ChannelClearEvent(Channel, HasNewDataEvent);
|
||||
UNREFERENCED_PARAMETER(Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelOWrite(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PWCHAR String,
|
||||
IN ULONG Length
|
||||
)
|
||||
NTAPI
|
||||
RawChannelOWrite(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR String,
|
||||
IN ULONG Length)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(String);
|
||||
|
||||
if ((ConMgrIsWriteEnabled(Channel)) && (Channel->WriteEnabled))
|
||||
{
|
||||
return RawChannelOEcho(Channel, String, Length);
|
||||
}
|
||||
|
||||
return RawChannelOWrite2(Channel, String, Length);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelIRead(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize,
|
||||
IN PULONG ReturnBufferSize
|
||||
)
|
||||
NTAPI
|
||||
RawChannelIRead(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize,
|
||||
IN PULONG ReturnBufferSize)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
ULONG CopyChars;
|
||||
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Buffer);
|
||||
CHECK_PARAMETER_WITH_STATUS(BufferSize > 0, STATUS_INVALID_BUFFER_SIZE);
|
||||
|
||||
*ReturnBufferSize = 0;
|
||||
|
||||
if (Channel->ChannelInputBufferLength(Channel) == 0)
|
||||
{
|
||||
ASSERT(ChannelHasNewIBufferData(Channel) == FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyChars = Channel->ChannelInputBufferLength(Channel);
|
||||
if (CopyChars > BufferSize) CopyChars = BufferSize;
|
||||
ASSERT(CopyChars <= Channel->ChannelInputBufferLength(Channel));
|
||||
|
||||
RtlCopyMemory(Buffer, Channel->IBuffer, CopyChars);
|
||||
|
||||
RawChannelSetIBufferIndex(Channel,
|
||||
RawChannelGetIBufferIndex(Channel) - CopyChars);
|
||||
|
||||
if (Channel->ChannelInputBufferLength(Channel))
|
||||
{
|
||||
RtlMoveMemory(Channel->IBuffer,
|
||||
&Channel->IBuffer[CopyChars],
|
||||
Channel->ChannelInputBufferLength(Channel));
|
||||
}
|
||||
|
||||
*ReturnBufferSize = CopyChars;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelIBufferIsFull(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
PBOOLEAN BufferStatus
|
||||
)
|
||||
NTAPI
|
||||
RawChannelIBufferIsFull(IN PSAC_CHANNEL Channel,
|
||||
OUT PBOOLEAN BufferStatus)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(BufferStatus);
|
||||
|
||||
*BufferStatus = RawChannelGetIBufferIndex(Channel) > SAC_RAW_IBUFFER_SIZE;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG
|
||||
RawChannelIBufferLength(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
RawChannelIBufferLength(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return 0;
|
||||
ASSERT(Channel);
|
||||
return RawChannelGetIBufferIndex(Channel);
|
||||
}
|
||||
|
||||
CHAR
|
||||
RawChannelIReadLast(
|
||||
IN PSAC_CHANNEL Channel
|
||||
)
|
||||
NTAPI
|
||||
RawChannelIReadLast(IN PSAC_CHANNEL Channel)
|
||||
{
|
||||
return 0;
|
||||
UCHAR LastChar = 0;
|
||||
|
||||
ASSERT(Channel);
|
||||
|
||||
if (Channel->ChannelInputBufferLength(Channel))
|
||||
{
|
||||
RawChannelSetIBufferIndex(Channel, RawChannelGetIBufferIndex(Channel) - 1);
|
||||
|
||||
LastChar = Channel->IBuffer[RawChannelGetIBufferIndex(Channel)];
|
||||
Channel->IBuffer[RawChannelGetIBufferIndex(Channel)] = 0;
|
||||
}
|
||||
|
||||
return LastChar;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RawChannelIWrite(
|
||||
IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize
|
||||
)
|
||||
NTAPI
|
||||
RawChannelIWrite(IN PSAC_CHANNEL Channel,
|
||||
IN PCHAR Buffer,
|
||||
IN ULONG BufferSize)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN IsFull;
|
||||
ULONG Index;
|
||||
|
||||
CHECK_PARAMETER1(Channel);
|
||||
CHECK_PARAMETER2(Buffer);
|
||||
CHECK_PARAMETER_WITH_STATUS(BufferSize > 0, STATUS_INVALID_BUFFER_SIZE);
|
||||
|
||||
Status = RawChannelIBufferIsFull(Channel, &IsFull);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
if (IsFull) return STATUS_UNSUCCESSFUL;
|
||||
|
||||
Index = RawChannelGetIBufferIndex(Channel);
|
||||
if ((SAC_RAW_IBUFFER_SIZE - Index) >= BufferSize) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
RtlCopyMemory(&Channel->IBuffer[Index], Buffer, BufferSize);
|
||||
|
||||
RawChannelSetIBufferIndex(Channel, BufferSize + Index);
|
||||
|
||||
if (Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
|
||||
{
|
||||
ChannelSetEvent(Channel, HasNewDataEvent);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/base/sac/driver/sacdrv.rc
|
||||
* PURPOSE: Resource File for EMS SAC Driver
|
||||
|
|
|
@ -1,18 +1,759 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/util.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* PROJECT: ReactOS Drivers
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: drivers/sac/driver/util.c
|
||||
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "sacdrv.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
PCHAR Utf8ConversionBuffer;
|
||||
ULONG Utf8ConversionBufferSize;
|
||||
PSAC_MACHINE_INFO MachineInformation;
|
||||
PVOID RequestSacCmdEventObjectBody;
|
||||
PKEVENT RequestSacCmdEventWaitObjectBody;
|
||||
PVOID RequestSacCmdSuccessEventObjectBody;
|
||||
PKEVENT RequestSacCmdSuccessEventWaitObjectBody;
|
||||
PVOID RequestSacCmdFailureEventObjectBody;
|
||||
PKEVENT RequestSacCmdFailureEventWaitObjectBody;
|
||||
PFILE_OBJECT ServiceProcessFileObject;
|
||||
BOOLEAN HaveUserModeServiceCmdEventInfo;
|
||||
|
||||
PSAC_MESSAGE_ENTRY GlobalMessageTable;
|
||||
ULONG GlobalMessageTableCount;
|
||||
|
||||
LONG SerialPortConsumerIndex, SerialPortProducerIndex;
|
||||
PCHAR SerialPortBuffer;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
SacTranslateUnicodeToUtf8(IN PWCHAR SourceBuffer,
|
||||
IN ULONG SourceBufferLength,
|
||||
OUT PCHAR DestinationBuffer,
|
||||
IN ULONG DestinationBufferSize,
|
||||
OUT PULONG UTF8Count,
|
||||
OUT PULONG ProcessedCount)
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PWCHAR
|
||||
NTAPI
|
||||
GetMessage(IN ULONG MessageIndex)
|
||||
{
|
||||
PSAC_MESSAGE_ENTRY MessageEntry;
|
||||
ULONG i;
|
||||
PWCHAR MessageData = NULL;
|
||||
|
||||
/* Loop all cached messages */
|
||||
for (i = 0; i < GlobalMessageTableCount; i++)
|
||||
{
|
||||
/* Check if this one matches the index */
|
||||
MessageEntry = &GlobalMessageTable[i];
|
||||
if (MessageEntry->Index == MessageIndex)
|
||||
{
|
||||
/* It does, return the buffer */
|
||||
MessageData = MessageEntry->Buffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We should always find it */
|
||||
if (!MessageData) ASSERT(FALSE);
|
||||
return MessageData;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UTF8EncodeAndSend(IN PWCHAR String)
|
||||
{
|
||||
ULONG ProcessedCount, Utf8Count, i;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
/* Call the translator routine */
|
||||
if (SacTranslateUnicodeToUtf8(String,
|
||||
wcslen(String),
|
||||
Utf8ConversionBuffer,
|
||||
Utf8ConversionBufferSize,
|
||||
&Utf8Count,
|
||||
&ProcessedCount))
|
||||
{
|
||||
/* Loop every character */
|
||||
for (i = 0; i < Utf8Count; i++)
|
||||
{
|
||||
/* Send it to the terminal */
|
||||
Status = HeadlessDispatch(HeadlessCmdPutData,
|
||||
&Utf8ConversionBuffer[i],
|
||||
sizeof(Utf8ConversionBuffer[i]),
|
||||
NULL,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Conversion failed */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
SacFormatMessage(IN PWCHAR FormattedString,
|
||||
IN PWCHAR MessageString,
|
||||
IN ULONG MessageSize)
|
||||
{
|
||||
/* FIXME: For now don't format anything */
|
||||
wcsncpy(FormattedString, MessageString, MessageSize / sizeof(WCHAR));
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PreloadGlobalMessageTable(IN PVOID ImageBase)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG MessageId, TotalLength, TextSize, i;
|
||||
PWCHAR StringBuffer;
|
||||
PMESSAGE_RESOURCE_ENTRY MessageEntry;
|
||||
PAGED_CODE();
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC PreloadGlobalMessageTable: Entering.\n");
|
||||
|
||||
/* Nothing to do if we already have a table */
|
||||
if (GlobalMessageTable) goto Exit;
|
||||
|
||||
/* Loop through up to 200 messages */
|
||||
for (MessageId = 1; MessageId != SAC_MAX_MESSAGES; MessageId++)
|
||||
{
|
||||
/* Find this message ID in the string table*/
|
||||
Status = RtlFindMessage(ImageBase,
|
||||
11,
|
||||
LANG_NEUTRAL,
|
||||
MessageId,
|
||||
&MessageEntry);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Make sure it's Unicode */
|
||||
ASSERT(MessageEntry->Flags & MESSAGE_RESOURCE_UNICODE);
|
||||
|
||||
/* Remove the space taken up by the OS header, and add our own */
|
||||
TotalLength += MessageEntry->Length -
|
||||
FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text) +
|
||||
sizeof(SAC_MESSAGE_ENTRY);
|
||||
|
||||
/* One more in the table */
|
||||
GlobalMessageTableCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/* We should've found at least one message... */
|
||||
if (!TotalLength)
|
||||
{
|
||||
/* Bail out otherwise */
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC PreloadGlobalMessageTable: No Messages.\n");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Allocate space for the buffers and headers */
|
||||
GlobalMessageTable = SacAllocatePool(TotalLength, GLOBAL_BLOCK_TAG);
|
||||
if (!GlobalMessageTable)
|
||||
{
|
||||
/* Bail out if we couldn't allocate it */
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* All the buffers are going to be at the end of the table */
|
||||
StringBuffer = (PWCHAR)(&GlobalMessageTable[GlobalMessageTableCount]);
|
||||
|
||||
/* Now loop over our entries again */
|
||||
for (i = 0, MessageId = 1; MessageId != SAC_MAX_MESSAGES; MessageId++)
|
||||
{
|
||||
/* Make sure the message is still there...! */
|
||||
Status = RtlFindMessage(ImageBase,
|
||||
11,
|
||||
LANG_NEUTRAL,
|
||||
MessageId,
|
||||
&MessageEntry);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Write the entry in the message table*/
|
||||
GlobalMessageTable[i].Index = MessageId;
|
||||
GlobalMessageTable[i].Buffer = StringBuffer;
|
||||
|
||||
/* The structure includes the size of the header, elide it */
|
||||
TextSize = MessageEntry->Length -
|
||||
FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text);
|
||||
|
||||
/* Format the message into the entry. It should be same or smaller */
|
||||
SacFormatMessage(StringBuffer, (PWCHAR)MessageEntry->Text, TextSize);
|
||||
ASSERT((ULONG)(wcslen(StringBuffer)*sizeof(WCHAR)) <= TextSize);
|
||||
|
||||
/* Move to the next buffer space */
|
||||
StringBuffer += TextSize;
|
||||
|
||||
/* Move to the next entry, make sure the status is full success */
|
||||
i++;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
/* All done, return the status code */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC TearDownGlobalMessageTable: Exiting with status 0x%0x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TearDownGlobalMessageTable(VOID)
|
||||
{
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC TearDownGlobalMessageTable: Entering.\n");
|
||||
|
||||
/* Free the table if one existed */
|
||||
if (GlobalMessageTable) SacFreePool(GlobalMessageTable);
|
||||
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC TearDownGlobalMessageTable: Exiting\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TranslateMachineInformationXML(IN PWCHAR *Buffer,
|
||||
IN PWCHAR ExtraData)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Size;
|
||||
PWCHAR p;
|
||||
CHECK_PARAMETER1(Buffer);
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
Size = wcslen(L"<machine-info>\r\n");
|
||||
|
||||
if (MachineInformation->MachineName)
|
||||
{
|
||||
Size += wcslen(MachineInformation->MachineName);
|
||||
Size += wcslen(L"<name>%s</name>\r\n");
|
||||
}
|
||||
|
||||
if (MachineInformation->MachineGuid)
|
||||
{
|
||||
Size += wcslen(MachineInformation->MachineGuid);
|
||||
Size += wcslen(L"<guid>%s</guid>\r\n");
|
||||
}
|
||||
|
||||
if (MachineInformation->ProcessorArchitecture)
|
||||
{
|
||||
Size += wcslen(MachineInformation->ProcessorArchitecture);
|
||||
Size += wcslen(L"<processor-architecture>%s</processor-architecture>\r\n");
|
||||
}
|
||||
|
||||
if (MachineInformation->MajorVersion)
|
||||
{
|
||||
Size += wcslen(MachineInformation->MajorVersion);
|
||||
Size += wcslen(L"<os-version>%s</os-version>\r\n");
|
||||
}
|
||||
|
||||
if (MachineInformation->BuildNumber)
|
||||
{
|
||||
Size += wcslen(MachineInformation->BuildNumber);
|
||||
Size += wcslen(L"<os-build-number>%s</os-build-number>\r\n");
|
||||
}
|
||||
|
||||
if (MachineInformation->ProductType)
|
||||
{
|
||||
Size += wcslen(MachineInformation->ProductType);
|
||||
Size += wcslen(L"<os-product>%s</os-product>\r\n");
|
||||
}
|
||||
|
||||
if (MachineInformation->ServicePack)
|
||||
{
|
||||
Size += wcslen(MachineInformation->ServicePack);
|
||||
Size += wcslen(L"<os-service-pack>%s</os-service-pack>\r\n");
|
||||
}
|
||||
|
||||
if (ExtraData) Size += wcslen(ExtraData);
|
||||
|
||||
Size += wcslen(L"</machine-info>\r\n");
|
||||
|
||||
p = (PWCHAR)SacAllocatePool((Size + sizeof(ANSI_NULL)) * sizeof(WCHAR), GLOBAL_BLOCK_TAG);
|
||||
|
||||
*Buffer = p;
|
||||
if (!p) return STATUS_NO_MEMORY;
|
||||
|
||||
Size = wcslen(L"<machine-info>\r\n");
|
||||
wcscpy(p, L"<machine-info>\r\n");
|
||||
|
||||
p += Size;
|
||||
|
||||
if (MachineInformation->MachineName)
|
||||
{
|
||||
p += swprintf(p, L"<name>%s</name>\r\n", MachineInformation->MachineName);
|
||||
}
|
||||
|
||||
if (MachineInformation->MachineGuid)
|
||||
{
|
||||
p += swprintf(p, L"<guid>%s</guid>\r\n", MachineInformation->MachineGuid);
|
||||
}
|
||||
|
||||
if (MachineInformation->ProcessorArchitecture)
|
||||
{
|
||||
p += swprintf(p, L"<processor-architecture>%s</processor-architecture>\r\n", MachineInformation->ProcessorArchitecture);
|
||||
}
|
||||
|
||||
if (MachineInformation->MajorVersion)
|
||||
{
|
||||
p += swprintf(p, L"<os-version>%s</os-version>\r\n", MachineInformation->MajorVersion);
|
||||
}
|
||||
|
||||
if (MachineInformation->BuildNumber)
|
||||
{
|
||||
p += swprintf(p, L"<os-build-number>%s</os-build-number>\r\n", MachineInformation->BuildNumber);
|
||||
}
|
||||
|
||||
if (MachineInformation->ProductType)
|
||||
{
|
||||
p += swprintf(p, L"<os-product>%s</os-product>\r\n", MachineInformation->ProductType);
|
||||
}
|
||||
|
||||
if (MachineInformation->ServicePack)
|
||||
{
|
||||
p += swprintf(p, L"<os-service-pack>%s</os-service-pack>\r\n", MachineInformation->ServicePack);
|
||||
}
|
||||
|
||||
if (ExtraData)
|
||||
{
|
||||
Size = wcslen(ExtraData);
|
||||
wcscpy(p, ExtraData);
|
||||
p += Size;
|
||||
}
|
||||
|
||||
wcscpy(p, L"</machine-info>\r\n");
|
||||
ASSERT((((ULONG) wcslen(*Buffer) + 1) * sizeof(WCHAR)) <= Size);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
InitializeMachineInformation(VOID)
|
||||
{
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC Initialize Machine Information : Entering.\n");
|
||||
|
||||
/* FIXME: TODO */
|
||||
MachineInformation = NULL;
|
||||
ASSERT(FALSE);
|
||||
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC Initialize Machine Information : Exiting with error.\n");
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
GetRegistryValueBuffer(IN PCWSTR KeyName,
|
||||
IN PWCHAR ValueName,
|
||||
IN PKEY_VALUE_PARTIAL_INFORMATION* Buffer)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING DestinationString;
|
||||
HANDLE Handle;
|
||||
SIZE_T ResultLength = 0;
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: Entering.\n");
|
||||
CHECK_PARAMETER1(KeyName);
|
||||
CHECK_PARAMETER2(ValueName);
|
||||
|
||||
/* Open the specified key */
|
||||
RtlInitUnicodeString(&DestinationString, KeyName);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DestinationString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenKey(&Handle,
|
||||
KEY_WRITE | SYNCHRONIZE | KEY_READ,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Bail out on failure */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: failed ZwOpenKey: %X.\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Query the size of the key */
|
||||
RtlInitUnicodeString(&DestinationString, ValueName);
|
||||
Status = ZwQueryValueKey(Handle,
|
||||
&DestinationString,
|
||||
KeyValuePartialInformation,
|
||||
NULL,
|
||||
0,
|
||||
&ResultLength);
|
||||
if (!ResultLength) return Status;
|
||||
|
||||
/* Allocate the buffer for the partial info structure and our integer data */
|
||||
ResultLength += sizeof(ULONG);
|
||||
*Buffer = SacAllocatePool(ResultLength, GLOBAL_BLOCK_TAG);
|
||||
if (!*Buffer)
|
||||
{
|
||||
SAC_DBG(1, "SAC GetRegistryValueBuffer: failed allocation\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Now read the data */
|
||||
Status = ZwQueryValueKey(Handle,
|
||||
&DestinationString,
|
||||
KeyValuePartialInformation,
|
||||
*Buffer,
|
||||
ResultLength,
|
||||
&ResultLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Free the buffer if we couldn't read the data */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: failed ZwQueryValueKey: %X.\n", Status);
|
||||
SacFreePool(*Buffer);
|
||||
}
|
||||
|
||||
/* Return the result */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: Exiting.\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SetRegistryValue(IN PCWSTR KeyName,
|
||||
IN PWCHAR ValueName,
|
||||
IN ULONG Type,
|
||||
IN PVOID Data,
|
||||
IN ULONG DataSize)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING DestinationString;
|
||||
HANDLE Handle;
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: Entering.\n");
|
||||
CHECK_PARAMETER1(KeyName);
|
||||
CHECK_PARAMETER2(ValueName);
|
||||
CHECK_PARAMETER4(Data);
|
||||
|
||||
/* Open the specified key */
|
||||
RtlInitUnicodeString(&DestinationString, KeyName);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DestinationString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenKey(&Handle,
|
||||
KEY_WRITE | SYNCHRONIZE | KEY_READ,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Bail out on failure */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: failed ZwOpenKey: %X.\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set the specified value */
|
||||
RtlInitUnicodeString(&DestinationString, ValueName);
|
||||
Status = ZwSetValueKey(Handle, &DestinationString, 0, Type, Data, DataSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Print error on failure */
|
||||
SAC_DBG(1, "SAC SetRegistryValue: failed ZwSetValueKey: %X.\n", Status);
|
||||
}
|
||||
|
||||
/* Close the handle and exit */
|
||||
NtClose(Handle);
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: Exiting.\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CopyRegistryValueData(IN PULONG* Buffer,
|
||||
IN PKEY_VALUE_PARTIAL_INFORMATION PartialInfo)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
CHECK_PARAMETER1(Buffer);
|
||||
CHECK_PARAMETER2(PartialInfo);
|
||||
|
||||
/* Allocate space for registry data */
|
||||
*Buffer = SacAllocatePool(PartialInfo->DataLength, GLOBAL_BLOCK_TAG);
|
||||
if (*Buffer)
|
||||
{
|
||||
/* Copy the data into the buffer */
|
||||
RtlCopyMemory(*Buffer, PartialInfo->Data, PartialInfo->DataLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the correct error code */
|
||||
SAC_DBG(SAC_DBG_UTIL, "SAC CopyRegistryValueBuffer: Failed ALLOCATE.\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Return the result */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
GetCommandConsoleLaunchingPermission(OUT PBOOLEAN Permission)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION Dummy;
|
||||
|
||||
/* Assume success and read the key */
|
||||
*Permission = TRUE;
|
||||
Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\sacdrv",
|
||||
L"DisableCmdSessions",
|
||||
&Dummy);
|
||||
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||
{
|
||||
/* The default is success */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only if the key is present and set, do we disable permission */
|
||||
if (NT_SUCCESS(Status)) *Permission = FALSE;
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ImposeSacCmdServiceStartTypePolicy(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION Buffer = NULL;
|
||||
PULONG Data;
|
||||
|
||||
/* Read the service start type*/
|
||||
Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\sacsvr",
|
||||
L"Start",
|
||||
&Buffer);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* If there's no start type, fail, as this is unusual */
|
||||
if (!Buffer) return STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* Read the value */
|
||||
Status = CopyRegistryValueData(&Data, Buffer);
|
||||
SacFreePool(Buffer);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Check what the current start type is */
|
||||
switch (*Data)
|
||||
{
|
||||
/* It's boot, system, or disabled */
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
/* Leave it as is */
|
||||
return Status;
|
||||
|
||||
case 3:
|
||||
|
||||
/* It's set to automatic, set it to system instead */
|
||||
*Data = 2;
|
||||
Status = SetRegistryValue(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\sacsvr",
|
||||
L"Start",
|
||||
REG_DWORD,
|
||||
Data,
|
||||
sizeof(ULONG));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC ImposeSacCmdServiceStartTypePolicy: Failed SetRegistryValue: %X\n", Status);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
InitializeCmdEventInfo(VOID)
|
||||
{
|
||||
/* Check if we were already initailized */
|
||||
if (HaveUserModeServiceCmdEventInfo)
|
||||
{
|
||||
/* Full state expected */
|
||||
ASSERT(RequestSacCmdEventObjectBody);
|
||||
ASSERT(RequestSacCmdSuccessEventObjectBody);
|
||||
ASSERT(RequestSacCmdFailureEventObjectBody);
|
||||
|
||||
/* Dereference each wait object in turn */
|
||||
if (RequestSacCmdEventObjectBody)
|
||||
{
|
||||
ObDereferenceObject(RequestSacCmdEventObjectBody);
|
||||
}
|
||||
|
||||
if (RequestSacCmdSuccessEventObjectBody)
|
||||
{
|
||||
ObDereferenceObject(RequestSacCmdSuccessEventObjectBody);
|
||||
}
|
||||
|
||||
if (RequestSacCmdFailureEventObjectBody)
|
||||
{
|
||||
ObDereferenceObject(RequestSacCmdFailureEventObjectBody);
|
||||
}
|
||||
}
|
||||
|
||||
/* Claer everything */
|
||||
RequestSacCmdEventObjectBody = NULL;
|
||||
RequestSacCmdEventWaitObjectBody = NULL;
|
||||
RequestSacCmdSuccessEventObjectBody = NULL;
|
||||
RequestSacCmdSuccessEventWaitObjectBody = NULL;
|
||||
RequestSacCmdFailureEventObjectBody = NULL;
|
||||
RequestSacCmdFailureEventWaitObjectBody = NULL;
|
||||
ServiceProcessFileObject = NULL;
|
||||
|
||||
/* Reset state */
|
||||
HaveUserModeServiceCmdEventInfo = FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RegisterBlueScreenMachineInformation(VOID)
|
||||
{
|
||||
PWCHAR XmlBuffer;
|
||||
PHEADLESS_BLUE_SCREEN_DATA BsBuffer;
|
||||
ULONG Length, HeaderLength, TotalLength;
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
|
||||
/* Create the XML buffer and make sure it's OK */
|
||||
Status = TranslateMachineInformationXML(&XmlBuffer, NULL);
|
||||
CHECK_PARAMETER_WITH_STATUS(NT_SUCCESS(Status), Status);
|
||||
CHECK_PARAMETER_WITH_STATUS(XmlBuffer, STATUS_UNSUCCESSFUL);
|
||||
|
||||
/* Compute the sizes and allocate a buffer for it */
|
||||
Length = wcslen(XmlBuffer);
|
||||
HeaderLength = strlen("MACHINEINFO");
|
||||
TotalLength = HeaderLength +
|
||||
Length +
|
||||
sizeof(*BsBuffer) +
|
||||
2 * sizeof(ANSI_NULL);
|
||||
BsBuffer = SacAllocatePool(TotalLength, GLOBAL_BLOCK_TAG);
|
||||
CHECK_PARAMETER_WITH_STATUS(BsBuffer, STATUS_NO_MEMORY);
|
||||
|
||||
/* Copy the XML property name */
|
||||
strcpy((PCHAR)BsBuffer->XMLData, "MACHINEINFO");
|
||||
BsBuffer->Property = (PUCHAR)HeaderLength + sizeof(ANSI_NULL);
|
||||
|
||||
/* Copy the data and NULL-terminate it */
|
||||
for (i = 0; i < Length; i++)
|
||||
{
|
||||
BsBuffer->XMLData[HeaderLength + sizeof(ANSI_NULL) + i] = XmlBuffer[i];
|
||||
}
|
||||
BsBuffer->XMLData[HeaderLength + sizeof(ANSI_NULL) + i] = ANSI_NULL;
|
||||
|
||||
/* Let the OS save the buffer for later */
|
||||
Status = HeadlessDispatch(HeadlessCmdSetBlueScreenData,
|
||||
BsBuffer,
|
||||
TotalLength,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Failure or not, we don't need this anymore */
|
||||
SacFreePool(BsBuffer);
|
||||
SacFreePool(XmlBuffer);
|
||||
|
||||
/* Return the result */
|
||||
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC Initialize Machine Information: Exiting.\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
FreeMachineInformation(VOID)
|
||||
{
|
||||
ASSERT(MachineInformation);
|
||||
|
||||
/* Free every cached string of machine information */
|
||||
if (MachineInformation->MachineName) SacFreePool(MachineInformation);
|
||||
if (MachineInformation->MachineGuid) SacFreePool(MachineInformation->MachineGuid);
|
||||
if (MachineInformation->ProcessorArchitecture) SacFreePool(MachineInformation->ProcessorArchitecture);
|
||||
if (MachineInformation->MajorVersion) SacFreePool(MachineInformation->MajorVersion);
|
||||
if (MachineInformation->BuildNumber) SacFreePool(MachineInformation->BuildNumber);
|
||||
if (MachineInformation->ProductType) SacFreePool(MachineInformation->ProductType);
|
||||
if (MachineInformation->ServicePack) SacFreePool(MachineInformation->ServicePack);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
VerifyEventWaitable(IN HANDLE Handle,
|
||||
OUT PVOID *WaitObject,
|
||||
OUT PVOID *ActualWaitObject)
|
||||
{
|
||||
PVOID Object;
|
||||
NTSTATUS Status;
|
||||
POBJECT_TYPE ObjectType;
|
||||
|
||||
/* Reference the object */
|
||||
Status = ObReferenceObjectByHandle(Handle,
|
||||
EVENT_ALL_ACCESS,
|
||||
NULL,
|
||||
KernelMode,
|
||||
&Object,
|
||||
NULL);
|
||||
*WaitObject = Object;
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC VerifyEventWaitable: Unable to reference event object (%lx)\n", Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check if the object itself is NOT being used */
|
||||
ObjectType = OBJECT_TO_OBJECT_HEADER(Object)->Type;
|
||||
if (ObjectType->TypeInfo.UseDefaultObject == FALSE)
|
||||
{
|
||||
/* Get the actual object that's being used for the wait */
|
||||
*ActualWaitObject = (PVOID)((ULONG_PTR)Object +
|
||||
(ULONG_PTR)ObjectType->DefaultObject);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Drop the reference we took */
|
||||
SAC_DBG(SAC_DBG_INIT, "SAC VerifyEventWaitable: event object not waitable!\n");
|
||||
ObDereferenceObject(*WaitObject);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SerialBufferGetChar(OUT PCHAR Char)
|
||||
{
|
||||
/* Check if nothing's been produced yet */
|
||||
if (SerialPortConsumerIndex == SerialPortProducerIndex)
|
||||
{
|
||||
return STATUS_NO_DATA_DETECTED;
|
||||
}
|
||||
|
||||
/* Consume the produced character and clear it*/
|
||||
*Char = SerialPortBuffer[SerialPortConsumerIndex];
|
||||
SerialPortBuffer[SerialPortConsumerIndex] = ANSI_NULL;
|
||||
|
||||
/* Advance the index and return success */
|
||||
_InterlockedExchange(&SerialPortConsumerIndex,
|
||||
(SerialPortConsumerIndex + 1) &
|
||||
(SAC_SERIAL_PORT_BUFFER_SIZE - 1));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ConvertAnsiToUnicode(
|
||||
|
@ -32,24 +773,6 @@ IsCmdEventRegistrationProcess(
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
InitializeCmdEventInfo(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
VerifyEventWaitable(
|
||||
IN PVOID Object,
|
||||
OUT PVOID *WaitObject,
|
||||
OUT PVOID *ActualWaitObject
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
InvokeUserModeService(
|
||||
VOID
|
||||
|
@ -58,32 +781,6 @@ InvokeUserModeService(
|
|||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
SacFormatMessage(
|
||||
IN PWCHAR FormattedString,
|
||||
IN PWCHAR MessageString,
|
||||
IN ULONG MessageSize
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
TearDownGlobalMessageTable(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PWCHAR
|
||||
GetMessage(
|
||||
IN ULONG MessageIndex
|
||||
)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SacTranslateUtf8ToUnicode(
|
||||
IN CHAR Utf8Char,
|
||||
|
@ -94,50 +791,6 @@ SacTranslateUtf8ToUnicode(
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SacTranslateUnicodeToUtf8(
|
||||
IN PWCHAR SourceBuffer,
|
||||
IN ULONG SourceBufferLength,
|
||||
OUT PCHAR DestinationBuffer,
|
||||
IN ULONG DestinationBufferSize,
|
||||
IN ULONG UTF8Count,
|
||||
OUT PULONG ProcessedCount
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetRegistryValueBuffer(
|
||||
IN PCWSTR KeyName,
|
||||
IN PWCHAR ValueName,
|
||||
IN PKEY_VALUE_PARTIAL_INFORMATION ValueBuffer
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
SetRegistryValue(
|
||||
IN PCWSTR KeyName,
|
||||
IN PWCHAR ValueName,
|
||||
IN ULONG Type,
|
||||
IN PVOID Data,
|
||||
IN ULONG DataSize
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CopyRegistryValueData(
|
||||
IN PVOID Dest,
|
||||
IN PKEY_VALUE_PARTIAL_INFORMATION ValueBuffer
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
TranslateMachineInformationText(
|
||||
IN PWCHAR Buffer)
|
||||
|
@ -145,55 +798,6 @@ TranslateMachineInformationText(
|
|||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
TranslateMachineInformationXML(
|
||||
IN PWCHAR Buffer,
|
||||
IN PWCHAR ExtraData
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
RegisterBlueScreenMachineInformation(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
FreeMachineInformation(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
SerialBufferGetChar(
|
||||
OUT PCHAR Char
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetCommandConsoleLaunchingPermission(
|
||||
OUT PBOOLEAN Permission
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ImposeSacCmdServiceStartTypePolicy(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CopyAndInsertStringAtInterval(
|
||||
IN PWCHAR SourceStr,
|
||||
|
@ -229,11 +833,3 @@ UnregisterSacCmdEvent(
|
|||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
UTF8EncodeAndSend(
|
||||
IN PWCHAR String
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ list(APPEND UNICODE_SOURCE
|
|||
neteventmsg.mc
|
||||
ntiologc.mc
|
||||
ntstatus.mc
|
||||
pciclass.mc)
|
||||
pciclass.mc
|
||||
sacmsg.mc)
|
||||
|
||||
add_message_headers(ANSI ${ANSI_SOURCE})
|
||||
# FIXME: this needs testing before switching to unicode
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
MessageId=1
|
||||
SymbolicName=SACDRV_1
|
||||
SymbolicName=SAC_INIT_STATUS
|
||||
Language=English
|
||||
Computer is booting, SAC started and initialized.\n\nUse the \"ch -?\" command for information about using channels.\nUse the \"?\" command for general help.
|
||||
.
|
||||
|
||||
MessageId=2
|
||||
SymbolicName=SACDRV_2
|
||||
SymbolicName=SAC_NEWLINE
|
||||
Language=English
|
||||
|
||||
.
|
||||
|
||||
MessageId=3
|
||||
SymbolicName=SACDRV_3
|
||||
SymbolicName=SAC_PROMPT
|
||||
Language=English
|
||||
SAC>%0
|
||||
.
|
||||
|
@ -59,9 +59,9 @@ Paging is now OFF.
|
|||
.
|
||||
|
||||
MessageId=11
|
||||
SymbolicName=SACDRV_11
|
||||
SymbolicName=SAC_OUT_OF_MEMORY_PROMPT
|
||||
Language=English
|
||||
Paging is now OFF.
|
||||
THIS LOOKS LIKE A BUG???
|
||||
.
|
||||
|
||||
MessageId=12
|
||||
|
@ -173,7 +173,7 @@ lock Lock access to Command Prompt channels.
|
|||
.
|
||||
|
||||
MessageId=48
|
||||
SymbolicName=SACDRV_48
|
||||
SymbolicName=SAC_FAIL_PROMPT
|
||||
Language=English
|
||||
Failed with status 0x%%X.
|
||||
.
|
||||
|
@ -269,13 +269,13 @@ SAC cannot raise the process priority any higher.
|
|||
.
|
||||
|
||||
MessageId=65
|
||||
SymbolicName=SACDRV_65
|
||||
SymbolicName=SAC_SHUTDOWN_FAIL_PROMPT
|
||||
Language=English
|
||||
SAC failed to shutdown the system.
|
||||
.
|
||||
|
||||
MessageId=66
|
||||
SymbolicName=SACDRV_66
|
||||
SymbolicName=SAC_RESTART_FAIL_PROMPT
|
||||
Language=English
|
||||
SAC failed to restart the system.
|
||||
.
|
||||
|
@ -551,19 +551,19 @@ ch Channel management commands. Use ch -? for more help.
|
|||
.
|
||||
|
||||
MessageId=113
|
||||
SymbolicName=SACDRV_113
|
||||
SymbolicName=SAC_RESTART_TIME_PROMPT
|
||||
Language=English
|
||||
Time since last reboot: %%d:%%02d:%%02d
|
||||
.
|
||||
|
||||
MessageId=114
|
||||
SymbolicName=SACDRV_114
|
||||
SymbolicName=SAC_RESTART_PROMPT
|
||||
Language=English
|
||||
SAC preparing to restart the system.
|
||||
.
|
||||
|
||||
MessageId=115
|
||||
SymbolicName=SACDRV_115
|
||||
SymbolicName=SAC_SHUTDOWN_PROMPT
|
||||
Language=English
|
||||
SAC preparing to shutdown the system.
|
||||
.
|
||||
|
@ -641,13 +641,13 @@ Error: There is no channel present at the specified index.
|
|||
.
|
||||
|
||||
MessageId=144
|
||||
SymbolicName=SACDRV_144
|
||||
SymbolicName=SAC_CHANNEL_NAME
|
||||
Language=English
|
||||
SAC%0
|
||||
.
|
||||
|
||||
MessageId=145
|
||||
SymbolicName=SACDRV_145
|
||||
SymbolicName=SAC_CHANNEL_DESCRIPTION
|
||||
Language=English
|
||||
Special Administration Console%0
|
||||
.
|
||||
|
|
Loading…
Reference in a new issue