Поделиться через


Метод IHttpFileInfo::GetVrToken

Возвращает виртуальный токен для соответствующего файла.

Синтаксис

virtual HANDLE GetVrToken(  
   VOID  
) const = 0;  

Параметры

Этот метод не принимает параметров.

Возвращаемое значение

Значение HANDLE для виртуального маркера; в противном случае — ЗНАЧЕНИЕ NULL.

Комментарии

Поведение метода зависит от GetVrToken реализации. В качестве руководства следует использовать следующие сведения, но они могут быть неправильными во всех сценариях:

  • Реализующие средства, ссылающиеся на интернет-файл, возвращают допустимый HANDLE.

  • Средства реализации, ссылающиеся на файл, не относящееся к Интернету, возвращают значение NULL.

Внимание!

Так как некоторые реализующие средства возвращают значение NULL в методе GetVrToken , всегда проверяйте это условие перед использованием возвращаемого HANDLEобъекта .

Примечания для разработчиков

Разработчики IHttpFileInfo отвечают за управление ресурсами с помощью этих данных; IHttpFileInfo Поэтому разработчики должны вызывать CloseHandle для , HANDLE когда он больше не нужен.

Примечания для абонентов

IHttpFileInfo разработчики отвечают за управление ресурсами с помощью этих данных; IHttpFileInfo поэтому клиенты не должны вызывать CloseHandle возвращаемый HANDLE объект , если эти данные больше не нужны. Кроме того, клиенты не должны изменять состояние памяти, на которую ссылается данный объект HANDLE; в противном случае будет вызвано нарушение доступа или данные станут недействительными.

Пример

В следующем примере кода показано, как использовать метод IHttpContext::GetFileInfo для создания модуля HTTP, который получает указатель на интерфейс IHttpFileInfo для текущего запроса. Затем в примере вызывается GetVrToken метод для получения сведений о виртуальном маркере для запрошенного файла и отображается в веб-клиенте.

#pragma warning( disable : 4290 )
#pragma warning( disable : 4530 )

#define _WINSOCKAPI_
#include <windows.h>
#include <io.h>
#include <sal.h>
#include <httpserv.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 CResponseWriter class writes 
// text to the response stream.
class CResponseWriter
{
public:
    // Creates the CResponseWriter class.
    // response: the IHttpResponse 
    // pointer to write to.
    // throws: a _com_error exception if
    // the IHttpResponse pointer is NULL.
    CResponseWriter(IHttpResponse* response)
        throw (_com_error)
    {
        // If the response is NULL,
        // throw an exception.
        if (NULL == response)
        {
            ThrowOnFail(E_INVALIDARG);            
        }

        // Set the internal response.
        m_response = response;
    }

    // The destructor for the CResponseWriter
    // class. The CResponseWriter method 
    // sets the IHttpResponse pointer to NULL.
    virtual ~CResponseWriter()
    {
        m_response = NULL;
    }
    
    // The Write method writes the 
    // PCSTR to the response stream.
    // pszValue: the PCSTR to write.
    // throws: a _com_error if the 
    // Write method fails.
    void Write
    (
        PCSTR pszValue        
    ) throw (_com_error)
    {
        // The string must not be 
        // NULL, and its length must 
        // be greater than 0.
        if ((NULL == pszValue) || 
            (strlen(pszValue) < 1))            
        {
            // Throw an invalid argument
            // exception.
            ThrowOnFail(E_INVALIDARG);                        
        }        

        // Create a data chunk structure.
        HTTP_DATA_CHUNK dataChunk;
        // Set the chunk to a chunk in memory.
        dataChunk.DataChunkType = 
            HttpDataChunkFromMemory;

        // Set the chunk to 
        // the pszValue parameter.
        dataChunk.FromMemory.pBuffer = 
            (PVOID)pszValue;
        // Set the chunk size 
        // to the pszValue length.
        dataChunk.FromMemory.BufferLength = 
            (USHORT)strlen(pszValue);
                
        // Declare and initialize OUT 
        // parameters for the WriteEntityChunks 
        // method.
        DWORD pcbSent = 0;
        BOOL pfCompletionExpected = FALSE;

        // Write the entity chunks to
        // the response stream.
        HRESULT hr =
            m_response->WriteEntityChunks
                (&dataChunk,
                 1,
                 FALSE,
                 FALSE,
                 &pcbSent,
                 &pfCompletionExpected);

        // Throw an exception if the call
        // to WriteEntityChunks is not a 
        // success.
        ThrowOnFail(hr);        
    }
    
    // The WriteLine method writes a string
    // and newline characters to the response steam.
    // pszValue: the PCSTR string to write.
    // throws: a _com_error if the PCSTR 
    // or the newline characters are not 
    // written to the response stream.
    void WriteLine
    (
        PCSTR pszValue        
    ) throw (_com_error)
    {
        // Try to write the pszValue parameter.
        Write(pszValue);        
        
        // Try to write the newline characters.
        Write("\r\n");
    }
    
    // Convenience method that writes a name 
    // and value pair to the response stream.
    // name: the name of the parameter.
    // value: the value of the parameter.
    // throws: a _com_error exception if
    // the response stream is not written.
    void WriteLine
    (
        const wstring& name,
        const wstring& value
    ) throw (_com_error)
    {
        // Convert the UNICODE strings 
        // to mutlibyte strings.
        string nameMulti = 
            CConvert::ToByteString(name);
        string valueMulti = 
            CConvert::ToByteString(value);

        // Create the string to write.
        string writeString =
            nameMulti + 
            string(":  ") + 
            valueMulti;

        // Write the line to
        // the response stream.
        WriteLine(writeString.c_str());        
    }

    // Tests an HRESULT for success.
    // hr: the HRESULT value to inspect.
    // throws: a _com_error if the HRESULT
    // parameter is not S_OK.
    static void ThrowOnFail(HRESULT hr)
    {
        if (FAILED(hr))
        {
            _com_error ce(hr);
            throw ce;
        }
    }
private:
    // Specify the IHttpResponse
    // pointer to write to.
    IHttpResponse* m_response;
};

// The MyHttpModule class extends the CHttpModule 
// class and handles response processing.  This 
// class handles retrieving an IHttpFileInfo pointer 
// from the IHttpContext pointer during the overridden 
// OnSendResponse method, and writes the IHttpFileInfo 
// data to the response stream.
class MyHttpModule : public CHttpModule
{
public:
    // The MyHttpModule method is the public 
    // constructor for the MyHttpModule class.
    MyHttpModule()
    {

    }

    // The OnSendResponse method 
    // handles respose processing.
    // pHttpContext: an IHttpContext pointer.
    // pProvider: an ISendResponseProvider pointer.
    // return: RQ_NOTIFICATION_FINISH_REQUEST if the 
    // IHttpFileInfo pointer can be retrieved from the 
    // pHttpContext parameter; otherwise, 
    // RQ_NOTIFICATION_CONTINUE.
    REQUEST_NOTIFICATION_STATUS OnSendResponse
    (
        IN IHttpContext* pHttpContext,
        IN OUT ISendResponseProvider* pProvider
    )
    {
        // Use the UNREFERENCED_PARAMETER macro since
        // the pProvider parameter is never used.
        UNREFERENCED_PARAMETER(pProvider);

        if (NULL == pHttpContext)
        {
            return RQ_NOTIFICATION_CONTINUE;
        }

        // Get an IHttpFileInfo pointer 
        // from the IHttpContext pointer.
        IHttpFileInfo* fileInfo = 
            pHttpContext->GetFileInfo();

        // Get the IHttpResponse pointer 
        // from the IHttpContext pointer.
        IHttpResponse* response = 
            pHttpContext->GetResponse();

        // Both the IHttpFileInfo pointer
        // and IHttpResponse pointer are
        // required for processing.
        if ((NULL == fileInfo) ||
            (NULL == response))
        {
            return RQ_NOTIFICATION_CONTINUE;
        }

        // Clear the existing response stream.        
        response->Clear();

        // Set the response header to plain text.
        HRESULT hr = 
            response->SetHeader(HttpHeaderContentType, 
                                "text/plain", 
                                (USHORT)strlen("text/plain"), 
                                 TRUE);

        // If the SetHeader method fails,
        // call the SetStatus with an error code.
        if (FAILED(hr))
        {
            response->SetStatus(500, 
                                "IHttpResponse::SetHeader", 
                                0, hr);
            return RQ_NOTIFICATION_CONTINUE;
        }

        // The CResponseWriter will throw a 
        // com_exception if it cannot be created, 
        // or if the response stream cannot be written. 
        // Create a new CResponseWriter, and wrap 
        // all calls into that CResponseWriter,
        // with a try-catch statement.
        try
        {
            // Declare a writer for 
            // the response stream.
            CResponseWriter writer(response);

            // Call the GetVrToken method 
            // on the IHttpFileInfo pointer.
            HANDLE vrToken = 
                fileInfo->GetVrToken();

            // Convert the VR token to a wstring.
            wstring vrTokenString = 
                CConvert::ToString(vrToken);

            // Write the token information 
            // to the response stream.
            writer.WriteLine(L"VR Token", vrTokenString);
        }
        catch (_com_error& ce)
        {
            // Attempt to get the 
            // description of the error.
            _bstr_t description = 
                ce.Description();

            // Print the description if 
            // it is not empty.
            if (0 == description.length())
            {
                description = ce.ErrorMessage();            
            }
            
            // Set an error status on the 
            // IHttpResponse pointer.
            response->SetStatus(500, description, 0, ce.Error());            
        }

        // Return RQ_NOTIFICATION_FINISH_REQUEST, which 
        // will terminate any additional request processing.
        return RQ_NOTIFICATION_FINISH_REQUEST;
    }
protected:    
    // The MyHttpModule is the protected virtual
    // constructor for the MyHttpModule class.
    virtual ~MyHttpModule()
    {

    }
};

// The MyHttpModuleFactory class implements the IHttpModuleFactory 
// interface, and creates a new MyHttpModule pointer, where this
// MyHttpModule listens for RQ_SEND_RESPONSE events.
class MyHttpModuleFactory : public IHttpModuleFactory
{
public:
    // The RegisterGlobalModule method creates a new 
    // MyHttpModuleFactory pointer, assigns that pointer 
    // as the factory on the pModuleInfo parameter, and
    // registers for RQ_SEND_RESPONSE events.
    // dwServerVersion: the current server version.
    // pModuleInfo: the IHttpModuleRegistrationInfo 
    // used for requesting notifications.
    // pGlobalInfo: the IHttpServer pointer.
    static HRESULT RegisterGlobalModule
    (
        DWORD dwServerVersion,
        IHttpModuleRegistrationInfo* pModuleInfo,
        IHttpServer* pGlobalInfo
    )
    {
        // Create a new MyHttpModuleFactory pointer.
        MyHttpModuleFactory* factory =
            new MyHttpModuleFactory;

        // If the factory is NULL, return a
        // return a ERROR_NOT_ENOUGH_MEMORY 
        // errror.
        if (NULL == factory)
        {
            return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
        }

        // Return the value from calling the 
        // SetRequestNotifications method by 
        // passing the factory for RQ_SEND_RESPONSE
        // events.
        return pModuleInfo->SetRequestNotifications(
            factory,
            RQ_SEND_RESPONSE,
            0);
    }

    // The GetHttpModule method creates a new MyHttpModule 
    // pointer and sets the ppModule with this pointer.
    // ppModule: the OUT parameter which 
    // accepts a new CHttpModule subclass.
    // pAllocator: the IModuleAllocator pointer, 
    // which is unused in this implementation.
    virtual HRESULT GetHttpModule
    (
        OUT CHttpModule** ppModule, 
        IN IModuleAllocator* pAllocator
    )
    {
        // Call the UNREFERENCED_PARAMETER with 
        // the IModuleAllocator pointer, because
        // this parameter is never used.
        UNREFERENCED_PARAMETER(pAllocator);        

        // Create a new MyHttpModule pointer and assign
        // it to the dereferenced ppModule pointer.
        *ppModule = new MyHttpModule;

        // If the dereferenced ppModule is NULL 
        // then heap memory is exhausted. Return
        // an ERROR_NOT_ENOUGH_MEMORY error.
        if (NULL == *ppModule)
        {
            return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
        }

        // Creating a new MyHttpModule pointer 
        // was successful; return S_OK.
        return S_OK;       
    }

    // The Terminate method must be implemented
    // by IHttpModuleFactory implementers, 
    // and calls delete on this.
    virtual void Terminate()
    {
        delete this;
    }

private:
    // The MyHttpModuleFactory is the 
    // protected constructor for the 
    // MyHttpModuleFactory class.
    MyHttpModuleFactory()
    {

    }

    // The MyHttpModuleFactory method is the 
    // protected virtual destructor for the 
    // MyHttpModuleFactory class.
    virtual ~MyHttpModuleFactory()
    {

    }
};

// 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 HRESULT value returned from 
// the MyHttpModuleFactory::RegisterGlobalModule
// static method.
HRESULT
__stdcall
RegisterModule
(
    DWORD dwServerVersion,
    IHttpModuleRegistrationInfo* pModuleInfo,
    IHttpServer* pGlobalInfo
)
{    
    // Register for global events using the MyHttpModuleFactory 
    // class' static RegisterGlobalModule method.
    return MyHttpModuleFactory::RegisterGlobalModule
        (dwServerVersion, pModuleInfo, pGlobalInfo);  
}

Ниже приведен пример выходных данных из предыдущего примера кода.

HTTP/1.1 200 OK  
content-Type:text/plain  
Server: Microsoft-IIS/7.0  
Date: Thu, 15 Dec 2005 22:22:09 GMT  
Content-Length: 17  
  
VR Token:  NULL  

Модуль должен экспортировать функцию RegisterModule . Эту функцию можно экспортировать, создав файл определения модуля (DEF- файл) для проекта, или скомпилировать модуль с помощью /EXPORT:RegisterModule параметра . Дополнительные сведения см. в разделе Пошаговое руководство. Создание модуля HTTP Request-Level с помощью машинного кода.

При необходимости можно скомпилировать код с помощью __stdcall (/Gz) соглашения о вызовах вместо явного объявления соглашения о вызовах для каждой функции.

Требования

Тип Описание
клиент — IIS 7.0 в Windows Vista
— IIS 7.5 в Windows 7
— IIS 8.0 в Windows 8
— IIS 10.0 в Windows 10
Сервер — IIS 7.0 в Windows Server 2008
— IIS 7.5 в Windows Server 2008 R2
— IIS 8.0 в Windows Server 2012
— IIS 8.5 в Windows Server 2012 R2
— IIS 10.0 в Windows Server 2016
Продукт — 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

См. также:

Интерфейс IHttpFileInfo