Can't download file using URLDownloadToFile in Visual C++ - c++

This question is about the usage of URLDownloadToFile API.
I am using URLDownloadToFile in Visual C++ MFC application. On Windows server 2008, the program is working fine.
Sample code:
// invalidate cache, so file is always downloaded from web site
// (if not called, the file will be retrieved from the cache if
// it's already been downloaded.)
DeleteUrlCacheEntry(aCSVDownloadURL);
CallbackHandler callbackHandler;
IBindStatusCallback* pBindStatusCallback = NULL;
callbackHandler.QueryInterface(IID_IBindStatusCallback,
reinterpret_cast<void**>(&pBindStatusCallback));
HRESULT hr = URLDownloadToFile(
NULL, // A pointer to the controlling IUnknown interface
DownloadURL,
FileName, // Filename to save the downloaded file in local
0, // Reserved. Must be set to 0.
pBindStatusCallback // Callback interface to catch the download response; basically the file name
);
if (hr == S_OK)
{
cout << "Download OK" << endl;
}
else if (hr == E_OUTOFMEMORY)
{
cout << "The buffer length is invalid, or there is insufficient memory to complete the operation." << endl;
} else if (hr == INET_E_DOWNLOAD_FAILURE)
{
cout << "The specified resource or callback interface was invalid." << endl;
}
else {
cout << "Other error" << endl;
}
But when run the app in Windows Server 2012 R2, I get the below error:
Error code: INET_E_DOWNLOAD_FAILURE
Description: The specified resource or callback interface was invalid.
Have done googling for few hours, but still no luck. It would be very much appreciated if there is a solution.
The program is created using Visual Studio 2015

Related

How to work with .mdb databases using Visual C++ (Not C++/CLI)?

