/*static char *SCCSID = "@(#)dllapi.c   6.13 92/02/18";*/
/*==============================================================*\
 *  DLLAPI.C - Sample PM application				*
 *								*
 *	(C) Copyright IBM Corporation 1992.			*
 *								*
 *--------------------------------------------------------------*
 *								*
 *  This DLL application program consists of a DLL file that	*
 *  provides a 32-bit DOS called functions, and an API's EXE    *
 *  file that uses the dynamic linking library to handle some	*
 *  operations. The DLL uses protected memory to protect its	*
 *  shared data, and exception management to validate the API's *
 *  pointer parameters, handle the errors returned.		*
 *  This application also serves as a template that can be	*
 *  easily modified by an application developer.  The source	*
 *  files are organized so that the overhead code that should	*
 *  be in all applications is located in the same files so	*
 *  that these files do not need to be modified.  The routines	*
 *  that deal with application specific code are also located	*
 *  in their own modules.  An application developer need only	*
 *  change these files in order to modify this template for	*
 *  his application.						*
 *								*
 *--------------------------------------------------------------*
 *								*
 *  This source file contains the following functions:		*
 *								*
 *	main() - main routine					*
 *	MainWndProc(hwnd, msg, mp1, mp2) - main window procedure*
 *	MainCommand(hwnd, mp1, mp2) - WM_COMMAND processing	*
 *	MessageBox(hwnd nId, pszMsg, fsStyle, bBeep)		*
 *								*
\*==============================================================*/
/*--------------------------------------------------------------*\
 *  Include files, macros, defined constants, and externs	*
\*--------------------------------------------------------------*/

#include "dllapi.h"

