ReactOS 0.4.15-dev-7788-g1ad9096
createspec.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <dbghelp.h>
Include dependency graph for createspec.c:

Go to the source code of this file.

Classes

struct  _EXPORT
 
struct  _EXPORT_DATA
 

Macros

#define _NO_CVCONST_H
 
#define MAX_PARAMETERS   64
 

Typedefs

typedef enum CV_call_e CV_call_e
 
typedef enum _PARAM_TYPES PARAM_TYPES
 
typedef enum _PARAM_TYPESPPARAM_TYPES
 
typedef struct _EXPORT EXPORT
 
typedef struct _EXPORTPEXPORT
 
typedef struct _EXPORT_DATA EXPORT_DATA
 
typedef struct _EXPORT_DATAPEXPORT_DATA
 

Enumerations

enum  BasicType {
  btNoType = 0 , btVoid = 1 , btChar = 2 , btWChar = 3 ,
  btInt = 6 , btUInt = 7 , btFloat = 8 , btBCD = 9 ,
  btBool = 10 , btLong = 13 , btULong = 14 , btCurrency = 25 ,
  btDate = 26 , btVariant = 27 , btComplex = 28 , btBit = 29 ,
  btBSTR = 30 , btHresult = 31 , btNoType = 0 , btVoid = 1 ,
  btChar = 2 , btWChar = 3 , btInt = 6 , btUInt = 7 ,
  btFloat = 8 , btBCD = 9 , btBool = 10 , btLong = 13 ,
  btULong = 14 , btCurrency = 25 , btDate = 26 , btVariant = 27 ,
  btComplex = 28 , btBit = 29 , btBSTR = 30 , btHresult = 31 ,
  btNoType = 0 , btVoid = 1 , btChar = 2 , btWChar = 3 ,
  btInt = 6 , btUInt = 7 , btFloat = 8 , btBCD = 9 ,
  btBool = 10 , btLong = 13 , btULong = 14 , btCurrency = 25 ,
  btDate = 26 , btVariant = 27 , btComplex = 28 , btBit = 29 ,
  btBSTR = 30 , btHresult = 31 , btNoType = 0 , btVoid = 1 ,
  btChar = 2 , btWChar = 3 , btInt = 6 , btUInt = 7 ,
  btFloat = 8 , btBCD = 9 , btBool = 10 , btLong = 13 ,
  btULong = 14 , btCurrency = 25 , btDate = 26 , btVariant = 27 ,
  btComplex = 28 , btBit = 29 , btBSTR = 30 , btHresult = 31 ,
  btChar16 = 32 , btChar32 = 33
}
 
enum  CV_call_e {
  CV_CALL_NEAR_C , CV_CALL_FAR_C , CV_CALL_NEAR_PASCAL , CV_CALL_FAR_PASCAL ,
  CV_CALL_NEAR_FAST , CV_CALL_FAR_FAST , CV_CALL_SKIPPED , CV_CALL_NEAR_STD ,
  CV_CALL_FAR_STD , CV_CALL_NEAR_SYS , CV_CALL_FAR_SYS , CV_CALL_THISCALL ,
  CV_CALL_MIPSCALL , CV_CALL_GENERIC , CV_CALL_ALPHACALL , CV_CALL_PPCCALL ,
  CV_CALL_SHCALL , CV_CALL_ARMCALL , CV_CALL_AM33CALL , CV_CALL_TRICALL ,
  CV_CALL_SH5CALL , CV_CALL_M32RCALL , CV_CALL_RESERVED , CV_CALL_NEAR_C = 0x00 ,
  CV_CALL_NEAR_FAST = 0x04 , CV_CALL_NEAR_STD = 0x07 , CV_CALL_NEAR_SYS = 0x09 , CV_CALL_THISCALL = 0x0b ,
  CV_CALL_CLRCALL = 0x16 , CV_CALL_NEAR_C , CV_CALL_FAR_C , CV_CALL_NEAR_PASCAL ,
  CV_CALL_FAR_PASCAL , CV_CALL_NEAR_FAST , CV_CALL_FAR_FAST , CV_CALL_SKIPPED ,
  CV_CALL_NEAR_STD , CV_CALL_FAR_STD , CV_CALL_NEAR_SYS , CV_CALL_FAR_SYS ,
  CV_CALL_THISCALL , CV_CALL_MIPSCALL , CV_CALL_GENERIC , CV_CALL_ALPHACALL ,
  CV_CALL_PPCCALL , CV_CALL_SHCALL , CV_CALL_ARMCALL , CV_CALL_AM33CALL ,
  CV_CALL_TRICALL , CV_CALL_SH5CALL , CV_CALL_M32RCALL , CV_CALL_RESERVED
}
 
enum  _PARAM_TYPES {
  TYPE_NONE , TYPE_LONG , TYPE_DOUBLE , TYPE_PTR ,
  TYPE_STR , TYPE_WSTR
}
 

Functions

void error (_In_ const char *pszFormat,...)
 
BOOL InitDbgHelp (VOID)
 
HMODULE LoadModuleWithSymbolsFullPath (_In_ PSTR pszFullModuleFileName)
 
HMODULE LoadModuleWithSymbols (_In_ PSTR pszModuleName)
 
HRESULT GetExportsFromFile (_In_ HMODULE hmod, _Out_ PEXPORT_DATA *ppExportData)
 
BOOL CALLBACK EnumParametersCallback (_In_ PSYMBOL_INFO pSymInfo, _In_ ULONG SymbolSize, _In_ PVOID UserContext)
 
ULONG64 GetFunctionFromForwarder (_In_ PCSTR pszForwarder)
 
HRESULT ParseImageSymbols (_In_ HMODULE hmod, _Inout_ PEXPORT_DATA pExportData)
 
const CHARGetCallingConvention (_In_ PEXPORT pExport)
 
HRESULT CreateSpecFile (_In_ PCSTR pszSpecFile, _In_ PEXPORT_DATA pExportData)
 
int main (int argc, char *argv[])
 

Variables

const chargapszTypeStrings []
 
HANDLE ghProcess
 

Macro Definition Documentation

◆ _NO_CVCONST_H

#define _NO_CVCONST_H

Definition at line 30 of file createspec.c.

◆ MAX_PARAMETERS

#define MAX_PARAMETERS   64

Definition at line 88 of file createspec.c.

Typedef Documentation

◆ CV_call_e

◆ EXPORT

◆ EXPORT_DATA

◆ PARAM_TYPES

◆ PEXPORT

typedef struct _EXPORT * PEXPORT

◆ PEXPORT_DATA

◆ PPARAM_TYPES

Enumeration Type Documentation

◆ _PARAM_TYPES

Enumerator
TYPE_NONE 
TYPE_LONG 
TYPE_DOUBLE 
TYPE_PTR 
TYPE_STR 
TYPE_WSTR 

Definition at line 67 of file createspec.c.

68{
enum _PARAM_TYPES * PPARAM_TYPES
@ TYPE_DOUBLE
Definition: createspec.c:71
@ TYPE_NONE
Definition: createspec.c:69
@ TYPE_STR
Definition: createspec.c:73
@ TYPE_PTR
Definition: createspec.c:72
@ TYPE_LONG
Definition: createspec.c:70
@ TYPE_WSTR
Definition: createspec.c:74
enum _PARAM_TYPES PARAM_TYPES

◆ BasicType

Enumerator
btNoType 
btVoid 
btChar 
btWChar 
btInt 
btUInt 
btFloat 
btBCD 
btBool 
btLong 
btULong 
btCurrency 
btDate 
btVariant 
btComplex 
btBit 
btBSTR 
btHresult 
btNoType 
btVoid 
btChar 
btWChar 
btInt 
btUInt 
btFloat 
btBCD 
btBool 
btLong 
btULong 
btCurrency 
btDate 
btVariant 
btComplex 
btBit 
btBSTR 
btHresult 
btNoType 
btVoid 
btChar 
btWChar 
btInt 
btUInt 
btFloat 
btBCD 
btBool 
btLong 
btULong 
btCurrency 
btDate 
btVariant 
btComplex 
btBit 
btBSTR 
btHresult 
btNoType 
btVoid 
btChar 
btWChar 
btInt 
btUInt 
btFloat 
btBCD 
btBool 
btLong 
btULong 
btCurrency 
btDate 
btVariant 
btComplex 
btBit 
btBSTR 
btHresult 
btChar16 
btChar32 

Definition at line 34 of file createspec.c.

34 {
35 btNoType = 0,
36 btVoid = 1,
37 btChar = 2,
38 btWChar = 3,
39 btInt = 6,
40 btUInt = 7,
41 btFloat = 8,
42 btBCD = 9,
43 btBool = 10,
44 btLong = 13,
45 btULong = 14,
46 btCurrency = 25,
47 btDate = 26,
48 btVariant = 27,
49 btComplex = 28,
50 btBit = 29,
51 btBSTR = 30,
52 btHresult = 31
53};
@ btVoid
Definition: createspec.c:36
@ btVariant
Definition: createspec.c:48
@ btBCD
Definition: createspec.c:42
@ btBSTR
Definition: createspec.c:51
@ btUInt
Definition: createspec.c:40
@ btULong
Definition: createspec.c:45
@ btLong
Definition: createspec.c:44
@ btChar
Definition: createspec.c:37
@ btBit
Definition: createspec.c:50
@ btNoType
Definition: createspec.c:35
@ btDate
Definition: createspec.c:47
@ btComplex
Definition: createspec.c:49
@ btBool
Definition: createspec.c:43
@ btInt
Definition: createspec.c:39
@ btCurrency
Definition: createspec.c:46
@ btHresult
Definition: createspec.c:52
@ btWChar
Definition: createspec.c:38
@ btFloat
Definition: createspec.c:41

◆ CV_call_e

Enumerator
CV_CALL_NEAR_C 
CV_CALL_FAR_C 
CV_CALL_NEAR_PASCAL 
CV_CALL_FAR_PASCAL 
CV_CALL_NEAR_FAST 
CV_CALL_FAR_FAST 
CV_CALL_SKIPPED 
CV_CALL_NEAR_STD 
CV_CALL_FAR_STD 
CV_CALL_NEAR_SYS 
CV_CALL_FAR_SYS 
CV_CALL_THISCALL 
CV_CALL_MIPSCALL 
CV_CALL_GENERIC 
CV_CALL_ALPHACALL 
CV_CALL_PPCCALL 
CV_CALL_SHCALL 
CV_CALL_ARMCALL 
CV_CALL_AM33CALL 
CV_CALL_TRICALL 
CV_CALL_SH5CALL 
CV_CALL_M32RCALL 
CV_CALL_RESERVED 
CV_CALL_NEAR_C 
CV_CALL_NEAR_FAST 
CV_CALL_NEAR_STD 
CV_CALL_NEAR_SYS 
CV_CALL_THISCALL 
CV_CALL_CLRCALL 
CV_CALL_NEAR_C 
CV_CALL_FAR_C 
CV_CALL_NEAR_PASCAL 
CV_CALL_FAR_PASCAL 
CV_CALL_NEAR_FAST 
CV_CALL_FAR_FAST 
CV_CALL_SKIPPED 
CV_CALL_NEAR_STD 
CV_CALL_FAR_STD 
CV_CALL_NEAR_SYS 
CV_CALL_FAR_SYS 
CV_CALL_THISCALL 
CV_CALL_MIPSCALL 
CV_CALL_GENERIC 
CV_CALL_ALPHACALL 
CV_CALL_PPCCALL 
CV_CALL_SHCALL 
CV_CALL_ARMCALL 
CV_CALL_AM33CALL 
CV_CALL_TRICALL 
CV_CALL_SH5CALL 
CV_CALL_M32RCALL 
CV_CALL_RESERVED 

Definition at line 55 of file createspec.c.

55 {
56 CV_CALL_NEAR_C = 0x00,
57 CV_CALL_NEAR_FAST = 0x04,
58 CV_CALL_NEAR_STD = 0x07,
59 CV_CALL_NEAR_SYS = 0x09,
60 CV_CALL_THISCALL = 0x0b,
61 CV_CALL_CLRCALL = 0x16
62} CV_call_e;
CV_call_e
Definition: createspec.c:55
@ CV_CALL_NEAR_STD
Definition: createspec.c:58
@ CV_CALL_NEAR_FAST
Definition: createspec.c:57
@ CV_CALL_NEAR_SYS
Definition: createspec.c:59
@ CV_CALL_THISCALL
Definition: createspec.c:60
@ CV_CALL_NEAR_C
Definition: createspec.c:56
@ CV_CALL_CLRCALL
Definition: createspec.c:61

Function Documentation

◆ CreateSpecFile()

HRESULT CreateSpecFile ( _In_ PCSTR  pszSpecFile,
_In_ PEXPORT_DATA  pExportData 
)

Definition at line 664 of file createspec.c.

667{
668 FILE *file;
669 ULONG i, p;
670 PEXPORT pExport;
671
672 /* Create the spec file */
673 if (fopen_s(&file, pszSpecFile, "w") != 0)
674 {
675 error("Failed to open spec file: '%s'\n", pszSpecFile);
676 return E_FAIL;
677 }
678
679 /* Loop all exports */
680 for (i = 0; i < pExportData->cNumberOfExports; i++)
681 {
682 pExport = &pExportData->aExports[i];
683
684 fprintf(file, "%lu %s ", i + 1, GetCallingConvention(pExport));
685 //if (pExport->fNoName)
686 if (pExport->pszName == NULL)
687 {
688 fprintf(file, "-noname ");
689 }
690
691 if (pExport->pszName != NULL)
692 {
693 fprintf(file, "%s", pExport->pszName);
694 }
695 else if (pExport->pszSymbol != NULL)
696 {
697 fprintf(file, "%s", pExport->pszSymbol);
698 }
699 else
700 {
701 fprintf(file, "NamelessExport_%lu", i);
702 }
703
704 if (!pExport->fData)
705 {
706 fprintf(file, "(");
707 for (p = 0; p < pExport->cParameters; p++)
708 {
709 fprintf(file, "%s", gapszTypeStrings[pExport->aeParameters[p]]);
710 if ((p + 1) < pExport->cParameters)
711 {
712 fprintf(file, " ");
713 }
714 }
715 fprintf(file, ")");
716 }
717
718 if (pExport->pszForwarder != NULL)
719 {
720 fprintf(file, " %s", pExport->pszForwarder);
721 }
722
723 fprintf(file, "\n");
724 }
725
726 fclose(file);
727
728 return S_OK;
729}
const CHAR * GetCallingConvention(_In_ PEXPORT pExport)
Definition: createspec.c:635
const char * gapszTypeStrings[]
Definition: createspec.c:78
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
#define S_OK
Definition: intsafe.h:52
#define error(str)
Definition: mkdosfs.c:1605
int CDECL fopen_s(FILE **pFile, const char *filename, const char *mode)
Definition: file.c:3257
ULONG fData
Definition: createspec.c:98
PSTR pszSymbol
Definition: createspec.c:92
PSTR pszName
Definition: createspec.c:91
PSTR pszForwarder
Definition: createspec.c:93
PARAM_TYPES aeParameters[MAX_PARAMETERS]
Definition: createspec.c:100
ULONG cParameters
Definition: createspec.c:99
Definition: fci.c:127
uint32_t ULONG
Definition: typedefs.h:59

Referenced by main().

◆ EnumParametersCallback()

BOOL CALLBACK EnumParametersCallback ( _In_ PSYMBOL_INFO  pSymInfo,
_In_ ULONG  SymbolSize,
_In_ PVOID  UserContext 
)

Definition at line 377 of file createspec.c.

381{
382 PEXPORT pExport = (PEXPORT)UserContext;
383 enum SymTagEnum eSymTag;
384 enum BasicType eBaseType;
385 DWORD dwTypeIndex;
386 ULONG64 ullLength;
387
388 /* If it's not a parameter, skip it */
389 if (!(pSymInfo->Flags & SYMFLAG_PARAMETER))
390 {
391 return TRUE;
392 }
393
394 /* Count this parameter */
395 pExport->cParameters++;
396
397 /* Get the type for the parameter */
399 pSymInfo->ModBase,
400 pSymInfo->TypeIndex,
402 &eSymTag))
403 {
404 switch (eSymTag)
405 {
406 case SymTagUDT:
407 case SymTagBaseType:
408
409 /* Try to get the size */
411 pSymInfo->ModBase,
412 pSymInfo->TypeIndex,
414 &ullLength))
415 {
416 if (ullLength > 8)
417 {
418 /* That is probably not possible */
419 __debugbreak();
420 }
421
422 if (ullLength > 4)
423 {
424 /* 'double' type */
425 pExport->aeParameters[pExport->cParameters - 1] = TYPE_DOUBLE;
426 break;
427 }
428 }
429
430 /* Default to 'long' type */
431 pExport->aeParameters[pExport->cParameters - 1] = TYPE_LONG;
432 break;
433
434 case SymTagEnum:
435 /* 'long' type */
436 pExport->aeParameters[pExport->cParameters - 1] = TYPE_LONG;
437 break;
438
440 /* 'ptr' type */
441 pExport->aeParameters[pExport->cParameters - 1] = TYPE_PTR;
442
443 /* Try to get the underlying type */
445 pSymInfo->ModBase,
446 pSymInfo->TypeIndex,
448 &dwTypeIndex))
449 {
450 /* Try to get the base type */
452 pSymInfo->ModBase,
453 dwTypeIndex,
455 &eBaseType))
456 {
457 /* Check for string types */
458 if (eBaseType == btChar)
459 {
460 /* 'str' type */
461 pExport->aeParameters[pExport->cParameters - 1] = TYPE_STR;
462 }
463 else if (eBaseType == btWChar)
464 {
465 /* 'wstr' type */
466 pExport->aeParameters[pExport->cParameters - 1] = TYPE_WSTR;
467 }
468 }
469 }
470 break;
471
472 default:
473 printf("Unhandled eSymTag: %u\n", eSymTag);
474 return FALSE;
475 }
476 }
477 else
478 {
479 printf("Could not get type info. Fallig back to ptr\n");
480 pExport->aeParameters[pExport->cParameters - 1] = TYPE_PTR;
481 }
482
483 return TRUE;
484}
HANDLE ghProcess
Definition: createspec.c:109
struct _EXPORT * PEXPORT
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define SYMFLAG_PARAMETER
Definition: compat.h:999
@ TI_GET_LENGTH
Definition: compat.h:1417
@ TI_GET_SYMTAG
Definition: compat.h:1415
@ TI_GET_TYPEID
Definition: compat.h:1419
@ TI_GET_BASETYPE
Definition: compat.h:1420
SymTagEnum
Definition: compat.h:1580
@ SymTagPointerType
Definition: compat.h:1595
@ SymTagBaseType
Definition: compat.h:1597
@ SymTagUDT
Definition: compat.h:1592
BasicType
Definition: compat.h:1616
BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase, ULONG TypeId, IMAGEHLP_SYMBOL_TYPE_INFO GetType, PVOID pInfo)
Definition: type.c:900
unsigned long DWORD
Definition: ntddk_ex.h:95
#define printf
Definition: freeldr.h:93
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
unsigned __int64 ULONG64
Definition: imports.h:198

Referenced by ParseImageSymbols().

◆ error()

void error ( _In_ const char pszFormat,
  ... 
)

Definition at line 112 of file createspec.c.

115{
116 CHAR szBuffer[512];
118 DWORD dwLastError;
119 va_list argptr;
120
121 /* Get last error */
122 dwLastError = GetLastError();
123
124 va_start(argptr, pszFormat);
125 cchBuffer = vsprintf_s(szBuffer, sizeof(szBuffer), pszFormat, argptr);
126 va_end(argptr);
127
128 /* Strip trailing newlines */
129 _Analysis_assume_(cchBuffer < sizeof(szBuffer));
130 while ((cchBuffer >= 1) &&
131 ((szBuffer[cchBuffer - 1] == '\r') ||
132 (szBuffer[cchBuffer - 1] == '\n')))
133 {
134 szBuffer[cchBuffer - 1] = '\0';
135 cchBuffer--;
136 }
137
138 /* Check if we have an error */
139 if (dwLastError != ERROR_SUCCESS)
140 {
141 /* Append error code */
142 cchBuffer += sprintf_s(szBuffer + cchBuffer,
143 sizeof(szBuffer) - cchBuffer,
144 " [error %lu: ", dwLastError);
145
146 /* Format the last error code */
148 NULL,
149 dwLastError,
150 0,
151 szBuffer + cchBuffer,
152 (DWORD)(sizeof(szBuffer) - cchBuffer),
153 NULL);
154
155 /* Strip trailing newlines */
156 _Analysis_assume_(cchBuffer < sizeof(szBuffer));
157 while ((cchBuffer >= 1) &&
158 ((szBuffer[cchBuffer - 1] == '\r') ||
159 (szBuffer[cchBuffer - 1] == '\n')))
160 {
161 szBuffer[cchBuffer - 1] = '\0';
162 cchBuffer--;
163 }
164
165 fprintf(stderr, "%s]\n", szBuffer);
166 }
167 else
168 {
169 fprintf(stderr, "%s\n", szBuffer);
170 }
171}
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define ERROR_SUCCESS
Definition: deptool.c:10
static DWORD cchBuffer
Definition: fusion.c:85
DWORD WINAPI FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:483
#define stderr
Definition: stdio.h:100
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
ULONG_PTR SIZE_T
Definition: typedefs.h:80
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:423
char CHAR
Definition: xmlstorage.h:175

