home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / setup / dinstall.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-15  |  29.5 KB  |  652 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995 Microsoft Corporation.  All Rights Reserved.
  4.  *
  5.  *  File:       dinstall.c
  6.  *  Content:    Game SDK sample setup program
  7.  ***************************************************************************/
  8.  
  9. #include <stdio.h>      // for sprintf
  10. #include <windows.h>
  11. #include <shellapi.h>   // for SHFileOperation
  12. #include <shlobj.h>     // for SHBroweForFolder
  13. #include "dsetup.h"
  14. #include "dinstall.h"
  15.  
  16. /*
  17.  * global constants and macros
  18.  */
  19. #define BUFFER_SIZE 512
  20.  
  21. #define LoadStrFromRes(uID,lpBuffer) \
  22. LoadString (GetModuleHandle(NULL),\
  23.             (uID),\
  24.             (lpBuffer),\
  25.             sizeof((lpBuffer)));
  26.  
  27.  
  28. /*
  29.  * list of files that will be copied from the source directory to
  30.  * to the directory the game is created in
  31.  */
  32. static char* copy_list [] =
  33. {
  34.         "ROCKEM3D.EXE",
  35.         "ARENA.X",
  36.         "BLOCK1.WAV",
  37.         "BLOCK2.WAV",
  38.         "BLOCK3.WAV",
  39.         "CBOO.WAV",
  40.         "CLOOP.WAV",
  41.         "CYEAH.WAV",
  42.         "DEBRIS_B.X",
  43.         "DEBRIS_R.X",
  44.         "DEFEND1.WAV",
  45.         "DEFEND2.WAV",
  46.         "DEMECH.X",
  47.         "DEMECHBK.PPM",
  48.         "DEMECHBT.PPM",
  49.         "DEMECHCH.PPM",
  50.         "DEMECHGR.PPM",
  51.         "DEMECHH1.PPM",
  52.         "DEMECHH2.PPM",
  53.         "DEMECHHD.PPM",
  54.         "DEMECHHN.PPM",
  55.         "DEMECHLA.PPM",
  56.         "DEMECHLL.PPM",
  57.         "DEMECHUA.PPM",
  58.         "DEMECHUL.PPM",
  59.         "GDK_FILL.PPM",
  60.         "HEAD.WAV",
  61.         "INTRO.WAV",
  62.         "PUNCH.WAV",
  63.         "PUNCH1.WAV",
  64.         "PUNCH2.WAV",
  65.         "PUNCH3.WAV",
  66.         "PUNCH4.WAV",
  67.         "REVDN1.WAV",
  68.         "REVDN2.WAV",
  69.         "REVDN3.WAV",
  70.         "REVUP1.WAV",
  71.         "REVUP2.WAV",
  72.         "REVUP3.WAV",
  73.         "RANDOM1.WAV",
  74.         "RANDOM2.WAV",
  75.         "RANDOM3.WAV",
  76.         "RANDOM4.WAV",
  77.         "RANDOM5.WAV",
  78.         "RANDOM6.WAV",
  79.         "ROCKEM3D.BIN",
  80.         "ROCKEM3D.MID",
  81.         "ROCKEM3D.PAL",
  82.         "SKMECH.X",
  83.         "SKMECHBK.PPM",
  84.         "SKMECHBT.PPM",
  85.         "SKMECHCH.PPM",
  86.         "SKMECHGR.PPM",
  87.         "SKMECHHN.PPM",
  88.         "SKMECHJD.PPM",
  89.         "SKMECHLA.PPM",
  90.         "SKMECHLL.PPM",
  91.         "SKMECHUA.PPM",
  92.         "SKMECHUL.PPM",
  93.         "SPLASH.PAL",
  94.         "WALK0.WAV",
  95.         "WALK1.WAV",
  96.         "WHOOSH1.WAV",
  97.         "WHOOSH2.WAV",
  98. };
  99.  
  100. static char       szTitle[BUFFER_SIZE];
  101.  
  102. /*
  103.  * prototypes
  104.  */
  105. BOOL FAR PASCAL masterDlgProc( HWND hdlg,DWORD message,DWORD wparam,DWORD lparam );
  106.  
  107. /*
  108.  * globals
  109.  */
  110. static HANDLE   hinst;
  111. static char     GameDirectory[MAX_PATH];    // where the user wants the game
  112. static char     SetupDirectory[MAX_PATH];     // where the user ran setup from
  113.  
  114. /*
  115.  * support functions
  116.  */
  117. void catpath(char *dst, char *src)
  118. {
  119.         int len = lstrlen(dst);
  120.         if (len > 0 && (dst[len-1] != '\\' && dst[len-1] != '/'))
  121.                 lstrcat(dst,"\\");
  122.         lstrcat(dst,src);
  123.  
  124.         // SHFileOperation needs a double null string.
  125.         len = lstrlen(dst);
  126.         dst[len+1] = 0;
  127. }
  128.  
  129. /*
  130.  * set a bitmap into a static control
  131.  */
  132. void SetBitmap(HWND hDlg, int id, char *szBitmap, int w, int h)
  133. {
  134.         HBITMAP hbm;
  135.         HWND hwnd;
  136.  
  137.         hwnd = GetDlgItem(hDlg, id);
  138.  
  139.         if (hwnd == NULL)
  140.                 return;
  141.  
  142.         hbm = (HBITMAP)LoadImage(hinst, szBitmap, IMAGE_BITMAP, w, h,
  143.                 LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS | LR_CREATEDIBSECTION);
  144.  
  145.         if (hbm)
  146.                 hbm = (HBITMAP)SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm);
  147.  
  148.         if (hbm)
  149.                 DeleteObject(hbm);
  150. }
  151.  
  152. void SetInfoText(HWND hDlg, char *sz, ...)
  153. {
  154.         char ach[128];
  155.         va_list marker;
  156.         va_start (marker,sz);
  157.         wvsprintf(ach, sz, marker);
  158.         SetDlgItemText(hDlg, IDC_INFO, ach);
  159. }
  160.  
  161. void _SHFree(void *p)
  162. {
  163.         IMalloc *pm;
  164.         SHGetMalloc(&pm);
  165.         if (pm)
  166.         {
  167.                 pm->lpVtbl->Free(pm,p);
  168.                 pm->lpVtbl->Release(pm);
  169.         }
  170. }
  171.  
  172. /*
  173.  * build a shortcut in the start menu
  174.  */
  175. void MakeShortcut()
  176. {
  177.         char buf[512];
  178.         char szSetupIni[MAX_PATH];
  179.         char szExeFile[MAX_PATH];
  180.         int len;
  181.         int fh;
  182.         char szGroupName[BUFFER_SIZE];
  183.         char szLinkName[BUFFER_SIZE];
  184.  
  185.         static char setup_ini[] =
  186.                 "[progman.groups]\r\n"
  187.                 "groupX=%s\r\n"
  188.                 "[groupX]\r\n"
  189.                 "\"%s\",\"%s\",,,,\"%s\"\r\n";
  190.  
  191.         GetWindowsDirectory(szSetupIni, sizeof(szSetupIni));
  192.         catpath(szSetupIni, "SETUP.INI");
  193.  
  194.         lstrcpy(buf, GameDirectory);
  195.         catpath(buf, copy_list[0]);
  196.         GetShortPathName(buf, szExeFile, sizeof(szExeFile));
  197.  
  198. //  lstrcpy(buf, GameDirectory);
  199. //  GetShortPathName(buf, szWork, sizeof(szWork));
  200.  
  201.         LoadStrFromRes( IDS_GROUP_NAME, szGroupName );
  202.         LoadStrFromRes( IDS_LINK_NAME, szLinkName );
  203.         len = wsprintf(buf, setup_ini, szGroupName, szLinkName,
  204.                 szExeFile, GameDirectory);
  205.  
  206.         fh = _lcreat(szSetupIni, 0);
  207.  
  208.         if (fh != -1)
  209.         {
  210.                 _lwrite(fh, buf, len);
  211.                 _lclose(fh);
  212.                 WinExec("grpconv -o", SW_HIDE);
  213.         }
  214. }
  215.  
  216. /*
  217.  * dlg proc for wizard dialog box, the setup is controlled from here.
  218.  */
  219. BOOL FAR PASCAL masterDlgProc(HWND hDlg,DWORD dwMessage,DWORD wParam,DWORD lParam)
  220. {
  221.         int             result;
  222.         static int  system_restart;
  223.         static int      current_dialog;
  224.         static int  busy;
  225.  
  226.         char        src[MAX_PATH];
  227.         char        dst[MAX_PATH];
  228.         SHFILEOPSTRUCT fileop;
  229.  
  230.         char       szBuffer[BUFFER_SIZE];
  231.  
  232.     switch(dwMessage)
  233.     {
  234.     case WM_INITDIALOG:
  235.                 busy = 0;
  236.                 current_dialog = 0;
  237.  
  238.                 LoadStrFromRes( IDS_TITLE, szTitle );
  239.                 SetWindowText( hDlg, szTitle );
  240.                 EnableWindow( GetDlgItem(hDlg, IDC_B), FALSE );
  241.                 EnableWindow( GetDlgItem(hDlg, IDC_H), FALSE );
  242.  
  243.                 /*
  244.                  * set the signon bitmap into our static control
  245.                  */
  246.                 LoadStrFromRes( IDS_SIGNON_BITMAP_NAME, szBuffer );
  247.                 SetBitmap( hDlg, IDC_STATIC, szBuffer, 175, 195 );
  248.  
  249.                 /*
  250.                  * limit the size of the input of this text field to the length of a path
  251.                  * put the default directory to install the game into in it
  252.                  * select the whole thing to make it easy for people to replace it
  253.                  * set the focus to it
  254.                  */
  255.                 SendDlgItemMessage( hDlg, IDC_EDIT, EM_LIMITTEXT, MAX_PATH, 0L);
  256.                 LoadStrFromRes( IDS_DEFAULT_GAME_DIR, szBuffer );
  257.                         SetDlgItemText( hDlg, IDC_EDIT, szBuffer );
  258.                 SendDlgItemMessage( hDlg, IDC_EDIT, EM_SETSEL, 0, MAKELONG(256, 256) );
  259.                         SetFocus( GetDlgItem(hDlg, IDC_EDIT) );
  260.                 /*
  261.                  * return 0 here indicating we have set the focus for the dialog box
  262.                  * and it doesn't need to help us
  263.                  */
  264.                 return 0;
  265.  
  266.     case WM_SETCURSOR:
  267.         if (busy)
  268.         {
  269.             SetCursor(LoadCursor(NULL, IDC_WAIT));
  270.             return TRUE;
  271.         }
  272.         break;
  273.  
  274.     case WM_COMMAND:
  275.                 switch(wParam)
  276.                 {
  277.                 case IDOK:
  278.                         if( busy > 0 )
  279.                         {
  280.                                 /*
  281.                                  * busy bit keeps us from taking input while we are off doing
  282.                                  * things that can create other dialog boxes and end up causing
  283.                                  * us to be reentered.
  284.                                  */
  285.                                 break;
  286.                         }
  287.                         else if( current_dialog == 0 )
  288.                         {
  289.                                         int     i;
  290.  
  291.                                         busy++;
  292.                                         EnableWindow(GetDlgItem(hDlg,IDOK), FALSE);
  293.                                         EnableWindow(GetDlgItem(hDlg,IDCANCEL), FALSE);
  294.                                         SetCursor(LoadCursor(NULL, IDC_WAIT));
  295.  
  296.                                         /*
  297.                                          * get the directory the user typed
  298.                                          */
  299.                                         GetWindowText( GetDlgItem( hDlg,IDC_EDIT ), GameDirectory, sizeof(GameDirectory));
  300.  
  301.                                         /*
  302.                                          * verify that the typed in directory is valid
  303.                                          * by having the SHELL copy WIN.INI to this directory
  304.                                          * it will also create the directory for us.
  305.                                          */
  306.                                         LoadStrFromRes( IDS_CREATE_MSG, szBuffer );
  307.                                         SetInfoText(hDlg, szBuffer);
  308.  
  309.                                         GetWindowsDirectory(src, sizeof(src));
  310.                                         catpath(src,"WIN.INI");
  311.  
  312.                                         lstrcpy(dst,GameDirectory);
  313.                                         catpath(dst,"SMAG.INI");
  314.  
  315.                                         fileop.hwnd     = hDlg;
  316.                                         fileop.wFunc    = FO_COPY;
  317.                                         fileop.pFrom    = src;
  318.                                         fileop.pTo      = dst;
  319.                                         fileop.fFlags   = FOF_SILENT | FOF_NOCONFIRMATION;
  320.  
  321.                                         if (SHFileOperation(&fileop) != 0)
  322.                                         {
  323.                                                 // failed, the shell gave the user a error.
  324.                                                 SetInfoText(hDlg, "");
  325.                                                 EnableWindow(GetDlgItem(hDlg,IDOK), TRUE);
  326.                                                 EnableWindow(GetDlgItem(hDlg,IDCANCEL), TRUE);
  327.                                                 busy--;
  328.                                                 break;
  329.                                         }
  330.  
  331.                                         /*
  332.                                          * the directory is valid now delete the bogus file
  333.                                          */
  334.                                         fileop.hwnd     = hDlg;
  335.                                         fileop.wFunc    = FO_DELETE;
  336.                                         fileop.pFrom    = dst;
  337.                                         fileop.pTo      = NULL;
  338.                                         fileop.fFlags   = FOF_SILENT | FOF_NOCONFIRMATION;
  339.  
  340.                                         SHFileOperation(&fileop);
  341.                                         SetInfoText(hDlg, "");
  342.  
  343.                                         /*
  344.                                          * check if there is enough space to install the game
  345.                                          * NOTE: there is always enough space at the moment :-)
  346.                                          */
  347.  
  348.                                         LoadStrFromRes( IDS_DISK_MSG, szBuffer );
  349.                                         SetInfoText(hDlg, szBuffer);
  350.  
  351.                                         if( 0 )
  352.                                         {
  353.                                                 /* your code goes here */
  354.                                         }
  355.                                         SetInfoText(hDlg, "");
  356.  
  357.                                         /*
  358.                                          * now setup DirectX
  359.                                          */
  360.                                         LoadStrFromRes( IDS_INSTALL_MSG, szBuffer );
  361.                                         SetInfoText(hDlg, szBuffer);
  362.  
  363.                                         result = DirectXSetup( hDlg, NULL, DSETUP_DIRECTX );
  364.  
  365.                                         SetInfoText(hDlg, "");
  366.  
  367.                                         if( result < 0 )
  368.                                         {
  369.                                                 if (result == DSETUPERR_NOTPREINSTALLEDONNT)
  370.                                                 {
  371.                                                         /*
  372.                                                          *  DirectX comes preinstalled on NT, and can only
  373.                                                          *  be installed in an NT release or Service Pack.
  374.                                                          *  If this error code is returned, then the required
  375.                                                          *  version of DirectX is not preinstalled on this
  376.                                                          *  NT machine.  The user will have to go get
  377.                                                          *  the NT version or Service Pack required, or this
  378.                                                          *  game will not run.  Note that any application
  379.                                                          *  can redistribute an NT Service Pack as long as
  380.                                                          *  it is distributed in its entirety.  Check out
  381.                                                          *  ftp://ftp.microsoft.com/bussys/winnt/winnt-public/fixes
  382.                                                          */
  383.                                                         LoadStrFromRes( IDS_NTFAILED_MSG, szBuffer );
  384.                                                         MessageBox( hDlg, szBuffer, szTitle, 0 );
  385.                                                 }
  386.                                                 else
  387.                                                 {
  388.                                                         LoadStrFromRes( IDS_FAILED_MSG, szBuffer );
  389.                                                         MessageBox( hDlg, szBuffer, szTitle, 0 );
  390.                                                 }
  391.                                                 EndDialog(hDlg, result);
  392.                                                 break;
  393.                                         }
  394.                                         else if( result == 0 )
  395.                                         {
  396.                                                 /*
  397.                                                  *  Check the post-install DirectX Version number,
  398.                                                  *  to check if the game will be able to run.
  399.                                                  *
  400.                                                  *  DirectXSetupGetVersion will get the version
  401.                                                  *  and revision info about the current installation.
  402.                                                  *  Note that since we're calling this after
  403.                                                  *  DirectXSetup, the "current" installation is the
  404.                                                  *  post-install version of DirectX.
  405.                                                  *
  406.                                                  *  Since we don't care about the revision number,
  407.                                                  *  we're leaving that parameter as NULL.
  408.                                                  */
  409.  
  410.                                                 DWORD dwVersion;
  411.  
  412.                                                 if( DirectXSetupGetVersion(&dwVersion, NULL) )
  413.                                                 {
  414.                                                         /*  we need DirectX 3.0 or better, so we're going
  415.                                                          *  to make sure that dwVersion is at least equal
  416.                                                          *  to 0x00040003.  If we needed DirectX 5.0
  417.                                                          *  functionality, we'd check for 0x00040005.
  418.                                                          *
  419.                                                          *  If your game needs specific DX functionality,
  420.                                                          *  this is a good place to check to ensure that
  421.                                                          *  the correct version of DirectX is available.
  422.                                                          *
  423.                                                          *  On Windows NT, DirectX is pre-installed, so
  424.                                                          *  this check will allow notification of NT users
  425.                                                          *  that they'll need to update through a service
  426.                                                          *  pack, or they won't be able to run the game.
  427.                                                          */
  428.  
  429.                                                         if( dwVersion < (DWORD)0x00040003 )
  430.                                                         {
  431.                                                                 sprintf(szBuffer,
  432.                                                                         "Your system is preinstalled with version %d.%d "
  433.                                                                         "of DirectX.  This game requires DirectX version "
  434.                                                                         "4.3 or better to run.\n\n"
  435.                                                                         "Do you want to install the game anyway?",
  436.                                                                         HIWORD(dwVersion), LOWORD(dwVersion));
  437.  
  438.                                                                 result = MessageBox( hDlg, szBuffer, szTitle, MB_YESNO);
  439.  
  440.                                                                 if( result == IDNO )
  441.                                                                 {
  442.                                                                         MessageBox( hDlg,
  443.                                                                         "You've chosen not to install the game.\n\n"
  444.                                                                         "Click \"OK\" to end Setup.",
  445.                                                                         szTitle, MB_OK);
  446.                                                                         EndDialog( hDlg, 0 );
  447.                                                                         break;
  448.                                                                 }
  449.                                                         }
  450.                                                 }
  451.                                         }
  452.  
  453.                                         /*
  454.                                          * check if there is enough space to install the game
  455.                                          * NOTE: there is always enough space at the moment :-)
  456.                                          */
  457.                                         LoadStrFromRes( IDS_DISK_MSG, szBuffer );
  458.                                         SetInfoText(hDlg, szBuffer);
  459.                                         if( 0 )
  460.                                         {
  461.                                                 /* your code goes here */
  462.                                         }
  463.                                         SetInfoText(hDlg, "");
  464.  
  465.                                         /*
  466.                                          * now copy the files.
  467.                                          */
  468.                                         system_restart = result;
  469.  
  470.                                         LoadStrFromRes( IDS_COPYING_MSG, szBuffer );
  471.                                         SetInfoText(hDlg, szBuffer);
  472.  
  473.                                         for( i = 0; i < sizeof( copy_list )/sizeof( copy_list[0] ); i++ )
  474.                                         {
  475.                                                 lstrcpy( src, SetupDirectory );
  476.                                                 catpath( src, copy_list[i] );
  477.  
  478.                                                 lstrcpy( dst, GameDirectory );
  479.                                                 catpath( dst, copy_list[i] );
  480.  
  481.                                                 LoadStrFromRes( IDS_CURRENT_FILE_MSG, szBuffer );
  482.                                                 SetInfoText(hDlg, szBuffer, copy_list[i]);
  483.  
  484.                                                 fileop.hwnd     = hDlg;
  485.                                                 fileop.wFunc    = FO_COPY;
  486.                                                 fileop.pFrom    = src;
  487.                                                 fileop.pTo      = dst;
  488.                                                 fileop.fFlags   = FOF_SILENT | FOF_NOCONFIRMATION;
  489.  
  490.                                                 while (result = SHFileOperation(&fileop))
  491.                                                 {
  492.                                                         char errorText[MAX_PATH+BUFFER_SIZE];
  493.  
  494.                                                         LoadStrFromRes( IDS_SETUP_FAILURE_MSG, szBuffer );
  495.                                                         wsprintf(errorText, szBuffer, copy_list[i] );
  496.                                                         result = MessageBox( hDlg, errorText, szTitle, MB_RETRYCANCEL );
  497.  
  498.                                                         if( result == IDCANCEL )
  499.                                                         {
  500.                                                                 result = -1;
  501.                                                                 break;
  502.                                                         }
  503.                                                 }
  504.  
  505.                                                 if( result == 0 )
  506.                                                 {
  507.                                                         SetFileAttributes( dst, FILE_ATTRIBUTE_NORMAL );
  508.                                                 }
  509.                                         }
  510.                                         SetInfoText(hDlg, "");
  511.  
  512.                                         LoadStrFromRes( IDS_STARTUP_MSG, szBuffer );
  513.                                         SetInfoText(hDlg, szBuffer);
  514.                                         MakeShortcut();
  515.                                         SetInfoText(hDlg, "");
  516.  
  517.                                         if( result >= 0 )
  518.                                         {
  519.                                                 /*
  520.                                                  * hide current controls
  521.                                                  */
  522.                                                 ShowWindow( GetDlgItem(hDlg, IDC_EDIT), SW_HIDE );
  523.                                                 ShowWindow( GetDlgItem(hDlg, IDC_DIRECTIONS1), SW_HIDE );
  524.                                                 ShowWindow( GetDlgItem(hDlg, IDC_DIRECTIONS2), SW_HIDE );
  525.                                                 ShowWindow( GetDlgItem(hDlg, IDC_EDITTEXT), SW_HIDE );
  526.                                                 ShowWindow( GetDlgItem(hDlg, IDC_INFO), SW_HIDE );
  527.                                                 ShowWindow( GetDlgItem(hDlg, IDC_BROWSE), SW_HIDE );
  528.  
  529.                                                 if( system_restart )
  530.                                                 {
  531.                                                         /*
  532.                                                          * show new dialogs
  533.                                                          */
  534.                                                         ShowWindow( GetDlgItem(hDlg, IDC_REBOOT1), SW_SHOW );
  535.                                                         ShowWindow( GetDlgItem(hDlg, IDC_REBOOT2), SW_SHOW );
  536.                                                         LoadStrFromRes( IDS_REBOOT_BUTTON, szBuffer );
  537.                                                         SetWindowText( GetDlgItem(hDlg, IDOK), szBuffer );
  538.  
  539.                                                         /*
  540.                                                          * set the reboot bitmap into our static control
  541.                                                          */
  542.                                                         LoadStrFromRes( IDS_REBOOT_BITMAP_NAME, szBuffer );
  543.                                                         SetBitmap(hDlg, IDC_STATIC, szBuffer, 270, 195);
  544.                                                         current_dialog++;
  545.                                                 }
  546.                                                 else
  547.                                                 {
  548.                                                         ShowWindow( GetDlgItem(hDlg, IDC_SUCCESS), SW_SHOW );
  549.                                                         LoadStrFromRes( IDS_FINISH_BUTTON, szBuffer );
  550.                                                         SetWindowText( GetDlgItem(hDlg, IDOK), szBuffer );
  551.                                                         current_dialog++;
  552.                                                         EnableWindow(GetDlgItem(hDlg,IDOK), TRUE);
  553.                                                         busy--;
  554.                                                         break;
  555.                                                 }
  556.                                         }
  557.  
  558.                                         EnableWindow(GetDlgItem(hDlg,IDOK), TRUE);
  559.                                         EnableWindow(GetDlgItem(hDlg,IDCANCEL), TRUE);
  560.                                         busy--;
  561.  
  562.                                         if( result < 0 )
  563.                                         {
  564.                                                 EndDialog( hDlg, result );
  565.                                         }
  566.                                 }
  567.                                 else if (current_dialog == 1)
  568.                                 {
  569.                                         /*
  570.                                          * restart windows, kill apps that aren't responding, reboot
  571.                                          */
  572.                                         if( system_restart )
  573.                                         {
  574.                                                 ExitWindowsEx( EWX_REBOOT, 0 );
  575.                                         }
  576.                                         else
  577.                                         {
  578.                                                 EndDialog( hDlg, 0 );
  579.                                         }
  580.                                 }
  581.                                 break;
  582.  
  583.                         case IDCANCEL:
  584.                                 if( !busy )
  585.                                 {
  586.                                         /*
  587.                                          * only allow cancel if we aren't doing anything else
  588.                                          */
  589.                                         EndDialog( hDlg, -1 );
  590.                                 }
  591.                                 break;
  592.  
  593.                         case IDC_BROWSE:
  594.                                 if( current_dialog == 0 )
  595.                                 {
  596.                                         BROWSEINFO bi;
  597.                                         LPITEMIDLIST pidl;
  598.                                         char ach[MAX_PATH];
  599.  
  600.                                         bi.hwndOwner      = hDlg;
  601.                                         bi.pidlRoot       = NULL;
  602.                                         bi.pszDisplayName = ach;
  603.                                         bi.lpszTitle      = NULL;
  604.                                         bi.ulFlags        = BIF_RETURNONLYFSDIRS;
  605.                                         bi.lpfn           = NULL;
  606.                                         bi.lParam         = 0;
  607.                                         bi.iImage         = 0;
  608.  
  609.                                         pidl = SHBrowseForFolder(&bi);
  610.  
  611.                                         if (pidl)
  612.                                         {
  613.                                                 SHGetPathFromIDList(pidl, ach);
  614.                                                 SetDlgItemText(hDlg, IDC_EDIT, ach);
  615.                                                 _SHFree(pidl);
  616.                                         }
  617.                                 }
  618.                                 break;
  619.                 }
  620.     }
  621.     return 0;
  622. }
  623.  
  624. /* **************************************************************** */
  625. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
  626. {
  627.         TCHAR * p;
  628.         TCHAR * x;
  629.         hinst = hInstance;
  630.  
  631.         /*
  632.          * get our fullpath name and strip the file name
  633.          */
  634.         GetModuleFileName(hInstance, SetupDirectory, sizeof(SetupDirectory));
  635.  
  636.         for (x=p=SetupDirectory; *p; p=AnsiNext(p))
  637.         {
  638.                 if ((*p == '\\') || (*p == '/'))
  639.                         x = p;
  640.         }
  641.         *x = 0;
  642.  
  643.         /*
  644.          * do the setup thing, it is all one big dialog box that you show
  645.          * and hide things from depending on the screen
  646.          * we just sign on, ask where to install, and install
  647.          */
  648.         DialogBox( hInstance, "DLG_MASTER", NULL, (DLGPROC)masterDlgProc );
  649.  
  650.         return 0;
  651. } /* WinMain */
  652.