//Sample code file: var/ndk/webBuildengine/tmp/viewable_samples/c5607871-120e-404c-9042-2603fb37af10/QUERY/CPP/MAIN.CPP

//Warning: This code has been marked up for HTML

/***************************************************************************
$name: MAIN.CPP
$version: 1.0 
$date_modified: 121498 
$description: Show how to create queries using the Novell GroupWare Object
              API.  NOTE: Only one ShowResults modeless dialog will be shown
              at once.
$owner: GroupWise SDK Team Lead
Copyright (c) 1998 Novell, Inc. All Rights Reserved.

THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
CUSTOMERS WITH RESPECT TO THIS CODE.
****************************************************************************/
#include <windows.h>
#include "main.h"



//---------- GLOBALS ----------

IGWSession* pIGWSession;
IGWAccount* pIGWAccount;
HINSTANCE ghInst;
HANDLE hResultDlg;      // Modeless dialog




/*-------------------------------------------------------------------------------------
WinMain

  IN:      hInst      -   Handle to instance of program
         hPrevInst   -   Previous instance handle
         lpCmdLine   -   Command line
         nShowCmd   -   Show command

  RETURN:   TRUE
-------------------------------------------------------------------------------------*/
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
   ghInst = hInst;

   DialogBox(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)MainWndProc);

   return(TRUE);
}



/*-------------------------------------------------------------------------------
MainWndProc

  IN:      hwndDlg      -   Handle to dialog
         message      -   Message to watch for
         wParam      -   ...
         lParam      -   ...

  RETURN:   0 
--------------------------------------------------------------------------------*/
LONG APIENTRY MainWndProc(HWND hwndDlg, UINT message, WPARAM wParam, LONG lParam)
{
   switch(message) {
      case WM_INITDIALOG: {
         InitGWSession();
         InitDlgControls(hwndDlg);
         break;
      }


      case WM_COMMAND:
         switch(LOWORD(wParam)) {
            case IDOK:
               DoQuery(hwndDlg);
               break;


            case IDCANCEL:
               DeinitGWSession();
               EndDialog(hwndDlg, IDCANCEL);
               break;


            case IDC_FIELD:
               if(HIWORD(wParam) == CBN_SELCHANGE)
                  OnFieldSelectionChanged(hwndDlg);

               break;
         }
           break;


      case WM_CLOSE:
         ShowWindow(hwndDlg, SW_HIDE);
         DeinitGWSession();
           EndDialog(hwndDlg, 0);
          break;

   }

   return(0);
}



/*-------------------------------------------
InitDlgControls

  IN:   hwndDlg   -   Handle to dialog

  NOTE:   Initializes the controls on dialog
--------------------------------------------*/
void InitDlgControls(HWND hwndDlg)
{
HWND hwndField, hwndOperator, hwndExpression;
int i;


    hwndField = GetDlgItem(hwndDlg, IDC_FIELD);
   hwndOperator = GetDlgItem(hwndDlg, IDC_KEY);
   hwndExpression = GetDlgItem(hwndDlg, IDC_ITEM);

   // Add strings to lists

   for(i=0; i<MAX_FIELDS; i++)
      SendMessage(hwndField, CB_ADDSTRING, 0, (LPARAM)fields[i].name);

   for(i=0; i<MAX_UNARY_STATUS; i++)
      SendMessage(hwndOperator, CB_ADDSTRING, 0, (LPARAM)stUnary[i]);

   // Set controls to first item in list

   SendMessage(hwndField, CB_SETCURSEL, 0, 0);
   SendMessage(hwndOperator, CB_SETCURSEL, 0, 0);

   EnableWindow(hwndOperator, FALSE);
   EnableWindow(hwndExpression, FALSE);
}



