Has anyone tried using the Win32 related files (windows.p, windows.i from Jurjen) on 64-bit environment?
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.
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.
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.
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.
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.
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.
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.
So far, changing LONG to INT64 seems to work fine.