* Added ini file suport (Thanks to Royce Mitchell!)

* Improved the partition list.
* Use information from txtsetup.sif to create directories.
* Added basic error handling.

svn path=/trunk/; revision=3753
This commit is contained in:
Eric Kohl 2002-11-13 18:25:18 +00:00
parent d4293289b3
commit 58cbfb764a
11 changed files with 1740 additions and 290 deletions

View file

@ -366,6 +366,57 @@ WriteConsoleOutputCharacters(LPCSTR lpCharacter,
}
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,
@ -892,7 +943,7 @@ 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)
{
COORD coPos;
ULONG Length;
@ -901,16 +952,20 @@ SetInputTextXY(SHORT x, SHORT y, SHORT len, PCHAR Text)
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('_',

View file

@ -108,7 +108,7 @@ VOID
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);

View file

@ -16,7 +16,7 @@
* 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
@ -38,4 +38,4 @@ GetDriveLetter(ULONG DriveNumber,
#endif /* __DRIVESUP_H__ */
/* EOF */
/* EOF */

View file

@ -0,0 +1,79 @@
/*
* 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 */

View file

@ -0,0 +1,36 @@
/*
* 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 */

View file

@ -0,0 +1,841 @@
/*
* 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 */

View file

@ -0,0 +1,104 @@
/*
* 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 */

View file

@ -1,4 +1,4 @@
# $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 = ../../..
@ -12,7 +12,7 @@ TARGET_INSTALLDIR = system32
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

View file

@ -16,7 +16,7 @@
* 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
@ -39,6 +39,88 @@
/* 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,
@ -49,16 +131,15 @@ CreatePartitionList(SHORT Left,
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)
@ -96,11 +177,11 @@ CreatePartitionList(SHORT Left,
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);
@ -144,17 +225,17 @@ CreatePartitionList(SHORT Left,
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);
@ -171,31 +252,9 @@ CreatePartitionList(SHORT Left,
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);
@ -203,9 +262,9 @@ CreatePartitionList(SHORT Left,
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;
}
}
@ -321,9 +380,8 @@ PrintPartitionData(PPARTLIST List,
ULONGLONG PartSize;
PCHAR Unit;
PCHAR PartType;
UCHAR Attribute;
PCHAR PartType;
Width = List->Right - List->Left - 1;
Height = List->Bottom - List->Top - 1;
@ -336,33 +394,38 @@ PrintPartitionData(PPARTLIST List,
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))
/* Determine partition type */
PartType = NULL;
if (PartEntry->Unpartitioned == FALSE)
{
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
{
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";
@ -370,29 +433,58 @@ PrintPartitionData(PPARTLIST List,
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);
}
@ -435,7 +527,6 @@ PrintDiskData(PPARTLIST List,
ULONGLONG DiskSize;
PCHAR Unit;
SHORT PartIndex;
BOOL PartPrinted;
DiskEntry = &List->DiskArray[DiskIndex];
@ -448,24 +539,23 @@ PrintDiskData(PPARTLIST List,
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,
@ -494,25 +584,19 @@ PrintDiskData(PPARTLIST List,
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);
}
@ -582,7 +666,7 @@ DrawPartitionList(PPARTLIST List)
coPos,
&Written);
/* draw upper right corner */
/* draw lower right corner */
coPos.X = List->Right;
coPos.Y = List->Bottom;
FillConsoleOutputCharacter(0xD9, // '+',

View file

@ -16,7 +16,7 @@
* 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
@ -50,6 +50,11 @@ typedef struct _PARTENTRY
ULONG PartType;
CHAR DriveLetter;
CHAR VolumeLabel[17];
CHAR FileSystemName[9];
BOOL Unpartitioned;
BOOL Used;
} PARTENTRY, *PPARTENTRY;

View file

@ -27,9 +27,13 @@
#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"
@ -56,14 +60,16 @@
HANDLE ProcessHeap;
BOOL PartDataValid = FALSE;
BOOLEAN PartDataValid;
PARTDATA PartData;
CHAR InstallDir[51];
WCHAR InstallDir[51];
UNICODE_STRING SourcePath;
UNICODE_STRING SourceRootPath;
PINICACHE IniCache;
/* FUNCTIONS ****************************************************************/
@ -88,6 +94,216 @@ PrintString(char* fmt,...)
}
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
@ -97,65 +313,15 @@ PrintString(char* fmt,...)
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)
{
@ -174,34 +340,11 @@ CHECKPOINT1;
}
}
/* 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
@ -211,6 +354,12 @@ static ULONG
StartPage(PINPUT_RECORD Ir)
{
NTSTATUS Status;
WCHAR FileNameBuffer[MAX_PATH];
UNICODE_STRING FileName;
PINICACHESECTION Section;
PWCHAR Value;
SetStatusText(" Please wait...");
@ -226,12 +375,91 @@ StartPage(PINPUT_RECORD Ir)
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");
@ -246,6 +474,9 @@ StartPage(PINPUT_RECORD Ir)
}
return(START_PAGE);
#endif
return(INTRO_PAGE);
}
@ -607,8 +838,8 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
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);
@ -632,6 +863,7 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
}
else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
{
return(PREPARE_COPY_PAGE);
}
else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
@ -647,7 +879,7 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
{
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);
@ -662,24 +894,14 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
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. ");
@ -701,111 +923,133 @@ PrepareCopyPage(PINPUT_RECORD Ir)
SetHighlightedTextXY(50, 12, "Done");
/* create directories */
SetInvertedTextXY(8, 14, "Create 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);
if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
{
return(QUIT_PAGE);
}
}
}
/*
* FIXME: Enumerate the ini section 'Directories' and create all "relative" directories
* FIXME:
* Install directories like '\reactos\test' are not handled yet.
*/
/* 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);
/* create the systemroot directory */
sprintf(PathBuffer,
"\\Device\\Harddisk%lu\\Partition%lu",
PartData.DiskNumber,
PartData.PartNumber);
if (InstallDir[0] != '\\')
strcat(PathBuffer, "\\");
strcat(PathBuffer, InstallDir);
/* remove trailing backslash */
Length = strlen(PathBuffer);
/* Remove trailing backslash */
Length = wcslen(PathBuffer);
if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
PathBuffer[Length - 1] = 0;
RtlCreateUnicodeStringFromAsciiz(&PathName,
PathBuffer);
/* 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);
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.ObjectName = &PathName;
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
ObjectAttributes.SecurityDescriptor = NULL;
ObjectAttributes.SecurityQualityOfService = NULL;
PopupError("Setup could not create the install directory.",
"ENTER = Reboot computer");
Status = NtCreateFile(&DirectoryHandle,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_DIRECTORY,
0,
FILE_CREATE,
FILE_DIRECTORY_FILE,
NULL,
0);
if (!NT_SUCCESS(Status))
while(TRUE)
{
PrintTextXY(6, 25, "Creating directory failed: Status = 0x%08lx", Status);
ConInKey(Ir);
if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
{
return(QUIT_PAGE);
}
}
else
}
/* Enumerate the directory values and create the subdirectories */
Iterator = IniCacheFindFirstValue(Section,
&KeyName,
&KeyValue);
if (Iterator != NULL)
{
do
{
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);
if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
{
IniCacheFindClose(Iterator);
return(QUIT_PAGE);
}
}
}
}
}
while (IniCacheFindNextValue(Iterator, &KeyName, &KeyValue));
RtlFreeUnicodeString(&PathName);
/* create the subdirectories */
/* append backslash and init end pointer */
strcat(PathBuffer, "\\");
Length = strlen(PathBuffer);
End = &PathBuffer[Length];
for (i = 0; Dirs[i] != NULL; i++)
{
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);
}
RtlFreeUnicodeString(&PathName);
}
IniCacheFindClose(Iterator);
}
SetTextXY(8, 14, "Create directories");
@ -1066,12 +1310,14 @@ NtProcessStartup(PPEB Peb)
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)
{