/*--------------------------------------------
InitGWSession

  RETURN:   True if succeeded False otherwise
--------------------------------------------*/
BOOL InitGWSession()
{
DIGWAccount* pDIGWAccount;
VARIANT vUserId, vCmdLine, vPassword, vWhenToPrompt, vReserved;


   CoInitialize(NULL);

   // Create the Session Object

   if(FAILED(CoCreateInstance(CLSID_GroupWare, NULL, CLSCTX_INPROC_SERVER |
      CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER, IID_IGWSession, (void**)&pIGWSession))) {
         ErrorMessage("Could not create session object"); 
         return FALSE;
   }

   VariantInit(&vUserId);
   VariantInit(&vCmdLine);
   VariantInit(&vPassword);
   VariantInit(&vWhenToPrompt);
   VariantInit(&vReserved);

   V_VT(&vUserId) = VT_EMPTY;
   V_VT(&vCmdLine) = VT_EMPTY;
   V_VT(&vPassword) = VT_EMPTY;
   V_VT(&vWhenToPrompt) = VT_I2;
   V_VT(&vReserved) = VT_EMPTY;

   V_I2(&vWhenToPrompt) = 0;


   // Login to GW session

   if(!SUCCEEDED(pIGWSession->Login(vUserId, vCmdLine, vPassword, vWhenToPrompt, vReserved, &pDIGWAccount))) {
      ErrorMessage("Couldn't login to session");
      return FALSE;
   }

   // Get the Root Account's Interface

   if(FAILED(pDIGWAccount->QueryInterface(IID_IGWAccount, (LPVOID*)&pIGWAccount))) {
      ErrorMessage("QueryInterface on IID_IGWAccount Failed");
      return FALSE;
   }

   pDIGWAccount->Release();

   return TRUE;
}



/*-------------------------------------
DeinitGWSession

  NOTE:   Cleanup and destory session
      objects before ending.
-------------------------------------*/
void DeinitGWSession()
{
   pIGWAccount->Release();
   pIGWSession->Release();

   CoUninitialize();
}



