windows-nt/Source/XPSP1/NT/base/ntsetup/textmode/kernel/dynupdt.c
2020-09-26 16:20:57 +08:00

485 lines
12 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
dynupdt.c
Abstract:
Dynamic Update support for text setup. Portions moved from i386\win31upg.c
Author:
Ovidiu Temereanca (ovidiut) 20-Aug-2000
Revision History:
--*/
#include "spprecmp.h"
#pragma hdrstop
//
// Macros
//
#define MAX_SECTION_NAME_LENGTH 14
#define UPDATES_SECTION_NAME L"updates"
#define UNIPROC_SECTION_NAME L"uniproc"
//
// Globals
//
HANDLE g_UpdatesCabHandle = NULL;
PVOID g_UpdatesSifHandle = NULL;
HANDLE g_UniprocCabHandle = NULL;
PVOID g_UniprocSifHandle = NULL;
WCHAR
SpExtractDriveLetter(
IN PWSTR PathComponent
);
BOOLEAN
SpInitAlternateSource (
VOID
)
{
PWSTR p;
NTSTATUS Status;
ULONG ErrorLine;
WCHAR updatesCab[MAX_PATH];
WCHAR updatesSif[MAX_PATH];
WCHAR updatesSifSection[MAX_SECTION_NAME_LENGTH];
WCHAR uniprocCab[MAX_PATH];
WCHAR uniprocSif[MAX_PATH];
WCHAR uniprocSifSection[MAX_SECTION_NAME_LENGTH];
BOOLEAN bUniprocCab = FALSE;
BOOLEAN b = FALSE;
//
// look if section [SetupParams] has an UpdatedSources key
//
p = SpGetSectionKeyIndex (WinntSifHandle, SIF_SETUPPARAMS, SIF_UPDATEDSOURCES, 0);
if (!p) {
return FALSE;
}
p = SpNtPathFromDosPath (p);
if (!p) {
goto exit;
}
wcscpy (updatesCab, p);
wcscpy (updatesSif, updatesCab);
p = wcsrchr (updatesSif, L'.');
if (!p) {
p = wcsrchr (updatesSif, 0);
}
wcscpy (p, L".sif");
//
// load the sif
//
Status = SpLoadSetupTextFile (
updatesSif,
NULL, // No image already in memory
0, // Image size is empty
&g_UpdatesSifHandle,
&ErrorLine,
FALSE,
FALSE
);
if (!NT_SUCCESS (Status)) {
KdPrintEx((
DPFLTR_SETUP_ID,
DPFLTR_ERROR_LEVEL,
"SETUP: SpInitAlternateSource: Unable to read %ws. ErrorLine = %ld, Status = %lx \n",
updatesSif,
ErrorLine,
Status
));
goto exit;
}
wcscpy (updatesSifSection, UPDATES_SECTION_NAME);
if (!SpSearchTextFileSection (g_UpdatesSifHandle, updatesSifSection) ||
SpCountLinesInSection (g_UpdatesSifHandle, updatesSifSection) == 0) {
KdPrintEx((
DPFLTR_SETUP_ID,
DPFLTR_ERROR_LEVEL,
"SETUP: SpInitAlternateSource: Section [%ws] not found or empty in %ws.\n",
updatesSifSection,
updatesSif
));
goto exit;
}
p = SpGetSectionKeyIndex (WinntSifHandle, SIF_SETUPPARAMS, SIF_UPDATEDSOURCES, 1);
if (p && *p) {
p = SpNtPathFromDosPath (p);
if (!p) {
goto exit;
}
wcscpy (uniprocCab, p);
wcscpy (uniprocSif, uniprocCab);
p = wcsrchr (uniprocSif, L'.');
if (!p) {
p = wcsstr (uniprocSif, 0);
}
wcscpy (p, L".sif");
//
// load the sif
//
Status = SpLoadSetupTextFile (
uniprocSif,
NULL, // No image already in memory
0, // Image size is empty
&g_UniprocSifHandle,
&ErrorLine,
FALSE,
FALSE
);
if (!NT_SUCCESS (Status)) {
KdPrintEx((
DPFLTR_SETUP_ID,
DPFLTR_ERROR_LEVEL,
"SETUP: SpInitAlternateSource: Unable to read %ws. ErrorLine = %ld, Status = %lx \n",
uniprocSif,
ErrorLine,
Status
));
goto exit;
}
wcscpy (uniprocSifSection, UNIPROC_SECTION_NAME);
if (!SpSearchTextFileSection (g_UniprocSifHandle, uniprocSifSection) ||
SpCountLinesInSection (g_UniprocSifHandle, uniprocSifSection) == 0) {
KdPrintEx((
DPFLTR_SETUP_ID,
DPFLTR_ERROR_LEVEL,
"SETUP: SpInitAlternateSource: Section [%ws] not found or empty in %ws.\n",
uniprocSifSection,
uniprocSif
));
goto exit;
}
bUniprocCab = TRUE;
}
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: SpInitAlternateSource: Using alternate sources: %ws\n", updatesCab));
b = SpInitializeUpdatesCab (
updatesCab,
updatesSifSection,
bUniprocCab ? uniprocCab : NULL,
bUniprocCab ? uniprocSifSection : NULL
);
exit:
if (!b) {
SpUninitAlternateSource ();
}
return b;
}
VOID
SpUninitAlternateSource (
VOID
)
{
if (g_UpdatesSifHandle) {
SpFreeTextFile (g_UpdatesSifHandle);
g_UpdatesSifHandle = NULL;
}
if (g_UniprocSifHandle) {
SpFreeTextFile (g_UniprocSifHandle);
g_UniprocSifHandle = NULL;
}
}
BOOLEAN
SpInitializeUpdatesCab (
IN PWSTR UpdatesCab,
IN PWSTR UpdatesSifSection,
IN PWSTR UniprocCab,
IN PWSTR UniprocSifSection
)
{
PWSTR CabFileSection;
NTSTATUS Status;
PWSTR DriverCabName, DriverCabPath;
OBJECT_ATTRIBUTES Obja;
UNICODE_STRING UnicodeString;
IO_STATUS_BLOCK IoStatusBlock;
CABDATA *MyCabData, *MyList = NULL;
DWORD i;
BOOLEAN b = TRUE;
INIT_OBJA (&Obja, &UnicodeString, UpdatesCab);
Status = ZwCreateFile (&g_UpdatesCabHandle,
FILE_GENERIC_READ,
&Obja,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
0,
NULL,
0 );
if (!NT_SUCCESS (Status)) {
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open cab file %ws. Status = %lx \n", UpdatesCab, Status));
return FALSE;
}
//
// create the list entry
//
MyCabData = SpMemAlloc (sizeof(CABDATA));
MyCabData->CabName = SpDupStringW (UpdatesCab);
MyCabData->CabHandle = g_UpdatesCabHandle;
MyCabData->CabSectionName = SpDupStringW (UpdatesSifSection);
MyCabData->CabInfHandle = g_UpdatesSifHandle;
MyCabData->Next = MyList;
MyList = MyCabData;
if (UniprocCab) {
INIT_OBJA (&Obja, &UnicodeString, UniprocCab);
Status = ZwCreateFile (&g_UniprocCabHandle,
FILE_GENERIC_READ,
&Obja,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
0,
NULL,
0 );
if (!NT_SUCCESS (Status)) {
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open cab file %ws. Status = %lx \n", UniprocCab, Status));
b = FALSE;
goto exit;
}
//
// create the list entry
//
MyCabData = SpMemAlloc (sizeof(CABDATA));
MyCabData->CabName = SpDupStringW (UniprocCab);
MyCabData->CabHandle = g_UniprocCabHandle;
MyCabData->CabSectionName = SpDupStringW (UniprocSifSection);
MyCabData->CabInfHandle = g_UniprocSifHandle;
MyCabData->Next = MyList;
MyList = MyCabData;
}
exit:
if (b) {
//
// insert it at the beginning
//
while (MyList && MyList->Next) {
MyList = MyList->Next;
}
if (MyList) {
MyList->Next = CabData;
CabData = MyList;
}
} else {
//
// destroy MyList
//
while (MyList) {
MyCabData = MyList->Next;
MyList = MyCabData;
SpMemFree (MyCabData->CabName);
SpMemFree (MyCabData->CabSectionName);
SpMemFree (MyCabData);
}
}
return b;
}
PWSTR
SpNtPathFromDosPath (
IN PWSTR DosPath
)
{
PDISK_REGION region;
WCHAR drive[_MAX_DRIVE];
WCHAR dir[_MAX_DIR];
WCHAR fname[_MAX_FNAME];
WCHAR ext[_MAX_EXT];
PWSTR p;
if (!DosPath) {
return NULL;
}
region = SpPathComponentToRegion (DosPath);
if (!region) {
return NULL;
}
if (DosPath[2] != L'\\') {
return NULL;
}
SpNtNameFromRegion (region, TemporaryBuffer, ELEMENT_COUNT(TemporaryBuffer), PartitionOrdinalCurrent);
wcscat (TemporaryBuffer, DosPath + 2);
return SpDupStringW (TemporaryBuffer);
}
PDISK_REGION
SpPathComponentToRegion(
IN PWSTR PathComponent
)
/*++
Routine Description:
This routine attempts to locate a region descriptor for a
given DOS path component. If the DOS path component does
not start with x:, then this fails.
Arguments:
PathComponent - supplies a component from the DOS search path,
for which a region esacriptor is desired.
Return Value:
Pointer to disk region; NULL if none found with drive letter
that starts the dos component.
--*/
{
WCHAR c;
ULONG disk;
PDISK_REGION region;
c = SpExtractDriveLetter(PathComponent);
if(!c) {
return(NULL);
}
for(disk=0; disk<HardDiskCount; disk++) {
for(region=PartitionedDisks[disk].PrimaryDiskRegions; region; region=region->Next) {
if(region->DriveLetter == c) {
ASSERT(region->PartitionedSpace);
return(region);
}
}
//
// Do not see extended partition on PC98.
//
for(region=PartitionedDisks[disk].ExtendedDiskRegions; region; region=region->Next) {
if(region->DriveLetter == c) {
ASSERT(region->PartitionedSpace);
return(region);
}
}
}
return(NULL);
}
WCHAR
SpExtractDriveLetter(
IN PWSTR PathComponent
)
{
WCHAR c;
if((wcslen(PathComponent) >= 2) && (PathComponent[1] == L':')) {
c = RtlUpcaseUnicodeChar(PathComponent[0]);
if((c >= L'A') && (c <= L'Z')) {
return(c);
}
}
return(0);
}
PWSTR
SpGetDynamicUpdateBootDriverPath(
IN PWSTR NtBootPath,
IN PWSTR NtBootDir,
IN PVOID InfHandle
)
/*++
Routine Description:
Gets the dynamic update boot driver directory's root
path.
Arguments:
NtBootPath - Boot path in NT namespace
NtBootDir - Boot directory under boot path (like $WIN_NT$.~BT)
InfHandle - Winnt.sif handle
Return Value:
Returns the dynamic update boot driver root path if successful
otherwise returns NULL
--*/
{
PWSTR DriverDir = NULL;
if (NtBootPath && NtBootDir && InfHandle) {
PWSTR Present = SpGetSectionKeyIndex(InfHandle,
WINNT_SETUPPARAMS_W,
WINNT_SP_DYNUPDTBOOTDRIVERPRESENT_W,
0);
PWSTR Dir = SpGetSectionKeyIndex(InfHandle,
WINNT_SETUPPARAMS_W,
WINNT_SP_DYNUPDTBOOTDRIVERROOT_W,
0);
if (Dir && Present && !_wcsicmp(Present, L"yes")) {
WCHAR Buffer[MAX_PATH];
wcscpy(Buffer, NtBootPath);
SpConcatenatePaths(Buffer, NtBootDir);
//
// NOTE : Currently ignore boot driver root path
//
// SpConcatenatePaths(Buffer, Dir);
DriverDir = SpDupStringW(Buffer);
}
}
return DriverDir;
}