1447 lines
30 KiB
C
1447 lines
30 KiB
C
/*++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
spmisc.h
|
|
|
|
Abstract:
|
|
|
|
Miscellaneous stuff for text setup.
|
|
|
|
Author:
|
|
|
|
Ted Miller (tedm) 29-July-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <crypt.h>
|
|
|
|
#ifndef _SPSETUP_DEFN_
|
|
#define _SPSETUP_DEFN_
|
|
|
|
|
|
extern PWSTR SetupSourceDevicePath;
|
|
extern PWSTR DirectoryOnSetupSource;
|
|
extern PVOID SifHandle;
|
|
extern BOOLEAN Win9xRollback;
|
|
|
|
ULONG
|
|
SpStartSetup(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SpGetWinntParams(
|
|
OUT PWSTR *DevicePath,
|
|
OUT PWSTR *DirectoryOnDevice
|
|
);
|
|
|
|
extern WCHAR TemporaryBuffer[16384];
|
|
|
|
|
|
//
|
|
// TRUE if setup should run in the step-up upgrade mode.
|
|
// In this mode, setup is not allowed to do clean install,
|
|
// and is not allowed to upgrade workstation to server.
|
|
//
|
|
// We also track an evaluation time for the evaluation SKU.
|
|
//
|
|
extern BOOLEAN StepUpMode;
|
|
extern ULONG EvaluationTime;
|
|
extern ULONG RestrictCpu;
|
|
extern ULONG SuiteType;
|
|
|
|
__inline
|
|
BOOLEAN
|
|
SpIsProductSuite(
|
|
DWORD SuiteToCheck
|
|
)
|
|
{
|
|
return (SuiteType & SuiteToCheck) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Non-0 if gui setup is supposed to be restartable.
|
|
// This causes us to do special stuff with hives in spconfig.c.
|
|
//
|
|
extern BOOLEAN RestartableGuiSetup;
|
|
|
|
//
|
|
// TRUE if user chose Repair Winnt
|
|
//
|
|
|
|
extern BOOLEAN RepairWinnt;
|
|
|
|
//
|
|
// TRUE if user chose Custom Setup.
|
|
//
|
|
extern BOOLEAN CustomSetup;
|
|
|
|
//
|
|
// TRUE if floppyless boot
|
|
//
|
|
extern BOOLEAN IsFloppylessBoot;
|
|
|
|
//
|
|
// TRUE is textmode is to pick a partition
|
|
//
|
|
extern BOOLEAN AutoPartitionPicker;
|
|
|
|
//
|
|
// Preferred installation dir
|
|
//
|
|
extern PWSTR PreferredInstallDir;
|
|
|
|
//
|
|
// ARC pathname of the device from which we were started.
|
|
//
|
|
extern PWSTR ArcBootDevicePath;
|
|
|
|
//
|
|
// Gets set to TRUE if the user elects to convert or format to ntfs.
|
|
// And a flag indicating whether we are doing a dirty sleazy hack
|
|
// for oem preinstall.
|
|
//
|
|
extern BOOLEAN ConvertNtVolumeToNtfs;
|
|
extern BOOLEAN ExtendingOemPartition;
|
|
|
|
//
|
|
// TRUE if upgrading NT to NT
|
|
//
|
|
typedef enum _ENUMUPRADETYPE {
|
|
DontUpgrade = 0,
|
|
UpgradeFull,
|
|
UpgradeInstallFresh
|
|
} ENUMUPGRADETYPE;
|
|
|
|
extern ENUMUPGRADETYPE NTUpgrade;
|
|
|
|
extern ENUMUPGRADETYPE IsNTUpgrade;
|
|
|
|
extern ULONG OldMinorVersion,OldMajorVersion;
|
|
|
|
//
|
|
// TRUE if upgrading Workstation to Standard Server, or upgrading
|
|
// existing Standard Server
|
|
//
|
|
extern BOOLEAN StandardServerUpgrade;
|
|
|
|
typedef enum _ENUMNONNTUPRADETYPE {
|
|
NoWinUpgrade = 0,
|
|
UpgradeWin31,
|
|
UpgradeWin95
|
|
} ENUMNONNTUPRADETYPE;
|
|
|
|
//
|
|
// Non-zero if upgrading win31 or win95 to NT.
|
|
//
|
|
extern ENUMNONNTUPRADETYPE WinUpgradeType;
|
|
|
|
//
|
|
// Macros to simplify use of enum type
|
|
//
|
|
|
|
#define ANY_TYPE_OF_UPGRADE (NTUpgrade || WinUpgradeType)
|
|
#define WIN9X_OR_NT_UPGRADE (NTUpgrade == UpgradeFull || WinUpgradeType == UpgradeWin95)
|
|
|
|
//
|
|
// TRUE if this setup was started with winnt.exe.
|
|
// Also a flag indicating whether the local source was not created and we
|
|
// should get files from the CD instead.
|
|
//
|
|
extern BOOLEAN WinntSetup;
|
|
extern BOOLEAN WinntFromCd;
|
|
|
|
#ifdef _X86_
|
|
//
|
|
// TRUE if this setup was started with winnt95.exe.
|
|
//
|
|
extern BOOLEAN Winnt95Setup;
|
|
#endif
|
|
|
|
//
|
|
// TRUE if any of the accessibility options was selected
|
|
//
|
|
extern BOOLEAN AccessibleSetup;
|
|
//
|
|
// If this is an unattended setup, this value will be a TRUE
|
|
//
|
|
extern BOOLEAN UnattendedOperation;
|
|
//
|
|
// If there is an Unattended GUI section, this value will be TRUE
|
|
//
|
|
extern BOOLEAN UnattendedGuiOperation;
|
|
//
|
|
// This value is strictly a pointer to the WINNT.SIF file in the
|
|
// case that Unattended operation occurs in either the textmode
|
|
// or GUI Mode case. It has been kept to avoid changing large
|
|
// sections of code.
|
|
//
|
|
extern PVOID UnattendedSifHandle;
|
|
//
|
|
// This value is a non-null pointer to the WINNT.SIF file. It is
|
|
// initialized when the driver is started. Any parameter which is
|
|
// to be passed to GUI mode is added to the WINNT.SIF file by
|
|
// referencing this parameter.
|
|
//
|
|
extern PVOID WinntSifHandle;
|
|
extern BOOLEAN SkipMissingFiles;
|
|
extern BOOLEAN HideWinDir;
|
|
|
|
|
|
//
|
|
// this value is a non-null pointer to the drvindex.inf file. It is
|
|
// initialized on startup. The list of files that are present in our
|
|
// driver cab file are indexed in this inf, so we can quickly look if a
|
|
// file is present in the cab
|
|
//
|
|
extern PVOID DriverInfHandle;
|
|
|
|
|
|
//
|
|
// This structure will keep track of all the cabs
|
|
// that we'll be installing from.
|
|
//
|
|
typedef struct _CABDATA {
|
|
struct _CABDATA *Next;
|
|
PWSTR CabName;
|
|
HANDLE CabHandle;
|
|
PWSTR CabSectionName;
|
|
PVOID CabInfHandle;
|
|
} CABDATA;
|
|
|
|
extern CABDATA *CabData;
|
|
|
|
//
|
|
// handle to delta.inf, used for private testing
|
|
//
|
|
extern PVOID PrivateInfHandle;
|
|
|
|
#ifdef _X86_
|
|
//
|
|
// WINNT95 may turn this flag on, it is off by default for everything
|
|
// else.
|
|
//
|
|
|
|
extern BOOLEAN MigrateOption;
|
|
#endif
|
|
|
|
|
|
//
|
|
// This is a handle to txtsetup.oem, used on pre-install mode.
|
|
//
|
|
extern PVOID PreinstallOemSifHandle;
|
|
|
|
|
|
//
|
|
// On unattended mode, indicates whether OEM files
|
|
// that have same name as Microsoft files released
|
|
// with the product should be overwritten.
|
|
//
|
|
extern BOOLEAN UnattendedOverwriteOem;
|
|
|
|
//
|
|
// On unattended mode, indicates that this is is
|
|
// an OEM pre-installation
|
|
//
|
|
extern BOOLEAN PreInstall;
|
|
|
|
|
|
//
|
|
// On pre-install mode, points to the directory that contains the files
|
|
// that need to be copied during textmode setup
|
|
//
|
|
extern PWSTR PreinstallOemSourcePath;
|
|
|
|
//
|
|
// Flags that indicate the type of mice detected in the machine.
|
|
// Note that more than one type of mice may be present.
|
|
//
|
|
extern BOOLEAN UsbMouseDetected;
|
|
extern BOOLEAN PS2MouseDetected;
|
|
extern BOOLEAN SerMouseDetected;
|
|
|
|
//
|
|
// Flags that indicate the type of keyboard detected in the machine.
|
|
// Note that more than one type of keyborad may be present.
|
|
//
|
|
extern BOOLEAN UsbKeyboardDetected;
|
|
extern BOOLEAN StdKeyboardDetected;
|
|
|
|
//
|
|
// This flag identifies "dockable" machines (portables)
|
|
// so that we can disble dynamic volumes on them
|
|
//
|
|
extern BOOLEAN DockableMachine;
|
|
|
|
//
|
|
// Variable used during the repair process, that indicates that the
|
|
// system has no CD-ROM drive.
|
|
// This is a hack that we did for World Bank so that they can repair
|
|
// the hives even if they don't have a CD-ROM drive.
|
|
//
|
|
extern BOOLEAN RepairNoCDROMDrive;
|
|
|
|
//
|
|
// RemoteBootSetup is true when Source and target paths are through the redirector
|
|
// with possibly no system partition.
|
|
//
|
|
// RemoteInstallSetup is true when we are doing a remote install.
|
|
//
|
|
// RemoteSysPrepSetup is true when we are doing a remote install of a sys prep image.
|
|
//
|
|
// RemoteSysPrepVolumeIsNtfs is true when the sysprep image we're copying down
|
|
// represents an ntfs volume.
|
|
//
|
|
|
|
extern BOOLEAN RemoteBootSetup;
|
|
extern BOOLEAN RemoteInstallSetup;
|
|
extern BOOLEAN RemoteSysPrepSetup;
|
|
extern BOOLEAN RemoteSysPrepVolumeIsNtfs;
|
|
|
|
//
|
|
// setupldr may pass us the administrator password in a remote install
|
|
// if the user is prompted for the password.
|
|
//
|
|
extern PWSTR NetBootAdministratorPassword;
|
|
|
|
|
|
|
|
extern BOOLEAN NoLs;
|
|
|
|
//
|
|
// Source and target paths are through the redirector with possibly no
|
|
// system partition,
|
|
//
|
|
|
|
extern BOOLEAN RemoteBootSetup;
|
|
|
|
//
|
|
// Filename of local source directory.
|
|
//
|
|
extern PWSTR LocalSourceDirectory;
|
|
|
|
//
|
|
// Platform-specific extension, used when creating names of sections
|
|
// in sif/inf files.
|
|
//
|
|
extern PWSTR PlatformExtension;
|
|
|
|
//
|
|
// TRUE if this is advanced server we're setting up.
|
|
//
|
|
extern BOOLEAN AdvancedServer;
|
|
|
|
//
|
|
// Windows NT Version.
|
|
//
|
|
extern ULONG WinntMajorVer;
|
|
extern ULONG WinntMinorVer;
|
|
|
|
//
|
|
// Representation of the boot device path in the nt namespace.
|
|
//
|
|
extern PWSTR NtBootDevicePath;
|
|
extern PWSTR DirectoryOnBootDevice;
|
|
|
|
//
|
|
// Setup parameters passed to us by setupldr.
|
|
//
|
|
extern SETUP_LOADER_BLOCK_SCALARS SetupParameters;
|
|
|
|
//
|
|
// System information gathered by the user-mode part of text setup
|
|
// and passed to us in IOCTL_SETUP_START
|
|
//
|
|
extern SYSTEM_BASIC_INFORMATION SystemBasicInfo;
|
|
|
|
//
|
|
// Flags indicating whether or not keyboard and video have been initialized
|
|
//
|
|
extern BOOLEAN VideoInitialized, KeyboardInitialized, KbdLayoutInitialized;
|
|
|
|
//
|
|
// ARC disk/signature information structure.
|
|
// A list of these is created during phase0 initialization.
|
|
//
|
|
typedef struct _DISK_SIGNATURE_INFORMATION {
|
|
struct _DISK_SIGNATURE_INFORMATION *Next;
|
|
ULONG Signature;
|
|
PWSTR ArcPath;
|
|
ULONG CheckSum;
|
|
BOOLEAN ValidPartitionTable;
|
|
BOOLEAN xInt13;
|
|
} DISK_SIGNATURE_INFORMATION, *PDISK_SIGNATURE_INFORMATION;
|
|
|
|
extern PDISK_SIGNATURE_INFORMATION DiskSignatureInformation;
|
|
|
|
//
|
|
// Flag indicating whether or not pcmcia driver has been initialized
|
|
//
|
|
|
|
extern BOOLEAN PcmciaLoaded;
|
|
|
|
//
|
|
// Flag indicating whether or not atapi driver has been initialized
|
|
//
|
|
|
|
extern BOOLEAN AtapiLoaded;
|
|
|
|
//
|
|
// Array with the PIDs of all NT greater than 4.x found in the machine (PID 2.0)
|
|
// The values in this array will be saved under Setup\PID key in the registry,
|
|
// and will be used during GUI setup
|
|
//
|
|
extern PWSTR* Pid20Array;
|
|
|
|
//
|
|
// Product Id read from setup.ini
|
|
//
|
|
extern PWSTR PidString;
|
|
|
|
//
|
|
// Object types.
|
|
//
|
|
extern POBJECT_TYPE *IoFileObjectType;
|
|
extern POBJECT_TYPE *IoDeviceObjectType;
|
|
|
|
|
|
//
|
|
// Gauge used to report progress of autochk and autofmt
|
|
//
|
|
extern PVOID UserModeGauge;
|
|
|
|
//
|
|
// This variable is used when displaying the progress bar
|
|
// during autochk and autofmt. It indicates the disk that
|
|
// is being autochecked or formatted.
|
|
//
|
|
extern ULONG CurrentDiskIndex;
|
|
|
|
//
|
|
// Process structure for usetup.exe
|
|
//
|
|
extern PEPROCESS UsetupProcess;
|
|
|
|
//
|
|
// Setup fatal error codes.
|
|
//
|
|
// If you add anything here, you must also update ntos\nls\bugcodes.txt.
|
|
//
|
|
#define SETUP_BUGCHECK_BAD_OEM_FONT 0
|
|
#define SETUP_BUGCHECK_BOOTPATH 4
|
|
#define SETUP_BUGCHECK_PARTITION 5
|
|
#define SETUP_BUGCHECK_BOOTMSGS 6
|
|
|
|
//
|
|
// The following error codes are no longer used, because we have friendlier
|
|
// error messages for them.
|
|
//
|
|
// #define SETUP_BUGCHECK_VIDEO 1
|
|
// #define SETUP_BUGCHECK_MEMORY 2
|
|
// #define SETUP_BUGCHECK_KEYBOARD 3
|
|
|
|
|
|
//
|
|
// Video-specific bugcheck subcodes.
|
|
//
|
|
#define VIDEOBUG_OPEN 0
|
|
#define VIDEOBUG_GETNUMMODES 1
|
|
#define VIDEOBUG_GETMODES 2
|
|
#define VIDEOBUG_BADMODE 3
|
|
#define VIDEOBUG_SETMODE 4
|
|
#define VIDEOBUG_MAP 5
|
|
#define VIDEOBUG_SETFONT 6
|
|
|
|
//
|
|
// Partition sanity check bugcheck subcodes.
|
|
//
|
|
#define PARTITIONBUG_A 0
|
|
#define PARTITIONBUG_B 1
|
|
|
|
//
|
|
// Use the following enum to access line draw characters in
|
|
// the LineChars array.
|
|
//
|
|
|
|
typedef enum {
|
|
LineCharDoubleUpperLeft = 0,
|
|
LineCharDoubleUpperRight,
|
|
LineCharDoubleLowerLeft,
|
|
LineCharDoubleLowerRight,
|
|
LineCharDoubleHorizontal,
|
|
LineCharDoubleVertical,
|
|
LineCharSingleUpperLeft,
|
|
LineCharSingleUpperRight,
|
|
LineCharSingleLowerLeft,
|
|
LineCharSingleLowerRight,
|
|
LineCharSingleHorizontal,
|
|
LineCharSingleVertical,
|
|
LineCharDoubleVerticalToSingleHorizontalRight,
|
|
LineCharDoubleVerticalToSingleHorizontalLeft,
|
|
LineCharMax
|
|
} LineCharIndex;
|
|
|
|
extern WCHAR LineChars[LineCharMax];
|
|
|
|
|
|
//
|
|
// Remember whether or not we write out an ntbootdd.sys
|
|
//
|
|
typedef struct _HARDWAREIDLIST {
|
|
struct _HARDWAREIDLIST *Next;
|
|
PWSTR HardwareID;
|
|
} HARDWAREIDLIST;
|
|
|
|
extern HARDWAREIDLIST *HardwareIDList;
|
|
extern BOOLEAN ForceBIOSBoot;
|
|
|
|
//
|
|
// Structure used to track a gauge.
|
|
//
|
|
typedef struct _GAS_GAUGE {
|
|
|
|
//
|
|
// upper left corner of outside of gauge.
|
|
//
|
|
ULONG GaugeX,GaugeY;
|
|
|
|
//
|
|
// Total width of gauge.
|
|
//
|
|
ULONG GaugeW;
|
|
|
|
//
|
|
// upper left corner of thermometer box.
|
|
//
|
|
ULONG ThermX,ThermY;
|
|
|
|
//
|
|
// Width of thermometer box.
|
|
//
|
|
ULONG ThermW;
|
|
|
|
//
|
|
// Total items reperesented by 100%
|
|
//
|
|
ULONG ItemCount;
|
|
|
|
//
|
|
// Items elapsed.
|
|
//
|
|
ULONG ItemsElapsed;
|
|
|
|
//
|
|
// Current percentage represented by ItemsElapsed.
|
|
//
|
|
ULONG CurrentPercentage;
|
|
|
|
//
|
|
// Caption text.
|
|
//
|
|
PWCHAR Caption;
|
|
|
|
//
|
|
// Absolute string
|
|
//
|
|
PWCHAR ProgressFmtStr;
|
|
ULONG ProgressFmtWidth;
|
|
|
|
//
|
|
// Flags controlling what value to print
|
|
//
|
|
ULONG Flags;
|
|
|
|
//
|
|
// Color for the gauge bar
|
|
//
|
|
UCHAR Attribute;
|
|
|
|
//
|
|
// Buffer used for drawing.
|
|
//
|
|
PWCHAR Buffer;
|
|
|
|
} GAS_GAUGE, *PGAS_GAUGE;
|
|
|
|
//
|
|
// Indicates whether autochk or autofmt are running
|
|
//
|
|
extern BOOLEAN AutochkRunning;
|
|
extern BOOLEAN AutofrmtRunning;
|
|
|
|
//
|
|
// Various textmode setup progress events
|
|
//
|
|
typedef enum {
|
|
CallbackEvent,
|
|
InitializationEvent,
|
|
PartitioningEvent,
|
|
FileCopyEvent,
|
|
BackupEvent,
|
|
UninstallEvent,
|
|
SavingSettingsEvent,
|
|
SetupCompletedEvent
|
|
} TM_SETUP_MAJOR_EVENT;
|
|
|
|
typedef enum {
|
|
CallbackInitialize,
|
|
CallbackDeInitialize,
|
|
InitializationStartEvent,
|
|
InitializationEndEvent,
|
|
PartitioningStartEvent,
|
|
ScanDisksEvent,
|
|
ScanDiskEvent,
|
|
CreatePartitionEvent,
|
|
DeletePartitionEvent,
|
|
FormatPartitionEvent,
|
|
ValidatePartitionEvent,
|
|
PartitioningEventEnd,
|
|
FileCopyStartEvent,
|
|
OneFileCopyEvent,
|
|
FileCopyEndEvent,
|
|
SavingSettingsStartEvent,
|
|
InitializeHiveEvent,
|
|
SaveHiveEvent,
|
|
HiveProcessingEndEvent,
|
|
SavingSettingsEndEvent,
|
|
ShutdownEvent,
|
|
UninstallStartEvent,
|
|
UninstallUpdateEvent,
|
|
UninstallEndEvent,
|
|
BackupStartEvent,
|
|
BackupEndEvent,
|
|
OneFileBackedUpEvent
|
|
} TM_SETUP_MINOR_EVENT;
|
|
|
|
typedef VOID (*TM_SETUP_PROGRESS_CALLBACK) (
|
|
IN TM_SETUP_MAJOR_EVENT MajorEvent,
|
|
IN TM_SETUP_MINOR_EVENT MinorEvent,
|
|
IN PVOID Context,
|
|
IN PVOID EventData
|
|
);
|
|
|
|
typedef struct _TM_PROGRESS_SUBSCRIBER {
|
|
TM_SETUP_PROGRESS_CALLBACK Callback;
|
|
PVOID Context;
|
|
} TM_PROGRESS_SUBSCRIBER, *PTM_PROGRESS_SUBSCRIBER;
|
|
|
|
|
|
NTSTATUS
|
|
RegisterSetupProgressCallback(
|
|
IN TM_SETUP_PROGRESS_CALLBACK CallBack,
|
|
IN PVOID Context
|
|
);
|
|
|
|
NTSTATUS
|
|
DeregisterSetupProgressCallback(
|
|
IN TM_SETUP_PROGRESS_CALLBACK CallBack,
|
|
IN PVOID Context
|
|
);
|
|
|
|
VOID
|
|
SendSetupProgressEvent(
|
|
IN TM_SETUP_MAJOR_EVENT MajorEvent,
|
|
IN TM_SETUP_MINOR_EVENT MinorEvent,
|
|
IN PVOID EventData
|
|
);
|
|
|
|
//
|
|
// Enumerate the possible returns values from SpEnumFiles()
|
|
//
|
|
typedef enum {
|
|
NormalReturn, // if the whole process completes uninterrupted
|
|
EnumFileError, // if an error occurs while enumerating files
|
|
CallbackReturn // if the callback returns FALSE, causing termination
|
|
} ENUMFILESRESULT;
|
|
|
|
typedef BOOLEAN (*ENUMFILESPROC) (
|
|
IN PCWSTR,
|
|
IN PFILE_BOTH_DIR_INFORMATION,
|
|
OUT PULONG,
|
|
IN PVOID
|
|
);
|
|
|
|
ENUMFILESRESULT
|
|
SpEnumFiles(
|
|
IN PCWSTR DirName,
|
|
IN ENUMFILESPROC EnumFilesProc,
|
|
OUT PULONG ReturnData,
|
|
IN PVOID Pointer
|
|
);
|
|
|
|
ENUMFILESRESULT
|
|
SpEnumFilesRecursive (
|
|
IN PWSTR DirName,
|
|
IN ENUMFILESPROC EnumFilesProc,
|
|
OUT PULONG ReturnData,
|
|
IN PVOID Pointer OPTIONAL
|
|
);
|
|
|
|
ENUMFILESRESULT
|
|
SpEnumFilesRecursiveLimited (
|
|
IN PWSTR DirName,
|
|
IN ENUMFILESPROC EnumFilesProc,
|
|
IN ULONG MaxDepth,
|
|
IN ULONG CurrentDepth,
|
|
OUT PULONG ReturnData,
|
|
IN PVOID p1 OPTIONAL
|
|
);
|
|
|
|
ENUMFILESRESULT
|
|
SpEnumFilesRecursiveDel (
|
|
IN PWSTR DirName,
|
|
IN ENUMFILESPROC EnumFilesProc,
|
|
OUT PULONG ReturnData,
|
|
IN PVOID p1 OPTIONAL
|
|
);
|
|
|
|
#define SecToNano(_sec) (LONGLONG)((_sec) * 1000 * 1000 * 10)
|
|
|
|
//
|
|
// This macro filters in-page exceptions, which occur if there is
|
|
// an I/O error while the memory manager is paging in parts of a
|
|
// memory-mapped file. Access to such data should be guarded with SEH!
|
|
//
|
|
#define IN_PAGE_ERROR \
|
|
\
|
|
((GetExceptionCode() == STATUS_IN_PAGE_ERROR) \
|
|
? EXCEPTION_EXECUTE_HANDLER \
|
|
: EXCEPTION_CONTINUE_SEARCH)
|
|
|
|
|
|
//
|
|
// Helper macro to make object attribute initialization a little cleaner.
|
|
//
|
|
#define INIT_OBJA(Obja,UnicodeString,UnicodeText) \
|
|
\
|
|
RtlInitUnicodeString((UnicodeString),(UnicodeText)); \
|
|
\
|
|
InitializeObjectAttributes( \
|
|
(Obja), \
|
|
(UnicodeString), \
|
|
OBJ_CASE_INSENSITIVE, \
|
|
NULL, \
|
|
NULL \
|
|
)
|
|
|
|
//
|
|
// Macro to align a buffer.
|
|
//
|
|
#define ALIGN(p,val) \
|
|
\
|
|
(PVOID)((((ULONG_PTR)(p) + (val) - 1)) & (~((ULONG_PTR)((val) - 1))))
|
|
|
|
|
|
//
|
|
// Macro to determine the number of elements in a statically
|
|
// initialized array.
|
|
//
|
|
#define ELEMENT_COUNT(x) (sizeof(x)/sizeof(x[0]))
|
|
|
|
//
|
|
// Marcos to pull potentially unaligned values from memory.
|
|
//
|
|
#define U_USHORT(p) (*(USHORT UNALIGNED *)(p))
|
|
#define U_ULONG(p) (*(ULONG UNALIGNED *)(p))
|
|
#define U_ULONGLONG(p) (*(ULONGLONG UNALIGNED *)(p))
|
|
|
|
|
|
|
|
typedef struct _SP_MIG_DRIVER_ENTRY {
|
|
LIST_ENTRY ListEntry;
|
|
PWSTR BaseDllName;
|
|
} SP_MIG_DRIVER_ENTRY, *PSP_MIG_DRIVER_ENTRY;
|
|
|
|
extern LIST_ENTRY MigratedDriversList;
|
|
|
|
BOOL
|
|
SpRememberMigratedDrivers (
|
|
OUT PLIST_ENTRY List,
|
|
IN PDETECTED_DEVICE SetupldrList
|
|
);
|
|
|
|
|
|
//
|
|
// Setup media types. Setup can be started from one media
|
|
// (ie, floppy) and copy files from another (ie, cd-rom).
|
|
//
|
|
typedef enum {
|
|
SetupBootMedia,
|
|
SetupSourceMedia
|
|
} SetupMediaType;
|
|
|
|
|
|
//
|
|
// Upgrade-specific routines.
|
|
//
|
|
VOID
|
|
SpPrepareFontsForUpgrade(
|
|
IN PCWSTR SystemDirectory
|
|
);
|
|
|
|
//
|
|
// User-mode services.
|
|
//
|
|
NTSTATUS
|
|
SpExecuteImage(
|
|
IN PWSTR ImagePath,
|
|
OUT PULONG ReturnStatus, OPTIONAL
|
|
IN ULONG ArgumentCount,
|
|
... // argv[0] is generated automatically
|
|
);
|
|
|
|
NTSTATUS
|
|
SpLoadUnloadKey(
|
|
IN HANDLE TargetKeyRootDirectory, OPTIONAL
|
|
IN HANDLE SourceFileRootDirectory, OPTIONAL
|
|
IN PWSTR TargetKeyName,
|
|
IN PWSTR SourceFileName OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SpDeleteKey(
|
|
IN HANDLE KeyRootDirectory, OPTIONAL
|
|
IN PWSTR Key
|
|
);
|
|
|
|
NTSTATUS
|
|
SpQueryDirectoryObject(
|
|
IN HANDLE DirectoryHandle,
|
|
IN BOOLEAN RestartScan,
|
|
IN OUT PULONG Context
|
|
);
|
|
|
|
NTSTATUS
|
|
SpFlushVirtualMemory(
|
|
IN PVOID BaseAddress,
|
|
IN ULONG RangeLength
|
|
);
|
|
|
|
VOID
|
|
SpShutdownSystem(
|
|
VOID
|
|
);
|
|
|
|
NTSTATUS
|
|
SpLoadKbdLayoutDll(
|
|
IN PWSTR Directory,
|
|
IN PWSTR DllName,
|
|
OUT PVOID *TableAddress
|
|
);
|
|
|
|
NTSTATUS
|
|
SpVerifyFileAccess(
|
|
IN PWSTR FileName,
|
|
IN ACCESS_MASK DesiredAccess
|
|
);
|
|
|
|
NTSTATUS
|
|
SpSetDefaultFileSecurity(
|
|
IN PWSTR FileName
|
|
);
|
|
|
|
NTSTATUS
|
|
SpCreatePageFile(
|
|
IN PWSTR FileName,
|
|
IN ULONG MinSize,
|
|
IN ULONG MaxSize
|
|
);
|
|
|
|
NTSTATUS
|
|
SpGetFullPathName(
|
|
IN OUT PWSTR FileName
|
|
);
|
|
|
|
NTSTATUS
|
|
SpDecryptPassword(
|
|
PENCRYPTED_NT_OWF_PASSWORD PasswordData,
|
|
ULONG PasswordDataLength,
|
|
ULONG Rid,
|
|
PNT_OWF_PASSWORD NtOwfPassword
|
|
);
|
|
|
|
//
|
|
// Registry Hives. We pass around the keys to the hives
|
|
// in an array. Use the following enum values to access
|
|
// the hive members
|
|
//
|
|
typedef enum {
|
|
SetupHiveSystem,
|
|
SetupHiveSoftware,
|
|
SetupHiveDefault,
|
|
SetupHiveUserdiff,
|
|
SetupHiveMax
|
|
} SetupHive;
|
|
|
|
//
|
|
// Function to set up registry.
|
|
//
|
|
VOID
|
|
SpInitializeRegistry(
|
|
IN PVOID SifHandle,
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice,
|
|
IN PWSTR SpecialDevicePath OPTIONAL,
|
|
IN PDISK_REGION SystemPartitionRegion
|
|
);
|
|
|
|
NTSTATUS
|
|
SpThirdPartyRegistry(
|
|
IN PVOID hKeyControlSetServices
|
|
);
|
|
|
|
|
|
//
|
|
// Function to examine a target registry
|
|
//
|
|
|
|
typedef enum {
|
|
UpgradeNotInProgress = 0,
|
|
UpgradeInProgress,
|
|
UpgradeMaxValue
|
|
} UPG_PROGRESS_TYPE;
|
|
|
|
|
|
NTSTATUS
|
|
SpDetermineProduct(
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot,
|
|
OUT PNT_PRODUCT_TYPE ProductType,
|
|
OUT ULONG *MajorVersion,
|
|
OUT ULONG *MinorVersion,
|
|
OUT ULONG *BuildNumber, OPTIONAL
|
|
OUT ULONG *ProductSuiteMask,
|
|
OUT UPG_PROGRESS_TYPE *UpgradeProgressValue,
|
|
OUT PWSTR *UniqueIdFromReg, OPTIONAL
|
|
OUT PWSTR *Pid, OPTIONAL
|
|
OUT PBOOLEAN pIsEvalVariation OPTIONAL,
|
|
OUT PLCID LangId,
|
|
OUT ULONG *ServicePack OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SpSetUpgradeStatus(
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot,
|
|
IN UPG_PROGRESS_TYPE UpgradeProgressValue
|
|
);
|
|
|
|
|
|
//
|
|
// Utility functions.
|
|
//
|
|
BOOLEAN
|
|
SpGetTargetPath(
|
|
IN PVOID SifHandle,
|
|
IN PDISK_REGION Region,
|
|
IN PWSTR DefaultPath,
|
|
OUT PWSTR *TargetPath
|
|
);
|
|
|
|
VOID
|
|
SpDeleteExistingTargetDir(
|
|
IN PDISK_REGION Region,
|
|
IN PWSTR NtDir,
|
|
IN BOOLEAN GaugeNeeded,
|
|
IN DWORD MsgId
|
|
);
|
|
|
|
VOID
|
|
SpDone(
|
|
IN ULONG MsgId,
|
|
IN BOOLEAN Successful,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
VOID
|
|
SpFatalSifError(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR Section,
|
|
IN PWSTR Key, OPTIONAL
|
|
IN ULONG Line,
|
|
IN ULONG ValueNumber
|
|
);
|
|
|
|
VOID
|
|
SpNonFatalSifError(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR Section,
|
|
IN PWSTR Key, OPTIONAL
|
|
IN ULONG Line,
|
|
IN ULONG ValueNumber,
|
|
IN PWSTR FileName
|
|
);
|
|
|
|
VOID
|
|
SpFatalKbdError(
|
|
IN ULONG MessageId,
|
|
...
|
|
);
|
|
|
|
VOID
|
|
SpFatalError(
|
|
IN ULONG MessageId,
|
|
...
|
|
);
|
|
|
|
PWSTR
|
|
SpMakePlatformSpecificSectionName(
|
|
IN PWSTR SectionName
|
|
);
|
|
|
|
VOID
|
|
SpConfirmExit(
|
|
VOID
|
|
);
|
|
|
|
PWSTR
|
|
SpDupStringW(
|
|
IN PCWSTR String
|
|
);
|
|
|
|
PSTR
|
|
SpDupString(
|
|
IN PCSTR String
|
|
);
|
|
|
|
#define \
|
|
SpDupStringA SpDupString
|
|
|
|
PWSTR
|
|
SpToUnicode(
|
|
IN PUCHAR OemString
|
|
);
|
|
|
|
PUCHAR
|
|
SpToOem(
|
|
IN PWSTR UnicodeString
|
|
);
|
|
|
|
VOID
|
|
SpGetSourceMediaInfo(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR MediaShortName,
|
|
OUT PWSTR *Description, OPTIONAL
|
|
OUT PWSTR *Tagfile, OPTIONAL
|
|
OUT PWSTR *Directory OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
SpConcatenatePaths(
|
|
IN OUT LPWSTR Path1,
|
|
IN LPCWSTR Path2
|
|
);
|
|
|
|
VOID
|
|
SpFetchDiskSpaceRequirements(
|
|
IN PVOID SifHandle,
|
|
IN ULONG BytesPerCluster,
|
|
OUT PULONG FreeKBRequired, OPTIONAL
|
|
OUT PULONG FreeKBRequiredSysPart OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
SpFetchTempDiskSpaceRequirements(
|
|
IN PVOID SifHandle,
|
|
IN ULONG BytesPerCluster,
|
|
OUT PULONG LocalSourceKBRequired, OPTIONAL
|
|
OUT PULONG BootKBRequired OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
SpFetchUpgradeDiskSpaceReq(
|
|
IN PVOID SifHandle,
|
|
OUT PULONG FreeKBRequired, OPTIONAL
|
|
OUT PULONG FreeKBRequiredSysPart OPTIONAL
|
|
);
|
|
|
|
PWCHAR
|
|
SpRetreiveMessageText(
|
|
IN PVOID ImageBase, OPTIONAL
|
|
IN ULONG MessageId,
|
|
IN OUT PWCHAR MessageText, OPTIONAL
|
|
IN ULONG MessageTextBufferSize OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SpRtlFormatMessage(
|
|
IN PWSTR MessageFormat,
|
|
IN ULONG MaximumWidth OPTIONAL,
|
|
IN BOOLEAN IgnoreInserts,
|
|
IN BOOLEAN ArgumentsAreAnsi,
|
|
IN BOOLEAN ArgumentsAreAnArray,
|
|
IN va_list *Arguments,
|
|
OUT PWSTR Buffer,
|
|
IN ULONG Length,
|
|
OUT PULONG ReturnLength OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
SpInitializeDriverInf(
|
|
IN HANDLE MasterSifHandle,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice
|
|
);
|
|
|
|
VOID
|
|
SpOpenDriverCab(
|
|
IN HANDLE MasterSifHandle,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice,
|
|
OUT PWSTR *Directory OPTIONAL
|
|
);
|
|
|
|
//
|
|
// Disk region name translations
|
|
//
|
|
|
|
typedef enum _ENUMARCPATHTYPE {
|
|
PrimaryArcPath = 0,
|
|
SecondaryArcPath
|
|
} ENUMARCPATHTYPE;
|
|
|
|
VOID
|
|
SpNtNameFromRegion(
|
|
IN PDISK_REGION Region,
|
|
OUT PWSTR NtPath,
|
|
IN ULONG BufferSizeBytes,
|
|
IN PartitionOrdinalType OrdinalType
|
|
);
|
|
|
|
BOOLEAN
|
|
SpNtNameFromDosPath (
|
|
IN PCWSTR DosPath,
|
|
OUT PWSTR NtPath,
|
|
IN UINT NtPathSizeInBytes,
|
|
IN PartitionOrdinalType OrdinalType
|
|
);
|
|
|
|
VOID
|
|
SpArcNameFromRegion(
|
|
IN PDISK_REGION Region,
|
|
OUT PWSTR ArcPath,
|
|
IN ULONG BufferSizeBytes,
|
|
IN PartitionOrdinalType OrdinalType,
|
|
IN ENUMARCPATHTYPE ArcPathType
|
|
);
|
|
|
|
PDISK_REGION
|
|
SpRegionFromArcOrDosName(
|
|
IN PWSTR Name,
|
|
IN PartitionOrdinalType OrdinalType,
|
|
IN PDISK_REGION PreviousMatch
|
|
);
|
|
|
|
PDISK_REGION
|
|
SpRegionFromNtName(
|
|
IN PWSTR NtName,
|
|
IN PartitionOrdinalType OrdinalType
|
|
);
|
|
|
|
PDISK_REGION
|
|
SpRegionFromDosName(
|
|
IN PCWSTR DosName
|
|
);
|
|
|
|
PDISK_REGION
|
|
SpRegionFromArcName(
|
|
IN PWSTR ArcName,
|
|
IN PartitionOrdinalType OrdinalType,
|
|
IN PDISK_REGION PreviousMatch
|
|
);
|
|
|
|
//
|
|
// Help routine.
|
|
//
|
|
#define SPHELP_HELPTEXT 0x00000000
|
|
#define SPHELP_LICENSETEXT 0x00000001
|
|
|
|
VOID
|
|
SpHelp(
|
|
IN ULONG MessageId, OPTIONAL
|
|
IN PCWSTR FileText, OPTIONAL
|
|
IN ULONG Flags
|
|
);
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
BOOLEAN
|
|
SpPromptForDisk(
|
|
IN PWSTR DiskDescription,
|
|
IN OUT PWSTR DiskDevicePath,
|
|
IN PWSTR DiskTagFile,
|
|
IN BOOLEAN IgnoreDiskInDrive,
|
|
IN BOOLEAN AllowEscape,
|
|
IN BOOLEAN WarnMultiplePrompts,
|
|
OUT PBOOLEAN pRedrawFlag
|
|
);
|
|
|
|
BOOLEAN
|
|
SpPromptForSetupMedia(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR MediaShortname,
|
|
IN PWSTR DiskDevicePath
|
|
);
|
|
|
|
ULONG
|
|
SpFindStringInTable(
|
|
IN PWSTR *StringTable,
|
|
IN PWSTR StringToFind
|
|
);
|
|
|
|
PWSTR
|
|
SpGenerateCompressedName(
|
|
IN PWSTR Filename
|
|
);
|
|
|
|
BOOLEAN
|
|
SpNonCriticalError(
|
|
IN PVOID SifHandle,
|
|
IN ULONG MsgId,
|
|
IN PWSTR p1,
|
|
IN PWSTR p2
|
|
);
|
|
|
|
BOOLEAN
|
|
SpNonCriticalErrorWithContinue(
|
|
IN ULONG MsgId,
|
|
IN PWSTR p1,
|
|
IN PWSTR p2
|
|
);
|
|
|
|
VOID
|
|
SpNonCriticalErrorNoRetry(
|
|
IN ULONG MsgId,
|
|
IN PWSTR p1,
|
|
IN PWSTR p2
|
|
);
|
|
|
|
VOID
|
|
SpPrepareForPrinterUpgrade(
|
|
IN PVOID SifHandle,
|
|
IN PDISK_REGION NtRegion,
|
|
IN PWSTR Sysroot
|
|
);
|
|
|
|
NTSTATUS
|
|
SpOpenSetValueAndClose(
|
|
IN HANDLE hKeyRoot,
|
|
IN PWSTR SubKeyName, OPTIONAL
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID Value,
|
|
IN ULONG ValueSize
|
|
);
|
|
|
|
NTSTATUS
|
|
SpDeleteValueKey(
|
|
IN HANDLE hKeyRoot,
|
|
IN PWSTR KeyName,
|
|
IN PWSTR ValueName
|
|
);
|
|
|
|
NTSTATUS
|
|
SpGetValueKey(
|
|
IN HANDLE hKeyRoot,
|
|
IN PWSTR KeyName,
|
|
IN PWSTR ValueName,
|
|
IN ULONG BufferLength,
|
|
OUT PUCHAR Buffer,
|
|
OUT PULONG ResultLength
|
|
);
|
|
|
|
BOOLEAN
|
|
SpIsRegionBeyondCylinder1024(
|
|
IN PDISK_REGION Region
|
|
);
|
|
|
|
PWSTR
|
|
SpDetermineSystemPartitionDirectory(
|
|
IN PDISK_REGION SystemPartitionRegion,
|
|
IN PWSTR OriginalSystemPartitionDirectory OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
SpFindSizeOfFilesInOsWinnt(
|
|
IN PVOID MasterSifHandle,
|
|
IN PDISK_REGION SystemPartition,
|
|
IN PULONG TotalSize
|
|
);
|
|
|
|
VOID
|
|
SpRunAutochkOnNtAndSystemPartitions(
|
|
IN HANDLE MasterSifHandle,
|
|
IN PDISK_REGION WinntPartitionRegion,
|
|
IN PDISK_REGION SystemPartitionRegion,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice,
|
|
IN PWSTR TargetPath
|
|
);
|
|
|
|
NTSTATUS
|
|
SpRunAutoFormat(
|
|
IN HANDLE MasterSifHandle,
|
|
IN PWSTR RegionDescription,
|
|
IN PDISK_REGION PartitionRegion,
|
|
IN ULONG FilesystemType,
|
|
IN BOOLEAN QuickFormat,
|
|
IN DWORD ClusterSize,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice
|
|
);
|
|
|
|
|
|
#ifdef _X86_
|
|
BOOL
|
|
SpUseBIOSToBoot(
|
|
IN PDISK_REGION NtPartitionRegion,
|
|
IN PWSTR NtPartitionDevicePath,
|
|
IN PVOID SifHandle
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// Utilities used for partitioning/formatting
|
|
//
|
|
|
|
USHORT
|
|
ComputeSecPerCluster(
|
|
IN ULONG NumSectors,
|
|
IN BOOLEAN SmallFat
|
|
);
|
|
|
|
NTSTATUS
|
|
SpLockUnlockVolume(
|
|
IN HANDLE Handle,
|
|
IN BOOLEAN LockVolume
|
|
);
|
|
|
|
NTSTATUS
|
|
SpDismountVolume(
|
|
IN HANDLE Handle
|
|
);
|
|
|
|
//
|
|
// Miscellaneous other stuff
|
|
//
|
|
BOOLEAN
|
|
SpReadSKUStuff(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SpSetDirtyShutdownFlag(
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot
|
|
);
|
|
|
|
BOOLEAN
|
|
SpPatchBootMessages(
|
|
VOID
|
|
);
|
|
|
|
ULONG
|
|
SpGetHeaderTextId(
|
|
VOID
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
SpGetVersionFromStr(
|
|
IN PWSTR VersionStr,
|
|
OUT PDWORD Version, // major * 100 + minor
|
|
OUT PDWORD BuildNumber
|
|
);
|
|
|
|
NTSTATUS
|
|
SpQueryCanonicalName(
|
|
IN PWSTR Name,
|
|
IN ULONG MaxDepth,
|
|
OUT PWSTR CanonicalName,
|
|
IN ULONG SizeOfBufferInBytes
|
|
);
|
|
|
|
void
|
|
SpDisableCrashRecoveryForGuiMode(
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot
|
|
);
|
|
|
|
//
|
|
// mountmanger mount point iteration routine(s)
|
|
//
|
|
typedef BOOLEAN (* SPMOUNTMGR_ITERATION_CALLBACK)(
|
|
IN PVOID Context,
|
|
IN PMOUNTMGR_MOUNT_POINTS MountPoints,
|
|
IN PMOUNTMGR_MOUNT_POINT MountPoint);
|
|
|
|
|
|
NTSTATUS
|
|
SpIterateMountMgrMountPoints(
|
|
IN PVOID Context,
|
|
IN SPMOUNTMGR_ITERATION_CALLBACK Callback
|
|
);
|
|
|
|
|
|
//
|
|
// Registry iteration abstractions
|
|
//
|
|
typedef struct _SPREGISTERYKEY_ITERATION_CALLBACK_DATA {
|
|
KEY_INFORMATION_CLASS InformationType;
|
|
PVOID Information;
|
|
HANDLE ParentKeyHandle;
|
|
} SP_REGISTRYKEY_ITERATION_CALLBACK_DATA, *PSP_REGISTRYKEY_ITERATION_CALLBACK_DATA;
|
|
|
|
//
|
|
// registry iteration call back
|
|
//
|
|
typedef BOOLEAN (* SP_REGISTRYKEY_ITERATION_CALLBACK)(
|
|
IN PVOID Context,
|
|
IN PSP_REGISTRYKEY_ITERATION_CALLBACK_DATA Data,
|
|
OUT NTSTATUS *StatusCode
|
|
);
|
|
|
|
NTSTATUS
|
|
SpIterateRegistryKeyForKeys(
|
|
IN HANDLE RootKeyHandle,
|
|
IN PWSTR KeyToIterate,
|
|
IN SP_REGISTRYKEY_ITERATION_CALLBACK Callback,
|
|
IN PVOID Context
|
|
);
|
|
|
|
|
|
#define MAX_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
|
#define MAX_COPY_SIZE(a) (MAX_ARRAY_SIZE(a) - 1)
|
|
#define MAX_APPEND_SIZE_W(a) (MAX_COPY_SIZE(a) - wcslen(a))
|
|
#define MAX_APPEND_SIZE MAX_APPEND_SIZE_W
|
|
|
|
|
|
#ifdef PRERELEASE
|
|
extern INT g_TestHook;
|
|
# define TESTHOOK(n) if(g_TestHook==(n))SpBugCheck(SETUP_BUGCHECK_BOOTMSGS,0,0,0)
|
|
#else
|
|
# define TESTHOOK(n)
|
|
#endif
|
|
|
|
|
|
//
|
|
// On x86, we want to clear the previous OS entry in boot.ini if
|
|
// we reformat C:
|
|
//
|
|
#ifdef _X86_
|
|
extern UCHAR OldSystemLine[MAX_PATH];
|
|
extern BOOLEAN DiscardOldSystemLine;
|
|
#endif
|
|
|
|
#endif // ndef _SPSETUP_DEFN_
|