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.
1623 lines
43 KiB
1623 lines
43 KiB
/*
|
|
* Copyright (c) 1996 Microsoft Corporation
|
|
*
|
|
* Module Name:
|
|
*
|
|
* ocgen.cpp
|
|
*
|
|
* Abstract:
|
|
*
|
|
* This file handles all messages passed by the OC Manager
|
|
*
|
|
* Author:
|
|
*
|
|
* Pat Styles (patst) Jan-20-1998
|
|
*
|
|
* Environment:
|
|
*
|
|
* User Mode
|
|
*/
|
|
|
|
#define _OCGEN_CPP_
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <tchar.h>
|
|
#include <objbase.h>
|
|
#include <shlwapi.h>
|
|
#include <lm.h>
|
|
#include "ocgen.h"
|
|
#include <strsafe.h>
|
|
#pragma hdrstop
|
|
|
|
// also referred to in ocgen.h // forward reference
|
|
|
|
DWORD OnPreinitialize();
|
|
DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc);
|
|
DWORD OnSetLanguage();
|
|
DWORD_PTR OnQueryImage();
|
|
DWORD OnSetupRequestPages(UINT type, PVOID srp);
|
|
DWORD OnQuerySelStateChange(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state, UINT flags);
|
|
DWORD OnCalcDiskSpace(LPCTSTR ComponentId, LPCTSTR SubcomponentId, DWORD addComponent, HDSKSPC dspace);
|
|
DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue);
|
|
DWORD OnNotificationFromQueue();
|
|
DWORD OnQueryStepCount();
|
|
DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
|
|
DWORD OnCleanup();
|
|
DWORD OnQueryState(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state);
|
|
DWORD OnNeedMedia();
|
|
DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
|
|
DWORD OnQuerySkipPage();
|
|
DWORD OnWizardCreated();
|
|
DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per);
|
|
|
|
PPER_COMPONENT_DATA AddNewComponent(LPCTSTR ComponentId);
|
|
PPER_COMPONENT_DATA LocateComponent(LPCTSTR ComponentId);
|
|
VOID RemoveComponent(LPCTSTR ComponentId);
|
|
BOOL StateInfo(PPER_COMPONENT_DATA cd, LPCTSTR SubcomponentId, BOOL *state);
|
|
DWORD RegisterServers(HINF hinf, LPCTSTR component, DWORD state);
|
|
DWORD EnumSections(HINF hinf, const TCHAR *component, const TCHAR *key, DWORD index, INFCONTEXT *pic, TCHAR *name);
|
|
DWORD RegisterServices(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
|
|
DWORD CleanupNetShares(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
|
|
DWORD RunExternalProgram(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
|
|
|
|
// for determining prior install status of WMI components
|
|
bool IsMSIProviderPresent();
|
|
|
|
|
|
// for registering dlls
|
|
|
|
typedef HRESULT (__stdcall *pfn)(void);
|
|
|
|
#define KEYWORD_REGSVR TEXT("RegSvr")
|
|
#define KEYWORD_UNREGSVR TEXT("UnregSvr")
|
|
#define KEYWORD_UNINSTALL TEXT("Uninstall")
|
|
#define KEYWORD_SOURCEPATH TEXT("SourcePath")
|
|
#define KEYWORD_DELSHARE TEXT("DelShare")
|
|
#define KEYWORD_ADDSERVICE TEXT("AddService")
|
|
#define KEYWORD_DELSERVICE TEXT("DelService")
|
|
#define KEYWORD_SHARENAME TEXT("Share")
|
|
#define KEYWORD_RUN TEXT("Run")
|
|
#define KEYVAL_SYSTEMSRC TEXT("SystemSrc")
|
|
#define KEYWORD_COMMANDLINE TEXT("CommandLine")
|
|
#define KEYWORD_TICKCOUNT TEXT("TickCount")
|
|
|
|
// Services keywords/options
|
|
#define KEYWORD_SERVICENAME TEXT("ServiceName")
|
|
#define KEYWORD_DISPLAYNAME TEXT("DisplayName")
|
|
#define KEYWORD_SERVICETYPE TEXT("ServiceType")
|
|
#define KEYWORD_STARTTYPE TEXT("StartType")
|
|
#define KEYWORD_ERRORCONTROL TEXT("ErrorControl")
|
|
#define KEYWORD_IMAGEPATH TEXT("BinaryPathName")
|
|
#define KEYWORD_LOADORDER TEXT("LoadOrderGroup")
|
|
#define KEYWORD_DEPENDENCIES TEXT("Dependencies")
|
|
#define KEYWORD_STARTNAME TEXT("ServiceStartName")
|
|
#define KEYWORD_PASSWORD TEXT("Password")
|
|
|
|
#define KEYVAL_ON TEXT("on")
|
|
#define KEYVAL_OFF TEXT("off")
|
|
#define KEYVAL_DEFAULT TEXT("default")
|
|
|
|
const char gszRegisterSvrRoutine[] = "DllRegisterServer";
|
|
const char gszUnregisterSvrRoutine[] = "DllUnregisterServer";
|
|
BOOL g_fRebootNeed = FALSE;
|
|
|
|
PPER_COMPONENT_DATA _cd;
|
|
|
|
void av()
|
|
{
|
|
_cd = NULL;
|
|
_cd->hinf = NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* called by CRT when _DllMainCRTStartup is the DLL entry point
|
|
*/
|
|
|
|
/*
|
|
Not needed now as Wbemupgd.dll already has a DllMain.
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DllMain(
|
|
IN HINSTANCE hinstance,
|
|
IN DWORD reason,
|
|
IN LPVOID reserved
|
|
)
|
|
{
|
|
BOOL b;
|
|
|
|
UNREFERENCED_PARAMETER(reserved);
|
|
|
|
b = true;
|
|
|
|
switch(reason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
ghinst = hinstance;
|
|
loginit();
|
|
|
|
// Fall through to process first thread
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
b = true;
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
break;
|
|
}
|
|
|
|
return(b);
|
|
}
|
|
*/
|
|
|
|
DWORD_PTR
|
|
OcEntry(
|
|
IN LPCTSTR ComponentId,
|
|
IN LPCTSTR SubcomponentId,
|
|
IN UINT Function,
|
|
IN UINT Param1,
|
|
IN OUT PVOID Param2
|
|
)
|
|
{
|
|
DWORD_PTR rc;
|
|
|
|
DebugTraceOCNotification(Function, ComponentId);
|
|
logOCNotification(Function, ComponentId);
|
|
|
|
switch(Function)
|
|
{
|
|
case OC_PREINITIALIZE:
|
|
rc = OnPreinitialize();
|
|
break;
|
|
|
|
case OC_INIT_COMPONENT:
|
|
rc = OnInitComponent(ComponentId, (PSETUP_INIT_COMPONENT)Param2);
|
|
break;
|
|
|
|
case OC_EXTRA_ROUTINES:
|
|
rc = OnExtraRoutines(ComponentId, (PEXTRA_ROUTINES)Param2);
|
|
break;
|
|
|
|
case OC_SET_LANGUAGE:
|
|
rc = OnSetLanguage();
|
|
break;
|
|
|
|
case OC_QUERY_IMAGE:
|
|
rc = OnQueryImage();
|
|
break;
|
|
|
|
case OC_REQUEST_PAGES:
|
|
rc = OnSetupRequestPages(Param1, Param2);
|
|
break;
|
|
|
|
case OC_QUERY_CHANGE_SEL_STATE:
|
|
rc = OnQuerySelStateChange(ComponentId, SubcomponentId, Param1, (UINT)((UINT_PTR)Param2));
|
|
break;
|
|
|
|
case OC_CALC_DISK_SPACE:
|
|
rc = OnCalcDiskSpace(ComponentId, SubcomponentId, Param1, Param2);
|
|
break;
|
|
|
|
case OC_QUEUE_FILE_OPS:
|
|
rc = OnQueueFileOps(ComponentId, SubcomponentId, (HSPFILEQ)Param2);
|
|
break;
|
|
|
|
case OC_NOTIFICATION_FROM_QUEUE:
|
|
rc = OnNotificationFromQueue();
|
|
break;
|
|
|
|
case OC_QUERY_STEP_COUNT:
|
|
rc = OnQueryStepCount();
|
|
break;
|
|
|
|
case OC_COMPLETE_INSTALLATION:
|
|
rc = OnCompleteInstallation(ComponentId, SubcomponentId);
|
|
break;
|
|
|
|
case OC_CLEANUP:
|
|
rc = OnCleanup();
|
|
break;
|
|
|
|
case OC_QUERY_STATE:
|
|
rc = OnQueryState(ComponentId, SubcomponentId, Param1);
|
|
break;
|
|
|
|
case OC_NEED_MEDIA:
|
|
rc = OnNeedMedia();
|
|
break;
|
|
|
|
case OC_ABOUT_TO_COMMIT_QUEUE:
|
|
rc = OnAboutToCommitQueue(ComponentId,SubcomponentId);
|
|
break;
|
|
|
|
case OC_QUERY_SKIP_PAGE:
|
|
rc = OnQuerySkipPage();
|
|
break;
|
|
|
|
case OC_WIZARD_CREATED:
|
|
rc = OnWizardCreated();
|
|
break;
|
|
|
|
default:
|
|
rc = NO_ERROR;
|
|
break;
|
|
}
|
|
|
|
DebugTrace(1, TEXT("processing completed"));
|
|
logOCNotificationCompletion();
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*-------------------------------------------------------*/
|
|
/*
|
|
* OC Manager message handlers
|
|
*
|
|
*-------------------------------------------------------*/
|
|
|
|
|
|
/* OnPreinitialize()
|
|
*
|
|
* handler for OC_PREINITIALIZE
|
|
*/
|
|
|
|
DWORD
|
|
OnPreinitialize(
|
|
VOID
|
|
)
|
|
{
|
|
#ifdef ANSI
|
|
return OCFLAG_ANSI;
|
|
#else
|
|
return OCFLAG_UNICODE;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* OnInitComponent()
|
|
*
|
|
* handler for OC_INIT_COMPONENT
|
|
*/
|
|
|
|
DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc)
|
|
{
|
|
PPER_COMPONENT_DATA cd;
|
|
INFCONTEXT context;
|
|
TCHAR buf[256];
|
|
HINF hinf;
|
|
BOOL rc;
|
|
|
|
// assert(0);
|
|
// av();
|
|
|
|
// add component to linked list
|
|
|
|
if (!(cd = AddNewComponent(ComponentId)))
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
// store component inf handle
|
|
|
|
cd->hinf = (psc->ComponentInfHandle == INVALID_HANDLE_VALUE)
|
|
? NULL
|
|
: psc->ComponentInfHandle;
|
|
|
|
// open the inf
|
|
|
|
if (cd->hinf)
|
|
SetupOpenAppendInfFile(NULL, cd->hinf,NULL);
|
|
|
|
// copy helper routines and flags
|
|
|
|
cd->HelperRoutines = psc->HelperRoutines;
|
|
|
|
cd->Flags = psc->SetupData.OperationFlags;
|
|
|
|
cd->SourcePath = NULL;
|
|
|
|
#if 0
|
|
// Setup the SourcePath. Read inf and see if we should use the NT setup source.
|
|
// If so, set to null and setupapi will take care of this for us. If there is
|
|
// something specified in the inf, use it, otherwise use what is passed to us.
|
|
|
|
*buf = 0;
|
|
rc = SetupFindFirstLine(cd->hinf,
|
|
ComponentId,
|
|
KEYWORD_SOURCEPATH,
|
|
&context);
|
|
|
|
if (rc) {
|
|
|
|
rc = SetupGetStringField(&context,
|
|
1,
|
|
buf,
|
|
sizeof(buf) / sizeof(TCHAR),
|
|
NULL);
|
|
|
|
}
|
|
|
|
if (!_tcsicmp(buf, KEYVAL_SYSTEMSRC)) {
|
|
|
|
cd->SourcePath = NULL;
|
|
|
|
} else {
|
|
|
|
cd->SourcePath = (TCHAR *)LocalAlloc(LMEM_FIXED, SBUF_SIZE);
|
|
if (!cd->SourcePath)
|
|
return ERROR_CANCELLED;
|
|
|
|
if (!*buf)
|
|
_tcscpy(cd->SourcePath, psc->SetupData.SourcePath);
|
|
else
|
|
ExpandEnvironmentStrings(buf, cd->SourcePath, S_SIZE);
|
|
}
|
|
|
|
#endif
|
|
|
|
// play
|
|
|
|
srand(GetTickCount());
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* OnExtraRoutines()
|
|
*
|
|
* handler for OC_EXTRA_ROUTINES
|
|
*/
|
|
|
|
DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per)
|
|
{
|
|
PPER_COMPONENT_DATA cd;
|
|
|
|
if (!(cd = LocateComponent(ComponentId)))
|
|
return NO_ERROR;
|
|
|
|
memcpy(&cd->ExtraRoutines, per, per->size);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* OnSetLanguage()
|
|
*
|
|
* handler for OC_SET_LANGUAGE
|
|
*/
|
|
|
|
DWORD OnSetLanguage()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* OnSetLanguage()
|
|
*
|
|
* handler for OC_SET_LANGUAGE
|
|
*/
|
|
|
|
DWORD_PTR OnQueryImage()
|
|
{
|
|
return (DWORD_PTR)LoadBitmap(NULL,MAKEINTRESOURCE(32754)); // OBM_CLOSE
|
|
}
|
|
|
|
/*
|
|
* OnSetupRequestPages
|
|
*
|
|
* Prepares wizard pages and returns them to the OC Manager
|
|
*/
|
|
|
|
DWORD OnSetupRequestPages(UINT type, PVOID srp)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* OnWizardCreated()
|
|
*/
|
|
|
|
DWORD OnWizardCreated()
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* OnQuerySkipPage()
|
|
*
|
|
* don't let the user deselect the sam component
|
|
*/
|
|
|
|
DWORD OnQuerySkipPage()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* OnQuerySelStateChange()
|
|
*
|
|
* don't let the user deselect the sam component
|
|
*/
|
|
|
|
DWORD OnQuerySelStateChange(LPCTSTR ComponentId,
|
|
LPCTSTR SubcomponentId,
|
|
UINT state,
|
|
UINT flags)
|
|
{
|
|
DWORD rc = true;
|
|
|
|
#if 0
|
|
// if (!(flags & OCQ_ACTUAL_SELECTION)) {
|
|
if (!_tcsicmp(SubcomponentId, TEXT("three"))) {
|
|
if (!state) {
|
|
return false;
|
|
}
|
|
}
|
|
if (!_tcsicmp(ComponentId, TEXT("three"))) {
|
|
if (!state) {
|
|
return false;
|
|
}
|
|
}
|
|
if (!_tcsicmp(SubcomponentId, TEXT("gs7"))) {
|
|
if (state) {
|
|
return false;
|
|
}
|
|
}
|
|
if (!_tcsicmp(ComponentId, TEXT("gs7"))) {
|
|
if (state) {
|
|
return false;
|
|
}
|
|
}
|
|
// }
|
|
#endif
|
|
|
|
if (!rc && (flags & OCQ_ACTUAL_SELECTION))
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* OnCalcDiskSpace()
|
|
*
|
|
* handler for OC_ON_CALC_DISK_SPACE
|
|
*/
|
|
|
|
DWORD OnCalcDiskSpace(LPCTSTR ComponentId,
|
|
LPCTSTR SubcomponentId,
|
|
DWORD addComponent,
|
|
HDSKSPC dspace)
|
|
{
|
|
DWORD rc = NO_ERROR;
|
|
TCHAR section[S_SIZE];
|
|
PPER_COMPONENT_DATA cd;
|
|
|
|
//
|
|
// Param1 = 0 if for removing component or non-0 if for adding component
|
|
// Param2 = HDSKSPC to operate on
|
|
//
|
|
// Return value is Win32 error code indicating outcome.
|
|
//
|
|
// In our case the private section for this component/subcomponent pair
|
|
// is a simple standard inf install section, so we can use the high-level
|
|
// disk space list api to do what we want.
|
|
//
|
|
|
|
if (!(cd = LocateComponent(ComponentId)))
|
|
return NO_ERROR;
|
|
|
|
StringCchCopy(section, S_SIZE, SubcomponentId);
|
|
|
|
if (addComponent)
|
|
{
|
|
rc = SetupAddInstallSectionToDiskSpaceList(dspace,
|
|
cd->hinf,
|
|
NULL,
|
|
section,
|
|
0,
|
|
0);
|
|
}
|
|
else
|
|
{
|
|
rc = SetupRemoveInstallSectionFromDiskSpaceList(dspace,
|
|
cd->hinf,
|
|
NULL,
|
|
section,
|
|
0,
|
|
0);
|
|
}
|
|
|
|
if (!rc)
|
|
rc = GetLastError();
|
|
else
|
|
rc = NO_ERROR;
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* OnQueueFileOps()
|
|
*
|
|
* handler for OC_QUEUE_FILE_OPS
|
|
*/
|
|
|
|
DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue)
|
|
{
|
|
PPER_COMPONENT_DATA cd;
|
|
BOOL state;
|
|
BOOL rc;
|
|
INFCONTEXT context;
|
|
TCHAR section[256];
|
|
TCHAR srcpathbuf[256];
|
|
TCHAR *srcpath;
|
|
|
|
if (!(cd = LocateComponent(ComponentId)))
|
|
return NO_ERROR;
|
|
|
|
if (!SubcomponentId || !*SubcomponentId)
|
|
return NO_ERROR;
|
|
|
|
cd->queue = queue;
|
|
|
|
if (!StateInfo(cd, SubcomponentId, &state))
|
|
return NO_ERROR;
|
|
|
|
StringCchPrintf(section, 256, SubcomponentId);
|
|
|
|
rc = TRUE;
|
|
if (!state) {
|
|
// being uninstalled. Fetch uninstall section name.
|
|
rc = SetupFindFirstLine(cd->hinf,
|
|
SubcomponentId,
|
|
KEYWORD_UNINSTALL,
|
|
&context);
|
|
|
|
if (rc) {
|
|
rc = SetupGetStringField(&context,
|
|
1,
|
|
section,
|
|
sizeof(section) / sizeof(TCHAR),
|
|
NULL);
|
|
}
|
|
|
|
// also, unregister the dlls and kill services before deletion
|
|
|
|
SetupInstallServicesFromInfSection(cd->hinf, section, 0);
|
|
SetupInstallFromInfSection(NULL,cd->hinf,section,SPINST_UNREGSVR,NULL,NULL,0,NULL,NULL,NULL,NULL);
|
|
}
|
|
|
|
if (rc) {
|
|
// if uninstalling, don't use version checks
|
|
rc = SetupInstallFilesFromInfSection(cd->hinf,
|
|
NULL,
|
|
queue,
|
|
section,
|
|
cd->SourcePath,
|
|
state ? SP_COPY_NEWER : 0);
|
|
}
|
|
|
|
if (!rc)
|
|
return GetLastError();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* OnNotificationFromQueue()
|
|
*
|
|
* handler for OC_NOTIFICATION_FROM_QUEUE
|
|
*
|
|
* NOTE: although this notification is defined,
|
|
* it is currently unimplemented in oc manager
|
|
*/
|
|
|
|
DWORD OnNotificationFromQueue()
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* OnQueryStepCount
|
|
*
|
|
* handler forOC_QUERY_STEP_COUNT
|
|
*/
|
|
|
|
DWORD OnQueryStepCount()
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
/*
|
|
* OnCompleteInstallation
|
|
*
|
|
* handler for OC_COMPLETE_INSTALLATION
|
|
*/
|
|
|
|
DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
|
|
{
|
|
PPER_COMPONENT_DATA cd;
|
|
INFCONTEXT context;
|
|
TCHAR section[256];
|
|
BOOL state;
|
|
BOOL rc;
|
|
DWORD Error = NO_ERROR;
|
|
|
|
// Do post-installation processing in the cleanup section.
|
|
// This way we know all compoents queued for installation
|
|
// have beein installed before we do our stuff.
|
|
|
|
if (!(cd = LocateComponent(ComponentId)))
|
|
return NO_ERROR;
|
|
|
|
if (!SubcomponentId || !*SubcomponentId)
|
|
return NO_ERROR;
|
|
|
|
if (!StateInfo(cd, SubcomponentId, &state))
|
|
return NO_ERROR;
|
|
|
|
StringCchPrintf(section, 256, SubcomponentId);
|
|
|
|
rc = TRUE;
|
|
if (!state) {
|
|
// being uninstalled. Fetch uninstall section name.
|
|
rc = SetupFindFirstLine(cd->hinf,
|
|
SubcomponentId,
|
|
KEYWORD_UNINSTALL,
|
|
&context);
|
|
|
|
if (rc) {
|
|
rc = SetupGetStringField(&context,
|
|
1,
|
|
section,
|
|
sizeof(section) / sizeof(TCHAR),
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
if (state) {
|
|
//
|
|
// installation
|
|
//
|
|
|
|
if (rc) {
|
|
// process the inf file
|
|
rc = SetupInstallFromInfSection(NULL, // hwndOwner
|
|
cd->hinf, // inf handle
|
|
section, // name of component
|
|
SPINST_ALL & ~SPINST_FILES,
|
|
NULL, // relative key root
|
|
NULL, // source root path
|
|
0, // copy flags
|
|
NULL, // callback routine
|
|
NULL, // callback routine context
|
|
NULL, // device info set
|
|
NULL); // device info struct
|
|
|
|
if (rc) {
|
|
rc = SetupInstallServicesFromInfSection(cd->hinf, section, 0);
|
|
Error = GetLastError();
|
|
|
|
if (!rc && Error == ERROR_SECTION_NOT_FOUND) {
|
|
rc = TRUE;
|
|
Error = NO_ERROR;
|
|
}
|
|
|
|
if (rc) {
|
|
if (Error == ERROR_SUCCESS_REBOOT_REQUIRED) {
|
|
cd->HelperRoutines.SetReboot(cd->HelperRoutines.OcManagerContext,TRUE);
|
|
}
|
|
Error = NO_ERROR;
|
|
rc = RunExternalProgram(cd, section, state);
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// uninstallation
|
|
//
|
|
|
|
if (rc)
|
|
{
|
|
|
|
rc = RunExternalProgram(cd, section, state);
|
|
|
|
}
|
|
if (rc) {
|
|
|
|
rc = CleanupNetShares(cd, section, state);
|
|
|
|
}
|
|
}
|
|
|
|
if (!rc && (Error == NO_ERROR) ) {
|
|
Error = GetLastError( );
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
/*
|
|
* OnCleanup()
|
|
*
|
|
* handler for OC_CLEANUP
|
|
*/
|
|
|
|
DWORD OnCleanup()
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* OnQueryState()
|
|
*
|
|
* handler for OC_QUERY_STATE
|
|
*/
|
|
|
|
DWORD OnQueryState(LPCTSTR ComponentId,
|
|
LPCTSTR SubcomponentId,
|
|
UINT state)
|
|
{
|
|
//
|
|
// Override default state if MSI provider is already
|
|
// present on the system and this is GUI-mode setup
|
|
//
|
|
PPER_COMPONENT_DATA cd;
|
|
if (cd = LocateComponent(ComponentId))
|
|
{
|
|
if (!(cd->Flags & SETUPOP_STANDALONE))
|
|
{
|
|
if (state == OCSELSTATETYPE_CURRENT)
|
|
{
|
|
if (!_wcsicmp(ComponentId, L"wbemmsi") && !_wcsicmp(SubcomponentId, L"wbemmsi"))
|
|
{
|
|
if (IsMSIProviderPresent())
|
|
{
|
|
return SubcompOn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return SubcompUseOcManagerDefault;
|
|
}
|
|
|
|
/*
|
|
* OnNeedMedia()
|
|
*
|
|
* handler for OC_NEED_MEDIA
|
|
*/
|
|
|
|
DWORD OnNeedMedia()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* OnAboutToCommitQueue()
|
|
*
|
|
* handler for OC_ABOUT_TO_COMMIT_QUEUE
|
|
*/
|
|
|
|
DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
|
|
{
|
|
PPER_COMPONENT_DATA cd;
|
|
BOOL state;
|
|
BOOL rc;
|
|
INFCONTEXT context;
|
|
TCHAR section[256];
|
|
TCHAR srcpathbuf[256];
|
|
TCHAR *srcpath;
|
|
|
|
if (!(cd = LocateComponent(ComponentId)))
|
|
return NO_ERROR;
|
|
|
|
if (!SubcomponentId || !*SubcomponentId)
|
|
return NO_ERROR;
|
|
|
|
if (!StateInfo(cd, SubcomponentId, &state))
|
|
return NO_ERROR;
|
|
|
|
//
|
|
// only do stuff on uninstall
|
|
//
|
|
if (state) {
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Fetch uninstall section name.
|
|
rc = SetupFindFirstLine(
|
|
cd->hinf,
|
|
SubcomponentId,
|
|
KEYWORD_UNINSTALL,
|
|
&context);
|
|
|
|
if (rc) {
|
|
rc = SetupGetStringField(
|
|
&context,
|
|
1,
|
|
section,
|
|
sizeof(section) / sizeof(TCHAR),
|
|
NULL);
|
|
}
|
|
|
|
if (rc)
|
|
rc = SetupInstallServicesFromInfSection(cd->hinf, section, 0);
|
|
|
|
if (rc) {
|
|
rc = SetupInstallFromInfSection(
|
|
NULL,
|
|
cd->hinf,
|
|
section,
|
|
SPINST_ALL & ~SPINST_FILES,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
|
|
if (rc) {
|
|
SetLastError(NO_ERROR);
|
|
}
|
|
return GetLastError();
|
|
|
|
}
|
|
|
|
/*
|
|
* AddNewComponent()
|
|
*
|
|
* add new compononent to the top of the component list
|
|
*/
|
|
|
|
PPER_COMPONENT_DATA AddNewComponent(LPCTSTR ComponentId)
|
|
{
|
|
PPER_COMPONENT_DATA data;
|
|
|
|
data = (PPER_COMPONENT_DATA)LocalAlloc(LPTR,sizeof(PER_COMPONENT_DATA));
|
|
if (!data)
|
|
return data;
|
|
|
|
data->ComponentId = (TCHAR *)LocalAlloc(LMEM_FIXED,
|
|
(_tcslen(ComponentId) + 1) * sizeof(TCHAR));
|
|
|
|
if(data->ComponentId)
|
|
{
|
|
StringCchCopy((TCHAR *)data->ComponentId, (_tcslen(ComponentId) + 1) * sizeof(TCHAR), ComponentId);
|
|
|
|
// Stick at head of list
|
|
data->Next = gcd;
|
|
gcd = data;
|
|
}
|
|
else
|
|
{
|
|
LocalFree((HLOCAL)data);
|
|
data = NULL;
|
|
}
|
|
|
|
return(data);
|
|
}
|
|
|
|
/*
|
|
* LocateComponent()
|
|
*
|
|
* returns a compoent struct that matches the
|
|
* passed component id.
|
|
*/
|
|
|
|
PPER_COMPONENT_DATA LocateComponent(LPCTSTR ComponentId)
|
|
{
|
|
PPER_COMPONENT_DATA p;
|
|
|
|
for (p = gcd; p; p=p->Next)
|
|
{
|
|
if (!_tcsicmp(p->ComponentId, ComponentId))
|
|
return p;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* RemoveComponent()
|
|
*
|
|
* yanks a component from our linked list of components
|
|
*/
|
|
|
|
VOID RemoveComponent(LPCTSTR ComponentId)
|
|
{
|
|
PPER_COMPONENT_DATA p, prev;
|
|
|
|
for (prev = NULL, p = gcd; p; prev = p, p = p->Next)
|
|
{
|
|
if (!_tcsicmp(p->ComponentId, ComponentId))
|
|
{
|
|
LocalFree((HLOCAL)p->ComponentId);
|
|
|
|
if (p->SourcePath)
|
|
LocalFree((HLOCAL)p->SourcePath);
|
|
|
|
if (prev)
|
|
prev->Next = p->Next;
|
|
else
|
|
gcd = p->Next;
|
|
|
|
LocalFree((HLOCAL)p);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// loads current selection state info into "state" and
|
|
// returns whether the selection state was changed
|
|
|
|
BOOL
|
|
StateInfo(
|
|
PPER_COMPONENT_DATA cd,
|
|
LPCTSTR SubcomponentId,
|
|
BOOL *state
|
|
)
|
|
{
|
|
BOOL rc = TRUE;
|
|
|
|
assert(state);
|
|
|
|
// otherwise, check for a change in installation state
|
|
|
|
*state = cd->HelperRoutines.QuerySelectionState(cd->HelperRoutines.OcManagerContext,
|
|
SubcomponentId,
|
|
OCSELSTATETYPE_CURRENT);
|
|
|
|
if (*state == cd->HelperRoutines.QuerySelectionState(cd->HelperRoutines.OcManagerContext,
|
|
SubcomponentId,
|
|
OCSELSTATETYPE_ORIGINAL))
|
|
{
|
|
// no change
|
|
rc = FALSE;
|
|
}
|
|
|
|
// if this is gui mode setup, presume the state has changed to force
|
|
// an installation (or uninstallation)
|
|
|
|
if (!(cd->Flags & SETUPOP_STANDALONE) && *state)
|
|
rc = TRUE;
|
|
|
|
return rc;
|
|
}
|
|
|
|
#if 0
|
|
|
|
//
|
|
// Andrewr -- get rid of RegisterServices and RegisterServers and have the oc gen component use setupapi instead.
|
|
// this reduces the amount of redundant code
|
|
//
|
|
|
|
DWORD RegisterServices(
|
|
PPER_COMPONENT_DATA cd,
|
|
LPCTSTR component,
|
|
DWORD state)
|
|
{
|
|
INFCONTEXT ic;
|
|
TCHAR buf[MAX_PATH];
|
|
TCHAR path[MAX_PATH];
|
|
TCHAR sname[S_SIZE];
|
|
TCHAR file[MAX_PATH];
|
|
DWORD section;
|
|
ULONG size;
|
|
pfn pfreg;
|
|
HINSTANCE hinst;
|
|
HRESULT hr;
|
|
TCHAR *keyword;
|
|
SC_HANDLE schSystem;
|
|
|
|
schSystem = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
|
|
if ( !schSystem ) {
|
|
DWORD dwError = GetLastError( );
|
|
|
|
if( !IsNT() && ( ERROR_CALL_NOT_IMPLEMENTED == dwError ) )
|
|
{
|
|
return( NO_ERROR );
|
|
}
|
|
else
|
|
{
|
|
return( dwError );
|
|
}
|
|
}
|
|
|
|
if (state) {
|
|
keyword = KEYWORD_ADDSERVICE;
|
|
} else {
|
|
keyword = KEYWORD_DELSERVICE;
|
|
}
|
|
|
|
for (section = 1;
|
|
EnumSections(cd->hinf, component, keyword, section, &ic, sname);
|
|
section++)
|
|
{
|
|
INFCONTEXT sic;
|
|
SC_HANDLE schService;
|
|
|
|
CHAR Temp[SBUF_SIZE];
|
|
TCHAR ServiceName[ SBUF_SIZE ];
|
|
TCHAR DisplayName[ SBUF_SIZE ];
|
|
DWORD ServiceType;
|
|
DWORD StartType;
|
|
DWORD ErrorControl;
|
|
TCHAR ImagePath[ SBUF_SIZE ];
|
|
TCHAR LoadOrder[ SBUF_SIZE ];
|
|
TCHAR Dependencies[ SBUF_SIZE ];
|
|
TCHAR StartName[ SBUF_SIZE ];
|
|
TCHAR Password[ SBUF_SIZE ];
|
|
|
|
BOOL fDisplayName = FALSE;
|
|
BOOL fServiceType = FALSE;
|
|
BOOL fStartType = FALSE;
|
|
BOOL fErrorControl = FALSE;
|
|
BOOL fLoadOrder = FALSE;
|
|
BOOL fDependencies = FALSE;
|
|
BOOL fStartName = FALSE;
|
|
BOOL fPassword = FALSE;
|
|
BOOL fDontReboot = FALSE;
|
|
|
|
//
|
|
// Must have ServiceName
|
|
//
|
|
if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_SERVICENAME, &sic))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SERVICENAME );
|
|
continue;
|
|
}
|
|
|
|
if (!SetupGetStringField(&sic, 1, ServiceName, SBUF_SIZE, NULL))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SERVICENAME );
|
|
continue;
|
|
}
|
|
|
|
if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_STARTTYPE, &sic))
|
|
{
|
|
if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
|
|
{
|
|
StartType = atoi( Temp );
|
|
fStartType = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( state )
|
|
{
|
|
if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_DISPLAYNAME, &sic))
|
|
{
|
|
if (SetupGetStringField(&sic, 1, DisplayName, SBUF_SIZE, NULL))
|
|
{
|
|
fDisplayName = TRUE;
|
|
}
|
|
}
|
|
|
|
if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_SERVICETYPE, &sic))
|
|
{
|
|
if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
|
|
{
|
|
ServiceType = atoi( Temp );
|
|
fServiceType = TRUE;
|
|
}
|
|
}
|
|
|
|
if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_ERRORCONTROL, &sic))
|
|
{
|
|
if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
|
|
{
|
|
ErrorControl = atoi( Temp );
|
|
fErrorControl = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Must have ImagePath
|
|
//
|
|
if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_IMAGEPATH, &sic))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_IMAGEPATH );
|
|
continue;
|
|
}
|
|
|
|
if (!SetupGetStringField(&sic, 1, ImagePath, SBUF_SIZE, NULL))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_IMAGEPATH );
|
|
continue;
|
|
}
|
|
|
|
if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_LOADORDER, &sic))
|
|
{
|
|
if (SetupGetStringField(&sic, 1, LoadOrder, SBUF_SIZE, NULL))
|
|
{
|
|
fLoadOrder = TRUE;
|
|
}
|
|
}
|
|
|
|
if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_DEPENDENCIES, &sic))
|
|
{
|
|
if (SetupGetStringField(&sic, 1, Dependencies, SBUF_SIZE-1, NULL))
|
|
{
|
|
LPTSTR psz = Dependencies;
|
|
// needs to be a double-null terminated string
|
|
Dependencies[ lstrlen(Dependencies) + 1] = TEXT('\0');
|
|
|
|
// change commas into NULL characters
|
|
while ( *psz )
|
|
{
|
|
if ( *psz == TEXT(',') )
|
|
{
|
|
*psz = TEXT('\0');
|
|
}
|
|
psz++;
|
|
}
|
|
fDependencies = TRUE;
|
|
}
|
|
}
|
|
|
|
if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_STARTNAME, &sic))
|
|
{
|
|
if (SetupGetStringField(&sic, 1, StartName, SBUF_SIZE, NULL))
|
|
{
|
|
fStartName = TRUE;
|
|
}
|
|
}
|
|
|
|
if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_PASSWORD, &sic))
|
|
{
|
|
if (SetupGetStringField(&sic, 1, Password, SBUF_SIZE, NULL))
|
|
{
|
|
fPassword = TRUE;
|
|
}
|
|
}
|
|
|
|
schService = CreateService(
|
|
schSystem,
|
|
ServiceName,
|
|
( fDisplayName == TRUE ? DisplayName : ServiceName ),
|
|
STANDARD_RIGHTS_REQUIRED | SERVICE_START,
|
|
( fServiceType == TRUE ? ServiceType : SERVICE_WIN32_OWN_PROCESS),
|
|
( fStartType == TRUE ? StartType : SERVICE_AUTO_START),
|
|
( fErrorControl == TRUE ? ErrorControl : SERVICE_ERROR_NORMAL),
|
|
ImagePath,
|
|
(fLoadOrder == TRUE ? LoadOrder : NULL),
|
|
NULL, // tag id
|
|
( fDependencies == TRUE ? Dependencies : NULL ),
|
|
( fStartName == TRUE ? StartName : NULL),
|
|
( fPassword == TRUE ? Password : NULL ));
|
|
|
|
if ( !schService )
|
|
{
|
|
DWORD Error = GetLastError( );
|
|
log( TEXT("OCGEN: CreateService() error 0x%08x\r\n"), Error );
|
|
return Error;
|
|
}
|
|
|
|
if ( (!fStartType)
|
|
|| ( fStartType && StartType == SERVICE_AUTO_START ))
|
|
{
|
|
if( !StartService( schService, 0, NULL ) )
|
|
{
|
|
DWORD Error = GetLastError( );
|
|
switch ( Error )
|
|
{
|
|
case ERROR_SERVICE_EXISTS:
|
|
{
|
|
log( TEXT("OCGEN: %s was already exists.\r\n"), ServiceName );
|
|
|
|
if ( fStartType && StartType == SERVICE_BOOT_START )
|
|
{
|
|
fDontReboot = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ERROR_SERVICE_ALREADY_RUNNING:
|
|
{
|
|
log( TEXT("OCGEN: %s was already started.\r\n"), ServiceName );
|
|
|
|
if ( fStartType && StartType == SERVICE_BOOT_START )
|
|
{
|
|
fDontReboot = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
log( TEXT("OCGEN: StartService() error 0x%08x\r\n"), Error );
|
|
return Error;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
schService = OpenService( schSystem,
|
|
ServiceName,
|
|
STANDARD_RIGHTS_REQUIRED | DELETE );
|
|
if ( schService )
|
|
{
|
|
SERVICE_STATUS ss;
|
|
DeleteService( schService );
|
|
ControlService( schService, SERVICE_CONTROL_STOP, &ss );
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// BOOT drivers require a reboot unless they were already started.
|
|
//
|
|
if ( schService
|
|
&& fStartType && StartType == SERVICE_BOOT_START
|
|
&& fDontReboot == FALSE)
|
|
{
|
|
cd->HelperRoutines.SetReboot(cd->HelperRoutines.OcManagerContext, NULL);
|
|
}
|
|
|
|
if ( schService )
|
|
{
|
|
CloseServiceHandle( schService );
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
#endif
|
|
#if 0
|
|
|
|
DWORD
|
|
RegisterServers(
|
|
HINF hinf,
|
|
LPCTSTR component,
|
|
DWORD state
|
|
)
|
|
{
|
|
INFCONTEXT ic;
|
|
TCHAR buf[MAX_PATH];
|
|
TCHAR path[MAX_PATH];
|
|
TCHAR sname[S_SIZE];
|
|
TCHAR file[MAX_PATH];
|
|
DWORD section;
|
|
ULONG size;
|
|
pfn pfreg;
|
|
HINSTANCE hinst;
|
|
HRESULT hr;
|
|
TCHAR *keyword;
|
|
LPCSTR routine;
|
|
|
|
CoInitialize(NULL);
|
|
|
|
if (state) {
|
|
keyword = KEYWORD_REGSVR;
|
|
routine = (LPCSTR)gszRegisterSvrRoutine;
|
|
} else {
|
|
keyword = KEYWORD_UNREGSVR;
|
|
routine = (LPCSTR)gszUnregisterSvrRoutine;
|
|
}
|
|
|
|
for (section = 1;
|
|
EnumSections(hinf, component, keyword, section, &ic, sname);
|
|
section++)
|
|
{
|
|
if (!SetupGetTargetPath(hinf, NULL, sname, path, sizeof(path), &size))
|
|
continue;
|
|
PathAddBackslash(path);
|
|
|
|
do {
|
|
// get fully qualified path to dll to register
|
|
|
|
if (!SetupGetStringField(&ic, 0, buf, sizeof(buf)/sizeof(buf[0]), NULL))
|
|
continue;
|
|
|
|
_tcscpy(file, path);
|
|
_tcscat(file, buf);
|
|
|
|
// call the dll's RegisterServer routine
|
|
|
|
if (!(hinst = LoadLibrary(file)))
|
|
continue;
|
|
|
|
if (!(pfreg = (pfn)GetProcAddress(hinst, routine)))
|
|
continue;
|
|
|
|
hr = pfreg();
|
|
assert(hr == NO_ERROR);
|
|
|
|
FreeLibrary(hinst);
|
|
|
|
// on to the next
|
|
|
|
} while (SetupFindNextLine(&ic, &ic));
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* EnumSections()
|
|
*
|
|
* finds the name of a section for a specified keyword
|
|
*/
|
|
|
|
DWORD
|
|
EnumSections(
|
|
HINF hinf,
|
|
const TCHAR *component,
|
|
const TCHAR *key,
|
|
DWORD index,
|
|
INFCONTEXT *pic,
|
|
TCHAR *name
|
|
)
|
|
{
|
|
TCHAR section[S_SIZE];
|
|
|
|
if (!SetupFindFirstLine(hinf, component, NULL, pic))
|
|
return 0;
|
|
|
|
if (!SetupFindNextMatchLine(pic, key, pic))
|
|
return 0;
|
|
|
|
if (index > SetupGetFieldCount(pic))
|
|
return 0;
|
|
|
|
if (!SetupGetStringField(pic, index, section, sizeof(section)/sizeof(section[0]), NULL))
|
|
return 0;
|
|
|
|
if (name)
|
|
StringCchCopy(name, S_SIZE, section); // "name" buffer was allocated elsewhere and is S_SIZE characters in size
|
|
|
|
return SetupFindFirstLine(hinf, section, NULL, pic);
|
|
}
|
|
|
|
|
|
DWORD
|
|
OcLog(
|
|
LPCTSTR ComponentId,
|
|
UINT level,
|
|
LPCTSTR sz
|
|
)
|
|
{
|
|
TCHAR fmt[5000];
|
|
PPER_COMPONENT_DATA cd;
|
|
|
|
if (!(cd = LocateComponent(ComponentId)))
|
|
return NO_ERROR;
|
|
|
|
assert(cd->ExtraRoutines.LogError);
|
|
assert(level);
|
|
assert(sz);
|
|
|
|
StringCchCopy(fmt, 5000, TEXT("%s: %s"));
|
|
|
|
return cd->ExtraRoutines.LogError(cd->HelperRoutines.OcManagerContext,
|
|
level,
|
|
fmt,
|
|
ComponentId,
|
|
sz);
|
|
}
|
|
|
|
DWORD
|
|
CleanupNetShares(
|
|
PPER_COMPONENT_DATA cd,
|
|
LPCTSTR component,
|
|
DWORD state)
|
|
{
|
|
INFCONTEXT ic;
|
|
TCHAR sname[S_SIZE];
|
|
DWORD section;
|
|
TCHAR *keyword;
|
|
|
|
if (state) {
|
|
return NO_ERROR;
|
|
} else {
|
|
keyword = KEYWORD_DELSHARE;
|
|
}
|
|
|
|
for (section = 1;
|
|
EnumSections(cd->hinf, component, keyword, section, &ic, sname);
|
|
section++)
|
|
{
|
|
INFCONTEXT sic;
|
|
NET_API_STATUS netStat;
|
|
|
|
CHAR Temp[SBUF_SIZE];
|
|
TCHAR ShareName[ SBUF_SIZE ];
|
|
|
|
if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_SHARENAME, &sic))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SHARENAME );
|
|
continue;
|
|
}
|
|
|
|
if (!SetupGetStringField(&sic, 1, ShareName, SBUF_SIZE, NULL))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_SHARENAME );
|
|
continue;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
netStat = NetShareDel( NULL, ShareName, 0 );
|
|
#else // UNICODE
|
|
WCHAR ShareNameW[ SBUF_SIZE ];
|
|
mbstowcs( ShareNameW, ShareName, lstrlen(ShareName));
|
|
netStat = NetShareDel( NULL, ShareNameW, 0 );
|
|
#endif // UNICODE
|
|
if ( netStat != NERR_Success )
|
|
{
|
|
log( TEXT("OCGEN: Failed to remove %s share. Error 0x%08x\r\n"), ShareName, netStat );
|
|
continue;
|
|
}
|
|
|
|
log( TEXT("OCGEN: %s share removed successfully.\r\n"), ShareName );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD
|
|
RunExternalProgram(
|
|
PPER_COMPONENT_DATA cd,
|
|
LPCTSTR component,
|
|
DWORD state)
|
|
{
|
|
INFCONTEXT ic;
|
|
TCHAR sname[S_SIZE];
|
|
DWORD section;
|
|
TCHAR *keyword;
|
|
|
|
keyword = KEYWORD_RUN;
|
|
|
|
for (section = 1;
|
|
EnumSections(cd->hinf, component, keyword, section, &ic, sname);
|
|
section++)
|
|
{
|
|
INFCONTEXT sic;
|
|
TCHAR CommandLine[ SBUF_SIZE ];
|
|
CHAR szTickCount[ SBUF_SIZE ];
|
|
ULONG TickCount;
|
|
BOOL b;
|
|
STARTUPINFO startupinfo;
|
|
PROCESS_INFORMATION process_information;
|
|
DWORD dwErr;
|
|
|
|
if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_COMMANDLINE , &sic))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_COMMANDLINE );
|
|
continue;
|
|
}
|
|
|
|
if (!SetupGetStringField(&sic, 1, CommandLine, SBUF_SIZE, NULL))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_COMMANDLINE );
|
|
continue;
|
|
}
|
|
|
|
if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_TICKCOUNT, &sic))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_TICKCOUNT );
|
|
continue;
|
|
}
|
|
|
|
if (!SetupGetStringFieldA(&sic, 1, szTickCount, SBUF_SIZE, NULL))
|
|
{
|
|
log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_TICKCOUNT );
|
|
continue;
|
|
}
|
|
|
|
TickCount = atoi( szTickCount );
|
|
|
|
ZeroMemory( &startupinfo, sizeof(startupinfo) );
|
|
startupinfo.cb = sizeof(startupinfo);
|
|
startupinfo.dwFlags = STARTF_USESHOWWINDOW;
|
|
startupinfo.wShowWindow = SW_HIDE | SW_SHOWMINNOACTIVE;
|
|
|
|
b = CreateProcess( NULL,
|
|
CommandLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
CREATE_DEFAULT_ERROR_MODE,
|
|
NULL,
|
|
NULL,
|
|
&startupinfo,
|
|
&process_information );
|
|
if ( !b )
|
|
{
|
|
log( TEXT("OCGEN: failed to spawn %s process.\r\n"), CommandLine );
|
|
continue;
|
|
}
|
|
|
|
dwErr = WaitForSingleObject( process_information.hProcess, TickCount * 1000 );
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
log( TEXT("OCGEN: WaitForSingleObject() failed. Error 0x%08x\r\n"), dwErr );
|
|
TerminateProcess( process_information.hProcess, -1 );
|
|
CloseHandle( process_information.hProcess );
|
|
CloseHandle( process_information.hThread );
|
|
continue;
|
|
}
|
|
|
|
CloseHandle( process_information.hProcess );
|
|
CloseHandle( process_information.hThread );
|
|
|
|
log( TEXT("OCGEN: %s successfully completed within %u seconds.\r\n"), CommandLine, TickCount );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Determine prior install status of WMI components
|
|
//
|
|
|
|
#define WBEM_REG_KEY L"SOFTWARE\\Microsoft\\WBEM"
|
|
#define INSTALL_DIR L"Installation Directory"
|
|
#define MSI_PROVIDER L"msiprov.dll"
|
|
#define CLSID_KEY L"Software\\classes\\CLSID"
|
|
#define CLSID_MSIPROV L"{BE0A9830-2B8B-11D1-A949-0060181EBBAD}"
|
|
|
|
bool IsMSIProviderPresent()
|
|
{
|
|
bool bRet = false;
|
|
|
|
//
|
|
// First check for the present of the provider dll
|
|
//
|
|
HKEY hKey;
|
|
long lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WBEM_REG_KEY, 0, KEY_READ, &hKey);
|
|
if(ERROR_SUCCESS == lRes)
|
|
{
|
|
WCHAR wszTmp[MAX_PATH + 1];
|
|
DWORD dwLen = (MAX_PATH + 1)*sizeof(WCHAR);
|
|
lRes = RegQueryValueEx(hKey, INSTALL_DIR, NULL, NULL, (LPBYTE)wszTmp, &dwLen);
|
|
RegCloseKey(hKey);
|
|
if(ERROR_SUCCESS == lRes)
|
|
{
|
|
WCHAR wszPath[MAX_PATH + 1];
|
|
if (ExpandEnvironmentStrings(wszTmp, wszPath, MAX_PATH + 1))
|
|
{
|
|
StringCchCat(wszPath, MAX_PATH + 1, L"\\" MSI_PROVIDER);
|
|
DWORD dwAttribs = GetFileAttributes(wszPath);
|
|
if (dwAttribs != 0xFFFFFFFF)
|
|
{
|
|
//
|
|
// The file exists, now check for its CLSID in the registry
|
|
//
|
|
WCHAR wszCLSIDKey[62]; // entire key is 61 characters long
|
|
StringCchCopy(wszCLSIDKey, 62, CLSID_KEY L"\\");
|
|
StringCchCat(wszCLSIDKey, 62, CLSID_MSIPROV);
|
|
|
|
lRes = RegOpenKey(HKEY_LOCAL_MACHINE, wszCLSIDKey, &hKey);
|
|
if(ERROR_SUCCESS == lRes)
|
|
{
|
|
RegCloseKey(hKey);
|
|
|
|
//
|
|
// Both the file and the CLSID exist, so the provider is installed
|
|
//
|
|
bRet = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|