Buffer handling is a pretty core topic to C and C++ programming. I would start by reading up on that. Here's the best I could find on short notice:
Once you understand that, try to think about it from the point of view of the function you're calling. When MsiGetTargetPath is called, assuming the other parameters are good, it figures out the path to see if it and a trailing null character fit in *pcchPathBuf
characters. If it fits, it copies the path to the TCHAR array pointed to by szPathBuf
, updates *pcchPathBuf
to reflect the actual size, and returns success. If it does not fit, it updates *pcchPathBuf
to reflect the size it needs (excluding the trailing null character), and returns ERROR_MORE_DATA
.
So your code needs to pass correct parameters, including a buffer of reasonable size. I'd start with MAX_PATH
and then only have to increase in some very unusual cases. Note that the following code takes advantage of the actual layout of std::wstring in all known implementations, but isn't guaranteed by the specification until C++11.
// assumes hInstall and strDirectory are defined and correct
std::wstring strPath; // assuming UNICODE here; use std::string if _MBCS instead
DWORD cchPath = MAX_PATH;
strPath.resize(cchPath);
DWORD nResult = ::MsiGetTargetPath(hInstall, strDirectory.c_str(), &strPath[0], &cchPath);
if (nResult == ERROR_MORE_DATA)
{
strPath.resize(++cchPath); // allocate extra spot for trailing null character
nResult = ::MsiGetTargetPath(hInstall, strDirectory.c_str(), &strPath[0], &cchPath);
}
if (nResult == ERROR_SUCCESS)
strPath.resize(cchPath);
else
strPath.clear();