◆ GetCallingConvention()

const CHAR * GetCallingConvention ( _In_ PEXPORT  pExport)

Definition at line 635 of file createspec.c.

637{
638 if (pExport->fData)
639 {
640 return "extern";
641 }
642
643#ifndef _M_AMD64
644 switch (pExport->dwCallingConvention)
645 {
646 case CV_CALL_NEAR_C:
647 return "cdecl";
649 return "fastcall";
650 case CV_CALL_NEAR_STD:
651 return "stdcall";
652 case CV_CALL_NEAR_SYS:
653 return "syscall";
654 case CV_CALL_THISCALL:
655 return "thiscall";
656 default:
657 __debugbreak();
658 }
659#endif
660 return "stdcall";
661}

Referenced by CreateSpecFile().

◆ GetExportsFromFile()

HRESULT GetExportsFromFile ( _In_ HMODULE  hmod,
_Out_ PEXPORT_DATA ppExportData 
)

Definition at line 303 of file createspec.c.

306{
307 PBYTE pjImageBase;
308 PIMAGE_EXPORT_DIRECTORY pExportDir;
309 ULONG i, cjExportSize, cFunctions, cjTableSize;
310 PEXPORT_DATA pExportData;
311 PULONG pulAddressTable, pulNameTable;
312 PUSHORT pusOrdinalTable;
313
314 pjImageBase = (PBYTE)hmod;
315
316 /* Get the export directory */
317 pExportDir = ImageDirectoryEntryToData(pjImageBase,
318 TRUE,
320 &cjExportSize);
321 if (pExportDir == NULL)
322 {
323 fprintf(stderr, "Failed to get export directory\n");
324 return E_FAIL;
325 }
326
327 cFunctions = pExportDir->NumberOfFunctions;
328 cjTableSize = FIELD_OFFSET(EXPORT_DATA, aExports[cFunctions]);
329
330 pExportData = malloc(cjTableSize);
331 if (pExportData == NULL)
332 {
333 error("Failed to allocate %u bytes of memory for export table\n", cjTableSize);
334 return E_OUTOFMEMORY;
335 }
336
337 RtlZeroMemory(pExportData, cjTableSize);
338
339 pulAddressTable = (PULONG)(pjImageBase + pExportDir->AddressOfFunctions);
340
341 pExportData->cNumberOfExports = cFunctions;
342
343 /* Loop through the function table */
344 for (i = 0; i < cFunctions; i++)
345 {
346 PVOID pvFunction = (pjImageBase + pulAddressTable[i]);
347
348 /* Check if this is a forwarder */
349 if ((ULONG_PTR)((PUCHAR)pvFunction - (PUCHAR)pExportDir) < cjExportSize)
350 {
351 pExportData->aExports[i].pszForwarder = _strdup(pvFunction);
352 }
353 else
354 {
355 pExportData->aExports[i].ulRva = pulAddressTable[i];
356 }
357 }
358
359 pulNameTable = (PULONG)(pjImageBase + pExportDir->AddressOfNames);
360 pusOrdinalTable = (PUSHORT)(pjImageBase + pExportDir->AddressOfNameOrdinals);
361
362 /* Loop through the name table */
363 for (i = 0; i < pExportDir->NumberOfNames; i++)
364 {
365 ULONG iIndex = pusOrdinalTable[i];
366 PSTR pszName = (PSTR)(pjImageBase + pulNameTable[i]);
367
368 pExportData->aExports[iIndex].pszName = _strdup(pszName);
369 }
370
371 *ppExportData = pExportData;
372 return S_OK;
373}
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define _strdup
Definition: debug_ros.c:7
#define malloc
Definition: debug_ros.c:4
#define IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: compat.h:151
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:143
PVOID WINAPI ImageDirectoryEntryToData(PVOID base, BOOLEAN image, USHORT dir, PULONG size)
Definition: pe_module.c:972
BYTE * PBYTE
Definition: pedump.c:66
EXPORT aExports[1]
Definition: createspec.c:106
ULONG cNumberOfExports
Definition: createspec.c:105
ULONG ulRva
Definition: createspec.c:94
DWORD AddressOfNameOrdinals
Definition: compat.h:167
uint32_t * PULONG
Definition: typedefs.h:59
char * PSTR
Definition: typedefs.h:51
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by main().

