/*==============================================================*\
 *  Svrqthrd.c - queue processing routine: initialization and
 *		 processing thread.
 *	Copyright 1992, IBM Corp.
 *
 *--------------------------------------------------------------
 *
 *  DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
 *  sample code created by IBM Corporation. This sample code is not
 *  part of any standard or IBM product and is provided to you solely
 *  for	 the purpose of assisting you in the development of your
 *  applications.  The code is provided "AS IS", without
 *  warranty of any kind.  IBM shall not be liable for any damages
 *  arising out of your use of the sample code, even if they have been
 *  advised of the possibility of   such damages.
 *
\*==============================================================*/


#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#define INCL_DOSQUEUES
#define INCL_DOSMEMMGR
#define INCL_WINMESSAGEMGR
#define INCL_DOSERRORS

#include <os2.h>

#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>

#include "svrqglbl.h"
#include "svrqmain.h"
#include "queue.h"
#include "svrqxtrn.h"


#define STACKSIZE    8192

static HQUEUE hqQ;

HQUEUE InitQ(PID  pidParent,   /* proccess that will send WM_CLOSE command */
	     HWND hwndParent)  /* window to post to */
{
   ULONG	      ulErrorMsg;
   BOOL		      fError=FALSE;
   static THREADPARAM tpThrdParm;

   if (!DosCreateQueue(&hqQ,
		       QUE_PRIORITY,
		       "\\queues\\" Q_NAME))
   {
      tpThrdParm.pidParent = pidParent;
      tpThrdParm.hwndParent = hwndParent;

      if( _beginthread(ReadQMessage,
			   NULL,
			   STACKSIZE,
			   (VOID *)&tpThrdParm) == -1 )
      {
	 ulErrorMsg = IDMSG_CREATE_THREAD_FAILED;
	 fError = TRUE;
      }
   }

   else
   {
      ulErrorMsg = IDMSG_CREATE_Q_FAILED;
      fError = TRUE;
   }

   if (fError)
   {
      MessageBox(HWND_DESKTOP,
		 ulErrorMsg,
		 MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL,
		 TRUE);
      return(0);
   }

   else
   {
      return (hqQ);
   }
}


#define	 MAXBUFF  10

VOID ReadQMessage(VOID *tpThrdParm)
{
   PVOID	pvdQMsg;
   BYTE		bPriority;
   REQUESTDATA	reqQdata;
   ULONG	cbRead;
   BOOL		fClose=FALSE, fError=FALSE;
   int		index=0;
   QDATA	qdataBuffer[MAXBUFF];
   PID		pidParent;
   HWND		hwndParent;

   pidParent = ((THREADPARAM *)tpThrdParm)->pidParent;
   hwndParent = ((THREADPARAM *)tpThrdParm)->hwndParent;

   while (!fClose && !fError)
   {
      if (!(DosReadQueue(hqQ,		  /* queue handle				*/
			 &reqQdata,	  /* queue result, incl. process id and request */
			 &cbRead,	  /* count of bytes in element			*/
		(VOID **)&pvdQMsg,	  /* address of element				*/
			 0,		  /* element number to read			*/
			 DCWW_WAIT,	  /* wait for element				*/
			 &bPriority,	  /* received element priority			*/
			 (HEV) NULL))) {  /* semaphore handle (not used)		*/

	 /* if parent process sends message to die... */

	 if (pidParent == reqQdata.pid && WM_CLOSE == reqQdata.ulData)
	 {
	    fClose = TRUE;
	 }

	 /* copy the string to some internal buffer, and post a message to the window
	  * to copy the new text to its own buffer and do what it will.
	  */
	 else
	 {
	    /* format the message */
	    switch(reqQdata.ulData)
	    {
	       case Q_MSG_DATE:
		  sprintf(qdataBuffer[index].pszMsg,
			  "Date -- Day: %d Month: %d Year: %d",
			  ((Q_DATE *)pvdQMsg)->usDay,
			  ((Q_DATE *)pvdQMsg)->usMonth,
			  ((Q_DATE *)pvdQMsg)->usYear);
		  break;

	       case Q_MSG_TEXT:
	       default:
		  strncpy(qdataBuffer[index].pszMsg, (CHAR *)pvdQMsg, cbRead);
		  break;
	    }

	    qdataBuffer[index].pidProcess = reqQdata.pid;
	    qdataBuffer[index].usPriority = bPriority;
	    WinPostMsg(hwndParent, WM_NEWQMSG, MPFROMP(&(qdataBuffer[index])), MPVOID);
	    index = (index < MAXBUFF-1) ? index+1 : 0;

	 /* after posting the message, unmark the memory and start the loop again
	  *
	  * CAVEAT: We are getting the offset by zeroing out the lower 16 bits
	  * of the block offset.  This can ONLY be done if the memory allocated
	  * is less than 64K.  Otherwise, the client must somehow (in the queue
	  * message would probably be a good idea) pass the offset to the server.
	  *
	  */
	    DosSubFreeMem((VOID *)((ULONG)pvdQMsg & ~(ULONG)0xFFFF), pvdQMsg, cbRead);
/*	      DosSubFreeMem(MAKEP(SELECTOROF(pvdQMsg), 0), pvdQMsg, cbRead);*/
	 }
      }

      else
      {
	 WinPostMsg(hwndMain, WM_MSG, MPFROMSHORT(IDMSG_READ_Q_ERROR), MPVOID);
	 fError = TRUE;
      }
   }

   DosCloseQueue(hqQ);
   fThrdsDead=TRUE;
}
