|
|
//Copyright (c) 1998 - 1999 Microsoft Corporation
/*--------------------------------------------------------------------------------------------------------
* * Module Name: * * hydraoc.cpp * * Abstract: * * This file implements the optional component HydraOc for Terminal Server Installations. * * * Author: * * Makarand Patwardhan - March 6, 1998 * * Environment: * * User Mode * -------------------------------------------------------------------------------------------------------*/
#include "stdafx.h"
#include "hydraoc.h"
#include "pages.h"
#include "subtoggle.h"
#include "subcore.h"
#include "ocmanage.h"
#define INITGUID // must be before iadmw.h
#include "iadmw.h" // Interface header
#include "iiscnfg.h" // MD_ & IIS_MD_ defines
#define REASONABLE_TIMEOUT 1000
#define TRANS_ADD 0
#define TRANS_DEL 1
#define TRANS_PRINT_PATH 2
#define STRING_TS_WEBCLIENT_INSTALL _T("TSWebClient.Install")
#define STRING_TS_WEBCLIENT_UNINSTALL _T("TSWebClient.UnInstall")
#define STRING_TS_WEBCLIENT _T("TSWebClient")
#define STRING_TS_WEBCLIENT_DIR _T("\\web\\tsweb")
/*--------------------------------------------------------------------------------------------------------
* declarations. * -------------------------------------------------------------------------------------------------------*/ EXTERN_C BOOL WINAPI LinkWindow_RegisterClass() ; EXTERN_C BOOL WINAPI LinkWindow_UnregisterClass( HINSTANCE ) ;
//
// component manager message handlers.
//
DWORD OnPreinitialize (); DWORD OnInitComponent (PSETUP_INIT_COMPONENT psc); DWORD OnExtraRoutines (PEXTRA_ROUTINES pExtraRoutines); DWORD OnSetLanguage (); DWORD OnQueryImage (); DWORD OnSetupRequestPages (WizardPagesType ePageType, SETUP_REQUEST_PAGES *pRequestPages); DWORD OnQuerySelStateChange (LPCTSTR SubcomponentId, UINT SelectionState, LONG Flag); DWORD OnCalcDiskSpace (LPCTSTR SubcomponentId, DWORD addComponent, HDSKSPC dspace); DWORD OnQueueFileOps (LPCTSTR SubcomponentId, HSPFILEQ queue); DWORD OnNotificationFromQueue (); DWORD OnQueryStepCount (LPCTSTR SubComponentId); DWORD OnCompleteInstallation (LPCTSTR SubcomponentId); DWORD OnCleanup (); DWORD OnQueryState (LPCTSTR SubComponentId, UINT whichstate); DWORD OnNeedMedia (); DWORD OnAboutToCommitQueue (LPCTSTR SubcomponentId); DWORD OnQuerySkipPage (); DWORD OnWizardCreated (); DWORD_PTR WebClientSetup (LPCTSTR, LPCTSTR, UINT, UINT_PTR, PVOID);
//
// private utility functions.
//
BOOL OpenMetabaseAndDoStuff(WCHAR *wszVDir, WCHAR *wszDir, int iTrans); BOOL GetVdirPhysicalPath(IMSAdminBase *pIMSAdminBase,WCHAR * wszVDir,WCHAR *wszStringPathToFill); BOOL AddVirtualDir(IMSAdminBase *pIMSAdminBase, WCHAR *wszVDir, WCHAR *wszDir); BOOL RemoveVirtualDir(IMSAdminBase *pIMSAdminBase, WCHAR *wszVDir); INT CheckifServiceExist(LPCTSTR lpServiceName);
/*--------------------------------------------------------------------------------------------------------
* defines * -------------------------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------------------------
* constants -------------------------------------------------------------------------------------------------------*/
//
// global variables and functions to access them.
//
SubCompToggle *gpSubCompToggle = NULL; SubCompCoreTS *gpSubCompCoreTS = NULL; COCPageData *gpAppSrvUninstallPageData = NULL; DefSecPageData *gpSecPageData = NULL; COCPageData *gpPermPageData = NULL; COCPageData *gpAppPageData = NULL;
/*--------------------------------------------------------------------------------------------------------
* LPCTSTR GetOCFunctionName(UINT uiFunction) * utility function for logging the oc messages. * returns oc manager function name from funciton id. * returns _T("Unknown Function") if its unknown. * -------------------------------------------------------------------------------------------------------*/ LPCTSTR GetOCFunctionName(UINT uiFunction) { struct { UINT msg; TCHAR *desc; } gMsgs[] = { {OC_PREINITIALIZE, TEXT("OC_PREINITIALIZE")}, {OC_INIT_COMPONENT, TEXT("OC_INIT_COMPONENT")}, {OC_SET_LANGUAGE, TEXT("OC_SET_LANGUAGE")}, {OC_QUERY_IMAGE, TEXT("OC_QUERY_IMAGE")}, {OC_REQUEST_PAGES, TEXT("OC_REQUEST_PAGES")}, {OC_QUERY_CHANGE_SEL_STATE, TEXT("OC_QUERY_CHANGE_SEL_STATE")}, {OC_CALC_DISK_SPACE, TEXT("OC_CALC_DISK_SPACE")}, {OC_QUEUE_FILE_OPS, TEXT("OC_QUEUE_FILE_OPS")}, {OC_NOTIFICATION_FROM_QUEUE,TEXT("OC_NOTIFICATION_FROM_QUEUE")}, {OC_QUERY_STEP_COUNT, TEXT("OC_QUERY_STEP_COUNT")}, {OC_COMPLETE_INSTALLATION, TEXT("OC_COMPLETE_INSTALLATION")}, {OC_CLEANUP, TEXT("OC_CLEANUP")}, {OC_QUERY_STATE, TEXT("OC_QUERY_STATE")}, {OC_NEED_MEDIA, TEXT("OC_NEED_MEDIA")}, {OC_ABOUT_TO_COMMIT_QUEUE, TEXT("OC_ABOUT_TO_COMMIT_QUEUE")}, {OC_QUERY_SKIP_PAGE, TEXT("OC_QUERY_SKIP_PAGE")}, {OC_WIZARD_CREATED, TEXT("OC_WIZARD_CREATED")}, {OC_EXTRA_ROUTINES, TEXT("OC_EXTRA_ROUTINES")} }; for (int i = 0; i < sizeof(gMsgs) / sizeof(gMsgs[0]); i++) { if (gMsgs[i].msg == uiFunction) return gMsgs[i].desc; } return _T("Unknown Function"); }
/*--------------------------------------------------------------------------------------------------------
* called by CRT when _DllMainCRTStartup is the DLL entry point * -------------------------------------------------------------------------------------------------------*/
BOOL WINAPI DllMain(IN HINSTANCE hinstance, IN DWORD reason, IN LPVOID /*reserved*/ ) { SetInstance( hinstance ); switch(reason) { case DLL_PROCESS_ATTACH: TCHAR szLogFile[MAX_PATH]; ExpandEnvironmentStrings(LOGFILE, szLogFile, MAX_PATH); LOGMESSAGEINIT(szLogFile, MODULENAME); break; case DLL_THREAD_ATTACH: case DLL_PROCESS_DETACH: case DLL_THREAD_DETACH: break; } return(TRUE); // for successful process_attach
}
/*--------------------------------------------------------------------------------------------------------
* This is our export function which will be called by OC Manager * -------------------------------------------------------------------------------------------------------*/ DWORD_PTR HydraOc( IN LPCTSTR ComponentId, IN LPCTSTR SubcomponentId, IN UINT Function, IN UINT_PTR Param1, IN OUT PVOID Param2 ) { // we use this variable to track if we receive OnCompleteInstallation or not.
// there is a problem with ocm which aborts all the components if any of them
// does something wrong with file queue.
static BOOL sbGotCompleteMessage = FALSE; LOGMESSAGE1(_T("Entering %s"), GetOCFunctionName(Function)); if ((OC_PREINITIALIZE != Function) && SubcomponentId) LOGMESSAGE2(_T("Component=%s, SubComponent=%s"), ComponentId, SubcomponentId); else LOGMESSAGE2(_T("Component=%s, SubComponent=%s"), ComponentId, _T("(null)"));
DWORD_PTR rc; if (SubcomponentId && _tcsicmp(SubcomponentId, _T("tswebClient")) == 0) { rc = WebClientSetup(ComponentId, SubcomponentId, Function, Param1, Param2); LOGMESSAGE2(_T("%s Done. Returning %lu\r\n\r\n"), GetOCFunctionName(Function), rc); return rc; } // since we are supporting only one component.
ASSERT(_tcsicmp(APPSRV_COMPONENT_NAME, ComponentId) == 0); switch(Function) { case OC_PREINITIALIZE: rc = OnPreinitialize(); break; case OC_INIT_COMPONENT: rc = OnInitComponent((PSETUP_INIT_COMPONENT)Param2); break; case OC_EXTRA_ROUTINES: rc = OnExtraRoutines((PEXTRA_ROUTINES)Param2); break; case OC_SET_LANGUAGE: rc = OnSetLanguage(); break; case OC_QUERY_IMAGE: rc = OnQueryImage(); break; case OC_REQUEST_PAGES: rc = OnSetupRequestPages(WizardPagesType(Param1), PSETUP_REQUEST_PAGES (Param2)); break; case OC_QUERY_CHANGE_SEL_STATE: rc = OnQuerySelStateChange(SubcomponentId, (UINT)Param1, LONG(ULONG_PTR(Param2))); break; case OC_CALC_DISK_SPACE: rc = OnCalcDiskSpace(SubcomponentId, (DWORD)Param1, Param2); break; case OC_QUEUE_FILE_OPS: rc = OnQueueFileOps(SubcomponentId, (HSPFILEQ)Param2); break; case OC_NOTIFICATION_FROM_QUEUE: rc = OnNotificationFromQueue(); break; case OC_QUERY_STEP_COUNT: rc = OnQueryStepCount(SubcomponentId); break; case OC_COMPLETE_INSTALLATION: sbGotCompleteMessage = TRUE; rc = OnCompleteInstallation(SubcomponentId); break; case OC_CLEANUP: rc = OnCleanup(); if (!sbGotCompleteMessage) { if (StateObject.IsStandAlone()) { LOGMESSAGE0(_T("Error:StandAlone:TSOC Did not get OC_COMPLETE_INSTALLATION.")); } else { LOGMESSAGE0(_T("Error:TSOC Did not get OC_COMPLETE_INSTALLATION.")); } } break; case OC_QUERY_STATE: rc = OnQueryState(SubcomponentId, (UINT)Param1); break; case OC_NEED_MEDIA: rc = OnNeedMedia(); break; case OC_ABOUT_TO_COMMIT_QUEUE: rc = OnAboutToCommitQueue(SubcomponentId); break; case OC_QUERY_SKIP_PAGE: rc = OnQuerySkipPage(); break; case OC_WIZARD_CREATED: rc = OnWizardCreated(); break; default: rc = 0; // it means we do not recognize this command.
break; } LOGMESSAGE2(_T("%s Done. Returning %lu\r\n\r\n"), GetOCFunctionName(Function), rc); return rc; }
/*--------------------------------------------------------------------------------------------------------
* OC Manager message handlers * -------------------------------------------------------------------------------------------------------*/
DWORD OnPreinitialize(VOID) { #ifdef ANSI
return OCFLAG_ANSI; #else
return OCFLAG_UNICODE; #endif
}
/*--------------------------------------------------------------------------------------------------------
* OnInitComponent() * * handler for OC_INIT_COMPONENT * -------------------------------------------------------------------------------------------------------*/
DWORD OnInitComponent(PSETUP_INIT_COMPONENT psc) { ASSERT(psc); //
// let the ocmanager know our version
//
psc->ComponentVersion = COMPONENT_VERSION; //
// Is this component written for newer version than the oc manager ?
//
if (COMPONENT_VERSION > psc->OCManagerVersion) { LOGMESSAGE2(_T("ERROR:OnInitComponent: COMPONENT_VERSION(%x) > psc->OCManagerVersion(%x)"), COMPONENT_VERSION, psc->OCManagerVersion); return ERROR_CALL_NOT_IMPLEMENTED; } if (!StateObject.Initialize(psc)) { return ERROR_CANCELLED; // due to ERROR_OUTOFMEMORY;
} // if its standalone (!guimode) setup, We must have Hydra in product suite by now.
// ASSERT( StateObject.IsGuiModeSetup() || DoesHydraKeysExists() );
//
// now create our subcomponents
//
gpSubCompToggle = new SubCompToggle; gpSubCompCoreTS = new SubCompCoreTS; if (!gpSubCompToggle || !gpSubCompCoreTS) return ERROR_CANCELLED; //
// if initialization of any of the sub component fails
// fail the setup
//
if (!gpSubCompToggle->Initialize() || !gpSubCompCoreTS->Initialize()) return ERROR_CANCELLED; return NO_ERROR; }
DWORD OnExtraRoutines( PEXTRA_ROUTINES pExtraRoutines ) { ASSERT(pExtraRoutines); return(SetExtraRoutines(pExtraRoutines) ? ERROR_SUCCESS : ERROR_CANCELLED); }
/*--------------------------------------------------------------------------------------------------------
* OnCalcDiskSpace() * * handler for OC_ON_CALC_DISK_SPACE * -------------------------------------------------------------------------------------------------------*/
DWORD OnCalcDiskSpace( LPCTSTR /* SubcomponentId */, DWORD addComponent, HDSKSPC dspace ) { return gpSubCompCoreTS->OnCalcDiskSpace(addComponent, dspace); }
/*--------------------------------------------------------------------------------------------------------
* OnQueueFileOps() * * handler for OC_QUEUE_FILE_OPS * -------------------------------------------------------------------------------------------------------*/
DWORD OnQueueFileOps(LPCTSTR SubcomponentId, HSPFILEQ queue) { if (SubcomponentId == NULL) { return gpSubCompCoreTS->OnQueueFiles( queue ); } else if (_tcsicmp(SubcomponentId, APPSRV_COMPONENT_NAME) == 0) { return gpSubCompToggle->OnQueueFiles( queue ); } else { ASSERT(FALSE); LOGMESSAGE1(_T("ERROR, Got a OnQueueFileOps with unknown SubComp(%s)"), SubcomponentId); return 0; } }
/*--------------------------------------------------------------------------------------------------------
* OnCompleteInstallation * * handler for OC_COMPLETE_INSTALLATION * -------------------------------------------------------------------------------------------------------*/
DWORD OnCompleteInstallation(LPCTSTR SubcomponentId) { static BOOL sbStateUpdated = FALSE; if (!sbStateUpdated) { StateObject.UpdateState(); sbStateUpdated = TRUE; } if (SubcomponentId == NULL) { return gpSubCompCoreTS->OnCompleteInstall(); } else if (_tcsicmp(SubcomponentId, APPSRV_COMPONENT_NAME) == 0) { return gpSubCompToggle->OnCompleteInstall(); } else { ASSERT(FALSE); LOGMESSAGE1(_T("ERROR, Got a Complete Installation with unknown SubComp(%s)"), SubcomponentId); return 0; } }
/*--------------------------------------------------------------------------------------------------------
* OnSetLanguage() * * handler for OC_SET_LANGUAGE * -------------------------------------------------------------------------------------------------------*/
DWORD OnSetLanguage() { return false; }
/*--------------------------------------------------------------------------------------------------------
* OnSetLanguage() * * handler for OC_SET_LANGUAGE * -------------------------------------------------------------------------------------------------------*/
DWORD OnQueryImage() { return NULL; }
/*--------------------------------------------------------------------------------------------------------
* OnSetupRequestPages * * Prepares wizard pages and returns them to the OC Manager * -------------------------------------------------------------------------------------------------------*/
DWORD OnSetupRequestPages (WizardPagesType ePageType, SETUP_REQUEST_PAGES *pRequestPages) { if (ePageType == WizPagesEarly) { ASSERT(pRequestPages); const UINT uiPages = 4; // if we are provided sufficient space for our pages
if (pRequestPages->MaxPages >= uiPages ) { //
// Pages will be deleted in PSPCB_RELEASE in OCPage::PropSheetPageProc
//
LinkWindow_RegisterClass(); gpAppPageData = new COCPageData; AppSrvWarningPage *pAppSrvWarnPage = new AppSrvWarningPage(gpAppPageData); gpSecPageData = new DefSecPageData; DefaultSecurityPage *pSecPage = new DefaultSecurityPage(gpSecPageData); gpPermPageData = new COCPageData; PermPage *pPermPage = new PermPage(gpPermPageData); gpAppSrvUninstallPageData = new COCPageData; AppSrvUninstallpage *pAppSrvUninstallPage = new AppSrvUninstallpage(gpAppSrvUninstallPageData); if (pAppSrvWarnPage && pAppSrvWarnPage->Initialize() && pSecPage && pSecPage->Initialize() && pPermPage && pPermPage->Initialize() && pAppSrvUninstallPage && pAppSrvUninstallPage->Initialize() ) { ASSERT(pRequestPages->Pages); pRequestPages->Pages[0] = CreatePropertySheetPage((PROPSHEETPAGE *) pAppSrvWarnPage); pRequestPages->Pages[1] = CreatePropertySheetPage((PROPSHEETPAGE *) pSecPage); pRequestPages->Pages[2] = CreatePropertySheetPage((PROPSHEETPAGE *) pPermPage); pRequestPages->Pages[3] = CreatePropertySheetPage((PROPSHEETPAGE *) pAppSrvUninstallPage); ASSERT(pRequestPages->Pages[0]); ASSERT(pRequestPages->Pages[1]); ASSERT(pRequestPages->Pages[2]); ASSERT(pRequestPages->Pages[3]); } else { //
// failed to allocate memory
//
if (gpAppPageData) delete gpAppPageData; gpAppPageData = NULL; if (pAppSrvWarnPage) delete pAppSrvWarnPage; pAppSrvWarnPage = NULL; if (gpSecPageData) delete gpSecPageData; gpSecPageData = NULL; if (pSecPage) delete pSecPage; pSecPage = NULL; if (gpPermPageData) delete gpPermPageData; gpPermPageData = NULL; if (pPermPage) delete pPermPage; pPermPage =NULL; if (gpAppSrvUninstallPageData) delete gpAppSrvUninstallPageData; gpAppSrvUninstallPageData = NULL; if (pAppSrvUninstallPage) delete pAppSrvUninstallPage; pAppSrvUninstallPage = NULL; SetLastError(ERROR_OUTOFMEMORY); return DWORD(-1); } } return uiPages; } return 0; }
/*--------------------------------------------------------------------------------------------------------
* OnWizardCreated() * -------------------------------------------------------------------------------------------------------*/
DWORD OnWizardCreated() { return NO_ERROR; }
/*--------------------------------------------------------------------------------------------------------
* OnQuerySkipPage() * * don't let the user deselect the sam component * -------------------------------------------------------------------------------------------------------*/
DWORD OnQuerySkipPage() { return false; }
/*--------------------------------------------------------------------------------------------------------
* OnQuerySelStateChange(LPCTSTR SubcomponentId, UINT SelectionState, LONG Flag); * * informs that user has changed the state of the component/subcomponent and asks approval * -------------------------------------------------------------------------------------------------------*/
DWORD OnQuerySelStateChange(LPCTSTR SubcomponentId, UINT SelectionState, LONG Flag) { BOOL bNewState = SelectionState; BOOL bDirectSelection = Flag & OCQ_ACTUAL_SELECTION; LOGMESSAGE3(_T("OnQuerySelStateChange for %s, NewState = %d, DirectSelect = %s"), SubcomponentId, SelectionState, bDirectSelection ? _T("True") : _T("False")); return gpSubCompToggle->OnQuerySelStateChange(bNewState, bDirectSelection); }
/*--------------------------------------------------------------------------------------------------------
* OnCleanup() * * handler for OC_CLEANUP * -------------------------------------------------------------------------------------------------------*/
DWORD OnCleanup() { if (gpAppPageData) delete gpAppPageData; if (gpSecPageData) delete gpSecPageData; if (gpPermPageData) delete gpPermPageData; if (gpAppSrvUninstallPageData) delete gpAppSrvUninstallPageData; if (gpSubCompToggle) delete gpSubCompToggle; if (gpSubCompCoreTS) delete gpSubCompCoreTS; // DestroySetupData();
DestroyExtraRoutines(); return NO_ERROR; }
/*--------------------------------------------------------------------------------------------------------
* OnQueryState() * * handler for OC_QUERY_STATE * -------------------------------------------------------------------------------------------------------*/
DWORD OnQueryState(LPCTSTR SubComponentId, UINT whichstate) { ASSERT(OCSELSTATETYPE_ORIGINAL == whichstate || OCSELSTATETYPE_CURRENT == whichstate || OCSELSTATETYPE_FINAL == whichstate); TCHAR szState[256]; switch (whichstate) { case OCSELSTATETYPE_ORIGINAL: _tcscpy(szState, _T("Original")); break; case OCSELSTATETYPE_CURRENT: _tcscpy(szState, _T("Current")); break; case OCSELSTATETYPE_FINAL: _tcscpy(szState, _T("Final")); break; default: ASSERT(FALSE); return ERROR_BAD_ARGUMENTS; } DWORD dwReturn = gpSubCompToggle->OnQueryState(whichstate); TCHAR szReturn[] = _T("SubcompUseOcManagerUknownState"); switch (dwReturn) { case SubcompOn: _tcscpy(szReturn, _T("SubcompOn")); break; case SubcompUseOcManagerDefault: _tcscpy(szReturn, _T("SubcompUseOcManagerDefault")); break; case SubcompOff: _tcscpy(szReturn, _T("SubcompOff")); break; default: ASSERT(FALSE); } LOGMESSAGE3(_T("Query State Asked For %s, %s. Returning %s"), SubComponentId, szState, szReturn); return dwReturn; }
/*--------------------------------------------------------------------------------------------------------
* 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 for OC_QUERY_STEP_COUNT * -------------------------------------------------------------------------------------------------------*/
DWORD OnQueryStepCount(LPCTSTR /* SubcomponentId */) { //
// now return the ticks for the component
//
return gpSubCompCoreTS->OnQueryStepCount() + gpSubCompToggle->OnQueryStepCount(); }
/*--------------------------------------------------------------------------------------------------------
* OnNeedMedia() * * handler for OC_NEED_MEDIA * -------------------------------------------------------------------------------------------------------*/
DWORD OnNeedMedia() { return false; }
/*--------------------------------------------------------------------------------------------------------
* OnAboutToCommitQueue() * * handler for OC_ABOUT_TO_COMMIT_QUEUE * -------------------------------------------------------------------------------------------------------*/
DWORD OnAboutToCommitQueue(LPCTSTR /* SubcomponentId */) { return NO_ERROR; }
/*--------------------------------------------------------------------------------------------------------
* BOOL DoesHydraKeysExists() * * checks if Teminal server string exists in the product suite key. * -------------------------------------------------------------------------------------------------------*/
BOOL DoesHydraKeysExists() { BOOL bStringExists = FALSE; DWORD dw = IsStringInMultiString( HKEY_LOCAL_MACHINE, PRODUCT_SUITE_KEY, PRODUCT_SUITE_VALUE, TS_PRODUCT_SUITE_STRING, &bStringExists); return (dw == ERROR_SUCCESS) && bStringExists; }
/*--------------------------------------------------------------------------------------------------------
* DWORD IsStringInMultiString(HKEY hkey, LPCTSTR szkey, LPCTSTR szvalue, LPCTSTR szCheckForString, BOOL *pbFound) * checks if parameter string exists in given multistring. * returns error code. * -------------------------------------------------------------------------------------------------------*/ DWORD IsStringInMultiString(HKEY hkey, LPCTSTR szkey, LPCTSTR szvalue, LPCTSTR szCheckForString, BOOL *pbFound) { ASSERT(szkey && *szkey); ASSERT(szvalue && *szvalue); ASSERT(szCheckForString&& *szCheckForString); ASSERT(*szkey != '\\'); ASSERT(pbFound); // not yet found.
*pbFound = FALSE; CRegistry reg; DWORD dwError = reg.OpenKey(hkey, szkey, KEY_READ); // open up the required key.
if (dwError == NO_ERROR) { LPTSTR szSuiteValue; DWORD dwSize; dwError = reg.ReadRegMultiString(szvalue, &szSuiteValue, &dwSize); if (dwError == NO_ERROR) { LPCTSTR pTemp = szSuiteValue; while(_tcslen(pTemp) > 0 ) { if (_tcscmp(pTemp, szCheckForString) == 0) { *pbFound = TRUE; break; } pTemp += _tcslen(pTemp) + 1; // point to the next string within the multistring.
if ( DWORD(pTemp - szSuiteValue) > (dwSize / sizeof(TCHAR))) break; // temporary pointer passes the size of the szSuiteValue something is wrong with szSuiteValue.
} } } return dwError; }
/*--------------------------------------------------------------------------------------------------------
* DWORD AppendStringToMultiString(HKEY hkey, LPCTSTR szSuitekey, LPCTSTR szSuitevalue, LPCTSTR szAppend) * appends given string to the given multi_sz value * the given key / value must exist. * returns error code. * -------------------------------------------------------------------------------------------------------*/ DWORD AppendStringToMultiString(HKEY hkey, LPCTSTR szSuitekey, LPCTSTR szSuitevalue, LPCTSTR szAppend) { ASSERT(szSuitekey && *szSuitekey); ASSERT(szSuitevalue && *szSuitevalue); ASSERT(szAppend && *szAppend); ASSERT(*szSuitekey != '\\'); CRegistry reg; // open the registry key.
DWORD dwResult = reg.OpenKey(hkey, szSuitekey, KEY_READ | KEY_WRITE); if (dwResult == ERROR_SUCCESS) { DWORD dwSize = 0; LPTSTR strOriginalString = 0; // read our multi string
dwResult = reg.ReadRegMultiString(szSuitevalue, &strOriginalString, &dwSize); if (dwResult == ERROR_SUCCESS) { // now calculate the Memory required for appending the string.
// as dwOldSize is in bytes and we are using TCHARs
DWORD dwMemReq = dwSize + ((_tcslen(szAppend) + 2) * sizeof(TCHAR) / sizeof(BYTE)); // NOTE: if dwSize is >= 1 we just require
// dwSize + ((_tcslen(szAppend) + 1) * sizeof(TCHAR) / sizeof(BYTE));
// But in case its 0 we provide space for an additional terminating null
LPTSTR szProductSuite = (LPTSTR ) new BYTE [dwMemReq]; if (!szProductSuite) { return ERROR_OUTOFMEMORY; } CopyMemory(szProductSuite, strOriginalString, dwSize);
// convert the size into TCHARs
dwSize = dwSize * sizeof(BYTE) / sizeof(TCHAR); if (dwSize <= 2) { // there are no strings out there.
_tcscpy(szProductSuite, szAppend);
// new size including terminating null in tchar
dwSize = _tcslen(szAppend) + 2; } else { // there are strings in its. so append our string before the terminating null.
// for example for this string "A\0B\0\0" dwSize == 5 and we are doing tcscat at "A\0B\0\0" + 4
_tcscpy(szProductSuite + dwSize - 1, szAppend); // new size including terminating null in tchar
dwSize += _tcslen(szAppend) + 1; } // now append a final terminating null character.
*(szProductSuite + dwSize-1) = NULL;
// reconvert size into bytes.
dwSize *= sizeof(TCHAR) / sizeof(BYTE); // and finally write the final string.
dwResult = reg.WriteRegMultiString(szSuitevalue, szProductSuite, dwSize); delete [] szProductSuite;
} } return dwResult; }
/*--------------------------------------------------------------------------------------------------------
* BOOL GetStringValue(HINF hinf, LPCTSTR section, LPCTSTR key, LPTSTR outputbuffer, DWORD dwSize) * returns the given string value under given section. * returns success * -------------------------------------------------------------------------------------------------------*/ DWORD GetStringValue(HINF hinf, LPCTSTR section, LPCTSTR key, LPTSTR outputbuffer, DWORD dwSize) { INFCONTEXT context;
BOOL rc = SetupFindFirstLine( hinf, section, key, &context ); if (rc) { rc = SetupGetStringField( &context, 1, outputbuffer, dwSize, &dwSize ); } if (!rc) return GetLastError(); else return ERROR_SUCCESS; }
DWORD_PTR WebClientSetup(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT Function, UINT_PTR Param1, PVOID Param2) { DWORD_PTR rc = NO_ERROR; BOOL bCurrentState, bOriginalState; LOGMESSAGE1(_T("Entering %s"), _T("WebClient Setup")); switch(Function) { case OC_INIT_COMPONENT: return NO_ERROR; case OC_QUERY_STATE: return SubcompUseOcManagerDefault; break; case OC_SET_LANGUAGE: return FALSE;
case OC_QUERY_IMAGE: rc = (DWORD_PTR)LoadImage(GetInstance(), MAKEINTRESOURCE(IDB_WEBCLIENT), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); LOGMESSAGE1(_T("Bitmap is: %d"), rc); return rc; case OC_QUERY_CHANGE_SEL_STATE: { BOOL rc = TRUE; BOOL fDependentSelection = (BOOL)((INT_PTR)Param2 & OCQ_DEPENDENT_SELECTION); BOOL fProposedState = (BOOL)Param1;
//
// Don't allow an indirect selection (e.g. don't allow clicking on
// the parent to enable the child)
//
if (fDependentSelection && fProposedState) { rc = FALSE; }
return rc; } break; case OC_CALC_DISK_SPACE: //rc = OnCalcDiskSpace(SubcomponentId, (DWORD)Param1, Param2);
//_tcscpy(section, SubcomponentId);
if ((DWORD)Param1) { rc = SetupAddInstallSectionToDiskSpaceList((HDSKSPC)Param2, GetComponentInfHandle(), NULL, STRING_TS_WEBCLIENT_INSTALL, 0, 0); } else { rc = SetupRemoveInstallSectionFromDiskSpaceList((HDSKSPC)Param2, GetComponentInfHandle(), NULL, STRING_TS_WEBCLIENT_INSTALL, 0, 0); } LOGMESSAGE1(_T("Query Disk Space return: %d"), rc); if (!rc) rc = GetLastError(); else rc = NO_ERROR; break; case OC_QUEUE_FILE_OPS: rc = NO_ERROR; bOriginalState = GetHelperRoutines().QuerySelectionState(GetHelperRoutines().OcManagerContext, STRING_TS_WEBCLIENT, OCSELSTATETYPE_ORIGINAL); bCurrentState = GetHelperRoutines().QuerySelectionState(GetHelperRoutines().OcManagerContext, STRING_TS_WEBCLIENT, OCSELSTATETYPE_CURRENT); LOGMESSAGE2(_T("Original=%d, Current=%d"), bOriginalState, bCurrentState); if(bCurrentState) { // Only copy files if it's machine upgrade or
// the component is not previously installed
if (!StateObject.IsStandAlone() || !bOriginalState) { if (!SetupInstallFilesFromInfSection(GetComponentInfHandle(), NULL, (HSPFILEQ)Param2, STRING_TS_WEBCLIENT_INSTALL, NULL, 0)) { rc = GetLastError(); LOGMESSAGE2(_T("ERROR:OnQueueFileOps::SetupInstallFilesFromInfSection <%s> failed.GetLastError() = <%ul)"), SubcomponentId, rc); } } LOGMESSAGE1(_T("Copy files return: %d"), rc); break; } else { if (!bOriginalState) { // Not installed before, do nothing
return NO_ERROR; } if (!SetupInstallFilesFromInfSection(GetComponentInfHandle(), NULL, (HSPFILEQ)Param2, STRING_TS_WEBCLIENT_UNINSTALL, NULL, 0)) { rc = GetLastError(); LOGMESSAGE2(_T("ERROR:OnQueueFileOps::SetupInstallFilesFromInfSection <%s> failed.GetLastError() = <%ul)"), SubcomponentId, rc); } LOGMESSAGE1(_T("Remove files return: %d"), rc); break; } case OC_COMPLETE_INSTALLATION: bOriginalState = GetHelperRoutines().QuerySelectionState(GetHelperRoutines().OcManagerContext, _T("TSWebClient"), OCSELSTATETYPE_ORIGINAL); bCurrentState = GetHelperRoutines().QuerySelectionState(GetHelperRoutines().OcManagerContext, _T("TSWebClient"), OCSELSTATETYPE_CURRENT); LOGMESSAGE2(_T("Orinal=%d, Current=%d"), bOriginalState, bCurrentState); if(bOriginalState==bCurrentState) //state does not change
return NO_ERROR; int iTrans; //mark removing or adding tsweb dir
int nLength; iTrans = 0; WCHAR wszVDirName[MAX_PATH]; WCHAR wszDirPath[MAX_PATH]; TCHAR szDirPath[MAX_PATH]; TCHAR szVDirName[MAX_PATH]; if (GetWindowsDirectory(szDirPath, MAX_PATH) == 0) { rc = GetLastError(); return rc; } nLength = _tcsclen(szDirPath); if(_T('\\')==szDirPath[nLength-1]) szDirPath[nLength-1]=_T('\0'); _tcscat(szDirPath, STRING_TS_WEBCLIENT_DIR); if (LoadString(GetInstance(), IDS_STRING_TSWEBCLIENT_VIRTUALPATH, szVDirName, MAX_PATH) == 0) { LOGMESSAGE0(_T("Can't load string IDS_STRING_TSWEBCLIENT_VIRTUALPATH")); rc = GetLastError();; } LOGMESSAGE2(_T("Dir Path is: %s, Virtual Name is: %s"), szDirPath, szVDirName); if(bCurrentState) //enable IIS directory
iTrans = TRANS_ADD; else iTrans = TRANS_DEL; #ifndef _UNICODE
MultiByteToWideChar(CP_ACP, 0, szDirPath, -1, (LPWSTR) wszDirPath, MAX_PATH); MultiByteToWideChar(CP_ACP, 0, szVDirName, -1, (LPWSTR) wszVDirName, MAX_PATH); #else
_tcscpy(wszDirPath, szDirPath); _tcscpy(wszVDirName, szVDirName); #endif
rc = OpenMetabaseAndDoStuff(wszVDirName, wszDirPath, iTrans)?0:1; LOGMESSAGE1(_T("Websetup complete, return is: %d"), rc); return rc; default: rc = NO_ERROR; // it means we do not recognize this command.
break; } return rc; }
BOOL OpenMetabaseAndDoStuff( WCHAR * wszVDir, WCHAR * wszDir, int iTrans) { BOOL fRet = FALSE; HRESULT hr; IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
WCHAR wszPrintString[MAX_PATH + MAX_PATH]; // Make sure that IISADMIN service exists
if (CheckifServiceExist(_T("IISADMIN")) != 0) { LOGMESSAGE0(_T("IISADMIN service does not exist")); // We have to return TRUE here if IIS service does not exist
return TRUE; } if( FAILED (hr = CoInitializeEx( NULL, COINIT_MULTITHREADED )) || FAILED (hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void **)&pIMSAdminBase))) { LOGMESSAGE1(_T("CoCreateInstance failed with error code %u"), hr); return FALSE; } switch (iTrans) { case TRANS_DEL: if(RemoveVirtualDir( pIMSAdminBase, wszVDir)) { hr = pIMSAdminBase->SaveData(); if( SUCCEEDED( hr )) { fRet = TRUE; } } break; case TRANS_ADD: if(AddVirtualDir( pIMSAdminBase, wszVDir, wszDir)) { hr = pIMSAdminBase->SaveData(); if( SUCCEEDED( hr )) { fRet = TRUE; } } break; default: break; } if (pIMSAdminBase) { pIMSAdminBase->Release(); pIMSAdminBase = NULL; } CoUninitialize(); return fRet; }
BOOL GetVdirPhysicalPath( IMSAdminBase *pIMSAdminBase, WCHAR * wszVDir, WCHAR *wszStringPathToFill) { HRESULT hr; BOOL fRet = FALSE; METADATA_HANDLE hMetabase = NULL; // handle to metabase
METADATA_RECORD mr; WCHAR szTmpData[MAX_PATH]; DWORD dwMDRequiredDataLen; // open key to ROOT on website #1 (default)
hr = pIMSAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/1", METADATA_PERMISSION_READ, REASONABLE_TIMEOUT, &hMetabase); if( FAILED( hr )) { return FALSE; } // Get the physical path for the WWWROOT
mr.dwMDIdentifier = MD_VR_PATH; mr.dwMDAttributes = 0; mr.dwMDUserType = IIS_MD_UT_FILE; mr.dwMDDataType = STRING_METADATA; mr.dwMDDataLen = sizeof( szTmpData ); mr.pbMDData = reinterpret_cast<unsigned char *>(szTmpData); //if nothing specified get the root.
if (_wcsicmp(wszVDir, L"") == 0) { WCHAR wszTempDir[MAX_PATH]; swprintf(wszTempDir,L"/ROOT/%s", wszVDir); hr = pIMSAdminBase->GetData( hMetabase, wszTempDir, &mr, &dwMDRequiredDataLen ); } else { hr = pIMSAdminBase->GetData( hMetabase, L"/ROOT", &mr, &dwMDRequiredDataLen ); } pIMSAdminBase->CloseKey( hMetabase ); if( SUCCEEDED( hr )) { wcscpy(wszStringPathToFill,szTmpData); fRet = TRUE; } pIMSAdminBase->CloseKey( hMetabase ); return fRet; }
BOOL AddVirtualDir( IMSAdminBase *pIMSAdminBase, WCHAR * wszVDir, WCHAR * wszDir) { HRESULT hr; BOOL fRet = FALSE; METADATA_HANDLE hMetabase = NULL; // handle to metabase
WCHAR szTempPath[MAX_PATH]; DWORD dwMDRequiredDataLen = 0; DWORD dwAccessPerm = 0; METADATA_RECORD mr; // Attempt to open the virtual dir set on Web server #1 (default server)
hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/1/ROOT", METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, REASONABLE_TIMEOUT, &hMetabase ); // Create the key if it does not exist.
if( FAILED( hr )) { return FALSE; } fRet = TRUE; mr.dwMDIdentifier = MD_VR_PATH; mr.dwMDAttributes = 0; mr.dwMDUserType = IIS_MD_UT_FILE; mr.dwMDDataType = STRING_METADATA; mr.dwMDDataLen = sizeof( szTempPath ); mr.pbMDData = reinterpret_cast<unsigned char *>(szTempPath);
// see if MD_VR_PATH exists.
hr = pIMSAdminBase->GetData( hMetabase, wszVDir, &mr, &dwMDRequiredDataLen ); if( FAILED( hr )) { fRet = FALSE; if( hr == MD_ERROR_DATA_NOT_FOUND || HRESULT_CODE(hr) == ERROR_PATH_NOT_FOUND ) { // Write both the key and the values if GetData() failed with any of the two errors.
pIMSAdminBase->AddKey( hMetabase, wszVDir ); mr.dwMDIdentifier = MD_VR_PATH; mr.dwMDAttributes = METADATA_INHERIT; mr.dwMDUserType = IIS_MD_UT_FILE; mr.dwMDDataType = STRING_METADATA; mr.dwMDDataLen = (wcslen(wszDir) + 1) * sizeof(WCHAR); mr.pbMDData = reinterpret_cast<unsigned char *>(wszDir); // Write MD_VR_PATH value
hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr ); fRet = SUCCEEDED( hr ); // Set the default authentication method
if( fRet ) { DWORD dwAuthorization = MD_AUTH_ANONYMOUS; // NTLM only.
mr.dwMDIdentifier = MD_AUTHORIZATION; mr.dwMDAttributes = METADATA_INHERIT; // need to inherit so that all subdirs are also protected.
mr.dwMDUserType = IIS_MD_UT_FILE; mr.dwMDDataType = DWORD_METADATA; mr.dwMDDataLen = sizeof(DWORD); mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAuthorization); // Write MD_AUTHORIZATION value
hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr ); fRet = SUCCEEDED( hr ); } } } // In the following, do the stuff that we always want to do to the virtual dir, regardless of Admin's setting.
if( fRet ) { dwAccessPerm = MD_ACCESS_READ; mr.dwMDIdentifier = MD_ACCESS_PERM; mr.dwMDAttributes = METADATA_INHERIT; // Make it inheritable so all subdirectories will have the same rights.
mr.dwMDUserType = IIS_MD_UT_FILE; mr.dwMDDataType = DWORD_METADATA; mr.dwMDDataLen = sizeof(DWORD); mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAccessPerm); // Write MD_ACCESS_PERM value
hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr ); fRet = SUCCEEDED( hr ); } if( fRet ) { PWCHAR szDefLoadFile = L"Default.htm,Default.asp"; mr.dwMDIdentifier = MD_DEFAULT_LOAD_FILE; mr.dwMDAttributes = 0; // no need for inheritence
mr.dwMDUserType = IIS_MD_UT_FILE; mr.dwMDDataType = STRING_METADATA; mr.dwMDDataLen = (wcslen(szDefLoadFile) + 1) * sizeof(WCHAR); mr.pbMDData = reinterpret_cast<unsigned char *>(szDefLoadFile); // Write MD_DEFAULT_LOAD_FILE value
hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr ); fRet = SUCCEEDED( hr ); } if( fRet ) { PWCHAR szKeyType = IIS_CLASS_WEB_VDIR_W; mr.dwMDIdentifier = MD_KEY_TYPE; mr.dwMDAttributes = 0; // no need for inheritence
mr.dwMDUserType = IIS_MD_UT_SERVER; mr.dwMDDataType = STRING_METADATA; mr.dwMDDataLen = (wcslen(szKeyType) + 1) * sizeof(WCHAR); mr.pbMDData = reinterpret_cast<unsigned char *>(szKeyType); // Write MD_DEFAULT_LOAD_FILE value
hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr ); fRet = SUCCEEDED( hr ); } pIMSAdminBase->CloseKey( hMetabase ); return fRet; }
BOOL RemoveVirtualDir( IMSAdminBase *pIMSAdminBase, WCHAR * wszVDir) { METADATA_HANDLE hMetabase = NULL; // handle to metabase
HRESULT hr; // Attempt to open the virtual dir set on Web server #1 (default server)
hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE, L"/LM/W3SVC/1/ROOT", METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, REASONABLE_TIMEOUT, &hMetabase ); if( FAILED( hr )) { return FALSE; } // We don't check the return value since the key may already
// not exist and we could get an error for that reason.
pIMSAdminBase->DeleteKey( hMetabase, wszVDir ); pIMSAdminBase->CloseKey( hMetabase ); return TRUE; }
//Check if the service "lpServiceName" exist or not
// if exist, return 0
// if not, return error code
INT CheckifServiceExist(LPCTSTR lpServiceName) { INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; if ((hScManager = OpenSCManager(NULL, NULL, GENERIC_ALL)) == NULL || (hService = OpenService(hScManager, lpServiceName, GENERIC_ALL)) == NULL) { err = GetLastError(); } if (hService) CloseServiceHandle(hService); if (hScManager) CloseServiceHandle(hScManager); return (err); }
// EOF
|