mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
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:
parent
4542325245
commit
14d176e62f
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user