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.
339 lines
9.8 KiB
339 lines
9.8 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 1997
|
|
*
|
|
* TITLE: DevDlg.Cpp
|
|
*
|
|
* VERSION: 2.0
|
|
*
|
|
* AUTHOR: ReedB
|
|
*
|
|
* DATE: 3 Apr, 1998
|
|
*
|
|
* DESCRIPTION:
|
|
* Implements device dialog UI for WIA devices. These methods execute
|
|
* only on the client side.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <objbase.h>
|
|
#include <stdio.h>
|
|
#include <tchar.h>
|
|
#include "wia.h"
|
|
#include "sti.h"
|
|
#include "wiadevd.h"
|
|
#include <initguid.h>
|
|
#include "wiadevdp.h"
|
|
|
|
HRESULT GetDeviceExtensionClassID( LPCWSTR pwszUiClassId, LPCTSTR pszCategory, IID &iidClassID )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
//
|
|
// Make sure all of the parameters are valid
|
|
//
|
|
if (pwszUiClassId && pszCategory && lstrlenW(pwszUiClassId) && lstrlen(pszCategory))
|
|
{
|
|
//
|
|
// Construct the key name
|
|
//
|
|
TCHAR szRootKeyName[1024] = {0};
|
|
_sntprintf( szRootKeyName, (sizeof(szRootKeyName)/sizeof(szRootKeyName[0])) - 1, TEXT("CLSID\\%ws\\shellex\\%s"), pwszUiClassId, pszCategory );
|
|
|
|
//
|
|
// open the reg key
|
|
//
|
|
HKEY hKeyRoot = NULL;
|
|
DWORD dwResult = RegOpenKeyEx( HKEY_CLASSES_ROOT, szRootKeyName, 0, KEY_READ, &hKeyRoot );
|
|
if (ERROR_SUCCESS == dwResult)
|
|
{
|
|
//
|
|
// Get the buffer size
|
|
//
|
|
TCHAR szClassID[MAX_PATH] = {0};
|
|
DWORD dwLength = sizeof(szClassID)/sizeof(szClassID[0]);
|
|
|
|
//
|
|
// Note that we only take the first registry key
|
|
//
|
|
dwResult = RegEnumKeyEx( hKeyRoot, 0, szClassID, &dwLength, NULL, NULL, NULL, NULL );
|
|
if (ERROR_SUCCESS == dwResult)
|
|
{
|
|
//
|
|
// Convert the registry string to a CLSID
|
|
//
|
|
#if defined(UNICODE)
|
|
hr = CLSIDFromString( szClassID, &iidClassID );
|
|
#else
|
|
WCHAR wszClassID[MAX_PATH] = {0};
|
|
MultiByteToWideChar( CP_ACP, 0, szClassID, -1, wszClassID, MAX_PATH );
|
|
hr = CLSIDFromString( wszClassID, &iidClassID );
|
|
#endif
|
|
}
|
|
else hr = HRESULT_FROM_WIN32(dwResult);
|
|
|
|
//
|
|
// Close the registry key
|
|
//
|
|
RegCloseKey(hKeyRoot);
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CreateDeviceExtension( LPCWSTR pwszUiClassId, LPCTSTR pszCategory, const IID &iid, void **ppvObject )
|
|
{
|
|
IID iidClassID = {0};
|
|
HRESULT hr = GetDeviceExtensionClassID( pwszUiClassId, pszCategory, iidClassID );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = CoCreateInstance( iidClassID, NULL, CLSCTX_INPROC_SERVER, iid, ppvObject );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetUiGuidFromWiaItem( IWiaItem *pWiaItem, LPWSTR pwszGuid, size_t nMaxLen )
|
|
{
|
|
HRESULT hr;
|
|
if (pWiaItem && pwszGuid)
|
|
{
|
|
IWiaPropertyStorage *pWiaPropertyStorage = NULL;
|
|
hr = pWiaItem->QueryInterface( IID_IWiaPropertyStorage, (void**)&pWiaPropertyStorage );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PROPSPEC ps[1];
|
|
PROPVARIANT pv[1];
|
|
ps[0].ulKind = PRSPEC_PROPID;
|
|
ps[0].propid = WIA_DIP_UI_CLSID;
|
|
hr = pWiaPropertyStorage->ReadMultiple(sizeof(ps)/sizeof(ps[0]), ps, pv );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (VT_LPWSTR == pv[0].vt || VT_BSTR == pv[0].vt)
|
|
{
|
|
lstrcpynW( pwszGuid, pv[0].bstrVal, nMaxLen );
|
|
hr = S_OK;
|
|
}
|
|
FreePropVariantArray( sizeof(pv)/sizeof(pv[0]), pv );
|
|
}
|
|
pWiaPropertyStorage->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetDeviceExtensionClassID( IWiaItem *pWiaItem, LPCTSTR pszCategory, IID &iidClassID )
|
|
{
|
|
WCHAR wszGuid[MAX_PATH] = {0};
|
|
HRESULT hr = GetUiGuidFromWiaItem(pWiaItem,wszGuid,sizeof(wszGuid)/sizeof(wszGuid[0]));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = GetDeviceExtensionClassID( wszGuid, pszCategory, iidClassID );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CreateDeviceExtension( IWiaItem *pWiaItem, LPCTSTR pszCategory, const IID &iid, void **ppvObject )
|
|
{
|
|
WCHAR wszGuid[MAX_PATH] = {0};
|
|
HRESULT hr = GetUiGuidFromWiaItem(pWiaItem,wszGuid,sizeof(wszGuid)/sizeof(wszGuid[0]));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = CreateDeviceExtension( wszGuid, pszCategory, iid, ppvObject );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* InvokeVendorDeviceDlg
|
|
*
|
|
* DESCRIPTION:
|
|
* Helper function which displays the system-supplied device dlg
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
static HRESULT InvokeSystemDeviceDlg(
|
|
IWiaItem __RPC_FAR *This,
|
|
DEVICEDIALOGDATA &DeviceDialogData )
|
|
{
|
|
IWiaUIExtension *pIWiaUIExtension = NULL;
|
|
HRESULT hr = CoCreateInstance( CLSID_WiaDefaultUi, NULL, CLSCTX_INPROC_SERVER, IID_IWiaUIExtension, (void**)(&pIWiaUIExtension) );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// The following call will return E_NOTIMPL if it is a device type
|
|
// we don't handle in the system UI
|
|
//
|
|
hr = pIWiaUIExtension->DeviceDialog(&DeviceDialogData);
|
|
pIWiaUIExtension->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* InvokeVendorDeviceDlg
|
|
*
|
|
* DESCRIPTION:
|
|
* Helper function which displays the IHV-supplied device dlg
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
static HRESULT InvokeVendorDeviceDlg(
|
|
IWiaItem __RPC_FAR *This,
|
|
DEVICEDIALOGDATA &DeviceDialogData )
|
|
{
|
|
IWiaUIExtension *pIWiaUIExtension = NULL;
|
|
HRESULT hr = CreateDeviceExtension( This, SHELLEX_WIAUIEXTENSION_NAME, IID_IWiaUIExtension, (void**)(&pIWiaUIExtension) );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// The following call will return E_NOTIMPL if the IHV has
|
|
// not implemented a custom UI
|
|
//
|
|
hr = pIWiaUIExtension->DeviceDialog(&DeviceDialogData);
|
|
pIWiaUIExtension->Release();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We want to override this return value, so we can
|
|
// handle it by showing the system UI as a fallback.
|
|
// Basically, we are going to assume a failure to create
|
|
// the extension means that the extension doesn't exist.
|
|
// We don't do that for the system UI, because if it can't
|
|
// load, that is considered a catastrophic failure.
|
|
//
|
|
hr = E_NOTIMPL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* IWiaItem_DeviceDlg_Proxy
|
|
*
|
|
* DESCRIPTION:
|
|
* Display device data acquistion UI.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
HRESULT _stdcall IWiaItem_DeviceDlg_Proxy(
|
|
IWiaItem __RPC_FAR *This,
|
|
HWND hwndParent,
|
|
LONG lFlags,
|
|
LONG lIntent,
|
|
LONG *plItemCount,
|
|
IWiaItem ***ppIWiaItems)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
//
|
|
// Make sure we have valid pointer arguments
|
|
//
|
|
if (!plItemCount || !ppIWiaItems)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
//
|
|
// Initialize the OUT arguments
|
|
//
|
|
*plItemCount = 0;
|
|
*ppIWiaItems = NULL;
|
|
|
|
//
|
|
// Verify that this is a root item.
|
|
//
|
|
LONG lItemType = 0;
|
|
hr = This->GetItemType(&lItemType);
|
|
if ((FAILED(hr)) || !(lItemType & WiaItemTypeRoot))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
//
|
|
// Prepare the struct we will be passing to the function
|
|
//
|
|
DEVICEDIALOGDATA DeviceDialogData = {0};
|
|
DeviceDialogData.cbSize = sizeof(DeviceDialogData);
|
|
DeviceDialogData.hwndParent = hwndParent;
|
|
DeviceDialogData.pIWiaItemRoot = This;
|
|
DeviceDialogData.dwFlags = lFlags;
|
|
DeviceDialogData.lIntent = lIntent;
|
|
DeviceDialogData.ppWiaItems = *ppIWiaItems;
|
|
|
|
//
|
|
// If the client wants to use the system UI, the order we try to do it in is:
|
|
// System UI --> IHV UI
|
|
// Otherwise, we do:
|
|
// IHV UI --> System UI
|
|
//
|
|
if (0 == (lFlags & WIA_DEVICE_DIALOG_USE_COMMON_UI))
|
|
{
|
|
hr = InvokeVendorDeviceDlg( This, DeviceDialogData );
|
|
if (E_NOTIMPL == hr)
|
|
{
|
|
hr = InvokeSystemDeviceDlg( This, DeviceDialogData );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = InvokeSystemDeviceDlg( This, DeviceDialogData );
|
|
if (E_NOTIMPL == hr)
|
|
{
|
|
hr = InvokeVendorDeviceDlg( This, DeviceDialogData );
|
|
}
|
|
}
|
|
|
|
//
|
|
// It should return S_OK for success, but who knows?
|
|
//
|
|
if (SUCCEEDED(hr) && hr != S_FALSE)
|
|
{
|
|
*ppIWiaItems = DeviceDialogData.ppWiaItems;
|
|
*plItemCount = DeviceDialogData.lItemCount;
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* IWiaItem_DeviceDlg_Stub
|
|
*
|
|
* DESCRIPTION:
|
|
* Never called.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT _stdcall IWiaItem_DeviceDlg_Stub(
|
|
IWiaItem __RPC_FAR *This,
|
|
HWND hwndParent,
|
|
LONG lFlags,
|
|
LONG lIntent,
|
|
LONG *plItemCount,
|
|
IWiaItem ***pIWiaItems)
|
|
{
|
|
return(S_OK);
|
|
}
|
|
|