惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - HAL9000

旧文重发:漫谈字符集和编码 用html5 canvas和JS写个数独游戏 如何破解.net软件 夜晚才能工作的程序员 公司让各部门写春联,这是我们部门写的对子 盖茨和乔布斯 利用简单的力学法则来模拟天体运行(2) 利用简单的力学法则来模拟天体运行 一个仿windows泡泡屏保的实现 informix cli 汉字乱码的解决办法 msdn版windows 8无法激活的解决办法 谁是DAC2.8和jet4.0的接班人? 一个长事务引起的血案——Informix 长事务回滚失败引起的阻塞故障处理 一些常见的星际旅行的科技名词与其"理论根据": 笔记:连接SCO上的FTP时为何那么慢 关于中文编程的段子的一个实现 VC非托管代码调用webservice,并支持代理服务器设置 找到锁域账号的元凶 求高手指点:VC中wininet的代理服务器问题,耗了两天了,没有一点办法
天哪,我遇上了一个windows api BUG! 并贡献一个完全支持代理服务器的http文件下载VC代码
HAL9000 · 2012-01-09 · via 博客园 - HAL9000

    好吧,我遇上了windows api的bug...

     一开始程序是采用了CInternetSession来打开一个Session,然后再用OpenUrl来打开一个CHttpFile文件. 这个程序一直工作得很好,只要ie能上网,它就能下载。如果用代理服务器,只需要在ie中设置好即可。如果代理服务器需要口令,只需要先在ie中访问页面,输入口令,并选择保存口令,这个程序就也能正常透过代理连接了。

    直到有一天,它被安装在了一台ie6的windows xp机器上,它不能工作了。

    因为 CInternetSession::OpenUrl方法调用了InternetOperUrl api函数,而InternetOperUrl函数,有个BUG.

     InternetOperUrl在IE6的环境下,除非代理服务器的用户名与口令与当前用户的用户名与口令一致,否则他不能透过代理服务器连接http文件。

    为什么我知道这是个BUG? 因为安装了ie8之后, InternetOperUrl就能正常工作了——只要在ie通过代理上网时,输入代理服务器口令时选择一下“保存我的口令”,InternetOperUrl就也能正常连接了。

    在ie6下, InternetOperUrl的似乎是总是用当前登录电脑的用户名与口令向代理服务器验证。这明显是一个错误。后来他们修好了。

    这个问题让我折腾了三天,安装了n台不同版本的windows和ie环境,测试了各种各样的程序,我都几乎准备要动用我的msdn技术支持时, 终于确认了问题原因。

    知道了原因就好办了。只需要绕开mfc的这个问题,直接用几个底层api就可以正常工作了。下面是可以正常工作的代码,一共支持三种不同的代理服务器设置:0 用ie的设置(包括ie保存了的密码),1,坚决不用代理,一定要直连。2,用本程序指定的代理。

 iProxyMode 、bProxyNeedPassword、proxyinfo、sProxyUserName、sProxyPassword是全局变量,你可以在调用这个函数之前准备好这些变量。

BOOL GetHttpFile(LPCTSTR psUrl, LPCTSTR psLocalFile, CString &sErrMg)

