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.
stephanerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

twardCommented:
What is the function you are using to put it in memory?
0
stephanerAuthor Commented:
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)
....
         
                           
0
twardCommented:
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.

0
The Ultimate Tool Kit for Technolgy Solution Provi

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy for valuable how-to assets including sample agreements, checklists, flowcharts, and more!

twardCommented:
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.
0
stephanerAuthor Commented:
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?

0
stephanerAuthor Commented:



0
y96andhaCommented:
Use the RtlMoveMemory function.

Example to copy 400 bytes of data starting with position 20 in the memory chunk, and to put these bytes back at position 1024 in the memory chunk:

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

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

Dim data as String
data=String(400,0)
CopyMemory1 data, mlng_MemoryAddress+20, 400

CopyMemory2 mlng_MemoryAddress+1024, data, 400



Please comment if you have any questions.

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
stephanerAuthor Commented:
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?
0
y96andhaCommented:
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.

0
stephanerAuthor Commented:
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"
0
y96andhaCommented:
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.


0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.