⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
        if ((!HttpQueryInfoW(This->request, HTTP_QUERY_CONTENT_TYPE, content_type, &len, NULL) &&
             GetLastError() != ERROR_INSUFFICIENT_BUFFER) ||
            !(content_type = HeapAlloc(GetProcessHeap(), 0, len)) ||
            !HttpQueryInfoW(This->request, HTTP_QUERY_CONTENT_TYPE, content_type, &len, NULL))
        {
            WARN("HttpQueryInfo failed: %d\n", GetLastError());
            IInternetProtocolSink_ReportProgress(This->protocol_sink,
                                                 (This->grfBINDF & BINDF_FROMURLMON) ?
                                                 BINDSTATUS_MIMETYPEAVAILABLE :
                                                 BINDSTATUS_RAWMIMETYPE,
                                                 wszDefaultContentType);
        }
        else
        {
            IInternetProtocolSink_ReportProgress(This->protocol_sink,
                                                 (This->grfBINDF & BINDF_FROMURLMON) ?
                                                 BINDSTATUS_MIMETYPEAVAILABLE :
                                                 BINDSTATUS_RAWMIMETYPE,
                                                 content_type);
        }

        len = 0;
        if ((!HttpQueryInfoW(This->request, HTTP_QUERY_CONTENT_LENGTH, content_length, &len, NULL) &&
             GetLastError() != ERROR_INSUFFICIENT_BUFFER) ||
            !(content_length = HeapAlloc(GetProcessHeap(), 0, len)) ||
            !HttpQueryInfoW(This->request, HTTP_QUERY_CONTENT_LENGTH, content_length, &len, NULL))
        {
            WARN("HttpQueryInfo failed: %d\n", GetLastError());
            This->content_length = 0;
        }
        else
        {
            This->content_length = atoiW(content_length);
        }

        This->flags |= FLAG_FIRST_CONTINUE_COMPLETE;
    }

    if (pProtocolData->pData >= (LPVOID)BINDSTATUS_DOWNLOADINGDATA)
    {
        if (!InternetQueryDataAvailable(This->request, &This->available_bytes, 0, 0))
        {
            if (GetLastError() == ERROR_IO_PENDING)
            {
                This->flags &= ~FLAG_REQUEST_COMPLETE;
            }
            else
            {
                WARN("InternetQueryDataAvailable failed: %d\n", GetLastError());
                HTTPPROTOCOL_ReportResult(This, INET_E_DATA_NOT_AVAILABLE);
            }
        }
        else
        {
            HTTPPROTOCOL_ReportData(This);
        }
    }

done:
    HeapFree(GetProcessHeap(), 0, response_headers);
    HeapFree(GetProcessHeap(), 0, content_type);
    HeapFree(GetProcessHeap(), 0, content_length);

    /* Returns S_OK on native */
    return S_OK;
}

static HRESULT WINAPI HttpProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
        DWORD dwOptions)
{
    HttpProtocol *This = PROTOCOL_THIS(iface);
    FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
    return E_NOTIMPL;
}

static HRESULT WINAPI HttpProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
{
    HttpProtocol *This = PROTOCOL_THIS(iface);

    TRACE("(%p)->(%08x)\n", This, dwOptions);
    HTTPPROTOCOL_Close(This);

    return S_OK;
}

static HRESULT WINAPI HttpProtocol_Suspend(IInternetProtocol *iface)
{
    HttpProtocol *This = PROTOCOL_THIS(iface);
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
}

static HRESULT WINAPI HttpProtocol_Resume(IInternetProtocol *iface)
{
    HttpProtocol *This = PROTOCOL_THIS(iface);
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
}

static HRESULT WINAPI HttpProtocol_Read(IInternetProtocol *iface, void *pv,
        ULONG cb, ULONG *pcbRead)
{
    HttpProtocol *This = PROTOCOL_THIS(iface);
    ULONG read = 0, len = 0;
    HRESULT hres = S_FALSE;

    TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);

    if (!(This->flags & FLAG_REQUEST_COMPLETE))
    {
        hres = E_PENDING;
    }
    else while (!(This->flags & FLAG_ALL_DATA_READ) &&
                read < cb)
    {
        if (This->available_bytes == 0)
        {
            /* InternetQueryDataAvailable may immediately fork and perform its asynchronous
             * read, so clear the flag _before_ calling so it does not incorrectly get cleared
             * after the status callback is called */
            This->flags &= ~FLAG_REQUEST_COMPLETE;
            if (!InternetQueryDataAvailable(This->request, &This->available_bytes, 0, 0))
            {
                if (GetLastError() == ERROR_IO_PENDING)
                {
                    hres = E_PENDING;
                }
                else
                {
                    WARN("InternetQueryDataAvailable failed: %d\n", GetLastError());
                    hres = INET_E_DATA_NOT_AVAILABLE;
                    HTTPPROTOCOL_ReportResult(This, hres);
                }
                goto done;
            }
            else if (This->available_bytes == 0)
            {
                HTTPPROTOCOL_AllDataRead(This);
            }
        }
        else
        {
            if (!InternetReadFile(This->request, ((BYTE *)pv)+read,
                                  This->available_bytes > cb-read ?
                                  cb-read : This->available_bytes, &len))
            {
                WARN("InternetReadFile failed: %d\n", GetLastError());
                hres = INET_E_DOWNLOAD_FAILURE;
                HTTPPROTOCOL_ReportResult(This, hres);
                goto done;
            }
            else if (len == 0)
            {
                HTTPPROTOCOL_AllDataRead(This);
            }
            else
            {
                read += len;
                This->current_position += len;
                This->available_bytes -= len;
            }
        }
    }

    /* Per MSDN this should be if (read == cb), but native returns S_OK
     * if any bytes were read, so we will too */
    if (read)
        hres = S_OK;

