bug 236312 prevent PendingFileRenameOperations registry value corruption and possible windows death r=ssu,sr=dbaron

bug 193723 non-admin WinXP users should be able to install (force a local GRE) r=ssu,sr=dougt
This commit is contained in:
dveditz%cruzio.com 2004-05-11 21:32:39 +00:00
parent 4542325245
commit 14d176e62f
2 changed files with 120 additions and 79 deletions

View File

@ -54,6 +54,7 @@
// shellapi.h is needed to build with WIN32_LEAN_AND_MEAN
#include <shellapi.h>
#include <Shlwapi.h>
#define HIDWORD(l) ((DWORD) (((ULONG) (l) >> 32) & 0xFFFF))
#define LODWORD(l) ((DWORD) (l))
@ -517,6 +518,111 @@ BOOL UpdateFile(char *szInFilename, char *szOutFilename, char *szIgnoreStr)
return(bFoundIgnoreStr);
}
/* Function: RemoveDelayedDeleteFileEntries()
*
* in: const char *aPathToMatch - path to match against
*
* purpose: To remove windows registry entries (normally set by the uninstaller)
* that dictates what files to remove at system remove.
* The windows registry key that will be parsed is:
*
* key : HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager
* name: PendingFileRenameOperations
*
* This will not remove any entries that are set to be 'renamed'
* at system remove, only to be 'deleted'.
*
* This function is multibyte safe.
*
* To see what format the value of the var is in, look up the win32 API:
* MoveFileEx()
*/
void RemoveDelayedDeleteFileEntries(const char *aPathToMatch)
{
HKEY hkResult;
DWORD dwErr;
DWORD dwType = REG_NONE;
DWORD oldMaxValueLen = 0;
DWORD newMaxValueLen = 0;
DWORD lenToEnd = 0;
char *multiStr = NULL;
const char key[] = "SYSTEM\\CurrentControlSet\\Control\\Session Manager";
const char name[] = "PendingFileRenameOperations";
char *pName;
char *pRename;
int nameLen, renameLen;
assert(aPathToMatch);
/* if not NT systems (win2k, winXP) return */
if (!(gSystemInfo.dwOSType & OS_NT))
return;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ|KEY_WRITE, &hkResult) != ERROR_SUCCESS)
return;
dwErr = RegQueryValueEx(hkResult, name, 0, &dwType, NULL, &oldMaxValueLen);
if (dwErr != ERROR_SUCCESS || oldMaxValueLen == 0 || dwType != REG_MULTI_SZ)
{
/* no value, no data, or wrong type */
return;
}
multiStr = calloc(oldMaxValueLen, sizeof(BYTE));
if (!multiStr)
return;
if (RegQueryValueEx(hkResult, name, 0, NULL, multiStr, &oldMaxValueLen) == ERROR_SUCCESS)
{
// The registry value consists of name/newname pairs of null-terminated
// strings, with a final extra null termination. We're only interested
// in files to be deleted, which are indicated by a null newname.
lenToEnd = newMaxValueLen = oldMaxValueLen;
pName = multiStr;
while(*pName && lenToEnd > 0)
{
// find the locations and lengths of the current pair. Count the
// nulls, we need to know how much data to skip or move
nameLen = strlen(pName) + 1;
pRename = pName + nameLen;
renameLen = strlen(pRename) + 1;
// How much remains beyond the current pair
lenToEnd -= (nameLen + renameLen);
if (*pRename == '\0')
{
// No new name, it's a delete. Is it the one we want?
if (StrStrI(pName, aPathToMatch))
{
// It's a match--
// delete this pair by moving the remainder on top
memmove(pName, pRename + renameLen, lenToEnd);
// update the total length to reflect the missing pair
newMaxValueLen -= (nameLen + renameLen);
// next pair is in place, continue w/out moving pName
continue;
}
}
// on to the next pair
pName = pRename + renameLen;
}
if (newMaxValueLen != oldMaxValueLen)
{
// We've deleted something, save the changed data
RegSetValueEx(hkResult, name, 0, REG_MULTI_SZ, multiStr, newMaxValueLen);
RegFlushKey(hkResult);
}
}
RegCloseKey(hkResult);
free(multiStr);
}
/* Looks for and removes the uninstaller from the Windows Registry
* that is set to delete the uninstaller at the next restart of
* Windows. This key is set/created when the user does the following:
@ -530,92 +636,21 @@ BOOL UpdateFile(char *szInFilename, char *szOutFilename, char *szIgnoreStr)
*/
void ClearWinRegUninstallFileDeletion(void)
{
char *szPtrIn = NULL;
char *szPtrOut = NULL;
char szInMultiStr[MAX_BUF];
char szOutMultiStr[MAX_BUF];
char szLCKeyBuf[MAX_BUF];
char szLCUninstallFilenameLongBuf[MAX_BUF];
char szLCUninstallFilenameShortBuf[MAX_BUF];
char szWinInitFile[MAX_BUF];
char szTempInitFile[MAX_BUF];
char szWinDir[MAX_BUF];
DWORD dwOutMultiStrLen;
DWORD dwType;
BOOL bFoundUninstaller = FALSE;
if(!GetWindowsDirectory(szWinDir, sizeof(szWinDir)))
return;
wsprintf(szLCUninstallFilenameLongBuf, "%s\\%s", szWinDir, sgProduct.szUninstallFilename);
GetShortPathName(szLCUninstallFilenameLongBuf, szLCUninstallFilenameShortBuf, sizeof(szLCUninstallFilenameShortBuf));
CharLower(szLCUninstallFilenameLongBuf);
CharLower(szLCUninstallFilenameShortBuf);
if(gSystemInfo.dwOSType & OS_NT)
{
ZeroMemory(szInMultiStr, sizeof(szInMultiStr));
ZeroMemory(szOutMultiStr, sizeof(szOutMultiStr));
dwType = GetWinReg(HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Control\\Session Manager",
"PendingFileRenameOperations",
szInMultiStr,
sizeof(szInMultiStr));
if((dwType == REG_MULTI_SZ) && (szInMultiStr != '\0'))
{
szPtrIn = szInMultiStr;
szPtrOut = szOutMultiStr;
dwOutMultiStrLen = 0;
do
{
lstrcpy(szLCKeyBuf, szPtrIn);
CharLower(szLCKeyBuf);
if(!strstr(szLCKeyBuf, szLCUninstallFilenameLongBuf) && !strstr(szLCKeyBuf, szLCUninstallFilenameShortBuf))
{
if((dwOutMultiStrLen + lstrlen(szPtrIn) + 3) <= sizeof(szOutMultiStr))
{
/* uninstaller not found, so copy the szPtrIn string to szPtrOut buffer */
lstrcpy(szPtrOut, szPtrIn);
dwOutMultiStrLen += lstrlen(szPtrIn) + 2; /* there are actually 2 NULL bytes between the strings */
szPtrOut = &szPtrOut[lstrlen(szPtrIn) + 2]; /* there are actually 2 NULL bytes between the strings */
}
else
{
bFoundUninstaller = FALSE;
/* not enough memory; break out of while loop. */
break;
}
}
else
bFoundUninstaller = TRUE;
szPtrIn = &szPtrIn[lstrlen(szPtrIn) + 2]; /* there are actually 2 NULL bytes between the strings */
}while(*szPtrIn != '\0');
}
if(bFoundUninstaller)
{
if(dwOutMultiStrLen > 0)
{
/* take into account the 3rd NULL byte that signifies the end of the MULTI string */
++dwOutMultiStrLen;
SetWinReg(HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Control\\Session Manager",
TRUE,
"PendingFileRenameOperations",
TRUE,
REG_MULTI_SZ,
szOutMultiStr,
dwOutMultiStrLen,
FALSE,
FALSE);
}
else
DeleteWinRegValue(HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Control\\Session Manager",
"PendingFilerenameOperations");
}
RemoveDelayedDeleteFileEntries(szLCUninstallFilenameShortBuf);
}
else
{
@ -7073,10 +7108,10 @@ HRESULT ParseConfigIni(LPSTR lpszCmdLine)
wsprintf(sgProduct.szRegPath, "Software\\%s\\%s\\%s", sgProduct.szCompanyName, sgProduct.szProductNameInternal, sgProduct.szUserAgent);
gbRestrictedAccess = VerifyRestrictedAccess();
if(gbRestrictedAccess)
if(gbRestrictedAccess && !gbForceInstall)
{
/* Detected user does not have the appropriate
* privileges on this system */
// User does not have the appropriate privileges on this system
// (-f "force install" option overrides this check)
char szTitle[MAX_BUF_TINY];
int iRvMB;
@ -7090,6 +7125,11 @@ HRESULT ParseConfigIni(LPSTR lpszCmdLine)
GetPrivateProfileString("Strings", "Message NORMAL Restricted Access", "", szBuf, sizeof(szBuf), szFileIniConfig);
iRvMB = MessageBox(hWndMain, szBuf, szTitle, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2);
// force a local GRE to avoid problems with non-admin installs
// but don't override an explicit command-line choice
if (sgProduct.greType == GRE_TYPE_NOT_SET)
sgProduct.greType = GRE_LOCAL;
break;
case AUTO:
@ -8008,7 +8048,7 @@ HRESULT DecryptVariable(LPSTR szVariable, DWORD dwVariableSize)
else if(lstrcmpi(szVariable, "COMMON_STARTUP") == 0)
{
/* parse for the "C:\WINNT40\Profiles\All Users\Start Menu\\Programs\\Startup" directory */
if(gSystemInfo.dwOSType & OS_WIN9x)
if(gSystemInfo.dwOSType & OS_WIN9x || gbRestrictedAccess)
{
GetWinReg(HKEY_CURRENT_USER, szWRMSShellFolders, "Startup", szVariable, dwVariableSize);
}
@ -8032,7 +8072,7 @@ HRESULT DecryptVariable(LPSTR szVariable, DWORD dwVariableSize)
else if(lstrcmpi(szVariable, "COMMON_PROGRAMS") == 0)
{
/* parse for the "C:\WINNT40\Profiles\All Users\Start Menu\\Programs" directory */
if(gSystemInfo.dwOSType & OS_WIN9x)
if(gSystemInfo.dwOSType & OS_WIN9x || gbRestrictedAccess)
{
GetWinReg(HKEY_CURRENT_USER, szWRMSShellFolders, "Programs", szVariable, dwVariableSize);
}
@ -8044,7 +8084,7 @@ HRESULT DecryptVariable(LPSTR szVariable, DWORD dwVariableSize)
else if(lstrcmpi(szVariable, "COMMON_STARTMENU") == 0)
{
/* parse for the "C:\WINNT40\Profiles\All Users\Start Menu" directory */
if(gSystemInfo.dwOSType & OS_WIN9x)
if(gSystemInfo.dwOSType & OS_WIN9x || gbRestrictedAccess)
{
GetWinReg(HKEY_CURRENT_USER, szWRMSShellFolders, "Start Menu", szVariable, dwVariableSize);
}
@ -8056,7 +8096,7 @@ HRESULT DecryptVariable(LPSTR szVariable, DWORD dwVariableSize)
else if(lstrcmpi(szVariable, "COMMON_DESKTOP") == 0)
{
/* parse for the "C:\WINNT40\Profiles\All Users\Desktop" directory */
if(gSystemInfo.dwOSType & OS_WIN9x)
if(gSystemInfo.dwOSType & OS_WIN9x || gbRestrictedAccess)
{
GetWinReg(HKEY_CURRENT_USER, szWRMSShellFolders, "Desktop", szVariable, dwVariableSize);
}

View File

@ -217,6 +217,7 @@ void RestoreAdditionalFlag(siC *siCNode);
void RestoreEnabledFlag(siC *siCNode);
void SwapFTPAndHTTP(char *szInUrl, DWORD dwInUrlSize);
void ClearWinRegUninstallFileDeletion(void);
void RemoveDelayedDeleteFileEntries(const char *aPathToMatch);
int AppendToGlobalMessageStream(char *szInfo);
char *GetOSTypeString(char *szOSType, DWORD dwOSTypeBufSize);
int UpdateIdiFile(char *szPartialUrl,