How to get IP Address from url without gethostbyname in Winsock API - c++

I want to get IP Address from URL. I find the answer in google, it only has gethostbyname() function solution, but MSDN said that this function is not used anymore.
I try to use getaddressinfo() or getnameinfo() (the example in MSDN), it only returns 255.255.255.255.
How can I do? Thank all!

gethostbyname() is indeed deprecated, and getaddrinfo() is the correct function to use now.
You need to parse the URL to extract its hostname, and optionally its port number (see InternetCrackUrl(), or other similar parser), then pass that hostname/port to getaddrinfo(). It will give you back a linked list of addrinfo structs containing each IP address assigned to the host, in sockaddr_in (IPv4) or sockaddr_in6 (IPv6) format.
If you need those IPs as strings, you can use inet_ntop(), RtlIpv4AddressToString()/RtlIpv6AddressToString(), getnameinfo() with the NI_NUMERICHOST flag, etc.

Addresses are obtained by domain name, not by URL.
Here are two functions to get an IPv6 and IPv4 address from a domain name.
Functions parameter is domain_name - domain name (eg dns.google).
The result is local_internet_name - a list of IPv6 or IPv4 addresses depending on the function used (e.g. {[8.8.8.8], [8.8.4.4]} for IPv4 addresses of the dns.google domain)
The return value is the attribute "Addresses found or not found" (true and false).
domain_name_to_internet_6_name
domain_name_to_internet_4_name
The functions use the MFC string classes, the C++ standard library, Windows DNS functions, and network functions.
An example of the output from a test console program:
2001:4860:4860::8888
2001:4860:4860::8844
8.8.8.8
8.8.4.4
D:\Projects\DNS_Test\Debug\DNS_Test.exe (process 14740) exited with code 0.
Press any key to close this window . . .
To create an executable for Windows, in Microsoft Visual Studio, you need to create a project from the "Console Application for Windows" template, and set the project properties to "Use MFC library" (as a shared library or as a static library)
Here's the code for a console program:
#include <afxwin.h>
#include <iostream>
#include <string>
#include <list>
#include <ws2tcpip.h>
#pragma comment(lib, "normaliz.lib")
#pragma comment(lib, "dnsapi.lib")
bool domain_name_to_internet_6_name(CStringW domain_name, std::list<CStringA>& local_internet_name)
{
const size_t CONST_MESSAGE_LENGTH = 500;
wchar_t local_domain_name_unicode[CONST_MESSAGE_LENGTH];
ZeroMemory(local_domain_name_unicode, sizeof(wchar_t) * CONST_MESSAGE_LENGTH);
if (IdnToAscii(0, domain_name, domain_name.GetLength(), local_domain_name_unicode, CONST_MESSAGE_LENGTH) == 0)
{
const int local_error_message_size = 500;
wchar_t local_error_message[local_error_message_size];
const int local_system_error_message_size = local_error_message_size - 250;
wchar_t local_system_error_message[local_system_error_message_size];
wcscpy_s(local_system_error_message, local_system_error_message_size, L"IdnToAscii finished with error");
CString local_time_string = CTime::GetCurrentTime().FormatGmt("%d/%m/%y %H:%M:%S GMT");
wsprintf((wchar_t*)local_error_message, L"Networking error -- %s -- %s\r\n", local_system_error_message, local_time_string.GetBuffer());
// В local_error_message находится текст с кодом сетевой ошибки при выполнении функции IdnToAscii
return false;
}
PDNS_RECORD ppQueryResults;
ZeroMemory(&ppQueryResults, sizeof(ppQueryResults));
if (DnsQuery_W(local_domain_name_unicode, DNS_TYPE_AAAA, 0, NULL, &ppQueryResults, NULL) == ERROR_SUCCESS)
{
for (PDNS_RECORD ptr = ppQueryResults; ptr != NULL; ptr = ptr->pNext)
{
if (ptr->wType == DNS_TYPE_AAAA)
{
if (ptr->wDataLength != 0)
{
char local_address_buffer[100];
inet_ntop(AF_INET6, &ptr->Data.AAAA.Ip6Address.IP6Byte, local_address_buffer, 100);
local_internet_name.push_back(local_address_buffer);
}
}
}
DnsFree(ppQueryResults, DnsFreeRecordList);
if (local_internet_name.size() != 0)
{
return true; // Адреса найдены
}
else
{
return false; // Адреса не найдены
}
return true;
}
return false;
}
bool domain_name_to_internet_4_name(CStringW domain_name, std::list<CStringA>& local_internet_name)
{
const size_t CONST_MESSAGE_LENGTH = 500;
wchar_t local_domain_name_unicode[CONST_MESSAGE_LENGTH];
ZeroMemory(local_domain_name_unicode, sizeof(wchar_t) * CONST_MESSAGE_LENGTH);
if (IdnToAscii(0, domain_name, domain_name.GetLength(), local_domain_name_unicode, CONST_MESSAGE_LENGTH) == 0)
{
const int local_error_message_size = 500;
wchar_t local_error_message[local_error_message_size];
const int local_system_error_message_size = local_error_message_size - 250;
wchar_t local_system_error_message[local_system_error_message_size];
wcscpy_s(local_system_error_message, local_system_error_message_size, L"IdnToAscii finished with error");
CString local_time_string = CTime::GetCurrentTime().FormatGmt("%d/%m/%y %H:%M:%S GMT");
wsprintf((wchar_t*)local_error_message, L"Networking error -- %s -- %s\r\n", local_system_error_message, local_time_string.GetBuffer());
// В local_error_message находится текст с кодом сетевой ошибки при выполнении функции IdnToAscii
return false;
}
PDNS_RECORD ppQueryResults;
ZeroMemory(&ppQueryResults, sizeof(ppQueryResults));
if (DnsQuery_W(local_domain_name_unicode, DNS_TYPE_A, 0, NULL, &ppQueryResults, NULL) == ERROR_SUCCESS)
{
for (PDNS_RECORD ptr = ppQueryResults; ptr != NULL; ptr = ptr->pNext)
{
if (ptr->wType == DNS_TYPE_A)
{
if (ptr->wDataLength != 0)
{
char local_address_buffer[100];
inet_ntop(AF_INET, &ptr->Data.A.IpAddress, local_address_buffer, 100);
local_internet_name.push_back(local_address_buffer);
}
}
}
DnsFree(ppQueryResults, DnsFreeRecordList);
if (local_internet_name.size() != 0)
{
return true; // Адреса найдены
}
else
{
return false; // Адреса не найдены
}
return true;
}
return false;
}
int main()
{
std::list<CStringA> local_internet_name_6;
if (domain_name_to_internet_6_name(CStringW(L"dns.google"), local_internet_name_6))
{
for (auto i = local_internet_name_6.begin(); i != local_internet_name_6.end(); i++)
{
std::cout << *i << std::endl;
}
}
std::list<CStringA> local_internet_name_4;
if (domain_name_to_internet_4_name(CStringW(L"dns.google"), local_internet_name_4))
{
for (auto i = local_internet_name_4.begin(); i != local_internet_name_4.end(); i++)
{
std::cout << *i << std::endl;
}
}
}

Related

What build environment differences are causing the mesa GBM library to behave differently

I am working on a basic demo application (kmscube) to do rendering via the DRM and GBM APIs. My application uses the TI variation of libgbm (mesa generic buffer management). TI provides the source, GNU autotools files, and a build environment (Yocto) to compile it. I compiled GBM in their environment and it works perfectly.
I did not want to use Yocto, so I moved the source into my own build system (buildroot) and compiled it. Everything compiles correctly (using the same autotools files), but when it runs, I get a segmentation fault when I call gbm_surface_create. I debugged as far as I could and found that the program steps into the gbm library but fails on return gbm->surface_create(gbm, width, height, format, flags);
What would cause a library to run differently when compiled in different environments. Are there some really important compiler or linker flags that I could be missing?
This is the code from the graphics application (in kmscube.c)
gbm.dev = gbm_create_device(drm.fd);
gbm.surface = gbm_surface_create(gbm.dev,
drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay,
drm_fmt_to_gbm_fmt(drm.format[DISP_ID]),
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!gbm.surface) {
printf("failed to create gbm surface\n");
return -1;
}
return 0;
This is the call stack that creates the device ( in gbm.c)
GBM_EXPORT struct gbm_device *
gbm_create_device(int fd)
{
struct gbm_device *gbm = NULL;
struct stat buf;
if (fd < 0 || fstat(fd, &buf) < 0 || !S_ISCHR(buf.st_mode)) {
fprintf(stderr, "gbm_create_device: invalid fd: %d\n", fd);
return NULL;
}
if (device_num == 0)
memset(devices, 0, sizeof devices);
gbm = _gbm_create_device(fd);
if (gbm == NULL)
return NULL;
gbm->dummy = gbm_create_device;
gbm->stat = buf;
gbm->refcount = 1;
if (device_num < ARRAY_SIZE(devices)-1)
devices[device_num++] = gbm;
return gbm;
}
(continued in backend.c)
struct gbm_device *
_gbm_create_device(int fd)
{
const struct gbm_backend *backend = NULL;
struct gbm_device *dev = NULL;
int i;
const char *b;
b = getenv("GBM_BACKEND");
if (b)
backend = load_backend(b);
if (backend)
dev = backend->create_device(fd);
for (i = 0; i < ARRAY_SIZE(backends) && dev == NULL; ++i) {
backend = load_backend(backends[i]);
if (backend == NULL)
continue;
fprintf(stderr, "found valid GBM backend : %s\n", backends[i]);
dev = backend->create_device(fd);
}
return dev;
}
static const void *
load_backend(const char *name)
{
char path[PATH_MAX];
void *module;
const char *entrypoint = "gbm_backend";
if (name[0] != '/')
snprintf(path, sizeof path, MODULEDIR "/%s", name);
else
snprintf(path, sizeof path, "%s", name);
module = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
if (!module) {
fprintf(stderr, "failed to load module: %s\n", dlerror());
return NULL;
}
else {
fprintf(stderr, "loaded module : %s\n", name);
}
return dlsym(module, entrypoint);
}
And here is the code that throws a segmentation fault (in gbm.c)
GBM_EXPORT struct gbm_surface *
gbm_surface_create(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags)
{
return gbm->surface_create(gbm, width, height, format, flags);
}

