// // Lookups an entry based on url string key. // If exists, locks the entry and hands out a managed handle representing a locked entry. // unsafe internal static SafeUnlockUrlCacheEntryFile LookupFile(Entry entry) { byte[] buffer = new byte[Entry.DefaultBufferSize]; int size = buffer.Length; SafeUnlockUrlCacheEntryFile handle = null; try { while (true) { fixed(byte *entryPtr = buffer) { //We may need to adjust the buffer size entry.Error = SafeUnlockUrlCacheEntryFile.GetAndLockFile(entry.Key, entryPtr, ref size, out handle); if (entry.Error == Status.Success) { entry.MaxBufferBytes = size; EntryFixup(entry, (EntryBuffer *)entryPtr, buffer); //The method is available in TRAVE return(handle); } if (entry.Error == Status.InsufficientBuffer) { if (size <= entry.MaxBufferBytes) { buffer = new byte[size]; continue; } } //some error has occured break; } } } catch (Exception e) { if (handle != null) { handle.Close(); } if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if (entry.Error == Status.Success) { entry.Error = Status.InternalError; } } return(null); }
internal static unsafe SafeUnlockUrlCacheEntryFile LookupFile(Entry entry) { byte[] buffer = new byte[0x800]; int length = buffer.Length; SafeUnlockUrlCacheEntryFile handle = null; try { try { Label_0011: fixed(byte *numRef = buffer) { entry.Error = SafeUnlockUrlCacheEntryFile.GetAndLockFile(entry.Key, numRef, ref length, out handle); if (entry.Error == Status.Success) { entry.MaxBufferBytes = length; EntryFixup(entry, (EntryBuffer *)numRef, buffer); return(handle); } if ((entry.Error == Status.InsufficientBuffer) && (length <= entry.MaxBufferBytes)) { buffer = new byte[length]; goto Label_0011; } } } finally { numRef = null; } } catch (Exception exception) { if (handle != null) { handle.Close(); } if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException)) { throw; } if (entry.Error == Status.Success) { entry.Error = Status.InternalError; } } return(null); }
// // Updates a Cached Entry metadata according to attibutes flags. // internal static Status Update(Entry newEntry, Entry_FC attributes) { // Currently WinInet does not support headers update, // hence don't need space for them although we'll need recreate a cache entry // if headers update is requested byte[] buffer = new byte[EntryBuffer.MarshalSize]; newEntry.Error = Status.Success; unsafe { fixed(byte *bytePtr = buffer) { EntryBuffer *ePtr = (EntryBuffer *)bytePtr; *ePtr = newEntry.Info; //set the version just in case ePtr->StructSize = EntryBuffer.MarshalSize; if ((attributes & Entry_FC.Headerinfo) == 0) { if (!UnsafeNclNativeMethods.UnsafeWinInetCache.SetUrlCacheEntryInfoW(newEntry.Key, bytePtr, attributes)) { newEntry.Error = (Status)Marshal.GetLastWin32Error(); } } else { // simulating headers update using Edited cache entry feature of WinInet Entry oldEntry = new Entry(newEntry.Key, newEntry.MaxBufferBytes); SafeUnlockUrlCacheEntryFile handle = null; bool wasEdited = false; try { // lock the entry and get the filename out. handle = LookupFile(oldEntry); if (handle == null) { //The same error would happen on update attributes, return it. newEntry.Error = oldEntry.Error; return(newEntry.Error); } //Copy strings from old entry that are not present in the method parameters newEntry.Filename = oldEntry.Filename; newEntry.OriginalUrl = oldEntry.OriginalUrl; newEntry.FileExt = oldEntry.FileExt; // We don't need to update this and some other attributes since will replace entire entry attributes &= ~Entry_FC.Headerinfo; //Copy attributes from an old entry that are not present in the method parameters if ((attributes & Entry_FC.Exptime) == 0) { newEntry.Info.ExpireTime = oldEntry.Info.ExpireTime; } if ((attributes & Entry_FC.Modtime) == 0) { newEntry.Info.LastModifiedTime = oldEntry.Info.LastModifiedTime; } if ((attributes & Entry_FC.Attribute) == 0) { newEntry.Info.EntryType = oldEntry.Info.EntryType; newEntry.Info.U.ExemptDelta = oldEntry.Info.U.ExemptDelta; if ((oldEntry.Info.EntryType & EntryType.StickyEntry) == EntryType.StickyEntry) { attributes |= (Entry_FC.Attribute | Entry_FC.ExemptDelta); } } // Those attributes will be taken care of by Commit() attributes &= ~(Entry_FC.Exptime | Entry_FC.Modtime); wasEdited = (oldEntry.Info.EntryType & EntryType.Edited) != 0; if (!wasEdited) { // Prevent the file from being deleted on entry Remove (kinda hack) oldEntry.Info.EntryType |= EntryType.Edited; // Recursion! if (Update(oldEntry, Entry_FC.Attribute) != Status.Success) { newEntry.Error = oldEntry.Error; return(newEntry.Error); } } } finally { if (handle != null) { handle.Close(); } } // At this point we try to delete the exisintg item and create a new one with the same // filename and the new headers. //We wish to ignore any errors from Remove since are going to replace the entry. Remove(oldEntry); if (Commit(newEntry) != Status.Success) { if (!wasEdited) { //revert back the original entry type oldEntry.Info.EntryType &= ~EntryType.Edited; Update(oldEntry, Entry_FC.Attribute); // Being already in error mode, cannot do much if Update fails. } return(newEntry.Error); } // Now see what's left in attributes change request. if (attributes != Entry_FC.None) { Update(newEntry, attributes); } //At this point newEntry.Error should contain the resulting status //and we replaced the entry in the cache with the same body //but different headers. Some more attributes may have changed as well. } } } return(newEntry.Error); }
internal static unsafe Status Update(Entry newEntry, Entry_FC attributes) { byte[] buffer = new byte[EntryBuffer.MarshalSize]; newEntry.Error = Status.Success; fixed(byte *numRef = buffer) { EntryBuffer *bufferPtr = (EntryBuffer *)numRef; bufferPtr[0] = newEntry.Info; bufferPtr->StructSize = EntryBuffer.MarshalSize; if ((attributes & Entry_FC.Headerinfo) == Entry_FC.None) { if (!UnsafeNclNativeMethods.UnsafeWinInetCache.SetUrlCacheEntryInfoW(newEntry.Key, numRef, attributes)) { newEntry.Error = (Status)Marshal.GetLastWin32Error(); } } else { Entry entry = new Entry(newEntry.Key, newEntry.MaxBufferBytes); SafeUnlockUrlCacheEntryFile file = null; bool flag = false; try { file = LookupFile(entry); if (file == null) { newEntry.Error = entry.Error; return(newEntry.Error); } newEntry.Filename = entry.Filename; newEntry.OriginalUrl = entry.OriginalUrl; newEntry.FileExt = entry.FileExt; attributes &= ~Entry_FC.Headerinfo; if ((attributes & Entry_FC.Exptime) == Entry_FC.None) { newEntry.Info.ExpireTime = entry.Info.ExpireTime; } if ((attributes & Entry_FC.Modtime) == Entry_FC.None) { newEntry.Info.LastModifiedTime = entry.Info.LastModifiedTime; } if ((attributes & Entry_FC.Attribute) == Entry_FC.None) { newEntry.Info.EntryType = entry.Info.EntryType; newEntry.Info.U.ExemptDelta = entry.Info.U.ExemptDelta; if ((entry.Info.EntryType & EntryType.StickyEntry) == EntryType.StickyEntry) { attributes |= Entry_FC.ExemptDelta | Entry_FC.Attribute; } } attributes &= ~(Entry_FC.Exptime | Entry_FC.Modtime); flag = (entry.Info.EntryType & EntryType.Edited) != 0; if (!flag) { entry.Info.EntryType |= EntryType.Edited; if (Update(entry, Entry_FC.Attribute) != Status.Success) { newEntry.Error = entry.Error; return(newEntry.Error); } } } finally { if (file != null) { file.Close(); } } Remove(entry); if (Commit(newEntry) != Status.Success) { if (!flag) { entry.Info.EntryType &= ~EntryType.Edited; Update(entry, Entry_FC.Attribute); } return(newEntry.Error); } if (attributes != Entry_FC.None) { Update(newEntry, attributes); } } } return(newEntry.Error); }