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

Last change on this file since 3947 was 3882, checked in by bird, 25 years ago

Corrections and handling of the updated field in function and file.

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