How to get number of connections on PORT per IP in Windows?

I have been searching around Google for some time and I can`t seem to find an answer...
I am using GetExtendedTcpTable() to view my current connections, but I am unable to get the number of connections that each IP does on a specific PORT.
Is there any example/function for this ? Or do I have to create something ?
Any guidance or example is much appreciated.
Have a nice day!
So using this code from MSDN as the basis we end up with this example which enumerates a list of connections, populating the pointer to int ports with the number of connections from remote systems to the local ports.
To determine the number of connections to a particular local port, you can simply print out the value of ports[port].
The code as supplied is very much more C, than C++, I just used a new[] and delete[] for the ports.
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
#define MALLOC(x) calloc(1, (x))
#define FREE(x) free((x))
int main()
{
// Declare and initialize variables
PMIB_TCPTABLE_OWNER_PID pTcpTable;
int *ports; // an array of all the possible ports
DWORD dwSize = 0;
DWORD dwRetVal = 0;
char szRemoteAddr[128];
struct in_addr IpAddr;
int i;
ports = new int[1 << (sizeof(u_short) * 8)]();
pTcpTable = (MIB_TCPTABLE_OWNER_PID *)MALLOC(sizeof(MIB_TCPTABLE_OWNER_PID));
if (pTcpTable == NULL) {
printf("Error allocating memory\n");
return 1;
}
dwSize = sizeof(MIB_TCPTABLE);
// Make an initial call to GetTcpTable to
// get the necessary size into the dwSize variable
if ((dwRetVal = GetExtendedTcpTable(pTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_BASIC_CONNECTIONS, 0)) ==
ERROR_INSUFFICIENT_BUFFER) {
FREE(pTcpTable);
pTcpTable = (MIB_TCPTABLE_OWNER_PID *)MALLOC(dwSize);
if (pTcpTable == NULL) {
printf("Error allocating memory\n");
return 1;
}
}
// Make a second call to GetTcpTable to get
// the actual data we require
if ((dwRetVal = GetExtendedTcpTable(pTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_BASIC_CONNECTIONS, 0)) == NO_ERROR) {
printf("\tNumber of entries: %d\n", (int)pTcpTable->dwNumEntries);
for (i = 0; i < (int)pTcpTable->dwNumEntries; i++) {
printf("\n\tTCP[%d] State: %ld - ", i,
pTcpTable->table[i].dwState);
if (pTcpTable->table[i].dwState != MIB_TCP_STATE_ESTAB)
continue;
// get the port in host order
u_short port = ntohs((u_short)pTcpTable->table[i].dwLocalPort);
ports[port] += 1; // increment this port
IpAddr.S_un.S_addr = (u_long)pTcpTable->table[i].dwRemoteAddr;
inet_ntop(AF_INET, &IpAddr, szRemoteAddr, sizeof(szRemoteAddr));
printf("\tTCP[%d] Remote Addr: %s:%d\n", i, szRemoteAddr, ntohs((u_short)pTcpTable->table[i].dwRemotePort));
}
}
else {
printf("\tGetExtendedTcpTable failed with %d\n", dwRetVal);
FREE(pTcpTable);
delete[] ports;
return 1;
}
if (pTcpTable != NULL) {
FREE(pTcpTable);
pTcpTable = NULL;
}
delete[] ports;
return 0;
}
Now if you wanted a list of the remote addresses coming to a port, then you could make a std::vector<std::string> remote_addresses and perform a remote_addresses.push_back(szRemoteAddr) when you determined that the port was correct.
There is a potential race condition where between the initial call to GetExtendedTcpTable and the subsequent call to GetExtendedTcpTable another connection comes in, which increases the value of dwSize. Generally asking for more memory helps in this case to just prevent this from being an issue - i.e. after the initial call, try asking for 8K more than you need - it's not likely to be a big issue, though.

C++ - Serial (COM) port - asio | VS2015 error(s)

1. What are we trying to achieve (and why)
We're currently trying to communicate with an industrial robot over USB(COM)<->serial(RS232). We would like to control the robot from a C++ application.
2. What setup do we have
We're using Visual Studio C++ 2015 with the built-in C++ compiler. Creating a "Win32 Console Application".
3. What steps have we taken?
We've got the connection working in Processing (Java) using Serial but we would like to implement it in C++.
3.1 Boost ASIO
We're using Boost ASIO (installed with NuGet package manager).
At this point we get 2 compile errors indicating the same problem:
Error C2694 'const char *asio::detail::system_category::name(void) const': overriding virtual function has less restrictive exception specification than base class virtual member function 'const char *std::error_category::name(void) noexcept const'
I figured that this error is most likely not caused by my code (I haven't changed the library). So I believe the VS21015 C++ compiler is not fully compatible with boost::asio?
I've found two other links/posts with somewhat the same error:
https://github.com/chriskohlhoff/asio/issues/35
And I tried the following define:
#ifndef ASIO_ERROR_CATEGORY_NOEXCEPT
#define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
#endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT)
Error in websocketpp library and boost in windows Visual Studio 2015
With the following define:
#define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
//or
#define ASIO_ERROR_CATEGORY_NOEXCEPT 1
But it did not resolve the errors. The even caused a lot of random syntax errors and undeclared identifiers (which would indicate missing the include of iterator.
3.2 Windows(base) and C
We've used some C code (and added in a little C++ Debugging) to detect COM ports. But it simply doesn't show them (however it does in device explorer). We even had to convert a LPCWSTR to char array (wtf?).
#include <stdio.h>
#include <cstdio>
#include <iostream>
#include <windows.h>
#include <winbase.h>
wchar_t *convertCharArrayToLPCWSTR(const char* charArray)
{
wchar_t* wString = new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
return wString;
}
BOOL COM_exists(int port)
{
char buffer[7];
COMMCONFIG CommConfig;
DWORD size;
if (!(1 <= port && port <= 255))
{
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.
std::cout << "COM" << port << " | " << (GetDefaultCommConfig(convertCharArrayToLPCWSTR(buffer), &CommConfig, &size)
|| size > sizeof CommConfig) << std::endl;
return (GetDefaultCommConfig(convertCharArrayToLPCWSTR(buffer), &CommConfig, &size)
|| size > sizeof CommConfig);
}
int main()
{
int i;
for (i = 1; i < 256; ++i)
{
if (COM_exists(i))
{
printf("COM%d exists\n", i);
}
}
std::cin.get();
return 0;
}
3.3 Another Serial.h from the internet
I believe it was from: http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c2503/CSerial--A-C-Class-for-Serial-Communications.htm
Same rules, I include the library, everything compiles fine. (Test written below)
#include <iostream>
#include <string>
#include "Serial.h"
int main(void)
{
CSerial serial;
if (serial.Open(8, 9600))
std::cout << "Port opened successfully" << std::endl;
else
std::cout << "Failed to open port!" << std::endl;
std::cin.get();
return 0;
}
But it still doesn't show my COM ports... (They do show up in device explorer though.)
4 So what is actually working?
This particular piece of code WILL display the right COM port...
TCHAR lpTargetPath[5000]; // buffer to store the path of the COMPORTS
DWORD test;
for (int i = 0; i<255; i++) // checking ports from COM0 to COM255
{
CString str;
str.Format(_T("%d"), i);
CString ComName = CString("COM") + CString(str); // converting to COM0, COM1, COM2
test = QueryDosDevice(ComName, lpTargetPath, 5000);
// Test the return value and error if any
if (test != 0) //QueryDosDevice returns zero if it didn't find an object
{
std::cout << "COM" << i << std::endl; // add to the ComboBox
}
}
Maybe you need to update to a more recent version of boost if you have not already.
The issue with the second part is you naming of the COM port. Only COM1 to 4 can be a 'bald' name. You need to format it like this:
\\.\COM9
Clearly take care of escape sequences here:
snprintf(buffer, sizeof(buffer), "\\\\.\\COM%d", port);
EDIT: Actually you don't need to do that with GetCommConfig, only with CreateFile for opening the port. It should work. I'd suspect your conversion to wide string.
You may also find a performance enhancement of you load the cfgmgr32.dll library first.
Using CreateFile for COM port detection can result in in BSODs on some Windows systems. Particular culprits are some software modems and some bluetooth devices which show up s COM ports. So using GetDefaultCommConfig is the way to go generally though it may not work for all ports.
So what else can you do? Use setupapi.dll. Sadly this is not completely trivial..
namespace {
typedef HKEY (__stdcall *OpenDevRegKey)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM);
typedef BOOL (__stdcall *ClassGuidsFromName)(LPCTSTR, LPGUID, DWORD, PDWORD);
typedef BOOL (__stdcall *DestroyDeviceInfoList)(HDEVINFO);
typedef BOOL (__stdcall *EnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
typedef HDEVINFO (__stdcall *GetClassDevs)(LPGUID, LPCTSTR, HWND, DWORD);
typedef BOOL (__stdcall *GetDeviceRegistryProperty)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
} // namespace
typedef std::basic_string<TCHAR> tstring;
struct PortEntry
{
tstring dev;
tstring name;
bool operator== (tstring const& device) const {
return dev == device; // TODO maybe use case-insentitive compare.
}
bool operator!= (tstring const& device) const {
return !(*this == device);
}
};
typedef std::vector<PortEntry> PortList;
// ...
DllHandler setupapi; // RAII class for LoadLibrary / FreeLibrary
if (!setupapi.load(_T("SETUPAPI.DLL"))) {
throw std::runtime_error("Can\'t open setupapi.dll");
}
OpenDevRegKey fnOpenDevRegKey =
setupapi.GetProc("SetupDiOpenDevRegKey");
ClassGuidsFromName fnClassGuidsFromName =
#ifdef UNICODE
setupapi.GetProc("SetupDiClassGuidsFromNameW");
#else
setupapi.GetProc("SetupDiClassGuidsFromNameA");
#endif
DestroyDeviceInfoList fnDestroyDeviceInfoList =
setupapi.GetProc("SetupDiDestroyDeviceInfoList");
EnumDeviceInfo fnEnumDeviceInfo =
setupapi.GetProc("SetupDiEnumDeviceInfo");
GetClassDevs fnGetClassDevs =
#ifdef UNICODE
setupapi.GetProc("SetupDiGetClassDevsW");
#else
setupapi.GetProc("SetupDiGetClassDevsA");
#endif
GetDeviceRegistryProperty fnGetDeviceRegistryProperty =
#ifdef UNICODE
setupapi.GetProc("SetupDiGetDeviceRegistryPropertyW");
#else
setupapi.GetProc("SetupDiGetDeviceRegistryPropertyA");
#endif
if ((fnOpenDevRegKey == 0) ||
(fnClassGuidsFromName == 0) ||
(fnDestroyDeviceInfoList == 0) ||
(fnEnumDeviceInfo == 0) ||
(fnGetClassDevs == 0) ||
(fnGetDeviceRegistryProperty == 0)
) {
throw std:runtime_error(
"Could not locate required functions in setupapi.dll"
);
}
// First need to get the GUID from the name "Ports"
//
DWORD dwGuids = 0;
(*fnClassGuidsFromName)(_T("Ports"), NULL, 0, &dwGuids);
if (dwGuids == 0)
{
throw std::runtime_error("Can\'t get GUIDs from \'Ports\' key in the registry");
}
// Allocate the needed memory
std::vector<GUID> guids(dwGuids);
// Get the GUIDs
if (!(*fnClassGuidsFromName)(_T("Ports"), &guids[0], dwGuids, &dwGuids))
{
throw std::runtime_error("Can\'t get GUIDs from \'Ports\' key in the registry");
}
// Now create a "device information set" which is required to enumerate all the ports
HDEVINFO hdevinfoset = (*fnGetClassDevs)(&guids[0], NULL, NULL, DIGCF_PRESENT);
if (hdevinfoset == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("Can\'t get create device information set.");
}
// Finished with the guids.
guids.clear();
// Finally do the enumeration
bool more = true;
int index = 0;
SP_DEVINFO_DATA devinfo;
while (more)
{
//Enumerate the current device
devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
more = (0 != (*fnEnumDeviceInfo)(hdevinfoset, index, &devinfo));
if (more)
{
PortEntry entry;
//Did we find a serial port for this device
bool added = false;
//Get the registry key which stores the ports settings
HKEY hdevkey = (*fnOpenDevRegKey)(
hdevinfoset,
&devinfo,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_QUERY_VALUE
);
if (hdevkey)
{
//Read in the name of the port
TCHAR port_name[256];
DWORD size = sizeof(port_name);
DWORD type = 0;
if ((::RegQueryValueEx(
hdevkey,
_T("PortName"),
NULL,
&type,
(LPBYTE) port_name,
&size
) == ERROR_SUCCESS) &&
(type == REG_SZ)
) {
// If it looks like "COMX" then
// add it to the array which will be returned
tstring s = port_name;
size_t len = s.length();
String const cmp(s, 0, 3);
if (CaseInsensitiveCompareEqual(String("COM"), cmp)) {
entry.name = s;
entry.dev = "\\\\.\\" + s;
added = true;
}
}
// Close the key now that we are finished with it
::RegCloseKey(hdevkey);
}
// If the port was a serial port, then also try to get its friendly name
if (added)
{
TCHAR friendly_name[256];
DWORD size = sizeof(friendly_name);
DWORD type = 0;
if ((fnGetDeviceRegistryProperty)(
hdevinfoset,
&devinfo,
SPDRP_DEVICEDESC,
&type,
(PBYTE)friendly_name,
size,
&size
) &&
(type == REG_SZ)
) {
entry.name += _T(" (");
entry.name += friendly_name;
entry.name += _T(")");
}
//
// Add the port to our vector.
//
// If we already have an entry for the given device, then
// overwrite it (this will add the friendly name).
//
PortList::iterator i = std::find(
ports.begin(),
ports.end(),
entry.dev
);
if (i == ports.end()) {
ports.push_back(entry);
}
else {
(*i) = entry;
}
}
}
++index;
}
// Free up the "device information set" now that we are finished with it
(*fnDestroyDeviceInfoList)(hdevinfoset);
You'll need to do a bit of work to make that compilable but it should work.
See https://support.microsoft.com/en-us/kb/259695

Substitute Console window by Windows Forms

I have created a Win32 Console Application project in Visual Studio 2012 C++.
How can I substitute the Console window by a more appealing GUI like Windows Forms?
int32_t main(int32_t argc, char* argv[])
{
const char *date = "20150428_1\\";
int mode=0;
_CallServerPtr pCallServer;
uint32_t start_address_comp=0;
uint32_t start_address_module=0;
const char* xmlFile_tx_dbb="tx_dbb.xml";;
char str[100] = "\0";
char localeStr[64];
memset(localeStr, 0, sizeof localeStr);
const char *l_path = "..\\XERCES\\Configs\\";
std::string buf = "";
double Fsym_Hz=(1/1.15)*1e9;
int selection=0;
int user_selection=0;
try
{
if (strlen(localeStr))
{
XMLPlatformUtils::Initialize(localeStr);
}
else
{
XMLPlatformUtils::Initialize();
}
}
catch (const XMLException& toCatch)
{
XERCES_STD_QUALIFIER cerr << "Error during initialization! :\n"
<< StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
}
static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull };
DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(gLS);
DOMLSParser *parser = ((DOMImplementationLS*)impl)->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
DOMConfiguration *config = parser->getDomConfig();
DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
DOMLSOutput *theOutputDesc = ((DOMImplementationLS*)impl)->createLSOutput();
config->setParameter(XMLUni::fgDOMDatatypeNormalization, true);
DOMCountErrorHandler errorHandler;
config->setParameter(XMLUni::fgDOMErrorHandler, &errorHandler);
XERCES_STD_QUALIFIER ifstream fin;
//reset error count first
errorHandler.resetErrors();*/
// reset document pool
parser->resetDocumentPool();
char* pszHostname = NULL;
pSaIn = 0;
pSaOut = 0;
// Initialize the COM Library
CoInitialize(NULL);
if (!pszHostname)
{
// Create the CallServer server object on the local computer
pCallServer.CreateInstance(CLSID_CallServer);
}
if (pCallServer == NULL)
throw "Failed to create the CallableVEE CallServer object";
// Load the VEE User Function library
char strpath[256];
strcpy (strpath,reposity_path);
strcat (strpath,l_path_vee);
_bstr_t bstrLibPath(strpath);
LibraryPtr pLib = pCallServer->GetLibraries()->Load(bstrLibPath);
// Print out the names of the UserFunctions in this library.
UserFunctionsPtr pUserFuncColl = pLib->GetUserFunctions();
VARIANT_BOOL bDebug = VARIANT_FALSE;
pCallServer->PutDebug(bDebug);
// Variables added by ivi
float *freq =(float *)_aligned_malloc(6,16); // Read frequency vector
// Previous variables
int32_t devIdx;
int32_t modeClock;
int32_t ifType;
const char *devType;
char fpga_device_type[32];
int32_t rc;
int32_t ref_clk=0;
uint32_t carrier=0;
uint32_t odelay_dac0 = 0;
uint32_t odelay_dac1 = 0;
// Parse the application arguments
if(argc!=5) {
printf("Usage: FMCxxxApp.exe {interface type} {device type} {device index} {clock mode} \n\n");
printf(" {interface type} can be either 0 (PCI) or 1 (Ethernet). At CEIT, we use 1 (Ethernet).\n");
printf(" {device type} is a string defining the target hardware (VP680, ML605, ...). At CEIT, we use VC707.\n");
printf(" {device index} is a PCI index or an Ethernet interface index. This value depends on the PC.\n");
printf(" {clock mode} can be either 0 (Int. Clock) or 1 (Ext. Clock)\n");
printf("\n");
printf("\n");
printf("Example: Fmc230APP.exe 1 VC707 0 0\n");
printf("\n");
printf("\n");
printf(" List of NDIS interfaces found in the system {device index}:\n");
printf(" -----------------------------------------------------------\n");
if(sipif_getdeviceenumeration(API_ENUM_DISPLAY)!=SIPIF_ERR_OK) {
printf("Could not obtain NDIS(Ethernet) device enumeration...\n Check if the 4dspnet driver installed or if the service started?\n");
printf("You can discard this error if you do not have any Ethernet based product in use.");
}
if( EXIT_IF_ERRORS)
{
sipif_free();
system("pause");
return -1;
}
...
}
You mean to have the same code in windows forms. That won't work. The printf and other commands work only in a console application. You must to create a windows form application and rewrite the code for it. You must rewrite all commands that don't work in a windows form application. There probably exists a conversion application, but for this short code I think it's better to rewrite it.

Generate machine-specific key for Mac

On Windows, we generate a PC-specific unique key used to tie a license to a PC. It's a C++ app using wxWidgets, which is theoretically cross-platform compatible but not been maintained on the Mac side. We use some Win32-specific code for generating a key... how might I do something comparable on the Mac?
Looking more into whitelionV and blahdiblah's asnwers, I found this useful page:
Accessing the system serial number programmatically
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
// Returns the serial number as a CFString.
// It is the caller's responsibility to release the returned CFString when done with it.
void CopySerialNumber(CFStringRef *serialNumber)
{
if (serialNumber != NULL) {
*serialNumber = NULL;
io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("IOPlatformExpertDevice"));
if (platformExpert) {
CFTypeRef serialNumberAsCFString =
IORegistryEntryCreateCFProperty(platformExpert,
CFSTR(kIOPlatformSerialNumberKey),
kCFAllocatorDefault, 0);
if (serialNumberAsCFString) {
*serialNumber = serialNumberAsCFString;
}
IOObjectRelease(platformExpert);
}
}
}
Accessing the built-in MAC address programmatically
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>
static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices);
static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress, UInt8 bufferSize);
static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices)
{
kern_return_t kernResult;
CFMutableDictionaryRef matchingDict;
CFMutableDictionaryRef propertyMatchDict;
matchingDict = IOServiceMatching(kIOEthernetInterfaceClass);
if (NULL == matchingDict) {
printf("IOServiceMatching returned a NULL dictionary.\n");
}
else {
propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (NULL == propertyMatchDict) {
printf("CFDictionaryCreateMutable returned a NULL dictionary.\n");
}
else {
CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
CFRelease(propertyMatchDict);
}
}
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, matchingServices);
if (KERN_SUCCESS != kernResult) {
printf("IOServiceGetMatchingServices returned 0x%08x\n", kernResult);
}
return kernResult;
}
static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress, UInt8 bufferSize)
{
io_object_t intfService;
io_object_t controllerService;
kern_return_t kernResult = KERN_FAILURE;
if (bufferSize < kIOEthernetAddressSize) {
return kernResult;
}
bzero(MACAddress, bufferSize);
while ((intfService = IOIteratorNext(intfIterator)))
{
CFTypeRef MACAddressAsCFData;
kernResult = IORegistryEntryGetParentEntry(intfService,
kIOServicePlane,
&controllerService);
if (KERN_SUCCESS != kernResult) {
printf("IORegistryEntryGetParentEntry returned 0x%08x\n", kernResult);
}
else {
MACAddressAsCFData = IORegistryEntryCreateCFProperty(controllerService,
CFSTR(kIOMACAddress),
kCFAllocatorDefault,
0);
if (MACAddressAsCFData) {
CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr
CFDataGetBytes(MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress);
CFRelease(MACAddressAsCFData);
}
(void) IOObjectRelease(controllerService);
}
(void) IOObjectRelease(intfService);
}
return kernResult;
}
int main(int argc, char *argv[])
{
kern_return_t kernResult = KERN_SUCCESS;
io_iterator_t intfIterator;
UInt8 MACAddress[kIOEthernetAddressSize];
kernResult = FindEthernetInterfaces(&intfIterator);
if (KERN_SUCCESS != kernResult) {
printf("FindEthernetInterfaces returned 0x%08x\n", kernResult);
}
else {
kernResult = GetMACAddress(intfIterator, MACAddress, sizeof(MACAddress));
if (KERN_SUCCESS != kernResult) {
printf("GetMACAddress returned 0x%08x\n", kernResult);
}
else {
printf("This system's built-in MAC address is %02x:%02x:%02x:%02x:%02x:%02x.\n",
MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3], MACAddress[4], MACAddress[5]);
}
}
(void) IOObjectRelease(intfIterator); // Release the iterator.
return kernResult;
}
While MAC is on the face of it probably preferable as being more predictable, they warn that:
Netbooting introduces a wrinkle with systems with multiple built-in
Ethernet ports. The primary Ethernet port on these systems is the one
that is connected to the NetBoot server. This means that a search for
the primary port may return either of the built-in MAC addresses
depending on which port was used for netbooting. Note that "built-in"
does not include Ethernet ports that reside on an expansion card.
It concerns me this might mean you don't always get the same value back?
You could just call system_profiler and look for "Serial Number"
/usr/sbin/system_profiler | grep "Serial Number (system)"
There might well be a programmatic way to get the same information, but I don't know it offhand.
To uniquely identify any machine you could try to use the MAC address. The process, although not trivial, its quite simple. There are a lot of cross platform open source libraries.
In fact you could try this Apple dev example