* Improved the partition list.
* Use information from txtsetup.sif to create directories.
* Added basic error handling.
svn path=/trunk/; revision=3753
}
+NTSTATUS
+WriteConsoleOutputCharactersW(LPCWSTR lpCharacter,
+ ULONG nLength,
+ COORD dwWriteCoord)
+{
+ IO_STATUS_BLOCK IoStatusBlock;
+ PCHAR Buffer;
+ COORD *pCoord;
+ PCHAR pText;
+ NTSTATUS Status;
+ ULONG i;
+
+ Buffer = RtlAllocateHeap(ProcessHeap,
+ 0,
+ nLength + sizeof(COORD));
+ pCoord = (COORD *)Buffer;
+ pText = (PCHAR)(pCoord + 1);
+
+ *pCoord = dwWriteCoord;
+
+ /* FIXME: use real unicode->oem conversion */
+ for (i = 0; i < nLength; i++)
+ pText[i] = (CHAR)lpCharacter[i];
+ pText[i] = 0;
+
+ Status = NtDeviceIoControlFile(StdOutput,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
+ NULL,
+ 0,
+ Buffer,
+ nLength + sizeof(COORD));
+ if (Status == STATUS_PENDING)
+ {
+ NtWaitForSingleObject(StdOutput,
+ FALSE,
+ NULL);
+ Status = IoStatusBlock.Status;
+ }
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Buffer);
+
+ return(Status);
+}
+
+
NTSTATUS
WriteConsoleOutputAttributes(CONST USHORT *lpAttribute,
ULONG nLength,
VOID
-SetInputTextXY(SHORT x, SHORT y, SHORT len, PCHAR Text)
+SetInputTextXY(SHORT x, SHORT y, SHORT len, PWCHAR Text)
{
COORD coPos;
ULONG Length;
coPos.X = x;
coPos.Y = y;
- Length = strlen(Text);
+ Length = wcslen(Text);
+ if (Length > len - 1)
+ {
+ Length = len - 1;
+ }
FillConsoleOutputAttribute(0x70,
len,
coPos,
&Written);
- WriteConsoleOutputCharacters(Text,
- Length,
- coPos);
+ WriteConsoleOutputCharactersW(Text,
+ Length,
+ coPos);
coPos.X += Length;
FillConsoleOutputCharacter('_',
SetTextXY(SHORT x, SHORT y, PCHAR Text);
VOID
-SetInputTextXY(SHORT x, SHORT y, SHORT len, PCHAR Text);
+SetInputTextXY(SHORT x, SHORT y, SHORT len, PWCHAR Text);
VOID
SetUnderlinedTextXY(SHORT x, SHORT y, PCHAR Text);
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: drivesup.h,v 1.2 2002/11/02 23:17:06 ekohl Exp $
+/* $Id: drivesup.h,v 1.3 2002/11/13 18:25:18 ekohl Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: subsys/system/usetup/drivesup.h
#endif /* __DRIVESUP_H__ */
-/* EOF */
\ No newline at end of file
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: filesup.c,v 1.1 2002/11/13 18:25:18 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/filesup.c
+ * PURPOSE: File support functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "filesup.h"
+
+
+/* FUNCTIONS ****************************************************************/
+
+
+NTSTATUS
+CreateDirectory(PWCHAR DirectoryName)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING PathName;
+ HANDLE DirectoryHandle;
+ NTSTATUS Status;
+
+ RtlCreateUnicodeString(&PathName,
+ DirectoryName);
+
+ ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
+ ObjectAttributes.RootDirectory = NULL;
+ ObjectAttributes.ObjectName = &PathName;
+ ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
+ ObjectAttributes.SecurityDescriptor = NULL;
+ ObjectAttributes.SecurityQualityOfService = NULL;
+
+ Status = NtCreateFile(&DirectoryHandle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_DIRECTORY,
+ 0,
+ FILE_CREATE,
+ FILE_DIRECTORY_FILE,
+ NULL,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ NtClose(DirectoryHandle);
+ }
+
+ RtlFreeUnicodeString(&PathName);
+
+ return(Status);
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: filesup.h,v 1.1 2002/11/13 18:25:18 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/filesup.h
+ * PURPOSE: File support functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __FILESUP_H__
+#define __FILESUP_H__
+
+NTSTATUS
+CreateDirectory(PWCHAR DirectoryName);
+
+
+#endif /* __FILESUP_H__ */
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: inicache.c,v 1.1 2002/11/13 18:25:18 ekohl Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/inicache.c
+ * PURPOSE: INI file parser that caches contents of INI file in memory
+ * PROGRAMMER: Royce Mitchell III
+ * Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include "usetup.h"
+#include "inicache.h"
+
+
+/* PRIVATE FUNCTIONS ********************************************************/
+
+static PINICACHEKEY
+IniCacheFreeKey(PINICACHEKEY Key)
+{
+ PINICACHEKEY Next;
+
+ if (Key == NULL)
+ {
+ return(NULL);
+ }
+
+ Next = Key->Next;
+ if (Key->Name != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key->Name);
+ Key->Name = NULL;
+ }
+
+ if (Key->Value != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key->Value);
+ Key->Value = NULL;
+ }
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key);
+
+ return(Next);
+}
+
+
+static PINICACHESECTION
+IniCacheFreeSection(PINICACHESECTION Section)
+{
+ PINICACHESECTION Next;
+
+ if (Section == NULL)
+ {
+ return(NULL);
+ }
+
+ Next = Section->Next;
+ while (Section->FirstKey != NULL)
+ {
+ Section->FirstKey = IniCacheFreeKey(Section->FirstKey);
+ }
+ Section->LastKey = NULL;
+
+ if (Section->Name != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Section->Name);
+ Section->Name = NULL;
+ }
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Section);
+
+ return(Next);
+}
+
+
+static PINICACHEKEY
+IniCacheFindKey(PINICACHESECTION Section,
+ PWCHAR Name,
+ ULONG NameLength)
+{
+ PINICACHEKEY Key;
+
+ Key = Section->FirstKey;
+ while (Key != NULL)
+ {
+ if (NameLength == wcslen(Key->Name))
+ {
+ if (_wcsnicmp(Key->Name, Name, NameLength) == 0)
+ break;
+ }
+
+ Key = Key->Next;
+ }
+
+ return(Key);
+}
+
+
+static PINICACHEKEY
+IniCacheAddKey(PINICACHESECTION Section,
+ PCHAR Name,
+ ULONG NameLength,
+ PCHAR Value,
+ ULONG ValueLength)
+{
+ PINICACHEKEY Key;
+ ULONG i;
+
+ Key = NULL;
+
+ if (Section == NULL ||
+ Name == NULL ||
+ NameLength == 0 ||
+ Value == NULL ||
+ ValueLength == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHEKEY));
+ if (Key == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+
+ RtlZeroMemory(Key,
+ sizeof(INICACHEKEY));
+
+
+ Key->Name = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (NameLength + 1) * sizeof(WCHAR));
+ if (Key->Name == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key);
+ return(NULL);
+ }
+
+ /* Copy value name */
+ for (i = 0; i < NameLength; i++)
+ {
+ Key->Name[i] = (WCHAR)Name[i];
+ }
+ Key->Name[NameLength] = 0;
+
+
+ Key->Value = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (ValueLength + 1) * sizeof(WCHAR));
+ if (Key->Value == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key->Name);
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key);
+ return(NULL);
+ }
+
+ /* Copy value data */
+ for (i = 0; i < ValueLength; i++)
+ {
+ Key->Value[i] = (WCHAR)Value[i];
+ }
+ Key->Value[ValueLength] = 0;
+
+
+ if (Section->FirstKey == NULL)
+ {
+ Section->FirstKey = Key;
+ Section->LastKey = Key;
+ }
+ else
+ {
+ Section->LastKey->Next = Key;
+ Key->Prev = Section->LastKey;
+ Section->LastKey = Key;
+ }
+
+ return(Key);
+}
+
+
+static PINICACHESECTION
+IniCacheFindSection(PINICACHE Cache,
+ PWCHAR Name,
+ ULONG NameLength)
+{
+ PINICACHESECTION Section = NULL;
+
+ if (Cache == NULL || Name == NULL || NameLength == 0)
+ {
+ return(NULL);
+ }
+
+ Section = Cache->FirstSection;
+
+ /* iterate through list of sections */
+ while (Section != NULL)
+ {
+ if (NameLength == wcslen(Section->Name))
+ {
+ /* are the contents the same too? */
+ if (_wcsnicmp(Section->Name, Name, NameLength) == 0)
+ break;
+ }
+
+ /* get the next section*/
+ Section = Section->Next;
+ }
+
+ return(Section);
+}
+
+
+static PINICACHESECTION
+IniCacheAddSection(PINICACHE Cache,
+ PCHAR Name,
+ ULONG NameLength)
+{
+ PINICACHESECTION Section = NULL;
+ ULONG i;
+
+ if (Cache == NULL || Name == NULL || NameLength == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHESECTION));
+ if (Section == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+ RtlZeroMemory(Section,
+ sizeof(INICACHESECTION));
+
+ /* Allocate and initialize section name */
+ Section->Name = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (NameLength + 1) * sizeof(WCHAR));
+ if (Section->Name == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Section);
+ return(NULL);
+ }
+
+ /* Copy section name */
+ for (i = 0; i < NameLength; i++)
+ {
+ Section->Name[i] = (WCHAR)Name[i];
+ }
+ Section->Name[NameLength] = 0;
+
+ /* Append section */
+ if (Cache->FirstSection == NULL)
+ {
+ Cache->FirstSection = Section;
+ Cache->LastSection = Section;
+ }
+ else
+ {
+ Cache->LastSection->Next = Section;
+ Section->Prev = Cache->LastSection;
+ Cache->LastSection = Section;
+ }
+
+ return(Section);
+}
+
+
+static PCHAR
+IniCacheSkipWhitespace(PCHAR Ptr)
+{
+ while (*Ptr != 0 && isspace(*Ptr))
+ Ptr++;
+
+ return((*Ptr == 0) ? NULL : Ptr);
+}
+
+
+static PCHAR
+IniCacheSkipToNextSection(PCHAR Ptr)
+{
+ while (*Ptr != 0 && *Ptr != '[')
+ {
+ while (*Ptr != 0 && *Ptr != L'\n')
+ {
+ Ptr++;
+ }
+ Ptr++;
+ }
+
+ return((*Ptr == 0) ? NULL : Ptr);
+}
+
+
+static PCHAR
+IniCacheGetSectionName(PCHAR Ptr,
+ PCHAR *NamePtr,
+ PULONG NameSize)
+{
+ ULONG Size = 0;
+ CHAR Name[256];
+
+ *NamePtr = NULL;
+ *NameSize = 0;
+
+ /* skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
+ {
+ Ptr++;
+ }
+
+ *NamePtr = Ptr;
+
+ while (*Ptr != 0 && *Ptr != ']')
+ {
+ Size++;
+ Ptr++;
+ }
+
+ Ptr++;
+
+ while (*Ptr != 0 && *Ptr != L'\n')
+ {
+ Ptr++;
+ }
+ Ptr++;
+
+ *NameSize = Size;
+
+ strncpy(Name, *NamePtr, Size);
+ Name[Size] = 0;
+
+ DPRINT("SectionName: '%s'\n", Name);
+
+ return(Ptr);
+}
+
+
+static PCHAR
+IniCacheGetKeyName(PCHAR Ptr,
+ PCHAR *NamePtr,
+ PULONG NameSize)
+{
+ ULONG Size = 0;
+
+ *NamePtr = NULL;
+ *NameSize = 0;
+
+ /* skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
+ {
+ Ptr++;
+ }
+
+ *NamePtr = Ptr;
+
+ while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '=')
+ {
+ Size++;
+ Ptr++;
+ }
+
+ *NameSize = Size;
+
+ return(Ptr);
+}
+
+
+static PCHAR
+IniCacheGetKeyValue(PCHAR Ptr,
+ PCHAR *DataPtr,
+ PULONG DataSize)
+{
+ ULONG Size = 0;
+
+ *DataPtr = NULL;
+ *DataSize = 0;
+
+ /* skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
+ {
+ Ptr++;
+ }
+
+ /* check and skip '=' */
+ if (*Ptr != '=')
+ {
+ return(NULL);
+ }
+ Ptr++;
+
+ /* skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
+ {
+ Ptr++;
+ }
+
+ /* check for quoted data */
+ if (*Ptr == '\"')
+ {
+ Ptr++;
+ *DataPtr = Ptr;
+
+ while (*Ptr != 0 && *Ptr != '\"')
+ {
+ Ptr++;
+ Size++;
+ }
+ Ptr++;
+ }
+ else
+ {
+ *DataPtr = Ptr;
+
+ while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '\n')
+ {
+ Ptr++;
+ Size++;
+ }
+ }
+
+ /* Skip to next line */
+ while (*Ptr != 0 && *Ptr != '\n')
+ {
+ Ptr++;
+ }
+ Ptr++;
+
+ *DataSize = Size;
+
+ return(Ptr);
+}
+
+
+
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+NTSTATUS
+IniCacheLoad(PINICACHE *Cache,
+ PUNICODE_STRING FileName)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ FILE_STANDARD_INFORMATION FileInfo;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PCHAR FileBuffer;
+ ULONG FileLength;
+ PCHAR Ptr;
+ LARGE_INTEGER FileOffset;
+
+ ULONG i;
+ PINICACHESECTION Section;
+ PINICACHEKEY Key;
+
+ PCHAR SectionName;
+ ULONG SectionNameSize;
+
+ PCHAR KeyName;
+ ULONG KeyNameSize;
+
+ PCHAR KeyValue;
+ ULONG KeyValueSize;
+
+ *Cache = NULL;
+
+ /* Open ini file */
+ InitializeObjectAttributes(&ObjectAttributes,
+ FileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_NON_DIRECTORY_FILE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ DPRINT("NtOpenFile() successful\n");
+
+ /* Query file size */
+ Status = NtQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInfo,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation);
+ if (Status == STATUS_PENDING)
+ {
+ DPRINT("NtQueryInformationFile() returns STATUS_PENDING\n");
+
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ FileLength = FileInfo.EndOfFile.u.LowPart;
+
+ DPRINT("File size: %lu\n", FileLength);
+
+ /* Allocate file buffer */
+ FileBuffer = RtlAllocateHeap(ProcessHeap,
+ 0,
+ FileLength + 1);
+ if (FileBuffer == NULL)
+ {
+ DPRINT1("RtlAllocateHeap() failed\n");
+ NtClose(FileHandle);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read file */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FileBuffer,
+ FileLength,
+ &FileOffset,
+ NULL);
+
+ if (Status == STATUS_PENDING)
+ {
+ DPRINT("NtReadFile() returns STATUS_PENDING\n");
+
+ Status = IoStatusBlock.Status;
+ }
+
+ /* Append string terminator */
+ FileBuffer[FileLength] = 0;
+
+ NtClose(FileHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ FileBuffer);
+ return(Status);
+ }
+
+
+ /* Allocate inicache header */
+ *Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHE));
+ if (*Cache == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Initialize inicache header */
+ RtlZeroMemory(*Cache,
+ sizeof(INICACHE));
+
+ /* Parse ini file */
+ Section = NULL;
+ Ptr = FileBuffer;
+ while (Ptr != NULL && *Ptr != 0)
+ {
+ Ptr = IniCacheSkipWhitespace(Ptr);
+ if (Ptr == NULL)
+ continue;
+
+ if (*Ptr == '[')
+ {
+ Section = NULL;
+ Ptr++;
+
+ Ptr = IniCacheGetSectionName(Ptr,
+ &SectionName,
+ &SectionNameSize);
+
+ Section = IniCacheAddSection(*Cache,
+ SectionName,
+ SectionNameSize);
+ if (Section == NULL)
+ {
+ DPRINT("IniCacheAddSection() failed\n");
+ Ptr = IniCacheSkipToNextSection(Ptr);
+ continue;
+ }
+ }
+ else
+ {
+ if (Section == NULL)
+ {
+ Ptr = IniCacheSkipToNextSection(Ptr);
+ continue;
+ }
+
+ Ptr = IniCacheGetKeyName(Ptr,
+ &KeyName,
+ &KeyNameSize);
+
+ Ptr = IniCacheGetKeyValue(Ptr,
+ &KeyValue,
+ &KeyValueSize);
+
+ Key = IniCacheAddKey(Section,
+ KeyName,
+ KeyNameSize,
+ KeyValue,
+ KeyValueSize);
+ if (Key == NULL)
+ {
+ DPRINT("IniCacheAddKey() failed\n");
+ }
+ }
+ }
+
+ /* Free file buffer */
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ FileBuffer);
+
+ return(Status);
+}
+
+
+VOID
+IniCacheDestroy(PINICACHE Cache)
+{
+ if (Cache == NULL)
+ {
+ return;
+ }
+
+ while (Cache->FirstSection != NULL)
+ {
+ Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection);
+ }
+ Cache->LastSection = NULL;
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Cache);
+}
+
+
+PINICACHESECTION
+IniCacheGetSection(PINICACHE Cache,
+ PWCHAR Name)
+{
+ PINICACHESECTION Section = NULL;
+
+ if (Cache == NULL || Name == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ /* iterate through list of sections */
+ Section = Cache->FirstSection;
+ while (Section != NULL)
+ {
+ DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name);
+
+ /* Are the section names the same? */
+ if (_wcsicmp(Section->Name, Name) == 0)
+ return(Section);
+
+ /* Get the next section */
+ Section = Section->Next;
+ }
+
+ DPRINT("Section not found\n");
+
+ return(NULL);
+}
+
+
+NTSTATUS
+IniCacheGetKey(PINICACHESECTION Section,
+ PWCHAR KeyName,
+ PWCHAR *KeyValue)
+{
+ PINICACHEKEY Key;
+
+ if (Section == NULL || KeyName == NULL || KeyValue == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(STATUS_INVALID_PARAMETER);
+ }
+
+ *KeyValue = NULL;
+
+ Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName));
+ if (Key == NULL)
+ {
+ return(STATUS_INVALID_PARAMETER);
+ }
+
+ *KeyValue = Key->Value;
+
+ return(STATUS_SUCCESS);
+}
+
+
+PINICACHEITERATOR
+IniCacheFindFirstValue(PINICACHESECTION Section,
+ PWCHAR *KeyName,
+ PWCHAR *KeyValue)
+{
+ PINICACHEITERATOR Iterator;
+ PINICACHEKEY Key;
+
+ if (Section == NULL || KeyName == NULL || KeyValue == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ Key = Section->FirstKey;
+ if (Key == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ *KeyName = Key->Name;
+ *KeyValue = Key->Value;
+
+ Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHEITERATOR));
+ if (Iterator == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+
+ Iterator->Section = Section;
+ Iterator->Key = Key;
+
+ return(Iterator);
+}
+
+
+BOOLEAN
+IniCacheFindNextValue(PINICACHEITERATOR Iterator,
+ PWCHAR *KeyName,
+ PWCHAR *KeyValue)
+{
+ PINICACHEKEY Key;
+
+ if (Iterator == NULL || KeyName == NULL || KeyValue == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(FALSE);
+ }
+
+ Key = Iterator->Key->Next;
+ if (Key == NULL)
+ {
+ DPRINT("No more entries\n");
+ return(FALSE);
+ }
+
+ *KeyName = Key->Name;
+ *KeyValue = Key->Value;
+
+ Iterator->Key = Key;
+
+ return(TRUE);
+}
+
+
+VOID
+IniCacheFindClose(PINICACHEITERATOR Iterator)
+{
+ if (Iterator == NULL)
+ return;
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Iterator);
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/inicache.h
+ * PURPOSE: INI file parser that caches contents of INI file in memory
+ * PROGRAMMER: Royce Mitchell III
+ * Eric Kohl
+ */
+
+#ifndef __INICACHE_H__
+#define __INICACHE_H__
+
+
+typedef struct _INICACHEKEY
+{
+ PWCHAR Name;
+ PWCHAR Value;
+
+ struct _INICACHEKEY *Next;
+ struct _INICACHEKEY *Prev;
+} INICACHEKEY, *PINICACHEKEY;
+
+
+typedef struct _INICACHESECTION
+{
+ PWCHAR Name;
+
+ PINICACHEKEY FirstKey;
+ PINICACHEKEY LastKey;
+
+ struct _INICACHESECTION *Next;
+ struct _INICACHESECTION *Prev;
+} INICACHESECTION, *PINICACHESECTION;
+
+
+typedef struct _INICACHE
+{
+ PINICACHESECTION FirstSection;
+ PINICACHESECTION LastSection;
+} INICACHE, *PINICACHE;
+
+
+typedef struct _PINICACHEITERATOR
+{
+ PINICACHESECTION Section;
+ PINICACHEKEY Key;
+} INICACHEITERATOR, *PINICACHEITERATOR;
+
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS
+IniCacheLoad(PINICACHE *Cache,
+ PUNICODE_STRING FileName);
+
+VOID
+IniCacheDestroy(PINICACHE Cache);
+
+PINICACHESECTION
+IniCacheGetSection(PINICACHE Cache,
+ PWCHAR Name);
+
+NTSTATUS
+IniCacheGetKey(PINICACHESECTION Section,
+ PWCHAR KeyName,
+ PWCHAR *KeyValue);
+
+
+
+PINICACHEITERATOR
+IniCacheFindFirstValue(PINICACHESECTION Section,
+ PWCHAR *KeyName,
+ PWCHAR *KeyValue);
+
+BOOLEAN
+IniCacheFindNextValue(PINICACHEITERATOR Iterator,
+ PWCHAR *KeyName,
+ PWCHAR *KeyValue);
+
+VOID
+IniCacheFindClose(PINICACHEITERATOR Iterator);
+
+
+#endif /* __INICACHE_H__ */
+
+/* EOF */
-# $Id: makefile,v 1.3 2002/10/29 18:40:02 ekohl Exp $
+# $Id: makefile,v 1.4 2002/11/13 18:25:18 ekohl Exp $
PATH_TO_TOP = ../../..
TARGET_CFLAGS = -D__NTAPP__
-TARGET_OBJECTS = $(TARGET_NAME).o console.o drivesup.o partlist.o
+TARGET_OBJECTS = $(TARGET_NAME).o console.o drivesup.o filesup.o inicache.o partlist.o
include $(PATH_TO_TOP)/rules.mak
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: partlist.c,v 1.3 2002/11/02 23:17:06 ekohl Exp $
+/* $Id: partlist.c,v 1.4 2002/11/13 18:25:18 ekohl Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: subsys/system/usetup/partlist.c
/* FUNCTIONS ****************************************************************/
+static VOID
+AddPartitionList(ULONG DiskNumber,
+ PDISKENTRY DiskEntry,
+ DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
+{
+ PPARTENTRY PartEntry;
+ ULONG i;
+ ULONG EntryCount;
+
+
+ /*
+ * FIXME:
+ * Determine required number of partiton entries.
+ * This must include entries for unused disk space.
+ */
+
+ /* Check for unpartitioned disk */
+ if (LayoutBuffer->PartitionCount == 0)
+ {
+ EntryCount = 1;
+ }
+ else
+ {
+
+#if 0
+ for (i = 0; i < LayoutBuffer->PartitionCount; i++)
+ {
+
+ }
+#endif
+
+ EntryCount = LayoutBuffer->PartitionCount;
+ }
+
+
+ DiskEntry->PartArray = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
+ 0,
+ EntryCount * sizeof(PARTENTRY));
+ DiskEntry->PartCount = EntryCount;
+
+ RtlZeroMemory(DiskEntry->PartArray,
+ EntryCount * sizeof(PARTENTRY));
+
+ if (LayoutBuffer->PartitionCount == 0)
+ {
+ /* Initialize an 'Unpartitioned space' entry */
+ PartEntry = &DiskEntry->PartArray[0];
+
+ PartEntry->Unpartitioned = TRUE;
+ PartEntry->PartSize = 0; /* ?? */
+
+ PartEntry->Used = TRUE;
+ }
+ else
+ {
+ for (i = 0; i < LayoutBuffer->PartitionCount; i++)
+ {
+ PartEntry = &DiskEntry->PartArray[i];
+
+ if ((LayoutBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED) &&
+ (!IsContainerPartition(LayoutBuffer->PartitionEntry[i].PartitionType)))
+ {
+ PartEntry->PartSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart;
+ PartEntry->PartNumber = LayoutBuffer->PartitionEntry[i].PartitionNumber,
+ PartEntry->PartType = LayoutBuffer->PartitionEntry[i].PartitionType;
+
+ PartEntry->DriveLetter = GetDriveLetter(DiskNumber,
+ LayoutBuffer->PartitionEntry[i].PartitionNumber);
+
+ PartEntry->Unpartitioned = FALSE;
+
+ PartEntry->Used = TRUE;
+ }
+ else
+ {
+ PartEntry->Used = FALSE;
+ }
+ }
+ }
+}
+
+
PPARTLIST
CreatePartitionList(SHORT Left,
SHORT Top,
OBJECT_ATTRIBUTES ObjectAttributes;
SYSTEM_DEVICE_INFORMATION Sdi;
DISK_GEOMETRY DiskGeometry;
+ IO_STATUS_BLOCK Iosb;
ULONG ReturnSize;
NTSTATUS Status;
- ULONG DiskCount;
- IO_STATUS_BLOCK Iosb;
+ ULONG DiskNumber;
WCHAR Buffer[MAX_PATH];
UNICODE_STRING Name;
HANDLE FileHandle;
DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
SCSI_ADDRESS ScsiAddress;
- ULONG i;
List = (PPARTLIST)RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTLIST));
if (List == NULL)
Sdi.NumberOfDisks * sizeof(DISKENTRY));
List->DiskCount = Sdi.NumberOfDisks;
- for (DiskCount = 0; DiskCount < Sdi.NumberOfDisks; DiskCount++)
+ for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
{
swprintf(Buffer,
L"\\Device\\Harddisk%d\\Partition0",
- DiskCount);
+ DiskNumber);
RtlInitUnicodeString(&Name,
Buffer);
sizeof(SCSI_ADDRESS));
- List->DiskArray[DiskCount].DiskSize =
+ List->DiskArray[DiskNumber].DiskSize =
DiskGeometry.Cylinders.QuadPart *
(ULONGLONG)DiskGeometry.TracksPerCylinder *
(ULONGLONG)DiskGeometry.SectorsPerTrack *
(ULONGLONG)DiskGeometry.BytesPerSector;
- List->DiskArray[DiskCount].DiskNumber = DiskCount;
- List->DiskArray[DiskCount].Port = ScsiAddress.PortNumber;
- List->DiskArray[DiskCount].Bus = ScsiAddress.PathId;
- List->DiskArray[DiskCount].Id = ScsiAddress.TargetId;
+ List->DiskArray[DiskNumber].DiskNumber = DiskNumber;
+ List->DiskArray[DiskNumber].Port = ScsiAddress.PortNumber;
+ List->DiskArray[DiskNumber].Bus = ScsiAddress.PathId;
+ List->DiskArray[DiskNumber].Id = ScsiAddress.TargetId;
- List->DiskArray[DiskCount].FixedDisk = TRUE;
+ List->DiskArray[DiskNumber].FixedDisk = TRUE;
LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192);
8192);
if (NT_SUCCESS(Status))
{
-
- List->DiskArray[DiskCount].PartArray = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
- 0,
- LayoutBuffer->PartitionCount * sizeof(PARTENTRY));
- List->DiskArray[DiskCount].PartCount = LayoutBuffer->PartitionCount;
-
- for (i = 0; i < LayoutBuffer->PartitionCount; i++)
- {
- if ((LayoutBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED) &&
- !IsContainerPartition(LayoutBuffer->PartitionEntry[i].PartitionType))
- {
- List->DiskArray[DiskCount].PartArray[i].PartSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart;
- List->DiskArray[DiskCount].PartArray[i].PartNumber = LayoutBuffer->PartitionEntry[i].PartitionNumber,
- List->DiskArray[DiskCount].PartArray[i].PartType = LayoutBuffer->PartitionEntry[i].PartitionType;
-
- List->DiskArray[DiskCount].PartArray[i].DriveLetter = GetDriveLetter(DiskCount,
- LayoutBuffer->PartitionEntry[i].PartitionNumber);
-
- List->DiskArray[DiskCount].PartArray[i].Used = TRUE;
- }
- else
- {
- List->DiskArray[DiskCount].PartArray[i].Used = FALSE;
- }
- }
+ AddPartitionList(DiskNumber,
+ &List->DiskArray[DiskNumber],
+ LayoutBuffer);
}
RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
else
{
/* mark removable disk entry */
- List->DiskArray[DiskCount].FixedDisk = FALSE;
- List->DiskArray[DiskCount].PartCount = 0;
- List->DiskArray[DiskCount].PartArray = NULL;
+ List->DiskArray[DiskNumber].FixedDisk = FALSE;
+ List->DiskArray[DiskNumber].PartCount = 0;
+ List->DiskArray[DiskNumber].PartArray = NULL;
}
}
ULONGLONG PartSize;
PCHAR Unit;
- PCHAR PartType;
UCHAR Attribute;
-
+ PCHAR PartType;
Width = List->Right - List->Left - 1;
Height = List->Bottom - List->Top - 1;
PartEntry = &List->DiskArray[DiskIndex].PartArray[PartIndex];
- if ((PartEntry->PartType == PARTITION_FAT_12) ||
- (PartEntry->PartType == PARTITION_FAT_16) ||
- (PartEntry->PartType == PARTITION_HUGE) ||
- (PartEntry->PartType == PARTITION_XINT13))
- {
- PartType = "FAT";
- }
- else if ((PartEntry->PartType == PARTITION_FAT32) ||
- (PartEntry->PartType == PARTITION_FAT32_XINT13))
- {
- PartType = "FAT32";
- }
- else if (PartEntry->PartType == PARTITION_IFS)
- {
- PartType = "NTFS"; /* FIXME: Not quite correct! */
- }
- else
+ /* Determine partition type */
+ PartType = NULL;
+ if (PartEntry->Unpartitioned == FALSE)
{
- PartType = "Unknown";
+ if ((PartEntry->PartType == PARTITION_FAT_12) ||
+ (PartEntry->PartType == PARTITION_FAT_16) ||
+ (PartEntry->PartType == PARTITION_HUGE) ||
+ (PartEntry->PartType == PARTITION_XINT13))
+ {
+ PartType = "FAT";
+ }
+ else if ((PartEntry->PartType == PARTITION_FAT32) ||
+ (PartEntry->PartType == PARTITION_FAT32_XINT13))
+ {
+ PartType = "FAT32";
+ }
+ else if (PartEntry->PartType == PARTITION_IFS)
+ {
+ PartType = "NTFS"; /* FIXME: Not quite correct! */
+ }
}
+
+#if 0
if (PartEntry->PartSize >= 0x280000000ULL) /* 10 GB */
{
PartSize = (PartEntry->PartSize + (1 << 29)) >> 30;
Unit = "GB";
}
- else if (PartEntry->PartSize >= 0xA00000ULL) /* 10 MB */
+ else
+#endif
+ if (PartEntry->PartSize >= 0xA00000ULL) /* 10 MB */
{
PartSize = (PartEntry->PartSize + (1 << 19)) >> 20;
Unit = "MB";
else
{
PartSize = (PartEntry->PartSize + (1 << 9)) >> 10;
- Unit = "kB";
+ Unit = "KB";
}
- if (PartEntry->DriveLetter != (CHAR)0)
+
+ if (PartEntry->Unpartitioned == TRUE)
{
sprintf(LineBuffer,
- "%c: %d: nr: %d type: %x (%s) %I64u %s",
+ " Unpartitioned space %I64u %s",
+ PartSize,
+ Unit);
+ }
+ else if (PartEntry->DriveLetter != (CHAR)0)
+ {
+ if (PartType == NULL)
+ {
+ sprintf(LineBuffer,
+ "%c: Type %-3lu %I64u %s",
+ PartEntry->DriveLetter,
+ PartEntry->PartType,
+ PartSize,
+ Unit);
+ }
+ else
+ {
+ sprintf(LineBuffer,
+ "%c: %s %I64u %s",
+ PartEntry->DriveLetter,
+ PartType,
+ PartSize,
+ Unit);
+ }
+
+#if 0
+ sprintf(LineBuffer,
+ "%c: %s (%d: nr: %d type: %x) %I64u %s",
PartEntry->DriveLetter,
+ PartType,
PartIndex,
PartEntry->PartNumber,
PartEntry->PartType,
- PartType,
PartSize,
Unit);
+#endif
}
else
{
sprintf(LineBuffer,
- " %d: nr: %d type: %x (%s) %I64u %s",
+ "-- %s (%d: nr: %d type: %x) %I64u %s",
+ PartEntry->FileSystemName,
PartIndex,
PartEntry->PartNumber,
PartEntry->PartType,
- PartType,
PartSize,
Unit);
}
ULONGLONG DiskSize;
PCHAR Unit;
SHORT PartIndex;
- BOOL PartPrinted;
DiskEntry = &List->DiskArray[DiskIndex];
coPos.X = List->Left + 1;
coPos.Y = List->Top + 1 + List->Line;
+#if 0
if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
{
DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
Unit = "GB";
}
- else if (DiskEntry->DiskSize >= 0xA00000ULL) /* 10 MB */
+ else
+#endif
{
DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
+ if (DiskSize == 0)
+ DiskSize = 1;
Unit = "MB";
}
- else
- {
- DiskSize = (DiskEntry->DiskSize + (1 << 9)) >> 10;
- Unit = "kB";
- }
sprintf(LineBuffer,
- "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
+ "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
DiskSize,
Unit,
DiskEntry->DiskNumber,
PrintEmptyLine(List);
- PartPrinted = FALSE;
-
/* Print partition lines*/
- for (PartIndex = 0; PartIndex < List->DiskArray[DiskIndex].PartCount; PartIndex++)
+ for (PartIndex = 0; PartIndex < DiskEntry->PartCount; PartIndex++)
{
- if (List->DiskArray[DiskIndex].PartArray[PartIndex].Used == TRUE)
+ if (DiskEntry->PartArray[PartIndex].Used == TRUE)
{
PrintPartitionData(List,
DiskIndex,
PartIndex);
- PartPrinted = TRUE;
}
}
/* Print separator line */
- if (PartPrinted == TRUE)
- {
- PrintEmptyLine(List);
- }
+ PrintEmptyLine(List);
}
coPos,
&Written);
- /* draw upper right corner */
+ /* draw lower right corner */
coPos.X = List->Right;
coPos.Y = List->Bottom;
FillConsoleOutputCharacter(0xD9, // '+',
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: partlist.h,v 1.3 2002/11/02 23:17:06 ekohl Exp $
+/* $Id: partlist.h,v 1.4 2002/11/13 18:25:18 ekohl Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: subsys/system/usetup/partlist.h
ULONG PartType;
CHAR DriveLetter;
+ CHAR VolumeLabel[17];
+ CHAR FileSystemName[9];
+
+ BOOL Unpartitioned;
+
BOOL Used;
} PARTENTRY, *PPARTENTRY;
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
+#include <ntos/minmax.h>
+#include <reactos/resource.h>
+
#include "usetup.h"
#include "console.h"
#include "partlist.h"
+#include "inicache.h"
HANDLE ProcessHeap;
-BOOL PartDataValid = FALSE;
+BOOLEAN PartDataValid;
PARTDATA PartData;
-CHAR InstallDir[51];
+WCHAR InstallDir[51];
UNICODE_STRING SourcePath;
UNICODE_STRING SourceRootPath;
+PINICACHE IniCache;
+
/* FUNCTIONS ****************************************************************/
}
+static VOID
+PopupError(PCHAR Text,
+ PCHAR Status)
+{
+ SHORT xScreen;
+ SHORT yScreen;
+ SHORT yTop;
+ SHORT xLeft;
+ COORD coPos;
+ ULONG Written;
+ ULONG Length;
+ ULONG MaxLength;
+ ULONG Lines;
+ PCHAR p;
+ PCHAR pnext;
+ BOOLEAN LastLine;
+ SHORT Width;
+ SHORT Height;
+
+
+ /* Count text lines and longest line */
+ MaxLength = 0;
+ Lines = 0;
+ pnext = Text;
+ while (TRUE)
+ {
+ p = strchr(pnext, '\n');
+ if (p == NULL)
+ {
+ Length = strlen(pnext);
+ LastLine = TRUE;
+ }
+ else
+ {
+ Length = (ULONG)(p - pnext);
+ LastLine = FALSE;
+ }
+
+ Lines++;
+ if (Length > MaxLength)
+ MaxLength = Length;
+
+ if (LastLine == TRUE)
+ break;
+
+ pnext = p + 1;
+ }
+
+ /* Check length of status line */
+ if (Status != NULL)
+ {
+ Length = strlen(Status);
+ if (Length > MaxLength)
+ MaxLength = Length;
+ }
+
+ GetScreenSize(&xScreen, &yScreen);
+
+ Width = MaxLength + 4;
+ Height = Lines + 2;
+ if (Status != NULL)
+ Height += 2;
+
+ yTop = (yScreen - Height) / 2;
+ xLeft = (xScreen - Width) / 2;
+
+
+ /* Set screen attributes */
+ coPos.X = xLeft;
+ for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
+ {
+ FillConsoleOutputAttribute(0x74,
+ Width,
+ coPos,
+ &Written);
+ }
+
+ /* draw upper left corner */
+ coPos.X = xLeft;
+ coPos.Y = yTop;
+ FillConsoleOutputCharacter(0xDA, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* draw upper edge */
+ coPos.X = xLeft + 1;
+ coPos.Y = yTop;
+ FillConsoleOutputCharacter(0xC4, // '-',
+ Width - 2,
+ coPos,
+ &Written);
+
+ /* draw upper right corner */
+ coPos.X = xLeft + Width - 1;
+ coPos.Y = yTop;
+ FillConsoleOutputCharacter(0xBF, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* Draw right edge, inner space and left edge */
+ for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
+ {
+ coPos.X = xLeft;
+ FillConsoleOutputCharacter(0xB3, // '|',
+ 1,
+ coPos,
+ &Written);
+
+ coPos.X = xLeft + 1;
+ FillConsoleOutputCharacter(' ',
+ Width - 2,
+ coPos,
+ &Written);
+
+ coPos.X = xLeft + Width - 1;
+ FillConsoleOutputCharacter(0xB3, // '|',
+ 1,
+ coPos,
+ &Written);
+ }
+
+ /* draw lower left corner */
+ coPos.X = xLeft;
+ coPos.Y = yTop + Height - 1;
+ FillConsoleOutputCharacter(0xC0, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* draw lower edge */
+ coPos.X = xLeft + 1;
+ coPos.Y = yTop + Height - 1;
+ FillConsoleOutputCharacter(0xC4, // '-',
+ Width - 2,
+ coPos,
+ &Written);
+
+ /* draw lower right corner */
+ coPos.X = xLeft + Width - 1;
+ coPos.Y = yTop + Height - 1;
+ FillConsoleOutputCharacter(0xD9, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* Print message text */
+ coPos.Y = yTop + 1;
+ pnext = Text;
+ while (TRUE)
+ {
+ p = strchr(pnext, '\n');
+ if (p == NULL)
+ {
+ Length = strlen(pnext);
+ LastLine = TRUE;
+ }
+ else
+ {
+ Length = (ULONG)(p - pnext);
+ LastLine = FALSE;
+ }
+
+ if (Length != 0)
+ {
+ coPos.X = xLeft + 2;
+ WriteConsoleOutputCharacters(pnext,
+ Length,
+ coPos);
+ }
+
+ if (LastLine == TRUE)
+ break;
+
+ coPos.Y++;
+ pnext = p + 1;
+ }
+
+ /* Print separator line and status text */
+ if (Status != NULL)
+ {
+ coPos.Y = yTop + Height - 3;
+ coPos.X = xLeft;
+ FillConsoleOutputCharacter(0xC3, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ coPos.X = xLeft + 1;
+ FillConsoleOutputCharacter(0xC4, // '-',
+ Width - 2,
+ coPos,
+ &Written);
+
+ coPos.X = xLeft + Width - 1;
+ FillConsoleOutputCharacter(0xB4, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ coPos.Y++;
+ coPos.X = xLeft + 2;
+ WriteConsoleOutputCharacters(Status,
+ min(strlen(Status), Width - 4),
+ coPos);
+ }
+}
+
+
/*
* Confirm quit setup
* RETURNS
static BOOL
ConfirmQuit(PINPUT_RECORD Ir)
{
- SHORT xScreen;
- SHORT yScreen;
- SHORT yTop;
- SHORT xLeft;
BOOL Result = FALSE;
- PUSHORT pAttributes = NULL;
- PUCHAR pCharacters = NULL;
- COORD Pos;
-
- GetScreenSize(&xScreen, &yScreen);
- yTop = (yScreen - 10) / 2;
- xLeft = (xScreen - 52) / 2;
-
- /* Save screen */
-#if 0
- Pos.X = 0;
- Pos.Y = 0;
- pAttributes = (PUSHORT)RtlAllocateHeap(ProcessHeap,
- 0,
- xScreen * yScreen * sizeof(USHORT));
-CHECKPOINT1;
-DPRINT1("pAttributes %p\n", pAttributes);
- ReadConsoleOutputAttributes(pAttributes,
- xScreen * yScreen,
- Pos,
- NULL);
-CHECKPOINT1;
- pCharacters = (PUCHAR)RtlAllocateHeap(ProcessHeap,
- 0,
- xScreen * yScreen * sizeof(UCHAR));
-CHECKPOINT1;
- ReadConsoleOutputCharacters(pCharacters,
- xScreen * yScreen,
- Pos,
- NULL);
-CHECKPOINT1;
-#endif
- /* Draw popup window */
- SetTextXY(xLeft, yTop,
- "+----------------------------------------------------+");
- SetTextXY(xLeft, yTop + 1,
- "| ReactOS 0.0.20 is not completely installed on your |");
- SetTextXY(xLeft, yTop + 2,
- "| computer. If you quit Setup now, you will need to |");
- SetTextXY(xLeft, yTop + 3,
- "| run Setup again to install ReactOS. |");
- SetTextXY(xLeft, yTop + 4,
- "| |");
- SetTextXY(xLeft, yTop + 5,
- "| * Press ENTER to continue Setup. |");
- SetTextXY(xLeft, yTop + 6,
- "| * Press F3 to quit Setup. |");
- SetTextXY(xLeft, yTop + 7,
- "+----------------------------------------------------+");
- SetTextXY(xLeft, yTop + 8,
- "| F3= Quit ENTER = Continue |");
- SetTextXY(xLeft, yTop + 9,
- "+----------------------------------------------------+");
+ PopupError("ReactOS is not completely installed on your\n"
+ "computer. If you quit Setup now, you will need to\n"
+ "run Setup again to install ReactOS.\n"
+ "\n"
+ " * Press ENTER to continue Setup.\n"
+ " * Press F3 to quit Setup.",
+ "F3= Quit ENTER = Continue");
while(TRUE)
{
}
}
- /* Restore screen */
-#if 0
-CHECKPOINT1;
- WriteConsoleOutputAttributes(pAttributes,
- xScreen * yScreen,
- Pos,
- NULL);
-CHECKPOINT1;
-
- WriteConsoleOutputCharacters(pCharacters,
- xScreen * yScreen,
- Pos);
-CHECKPOINT1;
-
- RtlFreeHeap(ProcessHeap,
- 0,
- pAttributes);
- RtlFreeHeap(ProcessHeap,
- 0,
- pCharacters);
-#endif
-
return(Result);
}
-
/*
* Start page
* RETURNS
StartPage(PINPUT_RECORD Ir)
{
NTSTATUS Status;
+ WCHAR FileNameBuffer[MAX_PATH];
+ UNICODE_STRING FileName;
+
+ PINICACHESECTION Section;
+ PWCHAR Value;
+
SetStatusText(" Please wait...");
PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
}
- /*
- * FIXME: Open and load txtsetup.sif here. A pointer (or handle) to the
- * ini data should be stored in a global variable.
- * The full path to txtsetup.sif is created by appending '\txtsetup.sif'
- * to the unicode string SourceRootPath.
- */
+
+ /* Load txtsetup.sif from install media. */
+ wcscpy(FileNameBuffer, SourceRootPath.Buffer);
+ wcscat(FileNameBuffer, L"\\install\\txtsetup.sif");
+ RtlInitUnicodeString(&FileName,
+ FileNameBuffer);
+
+ IniCache = NULL;
+ Status = IniCacheLoad(&IniCache,
+ &FileName);
+ if (!NT_SUCCESS(Status))
+ {
+ PopupError("Setup failed to load the file TXTSETUP.SIF.\n",
+ "ENTER = Reboot computer");
+
+ while(TRUE)
+ {
+ ConInKey(Ir);
+
+ if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+ {
+ return(QUIT_PAGE);
+ }
+ }
+ }
+
+ /* Open 'Version' section */
+ Section = IniCacheGetSection(IniCache,
+ L"Version");
+ if (Section == NULL)
+ {
+ PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
+ "ENTER = Reboot computer");
+
+ while(TRUE)
+ {
+ ConInKey(Ir);
+
+ if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+ {
+ return(QUIT_PAGE);
+ }
+ }
+ }
+
+
+ /* Get pointer 'Signature' key */
+ Status = IniCacheGetKey(Section,
+ L"Signature",
+ &Value);
+ if (!NT_SUCCESS(Status))
+ {
+ PopupError("Setup found a corrupt TXTSETUP.SIF.\n",
+ "ENTER = Reboot computer");
+
+ while(TRUE)
+ {
+ ConInKey(Ir);
+
+ if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+ {
+ return(QUIT_PAGE);
+ }
+ }
+ }
+
+ /* Check 'Signature' string */
+ if (_wcsicmp(Value, L"$ReactOS$") != 0)
+ {
+ PopupError("Setup found an invalid signature in TXTSETUP.SIF.\n",
+ "ENTER = Reboot computer");
+
+ while(TRUE)
+ {
+ ConInKey(Ir);
+
+ if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+ {
+ return(QUIT_PAGE);
+ }
+ }
+ }
+
+#if 0
+ PopupError("This is a test error.", "ENTER = Reboot computer");
SetStatusText(" ENTER = Continue");
}
return(START_PAGE);
+#endif
+
+ return(INTRO_PAGE);
}
SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a");
SetTextXY(6, 9, "directory where you want ReactOS to be installed:");
- strcpy(InstallDir, "\\reactos");
- Length = strlen(InstallDir);
+ wcscpy(InstallDir, L"\\reactos");
+ Length = wcslen(InstallDir);
SetInputTextXY(8, 11, 51, InstallDir);
}
else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
{
+
return(PREPARE_COPY_PAGE);
}
else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
{
if (Length < 50)
{
- InstallDir[Length] = Ir->Event.KeyEvent.uChar.AsciiChar;
+ InstallDir[Length] = (WCHAR)Ir->Event.KeyEvent.uChar.AsciiChar;
Length++;
InstallDir[Length] = 0;
SetInputTextXY(8, 11, 51, InstallDir);
static ULONG
PrepareCopyPage(PINPUT_RECORD Ir)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- CHAR PathBuffer[MAX_PATH];
- UNICODE_STRING PathName;
- HANDLE DirectoryHandle;
- NTSTATUS Status;
- PCHAR End;
+ WCHAR PathBuffer[MAX_PATH];
+ PINICACHESECTION Section;
+ PINICACHEITERATOR Iterator;
+ PWCHAR KeyName;
+ PWCHAR KeyValue;
ULONG Length;
- ULONG i;
+ NTSTATUS Status;
- PCHAR Dirs[]= {
- "System32",
- "System32\\Config",
- "System32\\Drivers",
- "Inf",
- "Help",
- "Fonts",
- NULL};
SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. ");
SetHighlightedTextXY(50, 12, "Done");
+
+
/* create directories */
SetInvertedTextXY(8, 14, "Create directories");
- /*
- * FIXME: Enumerate the ini section 'Directories' and create all "relative" directories
- */
+ /* Open 'Directories' section */
+ Section = IniCacheGetSection(IniCache,
+ L"Directories");
+ if (Section == NULL)
+ {
+ PopupError("Setup failed to find the 'Directories' section\n"
+ "in TXTSETUP.SIF.\n",
+ "ENTER = Reboot computer");
+ while(TRUE)
+ {
+ ConInKey(Ir);
- /* create the systemroot directory */
- sprintf(PathBuffer,
- "\\Device\\Harddisk%lu\\Partition%lu",
- PartData.DiskNumber,
- PartData.PartNumber);
- if (InstallDir[0] != '\\')
- strcat(PathBuffer, "\\");
- strcat(PathBuffer, InstallDir);
+ if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+ {
+ return(QUIT_PAGE);
+ }
+ }
+ }
+
+ /*
+ * FIXME:
+ * Install directories like '\reactos\test' are not handled yet.
+ */
- /* remove trailing backslash */
- Length = strlen(PathBuffer);
+ /* Build full install directory name */
+ swprintf(PathBuffer,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ PartData.DiskNumber,
+ PartData.PartNumber);
+ if (InstallDir[0] != L'\\')
+ wcscat(PathBuffer, L"\\");
+ wcscat(PathBuffer, InstallDir);
+
+ /* Remove trailing backslash */
+ Length = wcslen(PathBuffer);
if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
PathBuffer[Length - 1] = 0;
- RtlCreateUnicodeStringFromAsciiz(&PathName,
- PathBuffer);
-
- ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
- ObjectAttributes.RootDirectory = NULL;
- ObjectAttributes.ObjectName = &PathName;
- ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
- ObjectAttributes.SecurityDescriptor = NULL;
- ObjectAttributes.SecurityQualityOfService = NULL;
-
- Status = NtCreateFile(&DirectoryHandle,
- DIRECTORY_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_DIRECTORY,
- 0,
- FILE_CREATE,
- FILE_DIRECTORY_FILE,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- PrintTextXY(6, 25, "Creating directory failed: Status = 0x%08lx", Status);
-
- }
- else
- {
- PrintTextXY(6, 25, "Created directory.");
- NtClose (DirectoryHandle);
- }
-
+ /* Create the install directory */
+ Status = CreateDirectory(PathBuffer);
+ if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
+ {
+ DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
- RtlFreeUnicodeString(&PathName);
+ PopupError("Setup could not create the install directory.",
+ "ENTER = Reboot computer");
+ while(TRUE)
+ {
+ ConInKey(Ir);
- /* create the subdirectories */
+ if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+ {
+ return(QUIT_PAGE);
+ }
+ }
+ }
- /* append backslash and init end pointer */
- strcat(PathBuffer, "\\");
- Length = strlen(PathBuffer);
- End = &PathBuffer[Length];
- for (i = 0; Dirs[i] != NULL; i++)
+ /* Enumerate the directory values and create the subdirectories */
+ Iterator = IniCacheFindFirstValue(Section,
+ &KeyName,
+ &KeyValue);
+ if (Iterator != NULL)
+ {
+ do
{
- strcpy(End, Dirs[i]);
-
-
- RtlCreateUnicodeStringFromAsciiz(&PathName,
- PathBuffer);
-
-
- ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
- ObjectAttributes.RootDirectory = NULL;
- ObjectAttributes.ObjectName = &PathName;
- ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
- ObjectAttributes.SecurityDescriptor = NULL;
- ObjectAttributes.SecurityQualityOfService = NULL;
-
- Status = NtCreateFile(&DirectoryHandle,
- DIRECTORY_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_DIRECTORY,
- 0,
- FILE_CREATE,
- FILE_DIRECTORY_FILE,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- PrintTextXY(6, 25, "Creating directory failed: Status = 0x%08lx", Status);
- }
- else
- {
- PrintTextXY(6, 25, "Created directory.");
- NtClose (DirectoryHandle);
- }
+ if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
+ {
+ DPRINT("Absolute Path: '%S'\n", KeyValue);
+
+ swprintf(PathBuffer,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ PartData.DiskNumber,
+ PartData.PartNumber);
+ wcscat(PathBuffer, KeyValue);
+
+ DPRINT("FullPath: '%S'\n", PathBuffer);
+ }
+ else if (KeyValue[0] != L'\\')
+ {
+ DPRINT("RelativePath: '%S'\n", KeyValue);
+ swprintf(PathBuffer,
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ PartData.DiskNumber,
+ PartData.PartNumber);
+
+ if (InstallDir[0] != L'\\')
+ wcscat(PathBuffer, L"\\");
+ wcscat(PathBuffer, InstallDir);
+ wcscat(PathBuffer, L"\\");
+ wcscat(PathBuffer, KeyValue);
+
+ DPRINT("FullPath: '%S'\n", PathBuffer);
+
+ Status = CreateDirectory(PathBuffer);
+ if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
+ {
+ DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
+
+ PopupError("Setup could not create install directories.",
+ "ENTER = Reboot computer");
+
+ while(TRUE)
+ {
+ ConInKey(Ir);
- RtlFreeUnicodeString(&PathName);
+ if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+ {
+ IniCacheFindClose(Iterator);
+ return(QUIT_PAGE);
+ }
+ }
+ }
+ }
}
+ while (IniCacheFindNextValue(Iterator, &KeyName, &KeyValue));
+
+ IniCacheFindClose(Iterator);
+ }
SetTextXY(8, 14, "Create directories");
0,0,0,0,0);
}
+ PartDataValid = FALSE;
+
Page = START_PAGE;
while (Page != REBOOT_PAGE)
{
ClearScreen();
- SetUnderlinedTextXY(4, 3, " ReactOS 0.0.20 Setup ");
+ SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
switch (Page)
{