-----------------------------------------------
                            DECLARE AND DATA TYPES
                                January 2024
                 -----------------------------------------------
                                    CCB



1. THE DECLARE STATEMENT SYNTAX (from dv_foxhelp9.chm):

     DECLARE [cFunctionType] FunctionName IN LibraryName [AS AliasName]
        [cParamType1 [@] ParamName1, cParamType2 [@] ParamName2, ...]

     cFunctionType
     Indicates the data type of the return value from the shared library, if any.
     If the function does not return a value, omit cFunctionType.

     cFunctionType can assume the following values:
     SHORT   16-bit integer 
     INTEGER 32-bit integer
     SINGLE  32-bit floating point
     DOUBLE  64-bit floating point
     LONG    32-bit long integer
     STRING  Character string
     OBJECT  IDispatch object type


2. REFERENCE CODE:

     Usually, VFP Advanced (x64) supports all above function types same as VFP 9.0.

     When we pass a structure data as string to the Windows API function,
     we MUST pass the 64-bit structure data instead of the 32-bit structure data.

     For example,

     BOOL ShellExecuteEx(
       _Inout_  SHELLEXECUTEINFO *pExecInfo
     );

     When we pass the SHELLEXECUTEINFO structure data to ShellExecuteEx,
     we MUST pass the 64-bit SHELLEXECUTEINFO structure data.

     The 32-bit SHELLEXECUTEINFO structure:
     typedef struct _SHELLEXECUTEINFO {
       DWORD     cbSize;       // 0x00, cbSize = 0x3C
       ULONG     fMask;        // 0x04
       HWND      hwnd;         // 0x08
       LPCTSTR   lpVerb;       // 0x0C
       LPCTSTR   lpFile;       // 0x10
       LPCTSTR   lpParameters; // 0x14
       LPCTSTR   lpDirectory;  // 0x18
       int       nShow;        // 0x1C
       HINSTANCE hInstApp;     // 0x20
       LPVOID    lpIDList;     // 0x24
       LPCTSTR   lpClass;      // 0x28
       HKEY      hkeyClass;    // 0x2C
       DWORD     dwHotKey;     // 0x30
       HANDLE    hIcon;        // 0x34
       HANDLE    hProcess;     // 0x38
     } SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;
     The size of 32-bit SHELLEXECUTEINFO structure data is 0x3C bytes.

     The 64-bit SHELLEXECUTEINFO structure:
     typedef struct _SHELLEXECUTEINFO {
       DWORD     cbSize;       // 0x00, cbSize = 0x70
       ULONG     fMask;        // 0x04
       HWND      hwnd;         // 0x08
       LPCTSTR   lpVerb;       // 0x10
       LPCTSTR   lpFile;       // 0x18
       LPCTSTR   lpParameters; // 0x20
       LPCTSTR   lpDirectory;  // 0x28
       int       nShow;        // 0x30
       DWORD     padding1;     // 0x34
       HINSTANCE hInstApp;     // 0x38
       LPVOID    lpIDList;     // 0x40
       LPCTSTR   lpClass;      // 0x48
       HKEY      hkeyClass;    // 0x50
       DWORD     dwHotKey;     // 0x58
       DWORD     padding2;     // 0x5C
       HANDLE    hIcon;        // 0x60
       HANDLE    hProcess;     // 0x68
     } SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;
     The size of 64-bit SHELLEXECUTEINFO structure data is 0x70 bytes.

     If we want the same code can run in VFP Advanced (x64) and VFP 9.0,
     we can use the system variable _WIN64 to do it.
     
     The system variable _WIN64 always returns true (.T.) in VFP Advanced 64-bit version.

     For example,

     PRIVATE m.q_execinfo
     IF TYPE("_win64")="L".AND._win64=.T.
        m.q_execinfo=;
           fval2str(m.q_execinfo_cbsize,4)+;
           fval2str(m.q_execinfo_fmask,4)+;
           fval2str(m.q_execinfo_hwnd,8)+;
           fval2str(m.q_execinfo_lpverb,8)+;
           fval2str(m.q_execinfo_lpfile,8)+;
           fval2str(m.q_execinfo_lpparameters,8)+;
           fval2str(m.q_execinfo_lpdirectory,8)+;
           fval2str(m.q_execinfo_nshow,4)+;
           fval2str(0,4)+;
           fval2str(m.q_execinfo_hinstapp,8)+;
           fval2str(m.q_execinfo_lpidlist,8)+;
           fval2str(m.q_execinfo_lpclass,8)+;
           fval2str(m.q_execinfo_hkeyclass,8)+;
           fval2str(m.q_execinfo_dwhotkey,4)+;
           fval2str(0,4)+;
           fval2str(m.q_execinfo_hicon,8)+;
           fval2str(m.q_execinfo_hprocess,8)
     ELSE
        m.q_execinfo=;
           fval2str(m.q_execinfo_cbsize,4)+;
           fval2str(m.q_execinfo_fmask,4)+;
           fval2str(m.q_execinfo_hwnd,4)+;
           fval2str(m.q_execinfo_lpverb,4)+;
           fval2str(m.q_execinfo_lpfile,4)+;
           fval2str(m.q_execinfo_lpparameters,4)+;
           fval2str(m.q_execinfo_lpdirectory,4)+;
           fval2str(m.q_execinfo_nshow,4)+;
           fval2str(m.q_execinfo_hinstapp,4)+;
           fval2str(m.q_execinfo_lpidlist,4)+;
           fval2str(m.q_execinfo_lpclass,4)+;
           fval2str(m.q_execinfo_hkeyclass,4)+;
           fval2str(m.q_execinfo_dwhotkey,4)+;
           fval2str(m.q_execinfo_hicon,4)+;
           fval2str(m.q_execinfo_hprocess,4)
     ENDIF
     =shellexecuteex(@m.q_execinfo)

     In the header file, we can use the function SYS(17) instead of the system variable _WIN64.

     For example,

     * MSXML DOM parser
     #IF SYS(17) = "X64"
     #define MSXML_PARSER		"MSXML2.DOMDocument.6.0"
     #ELSE
     #define MSXML_PARSER		"MSXML2.DOMDocument.4.0"
     #ENDIF


