Recent

Author Topic: How do I give a Pointer to a other process  (Read 6587 times)

LazUser20

  • Newbie
  • Posts: 6
How do I give a Pointer to a other process
« on: May 13, 2021, 10:46:27 pm »
I have the following data structure.

Code: Pascal  [Select][+][-]
  1. type
  2.   PRasterImageInfo=^TRasterImageInfo;
  3.   TRasterImageInfo=packed record
  4.     nSize: DWord;
  5.     nItemID: LongInt;
  6.     hItem: THandle;
  7.     nFlags, nWidth, nHeight, nResSize: DWord;
  8.   end;
  9.  


It is filled with data:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.BitBtn1Click(Sender: TObject);
  2. begin
  3.   if OpenPictureDialog1.Execute
  4.     then
  5.       begin
  6.         Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
  7.  
  8.         RasterImageInfo.nSize:=sizeOf(RasterImageInfo);
  9.         RasterImageInfo.nItemID := 1;
  10.         RasterImageInfo.hItem := Image1.Picture.Bitmap.Handle;
  11.         RasterImageInfo.nFlags := $0007;
  12.         RasterImageInfo.nWidth  := Image1.Picture.Bitmap.Width;
  13.         RasterImageInfo.nHeight := Image1.Picture.Bitmap.Height;
  14.         RasterImageInfo.nResSize := GetFileSize(OpenPictureDialog1.FileName);
  15.  
  16.         ValueListEditor1.Values['nSize']:=IntToStr(RasterImageInfo.nSize);
  17.         ValueListEditor1.Values['nItemID']:=IntToStr(RasterImageInfo.nItemID);
  18.         ValueListEditor1.Values['nItem']:=IntToStr(RasterImageInfo.nItemID);
  19.         ValueListEditor1.Values['nFlags']:=IntToStr(RasterImageInfo.nFlags);
  20.         ValueListEditor1.Values['nWidth']:=IntToStr(RasterImageInfo.nWidth);
  21.         ValueListEditor1.Values['nHeight']:=IntToStr(RasterImageInfo.nHeight);
  22.         ValueListEditor1.Values['nResSize']:=IntToStr(RasterImageInfo.nResSize);
  23.         Label1.Caption := IntToStr(Image1.Picture.Bitmap.Width*Image1.Picture.Bitmap.Height*24);
  24.  
  25.       end;
  26. end;        
  27.  

How do I send the pointer to a other process (maybe as start parameter), to access the data of this structure in the other process?

The data structure is from here: http://www.x-ways.net/forensics/x-tensions/XWF_functions.html#E

At this time the second process read the pointer from the start arguments:

Code: C  [Select][+][-]
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <windows.h>
  3. #include <X-Tension.h>
  4. #include <stdlib.h> // EXIT_SUCCESS
  5. #include <string.h> // strcmp()
  6.  
  7. int main(int argc, struct RasterImageInfo* pRIInfo)
  8. {
  9.         for (int i = 0; i < argc; i++)
  10.         {
  11.                 // Ausgabe aller Parameter
  12.                 std::cout << i << " \"" << pRIInfo->nSize<< "\"" << std::endl;
  13.         std::cout << i << " \"" << pRIInfo->nItemID << "\"" << std::endl;
  14.         std::cout << i << " \"" << pRIInfo->hItem << "\"" << std::endl;
  15.         std::cout << i << " \"" << pRIInfo->nFlags << "\"" << std::endl;
  16.         std::cout << i << " \"" << pRIInfo->nWidth << "\"" << std::endl;
  17.         std::cout << i << " \"" << pRIInfo->nHeight << "\"" << std::endl;
  18.         std::cout << i << " \"" << pRIInfo->nResSize << "\"" << std::endl;
  19.         }
  20.  
  21.         std::cin.get();
  22.         return EXIT_SUCCESS;
  23. }
  24.  
  25.  

The pascal program is only for testing, if the C++-Tool read valid data, because I dont have access to a X-Ways.
« Last Edit: May 13, 2021, 10:49:01 pm by LazUser20 »

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: How do I give a Pointer to a other process
« Reply #1 on: May 14, 2021, 02:38:09 am »
Passing pointers is useless until a copy of the memory is passed, because Windows processes each have their own memory. There are several memory sharing mechanisms, but this must be explicitly implemented in both processes. Are you the creator of programs for both processes?

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: How do I give a Pointer to a other process
« Reply #2 on: May 14, 2021, 03:28:11 am »
How do I send the pointer to a other process (maybe as start parameter), to access the data of this structure in the other process?

