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.

675 lines
17 KiB

  1. /*++
  2. Filename : setuplog.c
  3. Description: This is the main file for the setuplog.c
  4. Created by: Wally Ho
  5. History: Created on 03/30/99.
  6. Contains these functions:
  7. 1. GetTargetFile (LPTSTR szOutPath, LPTSTR szBld)
  8. 2. GetNTSoundInfo (VOID)
  9. 3. ConnectAndWrite (LPTSTR MachineName, LPTSTR Buffer)
  10. 4. GetBuildNumber (LPTSTR szBld)
  11. 5. RandomMachineID (VOID)
  12. 6. WriteMinimalData (LPTSTR szFileName)
  13. 7. DeleteDatafile (LPTSTR szDatafile)
  14. 8. GlobalInit (VOID)
  15. --*/
  16. #include "setuplogEXE.h"
  17. VOID
  18. GetTargetFile (LPTSTR szOutPath, LPTSTR szBld)
  19. /*++
  20. Routine Description:
  21. The file name is generated based on the calling machine's name
  22. and the build number being installed. In the "before" case, the generated
  23. name is saved to c:\setuplog.ini, and this name is in turn read in
  24. "after" case.
  25. Arguments:
  26. Where to write the file.
  27. The build.
  28. Return Value:
  29. NONE
  30. --*/
  31. {
  32. HANDLE hFile;
  33. DWORD dwLen = MAX_PATH;
  34. TCHAR szParam [ MAX_PATH ];
  35. TCHAR szComputerName [20];
  36. TCHAR szComputerNameBld[30];
  37. g_pfnWriteDataToFile = (fnWriteData)GetProcAddress (LoadLibrary ("setuplog.dll"),
  38. "WriteDataToFile");
  39. GetComputerName (szComputerName, &dwLen);
  40. //
  41. // Build the new filename.Consisting of
  42. // 1. The Computername
  43. // 2. The build number.
  44. //
  45. _stprintf (szOutPath,TEXT("%s"), szComputerName);
  46. _tcscat (szOutPath, szBld);
  47. _tcscat (szOutPath, TEXT(".1"));
  48. //
  49. // Combine Computername and the build
  50. // To keep DavidShi code from breaking.
  51. //
  52. _stprintf(szComputerNameBld,TEXT("%s%s"),szComputerName,szBld);
  53. if (!lpCmdFrom.b_Cancel ){
  54. hFile = CreateFile (SAVE_FILE,
  55. GENERIC_WRITE,
  56. 0,
  57. NULL,
  58. CREATE_ALWAYS,
  59. FILE_ATTRIBUTE_HIDDEN,
  60. NULL );
  61. if (hFile == INVALID_HANDLE_VALUE){
  62. OutputDebugString ("Unable to write setuplog.ini\n");
  63. return;
  64. }
  65. // Check for Upgrade.
  66. _stprintf (szParam, TEXT("%s"), lpCmdFrom.b_Upgrade? TEXT("U"): TEXT("I"));
  67. WriteFile (hFile, (LPCVOID) szParam, 1, &dwLen, NULL);
  68. // Check for CD install.
  69. _stprintf (szParam, TEXT("%s\""), lpCmdFrom.b_CDrom? TEXT("C"): TEXT("N"));
  70. WriteFile (hFile, (LPCVOID) szParam, 2, &dwLen, NULL);
  71. // Write out the platform.
  72. // I think this get ignored so i may delete it. Its DavidShi code.
  73. WriteFile (hFile, (LPCVOID) szPlatform, _tcsclen(szPlatform), &dwLen, NULL);
  74. // Write out the drive.
  75. WriteFile (hFile, (LPCVOID) "\"C:", 3, &dwLen, NULL);
  76. // Write out the computer name and build
  77. WriteFile (hFile, (LPCVOID) szComputerNameBld, _tcsclen(szComputerNameBld)+1, &dwLen, NULL);
  78. // Write the RandomID.
  79. _stprintf (szParam, TEXT("\r\nMachineID %lu"), lpCmdFrom.dwRandomID);
  80. WriteFile (hFile, (LPCVOID) szParam,_tcsclen(szParam)+1 , &dwLen, NULL);
  81. // Check for MSI install
  82. _stprintf (szParam, TEXT("\r\nMSI %s"), lpCmdFrom.b_MsiInstall? TEXT("Y"): TEXT("N"));
  83. WriteFile (hFile, (LPCVOID) szParam,_tcsclen(szParam)+1 , &dwLen, NULL);
  84. CloseHandle (hFile);
  85. }
  86. }
  87. VOID
  88. GetNTSoundInfo()
  89. {
  90. HKEY hKey;
  91. DWORD dwCbData;
  92. ULONG ulType;
  93. LPTSTR sSubKey=TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32");
  94. INT i;
  95. TCHAR szSubKeyName[ MAX_PATH ];
  96. TCHAR szTempString[ MAX_PATH ];
  97. // Get Sound Card Info
  98. m.nNumWaveOutDevices = 0;
  99. hKey = 0;
  100. if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, sSubKey, 0, KEY_READ, &hKey)){
  101. // Loop through the key to see how many wave devices we have, but skip mmdrv.dll.
  102. for (i = 0; i <= 1; i++){
  103. if (i != 0)
  104. _stprintf(szSubKeyName, TEXT("wave%d"),i);
  105. else
  106. _tcscpy(szSubKeyName, TEXT("wave"));
  107. dwCbData = sizeof (szTempString);
  108. if (RegQueryValueEx(hKey, szSubKeyName, 0, &ulType, (LPBYTE)szTempString, &dwCbData))
  109. break;
  110. else{
  111. // We want to skip mmdrv.dll - not relevant.
  112. if (szTempString[0] &&
  113. _tcscmp(szTempString, TEXT("mmdrv.dll"))) {
  114. _tcscpy(&m.szWaveDriverName[m.nNumWaveOutDevices][0], szTempString);
  115. m.nNumWaveOutDevices++;
  116. }
  117. }
  118. }
  119. }
  120. if (hKey){
  121. RegCloseKey(hKey);
  122. hKey = 0;
  123. }
  124. sSubKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\drivers.desc");
  125. hKey = 0;
  126. if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, sSubKey, 0, KEY_READ, &hKey)){
  127. // Now grab the sound device string for each wave device
  128. for (i = 0; i < m.nNumWaveOutDevices; i++){
  129. dwCbData = sizeof szTempString;
  130. if (RegQueryValueEx(hKey, m.szWaveDriverName[i], 0, &ulType, (LPBYTE)szTempString, &dwCbData))
  131. _tcscpy(m.szWaveOutDesc[i], TEXT("Unknown"));
  132. else
  133. _tcscpy(m.szWaveOutDesc[i], szTempString);
  134. }
  135. }
  136. if (hKey){
  137. RegCloseKey(hKey);
  138. hKey = 0;
  139. }
  140. return;
  141. }
  142. VOID
  143. ConnectAndWrite(LPTSTR MachineName,
  144. LPTSTR Buffer)
  145. /*++
  146. Routine Description:
  147. Cconnect to the data share and write the buffer to a file
  148. named MachineNamebuild.1
  149. Arguments:
  150. The MachineName
  151. The buffer with the data to put in.
  152. Return Value:
  153. NONE
  154. --*/
  155. {
  156. TCHAR szLogName[ MAX_PATH ];
  157. HANDLE hWrite ;
  158. DWORD Size, Actual ;
  159. TCHAR szWriteFile[2000];
  160. _tcscpy(szWriteFile,Buffer);
  161. //
  162. // Blow through the list of servers.
  163. // and change the g_szServerShare to match.
  164. //
  165. if (TRUE == IsServerOnline(MachineName, NULL)){
  166. //
  167. // Set the server name now as we now have it
  168. // into the outputbuffer
  169. //
  170. _stprintf (Buffer+_tcsclen(Buffer),
  171. TEXT("IdwlogServer:%s\r\n"), g_szServerShare);
  172. _stprintf (szLogName, TEXT("%s\\%s"),g_szServerShare,MachineName );
  173. hWrite = CreateFile( szLogName,
  174. GENERIC_WRITE,
  175. 0,
  176. NULL,
  177. CREATE_ALWAYS,
  178. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
  179. NULL );
  180. if ( hWrite != INVALID_HANDLE_VALUE ){
  181. SetFilePointer( hWrite, 0, NULL, FILE_END );
  182. Size = _tcsclen( Buffer );
  183. WriteFile( hWrite, szWriteFile, Size, &Actual, NULL );
  184. CloseHandle( hWrite );
  185. }
  186. }
  187. }
  188. VOID
  189. GetBuildNumber (LPTSTR szBld)
  190. /*++
  191. Routine Description:
  192. Acquires the Build number from imagehlp.dll
  193. Arguments:
  194. Return Value:
  195. True upon sucessful completion.
  196. --*/
  197. {
  198. VS_FIXEDFILEINFO* pvsFileInfo;
  199. WIN32_FIND_DATA fd;
  200. HANDLE hFind;
  201. TCHAR szCurDir [MAX_PATH];
  202. TCHAR szFullPath[ MAX_PATH ];
  203. LPTSTR ptstr;
  204. DWORD dwTemp;
  205. DWORD dwLen;
  206. INT iBuild;
  207. LPVOID lpData;
  208. _tcscpy (szBld, TEXT("latest"));
  209. //
  210. // Use this to get the location
  211. // setuplog.exe is run from. this tool
  212. // will always assume imagehlp.dll is in its
  213. // current path or one up.
  214. //
  215. GetModuleFileName (NULL, szCurDir, MAX_PATH);
  216. //
  217. // This will cull off the setuplog.exe part
  218. // leaving us with the full path to where
  219. // setuplog.exe was on the CD or netshare.
  220. //
  221. ptstr = szCurDir + strlen(szCurDir);
  222. while (*ptstr-- != TEXT('\\'));
  223. ptstr++;
  224. *ptstr = ('\0');
  225. _stprintf (szFullPath, TEXT("%s\\imagehlp.dll"),szCurDir);
  226. //
  227. // On a network share the Imagehlp.dll is one up from where
  228. // setuplog.exe is located. We will look in both places.
  229. //
  230. hFind = FindFirstFile (szFullPath, &fd);
  231. if (INVALID_HANDLE_VALUE == hFind){
  232. //
  233. // Now we know the file in not in the
  234. // immediate directory. Move up one by
  235. // culling off one more directory.
  236. //
  237. ptstr = szCurDir + _tcsclen(szCurDir);
  238. while (*ptstr-- != '\\');
  239. ptstr++;
  240. *ptstr = '\0';
  241. _stprintf (szFullPath, TEXT("%s\\imagehlp.dll"),szCurDir);
  242. hFind = FindFirstFile (szFullPath,&fd);
  243. if (INVALID_HANDLE_VALUE == hFind){
  244. //
  245. // In case we cannot find it we will exit.
  246. //
  247. _tcscpy (szBld, TEXT("latest"));
  248. return;
  249. }
  250. }
  251. //
  252. // Get the buffer info size
  253. //
  254. dwLen = GetFileVersionInfoSize (szFullPath, &dwTemp);
  255. if ( 0 == dwLen ) {
  256. //
  257. // We have a problem.
  258. //
  259. _tcscpy (szBld, TEXT("latest"));
  260. return;
  261. }
  262. lpData = LocalAlloc (LPTR, dwLen);
  263. if ( lpData == NULL ) {
  264. //
  265. // We have a problem.
  266. //
  267. _tcscpy (szBld, TEXT("latest"));
  268. return;
  269. }
  270. //
  271. // Get the File Version Info
  272. //
  273. if(0 == GetFileVersionInfo(szFullPath,0,MAX_PATH,lpData)){
  274. //
  275. // We have a problem.
  276. //
  277. _tcscpy (szBld, TEXT("latest"));
  278. return;
  279. }
  280. if (0 == VerQueryValue (lpData, "\\", &pvsFileInfo, &dwTemp)) {
  281. //
  282. // We have a problem.
  283. //
  284. _tcscpy (szBld, TEXT("latest"));
  285. return;
  286. }
  287. //
  288. // The HIWORD() of this is the build
  289. // The LOWORD() of this is some garbage? :-)
  290. //
  291. iBuild = HIWORD(pvsFileInfo->dwFileVersionLS);
  292. LocalFree (lpData);
  293. //
  294. // Write it back to the buffer.
  295. //
  296. _stprintf(szBld, TEXT("%d"),iBuild);
  297. }
  298. DWORD
  299. RandomMachineID(VOID)
  300. /*++
  301. Author: Wallyho.
  302. Routine Description:
  303. Generates a DWORD Random MachineID for each machine
  304. Arguments:
  305. NONE
  306. Return Value:
  307. The DWORD random ID.
  308. --*/
  309. {
  310. INT i;
  311. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
  312. DWORD dwSize;
  313. INT iLenCName;
  314. INT iNameTotal = 0;
  315. DWORD dwMachineID;
  316. CHAR szRandomID[ 4 ]; // need 4 bytes to contain the DWORD.
  317. struct _timeb tm;
  318. //
  319. // This will get us the milliseconds
  320. //
  321. _ftime(&tm);
  322. //
  323. // Seed the random number generator.
  324. // We will seed with the seconds + milliseconds at
  325. // at that time. I was getting the same number
  326. // if I pressed the keyboard too fast in testing this.
  327. // The milli seconds should decrease the expectancy of
  328. // duplication.
  329. //
  330. srand ( (unsigned) time (NULL) + tm.millitm);
  331. //
  332. // This will guarantee a mostly random identifier.
  333. // Even with no computer name. We will tally the
  334. // ascii decimal value of the computer name and
  335. // add that to the randomly generated number.
  336. // The possibility of a dup is greatly decreased
  337. // since we switched to a dword system.
  338. // This computername tweak should be unnecessary.
  339. //
  340. dwSize = sizeof(szComputerName);
  341. if (0 == GetComputerName(szComputerName,&dwSize) ){
  342. //
  343. // This algorithm will limit the random number to
  344. // uppercase ascii alphabet.
  345. //
  346. szComputerName[0] = 65 + (rand() % 25);
  347. szComputerName[1] = 65 + (rand() % 25);
  348. szComputerName[2] = 65 + (rand() % 25);
  349. szComputerName[3] = 65 + (rand() % 25);
  350. szComputerName[4] = 65 + (rand() % 25);
  351. szComputerName[5] = 65 + (rand() % 25);
  352. szComputerName[6] = 65 + (rand() % 25);
  353. szComputerName[7] = TEXT('\0');
  354. }
  355. iLenCName = _tcslen (szComputerName);
  356. //
  357. // Tally up the individual elements in the file
  358. //
  359. for (i = 0; i < iLenCName; i++)
  360. iNameTotal += szComputerName[i];
  361. //
  362. // Generate four 8 bit numbers.
  363. // Add the some random number based on the
  364. // computername mod'ed to 0-100.
  365. // Limit the 8 bit number to 0-155 to make room
  366. // for the 100 from the computer name tweak.
  367. // Total per 8 bit is 256.
  368. // Do this tweak to only 2.
  369. // We will then cast and shift to combine it
  370. // into a DWORD.
  371. //
  372. szRandomID[0] = (rand() % 155) + (iNameTotal % 100);
  373. szRandomID[1] = rand() % 255;
  374. szRandomID[2] = (rand() % 155) + (iNameTotal % 100);
  375. szRandomID[3] = rand() % 255;
  376. //
  377. // This will combine the 4 8bit CHAR into one DWORD
  378. //
  379. dwMachineID = (DWORD)szRandomID[0] * 0x00000001 +
  380. (DWORD)szRandomID[1] * 0x00000100 +
  381. (DWORD)szRandomID[2] * 0x00010000 +
  382. (DWORD)szRandomID[3] * 0x01000000;
  383. return dwMachineID;
  384. }
  385. VOID
  386. WriteMinimalData (LPTSTR szFileName)
  387. /*++
  388. For machines on which setuplog.dll fails to load, just write
  389. the platform,a time stamp, upgrade, and cpu count.
  390. --*/
  391. {
  392. TCHAR szOutBuffer[4096];
  393. _tcscpy (szCPU ,TEXT("1"));
  394. _stprintf (szOutBuffer,
  395. TEXT("MachineID:%lu\r\n")
  396. TEXT("Source Media:%s\r\n")
  397. TEXT("Type:%s\r\n")
  398. TEXT("FromBld:%s\r\n")
  399. TEXT("Arch:%s\r\n")
  400. TEXT("Sound:%s\r\n")
  401. TEXT("NumProcs:%s\r\n")
  402. TEXT("MSI:%s\r\n"),
  403. lpCmdFrom.dwRandomID,
  404. lpCmdFrom.b_CDrom? TEXT("C"): TEXT("N"),
  405. lpCmdFrom.b_Upgrade? TEXT("U"): TEXT("I"),
  406. szPlatform,
  407. szArch,
  408. m.nNumWaveOutDevices? m.szWaveDriverName[m.nNumWaveOutDevices-1]: TEXT("None"),
  409. szCPU,
  410. lpCmdFrom.b_MsiInstall? TEXT("Y"): TEXT("N")
  411. );
  412. ConnectAndWrite (szFileName, szOutBuffer);
  413. }
  414. VOID
  415. DeleteDatafile (LPTSTR szDatafile)
  416. /*++
  417. Author:
  418. Routine Description:
  419. Deletes the file from the server if the user cancels it.
  420. Arguments:
  421. The name of the datafile.
  422. Return Value:
  423. NONE
  424. --*/
  425. {
  426. TCHAR szPath[MAX_PATH];
  427. _stprintf (szPath,TEXT("%s\\%s"), g_szServerShare,szDatafile);
  428. DeleteFile (szPath);
  429. }
  430. INT WINAPI
  431. WinMain(HINSTANCE hInst,
  432. HINSTANCE h,
  433. LPTSTR szCmdLine,
  434. INT nCmdShow)
  435. {
  436. BOOL bAfter = FALSE;
  437. TCHAR szBld[10];
  438. TCHAR szFileToSave[MAX_PATH];
  439. OSVERSIONINFO osVer;
  440. //
  441. // Initialize Global Variables.
  442. //
  443. // GlobalInit();
  444. // Spray up a simple help screen for /?
  445. if ( 0 == _tcscmp(szCmdLine, TEXT("/?")) ||
  446. 0 == _tcscmp(szCmdLine, TEXT("-?")) ){
  447. MessageBox(NULL,TEXT("setuplog upgrade cancel cdrom MSI "),TEXT("Help!"),MB_ICONQUESTION | MB_OK);
  448. return FALSE;
  449. }
  450. SetErrorMode (SEM_FAILCRITICALERRORS);
  451. //
  452. // See if Drive C is a HD.
  453. //
  454. if (DRIVE_FIXED != GetDriveType (TEXT("C:\\")) ){
  455. return 0;
  456. }
  457. osVer.dwOSVersionInfoSize= sizeof( osVer );
  458. GetVersionEx( &osVer );
  459. switch (osVer.dwPlatformId){
  460. case VER_PLATFORM_WIN32_NT:
  461. szPlatform = TEXT("Windows NT");
  462. switch (osVer.dwMajorVersion){
  463. case 3:
  464. szPlatform = TEXT("Windows NT 3.51");
  465. break;
  466. case 4:
  467. szPlatform = TEXT("Windows NT 4.0");
  468. break;
  469. case 5:
  470. szPlatform = szCurBld;
  471. break;
  472. }
  473. GetEnvironmentVariable ( TEXT("NUMBER_OF_PROCESSORS"), szCPU, 6);
  474. GetEnvironmentVariable ( TEXT("PROCESSOR_ARCHITECTURE"), szArch, 20);
  475. break;
  476. case VER_PLATFORM_WIN32_WINDOWS:
  477. szPlatform = TEXT("Windows 9x");
  478. _tcscpy (szArch, "X86");
  479. break;
  480. default:
  481. szPlatform = TEXT("Unknown");
  482. _tcscpy (szArch, TEXT("Unknown"));
  483. break;
  484. }
  485. //
  486. // This is a very primitive command line processor
  487. // I'll add to it now to get this working soon.
  488. // I'll flesh this out to a full parser soon.
  489. // Wallyho.
  490. //
  491. lpCmdFrom.b_Upgrade = _tcsstr (szCmdLine, TEXT("upgrade")) ? TRUE : FALSE;
  492. lpCmdFrom.b_Cancel = _tcsstr (szCmdLine, TEXT("cancel")) ? TRUE : FALSE;
  493. lpCmdFrom.b_CDrom = _tcsstr (szCmdLine, TEXT("cdrom")) ? TRUE : FALSE;
  494. lpCmdFrom.b_MsiInstall= _tcsstr (szCmdLine, TEXT("MSI")) ? TRUE : FALSE;
  495. if (osVer.dwMajorVersion >= 5){
  496. _itoa (osVer.dwBuildNumber, szCurBld, sizeof(szCurBld));
  497. }
  498. //
  499. // Load the build number in the szBld
  500. // Variable.
  501. //
  502. GetBuildNumber (szBld);
  503. //
  504. // Generate a MachineID upfront to use later.
  505. //
  506. lpCmdFrom.dwRandomID = RandomMachineID();
  507. GetTargetFile (szFileToSave, szBld);
  508. if (!lpCmdFrom.b_Cancel){
  509. GetNTSoundInfo ();
  510. if (g_pfnWriteDataToFile)
  511. g_pfnWriteDataToFile(szFileToSave, NULL, &lpCmdFrom);
  512. else
  513. WriteMinimalData (szFileToSave);
  514. }
  515. else
  516. DeleteDatafile (szFileToSave);
  517. return 0;
  518. }
  519. VOID
  520. GlobalInit(VOID)
  521. /*++
  522. Author: Wallyho.
  523. Routine Description:
  524. Initializes global Values.
  525. Arguments:
  526. NONE
  527. Return Value:
  528. NONE
  529. --*/
  530. {
  531. //
  532. // Do some global initializations.
  533. //
  534. }