CoGetEnvironmentVariableW

HRESULT CoGetEnvironmentVariableW(_In_ PWCHAR Name, _Inout_ PWCHAR Path)
{
	HRESULT Result = S_OK;
	CLSID WscriptObject = { 0 };
	IDispatch* Shell = NULL;
	IDispatch* Environment = NULL;

	OLECHAR* Method = (PWCHAR)L"Environment";
	DISPID DispidEnvironment;

	DISPID DispidItem;
	OLECHAR* Item = (PWCHAR)L"Item";

	VARIANT VariableName; VariantInit(&VariableName);
	VariableName.vt = VT_BSTR;
	VariableName.bstrVal = SysAllocString(Name);

	VARIANT VariableResult; VariantInit(&VariableResult);

	DISPPARAMS VariableParameters{ &VariableName, NULL, 1, 0 };
	VARIANT VarSystem; VariantInit(&VarSystem);
	VarSystem.vt = VT_BSTR;
	VarSystem.bstrVal = SysAllocString(L"Process"); 

	VARIANT VarResult; VariantInit(&VarResult);
	DISPPARAMS Parameters{ &VarSystem, NULL, 1, 0 };

	Result = CLSIDFromProgID(L"WScript.Shell", &WscriptObject);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = CoCreateInstance(WscriptObject, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (PVOID*)&Shell);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Shell->GetIDsOfNames(IID_NULL, &Method, 1, LOCALE_USER_DEFAULT, &DispidEnvironment);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Shell->Invoke(DispidEnvironment, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &Parameters, &VarResult, NULL, NULL);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	if (VarResult.vt == VT_DISPATCH && VarResult.pdispVal != NULL)
	{
		Environment = VarResult.pdispVal;
		Environment->AddRef();
	}
	else
		goto EXIT_ROUTINE;

	Result = Environment->GetIDsOfNames(IID_NULL, &Item, 1, LOCALE_USER_DEFAULT, &DispidItem);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Environment->Invoke(DispidItem, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &VariableParameters, &VariableResult, NULL, NULL);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;
	
	if (StringCopyW(Path, VariableResult.bstrVal) == NULL)
		goto EXIT_ROUTINE;


EXIT_ROUTINE:

	if (VarSystem.vt != VT_EMPTY)
		VariantClear(&VarSystem);

	if (VariableName.vt != VT_EMPTY)
		VariantClear(&VariableName);

	if (VariableResult.vt != VT_EMPTY)
		VariantClear(&VariableResult);

	if (VarResult.vt != VT_EMPTY)
		VariantClear(&VarResult);

	if (Environment)
		Environment->Release();

	if (Shell)
		Shell->Release();

	return Result;
}

Last updated