flat assembler
Message board for the users of flat assembler.

Index > Windows > Basic Strings (BSTRs)

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
Hello,

I want to compose a BSTR. A basic string consists of the following structure:

Length Prefix | Data itself | Terminator

4 Byte | 2 Bytes * number of characters | NULL

How is it possible to export a BSTR in FASM (please without the windows API). I've coded a little bit around, but I think it's wrong Embarassed:

proc BStr_Test
mov [eax-4], dword 2
mov [eax], dword 4
mov [eax+1], dword 0
ret
endp

Thank you in advance

Alexander
Post 15 Jan 2009, 19:49
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
Alexander,

What did you mean by export? Implement structure similar to BSTR?
Code:
struc BSTR [data] {
common
local length
        dd      length
label . word
forward
        du      data
common
length = $ - .
        dw      0
}    
You're right about [eax-4] but somewhat off-by-one in [eax+1] and last two dwords. Length is in bytes, but each item takes at least 2 bytes (remember the surrogates! Wink)

BTW, were you really want BSTR of single diamond, or that was ASCII end-of-tape? Wink

_________________
"Don't belong. Never join. Think for yourself. Peace." – Victor Stone.
Post 15 Jan 2009, 21:05
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
Thank you baldr.

I see...
I've to implement a structure, but forgive me my question:
I'm a newbe to fasm, so how is it possible to reach my goal?

Could you please give me a "complete" example of who to export a function in a dll which returns a BSTR or a pointer to BSTR, containing any data eg. "test"?

Please
Post 15 Jan 2009, 21:14
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
Alexander,

BSTR is a pointer.
What kind of a complete example do you need?
Define static data with BSTR macro (like, mystr BSTR "Hello, world!", 13, 10), return mystr
Post 15 Jan 2009, 21:23
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
Okey now I now how it works with static data, but is it also possible with dynamic creation of that data. Is it possible to create the data in a function in the code segement?

Thank you, baldr, for your expertise.

Alexander
Post 15 Jan 2009, 21:29
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
Alexander,

1. Allocate big enough memory range.
2. Copy contents.
3. Set size and terminator.
4. Return pointer.

Which part of the scheme is difficult?
Post 15 Jan 2009, 21:46
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
Baldr,

thank you for your answer. I'm absolutly new to fasm, so thank you for your patience. How do I master this all? Would you please be so kind to give me an example? I've nothing found in fasm documentation.

Thank you
Alexander
Post 15 Jan 2009, 21:53
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
Here is the sample code:
Code:
        format PE
        include "WIN32WX.INC"

        .code
start:  invoke  GetProcessHeap
        mov     [hBSTRHeap], eax
        stdcall SysAllocString, "Hello, world!"
        ret

proc SysAllocString sz
        mov     eax, [sz]
        test    eax, eax
        jz      .done                   ; got NULL, bail out
        invoke  lstrlen, [sz]
        test    eax, eax
        jz      .done                   ; got zero-length string, bail out
        shl     eax, 1                  ; they're 2-byte
        push    eax                     ; save string size
        add     eax, 4+2                ; length+terminator
        invoke  HeapAlloc, [hBSTRHeap], HEAP_ZERO_MEMORY, eax
        test    eax, eax
        jz      .done                   ; no core, bail out; extra dword at stack will be discarded, believe me Wink
        add     eax, 4
        push    eax                     ; save BSTR pointer
        invoke  RtlMoveMemory, eax, [sz], dword [esp+4]; it holds string size
        pop     eax                     ; retrieve it back
        pop     dword [eax-4]           ; put string size into it's place
.done:  ret
endp

        .data
hBSTRHeap rd 1

        .end    start    
It'll do nothing, you have to use debugger to see the guts.
Post 15 Jan 2009, 22:58
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
Wow, baldr, I tried it out and tested it with IDA. Amazing!!!

Thank you very much and thank you for your time!
Post 15 Jan 2009, 23:09
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
Alexander,

The code definitely could be written better, but duty calls… so it's quick'n'dirty. Wink
Post 15 Jan 2009, 23:19
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
Hello baldr,

your dynamic example worked perfectly. I think I must be to stupid because I tried to declare the structure and to define "mystr BSTR ..." as you wrote, but if I want to return the string, the vb6 application from which I call the fasm win32 dll crashes?

Crying or Very sad

Isn't the following correct:

Code:
mov eax, [mystr] 
ret    


or

Code:
mov eax, mystr
ret    


I also tried to change the du in the structure to db, because I thought that VB6 has problems with it. (But VB6 is Unicode-ready)?

So baldr,
please, where is the mistake?

baldr wrote:


BSTR is a pointer.
What kind of a complete example do you need?
Define static data with BSTR macro (like, mystr BSTR "Hello, world!", 13, 10), return mystr
Post 27 Jan 2009, 17:17
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
bladr?

Or anyone who can help me please?

Crying or Very sad Crying or Very sad Crying or Very sad

Alexander
Post 04 Feb 2009, 15:30
View user's profile Send private message Reply with quote
Yardman



Joined: 12 Apr 2005
Posts: 245
Location: US
Yardman
[ Post removed by author. ]


Last edited by Yardman on 04 Apr 2012, 03:28; edited 1 time in total
Post 04 Feb 2009, 15:49
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
Yardman wrote:
Can you show us DLL code and VB code?


The DLL-Code
Code:
format PE GUI 4.0 DLL
entry DllEntryPoint