You can't use pointers across process boundaries.  What you can do instead is allocate a named block of shared memory via CreateFileMapping() and MapViewOfFile() (see Sharing Files and Memory), and then each process can obtain its own pointer to the shared memory and read/write data in the block as needed.  You could pass the file mapping's shared name in a command-line parameter, if needed.

Note: you can't share an HBITMAP handle across processes, period.  So this approach will not work for sharing the TRasterImageInfo.hItem field.  You will have to save the TBitmap's pixel data according to MSDN's Bitmap Storage documentation.  For instance, by saving the TBitmap to a TMemoryStream and then copying the raw bytes from the stream to the shared memory.

For example:

Code: Pascal  [Select][+][-]
  1. type
  2.   PRasterImageInfo = ^TRasterImageInfo;
  3.   TRasterImageInfo = packed record
  4.     nSize: DWord;
  5.     nItemID: LongInt;
  6.     nFlags, nWidth, nHeight, nResSize: DWord;
  7.     nResBytes: array[0..0] of Byte;
  8.   end;
  9.      
  10. procedure TForm1.BitBtn1Click(Sender: TObject);
  11. var
  12.   MemStrm: TMemoryStream;
  13.   MemSize: DWORD;
  14.   hMapping: THandle;
  15.   RasterImageInfo: PRasterImageInfo;
  16. begin
  17.   if OpenPictureDialog1.Execute then
  18.   begin
  19.     Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
  20.      
  21.     MemStrm := TMemoryStream.Create;
  22.     try
  23.       Image1.Picture.Bitmap.SaveToStream(MemStrm);
  24.       MemSize := (SizeOf(TRasterImageInfo) - 1) + MemStrm.Size;
  25.  
  26.       hMapping := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, MemSize, 'RasterImageInfo');
  27.       if hMapping = 0 then RaiseLastOSError;
  28.       try
  29.         RasterImageInfo := MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, MemSize);
  30.         if RasterImageInfo = nil then RaiseLastOSError;
  31.         try
  32.           RasterImageInfo.nSize := MemSize;
  33.           RasterImageInfo.nItemID := 1;
  34.           RasterImageInfo.nFlags := $0007;
  35.           RasterImageInfo.nWidth  := Image1.Picture.Bitmap.Width;
  36.           RasterImageInfo.nHeight := Image1.Picture.Bitmap.Height;
  37.           RasterImageInfo.nResSize := Strm.Size;
  38.           Move(MemSStrm.Memory^, RasterImageInfo.nResBytes[0], Strm.Size);
  39.  
  40.           // run external program, wait for it to finish using RasterImageInfo ...
  41.  
  42.       finally
  43.         UnmapViewOfFile(RasterImageInfo);
  44.       end;
  45.     finally
  46.       CloseHandle(hMapping);
  47.     end;
  48.   finally
  49.     MemStrm.Free;
  50.   end;
  51. end;

