Call server with WinInet and WinHTTP - c++

I have a request that works fine when I use the WinInet API. I now want to make that request with the WinHTTP API as I already use it in my project and as it is simply better. My request is used for calling JSON. I already authenticated before calling this. When authenticating I get a SessionID that I send via cookie.
So here is my working WinInet code:
DWORD dwError;
HINTERNET hOpen = NULL, hReq = NULL;
hOpen = InternetOpen(_T(""), INTERNET_OPEN_TYPE_DIRECT, _T(""), _T(""), 0);
if(hOpen == NULL)
{
dwError = GetLastError();
return false;
}
CString cstrCookies = _T("Cookie: JSESSIONID=") + cstrSession;
CString cstr = _T("https://") + cstrServer + _T("/list/") + cstrFileOrFolder;
hReq = InternetOpenUrl(hOpen, cstr, cstrCookies, -1L,
INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_COOKIES, 0); // without NO_COOKIES I'll get a 401
if(hReq == NULL)
{
dwError = GetLastError();
InternetCloseHandle(hOpen);
return false;
}
DWORD dwCode, dwCodeSize;
dwCodeSize = sizeof(DWORD);
if(!HttpQueryInfo(hReq, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwCode, &dwCodeSize, NULL))
{
dwError = GetLastError();
InternetCloseHandle(hReq);
InternetCloseHandle(hOpen);
return false;
}
InternetCloseHandle(hOpen);
InternetCloseHandle(hReq);
return dwCode == 200;
So I now want to do the same using the WinHTTP API. Here is what I have for the moment:
DWORD dwError = 0;
HINTERNET hConnect = NULL, hRequest = NULL;
hConnect = WinHttpConnect(m_hSession, cstrServer, INTERNET_DEFAULT_HTTPS_PORT, 0);
if (hConnect == NULL)
{
return false;
}
hRequest = WinHttpOpenRequest(hConnect, NULL, cstrMethod + _T("/list/") + cstrFileOrFolder,
NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
if (hRequest == NULL)
{
WinHttpCloseHandle(hConnect);
return false;
}
DWORD dwOptionValue = WINHTTP_DISABLE_COOKIES;
if (WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwOptionValue,
sizeof(dwOptionValue)) != TRUE)
{
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hRequest);
return false;
}
const CString cstrHeaders = _T("Cookie: JSESSIONID=") + cstrSession;
if (WinHttpAddRequestHeaders(hRequest, cstrHeaders, cstrHeaders.GetLength(),
WINHTTP_ADDREQ_FLAG_ADD) != TRUE)
{
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hRequest);
return false;
}
if (WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, -1L, WINHTTP_NO_REQUEST_DATA, 0,
0, 0) != TRUE)
{
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hRequest);
return false;
}
if (WinHttpReceiveResponse(hRequest, NULL) != TRUE)
{
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hRequest);
return false;
}
DWORD dwCode, dwCodeSize;
dwCodeSize = sizeof(DWORD);
if(!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwCode, &dwCodeSize, NULL))
{
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hRequest);
return false;
}
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hRequest);
return dwCode == 200;
With that latter call I always receive a 401 but I should get a 200 like I do with the first method. I also found out that I get a 401 with the first call when I don't specify the INTERNET_FLAG_NO_COOKIES flag. So I suspect something with the cookie header is wrong. Do anyone see what I'm doing wrong? Or what is the difference between the two methods?
Thx...

Looks about right.
If I were you I would hook up an HTTP debugging proxy, like Fiddler, and examine and compare the HTTP traffic for the two methods. That might point you to what you need to do.

Ok, I found it. Wasn't obvious from the code I posted...
The string cstrMethod contains a user id that I extracted previously from the response header from an authentication call. This id is then used for constructing the method call. Now problem was that the user id comes from a response header so it ends with \r\n. So the constructed method call also contains \r\n and as therefore the user id is wrong I get the 401.
So I had to trim the user id string from the header before I could use it for further calls.
Well it's a little bit odd that the WinInet call accepted the \r\n.

Related

WinHttp websockets listener