◆ GetFunctionFromForwarder()

ULONG64 GetFunctionFromForwarder ( _In_ PCSTR  pszForwarder)

Definition at line 487 of file createspec.c.

489{
491 PCH pchDot, pszName;
492 ULONG64 ullFunction;
494
495 /* Copy the forwarder name */
496 strcpy_s(szDllName, sizeof(szDllName), pszForwarder);
497
498 /* Find the '.' */
499 pchDot = strchr(szDllName, '.');
500 if (pchDot == NULL)
501 {
502 error("Invalid name for forwarder '%s'!", pszForwarder);
503 return 0;
504 }
505
506 /* Terminate DLL name */
507 *pchDot = '\0';
508
509 /* Load the DLL */
511 if (hmod == NULL)
512 {
513 error("Failed to load module for forwarder '%s'!", pszForwarder);
514 return 0;
515 }
516
517 /* Get the function name and check for ordinal */
518 pszName = pchDot + 1;
519 if (pszName[0] == '#')
520 {
521 ULONG iOrdinal = strtoul(pszName + 1, NULL, 10);
522 if ((iOrdinal == 0) || (iOrdinal > 0xFFFF))
523 {
524 error("Got invalid ordinal %u for ''", iOrdinal, pszForwarder);
525 return 0;
526 }
527
528 pszName = (PSTR)(ULONG_PTR)iOrdinal;
529 }
530
531 /* Get the function address */
532 ullFunction = (ULONG_PTR)GetProcAddress(hmod, pszName);
533 if (ullFunction == 0)
534 {
535 error("Failed to resolve '%s' in '%s'.", pchDot + 1, szDllName);
536 return 0;
537 }
538
539 return ullFunction;
540}
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
char * strchr(const char *String, int ch)
Definition: utclib.c:501
HMODULE LoadModuleWithSymbols(_In_ PSTR pszModuleName)
Definition: createspec.c:252
static const WCHAR szDllName[]
Definition: sip.c:61
#define MAX_SYM_NAME
Definition: compat.h:975
#define GetProcAddress(x, y)
Definition: compat.h:753
#define ULONG_PTR
Definition: config.h:101
#define strcpy_s(d, l, s)
Definition: utility.h:200
CHAR * PCH
Definition: ntbasedef.h:391

Referenced by ParseImageSymbols().

◆ InitDbgHelp()

BOOL InitDbgHelp ( VOID  )

Definition at line 174 of file createspec.c.

176{
177 static const char *pszMsSymbolServer = "srv**symbols*http://msdl.microsoft.com/download/symbols";
179
180 /* Save current process ;-) */
182
183 /* Initialize dbghelp */
184 if (!SymInitialize(ghProcess, 0, FALSE))
185 {
186 error("SymInitialize() failed.");
187 return FALSE;
188 }
189
190 /* Set options */
193 Options &= ~SYMOPT_DEFERRED_LOADS;
195
196 /* Test if we can reach the MS symbol server */
197 if (!SymSrvIsStore(ghProcess, pszMsSymbolServer))
198 {
199 error("Failed to connect to symbol server.");
200 return FALSE;
201 }
202
203 /* Set MS symbol server as symbol search path */
204 SymSetSearchPath(ghProcess, pszMsSymbolServer);
205
206 return TRUE;
207}
#define SYMOPT_DEBUG
Definition: dbghelp.h:563
#define SYMOPT_INCLUDE_32BIT_MODULES
Definition: dbghelp.h:545
BOOL WINAPI SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)
Definition: dbghelp.c:534
#define GetCurrentProcess()
Definition: compat.h:759
DWORD WINAPI SymSetOptions(DWORD opts)
Definition: dbghelp.c:585
BOOL WINAPI SymSetSearchPath(HANDLE hProcess, PCSTR searchPath)
Definition: dbghelp.c:263
DWORD WINAPI SymGetOptions(void)
Definition: dbghelp.c:600
BOOL WINAPI SymSrvIsStore(HANDLE hProcess, PCSTR pszPath)
Definition: rosstubs.c:539
#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS
Definition: symdump.c:19
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534

Referenced by main().

◆ LoadModuleWithSymbols()

HMODULE LoadModuleWithSymbols ( _In_ PSTR  pszModuleName)

Definition at line 252 of file createspec.c.

