Leaked source code of windows server 2003
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.
 
 
 
 
 
 

783 lines
20 KiB

/*++
Copyright (C) 1999- Microsoft Corporation
Module Name:
eventcb.cpp
Abstract:
This module implements CWiaPTPEventCallback class
Author:
William Hsieh (williamh) created
Revision History:
--*/
#include "pch.h"
//
// This method is the callback function for every PTP event
//
// Input:
// pEvent -- PTP event block
//
HRESULT
CWiaMiniDriver::EventCallbackDispatch(
PPTP_EVENT pEvent
)
{
DBG_FN("CWiaMiniDriver::EventCallback");
HRESULT hr = S_OK;
CPtpMutex cpm(m_hPtpMutex);
if (!pEvent)
{
wiauDbgError("EventCallback", "invalid arg");
return E_INVALIDARG;
}
//
// Events are not expected when there is no open session. Just ignore the event
//
if (!m_pPTPCamera || !m_pPTPCamera->IsCameraSessionOpen())
{
wiauDbgError("EventCallback", "events not expected while there is no open session");
return E_FAIL;
}
//
// Figure out what the event is and call the appropriate function
//
switch (pEvent->EventCode)
{
case PTP_EVENTCODE_CANCELTRANSACTION:
hr = S_OK;
break;
case PTP_EVENTCODE_OBJECTADDED:
hr = AddNewObject(pEvent->Params[0]);
break;
case PTP_EVENTCODE_OBJECTREMOVED:
hr = RemoveObject(pEvent->Params[0]);
break;
case PTP_EVENTCODE_STOREADDED:
hr = AddNewStorage(pEvent->Params[0]);
break;
case PTP_EVENTCODE_STOREREMOVED:
hr = RemoveStorage(pEvent->Params[0]);
break;
case PTP_EVENTCODE_DEVICEPROPCHANGED:
hr = DevicePropChanged((WORD) pEvent->Params[0]);
break;
case PTP_EVENTCODE_OBJECTINFOCHANGED:
hr = ObjectInfoChanged(pEvent->Params[0]);
break;
case PTP_EVENTCODE_DEVICEINFOCHANGED:
// WIAFIX-8/29/2000-davepar Need to handle this
//hr = RebuildDrvItemTree(&DevErrVal);
break;
case PTP_EVENTCODE_REQUESTOBJECTTRANSFER:
//
// This event is ignored, because we don't know where to put the image. Maybe
// it should cause a "button pushed" event.
//
break;
case PTP_EVENTCODE_STOREFULL:
hr = StorageFull(pEvent->Params[0]);
break;
case PTP_EVENTCODE_DEVICERESET:
// WIAFIX-8/29/2000-davepar Need to handle this
//hr = RebuildDrvItemTree(&DevErrVal);
break;
case PTP_EVENTCODE_STORAGEINFOCHANGED:
hr = StorageInfoChanged(pEvent->Params[0]);
break;
case PTP_EVENTCODE_CAPTURECOMPLETE:
hr = CaptureComplete();
break;
case PTP_EVENTCODE_UNREPORTEDSTATUS:
// WIAFIX-8/29/2000-davepar Need to handle this
//hr = RebuildDrvItemTree(&DevErrVal);
break;
default:
//
// If it is a vendor's event, post it
//
if (pEvent->EventCode & PTP_DATACODE_VENDORMASK)
{
hr = PostVendorEvent(pEvent->EventCode);
}
break;
}
return hr;
}
//
// This function adds a new object to the driver item tree. If a new driver
// item is added, a WIA_EVENT_ITEM_CREATED event will be signaled.
//
// Input:
// ObjectHandle -- the new object handle
//
HRESULT
CWiaMiniDriver::AddNewObject(DWORD ObjectHandle)
{
DBG_FN("CWiaMiniDriver::AddNewObject");
HRESULT hr = S_OK;
//
// If there is a capture in progress, we need to wait until all new objects are reported, and
// only then start querying imformation about them. See a sample sequence from the spec below:
//
// -> InitiateCapture Operation ->
// <- InitiateCapture Response <-
// <- ObjectAdded Event(1) <-
// <- ObjectAdded Event(2) <-
// <- ObjectAdded Event(n) <-
// <- CaptureComplete Event <-
// -> GetObjectInfo Operation(1) ->
// <- ObjectInfo Dataset/Response(1) <-
// -> GetObjectInfo Operation(2) ->
// <- ObjectInfo Dataset/Response(2) <-
// -> GetObjectInfo Operation(n) ->
// <- ObjectInfo Dataset/Response(n) <-
//
//
// Check if there is a capture in progress
//
DWORD dwWait = WaitForSingleObject(m_TakePictureDoneEvent, 0);
//
// If there is no capture in progress, process the new object immediately
//
if (dwWait == WAIT_OBJECT_0)
{
hr = AddObject(ObjectHandle, TRUE);
if (FAILED(hr))
{
wiauDbgError("AddNewObject", "AddObject failed");
goto Cleanup;
}
}
//
// If there is a capture in progress, add the new object's handle to the list,
// all new objects will be processed once capture is finished
//
else if (dwWait == WAIT_TIMEOUT)
{
m_CapturedObjects.Add(ObjectHandle);
}
//
// WAIT_FAILED or WAIT_ABANDONED - something's wrong
//
else
{
wiauDbgError("AddNewObject", "WaitForSingle object failed");
hr = E_FAIL;
goto Cleanup;
}
Cleanup:
return hr;
}
//
// This function removes the given object handle from the driver item tree.
// If the object handle has a driver item associated with it and the
// driver item is removed, a WIA_EVENT_ITEM_REMOVED event will be signaled.
//
// Input:
// ObjectHandle -- the object handle to be removed
//
HRESULT
CWiaMiniDriver::RemoveObject(DWORD ObjectHandle)
{
DBG_FN("CWiaMiniDriver::RemoveObject");
HRESULT hr = S_OK;
//
// Find the driver item for the object handle.
//
IWiaDrvItem *pDrvItem = m_HandleItem.Lookup(ObjectHandle);
if (!pDrvItem)
{
wiauDbgError("RemoveObject", "tried to remove object that doesn't exist");
return S_FALSE;
}
//
// Try to remove the object from the ancillary assoc array, in case it's there too. Ancillary
// association objects actually point to images in the handle/item map, so don't delete the
// actual item
//
if (m_AncAssocParent.Remove(ObjectHandle))
{
wiauDbgTrace("RemoveObject", "ancillary association object removed");
}
else
{
BSTR bstrFullName;
hr = pDrvItem->GetFullItemName(&bstrFullName);
if (FAILED(hr))
{
wiauDbgError("RemoveObject", "GetFullItemName failed");
return hr;
}
hr = pDrvItem->RemoveItemFromFolder(WiaItemTypeDisconnected);
if (FAILED(hr))
{
wiauDbgError("RemoveObject", "UnlinkItemTree failed");
return hr;
}
hr = wiasQueueEvent(m_bstrDeviceId, &WIA_EVENT_ITEM_DELETED, bstrFullName);
if (FAILED(hr))
{
wiauDbgError("RemoveObject", "wiasQueueEvent failed");
return hr;
}
SysFreeString(bstrFullName);
}
//
// Remove the object from the handle/drvItem association
//
m_HandleItem.Remove(ObjectHandle);
return hr;
}
//
// This function adds a new storage to the driver item tree.
// A WIA_EVENT_STORAGE_CREATED event will be singaled.
//
// Input:
// StorageId -- the new storage id to be added
//
HRESULT
CWiaMiniDriver::AddNewStorage(DWORD StorageId)
{
DBG_FN("CWiaMiniDriver::AddNewStorage");
HRESULT hr = S_OK;
CArray32 StorageIdList;
//
// If several logical stores were added, the device may indicate
// to re-enumerate the stores
//
if (StorageId == PTP_STORAGEID_UNDEFINED)
{
hr = m_pPTPCamera->GetStorageIDs(&StorageIdList);
if (FAILED(hr))
{
wiauDbgError("AddNewStorage", "GetStorageIDs failed");
return hr;
}
//
// Loop through the list of new storage ids, removing the ones
// that have already been enumerated
//
int index;
for (int count = 0; count < StorageIdList.GetSize(); count++)
{
index = m_StorageIds.Find(StorageIdList[count]);
if (index >= 0)
{
StorageIdList.RemoveAt(index);
}
}
}
//
// Otherwise there is just one storage id to work on
//
else
{
StorageIdList.Add(StorageId);
}
//
// Loop through all of the new storage ids
//
CPtpStorageInfo tempSI;
for (int storageIndex = 0; storageIndex < StorageIdList.GetSize(); storageIndex++)
{
//
// Get info for the new storage
//
hr = m_pPTPCamera->GetStorageInfo(StorageIdList[storageIndex], &tempSI);
if (FAILED(hr))
{
wiauDbgError("drvInitializeWia", "GetStorageInfo failed");
return hr;
}
//
// Add the storage id to the main list
//
if (!m_StorageIds.Add(StorageIdList[storageIndex]))
{
wiauDbgError("AddNewStorage", "add storage id failed");
return E_OUTOFMEMORY;
}
//
// Add storage info to array
//
if (!m_StorageInfos.Add(tempSI))
{
wiauDbgError("drvInitializeWia", "add storage info failed");
return E_OUTOFMEMORY;
}
//
// Add an empty entry to the DCIM handle array
//
ULONG dummy = 0;
if (!m_DcimHandle.Add(dummy))
{
wiauDbgError("AddNewStorage", "add dcim handle failed");
return E_OUTOFMEMORY;
}
//
// Loop through all of the objects on the new storage, adding them one
// at a time.
//
CArray32 ObjectHandleList;
hr = m_pPTPCamera->GetObjectHandles(StorageIdList[storageIndex], PTP_FORMATCODE_ALL,
PTP_OBJECTHANDLE_ALL, &ObjectHandleList);
if (FAILED(hr))
{
wiauDbgError("AddNewStorage", "GetObjectHandles failed");
return hr;
}
//
// Iterate through the object handles, creating a WIA driver item for each
//
for (int objectindex = 0; objectindex < ObjectHandleList.GetSize(); objectindex++)
{
hr = AddObject(ObjectHandleList[objectindex], TRUE);
if (FAILED(hr))
{
wiauDbgError("AddNewStorage", "AddObject failed");
return hr;
}
}
}
return hr;
}
//
// This function removes all of the objects on a storage from the
// driver item tree, signalling WIA_EVENT_ITEM_DELETED as appropriate.
//
// Input:
// StorageId -- storage to delete
//
HRESULT
CWiaMiniDriver::RemoveStorage(DWORD StorageId)
{
DBG_FN("CWiaMiniDriver::RemoveStorage");
HRESULT hr = S_OK;
//
// If the lower 16 bits of the storage id is 0xffff, an entire physical store
// was removed--match only the upper 16 bits of the storage id
//
DWORD StorageIdMask = PTP_STORAGEID_ALL;
if ((StorageId & PTP_STORAGEID_LOGICAL) == PTP_STORAGEID_LOGICAL)
{
StorageIdMask = PTP_STORAGEID_PHYSICAL;
StorageId &= StorageIdMask;
}
//
// Traverse the driver item tree depth-first looking for objects that were on
// the removed storage
//
CWiaArray<IWiaDrvItem*> ItemStack;
IWiaDrvItem *pCurrent = NULL;
IWiaDrvItem *pChild = NULL;
IWiaDrvItem *pSibling = NULL;
if (m_pDrvItemRoot)
{
hr = m_pDrvItemRoot->GetFirstChildItem(&pCurrent);
if (FAILED(hr))
{
wiauDbgError("RemoveStorage", "GetFirstChildItem failed");
return hr;
}
}
else
{
wiauDbgWarning("RemoveStorage", "Tree is not built yet (m_pDrvItemRoot is NULL)");
pCurrent = NULL;
}
while (pCurrent)
{
hr = pCurrent->GetFirstChildItem(&pChild);
//
// GetFirstChildItem returns E_INVALIDARG if there are no child items
//
if (FAILED(hr) && hr != E_INVALIDARG)
{
wiauDbgError("RemoveStorage", "GetFirstChildItem failed");
return hr;
}
//
// Children exist, so traverse down the tree
//
if (hr != E_INVALIDARG && pChild)
{
if (!ItemStack.Push(pCurrent))
{
wiauDbgError("RemoveStorage", "memory allocation failed");
return E_OUTOFMEMORY;
}
pCurrent = pChild;
pChild = NULL;
}
//
// No children, so look for siblings and potentially delete the current driver item
//
else
{
//
// Loop through all of the siblings
//
while (TRUE)
{
hr = pCurrent->GetNextSiblingItem(&pSibling);
if (FAILED(hr))
{
wiauDbgError("RemoveStorage", "GetNextSiblingItem failed");
return hr;
}
//
// See if the item is on the storage which was removed
//
PDRVITEM_CONTEXT pDrvItemContext;
hr = pCurrent->GetDeviceSpecContext((BYTE **) &pDrvItemContext);
if (FAILED(hr))
{
wiauDbgError("RemoveStorage", "GetDeviceSpecContext failed");
return hr;
}
if ((pDrvItemContext->pObjectInfo->m_StorageId & StorageIdMask) == StorageId)
{
//
// Remove the item
//
hr = RemoveObject(pDrvItemContext->pObjectInfo->m_ObjectHandle);
if (FAILED(hr))
{
wiauDbgError("RemoveStorage", "RemoveObject failed");
return hr;
}
}
//
// Found a sibling, so go to the top and look for children
//
if (pSibling)
{
pCurrent = pSibling;
pSibling = NULL;
break;
}
//
// No sibling, so pop up a level
//
else
{
if (ItemStack.GetSize() > 0)
{
if (!ItemStack.Pop(pCurrent))
{
wiauDbgError("RemoveStorage", "Pop failed");
return E_FAIL;
}
}
//
// No more levels to pop, so the loop is done
//
else
{
pCurrent = NULL;
break;
}
}
}
}
}
//
// Remove the store from the appropriate arrays
//
for (int count = 0; count < m_StorageIds.GetSize(); count++)
{
if ((m_StorageIds[count] & StorageIdMask) == StorageId)
{
m_StorageIds.RemoveAt(count);
m_StorageInfos.RemoveAt(count);
m_DcimHandle.RemoveAt(count);
count--;
}
}
return hr;
}
//
// This function updates the value for a property
//
// Input:
// PropCode -- property code that was updated
//
HRESULT
CWiaMiniDriver::DevicePropChanged(WORD PropCode)
{
DBG_FN("CWiaMiniDriver::DevicePropChanged");
HRESULT hr = S_OK;
int idx = m_DeviceInfo.m_SupportedProps.Find(PropCode);
if (idx < 0)
{
wiauDbgWarning("DevicePropChanged", "prop code not found %d", PropCode);
return hr;
}
hr = m_pPTPCamera->GetDevicePropValue(PropCode, &m_PropDescs[idx]);
if (FAILED(hr))
{
wiauDbgError("DevicePropChanged", "GetDevicePropValue failed");
return hr;
}
return hr;
}
//
// This function updates the object info for an object
//
// Input:
// ObjectHandle -- the object whose ObjectInfo needs updating
//
HRESULT
CWiaMiniDriver::ObjectInfoChanged(DWORD ObjectHandle)
{
DBG_FN("CWiaMiniDriver::ObjectInfoChanged");
HRESULT hr = S_OK;
//
// Find the driver item for the object handle.
//
IWiaDrvItem *pDrvItem = m_HandleItem.Lookup(ObjectHandle);
if (!pDrvItem)
{
wiauDbgError("ObjectInfoChanged", "tried to update object that doesn't exist");
return S_FALSE;
}
PDRVITEM_CONTEXT pDrvItemContext;
hr = pDrvItem->GetDeviceSpecContext((BYTE **) &pDrvItemContext);
if (FAILED(hr))
{
wiauDbgError("ObjectInfoChanged", "GetDeviceSpecContext failed");
return hr;
}
hr = m_pPTPCamera->GetObjectInfo(ObjectHandle, pDrvItemContext->pObjectInfo);
if (FAILED(hr))
{
wiauDbgError("ObjectInfoChanged", "GetObjectInfo failed");
return hr;
}
return hr;
}
//
// This function marks a storage as full
//
// Input:
// StorageId -- the storage to be marked
//
HRESULT
CWiaMiniDriver::StorageFull(DWORD StorageId)
{
DBG_FN("CWiaMiniDriver::StorageFull");
HRESULT hr = S_OK;
INT index = m_StorageIds.Find(StorageId);
if (index < 0)
{
wiauDbgError("StorageFull", "storage id not found");
return S_FALSE;
}
CPtpStorageInfo *pStorageInfo = &m_StorageInfos[index];
pStorageInfo->m_FreeSpaceInBytes = 0;
pStorageInfo->m_FreeSpaceInImages = 0;
//
// Signal that the TakePicture command is complete, if the driver was waiting for one
//
if (!SetEvent(m_TakePictureDoneEvent))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
wiauDbgErrorHr(hr, "EventCallbackDispatch", "SetEvent failed");
return hr;
}
return hr;
}
//
// This function updates a StorageInfo
//
// Input:
// StorageId -- the storage id to be updated
//
HRESULT
CWiaMiniDriver::StorageInfoChanged(DWORD StorageId)
{
DBG_FN("CWiaMiniDriver::StorageInfoChanged");
HRESULT hr = S_OK;
INT index = m_StorageIds.Find(StorageId);
if (index < 0)
{
wiauDbgError("StorageInfoChanged", "storage id not found");
return S_FALSE;
}
CPtpStorageInfo *pStorageInfo = &m_StorageInfos[index];
hr = m_pPTPCamera->GetStorageInfo(StorageId, pStorageInfo);
if (FAILED(hr))
{
wiauDbgError("StorageInfoChanged", "GetStorageInfo failed");
return hr;
}
return hr;
}
//
// This function processes the CaptureComplete event
//
// Input:
// StorageId -- the storage id to be updated
//
HRESULT
CWiaMiniDriver::CaptureComplete()
{
DBG_FN("CWiaMiniDriver::CaptureComplete");
HRESULT hr = S_OK;
//
// Signal that the TakePicture command is complete
//
if (!SetEvent(m_TakePictureDoneEvent))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
wiauDbgErrorHr(hr, "EventCallbackDispatch", "SetEvent failed");
return hr;
}
return hr;
}
//
// This function posts a vendor defined event
//
// Input:
// EventCode -- the event code
//
HRESULT
CWiaMiniDriver::PostVendorEvent(WORD EventCode)
{
DBG_FN("CWiaMiniDriver::PostVendorEvent");
HRESULT hr = S_OK;
CVendorEventInfo *pEventInfo = NULL;
pEventInfo = m_VendorEventMap.Lookup(EventCode);
if (pEventInfo)
{
hr = wiasQueueEvent(m_bstrDeviceId, pEventInfo->pGuid, NULL);
if (FAILED(hr))
{
wiauDbgError("PostVendorEvent", "wiasQueueEvent failed");
return hr;
}
}
return hr;
}