I am trying to develop a WebSockets client in C++ using WinHttp. I am making very slow progress (I am .NET developer). I have my WS server developed in .NET 6 and now I am working on a C++ console app that connects to the server and listens for messages.
So far I successfully connect to the server and upgrade the connection to WS but struggle setting up the callback that triggers when a new message was sent from the server. I spent hours finding an example with no success.
Can someone please help me how to set the callback for the below code or provide me with a working example?
static void CALLBACK Callback(HINTERNET handle,
DWORD_PTR context,
DWORD code,
void* info,
DWORD length)
{
switch (code) {
case WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE:
{
int i = 0;
break;
}
case WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED:
{
int i = 0;
break;
}
case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE:
{
int i = 0;
break;
}
default:
{
}
}
if (0 != context)
{
}
}
int main()
{
DWORD dwError = ERROR_SUCCESS;
BOOL fStatus = FALSE;
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
BOOL bResults = FALSE;
HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL, hWebSocket = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen(L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0);
//WINHTTP_FLAG_ASYNC);
if (hSession == NULL)
{
dwError = GetLastError();
}
// Setup the status callback function.
WINHTTP_STATUS_CALLBACK isCallback = WinHttpSetStatusCallback(hSession,
(WINHTTP_STATUS_CALLBACK)Callback,
WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS,
NULL);
hConnect = WinHttpConnect(hSession, L"localhost", 5004, 0);
if (hConnect == NULL)
{
dwError = GetLastError();
}
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect,
L"GET",
L"/ws",
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);//WINHTTP_FLAG_SECURE); // flags
if (hRequest == NULL)
{
dwError = GetLastError();
}
//
// Request protocol upgrade from http to websocket.
//
#pragma prefast(suppress:6387, "WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET does not take any arguments.")
fStatus = WinHttpSetOption(hRequest,
WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET,
NULL,
0);
if (!fStatus)
{
dwError = GetLastError();
}
// Send a request.
if (hRequest)
fStatus = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0, // request data length
0, // total length
0); // context
if (!fStatus)
{
dwError = GetLastError();
}
fStatus = WinHttpReceiveResponse(hRequest, 0);
if (!fStatus)
{
dwError = GetLastError();
}
//
// Application should check what is the HTTP status code returned by the server and behave accordingly.
// WinHttpWebSocketCompleteUpgrade will fail if the HTTP status code is different than 101.
//
hWebSocket = WinHttpWebSocketCompleteUpgrade(hRequest, NULL);
if (hWebSocket == NULL)
{
dwError = GetLastError();
}
//
// The request handle is not needed anymore. From now on we will use the websocket handle.
//
WinHttpCloseHandle(hRequest);
hRequest = NULL;
std::cout << "Connected to WS!\n";
}

WinHttpSendRequest continuously fails with windows error code 87, ERROR_INVALID_PARAMETER (C++)