/*---------------------------------------------
OnFieldSelectionChanged

  IN:   hwndDlg      -   Handle to dialog

  NOTE:   Called whenever the user selects a
      different field to query for.
---------------------------------------------*/
void OnFieldSelectionChanged(HWND hwndDlg)
{
HWND hwndField, hwndOperator, hwndItem;
int i, sel;



   // Get handles to dialog controls

   hwndField = GetDlgItem(hwndDlg, IDC_FIELD);
   hwndOperator = GetDlgItem(hwndDlg, IDC_OPERATOR);
   hwndItem = GetDlgItem(hwndDlg, IDC_ITEM);


   sel = SendMessage(hwndField, CB_GETCURSEL, 0, 0);


   switch(fields[sel].type) {
      case GW_TEXT_FIELD:
         EnableWindow(hwndOperator, TRUE);
         EnableWindow(hwndItem, TRUE);

         SendMessage(hwndOperator, CB_RESETCONTENT, 0, 0);
         SendMessage(hwndItem, CB_RESETCONTENT, 0, 0);

         for(i=0; i<MAX_TEXT_OPERATORS; i++)
            SendMessage(hwndOperator, CB_ADDSTRING, 0, (LPARAM)opText[i]);

         SendMessage(hwndOperator, CB_SETCURSEL, 0, 0);
         break;


      case GW_NUMERIC_FIELD:
         EnableWindow(hwndOperator, TRUE);
         EnableWindow(hwndItem, TRUE);

         SendMessage(hwndOperator, CB_RESETCONTENT, 0, 0);
         SendMessage(hwndItem, CB_RESETCONTENT, 0, 0);

         for(i=0; i<MAX_NUMERIC_OPERATORS; i++)
            SendMessage(hwndOperator, CB_ADDSTRING, 0, (LPARAM)opNumeric[i]);

         SendMessage(hwndOperator, CB_SETCURSEL, 0, 0);
         break;


      case GW_DATE_FIELD:
         SendMessage(hwndOperator, CB_RESETCONTENT, 0, 0);
         SendMessage(hwndItem, CB_RESETCONTENT, 0, 0);

         for(i=0; i<MAX_DATE_OPERATORS; i++)
            SendMessage(hwndOperator, CB_ADDSTRING, 0, (LPARAM)opDate[i]);

         for(i=0; i<MAX_DATE_CONSTANTS; i++)
            SendMessage(hwndItem, CB_ADDSTRING, 0, (LPARAM)cDate[i]);

         SendMessage(hwndOperator, CB_SETCURSEL, 0, 0);
         SendMessage(hwndItem, CB_SETCURSEL, 0, 0);

         EnableWindow(hwndOperator, TRUE);
         EnableWindow(hwndItem, TRUE);
         break;

      case GW_UNARY_FIELD:
         SendMessage(hwndOperator, CB_RESETCONTENT, 0, 0);
         SendMessage(hwndItem, CB_RESETCONTENT, 0, 0);

         for(i=0; i<MAX_UNARY_STATUS; i++)
            SendMessage(hwndOperator, CB_ADDSTRING, 0, (LPARAM)stUnary[i]);

         SendMessage(hwndOperator, CB_SETCURSEL, 0, 0);

         EnableWindow(hwndOperator, FALSE);
         EnableWindow(hwndItem, FALSE);
         break;

      case GW_BOXTYPE_FIELD:
         EnableWindow(hwndOperator, TRUE);
         EnableWindow(hwndItem, TRUE);

         SendMessage(hwndOperator, CB_RESETCONTENT, 0, 0);
         SendMessage(hwndItem, CB_RESETCONTENT, 0, 0);

         for(i=0; i<MAX_BOXTYPE_OPERATORS; i++)
            SendMessage(hwndOperator, CB_ADDSTRING, 0, (LPARAM)opBoxType[i]);


         for(i=0; i<MAX_BOXTYPE_CONSTANTS; i++)
            SendMessage(hwndItem, CB_ADDSTRING, 0, (LPARAM)cBoxType[i]);

         SendMessage(hwndOperator, CB_SETCURSEL, 0, 0);
         SendMessage(hwndItem, CB_SETCURSEL, 0, 0);
         break;

      case GW_PRIORITY_FIELD:
         EnableWindow(hwndOperator, TRUE);
         EnableWindow(hwndItem, TRUE);

         SendMessage(hwndOperator, CB_RESETCONTENT, 0, 0);
         SendMessage(hwndItem, CB_RESETCONTENT, 0, 0);

         for(i=0; i<MAX_PRIORITY_OPERATORS; i++)
            SendMessage(hwndOperator, CB_ADDSTRING, 0, (LPARAM)opPriority[i]);


         for(i=0; i<MAX_PRIORITY_CONSTANTS; i++)
            SendMessage(hwndItem, CB_ADDSTRING, 0, (LPARAM)cPriority[i]);

         SendMessage(hwndOperator, CB_SETCURSEL, 0, 0);
         SendMessage(hwndItem, CB_SETCURSEL, 0, 0);
         break;

      case GW_ATTACHMENT_FIELD:
         EnableWindow(hwndOperator, TRUE);
         EnableWindow(hwndItem, TRUE);

         SendMessage(hwndOperator, CB_RESETCONTENT, 0, 0);
         SendMessage(hwndItem, CB_RESETCONTENT, 0, 0);

         for(i=0; i<MAX_ATTACHTYPE_OPERATORS; i++)
            SendMessage(hwndOperator, CB_ADDSTRING, 0, (LPARAM)opAttachType[i]);


         for(i=0; i<MAX_ATTACHTYPE_CONSTANTS; i++)
            SendMessage(hwndItem, CB_ADDSTRING, 0, (LPARAM)cAttachment[i]);

         SendMessage(hwndOperator, CB_SETCURSEL, 0, 0);
         SendMessage(hwndItem, CB_SETCURSEL, 0, 0);
         break;
   };

}



