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