Leaked source code of windows server 2003
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.

623 lines
16 KiB

  1. //+-----------------------------------------------------------------------------
  2. //
  3. // File logerr.cpp
  4. //
  5. // Contents Error and output logging to avoid broken nmake
  6. // This program reassigns stderr and stdout to two files
  7. // named TMPERR and tmpout, executes a given command and
  8. // appends the error and output messages to logerr.err
  9. // and logerr.log respectively.
  10. //
  11. // Returns 1 (which stops the execution of nmake) only if
  12. // logerr.err is not accesible. All other i/o errors are
  13. // logged to logerr.err.
  14. //
  15. // Author & Date adinas 02/18/98 create file
  16. // adinas 04/15/98 update to the new bingen's error values
  17. // bensont 04/05/00
  18. //
  19. //-------------------------------------------------------------------------------
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <winerror.h>
  23. #include <windows.h>
  24. #include <string.h>
  25. #include "iodll.h"
  26. #include <ntverp.h>
  27. #define LOGFILE "LOGFILE" // The exactly string of the system environment variable name
  28. #define ERRFILE "ERRFILE" // The exactly string of the system environment variable name
  29. #define TEMPEXT ".temp"
  30. #define DEFAULT_LOGFILE "logerr.log" // Default log filename
  31. #define DEFAULT_ERRFILE "logerr.err" // Default err filename
  32. #define MAX_FNAME_LEN MAX_PATH // Maximum length of the log/err filename string
  33. #define MAX_CMD_LEN 2048 // Maximum length of the command-line string
  34. #define LAST_KNOWN_WRN 11 // Maximum warning number known by logerr
  35. #define LAST_KNOWN_ERR 130 // Maximum error number known by logerr
  36. #define IODLL_UNKNOWN 1 // Used for unknown IODLL errors or warning
  37. #define SYSTEM 1 // Used for bingen errors with code > LAST_ERROR
  38. CHAR * pszCmdLine = NULL;
  39. CHAR szCommand[MAX_CMD_LEN];
  40. CHAR szLine[MAX_CMD_LEN];
  41. CHAR szLogfile[MAX_FNAME_LEN]; // Log filename, ex "logerr.log"
  42. CHAR szTempLogfile[MAX_FNAME_LEN + 6]; // Temp Log filename, ex "logerr.err.temp"
  43. CHAR szErrfile[MAX_FNAME_LEN]; // Error filename, ex "logerr.err"
  44. CHAR szTempErrfile[MAX_FNAME_LEN + 6]; // Temp Error filename, ex "logerr.err.temp"
  45. FILE *bak_std_out = stdout; // Backup stdout
  46. FILE *bak_std_err = stderr; // Backup stdin
  47. FILE *out_stream = NULL; // Stream for the new stdout
  48. FILE *out_stream_temp = NULL; // Stream for the new stdout
  49. FILE *err_stream = NULL; // Stream for the err file
  50. FILE *err_stream_temp = NULL; // Stream for the new stderr
  51. int returnval = 0; // Return value
  52. DWORD errorlevel = 0;
  53. BOOL Status;
  54. BOOL bReportError = FALSE;
  55. BOOL bBuildCommand = FALSE;
  56. // Define macros for printing
  57. // fatal error messages (FATAL) at stderr
  58. // fatal error messages (SFATAL) in logerr.log and logerr.err
  59. // error messages (ERRMSG) in logerr.log and logerr.err
  60. // error number (ERRNO) in logerr.log and logerr.err
  61. // warning messages (WRNMSG) in logerr.log
  62. // no messages (NOMSG) in logerr.log
  63. #define FATAL(err,msg) \
  64. fprintf(bak_std_err,"fatal error: %s %s",err,msg); \
  65. returnval=1;
  66. #define SFATAL(err,msg) \
  67. fprintf(bak_std_out,"fatal error: %s %s",err,msg); \
  68. fprintf(bak_std_err,"fatal error: %s %s",err,msg); \
  69. returnval=1;
  70. #define ERRMSG(err,msg) \
  71. fprintf(stderr,"ERROR %s: %s\n",#err,msg); \
  72. fprintf(stdout,"ERROR %s: %s\n",#err,msg);
  73. #define ERRNO(err,msg) \
  74. fprintf(stderr,"ERROR %d: %s\n",err,msg); \
  75. fprintf(stdout,"ERROR %d: %s\n",err,msg);
  76. #define WRNMSG(wrn,msg) \
  77. fprintf(stdout,"WARNING %s: %s\n",#wrn,msg);
  78. #define WRNNO(wrn,msg) \
  79. fprintf(stdout,"WARNING %d: %s\n",wrn,msg);
  80. #define NOMSG(msg) \
  81. fprintf(stdout,"%s\n",msg);
  82. // Print the command preceeded by ERROR or WARNING
  83. // if errorlevel is non zero.
  84. // Use ReportCmdExit for all commands but bingen.
  85. // For bingen, use ReportBingenExit.
  86. int __cdecl ReportCmdExit( INT errorlevel, CHAR* szCmdline );
  87. int __cdecl ReportBingenExit ( INT errorlevel, CHAR* szCmdline );
  88. int __cdecl ReportBuildExit ( INT errorlevel, CHAR* szCmdline );
  89. int __cdecl ReportRsrcExit ( INT errorlevel, CHAR* szCmdline );
  90. void __cdecl strlower(char *s);
  91. char * __cdecl strnchr(char *s, char c);
  92. int __cdecl GetEnvVar(char *envvarname, char *valuebuffer, char *defaultvalue, int bufsize);
  93. void __cdecl AppendDump(FILE *Master, CHAR *Transfile, BOOL bLogError);
  94. //+--------------------------------------------------------------
  95. //
  96. // Function: main
  97. //
  98. //---------------------------------------------------------------
  99. int
  100. __cdecl main(
  101. int argc,
  102. char* argv[] )
  103. {
  104. SSIZE_T len = 0; // The string length of the first item (command) of the command line
  105. // PROCESS_INFORMATION piProcInfo;
  106. // STARTUPINFO siStartInfo;
  107. // If no argument, print the help.
  108. if ( argc !=2 ) goto Help;
  109. pszCmdLine = strnchr(argv[1], ' ');
  110. Help:;
  111. // Provide help for using the tool, if required
  112. if ( argc <= 1 ||
  113. 0 == strcmp( argv[1], "/?" ) ||
  114. 0 == strcmp( argv[1], "-?" ) ||
  115. NULL == pszCmdLine ) {
  116. fprintf( stderr, "Usage:\tlogerr \"<command line>\"\n");
  117. fprintf( stderr, "Ex:\tlogerr \"xcopy /vf c:\\tmp\\myfile.txt .\"\n");
  118. returnval = 1;
  119. goto Error;
  120. }
  121. // Get Environment, LOGFILE, ERRFILE and ComSpec
  122. if ( (GetEnvVar(LOGFILE, szLogfile, DEFAULT_LOGFILE, MAX_FNAME_LEN) == 0) ||
  123. (GetEnvVar(ERRFILE, szErrfile, DEFAULT_ERRFILE, MAX_FNAME_LEN) == 0))
  124. goto Error;
  125. // Evaluate templog filename
  126. strcpy(szTempLogfile, szLogfile);
  127. strcpy(&szTempLogfile[strlen(szTempLogfile)], TEMPEXT);
  128. // Evaluate temperr filename
  129. strcpy(szTempErrfile, szErrfile);
  130. strcpy(&szTempErrfile[strlen(szTempErrfile)], TEMPEXT);
  131. // Prepare the output / error output file handle
  132. if ( (out_stream = fopen( szLogfile, "at")) == NULL) {
  133. FATAL(szLogfile, "Failed to open log file.");
  134. goto Error;
  135. }
  136. if ( (out_stream_temp = freopen(szTempLogfile, "w+t", stdout)) == NULL) {
  137. FATAL(szTempLogfile, "Failed to open temp error file.");
  138. goto Error;
  139. }
  140. if ( (err_stream = fopen(szErrfile, "a+t")) == NULL) {
  141. FATAL(szErrfile, "Failed to open error file.");
  142. goto Error;
  143. }
  144. if ( (err_stream_temp = freopen(szTempErrfile, "w+t", stderr)) == NULL) {
  145. FATAL(szTempErrfile, "Failed to open temp error file.");
  146. goto Error;
  147. }
  148. fseek(out_stream, 0, SEEK_END);
  149. fseek(err_stream, 0, SEEK_END);
  150. // Get the argument as command line (pszCmdLine)
  151. if (strlen(pszCmdLine) >= MAX_CMD_LEN ) { //- default_cmd_len - strlen(buf)
  152. FATAL(pszCmdLine, "The Full Command is too long !!!");
  153. goto Error;
  154. }
  155. // Get the first word as command (szCommand)
  156. len = strchr(pszCmdLine, ' ') - pszCmdLine;
  157. if (len < 0) len = strlen(pszCmdLine);
  158. if (len >= MAX_CMD_LEN) {
  159. FATAL(pszCmdLine,"The First Command is too long !!!");
  160. goto Error;
  161. }
  162. // system to execute the program
  163. strncpy(szCommand, pszCmdLine, len);
  164. strlower(szCommand);
  165. errorlevel=system( pszCmdLine );
  166. if ( strcmp( szCommand, "bingen" ) == 0)
  167. bReportError = ReportBingenExit( errorlevel, pszCmdLine );
  168. else if ( _stricmp( szCommand, "rsrc" ) == 0)
  169. bReportError = ReportRsrcExit( errorlevel, pszCmdLine );
  170. else if ( _stricmp( szCommand, "build" ) == 0) {
  171. bReportError = ReportBuildExit( errorlevel, pszCmdLine );
  172. bBuildCommand = TRUE;
  173. } else
  174. bReportError = ReportCmdExit( errorlevel, pszCmdLine );
  175. // Temp Error file complete, set to err_stream
  176. SetStdHandle(STD_ERROR_HANDLE, err_stream);
  177. if (NULL != err_stream_temp)
  178. fclose(err_stream_temp);
  179. else {
  180. FATAL(szTempErrfile, "Failed to close error file.");
  181. goto Error;
  182. }
  183. // Temp Error file complete, set to err_stream
  184. SetStdHandle(STD_OUTPUT_HANDLE, out_stream);
  185. if (NULL != out_stream_temp)
  186. fclose(out_stream_temp);
  187. else {
  188. FATAL(szTempLogfile, "Failed to close log file.");
  189. goto Error;
  190. }
  191. if (bReportError) {
  192. fprintf(err_stream, "ERROR %d: %s\n", errorlevel, pszCmdLine);
  193. fprintf(out_stream, "ERROR %d: %s\n", errorlevel, pszCmdLine);
  194. } else {
  195. fprintf(out_stream, "%s\n", pszCmdLine);
  196. }
  197. AppendDump(out_stream, szTempLogfile, 0);
  198. if (bBuildCommand)
  199. AppendDump(out_stream, "Build.log", 0);
  200. AppendDump(out_stream, szTempErrfile, 1);
  201. if (bBuildCommand)
  202. AppendDump(err_stream, "Build.err", 1);
  203. Error:
  204. SetStdHandle(STD_ERROR_HANDLE, bak_std_out);
  205. SetStdHandle(STD_OUTPUT_HANDLE, bak_std_err);
  206. if (NULL != err_stream)
  207. fclose(err_stream);
  208. if (NULL != out_stream)
  209. fclose(out_stream);
  210. // Delete the temporary files
  211. _unlink (szTempErrfile);
  212. _unlink (szTempLogfile);
  213. return returnval;
  214. } // main
  215. int
  216. __cdecl ReportBingenExit(
  217. INT errorlevel,
  218. CHAR* szCmdline
  219. ) {
  220. int result=FALSE;
  221. switch (errorlevel) {
  222. case ERROR_NO_ERROR:
  223. // NOMSG(szCmdline);
  224. break;
  225. case ERROR_RW_NO_RESOURCES:
  226. WRNMSG(ERROR_RW_NO_RESOURCES,szCmdline);
  227. break;
  228. case ERROR_RW_VXD_MSGPAGE:
  229. WRNMSG(ERROR_RW_VXD_MSGPAGE,szCmdline);
  230. break;
  231. case ERROR_IO_CHECKSUM_MISMATCH:
  232. WRNMSG(ERROR_IO_CHECKSUM_MISMATCH,szCmdline);
  233. break;
  234. case ERROR_FILE_CUSTOMRES:
  235. WRNMSG(ERROR_FILE_CUSTOMRES,szCmdline);
  236. break;
  237. case ERROR_FILE_VERSTAMPONLY:
  238. WRNMSG(ERROR_FILE_VERSTAMPONLY,szCmdline);
  239. break;
  240. case ERROR_RET_RESIZED:
  241. WRNMSG(ERROR_RET_RESIZED,szCmdline);
  242. break;
  243. case ERROR_RET_ID_NOTFOUND:
  244. WRNMSG(ERROR_RET_ID_NOTFOUND,szCmdline);
  245. break;
  246. case ERROR_RET_CNTX_CHANGED:
  247. WRNMSG(ERROR_RET_CNTX_CHANGED,szCmdline);
  248. break;
  249. case ERROR_RET_INVALID_TOKEN:
  250. WRNMSG(ERROR_RET_INVALID_TOKEN,szCmdline);
  251. break;
  252. case ERROR_RET_TOKEN_REMOVED:
  253. WRNMSG(ERROR_RET_TOKEN_REMOVED,szCmdline);
  254. break;
  255. case ERROR_RET_TOKEN_MISMATCH:
  256. WRNMSG(ERROR_RET_TOKEN_MISMATCH,szCmdline);
  257. break;
  258. case ERROR_HANDLE_INVALID:
  259. ERRMSG(ERROR_HANDLE_INVALID,szCmdline);
  260. result = TRUE;
  261. break;
  262. case ERROR_READING_INI:
  263. ERRMSG(ERROR_READING_INI,szCmdline);
  264. result = TRUE;
  265. break;
  266. case ERROR_NEW_FAILED:
  267. ERRMSG(ERROR_NEW_FAILED,szCmdline);
  268. result = TRUE;
  269. break;
  270. case ERROR_OUT_OF_DISKSPACE:
  271. ERRMSG(ERROR_OUT_OF_DISKSPACE,szCmdline);
  272. result = TRUE;
  273. break;
  274. case ERROR_FILE_OPEN:
  275. ERRMSG(ERROR_FILE_OPEN,szCmdline);
  276. result = TRUE;
  277. break;
  278. case ERROR_FILE_CREATE:
  279. ERRMSG(ERROR_FILE_CREATE,szCmdline);
  280. result = TRUE;
  281. break;
  282. case ERROR_FILE_INVALID_OFFSET:
  283. ERRMSG(ERROR_FILE_INVALID_OFFSET,szCmdline);
  284. result = TRUE;
  285. break;
  286. case ERROR_FILE_READ:
  287. ERRMSG(ERROR_FILE_READ,szCmdline);
  288. result = TRUE;
  289. break;
  290. case ERROR_FILE_WRITE:
  291. ERRMSG(ERROR_FILE_WRITE,szCmdline);
  292. result = TRUE;
  293. break;
  294. case ERROR_DLL_LOAD:
  295. ERRMSG(ERROR_DLL_LOAD,szCmdline);
  296. result = TRUE;
  297. break;
  298. case ERROR_DLL_PROC_ADDRESS:
  299. ERRMSG(ERROR_DLL_PROC_ADDRESS,szCmdline);
  300. result = TRUE;
  301. break;
  302. case ERROR_RW_LOADIMAGE:
  303. ERRMSG(ERROR_RW_LOADIMAGE,szCmdline);
  304. result = TRUE;
  305. break;
  306. case ERROR_RW_PARSEIMAGE:
  307. ERRMSG(ERROR_RW_PARSEIMAGE,szCmdline);
  308. result = TRUE;
  309. break;
  310. case ERROR_RW_GETIMAGE:
  311. ERRMSG(ERROR_RW_GETIMAGE,szCmdline);
  312. result = TRUE;
  313. break;
  314. case ERROR_RW_NOTREADY:
  315. ERRMSG(ERROR_RW_NOTREADY,szCmdline);
  316. result = TRUE;
  317. break;
  318. case ERROR_RW_BUFFER_TOO_SMALL:
  319. ERRMSG(ERROR_RW_BUFFER_TOO_SMALL,szCmdline);
  320. result = TRUE;
  321. break;
  322. case ERROR_RW_INVALID_FILE:
  323. ERRMSG(ERROR_RW_INVALID_FILE,szCmdline);
  324. result = TRUE;
  325. break;
  326. case ERROR_RW_IMAGE_TOO_BIG:
  327. ERRMSG(ERROR_RW_IMAGE_TOO_BIG,szCmdline);
  328. result = TRUE;
  329. break;
  330. case ERROR_RW_TOO_MANY_LEVELS:
  331. ERRMSG(ERROR_RW_TOO_MANY_LEVELS,szCmdline);
  332. result = TRUE;
  333. break;
  334. case ERROR_IO_INVALIDITEM:
  335. ERRMSG(ERROR_IO_INVALIDITEM,szCmdline);
  336. result = TRUE;
  337. break;
  338. case ERROR_IO_INVALIDID:
  339. ERRMSG(ERROR_IO_INVALIDID,szCmdline);
  340. result = TRUE;
  341. break;
  342. case ERROR_IO_INVALID_DLL:
  343. ERRMSG(ERROR_IO_INVALID_DLL,szCmdline);
  344. result = TRUE;
  345. break;
  346. case ERROR_IO_TYPE_NOT_SUPPORTED:
  347. ERRMSG(ERROR_IO_TYPE_NOT_SUPPORTED,szCmdline);
  348. result = TRUE;
  349. break;
  350. case ERROR_IO_INVALIDMODULE:
  351. ERRMSG(ERROR_IO_INVALIDMODULE,szCmdline);
  352. result = TRUE;
  353. break;
  354. case ERROR_IO_RESINFO_NULL:
  355. ERRMSG(ERROR_IO_RESINFO_NULL,szCmdline);
  356. result = TRUE;
  357. break;
  358. case ERROR_IO_UPDATEIMAGE:
  359. ERRMSG(ERROR_IO_UPDATEIMAGE,szCmdline);
  360. result = TRUE;
  361. break;
  362. case ERROR_IO_FILE_NOT_SUPPORTED:
  363. ERRMSG(ERROR_IO_FILE_NOT_SUPPORTED,szCmdline);
  364. result = TRUE;
  365. break;
  366. case ERROR_FILE_SYMPATH_NOT_FOUND:
  367. ERRMSG(ERROR_FILE_SYMPATH_NOT_FOUND,szCmdline);
  368. result = TRUE;
  369. break;
  370. case ERROR_FILE_MULTILANG:
  371. ERRMSG(ERROR_FILE_MULTILANG,szCmdline);
  372. result = TRUE;
  373. break;
  374. case ERROR_IO_SYMBOLFILE_NOT_FOUND:
  375. ERRMSG(ERROR_IO_SYMBOLFILE_NOT_FOUND,szCmdline);
  376. result = TRUE;
  377. break;
  378. default:
  379. break;
  380. };
  381. if (errorlevel > LAST_KNOWN_WRN && errorlevel <= LAST_WRN) {
  382. WRNMSG(IODLL_UNKNOWN,szCmdline);
  383. }
  384. if (errorlevel > LAST_KNOWN_ERR && errorlevel <= LAST_ERROR) {
  385. result = TRUE;
  386. ERRMSG(IODLL_UNKNOWN,szCmdline);
  387. }
  388. if (errorlevel > LAST_ERROR) {
  389. result = TRUE;
  390. ERRMSG(SYSTEM,szCmdline);
  391. }
  392. return result;
  393. } // ReportBingenExit
  394. int
  395. __cdecl ReportCmdExit (
  396. INT errorlevel,
  397. CHAR* szCmdline) {
  398. int result=FALSE;
  399. switch (errorlevel) {
  400. case 0:
  401. // NOMSG(szCmdline);
  402. break;
  403. default:
  404. // ERRNO(errorlevel,szCmdline);
  405. result = TRUE;
  406. }
  407. return result;
  408. } // ReportCmdExit
  409. int
  410. __cdecl ReportRsrcExit(
  411. INT errorlevel,
  412. CHAR* szCmdline
  413. ) {
  414. int result=FALSE;
  415. switch (errorlevel) {
  416. case 0:
  417. // NOMSG(szCmdline);
  418. break;
  419. case 1:
  420. WRNNO(1,szCmdline );
  421. break;
  422. default:
  423. ERRNO(errorlevel,szCmdline );
  424. result = TRUE;
  425. break;
  426. } // switch
  427. return result;
  428. }
  429. int
  430. __cdecl ReportBuildExit(
  431. INT errorlevel,
  432. CHAR* szCmdline
  433. ) {
  434. int result=FALSE;
  435. switch (errorlevel) {
  436. case 0:
  437. // NOMSG(szCmdline);
  438. break;
  439. default:
  440. // ERRNO(errorlevel,szCmdline );
  441. result = TRUE;
  442. break;
  443. } // switch
  444. return result;
  445. }
  446. char * __cdecl strnchr(char *s, char c) {
  447. while(*s==c);
  448. return (*s==NULL)?NULL:s;
  449. }
  450. int __cdecl GetEnvVar(char *envvarname, char *valuebuffer, char *defaultvalue, int bufsize) {
  451. int ret = 0;
  452. // ret == 0 => undefine ERRFILE, set to default
  453. // ret > MAX_FNAME_LEN => out of buffersize, set to fatal error
  454. if ((ret=GetEnvironmentVariable(envvarname, valuebuffer, bufsize)) == 0)
  455. strcpy(valuebuffer, defaultvalue);
  456. else if (ret > bufsize) {
  457. FATAL(envvarname,"The Environment Variable's value is too long!!!");
  458. return 0;
  459. }
  460. return 1;
  461. }
  462. void __cdecl strlower(char *s) {
  463. while(*s) {
  464. if(isalpha(*s)) *s|=0x20;
  465. s++;
  466. }
  467. }
  468. void __cdecl AppendDump(FILE *Master, CHAR *Transfile, BOOL bLogError) {
  469. SSIZE_T len = 0;
  470. FILE *Transaction;
  471. if ((Transaction=fopen(Transfile, "rt")) == NULL) {
  472. return;
  473. }
  474. while (fgets(szLine, sizeof(szLine) - sizeof(szLine[0]), Transaction)) {
  475. // Remove double \n
  476. for (len = strlen(szLine); --len >=0 && szLine[len] < ' '; szLine[len]=0);
  477. // Next Line if is empty line
  478. if (len < 1) continue;
  479. if (0 != ferror(Transaction)) {
  480. SFATAL(Transfile,"Unable to open for reading");
  481. return;
  482. } // if
  483. // Write to log file
  484. fprintf(Master, "\t%s\n", szLine);
  485. // Write to error file if need
  486. if (bLogError && bReportError) fprintf(err_stream, "\t%s\n", szLine);
  487. }
  488. if( ferror( Transaction ) ) {
  489. FATAL(pszCmdLine,"Temp error file broken !!!");
  490. }
  491. if (NULL != Transaction)
  492. fclose(Transaction);
  493. }