Link to home
Start Free TrialLog in
Avatar of stephaner
stephaner

asked on

API for reading memory

I am writing a program that that uses API calls to store a large file in a Allocated Chunk of memory.  How can I retrieve data from this chunk and store it back in to an array.
Avatar of tward
tward

What is the function you are using to put it in memory?
Avatar of stephaner

ASKER

Here is a copy of the subroutine.  This subroutine is part of a class.


Public Sub Load()
  Dim FileSize As Long      'Used to store the file size
  Dim hFile As Long         'Used as a handle to the File
  Dim retval As Long        'Used as generic return value
  Dim lpBytesread As Long   'Used by Api(ReadFile)
 

   
  'Get the size of the file
    FileSize = FileLen(FileName)

  'Verify that the file is not zero length.
    If FileSize > 0 Then

      'Allocate a block of memory equal to the size of the input file.
        mlng_HandleMemory = GlobalAlloc(GMEM_ZEROINIT, FileSize)
       

        'Verify that the allocation succeded
          If mlng_HandleMemory <> 0 Then

            'Lock newly allocated memory
              mlng_MemoryAddress = GlobalLock(mlng_HandleMemory)
         
             
            'Open the File
              hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, ByVal 0&)
             
                       
            'Read File into Memory
              retval = lread(hFile, ByVal mlng_MemoryAddress, FileSize)
         
                           
            'Close the File
              retval = CloseHandle(hFile)
....
         
                           
Try the following API call:

Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

Here is an explanation of the function:

The ReadProcessMemory function reads memory in a specified process. The entire area to be read must be accessible, or the operation fails.
BOOL ReadProcessMemory(
    HANDLE hProcess,      // handle of the process whose memory is read  
    LPCVOID lpBaseAddress,      // address to start reading
    LPVOID lpBuffer,      // address of buffer to place read data
    DWORD nSize,      // number of bytes to read
    LPDWORD lpNumberOfBytesRead       // address of number of bytes read
   );      
 
Parameters
hProcess
Identifies an open handle of a process whose memory is read. The handle must have PROCESS_VM_READ access to the process.
lpBaseAddress
Points to the base address in the specified process to be read. Before any data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for read access. If this is the case, the function proceeds; otherwise, the function fails.
lpBuffer
Points to a buffer that receives the contents from the address space of the specified process.
nSize
Specifies the requested number of bytes to read from the specified process.
lpNumberOfBytesRead
Points to the actual number of bytes transferred into the specified buffer. If lpNumberOfBytesRead is NULL, the parameter is ignored.
 
Return Values
If the function succeeds, the return value is TRUE.
If the function fails, the return value is FALSE. To get extended error information, call GetLastError.
The function fails if the requested read operation crosses into an area of the process that is inaccessible.
Remarks
ReadProcessMemory copies the data in the specified address range from the address space of the specified process into the specified buffer of the current process. Any process that has a handle with PROCESS_VM_READ access can call the function. The process whose address space is read is typically, but not necessarily, being debugged.
The entire area to be read must be accessible. If it is not, the function fails as noted previously.

Also note that after you are done with the memory you need to do a GlobalUnlock which I don't see in your above code.
I am not sure how to put my class together using this function.  Maybe a little background on what I am trying to achieve would help.
My class is used for bitmap manipulation and display.  The idea is that I would have a load function which copies the whole file into memory.  Then I could implement functions to read and dissect the data such as getting the BitmapHeadears, Bitmapdata, ShowBitmap, SaveBitmap.  It seems that since I will be accessing this data often, it would be faster to do it this way than simply reading the data from the file every time I need it.

It is for this reason that there is no call to unlock the memory as this would be done in the Save routine.

Also I have implemented this save routine, although it does copy data back into a file (using lwrite),  the data does not correspond with the original copy of it.

Is it that my approach to the problem is inadequate, or unrealizable?




ASKER CERTIFIED SOLUTION
Avatar of y96andha
y96andha

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I could not find the above declrations in the API file.  Do you no why?  Also right now I am using "agCopyData" to perform this task. However, this does not allow me to read in anything other than a string.  I would like to be able to read in directly other data types such as Intgers and Longs.  Would your functions allow for this?
Yes, they would. All you have to do is to make sure that the declaration passes pointers as the first two arguments and a length as the last. To read a Long, you would make a declaration like this:

Declare Sub MoveMemory3 Lib "kernel32" Alias "RtlMoveMemory" (dest as Long, Byval src as Long, Byval bytes as Long)

Dim data as Long
MoveMemory3 data, mlng_MemoryAddress+47, Len(data)


Notice that there is no ByVal on the first argument, which makes  VB take its address and pass it to the DLL function.

I do not know why the declaration is not in the API file. Maybe because VB isn't made for using pointers. Do you know if there is any instruction in VB to get the address of a certain variable? Anyway, I got the declaration from my C++ compiler, so it should work.

I cannot find a declaration for agCopyData either.

Ok, I was able to make it work for the following types: Byte, String, Integer, Long.  However I still need to know what the declare would be for an array of bytes? a UDT?  Also I had to modify each declare depending on the type.  Is there a way to have only one declare that fits all?

"agCopydata" is part of a lib called "ApiGid32.dll"
This lib contans the functions you mentioned such as:
agGetAddressForObject, gGetAddressForInteger, agGetAddressForLPSTR
and other usefull functions.  For more inforrmation on this lib:
"www.desare.com"
I do not know for an array of bytes. I have a student version of VB, which means I do not have a manual, just a CD. I think that you should pass the first byte. UDT= User Defined Type? In that case, it will work just like Byte, Integer, Long and so on.

To make a declare fit all, you should use

Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (dest as Any, src as Any, Byval bytes as Long)

This should enable you to specify whatever type you'd like. It could be that you still need need to specify the pointer address, that is, the mlng_MemoryAddress part as "ByVal xxx as Long".

On the other hand, if you can get the address for any data type, then you can use

Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal dest as Long, ByVal src as Long, Byval bytes as Long)

and just pass in the addresses.