The MASM Forum

General => The Campus => Topic started by: traphunter on November 30, 2013, 01:14:10 AM

Title: StringCb... and similar windows functions
Post by: traphunter on November 30, 2013, 01:14:10 AM
GoAsm; Easy Code IDE; ECGo header

Hello everybody!

I want to use the StringCB... functions (e.g. StringCbLengthW) defined in Strsave.h, but the linker quits with:

Error!
The following symbol was not defined in the object file or files:-
StringCbLengthW

My question is, it is necessary to download the whole PSDK to get the Strsave.lib or is there another solution? E.g. linking against a specific *.dll?

Thank you
traphunter
Title: Re: StringCb... and similar windows functions
Post by: jj2007 on November 30, 2013, 01:44:46 AM
I'm not sure if I ever installed the SDK on this machine here, but the libraries are there.
Have you checked C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib\strsafe.lib ?

Besides, Masm32 has \Masm32\include\ntstrsafe.inc, but my puter says "The program can't start because ntstrsafe.dll is missing" ::)

Apart from that: Using lstrcpyn etc with some caution is the better choice. These "safe" functions are very slow...
Title: Re: StringCb... and similar windows functions
Post by: traphunter on November 30, 2013, 02:11:26 AM
yes, I've checked my machine, I didn't have the libraries. I would like to use these functions in a none time critical task, where I didn't have the control over the input string.
Title: Re: StringCb... and similar windows functions
Post by: jj2007 on November 30, 2013, 02:18:08 AM
Quote from: traphunter on November 30, 2013, 02:11:26 AM... where I didn't have the control over the input string.

Safe and fast:

include \masm32\include\masm32rt.inc

.data
dest db 50 dup(?)
afterdest db "Don't trash me please...", 0

.code
somestring db "Hello, this is a simple string intended for testing string algos. It has 100 characters without zero", 0

.code
start:
mov esi, offset somestring
mov edi, offset dest
.if len(esi)>=sizeof dest
mov eax, sizeof dest
.endif
invoke lstrcpyn, edi, esi, eax
MsgBox 0, edi, offset afterdest, MB_OK
exit
end start


;)
Title: Re: StringCb... and similar windows functions
Post by: traphunter on November 30, 2013, 02:38:56 AM
yes, thank you, but I often try to use existing resources. Really, I would like to know, how to link these windows functions without downloading the whole SDK for getting the strsave.lib.
Title: Re: StringCb... and similar windows functions
Post by: dedndave on November 30, 2013, 03:56:08 AM
that's a strange one   :redface:

according to msdn, it should be in coredll.dll, and is supported xp sp2 or better
i also found references on the web to ntstrsafe.dll and strsafe.dll

i am running xp sp3, and i don't find any of those dll's on my machine - lol

Pelle's C has coredll.lib  <-------------------------  this one is under WinCE
masm32 has ntstrsafe.inc and ntstrsafe.lib
Title: Re: StringCb... and similar windows functions
Post by: dedndave on November 30, 2013, 04:02:16 AM
hmmm - it may be in MSVCRT
checking......
Title: Re: StringCb... and similar windows functions
Post by: dedndave on November 30, 2013, 04:08:22 AM
http://www.masmforum.com/board/index.php?topic=18010.msg151770#msg151770 (http://www.masmforum.com/board/index.php?topic=18010.msg151770#msg151770)

quote from Edgar....

QuoteThe string safe functions are not exported by any library, they are inline code in the SDK headers (Strsafe.h) so they would need to be rewritten from scratch for MASM. However in Windows 8 I noticed that a few of them are available in kernel32.dll as exports.
Title: Re: StringCb... and similar windows functions
Post by: dedndave on November 30, 2013, 04:29:53 AM
http://www.masmforum.com/board/index.php?topic=18010.msg151826#msg151826 (http://www.masmforum.com/board/index.php?topic=18010.msg151826#msg151826)

