|
|
/*
* 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; }
|