windows-nt/Source/XPSP1/NT/base/cluster/resdll/iis/iisutil.c

889 lines
21 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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