2

In my C# code I am trying to use C++ functions: CM_Locate_DevNodeW and CM_Open_DevNode_Key (using pinvoke). My code seems something like this:

String deviceId = "PCI\\VEN_8086&DEV_591B&SUBSYS_22128086&REV_01\\3&11583659&0&10";
int devInst = 0;
cmStatus = CM_Locate_DevNodeW(&devInst, deviceId, CM_LOCATE_DEVNODE_NORMAL);
if (cmStatus == CR_SUCCESS)
{
    UIntPtr pHKey = new UIntPtr();
    cmStatus = CM_Open_DevNode_Key(devInst, KEY_ALL_ACCESS, 0, RegDisposition_OpenExisting, pHKey, CM_REGISTRY_SOFTWARE);
    if (cmStatus == CR_SUCCESS)
    {
        //but here cmStatus=3 (Invalid Pointer)
    }
}

After calling to CM_Locate_DevNodeW, the devInst becomes 1, and the cmStatus is 0 = CR_SUCCESS. But the call to CM_Open_DevNode_Key fails. I don't know if CM_Locate_DevNodeW returns CR_SUCCESS but puts incorrect data within devInst? ('1' does not seems like real device instance handle...)

Or maybe the call to CM_Open_DevNode_Key is wrong?

I declared the functions like this:

[DllImport("cfgmgr32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern unsafe int CM_Locate_DevNodeW(
    int* pdnDevInst,  
    string pDeviceID, 
    ulong ulFlags);

[DllImport("cfgmgr32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern unsafe int CM_Open_DevNode_Key(
     int dnDevNode,
     int samDesired,
     int ulHardwareProfile,
     int Disposition,
     IntPtr phkDevice,
     int ulFlags);

Any help would be appreciated!

1
  • CM_Locate_DevNodeW isn't a C++ function. It's a C function provided by the Windows API. Commented Feb 6, 2019 at 16:13

1 Answer 1

1

I fiddled around with your code and this is what I've got so far. After reading some docs I found out that phkDevice parameter of CM_Open_DevNode_Key function was likely an out parameter so I updated function signature

[DllImport("cfgmgr32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern unsafe int CM_Open_DevNode_Key(
    int dnDevNode,
    int samDesired,
    int ulHardwareProfile,
    int Disposition,
    out IntPtr phkDevice, //added out keyword
    int ulFlags);

And I tried to run the following code

IntPtr pHKey;

string deviceId = @"my keyboard pci id";
int devInst = 0;
int cmStatus = CM_Locate_DevNodeW(&devInst, deviceId, CM_LOCATE_DEVNODE_NORMAL);
if (cmStatus == CR_SUCCESS)
{
    int opencmStatus = CM_Open_DevNode_Key(devInst, KEY_ALL_ACCESS, 0, RegDisposition_OpenExisting, out pHKey, CM_REGISTRY_SOFTWARE);
    if (opencmStatus == CR_SUCCESS)
    {
        // 
    }
}

I got opencmStatus 51 which corresponds to CR_ACCESS_DENIED. Then I thought "Hmm, don't I just requesting to much access? Let's try only read access options" So I replaced KEY_ALL_ACCESS with 1 (KEY_QUERY_VALUE) and ran the following code

IntPtr pHKey;

string deviceId = @"my keyboard pci id";
int devInst = 0;
int cmStatus = CM_Locate_DevNodeW(&devInst, deviceId, CM_LOCATE_DEVNODE_NORMAL);
if (cmStatus == CR_SUCCESS)
{
    int opencmStatus = CM_Open_DevNode_Key(devInst, 1, 0, RegDisposition_OpenExisting, out pHKey, CM_REGISTRY_SOFTWARE);
    if (opencmStatus == CR_SUCCESS)
    {
        //
    }
}

It worked as expected. Finally, this version gave me opencmStatus equals to 0.

I did all tests against my keyboard PCI identifier, dont know if it matters.

Sign up to request clarification or add additional context in comments.

1 Comment

Adding the out keyword was enough for solving my issue. I didn't get CR_ACCESS_DENIED even when using KEY_ALL_ACCESS, maybe this is because my app is running with Administrator privilege. Thanks for your quick and efficient support!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.