// // Need to include below 3 files for "IsNEC_98", even if DEBUGPERFTRACE does not defined. // #include #include #include #include #include #include #ifdef PRERELEASE #ifdef DBG #include #endif #endif #include #include #include #include #include #include #include #include #include #ifdef UNICODE #include #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