You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1060 lines
29 KiB
1060 lines
29 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 1998
|
|
*
|
|
* TITLE: IPropItm.Cpp
|
|
*
|
|
* VERSION: 2.0
|
|
*
|
|
* AUTHOR: ReedB
|
|
*
|
|
* DATE: 19 Feb, 1998
|
|
*
|
|
* DESCRIPTION:
|
|
* Implementation of WIA item class server properties.
|
|
*
|
|
*******************************************************************************/
|
|
#include "precomp.h"
|
|
#include "stiexe.h"
|
|
|
|
#include <regstr.h>
|
|
#include <wiamindr.h>
|
|
// #include <wiadbg.h>
|
|
|
|
#include "wiapsc.h"
|
|
#include "helpers.h"
|
|
|
|
//
|
|
// Strings used to access the registry. REGSTR_* string constants can be
|
|
// found in sdk\inc\regstr.h
|
|
//
|
|
|
|
TCHAR g_szREGSTR_PATH_WIA[] = REGSTR_PATH_SETUP TEXT("\\WIA");
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ReadMultiple
|
|
* WriteMultiple
|
|
* ReadPropertyNames
|
|
* Enum
|
|
* GetPropertyAttributes
|
|
* GetCount
|
|
*
|
|
* DESCRIPTION:
|
|
* IWiaPropertyStorage methods.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::ReadMultiple
|
|
*
|
|
* This method reads the specified number of properties from the item's
|
|
* current value property storage. This method conforms to that standard
|
|
* OLE IPropertyStorage::ReadMultiple method.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* cpspec - Number of properties to read.
|
|
* rgpspec - Array of PropSpec's specifying which properties
|
|
* are to be read.
|
|
* rgpropvar - Array where the property values will be copied
|
|
* to.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* cpspec
|
|
* rgpspec
|
|
* rgpropvar
|
|
*
|
|
* Return Value:
|
|
*
|
|
* status
|
|
*
|
|
* History:
|
|
*
|
|
* 9/3/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::ReadMultiple(
|
|
ULONG cpspec,
|
|
const PROPSPEC __RPC_FAR rgpspec[],
|
|
PROPVARIANT __RPC_FAR rgpropvar[])
|
|
{
|
|
DBG_FN(CWiaItem::ReadMultiple);
|
|
HRESULT hr;
|
|
LONG lFlags = 0;
|
|
|
|
//
|
|
// Corresponding driver item must be valid to talk with hardware.
|
|
//
|
|
|
|
hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// rgpropvar must be valid
|
|
//
|
|
|
|
if (IsBadWritePtr(rgpropvar, sizeof(PROPVARIANT) * cpspec)) {
|
|
DBG_ERR(("CWiaItem::ReadMultiple, last parameter (rgpropvar) is invalid"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
|
|
//
|
|
// Check whether the properties being read are the WIA Managed properties.
|
|
// If they are, there is still no need to initialize the item.
|
|
//
|
|
|
|
if (AreWiaInitializedProps(cpspec, (PROPSPEC*) rgpspec)) {
|
|
return (m_pPropStg->CurStg())->ReadMultiple(cpspec, rgpspec, rgpropvar);
|
|
}
|
|
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::ReadMultiple, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check whether the properties requested are all cacheable
|
|
//
|
|
|
|
hr = (m_pPropStg->AccessStg())->ReadMultiple(cpspec, rgpspec, rgpropvar);
|
|
if (FAILED(hr)) {
|
|
|
|
ReportReadWriteMultipleError(hr, "CWiaItem::ReadMultiple", NULL, TRUE, cpspec, rgpspec);
|
|
|
|
//
|
|
// Property attributes are not required absolutely, continue without it.
|
|
//
|
|
|
|
} else {
|
|
|
|
for (ULONG i = 0; i < cpspec; i++) {
|
|
|
|
//
|
|
// The client requests a property not read yet or non-cacheable
|
|
//
|
|
|
|
if ((rgpropvar[i].vt == VT_UI4) &&
|
|
(! (rgpropvar[i].lVal & WIA_PROP_CACHEABLE))) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clear the access flags from the rgpropvar
|
|
//
|
|
|
|
FreePropVariantArray(cpspec, rgpropvar);
|
|
|
|
//
|
|
// If all the properties are cacheable, then take the quick path
|
|
//
|
|
|
|
if (i == cpspec) {
|
|
|
|
hr = (m_pPropStg->CurStg())->ReadMultiple(cpspec, rgpspec, rgpropvar);
|
|
|
|
if (hr == S_OK) {
|
|
|
|
//
|
|
// Check whether all the properties are retrieved correctly
|
|
// some properties might not have been read from the storage
|
|
//
|
|
|
|
for (ULONG i = 0; i < cpspec; i++) {
|
|
|
|
if (rgpropvar[i].vt == VT_EMPTY) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == cpspec) {
|
|
|
|
//
|
|
// All the properties requested are found in cache
|
|
//
|
|
|
|
return (hr);
|
|
} else {
|
|
|
|
FreePropVariantArray(cpspec, rgpropvar);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Make sure all PropSpecs are using PropID's. This is so that
|
|
// drivers only have to deal with PropID's. If some of the
|
|
// PropSpecs are using string names, then convert them.
|
|
//
|
|
|
|
PROPSPEC *pPropSpec = NULL;
|
|
hr = m_pPropStg->NamesToPropIDs(cpspec, (PROPSPEC*) rgpspec, &pPropSpec);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Give device mini driver a chance to update the device properties.
|
|
//
|
|
{
|
|
LOCK_WIA_DEVICE _LWD(this, &hr);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_pActiveDevice->m_DrvWrapper.WIA_drvReadItemProperties((BYTE*)this,
|
|
lFlags,
|
|
cpspec,
|
|
(pPropSpec ? pPropSpec : rgpspec),
|
|
&m_lLastDevErrVal);
|
|
}
|
|
}
|
|
|
|
if (pPropSpec) {
|
|
LocalFree(pPropSpec);
|
|
pPropSpec = NULL;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = (m_pPropStg->CurStg())->ReadMultiple(cpspec, rgpspec, rgpropvar);
|
|
if (FAILED(hr)) {
|
|
ReportReadWriteMultipleError(hr,
|
|
"CWiaItem::ReadMultiple",
|
|
NULL,
|
|
TRUE,
|
|
cpspec,
|
|
rgpspec);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::ReadPropertyNames
|
|
*
|
|
* Returns the string name of the specified properties if they exist.
|
|
* This conforms to the standard OLE IPropertyStorage::ReadPropertyNames
|
|
* method.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pstmProp - Pointer to property stream.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 9/3/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::ReadPropertyNames(
|
|
ULONG cpropid,
|
|
const PROPID __RPC_FAR rgpropid[],
|
|
LPOLESTR __RPC_FAR rglpwstrName[])
|
|
{
|
|
DBG_FN(CWiaItem::ReadPropertyNames);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::ReadPropertyNames, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return (m_pPropStg->CurStg())->ReadPropertyNames(cpropid,rgpropid,rglpwstrName);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::WritePropertyNames
|
|
*
|
|
* Returns the string name of the specified properties if they exist.
|
|
* This conforms to the standard OLE IPropertyStorage::ReadPropertyNames
|
|
* method.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pstmProp - Pointer to property stream.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 9/3/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::WritePropertyNames(
|
|
ULONG cpropid,
|
|
const PROPID rgpropid[],
|
|
const LPOLESTR rglpwstrName[])
|
|
{
|
|
DBG_FN(CWiaItem::WritePropertyNames);
|
|
PROPVARIANT *pv;
|
|
PROPSPEC *pspec;
|
|
ULONG index;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::WritePropertyNames, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
pv = (PROPVARIANT*) LocalAlloc(LPTR, sizeof(PROPVARIANT) * cpropid);
|
|
if (!pv) {
|
|
DBG_ERR(("CWiaItem::WritePropertyNames, Out of memory"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
pspec = (PROPSPEC*) LocalAlloc(LPTR, sizeof(PROPSPEC) * cpropid);
|
|
if (!pspec) {
|
|
DBG_ERR(("CWiaItem::WritePropertyNames, Out of memory"));
|
|
LocalFree(pv);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// Put PROPIDs into the PROPSPEC array.
|
|
//
|
|
|
|
for (index = 0; index < cpropid; index++) {
|
|
pspec[index].ulKind = PRSPEC_PROPID;
|
|
pspec[index].propid = rgpropid[index];
|
|
}
|
|
|
|
hr = (m_pPropStg->AccessStg())->ReadMultiple(cpropid,
|
|
pspec,
|
|
pv);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Make sure the properties are App. written properties. If a valid
|
|
// access flag for a property exists, then it was written by the
|
|
// driver and not the App, so exit.
|
|
//
|
|
|
|
for (index = 0; index < cpropid; index++) {
|
|
if (pv[index].vt != VT_EMPTY) {
|
|
DBG_ERR(("CWiaItem::WritePropertyNames, not allowed to write prop: %d.",rgpropid[index]));
|
|
hr = E_ACCESSDENIED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = (m_pPropStg->CurStg())->WritePropertyNames(cpropid,
|
|
rgpropid,
|
|
rglpwstrName);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::WritePropertyNames, WritePropertyNames failed"));
|
|
}
|
|
}
|
|
} else {
|
|
DBG_ERR(("CWiaItem::WritePropertyNames, Reading Access values failed"));
|
|
}
|
|
|
|
LocalFree(pspec);
|
|
LocalFree(pv);
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::Enum
|
|
*
|
|
* Returns a IEnumSTATPROPSTG enumerator over the current value property
|
|
* storage. Conforms to the standard OLE IPRopertyStorage::Enum method.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pstmProp - Pointer to property stream.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 9/3/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::Enum(
|
|
IEnumSTATPROPSTG __RPC_FAR *__RPC_FAR *ppenum)
|
|
{
|
|
DBG_FN(CWiaItem::Enum);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Enum, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return (m_pPropStg->CurStg())->Enum(ppenum);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::WriteMultiple
|
|
*
|
|
* This method writes the specified number of properties into the item's
|
|
* property storage. Validation will be performed on those property
|
|
* values. The properties will be restored to their old (valid) values
|
|
* if validation fails.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* cpspec - Number of properties to write.
|
|
* rgpspec - Array of PropSpec's specifying which properties
|
|
* are to be written.
|
|
* rgpropvar - Array containing values that the properties
|
|
* will be set to.
|
|
* propidNameFirst - Minimum value for property identifiers when
|
|
* they don't exist and must be allocated.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status - S_OK if writes and validation succeeded.
|
|
* E_INVALIDARG if validation failed due to an
|
|
* incorrect property value.
|
|
* Other error returns are from
|
|
* ValidateWiaDrvItemAccess, CheckPropertyAccess,
|
|
* CreatePropertyStorage and CopyProperties.
|
|
*
|
|
* History:
|
|
*
|
|
* 9/3/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::WriteMultiple(
|
|
ULONG cpspec,
|
|
const PROPSPEC __RPC_FAR rgpspec[],
|
|
const PROPVARIANT __RPC_FAR rgpropvar[],
|
|
PROPID propidNameFirst)
|
|
{
|
|
DBG_FN(CWiaItem::WriteMultiple);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Corresponding driver item must be valid.
|
|
//
|
|
|
|
hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::WriteMultiple, ValidateDrvItemAccess failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::WriteMultiple, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// there is no point in going further if there are no properties to
|
|
// write
|
|
//
|
|
if(cpspec == 0) {
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// We do not want to fail users who erroneousely attempt to write
|
|
// to write to read-only properties IF that the values they
|
|
// are trying to write are the same as current values. To achive
|
|
// this, we first current values of the properties they want to
|
|
// write:
|
|
//
|
|
|
|
PROPVARIANT *curVals = (PROPVARIANT *) LocalAlloc(LPTR, sizeof(PROPVARIANT) * cpspec);
|
|
PROPSPEC *newSpecs = (PROPSPEC *) LocalAlloc(LPTR, sizeof(PROPSPEC) * cpspec);
|
|
PROPVARIANT *newVals = (PROPVARIANT *) LocalAlloc(LPTR, sizeof(PROPVARIANT) * cpspec);
|
|
ULONG newcpspec = cpspec;
|
|
|
|
if(curVals == NULL || newSpecs == NULL || newVals == NULL) {
|
|
DBG_ERR(("CWiaItem::WriteMultiple, failed to allocate memory"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
CopyMemory(newSpecs, rgpspec, sizeof(PROPSPEC) * cpspec);
|
|
CopyMemory(newVals, rgpropvar, sizeof(PROPVARIANT) * cpspec);
|
|
|
|
memset(curVals, 0, sizeof(PROPVARIANT) * cpspec);
|
|
hr = m_pPropStg->CurStg()->ReadMultiple(cpspec, rgpspec, curVals);
|
|
if(SUCCEEDED(hr)) {
|
|
//
|
|
// Now for every property value they want to write we check if
|
|
// it is the same as the current value
|
|
//
|
|
|
|
ULONG ulNewEltIndex = 0;
|
|
for(ULONG i = 0; i < cpspec; i++) {
|
|
|
|
if(curVals[i].vt != rgpropvar[i].vt)
|
|
continue;
|
|
|
|
if(memcmp(curVals + i, rgpropvar + i, sizeof(PROPVARIANT)) == 0 ||
|
|
(curVals[i].vt == VT_BSTR && !lstrcmp(curVals[i].bstrVal, rgpropvar[i].bstrVal)) ||
|
|
(curVals[i].vt == VT_CLSID && IsEqualGUID(*curVals[i].puuid, *rgpropvar[i].puuid)))
|
|
{
|
|
// the value "matches", wipe it from both arrays.
|
|
if(i != (cpspec - 1)) {
|
|
|
|
//
|
|
// Move a block of values/propspecs.
|
|
// The number of elements to move is 1 less than the
|
|
// remaining number of elements we still have to check.
|
|
// Move these elements up in the new value array - put
|
|
// them after the elements we've decided to keep so far
|
|
//
|
|
MoveMemory(newVals + ulNewEltIndex,
|
|
newVals + ulNewEltIndex + 1,
|
|
(cpspec - i - 1) * sizeof(PROPVARIANT));
|
|
MoveMemory(newSpecs + ulNewEltIndex,
|
|
newSpecs + ulNewEltIndex + 1,
|
|
(cpspec - i - 1) * sizeof(PROPSPEC));
|
|
}
|
|
|
|
newcpspec--;
|
|
} else {
|
|
//
|
|
// We want to keep this element, so increase the element index.
|
|
//
|
|
ulNewEltIndex++;
|
|
}
|
|
}
|
|
|
|
// It could happen that all values are the same, in which case we
|
|
// don't want to write anything at all
|
|
if(newcpspec == 0) {
|
|
hr = S_OK;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Verify write access to all requested properties. If any of the
|
|
// properties are read ony, the call fails with access denied.
|
|
//
|
|
|
|
hr = m_pPropStg->CheckPropertyAccess(TRUE,
|
|
newcpspec,
|
|
(PROPSPEC*)newSpecs);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::WriteMultiple, CheckPropertyAccess failed"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// First create the backup.
|
|
//
|
|
|
|
hr = m_pPropStg->Backup();
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Write property values.
|
|
//
|
|
|
|
hr = (m_pPropStg->CurStg())->WriteMultiple(newcpspec,
|
|
newSpecs,
|
|
newVals,
|
|
propidNameFirst);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Write was successful, so do validation
|
|
//
|
|
|
|
LONG lFlags = 0;
|
|
|
|
//
|
|
// Make sure all PropSpecs are using PropID's. If some of the
|
|
// PropSpecs are using string names, then convert them.
|
|
// This is so that drivers only have to deal with PropID's.
|
|
//
|
|
|
|
PROPSPEC *pPropSpec = NULL;
|
|
|
|
hr = m_pPropStg->NamesToPropIDs(newcpspec, (PROPSPEC*) newSpecs, &pPropSpec);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Let the device mini driver know the properties have changed.
|
|
// Device only gets propspec, must read prop values from item's
|
|
// property stream.
|
|
//
|
|
{
|
|
LOCK_WIA_DEVICE _LWD(this, &hr);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_pActiveDevice->m_DrvWrapper.WIA_drvValidateItemProperties((BYTE*)this,
|
|
lFlags,
|
|
newcpspec,
|
|
(pPropSpec ? pPropSpec : newSpecs),
|
|
&m_lLastDevErrVal);
|
|
}
|
|
}
|
|
|
|
if (pPropSpec) {
|
|
LocalFree(pPropSpec);
|
|
pPropSpec = NULL;
|
|
}
|
|
} else {
|
|
DBG_ERR(("CWiaItem::WriteMultiple, conversion to PropIDs failed"));
|
|
}
|
|
|
|
} else {
|
|
DBG_ERR(("CWiaItem::WriteMultiple, test write failed"));
|
|
}
|
|
|
|
HRESULT hresult;
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Validation passed, so free the backups. Use a new
|
|
// HRESULT, since we don't want to overwrite hr returned by
|
|
// drvValidateItemProperties.
|
|
//
|
|
|
|
hresult = m_pPropStg->ReleaseBackups();
|
|
if (FAILED(hresult)) {
|
|
DBG_ERR(("CWiaItem::WriteMultiple, ReleaseBackups failed, continuing anyway..."));
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// Didn't pass validation failed, so restore old values. Use
|
|
// a new HRESULT, since we don't want to overwrite hr returned
|
|
// by drvValidateItemProperties.
|
|
//
|
|
|
|
hresult = m_pPropStg->Undo();
|
|
if (FAILED(hresult)) {
|
|
|
|
DBG_ERR(("CWiaItem::WriteMultiple, Undo() failed, could not restore invalid properties to their original values"));
|
|
}
|
|
}
|
|
} else {
|
|
DBG_ERR(("CWiaItem::WriteMultiple, couldn't make backup copy of properties"));
|
|
}
|
|
|
|
Cleanup:
|
|
if(curVals) {
|
|
FreePropVariantArray(cpspec, curVals);
|
|
LocalFree(curVals);
|
|
}
|
|
if(newVals) LocalFree(newVals);
|
|
if(newSpecs) LocalFree(newSpecs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* GetPropertyAttributes
|
|
*
|
|
* Get the access flags and valid values for a property.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiasContext - Pointer to WIA item
|
|
* cPropSpec - The number of properties
|
|
* pPropSpec - array of property specification.
|
|
* pulAccessFlags - array of LONGs access flags.
|
|
* pPropVar - Pointer to returned valid values.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/15/1999 Original Version
|
|
* 07/19/1999 Moved from iitem to ipropitm to implement IWiaPropertyStorage
|
|
* interface.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::GetPropertyAttributes(
|
|
ULONG cPropSpec,
|
|
PROPSPEC pPropSpec[],
|
|
ULONG pulAccessFlags[],
|
|
PROPVARIANT ppvValidValues[])
|
|
{
|
|
DBG_FN(CWiaItem::GetPropertyAttributes);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::GetPropertyAttributes, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// RPC has already done parameter validation for us, so call
|
|
// GetPropertyAttributesHelper to do the work.
|
|
//
|
|
return GetPropertyAttributesHelper(this,
|
|
cPropSpec,
|
|
pPropSpec,
|
|
pulAccessFlags,
|
|
ppvValidValues);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::GetCount
|
|
*
|
|
* Returns the number of properties stored in an item's current value
|
|
* property storage.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pulPropCount - Address to store the property count.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 9/3/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::GetCount(
|
|
ULONG* pulPropCount)
|
|
{
|
|
DBG_FN(CWiaItem::GetCount);
|
|
IEnumSTATPROPSTG *pIEnum;
|
|
STATPROPSTG stg;
|
|
ULONG ulCount;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pulPropCount == NULL) {
|
|
DBG_ERR(("CWiaItem::GetCount, NULL parameter!"));
|
|
return E_INVALIDARG;
|
|
} else {
|
|
*pulPropCount = 0;
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::GetCount, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = (m_pPropStg->CurStg())->Enum(&pIEnum);
|
|
if (SUCCEEDED(hr)) {
|
|
ulCount = 0;
|
|
|
|
while (pIEnum->Next(1, &stg, NULL) == S_OK) {
|
|
ulCount++;
|
|
|
|
if(stg.lpwstrName) {
|
|
CoTaskMemFree(stg.lpwstrName);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = S_OK;
|
|
*pulPropCount = ulCount;
|
|
} else {
|
|
DBG_ERR(("CWiaItem::GetCount, pIEnum->Next failed (0x%X)", hr));
|
|
}
|
|
pIEnum->Release();
|
|
} else {
|
|
DBG_ERR(("CWiaItem::GetCount, Enum off CurStg failed (0x%X)", hr));
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::GetPropertyStream
|
|
*
|
|
* Get a copy of an items property stream. Caller must free returned
|
|
* property stream.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pCompatibilityId - Address of GUID to receive the device's property
|
|
* stream CompatibilityId.
|
|
* ppstmProp - Pointer to returned property stream.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 09/03/1998 Original Version
|
|
* 12/12/1999 Modified to use CompatibilityId
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::GetPropertyStream(
|
|
GUID *pCompatibilityId,
|
|
LPSTREAM *ppstmProp)
|
|
{
|
|
DBG_FN(CWiaItem::GetPropertyStream);
|
|
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::GetPropertyStream, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return m_pPropStg->GetPropertyStream(pCompatibilityId, ppstmProp);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::SetPropertyStream
|
|
*
|
|
* Set an items property stream.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pCompatibilityId - Pointer to a GUID representing the property
|
|
* stream CompatibilityId.
|
|
* pstmProp - Pointer to property stream.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 09/03/1998 Original Version
|
|
* 12/12/1999 Modified to use CompatibilityId
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::SetPropertyStream(
|
|
GUID *pCompatibilityId,
|
|
LPSTREAM pstmProp)
|
|
{
|
|
DBG_FN(CWiaItem::SetPropertyStream);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::SetPropertyStream, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return m_pPropStg->SetPropertyStream(pCompatibilityId, this, pstmProp);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
*
|
|
* Methods of IPropertyStorage not directly off IWiaPropertySTorage
|
|
*
|
|
* DeleteMultiple
|
|
* DeletePropertyNames
|
|
* Commit
|
|
* Revert
|
|
* SetTimes
|
|
* SetClass
|
|
* Stat
|
|
*
|
|
* 9/3/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::DeleteMultiple(
|
|
ULONG cpspec,
|
|
const PROPSPEC __RPC_FAR rgpspec[])
|
|
{
|
|
DBG_FN(CWiaItem::DeleteMultiple);
|
|
return E_ACCESSDENIED;
|
|
}
|
|
|
|
HRESULT _stdcall CWiaItem::DeletePropertyNames(
|
|
ULONG cpropid,
|
|
const PROPID __RPC_FAR rgpropid[])
|
|
{
|
|
DBG_FN(CWiaItem::DeletePropertyNames);
|
|
return E_ACCESSDENIED;
|
|
}
|
|
|
|
HRESULT _stdcall CWiaItem::Commit(DWORD grfCommitFlags)
|
|
{
|
|
DBG_FN(CWiaItem::Commit);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Commit, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = (m_pPropStg->CurStg())->Commit(grfCommitFlags);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _stdcall CWiaItem::Revert(void)
|
|
{
|
|
DBG_FN(CWiaItem::Revert);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Revert, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = (m_pPropStg->CurStg())->Revert();
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _stdcall CWiaItem::SetTimes(
|
|
const FILETIME __RPC_FAR *pctime,
|
|
const FILETIME __RPC_FAR *patime,
|
|
const FILETIME __RPC_FAR *pmtime)
|
|
{
|
|
DBG_FN(CWiaItem::SetTimes);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::SetTimes, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = (m_pPropStg->CurStg())->SetTimes(pctime,patime,pmtime);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _stdcall CWiaItem::SetClass(REFCLSID clsid)
|
|
{
|
|
DBG_FN(CWiaItem::SetClass);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::SetClass, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
return (m_pPropStg->CurStg())->SetClass(clsid);
|
|
}
|
|
|
|
HRESULT _stdcall CWiaItem::Stat(STATPROPSETSTG *pstatpsstg)
|
|
{
|
|
DBG_FN(CWiaItem::Stat);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Stat, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = (m_pPropStg->CurStg())->Stat(pstatpsstg);
|
|
return hr;
|
|
}
|