/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
- #define _WIN32_DCOM
- #include <stdio.h>
- #include <wtypes.h>
-
- #import "path\\mscorlib.tlb" no_namespace named_guids raw_interfaces_only
-
- HRESULT InvokeStaticMember(BSTR typeName, BSTR memberName,
- BindingFlags memberType, SAFEARRAY* parameters, VARIANT* retVal)
- {
- HRESULT hresult;
- IUnknown* pUnk = NULL;
- _Object* pObj = NULL;
- _Type* pType = NULL;
- _Type* pTypeOfType = NULL;
- _Type* pDesiredType = NULL;
- VARIANT typeNameParam;
- VARIANT getTypeRetVal;
- VARIANT nullObject;
- SAFEARRAY* psa;
- LONG index;
- BSTR getTypeName = SysAllocString(L"GetType");
-
- VariantInit(&typeNameParam);
- VariantInit(&getTypeRetVal);
- VariantInit(&nullObject);
-
- // Instantiate a dummy class just so we can get a System.Type instance
- hresult = CoCreateInstance(CLSID_Object, NULL,
- CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnk);
- if (FAILED(hresult)) goto cleanup;
-
- // Get the _Object interface so we can call GetType
- hresult = pUnk->QueryInterface(IID__Object, (void**)&pObj);
- if (FAILED(hresult)) goto cleanup;
-
- // Call _Object.GetType
- hresult = pObj->GetType(&pType);
- if (FAILED(hresult)) goto cleanup;
-
- // Call the instance Type.GetType method (inherited from Object)
- // in order to get the type for System.Type rather than the type for
- // System.Object
- hresult = pType->GetType(&pTypeOfType);
- if (FAILED(hresult)) goto cleanup;
-
- // Prepare a 1-element array containing the passed-in type name
- // to pass to the static Type.GetType method
- psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
- typeNameParam.vt = VT_BSTR;
- typeNameParam.bstrVal = typeName;
- index = 0;
- hresult = SafeArrayPutElement(psa, &index, &typeNameParam);
- if (FAILED(hresult)) goto cleanup;
-
- // Invoke the static Type.GetType method using reflection on the
- // type for System.Type in order to get the desired type
- nullObject.vt = VT_EMPTY;
- hresult = pTypeOfType->InvokeMember_3(getTypeName,
- (BindingFlags)(BindingFlags_InvokeMethod | BindingFlags_Public |
- BindingFlags_Static | BindingFlags_FlattenHierarchy), NULL,
- nullObject, psa, &getTypeRetVal);
- if (FAILED(hresult)) goto cleanup;
-
- // Get the _Type interface so we can call the static InvokeMember
- // method on the desired type to invoke the desired static member
- hresult = getTypeRetVal.punkVal->QueryInterface(IID__Type,
- (void**)&pDesiredType);
- if (FAILED(hresult)) goto cleanup;
-
- // Invoke the desired static member
- pDesiredType->InvokeMember_3(memberName, (BindingFlags)(memberType |
- BindingFlags_Public | BindingFlags_Static |
- BindingFlags_FlattenHierarchy), NULL, nullObject, parameters,
- retVal);
- if (FAILED(hresult)) goto cleanup;
-
- cleanup:
- if (pUnk) pUnk->Release();
- if (pObj) pObj->Release();
- if (pType) pType->Release();
- if (pTypeOfType) pTypeOfType->Release();
- if (pDesiredType) pDesiredType->Release();
- if (getTypeName) SysFreeString(getTypeName);
- SafeArrayDestroy(psa);
- VariantClear(&typeNameParam);
- VariantClear(&getTypeRetVal);
- VariantClear(&nullObject);
-
- return hresult;
- };
-
- int main(int argc, char* argv[])
- {
- HRESULT hresult;
- VARIANT retVal;
- _AppDomain* pDomain = NULL;
- BSTR typeName1, typeName2, memberName1, memberName2, directory;
-
- // Initialize COM
- hresult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot initialize COM: 0x%x\n", hresult);
- return -1;
- }
-
- VariantInit(&retVal);
-
- // ------------------------------------------
- // Example 1: Calling System.Console.ReadLine
- // ------------------------------------------
-
- typeName1 = SysAllocString(L"System.Console");
- memberName1 = SysAllocString(L"ReadLine");
-
- printf("Type in something followed by Enter: ");
-
- hresult = InvokeStaticMember(typeName1, memberName1,
- BindingFlags_InvokeMethod, NULL, &retVal);
- if (FAILED(hresult))
- {
- printf("ERROR: Invocation failed: 0x%x\n", hresult);
- return -1;
- }
-
- wprintf(L"You typed: '%s'\n", retVal.bstrVal);
-
- // --------------------------------------------------
- // Example 2: Calling System.AppDomain.CurrentDomain
- // --------------------------------------------------
-
- typeName2 = SysAllocString(L"System.AppDomain");
- memberName2 = SysAllocString(L"CurrentDomain");
-
- hresult = InvokeStaticMember(typeName2, memberName2,
- BindingFlags_GetProperty, NULL, &retVal);
- if (FAILED(hresult))
- {
- printf("ERROR: Invocation failed: 0x%x\n", hresult);
- return -1;
- }
-
- // Get the _AppDomain interface from the returned IUnknown pointer
- hresult = retVal.punkVal->QueryInterface(IID__AppDomain,
- (void**)&pDomain);
- if (FAILED(hresult))
- {
- printf("ERROR: Could not get _AppDomain interface pointer: 0x%x\n",
- hresult);
- return -1;
- }
-
- // Call the BaseDirectory property on the _AppDomain instance
- pDomain->get_BaseDirectory(&directory);
- wprintf(L"Base directory of the current domain: '%s'\n", directory);
-
- CoUninitialize();
- return 0;
- };
-
-
-
- #define _WIN32_DCOM
- #include <stdio.h>
- #include <wtypes.h>
-
- // Reference the two necessary type libraries
- #import "path\\mscoree.tlb" no_namespace named_guids raw_interfaces_only
- #import "path\\mscorlib.tlb" no_namespace named_guids raw_interfaces_only
-
- IUnknown* pUnk = NULL;
- IUnknown* pUnk2 = NULL;
- ICorRuntimeHost* pHost = NULL;
- _AppDomain* pDomain = NULL;
- _ObjectHandle* pHandle = NULL;
- IDispatch* pDisp = NULL;
-
- BSTR asmName;
- BSTR typeName;
- VARIANT arrayList;
- VARIANT param;
-
- void Cleanup()
- {
- pHost->Stop();
- if (pUnk) pUnk->Release();
- if (pUnk2) pUnk2->Release();
- if (pDisp) pDisp->Release();
- if (pHandle) pHandle->Release();
- if (pDomain) pDomain->Release();
- if (pHost) pHost->Release();
- if (asmName) SysFreeString(asmName);
- if (typeName) SysFreeString(typeName);
- VariantClear(¶m);
- VariantClear(&arrayList);
- CoUninitialize();
- };
-
- int main(int argc, char* argv[])
- {
- HRESULT hresult;
-
- // Initialize COM
- hresult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot initialize COM: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- // Initialize the CLR
- hresult = CoCreateInstance(CLSID_CorRuntimeHost, NULL,
- CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnk);
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot create host object: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- // Get the ICorRuntimeHost interface
- hresult = pUnk->QueryInterface(IID_ICorRuntimeHost, (void**)&pHost);
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot get ICorRuntimeHost interface pointer: 0x%x\n",
- hresult);
- Cleanup();
- return -1;
- }
-
- // Start the host
- hresult = pHost->Start();
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot start host: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- // Get the default domain
- hresult = pHost->GetDefaultDomain(&pUnk2);
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot get default domain: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- // Get the _AppDomain interface
- hresult = pUnk2->QueryInterface(IID__AppDomain, (void**)&pDomain);
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot get _AppDomain interface pointer: 0x%x\n",
- hresult);
- Cleanup();
- return -1;
- }
-
- // Strings for CreateInstance_3
- asmName = SysAllocString(L"mscorlib");
- typeName = SysAllocString(L"System.Collections.ArrayList");
-
- // Create a 1D array with one integer element
- SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
- VariantInit(¶m);
- param.vt = VT_I4;
- param.lVal = 128;
- LONG index = 0;
-
- hresult = SafeArrayPutElement(psa, &index, ¶m);
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot set SAFEARRAY element: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- // Create an instance of ArrayList using a parameterized constructor
- hresult = pDomain->CreateInstance_3(asmName, typeName, VARIANT_TRUE,
- BindingFlags_Default, NULL, psa, NULL, NULL, NULL, &pHandle);
- if (FAILED(hresult))
- {
- printf("ERROR: Cannot create instance: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- // Unwrap the ArrayList instance inside the ObjectHandle
- VariantInit(&arrayList);
- hresult = pHandle->Unwrap(&arrayList);
- if (FAILED(hresult))
- {
- printf("ERROR: Could not unwrap object handle: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- // Get the IDispatch interface so we can call the Capacity property
- hresult = arrayList.punkVal->QueryInterface(IID_IDispatch,
- (void**)&pDisp);
- if (FAILED(hresult))
- {
- printf("ERROR: Could not get IDispatch interface pointer: 0x%x\n",
- hresult);
- Cleanup();
- return -1;
- }
-
- // Get the DISPID for the Capacity property
- OLECHAR* name = L"Capacity";
- DISPID dispid;
- hresult = pDisp->GetIDsOfNames(IID_NULL, &name, 1, GetUserDefaultLCID(),
- &dispid);
- if (FAILED(hresult))
- {
- printf("ERROR: GetIDsOfNames failed: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- // Invoke the Capacity property
- VARIANT result;
- VariantInit(&result);
- DISPPARAMS params = { NULL, NULL, 0, 0 };
-
- hresult = pDisp->Invoke(dispid, IID_NULL, GetUserDefaultLCID(),
- DISPATCH_PROPERTYGET, ¶ms, &result, NULL, NULL);
- if (FAILED(hresult))
- {
- printf("ERROR: Invoke failed: 0x%x\n", hresult);
- Cleanup();
- return -1;
- }
-
- printf("ArrayList Capacity: %d\n", result.lVal);
-
- Cleanup();
- return 0;
- };
-
-
-
-
-
- // http://social.msdn.microsoft.com/Forums/vstudio/en-US/ce105a9b-837d-4384-ac03-287b45c1ecc9/marshalling-safearray-of-user-defined-struct
-
-
-
- __declspec(dllexport) SAFEARRAY * music_library_get_songs()
-
- {
-
- USES_CONVERSION;
-
- HRESULT hr = S_OK;
-
-
-
- // safe array dim
-
- SAFEARRAYBOUND safeArrayDim[1];
-
- safeArrayDim[0].lLbound = 0;
-
- safeArrayDim[0].cElements = 5;
-
-
-
- // create safe array
-
- SAFEARRAY * pSafeArray = SafeArrayCreate(VT_VARIANT,1,safeArrayDim);
-
-
-
- // fill safe array with data
-
- if(pSafeArray != NULL) {
-
- unsigned int i;
-
- long index;
-
- pSafeArray->pvData = malloc(5*sizeof(t_song));
-
- for(i = safeArrayDim[0].lLbound; i < safeArrayDim[0].cElements + safeArrayDim[0].lLbound; i++) {
-
- VARIANT vOut;
-
- VariantInit(&vOut);
-
- t_song * song = (t_song*)malloc(sizeof(t_song));
-
- song->album = "album";
-
- song->artist = "artist";
-
- song->name = "name";
-
- /* i don't know how to connect the song structure with the VARIANT
-
- */
-
- hr = SafeArrayPutElement(pSafeArray, &index, &vOut);
-
- VariantClear(&vOut);
-
- }
-
- }
-
- return pSafeArray;
-
- }
- managed c# code
- // structure marshaling
-
- [StructLayout(LayoutKind.Sequential)]
-
- public class Song
-
- {
-
- [MarshalAs(UnmanagedType.LPTStr)]
-
- public string name;
-
- [MarshalAs(UnmanagedType.LPStr)]
-
- public string album;
-
- [MarshalAs(UnmanagedType.LPStr)]
-
- public string artist;
-
-
-
- }
-
-
-
-
-
- [DllImport(MyLibrary.dll)]
-
- [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_VARIANT)]
-
-
-
-
- USES_CONVERSION; // enables use of ATL conversion macro A2W
- char buffer[20]; // used to store ANSI string
- HRESULT hr= S_OK;
-
- // Create SafeArray of VARIANT BSTRs
- SAFEARRAY *pSA;
- SAFEARRAYBOUND aDim[1]; // a one dimensional array
- aDim[0].lLbound= 0; // Visual Basic arrays start with index 0
- aDim[0].cElements= 10;
- pSA= SafeArrayCreate(VT_VARIANT,1,aDim); // create a 1D SafeArray of VARIANTS
- if (pSA != NULL) {
- long aLong[1];
- // iterate over array adding VARIANTs of type VT_BSTR
- for (long l= aDim[0].lLbound; l< (aDim[0].cElements + aDim[0].lLbound); l++) {
- VARIANT vOut;
- VariantInit(&vOut);
- vOut.vt= VT_BSTR; // set type
- ltoa(l,buffer,10); // convert long to ANSI string value
- vOut.bstrVal= ::SysAllocString(A2W(buffer)); // system wide "new"
- aLong[0]= l; // set index value
- if (hr= SafeArrayPutElement(pSA, aLong, &vOut)) { // "correctly" copies VARIANT
- VariantClear(&vOut); // release BSTR from memory on error
- SafeArrayDestroy(pSA); // does a deep destroy on error
- return hr;
- }
- VariantClear(&vOut); // does a deep destroy of source VARIANT
- } // end iteration
- }
- // clean up here only if you do not return SafeArray as an [out, retval]
- SafeArrayDestroy(pSA); // again does a deep destroy
-
-
-
-
- // Learning DCOM book on Safary
- void CallOcrImage(IOcr *pIOcr, BYTE *pImage, ULONG len)
- {
- // Create a one-dimensional SAFEARRAY of BYTEs (VT_UI)
- // The size of this array is len, which represents our image length.
- SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
- // Access the data pointer
- unsigned char *pc = NULL;
- SafeArrayAccessData(psa, reinterpret_cast<void HUGEP**>(&pc));
- // Copy our binary image data into array
- memcpy(pc, pImage, len);
- // Done accessing, so unaccess now.
- SafeArrayUnaccessData(psa);
- // Now we've got the array, we need to store it in
- // a VARIANT (the value holder).
- VARIANT vImage; // So, let's create a variant
- VariantInit(&vImage); // Initialize the variant
- // Tell the value holder it's holding a SAFEARRAY of bytes
- binaryImageArray.vt = (VT_ARRAY|VT_UI1) ;
- binaryImageArray.parray = psa; // Let the variant hold the array
- // Yes! That much set up work before we can invoke a method!
- // Now for the method invocation...
- BSTR pOcrText ; // Where the OCR text will be stored
- HRESULT hr = pIOcr->OcrImage(vImage, &pOcrText);
- if (SUCCEEDED(hr)) {
- m_strOCRResults = pOcrText ;
- SysFreeString(pOcrText) ;
- }
- SafeArrayDestroyData(psa); // Destroy the data within the SAFEARRAY
- SafeArrayDestroy(psa); // Destroy the SAFEARRAY
- // Clear the data
- VariantClear(&binaryImageArray);
- }
-
-
-
- void CVcpphostclrDlg::OnTestmanagedclassButton()
-
- HRESULT hRes;
- ICorRuntimeHost *pRuntimeHost;
- IUnknown *pUnkAppDomain;
- _AppDomain *pAppDomain;
- _ObjectHandle *pHandle;
- OLECHAR *methodName=L"GetSalary";
- VARIANT vntResult;
- float fltVal;
- DISPID dispid;
- EXCEPINFO errorInfo;
- UINT intArg;
- DISPPARAMS param;
- BSTR bstrTypeName, bstrAssemblyName;
- SAFEARRAY *paramArray;
- VARIANT paramID, paramName;
- VARIANT paramSalary, paramBonus;
- LONG index;
- hRes=CoInitializeEx(NULL,COINIT_MULTITHREADED);
- if (FAILED(hRes))
- AfxMessageBox("Could not initialize COM");
- hRes=CoCreateInstance(CLSID_CorRuntimeHost,
- NULL,CLSCTX_INPROC_SERVER,
- IID_ICorRuntimeHost,
- (void **)&pRuntimeHost);
- if (FAILED(hRes))
- AfxMessageBox("Could not create host");
- hRes=pRuntimeHost->Start();
- hRes=pRuntimeHost->GetDefaultDomain(
- &pUnkAppDomain);
- if (FAILED(hRes))
- AfxMessageBox("Could not get Appdomain");
- hRes=pUnkAppDomain->QueryInterface(
- IID__AppDomain,(void **)&pAppDomain);
- if (FAILED(hRes))
- AfxMessageBox("Failed to get domain");
- if (pUnkAppDomain!=NULL)
- pUnkAppDomain->Release();
- bstrTypeName=SysAllocString(
- L"AssemblyDemo.Manager");
- bstrAssemblyName=SysAllocString(
- L"multifile3,Version=2.0.0.0,Culture=neutral,
- PublicKeyToken=8a707be49fd7d8f4");
- paramArray=SafeArrayCreateVector(VT_VARIANT,0,4);
-
- VariantInit(¶mID);
- paramID.vt=VT_I4;
- paramID.lVal=45;
- index=0;
- hRes=SafeArrayPutElement(paramArray,
- &index,¶mID);
- VariantInit(¶mName);
- paramName.vt=VT_BSTR;
- paramName.bstrVal=SysAllocString(L"Alan Gordon");
- index=1;
- hRes=SafeArrayPutElement(paramArray,
- &index,¶mName);
- VariantInit(¶mSalary);
- paramSalary.vt=VT_R4;
- paramSalary.fltVal=1000.0;
- VariantChangeType(¶mSalary,¶mSalary,
- 0,VT_DECIMAL);
- index=2;
- hRes=SafeArrayPutElement(paramArray,
- &index,¶mSalary);
- VariantInit(¶mBonus);
- paramBonus.vt=VT_R4;
- paramBonus.fltVal=100.0;
- VariantChangeType(¶mBonus,¶mBonus,
- 0,VT_DECIMAL);
- index=3;
- hRes=SafeArrayPutElement(paramArray,
- &index,¶mBonus);
- hRes=pAppDomain->CreateInstance_3(
- bstrAssemblyName,bstrTypeName,VARIANT_TRUE,
- BindingFlags_Default,NULL,paramArray,
- NULL,NULL,NULL,&pHandle);
- if (FAILED(hRes))
- AfxMessageBox("Could not create object");
- VARIANT vntObject;
- IDispatch *pObject;
- VariantInit(&vntObject);
- pHandle->Unwrap(&vntObject);
- vntObject.punkVal->QueryInterface(IID_IDispatch,
- (void **)&pObject);
- if (vntObject.punkVal!=NULL)
- vntObject.punkVal->Release();
-
- param.cArgs=0;
- param.rgvarg=NULL;
- param.cNamedArgs=0;
- param.rgdispidNamedArgs=NULL;
- VariantInit(&vntResult);
- hRes=pObject->GetIDsOfNames(IID_NULL,
- &methodName,1,GetUserDefaultLCID(),&dispid);
- hRes=pObject->Invoke(dispid,IID_NULL,
- GetUserDefaultLCID(),
- DISPATCH_METHOD,¶m,&vntResult,
- &errorInfo,&intArg);
- if (SUCCEEDED(hRes))
- {
- vntResult.decVal;
- VarR4FromDec(&vntResult.decVal,&fltVal);
- }
- else
- {
- // Handle the error, code omitted...
- }
- if (pObject!=NULL)
- pObject->Release();
- if (pAppDomain!=NULL)
- pAppDomain->Release();
-
- SysFreeString(bstrTypeName);
- SysFreeString(bstrAssemblyName);
- SafeArrayDestroy(paramArray);
- }
-
-
-
-
-
-
-
- // _bstr_t_Assign.cpp
-
- #include <comdef.h>
- #include <stdio.h>
-
- int main()
- {
- // creates a _bstr_t wrapper
- _bstr_t bstrWrapper;
-
- // creates BSTR and attaches to it
- bstrWrapper = "some text";
- wprintf_s(L"bstrWrapper = %s\n",
- static_cast<wchar_t*>(bstrWrapper));
-
- // bstrWrapper releases its BSTR
- BSTR bstr = bstrWrapper.Detach();
- wprintf_s(L"bstrWrapper = %s\n",
- static_cast<wchar_t*>(bstrWrapper));
- // "some text"
- wprintf_s(L"bstr = %s\n", bstr);
-
- bstrWrapper.Attach(SysAllocString(OLESTR("SysAllocedString")));
- wprintf_s(L"bstrWrapper = %s\n",
- static_cast<wchar_t*>(bstrWrapper));
-
- // assign a BSTR to our _bstr_t
- bstrWrapper.Assign(bstr);
- wprintf_s(L"bstrWrapper = %s\n",
- static_cast<wchar_t*>(bstrWrapper));
-
- // done with BSTR, do manual cleanup
- SysFreeString(bstr);
-
- // resuse bstr
- bstr= SysAllocString(OLESTR("Yet another string"));
- // two wrappers, one BSTR
- _bstr_t bstrWrapper2 = bstrWrapper;
-
- *bstrWrapper.GetAddress() = bstr;
-
- // bstrWrapper and bstrWrapper2 do still point to BSTR
- bstr = 0;
- wprintf_s(L"bstrWrapper = %s\n",
- static_cast<wchar_t*>(bstrWrapper));
- wprintf_s(L"bstrWrapper2 = %s\n",
- static_cast<wchar_t*>(bstrWrapper2));
-
- // new value into BSTR
- _snwprintf_s(bstrWrapper.GetBSTR(), 100, bstrWrapper.length(),
- L"changing BSTR");
- wprintf_s(L"bstrWrapper = %s\n",
- static_cast<wchar_t*>(bstrWrapper));
- wprintf_s(L"bstrWrapper2 = %s\n",
- static_cast<wchar_t*>(bstrWrapper2));
- }
-
-
-
- HRESULT PASCAL __export CPoly::EnumPoints(IEnumVARIANT FAR* FAR* ppenum)
- {
- unsigned int i;
- HRESULT hresult;
- VARIANT var;
- SAFEARRAY FAR* psa;
- CEnumPoint FAR* penum;
- POINTLINK FAR* ppointlink;
- SAFEARRAYBOUND rgsabound[1];
- rgsabound[0].lLbound = 0;
- rgsabound[0].cElements = m_cPoints;
-
- psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
- if(psa == NULL){
- HRESULT = ResultFromScode(E_OUTOFMEMORY);
- goto LError0;
- }
-
- // Code omitted here for brevity.
-
- V_VT(&var) = VT_DISPATCH;
- HRESULT = ppointlink->ppoint->QueryInterface(
- IID_IDispatch, (void FAR* FAR*)&V_DISPATCH(&var));
- if(HRESULT != NOERROR)
- goto LError1;
-
- ix[0] = i;
- SafeArrayPutElement(psa, ix, &var);
-
- ppointlink = ppointlink->next;
- }
-
- HRESULT = CEnumPoint::Create(psa, &penum);
- if(HRESULT != NOERROR)
- goto LError1;
- *ppenum = penum;
- return NOERROR;
-
- LError1:;
- SafeArrayDestroy(psa);
-
- LError0:;
- return hresult;
- }
-
- // http://social.msdn.microsoft.com/Forums/vstudio/en-US/cdc68fd4-08d5-4bfd-8dd7-6c095bd619a6/any-easy-way-to-create-a-safearray
- void AlternativeSetSafeArrayData(/*[in]*/ SAFEARRAY* psaStrings)
- {
- BSTR bstr = ::SysAllocString(OLESTR("Another BSTR."));
- VARIANT var;
- long lIndexVector[1];
-
- lIndexVector[0] = 0;
-
- VariantInit(&var);
- VariantClear(&var);
- V_VT(&var) = VT_BSTR;
- V_BSTR(&var) = bstr;
-
- SafeArrayPutElement
- (
- psaStrings,
- (long*)lIndexVector,
- (void*)&var
- );
-
- VariantClear(&var);
- }