コード例 #1
0
ファイル: WinInetCache.cs プロジェクト: wenzai007/dotnet462
        //
        // Gets the headers and optionally other meta data out of a cached entry
        //
        // Whenever an empty line found in the buffer, the resulting array of
        // collections will grow in size
        //
        private static unsafe Status GetEntryHeaders(Entry entry, EntryBuffer *bufferPtr, byte[] buffer)
        {
            entry.Error    = Status.Success;
            entry.MetaInfo = null;

            //
            if (bufferPtr->_OffsetHeaderInfo == IntPtr.Zero || bufferPtr->HeaderInfoChars == 0 || (bufferPtr->EntryType & EntryType.UrlHistory) != 0)
            {
                return(Status.Success);
            }

            int bufferCharLength = bufferPtr->HeaderInfoChars + ((int)(bufferPtr->_OffsetHeaderInfo)) / c_CharSz;

            if (bufferCharLength * c_CharSz > entry.MaxBufferBytes)
            {
                // WinInet

                bufferCharLength = entry.MaxBufferBytes / c_CharSz;
            }
            //WinInet may put terminating nulls at the end of the buffer, remove them.
            while (((char *)bufferPtr)[bufferCharLength - 1] == 0)
            {
                --bufferCharLength;
            }
            entry.MetaInfo = Encoding.Unicode.GetString(buffer, (int)bufferPtr->_OffsetHeaderInfo, (bufferCharLength - (int)bufferPtr->_OffsetHeaderInfo / 2) * 2);
            return(entry.Error);
        }
コード例 #2
0
        //
        // Gets the headers and optionally other meta data out of a cached entry
        //
        // Whenever an empty line found in the buffer, the resulting array of
        // collections will grow in size
        //
        private static unsafe Status GetEntryHeaders(Entry entry, EntryBuffer *bufferPtr, byte[] buffer)
        {
            entry.Error    = Status.Success;
            entry.MetaInfo = null;

            //
            if (bufferPtr->_OffsetHeaderInfo == IntPtr.Zero || bufferPtr->HeaderInfoChars == 0 || (bufferPtr->EntryType & EntryType.UrlHistory) != 0)
            {
                return(Status.Success);
            }

            int bufferCharLength = bufferPtr->HeaderInfoChars + ((int)(bufferPtr->_OffsetHeaderInfo)) / c_CharSz;

            if (bufferCharLength * c_CharSz > entry.MaxBufferBytes)
            {
                // WinInet bug? They may report offset+HeaderInfoChars as a greater value than MaxBufferBytes as total buffer size.
                // Actually, the last one seems to be accurate based on the data we have provided for Commit.
                bufferCharLength = entry.MaxBufferBytes / c_CharSz;
            }
            //WinInet may put terminating nulls at the end of the buffer, remove them.
            while (((char *)bufferPtr)[bufferCharLength - 1] == 0)
            {
                --bufferCharLength;
            }
            entry.MetaInfo = Encoding.Unicode.GetString(buffer, (int)bufferPtr->_OffsetHeaderInfo, (bufferCharLength - (int)bufferPtr->_OffsetHeaderInfo / 2) * 2);
            return(entry.Error);
        }
コード例 #3
0
 private static unsafe Status EntryFixup(Entry entry, EntryBuffer *bufferPtr, byte[] buffer)
 {
     bufferPtr._OffsetExtension     = (bufferPtr._OffsetExtension == IntPtr.Zero) ? IntPtr.Zero : ((IntPtr)((long)((((void *)bufferPtr._OffsetExtension) - bufferPtr) / 1)));
     bufferPtr._OffsetFileName      = (bufferPtr._OffsetFileName == IntPtr.Zero) ? IntPtr.Zero : ((IntPtr)((long)((((void *)bufferPtr._OffsetFileName) - bufferPtr) / 1)));
     bufferPtr._OffsetHeaderInfo    = (bufferPtr._OffsetHeaderInfo == IntPtr.Zero) ? IntPtr.Zero : ((IntPtr)((long)((((void *)bufferPtr._OffsetHeaderInfo) - bufferPtr) / 1)));
     bufferPtr._OffsetSourceUrlName = (bufferPtr._OffsetSourceUrlName == IntPtr.Zero) ? IntPtr.Zero : ((IntPtr)((long)((((void *)bufferPtr._OffsetSourceUrlName) - bufferPtr) / 1)));
     entry.Info        = bufferPtr[0];
     entry.OriginalUrl = GetEntryBufferString((void *)bufferPtr, (int)bufferPtr._OffsetSourceUrlName);
     entry.Filename    = GetEntryBufferString((void *)bufferPtr, (int)bufferPtr._OffsetFileName);
     entry.FileExt     = GetEntryBufferString((void *)bufferPtr, (int)bufferPtr._OffsetExtension);
     return(GetEntryHeaders(entry, bufferPtr, buffer));
 }
コード例 #4
0
        //
        // Does the fixup of the returned buffer by converting internal pointer to offsets
        // it also does copying of non-string values from unmanaged buffer to Entry.Buffer members
        //
        unsafe private static Status EntryFixup(Entry entry, EntryBuffer *bufferPtr, byte[] buffer)
        {
            unchecked {
                bufferPtr->_OffsetExtension     = bufferPtr->_OffsetExtension == IntPtr.Zero? IntPtr.Zero: (IntPtr)((byte *)bufferPtr->_OffsetExtension - (byte *)bufferPtr);
                bufferPtr->_OffsetFileName      = bufferPtr->_OffsetFileName == IntPtr.Zero? IntPtr.Zero: (IntPtr)((byte *)bufferPtr->_OffsetFileName - (byte *)bufferPtr);
                bufferPtr->_OffsetHeaderInfo    = bufferPtr->_OffsetHeaderInfo == IntPtr.Zero? IntPtr.Zero: (IntPtr)((byte *)bufferPtr->_OffsetHeaderInfo - (byte *)bufferPtr);
                bufferPtr->_OffsetSourceUrlName = bufferPtr->_OffsetSourceUrlName == IntPtr.Zero? IntPtr.Zero: (IntPtr)((byte *)bufferPtr->_OffsetSourceUrlName - (byte *)bufferPtr);

                // Get a managed EntryBuffer copy out of byte[]
                entry.Info        = *bufferPtr;
                entry.OriginalUrl = GetEntryBufferString(bufferPtr, (int)(bufferPtr->_OffsetSourceUrlName));
                entry.Filename    = GetEntryBufferString(bufferPtr, (int)(bufferPtr->_OffsetFileName));
                entry.FileExt     = GetEntryBufferString(bufferPtr, (int)(bufferPtr->_OffsetExtension));
            }
            return(GetEntryHeaders(entry, bufferPtr, buffer));
        }
コード例 #5
0
        private static unsafe Status GetEntryHeaders(Entry entry, EntryBuffer *bufferPtr, byte[] buffer)
        {
            entry.Error    = Status.Success;
            entry.MetaInfo = null;
            if (((bufferPtr._OffsetHeaderInfo == IntPtr.Zero) || (bufferPtr.HeaderInfoChars == 0)) || ((bufferPtr.EntryType & EntryType.UrlHistory) != 0))
            {
                return(Status.Success);
            }
            int num = bufferPtr.HeaderInfoChars + (((int)bufferPtr._OffsetHeaderInfo) / 2);

            if ((num * 2) > entry.MaxBufferBytes)
            {
                num = entry.MaxBufferBytes / 2;
            }
            while (*(((ushort *)(bufferPtr + ((num - 1) * 2)))) == 0)
            {
                num--;
            }
            entry.MetaInfo = Encoding.Unicode.GetString(buffer, (int)bufferPtr._OffsetHeaderInfo, (num - (((int)bufferPtr._OffsetHeaderInfo) / 2)) * 2);
            return(entry.Error);
        }
コード例 #6
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);
        }
コード例 #7
0
        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);
        }