----------------------------------------------- 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 some Windows API functions such as GetModuleHandle("NTDLL.DLL") and GetProcAddress(hmodule_ntdll,"RtlGetVersion") return a high address. In VFP Advanced (x64), we can call 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. |