A simple problem, for which the answer is annoyingly hard to find: you are trying to set a COM object property using IDispatch::Invoke, and you get a blasted error. For instance, you may be using code like this:
OLECHAR *pszParam = OLESTR("Param"); DISPPARAMS dispparams; VARIANT FAR VarData; pObject->GetIDsOfNames(IID_NULL, &pszParam, 1, LOCALE_USER_DEFAULT, &dispid); dispparams.rgvarg = &VarData; dispparams.rgvarg[0].intVal = 1; dispparams.rgvarg[0].vt = VT_INT; dispparams.cArgs = 1; dispparams.cNamedArgs = 0; pObject->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
&dispparams, NULL, NULL, NULL);
What could possibly be wrong? Well, if you look long enough and hard enough, you'll find a few sentences on this topic buried deep within Microsoft's documentation. It is that some Automation servers cannot distinguish between DISPATCH_PROPERTYPUT and DISPATCH_PROPERTYGET, so you need to use a named parameter with a special dispid:
OLECHAR *pszParam = OLESTR("Param"); DISPPARAMS dispparams; DISPID dispidPut = DISPID_PROPERTYPUT; VARIANT FAR VarData; pObject->GetIDsOfNames(IID_NULL, &pszParam, 1, LOCALE_USER_DEFAULT, &dispid); dispparams.rgvarg = &VarData; dispparams.rgvarg[0].intVal = 1; dispparams.rgvarg[0].vt = VT_INT; dispparams.cArgs = 1; dispparams.cNamedArgs = 1; dispparams.rgdispidNamedArgs = &dispidPut; pObject->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
&dispparams, NULL, NULL, NULL);
That's all it takes, but of course it'd be nice if this were noted where IDispatch::Invoke is documented.