PDH cant access total CPU time through PdhAddCounter() - c++

i am currently trying to make some sort of CPU usage overview for my DirectX program, but it seems that i am not able to get this information through PdhAddCounter().
My code looks like this:
status = PdhOpenQuery(NULL, 0, &m_queryHandle);
if(status != ERROR_SUCCESS)
{
m_canReadCpu = false;
}
status = PdhAddCounter(m_queryHandle, TEXT("\\Processor(_Total)\\% processor time"), 0, &m_counterHandle);
if(status != ERROR_SUCCESS)
{
m_canReadCpu = false;
}
After the PdhAddCounter call my status is = -1073738824, wich causes the program to fail.
Im using a Windows 7 64bit system, do i have to make something different in a 64bit environment?
Thanks for any help.

Remember: PdhAddCounter is locale sensible.
The response -1073738824 means PDH_CSTATUS_NO_OBJECT=0xC0000BB8. The api didn't find that string. Are you using a non-english OS?
If you need to do a Windows XP compatible application you need to use a workaround like this: http://en.verysource.com/code/3604946_1/platforminfo.cpp.html.
For Vista and Windows 7, 8,... you can use PdhAddEnglishCounter instead.

You may also want to use GetSystemTimes kernel32 API which will free you from the dependency on pdh.dll.
See my answer here.

Related

Detect emptiness of DVD-RAM media on Windows 7 x64

I'm trying to detect if a DVD-RAM media is empty or not, with C++ on Windows. The simplest choice is to use IMAPI (version 2) - boilerplate code omitted:
IMAPI_FORMAT2_DATA_MEDIA_STATE state;
HRESULT hr;
// ... Initialize an MsftDiscFormat2Data COM object and put recorder
hr = format->get_CurrentMediaStatus( &state );
// ... Verify returned status ...
return (state & IMAPI_FORMAT2_DATA_MEDIA_STATE_BLANK);
This code usually works perfectly. However, with DVD-RAM it gives the wrong results: the only flag enabled in the returned state is IMAPI_FORMAT2_DATA_MEDIA_STATE_OVERWRITE_ONLY ( = 0x1).
On Windows Vista 32 bit it works as expected.
Does anyone knows the reason for this result? Is there any workaround?
You can use the method IDiscFormat2::get_MediaHeuristicallyBlank from IDiscFormat2 interface.
It will attempt to determine if the media is blank using heuristics (mainly for DVD+RW and DVD-RAM media).
VARIANT_BOOL vbBlank;
hr = format->get_MediaHeuristicallyBlank(&vbBlank);
if (VARIANT_TRUE == vbBlank)
Log("The media is blank.");
In order to determine if the current media is reported as physically blank by the drive you can use IDiscFormat2::get_MediaPhysicallyBlank method.
As for the reasons of the different behavior between Windows7 x64 and Windows Vista x86, it could be because IMAPIv2 versions may be different on those systems. You may want to update your Vista machine with the latest Image Mastering API v2.0 update package to get the same results on each system.

How to set and read pins on the parallel port from C++?

