using google-geocoding-api from China - c++

I'm a green hand coder from China. I met some problem in using the google-geocoding-api, it is correct when I debug with the following code, but there is no response when I use the gennerated .exe file compile in release mode。Cause I am in China,So I can just use the net agent to visit the URL,so I don't kown wheteher it is the problem of net work or the problem of my code. Could someone help me to try the following code to check the exactly problem.
// street_name.cpp :
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <Windows.h>
#include <wininet.h>
using namespace std;
#define MAXBLOCKSIZE 500
#pragma comment (lib, "wininet.lib")
void download(const char*);
int main(int argc, char* argv[]){
const char *cUrl = NULL;
char Url[512];
float lat = 45.798748;
float lng = 126.531115;
sprintf(Url,"https://maps.googleapis.com/maps/api/geocode/xml?latlng=45.797749,126.523811&result_type=route&address_component_type=route&key=AIzaSyC6M3Pbbjdrgtl8QZjuJPK-1JdAJD5oEgA",lat,lng);
cUrl = Url;
download(cUrl);
if (argc > 1)
{
download((const char*)argv[1]);
}
else
{
cout << "Usage: auto-Update url";
}
return 0;
}
/**
*
* #param Url: The target action url
*
*/
void download(const char *Url)
{
HINTERNET hSession = InternetOpenA("RookIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
string StreetName;
if (hSession != NULL)
{
HINTERNET handle2 = InternetOpenUrlA(hSession, Url, NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
if (handle2 != NULL)
{
cout << Url << endl;
byte Temp[MAXBLOCKSIZE] = {0};
ULONG Number = 1;
int i = 0;
ofstream ofs("baidu.txt");
if (ofs)
{
while (Number > 0)
{
InternetReadFile(handle2, Temp, MAXBLOCKSIZE - 1, &Number);
string a = string((const char*)Temp,Number);
ofs << a.c_str();
StreetName += a;
}
ofs.close();
}
InternetCloseHandle(handle2);
handle2 = NULL;
}
InternetCloseHandle(hSession);
hSession = NULL;
}
}

If your requests are coming from China, it may be that HTTPS requests are blocked. Try HTTP.
I'm thinking this may be related to https://meta.stackexchange.com/questions/191338/https-problem-when-accessing-stack-overflow-in-china

Related

Serial Communication C++ Select Connect

main
#include "stdafx.h"
#include <iostream>
#include "SerialPort.h"
#include <WinBase.h>
using namespace std;
int main()
{
cout << "Monitoring System \n";
cout << "Please select a connection method\n\n";
cout << "1.Serial 2.TCP \n";
int num;
while (!(cin >> num))
{
cin.clear();
cin.ignore(INT_MAX, '\n');
cout << "Please enter a number only ";
}
if(num==1)
{
int i,SN;
int k=0;
cout << "Scan all ports that are currently...\n";
for (i = 1; i < 30; ++i)
{
if (COM_exists(i))
{
cout <<++k<< ".COM" << i << "\n";
}
}
cout << "\nselect a port to connect.\n";
scanf_s("%d", &SN, sizeof SN);
if (SN == 1)
{
SerialPort PortOpen("COM", CBR_115200, 8, "#or", 24);
PortOpen.getData();
PortOpen.getData();
cout << PortOpen.SerialBuffer << endl;
return 0;
}
}
}
serial cpp
#include "stdafx.h"
#include <string.h>
#include "SerialPort.h"
using namespace std;
BOOL COM_exists(int port)
{
char buffer[7];
COMMCONFIG CommConfig;
DWORD size;
if (!(1 <= port && port <= 30))
{
return FALSE;
}
snprintf(buffer, sizeof buffer, "COM%d", port);
size = sizeof CommConfig;
// COM port exists if GetDefaultCommConfig returns TRUE
// or changes <size> to indicate COMMCONFIG buffer too small.
return (GetDefaultCommConfig(buffer, &CommConfig, &size)
|| size > sizeof CommConfig);
}
SerialPort::SerialPort(LPCSTR COM,int setBaudRate, int setByteSize, char* commandBuffer, int BufSize) {
this->BufSize = BufSize;
this->SerialBuffer = new char[BufSize];
this->NoBytesRead = BufSize;
Connect(COM, setBaudRate, setByteSize, commandBuffer);
}
void SerialPort::Connect(LPCSTR COM ,int setBaudRate, int setByteSize, char* commandBuffer) {
this->COMport = COM;
this->hComm = CreateFile(COM, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); // (port name, read/write , no sharing , no security, open existing port only, non overlapped i/o , null for comm devices)
if (this->hComm == INVALID_HANDLE_VALUE)
cout << "PortOpen Fail." << endl;
else {
cout << "PortOpen Success." << endl;
sendCommand(setBaudRate, setByteSize, commandBuffer);
}
}
void SerialPort::sendCommand(int setBaudRate, int setByteSize, char* commandBuffer) {
this->commandBuffer = commandBuffer;
this->dNoOFBytestoWrite = sizeof(commandBuffer);
this->Status = WriteFile(hComm, commandBuffer, dNoOFBytestoWrite, &dNoOfBytesWritten, NULL);
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
dcbSerialParams.BaudRate = setBaudRate;
dcbSerialParams.ByteSize = setByteSize;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 10;
timeouts.ReadTotalTimeoutConstant = 10;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (this->Status)
cout << "Command Successful" << endl;
else
{
cout << "fail to Command" << endl;
}
}
void SerialPort::getData() {
ReadFile(this->hComm, &*this->SerialBuffer, this->BufSize, &this->NoBytesRead, NULL);
}
SerialPort.h
#pragma once
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <WinBase.h>
using namespace std;
class SerialPort {
public:
HANDLE hComm;
LPCSTR COMport;
DWORD dNoOFBytestoWrite;
DWORD dNoOfBytesWritten;
int BufSize;
int Status;
char* SerialBuffer;
char* commandBuffer;
DWORD NoBytesRead;
int port;
SerialPort(LPCSTR COMport,int setBaudRate, int setByteSize, char* commandBuffer, int BufSize);
void Connect(LPCSTR COMport, int setBaudRate, int setByteSize, char* commandBuffer);
void sendCommand(int setBaudRate, int setByteSize, char* commandBuffer);
void getData();
};
BOOL COM_exists(int port);
I am writing a code to connect by selecting a serial port.
example, 1.COM1 / 2.COM3 / 3.COM4
How do I modify the main to connect COM4 that matches No. 3?
How do I automatically read and use matching ports to match numbers?
I am writing a code to connect by selecting a serial port.
example, 1.COM1 / 2.COM3 / 3.COM4
How do I modify the main to connect COM4 that matches No. 3?
How do I automatically read and use matching ports to match numbers?
I would personally never ever use the old school style open and close COM port to detect if it exists.
Assuming you are running on Windows I would use the SetupDi to find the serial port without opening it.
A little snippet to adapt:
#include <initguid.h>
#include <windows.h> // Data Type
#include <setupapi.h> // ::SetupDi*********
#include <devguid.h> // Device
// Global Variables
HDEVINFO m_hDevInfo; //!< Reference to device information set
SP_DEVINFO_DATA m_spDevInfoData; //!< Device information structure (references a device instance that is a member of a device information set)
BOOL m_bDevInfo; //!< Tested to ensure EnumDeviceInfo has been called
short m_MemberIndex = -1; //!< Preserves state between EnumDeviceInfo calls
bool WIN_EnumDeviceInfo ()
{
m_MemberIndex++;
m_spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
m_bDevInfo = ::SetupDiEnumDeviceInfo(m_hDevInfo, m_MemberIndex, &m_spDevInfoData);
return m_bDevInfo;
}
bool WIN_GetDeviceRegistryProperty(DWORD Property, PBYTE PropertyBuffer)
{
BOOL bGotRegProp = ::SetupDiGetDeviceRegistryProperty(m_hDevInfo, &m_spDevInfoData,
Property,
0L,
PropertyBuffer,
2048,
0);
return bGotRegProp;
}
void ScanSerial()
{
WORD Flags;
PCWSTR Enumerator=0;
const GUID *ClassGuid;
HWND m_hWnd;
ClassGuid = &GUID_DEVCLASS_PORTS;
Flags = DIGCF_PROFILE;
m_hDevInfo = SetupDiGetClassDevs(ClassGuid, Enumerator, m_hWnd, Flags);
while(WIN_EnumDeviceInfo())
{
wchar_t szBuf[MAX_PATH] = {0};
if(WIN_GetDeviceRegistryProperty(SPDRP_CLASS, (PBYTE)szBuf))
{
wchar_t szFriendlyName[MAX_PATH] = {0};
WIN_GetDeviceRegistryProperty (SPDRP_FRIENDLYNAME, (PBYTE)szFriendlyName);
}
}
}
From the szFriendlyName you can filter the COMx number without opening it or either confusing them...
Try and enjoy...

How to bundle static library into NSIS plugin

I'm new in NSIS and C++.
I write a NSIS plugin to check a license with http request with VS2010.
But the plugin only work on the computers with VS2010 installed.
I guess the reason is the libraries like "ws2_32.lib" is not bundled in the package.
I want the installation package with this plugin worked on the computers without C++ installed.
Is there any idea how to solve it?
Thanks a lot.
Here is my code.
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <WinSock2.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
#include <string.h>
#include <stdio.h>
#include "./../nsis/pluginapi.h"
#include <windows.h>
#include <Wincrypt.h>
#pragma comment(lib,"crypt32")
#pragma comment(lib,"./../nsis/pluginapi-x86-unicode.lib")
#pragma comment(lib, "ws2_32.lib")
void __declspec(dllexport) myFunction(HWND hwndParent, int string_size,
TCHAR *variables, stack_t **stacktop,
extra_parameters *extra)
{
g_hwndParent = hwndParent;
EXDLL_INIT();
//读取输入参数
WCHAR szComponent[256];
popstring(szComponent);
//打印参数
WCHAR buf[1024];
//这里能正确打印出来自NSIS的中文信息。
//wsprintf(buf, L"kagula $0=[%s][szComponent]\n", szComponent);
//MessageBoxW(g_hwndParent, buf, 0, MB_OK);
WCHAR urlComponent[256];
popstring(urlComponent);
//wsprintf(buf, L"kagula $0=[%s][urlComponent]\n", urlComponent);
//MessageBoxW(g_hwndParent, buf, 0, MB_OK);
WCHAR ipComponent[256];
popstring(ipComponent);
WCHAR portComponent[256];
popstring(portComponent);
//准备返回参考
int len = (int)wcslen(szComponent);
int input_len = (int)wcslen(szComponent);
//printf("%d\n", input_len);
//char server_id[256];
//for (int i = 0; i <
char* server_id = wchar2char(szComponent);
printf("%d\n", strlen(server_id));
//char* server_id = new char(256);
//for (int i = 0; i < input_len; i++) {
// server_id[i] = szComponent[i];
//}
//to_narrow(szComponent, server_id, 256);
printf("serid %s", server_id);
//打印参数
char* ret = ""; // 返回Http Response
try
{
// 开始进行socket初始化
WSADATA wData;
::WSAStartup(MAKEWORD(2, 2), &wData);
SOCKET clientSocket = socket(AF_INET, 1, 0);
struct sockaddr_in ServerAddr = {0};
char* m_ip = wchar2char(ipComponent);
int m_port = atoi(wchar2char(portComponent));
char* req = wchar2char(urlComponent);
WCHAR bufchar[3069];
//这里能正确打印出来自NSIS的中文信息。
//wsprintf(bufchar, L"kagula $0=[%s][server_id]\n", char2wchar(server_id));
//MessageBoxW(g_hwndParent, bufchar, 0, MB_OK);
printf("req %s", req);
char* urlSend = (char*) malloc(strlen(req) + strlen(server_id));
strcpy(urlSend, req);
strcat(urlSend, server_id);
//strcat(req, server_id);
printf("req %s", req);
ServerAddr.sin_addr.s_addr = inet_addr(m_ip);
ServerAddr.sin_port = htons(m_port);
ServerAddr.sin_family = AF_INET;
int errNo = connect(clientSocket, (sockaddr*)&ServerAddr, sizeof(ServerAddr));
printf("errNo connect %d \n", errNo);
if(errNo == 0)
{
// "GET /[req] HTTP/1.1\r\n"
// "Connection:Keep-Alive\r\n"
// "Accept-Encoding:gzip, deflate\r\n"
// "Accept-Language:zh-CN,en,*\r\n"
// "User-Agent:Mozilla/5.0\r\n\r\n";
char* cookie = " HTTP/1.1\r\nCookie:16888\r\n\r\n";
// strSend = "GET " + req + strSend;
char* gp = "GET ";
char* strSend = (char*) malloc(strlen(gp) + strlen(cookie) + strlen(urlSend));
strcpy(strSend, gp);
strcat(strSend, urlSend);
strcat(strSend, cookie);
// 发送
errNo = send(clientSocket, strSend, strlen(strSend), 0);
if(errNo > 0)
{
//cout << "发送成功" << endl;
}
else
{
//std::cout << "errNo:" << errNo << std::endl;
printf("errNo:");
// return ret;
}
// 接收
char bufRecv[3069] = {0};
errNo = recv(clientSocket, bufRecv, 3069, 0);
if(errNo > 0)
{
ret = bufRecv;// 如果接收成功,则返回接收的数据内容
}
else
{
// std::cout << "errNo:" << errNo << std::endl;
printf("errNo:");
// return ret;
}
}
else
{
errNo = WSAGetLastError();
// std::cout << "errNo:" << errNo << std::endl;
printf("errNo:");
printf(errNo + "");
}
// socket环境清理
::WSACleanup();
}
catch (...)
{
// return "";
}
printf(ret);
// push back on the stack
TCHAR * tchar;
char* ok_str = "ServerId is OK";
if(strstr(ret, ok_str) == NULL) {
tchar = _T("0");
} else {
tchar = _T("1");
}
for (int i = 0; i < len; ++i) {
printf("%d", i);
szComponent[i] += 1;
}
pushstring(tchar);
}
I guess the reason is the libraries like "ws2_32.lib" is not bundled in the package.
No, that thing is only consumed by Visual C++ linker. In runtime, the corresponding DLL is taken from C:\Windows\System32\ws2_32.dll
Most likely reason is C and C++ runtime DLLs. By default, Visual Studio C++ projects use dynamic linking to these libraries. For an installer plugin, a good way to fix is switch to static C++ runtime. Right click on the project, Configuration properties, C/C++, Code Generation, change the “Runtime Library” setting to Multi-threaded Debug (/MTd) for debug configuration and Multi-threaded (/MT) for release configuration.
P.S. I would recommend a higher-level library for HTTP networking, such as WinHTTP or WinINet. Modern Internet has migrated from http to https.

*FIXED *constantly update console using cpp (msfs2020 SimConnect)

example picture
Im trying to constantly update the console number related to altitude. At the moment its a static number, and does not update while the plane is gaining, or loosing altitude. There is a comment near the bottom of the text referring to the prinf() that im using to send it to console(not sure what all was needed to be seen so I sent it all).
#include <iostream>
#include <Windows.h>
#include "SimConnect.h"
#include <string>
#include <sstream>
using namespace std;
HANDLE hSimConnect = NULL;
enum DATA_DEFINE_ID
{
DEFINITION_ID_AP,
};
enum DATA_REQUEST_ID
{
REQUEST_AP_SETTINGS,
};
enum EVENT_ID
{
EVENT_SET_AP_ALTITUDE,
};
struct DataRefs
{
double altitude;
double knots;
};
int main() {
HRESULT hr;
SIMCONNECT_RECV* pData = NULL;
DWORD cbData = 0;
bool bRequestProcessed = false;
int SelectedAltitude = 0;
SIMCONNECT_RECV_SIMOBJECT_DATA* pObjData = NULL;
DataRefs* pDataRefs = NULL;
if (SUCCEEDED(SimConnect_Open(&hSimConnect, "Client Event", NULL, NULL, NULL, NULL))) {
printf("Connected to MSFS2020!\n");
}
else {
/* string str = "42";
int num2 = stoi(str);
cout << num2;
*/
printf("Failed to Connect to MSFS2020\n");
}
//simVars
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "PLANE ALTITUDE", "Feet");
//hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AIRSPEED TRUE", "Knots");
// Check simVars
hr = SimConnect_RequestDataOnSimObject(hSimConnect, REQUEST_AP_SETTINGS, DEFINITION_ID_AP, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_ONCE);
if (FAILED(hr))
{
printf("RequestDataOnSimObject for AutopilotData structure - error\n");
}
bRequestProcessed = false;
while (!bRequestProcessed)
{
hr = SimConnect_GetNextDispatch(hSimConnect, &pData, &cbData);
if (SUCCEEDED(hr))
{
pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*)pData;
pDataRefs = (DataRefs*)&pObjData->dwData;
/* int altint;
altint = stoi (pDataRefs->altitude);
string str = "42";
int num2 = stoi(str);
cout << num2;
*/
/*
printf("\rCurrent plane altitude: %.f feet", pDataRefs->altitude);
fflush(stdout);
*/
//This line of code is what im referring to
printf("\rCurrent altitude: %.f feet", pDataRefs->altitude);
//printf("\rCurrent speed: %.f knots", pDataRefs->knots);
}
}
// Close
hr = SimConnect_Close(hSimConnect);
return 0;
}
Found the issue. If you CTRL-F "hr = SimConnect_RequestDataOnSimObject(hSimConnect, REQUEST_AP_SETTINGS, DEFINITION_ID_AP, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_ONCE);", you can see that I use SIMCONNECT_PERIOD_ONCE. looking into the documentation (https://www.prepar3d.com/SDKv4/sdk/simconnect_api/references/structures_and_enumerations.html), I replaced SIMCONNECT_PERIOD_ONCE with SIMCONNECT_PERIOD_SECOND to update it every second.

Im unsure of why my http server is not reading in a filelocation C++

Im creating a http server in c++. I know that TCPServer.h works and that thing/text.txt exists but for some reason the code doesnt read the text file when I do 127.0.0.1. If you would like TCPServer.h to help help just ask I would be more than happy to send it but I just didnt see a reason to do it
#include "TCPServer.h"
#include <future>
#include <fstream>
#include <WS2tcpip.h>
#include <iostream>
#define MAX_BUF (4096)
#pragma comment (lib, "ws2_32.lib")
char * getLoc(char * c) {
char * ret = (char *)malloc(4096);
ZeroMemory(ret, 4096);
for(int i = 4; i < 4092; i++) {
if (*(c + i) == ' ') {
return ret;
}
else {
*(ret + i - 4) = *(c + i);
}
}
return ret;
}
void doStuff(SOCKET sock) {
char * recieved = (char *)malloc(4096);
recv(sock, recieved, 4096, 0);
char * loc = getLoc(recieved);
std::string fileLocation("thing");
fileLocation += loc;
std::ifstream fil;
fil.open(fileLocation);
char * contents = (char *)malloc(4096);
ZeroMemory(contents, 4096);
fil.read(contents, 4096);
fil.close();
std::cout << fileLocation;
std::string shoot("HTTP/1.1 200 OK\n");
shoot += contents;
std::cout << "\n\n\n" << shoot;
send(sock, shoot.c_str(), 4096, 0);
}
int main() {
TCPServ s;
s.createSock(80);
while (true) {
SOCKET sock = s.listenFor();
std::future <void> f = std::async(doStuff, sock);
}
}

Can't read USN journal non-stop

My goal is to read write operations from a chosen drive (usually C), using USN journal.
In the next code I've written, I made a small class that processes USN records by using DeviceIoControl
with the FSCTL_QUERY_USN_JOURNAL and FSCTL_ENUM_USN_DATA codes.
#include "stdafx.h"
#include <stdio.h>
#include <assert.h>
#include <vector>
#include <system_error>
#include <Windows.h>
[[noreturn]] void throw_system_error(int error_code) {
throw std::system_error(error_code, std::system_category());
}
class usn_journal {
private:
HANDLE m_drive_handle;
std::vector<uint8_t> m_buffer;
USN_JOURNAL_DATA* m_usn_journal_data;
USN m_next_usn_record_id;
public:
usn_journal(const wchar_t* driver_name) {
m_next_usn_record_id = 0;
m_drive_handle = ::CreateFileW(
driver_name,
GENERIC_READ,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_ALWAYS,
FILE_FLAG_NO_BUFFERING,
nullptr);
if (m_drive_handle == INVALID_HANDLE_VALUE) {
throw_system_error(::GetLastError());
}
m_buffer.resize(1024 * 1024);
}
~usn_journal() {
::CloseHandle(m_drive_handle);
}
void refresh_jounral() {
assert(m_buffer.size() == 1024 * 1024);
DWORD buffer_count = 0;
if (!DeviceIoControl(
m_drive_handle,
FSCTL_QUERY_USN_JOURNAL,
nullptr,
0,
m_buffer.data(),
m_buffer.size(),
&buffer_count,
nullptr)) {
throw_system_error(::GetLastError());
}
m_usn_journal_data =
reinterpret_cast<decltype(m_usn_journal_data)>(m_buffer.data());
}
void process_entries() {
DWORD bytes_read = 0;
MFT_ENUM_DATA_V0 mft_enum_data = {};
mft_enum_data.StartFileReferenceNumber = m_next_usn_record_id;
mft_enum_data.LowUsn = 0;
mft_enum_data.HighUsn = m_usn_journal_data->MaxUsn;
assert(m_buffer.size() == 1024 * 1024);
for (;;){
auto buffer = m_buffer.data();
if (!DeviceIoControl(
m_drive_handle,
FSCTL_ENUM_USN_DATA,
&mft_enum_data,
sizeof(mft_enum_data),
buffer,
m_buffer.size(),
&bytes_read,
nullptr)){
auto error_code = ::GetLastError();
if (error_code == ERROR_HANDLE_EOF) {
return;
}
else {
throw_system_error(::GetLastError());
}
}
m_next_usn_record_id = *reinterpret_cast<USN*>(buffer);
auto buffer_real_begin = buffer + sizeof(USN);
auto usn_cursor = reinterpret_cast<USN_RECORD*>(buffer_real_begin);
int64_t total_usn_buffer_number = bytes_read - sizeof(USN);
while (total_usn_buffer_number >= 0){
total_usn_buffer_number -= usn_cursor->RecordLength;
buffer = reinterpret_cast<uint8_t*>(usn_cursor) + usn_cursor->RecordLength;
usn_cursor = reinterpret_cast<USN_RECORD*>(usn_cursor);
if (usn_cursor->Reason != 0) {
printf("%d\n", (int)usn_cursor->Reason);
}
}
mft_enum_data.StartFileReferenceNumber = m_next_usn_record_id;
}
}
};
int main(int argc, char ** argv){
usn_journal my_journal(L"\\\\?\\c:");
while (true) {
my_journal.refresh_jounral();
my_journal.process_entries();
}
return 0;
}
Here is my problem, after a while, the records are exhausted, and calling DeviceIoControl and FSCTL_ENUM_USN_DATA
DeviceIoControl fails and the error code I get is ERROR_HANDLE_EOF, even if I refresh the journal, I get the same error.
I want to be able to stream any new USN record, and handle write events. I know for sure it's possible as there are
third party tools which present USN records non-stop.
how can reproduce this state of non-stop streaming?