⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hotswap.cpp

📁 Vc.Net入门与提高源码
💻 CPP
字号:
// hotswap.cpp : Defines the entry point for the DLL application.
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Classes Reference and related electronic
// documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft C++ Libraries products.

#include "stdafx.h"
// For custom assert and trace handling with WebDbg.exe
#ifdef _DEBUG
CDebugReportHook g_ReportHook;
#endif

[ module(name="hotswap", type="dll") ];
[ emitidl(restricted) ];

// This interface is implemented by our extension class and provided to 
// request handlers via IServiceProvider. A request handler can use this 
// interface to stop and resume request handling by the extension.
__interface __declspec(uuid("D11BEC99-9280-430d-94D1-DEBF555E3272"))
IHotSwapExtension : public IUnknown
{
	virtual HRESULT StopRequests() = 0;
	virtual HRESULT ResumeRequests() = 0;
	virtual HRESULT IsRunning(BOOL *pbRunning) = 0;
	virtual HRESULT FlushCaches() = 0;
};

// **********************WARNING************************************
// **********************WARNING************************************
// **********************WARNING************************************
// **********************WARNING************************************
// **********************WARNING************************************
// **********************WARNING************************************
// **********************WARNING************************************
// This is the request handler for HotSwapAdmin.srf. Please note that
// this is just a sample of how you could use a request handler to block
// requests while files are copied. The request handler coded as it is now,
// could really pose a security risk to your site because a caller 
// could block request handling on your site indefinately. You must 
// implement your own security for your request handler so that random 
// callers can't access this code.
[request_handler("admin")]
class CAdmin
{
public:
	CComPtr<IHotSwapExtension> m_spHSE;
	CString m_strErrMessage;

	HTTP_CODE ValidateAndExchange()
	{
		m_spServiceProvider->QueryService(__uuidof(IHotSwapExtension), 
						__uuidof(IHotSwapExtension), (void **) &m_spHSE);

		if (!m_spHSE)
		{
			// No hotswap service. Return message and we're done.
			m_strErrMessage = "<h1>Hot swap capability not supported!</h1>";
		}

		LPCSTR szCommand = m_HttpRequest.FormVars.Lookup("command");
		if (szCommand)
		{
			if (!stricmp(szCommand, "start"))
			{
				m_spHSE->ResumeRequests();
			}
			else if (!strcmp(szCommand, "swap"))
			{
				LPCSTR szReplaceFile = NULL;
				LPCSTR szWithFile = NULL;
				DWORD dwErr = VALIDATION_E_FAIL;
				
				// find out which file needs to be replaced
				if (VALIDATION_S_OK != m_HttpRequest.FormVars.Validate(
					"replace_file", &szReplaceFile, 1, MAX_PATH))
					m_strErrMessage = _T("Error: replace_file parameter is not valid");
				else if (VALIDATION_S_OK != m_HttpRequest.FormVars.Validate(
					"with_file", &szWithFile, 1, MAX_PATH))
					m_strErrMessage = _T("Error: with_file parameter is not valid");
				else
				{
					// block requests
					if (S_OK == m_spHSE->StopRequests())
					{
						// flush the DLL cache
						if (S_OK == m_spHSE->FlushCaches())
						{
							// It's all good so far, replace the file
							LPCTSTR szr = CA2T(szReplaceFile);
							LPCTSTR szw = CA2T(szWithFile);

							if (!CopyFile(szw, szr, FALSE))
							{
								DWORD dwLastErr = GetLastError();
								m_strErrMessage.Format(_T("Error: replacing file %s with %s failed. Last error was 0x%0.8x."),
										szr, szw, dwLastErr);
							}
							else
								m_strErrMessage.Format(_T("Success: replaced file %s with file %s"),
											szr, szw);
						}
					}
				}
				// resume requests
				m_spHSE->ResumeRequests();
			}
		}
		return HTTP_SUCCESS;
	}

	[tag_name("IsRunning")]
	HTTP_CODE OnIsRunning()
	{
		BOOL bRunning;
		m_spHSE->IsRunning(&bRunning);
		return bRunning ? HTTP_SUCCESS : HTTP_S_FALSE;
	}

	[tag_name("ErrorMessage")]
	HTTP_CODE OnGetErrorMessage()
	{
		m_HttpResponse << m_strErrMessage;
		return HTTP_SUCCESS;
	}
};