/*-----------------------------------------
DoQuery

  IN:   hwndDlg      -    Handle to dialog

  NOTE:   Do the query
------------------------------------------*/
void DoQuery(HWND hwndDlg)
{
HWND hwndField, hwndKey, hwndItem;
DIGWQuery* pDIGWQuery;
IGWQuery*pIGWQuery;
char* pszExpression;
char* pszItem;
char szKey[14];
VARIANT_BOOL bCompleted = FALSE;
BSTR bStr;
int fLen, kLen, iLen, fSel, kSel;
HCURSOR hCursor;



   // Create the query object

   pIGWAccount->CreateQuery(&pDIGWQuery);

   if(pDIGWQuery && SUCCEEDED(pDIGWQuery->QueryInterface(IID_IGWQuery, (void**)&pIGWQuery))) {
      pDIGWQuery->Release();

      // Set cursor  to the wait cursor

      hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));

      // Get handles to dialog controls 

      hwndField = GetDlgItem(hwndDlg, IDC_SEARCH);
      hwndKey = GetDlgItem(hwndDlg, IDC_KEY);
      hwndItem = GetDlgItem(hwndDlg, IDC_ITEM);
      


      // Get current selection of field and key selections

      fSel = SendMessage(hwndField, CB_GETCURSEL, 0, 0);
      kSel = SendMessage(hwndKey, CB_GETCURSEL, 0, 0);


      switch(fields[fSel].type) {
         case GW_TEXT_FIELD:
            lstrcpy(szKey, opText[kSel]);
            break;


         case GW_NUMERIC_FIELD:
            lstrcpy(szKey, opNumeric[kSel]);
            break;


         case GW_DATE_FIELD:
            lstrcpy(szKey, opDate[kSel]);
            break;


         case GW_UNARY_FIELD:
            szKey[0] = NULL;
            break;

         case GW_BOXTYPE_FIELD:
            lstrcpy(szKey, opBoxType[kSel]);
            break;

         case GW_PRIORITY_FIELD:
            lstrcpy(szKey, opPriority[kSel]);
            break;

         case GW_ATTACHMENT_FIELD:
            lstrcpy(szKey, opAttachType[kSel]);
            break;

      }

      // How long is the field and item strings

      fLen = lstrlen(fields[fSel].name);
      kLen = lstrlen(szKey);
      iLen = SendMessage(hwndItem, WM_GETTEXTLENGTH, 0, 0) + 1;


      pszItem = new char[iLen];
      pszExpression = new char[fLen + iLen + kLen + 10];


      SendMessage(hwndItem, WM_GETTEXT, iLen, (LPARAM)pszItem);


      // EXAMPLE:

      // (FROM CONTAINS "Mike")

      lstrcpy(pszExpression, "(");
      lstrcat(pszExpression, fields[fSel].name);
      lstrcat(pszExpression, szKey);

      switch(fields[fSel].type) {
         case GW_TEXT_FIELD:
            lstrcat(pszExpression, "\"");
            lstrcat(pszExpression, pszItem);
            lstrcat(pszExpression, "\"");
            break;

         case GW_DATE_FIELD:
         case GW_NUMERIC_FIELD:
         case GW_BOXTYPE_FIELD:
         case GW_PRIORITY_FIELD:
         case GW_ATTACHMENT_FIELD:
            lstrcat(pszExpression, pszItem);
            break;
      }


      lstrcat(pszExpression, ")");
      
      bStr = SysAllocString(TO_OLE_STRING(pszExpression));

      // Put what are we querying for

      pIGWQuery->put_Expression(bStr);

      // Start the query

      pIGWQuery->Start();

      // Loop until query is completed

      while(bCompleted == FALSE) {
         pIGWQuery->get_Completed(&bCompleted);
         pIGWQuery->Refresh();
      }


      ShowResults(hwndDlg, pIGWQuery, pszExpression);

      pIGWQuery->Release();
      delete[] pszExpression;
      delete[] pszItem;

      // Set the cursor back to the original

      SetCursor(hCursor);
   }
}