i agree with the last 3 posts in that thread from Hutch, Jochen, and Greg
string-safe functions are a "compiler thing"
in assembly language, the program should be designed so that buffer over-flows don't occur   :t
i.e., if you need a string-safe function, you're doing it wrong - lol
Title: Re: StringCb... and similar windows functions
Post by: traphunter on November 30, 2013, 05:08:52 AM
Ah, thank you very much, in strsave.h are c++ inline functions. I won't use the strsave.lib anymore. ;)

BTW: The question is not whether I need a function, the question is, it's better to reuse or to write code by yourself? The answer: it varies ;)

with best regards
traphunter
Title: Re: StringCb... and similar windows functions
Post by: dedndave on November 30, 2013, 06:08:09 AM
in assembly language, we might simply create a temp buffer on the stack
that way, you know the buffer is large enough to accomodate the string
thus, the function is never required

i hope that's a little clearer
Title: Re: StringCb... and similar windows functions
Post by: traphunter on November 30, 2013, 07:53:14 AM
If the stringlength is unknown and unpredictable due to streaminput, I can't locate enough memory anywhere, whether what coding language is used. Now I will use the lstr... functions with own coded wrapper.

I only wanted to know a way to use these StringC... functions. I've searched for that, here in this forum and elsewhere, but maybe with wrong phrases. Due to your hints I know much more than before. Thank you very much! :)
Title: Re: StringCb... and similar windows functions
Post by: MichaelW on November 30, 2013, 02:22:38 PM
Judging from it not containing a DLL name but containing at least one object module name, the strsafe.lib from my 2003 PSDK is apparently a static library.

;==============================================================================
include \masm32\include\masm32rt.inc
includelib strsafe.lib
;==============================================================================
StringCbLengthA proto :DWORD,:DWORD,:DWORD
;  _In_   LPCTSTR psz,
;  _In_   size_t cbMax,
;  _Out_  size_t *pcb
;==============================================================================
.data
    slength  dd 0
    string   db "my other brother darryl",0
.code
;==============================================================================
;==============================================================================
start:
;==============================================================================
    invoke StringCbLengthA, ADDR string, 24, ADDR slength
    printf("%d\t%d\n\n",eax,slength)
    inkey
    exit
;==============================================================================
end start


0       23


And from strsafe.h:

#define S_OK  ((HRESULT)0x00000000L)

Title: Re: StringCb... and similar windows functions
Post by: jj2007 on November 30, 2013, 02:49:12 PM
I get Unresolved external symbol '_StringCbLengthA@12'. from my C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib\strsafe.lib of 30.09.2009...

As Dave wrote, it's a 'compiler thing' - here is its definition from strsafe.h:
STRSAFEAPI
StringCbCopyNA(
    __out_bcount(cbDest) STRSAFE_LPSTR pszDest,
    __in size_t cbDest,
    __in_bcount(cbToCopy) STRSAFE_PCNZCH pszSrc,
    __in size_t cbToCopy)
{
    HRESULT hr;
    size_t cchDest = cbDest / sizeof(char);

    hr = StringValidateDestA(pszDest, cchDest, STRSAFE_MAX_CCH);
   
    if (SUCCEEDED(hr))
    {
        size_t cchToCopy = cbToCopy / sizeof(char);

        if (cchToCopy > STRSAFE_MAX_LENGTH)
        {
            hr = STRSAFE_E_INVALID_PARAMETER;
           
            *pszDest = '\0';
        }
        else
        {
            hr = StringCopyWorkerA(pszDest,
                                   cchDest,
                                   NULL,
                                   pszSrc,
                                   cchToCopy);
        }
    }

    return hr;
}


By the way, we discussed all that already one year ago (http://masm32.com/board/index.php?topic=812.0).
Title: Re: StringCb... and similar windows functions
Post by: dedndave on November 30, 2013, 10:11:47 PM
ahhhh, Michael - the PSDK has the static library   :t
don't know how i missed that one (i probably searched for ntstrsafe.lib)

the LIB in the masm32 package is undoubtedly an import library - with no DLL to import from   :P
Title: Re: StringCb... and similar windows functions
Post by: jj2007 on November 30, 2013, 10:34:15 PM
Quote from: dedndave on November 30, 2013, 10:11:47 PM
ahhhh, Michael - the PSDK has the static library   :t

See reply #1. But it doesn't help much, at least with my machines, because the exe complains about the missing ntdll :(

However, StringCbLengthA works:

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)