I am trying to send an http post request through a proxy that has headers and optionally, json content, using WinHTTP. I have tried solutions outlined in the questions here:
WinHttpSendRequest failed with error code 87
WinHttpSendRequest returns ERROR_INVALID_PARAMETER
However, it just does not seem to change anything. I have the post request functions pasted below. Perhaps there is something that I missed. Please let me know if there is anything I can do to fix this.
The problematic area is around WinHttpSendRequest
std::string PostRequest(std::wstring token, std::string json, std::string proxy, std::wstring url, std::wstring domain) {
std::cout<<"PostRequest function started"<<std::endl;
std::cout<<"json is being processed"<<std::endl;
LPSTR data = (LPSTR)json.c_str();
DWORD data_len;
if(data!=0) data_len = strlen(data); else data_len = 0;
std::cout<<"json done"<<std::endl<<GetLastError()<<std::endl;
std::string response;
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
BOOL bResults = FALSE;
HINTERNET hConnect = NULL, hRequest = NULL;
std::wstring stemp = std::wstring(proxy.begin(), proxy.end());
const wchar_t* sw = stemp.c_str();
std::cout<<"initializing WinHttpOpen"<<std::endl<<GetLastError()<<std::endl;
HINTERNET hSession=WinHttpOpen(L"WinHTTP Example/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, L"http://"+*sw, WINHTTP_NO_PROXY_BYPASS, 0);
std::cout<<"initializing WinHttpConnect"<<std::endl<<GetLastError()<<std::endl;
if(hSession) hConnect = WinHttpConnect(hSession, domain.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0 );
std::cout<<"initializing WinHttpOpenRequest"<<std::endl<<GetLastError()<<std::endl;
if(hConnect) hRequest = WinHttpOpenRequest(hConnect, L"POST", url.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
const wchar_t *additionalHeaders =
L"Content-Type: application/json\r\n"
L"User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11\r\n"
L"Authorization: "+*token.c_str()+*L"\r\n";
DWORD headersLength = -1;
std::cout<<"initializing WinHttpSendRequest"<<std::endl<<GetLastError()<<std::endl;
std::cout<<"bResults: "<<bResults<<std::endl;
LPVOID rqdata;
if(data==0)rqdata = WINHTTP_NO_REQUEST_DATA;
else rqdata=(LPVOID)data;
if (hRequest) bResults = WinHttpSendRequest(hRequest, additionalHeaders, headersLength, rqdata, data_len, data_len, 0);
else std::cout<<"else 1"<<std::endl;
std::cout<<"bResults: "<<bResults<<std::endl;
std::cout<<"initializing WinHttpReceiveResponse"<<std::endl<<GetLastError()<<std::endl;
if (bResults) bResults = WinHttpReceiveResponse(hRequest, NULL);
else std::cout<<"else 2"<<std::endl;
std::cout<<"bResults: "<<bResults<<std::endl;
if (bResults)
{
do
{
// Check for available data.
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
std::cout<<"Error in WinHttpQueryDataAvailable.\n"<<GetLastError();
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize + 1];
if (!pszOutBuffer)
{
printf("Out of memory\n");
dwSize = 0;
}
else
{
// Read the data.
ZeroMemory(pszOutBuffer, dwSize + 1);
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer,
dwSize, &dwDownloaded))
std::cout<<"Error in WinHttpReadData.\n"<<GetLastError();
else
response = response + std::string(pszOutBuffer);
// Free the memory allocated to the buffer.
delete[] pszOutBuffer;
}
} while (dwSize > 0);
}
if (!bResults)
std::cout<<"Error has occurred.\n"<<GetLastError()<<std::endl;
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
return response;
}
all of the cout's are for debugging which will be removed by me later.
The output looks like this: (sorry if it is kind of messy)
PostRequest function started
json is being processed
json done
0
initializing WinHttpOpen
0
initializing WinHttpConnect
0
initializing WinHttpOpenRequest
0
initializing WinHttpSendRequest
0
bResults: 0
bResults: 0
initializing WinHttpReceiveResponse
87
else 2
bResults: 0
Error has occurred.
87

HInternet works only one time

This code is in a C++ DLL injected in a game. (This is on a private server so it is legal). The code has to be executed multiple times. However, it works only the first time. It could be on the WCF end but I managed to send 2 and 5 successful requests from a .net dll loaded from the c++ dll before.
Since I didn't figure out why it was blocked after 2 and 5 requests, I decided to go all native but now I'm blocked after one request. I have a feeling it now has to do with the way I'm parsing the response.
The first execution gets a 200 code status and the second one gets a 0.
edit : my fire wall is turned off.
HINTERNET hInternet = InternetOpen(_T("MyApp"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hInternet, _T("localhost"), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
LPCSTR rgpszAcceptTypes[] = { _T("application/json"), NULL };
HINTERNET hRequest = HttpOpenRequest(hConnect, _T("POST"), _T("/xxxBackend/service1.svc/SaveDataVoid"), NULL, NULL, rgpszAcceptTypes, 0, 0);
HttpAddRequestHeaders(hRequest, _T("Content-Type: application/json\r\n"), -1, HTTP_ADDREQ_FLAG_ADD);
char *JsonData = "{\"data\":{\"AccountName\":\"\",\"CharName\":\"SilverDeth-IV\",\"GameDiff\":\"1\",\"CompressedData\":[8228138568842941382,8247906688399250381,8244242016143283142]}}";
HttpSendRequest(hRequest, NULL, 0, JsonData, strlen(JsonData));
DWORD StatusCode = 0;
DWORD StatusCodeLen = sizeof(StatusCode);
HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &StatusCode, &StatusCodeLen, NULL);
if (StatusCode == 200)
{
char *lpBuffer[2000];
DWORD lpdwNumberOfBytesRead = 0;
InternetQueryDataAvailable(hRequest, &StatusCodeLen, 0, 0);
bool bRetval = InternetReadFile(hRequest, lpBuffer, 2000, &lpdwNumberOfBytesRead);
}
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
The code you have shown is not doing ANY error handling at all. Add that in, and then see where the failure is really occurring. The fact that StatusCode is 0 means HttpQueryInfo() is failing, which could happen if you did not obtain a valid hRequest to begin with.
BTW, rgpszAcceptTypes needs to be declared as LPCTSTR instead of LPCSTR, and you should be using the TEXT() macro instead of the _T() macro. TEXT() belongs to the Win32 API, but _T() belongs to the C runtime library, which you are not using in this code.
Try this:
void InetError(LPCTSTR msg)
{
DWORD dwErr = GetLastError();
if (dwErr == ERROR_INTERNET_EXTENDED_ERROR)
{
DWORD dwInetErr = 0;
LPTSTR szResp = NULL;
DWORD dwLength = 0;
InternetGetLastResponseInfo(&dwInetErr, NULL, &dwLength);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
szResp = new TCHAR[dwLength+1];
InternetGetLastResponseInfo(&dwInetErr, szResp, &dwLength);
}
// use msg, szResp, and dwInetErr as needed...
delete[] szResp;
}
else
{
// use msg and dwErr as needed...
}
}
...
HINTERNET hInternet = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
hInternet = InternetOpen(TEXT("MyApp"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!hInternet)
{
InetError(TEXT("InternetOpen failed"));
goto done;
}
hConnect = InternetConnect(hInternet, TEXT("localhost"), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (!hConnect)
{
InetError(TEXT("InternetConnect failed"));
goto done;
}
LPCTSTR rgpszAcceptTypes[] = { TEXT("application/json"), NULL };
hRequest = HttpOpenRequest(hConnect, TEXT("POST"), TEXT("/xxxBackend/service1.svc/SaveDataVoid"), NULL, NULL, rgpszAcceptTypes, 0, 0);
if (!hRequest)
{
InetError(TEXT("HttpOpenRequest failed"));
goto done;
}
if (!HttpAddRequestHeaders(hRequest, TEXT("Content-Type: application/json\r\n"), -1, HTTP_ADDREQ_FLAG_ADD))
{
InetError(TEXT("HttpAddRequestHeaders failed"));
goto done;
}
char *JsonData = "{\"data\":{\"AccountName\":\"\",\"CharName\":\"SilverDeth-IV\",\"GameDiff\":\"1\",\"CompressedData\":[8228138568842941382,8247906688399250381,8244242016143283142]}}";
if (!HttpSendRequest(hRequest, NULL, 0, JsonData, strlen(JsonData)))
{
InetError(TEXT("HttpSendRequest failed"));
goto done;
}
DWORD StatusCode = 0;
DWORD StatusCodeLen = sizeof(StatusCode);
if (!HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &StatusCode, &StatusCodeLen, NULL))
{
InetError(TEXT("HttpQueryInfo failed"));
goto done;
}
if (StatusCode == 200)
{
BYTE Buffer[2000];
DWORD dwNumberOfBytes = 0;
DWORD dwNumberOfBytesRead = 0;
if (!InternetQueryDataAvailable(hRequest, &dwNumberOfBytes, 0, 0))
{
InetError(TEXT("InternetQueryDataAvailable failed"));
goto done;
}
if (!InternetReadFile(hRequest, Buffer, min(dwNumberOfBytes, sizeof(Buffer)), &dwNumberOfBytesRead))
{
InetError(TEXT("InternetReadFile failed"));
goto done;
}
//...
}
done:
if (hRequest) InternetCloseHandle(hRequest);
if (hConnect) InternetCloseHandle(hConnect);
if (hInternet) InternetCloseHandle(hInternet);

WinHTTP Website Login

I am trying to retrieve the source code of a web page using WinHTTP. Reading from this page: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384110(v=vs.85).aspx
I was able to come up with this code. The HTTP status code is 200 which means the request was completed correctly. I end up getting the source code for the login page instead of my intended web page behind it.
Should I send a httprequest to the login page and then to the file path?
Here is the code:
#include <windows.h>
#include <winhttp.h>
#include <string>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
#pragma comment(lib, "winhttp.lib")
DWORD ChooseAuthScheme(DWORD dwSupportedSchemes)
{
// It is the server's responsibility only to accept
// authentication schemes that provide a sufficient
// level of security to protect the servers resources.
//
// The client is also obligated only to use an authentication
// scheme that adequately protects its username and password.
//
// Thus, this sample code does not use Basic authentication
// becaus Basic authentication exposes the client's username
// and password to anyone monitoring the connection.
if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NEGOTIATE)
return WINHTTP_AUTH_SCHEME_NEGOTIATE;
else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NTLM)
return WINHTTP_AUTH_SCHEME_NTLM;
else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_PASSPORT)
return WINHTTP_AUTH_SCHEME_PASSPORT;
else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_DIGEST)
return WINHTTP_AUTH_SCHEME_DIGEST;
else
return 0;
}
struct SWinHttpSampleGet
{
LPCWSTR szServer;
LPCWSTR szPath;
BOOL fUseSSL;
LPCWSTR szServerUsername;
LPCWSTR szServerPassword;
LPCWSTR szProxyUsername;
LPCWSTR szProxyPassword;
};
void WinHttpAuthSample(IN SWinHttpSampleGet *pGetRequest)
{
string contents;
DWORD dwStatusCode = 0;
DWORD dwSupportedSchemes;
DWORD dwFirstScheme;
DWORD dwSelectedScheme;
DWORD dwTarget;
DWORD dwLastStatus = 0;
DWORD dwSize = sizeof(DWORD);
BOOL bResults = FALSE;
BOOL bDone = FALSE;
DWORD dwProxyAuthScheme = 0;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen(L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
INTERNET_PORT nPort = (pGetRequest->fUseSSL) ?
INTERNET_DEFAULT_HTTPS_PORT :
INTERNET_DEFAULT_HTTP_PORT;
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect(hSession,
pGetRequest->szServer,
nPort, 0);
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect,
L"GET",
pGetRequest->szPath,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
(pGetRequest->fUseSSL) ?
WINHTTP_FLAG_SECURE : 0);
// Continue to send a request until status code
// is not 401 or 407.
if (hRequest == NULL)
bDone = TRUE;
while (!bDone)
{
// If a proxy authentication challenge was responded to, reset
// those credentials before each SendRequest, because the proxy
// may require re-authentication after responding to a 401 or
// to a redirect. If you don't, you can get into a
// 407-401-407-401- loop.
if (dwProxyAuthScheme != 0)
bResults = WinHttpSetCredentials(hRequest,
WINHTTP_AUTH_TARGET_PROXY,
dwProxyAuthScheme,
pGetRequest->szProxyUsername,
pGetRequest->szProxyPassword,
NULL);
// Send a request.
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0);
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
// Resend the request in case of
// ERROR_WINHTTP_RESEND_REQUEST error.
if (!bResults && GetLastError() == ERROR_WINHTTP_RESEND_REQUEST)
continue;
// Check the status code.
if (bResults)
bResults = WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_STATUS_CODE |
WINHTTP_QUERY_FLAG_NUMBER,
NULL,
&dwStatusCode,
&dwSize,
NULL);
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
if (bResults)
{
switch (dwStatusCode)
{
case 200:
// The resource was successfully retrieved.
// You can use WinHttpReadData to read the
// contents of the server's response.
printf("The resource was successfully retrieved.\n");
do
{
// Check for available data.
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
{
printf("Error %u in WinHttpQueryDataAvailable.\n",
GetLastError());
break;
}
// No more available data.
if (!dwSize)
break;
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize + 1];
if (!pszOutBuffer)
{
printf("Out of memory\n");
break;
}
// Read the Data.
ZeroMemory(pszOutBuffer, dwSize + 1);
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer,
dwSize, &dwDownloaded))
{
printf("Error %u in WinHttpReadData.\n", GetLastError());
}
else
{
printf("%s", pszOutBuffer);
contents += pszOutBuffer;
}
// Free the memory allocated to the buffer.
delete[] pszOutBuffer;
// This condition should never be reached since WinHttpQueryDataAvailable
// reported that there are bits to read.
if (!dwDownloaded)
break;
} while (dwSize > 0);
bDone = true;
break;
case 401:
// The server requires authentication.
printf(" The server requires authentication. Sending credentials...\n");
// Obtain the supported and preferred schemes.
bResults = WinHttpQueryAuthSchemes(hRequest,
&dwSupportedSchemes,
&dwFirstScheme,
&dwTarget);
// Set the credentials before resending the request.
if (bResults)
{
dwSelectedScheme = ChooseAuthScheme(dwSupportedSchemes);
if (dwSelectedScheme == 0)
bDone = TRUE;
else
bResults = WinHttpSetCredentials(hRequest,
dwTarget,
dwSelectedScheme,
pGetRequest->szServerUsername,
pGetRequest->szServerPassword,
NULL);
}
// If the same credentials are requested twice, abort the
// request. For simplicity, this sample does not check
// for a repeated sequence of status codes.
if (dwLastStatus == 401)
bDone = TRUE;
break;
case 407:
// The proxy requires authentication.
printf("The proxy requires authentication. Sending credentials...\n");
// Obtain the supported and preferred schemes.
bResults = WinHttpQueryAuthSchemes(hRequest,
&dwSupportedSchemes,
&dwFirstScheme,
&dwTarget);
// Set the credentials before resending the request.
if (bResults)
dwProxyAuthScheme = ChooseAuthScheme(dwSupportedSchemes);
// If the same credentials are requested twice, abort the
// request. For simplicity, this sample does not check
// for a repeated sequence of status codes.
if (dwLastStatus == 407)
bDone = TRUE;
break;
default:
// The status code does not indicate success.
printf("Error. Status code %d returned.\n", dwStatusCode);
bDone = TRUE;
}
}
// Keep track of the last status code.
dwLastStatus = dwStatusCode;
// If there are any errors, break out of the loop.
if (!bResults)
bDone = TRUE;
}
// Report any errors.
if (!bResults)
{
DWORD dwLastError = GetLastError();
printf("Error %d has occurred.\n", dwLastError);
}
ofstream fout("Output.txt");
fout << contents;
fout.close();
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
}
int main()
{
wstring Server = L"moodle.redlands.edu";
wstring Path = L"/course/view.php?id=2213/";
wstring User = L"test";
wstring Pass = L"password";
wstring User_Proxy = L"test";
wstring Pass_Proxy = L"password";
SWinHttpSampleGet Lawl{
Server.c_str(),
Path.c_str(),
1,
User.c_str(),
Pass.c_str(),
User_Proxy.c_str(), Pass_Proxy.c_str()
};
WinHttpAuthSample(&Lawl);
system("PAUSE");
return 0;
}

C++ wininet, connect to weblogin, how to set cookies?

Hey all i want to login onto my works webpage with wininet, this is my current code:
int main()
{
HINTERNET hInet = InternetOpenA("UserAgent/1.0", INTERNET_OPEN_TYPE_PRECONFIG,0, 0, 0 );
if(!hInet)
{
printf("hInet Failed!\n");
return -1;
}
HINTERNET hConnection = InternetConnectA( hInet,"app.tamigo.com",INTERNET_DEFAULT_HTTPS_PORT,"","", INTERNET_SERVICE_HTTP,0,0);
if (!hConnection)
{
InternetCloseHandle(hInet);
printf("InternetConnectA failed!\n");
return -1;
}
HINTERNET hRequest = HttpOpenRequestA( hConnection, "Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",NULL,"https://app.tamigo.com/Home/Pages/Login.aspx", NULL, INTERNET_FLAG_KEEP_CONNECTION, 0 );
if (!hRequest)
{
printf("BuildRequestHeader failed %d!\n",GetLastError());
InternetCloseHandle(hConnection);
InternetCloseHandle(hInet);
return -1;
}
HttpSendRequestA(hRequest, NULL, 0, NULL, 0);
DWORD dwInfoLevel = HTTP_QUERY_RAW_HEADERS_CRLF;
DWORD dwInfoBufferLength = 10;
BYTE *pInfoBuffer = (BYTE *)malloc(dwInfoBufferLength+1);
while (!HttpQueryInfo(hRequest, dwInfoLevel, pInfoBuffer, &dwInfoBufferLength, NULL))
{
DWORD dwError = GetLastError();
if (dwError == ERROR_INSUFFICIENT_BUFFER)
{
free(pInfoBuffer);
pInfoBuffer = (BYTE *)malloc(dwInfoBufferLength+1);
}
else
{
fprintf(stderr, "HttpQueryInfo failed, error = %d (0x%x)\n",
GetLastError(), GetLastError());
break;
}
}
pInfoBuffer[dwInfoBufferLength] = '\0';
printf("%s", pInfoBuffer);
free(pInfoBuffer);
cin.get();
return 1;
}
if this code is right, i have to login with my username and pass,i got a cookie using "Firefox plugin Tamper Data". How can i set this cookie with wininet?
Thanks alot for reading and for your time
If the cookie already exists from a previous WinInet request, then WinInet will send it automatically. However, if the cookie does not exist in WinInet's cookie cache (if instance, if you got the cookie from another source), then you will have to use HttpAddRequestHeaders() to provide your own Cookie: request header before calling HttpSendRequest().