home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / directx2 / sdk / samples / setup / dinstall.c next >
Encoding:
C/C++ Source or Header  |  1996-05-28  |  19.0 KB  |  601 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 <windows.h>
  10. #include <shellapi.h>   // for SHFileOperation
  11. #include <shlobj.h>     // for SHBroweForFolder
  12. #include "dsetup.h"
  13. #include "dinstall.h"
  14.  
  15. /*
  16.  * defines used for compile time reminder messages
  17.  */
  18. #define QUOTE(x) #x
  19. #define QQUOTE(y) QUOTE(y)
  20. #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) "):" str
  21.  
  22. /*
  23.  * global constants and macros
  24.  */
  25. #define BUFFER_SIZE 512
  26.  
  27. #define LoadStrFromRes(uID,lpBuffer) \
  28. LoadString (GetModuleHandle(NULL),\
  29.             (uID),\
  30.             (lpBuffer),\
  31.             sizeof((lpBuffer)));
  32.  
  33.  
  34. /*
  35.  * list of files that will be copied from the source directory to
  36.  * to the directory the game is created in
  37.  */
  38. static char* copy_list [] =
  39. {
  40.         "ROCKEM3D.EXE",
  41.         "ARENA.X",
  42.         "BLOCK1.WAV",
  43.         "BLOCK2.WAV",
  44.         "BLOCK3.WAV",
  45.         "CBOO.WAV",
  46.         "CLOOP.WAV",
  47.         "CYEAH.WAV",
  48.         "DEBRIS_B.X",
  49.         "DEBRIS_R.X",
  50.         "DEFEND1.WAV",
  51.         "DEFEND2.WAV",
  52.         "DEMECH.X",
  53.         "DEMECHBK.PPM",
  54.         "DEMECHBT.PPM",
  55.         "DEMECHCH.PPM",
  56.         "DEMECHGR.PPM",
  57.         "DEMECHH1.PPM",
  58.         "DEMECHH2.PPM",
  59.         "DEMECHHD.PPM",
  60.         "DEMECHHN.PPM",
  61.         "DEMECHLA.PPM",
  62.         "DEMECHLL.PPM",
  63.         "DEMECHUA.PPM",
  64.         "DEMECHUL.PPM",
  65.         "GDK_FILL.PPM",
  66.         "HEAD.WAV",
  67.         "INTRO.WAV",
  68.         "PUNCH.WAV",
  69.         "PUNCH1.WAV",
  70.         "PUNCH2.WAV",
  71.         "PUNCH3.WAV",
  72.         "PUNCH4.WAV",
  73.         "REVDN1.WAV",
  74.         "REVDN2.WAV",
  75.         "REVDN3.WAV",
  76.         "REVUP1.WAV",
  77.         "REVUP2.WAV",
  78.         "REVUP3.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.     wvsprintf(ach, sz, (void*)(&sz+1));
  156.     SetDlgItemText(hDlg, IDC_INFO, ach);
  157. }
  158.  
  159. void _SHFree(void *p)
  160. {
  161.     IMalloc *pm;
  162.     SHGetMalloc(&pm);
  163.     if (pm)
  164.     {
  165.         pm->lpVtbl->Free(pm,p);
  166.         pm->lpVtbl->Release(pm);
  167.     }
  168. }
  169.  
  170. /*
  171.  * build a shortcut in the start menu
  172.  */
  173. void MakeShortcut()
  174. {
  175.     char buf[512];
  176.     char szSetupIni[MAX_PATH];
  177.     char szExeFile[MAX_PATH];
  178.     int len;
  179.     int fh;
  180.     char szGroupName[BUFFER_SIZE];
  181.     char szLinkName[BUFFER_SIZE];
  182.  
  183.     static char setup_ini[] =
  184.         "[progman.groups]\r\n"
  185.         "groupX=%s\r\n"
  186.         "[groupX]\r\n"
  187.         "\"%s\",\"%s\",,,,\"%s\"\r\n";
  188.  
  189.     GetWindowsDirectory(szSetupIni, sizeof(szSetupIni));
  190.     catpath(szSetupIni, "SETUP.INI");
  191.  
  192.     lstrcpy(buf, GameDirectory);
  193.     catpath(buf, copy_list[0]);
  194.     GetShortPathName(buf, szExeFile, sizeof(szExeFile));
  195.  
  196. //  lstrcpy(buf, GameDirectory);
  197. //  GetShortPathName(buf, szWork, sizeof(szWork));
  198.  
  199.     LoadStrFromRes( IDS_GROUP_NAME, szGroupName );
  200.     LoadStrFromRes( IDS_LINK_NAME, szLinkName );
  201.     len = wsprintf(buf, setup_ini, szGroupName, szLinkName, 
  202.                    szExeFile, GameDirectory);
  203.  
  204.     fh = _lcreat(szSetupIni, 0);
  205.  
  206.     if (fh != -1)
  207.     {
  208.         _lwrite(fh, buf, len);
  209.         _lclose(fh);
  210.         WinExec("grpconv -o", SW_HIDE);
  211.     }
  212. }
  213.  
  214. /*
  215.  * dlg proc for wizard dialog box, the setup is controlled from here.
  216.  */
  217. BOOL FAR PASCAL masterDlgProc(HWND hDlg,DWORD dwMessage,DWORD wParam,DWORD lParam)
  218. {
  219.     int         result;
  220.     static int  system_restart;
  221.     static int  current_dialog;
  222.     static int  busy;
  223.  
  224.     char        src[MAX_PATH];
  225.     char        dst[MAX_PATH];
  226.     SHFILEOPSTRUCT fileop;
  227.  
  228.     char       szBuffer[BUFFER_SIZE];
  229.  
  230.     switch(dwMessage)
  231.     {
  232.     case WM_INITDIALOG:
  233.         busy = 0;
  234.         current_dialog = 0;
  235.  
  236.         LoadStrFromRes( IDS_TITLE, szTitle );
  237.         SetWindowText( hDlg, szTitle );
  238.         EnableWindow( GetDlgItem(hDlg, IDC_B), FALSE );
  239.         EnableWindow( GetDlgItem(hDlg, IDC_H), FALSE );
  240.  
  241.         /*
  242.          * set the signon bitmap into our static control
  243.          */
  244.         LoadStrFromRes( IDS_SIGNON_BITMAP_NAME, szBuffer );
  245.         SetBitmap( hDlg, IDC_STATIC, szBuffer, 175, 195 );
  246.  
  247.         /*
  248.          * limit the size of the input of this text field to the length of a path
  249.          * put the default directory to install the game into in it
  250.          * select the whole thing to make it easy for people to replace it
  251.          * set the focus to it
  252.          */
  253.         SendDlgItemMessage( hDlg, IDC_EDIT, EM_LIMITTEXT, MAX_PATH, 0L);
  254.         LoadStrFromRes( IDS_DEFAULT_GAME_DIR, szBuffer );
  255.         SetDlgItemText( hDlg, IDC_EDIT, szBuffer );
  256.         SendDlgItemMessage( hDlg, IDC_EDIT, EM_SETSEL, 0, MAKELONG(256, 256) );
  257.         SetFocus( GetDlgItem(hDlg, IDC_EDIT) );
  258.         /*
  259.          * return 0 here indicating we have set the focus for the dialog box
  260.          * and it doesn't need to help us
  261.          */
  262.         return 0;
  263.  
  264.     case WM_SETCURSOR:
  265.         if (busy)
  266.         {
  267.             SetCursor(LoadCursor(NULL, IDC_WAIT));
  268.             return TRUE;
  269.         }
  270.         break;
  271.  
  272.     case WM_COMMAND:
  273.         switch(wParam)
  274.         {
  275.         case IDOK:
  276.             if( busy > 0 )
  277.             {
  278.                 /*
  279.                  * busy bit keeps us from taking input while we are off doing
  280.                  * things that can create other dialog boxes and end up causing
  281.                  * us to be reentered.
  282.                  */
  283.                 break;
  284.             }
  285.             else if( current_dialog == 0 )
  286.             {
  287.                 int     i;
  288.  
  289.                 busy++;
  290.                 EnableWindow(GetDlgItem(hDlg,IDOK), FALSE);
  291.                 EnableWindow(GetDlgItem(hDlg,IDCANCEL), FALSE);
  292.                 SetCursor(LoadCursor(NULL, IDC_WAIT));
  293.  
  294.                 /*
  295.                  * get the directory the user typed
  296.                  */
  297.                 GetWindowText( GetDlgItem( hDlg,IDC_EDIT ), GameDirectory, sizeof(GameDirectory));
  298.  
  299.                 /*
  300.                  * verify that the typed in directory is valid
  301.                  * by having the SHELL copy WIN.INI to this directory
  302.                  * it will also create the directory for us.
  303.                  */
  304.                 LoadStrFromRes( IDS_CREATE_MSG, szBuffer );
  305.                 SetInfoText(hDlg, szBuffer);
  306.  
  307.                 GetWindowsDirectory(src, sizeof(src));
  308.                 catpath(src,"WIN.INI");
  309.  
  310.                 lstrcpy(dst,GameDirectory);
  311.                 catpath(dst,"SMAG.INI");
  312.  
  313.                 fileop.hwnd     = hDlg;
  314.                 fileop.wFunc    = FO_COPY;
  315.                 fileop.pFrom    = src;
  316.                 fileop.pTo      = dst;
  317.                 fileop.fFlags   = FOF_SILENT | FOF_NOCONFIRMATION;
  318.  
  319.                 if (SHFileOperation(&fileop) != 0)
  320.                 {
  321.                     // failed, the shell gave the user a error.
  322.                     SetInfoText(hDlg, "");
  323.                     EnableWindow(GetDlgItem(hDlg,IDOK), TRUE);
  324.                     EnableWindow(GetDlgItem(hDlg,IDCANCEL), TRUE);
  325.                     busy--;
  326.                     break;
  327.                 }
  328.  
  329.                 /*
  330.                  * the directory is valid now delete the bogus file
  331.                  */
  332.                 fileop.hwnd     = hDlg;
  333.                 fileop.wFunc    = FO_DELETE;
  334.                 fileop.pFrom    = dst;
  335.                 fileop.pTo      = NULL;
  336.                 fileop.fFlags   = FOF_SILENT | FOF_NOCONFIRMATION;
  337.  
  338.                 SHFileOperation(&fileop);
  339.                 SetInfoText(hDlg, "");
  340.  
  341.                 /*
  342.                  * check if there is enough space to install the game
  343.                  * NOTE: there is always enough space at the moment :-)
  344.                  */
  345.                 LoadStrFromRes( IDS_DISK_MSG, szBuffer );
  346.                 SetInfoText(hDlg, szBuffer);
  347.                 if( 0 )
  348.                 {
  349.                     /* your code goes here */
  350.                 }
  351.                 SetInfoText(hDlg, "");
  352.  
  353.                 /*
  354.                  * now setup DirectX
  355.                  */
  356.                 LoadStrFromRes( IDS_INSTALL_MSG, szBuffer );
  357.                 SetInfoText(hDlg, szBuffer);
  358.                 /*
  359.                  * DSETUP_REQUIRESD3D flag is set if the application must have
  360.                  * D3D installed to run.  This may not be the case on some versions
  361.                  * Windows NT.  If this flag is not set you will still get the
  362.                  * error message DSETUPERR_NTWITHNO3D returned from DirectXSetup
  363.                  * but the user will not get a dialog box.
  364.                  * If you set this flag DirectXSetup will inform the end-user
  365.                  * that Direct3D is not present on their Windows NT system.
  366.                  */
  367.                 #ifdef NODIRECT3D
  368.                     #pragma message( REMIND( "This code calls DirectXSetup WITHOUT the" ))
  369.                     #pragma message( REMIND( "DSETUP_REQUIRESD3D flag set." ))
  370.                     #pragma message( REMIND( "You should set this flag if your app" ))
  371.                     #pragma message( REMIND( "requires Direct3D to run." ))
  372.                     #pragma message( REMIND( "You can do this by removing the -DNODIRECT3D" ))
  373.                     #pragma message( REMIND( "flag from the compiler command line" ))
  374.  
  375.                     result = DirectXSetup( hDlg, NULL, DSETUP_DIRECTX );
  376.                     /*
  377.                      * if you don't need Direct3D you must have the following code in place:
  378.                      */
  379.                      if( result == DSETUPERR_NTWITHNO3D )
  380.                      {
  381.                          result = 0;
  382.                      }
  383.                 #else
  384.                     #pragma message( REMIND( "This code calls DirectXSetup with the" ))
  385.                     #pragma message( REMIND( "DSETUP_REQUIRESD3D flag set." ))
  386.                     #pragma message( REMIND( "You should remove this flag if you are" ))
  387.                     #pragma message( REMIND( "not using Direct3D." ))
  388.                     #pragma message( REMIND( "You can do this by adding -DNODIRECT3D to" ))
  389.                     #pragma message( REMIND( "the compile flags" ))
  390.  
  391.                     result = DirectXSetup( hDlg, NULL, DSETUP_REQUIRESD3D | DSETUP_DIRECTX );
  392.                 #endif
  393.                 SetInfoText(hDlg, "");
  394.  
  395.                 if( result < 0 )
  396.                 {
  397.                     LoadStrFromRes( IDS_FAILED_MSG, szBuffer );
  398.                     MessageBox( hDlg, szBuffer, szTitle, 0 );
  399.                     EndDialog(hDlg, result);
  400.                     break;
  401.                 }
  402.  
  403.                 /*
  404.                  * check if there is enough space to install the game
  405.                  * NOTE: there is always enough space at the moment :-)
  406.                  */
  407.                 LoadStrFromRes( IDS_DISK_MSG, szBuffer );
  408.                 SetInfoText(hDlg, szBuffer);
  409.                 if( 0 )
  410.                 {
  411.                     /* your code goes here */
  412.                 }
  413.                 SetInfoText(hDlg, "");
  414.  
  415.                 /*
  416.                  * now copy the files.
  417.                  */
  418.                 system_restart = result;
  419.  
  420.                 LoadStrFromRes( IDS_COPYING_MSG, szBuffer );
  421.                 SetInfoText(hDlg, szBuffer);
  422.                 for( i = 0; i < sizeof( copy_list )/sizeof( copy_list[0] ); i++ )
  423.                 {
  424.                     lstrcpy( src, SetupDirectory );
  425.                     catpath( src, copy_list[i] );
  426.  
  427.                     lstrcpy( dst, GameDirectory );
  428.                     catpath( dst, copy_list[i] );
  429.  
  430.                     LoadStrFromRes( IDS_CURRENT_FILE_MSG, szBuffer );
  431.                     SetInfoText(hDlg, szBuffer, copy_list[i]);
  432.  
  433.                     fileop.hwnd     = hDlg;
  434.                     fileop.wFunc    = FO_COPY;
  435.                     fileop.pFrom    = src;
  436.                     fileop.pTo      = dst;
  437.                     fileop.fFlags   = FOF_SILENT | FOF_NOCONFIRMATION;
  438.  
  439.                     while (result = SHFileOperation(&fileop))
  440.                     {
  441.                         char errorText[MAX_PATH+BUFFER_SIZE];
  442.  
  443.                         LoadStrFromRes( IDS_SETUP_FAILURE_MSG, szBuffer );
  444.                         wsprintf(errorText, szBuffer, copy_list[i] );
  445.                         result = MessageBox( hDlg, errorText, szTitle, MB_RETRYCANCEL );
  446.  
  447.                         if( result == IDCANCEL )
  448.                         {
  449.                             result = -1;
  450.                             break;
  451.                         }
  452.                     }
  453.  
  454.                     if( result == 0 )
  455.                     {
  456.                         SetFileAttributes( dst, FILE_ATTRIBUTE_NORMAL );
  457.                     }
  458.                 }
  459.                 SetInfoText(hDlg, "");
  460.  
  461.                 LoadStrFromRes( IDS_STARTUP_MSG, szBuffer );
  462.                 SetInfoText(hDlg, szBuffer);
  463.                 MakeShortcut();
  464.                 SetInfoText(hDlg, "");
  465.  
  466.                 if( result >= 0 )
  467.                 {
  468.                     /*
  469.                      * hide current controls
  470.                      */
  471.                     ShowWindow( GetDlgItem(hDlg, IDC_EDIT), SW_HIDE );
  472.                     ShowWindow( GetDlgItem(hDlg, IDC_DIRECTIONS1), SW_HIDE );
  473.                     ShowWindow( GetDlgItem(hDlg, IDC_DIRECTIONS2), SW_HIDE );
  474.                     ShowWindow( GetDlgItem(hDlg, IDC_EDITTEXT), SW_HIDE );
  475.                     ShowWindow( GetDlgItem(hDlg, IDC_INFO), SW_HIDE );
  476.                     ShowWindow( GetDlgItem(hDlg, IDC_BROWSE), SW_HIDE );
  477.  
  478.                     if( system_restart )
  479.                     {
  480.                         /*
  481.                          * show new dialogs
  482.                          */
  483.                         ShowWindow( GetDlgItem(hDlg, IDC_REBOOT1), SW_SHOW );
  484.                         ShowWindow( GetDlgItem(hDlg, IDC_REBOOT2), SW_SHOW );
  485.                         LoadStrFromRes( IDS_REBOOT_BUTTON, szBuffer );
  486.                         SetWindowText( GetDlgItem(hDlg, IDOK), szBuffer );
  487.  
  488.                         /*
  489.                          * set the reboot bitmap into our static control
  490.                          */
  491.                         LoadStrFromRes( IDS_REBOOT_BITMAP_NAME, szBuffer );
  492.                         SetBitmap(hDlg, IDC_STATIC, szBuffer, 270, 195);
  493.                         current_dialog++;
  494.                     }
  495.                     else
  496.                     {
  497.                         ShowWindow( GetDlgItem(hDlg, IDC_SUCCESS), SW_SHOW );
  498.                         LoadStrFromRes( IDS_FINISH_BUTTON, szBuffer );
  499.                         SetWindowText( GetDlgItem(hDlg, IDOK), szBuffer );
  500.                         current_dialog++;
  501.                         EnableWindow(GetDlgItem(hDlg,IDOK), TRUE);
  502.                         busy--;
  503.                         break;
  504.                     }
  505.                 }
  506.  
  507.                 EnableWindow(GetDlgItem(hDlg,IDOK), TRUE);
  508.                 EnableWindow(GetDlgItem(hDlg,IDCANCEL), TRUE);
  509.                 busy--;
  510.  
  511.                 if( result < 0 )
  512.                 {
  513.                     EndDialog( hDlg, result );
  514.                 }
  515.             }
  516.             else if (current_dialog == 1)
  517.             {
  518.                 /*
  519.                  * restart windows, kill apps that aren't responding, reboot
  520.                  */
  521.                 if( system_restart )
  522.                 {
  523.                     ExitWindowsEx( EWX_REBOOT, 0 );
  524.                 }
  525.                 else
  526.                 {
  527.                     EndDialog( hDlg, 0 );
  528.                 }
  529.             }
  530.             break;
  531.  
  532.         case IDCANCEL:
  533.             if( !busy )
  534.             {
  535.                 /*
  536.                  * only allow cancel if we aren't doing anything else
  537.                  */
  538.                 EndDialog( hDlg, -1 );
  539.             }
  540.             break;
  541.  
  542.         case IDC_BROWSE:
  543.             if( current_dialog == 0 )
  544.             {
  545.                 BROWSEINFO bi;
  546.                 LPITEMIDLIST pidl;
  547.                 char ach[MAX_PATH];
  548.  
  549.                 bi.hwndOwner      = hDlg;
  550.                 bi.pidlRoot       = NULL;
  551.                 bi.pszDisplayName = ach;
  552.                 bi.lpszTitle      = NULL;
  553.                 bi.ulFlags        = BIF_RETURNONLYFSDIRS;
  554.                 bi.lpfn           = NULL;
  555.                 bi.lParam         = 0;
  556.                 bi.iImage         = 0;
  557.  
  558.                 pidl = SHBrowseForFolder(&bi);
  559.  
  560.                 if (pidl)
  561.                 {
  562.                     SHGetPathFromIDList(pidl, ach);
  563.                     SetDlgItemText(hDlg, IDC_EDIT, ach);
  564.                     _SHFree(pidl);
  565.                 }
  566.             }
  567.             break;
  568.         }
  569.     }
  570.     return 0;
  571. }
  572.  
  573. /* **************************************************************** */
  574. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
  575. {
  576.     TCHAR * p;
  577.     TCHAR * x;
  578.     hinst = hInstance;
  579.  
  580.     /*
  581.      * get our fullpath name and strip the file name
  582.      */
  583.     GetModuleFileName(hInstance, SetupDirectory, sizeof(SetupDirectory));
  584.  
  585.     for (x=p=SetupDirectory; *p; p=AnsiNext(p))
  586.     {
  587.         if (*p == '\\' || *p == '/')
  588.             x = p;
  589.     }
  590.     *x = 0;
  591.  
  592.     /*
  593.      * do the setup thing, it is all one big dialog box that you show
  594.      * and hide things from depending on the screen
  595.      * we just sign on, ask where to install, and install
  596.      */
  597.     DialogBox( hInstance, "DLG_MASTER", NULL, (DLGPROC)masterDlgProc );
  598.  
  599.     return 0;
  600. } /* WinMain */
  601.