I'm becoming insane currently because I am not able to find a solution to the following task:
I want to
read out data from tables inside a MS Access .mdb database
manipulate said data and
write it back into the same database
do all that with Visual C++ (not with CLI as I would have to adjust lots of already existing code)
To do so, I tried to use the solution provided here, which uses ADO to work with the Northwind 2007.accdb database (It shouldn't be a problem that they access .accdb instead of .mdb right?). I copypasted the code given there into an empty project in VS2017 x64, only adjusted the sourcepath of the Northwind database and changed the following line
hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
to
HRESULT hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
because otherwise hr isn't defined. (Was this an incorrect adjustment?)
I have MS Access 2016 64bit version installed.
Now here is my code:
#import <C:\\Program Files\\Common Files\\System\\ado\\msado15.dll> rename( "EOF", "AdoNSEOF" )
#include <iostream>
using namespace std;
int main() {
_bstr_t bstrConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\Public\\Downloads\\Northwind 2007.accdb;";
// Shows the Data Access Method used in this sample.
const char* DAM = "ADO";
ADODB::_ConnectionPtr pConn("ADODB.Connection");
HRESULT hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
if (SUCCEEDED(hr)) {
cout << DAM << ": Successfully connected to database. Data source name:\n "
<< pConn->GetConnectionString() << endl;
// Prepare SQL query.
_bstr_t query = "SELECT Customers.[Company], Customers.[First Name] FROM Customers;";
cout << DAM << ": SQL query:\n " << query << endl;
// Excecute the query and create a record set.
ADODB::_RecordsetPtr pRS("ADODB.Recordset");
hr = pRS->Open(query,
_variant_t((IDispatch *)pConn, true),
ADODB::adOpenUnspecified,
ADODB::adLockUnspecified,
ADODB::adCmdText);
if (SUCCEEDED(hr)) {
cout << DAM << ": Retrieve schema info for the given result set: " << endl;
ADODB::Fields* pFields = NULL;
hr = pRS->get_Fields(&pFields);
if (SUCCEEDED(hr) && pFields && pFields->GetCount() > 0) {
for (long nIndex = 0; nIndex < pFields->GetCount(); nIndex++) {
cout << " | " << _bstr_t(pFields->GetItem(nIndex)->GetName());
}
cout << endl;
} else {
cout << DAM << ": Error: Number of fields in the result set is 0." << endl;
}
cout << DAM << ": Fetch the actual data: " << endl;
int rowCount = 0;
while (!pRS->AdoNSEOF) {
for (long nIndex = 0; nIndex < pFields->GetCount(); nIndex++) {
cout << " | " << _bstr_t(pFields->GetItem(nIndex)->GetValue());
}
cout << endl;
pRS->MoveNext();
rowCount++;
}
cout << DAM << ": Total Row Count: " << rowCount << endl;
}
pRS->Close();
pConn->Close();
cout << DAM << ": Cleanup. Done." << endl;
} else {
cout << DAM << ": Unable to connect to data source: " << bstrConnect << endl;
}
return 1;
}
The code compiles but in msado15.tlh which is generated by the import directive there are 52 errors E0102 shown (for different lines but always the same error), the description being: The Forward declaration of the enumeration type doesn't comply to the standard (rough translation, I think it gets the point across). (As a side question: When using the import directive, where in the project properties do I have to link the msado15.dll path? I added the C:\Program Files\Common Files\System\ado path to the Include directory, was that right?)
Furthermore running the .exe or executing it in Powershell doesn't work, Windows gives out the message "MYPROGRAM.exe isn't running anymore" with the only option to close the program.
What am I doing wrong? Have I chosen the wrong approach to what in my eyes seems to be a task that should be quite easy to solve (shouldn't be that hard to read out a damn table in Visual C++)?
Is there maybe a better way to work with .mdb databases (like using DAO, ODBC or OLE DB for example) and are there working up-to-date code samples that one could work with or a nice documentation/tutorial that explains step-by-step how to connect to the database and shows how to read from and write into it?
EDIT1: A_Singh7 provided the following solutions:
define ghr as a global variable
change the return value of the main function to 0
Use the code provided here
The first two solutions didn't do the trick so I tried it with the code from solution 3. This is the output in Powershell i receive:
ADO: Successfully connected to database. Data source name:
Provider=Microsoft.ACE.OLEDB.12.0;User ID=admin;Data Source=C:\Users\Public\Downloads\Northwind 2007.accdb;Mode=Share Deny None;Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=False;Jet OLEDB:Bypass UserInfo Validation=False;Jet OLEDB:Limited DB Caching=False;Jet OLEDB:Bypass ChoiceField Validation=False;
ADO: SQL query
SELECT Customers.[Company], Customers.[First Name] FROM Customers;
Afterwards, the .exe sadly crashes and I still have to figure out why. Nonetheless establishing a connection to the database seems to work, which was the main issue I had.
Try to declare hr as a global variable.
That’s like,
#include <iostream>
using namespace std;
HRESULT hr;
int main ()
{
// your code
// the line hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified); should remain as it is
}
First try the above, if it doesn’t work, try changing return 1; to return 0;.
If that even doesn’t work, see here:
http://msdn.microsoft.com/en-us/library/cc811599.aspx
Take help from here after that :
Connecting to MS Access database using C++ using Visual Studio 2008
Here you just need to include the file stafdx.h as a header to make the code work perfectly.

Having trouble using winpcap to write DLT_USER0 captures

I'm making a C++ program using MINGW that uses the Winpcap library to save BTLE packets into a PCAP file.
I'm trying to open a PCAP file using the DLT_USER0 link layer type.
I can open DLT_USER0 using the call to pcap_open_dead() but pcap_dump_open() is complaining that it doesn't know the corresponding link type.
I get the following message after calling pcap_geterr():
out-dump.pcap: link-layer type -1 isn't supported in savefiles
Here's my code below.
#define OUT_FILENAME "out-dump.pcap"
pcap_t *pcap_dumpfile; // Descriptor of an open capture instance
pcap_dumper_t *dumper; // libpcap savefile descriptor"
// pcap_open_dead() creates a pcap_t structure to use when
// calling other functions in libpacp
pcap_dumpfile = pcap_open_dead(DLT_USER0, 128);
// Check if pcap_dumpfile was created. If it was not it will return a NULL
if (NULL == pcap_dumpfile)
{
cout << "\npcap_open_dead() FAILED!!!" << endl;
}
else
{
// Open a save file to write to!
dumper = pcap_dump_open(pcap_dumpfile, OUT_FILENAME);
pcap_dump_flush(dumper);
// Check if the dumper was created
if (NULL == dumper)
{
// Printout the FAIL status
cout << "\npcap_dump_open() FAILED!!!" << endl;
// Printout the PCAP Error
cout << "\n" << pcap_geterr(pcap_dumpfile) << endl;
// Close the pcap_dumpfile and deallocate it's resources
pcap_close(pcap_dumpfile);
}
}
I'm using the WinPcap 4.1.2 Developer's Pack to build my C++ application.
Sadly, that's a bug in WinPcap 4.1.2.
Hopefully, a future release of WinPcap will be based on a later version of libpcap in which the bug is fixed.

Visual C++, Windows Update Interface (IUpdate) <wuapi.h>, get_MsrcSeverity

I'm probably just blind, but I cannot see any errors here (and I am looking on this issue already for days now...)
I am trying to get the Patch Priority (Severity) from the Windows Update Interface using the following piece of code in Visual Studio:
#include "stdafx.h"
#include <wuapi.h>
#include <iostream>
#include <ATLComTime.h>
#include <wuerror.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr;
hr = CoInitialize(NULL);
IUpdateSession* iUpdate;
IUpdateSearcher* searcher;
ISearchResult* results;
BSTR criteria = SysAllocString(L"IsInstalled=0");
hr = CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&iUpdate);
hr = iUpdate->CreateUpdateSearcher(&searcher);
wcout << L"Searching for updates ..."<<endl;
hr = searcher->Search(criteria, &results);
SysFreeString(criteria);
switch(hr)
{
case S_OK:
wcout<<L"List of applicable items on the machine:"<<endl;
break;
case WU_E_LEGACYSERVER:
wcout<<L"No server selection enabled"<<endl;
return 0;
case WU_E_INVALID_CRITERIA:
wcout<<L"Invalid search criteria"<<endl;
return 0;
}
IUpdateCollection *updateList;
IUpdateCollection *bundledUpdates;
IUpdate *updateItem;
IUpdate *bundledUpdateItem;
LONG updateSize;
LONG bundledUpdateSize;
BSTR updateName;
BSTR severity;
results->get_Updates(&updateList);
updateList->get_Count(&updateSize);
if (updateSize == 0)
{
wcout << L"No updates found"<<endl;
}
for (LONG i = 0; i < updateSize; i++)
{
updateList->get_Item(i,&updateItem);
updateItem->get_Title(&updateName);
severity = NULL;
updateItem->get_MsrcSeverity(&severity);
if (severity != NULL)
{
wcout << L"update severity: " << severity << endl;
}
wcout<<i+1<<" - " << updateName << endl;
// bundled updates
updateItem->get_BundledUpdates(&bundledUpdates);
bundledUpdates->get_Count(&bundledUpdateSize);
if (bundledUpdateSize != 0)
{
// iterate through bundled updates
for (LONG ii = 0; ii < bundledUpdateSize; ii++)
{
bundledUpdates->get_Item(ii, &bundledUpdateItem);
severity = NULL;
bundledUpdateItem->get_MsrcSeverity(&severity);
if (severity != NULL)
{
wcout << L" bundled update severity: " << severity << endl;
}
}
}
}
::CoUninitialize();
wcin.get();
return 0;
}
So here's the issue: updateItem->get_MsrcSeverity(&severity); is not returning anything. If I catch the result code with an HRESULT it always returns S_OK.
Link to MSDN IUpdate MsrcSeverity: http://msdn.microsoft.com/en-us/library/windows/desktop/aa386906(v=vs.85).aspx
Can you see what I am doing obviously wrong or is the get_MsrcSeverity function currently broken?
#EDIT: Changed the code to iterate through "BundledUpdates" as suggested.
#EDIT2: the code now outputs the severity value of the updateItem as well as the bundledUpdatesItem, but it's always NULL.
I also know there is one important update waiting for my computer - regarding to Windows Update in the control panel. It is KB2858725.
#EDIT3: Okay, it turns out, KB2858725 is no security update and therefore has no severity rating by Microsoft. But how does Microsoft Windows Update now categorize the updates in "important" and "optional" like you can see it in control panel's update?
Thank you for any hints!
// Markus
I've been struggling with the exact same problem for hours now... I finally figured out that Microsoft only seems to set the MsrcSeverity value on some updates. For general Windows updates, it's usually null. For most security updates it's set to one of:
"Critical"
"Moderate"
"Important"
"Low"
It seems as though the "Unspecified" value is never used, though it is documented in MSDN (http://msdn.microsoft.com/en-us/library/microsoft.updateservices.administration.msrcseverity(v=vs.85).aspx).
I wrote a small C# program to list all available updates and their reported severity. It requires a reference to WUApiLib:
using System;
using WUApiLib;
namespace EnumerateUpdates
{
class Program
{
static void Main(string[] args)
{
var session = new UpdateSession();
var searcher = session.CreateUpdateSearcher();
searcher.Online = false;
// Find all updates that have not yet been installed
var result = searcher.Search("IsInstalled=0 And IsHidden=0");
foreach (dynamic update in result.Updates)
{
Console.WriteLine(update.Title + ": " + update.Description);
Console.WriteLine("Severity is " + update.MsrcSeverity);
Console.WriteLine();
}
Console.ReadLine();
}
}
}
Hope this helps someone!
Look for bundled updates in the list. The bundled updates does not have some properties or methods as described on this page.
Remarks
If the BundledUpdates property contains an IUpdateCollection, some
properties and methods of the update may only be available on the
bundled updates, for example, DownloadContents or CopyFromCache.
The update you are processing in is a bundled update. Extract the individual updates from this bundle, it will have the property you are looking out for.
The IUpdate interface has a method get_BundledUpdates which gets you a IUpdateCollection if the size of this collection is greater then 0, this is a bundled update.

CLR ICLRControl::GetCLRManager fails with error HOST_E_INVALIDOPERATION

I have a native process which uses .NET component via COM interop. Once the process is up, I am trying to get interface pointers to the various CLR managers such as ICLRDebugManager, ICLRGCManager, etc. using the ICLRControl interface pointer. I'm able to reach up to acquiring ICLRControl interface without a glitch. ICLRRuntimeInfo also correctly tells me that it is 4.0.x .net version when I call GetVersionString on it.
It is only that the ICLRControl::GetCLRManager keeps failing with error 0x80130122, which error code stands for HOST_E_INVALIDOPERATION. Searched the internet, but could not get information as to why this might be failing. Any help is much appreciated.
TIA.
WinCPP
Edit 1. Adding code snippet.
// ICLRRuntimeInfo interface pointer
CComQIPtr<ICLRRuntimeInfo> pCLRRuntimeInfo = pUnk;
if (!pCLRRuntimeInfo)
{
cout << "failed to get run time info interface pointer" << endl;
return;
}
TCHAR version[128];
memset(version, 0, 128);
DWORD count = 127;
pCLRRuntimeInfo->GetVersionString(version, &count);
cout << version << endl;
// ICLRRuntimeHost
CComPtr<ICLRRuntimeHost> pCLRRuntimeHost = 0;
hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pCLRRuntimeHost);
if (FAILED(hr))
{
cout << "failed to get run time host interface pointer" << endl;
return;
}
// ICLRControl
CComPtr<ICLRControl> pCLRControl = 0;
hr = pCLRRuntimeHost->GetCLRControl(&pCLRControl);
if (FAILED(hr))
{
cout << "failed to get clr control interface pointer" << endl;
return;
}
///////////////////////////////////////////
// Everything is successful upto this point
///////////////////////////////////////////
// ICLRGCManager
CComPtr<ICLRGCManager> pCLRGCManager = 0;
hr = pCLRControl->GetCLRManager(IID_ICLRGCManager, (LPVOID *)&pCLRGCManager);
if (FAILED(hr))
{
cout << "failed to get GC manager interface pointer" << endl;
return;
}
// Above call fails with the error 0x81031022, though everything is as per the MSDN documentation for the API
Looking at this source code on GitHub, it looks like CCorCLRControl::GetCLRManager will return HOST_E_INVALIDOPERATION if the runtime has already been started.
This explains why you are receiving that error code when attempting to "latch on to already loaded CLR instance," but that you meet with success when you create a CLR instance explicitly.