done:
    if (pcbRead)
        *pcbRead = read;

    if (hres != E_PENDING)
        This->flags |= FLAG_REQUEST_COMPLETE;

    return hres;
}

static HRESULT WINAPI HttpProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
        DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
    HttpProtocol *This = PROTOCOL_THIS(iface);
    FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
    return E_NOTIMPL;
}

static HRESULT WINAPI HttpProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
{
    HttpProtocol *This = PROTOCOL_THIS(iface);

    TRACE("(%p)->(%08x)\n", This, dwOptions);

    if (!InternetLockRequestFile(This->request, &This->lock))
        WARN("InternetLockRequest failed: %d\n", GetLastError());

    return S_OK;
}

static HRESULT WINAPI HttpProtocol_UnlockRequest(IInternetProtocol *iface)
{
    HttpProtocol *This = PROTOCOL_THIS(iface);

    TRACE("(%p)\n", This);

    if (This->lock)
    {
        if (!InternetUnlockRequestFile(This->lock))
            WARN("InternetUnlockRequest failed: %d\n", GetLastError());
        This->lock = 0;
    }

    return S_OK;
}

#undef PROTOCOL_THIS

#define PRIORITY_THIS(iface) DEFINE_THIS(HttpProtocol, InternetPriority, iface)

static HRESULT WINAPI HttpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv)
{
    HttpProtocol *This = PRIORITY_THIS(iface);
    return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
}

static ULONG WINAPI HttpPriority_AddRef(IInternetPriority *iface)
{
    HttpProtocol *This = PRIORITY_THIS(iface);
    return IInternetProtocol_AddRef(PROTOCOL(This));
}

static ULONG WINAPI HttpPriority_Release(IInternetPriority *iface)
{
    HttpProtocol *This = PRIORITY_THIS(iface);
    return IInternetProtocol_Release(PROTOCOL(This));
}

static HRESULT WINAPI HttpPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
{
    HttpProtocol *This = PRIORITY_THIS(iface);

    TRACE("(%p)->(%d)\n", This, nPriority);

    This->priority = nPriority;
    return S_OK;
}

static HRESULT WINAPI HttpPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
{
    HttpProtocol *This = PRIORITY_THIS(iface);

    TRACE("(%p)->(%p)\n", This, pnPriority);

    *pnPriority = This->priority;
    return S_OK;
}

#undef PRIORITY_THIS

static const IInternetPriorityVtbl HttpPriorityVtbl = {
    HttpPriority_QueryInterface,
    HttpPriority_AddRef,
    HttpPriority_Release,
    HttpPriority_SetPriority,
    HttpPriority_GetPriority
};

static const IInternetProtocolVtbl HttpProtocolVtbl = {
    HttpProtocol_QueryInterface,
    HttpProtocol_AddRef,
    HttpProtocol_Release,
    HttpProtocol_Start,
    HttpProtocol_Continue,
    HttpProtocol_Abort,
    HttpProtocol_Terminate,
    HttpProtocol_Suspend,
    HttpProtocol_Resume,
    HttpProtocol_Read,
    HttpProtocol_Seek,
    HttpProtocol_LockRequest,
    HttpProtocol_UnlockRequest
};

HRESULT HttpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
{
    HttpProtocol *ret;

    TRACE("(%p %p)\n", pUnkOuter, ppobj);

    URLMON_LockModule();

    ret = HeapAlloc(GetProcessHeap(), 0, sizeof(HttpProtocol));

    ret->lpInternetProtocolVtbl = &HttpProtocolVtbl;
    ret->lpInternetPriorityVtbl = &HttpPriorityVtbl;
    ret->flags = ret->grfBINDF = 0;
    memset(&ret->bind_info, 0, sizeof(ret->bind_info));
    ret->protocol_sink = 0;
    ret->http_negotiate = 0;
    ret->internet = ret->connect = ret->request = 0;
    ret->full_header = 0;
    ret->lock = 0;
    ret->current_position = ret->content_length = ret->available_bytes = 0;
    ret->priority = 0;
    ret->ref = 1;

    *ppobj = PROTOCOL(ret);
    
    return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -