Windows2003-3790/inetcore/wininet/urlcache/flock.cxx
2020-09-30 16:53:55 +02:00

353 lines
10 KiB
C++

#include "flock.hxx"
#include <resource.h>
#include <cache.hxx>
#undef inet_ntoa
#undef inet_addr
#undef gethostname
#undef gethostbyname
#undef gethostbyaddr
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef sunos5
extern "C" int gethostname(char*,int);
#endif
extern HANDLE MwOpenProcess(pid_t, BOOL);
extern "C" MwAtExit(void (*f)(void));
//locally used functions
int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len);
off_t lock_test(int fd, int type, off_t *offset, int whence, off_t *len);
#define REG_READONLYCACHE TEXT("Software\\Microsoft\\Internet Explorer\\Unix\\ReadOnlyCacheWarning")
#define REG_READONLYCACHEKEY TEXT("ShowCacheWarning")
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#define SECONDSINDAY 86400
#define REG_READONLYCACHE TEXT("Software\\Microsoft\\Internet Explorer\\Unix\\ReadOnlyCacheWarning")
#define REG_READONLYCACHEKEY TEXT("ShowCacheWarning")
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#define SECONDSINDAY 86400
// lock region relative to whence starting at offset upto len bytes
int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) {
struct flock lock;
lock.l_type = type; //F_RDLCK, F_WRLCK, F_UNLCK
lock.l_start = offset; //byte offset, relative to l_whence
lock.l_whence = whence; //SEEK_SET, SEEK_CUR, SEEK_END
lock.l_len = len; //#bytes (0 means to EOF)
return( fcntl(fd, cmd, &lock) );
}
// test region for locks relative to whence starting at offset for len bytes
off_t lock_test(int fd, int type, off_t *offset, int whence, off_t *len) {
struct flock lock;
lock.l_type = type; //F_RDLCK, F_WRLCK, F_UNLCK
lock.l_start = *offset; //byte offset, relative to l_whence
lock.l_whence = whence; //SEEK_SET, SEEK_CUR, SEEK_END
lock.l_len = *len; // #bytes (0 means to EOF)
if (fcntl(fd, F_GETLK, &lock) < 0)
return(-1);
if (lock.l_type == F_UNLCK)
return(0); // nobody has lock in this region
else if (lock.l_type == F_RDLCK) {
*offset = lock.l_start;
*len = lock.l_len;
return(lock.l_start); // byte offset of host with read lock
} else { // dont support extended semantics of
return(-1); // write lock yet
}
}
extern "C" void unixCleanupWininetCacheLockFile()
{
// if(!g_ReadOnlyCaches)
//unlink(szLockDBName);
}
BOOL CreateAtomicCacheLockFile(BOOL *pfReadOnlyCaches, char **pszLockingHost)
{
int fdlockdbf, fdlock, envLen, hostbynameerr;
off_t IPOffset=0, IPLen=0, ownIPOffset, ownIPLen;
char *hostname, hostbynamebuf[512];
char szLockFileName[MAX_PATH+1], szLockDBName[MAX_PATH+1];
struct hostent hostbynameresult;
#ifdef ux10
struct hostent_data hostentdata;
#endif
char *pEnv = getenv("MWUSER_DIRECTORY");
/* Don't process the ielock file for Mainwin Lite programs */
if (MwIsInitLite())
goto Cleanup;
if (pEnv == 0)
return FALSE;
envLen = strlen(pEnv);
if (envLen > MAX_PATH-256)
return FALSE;
strcpy(szLockFileName, pEnv);
if (szLockFileName[envLen-1] != '/') {
szLockFileName[envLen] = '/';
szLockFileName[envLen+1] = 0x00;
}
strcpy(szLockDBName, pEnv);
if (szLockDBName[envLen-1] != '/') {
szLockDBName[envLen] = '/';
szLockDBName[envLen+1] = 0x00;
}
strcat(szLockFileName, LF);
strcat(szLockDBName, LOCKDBF);
hostname = (char *)malloc(256*sizeof(char));
if ((hostname == NULL) || (gethostname(hostname, 256) == -1)) {
*pfReadOnlyCaches = TRUE;
return FALSE;
}
#ifdef sunos5
if (!(gethostbyname_r(hostname, &hostbynameresult, hostbynamebuf,
sizeof(hostbynamebuf), &hostbynameerr))) {
*pfReadOnlyCaches = TRUE;
return FALSE;
}
#endif
#ifdef ux10
if (gethostbyname_r(hostname, &hostbynameresult, &hostentdata) < 0) {
*pfReadOnlyCaches = TRUE;
return FALSE;
}
#endif
struct in_addr *ptr = (struct in_addr *)*hostbynameresult.h_addr_list;
ownIPOffset = inet_netof(*ptr);
ownIPLen = inet_lnaof(*ptr);
if ((fdlock = open(szLockFileName, O_WRONLY|O_CREAT|O_EXCL, FILE_MODE)) < 0) {
if (errno == EEXIST) {
if ((fdlock = open(szLockFileName, O_WRONLY)) < 0) {
*pfReadOnlyCaches = TRUE;
return FALSE;
}
} else {
*pfReadOnlyCaches = TRUE;
return FALSE;
}
}
if (writew_lock(fdlock, 0, SEEK_SET, 0) < 0) {
*pfReadOnlyCaches = TRUE;
return FALSE;
}
/*under this lock, now do all the examination of szLockDBName*/
if ((fdlockdbf = open(szLockDBName, O_RDWR|O_CREAT|O_EXCL, FILE_MODE)) < 0) {
if (errno == EEXIST) {
if ((fdlockdbf = open(szLockDBName, O_RDWR)) < 0) {
*pfReadOnlyCaches = TRUE;
un_lock(fdlock, 0, SEEK_SET, 0);
return FALSE;
}
} else {
*pfReadOnlyCaches = TRUE;
un_lock(fdlock, 0, SEEK_SET, 0);
return FALSE;
}
}
/* check entire file for locking */
if ((can_writelock(fdlockdbf, &IPOffset, SEEK_SET, &IPLen)) >= 0) {
if ((IPOffset == 0) || ((IPOffset == ownIPOffset) && (IPLen == ownIPLen))){
// either no IE writing to cache or IE on own host writing to cache
// (IP address is identical)..either way we have write access
*pfReadOnlyCaches = FALSE;
*pszLockingHost = hostname;
//lock at "network part" position for "host part" bytes
read_lock(fdlockdbf, ownIPOffset, SEEK_SET, ownIPLen);
un_lock(fdlock, 0, SEEK_SET, 0);
return TRUE;
} else {
//some other host writing to cache
*pfReadOnlyCaches = TRUE;
u_long addr = inet_addr(inet_ntoa(inet_makeaddr(IPOffset, IPLen)));
struct hostent * hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
if (!hp)
; //cant find hostname from offset & length of locked bytes..
else
*pszLockingHost = hp->h_name;
un_lock(fdlock, 0, SEEK_SET, 0);
return TRUE;
}
} else {
//can_writelock returned -1 with some fcntl error
*pfReadOnlyCaches = TRUE;
un_lock(fdlock, 0, SEEK_SET, 0);
return FALSE;
}
Cleanup:
return TRUE;
}
BOOL DeleteAtomicCacheLockFile()
{
/* Don't process for MainWin Lite programs */
/* Right now, the code below does not make sense because all
* we do is return TRUE. So, commenting out this code for now.
*/
#if 0
if (MwIsInitLite())
goto Cleanup;
Cleanup:
#endif /* 0 */
//unlink(szLockDBName);
return TRUE;
}
#if 0 // Back out till we get a consensus on this
BOOL CALLBACK ReadOnlyCache_DlgProc(HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam) {
switch (uMsg) {
case WM_INITDIALOG:
{
LPTSTR lpszMessageStr = (LPTSTR)lParam;
TCHAR pszText[MAX_PATH];
TCHAR pszFormattedText[MAX_PATH];
if (lpszMessageStr)
{
if (LoadString(GlobalDllHandle,
IDS_READONLYCACHE,
pszText,
ARRAYSIZE(pszText))) {
wsprintf(pszFormattedText,pszText, lpszMessageStr);
SetDlgItemText(hDlg, IDC_READONLYCACHE, pszFormattedText);
}
}
SetFocus(GetDlgItem(hDlg, IDOK));
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
{
if (IsDlgButtonChecked(hDlg, IDC_DONT_WANT_WARNING))
EndDialog(hDlg, 1);
else
EndDialog(hDlg, 0);
break;
}
default:
return FALSE;
}
return TRUE;
case WM_CLOSE:
{
if (IsDlgButtonChecked(hDlg, IDC_DONT_WANT_WARNING))
EndDialog(hDlg, 1);
else
EndDialog(hDlg, 0);
}
return TRUE;
}
return FALSE;
}
void ShowReadOnlyCacheDialog(char* pszHostName) {
DWORD dwError = E_FAIL;
HKEY hKey = NULL;
DWORD dwValue = 0;
DWORD dwValueType;
DWORD dwValueSize = sizeof(DWORD);
if ((dwError = REGOPENKEYEX(HKEY_CURRENT_USER,
REG_READONLYCACHE,
0,
KEY_READ|KEY_WRITE,
&hKey)) != ERROR_SUCCESS)
{
goto Cleanup;
}
if ((dwError = RegQueryValueEx(hKey,
REG_READONLYCACHEKEY,
0,
&dwValueType,
(LPBYTE)&dwValue,
&dwValueSize)) != ERROR_SUCCESS)
{
goto Cleanup;
}
if (dwValue)
{
int fRet = 0;
if ((fRet = DialogBoxParam(GlobalDllHandle,
MAKEINTRESOURCE(IDD_READONLYCACHE),
NULL,
ReadOnlyCache_DlgProc,
(LPARAM)pszHostName)) < 0)
{
goto Cleanup;
}
/*
* we are here, because the registry told us to show this dialog.
* now, we check if fRet == TRUE, in which case we don't show this
* dialog in the future. And, we update the registry.
*/
if (fRet == 1) {
/* ShowCacheWarning will be set to False in the registry */
dwValue = 0;
/*
* we don't check for the error here, because we close the key next
* and if we did not save successfully, we will show this dialog again
*/
RegSetValueEx(hKey,
REG_READONLYCACHEKEY,
0,
dwValueType,
(LPBYTE)&dwValue,
dwValueSize);
}
}
Cleanup:
if (hKey)
REGCLOSEKEY(hKey);
return;
}
#endif