Source code of Windows XP (NT5)
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.

1022 lines
25 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /**************************************************************************/
  4. /***** Shell Component - WinMain, ShellWndProc routines *******************/
  5. /**************************************************************************/
  6. //
  7. // Reentrancy control.
  8. //
  9. BOOL
  10. EnterInterpreter(
  11. VOID
  12. );
  13. #define EXIT_CODE "Exit_Code"
  14. extern HWND hwndProgressGizmo;
  15. //
  16. // This flag tells us whether we were invoked as a standalone process
  17. // or whether we were called to interpret a legacy inf from within a process.
  18. //
  19. BOOL OwnProcess;
  20. //
  21. // The following two globals are only valid if 'OwnProcess' is FALSE. They are
  22. // used to keep track of what services have been modified during an INF 'run'.
  23. // Refer to sc.c!LegacyInfGetModifiedSvcList() for more details.
  24. //
  25. LPSTR ServicesModified;
  26. DWORD ServicesModifiedSize;
  27. /*
  28. ** Shell Global Variables
  29. */
  30. HANDLE hInst = (HANDLE)NULL;
  31. HWND hWndShell = (HWND)NULL;
  32. HANDLE SupportLibHandle = NULL;
  33. HWND hwParam = NULL ;
  34. HWND hwPseudoParent = NULL ;
  35. static BOOL fParamFlashOn = FALSE ;
  36. // SZ szShlScriptSection = (SZ)NULL;
  37. //
  38. // No longer used (we never try to abort a shutdown)
  39. //
  40. // BOOL fIgnoreQueryEndSession = fTrue;
  41. CHP rgchBufTmpLong[cchpBufTmpLongBuf] = "long";
  42. CHP rgchBufTmpShort[cchpBufTmpShortBuf] = "short";
  43. HBITMAP hbmAdvertList [ BMP_MAX + 1 ] ;
  44. INT cAdvertIndex = -1 ;
  45. INT cAdvertCycleSeconds = 0 ;
  46. INT cyAdvert = 0 ;
  47. INT cxAdvert = 0 ;
  48. INT dyChar = 0;
  49. INT dxChar = 0;
  50. BOOL bTimerEnabled = FALSE ;
  51. RECT rcBmpMax = {-1,-1,-1,-1} ;
  52. extern BOOL fFullScreen;
  53. extern INT gaugeCopyPercentage ;
  54. extern PSTR LastShellReturn;
  55. extern DWORD LastShellReturnSize;
  56. SCP rgscp[] = {
  57. { "UI", spcUI },
  58. { "READ-SYMS", spcReadSyms },
  59. { "DETECT", spcDetect },
  60. { "INSTALL", spcInstall },
  61. { "UPDATE-INF", spcUpdateInf },
  62. { "WRITE-INF", spcWriteInf },
  63. { "EXIT", spcExit },
  64. { "WRITE-SYMTAB", spcWriteSymTab },
  65. { "SET-TITLE", spcSetTitle },
  66. { "EXIT-AND-EXEC", spcExitAndExec },
  67. { "ENABLEEXIT", spcEnableExit },
  68. { "DISABLEEXIT", spcDisableExit },
  69. { "SHELL", spcShell },
  70. { "RETURN", spcReturn },
  71. { NULL, spcUnknown },
  72. };
  73. PSPT psptShellScript = (PSPT)NULL;
  74. VOID
  75. RebootMachineIfNeeded(
  76. );
  77. #define TimerInterval 500 // 1/2 second
  78. #define TimerId 1
  79. VOID FSetTimer ( VOID ) ;
  80. VOID FHandleBmpTimer ( VOID ) ;
  81. VOID FFlashParentActive ( VOID ) ;
  82. VOID FPaintBmp ( HWND hwnd, HDC hdc ) ;
  83. #define POINTSIZE_WASHTEXT 24
  84. #define X_WASHTEXT 5
  85. #define Y_WASHTEXT 5
  86. #define CR_BLACK RGB(0, 0, 0)
  87. #define CR_DKBLUE RGB(0, 0, 128)
  88. UINT ScreenWidth,ScreenHeight;
  89. int
  90. real_dll_main(
  91. IN int argc,
  92. IN char *argv[],
  93. IN char *CommandLine OPTIONAL
  94. )
  95. {
  96. HANDLE hInst;
  97. HANDLE hPrevInst = NULL;
  98. LPSTR lpCmdLine;
  99. INT nCmdShow = SW_SHOWNORMAL;
  100. USHORT _argc = (USHORT)argc;
  101. CHAR **_argv = argv;
  102. MSG msg;
  103. SZ szInfSrcPath;
  104. SZ szDestDir;
  105. SZ szSrcDir;
  106. SZ szCWD;
  107. PSTR sz;
  108. INT wModeSetup;
  109. INT rc;
  110. hInst = MyDllModuleHandle;
  111. lpCmdLine = CommandLine ? CommandLine : GetCommandLine();
  112. //
  113. // Strip off the first string (program name).
  114. //
  115. if(sz = strchr(lpCmdLine,' ')) {
  116. do {
  117. sz++;
  118. } while(*sz == ' ');
  119. lpCmdLine = sz;
  120. } else {
  121. // no spaces, program name is alone on cmd line.
  122. lpCmdLine += lstrlen(lpCmdLine);
  123. }
  124. ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
  125. ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
  126. //
  127. // We check for the -f parameter here because we have to create (and display)
  128. // the Seup window before calling the FParseCmdLine function.
  129. //
  130. if( _argc < 2 ) {
  131. //
  132. // No parameters on setup command line. If setup has been run from
  133. // the windows system direcotry then we conclude that setup has been
  134. // run in maintenance mode
  135. //
  136. CHAR szSystemDir[MAX_PATH];
  137. CHAR szCWD[MAX_PATH];
  138. if ( GetSystemDirectory( szSystemDir, MAX_PATH ) &&
  139. GetModuleFileName(hInst, szCWD, MAX_PATH)
  140. ) {
  141. SZ szFileSpec;
  142. //
  143. // Extract the directory of the module file spec and compare it
  144. // with the system directory. If the two are the same assume
  145. // we are maintenance mode
  146. if( szFileSpec = strrchr( szCWD, '\\' ) ) {
  147. *szFileSpec = '\0';
  148. if( !lstrcmpi( szSystemDir, szCWD ) ) {
  149. fFullScreen = fFalse;
  150. }
  151. }
  152. }
  153. }
  154. else {
  155. //
  156. // Check to see if blue wash has been explicitly disabled or
  157. // if a primary parent window handle has been passed in.
  158. //
  159. while ( --argc ) {
  160. if ( (_argv[argc][0] == '/') || (_argv[argc][0] == '-')) {
  161. switch ( _argv[argc][1] )
  162. {
  163. case 'F':
  164. case 'f':
  165. fFullScreen = fFalse;
  166. break;
  167. case 'w':
  168. case 'W':
  169. hwParam = (HWND) LongToHandle(atol( _argv[argc+1] )) ;
  170. break ;
  171. default:
  172. break ;
  173. }
  174. }
  175. }
  176. _argv = argv;
  177. }
  178. CurrentCursor = LoadCursor(NULL,IDC_ARROW);
  179. if(!CreateShellWindow(hInst,nCmdShow,FALSE)) {
  180. return( SETUP_ERROR_GENERAL );
  181. }
  182. rc = ParseCmdLine(
  183. hInst,
  184. (SZ)lpCmdLine,
  185. &szInfSrcPath,
  186. &szDestDir,
  187. &szSrcDir,
  188. &szCWD,
  189. &wModeSetup
  190. );
  191. if( rc != CMDLINE_SUCCESS) {
  192. FDestroyShellWindow() ;
  193. return( ( rc == CMDLINE_SETUPDONE ) ?
  194. SETUP_ERROR_SUCCESS : SETUP_ERROR_GENERAL );
  195. }
  196. if(!FInitApp(hInst, szInfSrcPath, szDestDir, szSrcDir, szCWD,
  197. wModeSetup)) {
  198. FDestroyShellWindow() ;
  199. return(SETUP_ERROR_GENERAL);
  200. }
  201. // Start the timer ticking
  202. FSetTimer() ;
  203. //
  204. // Set the parent app, if any, to *appear* enabled
  205. //
  206. if(OwnProcess) {
  207. FFlashParentWindow(TRUE);
  208. }
  209. while (GetMessage(&msg, NULL, 0, 0)) {
  210. if(FUiLibFilter(&msg) &&
  211. (hwndProgressGizmo == NULL ||
  212. !IsDialogMessage(hwndProgressGizmo,&msg))) {
  213. TranslateMessage(&msg);
  214. DispatchMessage(&msg);
  215. }
  216. }
  217. return (int)(msg.wParam);
  218. }
  219. int
  220. dll_main(
  221. IN int argc,
  222. IN char *argv[]
  223. )
  224. {
  225. if(!EnterInterpreter()) {
  226. return(SETUP_ERROR_GENERAL);
  227. }
  228. OwnProcess = TRUE;
  229. //
  230. // Set the modified service list buffer to empty, so we won't be fooled into
  231. // using it should someone mistakenly call LegacyInfGetModifiedSvcList().
  232. // This buffer is only valid when used after a successful call to
  233. // LegacyInfInterpret().
  234. //
  235. ServicesModified = NULL;
  236. ServicesModifiedSize = 0;
  237. return(real_dll_main(argc,argv,NULL));
  238. }
  239. /*
  240. ** Purpose:
  241. ** ??
  242. ** Arguments:
  243. ** none
  244. ** Returns:
  245. ** none
  246. **
  247. ***************************************************************************/
  248. LRESULT APIENTRY ShellWndProc(HWND hWnd, UINT wMsg, WPARAM wParam,
  249. LPARAM lParam)
  250. {
  251. PAINTSTRUCT ps;
  252. HDC hdc;
  253. RECT rc;
  254. INT ExitCode = SETUP_ERROR_GENERAL;
  255. SZ szExitCode;
  256. static LPSTR HelpContext = NULL;
  257. switch (wMsg) {
  258. case WM_CREATE:
  259. break;
  260. case WM_ERASEBKGND:
  261. break;
  262. case WM_PAINT:
  263. hdc = BeginPaint(hWnd, &ps);
  264. if ( fFullScreen ) {
  265. HBITMAP hbmBackground;
  266. HDC hdcMem;
  267. BITMAP bm;
  268. BOOL Drawn;
  269. LOGFONT LogFont;
  270. HFONT hFont,hFontOld;
  271. COLORREF crBk,crTx;
  272. Drawn = FALSE;
  273. GetClientRect(hWnd, &rc);
  274. if(hbmBackground = LoadBitmap(MyDllModuleHandle,MAKEINTRESOURCE(IDB_BACKGROUND))) {
  275. if(hdcMem = CreateCompatibleDC(ps.hdc)) {
  276. crBk = SetBkColor(ps.hdc,CR_DKBLUE);
  277. crTx = SetTextColor(ps.hdc,CR_BLACK);
  278. SelectObject(hdcMem,hbmBackground);
  279. GetObject(hbmBackground,sizeof(BITMAP),&bm);
  280. StretchBlt(
  281. ps.hdc,
  282. 0,0,
  283. ScreenWidth+1,
  284. ScreenHeight+1,
  285. hdcMem,
  286. 0,0,
  287. bm.bmWidth,bm.bmHeight,
  288. SRCCOPY
  289. );
  290. DeleteDC(hdcMem);
  291. SetBkColor(ps.hdc, crBk);
  292. SetTextColor(ps.hdc, crTx);
  293. Drawn = TRUE;
  294. }
  295. DeleteObject(hbmBackground);
  296. }
  297. if(!Drawn) {
  298. PatBlt(ps.hdc,0,0,ScreenWidth,ScreenHeight,BLACKNESS);
  299. }
  300. ZeroMemory(&LogFont,sizeof(LOGFONT));
  301. LogFont.lfHeight = -1 * (GetDeviceCaps(ps.hdc,LOGPIXELSY) * POINTSIZE_WASHTEXT / 72);
  302. LogFont.lfWeight = FW_DONTCARE;
  303. //LogFont.lfItalic = TRUE;
  304. LogFont.lfCharSet = DEFAULT_CHARSET;
  305. LogFont.lfQuality = PROOF_QUALITY;
  306. LogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN;
  307. lstrcpy(LogFont.lfFaceName,"MS Serif");
  308. if(hFont = CreateFontIndirect(&LogFont)) {
  309. TCHAR Buffer[128];
  310. UINT i;
  311. i = LoadString(MyDllModuleHandle,IDS_WINDOWS_NT_SETUP,Buffer,sizeof(Buffer)/sizeof(TCHAR));
  312. hFontOld = SelectObject(ps.hdc,hFont);
  313. SetTextColor(ps.hdc, RGB(255,255,255));
  314. SetBkMode(ps.hdc, TRANSPARENT);
  315. ExtTextOut(ps.hdc,X_WASHTEXT,Y_WASHTEXT,ETO_CLIPPED,&rc,Buffer,i,NULL);
  316. SelectObject(ps.hdc, hFontOld);
  317. DeleteObject(hFont);
  318. }
  319. if(cAdvertIndex >= 0) {
  320. FPaintBmp( hWnd, hdc ) ;
  321. }
  322. }
  323. EndPaint(hWnd, &ps);
  324. break;
  325. case WM_ACTIVATEAPP:
  326. if (wParam != 0) {
  327. SetWindowPos(
  328. hWnd,
  329. NULL,
  330. 0, 0, 0, 0,
  331. SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
  332. );
  333. }
  334. return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  335. case WM_NCHITTEST: {
  336. extern BOOL WaitingOnChild;
  337. if(WaitingOnChild) {
  338. return(HTERROR);
  339. } else {
  340. return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  341. }
  342. }
  343. case WM_TIMER:
  344. if ( wParam == TimerId && cAdvertIndex >= 0 ){
  345. FHandleBmpTimer() ;
  346. }
  347. break ;
  348. case WM_CLOSE:
  349. if (HdlgStackTop() != NULL) {
  350. SendMessage(HdlgStackTop(), WM_CLOSE, 0, 0L);
  351. } else {
  352. MessageBeep(0);
  353. }
  354. break;
  355. case STF_UI_EVENT:
  356. if (!FGenericEventHandler(hInst, hWnd, wMsg, wParam, lParam)) {
  357. if (hWndShell != NULL) {
  358. SendMessage(hWndShell, (WORD)STF_ERROR_ABORT, 0, 0);
  359. }
  360. }
  361. break;
  362. case STF_SHL_INTERP:
  363. if (!FInterpretNextInfLine(wParam, lParam)) {
  364. if (hWndShell != NULL) {
  365. SendMessage(hWndShell, (WORD)STF_ERROR_ABORT, 0, 0);
  366. }
  367. }
  368. break;
  369. case STF_HELP_DLG_DESTROYED:
  370. case STF_INFO_DLG_DESTROYED:
  371. case STF_EDIT_DLG_DESTROYED:
  372. case STF_RADIO_DLG_DESTROYED:
  373. case STF_LIST_DLG_DESTROYED:
  374. case STF_MULTI_DLG_DESTROYED:
  375. case STF_QUIT_DLG_DESTROYED:
  376. case STF_COMBO_DLG_DESTROYED:
  377. case STF_MULTICOMBO_DLG_DESTROYED:
  378. case STF_MULTICOMBO_RADIO_DLG_DESTROYED:
  379. case STF_DUAL_DLG_DESTROYED:
  380. case STF_MAINT_DLG_DESTROYED:
  381. break;
  382. case WM_ENTERIDLE:
  383. if(wParam == MSGF_DIALOGBOX) {
  384. SendMessage((HWND)lParam,WM_ENTERIDLE,wParam,lParam);
  385. }
  386. return(0);
  387. case WM_SETCURSOR:
  388. SetCursor(CurrentCursor);
  389. return(TRUE);
  390. case WM_DESTROY:
  391. if ( pGlobalContext() ) {
  392. szExitCode = SzFindSymbolValueInSymTab( EXIT_CODE );
  393. if ( szExitCode && (szExitCode[0] != '\0')) {
  394. ExitCode = atoi( szExitCode );
  395. } else {
  396. ExitCode = SETUP_ERROR_GENERAL;
  397. }
  398. FCloseWinHelp(hWnd);
  399. }
  400. FTermHook();
  401. PostQuitMessage(ExitCode);
  402. break;
  403. case STF_ERROR_ABORT:
  404. FCloseWinHelp(hWnd);
  405. RebootMachineIfNeeded();
  406. FFlashParentActive() ;
  407. if(OwnProcess) {
  408. ExitProcess(ExitCode);
  409. } else {
  410. FDestroyShellWindow();
  411. }
  412. break;
  413. case WM_COMMAND:
  414. switch (LOWORD(wParam)) {
  415. case ID_HELPBUTTON:
  416. FProcessWinHelp(hWnd);
  417. break;
  418. default:
  419. return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  420. }
  421. break;
  422. default:
  423. return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  424. }
  425. return(0L);
  426. }
  427. VOID
  428. SetSupportLibHandle(
  429. IN HANDLE Handle
  430. )
  431. {
  432. SupportLibHandle = Handle;
  433. }
  434. VOID
  435. RebootMachineIfNeeded(
  436. )
  437. {
  438. SZ sz;
  439. BOOLEAN OldState;
  440. NTSTATUS Status;
  441. if ( pGlobalContext()
  442. && ( sz = SzFindSymbolValueInSymTab("!STF_INSTALL_TYPE") ) != (SZ)NULL
  443. && !lstrcmpi( sz, "SETUPBOOTED" ) ) {
  444. Status = RtlAdjustPrivilege(
  445. SE_SHUTDOWN_PRIVILEGE,
  446. TRUE,
  447. FALSE,
  448. &OldState);
  449. if( NT_SUCCESS( Status ) ) {
  450. if(OwnProcess) {
  451. ExitWindowsEx(EWX_REBOOT, 0);
  452. }
  453. }
  454. }
  455. }
  456. VOID FDestroyShellWindow ( VOID )
  457. {
  458. if ( bTimerEnabled ) {
  459. KillTimer( hWndShell, TimerId ) ;
  460. }
  461. if ( hwParam ) {
  462. EnableWindow( hwParam, TRUE );
  463. SetActiveWindow( hwParam ) ;
  464. }
  465. DestroyWindow( hWndShell ) ; // needed to kill bootstrapper
  466. }
  467. // Set the parent app's window, if any, to appear
  468. // active or inactive, according to 'On'.
  469. VOID FFlashParentWindow ( BOOL On )
  470. {
  471. if ( hwParam == NULL || On == fParamFlashOn )
  472. return ;
  473. fParamFlashOn = On ;
  474. FlashWindow( hwParam, fTrue ) ;
  475. }
  476. VOID FFlashParentActive ( VOID )
  477. {
  478. if ( hwParam == NULL )
  479. return ;
  480. // We don't know what state the parent is in. If
  481. // we flash and find that it WAS active, do it again.
  482. if ( FlashWindow( hwParam, fTrue ) )
  483. FlashWindow( hwParam, fTrue ) ;
  484. }
  485. // Start the timer sending WM_TIMER messages to the
  486. // main window.
  487. VOID FSetTimer ( VOID )
  488. {
  489. bTimerEnabled = (SetTimer( hWndShell, TimerId, TimerInterval, NULL ) != 0);
  490. }
  491. // This routine maintains a RECT structure defining the
  492. // largest rectangle modified by an "advertising" bitmap.
  493. // Its value is used to invalidate only the exact portions
  494. // of the shell window.
  495. static void computeBmpUpdateRect ( HBITMAP hbmNext )
  496. {
  497. BITMAP bm ;
  498. RECT rc ;
  499. int ix, iy ;
  500. // Get info about this bitmap
  501. GetObject( hbmNext, sizeof bm, & bm ) ;
  502. // Compute the rectangle it will occupy
  503. GetClientRect( hWndShell, & rc ) ;
  504. ix = (rc.right - rc.left) / 100 ;
  505. ix *= cxAdvert ;
  506. iy = (rc.bottom - rc.top) / 100 ;
  507. iy *= cyAdvert ;
  508. rc.left = ix ;
  509. rc.right = ix + bm.bmWidth ;
  510. rc.top = iy ;
  511. rc.bottom = iy + bm.bmHeight ;
  512. // Compute the max rect of this and prior history
  513. if ( rcBmpMax.left == -1 ) {
  514. rcBmpMax = rc ;
  515. } else {
  516. if ( rc.left < rcBmpMax.left )
  517. rcBmpMax.left = rc.left ;
  518. if ( rc.top < rcBmpMax.top )
  519. rcBmpMax.top = rc.top ;
  520. if ( rc.right > rcBmpMax.right )
  521. rcBmpMax.right = rc.right ;
  522. if ( rc.bottom > rcBmpMax.bottom )
  523. rcBmpMax.bottom = rc.bottom ;
  524. }
  525. }
  526. /*
  527. * Update the BMP being displayed unless the cycle is zero seconds.
  528. *
  529. * The logic works as follows: If the cycle time is > 1, then
  530. * the bitmaps just cycle in a loop, with each bitmap being
  531. * displayed for the time given.
  532. *
  533. * If the cycle type is == 1, then the display is synchronized
  534. * with the copy dialogs completion percentage. The global variable
  535. * "gaugeCopyPercentage" is monitored, and each time it moves
  536. * into a new "band", the bit map is updated. Band size is determined
  537. * by dividing the 100% level by the number of bitmaps. The
  538. * routine guarantees that no bitmap will appear for less than 15
  539. * seconds. When the copy operation complets, it sets gaugeCopyPercentage
  540. * back to -1 and the INF is responsible for calling BmpHide to tear
  541. * down the bitmaps.
  542. */
  543. VOID FHandleBmpTimer ( VOID )
  544. {
  545. #define MINIMUM_BITMAP_CYCLE 15
  546. static DWORD dwFirstTime = 0;
  547. static DWORD dwLastTime = 0 ;
  548. static INT cIndexLast = -1 ;
  549. if ( cAdvertIndex >= 0 && cAdvertCycleSeconds != 0 ) {
  550. INT cIndexMax;
  551. INT iBmp = cIndexLast;
  552. DWORD dwCurrTime = GetCurrentTime();
  553. DWORD dwElapsedCycles;
  554. // Count the number of bitmaps
  555. for ( cIndexMax = 0 ;
  556. hbmAdvertList[cIndexMax] ;
  557. cIndexMax++ ) ;
  558. // See if we're based on percentages or timing
  559. if ( cAdvertCycleSeconds == 1 ) {
  560. // Percentages: check percentage complete of copy operation.
  561. // Don't update display if gauge isn't active yet
  562. if ( gaugeCopyPercentage >= 0 ) {
  563. if ( gaugeCopyPercentage >= 100 )
  564. gaugeCopyPercentage = 99 ;
  565. iBmp = gaugeCopyPercentage / (100 / cIndexMax) ;
  566. if ( iBmp >= cIndexMax )
  567. iBmp = cIndexMax - 1 ;
  568. }
  569. } else {
  570. // Timing: see if the current bitmap has expired
  571. if ( dwFirstTime == 0 )
  572. dwFirstTime = dwCurrTime ;
  573. dwElapsedCycles = (dwCurrTime - dwFirstTime)
  574. / (cAdvertCycleSeconds * TimerInterval) ;
  575. iBmp = dwElapsedCycles % cIndexMax ;
  576. }
  577. if ( iBmp != cIndexLast
  578. && (dwLastTime + MINIMUM_BITMAP_CYCLE) < dwCurrTime ) {
  579. cAdvertIndex = iBmp ;
  580. computeBmpUpdateRect( hbmAdvertList[ cAdvertIndex ] ) ;
  581. InvalidateRect( hWndShell, & rcBmpMax, FALSE ) ;
  582. UpdateWindow( hWndShell ) ;
  583. dwLastTime = dwCurrTime ;
  584. }
  585. } else if ( cAdvertIndex < 0 && cIndexLast >= 0 ) {
  586. // Reset last cycle timer.
  587. dwLastTime = dwFirstTime = 0 ;
  588. // Reset largest BMP rectangle.
  589. rcBmpMax.top =
  590. rcBmpMax.left =
  591. rcBmpMax.right =
  592. rcBmpMax.bottom = -1 ;
  593. }
  594. cIndexLast = cAdvertIndex ;
  595. }
  596. VOID FPaintBmp ( HWND hwnd, HDC hdc )
  597. {
  598. HDC hdcBits;
  599. BITMAP bm;
  600. RECT rect ;
  601. INT ix, iy ;
  602. HDC hdcLocal = NULL ;
  603. if ( hdc == NULL )
  604. {
  605. hdcLocal = hdc = GetDC( hwnd ) ;
  606. if ( hdc == NULL )
  607. return ;
  608. }
  609. GetClientRect( hwnd, & rect ) ;
  610. ix = (rect.right - rect.left) / 100 ;
  611. ix *= cxAdvert ;
  612. iy = (rect.bottom - rect.top) / 100 ;
  613. iy *= cyAdvert ;
  614. hdcBits = CreateCompatibleDC( hdc ) ;
  615. if (hdcBits) {
  616. GetObject(hbmAdvertList[cAdvertIndex], sizeof (BITMAP), & bm ) ;
  617. SelectObject( hdcBits, hbmAdvertList[cAdvertIndex] ) ;
  618. BitBlt( hdc, ix, iy,
  619. bm.bmWidth,
  620. bm.bmHeight,
  621. hdcBits,
  622. 0, 0, SRCCOPY ) ;
  623. DeleteDC( hdcBits ) ;
  624. }
  625. if ( hdcLocal )
  626. {
  627. ReleaseDC( hwnd, hdcLocal ) ;
  628. }
  629. }
  630. //
  631. // NOTE: This function is NOT NOT NOT serially reentrant!
  632. // It relies on the caller to free this module and then reload it
  633. // in between calls!!!
  634. //
  635. BOOL
  636. LegacyInfInterpret(
  637. IN HWND OwnerWindow,
  638. IN PCSTR InfFilename,
  639. IN PCSTR InfSection, OPTIONAL
  640. IN PCHAR ExtraVariables,
  641. OUT PSTR InfResult,
  642. IN DWORD BufferSize,
  643. OUT int *InterpResult,
  644. IN PCSTR InfSourceDir OPTIONAL
  645. )
  646. {
  647. PSTR CommandLine;
  648. PSTR ArgvLine;
  649. PSTR ptr;
  650. PSTR Source;
  651. PSTR Sym;
  652. PSTR Val;
  653. PVOID p;
  654. UINT Length;
  655. UINT RequiredLength;
  656. BOOL b;
  657. int argvsize;
  658. int argc;
  659. char **argv;
  660. CHAR Window[24];
  661. #define CLINE_SIZE 32768
  662. b = FALSE;
  663. //
  664. // Reentrancy control.
  665. //
  666. if(!EnterInterpreter()) {
  667. return(FALSE);
  668. }
  669. //
  670. // Initialize the buffer that may be used to contain list of services modified during
  671. // this INF run. (This will only be used if !LEGACY_DODEVINSTALL is set.)
  672. //
  673. ServicesModified = NULL;
  674. ServicesModifiedSize = 0;
  675. //
  676. // Allocate memory for the command line
  677. //
  678. CommandLine = SAlloc(CLINE_SIZE);
  679. if(!CommandLine) {
  680. return(FALSE);
  681. }
  682. CommandLine[0] = L'\0';
  683. //
  684. // Allocate memory for the "-s <filename>" part
  685. //
  686. Source = SAlloc(MAX_PATH + 5);
  687. if(!Source) {
  688. SFree(CommandLine);
  689. return (FALSE);
  690. }
  691. Source[0] = L'\0';
  692. if(IsWindow(OwnerWindow)) {
  693. wsprintf(Window," -w %u",OwnerWindow);
  694. } else {
  695. Window[0] = 0;
  696. Window[1] = 0;
  697. }
  698. if(InfSourceDir) {
  699. _snprintf(
  700. Source,
  701. (MAX_PATH + 5),
  702. " -s %s",
  703. InfSourceDir);
  704. }
  705. //
  706. // Create the minimum sized command line that need be parsed in an
  707. // argc/argv format
  708. //
  709. _snprintf(
  710. CommandLine,
  711. CLINE_SIZE - 1,
  712. "setup -f%s",
  713. Window);
  714. CommandLine[CLINE_SIZE-1] = 0;
  715. //
  716. // Create a dummy argv list -> required to be parse compatible with
  717. // dll_main()
  718. //
  719. ArgvLine = SAlloc ( strlen(CommandLine) + 1 );
  720. if(!ArgvLine) {
  721. SFree(CommandLine);
  722. SFree(Source);
  723. return (FALSE);
  724. }
  725. //
  726. // Allocate storage for the argv
  727. //
  728. argvsize = 8;
  729. argv = SAlloc( argvsize * sizeof( char * ) );
  730. if(!argv) {
  731. SFree(CommandLine);
  732. SFree(Source);
  733. SFree(ArgvLine);
  734. return (FALSE);
  735. }
  736. //
  737. // Create the argv list
  738. //
  739. strcpy(ArgvLine,CommandLine);
  740. ptr = ArgvLine;
  741. argv[0] = ptr;
  742. argc = 1;
  743. while(*ptr != '\0') {
  744. if(argc == argvsize) {
  745. argvsize += 8;
  746. argv = SRealloc( argv, argvsize * sizeof( char * ) );
  747. if(!argv) {
  748. SFree(CommandLine);
  749. SFree(Source);
  750. SFree(ArgvLine);
  751. return (FALSE);
  752. }
  753. }
  754. if(*ptr == ' ') {
  755. while(*ptr == ' ') {
  756. *ptr++ = '\0';
  757. }
  758. argv[argc++] = ptr;
  759. } else {
  760. ptr++;
  761. }
  762. }
  763. //
  764. // Create the real command line now. If the caller specified an inf section,
  765. // then he wants to call a particular section in an inf, via legacy.inf.
  766. // If the caller did not specify an inf section, then he wants to invoke
  767. // [Shell Commands] in the given inf, directly (ie, not via legacy.inf).
  768. //
  769. _snprintf(
  770. CommandLine,
  771. CLINE_SIZE - 1,
  772. "setup -f -i %s%s%s -t LEGACY_TARGET_INF = %s -t LEGACY_TARGET_SECTION = %s",
  773. InfSection ? "legacy.inf" : InfFilename,
  774. Window,
  775. Source,
  776. InfFilename,
  777. InfSection ? InfSection : "\"Shell Commands\""
  778. );
  779. CommandLine[CLINE_SIZE-1] = 0;
  780. //
  781. // Now add the extra symbols to the command line.
  782. //
  783. Sym = ExtraVariables;
  784. while(*Sym) {
  785. Val = Sym + strlen(Sym) + 1;
  786. Length = strlen(Sym) + strlen(Val) + 8;
  787. if(strlen(CommandLine) + Length <= CLINE_SIZE) {
  788. strcat(CommandLine," -t ");
  789. strcat(CommandLine,Sym);
  790. strcat(CommandLine," = ");
  791. strcat(CommandLine,Val);
  792. }
  793. Sym = Val + strlen(Val) + 1;
  794. }
  795. //
  796. // Set a global pointer to the area and size of the return buffer
  797. //
  798. LastShellReturn = InfResult;
  799. LastShellReturnSize = BufferSize;
  800. if(p = SRealloc(CommandLine,strlen(CommandLine)+1)) {
  801. //
  802. // OK, let 'er rip.
  803. //
  804. OwnProcess = FALSE;
  805. CommandLine = p;
  806. *InterpResult = real_dll_main(argc,argv,CommandLine);
  807. b = TRUE;
  808. }
  809. //
  810. // The caller is not going to call our LegacyInfGetModifiedSvcList() API
  811. // if this routine returns failure. So we need to clean up the buffer now,
  812. // if we failed.
  813. //
  814. if((!b || (*InterpResult != SETUP_ERROR_SUCCESS)) && ServicesModified) {
  815. SFree(ServicesModified);
  816. ServicesModified = NULL;
  817. ServicesModifiedSize = 0;
  818. }
  819. LastShellReturn = NULL;
  820. LastShellReturnSize = 0;
  821. SFree(Source);
  822. SFree(CommandLine);
  823. return(b);
  824. }
  825. BOOL
  826. EnterInterpreter(
  827. VOID
  828. )
  829. {
  830. static LONG InInterpreter = -1;
  831. //
  832. // The InInterpreter flag starts out at -1. The first increment
  833. // makes it 0; subsequent increments make it > 0. Only the first
  834. // increment will allow entry into the module.
  835. //
  836. return(InterlockedIncrement(&InInterpreter) == 0);
  837. }