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

1147 lines
38 KiB
C++

/*******************************************************
* @doc SHROOM EXTERNAL API *
* *
* GROUPIMP.CPP *
* *
* Copyright (C) Microsoft Corporation 1997 *
* All rights reserved. *
* *
* This file contains CITGroupLocal, the local *
* implementation of IITGroup. *
* *
********************************************************
* *
* Author: Eric Rynes, with deep debt to Erin Foxford *
* and her WWIMP.CPP code. *
* Current Owner: a-ericry *
* *
*******************************************************/
#include <mvopsys.h>
#ifdef _DEBUG
static char s_aszModule[] = __FILE__;
#endif
#include <atlinc.h> // includes for ATL
// MediaView (InfoTech) includes
#include <groups.h>
#include <wwheel.h>
#include "ITDB.h"
#include "itww.h"
#include "itquery.h"
#include "itgroup.h"
#include "groupimp.h"
#include <windows.h>
#include <ccfiles.h>
CITGroupLocal::~CITGroupLocal()
{
Free();
}
/*******************************************************
*
* @method STDMETHODIMP | IITGroup | Initiate |
*
* Creates and initializes a group.
*
* @parm DWORD | lcGrpItem | Maximum number of items in the group.
* @rvalue S_OK | The group was successfully created and initialized.
* @rvalue E_ALREADYINIT | The group already exists.
* @rvalue E_OUTOFMEMORY | Insufficient memory available for the operation
* *
*******************************************************/
STDMETHODIMP CITGroupLocal::Initiate(DWORD lcGrpItem)
{
HRESULT hr = S_OK; // Note: GroupInitiate takes phr as an "out" parameter,
// then sends it to GroupCreate as an "in/out" parameter ("in" when successful).
// Therefore, it must be initialized to S_OK.
// Return error if client attempts to re-initiate a group.
if (NULL != m_lpGroup)
return E_ALREADYINIT;
// HACK: Apparently, groups are not growable by default (at present).
// Client might need to initiate a group before knowing how many hits
// s/he will get. Eventually, the groupcom.c code will be changed to
// make all groups "growable" by default.
if (0 == lcGrpItem)
m_lpGroup = GroupInitiate(LCBITGROUPMAX, &hr);
else
m_lpGroup = GroupInitiate(lcGrpItem, &hr);
return hr;
}
/*******************************************************
*
* @method STDMETHODIMP | IITGroup | CreateFromBitVector |
* Creates a group from a bitvector.
*
* @parm LPBYTE | lpBits |
* Pointer to bitfield
* @parm DWORD | dwSize |
* Number of bytes in bitfield.
* @parm DWORD | dwItems |
* Number of items (if not exactly dwSize*8). If dwItems==0, dwSize*8
* is used.
*
* @rvalue S_OK | The group was successfully made from the bitvector
* @rvalue E_OUTOFMEMORY | There is not enough memory to complete the operation.
* @rvalue E_ALREADYINIT | The group already exists.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::CreateFromBitVector(LPBYTE lpBits, DWORD dwSize, DWORD dwItems)
{
// Currently, GroupMake is not being called. Before someone calls it,
// its code should be cleaned up. Specifically, its HRESULT communication
// should be resolved, and whatever HRESULT/ERRB it sends to GroupCreate
// should be initialized to S_OK.
// Return error if client attempts to re-create a group (GroupMake
// calls GroupCreate, then GroupTrimmed).
if (NULL != m_lpGroup)
return E_ALREADYINIT;
m_lpGroup = GroupMake(lpBits, dwSize, dwItems);
// Note: GroupMake defines its own local ERRB variable, which it sends
// (by reference) to GroupCreate in the PHRESULT parameter slot.
return (NULL != m_lpGroup ? S_OK : E_OUTOFMEMORY);
// GroupMake only calls GroupTrimmed when GroupMake receives a non-NULL
// group from GroupCreate; when GroupTrimmed receives a non-NULL group,
// it only returns S_OK or E_OUTOFMEMORY.
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | CreateFromBuffer |
* This function creates a group from a buffer.
*
* @parm HANDLE | h |
* Handle to memory buffer containing raw group file data.
*
* @rdesc This method returns S_OK when successful. If the group already exists, it returns E_ALREADYINIT.
* Other error codes are determined by the C function
* GroupBufferCreate in file groupcom.c.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::CreateFromBuffer(HANDLE h)
{
HRESULT hr = S_OK; // Note: GroupCreate (called by GroupBufferCreate) takes phr
// as an "in/out" parameter ("in" when successful). Therefore, it must be
// initialized to S_OK.
// Return error if client attempts to re-create a group (GroupBufferCreate
// calls GroupCreate).
if (NULL != m_lpGroup)
return E_ALREADYINIT;
m_lpGroup = GroupBufferCreate(h, &hr);
return hr;
}
/***********************************************************************
*
* @method STDMETHODIMP | IITGroup | Open |
* Opens the group using IStorage/IStream/GroupBufferCreate.
*
* @parm IITDatabase* | lpITDB | Database interface pointer.
* @parm LPCWSTR | lpszMoniker | Storage name.
*
* @rvalue S_OK | The group was successfully opened from the database.
* @rvalue E_ALREADYINIT | The group has already been initialized.
* @rvalue E_FILEREAD | An error occurred reading from the group file.
* @rvalue E_OUTOFMEMORY | An error occurred while allocating memory for the local buffer.
* @comm Other error codes might be possible. See IStorage methods
* OpenStorage and OpenStream, and IStream methods Stat and Read.
*
***********************************************************************/
STDMETHODIMP CITGroupLocal::Open(IITDatabase* lpITDB, LPCWSTR lpszMoniker)
{
HRESULT hr;
IStorage* pSubStorage = NULL;
IStream* pStream = NULL;
STATSTG statstg;
HANDLE hBuffer; // GroupBufferCreate takes a HANDLE to a buffer
DWORD dwNumBytesRead = 0; // same type as ULONG,
LPWSTR szStorageName;
// which is returned from pIStream->Read()
if (NULL != m_lpGroup)
return E_ALREADYINIT;
// Open substorage and pass to group
szStorageName = new WCHAR [CCH_MAX_OBJ_NAME + CCH_MAX_OBJ_STORAGE + 1];
WSTRCPY (szStorageName, SZ_GP_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';
}
hr = lpITDB->GetObjectPersistence(szStorageName, IITDB_OBJINST_NULL,
(LPVOID *) &pSubStorage, FALSE);
delete szStorageName;
if (FAILED(hr))
return hr;
hr = pSubStorage->OpenStream(SZ_GROUP_MAIN, NULL, STGM_READ, 0, &pStream);
pSubStorage->Release(); // we're done with the storage--release it
if (FAILED(hr)) // error opening the stream
return hr;
hr = pStream->Stat(&statstg, STATFLAG_NONAME); // get the size of the stream
if (FAILED(hr))
{
pStream->Release(); // release the stream
return hr;
}
// allocate memory for statstg.cbSize bytes in hBuffer
hBuffer = _GLOBALALLOC(GMEM_FIXED | GMEM_ZEROINIT, (statstg.cbSize).LowPart);
if (NULL == hBuffer)
{
pStream->Release(); // release the stream
return E_OUTOFMEMORY;
}
hr = pStream->Read((void *)hBuffer, (statstg.cbSize).LowPart, &dwNumBytesRead);
pStream->Release(); // we're done with the stream--release it
if (SUCCEEDED(hr) &&
dwNumBytesRead != (statstg.cbSize).LowPart)
hr = E_FILEREAD;
if (SUCCEEDED(hr))
m_lpGroup = GroupBufferCreate(hBuffer, &hr);
_GLOBALFREE(hBuffer);
return hr;
}
/*********************************************
*
* @method STDMETHODIMP | IITGroup | Free |
* Frees the memory allocated for a group.
*
* @rvalue | S_OK | This method always returns S_OK.
*
*********************************************/
STDMETHODIMP CITGroupLocal::Free(void)
{
if (NULL != m_lpGroup)
GroupFree(m_lpGroup);
m_lpGroup = NULL;
return S_OK;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | CopyOutBitVector |
* This function copies the bitfield data of one group out to another.
*
* @parm IITGroup* | pIITGroup|
* (out) Pointer to destination group.
*
* @rvalue S_OK | success
* @rvalue E_NOTINIT | source (member variable) group is NULL
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::CopyOutBitVector(IITGroup* pIITGroup)
{
if (NULL == m_lpGroup)
return E_NOTINIT;
return pIITGroup->PutRemoteImageOfGroup(m_lpGroup);
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | AddItem |
* This function adds a group item number into the given group.
*
* @parm DWORD | dwGrpItem |
* Group Item to be added into the group. The value of dwGrpItem must be
* between 0 and 524280
*
* @rvalue S_OK | The item was successfully added to the group.
* @rvalue E_NOTINIT | The group was not initialized, and no item
* can be added to it.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::AddItem(DWORD dwGrpItem)
{
if (NULL == m_lpGroup)
return E_NOTINIT;
return GroupAddItem(m_lpGroup, dwGrpItem);
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | RemoveItem |
* This function removes a group item number from the given group.
*
* @parm DWORD | dwGrpItem |
* Item to be removed from the group.
*
* @rvalue S_OK | The item was successfully removed from the gruop.
* @rvalue E_NOTINIT | The group was not initialized, and no item
* can be removed from it.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::RemoveItem(DWORD dwGrpItem)
{
if (NULL == m_lpGroup)
return E_NOTINIT;
return GroupRemoveItem(m_lpGroup, dwGrpItem);
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | FindTopicNum |
* Given a pointer to a group and a count to count from the first
* topic number of the group (dwCount), this function returns the
* topic number of the nth (dwCount) item of the list (counting from 0),
* or -1 if not found
*
* @parm DWORD | dwCount |
* The index count in to the group. Count begins at zero.
*
* @parm LPDWORD | lpdwOutputTopicNum |
* (out) The topic number, or a pointer to -1 in case of error.
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue S_FALSE | The operation completed successfully, but the list contains fewer than dwCount items.
* @rvalue E_INVALIDARG | dwCount <gt>= m_lpGroup-<gt>lcItem
* @rvalue E_NOTINIT | The target group is NULL. For other errors, see groupcom.c.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::FindTopicNum(DWORD dwCount, LPDWORD lpdwOutputTopicNum)
{
HRESULT hr = S_OK; // initialized just for safety's sake
// Return error if client attempts to find a topic in a NULL (nonexistent) group.
if (NULL == m_lpGroup)
return E_NOTINIT;
if (dwCount >= m_lpGroup->lcItem)
return E_INVALIDARG;
*lpdwOutputTopicNum = GroupFind(m_lpGroup, dwCount, &hr);
if ((-1 == *lpdwOutputTopicNum) && (SUCCEEDED(hr))) // not found
return S_FALSE;
return hr;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | FindOffset |
* Given a pointer to a group and a topic number,
* this function finds the position of the item in the
* group that has "dwTopicNum" as a topic number or -1 if error.
* This is the counter-API of FindTopicNum().
*
* @parm DWORD | dwTopicNum |
* The index count in to the group. Count begins at zero.
*
* @parm LPDWORD | lpdwOutputOffset |
* (out) The position of the item in the group. In case of error,
* this parameter returns a pointer to -1. If the dwTopicNum is not part of
* the group, the rvalue is set to ERR_NOTEXIST and the function
* returns the closest UID less than dwTopicNum.
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue E_NOTINIT | The target group (member variable) is NULL.
* @rvalue E_INVALIDARG | dwTopicNum <gt> m_lpGroup-<gt>maxItemAllGroup.
*
* @comm See GroupFindOffset in groupcom.c.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::FindOffset(DWORD dwTopicNum, LPDWORD lpdwOutputOffset)
{
HRESULT hr = S_OK; // initialized just for safety's sake
// Return error if client attempts to find a position/offset in a NULL (nonexistent) group.
if (NULL == m_lpGroup)
return E_NOTINIT;
if (dwTopicNum > m_lpGroup->maxItemAllGroup)
return E_INVALIDARG;
*lpdwOutputOffset = GroupFindOffset(m_lpGroup, dwTopicNum, &hr);
return hr;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | GetSize |
* This method retrieves the size of the bitvector in private member
* variable m_lpGroup.
*
* @parm LPDWORD | lpdwGrpSize |
* (out) The maxItemAllGroup field of the group structure.
* The total number of items (on and off) in the group. The
* group contains no items, either "on" or "off," beyond this position.
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue E_NOTINIT | The group has not been initialized.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::GetSize(LPDWORD lpdwGrpSize)
{
if (NULL == m_lpGroup)
return E_NOTINIT;
*lpdwGrpSize = m_lpGroup->maxItemAllGroup;
return S_OK;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | Trim |
* Trims down the size of the group's bit vector.
* For example, if the bitvector is all zeroes, the bitvector pointer
* is set to NULL.
*
* @rvalue S_OK | the group was successfully trimmed
* @rvalue E_OUTOFMEMORY | out-of-memory
* @rvalue E_NOTINIT | the group pointer is NULL
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::Trim(void)
{
// Return error if client attempts to trim a NULL (nonexistent) group.
if (NULL == m_lpGroup)
return E_NOTINIT;
return GroupTrimmed(m_lpGroup);
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | And |
* The function overwrites the member variable group with a new group
* resulting from the ANDing of this group with an input group.
*
* @parm IITGROUP* | pIITGroup |
* Interface pointer to the input group.
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue E_NOTINIT | m_lpGroup == NULL
* @rvalue E_INVALIDARG | The input group is NULL
*
* @comm See GroupAnd in groupcom.c for additional error conditions.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::And(IITGroup* pIITGroup)
{
HRESULT hr = S_OK;// Note: GroupCreate (called by GroupCheckAndCreate,
// within GroupAnd) takes phr as an "in/out" parameter ("in" when successful).
// Therefore, hr1 must be initialized to S_OK.
// Return error if client attempts to GroupAnd a NULL (nonexistent) group.
if (NULL == m_lpGroup)
return E_NOTINIT;
if (NULL == pIITGroup)
return E_INVALIDARG;
if ((0 == m_lpGroup->maxItemAllGroup) || (0 == m_lpGroup->lcItem))
return S_OK;
_LPGROUP lpGroupIn = (_LPGROUP)pIITGroup->GetLocalImageOfGroup(); // access private member var.
if ((0 == lpGroupIn->maxItemAllGroup) || (0 == lpGroupIn->lcItem))
return GroupCopy(m_lpGroup, lpGroupIn);
_LPGROUP ANDed_group = GroupAnd(m_lpGroup, lpGroupIn, &hr); // allocates memory!!
if (FAILED(hr))
{
GroupFree(ANDed_group);
return hr;
}
hr = GroupCopy(m_lpGroup, ANDed_group);
GroupFree(ANDed_group);
return hr;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | And |
* This function creates a new group resulting from the ANDing of the
* member variable group with an input group.
*
* @parm IITGroup* | pIITGroupIn |
* (in) Interface pointer to the input group.
*
* @parm IITGroup* | pIITGroupOut |
* (out) Interface pointer to the output group.
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue E_NOTINIT | m_lpGroup == NULL
* @rvalue E_INVALIDARG | The input group is NULL
*
* @comm See GroupAnd in groupcom.c for additional error conditions.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::And(IITGroup* pIITGroupIn, IITGroup* pIITGroupOut)
{
HRESULT hr = S_OK;// Note: GroupCreate (called by GroupCheckAndCreate,
// within GroupAnd) takes phr as an "in/out" parameter ("in" when successful).
// Therefore, it must be initialized to S_OK.
// Return error if client attempts to GroupAnd a NULL (nonexistent) group.
if (NULL == m_lpGroup)
return E_NOTINIT;
if (NULL == pIITGroupIn)
return E_INVALIDARG;
if ((0 == m_lpGroup->maxItemAllGroup) || (0 == m_lpGroup->lcItem))
return pIITGroupOut->PutRemoteImageOfGroup(m_lpGroup);
_LPGROUP lpGroupIn = (_LPGROUP)pIITGroupIn->GetLocalImageOfGroup(); // access private member var.
if ((0 == lpGroupIn->maxItemAllGroup) || (0 == lpGroupIn->lcItem))
{
if (pIITGroupOut == pIITGroupIn)
return S_OK;// avoid the overhead of the function call;
// client called a->And(b,b), which is equivalent to b->And(a)
return pIITGroupOut->PutRemoteImageOfGroup(lpGroupIn);
}
_LPGROUP ANDed_group = GroupAnd(m_lpGroup, lpGroupIn, &hr); // allocates memory!!
if (FAILED(hr))
{
GroupFree(ANDed_group);
return hr;
}
hr = pIITGroupOut->PutRemoteImageOfGroup(ANDed_group);
GroupFree(ANDed_group);
return hr;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | Or |
* This function overwrites the member variable group with a new group
* resulting from the ORing of this group with an input group.
*
* @parm IITGroup* | pIITGroup |
* Interface pointer to the input group
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue E_NOTINIT | m_lpGroup == NULL
* @rvalue E_INVALIDARG | input group is NULL
*
* @comm See GroupOr in groupcom.c for additional error conditions.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::Or(IITGroup* pIITGroup)
{
HRESULT hr = S_OK; // Note: GroupCreate (called by GroupOr)
// takes phr as an "in/out" parameter ("in" when successful). Therefore, it must
// be initialized to S_OK.
// Return error if client attempts to GroupOr a NULL (nonexistent) group.
if (NULL == m_lpGroup)
return E_NOTINIT;
if (NULL == pIITGroup)
return E_INVALIDARG;
_LPGROUP lpGroupIn = (_LPGROUP)pIITGroup->GetLocalImageOfGroup();
if ((0 == m_lpGroup->maxItemAllGroup) || (0 == m_lpGroup->lcItem))
return GroupCopy(m_lpGroup, lpGroupIn); // copy lpGroupIn's bits into m_lpGroup
if ((0 == lpGroupIn->maxItemAllGroup) || (0 == lpGroupIn->lcItem))
return S_OK;
_LPGROUP ORed_group = GroupOr(m_lpGroup, lpGroupIn, &hr); // allocates memory!!
if (FAILED(hr))
{
GroupFree(ORed_group);
return hr;
}
hr = GroupCopy(m_lpGroup, ORed_group);
GroupFree(ORed_group);
return hr;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | Or |
* This function creates a new group resulting from the ORing of the
* member variable group with an input group.
*
* @parm IITGroup* | pIITGroupIn |
* (in) Interface pointer to the input group.
*
* @parm IITGroup* | pIITGroupOut |
* (out) Interface pointer to the output group.
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue E_NOTINIT | m_lpGroup is equal to NULL
* @rvalue E_INVALIDARG | The input group is NULL
*
* @comm See GroupOr in groupcom.c for additional error conditions.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::Or(IITGroup* pIITGroupIn, IITGroup* pIITGroupOut)
{
HRESULT hr = S_OK;// Note: GroupCreate (called by GroupDuplicate)
// takes phr as an "in/out" parameter ("in" when successful). Therefore, it
// must be initialized to S_OK.
// Return error if client attempts to GroupOr a NULL (nonexistent) group.
if (NULL == m_lpGroup)
return E_NOTINIT;
if (NULL == pIITGroupIn)
return E_INVALIDARG;
_LPGROUP lpGroupIn = (_LPGROUP)pIITGroupIn->GetLocalImageOfGroup(); // access private member var.
if ((0 == m_lpGroup->maxItemAllGroup) || (0 == m_lpGroup->lcItem))
return pIITGroupOut->PutRemoteImageOfGroup(lpGroupIn);
if ((0 == lpGroupIn->maxItemAllGroup) || (0 == lpGroupIn->lcItem))
return pIITGroupOut->PutRemoteImageOfGroup(m_lpGroup);
_LPGROUP ORed_group = GroupOr(m_lpGroup, lpGroupIn, &hr); // allocates memory!!
if (FAILED(hr))
{
GroupFree(ORed_group);
return hr;
}
hr = pIITGroupOut->PutRemoteImageOfGroup(ORed_group);
GroupFree(ORed_group);
return hr;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | Not |
* This function overwrites the member variable group with the
* "NOT" of itself.
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue E_NOTINIT | m_lpGroup is equal to NULL
*
* @comm See GroupNot in groupcom.c for additional error conditions.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::Not(void)
{
HRESULT hr = S_OK;
if (NULL == m_lpGroup)
return E_NOTINIT;
if ((0 == m_lpGroup->maxItemAllGroup) || (0 == m_lpGroup->lcItem))
return S_OK;
_LPGROUP NOTed_group = GroupNot(m_lpGroup, &hr); // allocates memory!!
if (FAILED(hr))
{
GroupFree(NOTed_group);
return hr;
}
hr = GroupCopy(m_lpGroup, NOTed_group);
GroupFree(NOTed_group);
return hr;
}
/*************************************************************************
*
* @method STDMETHODIMP | IITGroup | Not |
* This function creates a new group equalling the "NOT"
* of the member variable group.
*
* @parm IITGroup* | pIITGroupOut |
* (out) Pointer to the output group.
*
* @rvalue S_OK | The operation completed successfully.
* @rvalue E_NOTINIT | m_lpGroup is equal to NULL
*
* @comm See GroupOr in groupcom.c for additional error conditions.
*
*************************************************************************/
STDMETHODIMP CITGroupLocal::Not(IITGroup* pIITGroupOut)
{
HRESULT hr = S_OK;
if (NULL == m_lpGroup)
return E_NOTINIT;
if ((0 == m_lpGroup->maxItemAllGroup) || (0 == m_lpGroup->lcItem))
return pIITGroupOut->PutRemoteImageOfGroup(m_lpGroup);
_LPGROUP NOTed_group = GroupNot(m_lpGroup, &hr); // allocates memory!!
if (FAILED(hr))
{
GroupFree(NOTed_group);
return hr;
}
hr = pIITGroupOut->PutRemoteImageOfGroup(NOTed_group);
GroupFree(NOTed_group);
return hr;
}
/****************************************************
*
* @method STDMETHODIMP | IITGroup | IsBitSet |
*
* Determines whether the bit is set for the topic number
* in question.
*
* @parm DWORD | dwTopicNum | Query's topic number
*
* @rvalue S_OK | true (bit is set)
* @rvalue S_FALSE | false (bit is not set)
*
****************************************************/
STDMETHODIMP CITGroupLocal::IsBitSet(DWORD dwTopicNum)
{
if (NULL == m_lpGroup)
return E_NOTINIT;
BOOL fRet = GroupIsBitSet(m_lpGroup, dwTopicNum);
return (FALSE == fRet ? S_FALSE : S_OK);
}
/**********************************************************************************
*
* @method STDMETHODIMP | IITGroup | CountBitsOn |
*
* Determines the number of items in the group which are set (on).
*
* @parm LPDWORD | lpdwTotalNumBitsOn | (out) The number of items in the group which are set (on).
*
* @rvalue S_OK | This method always returns S_OK.
*
**********************************************************************************/
STDMETHODIMP CITGroupLocal::CountBitsOn(LPDWORD lpdwTotalNumBitsOn)
{
*lpdwTotalNumBitsOn = LrgbBitCount(m_lpGroup->lpbGrpBitVect,
m_lpGroup->dwSize);
return S_OK;
}
/**********************************************************************************
*
* @method STDMETHODIMP | IITGroup | Clear|
*
* Sets all bits in the group to zero. This method turns all items "off" in a group.
* It is equivalent to calling RemoveItem on every item in the group. The group
* remains initialized, and its size (which can be retrieved using GetSize) remains
* unchanged. The memory owned by the group remains unchanged.
*
* @rvalue E_OUTOFMEMORY | The group could not be manipulated because of
* low memory conditions.
* @rvalue S_OK | The operation was performed successfully .
*
**********************************************************************************/
STDMETHODIMP CITGroupLocal::Clear(void)
{
HRESULT hr;
if (NULL == m_lpGroup)
return E_NOTINIT;
if (m_lpGroup->lcItem > 0)
MEMSET(m_lpGroup->lpbGrpBitVect, 0, (DWORD)m_lpGroup->dwSize);
// add an item to the end of the group, which will
// cause the group to be allocated to its full size.
if (FAILED(hr = GroupAddItem(m_lpGroup, m_lpGroup->maxItemAllGroup - 1)))
return hr;
// this can only fail if we pass NULL.
// fortunately, GroupRemoveItem does not trim the group.
GroupRemoveItem(m_lpGroup,m_lpGroup->maxItemAllGroup - 1);
m_lpGroup->lcItem = 0;
m_lpGroup->minItem = m_lpGroup->maxItem = 0;
m_lpGroup->nCache = 0;
return S_OK;
}
/**********************************************************
*
* @method _LPGROUP | IITGroup | GetLocalImageOfGroup |
*
* Returns an LPVOID pointer to an actual group (not an ITGroup).
*
*
* @rvalue m_lpGroup | This method always returns an LPVOID pointer
* to the group. This pointer can be NULL.
* @comm This method will not work for group operations between
* different machines. A new version of GetLocalImageOfGroup needs
* to be created to handle the HTTP case.
*
**********************************************************/
STDMETHODIMP_(LPVOID) CITGroupLocal::GetLocalImageOfGroup(void)
{
return (LPVOID)m_lpGroup;
}
/*************************************************************
*
* @method _LPGROUP | IITGroup | PutRemoteImageOfGroup |
* Copies the bits from the input group into the
* private member variable group. If the latter is
* NULL, space is allocated for it using the
* GroupDuplicate function in groupcom.c.
*
* @parm _LPGROUP | lpGroupIn |
* The input group being assigned to the private
* member variable group.
*
* @rvalue S_OK | The input group was successfully assigned.
* @rvalue E_INVALIDARG | The input group is a NULL pointer.
* @comm See GroupDuplicate, GroupCopy in groupcom.c for
* any other possible return values.
*
*************************************************************/
STDMETHODIMP CITGroupLocal::PutRemoteImageOfGroup(LPVOID lpGroupIn)
{
HRESULT hr = S_OK; // Note: GroupDuplicate takes phr as an "out" parameter,
// then sends it to GroupCreate as an "in/out" parameter ("in" when successful).
// Therefore, it must be initialized to S_OK.
if (NULL == lpGroupIn)
return E_INVALIDARG;
if (NULL != m_lpGroup)
return GroupCopy(m_lpGroup, (_LPGROUP)lpGroupIn); // simply copy the bitvector
// NULL == m_lpGroup -- allocate memory for the group, initialize it
m_lpGroup = GroupDuplicate((_LPGROUP)lpGroupIn, &hr);
return hr;
}
/////////// GroupArray methods
STDMETHODIMP_(LPVOID) CITGroupArrayLocal::GetLocalImageOfGroup(void)
{
HRESULT hr;
// recalculate the group
if (NULL == m_pGroup)
{
hr = CoCreateInstance(CLSID_IITGroupLocal, NULL, CLSCTX_INPROC_SERVER,
IID_IITGroup, (VOID **)&m_pGroup);
if (FAILED(hr))
return NULL;
// passing LCBITGROUPMAX means a dynamically sized group
if (!m_pGroup || FAILED(m_pGroup->Initiate(1)))
return NULL;
}
ITASSERT(m_pGroup);
if (m_fDirty)
{
DWORD dwT;
int i;
m_pGroup->Clear();
for (i = 0, dwT = 1L; i < m_iEntryMax; i++, dwT <<= 1)
if (dwT & m_rgfEntries)
{
if (m_iDefaultOp == ITGP_OPERATOR_AND)
m_pGroup->And(m_rgpGroup[i]);
else
m_pGroup->Or(m_rgpGroup[i]);
}
m_fDirty = FALSE;
}
if (m_pGroup)
return (LPVOID)(m_pGroup->GetLocalImageOfGroup());
return NULL;
}
CITGroupArrayLocal::~CITGroupArrayLocal()
{
DWORD dwT;
int i;
if (m_pGroup)
{
m_pGroup->Release();
m_pGroup = NULL;
}
// now free all the groups we allocated in the array
for (i = 0, dwT = 1L; i < m_iEntryMax; i++, dwT <<= 1)
if (m_rgpGroup[i])
m_rgpGroup[i]->Release();
}
/********************************************************************
* @method STDMETHODIMP | IITGroupArray | InitEntry |
* Adds a group to the group array
* @parm IITDatabase* | piitDB | Pointer to the database object.
* @parm LPCWSTR | lpszName | Name of group in the database to add.
* @parm LONG& | lEntryNum | (out) The index of the new array
* element.
*
* @rvalue E_OUTOFRANGE | No more array entries can be created. The maximum is
* ITGP_MAX_GROUPARRAY_ENTRIES
* @rvalue E_BADPARAM | piitDB or lpszName was NULL
* @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 group was successfully opened
* @comm When you call InitEntry, it doesn't mark the array entry as "set", it
* just initializes a new array entry with the given group data and returns the index of
* the new array entry. All the group array
* entries are initially "clear" until you set them with SetEntry. Also, the default operator
* for IITGroupArray is ITGP_OPERATOR_OR, the OR operator.
*
********************************************************************/
STDMETHODIMP CITGroupArrayLocal::InitEntry(IITDatabase *piitDB, LPCWSTR lpwszName, LONG& lEntryNum)
{
IITGroup *piitGroup;
HRESULT hr;
if (NULL == piitDB || NULL == lpwszName)
return E_BADPARAM;
if (m_iEntryMax >= ITGP_MAX_GROUPARRAY_ENTRIES - 1)
return E_OUTOFRANGE;
// open and add to the current array
// UNDONE: this isn't as efficient as it could be
hr = CoCreateInstance(CLSID_IITGroupLocal, NULL, CLSCTX_INPROC_SERVER,
IID_IITGroup, (VOID **)&piitGroup);
if (FAILED(hr))
return hr;
m_rgpGroup[m_iEntryMax] = piitGroup;
if (NULL == piitGroup)
return E_OUTOFMEMORY;
if (S_OK == (hr = piitGroup->Open(piitDB, lpwszName)))
{
lEntryNum = m_iEntryMax++;
return S_OK;
}
piitGroup->Release();
m_rgpGroup[m_iEntryMax] = NULL;
return hr;
}
/********************************************************************
* @method STDMETHODIMP | IITGroupArray | InitEntry |
* Adds a group to the group array
* @parm IITGroup* | piitGroup | Pointer to caller-owned group object
* @parm LONG& | lEntryNum | (out) The index of the new array
* element.
*
* @rvalue E_OUTOFRANGE | No more array entries can be created. The maximum is
* ITGP_MAX_GROUPARRAY_ENTRIES
* @rvalue E_BADPARAM | piitGroup was NULL
* @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 occur while opening a storage.
* @rvalue S_OK | The group was successfully opened.
* @comm This must be the first method called after the object is instantiated.
* When you call InitEntry, it doesn't mark the array entry as "set", it
* just initializes a new array entry with the given group data and returns the index of
* the new array entry. All the group array
* entries are initially "clear" until you set them with SetEntry. Also, the default operator
* for IITGroupArray is ITGP_OPERATOR_OR, the OR operator.
*
********************************************************************/
STDMETHODIMP CITGroupArrayLocal::InitEntry(IITGroup *piitGroup, LONG& lEntryNum)
{
if (m_iEntryMax >= ITGP_MAX_GROUPARRAY_ENTRIES - 1)
return E_OUTOFRANGE;
if (NULL == piitGroup)
return E_BADPARAM;
m_rgpGroup[m_iEntryMax] = piitGroup;
piitGroup->AddRef();
lEntryNum = m_iEntryMax++;
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITGroupArray | SetEntry |
* Turns on the array element corresponding to the given entry number
* @parm LONG | lEntryNum | The index into the array to mark as "on"
*
* @rvalue E_OUTOFRANGE | The given array index is too large
* @rvalue S_OK | The operation completed successfully
*
********************************************************************/
STDMETHODIMP CITGroupArrayLocal::SetEntry(LONG lEntryNum)
{
DWORD dwT;
if (lEntryNum >= m_iEntryMax)
return E_OUTOFRANGE;
if (lEntryNum == ITGP_ALL_ENTRIES)
{
m_rgfEntries = 0xFFFFFFFF;
m_fDirty = TRUE;
return S_OK;
}
dwT = 1L << lEntryNum;
m_fDirty = !(m_rgfEntries & dwT);
m_rgfEntries |= dwT;
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITGroupArray | ClearEntry |
* Turns off the array element corresponding to the given entry number
* @parm LONG | lEntryNum | The index into the array to mark as "off"
*
* @rvalue E_OUTOFRANGE | The given array index is too large
* @rvalue S_OK | The operation was completed successfully
*
********************************************************************/
STDMETHODIMP CITGroupArrayLocal::ClearEntry(LONG lEntryNum)
{
DWORD dwT;
if (lEntryNum >= m_iEntryMax)
return E_OUTOFRANGE;
if (lEntryNum == ITGP_ALL_ENTRIES)
{
m_rgfEntries = 0L;
m_fDirty = TRUE;
return S_OK;
}
dwT = 1L << lEntryNum;
m_fDirty = !!(m_rgfEntries & dwT);
m_rgfEntries &= ~dwT;
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITGroupArray | SetDefaultOp |
* Set the default operator to be used between all the entries
* in the group array.
* @parm LONG | iDefaultOp | One of ITGP_OPERATOR_OR, ITGP_OPERATOR_AND
*
* @rvalue E_BADPARAM | An invalid operator was specified
* @rvalue S_OK | The operation completed successfully
*
* @comm The default operator is used when the group array is treated
* as an ordinary group by other objects. In that case, the group array
* appears to be a single group consisting of all the groups specified
* with each entry, and OR'd r AND'd together. Only one operator at a time
* can be applied, and it must apply to all entries in the array. To
* perform more complex filter operations you can create group arrays using
* other group arrays.
********************************************************************/
STDMETHODIMP CITGroupArrayLocal::SetDefaultOp(LONG iDefaultOp)
{
if (iDefaultOp > ITGP_OPERATOR_AND)
return E_BADPARAM;
if (iDefaultOp != m_iDefaultOp)
{
m_iDefaultOp = iDefaultOp;
m_fDirty = TRUE;
}
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITGroupArray | ToString |
* Returns a string representation of the group array.
*
* @parm LPWSTR * | ppwBuffer | (out) The string representation of the group array.
*
* @rvalue E_NOTIMPL | This method is currently only implemented for the HTTP
* transport layer.
* @rvalue S_OK | The operation completed successfully.
*
* @comm NOTE: This method is currently only implemented for the HTTP transport layer.
*
* The ToString method will allocate the memory for the returned string.
* The caller must call CoTaskMemFree on the returned pointer when
* finished with the string.
*
* The format of the string is:
* <lt>opcode-0<gt><lt>group-0<gt><lt>opcode-1<gt><lt>group-1<gt>...<lt>opcode-N<gt><lt>group-N<gt>
*
* where <lt>opcode-N<gt> is one of '&' (AND), '+' (OR) and
* where <lt>group-N<gt> is the string representing the N-th entry in the group array.
* If the entry is itself a group array, the entry is delimited by [ and ].
*
* For example: &media1&media2&[+book1+book4+book9].
*
* Currently, it is assumed all the groups named in the string belong to the same
* database.
*
********************************************************************/
STDMETHODIMP CITGroupArrayLocal::ToString(LPWSTR *ppwBuffer)
{
return E_NOTIMPL;
}