MS CryptoAPI doesn't work on Windows XP with CryptAcquireContext()

I wrote some code using the Microsoft CryptoAPI to calculate a SHA-1 and got the compiled exe working on Windows 7, Win Server 2008, Win Server 2003. However, when I run it under Windows XP SP3, it does not work.
I narrowed down the failure to the CryptAcquireContext() call.
I did notice that a previous post talked about the XP faulty naming of "… (Prototype)" and it must be accounted for by using a WinXP specific macro MS_ENH_RSA_AES_PROV_XP.
I did the XP specific code modifications and it still doesn't work. (The bResult returns 0 false on Win XP, all other platforms bResult returns 1 true.)
I checked the MS_ENH_RSA_AES_PROV_XP with the actual key+string values I see in regedit.exe so everything looks like it's set up to work but no success.
Have I overlooked something to make it work on Windows XP?
I've pasted shortest possible example to illustrate the issue. I used VS2010 C++.
// based on examples from http://msdn.microsoft.com/en-us/library/ms867086.aspx
#include "windows.h"
#include "wincrypt.h"
#include <iostream>
#include <iomanip> // for setw()
void main()
{
BOOL bResult;
HCRYPTPROV hProv;
// Attempt to acquire a handle to the default key container.
bResult = CryptAcquireContext(
&hProv, // Variable to hold returned handle.
NULL, // Use default key container.
MS_DEF_PROV, // Use default CSP.
PROV_RSA_FULL, // Type of provider to acquire.
0); // No special action.
std::cout << "line: " << std::setw(4) << __LINE__ << "; " << "bResult = " << bResult << std::endl;
if (! bResult) { // try Windows XP provider name
bResult = CryptAcquireContext(
&hProv, // Variable to hold returned handle.
NULL, // Use default key container.
MS_ENH_RSA_AES_PROV_XP, // Windows XP specific instead of using default CSP.
PROV_RSA_AES, // Type of provider to acquire.
0); // No special action.
std::cout << "line: " << std::setw(4) << __LINE__ << "; " << "bResult = " << bResult << std::endl;
}
if (bResult)
CryptReleaseContext(hProv, 0);
}
Windows 7 success:
Windows XP failure:
In your CryptAcquireContext code, it appears you are missing the parameter to get a context without a specific container set. You need to pass the CRYPT_VERIFYCONTEXT option in CryptAcquireContext.
Windows 7 might be working around this.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx
For further diagnosis, the results of GetLastError() would be requisite.