Ejemplo n.º 1
0
        //
        // 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);
        }
Ejemplo n.º 3
0
        //
        // 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);
        }