{
    BOOL b;
    BOOL bOK = TRUE;
    DWORD dwServiceType;
    CString strServer;
    CString strObject;
    INTERNET_PORT nPort;

    BOOL bParsed = AfxParseURL(psUrl, dwServiceType, strServer, strObject, nPort);
    if (!bParsed)
    {
        sErrMg = "远程文件地址格式不对!";
        return FALSE;
    }

    HINTERNET m_hInternet = InternetOpen(
        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)"
        INTERNET_OPEN_TYPE_PRECONFIG,
        NULL,
        NULL, 0);

    if (FALSE == m_hInternet)
    {
        InternetCloseHandle(m_hInternet);
        sErrMg.Format("建立网络会话 %s 失败", psUrl);
        return FALSE;
    }

    if (iProxyMode != 0)
    {
        b = InternetSetOption (NULL, INTERNET_OPTION_PROXY, (LPVOID) &proxyinfo, sizeof (proxyinfo));
    }

    HINTERNET m_hConnection = InternetConnect(
        m_hInternet, 
        strServer,
        nPort, 
        NULL, 
        NULL,
        INTERNET_SERVICE_HTTP, 
        INTERNET_FLAG_NO_UI, 
        NULL);

    if (FALSE == m_hConnection)
    {
        InternetCloseHandle(m_hConnection);
        InternetCloseHandle(m_hInternet);
        sErrMg.Format("建立网络连接 %s 失败", psUrl);
        return FALSE;
    }

    if (iProxyMode == 2 && bProxyNeedPassword)
    {
        DWORD dwUserNameLen = sProxyUserName.GetLength() + 1;
        DWORD dwUserPassLen = sProxyPassword.GetLength() + 1;

        b = InternetSetOption (m_hConnection, INTERNET_OPTION_PROXY_USERNAME, (LPVOID)(LPCTSTR)sProxyUserName, dwUserNameLen);    
        b = InternetSetOption (m_hConnection, INTERNET_OPTION_PROXY_PASSWORD, (LPVOID)(LPCTSTR)sProxyPassword, dwUserPassLen);    
    }

    static LPCTSTR s_szAcceptTypes[] = { _T("*/*"), NULL };

    HINTERNET m_hRequest = HttpOpenRequest(
        m_hConnection, _T("GET"), 
        strObject, 
        _T("HTTP/1.0"), NULL,
        s_szAcceptTypes, 
        INTERNET_FLAG_NO_UI | INTERNET_FLAG_KEEP_CONNECTION, // | ((m_url.GetScheme() == ATL_URL_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0)
        NULL);
    if (FALSE == m_hRequest)
    {
        InternetCloseHandle(m_hRequest);
        InternetCloseHandle(m_hConnection);
        InternetCloseHandle(m_hInternet);
        sErrMg.Format("打开网络连接 %s 失败", psUrl);
        return FALSE;
    }

    CString strHeaders;
    //strHeaders.Append(_T("Content-Type: text/xml; charset=utf-8\r\n"));

    b = HttpSendRequest(m_hRequest, strHeaders, (DWORD) strHeaders.GetLength(),        
        NULL, 0);

    if (FALSE == b)
    {
        InternetCloseHandle(m_hRequest);
        InternetCloseHandle(m_hConnection);
        InternetCloseHandle(m_hInternet);
        sErrMg.Format("向服务器发送请求 %s 失败", psUrl);
        return FALSE;
    }

    int iStatus = GetInternetRequestStatusCode(m_hRequest);

    if(!(iStatus>= 200&& iStatus<300 ))
    {
        InternetCloseHandle(m_hRequest);
        InternetCloseHandle(m_hConnection);
        InternetCloseHandle(m_hInternet);
        sErrMg.Format("打开远程文件出错,错误码:%d", iStatus);
        return FALSE;
    }

    byte pData[65535];
    DWORD dwReadedLen;
    DWORD dwWrittenLen;  

    HANDLE hfile = CreateFile(psLocalFile,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); 
    if (hfile == INVALID_HANDLE_VALUE)  
    {    
        InternetCloseHandle(m_hRequest);
        InternetCloseHandle(m_hConnection);
        InternetCloseHandle(m_hInternet);

        sErrMg.Format("创建本地文件 %s 失败", psLocalFile);

        return FALSE;
    }  

    while(1)
    {
        b =  InternetReadFile(m_hRequest, (LPVOID)pData, sizeof(pData), &dwReadedLen);
        if (b == FALSE)
        {
            CloseHandle(hfile);
            InternetCloseHandle(m_hRequest);
            InternetCloseHandle(m_hConnection);
            InternetCloseHandle(m_hInternet);

            sErrMg.Format("读取文件 %s 失败", psUrl);
            return FALSE;
        }
        if(dwReadedLen == 0)
        {
            break;  
        }
        b = WriteFile(hfile, pData, dwReadedLen, &dwWrittenLen,NULL);  
        if (b == FALSE)  
        {  
            CloseHandle(hfile);
            InternetCloseHandle(m_hRequest);
            InternetCloseHandle(m_hConnection);
            InternetCloseHandle(m_hInternet);
            sErrMg.Format("写入本地文件 %s 失败", psLocalFile);
            return FALSE;
        }  

    }

    CloseHandle(hfile);
    InternetCloseHandle(m_hRequest);
    InternetCloseHandle(m_hConnection);
    InternetCloseHandle(m_hInternet);
    sErrMg.Format("下载成功");
    return TRUE;

}