Code: C  [Select][+][-]
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <windows.h>
  3. #include <X-Tension.h>
  4. #include <cstdlib> // EXIT_SUCCESS
  5. #include <cstring> // std::strcmp()
  6.  
  7. #pragma pack(push, 1) // <-- or your compiler's equivalent
  8. typedef struct TRasterImageInfo
  9. {
  10.     DWORD nSize;
  11.     LONG nItemID;
  12.     DWORD nFlags, nWidth, nHeight, nResSize;
  13.     BYTE nResBytes[1];
  14. } TRasterImageInfo, *PRasterImageInfo;
  15. #pragma pack(pop) // <-- or your compiler's equivalent
  16.      
  17. int main(int argc, char* argv[])
  18. {    
  19.     HANDLE hMapping = OpenFileMapping(FILE_MAP_READ, FALSE, TEXT("RasterImageInfo"));
  20.     if (hMapping == NULL)
  21.         return EXIT_FAILURE;
  22.  
  23.     PRasterImageInfo pRIInfo = (PRasterImageInfo) MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  24.     if (pRIInfo == NULL)
  25.     {
  26.         CloseHandle(hMapping);
  27.         return EXIT_FAILURE;
  28.     }
  29.  
  30.     // Ausgabe aller Parameter
  31.     std::cout << i << " \"" << pRIInfo->nSize << "\"" << std::endl;
  32.     std::cout << i << " \"" << pRIInfo->nItemID << "\"" << std::endl;
  33.     std::cout << i << " \"" << pRIInfo->nFlags << "\"" << std::endl;
  34.     std::cout << i << " \"" << pRIInfo->nWidth << "\"" << std::endl;
  35.     std::cout << i << " \"" << pRIInfo->nHeight << "\"" << std::endl;
  36.     std::cout << i << " \"" << pRIInfo->nResSize << "\"" << std::endl;
  37.     // use pRIInfo->nResBytes as needed...
  38.  
  39.     UnmapViewOfFile(pRIInfo);
  40.     CloseHandle(hMapping);
  41.  
  42.     std::cin.get();
  43.     return EXIT_SUCCESS;
  44. }
« Last Edit: May 14, 2021, 03:31:55 am by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

LazUser20

  • Newbie
  • Posts: 6
Re: How do I give a Pointer to a other process
« Reply #3 on: May 30, 2021, 02:21:42 pm »
OK. Thank you for your help.

How do I put the whole record at the process execute (or something similar) to get it as process parameter at the other programm?

Is ist possible just to get only a FilePointer and put this in a record instead of a handle to memory?
« Last Edit: May 30, 2021, 02:29:41 pm by LazUser20 »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: How do I give a Pointer to a other process
« Reply #4 on: May 30, 2021, 02:53:31 pm »
OK. Thank you for your help.

How do I put the whole record at the process execute (or something similar) to get it as process parameter at the other programm?

Use shared memory.

Quote
Is ist possible just to get only a FilePointer and put this in a record instead of a handle to memory?

In general, no. You can pass a filename around and then open that with appropriate locking discipline, but you might do better considering IPC using OS-specific or UDP datagrams.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: How do I give a Pointer to a other process
« Reply #5 on: May 30, 2021, 03:03:51 pm »
X-Ways expects your code to be in a DLL. Meaning your code is going to be in the "same" process.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: How do I give a Pointer to a other process
« Reply #6 on: May 31, 2021, 11:17:19 am »
How do I put the whole record at the process execute (or something similar) to get it as process parameter at the other programm?

Copy the record into shared memory, exactly like how I showed you. Did you even try it?

Is ist possible just to get only a FilePointer and put this in a record instead of a handle to memory?

No.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

LazUser20

  • Newbie
  • Posts: 6
Re: How do I give a Pointer to a other process
« Reply #7 on: June 09, 2021, 07:20:04 pm »
X-Ways expects your code to be in a DLL. Meaning your code is going to be in the "same" process.

Actual I don't have Xways so at this time it is not planed to build a X-tension. The project only should address the processing of the data and this maybe will be used later for building an xtension. 
So I plan to build a tool, which read an image file and create the data structure and give this to the c++ program.

ccrause

  • Hero Member
  • *****
  • Posts: 845
Re: How do I give a Pointer to a other process
« Reply #8 on: June 09, 2021, 09:36:16 pm »
X-Ways expects your code to be in a DLL. Meaning your code is going to be in the "same" process.

Actual I don't have Xways so at this time it is not planed to build a X-tension. The project only should address the processing of the data and this maybe will be used later for building an xtension. 
So I plan to build a tool, which read an image file and create the data structure and give this to the c++ program.
Do you have an example of calling this C++ program with a pointer to RasterImageInfo?  I only know the very basics of C/C++, but the main function of the C++ program you showed in the first post looks non-standard.  Is that a real working program?

LazUser20

  • Newbie
  • Posts: 6
Re: How do I give a Pointer to a other process
« Reply #9 on: June 13, 2021, 04:51:42 pm »

Copy the record into shared memory, exactly like how I showed you. Did you even try it?


Yes I tryed, but the compiler didn't compiled the Lazarus Part.

At "RasterImageInfo.nSize := MemSize;" there are errors:

