source: trunk/tools/database/APIImport.cpp@ 6752

Last change on this file since 6752 was 6678, checked in by bird, 24 years ago

reverse prev rev.

File size: 14.6 KB
Line 
1/* $Id: APIImport.cpp,v 1.12 2001-09-07 10:31:42 bird Exp $ */
2/*
3 *
4 * APIImport - imports a DLL or Dll-.def with functions into the Odin32 database.
5 *
6 * Copyright (c) 1999-2000 knut st. osmundsen
7 *
8 */
9
10
11/*******************************************************************************
12* Header Files *
13*******************************************************************************/
14#include <os2.h>
15#include <stdio.h>
16#include <string.h>
17
18#include "APIImport.h"
19#include "kFile.h"
20#include "kInterfaces.h"
21#include "kFileFormatBase.h"
22#include "kFilePE.h"
23#include "kFileDef.h"
24#include "db.h"
25
26
27/*******************************************************************************
28* Global Variables *
29*******************************************************************************/
30static FILE *phLog = NULL;
31
32/*******************************************************************************
33* Internal Functions *
34*******************************************************************************/
35static void syntax(void);
36static void openLog(void);
37static void closeLog(void);
38static long processFile(const char *pszFilename, const POPTIONS pOptions, long &cFunctions);
39static void demangle(char *pszDemangled, const char *pszMangledName);
40
41
42/**
43 * Main function.
44 * @returns low word : number of errors
45 * high word: flags.
46 * @param argc Argument count.
47 * @param argv Argument array.
48 */
49int main(int argc, char **argv)
50{
51 int argi;
52 BOOL fFatal = FALSE;
53 long lRc = 0;
54 OPTIONS options = {0};
55 char *pszHost = "localhost";
56 char *pszDatabase = "Odin32";
57 char *pszUser = "root";
58 char *pszPasswd = "";
59 long cFunctions = 0;
60
61
62 /**************************************************************************
63 * parse arguments.
64 * options: -h or -? help
65 * -o[+|-] ordinals, o- ignore them, o+ import them (def).
66 * -d:<dbname> Database name
67 * -p:<passwd> Password
68 * -u:<user> Userid
69 * -h:<host> Hostname/IP-address
70 * -e[+|-] Erase functions which wasn't found.
71 **************************************************************************/
72 if (argc == 1)
73 syntax();
74 argi = 1;
75 while (argi < argc && !fFatal)
76 {
77 if(argv[argi][0] == '-' || argv[argi][0] == '/')
78 {
79 switch (argv[argi][1])
80 {
81 case 'd':
82 case 'D':
83 if (argv[argi][2] == ':')
84 pszDatabase = &argv[argi][3];
85 else
86 fprintf(stderr, "warning: option '-d:' requires database name.\n");
87 break;
88
89 case 'e': /* erase */
90 case 'E':
91 options.fErase = argv[argi][2] != '-';
92 break;
93
94 case 'h':
95 case 'H':
96 if (argv[argi][2] == ':')
97 {
98 pszHost = &argv[argi][3];
99 break;
100 }
101 case '?':
102 syntax();
103 return 0;
104
105 case 'o': /* ordinals*/
106 case 'O':
107 options.fIgnoreOrdinals = argv[argi][2] != '-';
108 break;
109
110 case 'p':
111 case 'P':
112 if (argv[argi][2] == ':')
113 pszPasswd = &argv[argi][3];
114 else
115 fprintf(stderr, "warning: option '-p:' requires password.\n");
116 break;
117
118 case 'u':
119 case 'U':
120 if (argv[argi][2] == ':')
121 pszUser = &argv[argi][3];
122 else
123 fprintf(stderr, "error: option '-u:' requires userid.\n");
124 break;
125
126 default:
127 fprintf(stderr, "incorrect parameter. (argi=%d, argv[argi]=%s)\n", argi, argv[argi]);
128 fFatal = TRUE;
129 break;
130 }
131 }
132 else
133 {
134 long l;
135 if (phLog == NULL)
136 openLog();
137 /* try connect to db */
138 if (dbConnect(pszHost, pszUser, pszPasswd, pszDatabase))
139 {
140 l = processFile(argv[argi], &options, cFunctions);
141 lRc = ((lRc & 0xffff0000UL) | (l & 0xffff0000UL)) | ((lRc & 0x0000ffffUL) + l & 0x0000ffffUL);
142 dbDisconnect();
143 }
144 else
145 {
146 fprintf(phLog, "Could not connect to database (Odin32). \n\terror description: %s\n", dbGetLastErrorDesc());
147 l = 0x00010001;
148 lRc = ((lRc & 0xffff0000UL) | (l & 0xffff0000UL)) | ((lRc & 0x0000ffffUL) + l & 0x0000ffffUL);
149 break;
150 }
151 }
152 argi++;
153 }
154
155 /* write function count */
156 if (phLog != NULL)
157 fprintf(phLog, "\n %d functions were imported!\n\n", cFunctions);
158
159 /* close the log */
160 closeLog();
161
162 /* warn if error during processing. */
163 if (!fFatal && lRc > 0)
164 fprintf(stderr, "%s did occur during the processing. Please check the log file. lRc=0x%08lx\n",
165 (0x0000FFFFL & lRc) > 1 ? "Errors" : "An error", lRc);
166 return (int)lRc;
167}
168
169
170
171/**
172 * Display syntax/help .
173 */
174static void syntax()
175{
176 printf("\n"
177 "APIImport v%01d.%02d - Odin32 API Database utility\n"
178 "----------------------------------------------\n"
179 "syntax: APIImport.exe [-h|-?] [options] <dll/defnames>\n"
180 "\n"
181 " -h or -? Syntax help. (this)\n"
182 " -o[+|-] Ordinals, '+' imports (default), '-' ignores.\n"
183 " -h:<hostname> Database server hostname. default: localhost\n"
184 " -u:<username> Username on the server. default: root\n"
185 " -p:<password> Password. default: <empty>\n"
186 " -d:<database> Database to use. default: Odin32\n"
187 " -e[+|-] Erase functions which wasn't found.\n"
188 " default: -e-\n"
189 " dll/defnames List of DLL/Defs to process.\n"
190 "\n"
191 "Note. Options may be switched on and off between dlls.\n"
192 "\n"
193 "\n"
194 "This utility will insert or update the 'dll' and 'function' tables in the\n"
195 "database. It read a PE-DLL or a OS/2 Definition file (.Def). From the file\n"
196 "it imports the:\n"
197 "\t1) module name\n"
198 "\t2) function name\n"
199 "\t3) function ordinal (If not option 'o-' is specified.)\n"
200 "\n"
201 "Copyright (c) 1999-2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)",
202 MAJOR_VER, MINOR_VER
203 );
204}
205
206
207/**
208 * Opens the log file.
209 * @remark If open fails stderr is used.
210 */
211static void openLog(void)
212{
213 if (phLog == NULL)
214 {
215 phLog = fopen("APIImport.Log", "w");
216 if (phLog == NULL)
217 {
218 fprintf(stderr,"error occured while opening log file - will use stderr instead.\n");
219 phLog = stderr;
220 }
221 }
222}
223
224
225/**
226 * Closes log file.
227 */
228static void closeLog(void)
229{
230 if (phLog != stderr && phLog != NULL)
231 fclose(phLog);
232}
233
234
235/**
236 * Processes a file using the given options. Transparently processes .Def's and PE DLLs
237 * @returns low word, number of errors.
238 * high word, flags (currently not flags are defined/used).
239 * @param pszFilename Pointer to the filename of the file which is to be processed.
240 * @param pOptions Pointer to the options-struct.
241 * @param cFunctions Function count which is to be updated when functions are imported.
242 */
243static long processFile(const char *pszFilename, const POPTIONS pOptions, long &cFunctions)
244{
245 long lRc = 1;
246
247 /* try open file */
248 try
249 {
250 kFile * pInFile = new kFile(pszFilename);
251
252 try
253 {
254 kFileFormatBase * pFileBase = NULL;
255 kExportI * pExportFile;
256 kModuleI * pModuleFile;
257 char achDataBuffer[0x200];
258 char *pszModuleName = &achDataBuffer[0];
259 signed long lDll;
260
261 /* try create file objects */
262 try
263 {
264 kFilePE *pFile = new kFilePE(pInFile);
265 pExportFile = pFile;
266 pModuleFile = pFile;
267 pFileBase = pFile;
268 }
269 catch (int i)
270 {
271 i = i;
272 kFileDef *pFile = new kFileDef(pInFile);
273 pExportFile = pFile;
274 pModuleFile = pFile;
275 pFileBase = pFile;
276 }
277
278 if (pModuleFile->moduleGetName(pszModuleName))
279 {
280 int cch = strlen(pszModuleName);
281
282 /* remove '.dll' */
283 if (cch > 4 && !stricmp(&pszModuleName[cch-4], ".dll"))
284 pszModuleName[cch-4] = '\0';
285 fprintf(phLog, "%s: modulename = %s\n", pszFilename, pszModuleName);
286
287 /* find or insert module name */
288 if ((lDll = dbCheckInsertDll(pszModuleName, DLL_ODIN32_API)) >= 0)
289 {
290 BOOL fClearUpdateOk = FALSE;
291 BOOL fOk;
292 kExportEntry export;
293
294 /* Clear the update flag for all functions in this DLL. */
295 if (pOptions->fErase)
296 fClearUpdateOk = dbClearUpdateFlagFunction(lDll, FALSE);
297
298 lRc = 0;
299 fOk = pExportFile->exportFindFirst(&export);
300 while (fOk)
301 {
302 /* check if name or not */
303 if (!pFileBase->isDef() || export.ulOrdinal < ORD_START_INTERNAL_FUNCTIONS)
304 {
305 char szIntName[256];
306 char szName[256];
307
308 /* exported name */
309 if (export.achName == '\0')
310 sprintf(&szName[0], "Ordinal%04ld", export.ulOrdinal);
311 else
312 demangle(&szName[0], &export.achName[0]);
313
314 /* internal name */
315 if (export.achIntName[0] == '\0')
316 demangle(&szIntName[0], &szName[0]);
317 else
318 demangle(&szIntName[0], export.achIntName);
319
320 fprintf(phLog, "%s: %08ld %-30s %s\n",
321 pszFilename, export.ulOrdinal, &szName[0], &szIntName[0]);
322
323 /* length test */
324 if (strlen(szIntName) > 100)
325 {
326 fprintf(phLog, "%s: error - intname is too long (%d). %s\n", pszFilename, strlen(szIntName), szIntName);
327 lRc++;
328 }
329 else if (strlen(szName) > 100)
330 {
331 fprintf(phLog, "%s: error - name is too long (%d). %s\n", pszFilename, strlen(szName), szName);
332 lRc++;
333 }
334 else
335 { /* Update Database */
336 fOk = dbInsertUpdateFunction(lDll,
337 &szName[0],
338 &szIntName[0],
339 export.ulOrdinal,
340 pOptions->fIgnoreOrdinals && export.ulOrdinal != 0xffffffffUL,
341 FUNCTION_ODIN32_API
342 );
343 if (fOk)
344 cFunctions++;
345 else
346 {
347 fprintf(phLog, "%s: error - dbInsertUpdateFunction failed.\n\terror description: %s \n",
348 pszFilename, dbGetLastErrorDesc());
349 lRc++;
350 }
351 }
352 }
353
354 /* next */
355 fOk = pExportFile->exportFindNext(&export);
356 }
357
358 /* Clear the update flag for all functions in this DLL. */
359 if (fClearUpdateOk && pOptions->fErase)
360 if (!dbDeleteNotUpdatedFunctions(lDll, FALSE))
361 {
362 fprintf(phLog, "%s: error - dbDeleteNotUpdatedFunctions failed.\n\terror description: %s\n",
363 pszFilename, dbGetLastErrorDesc());
364 lRc += 1;
365 }
366 }
367 else
368 fprintf(phLog, "%s: error - could not find/insert module name (%s).\n", pszFilename, pszModuleName);
369 }
370 else
371 fprintf(phLog, "%s: error - could not get module name.\n", pszFilename);
372
373 if (pFileBase)
374 delete(pFileBase);
375 }
376 catch (int err)
377 {
378 fprintf(phLog, "%s: error - could not map dll/def into memory, errorno=%d.\n", pszFilename, err);
379 }
380 }
381 catch (int err)
382 {
383 fprintf(phLog, "%s: error - could not open file, errorno=%d.\n", pszFilename, err);
384 }
385
386 /* close db */
387 dbDisconnect();
388
389 return lRc;
390}
391
392
393/**
394 * Demangles stdcall functions.
395 * @param pszDemangled Pointer to buffer which will hold the demangled name upon return.
396 * @param pszMangledName Mangled name
397 */
398static void demangle(char *pszDemangled, const char *pszMangledName)
399{
400 int iEnd;
401 /* check for @ */
402 iEnd = strlen(pszMangledName);
403 if (iEnd-- > 3 && *pszMangledName == '_')
404 {
405 while ((pszMangledName[iEnd] >= '0' && pszMangledName[iEnd] <= '9') && iEnd > 0)
406 iEnd--;
407 if (pszMangledName[iEnd] == '@')
408 {
409 *pszDemangled = '\0';
410 strncat(pszDemangled, pszMangledName+1, iEnd - 1);
411 return;
412 }
413 }
414
415 /* not stdcall */
416 strcpy(pszDemangled, pszMangledName);
417}
418
Note: See TracBrowser for help on using the repository browser.