/****************************************************************\
 *  Main routine						*
 *--------------------------------------------------------------*
 *								*
 *  Name:    main()						*
 *								*
 *  Purpose: Initializes the PM environment, calls the		*
 *	     initialization routine, creates the main window,	*
 *	     and polls the message queue.			*
 *								*
 *  Usage:							*
 *								*
 *  Method:  -obtains anchor block handle and creates message	*
 *		queue						*
 *	     -calls the initialization routine			*
 *	     -creates the main frame window which creates the	*
 *		main client window				*
 *	     -polls the message queue via Get/Dispatch Msg loop *
 *	     -upon exiting the loop, exits			*
 *								*
 *  Returns: 1 - if sucessful execution completed		*
 *	     0 - if error					*
 *								*
\****************************************************************/
INT main(VOID)
{
   QMSG qmsg;					   /* message structure */
   ULONG ctlData=FCF_STANDARD;		     /* main frame control data */
   EXCEPTIONREGISTRATIONRECORD ExceptionStruct;

   strcpy(szWindowText,"DLLAPI Sample");
   hwndChild = (HWND)0;
   hab = WinInitialize(0);
   if(!hab)
   {
       DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
       DosExit(EXIT_PROCESS, RETURN_ERROR);
   }
   hmq = WinCreateMsgQueue(hab, 0);
   if(!hmq)
   {
       DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
       WinTerminate(hab);
       DosExit(EXIT_PROCESS, RETURN_ERROR);
   }
   if(!Init())
   {
       MessageBox(HWND_DESKTOP, IDMSG_INITFAILED, "Error !",
			   MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
       DosExit(EXIT_PROCESS, RETURN_ERROR);
   }
					      /* create the main window */
   hwndMainFrame = WinCreateStdWindow(HWND_DESKTOP,
				      WS_VISIBLE,
				      (PVOID)&ctlData,
				      (PSZ)szAppName,
				      (PSZ)NULL,
				      WS_VISIBLE,
				      (HMODULE)NULL,
				      ID_RESOURCE,
				      (PHWND)&hwndMain);
   if(!hwndMainFrame)
   {
       MessageBox(HWND_DESKTOP, IDMSG_MAINWINCREATEFAILED, "Error !",
			   MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
       DosExit(EXIT_PROCESS, RETURN_ERROR);
   }
   InitHelp();
   ExceptionStruct.ExceptionHandler = (_ERR *)&GPFHandler;
   DosSetExceptionHandler(&ExceptionStruct) ;

   while(WinGetMsg(hmq, (PQMSG)&qmsg, 0L, 0L, 0L))
	   WinDispatchMsg(hmq, (PQMSG)&qmsg);

   DosUnsetExceptionHandler(&ExceptionStruct) ;
					   /* destroy the help instance */
   DestroyHelpInstance();
				    /* will normally be put in ExitProc */
   DosExit(EXIT_PROCESS, RETURN_SUCCESS);
   return 0;
}							       /* main() */

/****************************************************************\
 *  Main client window procedure				*
 *--------------------------------------------------------------*
 *								*
 *  Name:    MainWndProc(hwnd, msg, mp1, mp2)			*
 *								*
 *  Purpose: Processes the messages sent to the main client	*
 *	     window. This routine processes the basic messages	*
 *	     all client windows should process and passes all	*
 *	     others onto UserWndProc where the developer can	*
 *	     process any others.				*
 *								*
 *  Usage:   Called for each message placed in the main		*
 *	     window's message queue                             *
 *								*
 *  Method:  a switch statement branches to the routines to be	*
 *	     performed for each message processed. Any messages *
 *	     not specifically process are passed to the user's  *
 *	     message processing procedure UserWndProc().	*
 *								*
 *  Returns: Return values are determined by each message	*
 *								*
\****************************************************************/
MRESULT EXPENTRY MainWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   MRESULT sRC;

   switch(msg) {
       case WM_PAINT:
	   MainPaint(hwnd);
	   break;

       case WM_COMMAND:
	   MainCommand(hwnd, mp1, mp2);
	   break;

   /*--------------------------------------------------*\
    *	   Any messages not processed are passed on    *
    *	   to the user's window proc.  It is           *
    *	   responsible for passing any messages it     *
    *	   doesn't handle onto WinDefWindowProc()      *
   \*--------------------------------------------------*/
       case HM_QUERY_KEYS_HELP:
	   return ((MRESULT)PANEL_KEYSHELP);

       default:
	   sRC = WinDefWindowProc(hwnd, msg, mp1, mp2);
	   return sRC;
   }
   return (MRESULT)0L; /*all window procedures should return 0 as a default*/
}							 /* MainWndProc() */

/****************************************************************\
 *  Main client painting routine				*
 *--------------------------------------------------------------*
 *								*
 *  Name:    MainPaint(hwnd)					*
 *								*
 *  Purpose: Paints the main client window.			*
 *								*
 *  Usage:   Routine is called whenver the client window	*
 *	     procedure receives a WM_PAINT message		*
 *								*
 *  Method:  -begins painting by calling WinBeginPaint		*
 *		and retriving the HPS for the window		*
 *	     -paint page info boxes				*
 *								*
 *	     -ends painting by calling WinEndPaint		*
 *								*
 *  Returns: VOID						*
 *								*
\****************************************************************/
VOID MainPaint(HWND hwnd)
{
   HPS	  hps;				/* Handle for painting		 */
   RECTL  rect;				/* Rectangle struct for painting */
   CHAR	  szBuffer[BUFF_SIZE];
   POINTL ptl;

   hps = WinBeginPaint(hwnd, 0L, (PRECTL)&rect);
   WinFillRect(hps, (PRECTL)&rect, CLR_BACKGROUND);
			      /* Fill update rectangle with window color */
   WinQueryWindowRect(hwndMain, (PRECTL)&rect);
   switch (sStatus) {
   case IDM_SEARCH:
      ptl.x = HORZ_INDENT;
      ptl.y = rect.yTop - VERT_TEXT_POS;
      memset(szBuffer, 0, sizeof(szBuffer));
      strcpy(szBuffer, "Searching Path: [");
      strcat(szBuffer, ObjInfo.szCurDriver);
      strcat(szBuffer, ObjInfo.szCurPath);
      strcat(szBuffer, "]");

      GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);

      ptl.x = HORZ_INDENT;
      ptl.y = rect.yTop - VERT_TEXT_POS * 2;
      memset(szBuffer, 0, sizeof(szBuffer));
      strcpy(szBuffer, "Searching Pattern: [");
      strcat(szBuffer, ObjInfo.szCurPattern);
      strcat(szBuffer, "]");

      GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);

      break;
   default:
      break;
   }							   /* endswitch */
   WinEndPaint(hps);
   return;
}							 /* MainPaint() */

/****************************************************************\
 *  Main window WM_COMMAND processing procedure			*
 *--------------------------------------------------------------*
 *								*
 *  Name:   MainCommand(hwnd, mp1, mp2)				*
 *								*
 *  Purpose:Calls the appropriate procedures that deal with	*
 *	     the selected menu item.				*
 *								*
 *  Usage:  Routine is called whenever a WM_COMMAND message	*
 *	    is posted to the main window.			*
 *								*
 *  Method: a switch statement branches on the id of the	*
 *	    menu item that posted the message and the		*
 *	    appropriate action for that item is taken.	Any	*
 *	    menu ids that are not part of the standard menu	*
 *	    set are passed onto the user defined WM_COMMAND	*
 *	    processing procedure.				*
 *								*
 *  Returns: VOID						*
 *								*
\****************************************************************/
VOID MainCommand(HWND hwnd, MPARAM mp1, MPARAM mp2)
{
    switch(SHORT1FROMMP(mp1))
    {
	case IDM_GENERALHELP:
	   HelpExtended(mp2);
	   return;

	case IDM_USINGHELP:
	   HelpHelpForHelp(mp2);
	   return;

	case IDM_TUTORIAL:
	   HelpKeys(mp2);
	   return;

	case IDM_HELPINDEX:
	   HelpIndex(mp2);
	   return;

	case IDM_HELPPRODUCTINFO:
	   HelpAbout(mp2);
	   return;

    /*--------------------------------------------------*\
     *	    User command processing routine is called	*
     *	    here so any ids not procecessed here can be *
     *	    processed					*
    \*--------------------------------------------------*/
	default:
	    UserCommand(hwnd, mp1, mp2);
	    break;
    }
    return;
}						 /* MainCommand() */


