HInternet works only one time - c++

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);

Related

Access secure website using winhttp . TLS 1.3

I have the following code that works with SSL sites like microsoft.com
but not with www.dmo.gov.uk.
When I open the site using chrome I can see that it requires TLS 1.3
But when I open this side from my Android phone it falls back on using 1.2
Is there any header or another way to force website to negotiate TLS 1.2 when I access it using Winhttp.
#include <iostream>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Winhttp.h>
#pragma comment(lib, "winhttp.lib")
static void APIENTRY StatusCallback(
HINTERNET handle,
DWORD_PTR context,
DWORD status,
LPVOID info,
DWORD size) {
handle;
DWORD err = 0;
if (status == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) {
err = *(DWORD*)info;
printf("Error flags %#010x\n", err);
}
}
int main()
{
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
BOOL bResults = FALSE;
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
BOOL ret = FALSE;
hSession = WinHttpOpen(
L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
DWORD secure_protocols =
WINHTTP_FLAG_SECURE_PROTOCOL_SSL3
| WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3;
ret = ::WinHttpSetOption(
hSession,
WINHTTP_OPTION_SECURE_PROTOCOLS,
&secure_protocols,
sizeof(secure_protocols));
WinHttpSetStatusCallback(
hSession,
StatusCallback,
WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0);
if (hSession)
hConnect = WinHttpConnect(
hSession,
L"www.dmo.gov.uk",
// L"www.microsoft.com",
INTERNET_DEFAULT_HTTPS_PORT, 0);
if (hConnect)
hRequest = WinHttpOpenRequest(
hConnect, L"GET", NULL,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE);
DWORD dwFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA
| SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE
| SECURITY_FLAG_IGNORE_CERT_CN_INVALID
| SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
ret = WinHttpSetOption(
hRequest,
WINHTTP_OPTION_SECURITY_FLAGS,
(void *)&dwFlags,
sizeof(dwFlags));
if (FALSE == ret) {
printf("Error %u in WinHttpSetOption.\n", GetLastError());
}
// Send a request.
if (hRequest) {
bResults = WinHttpSendRequest(
hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA,
0, 0, 0);
}
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse(
hRequest, nullptr);
// Keep checking for data until there is nothing left.
if (bResults)
do
{
// Check for available data.
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
printf("Error %d 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))
printf("Error %d in WinHttpReadData.\n", GetLastError());
else
printf("%s\n", pszOutBuffer);
// Free the memory allocated to the buffer.
delete[] pszOutBuffer;
}
} while (dwSize > 0);
// Report any errors.
if (!bResults)
printf("Error %d has occurred.\n", GetLastError());
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
}

POST Request in WinHttp c++

I'm trying to make a POST request in c++ with the WinHTTP api Click to the Microsoft Guide, the problem is that the example that is available in the microsoft webpage is a "GET" request so I came up with this code searching on the internet:
First we call the code:
HttpsWebRequestPost("example.com", "/api.php?action=UserLogin", "loginUsername=" + USERNAME + "&loginPassword=" + PASSWORD + "&url=/index.php?page=Portal");
Then:
#include <Windows.h>
#include <WinHttp.h>
#include <stdio.h>
#include <iostream> //getchar
#include <fstream>
#pragma comment(lib, "winhttp.lib")
using namespace std;
std::wstring get_utf16(const std::string &str, int codepage)
{
if (str.empty()) return std::wstring();
int sz = MultiByteToWideChar(codepage, 0, &str[0], (int)str.size(), 0, 0);
std::wstring res(sz, 0);
MultiByteToWideChar(codepage, 0, &str[0], (int)str.size(), &res[0], sz);
return res;
}
string HttpsWebRequestPost(string domain, string url, string dat)
{
//Extra
LPSTR data = const_cast<char *>(dat.c_str());;
DWORD data_len = strlen(data);
wstring sdomain = get_utf16(domain, CP_UTF8);
wstring surl = get_utf16(url, CP_UTF8);
string response;
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
BOOL bResults = FALSE;
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);
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect(hSession, sdomain.c_str(),
INTERNET_DEFAULT_HTTP_PORT, 0);
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect, L"POST", surl.c_str(),
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
// Send a request.
if (hRequest)
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
(LPVOID)data, data_len,
data_len, 0);
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
// Keep checking for data until there is nothing left.
if (bResults)
{
do
{
// Check for available data.
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
printf("Error %u 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))
printf("Error %u in WinHttpReadData.\n", GetLastError());
else
//printf("%s", pszOutBuffer);
response = response + string(pszOutBuffer);
// Free the memory allocated to the buffer.
delete[] pszOutBuffer;
}
} while (dwSize > 0);
}
// Report any errors.
if (!bResults)
printf("Error %d has occurred.\n", GetLastError());
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
return response;
}
But using WireShark I only get:
Hypertext Transfer Protocol
POST ***************** HTTP/1.1\r\n
Connection: Keep-Alive\r\n
User-Agent: WinHTTP Example/1.0\r\n
Content-Length: **\r\n
Host: ******\r\n
\r\n
Anyone can help meto fix this or know an easier method?
Thanks
In order for PHP (or any other post-processing language) to recognise POST data, add this:
LPCWSTR additionalHeaders = L"Content-Type: application/x-www-form-urlencoded\r\n";
DWORD headersLength = -1;
bResults = WinHttpSendRequest( hRequest,
additionalHeaders,
headersLength ,
(LPVOID)data,
data_len,
data_len,
0);
The rest of a code is functional, should work:
The following code works for me when I tried to post text in key(info) and value(this is some info) pair. The status code 200 returned at the end.
int main()
{
DWORD dwSize = 0;
LPVOID lpOutBuffer = NULL;
BOOL bResults = FALSE;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
std::wstring url{ L"http://app.pomdit.com:3010/uploadfile" };
URL_COMPONENTS components{};
components.dwStructSize = sizeof(components);
components.dwHostNameLength = (DWORD)-1;
components.dwUrlPathLength = (DWORD)-1;
if (!WinHttpCrackUrl(url.c_str(), static_cast<DWORD>(url.length()), 0, &components)) {
wprintf((L"WinHttpCrackUrl(): " + ErrorMessage(GetLastError())).c_str());
}
std::wstring hostName(components.lpszHostName ? std::wstring{ components.lpszHostName, components.dwHostNameLength } : L"localhost");
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect(hSession, hostName.c_str(),
components.nPort, 0);
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect, L"POST", components.lpszUrlPath,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
const WCHAR* ContentType =
L"Content-Type: multipart/form-data;boundary = 19024605111143684786787635207";
const char* MultipartRequestBody =
"--19024605111143684786787635207\r\n"
"Content-Disposition: form-data; name=\"info\"\r\n"
"\r\n"
"this is some info\r\n"
"--19024605111143684786787635207\r\n";
bResults = WinHttpSendRequest(hRequest, ContentType, wcslen(ContentType),
(LPVOID)MultipartRequestBody,
strlen(MultipartRequestBody),
strlen(MultipartRequestBody),
NULL);
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
// First, use WinHttpQueryHeaders to obtain the size of the buffer.
if (bResults)
{
DWORD status{}, len = sizeof(status);
bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &len, NULL);
if (bResults)
{
printf("Status code = %d.\n", status);
}
}
else
{
wprintf(L"WinHttpReceiveResponse(): %s\n", ErrorMessage(GetLastError()).c_str());
}
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
}

