I am having trouble with

invoke SafeArrayGetElement, param1, ADDR counter, EDI

invoke SafeArrayGetElement, IN, IN, OUT

I am sure my param 1 is a pointer to a safearray as it has worked in other function calls.  And I have been able to read param1s elements videlicet: cDims, fFeatures, cbElements, and there seems to be some pvData too, but its Greek to me.
I have tried calling this function from counter = 0 to well below 1, but I only get DISP_E_BADINDEX.  I tried multidimensional arrays in place of counter but that just gives me E_INVALIDARG.  And just imagine the number of multidimensional arrays you could try.  I have tried qword counters and many other things in place of counter and that just freezes the Excel worksheet that is calling the DLL that this function is in.

I know there are some bogus functions, but I have seen a lot of examples of this called on the net.  But I have not seen it called in an assembly DLL for a VB macro in an Excel worksheet.

I do believe it would be easier to write the param1 data to a file and have the dll work on the file data. But I desire to figure this one out.

I have tried locking and unlocking the safearray first too.

I have tried different things in param3 like VARIANTs too. But that results in more exceptional freezes.

VB sucks.

Why do they the people who live over there and do that to them-- make functions that dont work?
Posted on 2007-11-25 18:31:11 by roaknog
Make sure you're passing the ADDRESS where the indices in question are stored, and not the indices themselves.

That's all I can say without seeing the code.
Posted on 2007-11-25 19:01:30 by ti_mo_n
I finally got it to work.  SafeArrayPutElement is persnickety.  I could feel my head get hot in my endeavor to code for it.

.686 
.model flat, stdcall
option casemap:none


include user32.inc
include oleaut32.inc
include kernel32.inc

includelib user32.lib
includelib oleaut32.lib
includelib kernel32.lib



GetElementsFromSafearray PROTO p1:DWORD, p2:DWORD
OutputNumber PROTO p1:DWORD
PutElementsIntoSafearray PROTO p1:DWORD, p2:DWORD
wsprintfA PROTO C :DWORD,:VARARG
wsprintf EQU <wsprintfA>



.data
; structures
SAFEARRAYBOUND STRUC
cElements DWORD 0
Lbound DWORD 0
SAFEARRAYBOUND ENDS
aDim SAFEARRAYBOUND <>
SAFEARRAY STRUC ; size = 12 bytes
cDims WORD 0 ; Count of dimensions in this array.
fFeatures WORD 0 ; Flags used by the SafeArray
cbElements DWORD 0 ; Size of an element of the array. Does not include size of pointed-to data.
cLocks DWORD 0 ; Number of times the array has been locked without corresponding unlock.
pvData DWORD 0
rgsabound1 SAFEARRAYBOUND <>, <>
SAFEARRAY ENDS
PSAFEARRAY TYPEDEF PTR SAFEARRAY
p_s_a PSAFEARRAY 0
ARRAY STRUC
my_array DWORD 1000 dup (0)
ARRAY ENDS
array ARRAY <>
PARRAY TYPEDEF PTR ARRAY

; general variables
cw_msg DB 10, 13, 10, 13, '    Freehafer''s 32 Bit Safearray Program Is Terminated!', 10, 13, 10, 13, '    (c)2007 INNIEA PUBLISHING CO.  R', 153, 142, 'K NOG!', 10, 13, 10, 13, '    Hit enter key to exit . . . ', 0
create_msg DB 'Call to SafeArrayCreate is bad.', 0
input_msg DB 10, 13, 10, 13, '    Input a zero based index number: ', 0
total_index_count DWORD 17

; put safearray element procedure variables
put_error_msg DB 'Call to SafeArrayPutElement is bad.', 0
aindex DWORD 1000 dup (0)
ai DWORD 1000 dup (0)

; get safearray element procedure variables
buffy DB 512 dup (?)
new_line DB 10, 13, 10, 13, '    Index = %d    Value = %d.', 0
get_error_msg DB 'Call to SafeArrayGetElement is bad.', 0

; display number procedure variable
num_char_written DD 0
bytes_to_write DB 0

; input number procedure variables
num_char_read DD 0
bytes_to_read DB 0

; get handles procedure variables
w_std_handle DD 0
r_std_handle DD 0



.code
start:
call GetHandles
invoke WriteConsole, w_std_handle, ADDR input_msg, sizeof input_msg, ADDR num_char_written, 0
call InputNumber
mov total_index_count, EAX

mov DWORD PTR , 0
mov DWORD PTR , 1
mov EAX, total_index_count
mov DWORD PTR , EAX
lea EAX, DWORD PTR
invoke SafeArrayCreate, 2, 1, EAX
.if EAX == 0
invoke MessageBoxA, 0, ADDR create_msg, 0, 0
.endif
mov p_s_a, EAX

invoke PutElementsIntoSafearray, p_s_a, total_index_count
invoke GetElementsFromSafearray, p_s_a, total_index_count