254{
255 CHAR szFullFileName[MAX_PATH];
257
258 /* Check if the file name has a path */
259 if (strchr(pszModuleName, '\\') != NULL)
260 {
261 /* Try as it is */
262 hmod = LoadModuleWithSymbolsFullPath(pszModuleName);
263 if (hmod != NULL)
264 {
265 return hmod;
266 }
267 }
268
269 /* Try current directory */
270 GetCurrentDirectoryA(MAX_PATH, szFullFileName);
271 strcat_s(szFullFileName, sizeof(szFullFileName), "\\");
272 strcat_s(szFullFileName, sizeof(szFullFileName), pszModuleName);
273 hmod = LoadModuleWithSymbolsFullPath(szFullFileName);
274 if (hmod != NULL)
275 {
276 return hmod;
277 }
278
279 /* Try system32 */
280 strcpy_s(szFullFileName, sizeof(szFullFileName), "%systemroot%\\system32\\");
281 strcat_s(szFullFileName, sizeof(szFullFileName), pszModuleName);
282 hmod = LoadModuleWithSymbolsFullPath(szFullFileName);
283 if (hmod != NULL)
284 {
285 return hmod;
286 }
287
288#ifdef _WIN64
289 /* Try SysWOW64 */
290 strcpy_s(szFullFileName, sizeof(szFullFileName), "%systemroot%\\SysWOW64\\");
291 strcat_s(szFullFileName, sizeof(szFullFileName), pszModuleName);
292 hmod = LoadModuleWithSymbolsFullPath(szFullFileName);
293 if (hmod != NULL)
294 {
295 return hmod;
296 }
297#endif // _WIN64
298
299 return NULL;
300}
HMODULE LoadModuleWithSymbolsFullPath(_In_ PSTR pszFullModuleFileName)
Definition: createspec.c:210
#define MAX_PATH
Definition: compat.h:34
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
int CDECL strcat_s(char *dst, size_t elem, const char *src)
Definition: string.c:40

Referenced by GetFunctionFromForwarder(), and main().

◆ LoadModuleWithSymbolsFullPath()

HMODULE LoadModuleWithSymbolsFullPath ( _In_ PSTR  pszFullModuleFileName)

Definition at line 210 of file createspec.c.