I am helping a friend to finish a final year project in which he has this circuit that we want to switch on and off using a C++ program.
I initially thought it would be easy, but I have failed to implement this program.
The main problem is that
Windows XP and above don't allow direct access to hardware so some websites are suggesting that I need to write a driver or find a driver.
I have also looked at some projects online but they seem to work for Windows XP but fail to work for Windows 7.
Also, most projects were written in VB or C# which I am not familiar with.
Question:
Is there a suitable driver that works for Windows XP and Windows 7, and if yes how can I use it in my code? (code snippets would be appreciated)
Is there a cross platform way of dealing communicating with parallel ports?
Have a look at codeproject: here, here and here. You'll find treasures.
The 1st link works for Windows 7 - both 32 bit and 64 bit.
You shouldn't need to write a driver or anything -- you just call CreateFile with a filename like "LPT1" to open up a handle to the parallel port, and then you can use WriteFile to write data to it. For example:
HANDLE parallelPort = CreateFile("LPT1", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(parallelPort == INVALID_HANDLE_VALUE)
{
// handle error
}
...
// Write the string "foobar" (and its null terminator) to the parallel port.
// Error checking omitted for expository purposes.
const char *data = "foobar";
WriteFile(parallelPort, data, strlen(data)+1, NULL, NULL);
...
CloseHandle(parallelPort);

Some CPU Information

Well, i we're working on a CPU Controller, which shows all CPU Data. I've managed to get Windows Version, Windows Service Pack, Processor Name, Processor Speed, Processor Identifier(Though Registry Vals).
But now i don't have any idea of how to get the processor Instructions, Caches, Video Card Information (Video Card Name, Available Memory, Total Memory), Southbridge Information (Ethernet Information)
Well, i've been loking on WinAPI but i get it very hard to work. I've looked over google 3 hours but nothing. :/ Any idea? :(
Have you looked at WMI ? This appears to suggest you can get SouthBridge info through WMI.
Gonna expand cppanda's answer a bit:
Concerning video cards, there's sometimes more than one in the system. The best way to get oodles n oodles of information on them is to use DirectX.
If it's meant to be compatible with Vista and up, you can use DXGI, which is cleaner and easier to use in my opinion.
First things first, you'll need to create a DXGI factory...
IDXGIFactory* DXGIFactoryPtr = 0;
HRESULT RetVal = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&DXGIFactoryPtr);
if (FAILED(RetVal)) {/*Error Checking*/;}
then use it to loop through each adapter...
unsigned short I = 0;
IDXGIAdapter* AdapterPtr = 0;
std::vector<IDXGIAdapter*> Adapters;
while (DXGIFactoryPtr->EnumAdapters(I, &AdapterPtr) != DXGI_ERROR_NOT_FOUND)
{
Adapters.push_back(AdapterPtr);
++I;
}
From here, you can see if Direct3D 10 is supported:
if (Adapters[I]->CheckInterfaceSupport(__uuidof(ID3D10Device), 0) == S_OK)
{ /*D3D10 is supported for this device*/; }
Enumerate attached outputs [I.E. Moniters], which could be useful for checking which resolutions are supported and such:
unsigned short J = 0;
IDXGIOutput* OutputPtr = 0;
std::vector<IDXGIOutput*> Outputs;
while (Adapter[I]->EnumOutputs(J, &OutputPtr) != DXGI_ERROR_NOT_FOUND)
{
Outputs.push_back(OutputPtr);
++J;
}
and get a description:
DXGI_ADAPTER_DESC AdapterDescription;
Adapter[I]->GetDesc(&AdapterDescription);
AdapterDescription has the fields Description, VenderId, DeviceId, SubSysId, Revision, DedicatedVideoMemory, DedicatedSystemMemory, SharedSystemMemory, and AdapterLuid.
AdapterLuid is a system specific unique identifier for the card, but all the others should be very obvious given the names.
Beyond that, it becomes vendor specific I think.
For DirectX 9, which is available for Windows 2000 up, it's a bit different. First, you have to create the core Direct3D9 object:
IDirect3D9* D3D9 = Direct3DCreate9(D3D_SDK_VERSION);
if (D3D9 == 0)
{ /* Error checking*/; }
Then get the adapter count:
unsigned short AdapterCount = (unsigned short)D3D9->GetAdapterCount();
Then loop through them, getting their identifiers:
D3DADAPTER_IDENTIFIER9* Identifiers = new D3DADAPTER_IDENTIFIER9[AdapterCount];
HRESULT RetVal = 0;
for (unsigned short I = 0; I < AdapterCount; ++I)
{
RetVal = D3D9->GetAdapterIdentifier(I, 0, &Identifiers[I]);
if (FAILED(RetVal))
{ /* Error checking*/; }
}
Again, most of the fields should be self explanitory. WHQLLevel is information on if and when Microsoft tested that driver's compatability with Windows, and for the most part can be safely ignored. Using close to the same method above, you can also acquire a device's capabilities using GetDeviceCaps, which would give you more information.
As cppanda said, you can use IDirect3DDevice9::GetAvailableTextureMem(), but that requires you to create the device before querying it. Anything the above two don't indicate require creating the device before retrieving it.
Hope that helps~
[Side note, a lot of this was pulled out of the DirectX SDK so code's theirs, not mine.]
Take a look at:
MEMORYSTATUSEX status;
GlobalMemoryStatusEx(&status);
For RAM and Virtual RAM
For video memory
vista:
CreateDXGIFactory API via GetProcAddress()
Below vista, d3d9 API
GetAvailableTextureMemory()
Well, the CPUID instruction gives a bit of info. Not all that you need, but it's a start.

How do you programmatically determine whether a Windows computer is a member of a domain?

I need a way to determine whether the computer running my program is joined to any domain. It doesn't matter what specific domain it is part of, just whether it is connected to anything. I'm coding in vc++ against the Win32 API.
Straight from Microsoft:
How To Determine If a Windows NT/Windows 2000 Computer Is a Domain Member
This approach uses the Windows API. From the article summary:
This article describes how to
determine if a computer that is
running Windows NT 4.0 or Windows 2000
is a member of a domain, is a member
of a workgroup, or is a stand-alone
computer using the Local Security
Authority APIs.
The article also provides sample code for a small program that outputs whether the computer the program is running on is part of a domain, part of a workgroup, or a standalone computer.
I think the NetServerEnum function will help you in what you want; I would ask for the primary domain controllers with the SV_TYPE_DOMAIN_CTRL constant for servertype parameter. If you don't get any, then you're not in a domain.
The code in the MSDN sample is a little outdated. This is the function I came up with that works.
bool ComputerBelongsToDomain()
{
bool ret = false;
LSA_OBJECT_ATTRIBUTES objectAttributes;
LSA_HANDLE policyHandle;
NTSTATUS status;
PPOLICY_PRIMARY_DOMAIN_INFO info;
// Object attributes are reserved, so initialize to zeros.
ZeroMemory(&objectAttributes, sizeof(objectAttributes));
status = LsaOpenPolicy(NULL, &objectAttributes, GENERIC_READ | POLICY_VIEW_LOCAL_INFORMATION, &policyHandle);
if (!status)
{
status = LsaQueryInformationPolicy(policyHandle, PolicyPrimaryDomainInformation, (LPVOID*)&info);
if (!status)
{
if (info->Sid)
ret = true;
LsaFreeMemory(info);
}
LsaClose(policyHandle);
}
return ret;
}
Here is a dead simple approach I don't see mentioned.
TCHAR UserDnsDomain[128] = { 0 };
DWORD Result = 0;
Result = GetEnvironmentVariable("USERDNSDOMAIN", UserDnsDomain, sizeof(UserDnsDomain));
if (Result == 0 || Result >= sizeof(UserDnsDomain) || GetLastError() == ERROR_ENVVAR_NOT_FOUND)
{
return(FALSE); // Not logged in to a domain
}
This is predicated on the idea that if the user who is running this code is not currently logged in to a domain, then the USERDNSDOMAIN environment variable will be empty or unavailable. But there are some caveats you should think about.
Pros:
Very easy to implement.
99% reliable.
Cons:
May fail or return false results if the computer is domain joined, but the user executing this code is logged on to that computer with a local account.
May fail or return false results if the computer is domain joined, but network connectivity to a domain controller was unavailable at the time of logon/user logged on with cached credentials.
You can check the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon for the value of 'CachePrimaryDomain'.
Avoid LSA which is a wrong method.
You must use DS api (2 lines of code)
what about from the name of the computer?
edit: this was a crapy 'answer' from way back. What I meant was cheching for the form domain\name in the computer name. That of course implies that you do know the name of the domain, it does not solves the issue of just knowing if the computer is in any domain.

IDebugProgramProvider2.GetProviderProcessData on Vista

As part of a JavaScript Profiler for IE 6/7 I needed to load a custom debugger that I created into IE. I got this working fine on XP, but couldn't get it working on Vista (full story here: http://damianblog.com/2008/09/09/tracejs-v2-rip/).
The call to GetProviderProcessData is failing on Vista. Anyone have any suggestions?
Thanks,
Damian
// Create the MsProgramProvider
IDebugProgramProvider2* pIDebugProgramProvider2 = 0;
HRESULT st = CoCreateInstance(CLSID_MsProgramProvider, 0, CLSCTX_ALL, IID_IDebugProgramProvider2, (void**)&pIDebugProgramProvider2);
if(st != S_OK) {
return st;
}
// Get the IDebugProgramNode2 instances running in this process
AD_PROCESS_ID processID;
processID.ProcessId.dwProcessId = GetCurrentProcessId();
processID.ProcessIdType = AD_PROCESS_ID_SYSTEM;
CONST_GUID_ARRAY engineFilter;
engineFilter.dwCount = 0;
PROVIDER_PROCESS_DATA processData;
st = pIDebugProgramProvider2->GetProviderProcessData(PFLAG_GET_PROGRAM_NODES|PFLAG_DEBUGGEE, 0, processID, engineFilter, &processData);
if(st != S_OK) {
ShowError(L"GPPD Failed", st);
pIDebugProgramProvider2->Release();
return st;
}
It would help to know what the error result was.
Possible problems I can think of:
If your getting permission denied, your most likely missing some requried Privilege in your ACL. New ones are sometimes not doceumented well, check the latest Platform SDK headers to see if any new ones that still out. It may be that under vista the Privilege is not assigned my default to your ACL any longer.
If your getting some sort of Not Found type error, then it may be 32bit / 64bit problem. Your debbugging API may only be available under 64bit COM on vista 64. The 32bit/64bit interoperation can be very confusing.
I'm not familiar with these interfaces, but unexpected failures in Vista may require being past a UAC prompt. Have you tried starting the debugger with admin privileges?