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.

499 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: Main.cpp
  7. //
  8. // Contents: Main wrapper file for SRDiag, this will call into cab.cpp,
  9. // chglog.cpp, getreg.cpp, rpenum.cpp for getting changlog,
  10. // restore points, registry information. This file also contains
  11. // routines for getting file information, restore Guid, and generic
  12. // logging imposed by cab.cpp
  13. //
  14. // Objects:
  15. //
  16. // Coupling:
  17. //
  18. // Notes:
  19. //
  20. // History: 9/21/00 SHeffner Created
  21. // 10/5/00 SHeffner Moved file specific gathering to the header file.
  22. //
  23. //----------------------------------------------------------------------------
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Common Includes
  27. //
  28. //----------------------------------------------------------------------------
  29. #include <stdio.h>
  30. #include <windows.h>
  31. #include <stdlib.h>
  32. #include <cab.h>
  33. #include <main.h>
  34. #include <dbgtrace.h>
  35. #include <winver.h>
  36. #include "srrpcapi.h"
  37. //+---------------------------------------------------------------------------
  38. //
  39. // Function proto typing for rpenum.cpp, getreg.cpp, Chglog.cpp
  40. //
  41. //----------------------------------------------------------------------------
  42. bool GetSRRegistry(char *szFilename, WCHAR *szPath, bool bRecurse);
  43. void GetChgLog(char *szLogfile);
  44. void RPEnumDrive(HFCI hc, char *szLogFile);
  45. //+---------------------------------------------------------------------------
  46. //
  47. // Global Variables used within main, and through cab.cpp
  48. //
  49. //----------------------------------------------------------------------------
  50. FILE *fLogStream = NULL; //For the Log, and Log2 routines
  51. extern char g_szCabFileLocation[_MAX_PATH]; //This is actually defined in cab.cpp
  52. extern char g_szCabFileName[_MAX_PATH]; //This is actually defined in cab.cpp
  53. void __cdecl main(int argc, char *argv[])
  54. {
  55. HFCI hc = NULL;
  56. int i=0;
  57. bool bResult=false;
  58. char szString[_MAX_PATH], szRestoreDirPath[_MAX_PATH];
  59. char *szTest[1], *szArgCmd[200];
  60. //Process any commandline arguments
  61. memset(szArgCmd, 0, sizeof(char)*200); //Clean up before relying on this DS.
  62. ArgParse(argc, argv, szArgCmd);
  63. //Open up the log file, and start logging all activity
  64. strcpy(szString, getenv("TEMP"));
  65. strcat(szString, "\\SRDIAG.LOG");
  66. fLogStream = fopen(szString, "w");
  67. //Create a cab, if we fail then just skip,
  68. // else gather all of the relevant files required.
  69. if (NULL != (hc = create_cab()) )
  70. {
  71. //First add in any files that were specified on the command line, but first figuring out
  72. // how many were really specified
  73. for(i=0;i<200;i++) if(NULL == szArgCmd[i]) break;
  74. bResult = test_fci(hc, i, szArgCmd, "");
  75. //Get the Temp Location, ensure we have a new file, then
  76. // get the registry keys, and dump into our text file
  77. strcpy(szString, getenv("TEMP"));
  78. strcat(szString, "\\SR-Reg.txt");
  79. DeleteFileA(szString);
  80. i = 0;
  81. while (NULL != *wszRegKeys[i][0]) {
  82. if(0 == wcscmp(wszRegKeys[i][1], TEXT("0")))
  83. GetSRRegistry(szString, wszRegKeys[i][0], false);
  84. else
  85. GetSRRegistry(szString, wszRegKeys[i][0], true);
  86. i++;
  87. }
  88. //Add the log to the Cab, and clean up
  89. szTest[0] = szString;
  90. bResult = test_fci(hc, 1, szTest, "");
  91. DeleteFileA(szString);
  92. //Add files Bases on WinDir relative root
  93. i = 0;
  94. while (NULL != *szWindirFileCollection[i]) {
  95. strcpy(szString, getenv("WINDIR"));
  96. strcat(szString, szWindirFileCollection[i]);
  97. szTest[0] = szString;
  98. bResult = test_fci(hc, 1, szTest, "");
  99. i++;
  100. }
  101. //Get the restore directory on the system drive, and then Add in critial files
  102. GetRestoreGuid(szString);
  103. sprintf(szRestoreDirPath, "%s\\System Volume Information\\_Restore%s\\", getenv("SYSTEMDRIVE"), szString );
  104. //Add files Bases on System Volume Information relative root
  105. i = 0;
  106. while (NULL != *szSysVolFileCollection[i]) {
  107. strcpy(szString, szRestoreDirPath);
  108. strcat(szString, szSysVolFileCollection[i]);
  109. szTest[0] = szString;
  110. bResult = test_fci(hc, 1, szTest, "");
  111. i++;
  112. }
  113. //Get the Restore point enumeration, and then cab the file
  114. strcpy(szString, getenv("TEMP"));
  115. strcat(szString, "\\SR-RP.LOG");
  116. RPEnumDrive(hc, szString);
  117. szTest[0] = szString;
  118. bResult = test_fci(hc, 1, szTest, "");
  119. DeleteFileA(szString);
  120. //Get the ChangeLog enumeration, and then cab and delete the file
  121. //first we need to switch the log, then gather the log
  122. SRSwitchLog();
  123. strcpy(szString, getenv("TEMP"));
  124. strcat(szString, "\\SR-CHGLog.LOG");
  125. GetChgLog(szString);
  126. szTest[0] = szString;
  127. bResult = test_fci(hc, 1, szTest, "");
  128. DeleteFileA(szString);
  129. //Get the fileversion info for each of the Files
  130. strcpy(szString, getenv("TEMP"));
  131. strcat(szString, "\\SR-FileList.LOG");
  132. SRGetFileInfo(szString);
  133. szTest[0] = szString;
  134. bResult = test_fci(hc, 1, szTest, "");
  135. DeleteFileA(szString);
  136. //Close out logging, and add the log to the cab
  137. // (THIS SHOULD BE THE LAST THING WE ARE DOING!!)
  138. fclose(fLogStream);
  139. fLogStream = NULL;
  140. strcpy(szString, getenv("TEMP"));
  141. strcat(szString, "\\SRDIAG.LOG");
  142. szTest[0] = szString;
  143. bResult = test_fci(hc, 1, szTest, "");
  144. DeleteFileA(szString);
  145. }
  146. //Completes cab file under construction
  147. if (flush_cab(hc))
  148. {
  149. Log("Cabbing Process was Sucessful");
  150. }
  151. else
  152. {
  153. Log("Cabbing Process has failed");
  154. }
  155. }
  156. //+---------------------------------------------------------------------------
  157. //
  158. // Function: Log
  159. //
  160. // Synopsis: Will print a String to both our log file, and also the console
  161. //
  162. // Arguments: [szString] -- Simple ANSI string to log
  163. //
  164. // Returns: void
  165. //
  166. // History: 9/21/00 SHeffner Created
  167. //
  168. //
  169. //----------------------------------------------------------------------------
  170. void Log(char *szString)
  171. {
  172. if( NULL != fLogStream)
  173. fprintf(fLogStream, "%s\n", szString);
  174. puts(szString);
  175. }
  176. //+---------------------------------------------------------------------------
  177. //
  178. // Function: Log2
  179. //
  180. // Synopsis: Takes two strings, and will print them back to back to both the
  181. // log file, and also to the console
  182. //
  183. // Arguments: [szString] -- Simple ANSI string to log
  184. // [szString2] -- Simple ANSI string to log
  185. //
  186. // Returns: void
  187. //
  188. // History: 9/21/00 SHeffner Created
  189. //
  190. //
  191. //----------------------------------------------------------------------------
  192. void Log2(char *szString, char *szString2)
  193. {
  194. if( NULL != fLogStream)
  195. fprintf(fLogStream,"%s %s\n", szString, szString2);
  196. printf("%s %s\n", szString, szString2);
  197. }
  198. //+---------------------------------------------------------------------------
  199. //
  200. // Function: GetRestoreGuid
  201. //
  202. // Synopsis: Will retrieve from the registry what the GUID is for the current
  203. // Restore directory, and return this in the string pointer passed
  204. // to the function.
  205. //
  206. // Arguments: [szString] -- Simple ANSI string to receive the string
  207. //
  208. // Returns: void
  209. //
  210. // History: 9/21/00 SHeffner Created
  211. //
  212. //
  213. //----------------------------------------------------------------------------
  214. void GetRestoreGuid(char *szString)
  215. {
  216. long lResult;
  217. HKEY mHkey;
  218. DWORD dwType, dwLength;
  219. lResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SystemRestore\\Cfg", 0, KEY_READ, &mHkey);
  220. dwLength = _MAX_PATH +1;
  221. lResult = RegQueryValueExA(mHkey, "MachineGuid", NULL, &dwType, (unsigned char *)szString, &dwLength);
  222. }
  223. //+---------------------------------------------------------------------------
  224. //
  225. // Function: SRGetFileInfo
  226. //
  227. // Synopsis: This is the wrapper function for InfoPerFile, where I will assemble
  228. // the file path for each of the relevant files that we need to get
  229. // file statistics.
  230. //
  231. // Arguments: [szLogFile] -- The path to the file that I will log this information to.
  232. //
  233. // Returns: void
  234. //
  235. // History: 9/21/00 SHeffner Created
  236. //
  237. //
  238. //----------------------------------------------------------------------------
  239. void SRGetFileInfo(char *szLogFile)
  240. {
  241. int iCount;
  242. WCHAR szString[_MAX_PATH];
  243. //Initialize counter, and walk through the filelist that we have
  244. iCount = 0;
  245. while(NULL != *wszFileVersionList[iCount])
  246. {
  247. //Assemble the path, since I just have the relative path from windir
  248. wcscpy(szString, _wgetenv(L"WINDIR"));
  249. wcscat(szString, wszFileVersionList[iCount]);
  250. //Call function to do the work since we have full path, and log file name
  251. InfoPerFile(szLogFile, szString);
  252. iCount++;
  253. }
  254. }
  255. //+---------------------------------------------------------------------------
  256. //
  257. // Function: InfoPerFile
  258. //
  259. // Synopsis: This function takes the log file path, and the filename, and then
  260. // will put out the relevant information from the file to be logged.
  261. //
  262. //
  263. // Arguments: [szLogFile] -- The path to the file that I will log this information to.
  264. // [szFileName] -- The full path, and name of the file to get the information for.
  265. //
  266. // Returns: void
  267. //
  268. // History: 9/21/00 SHeffner Created
  269. //
  270. //
  271. //----------------------------------------------------------------------------
  272. void InfoPerFile(char *szLogFile, WCHAR *szFileName)
  273. {
  274. BY_HANDLE_FILE_INFORMATION finfo;
  275. SYSTEMTIME st;
  276. HANDLE handle;
  277. FILE *fStream;
  278. WCHAR szString[_MAX_PATH];
  279. VOID *pBuffer;
  280. VS_FIXEDFILEINFO FixedFileInfo;
  281. UINT uLen;
  282. DWORD dSize, dResult, i;
  283. struct LANGANDCODEPAGE {
  284. WORD wLanguage;
  285. WORD wCodePage;
  286. } *lpTranslate;
  287. WCHAR *szMonth[] = { L"January", L"Feburary", L"March", L"April", L"May", L"June", L"July", L"August", L"September", L"October", L"November", L"December" };
  288. WCHAR *szDay[] = {L"Sunday", L"Monday", L"Tuesday", L"Wednesday", L"Thursday", L"Friday", L"Saturday" };
  289. if ( NULL == *szFileName) return;
  290. //Open up our log file, and log the file we are processing
  291. fStream = fopen(szLogFile, "a");
  292. if( NULL == fStream) return; //if we have an invalid handle just return back.
  293. fprintf(fStream, "\n%S\n", szFileName);
  294. //Open up the file so that we can get the information from the handle
  295. // If we are unable to do this we will just log the generic not able to find file.
  296. if( INVALID_HANDLE_VALUE != (handle = CreateFile(szFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) )
  297. {
  298. if (FALSE != GetFileInformationByHandle(handle, &finfo))
  299. {
  300. //FileCreation
  301. FileTimeToSystemTime( &finfo.ftCreationTime, &st);
  302. fprintf(fStream, "\tCreation Date=%S %S %lu, %lu %lu:%lu:%lu\n",
  303. szDay[st.wDayOfWeek],szMonth[st.wMonth-1],st.wDay,st.wYear,st.wHour,st.wMinute,st.wSecond);
  304. //FileLastAccess
  305. FileTimeToSystemTime( &finfo.ftLastAccessTime, &st);
  306. fprintf(fStream, "\tLast Access Date=%S %S %lu, %lu %lu:%lu:%lu\n",
  307. szDay[st.wDayOfWeek],szMonth[st.wMonth-1],st.wDay,st.wYear,st.wHour,st.wMinute,st.wSecond);
  308. //FileLastWrite
  309. FileTimeToSystemTime( &finfo.ftLastWriteTime, &st);
  310. fprintf(fStream, "\tLast Write Date=%S %S %lu, %lu %lu:%lu:%lu\n",
  311. szDay[st.wDayOfWeek],szMonth[st.wMonth-1],st.wDay,st.wYear,st.wHour,st.wMinute,st.wSecond);
  312. //File Attributes
  313. wcscpy(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? L"ARCHIVE " : L"");
  314. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ? L"COMPRESSED " : L"");
  315. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? L"DIRECTORY " : L"");
  316. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED ? L"ENCRYPTED " : L"");
  317. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? L"HIDDEN " : L"");
  318. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? L"NORMAL " : L"");
  319. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE ? L"OFFLINE " : L"");
  320. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? L"READONLY " : L"");
  321. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? L"REPARSE_POINT " : L"");
  322. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE ? L"SPARSE_FILE " : L"");
  323. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? L"SYSTEM " : L"");
  324. wcscat(szString, finfo.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY ? L"TEMPORARY " : L"");
  325. fprintf(fStream, "\tAttributes=%S\n", szString);
  326. //Get the VolumeSerialNumber, FileSize, and Number of Links
  327. fprintf(fStream, "\tVolumeSerialNumber=%lu\n", finfo.dwVolumeSerialNumber);
  328. fprintf(fStream, "\tFileSize=%lu%lu\n", finfo.nFileSizeHigh, finfo.nFileSizeLow);
  329. fprintf(fStream, "\tNumberOfLinks=%lu\n", finfo.nNumberOfLinks);
  330. if( 0 != (dSize = GetFileVersionInfoSize(szFileName, &dResult)) )
  331. {
  332. if( NULL != (pBuffer = malloc(dSize)) )
  333. {
  334. GetFileVersionInfo(szFileName, dResult, dSize, (LPVOID) pBuffer);
  335. // Read the list of languages and code pages.
  336. VerQueryValue(pBuffer,
  337. TEXT("\\VarFileInfo\\Translation"),
  338. (LPVOID*)&lpTranslate,
  339. &uLen);
  340. // Read the Version info for each language and code page.
  341. for( i=0; i < (uLen/sizeof(struct LANGANDCODEPAGE)); i++ )
  342. {
  343. char *lpBuffer;
  344. DWORD dwBytes, dwCount = 0;
  345. fprintf(fStream, "\tLanguage=%x%x\n", lpTranslate[i].wLanguage, lpTranslate[i].wCodePage);
  346. while (NULL != *wszVersionResource[dwCount] )
  347. {
  348. //Generate the string, for getting the resource based on the language, then
  349. // retrieve this, and then put it to the log file.
  350. wsprintf( szString, L"\\StringFileInfo\\%04x%04x\\%s",
  351. lpTranslate[i].wLanguage,
  352. lpTranslate[i].wCodePage,
  353. wszVersionResource[dwCount]);
  354. VerQueryValue(pBuffer,
  355. szString,
  356. (LPVOID *) &lpBuffer,
  357. &uLen);
  358. if( 0 != uLen )
  359. fprintf(fStream, "\t%S=%S\n", wszVersionResource[dwCount], lpBuffer);
  360. dwCount++;
  361. } //While loop end, for each resource
  362. } //for loop end for each language
  363. //Clean up the allocated memory
  364. free(pBuffer);
  365. } //If check for getting memory
  366. } //If check for getting the fileversioninfosize
  367. } //if check for GetFileInformationByHandle on the file
  368. CloseHandle(handle);
  369. } //if check on can I open this file
  370. //Cleanup
  371. fclose(fStream);
  372. }
  373. //+---------------------------------------------------------------------------
  374. //
  375. // Function: ArgParse
  376. //
  377. // Synopsis: This function simply looks for the key word parameters, and will build
  378. // an array pointing to each of the files that we want to include in the cab
  379. // in addition to the normal files.
  380. //
  381. //
  382. // Arguments: [argc] -- Count of the number of arguments
  383. // [argv] -- Array of the arguments.
  384. //
  385. // Returns: void
  386. //
  387. // History: 9/21/00 SHeffner Created
  388. //
  389. //
  390. //----------------------------------------------------------------------------
  391. void ArgParse(int argc, char *argv[], char *szArgCmd[])
  392. {
  393. int iCount, iWalk;
  394. //If no command line specified then just do the normal cabbing, with core files
  395. if(1 == argc)
  396. return;
  397. //walk through each of the arguments, and check to see if its a help, file, cabname, cabloc, or a ?
  398. for(iCount = 1; iCount < argc; iCount++)
  399. {
  400. if( 0 == _strnicoll(&argv[iCount][1], "?", strlen("?")) )
  401. Usage();
  402. if( 0 == _strnicoll(&argv[iCount][1], "help", strlen("help")) )
  403. Usage();
  404. if( 0 == _strnicoll(&argv[iCount][1], "cabname", strlen("cabname")) )
  405. strcpy(g_szCabFileName, (strstr(argv[iCount], ":") + 1));
  406. if( 0 == _strnicoll(&argv[iCount][1], "cabloc", strlen("cabloc")) )
  407. strcpy(g_szCabFileLocation, (strstr(argv[iCount], ":") + 1));
  408. if( 0 == _strnicoll(&argv[iCount][1], "file", strlen("file")) )
  409. {
  410. //find the first spot where I can put the pointer to this filename
  411. for( iWalk=0; iWalk < 200; iWalk++)
  412. {
  413. if( NULL == szArgCmd[iWalk] )
  414. {
  415. szArgCmd[iWalk] = strstr(argv[iCount], ":") + 1;
  416. break;
  417. }
  418. } //end for loop, walking through DS
  419. } //end of if for is this an added file
  420. } //end of for loop walking through all of the arguments
  421. }
  422. //+---------------------------------------------------------------------------
  423. //
  424. // Function: Usage
  425. //
  426. // Synopsis: Displaies the command line usage
  427. //
  428. //
  429. // Arguments:
  430. //
  431. // Returns: void
  432. //
  433. // History: 9/21/00 SHeffner Created
  434. //
  435. //
  436. //----------------------------------------------------------------------------
  437. void Usage()
  438. {
  439. printf("Usage: SrDiag [/Cabname:test.cab] [/Cabloc:\"c:\\temp\\\"] [/file:\"c:\\boot.ini\"]\n");
  440. printf(" /cabloc is pointing to the location to store the cab, this should have a \\ on the end\n");
  441. printf(" /cabname is the full name of the cab file that you wish to use. \n");
  442. printf(" /file is the name and path of a file that you wish to add to the cab, this can be used many times\n");
  443. exit(0);
  444. }