IHttpTokenEntry::GetPrimaryToken 메서드
요청을 처리하는 프로세스의 기본 토큰을 반환합니다.
구문
virtual HANDLE GetPrimaryToken(
VOID
) = 0;
매개 변수
이 메서드는 매개 변수를 사용하지 않습니다.
반환 값
HANDLE
요청을 처리하는 프로세스에 대한 가장 토큰을 나타내는 입니다. NULL일 수 있습니다.
설명
기본 토큰은 요청을 처리하는 프로세스와 연결된 사용자 계정의 보안 컨텍스트를 정의하는 핸들입니다. 이 토큰은 프로세스에 대한 액세스 규칙에 따라 시스템 리소스에 대한 액세스를 제한합니다.
GL_CACHE_OPERATION 이벤트에 등록하는 CGlobalModule 파생 클래스는 CGlobalModule::OnGlobalCacheOperationvirtual
메서드의 매개 변수로 ICacheProvider 포인터를 받습니다. ICacheProvider::GetCacheRecord 메서드를 호출하여 IHttpCacheSpecificData 포인터를 검색할 수 있으며, 경우에 따라 이 IHttpCacheSpecificData
포인터를 IHttpTokenEntry 포인터로 다운캐스트할 수 있습니다. 그런 다음 메서드를 호출하여 기본 토큰 핸들을 검색할 GetPrimaryToken
수 있습니다.
다운캐스트 규칙에 대한 자세한 내용은 ICacheProvider::GetCacheRecord를 참조하세요.
구현자에 대한 참고 사항
IHttpTokenEntry
구현자는 이 데이터를 사용하여 리소스 관리를 담당합니다. 따라서 IHttpTokenEntry
구현자는 더 이상 필요하지 않은 경우 핸들에서 CloseHandle 을 호출해야 합니다.
호출자 참고 사항
IHttpTokenEntry
구현자는 이 데이터를 사용하여 리소스 관리를 담당합니다. 따라서 IHttpTokenEntry
클라이언트는 이 데이터가 더 이상 필요하지 않을 때 반환된 핸들에서 를 호출 CloseHandle
해서는 안 됩니다. 또한 액세스 위반이 throw되거나 데이터가 무효화되므로 클라이언트는 이 핸들이 참조하는 메모리의 상태를 변경해서는 안 됩니다.
예제
다음 코드 예제에서는 이벤트를 수신 대기 GL_CACHE_OPERATION
하고 GL_CACHE_CLEANUP 다음 이벤트 뷰어 정보를 쓰는 전역 모듈을 만드는 방법을 보여 줍니다IHttpTokenEntry
.
주의
IIS 7은 이벤트 뷰어 많은 수의 이벤트를 생성합니다. 프로덕션 환경에서 로그 오버플로 오류를 방지하려면 일반적으로 이벤트 로그에 캐시 정보를 쓰지 않아야 합니다. 데모를 위해 이 코드 예제에서는 디버그 모드에서만 이벤트 뷰어 항목을 씁니다.
#pragma warning( disable : 4290 )
#pragma warning( disable : 4530 )
#define _WINSOCKAPI_
#include <windows.h>
#include <sal.h>
#include <tchar.h>
#include <initguid.h>
#include <httptrace.h>
#include <httpserv.h>
#include <httpcach.h>
#include <string>
using namespace std;
// The CConvert class mirrors the Convert class that is
// defined in the .NET Framework. It converts primitives
// and other data types to wstring types.
class CConvert
{
public:
// The ToString method converts a HANDLE to a wstring.
// h: the HANDLE to convert to a wstring.
// return: the HANDLE as a wstring.
static wstring ToString(HANDLE h)
{
// If the HANDLE is NULL, return the "NULL" string.
if (NULL == h)
{
return L"NULL";
}
// If the HANDLE is not valid, return
// the INVALID_HANDLE_VALUE as a string.
if (INVALID_HANDLE_VALUE == h)
{
return L"INVALID_HANDLE_VALUE";
}
// The HANDLE is valid.
return L"valid";
}
// The ToByteString converts a double-byte
// character string to a single-byte string.
// str: the double-byte string to convert.
// return: a single-byte string copied from str.
static string ToByteString(const wstring& str)
{
// Get the length of the
// double-byte string.
size_t length = str.length();
// Create a temporary char pointer.
char* byteChar = new char[length+1];
byteChar[0] = '\0';
// Copy the double-byte character string
// into the single-byte string.
size_t charsReturned = 0;
wcstombs_s(&charsReturned, byteChar,
length+1, str.c_str(), length+1);
// Create a string to return.
string retString = byteChar;
// Delete the temporary string and
// set that string to NULL.
delete[] byteChar;
byteChar = NULL;
// Return the single-byte string.
return retString;
}
};
// The CEventException class is
// an exception that can be thrown
// when writing an event fails.
class CEventException
{
public:
// Creates the CEventException class.
// str: the wstring that could
// not be written to a log.
CEventException(const wstring& str)
: m_string(str)
{
}
// Creates the destructor for
// the CEventException class.
virtual ~CEventException()
{
}
private:
// Specify the wstring that could
// not be written to an event viewer.
wstring m_string;
};
// The CEventWriter class writes XML
// documents and strings to the event log.
class CEventWriter
{
public:
// Creates the CEventWriter class.
// name: the name of the
// event log to open.
CEventWriter(const wstring& name)
{
#ifdef UNICODE
m_eventLog = RegisterEventSource(NULL, name.c_str());
#else
string multiName = CConvert::ToByteString(name);
m_eventLog = RegisterEventSource(NULL, multiName.c_str());
#endif
}
// Creates the destructor for the
// CEventWriter class. This destructor
// closes the HANDLE to the event
// log if that HANDLE is open.
virtual ~CEventWriter()
{
// If the HANDLE to the event
// log is open, close it.
if (NULL != m_eventLog)
{
// Deregister the event log HANDLE.
DeregisterEventSource(m_eventLog);
// Set the HANDLE to NULL.
m_eventLog = NULL;
}
}
// The ReportInfo method writes
// a wstring to the event log.
// info: the wstring to write.
// return: true if the event log is written.
BOOL ReportInfo(const wstring& info)
{
return ReportEvent(EVENTLOG_INFORMATION_TYPE, info);
}
protected:
// The ReportEvent method accepts an event type
// and a wstring, and attempts to write that
// event to the event log.
// type: the type of the event.
// data: the wstring to write to the event log.
// return: true if the event log is written;
// otherwise, false.
BOOL ReportEvent(WORD type, const wstring& data)
{
// If the m_eventLog HANDLE
// is NULL, return false.
if (NULL == m_eventLog)
{
return FALSE;
}
#ifndef _DEBUG
// If the current build is not debug,
// return so the event log is not written.
return TRUE;
#endif
#ifdef UNICODE
// The unicode version of the ReportEvent
// method requires double-byte strings.
PCWSTR arr[1];
arr[0] = data.c_str();
return ::ReportEvent(m_eventLog,
type,
0, 0, NULL, 1,
0, arr, (void*)arr);
#else
// The non-unicode version of the ReportEvent
// method requires single-byte strings.
string multiByte =
CConvert::ToByteString(data);
LPCSTR arr[1];
arr[0] = multiByte.c_str();
return ::ReportEvent(m_eventLog,
type,
0, 0, NULL, 1,
0, arr, (void*)arr);
#endif
}
private:
// Specify the HANDLE to the
// event log for writing.
HANDLE m_eventLog;
};
// The CGlobalCacheModule class creates the CGlobalModule
// class and registers for GL_CACHE_OPERATION and
// GL_CACHE_CLEANUP events.
class CGlobalCacheModule : public CGlobalModule
{
public:
// Creates the destructor for the
// CGlobalCacheModule class.
virtual ~CGlobalCacheModule()
{
}
// The RegisterGlobalModule method creates and registers
// a new CGlobalCacheModule for GL_CACHE_OPERATION and
// GL_CACHE_CLEANUP events.
// dwServerVersion: the current server version.
// pModuleInfo: the current IHttpModuleRegistrationInfo pointer.
// pGlobalInfo: the current IHttpServer pointer.
// return: ERROR_NOT_ENOUGH_MEMORY if the heap is out of
// memory; otherwise, the value from the call to the
// SetGlobalNotifications method on the pModuleInfo pointer.
static HRESULT RegisterGlobalModule
(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo* pModuleInfo,
IHttpServer* pGlobalInfo
)
{
// The pGlobalInfo parmeter must be non-NULL because
// the constructor for the CGlobalCacheModule class
// requires a non-NULL pointer to a valid IHttpServer
// pointer.
if (NULL == pGlobalInfo)
{
return E_INVALIDARG;
}
// Create a new CGlobalCacheModule pointer.
CGlobalCacheModule* traceModule =
new CGlobalCacheModule();
// Return an out-of-memory error if the traceModule
// is NULL after the call to the new operator.
if (NULL == traceModule)
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
// Attempt to set global notification for both
// GL_CACHE_OPERATION and GL_CACHE_CLEANUP events
// by using the traceModule as a listener.
HRESULT hr = pModuleInfo->SetGlobalNotifications
(traceModule, GL_CACHE_OPERATION | GL_CACHE_CLEANUP);
// If the SetGlobalNotifications method
// fails, return the HRESULT.
if (FAILED(hr))
{
return hr;
}
// Set the priority to PRIORITY_ALIAS_FIRST,
// which will populate the data as much as possible.
hr = pModuleInfo->SetPriorityForGlobalNotification(
GL_CACHE_OPERATION, PRIORITY_ALIAS_FIRST);
// Return the HRESULT from the call to
// the SetGlobalNotifications method.
return hr;
}
// The OnGlobalCacheOperation method is called
// when GL_CACHE_OPERATION operations occur.
// pProvider: the current ICacheProvider pointer.
// return: GL_NOTIFICATION_CONTINUE if the event
// log is written; otherwise, GL_NOTIFICATION_HANDLED.
virtual GLOBAL_NOTIFICATION_STATUS OnGlobalCacheOperation
(
IN ICacheProvider* pProvider
)
{
// The OnGlobalCacheOperation must return if the
// pProvider parameter is NULL because this pointer
// is needed for data to write to the event log.
if (NULL == pProvider)
{
return GL_NOTIFICATION_CONTINUE;
}
try
{
// Get the IHttpCacheSpecificData pointer
// from the ICacheProvider element.
IHttpCacheSpecificData* cacheSpecificData =
pProvider->GetCacheRecord();
// Write the IHttpCacheSpecificData
// pointer information to the event log.
Write(cacheSpecificData);
}
// A CEventException is thrown
// if any Write method cannot
// write to the event log.
catch (CEventException)
{
return GL_NOTIFICATION_HANDLED;
}
// Return GL_NOTIFICATION_CONTINUE so that
// other listeners will receive the event.
return GL_NOTIFICATION_CONTINUE;
}
// The OnGlobalCacheCleanup method is called
// when GL_CACHE_CLEANUP events occur.
// return: GL_NOTIFICATION_CONTINUE.
virtual GLOBAL_NOTIFICATION_STATUS OnGlobalCacheCleanup(VOID)
{
// Return GL_NOTIFICATION_CONTINUE so that
// other listeners will receive this event.
return GL_NOTIFICATION_CONTINUE;
}
// PRE: none.
// POST: the Terminate method calls delete on
// this, which releases the memory for the current
// CGlobalCacheModule pointer on the heap.
virtual VOID Terminate(VOID)
{
delete this;
}
protected:
// Creates the constructor for
// the CGlobalCacheModule class.
// The constructor initializes the
// private m_eventWriter to write
// to the IISADMIN event log.
CGlobalCacheModule() : m_eventWriter(L"IISADMIN")
{
}
// The ReportInfo method writes the
// formatted name and value of a method
// call to the event log.
// name: the name of the method or property.
// value: the value of the
// method or the property.
// throws: a CEventException exception.
void ReportInfo
(
const wstring& name,
const wstring& value
) throw (CEventException)
{
// Create a formatted string to
// write to the event log.
wstring infoString =
name + wstring(L": ") + value;
// Attempt to write the formatted
// string to the event log. If the
// ReportInfo method call fails,
// throw a CEventException exception.
if (!m_eventWriter.ReportInfo(infoString))
{
throw CEventException(infoString);
}
}
// The Write method writes IHttpTokenEntry
// pointer information to the event log.
// tokenEntry: the IHttpTokenEntry
// pointer to write.
// throws: a CEventException exception.
void Write
(
IHttpTokenEntry* tokenEntry
) throw (CEventException)
{
// If the tokenEntry parameter is NULL,
// throw a CEventException exception.
if (NULL == tokenEntry)
{
CEventException ce
(L"NULL IHttpTokenEntry pointer");
throw ce;
}
// Get the primary token from the
// IHttpTokenEntry pointer.
HANDLE primaryTokenHANDLE =
tokenEntry->GetPrimaryToken();
// Convert the primary
// token to a wstring.
wstring primaryToken =
CConvert::ToString(primaryTokenHANDLE);
// Write the primary token information
// to the event log.
ReportInfo(L"IHttpTokenEntry::GetPrimaryToken",
primaryToken);
}
// The Write method writes IHttpCacheSpecificData
// pointer information to the event log.
// cacheSpecificData: the IHttpCacheSpecificData
// pointer to write.
// throws: a CEventException exception.
void Write
(
IHttpCacheSpecificData* cacheSpecificData
) throw (CEventException)
{
// If the cacheSpecificData is NULL,
// return. IHttpCacheSpecificData
// pointer data is optional.
if (NULL == cacheSpecificData)
{
return;
}
// Get the IHttpCacheKey pointer from the
// IHttpCacheSpecificData pointer.
IHttpCacheKey* cacheKey =
cacheSpecificData->GetCacheKey();
// If the cacheKey is non-NULL, get its name.
// This may allow downcasting to a more specific
// IHttpCacheSpecificData pointer type.
if (NULL != cacheKey)
{
// Get the cache name from the cacheKey.
wstring cacheKeyName = cacheKey->GetCacheName();
// If the cacheKeyName is TOKEN_CACHE_NAME, the
// IHttpCacheSpecificData pointer can be
// downcast to an IHttpTokenEntry pointer.
if (TOKEN_CACHE_NAME == cacheKeyName)
{
// Attempt to cast the IHttpCacheSpecificData
// pointer to an IHttpTokenEntry pointer.
IHttpTokenEntry* tokenEntry =
dynamic_cast<IHttpTokenEntry*>(cacheSpecificData);
// Write the IHttpTokenEntry pointer
// information to the event log.
Write(tokenEntry);
}
}
}
private:
// Specify the event writer.
CEventWriter m_eventWriter;
};
// The RegisterModule method is the
// main entry point for the DLL.
// dwServerVersion: the current server version.
// pModuleInfo: the current
// IHttpModuleRegistrationInfo pointer.
// pGlobalInfo: the current IHttpServer pointer.
// return: the value returned by calling the
// CGlobalCacheModule::RegisterGlobalModule
// method.
HRESULT
__stdcall
RegisterModule(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo* pModuleInfo,
IHttpServer* pGlobalInfo
)
{
// Call the static method for initialization.
return CGlobalCacheModule::RegisterGlobalModule
(dwServerVersion,
pModuleInfo,
pGlobalInfo);
}
위의 코드는 데이터 상자에 다음과 유사한 문자열이 포함된 이벤트 뷰어 새 이벤트를 씁니다.
IHttpTokenEntry::GetPrimaryToken: valid
모듈은 RegisterModule 함수를 내보내야 합니다. 프로젝트에 대한 모듈 정의(.def) 파일을 만들어 이 함수를 내보내거나 스위치를 사용하여 /EXPORT:RegisterModule
모듈을 컴파일할 수 있습니다. 자세한 내용은 연습: 네이티브 코드를 사용하여 Request-Level HTTP 모듈 만들기를 참조하세요.
필요에 따라 각 함수에 대한 호출 규칙을 명시적으로 선언하는 대신 호출 규칙을 사용하여 __stdcall (/Gz)
코드를 컴파일할 수 있습니다.
요구 사항
형식 | Description |
---|---|
클라이언트 | - Windows Vista의 IIS 7.0 - Windows 7의 IIS 7.5 - Windows 8의 IIS 8.0 - WINDOWS 10 IIS 10.0 |
서버 | - Windows Server 2008의 IIS 7.0 - Windows Server 2008 R2의 IIS 7.5 - Windows Server 2012의 IIS 8.0 - Windows Server 2012 R2의 IIS 8.5 - WINDOWS SERVER 2016 IIS 10.0 |
제품 | - IIS 7.0, IIS 7.5, IIS 8.0, IIS 8.5, IIS 10.0 - IIS Express 7.5, IIS Express 8.0, IIS Express 10.0 |
헤더 | Httpserv.h |