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.

902 lines
23 KiB

  1. // SetupClass.cpp : Implementation of CSetupClass
  2. #include "stdafx.h"
  3. #include "DevCon2.h"
  4. #include "SetupClass.h"
  5. #include "devices.h"
  6. #include "utils.h"
  7. #include "xStrings.h"
  8. /////////////////////////////////////////////////////////////////////////////
  9. // CSetupClass
  10. CSetupClass::~CSetupClass()
  11. {
  12. if(pMachine) {
  13. SysFreeString(pMachine);
  14. }
  15. }
  16. HRESULT CSetupClass::Init(GUID *pGuid,LPWSTR Machine, IDeviceConsole *pDevCon)
  17. {
  18. ClassGuid = *pGuid;
  19. if(pMachine) {
  20. SysFreeString(pMachine);
  21. }
  22. if(Machine) {
  23. pMachine = SysAllocString(Machine);
  24. if(!pMachine) {
  25. return E_OUTOFMEMORY;
  26. }
  27. } else {
  28. pMachine = NULL;
  29. }
  30. DeviceConsole = pDevCon;
  31. return S_OK;
  32. }
  33. BOOL CSetupClass::IsDuplicate(GUID *pCheck)
  34. {
  35. //
  36. // only valid if pMachine/DeviceConsole known to be same
  37. //
  38. return memcmp(&ClassGuid,pCheck,sizeof(GUID)) ? FALSE : TRUE;
  39. }
  40. STDMETHODIMP CSetupClass::get_Name(BSTR *pVal)
  41. {
  42. HRESULT hr;
  43. DWORD Err;
  44. LPWSTR Buffer;
  45. DWORD BuffSize=128;
  46. DWORD ReqSize;
  47. for(;;) {
  48. Buffer = new WCHAR[BuffSize];
  49. if(!Buffer) {
  50. return E_OUTOFMEMORY;
  51. }
  52. if(SetupDiClassNameFromGuidEx(&ClassGuid,Buffer,BuffSize,&ReqSize,pMachine,NULL)) {
  53. *pVal = SysAllocString(Buffer);
  54. delete [] Buffer;
  55. if(!*pVal) {
  56. return E_OUTOFMEMORY;
  57. }
  58. return S_OK;
  59. }
  60. Err = GetLastError();
  61. delete [] Buffer;
  62. if(Err != ERROR_INSUFFICIENT_BUFFER) {
  63. hr = HRESULT_FROM_SETUPAPI(Err);
  64. return hr;
  65. }
  66. BuffSize = ReqSize+2;
  67. }
  68. return S_OK;
  69. }
  70. STDMETHODIMP CSetupClass::get_Description(BSTR *pVal)
  71. {
  72. HRESULT hr;
  73. DWORD Err;
  74. LPWSTR Buffer;
  75. DWORD BuffSize=128;
  76. DWORD ReqSize;
  77. for(;;) {
  78. Buffer = new WCHAR[BuffSize];
  79. if(!Buffer) {
  80. return E_OUTOFMEMORY;
  81. }
  82. if(SetupDiGetClassDescriptionEx(&ClassGuid,Buffer,BuffSize,&ReqSize,pMachine,NULL)) {
  83. *pVal = SysAllocString(Buffer);
  84. delete [] Buffer;
  85. if(!*pVal) {
  86. return E_OUTOFMEMORY;
  87. }
  88. return S_OK;
  89. }
  90. Err = GetLastError();
  91. delete [] Buffer;
  92. if(Err != ERROR_INSUFFICIENT_BUFFER) {
  93. hr = HRESULT_FROM_SETUPAPI(Err);
  94. return hr;
  95. }
  96. BuffSize = ReqSize+2;
  97. }
  98. return S_OK;
  99. }
  100. STDMETHODIMP CSetupClass::Devices(VARIANT flags,LPDISPATCH * pDevices)
  101. {
  102. DWORD diflags = 0;
  103. HRESULT hr;
  104. HDEVINFO hDevInfo;
  105. DWORD Err;
  106. hr = TranslateDeviceFlags(&flags,&diflags);
  107. if(FAILED(hr)) {
  108. return hr;
  109. }
  110. hDevInfo = SetupDiGetClassDevsEx(&ClassGuid,NULL,NULL,diflags,NULL,pMachine,NULL);
  111. if(hDevInfo == INVALID_HANDLE_VALUE) {
  112. Err = GetLastError();
  113. return HRESULT_FROM_SETUPAPI(Err);
  114. }
  115. CComObject<CDevices> *d;
  116. hr = CComObject<CDevices>::CreateInstance(&d);
  117. if(FAILED(hr)) {
  118. SetupDiDestroyDeviceInfoList(hDevInfo);
  119. return hr;
  120. }
  121. d->AddRef();
  122. hr = d->Init(hDevInfo,DeviceConsole);
  123. if(FAILED(hr)) {
  124. d->Release();
  125. return hr;
  126. }
  127. *pDevices = d;
  128. return S_OK;
  129. }
  130. STDMETHODIMP CSetupClass::CreateEmptyDeviceList(LPDISPATCH *pDevices)
  131. {
  132. HRESULT hr;
  133. HDEVINFO hDevInfo;
  134. DWORD Err;
  135. hDevInfo = SetupDiCreateDeviceInfoListEx(&ClassGuid,
  136. NULL,
  137. pMachine,
  138. NULL);
  139. if(hDevInfo == INVALID_HANDLE_VALUE) {
  140. Err = GetLastError();
  141. return HRESULT_FROM_SETUPAPI(Err);
  142. }
  143. CComObject<CDevices> *d;
  144. hr = CComObject<CDevices>::CreateInstance(&d);
  145. if(FAILED(hr)) {
  146. SetupDiDestroyDeviceInfoList(hDevInfo);
  147. return hr;
  148. }
  149. d->AddRef();
  150. hr = d->Init(hDevInfo,DeviceConsole);
  151. if(FAILED(hr)) {
  152. d->Release();
  153. return hr;
  154. }
  155. *pDevices = d;
  156. return S_OK;
  157. }
  158. STDMETHODIMP CSetupClass::get_Guid(BSTR *pVal)
  159. {
  160. LPOLESTR pStr;
  161. HRESULT hr = StringFromCLSID(ClassGuid,&pStr);
  162. if(FAILED(hr)) {
  163. return hr;
  164. }
  165. *pVal = SysAllocString(pStr);
  166. CoTaskMemFree(pStr);
  167. if(!*pVal) {
  168. return E_OUTOFMEMORY;
  169. }
  170. return S_OK;
  171. }
  172. GUID* CSetupClass::Guid()
  173. {
  174. return &ClassGuid;
  175. }
  176. STDMETHODIMP CSetupClass::get_Machine(BSTR *pVal)
  177. {
  178. if((pMachine == NULL) || !pMachine[0]) {
  179. *pVal = SysAllocString(L"");
  180. if(*pVal) {
  181. return S_FALSE;
  182. }
  183. } else {
  184. *pVal = SysAllocString(pMachine);
  185. if(*pVal) {
  186. return S_OK;
  187. }
  188. }
  189. *pVal = NULL;
  190. return E_OUTOFMEMORY;
  191. }
  192. STDMETHODIMP CSetupClass::get__ClassGuid(GUID *pVal)
  193. {
  194. *pVal = ClassGuid;
  195. return S_OK;
  196. }
  197. STDMETHODIMP CSetupClass::get__Machine(BSTR *pVal)
  198. {
  199. return get_Machine(pVal);
  200. return S_OK;
  201. }
  202. HRESULT CSetupClass::GetClassProperty(DWORD prop, VARIANT *pVal)
  203. {
  204. #if 0
  205. //
  206. // first obtain raw registry data
  207. //
  208. LPBYTE buffer = NULL;
  209. DWORD size = 1024;
  210. DWORD bufsize;
  211. DWORD reqSize;
  212. DWORD dataType;
  213. HRESULT hr;
  214. for(;;) {
  215. if(buffer) {
  216. delete [] buffer;
  217. }
  218. bufsize = size + sizeof(WCHAR)*2;
  219. buffer = new BYTE[bufsize];
  220. if(!buffer) {
  221. return E_OUTOFMEMORY;
  222. }
  223. if(SetupDiGetClassRegistryProperty(&ClassGuid,prop,&dataType,buffer,size,&reqSize,pMachine,NULL)) {
  224. break;
  225. }
  226. DWORD Err = GetLastError();
  227. if(Err != ERROR_INSUFFICIENT_BUFFER) {
  228. delete [] buffer;
  229. hr = HRESULT_FROM_SETUPAPI(Err);
  230. return hr;
  231. }
  232. }
  233. //
  234. // now determine how to parcel it to caller
  235. //
  236. switch(dataType) {
  237. case REG_DWORD: {
  238. //
  239. // package value as a long
  240. //
  241. if(size != sizeof(DWORD)) {
  242. hr = E_INVALIDARG;
  243. } else {
  244. VariantClear(pVal);
  245. V_VT(pVal) = VT_I4;
  246. V_I4(pVal) = (long)*((DWORD*)buffer);
  247. hr = S_OK;
  248. }
  249. }
  250. break;
  251. case REG_SZ: {
  252. //
  253. // package value as string
  254. //
  255. VariantClear(pVal);
  256. ZeroMemory(buffer+size,sizeof(WCHAR));
  257. BSTR pString = SysAllocString((LPWSTR)buffer);
  258. if(!pString) {
  259. hr = E_OUTOFMEMORY;
  260. } else {
  261. V_VT(pVal) = VT_BSTR;
  262. V_BSTR(pVal) = pString;
  263. hr = S_OK;
  264. }
  265. }
  266. break;
  267. case REG_MULTI_SZ: {
  268. //
  269. // package as string-list
  270. //
  271. VariantClear(pVal);
  272. ZeroMemory(buffer+size,sizeof(WCHAR)*2);
  273. CComObject<CStrings> *strings;
  274. hr = CComObject<CStrings>::CreateInstance(&strings);
  275. if(FAILED(hr)) {
  276. break;
  277. }
  278. strings->AddRef();
  279. LPWSTR p;
  280. UINT len = 0;
  281. for(p = (LPWSTR)buffer;*p;p+=len+1) {
  282. len = wcslen(p);
  283. hr = strings->InternalAdd(p,len);
  284. if(FAILED(hr)) {
  285. strings->Release();
  286. break;
  287. }
  288. }
  289. V_VT(pVal) = VT_DISPATCH;
  290. V_DISPATCH(pVal) = strings;
  291. hr = S_OK;
  292. }
  293. break;
  294. default:
  295. hr = E_INVALIDARG;
  296. break;
  297. }
  298. delete [] buffer;
  299. return hr;
  300. #endif
  301. return E_NOTIMPL;
  302. }
  303. HRESULT CSetupClass::PutClassPropertyString(DWORD prop, VARIANT *pVal)
  304. {
  305. #if 0
  306. HRESULT hr;
  307. DWORD len = 0;
  308. PBYTE data = NULL;
  309. CComVariant v;
  310. if(!IsBlank(pVal)) {
  311. hr = v.ChangeType(VT_BSTR,pVal);
  312. if(FAILED(hr)) {
  313. return hr;
  314. }
  315. len = (SysStringLen(V_BSTR(&v))+1)*sizeof(WCHAR);
  316. data = (PBYTE)V_BSTR(&v);
  317. }
  318. if(SetupDiSetClassRegistryProperty(&ClassGuid,
  319. prop,
  320. data,
  321. len,
  322. pMachine,
  323. NULL)) {
  324. return S_OK;
  325. }
  326. DWORD Err = GetLastError();
  327. return HRESULT_FROM_SETUPAPI(Err);
  328. #endif
  329. return E_NOTIMPL;
  330. }
  331. HRESULT CSetupClass::PutClassPropertyDword(DWORD prop, VARIANT *pVal)
  332. {
  333. #if 0
  334. CComVariant v;
  335. HRESULT hr;
  336. DWORD len = 0;
  337. PBYTE data = NULL;
  338. if(!IsBlank(pVal)) {
  339. hr = v.ChangeType(VT_I4,pVal);
  340. if(FAILED(hr)) {
  341. return hr;
  342. }
  343. len = sizeof(V_I4(&v));
  344. data = (PBYTE)&V_I4(&v);
  345. }
  346. if(SetupDiSetClassRegistryProperty(&ClassGuid,
  347. prop,
  348. data,
  349. len,
  350. pMachine,
  351. NULL)) {
  352. return S_OK;
  353. }
  354. DWORD Err = GetLastError();
  355. return HRESULT_FROM_SETUPAPI(Err);
  356. #endif
  357. return E_NOTIMPL;
  358. }
  359. HRESULT CSetupClass::PutClassPropertyMultiSz(DWORD prop, VARIANT *pVal)
  360. {
  361. #if 0
  362. //
  363. // build a CStrings collection
  364. //
  365. HRESULT hr;
  366. CComObject<CStrings> *strings = NULL;
  367. DWORD len = 0;
  368. PBYTE data = NULL;
  369. LPWSTR multisz;
  370. if(!IsBlank(pVal)) {
  371. hr = CComObject<CStrings>::CreateInstance(&strings);
  372. if(FAILED(hr)) {
  373. return hr;
  374. }
  375. strings->AddRef();
  376. hr = strings->Add(*pVal);
  377. if(FAILED(hr)) {
  378. strings->Release();
  379. return hr;
  380. }
  381. //
  382. // now obtain multisz from the collection
  383. //
  384. hr = strings->GetMultiSz(&multisz,&len);
  385. strings->Release(); // done with temporary collection
  386. if(FAILED(hr)) {
  387. return hr;
  388. }
  389. //
  390. // now write the multi-sz value to device registry
  391. //
  392. len *= sizeof(WCHAR);
  393. data = (PBYTE)multisz;
  394. }
  395. CONFIGRET cr = CM_Get_Class_Registry_Property(
  396. if(SetupDiSetClassRegistryProperty(&ClassGuid,
  397. prop,
  398. (PBYTE)multisz,
  399. len,
  400. pMachine,
  401. NULL)) {
  402. if(multisz) {
  403. delete [] multisz;
  404. }
  405. return S_OK;
  406. }
  407. DWORD Err = GetLastError();
  408. if(multisz) {
  409. delete [] multisz;
  410. }
  411. return HRESULT_FROM_SETUPAPI(Err);
  412. #endif
  413. return E_NOTIMPL;
  414. }
  415. STDMETHODIMP CSetupClass::get_Security(VARIANT *pVal)
  416. {
  417. return GetClassProperty(SPDRP_SECURITY_SDS,pVal);
  418. }
  419. STDMETHODIMP CSetupClass::put_Security(VARIANT newVal)
  420. {
  421. return PutClassPropertyString(SPDRP_SECURITY_SDS,&newVal);
  422. }
  423. STDMETHODIMP CSetupClass::get_DeviceTypeOverride(VARIANT *pVal)
  424. {
  425. return GetClassProperty(SPDRP_DEVTYPE,pVal);
  426. }
  427. STDMETHODIMP CSetupClass::put_DeviceTypeOverride(VARIANT newVal)
  428. {
  429. return PutClassPropertyDword(SPDRP_DEVTYPE,&newVal);
  430. }
  431. STDMETHODIMP CSetupClass::get_ForceExclusive(VARIANT *pVal)
  432. {
  433. return GetClassProperty(SPDRP_EXCLUSIVE,pVal);
  434. }
  435. STDMETHODIMP CSetupClass::put_ForceExclusive(VARIANT newVal)
  436. {
  437. return PutClassPropertyDword(SPDRP_EXCLUSIVE,&newVal);
  438. }
  439. STDMETHODIMP CSetupClass::get_CharacteristicsOverride(VARIANT *pVal)
  440. {
  441. return GetClassProperty(SPDRP_CHARACTERISTICS,pVal);
  442. }
  443. STDMETHODIMP CSetupClass::put_CharacteristicsOverride(VARIANT newVal)
  444. {
  445. return PutClassPropertyDword(SPDRP_CHARACTERISTICS,&newVal);
  446. }
  447. HRESULT CSetupClass::SubKeyInfo(LPCWSTR subkey, HKEY *hKey, LPWSTR *pSubKey,LPCWSTR *pKeyVal,BOOL writeable)
  448. {
  449. DWORD Scope = DICS_FLAG_GLOBAL;
  450. DWORD HwProfile = 0;
  451. HKEY hParentKey;
  452. LPWSTR keyname;
  453. LPCWSTR keyval;
  454. size_t len;
  455. hParentKey = SetupDiOpenClassRegKeyEx(&ClassGuid,
  456. writeable ? KEY_WRITE: KEY_READ,
  457. DIOCR_INSTALLER,
  458. pMachine,
  459. NULL
  460. );
  461. if((hParentKey == NULL) || (hParentKey == INVALID_HANDLE_VALUE)) {
  462. DWORD Err = GetLastError();
  463. return HRESULT_FROM_SETUPAPI(Err);
  464. }
  465. //
  466. // determine value part of key
  467. //
  468. keyval = wcsrchr(subkey,L'\\');
  469. if(!keyval) {
  470. *hKey = hParentKey;
  471. *pKeyVal = subkey[0] ? subkey : NULL;
  472. *pSubKey = NULL;
  473. return S_OK;
  474. }
  475. len = keyval-subkey+1;
  476. keyname = new WCHAR[len];
  477. if(!keyname) {
  478. RegCloseKey(hParentKey);
  479. return E_OUTOFMEMORY;
  480. }
  481. wcsncpy(keyname,subkey,len);
  482. keyname[len-1] = 0;
  483. keyval++;
  484. if(!keyval[0]) {
  485. keyval = NULL;
  486. }
  487. *hKey = hParentKey;
  488. *pSubKey = keyname;
  489. *pKeyVal = keyval;
  490. return S_OK;
  491. }
  492. STDMETHODIMP CSetupClass::RegRead(BSTR key,VARIANT * pValue)
  493. {
  494. HKEY hParentKey;
  495. HKEY hKey;
  496. LPCWSTR val;
  497. LPWSTR subkey;
  498. LONG regerr;
  499. DWORD regType;
  500. DWORD regSize;
  501. LPBYTE pByte;
  502. if(!pValue) {
  503. return E_INVALIDARG;
  504. }
  505. VariantInit(pValue);
  506. HRESULT hr = SubKeyInfo(key,&hParentKey,&subkey,&val,FALSE);
  507. if(FAILED(hr)) {
  508. return hr;
  509. }
  510. //
  511. // now work out and marshell data
  512. //
  513. if(subkey) {
  514. regerr = RegOpenKeyEx(hParentKey,subkey,0,KEY_READ,&hKey);
  515. delete [] subkey;
  516. RegCloseKey(hParentKey);
  517. if(regerr != NO_ERROR) {
  518. return HRESULT_FROM_SETUPAPI(regerr);
  519. }
  520. } else {
  521. hKey = hParentKey;
  522. }
  523. regSize = 0;
  524. regerr = RegQueryValueEx(hKey,val,NULL,&regType,NULL,&regSize);
  525. if(regerr != NO_ERROR) {
  526. RegCloseKey(hKey);
  527. return HRESULT_FROM_SETUPAPI(regerr);
  528. }
  529. pByte = new BYTE[regSize+sizeof(WCHAR)*2];
  530. if(!pByte) {
  531. RegCloseKey(hKey);
  532. return E_OUTOFMEMORY;
  533. }
  534. regerr = RegQueryValueEx(hKey,val,NULL,&regType,pByte,&regSize);
  535. RegCloseKey(hKey);
  536. if(regerr != NO_ERROR) {
  537. delete [] pByte;
  538. return HRESULT_FROM_SETUPAPI(regerr);
  539. }
  540. switch(regType) {
  541. case REG_DWORD:
  542. if(regSize != 4) {
  543. delete [] pByte;
  544. return DISP_E_TYPEMISMATCH;
  545. }
  546. V_VT(pValue) = VT_UI4;
  547. V_UI4(pValue) = *(DWORD*)pByte;
  548. break;
  549. case REG_BINARY:
  550. switch(regSize) {
  551. case 1:
  552. V_VT(pValue) = VT_UI1;
  553. V_UI1(pValue) = *((BYTE*)pByte);
  554. break;
  555. case 2:
  556. V_VT(pValue) = VT_UI2;
  557. V_UI2(pValue) = *((WORD*)pByte);
  558. break;
  559. case 4:
  560. V_VT(pValue) = VT_UI4;
  561. V_UI4(pValue) = *((DWORD*)pByte);
  562. break;
  563. default:
  564. delete [] pByte;
  565. return DISP_E_TYPEMISMATCH;
  566. }
  567. break;
  568. case REG_SZ:
  569. ZeroMemory(pByte+regSize,sizeof(WCHAR)*1);
  570. V_VT(pValue) = VT_BSTR;
  571. V_BSTR(pValue) = SysAllocString((LPWSTR)pByte);
  572. if(!V_BSTR(pValue)) {
  573. delete [] pByte;
  574. return E_OUTOFMEMORY;
  575. }
  576. break;
  577. case REG_MULTI_SZ: {
  578. ZeroMemory(pByte+regSize,sizeof(WCHAR)*2);
  579. CComObject<CStrings> *pStringTemp = NULL;
  580. hr = CComObject<CStrings>::CreateInstance(&pStringTemp);
  581. if(FAILED(hr)) {
  582. delete [] pByte;
  583. return hr;
  584. }
  585. pStringTemp->AddRef();
  586. hr = pStringTemp->FromMultiSz((LPWSTR)pByte);
  587. if(FAILED(hr)) {
  588. pStringTemp->Release();
  589. delete [] pByte;
  590. return hr;
  591. }
  592. V_VT(pValue) = VT_DISPATCH;
  593. V_DISPATCH(pValue) = pStringTemp;
  594. }
  595. break;
  596. case REG_EXPAND_SZ:
  597. ZeroMemory(pByte+regSize,sizeof(WCHAR)*1);
  598. regSize = ExpandEnvironmentStrings((LPWSTR)pByte,NULL,0);
  599. if(regSize == 0) {
  600. V_VT(pValue) = VT_BSTR;
  601. V_BSTR(pValue) = SysAllocString((LPWSTR)pByte);
  602. } else {
  603. LPWSTR pExp = new WCHAR[regSize+1];
  604. if(!pExp) {
  605. delete [] pByte;
  606. return E_OUTOFMEMORY;
  607. }
  608. regSize = ExpandEnvironmentStrings((LPWSTR)pByte,NULL,regSize);
  609. V_VT(pValue) = VT_BSTR;
  610. V_BSTR(pValue) = SysAllocString(pExp);
  611. delete [] pExp;
  612. }
  613. if(!V_BSTR(pValue)) {
  614. delete [] pByte;
  615. return E_OUTOFMEMORY;
  616. }
  617. break;
  618. default:
  619. delete [] pByte;
  620. return HRESULT_FROM_SETUPAPI(regerr);
  621. }
  622. delete [] pByte;
  623. return S_OK;
  624. }
  625. STDMETHODIMP CSetupClass::RegWrite(BSTR key, VARIANT val, VARIANT strType)
  626. {
  627. HKEY hParentKey;
  628. HKEY hKey;
  629. LPCWSTR valname;
  630. LPWSTR subkey;
  631. LONG regerr;
  632. CComVariant strType_v;
  633. CComVariant val_v;
  634. LPCWSTR pType;
  635. HRESULT hr;
  636. DWORD dwType;
  637. BOOL DetermineType = FALSE;
  638. LPBYTE pData = NULL;
  639. LPWSTR pString = NULL;
  640. DWORD DataSize = 0;
  641. BYTE SimpleData[4];
  642. LPVARIANT pVal = &val;
  643. while(V_VT(pVal) == (VT_BYREF|VT_VARIANT)) {
  644. pVal = V_VARIANTREF(pVal);
  645. }
  646. //
  647. // validate strType
  648. //
  649. hr = GetOptionalString(&strType,strType_v,&pType);
  650. if(FAILED(hr)) {
  651. return hr;
  652. }
  653. if((pType == NULL) || !pType[0]) {
  654. //
  655. // determine type of variant
  656. //
  657. if(IsNumericVariant(pVal)) {
  658. dwType = REG_DWORD;
  659. } else if(IsMultiValueVariant(pVal)) {
  660. dwType = REG_MULTI_SZ;
  661. } else {
  662. dwType = REG_SZ;
  663. }
  664. } else if(_wcsicmp(pType,L"REG_DWORD")==0) {
  665. dwType = REG_DWORD;
  666. } else if(_wcsicmp(pType,L"REG_SZ")==0) {
  667. dwType = REG_SZ;
  668. } else if(_wcsicmp(pType,L"REG_EXPAND_SZ")==0) {
  669. dwType = REG_EXPAND_SZ;
  670. } else if(_wcsicmp(pType,L"REG_MULTI_SZ")==0) {
  671. dwType = REG_MULTI_SZ;
  672. } else if(_wcsicmp(pType,L"REG_BINARY")==0) {
  673. dwType = REG_BINARY;
  674. } else {
  675. return DISP_E_TYPEMISMATCH;
  676. }
  677. //
  678. // build up value data
  679. //
  680. switch(dwType) {
  681. case REG_BINARY:
  682. pData = SimpleData;
  683. switch V_VT(pVal) {
  684. case VT_I1:
  685. case VT_UI1:
  686. *(LPBYTE)pData = V_UI1(pVal);
  687. DataSize = 1;
  688. break;
  689. case VT_I1|VT_BYREF:
  690. case VT_UI1|VT_BYREF:
  691. *(LPBYTE)pData = *V_UI1REF(pVal);
  692. DataSize = 1;
  693. break;
  694. case VT_I2:
  695. case VT_UI2:
  696. *(LPWORD)pData = V_UI2(pVal);
  697. DataSize = 2;
  698. break;
  699. case VT_I2|VT_BYREF:
  700. case VT_UI2|VT_BYREF:
  701. *(LPWORD)pData = *V_UI2REF(pVal);
  702. DataSize = 2;
  703. break;
  704. case VT_I4:
  705. case VT_UI4:
  706. *(LPDWORD)pData = V_UI4(pVal);
  707. DataSize = 4;
  708. break;
  709. case VT_I4|VT_BYREF:
  710. case VT_UI4|VT_BYREF:
  711. *(LPDWORD)pData = *V_UI4REF(pVal);
  712. DataSize = 4;
  713. break;
  714. default:
  715. return DISP_E_TYPEMISMATCH;
  716. }
  717. break;
  718. case REG_DWORD:
  719. pData = SimpleData;
  720. hr = val_v.ChangeType(VT_UI4,pVal);
  721. if(FAILED(hr)) {
  722. return DISP_E_TYPEMISMATCH;
  723. }
  724. *(LPDWORD)pData = V_UI4(pVal);
  725. DataSize = 4;
  726. break;
  727. case REG_SZ:
  728. case REG_EXPAND_SZ:
  729. hr = val_v.ChangeType(VT_BSTR,pVal);
  730. if(FAILED(hr)) {
  731. return DISP_E_TYPEMISMATCH;
  732. }
  733. DataSize = (SysStringLen(V_BSTR(&val_v))+1);
  734. pString = new WCHAR[DataSize];
  735. if(!pString) {
  736. return E_OUTOFMEMORY;
  737. }
  738. pData = (LPBYTE)pString;
  739. DataSize *= sizeof(WCHAR);
  740. memcpy(pData,V_BSTR(&val_v),DataSize);
  741. break;
  742. case REG_MULTI_SZ: {
  743. CComObject<CStrings> *pStringTemp = NULL;
  744. hr = CComObject<CStrings>::CreateInstance(&pStringTemp);
  745. if(FAILED(hr)) {
  746. return hr;
  747. }
  748. pStringTemp->AddRef();
  749. hr = pStringTemp->InternalInsert(0,pVal);
  750. if(FAILED(hr)) {
  751. pStringTemp->Release();
  752. return hr;
  753. }
  754. hr = pStringTemp->GetMultiSz(&pString,&DataSize);
  755. pStringTemp->Release();
  756. if(FAILED(hr)) {
  757. return hr;
  758. }
  759. pData = (LPBYTE)pString;
  760. DataSize *= sizeof(WCHAR);
  761. }
  762. break;
  763. default:
  764. return DISP_E_TYPEMISMATCH;
  765. }
  766. hr = SubKeyInfo(key,&hParentKey,&subkey,&valname,TRUE);
  767. if(FAILED(hr)) {
  768. if(pString) {
  769. delete [] pString;
  770. }
  771. return hr;
  772. }
  773. if(subkey) {
  774. regerr = RegCreateKeyEx(hParentKey,subkey,0,NULL,0,KEY_WRITE,NULL,&hKey,NULL);
  775. delete [] subkey;
  776. RegCloseKey(hParentKey);
  777. if(regerr != NO_ERROR) {
  778. if(pString) {
  779. delete [] pString;
  780. }
  781. return HRESULT_FROM_SETUPAPI(regerr);
  782. }
  783. } else {
  784. hKey = hParentKey;
  785. }
  786. regerr = RegSetValueEx(hKey,valname,0,dwType,pData,DataSize);
  787. if(pString) {
  788. delete [] pString;
  789. }
  790. RegCloseKey(hKey);
  791. if(regerr != NO_ERROR) {
  792. return HRESULT_FROM_SETUPAPI(regerr);
  793. }
  794. return S_OK;
  795. }
  796. STDMETHODIMP CSetupClass::RegDelete(BSTR key)
  797. {
  798. HKEY hParentKey;
  799. HKEY hKey;
  800. LPCWSTR valname;
  801. LPWSTR subkey;
  802. LONG regerr;
  803. HRESULT hr = SubKeyInfo(key,&hParentKey,&subkey,&valname,TRUE);
  804. if(FAILED(hr)) {
  805. return hr;
  806. }
  807. if(subkey) {
  808. regerr = RegOpenKeyEx(hParentKey,subkey,0,KEY_WRITE,&hKey);
  809. delete [] subkey;
  810. RegCloseKey(hParentKey);
  811. if(regerr != NO_ERROR) {
  812. return HRESULT_FROM_SETUPAPI(regerr);
  813. }
  814. } else {
  815. hKey = hParentKey;
  816. }
  817. regerr = RegDeleteValue(hKey,valname);
  818. RegCloseKey(hKey);
  819. if(regerr != NO_ERROR) {
  820. return HRESULT_FROM_SETUPAPI(regerr);
  821. }
  822. return S_OK;
  823. }