class CSwapExtension : 
	public CIsapiExtension<>,
	public IHotSwapExtension
{
	typedef CIsapiExtension<> baseClass;
	HANDLE m_hGoEvent;
	HANDLE m_hDoneEvent;
	LONG m_lActiveThreads;
	BOOL m_bRunning;

public:

	// IHotSwapExtension methods

	// Sets the event that will block all threads in DispatchStencilCall
	// then waits for all of the currently active threads to complete their
	// processing.
	HRESULT StopRequests()
	{
		ResetEvent(m_hGoEvent);

		while (InterlockedCompareExchange(&m_lActiveThreads, 1, 1) > 1)
		{
			WaitForSingleObject(m_hDoneEvent, INFINITE);
			ResetEvent(m_hDoneEvent);
		}
		m_bRunning = FALSE;
		return S_OK;
	}

	// resumes request processing.
	HRESULT ResumeRequests()
	{
		m_bRunning = TRUE;
		SetEvent(m_hGoEvent);
		return S_OK;
	}

	HRESULT IsRunning(BOOL *pbRunning)
	{
		*pbRunning = m_bRunning;
		return S_OK;
	}

	// This is the function that actually unloads the caches.
	// We call m_DllCache.Flush twice on purpose because of the
	// mechanics of the DLL cache.
	HRESULT FlushCaches()
	{
		m_StencilCache.RemoveAllStencils();
	    m_DllCache.Flush();
		m_DllCache.Flush();
		return S_OK;
	}

	// Base class overrides

	// DispatchStencilCall is the function called by threads in the ISAPI extension's
	// thread pool right after they de-queue a request from the pool. Basically, it's
	// the main entry point for all ATLS requests. We will block here on m_hGoEvent until
	// the copy of the files is done. One of the threads in the pool is currently working
	// on the swapping, and will reset the event when it's done.
	BOOL DispatchStencilCall(AtlServerRequest *pRequestInfo) throw()
	{
		// While m_hGoEvent is non-signaled, no requests will be dispatched!
		WaitForSingleObject(m_hGoEvent, INFINITE);
		InterlockedIncrement(&m_lActiveThreads);
		BOOL bRet = baseClass::DispatchStencilCall(pRequestInfo);
		if (InterlockedDecrement(&m_lActiveThreads)==1)
			SetEvent(m_hDoneEvent);
		return bRet;
	}

	// This is the entry point that IIS calls right after it 
	// does a LoadLibrary on our DLL. This is always a good place
	// to do extension specific initializations.
	BOOL GetExtensionVersion(HSE_VERSION_INFO* pVer)
	{
		m_hGoEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
		m_hDoneEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
		m_lActiveThreads = 0;
		m_bRunning = TRUE;

		if (!baseClass::GetExtensionVersion(pVer))
			return FALSE;

		return TRUE;
	}

	// This is the last function IIS calls before it unloads 
	// us. Always a good place to do extension specific un-initialization.
	BOOL TerminateExtension(DWORD dwFlags)
	{
		CloseHandle(m_hGoEvent);
		CloseHandle(m_hDoneEvent);
		return baseClass::TerminateExtension(dwFlags);
	}


	// Override this function to expose the HotSwap service that is implemented by
	// this class (see IHotSwapExtension interface above).
	HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService,	REFIID riid,
		void **ppvObject)
	{
		
		HRESULT hr = baseClass::QueryService(guidService, riid, ppvObject);
		if (hr == E_POINTER || hr == E_NOINTERFACE)
		{
			if (InlineIsEqualGUID(guidService, __uuidof(IHotSwapExtension)))
				hr =  QueryInterface(riid, ppvObject);
		}
		return hr;
	}

	// The rest of this class is just standard IUnknown requirements
	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv) throw()
	{
		if (!ppv)
			return E_POINTER;

		if (InlineIsEqualGUID(riid, __uuidof(IHotSwapExtension)))
		{
			*ppv = static_cast<IUnknown*>(static_cast<IHotSwapExtension*>(this));
			AddRef();
			return S_OK;
		}
		return baseClass::QueryInterface(riid, ppv);
	}

	ULONG STDMETHODCALLTYPE AddRef()
	{
		return baseClass::AddRef();
	}

	ULONG STDMETHODCALLTYPE Release()
	{
		return baseClass::Release();
	}

};

// the one and only isapi extension handler!
CSwapExtension theExtension;


// Delegate ISAPI exports to theExtension
//
extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
{
	return theExtension.HttpExtensionProc(lpECB);
}

extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)
{
	return theExtension.GetExtensionVersion(pVer);
}

extern "C" BOOL WINAPI TerminateExtension(DWORD dwFlags)
{
	return theExtension.TerminateExtension(dwFlags);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -