예제 #1
0
        private void AsyncReadPageCallback<TContext>(uint errorCode, uint numBytes, NativeOverlapped* overlap)
        {
            if (errorCode != 0)
            {
                Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode);
            }

            PageAsyncReadResult<TContext> result = (PageAsyncReadResult<TContext>)Overlapped.Unpack(overlap).AsyncResult;

            if (Interlocked.Decrement(ref result.count) == 1)
            {
                // We will be issuing another I/O, so free this overlap
                Overlapped.Free(overlap);

                long ptr = (long)pointers[result.page % BufferSize];
                // Correct for page 0 of HLOG
                if (result.page == 0)
                    ptr += Constants.kFirstValidAddress;

                long minObjAddress = long.MaxValue;
                long maxObjAddress = long.MinValue;

                while (ptr < (long)pointers[result.page % BufferSize] + PageSize)
                {
                    if (!Layout.GetInfo(ptr)->Invalid)
                    {
                        if (Key.HasObjectsToSerialize())
                        {
                            Key* key = Layout.GetKey(ptr);
                            var addr = ((AddressInfo*)key)->Address;
                            if (addr < minObjAddress) minObjAddress = addr;
                            addr += ((AddressInfo*)key)->Size;
                            if (addr > maxObjAddress) maxObjAddress = addr;
                        }

                        if (Value.HasObjectsToSerialize())
                        {
                            Value* value = Layout.GetValue(ptr);
                            var addr = ((AddressInfo*)value)->Address;
                            if (addr < minObjAddress) minObjAddress = addr;
                            addr += ((AddressInfo*)value)->Size;
                            if (addr > maxObjAddress) maxObjAddress = addr;
                        }
                    }
                    ptr += Layout.GetPhysicalSize(ptr);
                }

                // Object log fragment should be aligned by construction
                Debug.Assert(minObjAddress % sectorSize == 0);

                var to_read = (int)(maxObjAddress - minObjAddress);
                var objBuffer = ioBufferPool.Get(to_read);
                result.freeBuffer1 = objBuffer;
                var alignedLength = (to_read + (sectorSize - 1)) & ~(sectorSize - 1);

                // Request objects from objlog
                result.objlogDevice.ReadAsync(
                    (int)(result.page >> (LogSegmentSizeBits-LogPageSizeBits)),
                    (ulong)minObjAddress, 
                    (IntPtr)objBuffer.aligned_pointer, (uint)alignedLength, AsyncReadPageCallback<TContext>, result);
            }
            else
            {
                // Load objects from buffer into memory
                long ptr = (long)pointers[result.page % BufferSize];
                // Correct for page 0 of HLOG
                if (result.page == 0)
                    ptr += Constants.kFirstValidAddress;

                MemoryStream ms = new MemoryStream(result.freeBuffer1.buffer);
                ms.Seek(result.freeBuffer1.offset + result.freeBuffer1.valid_offset, SeekOrigin.Begin);

                while (ptr < (long)pointers[result.page % BufferSize] + PageSize)
                {
                    if (!Layout.GetInfo(ptr)->Invalid)
                    {
                        if (Key.HasObjectsToSerialize())
                        {
                            Key.Deserialize(Layout.GetKey(ptr), ms);
                        }

                        if (Value.HasObjectsToSerialize())
                        {
                            Value.Deserialize(Layout.GetValue(ptr), ms);
                        }
                    }
                    ptr += Layout.GetPhysicalSize(ptr);
                }
                ms.Dispose();

                result.Free();

                // Call the "real" page read callback
                result.callback(errorCode, numBytes, overlap);
            }
           
        }
예제 #2
0
        unsafe private static void AsyncPSCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped)
        {
            // Unpack overlapped
            Overlapped overlapped = Overlapped.Unpack(pOverlapped);
            // Free the overlapped struct in EndRead/EndWrite.

            // Extract async result from overlapped 
            PipeStreamAsyncResult asyncResult = (PipeStreamAsyncResult)overlapped.AsyncResult;
            asyncResult._numBytes = (int)numBytes;

            // Allow async read to finish
            if (!asyncResult._isWrite)
            {
                if (errorCode == Interop.mincore.Errors.ERROR_BROKEN_PIPE ||
                    errorCode == Interop.mincore.Errors.ERROR_PIPE_NOT_CONNECTED ||
                    errorCode == Interop.mincore.Errors.ERROR_NO_DATA)
                {
                    errorCode = 0;
                    numBytes = 0;
                }
            }

            // For message type buffer.
            if (errorCode == Interop.mincore.Errors.ERROR_MORE_DATA)
            {
                errorCode = 0;
                asyncResult._isMessageComplete = false;
            }
            else
            {
                asyncResult._isMessageComplete = true;
            }

            asyncResult._errorCode = (int)errorCode;

            // Call the user-provided callback.  It can and often should
            // call EndRead or EndWrite.  There's no reason to use an async 
            // delegate here - we're already on a threadpool thread.  
            // IAsyncResult's completedSynchronously property must return
            // false here, saying the user callback was called on another thread.
            asyncResult._completedSynchronously = false;
            asyncResult._isComplete = true;

            // The OS does not signal this event.  We must do it ourselves.
            ManualResetEvent wh = asyncResult._waitHandle;
            if (wh != null)
            {
                Debug.Assert(!wh.GetSafeWaitHandle().IsClosed, "ManualResetEvent already closed!");
                bool r = wh.Set();
                Debug.Assert(r, "ManualResetEvent::Set failed!");
                if (!r)
                {
                    throw Win32Marshal.GetExceptionForLastWin32Error();
                }
            }

            AsyncCallback callback = asyncResult._userCallback;
            if (callback != null)
            {
                callback(asyncResult);
            }
        }
예제 #3
0
        protected void AsyncGetFromDiskCallback(
            uint errorCode,
            uint numBytes,
            NativeOverlapped *overlap)
        {
            if (errorCode != 0)
            {
                Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode);
            }

            var result = (AsyncGetFromDiskResult <AsyncIOContext>)Overlapped.Unpack(overlap).AsyncResult;

            Interlocked.Decrement(ref numPendingReads);

            var ctx    = result.context;
            var record = ctx.record.GetValidPointer();

            if (Layout.HasTotalRecord(record, ctx.record.available_bytes, out int requiredBytes))
            {
                //We have the complete record.
                if (RetrievedObjects(record, ctx))
                {
                    if (Key.Equals(ctx.key, Layout.GetKey((long)record)))
                    {
                        //The keys are same, so I/O is complete
                        // ctx.record = result.record;
                        ctx.callbackQueue.Add(ctx);
                    }
                    else
                    {
                        var oldAddress = ctx.logicalAddress;

                        //keys are not same. I/O is not complete
                        ctx.logicalAddress = ((RecordInfo *)record)->PreviousAddress;
                        if (ctx.logicalAddress != Constants.kInvalidAddress)
                        {
                            // Delete key, value, record
                            if (Key.HasObjectsToSerialize())
                            {
                                var physicalAddress = (long)ctx.record.GetValidPointer();
                                Key.Free(Layout.GetKey(physicalAddress));
                            }
                            if (Value.HasObjectsToSerialize())
                            {
                                var physicalAddress = (long)ctx.record.GetValidPointer();
                                Value.Free(Layout.GetValue(physicalAddress));
                            }
                            ctx.record.Return();
                            AsyncGetFromDisk(ctx.logicalAddress, requiredBytes, AsyncGetFromDiskCallback, ctx);
                        }
                        else
                        {
                            ctx.callbackQueue.Add(ctx);
                        }
                    }
                }
            }
            else
            {
                ctx.record.Return();
                AsyncGetFromDisk(ctx.logicalAddress, requiredBytes, AsyncGetFromDiskCallback, ctx);
            }

            Overlapped.Free(overlap);
        }
        /// <include file='doc\FileSystemWatcher.uex' path='docs/doc[@for="FileSystemWatcher.CompletionStatusChanged"]/*' />
        /// <devdoc>
        ///     Callback from thread pool.
        /// </devdoc>
        /// <internalonly/>
        private unsafe void CompletionStatusChanged(uint errorCode, uint numBytes, NativeOverlapped *overlappedPointer)
        {
            Overlapped overlapped    = Overlapped.Unpack(overlappedPointer);
            ulong      bufferPtrTemp = ((ulong)overlapped.OffsetHigh) << 32;

            bufferPtrTemp = bufferPtrTemp | (0x00000000ffffffff & (ulong)overlapped.OffsetLow);
            IntPtr bufferPtr = (IntPtr)bufferPtrTemp;

            try {
                if (stopListening)
                {
                    return;
                }

                lock (this) {
                    if (errorCode != 0)
                    {
                        if (errorCode == 995 /* ERROR_OPERATION_ABORTED */)
                        {
                            //Win2000 inside a service the first completion status is false
                            //cannot return without monitoring again.
                            //NOTE, stefanph: Because this return statement is inside a try/finally block,
                            //the finally block will execute. It does restart the monitoring.
                            return;
                        }
                        else
                        {
                            OnError(new ErrorEventArgs(new Win32Exception((int)errorCode)));
                            EnableRaisingEvents = false;
                            return;
                        }
                    }

                    if (numBytes == 0)
                    {
                        NotifyInternalBufferOverflowEvent();
                    }
                    else    // Else, parse each of them and notify appropriate delegates

                    /******
                     *  Format for the buffer is the following C struct:
                     *
                     *  typedef struct _FILE_NOTIFY_INFORMATION {
                     *     DWORD NextEntryOffset;
                     *     DWORD Action;
                     *     DWORD FileNameLength;
                     *     WCHAR FileName[1];
                     *  } FILE_NOTIFY_INFORMATION;
                     *
                     *  NOTE1: FileNameLength is length in bytes.
                     *  NOTE2: The Filename is a Unicode string that's NOT NULL terminated.
                     *  NOTE3: A NextEntryOffset of zero means that it's the last entry
                     *******/

                    // Parse the file notify buffer
                    {
                        int    offset = 0;
                        int    nextOffset, action, nameLength;
                        string oldName = null;

                        do
                        {
                            // Get next offset
                            nextOffset = Marshal.ReadInt32((IntPtr)((long)bufferPtr + offset));

                            // Get change flag
                            action = Marshal.ReadInt32((IntPtr)((long)bufferPtr + offset + 4));

                            // Get filename length (in bytes)
                            nameLength = Marshal.ReadInt32((IntPtr)((long)bufferPtr + offset + 8));

                            string name = Marshal.PtrToStringUni((IntPtr)((long)bufferPtr + offset + 12), nameLength / 2).ToLower(CultureInfo.InvariantCulture);

                            /* A slightly convoluted piece of code follows.  Here's what's happening:
                             *
                             * We wish to collapse the poorly done rename notifications from the
                             * ReadDirectoryChangesW API into a nice rename event. So to do that,
                             * it's assumed that a FILE_ACTION_RENAMED_OLD_NAME will be followed
                             * immediately by a FILE_ACTION_RENAMED_NEW_NAME in the buffer, which is
                             * all that the following code is doing.
                             *
                             * On a FILE_ACTION_RENAMED_OLD_NAME, it asserts that no previous one existed
                             * and saves its name.  If there are no more events in the buffer, it'll
                             * assert and fire a RenameEventArgs with the Name field null.
                             *
                             * If a NEW_NAME action comes in with no previous OLD_NAME, we assert and fire
                             * a rename event with the OldName field null.
                             *
                             * If the OLD_NAME and NEW_NAME actions are indeed there one after the other,
                             * we'll fire the RenamedEventArgs normally and clear oldName.
                             *
                             * If the OLD_NAME is followed by another action, we assert and then fire the
                             * rename event with the Name field null and then fire the next action.
                             *
                             * In case it's not a OLD_NAME or NEW_NAME action, we just fire the event normally.
                             *
                             * (Phew!)
                             */

                            // If the action is RENAMED_FROM, save the name of the file
                            if (action == Direct.FILE_ACTION_RENAMED_OLD_NAME)
                            {
                                Debug.Assert(oldName == null, "FileSystemWatcher: Two FILE_ACTION_RENAMED_OLD_NAME " +
                                             "in a row!  [" + oldName + "], [ " + name + "]");

                                oldName = name;
                            }
                            else if (action == Direct.FILE_ACTION_RENAMED_NEW_NAME)
                            {
                                if (oldName != null)
                                {
                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
                                    oldName = null;
                                }
                                else
                                {
                                    Debug.Assert(false, "FileSystemWatcher: FILE_ACTION_RENAMED_NEW_NAME with no" +
                                                 "old name! [ " + name + "]");

                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
                                    oldName = null;
                                }
                            }
                            else
                            {
                                if (oldName != null)
                                {
                                    Debug.Assert(false, "FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" +
                                                 "new name!  [" + oldName + "]");

                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
                                    oldName = null;
                                }

                                // Notify each file of change
                                NotifyFileSystemEventArgs(action, name);
                            }

                            offset += nextOffset;
                        } while (nextOffset != 0);

                        if (oldName != null)
                        {
                            Debug.Assert(false, "FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" +
                                         "new name!  [" + oldName + "]");

                            NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
                            oldName = null;
                        }
                    }
                }
            }
            finally {
                Overlapped.Free(overlappedPointer);
                if (stopListening || runOnce)
                {
                    if (bufferPtr != (IntPtr)0)
                    {
                        Marshal.FreeHGlobal(bufferPtr);
                    }
                }
                else
                {
                    Monitor(bufferPtr);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// IOCompletion callback for page flush
        /// </summary>
        /// <param name="errorCode"></param>
        /// <param name="numBytes"></param>
        /// <param name="overlap"></param>
        private void AsyncFlushPartialObjectLogCallback <TContext>(uint errorCode, uint numBytes, NativeOverlapped *overlap)
        {
            if (errorCode != 0)
            {
                Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode);
            }

            // Set the page status to flushed
            PageAsyncFlushResult <TContext> result = (PageAsyncFlushResult <TContext>)Overlapped.Unpack(overlap).AsyncResult;

            result.done.Set();

            Overlapped.Free(overlap);
        }
예제 #6
0
        private static unsafe Task <TOut?> ExplicitDeviceIoControlAsync <TIn, TOut>(SafeFileHandle hDevice, uint ioControlCode, TIn?inVal, TOut?outVal) where TIn : struct where TOut : struct
        {
            ThreadPool.BindHandle(hDevice);
            var tcs              = new TaskCompletionSource <TOut?>();
            var buffer           = Pack(inVal, outVal);
            var nativeOverlapped = new Overlapped().Pack((code, bytes, overlap) =>
            {
                try
                {
                    switch (code)
                    {
                    case Win32Error.ERROR_SUCCESS:
                        outVal = Unpack <TIn, TOut>(buffer).Item2;
                        tcs.TrySetResult(outVal);
                        break;

                    case Win32Error.ERROR_OPERATION_ABORTED:
                        tcs.TrySetCanceled();
                        break;

                    default:
                        tcs.TrySetException(new Win32Exception((int)code));
                        break;
                    }
                }
                finally
                {
                    Overlapped.Unpack(overlap);
                    Overlapped.Free(overlap);
                }
            }, buffer);

            var unpack = true;

            try
            {
                var inSz = Marshal.SizeOf(typeof(TIn));
                fixed(byte *pIn = buffer, pOut = &buffer[inSz])
                {
                    uint bRet;
                    var  ret = DeviceIoControl(hDevice, ioControlCode, pIn, (uint)inSz, pOut, (uint)(buffer.Length - inSz), out bRet, nativeOverlapped);

                    if (ret)
                    {
                        outVal = Unpack <TIn, TOut>(buffer).Item2;
                        tcs.SetResult(outVal);
                        return(tcs.Task);
                    }
                }

                var lastWin32Error = Marshal.GetLastWin32Error();
                if (lastWin32Error != Win32Error.ERROR_IO_PENDING && lastWin32Error != Win32Error.ERROR_SUCCESS)
                {
                    throw new Win32Exception(lastWin32Error);
                }
                unpack = false;
                return(tcs.Task);
            }
            finally
            {
                if (unpack)
                {
                    Overlapped.Unpack(nativeOverlapped);
                    Overlapped.Free(nativeOverlapped);
                }
            }
        }
예제 #7
0
        private static unsafe void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
            ThreadPoolBoundHandleOverlapped overlapped = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(nativeOverlapped);

            //
            // The Win32 thread pool implementation of ThreadPoolBoundHandle does not permit reuse of NativeOverlapped
            // pointers without freeing them and allocating new a new one.  We need to ensure that code using the CLR
            // ThreadPool implementation follows those rules.
            //
            if (overlapped._completed)
            {
                throw new InvalidOperationException(SR.InvalidOperation_NativeOverlappedReused);
            }

            overlapped._completed = true;

            if (overlapped._boundHandle == null)
            {
                throw new InvalidOperationException(SR.Argument_NativeOverlappedAlreadyFree);
            }

            overlapped._userCallback(errorCode, numBytes, nativeOverlapped);
        }
예제 #8
0
        public static unsafe Task WriteAsync(SafeFileHandle hFile, long fileOffset, ArraySegment <byte> bytes)
        {
            if (fileOffset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(fileOffset));
            }

            var asyncResult = new AsyncResult();
            int low         = (int)(fileOffset & 0xFFFFFFFF);
            int high        = (int)(fileOffset >> 32);
            var o           = new Overlapped(low, high, IntPtr.Zero, asyncResult);

            fixed(byte *bufferBase = bytes.Array)
            {
                // https://docs.microsoft.com/en-us/dotnet/api/system.threading.overlapped.pack?view=netframework-4.7#System_Threading_Overlapped_Pack_System_Threading_IOCompletionCallback_System_Object_
                // The buffer or buffers specified in userData must be the same as those passed to the unmanaged operating system function that performs the asynchronous I/O.
                // The runtime pins the buffer or buffers specified in userData for the duration of the I/O operation.
                NativeOverlapped *pOverlapped = o.Pack(CompletionCallback, bytes.Array);
                bool needToFree = true;

                try
                {
                    if (WriteFile(hFile, bufferBase + bytes.Offset, bytes.Count, IntPtr.Zero, pOverlapped) != 0)
                    {
                        // Completed synchronously.

                        // The number of bytes transferred for the I/O request. The system sets this member if the request is completed without errors.
                        // https://msdn.microsoft.com/en-us/library/windows/desktop/ms684342(v=vs.85).aspx
                        int bytesWritten = (int)pOverlapped->InternalHigh.ToInt64();
                        if (bytesWritten != bytes.Count)
                        {
                            throw new EndOfStreamException("Could not write all the bytes.");
                        }

                        return(CompletedTask);
                    }
                    else
                    {
                        int systemErrorCode = Marshal.GetLastWin32Error();
                        if (systemErrorCode == ERROR_IO_DEVICE)
                        {
                            throw new IOException($"WriteFile failed with system error ERROR_IO_DEVICE", new Win32Exception(systemErrorCode));
                        }
                        else if (systemErrorCode == ERROR_IO_PENDING)
                        {
                            needToFree = false;
                        }
                        else
                        {
                            throw new Win32Exception(systemErrorCode, $"WriteFile failed with system error code:{systemErrorCode}");
                        }

                        return(asyncResult.CompletionSource.Value.Task.ContinueWith(t =>
                        {
                            if (t.Status == TaskStatus.RanToCompletion && t.Result != bytes.Count)
                            {
                                throw new EndOfStreamException("Could not write all the bytes.");
                            }

                            return t;
                        }));
                    }
                }
                finally
                {
                    if (needToFree)
                    {
                        Overlapped.Unpack(pOverlapped);
                        Overlapped.Free(pOverlapped);
                    }
                }
            }
        }
