Author Topic: LB_INITSTORAGE  (Read 3700 times)

jj2007

  • Member
  • *****
  • Posts: 13002
  • Assembler is fun ;-)
    • MasmBasic
LB_INITSTORAGE
« on: August 07, 2016, 12:46:33 PM »
VS 2010 Express help on LB_INITSTORAGE:
Quote
Microsoft Windows NT 4.0 : This message does not allocate the specified amount of memory; however, it always returns the value specified in the wParam parameter.

Old Win32.hlp:
Quote
Windows NT: This message is not needed on Windows NT. It does not reserve the specified amount of memory, because available memory is virtually unlimited. The return value is always the value specified in the cItems parameter.

And both statements are bulls**t, Redmond! For large listboxes, you desperately need this message :badgrin:

More confusion about the meaning of its lParam

P.S.: Little testbed attached. If no commandline is supplied, it will use Windows.inc:
Code: [Select]
1 ms for reading 26902 lines from \Masm32\include\Windows.inc

107 ms for SetListBox, fast
197 ms for SetListBox, slow

91 ms for SetListBox, fast
196 ms for SetListBox, slow

91 ms for SetListBox, fast
219 ms for SetListBox, slow

101 ms for SetListBox, fast
195 ms for SetListBox, slow

133     bytes for slbFast
72      bytes for slbSlow

A factor 2... that's harmless, try dragging instead C:\Windows\tracing\NDPTSP.LOG over the exe 8)
Mine is 10MB, if yours is much bigger then the proggie might hang forever:
Code: [Select]
14 ms for reading 123200 lines from C:\Windows\tracing\NDPTSP.LOG

179 ms for SetListBox, fast
23930 ms for SetListBox, slow

126 ms for SetListBox, fast
23922 ms for SetListBox, slow

126 ms for SetListBox, fast
23973 ms for SetListBox, slow

127 ms for SetListBox, fast
23984 ms for SetListBox, slow
« Last Edit: August 07, 2016, 07:10:33 PM by jj2007 »

TWell

  • Member
  • ****
  • Posts: 743
Re: LB_INITSTORAGE
« Reply #1 on: August 07, 2016, 08:02:56 PM »
Quote
lParam
The amount of memory, in bytes, to allocate for item strings.
This is misleading,
ANSI and UNICODE allocates same amount of memory in listbox in NT as it is UNICODE internally?
Should it be 'in chars, to allocate for item strings' ?
EDIT:
ANSI: char = byte and internally it allocates words.
UNICODE: real amount bytes.
« Last Edit: August 07, 2016, 09:30:14 PM by TWell »

jj2007

  • Member
  • *****
  • Posts: 13002
  • Assembler is fun ;-)
    • MasmBasic
Re: LB_INITSTORAGE
« Reply #2 on: August 07, 2016, 08:17:19 PM »
Good question: bytes to allocate for the strings? I've tested it with varying average string lengths:

SetListbox L$(), c len:85   ; reset content, then reload with assumed average string len

For 85 bytes, it takes 133 ms to load the 10MB listbox; for 75 bytes, it takes a whopping 5000 ms 8)

So with no options, I calculate the average len of the first 127 strings, add a few bytes, multiply with #elements and use the result for lParam:
Code: [Select]
  push ecx ; #elements in string array
  xor ecx, ecx
  xor edi, edi
  .Repeat
push ecx    ; index of element
push arg    ; array ID
call MbArrayGet
add edi, Len(eax)
inc ecx
  .Until ecx>127 || ecx>stack
  xchg eax, edi
  add eax, 127
  cdq
  idiv ecx
  inc eax
  inc eax
  mov ecx, stack
  inc ecx
  mul ecx
  invoke SendMessage, GuiLB, LB_INITSTORAGE, ecx, eax

And that works like a charm - slightly above the fastest point.

Don't ask me why that works, though. My Recall() converts to UTF-8, so the average string len is an ASCII value, but:
Code: [Select]
invoke SendMessageW, GuiLB, LB_ADDSTRING, 0, wRec$(eax)  ; UNICODE
And that supports your theory that lParam refers to chars. Messy...

adeyblue

  • Member
  • **
  • Posts: 89
    • Airesoft
Re: LB_INITSTORAGE
« Reply #3 on: August 08, 2016, 01:53:21 AM »
And both statements are bulls**t, Redmond!

They're technically true (assuming NT4 was comtemporary with the win32.hlp). In NT4, LB_INITSTORAGE doesn't do anything, here's the part of the source code:
Quote
    case LB_INITSTORAGE:
// LATER -- figure out how to port this -- FritzS
//        return((LRESULT) LBInitStorage(plb, (int) wParamLo, lParam));
        return wParam;

Then they figured it out for Win2k:
Quote
    case LB_INITSTORAGE:
        return xxxLBInitStorage(plb, fAnsi, (INT)wParam, (INT)lParam);

The code for what it actually does is in here http://read.pudn.com/downloads3/sourcecode/windows/248345/win2k/private/ntos/w32/ntuser/client/lboxctl1.c__.htm

jj2007

  • Member
  • *****
  • Posts: 13002
  • Assembler is fun ;-)
    • MasmBasic
Re: LB_INITSTORAGE
« Reply #4 on: August 08, 2016, 06:01:21 AM »
The code for what it actually does is in here http://read.pudn.com/downloads3/sourcecode/windows/248345/win2k/private/ntos/w32/ntuser/client/lboxctl1.c__.htm

Nice find, adeyblue :t
Quote
     * if the app is talking ANSI, then adjust for the worst case in unicode 
     * where each single ansi byte translates to one 16 bit unicode value 

P.S.: Under the hood, you might discover this:
Code: [Select]
753E90F1             ³.  FF15 F4003975      call near [<&ntdll.RtlReAllocateH ; ÀNTDLL.RtlReAllocateHeap
With size = 2*lParam. Unless you use SendMessageW, in which case size = lParam :biggrin:
« Last Edit: August 08, 2016, 07:24:44 AM by jj2007 »