212{
214 DWORD64 dwModuleBase;
215
216 /* Load the DLL */
217 hmod = LoadLibraryExA(pszFullModuleFileName,
218 NULL,
222 if (hmod == NULL)
223 {
224 return NULL;
225 }
226
227 /* Load symbols for this module */
228 dwModuleBase = SymLoadModule64(ghProcess,
229 NULL,
230 pszFullModuleFileName,
231 NULL,
233 0);
234 if (dwModuleBase == 0)
235 {
236 /* ERROR_SUCCESS means, we have symbols already */
238 {
239 return NULL;
240 }
241 }
242 else
243 {
244 printf("Successfully loaded symbols for '%s'\n",
245 pszFullModuleFileName);
246 }
247
248 return hmod;
249}
DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
Definition: module.c:878
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:159
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint64_t DWORD64
Definition: typedefs.h:67
#define LOAD_WITH_ALTERED_SEARCH_PATH
Definition: winbase.h:344
#define LOAD_IGNORE_CODE_AUTHZ_LEVEL
Definition: winbase.h:345
#define DONT_RESOLVE_DLL_REFERENCES
Definition: winbase.h:341

Referenced by LoadModuleWithSymbols().

◆ main()

int main ( int argc  ,
char argv[] 
)

Definition at line 731 of file createspec.c.

732{
733 HRESULT hr;
734 CHAR szSpecFile[MAX_PATH];
735 PSTR pszSpecFile;
736 PEXPORT_DATA pExportData;
738
739 /* Check parameters */
740 if ((argc < 2) || !strcmp(argv[1], "/?"))
741 {
742 printf("syntax: createspec <image file> [<spec file>]\n");
743 return 0;
744 }
745
746 /* Check if we have a spec file name */
747 if (argc > 2)
748 {
749 pszSpecFile = argv[2];
750 }
751 else
752 {
753 /* Create spec file name from image file name */
754 PSTR pszStart = strrchr(argv[1], '\\');
755 if (pszStart == 0)
756 pszStart = argv[1];
757
758 strcpy_s(szSpecFile, sizeof(szSpecFile), pszStart);
759 strcat_s(szSpecFile, sizeof(szSpecFile), ".spec");
760 pszSpecFile = szSpecFile;
761 }
762
763 /* Initialize dbghelp.dll */
764 if (!InitDbgHelp())
765 {
766 error("Failed to init dbghelp!\n"
767 "Make sure you have dbghelp.dll and symsrv.dll in the same folder.\n");
768 return E_FAIL;
769 }
770
771 /* Load the file including symbols */
772 printf("Loading symbols for '%s', please wait...\n", argv[1]);
774 if (hmod == NULL)
775 {
776 error("Failed to load module '%s'!", argv[1]);
777 return E_FAIL;
778 }
779
780 /* Get the exports */
781 hr = GetExportsFromFile(hmod, &pExportData);
782 if (!SUCCEEDED(hr))
783 {
784 error("Failed to get exports: %lx\n", hr);
785 return hr;
786 }
787
788 /* Get additional info from symbols */
789 hr = ParseImageSymbols(hmod, pExportData);
790 if (!SUCCEEDED(hr))
791 {
792 error("Failed to get symbol information: hr=%lx\n", hr);
793 }
794
795 /* Write the spec file */
796 hr = CreateSpecFile(pszSpecFile, pExportData);
797
798 printf("Spec file '%s' was successfully written.\n", szSpecFile);
799
800 return hr;
801}
static int argc
Definition: ServiceArgs.c:12
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
HRESULT CreateSpecFile(_In_ PCSTR pszSpecFile, _In_ PEXPORT_DATA pExportData)
Definition: createspec.c:664
HRESULT ParseImageSymbols(_In_ HMODULE hmod, _Inout_ PEXPORT_DATA pExportData)
Definition: createspec.c:543
BOOL InitDbgHelp(VOID)
Definition: createspec.c:174
HRESULT GetExportsFromFile(_In_ HMODULE hmod, _Out_ PEXPORT_DATA *ppExportData)
Definition: createspec.c:303
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define argv
Definition: mplay32.c:18
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
HRESULT hr
Definition: shlfolder.c:183

◆ ParseImageSymbols()

HRESULT ParseImageSymbols ( _In_ HMODULE  hmod,
_Inout_ PEXPORT_DATA  pExportData 
)

Definition at line 543 of file createspec.c.

546{
547 DWORD64 dwModuleBase;
548 ULONG i;
549 IMAGEHLP_STACK_FRAME StackFrame;
551
552 dwModuleBase = (DWORD_PTR)hmod;
553
554 /* Loop through all exports */
555 for (i = 0; i < pExportData->cNumberOfExports; i++)
556 {
557 PEXPORT pExport = &pExportData->aExports[i];
558 ULONG64 ullFunction = dwModuleBase + pExportData->aExports[i].ulRva;
559 ULONG64 ullDisplacement;
560
561 /* Check if this is a forwarder */
562 if (pExport->pszForwarder != NULL)
563 {
564 /* Load the module and get the function address */
565 ullFunction = GetFunctionFromForwarder(pExport->pszForwarder);
566 if (ullFunction == 0)
567 {
568 printf("Failed to get function for forwarder '%s'. Skipping.\n", pExport->pszForwarder);
569 continue;
570 }
571 }
572
573 RtlZeroMemory(&sym, sizeof(sym));
574 sym.si.SizeOfStruct = sizeof(SYMBOL_INFO);
576
577 /* Try to find the symbol */
578 if (!SymFromAddr(ghProcess, ullFunction, &ullDisplacement, &sym.si))
579 {
580 error("Error: SymFromAddr() failed.");
581 continue;
582 }
583
584 /* Get the symbol name */
585 pExport->pszSymbol = _strdup(sym.si.Name);
586
587 /* Check if it is a function */
588 if (sym.si.Tag == SymTagFunction)
589 {
590 /* Get the calling convention */
592 dwModuleBase,
593 sym.si.TypeIndex,
595 &pExport->dwCallingConvention))
596 {
597 /* Fall back to __stdcall */
599 }
600
601 /* Set the context to the function address */
602 RtlZeroMemory(&StackFrame, sizeof(StackFrame));
603 StackFrame.InstructionOffset = ullFunction;
604 if (!SymSetContext(ghProcess, &StackFrame, NULL))
605 {
606 error("SymSetContext failed for i = %u.", i);
607 continue;
608 }
609
610 /* Enumerate all symbols for this function */
612 0, // use SymSetContext
613 NULL,
615 pExport))
616 {
617 error("SymEnumSymbols failed for i = %u.", i);
618 continue;
619 }
620 }
621 else if (sym.si.Tag == SymTagPublicSymbol)
622 {
624 }
625 else if (sym.si.Tag == SymTagData)
626 {
627 pExport->fData = TRUE;
628 }
629 }
630
631 return S_OK;
632}
BOOL CALLBACK EnumParametersCallback(_In_ PSYMBOL_INFO pSymInfo, _In_ ULONG SymbolSize, _In_ PVOID UserContext)
Definition: createspec.c:377
ULONG64 GetFunctionFromForwarder(_In_ PCSTR pszForwarder)
Definition: createspec.c:487
BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, DWORD64 *Displacement, PSYMBOL_INFO Symbol)
Definition: symbol.c:1263
struct _SYMBOL_INFO SYMBOL_INFO
@ TI_GET_CALLING_CONVENTION
Definition: compat.h:1441
@ SymTagFunction
Definition: compat.h:1586
@ SymTagPublicSymbol
Definition: compat.h:1591
@ SymTagData
Definition: compat.h:1588
BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame, PIMAGEHLP_CONTEXT Context)
Definition: dbghelp.c:658
DWORD dwCallingConvention
Definition: createspec.c:95
ULONG64 InstructionOffset
Definition: compat.h:1376
SYMBOL_INFO si
Definition: dbghelp.h:1179
ULONG TypeIndex
Definition: compat.h:1039
ULONG SizeOfStruct
Definition: compat.h:1038
ULONG Tag
Definition: compat.h:1049
CHAR Name[1]
Definition: compat.h:1052
ULONG MaxNameLen
Definition: compat.h:1051
BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask, PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, PVOID UserContext)
Definition: symbol.c:1147
#define DWORD_PTR
Definition: treelist.c:76

Referenced by main().

Variable Documentation

◆ gapszTypeStrings

const char* gapszTypeStrings[]
Initial value:
=
{
"???",
"long",
"double",
"ptr",
"str",
"wstr"
}

Definition at line 78 of file createspec.c.

Referenced by CreateSpecFile().

◆ ghProcess