Modifications needed to use windows.i on 64-bit

Posted by jquerijero on 11-Mar-2020 20:24

Has anyone tried using the Win32 related files (windows.p, windows.i from Jurjen) on 64-bit environment?

Posted by Stefan Drissen on 13-Mar-2020 11:57

Putting the external data types in preprocessors cleans that up quite a bit and also makes it easier to compare to the API documenation:

/*
   [name]         CreateProcess
   [description]  Creates a new process and its primary thread.

   msdn.microsoft.com/.../ms682425.aspx
*/
PROCEDURE CreateProcessA EXTERNAL {&KERNEL32.DLL}:
   DEFINE INPUT         PARAMETER lpApplicationName      AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpCommandline          AS CHARACTER   NO-UNDO.
   DEFINE INPUT         PARAMETER lpProcessAttributes    AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpThreadAttributes     AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER bInheritHandles        AS {&BOOL}     NO-UNDO.
   DEFINE INPUT         PARAMETER dwCreationFlags        AS {&DWORD}    NO-UNDO.
   DEFINE INPUT         PARAMETER lpEnvironment          AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpCurrentDirectory     AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpStartupInfo          AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpProcessInformation   AS {&POINTER}  NO-UNDO.
   DEFINE       RETURN  PARAMETER bResult                AS {&BOOL}     NO-UNDO.

END PROCEDURE.

Posted by Jeff Ledbetter on 13-Mar-2020 11:48

We don't use the "Jurjen Files", but this is the type of thing that you need to do:

PROCEDURE CreateProcessA EXTERNAL "kernel32.dll":

  &IF PROVERSION LT "11.3" &THEN
    DEFINE INPUT  PARAMETER lpApplicationName    AS LONG.
    DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
    DEFINE INPUT  PARAMETER lpProcessAttributes  AS LONG.
    DEFINE INPUT  PARAMETER lpThreadAttributes   AS LONG.
    DEFINE INPUT  PARAMETER bInheritHandles      AS LONG.
    DEFINE INPUT  PARAMETER dCreationFlags       AS LONG.
    DEFINE INPUT  PARAMETER lpEnvironment        AS LONG.
    DEFINE INPUT  PARAMETER lpCurrentDirectory   AS LONG.
    DEFINE INPUT  PARAMETER lpStartupInfo        AS LONG.
    DEFINE INPUT  PARAMETER lpProcessInformation AS LONG. 
    DEFINE RETURN PARAMETER bResult              AS LONG. 
  &ELSE
    &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
      DEFINE INPUT  PARAMETER lpApplicationName    AS INT64.
      DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
      DEFINE INPUT  PARAMETER lpProcessAttributes  AS INT64.
      DEFINE INPUT  PARAMETER lpThreadAttributes   AS INT64.
      DEFINE INPUT  PARAMETER bInheritHandles      AS INT64.
      DEFINE INPUT  PARAMETER dCreationFlags       AS INT64.
      DEFINE INPUT  PARAMETER lpEnvironment        AS INT64.
      DEFINE INPUT  PARAMETER lpCurrentDirectory   AS INT64.
      DEFINE INPUT  PARAMETER lpStartupInfo        AS INT64.
      DEFINE INPUT  PARAMETER lpProcessInformation AS INT64. 
      DEFINE RETURN PARAMETER bResult              AS INT64. 
    &ELSE
      DEFINE INPUT  PARAMETER lpApplicationName    AS LONG.
      DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
      DEFINE INPUT  PARAMETER lpProcessAttributes  AS LONG.
      DEFINE INPUT  PARAMETER lpThreadAttributes   AS LONG.
      DEFINE INPUT  PARAMETER bInheritHandles      AS LONG.
      DEFINE INPUT  PARAMETER dCreationFlags       AS LONG.
      DEFINE INPUT  PARAMETER lpEnvironment        AS LONG.
      DEFINE INPUT  PARAMETER lpCurrentDirectory   AS LONG.
      DEFINE INPUT  PARAMETER lpStartupInfo        AS LONG.
      DEFINE INPUT  PARAMETER lpProcessInformation AS LONG. 
      DEFINE RETURN PARAMETER bResult              AS LONG. 
    &ENDIF
  &ENDIF
  
END PROCEDURE.

All Replies

Posted by Stefan Drissen on 11-Mar-2020 22:33

The Jurjen files can be found on oehive.org.

You will need to adjust anything that is using pointers, longs or memory structures.

These days the API is no longer hiding in some SDK on a CD but is completely available on docs.microsoft.com.

Before using this - I would first look at using .Net classes.

Posted by Jurjen Dijkstra on 13-Mar-2020 08:28

hehehe "The Jurjen files", I like that, it's like the title of a Ludlum book :-D  Thanks Stefan.

Personally I have only used it with Prowin32.exe, we could never upgrade to the 64 bit Progress GUI because we invested deep in DLL in OCX.

And in the Appserver partition we don't use any api's at all because we assume it must run on linux.

In other words, I have never tried, and I don't think that the files that I have published looong ago are 64-bit ready.

Posted by Jeff Ledbetter on 13-Mar-2020 11:48

