Jump to content

"memory cannot be 'read'" after DllCall().


ogloed
 Share

Recommended Posts

Again, I'm struggling with DllCall(). So I have this MS C++ 6.0 compiled DLL and a manual for it. There's a function:
 

Get information of disk arrays
Declaration:
VINT vr_get_array_info (VINT array_index, vr_array_info_t* pinfo);
Description:
Application can fetch the information of one specific disk array, which is located
by index of all disk arrays in current system.
Input parameters:
VINT array_index :
Index to all disk arrays in system, specify which disk array.
vr_array_info_t *pinfo :
14
Pointer to a vr_array_info_t data structure to get the information
Return value:
VR_SUCCESS :
Get the information successfully.
VR_ERR_NOT_INITED :
Raid lib hasn’t been initialized.
VR_ERR_INVALID_INDEX :
The input index is invalid.
VR_ERR_INVALID_PARAM :
Input parameter is invalid: the pointer is NULL.

Here's what DLL Export Viewer says:
 

Function Name     : int __cdecl vr_get_array_info(int,struct _vr_array_info *)


Here's what is this _vr_array_info:
 

typedef struct _vr_array_info {
        VWORD status;  // current status of disk array
                        
        VBYTE raidType;// same as Disk_Array.raidType, but value 0xFF means
                        // a stand-alone disk. When it's a stand-alone disk,
                        // only arDevices[0] and diskNum has meaning, and diskNum should
                        // always be 1 .

        VBYTE diskNum;// count of valid arDevices[] members. 

        // Note: disk array maybe incomplete, i.e. , some disk in the array maybe missing, 
        //     corresponding device ptr arDevices[i]->pRealDevice should be NULL.
        
        VDWORD capacityLow;// (Unit: sector)
        VDWORD capacityHigh;// (Unit: sector)

        // following 8 bytes define the real-capcity (in sector) of every disk in array
        VDWORD realCapacityLow;        // (Unit: sector)
        VDWORD realCapacityHigh;       // (Unit: sector)


        VDWORD stripeSize; // valid when raid is raid0, raid5 or raid01, in Kbytes
        VDWORD blockSize; // valid when raid is RAID5, in Kbytes

        VBOOL  bNeedMigration; // the raid need migration
                               // only valid when raid0/raid5/matrixRaid
        VBOOL  bNeedInit;      // the raid need initialization, only valid for RAID5
        VBOOL  bOptimized;     // only for RAID5, this RAID5 access was optimized

         VBYTE systemDisk;     /* does the devices within this disk array 
                                  contain system files of current running OS ? 
                                   the probably value are:
                                   VR_DEVICE_NOT_SYS_DISK
                                   VR_DEVICE_MAYBE_SYS_DISK
                                   VR_DEVICE_SYS_DISK
                                 they are defined in this file */

        VWORD raid_index;// only raid index, no meaning with stand-alone disk
        VINT  index; // all device index, including all raid and stand-alone disk
} vr_array_info_t;



Here's my code (function names are actually decorated, so):
 

Local $pTest

$hDLL = DllOpen(@ScriptDir & "\drvInterface.dll")

;~ VINT vr_init (void);
ConsoleWrite("vr_init..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_init@@YAHXZ")

;~ VINT vr_get_controller_num (VINT *pnumber);
ConsoleWrite("vr_get_controller_num..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_controller_num@@YAHPAH@Z", "int*", "$pTest")
$iControllerNumber = $sTest[1]
ConsoleWrite("$iControllerNumber = " & $iControllerNumber & @CRLF)

;~ VINT vr_get_device_num (VINT *pnumber);
ConsoleWrite("vr_get_device_num..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_device_num@@YAHPAH@Z", "int*", "$pTest")
$iDeviceNumber = $sTest[1]
ConsoleWrite("$iDeviceNumber = " & $iDeviceNumber & @CRLF)

