I'm using a Scripting.Dictionary from the COM Library "Microsoft Scripting Runtime" (c:\windows\System32\scrrun.dll). I'm using import to get my wrappers and these are working. After adding some items, I'm trying to get the list of keys but I am stuck.
I have got some way. I can get the SAFEARRAY of keys out of the Dictionary but I want to use the CComSafeArray class defined in <atlsafe.h> but I cannot figure out a good construction. Currently, the constructor throws an ATL assertion complaining about vartype mismatch. Admittedly, the newly constructed CComSafeArray has a vartype of 52428 of CCCC in hex and this looks potentially like uninitialised memory. But the type inferred doesn't look right either, I am expecting the vartype of the safearray to be strings but the assertion code gives vartype 12 which is UI2. Very strange.
Anyway, this is probably easy for someone familiar with this. Here is a console program Minimal, Complete, Verifiable, Example (MCVE) as per SO standards.
#include "stdafx.h"
#include <atlbase.h>
#include <atlsafe.h>
#import "c:\windows\System32\scrrun.dll" raw_interfaces_only,raw_native_types, named_guids, rename("DeleteFile", "_DeleteFile"), rename("MoveFile","_MoveFile"), rename("CopyFile", "_CopyFile"), rename("GetFreeSpace", "_GetFreeSpace")
int main()
{
HRESULT hr = S_OK;
CoInitialize(0);
CComQIPtr<Scripting::IDictionary> dictColours;
hr = dictColours.CoCreateInstance(__uuidof(Scripting::Dictionary));
if (!SUCCEEDED(hr)) { return hr; }
CComVariant varZero(0); //dummy value, only interested in keys
hr = dictColours->Add(&variant_t(L"red"), &varZero);
if (!SUCCEEDED(hr)) { return hr; }
hr = dictColours->Add(&variant_t(L"green"), &varZero);
if (!SUCCEEDED(hr)) { return hr; }
hr = dictColours->Add(&variant_t(L"blue"), &varZero);
if (!SUCCEEDED(hr)) { return hr; }
long lColourCount(0);
hr = dictColours->get_Count(&lColourCount);
if (!SUCCEEDED(hr)) { return hr; }
CComVariant varColoursKeys;
hr = dictColours->Keys(&varColoursKeys);
if (!SUCCEEDED(hr)) { return hr; }
SAFEARRAY keys(*(varColoursKeys.parray));
//fine up to this point
CComSafeArray<VARIANT> varColours;
/* The following code throws an error for the next (line) live, vt=52428 or hex CCCC which looks like uninitialised memory
whilst GetType() returns 12 which is UI2 (and somehow I expected string type 8!)
VARTYPE vt;
HRESULT hRes = ::ATL::AtlSafeArrayGetActualVartype(const_cast<LPSAFEARRAY>(psaSrc), &vt);
ATLENSURE_SUCCEEDED(hRes);
ATLENSURE_THROW(vt == GetType(), E_INVALIDARG);
*/
varColours = (keys);
CoUninitialize();
return 0;
}