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.

1667 lines
46 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: DevInfo.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 9 Jan, 1998
  12. *
  13. * DESCRIPTION:
  14. * Implementation for WIA device enumeration and information interface.
  15. *
  16. *******************************************************************************/
  17. #include "precomp.h"
  18. #include "stiexe.h"
  19. #include "wiamindr.h"
  20. #include "wia.h"
  21. #include "devmgr.h"
  22. #include "devinfo.h"
  23. #include "helpers.h"
  24. #define REGSTR_PATH_STICONTROL_DEVLIST_W L"System\\CurrentControlSet\\Control\\StillImage\\DevList"
  25. #define REGSTR_PATH_STI_CLASS_W L"{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}"
  26. typedef struct _WIA_REMOTE_DEVICE {
  27. HKEY hKeyDevice;
  28. WCHAR wszDevName[MAX_PATH];
  29. }WIA_REMOTE_DEVICE,*PWIA_REMOTE_DEVICE;
  30. /**************************************************************************\
  31. * GetPropID
  32. *
  33. * This method takes in a PROPSPEC and returns a PROPSPEC with the
  34. * whose ulKind field is always PRSPEC_PROPID. So if the input PROPSPEC
  35. * is a PropID, then it is simply copied to the output parameter, else
  36. * if it is identified by a name, then the name is looked up and the
  37. * corresponding PropId is returned in the output parameter.
  38. *
  39. * Arguments:
  40. *
  41. * pWiaPropStg - The property storage to work from
  42. * pPropSpecIn - A pointer to the input PROPSPEC containing the
  43. * property name.
  44. * pPropSpecOut - A pointer to a PROPSPEC where the corresponding
  45. * PropID will be put.
  46. *
  47. * Return Value:
  48. *
  49. * Status - An E_INVALIDARG will be returned if the property
  50. * is not found. If it is, then S_OK will be returned.
  51. * If an error occurs getting the enumerator from the
  52. * property storage, then that error is returned.
  53. *
  54. * History:
  55. *
  56. * 27/4/1998 Original Version
  57. *
  58. \**************************************************************************/
  59. HRESULT GetPropID(
  60. IWiaPropertyStorage *pWiaPropStg,
  61. PROPSPEC *pPropSpecIn,
  62. PROPSPEC *pPropSpecOut)
  63. {
  64. HRESULT hr;
  65. IEnumSTATPROPSTG *pIEnum;
  66. if (!pWiaPropStg) {
  67. DBG_ERR(("::GetPropIDFromName, property storage argument is NULL!"));
  68. return E_INVALIDARG;
  69. }
  70. //
  71. // If pPropSpecIn is a PropID, simply copy to pPropSpecOut
  72. //
  73. if (pPropSpecIn->ulKind == PRSPEC_PROPID) {
  74. pPropSpecOut->ulKind = PRSPEC_PROPID;
  75. pPropSpecOut->propid = pPropSpecIn->propid;
  76. return S_OK;
  77. }
  78. hr = pWiaPropStg->Enum(&pIEnum);
  79. if (FAILED(hr)) {
  80. DBG_ERR(("::GetPropIDFromName, error getting IEnumSTATPROPSTG!"));
  81. return hr;
  82. }
  83. //
  84. // Go through properties
  85. //
  86. STATPROPSTG statProp;
  87. ULONG celtFetched;
  88. statProp.lpwstrName = NULL;
  89. for (celtFetched = 1; celtFetched > 0; pIEnum->Next(1, &statProp, &celtFetched)) {
  90. if (statProp.lpwstrName) {
  91. if ((wcscmp(statProp.lpwstrName, pPropSpecIn->lpwstr)) == 0) {
  92. //
  93. // Found the right one, so get it's PropID
  94. //
  95. pPropSpecOut->ulKind = PRSPEC_PROPID;
  96. pPropSpecOut->propid = statProp.propid;
  97. pIEnum->Release();
  98. CoTaskMemFree(statProp.lpwstrName);
  99. return S_OK;
  100. }
  101. //
  102. // Free the property name
  103. //
  104. CoTaskMemFree(statProp.lpwstrName);
  105. statProp.lpwstrName = NULL;
  106. }
  107. }
  108. pIEnum->Release();
  109. //
  110. // Property not found
  111. //
  112. return E_INVALIDARG;
  113. }
  114. /**************************************************************************\
  115. * EnumRemoteDevices
  116. *
  117. *
  118. *
  119. * Arguments:
  120. *
  121. *
  122. *
  123. * Return Value:
  124. *
  125. * Status
  126. *
  127. * History:
  128. *
  129. * 1/4/1999 Original Version
  130. *
  131. \**************************************************************************/
  132. HRESULT
  133. EnumRemoteDevices(DWORD *pnDevices,WIA_REMOTE_DEVICE **ppRemDev)
  134. {
  135. DBG_FN(::EnumRemoteDevices);
  136. *pnDevices = 0;
  137. DWORD numDev = 0;
  138. HRESULT hr = S_OK;
  139. //
  140. // find remote device entry in registry
  141. //
  142. LPWSTR szKeyName = REGSTR_PATH_STICONTROL_DEVLIST_W;
  143. HKEY hKeySetup,hKeyDevice;
  144. LONG lResult;
  145. if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
  146. szKeyName,
  147. 0,
  148. KEY_READ | KEY_WRITE,
  149. &hKeySetup) == ERROR_SUCCESS) {
  150. //
  151. // look for machine names
  152. //
  153. WCHAR wszTemp[MAX_PATH+1];
  154. LONG MachineIndex = 0;
  155. //
  156. // go through once to find number
  157. //
  158. do {
  159. lResult = RegEnumKeyW(hKeySetup,MachineIndex++,wszTemp,MAX_PATH+1);
  160. if (lResult == ERROR_SUCCESS) {
  161. numDev++;
  162. }
  163. } while (lResult == ERROR_SUCCESS);
  164. //
  165. // allocate array for return values
  166. //
  167. PWIA_REMOTE_DEVICE pRemDev = (PWIA_REMOTE_DEVICE)LocalAlloc(LPTR,numDev * sizeof(WIA_REMOTE_DEVICE));
  168. *ppRemDev = pRemDev;
  169. if (pRemDev == NULL) {
  170. RegCloseKey(hKeySetup);
  171. DBG_ERR(("EnumRemoteDevices: failed to allcate memory for Remote device"));
  172. return E_OUTOFMEMORY;
  173. }
  174. //
  175. // go through enumeration again, open key and copy name and key to buffer
  176. //
  177. MachineIndex = 0;
  178. do {
  179. lResult = RegEnumKeyW(hKeySetup,MachineIndex,wszTemp,MAX_PATH+1);
  180. if (lResult == ERROR_SUCCESS) {
  181. lResult = RegOpenKeyExW (hKeySetup,
  182. wszTemp,
  183. 0,
  184. KEY_READ | KEY_WRITE,
  185. &hKeyDevice);
  186. if (lResult == ERROR_SUCCESS) {
  187. (*pnDevices)++;
  188. lstrcpyW(pRemDev[MachineIndex].wszDevName,wszTemp);
  189. pRemDev[MachineIndex].hKeyDevice = hKeyDevice;
  190. MachineIndex++;
  191. } else {
  192. DBG_ERR(("EnumRemoteDevices: failed RegOpenKeyExW, status = %lx",lResult));
  193. }
  194. }
  195. } while (lResult == ERROR_SUCCESS);
  196. }
  197. return hr;
  198. }
  199. /**************************************************************************\
  200. * SetWIARemoteDevInfoProperties
  201. *
  202. * Create a property storage on given stream and then write WIA and
  203. * STI device information into the device info properties.
  204. *
  205. * Arguments:
  206. *
  207. * pSti - sti object
  208. * pStm - return stream
  209. * pSdi - sti information on current device
  210. *
  211. * Return Value:
  212. *
  213. * status
  214. *
  215. * History:
  216. *
  217. * 9/2/1998 Original Version
  218. *
  219. \**************************************************************************/
  220. HRESULT SetWIARemoteDevInfoProperties(
  221. LPSTREAM pStm,
  222. PWIA_REMOTE_DEVICE pRemoteDevice)
  223. {
  224. DBG_FN(::SetWIARemoteDevInfoProperties);
  225. UINT i;
  226. HRESULT hr;
  227. LONG lResult;
  228. IPropertyStorage *pPropStg = NULL;
  229. PROPSPEC propspec[WIA_NUM_DIP];
  230. PROPVARIANT propvar[WIA_NUM_DIP];
  231. //
  232. // Create an IPropertyStorage on the stream.
  233. //
  234. hr = StgCreatePropStg(pStm,
  235. FMTID_NULL,
  236. &CLSID_NULL,
  237. PROPSETFLAG_DEFAULT,
  238. 0,
  239. &pPropStg);
  240. if (SUCCEEDED(hr)) {
  241. //
  242. // Set the property specifications and data. Order must match
  243. // the property order in devmangr.idl and wia.h.
  244. //
  245. memset(propspec, 0, sizeof(PROPSPEC) * WIA_NUM_DIP);
  246. memset(propvar, 0, sizeof(VARIANT) * WIA_NUM_DIP);
  247. DWORD dwType;
  248. DWORD dwSize;
  249. for (i = 0; i < WIA_NUM_DIP; i++) {
  250. PROPID propid = g_piDeviceInfo[i];
  251. propspec[i].ulKind = PRSPEC_PROPID;
  252. propspec[i].propid = propid;
  253. propvar[i].vt = VT_BSTR;
  254. switch (propid) {
  255. case WIA_DIP_DEV_ID:
  256. case WIA_DIP_SERVER_NAME:
  257. case WIA_DIP_VEND_DESC:
  258. case WIA_DIP_DEV_DESC:
  259. case WIA_DIP_PORT_NAME:
  260. case WIA_DIP_DEV_NAME:
  261. case WIA_DIP_REMOTE_DEV_ID:
  262. case WIA_DIP_UI_CLSID:
  263. case WIA_DIP_BAUDRATE:
  264. WCHAR szTemp[MAX_PATH];
  265. dwType = REG_SZ;
  266. dwSize = MAX_PATH;
  267. lResult = RegQueryValueExW(pRemoteDevice->hKeyDevice,
  268. g_pszDeviceInfo[i],
  269. 0,
  270. &dwType,
  271. (LPBYTE)szTemp,
  272. &dwSize);
  273. if (lResult == ERROR_SUCCESS) {
  274. propvar[i].bstrVal = SysAllocString(szTemp);
  275. if (!propvar[i].bstrVal) {
  276. DBG_ERR(("SetWIARemoteDevInfoProperties, unable to alloc dev info strings"));
  277. }
  278. }
  279. else {
  280. DBG_ERR(("SetWIARemoteDevInfoProperties, RegQueryValueExW failed"));
  281. DBG_ERR((" error: %d, propid = %li", lResult, propid));
  282. hr = HRESULT_FROM_WIN32(lResult);
  283. propvar[i].bstrVal = NULL;
  284. }
  285. break;
  286. case WIA_DIP_DEV_TYPE:
  287. {
  288. DWORD dwValue;
  289. dwType = REG_DWORD;
  290. dwSize = sizeof(DWORD);
  291. lResult = RegQueryValueExW(pRemoteDevice->hKeyDevice,
  292. g_pszDeviceInfo[i],
  293. 0,
  294. &dwType,
  295. (LPBYTE)&dwValue,
  296. &dwSize);
  297. if (lResult == ERROR_SUCCESS) {
  298. propvar[i].vt = VT_I4;
  299. propvar[i].lVal = (LONG)dwValue;
  300. }
  301. else {
  302. DBG_ERR(("SetWIARemoteDevInfoProperties, RegQueryValueExW failed"));
  303. DBG_ERR((" error: %d, propid = %li", lResult, propid));
  304. hr = HRESULT_FROM_WIN32(lResult);
  305. }
  306. }
  307. break;
  308. case WIA_DIP_HW_CONFIG:
  309. {
  310. DWORD dwValue;
  311. dwType = REG_DWORD;
  312. dwSize = sizeof(DWORD);
  313. lResult = RegQueryValueExW(pRemoteDevice->hKeyDevice,
  314. REGSTR_VAL_HARDWARE_W,
  315. 0,
  316. &dwType,
  317. (LPBYTE)&dwValue,
  318. &dwSize);
  319. if (lResult == ERROR_SUCCESS) {
  320. propvar[i].vt = VT_I4;
  321. propvar[i].lVal = (LONG)dwValue;
  322. }
  323. else {
  324. DBG_ERR(("SetWIARemoteDevInfoProperties, RegQueryValueExW failed"));
  325. DBG_ERR((" error: %d, propid = %li", lResult, propid));
  326. hr = HRESULT_FROM_WIN32(lResult);
  327. }
  328. }
  329. break;
  330. case WIA_DIP_STI_GEN_CAPABILITIES:
  331. {
  332. DWORD dwValue;
  333. dwType = REG_DWORD;
  334. dwSize = sizeof(DWORD);
  335. lResult = RegQueryValueExW(pRemoteDevice->hKeyDevice,
  336. REGSTR_VAL_GENERIC_CAPS_W,
  337. 0,
  338. &dwType,
  339. (LPBYTE)&dwValue,
  340. &dwSize);
  341. if (lResult == ERROR_SUCCESS) {
  342. propvar[i].vt = VT_I4;
  343. propvar[i].lVal = (LONG)dwValue;
  344. }
  345. else {
  346. DBG_ERR(("SetWIARemoteDevInfoProperties, RegQueryValueExW failed"));
  347. DBG_ERR((" error: %d, propid = %li", lResult, propid));
  348. hr = HRESULT_FROM_WIN32(lResult);
  349. }
  350. }
  351. break;
  352. default:
  353. hr = E_FAIL;
  354. DBG_ERR(("SetWIARemoteDevInfoProperties, Unknown device property"));
  355. DBG_ERR((" propid = %li",propid));
  356. }
  357. }
  358. //
  359. // Set the properties for a device
  360. //
  361. if (SUCCEEDED(hr)) {
  362. hr = pPropStg->WriteMultiple(WIA_NUM_DIP,
  363. propspec,
  364. propvar,
  365. WIA_DIP_FIRST);
  366. //
  367. // write property names
  368. //
  369. if (SUCCEEDED(hr)) {
  370. hr = pPropStg->WritePropertyNames(WIA_NUM_DIP,
  371. g_piDeviceInfo,
  372. g_pszDeviceInfo);
  373. if (FAILED(hr)) {
  374. DBG_ERR(("SetWIARemoteDevInfoProperties, WritePropertyNames failed (0x%X)", hr));
  375. }
  376. }
  377. else {
  378. ReportReadWriteMultipleError(hr, "SetWIARemoteDevInfoProperties", NULL, FALSE, WIA_NUM_DIP, propspec);
  379. }
  380. }
  381. // Free the allocated BSTR's.
  382. FreePropVariantArray(WIA_NUM_DIP, propvar);
  383. pPropStg->Release();
  384. }
  385. else {
  386. DBG_ERR(("SetWIARemoteDevInfoProperties, StgCreatePropStg Failed"));
  387. }
  388. return hr;
  389. }
  390. /**************************************************************************\
  391. *
  392. * QueryInterface
  393. * AddRef
  394. * Release
  395. *
  396. * Arguments:
  397. *
  398. * standard
  399. *
  400. * Return Value:
  401. *
  402. * status
  403. *
  404. * History:
  405. *
  406. * 9/2/1998 original version
  407. *
  408. \**************************************************************************/
  409. HRESULT _stdcall CEnumWIADevInfo::QueryInterface(const IID& iid, void** ppv)
  410. {
  411. *ppv = NULL;
  412. if (iid == IID_IUnknown || iid == IID_IEnumWIA_DEV_INFO) {
  413. *ppv = (IEnumWIA_DEV_INFO*) this;
  414. }
  415. else {
  416. return E_NOINTERFACE;
  417. }
  418. AddRef();
  419. return S_OK;
  420. }
  421. ULONG _stdcall CEnumWIADevInfo::AddRef()
  422. {
  423. InterlockedIncrement((long*) &m_cRef);
  424. return m_cRef;
  425. }
  426. ULONG _stdcall CEnumWIADevInfo::Release()
  427. {
  428. ULONG ulRefCount = m_cRef - 1;
  429. if (InterlockedDecrement((long*) &m_cRef) == 0) {
  430. delete this;
  431. return 0;
  432. }
  433. return ulRefCount;
  434. }
  435. /**************************************************************************\
  436. * CEnumWIADevInfo::CEnumWIADevInfo
  437. *
  438. * Init basic class info
  439. *
  440. * Arguments:
  441. *
  442. * none
  443. *
  444. * Return Value:
  445. *
  446. * none
  447. *
  448. * History:
  449. *
  450. * 9/2/1998
  451. *
  452. \**************************************************************************/
  453. CEnumWIADevInfo::CEnumWIADevInfo()
  454. {
  455. m_cRef = 0;
  456. m_lType = 0;
  457. m_pIWiaPropStg = NULL;
  458. m_cDevices = 0;
  459. m_ulIndex = 0;
  460. //
  461. // We're creating a component that exposes interfaces to clients, so
  462. // inform service to make sure service wont shutdown prematurely.
  463. //
  464. CWiaSvc::AddRef();
  465. }
  466. /**************************************************************************\
  467. * CEnumWIADevInfo::Initialize
  468. *
  469. * Get list of all devices from sti, then creat a stream for each device.
  470. * Write all the device info properties for each device into each stream.
  471. *
  472. * Arguments:
  473. *
  474. * lType - type of device this enumerator is being created for
  475. * pSti - sti object
  476. *
  477. * Return Value:
  478. *
  479. * status
  480. *
  481. * History:
  482. *
  483. * 9/2/1998 initial version
  484. * 07/06/1999 Changed to intialize entrie array of Dev. Info. storages
  485. *
  486. \**************************************************************************/
  487. HRESULT CEnumWIADevInfo::Initialize(
  488. LONG lType)
  489. {
  490. DBG_FN(CEnumWIADevInfo::Initialize);
  491. HRESULT hr = E_FAIL;
  492. DWORD cDevices = 0;
  493. hr = g_pDevMan->GetDevInfoStgs(lType, &m_cDevices, &m_pIWiaPropStg);
  494. // TBD: What about remote devices?
  495. return hr;
  496. }
  497. /**************************************************************************\
  498. * CEnumWIADevInfo::~CEnumWIADevInfo
  499. *
  500. * Release and free the backing property streams for each device
  501. *
  502. * Arguments:
  503. *
  504. * none
  505. *
  506. * Return Value:
  507. *
  508. * none
  509. *
  510. * History:
  511. *
  512. * 9/2/1998
  513. *
  514. \**************************************************************************/
  515. CEnumWIADevInfo::~CEnumWIADevInfo()
  516. {
  517. DBG_FN(CEnumWIADevInfo::~CEnumWIADevInfo);
  518. if (m_pIWiaPropStg) {
  519. for (ULONG index = 0; index < m_cDevices; index++) {
  520. if (m_pIWiaPropStg[index]) {
  521. m_pIWiaPropStg[index]->Release();
  522. m_pIWiaPropStg[index] = NULL;
  523. }
  524. }
  525. delete[] m_pIWiaPropStg;
  526. m_pIWiaPropStg = NULL;
  527. }
  528. //
  529. // Component is destroyed, so no more interfaces are exposed from here.
  530. // Inform server by decrementing it's reference count. This will allow
  531. // it to shutdown if it's no longer needed.
  532. //
  533. CWiaSvc::Release();
  534. }
  535. /**************************************************************************\
  536. * CEnumWIADevInfo::Next
  537. *
  538. * Get the next propstg(s) in the enumerator and return.
  539. * Next_Proxy ensures that last parameter is non-NULL.
  540. *
  541. * Arguments:
  542. *
  543. * celt - number of property storages requested
  544. * rgelt - return propstg array
  545. * pceltFetched - number of property storages returned
  546. *
  547. * Return Value:
  548. *
  549. * status
  550. *
  551. * History:
  552. *
  553. * 9/2/1998
  554. *
  555. \**************************************************************************/
  556. HRESULT __stdcall CEnumWIADevInfo::Next(
  557. ULONG celt,
  558. IWiaPropertyStorage **rgelt,
  559. ULONG *pceltFetched)
  560. {
  561. DBG_FN(CEnumWIADevInfo::Next);
  562. HRESULT hr = S_FALSE;
  563. ULONG ulCount;
  564. DBG_TRC(("CEnumWIADevInfo::Next, celt=%d ", celt));
  565. *pceltFetched = 0;
  566. //
  567. // Validate parameters
  568. //
  569. if (celt == 0) {
  570. return(S_OK);
  571. }
  572. //
  573. // Check whether any more elements exist to enumerate through.
  574. //
  575. if ((m_ulIndex >= m_cDevices)) {
  576. return S_FALSE;
  577. }
  578. //
  579. // Check that the requested number of elements exist. If not,
  580. // set ulCount to the remaining number of elements.
  581. //
  582. if (celt > (m_cDevices - m_ulIndex)) {
  583. ulCount = m_cDevices - m_ulIndex;
  584. } else {
  585. ulCount = celt;
  586. }
  587. memset(rgelt, 0, sizeof(IWiaPropertyStorage*) * celt);
  588. //
  589. // Return the requested elements
  590. //
  591. for (ULONG index = 0; index < ulCount; index++) {
  592. hr = m_pIWiaPropStg[m_ulIndex]->QueryInterface(IID_IWiaPropertyStorage,
  593. (void**) &rgelt[index]);
  594. if (FAILED(hr)) {
  595. DBG_ERR(("CEnumWIADevInfo::Next, QI for IPropertyStorage failed"));
  596. break;
  597. }
  598. m_ulIndex++;
  599. }
  600. if (FAILED(hr)) {
  601. for (ULONG index = 0; index < ulCount; index++) {
  602. if (rgelt[index]) {
  603. rgelt[index]->Release();
  604. rgelt[index] = NULL;
  605. }
  606. }
  607. }
  608. *pceltFetched = ulCount;
  609. DBG_TRC(("CEnumWIADevInfo::Next exiting ulCount=%d *pceltFetched=%d hr=0x%X rgelt[0]=0x%lX",
  610. ulCount,*pceltFetched,hr,rgelt[0]));
  611. //
  612. // Return S_FALSE if we returned less elements than requested
  613. //
  614. if (ulCount < celt) {
  615. hr = S_FALSE;
  616. }
  617. return hr;
  618. }
  619. /**************************************************************************\
  620. * CEnumWIADevInfo::Skip
  621. *
  622. * Skip a number of entries in the enumerator
  623. *
  624. * Arguments:
  625. *
  626. * celt - number to skip
  627. *
  628. * Return Value:
  629. *
  630. * status
  631. *
  632. * History:
  633. *
  634. * 9/2/1998
  635. *
  636. \**************************************************************************/
  637. HRESULT __stdcall CEnumWIADevInfo::Skip(ULONG celt)
  638. {
  639. DBG_FN(CEnumWIADevInfo::Skip);
  640. //
  641. // Check that we actually have a device list and that we don't
  642. // exceed the number of elements
  643. //
  644. if((m_pIWiaPropStg) && ((m_ulIndex + celt) < m_cDevices)) {
  645. m_ulIndex += celt;
  646. return S_OK;
  647. }
  648. return S_FALSE;
  649. }
  650. /**************************************************************************\
  651. * CEnumWIADevInfo::Reset
  652. *
  653. * reset enumerator to first item
  654. *
  655. * Arguments:
  656. *
  657. * none
  658. *
  659. * Return Value:
  660. *
  661. * status
  662. *
  663. * History:
  664. *
  665. * 9/2/1998 Original Version
  666. *
  667. \**************************************************************************/
  668. HRESULT __stdcall CEnumWIADevInfo::Reset(void)
  669. {
  670. DBG_FN(CEnumWIADevInfo::Reset);
  671. m_ulIndex = 0;
  672. return S_OK;
  673. }
  674. /**************************************************************************\
  675. * CEnumWIADevInfo::Clone
  676. *
  677. * Create a new enumerator and start it at the same location
  678. * this enumerator is running
  679. *
  680. * Arguments:
  681. *
  682. * ppenum return new enumerator interface
  683. *
  684. * Return Value:
  685. *
  686. * status
  687. *
  688. * History:
  689. *
  690. * 9/2/1998 Original Version
  691. *
  692. \**************************************************************************/
  693. HRESULT __stdcall CEnumWIADevInfo::Clone(IEnumWIA_DEV_INFO **ppenum)
  694. {
  695. DBG_FN(CEnumWIADevInfo::Clone);
  696. HRESULT hr = S_OK;
  697. CEnumWIADevInfo* pClone=NULL;
  698. pClone = new CEnumWIADevInfo();
  699. if (!pClone) {
  700. return E_OUTOFMEMORY;
  701. }
  702. hr = pClone->Initialize(m_lType);
  703. if (FAILED(hr)) {
  704. delete pClone;
  705. return hr;
  706. }
  707. pClone->m_ulIndex = m_ulIndex;
  708. hr = pClone->QueryInterface(IID_IEnumWIA_DEV_INFO, (void**) ppenum);
  709. if (FAILED(hr)) {
  710. delete pClone;
  711. DBG_ERR(("CEnumWIADevInfo::Clone, QI for IWiaPropertyStorage failed"));
  712. return hr;
  713. }
  714. return S_OK;
  715. }
  716. /**************************************************************************\
  717. * GetCount
  718. *
  719. * Returns the number of elements stored in this enumerator.
  720. *
  721. * Arguments:
  722. *
  723. * pcelt - address of ULONG where to put the number of elements.
  724. *
  725. * Return Value:
  726. *
  727. * Status - S_OK if successful
  728. * E_FAIL if failed
  729. *
  730. * History:
  731. *
  732. * 05/07/99 Original Version
  733. *
  734. \**************************************************************************/
  735. HRESULT _stdcall CEnumWIADevInfo::GetCount(ULONG *pcelt)
  736. {
  737. DBG_FN(CEnumWIADevInfo::GetCount);
  738. if (IsBadWritePtr(pcelt, sizeof(ULONG))) {
  739. return E_POINTER;
  740. } else {
  741. *pcelt = 0;
  742. }
  743. //
  744. // Check that we actually have a list and that the count
  745. // has a non-zero value.
  746. //
  747. if(m_cDevices && m_pIWiaPropStg) {
  748. *pcelt = m_cDevices;
  749. }
  750. return S_OK;
  751. }
  752. /**************************************************************************\
  753. *
  754. * QueryInterface
  755. * AddRef
  756. * Release
  757. *
  758. * Arguments:
  759. *
  760. *
  761. *
  762. * Return Value:
  763. *
  764. *
  765. *
  766. * History:
  767. *
  768. * 9/2/1998 Original Version
  769. *
  770. \**************************************************************************/
  771. HRESULT _stdcall CWIADevInfo::QueryInterface(const IID& iid, void** ppv)
  772. {
  773. *ppv = NULL;
  774. if (iid == IID_IUnknown || iid == IID_IWiaPropertyStorage) {
  775. *ppv = (IWiaPropertyStorage*) this;
  776. } else if (iid == IID_IPropertyStorage) {
  777. *ppv = (IPropertyStorage*) this;
  778. }
  779. else {
  780. return E_NOINTERFACE;
  781. }
  782. AddRef();
  783. return S_OK;
  784. }
  785. ULONG _stdcall CWIADevInfo::AddRef()
  786. {
  787. InterlockedIncrement((long*) &m_cRef);
  788. return m_cRef;
  789. }
  790. ULONG _stdcall CWIADevInfo::Release()
  791. {
  792. ULONG ulRefCount = m_cRef - 1;
  793. if (InterlockedDecrement((long*) &m_cRef) == 0) {
  794. delete this;
  795. return 0;
  796. }
  797. return ulRefCount;
  798. }
  799. /**************************************************************************\
  800. * CWIADevInfo::CWIADevInfo
  801. *
  802. * init empty object
  803. *
  804. * Arguments:
  805. *
  806. * none
  807. *
  808. * Return Value:
  809. *
  810. * none
  811. *
  812. * History:
  813. *
  814. * 9/2/1998 Original Version
  815. *
  816. \**************************************************************************/
  817. CWIADevInfo::CWIADevInfo()
  818. {
  819. m_cRef = 0;
  820. m_pITypeInfo = NULL;
  821. m_pIPropStg = NULL;
  822. m_pIStm = NULL;
  823. //
  824. // We're creating a component that exposes interfaces to clients, so
  825. // inform service to make sure service wont shutdown prematurely.
  826. //
  827. CWiaSvc::AddRef();
  828. }
  829. /**************************************************************************\
  830. * CopyItemProp
  831. *
  832. * This helper method copies a single property from source to destination.
  833. *
  834. * Arguments:
  835. *
  836. * pIPropStgSrc - The IPropertyStorage that contains the property to
  837. * copy.
  838. * pIPropStgDst - The IPropertyStorage where the value is copied to.
  839. * pps - The PROPSPEC which specifies the source property.
  840. * pszErr - A string that will be printed out when an error
  841. * occurs.
  842. * Return Value:
  843. *
  844. * Status - Returns HRESULT from ReadMultiple and WriteMultiple.
  845. *
  846. * History:
  847. *
  848. * 28/04/1999 Original Version
  849. *
  850. \**************************************************************************/
  851. HRESULT CopyItemProp(
  852. IPropertyStorage *pIPropStgSrc,
  853. IPropertyStorage *pIPropStgDst,
  854. PROPSPEC *pps,
  855. LPSTR pszErr)
  856. {
  857. DBG_FN(::CopyItemProp);
  858. PROPVARIANT pv[1];
  859. HRESULT hr = pIPropStgSrc->ReadMultiple(1, pps, pv);
  860. if (SUCCEEDED(hr)) {
  861. hr = pIPropStgDst->WriteMultiple(1, pps, pv, WIA_DIP_FIRST);
  862. if (FAILED(hr)) {
  863. ReportReadWriteMultipleError(hr,
  864. "CopyItemProp",
  865. pszErr,
  866. FALSE,
  867. 1,
  868. pps);
  869. }
  870. PropVariantClear(pv);
  871. }
  872. else {
  873. ReportReadWriteMultipleError(hr,
  874. "CopyItemProp",
  875. pszErr,
  876. TRUE,
  877. 1,
  878. pps);
  879. }
  880. return hr;
  881. }
  882. /**************************************************************************\
  883. * CWIADevInfo::Initialize
  884. *
  885. * Initialize DevInfo object with a stream, the stream must already be
  886. * filled out with device information properties
  887. *
  888. * Arguments:
  889. *
  890. * pIStream - data stream for the device
  891. *
  892. * Return Value:
  893. *
  894. * status
  895. *
  896. * History:
  897. *
  898. * 9/2/1998 Original Version
  899. *
  900. \**************************************************************************/
  901. HRESULT CWIADevInfo::Initialize()
  902. {
  903. DBG_FN(CWIADevInfo::Initialize);
  904. HRESULT hr;
  905. hr = CreateStreamOnHGlobal(NULL, TRUE, &m_pIStm);
  906. if (SUCCEEDED(hr)) {
  907. //
  908. // Open a property storage on the stream.
  909. //
  910. hr = StgCreatePropStg(m_pIStm,
  911. FMTID_NULL,
  912. &CLSID_NULL,
  913. PROPSETFLAG_DEFAULT,
  914. 0,
  915. &m_pIPropStg);
  916. if (FAILED(hr)) {
  917. DBG_ERR(("CWIADevInfo::Initialize, StgOpenPropStg failed (0x%X)", hr));
  918. }
  919. } else {
  920. DBG_ERR(("CWIADevInfo::Initialize, CreateStreamOnHGlobal failed (0x%X)", hr));
  921. }
  922. return hr;
  923. }
  924. /**************************************************************************\
  925. * CWIADevInfo::~CWIADevInfo
  926. *
  927. * release references to stream and typeInfo
  928. *
  929. * Arguments:
  930. *
  931. * none
  932. *
  933. * Return Value:
  934. *
  935. * none
  936. *
  937. * History:
  938. *
  939. * 9/2/1998 Original Version
  940. *
  941. \**************************************************************************/
  942. CWIADevInfo::~CWIADevInfo()
  943. {
  944. DBG_FN(CWIADevInfo::~CWIADevInfo);
  945. if (m_pIPropStg) {
  946. m_pIPropStg->Release();
  947. m_pIPropStg = NULL;
  948. }
  949. if (m_pIStm) {
  950. m_pIStm->Release();
  951. m_pIStm = NULL;
  952. }
  953. if (m_pITypeInfo) {
  954. m_pITypeInfo->Release();
  955. }
  956. //
  957. // Component is destroyed, so no more interfaces are exposed from here.
  958. // Inform server by decrementing it's reference count. This will allow
  959. // it to shutdown if it's no longer needed.
  960. //
  961. CWiaSvc::Release();
  962. }
  963. /**************************************************************************\
  964. * UpdateDeviceProperties
  965. *
  966. * Helper function for CWIADevInfo::WriteMultiple. It is used to change
  967. * the Device properties which are stored in the registry.
  968. *
  969. * Arguments:
  970. *
  971. * cpspec - count of properties to write.
  972. * rgpspec - PROPSPEC identifying the properties to write. Caller
  973. * ensures that these are of type PRSPEC_PROPID.
  974. * rgpropvar - PROPVARIANT array containing the values to write.
  975. *
  976. * Return Value:
  977. *
  978. * Status
  979. *
  980. * History:
  981. *
  982. * 26/08/1999 Original Version
  983. *
  984. \**************************************************************************/
  985. HRESULT CWIADevInfo::UpdateDeviceProperties(
  986. ULONG cpspec,
  987. const PROPSPEC *rgpspec,
  988. const PROPVARIANT *rgpropvar)
  989. {
  990. DBG_FN(CWIADevInfo::UpdateDeviceProperties);
  991. ACTIVE_DEVICE *pActiveDevice = NULL;
  992. DEVICE_INFO *pDeviceInfo = NULL;
  993. PROPSPEC ps[1] = {{PRSPEC_PROPID, WIA_DIP_DEV_ID}};
  994. PROPVARIANT pvDevID[1];
  995. PSTI pSti;
  996. HRESULT hr = S_OK;
  997. WCHAR *wszSavedLocalName = NULL;
  998. WCHAR *wszSavedPortName = NULL;
  999. WCHAR *wszSavedBaudRate = NULL;
  1000. //
  1001. // Get the DeviceID
  1002. //
  1003. PropVariantInit(pvDevID);
  1004. hr = ReadMultiple(1, ps, pvDevID);
  1005. if (hr == S_OK) {
  1006. //
  1007. // Use the DeviceID to get the corresponding ACTIVE_DEVICE
  1008. //
  1009. pActiveDevice = g_pDevMan->IsInList(DEV_MAN_IN_LIST_DEV_ID, pvDevID->bstrVal);
  1010. if (pActiveDevice) {
  1011. TAKE_ACTIVE_DEVICE t(pActiveDevice);
  1012. pDeviceInfo = pActiveDevice->m_DrvWrapper.getDevInfo();
  1013. if (pDeviceInfo) {
  1014. //
  1015. // Update the pDevInfo struct values to the new values from
  1016. // rgpropvar. Inside this loop is where we update pDevInfo
  1017. // with all the fields we recognize. So far, these are:
  1018. // WIA_DIP_DEV_NAME
  1019. // WIA_DIP_PORT_NAME
  1020. // WIA_DIP_BAUDRATE
  1021. //
  1022. for (ULONG index = 0; index < cpspec; index++) {
  1023. //
  1024. // If the FriendlyName is being changed,
  1025. // then set the local name in pDevInfo.
  1026. // Make sure to free the old one before allocating the new one.
  1027. //
  1028. if (rgpspec[index].propid == WIA_DIP_DEV_NAME) {
  1029. //
  1030. // Check the the friendly name is not blank or null
  1031. //
  1032. //
  1033. // NOTE: The Shell should check for blank names, not us.
  1034. // However, it is safest to do it here...
  1035. //
  1036. if (rgpropvar[index].bstrVal) {
  1037. if (wcslen(rgpropvar[index].bstrVal) > 0) {
  1038. //
  1039. // Set the new local name. Save the old value, in case the
  1040. // update fails and we need to roll back.
  1041. //
  1042. wszSavedLocalName = pDeviceInfo->wszLocalName;
  1043. pDeviceInfo->wszLocalName = AllocCopyString(rgpropvar[index].bstrVal);
  1044. if (!pDeviceInfo->wszLocalName) {
  1045. DBG_ERR(("CWIADevInfo::UpdateDeviceProperties, Out of memory"));
  1046. hr = E_OUTOFMEMORY;
  1047. }
  1048. } else {
  1049. DBG_ERR(("CWIADevInfo::UpdateDeviceProperties, WIA_DIP_DEV_NAME is blank"));
  1050. hr = E_INVALIDARG;
  1051. break;
  1052. }
  1053. } else {
  1054. DBG_ERR(("CWIADevInfo::UpdateDeviceProperties, WIA_DIP_DEV_NAME is NULL"));
  1055. hr = E_INVALIDARG;
  1056. break;
  1057. }
  1058. }
  1059. //
  1060. // If the port name is being changed, set it in pDeviceInfo.
  1061. //
  1062. if (rgpspec[index].propid == WIA_DIP_PORT_NAME) {
  1063. //
  1064. // Set the new port name. Save the old value, in case the
  1065. // update fails and we need to roll back.
  1066. //
  1067. wszSavedPortName = pDeviceInfo->wszPortName;
  1068. pDeviceInfo->wszPortName = AllocCopyString(rgpropvar[index].bstrVal);
  1069. if (!pDeviceInfo->wszPortName) {
  1070. DBG_ERR(("CWIADevInfo::UpdateDeviceProperties, Out of memory"));
  1071. hr = E_OUTOFMEMORY;
  1072. }
  1073. }
  1074. //
  1075. // If the baudrate is being changed, set it in pDeviceInfo.
  1076. //
  1077. if (rgpspec[index].propid == WIA_DIP_BAUDRATE) {
  1078. //
  1079. // Set the new baudrate. Save the old value, in case the
  1080. // update fails and we need to roll back.
  1081. //
  1082. wszSavedBaudRate = pDeviceInfo->wszBaudRate;
  1083. pDeviceInfo->wszBaudRate = AllocCopyString(rgpropvar[index].bstrVal);
  1084. if (!pDeviceInfo->wszBaudRate) {
  1085. DBG_ERR(("CWIADevInfo::UpdateDeviceProperties, Out of memory"));
  1086. hr = E_OUTOFMEMORY;
  1087. }
  1088. }
  1089. }
  1090. }
  1091. if (SUCCEEDED(hr)) {
  1092. //
  1093. // Write the changes to the registry
  1094. //
  1095. hr = g_pDevMan->UpdateDeviceRegistry(pDeviceInfo);
  1096. }
  1097. //
  1098. // Release the ACTIVE_DEVICE since it was AddRef'd by IsInList(...)
  1099. //
  1100. pActiveDevice->Release();
  1101. }
  1102. //
  1103. // Free the propvariant data
  1104. //
  1105. PropVariantClear(pvDevID);
  1106. } else {
  1107. DBG_ERR(("CWIADevInfo::UpdateDeviceProperties, could not read the DeviceID (0x%X)", hr));
  1108. }
  1109. //
  1110. // Do cleanup
  1111. //
  1112. if (SUCCEEDED(hr))
  1113. {
  1114. //
  1115. // On success, we need to free the old, saved values
  1116. //
  1117. if (wszSavedLocalName) {
  1118. delete [] wszSavedLocalName;
  1119. wszSavedLocalName = NULL;
  1120. }
  1121. if (wszSavedPortName) {
  1122. delete [] wszSavedPortName;
  1123. wszSavedPortName = NULL;
  1124. }
  1125. if (wszSavedBaudRate) {
  1126. delete [] wszSavedBaudRate;
  1127. wszSavedBaudRate = NULL;
  1128. }
  1129. }
  1130. else
  1131. {
  1132. //
  1133. // On failure, we need to roll back to the old values.
  1134. //
  1135. if (wszSavedLocalName) {
  1136. if (pDeviceInfo->wszLocalName)
  1137. {
  1138. delete [] pDeviceInfo->wszLocalName;
  1139. }
  1140. pDeviceInfo->wszLocalName = wszSavedLocalName;
  1141. }
  1142. if (wszSavedPortName) {
  1143. if (pDeviceInfo->wszPortName)
  1144. {
  1145. delete [] pDeviceInfo->wszPortName;
  1146. }
  1147. pDeviceInfo->wszPortName = wszSavedLocalName;
  1148. }
  1149. if (wszSavedBaudRate) {
  1150. if (pDeviceInfo->wszBaudRate)
  1151. {
  1152. delete [] pDeviceInfo->wszBaudRate;
  1153. }
  1154. pDeviceInfo->wszBaudRate = wszSavedLocalName;
  1155. }
  1156. }
  1157. return hr;
  1158. }
  1159. /*******************************************************************************
  1160. *
  1161. * ReadMultiple
  1162. * WriteMultiple
  1163. * DeleteMultiple
  1164. * ReadPropertyNames
  1165. * WritePropertyNames
  1166. * DeletePropertyNames
  1167. * Commit
  1168. * Revert
  1169. * Enum
  1170. * SetTimes
  1171. * SetClass
  1172. * Stat
  1173. *
  1174. * Pass-through implementation to IPropStg
  1175. *
  1176. * Arguments:
  1177. *
  1178. *
  1179. *
  1180. * Return Value:
  1181. *
  1182. *
  1183. *
  1184. * History:
  1185. *
  1186. * 9/2/1998 Original Version
  1187. *
  1188. \**************************************************************************/
  1189. HRESULT _stdcall CWIADevInfo::ReadMultiple(
  1190. ULONG cpspec,
  1191. const PROPSPEC *rgpspec,
  1192. PROPVARIANT *rgpropvar)
  1193. {
  1194. DBG_FN(CWIADevInfo::ReadMultiple);
  1195. HRESULT hr = m_pIPropStg->ReadMultiple(cpspec, rgpspec, rgpropvar);
  1196. if (FAILED(hr)) {
  1197. ReportReadWriteMultipleError(hr, "CWIADevInfo::ReadMultiple", NULL, TRUE, cpspec, rgpspec);
  1198. }
  1199. return hr;
  1200. }
  1201. HRESULT _stdcall CWIADevInfo::WriteMultiple(
  1202. ULONG cpspec,
  1203. const PROPSPEC *rgpspec,
  1204. const PROPVARIANT *rgpropvar,
  1205. PROPID propidNameFirst)
  1206. {
  1207. DBG_FN(CWIADevInfo::WriteMultiple);
  1208. BOOL bInvalidProp;
  1209. PROPSPEC *pPropSpec;
  1210. HRESULT hr = S_OK;
  1211. //
  1212. // Attempt to impersonate the client. We need it since LocalService does not have sufficient permissions
  1213. // to modify the registry where the DIP values are stored - only ADMINs have rights to this key.
  1214. //
  1215. hr = CoImpersonateClient();
  1216. if (SUCCEEDED(hr))
  1217. {
  1218. //
  1219. // Attempt to update any properties to which access is allowed.
  1220. // Currently, only the FriendlyName may be changed, anything
  1221. // else returns E_INVALIDARG.
  1222. //
  1223. pPropSpec = (PROPSPEC*) LocalAlloc(LPTR, sizeof(PROPSPEC) * cpspec);
  1224. if (pPropSpec) {
  1225. //
  1226. // First, make a copy of the incoming PROPSPEC array, and convert
  1227. // any property names to PROPIDs. While doing the conversion,
  1228. // make sure that access to those properties are allowed.
  1229. // This ensures that UpdateDeviceProperties receives only valid
  1230. // properties indicated by PROPIDs.
  1231. //
  1232. for (ULONG index = 0; index < cpspec; index++) {
  1233. bInvalidProp = TRUE;
  1234. pPropSpec[index].ulKind = PRSPEC_PROPID;
  1235. if (SUCCEEDED(GetPropID(this, (PROPSPEC*)&rgpspec[index], &pPropSpec[index]))) {
  1236. //
  1237. // Look for PropID matches here. So far, we only recognize:
  1238. // WIA_DIP_DEV_NAME
  1239. // WIA_DIP_PORT_NAME
  1240. // WIA_DIP_BAUDRATE
  1241. //
  1242. switch (rgpspec[index].propid) {
  1243. case WIA_DIP_DEV_NAME :
  1244. case WIA_DIP_PORT_NAME :
  1245. case WIA_DIP_BAUDRATE :
  1246. bInvalidProp = FALSE;
  1247. break;
  1248. default:
  1249. bInvalidProp = TRUE;
  1250. }
  1251. }
  1252. if (bInvalidProp) {
  1253. DBG_ERR(("CWIADevInfo::WriteMultiple, property not allowed to be written"));
  1254. hr = E_ACCESSDENIED;
  1255. break;
  1256. }
  1257. }
  1258. if (SUCCEEDED(hr)) {
  1259. //
  1260. // Update the device properties stored in the registry
  1261. //
  1262. hr = UpdateDeviceProperties(cpspec, pPropSpec, rgpropvar);
  1263. if (SUCCEEDED(hr)) {
  1264. //
  1265. // Registry updated, so update the PropertyStorage to reflect
  1266. // the change.
  1267. //
  1268. hr = m_pIPropStg->WriteMultiple(cpspec,
  1269. pPropSpec,
  1270. rgpropvar,
  1271. WIA_DIP_FIRST);
  1272. if (FAILED(hr)) {
  1273. DBG_ERR(("CWIADevInfo::WriteMultiple, updated registry, but failed to update property storage"));
  1274. }
  1275. }
  1276. }
  1277. //
  1278. // Free our PropSpec array
  1279. //
  1280. LocalFree(pPropSpec);
  1281. } else {
  1282. DBG_ERR(("CWIADevInfo::WriteMultiple, out of memory"));
  1283. hr = E_OUTOFMEMORY;
  1284. }
  1285. HRESULT hrRevert = CoRevertToSelf();
  1286. if (FAILED(hrRevert))
  1287. {
  1288. DBG_ERR(("CWIADevInfo::WriteMultiple, could not revert to self, hr = %08X", hr));
  1289. // TBD: What do we do now? Terminate?
  1290. }
  1291. }
  1292. else
  1293. {
  1294. DBG_ERR(("Error attempting to update device settings, could not impersonate client, therefore we do not have sufficient credentials to write to the registry"));
  1295. }
  1296. return hr;
  1297. }
  1298. HRESULT _stdcall CWIADevInfo::ReadPropertyNames(
  1299. ULONG cpropid,
  1300. const PROPID *rgpropid,
  1301. LPOLESTR *rglpwstrName)
  1302. {
  1303. DBG_FN(CWIADevInfo::ReadPropertyNames);
  1304. return m_pIPropStg->ReadPropertyNames(cpropid,rgpropid,rglpwstrName);
  1305. }
  1306. HRESULT _stdcall CWIADevInfo::WritePropertyNames(
  1307. ULONG cpropid,
  1308. const PROPID *rgpropid,
  1309. const LPOLESTR *rglpwstrName)
  1310. {
  1311. DBG_FN(CWIADevInfo::WritePropertyNames);
  1312. return(E_ACCESSDENIED);
  1313. }
  1314. HRESULT _stdcall CWIADevInfo::Enum(
  1315. IEnumSTATPROPSTG **ppenum)
  1316. {
  1317. DBG_FN(CWIADevInfo::Enum);
  1318. return m_pIPropStg->Enum(ppenum);
  1319. }
  1320. HRESULT _stdcall CWIADevInfo::GetPropertyAttributes(
  1321. ULONG cPropSpec,
  1322. PROPSPEC *pPropSpec,
  1323. ULONG *pulAccessFlags,
  1324. PROPVARIANT *ppvValidValues)
  1325. {
  1326. DBG_FN(CWIADevInfo::GetPropertyAttributes);
  1327. return E_ACCESSDENIED;
  1328. }
  1329. HRESULT _stdcall CWIADevInfo::GetCount(
  1330. ULONG* pulPropCount)
  1331. {
  1332. DBG_FN(CWIADevInfo::GetCount);
  1333. IEnumSTATPROPSTG *pIEnum;
  1334. STATPROPSTG stg;
  1335. ULONG ulCount;
  1336. HRESULT hr = S_OK;
  1337. stg.lpwstrName = NULL;
  1338. hr = m_pIPropStg->Enum(&pIEnum);
  1339. if (SUCCEEDED(hr)) {
  1340. for (ulCount = 0; hr == S_OK; hr = pIEnum->Next(1, &stg, NULL)) {
  1341. ulCount++;
  1342. if(stg.lpwstrName) {
  1343. CoTaskMemFree(stg.lpwstrName);
  1344. }
  1345. }
  1346. if (SUCCEEDED(hr)) {
  1347. hr = S_OK;
  1348. *pulPropCount = ulCount;
  1349. } else {
  1350. DBG_ERR(("CWIADevInfo::GetCount, pIEnum->Next failed (0x%X)", hr));
  1351. }
  1352. pIEnum->Release();
  1353. } else {
  1354. DBG_ERR(("CWIADevInfo::GetCount, Enum failed"));
  1355. }
  1356. return hr;
  1357. }
  1358. HRESULT _stdcall CWIADevInfo::GetPropertyStream(GUID *pCompatibilityId, LPSTREAM *ppstmProp)
  1359. {
  1360. DBG_FN(CWIADevInfo::GetPropertyStream);
  1361. return E_NOTIMPL;
  1362. }
  1363. HRESULT _stdcall CWIADevInfo::SetPropertyStream(GUID *pCompatibilityId, LPSTREAM pstmProp)
  1364. {
  1365. DBG_FN(CWIADevInfo::SetPropertyStream);
  1366. return E_ACCESSDENIED;
  1367. }
  1368. /**************************************************************************\
  1369. *
  1370. * Methods of IPropertyStorage not directly off IWiaPropertySTorage
  1371. *
  1372. * DeleteMultiple
  1373. * DeletePropertyNames
  1374. * Commit
  1375. * Revert
  1376. * SetTimes
  1377. * SetClass
  1378. * Stat
  1379. *
  1380. * 9/3/1998 Original Version
  1381. *
  1382. \**************************************************************************/
  1383. HRESULT _stdcall CWIADevInfo::DeleteMultiple(
  1384. ULONG cpspec,
  1385. const PROPSPEC __RPC_FAR rgpspec[])
  1386. {
  1387. DBG_FN(CWIADevInfo::DeleteMultiple);
  1388. return E_ACCESSDENIED;
  1389. }
  1390. HRESULT _stdcall CWIADevInfo::DeletePropertyNames(
  1391. ULONG cpropid,
  1392. const PROPID __RPC_FAR rgpropid[])
  1393. {
  1394. DBG_FN(CWIADevInfo::DeletePropertyNames);
  1395. return E_ACCESSDENIED;
  1396. }
  1397. HRESULT _stdcall CWIADevInfo::Commit(DWORD grfCommitFlags)
  1398. {
  1399. DBG_FN(CWIADevInfo::Commit);
  1400. return m_pIPropStg->Commit(grfCommitFlags);
  1401. }
  1402. HRESULT _stdcall CWIADevInfo::Revert(void)
  1403. {
  1404. DBG_FN(CWIADevInfo::Revert);
  1405. return m_pIPropStg->Revert();
  1406. }
  1407. HRESULT _stdcall CWIADevInfo::SetTimes(
  1408. const FILETIME __RPC_FAR *pctime,
  1409. const FILETIME __RPC_FAR *patime,
  1410. const FILETIME __RPC_FAR *pmtime)
  1411. {
  1412. DBG_FN(CWIADevInfo::SetTimes);
  1413. return m_pIPropStg->SetTimes(pctime,patime,pmtime);
  1414. }
  1415. HRESULT _stdcall CWIADevInfo::SetClass(REFCLSID clsid)
  1416. {
  1417. DBG_FN(CWIADevInfo::SetClass);
  1418. return E_ACCESSDENIED;
  1419. }
  1420. HRESULT _stdcall CWIADevInfo::Stat(STATPROPSETSTG *pstatpsstg)
  1421. {
  1422. DBG_FN(CWIADevInfo::Stat);
  1423. return m_pIPropStg->Stat(pstatpsstg);
  1424. }