예제 #9
0
        /// <devdoc>
        ///     Callback from thread pool.
        /// </devdoc>
        /// <internalonly/>
        private unsafe void CompletionStatusChanged(uint errorCode, uint numBytes, NativeOverlapped *overlappedPointer)
        {
            Overlapped     overlapped  = Overlapped.Unpack(overlappedPointer);
            FSWAsyncResult asyncResult = (FSWAsyncResult)overlapped.AsyncResult;

            try
            {
                if (_stopListening)
                {
                    return;
                }

                lock (this)
                {
                    if (errorCode != 0)
                    {
                        if (errorCode == 995 /* ERROR_OPERATION_ABORTED */)
                        {
                            //Inside a service the first completion status is false
                            //cannot return without monitoring again.
                            //Because this return statement is inside a try/finally block,
                            //the finally block will execute. It does restart the monitoring.
                            return;
                        }
                        else
                        {
                            OnError(new ErrorEventArgs(new Win32Exception((int)errorCode)));
                            EnableRaisingEvents = false;
                            return;
                        }
                    }

                    // Ignore any events that occurred before this "session",
                    // so we don't get changed or error events after we
                    // told FSW to stop.
                    if (asyncResult.session != _currentSession)
                    {
                        return;
                    }


                    if (numBytes == 0)
                    {
                        NotifyInternalBufferOverflowEvent();
                    }
                    else
                    {  // Else, parse each of them and notify appropriate delegates
                       /******
                        *  Format for the buffer is the following C struct:
                        *
                        *  typedef struct _FILE_NOTIFY_INFORMATION {
                        *     DWORD NextEntryOffset;
                        *     DWORD Action;
                        *     DWORD FileNameLength;
                        *     WCHAR FileName[1];
                        *  } FILE_NOTIFY_INFORMATION;
                        *
                        *  NOTE1: FileNameLength is length in bytes.
                        *  NOTE2: The Filename is a Unicode string that's NOT NULL terminated.
                        *  NOTE3: A NextEntryOffset of zero means that it's the last entry
                        *******/

                        // Parse the file notify buffer:
                        int    offset = 0;
                        int    nextOffset, action, nameLength;
                        string oldName = null;
                        string name    = null;

                        do
                        {
                            fixed(byte *buffPtr = asyncResult.buffer)
                            {
                                // Get next offset:
                                nextOffset = *((int *)(buffPtr + offset));

                                // Get change flag:
                                action = *((int *)(buffPtr + offset + 4));

                                // Get filename length (in bytes):
                                nameLength = *((int *)(buffPtr + offset + 8));
                                name       = new string((char *)(buffPtr + offset + 12), 0, nameLength / 2);
                            }


                            /* A slightly convoluted piece of code follows.  Here's what's happening:
                             *
                             * We wish to collapse the poorly done rename notifications from the
                             * ReadDirectoryChangesW API into a nice rename event. So to do that,
                             * it's assumed that a FILE_ACTION_RENAMED_OLD_NAME will be followed
                             * immediately by a FILE_ACTION_RENAMED_NEW_NAME in the buffer, which is
                             * all that the following code is doing.
                             *
                             * On a FILE_ACTION_RENAMED_OLD_NAME, it asserts that no previous one existed
                             * and saves its name.  If there are no more events in the buffer, it'll
                             * assert and fire a RenameEventArgs with the Name field null.
                             *
                             * If a NEW_NAME action comes in with no previous OLD_NAME, we assert and fire
                             * a rename event with the OldName field null.
                             *
                             * If the OLD_NAME and NEW_NAME actions are indeed there one after the other,
                             * we'll fire the RenamedEventArgs normally and clear oldName.
                             *
                             * If the OLD_NAME is followed by another action, we assert and then fire the
                             * rename event with the Name field null and then fire the next action.
                             *
                             * In case it's not a OLD_NAME or NEW_NAME action, we just fire the event normally.
                             *
                             * (Phew!)
                             */

                            // If the action is RENAMED_FROM, save the name of the file
                            if (action == Direct.FILE_ACTION_RENAMED_OLD_NAME)
                            {
                                Debug.Assert(oldName == null, "FileSystemWatcher: Two FILE_ACTION_RENAMED_OLD_NAME " +
                                             "in a row!  [" + oldName + "], [ " + name + "]");

                                oldName = name;
                            }
                            else if (action == Direct.FILE_ACTION_RENAMED_NEW_NAME)
                            {
                                if (oldName != null)
                                {
                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
                                    oldName = null;
                                }
                                else
                                {
                                    Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_NEW_NAME with no" +
                                               "old name! [ " + name + "]");

                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
                                    oldName = null;
                                }
                            }
                            else
                            {
                                if (oldName != null)
                                {
                                    Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" +
                                               "new name!  [" + oldName + "]");

                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
                                    oldName = null;
                                }

                                // Notify each file of change
                                NotifyFileSystemEventArgs(action, name);
                            }

                            offset += nextOffset;
                        } while (nextOffset != 0);

                        if (oldName != null)
                        {
                            Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" +
                                       "new name!  [" + oldName + "]");

                            NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
                            oldName = null;
                        }
                    }
                }
            }
            finally
            {
                Overlapped.Free(overlappedPointer);
                if (!_stopListening)
                {
                    Monitor(asyncResult.buffer);
                }
            }
        }
