Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

391 lines
9.3 KiB

  1. #include "windows.h"
  2. #include "windowsx.h"
  3. #include "shlwapi.h"
  4. #include "commctrl.h"
  5. #include "comctrlp.h"
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #define VERSION TEXT("0.00")
  9. #define SIZEOF(x) sizeof(x)
  10. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  11. typedef struct
  12. {
  13. WORD wOrdinal;
  14. LPTSTR pFunction;
  15. } EXPORTENTRY, * LPEXPORTENTRY;
  16. //
  17. // read a line, skipping leading and trailing white space and placing the output
  18. // into the specified buffer.
  19. //
  20. LPTSTR _ReadLine(LPTSTR pSource, LPTSTR pBuffer, INT cchBuffer)
  21. {
  22. //
  23. // skip leading white space
  24. //
  25. *pBuffer = TEXT('\0');
  26. while ( (*pSource == TEXT(' ')) ||
  27. (*pSource == TEXT('\t')) )
  28. {
  29. pSource++;
  30. }
  31. if ( !*pSource )
  32. return NULL;
  33. while ( (*pSource != TEXT('\r')) &&
  34. (*pSource != TEXT('\n')) &&
  35. (*pSource != TEXT('\0')) &&
  36. (cchBuffer >= 1) )
  37. {
  38. *pBuffer++ = *pSource++;
  39. cchBuffer--;
  40. }
  41. *pBuffer++ = TEXT('\0');
  42. while ( (*pSource == TEXT('\r')) ||
  43. (*pSource == TEXT('\n')) )
  44. {
  45. pSource++;
  46. }
  47. return pSource;
  48. }
  49. //
  50. // Get string element, given an index into the buffer copy out the element
  51. // that we want.
  52. //
  53. BOOL _GetStringElement(LPTSTR pString, INT index, BOOL fEntireLine, LPTSTR pBuffer, INT cchBuffer)
  54. {
  55. for ( ; *pString && (index > 0) ; index-- )
  56. {
  57. while ( *pString != TEXT(',') && *pString != TEXT('\0') )
  58. pString++;
  59. if ( *pString == TEXT(',') )
  60. pString++;
  61. }
  62. if ( index )
  63. return FALSE;
  64. while ( *pString == TEXT(' ') )
  65. pString++;
  66. while ( *pString && (cchBuffer > 1) )
  67. {
  68. if ( !fEntireLine && (*pString == TEXT(',')) )
  69. break;
  70. *pBuffer++ = *pString++;
  71. cchBuffer--;
  72. }
  73. *pBuffer = TEXT('\0');
  74. return TRUE;
  75. }
  76. //
  77. // Get a stub function name given its module and function name.
  78. //
  79. static TCHAR szStubFunction[MAX_PATH];
  80. LPTSTR _GetStubFunction(LPTSTR pModule, LPTSTR pFunction)
  81. {
  82. wnsprintf(szStubFunction, ARRAYSIZE(szStubFunction), TEXT("_%s_%s"), pModule, pFunction);
  83. return szStubFunction;
  84. }
  85. //
  86. // Generate stub
  87. //
  88. // This takes a line from the file and get the information we need from it.
  89. //
  90. BOOL _GenerateStub(LPTSTR pModule, LPTSTR pBuffer, HDPA hdpaFunctions, HDPA hdpaOrdinals)
  91. {
  92. TCHAR szResultType[MAX_PATH];
  93. TCHAR szResult[MAX_PATH];
  94. TCHAR szFunction[MAX_PATH];
  95. TCHAR szArguments[MAX_PATH*2];
  96. LPTSTR pFunction;
  97. LPTSTR pOrdinal;
  98. INT iByName, iByOrdinal;
  99. LPEXPORTENTRY pExport;
  100. // get the fields, all are required
  101. if ( !_GetStringElement(pBuffer, 0, FALSE, szResultType, ARRAYSIZE(szResultType)) )
  102. return FALSE;
  103. if ( !_GetStringElement(pBuffer, 1, FALSE, szResult, ARRAYSIZE(szResult)) )
  104. return FALSE;
  105. if ( !_GetStringElement(pBuffer, 2, FALSE, szFunction, ARRAYSIZE(szFunction)) )
  106. return FALSE;
  107. if ( !_GetStringElement(pBuffer, 3, TRUE, szArguments, ARRAYSIZE(szArguments)) )
  108. return FALSE;
  109. // if the function name is bla@4 then it has an ordinal therefore we must attempt
  110. // to get the ordinal number.
  111. pOrdinal = StrChr(szFunction, TEXT('@'));
  112. if ( pOrdinal )
  113. *pOrdinal++ = TEXT('\0');
  114. // allocate an export, adding both the ordinals and the functions as required.
  115. // if pOrdinal != NULL then we assume that we should parse the int.
  116. pExport = LocalAlloc(LPTR, SIZEOF(EXPORTENTRY));
  117. if ( !pExport )
  118. return FALSE;
  119. Str_SetPtr(&pFunction, szFunction);
  120. if ( !pFunction )
  121. {
  122. LocalFree(pExport);
  123. return FALSE;
  124. }
  125. pExport->wOrdinal = (WORD) StrToInt(pOrdinal ? pOrdinal:TEXT(""));
  126. pExport->pFunction = pFunction;
  127. iByOrdinal = iByName = DPA_AppendPtr(hdpaFunctions, pExport);
  128. if ( pOrdinal )
  129. iByOrdinal = DPA_AppendPtr(hdpaOrdinals, pExport);
  130. if ( (iByName == -1) || (iByOrdinal == -1) )
  131. {
  132. if ( iByName != -1 )
  133. DPA_DeletePtr(hdpaFunctions, iByName);
  134. LocalFree(pExport);
  135. Str_SetPtr(&pFunction, NULL);
  136. return FALSE;
  137. }
  138. // spew out the function name
  139. printf(TEXT("\n"));
  140. printf(TEXT("%s %s%s\n"), szResultType, _GetStubFunction(pModule, pFunction), szArguments);
  141. printf(TEXT("{\n"));
  142. if ( szResult[0] )
  143. printf(TEXT(" return %s;\n"), szResult);
  144. printf(TEXT("}\n"));
  145. return TRUE;
  146. }
  147. //
  148. // "stubgen <stub list> <module>"
  149. //
  150. // The stub list is a text file that lists all the exports you want to generate
  151. // stubs for, each stub is a simple function which returns a specified result.
  152. //
  153. // The format of the file is:
  154. //
  155. // <result type>,<result>,<function>,<arguments>
  156. //
  157. // eg:
  158. //
  159. // BOOL, FALSE, SHBrowseForContainer, (bla, bla, bla)
  160. //
  161. // Which generates a stub:
  162. //
  163. // BOOL SHBrowseForContainer(bla, bla, bla)
  164. // {
  165. // return FALSE;
  166. // }
  167. //
  168. INT _SortNameCB(LPVOID p1, LPVOID p2, LPARAM lParam)
  169. {
  170. LPEXPORTENTRY pExport1 = (LPEXPORTENTRY)p1;
  171. LPEXPORTENTRY pExport2 = (LPEXPORTENTRY)p2;
  172. return StrCmpI(pExport1->pFunction, pExport2->pFunction);
  173. }
  174. INT _SortOrdinalCB(LPVOID p1, LPVOID p2, LPARAM lParam)
  175. {
  176. LPEXPORTENTRY pExport1 = (LPEXPORTENTRY)p1;
  177. LPEXPORTENTRY pExport2 = (LPEXPORTENTRY)p2;
  178. return pExport1->wOrdinal - pExport2->wOrdinal;
  179. }
  180. INT __cdecl main(INT cArgs, LPTSTR pArgs[])
  181. {
  182. TCHAR szSource[MAX_PATH];
  183. TCHAR szModule[MAX_PATH];
  184. HANDLE hFile;
  185. LPTSTR pStubFile;
  186. DWORD dwSize, dwRead;
  187. HDPA hdpaFunctions;
  188. HDPA hdpaOrdinals;
  189. INT i;
  190. if ( cArgs < 2 )
  191. {
  192. printf(TEXT("stubgen: <src> <module>\n"));
  193. return -1;
  194. }
  195. StrCpy(szSource, pArgs[1]);
  196. StrCpy(szModule, pArgs[2]);
  197. //
  198. // load the source file into memory and then lets generate the stub table,
  199. // add a TCHAR to the file size to get it null terminated
  200. //
  201. hFile = CreateFile(szSource,
  202. GENERIC_READ,
  203. FILE_SHARE_READ,
  204. NULL,
  205. OPEN_EXISTING,
  206. FILE_ATTRIBUTE_NORMAL,
  207. NULL);
  208. if ( hFile == INVALID_HANDLE_VALUE )
  209. return -1;
  210. dwSize = GetFileSize(hFile, NULL);
  211. pStubFile = LocalAlloc(LPTR, dwSize+SIZEOF(TCHAR));
  212. if ( !pStubFile ||
  213. !ReadFile(hFile, pStubFile, dwSize, &dwRead, NULL) ||
  214. dwRead != dwSize )
  215. {
  216. CloseHandle(hFile);
  217. return -1;
  218. }
  219. CloseHandle(hFile);
  220. //
  221. // Create the DPA we will use for storing the function names
  222. //
  223. hdpaFunctions = DPA_Create(16);
  224. hdpaOrdinals = DPA_Create(16);
  225. if ( !hdpaFunctions || ! hdpaOrdinals )
  226. return -1;
  227. //
  228. // output header information
  229. //
  230. for ( i = 3 ; i < cArgs ; i++ )
  231. printf(TEXT("#include \"%s\"\n"), pArgs[i]);
  232. printf(TEXT("#pragma hdrstop\n"));
  233. printf(TEXT("\n"));
  234. printf(TEXT("// Generate from %s by stubgen.exe\n"), szSource);
  235. printf(TEXT("// *** DO NOT EDIT THIS FILE ***\n\n"));
  236. //
  237. // now lets parse the file, trying to the function prototypes from it,
  238. // we skip all lines that start with a ';', '#' or '/' (as in //)
  239. //
  240. while ( pStubFile )
  241. {
  242. TCHAR szBuffer[1024];
  243. pStubFile = _ReadLine(pStubFile, szBuffer, ARRAYSIZE(szBuffer));
  244. if ( pStubFile )
  245. {
  246. switch ( szBuffer[0] )
  247. {
  248. case TEXT('#'):
  249. case TEXT(';'):
  250. case TEXT('/'):
  251. // comments are stripped
  252. break;
  253. default:
  254. _GenerateStub(szModule, szBuffer, hdpaFunctions, hdpaOrdinals);
  255. break;
  256. }
  257. }
  258. }
  259. //
  260. // if hdpaFunctions contains anything then we have generated a set of
  261. // stubs, so lets sort it and output that.
  262. //
  263. if ( DPA_GetPtrCount(hdpaFunctions) )
  264. {
  265. DPA_Sort(hdpaFunctions, _SortNameCB, 0);
  266. printf(TEXT("\n"));
  267. printf(TEXT("const INT g_c%sExportTable = %d;\n"), szModule, DPA_GetPtrCount(hdpaFunctions));
  268. printf(TEXT("const EXPORTTABLE g_%sExportTable[] =\n"), szModule);
  269. printf(TEXT("{\n"));
  270. for ( i = 0 ; i < DPA_GetPtrCount(hdpaFunctions); i++ )
  271. {
  272. LPEXPORTENTRY pExport = (LPEXPORTENTRY)DPA_GetPtr(hdpaFunctions, i);
  273. TCHAR szBuffer[MAX_PATH];
  274. StrCpy(szBuffer, pExport->pFunction);
  275. #if UNICODE
  276. _wcslwr(szBuffer);
  277. #else
  278. _strlwr(szBuffer);
  279. #endif
  280. printf(TEXT(" \"%s\", (FARPROC)%s,\n"), szBuffer, _GetStubFunction(szModule, pExport->pFunction));
  281. }
  282. printf(TEXT("};\n"));
  283. }
  284. if ( DPA_GetPtrCount(hdpaOrdinals) )
  285. {
  286. DPA_Sort(hdpaFunctions, _SortOrdinalCB, 0);
  287. printf(TEXT("\n"));
  288. printf(TEXT("const INT g_c%sOrdinalTable = %d;\n"), szModule, DPA_GetPtrCount(hdpaOrdinals));
  289. printf(TEXT("const ORDINALTABLE g_%sOrdinalTable[] =\n"), szModule);
  290. printf(TEXT("{\n"));
  291. for ( i = 0 ; i < DPA_GetPtrCount(hdpaOrdinals); i++ )
  292. {
  293. LPEXPORTENTRY pExport = (LPEXPORTENTRY)DPA_GetPtr(hdpaOrdinals, i);
  294. printf(TEXT(" %d, (FARPROC)%s,\n"), pExport->wOrdinal, _GetStubFunction(szModule, pExport->pFunction));
  295. }
  296. printf(TEXT("};\n"));
  297. }
  298. return 0;
  299. }