section '.code' code readable executable

struc BSTR [data]
{
     common
      local length
                dd      length
      label . word
        forward
             du      data
        common
      length = $ - .
              dw      0
}

mystr BSTR "Hello, world!", 13, 10


proc BStr_Generator  
    mov eax, [mystr]
    ret
endp

proc DllEntryPoint, hinstDLL,fdwReason,lpvReserved
       mov     eax,TRUE
    ret
endp

include "idata.inc"

section '.edata' export data readable

  export 'ERRORMSG.DLL',\
  BStr_Generator, 'BStr_Generator'
    


idata.inc
Code:
section '.idata' import data readable writeable

  library kernel32,'kernel32.dll',\
          user32,'user32.dll'

  import kernel32,\
         FormatMessage,'FormatMessageA',\
         GetLastError,'GetLastError',\
         LocalFree,'LocalFree'

  import user32,\
         MessageBox,'MessageBoxA'
    


In Visual Basic 6 - GUI Win32-Application (should display a MessageBox with the string)
Code:
Private Declare Function BStr_Generator _
Lib "Test.dll" _
() As String
Private Sub Form_Load()
    MsgBox (BStr_Generator())
    End
End Sub

    


Any help would be nice! Sad
Post 04 Feb 2009, 17:10
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
baldr or Yardman? Anyone?

Where's the mistake
Post 04 Feb 2009, 17:49
View user's profile Send private message Reply with quote
Yardman



Joined: 12 Apr 2005
Posts: 245
Location: US
Yardman
[ Post removed by author. ]


Last edited by Yardman on 04 Apr 2012, 03:28; edited 1 time in total
Post 04 Feb 2009, 18:51
View user's profile Send private message Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
Yardman wrote:
Alexander,

The problem is the conversion that VB does on the
returned string. If you want the proc BStr_Generator
to return a BSTR you will need to play games so that
the BSTR does not get turned into another BSTR when
the function returns to VB.

See here:

http://vb.mvps.org/tips/vb5dll.asp

and look in section 5: Passing and Returning Strings.

Also, you were right about

mov eax, [mystr] needs to be
mov eax, mystr

Mark


Hi Mark,

the problem is in IDA everything is perfect, but when I return to VB6 (the same problem occurs when I use .NET - .NET internally uses BSTRs) the application crashes. I've been playing around for hours (days), but I can't get rid of the problem!? Sad

In the article they allocate the string bstrUpperCase dynamically by calling the function SysAllocStringByteLen, doing some manipulation and returning the BSTR, but the difference between my code is that the len has already been allocated by the compiler and I just want to return the BSTR.

Why is my version not working?

I would be glad for any suggestions.

Thanks Very Happy

Alexander
Post 04 Feb 2009, 19:40
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3045
Location: vpcmipstrm
bitRAKE
Windows must be able to control the (de-)allocation of the string. Use the OLE string functions to create/use BSTRs - it is the easiest way to insure it will work.
Quote:
To handle strings that are allocated by one component and freed by another, Automation defines a special set of functions. These functions use the following data type: typedef OLECHAR * BSTR;

These strings are zero-terminated, and in most cases they can be treated just like OLECHAR* strings. However, you can query a BSTR for its length rather than scan it, so it can contain embedded null characters. The length is stored as a 32-bit integer at the memory location preceding the data in the string. Instead of reading this location directly, applications should use the string manipulation functions to access the length of a BSTR.
It's impossible to know if another component will attempt to free the BSTR passed to it.
Post 05 Feb 2009, 05:27
View user's profile Send private message Visit poster's website Reply with quote
Alexander



Joined: 22 Dec 2008
Posts: 40
Alexander
bitRAKE wrote:
Windows must be able to control the (de-)allocation of the string. Use the OLE string functions to create/use BSTRs - it is the easiest way to insure it will work.
Quote:
To handle strings that are allocated by one component and freed by another, Automation defines a special set of functions. These functions use the following data type: typedef OLECHAR * BSTR;

These strings are zero-terminated, and in most cases they can be treated just like OLECHAR* strings. However, you can query a BSTR for its length rather than scan it, so it can contain embedded null characters. The length is stored as a 32-bit integer at the memory location preceding the data in the string. Instead of reading this location directly, applications should use the string manipulation functions to access the length of a BSTR.
It's impossible to know if another component will attempt to free the BSTR passed to it.



bitRAKE,

thanks for your answer, but how will any ole function or api know that the string wasn't manipulated. Isn't there a way in fasm for a solution?

Thanks

Alexander
Post 05 Feb 2009, 23:03
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3045
Location: vpcmipstrm
bitRAKE
Alexander wrote:
how will any ole function or api know that the string wasn't manipulated. Isn't there a way in fasm for a solution?
My understanding is that strings are consumed by APIs, or rather we must assume they are consumed because a returned BSTR can be different than the one passed. The convention works on not knowing. Of course it can be done in FASM, but it must be compatible with the convention.

I am by no means very experienced with COM/BSTR, but I've seen other's struggle with the same problem on the MASM forums in years past. Japheth has done much with COM in assembly, but the code has much MASM specific syntax glue holding it all together (i.e. tough reading for a MASM noob). IronFelix's recent posting looks much better by comparison, but lacks the depth of Japheth's work. (I'm being my typical overcritical ass - hope they don't take it personal, both are great work.)

_________________
¯\(°_o)/¯ unlicense.org
Post 06 Feb 2009, 02:13
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.