News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Microsoft Layer for Unicode in MASM32

Started by KSS, April 23, 2006, 09:25:45 PM

Previous topic - Next topic

KSS

How I can write program in TRUE unicode that can run under 9x/Me systems?

  Example:
   Invoke MessageBoxW,0,ADDR MB_Text_string,0,MB_OK

hutch--

KSS,

What you can get out of win9x depends purely on how effective the unicode support is for it and while I don't have the details handy, i gathered it only supplied empty stubs for many of the unicode functions. This is something you would have to look up at Microsoft as I don't personally have any data on unicode support for win9x.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Vortex

Platform Software Development Kit Redistributable: Microsoft Layer for Unicode on Windows 95, 98, and Me Systems, 1.1.3790.0 :

http://www.microsoft.com/downloads/details.aspx?FamilyID=73BA7BD7-ED06-4F0D-80A4-2A7EEAEE17E2&displaylang=en

QuoteOverview
The Microsoft Layer for Unicode on Windows 95, 98, and Me systems (MSLU) helps to provide a layer over the Win32 API on Win9x so that you can write a single Unicode version of your application.

KSS

Thanks you for answer, but I want load/call "unicows.dll" dynamical. (Such as in GoAsm mslu loader)

I tried load "unicows.dll" with LoadLibraryA() {I read article "Compiling Your Application with the Microsoft Layer for Unicode" in my Platform SDK.}, but it not work. :'(

MichaelW

This works for me under Windows 98 SE:

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      hLib  dd 0
      modfn dw 256 dup(0)
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke LoadLibrary, chr$("unicows.dll")
    mov   hLib, eax
    print uhex$(eax),13,10
    invoke GetProcAddress,hLib,chr$("GetModuleFileNameW")
    push  eax
    print uhex$(eax),13,10
    pop   eax
    push  256
    push  OFFSET modfn
    push  0
    call  eax
    print ustr$(eax),13,10
    invoke crt_printf,chr$("single-byte character string:%s%c"),ADDR modfn,10
    invoke crt_printf,chr$("wide-character string:%S%c"),ADDR modfn,10
    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


I think a better solution might be to link with the unicows.lib from the PSDK, but I have no idea how to do that. I'm assuming that unicows.lib is a static library because it's 2.27MB, where the import library I built was only 103KB.

BTW, judging from the module definition file produced by Vortex's Dll2inc tool, unicows.dll contains 507 functions.

eschew obfuscation

KSS

MichaelW,
Your method is very hard to use in big app! I don't like it.

Possible, I need load "unicows.dll" and dynamically replace all unicode functions addresses that used in my app (in import table) to functions addresses from "unicows.dll" that have same names? :8)


MichaelW

Linking with the unicows.lib from the PSDK turned out to be easier than I thought it would be. At least most of the necessary prototypes are already in the MASM32 include files, and with unicows.lib included first the linker produced an exe with no unicode functions in the imports.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    includelib unicows.lib
    include \masm32\include\masm32rt.inc
    include \masm32\macros\ucmacros.asm   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      modfnw  dw 256 dup(0)
      envvarw dw 512 dup(0)
    .code
start:   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke GetModuleFileNameW,NULL,ADDR modfnw,256
    invoke crt_printf,chr$("%S%c"),ADDR modfnw,10

    invoke GetEnvironmentVariableW,uni$("Path"),ADDR envvarw,512
    invoke crt_printf,chr$("%S%c"),ADDR envvarw,10

    invoke MessageBoxW,0,uni$("MessageBoxW"),uni$("MessageBoxW"),0

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


Here is a listing of the imports from kernel32.dll with unicows.lib included first (as it is in the attachment):

00004000  23C SetLastError
00004004   B3 FreeLibrary
00004008   1E CompareStringA
0000400C  109 GetModuleHandleA
00004010  107 GetModuleFileNameA
00004014  162 GetWindowsDirectoryA
00004018  13C GetSystemDirectoryA
0000401C  1A4 LoadLibraryA
00004020  18F InterlockedExchange
00004024   FD GetLastError
00004028   80 ExitProcess
0000402C  134 GetStdHandle
00004030  29E WriteFile
00004034   A8 FlushConsoleInputBuffer
00004038  260 Sleep

The resulting exe (14KB) runs under Windows 98 SE and produces the same output as it produces under Windows 2000.

Here is the same listing with unicows.lib included last:

00002000   A8 FlushConsoleInputBuffer
00002004  29E WriteFile
00002008   80 ExitProcess
0000200C   ED GetEnvironmentVariableW
00002010  108 GetModuleFileNameW
00002014  134 GetStdHandle
00002018  260 Sleep

The resulting exe (4KB) runs under Windows 98 SE, but the GetModuleFileNameW and GetEnvironmentVariableW calls fail.



