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

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.

Related

IPortableDeviceManager::GetDevices returning 0 Devices

I'm currently writing a simple application to retrieve a list of the PnP devices of my computer. To do this, I'm making use of the Windows PortableDeviceApi Library.
So far I have the following code:
#include <iostream>
#include <PortableDeviceApi.h>
#include <wrl.h>
inline void getDeviceHWIDs() {
// Initialize
CoInitialize(nullptr);
// create portable device manager object
Microsoft::WRL::ComPtr<IPortableDeviceManager> device_manager;
HRESULT hr = CoCreateInstance(CLSID_PortableDeviceManager,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&device_manager));
if (FAILED(hr)) {
std::cout << "! Failed to CoCreateInstance CLSID_PortableDeviceManager, hr = " << std::hex << hr << std::endl;
}
// obtain amount of devices
DWORD pnp_device_id_count = 0;
if (SUCCEEDED(hr)) {
hr = device_manager->GetDevices(nullptr, &pnp_device_id_count);
if (FAILED(hr)) {
std::cout << "! Failed to get number of devices on the system, hr = " << std::hex << hr << std::endl;
}
}
std::cout << "Devices found: " << pnp_device_id_count << std::endl;
// Uninitialize
CoUninitialize();
}
The code compiles and runs successfully, however pnp_device_id_count is returning 0, indicating that there are no PnP devices connected to my computer. This is obviously an incorrect result, since Get-PnpDevice in PowerShell returns a large list of devices.
Any help would be much appreciated, as I'm a bit stumped over this ':(
Thank you :)
This is expected, Windows Portable Devices provides only a way to communicate with music players, storage devices, mobile phones, cameras, and many other types of connected devices.
It will not enumerate all devices on your system. Connect an IPhone and you will see pnp_device_id_count become 1.
To enumerate all devices you can use WinRT's Windows.Devices.Enumeration Namespace or the ancient Setup API.
Here is a (C# but you can do the same with C++) sample for using WinRT's one https://github.com/smourier/DeviceExplorer and a C++ sample for using Setup API: https://www.codeproject.com/Articles/14412/Enumerating-windows-device

How to "WINAPI::GetLastError" in QT application?

Why is last error in QT application always zero ?
SetLastError(23);
qDebug() << "LastError: " << GetLastError();
expected output:
LastError: 23
actual output:
LastError: 0
I can't google anything about this issue. Are these functions hooked by QT ?
DWORD lastError = GetLastError();
qDebug() << "LastError: " << lastError;
Always grab the last error immediately after the API call that failed. Those intervening qDebug() and operator<< calls themselves call Windows API functions, which may or may not reset the last error.
When you make calls to the runtime library then that in turn can call Win32 API functions, and reset the error value. Fix your code like this:
SetLastError(23);
DWORD err = GetLastError();
qDebug() << "LastError: " << err;
This ensures that you read the error value before the runtime makes calls to Win32 functions.

AddFontResource + SetCurrentConsoleFontEx are not changing a console font

I'm trying to change a console font to a custom one, but this specific code piece doesn't seem to acomplish anything, even though this is what I came up while trying to find a solution around the Internet. I tested just the SetCurrentConsoleFontEx with this custom font by installing and adding it to the console with regestry by hand, and it's been functioning properly.
#include <iostream>
#include <Windows.h>
int main()
{
std::cout << "Default font" << std::endl;
system("pause");
HANDLE m_stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
AddFontResourceEx(L"Iosevka.ttf", FR_PRIVATE, 0);
SendNotifyMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
CONSOLE_FONT_INFOEX cfie;
ZeroMemory(&cfie, sizeof(cfie));
cfie.cbSize = sizeof(cfie);
cfie.dwFontSize.Y = 21;
lstrcpyW(cfie.FaceName, L"Iosevka");
SetCurrentConsoleFontEx(m_stdOut, false, &cfie);
std::cout << "Custom font" << std::endl;
RemoveFontResource(L"Iosevka.ttf");
system("pause");
return 0;
}
You are calling AddFontResourceEx() with FR_PRIVATE flag, which means the font is available only to your process.
Unfortunately, the console window is not part of your process (GetWindowThreadProcessId() lies in this regard!). It is hosted by a system process ("csrss.exe" before Win 7, "conhost.exe" since then).
See: Windows Command-Line: Inside the Windows Console
To make the font available to the console, you have to remove the FR_PRIVATE flag or install the font permanently.

I2C error when using the Windows Monitor Configuration Functions

I'm attempting to get/set the brightness level of the monitor through the Windows API. I've tried both the Low-Level Monitor Configuration Functions and the High-Level Monitor Configuration Functions, but they both seem to be breaking in the same place. In both cases I have no problem getting the HMONITOR handle and getting the physical monitor handle from the HMONITOR, but once I try to query the DDC/CI capabilities, I get an error saying "An error occurred while transmitting data to the device on the I2C bus."
The particular functions that cause this error are GetMonitorCapabilities for the high-level functions and GetCapabilitiesStringLength for the low-level functions. They both cause the same error.
This leads me to believe that maybe my monitor doesn't support DDC/CI, but I know my laptop's monitor brightness can be changed through the control panel, so it must be controlled through software somehow. Also I can successfully use the WMI classes in a PowerShell script to get/set the brightness as described on this page. Most things I've read suggest that most modern laptop screens do support DDC/CI.
Is there any way to find out what is causing this error or to get more information about it? I'm currently working in C++ in Visual Studio 2013 on Windows 7. I could probably use WMI in my C++ program if I can't get this current method working, but I thought I would ask here first.
Here's the code I currently have:
#include "stdafx.h"
#include <windows.h>
#include <highlevelmonitorconfigurationapi.h>
#include <lowlevelmonitorconfigurationapi.h>
#include <physicalmonitorenumerationapi.h>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
DWORD minBrightness, curBrightness, maxBrightness;
HWND curWin = GetConsoleWindow();
if (curWin == NULL) {
std::cout << "Problem getting a handle to the window." << std::endl;
return 1;
}
// Call MonitorFromWindow to get the HMONITOR handle
HMONITOR curMon = MonitorFromWindow(curWin, MONITOR_DEFAULTTONULL);
if (curMon == NULL) {
std::cout << "Problem getting the display monitor" << std::endl;
return 1;
}
// Call GetNumberOfPhysicalMonitorsFromHMONITOR to get the needed array size
DWORD monitorCount;
if (!GetNumberOfPhysicalMonitorsFromHMONITOR(curMon, &monitorCount)) {
std::cout << "Problem getting the number of physical monitors" << std::endl;
return 1;
}
// Call GetPhysicalMonitorsFromHMONITOR to get a handle to the physical monitor
LPPHYSICAL_MONITOR physicalMonitors = (LPPHYSICAL_MONITOR)malloc(monitorCount*sizeof(PHYSICAL_MONITOR));
if (physicalMonitors == NULL) {
std::cout << "Unable to malloc the physical monitor array." << std::endl;
return 1;
}
if (!GetPhysicalMonitorsFromHMONITOR(curMon, monitorCount, physicalMonitors)) {
std::cout << "Problem getting the physical monitors." << std::endl;
return 1;
}
std::cout << "Num Monitors: " << monitorCount << std::endl; // This prints '1' as expected.
wprintf(L"%s\n", physicalMonitors[0].szPhysicalMonitorDescription); // This prints "Generic PnP Monitor" as expected
// Call GetMonitorCapabilities to find out which functions it supports
DWORD monCaps;
DWORD monColorTemps;
// The following function call fails with the error "An error occurred while transmitting data to the device on the I2C bus."
if (!GetMonitorCapabilities(physicalMonitors[0].hPhysicalMonitor, &monCaps, &monColorTemps)) {
std::cout << "Problem getting the monitor's capabilities." << std::endl;
DWORD errNum = GetLastError();
DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
LPVOID buffer;
FormatMessage(flags, NULL, errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&buffer, 0, NULL);
wprintf(L"%s\n", buffer);
return 1;
}
// Same error when I use GetCapabilitiesStringLength(...) here.
// More code that is currently never reached...
return 0;
}
Edit: Also I should note that physicalMonitors[0].hPhysicalMonitor is 0, even though the monitor count and text description are valid and the GetPhysicalMonitorsFromHMONITOR function returns successfully. Any thoughts on why this might be?
This is a "wonky hardware" problem, the I2C bus it talks about is the logical interconnect between the video adapter and the display monitor. Primarily useful for plug & play. Underlying error code is 0xC01E0582, STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA. It is generated by a the DxgkDdiI2CTransmitDataToDisplay() helper function in the video miniport driver. It is the vendor's video driver job to configure it, providing the functions that tickle the bus and to implement the IOCTL underlying GetMonitorCapabilities().
Clearly you are device driver land here, there isn't anything you can do about this failure in your C++ program. You can randomly spin the wheel of fortune by looking for a driver update from the video adapter manufacturer. But non-zero odds that the monitor is at fault here. Try another one first.
I know its bad time to reply but i thought you should know.
The problem you are facing is because of the DDC/CI disabled on your monitor so you should go to the monitor settings and check if DDC/CI is disabled and if it is, then you have to enable it and run your code again. It would work. If you were not able to find DDC/CI option ( some of the monitor have a separate button for enabling/disabling the DDC/CI like the Benq's T71W monitor has a separate down arrow button to enable/disable DDC/CI ) then you should refer to your monitor's manual or contact the manufacturer.
Hope that helps. and sorry for late reply.
Best of luck. :)
As I read the original question, the poster wanted to control a laptop display using DDC/CI. Laptop displays do not support DDC/CI. They provide a stripped down I2C bus sufficient to read the EDID at slave address x50, but that's it.

How to detect antivirus installed on windows 2003 server and 2008 server 2003 server R2and 2008 server R2 using WMI or other then WMI in C++

i have used WMI to detect that antivirus is present on OS,
itz woking fine and display me information of antivirus like name and instance id on win xp and window7 by using Namespace:\root\SecurityCenter and \root\SecurityCenter, \root\Security.
if(isHLOSVersion( ))
hres = pLoc->ConnectServer( _bstr_t(L"root\\SecurityCenter2"),
// Object path of SecurityCenter
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
else
hres = pLoc->ConnectServer( _bstr_t(L"root\\SecurityCenter"),
// Object path of SecurityCenter
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
But in case of windows 2003 server and 2008 server 2003 server R2and 2008 server R2 these above namespace are not present so this is not working there.
Please let me know how can we detect that antivirus present or not windows 2003 server and 2008 server 2003 server R2and 2008 server R2 operating system.
That namespace is not available on Windows Server platforms an I think it might be deprecated for Workstation (i.e. going away).
You can probably use WscGetSecurityProviderHealth() to get the same result.
See http://msdn.microsoft.com/en-us/library/bb432506.aspx
Here's my trivial sample that seems to work:
#define _WIN32_WINNT _WIN32_WINNT_WIN7
#include <Windows.h>
#include <Wscapi.h>
#include <iostream>
#pragma comment(lib, "Wscapi")
int main(int argc, char* argv[])
{
WSC_SECURITY_PROVIDER_HEALTH health;
const DWORD dwAntivirus(WSC_SECURITY_PROVIDER_ANTIVIRUS);
HRESULT hr = WscGetSecurityProviderHealth(dwAntivirus, &health);
if (FAILED(hr))
{
std::cerr << "Error " << std::hex
<< std::showbase << hr << "\n";
return -1;
}
switch (health)
{
case WSC_SECURITY_PROVIDER_HEALTH_GOOD:
std::cout << "Antivirus health is good\n";
return 0;
case WSC_SECURITY_PROVIDER_HEALTH_NOTMONITORED:
std::cout << "Antivirus health is not monitored\n";
return 1;
case WSC_SECURITY_PROVIDER_HEALTH_POOR:
std::cout << "Antivirus health is poor\n";
return 2;
case WSC_SECURITY_PROVIDER_HEALTH_SNOOZE:
std::cout << "Antivirus health is snooze\n";
return 3;
default:
std::cout << "Unexpected antivirus health value: "
<< std::hex << std::showbase
<< health << "\n";
return 4;
}
}
Update 9 Dec 2012
Alex points out (below) that this does not work on Windows Server, only on Workstation versions of Windows. On reflection, it occurs to me that it is probably deliberate and, in fact, probably for the best.
Do application programs really need to know the status of a server? Most security programs for servers have mechanisms to set alarms when they fail. An admin will monitor those alarms and fix what is broken. Application programs should simply behave as if security is fully operational.
If you really must know about a particular program, you can look for its exe name amongst the processes and see if the process is running and is consuming cpu (not hung). Beyond that you might need to work with the security program's vendor: they may have an API to query the program.