/*--------------------------------------------------
ShowResults

  IN:   hwndDlg         -   Handle to dialog
      pIGWQuery      -   Query object we created
      pszExpression   -   Expression string

  NOTE:   Show the results of the query
--------------------------------------------------*/
void ShowResults(HWND hwndDlg, IGWQuery* pIGWQuery, char* pszExpression)
{
HWND hwndLView, hwndNFound, hwndExpression;
DIGWMessageList* pDIGWMessageList;
DIGWMessage* pDIGWMessage;
DIGWFormattedText* pDIGWFormattedText;
DIGWFolders* pDIGWFolders;
DIGWFolder* pDIGWFolder;
IGWMessageList* pIGWMessageList;
IGWMessage* pIGWMessage;
IGWFormattedText* pIGWFormattedText;
IGWFolders* pIGWFolders;
IGWFolder* pIGWFolder;
VARIANT vIdx, vDate;
long lCount, fCount;
BSTR bStr;
LV_ITEM lvItem;
DATE crDate;
char num[5];
char szFolders[300];



   // Show only one dialog

   if(!IsWindow(hResultDlg)) {
      hResultDlg = CreateDialog(ghInst, MAKEINTRESOURCE(IDD_RESULTS), hwndDlg, (DLGPROC)ResultDlgProc);
   }

   hwndLView = GetDlgItem(hResultDlg, IDC_RESULTS);
   hwndNFound = GetDlgItem(hResultDlg, IDC_NUMFOUND);
   hwndExpression = GetDlgItem(hResultDlg, IDC_QUERY_EXPRESSION);

   // Delete items from previous query

   ListView_DeleteAllItems(hwndLView);

   // Show the expression on the dialog

   SendMessage(hwndExpression, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pszExpression);

   // Get the messages that match the query

   pIGWQuery->get_QueryMessages(&pDIGWMessageList);

   if(pDIGWMessageList && SUCCEEDED(pDIGWMessageList->QueryInterface(IID_IGWMessageList, (void**)&pIGWMessageList))) {
      pDIGWMessageList->Release();

      // How many messages are there?

      pIGWMessageList->get_Count(&lCount);
      ListView_SetItemCount(hwndLView, lCount);

      ltoa(lCount, num, 10);
      SendMessage(hwndNFound, WM_SETTEXT, 0, (LPARAM)num);

      VariantInit(&vIdx);
      V_VT(&vIdx) = VT_I4;


      for(int i=0; i<lCount; i++) {
         V_I4(&vIdx) = i + 1;
         pIGWMessageList->Item(vIdx, &pDIGWMessage);

         if(pDIGWMessage && SUCCEEDED(pDIGWMessage->QueryInterface(IID_IGWMessage, (void**)&pIGWMessage))) {
            pDIGWMessage->Release();

            lvItem.mask = LVIF_TEXT;
            lvItem.iItem = i;

            //****** View name ****

            pIGWMessage->get_ViewName(&bStr);
            lvItem.iSubItem = 0;
            lvItem.pszText = FROM_OLE_STRING(bStr);
            ListView_InsertItem(hwndLView, &lvItem);
            SysFreeString(bStr);
            bStr = NULL;


            //***** From ******

            pIGWMessage->get_FromText(&bStr);
            ListView_SetItemText(hwndLView, i, 1, FROM_OLE_STRING(bStr));
            SysFreeString(bStr);
            bStr = NULL;


            //****** Subject ******

            pIGWMessage->get_Subject(&pDIGWFormattedText);

            if(pDIGWFormattedText && SUCCEEDED(pDIGWFormattedText->QueryInterface(IID_IGWFormattedText, (void**)&pIGWFormattedText))) {
               pDIGWFormattedText->Release();

               pIGWFormattedText->get_PlainText(&bStr);

               ListView_SetItemText(hwndLView, i, 2, FROM_OLE_STRING(bStr));
               SysFreeString(bStr);
               bStr = NULL;

               pIGWFormattedText->Release();
            }


            //******* Date ********

            pIGWMessage->get_CreationDate(&crDate);

            VariantInit(&vDate);
            V_VT(&vDate) = VT_DATE;
            V_DATE(&vDate) = crDate;

            if(SUCCEEDED(VariantChangeType(&vDate, &vDate, 0, VT_BSTR))) 
               ListView_SetItemText(hwndLView, i, 3, FROM_OLE_STRING(V_BSTR(&vDate)));



            // Folders

            pIGWMessage->get_EnclosingFolders(&pDIGWFolders);

            if(pDIGWFolders && SUCCEEDED(pDIGWFolders->QueryInterface(IID_IGWFolders, (void**)&pIGWFolders))) {
               pDIGWFolders->Release();

               VARIANT fIdx;
               VariantInit(&fIdx);
               V_VT(&fIdx) = VT_I4;

               szFolders[0] = NULL;

               // How many folders are there?

               pIGWFolders->get_Count(&fCount);

               // Get all folders this message is contained in

               for(int n=0; n<fCount; n++) {
                  V_I4(&fIdx) = n + 1;

                  pIGWFolders->Item(fIdx, &pDIGWFolder);

                  if(pDIGWFolder && SUCCEEDED(pDIGWFolder->QueryInterface(IID_IGWFolder, (void**)&pIGWFolder))) {
                     pDIGWFolder->Release();

                     pIGWFolder->get_Name(&bStr);
                     lstrcat(szFolders, FROM_OLE_STRING(bStr));
                     SysFreeString(bStr);
                     bStr = NULL;

                     pIGWFolder->Release();
                  }

               }

               pIGWFolders->Release();
            }

            ListView_SetItemText(hwndLView, i, 4, szFolders);

            // Version

            // Document

            // Library


            pIGWMessage->Release();
         }
      } // for


      pIGWMessageList->Release();
   }

   ShowWindow(hResultDlg, SW_SHOW);
}



