PageRenderTime 33ms CodeModel.GetById 5ms RepoModel.GetById 0ms app.codeStats 0ms

/doc/notes_on_COM_gu.cpp

http://r2clr.codeplex.com
C++ | 775 lines | 537 code | 165 blank | 73 comment | 62 complexity | cf17dc545a22f73c1b3f554ca28ecad4 MD5 | raw file
  1. #define _WIN32_DCOM
  2. #include <stdio.h>
  3. #include <wtypes.h>
  4. #import "path\\mscorlib.tlb" no_namespace named_guids raw_interfaces_only
  5. HRESULT InvokeStaticMember(BSTR typeName, BSTR memberName,
  6. BindingFlags memberType, SAFEARRAY* parameters, VARIANT* retVal)
  7. {
  8. HRESULT hresult;
  9. IUnknown* pUnk = NULL;
  10. _Object* pObj = NULL;
  11. _Type* pType = NULL;
  12. _Type* pTypeOfType = NULL;
  13. _Type* pDesiredType = NULL;
  14. VARIANT typeNameParam;
  15. VARIANT getTypeRetVal;
  16. VARIANT nullObject;
  17. SAFEARRAY* psa;
  18. LONG index;
  19. BSTR getTypeName = SysAllocString(L"GetType");
  20. VariantInit(&typeNameParam);
  21. VariantInit(&getTypeRetVal);
  22. VariantInit(&nullObject);
  23. // Instantiate a dummy class just so we can get a System.Type instance
  24. hresult = CoCreateInstance(CLSID_Object, NULL,
  25. CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnk);
  26. if (FAILED(hresult)) goto cleanup;
  27. // Get the _Object interface so we can call GetType
  28. hresult = pUnk->QueryInterface(IID__Object, (void**)&pObj);
  29. if (FAILED(hresult)) goto cleanup;
  30. // Call _Object.GetType
  31. hresult = pObj->GetType(&pType);
  32. if (FAILED(hresult)) goto cleanup;
  33. // Call the instance Type.GetType method (inherited from Object)
  34. // in order to get the type for System.Type rather than the type for
  35. // System.Object
  36. hresult = pType->GetType(&pTypeOfType);
  37. if (FAILED(hresult)) goto cleanup;
  38. // Prepare a 1-element array containing the passed-in type name
  39. // to pass to the static Type.GetType method
  40. psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
  41. typeNameParam.vt = VT_BSTR;
  42. typeNameParam.bstrVal = typeName;
  43. index = 0;
  44. hresult = SafeArrayPutElement(psa, &index, &typeNameParam);
  45. if (FAILED(hresult)) goto cleanup;
  46. // Invoke the static Type.GetType method using reflection on the
  47. // type for System.Type in order to get the desired type
  48. nullObject.vt = VT_EMPTY;
  49. hresult = pTypeOfType->InvokeMember_3(getTypeName,
  50. (BindingFlags)(BindingFlags_InvokeMethod | BindingFlags_Public |
  51. BindingFlags_Static | BindingFlags_FlattenHierarchy), NULL,
  52. nullObject, psa, &getTypeRetVal);
  53. if (FAILED(hresult)) goto cleanup;
  54. // Get the _Type interface so we can call the static InvokeMember
  55. // method on the desired type to invoke the desired static member
  56. hresult = getTypeRetVal.punkVal->QueryInterface(IID__Type,
  57. (void**)&pDesiredType);
  58. if (FAILED(hresult)) goto cleanup;
  59. // Invoke the desired static member
  60. pDesiredType->InvokeMember_3(memberName, (BindingFlags)(memberType |
  61. BindingFlags_Public | BindingFlags_Static |
  62. BindingFlags_FlattenHierarchy), NULL, nullObject, parameters,
  63. retVal);
  64. if (FAILED(hresult)) goto cleanup;
  65. cleanup:
  66. if (pUnk) pUnk->Release();
  67. if (pObj) pObj->Release();
  68. if (pType) pType->Release();
  69. if (pTypeOfType) pTypeOfType->Release();
  70. if (pDesiredType) pDesiredType->Release();
  71. if (getTypeName) SysFreeString(getTypeName);
  72. SafeArrayDestroy(psa);
  73. VariantClear(&typeNameParam);
  74. VariantClear(&getTypeRetVal);
  75. VariantClear(&nullObject);
  76. return hresult;
  77. };
  78. int main(int argc, char* argv[])
  79. {
  80. HRESULT hresult;
  81. VARIANT retVal;
  82. _AppDomain* pDomain = NULL;
  83. BSTR typeName1, typeName2, memberName1, memberName2, directory;
  84. // Initialize COM
  85. hresult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  86. if (FAILED(hresult))
  87. {
  88. printf("ERROR: Cannot initialize COM: 0x%x\n", hresult);
  89. return -1;
  90. }
  91. VariantInit(&retVal);
  92. // ------------------------------------------
  93. // Example 1: Calling System.Console.ReadLine
  94. // ------------------------------------------
  95. typeName1 = SysAllocString(L"System.Console");
  96. memberName1 = SysAllocString(L"ReadLine");
  97. printf("Type in something followed by Enter: ");
  98. hresult = InvokeStaticMember(typeName1, memberName1,
  99. BindingFlags_InvokeMethod, NULL, &retVal);
  100. if (FAILED(hresult))
  101. {
  102. printf("ERROR: Invocation failed: 0x%x\n", hresult);
  103. return -1;
  104. }
  105. wprintf(L"You typed: '%s'\n", retVal.bstrVal);
  106. // --------------------------------------------------
  107. // Example 2: Calling System.AppDomain.CurrentDomain
  108. // --------------------------------------------------
  109. typeName2 = SysAllocString(L"System.AppDomain");
  110. memberName2 = SysAllocString(L"CurrentDomain");
  111. hresult = InvokeStaticMember(typeName2, memberName2,
  112. BindingFlags_GetProperty, NULL, &retVal);
  113. if (FAILED(hresult))
  114. {
  115. printf("ERROR: Invocation failed: 0x%x\n", hresult);
  116. return -1;
  117. }
  118. // Get the _AppDomain interface from the returned IUnknown pointer
  119. hresult = retVal.punkVal->QueryInterface(IID__AppDomain,
  120. (void**)&pDomain);
  121. if (FAILED(hresult))
  122. {
  123. printf("ERROR: Could not get _AppDomain interface pointer: 0x%x\n",
  124. hresult);
  125. return -1;
  126. }
  127. // Call the BaseDirectory property on the _AppDomain instance
  128. pDomain->get_BaseDirectory(&directory);
  129. wprintf(L"Base directory of the current domain: '%s'\n", directory);
  130. CoUninitialize();
  131. return 0;
  132. };
  133. #define _WIN32_DCOM
  134. #include <stdio.h>
  135. #include <wtypes.h>
  136. // Reference the two necessary type libraries
  137. #import "path\\mscoree.tlb" no_namespace named_guids raw_interfaces_only
  138. #import "path\\mscorlib.tlb" no_namespace named_guids raw_interfaces_only
  139. IUnknown* pUnk = NULL;
  140. IUnknown* pUnk2 = NULL;
  141. ICorRuntimeHost* pHost = NULL;
  142. _AppDomain* pDomain = NULL;
  143. _ObjectHandle* pHandle = NULL;
  144. IDispatch* pDisp = NULL;
  145. BSTR asmName;
  146. BSTR typeName;
  147. VARIANT arrayList;
  148. VARIANT param;
  149. void Cleanup()
  150. {
  151. pHost->Stop();
  152. if (pUnk) pUnk->Release();
  153. if (pUnk2) pUnk2->Release();
  154. if (pDisp) pDisp->Release();
  155. if (pHandle) pHandle->Release();
  156. if (pDomain) pDomain->Release();
  157. if (pHost) pHost->Release();
  158. if (asmName) SysFreeString(asmName);
  159. if (typeName) SysFreeString(typeName);
  160. VariantClear(&param);
  161. VariantClear(&arrayList);
  162. CoUninitialize();
  163. };
  164. int main(int argc, char* argv[])
  165. {
  166. HRESULT hresult;
  167. // Initialize COM
  168. hresult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  169. if (FAILED(hresult))
  170. {
  171. printf("ERROR: Cannot initialize COM: 0x%x\n", hresult);
  172. Cleanup();
  173. return -1;
  174. }
  175. // Initialize the CLR
  176. hresult = CoCreateInstance(CLSID_CorRuntimeHost, NULL,
  177. CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnk);
  178. if (FAILED(hresult))
  179. {
  180. printf("ERROR: Cannot create host object: 0x%x\n", hresult);
  181. Cleanup();
  182. return -1;
  183. }
  184. // Get the ICorRuntimeHost interface
  185. hresult = pUnk->QueryInterface(IID_ICorRuntimeHost, (void**)&pHost);
  186. if (FAILED(hresult))
  187. {
  188. printf("ERROR: Cannot get ICorRuntimeHost interface pointer: 0x%x\n",
  189. hresult);
  190. Cleanup();
  191. return -1;
  192. }
  193. // Start the host
  194. hresult = pHost->Start();
  195. if (FAILED(hresult))
  196. {
  197. printf("ERROR: Cannot start host: 0x%x\n", hresult);
  198. Cleanup();
  199. return -1;
  200. }
  201. // Get the default domain
  202. hresult = pHost->GetDefaultDomain(&pUnk2);
  203. if (FAILED(hresult))
  204. {
  205. printf("ERROR: Cannot get default domain: 0x%x\n", hresult);
  206. Cleanup();
  207. return -1;
  208. }
  209. // Get the _AppDomain interface
  210. hresult = pUnk2->QueryInterface(IID__AppDomain, (void**)&pDomain);
  211. if (FAILED(hresult))
  212. {
  213. printf("ERROR: Cannot get _AppDomain interface pointer: 0x%x\n",
  214. hresult);
  215. Cleanup();
  216. return -1;
  217. }
  218. // Strings for CreateInstance_3
  219. asmName = SysAllocString(L"mscorlib");
  220. typeName = SysAllocString(L"System.Collections.ArrayList");
  221. // Create a 1D array with one integer element
  222. SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
  223. VariantInit(&param);
  224. param.vt = VT_I4;
  225. param.lVal = 128;
  226. LONG index = 0;
  227. hresult = SafeArrayPutElement(psa, &index, &param);
  228. if (FAILED(hresult))
  229. {
  230. printf("ERROR: Cannot set SAFEARRAY element: 0x%x\n", hresult);
  231. Cleanup();
  232. return -1;
  233. }
  234. // Create an instance of ArrayList using a parameterized constructor
  235. hresult = pDomain->CreateInstance_3(asmName, typeName, VARIANT_TRUE,
  236. BindingFlags_Default, NULL, psa, NULL, NULL, NULL, &pHandle);
  237. if (FAILED(hresult))
  238. {
  239. printf("ERROR: Cannot create instance: 0x%x\n", hresult);
  240. Cleanup();
  241. return -1;
  242. }
  243. // Unwrap the ArrayList instance inside the ObjectHandle
  244. VariantInit(&arrayList);
  245. hresult = pHandle->Unwrap(&arrayList);
  246. if (FAILED(hresult))
  247. {
  248. printf("ERROR: Could not unwrap object handle: 0x%x\n", hresult);
  249. Cleanup();
  250. return -1;
  251. }
  252. // Get the IDispatch interface so we can call the Capacity property
  253. hresult = arrayList.punkVal->QueryInterface(IID_IDispatch,
  254. (void**)&pDisp);
  255. if (FAILED(hresult))
  256. {
  257. printf("ERROR: Could not get IDispatch interface pointer: 0x%x\n",
  258. hresult);
  259. Cleanup();
  260. return -1;
  261. }
  262. // Get the DISPID for the Capacity property
  263. OLECHAR* name = L"Capacity";
  264. DISPID dispid;
  265. hresult = pDisp->GetIDsOfNames(IID_NULL, &name, 1, GetUserDefaultLCID(),
  266. &dispid);
  267. if (FAILED(hresult))
  268. {
  269. printf("ERROR: GetIDsOfNames failed: 0x%x\n", hresult);
  270. Cleanup();
  271. return -1;
  272. }
  273. // Invoke the Capacity property
  274. VARIANT result;
  275. VariantInit(&result);
  276. DISPPARAMS params = { NULL, NULL, 0, 0 };
  277. hresult = pDisp->Invoke(dispid, IID_NULL, GetUserDefaultLCID(),
  278. DISPATCH_PROPERTYGET, &params, &result, NULL, NULL);
  279. if (FAILED(hresult))
  280. {
  281. printf("ERROR: Invoke failed: 0x%x\n", hresult);
  282. Cleanup();
  283. return -1;
  284. }
  285. printf("ArrayList Capacity: %d\n", result.lVal);
  286. Cleanup();
  287. return 0;
  288. };
  289. // http://social.msdn.microsoft.com/Forums/vstudio/en-US/ce105a9b-837d-4384-ac03-287b45c1ecc9/marshalling-safearray-of-user-defined-struct
  290. __declspec(dllexport) SAFEARRAY * music_library_get_songs()
  291. {
  292. USES_CONVERSION;
  293. HRESULT hr = S_OK;
  294. // safe array dim
  295. SAFEARRAYBOUND safeArrayDim[1];
  296. safeArrayDim[0].lLbound = 0;
  297. safeArrayDim[0].cElements = 5;
  298. // create safe array
  299. SAFEARRAY * pSafeArray = SafeArrayCreate(VT_VARIANT,1,safeArrayDim);
  300. // fill safe array with data
  301. if(pSafeArray != NULL) {
  302. unsigned int i;
  303. long index;
  304. pSafeArray->pvData = malloc(5*sizeof(t_song));
  305. for(i = safeArrayDim[0].lLbound; i < safeArrayDim[0].cElements + safeArrayDim[0].lLbound; i++) {
  306. VARIANT vOut;
  307. VariantInit(&vOut);
  308. t_song * song = (t_song*)malloc(sizeof(t_song));
  309. song->album = "album";
  310. song->artist = "artist";
  311. song->name = "name";
  312. /* i don't know how to connect the song structure with the VARIANT
  313. */
  314. hr = SafeArrayPutElement(pSafeArray, &index, &vOut);
  315. VariantClear(&vOut);
  316. }
  317. }
  318. return pSafeArray;
  319. }
  320. managed c# code
  321. // structure marshaling
  322. [StructLayout(LayoutKind.Sequential)]
  323. public class Song
  324. {
  325. [MarshalAs(UnmanagedType.LPTStr)]
  326. public string name;
  327. [MarshalAs(UnmanagedType.LPStr)]
  328. public string album;
  329. [MarshalAs(UnmanagedType.LPStr)]
  330. public string artist;
  331. }
  332. [DllImport(MyLibrary.dll)]
  333. [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_VARIANT)]
  334. USES_CONVERSION; // enables use of ATL conversion macro A2W
  335. char buffer[20]; // used to store ANSI string
  336. HRESULT hr= S_OK;
  337. // Create SafeArray of VARIANT BSTRs
  338. SAFEARRAY *pSA;
  339. SAFEARRAYBOUND aDim[1]; // a one dimensional array
  340. aDim[0].lLbound= 0; // Visual Basic arrays start with index 0
  341. aDim[0].cElements= 10;
  342. pSA= SafeArrayCreate(VT_VARIANT,1,aDim); // create a 1D SafeArray of VARIANTS
  343. if (pSA != NULL) {
  344. long aLong[1];
  345. // iterate over array adding VARIANTs of type VT_BSTR
  346. for (long l= aDim[0].lLbound; l< (aDim[0].cElements + aDim[0].lLbound); l++) {
  347. VARIANT vOut;
  348. VariantInit(&vOut);
  349. vOut.vt= VT_BSTR; // set type
  350. ltoa(l,buffer,10); // convert long to ANSI string value
  351. vOut.bstrVal= ::SysAllocString(A2W(buffer)); // system wide "new"
  352. aLong[0]= l; // set index value
  353. if (hr= SafeArrayPutElement(pSA, aLong, &vOut)) { // "correctly" copies VARIANT
  354. VariantClear(&vOut); // release BSTR from memory on error
  355. SafeArrayDestroy(pSA); // does a deep destroy on error
  356. return hr;
  357. }
  358. VariantClear(&vOut); // does a deep destroy of source VARIANT
  359. } // end iteration
  360. }
  361. // clean up here only if you do not return SafeArray as an [out, retval]
  362. SafeArrayDestroy(pSA); // again does a deep destroy
  363. // Learning DCOM book on Safary
  364. void CallOcrImage(IOcr *pIOcr, BYTE *pImage, ULONG len)
  365. {
  366. // Create a one-dimensional SAFEARRAY of BYTEs (VT_UI)
  367. // The size of this array is len, which represents our image length.
  368. SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
  369. // Access the data pointer
  370. unsigned char *pc = NULL;
  371. SafeArrayAccessData(psa, reinterpret_cast<void HUGEP**>(&pc));
  372. // Copy our binary image data into array
  373. memcpy(pc, pImage, len);
  374. // Done accessing, so unaccess now.
  375. SafeArrayUnaccessData(psa);
  376. // Now we've got the array, we need to store it in
  377. // a VARIANT (the value holder).
  378. VARIANT vImage; // So, let's create a variant
  379. VariantInit(&vImage); // Initialize the variant
  380. // Tell the value holder it's holding a SAFEARRAY of bytes
  381. binaryImageArray.vt = (VT_ARRAY|VT_UI1) ;
  382. binaryImageArray.parray = psa; // Let the variant hold the array
  383. // Yes! That much set up work before we can invoke a method!
  384. // Now for the method invocation...
  385. BSTR pOcrText ; // Where the OCR text will be stored
  386. HRESULT hr = pIOcr->OcrImage(vImage, &pOcrText);
  387. if (SUCCEEDED(hr)) {
  388. m_strOCRResults = pOcrText ;
  389. SysFreeString(pOcrText) ;
  390. }
  391. SafeArrayDestroyData(psa); // Destroy the data within the SAFEARRAY
  392. SafeArrayDestroy(psa); // Destroy the SAFEARRAY
  393. // Clear the data
  394. VariantClear(&binaryImageArray);
  395. }
  396. void CVcpphostclrDlg::OnTestmanagedclassButton()
  397. HRESULT hRes;
  398. ICorRuntimeHost *pRuntimeHost;
  399. IUnknown *pUnkAppDomain;
  400. _AppDomain *pAppDomain;
  401. _ObjectHandle *pHandle;
  402. OLECHAR *methodName=L"GetSalary";
  403. VARIANT vntResult;
  404. float fltVal;
  405. DISPID dispid;
  406. EXCEPINFO errorInfo;
  407. UINT intArg;
  408. DISPPARAMS param;
  409. BSTR bstrTypeName, bstrAssemblyName;
  410. SAFEARRAY *paramArray;
  411. VARIANT paramID, paramName;
  412. VARIANT paramSalary, paramBonus;
  413. LONG index;
  414. hRes=CoInitializeEx(NULL,COINIT_MULTITHREADED);
  415. if (FAILED(hRes))
  416. AfxMessageBox("Could not initialize COM");
  417. hRes=CoCreateInstance(CLSID_CorRuntimeHost,
  418. NULL,CLSCTX_INPROC_SERVER,
  419. IID_ICorRuntimeHost,
  420. (void **)&pRuntimeHost);
  421. if (FAILED(hRes))
  422. AfxMessageBox("Could not create host");
  423. hRes=pRuntimeHost->Start();
  424. hRes=pRuntimeHost->GetDefaultDomain(
  425. &pUnkAppDomain);
  426. if (FAILED(hRes))
  427. AfxMessageBox("Could not get Appdomain");
  428. hRes=pUnkAppDomain->QueryInterface(
  429. IID__AppDomain,(void **)&pAppDomain);
  430. if (FAILED(hRes))
  431. AfxMessageBox("Failed to get domain");
  432. if (pUnkAppDomain!=NULL)
  433. pUnkAppDomain->Release();
  434. bstrTypeName=SysAllocString(
  435. L"AssemblyDemo.Manager");
  436. bstrAssemblyName=SysAllocString(
  437. L"multifile3,Version=2.0.0.0,Culture=neutral,
  438. PublicKeyToken=8a707be49fd7d8f4");
  439. paramArray=SafeArrayCreateVector(VT_VARIANT,0,4);
  440. VariantInit(&paramID);
  441. paramID.vt=VT_I4;
  442. paramID.lVal=45;
  443. index=0;
  444. hRes=SafeArrayPutElement(paramArray,
  445. &index,&paramID);
  446. VariantInit(&paramName);
  447. paramName.vt=VT_BSTR;
  448. paramName.bstrVal=SysAllocString(L"Alan Gordon");
  449. index=1;
  450. hRes=SafeArrayPutElement(paramArray,
  451. &index,&paramName);
  452. VariantInit(&paramSalary);
  453. paramSalary.vt=VT_R4;
  454. paramSalary.fltVal=1000.0;
  455. VariantChangeType(&paramSalary,&paramSalary,
  456. 0,VT_DECIMAL);
  457. index=2;
  458. hRes=SafeArrayPutElement(paramArray,
  459. &index,&paramSalary);
  460. VariantInit(&paramBonus);
  461. paramBonus.vt=VT_R4;
  462. paramBonus.fltVal=100.0;
  463. VariantChangeType(&paramBonus,&paramBonus,
  464. 0,VT_DECIMAL);
  465. index=3;
  466. hRes=SafeArrayPutElement(paramArray,
  467. &index,&paramBonus);
  468. hRes=pAppDomain->CreateInstance_3(
  469. bstrAssemblyName,bstrTypeName,VARIANT_TRUE,
  470. BindingFlags_Default,NULL,paramArray,
  471. NULL,NULL,NULL,&pHandle);
  472. if (FAILED(hRes))
  473. AfxMessageBox("Could not create object");
  474. VARIANT vntObject;
  475. IDispatch *pObject;
  476. VariantInit(&vntObject);
  477. pHandle->Unwrap(&vntObject);
  478. vntObject.punkVal->QueryInterface(IID_IDispatch,
  479. (void **)&pObject);
  480. if (vntObject.punkVal!=NULL)
  481. vntObject.punkVal->Release();
  482. param.cArgs=0;
  483. param.rgvarg=NULL;
  484. param.cNamedArgs=0;
  485. param.rgdispidNamedArgs=NULL;
  486. VariantInit(&vntResult);
  487. hRes=pObject->GetIDsOfNames(IID_NULL,
  488. &methodName,1,GetUserDefaultLCID(),&dispid);
  489. hRes=pObject->Invoke(dispid,IID_NULL,
  490. GetUserDefaultLCID(),
  491. DISPATCH_METHOD,&param,&vntResult,
  492. &errorInfo,&intArg);
  493. if (SUCCEEDED(hRes))
  494. {
  495. vntResult.decVal;
  496. VarR4FromDec(&vntResult.decVal,&fltVal);
  497. }
  498. else
  499. {
  500. // Handle the error, code omitted...
  501. }
  502. if (pObject!=NULL)
  503. pObject->Release();
  504. if (pAppDomain!=NULL)
  505. pAppDomain->Release();
  506. SysFreeString(bstrTypeName);
  507. SysFreeString(bstrAssemblyName);
  508. SafeArrayDestroy(paramArray);
  509. }
  510. // _bstr_t_Assign.cpp
  511. #include <comdef.h>
  512. #include <stdio.h>
  513. int main()
  514. {
  515. // creates a _bstr_t wrapper
  516. _bstr_t bstrWrapper;
  517. // creates BSTR and attaches to it
  518. bstrWrapper = "some text";
  519. wprintf_s(L"bstrWrapper = %s\n",
  520. static_cast<wchar_t*>(bstrWrapper));
  521. // bstrWrapper releases its BSTR
  522. BSTR bstr = bstrWrapper.Detach();
  523. wprintf_s(L"bstrWrapper = %s\n",
  524. static_cast<wchar_t*>(bstrWrapper));
  525. // "some text"
  526. wprintf_s(L"bstr = %s\n", bstr);
  527. bstrWrapper.Attach(SysAllocString(OLESTR("SysAllocedString")));
  528. wprintf_s(L"bstrWrapper = %s\n",
  529. static_cast<wchar_t*>(bstrWrapper));
  530. // assign a BSTR to our _bstr_t
  531. bstrWrapper.Assign(bstr);
  532. wprintf_s(L"bstrWrapper = %s\n",
  533. static_cast<wchar_t*>(bstrWrapper));
  534. // done with BSTR, do manual cleanup
  535. SysFreeString(bstr);
  536. // resuse bstr
  537. bstr= SysAllocString(OLESTR("Yet another string"));
  538. // two wrappers, one BSTR
  539. _bstr_t bstrWrapper2 = bstrWrapper;
  540. *bstrWrapper.GetAddress() = bstr;
  541. // bstrWrapper and bstrWrapper2 do still point to BSTR
  542. bstr = 0;
  543. wprintf_s(L"bstrWrapper = %s\n",
  544. static_cast<wchar_t*>(bstrWrapper));
  545. wprintf_s(L"bstrWrapper2 = %s\n",
  546. static_cast<wchar_t*>(bstrWrapper2));
  547. // new value into BSTR
  548. _snwprintf_s(bstrWrapper.GetBSTR(), 100, bstrWrapper.length(),
  549. L"changing BSTR");
  550. wprintf_s(L"bstrWrapper = %s\n",
  551. static_cast<wchar_t*>(bstrWrapper));
  552. wprintf_s(L"bstrWrapper2 = %s\n",
  553. static_cast<wchar_t*>(bstrWrapper2));
  554. }
  555. HRESULT PASCAL __export CPoly::EnumPoints(IEnumVARIANT FAR* FAR* ppenum)
  556. {
  557. unsigned int i;
  558. HRESULT hresult;
  559. VARIANT var;
  560. SAFEARRAY FAR* psa;
  561. CEnumPoint FAR* penum;
  562. POINTLINK FAR* ppointlink;
  563. SAFEARRAYBOUND rgsabound[1];
  564. rgsabound[0].lLbound = 0;
  565. rgsabound[0].cElements = m_cPoints;
  566. psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
  567. if(psa == NULL){
  568. HRESULT = ResultFromScode(E_OUTOFMEMORY);
  569. goto LError0;
  570. }
  571. // Code omitted here for brevity.
  572. V_VT(&var) = VT_DISPATCH;
  573. HRESULT = ppointlink->ppoint->QueryInterface(
  574. IID_IDispatch, (void FAR* FAR*)&V_DISPATCH(&var));
  575. if(HRESULT != NOERROR)
  576. goto LError1;
  577. ix[0] = i;
  578. SafeArrayPutElement(psa, ix, &var);
  579. ppointlink = ppointlink->next;
  580. }
  581. HRESULT = CEnumPoint::Create(psa, &penum);
  582. if(HRESULT != NOERROR)
  583. goto LError1;
  584. *ppenum = penum;
  585. return NOERROR;
  586. LError1:;
  587. SafeArrayDestroy(psa);
  588. LError0:;
  589. return hresult;
  590. }
  591. // http://social.msdn.microsoft.com/Forums/vstudio/en-US/cdc68fd4-08d5-4bfd-8dd7-6c095bd619a6/any-easy-way-to-create-a-safearray
  592. void AlternativeSetSafeArrayData(/*[in]*/ SAFEARRAY* psaStrings)
  593. {
  594. BSTR bstr = ::SysAllocString(OLESTR("Another BSTR."));
  595. VARIANT var;
  596. long lIndexVector[1];
  597. lIndexVector[0] = 0;
  598. VariantInit(&var);
  599. VariantClear(&var);
  600. V_VT(&var) = VT_BSTR;
  601. V_BSTR(&var) = bstr;
  602. SafeArrayPutElement
  603. (
  604. psaStrings,
  605. (long*)lIndexVector,
  606. (void*)&var
  607. );
  608. VariantClear(&var);
  609. }