[attachment deleted by admin]
eschew obfuscation

KSS

MichaelW,
For first — view my attached archive.

   About how to work "unicows.lib" and "unicows.dll"
(When you include "unicows.lib" before kernel32.lib, advapi32.lib, user32.lib, gdi32.lib, shell32.lib, comdlg32.lib, version.lib, mpr.lib, rasapi32.lib, winmm.lib, winspool.lib, vfw32.lib, secur32.lib, oleacc.lib, oledlg.lib, sensapi.lib)
  1. All unicode function are stripped from result exe-file and add they ANSI equivalent. (to work in Win9x/Me)
  2. In code (where placed calls to unicode functions) dispose call to "unicows.*" functions (that determine about what OS they run, and decide what type of function to call)

Because "unicows.lib" work so badly (I think) I don't want use it at the link-time.
So... I looks for method that allow me to use "unicows.dll" only at run-time.

My things about this:
I need load "unicows.dll" and dynamically replace all unicode functions addresses that used in my app (in import table) to functions addresses from "unicows.dll" that have same names.
But I didn't try this. (I shall do it on following week.)


[attachment deleted by admin]

KSS


Mark Jones

Is this what you are wanting to do?

Quote from: Wikipedia: Microsoft Layer for Unicode:
When a wide-character function is called for the first time at runtime, the function stub in UNICOWS.LIB first receives control and decides if it is running on a Windows 95/98/ME system:

    * If so, it dynamically loads the UNICOWS.DLL (if it hasn't been loaded yet) and passes control to the corresponding thunking stub in there. The thunking stub translates the wide-character arguments into ANSI strings and then invokes the native A version from the OS, and then translates any returned strings back into wide-character format.
    * If the OS natively supports the W version (ie: Windows NT/2000/XP/2003), then the function stub updates the in-memory import table so that future calls will directly invoke the native W version without any more overhead.

Because of this technique, when an application is linked against MSLU, only Windows 95/98/ME systems will need the UNICOWS.DLL at runtime, and on all other operating systems there is only a slight performance penalty for the first function call.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

MichaelW

This is just a quick test to verify that linking with unicows.lib does not (significantly) slow down calls to Unicode functions under Windows 2000.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    includelib unicows.lib
    include \masm32\include\masm32rt.inc
    include \masm32\macros\ucmacros.asm
    .686
    include timers.asm
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      modfnw  dw 256 dup(0)
      envvarw dw 512 dup(0)
    .code
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    LOOP_COUNT equ 5000000
    invoke Sleep,1000

    counter_begin LOOP_COUNT,HIGH_PRIORITY_CLASS
      invoke GetModuleFileNameW,NULL,ADDR modfnw,256
    counter_end
    print ustr$(eax)," cycles",13,10

    counter_begin LOOP_COUNT,HIGH_PRIORITY_CLASS
      invoke GetEnvironmentVariableW,uni$("Path"),ADDR envvarw,512
    counter_end
    print ustr$(eax)," cycles",13,10

    counter_begin LOOP_COUNT,HIGH_PRIORITY_CLASS
      invoke lstrlenW,ADDR envvarw
    counter_end
    print ustr$(eax)," cycles",13,10

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


Result without unicows.lib:

195 cycles
563 cycles
455 cycles


Result with unicows.lib:

198 cycles
563 cycles
455 cycles


The run to run variation was typically plus or minus one cycle, but the call to GetModuleFileNameW consistently took slightly longer with unicows.lib.

eschew obfuscation

KSS

Hi, MichaelW!
I make my own loader for "UnicoWS.dll" because:

  • I need simple debug (Try debug with unicows.lib :toothy)
  • With my own loader I can use any similar project (Projects that free)

I have almost written it. (I have some understand trouble with IMAGE_IMPORT_DESCRIPTOR and IMAGE_THUNK_DATA)

KSS

#13
I wrote my own loader for "UnicoWS.DLL"  :toothy

If somebody interest this — please test this loader in:

  • Windows 95
  • Windows 98
  • Windows Me (I tested it in this OS, but I want be confident that it work normal)


Anybody know that user32.MessageBoxW in WinMe works OK???
I looked in unicows.MessageBoxW and found that it use user32.MessageBoxW :eek

[attachment deleted by admin]

Mark Jones

#14
Quote from: MichaelW on April 25, 2006, 11:30:01 PM
Linking with the unicows.lib from the PSDK turned out to be easier than I thought it would be...

I can't get your app to compile properly Michael. It's as if the unicows.lib is not being recognized at all, the build size is always 4kb. I've tried the v7.xx and 6.15 ML and Link with many options to no avail. Does it have to be assembled on a 9x platform or use some other obscure link options? Example attached.

EDIT: corrected makeit.bat.

[attachment deleted by admin]
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08