[NTOSKRNL]: Add and fix more glue code for EMS/Headless support. The SAC driver is at least correctly able to initialize now when /redirect is enabled.

[SACMSG]: SAC wants the message tables as Unicode, but the CMakeList has an obscure comment that Unicode MC needs "testing". Well, I'll be the first to test it and confirm it works -- implement a UNICODE_SOURCE_REALLY to get Unicode-mc.
[SACMSG]: Add a few more constants.
[SACDRV]: Implement InitializeMachineInformation.
[SACDRV]: Fix countless bugs. Now the entire driver initializes up to UTF8EncodeAndSend, which is unimplemented. We're almost there!

svn path=/trunk/; revision=59718
This commit is contained in:
Alex Ionescu 2013-08-13 03:18:03 +00:00
parent 1f8570be62
commit 7e5cd96267
8 changed files with 777 additions and 331 deletions

View file

@ -77,6 +77,8 @@ CreateDeviceSecurityDescriptor(IN PDEVICE_OBJECT *DeviceObject)
else
{
SAC_DBG(SAC_DBG_INIT, "SAC CreateDeviceSecurityDescriptor : Unable to create Raw ACL, error : %x\n", Status);
/* FIXME: Temporary hack */
Status = STATUS_SUCCESS;
goto CleanupPath;
}
@ -377,7 +379,7 @@ InitializeGlobalData(IN PUNICODE_STRING RegistryPath,
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n");
/* If we already did this, bail out */
if (!GlobalDataInitialized) goto SuccessExit;
if (GlobalDataInitialized) goto SuccessExit;
/* Setup the symbolic link for Win32 support */
RtlInitUnicodeString(&LinkName, L"\\DosDevices\\SAC");

View file

@ -93,6 +93,11 @@ MyAllocatePool(IN SIZE_T PoolSize,
IN PCHAR File,
IN ULONG Line)
{
PVOID p;
p = ExAllocatePoolWithTag(NonPagedPool, PoolSize, Tag);
SAC_DBG(SAC_DBG_MM, "Returning block 0x%X.\n", p);
return p;
#if 0
KIRQL OldIrql;
PSAC_MEMORY_LIST GlobalDescriptor, NewDescriptor;
PSAC_MEMORY_ENTRY LocalDescriptor, NextDescriptor;
@ -102,7 +107,7 @@ MyAllocatePool(IN SIZE_T PoolSize,
SAC_DBG(SAC_DBG_MM, "Entering.\n");
/* Acquire the memory allocation lock and align the size request */
KeAcquireSpinLock(&MemoryLock, &OldIrql);;
KeAcquireSpinLock(&MemoryLock, &OldIrql);
PoolSize = ALIGN_UP(PoolSize, ULONGLONG);
#if _USE_SAC_HEAP_ALLOCATOR_
@ -220,12 +225,14 @@ MyAllocatePool(IN SIZE_T PoolSize,
Buffer = LocalDescriptor + 1;
RtlZeroMemory(Buffer, PoolSize);
return Buffer;
#endif
}
VOID
NTAPI
MyFreePool(IN PVOID *Block)
{
#if 0
PSAC_MEMORY_ENTRY NextDescriptor;
PSAC_MEMORY_ENTRY ThisDescriptor, FoundDescriptor;
PSAC_MEMORY_ENTRY LocalDescriptor = (PVOID)((ULONG_PTR)(*Block) - sizeof(SAC_MEMORY_ENTRY));
@ -323,10 +330,10 @@ MyFreePool(IN PVOID *Block)
LocalSize = GlobalSize = 0;
ThisDescriptor = (PVOID)LocalSize;
NextDescriptor = (PVOID)GlobalSize;
GlobalDescriptor = (PVOID) ThisDescriptor;
GlobalDescriptor = (PVOID)ThisDescriptor;
FoundDescriptor = (PVOID)GlobalDescriptor;
GlobalDescriptor = (PVOID) NextDescriptor;
NextDescriptor = (PVOID) FoundDescriptor;
GlobalDescriptor = (PVOID)NextDescriptor;
NextDescriptor = (PVOID)FoundDescriptor;
/* Use the NT pool allocator*/
ExFreePool(LocalDescriptor);
@ -334,6 +341,8 @@ MyFreePool(IN PVOID *Block)
/* Release the lock, delete the address, and return */
KeReleaseSpinLock(&MemoryLock, OldIrql);
#endif
ExFreePool(*Block);
*Block = NULL;
SAC_DBG(SAC_DBG_MM, "exiting.\n");
}

View file

@ -35,6 +35,7 @@
#define SAC_DBG_UTIL 0x02
#define SAC_DBG_INIT 0x04
#define SAC_DBG_MM 0x1000
#define SAC_DBG_MACHINE 0x2000
#define SAC_DBG(x, ...) \
if (SACDebug & x) \
{ \

View file

@ -13,7 +13,7 @@
/* GLOBALS *******************************************************************/
PCHAR Utf8ConversionBuffer;
ULONG Utf8ConversionBufferSize;
ULONG Utf8ConversionBufferSize = PAGE_SIZE;
PSAC_MACHINE_INFO MachineInformation;
PVOID RequestSacCmdEventObjectBody;
PKEVENT RequestSacCmdEventWaitObjectBody;
@ -122,7 +122,7 @@ NTSTATUS
NTAPI
PreloadGlobalMessageTable(IN PVOID ImageBase)
{
NTSTATUS Status;
NTSTATUS Status, Status2;
ULONG MessageId, TotalLength, TextSize, i;
PWCHAR StringBuffer;
PMESSAGE_RESOURCE_ENTRY MessageEntry;
@ -130,6 +130,7 @@ PreloadGlobalMessageTable(IN PVOID ImageBase)
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC PreloadGlobalMessageTable: Entering.\n");
/* Nothing to do if we already have a table */
Status = STATUS_SUCCESS;
if (GlobalMessageTable) goto Exit;
/* Loop through up to 200 messages */
@ -137,12 +138,12 @@ PreloadGlobalMessageTable(IN PVOID ImageBase)
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))
Status2 = RtlFindMessage(ImageBase,
11,
LANG_NEUTRAL,
MessageId,
&MessageEntry);
if (NT_SUCCESS(Status2))
{
/* Make sure it's Unicode */
ASSERT(MessageEntry->Flags & MESSAGE_RESOURCE_UNICODE);
@ -182,12 +183,12 @@ PreloadGlobalMessageTable(IN PVOID ImageBase)
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))
Status2 = RtlFindMessage(ImageBase,
11,
LANG_NEUTRAL,
MessageId,
&MessageEntry);
if (NT_SUCCESS(Status2))
{
/* Write the entry in the message table*/
GlobalMessageTable[i].Index = MessageId;
@ -202,7 +203,7 @@ PreloadGlobalMessageTable(IN PVOID ImageBase)
ASSERT((ULONG)(wcslen(StringBuffer)*sizeof(WCHAR)) <= TextSize);
/* Move to the next buffer space */
StringBuffer += TextSize;
StringBuffer += (TextSize / sizeof(WCHAR));
/* Move to the next entry, make sure the status is full success */
i++;
@ -229,135 +230,6 @@ TearDownGlobalMessageTable(VOID)
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,
@ -479,7 +351,7 @@ SetRegistryValue(IN PCWSTR KeyName,
NTSTATUS
NTAPI
CopyRegistryValueData(IN PULONG* Buffer,
CopyRegistryValueData(IN PVOID* Buffer,
IN PKEY_VALUE_PARTIAL_INFORMATION PartialInfo)
{
NTSTATUS Status = STATUS_SUCCESS;
@ -504,6 +376,446 @@ CopyRegistryValueData(IN PULONG* Buffer,
return Status;
}
NTSTATUS
NTAPI
TranslateMachineInformationXML(IN PWCHAR *Buffer,
IN PWCHAR ExtraData)
{
NTSTATUS Status;
ULONG Size;
PWCHAR p;
CHECK_PARAMETER1(Buffer);
/* Start by believing the world is beautiful */
Status = STATUS_SUCCESS;
/* First, the header */
Size = wcslen(L"<machine-info>\r\n");
/* Do we have a machine name? */
if (MachineInformation->MachineName)
{
/* Go and add it in */
Size += wcslen(MachineInformation->MachineName);
Size += wcslen(L"<name>%s</name>\r\n");
}
/* Do we have a GUID? */
if (MachineInformation->MachineGuid)
{
/* Go and add it in */
Size += wcslen(MachineInformation->MachineGuid);
Size += wcslen(L"<guid>%s</guid>\r\n");
}
/* Do we know the processor? */
if (MachineInformation->ProcessorArchitecture)
{
/* Go and add it in */
Size += wcslen(MachineInformation->ProcessorArchitecture);
Size += wcslen(L"<processor-architecture>%s</processor-architecture>\r\n");
}
/* Do we have the version? */
if (MachineInformation->MajorVersion)
{
/* Go and add it in */
Size += wcslen(MachineInformation->MajorVersion);
Size += wcslen(L"<os-version>%s</os-version>\r\n");
}
/* Do we have the build? */
if (MachineInformation->BuildNumber)
{
/* Go and add it in */
Size += wcslen(MachineInformation->BuildNumber);
Size += wcslen(L"<os-build-number>%s</os-build-number>\r\n");
}
/* Do we have the product type? */
if (MachineInformation->ProductType)
{
/* Go and add it in */
Size += wcslen(MachineInformation->ProductType);
Size += wcslen(L"<os-product>%s</os-product>\r\n");
}
/* Do we have a service pack? */
if (MachineInformation->ServicePack)
{
/* Go and add it in */
Size += wcslen(MachineInformation->ServicePack);
Size += wcslen(L"<os-service-pack>%s</os-service-pack>\r\n");
}
/* Anything else we need to know? Add it in too */
if (ExtraData) Size += wcslen(ExtraData);
/* Finally, add the footer */
Size += wcslen(L"</machine-info>\r\n");
/* Convert to bytes and add a NULL */
Size += sizeof(ANSI_NULL);
Size *= sizeof(WCHAR);
/* Allocate space for the buffer */
p = SacAllocatePool(Size, GLOBAL_BLOCK_TAG);
*Buffer = p;
if (!p) return STATUS_NO_MEMORY;
wcscpy(p, L"<machine-info>\r\n");
p += wcslen(L"<machine-info>\r\n");;
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)
{
wcscpy(p, ExtraData);
p += wcslen(ExtraData);
}
wcscpy(p, L"</machine-info>\r\n");
SAC_DBG(SAC_DBG_ENTRY_EXIT, "MachineInformation: %S\n", *Buffer);
ASSERT((((ULONG)wcslen(*Buffer) + 1) * sizeof(WCHAR)) <= Size);
return Status;
}
VOID
NTAPI
InitializeMachineInformation(VOID)
{
NTSTATUS Status;
PWCHAR GuidString, MajorVersion, ServicePack, BuildNumber, MessageBuffer;
PWCHAR ProductType;
ULONG SuiteTypeMessage;
BOOLEAN SetupInProgress = FALSE;
GUID SystemGuid;
ULONG RealSize, Size, OutputSize;
PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
RTL_OSVERSIONINFOEXW VersionInformation;
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC Initialize Machine Information : Entering.\n");
/* Don't do anything if we already quried this */
if (MachineInformation)
{
SAC_DBG(SAC_DBG_MACHINE, "SAC Initialize Machine Information:: MachineInformationBuffer already initialzied.\n");
return;
}
/* Allocate the machine information */
MachineInformation = SacAllocatePool(sizeof(*MachineInformation),
GLOBAL_BLOCK_TAG);
if (!MachineInformation)
{
goto Fail;
}
/* Zero it out for now */
RtlZeroMemory(MachineInformation, sizeof(*MachineInformation));
/* Query OS version */
RtlZeroMemory(&VersionInformation, sizeof(VersionInformation));
VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
Status = RtlGetVersion((PRTL_OSVERSIONINFOW)&VersionInformation);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (2).\n");
goto Fail;
}
/* Check if setup is in progress */
Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\Setup",
L"SystemSetupInProgress",
&PartialInfo);
if (NT_SUCCESS(Status))
{
/* The key is there, is the value set? */
if (*(PULONG)PartialInfo->Data) SetupInProgress = TRUE;
SacFreePool(PartialInfo);
if (SetupInProgress)
{
/* Yes, so we'll use a special hostname to identify this */
MessageBuffer = GetMessage(SAC_UNINITIALIZED_MSG);
Size = wcslen(MessageBuffer);
ASSERT(Size > 0);
RealSize = Size * sizeof(WCHAR) + sizeof(UNICODE_NULL);
/* Make room for it and copy it in there */
MachineInformation->MachineName = SacAllocatePool(RealSize,
GLOBAL_BLOCK_TAG);
if (MachineInformation->MachineName)
{
wcscpy(MachineInformation->MachineName, MessageBuffer);
}
}
}
/* If we are not in setup mode, or if we failed to check... */
if (!SetupInProgress)
{
/* Query the computer name */
Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\"
L"CurrentControlSet\\Control\\"
L"ComputerName\\ComputerName",
L"ComputerName",
&PartialInfo);
if (!NT_SUCCESS(Status))
{
/* It's not critical, but we won't have it */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Failed to get machine name.\n");
}
else
{
/* We have the name, copy it from the registry */
Status = CopyRegistryValueData((PVOID*)&MachineInformation->
MachineName,
PartialInfo);
SacFreePool(PartialInfo);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (20).\n");
goto Fail;
}
}
}
/* Next step, try to get the machine GUID */
RtlZeroMemory(&SystemGuid, sizeof(SystemGuid));
OutputSize = sizeof(SystemGuid);
Status = HeadlessDispatch(HeadlessCmdQueryGUID,
NULL,
0,
&SystemGuid,
&OutputSize);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Failed to get Machine GUID.\n");
}
else
{
/* We have it -- make room for it */
GuidString = SacAllocatePool(0x50, GLOBAL_BLOCK_TAG);
if (!GuidString)
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (31).\n");
goto Fail;
}
/* Build the string with the GUID in it, and save the ppointer to it */
swprintf(GuidString,
L"%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
SystemGuid.Data1,
SystemGuid.Data2,
SystemGuid.Data3,
SystemGuid.Data4[0],
SystemGuid.Data4[1],
SystemGuid.Data4[2],
SystemGuid.Data4[3],
SystemGuid.Data4[4],
SystemGuid.Data4[5],
SystemGuid.Data4[6],
SystemGuid.Data4[7]);
MachineInformation->MachineGuid = GuidString;
}
/* Next, query the processor architecture */
Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\"
L"CurrentControlSet\\Control\\"
L"Session Manager\\Environment",
L"PROCESSOR_ARCHITECTURE",
&PartialInfo);
if (!NT_SUCCESS(Status))
{
/* It's not critical, but we won't have it */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (30).\n");
}
else
{
/* We have it! Copy the value from the registry */
Status = CopyRegistryValueData((PVOID*)&MachineInformation->
ProcessorArchitecture,
PartialInfo);
SacFreePool(PartialInfo);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (30).\n");
goto Fail;
}
}
/* Now allocate a buffer for the OS version number */
MajorVersion = SacAllocatePool(0x18, GLOBAL_BLOCK_TAG);
if (!MajorVersion)
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (50).\n");
goto Fail;
}
/* Build the buffer and set a pointer to it */
swprintf(MajorVersion,
L"%d.%d",
VersionInformation.dwMajorVersion,
VersionInformation.dwMinorVersion);
MachineInformation->MajorVersion = MajorVersion;
/* Now allocate a buffer for the OS build number */
BuildNumber = SacAllocatePool(0xC, GLOBAL_BLOCK_TAG);
if (!BuildNumber)
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (60).\n");
goto Fail;
}
/* Build the buffer and set a pointer to it */
swprintf(BuildNumber, L"%d", VersionInformation.dwBuildNumber);
MachineInformation->BuildNumber = BuildNumber;
/* Now check what kind of SKU this is */
if (ExVerifySuite(DataCenter))
{
SuiteTypeMessage = SAC_DATACENTER_SUITE_MSG;
}
else if (ExVerifySuite(EmbeddedNT))
{
SuiteTypeMessage = SAC_EMBEDDED_SUITE_MSG;
}
else if (ExVerifySuite(Enterprise))
{
SuiteTypeMessage = SAC_ENTERPRISE_SUITE_MSG;
}
else
{
/* Unknown or perhaps a client SKU */
SuiteTypeMessage = SAC_NO_SUITE_MSG;
}
/* Get the string that correponds to the SKU type */
MessageBuffer = GetMessage(SuiteTypeMessage);
if (!MessageBuffer)
{
/* We won't have it, but this isn't critical */
SAC_DBG(SAC_DBG_INIT, "SAC InitializeMachineInformation: Failed to get product type.\n");
}
else
{
/* Calculate the size we need to hold the string */
Size = wcslen(MessageBuffer);
ASSERT(Size > 0);
RealSize = Size * sizeof(WCHAR) + sizeof(UNICODE_NULL);
/* Allocate a buffer for it */
ProductType = SacAllocatePool(RealSize, GLOBAL_BLOCK_TAG);
if (!ProductType)
{
SAC_DBG(SAC_DBG_INIT, "SAC InitializeMachineInformation: Failed product type memory allocation.\n");
goto Fail;
}
/* Copy the string and set the pointer */
RtlCopyMemory(ProductType, MessageBuffer, RealSize);
MachineInformation->ProductType = ProductType;
}
/* Check if this is a SP version or RTM version */
if (VersionInformation.wServicePackMajor)
{
/* This is a service pack, allocate a buffer for the version */
ServicePack = SacAllocatePool(0x18, GLOBAL_BLOCK_TAG);
if (ServicePack)
{
/* Build the buffer and set a pointer to it */
swprintf(ServicePack,
L"%d.%d",
VersionInformation.wServicePackMajor,
VersionInformation.wServicePackMinor);
MachineInformation->ServicePack = ServicePack;
/* We've collected all the machine info and are done! */
return;
}
/* This is the failure path */
SAC_DBG(SAC_DBG_INIT, "SAC InitializeMachineInformation: Failed service pack memory allocation.\n");
}
else
{
/* Get a generic string that indicates there's no service pack */
MessageBuffer = GetMessage(SAC_NO_DATA_MSG);
Size = wcslen(MessageBuffer);
ASSERT(Size > 0);
RealSize = Size * sizeof(WCHAR) + sizeof(UNICODE_NULL);
/* Allocate memory for the "no service pack" string */
ServicePack = SacAllocatePool(RealSize, GLOBAL_BLOCK_TAG);
if (ServicePack)
{
/* Copy the buffer and set a pointer to it */
RtlCopyMemory(ServicePack, MessageBuffer, RealSize);
MachineInformation->ServicePack = ServicePack;
/* We've collected all the machine info and are done! */
return;
}
SAC_DBG(SAC_DBG_INIT, "SAC InitializeMachineInformation: Failed service pack memory allocation.\n");
}
Fail:
/* In the failure path, always cleanup the machine information buffer */
if (MachineInformation)
{
SacFreePool(MachineInformation);
}
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC Initialize Machine Information : Exiting with error.\n");
}
NTSTATUS
NTAPI
GetCommandConsoleLaunchingPermission(OUT PBOOLEAN Permission)
@ -549,7 +861,7 @@ ImposeSacCmdServiceStartTypePolicy(VOID)
if (!Buffer) return STATUS_UNSUCCESSFUL;
/* Read the value */
Status = CopyRegistryValueData(&Data, Buffer);
Status = CopyRegistryValueData((PVOID*)&Data, Buffer);
SacFreePool(Buffer);
if (!NT_SUCCESS(Status)) return Status;
@ -632,7 +944,7 @@ NTAPI
RegisterBlueScreenMachineInformation(VOID)
{
PWCHAR XmlBuffer;
PHEADLESS_BLUE_SCREEN_DATA BsBuffer;
PHEADLESS_CMD_SET_BLUE_SCREEN_DATA BsBuffer;
ULONG Length, HeaderLength, TotalLength;
NTSTATUS Status;
ULONG i;
@ -653,15 +965,15 @@ RegisterBlueScreenMachineInformation(VOID)
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);
strcpy((PCHAR)BsBuffer->Data, "MACHINEINFO");
BsBuffer->ValueIndex = 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->Data[BsBuffer->ValueIndex + i] = XmlBuffer[i];
}
BsBuffer->XMLData[HeaderLength + sizeof(ANSI_NULL) + i] = ANSI_NULL;
BsBuffer->Data[BsBuffer->ValueIndex + i] = ANSI_NULL;
/* Let the OS save the buffer for later */
Status = HeadlessDispatch(HeadlessCmdSetBlueScreenData,

View file

@ -7,9 +7,12 @@ list(APPEND UNICODE_SOURCE
neteventmsg.mc
ntiologc.mc
ntstatus.mc
pciclass.mc
pciclass.mc)
list(APPEND UNICODE_SOURCE_REALLY
sacmsg.mc)
add_message_headers(ANSI ${ANSI_SOURCE})
# FIXME: this needs testing before switching to unicode
add_message_headers(ANSI ${UNICODE_SOURCE})
add_message_headers(UNICODE ${UNICODE_SOURCE_REALLY})

View file

@ -461,7 +461,7 @@ Language=English
.
MessageId=98
SymbolicName=SACDRV_98
SymbolicName=SAC_NO_DATA_MSG
Language=English
None%0
.
@ -473,25 +473,25 @@ Language=English
.
MessageId=100
SymbolicName=SACDRV_100
SymbolicName=SAC_DATACENTER_SUITE_MSG
Language=English
Windows Server 2003 Datacenter Edition%0
.
MessageId=101
SymbolicName=SACDRV_101
SymbolicName=SAC_EMBEDDED_SUITE_MSG
Language=English
Windows Server 2003 Embedded%0
.
MessageId=102
SymbolicName=SACDRV_102
SymbolicName=SAC_ENTERPRISE_SUITE_MSG
Language=English
Windows Server 2003 Enterprise Edition%0
.
MessageId=103
SymbolicName=SACDRV_103
SymbolicName=SAC_NO_SUITE_MSG
Language=English
Windows Server 2003%0
.
@ -695,7 +695,7 @@ The specified gateway IP address is invalid.
.
MessageId=153
SymbolicName=SACDRV_153
SymbolicName=SAC_UNINITIALIZED_MSG
Language=English
not yet initialized%0
.

View file

@ -17,111 +17,156 @@ PHEADLESS_GLOBALS HeadlessGlobals;
/* FUNCTIONS *****************************************************************/
FORCEINLINE
KIRQL
HdlspAcquireGlobalLock(VOID)
{
KIRQL OldIrql;
/* Don't acquire the lock if we are bugchecking */
if (!HeadlessGlobals->InBugCheck)
{
KeAcquireSpinLock(&HeadlessGlobals->SpinLock, &OldIrql);
}
else
{
OldIrql = 0xFF;
}
return OldIrql;
}
FORCEINLINE
VOID
HdlspReleaselobalLock(IN KIRQL OldIrql)
{
/* Only release the lock if we aren't bugchecking */
if (OldIrql != 0xFF)
{
KeReleaseSpinLock(&HeadlessGlobals->SpinLock, OldIrql);
}
else
{
ASSERT(HeadlessGlobals->InBugCheck == TRUE);
}
}
VOID
NTAPI
HdlspSendStringAtBaud(
IN PUCHAR String
)
HdlspSendStringAtBaud(IN PUCHAR String)
{
/* Send every byte */
while (*String++ != ANSI_NULL)
{
InbvPortPutByte(HeadlessGlobals->TerminalPort, *String);
}
/* Send every byte */
while (*String++ != ANSI_NULL)
{
InbvPortPutByte(HeadlessGlobals->TerminalPort, *String);
}
}
NTSTATUS
NTAPI
HdlspEnableTerminal(
IN BOOLEAN Enable
)
HdlspEnableTerminal(IN BOOLEAN Enable)
{
/* Enable if requested, as long as this isn't a PCI serial port crashing */
if ((Enable) &&
!(HeadlessGlobals->TerminalEnabled) &&
!((HeadlessGlobals->IsMMIODevice) && (HeadlessGlobals->InBugCheck)))
{
/* Initialize the COM port with cportlib */
HeadlessGlobals->TerminalEnabled = InbvPortInitialize(
HeadlessGlobals->TerminalBaudRate,
HeadlessGlobals->TerminalPortNumber,
HeadlessGlobals->TerminalPortAddress,
&HeadlessGlobals->TerminalPort,
HeadlessGlobals->IsMMIODevice);
if (!HeadlessGlobals->TerminalEnabled) return STATUS_UNSUCCESSFUL;
/* Enable if requested, as long as this isn't a PCI serial port crashing */
if ((Enable) &&
!(HeadlessGlobals->TerminalEnabled) &&
!((HeadlessGlobals->IsMMIODevice) && (HeadlessGlobals->InBugCheck)))
{
/* Initialize the COM port with cportlib */
HeadlessGlobals->TerminalEnabled = InbvPortInitialize(HeadlessGlobals->
TerminalBaudRate,
HeadlessGlobals->
TerminalPortNumber,
HeadlessGlobals->
TerminalPortAddress,
&HeadlessGlobals->
TerminalPort,
HeadlessGlobals->
IsMMIODevice);
if (!HeadlessGlobals->TerminalEnabled)
{
DPRINT1("Failed to initialize port through cportlib\n");
return STATUS_UNSUCCESSFUL;
}
/* Cleanup the screen and reset the cursor */
HdlspSendStringAtBaud((PUCHAR)"\x1B[2J");
HdlspSendStringAtBaud((PUCHAR)"\x1B[H");
/* Cleanup the screen and reset the cursor */
HdlspSendStringAtBaud((PUCHAR)"\x1B[2J");
HdlspSendStringAtBaud((PUCHAR)"\x1B[H");
/* Enable FIFO */
InbvPortEnableFifo(HeadlessGlobals->TerminalPort, TRUE);
}
else if (!Enable)
{
/* Specific case when headless is being disabled */
InbvPortTerminate(HeadlessGlobals->TerminalPort);
HeadlessGlobals->TerminalPort = 0;
HeadlessGlobals->TerminalEnabled = FALSE;
}
return STATUS_SUCCESS;
/* Enable FIFO */
InbvPortEnableFifo(HeadlessGlobals->TerminalPort, TRUE);
}
else if (!Enable)
{
/* Specific case when headless is being disabled */
InbvPortTerminate(HeadlessGlobals->TerminalPort);
HeadlessGlobals->TerminalPort = 0;
HeadlessGlobals->TerminalEnabled = FALSE;
}
/* All done */
return STATUS_SUCCESS;
}
VOID
NTAPI
INIT_FUNCTION
HeadlessInit(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
HeadlessInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PHEADLESS_LOADER_BLOCK HeadlessBlock;
PHEADLESS_LOADER_BLOCK HeadlessBlock;
HeadlessBlock = LoaderBlock->Extension->HeadlessLoaderBlock;
if (!HeadlessBlock) return;
if ((HeadlessBlock->PortNumber > 4) && (HeadlessBlock->UsedBiosSettings)) return;
/* Only initialize further if the loader found EMS enabled */
HeadlessBlock = LoaderBlock->Extension->HeadlessLoaderBlock;
if (!HeadlessBlock) return;
HeadlessGlobals = ExAllocatePoolWithTag(
NonPagedPool,
sizeof(HEADLESS_GLOBALS),
'sldH');
if (!HeadlessGlobals) return;
/* Ignore invalid EMS settings */
if ((HeadlessBlock->PortNumber > 4) && (HeadlessBlock->UsedBiosSettings)) return;
/* Zero and copy loader data */
RtlZeroMemory(HeadlessGlobals, sizeof(HEADLESS_GLOBALS));
HeadlessGlobals->TerminalPortNumber = HeadlessBlock->PortNumber;
HeadlessGlobals->TerminalPortAddress = HeadlessBlock->PortAddress;
HeadlessGlobals->TerminalBaudRate = HeadlessBlock->BaudRate;
HeadlessGlobals->TerminalParity = HeadlessBlock->Parity;
HeadlessGlobals->TerminalStopBits = HeadlessBlock->StopBits;
HeadlessGlobals->UsedBiosSettings = HeadlessBlock->UsedBiosSettings;
HeadlessGlobals->IsMMIODevice = HeadlessBlock->IsMMIODevice;
HeadlessGlobals->TerminalType = HeadlessBlock->TerminalType;
HeadlessGlobals->SystemGUID = HeadlessBlock->SystemGUID;
/* Allocate the global headless data */
HeadlessGlobals = ExAllocatePoolWithTag(NonPagedPool,
sizeof(*HeadlessGlobals),
'sldH');
if (!HeadlessGlobals) return;
/* These two are opposites of each other */
if (HeadlessGlobals->IsMMIODevice) HeadlessGlobals->IsNonLegacyDevice = TRUE;
/* Zero and copy loader data */
RtlZeroMemory(HeadlessGlobals, sizeof(*HeadlessGlobals));
HeadlessGlobals->TerminalPortNumber = HeadlessBlock->PortNumber;
HeadlessGlobals->TerminalPortAddress = HeadlessBlock->PortAddress;
HeadlessGlobals->TerminalBaudRate = HeadlessBlock->BaudRate;
HeadlessGlobals->TerminalParity = HeadlessBlock->Parity;
HeadlessGlobals->TerminalStopBits = HeadlessBlock->StopBits;
HeadlessGlobals->UsedBiosSettings = HeadlessBlock->UsedBiosSettings;
HeadlessGlobals->IsMMIODevice = HeadlessBlock->IsMMIODevice;
HeadlessGlobals->TerminalType = HeadlessBlock->TerminalType;
HeadlessGlobals->SystemGUID = HeadlessBlock->SystemGUID;
DPRINT1("EMS on Port %d (0x%lx) at %d bps\n",
HeadlessGlobals->TerminalPortNumber,
HeadlessGlobals->TerminalPortAddress,
HeadlessGlobals->TerminalBaudRate);
/* Check for a PCI device, warn that this isn't supported */
if (HeadlessBlock->PciDeviceId != PCI_INVALID_VENDORID)
{
DPRINT1("PCI Serial Ports not supported\n");
}
/* These two are opposites of each other */
if (HeadlessGlobals->IsMMIODevice) HeadlessGlobals->IsNonLegacyDevice = TRUE;
/* Log entries are not yet supported */
DPRINT1("FIXME: No Headless logging support\n");
/* Check for a PCI device, warn that this isn't supported */
if (HeadlessBlock->PciDeviceId != PCI_INVALID_VENDORID)
{
DPRINT1("PCI Serial Ports not supported\n");
}
/* Allocate temporary buffer */
HeadlessGlobals->TmpBuffer = ExAllocatePoolWithTag(NonPagedPool, 80, 'sldH');
if (!HeadlessGlobals->TmpBuffer) return;
/* Log entries are not yet supported */
DPRINT1("FIXME: No Headless logging support\n");
/* Windows seems to apply some special hacks for 9600 bps */
if (HeadlessGlobals->TerminalBaudRate == 9600)
{
DPRINT1("Please use other baud rate than 9600bps for now\n");
}
/* Allocate temporary buffer */
HeadlessGlobals->TmpBuffer = ExAllocatePoolWithTag(NonPagedPool, 80, 'sldH');
if (!HeadlessGlobals->TmpBuffer) return;
/* Enable the terminal */
HdlspEnableTerminal(TRUE);
/* Windows seems to apply some special hacks for 9600 bps */
if (HeadlessGlobals->TerminalBaudRate == 9600)
{
DPRINT1("Please use other baud rate than 9600bps for now\n");
}
/* Enable the terminal */
HdlspEnableTerminal(TRUE);
}
VOID
@ -197,59 +242,80 @@ HdlspPutString(
NTSTATUS
NTAPI
HdlspDispatch(
IN HEADLESS_CMD Command,
IN PVOID InputBuffer,
IN SIZE_T InputBufferSize,
OUT PVOID OutputBuffer,
OUT PSIZE_T OutputBufferSize
)
HdlspDispatch(IN HEADLESS_CMD Command,
IN PVOID InputBuffer,
IN SIZE_T InputBufferSize,
OUT PVOID OutputBuffer,
OUT PSIZE_T OutputBufferSize)
{
//NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
ASSERT(HeadlessGlobals != NULL);
KIRQL OldIrql;
PHEADLESS_RSP_QUERY_INFO HeadlessInfo;
PHEADLESS_CMD_PUT_STRING PutString;
PHEADLESS_CMD_ENABLE_TERMINAL EnableTerminal;
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
ASSERT(HeadlessGlobals != NULL);
// ASSERT(HeadlessGlobals->PageLockHandle != NULL);
/* FIXME: This should be using the headless spinlock */
/* Ignore non-reentrant commands */
if ((Command != HeadlessCmdAddLogEntry) &&
(Command != HeadlessCmdStartBugCheck) &&
(Command != HeadlessCmdSendBlueScreenData) &&
(Command != HeadlessCmdDoBugCheckProcessing))
{
OldIrql = HdlspAcquireGlobalLock();
/* Ignore non-reentrant commands */
if ((Command != HeadlessCmdAddLogEntry) &&
(Command != HeadlessCmdStartBugCheck) &&
(Command != HeadlessCmdSendBlueScreenData) &&
(Command != HeadlessCmdDoBugCheckProcessing))
{
if (HeadlessGlobals->ProcessingCmd) return STATUS_UNSUCCESSFUL;
if (HeadlessGlobals->ProcessingCmd)
{
HdlspReleaselobalLock(OldIrql);
return STATUS_UNSUCCESSFUL;
}
/* Don't allow these commands next time */
HeadlessGlobals->ProcessingCmd = TRUE;
}
/* Don't allow these commands next time */
HeadlessGlobals->ProcessingCmd = TRUE;
HdlspReleaselobalLock(OldIrql);
}
/* Handle each command */
switch (Command)
{
case HeadlessCmdEnableTerminal:
/* Make sure the caller passed valid data */
if (!(InputBuffer) ||
(InputBufferSize != sizeof(*EnableTerminal)))
{
DPRINT1("Invalid buffer\n");
Status = STATUS_INVALID_PARAMETER;
break;
}
/* Go and enable it */
EnableTerminal = InputBuffer;
Status = HdlspEnableTerminal(EnableTerminal->Enable);
break;
/* Handle each command */
switch (Command)
{
case HeadlessCmdEnableTerminal:
break;
case HeadlessCmdCheckForReboot:
break;
case HeadlessCmdPutString:
/* Validate the existence of an input buffer */
if (!InputBuffer)
{
//Status = STATUS_INVALID_PARAMETER;
goto Reset;
}
/* Validate the existence of an input buffer */
if (!InputBuffer)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
/* Terminal should be on */
if (HeadlessGlobals->TerminalEnabled)
{
/* Print each byte in the string making sure VT100 chars are used */
PHEADLESS_CMD_PUT_STRING PutString = (PVOID)InputBuffer;
PutString = InputBuffer;
HdlspPutString(PutString->String);
}
/* Return success either way */
//Status = STATUS_SUCCESS;
Status = STATUS_SUCCESS;
break;
case HeadlessCmdClearDisplay:
break;
@ -276,13 +342,62 @@ HdlspDispatch(
case HeadlessCmdDoBugCheckProcessing:
break;
case HeadlessCmdQueryInformation:
break;
/* Make sure the caller passed valid data */
if (!(OutputBuffer) ||
!(OutputBufferSize) ||
(*OutputBufferSize < sizeof(*HeadlessInfo)))
{
DPRINT1("Invalid buffer\n");
Status = STATUS_INVALID_PARAMETER;
break;
}
/* If we got here, headless is enabled -- we know this much */
HeadlessInfo = OutputBuffer;
HeadlessInfo->PortType = HeadlessSerialPort;
HeadlessInfo->Serial.TerminalAttached = TRUE;
HeadlessInfo->Serial.UsedBiosSettings = HeadlessGlobals->UsedBiosSettings;
HeadlessInfo->Serial.TerminalBaudRate = HeadlessGlobals->TerminalBaudRate;
HeadlessInfo->Serial.TerminalType = HeadlessGlobals->TerminalType;
/* Now check on what port/baud it's enabled on */
if ((HeadlessGlobals->TerminalPortNumber >= 1) ||
(HeadlessGlobals->UsedBiosSettings))
{
/* Get the EMS information */
HeadlessInfo->Serial.TerminalPort = HeadlessGlobals->
TerminalPortNumber;
HeadlessInfo->Serial.TerminalPortBaseAddress = HeadlessGlobals->
TerminalPortAddress;
}
else
{
/* We don't know for sure */
HeadlessInfo->Serial.TerminalPort = SerialPortUndefined;
HeadlessInfo->Serial.TerminalPortBaseAddress = 0;
}
/* All done */
Status = STATUS_SUCCESS;
break;
case HeadlessCmdAddLogEntry:
break;
case HeadlessCmdDisplayLog:
break;
case HeadlessCmdSetBlueScreenData:
break;
case HeadlessCmdSetBlueScreenData:
/* Validate the existence of an input buffer */
if (!InputBuffer)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
/* Lie so that we can get Hdl bringup a little bit further */
UNIMPLEMENTED;
Status = STATUS_SUCCESS;
break;
case HeadlessCmdSendBlueScreenData:
break;
case HeadlessCmdQueryGUID:
@ -293,60 +408,60 @@ HdlspDispatch(
break;
}
Reset:
/* Unset prcessing state */
if ((Command != HeadlessCmdAddLogEntry) &&
(Command != HeadlessCmdStartBugCheck) &&
(Command != HeadlessCmdSendBlueScreenData) &&
(Command != HeadlessCmdDoBugCheckProcessing))
{
ASSERT(HeadlessGlobals->ProcessingCmd == TRUE);
HeadlessGlobals->ProcessingCmd = FALSE;
}
/* Unset processing state */
if ((Command != HeadlessCmdAddLogEntry) &&
(Command != HeadlessCmdStartBugCheck) &&
(Command != HeadlessCmdSendBlueScreenData) &&
(Command != HeadlessCmdDoBugCheckProcessing))
{
ASSERT(HeadlessGlobals->ProcessingCmd == TRUE);
HeadlessGlobals->ProcessingCmd = FALSE;
}
//UNIMPLEMENTED;
return STATUS_SUCCESS;
/* All done */
return Status;
}
/*
* @unimplemented
* @implemented
*/
NTSTATUS
NTAPI
HeadlessDispatch(
IN HEADLESS_CMD Command,
IN PVOID InputBuffer,
IN SIZE_T InputBufferSize,
OUT PVOID OutputBuffer,
OUT PSIZE_T OutputBufferSize
)
HeadlessDispatch(IN HEADLESS_CMD Command,
IN PVOID InputBuffer,
IN SIZE_T InputBufferSize,
OUT PVOID OutputBuffer,
OUT PSIZE_T OutputBufferSize)
{
/* Check for stubs that will expect something even with headless off */
if (!HeadlessGlobals)
{
/* Don't allow the SAC to connect */
if (Command == HeadlessCmdEnableTerminal) return STATUS_UNSUCCESSFUL;
/* Check for stubs that will expect something even with headless off */
if (!HeadlessGlobals)
{
/* Don't allow the SAC to connect */
if (Command == HeadlessCmdEnableTerminal) return STATUS_UNSUCCESSFUL;
/* Send bogus reply */
if ((Command == HeadlessCmdQueryInformation) ||
(Command == HeadlessCmdGetByte) ||
(Command == HeadlessCmdGetLine) ||
(Command == HeadlessCmdCheckForReboot) ||
(Command == HeadlessCmdTerminalPoll))
{
if (!(OutputBuffer) || !(OutputBufferSize)) return STATUS_INVALID_PARAMETER;
RtlZeroMemory(OutputBuffer, *OutputBufferSize);
}
return STATUS_SUCCESS;
}
/* Do the real work */
return HdlspDispatch(
Command,
InputBuffer,
InputBufferSize,
OutputBuffer,
OutputBufferSize);
}
/* Send bogus reply */
if ((Command == HeadlessCmdQueryInformation) ||
(Command == HeadlessCmdGetByte) ||
(Command == HeadlessCmdGetLine) ||
(Command == HeadlessCmdCheckForReboot) ||
(Command == HeadlessCmdTerminalPoll))
{
if (!(OutputBuffer) || !(OutputBufferSize))
{
return STATUS_INVALID_PARAMETER;
}
RtlZeroMemory(OutputBuffer, *OutputBufferSize);
}
return STATUS_SUCCESS;
}
/* Do the real work */
return HdlspDispatch(Command,
InputBuffer,
InputBufferSize,
OutputBuffer,
OutputBufferSize);
}
/* EOF */

View file

@ -72,12 +72,11 @@ typedef struct _HEADLESS_LOG_ENTRY
//
// Headless Bugcheck Information
//
typedef struct _HEADLESS_BLUE_SCREEN_DATA
typedef struct _HEADLESS_CMD_SET_BLUE_SCREEN_DATA
{
PUCHAR Property;
PUCHAR XMLData;
struct _HEADLESS_BLUE_SCREEN_DATA *Next;
} HEADLESS_BLUE_SCREEN_DATA, * PHEADLESS_BLUE_SCREEN_DATA;
ULONG ValueIndex;
UCHAR Data[ANYSIZE_ARRAY];
} HEADLESS_CMD_SET_BLUE_SCREEN_DATA, *PHEADLESS_CMD_SET_BLUE_SCREEN_DATA;
//
// Headless Control Structure, mostly for !SAC
@ -89,7 +88,7 @@ typedef struct _HEADLESS_GLOBALS
PHEADLESS_LOG_ENTRY LogEntries;
PUCHAR TmpBuffer;
PUCHAR InputBuffer;
PHEADLESS_BLUE_SCREEN_DATA BlueScreenData;
PHEADLESS_CMD_SET_BLUE_SCREEN_DATA BlueScreenData;
union
{
struct
@ -183,6 +182,11 @@ typedef struct _HEADLESS_RSP_QUERY_INFO
};
} HEADLESS_RSP_QUERY_INFO, *PHEADLESS_RSP_QUERY_INFO;
typedef struct _HEADLESS_CMD_ENABLE_TERMINAL
{
BOOLEAN Enable;
} HEADLESS_CMD_ENABLE_TERMINAL, *PHEADLESS_CMD_ENABLE_TERMINAL;
typedef struct _HEADLESS_CMD_PUT_STRING
{
UCHAR String[1];