We don't use the "Jurjen Files", but this is the type of thing that you need to do:

PROCEDURE CreateProcessA EXTERNAL "kernel32.dll":

  &IF PROVERSION LT "11.3" &THEN
    DEFINE INPUT  PARAMETER lpApplicationName    AS LONG.
    DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
    DEFINE INPUT  PARAMETER lpProcessAttributes  AS LONG.
    DEFINE INPUT  PARAMETER lpThreadAttributes   AS LONG.
    DEFINE INPUT  PARAMETER bInheritHandles      AS LONG.
    DEFINE INPUT  PARAMETER dCreationFlags       AS LONG.
    DEFINE INPUT  PARAMETER lpEnvironment        AS LONG.
    DEFINE INPUT  PARAMETER lpCurrentDirectory   AS LONG.
    DEFINE INPUT  PARAMETER lpStartupInfo        AS LONG.
    DEFINE INPUT  PARAMETER lpProcessInformation AS LONG. 
    DEFINE RETURN PARAMETER bResult              AS LONG. 
  &ELSE
    &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
      DEFINE INPUT  PARAMETER lpApplicationName    AS INT64.
      DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
      DEFINE INPUT  PARAMETER lpProcessAttributes  AS INT64.
      DEFINE INPUT  PARAMETER lpThreadAttributes   AS INT64.
      DEFINE INPUT  PARAMETER bInheritHandles      AS INT64.
      DEFINE INPUT  PARAMETER dCreationFlags       AS INT64.
      DEFINE INPUT  PARAMETER lpEnvironment        AS INT64.
      DEFINE INPUT  PARAMETER lpCurrentDirectory   AS INT64.
      DEFINE INPUT  PARAMETER lpStartupInfo        AS INT64.
      DEFINE INPUT  PARAMETER lpProcessInformation AS INT64. 
      DEFINE RETURN PARAMETER bResult              AS INT64. 
    &ELSE
      DEFINE INPUT  PARAMETER lpApplicationName    AS LONG.
      DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
      DEFINE INPUT  PARAMETER lpProcessAttributes  AS LONG.
      DEFINE INPUT  PARAMETER lpThreadAttributes   AS LONG.
      DEFINE INPUT  PARAMETER bInheritHandles      AS LONG.
      DEFINE INPUT  PARAMETER dCreationFlags       AS LONG.
      DEFINE INPUT  PARAMETER lpEnvironment        AS LONG.
      DEFINE INPUT  PARAMETER lpCurrentDirectory   AS LONG.
      DEFINE INPUT  PARAMETER lpStartupInfo        AS LONG.
      DEFINE INPUT  PARAMETER lpProcessInformation AS LONG. 
      DEFINE RETURN PARAMETER bResult              AS LONG. 
    &ENDIF
  &ENDIF
  
END PROCEDURE.

Posted by Stefan Drissen on 13-Mar-2020 11:57

Putting the external data types in preprocessors cleans that up quite a bit and also makes it easier to compare to the API documenation:

/*
   [name]         CreateProcess
   [description]  Creates a new process and its primary thread.

   msdn.microsoft.com/.../ms682425.aspx
*/
PROCEDURE CreateProcessA EXTERNAL {&KERNEL32.DLL}:
   DEFINE INPUT         PARAMETER lpApplicationName      AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpCommandline          AS CHARACTER   NO-UNDO.
   DEFINE INPUT         PARAMETER lpProcessAttributes    AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpThreadAttributes     AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER bInheritHandles        AS {&BOOL}     NO-UNDO.
   DEFINE INPUT         PARAMETER dwCreationFlags        AS {&DWORD}    NO-UNDO.
   DEFINE INPUT         PARAMETER lpEnvironment          AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpCurrentDirectory     AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpStartupInfo          AS {&POINTER}  NO-UNDO.
   DEFINE INPUT         PARAMETER lpProcessInformation   AS {&POINTER}  NO-UNDO.
   DEFINE       RETURN  PARAMETER bResult                AS {&BOOL}     NO-UNDO.

END PROCEDURE.

Posted by frank.meulblok on 13-Mar-2020 13:06

Keep in mind though, if you try to handle this with preprocessors, you end up programs that you need to both compile and deploy under a specific bit-level. Get things wrong and stuff start to crash and burn because of truncated pointers, byte misalignment etc.

Speaking of byte allignment, did you check where the API expects structs as input/you're getting structs returned as memptrs from the API, and adjust your code to follow 64-bit byte alligment rules in the 64-bit builds ? If you forgot that, stuff starts exploding too.

As Stefan said, look at replacing your API calls with .NET-based equivalents first.

Then you can let the .NET framework handle that 32-bit vs 64-bit interoperability, and you only need to worry about a a single bit-level independent build of your r-code.

Also, issues you'll run into will be generally easier to troubleshoot because you'll get more meaningful errors instead of hard-to-trace hard crashes.

And you'll get wide-character support as default. So you don't have to rewrite things again to use the <function>W calls just because a customer wants to be able to, say, use an accented letter in a filename.

Posted by jquerijero on 13-Mar-2020 14:27

So far, changing LONG to INT64 seems to work fine.

This thread is closed