|
|
/*******************************************************
* @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; }
|