[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:
Alex Ionescu 2013-08-06 01:12:08 +00:00
parent f9c1de4baa
commit 6568f7df16
19 changed files with 4468 additions and 1314 deletions

View file

@ -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"

View file

@ -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

View file

@ -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)

View file

@ -0,0 +1,2 @@
add_subdirectory(driver)

View 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)

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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");
}

View file

@ -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;
}

View file

@ -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");
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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
.