Author Topic: Module/Process32First/Next Revisited  (Read 5195 times)

dedndave

  • Member
  • *****
  • Posts: 8827
  • Still using Abacus 2.0
    • DednDave
Module/Process32First/Next Revisited
« on: August 22, 2015, 12:56:21 PM »
The Masm32 package has an issue with the Module32First, Module32Next, Process32First, and Process32Next API's.
It has been discussed and resolved in previous threads, namely this one from the old forum...

http://www.masmforum.com/board/index.php?topic=18294

Description of the Problem...

The issue is the way the functions are defined, as opposed to the way most other API functions are defined.
Let's use MessageBox as an example (representative of most API's)

In user32.lib, MessageBox is defined as (2) functions, an ANSI version, and a UNICODE version:
Code: [Select]
MessageBoxA
MessageBoxW

When Hutch added UNICODE support to the Masm32 package, he did so by use of the __UNICODE__ symbol.
If the __UNICODE__ symbol is not defined, the ANSI version of the function is used for MessageBox.
If the __UNICODE__ symbol is defined, the UNICODE version of the function is used for MessageBox.

Code: [Select]
MessageBoxA PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
IFNDEF __UNICODE__
  MessageBox equ <MessageBoxA>
ENDIF

MessageBoxW PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
IFDEF __UNICODE__
  MessageBox equ <MessageBoxW>
ENDIF

This is great for nearly all the windows API functions.
If you write a UNICODE app, you define the __UNICODE__ symbol (usually with an EQU).
Now, when you call MessageBox, the UNICODE version is used.
If you write a UNICODE app, but want to use the ANSI version, you can override the selection by using MessageBoxA.
Conversely, if you write an ANSI app, but want to use the UNICODE version, you can override by using MessageBoxW.

Unfortunately, microsoft "messed up" on the ANSI/UNICODE naming convention on the 4 functions we are interested in.
This probably wasn't really a mistake, as much as a chronological change, allowing for backward compatibility.
For these 4 functions, the ANSI version has no "A" at the end.
This caused problems when creating the INC's and LIB's in the Masm32 package.
For one thing, there is no Module32FirstA, Module32NextA, Process32FirstA, or Process32NextA.
As a result, the ANSI version of these functions did not get pulled into the kernel32.lib or kernl32p.lib DEF files.

In the include files, Hutch has prototyped these functions like so...

Code: [Select]
Module32FirstW PROTO STDCALL :DWORD,:DWORD

IFDEF __UNICODE__
  Module32First equ <Module32FirstW>
ENDIF

Compare this with the MessageBox example above, and you'll see that there is no ANSI prototype to work with.
To further complicate the problem, if you elect to define the __UNICODE__ symbol,
the name, "Module32First" is unavailable for use in the ANSI form.

Soultion, the libraries....

These 4 functions are found in both kernel32.lib and kernl32p.lib, from the masm32\lib folder.
Attached are the 2 updated libraries, that were created using Erol's lib2def and def2lib tools.
For each LIB, a DEF file was created, the 4 functions were added, then those DEF files were used to create new LIB's.
I prefer to rename the old LIB's, in the event of some problem, then replace them with the updated ones.
Or, you can just delete the old LIB's.
As an added advantage, the newer LIB's are considerably smaller than the original ones.
Erol's tool uses a compact form for imports.

Now, for the include files....

Kernel32.inc and kernl32p.inc are found in the masm32\include folder.
I have not attached modified files. Instead, I leave it to you to decide what best suits your needs.
In the previous forum threads, a number of methods were mentioned.
Some of them weren't viable (including some of my own).
At the end of the day, you may have wound up using something like this...

Code: [Select]
Module32FirstW PROTO   :DWORD,:DWORD

IFDEF __UNICODE__
  Module32First  TEXTEQU <Module32FirstW>
ELSE
  Module32First  PROTO   :DWORD,:DWORD
ENDIF

This works fairly well.
But, if you write a UNICODE app, you cannot override to get the ANSI version.

I propose a different solution, that allows override in both ANSI and UNICODE apps...

Code: [Select]
Module32First  PROTO   :DWORD,:DWORD
Module32FirstW PROTO   :DWORD,:DWORD
Module32FirstA TEXTEQU <Module32First>

IFDEF __UNICODE__
  _Module32First  TEXTEQU <Module32FirstW>
ELSE
  _Module32First  TEXTEQU <Module32First>
ENDIF

We proceed the name with an underscore, as we have done for other naming conflicts.

I am open to suggestions   :P

jj2007

  • Member
  • *****
  • Posts: 10651
  • Assembler is fun ;-)
    • MasmBasic
Re: Module/Process32First/Next Revisited
« Reply #1 on: August 22, 2015, 07:07:25 PM »
Your solution is consistent and covers all cases :t
Question is only how to ensure that users know about it. Maybe this:
Code: [Select]
Module32First MACRO args:VARARG
  echo ### no such function, use _Module32First instead ###
ENDM

dedndave

  • Member
  • *****
  • Posts: 8827
  • Still using Abacus 2.0
    • DednDave
Re: Module/Process32First/Next Revisited
« Reply #2 on: August 22, 2015, 07:48:03 PM »
not a bad thought   :biggrin:

well, except you'd get symbol redefinition

jj2007

  • Member
  • *****
  • Posts: 10651
  • Assembler is fun ;-)
    • MasmBasic
Re: Module/Process32First/Next Revisited
« Reply #3 on: August 22, 2015, 08:03:25 PM »
well, except you'd get symbol redefinition

If it's not defined elsewhere, the assembler won't know it yet. The libs are the linker's job.

dedndave

  • Member
  • *****
  • Posts: 8827
  • Still using Abacus 2.0
    • DednDave
Re: Module/Process32First/Next Revisited
« Reply #4 on: August 23, 2015, 09:55:57 AM »
i don't know how you would

Code: [Select]
Module32First  PROTO   :DWORD,:DWORD
Module32FirstW PROTO   :DWORD,:DWORD

then turn around and assign a macro to the same symbol
you can't alias the name and prototype it with the same directive (that would be cool)
and, you can't really change the name of a library module

jj2007

  • Member
  • *****
  • Posts: 10651
  • Assembler is fun ;-)
    • MasmBasic
Re: Module/Process32First/Next Revisited
« Reply #5 on: August 23, 2015, 04:59:19 PM »
and, you can't really change the name of a library module

You are probably right. Visual Basic (and MB Declare) allow such aliases, but I wouldn't know how to do it with the Masm toolset.