Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310/* * 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 *******************************************************************/
#include "sacdrv.h"
#include <ndk/rtlfuncs.h>
/* GLOBALS ********************************************************************/
PCHAR Utf8ConversionBuffer;ULONG Utf8ConversionBufferSize = PAGE_SIZE;
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 ******************************************************************/
BOOLEANNTAPISacTranslateUtf8ToUnicode(IN CHAR Utf8Char, IN PCHAR Utf8Buffer, OUT PWCHAR Utf8Value){ ULONG i;
/* Find out how many valid characters we have in the buffer */ i = 0; while (Utf8Buffer[i++] && (i < 3));
/* If we have at least 3, shift everything by a byte */ if (i >= 3) { /* The last input character goes at the end */ Utf8Buffer[0] = Utf8Buffer[1]; Utf8Buffer[1] = Utf8Buffer[2]; Utf8Buffer[2] = Utf8Char; } else { /* We don't have more than 3 characters, place the input at the index */ Utf8Buffer[i] = Utf8Char; }
/* Print to debugger */ SAC_DBG(SAC_DBG_ENTRY_EXIT, "SacTranslateUtf8ToUnicode - About to decode the UTF8 buffer.\n"); SAC_DBG(SAC_DBG_ENTRY_EXIT, " UTF8[0]: 0x%02lx UTF8[1]: 0x%02lx UTF8[2]: 0x%02lx\n", Utf8Buffer[0], Utf8Buffer[1], Utf8Buffer[2]);
/* Is this a simple ANSI character? */ if (!(Utf8Char & 0x80)) { /* Return it as Unicode, nothing left to do */ SAC_DBG(SAC_DBG_ENTRY_EXIT, "SACDRV: SacTranslateUTf8ToUnicode - Case1\n"); *Utf8Value = (WCHAR)Utf8Char; Utf8Buffer[0] = Utf8Buffer[1]; Utf8Buffer[1] = Utf8Buffer[2]; Utf8Buffer[2] = UNICODE_NULL; return TRUE; }
/* Anything else is not yet supported */ ASSERT(FALSE); return FALSE;}
BOOLEANNTAPISacTranslateUnicodeToUtf8(IN PWCHAR SourceBuffer, IN ULONG SourceBufferLength, OUT PCHAR DestinationBuffer, IN ULONG DestinationBufferSize, OUT PULONG UTF8Count, OUT PULONG ProcessedCount){ *UTF8Count = 0; *ProcessedCount = 0;
while ((*SourceBuffer) && (*UTF8Count < DestinationBufferSize) && (*ProcessedCount < SourceBufferLength)) { if (*SourceBuffer & 0xFF80) { if (*SourceBuffer & 0xF800) { if ((*UTF8Count + 3) >= DestinationBufferSize) break; DestinationBuffer[*UTF8Count] = ((*SourceBuffer >> 12) & 0xF) | 0xE0; ++*UTF8Count; DestinationBuffer[*UTF8Count] = ((*SourceBuffer >> 6) & 0x3F) | 0x80; } else { if ((*UTF8Count + 2) >= DestinationBufferSize) break; DestinationBuffer[*UTF8Count] = ((*SourceBuffer >> 6) & 31) | 0xC0; } ++*UTF8Count; DestinationBuffer[*UTF8Count] = (*SourceBuffer & 0x3F) | 0x80; } else { DestinationBuffer[*UTF8Count] = (*SourceBuffer & 0x7F); }
++*UTF8Count; ++*ProcessedCount; ++SourceBuffer; }
ASSERT(*ProcessedCount <= SourceBufferLength); ASSERT(*UTF8Count <= DestinationBufferSize); return TRUE;}
PWCHARNTAPIGetMessage(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;}
NTSTATUSNTAPIUTF8EncodeAndSend(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;}
VOIDNTAPISacFormatMessage(IN PWCHAR FormattedString, IN PWCHAR MessageString, IN ULONG MessageSize){ SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Entering.\n");
/* Check if any of the parameters are NULL or zero */ if (!(MessageString) || !(FormattedString) || !(MessageSize)) { SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Exiting with invalid parameters.\n"); return; }
/* Keep going as long as there's still characters */ while ((MessageString[0]) && (MessageSize)) { /* Is it a non-formatting character? */ if (MessageString[0] != L'%') { /* Just write it back into the buffer and keep going */ *FormattedString++ = MessageString[0]; MessageString++; } else { /* Go over the format characters we recognize */ switch (MessageString[1]) { case L'0': *FormattedString = UNICODE_NULL; return;
case L'%': *FormattedString++ = L'%'; break;
case L'\\': *FormattedString++ = L'\r'; *FormattedString++ = L'\n'; break;
case L'r': *FormattedString++ = L'\r'; break;
case L'b': *FormattedString++ = L' '; break;
case L'.': *FormattedString++ = L'.'; break;
case L'!': *FormattedString++ = L'!'; break;
default: /* Only move forward one character */ MessageString--; break; }
/* Move forward two characters */ MessageString += 2; }
/* Move to the next character*/ MessageSize--; }
/* All done */ *FormattedString = UNICODE_NULL; SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Exiting.\n");}
NTSTATUSNTAPIPreloadGlobalMessageTable(IN PVOID ImageBase){ NTSTATUS Status, Status2; 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 */ Status = STATUS_SUCCESS; if (GlobalMessageTable) goto Exit;
/* Loop through up to 200 messages */ TotalLength = 0; for (MessageId = 1; MessageId != SAC_MAX_MESSAGES; MessageId++) { /* Find this message in the message table */ Status2 = RtlFindMessage(ImageBase, RT_MESSAGETABLE, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), MessageId, &MessageEntry); if (NT_SUCCESS(Status2)) { /* 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! */ Status2 = RtlFindMessage(ImageBase, RT_MESSAGETABLE, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), MessageId, &MessageEntry); if (NT_SUCCESS(Status2)) { /* 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 / sizeof(WCHAR));
/* 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;}
NTSTATUSNTAPITearDownGlobalMessageTable(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;}
NTSTATUSNTAPIGetRegistryValueBuffer(IN PCWSTR KeyName, IN PWCHAR ValueName, IN PKEY_VALUE_PARTIAL_INFORMATION* Buffer){ NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING DestinationString; HANDLE Handle; ULONG 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 | OBJ_KERNEL_HANDLE, 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) goto Quit;
/* 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(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: failed allocation\n"); goto Quit; }
/* 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); }
Quit: /* Close the handle and exit */ ZwClose(Handle); SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: Exiting.\n"); return Status;}
NTSTATUSNTAPISetRegistryValue(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 | OBJ_KERNEL_HANDLE, 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(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: failed ZwSetValueKey: %X.\n", Status); }
/* Close the handle and exit */ ZwClose(Handle); SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: Exiting.\n"); return Status;}
NTSTATUSNTAPICopyRegistryValueData(IN PVOID* 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;}
NTSTATUSNTAPITranslateMachineInformationXML(IN PWCHAR *Buffer, IN PWCHAR ExtraData){ NTSTATUS Status; SIZE_T 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;}
VOIDNTAPIInitializeMachineInformation(VOID){ NTSTATUS Status; PWCHAR GuidString, MajorVersion, ServicePack, BuildNumber, MessageBuffer; PWCHAR ProductType; ULONG SuiteTypeMessage; BOOLEAN SetupInProgress = FALSE; GUID SystemGuid; SIZE_T 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 queried this */ if (MachineInformation) { SAC_DBG(SAC_DBG_MACHINE, "SAC Initialize Machine Information:: MachineInformationBuffer already initialized.\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 corresponds 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");}
NTSTATUSNTAPIGetCommandConsoleLaunchingPermission(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;}
NTSTATUSNTAPIImposeSacCmdServiceStartTypePolicy(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((PVOID*)&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;}
VOIDNTAPIInitializeCmdEventInfo(VOID){ /* Check if we were already initialized */ 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;}
NTSTATUSNTAPIRegisterBlueScreenMachineInformation(VOID){ PWCHAR XmlBuffer; PHEADLESS_CMD_SET_BLUE_SCREEN_DATA BsBuffer; SIZE_T 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->Data, "MACHINEINFO"); BsBuffer->ValueIndex = HeaderLength + sizeof(ANSI_NULL);
/* Copy the data and NULL-terminate it */ for (i = 0; i < Length; i++) { BsBuffer->Data[BsBuffer->ValueIndex + i] = XmlBuffer[i]; } BsBuffer->Data[BsBuffer->ValueIndex + 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;}
VOIDNTAPIFreeMachineInformation(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);}
BOOLEANNTAPIVerifyEventWaitable(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;}
NTSTATUSNTAPISerialBufferGetChar(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;}
ULONGNTAPIGetMessageLineCount(IN ULONG MessageIndex){ ULONG LineCount = 0; PWCHAR Buffer;
/* Get the message buffer */ Buffer = GetMessage(MessageIndex); if (Buffer) { /* Scan it looking for new lines, and increment the count each time */ while (*Buffer) if (*Buffer++ == L'\n') ++LineCount; }
/* Return the line count */ return LineCount;}
ULONGConvertAnsiToUnicode( IN PWCHAR pwch, IN PCHAR pch, IN ULONG length ){ return STATUS_NOT_IMPLEMENTED;}
BOOLEANIsCmdEventRegistrationProcess( IN PFILE_OBJECT FileObject ){ return FALSE;}
NTSTATUSInvokeUserModeService( VOID ){ return STATUS_NOT_IMPLEMENTED;}
NTSTATUSTranslateMachineInformationText( IN PWCHAR Buffer){ return STATUS_NOT_IMPLEMENTED;}
NTSTATUSCopyAndInsertStringAtInterval( IN PWCHAR SourceStr, IN ULONG Interval, IN PWCHAR InsertStr, OUT PWCHAR pDestStr ){ return STATUS_NOT_IMPLEMENTED;}
NTSTATUSRegisterSacCmdEvent( IN PVOID Object, IN PKEVENT SetupCmdEvent[] ){ return STATUS_NOT_IMPLEMENTED;}
NTSTATUSUnregisterSacCmdEvent( IN PFILE_OBJECT FileObject ){ return STATUS_NOT_IMPLEMENTED;}