Announcement

Collapse
No announcement yet.

Can you dimension a UDT at a specific address?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can you dimension a UDT at a specific address?

    I am trying to dimension a UDT at a address passed from another program. I can't get Program2 to compile.

    Code:
    #COMPILE EXE "Program1.Exe"
    #DIM ALL
    
    TYPE Record
      Field1 AS STRING * 40
      Field2 AS STRING * 40
      Field3 AS STRING * 40
    END TYPE
    
    FUNCTION PBMAIN () AS LONG
      LOCAL R AS Record
    
      SHELL "Program2.Exe" & " " & DEC$(VARPTR(R))
    
      ? R.Field1 & $CRLF & _
        R.Field2 & $CRLF & _
        R.Field3
    END FUNCTION
    Code:
    #COMPILE EXE "Program2.Exe"
    #DIM ALL
    
    TYPE Record
      Field1 AS STRING * 40
      Field2 AS STRING * 40
      Field3 AS STRING * 40
    END TYPE
    
    FUNCTION PBMAIN () AS LONG
      DIM R AS Record AT VAL(COMMAND$) '<--- this line will not compile
    
      R.Field1 = "Field1"
      R.Field2 = "Field2"
      R.Field3 = "Field3"
    END FUNCTION

  • #2
    I got this to compile but it is showing blanks.
    Code:
    #COMPILE EXE "Program2.Exe"
    #DIM ALL
    
    TYPE Record
      Field1 AS STRING * 40
      Field2 AS STRING * 40
      Field3 AS STRING * 40
    END TYPE
    
    FUNCTION PBMAIN () AS LONG
      LOCAL R AS Record
    
      R.Field1 = "Field1"
      R.Field2 = "Field2"
      R.Field3 = "Field3"
    
      POKE$ VAL(COMMAND$), PEEK$(VARPTR(R), SIZEOF(Record))
    END FUNCTION

    Comment


    • #3
      DIM AT only works with arrays.
      Try DIMing an array of 1 item at that address.

      Comment


      • #4
        Use DIM AT with a one-element array, LIKE DIM myUDT(0) AT...

        "Not my circus, not my monkeys."

        Comment


        • #5
          Snap!

          Comment


          • #6
            Missed it by that much.
            "Not my circus, not my monkeys."

            Comment


            • #7
              Actually I don't think you can alter memory in another programs memory space. Probably have to try another approach.

              Comment


              • #8
                Hi Frank,
                Id prefer to use a pointer instead of DIM AT.
                Like: LOCAL pRecord AS RecordType POINTER

                Now, you can not write to the memory of another process directly, you will have to open the other process via OpenProcess() and use WriteProcessMemory().

                Code:
                #COMPILE EXE "Program1.Exe" '#Win#
                #DIM ALL
                #INCLUDE "Win32Api.inc"
                
                TYPE RecordType
                  Field1 AS STRING * 40
                  Field2 AS STRING * 40
                  Field3 AS STRING * 40
                END TYPE
                '_____________________________________________________________________________
                
                FUNCTION PBMAIN () AS LONG
                 LOCAL Record AS RecordType
                
                 SHELL "Program2.exe" & " " & HEX$(VARPTR(Record), 8) & " " & HEX$(GetCurrentProcessId(), 8)
                
                 ? Record.Field1 & $CRLF & _
                   Record.Field2 & $CRLF & _
                   Record.Field3, %MB_OK OR %MB_TOPMOST, "Program1"
                
                END FUNCTION
                '_____________________________________________________________________________
                '
                Code:
                #COMPILE EXE "Program2.Exe" '#Win#
                #DIM ALL
                #INCLUDE "Win32Api.inc"
                
                TYPE RecordType
                 Field1 AS STRING * 40
                 Field2 AS STRING * 40
                 Field3 AS STRING * 40
                END TYPE
                '_____________________________________________________________________________
                
                FUNCTION PBMAIN () AS LONG
                 LOCAL pRecord         AS RecordType POINTER
                 LOCAL Record          AS RecordType
                 LOCAL pid             AS DWORD
                 LOCAL hProcess        AS DWORD
                 LOCAL dwNumberOfBytes AS DWORD
                
                 pRecord = VAL("&h" & COMMAND$)
                 pid     = VAL("&h" & PARSE$(COMMAND$, $SPC, 2))
                
                 'Open pid process of Program1
                 hProcess = OpenProcess(%PROCESS_VM_OPERATION OR %PROCESS_VM_READ OR %PROCESS_VM_WRITE OR %PROCESS_QUERY_INFORMATION, %FALSE, pid)
                 IF hProcess THEN 'If hProcess <> 0 then we succeeded
                
                   Record.Field1 = "Field1"
                   Record.Field2 = "Field2"
                   Record.Field3 = "Field3"
                
                   'Write in the other program memory
                   WriteProcessMemory(hProcess, BYVAL pRecord, BYVAL VARPTR(Record), BYVAL SIZEOF(RecordType), dwNumberOfBytes)
                
                 END IF
                
                END FUNCTION
                '_____________________________________________________________________________
                '

                Comment


                • #9
                  You did it again Pierre... You threw me into the deep end of Windows and now I have to go read. lol. It looks like exactly what I need, just have to learn something new... again!

                  While you were working on this I was playing with GLOBALMEM and having the same results. I assume that GLOBALMEM is not available to another process just as local variables?

                  Thanks Pierre,
                  Frank

                  PS for anyone else trying these programs, my antivirus program absolutely hated program2. Had to disable it to get this to run.

                  Comment


                  • #10
                    About GlobalMem, this may be interesting... Global and Local Functions
                    Depending of the context you are working in, an Interprocess Communications mechanisms might be better. There are many demos on this forum...

                    Comment


                    • #11
                      Very interesting read Pierre. Thank you. The programs I am developing would work well with the interprocess method. I am used to the old terminology where Global meant everywhere in the computer. It seems like that Global is gone.

                      Thanks again for all your help.
                      Frank

                      Comment


                      • #12
                        Hey Pierre! Made a version 2.0 of your UDT passing program to go both ways. I needed a send as well as a receive. Thanks again.

                        Program 1
                        Code:
                        #COMPILE EXE "Program1.Exe" '#Win#
                        #DIM ALL
                        #INCLUDE "Win32Api.inc"
                        
                        TYPE RecordType
                          Field1 AS STRING * 40
                          Field2 AS STRING * 40
                          Field3 AS STRING * 40
                        END TYPE
                        '_____________________________________________________________________________
                        
                        FUNCTION PBMAIN () AS LONG
                          LOCAL pRecord AS RecordType POINTER
                          LOCAL pid     AS DWORD
                          LOCAL Record  AS RecordType
                        
                        	Record.Field1 = "Field1 from Program1"
                        	Record.Field2 = "Field2 from Program1"
                        	Record.Field3 = "Field3 from Program1"
                        
                        	pRecord = varptr(Record): pid = GetCurrentProcessID()	
                          ? "pRecord=" & hex$(pRecord, 8) & ", pid=" & hex$(pid, 8), %MB_OK OR %MB_TOPMOST, "Sent from Program1"
                          SHELL "Program2.exe" & " " & HEX$(pRecord, 8) & " " & HEX$(pid, 8)
                        
                          ? "Field1=" & Record.Field1 & $CRLF & _
                            "Field2=" & Record.Field2 & $CRLF & _
                            "Field3=" & Record.Field3, %MB_OK OR %MB_TOPMOST, "Received from Program2"
                        END FUNCTION
                        '_____________________________________________________________________________
                        '
                        Program 2
                        Code:
                        #COMPILE EXE "Program2.Exe" '#Win#
                        #DIM ALL
                        #INCLUDE "Win32Api.inc"
                        
                        TYPE RecordType
                          Field1 AS STRING * 40
                          Field2 AS STRING * 40
                          Field3 AS STRING * 40
                        END TYPE
                        '_____________________________________________________________________________
                        
                        FUNCTION PBMAIN () AS LONG
                          LOCAL pRecord         AS RecordType POINTER
                          LOCAL pid             AS DWORD
                          LOCAL Record          AS RecordType
                          LOCAL hProcess        AS DWORD
                          LOCAL dwNumberOfBytes AS DWORD
                        
                          pRecord = VAL("&h" & COMMAND$): pid = VAL("&h" & PARSE$(COMMAND$, $SPC, 2))
                          ? "pRecord=" & hex$(pRecord) & ", pid=" & hex$(pid), %MB_OK OR %MB_TOPMOST, "Received from Program1"
                        
                          'Open pid process of Program1
                          hProcess = OpenProcess(%PROCESS_VM_OPERATION OR %PROCESS_VM_READ OR %PROCESS_VM_WRITE, %FALSE, pid)
                          IF hProcess THEN 'If hProcess <> 0 then we succeeded
                            ReadProcessMemory(hProcess, pRecord, byval VARPTR(Record), SIZEOF(RecordType), dwNumberOfBytes)
                        	  ? "Field1=" & Record.Field1 & $CRLF & _
                          	  "Field2=" & Record.Field2 & $CRLF & _
                            	"Field3=" & Record.Field3 & $CRLF & _
                        			" Bytes=" & DEC$(dwNumberOfBytes), %MB_OK OR %MB_TOPMOST, "Received from Program1"
                        
                            Record.Field1 = "Field1 from Program 2"
                            Record.Field2 = "Field2 from Program 2"
                            Record.Field3 = "Field3 from Program 2"
                        
                            'Write in the other program memory
                            WriteProcessMemory(hProcess, pRecord, byval VARPTR(Record), SIZEOF(RecordType), dwNumberOfBytes)
                            CloseHandle hProcess
                          END IF
                        END FUNCTION
                        '_____________________________________________________________________________
                        '
                        Of course, comments welcome.
                        Frank

                        Comment


                        • #13
                          Good work Frank!

                          Comment

                          Working...
                          X