InternetCrackUrl not returning lpszHostName properly - c++

I am developing a plugin for NSIS (Unicode) and I am trying to use InternetCrackUrl() to get the hostname of a URL (ie: http://www.google.com/test.html -> www.google.com) but instead of lpszHostName just returning "www.google.com", it returns "www.google.com/test.html".
Here is my code:
void __declspec(dllexport) Example(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters *extra) {
g_hwndParent=hwndParent;
EXDLL_INIT();
LPWSTR szURI = new WCHAR[string_size];
URL_COMPONENTS urlComp;
// Sets szURI to "http://www.xyz.com/test.html"
popstring(szURI);
wstring strUri = szURI;
ZeroMemory(&urlComp, sizeof(urlComp));
urlComp.dwStructSize = sizeof(urlComp);
// Set required component lengths to non-zero so that they are cracked.
urlComp.dwHostNameLength = static_cast<DWORD>(-1);
urlComp.dwSchemeLength = static_cast<DWORD>(-1);
urlComp.dwUrlPathLength = static_cast<DWORD>(-1);
urlComp.dwExtraInfoLength = static_cast<DWORD>(-1);
if (!InternetCrackUrlW(strUri.c_str(), strUri.length(), 0, &urlComp)) {
return _T("InternetCrackUrl failed");
}
// urlComp.lpszHostName = www.xyz.com/test.html
}
Any ideas?

If you don't provide your own buffer InternetCrackUrl will return pointers to characters in the original string you pass as input. It doesn't copy the string.
So, lpszHostName will point to the first character, and dwHostNameLength will give you the number of chars that make the host name.

That is the expected behavior.
Because when you say www.google.com it translates to http://www.google.com/test.html.
The URL is really www.google.com/test.html which is what is returned.
To get what you need, you will need to do some string manipulation.
You could use the strrchr function or the find_first_of method of the std::string class.

Related

How to capture string returned from a url called from c++ program

I want to capture the string value returned from a url. The url is called from a c++ program. For example, the url in a browser address window returns a string value to the browser screen. How to I capture that value if the url is called from a c++ program.
I tried popen but that didn't seem to work.
TCHAR psBuffer[128];
FILE* pPipe;
if ((pPipe = _popen("http://xxxx.com/kmver.php", "rt")) == NULL)
{
AfxMessageBox(_T("Can't access http://xxxx.com/kmver.php"));
}
else
{
fgets(psBuffer, 128, pPipe);
CString sVal = psBuffer;
_pclose(pPipe);
}

xmlReadMemory - unknown 'url' parameter

I have my xml as char buffer (that's fetched from server, I don't want to save it -> takes extra time and is completely obsolete):
char myword[] = "...xml..."
xmlSchemaParserCtxtPtr ctxt = xmlSchemaNewParserCtxt(xsdFilePath);
xmlDocPtr doc = ?;
Now I need to get doc. I'm trying to use following function:
doc = xmlReadMemory(myword, sizeof(myword), ?URL?, NULL, 0)
But the problem is with URL, what should I put in there..? Am I using this function right? Maybe there is another way to get xmlDocPtr?
BTW: I need xmlDocPtr to perform:
ret = xmlSchemaValidateDoc(ctxt, doc);
Simply pass a NULL pointer:
doc = xmlReadMemory(myword, sizeof(myword), NULL, NULL, 0);

Using UpdateResource with StringTables in C++

I need to edit the resources of a file in C++ using UpdateResource(), however I am unsure on how to go about getting the data for the 5th parameter (lpData).
I have no idea about how to create the data that needs to be provided for the function and the structure of the data, Can anybody provide guidance on how to go about getting/creating the data?
Simply you can use:
wchar_t wszMyText[] = L"Some text";
HANDLE hUpdate = BeginUpdateResourceW( L"/path/to/file", FALSE );
// test return value.
BOOL res = UpdateResourceW( hUpdate, RT_STRING, L"MyResource", wszMyText,
sizeof(wszMyText) - sizeof(wchar_t);
// check return value
EndUpdateResource( hUpdate, FALSE );

Access X509 Certificate store with unmanaged C++

Does anyone know how I would do the equivalent of the below C# code using unmanaged C++ i.e. query a certificate from the X509 certificate store by thumbprint?
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var allCerts = store.Certificates;
foreach (var certificate in from X509Certificate2 certificate in allCerts
where certificate.Thumbprint != null
&& certificate.Thumbprint.Equals(thumbprint, StringComparison.OrdinalIgnoreCase)
select certificate)
{
return certificate;
}
Thanks in advance
Dave
In order to accomplish what you want, you'll have to look into the Win32 CryptAPI library. It won't be as easy as .NET. Look into CertOpenStore and CertFindCertificateInStore.
You'll need to open a certificate store and pass it into CertFindCertificateStore, creating a structure to hold whatever criteria you want to use to find your certificate. You can use a serial number, signature, etc.
HCERTSTORE hSysStore = NULL;
PCCERT_CONTEXT pDesiredCert = NULL;
if(hSysStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM, // The store provider type
0, // The encoding type is
// not needed
NULL, // Use the default HCRYPTPROV
CERT_SYSTEM_STORE_CURRENT_USER, // Set the store location in a
// registry location
L"MY" // The store name as a Unicode
// string
))
{
//We have our store, let's do stuff with it
if (pDesiredCert = CertFindCertificateInStore(.....) { ..... }
}
else
{
//Error stuff
}
You will need to #include <Wincrypt.h> and #include <windows.h>
The code from CertFindCertificateInStore. will not work on newer systems. On newer versions of Windows the certificate's name or subject are in Unicode format which uses 2 bytes for each character. The folowing line:
LPCSTR lpszCertSubject = (LPCSTR) "Cert_subject_1";
has to be change into:
LPCWSTR lpszCertSubject = (LPCWSTR ) L"Cert_subject_1";
or
LPCTSTR lpszCertSubject = (LPCTSTR ) _T"Cert_subject_1"; // add #include <tchar.h>
depending on what you need.

return array from com object

I want to pass a list of alarm names from COM to VBScript used in ASP pages. If the method name is GetAlarms, What would be the signature of the method?. The number of alarms returned by GetAlarms will vary.
Does VBScrip support Safe Array?
The declaration in the *.idl file would look like this:
[id(1)] HRESULT GetAlarms([out,retval] SAFEARRAY(VARIANT)* pAlarms);
The corresponding C++ method would look like this:
STDMETHODIMP CMyClass::GetAlarms(SAFEARRAY** pAlarms)
{
CComSafeArray<VARIANT> alarms(3);
CComVariant value;
value = L"First Alarm";
alarms.SetAt(0, value);
value = L"Second Alarm";
alarms.SetAt(1, value);
value = L"Third Alarm";
alarms.SetAt(2, value);
*pAlarms = alarms.Detach();
return S_OK;
}
And finally, here is a sample VBScript that uses the above method:
Set obj = CreateObject("MyLib.MyClass")
a = obj.GetAlarms
For i = 0 To UBound(a)
MsgBox a(i)
Next
In ASP, of course, you would use something else instead of MsgBox.