/*********************************************************************** * * ABSEARCH.C * * Sample AB directory container Search object * * This file contains the code for implementing the Sample AB * directory container search object. Also known as advanced * search. * * This search object was retrieved by OpenProperty on PR_SEARCH on the * AB directory found in ABCONT.C. * * The following routines are implemented in this file: * * HrNewSearch * ABSRCH_Release * ABSRCH_SaveChanges * ABSRCH_OpenProperty * ABSRCH_GetSearchCriteria * * HrGetSearchDialog * * Copyright 1992, 1993, 1994 Microsoft Corporation. All Rights Reserved. * ***********************************************************************/ #include "faxab.h" /* * Proptags used only in this module */ #define PR_ANR_STRING_A PROP_TAG(PT_STRING8,0x6602) /* Display table control structures for the Search property sheet. */ /* * The Sample AB exposes an 'advanced' search dialog. The following * structures define it's layout. */ /* * The edit control that will have the name to be search for on it. */ #define MAX_SEARCH_NAME 50 DTBLEDIT editSearchName = { SIZEOF(DTBLEDIT), 0, MAX_SEARCH_NAME, PR_ANR_STRING_A }; /* * Display table pages for Search property sheet */ DTCTL rgdtctlSearchGeneral[] = { /* * Defines the name of this Pane. */ {DTCT_PAGE, 0, NULL, 0, NULL, 0, &dtblpage}, /* group box control */ {DTCT_GROUPBOX, 0, NULL, 0, NULL, IDC_STATIC_CONTROL, &dtblgroupbox}, /* control and edit control */ {DTCT_LABEL, 0, NULL, 0, NULL, IDC_STATIC_CONTROL, &dtbllabel}, {DTCT_EDIT, DT_EDITABLE, NULL, 0, (LPTSTR)szNoFilter, IDC_SEARCH_NAME, &editSearchName}, }; /* * Actual definition of the set of pages that make up this advanced search * dialog. */ DTPAGE rgdtpageSearch[] = { { ARRAYSIZE(rgdtctlSearchGeneral), (LPTSTR) MAKEINTRESOURCE(SearchGeneralPage), TEXT(""), rgdtctlSearchGeneral } }; /* * ABSearch vtbl is filled in here. */ ABSRCH_Vtbl vtblABSRCH = { (ABSRCH_QueryInterface_METHOD *) ROOT_QueryInterface, (ABSRCH_AddRef_METHOD *) ROOT_AddRef, ABSRCH_Release, (ABSRCH_GetLastError_METHOD *) ROOT_GetLastError, ABSRCH_SaveChanges, (ABSRCH_GetProps_METHOD *) WRAP_GetProps, (ABSRCH_GetPropList_METHOD *) WRAP_GetPropList, ABSRCH_OpenProperty, (ABSRCH_SetProps_METHOD *) WRAP_SetProps, (ABSRCH_DeleteProps_METHOD *) WRAP_DeleteProps, (ABSRCH_CopyTo_METHOD *) WRAP_CopyTo, (ABSRCH_CopyProps_METHOD *) WRAP_CopyProps, (ABSRCH_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs, (ABSRCH_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames, (ABSRCH_GetContentsTable_METHOD *) ROOT_GetContentsTable, (ABSRCH_GetHierarchyTable_METHOD *) ABC_GetHierarchyTable, (ABSRCH_OpenEntry_METHOD *) ROOT_OpenEntry, (ABSRCH_SetSearchCriteria_METHOD *) ROOT_SetSearchCriteria, ABSRCH_GetSearchCriteria, }; HRESULT HrGetSearchDialog(LPABSRCH lpABSearch, LPMAPITABLE * lppSearchTable); /* - HrNewSearch - * Creates an advanced search object * * */ /* * Properties that are initially set on this object */ enum { ivalabsrchPR_ANR_STRING = 0, cvalabsrchMax }; HRESULT HrNewSearch( LPMAPICONTAINER * lppABSearch, LPABLOGON lpABLogon, LPCIID lpInterface, HINSTANCE hLibrary, LPALLOCATEBUFFER lpAllocBuff, LPALLOCATEMORE lpAllocMore, LPFREEBUFFER lpFreeBuff, LPMALLOC lpMalloc ) { HRESULT hResult = hrSuccess; LPABSRCH lpABSearch = NULL; SCODE sc; LPPROPDATA lpPropData = NULL; SPropValue spv[cvalabsrchMax]; /* Do I support this interface?? */ if (lpInterface) { if ( memcmp(lpInterface, &IID_IMAPIContainer, SIZEOF(IID)) && memcmp(lpInterface, &IID_IMAPIProp, SIZEOF(IID)) && memcmp(lpInterface, &IID_IUnknown, SIZEOF(IID)) ) { DebugTraceSc(HrNewSearch, MAPI_E_INTERFACE_NOT_SUPPORTED); return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED); } } /* * Allocate space for the directory container structure */ sc = lpAllocBuff( SIZEOF(ABSRCH), (LPVOID *) &lpABSearch ); if (FAILED(sc)) { hResult = ResultFromScode(sc); goto err; } lpABSearch->lpVtbl = &vtblABSRCH; lpABSearch->lcInit = 1; lpABSearch->hResult = hrSuccess; lpABSearch->idsLastError = 0; lpABSearch->hLibrary = hLibrary; lpABSearch->lpAllocBuff = lpAllocBuff; lpABSearch->lpAllocMore = lpAllocMore; lpABSearch->lpFreeBuff = lpFreeBuff; lpABSearch->lpMalloc = lpMalloc; lpABSearch->lpABLogon = lpABLogon; lpABSearch->lpRestrictData = NULL; /* * Create property storage object */ sc = CreateIProp((LPIID) &IID_IMAPIPropData, lpAllocBuff, lpAllocMore, lpFreeBuff, lpMalloc, &lpPropData); if (FAILED(sc)) { hResult = ResultFromScode(sc); goto err; } spv[ivalabsrchPR_ANR_STRING].ulPropTag = PR_ANR_STRING_A; spv[ivalabsrchPR_ANR_STRING].Value.lpszA = ""; /* * Set the default properties */ hResult = lpPropData->lpVtbl->SetProps(lpPropData, cvalabsrchMax, spv, NULL); InitializeCriticalSection(&lpABSearch->cs); lpABSearch->lpPropData = (LPMAPIPROP) lpPropData; *lppABSearch = (LPMAPICONTAINER) lpABSearch; out: DebugTraceResult(HrNewSearch, hResult); return hResult; err: /* * free the ABContainer object */ lpFreeBuff( lpABSearch ); /* * free the property storage object */ if (lpPropData) lpPropData->lpVtbl->Release(lpPropData); goto out; } /* - ABSRCH_Release - * Decrement lcInit. * When lcInit == 0, free up the lpABSearch structure * */ STDMETHODIMP_(ULONG) ABSRCH_Release(LPABSRCH lpABSearch) { long lcInit; /* * Check to see if it has a jump table */ if (IsBadReadPtr(lpABSearch, SIZEOF(ABSRCH))) { /* * No jump table found */ return 1; } /* * Check to see that it's the correct jump table */ if (lpABSearch->lpVtbl != &vtblABSRCH) { /* * Not my jump table */ return 1; } EnterCriticalSection(&lpABSearch->cs); lcInit = --lpABSearch->lcInit; LeaveCriticalSection(&lpABSearch->cs); if (lcInit == 0) { /* * Get rid of the lpPropData */ if (lpABSearch->lpPropData) lpABSearch->lpPropData->lpVtbl->Release(lpABSearch->lpPropData); /* * Free up the restriction data */ lpABSearch->lpFreeBuff(lpABSearch->lpRestrictData); /* * Destroy the critical section for this object */ DeleteCriticalSection(&lpABSearch->cs); /* * Set the Jump table to NULL. This way the client will find out * real fast if it's calling a method on a released object. That is, * the client will crash. Hopefully, this will happen during the * development stage of the client. */ lpABSearch->lpVtbl = NULL; /* * Need to free the object */ lpABSearch->lpFreeBuff(lpABSearch); return 0; } return lpABSearch->lcInit; } /* - ABSRCH_SaveChanges - * This is used to save changes associated with the search dialog * in order to get the advanced search restriction and to save changes * associated with the container details dialog. * */ SPropTagArray tagaANR_INT = { 1, { PR_ANR_STRING_A } }; STDMETHODIMP ABSRCH_SaveChanges(LPABSRCH lpABSearch, ULONG ulFlags) { HRESULT hResult; ULONG ulCount; LPSPropValue lpspv = NULL; LPPROPDATA lpPropData = (LPPROPDATA) lpABSearch->lpPropData; /* * Check to see if it has a jump table */ if (IsBadReadPtr(lpABSearch, SIZEOF(ABSRCH))) { /* * No jump table found */ hResult = ResultFromScode(E_INVALIDARG); return hResult; } /* * Check to see that it's the correct jump table */ if (lpABSearch->lpVtbl != &vtblABSRCH) { /* * Not my jump table */ hResult = ResultFromScode(E_INVALIDARG); return hResult; } EnterCriticalSection(&lpABSearch->cs); /* * Is there a PR_ANR_STRING?? */ hResult = lpPropData->lpVtbl->GetProps(lpPropData, &tagaANR_INT, 0, /* ansi */ &ulCount, &lpspv); if (HR_FAILED(hResult)) { goto ret; } if ((lpspv->ulPropTag == PR_ANR_STRING_A) && (lpspv->Value.lpszA != '\0')) { /* * save away the information to build up the new restriction */ /* Free any existing data */ if (lpABSearch->lpRestrictData) { lpABSearch->lpFreeBuff(lpABSearch->lpRestrictData); } lpABSearch->lpRestrictData = lpspv; lpspv = NULL; } ret: LeaveCriticalSection(&lpABSearch->cs); lpABSearch->lpFreeBuff(lpspv); DebugTraceResult(ABSRCH_SaveChanges, hResult); return hResult; } /************************************************************************* * - ABSRCH_OpenProperty - * * This method allows the opening of the following object: * * PR_DETAILS_TABLE :- Gets the display table associated with * the advanced search dialog. */ STDMETHODIMP ABSRCH_OpenProperty( LPABSRCH lpABSearch, ULONG ulPropTag, LPCIID lpiid, ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN * lppUnk ) { HRESULT hResult; /* * Check to see if it's big enough to be this object */ if (IsBadReadPtr(lpABSearch, SIZEOF(ABSRCH))) { /* * Not big enough to be this object */ hResult = ResultFromScode(E_INVALIDARG); goto out; } /* * Check to see that it's the correct vtbl */ if (lpABSearch->lpVtbl != &vtblABSRCH) { /* * Not my vtbl */ hResult = ResultFromScode(E_INVALIDARG); goto out; } if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN))) { /* * Got to be able to return an object */ hResult = ResultFromScode(E_INVALIDARG); goto out; } if (IsBadReadPtr(lpiid, (UINT) SIZEOF(IID))) { /* * An interface ID is required for this call. */ hResult = ResultFromScode(E_INVALIDARG); goto out; } /* * check for unknown flags */ if (ulFlags & ~(MAPI_DEFERRED_ERRORS | MAPI_CREATE | MAPI_MODIFY)) { hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS); goto out; } /* * Check for flags we can't support */ if (ulFlags & (MAPI_CREATE|MAPI_MODIFY)) { hResult = ResultFromScode(E_ACCESSDENIED); goto out; } if (ulInterfaceOptions & ~MAPI_UNICODE) { /* * Only UNICODE flag should be set for any of the objects that might * be returned from this object. */ hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS); goto out; } if ( ulInterfaceOptions & MAPI_UNICODE ) { hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH ); DebugTraceArg( ABSRCH_OpenProperty, "bad character width" ); goto out; } /* * Details for this Search object */ if (ulPropTag == PR_DETAILS_TABLE) { if (!memcmp(lpiid, &IID_IMAPITable, SIZEOF(IID))) { hResult = HrGetSearchDialog(lpABSearch, (LPMAPITABLE *) lppUnk); goto out; } } hResult = ResultFromScode(MAPI_E_NO_SUPPORT); out: DebugTraceResult(ABSRCH_OpenProperty, hResult); return hResult; } /* - ABSRCH_GetSearchCriteria - * Generates the restriction associated with the data from * the advanced search dialog. This restriction is subsequently * applied to the contents table retrieved from this container. */ STDMETHODIMP ABSRCH_GetSearchCriteria( LPABSRCH lpABSearch, ULONG ulFlags, LPSRestriction FAR * lppRestriction, LPENTRYLIST FAR * lppContainerList, ULONG FAR * lpulSearchState ) { HRESULT hResult = hrSuccess; SCODE sc; LPSRestriction lpRestriction = NULL; LPSPropValue lpPropANR = NULL; LPSTR lpszPartNameA; LPSTR lpszRestrNameA; /* * Check to see if it's large enough to be my object */ if (IsBadReadPtr(lpABSearch, SIZEOF(ABSRCH))) { /* * Not large enough */ hResult = ResultFromScode(E_INVALIDARG); DebugTraceResult(ABSRCH_GetSearchCriteria, hResult); return hResult; } /* * Check to see that it's the correct vtbl */ if (lpABSearch->lpVtbl != &vtblABSRCH) { /* * Not my vtbl */ hResult = ResultFromScode(E_INVALIDARG); DebugTraceResult(ABSRCH_GetSearchCriteria, hResult); return hResult; } /* * Check out parameters */ if ( ulFlags & ~(MAPI_UNICODE) ) { hResult = ResultFromScode( MAPI_E_UNKNOWN_FLAGS ); DebugTraceResult(ABSRCH_GetSearchCriteria, hResult); return hResult; } if ( ulFlags & MAPI_UNICODE ) { DebugTraceArg( ABSRCH_GetSearchCriteria, "bad character width" ); return ResultFromScode( MAPI_E_BAD_CHARWIDTH ); } if (IsBadWritePtr(lppRestriction, SIZEOF(LPSRestriction))) { hResult = ResultFromScode(E_INVALIDARG); DebugTraceResult(ABSRCH_GetSearchCriteria, hResult); return hResult; } if (lpulSearchState && IsBadWritePtr(lpulSearchState, SIZEOF(ULONG))) { hResult = ResultFromScode(E_INVALIDARG); DebugTraceResult(ABSRCH_GetSearchCriteria, hResult); return hResult; } if (lppContainerList && IsBadWritePtr(lppContainerList, SIZEOF(LPENTRYLIST))) { hResult = ResultFromScode(E_INVALIDARG); DebugTraceResult(ABSRCH_GetSearchCriteria, hResult); return hResult; } if (!lpABSearch->lpRestrictData) { hResult = ResultFromScode(MAPI_E_NOT_INITIALIZED); if (lppRestriction) *lppRestriction = NULL; if (lppContainerList) *lppContainerList = NULL; if (lpulSearchState) *lpulSearchState = 0L; DebugTraceResult(ABSRCH_GetSearchCriteria, hResult); return hResult; } /* * Entering state dependant section */ EnterCriticalSection(&lpABSearch->cs); /* * Ok, now build up a restriction using lpRestrictData (an LPSPropValue) */ sc = lpABSearch->lpAllocBuff(SIZEOF(SRestriction), &lpRestriction); if (FAILED(sc)) { hResult = ResultFromScode(sc); goto err; } sc = lpABSearch->lpAllocMore(SIZEOF(SPropValue), lpRestriction, &lpPropANR); if (FAILED(sc)) { hResult = ResultFromScode(sc); goto err; } lpszRestrNameA = lpABSearch->lpRestrictData->Value.lpszA; sc = lpABSearch->lpAllocMore( lstrlenA(lpszRestrNameA)+1, lpRestriction, &lpszPartNameA ); if (FAILED(sc)) { hResult = ResultFromScode(sc); goto err; } lstrcpyA(lpszPartNameA, lpszRestrNameA); lpPropANR->ulPropTag = PR_ANR_A; lpPropANR->Value.lpszA = lpszPartNameA; lpRestriction->rt = RES_PROPERTY; lpRestriction->res.resProperty.relop = RELOP_EQ; lpRestriction->res.resProperty.ulPropTag = PR_ANR_A; lpRestriction->res.resProperty.lpProp = lpPropANR; *lppRestriction = lpRestriction; /* * The returned SearchState is set to 0 because none * of the defined states match what's going on. */ if (lpulSearchState) *lpulSearchState = 0; out: LeaveCriticalSection(&lpABSearch->cs); DebugTraceResult(ABSRCH_GetSearchCriteria, hResult); return hResult; err: lpABSearch->lpFreeBuff(lpRestriction); goto out; } /* - HrGetSearchDialog - * * Builds a display table for the search dialog. */ HRESULT HrGetSearchDialog(LPABSRCH lpABSearch, LPMAPITABLE * lppSearchTable) { HRESULT hResult; /* Create a display table */ hResult = BuildDisplayTable( lpABSearch->lpAllocBuff, lpABSearch->lpAllocMore, lpABSearch->lpFreeBuff, lpABSearch->lpMalloc, lpABSearch->hLibrary, ARRAYSIZE(rgdtpageSearch), rgdtpageSearch, 0, lppSearchTable, NULL); DebugTraceResult(ABSRCH_GetSearchDialog, hResult); return hResult; }