/* * Copyright (c) 1998 Microsoft Corporation * * Module Name: * * licenoc.cpp * * Abstract: * * This file contains the main OC code. * * Author: * * Breen Hagan (BreenH) Oct-02-98 * * Environment: * * User Mode */ #include "stdafx.h" #include "pages.h" #include "..\common\svcrole.h" #include "upgdef.h" #include "logfile.h" /* * Constants. */ const TCHAR gszLogFile[] = _T("%SystemRoot%\\LicenOc.log"); const TCHAR *gInstallSectionNames[] = { _T("LicenseServer.Install"), _T("LicenseServer.Uninstall"), _T("LicenseServer.DoNothing") }; /* * Global variables. */ BOOL gNt4Upgrade = FALSE; BOOL gNtUpgrade; BOOL gStandAlone; BOOL gUnAttended; EnablePage *gEnableDlg = NULL; EServerType gServerRole = eEnterpriseServer; HINSTANCE ghInstance = NULL; PSETUP_INIT_COMPONENT gpInitComponentData = NULL; /* * Function prototypes. */ HINF GetComponentInfHandle(VOID); DWORD GetComponentVersion(VOID); HINSTANCE GetInstance(VOID); EInstall GetInstallSection(VOID); LPCTSTR GetInstallSectionName(VOID); BOOL GetSelectionState(UINT); EServerType GetServerRole(VOID); DWORD OnPreinitialize(UINT_PTR); DWORD OnInitComponent(PSETUP_INIT_COMPONENT); DWORD OnSetLanguage(UINT_PTR); DWORD OnQueryImage(UINT_PTR, PDWORD); DWORD OnRequestPages(WizardPagesType, PSETUP_REQUEST_PAGES); DWORD OnWizardCreated(VOID); DWORD OnQueryState(UINT_PTR); DWORD OnQueryChangeSelState(UINT_PTR, UINT); DWORD OnCalcDiskSpace(LPCTSTR, UINT_PTR, HDSKSPC); DWORD OnQueueFileOps(LPCTSTR, HSPFILEQ); DWORD OnQueryStepCount(VOID); DWORD OnAboutToCommitQueue(VOID); DWORD OnCompleteInstallation(LPCTSTR); DWORD OnCleanup(VOID); VOID SetDatabaseDirectory(LPCTSTR); DWORD SetServerRole(UINT); #define GetCurrentSelectionState() GetSelectionState(OCSELSTATETYPE_CURRENT) #define GetOriginalSelectionState() GetSelectionState(OCSELSTATETYPE_ORIGINAL) /* * Helper Functions. */ HINF GetComponentInfHandle( VOID ) { return(gpInitComponentData->ComponentInfHandle); } DWORD GetComponentVersion( VOID ) { return(OCMANAGER_VERSION); } HINSTANCE GetInstance( VOID ) { return(ghInstance); } EInstall GetInstallSection( VOID ) { BOOL fCurrentState = GetCurrentSelectionState(); BOOL fOriginalState = GetOriginalSelectionState(); // // StandAlone Setup Matrix // // Originally Selected, Currently Selected -> DoNothing // Originally Selected, Currently Unselected -> Uninstall // Originally Unselected, Currently Selected -> Install // Originally Unselected, Currently Unselected -> DoNothing // // Gui Mode / Upgrade Matrix // // Nt 4.0 any setup, Nt 5.0 w LS -> Install // Nt 4.0 any setup, Nt 5.0 w/o LS -> Uninstall // Nt 5.0 w/ LS, Nt 5.0 w/ LS -> Install // Nt 5.0 w/ LS, Nt 5.0 w/o LS -> Uninstall // Nt 5.0 w/o LS, Nt 5.0 w/ LS -> Install // Nt 5.0 w/o LS, Nt 5.0 w/o LS -> Uninstall // Win9x, Nt5.0 w/ LS -> Install // Win9x, Nt5.0 w/o LS -> Uninstall // // // If this is a TS 4 installation, fOriginalState will be false, // even though LS is installed. Handle this case first. // if (gNt4Upgrade) { if (fCurrentState) { return(kInstall); } else { return(kUninstall); } } if (gStandAlone && (fCurrentState == fOriginalState)) { return(kDoNothing); } if (fCurrentState) { return(kInstall); } else { return(kUninstall); } } LPCTSTR GetInstallSectionName( VOID ) { LOGMESSAGE( _T("GetInstallSectionName: Returned %s"), gInstallSectionNames[(INT)GetInstallSection()] ); return(gInstallSectionNames[(INT)GetInstallSection()]); } BOOL GetSelectionState( UINT StateType ) { return(gpInitComponentData->HelperRoutines.QuerySelectionState( gpInitComponentData->HelperRoutines.OcManagerContext, COMPONENT_NAME, StateType )); } EServerType GetServerRole( VOID ) { return(gServerRole); } BOOL InWin2000Domain( VOID ) { NET_API_STATUS dwErr; DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDomainInfo = NULL; PDOMAIN_CONTROLLER_INFO pdcInfo = NULL; BOOL fRet = FALSE; // // Check if we're in a workgroup // dwErr = DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *) &pDomainInfo); if ((dwErr != NO_ERROR) || (pDomainInfo == NULL)) { return FALSE; } switch (pDomainInfo->MachineRole) { case DsRole_RoleStandaloneWorkstation: case DsRole_RoleStandaloneServer: DsRoleFreeMemory(pDomainInfo); return FALSE; break; // just in case } DsRoleFreeMemory(pDomainInfo); dwErr = DsGetDcName(NULL, // Computer Name NULL, // Domain Name NULL, // Domain GUID NULL, // Site Name DS_DIRECTORY_SERVICE_PREFERRED, &pdcInfo); if ((dwErr != NO_ERROR) || (pdcInfo == NULL)) { return FALSE; } if (pdcInfo->Flags & DS_DS_FLAG) { fRet = TRUE; } NetApiBufferFree(pdcInfo); return fRet; } DWORD SetServerRole( IN UINT newType ) { switch(newType) { case ePlainServer: case eEnterpriseServer: gServerRole = (EServerType)newType; break; default: return(ERROR_INVALID_PARAMETER); } return(NO_ERROR); } /* * DllMain * * Initial entry point into the License Server OC dll. */ DWORD WINAPI DllMain( IN HINSTANCE hInstance, IN DWORD dwReason, IN LPVOID lpReserved ) { TCHAR pszLogFile[MAX_PATH + 1]; switch(dwReason) { case DLL_PROCESS_ATTACH: if (hInstance != NULL) { ghInstance = hInstance; } else { return(FALSE); } ExpandEnvironmentStrings(gszLogFile, pszLogFile, MAX_PATH); LOGINIT(pszLogFile, COMPONENT_NAME); break; case DLL_THREAD_ATTACH: break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_DETACH: break; } UNREFERENCED_PARAMETER(lpReserved); return(TRUE); } /* * EntryProc() * * Entry point into OCBase class for OCManager. */ DWORD EntryProc( IN LPCVOID ComponentId, IN LPCVOID SubcomponentId, IN UINT Function, IN UINT_PTR Param1, IN OUT PVOID Param2 ) { DWORD dwRet; switch(Function) { case OC_PREINITIALIZE: LOGMESSAGE(_T("\r\nOnPreinitialize: Entered")); dwRet = OnPreinitialize( Param1 ); LOGMESSAGE(_T("OnPreinitialize: Returned")); break; case OC_INIT_COMPONENT: LOGMESSAGE(_T("\r\nOnInitComponent: Entered")); dwRet = OnInitComponent( (PSETUP_INIT_COMPONENT)Param2 ); LOGMESSAGE(_T("OnInitComponent: Returned")); break; case OC_SET_LANGUAGE: LOGMESSAGE(_T("\r\nOnSetLanguage: Entered")); dwRet = OnSetLanguage( Param1 ); LOGMESSAGE(_T("OnSetLanguage: Returned")); break; case OC_QUERY_IMAGE: LOGMESSAGE(_T("\r\nOnQueryImage: Entered")); dwRet = OnQueryImage( Param1, (PDWORD)Param2 ); LOGMESSAGE(_T("OnQueryImage: Returned")); break; case OC_REQUEST_PAGES: LOGMESSAGE(_T("\r\nOnRequestPages: Entered")); dwRet = OnRequestPages( (WizardPagesType)Param1, (PSETUP_REQUEST_PAGES)Param2 ); LOGMESSAGE(_T("OnRequestPages: Returned")); break; case OC_WIZARD_CREATED: LOGMESSAGE(_T("\r\nOnWizardCreated: Entered")); dwRet = OnWizardCreated(); LOGMESSAGE(_T("OnWizardCreated: Returned")); break; case OC_QUERY_STATE: LOGMESSAGE(_T("\r\nOnQueryState: Entered")); dwRet = OnQueryState( Param1 ); LOGMESSAGE(_T("OnQueryState: Returned")); break; case OC_QUERY_CHANGE_SEL_STATE: LOGMESSAGE(_T("\r\nOnQueryChangeSelState: Entered")); dwRet = OnQueryChangeSelState( Param1, (UINT)((UINT_PTR)Param2) ); LOGMESSAGE(_T("OnQueryChangeSelState: Returned")); break; case OC_CALC_DISK_SPACE: LOGMESSAGE(_T("\r\nOnCalcDiskSpace: Entered")); dwRet = OnCalcDiskSpace( (LPCTSTR)SubcomponentId, Param1, (HDSKSPC)Param2 ); LOGMESSAGE(_T("OnCalcDiskSpace: Returned")); break; case OC_QUEUE_FILE_OPS: LOGMESSAGE(_T("\r\nOnQueueFileOps: Entered")); dwRet = OnQueueFileOps( (LPCTSTR)SubcomponentId, (HSPFILEQ)Param2 ); LOGMESSAGE(_T("OnQueueFileOps: Returned")); break; case OC_QUERY_STEP_COUNT: LOGMESSAGE(_T("\r\nOnQueryStepCount: Entered")); dwRet = OnQueryStepCount(); LOGMESSAGE(_T("OnQueryStepCount: Returned")); break; case OC_ABOUT_TO_COMMIT_QUEUE: LOGMESSAGE(_T("\r\nOnAboutToCommitQueue: Entered")); dwRet = OnAboutToCommitQueue(); LOGMESSAGE(_T("OnAboutToCommitQueue: Returned")); break; case OC_COMPLETE_INSTALLATION: LOGMESSAGE(_T("\r\nOnCompleteInstallation: Entered")); dwRet = OnCompleteInstallation( (LPCTSTR)SubcomponentId ); LOGMESSAGE(_T("OnCompleteInstallation: Returned")); break; case OC_CLEANUP: LOGMESSAGE(_T("\r\nOnCleanup: Entered")); dwRet = OnCleanup(); break; default: LOGMESSAGE(_T("\r\nOC Manager calling for unknown function %ld\r\n"), Function); dwRet = 0; } UNREFERENCED_PARAMETER(ComponentId); return(dwRet); } /* * OnPreinitialize() * * */ DWORD OnPreinitialize( IN UINT_PTR Flags ) { UNREFERENCED_PARAMETER(Flags); #ifdef UNICODE return(OCFLAG_UNICODE); #else return(OCFLAG_ANSI); #endif } /* * OnInitComponent() * * */ DWORD OnInitComponent( IN PSETUP_INIT_COMPONENT pSetupInitComponent ) { BOOL fErr; DWORDLONG OperationFlags; if (pSetupInitComponent == NULL) { LOGMESSAGE(_T("OnInitComponent: Passed NULL PSETUP_INIT_COMPONENT")); return(ERROR_CANCELLED); } // // Verify that the OC Manager and OC versions are compatible. // pSetupInitComponent->ComponentVersion = GetComponentVersion(); if (pSetupInitComponent->ComponentVersion > pSetupInitComponent->OCManagerVersion) { LOGMESSAGE(_T("OnInitComponent: Version mismatch.")); return(ERROR_CALL_NOT_IMPLEMENTED); } // // Copy setup data. // gpInitComponentData = (PSETUP_INIT_COMPONENT)LocalAlloc( LPTR, sizeof(SETUP_INIT_COMPONENT) ); if (gpInitComponentData == NULL) { LOGMESSAGE(_T("OnInitComponent: Can't allocate gpInitComponentData.")); return(ERROR_CANCELLED); } CopyMemory( gpInitComponentData, pSetupInitComponent, sizeof(SETUP_INIT_COMPONENT) ); // // Open Inf file. // if (GetComponentInfHandle() == NULL) { return(ERROR_CANCELLED); } fErr = SetupOpenAppendInfFile( NULL, GetComponentInfHandle(), NULL ); if (!fErr) { LOGMESSAGE(_T("OnInitComponent: SetupOpenAppendInfFile failed: %ld"), GetLastError()); return(GetLastError()); } // // Set state variables. // OperationFlags = gpInitComponentData->SetupData.OperationFlags; gStandAlone = OperationFlags & SETUPOP_STANDALONE ? TRUE : FALSE; gUnAttended = OperationFlags & SETUPOP_BATCH ? TRUE : FALSE; gNtUpgrade = OperationFlags & SETUPOP_NTUPGRADE ? TRUE : FALSE; LOGMESSAGE(_T("OnInitComponent: gStandAlone = %s"), gStandAlone ? _T("TRUE") : _T("FALSE")); LOGMESSAGE(_T("OnInitComponent: gUnAttended = %s"), gUnAttended ? _T("TRUE") : _T("FALSE")); LOGMESSAGE(_T("OnInitComponent: gNtUpgrade = %s"), gNtUpgrade ? _T("TRUE") : _T("FALSE")); // // Gather previous version's information from registry. If the role // does not exist in the registry, SetServerRole will stay with the // default, PlainServer. // SetServerRole(GetServerRoleFromRegistry()); // // Check for Nt4 Upgrade. // if (GetNT4DbConfig(NULL, NULL, NULL, NULL) == NO_ERROR) { LOGMESSAGE(_T("OnInitComponent: Nt4Upgrade")); gNt4Upgrade = TRUE; DeleteNT4ODBCDataSource(); } // // License Server will only use the directory in the registry during // an Nt5 to Nt5 upgrade or stand alone setup from Add/Remove Programs. // if (gStandAlone || (gNtUpgrade && !gNt4Upgrade)) { LPCTSTR pszDbDirFromReg = GetDatabaseDirectoryFromRegistry(); if (pszDbDirFromReg != NULL) { SetDatabaseDirectory(pszDbDirFromReg); } } return(NO_ERROR); } /* * OnSetLanguage() * * */ DWORD OnSetLanguage( IN UINT_PTR LanguageId ) { UNREFERENCED_PARAMETER(LanguageId); return((DWORD)FALSE); } /* * OnQueryImage() * * */ DWORD OnQueryImage( IN UINT_PTR SubCompEnum, IN OUT PDWORD Size ) { UNREFERENCED_PARAMETER(SubCompEnum); UNREFERENCED_PARAMETER(Size); return((DWORD)NULL); } /* * OnRequestPages() * * */ DWORD OnRequestPages( IN WizardPagesType PageTypeEnum, IN OUT PSETUP_REQUEST_PAGES pRequestPages ) { const DWORD cUiPages = 1; BOOL fErr; LOGMESSAGE(_T("OnRequestPages: Page Type %d"), PageTypeEnum); if (pRequestPages == NULL) { LOGMESSAGE(_T("OnRequestPages: pRequestPages == NULL")); return(0); } if ((!gStandAlone) || (PageTypeEnum != WizPagesEarly)) { return(0); } if (pRequestPages->MaxPages >= cUiPages) { gEnableDlg = new EnablePage; if (gEnableDlg == NULL) { goto CleanUp1; } fErr = gEnableDlg->Initialize(); if (!fErr) { goto CleanUp1; } pRequestPages->Pages[0] = CreatePropertySheetPage( (LPPROPSHEETPAGE)gEnableDlg ); if (pRequestPages->Pages[0] == NULL) { LOGMESSAGE(_T("OnRequestPages: Failed CreatePropertySheetPage!")); goto CleanUp0; } } return(cUiPages); CleanUp0: delete gEnableDlg; CleanUp1: SetLastError(ERROR_OUTOFMEMORY); LOGMESSAGE(_T("OnRequestPages: Out of Memory!")); return((DWORD)-1); } /* * OnWizardCreated() * * */ DWORD OnWizardCreated( VOID ) { return(NO_ERROR); } /* * OnQueryState() * * */ DWORD OnQueryState( IN UINT_PTR uState ) { UNREFERENCED_PARAMETER(uState); return(SubcompUseOcManagerDefault); } /* * OnQueryChangeSelState() * * */ DWORD OnQueryChangeSelState( IN UINT_PTR SelectionState, IN UINT Flags ) { BOOL fDirectSelection; BOOL fRet; BOOL fSelect; UNREFERENCED_PARAMETER(Flags); if (Flags & OCQ_ACTUAL_SELECTION) { fDirectSelection = TRUE; } else { fDirectSelection = FALSE; } fRet = TRUE; fSelect = (SelectionState != 0); if (!fSelect && fDirectSelection && GetOriginalSelectionState()) { DWORD dwStatus; HWND hWnd; int iRet; hWnd = gpInitComponentData->HelperRoutines.QueryWizardDialogHandle(gpInitComponentData->HelperRoutines.OcManagerContext); dwStatus = DisplayMessageBox( hWnd, IDS_STRING_LICENSES_GO_BYE_BYE, IDS_MAIN_TITLE, MB_YESNO, &iRet ); if (dwStatus == ERROR_SUCCESS) { fRet = (iRet == IDYES); } } return((DWORD)fRet); } /* * OnCalcDiskSpace() * * */ DWORD OnCalcDiskSpace( IN LPCTSTR SubcomponentId, IN UINT_PTR AddComponent, IN OUT HDSKSPC DiskSpaceHdr ) { BOOL fErr; LPCTSTR pSection; if ((SubcomponentId == NULL) || (SubcomponentId[0] == NULL)) { return(0); } LOGMESSAGE(_T("OnCalcDiskSpace: %s"), AddComponent ? _T("Installing") : _T("Removing")); // // There is no clear documentation on how this should work. If the // size of the installation should be visible no matter what, then // the section to install should be hardcoded, not determined by // the current state. // pSection = gInstallSectionNames[kInstall]; LOGMESSAGE(_T("OnCalcDiskSpace: Calculating for %s"), pSection); if (AddComponent != 0) { fErr = SetupAddInstallSectionToDiskSpaceList( DiskSpaceHdr, GetComponentInfHandle(), NULL, pSection, NULL, 0 ); } else { fErr = SetupRemoveInstallSectionFromDiskSpaceList( DiskSpaceHdr, GetComponentInfHandle(), NULL, pSection, NULL, 0 ); } if (fErr) { return(NO_ERROR); } else { LOGMESSAGE(_T("OnCalcDiskSpace: Error %ld"), GetLastError()); return(GetLastError()); } } /* * OnQueueFileOps() * * */ DWORD OnQueueFileOps( IN LPCTSTR SubcomponentId, IN OUT HSPFILEQ FileQueueHdr ) { BOOL fErr; DWORD dwErr; EInstall eInstallSection; LPCTSTR pSection; if ((SubcomponentId == NULL) || (SubcomponentId[0] == NULL)) { return(0); } pSection = GetInstallSectionName(); LOGMESSAGE(_T("OnQueueFileOps: Queueing %s"), pSection); // // Stop and remove the license server service, if needed. This must // be done before queueing files for deletion. // eInstallSection = GetInstallSection(); if (eInstallSection == kUninstall) { if (gServerRole == eEnterpriseServer) { if (UnpublishEnterpriseServer() != S_OK) { LOGMESSAGE( _T("OnQueueFileOps: UnpublishEnterpriseServer() failed") ); } } dwErr = ServiceDeleteFromInfSection( GetComponentInfHandle(), pSection ); if (dwErr != ERROR_SUCCESS) { LOGMESSAGE( _T("OnQueueFileOps: Error deleting service: %ld"), dwErr ); } } fErr = SetupInstallFilesFromInfSection( GetComponentInfHandle(), NULL, FileQueueHdr, pSection, NULL, eInstallSection == kUninstall ? 0 : SP_COPY_NEWER ); if (fErr) { return(NO_ERROR); } else { LOGMESSAGE(_T("OnQueueFileOps: Error %ld"), GetLastError()); return(GetLastError()); } } /* * OnQueryStepCount() * * TODO: how many steps, when should we tick? */ DWORD OnQueryStepCount( VOID ) { return(0); } /* * OnAboutToCommitQueue() * * */ DWORD OnAboutToCommitQueue( VOID ) { return(NO_ERROR); } /* * OnCompleteInstallation() * * */ DWORD OnCompleteInstallation( IN LPCTSTR SubcomponentId ) { BOOL fErr; DWORD dwErr; EInstall eInstallSection = GetInstallSection(); LPCTSTR pSection; TCHAR tchBuf[MESSAGE_SIZE] ={0}; TCHAR tchTitle[TITLE_SIZE] = {0}; if ((SubcomponentId == NULL) || (SubcomponentId[0] == NULL)) { return(NO_ERROR); } if (eInstallSection == kDoNothing) { LOGMESSAGE(_T("OnCompleteInstallation: Nothing to do")); return(NO_ERROR); } pSection = GetInstallSectionName(); // // In GUI mode setup and in unattended StandAlone setup, the wizard // page does not display, and therefore the directory is not created. // Create the default directory here. // if (eInstallSection == kInstall) { if ((!gStandAlone) || (gUnAttended)) { CreateDatabaseDirectory(); } } // // SetupAPI correctly handles installing and removing files, and // creating start menu links. // fErr = SetupInstallFromInfSection( NULL, GetComponentInfHandle(), pSection, SPINST_INIFILES | SPINST_REGISTRY | SPINST_PROFILEITEMS, NULL, NULL, 0, NULL, NULL, NULL, NULL ); if (!fErr) { LOGMESSAGE(_T("OnCompleteInstallation: InstallFromInf failed %ld"), GetLastError()); return(GetLastError()); } // // Perform installation and upgrade-specific tasks. // if (eInstallSection == kInstall) { LOGMESSAGE(_T("OnCompleteInstallation: Installing")); // // Set service settings first and install the service. // dwErr = CreateRegistrySettings(GetDatabaseDirectory(), gServerRole); if (dwErr != NO_ERROR) { LOGMESSAGE( _T("OnCompleteInstallation: CreateRegistrySettings: Error %ld"), dwErr ); return(dwErr); } fErr = SetupInstallServicesFromInfSection( GetComponentInfHandle(), pSection, 0 ); if (!fErr) { LOGMESSAGE( _T("OnCompleteInstallation: InstallServices: Error %ld"), GetLastError() ); return(GetLastError()); } if (gServerRole == eEnterpriseServer) { if (PublishEnterpriseServer() != S_OK) { LOGMESSAGE(_T("OnCompleteInstallation: PublishEnterpriseServer() failed. Setup will still complete.")); LOGMESSAGE(_T("PublishEnterpriseServer: Uninstall, try logging on as a member of the Enterprise Admins or Domain Admins group and then run setup again.")); if (!gUnAttended) { LoadString( GetInstance(), IDS_INSUFFICIENT_PERMISSION, tchBuf, sizeof(tchBuf)/sizeof(TCHAR)); LoadString( GetInstance(), IDS_MAIN_TITLE, tchTitle, sizeof(tchTitle)/sizeof(TCHAR)); MessageBox( NULL, tchBuf, tchTitle, MB_OK | MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); } } } if (gStandAlone) { dwErr = ServiceStartFromInfSection( GetComponentInfHandle(), pSection ); if (dwErr != ERROR_SUCCESS) { LOGMESSAGE( _T("OnCompleteInstallation: Error starting service: %ld"), dwErr ); return(dwErr); } } } else if (eInstallSection == kUninstall) { CleanLicenseServerSecret(); RemoveDatabaseDirectory(); RemoveRegistrySettings(); } return(NO_ERROR); } /* * OnCleanup() * * */ DWORD OnCleanup( VOID ) { if (gpInitComponentData != NULL) { LocalFree(gpInitComponentData); } if (gEnableDlg != NULL) { delete gEnableDlg; } LOGMESSAGE(_T("OnCleanup: Returned")); LOGCLOSE(); return(NO_ERROR); }