windows-nt/Source/XPSP1/NT/enduser/stuff/itircl/wrdwheel/local/wwimp.cpp
2020-09-26 16:20:57 +08:00

849 lines
24 KiB
C++

/*************************************************************************
* @doc SHROOM EXTERNAL API *
* *
* WWIMP.CPP *
* *
* Copyright (C) Microsoft Corporation 1997 *
* All Rights reserved. *
* *
* This file contains CITWordWheelLocal, the local implementation *
* of IITWordWheel *
* *
**************************************************************************
* *
* Written By : Erin Foxford *
* Current Owner: erinfox *
* *
*
* TODO TODO TODO: Replace the blind use of critical sections with a
* better way of ensuring thread-safeness while preserving performance.
* But for now, in the interest of coding time, we just make sure the
* code is thread-safe.
*
**************************************************************************/
#include <mvopsys.h>
#ifdef _DEBUG
static char s_aszModule[] = __FILE__; /* For error report */
#endif
#include <atlinc.h> // includes for ATL.
// MediaView (InfoTech) includes
#include <groups.h>
#include <wwheel.h>
#include "itcat.h" // catalog
#include "itcc.h" // needed for STDPROP_SORTKEY def.
#include "ITPropl.h" // property list
#include "itrs.h" // result set
#include "itquery.h" // query and index
#include <ccfiles.h>
#include "ITDB.h"
#include "DBImp.h"
#include "itww.h"
#include "WWImp.h"
#include "itgroup.h"
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | Open |
* Opens a word wheel
* @parm IITDatabase* | lpITDB | Pointer to database object
* @parm LPCWSTR | lpszMoniker | Name of word wheel
* @parm DWORD | dwFlags | One or more of the following values:
* @flag ITWW_OPEN_CONNECT | If the wordwheel resides on a remote machine,
* connect to the machine during this call to retrieve initialization data. Otherwise
* the connection is delayed until the first API call which requires this data.
*
* @rvalue E_INVALIDARG | IITDatabase* or lpszMoniker was NULL
* @rvalue E_ALREADYOPEN | Word wheel is already open
* @rvalue E_GETLASTERROR | An I/O or transport operation failed. Call the Win32
* GetLastError function to retrieve the error code.
* @rvalue STG_E_* | Any of the IStorage errors that could while opening a storage
* @rvalue S_OK | The word wheel was successfully opened
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::Open(IITDatabase* lpITDB, LPCWSTR lpszMoniker, DWORD dwFlags)
{
HRESULT hr;
LPWSTR szStorageName;
if (NULL == lpITDB || NULL == lpszMoniker)
return E_POINTER;
// TODO: Report error or close word wheel if it's already open ?
if (m_hWheel || m_pSubStorage)
return E_ALREADYOPEN;
m_cs.Lock();
// Open substorage and pass to word wheel
szStorageName = new WCHAR [CCH_MAX_OBJ_NAME + CCH_MAX_OBJ_STORAGE + 1];
WSTRCPY (szStorageName, SZ_WW_STORAGE);
if (WSTRLEN (lpszMoniker) <= CCH_MAX_OBJ_NAME)
WSTRCAT (szStorageName, lpszMoniker);
else
{
MEMCPY (szStorageName, lpszMoniker, CCH_MAX_OBJ_NAME * sizeof (WCHAR));
szStorageName [CCH_MAX_OBJ_NAME + CCH_MAX_OBJ_STORAGE] = (WCHAR)'\0';
}
if (SUCCEEDED(hr = lpITDB->GetObjectPersistence(szStorageName,
IITDB_OBJINST_NULL,
(LPVOID *) &m_pSubStorage, FALSE)))
{
// Open word wheel
m_hWheel = WordWheelOpen(lpITDB, m_pSubStorage, &hr);
}
delete szStorageName;
if (m_hWheel == NULL || FAILED(hr))
{
exit0:
if (m_pSubStorage != NULL)
{
m_pSubStorage->Release();
m_pSubStorage = NULL;
}
m_cs.Unlock();
return hr;
}
// NOTE:
// If the client wants to load a group into the word wheel for filtering,
// s/he must first call the "Open" method of ITWordWheel, then create
// a group (these two steps may be interchanged), then call the "SetGroup"
// method of ITWordWheel.
// Store count
m_cEntries = m_cMaxEntries = WordWheelLength(m_hWheel, &hr);
// Open catalog object - we only need one instance
hr = CoCreateInstance(CLSID_IITCatalogLocal, NULL, CLSCTX_INPROC_SERVER, IID_IITCatalog,
(VOID **) &m_pCatalog);
if (FAILED(hr))
goto exit0;
// If we can't open the catalog hat's OK because we can run
// without it.
if (FAILED(m_pCatalog->Open(lpITDB)))
{
m_pCatalog->Release();
m_pCatalog = NULL;
}
m_cs.Unlock();
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | Close |
* Closes a word wheel
*
* @rvalue S_OK | The word wheel was successfully closed
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::Close(void)
{
m_cs.Lock();
if (m_hWheel)
{
WordWheelClose(m_hWheel);
m_hWheel = NULL;
}
else
return E_NOTINIT;
if (m_pSubStorage)
{
m_pSubStorage->Release();
m_pSubStorage = NULL;
}
if (m_pCatalog)
{
m_pCatalog->Close();
m_pCatalog->Release();
m_pCatalog = NULL;
}
if (m_hScratchBuffer)
{
_GLOBALFREE(m_hScratchBuffer);
m_hScratchBuffer = NULL;
}
m_cbScratchBuffer = 0;
if (m_pIITGroup != NULL)
{
m_pIITGroup->Release();
m_pIITGroup = NULL;
}
m_cs.Unlock();
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | GetLocaleInfo |
* Gets locale info that the word wheel was built with.
* @parm DWORD* | pdwCodePageID | On exit, pointer to code page ID.
* @parm LCID* | plcid | On exit, pointer to locale ID.
*
* @rvalue S_OK | The locale info was successfully retrieved.
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::GetLocaleInfo(DWORD *pdwCodePageID, LCID *plcid)
{
HRESULT hr = S_OK;
PWHEEL pwheel = NULL;
if (pdwCodePageID == NULL || plcid == NULL)
return (SetErrReturn(E_POINTER));
if (m_hWheel == NULL)
return (E_NOTOPEN);
m_cs.Lock();
// validate the parameters and lock down the structure
if ((pwheel = (PWHEEL)_GLOBALLOCK(m_hWheel)) != NULL &&
PWHEEL_OK(pwheel))
{
BTREE_PARAMS btp;
GetBtreeParams(pwheel->pInfo->hbt, &btp);
*pdwCodePageID = btp.dwCodePageID;
*plcid = btp.lcid;
}
else
hr = E_UNEXPECTED;
if (pwheel != NULL)
_GLOBALUNLOCK(m_hWheel);
m_cs.Unlock();
return (hr);
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | GetSorterInstance |
* Get the ID of the sorter instance being used by the
* word wheel
*
* @parm DWORD* | pdwObjInstance | Pointer to sorter instance ID
*
* @rvalue E_NOTOPEN | The word wheel has not been opened
* @rvalue E_POINTER | pdwObjInstance was an invalid pointer
* @rvalue S_OK | The sorter instance ID was successfully obtained
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::GetSorterInstance(DWORD *pdwObjInstance)
{
HRESULT hr = S_OK;
PWHEEL pwheel = NULL;
if (m_hWheel == NULL)
return (E_NOTOPEN);
if (pdwObjInstance == NULL)
return (E_POINTER);
m_cs.Lock();
// validate the parameters and lock down the structure
if ((pwheel = (PWHEEL)_GLOBALLOCK(m_hWheel)) != NULL &&
PWHEEL_OK(pwheel))
{
BTREE_PARAMS btp;
GetBtreeParams(pwheel->pInfo->hbt, &btp);
*pdwObjInstance =
(btp.rgchFormat[0] == KT_EXTSORT ? btp.dwExtSortInstID :
IITDB_OBJINST_NULL);
}
else
hr = E_UNEXPECTED;
if (pwheel != NULL)
_GLOBALUNLOCK(m_hWheel);
m_cs.Unlock();
return (hr);
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | Count |
* Returns number of entries in word wheel through pcEntries
*
* @parm LONG* | pcEntries | Number of entries in word wheel
*
* @rvalue E_NOTOPEN | The word wheel has not been opened
* @rvalue E_POINTER | pcEntries was an invalid pointer
* @rvalue S_OK | The count was successfully returned
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::Count(LONG *pcEntries)
{
if (NULL == m_hWheel)
return E_NOTOPEN;
if (NULL == pcEntries)
return E_POINTER;
*pcEntries = m_cEntries;
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | Lookup |
* Looks up an entry and returns contents in a buffer
*
* @parm LONG | lEntry | Entry to look up
* @parm LPVOID | lpvKeyBuf | Buffer to return entry
* @parm DWORD | cbKeyBuf | Buffer size in number of bytes
*
* @rvalue E_OUTOFRANGE | Entry number is out of range
* @rvalue S_OK | The word wheel entry was successfully returned
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::Lookup(LONG lEntry, LPVOID lpvKeyBuf, DWORD cbKeyBuf)
{
if (NULL == m_hWheel)
return E_NOTOPEN;
if (NULL == lpvKeyBuf)
return E_POINTER;
m_cs.Lock();
HRESULT hr = WordWheelLookup(m_hWheel, lEntry, lpvKeyBuf, cbKeyBuf);
m_cs.Unlock();
return hr;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | Lookup |
* Looks up an entry and returns contents as a result set
*
* @parm LONG | lEntry | Entry to look up
* @parm IITResultList* | lpITResult | Pointer to result set to fill
* @parm LONG | cEntries | Number of entries to fill result set
*
* @rvalue E_INVALIDARG | Invalid argument was passed (cEntries <lt>= 0 or lpITResult
* is NULL)
* @rvalue E_OUTOFRANGE | The entry does not exist in the word wheel
* @rvalue S_OK | The word wheel entry was successfully returned
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::Lookup(LONG lEntry, IITResultSet* lpITResult, LONG cEntries)
{
PWHEEL pWheel = NULL; // pointer to locked-down structure
PWHEELINFO pInfo = NULL;
BYTE Key[ITWW_CBKEY_MAX];
BYTE DataBuffer[8];
DWORD dwOffset; // Offset into data file
DWORD cbRead;
LPBYTE pPropBuffer = NULL;
LARGE_INTEGER dlibMove; // For seeking
ULARGE_INTEGER libNewPos;
IITSortKey *pITSortKey = NULL;
LONG iRow;
LONG iColumn;
LONG iEntry; // Loop index
LONG lMaxEntry;
HRESULT hr;
if (NULL == m_hWheel)
return E_NOTOPEN;
if (NULL == lpITResult)
return E_POINTER;
m_cs.Lock();
// validate the parameters and lock down the structure
if ((pWheel = (PWHEEL)_GLOBALLOCK(m_hWheel))==NULL ||
!PWHEEL_OK(pWheel))
{
hr = E_INVALIDSTATE;
warning_abort;
}
pInfo = pWheel->pInfo;
// if result set is empty, add columns based on header
lpITResult->GetColumnCount(iColumn);
if (0 == iColumn)
{
lpITResult->Add(STDPROP_SORTKEY, (LPWSTR) NULL, PRIORITY_NORMAL);
if (pInfo->pKeyHdr)
lpITResult->Add(pInfo->pKeyHdr);
}
// Check for a btree key type that the word wheel supports and set
// pITSortKey.
if (FAILED(hr = CheckWordWheelKeyType(pInfo->hbt, &pITSortKey)))
assert_abort;
lMaxEntry = lEntry + cEntries;
for (iEntry = lEntry; iEntry < lMaxEntry ; iEntry++)
{
DWORD cbKeyData = 0L; // Amount of data in key property
// exceeded entries in word wheel
if (iEntry >= m_cEntries)
break;
// If there's a filter, let's get the proper entry in the WW.
if (!m_pIITGroup)
lEntry = iEntry;
else
{
hr = m_pIITGroup->FindTopicNum((DWORD)iEntry, (DWORD*)(&lEntry));
if (FAILED(hr))
goto cleanup;
else if (S_FALSE == hr) // not found
break;
}
// lookup the entry in the map file
hr = RcKeyFromIndexHbt(pInfo->hbt, pInfo->hmapbt,
(KEY)Key, ITWW_CBKEY_MAX, lEntry);
if (FAILED(hr))
goto cleanup;
// lookup data associated w/ key
hr = RcLookupByKey(pInfo->hbt, (KEY)Key, NULL, DataBuffer);
if (FAILED(hr))
goto cleanup;
dwOffset = *(LPDWORD) &DataBuffer[4];
// get data from data file
// seek to get offset into data file where key
// properties reside
dlibMove.QuadPart = dwOffset;
hr = (pInfo->hf)->Seek(dlibMove, STREAM_SEEK_SET, &libNewPos);
if (FAILED(hr))
goto cleanup;
// read in amount of key data
hr = (pInfo->hf)->Read(&cbKeyData, sizeof(DWORD), &cbRead);
if (FAILED(hr))
goto cleanup;
// get current last row so we can set the data there
lpITResult->GetRowCount(iRow);
// Set key. Note that GetColumnFromPropID might return error
// if caller didn't specify STDPROP_SORTKEY.
if (SUCCEEDED(hr = lpITResult->GetColumnFromPropID(STDPROP_SORTKEY, iColumn)))
lpITResult->Set(iRow, iColumn, (LPVOID) Key,
CbKeyWordWheel((LPVOID) Key, pITSortKey));
if (cbKeyData)
{
// read the data
hr = ReallocBufferHmem
(&m_hScratchBuffer, &m_cbScratchBuffer, cbKeyData);
if (FAILED(hr))
goto cleanup;
if(NULL == (pPropBuffer = (BYTE *)_GLOBALLOCK(m_hScratchBuffer)))
{
hr = E_OUTOFMEMORY;
goto cleanup;
}
hr = (pInfo->hf)->Read(pPropBuffer, cbKeyData, &cbRead);
// Even if Set(iRow...) fails, set other properties, if there are any
// TODO: This function may need optimization
lpITResult->Set(iRow, pInfo->pKeyHdr, pPropBuffer);
_GLOBALUNLOCK(m_hScratchBuffer);
}
}
cleanup:
if (NULL != pWheel)
_GLOBALUNLOCK(m_hWheel);
if (pITSortKey != NULL)
pITSortKey->Release();
m_cs.Unlock();
return hr;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | Lookup |
* Returns word wheel entry closest to given prefix
*
* @parm LPCVOID | lpcvPrefix | Prefix to look up
* @parm BOOL | fExactMatch | TRUE if prefix must have exact match; FALSE otherwise
* @parm LONG* | plEntry | Entry into word wheel with closest match
*
* @rvalue E_NOTEXIST | The prefix doesn't exist; returned when fExactMatch is set
* to TRUE and there is no match.
* @rvalue E_POINTER | Either lpcvPrefix or pcEntries was an invalid pointer
* @rvalue S_OK | The entry was successfully returned
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::Lookup(LPCVOID lpcvPrefix, BOOL fExactMatch,
LONG *plEntry)
{
HRESULT hr;
if (NULL == m_hWheel)
return E_NOTOPEN;
if (NULL == lpcvPrefix || NULL == plEntry)
return E_POINTER;
m_cs.Lock();
*plEntry = WordWheelPrefix(m_hWheel, lpcvPrefix, fExactMatch, &hr);
m_cs.Unlock();
return hr;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | GetDataCount |
* Returns number of occurrences associated with given word wheel entry
*
* @parm LONG | lEntry | Entry into word wheel
* @parm DWORD* | pdwCount | Number of occurrences
*
* @rvalue E_NOTEXIST | Entry number is not in the valid range
* @rvalue S_OK | The entry was successfully returned
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::GetDataCount(LONG lEntry, DWORD *pdwCount)
{
HRESULT hr = S_OK;
BYTE Key[ITWW_CBKEY_MAX];
BYTE DataBuffer[8];
if (NULL == m_hWheel)
return E_NOTOPEN;
if (NULL == pdwCount)
return E_POINTER;
m_cs.Lock();
PWHEEL pWheel = (PWHEEL)_GLOBALLOCK(m_hWheel);
PWHEELINFO pInfo = pWheel->pInfo;
if (pWheel->pIITGroup)
{
hr = (pWheel->pIITGroup)->FindTopicNum((DWORD)lEntry, (DWORD*)(&lEntry));
if (FAILED(hr))
goto cleanup;
}
// lookup the entry in the map file
hr = RcKeyFromIndexHbt(pInfo->hbt, pInfo->hmapbt,
(KEY)Key, ITWW_CBKEY_MAX, lEntry);
if (FAILED(hr))
goto cleanup;
// lookup some data (count) associated w/ key
hr = RcLookupByKey(pInfo->hbt, (KEY)Key, NULL, DataBuffer);
if (FAILED(hr))
goto cleanup;
*pdwCount = *(LPDWORD) DataBuffer;
cleanup:
if (NULL != pWheel)
_GLOBALUNLOCK(m_hWheel);
m_cs.Unlock();
return hr;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | GetData |
* Fills given result set with rows corresponding to user data
*
* @parm LONG | lEntry | Entry
* @parm IITResultSet* | lpITResult | Pointer to result set object to fill
*
* @rvalue E_INVALIDARG | Result set pointer cannot be NULL
* @rvalue E_NOTEXIST | Entry number is not in the valid range
* @rvalue E_OUTOFMEMORY | Memory allocation failed
* @rvalue S_OK | The entry was successfully returned
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::GetData(LONG lEntry, IITResultSet* lpITResult)
{
BYTE Key[ITWW_CBKEY_MAX];
BYTE DataBuffer[8];
DWORD dwCount; // Number of occurrences
DWORD dwOffset; // Offset into data file
LARGE_INTEGER dlibMove; // For seeking
ULARGE_INTEGER libNewPos;
DWORD cbPropSize;
LPBYTE pPropBuffer = NULL;
DWORD cbRead;
LONG iColumn;
DWORD iRow; // Loop index
HRESULT hr = S_OK;
if (NULL == m_hWheel)
return E_NOTOPEN;
if (NULL == lpITResult)
return E_POINTER;
m_cs.Lock();
PWHEEL pWheel = (PWHEEL)_GLOBALLOCK(m_hWheel);
PWHEELINFO pInfo = pWheel->pInfo;
// if result set is empty, add columns based on header
// also add columns passed on catalog header
lpITResult->GetColumnCount(iColumn);
if (0 == iColumn)
{
lpITResult->Add(pInfo->pOccHdr);
if (m_pCatalog)
m_pCatalog->GetColumns(lpITResult);
}
if (pWheel->pIITGroup)
{
hr = (pWheel->pIITGroup)->FindTopicNum((DWORD)lEntry, (DWORD*)(&lEntry));
if (FAILED(hr))
goto cleanup;
}
// lookup the entry in the map file
hr = RcKeyFromIndexHbt(pInfo->hbt, pInfo->hmapbt,
(KEY)Key, ITWW_CBKEY_MAX, lEntry);
if (FAILED(hr))
goto cleanup;
// lookup some data (count and offset into data file) associated w/ key
hr = RcLookupByKey(pInfo->hbt, (KEY)Key, NULL, DataBuffer);
if (FAILED(hr))
goto cleanup;
dwCount = *(LPDWORD) DataBuffer;
dwOffset = *(LPDWORD) &DataBuffer[4];
// get data from data file
// seek to get offset into data file where key
// properties reside and find out how much to skip
dlibMove.QuadPart = dwOffset;
hr = (pInfo->hf)->Seek(dlibMove, STREAM_SEEK_SET, &libNewPos);
if (FAILED(hr))
goto cleanup;
DWORD dwDataOffset;
hr = (pInfo->hf)->Read(&dwDataOffset, sizeof(DWORD), &cbRead);
if (FAILED(hr))
goto cleanup;
// Seek to where data properties start
dlibMove.QuadPart = dwDataOffset;
hr = (pInfo->hf)->Seek(dlibMove, STREAM_SEEK_CUR, &libNewPos);
if (FAILED(hr))
goto cleanup;
// Loop over all properties - get size, then read in property info into
// memory block
for (iRow = 0; iRow < dwCount; iRow++)
{
hr = (pInfo->hf)->Read(&cbPropSize, sizeof(DWORD), &cbRead);
if (FAILED(hr))
goto cleanup;
hr = ReallocBufferHmem
(&m_hScratchBuffer, &m_cbScratchBuffer, cbPropSize);
if (FAILED(hr))
goto cleanup;
if(NULL == (pPropBuffer = (BYTE *)_GLOBALLOCK(m_hScratchBuffer)))
{
hr = E_OUTOFMEMORY;
goto cleanup;
}
hr = (pInfo->hf)->Read(pPropBuffer, cbPropSize, &cbRead);
if(SUCCEEDED(hr))
// pass header and data to append to result set
// TODO: This function may need optimization
hr = lpITResult->Append(pInfo->pOccHdr, pPropBuffer);
_GLOBALUNLOCK(m_hScratchBuffer);
if (FAILED(hr))
goto cleanup;
}
// Then fill result set w/ any properties that might be in catalog
if (m_pCatalog)
hr = m_pCatalog->Lookup(lpITResult);
// if (S_FALSE == hr)
hr = S_OK; // don't report S_FALSE
cleanup:
if (NULL != pWheel)
_GLOBALUNLOCK(m_hWheel);
m_cs.Unlock();
return hr;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | GetDataColumns |
* Adds columns to given result set for all data properties
*
* @parm IITResultSet* | pRS | Pointer to result set
*
* @rvalue S_OK | The columns were successfully added
*
********************************************************************/
STDMETHODIMP CITWordWheelLocal::GetDataColumns(IITResultSet* pRS)
{
PWHEEL pWheel = (PWHEEL)_GLOBALLOCK(m_hWheel);
PWHEELINFO pInfo = pWheel->pInfo;
if (pRS == NULL)
return E_POINTER;
pRS->Add(pInfo->pOccHdr);
if (NULL != pWheel)
_GLOBALUNLOCK(m_hWheel);
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | SetGroup |
* Associates a group with a word wheel, used for filtering.
*
* @parm IITGroup* | pIITGroup | pointer to a pre-loaded group interface
*
* @rvalue S_OK | interface pointer not NULL--successfully assigned
* @rvalue E_INVALIDARG | received a NULL pointer for the interface
* @rvalue E_NOTOPEN | the word wheel was not found to be open
* @rvalue E_OUTOFMEMORY | unable to lock the wordwheel's memory
* @rvalue E_BADFILTERSIZE | the filter group and wordwheel have different sizes
*
* @comm This method does not verify that the group behind the
* interface has been loaded, or that the group is not empty.
* If the client assigns the group interface pointer any random
* positive value other than zero, without properly instantiating
* the group object, this method returns S_OK.
********************************************************************/
STDMETHODIMP CITWordWheelLocal::SetGroup(IITGroup* pIITGroup)
{
if (NULL == m_hWheel)
return E_NOTOPEN;
m_cs.Lock();
PWHEEL pWheel;
if (NULL == (pWheel = (PWHEEL)_GLOBALLOCK(m_hWheel)))
{
m_cs.Unlock();
return E_OUTOFMEMORY;
}
// NULL is a valid argument--client is attempting to free the group
if (pIITGroup)
{
// We need to access the group's maxItemAllGroup and lcItem fields.
// We can make two function calls, or locally store the output of a single call.
_LPGROUP localImage = (_LPGROUP)(pIITGroup->GetLocalImageOfGroup());
if ((DWORD)(m_cMaxEntries) != localImage->maxItemAllGroup)
{
_GLOBALUNLOCK(m_hWheel);
m_cs.Unlock();
return E_BADFILTERSIZE;
}
pWheel->lNumEntries = m_cEntries = (LONG)(localImage->lcItem);
}
else
{
pWheel->lNumEntries = m_cEntries = m_cMaxEntries;
}
if (pIITGroup)
pIITGroup->AddRef();
if (m_pIITGroup != NULL)
m_pIITGroup->Release();
pWheel->pIITGroup = m_pIITGroup = pIITGroup;
_GLOBALUNLOCK(m_hWheel);
m_cs.Unlock();
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITWordWheel | GetGroup |
* Retrieves the group associated with the word wheel.
*
* @parm IITGroup** | ppIITGroup | (out) Pointer to the group interface.
*
* @rvalue S_OK | private member variable m_pIITGroup != NULL
* @rvalue E_NOTINIT | private member variable m_pIITGroup == NULL
* @rvalue E_BADPARAM | ppIITGroup was NULL
********************************************************************/
STDMETHODIMP CITWordWheelLocal::GetGroup(IITGroup** ppiitGroup)
{
if (NULL == ppiitGroup)
return E_POINTER;
if (m_pIITGroup == NULL)
return E_NOTINIT;
(*ppiitGroup = m_pIITGroup)->AddRef();
return S_OK;
}