Reputation: 1637
I am writing a C++ Custom action for WiX that will be called during installation to remove any leftovers installed by the installer. Consider the following code:
UINT __stdcall DeleteResidue(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
LPWSTR lpFolderPath = NULL;
std::wstring temp;
SHFILEOPSTRUCT shFile;
hr = WcaInitialize(hInstall, "DeleteResidue");
ExitOnFailure(hr, "Failed to initialize");
hr = WcaGetProperty(L"LPCOMMAPPDATAFOLDER",&lpFolderPath);
ExitOnFailure(hr, "Failure in Finding Common App Data Folder");
temp = std::wstring(lpFolderPath);
temp+=L"\0\0";
//Stop the LPA and LPA Monitor Service. Then delete the residue.
WcaLog(LOGMSG_STANDARD, "Doing Delete Residue");
ZeroMemory(&shFile, sizeof(shFile));
shFile.hwnd = NULL;
shFile.wFunc = FO_DELETE;
shFile.pFrom = temp.c_str();
shFile.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI;
BOOL res = DirectoryExists(lpFolderPath);
if(res)
{
WcaLog(LOGMSG_STANDARD, "The directory exist");
int result = SHFileOperation(&shFile);
if(!result)
WcaLog(LOGMSG_STANDARD, "The directory should have deleted by now");
else
WcaLog(LOGMSG_STANDARD, "The directory could not be deleted.Error code %d", result);
}
else
{
WcaLog(LOGMSG_STANDARD, "It Seems the Installed Folder is No more there");
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
In above code, we get C:\ProgramData
inLPCOMMAPPDATAFOLDER
. The doc states that pFrom
should be double null terminated
. However the return value of the code is 0x2
i.e. ERROR_FILE_NOT_FOUND
. What is wrong in the code above?
Upvotes: 2
Views: 1000
Reputation: 9837
You are not double nul terminating the pFrom
.
You have a standard string (which includes the null terminator when you call .c_str()
on it).
temp = std::wstring(lpFolderPath);
You then concatenate an empty string onto it:
temp+=L"\0\0";
This leaves the original string unchanged. This is because the std::string::operator+(const wchar_t*)
takes a null terminated string. The fact that you have 2 nulls is immaterial it only reads up to the first null. It doesn't even add that null as what you've effectively given it is an empty string and the result of concatenating an empty string to something else is a no-op.
There's a few ways to solve this, but probably easiest is to change
temp+=L"\0\0";
to
temp.push_back(L'\0');
which explicitly adds another nul to the string so when you eventaully call temp.c_str()
you'll get back the double nul-terminated string you need.
Upvotes: 2