|
|
/*++
Copyright (c) 1992-1996 Microsoft Corporation
Module Name:
iisutil.c
Abstract:
IIS Resource utility routine DLL
Author:
Pete Benoit (v-pbenoi) 12-SEP-1996
Revision History:
--*/
#include "iisutil.h"
DWORD IISService[] = { INET_HTTP, INET_FTP, INET_GOPHER };
#define IIS_MNGT_DLLNAME L"infoadmn.dll"
//
// Define some globals used to get iis management routines
//
HINSTANCE iisDLL = NULL; typedef NET_API_STATUS (NET_API_FUNCTION *INETINFOGETPROC)(LPWSTR,DWORD,LPINET_INFO_CONFIG_INFO *); typedef NET_API_STATUS (NET_API_FUNCTION *INETINFOSETPROC)(LPWSTR,DWORD,LPINET_INFO_CONFIG_INFO); typedef NET_API_STATUS (NET_API_FUNCTION *INETINFOFLUSHPROC)(LPWSTR,DWORD);
INETINFOGETPROC InetInfoGet = NULL; INETINFOSETPROC InetInfoSet = NULL; INETINFOFLUSHPROC InetInfoFlushMemory = NULL;
DWORD IsIISMngtDllLoaded( ) /*++
Routine Description: Checks to see if the IIS mngt dll loaded Arguments:
Return Value: ERROR_SUCCESS - Successfully loaded and found A Win32 error code on failure.
--*/
{ if (iisDLL != NULL) { return(ERROR_SUCCESS); } return(ERROR_SERVICE_NOT_ACTIVE); }
DWORD IISLoadMngtDll( ) /*++
Routine Description: This routine tries to load the iis management dll. Then it attempts to find the procedures required to manage it.
Arguments:
Return Value: ERROR_SUCCESS - Successfully loaded and found A Win32 error code on failure.
--*/
{ DWORD status; //
// Try and load the IIS Mngt dll
//
iisDLL = LoadLibrary( IIS_MNGT_DLLNAME ); if (iisDLL == NULL) { return(GetLastError()); } //
// Try to locate the management routines
//
InetInfoGet = (INETINFOGETPROC)GetProcAddress(iisDLL,"InetInfoGetAdminInformation"); if (InetInfoGet == NULL) { status = GetLastError(); goto error_exit; }
InetInfoSet = (INETINFOSETPROC)GetProcAddress(iisDLL,"InetInfoSetAdminInformation"); if (InetInfoGet == NULL) { status = GetLastError(); goto error_exit; }
InetInfoFlushMemory = (INETINFOFLUSHPROC)GetProcAddress(iisDLL,"InetInfoFlushMemoryCache"); if (InetInfoFlushMemory == NULL) { status = GetLastError(); goto error_exit; } return(ERROR_SUCCESS); error_exit: IISUnloadMngtDll(); return(status);
} // END IsIISInstalled
VOID IISUnloadMngtDll( )
/*++
Routine Description: This routine frees the IIS management DLL
Arguments:
Return Value:
--*/ { if (iisDLL != NULL) { FreeLibrary( iisDLL); }
iisDLL = NULL; InetInfoGet = NULL; InetInfoSet = NULL; InetInfoFlushMemory = NULL; }
DWORD GetIISInfo( IN DWORD ServiceType, OUT LPINET_INFO_CONFIG_INFO *IISInfo )
/*++
Routine Description:
Get IIS information. This call returns a pointer to an INET_INFO_CONFIG_INFO structure
Arguments:
ServiceType - The type of service
IISInfo - return a pointer to an INET_INFO_CONFIG_INFO structure. This structure contains the virtual root information
Return Value:
NET_API_STATUS
--*/
{ DWORD Status; if (InetInfoGet == NULL) { return(ERROR_SERVICE_NOT_ACTIVE); } Status=InetInfoGet(NULL,IISService[ServiceType],IISInfo); return(Status);
} // END GetIISInfo
DWORD SetIISInfo( IN DWORD ServiceType, IN LPINET_INFO_CONFIG_INFO IISInfo )
/*++
Routine Description:
Set IIS information. This call sets inet config infor using the INET_INFO_CONFIG_INFO structure
Arguments:
ServiceType - The type of service
IISInfo - pointer to an INET_INFO_CONFIG_INFO structure. This structure contains the virtual root information
Return Value:
ERROR_SUCCESS NET ERROR Status
--*/
{ DWORD Status;
if ((InetInfoSet == NULL) || (InetInfoFlushMemory == NULL)) { return(ERROR_SERVICE_NOT_ACTIVE); } //
// Only set the VirtualRoots
//
IISInfo->FieldControl = FC_INET_INFO_VIRTUAL_ROOTS;
Status=InetInfoSet(NULL,IISService[ServiceType],IISInfo);
if (Status != ERROR_SUCCESS) { return(Status); }
//
// If we sucessfully set the virtual root information
// flush the memory cache
//
Status = InetInfoFlushMemory(NULL,IISService[ServiceType]);
return(Status);
} // END SetIISInfo
DWORD OffLineVirtualRoot( IN LPIIS_RESOURCE ResourceEntry, IN PLOG_EVENT_ROUTINE LogEvent )
/*++
Routine Description:
Take offline all Virtual Roots for this resource
Arguments:
ResourceEntry - The resource that contains a list of virtual roots
Return Value:
ERROR_SUCCESS W32 error code
--*/
{
LPINET_INFO_CONFIG_INFO IISInfo = NULL; LPINET_INFO_VIRTUAL_ROOT_LIST tmpVRL = NULL; LPINET_INFO_VIRTUAL_ROOT_LIST iisVRL = NULL; LPINET_INFO_VIRTUAL_ROOT_ENTRY resVR = NULL; DWORD Status = ERROR_SUCCESS; DWORD i,c; BOOLEAN MatchFound; DWORD MatchingEntries = 0;
//
// Call IIS Management API to GET list of Virtual Roots
//
Status = GetIISInfo(ResourceEntry->ServiceType, &IISInfo); if (Status != ERROR_SUCCESS) { goto error_exit; }
//
// For Robustness check to see if the IIS returned SUCCESS but
// did not return a valid address
//
if (IISInfo == NULL) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Error [OffLineVirtualRoots] Get IIS information returned NULL\n"); Status = ERROR_RESOURCE_NOT_FOUND; goto error_exit; }
//
// Save pointer to original VirtualRoot Structure
//
iisVRL = IISInfo->VirtualRoots; resVR = ResourceEntry->VirtualRoot;
//
// If the caller called terminate after open BUT before online
// the VR field of the resource could be NULL. Return so we don't accvio
//
if (resVR == NULL) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Error [OffLineVirtualRoots] Resource VR information is NULL\n"); Status = ERROR_RESOURCE_NOT_FOUND; goto error_exit; } //
// This is a sanity check
//
if ( (resVR->pszRoot == NULL) || (resVR->pszAddress == NULL) || (resVR->pszDirectory == NULL) ) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Error [OffLineVirtualRoots] Resource has NULL entries for root , addr or directory\n"); Status = ERROR_RESOURCE_NOT_FOUND; goto error_exit; } //
// Allocate storage to Filter out Virtual Roots managed by the Cluster
//
tmpVRL = LocalAlloc(LPTR, ( (iisVRL->cEntries + 1) * sizeof(INET_INFO_VIRTUAL_ROOT_ENTRY) ) + sizeof(INET_INFO_VIRTUAL_ROOT_LIST)); //
// Check to see we got a valid address
//
if (tmpVRL == NULL) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Error [OffLineVirtualRoots] Allocation of TMP VR failed\n"); Status = ERROR_RESOURCE_NOT_FOUND; goto error_exit; }
//
// This is so ugly ...
// 1. Enumerate and compare each IIS VR KEY with the resource VR
// 2. Add ones that don't match to the tmpVR
// 3. Use the tmpVR to update the IIS service and mask resources entries
tmpVRL->cEntries = 0; for (i=0;i<iisVRL->cEntries ;i++ ) { MatchFound = FALSE;
if ( (_wcsicmp(iisVRL->aVirtRootEntry[i].pszRoot,resVR->pszRoot) == 0) && (_wcsicmp(iisVRL->aVirtRootEntry[i].pszAddress,resVR->pszAddress) == 0) // (_wcsicmp(iisVRL->aVirtRootEntry[i].pszDirectory,resVR->pszDirectory) == 0)
){ // if all the VR primary keys match then skip this entry
MatchFound = TRUE; MatchingEntries +=1; } // END if
// No matching entry found in the Cluster config data so this VR is ok
if (!MatchFound) { tmpVRL->aVirtRootEntry[tmpVRL->cEntries++] = iisVRL->aVirtRootEntry[i]; } // END if !MatchFound
} // END for i=0
IISInfo->VirtualRoots = tmpVRL; //
// Call IIS Management API to SET list of Virtual Roots
// But only call this if we have something to remove
//
if (MatchingEntries > 0) { Status = SetIISInfo(ResourceEntry->ServiceType, IISInfo); }
// Destruct any temporary storage
IISInfo->VirtualRoots = iisVRL;
error_exit: if (IISInfo != NULL) MIDL_user_free((LPVOID)IISInfo); if (tmpVRL != NULL) LocalFree(tmpVRL);
return(Status); } //OfflineVirtualRoot
DWORD OnLineVirtualRoot( IN LPIIS_RESOURCE ResourceEntry, IN PLOG_EVENT_ROUTINE LogEvent )
/*++
Routine Description:
Add this resources Virtual Root to the IIS
Arguments:
ResourceEntry - The resource that contains a list of virtual roots
Return Value:
ERROR_SUCCESS W32 error code
--*/ {
LPINET_INFO_CONFIG_INFO IISInfo = NULL; LPINET_INFO_VIRTUAL_ROOT_LIST tmpVRL = NULL; LPINET_INFO_VIRTUAL_ROOT_LIST iisVRL = NULL; LPINET_INFO_VIRTUAL_ROOT_ENTRY resVR = NULL; DWORD Status = ERROR_SUCCESS; DWORD i,c; BOOLEAN MatchFound;
// Call IIS Management API to GET list of Virtual Roots
Status = GetIISInfo(ResourceEntry->ServiceType, &IISInfo); if (Status != ERROR_SUCCESS) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Error [OnLineVirtualRoots] Get IIS information call failed status = %1!u! \n", Status); goto error_exit; }
// Save pointer to original VirtualRoot Structure
iisVRL = IISInfo->VirtualRoots; resVR = ResourceEntry->VirtualRoot;
// Add Virtual Roots managed by the resource
if (resVR == NULL) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Error [OnLineVirtualRoots] NULL virtual root entry \n"); Status = ERROR_RESOURCE_NOT_FOUND; goto error_exit; }
//
// See if the resource is already on line. In which
// case this is a duplicate
//
if ( VerifyIISService( ResourceEntry,FALSE,LogEvent ) ) { // We found a duplicate or this resource is already online
(LogEvent)( ResourceEntry->ResourceHandle, LOG_INFORMATION, L"Warning [OnLineThread] Resource already online or is a duplicate. Check for Unique Alias property\n"); // Status = ERROR_DUP_NAME;
Status = ERROR_SUCCESS; goto error_exit; }
#if DBG
(LogEvent)( ResourceEntry->ResourceHandle, LOG_INFORMATION, L"[OnLineVirtualRoots] about to set info Root = %1!ws! ip = %2!ws! Dir = %3!ws! Mask = %4!u! Name = %5!ws! Pass = %6!ws! \n", resVR->pszRoot, resVR->pszAddress, resVR->pszDirectory, resVR->dwMask, resVR->pszAccountName, resVR->AccountPassword); #endif
// Allocate temporary storage for cluster and iis vr entries
tmpVRL = LocalAlloc(LPTR, ((iisVRL->cEntries + 1) * sizeof(INET_INFO_VIRTUAL_ROOT_ENTRY) ) + sizeof(INET_INFO_VIRTUAL_ROOT_LIST)); // Make sure we didn't fail on the allocate
if (tmpVRL == NULL){ (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"[OnLineVirtualRoots] LocalAlloc for temp VRL failed\n"); Status = ERROR_RESOURCE_NOT_FOUND; goto error_exit; }
tmpVRL->aVirtRootEntry[0] = *resVR;
// Add any additional VR not managed by the cluster
for (i=0;i<iisVRL->cEntries ;i++ ) { tmpVRL->aVirtRootEntry[i+1] = iisVRL->aVirtRootEntry[i]; }
tmpVRL->cEntries = iisVRL->cEntries + 1;
IISInfo->VirtualRoots = tmpVRL; #if DBG
for (i=0;i < tmpVRL->cEntries ;i++ ) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_INFORMATION, L"[OnLineVirtualRoots] about to set info Root = %1!ws! Ipaddr = %2!ws! Dir = %3!ws! Mask = %4!u! Name = %5!ws! Pass = %6!ws! \n", tmpVRL->aVirtRootEntry[i].pszRoot, tmpVRL->aVirtRootEntry[i].pszAddress, tmpVRL->aVirtRootEntry[i].pszDirectory, tmpVRL->aVirtRootEntry[i].dwMask, tmpVRL->aVirtRootEntry[i].pszAccountName, tmpVRL->aVirtRootEntry[i].AccountPassword); } #endif
// Call IIS Management API to SET list of Virtual Roots
Status = SetIISInfo(ResourceEntry->ServiceType, IISInfo); if (Status != ERROR_SUCCESS) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"[OnLineVirtualRoots] set info status = %1!u!\n", Status); } else {
//
// See if root came on line sucessfully
//
if ( !VerifyIISService( ResourceEntry,FALSE,LogEvent ) ) { //
// The root was sucessfully added to iis but the iis could
// not access the root. Remove it here so the inet manager does
// not contain bad roots
//
OffLineVirtualRoot( ResourceEntry, LogEvent);
(LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"ERROR [OnLineThread] IIS could not bring resource online. Verify IIS root is accessable. \n"); Status = ERROR_RESOURCE_NOT_AVAILABLE;
} // if !VerifyIISService
} // if status != ERROR_SUCCESS
// Destruct any temporary storage
IISInfo->VirtualRoots = iisVRL; error_exit: if (IISInfo != NULL) MIDL_user_free((LPVOID)IISInfo); if (tmpVRL != NULL) LocalFree(tmpVRL);
return(Status);
} // END OnLineVirtualRoot
VOID FreeIISResource( IN LPIIS_RESOURCE ResourceEntry )
/*++
Routine Description:
Free all the storage for a IIS_RESOURCE
Arguments:
vr - virtual root to free
Return Value:
NONE
--*/
{ if (ResourceEntry != NULL) {
if (ResourceEntry->ParametersKey != NULL ) { ClusterRegCloseKey( ResourceEntry->ParametersKey ); }
if (ResourceEntry->hResource != NULL ) { CloseClusterResource( ResourceEntry->hResource ); } LocalFree( ResourceEntry->Params.ServiceName ); LocalFree( ResourceEntry->Params.Alias ); LocalFree( ResourceEntry->Params.Directory );
if (ResourceEntry->VirtualRoot != NULL) { DestructVR(ResourceEntry->VirtualRoot); } } // ResourceEntry != NULL
} // FreeIISResource
VOID DestructIISResource( IN LPIIS_RESOURCE ResourceEntry )
/*++
Routine Description:
Free all the storage for a ResourceEntry and the ResourceEntry
Arguments:
vr - virtual root to free
Return Value:
NONE
--*/ { if (ResourceEntry != NULL) { FreeIISResource(ResourceEntry), LocalFree(ResourceEntry); } // ResourceEntry != NULL
} // DestructIISResource
VOID FreeVR( IN LPINET_INFO_VIRTUAL_ROOT_ENTRY vr )
/*++
Routine Description:
Free all the storage for a Virtual Root
Arguments:
vr - virtual root to free
Return Value:
NONE
--*/
{
if (vr == NULL) { return; } if (vr->pszRoot != NULL) { LocalFree(vr->pszRoot); } if (vr->pszAddress != NULL) { LocalFree(vr->pszAddress); } if (vr->pszDirectory != NULL) { LocalFree(vr->pszDirectory); } if (vr->pszAccountName != NULL) { LocalFree(vr->pszAccountName); }
}// FreeVR
VOID DestructVR( LPINET_INFO_VIRTUAL_ROOT_ENTRY vr )
/*++
Routine Description:
Free all the storage for a Virtual Root and vr
Arguments:
vr - virtual root to free
Return Value:
NONE
--*/
{
if (vr == NULL) { return; } FreeVR(vr); LocalFree(vr);
}// DestructVR
BOOL VerifyIISService( IN LPIIS_RESOURCE ResourceEntry, IN BOOL IsAliveFlag, IN PLOG_EVENT_ROUTINE LogEvent )
/*++
Routine Description:
Verify that the IIS service is running and that it has virtual roots contained in the resource Steps: 1. Make sure the IIS service is running by calling the mngt API 2. Verfify that the resources virtual roots are currently in the running system 3. Check the dwError field to make sure the VR for the resource is accessable 4. Sanity check to make sure the resources virtual root was found
Arguments:
Resource - supplies the resource id
IsAliveFlag - says this is an IsAlive call - used only for debug print
Return Value:
TRUE - if service is running and service contains resources virtual roots
FALSE - service is in any other state
--*/ { DWORD status; DWORD MatchingEntries = 0; DWORD VRAccessErrors = 0; BOOL MatchFound; LPINET_INFO_CONFIG_INFO IISInfo = NULL; LPINET_INFO_VIRTUAL_ROOT_ENTRY resVR = NULL; LPINET_INFO_VIRTUAL_ROOT_LIST iisVRL = NULL; DWORD c; BOOL VerifyStatus = TRUE;
//
// Get IIS virtual root information
//
status = GetIISInfo(ResourceEntry->ServiceType, &IISInfo);
//
// Check the error status to see if the service is starting
//
if (status != ERROR_SUCCESS) { if (status == ERROR_SERVICE_NOT_ACTIVE) { //
// Service is not active
//
(LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"IsAlive/LooksAlive ERROR Service NOT active service %1!ws!.\n", ResourceEntry->Params.ServiceName ); } else { //
// Some type of error
//
(LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"IsAlive/LooksAlive ERROR getting information for service %1!ws! status = %2!u!\n", ResourceEntry->Params.ServiceName, status); } //
// Return false;
//
VerifyStatus = FALSE; goto error_exit; }
iisVRL = IISInfo->VirtualRoots; resVR = ResourceEntry->VirtualRoot; //
// Now check to see if the Virtual roots for this resource exist in the service
//
MatchFound = FALSE; for (c=0;c<iisVRL->cEntries ;c++ ) { if ( (_wcsicmp(resVR->pszRoot,iisVRL->aVirtRootEntry[c].pszRoot) == 0) && (_wcsicmp(resVR->pszAddress,iisVRL->aVirtRootEntry[c].pszAddress) == 0) /// (_wcsicmp(resVR->pszDirectory,iisVRL->aVirtRootEntry[c].pszDirectory) == 0)
){ //
// if all the VR primary keys match
//
MatchFound = TRUE; MatchingEntries +=1; //
// See if the IIS can sucessfully access this virtual root
//
if (iisVRL->aVirtRootEntry[c].dwError != ERROR_SUCCESS) { VRAccessErrors +=1; (LogEvent)( ResourceEntry->ResourceHandle, LOG_INFORMATION, L"IsAlive/LooksAlive virtual root %1!ws! IIS Access Error service %2!ws! error = %3!u!\n", resVR->pszRoot, ResourceEntry->Params.ServiceName, iisVRL->aVirtRootEntry[c].dwError);
} // END dwERROR != ERROR_SUCCESS
break;
} // END if
} // END for c=0
// No matching entry found in the Cluster config data so this VR is ok
if (!MatchFound) { if (IsAliveFlag) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"ERROR IsAlive/LooksAlive virtual root %1!ws! not found for service %2!ws!\n", resVR->pszRoot, ResourceEntry->Params.ServiceName, status); } VerifyStatus = FALSE; goto error_exit; } // END if !MatchFound
//
// Perform sanity check
//
if (MatchingEntries != 1) { (LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"ERROR IsAlive/LooksAlive more than one resource is active, service %1!ws!\n", ResourceEntry->Params.ServiceName); VerifyStatus = FALSE; goto error_exit; }
//
// If the resources virtual root is inaccessable then the resource is offline
//
if (VRAccessErrors != 0) { VerifyStatus = FALSE; }
error_exit: if (IISInfo != NULL) MIDL_user_free((LPVOID)IISInfo); return(VerifyStatus);
} // VerifyIISService
|