#include "flock.hxx" // #include #include #undef inet_ntoa #undef inet_addr #undef gethostname #undef gethostbyname #undef gethostbyaddr #include #include #include #include #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