windows-nt/Source/XPSP1/NT/base/ntsetup/ocmanage/common/oc.h
2020-09-26 16:20:57 +08:00

850 lines
17 KiB
C

//
// Need to include below 3 files for "IsNEC_98", even if DEBUGPERFTRACE does not defined.
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <prsht.h>
#include <commctrl.h>
#ifdef PRERELEASE
#ifdef DBG
#include <objbase.h>
#endif
#endif
#include <setupapi.h>
#include <spapip.h>
#include <ocmanage.h>
#include <ocmgrlib.h>
#include <tchar.h>
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#include <winnls.h>
#ifdef UNICODE
#include <sfcapip.h>
#endif
#include "msg.h"
#include "res.h"
#if DBG
#define MYASSERT( exp ) \
if (!(exp)) \
RtlAssert( #exp, __FILE__, __LINE__, NULL )
#else
#define MYASSERT( exp )
#endif // DBG
//
// Names of wizard page types.
//
extern LPCTSTR WizardPagesTypeNames[WizPagesTypeMax];
//
// Window handle of wizard dialog. Set when the OC Manager client
// calls OcRememberWizardDialogHandle.
//
extern HWND WizardDialogHandle;
//
// Name of sections and keys in infs.
//
extern LPCTSTR szComponents;
extern LPCTSTR szOptionalComponents;
extern LPCTSTR szExtraSetupFiles;
extern LPCTSTR szNeeds;
extern LPCTSTR szParent;
extern LPCTSTR szIconIndex;
extern LPCTSTR szTip;
extern LPCTSTR szOptionDesc;
extern LPCTSTR szInstalledFlag;
//
// Key in registry where private component data is kept.
// We form a unique name within this key for the OC Manager
// instantiation.
//
extern LPCTSTR szPrivateDataRoot;
extern LPCTSTR szMasterInfs;
extern LPCTSTR szSubcompList;
//
// Other string constants.
//
extern LPCTSTR szSetupDir;
extern LPCTSTR szOcManagerErrors;
//
// DLL module handle.
//
extern HMODULE MyModuleHandle;
//
// for debugging
//
extern DWORD gDebugLevel;
//
// Define structure describing an optional component.
//
typedef struct _OPTIONAL_COMPONENT {
//
// String id of name of inf file in the OC Manager's
// InfListStringTable string table. If -1, then
// the subcomponent does not appear on the OC page.
//
LONG InfStringId;
//
// Backpointer to top level component
//
LONG TopLevelStringId;
//
// String id of parent component, -1 if none.
//
LONG ParentStringId;
//
// String id of first child, -1 if none.
//
LONG FirstChildStringId;
//
// Count of children.
//
UINT ChildrenCount;
//
// String id of next sibling, -1 if none.
//
LONG NextSiblingStringId;
//
// String ids of needs and needed by.
//
PLONG NeedsStringIds;
UINT NeedsCount;
PLONG NeededByStringIds;
UINT NeededByCount;
// String ids of exclude and excluded by
PLONG ExcludeStringIds;
UINT ExcludeCount;
PLONG ExcludedByStringIds;
UINT ExcludedByCount;
//
// Misc flags.
//
UINT InternalFlags;
//
// Approximation of required disk space.
//
LONGLONG SizeApproximation;
//
// Icon index of the component.
// -1 means we're supposed to get it from the component itself.
// -2 means we're supposed to use IconDll and IconResource
//
UINT IconIndex;
TCHAR IconDll[MAX_PATH];
TCHAR IconResource[50];
//
// Selection state (SELSTATE_xxx constants).
//
UINT SelectionState;
UINT OriginalSelectionState;
// Installation Flag as obtained from the inf
UINT InstalledState;
//
// Mode bits.
//
UINT ModeBits;
//
// Human-readable stuff describing the component.
//
TCHAR Description[MAXOCDESC];
TCHAR Tip[MAXOCTIP];
//
// From here down, stuff is meaningful only for top-level components.
//
//
// Stuff describing the OC's installation DLL and how to call it.
//
TCHAR InstallationDllName[MAX_PATH];
CHAR InterfaceFunctionName[MAX_PATH];
HMODULE InstallationDll;
POCSETUPPROC InstallationRoutine;
//
// Version of the OC Manager to which this component was written.
//
UINT ExpectedVersion;
// this flag indicates whether the subcomponent was intialialized
BOOL Exists;
// points to the helper context for this component
struct _HELPER_CONTEXT *HelperContext;
//
// Flags: ANSI/Unicode, etc.
//
UINT Flags;
} OPTIONAL_COMPONENT, *POPTIONAL_COMPONENT;
//
// locale info
//
typedef struct _LOCALE {
LCID lcid;
TCHAR DecimalSeparator[4];
} LOCALE, *PLOCALE;
extern LOCALE locale;
//
// Indices for installation states.
//
#define INSTSTATE_NO 0
#define INSTSTATE_UNKNOWN 1
#define INSTSTATE_YES 2
//
// Flags for InternalFlags member of OPTIONAL_COMPONENT structure.
//
#define OCFLAG_PROCESSED 0x00000001
#define OCFLAG_ANYORIGINALLYON 0x00000002
#define OCFLAG_ANYORIGINALLYOFF 0x00000004
#define OCFLAG_HIDE 0x00000008
#define OCFLAG_STATECHANGE 0x00000010
#define OCFLAG_TOPLEVELITEM 0x00000020
#define OCFLAG_NEWITEM 0x00000040
#define OCFLAG_NOWIZARDPAGES 0x00000080
#define OCFLAG_APPROXSPACE 0x00000100
#define OCFLAG_NOQUERYSKIPPAGES 0x00000200
#define OCFLAG_NOEXTRAROUTINES 0x00000400
// indicates an exception when calling a component
#define ERROR_CALL_COMPONENT -666
//
// values to sync copies with the OS
//
#define OC_ALLOWRENAME TEXT("AllowProtectedRenames")
//
// Define structure describing a per-component inf.
//
typedef struct _OC_INF {
//
// Handle to open inf file.
//
HINF Handle;
} OC_INF, *POC_INF;
//
// Define structure corresponding to an instance of the OC Manager.
// This is actually somewhat broken, in that this actually closely corresponds
// to a master OC INF, and we might want to consider breaking out the string
// tables into another structure, so we can more easily achieve a unified
// namespace if we have multiple master OC INFs at play simultaneously.
//
typedef struct _OC_MANAGER {
//
// Callbacks into OC Manaer client.
//
OCM_CLIENT_CALLBACKS Callbacks;
//
// Handle of Master OC INF.
//
HINF MasterOcInf;
//
// unattended inf handle
//
HINF UnattendedInf;
//
// Master OC Inf file, and unattended file
//
TCHAR MasterOcInfPath[MAX_PATH];
TCHAR UnattendedInfPath[MAX_PATH];
// we run from whatever directory the master inf is in
TCHAR SourceDir[MAX_PATH];
//
// Name of "suite" -- in other words, a shortname that
// is unique to the master OC inf that this structure represents.
// We base it on the name of the master OC inf itself.
//
TCHAR SuiteName[MAX_PATH];
//
// page titles
//
TCHAR SetupPageTitle[MAX_PATH];
// window title
TCHAR WindowTitle[MAX_PATH];
//
// List of per-component OC INFs currently loaded.
// Each inf's name is in the string table and the extra data
// for each is an OC_INF structure.
//
PVOID InfListStringTable;
//
// String table for names of all components and subcomponents.
// Extra data for each is an OPTIONAL_COMPONENT structure.
//
PVOID ComponentStringTable;
//
// pointer to OcSetupPage structure so we can free this data
// if the user cancels before we get to the wizard page.
//
PVOID OcSetupPage;
//
// Setup mode (custom, typical, etc)
//
UINT SetupMode;
//
// List of top-level optional component string IDs.
// This is necessary because we need to preserve ordering
// from the master OC Inf.
//
UINT TopLevelOcCount;
PLONG TopLevelOcStringIds;
UINT TopLevelParentOcCount;
PLONG TopLevelParentOcStringIds;
//
// Are there subcomponents on the details page?
//
BOOL SubComponentsPresent;
//
// Each element in this array points to an array that
// gives ordering for querying wizard pages from the optional components.
//
PLONG WizardPagesOrder[WizPagesTypeMax];
//
// Subkey relative to szPrivateDataRoot where private
// data for components plugged into the OC will live.
// 2 8-char DWORD representations plus a separator and nul.
//
TCHAR PrivateDataSubkey[18];
HKEY hKeyPrivateData;
HKEY hKeyPrivateDataRoot;
//
// If we are completing installation, this item is the window handle
// of the progress text control.
//
HWND ProgressTextWindow;
//
// String id of component currently processing an interface routine.
// -1 means the OC manager is not currently processing one.
//
LONG CurrentComponentStringId;
// Component Ids of aborted components
PLONG AbortedComponentIds;
UINT AbortedCount;
//
// Various flags
//
UINT InternalFlags;
//
// setup data
//
SETUP_DATA SetupData;
} OC_MANAGER, *POC_MANAGER;
//
// Flags for InternalFlags member of OC_MANAGER structure
//
#define OCMFLAG_ANYORIGINALLYON 0x00000001
#define OCMFLAG_ANYORIGINALLYOFF 0x00000002
#define OCMFLAG_ANYDELAYEDMOVES 0x00000004
#define OCMFLAG_NEWINF 0x00000008
#define OCMFLAG_USERCANCELED 0x00000010
#define OCMFLAG_FILEABORT 0x00000020
#define OCMFLAG_NOPREOCPAGES 0x00000040
#define OCMFLAG_KILLSUBCOMPS 0x00000080
#define OCMFLAG_ANYINSTALLED 0x00000100
#define OCMFLAG_ANYUNINSTALLED 0x00000200
#define OCMFLAG_RUNQUIET 0x00000400
#define OCMFLAG_LANGUAGEAWARE 0x00000800
//
// Define structure we use to get back to a particular component
// when a component calls a helper routine asynchronously (for routines
// such as get and set private data).
//
// As each component is initialized it gets one of these structures.
//
typedef struct _HELPER_CONTEXT {
POC_MANAGER OcManager;
LONG ComponentStringId;
} HELPER_CONTEXT, *PHELPER_CONTEXT;
//
// Macros for callbacks. Assumes there is a local variable called OcManager
// that is of type POC_MANAGER.
//
#define OcFillInSetupDataA(p) OcManager->Callbacks.FillInSetupDataA(p)
#ifdef UNICODE
#define OcFillInSetupDataW(p) OcManager->Callbacks.FillInSetupDataW(p)
#endif
#define OcLogError OcManager->Callbacks.LogError
//
// Global table of helper routines.
//
extern OCMANAGER_ROUTINESA HelperRoutinesA;
#ifdef UNICODE
extern OCMANAGER_ROUTINESW HelperRoutinesW;
#endif
extern EXTRA_ROUTINESA ExtraRoutinesA;
#ifdef UNICODE
extern EXTRA_ROUTINESW ExtraRoutinesW;
#endif
// ocm phase ids for reporting errors with
typedef enum {
pidCallComponent = 0,
pidLoadComponent,
pidPreInit,
pidInitComponent,
pidRequestPages,
pidCalcDiskSpace,
pidQueueFileOps,
pidQueryStepCount,
pidCompleteInstallation,
pidExtraRoutines
} pid;
//
// Misc routines.
//
VOID
pOcGetApproximateDiskSpace(
IN POC_MANAGER OcManager
);
LONG
pOcGetTopLevelComponent(
IN POC_MANAGER OcManager,
IN LONG StringId
);
VOID
pOcTickSetupGauge(
IN OUT POC_MANAGER OcManager
);
UINT
_LogError(
IN POC_MANAGER OcManager,
IN OcErrorLevel ErrorLevel,
IN UINT MessageId,
...
);
UINT
pOcCreateComponentSpecificMiniIcon(
IN POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN UINT Width,
IN UINT Height,
IN LPCTSTR DllName, OPTIONAL
IN LPCTSTR ResourceId OPTIONAL
);
VOID
pOcUpdateParentSelectionStates(
IN POC_MANAGER OcManager,
IN HWND ListBox, OPTIONAL
IN LONG SubcomponentStringId
);
VOID
pOcFormSuitePath(
IN LPCTSTR SuiteName,
IN LPCTSTR FileName, OPTIONAL
OUT LPTSTR FullPath
);
BOOL
OcHelperConfirmCancel(
IN HWND ParentWindow
);
BOOL
pOcDoesAnyoneWantToSkipPage(
IN OUT POC_MANAGER OcManager,
IN OcManagerPage WhichPage
);
VOID
pOcExternalProgressIndicator(
IN PHELPER_CONTEXT OcManagerContext,
IN BOOL ExternalIndicator
);
BOOL
pConvertStringToLongLong(
IN PCTSTR String,
OUT PLONGLONG Value
);
VOID
pOcFreeOcSetupPage(
IN PVOID SetupPageData
);
HRESULT
FTestForOutstandingCoInits(
VOID
);
//
// wrapper for calling components
//
DWORD
CallComponent(
IN POC_MANAGER OcManager,
IN POPTIONAL_COMPONENT Oc,
IN LPCVOID ComponentId,
IN LPCVOID SubcomponentId,
IN UINT Function,
IN UINT_PTR Param1,
IN OUT PVOID Param2
);
//
// Interfacing routines.
//
UINT
OcInterfacePreinitialize(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId
);
UINT
OcInterfaceInitComponent(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId
);
UINT
OcInterfaceExtraRoutines(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId
);
SubComponentState
OcInterfaceQueryState(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN UINT WhichState
);
BOOL
OcInterfaceSetLanguage(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN WORD LanguageId
);
HBITMAP
OcInterfaceQueryImage(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN SubComponentInfo WhichImage,
IN UINT DesiredWidth,
IN UINT DesiredHeight
);
HBITMAP
OcInterfaceQueryImageEx(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN SubComponentInfo WhichImage,
IN UINT DesiredWidth,
IN UINT DesiredHeight
);
VOID
OcInterfaceWizardCreated(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN HWND DialogHandle
);
UINT
OcInterfaceRequestPages(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN WizardPagesType WhichPages,
OUT PSETUP_REQUEST_PAGES *RequestPages
);
BOOL
OcInterfaceQuerySkipPage(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN OcManagerPage WhichPage
);
BOOL
OcInterfaceNeedMedia(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN PSOURCE_MEDIA SourceMedia,
OUT LPTSTR NewPath
);
BOOL
OcInterfaceFileBusy(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN PFILEPATHS FIlePaths,
OUT LPTSTR NewPath
);
BOOL
OcInterfaceQueryChangeSelState(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN BOOL Selected,
IN UINT Flags
);
UINT
OcInterfaceCalcDiskSpace(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN HDSKSPC DiskSpaceList,
IN BOOL AddingToList
);
UINT
OcInterfaceQueueFileOps(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN HSPFILEQ FileQueue
);
UINT
OcInterfaceQueryStepCount(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
OUT PUINT StepCount
);
UINT
OcInterfaceCompleteInstallation(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId,
IN LPCTSTR Subcomponent,
IN BOOL PreQueueCommit
);
VOID
OcInterfaceCleanup(
IN OUT POC_MANAGER OcManager,
IN LONG ComponentId
);
DWORD
StandAloneSetupAppInterfaceRoutine(
IN LPCVOID ComponentId,
IN LPCVOID SubcomponentId,
IN UINT Function,
IN UINT_PTR Param1,
IN OUT PVOID Param2
);
//
// Persistent state fetch/store
//
BOOL
pOcFetchInstallStates(
IN POC_MANAGER OcManager
);
BOOL
pOcRememberInstallStates(
IN POC_MANAGER OcManager
);
BOOL
pOcSetOneInstallState(
IN POC_MANAGER OcManager,
IN LONG StringId
);
BOOL
pOcRemoveComponent(
IN POC_MANAGER OcManager,
IN LONG ComponentId,
IN DWORD PhaseId
);
BOOL
pOcComponentWasRemoved(
IN POC_MANAGER OcManager,
IN LONG ComponentId
);
BOOL
pOcHelperReportExternalError(
IN POC_MANAGER OcManager,
IN LONG ComponentId,
IN LONG SubcomponentId, OPTIONAL
IN DWORD_PTR MessageId,
IN DWORD Flags,
...
);
//
// Use this flag to call OcHelperReportExternalError and use
// a Message ID defined in the OCManage.dll
//
#define ERRFLG_OCM_MESSAGE 0x80000000
BOOL
OcHelperClearExternalError (
IN POC_MANAGER OcManager,
IN LONG ComponentId,
IN LONG SubcomponentId OPTIONAL
);
//
// Debuging stuff
//
#if DBG
#define _OC_DBG
#endif
//
// should not be defined for retail release!!!
//
#if PRERELEASE
#define _OC_DBG
#endif
VOID
_ErrOut(
IN LPCTSTR Format,
...
);
VOID
_WrnOut(
IN LPCTSTR Format,
...
);
VOID
_TrcOut(
IN LPCTSTR Format,
...
);
#define ERR(x) _ErrOut x
//
// these guys are switched out in a free build.
//
#ifdef _OC_DBG
#define TRACE(x) _TrcOut x
#define WRN(x) _WrnOut x
#define DBGOUT(x) \
if (gDebugLevel >= 100) _TrcOut x
#else
#define TRACE(x)
#define WRN(x)
#define DBGOUT(x)
#endif
// Normally a call to tmbox is for debug tracing and all such calls
// should be removed before checking in. However, if called through
// the mbox() macro, this indicates the call is meant to ship.
DWORD
tmbox(
LPCTSTR fmt,
...
);
#define mbox tmbox