home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1999 September
/
CHIPCD_9_99.iso
/
software
/
uaktualnienia
/
OptionPackPL
/
msmqocm.cab
/
booksrvr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-04-07
|
24KB
|
740 lines
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <mq.h>
#include <mqmail.h>
//helper macro to define MQ props
#define SizedMQProps(_QUEUE_or_MSG_, _cProps_, _Name_) \
_QUEUE_or_MSG_##PROPID _Name_##rgPropID[_cProps_]; \
MQPROPVARIANT _Name_##rgPropVar[_cProps_]; \
HRESULT _Name_##rgStatus[_cProps_]; \
MQ##_QUEUE_or_MSG_##PROPS _Name_ = \
{0, _Name_##rgPropID, _Name_##rgPropVar, _Name_##rgStatus}
char * szBookList = "Lonely Hearts, Arthur C. Van Haven, NorthStar & co.\r\n"
"Magnetic Forces, Nathan Axelrod, Science Inc.\r\n"
"Dual Balance, Big John Array, Marshal & Sons\r\n"
"Bake It!, Sarah McBarney, Spoon Publishers\r\n";
char * szBookListInStock =
"Magnetic Forces, Nathan Axelrod, Science Inc.\r\n"
"Bake It!, Sarah McBarney, Spoon Publishers\r\n";
#define BOOKSRVR_MSG_INIT_BUFSIZE 10000
#define BOOKSRVR_RE_SUBJECT_INIT_BUFSIZE 200
//control structure
typedef struct BOOKSRVR_tag
{
int argc;
char ** argv;
char * szQLabelIn;
HANDLE hToExitEvent;
QUEUEHANDLE hQueue;
HANDLE hRcvEvent;
ULONG cbBuffer;
LPBYTE lpbBuffer;
OVERLAPPED sOverlapped;
LPMQMailEMail pEMail;
ULONG cbReSubject;
char * pszReSubject;
ULONG cbRetBuffer;
LPBYTE lpbRetBuffer;
QUEUEHANDLE hSendQueue;
} BOOKSRVR, *LPBOOKSRVR;
//create unicode string from ansi
BOOL FCreateUnicodeStr(LPSTR pszAnsi, LPWSTR * ppwszUnicode)
{
LPWSTR pwszUnicode;
int cchUnicode;
//alloc unicode string
cchUnicode = strlen(pszAnsi) + 1;
pwszUnicode = (LPWSTR)malloc(cchUnicode*sizeof(WCHAR));
if (pwszUnicode == NULL)
{
printf("Error %lx allocating unicode string\n", GetLastError());
return(FALSE);
}
//convert to unicode
if (!MultiByteToWideChar(CP_ACP, 0, pszAnsi, -1, pwszUnicode, cchUnicode))
{
printf("Error %lx in MultiByteToWideChar\n", GetLastError());
free(pwszUnicode);
return(FALSE);
}
//return unicode string
*ppwszUnicode = pwszUnicode;
return(TRUE);
}
LPMQMailFormField lpFindFieldByName(LPMQMailEMail pEMail,
char * pszName,
MQMailFormFieldType iType)
{
ULONG ulTmp;
BOOL fNotFound;
LPMQMailFormField lpField;
for (ulTmp = 0, fNotFound = TRUE;
(ulTmp < pEMail->form.pFields->cFields) && fNotFound;
ulTmp++)
{
lpField = pEMail->form.pFields->apField[ulTmp];
if ((strcmpi(lpField->szName, pszName) == 0) &&
(lpField->iType == iType))
{
fNotFound = FALSE;
}
}
if (fNotFound)
return(NULL);
else
return(lpField);
}
enum
{
LOCATE_Q_INSTANCE,
COUNT_LOCATE_PROPS
};
#define MAX_FMTNAME 512
BOOL FOpenQueueByLabel(LPBOOKSRVR pBookSrvr, LPSTR szQLabel, DWORD dwAccess, QUEUEHANDLE * phQueue)
{
HRESULT hr;
MQRESTRICTION res;
MQPROPERTYRESTRICTION aresToAnd[2];
MQCOLUMNSET sColSet;
PROPID rgPropSpec[COUNT_LOCATE_PROPS];
MQPROPVARIANT rgPropVar[COUNT_LOCATE_PROPS];
ULONG ulTmp;
CLSID clsidQueue;
WCHAR wszFmtName[MAX_FMTNAME];
DWORD cFmtName = MAX_FMTNAME * sizeof(WCHAR);
CLSID clsidFalc = CLSID_MQMailQueueType;
DWORD cProps;
LPWSTR pwszUnicodeQLabel;
HANDLE hEnum;
//create unicode string for locate
if (!FCreateUnicodeStr(szQLabel, &pwszUnicodeQLabel))
return(FALSE);
// Restriction for locate - Label==pszQLabel & Type==CLSID_MQMailQueueType
aresToAnd[0].rel = PREQ;
aresToAnd[0].prop = PROPID_Q_LABEL;
aresToAnd[0].prval.vt = VT_LPWSTR;
aresToAnd[0].prval.pwszVal = pwszUnicodeQLabel;
aresToAnd[1].rel = PREQ;
aresToAnd[1].prop = PROPID_Q_TYPE;
aresToAnd[1].prval.vt = VT_CLSID;
aresToAnd[1].prval.puuid = &clsidFalc;
res.cRes = 2;
res.paPropRes = aresToAnd;
// Columns for locate
rgPropSpec[0] = PROPID_Q_INSTANCE;
sColSet.cCol = COUNT_LOCATE_PROPS;
sColSet.aCol = rgPropSpec;
//locate
hr = MQLocateBegin(NULL, &res, &sColSet, NULL, &hEnum);
if (FAILED(hr))
{
printf("Error %lx in MQLocateBegin\n", hr);
free(pwszUnicodeQLabel);
return(FALSE);
}
//prepare for locate next
cProps = COUNT_LOCATE_PROPS;
for (ulTmp = 0; ulTmp < COUNT_LOCATE_PROPS; ulTmp++)
rgPropVar[ulTmp].vt = VT_NULL;
//locate next
hr = MQLocateNext(hEnum, &cProps, rgPropVar);
if (FAILED(hr))
{
printf("Error %lx in MQLocateNext\n", hr);
MQLocateEnd(hEnum);
free(pwszUnicodeQLabel);
return(FALSE);
}
//check if queue was found
if (cProps != COUNT_LOCATE_PROPS)
{
MQLocateEnd(hEnum);
free(pwszUnicodeQLabel);
return(FALSE);
}
//get clsid and free resources
memcpy(&clsidQueue, rgPropVar[LOCATE_Q_INSTANCE].puuid, sizeof(CLSID));
MQFreeMemory(rgPropVar[LOCATE_Q_INSTANCE].puuid);
MQLocateEnd(hEnum);
free(pwszUnicodeQLabel);
//convert clsid to format name for MQOpenQueue
hr = MQInstanceToFormatName(&clsidQueue, wszFmtName, &cFmtName);
if (FAILED(hr))
{
printf("Error %lx in MQInstanceToFormatName\n", hr);
return(FALSE);
}
//open queue
hr = MQOpenQueue(wszFmtName, dwAccess, 0, phQueue);
if (FAILED(hr))
{
printf("Error %lx in MQOpenQueue\n", hr);
return(FALSE);
}
return(TRUE);
}
enum
{
CREATE_Q_LABEL,
CREATE_Q_TYPE,
CREATE_Q_PATHNAME,
COUNT_CREATE_Q_PROPS
};
#define MAX_QPATH 512
BOOL FCreateQueue(LPBOOKSRVR pBookSrvr, LPSTR szQLabel)
{
HRESULT hr;
SizedMQProps(QUEUE, COUNT_CREATE_Q_PROPS, sCreateQProps);
WCHAR wszUnicodeComputerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwTmp = MAX_COMPUTERNAME_LENGTH;
WCHAR wszUnicodeQPath[MAX_QPATH + 1];
LPWSTR pwszUnicodeQLabel;
CLSID clsidFalc = CLSID_MQMailQueueType;
WCHAR wszFmtName[MAX_FMTNAME];
DWORD cFmtName = MAX_FMTNAME;
wcscpy(wszUnicodeComputerName, L".");
//create unicode queue label
if (!FCreateUnicodeStr(szQLabel, &pwszUnicodeQLabel))
return(FALSE);
//Falcon queue path is <machine-name>\<queue-name>
swprintf(wszUnicodeQPath, L"%s\\%s",
wszUnicodeComputerName, pwszUnicodeQLabel);
//fill props
sCreateQProps.cProp = COUNT_CREATE_Q_PROPS;
sCreateQProps.aPropID[CREATE_Q_LABEL] = PROPID_Q_LABEL;
sCreateQProps.aPropVar[CREATE_Q_LABEL].vt = VT_LPWSTR;
sCreateQProps.aPropVar[CREATE_Q_LABEL].pwszVal = pwszUnicodeQLabel;
sCreateQProps.aPropID[CREATE_Q_TYPE] = PROPID_Q_TYPE;
sCreateQProps.aPropVar[CREATE_Q_TYPE].vt = VT_CLSID;
sCreateQProps.aPropVar[CREATE_Q_TYPE].puuid = &clsidFalc;
sCreateQProps.aPropID[CREATE_Q_PATHNAME] = PROPID_Q_PATHNAME;
sCreateQProps.aPropVar[CREATE_Q_PATHNAME].vt = VT_LPWSTR;
sCreateQProps.aPropVar[CREATE_Q_PATHNAME].pwszVal = wszUnicodeQPath;
//create queue
hr = MQCreateQueue(NULL, &sCreateQProps, wszFmtName, &cFmtName);
free(pwszUnicodeQLabel);
if (FAILED(hr))
{
printf("Error %lx in MQCreateQueue\n", hr);
return(FALSE);
}
return(TRUE);
}
BOOL FOpenCreateQueueByLabel(LPBOOKSRVR pBookSrvr, LPSTR szQLabel, DWORD dwAccess, QUEUEHANDLE * phQueue)
{
//try to open the queue
if (!FOpenQueueByLabel(pBookSrvr, szQLabel, dwAccess, phQueue))
{
//open failed, create it, and try to open again
if (FCreateQueue(pBookSrvr, szQLabel))
return(FOpenQueueByLabel(pBookSrvr, szQLabel, dwAccess, phQueue));
else //create failed
return(FALSE);
}
return(TRUE);
}
enum
{
SEND_M_BODY,
SEND_M_DELIVERY,
COUNT_SEND_M_PROPS
};
//send body to sender queue
BOOL FSendBody(LPBOOKSRVR pBookSrvr, ULONG cbBuffer, LPBYTE lpbBuffer, LPSTR szQueueLabel)
{
HRESULT hr;
SizedMQProps(MSG, COUNT_SEND_M_PROPS, sSendMsgProps);
//open queue for send
if (!FOpenQueueByLabel(pBookSrvr, szQueueLabel, MQ_SEND_ACCESS, &pBookSrvr->hSendQueue))
return(FALSE);
sSendMsgProps.cProp = COUNT_SEND_M_PROPS;
// Body
sSendMsgProps.aPropID[SEND_M_BODY] = PROPID_M_BODY;
sSendMsgProps.aPropVar[SEND_M_BODY].vt = VT_VECTOR | VT_UI1;
sSendMsgProps.aPropVar[SEND_M_BODY].caub.cElems = cbBuffer;
sSendMsgProps.aPropVar[SEND_M_BODY].caub.pElems = lpbBuffer;
// Persistent
sSendMsgProps.aPropID[SEND_M_DELIVERY] = PROPID_M_DELIVERY;
sSendMsgProps.aPropVar[SEND_M_DELIVERY].vt = VT_UI1;
sSendMsgProps.aPropVar[SEND_M_DELIVERY].bVal = MQMSG_DELIVERY_RECOVERABLE;
//send message
hr = MQSendMessage(pBookSrvr->hSendQueue, &sSendMsgProps, NULL);
if (FAILED(hr))
{
printf("Error %lx in MQSendMessage", hr);
return(FALSE);
}
//close send queue
MQCloseQueue(pBookSrvr->hSendQueue);
pBookSrvr->hSendQueue = NULL;
return(TRUE);
}
BOOL FReplyToQuery(LPBOOKSRVR pBookSrvr, char * pszBookList,
LPMQMailFormField pOrigInStock,
LPMQMailFormField pOrigQuery)
{
MQMailRecip sFrom;
MQMailRecip sTo;
LPMQMailRecip apRecip[1];
MQMailRecipList sRecipList;
MQMailEMail sEMail;
FILETIME ft;
MQMailFormField sFieldResults;
LPMQMailFormField apField[3];
MQMailFormFieldList sFieldList;
HRESULT hr;
ULONG ulNeededReSubject;
//init reply email
ZeroMemory(&sEMail, sizeof(MQMailEMail));
//fill in subject from original mail with RE: before
ulNeededReSubject = strlen(pBookSrvr->pEMail->szSubject) + 5;
//realloc if necessary
if (ulNeededReSubject > pBookSrvr->cbReSubject)
{
pBookSrvr->pszReSubject = realloc(pBookSrvr->pszReSubject, ulNeededReSubject);
if (pBookSrvr->pszReSubject == NULL)
{
printf("Error %s realocating reply subject", GetLastError());
return(FALSE);
}
pBookSrvr->cbReSubject = ulNeededReSubject;
}
sprintf(pBookSrvr->pszReSubject, "Re: %s", pBookSrvr->pEMail->szSubject);
sEMail.szSubject = pBookSrvr->pszReSubject;
//time
GetSystemTimeAsFileTime(&ft);
sEMail.pftDate = &ft;
//reports
sEMail.fRequestDeliveryReport = FALSE;
sEMail.fRequestNonDeliveryReport = FALSE;
//fill in our attributes in the From recip
ZeroMemory(&sFrom, sizeof(MQMailRecip));
sFrom.szName = "Book Server";
sFrom.szQueueLabel = pBookSrvr->szQLabelIn;
sFrom.szAddress = pBookSrvr->szQLabelIn;
sEMail.pFrom = &sFrom;
//fill in To attributes out of original From
sTo = *(pBookSrvr->pEMail->pFrom);
sTo.iType = MQMailRecip_TO;
apRecip[0] = &sTo;
sRecipList.cRecips = 1;
sRecipList.apRecip = apRecip;
sEMail.pRecips = &sRecipList;
//type is form
sEMail.iType = MQMailEMail_FORM;
//form name
sEMail.form.szName = "IPM.BOOKS.RESULTS";
//form fields
sFieldResults.szName = "results";
sFieldResults.iType = MQMailFormField_STRING;
sFieldResults.Value.lpsz = pszBookList;
apField[0] = pOrigQuery;
apField[1] = pOrigInStock;
apField[2] = &sFieldResults;
sFieldList.cFields = 3;
sFieldList.apField = apField;
sEMail.form.pFields = &sFieldList;
//reserved should be NULL
sEMail.pReserved = NULL;
//compose body out of EMail structure
hr = MQMailComposeBody(&sEMail, &pBookSrvr->cbRetBuffer,
&pBookSrvr->lpbRetBuffer);
if (FAILED(hr))
{
printf("Error %lx in MQMailComposeBody\n", hr);
return(FALSE);
}
//send body to sender queue
if (!FSendBody(pBookSrvr, pBookSrvr->cbRetBuffer, pBookSrvr->lpbRetBuffer,
pBookSrvr->pEMail->pFrom->szQueueLabel))
return(FALSE);
//free body
MQMailFreeMemory(pBookSrvr->lpbRetBuffer);
pBookSrvr->lpbRetBuffer = NULL;
return(TRUE);
}
BOOL FHandleBody(LPBOOKSRVR pBookSrvr, ULONG ulBodySize)
{
HRESULT hr;
BOOL fIgnore;
LPMQMailFormField lpQueryField, lpInStockField;
LPSTR szRetList;
//parse the body into an email structure
hr = MQMailParseBody(ulBodySize, pBookSrvr->lpbBuffer, &pBookSrvr->pEMail);
if (FAILED(hr))
{
printf("Error %lx parsing message, ignoring message\n", hr);
return(TRUE);
}
//make sure this is our form, if not, ignore
if (pBookSrvr->pEMail->iType != MQMailEMail_FORM)
fIgnore = TRUE;
else if (pBookSrvr->pEMail->form.szName == NULL)
fIgnore = TRUE;
else if (strcmpi(pBookSrvr->pEMail->form.szName, "IPM.BOOKS.QUERY") != 0)
fIgnore = TRUE;
else
fIgnore = FALSE;
if (fIgnore)
{
printf("Can't recognize form, ignoring message\n", hr);
return(TRUE);
}
//find the form field named "query" with type string, and
// the form field named "instock" with type boolean.
lpQueryField = lpFindFieldByName(pBookSrvr->pEMail, "query", MQMailFormField_STRING);
lpInStockField = lpFindFieldByName(pBookSrvr->pEMail, "instock", MQMailFormField_BOOL);
if ((lpQueryField == NULL) || (lpInStockField == NULL))
{
printf("Can't find requested fields in form, ignoring message\n", hr);
return(TRUE);
}
//got a query, reply with a book list (...)
printf("\nRECEIVED from %s<%s> the following query: %s\n",
pBookSrvr->pEMail->pFrom->szName,
pBookSrvr->pEMail->pFrom->szAddress,
lpQueryField->Value.lpsz);
if (lpInStockField->Value.b)
{
printf("Information is requested only for books in stock\n");
szRetList = szBookListInStock;
}
else
szRetList = szBookList;
printf("Replying with the following list:\n%s\n", szRetList);
if (!FReplyToQuery(pBookSrvr, szRetList, lpQueryField, lpInStockField))
return(FALSE);
//free returned EMail structure
MQMailFreeMemory(pBookSrvr->pEMail);
pBookSrvr->pEMail = NULL;
return(TRUE);
}
enum
{
RECEIVE_M_BODY,
RECEIVE_M_BODY_SIZE,
COUNT_RECEIVE_M_PROPS
};
BOOL FHandleMessage(LPBOOKSRVR pBookSrvr, MQMSGPROPS * pRcvMsgProps)
{
HRESULT hr;
//result of async is in overlapped structure
hr = pBookSrvr->sOverlapped.Internal;
if (FAILED(hr))
{
ULONG ulNewBodySize;
//if error not related to buffer overflow, exit
if (hr != MQ_ERROR_BUFFER_OVERFLOW)
{
printf("Error %lx in async receive", hr);
return(FALSE);
}
//there was a buffer overflow, realloc buffer
ulNewBodySize = pRcvMsgProps->aPropVar[RECEIVE_M_BODY_SIZE].ulVal;
printf("Message is too big, reallocating buffer to size %l\n", ulNewBodySize);
pBookSrvr->lpbBuffer = realloc(pBookSrvr->lpbBuffer, ulNewBodySize);
if (pBookSrvr->lpbBuffer == NULL)
{
printf("Error %lx in realloc body buffer", GetLastError());
return(FALSE);
}
pBookSrvr->cbBuffer = ulNewBodySize;
//update props & buffer in rcv props, and call receive again
pRcvMsgProps->aPropVar[RECEIVE_M_BODY].caub.cElems = pBookSrvr->cbBuffer;
pRcvMsgProps->aPropVar[RECEIVE_M_BODY].caub.pElems = pBookSrvr->lpbBuffer;
hr = MQReceiveMessage(pBookSrvr->hQueue, 0, MQ_ACTION_RECEIVE,
pRcvMsgProps, NULL, NULL, NULL, NULL);
if (FAILED(hr))
{
printf("Error %lx in MQReceiveMessage", hr);
return(FALSE);
}
}
//now we have a body, call a routine to handle it
if (!FHandleBody(pBookSrvr, pRcvMsgProps->aPropVar[RECEIVE_M_BODY_SIZE].ulVal))
return(FALSE);
return(TRUE);
}
DWORD WINAPI dwBookSrvrThread(LPVOID lpParameter)
{
LPBOOKSRVR pBookSrvr = (LPBOOKSRVR) lpParameter;
DWORD dwWait;
BOOL fFinished = FALSE;
HANDLE ahWait[2];
HRESULT hr;
SizedMQProps(MSG, COUNT_RECEIVE_M_PROPS, sRcvMsgProps);
//open/create input queue for receive
if (!FOpenCreateQueueByLabel(pBookSrvr, pBookSrvr->szQLabelIn, MQ_RECEIVE_ACCESS, &pBookSrvr->hQueue))
return(1);
//create async receive event
pBookSrvr->hRcvEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pBookSrvr->hRcvEvent == NULL)
{
printf("Error %lx creating async receive event\n", GetLastError());
return(1);
}
//init overlapped
pBookSrvr->sOverlapped.hEvent = pBookSrvr->hRcvEvent;
//allocate memory for body
pBookSrvr->cbBuffer = BOOKSRVR_MSG_INIT_BUFSIZE;
pBookSrvr->lpbBuffer = malloc(pBookSrvr->cbBuffer);
if (pBookSrvr->lpbBuffer == NULL)
{
printf("Error %lx allocating body buffer\n");
return(1);
}
//allocate memory for reply subject
pBookSrvr->cbReSubject = BOOKSRVR_RE_SUBJECT_INIT_BUFSIZE;
pBookSrvr->pszReSubject = malloc(pBookSrvr->cbReSubject);
if (pBookSrvr->pszReSubject == NULL)
{
printf("Error %lx allocating re: subject buffer\n");
return(1);
}
//prepare handle array for WaitForMultipleObjects
ahWait[0] = pBookSrvr->hToExitEvent;
ahWait[1] = pBookSrvr->hRcvEvent;
//loop until we are asked to exit
while (!fFinished)
{
//request async message
sRcvMsgProps.cProp = COUNT_RECEIVE_M_PROPS;
sRcvMsgProps.aPropID [RECEIVE_M_BODY] = PROPID_M_BODY;
sRcvMsgProps.aPropVar[RECEIVE_M_BODY].vt = VT_VECTOR | VT_UI1;
sRcvMsgProps.aPropVar[RECEIVE_M_BODY].caub.cElems = pBookSrvr->cbBuffer;
sRcvMsgProps.aPropVar[RECEIVE_M_BODY].caub.pElems = pBookSrvr->lpbBuffer;
sRcvMsgProps.aPropID [RECEIVE_M_BODY_SIZE] = PROPID_M_BODY_SIZE;
sRcvMsgProps.aPropVar[RECEIVE_M_BODY_SIZE].vt = VT_UI4;
hr = MQReceiveMessage
(pBookSrvr->hQueue, INFINITE, MQ_ACTION_RECEIVE, &sRcvMsgProps,
&pBookSrvr->sOverlapped, NULL, NULL, NULL);
// if not FAILED(hr), either there is already a message received (MQ_OK) and the event is triggered, or it is pending
// and the event will be triggered when something happens. in both cases the result is handled by the event handler as wanted.
// if FAILED(hr), the event is not triggered, so we force it to be handled by the event handler
// by triggering the event, and setting the overlapped status to what we got.
if (FAILED(hr))
{
pBookSrvr->sOverlapped.Internal = hr;
SetEvent(pBookSrvr->sOverlapped.hEvent);
}
//wait for falcon message or exit event from main program
dwWait = WaitForMultipleObjects(2, ahWait, FALSE, INFINITE);
switch(dwWait)
{
case WAIT_OBJECT_0: //exit event from main program
fFinished = TRUE;
break;
case WAIT_OBJECT_0 + 1: //falcon message
if (!FHandleMessage(pBookSrvr, &sRcvMsgProps))
return(1);
break;
default:
printf("Error %lx happened in WaitForMultipleObjects\n", GetLastError());
return(1);
break;
}
}
return(0);
}
//-----------------------------------------------------------------
//start worker thread
//-----------------------------------------------------------------
BOOL FBookSrvr(LPBOOKSRVR pBookSrvr)
{
DWORD dwThreadId, dwWait;
HANDLE hThread;
//create synchronization event with working thread
pBookSrvr->hToExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pBookSrvr->hToExitEvent == NULL)
{
printf("Error %lx creating synchronization event\n", GetLastError());
return(FALSE);
}
//Start worker thread
hThread = CreateThread(NULL, 0, dwBookSrvrThread, pBookSrvr,
CREATE_SUSPENDED, &dwThreadId);
if (hThread == NULL)
{
printf("Error %lx creating worker thread\n", GetLastError());
return(FALSE);
}
printf("Booksrvr is running, use your mail client to send Book Search forms and look for response(s) (Press <Enter> to quit)\n");
ResumeThread(hThread);
//wait for <Enter> key
getchar();
printf("Quiting...\n");
//signal worker thread to exit
SetEvent(pBookSrvr->hToExitEvent);
//wait for it to exit
dwWait = WaitForSingleObject(hThread, 100000);
//if thread not terminated yet, kill it
if (dwWait != WAIT_OBJECT_0)
TerminateThread(hThread, 0);
return(TRUE);
}
//-----------------------------------------------------------------
//cleanup control structure
//-----------------------------------------------------------------
void CleanupBookSrvr(LPBOOKSRVR pBookSrvr)
{
if (pBookSrvr->hQueue != NULL)
MQCloseQueue(pBookSrvr->hQueue);
if (pBookSrvr->hSendQueue != NULL)
MQCloseQueue(pBookSrvr->hSendQueue);
if (pBookSrvr->lpbRetBuffer != NULL)
MQMailFreeMemory(pBookSrvr->lpbRetBuffer);
if (pBookSrvr->pszReSubject != NULL)
free(pBookSrvr->pszReSubject);
if (pBookSrvr->pEMail != NULL)
MQMailFreeMemory(pBookSrvr->pEMail);
if (pBookSrvr->lpbBuffer != NULL)
free(pBookSrvr->lpbBuffer);
if (pBookSrvr->hRcvEvent != NULL)
CloseHandle(pBookSrvr->hRcvEvent);
if (pBookSrvr->hToExitEvent != NULL)
CloseHandle(pBookSrvr->hToExitEvent);
}
//-----------------------------------------------------------------
//check arguments
//-----------------------------------------------------------------
BOOL FCheckArgs(LPBOOKSRVR pBookSrvr)
{
if (pBookSrvr->argc < 2)
return(FALSE);
pBookSrvr->szQLabelIn = pBookSrvr->argv[1];
return(TRUE);
}
//-----------------------------------------------------------------
//main
//-----------------------------------------------------------------
int main(int argc, char * argv[])
{
BOOKSRVR sBookSrvr;
BOOL fRet;
//initialize conrol structure
ZeroMemory(&sBookSrvr, sizeof(BOOKSRVR));
sBookSrvr.argc = argc;
sBookSrvr.argv = argv;
//check arguments
if (!FCheckArgs(&sBookSrvr))
{
printf("Usage: booksrvr <input-queue-label>\n");
printf(" <input-queue-label> - label of a queue where book requests arrive\n");
exit(1);
}
//do the real work
fRet = FBookSrvr(&sBookSrvr);
//cleanup
CleanupBookSrvr(&sBookSrvr);
if (fRet)
exit(0);
else
exit(2);
//needed for compilation
return(0);
}