예제 #10
0
        private static unsafe void WaitCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped *nativeOverlapped)
        {
            ListenerClientCertAsyncResult asyncResult = (ListenerClientCertAsyncResult)Overlapped.Unpack(nativeOverlapped).AsyncResult;
            HttpListenerRequest           asyncObject = (HttpListenerRequest)asyncResult.AsyncObject;
            object result = null;

            try
            {
                if (errorCode == 0xea)
                {
                    UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *requestBlob = asyncResult.RequestBlob;
                    asyncResult.Reset(numBytes + requestBlob->CertEncodedSize);
                    uint pBytesReceived = 0;
                    errorCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(asyncObject.HttpListenerContext.RequestQueueHandle, asyncObject.m_ConnectionId, 0, asyncResult.m_MemoryBlob, asyncResult.m_Size, &pBytesReceived, asyncResult.m_pOverlapped);
                    if ((errorCode == 0x3e5) || (errorCode == 0))
                    {
                        return;
                    }
                }
                if (errorCode != 0)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *memoryBlob = asyncResult.m_MemoryBlob;
                    if (memoryBlob != null)
                    {
                        if (memoryBlob->pCertEncoded != null)
                        {
                            try
                            {
                                byte[] destination = new byte[memoryBlob->CertEncodedSize];
                                Marshal.Copy((IntPtr)memoryBlob->pCertEncoded, destination, 0, destination.Length);
                                result = asyncObject.ClientCertificate = new X509Certificate2(destination);
                            }
                            catch (CryptographicException exception)
                            {
                                result = exception;
                            }
                            catch (SecurityException exception2)
                            {
                                result = exception2;
                            }
                        }
                        asyncObject.SetClientCertificateError((int)memoryBlob->CertFlags);
                    }
                }
            }
            catch (Exception exception3)
            {
                if (NclUtilities.IsFatal(exception3))
                {
                    throw;
                }
                result = exception3;
            }
            finally
            {
                if (errorCode != 0x3e5)
                {
                    asyncObject.ClientCertState = ListenerClientCertState.Completed;
                }
            }
            asyncResult.InvokeCallback(result);
        }