windows-nt/Source/XPSP1/NT/printscan/wia/common/stirt/stiobj.c
2020-09-26 16:20:57 +08:00

3556 lines
96 KiB
C

/*****************************************************************************
*
* StiObj.c
*
* Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
*
* Abstract:
*
* The IStillImage main interface.
*
* Contents:
*
* CStiObj_New
*
*****************************************************************************/
#include "sticomm.h"
#include "enum.h"
#include "stisvc.h"
//
// Private defines
//
#define DbgFl DbgFlSti
//
//
//
#undef IStillImage
//
// DEVICE_INFO_SIZE and WIA_DEVICE_INFO_SIZE
//
// These defines represent the space needed to store the device information
// structs and the string data that some of their members point to.
// STI_DEVICE_INFORMATION has 5 strings while STI_WIA_DEVICE_INFORMATION
// has 6. To be completely safe, these device info sizes should be
// (MAX_PATH * sizeof(WCHAR) * no. of strings) + struct size.
//
#define DEVICE_INFO_SIZE (sizeof(STI_DEVICE_INFORMATION)+(MAX_PATH * sizeof(WCHAR) * 5))
#define WIA_DEVICE_INFO_SIZE (sizeof(STI_WIA_DEVICE_INFORMATION)+(MAX_PATH * sizeof(WCHAR) * 6))
//
// DEVICE_LIST_SIZE. Note that this is currently a fixed size, but will change
// as soon we abstract device enumeration into a class.
//
// Device list size is fixed at the moment. It's size is:
// MAX_NUM_DEVICES * (max(DEVICE_INFO_SIZE, WIA_DEVICE_INFO_SIZE))
// i.e. enough to hold MAX_NUM_DEVICES only.
#define MAX_NUM_DEVICES 16
#define DEVICE_LIST_SIZE MAX_NUM_DEVICES * (max(DEVICE_INFO_SIZE, WIA_DEVICE_INFO_SIZE))
/*****************************************************************************
*
* @doc INTERNAL
*
* @struct CStiObj |
*
* The <i IStillImage> object, from which other things come.
*
*
* @field IStillImage | Sti |
*
* STI interface
*
* @field IStillImage | dwVersion |
*
* Version identifier
*
* @comm
*
* We contain no instance data, so no critical section
* is necessary.
*
*****************************************************************************/
typedef struct CStiObj {
/* Supported interfaces */
TFORM(IStillImage) TFORM(sti);
SFORM(IStillImage) SFORM(sti);
DWORD dwVersion;
} CStiObj, *PCStiObj;
#define ThisClass CStiObj
#define ThisInterface TFORM(IStillImage)
#define ThisInterfaceA IStillImageA
#define ThisInterfaceW IStillImageW
#define ThisInterfaceT IStillImage
/*****************************************************************************
*
* Declare the interfaces we will be providing.
*
*****************************************************************************/
Primary_Interface(CStiObj, TFORM(ThisInterfaceT));
Secondary_Interface(CStiObj, SFORM(ThisInterfaceT));
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | QueryInterface |
*
* Gives a client access to other interfaces on an object.
*
* @cwrap LPStillImage | lpStillImage
*
* @parm IN REFIID | riid |
*
* The requested interface's IID.
*
* @parm OUT LPVOID * | ppvObj |
*
* Receives a pointer to the obtained interface.
*
* @returns
*
* Returns a COM error code.
*
* @xref OLE documentation for <mf IUnknown::QueryInterface>.
*
*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | AddRef |
*
* Increments the reference count for the interface.
*
* @cwrap LPStillImage | lpStillImage
*
* @returns
*
* Returns the object reference count.
*
* @xref OLE documentation for <mf IUnknown::AddRef>.
*
*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | Release |
*
* Decrements the reference count for the interface.
* If the reference count on the object falls to zero,
* the object is freed from memory.
*
* @cwrap LPStillImage | lpStillImage
*
* @returns
*
* Returns the object reference count.
*
* @xref OLE documentation for <mf IUnknown::Release>.
*
*****************************************************************************
*
* @doc INTERNAL
*
* @method HRESULT | IStillImage | QIHelper |
*
* We don't have any dynamic interfaces and simply forward
* to <f Common_QIHelper>.
*
* @parm IN REFIID | riid |
*
* The requested interface's IID.
*
* @parm OUT LPVOID * | ppvObj |
*
* Receives a pointer to the obtained interface.
*
*****************************************************************************
*
* @doc INTERNAL
*
* @method HRESULT | IStillImage | Finalize |
*
* We don't have any instance data, so we can just
* forward to <f Common_Finalize>.
*
*****************************************************************************/
#ifdef DEBUG
Default_QueryInterface(CStiObj)
Default_AddRef(CStiObj)
Default_Release(CStiObj)
#else
#define CStiObj_QueryInterface Common_QueryInterface
#define CStiObj_AddRef Common_AddRef
#define CStiObj_Release Common_Release
#endif
#define CStiObj_QIHelper Common_QIHelper
//#define CStiObj_Finalize Common_Finalize
#pragma BEGIN_CONST_DATA
#pragma END_CONST_DATA
/*****************************************************************************
*
* @doc INTERNAL
*
* @method HRESULT | IStillImage | CreateDeviceHelper |
*
* Creates and initializes an instance of a device which is
* specified by the GUID and IID.
*
* @cwrap LPStillImage | lpStillImage
*
* @parm IN PCGUID | pguid |
*
* See <mf IStillImage::CreateDevice>.
*
* @parm OUT PPV | ppvObj |
*
* See <mf IStillImage::CreateDevice>.
*
* @parm IN LPUNKNOWN | punkOuter |
*
* See <mf IStillImage::CreateDevice>.
*
* @parm IN RIID | riid |
*
* The interface the application wants to create. This will
* be <i IStillImageDevice> .
* If the object is aggregated, then this parameter is ignored.
*
* @returns
*
* Returns a COM error code.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_CreateDeviceHelper(
PCStiObj this,
LPWSTR pwszDeviceName,
PPV ppvObj,
DWORD dwMode,
PUNK punkOuter,
RIID riid)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProc(CStiObj_CreateDeviceHelper,(_ "ppxG", this, pwszDeviceName, punkOuter, riid));
hres = CStiDevice_New(punkOuter, riid, ppvObj);
if (SUCCEEDED(hres) && punkOuter == 0) {
PSTIDEVICE pdev = *ppvObj;
hres = IStiDevice_Initialize(pdev, g_hInst,pwszDeviceName,this->dwVersion,dwMode);
if (SUCCEEDED(hres)) {
} else {
Invoke_Release(ppvObj);
}
}
ExitOleProcPpv(ppvObj);
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | CreateDevice |
*
* Creates and initializes an instance of a device which is
* specified by the GUID and IID.
*
* @cwrap LPStillImage | lpStillImage
*
* @parm REFGUID | rguid |
* Identifies the instance of the
* device for which the indicated interface
* is requested. The <mf IStillImage::EnumDevices> method
* can be used to determine which instance GUIDs are supported by
* the system.
*
* @parm OUT LPSTIDEVICE * | lplpStillImageDevice |
* Points to where to return
* the pointer to the <i IStillImageDevice> interface, if successful.
*
* @parm IN LPUNKNOWN | punkOuter | Pointer to controlling unknown
* for OLE aggregation, or 0 if the interface is not aggregated.
* Most callers will pass 0.
*
* @comm Calling this function with <p punkOuter> = NULL
* is equivalent to creating the object via
* <f CoCreateInstance>(&CLSID_StillImageDevice, NULL,
* CLSCTX_INPROC_SERVER, <p riid>, <p lplpStillImageDevice>);
* then initializing it with <f Initialize>.
*
* Calling this function with <p punkOuter> != NULL
* is equivalent to creating the object via
* <f CoCreateInstance>(&CLSID_StillImageDevice, <p punkOuter>,
* CLSCTX_INPROC_SERVER, &IID_IUnknown, <p lplpStillImageDevice>).
* The aggregated object must be initialized manually.
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
* <c STIERR_NOINTERFACE> = <c E_NOINTERFACE>
* The specified interface is not supported by the object.
*
* <c STIERR_DEVICENOTREG> = The device instance does not
* correspond to a device that is registered with StillImage.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_CreateDeviceW(
PV pSti,
LPWSTR pwszDeviceName,
DWORD dwMode,
PSTIDEVICE *ppDev,
PUNK punkOuter
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::CreateDevice,(_ "ppp", pSti, pwszDeviceName, punkOuter));
// Validate passed pointer to interface and obtain pointer to object instance
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
hres = CStiObj_CreateDeviceHelper(this, pwszDeviceName, (PPV)ppDev,dwMode,punkOuter, &IID_IStiDevice);
}
ExitOleProcPpv(ppDev);
return hres;
}
STDMETHODIMP
CStiObj_CreateDeviceA(
PV pSti,
LPCSTR pszDeviceName,
DWORD dwMode,
PSTIDEVICE *ppDev,
PUNK punkOuter
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::CreateDevice,(_ "ppp", pSti, pszDeviceName, punkOuter));
// Validate passed pointer to interface and obtain pointer to object instance
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
PVOID pBuffer = NULL;
UINT uiSize = (lstrlenA(pszDeviceName)+1)*sizeof(WCHAR);
hres = AllocCbPpv(uiSize, &pBuffer);
if (SUCCEEDED(hres)) {
*((LPWSTR)pBuffer) = L'\0';
AToU(pBuffer,uiSize,pszDeviceName);
hres = CStiObj_CreateDeviceHelper(this,
(LPWSTR)pBuffer,
(PPV)ppDev,
dwMode,
punkOuter,
&IID_IStiDevice);
FreePpv(&pBuffer);
}
}
ExitOleProcPpv(ppDev);
return hres;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @method HRESULT | IStillImage | GetDeviceInfoHelper |
*
*
* @cwrap LPStillImage | lpStillImage
*
* @returns
*
* Returns a COM error code.
*
* No validation performed
*
*****************************************************************************/
BOOL INLINE
AddOneString(LPCWSTR pStart,LPCWSTR pNew,LPWSTR *ppTarget)
{
if (pStart + OSUtil_StrLenW(pNew) + 1 < *ppTarget ) {
(*ppTarget)-= (OSUtil_StrLenW(pNew) + 1);
OSUtil_lstrcpyW(*ppTarget,pNew);
return TRUE;
}
return FALSE;
}
/*
BOOL INLINE
AddOneStringA(LPCSTR pStart,LPCSTR pNew,LPSTR *ppTarget)
{
if (pStart + lstrlenA(pNew) + 1 < *ppTarget ) {
(*ppTarget)-= (lstrlenA(pNew) + 1);
lstrcpyA(*ppTarget,pNew);
return TRUE;
}
return FALSE;
}
*/
BOOL
PullFromRegistry(
HKEY hkeyDevice,
LPWSTR *ppwstrPointer,
LPCWSTR lpwstrKey,
LPCWSTR lpwstrBarrier,
LPWSTR *ppwstrBuffer
)
{
BOOL bReturn = TRUE;
LPWSTR pwstrNewString = NULL;
ReadRegistryString(hkeyDevice,lpwstrKey,L"",FALSE,&pwstrNewString);
*ppwstrPointer = NULL;
if (pwstrNewString) {
bReturn = AddOneString(lpwstrBarrier, pwstrNewString,ppwstrBuffer);
FreePv(pwstrNewString);
*ppwstrPointer = *ppwstrBuffer;
}
return bReturn;
}
STDMETHODIMP
GetDeviceInfoHelper(
LPWSTR pszDeviceName,
PSTI_DEVICE_INFORMATION *ppCurrentDevPtr,
PWSTR *ppwszCurrentString
)
{
HRESULT hres = STIERR_INVALID_PARAM;
HKEY hkeyDevice;
PSTI_DEVICE_INFORMATION pDevPtr = *ppCurrentDevPtr;
// PWSTR pwszNewString = NULL;
PWSTR pwszBarrier;
PWSTR pwszTargetString = *ppwszCurrentString;
DWORD dwMajorType,dwMinorType;
// Open device registry key
hres = OpenDeviceRegistryKey(pszDeviceName,NULL,&hkeyDevice);
if (!SUCCEEDED(hres)) {
return hres;
}
//
// Read flags and strings
//
pDevPtr->dwSize = cbX(STI_DEVICE_INFORMATION);
dwMajorType = dwMinorType = 0;
ZeroX(pDevPtr->DeviceCapabilities) ;
ZeroX(pDevPtr->dwHardwareConfiguration) ;
dwMajorType = (STI_DEVICE_TYPE)ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_DEVICETYPE_W,StiDeviceTypeDefault);
dwMinorType = (STI_DEVICE_TYPE)ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_DEVICESUBTYPE_W,0);
pDevPtr->DeviceCapabilities.dwGeneric = ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_GENERIC_CAPS_W,0);
pDevPtr->DeviceType = MAKELONG(dwMinorType,dwMajorType);
pDevPtr->dwHardwareConfiguration = ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_HARDWARE_W,0);
OSUtil_lstrcpyW(pDevPtr->szDeviceInternalName,pszDeviceName);
//
// Add strings
//
pwszBarrier = (LPWSTR)((LPBYTE)pDevPtr + pDevPtr->dwSize);
//
// Add strings
//
pwszBarrier = (LPWSTR)((LPBYTE)pDevPtr + pDevPtr->dwSize);
if (
!PullFromRegistry(hkeyDevice, &pDevPtr -> pszVendorDescription,
REGSTR_VAL_VENDOR_NAME_W, pwszBarrier, &pwszTargetString) ||
!PullFromRegistry(hkeyDevice, &pDevPtr->pszLocalName,
REGSTR_VAL_FRIENDLY_NAME_W, pwszBarrier, &pwszTargetString) ||
!PullFromRegistry(hkeyDevice, &pDevPtr->pszDeviceDescription,
REGSTR_VAL_DEVICE_NAME_W, pwszBarrier, &pwszTargetString) ||
!PullFromRegistry(hkeyDevice, &pDevPtr->pszPortName,
REGSTR_VAL_DEVICEPORT_W, pwszBarrier, &pwszTargetString) ||
//!PullFromRegistry(hkeyDevice, &pDevPtr->pszTwainDataSource,
//REGSTR_VAL_TWAIN_SOURCE_W, pwszBarrier, &pwszTargetString) ||
//!PullFromRegistry(hkeyDevice, &pDevPtr->pszEventList,
//REGSTR_VAL_EVENTS_W, pwszBarrier, &pwszTargetString) ||
!PullFromRegistry(hkeyDevice, &pDevPtr->pszPropProvider,
REGSTR_VAL_PROP_PROVIDER_W, pwszBarrier, &pwszTargetString)) {
// we ran out of memory, somewhere
RegCloseKey(hkeyDevice);
return E_OUTOFMEMORY;
}
#ifdef DEAD_CODE
ReadRegistryString(hkeyDevice,REGSTR_VAL_VENDOR_NAME_W,L"",FALSE,&pwszNewString);
pDevPtr->pszVendorDescription = NULL;
if (pwszNewString) {
if (!AddOneString(pwszBarrier,pwszNewString,&pwszTargetString)) {
// Not enough room for next string
hres = E_OUTOFMEMORY;
goto Cleanup;
}
FreePv(pwszNewString);
pwszNewString = NULL;
pDevPtr->pszVendorDescription = pwszTargetString;
}
ReadRegistryString(hkeyDevice,REGSTR_VAL_DEV_NAME_W,L"",FALSE,&pwszNewString);
if (!pwszNewString || !*pwszNewString) {
FreePv(pwszNewString);
pwszNewString = NULL;
ReadRegistryString(hkeyDevice,REGSTR_VAL_DRIVER_DESC_W,L"",FALSE,&pwszNewString);
}
pDevPtr->pszLocalName = NULL;
if (pwszNewString) {
if (!AddOneString(pwszBarrier,pwszNewString,&pwszTargetString)) {
// Not enough room for next string
hres = E_OUTOFMEMORY;
goto Cleanup;
}
FreePv(pwszNewString);
pwszNewString = NULL;
pDevPtr->pszLocalName = pwszTargetString;
}
#endif
*ppCurrentDevPtr += 1;
*ppwszCurrentString = pwszTargetString;
#ifdef DEAD_CODE
Cleanup:
if (pwszNewString) {
FreePv(pwszNewString);
}
#endif
RegCloseKey(hkeyDevice);
return S_OK;
}
/**************************************************************************\
* GetDeviceInfoHelperWIA
*
* get WIA info as well
*
* Arguments:
*
*
*
* Return Value:
*
* Status
*
* History:
*
* 10/6/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP
GetDeviceInfoHelperWIA(
LPWSTR pszDeviceName,
PSTI_WIA_DEVICE_INFORMATION *ppCurrentDevPtr,
PWSTR *ppwszCurrentString
)
{
HRESULT hres = STIERR_INVALID_PARAM;
HKEY hkeyDevice;
HKEY hkeyDeviceData;
PSTI_WIA_DEVICE_INFORMATION pDevPtr = *ppCurrentDevPtr;
PWSTR pwszBarrier;
PWSTR pwszTargetString = *ppwszCurrentString;
DWORD dwMajorType,dwMinorType;
BOOL bRet;
// Open device registry key
hres = OpenDeviceRegistryKey(pszDeviceName,NULL,&hkeyDevice);
if (!SUCCEEDED(hres)) {
return hres;
}
//
// open DeviceData field
//
hres = OpenDeviceRegistryKey(pszDeviceName,L"DeviceData",&hkeyDeviceData);
if (!SUCCEEDED(hres)) {
RegCloseKey(hkeyDevice);
return hres;
}
//
// Read flags and strings
//
pDevPtr->dwSize = cbX(STI_WIA_DEVICE_INFORMATION);
dwMajorType = dwMinorType = 0;
ZeroX(pDevPtr->DeviceCapabilities) ;
ZeroX(pDevPtr->dwHardwareConfiguration) ;
dwMajorType = (STI_DEVICE_TYPE)ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_DEVICETYPE_W,StiDeviceTypeDefault);
dwMinorType = (STI_DEVICE_TYPE)ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_DEVICESUBTYPE_W,0);
pDevPtr->DeviceCapabilities.dwGeneric = ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_GENERIC_CAPS_W,0);
pDevPtr->DeviceType = MAKELONG(dwMinorType,dwMajorType);
pDevPtr->dwHardwareConfiguration = ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_HARDWARE_W,0);
OSUtil_lstrcpyW(pDevPtr->szDeviceInternalName,pszDeviceName);
//
// Add strings
//
pwszBarrier = (LPWSTR)((LPBYTE)pDevPtr + pDevPtr->dwSize);
bRet = PullFromRegistry(hkeyDevice, &pDevPtr ->pszVendorDescription,
REGSTR_VAL_VENDOR_NAME_W, pwszBarrier, &pwszTargetString);
if (!bRet) {
goto InfoCleanup;
}
bRet = PullFromRegistry(hkeyDevice, &pDevPtr->pszLocalName,
REGSTR_VAL_FRIENDLY_NAME_W, pwszBarrier, &pwszTargetString);
if (!bRet) {
goto InfoCleanup;
}
bRet = PullFromRegistry(hkeyDevice, &pDevPtr->pszDeviceDescription,
REGSTR_VAL_DEVICE_NAME_W, pwszBarrier, &pwszTargetString);
if (!bRet) {
goto InfoCleanup;
}
bRet = PullFromRegistry(hkeyDevice, &pDevPtr->pszPortName,
REGSTR_VAL_DEVICEPORT_W, pwszBarrier, &pwszTargetString);
if (!bRet) {
goto InfoCleanup;
}
bRet = PullFromRegistry(hkeyDevice, &pDevPtr->pszPropProvider,
REGSTR_VAL_PROP_PROVIDER_W, pwszBarrier, &pwszTargetString);
if (!bRet) {
goto InfoCleanup;
}
//
// WIA VALUES
//
bRet = PullFromRegistry(hkeyDeviceData, &pDevPtr->pszServer,
WIA_DIP_SERVER_NAME_STR, pwszBarrier, &pwszTargetString);
if (!bRet) {
goto InfoCleanup;
}
*ppCurrentDevPtr += 1;
*ppwszCurrentString = pwszTargetString;
RegCloseKey(hkeyDeviceData);
RegCloseKey(hkeyDevice);
return S_OK;
InfoCleanup:
//
// we ran out of memory, somewhere
//
RegCloseKey(hkeyDevice);
RegCloseKey(hkeyDeviceData);
return E_OUTOFMEMORY;
}
/*
* Setting device information helper
*
*/
STDMETHODIMP
SetDeviceInfoHelper(
PSTI_DEVICE_INFORMATION pDevPtr
)
{
HRESULT hres = S_OK;
HKEY hkeyDevice;
PWSTR pwszNewString = NULL;
DWORD dwHardwareConfiguration;
DWORD dwError;
if (!pDevPtr || OSUtil_StrLenW(pDevPtr->szDeviceInternalName) > STI_MAX_INTERNAL_NAME_LENGTH) {
return STIERR_INVALID_PARAM;
}
//
// Open device registry key
//
hres = OpenDeviceRegistryKey(pDevPtr->szDeviceInternalName,NULL,&hkeyDevice);
if (!SUCCEEDED(hres)) {
return STIERR_INVALID_DEVICE_NAME;
}
ZeroX(dwHardwareConfiguration) ;
dwHardwareConfiguration = ReadRegistryDwordW( hkeyDevice,REGSTR_VAL_HARDWARE_W,0);
#ifdef NOT_IMPL
//
// Changing device information by caller is allowed only for Unknown device types
// For all others settings are handled by setup and control panel
//
if (dwHardwareConfiguration != STI_HW_CONFIG_UNKNOWN ) {
hres = STIERR_INVALID_HW_TYPE;
goto Cleanup;
}
#endif
//
// Store new port name, and new FriendlyName
//
if (!IsBadStringPtrW(pDevPtr->pszPortName, MAX_PATH * sizeof(WCHAR))) {
dwError = WriteRegistryStringW(hkeyDevice ,
REGSTR_VAL_DEVICEPORT_W,
pDevPtr->pszPortName,
(OSUtil_StrLenW(pDevPtr->pszPortName)+1)*sizeof(WCHAR),
REG_SZ
);
if ((dwError == ERROR_SUCCESS) &&
!(IsBadStringPtrW(pDevPtr->pszLocalName, MAX_PATH * sizeof(WCHAR)))) {
dwError = WriteRegistryStringW(hkeyDevice ,
REGSTR_VAL_FRIENDLY_NAME_W,
pDevPtr->pszLocalName,
(OSUtil_StrLenW(pDevPtr->pszLocalName)+1)*sizeof(WCHAR),
REG_SZ
);
if (dwError == ERROR_SUCCESS) {
hres = S_OK;
}
}
if (dwError != ERROR_SUCCESS) {
hres = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
}
else {
hres = STIERR_INVALID_PARAM;
goto Cleanup;
}
Cleanup:
if (pwszNewString) {
FreePv(pwszNewString);
}
RegCloseKey(hkeyDevice);
return hres;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @method HRESULT | IStillImage | IsStillImageDeviceRegistryNode |
*
* Verifies if given enumeration registry node is associated with Still Image device
*
* @cwrap LPStillImage | lpStillImage
*
* @returns
*
* TRUE if node is representing still image devie
*
* No validation performed
*
*****************************************************************************/
BOOL WINAPI
IsStillImageDeviceRegistryNode(
LPTSTR ptszDeviceKey
)
{
BOOL fRet = FALSE;
DWORD dwError;
HKEY hkeyDevice = NULL;
HKEY hkeyDeviceParameters = NULL;
TCHAR szDevClass[64]; // NOTE: This technically shouldn't be a
// hardcoded number, we should do a RegQueryValueEx
// to get the required size, allocate the memory,
// and then call RegQueryValueEx for the data.
// However, if either the class name or image name
// cannot fit into this buffer, we know it doesn't
// belong to us, so this is OK.
TCHAR szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH];
TCHAR szDeviceKey[MAX_PATH];
ULONG cbData;
//
// Open enumeration registry key
//
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, // hkey
ptszDeviceKey, // reg entry string
0, // dwReserved
KEY_READ, // access
&hkeyDevice); // pHkeyReturned.
if (ERROR_SUCCESS != dwError) {
return FALSE;
}
//
// First check it's class . It should be equal to "Image"
//
cbData = sizeof(szDevClass);
*szDevClass = TEXT('\0');
if ((RegQueryValueEx(hkeyDevice,
REGSTR_VAL_CLASS,
NULL,
NULL,
(PBYTE)szDevClass,
&cbData) != ERROR_SUCCESS) ||
(lstrcmpi(szDevClass, CLASSNAME) != 0)) {
fRet = FALSE;
goto CleanUp;
}
//
// Now we check subclass in one of two locations: either in enumeration subkey, or in
// control subkey
//
cbData = sizeof(szDevClass);
if (RegQueryValueEx(hkeyDevice,
REGSTR_VAL_SUBCLASS,
NULL,
NULL,
(PBYTE)szDevClass,
&cbData) == ERROR_SUCCESS) {
fRet = (lstrcmpi(szDevClass, STILLIMAGE) == 0) ? TRUE : FALSE;
goto CleanUp;
}
cbData = sizeof(szDevDriver);
dwError = RegQueryValueEx(hkeyDevice,
REGSTR_VAL_DRIVER,
NULL,
NULL,
(PBYTE)szDevDriver,
&cbData);
if (ERROR_SUCCESS != dwError ) {
goto CleanUp;
}
lstrcat(lstrcpy(szDeviceKey,
(g_NoUnicodePlatform) ? REGSTR_PATH_STIDEVICES : REGSTR_PATH_STIDEVICES_NT),
TEXT("\\"));
lstrcat(szDeviceKey,szDevDriver);
dwError = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
szDeviceKey,
0L,
NULL,
0L,
KEY_READ,
NULL,
&hkeyDeviceParameters,
NULL
);
if (ERROR_SUCCESS != dwError) {
goto CleanUp;
}
cbData = sizeof(szDevClass);
dwError = RegQueryValueEx(hkeyDeviceParameters,
REGSTR_VAL_SUBCLASS,
NULL,
NULL,
(PBYTE)szDevClass,
&cbData);
if (ERROR_SUCCESS == dwError) {
fRet = (lstrcmpi(szDevClass, STILLIMAGE) == 0) ? TRUE : FALSE;
goto CleanUp;
}
CleanUp:
if (hkeyDevice) {
RegCloseKey(hkeyDevice);
hkeyDevice = NULL;
}
if (hkeyDeviceParameters) {
RegCloseKey(hkeyDeviceParameters);
hkeyDeviceParameters = NULL;
}
return fRet;
} // endproc IsStillImageDeviceRegistryNode
/*
DWORD
EnumNextLevel(
LPSTR *ppCurrentDevPtr,
LPWSTR *ppwszCurrentString,
DWORD *pdwItemsReturned,
BOOL *pfAlreadyEnumerated,
LPSTR pszDeviceKey,
int Level
)
{
HKEY hkeyDevice;
char szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH];
WCHAR wszDeviceKey[MAX_PATH];
ULONG cbString;
ULONG cbData;
DWORD dwIndex;
DWORD dwError;
DEVINST dnDevNode;
USHORT cbEnumPath;
HANDLE hDevInfo;
GUID Guid;
DWORD dwRequired;
DWORD Idx;
SP_DEVINFO_DATA spDevInfoData;
DWORD dwConfigFlags;
dwError = 0;
if (Level == 0) {
if(!IsStillImageDeviceRegistryNodeA(pszDeviceKey)) {
//
// Nobody there...continue with the enumeration
//
return 0;
}
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, // hkey
pszDeviceKey, // reg entry string
0, // dwReserved
KEY_READ, // access
&hkeyDevice); // pHkeyReturned.
if (dwError != ERROR_SUCCESS) {
return 0;
}
dnDevNode = 0;
cbEnumPath = ((g_NoUnicodePlatform) ? lstrlen(REGSTR_PATH_ENUM) : lstrlen(REGSTR_PATH_NT_ENUM_A)) + 1;
CM_Locate_DevNode (&dnDevNode, pszDeviceKey + cbEnumPath, 0);
if (dnDevNode == 0 && *pfAlreadyEnumerated == FALSE) {
#ifdef NODEF
//
// This is dead code, it should be removed.
//
//
// Try to locate this devnode by forcing a re-enumeration.
//
if (SetupDiClassGuidsFromName (REGSTR_KEY_SCSI_CLASS, &Guid, sizeof(GUID), &dwRequired)) {
hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, 0);
if (hDevInfo != INVALID_HANDLE_VALUE) {
spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
CM_Reenumerate_DevNode (spDevInfoData.DevInst, CM_REENUMERATE_SYNCHRONOUS);
}
}
SetupDiDestroyDeviceInfoList (hDevInfo);
}
#endif
//
// Try again to locate our devnode.
//
*pfAlreadyEnumerated = TRUE;
CM_Locate_DevNode (&dnDevNode, pszDeviceKey + cbEnumPath, 0);
if (dnDevNode == 0) {
//
// Skip this one.
//
RegCloseKey(hkeyDevice);
return 0;
}
}
//
// Check that this device is in the current hardware profile
//
dwConfigFlags = 0;
CM_Get_HW_Prof_Flags (pszDeviceKey + cbEnumPath, 0, &dwConfigFlags, 0);
if (dwConfigFlags & CSCONFIGFLAG_DO_NOT_CREATE) {
//
// Skip this one.
//
RegCloseKey(hkeyDevice);
return 0;
}
cbData = sizeof(szDevDriver);
if ((RegQueryValueEx(hkeyDevice, REGSTR_VAL_DRIVER, NULL, NULL, szDevDriver,
&cbData) == ERROR_SUCCESS)) {
//
// Got one device - add it to the buffer
//
AToU(wszDeviceKey,sizeof(wszDeviceKey)/sizeof(WCHAR),szDevDriver);
dwError = (DWORD)GetDeviceInfoHelper(wszDeviceKey,
(PSTI_DEVICE_INFORMATION *)ppCurrentDevPtr,
ppwszCurrentString);
if (!SUCCEEDED(dwError)) {
RegCloseKey(hkeyDevice);
//
// Return value is HRESULT, we should return a Win32 error
//
if (dwError == E_OUTOFMEMORY) {
return ERROR_NOT_ENOUGH_MEMORY;
} else {
return ERROR_INVALID_DATA;
}
}
(*pdwItemsReturned)++;
RegCloseKey(hkeyDevice);
return 0;
}
RegCloseKey(hkeyDevice);
return 0;
}
cbString = lstrlen(pszDeviceKey);
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, // hkey
pszDeviceKey, // reg entry string
0, // dwReserved
KEY_READ, // access
&hkeyDevice); // pHkeyReturned.
for (dwIndex = 0; dwError == ERROR_SUCCESS; dwIndex++) {
*(pszDeviceKey + cbString) = '\\';
cbData = MAX_PATH - cbString - 1;
dwError = RegEnumKey(hkeyDevice,
dwIndex,
&pszDeviceKey[cbString+1],
cbData);
if (dwError == ERROR_SUCCESS) {
if ((dwError = EnumNextLevel (ppCurrentDevPtr,
ppwszCurrentString,
pdwItemsReturned,
pfAlreadyEnumerated,
pszDeviceKey,
Level - 1)) != ERROR_SUCCESS) {
RegCloseKey(hkeyDevice);
pszDeviceKey[cbString] = '\0';
return (dwError);
}
}
}
RegCloseKey(hkeyDevice);
pszDeviceKey[cbString] = '\0';
return(0);
}
*/
DWORD
EnumFromSetupApi(
LPSTR *ppCurrentDevPtr,
LPWSTR *ppwszCurrentString,
DWORD *pdwItemsReturned
)
{
HANDLE hDevInfo;
GUID Guid = GUID_DEVCLASS_IMAGE;
DWORD dwRequired;
DWORD Idx;
SP_DEVINFO_DATA spDevInfoData;
SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
HKEY hKeyDevice;
char szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH];
TCHAR tszDevClass[32];
WCHAR wszDeviceKey[MAX_PATH];
ULONG cbData;
DWORD dwError;
DWORD dwReturn;
DWORD dwType;
DWORD dwKeyType;
BOOL fRet;
LONG lRet;
PWIA_DEVKEYLIST pWiaDevKeyList;
dwRequired = 0;
dwError = ERROR_SUCCESS;
dwReturn = ERROR_NO_MATCH;
pWiaDevKeyList = NULL;
//
// Get the class device list
//
pWiaDevKeyList = WiaCreateDeviceRegistryList(TRUE);
if(NULL != pWiaDevKeyList){
for (Idx = 0; Idx < pWiaDevKeyList->dwNumberOfDevices; Idx++) {
//
// Check whether we have space for this device inside the device list.
// NOTE: This will change when the device list size becomes dynamic
//
if (((Idx + 1) * max(DEVICE_INFO_SIZE, WIA_DEVICE_INFO_SIZE)) > DEVICE_LIST_SIZE) {
break;
}
//
// Now get all the device info
//
cbData = sizeof(szDevDriver);
*szDevDriver = '\0';
dwError = RegQueryValueExA(pWiaDevKeyList->Dev[Idx].hkDeviceRegistry,
REGSTR_VAL_DEVICE_ID_A,
// REGSTR_VAL_FRIENDLY_NAME_A,
NULL,
NULL,
(LPBYTE)szDevDriver,
&cbData);
if(ERROR_SUCCESS == dwError){
AToU(wszDeviceKey,sizeof(wszDeviceKey)/sizeof(WCHAR),szDevDriver);
dwError = (DWORD)GetDeviceInfoHelper(wszDeviceKey,
(PSTI_DEVICE_INFORMATION *)ppCurrentDevPtr,
ppwszCurrentString);
if (!SUCCEEDED(dwError)) {
//
// dwError is an HRESULT, we should return a Win32 error
//
if (dwError == E_OUTOFMEMORY) {
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
} else {
dwReturn = ERROR_INVALID_DATA;
}
break;
} else {
//
// At least one device passed.
//
dwReturn = ERROR_SUCCESS;
}
(*pdwItemsReturned)++;
} else { // if(ERROR_SUCCESS == dwError)
} // if(ERROR_SUCCESS == dwError)
} // for (Idx = 0; pWiaDevKeyList->dwNumberOfDevices; Idx++)
} // if(NULL != pWiaDevKeyList)
//
// Free device registry list.
//
if(NULL != pWiaDevKeyList){
WiaDestroyDeviceRegistryList(pWiaDevKeyList);
}
return (dwReturn);
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @method HRESULT | IStillImage | BuildDeviceListHelper |
*
* Fills passed buffer with list of available still image devices
*
* @cwrap LPStillImage | lpStillImage
*
* @returns
*
* Returns a COM error code.
*
*****************************************************************************/
// BUGBUG does not honor filter flags
STDMETHODIMP
BuildDeviceListHelper(
DWORD dwType,
DWORD dwFlags,
DWORD *pdwItemsReturned,
LPVOID *ppBuffer
)
{
HRESULT hres;
DWORD dwError;
LPSTR pCurrentDevPtr;
LPWSTR pwszCurrentString;
BOOL fAlreadyEnumerated;
*pdwItemsReturned = 0;
*ppBuffer = NULL;
hres = S_OK;
// Get initial buffer for return data
hres = AllocCbPpv(DEVICE_LIST_SIZE, ppBuffer);
if (!SUCCEEDED(hres)) {
return E_OUTOFMEMORY;
}
hres = S_OK;
//
// Re-enumerate parallel device if it's installed and not detected on OS boot.
//
if(0 == dwFlags){
//
// Enumerate LPT port via WIA service.
//
SC_HANDLE hSCM;
SC_HANDLE hService;
SERVICE_STATUS ServiceStatus;
__try {
//
// Open Service Control Manager.
//
hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT);
if (!hSCM) {
dwError = GetLastError();
__leave;
}
//
// Open WIA service.
//
hService = OpenService(
hSCM,
STI_SERVICE_NAME,
SERVICE_USER_DEFINED_CONTROL
);
if (!hService) {
dwError = GetLastError();
__leave;
}
//
// Post custom service control message.
//
ControlService(hService, STI_SERVICE_CONTROL_LPTENUM, &ServiceStatus);
//
// Close service handle.
//
CloseServiceHandle(hService);
} // __try
__finally {
if(NULL != hSCM){
CloseServiceHandle( hSCM );
} // if(NULL != hSCM)
} // __finally
} // if(0 == dwFlags)
//
// NOTE: DEVICE_LIST_SIZE is hard coded for the time being. Checks are done in
// EnumFromSetupApi to ensure we never overrun this buffer.
//
pCurrentDevPtr = *ppBuffer;
pwszCurrentString = (LPWSTR)(pCurrentDevPtr + DEVICE_LIST_SIZE);
fAlreadyEnumerated = FALSE;
dwError = EnumFromSetupApi (&pCurrentDevPtr,
&pwszCurrentString,
pdwItemsReturned);
if (dwError != NOERROR) {
hres = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
FreePpv(ppBuffer);
}
return hres;
}
BOOL
TranslateDeviceInfo(
PSTI_DEVICE_INFORMATIONA pDest,
LPSTR *pCurrentStringDest,
PSTI_DEVICE_INFORMATIONW pSrc
)
{
LPSTR pStringDest = *pCurrentStringDest;
pDest->dwSize = cbX(STI_DEVICE_INFORMATIONA);
pDest->DeviceType = pSrc->DeviceType;
pDest->DeviceCapabilities = pSrc->DeviceCapabilities;
pDest->dwHardwareConfiguration = pSrc->dwHardwareConfiguration;
UToA(pDest->szDeviceInternalName,STI_MAX_INTERNAL_NAME_LENGTH,pSrc->szDeviceInternalName);
UToA(pStringDest,MAX_PATH,pSrc->pszVendorDescription);
pDest->pszVendorDescription = pStringDest;
pStringDest+=lstrlenA(pStringDest)+sizeof(CHAR);
UToA(pStringDest,MAX_PATH,pSrc->pszDeviceDescription);
pDest->pszDeviceDescription = pStringDest;
pStringDest+=lstrlenA(pStringDest)+sizeof(CHAR);
UToA(pStringDest,MAX_PATH,pSrc->pszPortName);
pDest->pszPortName = pStringDest;
pStringDest+=lstrlenA(pStringDest)+sizeof(CHAR);
UToA(pStringDest,MAX_PATH,pSrc->pszPropProvider);
pDest->pszPropProvider = pStringDest;
pStringDest+=lstrlenA(pStringDest)+sizeof(CHAR);
UToA(pStringDest,MAX_PATH,pSrc->pszLocalName);
pDest->pszLocalName = pStringDest;
pStringDest+=lstrlenA(pStringDest)+sizeof(CHAR);
*pCurrentStringDest = pStringDest;
return TRUE;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | GetDeviceList |
*
*
* @cwrap LPStillImage | lpStillImage
*
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
* <c STIERR_NOINTERFACE> = <c E_NOINTERFACE>
* The specified interface is not supported by the object.
*
* <c STIERR_DEVICENOTREG> = The device instance does not
* correspond to a device that is registered with StillImage.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_GetDeviceListW(
PV pSti,
DWORD dwType,
DWORD dwFlags,
DWORD *pdwItemsReturned,
LPVOID *ppBuffer
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::GetDeviceList,(_ "pp", pSti,ppBuffer ));
// Validate passed pointer to interface and obtain pointer to object instance
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
if ( SUCCEEDED(hres = hresFullValidPdwOut_(ppBuffer, s_szProc, 5)) &&
SUCCEEDED(hres = hresFullValidPdwOut_(pdwItemsReturned, s_szProc, 4))
) {
hres = BuildDeviceListHelper(dwType,dwFlags,pdwItemsReturned,ppBuffer);
if (!SUCCEEDED(hres) ) {
FreePpv(ppBuffer);
}
}
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_GetDeviceListA(
PV pSti,
DWORD dwType,
DWORD dwFlags,
DWORD *pdwItemsReturned,
LPVOID *ppBuffer
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::GetDeviceList,(_ "pp", pSti,ppBuffer ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
if ( SUCCEEDED(hres = hresFullValidPdwOut_(ppBuffer, s_szProc, 5)) &&
SUCCEEDED(hres = hresFullValidPdwOut_(pdwItemsReturned, s_szProc, 4))
) {
LPVOID pvTempBuffer = NULL;
UINT uiSize;
hres = BuildDeviceListHelper(dwType,dwFlags,pdwItemsReturned,&pvTempBuffer);
if (SUCCEEDED(hres) ) {
LPSTR pStringDest;
PSTI_DEVICE_INFORMATIONA pDest;
PSTI_DEVICE_INFORMATIONW pSrc;
UINT uiIndex;
//
// Allocate new buffer , transform data into ANSI and free scratch
//
uiSize = (UINT)LocalSize(pvTempBuffer);
if (uiSize > 0 && pdwItemsReturned > 0) {
hres = AllocCbPpv(uiSize, ppBuffer);
if (SUCCEEDED(hres)) {
pDest = *ppBuffer;
pSrc = pvTempBuffer;
pStringDest = (LPSTR)(pDest+ *pdwItemsReturned);
for (uiIndex = 0;
uiIndex < *pdwItemsReturned;
uiIndex++) {
TranslateDeviceInfo(pDest,&pStringDest,pSrc);
pDest++, pSrc++;
}
}
}
FreePpv(&pvTempBuffer);
}
}
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | GetDeviceInfo |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm REFGUID | rguid |
* Identifies the instance of the
* device for which the indicated interface
* is requested. The <mf IStillImage::EnumDevices> method
* can be used to determine which instance GUIDs are supported by
* the system.
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_GetDeviceInfoW(
PV pSti,
LPWSTR pwszDeviceName,
LPVOID *ppBuffer
)
{
HRESULT hres= STIERR_INVALID_PARAM;
PSTI_DEVICE_INFORMATION pCurrentDevPtr;
LPWSTR pwszCurrentString;
EnterProcR(IStillImage::GetDeviceInfo,(_ "ppp", pSti,pwszDeviceName,ppBuffer ));
// Validate passed pointer to interface and obtain pointer to object instance
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
// Get initial buffer for return data
hres = AllocCbPpv(DEVICE_INFO_SIZE, ppBuffer);
if (!SUCCEEDED(hres)) {
return E_OUTOFMEMORY;
}
// Get information on this device calling helper routine
pCurrentDevPtr = (PSTI_DEVICE_INFORMATION)*ppBuffer;
pwszCurrentString = (LPWSTR)((LPBYTE)*ppBuffer+DEVICE_INFO_SIZE);
hres=GetDeviceInfoHelper(pwszDeviceName,&pCurrentDevPtr,&pwszCurrentString);
if (!SUCCEEDED(hres)) {
FreePpv(ppBuffer);
}
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_GetDeviceInfoA(
PV pSti,
LPCSTR pszDeviceName,
LPVOID *ppBuffer
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::GetDeviceInfo,(_ "ppp", pSti,pszDeviceName,ppBuffer ));
// Validate passed pointer to interface and obtain pointer to object instance
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
WCHAR wszDeviceName[STI_MAX_INTERNAL_NAME_LENGTH] = {L'\0'};
PVOID pBuffer;
AToU(wszDeviceName,STI_MAX_INTERNAL_NAME_LENGTH,pszDeviceName);
hres = CStiObj_GetDeviceInfoW(pSti,wszDeviceName,&pBuffer);
if (SUCCEEDED(hres)) {
hres = AllocCbPpv(DEVICE_INFO_SIZE, ppBuffer);
if (SUCCEEDED(hres)) {
LPSTR pStringDest = (LPSTR)*ppBuffer+sizeof(STI_DEVICE_INFORMATIONA);
TranslateDeviceInfo((PSTI_DEVICE_INFORMATIONA)*ppBuffer,
&pStringDest,
(PSTI_DEVICE_INFORMATIONW)pBuffer);
FreePpv(&pBuffer);
}
}
}
ExitOleProc();
return hres;
}
/**************************************************************************\
* PrivateGetDeviceInfoW
*
* Private server entry point to get WIA device info
*
* Arguments:
*
*
*
* Return Value:
*
* Status
*
* History:
*
* 10/7/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP
StiPrivateGetDeviceInfoHelperW(
LPWSTR pwszDeviceName,
LPVOID *ppBuffer
)
{
HRESULT hres = STIERR_INVALID_PARAM;
LPWSTR pwszCurrentString;
PSTI_WIA_DEVICE_INFORMATION pCurrentDevPtr;
//
// Get initial buffer for return data
//
hres = AllocCbPpv(WIA_DEVICE_INFO_SIZE, ppBuffer);
if (!SUCCEEDED(hres)) {
return E_OUTOFMEMORY;
}
//
// Get information on this device calling helper routine
//
pCurrentDevPtr = (PSTI_WIA_DEVICE_INFORMATION)*ppBuffer;
pwszCurrentString = (LPWSTR)((LPBYTE)*ppBuffer+WIA_DEVICE_INFO_SIZE);
hres=GetDeviceInfoHelperWIA(pwszDeviceName, &pCurrentDevPtr,&pwszCurrentString);
if (!SUCCEEDED(hres)) {
FreePpv(ppBuffer);
*ppBuffer = NULL;
} else
{
if (*ppBuffer) {
if (OSUtil_StrLenW(((PSTI_WIA_DEVICE_INFORMATION) *ppBuffer)->pszServer) == 0)
{
//
// Assume that this is not a WIA device, since server name is
// blank.
//
FreePpv(ppBuffer);
*ppBuffer = NULL;
} else
{
//
// set size of buffer so buffers can be chained independently
//
if (pCurrentDevPtr) {
pCurrentDevPtr->dwSize = WIA_DEVICE_INFO_SIZE;
}
}
}
}
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | SetDeviceValue |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_SetDeviceValueW(
PV pSti,
LPWSTR pwszDeviceName,
LPWSTR pwszValueName,
DWORD Type,
LPBYTE pData,
DWORD cbData
)
{
HRESULT hres = STIERR_INVALID_PARAM;
HKEY hkeyDevice;
LONG dwError;
EnterProcR(IStillImage::SetDeviceValue,(_ "ppp", pSti,pwszDeviceName,pData ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
//
// Open device registry key
//
hres = OpenDeviceRegistryKey(pwszDeviceName,REGSTR_VAL_DATA_W,&hkeyDevice);
if (!SUCCEEDED(hres)) {
return hres;
}
//
// Implement set value
//
dwError = OSUtil_RegSetValueExW(hkeyDevice,
pwszValueName,
Type,
pData,
cbData,
(this->dwVersion & STI_VERSION_FLAG_UNICODE) ? TRUE : FALSE);
if (hkeyDevice) {
RegCloseKey(hkeyDevice);
}
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_SetDeviceValueA(
PV pSti,
LPCSTR pszDeviceName,
LPCSTR pszValueName,
DWORD Type,
LPBYTE pData,
DWORD cbData
)
{
HRESULT hres;
HKEY hkeyDevice;
LONG dwError;
EnterProcR(IStillImage::SetDeviceValue,(_ "ppp", pSti,pszDeviceName,pData ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
WCHAR wszDeviceName[STI_MAX_INTERNAL_NAME_LENGTH] = {L'\0'};
WCHAR wszValueName[MAX_PATH] = {L'\0'};
AToU(wszDeviceName,STI_MAX_INTERNAL_NAME_LENGTH,pszDeviceName);
AToU(wszValueName,MAX_PATH,pszValueName);
//
// Open device registry key
//
hres = OpenDeviceRegistryKey(wszDeviceName,REGSTR_VAL_DATA_W,&hkeyDevice);
if (SUCCEEDED(hres)) {
//
// Implement set value
//
dwError = OSUtil_RegSetValueExW(hkeyDevice,
wszValueName,
Type,
pData,
cbData,
(this->dwVersion & STI_VERSION_FLAG_UNICODE) ? TRUE : FALSE);
if (hkeyDevice) {
RegCloseKey(hkeyDevice);
}
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
}
ExitOleProc();
return hres;
}
/****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | GetDeviceValue |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_GetDeviceValueW(
PV pSti,
LPWSTR pwszDeviceName,
LPWSTR pwszValueName,
LPDWORD pType,
LPBYTE pData,
LPDWORD pcbData
)
{
HRESULT hres = STIERR_INVALID_PARAM;
HKEY hkeyDevice;
LONG dwError;
EnterProcR(IStillImage::GetDeviceValue,(_ "ppp", pSti,pwszDeviceName,pData ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
//
// Open device registry key
//
hres = OpenDeviceRegistryKey(pwszDeviceName,REGSTR_VAL_DATA_W,&hkeyDevice);
if (!SUCCEEDED(hres)) {
return hres;
}
//
// Implement get value
//
dwError = OSUtil_RegQueryValueExW(hkeyDevice,
pwszValueName,
pType,
pData,
pcbData,
(this->dwVersion & STI_VERSION_FLAG_UNICODE) ? TRUE : FALSE);
if (hkeyDevice) {
RegCloseKey(hkeyDevice);
}
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_GetDeviceValueA(
PV pSti,
LPCSTR pszDeviceName,
LPCSTR pszValueName,
LPDWORD pType,
LPBYTE pData,
LPDWORD pcbData
)
{
HRESULT hres = STIERR_INVALID_PARAM;
HKEY hkeyDevice;
LONG dwError;
EnterProcR(IStillImage::GetDeviceValue,(_ "ppp", pSti,pszDeviceName,pData ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
LPWSTR pwszDevName = NULL;
hres = OSUtil_GetWideString(&pwszDevName,pszDeviceName);
if (SUCCEEDED(hres)) {
//
// Open device registry key
//
hres = OpenDeviceRegistryKey(pwszDevName,REGSTR_VAL_DATA_W,&hkeyDevice);
if (SUCCEEDED(hres)) {
//
// Implement get value
//
dwError = RegQueryValueExA(hkeyDevice,
pszValueName,
0,
pType,
pData,
pcbData);
if (hkeyDevice) {
RegCloseKey(hkeyDevice);
}
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
}
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | GetSTILaunchInformation |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_GetSTILaunchInformationW(
PV pSti,
WCHAR *pwszDeviceName,
DWORD *pdwEventCode,
WCHAR *pwszEventName
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::GetSTILaunchInformation,(_ "pppp", pSti,pwszDeviceName,pdwEventCode,pwszEventName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
//
// Parse process command line to check if there is STI information
//
hres = ExtractCommandLineArgumentW("StiDevice",pwszDeviceName);
if (SUCCEEDED(hres) ) {
hres = ExtractCommandLineArgumentW("StiEvent",pwszEventName);
}
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_GetSTILaunchInformationA(
PV pSti,
LPSTR pszDeviceName,
DWORD *pdwEventCode,
LPSTR pszEventName
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::GetSTILaunchInformation,(_ "pppp", pSti,pszDeviceName,pdwEventCode,pszEventName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
hres = ExtractCommandLineArgumentA("StiDevice",pszDeviceName);
if (SUCCEEDED(hres) ) {
hres = ExtractCommandLineArgumentA("StiEvent",pszEventName);
}
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | RegisterLaunchApplication |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
static WCHAR szSTICommandLineTail[] = {L" /StiDevice:%1 /StiEvent:%2"};
static CHAR szSTICommandLineTail_A[] = {" /StiDevice:%1 /StiEvent:%2"};
STDMETHODIMP
CStiObj_RegisterLaunchApplicationW(
PV pSti,
LPWSTR pwszAppName,
LPWSTR pwszCommandLine
)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwErr = 0;
DWORD dwCommandLineLength, cbNewLength;
LPWSTR pszWide = NULL;
HKEY hkeyApps;
CHAR szAppName[MAX_PATH] = {'\0'};
CHAR szCmdLine[MAX_PATH] = {'\0'};
EnterProcR(IStillImage::RegisterLaunchApplication,(_ "ppp", pSti,pwszAppName,pwszCommandLine ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
if (pwszCommandLine && *pwszCommandLine &&
pwszAppName && *pwszAppName
) {
//
// Add STI formatiing tail to the command line
//
dwCommandLineLength = OSUtil_StrLenW(pwszCommandLine);
cbNewLength = ((dwCommandLineLength+1) + OSUtil_StrLenW(szSTICommandLineTail) + 1)*sizeof(WCHAR) ;
hres = AllocCbPpv(cbNewLength, (PPV)&pszWide);
if (pszWide) {
HRESULT hresCom ;
// Need to initialize COM apartment to call WIA event registration
hresCom = CoInitialize(NULL);
OSUtil_lstrcpyW(pszWide,pwszCommandLine);
OSUtil_lstrcatW(pszWide,szSTICommandLineTail);
dwErr = OSUtil_RegCreateKeyExW(HKEY_LOCAL_MACHINE,
REGSTR_PATH_REG_APPS_W,
0L,
NULL,
0L,
KEY_ALL_ACCESS,
NULL,
&hkeyApps,
NULL
);
if (NOERROR == dwErr ) {
WriteRegistryStringW(hkeyApps,
pwszAppName ,
pszWide,
cbNewLength,
REG_SZ);
RegCloseKey(hkeyApps);
}
//
// Register for standard WIA events on all devices , setting as non default
//
if (WideCharToMultiByte(CP_ACP,
0,
pwszAppName,
-1,
szAppName,
MAX_PATH,
NULL,
NULL)) {
if (WideCharToMultiByte(CP_ACP,
0,
pszWide,
-1,
szCmdLine,
MAX_PATH,
NULL,
NULL)) {
hres = RunRegisterProcess(szAppName, szCmdLine);
} else {
hres = E_FAIL;
}
} else {
hres = E_FAIL;
}
FreePpv(&pszWide);
// Balance apartment initiazation
if ((S_OK == hresCom) || (S_FALSE == hresCom)) {
CoUninitialize();
}
hres = (dwErr == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwErr);
}
else {
DebugOutPtszV(DbgFl, TEXT("Could not get unicode string -- out of memory"));
hres = E_OUTOFMEMORY;
}
}
else {
hres = STIERR_INVALID_PARAM;
}
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_RegisterLaunchApplicationA(
PV pSti,
LPCSTR pszAppName,
LPCSTR pszCommandLine
)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwErr = 0;
DWORD dwCommandLineLength, cbNewLength;
LPWSTR pszWide = NULL;
HKEY hkeyApps;
EnterProcR(IStillImage::RegisterLaunchApplication,(_ "ppp", pSti,pszAppName,pszCommandLine ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
// Add STI formatiing tail to the command line
//
if (pszCommandLine && *pszCommandLine &&
pszAppName && *pszAppName
) {
LPSTR pszBuffer;
// Add STI formatiing tail to the command line
//
dwCommandLineLength = lstrlenA(pszCommandLine);
cbNewLength = ((dwCommandLineLength+1) + OSUtil_StrLenW(szSTICommandLineTail) + 1)*sizeof(WCHAR) ;
hres = AllocCbPpv(cbNewLength, (PPV)&pszBuffer);
if (pszBuffer) {
lstrcpyA(pszBuffer,pszCommandLine);
UToA(pszBuffer+lstrlenA(pszBuffer),
(cbNewLength - dwCommandLineLength),
szSTICommandLineTail);
dwErr = RegCreateKeyExA(HKEY_LOCAL_MACHINE,
REGSTR_PATH_REG_APPS_A,
0L,
NULL,
0L,
KEY_ALL_ACCESS,
NULL,
&hkeyApps,
NULL
);
if (NOERROR == dwErr ) {
WriteRegistryStringA(hkeyApps,
pszAppName ,
pszBuffer,
lstrlenA(pszBuffer)+1,
REG_SZ);
RegCloseKey(hkeyApps);
}
{
//
// Register for standard WIA events on all devices , setting as non default
//
PVOID pWideCMDLine = NULL;
UINT uiSize = (lstrlenA(pszBuffer)+1)*sizeof(WCHAR);
CHAR szCmdLine[MAX_PATH] = {'\0'};
//
// Make sure we wont overrun our buffer
//
if ((lstrlenA(szCmdLine) + lstrlenA(szSTICommandLineTail_A) + lstrlenA(" ") + sizeof('\0'))
< (MAX_PATH)) {
lstrcatA(szCmdLine, pszCommandLine);
lstrcatA(szCmdLine, " ");
lstrcatA(szCmdLine, szSTICommandLineTail_A);
dwErr = (DWORD) RunRegisterProcess((LPSTR)pszAppName, szCmdLine);
} else {
dwErr = (DWORD) E_INVALIDARG;
}
}
FreePpv(&pszBuffer);
hres = (dwErr == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwErr);
}
else {
DebugOutPtszV(DbgFl,TEXT("Could not get unicode string -- out of memory"));
hres = E_OUTOFMEMORY;
}
}
else {
hres = STIERR_INVALID_PARAM;
}
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | RegisterLaunchApplication |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_UnregisterLaunchApplicationW(
PV pSti,
LPWSTR pwszAppName
)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwErr;
HKEY hkeyApps;
EnterProcR(IStillImage::UnregisterLaunchApplication,(_ "pp", pSti,pwszAppName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
dwErr = OSUtil_RegOpenKeyExW(HKEY_LOCAL_MACHINE,
REGSTR_PATH_REG_APPS_W,
0L,
KEY_ALL_ACCESS,
&hkeyApps
);
if (NOERROR == dwErr ) {
OSUtil_RegDeleteValueW(hkeyApps,pwszAppName);
RegCloseKey(hkeyApps);
}
hres = (dwErr == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwErr);
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_UnregisterLaunchApplicationA(
PV pSti,
LPCSTR pszAppName
)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwErr;
HKEY hkeyApps;
EnterProcR(IStillImage::UnregisterLaunchApplication,(_ "pp", pSti,pszAppName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
dwErr = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
REGSTR_PATH_REG_APPS_A,
0L,
KEY_ALL_ACCESS,
&hkeyApps
);
if (NOERROR == dwErr ) {
RegDeleteValueA(hkeyApps,pszAppName);
RegCloseKey(hkeyApps);
}
hres = (dwErr == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwErr);
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | LaunchApplicationForDevice |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_LaunchApplicationForDeviceW(
PV pSti,
LPWSTR pwszDeviceName,
LPWSTR pwszAppName,
LPSTINOTIFY pStiNotify
)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwError ;
EnterProcR(IStillImage::LaunchApplicationForDevice,(_ "pp", pSti,pwszAppName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
dwError = RpcStiApiLaunchApplication(NULL,
pwszDeviceName,
pwszAppName,
pStiNotify
);
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_LaunchApplicationForDeviceA(
PV pSti,
LPCSTR pszDeviceName,
LPCSTR pszApplicationName,
LPSTINOTIFY pStiNotify
)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwError;
EnterProcR(IStillImage::LaunchApplicationForDevice,(_ "pp", pSti,pszApplicationName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
LPWSTR pwszDevName = NULL;
LPWSTR pwszAppName = NULL;
hres = OSUtil_GetWideString(&pwszDevName,pszDeviceName);
if (SUCCEEDED(hres)) {
hres = OSUtil_GetWideString(&pwszAppName,pszApplicationName);
if (SUCCEEDED(hres)) {
dwError = RpcStiApiLaunchApplication(NULL,
pwszDevName,
pwszAppName,
pStiNotify
);
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
}
FreePpv(&pwszAppName);
FreePpv(&pwszDevName);
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | SetupDeviceParameters |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_SetupDeviceParametersW(
PV pSti,
PSTI_DEVICE_INFORMATIONW pDevInfo
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::SetupDeviceParameters,(_ "pp", pSti, pDevInfo));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
hres = SetDeviceInfoHelper(pDevInfo);
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_SetupDeviceParametersA(
PV pSti,
PSTI_DEVICE_INFORMATIONA pDevInfo
)
{
HRESULT hres = STIERR_INVALID_PARAM;
EnterProcR(IStillImage::SetupDeviceParameters,(_ "pp", pSti, pDevInfo));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
hres = STIERR_UNSUPPORTED;
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | SetupDeviceParameters |
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_WriteToErrorLogW(
PV pSti,
DWORD dwMessageType,
LPCWSTR pwszMessage
)
{
HRESULT hres = S_OK;
EnterProcR(IStillImage::WriteToErrorLog,(_ "pp", pSti, pwszMessage));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
//
// Validate parameters here
//
if (SUCCEEDED(hres = hresFullValidReadPvCb(pwszMessage,2, 3))) {
#ifndef UNICODE
//
// Since we're ANSI, the ReportStiLogMessage is expecting an ANSI string,
// but our message is UNICODE, so we must convert.
// NOTE: We never expect CStiObj_WriteToErrorLogW to be called if we're compiling
// ANSI, but just in case...
//
LPSTR lpszANSI = NULL;
if ( SUCCEEDED(OSUtil_GetAnsiString(&lpszANSI,pwszMessage))) {
ReportStiLogMessage(g_hStiFileLog,
dwMessageType,
lpszANSI
);
FreePpv(&lpszANSI);
}
#else
ReportStiLogMessage(g_hStiFileLog,
dwMessageType,
pwszMessage
);
#endif
}
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_WriteToErrorLogA(
PV pSti,
DWORD dwMessageType,
LPCSTR pszMessage
)
{
HRESULT hres = S_OK;
EnterProcR(IStillImage::WriteToErrorLog,(_ "pp", pSti, pszMessage));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
//
// Validate parameters here
//
if (SUCCEEDED(hres = hresFullValidReadPvCb(pszMessage,2, 3))) {
#ifndef UNICODE
ReportStiLogMessage(g_hStiFileLog,
dwMessageType,
pszMessage
);
#else
//
// Since we're UNICODE, the ReportStiLogMessage is expecting a WideString,
// but our message is ANSI, so we must convert.
// NOTE: We never expect CStiObj_WriteToErrorLogA to be called if we're compiling
// UNICODE, but just in case...
//
LPWSTR lpwszWide = NULL;
if ( SUCCEEDED(OSUtil_GetWideString(&lpwszWide,pszMessage))) {
ReportStiLogMessage(g_hStiFileLog,
dwMessageType,
lpwszWide
);
FreePpv(&lpwszWide);
}
#endif
}
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | |
*
*
* To control state of notification handling. For polled devices this means state of monitor
* polling, for true notification devices means enabling/disabling notification flow
* from monitor to registered applications
*
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_EnableHwNotificationsW(
PV pSti,
LPCWSTR pwszDeviceName,
BOOL bNewState)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwError = NOERROR;
EnterProcR(IStillImage::CStiObj_EnableHwNotifications,(_ "pp", pSti,pwszDeviceName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
dwError = RpcStiApiEnableHwNotifications(NULL,
pwszDeviceName,
bNewState);
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_EnableHwNotificationsA(
PV pSti,
LPCSTR pszDeviceName,
BOOL bNewState)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwError = NOERROR;
EnterProcR(IStillImage::CStiObj_EnableHwNotifications,(_ "pp", pSti,pszDeviceName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
LPWSTR pwszDeviceName=NULL ;
hres = OSUtil_GetWideString(&pwszDeviceName,pszDeviceName);
if (SUCCEEDED(hres)) {
dwError = RpcStiApiEnableHwNotifications(NULL,
pwszDeviceName,
bNewState);
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
FreePpv(&pwszDeviceName);
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | |
*
*
* To control state of notification handling. For polled devices this means state of monitor
* polling, for true notification devices means enabling/disabling notification flow
* from monitor to registered applications
*
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_GetHwNotificationStateW(
PV pSti,
LPCWSTR pwszDeviceName,
BOOL* pbCurrentState)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwError = NOERROR;
EnterProcR(IStillImage::CStiObj_GetHwNotificationState,(_ "pp", pSti,pwszDeviceName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
dwError = RpcStiApiGetHwNotificationState(NULL,
pwszDeviceName,
pbCurrentState);
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_GetHwNotificationStateA(
PV pSti,
LPCSTR pszDeviceName,
BOOL* pbCurrentState)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwError = NOERROR;
EnterProcR(IStillImage::CStiObj_GetHwNotificationState,(_ "pp", pSti,pszDeviceName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
LPWSTR pwszDeviceName=NULL ;
hres = OSUtil_GetWideString(&pwszDeviceName,pszDeviceName);
if (SUCCEEDED(hres)) {
dwError = RpcStiApiGetHwNotificationState(NULL,
pwszDeviceName,
pbCurrentState);
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
FreePpv(&pwszDeviceName);
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | RefreshDeviceBus |
*
*
* When device is installed but not accessible, application may request bus refresh
* which in some cases will make device known. This is mainly used for nonPnP buses
* like SCSI, when device was powered on after PnP enumeration
*
*
*
*
* @cwrap LPStillImage | lpStillImage
*
* @parm
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
* <p ppvOut> parameter is not a valid pointer.
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
HRESULT
WINAPI
RefreshDeviceParentHelper(
LPCWSTR pwszDeviceName
)
{
HRESULT hres;
DWORD dwError = NOERROR;
CONFIGRET cmRetCode = CR_SUCCESS ;
HANDLE hDevInfo;
DEVINST hdevParent;
GUID Guid = GUID_DEVCLASS_IMAGE;
DWORD dwRequired;
DWORD Idx;
SP_DEVINFO_DATA spDevInfoData;
WCHAR szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH];
ULONG cbData;
BOOL fRet;
BOOL fFoundDriverNameMatch;
dwRequired = 0;
dwError = 0;
//
// Navigating through Setup API set
// As we don't have reverse search to retrive device info handle , based on
// driver name, we do exsaustive search. Number of imaging devices for given class ID
// is never as large to make a problem.
//
//
hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
fFoundDriverNameMatch = FALSE;
hres = STIERR_INVALID_DEVICE_NAME;
if (hDevInfo != INVALID_HANDLE_VALUE) {
spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
//
// Compare driver name
//
*szDevDriver = L'\0';
fRet = SetupDiGetDeviceRegistryPropertyW (hDevInfo,
&spDevInfoData,
SPDRP_DRIVER,
NULL,
(LPBYTE)szDevDriver,
sizeof (szDevDriver),
&cbData
);
if (fRet && !lstrcmpiW(szDevDriver,pwszDeviceName)) {
fFoundDriverNameMatch = TRUE;
break;
}
}
if(fFoundDriverNameMatch) {
//
// Found instance for the device with matching driver name
//
hdevParent = 0;
cmRetCode = CM_Get_Parent(&hdevParent,
spDevInfoData.DevInst,
0);
dwError = GetLastError();
if((CR_SUCCESS == cmRetCode) && hdevParent) {
CM_Reenumerate_DevNode(hdevParent,CM_REENUMERATE_NORMAL );
dwError = GetLastError();
}
hres = (dwError == NOERROR) ? S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,dwError);
}
else {
hres = STIERR_INVALID_DEVICE_NAME;
}
//
SetupDiDestroyDeviceInfoList (hDevInfo);
}
else {
hres = STIERR_INVALID_DEVICE_NAME;
}
return hres;
}
STDMETHODIMP
CStiObj_RefreshDeviceBusW(
PV pSti,
LPCWSTR pwszDeviceName
)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwErr = NOERROR;
CONFIGRET cmRetCode = CR_SUCCESS ;
EnterProcR(IStillImage::CStiObj_RefreshDeviceBus,(_ "pp", pSti,pwszDeviceName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPvNm(pSti, stiW);
hres = RefreshDeviceParentHelper(pwszDeviceName);
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_RefreshDeviceBusA(
PV pSti,
LPCSTR pszDeviceName
)
{
HRESULT hres = STIERR_INVALID_PARAM;
DWORD dwError = NOERROR;
EnterProcR(IStillImage::CStiObj_RefreshDeviceBus,(_ "pp", pSti,pszDeviceName ));
//
// Validate passed pointer to interface and obtain pointer to object instance
//
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPvNm(pSti, stiA);
LPWSTR pwszDeviceName=NULL ;
hres = OSUtil_GetWideString(&pwszDeviceName,pszDeviceName);
if (SUCCEEDED(hres)) {
if (pwszDeviceName) {
hres = RefreshDeviceParentHelper(pwszDeviceName);
FreePpv(&pwszDeviceName);
}
}
}
ExitOleProc();
return hres;
}
////////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*
* @doc EXTERNAL
*
* @method HRESULT | IStillImage | Initialize |
*
* Initialize a StillImage object.
*
* The <f StillImageCreate> method automatically
* initializes the StillImage object device after creating it.
* Applications normally do not need to call this function.
*
* @cwrap LPStillImage | lpStillImage
*
* @parm IN HINSTANCE | hinst |
*
* Instance handle of the application or DLL that is creating
* the StillImage object.
*
* StillImage uses this value to determine whether the
* application or DLL has been certified.
*
* @parm DWORD | dwVersion |
*
* Version number of the dinput.h header file that was used.
* This value must be <c StillImage_VERSION>.
*
* StillImage uses this value to determine what version of
* StillImage the application or DLL was designed for.
*
* @returns
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c DI_OK> = <c S_OK>: The device is attached.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_InitializeW(
PV pSti,
HINSTANCE hinst,
DWORD dwVersion
)
{
HRESULT hres;
EnterProcR(IStillImage::Initialize, (_ "pxx", pSti, hinst, dwVersion));
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceW))) {
PCStiObj this = _thisPv(pSti);
if (SUCCEEDED(hres = hresValidInstanceVer(hinst, dwVersion))) {
this->dwVersion = dwVersion;
}
}
ExitOleProc();
return hres;
}
STDMETHODIMP
CStiObj_InitializeA(
PV pSti,
HINSTANCE hinst,
DWORD dwVersion
)
{
HRESULT hres;
EnterProcR(IStillImage::Initialize, (_ "pxx", pSti, hinst, dwVersion));
if (SUCCEEDED(hres = hresPvI(pSti, ThisInterfaceA))) {
PCStiObj this = _thisPv(pSti);
if (SUCCEEDED(hres = hresValidInstanceVer(hinst, dwVersion))) {
this->dwVersion = dwVersion;
}
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func void | CStiObj_Finalize |
*
* Releases the resources of a STI object
*
* @parm PV | pvObj |
*
* Object being released. Note that it may not have been
* completely initialized, so everything should be done
* carefully.
*
*****************************************************************************/
void INTERNAL
CStiObj_Finalize(PV pvObj)
{
PCStiObj this = pvObj;
//
// Free COM libraries if connected to them
//
DllUnInitializeCOM();
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func HRESULT | StiCreateHelper |
*
* <bnew>This function creates a new StillImage object
* which supports the <i IStillImage> COM interface.
*
* On success, the function returns a pointer to the new object in
* *<p lplpSti>.
* <enew>
*
* @parm IN HINSTANCE | hinst |
*
* Instance handle of the application or DLL that is creating
* the Sti object.
*
* @parm DWORD | dwVersion |
*
* Version number of the sti.h header file that was used.
* This value must be <c STI_VERSION>.
*
* @parm OUT PPV | ppvObj |
* Points to where to return
* the pointer to the <i ISti> interface, if successful.
*
* @parm IN LPUNKNOWN | punkOuter | Pointer to controlling unknown.
*
* @parm RIID | riid |
*
* The interface the application wants to create.
*
* If the object is aggregated, then this parameter is ignored.
*
* @returns
*
* Returns a COM error code. The following error codes are
* intended to be illustrative and not necessarily comprehensive.
*
* <c STI_OK> = <c S_OK>: The operation completed successfully.
*
* <c STIERR_INVALIDPARAM>
*
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
* Out of memory.
*
*****************************************************************************/
STDMETHODIMP
StiCreateHelper(
HINSTANCE hinst,
DWORD dwVer,
PPV ppvObj,
PUNK punkOuter,
RIID riid)
{
HRESULT hres;
EnterProc(StiCreateHelper,
(_ "xxxG", hinst, dwVer, punkOuter, riid));
hres = CStiObj_New(punkOuter,punkOuter ? &IID_IUnknown : riid, ppvObj);
if (SUCCEEDED(hres) && punkOuter == 0) {
PSTI psti = *ppvObj;
hres = psti->lpVtbl->Initialize(psti, hinst, dwVer);
if (SUCCEEDED(hres)) {
} else {
Invoke_Release(ppvObj);
}
}
ExitOleProcPpv(ppvObj);
return hres;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @mfunc HRESULT | IStillImage | New |
*
* Create a new instance of an IStillImage object.
*
* @parm IN PUNK | punkOuter |
*
* Controlling unknown for aggregation.
*
* @parm IN RIID | riid |
* Desired interface to new object.
*
* @parm OUT PPV | ppvObj |
* Output pointer for new object.
*
* @returns
*
* Standard OLE <t HRESULT>.
*
*****************************************************************************/
STDMETHODIMP
CStiObj_New(PUNK punkOuter, RIID riid, PPV ppvObj)
{
HRESULT hres;
EnterProcR(IStillImage::CreateInstance, (_ "Gp", riid, ppvObj));
hres = Common_NewRiid(CStiObj, punkOuter, riid, ppvObj);
ExitOleProcPpvR(ppvObj);
return hres;
}
/*****************************************************************************
*
* The long-awaited vtbls and templates
*
*****************************************************************************/
#pragma BEGIN_CONST_DATA
#define CStiObj_Signature (DWORD)'STI'
Interface_Template_Begin(CStiObj)
Primary_Interface_Template(CStiObj,TFORM(ThisInterfaceT))
Secondary_Interface_Template(CStiObj, SFORM(ThisInterfaceT))
Interface_Template_End(CStiObj)
Primary_Interface_Begin(CStiObj, TFORM(ThisInterfaceT))
TFORM(CStiObj_Initialize),
TFORM(CStiObj_GetDeviceList),
TFORM(CStiObj_GetDeviceInfo),
TFORM(CStiObj_CreateDevice),
TFORM(CStiObj_GetDeviceValue),
TFORM(CStiObj_SetDeviceValue),
TFORM(CStiObj_GetSTILaunchInformation),
TFORM(CStiObj_RegisterLaunchApplication),
TFORM(CStiObj_UnregisterLaunchApplication),
TFORM(CStiObj_EnableHwNotifications),
TFORM(CStiObj_GetHwNotificationState),
TFORM(CStiObj_RefreshDeviceBus),
TFORM(CStiObj_LaunchApplicationForDevice),
TFORM(CStiObj_SetupDeviceParameters),
TFORM(CStiObj_WriteToErrorLog)
Primary_Interface_End(CStiObj, TFORM(ThisInterfaceT))
Secondary_Interface_Begin(CStiObj,SFORM(ThisInterfaceT), SFORM(sti))
SFORM(CStiObj_Initialize),
SFORM(CStiObj_GetDeviceList),
SFORM(CStiObj_GetDeviceInfo),
SFORM(CStiObj_CreateDevice),
SFORM(CStiObj_GetDeviceValue),
SFORM(CStiObj_SetDeviceValue),
SFORM(CStiObj_GetSTILaunchInformation),
SFORM(CStiObj_RegisterLaunchApplication),
SFORM(CStiObj_UnregisterLaunchApplication),
SFORM(CStiObj_EnableHwNotifications),
SFORM(CStiObj_GetHwNotificationState),
SFORM(CStiObj_RefreshDeviceBus),
SFORM(CStiObj_LaunchApplicationForDevice),
SFORM(CStiObj_SetupDeviceParameters),
SFORM(CStiObj_WriteToErrorLog)
Secondary_Interface_End(CStiObj,SFORM(ThisInterfaceT), SFORM(sti))