WinHttpReadData in Win32 app dont work properly

I use WinHTTP to get text from URL http://www.google.com/complete/search?output=toolbar&hl=vi&q=hoazzztf. The reponse text must be: <toplevel/> but I get the reponse like this:
Any idea? Thank!
(Reponse text may contains UTF-8 character)
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
BOOL bResults = FALSE;
hSession = WinHttpOpen(L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
WinHttpSetTimeouts(hSession, 1000, 2000, 1000, 1000);
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect(hSession, L"www.google.com",
INTERNET_DEFAULT_HTTPS_PORT, 0);
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/complete/search?output=toolbar&hl=vi&q=hoazzztf",
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE);
// Send a request.
if (hRequest)
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0,
0, 0);
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
if (!bResults)
{
SetWindowText(hWnd, L"ERR-4");
break;
}
if (bResults)
{
do
{
// Check for available data.
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
{
break;
}
// No more available data.
if (!dwSize)
break;
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize + 1];
if (!pszOutBuffer)
{
break;
}
// Read the Data.
ZeroMemory((LPVOID)pszOutBuffer, dwSize + 1);
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer,
dwSize, &dwDownloaded))
{
}
else
{
MessageBox(hWnd, (LPCWSTR)pszOutBuffer, L"", NULL);
}
// 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);
}
// Report any errors.
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
WinHttpReadData reads raw data, but you forced it to be an array of 2-byte WCHAR's. I think google uses utf-8 encoding on their pages, so you need to convert it first.
Another problem in your code is that you don't set terminating 0:
...
else
{
pszOutBuffer[ dwDownloaded ] = 0;
MessageBox(hWnd, pszOutBuffer, "", NULL);
}
Then, checking value returned by new is senseless, because new throws an exception in case of failure.
I fixed:
MessageBox(hWnd, (LPCWSTR)pszOutBuffer, L"", NULL);
to:
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, pszOutBuffer, -1, NULL, 0);
wchar_t* wstr = new wchar_t[wchars_num];
MultiByteToWideChar(CP_UTF8, 0, pszOutBuffer, -1, wstr, wchars_num);

Send JSON data via HttpOpenRequest

I'm not programming at C++, but i'm asking for someone who does, so i'm sorry if my question is simple or stupid.
I need a simple example of using HttpOpenRequest/HttpSendRequest objects in order to send JSON data to some web service/site.
Thank you
Here is a very bare bones example to send a JSON string to http://hostname/path/scriptname. You will have to add proper error checking, status code checking, etc as needed:
HINTERNET hInternet = InternetOpen(_T("MyApp"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hInternet, _T("hostname"), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
LPTSTR rgpszAcceptTypes[] = {_T("application/json"), NULL};
HINTERNET hRequest = HttpOpenRequest(hConnect, _T("POST"), _T("/path/scriptname"), NULL, NULL, rgpszAcceptTypes, 0, 0);
HttpAddRequestHeaders(hRequest, _T("Content-Type: application/json\r\n"), -1, HTTP_ADDREQ_FLAG_ADD);
char *JsonData = "..."; // your actual JSON data here
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)
{
// use InternetQueryDataAvailable() and InternetReadFile()
// to read any response data as needed...
}
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);

WCHAR to String, how do i do it?

String* Adder::downloadUrl(String* url)
{
DWORD dwSize = 0;
LPVOID lpOutBuffer = NULL;
BOOL bResults = FALSE;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen( L"A WinHTTP Example Program/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect( hSession, L"www.google.com",
INTERNET_DEFAULT_HTTP_PORT, 0);
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
// Send a request.
if (hRequest)
bResults = WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0,
0, 0);
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse( hRequest, NULL);
// First, use WinHttpQueryHeaders to obtain the size of the buffer.
if (bResults)
{
WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX, NULL,
&dwSize, WINHTTP_NO_HEADER_INDEX);
// Allocate memory for the buffer.
if( GetLastError( ) == ERROR_INSUFFICIENT_BUFFER )
{
lpOutBuffer = new WCHAR[dwSize/sizeof(WCHAR)];
// Now, use WinHttpQueryHeaders to retrieve the header.
bResults = WinHttpQueryHeaders( hRequest,
WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX,
lpOutBuffer, &dwSize,
WINHTTP_NO_HEADER_INDEX);
}
}
// Print the header contents.
if (bResults)
printf("Header contents: \n%S",lpOutBuffer);
// Free the allocated memory.
delete [] lpOutBuffer;
// Report any errors.
if (!bResults)
printf("Error %d has occurred.\n",GetLastError());
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
String* retOne;
return retOne;
}
I want to get response as string i am using dll in C#, dont know vc++ at all, please suggest a way.
String* retOne //how to get response;
return retOne;
UPDATE
// Convert a wide Unicode string to an UTF8 string
std::string utf8_encode(const std::wstring &wstr)
{
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo( size_needed, 0 );
WideCharToMultiByte (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
}
String* retOne = utf8_encode(lpOutBuffer);
Gives error: 'utf8_encode' : cannot convert parameter 1 from 'LPVOID' to 'const std::wstring
Please don't post comments suggesting use of .net libraries.
Looks like you need the WideCharToMultiByte function
Whats hard in this process is to understand the function WideCharToMultiByte.
Basically what you need to do in order to get the whole string (and avoid garbage as a result of not having a null terminating string) is first use:
int size_needed = WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)lpOutBuffer, -1, NULL, 0, NULL, NULL);
char *stringMe = new char[size_needed + 1];
While size_needed will be the required buffer size for lpMultiByteStr in the WideCharToMultiByte function.
Afterwards you just need to use that function again, since now you have the complete size:
WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)lpOutBuffer, -1, stringMe, size_needed, NULL, NULL);
stringMe[size_needed + 1] = NULL;
Now you can also convert it to String:
std::string serverOutput(stringMe);
Try this:
String* retOne = utf8_encode(std::wstring(lpOutBuffer));
or
String* retOne = utf8_encode(std::wstring((WCHAR*)lpOutBuffer));