3. THE INTEGER AND LONG DATA TYPES:

     In VFP 9.0 (and before), there is no difference for the INTEGER data type and the LONG data type, they are 32-bit integer.

     In VFP Advanced (x64), for the HANDLE data type and the size_t data type, recommend to use the LONG data type instead of the INTEGER data type.

     For example,

     BOOL WINAPI OpenProcessToken(
       _In_  HANDLE  ProcessHandle,
       _In_  DWORD   DesiredAccess,
       _Out_ PHANDLE TokenHandle
     );

     Sometimes the following code can not run fine in VFP Advanced (x64):
     DECLARE INTEGER OpenProcessToken IN win32api ;
        INTEGER ProcessHandle,;
        INTEGER DesiredAccess,;
        INTEGER @TokenHandle

     Recommend to use the following code:
     DECLARE INTEGER OpenProcessToken IN win32api ;
        LONG ProcessHandle,;
        INTEGER DesiredAccess,;
        LONG @TokenHandle


4. THE DECLARE COMMAND ON HIGH ADDRESS SPACE:

     Some DLLs such as NTDLL.DLL will be loaded on high address space on windows 10 or later,
     so GetModuleHandle("NTDLL.DLL") and GetProcAddress(hmodule_ntdll,"RtlGetVersion") return a high address.

     In VFP Advanced (x64), we can use ALL Windows API functions on high address space (between 0x100000000 (4 GB) and 0x7FFFFFFFFFFFFh (2048 TB)).
     
     In VFP Advanced (x64), we can pass some parameters on high address space (between 0x100000000 (4 GB) and 0x7FFFFFFFFFFFFh (2048 TB))
     and/or large integers between 0x100000000 (4 GB) and 0x7FFFFFFFFFFFFh (2048 TB)) to the following Windows API functions:

     * KERNEL32.DLL
     DECLARE LONG "GetProcAddress" IN WIN32API ;
        LONG hModule,; && high address space
        STRING lpProcName

     DECLARE LONG "VirtualAlloc" IN WIN32API ;
        LONG lpAddress,; && high address space
        LONG dwSize,;    && large integer
        INTEGER flAllocationType,;
        INTEGER flProtect

     DECLARE LONG "VirtualAllocEx" IN WIN32API ;
        LONG hProcess,;
        LONG lpAddress,; && high address space
        LONG dwSize,;    && large integer
        INTEGER flAllocationType,;
        INTEGER flProtect

     DECLARE INTEGER "VirtualFree" IN WIN32API ;
        LONG lpAddress,; && high address space
        LONG dwSize,;    && large integer
        INTEGER dwFreeType
          
     DECLARE INTEGER "VirtualFreeEx" IN WIN32API ;
        LONG hProcess,;
        LONG lpAddress,; && high address space
        LONG dwSize,;    && large integer
        INTEGER dwFreeType

     DECLARE INTEGER "VirtualLock" IN WIN32API ;
        LONG lpAddress,; && high address space
        LONG dwSize      && large integer

     DECLARE INTEGER "VirtualUnlock" IN WIN32API ;
        LONG lpAddress,; && high address space
        LONG dwSize      && large integer

     DECLARE LONG "VirtualQuery" IN WIN32API ;
        LONG lpAddress,; && high address space
        INTEGER lpBuffer,;
        INTEGER dwLength

     DECLARE LONG "VirtualQueryEx" IN WIN32API ;
        LONG hProcess,;
        LONG lpAddress,; && high address space
        INTEGER lpBuffer,;
        INTEGER dwLength

     DECLARE INTEGER "VirtualProtect" IN WIN32API ;
        LONG lpAddress,; && high address space
        LONG dwSize,;    && large integer
        INTEGER flNewProtect,;
        INTEGER @lpflOldProtect

     DECLARE INTEGER "VirtualProtectEx" IN WIN32API ;
        LONG hProcess,;
        LONG lpAddress,; && high address space
        LONG dwSize,;    && large integer
        INTEGER flNewProtect,;
        INTEGER @lpflOldProtect

     DECLARE INTEGER "ReadProcessMemory" IN WIN32API ;
        LONG hProcess,;
        LONG lpAddress,; && high address space
        STRING @lpBuffer,;
        INTEGER nSize,;
        INTEGER @lpNumberOfBytesRead

     DECLARE INTEGER "WriteProcessMemory" IN WIN32API ;
        LONG hProcess,;
        LONG lpAddress,; && high address space
        STRING lpBuffer,;
        INTEGER nSize,;
        INTEGER @lpNumberOfBytesRead

     DECLARE INTEGER "UnhandledExceptionFilter" IN WIN32API ;
        LONG ExceptionInfo && high address space

     * PSAPI.DLL
     DECLARE INTEGER "GetModuleInformation" IN "PSAPI.DLL" ;
        LONG hProcess,;
        LONG hModule,; && high address space
        STRING @lpmodinfo,;
        INTEGER cb

     * NTDLL.DLL
     DECLARE INTEGER "NtAllocateVirtualMemory" IN "NTDLL.DLL" ;
        LONG ProcessHandle,;
        LONG BaseAddress,; && high address space
        INTEGER ZeroBits,;
        LONG RegionSize,;  && large integer
        INTEGER AllocationType,;
        INTEGER Protect

     DECLARE INTEGER "NtFreeVirtualMemory" IN "NTDLL.DLL" ;
        LONG ProcessHandle,;
        LONG BaseAddress,; && high address space
        LONG RegionSize,;  && large integer
        INTEGER FreeType

     DECLARE INTEGER "NtLockVirtualMemory" IN "NTDLL.DLL" ;
        LONG ProcessHandle,;
        LONG BaseAddress,; && high address space
        LONG RegionSize,;  && large integer
        INTEGER MapType

     DECLARE INTEGER "NtUnlockVirtualMemory" IN "NTDLL.DLL" ;
        LONG ProcessHandle,;
        LONG BaseAddress,; && high address space
        LONG RegionSize,;  && large integer
        INTEGER MapType

     DECLARE INTEGER "NtQueryVirtualMemory" IN "NTDLL.DLL" ;
        LONG ProcessHandle,;
        LONG BaseAddress,; && high address space
        INTEGER MemoryInformationClass,;
        STRING @MemoryInformation,;
        INTEGER MemoryInformationLength,;
        INTEGER @ReturnLength

     DECLARE INTEGER "NtReadVirtualMemory" IN "NTDLL.DLL" ;
        LONG ProcessHandle,;
        LONG BaseAddress,; && high address space
        STRING @Buffer,;
        INTEGER BufferSize,;
        INTEGER @NumberOfBytesRead

     DECLARE INTEGER "NtWriteVirtualMemory" IN "NTDLL.DLL" ;
        LONG ProcessHandle,;
        LONG BaseAddress,; && high address space
        STRING Buffer,;
        INTEGER BufferSize,;
        INTEGER @NumberOfBytesRead


5. REFERENCE WEBSITES:

     For the HANDLE data type, usually it starts with the character H, for example, HANDLE, HBITMAP, HBRUSH.
     Please refer to:
     1, Windows Data Types.
     http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx


6. OTHER:

     For reference only, there is no guarantees.

     Any questions or suggestions, please send me an email at ccb2000@163.com.