/*--------------------------------------------------------------------------------
ResultDlgProc

  IN:         hwndDlg   -   Handle to dialog
            message   -   Message to watch for
            wParam   -   WPARAM
            lParam   -   LPARAM

  RETURN:
---------------------------------------------------------------------------------*/
LONG APIENTRY ResultDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LONG lParam)
{
   switch(message) {
      case WM_INITDIALOG: {
         HWND hwndResults;
         LV_COLUMN col;

         hwndResults = GetDlgItem(hwndDlg, IDC_RESULTS);

         // Insert columns for list view

         col.mask = LVCF_TEXT | LVCF_WIDTH;
         col.cx = 100;

         // Name

         col.pszText = "View Name";
         ListView_InsertColumn(hwndResults, 0, &col);

         // From

         col.pszText = "From";
         ListView_InsertColumn(hwndResults, 1, &col);

         // Subject

         col.pszText = "Subject";
         ListView_InsertColumn(hwndResults, 2, &col);

         // Date

         col.pszText = "Date";
         ListView_InsertColumn(hwndResults, 3, &col);

         // Folder

         col.pszText = "Folder";
         ListView_InsertColumn(hwndResults, 4, &col);

         // Version

         col.pszText = "Version";
         ListView_InsertColumn(hwndResults, 5, &col);

         // Document #

         col.pszText = "Document#";
         ListView_InsertColumn(hwndResults, 6, &col);

         // Library

         col.pszText = "Library";
         ListView_InsertColumn(hwndResults, 7, &col);
         break;
      }

      case WM_COMMAND:
         switch(LOWORD(wParam)) {
            case IDOK:
               DestroyWindow(hwndDlg);
               hResultDlg = 0;
               break;
         }
           break;

      case WM_CLOSE:
         DestroyWindow(hwndDlg);
         hResultDlg = 0;
          break;
   }

   return(0);
}