806 lines
20 KiB
C++
806 lines
20 KiB
C++
#include <pch.h>
|
|
#pragma hdrstop
|
|
|
|
#include <httpext.h>
|
|
#include <httpfilt.h>
|
|
#include <wininet.h>
|
|
#include <msxml.h>
|
|
#include <oleauto.h>
|
|
#include "ssdpapi.h"
|
|
#include "ncbase.h"
|
|
#include "updiag.h"
|
|
#include "ncxml.h"
|
|
|
|
BOOL g_fInited = FALSE;
|
|
HANDLE g_hMapFile = NULL;
|
|
SHARED_DATA * g_pdata = NULL;
|
|
HANDLE g_hEvent = NULL;
|
|
HANDLE g_hEventRet = NULL;
|
|
HANDLE g_hMutex = NULL;
|
|
BOOL g_fTurnOff = FALSE;
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpv)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL FInit()
|
|
{
|
|
SECURITY_ATTRIBUTES sa = {0};
|
|
SECURITY_DESCRIPTOR sd = {0};
|
|
|
|
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
|
|
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
|
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
sa.bInheritHandle = FALSE;
|
|
sa.lpSecurityDescriptor = &sd;
|
|
|
|
InitializeDebugging();
|
|
|
|
TraceTag(ttidIsapiCtl, "Initializing...");
|
|
|
|
g_hEvent = CreateEvent(&sa, FALSE, FALSE, c_szSharedEvent);
|
|
if (g_hEvent)
|
|
{
|
|
if (GetLastError() != ERROR_ALREADY_EXISTS)
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Event wasn't already created!");
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Created event...");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Could not create event! Error = %d.",
|
|
GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
g_hEventRet = CreateEvent(&sa, FALSE, FALSE, c_szSharedEventRet);
|
|
if (g_hEventRet)
|
|
{
|
|
if (GetLastError() != ERROR_ALREADY_EXISTS)
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Return event wasn't already created!");
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Created return event...");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Could not create return event! Error = %d.",
|
|
GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
g_hMutex = CreateMutex(&sa, FALSE, c_szSharedMutex);
|
|
if (g_hMutex)
|
|
{
|
|
if (GetLastError() != ERROR_ALREADY_EXISTS)
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Mutex wasn't already created!");
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Created mutex...");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Could not create event! Error = %d.",
|
|
GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
g_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, c_szSharedData);
|
|
if (g_hMapFile)
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Opened file mapping...");
|
|
g_pdata = (SHARED_DATA *)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS,
|
|
0, 0, 0);
|
|
if (g_pdata)
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Shared data successful at 0x%08X.", g_pdata);
|
|
TraceTag(ttidIsapiCtl, "ISAPICTL is initialized.");
|
|
g_fInited = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Failed to map file. Error %d.", GetLastError());
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Failed to open file mapping. Error %d.", GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (g_pdata)
|
|
{
|
|
UnmapViewOfFile((LPVOID)g_pdata);
|
|
}
|
|
|
|
if (g_hMapFile)
|
|
{
|
|
CloseHandle(g_hMapFile);
|
|
}
|
|
|
|
if (g_hEvent)
|
|
{
|
|
CloseHandle(g_hEvent);
|
|
}
|
|
|
|
if (g_hEventRet)
|
|
{
|
|
CloseHandle(g_hEvent);
|
|
}
|
|
|
|
if (g_hMutex)
|
|
{
|
|
CloseHandle(g_hMutex);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO * pver)
|
|
{
|
|
if (!g_fInited && !g_fTurnOff)
|
|
{
|
|
if (!FInit())
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Failed to initialize. Aborting!");
|
|
SsdpCleanup();
|
|
g_fTurnOff = TRUE;
|
|
TraceTag(ttidIsapiCtl, "Turning off.");
|
|
//return FALSE;
|
|
}
|
|
}
|
|
|
|
pver->dwExtensionVersion = MAKELONG(1, 0);
|
|
lstrcpyA(pver->lpszExtensionDesc, "UPnP ISAPI Control Extension");
|
|
|
|
TraceTag(ttidIsapiCtl, "ISAPICTL: Extension version: %s.",
|
|
pver->lpszExtensionDesc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
HrParseHeader(
|
|
IXMLDOMNode * pxdnHeader)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IXMLDOMNode * pxdnChild = NULL;
|
|
|
|
hr = pxdnHeader->get_firstChild(&pxdnChild);
|
|
|
|
while (SUCCEEDED(hr) && pxdnChild)
|
|
{
|
|
IXMLDOMNode * pxdnNextSibling = NULL;
|
|
BSTR bstrBaseName = NULL;
|
|
|
|
hr = pxdnChild->get_baseName(&bstrBaseName);
|
|
|
|
if (SUCCEEDED(hr) && bstrBaseName)
|
|
{
|
|
if (wcscmp(bstrBaseName, L"sequenceNumber") == 0)
|
|
{
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseHeader(): "
|
|
"Parsing sequence number node");
|
|
|
|
BSTR bstrSeqNumberText = NULL;
|
|
|
|
hr = pxdnChild->get_text(&bstrSeqNumberText);
|
|
|
|
if (SUCCEEDED(hr) && bstrSeqNumberText)
|
|
{
|
|
LONG lSeqNumber = _wtol(bstrSeqNumberText);
|
|
|
|
g_pdata->dwSeqNumber = (DWORD) lSeqNumber;
|
|
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseHeader(): "
|
|
"Sequence number is %d\n",
|
|
g_pdata->dwSeqNumber);
|
|
|
|
SysFreeString(bstrSeqNumberText);
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseHeader(): "
|
|
"Failed to get sequence number text");
|
|
}
|
|
}
|
|
else if (wcscmp(bstrBaseName, L"SID") == 0)
|
|
{
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseHeader(): "
|
|
"Parsing SID node");
|
|
|
|
BSTR bstrSIDText = NULL;
|
|
|
|
hr = pxdnChild->get_text(&bstrSIDText);
|
|
|
|
if (SUCCEEDED(hr) && bstrSIDText)
|
|
{
|
|
DWORD cch;
|
|
|
|
cch = SysStringLen(bstrSIDText)+1;
|
|
WideCharToMultiByte(CP_ACP, 0, bstrSIDText,
|
|
cch,
|
|
(LPSTR)g_pdata->szSID,
|
|
cch, NULL, NULL);
|
|
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseHeader(): "
|
|
"SID is %s\n",
|
|
g_pdata->szSID);
|
|
|
|
SysFreeString(bstrSIDText);
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseHeader(): "
|
|
"Failed to get SID text");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Found an unknown node. This SOAP request is not valid.
|
|
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseHeader(): "
|
|
"Found unknown node \"%S\"",
|
|
bstrBaseName);
|
|
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
SysFreeString(bstrBaseName);
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
TraceError("HrParseHeader(): "
|
|
"Failed to get node base name",
|
|
hr);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pxdnChild->get_nextSibling(&pxdnNextSibling);
|
|
pxdnChild->Release();
|
|
pxdnChild = pxdnNextSibling;
|
|
}
|
|
else
|
|
{
|
|
pxdnChild->Release();
|
|
pxdnChild = NULL;
|
|
}
|
|
|
|
};
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Last success return code out of the loop would have
|
|
// been S_FALSE.
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError("HrParseHeader(): "
|
|
"Exiting",
|
|
hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
HrParseBody(
|
|
IXMLDOMNode * pxdnBody)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Find the action node. This is the first child of the <Body> node.
|
|
|
|
IXMLDOMNode * pxdnAction = NULL;
|
|
|
|
hr = pxdnBody->get_firstChild(&pxdnAction);
|
|
|
|
if (SUCCEEDED(hr) && pxdnAction)
|
|
{
|
|
BSTR bstrActionName = NULL;
|
|
|
|
hr = pxdnAction->get_baseName(&bstrActionName);
|
|
|
|
if (SUCCEEDED(hr) && bstrActionName)
|
|
{
|
|
// Copy the action name into the shared data.
|
|
|
|
DWORD cch;
|
|
|
|
cch = SysStringLen(bstrActionName) + 1;
|
|
WideCharToMultiByte(CP_ACP, 0, bstrActionName,
|
|
cch,
|
|
(LPSTR)g_pdata->szAction,
|
|
cch, NULL, NULL);
|
|
|
|
// Copy each of the action arguments into the shared data.
|
|
|
|
IXMLDOMNode * pxdnArgument = NULL;
|
|
|
|
hr = pxdnAction->get_firstChild(&pxdnArgument);
|
|
|
|
while (SUCCEEDED(hr) && pxdnArgument)
|
|
{
|
|
BSTR bstrArgText = NULL;
|
|
|
|
hr = pxdnArgument->get_text(&bstrArgText);
|
|
|
|
if (SUCCEEDED(hr) && bstrArgText)
|
|
{
|
|
DWORD cch;
|
|
|
|
cch = SysStringLen(bstrArgText) + 1;
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, bstrArgText,
|
|
cch,
|
|
(LPSTR)g_pdata->rgArgs[g_pdata->cArgs].szValue,
|
|
cch, NULL, NULL);
|
|
|
|
g_pdata->cArgs++;
|
|
|
|
SysFreeString(bstrArgText);
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
TraceError("HrParseBody(): "
|
|
"Failed to get argument text",
|
|
hr);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNode * pxdnNextArgument = NULL;
|
|
|
|
hr = pxdnArgument->get_nextSibling(&pxdnNextArgument);
|
|
pxdnArgument->Release();
|
|
pxdnArgument = pxdnNextArgument;
|
|
}
|
|
else
|
|
{
|
|
pxdnArgument->Release();
|
|
pxdnArgument = NULL;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
SysFreeString(bstrActionName);
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
TraceError("HrParseBody(): "
|
|
"Failed to get action name",
|
|
hr);
|
|
}
|
|
|
|
pxdnAction->Release();
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
TraceError("HrParseBody(): "
|
|
"Failed to get action node",
|
|
hr);
|
|
}
|
|
|
|
|
|
|
|
TraceError("HrParseBody(): "
|
|
"Exiting",
|
|
hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
HrParseAction(
|
|
IXMLDOMNode * pxdnSOAPEnvelope)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IXMLDOMNode * pxdnChild = NULL;
|
|
|
|
hr = pxdnSOAPEnvelope->get_firstChild(&pxdnChild);
|
|
|
|
while (SUCCEEDED(hr) && pxdnChild)
|
|
{
|
|
IXMLDOMNode * pxdnNextSibling = NULL;
|
|
BSTR bstrBaseName = NULL;
|
|
|
|
hr = pxdnChild->get_baseName(&bstrBaseName);
|
|
|
|
if (SUCCEEDED(hr) && bstrBaseName)
|
|
{
|
|
if (wcscmp(bstrBaseName, L"Header") == 0)
|
|
{
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseAction(): "
|
|
"Parsing Header node");
|
|
|
|
hr = HrParseHeader(pxdnChild);
|
|
|
|
}
|
|
else if (wcscmp(bstrBaseName, L"Body") == 0)
|
|
{
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseAction(): "
|
|
"Parsing Body node");
|
|
|
|
hr = HrParseBody(pxdnChild);
|
|
|
|
}
|
|
else
|
|
{
|
|
// Found an unknown node. This SOAP request is not valid.
|
|
TraceTag(ttidIsapiCtl,
|
|
"HrParseAction(): "
|
|
"Found unknown node \"%S\"",
|
|
bstrBaseName);
|
|
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
SysFreeString(bstrBaseName);
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
TraceError("HrParseAction(): "
|
|
"Failed to get node base name",
|
|
hr);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pxdnChild->get_nextSibling(&pxdnNextSibling);
|
|
pxdnChild->Release();
|
|
pxdnChild = pxdnNextSibling;
|
|
}
|
|
else
|
|
{
|
|
pxdnChild->Release();
|
|
pxdnChild = NULL;
|
|
}
|
|
|
|
};
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Last success return code out of the loop would have
|
|
// been S_FALSE.
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError("HrParseAction(): "
|
|
"Exiting",
|
|
hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT HrLoadArgsFromXml(LPCWSTR szXml)
|
|
{
|
|
VARIANT_BOOL vbSuccess;
|
|
HRESULT hr = S_OK;
|
|
IXMLDOMDocument * pxmlDoc;
|
|
IXMLDOMNodeList * pNodeList = NULL;
|
|
IXMLDOMNode * pNode = NULL;
|
|
IXMLDOMNode * pNext = NULL;
|
|
|
|
hr = CoCreateInstance(CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IXMLDOMDocument, (LPVOID *)&pxmlDoc);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pxmlDoc->put_async(VARIANT_FALSE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pxmlDoc->loadXML((BSTR)szXml, &vbSuccess);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMElement * pxde;
|
|
|
|
hr = pxmlDoc->get_documentElement(&pxde);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HrParseAction(pxde);
|
|
|
|
|
|
ReleaseObj(pxde);
|
|
}
|
|
}
|
|
}
|
|
|
|
ReleaseObj(pxmlDoc);
|
|
}
|
|
|
|
TraceError("HrLoadArgsFromXml", hr);
|
|
return hr;
|
|
}
|
|
|
|
DWORD DwProcessXoapRequest(LPSTR szUri, DWORD cbData, LPBYTE pbData)
|
|
{
|
|
LPSTR szData = (LPSTR)pbData;
|
|
UPNP_PROPERTY * rgProps;
|
|
DWORD cProps;
|
|
DWORD dwReturn = 0;
|
|
HRESULT hr;
|
|
|
|
// Must acquire shared-memory mutex first
|
|
//
|
|
if (WAIT_OBJECT_0 == WaitForSingleObject(g_hMutex, INFINITE))
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Acquired mutex...");
|
|
|
|
ZeroMemory(g_pdata, sizeof(SHARED_DATA));
|
|
|
|
LPSTR szAnsi;
|
|
LPWSTR wszXmlBody;
|
|
|
|
szAnsi = new CHAR[cbData + 1];
|
|
CopyMemory(szAnsi, pbData, cbData);
|
|
szAnsi[cbData] = 0;
|
|
wszXmlBody = WszFromSz(szAnsi);
|
|
|
|
TraceTag(ttidIsapiCtl, "URI = %s: Data = %s.", szUri, szAnsi);
|
|
|
|
delete [] szAnsi;
|
|
|
|
hr = HrLoadArgsFromXml(wszXmlBody);
|
|
TraceError("DwProcessXoapRequest: HrLoadArgsFromXml", hr);
|
|
|
|
// Done with changes to shared memory
|
|
TraceTag(ttidIsapiCtl, "Releasing mutex...");
|
|
ReleaseMutex(g_hMutex);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// Copy in event source URI
|
|
lstrcpyA(g_pdata->szEventSource, szUri);
|
|
|
|
TraceTag(ttidIsapiCtl, "Setting event...");
|
|
|
|
// Now tell the device we're ready for it to process
|
|
SetEvent(g_hEvent);
|
|
|
|
TraceTag(ttidIsapiCtl, "Waiting for return event...");
|
|
|
|
// Immediately wait on event again for return response
|
|
if (WAIT_OBJECT_0 == WaitForSingleObject(g_hEventRet, INFINITE))
|
|
{
|
|
dwReturn = g_pdata->dwReturn;
|
|
TraceTag(ttidIsapiCtl, "Setting return value to %d.", dwReturn);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// On failure, we don't even need to signal the device. This
|
|
// XOAP request wasn't properly formed or we couldn't process
|
|
// it anyway
|
|
//
|
|
TraceError("DwProcessXoapRequest - failed to load args from XML", hr);
|
|
dwReturn = DwWin32ErrorFromHr(hr);
|
|
}
|
|
|
|
// And we're done!
|
|
}
|
|
|
|
return dwReturn;
|
|
}
|
|
|
|
HRESULT HrComposeXoapResponse(DWORD dwValue, LPSTR *pszOut)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPSTR szOut;
|
|
CHAR szBuffer[1024];
|
|
|
|
Assert(pszOut);
|
|
|
|
|
|
// $ BUGBUG SPATHER Response should be namespace-qualified.
|
|
|
|
wsprintfA(szBuffer,
|
|
"<SOAP:Envelope xmlns:SOAP=\"urn:schemas-xmlsoap-org:soap.v1\">\r\n"
|
|
" <SOAP:Body>\r\n"
|
|
" <%sResponse>\r\n"
|
|
" <return>%d</return>\r\n"
|
|
" </%sResponse>\r\n"
|
|
" </SOAP:Body>\r\n"
|
|
"</SOAP:Envelope>",
|
|
g_pdata->szAction,
|
|
dwValue,
|
|
g_pdata->szAction);
|
|
|
|
szOut = SzaDupSza(szBuffer);
|
|
if (szOut)
|
|
{
|
|
*pszOut = szOut;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
TraceError("HrComposeXoapResponse", hr);
|
|
return hr;
|
|
}
|
|
|
|
DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK pecb)
|
|
{
|
|
DWORD hseStatus = HSE_STATUS_SUCCESS;
|
|
|
|
if (g_fInited)
|
|
{
|
|
DWORD dwReturn;
|
|
HRESULT hr;
|
|
|
|
if (!lstrcmpiA(pecb->lpszMethod, "M-POST"))
|
|
{
|
|
LPSTR szResponse;
|
|
DWORD cbResponse;
|
|
|
|
// This was a post request so it's a XOAP control request
|
|
TraceTag(ttidIsapiCtl, "Received 'M-POST' request");
|
|
|
|
// The URI of the event source will be the query string
|
|
dwReturn = DwProcessXoapRequest(pecb->lpszQueryString,
|
|
pecb->cbAvailable,
|
|
pecb->lpbData);
|
|
|
|
// Send XOAP response with dwReturn
|
|
TraceTag(ttidIsapiCtl, "Sending XOAP response for %d.", dwReturn);
|
|
|
|
hr = HrComposeXoapResponse(dwReturn, &szResponse);
|
|
if (S_OK == hr)
|
|
{
|
|
cbResponse = lstrlenA(szResponse);
|
|
|
|
TraceTag(ttidIsapiCtl, "Writing XOAP response: %s.", szResponse);
|
|
|
|
pecb->WriteClient(pecb->ConnID, (LPVOID)szResponse,
|
|
&cbResponse, 0);
|
|
|
|
free(szResponse);
|
|
}
|
|
}
|
|
else if (!lstrcmpiA(pecb->lpszMethod, "POST"))
|
|
{
|
|
|
|
HSE_SEND_HEADER_EX_INFO hse;
|
|
LPSTR szResponse = "";
|
|
DWORD cbResponse;
|
|
LPSTR szStatus = "405 Method Not Allowed";
|
|
DWORD cbStatus;
|
|
|
|
|
|
TraceTag(ttidIsapiCtl, "Received 'POST' request");
|
|
TraceTag(ttidIsapiCtl, "Data = %s.", pecb->lpbData);
|
|
|
|
ZeroMemory(&hse, sizeof(HSE_SEND_HEADER_EX_INFO));
|
|
cbResponse = lstrlenA(szResponse);
|
|
cbStatus = lstrlenA(szStatus);
|
|
hse.pszStatus = szStatus;// here you should print "405 Method Not Allowed"
|
|
hse.pszHeader = szResponse; // this one should be empty for http errors
|
|
hse.cchStatus = cbStatus;
|
|
hse.cchHeader = cbResponse;
|
|
hse.fKeepConn = FALSE;
|
|
|
|
pecb->dwHttpStatusCode = HTTP_STATUS_BAD_METHOD;
|
|
|
|
pecb->ServerSupportFunction(pecb->ConnID,
|
|
HSE_REQ_SEND_RESPONSE_HEADER_EX,
|
|
(LPVOID)&hse,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Data = %s.", pecb->lpbData);
|
|
|
|
pecb->dwHttpStatusCode = HTTP_STATUS_BAD_METHOD;
|
|
TraceTag(ttidIsapiCtl, "ISAPICTL: Received bad method '%s' request.",
|
|
pecb->lpszMethod);
|
|
|
|
hseStatus = HSE_STATUS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidIsapiCtl, "Not initialized!");
|
|
}
|
|
|
|
return hseStatus;
|
|
}
|
|
|
|
|
|
BOOL WINAPI TerminateExtension(DWORD dwFlags)
|
|
{
|
|
TraceTag(ttidIsapiCtl, "TerminateExtension: Exiting...");
|
|
|
|
if (g_pdata)
|
|
{
|
|
UnmapViewOfFile((LPVOID)g_pdata);
|
|
}
|
|
|
|
if (g_hMapFile)
|
|
{
|
|
CloseHandle(g_hMapFile);
|
|
}
|
|
|
|
if (g_hEvent)
|
|
{
|
|
CloseHandle(g_hEvent);
|
|
}
|
|
|
|
if (g_hEventRet)
|
|
{
|
|
CloseHandle(g_hEvent);
|
|
}
|
|
|
|
if (g_hMutex)
|
|
{
|
|
CloseHandle(g_hMutex);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|