/****************************************************************\
 *  Non-standard menu item command processing procedure		*
 *--------------------------------------------------------------*
 *								*
 *  Name:    UserCommand(hwnd, mp1, mp2)			*
 *								*
 *  Purpose: Process any WM_COMMAND messages send to hwndMain	*
 *		that are not processed by MainCommand		*
 *								*
 *  Usage:   Routine is called for each WM_COMMAND that is	*
 *	     not posted by a standard menu item			*
 *								*
 *  Method:  A switch statement branches control based upon	*
 *	     the id of the control which posted the message	*
 *								*
 *  Returns: VOID						*
 *								*
\****************************************************************/
VOID UserCommand(HWND hwnd, MPARAM mp1, MPARAM mp2)
{
   HPS	       hps;
   RECTL       rect;
   CHAR	       szBuffer[BUFF_SIZE];
   APIRET      Ret;
   POINTL      ptl;

   switch (SHORT1FROMMP(mp1))
   {
       case IDM_SEARCH:
	   if (WinDlgBox(HWND_DESKTOP,
			 hwnd,
			 (PFNWP)GetPatternDlgProc,
			 (HMODULE)0,
			 (ULONG)IDD_GETPATTERN,
			 (PVOID)&ObjInfo) )
	   {
	      sStatus = IDM_SEARCH;
	      hps = WinGetPS(hwnd);
	      WinQueryWindowRect(hwnd, &rect);
	      WinFillRect(hps, (PRECTL)&rect, CLR_BACKGROUND);
	      ptl.x = HORZ_INDENT;
	      ptl.y = rect.yTop - VERT_TEXT_POS;
	      memset(szBuffer, 0, sizeof(szBuffer));
	      strcpy(szBuffer, "Searching Path: [");
	      strcat(szBuffer, ObjInfo.szNewDriver);
	      strcat(szBuffer, ObjInfo.szNewPath);
	      strcat(szBuffer, "]");

	      GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);

	      ptl.x = HORZ_INDENT;
	      ptl.y = rect.yTop - VERT_TEXT_POS * 2;
	      memset(szBuffer, 0, sizeof(szBuffer));
	      strcpy(szBuffer, "Searching Pattern: [");
	      strcat(szBuffer, ObjInfo.szNewPattern);
	      strcat(szBuffer, "]");

	      GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);
	      WinReleasePS(hps);

	      Ret=SearchFile(&ObjInfo, &pFindFile);
	      if (Ret)
	      {
		  switch(Ret) {
		  case ERROR_FILE_NOT_FOUND:
		       MessageBox(hwnd, IDMSG_FILENOTFOUND, "Warning !",
				MB_OK | MB_INFORMATION | MB_MOVEABLE, TRUE);
		       break;
		  case ERROR_DRIVE_LOCKED:
		       MessageBox(hwnd, IDMSG_DRIVELOCKED, "Error !",
				MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		       break;
		  case ERROR_PATH_NOT_FOUND:
		       MessageBox(hwnd, IDMSG_PATHNOTFOUND, "Error !",
				MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		       break;
		  case RETURN_ERROR:
		       MessageBox(hwnd, IDMSG_ERRORSETPATH, "Error !",
				MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		       break;
		  case ERROR_BUFFER_OVERFLOW:
		       MessageBox(hwnd, IDMSG_BUFFEROVERFLOW, "Error !",
				MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		       break;
		  case ERROR_INVALID_DRIVE:
		       MessageBox(hwnd, IDMSG_ERRORINVALIDDRIVE, "Error !",
				MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		       break;
		  }			  /* End of switch(Ret)	  */
	      }				  /* Endif of DisplayFile */
	      else
	      {
		 memset(ObjInfo.szCurDriver,0,sizeof(ObjInfo.szCurDriver));
		 memset(ObjInfo.szCurPath,0,sizeof(ObjInfo.szCurPath));
		 memset(ObjInfo.szCurPattern,0,sizeof(ObjInfo.szCurPattern));
		 strcpy(ObjInfo.szCurDriver,ObjInfo.szNewDriver);
		 strcpy(ObjInfo.szCurPath,ObjInfo.szNewPath);
		 strcpy(ObjInfo.szCurPattern,ObjInfo.szNewPattern);
		 rect.yTop = rect.yTop-VERT_TEXT_POS*2-5;

		 if(WinDlgBox(HWND_DESKTOP,
			   hwnd,
			   (PFNWP)DispFileDlgProc,
			   (HMODULE)0,
			   (ULONG)IDD_DSPFILESTRUCT,
			   (PVOID)NULL) )

		     DisplayFile(hwnd, rect, &pFlList);
	      }
	   }			       /* End of case(IDM_SEARCH) */
	   break;

       case IDM_OPEN:
	   if (WinDlgBox(HWND_DESKTOP,
			 hwnd,
			 (PFNWP)OpenDlgProc,
			 (HMODULE)0,
			 (ULONG)IDD_OPENFILE,
			 (PVOID)&FileInfo) )
	   {
	      Ret=ReadFileProc(&FileInfo);
	      if(Ret)
	      {
		 switch(Ret) {
		 case ERROR_PATH_NOT_FOUND:
		      MessageBox(hwnd, IDMSG_PATHNOTFOUND, "Error !",
			       MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		      break;
		 case ERROR_OPEN_FAILED:
		      MessageBox(hwnd, IDMSG_OPENFAILED, "Error !",
			       MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		      break;
		 case ERROR_FILE_NOT_FOUND:
		      MessageBox(hwnd, IDMSG_FILENOTFOUND, "Error !",
			       MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		      break;
		 case ERROR_ACCESS_DENIED:
		      MessageBox(hwnd, IDMSG_ACCESSDENIED, "Error !",
			       MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		      break;
		 default:
		      MessageBox(hwnd, IDMSG_RETURNERROR, "Error !",
			       MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
		      break;
		 }
	      }
	      else
	      {
		 if(!WinDlgBox(HWND_DESKTOP,
			      hwnd,
			      (PFNWP)DisplayDlgProc,
			      (HMODULE)0,
			      (ULONG)IDD_DISPLAYTEXT,
			      (PVOID)&FileInfo) )
		 MessageBox(hwnd, IDMSG_DSPTEXTERROR, "Error !",
			  MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
	      }
	   }
	   break;
       case IDM_CALCUL:
	   if (WinDlgBox(HWND_DESKTOP,
			 hwnd,
			 (PFNWP)MathDlgProc,
			 (HMODULE)0,
			 (ULONG)IDD_GETMATHINFO,
			 (PVOID)&MathInfo) )
	   {
	      if(*(MathInfo.pszOperation) != '\000')
	      {
		 CalCulProc(&MathInfo);

		 if(!WinDlgBox(HWND_DESKTOP,
			      hwnd,
			      (PFNWP)ResultDlgProc,
			      (HMODULE)0,
			      (ULONG)IDD_DISPLAYVALUE,
			      (PVOID)&MathInfo) )
		 MessageBox(hwnd, IDMSG_DSPTEXTERROR, "Error !",
			  MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
	      }
	   }
	   break;

       default:
	 break;
   }
    /* This routine currently doesn't use the mp2 parameter but       *\
     *	it is referenced here to prevent an 'Unreferenced Parameter'  *
    \*	warning at compile time.				      */
   return;
}

/****************************************************************\
 *  Message Box procedure					*
 *--------------------------------------------------------------*
 *								*
 *  Name:    MessageBox(hwndOwner,IdMsg,pszMsg,fsStyle,bBeep)	*
 *								*
 *  Purpose: Displays the warning message box with the message	*
 *		given in nIdMsg retrived from the message table *
 *								*
 *  Usage:   Called whever an error occurs and a message wishes *
 *	     to be displayed to the user			*
 *								*
 *  Method:  - Message string is loaded from the process'       *
 *		message table					*
 *	     - Alarm beep is sounded if desired			*
 *	     - Message box with the message is displayed	*
 *								*
 *  Returns: VOID						*
 *								*
\****************************************************************/
VOID MessageBox(HWND hwndOwner, LONG IdMsg, PSZ pszMsg, LONG fsStyle,
		     BOOL bBeep)
{
   CHAR szText[MESSAGELEN];

   if(!WinLoadMessage(hab, (HMODULE)NULL, IdMsg, MESSAGELEN, (PSZ)szText))
   {
       WinAlarm(HWND_DESKTOP, WA_ERROR);
       return;
   }
   if(bBeep)
       WinAlarm(HWND_DESKTOP, WA_ERROR);

   WinMessageBox(HWND_DESKTOP,
		 hwndOwner,
		 szText,
		 (PSZ)pszMsg,
		 IDM_MSGBOX,
		 fsStyle);
   return;
}						   /* MessageBox() */
