Detecting 404's in Wininet

Hi,
I am having a problem with detecting 404's in Wininet, specifically using the HttpQueryInfo function. I have asked on 2 separate forums (SO and Daniweb), and no one has been able to answer. (SO had an answer, but it did not fix the problem).

What I am trying to do is check if a page exists on the web server by querying for a 404 status. Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    int statusCode;
    DWORD statCharLen = 128;
    char statChar[statCharLen];

    //Check existance of page (for 404 error)
    if(!HttpQueryInfo(hRequestHandle,
                      HTTP_QUERY_STATUS_CODE,
                      &statChar,
                      &statCharLen,
                      NULL))
        return 4;
    statusCode = atoi(statChar);

    if(statusCode == 404)
        cout << "We got a 404 error" << endl;

    cout << "Stat code text : " << statChar << endl;
    cout << "Stat code num  : " << statusCode << endl;
    cout << "404 status code: " << HTTP_STATUS_NOT_FOUND << endl;


However, the status code is always a 1 byte char array of "0".

Any ideas? I have spent quite a bit of time trying to figure this out (a week now)

Thanks!
--D
First, line 3 is non-standard C++. I am pretty sure most compilers will reject line #3 in your code snippet. Which compiler are you using?

In any case, the standard way would be to allocate memory using a memory-allocator function, namely the new operator or malloc or a Windows-specific function like LocalAlloc().

Second, if you read the Remarks section @ MSDN Online about the HttpQueryInfo() function (http://msdn.microsoft.com/en-us/library/aa384238(VS.85).aspx), you'll see that the data type returned by a query for the status code is a number, not a string, so your use of atoi() is 100% incorrect as per the documentation. All you have to do is reinterpret the buffer as a DWORD. You can confirm you have a DWORD if after the function call, the value of statCharLen == sizeof(DWORD).
Last edited on
I am using MinGW, and C::B IDE.

I have made some modifications to my code, but the buffer length is not the size of a DWORD :/
It dosent really make sense to me, it should return buffer the size of a DWORD because I am requesting only the status code.

The buffer length returned is 1.

My new code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    DWORD statCodeLen = sizeof(DWORD);
    DWORD statCode;
    void *pStatCode = new char[statCodeLen];

    //cout << "Size of DWORD: " << sizeof(DWORD) << endl;

    //Check existance of page (for 404 error)
    if(!HttpQueryInfo(hRequestHandle,
                      HTTP_QUERY_STATUS_CODE,
                      &pStatCode,
                      &statCodeLen,
                      NULL))
    {
        delete [] pStatCode;
        return 4;
    }

    if(statCodeLen != sizeof(DWORD))
    {
        delete [] pStatCode;
        //return 5; //Skip to check the values of the rest of the variables.
    }

    statCode = (DWORD)&pStatCode;

    if(statCode == HTTP_STATUS_NOT_FOUND)
        cout << "We got a 404 error" << endl;

    cout << "Stat code      : " << statCode << endl;
    cout << "Size of buffer : " << statCodeLen << endl;
    cout << "404 status code: " << HTTP_STATUS_NOT_FOUND << endl;


The stat code variable contains "2686376", but this doesn't make much sense because the buffer length was supposed to be 4 ( sizeof(DWORD) ).

I'm lost here. Most of the win32 API is not that difficult, but this is giving me some odd problems. (I'm sure its a stupid mistake though).

--D
Last edited on
closed account (DSLq5Di1)
Well.. you are grabbing the address of pStatCode, and assigning it to statCode.

statCode = atoi(static_cast<char*>(pStatCode));
You are missing the HTTP_QUERY_FLAG_NUMBER flag as per the Remarks section @ MSDN Online and you should have reinterpreted *pStatCode, not &pStatCode. Your buffer is also not needed. You can do it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    DWORD statCodeLen = sizeof(DWORD);
    DWORD statCode;

    //cout << "Size of DWORD: " << sizeof(DWORD) << endl;

    //Check existance of page (for 404 error)
    if(!HttpQueryInfo(hRequestHandle,
                      HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
                      &statCode,
                      &statCodeLen,
                      NULL))
    {
        return 4;
    }

    if(statCodeLen != sizeof(DWORD))
    {
        //return 5; //Skip to check the values of the rest of the variables.
    }

    if(statCode == HTTP_STATUS_NOT_FOUND)
        cout << "We got a 404 error" << endl;
Last edited on
Thanks, the statCodeLen is now the correct size (4 bytes), but there is no data in the statCode variable. When printed out, it is still "0". I'm not sure what to make of this, the code I am using is yours exactly.

Sorry I cant figure this out myself further, but it doesn't really make much sense.
If you are using my exact code, you'll notice that the DWORD statCode is not initialized to zero before calling the function. If you are debugging, most likely it contains a value other than zero before the function call. If after the function call you are getting zero, it means this is the value being written by HttpQueryInfo(). More I cannot tell you. I have never used this function before, so I have no prior experience.

If the function is indeed not failing, this is the code you are getting. My recommendation: Make an HTTP request that you know for sure it either works (HTTP_STATUS_OK) or doesn't (verify it using an Internet browser). Then compare to what your program is telling you. I would start here.
Topic archived. No new replies allowed.