; #INDEX# ======================================================================================================================= ; Title .........: SafeArray UDF ; AutoIt Version : 3.3 ; Language ......: English ; Description ...: Provides functions for creating, managing, and interacting with COM SafeArray structures, including VARIANT handling. ; Author(s) .....: Numeric1 ; Remarks .......: Standalone UDF with no dependencies on AutoItObject.au3 or Variant.au3. ; Based on SafeArray and Variant functions from AutoItObject.au3 by the AutoItObject-Team. ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/ ; =============================================================================================================================== ; #CONSTANTS# =================================================================================================================== ; Description ...: Structures, variant types, and flags for SafeArray, VARIANT, and BSTR operations. ; Remarks .......: Used for manipulating SafeArray and VARIANT structures in COM automation. ; Author ........: Numeric1 ; =============================================================================================================================== #include-once #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include ; #CURRENT# ===================================================================================================================== ; _AutoItArrayFromSafeArray ; _CreateSafeArrayBounds ; _CreateSafeArrayIndices ; _SafeArrayAccessData ; _SafeArrayAddRef ; _SafeArrayAllocData ; _SafeArrayAllocDescriptor ; _SafeArrayAllocDescriptorEx ; _SafeArrayCopyData ; _SafeArrayCreate ; _SafeArrayCreateEx ; _SafeArrayCreateVector ; _SafeArrayCreateVectorEx ; _SafeArrayDestroy ; _SafeArrayDestroyData ; _SafeArrayDestroyDescriptor ; _SafeArrayFromAutoItArray ; _SafeArrayGetDim ; _SafeArrayGetElement ; _SafeArrayGetElementSize ; _SafeArrayGetID ; _SafeArrayGetLBound ; _SafeArrayGetUBound ; _SafeArrayGetVartype ; _SafeArrayLock ; _SafeArrayPutElement ; _SafeArrayRelease ; _SafeArrayUnaccessData ; _SafeArrayUnlock ; _SysAllocString ; _SysFreeString ; _SysReadString ; _SysStringLen ; _VariantClear ; _VariantInit ; _VariantRead ; _VariantSet ; =============================================================================================================================== ; SAFEARRAYBOUND structure Global Const $tagSAFEARRAYBOUND = "ulong cElements;long lLbound;" ; VARIANT structure Global Const $tagVARIANT = "word vt;word r1;word r2;word r3;ptr data;ptr reserved;" ; Variant types (VT_*) Global Const $VT_EMPTY = 0x0000 Global Const $VT_NULL = 0x0001 Global Const $VT_I2 = 0x0002 Global Const $VT_I4 = 0x0003 Global Const $VT_R4 = 0x0004 Global Const $VT_R8 = 0x0005 Global Const $VT_CY = 0x0006 Global Const $VT_DATE = 0x0007 Global Const $VT_BSTR = 0x0008 Global Const $VT_DISPATCH = 0x0009 Global Const $VT_ERROR = 0x000A Global Const $VT_BOOL = 0x000B Global Const $VT_VARIANT = 0x000C Global Const $VT_UNKNOWN = 0x000D Global Const $VT_DECIMAL = 0x000E Global Const $VT_I1 = 0x0010 Global Const $VT_UI1 = 0x0011 Global Const $VT_UI2 = 0x0012 Global Const $VT_UI4 = 0x0013 Global Const $VT_I8 = 0x0014 Global Const $VT_UI8 = 0x0015 Global Const $VT_INT = 0x0016 Global Const $VT_UINT = 0x0017 Global Const $VT_ARRAY = 0x2000 Global Const $VT_BYREF = 0x4000 Global Const $VT_PTR = 26 Global Const $VT_CLSID = 0x001E Global Const $VT_FILETIME = 0x0040 ; Size constants Global Const $VARIANT_SIZE = DllStructGetSize(DllStructCreate($tagVARIANT)) Global Const $PTR_SIZE = DllStructGetSize(DllStructCreate('ptr')) ; #VARIABLES# =================================================================================================================== ; Description ...: Global handles and flags for DLLs used in SafeArray and VARIANT operations. ; Author ........: Numeric1 ; =============================================================================================================================== Global Const $gh_SafeArray_oleautdll = DllOpen("oleaut32.dll") Global Const $gh_SafeArray_ole32dll = DllOpen("ole32.dll") Global Const $SAFEARRAY_X64 = @AutoItX64 ; #FUNCTION# ==================================================================================================================== ; Name ..........: _AutoItArrayFromSafeArray ; Description ...: Converts a COM SafeArray to an AutoIt array. ; Syntax ........: _AutoItArrayFromSafeArray($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; Return values .: Success: AutoIt array with the same dimensions and data. ; Failure: 0 and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - Invalid dimensions or SafeArray access error. ; 3 - Failed to get lower bound. ; 4 - Failed to get upper bound. ; 5 - Invalid dimension size (<= 0). ; 7 - Too many dimensions (> 5). ; 8 - SafeArray does not contain VARIANT elements. ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Preserves AutoIt dimension order. Only supports VT_VARIANT SafeArrays. ; Related .......: _SafeArrayFromAutoItArray, _SafeArrayGetElement ; Example .......: Local $aArray = _AutoItArrayFromSafeArray($pSafeArray) ; =============================================================================================================================== Func _AutoItArrayFromSafeArray($pSafeArray) If Not $pSafeArray Then Return SetError(1, 0, 0) Local $vType If _SafeArrayGetVartype($pSafeArray, $vType) <> 0 Or $vType <> $VT_VARIANT Then Return SetError(8, 0, 0) Local $iDim = _SafeArrayGetDim($pSafeArray) If @error Or $iDim = 0 Then Return SetError(2, 0, 0) If $iDim > 5 Then Return SetError(7, 0, 0) ; Get bounds Local $aLBounds[$iDim], $aUBounds[$iDim], $aSizes[$iDim] For $i = 1 To $iDim _SafeArrayGetLBound($pSafeArray, $i, $aLBounds[$i - 1]) If @error Then Return SetError(3, 0, 0) _SafeArrayGetUBound($pSafeArray, $i, $aUBounds[$i - 1]) If @error Then Return SetError(4, 0, 0) $aSizes[$i - 1] = $aUBounds[$i - 1] - $aLBounds[$i - 1] + 1 If $aSizes[$i - 1] <= 0 Then Return SetError(5, 0, 0) Next ; Create AutoIt array Local $aArray = __CreateAutoItArray($aSizes) ; Fill AutoIt array __ReadSafeArrayUsingGetElement($pSafeArray, $aArray, $aSizes, 0, $iDim) Return $aArray EndFunc ;==>_AutoItArrayFromSafeArray ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CreateSafeArrayBounds ; Description ...: Creates a SAFEARRAYBOUND structure for a SafeArray, supporting up to 5 dimensions. ; Syntax ........: _CreateSafeArrayBounds($iElements1 [, $iLBound1 = 0 [, $iElements2 = 0 [, $iLBound2 = 0 [, ...]]]]) ; Parameters ....: $iElements1 - Number of elements for the first dimension (required). ; $iLBound1 - (Optional) Lower bound for the first dimension (default: 0). ; $iElements2 - (Optional) Number of elements for the second dimension (default: 0). ; $iLBound2 - (Optional) Lower bound for the second dimension (default: 0). ; $iElements3 - (Optional) Number of elements for the third dimension (default: 0). ; $iLBound3 - (Optional) Lower bound for the third dimension (default: 0). ; $iElements4 - (Optional) Number of elements for the fourth dimension (default: 0). ; $iLBound4 - (Optional) Lower bound for the fourth dimension (default: 0). ; $iElements5 - (Optional) Number of elements for the fifth dimension (default: 0). ; $iLBound5 - (Optional) Lower bound for the fifth dimension (default: 0). ; Return values .: Success: Pointer to the SAFEARRAYBOUND structure. ; Failure: 0 and sets @error: ; 1 - Too many dimensions (> 5). ; 2 - Invalid number of elements (<= 0 for a specified dimension). ; 3 - Failed to create the structure. ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: The structure is created based on non-zero $iElements parameters. ; Example .......: Local $pBounds = _CreateSafeArrayBounds(3, 0, 2, 0) ; 2D SafeArray (3x2) ; =============================================================================================================================== Func _CreateSafeArrayBounds($iElements1, $iLBound1 = 0, $iElements2 = 0, $iLBound2 = 0, $iElements3 = 0, $iLBound3 = 0, $iElements4 = 0, $iLBound4 = 0, $iElements5 = 0, $iLBound5 = 0) Local $iDims = 1 If $iElements2 > 0 Then $iDims = 2 If $iElements3 > 0 Then $iDims = 3 If $iElements4 > 0 Then $iDims = 4 If $iElements5 > 0 Then $iDims = 5 If $iDims > 5 Then Return SetError(1, 0, 0) If $iElements1 <= 0 Then Return SetError(2, 0, 0) If $iDims >= 2 And $iElements2 <= 0 Then Return SetError(2, 0, 0) If $iDims >= 3 And $iElements3 <= 0 Then Return SetError(2, 0, 0) If $iDims >= 4 And $iElements4 <= 0 Then Return SetError(2, 0, 0) If $iDims >= 5 And $iElements5 <= 0 Then Return SetError(2, 0, 0) Local $sTag = $tagSAFEARRAYBOUND For $i = 2 To $iDims $sTag &= $tagSAFEARRAYBOUND Next Local $tBounds = DllStructCreate($sTag) If @error Then Return SetError(3, 0, 0) DllStructSetData($tBounds, 1, $iElements1) DllStructSetData($tBounds, 2, $iLBound1) If $iDims >= 2 Then DllStructSetData($tBounds, 3, $iElements2) DllStructSetData($tBounds, 4, $iLBound2) EndIf If $iDims >= 3 Then DllStructSetData($tBounds, 5, $iElements3) DllStructSetData($tBounds, 6, $iLBound3) EndIf If $iDims >= 4 Then DllStructSetData($tBounds, 7, $iElements4) DllStructSetData($tBounds, 8, $iLBound4) EndIf If $iDims >= 5 Then DllStructSetData($tBounds, 9, $iElements5) DllStructSetData($tBounds, 10, $iLBound5) EndIf Return DllStructGetPtr($tBounds) EndFunc ;==>_CreateSafeArrayBounds ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CreateSafeArrayIndices ; Description ...: Creates an array of indices for a SafeArray, supporting up to 5 dimensions. ; Syntax ........: _CreateSafeArrayIndices([$iIndex1 = 0 [, $iIndex2 = 0 [, $iIndex3 = 0 [, $iIndex4 = 0 [, $iIndex5 = 0]]]]]) ; Parameters ....: $iIndex1 - (Optional) First index (default: 0). ; $iIndex2 - (Optional) Second index (default: 0). ; $iIndex3 - (Optional) Third index (default: 0). ; $iIndex4 - (Optional) Fourth index (default: 0). ; $iIndex5 - (Optional) Fifth index (default: 0). ; Return values .: Success: 1D array containing the specified indices. ; Failure: 0 and sets @error to 1 (too many dimensions). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Compatible with _SafeArrayPutElement and _SafeArrayGetElement. ; Example .......: Local $aIndices = _CreateSafeArrayIndices(2, 3) ; Returns [2, 3] ; =============================================================================================================================== Func _CreateSafeArrayIndices($iIndex1 = 0, $iIndex2 = 0, $iIndex3 = 0, $iIndex4 = 0, $iIndex5 = 0) If @NumParams > 5 Then Return SetError(1, 0, 0) Local $aArray[@NumParams] If @NumParams >= 1 Then $aArray[0] = $iIndex1 If @NumParams >= 2 Then $aArray[1] = $iIndex2 If @NumParams >= 3 Then $aArray[2] = $iIndex3 If @NumParams >= 4 Then $aArray[3] = $iIndex4 If @NumParams >= 5 Then $aArray[4] = $iIndex5 Return $aArray EndFunc ;==>_CreateSafeArrayIndices ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayAccessData ; Description ...: Locks a SafeArray and retrieves a pointer to its data. ; Syntax ........: _SafeArrayAccessData($pSafeArray, ByRef $pArrayData) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $pArrayData - [out] Pointer to the SafeArray's data. ; Return values .: Success: 0 ; Failure: Non-zero HRESULT and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Must be followed by _SafeArrayUnaccessData to unlock the SafeArray. ; Related .......: _SafeArrayUnaccessData, _SafeArrayFromAutoItArray ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayaccessdata ; Example .......: Local $pData ; _SafeArrayAccessData($pSafeArray, $pData) ; =============================================================================================================================== Func _SafeArrayAccessData($pSafeArray, ByRef $pArrayData) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayAccessData", "ptr", $pSafeArray, "ptr*", 0) If @error Then Return SetError(1, 0, 1) $pArrayData = $aCall[2] Return $aCall[0] EndFunc ;==>_SafeArrayAccessData ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayAddRef ; Description ...: Increments the reference count of a SafeArray. ; Syntax ........: _SafeArrayAddRef($pSafeArray, ByRef $ppvData) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $ppvData - [out] Pointer to the SafeArray's data. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Increments the reference count of the SafeArray and retrieves a pointer to its data. The caller must call ; _SafeArrayRelease to decrement the reference count. Use with caution as AutoIt typically manages SafeArray lifetime. ; Related .......: _SafeArrayRelease, _SafeArrayAccessData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayaddref ; Example .......: Local $pData ; _SafeArrayAddRef($pSafeArray, $pData) ; _SafeArrayRelease($pSafeArray) ; =============================================================================================================================== Func _SafeArrayAddRef($pSafeArray, ByRef $ppvData) If Not $pSafeArray Then Return SetError(1, 0, 1) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayAddRef", "ptr", $pSafeArray, "ptr*", 0) If @error Then Return SetError(2, 0, 1) $ppvData = $aCall[2] Return $aCall[0] EndFunc ;==>_SafeArrayAddRef ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayAllocData ; Description ...: Allocates memory for a SafeArray's data without initializing it. ; Syntax ........: _SafeArrayAllocData($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray descriptor. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: The SafeArray descriptor must have been allocated using _SafeArrayAllocDescriptor or _SafeArrayAllocDescriptorEx. ; The caller must initialize the data and call _SafeArrayDestroyData to free it. ; Related .......: _SafeArrayAllocDescriptor, _SafeArrayAllocDescriptorEx, _SafeArrayDestroyData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayallocdata ; Example .......: Local $pSafeArray = _SafeArrayAllocDescriptor(1) ; _SafeArrayAllocData($pSafeArray) ; _SafeArrayDestroyData($pSafeArray) ; _SafeArrayDestroyDescriptor($pSafeArray) ; =============================================================================================================================== Func _SafeArrayAllocData($pSafeArray) If Not $pSafeArray Then Return SetError(1, 0, 1) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayAllocData", "ptr", $pSafeArray) If @error Then Return SetError(2, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayAllocData ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayAllocDescriptor ; Description ...: Allocates a SafeArray descriptor for the specified number of dimensions. ; Syntax ........: _SafeArrayAllocDescriptor($cDims) ; Parameters ....: $cDims - Number of dimensions for the SafeArray descriptor. ; Return values .: Success: Pointer to the SafeArray descriptor. ; Failure: 0 and sets @error: ; 1 - Invalid number of dimensions (<= 0 or > 5). ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: The descriptor must be initialized with bounds and data. Use _SafeArrayDestroyDescriptor to free it. ; Related .......: _SafeArrayAllocDescriptorEx, _SafeArrayDestroyDescriptor, _SafeArrayAllocData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayallocdescriptor ; Example .......: Local $pSafeArray = _SafeArrayAllocDescriptor(1) ; _SafeArrayDestroyDescriptor($pSafeArray) ; =============================================================================================================================== Func _SafeArrayAllocDescriptor($cDims) If $cDims < 1 Or $cDims > 5 Then Return SetError(1, 0, 0) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayAllocDescriptor", "uint", $cDims, "ptr*", 0) If @error Then Return SetError(2, 0, 0) Return $aCall[2] EndFunc ;==>_SafeArrayAllocDescriptor ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayAllocDescriptorEx ; Description ...: Allocates a SafeArray descriptor with a specified VARIANT type and number of dimensions. ; Syntax ........: _SafeArrayAllocDescriptorEx($vType, $cDims) ; Parameters ....: $vType - VARIANT type for the SafeArray elements (e.g., $VT_VARIANT, $VT_I4). ; $cDims - Number of dimensions for the SafeArray descriptor. ; Return values .: Success: Pointer to the SafeArray descriptor. ; Failure: 0 and sets @error: ; 1 - Invalid number of dimensions (<= 0 or > 5). ; 2 - Invalid VARIANT type. ; 3 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: The descriptor must be initialized with bounds and data. Use _SafeArrayDestroyDescriptor to free it. ; Related .......: _SafeArrayAllocDescriptor, _SafeArrayDestroyDescriptor, _SafeArrayAllocData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayallocdescriptorex ; Example .......: Local $pSafeArray = _SafeArrayAllocDescriptorEx($VT_VARIANT, 1) ; _SafeArrayDestroyDescriptor($pSafeArray) ; =============================================================================================================================== Func _SafeArrayAllocDescriptorEx($vType, $cDims) If $cDims < 1 Or $cDims > 5 Then Return SetError(1, 0, 0) If Not IsInt($vType) Or $vType < 0 Or $vType > 0xFFFF Then Return SetError(2, 0, 0) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayAllocDescriptorEx", "dword", $vType, "uint", $cDims, "ptr*", 0) If @error Then Return SetError(3, 0, 0) Return $aCall[3] EndFunc ;==>_SafeArrayAllocDescriptorEx ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayCopyData ; Description ...: Copies the data from one SafeArray to another. ; Syntax ........: _SafeArrayCopyData($pSafeArraySource, $pSafeArrayDest) ; Parameters ....: $pSafeArraySource - Pointer to the source SafeArray. ; $pSafeArrayDest - Pointer to the destination SafeArray. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error: ; 1 - Invalid source or destination SafeArray pointer. ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: The destination SafeArray must have compatible dimensions and type. The caller is responsible for destroying ; both SafeArrays using _SafeArrayDestroy. ; Related .......: _SafeArrayCopy, _SafeArrayCreate ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraycopydata ; Example .......: Local $pSafeArrayDest = _SafeArrayCreate($VT_VARIANT, 1, $pBounds) ; _SafeArrayCopyData($pSafeArraySource, $pSafeArrayDest) ; _SafeArrayDestroy($pSafeArrayDest) ; =============================================================================================================================== Func _SafeArrayCopyData($pSafeArraySource, $pSafeArrayDest) If Not $pSafeArraySource Or Not $pSafeArrayDest Then Return SetError(1, 0, 1) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayCopyData", "ptr", $pSafeArraySource, "ptr", $pSafeArrayDest) If @error Then Return SetError(2, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayCopyData ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayCreate ; Description ...: Creates a COM SafeArray with the specified type and dimensions. ; Syntax ........: _SafeArrayCreate($vType, $cDims, $rgsabound) ; Parameters ....: $vType - VARIANT type for the SafeArray elements (e.g., $VT_VARIANT, $VT_I4). ; $cDims - Number of dimensions in the SafeArray. ; $rgsabound - Pointer to a SAFEARRAYBOUND structure defining the bounds. ; Return values .: Success: Pointer to the created SafeArray. ; Failure: 0 and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Uses oleaut32.dll. Caller is responsible for destroying the SafeArray with _SafeArrayDestroy. ; Related .......: _SafeArrayCreateEx, _SafeArrayDestroy, _CreateSafeArrayBounds ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraycreate ; Example .......: Local $tBound = DllStructCreate($tagSAFEARRAYBOUND) ; DllStructSetData($tBound, "cElements", 3) ; DllStructSetData($tBound, "lLbound", 0) ; Local $pSafeArray = _SafeArrayCreate($VT_VARIANT, 1, DllStructGetPtr($tBound)) ; =============================================================================================================================== Func _SafeArrayCreate($vType, $cDims, $rgsabound) Local $aCall = DllCall($gh_SafeArray_oleautdll, "ptr", "SafeArrayCreate", "dword", $vType, "uint", $cDims, "ptr", $rgsabound) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc ;==>_SafeArrayCreate ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayCreateEx ; Description ...: Creates a SafeArray with default bounds if none are specified. ; Syntax ........: _SafeArrayCreateEx([$vType = $VT_VARIANT [, $cDims = 1 [, $pBounds = 0 [, $iDefaultElements = 10]]]]) ; Parameters ....: $vType - (Optional) VARIANT type for elements (default: $VT_VARIANT). ; $cDims - (Optional) Number of dimensions (1 to 5, default: 1). ; $pBounds - (Optional) Pointer to SAFEARRAYBOUND structure (default: 0, creates default bounds). ; $iDefaultElements - (Optional) Number of elements for default bounds (default: 10). ; Return values .: Success: Pointer to the created SafeArray. ; Failure: 0 and sets @error: ; 1 - Invalid number of dimensions (<= 0 or > 5). ; 2 - Invalid VARIANT type. ; 3 - Failed to create default bounds structure. ; 4 - Invalid $pBounds pointer. ; 5 - Failed to create SafeArray (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: If $pBounds is 0, creates a SAFEARRAYBOUND structure with $iDefaultElements per dimension. ; Related .......: _SafeArrayCreate, _SafeArrayDestroy, _CreateSafeArrayBounds ; Example .......: Local $pSafeArray = _SafeArrayCreateEx($VT_VARIANT, 1) ; 1D SafeArray with 10 elements ; =============================================================================================================================== Func _SafeArrayCreateEx($vType = $VT_VARIANT, $cDims = 1, $pBounds = 0, $iDefaultElements = 10) If $cDims < 1 Or $cDims > 5 Then Return SetError(1, 0, 0) If Not IsInt($vType) Or $vType < 0 Or $vType > 0xFFFF Then Return SetError(2, 0, 0) Local $tSAbound If $pBounds = 0 Then Local $sTag = $tagSAFEARRAYBOUND For $i = 2 To $cDims $sTag &= $tagSAFEARRAYBOUND Next $tSAbound = DllStructCreate($sTag) If @error Then Return SetError(3, 0, 0) For $i = 1 To $cDims DllStructSetData($tSAbound, ($i - 1) * 2 + 1, $iDefaultElements) DllStructSetData($tSAbound, ($i - 1) * 2 + 2, 0) Next $pBounds = DllStructGetPtr($tSAbound) Else If Not IsPtr($pBounds) Then Return SetError(4, 0, 0) EndIf Local $pSafeArray = _SafeArrayCreate($vType, $cDims, $pBounds) If @error Then Return SetError(5, 0, 0) Return $pSafeArray EndFunc ;==>_SafeArrayCreateEx ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayCreateVector ; Description ...: Creates a one-dimensional SafeArray with the specified type and bounds. ; Syntax ........: _SafeArrayCreateVector($vType, $lLBound, $cElements) ; Parameters ....: $vType - VARIANT type for the SafeArray elements (e.g., $VT_VARIANT, $VT_I4). ; $lLBound - Lower bound of the SafeArray. ; $cElements - Number of elements in the SafeArray. ; Return values .: Success: Pointer to the created SafeArray. ; Failure: 0 and sets @error: ; 1 - Invalid VARIANT type. ; 2 - Invalid number of elements (< 0). ; 3 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Creates a 1D SafeArray. The caller must destroy it using _SafeArrayDestroy. ; Related .......: _SafeArrayCreate, _SafeArrayCreateVectorEx, _SafeArrayDestroy ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraycreatevector ; Example .......: Local $pSafeArray = _SafeArrayCreateVector($VT_VARIANT, 0, 10) ; _SafeArrayDestroy($pSafeArray) ; =============================================================================================================================== Func _SafeArrayCreateVector($vType, $lLBound, $cElements) If Not IsInt($vType) Or $vType < 0 Or $vType > 0xFFFF Then Return SetError(1, 0, 0) If $cElements < 0 Then Return SetError(2, 0, 0) Local $aCall = DllCall($gh_SafeArray_oleautdll, "ptr", "SafeArrayCreateVector", "dword", $vType, "long", $lLBound, "uint", $cElements) If @error Then Return SetError(3, 0, 0) Return $aCall[0] EndFunc ;==>_SafeArrayCreateVector ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayCreateVectorEx ; Description ...: Creates a one-dimensional SafeArray with the specified type, bounds, and optional parameter. ; Syntax ........: _SafeArrayCreateVectorEx($vType, $lLBound, $cElements, $pvExtra) ; Parameters ....: $vType - VARIANT type for the SafeArray elements (e.g., $VT_VARIANT, $VT_I4). ; $lLBound - Lower bound of the SafeArray. ; $cElements - Number of elements in the SafeArray. ; $pvExtra - Optional pointer to additional data (typically 0 in AutoIt). ; Return values .: Success: Pointer to the created SafeArray. ; Failure: 0 and sets @error: ; 1 - Invalid VARIANT type. ; 2 - Invalid number of elements (< 0). ; 3 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Similar to _SafeArrayCreateVector but allows an optional extra parameter. The caller must destroy it using _SafeArrayDestroy. ; Related .......: _SafeArrayCreateVector, _SafeArrayCreate, _SafeArrayDestroy ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraycreatevectorex ; Example .......: Local $pSafeArray = _SafeArrayCreateVectorEx($VT_VARIANT, 0, 10, 0) ; _SafeArrayDestroy($pSafeArray) ; =============================================================================================================================== Func _SafeArrayCreateVectorEx($vType, $lLBound, $cElements, $pvExtra) If Not IsInt($vType) Or $vType < 0 Or $vType > 0xFFFF Then Return SetError(1, 0, 0) If $cElements < 0 Then Return SetError(2, 0, 0) Local $aCall = DllCall($gh_SafeArray_oleautdll, "ptr", "SafeArrayCreateVectorEx", "dword", $vType, "long", $lLBound, "uint", $cElements, "ptr", $pvExtra) If @error Then Return SetError(3, 0, 0) Return $aCall[0] EndFunc ;==>_SafeArrayCreateVectorEx ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayDestroy ; Description ...: Destroys a SafeArray and frees its memory. ; Syntax ........: _SafeArrayDestroy($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray to destroy. ; Return values .: Success: 0 ; Failure: Non-zero HRESULT and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Must be called to free SafeArray resources. ; Related .......: _SafeArrayCreate, _SafeArrayCreateEx ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraydestroy ; Example .......: _SafeArrayDestroy($pSafeArray) ; =============================================================================================================================== Func _SafeArrayDestroy($pSafeArray) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayDestroy", "ptr", $pSafeArray) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayDestroy ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayDestroyData ; Description ...: Frees the data of a SafeArray without destroying its descriptor. ; Syntax ........: _SafeArrayDestroyData($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Use with SafeArrays created via _SafeArrayAllocDescriptor or _SafeArrayAllocDescriptorEx. The descriptor ; must be freed separately using _SafeArrayDestroyDescriptor. ; Related .......: _SafeArrayAllocData, _SafeArrayDestroyDescriptor, _SafeArrayDestroy ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraydestroydata ; Example .......: Local $pSafeArray = _SafeArrayAllocDescriptor(1) ; _SafeArrayAllocData($pSafeArray) ; _SafeArrayDestroyData($pSafeArray) ; _SafeArrayDestroyDescriptor($pSafeArray) ; =============================================================================================================================== Func _SafeArrayDestroyData($pSafeArray) If Not $pSafeArray Then Return SetError(1, 0, 1) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayDestroyData", "ptr", $pSafeArray) If @error Then Return SetError(2, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayDestroyData ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayDestroyDescriptor ; Description ...: Frees a SafeArray descriptor allocated by _SafeArrayAllocDescriptor or _SafeArrayAllocDescriptorEx. ; Syntax ........: _SafeArrayDestroyDescriptor($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray descriptor. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Must be called to free descriptors allocated by _SafeArrayAllocDescriptor or _SafeArrayAllocDescriptorEx. ; Related .......: _SafeArrayAllocDescriptor, _SafeArrayAllocDescriptorEx, _SafeArrayDestroyData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraydestroydescriptor ; Example .......: Local $pSafeArray = _SafeArrayAllocDescriptor(1) ; _SafeArrayDestroyDescriptor($pSafeArray) ; =============================================================================================================================== Func _SafeArrayDestroyDescriptor($pSafeArray) If Not $pSafeArray Then Return SetError(1, 0, 1) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayDestroyDescriptor", "ptr", $pSafeArray) If @error Then Return SetError(2, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayDestroyDescriptor ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayFromAutoItArray ; Description ...: Converts an AutoIt array to a COM SafeArray. ; Syntax ........: _SafeArrayFromAutoItArray(ByRef Const $aArray) ; Parameters ....: $aArray - AutoIt array to convert (1 to 5 dimensions). ; Return values .: Success: Pointer to the created SafeArray. ; Failure: 0 and sets @error: ; 1 - Input is not an array. ; 2 - Invalid dimensions (0 dimensions). ; 3 - Invalid dimension size (<= 0). ; 4 - Failed to create SafeArray. ; 6 - Too many dimensions (> 5). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Preserves AutoIt dimension order. Only supports VT_VARIANT SafeArrays. ; Related .......: _AutoItArrayFromSafeArray, _SafeArrayCreate ; Example .......: Local $aArray[3][2] = [[1, "Two"], [3, 4.5], ["Five", 6]] ; Local $pSafeArray = _SafeArrayFromAutoItArray($aArray) ; =============================================================================================================================== Func _SafeArrayFromAutoItArray(ByRef Const $aArray) If Not IsArray($aArray) Then Return SetError(1, 0, 0) Local $iDim = UBound($aArray, 0) If $iDim = 0 Then Return SetError(2, 0, 0) If $iDim > 5 Then Return SetError(6, 0, 0) ; Get array bounds Local $aBounds[$iDim], $aSizes[$iDim] For $i = 1 To $iDim $aBounds[$i - 1] = UBound($aArray, $i) If $aBounds[$i - 1] <= 0 Then Return SetError(3, 0, 0) $aSizes[$i - 1] = $aBounds[$i - 1] Next ; Create SAFEARRAYBOUND structure Local $sTag = $tagSAFEARRAYBOUND For $i = 2 To $iDim $sTag &= $tagSAFEARRAYBOUND Next Local $tBound = DllStructCreate($sTag) For $i = 1 To $iDim DllStructSetData($tBound, ($i - 1) * 2 + 1, $aSizes[$i - 1]) DllStructSetData($tBound, ($i - 1) * 2 + 2, 0) Next ; Create SafeArray Local $pSafeArray = _SafeArrayCreate($VT_VARIANT, $iDim, DllStructGetPtr($tBound)) If $pSafeArray = 0 Then Return SetError(4, 0, 0) ; Fill SafeArray __FillSafeArrayUsingPutElement($pSafeArray, $aArray, $aSizes, 0, $iDim) Return $pSafeArray EndFunc ;==>_SafeArrayFromAutoItArray ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayGetDim ; Description ...: Retrieves the number of dimensions in a SafeArray. ; Syntax ........: _SafeArrayGetDim($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; Return values .: Success: Number of dimensions. ; Failure: 0 and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Used to determine the dimensionality of a SafeArray. ; Related .......: _SafeArrayGetLBound, _SafeArrayGetUBound ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraygetdim ; Example .......: Local $iDim = _SafeArrayGetDim($pSafeArray) ; =============================================================================================================================== Func _SafeArrayGetDim($pSafeArray) Local $aResult = DllCall($gh_SafeArray_oleautdll, "uint", "SafeArrayGetDim", "ptr", $pSafeArray) If @error Then Return SetError(1, 0, 0) Return $aResult[0] EndFunc ;==>_SafeArrayGetDim ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayGetElement ; Description ...: Retrieves an element from a SafeArray using the specified indices. ; Syntax ........: _SafeArrayGetElement($pSafeArray, ByRef $aIndices) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $aIndices - Array of indices for accessing the element (AutoIt order). ; Return values .: Success: The value of the element (converted to AutoIt type). ; Failure: 0 and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - Invalid dimensions or SafeArray access error. ; 3 - Mismatch between indices and SafeArray dimensions. ; 4 - Failed to retrieve element (DllCall failure). ; 5 - SafeArray does not contain VARIANT elements. ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Uses AutoIt dimension order. Only supports SafeArrays of type VT_VARIANT. ; Related .......: _SafeArrayPutElement, _CreateSafeArrayIndices ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraygetelement ; Example .......: Local $aIndices = _CreateSafeArrayIndices(1, 0) ; Local $vValue = _SafeArrayGetElement($pSafeArray, $aIndices) ; =============================================================================================================================== Func _SafeArrayGetElement($pSafeArray, ByRef $aIndices) If Not $pSafeArray Then Return SetError(1, 0, 0) Local $iDim = _SafeArrayGetDim($pSafeArray) If @error Or $iDim = 0 Then Return SetError(2, 0, 0) If Not IsArray($aIndices) Or UBound($aIndices) <> $iDim Then Return SetError(3, 0, 0) Local $vType If _SafeArrayGetVartype($pSafeArray, $vType) <> 0 Or $vType <> $VT_VARIANT Then Return SetError(5, 0, 0) ; Create indices structure Local $tIndices = DllStructCreate("long[" & $iDim & "]") For $i = 0 To $iDim - 1 DllStructSetData($tIndices, 1, $aIndices[$i], $i + 1) Next ; Retrieve element Local $tVariant = DllStructCreate("byte[" & $VARIANT_SIZE & "]") Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayGetElement", _ "ptr", $pSafeArray, "ptr", DllStructGetPtr($tIndices), "ptr", DllStructGetPtr($tVariant)) If @error Or $aCall[0] <> 0 Then Return SetError(4, 0, 0) Return _VariantRead(DllStructGetPtr($tVariant)) EndFunc ;==>_SafeArrayGetElement ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayGetElementSize ; Description ...: Retrieves the size (in bytes) of an element in a SafeArray. ; Syntax ........: _SafeArrayGetElementSize($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; Return values .: Success: Size of an element in bytes. ; Failure: 0 and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Useful for determining memory requirements for SafeArray data access. ; Related .......: _SafeArrayGetVartype, _SafeArrayAccessData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraygetelementsize ; Example .......: Local $iSize = _SafeArrayGetElementSize($pSafeArray) ; ConsoleWrite("Element size: " & $iSize & " bytes" & @CRLF) ; =============================================================================================================================== Func _SafeArrayGetElementSize($pSafeArray) If Not $pSafeArray Then Return SetError(1, 0, 0) Local $aCall = DllCall($gh_SafeArray_oleautdll, "uint", "SafeArrayGetElementSize", "ptr", $pSafeArray) If @error Then Return SetError(2, 0, 0) Return $aCall[0] EndFunc ;==>_SafeArrayGetElementSize ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayGetID ; Description ...: Retrieves the IID of the interface for a SafeArray of objects. ; Syntax ........: _SafeArrayGetID($pSafeArray, ByRef $pIID) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $pIID - [out] Pointer to a GUID structure containing the IID. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Typically used for SafeArrays containing objects (e.g., VT_DISPATCH, VT_UNKNOWN). The IID is stored in a ; GUID structure. In AutoIt, this is rarely needed due to high-level COM handling. ; Related .......: _SafeArrayGetVartype, __PtrToIDispatch ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraygetiid ; Example .......: Local $tIID = DllStructCreate("byte[16]") ; _SafeArrayGetID($pSafeArray, DllStructGetPtr($tIID)) ; =============================================================================================================================== Func _SafeArrayGetID($pSafeArray, ByRef $pIID) If Not $pSafeArray Then Return SetError(1, 0, 1) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayGetIID", "ptr", $pSafeArray, "ptr", $pIID) If @error Then Return SetError(2, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayGetID ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayGetLBound ; Description ...: Retrieves the lower bound of a specified SafeArray dimension. ; Syntax ........: _SafeArrayGetLBound($pSafeArray, $iDim, ByRef $iBound) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $iDim - Dimension number (1-based). ; $iBound - [out] Lower bound of the dimension. ; Return values .: Success: 0 ; Failure: Non-zero HRESULT and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Used to determine the starting index of a SafeArray dimension. ; Related .......: _SafeArrayGetUBound, _SafeArrayGetDim ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraygetlbound ; Example .......: Local $iBound ; _SafeArrayGetLBound($pSafeArray, 1, $iBound) ; =============================================================================================================================== Func _SafeArrayGetLBound($pSafeArray, $iDim, ByRef $iBound) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayGetLBound", "ptr", $pSafeArray, "uint", $iDim, "long*", 0) If @error Then Return SetError(1, 0, 1) $iBound = $aCall[3] Return $aCall[0] EndFunc ;==>_SafeArrayGetLBound ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayGetUBound ; Description ...: Retrieves the upper bound of a specified SafeArray dimension. ; Syntax ........: _SafeArrayGetUBound($pSafeArray, $iDim, ByRef $iBound) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $iDim - Dimension number (1-based). ; $iBound - [out] Upper bound of the dimension. ; Return values .: Success: 0 ; Failure: Non-zero HRESULT and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Used to determine the size of a SafeArray dimension. ; Related .......: _SafeArrayGetLBound, _SafeArrayGetDim ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraygetubound ; Example .......: Local $iBound ; _SafeArrayGetUBound($pSafeArray, 1, $iBound) ; =============================================================================================================================== Func _SafeArrayGetUBound($pSafeArray, $iDim, ByRef $iBound) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayGetUBound", "ptr", $pSafeArray, "uint", $iDim, "long*", 0) If @error Then Return SetError(1, 0, 1) $iBound = $aCall[3] Return $aCall[0] EndFunc ;==>_SafeArrayGetUBound ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayGetVartype ; Description ...: Retrieves the VARIANT type of the elements in a SafeArray. ; Syntax ........: _SafeArrayGetVartype($pSafeArray, ByRef $vType) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $vType - [out] VARIANT type of the SafeArray elements. ; Return values .: Success: 0 ; Failure: Non-zero HRESULT and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Used to verify the type of data stored in the SafeArray. ; Related .......: _SafeArrayCreate, _SafeArrayFromAutoItArray ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraygetvartype ; Example .......: Local $vType ; _SafeArrayGetVartype($pSafeArray, $vType) ; =============================================================================================================================== Func _SafeArrayGetVartype($pSafeArray, ByRef $vType) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayGetVartype", "ptr", $pSafeArray, "dword*", 0) If @error Then Return SetError(1, 0, 1) $vType = $aCall[2] Return $aCall[0] EndFunc ;==>_SafeArrayGetVartype ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayLock ; Description ...: Locks a SafeArray to prevent other threads from accessing it, allowing safe data manipulation. ; Syntax ........: _SafeArrayLock($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray to lock. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Must be followed by _SafeArrayUnlock to release the lock. Locking ensures safe access to the SafeArray's data, ; typically used with _SafeArrayAccessData. Multiple locks increment the lock count; each requires a corresponding unlock. ; Related .......: _SafeArrayUnlock, _SafeArrayAccessData, _SafeArrayUnaccessData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearraylock ; Example .......: Local $pSafeArray = _SafeArrayCreateVector($VT_VARIANT, 0, 10) ; _SafeArrayLock($pSafeArray) ; ; Access data ; _SafeArrayUnlock($pSafeArray) ; =============================================================================================================================== Func _SafeArrayLock($pSafeArray) Local $aCall = DllCall($gh_SafeArray_oleautdll, "long", "SafeArrayLock", "ptr", $pSafeArray) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayLock ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayPutElement ; Description ...: Sets an element in a SafeArray at the specified indices. ; Syntax ........: _SafeArrayPutElement($pSafeArray, $aIndices, $vValue) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $aIndices - Array of indices for setting the element (AutoIt order). ; $vValue - Value to set (AutoIt type). ; Return values .: Success: 0 ; Failure: 1 and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - Invalid dimensions or SafeArray access error. ; 3 - Mismatch between indices and SafeArray dimensions. ; 4 - Failed to set element (DllCall failure). ; 5 - SafeArray does not contain VARIANT elements. ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Uses AutoIt dimension order. Only supports SafeArrays of type VT_VARIANT. ; Related .......: _SafeArrayGetElement, _CreateSafeArrayIndices ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayputelement ; Example .......: Local $aIndices = _CreateSafeArrayIndices(1, 0) ; _SafeArrayPutElement($pSafeArray, $aIndices, "NewValue") ; =============================================================================================================================== Func _SafeArrayPutElement($pSafeArray, $aIndices, $vValue) If Not $pSafeArray Then Return SetError(1, 0, 1) Local $iDim = _SafeArrayGetDim($pSafeArray) If @error Or $iDim = 0 Then Return SetError(2, 0, 1) If Not IsArray($aIndices) Or UBound($aIndices) <> $iDim Then Return SetError(3, 0, 1) Local $vType If _SafeArrayGetVartype($pSafeArray, $vType) <> 0 Or $vType <> $VT_VARIANT Then Return SetError(5, 0, 1) ; Create indices structure Local $tIndices = DllStructCreate("long[" & $iDim & "]") For $i = 0 To $iDim - 1 DllStructSetData($tIndices, 1, $aIndices[$i], $i + 1) Next ; Set element Local $tVariant = DllStructCreate($tagVARIANT) _VariantInit(DllStructGetPtr($tVariant)) _VariantSet(DllStructGetPtr($tVariant), $vValue) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayPutElement", "ptr", $pSafeArray, "ptr", DllStructGetPtr($tIndices), "ptr", DllStructGetPtr($tVariant)) If @error Or $aCall[0] <> 0 Then Return SetError(4, 0, 1) Return 0 EndFunc ;==>_SafeArrayPutElement ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayRelease ; Description ...: Decrements the reference count of a SafeArray previously incremented by _SafeArrayAddRef. ; Syntax ........: _SafeArrayRelease($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error: ; 1 - Invalid SafeArray pointer. ; 2 - DllCall failure. ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Must be called to release a SafeArray after _SafeArrayAddRef. Does not destroy the SafeArray unless the ; reference count reaches zero. ; Related .......: _SafeArrayAddRef, _SafeArrayDestroy ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayrelease ; Example .......: Local $pData ; _SafeArrayAddRef($pSafeArray, $pData) ; _SafeArrayRelease($pSafeArray) ; =============================================================================================================================== Func _SafeArrayRelease($pSafeArray) If Not $pSafeArray Then Return SetError(1, 0, 1) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayRelease", "ptr", $pSafeArray) If @error Then Return SetError(2, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayRelease ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayUnaccessData ; Description ...: Unlocks a SafeArray after data access. ; Syntax ........: _SafeArrayUnaccessData($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; Return values .: Success: 0 ; Failure: Non-zero HRESULT and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Must be called after _SafeArrayAccessData to release the lock. ; Related .......: _SafeArrayAccessData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayunaccessdata ; Example .......: _SafeArrayUnaccessData($pSafeArray) ; =============================================================================================================================== Func _SafeArrayUnaccessData($pSafeArray) Local $aCall = DllCall($gh_SafeArray_oleautdll, "int", "SafeArrayUnaccessData", "ptr", $pSafeArray) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayUnaccessData ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SafeArrayUnlock ; Description ...: Unlocks a previously locked SafeArray, decrementing its lock count. ; Syntax ........: _SafeArrayUnlock($pSafeArray) ; Parameters ....: $pSafeArray - Pointer to the SafeArray to unlock. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT and sets @error to 1 (DllCall failure). ; Author ........: Numeric1 ; Modified ......: 2025-08-03 ; Remarks .......: Must be called after _SafeArrayLock to release the lock. The SafeArray remains locked until the lock count ; reaches zero. Use with _SafeArrayAccessData to ensure safe data manipulation. ; Related .......: _SafeArrayLock, _SafeArrayAccessData, _SafeArrayUnaccessData ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayunlock ; Example .......: Local $pSafeArray = _SafeArrayCreateVector($VT_VARIANT, 0, 10) ; _SafeArrayLock($pSafeArray) ; ; Access data ; _SafeArrayUnlock($pSafeArray) ; =============================================================================================================================== Func _SafeArrayUnlock($pSafeArray) Local $aCall = DllCall($gh_SafeArray_oleautdll, "long", "SafeArrayUnlock", "ptr", $pSafeArray) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ;==>_SafeArrayUnlock ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SysAllocString ; Description ...: Allocates a BSTR from a Unicode string. ; Syntax ........: _SysAllocString($sString) ; Parameters ....: $sString - Unicode string to allocate as a BSTR. ; Return values .: Success: Pointer to the allocated BSTR. ; Failure: 0, with @error set to 1 (DllCall error). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: The caller must free the BSTR using _SysFreeString. ; Related .......: _SysFreeString, _SysReadString ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-sysallocstring ; Example .......: Local $pBSTR = _SysAllocString("Hello") ; _SysFreeString($pBSTR) ; =============================================================================================================================== Func _SysAllocString($sString) Local $aRet = DllCall($gh_SafeArray_oleautdll, "ptr", "SysAllocString", "wstr", $sString) If @error Then Return SetError(1, 0, 0) Return $aRet[0] EndFunc ;==>_SysAllocString ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SysFreeString ; Description ...: Frees a previously allocated BSTR. ; Syntax ........: _SysFreeString($pBSTR) ; Parameters ....: $pBSTR - Pointer to the BSTR to free. ; Return values .: Success: 0 ; Failure: 0, with @error set to: ; 1 - Invalid BSTR pointer. ; 2 - DllCall error. ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Must be called to free BSTRs allocated by _SysAllocString. ; Related .......: _SysAllocString, _SysReadString ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-sysfreestring ; Example .......: Local $pBSTR = _SysAllocString("Hello") ; _SysFreeString($pBSTR) ; =============================================================================================================================== Func _SysFreeString($pBSTR) If Not $pBSTR Then Return SetError(1, 0, 0) DllCall($gh_SafeArray_oleautdll, "none", "SysFreeString", "ptr", $pBSTR) If @error Then Return SetError(2, 0, 0) Return 0 EndFunc ;==>_SysFreeString ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SysReadString ; Description ...: Reads the contents of a BSTR into an AutoIt string. ; Syntax ........: _SysReadString($pBSTR [, $iLen = -1]) ; Parameters ....: $pBSTR - Pointer to the BSTR to read. ; $iLen - (Optional) Length of the string to read (default: -1, reads entire string). ; Return values .: Success: The string contents of the BSTR. ; Failure: Empty string, with @error set to: ; 1 - Invalid BSTR pointer. ; 2 - Invalid string length or empty BSTR. ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: The BSTR must be valid and not freed. ; Related .......: _SysAllocString, _SysFreeString, _SysStringLen ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-sysallocstring ; Example .......: Local $pBSTR = _SysAllocString("Hello") ; ConsoleWrite(_SysReadString($pBSTR) & @CRLF) ; _SysFreeString($pBSTR) ; =============================================================================================================================== Func _SysReadString($pBSTR, $iLen = -1) If Not $pBSTR Then Return SetError(1, 0, "") If $iLen < 1 Then $iLen = _SysStringLen($pBSTR) If $iLen < 1 Then Return SetError(2, 0, "") Return DllStructGetData(DllStructCreate("wchar[" & $iLen & "]", $pBSTR), 1) EndFunc ;==>_SysReadString ; #FUNCTION# ==================================================================================================================== ; Name ..........: _SysStringLen ; Description ...: Retrieves the length of a BSTR (in characters). ; Syntax ........: _SysStringLen($pBSTR) ; Parameters ....: $pBSTR - Pointer to the BSTR. ; Return values .: Success: Length of the BSTR (in characters). ; Failure: 0, with @error set to: ; 1 - Invalid BSTR pointer. ; 2 - DllCall error. ; Author ........: ProgAndy, Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Does not include the null terminator. ; Related .......: _SysAllocString, _SysReadString, _SysFreeString ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-sysstringlen ; Example .......: Local $pBSTR = _SysAllocString("Hello") ; ConsoleWrite("Length: " & _SysStringLen($pBSTR) & @CRLF) ; _SysFreeString($pBSTR) ; =============================================================================================================================== Func _SysStringLen($pBSTR) If Not $pBSTR Then Return SetError(1, 0, 0) Local $aRet = DllCall($gh_SafeArray_oleautdll, "uint", "SysStringLen", "ptr", $pBSTR) If @error Then Return SetError(2, 0, 0) Return $aRet[0] EndFunc ;==>_SysStringLen ; #FUNCTION# ==================================================================================================================== ; Name ..........: _VariantInit ; Description ...: Initializes a VARIANT structure to VT_EMPTY. ; Syntax ........: _VariantInit($pVariant) ; Parameters ....: $pVariant - Pointer to the VARIANT structure to initialize. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT, with @error set to 1 (DllCall error). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Initializes the VARIANT to a safe state before use. ; Related .......: _VariantClear ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-variantinit ; Example .......: Local $tVar = DllStructCreate($tagVARIANT) ; _VariantInit(DllStructGetPtr($tVar)) ; =============================================================================================================================== Func _VariantInit($pVariant) Local $aCall = DllCall($gh_SafeArray_oleautdll, "long", "VariantInit", "ptr", $pVariant) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ;==>_VariantInit ; #FUNCTION# ==================================================================================================================== ; Name ..........: _VariantClear ; Description ...: Clears the contents of a VARIANT structure. ; Syntax ........: _VariantClear($pVariant) ; Parameters ....: $pVariant - Pointer to the VARIANT structure to clear. ; Return values .: Success: 0 (S_OK). ; Failure: Non-zero HRESULT, with @error set to 1 (DllCall error). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Frees resources held by the VARIANT (e.g., BSTR, SafeArray). ; Related .......: _VariantInit ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-variantclear ; Example .......: Local $tVar = DllStructCreate($tagVARIANT) ; _VariantClear(DllStructGetPtr($tVar)) ; =============================================================================================================================== Func _VariantClear($pVariant) Local $aCall = DllCall($gh_SafeArray_oleautdll, "long", "VariantClear", "ptr", $pVariant) If @error Then Return SetError(1, 0, 1) Return $aCall[0] EndFunc ;==>_VariantClear ; #FUNCTION# ==================================================================================================================== ; Name ..........: _VariantRead ; Description ...: Reads the value of a VARIANT structure and converts it to an AutoIt type. ; Syntax ........: _VariantRead($pVariant) ; Parameters ....: $pVariant - Pointer to the VARIANT structure. ; Return values .: Success: The AutoIt value from the VARIANT. ; Failure: Empty string or Default, with @error set to 1 (unsupported VARIANT type). ; Author ........: monoceres, ProgAndy ; Modified ......: 2025-07-31 ; Remarks .......: Supports VT_I1, VT_UI1, VT_I2, VT_I4, VT_I8, VT_R4, VT_R8, VT_UI2, VT_UI4, VT_UI8, VT_BSTR, VT_BOOL, ; VT_ARRAY|VT_VARIANT, VT_DISPATCH, VT_PTR, VT_ERROR. ; Related .......: _VariantSet, _SysReadString, _AutoItArrayFromSafeArray ; Example .......: Local $tVar = DllStructCreate($tagVARIANT) ; _VariantSet(DllStructGetPtr($tVar), "Hello") ; ConsoleWrite(_VariantRead(DllStructGetPtr($tVar)) & @CRLF) ; =============================================================================================================================== Func _VariantRead($pVariant) ; Author: monoceres, Prog@ndy Local $var = DllStructCreate($tagVARIANT, $pVariant), $data ; Translate the vt id to a autoit dllcall type Local $VT = DllStructGetData($var, "vt"), $type Switch $VT Case $VT_I1, $VT_UI1 $type = "byte" Case $VT_I2 $type = "short" Case $VT_I4 $type = "int" Case $VT_I8 $type = "int64" Case $VT_R4 $type = "float" Case $VT_R8 $type = "double" Case $VT_UI2 $type = 'word' Case $VT_UI4 $type = 'uint' Case $VT_UI8 $type = 'uint64' Case $VT_BSTR, $VT_CLSID Return _SysReadString(DllStructGetData($var, "data")) Case $VT_BOOL $type = 'short' Case BitOR($VT_ARRAY, $VT_UI1) Local $pSafeArray = DllStructGetData($var, "data") Local $bound, $pData, $lbound If 0 = _SafeArrayGetUBound($pSafeArray, 1, $bound) Then _SafeArrayGetLBound($pSafeArray, 1, $lbound) $bound += 1 - $lbound If 0 = _SafeArrayAccessData($pSafeArray, $pData) Then Local $tData = DllStructCreate("byte[" & $bound & "]", $pData) $data = DllStructGetData($tData, 1) _SafeArrayUnaccessData($pSafeArray) EndIf EndIf Return $data Case BitOR($VT_ARRAY, $VT_VARIANT) Return _AutoItArrayFromSafeArray(DllStructGetData($var, "data")) Case $VT_DISPATCH Return __PtrToIDispatch(DllStructGetData($var, "data")) Case $VT_PTR Return DllStructGetData($var, "data") Case $VT_ERROR Return Default Case $VT_DATE $type = "double" Case $VT_FILETIME $type = "int64" Case Else Return SetError(1, 0, '') EndSwitch $data = DllStructCreate($type, DllStructGetPtr($var, "data")) Switch $VT Case $VT_BOOL Return DllStructGetData($data, 1) <> 0 Case $VT_DATE Local $tFileTime = DllStructCreate($tagFILETIME) Local $aCall = DllCall("Propsys.dll", "long", "VariantToFileTime", _ "ptr", DllStructGetPtr($var), "dword", 0, "ptr", DllStructGetPtr($tFileTime)) If @error Or $aCall[0] <> 0 Then Return SetError(1, 0, "1980/01/01 00:00:00") Return _Date_Time_FileTimeToStr($tFileTime, 1) Case $VT_FILETIME Local $iFileTime64 = DllStructGetData($data, 1) Local $tFTime = __Int64ToFileTime($iFileTime64) Return _Date_Time_FileTimeToStr($tFTime, 1) EndSwitch Return DllStructGetData($data, 1) EndFunc ;==>_VariantRead ; #FUNCTION# ==================================================================================================================== ; Name ..........: _VariantSet ; Description ...: Sets the value of a VARIANT structure from an AutoIt value. ; Syntax ........: _VariantSet($pVariant, $vValue [, $iSpecialType = 0]) ; Parameters ....: $pVariant - Pointer to the VARIANT structure. ; $vValue - AutoIt value to set (e.g., Int32, String, Array). ; $iSpecialType - Optional: Override VARIANT type (default: 0, auto-detect). ; Return values .: Success: Pointer to the VARIANT structure. ; Failure: 0, with @error set to: ; 1 - Failed to allocate memory for new VARIANT. ; 2 - Failed to initialize VARIANT. ; Author ........: monoceres, ProgAndy ; Modified ......: 2025-07-31 ; Remarks .......: If $pVariant is 0, a new VARIANT is allocated using __CoTaskMemAlloc. ; Supports Int32, Int64, String, Double, Float, Bool, Ptr, Object, Array. ; Related .......: _VariantRead, _SysAllocString, _SafeArrayFromAutoItArray ; Example .......: Local $tVar = DllStructCreate($tagVARIANT) ; _VariantSet(DllStructGetPtr($tVar), 42) ; ConsoleWrite(_VariantRead(DllStructGetPtr($tVar)) & @CRLF) ; =============================================================================================================================== Func _VariantSet($pVar, $vVal, $iSpecialType = 0) ; Author: monoceres, Prog@ndy If Not $pVar Then $pVar = __CoTaskMemAlloc($VARIANT_SIZE) _VariantInit($pVar) Else _VariantClear($pVar) EndIf Local $tVar = DllStructCreate($tagVARIANT, $pVar) Local $iType = $VT_EMPTY, $vDataType = '' Switch VarGetType($vVal) Case "Int32" $iType = $VT_I4 $vDataType = 'int' Case "Int64" $iType = $VT_I8 $vDataType = 'int64' Case "String", 'Text' $iType = $VT_BSTR $vDataType = 'ptr' $vVal = _SysAllocString($vVal) Case "Double" $vDataType = 'double' $iType = $VT_R8 Case "Float" $vDataType = 'float' $iType = $VT_R4 Case "Bool" $vDataType = 'short' $iType = $VT_BOOL If $vVal Then $vVal = 0xffff Else $vVal = 0 EndIf Case 'Ptr' If $SAFEARRAY_X64 Then $iType = $VT_UI8 Else $iType = $VT_UI4 EndIf $vDataType = 'ptr' Case 'Object' __IUnknownAddRef($vVal) $vDataType = 'ptr' $iType = $VT_DISPATCH Case "Binary" ; ARRAY OF BYTES ! Local $tSafeArrayBound = DllStructCreate($tagSAFEARRAYBOUND) DllStructSetData($tSafeArrayBound, 1, BinaryLen($vVal)) Local $pSafeArray = _SafeArrayCreate($VT_UI1, 1, DllStructGetPtr($tSafeArrayBound)) Local $pData If 0 = _SafeArrayAccessData($pSafeArray, $pData) Then Local $tData = DllStructCreate("byte[" & BinaryLen($vVal) & "]", $pData) DllStructSetData($tData, 1, $vVal) _SafeArrayUnaccessData($pSafeArray) $vVal = $pSafeArray $vDataType = 'ptr' $iType = BitOR($VT_ARRAY, $VT_UI1) EndIf Case "Array" $vDataType = 'ptr' $vVal = _SafeArrayFromAutoItArray($vVal) $iType = BitOR($VT_ARRAY, $VT_VARIANT) Case Else ;"Keyword" ; all keywords and unknown Vartypes will be handled as "default" $iType = $VT_ERROR $vDataType = 'int' EndSwitch Switch $iSpecialType Case $VT_DATE $vDataType = 'double' $vVal = _SysReadString($vVal) If _DateIsValid($vVal) Then Local $aMyDate, $aMyTime _DateTimeSplit($vVal, $aMyDate, $aMyTime) Local $iYear = Int($aMyDate[1]) Local $iMonth = Int($aMyDate[2]) Local $iDay = Int($aMyDate[3]) Local $iHour = Int($aMyTime[1]) Local $iMinute = Int($aMyTime[2]) Local $iSecond = ($aMyTime[0] = 3) ? Int($aMyTime[3]) : 0 Local $wDosDate = BitOR($iDay, BitShift($iMonth, -5), BitShift($iYear - 1980, -9)) Local $wDosTime = BitOR(Int($iSecond / 2), BitShift($iMinute, -5), BitShift($iHour, -11)) Local $tVariantTime = DllStructCreate("double") Local $aRet = DllCall("OleAut32.dll", "int", "DosDateTimeToVariantTime", "ushort", $wDosDate, "ushort", $wDosTime, "ptr", DllStructGetPtr($tVariantTime)) If @error Or $aRet[0] = 0 Then Return SetError(1, 0, 0) $vVal = DllStructGetData($tVariantTime, 1) EndIf Case $VT_CLSID $iType = $VT_CLSID Case $VT_FILETIME ; Convert FILETIME to a single 64-bit integer (optional, for display) Local $iFileTime64 = ((DllStructGetData($vVal, "Lo") * 0x100000000) + DllStructGetData($vVal, "Hi")) $vVal = $iFileTime64 $vDataType = "int64" $iType = $VT_FILETIME EndSwitch If $vDataType Then DllStructSetData(DllStructCreate($vDataType, DllStructGetPtr($tVar, 'data')), 1, $vVal) If @NumParams = 3 Then $iType = $iSpecialType DllStructSetData($tVar, 'vt', $iType) EndIf Return $pVar EndFunc ;==>_VariantSet ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: __CreateAutoItArray ; Description ...: Creates a multi-dimensional AutoIt array based on specified sizes. ; Syntax ........: __CreateAutoItArray($aSizes) ; Parameters ....: $aSizes - Array of sizes for each dimension. ; Return values .: AutoIt array with the specified dimensions. ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Internal function used by _AutoItArrayFromSafeArray. ; Related .......: _AutoItArrayFromSafeArray ; =============================================================================================================================== Func __CreateAutoItArray(Const ByRef $aSizes) Switch UBound($aSizes) Case 1 Local $aArray[$aSizes[0]] Return $aArray Case 2 Local $aArray[$aSizes[0]][$aSizes[1]] Return $aArray Case 3 Local $aArray[$aSizes[0]][$aSizes[1]][$aSizes[2]] Return $aArray Case 4 Local $aArray[$aSizes[0]][$aSizes[1]][$aSizes[2]][$aSizes[3]] Return $aArray Case 5 Local $aArray[$aSizes[0]][$aSizes[1]][$aSizes[2]][$aSizes[3]][$aSizes[4]] Return $aArray EndSwitch EndFunc ;==>__CreateAutoItArray ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: __CoTaskMemAlloc ; Description ...: Allocates memory using COM task allocator. ; Syntax ........: __CoTaskMemAlloc($iSize) ; Parameters ....: $iSize - Size of memory to allocate (in bytes). ; Return values .: Success: Pointer to allocated memory. ; Failure: 0, with @error set to 1 (DllCall error). ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: The caller must free the memory using __CoTaskMemFree. ; Related .......: __CoTaskMemFree ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemalloc ; Example .......: Local $pMem = __CoTaskMemAlloc(100) ; __CoTaskMemFree($pMem) ; =============================================================================================================================== Func __CoTaskMemAlloc($iSize) Local $aCall = DllCall($gh_SafeArray_ole32dll, "ptr", "CoTaskMemAlloc", "uint_ptr", $iSize) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc ;==>__CoTaskMemAlloc ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: __CoTaskMemFree ; Description ...: Frees memory allocated by __CoTaskMemAlloc. ; Syntax ........: __CoTaskMemFree($pMemory) ; Parameters ....: $pMemory - Pointer to the memory to free. ; Return values .: Success: 0 ; Failure: 0, with @error set to: ; 1 - Invalid memory pointer. ; 2 - DllCall error. ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Must be called to free memory allocated by __CoTaskMemAlloc. ; Related .......: __CoTaskMemAlloc ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemfree ; Example .......: Local $pMem = __CoTaskMemAlloc(100) ; __CoTaskMemFree($pMem) ; =============================================================================================================================== Func __CoTaskMemFree($pMemory) If Not $pMemory Then Return SetError(1, 0, 0) DllCall($gh_SafeArray_ole32dll, "none", "CoTaskMemFree", "ptr", $pMemory) If @error Then Return SetError(2, 0, 0) Return 0 EndFunc ;==>__CoTaskMemFree ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: __FillSafeArrayUsingPutElement ; Description ...: Recursively fills a SafeArray with elements from an AutoIt array. ; Syntax ........: __FillSafeArrayUsingPutElement($pSafeArray, Const ByRef $aArray, Const ByRef $aSizes, $iDim, $iMaxDim [, $aCurrentIndices = ""]) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $aArray - AutoIt array to copy from. ; $aSizes - Array of dimension sizes. ; $iDim - Current dimension being processed. ; $iMaxDim - Total number of dimensions. ; $aCurrentIndices - (Optional) Array of current indices. ; Return values .: None ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Internal function used by _SafeArrayFromAutoItArray. ; Related .......: _SafeArrayFromAutoItArray, _SafeArrayPutElement ; =============================================================================================================================== Func __FillSafeArrayUsingPutElement($pSafeArray, Const ByRef $aArray, Const ByRef $aSizes, $iDim, $iMaxDim, $aCurrentIndices = "") If $aCurrentIndices = "" Then Dim $aCurrentIndices[$iMaxDim] EndIf If $iDim = $iMaxDim - 1 Then For $i = 0 To $aSizes[$iDim] - 1 $aCurrentIndices[$iDim] = $i Local $aIndices[$iMaxDim] For $j = 0 To $iMaxDim - 1 $aIndices[$j] = $aCurrentIndices[$j] Next Local $vValue Switch $iMaxDim Case 1 $vValue = $aArray[$aIndices[0]] Case 2 $vValue = $aArray[$aIndices[0]][$aIndices[1]] Case 3 $vValue = $aArray[$aIndices[0]][$aIndices[1]][$aIndices[2]] Case 4 $vValue = $aArray[$aIndices[0]][$aIndices[1]][$aIndices[2]][$aIndices[3]] Case 5 $vValue = $aArray[$aIndices[0]][$aIndices[1]][$aIndices[2]][$aIndices[3]][$aIndices[4]] EndSwitch _SafeArrayPutElement($pSafeArray, $aIndices, $vValue) Next Else For $i = 0 To $aSizes[$iDim] - 1 $aCurrentIndices[$iDim] = $i __FillSafeArrayUsingPutElement($pSafeArray, $aArray, $aSizes, $iDim + 1, $iMaxDim, $aCurrentIndices) Next EndIf EndFunc ;==>__FillSafeArrayUsingPutElement ;#INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: __IUnknownAddRef ; Description ...: Increments the reference count of a COM object (IUnknown or IDispatch). ; Syntax ........: __IUnknownAddRef($vObject) ; Parameters ....: $vObject - COM object or pointer to IUnknown/IDispatch interface. ; Return values .: Success: New reference count. ; Failure: 0, with @error set to 1 (DllCall error or invalid object). ; Author ........: ProgAndy ; Modified ......: 2025-07-31 ; Remarks .......: Must be paired with __IUnknownRelease to manage COM object lifetime. ; Related .......: __IUnknownRelease, __PtrToIDispatch ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-addref ; Example .......: Local $oObj = ObjCreate("Scripting.Dictionary") ; __IUnknownAddRef($oObj) ; __IUnknownRelease($oObj) ; =============================================================================================================================== Func __IUnknownAddRef($vObject) Local $sType = "ptr" If IsObj($vObject) Then $sType = "idispatch" Local $tVariant = DllStructCreate($tagVARIANT) Local $aCall = DllCall($gh_SafeArray_oleautdll, "long", "DispCallFunc", _ $sType, $vObject, _ "dword", $PTR_SIZE, _ ; offset for AddRef (4 for x86, 8 for x64) "dword", 4, _ ; CC_STDCALL "dword", $VT_UINT, _ "dword", 0, _ ; number of parameters "ptr", 0, _ ; parameters "ptr", 0, _ ; parameters "ptr", DllStructGetPtr($tVariant)) If @error Or $aCall[0] Then Return SetError(1, 0, 0) Return DllStructGetData(DllStructCreate("dword", DllStructGetPtr($tVariant, "data")), 1) EndFunc ;==>__IUnknownAddRef ; #INTERNAL_USE_ONLY# =========================================================================================================== Func __Int64ToFileTime($iInt64) Local $tFileTime = DllStructCreate($tagFILETIME) Local $iLow = BitAND($iInt64, 0xFFFFFFFF) Local $iHigh = BitShift($iInt64, 32) DllStructSetData($tFileTime, "Lo", $iLow) ; Lower 32 bits DllStructSetData($tFileTime, "Hi", $iHigh) ; Upper 32 bits Return $tFileTime EndFunc ;==>__Int64ToFileTime ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: __IUnknownRelease ; Description ...: Decrements the reference count of a COM object (IUnknown or IDispatch). ; Syntax ........: __IUnknownRelease($vObject) ; Parameters ....: $vObject - COM object or pointer to IUnknown/IDispatch interface. ; Return values .: Success: New reference count. ; Failure: 0, with @error set to 1 (DllCall error or invalid object). ; Author ........: ProgAndy ; Modified ......: 2025-07-31 ; Remarks .......: Must be called to release COM objects after __IUnknownAddRef. ; Related .......: __IUnknownAddRef, __PtrToIDispatch ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-release ; Example .......: Local $oObj = ObjCreate("Scripting.Dictionary") ; __IUnknownAddRef($oObj) ; __IUnknownRelease($oObj) ; =============================================================================================================================== Func __IUnknownRelease($vObject) Local $sType = "ptr" If IsObj($vObject) Then $sType = "idispatch" Local $tVariant = DllStructCreate($tagVARIANT) Local $aCall = DllCall($gh_SafeArray_oleautdll, "long", "DispCallFunc", _ $sType, $vObject, _ "dword", 2 * $PTR_SIZE, _ ; offset for Release (8 for x86, 16 for x64) "dword", 4, _ ; CC_STDCALL "dword", $VT_UINT, _ "dword", 0, _ ; number of parameters "ptr", 0, _ ; parameters "ptr", 0, _ ; parameters "ptr", DllStructGetPtr($tVariant)) If @error Or $aCall[0] Then Return SetError(1, 0, 0) Return DllStructGetData(DllStructCreate("dword", DllStructGetPtr($tVariant, "data")), 1) EndFunc ;==>__IUnknownRelease ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: __PtrToIDispatch ; Description ...: Converts a pointer to an IDispatch interface to an AutoIt COM object. ; Syntax ........: __PtrToIDispatch($pDispatch) ; Parameters ....: $pDispatch - Pointer to an IDispatch interface. ; Return values .: Success: AutoIt COM object (IDispatch). ; Failure: 0, with @error set to 1 (DllCall error or invalid pointer). ; Author ........: ProgAndy, Numeric1 ; Modified ......: 2025-08-03 (Corrected implementation) ; Remarks .......: Does NOT increment the reference count - caller is responsible for lifetime management. ; Related .......: __IUnknownAddRef, __IUnknownRelease ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-idispatch ; Example .......: ; Requires a valid IDispatch pointer from a COM operation ; =============================================================================================================================== Func __PtrToIDispatch($pDispatch) If Not $pDispatch Then Return SetError(1, 0, 0) Local $oObj = ObjCreateInterface($pDispatch, "{00020400-0000-0000-C000-000000000046}") ; IDispatch If Not IsObj($oObj) Then Return SetError(1, 0, 0) __IUnknownAddRef($oObj) Return $oObj EndFunc ;==>__PtrToIDispatch ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: __ReadSafeArrayUsingGetElement ; Description ...: Recursively reads elements from a SafeArray into an AutoIt array. ; Syntax ........: __ReadSafeArrayUsingGetElement($pSafeArray, ByRef $aArray, Const ByRef $aSizes, $iDim, $iMaxDim [, $aCurrentIndices = ""]) ; Parameters ....: $pSafeArray - Pointer to the SafeArray. ; $aArray - AutoIt array to fill. ; $aSizes - Array of dimension sizes. ; $iDim - Current dimension being processed. ; $iMaxDim - Total number of dimensions. ; $aCurrentIndices - (Optional) Array of current indices. ; Return values .: None ; Author ........: Numeric1 ; Modified ......: 2025-07-31 ; Remarks .......: Internal function used by _AutoItArrayFromSafeArray. ; Related .......: _AutoItArrayFromSafeArray, _SafeArrayGetElement ; =============================================================================================================================== Func __ReadSafeArrayUsingGetElement($pSafeArray, ByRef $aArray, Const ByRef $aSizes, $iDim, $iMaxDim, $aCurrentIndices = "") If $aCurrentIndices = "" Then Dim $aCurrentIndices[$iMaxDim] EndIf If $iDim = $iMaxDim - 1 Then For $i = 0 To $aSizes[$iDim] - 1 $aCurrentIndices[$iDim] = $i Local $aIndices[$iMaxDim] For $j = 0 To $iMaxDim - 1 $aIndices[$j] = $aCurrentIndices[$j] Next Local $vValue = _SafeArrayGetElement($pSafeArray, $aIndices) Switch $iMaxDim Case 1 $aArray[$aIndices[0]] = $vValue Case 2 $aArray[$aIndices[0]][$aIndices[1]] = $vValue Case 3 $aArray[$aIndices[0]][$aIndices[1]][$aIndices[2]] = $vValue Case 4 $aArray[$aIndices[0]][$aIndices[1]][$aIndices[2]][$aIndices[3]] = $vValue Case 5 $aArray[$aIndices[0]][$aIndices[1]][$aIndices[2]][$aIndices[3]][$aIndices[4]] = $vValue EndSwitch Next Else For $i = 0 To $aSizes[$iDim] - 1 $aCurrentIndices[$iDim] = $i __ReadSafeArrayUsingGetElement($pSafeArray, $aArray, $aSizes, $iDim + 1, $iMaxDim, $aCurrentIndices) Next EndIf EndFunc ;==>__ReadSafeArrayUsingGetElement ; #INTERNAL_USE_ONLY# =========================================================================================================== Func __VariantTimeToDosDateTime($dValue) Local $aRet = DllCall("OleAut32.dll", "int", "VariantTimeToDosDateTime", "double", $dValue, "ptr*", 0, "ptr*", 0) If @error Or $aRet[0] = 0 Then Return SetError(1, 0, "1980/01/01 00:00:00") Local $iDosDate = $aRet[2] Local $iDosTime = $aRet[3] Local $iDay = BitAND($iDosDate, 0x1F) ; Bits 0-4 Local $iMonth = BitAND(BitShift($iDosDate, 5), 0x0F) ; Bits 5-8 Local $iYear = 1980 + BitShift($iDosDate, 9) ; Bits 9-15 Local $iSecond = 2 * BitAND($iDosTime, 0x1F) ; Bits 0-4 (secondes divisées par 2) Local $iMinute = BitAND(BitShift($iDosTime, 5), 0x3F) ; Bits 5-10 Local $iHour = BitShift($iDosTime, 11) ; Bits 11-15 ; YYYY/MM/DD HH:MM:SS Return StringFormat("%04d/%02d/%02d %02d:%02d:%02d", $iYear, $iMonth, $iDay, $iHour, $iMinute, $iSecond) EndFunc ;==>__VariantTimeToDosDateTime