|
|
#include <tchar.h>
#include <windows.h>
#include <windowsx.h>
#include <objbase.h>
#include <stdlib.h>
#include <stdarg.h>
#include <wia.h>
#include <stdio.h>
#ifdef _DEBUG
#define TRACE(x) Trace x
#else
#define TRACE(x) Trace x
#endif
#define RELEASE(x)\
do {\ if((x)) {\ (x)->Release(); \ (x) = NULL;\ }\ }while(0)
#define REQUIRE(x)\
do {\ if(!(x)) {\ TRACE((_T("%hs(%d): %hs failed with LastError() = %d\r\n"),\ __FILE__, __LINE__, #x, GetLastError()));\ goto Cleanup;\ }\ } while(0)
#define REQUIRE_S_OK(x)\
do {\ hr = (x);\ \ if(hr != S_OK) {\ TRACE((_T("%hs(%d): %hs failed with hr = %x\r\n"),\ __FILE__, __LINE__, #x, hr));\ goto Cleanup;\ }\ } while(0)
#define REQUIRE_SUCCESS(x)\
do {\ DWORD dwResult = (x);\ \ if(dwResult != ERROR_SUCCESS) {\ TRACE((_T("%hs(%d): %hs failed with status = %x\r\n"),\ __FILE__, __LINE__, #x, dwResult));\ goto Cleanup;\ }\ } while(0)
void Trace(LPCTSTR fmt, ...) { TCHAR buffer[2048]; va_list marker;
va_start(marker, fmt); wvsprintf(buffer, fmt, marker);
printf("\nError: %ws", buffer); }
struct regVals_t { ULONG propId; LPWSTR propName; } regVals[] = { {WIA_DIP_DEV_ID, WIA_DIP_DEV_ID_STR}, {WIA_DIP_VEND_DESC, WIA_DIP_VEND_DESC_STR}, {WIA_DIP_DEV_DESC, WIA_DIP_DEV_DESC_STR}, {WIA_DIP_DEV_TYPE, WIA_DIP_DEV_TYPE_STR}, {WIA_DIP_PORT_NAME, WIA_DIP_PORT_NAME_STR}, {WIA_DIP_DEV_NAME, WIA_DIP_DEV_NAME_STR}, {WIA_DIP_SERVER_NAME, WIA_DIP_SERVER_NAME_STR}, {WIA_DIP_REMOTE_DEV_ID, WIA_DIP_REMOTE_DEV_ID_STR}, {WIA_DIP_UI_CLSID, WIA_DIP_UI_CLSID_STR} }; #define NREGVALS (sizeof(regVals) / sizeof(regVals[0]))
HRESULT RegisterRemoteScanners(LPCWSTR servername) { HRESULT hr; IWiaDevMgr *pDevMgr = NULL; IEnumWIA_DEV_INFO *pEnumInfo = NULL; IWiaPropertyStorage *pWiaPropStg = NULL; COSERVERINFO csi; HKEY hDevList = NULL; HKEY hKey = NULL; MULTI_QI mq[1];
ZeroMemory(&csi, sizeof(csi)); csi.pAuthInfo = NULL; csi.pwszName = SysAllocString(servername);
mq[0].hr = S_OK; mq[0].pIID = &IID_IWiaDevMgr; mq[0].pItf = NULL;
REQUIRE_S_OK(CoCreateInstanceEx(CLSID_WiaDevMgr, NULL, CLSCTX_REMOTE_SERVER, &csi, 1, mq));
pDevMgr = (IWiaDevMgr *)mq[0].pItf;
REQUIRE_SUCCESS(RegCreateKeyEx( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\StillImage\\DevList"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hDevList, NULL));
//
// Enumerate all devices scanner
//
REQUIRE_S_OK(pDevMgr->EnumDeviceInfo(0, &pEnumInfo));
while(pEnumInfo->Next(1, &pWiaPropStg, NULL) == S_OK) { PROPSPEC ps[NREGVALS]; PROPVARIANT pv[NREGVALS]; WCHAR keyname[MAX_PATH]; WCHAR *p; int i;
ZeroMemory(pv, sizeof(pv)); for(i = 0; i < NREGVALS; i++) { ps[i].ulKind = PRSPEC_PROPID; ps[i].propid = regVals[i].propId; }
REQUIRE_S_OK(pWiaPropStg->ReadMultiple( sizeof(ps) / sizeof(ps[0]), ps, pv));
//
// Skip any remote devices (anything other than "local"
// in server name field
//
for(i = 0; i < NREGVALS; i++) { if(regVals[i].propId == WIA_DIP_SERVER_NAME) { if(wcscmp(pv[i].bstrVal, L"local")) { goto SkipDevice; } } }
//
// pv[0] consists of device ID and "\NNN", replace "\" with ".", prepend target machine name
//
p = pv[0].bstrVal; wcscpy(keyname, servername); wcscat(keyname, L"."); while(*p && *p != L'\\') { p++; } REQUIRE(*p == L'\\'); REQUIRE(*(++p) != L'\0');
wcscat(keyname, p);
//
// Create device key and populate values
//
REQUIRE_SUCCESS(RegCreateKeyExW( hDevList, keyname, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL));
for(i = 0; i < NREGVALS; i++) {
switch(pv[i].vt) {
case VT_BSTR: if(regVals[i].propId == WIA_DIP_SERVER_NAME) { //
// Server name is reported as "local",
// we need to set it to the actual server name
//
REQUIRE_SUCCESS(RegSetValueExW( hKey, regVals[i].propName, 0, REG_SZ, (CONST BYTE *)servername, wcslen(servername) * sizeof(WCHAR))); } else { //
// All other values we simply copy
//
REQUIRE_SUCCESS(RegSetValueExW( hKey, regVals[i].propName, 0, REG_SZ, (CONST BYTE *)pv[i].bstrVal, wcslen(pv[i].bstrVal) * sizeof(WCHAR))); } break;
case VT_I4: REQUIRE_SUCCESS(RegSetValueExW( hKey, regVals[i].propName, 0, REG_DWORD, (CONST BYTE *)&pv[i].lVal, sizeof(DWORD))); break;
default: TRACE((_T("Unexpected property type: %d\n"), pv[i].vt)); break; }
PropVariantClear(pv + i); }
RegCloseKey(hKey); SkipDevice: RELEASE(pWiaPropStg); }
Cleanup: if(hDevList) RegCloseKey(hDevList); RELEASE(pEnumInfo); RELEASE(pDevMgr);
if(csi.pwszName) SysFreeString(csi.pwszName); return hr; }
int __cdecl main(int argc, char **argv) { HRESULT hr; WCHAR servername[MAX_PATH]; HKEY hKey;
if(argc < 2) { printf("usage: connect <server name>\n"); exit(0); }
MultiByteToWideChar(CP_ACP, 0, argv[1], -1, servername, sizeof(servername) / sizeof(servername[0]));
printf("Registering scanners on %s...", argv[1]); REQUIRE_S_OK(CoInitializeEx(NULL, COINIT_MULTITHREADED)); REQUIRE_S_OK(CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL)); REQUIRE_S_OK(RegisterRemoteScanners(servername));
REQUIRE_SUCCESS(RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\StillImage\\DevList"), 0, KEY_READ, &hKey)); for(int i = 0;;i++) { TCHAR subkeyName[1024]; DWORD subkeySize; HKEY hSubKey; TCHAR string[1024]; DWORD cbString; DWORD dwType; subkeySize = sizeof(subkeyName) / sizeof(subkeyName[0]); if(RegEnumKeyEx(hKey, i, subkeyName, &subkeySize, 0, NULL, NULL, NULL) != ERROR_SUCCESS) { break; } REQUIRE_SUCCESS(RegOpenKeyEx(hKey, subkeyName, 0, KEY_READ, &hSubKey)); cbString = sizeof(string); REQUIRE_SUCCESS(RegQueryValueEx(hSubKey, _T("Server"), NULL, &dwType, (BYTE *)string, &cbString)); if(lstrcmpi(string, servername)) continue; cbString = sizeof(string); REQUIRE_SUCCESS(RegQueryValueEx(hSubKey, _T("Name"), NULL, &dwType, (BYTE *)string, &cbString)); printf("\nRegistered: %ws", string); RegCloseKey(hSubKey); }
printf("\ndone.\n"); Cleanup: CoUninitialize(); return 0; }
|