;~ VINT vr_get_array_num (VINT only_raid, VINT *pnumber);
ConsoleWrite("vr_get_array_num..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_array_num@@YAHHPAH@Z", "int", 0, "int*", "$pTest")
$iArrayNumber = $sTest[2]
ConsoleWrite("$iArrayNumber = " & $iArrayNumber & @CRLF)

$vr_array_info = DllStructCreate("ushort status;byte raidType;byte diskNum;dword capacityLow;dword capacityHigh;dword stripeSize;dword blockSize;boolean bNeedMigration;boolean bNeedInit;boolean bOptimized;byte systemDisk;byte raid_index;int index")
;~ VINT vr_get_array_info (VINT array_index, vr_array_info_t* pinfo);
ConsoleWrite("vr_get_array_info..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_array_info@@YAHHPAU_vr_array_info@@@Z", "int", 0, "struct*", $vr_array_info)

;~ void vr_exit (void);
ConsoleWrite("vr_exit..." & @CRLF)
$sTest = DllCall($hDLL, "none", "?vr_exit@@YAXXZ")

DllClose($hDLL)

Exit

Everything works fine up to vr_get_array_info part. This is where I get a "memory cannot be 'read'" Windows error ("Instruction at 0x7c93a514 referenced memory at 0x00000000").

What am I doing wrong? Please help.

drvInterface.dll

ProgGuide.pdf

Link to comment
Share on other sites

1 hour ago, Danp2 said:

Looks like you got the structure definition wrong --

VDWORD realCapacityLow;        // (Unit: sector)
        VDWORD realCapacityHigh;       // (Unit: sector)

is missing

byte raid_index;

also appears to be wrong.

Well, thank you and "thank you" to authors of the DLL manual. For there's a little bit different picture:

 

vr_array_info_t
typedef struct _vr_array_info {
VWORD status;
VBYTE raidType; // value 0xFF means
// a stand-alone disk. When it's a stand-alone disk,
// only diskNum has meaning, and diskNum should
// always be 1 .
VBYTE diskNum;// count of valid disk members.
VDWORD capacityLow;// (Unit: sector)
VDWORD capacityHigh;// (Unit: sector)
VDWORD stripeSize; // valid when raid is raid0 or raid01, in Kbytes
VDWORD blockSize; // valid when raid is RAID5, in Kbytes
VBOOL bNeedMigration; // the raid need migration
// only valid when raid0/raid5/matrixRaid
VBOOL bNeedInit; // the raid need initialization, only valid for RAID5
VBOOL bOptimized; // only for RAID5, this RAID5 access was optimized
VBYTE systemDisk; /* does the devices within this disk array contain system
files of current running OS ? The probably value are:
VR_DEVICE_NOT_SYS_DISK
VR_DEVICE_MAYBE_SYS_DISK
VR_DEVICE_SYS_DISK
they are defined in this file */
VBYTE raid_index;// only raid index, no meaning with stand-alone disk
VINT index; // all device index, including all raid and stand-alone disk
} vr_array_info_t;

OK, so here's what I changed:
 

$vr_array_info = DllStructCreate("ushort status;byte raidType;byte diskNum;dword capacityLow;dword capacityHigh;dword realCapacityLow;dword realCapacityHigh;dword stripeSize;dword blockSize;boolean bNeedMigration;boolean bNeedInit;boolean bOptimized;byte systemDisk;ushort raid_index;int index")

Getting the same "memory cannot be 'read'", but now with "referenced memory at 0x00000004" and "referenced memory at 0x00000000"  showing randomly.

Link to comment
Share on other sites

Working piece of code:

 

$vr_array_info = DllStructCreate("ushort status;ubyte raidType;ubyte diskNum;ulong capacityLow;ulong capacityHigh;ulong realCapacityLow;ulong realCapacityHigh;ulong stripeSize;ulong blockSize;int bNeedMigration;int bNeedInit;int bOptimized;ubyte systemDisk;ushort raid_index;int index")
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_array_info@@YAHHPAU_vr_array_info@@@Z", "int", 0, "struct*", DllStructGetPtr($vr_array_info))

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...