Error: Illegal qualifier
Hint: may be pointer dereference is missing
Error: Illegal expression

I could fix it to this:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.BitBtn1Click(Sender: TObject);
  2.  
  3. var
  4.   MemStrm: TMemoryStream;
  5.   MemSize: DWORD;
  6.   hMapping: THandle;
  7.   RasterImageInfo: PRasterImageInfo;
  8.   Output: String;
  9. begin
  10.   if OpenPictureDialog1.Execute then
  11.   begin
  12.     Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
  13.  
  14.     MemStrm := TMemoryStream.Create;
  15.     try
  16.       Image1.Picture.Bitmap.SaveToStream(MemStrm);
  17.       MemSize := (SizeOf(TRasterImageInfo) - 1) + MemStrm.Size;
  18.  
  19.       hMapping := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, MemSize, 'RasterImageInfo');
  20.       if hMapping = 0 then RaiseLastOSError;
  21.       try
  22.         RasterImageInfo := MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, MemSize);
  23.         if RasterImageInfo = nil then RaiseLastOSError;
  24.         try
  25.           RasterImageInfo^.nSize := MemSize;
  26.           RasterImageInfo^.nItemID := 1;
  27.           RasterImageInfo^.nFlags := $0007;
  28.           RasterImageInfo^.nWidth  := Image1.Picture.Bitmap.Width;
  29.           RasterImageInfo^.nHeight := Image1.Picture.Bitmap.Height;
  30.           RasterImageInfo^.nResSize := MemStrm.Size;
  31.           Move(MemStrm.Memory^, RasterImageInfo^.nResBytes[0], MemStrm.Size);
  32.  
  33.           // run external program, wait for it to finish using RasterImageInfo ...
  34.  
  35.           RunCommand(toolpath, output);
  36.         finally
  37.         end;
  38.       finally
  39.         UnmapViewOfFile(RasterImageInfo);
  40.       end;
  41.     finally
  42.       CloseHandle(hMapping);
  43.       MemStrm.Free;
  44.     end;
  45.   end;
  46. end;      
  47.  
  48.  

Both tools are copiled now.

Is there a simple way to get the picture from the memory drawed at a screen or write it to a file?
So that I can see that it really works?

Update:

I was able to save the File with just this to lines:
Code: C  [Select][+][-]
  1.     #pragma warning(suppress : 4996)
  2.     FILE* file = fopen("memory.bmp", "wb");
  3.     fwrite(pRIInfo->nResBytes, 1, pRIInfo->nResSize, file);
  4.  

The size and the md5 hash are equal to the orignal file, if that was a normal bitmap image.
This is a good basis for further working.

Big Thanks to Remy Lebeau

« Last Edit: June 13, 2021, 06:16:55 pm by LazUser20 »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: How do I give a Pointer to a other process
« Reply #10 on: June 13, 2021, 09:03:20 pm »
Yes I tryed, but the compiler didn't compiled the Lazarus Part.

At "RasterImageInfo.nSize := MemSize;" there are errors:

Error: Illegal qualifier
Hint: may be pointer dereference is missing
Error: Illegal expression

I guess that means FreePascal does not support the same "extended pointer syntax" that Delphi does, which allows for omiting the caret (^) when dereferencing a pointer.

I could fix it to this:

That looks correct, yes.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: How do I give a Pointer to a other process
« Reply #11 on: June 13, 2021, 10:01:14 pm »

I guess that means FreePascal does not support the same "extended pointer syntax" that Delphi does, which allows for omiting the caret (^) when dereferencing a pointer.

It does for 20 years now. IF you actually set it to Delphi compatibility.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: How do I give a Pointer to a other process
« Reply #12 on: June 13, 2021, 10:31:37 pm »
or use:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}
  2. {$ModeSwitch autoderef}

dsiders

  • Hero Member
  • *****
  • Posts: 1052
Re: How do I give a Pointer to a other process
« Reply #13 on: June 13, 2021, 10:40:29 pm »
or use:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}
  2. {$ModeSwitch autoderef}

Aha! I've never noticed that one.
Thanks @engkin.
Preview Lazarus 3.99 documentation at: https://dsiders.gitlab.io/lazdocsnext

 

TinyPortal © 2005-2018