News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

StringCb... and similar windows functions

Started by traphunter, November 30, 2013, 01:14:10 AM

Previous topic - Next topic

jj2007

#15
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

TWell

#16
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

dedndave

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


MichaelW

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.
Well Microsoft, here's another nice mess you've gotten us into.

jj2007

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
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?  ;)

traphunter

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.

dedndave

in most cases....
EAX, ECX, EDX are volatile
EBX, EBP, ESI, EDI are preserved

MichaelW

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

Well Microsoft, here's another nice mess you've gotten us into.

jj2007

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".
In this specific case, only eax and edx get changed, because all MasmBasic macros preserve ecx.