Функция HttpExtensionProc
Теперь рассмотрим вторую функцию, которую должна экспортировать библиотека DLL расширения ISAPI. Она называется HttpExtensionProc и имеет следующий прототип:
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB);
Функция HttpExtensionProc получает единственный параметр - указатель на структуру типа EXTENSION_CONTROL_BLOCK, определенную в файле httpext.h:
typedef struct _EXTENSION_CONTROL_BLOCK
{
DWORD cbSize; // размер структуры в байтах
DWORD dwVersion; // версия спецификации ISAPI
HCONN ConnID; // идентификатор канала
DWORD dwHttpStatusCode; // код состояния HTTP
CHAR lpszLogData[HSE_LOG_BUFFER_LEN]; // текстовая строка,
// закрытая двоичным нулем, в которой находится информация
// протоколирования, специфичная для данного расширения
LPSTR lpszMethod; // переменная REQUEST_METHOD
LPSTR lpszQueryString; // переменная QUERY_STRING
LPSTR lpszPathInfo; // переменная PATH_INFO
LPSTR lpszPathTranslated; // переменная PATH_TRANSLATED
DWORD cbTotalBytes; // полный размер данных, полученных от
// навигатора
DWORD cbAvailable; // размер доступного блока данных
LPBYTE lpbData; // указатель на доступный блок данных
// размером cbAvailable байт
LPSTR lpszContentType; // тип принятых данных
// Функция GetServerVariable для получения значения переменных
BOOL (WINAPI * GetServerVariable)(HCONN hConn,
LPSTR lpszVariableName, LPVOID lpvBuffer, LPDWORD lpdwSize);
// Функция WriteClient для посылки данных удаленному пользователю
BOOL (WINAPI * WriteClient)(HCONN ConnID,
LPVOID Buffer, LPDWORD lpdwBytes, DWORD dwReserved);
// Функция ReadClient для получения данных от удаленного
// пользователя
BOOL (WINAPI * ReadClient) (HCONN ConnID,
LPVOID lpvBuffer, LPDWORD lpdwSize);
// Вспомогательная функция ServerSupportFunction
// для выполнения различных операций
BOOL (WINAPI * ServerSupportFunction)(HCONN hConn,
DWORD dwHSERRequest, LPVOID lpvBuffer,
LPDWORD lpdwSize, LPDWORD lpdwDataType);
} EXTENSION_CONTROL_BLOCK, *LPEXTENSION_CONTROL_BLOCK;
Рассмотрим отдельные поля этой структуры.
- cbSize
- dwVersion
- ConnID
- dwHttpStatusCode
- lpszLogData
- lpszMethod
- lpszQueryString
- lpszPathInfo
- lpszPathTranslated
- cbTotalBytes
- cbAvailable
- lpbData
- lpszContentType
- GetServerVariable
- WriteClient
- ReadClient
- ServerSupportFunction
В самом начале структуры EXTENSION_CONTROL_BLOCK находится поле cbSize, в которое при вызове расширения сервер записывает размер структуры в байтах.
Поле dwVersion содержит номер версии расширения ISAPI. Верхнее и нижнее значения номера версии можно получить, соответственно, при помощи макрокоманд HIWORD и LOWORD.
В поле ConnID сервер записывает идентификатор канала, созданного для расширения. Это поле вы не должны изменять.
Поле dwHttpStatusCode должно заполняться расширением ISAPI. Вы должны записать сюда результат завершения операции (код состояния транзации). В случае успеха в это поле записывается значение 200 (как указано в спецификации HTTP).
Поле lpszLogData предназначено для записи сообщения о выполнении транзакции в журнал сервера WWW. Это сообщение должно быть в виде текстовой строки, закрытой нулем. Размер строки в байтах не должен превышать значения HSE_LOG_BUFFER_LEN.
Поле lpszMethod заполняется сервером и содержит название метода передачи данных от удаленного пользователя серверу в виде текстовой строки, закрытой двоичным нулем. Расширения ISAPI используют те же самые методы, что и программы CGI - метод GET и метод POST. Проводя аналогию с программами CGI дальше, скажем, что поле lpszMethod эквивалентно переменной среды с именем REQUEST_METHOD, создаваемой для программы CGI.
Аналогично, поле lpszQueryString соответствует переменной среды с именем QUERY_STRING. В это поле записываются данные, принятые от удаленного пользователя методом GET.
В поле lpszPathInfo записывается виртуальный путь к программному файлу библиотеки DLL расширения ISAPI. Напомним, что аналогичная информация для программ CGI передавалась через переменную среды с именем PATH_INFO.
Это поле содержит физический путь к программному файлу библиотеки DLL расширения ISAPI. Оно соответствует переменной среды с именем PATH_TRANSLATED, создаваемой для программ CGI.
В поле cbTotalBytes записывается общее количество байт данных, которое необходимо получить от удаленного пользователя. Часть этих данных (размером не более 48 Кбайт) считывается сервером автоматически и становится доступной сразу после того как функция HttpExtensionProc получит управление. Остальные данные необходимо дочитать в цикле при помощи функции ReadClient, о которой мы еще будем говорить.
В поле cbAvailable записывается размер блока данных, полученных от удаленного пользователя автоматически. Как мы только что сказали, размер этого блока не может превышать 48 Кбайт. Этого, однако, вполне достаточно для обработки данных, полученных от форм обычного размера.
Указатель на область памяти, в которую записан сервером полученный от удаленного пользователя блок данных размером cbAvailable байт.
Поле lpszContentType содержит тип принятых данных, например, text/html.
Помимо полей данных, структура EXTENSION_CONTROL_BLOCK содержит указатели на функции. С помощью этих функций расширение ISAPI может выполнять различные операции, такие как прием данных от удаленного пользователя.
Поле GetServerVariable содержит указатель на функцию, с помощью которой расширение ISAPI может получить информацию, которая доступна программам CGI через переменные среды, описанные нами в предыдущей главе этой книги.
В поле WriteClient находится адрес функции, которую расширение ISAPI должно использовать для посылки данных удаленному пользователю. Таким образом, вместо того чтобы записывать данные в стандартный поток вывода STDOUT, как это делает программа CGI, приложение ISAPI посылает данные с помощью функции WriteClient.
С помощью функции, адрес которой передается в поле ReadClient, приложение может дочитать дополнительные данные, не поместившиеся в буфер предварительного чтения, имеющий адрес lpbData и размер, не превышающий 48 Кбайт. Аналогичную операцию приема данных от пользователя выполняет программа CGI в случае применения метода передачи данных POST. Отличие заключается в том, что программа CGI получает данные через стандартный поток ввода STDIN, а расширение ISAPI берет эти данные из буфера предварительного чтения и при необходимости дочитывает данные функцией ReadClient.
С помощью функции, адрес которой передается через поле ServerSupportFunction, расширение ISAPI может выполнять различные действия, такие как посылка стандартного заголовка протокола HTTP и некоторые другие.
При успешном завершении функция HttpExtensionProc должна вернуть значение HSE_STATUS_SUCCESS, а при ошибке - значение HSE_STATUS_ERROR. Соответствующие константы определены в файле httpext.h.