xref: /reactos/drivers/sac/driver/util.c (revision ed125de9)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:     ReactOS Drivers
3c2c66affSColin Finck  * LICENSE:     BSD - See COPYING.ARM in the top level directory
4c2c66affSColin Finck  * FILE:        drivers/sac/driver/util.c
5c2c66affSColin Finck  * PURPOSE:     Driver for the Server Administration Console (SAC) for EMS
6c2c66affSColin Finck  * PROGRAMMERS: ReactOS Portable Systems Group
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck /* INCLUDES *******************************************************************/
10c2c66affSColin Finck 
11c2c66affSColin Finck #include "sacdrv.h"
12c2c66affSColin Finck 
13c2c66affSColin Finck #include <ndk/rtlfuncs.h>
14c2c66affSColin Finck 
15c2c66affSColin Finck /* GLOBALS ********************************************************************/
16c2c66affSColin Finck 
17c2c66affSColin Finck PCHAR Utf8ConversionBuffer;
18c2c66affSColin Finck ULONG Utf8ConversionBufferSize = PAGE_SIZE;
19c2c66affSColin Finck 
20c2c66affSColin Finck PSAC_MACHINE_INFO MachineInformation;
21c2c66affSColin Finck 
22c2c66affSColin Finck PVOID RequestSacCmdEventObjectBody;
23c2c66affSColin Finck PKEVENT RequestSacCmdEventWaitObjectBody;
24c2c66affSColin Finck PVOID RequestSacCmdSuccessEventObjectBody;
25c2c66affSColin Finck PKEVENT RequestSacCmdSuccessEventWaitObjectBody;
26c2c66affSColin Finck PVOID RequestSacCmdFailureEventObjectBody;
27c2c66affSColin Finck PKEVENT RequestSacCmdFailureEventWaitObjectBody;
28c2c66affSColin Finck PFILE_OBJECT ServiceProcessFileObject;
29c2c66affSColin Finck BOOLEAN HaveUserModeServiceCmdEventInfo;
30c2c66affSColin Finck 
31c2c66affSColin Finck PSAC_MESSAGE_ENTRY GlobalMessageTable;
32c2c66affSColin Finck ULONG GlobalMessageTableCount;
33c2c66affSColin Finck 
34c2c66affSColin Finck LONG SerialPortConsumerIndex, SerialPortProducerIndex;
35c2c66affSColin Finck PCHAR SerialPortBuffer;
36c2c66affSColin Finck 
37c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
38c2c66affSColin Finck 
39c2c66affSColin Finck BOOLEAN
40c2c66affSColin Finck NTAPI
SacTranslateUtf8ToUnicode(IN CHAR Utf8Char,IN PCHAR Utf8Buffer,OUT PWCHAR Utf8Value)41c2c66affSColin Finck SacTranslateUtf8ToUnicode(IN CHAR Utf8Char,
42c2c66affSColin Finck                           IN PCHAR Utf8Buffer,
43c2c66affSColin Finck                           OUT PWCHAR Utf8Value)
44c2c66affSColin Finck {
45c2c66affSColin Finck     ULONG i;
46c2c66affSColin Finck 
47c2c66affSColin Finck     /* Find out how many valid characters we have in the buffer */
48c2c66affSColin Finck     i = 0;
49c2c66affSColin Finck     while (Utf8Buffer[i++] && (i < 3));
50c2c66affSColin Finck 
51c2c66affSColin Finck     /* If we have at least 3, shift everything by a byte */
52c2c66affSColin Finck     if (i >= 3)
53c2c66affSColin Finck     {
54c2c66affSColin Finck         /* The last input character goes at the end */
55c2c66affSColin Finck         Utf8Buffer[0] = Utf8Buffer[1];
56c2c66affSColin Finck         Utf8Buffer[1] = Utf8Buffer[2];
57c2c66affSColin Finck         Utf8Buffer[2] = Utf8Char;
58c2c66affSColin Finck     }
59c2c66affSColin Finck     else
60c2c66affSColin Finck     {
61c2c66affSColin Finck         /* We don't have more than 3 characters, place the input at the index */
62c2c66affSColin Finck         Utf8Buffer[i] = Utf8Char;
63c2c66affSColin Finck     }
64c2c66affSColin Finck 
65c2c66affSColin Finck     /* Print to debugger */
66c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SacTranslateUtf8ToUnicode - About to decode the UTF8 buffer.\n");
67c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "                                  UTF8[0]: 0x%02lx UTF8[1]: 0x%02lx UTF8[2]: 0x%02lx\n",
68c2c66affSColin Finck             Utf8Buffer[0],
69c2c66affSColin Finck             Utf8Buffer[1],
70c2c66affSColin Finck             Utf8Buffer[2]);
71c2c66affSColin Finck 
72c2c66affSColin Finck     /* Is this a simple ANSI character? */
73c2c66affSColin Finck     if (!(Utf8Char & 0x80))
74c2c66affSColin Finck     {
75c2c66affSColin Finck         /* Return it as Unicode, nothing left to do */
76c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SACDRV: SacTranslateUTf8ToUnicode - Case1\n");
77c2c66affSColin Finck         *Utf8Value = (WCHAR)Utf8Char;
78c2c66affSColin Finck         Utf8Buffer[0] = Utf8Buffer[1];
79c2c66affSColin Finck         Utf8Buffer[1] = Utf8Buffer[2];
80c2c66affSColin Finck         Utf8Buffer[2] = UNICODE_NULL;
81c2c66affSColin Finck         return TRUE;
82c2c66affSColin Finck     }
83c2c66affSColin Finck 
84c2c66affSColin Finck     /* Anything else is not yet supported */
85c2c66affSColin Finck     ASSERT(FALSE);
86c2c66affSColin Finck     return FALSE;
87c2c66affSColin Finck }
88c2c66affSColin Finck 
89c2c66affSColin Finck BOOLEAN
90c2c66affSColin Finck NTAPI
SacTranslateUnicodeToUtf8(IN PWCHAR SourceBuffer,IN ULONG SourceBufferLength,OUT PCHAR DestinationBuffer,IN ULONG DestinationBufferSize,OUT PULONG UTF8Count,OUT PULONG ProcessedCount)91c2c66affSColin Finck SacTranslateUnicodeToUtf8(IN PWCHAR SourceBuffer,
92c2c66affSColin Finck                           IN ULONG SourceBufferLength,
93c2c66affSColin Finck                           OUT PCHAR DestinationBuffer,
94c2c66affSColin Finck                           IN ULONG DestinationBufferSize,
95c2c66affSColin Finck                           OUT PULONG UTF8Count,
96c2c66affSColin Finck                           OUT PULONG ProcessedCount)
97c2c66affSColin Finck {
98c2c66affSColin Finck     *UTF8Count = 0;
99c2c66affSColin Finck     *ProcessedCount = 0;
100c2c66affSColin Finck 
101c2c66affSColin Finck     while ((*SourceBuffer) &&
102c2c66affSColin Finck            (*UTF8Count < DestinationBufferSize) &&
103c2c66affSColin Finck            (*ProcessedCount < SourceBufferLength))
104c2c66affSColin Finck     {
105c2c66affSColin Finck         if (*SourceBuffer & 0xFF80)
106c2c66affSColin Finck         {
107c2c66affSColin Finck             if (*SourceBuffer & 0xF800)
108c2c66affSColin Finck             {
109c2c66affSColin Finck                 if ((*UTF8Count + 3) >= DestinationBufferSize) break;
110c2c66affSColin Finck                 DestinationBuffer[*UTF8Count] = ((*SourceBuffer >> 12) & 0xF) | 0xE0;
111c2c66affSColin Finck                 ++*UTF8Count;
112c2c66affSColin Finck                 DestinationBuffer[*UTF8Count] = ((*SourceBuffer >> 6) & 0x3F) | 0x80;
113c2c66affSColin Finck             }
114c2c66affSColin Finck             else
115c2c66affSColin Finck             {
116c2c66affSColin Finck                 if ((*UTF8Count + 2) >= DestinationBufferSize) break;
117c2c66affSColin Finck                 DestinationBuffer[*UTF8Count] = ((*SourceBuffer >> 6) & 31) | 0xC0;
118c2c66affSColin Finck             }
119c2c66affSColin Finck             ++*UTF8Count;
120c2c66affSColin Finck             DestinationBuffer[*UTF8Count] = (*SourceBuffer & 0x3F) | 0x80;
121c2c66affSColin Finck         }
122c2c66affSColin Finck         else
123c2c66affSColin Finck         {
124c2c66affSColin Finck             DestinationBuffer[*UTF8Count] = (*SourceBuffer & 0x7F);
125c2c66affSColin Finck         }
126c2c66affSColin Finck 
127c2c66affSColin Finck         ++*UTF8Count;
128c2c66affSColin Finck         ++*ProcessedCount;
129c2c66affSColin Finck         ++SourceBuffer;
130c2c66affSColin Finck     }
131c2c66affSColin Finck 
132c2c66affSColin Finck     ASSERT(*ProcessedCount <= SourceBufferLength);
133c2c66affSColin Finck     ASSERT(*UTF8Count <= DestinationBufferSize);
134c2c66affSColin Finck     return TRUE;
135c2c66affSColin Finck }
136c2c66affSColin Finck 
137c2c66affSColin Finck PWCHAR
138c2c66affSColin Finck NTAPI
GetMessage(IN ULONG MessageIndex)139c2c66affSColin Finck GetMessage(IN ULONG MessageIndex)
140c2c66affSColin Finck {
141c2c66affSColin Finck     PSAC_MESSAGE_ENTRY MessageEntry;
142c2c66affSColin Finck     ULONG i;
143c2c66affSColin Finck     PWCHAR MessageData = NULL;
144c2c66affSColin Finck 
145c2c66affSColin Finck     /* Loop all cached messages */
146c2c66affSColin Finck     for (i = 0; i < GlobalMessageTableCount; i++)
147c2c66affSColin Finck     {
148c2c66affSColin Finck         /* Check if this one matches the index */
149c2c66affSColin Finck         MessageEntry = &GlobalMessageTable[i];
150c2c66affSColin Finck         if (MessageEntry->Index == MessageIndex)
151c2c66affSColin Finck         {
152c2c66affSColin Finck             /* It does, return the buffer */
153c2c66affSColin Finck             MessageData = MessageEntry->Buffer;
154c2c66affSColin Finck             break;
155c2c66affSColin Finck         }
156c2c66affSColin Finck     }
157c2c66affSColin Finck 
158c2c66affSColin Finck     /* We should always find it */
159c2c66affSColin Finck     if (!MessageData) ASSERT(FALSE);
160c2c66affSColin Finck     return MessageData;
161c2c66affSColin Finck }
162c2c66affSColin Finck 
163c2c66affSColin Finck NTSTATUS
164c2c66affSColin Finck NTAPI
UTF8EncodeAndSend(IN PWCHAR String)165c2c66affSColin Finck UTF8EncodeAndSend(IN PWCHAR String)
166c2c66affSColin Finck {
167c2c66affSColin Finck     ULONG ProcessedCount, Utf8Count, i;
168c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
169c2c66affSColin Finck 
170c2c66affSColin Finck     /* Call the translator routine */
171c2c66affSColin Finck     if (SacTranslateUnicodeToUtf8(String,
172c2c66affSColin Finck                                   wcslen(String),
173c2c66affSColin Finck                                   Utf8ConversionBuffer,
174c2c66affSColin Finck                                   Utf8ConversionBufferSize,
175c2c66affSColin Finck                                   &Utf8Count,
176c2c66affSColin Finck                                   &ProcessedCount))
177c2c66affSColin Finck     {
178c2c66affSColin Finck         /* Loop every character */
179c2c66affSColin Finck         for (i = 0; i < Utf8Count; i++)
180c2c66affSColin Finck         {
181c2c66affSColin Finck             /* Send it to the terminal */
182c2c66affSColin Finck             Status = HeadlessDispatch(HeadlessCmdPutData,
183c2c66affSColin Finck                                       &Utf8ConversionBuffer[i],
184c2c66affSColin Finck                                       sizeof(Utf8ConversionBuffer[i]),
185c2c66affSColin Finck                                       NULL,
186c2c66affSColin Finck                                       NULL);
187c2c66affSColin Finck             if (!NT_SUCCESS(Status)) break;
188c2c66affSColin Finck         }
189c2c66affSColin Finck     }
190c2c66affSColin Finck     else
191c2c66affSColin Finck     {
192c2c66affSColin Finck         /* Conversion failed */
193c2c66affSColin Finck         Status = STATUS_UNSUCCESSFUL;
194c2c66affSColin Finck     }
195c2c66affSColin Finck 
196c2c66affSColin Finck     /* All done */
197c2c66affSColin Finck     return Status;
198c2c66affSColin Finck }
199c2c66affSColin Finck 
200c2c66affSColin Finck VOID
201c2c66affSColin Finck NTAPI
SacFormatMessage(IN PWCHAR FormattedString,IN PWCHAR MessageString,IN ULONG MessageSize)202c2c66affSColin Finck SacFormatMessage(IN PWCHAR FormattedString,
203c2c66affSColin Finck                  IN PWCHAR MessageString,
204c2c66affSColin Finck                  IN ULONG MessageSize)
205c2c66affSColin Finck {
206c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Entering.\n");
207c2c66affSColin Finck 
208c2c66affSColin Finck     /* Check if any of the parameters are NULL or zero */
209c2c66affSColin Finck     if (!(MessageString) || !(FormattedString) || !(MessageSize))
210c2c66affSColin Finck     {
211c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Exiting with invalid parameters.\n");
212c2c66affSColin Finck         return;
213c2c66affSColin Finck     }
214c2c66affSColin Finck 
215c2c66affSColin Finck     /* Keep going as long as there's still characters */
216c2c66affSColin Finck     while ((MessageString[0]) && (MessageSize))
217c2c66affSColin Finck     {
218c2c66affSColin Finck         /* Is it a non-formatting character? */
219c2c66affSColin Finck         if (MessageString[0] != L'%')
220c2c66affSColin Finck         {
221c2c66affSColin Finck             /* Just write it back into the buffer and keep going */
222c2c66affSColin Finck             *FormattedString++ = MessageString[0];
223c2c66affSColin Finck             MessageString++;
224c2c66affSColin Finck         }
225c2c66affSColin Finck         else
226c2c66affSColin Finck         {
227c2c66affSColin Finck             /* Go over the format characters we recognize */
228c2c66affSColin Finck             switch (MessageString[1])
229c2c66affSColin Finck             {
230c2c66affSColin Finck                 case L'0':
231c2c66affSColin Finck                     *FormattedString = UNICODE_NULL;
232c2c66affSColin Finck                     return;
233c2c66affSColin Finck 
234c2c66affSColin Finck                 case L'%':
235c2c66affSColin Finck                     *FormattedString++ = L'%';
236c2c66affSColin Finck                     break;
237c2c66affSColin Finck 
238c2c66affSColin Finck                 case L'\\':
239c2c66affSColin Finck                     *FormattedString++ = L'\r';
240c2c66affSColin Finck                     *FormattedString++ = L'\n';
241c2c66affSColin Finck                     break;
242c2c66affSColin Finck 
243c2c66affSColin Finck                 case L'r':
244c2c66affSColin Finck                     *FormattedString++ = L'\r';
245c2c66affSColin Finck                     break;
246c2c66affSColin Finck 
247c2c66affSColin Finck                 case L'b':
248c2c66affSColin Finck                     *FormattedString++ = L' ';
249c2c66affSColin Finck                     break;
250c2c66affSColin Finck 
251c2c66affSColin Finck                 case L'.':
252c2c66affSColin Finck                     *FormattedString++ = L'.';
253c2c66affSColin Finck                     break;
254c2c66affSColin Finck 
255c2c66affSColin Finck                 case L'!':
256c2c66affSColin Finck                     *FormattedString++ = L'!';
257c2c66affSColin Finck                     break;
258c2c66affSColin Finck 
259c2c66affSColin Finck                 default:
260c2c66affSColin Finck                     /* Only move forward one character */
261c2c66affSColin Finck                     MessageString--;
262c2c66affSColin Finck                     break;
263c2c66affSColin Finck             }
264c2c66affSColin Finck 
265c2c66affSColin Finck             /* Move forward two characters */
266c2c66affSColin Finck             MessageString += 2;
267c2c66affSColin Finck         }
268c2c66affSColin Finck 
269c2c66affSColin Finck         /* Move to the next character*/
270c2c66affSColin Finck         MessageSize--;
271c2c66affSColin Finck     }
272c2c66affSColin Finck 
273c2c66affSColin Finck     /* All done */
274c2c66affSColin Finck     *FormattedString = UNICODE_NULL;
275c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SacFormatMessage: Exiting.\n");
276c2c66affSColin Finck }
277c2c66affSColin Finck 
278c2c66affSColin Finck NTSTATUS
279c2c66affSColin Finck NTAPI
PreloadGlobalMessageTable(IN PVOID ImageBase)280c2c66affSColin Finck PreloadGlobalMessageTable(IN PVOID ImageBase)
281c2c66affSColin Finck {
282c2c66affSColin Finck     NTSTATUS Status, Status2;
283c2c66affSColin Finck     ULONG MessageId, TotalLength, TextSize, i;
284c2c66affSColin Finck     PWCHAR StringBuffer;
285c2c66affSColin Finck     PMESSAGE_RESOURCE_ENTRY MessageEntry;
286c2c66affSColin Finck     PAGED_CODE();
287c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC PreloadGlobalMessageTable: Entering.\n");
288c2c66affSColin Finck 
289c2c66affSColin Finck     /* Nothing to do if we already have a table */
290c2c66affSColin Finck     Status = STATUS_SUCCESS;
291c2c66affSColin Finck     if (GlobalMessageTable) goto Exit;
292c2c66affSColin Finck 
293c2c66affSColin Finck     /* Loop through up to 200 messages */
294c2c66affSColin Finck     TotalLength = 0;
295c2c66affSColin Finck     for (MessageId = 1; MessageId != SAC_MAX_MESSAGES; MessageId++)
296c2c66affSColin Finck     {
297c2c66affSColin Finck         /* Find this message ID in the string table*/
298c2c66affSColin Finck         Status2 = RtlFindMessage(ImageBase,
299c2c66affSColin Finck                                  11,
300c2c66affSColin Finck                                  LANG_NEUTRAL,
301c2c66affSColin Finck                                  MessageId,
302c2c66affSColin Finck                                  &MessageEntry);
303c2c66affSColin Finck         if (NT_SUCCESS(Status2))
304c2c66affSColin Finck         {
305c2c66affSColin Finck             /* Make sure it's Unicode */
306c2c66affSColin Finck             ASSERT(MessageEntry->Flags & MESSAGE_RESOURCE_UNICODE);
307c2c66affSColin Finck 
308c2c66affSColin Finck             /* Remove the space taken up by the OS header, and add our own */
309c2c66affSColin Finck             TotalLength += MessageEntry->Length -
310c2c66affSColin Finck                            FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text) +
311c2c66affSColin Finck                            sizeof(SAC_MESSAGE_ENTRY);
312c2c66affSColin Finck 
313c2c66affSColin Finck             /* One more in the table */
314c2c66affSColin Finck             GlobalMessageTableCount++;
315c2c66affSColin Finck         }
316c2c66affSColin Finck     }
317c2c66affSColin Finck 
318c2c66affSColin Finck     /* We should've found at least one message... */
319c2c66affSColin Finck     if (!TotalLength)
320c2c66affSColin Finck     {
321c2c66affSColin Finck         /* Bail out otherwise */
322c2c66affSColin Finck         SAC_DBG(SAC_DBG_INIT, "SAC PreloadGlobalMessageTable: No Messages.\n");
323c2c66affSColin Finck         Status = STATUS_INVALID_PARAMETER;
324c2c66affSColin Finck         goto Exit;
325c2c66affSColin Finck     }
326c2c66affSColin Finck 
327c2c66affSColin Finck     /* Allocate space for the buffers and headers */
328c2c66affSColin Finck     GlobalMessageTable = SacAllocatePool(TotalLength, GLOBAL_BLOCK_TAG);
329c2c66affSColin Finck     if (!GlobalMessageTable)
330c2c66affSColin Finck     {
331c2c66affSColin Finck         /* Bail out if we couldn't allocate it */
332c2c66affSColin Finck         Status = STATUS_NO_MEMORY;
333c2c66affSColin Finck         goto Exit;
334c2c66affSColin Finck     }
335c2c66affSColin Finck 
336c2c66affSColin Finck     /* All the buffers are going to be at the end of the table */
337c2c66affSColin Finck     StringBuffer = (PWCHAR)(&GlobalMessageTable[GlobalMessageTableCount]);
338c2c66affSColin Finck 
339c2c66affSColin Finck     /* Now loop over our entries again */
340c2c66affSColin Finck     for (i = 0, MessageId = 1; MessageId != SAC_MAX_MESSAGES; MessageId++)
341c2c66affSColin Finck     {
342c2c66affSColin Finck         /* Make sure the message is still there...! */
343c2c66affSColin Finck         Status2 = RtlFindMessage(ImageBase,
344c2c66affSColin Finck                                  11,
345c2c66affSColin Finck                                  LANG_NEUTRAL,
346c2c66affSColin Finck                                  MessageId,
347c2c66affSColin Finck                                  &MessageEntry);
348c2c66affSColin Finck         if (NT_SUCCESS(Status2))
349c2c66affSColin Finck         {
350c2c66affSColin Finck             /* Write the entry in the message table*/
351c2c66affSColin Finck             GlobalMessageTable[i].Index = MessageId;
352c2c66affSColin Finck             GlobalMessageTable[i].Buffer = StringBuffer;
353c2c66affSColin Finck 
354c2c66affSColin Finck             /* The structure includes the size of the header, elide it */
355c2c66affSColin Finck             TextSize = MessageEntry->Length -
356c2c66affSColin Finck                        FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text);
357c2c66affSColin Finck 
358c2c66affSColin Finck             /* Format the message into the entry. It should be same or smaller */
359c2c66affSColin Finck             SacFormatMessage(StringBuffer, (PWCHAR)MessageEntry->Text, TextSize);
360c2c66affSColin Finck             ASSERT((ULONG)(wcslen(StringBuffer)*sizeof(WCHAR)) <= TextSize);
361c2c66affSColin Finck 
362c2c66affSColin Finck             /* Move to the next buffer space */
363c2c66affSColin Finck             StringBuffer += (TextSize / sizeof(WCHAR));
364c2c66affSColin Finck 
365c2c66affSColin Finck             /* Move to the next entry, make sure the status is full success */
366c2c66affSColin Finck             i++;
367c2c66affSColin Finck             Status = STATUS_SUCCESS;
368c2c66affSColin Finck         }
369c2c66affSColin Finck     }
370c2c66affSColin Finck 
371c2c66affSColin Finck Exit:
372c2c66affSColin Finck     /* All done, return the status code */
373c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC TearDownGlobalMessageTable: Exiting with status 0x%0x\n", Status);
374c2c66affSColin Finck     return Status;
375c2c66affSColin Finck }
376c2c66affSColin Finck 
377c2c66affSColin Finck NTSTATUS
378c2c66affSColin Finck NTAPI
TearDownGlobalMessageTable(VOID)379c2c66affSColin Finck TearDownGlobalMessageTable(VOID)
380c2c66affSColin Finck {
381c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC TearDownGlobalMessageTable: Entering.\n");
382c2c66affSColin Finck 
383c2c66affSColin Finck     /* Free the table if one existed */
384c2c66affSColin Finck     if (GlobalMessageTable) SacFreePool(GlobalMessageTable);
385c2c66affSColin Finck 
386c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC TearDownGlobalMessageTable: Exiting\n");
387c2c66affSColin Finck     return STATUS_SUCCESS;
388c2c66affSColin Finck }
389c2c66affSColin Finck 
390c2c66affSColin Finck NTSTATUS
391c2c66affSColin Finck NTAPI
GetRegistryValueBuffer(IN PCWSTR KeyName,IN PWCHAR ValueName,IN PKEY_VALUE_PARTIAL_INFORMATION * Buffer)392c2c66affSColin Finck GetRegistryValueBuffer(IN PCWSTR KeyName,
393c2c66affSColin Finck                        IN PWCHAR ValueName,
394c2c66affSColin Finck                        IN PKEY_VALUE_PARTIAL_INFORMATION* Buffer)
395c2c66affSColin Finck {
396c2c66affSColin Finck     NTSTATUS Status;
397c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
398c2c66affSColin Finck     UNICODE_STRING DestinationString;
399c2c66affSColin Finck     HANDLE Handle;
4009e066abeSTimo Kreuzer     ULONG ResultLength = 0;
401c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: Entering.\n");
402c2c66affSColin Finck     CHECK_PARAMETER1(KeyName);
403c2c66affSColin Finck     CHECK_PARAMETER2(ValueName);
404c2c66affSColin Finck 
405c2c66affSColin Finck     /* Open the specified key */
406c2c66affSColin Finck     RtlInitUnicodeString(&DestinationString, KeyName);
407c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
408c2c66affSColin Finck                                &DestinationString,
409*ed125de9SSerge Gautherie                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
410c2c66affSColin Finck                                NULL,
411c2c66affSColin Finck                                NULL);
412c2c66affSColin Finck     Status = ZwOpenKey(&Handle,
413c2c66affSColin Finck                        KEY_WRITE | SYNCHRONIZE | KEY_READ,
414c2c66affSColin Finck                        &ObjectAttributes);
415c2c66affSColin Finck     if (!NT_SUCCESS(Status))
416c2c66affSColin Finck     {
417c2c66affSColin Finck         /* Bail out on failure */
418c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: failed ZwOpenKey: %X.\n", Status);
419c2c66affSColin Finck         return Status;
420c2c66affSColin Finck     }
421c2c66affSColin Finck 
422c2c66affSColin Finck     /* Query the size of the key */
423c2c66affSColin Finck     RtlInitUnicodeString(&DestinationString, ValueName);
424c2c66affSColin Finck     Status = ZwQueryValueKey(Handle,
425c2c66affSColin Finck                              &DestinationString,
426c2c66affSColin Finck                              KeyValuePartialInformation,
427c2c66affSColin Finck                              NULL,
428c2c66affSColin Finck                              0,
429c2c66affSColin Finck                              &ResultLength);
430*ed125de9SSerge Gautherie     if (!ResultLength)
431*ed125de9SSerge Gautherie         goto Quit;
432c2c66affSColin Finck 
433c2c66affSColin Finck     /* Allocate the buffer for the partial info structure and our integer data */
434c2c66affSColin Finck     ResultLength += sizeof(ULONG);
435c2c66affSColin Finck     *Buffer = SacAllocatePool(ResultLength, GLOBAL_BLOCK_TAG);
436c2c66affSColin Finck     if (!*Buffer)
437c2c66affSColin Finck     {
438c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: failed allocation\n");
439*ed125de9SSerge Gautherie         goto Quit;
440c2c66affSColin Finck     }
441c2c66affSColin Finck 
442c2c66affSColin Finck     /* Now read the data */
443c2c66affSColin Finck     Status = ZwQueryValueKey(Handle,
444c2c66affSColin Finck                              &DestinationString,
445c2c66affSColin Finck                              KeyValuePartialInformation,
446c2c66affSColin Finck                              *Buffer,
447c2c66affSColin Finck                              ResultLength,
448c2c66affSColin Finck                              &ResultLength);
449c2c66affSColin Finck     if (!NT_SUCCESS(Status))
450c2c66affSColin Finck     {
451c2c66affSColin Finck         /* Free the buffer if we couldn't read the data */
452c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: failed ZwQueryValueKey: %X.\n", Status);
453c2c66affSColin Finck         SacFreePool(*Buffer);
454c2c66affSColin Finck     }
455c2c66affSColin Finck 
456*ed125de9SSerge Gautherie Quit:
457*ed125de9SSerge Gautherie     /* Close the handle and exit */
458*ed125de9SSerge Gautherie     ZwClose(Handle);
459*ed125de9SSerge Gautherie     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC GetRegistryValueBuffer: Exiting.\n");
460c2c66affSColin Finck     return Status;
461c2c66affSColin Finck }
462c2c66affSColin Finck 
463c2c66affSColin Finck NTSTATUS
464c2c66affSColin Finck NTAPI
SetRegistryValue(IN PCWSTR KeyName,IN PWCHAR ValueName,IN ULONG Type,IN PVOID Data,IN ULONG DataSize)465c2c66affSColin Finck SetRegistryValue(IN PCWSTR KeyName,
466c2c66affSColin Finck                  IN PWCHAR ValueName,
467c2c66affSColin Finck                  IN ULONG Type,
468c2c66affSColin Finck                  IN PVOID Data,
469c2c66affSColin Finck                  IN ULONG DataSize)
470c2c66affSColin Finck {
471c2c66affSColin Finck     NTSTATUS Status;
472c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
473c2c66affSColin Finck     UNICODE_STRING DestinationString;
474c2c66affSColin Finck     HANDLE Handle;
475c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: Entering.\n");
476c2c66affSColin Finck     CHECK_PARAMETER1(KeyName);
477c2c66affSColin Finck     CHECK_PARAMETER2(ValueName);
478c2c66affSColin Finck     CHECK_PARAMETER4(Data);
479c2c66affSColin Finck 
480c2c66affSColin Finck     /* Open the specified key */
481c2c66affSColin Finck     RtlInitUnicodeString(&DestinationString, KeyName);
482c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
483c2c66affSColin Finck                                &DestinationString,
484*ed125de9SSerge Gautherie                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
485c2c66affSColin Finck                                NULL,
486c2c66affSColin Finck                                NULL);
487c2c66affSColin Finck     Status = ZwOpenKey(&Handle,
488c2c66affSColin Finck                        KEY_WRITE | SYNCHRONIZE | KEY_READ,
489c2c66affSColin Finck                        &ObjectAttributes);
490c2c66affSColin Finck     if (!NT_SUCCESS(Status))
491c2c66affSColin Finck     {
492c2c66affSColin Finck         /* Bail out on failure */
493c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: failed ZwOpenKey: %X.\n", Status);
494c2c66affSColin Finck         return Status;
495c2c66affSColin Finck     }
496c2c66affSColin Finck 
497c2c66affSColin Finck     /* Set the specified value */
498c2c66affSColin Finck     RtlInitUnicodeString(&DestinationString, ValueName);
499c2c66affSColin Finck     Status = ZwSetValueKey(Handle, &DestinationString, 0, Type, Data, DataSize);
500c2c66affSColin Finck     if (!NT_SUCCESS(Status))
501c2c66affSColin Finck     {
502c2c66affSColin Finck         /* Print error on failure */
503c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: failed ZwSetValueKey: %X.\n", Status);
504c2c66affSColin Finck     }
505c2c66affSColin Finck 
506c2c66affSColin Finck     /* Close the handle and exit */
507*ed125de9SSerge Gautherie     ZwClose(Handle);
508c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC SetRegistryValue: Exiting.\n");
509c2c66affSColin Finck     return Status;
510c2c66affSColin Finck }
511c2c66affSColin Finck 
512c2c66affSColin Finck NTSTATUS
513c2c66affSColin Finck NTAPI
CopyRegistryValueData(IN PVOID * Buffer,IN PKEY_VALUE_PARTIAL_INFORMATION PartialInfo)514c2c66affSColin Finck CopyRegistryValueData(IN PVOID* Buffer,
515c2c66affSColin Finck                       IN PKEY_VALUE_PARTIAL_INFORMATION PartialInfo)
516c2c66affSColin Finck {
517c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
518c2c66affSColin Finck     CHECK_PARAMETER1(Buffer);
519c2c66affSColin Finck     CHECK_PARAMETER2(PartialInfo);
520c2c66affSColin Finck 
521c2c66affSColin Finck     /* Allocate space for registry data */
522c2c66affSColin Finck     *Buffer = SacAllocatePool(PartialInfo->DataLength, GLOBAL_BLOCK_TAG);
523c2c66affSColin Finck     if (*Buffer)
524c2c66affSColin Finck     {
525c2c66affSColin Finck         /* Copy the data into the buffer */
526c2c66affSColin Finck         RtlCopyMemory(*Buffer, PartialInfo->Data, PartialInfo->DataLength);
527c2c66affSColin Finck     }
528c2c66affSColin Finck     else
529c2c66affSColin Finck     {
530c2c66affSColin Finck         /* Set the correct error code */
531c2c66affSColin Finck         SAC_DBG(SAC_DBG_UTIL, "SAC CopyRegistryValueBuffer: Failed ALLOCATE.\n");
532c2c66affSColin Finck         Status = STATUS_NO_MEMORY;
533c2c66affSColin Finck     }
534c2c66affSColin Finck 
535c2c66affSColin Finck     /* Return the result */
536c2c66affSColin Finck     return Status;
537c2c66affSColin Finck }
538c2c66affSColin Finck 
539c2c66affSColin Finck NTSTATUS
540c2c66affSColin Finck NTAPI
TranslateMachineInformationXML(IN PWCHAR * Buffer,IN PWCHAR ExtraData)541c2c66affSColin Finck TranslateMachineInformationXML(IN PWCHAR *Buffer,
542c2c66affSColin Finck                                IN PWCHAR ExtraData)
543c2c66affSColin Finck {
544c2c66affSColin Finck     NTSTATUS Status;
5459e066abeSTimo Kreuzer     SIZE_T Size;
546c2c66affSColin Finck     PWCHAR p;
547c2c66affSColin Finck     CHECK_PARAMETER1(Buffer);
548c2c66affSColin Finck 
549c2c66affSColin Finck     /* Start by believing the world is beautiful */
550c2c66affSColin Finck     Status = STATUS_SUCCESS;
551c2c66affSColin Finck 
552c2c66affSColin Finck     /* First, the header */
553c2c66affSColin Finck     Size = wcslen(L"<machine-info>\r\n");
554c2c66affSColin Finck 
555c2c66affSColin Finck     /* Do we have a machine name? */
556c2c66affSColin Finck     if (MachineInformation->MachineName)
557c2c66affSColin Finck     {
558c2c66affSColin Finck         /* Go and add it in */
559c2c66affSColin Finck         Size += wcslen(MachineInformation->MachineName);
560c2c66affSColin Finck         Size += wcslen(L"<name>%s</name>\r\n");
561c2c66affSColin Finck     }
562c2c66affSColin Finck 
563c2c66affSColin Finck     /* Do we have a GUID? */
564c2c66affSColin Finck     if (MachineInformation->MachineGuid)
565c2c66affSColin Finck     {
566c2c66affSColin Finck         /* Go and add it in */
567c2c66affSColin Finck         Size += wcslen(MachineInformation->MachineGuid);
568c2c66affSColin Finck         Size += wcslen(L"<guid>%s</guid>\r\n");
569c2c66affSColin Finck     }
570c2c66affSColin Finck 
571c2c66affSColin Finck     /* Do we know the processor? */
572c2c66affSColin Finck     if (MachineInformation->ProcessorArchitecture)
573c2c66affSColin Finck     {
574c2c66affSColin Finck         /* Go and add it in */
575c2c66affSColin Finck         Size += wcslen(MachineInformation->ProcessorArchitecture);
576c2c66affSColin Finck         Size += wcslen(L"<processor-architecture>%s</processor-architecture>\r\n");
577c2c66affSColin Finck     }
578c2c66affSColin Finck 
579c2c66affSColin Finck     /* Do we have the version? */
580c2c66affSColin Finck     if (MachineInformation->MajorVersion)
581c2c66affSColin Finck     {
582c2c66affSColin Finck         /* Go and add it in */
583c2c66affSColin Finck         Size += wcslen(MachineInformation->MajorVersion);
584c2c66affSColin Finck         Size += wcslen(L"<os-version>%s</os-version>\r\n");
585c2c66affSColin Finck     }
586c2c66affSColin Finck 
587c2c66affSColin Finck     /* Do we have the build? */
588c2c66affSColin Finck     if (MachineInformation->BuildNumber)
589c2c66affSColin Finck     {
590c2c66affSColin Finck         /* Go and add it in */
591c2c66affSColin Finck         Size += wcslen(MachineInformation->BuildNumber);
592c2c66affSColin Finck         Size += wcslen(L"<os-build-number>%s</os-build-number>\r\n");
593c2c66affSColin Finck     }
594c2c66affSColin Finck 
595c2c66affSColin Finck     /* Do we have the product type? */
596c2c66affSColin Finck     if (MachineInformation->ProductType)
597c2c66affSColin Finck     {
598c2c66affSColin Finck         /* Go and add it in */
599c2c66affSColin Finck         Size += wcslen(MachineInformation->ProductType);
600c2c66affSColin Finck         Size += wcslen(L"<os-product>%s</os-product>\r\n");
601c2c66affSColin Finck     }
602c2c66affSColin Finck 
603c2c66affSColin Finck     /* Do we have a service pack? */
604c2c66affSColin Finck     if (MachineInformation->ServicePack)
605c2c66affSColin Finck     {
606c2c66affSColin Finck         /* Go and add it in */
607c2c66affSColin Finck         Size += wcslen(MachineInformation->ServicePack);
608c2c66affSColin Finck         Size += wcslen(L"<os-service-pack>%s</os-service-pack>\r\n");
609c2c66affSColin Finck     }
610c2c66affSColin Finck 
611c2c66affSColin Finck     /* Anything else we need to know? Add it in too */
612c2c66affSColin Finck     if (ExtraData) Size += wcslen(ExtraData);
613c2c66affSColin Finck 
614c2c66affSColin Finck     /* Finally, add the footer */
615c2c66affSColin Finck     Size += wcslen(L"</machine-info>\r\n");
616c2c66affSColin Finck 
617c2c66affSColin Finck     /* Convert to bytes and add a NULL */
618c2c66affSColin Finck     Size += sizeof(ANSI_NULL);
619c2c66affSColin Finck     Size *= sizeof(WCHAR);
620c2c66affSColin Finck 
621c2c66affSColin Finck     /* Allocate space for the buffer */
622c2c66affSColin Finck     p = SacAllocatePool(Size, GLOBAL_BLOCK_TAG);
623c2c66affSColin Finck     *Buffer = p;
624c2c66affSColin Finck     if (!p) return STATUS_NO_MEMORY;
625c2c66affSColin Finck 
626c2c66affSColin Finck     wcscpy(p, L"<machine-info>\r\n");
627c2c66affSColin Finck     p += wcslen(L"<machine-info>\r\n");
628c2c66affSColin Finck 
629c2c66affSColin Finck     if (MachineInformation->MachineName)
630c2c66affSColin Finck     {
631c2c66affSColin Finck         p += swprintf(p,
632c2c66affSColin Finck                       L"<name>%s</name>\r\n",
633c2c66affSColin Finck                       MachineInformation->MachineName);
634c2c66affSColin Finck     }
635c2c66affSColin Finck 
636c2c66affSColin Finck     if (MachineInformation->MachineGuid)
637c2c66affSColin Finck     {
638c2c66affSColin Finck         p += swprintf(p,
639c2c66affSColin Finck                       L"<guid>%s</guid>\r\n",
640c2c66affSColin Finck                       MachineInformation->MachineGuid);
641c2c66affSColin Finck     }
642c2c66affSColin Finck 
643c2c66affSColin Finck     if (MachineInformation->ProcessorArchitecture)
644c2c66affSColin Finck     {
645c2c66affSColin Finck         p += swprintf(p,
646c2c66affSColin Finck                       L"<processor-architecture>%s</processor-architecture>\r\n",
647c2c66affSColin Finck                       MachineInformation->ProcessorArchitecture);
648c2c66affSColin Finck     }
649c2c66affSColin Finck 
650c2c66affSColin Finck     if (MachineInformation->MajorVersion)
651c2c66affSColin Finck     {
652c2c66affSColin Finck         p += swprintf(p,
653c2c66affSColin Finck                       L"<os-version>%s</os-version>\r\n",
654c2c66affSColin Finck                       MachineInformation->MajorVersion);
655c2c66affSColin Finck     }
656c2c66affSColin Finck 
657c2c66affSColin Finck     if (MachineInformation->BuildNumber)
658c2c66affSColin Finck     {
659c2c66affSColin Finck         p += swprintf(p,
660c2c66affSColin Finck                       L"<os-build-number>%s</os-build-number>\r\n",
661c2c66affSColin Finck                       MachineInformation->BuildNumber);
662c2c66affSColin Finck     }
663c2c66affSColin Finck 
664c2c66affSColin Finck     if (MachineInformation->ProductType)
665c2c66affSColin Finck     {
666c2c66affSColin Finck         p += swprintf(p,
667c2c66affSColin Finck                       L"<os-product>%s</os-product>\r\n",
668c2c66affSColin Finck                       MachineInformation->ProductType);
669c2c66affSColin Finck     }
670c2c66affSColin Finck 
671c2c66affSColin Finck     if (MachineInformation->ServicePack)
672c2c66affSColin Finck     {
673c2c66affSColin Finck         p += swprintf(p,
674c2c66affSColin Finck                       L"<os-service-pack>%s</os-service-pack>\r\n",
675c2c66affSColin Finck                       MachineInformation->ServicePack);
676c2c66affSColin Finck     }
677c2c66affSColin Finck 
678c2c66affSColin Finck     if (ExtraData)
679c2c66affSColin Finck     {
680c2c66affSColin Finck         wcscpy(p, ExtraData);
681c2c66affSColin Finck         p += wcslen(ExtraData);
682c2c66affSColin Finck     }
683c2c66affSColin Finck 
684c2c66affSColin Finck     wcscpy(p, L"</machine-info>\r\n");
685c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "MachineInformation: %S\n", *Buffer);
686c2c66affSColin Finck     ASSERT((((ULONG)wcslen(*Buffer) + 1) * sizeof(WCHAR)) <= Size);
687c2c66affSColin Finck     return Status;
688c2c66affSColin Finck }
689c2c66affSColin Finck 
690c2c66affSColin Finck VOID
691c2c66affSColin Finck NTAPI
InitializeMachineInformation(VOID)692c2c66affSColin Finck InitializeMachineInformation(VOID)
693c2c66affSColin Finck {
694c2c66affSColin Finck     NTSTATUS Status;
695c2c66affSColin Finck     PWCHAR GuidString, MajorVersion, ServicePack, BuildNumber, MessageBuffer;
696c2c66affSColin Finck     PWCHAR ProductType;
697c2c66affSColin Finck     ULONG SuiteTypeMessage;
698c2c66affSColin Finck     BOOLEAN SetupInProgress = FALSE;
699c2c66affSColin Finck     GUID SystemGuid;
7009e066abeSTimo Kreuzer     SIZE_T RealSize, Size, OutputSize;
701c2c66affSColin Finck     PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
702c2c66affSColin Finck     RTL_OSVERSIONINFOEXW VersionInformation;
703c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC Initialize Machine Information : Entering.\n");
704c2c66affSColin Finck 
705c2c66affSColin Finck     /* Don't do anything if we already queried this */
706c2c66affSColin Finck     if (MachineInformation)
707c2c66affSColin Finck     {
708c2c66affSColin Finck         SAC_DBG(SAC_DBG_MACHINE, "SAC Initialize Machine Information:: MachineInformationBuffer already initialized.\n");
709c2c66affSColin Finck         return;
710c2c66affSColin Finck     }
711c2c66affSColin Finck 
712c2c66affSColin Finck     /* Allocate the machine information */
713c2c66affSColin Finck     MachineInformation = SacAllocatePool(sizeof(*MachineInformation),
714c2c66affSColin Finck                                          GLOBAL_BLOCK_TAG);
715c2c66affSColin Finck     if (!MachineInformation)
716c2c66affSColin Finck     {
717c2c66affSColin Finck         goto Fail;
718c2c66affSColin Finck     }
719c2c66affSColin Finck 
720c2c66affSColin Finck     /* Zero it out for now */
721c2c66affSColin Finck     RtlZeroMemory(MachineInformation, sizeof(*MachineInformation));
722c2c66affSColin Finck 
723c2c66affSColin Finck     /* Query OS version */
724c2c66affSColin Finck     RtlZeroMemory(&VersionInformation, sizeof(VersionInformation));
725c2c66affSColin Finck     VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
726c2c66affSColin Finck     Status = RtlGetVersion((PRTL_OSVERSIONINFOW)&VersionInformation);
727c2c66affSColin Finck     if (!NT_SUCCESS(Status))
728c2c66affSColin Finck     {
729c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (2).\n");
730c2c66affSColin Finck         goto Fail;
731c2c66affSColin Finck     }
732c2c66affSColin Finck 
733c2c66affSColin Finck     /* Check if setup is in progress */
734c2c66affSColin Finck     Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\Setup",
735c2c66affSColin Finck                                     L"SystemSetupInProgress",
736c2c66affSColin Finck                                     &PartialInfo);
737c2c66affSColin Finck     if (NT_SUCCESS(Status))
738c2c66affSColin Finck     {
739c2c66affSColin Finck         /* The key is there, is the value set? */
740c2c66affSColin Finck         if (*(PULONG)PartialInfo->Data) SetupInProgress = TRUE;
741c2c66affSColin Finck         SacFreePool(PartialInfo);
742c2c66affSColin Finck         if (SetupInProgress)
743c2c66affSColin Finck         {
744c2c66affSColin Finck             /* Yes, so we'll use a special hostname to identify this */
745c2c66affSColin Finck             MessageBuffer = GetMessage(SAC_UNINITIALIZED_MSG);
746c2c66affSColin Finck             Size = wcslen(MessageBuffer);
747c2c66affSColin Finck             ASSERT(Size > 0);
748c2c66affSColin Finck             RealSize = Size * sizeof(WCHAR) + sizeof(UNICODE_NULL);
749c2c66affSColin Finck 
750c2c66affSColin Finck             /* Make room for it and copy it in there */
751c2c66affSColin Finck             MachineInformation->MachineName = SacAllocatePool(RealSize,
752c2c66affSColin Finck                                                               GLOBAL_BLOCK_TAG);
753c2c66affSColin Finck             if (MachineInformation->MachineName)
754c2c66affSColin Finck             {
755c2c66affSColin Finck                 wcscpy(MachineInformation->MachineName, MessageBuffer);
756c2c66affSColin Finck             }
757c2c66affSColin Finck         }
758c2c66affSColin Finck     }
759c2c66affSColin Finck 
760c2c66affSColin Finck     /* If we are not in setup mode, or if we failed to check... */
761c2c66affSColin Finck     if (!SetupInProgress)
762c2c66affSColin Finck     {
763c2c66affSColin Finck         /* Query the computer name */
764c2c66affSColin Finck         Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\"
765c2c66affSColin Finck                                         L"CurrentControlSet\\Control\\"
766c2c66affSColin Finck                                         L"ComputerName\\ComputerName",
767c2c66affSColin Finck                                         L"ComputerName",
768c2c66affSColin Finck                                         &PartialInfo);
769c2c66affSColin Finck         if (!NT_SUCCESS(Status))
770c2c66affSColin Finck         {
771c2c66affSColin Finck             /* It's not critical, but we won't have it */
772c2c66affSColin Finck             SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Failed to get machine name.\n");
773c2c66affSColin Finck         }
774c2c66affSColin Finck         else
775c2c66affSColin Finck         {
776c2c66affSColin Finck             /* We have the name, copy it from the registry */
777c2c66affSColin Finck             Status = CopyRegistryValueData((PVOID*)&MachineInformation->
778c2c66affSColin Finck                                            MachineName,
779c2c66affSColin Finck                                            PartialInfo);
780c2c66affSColin Finck             SacFreePool(PartialInfo);
781c2c66affSColin Finck             if (!NT_SUCCESS(Status))
782c2c66affSColin Finck             {
783c2c66affSColin Finck                 SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (20).\n");
784c2c66affSColin Finck                 goto Fail;
785c2c66affSColin Finck             }
786c2c66affSColin Finck         }
787c2c66affSColin Finck     }
788c2c66affSColin Finck 
789c2c66affSColin Finck     /* Next step, try to get the machine GUID */
790c2c66affSColin Finck     RtlZeroMemory(&SystemGuid, sizeof(SystemGuid));
791c2c66affSColin Finck     OutputSize = sizeof(SystemGuid);
792c2c66affSColin Finck     Status = HeadlessDispatch(HeadlessCmdQueryGUID,
793c2c66affSColin Finck                               NULL,
794c2c66affSColin Finck                               0,
795c2c66affSColin Finck                               &SystemGuid,
796c2c66affSColin Finck                               &OutputSize);
797c2c66affSColin Finck     if (!NT_SUCCESS(Status))
798c2c66affSColin Finck     {
799c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Failed to get Machine GUID.\n");
800c2c66affSColin Finck     }
801c2c66affSColin Finck     else
802c2c66affSColin Finck     {
803c2c66affSColin Finck         /* We have it -- make room for it */
804c2c66affSColin Finck         GuidString = SacAllocatePool(0x50, GLOBAL_BLOCK_TAG);
805c2c66affSColin Finck         if (!GuidString)
806c2c66affSColin Finck         {
807c2c66affSColin Finck             SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (31).\n");
808c2c66affSColin Finck             goto Fail;
809c2c66affSColin Finck         }
810c2c66affSColin Finck 
811c2c66affSColin Finck         /* Build the string with the GUID in it, and save the ppointer to it */
812c2c66affSColin Finck         swprintf(GuidString,
813c2c66affSColin Finck                  L"%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
814c2c66affSColin Finck                  SystemGuid.Data1,
815c2c66affSColin Finck                  SystemGuid.Data2,
816c2c66affSColin Finck                  SystemGuid.Data3,
817c2c66affSColin Finck                  SystemGuid.Data4[0],
818c2c66affSColin Finck                  SystemGuid.Data4[1],
819c2c66affSColin Finck                  SystemGuid.Data4[2],
820c2c66affSColin Finck                  SystemGuid.Data4[3],
821c2c66affSColin Finck                  SystemGuid.Data4[4],
822c2c66affSColin Finck                  SystemGuid.Data4[5],
823c2c66affSColin Finck                  SystemGuid.Data4[6],
824c2c66affSColin Finck                  SystemGuid.Data4[7]);
825c2c66affSColin Finck         MachineInformation->MachineGuid = GuidString;
826c2c66affSColin Finck     }
827c2c66affSColin Finck 
828c2c66affSColin Finck     /* Next, query the processor architecture */
829c2c66affSColin Finck     Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\"
830c2c66affSColin Finck                                     L"CurrentControlSet\\Control\\"
831c2c66affSColin Finck                                     L"Session Manager\\Environment",
832c2c66affSColin Finck                                     L"PROCESSOR_ARCHITECTURE",
833c2c66affSColin Finck                                     &PartialInfo);
834c2c66affSColin Finck     if (!NT_SUCCESS(Status))
835c2c66affSColin Finck     {
836c2c66affSColin Finck         /* It's not critical, but we won't have it */
837c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (30).\n");
838c2c66affSColin Finck     }
839c2c66affSColin Finck     else
840c2c66affSColin Finck     {
841c2c66affSColin Finck         /* We have it! Copy the value from the registry */
842c2c66affSColin Finck         Status = CopyRegistryValueData((PVOID*)&MachineInformation->
843c2c66affSColin Finck                                        ProcessorArchitecture,
844c2c66affSColin Finck                                        PartialInfo);
845c2c66affSColin Finck         SacFreePool(PartialInfo);
846c2c66affSColin Finck         if (!NT_SUCCESS(Status))
847c2c66affSColin Finck         {
848c2c66affSColin Finck             SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (30).\n");
849c2c66affSColin Finck             goto Fail;
850c2c66affSColin Finck         }
851c2c66affSColin Finck     }
852c2c66affSColin Finck 
853c2c66affSColin Finck     /* Now allocate a buffer for the OS version number */
854c2c66affSColin Finck     MajorVersion = SacAllocatePool(0x18, GLOBAL_BLOCK_TAG);
855c2c66affSColin Finck     if (!MajorVersion)
856c2c66affSColin Finck     {
857c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (50).\n");
858c2c66affSColin Finck         goto Fail;
859c2c66affSColin Finck     }
860c2c66affSColin Finck 
861c2c66affSColin Finck     /* Build the buffer and set a pointer to it */
862c2c66affSColin Finck     swprintf(MajorVersion,
863c2c66affSColin Finck              L"%d.%d",
864c2c66affSColin Finck              VersionInformation.dwMajorVersion,
865c2c66affSColin Finck              VersionInformation.dwMinorVersion);
866c2c66affSColin Finck     MachineInformation->MajorVersion = MajorVersion;
867c2c66affSColin Finck 
868c2c66affSColin Finck     /* Now allocate a buffer for the OS build number */
869c2c66affSColin Finck     BuildNumber = SacAllocatePool(0xC, GLOBAL_BLOCK_TAG);
870c2c66affSColin Finck     if (!BuildNumber)
871c2c66affSColin Finck     {
872c2c66affSColin Finck         SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC InitializeMachineInformation: Exiting (60).\n");
873c2c66affSColin Finck         goto Fail;
874c2c66affSColin Finck     }
875c2c66affSColin Finck 
876c2c66affSColin Finck     /* Build the buffer and set a pointer to it */
877c2c66affSColin Finck     swprintf(BuildNumber, L"%d", VersionInformation.dwBuildNumber);
878c2c66affSColin Finck     MachineInformation->BuildNumber = BuildNumber;
879c2c66affSColin Finck 
880c2c66affSColin Finck     /* Now check what kind of SKU this is */
881c2c66affSColin Finck     if (ExVerifySuite(DataCenter))
882c2c66affSColin Finck     {
883c2c66affSColin Finck         SuiteTypeMessage = SAC_DATACENTER_SUITE_MSG;
884c2c66affSColin Finck     }
885c2c66affSColin Finck     else if (ExVerifySuite(EmbeddedNT))
886c2c66affSColin Finck     {
887c2c66affSColin Finck         SuiteTypeMessage = SAC_EMBEDDED_SUITE_MSG;
888c2c66affSColin Finck     }
889c2c66affSColin Finck     else if (ExVerifySuite(Enterprise))
890c2c66affSColin Finck     {
891c2c66affSColin Finck         SuiteTypeMessage = SAC_ENTERPRISE_SUITE_MSG;
892c2c66affSColin Finck     }
893c2c66affSColin Finck     else
894c2c66affSColin Finck     {
895c2c66affSColin Finck         /* Unknown or perhaps a client SKU */
896c2c66affSColin Finck         SuiteTypeMessage = SAC_NO_SUITE_MSG;
897c2c66affSColin Finck     }
898c2c66affSColin Finck 
899c2c66affSColin Finck     /* Get the string that corresponds to the SKU type */
900c2c66affSColin Finck     MessageBuffer = GetMessage(SuiteTypeMessage);
901c2c66affSColin Finck     if (!MessageBuffer)
902c2c66affSColin Finck     {
903c2c66affSColin Finck         /* We won't have it, but this isn't critical */
904c2c66affSColin Finck         SAC_DBG(SAC_DBG_INIT, "SAC InitializeMachineInformation: Failed to get product type.\n");
905c2c66affSColin Finck     }
906c2c66affSColin Finck     else
907c2c66affSColin Finck     {
908c2c66affSColin Finck         /* Calculate the size we need to hold the string */
909c2c66affSColin Finck         Size = wcslen(MessageBuffer);
910c2c66affSColin Finck         ASSERT(Size > 0);
911c2c66affSColin Finck         RealSize = Size * sizeof(WCHAR) + sizeof(UNICODE_NULL);
912c2c66affSColin Finck 
913c2c66affSColin Finck         /* Allocate a buffer for it */
914c2c66affSColin Finck         ProductType = SacAllocatePool(RealSize, GLOBAL_BLOCK_TAG);
915c2c66affSColin Finck         if (!ProductType)
916c2c66affSColin Finck         {
917c2c66affSColin Finck             SAC_DBG(SAC_DBG_INIT, "SAC InitializeMachineInformation: Failed product type memory allocation.\n");
918c2c66affSColin Finck             goto Fail;
919c2c66affSColin Finck         }
920c2c66affSColin Finck 
921c2c66affSColin Finck         /* Copy the string and set the pointer */
922c2c66affSColin Finck         RtlCopyMemory(ProductType, MessageBuffer, RealSize);
923c2c66affSColin Finck         MachineInformation->ProductType = ProductType;
924c2c66affSColin Finck     }
925c2c66affSColin Finck 
926c2c66affSColin Finck     /* Check if this is a SP version or RTM version */
927c2c66affSColin Finck     if (VersionInformation.wServicePackMajor)
928c2c66affSColin Finck     {
929c2c66affSColin Finck         /* This is a service pack, allocate a buffer for the version */
930c2c66affSColin Finck         ServicePack = SacAllocatePool(0x18, GLOBAL_BLOCK_TAG);
931c2c66affSColin Finck         if (ServicePack)
932c2c66affSColin Finck         {
933c2c66affSColin Finck             /* Build the buffer and set a pointer to it */
934c2c66affSColin Finck             swprintf(ServicePack,
935c2c66affSColin Finck                      L"%d.%d",
936c2c66affSColin Finck                      VersionInformation.wServicePackMajor,
937c2c66affSColin Finck                      VersionInformation.wServicePackMinor);
938c2c66affSColin Finck             MachineInformation->ServicePack = ServicePack;
939c2c66affSColin Finck 
940c2c66affSColin Finck             /* We've collected all the machine info and are done! */
941c2c66affSColin Finck             return;
942c2c66affSColin Finck         }
943c2c66affSColin Finck 
944c2c66affSColin Finck         /* This is the failure path */
945c2c66affSColin Finck         SAC_DBG(SAC_DBG_INIT, "SAC InitializeMachineInformation: Failed service pack memory allocation.\n");
946c2c66affSColin Finck     }
947c2c66affSColin Finck     else
948c2c66affSColin Finck     {
949c2c66affSColin Finck         /* Get a generic string that indicates there's no service pack */
950c2c66affSColin Finck         MessageBuffer = GetMessage(SAC_NO_DATA_MSG);
951c2c66affSColin Finck         Size = wcslen(MessageBuffer);
952c2c66affSColin Finck         ASSERT(Size > 0);
953c2c66affSColin Finck         RealSize = Size * sizeof(WCHAR) + sizeof(UNICODE_NULL);
954c2c66affSColin Finck 
955c2c66affSColin Finck         /* Allocate memory for the "no service pack" string */
956c2c66affSColin Finck         ServicePack = SacAllocatePool(RealSize, GLOBAL_BLOCK_TAG);
957c2c66affSColin Finck         if (ServicePack)
958c2c66affSColin Finck         {
959c2c66affSColin Finck             /* Copy the buffer and set a pointer to it */
960c2c66affSColin Finck             RtlCopyMemory(ServicePack, MessageBuffer, RealSize);
961c2c66affSColin Finck             MachineInformation->ServicePack = ServicePack;
962c2c66affSColin Finck 
963c2c66affSColin Finck             /* We've collected all the machine info and are done! */
964c2c66affSColin Finck             return;
965c2c66affSColin Finck         }
966c2c66affSColin Finck 
967c2c66affSColin Finck         SAC_DBG(SAC_DBG_INIT, "SAC InitializeMachineInformation: Failed service pack memory allocation.\n");
968c2c66affSColin Finck     }
969c2c66affSColin Finck 
970c2c66affSColin Finck Fail:
971c2c66affSColin Finck     /* In the failure path, always cleanup the machine information buffer */
972c2c66affSColin Finck     if (MachineInformation)
973c2c66affSColin Finck     {
974c2c66affSColin Finck         SacFreePool(MachineInformation);
975c2c66affSColin Finck     }
976c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC Initialize Machine Information : Exiting with error.\n");
977c2c66affSColin Finck }
978c2c66affSColin Finck 
979c2c66affSColin Finck NTSTATUS
980c2c66affSColin Finck NTAPI
GetCommandConsoleLaunchingPermission(OUT PBOOLEAN Permission)981c2c66affSColin Finck GetCommandConsoleLaunchingPermission(OUT PBOOLEAN Permission)
982c2c66affSColin Finck {
983c2c66affSColin Finck     NTSTATUS Status;
984c2c66affSColin Finck     PKEY_VALUE_PARTIAL_INFORMATION Dummy;
985c2c66affSColin Finck 
986c2c66affSColin Finck     /* Assume success and read the key */
987c2c66affSColin Finck     *Permission = TRUE;
988c2c66affSColin Finck     Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\sacdrv",
989c2c66affSColin Finck                                     L"DisableCmdSessions",
990c2c66affSColin Finck                                     &Dummy);
991c2c66affSColin Finck     if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
992c2c66affSColin Finck     {
993c2c66affSColin Finck         /* The default is success */
994c2c66affSColin Finck         Status = STATUS_SUCCESS;
995c2c66affSColin Finck     }
996c2c66affSColin Finck     else
997c2c66affSColin Finck     {
998c2c66affSColin Finck         /* Only if the key is present and set, do we disable permission */
999c2c66affSColin Finck         if (NT_SUCCESS(Status)) *Permission = FALSE;
1000c2c66affSColin Finck     }
1001c2c66affSColin Finck 
1002c2c66affSColin Finck     /* Return status */
1003c2c66affSColin Finck     return Status;
1004c2c66affSColin Finck }
1005c2c66affSColin Finck 
1006c2c66affSColin Finck NTSTATUS
1007c2c66affSColin Finck NTAPI
ImposeSacCmdServiceStartTypePolicy(VOID)1008c2c66affSColin Finck ImposeSacCmdServiceStartTypePolicy(VOID)
1009c2c66affSColin Finck {
1010c2c66affSColin Finck     NTSTATUS Status;
1011c2c66affSColin Finck     PKEY_VALUE_PARTIAL_INFORMATION Buffer = NULL;
1012c2c66affSColin Finck     PULONG Data;
1013c2c66affSColin Finck 
1014c2c66affSColin Finck     /* Read the service start type*/
1015c2c66affSColin Finck     Status = GetRegistryValueBuffer(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\sacsvr",
1016c2c66affSColin Finck                                     L"Start",
1017c2c66affSColin Finck                                     &Buffer);
1018c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
1019c2c66affSColin Finck 
1020c2c66affSColin Finck     /* If there's no start type, fail, as this is unusual */
1021c2c66affSColin Finck     if (!Buffer) return STATUS_UNSUCCESSFUL;
1022c2c66affSColin Finck 
1023c2c66affSColin Finck     /* Read the value */
1024c2c66affSColin Finck     Status = CopyRegistryValueData((PVOID*)&Data, Buffer);
1025c2c66affSColin Finck     SacFreePool(Buffer);
1026c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
1027c2c66affSColin Finck 
1028c2c66affSColin Finck     /* Check what the current start type is */
1029c2c66affSColin Finck     switch (*Data)
1030c2c66affSColin Finck     {
1031c2c66affSColin Finck         /* It's boot, system, or disabled */
1032c2c66affSColin Finck         case 1:
1033c2c66affSColin Finck         case 2:
1034c2c66affSColin Finck         case 4:
1035c2c66affSColin Finck             /* Leave it as is */
1036c2c66affSColin Finck             return Status;
1037c2c66affSColin Finck 
1038c2c66affSColin Finck         case 3:
1039c2c66affSColin Finck 
1040c2c66affSColin Finck             /* It's set to automatic, set it to system instead */
1041c2c66affSColin Finck             *Data = 2;
1042c2c66affSColin Finck             Status = SetRegistryValue(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\sacsvr",
1043c2c66affSColin Finck                                       L"Start",
1044c2c66affSColin Finck                                       REG_DWORD,
1045c2c66affSColin Finck                                       Data,
1046c2c66affSColin Finck                                       sizeof(ULONG));
1047c2c66affSColin Finck             if (!NT_SUCCESS(Status))
1048c2c66affSColin Finck             {
1049c2c66affSColin Finck                 SAC_DBG(SAC_DBG_INIT, "SAC ImposeSacCmdServiceStartTypePolicy: Failed SetRegistryValue: %X\n", Status);
1050c2c66affSColin Finck             }
1051c2c66affSColin Finck             break;
1052c2c66affSColin Finck 
1053c2c66affSColin Finck         default:
1054c2c66affSColin Finck             ASSERT(FALSE);
1055c2c66affSColin Finck     }
1056c2c66affSColin Finck 
1057c2c66affSColin Finck     return Status;
1058c2c66affSColin Finck }
1059c2c66affSColin Finck 
1060c2c66affSColin Finck VOID
1061c2c66affSColin Finck NTAPI
InitializeCmdEventInfo(VOID)1062c2c66affSColin Finck InitializeCmdEventInfo(VOID)
1063c2c66affSColin Finck {
1064c2c66affSColin Finck     /* Check if we were already initialized */
1065c2c66affSColin Finck     if (HaveUserModeServiceCmdEventInfo)
1066c2c66affSColin Finck     {
1067c2c66affSColin Finck         /* Full state expected */
1068c2c66affSColin Finck         ASSERT(RequestSacCmdEventObjectBody);
1069c2c66affSColin Finck         ASSERT(RequestSacCmdSuccessEventObjectBody);
1070c2c66affSColin Finck         ASSERT(RequestSacCmdFailureEventObjectBody);
1071c2c66affSColin Finck 
1072c2c66affSColin Finck         /* Dereference each wait object in turn */
1073c2c66affSColin Finck         if (RequestSacCmdEventObjectBody)
1074c2c66affSColin Finck         {
1075c2c66affSColin Finck             ObDereferenceObject(RequestSacCmdEventObjectBody);
1076c2c66affSColin Finck         }
1077c2c66affSColin Finck 
1078c2c66affSColin Finck         if (RequestSacCmdSuccessEventObjectBody)
1079c2c66affSColin Finck         {
1080c2c66affSColin Finck             ObDereferenceObject(RequestSacCmdSuccessEventObjectBody);
1081c2c66affSColin Finck         }
1082c2c66affSColin Finck 
1083c2c66affSColin Finck         if (RequestSacCmdFailureEventObjectBody)
1084c2c66affSColin Finck         {
1085c2c66affSColin Finck             ObDereferenceObject(RequestSacCmdFailureEventObjectBody);
1086c2c66affSColin Finck         }
1087c2c66affSColin Finck     }
1088c2c66affSColin Finck 
1089c2c66affSColin Finck     /* Claer everything */
1090c2c66affSColin Finck     RequestSacCmdEventObjectBody = NULL;
1091c2c66affSColin Finck     RequestSacCmdEventWaitObjectBody = NULL;
1092c2c66affSColin Finck     RequestSacCmdSuccessEventObjectBody = NULL;
1093c2c66affSColin Finck     RequestSacCmdSuccessEventWaitObjectBody = NULL;
1094c2c66affSColin Finck     RequestSacCmdFailureEventObjectBody = NULL;
1095c2c66affSColin Finck     RequestSacCmdFailureEventWaitObjectBody = NULL;
1096c2c66affSColin Finck     ServiceProcessFileObject = NULL;
1097c2c66affSColin Finck 
1098c2c66affSColin Finck     /* Reset state */
1099c2c66affSColin Finck     HaveUserModeServiceCmdEventInfo = FALSE;
1100c2c66affSColin Finck }
1101c2c66affSColin Finck 
1102c2c66affSColin Finck NTSTATUS
1103c2c66affSColin Finck NTAPI
RegisterBlueScreenMachineInformation(VOID)1104c2c66affSColin Finck RegisterBlueScreenMachineInformation(VOID)
1105c2c66affSColin Finck {
1106c2c66affSColin Finck     PWCHAR XmlBuffer;
1107c2c66affSColin Finck     PHEADLESS_CMD_SET_BLUE_SCREEN_DATA BsBuffer;
11089e066abeSTimo Kreuzer     SIZE_T Length, HeaderLength, TotalLength;
1109c2c66affSColin Finck     NTSTATUS Status;
1110c2c66affSColin Finck     ULONG i;
1111c2c66affSColin Finck 
1112c2c66affSColin Finck     /* Create the XML buffer and make sure it's OK */
1113c2c66affSColin Finck     Status = TranslateMachineInformationXML(&XmlBuffer, NULL);
1114c2c66affSColin Finck     CHECK_PARAMETER_WITH_STATUS(NT_SUCCESS(Status), Status);
1115c2c66affSColin Finck     CHECK_PARAMETER_WITH_STATUS(XmlBuffer, STATUS_UNSUCCESSFUL);
1116c2c66affSColin Finck 
1117c2c66affSColin Finck     /* Compute the sizes and allocate a buffer for it */
1118c2c66affSColin Finck     Length = wcslen(XmlBuffer);
1119c2c66affSColin Finck     HeaderLength = strlen("MACHINEINFO");
1120c2c66affSColin Finck     TotalLength = HeaderLength +
1121c2c66affSColin Finck                   Length +
1122c2c66affSColin Finck                   sizeof(*BsBuffer) +
1123c2c66affSColin Finck                   2 * sizeof(ANSI_NULL);
1124c2c66affSColin Finck     BsBuffer = SacAllocatePool(TotalLength, GLOBAL_BLOCK_TAG);
1125c2c66affSColin Finck     CHECK_PARAMETER_WITH_STATUS(BsBuffer, STATUS_NO_MEMORY);
1126c2c66affSColin Finck 
1127c2c66affSColin Finck     /* Copy the XML property name */
1128c2c66affSColin Finck     strcpy((PCHAR)BsBuffer->Data, "MACHINEINFO");
1129c2c66affSColin Finck     BsBuffer->ValueIndex = HeaderLength + sizeof(ANSI_NULL);
1130c2c66affSColin Finck 
1131c2c66affSColin Finck     /* Copy the data and NULL-terminate it */
1132c2c66affSColin Finck     for (i = 0; i < Length; i++)
1133c2c66affSColin Finck     {
1134c2c66affSColin Finck         BsBuffer->Data[BsBuffer->ValueIndex + i] = XmlBuffer[i];
1135c2c66affSColin Finck     }
1136c2c66affSColin Finck     BsBuffer->Data[BsBuffer->ValueIndex + i] = ANSI_NULL;
1137c2c66affSColin Finck 
1138c2c66affSColin Finck     /* Let the OS save the buffer for later */
1139c2c66affSColin Finck     Status = HeadlessDispatch(HeadlessCmdSetBlueScreenData,
1140c2c66affSColin Finck                               BsBuffer,
1141c2c66affSColin Finck                               TotalLength,
1142c2c66affSColin Finck                               NULL,
1143c2c66affSColin Finck                               NULL);
1144c2c66affSColin Finck 
1145c2c66affSColin Finck     /* Failure or not, we don't need this anymore */
1146c2c66affSColin Finck     SacFreePool(BsBuffer);
1147c2c66affSColin Finck     SacFreePool(XmlBuffer);
1148c2c66affSColin Finck 
1149c2c66affSColin Finck     /* Return the result */
1150c2c66affSColin Finck     SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC Initialize Machine Information: Exiting.\n");
1151c2c66affSColin Finck     return Status;
1152c2c66affSColin Finck }
1153c2c66affSColin Finck 
1154c2c66affSColin Finck VOID
1155c2c66affSColin Finck NTAPI
FreeMachineInformation(VOID)1156c2c66affSColin Finck FreeMachineInformation(VOID)
1157c2c66affSColin Finck {
1158c2c66affSColin Finck     ASSERT(MachineInformation);
1159c2c66affSColin Finck 
1160c2c66affSColin Finck     /* Free every cached string of machine information */
1161c2c66affSColin Finck     if (MachineInformation->MachineName) SacFreePool(MachineInformation);
1162c2c66affSColin Finck     if (MachineInformation->MachineGuid) SacFreePool(MachineInformation->MachineGuid);
1163c2c66affSColin Finck     if (MachineInformation->ProcessorArchitecture) SacFreePool(MachineInformation->ProcessorArchitecture);
1164c2c66affSColin Finck     if (MachineInformation->MajorVersion) SacFreePool(MachineInformation->MajorVersion);
1165c2c66affSColin Finck     if (MachineInformation->BuildNumber) SacFreePool(MachineInformation->BuildNumber);
1166c2c66affSColin Finck     if (MachineInformation->ProductType) SacFreePool(MachineInformation->ProductType);
1167c2c66affSColin Finck     if (MachineInformation->ServicePack) SacFreePool(MachineInformation->ServicePack);
1168c2c66affSColin Finck }
1169c2c66affSColin Finck 
1170c2c66affSColin Finck BOOLEAN
1171c2c66affSColin Finck NTAPI
VerifyEventWaitable(IN HANDLE Handle,OUT PVOID * WaitObject,OUT PVOID * ActualWaitObject)1172c2c66affSColin Finck VerifyEventWaitable(IN HANDLE Handle,
1173c2c66affSColin Finck                     OUT PVOID *WaitObject,
1174c2c66affSColin Finck                     OUT PVOID *ActualWaitObject)
1175c2c66affSColin Finck {
1176c2c66affSColin Finck     PVOID Object;
1177c2c66affSColin Finck     NTSTATUS Status;
1178c2c66affSColin Finck     POBJECT_TYPE ObjectType;
1179c2c66affSColin Finck 
1180c2c66affSColin Finck     /* Reference the object */
1181c2c66affSColin Finck     Status = ObReferenceObjectByHandle(Handle,
1182c2c66affSColin Finck                                        EVENT_ALL_ACCESS,
1183c2c66affSColin Finck                                        NULL,
1184c2c66affSColin Finck                                        KernelMode,
1185c2c66affSColin Finck                                        &Object,
1186c2c66affSColin Finck                                        NULL);
1187c2c66affSColin Finck     *WaitObject = Object;
1188c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1189c2c66affSColin Finck     {
1190c2c66affSColin Finck         SAC_DBG(SAC_DBG_INIT, "SAC VerifyEventWaitable: Unable to reference event object (%lx)\n", Status);
1191c2c66affSColin Finck         return FALSE;
1192c2c66affSColin Finck     }
1193c2c66affSColin Finck 
1194c2c66affSColin Finck     /* Check if the object itself is NOT being used */
1195c2c66affSColin Finck     ObjectType = OBJECT_TO_OBJECT_HEADER(Object)->Type;
1196c2c66affSColin Finck     if (ObjectType->TypeInfo.UseDefaultObject == FALSE)
1197c2c66affSColin Finck     {
1198c2c66affSColin Finck         /* Get the actual object that's being used for the wait */
1199c2c66affSColin Finck         *ActualWaitObject = (PVOID)((ULONG_PTR)Object +
1200c2c66affSColin Finck                                     (ULONG_PTR)ObjectType->DefaultObject);
1201c2c66affSColin Finck         return TRUE;
1202c2c66affSColin Finck     }
1203c2c66affSColin Finck 
1204c2c66affSColin Finck     /* Drop the reference we took */
1205c2c66affSColin Finck     SAC_DBG(SAC_DBG_INIT, "SAC VerifyEventWaitable: event object not waitable!\n");
1206c2c66affSColin Finck     ObDereferenceObject(*WaitObject);
1207c2c66affSColin Finck     return FALSE;
1208c2c66affSColin Finck }
1209c2c66affSColin Finck 
1210c2c66affSColin Finck NTSTATUS
1211c2c66affSColin Finck NTAPI
SerialBufferGetChar(OUT PCHAR Char)1212c2c66affSColin Finck SerialBufferGetChar(OUT PCHAR Char)
1213c2c66affSColin Finck {
1214c2c66affSColin Finck     /* Check if nothing's been produced yet */
1215c2c66affSColin Finck     if (SerialPortConsumerIndex == SerialPortProducerIndex)
1216c2c66affSColin Finck     {
1217c2c66affSColin Finck         return STATUS_NO_DATA_DETECTED;
1218c2c66affSColin Finck     }
1219c2c66affSColin Finck 
1220c2c66affSColin Finck     /* Consume the produced character and clear it*/
1221c2c66affSColin Finck     *Char = SerialPortBuffer[SerialPortConsumerIndex];
1222c2c66affSColin Finck     SerialPortBuffer[SerialPortConsumerIndex] = ANSI_NULL;
1223c2c66affSColin Finck 
1224c2c66affSColin Finck     /* Advance the index and return success */
1225c2c66affSColin Finck     _InterlockedExchange(&SerialPortConsumerIndex,
1226c2c66affSColin Finck                          (SerialPortConsumerIndex + 1) &
1227c2c66affSColin Finck                          (SAC_SERIAL_PORT_BUFFER_SIZE - 1));
1228c2c66affSColin Finck     return STATUS_SUCCESS;
1229c2c66affSColin Finck }
1230c2c66affSColin Finck 
1231c2c66affSColin Finck ULONG
1232c2c66affSColin Finck NTAPI
GetMessageLineCount(IN ULONG MessageIndex)1233c2c66affSColin Finck GetMessageLineCount(IN ULONG MessageIndex)
1234c2c66affSColin Finck {
1235c2c66affSColin Finck     ULONG LineCount = 0;
1236c2c66affSColin Finck     PWCHAR Buffer;
1237c2c66affSColin Finck 
1238c2c66affSColin Finck     /* Get the message buffer */
1239c2c66affSColin Finck     Buffer = GetMessage(MessageIndex);
1240c2c66affSColin Finck     if (Buffer)
1241c2c66affSColin Finck     {
1242c2c66affSColin Finck         /* Scan it looking for new lines, and increment the count each time */
1243c2c66affSColin Finck         while (*Buffer) if (*Buffer++ == L'\n') ++LineCount;
1244c2c66affSColin Finck     }
1245c2c66affSColin Finck 
1246c2c66affSColin Finck     /* Return the line count */
1247c2c66affSColin Finck     return LineCount;
1248c2c66affSColin Finck }
1249c2c66affSColin Finck 
1250c2c66affSColin Finck ULONG
ConvertAnsiToUnicode(IN PWCHAR pwch,IN PCHAR pch,IN ULONG length)1251c2c66affSColin Finck ConvertAnsiToUnicode(
1252c2c66affSColin Finck     IN PWCHAR pwch,
1253c2c66affSColin Finck     IN PCHAR pch,
1254c2c66affSColin Finck     IN ULONG length
1255c2c66affSColin Finck     )
1256c2c66affSColin Finck {
1257c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1258c2c66affSColin Finck }
1259c2c66affSColin Finck 
1260c2c66affSColin Finck BOOLEAN
IsCmdEventRegistrationProcess(IN PFILE_OBJECT FileObject)1261c2c66affSColin Finck IsCmdEventRegistrationProcess(
1262c2c66affSColin Finck     IN PFILE_OBJECT FileObject
1263c2c66affSColin Finck     )
1264c2c66affSColin Finck {
1265c2c66affSColin Finck     return FALSE;
1266c2c66affSColin Finck }
1267c2c66affSColin Finck 
1268c2c66affSColin Finck NTSTATUS
InvokeUserModeService(VOID)1269c2c66affSColin Finck InvokeUserModeService(
1270c2c66affSColin Finck     VOID
1271c2c66affSColin Finck     )
1272c2c66affSColin Finck {
1273c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1274c2c66affSColin Finck }
1275c2c66affSColin Finck 
1276c2c66affSColin Finck NTSTATUS
TranslateMachineInformationText(IN PWCHAR Buffer)1277c2c66affSColin Finck TranslateMachineInformationText(
1278c2c66affSColin Finck     IN PWCHAR Buffer)
1279c2c66affSColin Finck {
1280c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1281c2c66affSColin Finck }
1282c2c66affSColin Finck 
1283c2c66affSColin Finck NTSTATUS
CopyAndInsertStringAtInterval(IN PWCHAR SourceStr,IN ULONG Interval,IN PWCHAR InsertStr,OUT PWCHAR pDestStr)1284c2c66affSColin Finck CopyAndInsertStringAtInterval(
1285c2c66affSColin Finck     IN PWCHAR SourceStr,
1286c2c66affSColin Finck     IN ULONG Interval,
1287c2c66affSColin Finck     IN PWCHAR InsertStr,
1288c2c66affSColin Finck     OUT PWCHAR pDestStr
1289c2c66affSColin Finck     )
1290c2c66affSColin Finck {
1291c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1292c2c66affSColin Finck }
1293c2c66affSColin Finck 
1294c2c66affSColin Finck NTSTATUS
RegisterSacCmdEvent(IN PVOID Object,IN PKEVENT SetupCmdEvent[])1295c2c66affSColin Finck RegisterSacCmdEvent(
1296c2c66affSColin Finck     IN PVOID Object,
1297c2c66affSColin Finck     IN PKEVENT SetupCmdEvent[]
1298c2c66affSColin Finck     )
1299c2c66affSColin Finck {
1300c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1301c2c66affSColin Finck }
1302c2c66affSColin Finck 
1303c2c66affSColin Finck NTSTATUS
UnregisterSacCmdEvent(IN PFILE_OBJECT FileObject)1304c2c66affSColin Finck UnregisterSacCmdEvent(
1305c2c66affSColin Finck     IN PFILE_OBJECT FileObject
1306c2c66affSColin Finck     )
1307c2c66affSColin Finck {
1308c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1309c2c66affSColin Finck }
1310