Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1075 lines
26 KiB

#include "spprecmp.h"
#pragma hdrstop
PWSTR *NtDirectoryList;
ULONG NtDirectoryCount;
BOOLEAN
SpNFilesExist(
IN OUT PWSTR PathName,
IN PWSTR *Files,
IN ULONG FileCount,
IN BOOLEAN Directories
)
{
UNICODE_STRING UnicodeString;
OBJECT_ATTRIBUTES Obja;
HANDLE Handle;
ULONG i;
PWSTR FilenamePart;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
//
// No reason to call this routine to check for 0 files.
//
ASSERT(FileCount);
//
// Stick a backslash on the end of the path part if necessary.
//
SpConcatenatePaths(PathName,L"");
FilenamePart = PathName + wcslen(PathName);
//
// Check each file. If any one of then doesn't exist,
// then return FALSE.
//
for(i=0; i<FileCount; i++) {
wcscpy(FilenamePart,Files[i]);
INIT_OBJA(&Obja,&UnicodeString,PathName);
Status = ZwCreateFile(
&Handle,
FILE_READ_ATTRIBUTES,
&Obja,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
Directories ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE,
NULL,
0
);
if(NT_SUCCESS(Status)) {
ZwClose(Handle);
} else {
*FilenamePart = 0;
return(FALSE);
}
}
//
// All exist. Return TRUE.
//
*FilenamePart = 0;
return(TRUE);
}
BOOLEAN
SpIsNtInDirectory(
IN PDISK_REGION Region,
IN PWSTR Directory
)
/*++
Routine Description:
Determine whether Windows NT is present on a partition in one of a
set of given directories. This determination is based on the presence
of certain windows nt system files and directories.
Arguments:
Region - supplies the region descriptor for the partition to check.
Directory - supplies the path to check for a windows nt installation.
Return Value:
TRUE if we think we've found Windows NT in the given directory on
the given partition.
--*/
{
PWSTR directories[3] = { L"system32",L"system32\\drivers",L"system32\\config" };
PWSTR files[2] = { L"system32\\ntoskrnl.exe",L"system32\\ntdll.dll" };
PWSTR OpenPath;
BOOLEAN rc;
OpenPath = SpMemAlloc(1024);
//
// Place the fixed part of the name into the buffer.
//
SpNtNameFromRegion(
Region,
OpenPath,
1024,
PartitionOrdinalCurrent
);
SpConcatenatePaths(OpenPath,Directory);
if(SpNFilesExist(OpenPath,directories,ELEMENT_COUNT(directories),TRUE )
&& SpNFilesExist(OpenPath,files ,ELEMENT_COUNT(files) ,FALSE))
{
rc = TRUE;
} else {
rc = FALSE;
}
SpMemFree(OpenPath);
return(rc);
}
VOID
SpGetNtDirectoryList(
OUT PWSTR **DirectoryList,
OUT PULONG DirectoryCount
)
/*++
Routine Description:
Determine the list of directories into which NT may be installed.
This is independent of the partitions onto which it may be installed.
The determination of which directories nt might be in is based on
boot.ini in the x86 case, or on arc firmware (OSLOADFILENAME var)
in the arc case.
Arguments:
DirectoryList - receives a pointer to an array of strings,
each of which contains a possible windows nt tree.
DirectoryCount - receives the number of elements in DirectoryList.
This may be 0.
Return Value:
None. The caller must free the array in DirectoryList if
DirectoryCount is returned as non-0.
--*/
{
ULONG i;
PWSTR *DirList;
DirList = SpGetBootVar( OSLOADFILENAME );
for( i = 0; DirList[i]; i++ ) {
}
*DirectoryList = DirList;
*DirectoryCount = i;
return;
}
ULONG
SpRemoveInstallation(
IN PDISK_REGION Region,
IN PWSTR PartitionPath,
IN PWSTR Directory
)
{
HANDLE Handle;
NTSTATUS Status;
PWSTR FileName;
ULONG Space = 0;
ULONG ClusterSize;
ULONG bps;
PVOID Gauge;
PWSTR Filename;
ULONG FileCount;
ULONG FileSize;
ULONG i;
OBJECT_ATTRIBUTES Obja;
UNICODE_STRING UnicodeString;
IO_STATUS_BLOCK IoStatusBlock;
ULONG ErrLine;
PVOID Inf;
BOOLEAN OldFormatSetupLogFile;
PWSTR SectionName;
HANDLE TempHandle;
ULONG RootDirLength;
PUCHAR UBuffer;
PUCHAR Buffer;
FileName = SpMemAlloc(1024);
//
// Fetch the number of bytes in a sector.
//
bps = HardDisks[Region->DiskNumber].Geometry.BytesPerSector;
//
// Get cluster size from the BPB.
//
ASSERT(Region->Filesystem >= FilesystemFirstKnown);
Status = SpOpenPartition(
HardDisks[Region->DiskNumber].DevicePath,
SpPtGetOrdinal(Region,PartitionOrdinalCurrent),
&Handle,
FALSE
);
if(!NT_SUCCESS(Status)) {
goto xx0;
}
UBuffer = SpMemAlloc(2*bps);
Buffer = ALIGN(UBuffer,bps);
Status = SpReadWriteDiskSectors(
Handle,
0,
1,
bps,
Buffer,
FALSE
);
if(!NT_SUCCESS(Status)) {
ZwClose(Handle);
SpMemFree(UBuffer);
goto xx0;
}
//
// Make sure this sector appears to hold a valid boot sector
// for a hard disk.
//
if((Buffer[510] == 0x55) && (Buffer[511] == 0xaa) && (Buffer[21] == 0xf8)) {
//
// bps * spc.
//
ClusterSize = (ULONG)U_USHORT(Buffer+11) * (ULONG)Buffer[13];
} else {
KdPrint(("SETUP: SpRemoveInstallation: sector 0 on %ws is invalid\n",PartitionPath));
Status = STATUS_UNSUCCESSFUL;
}
ZwClose(Handle);
SpMemFree(UBuffer);
if(!NT_SUCCESS(Status)) {
KdPrint(("SETUP: SpRemoveInstallation: can't get cluster size on %ws\n",PartitionPath));
goto xx0;
}
//
// Find out if the repair directory exists, if it does exist load
// setup.log from the repair directory. Otherwise, load setup.log
// from the WinNt directory
//
wcscpy(FileName,PartitionPath);
SpConcatenatePaths(FileName,Directory);
RootDirLength = wcslen(FileName);
SpConcatenatePaths(FileName,SETUP_REPAIR_DIRECTORY);
INIT_OBJA( &Obja, &UnicodeString, FileName );
Status = ZwOpenFile( &TempHandle,
FILE_LIST_DIRECTORY | SYNCHRONIZE,
&Obja,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
);
if( !NT_SUCCESS( Status ) ) {
FileName[ RootDirLength ] = L'\0';
} else {
ZwClose( TempHandle );
}
SpConcatenatePaths(FileName,SETUP_LOG_FILENAME);
//
// Load setup.log from the given path.
//
Status = SpLoadSetupTextFile(FileName,NULL,0,&Inf,&ErrLine);
if(!NT_SUCCESS(Status)) {
KdPrint(("SETUP: SpRemoveInstallation: can't load inf file %ws (%lx)\n",FileName,Status));
while(1) {
ULONG ks[3] = { ASCI_CR,KEY_F1,0 };
SpStartScreen(
SP_SCRN_CANT_LOAD_SETUP_LOG,
3,
HEADER_HEIGHT+2,
FALSE,
FALSE,
DEFAULT_ATTRIBUTE,
FileName + wcslen(PartitionPath) // skip \device\harddiskx\partitiony
);
SpDisplayStatusOptions(
DEFAULT_STATUS_ATTRIBUTE,
SP_STAT_F1_EQUALS_HELP,
SP_STAT_ENTER_EQUALS_CONTINUE,
0
);
switch(SpWaitValidKey(ks,NULL,NULL)) {
case KEY_F1:
SpHelp(SP_HELP_CANT_LOAD_SETUP_LOG, NULL, SPHELP_HELPTEXT);
break;
case ASCI_CR:
goto xx0;
}
}
}
//
// Go through all files in the [Repair.WinntFiles] section
//
SpStartScreen(
SP_SCRN_WAIT_REMOVING_NT_FILES,
0,
8,
TRUE,
FALSE,
DEFAULT_ATTRIBUTE
);
//
// Determine whether setup.log has the new or old style
//
if( OldFormatSetupLogFile = !IsSetupLogFormatNew( Inf ) ) {
SectionName = SIF_REPAIRWINNTFILES;
} else {
SectionName = SIF_NEW_REPAIR_WINNTFILES;
}
FileCount = SpCountLinesInSection(Inf,SectionName);
SpFormatMessage(
(PWSTR)TemporaryBuffer,
sizeof(TemporaryBuffer),
SP_TEXT_SETUP_IS_REMOVING_FILES
);
Gauge = SpCreateAndDisplayGauge(
FileCount,
0,
VideoVars.ScreenHeight - STATUS_HEIGHT - (3*GAUGE_HEIGHT/2),
(PWSTR)TemporaryBuffer
);
//
// Clear the status area.
//
SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,0);
//
// Set the status text in the lower right portion of the screen
// to "Removing:" in preparation for displaying filenames as
// files are deleted. The 12 is for an 8.3 name.
//
SpDisplayStatusActionLabel(SP_STAT_REMOVING,12);
for(i=0; i<FileCount; i++) {
if( OldFormatSetupLogFile ) {
Filename = SpGetSectionLineIndex(Inf,SectionName,i,1);
} else {
Filename = SpGetKeyName(Inf,SectionName,i);
}
if(Filename) {
PWCHAR p = wcsrchr(Filename,L'\\');
if(p) {
p++;
} else {
p = Filename;
}
#ifdef _X86_
{
//
// Don't remove files in the system directory.
// We might have installed into the windows directory
// so removing files in the system directory would
// wipe out the user's fonts (which are shared between
// 3.1 and nt).
//
PWSTR dup = SpDupStringW(Filename);
SpStringToLower(dup);
if(wcsstr(dup,L"\\system\\")) {
SpMemFree(dup);
SpTickGauge(Gauge);
continue;
}
SpMemFree(dup);
}
#endif
SpDisplayStatusActionObject(p);
//
// Form the full pathname of the file being deleted.
//
wcscpy(FileName,PartitionPath);
SpConcatenatePaths(FileName,Filename);
//
// Open the file.
//
INIT_OBJA(&Obja,&UnicodeString,FileName);
Status = ZwCreateFile(
&Handle,
FILE_READ_ATTRIBUTES,
&Obja,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, // open if exists
FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if(!NT_SUCCESS(Status)) {
KdPrint(("SETUP: SpRemoveInstallation: unable to open %ws (%lx)\n",FileName,Status));
} else {
//
// Get the file size.
//
Status = SpGetFileSize(Handle,&FileSize);
if(!NT_SUCCESS(Status)) {
KdPrint(("SETUP: SpRemoveInstallation: unable to get %ws file size (%lx)\n",FileName,Status));
FileSize = 0;
} else {
//
// Add the size of this file to the running total.
//
if(FileSize % ClusterSize) {
FileSize += ClusterSize - (FileSize % ClusterSize);
}
Space += FileSize;
}
ZwClose(Handle);
//
// Delete the file
//
Status = SpDeleteFile(FileName,NULL,NULL);
if(!NT_SUCCESS(Status)) {
KdPrint(("SETUP: Unable to delete %ws (%lx)\n",FileName,Status));
Space -= FileSize;
}
}
}
SpTickGauge(Gauge);
}
SpFreeTextFile(Inf);
SpDestroyGauge(Gauge);
SpDisplayStatusActionLabel(0,0);
xx0:
SpMemFree(FileName);
return(Space);
}
VOID
SpFreeNtDirectoryList(
IN OUT PWSTR **DirectoryList,
IN OUT PULONG DirectoryCount
)
{
ULONG i;
if(*DirectoryList) {
for(i=0; i<*DirectoryCount; i++) {
if((*DirectoryList)[i]) {
SpMemFree((*DirectoryList)[i]);
(*DirectoryList)[i] = NULL;
}
}
SpMemFree(*DirectoryList);
*DirectoryList = NULL;
*DirectoryCount = 0;
}
}
BOOLEAN
SpIsNtOnPartition(
IN PDISK_REGION Region
)
/*++
Routine Description:
Determine whether there is any Windows NT installed on
a given partition.
Arguments:
PartitionPath - supplies NT path to partition on which we
should look for NT installations.
Return Value:
TRUE if any NT installations were found.
FALSE if not.
--*/
{
ULONG i;
CLEAR_CLIENT_SCREEN();
SpDisplayStatusText(SP_STAT_EXAMINING_DISK_CONFIG,DEFAULT_STATUS_ATTRIBUTE);
// SpFreeNtDirectoryList(&NtDirectoryList,&NtDirectoryCount);
SpGetNtDirectoryList(&NtDirectoryList,&NtDirectoryCount);
for(i=0; i<NtDirectoryCount; i++) {
if(SpIsNtInDirectory(Region,NtDirectoryList[i])) {
return(TRUE);
}
}
return(FALSE);
}
BOOLEAN
SpAllowRemoveNt(
IN PDISK_REGION Region,
IN PWSTR DriveSpec, OPTIONAL
IN BOOLEAN RescanForNTs,
IN ULONG ScreenMsgId,
OUT PULONG SpaceFreed
)
/*++
Routine Description:
Arguments:
ScreenMsgId - supplies the message id of the text that will be
printed above the menu of located nt directories,
to supply instructions, etc.
SpaceFreed - receives amount of disk space created by removing a
Windows NT tree, if this function returns TRUE.
Return Value:
TRUE if any files were actually removed.
FALSE otherwise.
If an error occured, the user will have already been told about it.
--*/
{
ULONG i;
ULONG NtCount;
PULONG MenuOrdinals;
PWSTR *MenuItems;
PWSTR *MenuTemp;
BOOLEAN rc,b;
BOOLEAN Add;
ULONG MenuWidth,MenuLeftX;
PVOID Menu;
PWSTR PartitionPath;
CLEAR_CLIENT_SCREEN();
SpDisplayStatusText(SP_STAT_EXAMINING_DISK_CONFIG,DEFAULT_STATUS_ATTRIBUTE);
PartitionPath = SpMemAlloc(512);
//
// Form the nt pathname for this partition.
//
SpNtNameFromRegion(
Region,
PartitionPath,
512,
PartitionOrdinalCurrent
);
//
// Assume nothing deleted.
//
rc = FALSE;
//
// Go look for Windows NT installations.
//
if(RescanForNTs) {
// SpFreeNtDirectoryList(&NtDirectoryList,&NtDirectoryCount);
SpGetNtDirectoryList(&NtDirectoryList,&NtDirectoryCount);
}
if(!NtDirectoryCount) {
goto xx0;
}
//
// Determine whether any of the NT trees we found are
// on the given partition, and build an association between
// NT trees and their ordinal positions in the menu we will
// present to the user, and the menu itself.
//
NtCount = 0;
MenuOrdinals = SpMemAlloc((NtDirectoryCount+1)*sizeof(ULONG));
MenuItems = SpMemAlloc((NtDirectoryCount+1)*sizeof(PWSTR));
//
// Eliminate potential duplicate entries in the menu
// to be presented to the user.
//
MenuTemp = SpMemAlloc(NtDirectoryCount*sizeof(PWSTR));
for(i=0; i<NtDirectoryCount; i++) {
WCHAR FullName[128];
ULONG j;
_snwprintf(
FullName,
(sizeof(FullName)/sizeof(WCHAR))-1,
L"%s%s",
DriveSpec ? DriveSpec : L"",
NtDirectoryList[i]
);
FullName[(sizeof(FullName)/sizeof(WCHAR))-1] = 0;
//
// If the name is not already in the list, then add it.
//
for(Add=TRUE,j=0; Add && (j<i); j++) {
if(MenuTemp[j] && !_wcsicmp(FullName,MenuTemp[j])) {
Add = FALSE;
}
}
MenuTemp[i] = Add ? SpDupStringW(FullName) : NULL;
}
//
// Construct the menu to be presented to the user by looking in the
// list of directories constructed above.
//
for(i=0; i<NtDirectoryCount; i++) {
if(MenuTemp[i] && SpIsNtInDirectory(Region,NtDirectoryList[i])) {
MenuOrdinals[NtCount] = i;
MenuItems[NtCount] = SpDupStringW(MenuTemp[i]);
NtCount++;
}
}
for(i=0; i<NtDirectoryCount; i++) {
if(MenuTemp[i]) {
SpMemFree(MenuTemp[i]);
}
}
SpMemFree(MenuTemp);
//
// If we found any nt directories on this partition,
// make a menu to present to the user. Otherwise we
// are done here.
//
if(!NtCount) {
goto xx1;
}
MenuOrdinals = SpMemRealloc(MenuOrdinals,(NtCount+1) * sizeof(ULONG));
MenuItems = SpMemRealloc(MenuItems,(NtCount+1) * sizeof(PWSTR));
SpFormatMessage((PWSTR)TemporaryBuffer,sizeof(TemporaryBuffer),SP_TEXT_REMOVE_NO_FILES);
MenuItems[NtCount] = SpDupStringW((PWSTR)TemporaryBuffer);
//
// Determine the width of the widest item.
//
MenuWidth = 0;
for(i=0; i<=NtCount; i++) {
if(SplangGetColumnCount(MenuItems[i]) > MenuWidth) {
MenuWidth = SplangGetColumnCount(MenuItems[i]);
}
}
//
// Use 80-column screen here because that's how the screen text
// above the menu will be formatted.
//
MenuLeftX = 40 - (MenuWidth/2);
//
// Create menu and populate it.
//
SpDisplayScreen(ScreenMsgId,3,HEADER_HEIGHT+1);
Menu = SpMnCreate(
MenuLeftX,
NextMessageTopLine+(SplangQueryMinimizeExtraSpacing() ? 1 : 2),
MenuWidth,
VideoVars.ScreenHeight-STATUS_HEIGHT-NextMessageTopLine-(SplangQueryMinimizeExtraSpacing() ? 2 : 3)
);
for(i=0; i<=NtCount; i++) {
SpMnAddItem(Menu,MenuItems[i],MenuLeftX,MenuWidth,TRUE,i);
}
//
// Present the menu of installations available for removal
// on this partition and await a choice.
//
b = TRUE;
do {
ULONG Keys[4] = { ASCI_CR,KEY_F3,ASCI_ESC,0 };
ULONG Mnemonics[2] = { MnemonicRemoveFiles,0 };
ULONG key,Choice;
SpDisplayScreen(ScreenMsgId,3,HEADER_HEIGHT+1);
SpDisplayStatusOptions(
DEFAULT_STATUS_ATTRIBUTE,
SP_STAT_ESC_EQUALS_CANCEL,
SP_STAT_ENTER_EQUALS_SELECT,
SP_STAT_F3_EQUALS_EXIT,
0
);
nextkey:
SpMnDisplay(Menu,NtCount,FALSE,Keys,NULL,NULL,&key,&Choice);
if(key == KEY_F3) {
SpConfirmExit();
} else if(key == ASCI_ESC) {
break;
} else if(key == ASCI_CR) {
if(Choice == NtCount) {
b = FALSE;
} else {
BOOLEAN keys;
ULONG ValidKeys2[3] = { KEY_F3,ASCI_ESC,0 };
//
// User wants to actually remove an installation.
// Confirm and then do that here.
//
redraw2:
SpStartScreen(
SP_SCRN_REMOVE_EXISTING_NT,
3,
HEADER_HEIGHT+1,
FALSE,
FALSE,
DEFAULT_ATTRIBUTE,
MenuItems[Choice]
);
SpDisplayStatusOptions(
DEFAULT_STATUS_ATTRIBUTE,
SP_STAT_R_EQUALS_REMOVE_FILES,
SP_STAT_ESC_EQUALS_CANCEL,
SP_STAT_F3_EQUALS_EXIT,
0
);
keys = TRUE;
while(keys) {
switch(SpWaitValidKey(ValidKeys2,NULL,Mnemonics)) {
case KEY_F3:
SpConfirmExit();
goto redraw2;
case ASCI_ESC:
keys = FALSE;
break;
default:
//
// Must be r=remove files.
//
*SpaceFreed = SpRemoveInstallation(
Region,
PartitionPath,
NtDirectoryList[MenuOrdinals[Choice]]
);
rc = TRUE;
SpStartScreen(
SP_SCRN_DONE_REMOVING_EXISTING_NT,
4,
HEADER_HEIGHT+3,
FALSE,
FALSE,
DEFAULT_ATTRIBUTE,
*SpaceFreed
);
SpDisplayStatusOptions(
DEFAULT_STATUS_ATTRIBUTE,
SP_STAT_ENTER_EQUALS_CONTINUE,
0
);
while(SpkbdGetKeypress() != ASCI_CR) ;
keys = FALSE;
b = FALSE;
break;
}
}
}
} else {
goto nextkey;
}
} while(b);
SpMnDestroy(Menu);
xx1:
for(i=0; i<=NtCount; i++) {
SpMemFree(MenuItems[i]);
}
SpMemFree(MenuItems);
SpMemFree(MenuOrdinals);
xx0:
SpMemFree(PartitionPath);
return(rc);
}
#if 0
typedef
VOID
(*PINSTALLATION_CALLBACK_ROUTINE)(
IN PWSTR DirectoryPath,
IN PFILE_DIRECTORY_INFORMATION FoundFileInfo
);
//
// Stuff to reduce stack usage.
//
PINSTALLATION_CALLBACK_ROUTINE FileIterationCallback;
POBJECT_ATTRIBUTES FileIterationObja;
PIO_STATUS_BLOCK FileIterationIoStatusBlock;
PUNICODE_STRING FileIterationUnicodeString;
VOID
SpIterateInstallationFilesWorker(
IN PWSTR FilenamePart1,
IN PWSTR FilenamePart2
)
{
PVOID InfoBuffer;
PWSTR FullPath;
NTSTATUS Status;
HANDLE hFile;
BOOLEAN restart;
#define DIRINFO(x) ((PFILE_DIRECTORY_INFORMATION)InfoBuffer)
InfoBuffer = SpMemAlloc(1024);
//
// Form the full path name of the current directory.
//
FullPath = SpMemAlloc( ( wcslen(FilenamePart1)
+ (FilenamePart2 ? wcslen(FilenamePart2) : 0),
+ 2) * sizeof(WCHAR)
);
wcscpy(FullPath,FilenamePart1);
if(FilenamePart2) {
SpConcatenatePaths(FullPath,FilenamePart2);
}
//
// Open the directory for list access.
//
INIT_OBJA(FileIterationObja,FileIterationUnicodeString,FullPath);
Status = ZwOpenFile(
&hFile,
FILE_LIST_DIRECTORY | SYNCHRONIZE,
FileIterationObja,
FileIterationIoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
);
if(NT_SUCCESS(Status)) {
restart = TRUE;
do {
Status = ZwQueryDirectoryFile(
hFile,
NULL,
NULL,
NULL,
FileIterationIoStatusBlock,
InfoBuffer,
1024 - sizeof(WCHAR), // leave room for nul
FileDirectoryInformation,
TRUE, // return single entry
NULL, // no file name (match all files)
restart
);
restart = FALSE;
if(NT_SUCCESS(Status)) {
//
// nul-terminate the filename just in case
//
DIRINFO->FileName[DIRINFO->FileNameLength/sizeof(WCHAR)] = 0;
if(DIRINFO->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if(DIRINFO->FileName[0] != L'.') {
SpIterateInstallationFiles(
FullPath,
DIRINFO->FileName
);
FileIterationCallback(FullPath,InfoBuffer);
}
} else {
FileIterationCallback(FullPath,InfoBuffer);
}
}
} while(NT_SUCCESS(Status));
ZwClose(hFile);
} else {
KdPrint(("SETUP: unable to open directory %ws for list access (%lx)\n",FullPath,Status));
}
SpMemFree(FullPath);
SpMemFree(InfoBuffer);
}
VOID
SpIterateInstallationFiles(
IN PWSTR FilenamePart1,
IN PWSTR FilenamePart2,
IN PINSTALLATION_CALLBACK_ROUTINE CallbackFunction
)
{
//
// Set up stack-saving globals
//
FileIterationIoStatusBlock = SpMemAlloc(sizeof(IO_STATUS_BLOCK);
FileIterationUnicodeString = SpMemAlloc(sizeof(UNICODE_STRING));
FileIterationObja = SpMemAlloc(sizeof(OBJECT_ATTRIBUTES);
FileIterationCallback = CallbackFunction;
//
// Do the iteration.
//
SpIterateInstallationFilesWorker(FileNamePart1,FilenamePart2);
//
// Clean up.
//
SpMemFree(FileIterationObja);
SpMemFree(FileIterationUnicodeString);
SpMemFree(FileIterationIoStatusBlock);
}
#endif
BOOLEAN
IsSetupLogFormatNew(
IN PVOID Inf
)
/*++
Routine Description:
Informs the caller whether or not the information on setup.log
is in the new format.
Arguments:
Inf -
Return Value:
TRUE if the information is in the new format.
FALSE otherwise.
--*/
{
return( SpGetSectionKeyExists ( Inf,
SIF_NEW_REPAIR_SIGNATURE,
SIF_NEW_REPAIR_VERSION_KEY )
);
}