3948    cycles for 100 * MasmBasic Len
30580   cycles for 100 * StringCbLengthA

3936    cycles for 100 * MasmBasic Len
30588   cycles for 100 * StringCbLengthA

3936    cycles for 100 * MasmBasic Len
30676   cycles for 100 * StringCbLengthA
Title: Re: StringCb... and similar windows functions
Post by: TWell on November 30, 2013, 11:55:25 PM
MichaelW's example with POAsm:.386
.model FLAT, c
option casemap:none
;==============================================================================
;include \masm32\include\masm32rt.inc
includelib kernel32.lib
includelib msvcrt.lib
includelib strsafe.lib
;==============================================================================
StringCbLengthA proto stdcall :DWORD,:DWORD,:DWORD
;  _In_   LPCTSTR psz,
;  _In_   size_t cbMax,
;  _Out_  size_t *pcb
;==============================================================================
ExitProcess proto stdcall :DWORD
printf proto C :DWORD,:VARARG

.data
    slength  dd 0
    string   db "my other brother darryl",0
    fmt      db "%d",9,"%d",13,10,0
.code
;==============================================================================
;==============================================================================
start:
;==============================================================================
    invoke StringCbLengthA, ADDR string, 24, ADDR slength
    invoke printf,addr fmt,eax,slength
    invoke  ExitProcess,0
;==============================================================================
end start
LIBRARY msvcrt.dll
EXPORTS
printf
Title: Re: StringCb... and similar windows functions
Post by: dedndave on December 01, 2013, 03:44:57 AM
3948    cycles for 100 * MasmBasic Len
30580   cycles for 100 * StringCbLengthA

3936    cycles for 100 * MasmBasic Len
30588   cycles for 100 * StringCbLengthA

3936    cycles for 100 * MasmBasic Len
30676   cycles for 100 * StringCbLengthA


not very "zippy" - lol

