📄 protogen.bat
字号:
; fdwAnsiUnicode: -1 Enum all symbols
; FF_SYM_ANSI Enum only ANSI symbols
; FF_SYM_UNICODE Enum only UNICODE symbols
and edi, 0
mov esi, pSymEntries
assume esi:ptr SYM_ENTRY
.if fdwAnsiUnicode == -1
xor ebx, ebx
.while ebx < uNumberOfSymbols
mov eax, [esi].ccUndecSymbolNameLength
.if edi < eax
mov edi, eax
.endif
inc ebx ; next symbol
add esi, sizeof SYM_ENTRY
.endw
.else
xor ebx, ebx
.while ebx < uNumberOfSymbols
mov eax, fdwAnsiUnicode
.if [esi].dwFlags & eax ; enum only appropriate symbols
mov eax, [esi].ccUndecSymbolNameLength
.if edi < eax
mov edi, eax
.endif
.endif
inc ebx ; next symbol
add esi, sizeof SYM_ENTRY
.endw
.endif
mov eax, edi
ret
GetMaxSymbolNameLenght endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; GenerateBanner
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
GenerateBanner proc uses esi edi ebx pBanner:LPSTR, cb:UINT
lea esi, g_szCommentedLine
mov ebx, sizeof g_szCommentedLine
mov edi, g_pIncludeCurrent
NewLine edi
invoke fCopyMemory, edi, esi, ebx
add edi, ebx
invoke fCopyMemory, edi, pBanner, cb
add edi, cb
invoke fCopyMemory, edi, esi, ebx
add edi, ebx
NewLine edi
mov g_pIncludeCurrent, edi
ret
GenerateBanner endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; DbgPrintSymbolsInfo
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
IFDEF DEBUG
DbgPrintSymbolsInfo proc uses esi edi ebx dwCC:DWORD
local buffer[1024]:CHAR
local uNumOfSymbols:UINT
local uPrintedSymbols:UINT
local uLeftMarguinToUndecSymbol:UINT
; Use it to print all symbols of paticular cc
and uPrintedSymbols, 0
invoke PrintConsole, $CTA0("\n;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n\n"), 0
invoke PrintConsole, $CTA0("Indx Header Flags ImpType Name Type Pars Symbol\n"), 0
lea esi, g_paCcEntries
assume esi:ptr CC_ENTRY
mov eax, dwCC
push [esi][eax*(sizeof CC_ENTRY)].uNumEntries
pop uNumOfSymbols
mov esi, [esi][eax*(sizeof CC_ENTRY)].pSymEntries
assume esi:nothing
assume esi:ptr SYM_ENTRY
xor ebx, ebx
.while ebx < uNumOfSymbols
; Index of symbol in the library
invoke wsprintf, addr buffer, $CTA0("%04u "), [esi].uIndex
invoke lstrcpy, addr g_acDebugMessage, addr buffer
; RVA to symbol's IMAGE_ARCHIVE_MEMBER_HEADER
mov eax, [esi].pMemberHeader
sub eax, g_pLibraryImage ; VA -> RVA
invoke wsprintf, addr buffer, $CTA0("%08X "), eax
invoke lstrcat, addr g_acDebugMessage, addr buffer
; FF_SYM_XXX
mov edi, [esi].dwFlags
shl edi, 32-4 ; used flags
; FF_SYM_VARIABLE equ 00000008 ; symbol is possibly a variable not a function
shl edi, 1
.if CARRY?
invoke lstrcat, addr g_acDebugMessage, $CTA0("V")
.else
invoke lstrcat, addr g_acDebugMessage, $CTA0("-")
.endif
; FF_SYM___IMP_ equ 00000004 ; symbol has prepending '__imp_'
shl edi, 1
.if CARRY?
invoke lstrcat, addr g_acDebugMessage, $CTA0("I")
.else
invoke lstrcat, addr g_acDebugMessage, $CTA0("-")
.endif
; FF_SYM_UNICODE equ 00000002 ; symbol has 'W' at the very end of its name
shl edi, 1
.if CARRY?
invoke lstrcat, addr g_acDebugMessage, $CTA0("W")
.else
invoke lstrcat, addr g_acDebugMessage, $CTA0("-")
.endif
; FF_SYM_ANSI equ 00000001 ; symbol has 'A' at the very end of its name
shl edi, 1
.if CARRY?
invoke lstrcat, addr g_acDebugMessage, $CTA0("A")
.else
invoke lstrcat, addr g_acDebugMessage, $CTA0("-")
.endif
; Import Type
comment ^
IMPORT_CODE 0 The import is executable code.
IMPORT_DATA 1 The import is data.
IMPORT_CONST 2 The import was specified as CONST in the .def file.
ImpType
CODE
DATA
CONST
^
.if [esi].byImportType == IMPORT_CODE
invoke lstrcat, addr g_acDebugMessage, $CTA0(" CODE ")
.elseif [esi].byImportType == IMPORT_DATA
invoke lstrcat, addr g_acDebugMessage, $CTA0(" DATA ")
.elseif [esi].byImportType == IMPORT_CONST
invoke lstrcat, addr g_acDebugMessage, $CTA0(" CONST ")
.else
invoke lstrcat, addr g_acDebugMessage, $CTA0(" ")
.endif
; Import Name Type
comment ^
IMPORT_ORDINAL 0 The import is by ordinal. This indicates that the value in the Ordinal/Hint field of the Import Header is the import's ordinal. If this constant is not specified, then the Ordinal/Hint field should always be interpreted as the import's hint.
IMPORT_NAME 1 The import name is identical to the public symbol name.
IMPORT_NAME_NOPREFIX 2 The import name is the public symbol name, but skipping the leading ?, @, or optionally _.
IMPORT_NAME_UNDECORATE 3 The import name is the public symbol name, but skipping the leading ?, @, or optionally _, and truncating at the first @.
Name Type
ORDINAL
NAME
NAME_NOPREF
NAME_UNDEC
^
.if [esi].byImportNameType == IMPORT_ORDINAL
invoke lstrcat, addr g_acDebugMessage, $CTA0("ORDINAL ")
.elseif [esi].byImportNameType == IMPORT_ORDINAL
invoke lstrcat, addr g_acDebugMessage, $CTA0("NAME ")
.elseif [esi].byImportNameType == IMPORT_NAME_NOPREFIX
invoke lstrcat, addr g_acDebugMessage, $CTA0("NAME_NOPREF ")
.elseif [esi].byImportNameType == IMPORT_NAME_UNDECORATE
invoke lstrcat, addr g_acDebugMessage, $CTA0("NAME_UNDEC ")
.else
invoke lstrcat, addr g_acDebugMessage, $CTA0(" ")
.endif
; Number of accepting by function parameters or -1 if not recognized
invoke wsprintf, addr buffer, $CTA0("%02d "), [esi].uNumberOfParameters
invoke lstrcat, addr g_acDebugMessage, addr buffer
invoke lstrlen, addr g_acDebugMessage
mov uLeftMarguinToUndecSymbol, eax
; Print name as is
mov edi, [esi].pSymbolName
.if [esi].dwFlags & FF_SYM___IMP_
sub edi, sizeof g_sz__imp_ - 1
.endif
invoke lstrcat, addr g_acDebugMessage, edi
invoke PrintConsole, addr g_acDebugMessage, 0
invoke PrintConsole, $CTA0("\n"), 0
; Print undecorated name
mov ecx, [esi].pUndecSymbolNameStart
sub ecx, [esi].pSymbolName
.if [esi].dwFlags & FF_SYM___IMP_
add ecx, sizeof g_sz__imp_ - 1
.endif
add ecx, uLeftMarguinToUndecSymbol
lea edi, g_acDebugMessage
mov al, ' '
db 0F3h, 0AAh ; repe stosb
push esi
mov ecx, [esi].ccUndecSymbolNameLength ; num of chars of undecorated symbol name.
mov esi, [esi].pUndecSymbolNameStart ; VA to the beginning of undecorated symbol name
db 0F3h, 0A4h ; repe movsb
mov byte ptr [edi], 0 ; terminate with zero
pop esi
invoke PrintConsole, addr g_acDebugMessage, 0
invoke PrintConsole, $CTA0("\n"), 0
inc uPrintedSymbols
inc ebx
add esi, sizeof SYM_ENTRY
.endw
assume esi:nothing
invoke wsprintf, addr g_acDebugMessage, $CTA0("\n%u symbols\n"), uPrintedSymbols
invoke PrintConsole, addr g_acDebugMessage, 0
invoke PrintConsole, $CTA0("\n;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n\n"), 0
ret
DbgPrintSymbolsInfo endp
ENDIF
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; GenerateProtoStdCall
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
GenerateProtoStdCall proc uses esi edi ebx pSymEntries:PTR SYM_ENTRY, uNumberOfSymbols:UINT
IFDEF DEBUG
local uPrintedSymbols:UINT
ENDIF
local uProtoMargin:UINT
local acMessage[256]:CHAR
.if uNumberOfSymbols != 0
; write banner
invoke GenerateBanner, \
$CTA(";: STDCALL ::\n", g_szStdCallProtoBanner), sizeof g_szStdCallProtoBanner
; mov g_pIncludeCurrent, eax ; update the pointer
.else
Fix
ret
.endif
IFDEF DEBUG
and uPrintedSymbols, 0
ENDIF
mov esi, pSymEntries
assume esi:ptr SYM_ENTRY
invoke GetMaxSymbolNameLenght, esi, uNumberOfSymbols, -1
mov uProtoMargin, eax
Fix
; invoke Sort, esi, uNumberOfSymbols, CC_STDCALL
xor ebx, ebx
.while ebx < uNumberOfSymbols
Fix make it possible to generate __imp_ protos
.if [esi].dwFlags & FF_SYM___IMP_
; skip this symbol
jmp @F ; continue
.endif
IFDEF DEBUG
; invoke DbgPrintImportTypes, [esi][ebx*(sizeof SYM_ENTRY)].pSymbolName, [esi][ebx*(sizeof SYM_ENTRY)].dwFlagsAndIndex
ENDIF
IFDEF GENERATE_INVOKE
Fix Generate invoke only for masm
invoke fCopyMemory, g_pIncludeCurrent, addr g_szInvoke, sizeof g_szInvoke
add g_pIncludeCurrent, sizeof g_szInvoke
ENDIF
; Write undecorated symbol name
invoke fCopyMemory, g_pIncludeCurrent, [esi].pUndecSymbolNameStart, [esi].ccUndecSymbolNameLength
mov eax, [esi].ccUndecSymbolNameLength
add g_pIncludeCurrent, eax
; fill with spaces untill proto margin
mov eax, uProtoMargin
sub eax, [esi].ccUndecSymbolNameLength
IFNDEF GENERATE_INVOKE
; not sure we need to do this check here but who cares...
.if !SIGN?
push eax
invoke fFillMemory, g_pIncludeCurrent, eax, ' '
pop eax
add g_pIncludeCurrent, eax
.endif
ENDIF
; write proto
IFNDEF GENERATE_INVOKE
invoke fCopyMemory, g_pIncludeCurrent, $CTA(" proto stdcall", g_szProtoStdCall), sizeof g_szProtoStdCall
add g_pIncludeCurrent, sizeof g_szProtoStdCall
ENDIF
mov edi, [esi].uNumberOfParameters
.if edi == -1
invoke fCopyMemory, g_pIncludeCurrent, $CTA(" ; Weird number of parameters\:", g_szWeirdNumParams), sizeof g_szWeirdNumParams
add g_pIncludeCurrent, sizeof g_szWeirdNumParams
IFDEF DEBUG
invoke wsprintf, addr g_acDebugMessage, \
$CTA0("\n%u stdcall symbols has weird number of parameters = %d\n\n"), \
uPrintedSymbols, [esi].uNumberOfParameters
invoke PrintConsole, addr g_acDebugMessage, 0
ENDIF
.elseif edi > 0
.while edi > 0
IFDEF GENERATE_INVOKE
invoke fCopyMemory, g_pIncludeCurrent, addr g_szZero, sizeof g_szZero
add g_pIncludeCurrent, sizeof g_szDWORD
ELSE
invoke fCopyMemory, g_pIncludeCurrent, $CTA(" :DWORD,", g_szDWORD), sizeof g_szDWORD
add g_pIncludeCurrent, sizeof g_szDWORD
ENDIF
dec edi
.endw
IFNDEF GENERATE_INVOKE
sub g_pIncludeCurrent, 1 ; remove trailing ","
ENDIF
.endif
.if [esi].dwFlags & FF_SYM_VARIABLE
invoke fCopyMemory, g_pIncludeCurrent, addr g_szExportedVariable, sizeof g_szExportedVariable
add g_pIncludeCurrent, sizeof g_szExportedVariable
.endif
NewLine g_pIncludeCurrent
IFDEF DEBUG
inc uPrintedSymbols
ENDIF
;IFDEF DEBUG
; .else
; invoke wsprintf, addr g_acDebugMessage, $CTA0("Skip: %s\n"), [esi].pSymbolName
; invoke PrintConsole, addr g_acDebugMessage, 0
;ENDIF
; .endif
@@:
add esi, sizeof SYM_ENTRY
inc ebx ; next symbol
.endw
IFDEF DEBUG
; Print how many symbols were prototyped
invoke wsprintf, addr g_acDebugMessage, $CTA0("\nProtos for %u stdcall symbols generated\n\n"), uPrintedSymbols
invoke PrintConsole, addr g_acDebugMessage, 0
ENDIF
Fix
; invoke GenerateEquationsStdCall, pSymEntries, uNumberOfSymbols
ret
GenerateProtoStdCall endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; GenerateProtoCDecl
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
GenerateProtoCDecl proc uses esi edi ebx pSymEntries:PTR SYM_ENTRY, uNumberOfSymbols:UINT
IFDEF DEBUG
local uPrintedSymbols:UINT
ENDIF
local uProtoMargin:UINT
local acMessage[256]:CHAR
.if uNumberOfSymbols != 0
; write banner
invoke GenerateBanner, \
$CTA(";: CDECL ::\n", g_szCDeclProtoBanner), sizeof g_szCDeclProtoBanner
; mov g_pIncludeCurrent, eax ; update the pointer
.else
Fix
ret
.endif
IFDEF DEBUG
and uPrintedSymbols, 0
ENDIF
mov esi, pSymEntries
assume esi:ptr SYM_ENTRY
invoke GetMaxSymbolNameLenght, esi, uNumberOfSymbols, -1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -