HttpWebListener()
        {
            int result =

                ComNetOS.IsWinNt ?

                UlSysApi.UlCreateAppPool(
                    ref m_AppPoolHandle,
                    string.Empty,
                    IntPtr.Zero,
                    UlConstants.UL_OPTION_OVERLAPPED)

            :

                UlVxdApi.UlCreateAppPool(
                    ref m_AppPoolHandle);

            if (result != NativeMethods.ERROR_SUCCESS)
            {
                throw new InvalidOperationException("UlCreateAppPool() failed, err#" + Convert.ToString(result));
            }

            //
            // we count the number of instances so that in the destructor we are
            // able to correctly call UlTerminate() and be gracefully shutdown the
            // driver when this process no longer needs it
            //

            m_InstancesCounter++;

            GlobalLog.Print("UlCreateAppPool() succesfull, AppPool handle is "
                            + Convert.ToString(m_AppPoolHandle));

            return;
        } // WebListener()
        RemoveUriPrefix(
            string uriPrefix)
        {
            if (!m_UriPrefixes.Contains(uriPrefix))
            {
                return(false);
            }

            int result =
                ComNetOS.IsWinNt ?

                UlSysApi.UlRemoveTransientUrl(
                    m_AppPoolHandle,
                    uriPrefix)

            :

                UlVxdApi.UlUnregisterUri(
                    m_AppPoolHandle,
                    uriPrefix);

            if (result != NativeMethods.ERROR_SUCCESS)
            {
                throw new InvalidOperationException("UlUnregisterUri() failed");
            }

            m_UriPrefixes.Remove(uriPrefix);

            return(true);
        } // RemoveUriPrefix()
        AddUriPrefix(
            string uriPrefix)
        {
            //check permissions for URI being listened
            (new WebPermission(NetworkAccess.Accept, uriPrefix)).Demand();

            int result =

                ComNetOS.IsWinNt ?

                UlSysApi.UlAddTransientUrl(
                    m_AppPoolHandle,
                    uriPrefix)

            :

                UlVxdApi.UlRegisterUri(
                    m_AppPoolHandle,
                    uriPrefix);

            if (result != NativeMethods.ERROR_SUCCESS)
            {
                throw new InvalidOperationException("UlRegisterUri() failed, err#" + Convert.ToString(result));
            }

            GlobalLog.Print("AddUriPrefix( " + uriPrefix + " ) handle:"
                            + Convert.ToString(m_AppPoolHandle));

            m_UriPrefixes.Add(uriPrefix);

            return(true);
        } // AddUriPrefix()
        Close()
        {
            RemoveAll();

            if (m_InstancesCounter-- == 0)
            {
                if (ComNetOS.IsWinNt)
                {
                    UlSysApi.UlTerminate();
                }
                else
                {
                    UlVxdApi.UlTerminate();
                }
            }

            return;
        } // Close()
        } // Position


        public override int Read(
            [In, Out] byte[] buffer,
            int offset,
            int count)
        {
            GlobalLog.Print("ListenerRequestStream.ReadCore() offset: " + Convert.ToString(offset) + " count:" + Convert.ToString(count));            int DataCopiedFromBuffer = 0;
            int DataCopiedFromDriver = 0;

            //
            // see if we still have some data in the buffer
            //

            if (m_BufferedDataExists)
            {
                //
                // start sending data in the buffer
                //

                DataCopiedFromBuffer =
                    Math.Min(
                        m_DataBuffer.Length - m_DataBufferOffset,
                        count);

                Buffer.BlockCopy(
                    m_DataBuffer,
                    m_DataBufferOffset,
                    buffer,
                    offset,
                    DataCopiedFromBuffer);

                //
                // update the offset for the buffered data for subsequent calls
                //

                m_DataBufferOffset  += DataCopiedFromBuffer;
                m_BufferedDataExists = m_DataBuffer.Length > m_DataBufferOffset;

                //
                // update offset and count in the buffer for subsequent calls
                //

                offset += DataCopiedFromBuffer;
                count  -= DataCopiedFromBuffer;
            }

            //
            // if all the data requested was handled by the buffered data we don't
            // need to call the driver for more, so we just return here
            //

            if (count <= 0 || !m_MoreToRead)
            {
                return(DataCopiedFromBuffer);
            }

            //
            // otherwise pin the buffer and make an unmanaged call to the driver to
            // read more entity body
            //

            GCHandle PinnedBuffer;
            IntPtr   AddrOfPinnedBuffer = IntPtr.Zero;

            PinnedBuffer       = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            AddrOfPinnedBuffer = PinnedBuffer.AddrOfPinnedObject();

            //
            // issue unmanaged blocking call
            //

            int result =
                ComNetOS.IsWinNt ?

                UlSysApi.UlReceiveEntityBody(
                    m_AppPoolHandle,
                    m_RequestId,
                    UlConstants.UL_RECEIVE_REQUEST_FLAG_COPY_BODY,
                    AddrOfPinnedBuffer,
                    count,
                    ref DataCopiedFromDriver,
                    IntPtr.Zero)

            :

                UlVxdApi.UlReceiveHttpRequestEntityBody(
                    m_AppPoolHandle,
                    m_RequestId,
                    0,
                    AddrOfPinnedBuffer,
                    count,
                    ref DataCopiedFromDriver,
                    IntPtr.Zero);

            PinnedBuffer.Free();

            if (result != NativeMethods.ERROR_SUCCESS && result != NativeMethods.ERROR_HANDLE_EOF)
            {
                //
                // Consider: move all Exception string to system.txt for localization
                //
                throw new InvalidOperationException("UlReceiveEntityBody() failed, err#" + Convert.ToString(result));
            }

            return(DataCopiedFromBuffer + DataCopiedFromDriver);
        } // Read()
        public override void Close()
        {
            if (m_Closed)
            {
                return;
            }
            m_Closed = true;

            //
            // we need to flush ul in order to tell it that we have no more data
            // to send in the entity body, and if we're chunk-encoding we need to
            // send the trailer chunk
            //

            if (m_SendChunked == true)
            {
                //
                // send the trailer
                //
            }

            int DataWritten = 0;

            int result =
                ComNetOS.IsWinNt ?

                UlSysApi.UlSendEntityBody(
                    m_AppPoolHandle,
                    m_RequestId,
                    0,
                    0,
                    IntPtr.Zero,
                    ref DataWritten,
                    IntPtr.Zero)

            :

                UlVxdApi.UlSendHttpResponseEntityBody(
                    m_AppPoolHandle,
                    m_RequestId,
                    0,
                    0,
                    IntPtr.Zero,
                    ref DataWritten,
                    IntPtr.Zero);

            GlobalLog.Print("UlSendHttpResponseEntityBody(0) DataWritten: " + Convert.ToString(DataWritten));

            //
            // ignore return value???
            //

            if (result != NativeMethods.ERROR_SUCCESS && result != NativeMethods.ERROR_HANDLE_EOF)
            {
                GlobalLog.Print("sync UlSendHttpResponseEntityBody(0) failed, err#" + Convert.ToString(result));

                // throw new InvalidOperationException( "UlSendHttpResponseEntityBody() failed, err#" + Convert.ToString( result ) );
            }

            return;
        } // Close()
        } // Position


        //
        // write a chunk of data to ul
        //

        public override void Write(
            byte[] buffer,
            int offset,
            int count)
        {
            GlobalLog.Print("ListenerResponseStream.WriteCore() offset: " + Convert.ToString(offset) + " count:" + Convert.ToString(count));

            if (m_ContentLength != -1 && m_ContentLength < count)
            {
                //
                // user can't send more data than specified in the ContentLength
                //

                throw new ProtocolViolationException(SR.GetString(SR.net_entitytoobig));
            }

            int DataToWrite = count;

            GCHandle PinnedBuffer       = new GCHandle();
            IntPtr   AddrOfPinnedBuffer = IntPtr.Zero;

            if (m_SendChunked)
            {
                string ChunkHeader = "0x" + Convert.ToString(count, 16);

                DataToWrite += ChunkHeader.Length + 4;

                AddrOfPinnedBuffer = Marshal.AllocHGlobal(DataToWrite);

                Marshal.Copy(ChunkHeader.ToCharArray(), 0, AddrOfPinnedBuffer, ChunkHeader.Length);
                Marshal.WriteInt16(AddrOfPinnedBuffer, ChunkHeader.Length, 0x0A0D);
                Marshal.Copy((byte[])buffer, offset, IntPtrHelper.Add(AddrOfPinnedBuffer, ChunkHeader.Length + 2), count);
                Marshal.WriteInt16(AddrOfPinnedBuffer, DataToWrite - 2, 0x0A0D);
            }
            else
            {
                //
                // pin the buffer and make an unmanaged call to the driver to
                // write more entity body
                //

                PinnedBuffer       = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                AddrOfPinnedBuffer = PinnedBuffer.AddrOfPinnedObject();
            }


            //
            // set up a UL_DATA_CHUNK structure to pass down to UL with pointers
            // to data to be written
            //

            IntPtr AddrOfPinnedEntityChunks = Marshal.AllocHGlobal(32);

            //
            // AddrOfPinnedBuffer and count go into a pEntityChunks structure
            //

            Marshal.WriteInt64(AddrOfPinnedEntityChunks, 0, 0);
            Marshal.WriteIntPtr(AddrOfPinnedEntityChunks, 8, AddrOfPinnedBuffer);
            Marshal.WriteInt32(AddrOfPinnedEntityChunks, 12, DataToWrite);
            Marshal.WriteInt64(AddrOfPinnedEntityChunks, 16, 0);
            Marshal.WriteInt64(AddrOfPinnedEntityChunks, 24, 0);

            GlobalLog.Print("Calling UlSendHttpResponseEntityBody: AddrOfPinnedEntityChunks:" + Convert.ToString(AddrOfPinnedEntityChunks)
                            + " AddrOfPinnedBuffer:" + Convert.ToString(AddrOfPinnedBuffer)
                            + " DataToWrite:" + Convert.ToString(DataToWrite));

            //
            // issue unmanaged blocking call
            //

            int DataWritten = 0;

            int result =
                ComNetOS.IsWinNt ?

                UlSysApi.UlSendEntityBody(
                    m_AppPoolHandle,
                    m_RequestId,
                    UlConstants.UL_SEND_RESPONSE_FLAG_MORE_DATA,
                    1,
                    AddrOfPinnedEntityChunks,
                    ref DataWritten,
                    IntPtr.Zero)

            :

                UlVxdApi.UlSendHttpResponseEntityBody(
                    m_AppPoolHandle,
                    m_RequestId,
                    0,
                    1,
                    AddrOfPinnedEntityChunks,
                    ref DataWritten,
                    IntPtr.Zero);

            if (m_SendChunked)
            {
                //
                // data was copied into an unmanaged buffer, free it
                //

                Marshal.FreeHGlobal(AddrOfPinnedBuffer);
            }
            else
            {
                //
                // data wasn't copied unpin the pinned buffer
                //

                PinnedBuffer.Free();
            }

            Marshal.FreeHGlobal(AddrOfPinnedEntityChunks);

            GlobalLog.Print("UlSendHttpResponseEntityBody() DataWritten:" + Convert.ToString(DataWritten) + " DataToWrite:" + Convert.ToString(DataToWrite));

            if (result != NativeMethods.ERROR_SUCCESS)   //Win32.ERROR_CANCELLED || Win32.ERROR_BAD_COMMAND || NativeMethods.ERROR_INVALID_PARAMETER
            {
                throw new ProtocolViolationException(SR.GetString(SR.net_connclosed) + Convert.ToString(result));
            }

            //
            // double check the number of bytes written
            //

            if (DataWritten != DataToWrite)
            {
                throw new InvalidOperationException("sync UlSendHttpResponseEntityBody() failed to write all the data" +
                                                    " count:" + Convert.ToString(count) +
                                                    " DataWritten:" + Convert.ToString(DataWritten) +
                                                    " DataToWrite:" + Convert.ToString(DataToWrite) +
                                                    " m_AppPoolHandle:" + Convert.ToString(m_AppPoolHandle) +
                                                    " m_RequestId:" + Convert.ToString(m_RequestId) +
                                                    " err#" + Convert.ToString(result));
            }

            if (result != NativeMethods.ERROR_SUCCESS && result != NativeMethods.ERROR_HANDLE_EOF)
            {
                //
                // Consider: move all Exception string to system.txt for localization
                //
                throw new InvalidOperationException("sync UlSendHttpResponseEntityBody() failed, err#" + Convert.ToString(result));
            }

            if (m_ContentLength != -1)
            {
                //
                // keep track of the data transferred
                //

                m_ContentLength -= count;

                if (m_ContentLength == 0)
                {
                    //
                    // I should be able to call Close() at this point
                    //
                }
            }

            return; // DataToWrite;
        } // Write()
        /// <include file='doc\HttpListenerWebResponse.uex' path='docs/doc[@for="HttpListenerWebResponse.GetResponseStream"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public override Stream GetResponseStream()
        {
            GlobalLog.Print("entering GetResponseStream()");

            //
            // check if the Stream was already handed to the user before
            //
            if (m_ResponseStream != null)
            {
                return(m_ResponseStream);
            }

            //
            // CODEWORK: replace the bool variable with a check on the minimal
            // info that NEEDS to be set in a HTTP Response in order to send
            // the headers
            //
            if (m_StatusDescription == null || !m_ReadyToSendHeaders)
            {
                throw new InvalidOperationException(SR.GetString());
            }

            //
            // handing off the Stream object out of WebResponse, implies that
            // we're ready to send the response headers back to the client
            //

            int myFlags = 0;


            //
            // check ContentLength consistency
            //

            m_SendChunked = false;
            m_KeepAlive   = true;

            if (m_ContentLength == -1)
            {
                //
                // server didn't specify response content length
                //

                if (m_ClientVersion.Major < 1 || (m_ClientVersion.Major == 1 && m_ClientVersion.Minor < 1))
                {
                    //
                    // make sure there's no Keep-Alive header specified
                    //

                    m_WebHeaders.RemoveInternal(HttpKnownHeaderNames.KeepAlive);
                    m_KeepAlive = false;
                }
                else if (m_ClientVersion.Major == 1)
                {
                    //
                    // we need to chunk the response, regardless of what the
                    // user wanted to do
                    //

                    m_WebHeaders.AddInternal(HttpKnownHeaderNames.TransferEncoding, "chunked");

                    m_SendChunked = true;
                }
                else
                {
                    //
                    // this protocol version is not supported? ul should have
                    // responded with a 503
                    //

                    throw new ProtocolViolationException(SR.GetString(SR.net_invalidversion));
                }
            }
            else
            {
                m_WebHeaders.ChangeInternal(HttpKnownHeaderNames.ContentLength, Convert.ToString(m_ContentLength));

                myFlags = UlConstants.UL_SEND_RESPONSE_FLAG_MORE_DATA;
            }

            //
            // I'm going to make this REALLY inefficient, I'll fix it later
            // CODEWORK: make this incrementally computed
            //

            string Name, Value;
            int    i, k, count, index, length, offset, TotalResponseSize, TotalKnownHeadersLength = 0, TotalUnknownHeadersLength = 0, UnknownHeaderCount = 0;

            i     = 0;
            count = m_WebHeaders.Count;
            for (k = 0; k < count; k++)
            {
                Name  = (string)m_WebHeaders.GetKey(k);
                Value = (string)m_WebHeaders.Get(k);
                index = UL_HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(Name);

                if (index < 0)
                {
                    //
                    // unknown header
                    //

                    GlobalLog.Print(Name + " is unknown header Value:" + Value);

                    UnknownHeaderCount++;

                    TotalUnknownHeadersLength += Name.Length + Value.Length;
                }
                else
                {
                    //
                    // known header
                    //

                    GlobalLog.Print(Name + " is known header:" + Convert.ToString(index) + " Value:" + Value);

                    TotalKnownHeadersLength += Value.Length;
                }
            }

            TotalResponseSize =
                260 +                            // fixed size (includes know headers array)
                2 * m_StatusDescription.Length + // staus description
                2 * TotalKnownHeadersLength +    // known headers
                4 * 4 * UnknownHeaderCount +     // unknow headers array
                2 * TotalUnknownHeadersLength;   // unknow headers

            //
            // allocate a managed UL_HTTP_RESPONSE structure, and store
            // unmanaged pinned memory pointers into structure members
            //
            IntPtr pResponse      = Marshal.AllocHGlobal(TotalResponseSize);
            IntPtr pPointerOffset = ComNetOS.IsWinNt ? pResponse : IntPtr.Zero;

            GlobalLog.Print("Allocated " + Convert.ToString(TotalResponseSize) + " bytes from:" + Convert.ToString(pResponse) + " to fit Response");            Marshal.WriteInt16(pResponse, 0, 0);     // Flags
            Marshal.WriteInt16(pResponse, 2, (short)m_Status);
            Marshal.WriteInt32(pResponse, 12, UnknownHeaderCount);

            offset = 260;

            length = 2 * m_StatusDescription.Length;
            Marshal.WriteInt32(pResponse, 4, length);
            Marshal.WriteInt32(pResponse, 8, pPointerOffset + offset);
            Marshal.Copy(Encoding.Unicode.GetBytes(m_StatusDescription), 0, pResponse + offset, length);
            offset += length;

            for (i = k = 0; i < 30; i++, k += 2)
            {
                Name  = UL_HTTP_RESPONSE_HEADER_ID.ToString(i);
                Value = m_WebHeaders[Name];

                Marshal.WriteInt64(pResponse, 20 + i * 8, 0);

                if (Value != null)
                {
                    //
                    // this known header key, has a value which is not null
                    //

                    length = 2 * Value.Length;
                    Marshal.WriteInt16(pResponse, 20 + i * 8, (short)length); // could use 32 as well because of padding
                    Marshal.WriteInt32(pResponse, 24 + i * 8, pPointerOffset + offset);
                    Marshal.Copy(Encoding.Unicode.GetBytes(Value), 0, pResponse + offset, length);

                    GlobalLog.Print("writing:" + Name + " from " + Convert.ToString(offset) + " to " + Convert.ToString(offset + length - 1));

                    offset += length;
                }
            }

            int pUnknownHeaders = offset;

            Marshal.WriteInt32(pResponse, 16, pPointerOffset + pUnknownHeaders);

            offset += UnknownHeaderCount * 16;

            i     = 0;
            count = m_WebHeaders.Count;
            for (k = 0; k < count; k++)
            {
                Name  = (string)m_WebHeaders.GetKey(k);
                Value = (string)m_WebHeaders.Get(k);
                index = UL_HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(Name);

                if (index < 0)
                {
                    //
                    // unknown header
                    //

                    GlobalLog.Print(Name + " is unknown header offset:" + Convert.ToString(offset));

                    length = 2 * Name.Length;
                    Marshal.WriteInt32(pResponse, pUnknownHeaders + i * 16, length);
                    Marshal.WriteInt32(pResponse, pUnknownHeaders + 4 + i * 16, pPointerOffset + offset);
                    Marshal.Copy(Encoding.Unicode.GetBytes(Name), 0, pResponse + offset, length);

                    GlobalLog.Print("writing:" + Name + " from " + Convert.ToString(offset) + " to " + Convert.ToString(offset + length - 1));

                    offset += length;


                    length = 2 * Value.Length;
                    Marshal.WriteInt32(pResponse, pUnknownHeaders + 8 + i * 16, length);
                    Marshal.WriteInt32(pResponse, pUnknownHeaders + 12 + i * 16, pPointerOffset + offset);
                    Marshal.Copy(Encoding.Unicode.GetBytes(Value), 0, pResponse + offset, length);

                    GlobalLog.Print("writing:" + Value + " from " + Convert.ToString(offset) + " to " + Convert.ToString(offset + length - 1));

                    offset += length;

                    i++;
                }
            }

            int DataWritten = 0;

            int result =
                ComNetOS.IsWinNt ?

                UlSysApi.UlSendHttpResponse(
                    m_AppPoolHandle,
                    m_RequestId,
                    myFlags,
                    pResponse,
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref DataWritten,
                    IntPtr.Zero)

            :

                UlVxdApi.UlSendHttpResponseHeaders(
                    m_AppPoolHandle,
                    m_RequestId,
                    0,
                    pResponse,                           // Response,
                    TotalResponseSize,
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref DataWritten,
                    IntPtr.Zero);

            GlobalLog.Print("UlSendHttpResponseHeaders() DataWritten: " + Convert.ToString(DataWritten));

            Marshal.FreeHGlobal(pResponse);

            //
            // check return value, if IO is cancelled we'll throw
            //

            if (result != NativeMethods.ERROR_SUCCESS)
            {
                throw new IOException("Request/Response processing was cancelled");
            }

            //
            // don't touch m_WebHeaders & m_StatusDescription anymore
            //

            m_ReadyToSendHeaders = false;

            //
            // if not create the Stream
            //

            m_ResponseStream = new
                               ListenerResponseStream(
                m_AppPoolHandle,
                m_RequestId,
                m_ContentLength,
                m_SendChunked,
                m_KeepAlive);

            //
            // and return it to the user
            //

            return(m_ResponseStream);
        } // GetResponseStream()
        m_InitializeUriListener()
        {
            if (ComNetOS.IsWinNt)
            {
                //
                // if this is WinNT we initialize ul.vxd
                //

                //
                // we need to create a special config group that allows for
                // transient registrations under the "http://*:80/" namespace
                // this will call UlInitialize() as well
                //

                int result = UlSysApi.UlCreateRootConfigGroup("http://*:80/");

                if (result != 0)
                {
                    throw new InvalidOperationException("Failed Initializing ul.sys");
                }

                GlobalLog.Print("UlCreateRootConfigGroup() succeeded");

                /*
                 * //
                 * // if we use this initialization we will need tcgsec.exe to be
                 * // running in order to make this work
                 * //
                 *
                 * int result = UlSysApi.UlInitialize(0);
                 *
                 * if ( result != 0 ) {
                 *  throw new InvalidOperationException( "Failed Initializing ul.sys" );
                 * }
                 *
                 * GlobalLog.Print("UL.SYS correctly initialized" );
                 */
            }
            else if (ComNetOS.IsWin9x)
            {
                //
                // if this is Win9x we initialize ul.vxd
                //

                int result = UlVxdApi.UlInitialize();

                if (result != 0)
                {
                    throw new InvalidOperationException("Failed Initializing ul.vxd");
                }

                GlobalLog.Print("UL.VXD correctly initialized");
            }
            else
            {
                //
                // this is the only place in which we check for OperatingSystem other than
                // NT and Win9x, past this point we can assume that:
                // if it's not WinNt then it's Win9x.
                //

                throw new InvalidOperationException("Illegal OperatingSystem version");
            }

            return(true);
        } // InitializeUriListener()
        BeginGetRequest(
            AsyncCallback requestCallback,
            Object stateObject)
        {
            //
            // Validation
            //

            if (m_AppPoolHandle == NativeMethods.INVALID_HANDLE_VALUE)
            {
                throw new InvalidOperationException("The AppPool handle is invalid");
            }

            //
            // prepare the ListenerAsyncResult object ( this will have it's own
            // event that the user can wait on for IO completion - which means we
            // need to signal it when IO completes )
            //

            GlobalLog.Print("BeginGetRequest() creating ListenerAsyncResult");

            ListenerAsyncResult AResult = new ListenerAsyncResult(
                stateObject,
                requestCallback);

            AutoResetEvent m_Event = new AutoResetEvent(false);

            Marshal.WriteIntPtr(
                AResult.m_Overlapped,
                Win32.OverlappedhEventOffset,
                m_Event.Handle);

            //
            // issue unmanaged call until we read enough data:
            // usually starting with a InitialBufferSize==4096 bytes we should be
            // able to get all the headers ( and part of the entity body, if any
            // is present ), if we don't, if the call didn't fail for othe reasons,
            // we get indication in BytesReturned, on how big the buffer should be
            // to receive the data available, so usually the second call will
            // succeed, but we have to consider the case of two competing calls
            // for the same RequestId, and that's why we need a loop and not just
            // a try/retry-expecting-success fashion
            //

            int result;

            for (;;)
            {
                //
                // check if we're in a healthy state
                //
                if (AResult.m_Retries++ > m_MaxRetries)
                {
                    throw new InvalidOperationException("UlReceiveHttpRequest() Too many retries");
                }

                result =
                    ComNetOS.IsWinNt ?

                    UlSysApi.UlReceiveHttpRequest(
                        m_AppPoolHandle,
                        AResult.m_RequestId,
                        UlConstants.UL_RECEIVE_REQUEST_FLAG_COPY_BODY,
                        AResult.m_Buffer,
                        AResult.m_BufferSize,
                        ref AResult.m_BytesReturned,
                        AResult.m_Overlapped)

                :

                    UlVxdApi.UlReceiveHttpRequestHeaders(
                        m_AppPoolHandle,
                        AResult.m_RequestId,
                        0,
                        AResult.m_Buffer,
                        AResult.m_BufferSize,
                        ref AResult.m_BytesReturned,
                        AResult.m_Overlapped);

                GlobalLog.Print("UlReceiveHttpRequest() returns:"
                                + Convert.ToString(result));

                if (result == NativeMethods.ERROR_SUCCESS || result == NativeMethods.ERROR_IO_PENDING)
                {
                    //
                    // synchronous success or successfull pending: we are done
                    //

                    break;
                }

                if (result == NativeMethods.ERROR_INVALID_PARAMETER)
                {
                    //
                    // we might get this if somebody stole our RequestId,
                    // set RequestId to null
                    //

                    AResult.m_RequestId = 0;

                    //
                    // and start all over again with the buffer we
                    // just allocated
                    //

                    continue;
                }

                if (result == NativeMethods.ERROR_MORE_DATA)
                {
                    //
                    // the buffer was not big enough to fit the headers, we need
                    // to read the RequestId returned, grow the buffer, keeping
                    // the data already transferred
                    //

                    AResult.m_RequestId = Marshal.ReadInt64(IntPtrHelper.Add(AResult.m_Buffer, m_RequestIdOffset));

                    //
                    // allocate a new buffer of the required size
                    //

                    IntPtr NewBuffer = Marshal.AllocHGlobal(AResult.m_BytesReturned);

                    //
                    // copy the data already read from the old buffer into the
                    // new one
                    //

                    NativeMethods.CopyMemory(NewBuffer, AResult.m_Buffer, AResult.m_BufferSize);


                    //
                    // free the old buffer
                    //

                    Marshal.FreeHGlobal(AResult.m_Buffer);

                    //
                    // update buffer pointer and size
                    //

                    AResult.m_Buffer        = NewBuffer;
                    AResult.m_BufferSize    = AResult.m_BytesReturned;
                    AResult.m_BytesReturned = 0;

                    //
                    // and start all over again with the new buffer
                    //

                    continue;
                }

                //
                // someother bad error, possible( ? ) return values are:
                //
                // ERROR_INVALID_HANDLE
                // ERROR_INSUFFICIENT_BUFFER
                // ERROR_OPERATION_ABORTED
                // ERROR_IO_PENDING
                //

                throw new InvalidOperationException("UlReceiveHttpRequest() failed, err#" + Convert.ToString(result));
            }

            //
            // we get here only if a break happens, i.e.
            // 1) syncronous completion
            // 2) the IO pended
            //

            if (result == NativeMethods.ERROR_SUCCESS)
            {
                //
                // set syncronous completion to true
                //

                AResult.Complete(true);

                //
                // and call the internal callback
                //

                WaitCallback(AResult, false);
            }
            else
            {
                //
                // create a new delegate
                // and spin a new thread from the thread pool to wake up when the
                // event is signaled and call the delegate
                //

                ThreadPool.RegisterWaitForSingleObject(
                    m_Event,
                    new WaitOrTimerCallback(WaitCallback),
                    AResult,
                    -1,
                    true);
            }

            GlobalLog.Print("returning AResult");

            return(AResult);
        } // StartListen()
        GetRequest()
        {
            //
            // Validation
            //

            if (m_AppPoolHandle == NativeMethods.INVALID_HANDLE_VALUE)
            {
                throw new InvalidOperationException("The AppPool handle is invalid");
            }

            int result;

            int retries = 0;

            //
            // defined in ulcommonapi.cs
            //

            int RcvHeadersBufferSize = UlConstants.InitialBufferSize;

            //
            // prepare ( allocate/pin ) buffers and data for the first unmanaged call
            //

            GCHandle PinnedBuffer;
            GCHandle NewPinnedBuffer;

            IntPtr AddrOfPinnedBuffer    = IntPtr.Zero;
            IntPtr NewAddrOfPinnedBuffer = IntPtr.Zero;

            int  BytesReturned = 0;
            long RequestId     = 0;

            byte[] RcvHeadersBuffer = new byte[RcvHeadersBufferSize];

            //
            // pin buffers and data for the unmanaged call
            //

            PinnedBuffer       = GCHandle.Alloc(RcvHeadersBuffer, GCHandleType.Pinned);
            AddrOfPinnedBuffer = PinnedBuffer.AddrOfPinnedObject();

            //
            // issue unmanaged blocking call until we read enough data:
            // usually starting with a InitialBufferSize==4096 bytes we should be
            // able to get all the headers ( and part of the entity body, if any
            // is present ), if we don't, if the call didn't fail for othe reasons,
            // we get indication in BytesReturned, on how big the buffer should be
            // to receive the data available, so usually the second call will
            // succeed, but we have to consider the case of two competing calls
            // for the same RequestId, and that's why we need a loop and not just
            // a try/retry-expecting-success fashion
            //

            for (;;)
            {
                //
                // check if we're in a healthy state
                //
                if (retries++ > m_MaxRetries)
                {
                    throw new InvalidOperationException("UlReceiveHttpRequest() Too many retries");
                }

                result =
                    ComNetOS.IsWinNt ?

                    UlSysApi.UlReceiveHttpRequest(
                        m_AppPoolHandle,
                        RequestId,
                        UlConstants.UL_RECEIVE_REQUEST_FLAG_COPY_BODY,
                        AddrOfPinnedBuffer,
                        RcvHeadersBufferSize,
                        ref BytesReturned,
                        IntPtr.Zero)

                :

                    UlVxdApi.UlReceiveHttpRequestHeaders(
                        m_AppPoolHandle,
                        RequestId,
                        0,
                        AddrOfPinnedBuffer,
                        RcvHeadersBufferSize,
                        ref BytesReturned,
                        IntPtr.Zero);

                if (result == NativeMethods.ERROR_SUCCESS)
                {
                    //
                    // success, we are done.
                    //

                    break;
                }

                if (result == NativeMethods.ERROR_INVALID_PARAMETER)
                {
                    //
                    // we might get this if somebody stole our RequestId,
                    // set RequestId to null
                    //

                    RequestId = 0;

                    //
                    // and start all over again with the buffer we
                    // just allocated
                    //

                    continue;
                }

                //
                // let's check if ul is in good shape:
                //

                if (BytesReturned < RcvHeadersBufferSize)
                {
                    throw new InvalidOperationException("UlReceiveHttpRequest() sent bogus BytesReturned: " + Convert.ToString(BytesReturned));
                }

                if (result == NativeMethods.ERROR_MORE_DATA)
                {
                    //
                    // the buffer was not big enough to fit the headers, we need
                    // to read the RequestId returned, grow the buffer, keeping
                    // the data already transferred
                    //

                    RequestId = Marshal.ReadInt64(IntPtrHelper.Add(AddrOfPinnedBuffer, m_RequestIdOffset));

                    //
                    // CODEWORK: wait for the answer from LarrySu
                    //

                    //
                    // if the buffer size was too small, grow the buffer
                    // this reallocation dereferences the old buffer, but since
                    // this was previously pinned, it won't be garbage collected
                    // until we unpin it ( which we do below )
                    //

                    RcvHeadersBuffer = new byte[BytesReturned];

                    //
                    // pin the new one
                    //

                    NewPinnedBuffer       = GCHandle.Alloc(RcvHeadersBuffer, GCHandleType.Pinned);
                    NewAddrOfPinnedBuffer = NewPinnedBuffer.AddrOfPinnedObject();

                    //
                    // copy the valid data
                    //

                    Marshal.Copy(AddrOfPinnedBuffer, RcvHeadersBuffer, 0, RcvHeadersBufferSize);
                    RcvHeadersBufferSize = BytesReturned;

                    //
                    // unpin the old buffer, reset pinned/unmanaged pointers
                    //

                    PinnedBuffer.Free();

                    PinnedBuffer       = NewPinnedBuffer;
                    AddrOfPinnedBuffer = NewAddrOfPinnedBuffer;

                    //
                    // and start all over again with the new buffer
                    //

                    continue;
                }

                //
                // someother bad error, possible( ? ) return values are:
                //
                // ERROR_INVALID_HANDLE
                // ERROR_INSUFFICIENT_BUFFER
                // ERROR_OPERATION_ABORTED
                // ERROR_IO_PENDING
                //

                throw new InvalidOperationException("UlReceiveHttpRequest() failed, err#" + Convert.ToString(result));
            }

            GlobalLog.Print("GetRequest RequestId:" + Convert.ToString(RequestId));            //
            // translate unmanaged results into a new managed object
            //

            HttpListenerWebRequest
                myWebRequest =
                new HttpListenerWebRequest(AddrOfPinnedBuffer, RcvHeadersBufferSize, m_AppPoolHandle);

            //
            // free the unmanaged buffer ( deallocate/unpin ) after unmanaged call
            //

            PinnedBuffer.Free();

            return(myWebRequest);
        } // GetRequest()