(http://i5.photobucket.com/albums/y188/MsPurrl/Fictional%20Characters/Zippy.jpg)
Title: Re: StringCb... and similar windows functions
Post by: MichaelW on December 01, 2013, 03:09:31 PM
Quote from: jj2007 on November 30, 2013, 02:49:12 PM
I get Unresolved external symbol '_StringCbLengthA@12'. from my C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib\strsafe.lib of 30.09.2009...

Using the Microsoft Visual C++ Toolkit 2003 compiler it works fine for me, whether the function is inlined or linked in from the library. The attachment includes the EXE and assembly ouput for both.

Doing a dump of the EXEs I see that they both contain the name mscoree.dll. The description from the DLL properties is:

Microsoft .NET Runtime Execution Engine

Makes me wonder how portable the EXEs are...

It looks like all of the EXEs I built with that compiler contain the name, apparently associated with CorExitProcess.
Title: Re: StringCb... and similar windows functions
Post by: jj2007 on December 01, 2013, 07:27:08 PM
Thanks, Michael :t

Test_Inline.asm:
; Line 5165
   lea   ecx, DWORD PTR _cchLength$[ebp]
   push   ecx
   mov   edx, DWORD PTR _cchMax$[ebp]
   push   edx
   mov   eax, DWORD PTR _psz$[ebp]
   push   eax
   call   _StringLengthWorkerA@12


It's a mystery how they can release into the wild an algo that is eight times slower than a reasonable handcrafted one doing exactly the same ::)

Well, almost exactly. Just for fun:

include \masm32\MasmBasic\MasmBasic.inc        ; download (http://masm32.com/board/index.php?topic=94.0)
StringCbLengthA proto :DWORD,:DWORD,:DWORD
includelib strsafestatic.lib

  Init tc
  Let esi=FileRead$("\Masm32\include\Windows.inc")        ; get a source text
  invoke VirtualAlloc, 0, 4096, MEM_COMMIT, PAGE_READWRITE        ; create a 4k buffer
  xchg eax, edi
  pushad
  mov ecx, 4096
  rep movsb        ; copy
  popad
  Print Str$("Len=%i\twith MasmBasic Len\n", Len(edi))
  push eax
  invoke StringCbLengthA, edi, 4096, esp
  pop ecx
  Print Str$("Len=%i   \twith StringCbLengthA\n", ecx)
  Print Str$("Len=%i\twith Masm32 len\n", len(edi))
  Exit
  TryCatchEnd
end start


Output:
Len=4096        with MasmBasic Len
Len=0           with StringCbLengthA
The instruction at "0040149A" referred to the memory location...


And of course, StringCbLengthA reports "The operation completed successfully" - what else would you expect from such a "safe" function?  ;)
Title: Re: StringCb... and similar windows functions
Post by: traphunter on December 02, 2013, 12:43:55 AM
Print Str$("Len=%i\twith MasmBasic Len\n", Len(edi))

change this line the value of edi?
I don't use masm, therefore I can't test it.
Title: Re: StringCb... and similar windows functions
Post by: dedndave on December 02, 2013, 12:48:22 AM
in most cases....
EAX, ECX, EDX are volatile
EBX, EBP, ESI, EDI are preserved
Title: Re: StringCb... and similar windows functions
Post by: MichaelW on December 02, 2013, 03:34:21 AM
QuoteAnd of course, StringCbLengthA reports "The operation completed successfully"...

In my test it failed.

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#define STRSAFE_LIB
#include <strsafe.h>
int main (void)
{
    int res;
    size_t slen;
    char *p = VirtualAlloc(0,4096,MEM_COMMIT,PAGE_READWRITE);
    FILE *stream = fopen( "\\masm32\\include\\windows.inc", "r");
    printf("read: %d\n",fread(p,1,4096,stream));

    res = StringCbLength(p,4096,&slen);
    switch(res)
    {
        case S_OK:
            printf("S_OK\n");
            break;
        case STRSAFE_E_INSUFFICIENT_BUFFER:
            printf("STRSAFE_E_INSUFFICIENT_BUFFER\n");
            break;
        case STRSAFE_E_INVALID_PARAMETER:
            printf("STRSAFE_E_INVALID_PARAMETER\n");
            break;
        case STRSAFE_E_END_OF_FILE:
            printf("STRSAFE_E_END_OF_FILE\n");
            break;
    }
    printf("length: %d\n\n",slen);

    // For StringCbLength the cbMax parameter must specify the maximum
    // number of bytes allowed, including the null terminator, so to
    // correct this problem overwrite the last byte with a null.

    p[4095] = 0;

    res = StringCbLength(p,4096,&slen);
    switch(res)
    {
        case S_OK:
            printf("S_OK\n");
            break;
        case STRSAFE_E_INSUFFICIENT_BUFFER:
            printf("STRSAFE_E_INSUFFICIENT_BUFFER\n");
            break;
        case STRSAFE_E_INVALID_PARAMETER:
            printf("STRSAFE_E_INVALID_PARAMETER\n");
            break;
        case STRSAFE_E_END_OF_FILE:
            printf("STRSAFE_E_END_OF_FILE\n");
            break;
    }
    printf("length: %d\n\n",slen);

    fclose(stream);

    getch();
    return 0;
}


read: 4096
STRSAFE_E_INVALID_PARAMETER
length: 0

S_OK
length: 4095

Title: Re: StringCb... and similar windows functions
Post by: jj2007 on December 02, 2013, 04:24:09 AM
Quote from: MichaelW on December 02, 2013, 03:34:21 AM
QuoteAnd of course, StringCbLengthA reports "The operation completed successfully"...

In my test it failed.

I am wrong and you are right, Michael. While GetLastError reports "The operation completed successfully", StringCbLengthA returns indeed STRSAFE_E_INVALID_PARAMETER (80070057h).

Quote from: traphunter on December 02, 2013, 12:43:55 AM
Print Str$("Len=%i\twith MasmBasic Len\n", Len(edi))

change this line the value of edi?

As Dave already wrote, edi is one of the non-volatile registers. See "register gets trashed (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm)".
In this specific case, only eax and edx get changed, because all MasmBasic macros preserve ecx.