📄 is2odbc.cpp
字号:
/*
* Is2odbc.cpp : Implementation file for Internet Server Extension
* ISAPI to ODBC Extension
*
* Sample code for "Multithreading Applications in Win32"
* This is from Chapter 16
*
* Implement an ISAPI extension that will launch and then
* talk to an external process that is running the JET engine.
*
* The error messages returned by this filter are appropriate
* for developers. They would need to be changed if this page
* were being used by endusers.
*/
#include "stdafx.h"
#include "Is2Odbc.h"
// Add our include files here
#include "MtVerify.h"
#include "Request.h"
//
// Define how long an ISAPI thread should wait while
// handling a DB request.
//
#define TIMEOUT_MUTEX 5000 /* 10 sec wait to do a request */
#define TIMEOUT_EVENT 360000 /* 60 sec wait for results */
///////////////////////////////////////////////////////////////////////
// The one and only CWinApp object
// NOTE: You may remove this object if you alter your project to no
// longer use MFC in a DLL.
CWinApp theApp;
//
// Setup a security descriptor that allows world access
//
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
///////////////////////////////////////////////////////////////////////
// command-parsing map
BEGIN_PARSE_MAP(CIs2OdbcExtension, CHttpServer)
// TODO: insert your ON_PARSE_COMMAND() and
// ON_PARSE_COMMAND_PARAMS() here to hook up your commands.
// For example:
//
// Added Optional Filter and Sort arguments
//
ON_PARSE_COMMAND(Default, CIs2OdbcExtension, ITS_PSTR ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("Filter=~ Sort=~")
DEFAULT_PARSE_COMMAND(Default, CIs2OdbcExtension)
END_PARSE_MAP(CIs2OdbcExtension)
///////////////////////////////////////////////////////////////////////
// The one and only CIs2OdbcExtension object
CIs2OdbcExtension theExtension;
///////////////////////////////////////////////////////////////////////
// CIs2OdbcExtension implementation
CIs2OdbcExtension::CIs2OdbcExtension()
{
}
CIs2OdbcExtension::~CIs2OdbcExtension()
{
}
BOOL CIs2OdbcExtension::GetExtensionVersion(HSE_VERSION_INFO* pVer)
{
// Call default implementation for initialization
CHttpServer::GetExtensionVersion(pVer);
// Load description string
TCHAR sz[HSE_MAX_EXT_DLL_NAME_LEN+1];
ISAPIVERIFY(::LoadString(AfxGetResourceHandle(),
IDS_SERVER, sz, HSE_MAX_EXT_DLL_NAME_LEN));
_tcscpy(pVer->lpszExtensionDesc, sz);
return TRUE;
}
BOOL CIs2OdbcExtension::InitInstance(CHttpServerContext* pCtxt)
{
// Let the base class do its job.
CHttpServer::InitInstance(pCtxt);
// create a security descriptor that allows anyone
// to get at the event...
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
return FALSE;
// add a NULL disc. ACL to the security descriptor.
//
if (!SetSecurityDescriptorDacl(&sd, TRUE, (PACL) NULL, FALSE))
return FALSE;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////
// CIs2OdbcExtension command handlers
//
// Added Filter and Sort arguments
void CIs2OdbcExtension::Default(CHttpServerContext* pCtxt, LPTSTR pszFilter, LPTSTR pszSort)
{
StartContent(pCtxt);
WriteTitle(pCtxt);
CEvent serverRunning(FALSE, TRUE, EVENT_SERVER_RUNNING, &sa);
if (::GetLastError() != ERROR_ALREADY_EXISTS)
{
CString strDllPath;
GetModuleFileName( theApp.m_hInstance,
strDllPath.GetBuffer(MAX_PATH),
MAX_PATH );
strDllPath.ReleaseBuffer();
strDllPath = strDllPath.Left( strDllPath.ReverseFind(_T('\\'))+1 );
strDllPath += "DbServer.EXE";
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
BOOL fServerCreated = ::CreateProcess(
strDllPath,
NULL, // Command line
NULL, // Process Security
NULL, // Thread Security
FALSE, // No Inherit
DETACHED_PROCESS,
NULL, // Environment
NULL,
&si,
&pi
);
if (!fServerCreated)
{
*pCtxt << _T("CreateProcess failed calling DbServer.<p>");
EndContent(pCtxt);
return;
}
}
// DbServer may be starting up now, so wait for it.
if (::WaitForSingleObject(serverRunning, TIMEOUT_EVENT) == WAIT_TIMEOUT)
{
*pCtxt << _T("DbServer failed to start.<p>");
EndContent(pCtxt);
return;
}
// This mutex is only used within the Web server,
// so it should not need world security attributes.
CMutex myMutex(FALSE, MUTEX_DB_REQUEST);
CSingleLock myLock(&myMutex, FALSE);
// Wait to get access to DbServer
// If another request is outstanding then we will not get in.
if (myLock.Lock(TIMEOUT_MUTEX))
{
// Create events for signalling DbServer
CEvent startEvent(FALSE, TRUE, EVENT_START_PROCESSING, &sa);
CEvent doneEvent(FALSE, TRUE, EVENT_DONE_PROCESSING, &sa);
//
// Allocate memory for our data structure in shared memory.
//
HANDLE hFileMapping = NULL;
DbRequest* pDbRequest = NULL;
MTVERIFY( hFileMapping = ::CreateFileMapping((LPVOID) -1, &sa,
PAGE_READWRITE, 0, sizeof(DbRequest),
FILE_DB_REQUEST));
MTVERIFY( pDbRequest = (DbRequest*) ::MapViewOfFile(hFileMapping,
FILE_MAP_ALL_ACCESS, 0, 0, 0));
//
// Fill in our DB request.
// Make sure we detect the default argument "~" and replace it.
//
strcpy(pDbRequest->sqlFilter, "");
if (strcmp(pszFilter, "~") != 0)
strcpy(pDbRequest->sqlFilter, pszFilter);
strcpy(pDbRequest->sqlSort, "");
if (strcmp(pszSort, "~") != 0)
strcpy(pDbRequest->sqlSort, pszSort);
// Tell DbServer to do the DB Query
startEvent.SetEvent();
// Wait for result from DbServer
// If Server has died, we can tell user
CSingleLock waitForDoneEvent(&doneEvent, FALSE);
if (waitForDoneEvent.Lock(TIMEOUT_EVENT))
{ // got result from server
*pCtxt << _T("The following books match your search request:<p>");
*pCtxt << pDbRequest->sqlResult << "<p>";
} // end if
else
{ // Got no response from server
*pCtxt << _T("Sorry, but DbServer never responded with the results.<p>");
} // end else
doneEvent.ResetEvent();
// Close request data structure
UnmapViewOfFile(pDbRequest);
CloseHandle(hFileMapping);
} // end if
else
{ // Another Thread is busy accessing the server
*pCtxt << _T("Sorry, another Web Page is busy making a database request.<p>");
} // end else
EndContent(pCtxt);
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CIs2OdbcExtension, CHttpServer)
//{{AFX_MSG_MAP(CIs2OdbcExtension)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
///////////////////////////////////////////////////////////////////////
// If your extension will not use MFC, you'll need this code to make
// sure the extension objects can find the resource handle for the
// module. If you convert your extension to not be dependent on MFC,
// remove the comments arounn the following AfxGetResourceHandle()
// and DllMain() functions, as well as the g_hInstance global.
/****
static HINSTANCE g_hInstance;
HINSTANCE AFXISAPI AfxGetResourceHandle()
{
return g_hInstance;
}
BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason,
LPVOID lpReserved)
{
if (ulReason == DLL_PROCESS_ATTACH)
{
g_hInstance = hInst;
}
return TRUE;
}
****/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -