1 // Copyright 2014 Idol Software, Inc.
3 // This file is part of Doctor Dump SDK.
5 // Doctor Dump SDK is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 class Error
: public std::runtime_error
25 static std::string
GetError(const char* text
, DWORD err
);
27 Error(const char* text
, DWORD err
) : std::runtime_error(GetError(text
, err
)) {}
34 Handle(HINTERNET handle
= NULL
) : m_handle(handle
) {}
35 ~Handle() { if (m_handle
) InternetCloseHandle(m_handle
); }
36 operator HINTERNET() { return m_handle
; }
37 operator bool() { return m_handle
!= NULL
; }
40 std::vector
<BYTE
> ReadFile(HINTERNET hRequest
);
42 std::string
EscapeString(const std::string
& text
);
45 using namespace wininet
;
47 std::string
wininet::Error::GetError(const char* text
, DWORD err
)
50 sprintf_s(buf
, "%s, error %d", text
, err
);
54 std::vector
<BYTE
> wininet::ReadFile(HINTERNET hRequest
)
56 std::vector
<BYTE
> result
;
58 while (InternetQueryDataAvailable(hRequest
, &bytesAvailable
, 0, 0))
60 size_t cur
= result
.size();
61 result
.resize(cur
+ bytesAvailable
);
63 bool res
= !!InternetReadFile(hRequest
, result
.data() + cur
, bytesAvailable
, &bytesRead
);
64 result
.resize(cur
+ bytesRead
);
65 if (!res
|| bytesRead
== 0)
71 std::string
wininet::EscapeString(const std::string
& text
)
74 result
.resize(text
.size() * 3);
76 if (!AtlEscapeUrl(text
.c_str(), &result
.front(), &size
, (DWORD
)result
.size(), ATL_URL_ENCODE_PERCENT
))
78 result
.resize(size
* 3);
79 if (!AtlEscapeUrl(text
.c_str(), &result
.front(), &size
, (DWORD
)result
.size(), ATL_URL_ENCODE_PERCENT
))
80 throw Error("AtlEscapeUrl failed", 0);
82 result
.resize(size
- 1);
86 std::vector
<BYTE
> statistics::HttpPost(LPCTSTR agent
, const CUrl
& url
, LPCTSTR
* accept
, LPCTSTR hdrs
, LPVOID postData
, DWORD postDataSize
, DWORD
& responseCode
)
88 Handle
hSession(InternetOpen(agent
, INTERNET_OPEN_TYPE_PRECONFIG
, NULL
, NULL
, 0));
90 throw Error("InternetOpen failed", GetLastError());
92 Handle
hConnect(InternetConnect(hSession
, url
.GetHostName(), INTERNET_DEFAULT_HTTP_PORT
, NULL
, NULL
, INTERNET_SERVICE_HTTP
, 0, 1));
94 throw Error("InternetConnect failed", GetLastError());
96 Handle
hRequest(HttpOpenRequest(hConnect
, _T("POST"), url
.GetUrlPath(), NULL
, NULL
, accept
, 0, INTERNET_NO_CALLBACK
));
98 throw Error("HttpOpenRequest failed", GetLastError());
100 if (!HttpSendRequest(hRequest
, hdrs
, -1, postData
, postDataSize
))
101 throw Error("HttpSendRequest failed", GetLastError());
103 DWORD size
= sizeof(responseCode
);
104 HttpQueryInfo(hRequest
, HTTP_QUERY_STATUS_CODE
| HTTP_QUERY_FLAG_NUMBER
, &responseCode
, &size
, NULL
);
105 return ReadFile(hRequest
);
108 std::vector
<BYTE
> statistics::HttpPostXWwwFormUrlencoded(LPCTSTR agent
, const CUrl
& url
, LPCTSTR
* accept
, const Params
& query
, DWORD
& responseCode
)
110 LPCTSTR hdrs
= _T("Content-Type: application/x-www-form-urlencoded");
112 std::string postData
;
113 for each (auto& var in query
)
115 if (!postData
.empty())
117 postData
+= EscapeString(var
.first
) + "=" + EscapeString(var
.second
);
120 return HttpPost(agent
, url
, accept
, hdrs
, (LPVOID
)postData
.c_str(), (DWORD
)postData
.size(), responseCode
);
127 typedef BOOL (WINAPI
*LPFN_ISWOW64PROCESS
) (HANDLE
, PBOOL
);
128 LPFN_ISWOW64PROCESS fnIsWow64Process
= NULL
;
130 BOOL bIsWow64
= FALSE
;
132 HMODULE hKernel32
= GetModuleHandle(TEXT("kernel32"));
133 if (NULL
!= hKernel32
)
134 fnIsWow64Process
= (LPFN_ISWOW64PROCESS
)GetProcAddress(hKernel32
,"IsWow64Process");
136 if (NULL
!= fnIsWow64Process
)
137 fnIsWow64Process(GetCurrentProcess(), &bIsWow64
);
142 std::string
GetMachineGuid()
149 DWORD param
= IsWow64() ? KEY_WOW64_64KEY
: 0;
151 if (ERROR_SUCCESS
== RegOpenKeyEx(HKEY_LOCAL_MACHINE
, _T("SOFTWARE\\Microsoft\\Cryptography"), 0, KEY_READ
|param
, &hCryptography
))
154 DWORD size
= (DWORD
)result
.size();
155 if (ERROR_SUCCESS
== RegQueryValueExA(hCryptography
, "MachineGuid", NULL
, NULL
, (LPBYTE
)&result
.front(), &size
))
159 RegCloseKey(hCryptography
);
164 std::string
GetCurrentProcessVersion()
166 TCHAR path
[MAX_PATH
];
167 if (!GetModuleFileName(NULL
, path
, _countof(path
)))
170 std::vector
<BYTE
> verInfo(GetFileVersionInfoSize(path
, NULL
));
171 VS_FIXEDFILEINFO
* lpFileinfo
= NULL
;
174 || !GetFileVersionInfo(path
, 0, static_cast<DWORD
>(verInfo
.size()), &verInfo
[0])
175 || !VerQueryValue(&verInfo
[0], _T("\\"), (LPVOID
*)&lpFileinfo
, &uLen
))
179 sprintf_s(version
, "%d.%d.%d.%d",
180 HIWORD(lpFileinfo
->dwProductVersionMS
),
181 LOWORD(lpFileinfo
->dwProductVersionMS
),
182 HIWORD(lpFileinfo
->dwProductVersionLS
),
183 LOWORD(lpFileinfo
->dwProductVersionLS
));
188 bool statistics::SendExceptionToGoogleAnalytics(LPCSTR tid
, const std::string
& cid
, const std::string
& appName
, const std::string
& appVersion
, const std::string
& exceptionDescr
, bool exceptionFatal
)
194 url
.CrackUrl(_T("http://httpbin.org/post"));
196 url
.CrackUrl(_T("http://www.google-analytics.com/collect"));
198 LPCTSTR accept
[]= { _T("*/*"), NULL
};
200 query
.emplace_back(Param("v", "1"));
201 query
.emplace_back(Param("tid", tid
));
202 query
.emplace_back(Param("cid", cid
));
203 query
.emplace_back(Param("t", "exception"));
204 query
.emplace_back(Param("an", appName
));
205 query
.emplace_back(Param("av", appVersion
));
206 query
.emplace_back(Param("exd", exceptionDescr
));
207 query
.emplace_back(Param("exf", exceptionFatal
? "1" : "0"));
209 DWORD responseCode
= 0;
210 std::vector
<BYTE
> data
= HttpPostXWwwFormUrlencoded(_T("MyAgent"), url
, accept
, query
, responseCode
);
212 printf("HTTP %d\n", responseCode
);
214 printf("%s", (LPCSTR
)data
.data());
218 catch (std::exception
& ex
)
220 UNREFERENCED_PARAMETER(ex
);
222 printf("Error: %s\n", ex
.what());
228 bool statistics::SendExceptionToGoogleAnalytics(
230 const std::string
& appName
,
231 const std::string
& exceptionDescr
,
234 return SendExceptionToGoogleAnalytics(tid
, GetMachineGuid(), appName
, GetCurrentProcessVersion(), exceptionDescr
, exceptionFatal
);