ASSUME ESI:PARRAY
mov ESI, EAX
mov ECX, 0
mov EBX, 0
.while ECX < total_index_count
mov EAX, DWORD PTR
add EBX, 4
pusha
invoke wsprintf, ADDR buffy, ADDR new_line, ECX, EAX
invoke WriteConsole, w_std_handle, ADDR buffy, EAX, ADDR num_char_written, 0
popa
inc ECX
.endw
ASSUME ESI:NOTHING

invoke WriteConsole, w_std_handle, ADDR cw_msg, sizeof cw_msg, ADDR num_char_written, 0
invoke ReadConsole, r_std_handle, ADDR bytes_to_read, 1, ADDR num_char_read, 0
invoke ReadConsole, r_std_handle, ADDR bytes_to_read, 1, ADDR num_char_read, 0
invoke ExitProcess, 0



;________________________________________________________________________________



GetElementsFromSafearray proc USES ESI EDI EBX ECX EDX psa:DWORD, limit:DWORD
LOCAL hres:DWORD
LOCAL counter:DWORD
LOCAL each_item:DWORD
LOCAL counter_plus:DWORD
mov DWORD PTR , 0
mov counter, 0
mov counter_plus, 0
mov EBX, limit
.while counter < EBX
mov ECX, counter
mov EAX, counter
mov DWORD PTR , EAX
lea EDI, DWORD PTR
lea ECX, DWORD PTR
invoke SafeArrayGetElement, psa, ECX, EDI
; EXTRACT VALUES AND PUT THEM IN pointer_array for EAX
pusha
mov EBX, counter_plus
mov ECX, DWORD PTR
mov DWORD PTR , ECX
mov DWORD PTR , ECX ; save it in array
invoke wsprintf, ADDR buffy, ADDR new_line, counter, each_item
invoke WriteConsole, w_std_handle, ADDR buffy, EAX, ADDR num_char_written, 0
popa
; END EXTRACT VALUES AND PUT THEM IN pointer_array for EAX
mov hres, EAX
inc counter
add counter_plus, 4
.endw
.if hres != 0
invoke MessageBoxA, 0, ADDR get_error_msg, 0, 0
.endif
lea EAX, DWORD PTR
ret
GetElementsFromSafearray endp



;________________________________________________________________________________



GetHandles proc
invoke GetStdHandle, -11
mov w_std_handle, EAX
invoke GetStdHandle, -10
mov r_std_handle, EAX
ret
GetHandles endp



;________________________________________________________________________________



InputNumber proc USES EBX ECX EDX
LOCAL IN_NUMBER:DWORD
mov IN_NUMBER, 0
read_loop:
mov EBX, 0
invoke ReadConsole, r_std_handle, ADDR bytes_to_read, 1, ADDR num_char_read, 0
mov AL, bytes_to_read
cmp AL, 0
jne not_special
jmp short exit_read
not_special:
cmp al,'0'
jb exit_read
cmp AL, '9'
ja exit_read
sub AL, '0'
mov BL, AL
mov EAX, IN_NUMBER
mov ECX, 10
mul ECX
mov IN_NUMBER, EAX
add IN_NUMBER, EBX
jmp short read_loop
exit_read:
mov EAX, IN_NUMBER
ret
InputNumber endp



;________________________________________________________________________________



OutputNumber proc USES EBX ECX EDX OUT_NUMBER:DWORD
LOCAL counter:DWORD
mov EAX, OUT_NUMBER
mov EBX, 10
mov counter, 0
display_number_loop_next_divide:
mov EDX, 0
div EBX
push EDX
inc counter
cmp EAX, 0
jne display_number_loop_next_divide
display_number_out_loop:
pop EDX
add DL, 48
mov bytes_to_write[0], DL
invoke WriteConsole, w_std_handle, ADDR bytes_to_write, 1, ADDR num_char_written, 0
dec counter
.IF (counter > 0)
jmp display_number_out_loop
.ENDIF
ret
OutputNumber endp



;________________________________________________________________________________



PutElementsIntoSafearray proc USES EBX ECX EDX psa:DWORD, limit:DWORD
LOCAL hres:DWORD
LOCAL counter:DWORD
mov EBX, limit
mov counter, 0
.while counter < EBX
mov EDX, counter
mov DWORD PTR , EDX
mov EAX, DWORD PTR
imul EAX, 13
mov DWORD PTR , EAX
lea ECX, DWORD PTR
lea EDX, DWORD PTR
invoke SafeArrayPutElement, psa, EDX, ECX
mov hres, EAX
inc counter
.endw
.if hres != 0
invoke MessageBoxA, 0, ADDR put_error_msg, 0, 0
.endif
mov EAX, 0
ret
PutElementsIntoSafearray endp



;________________________________________________________________________________



end start

Posted on 2007-12-01 08:57:19 by roaknog