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.