From 75032.2070@compuserve.comWed Feb 14 19:29:51 1996
Date: 14 Feb 96 01:18:14 EST
From: Mike Enright <75032.2070@compuserve.com>
To: Jack Thornton <jack@levelfive.com>
Subject: InstallShield+DirectXSetup

I got this from John Miles on WINMM. He said "I did this, and it wasn't hard,
and I'll send it to anyone who asks." I said, "send it to me." This is what he
sent.

John Miles does sound libraries for Windows and Dos in his real job.

--Mike

------------------

Here is the C source and batch file to make it.  You do have to come up with
some way to tell DirectXSetup() where your DIRECTX distribution directory is.  I
do this by scanning all the CD drives in the system until I find the Wing
Commander III disc, for example.

The resulting DXHELPER.DLL should be icomp'ed into your _setup.lib, so that it
ends up in the temporary directory used by InstallShield during setup.

Feel free to distribute (or contribute to the forum library)...

-------------------------------------------------------DXHELPER.C----------------
----------------------------------------
//
// DirectXSetup caller shell
// 
// Linked as DLL because InstallShield does not support WINAPI convention
// 
// John Miles 1/96
//

#include <windows.h>
#include "dsetup.h"

//
// List of CD drives and their associated WC3 CD #s
//

int CD_drive_list[26];
int CD_disk_list [26];
int CD_drive_count;

//
// Get disk # (1=CD1...4=CD4) of CD at specified drive (0=A...25=Z)
//
// Returns -1 if CD is not Wing Commander III disk
//

int CD_get_ID(int drive)
{
   LPTSTR root_path = "x:\\";
   BOOL   result;
   char   volume_name[16];
   int    i;

   root_path[0] = drive + 'A';

   result = GetVolumeInformation(root_path,
                                 volume_name,
                                 sizeof(volume_name)-1,
                                 NULL,
                                 NULL,
                                 NULL,
                                 NULL,
                                 0);

   for (i=0; i < 6; i++)
      {
      if (toupper(volume_name[i]) != "WC3_CD"[i])
         {
         return -1;
         }
      }

   return volume_name[6] - '0';
}

//
// Enumerate CD drives
//

void CD_enumerate(void)
{
   DWORD  drive_mask;
   LPTSTR root_path = "x:\\";
   int    d;

   CD_drive_count = 0;

   drive_mask = GetLogicalDrives();
      
   for (d=0; d < 26; d++)
      {
      if (drive_mask & (1 << d))
         {
         root_path[0] = d + 'A';

         if (GetDriveType(root_path) == DRIVE_CDROM)
            {
            CD_drive_list[CD_drive_count] = d;
            CD_disk_list [CD_drive_count] = CD_get_ID(d);

            if (CD_disk_list[CD_drive_count] != -1)
               {  
               char buff[80];

               wsprintf(buff,"DXHELPER found disk #%d in drive %c:\n",
                  CD_disk_list[CD_drive_count],
                  CD_drive_list[CD_drive_count]+'A');

               OutputDebugStr(buff);
               }

            ++CD_drive_count;
            }
         }
      }
}

//                                                                      
// Get drive (0=A...25=Z) that currently contains disk # (1=CD1...4=CD4)
// and optional root file/directory name to search for                  
//                                                                      
// Return -1 if no CD drive currently contains requested disk           
//                                                                      

int CD_find_volume(int volume, char *file)
{
   char temp_drive[] = "x:\\";
   char temp_pathname[256];
   int  i;

   //
   // Update list in case a CD was changed since the last call
   //


   OutputDebugString("Looking...\n");

   CD_enumerate();

   //
   // Try to find a disk entry that satisfies request
   //

   for (i=0; i < CD_drive_count; i++)
      {
      if (CD_disk_list[i] == volume)
         {
         if (file != NULL)
            {
            temp_drive[0] = CD_drive_list[i] + 'A';
            strcpy(temp_pathname, temp_drive);
            strcat(temp_pathname, file);

            //
            // Hack to see if file exists: try to copy it to NUL device,
            // and check for error
            //

            if (!CopyFile(temp_pathname,
                          "NUL",
                          FALSE))
               {
               OutputDebugStr("Not found: ");
               OutputDebugStr(temp_pathname);
               OutputDebugStr("\n");
               continue;
               }
               OutputDebugStr("Found: ");
               OutputDebugStr(temp_pathname);
               OutputDebugStr("\n");
            }

         return CD_drive_list[i];
         }
      }

   return -1;
}

//
// Exported DirectXSetup function
//
// This is a PASCAL (not WINAPI) function which can be called from an
InstallShield script
//

LONG PASCAL my_DirectXSetup(void)
{
   int drive;
   char path[] = "x:\\DIRECTX";

   OutputDebugString("Entering DXHELPER...\n");

   //
   // Find Wing III CD
   //
 
   drive = CD_find_volume(1,"WC3.ICO");

   if (drive == -1)
      {
      return -8;     // DSETUPERR_CANTFINDDIR
      }

   path[0] = drive + 'A';

   //
   // Call DirectXSetup with <Wing III CD>:\\<DIRECTX path>
   //

   return DirectXSetup(NULL,
                       path,
                       DSETUP_DIRECTX);
}

---------------------------------------------DXHELPER.DEF------------------------
-------------------
LIBRARY	     DXHELPER

DESCRIPTION  'DirectSetup helper'

CODE	     PRELOAD MOVEABLE DISCARDABLE
DATA	     PRELOAD MOVEABLE SHARED

EXPORTS
        my_DirectXSetup

SECTIONS
    .bss     SHARED READ WRITE
    .data    SHARED READ WRITE


-----------------------------------------------MAKEDXH.BAT-----------------------
--------------------
rem Set up environment for 32-bit MS Visual C -- other compilers should work OK
call setset c9
cl -c -W3 -Zp1 -D_X86_=1 -DWIN32 -D_WIN32 -I..\lib dxhelper.c
lib -machine:i386 -def:dxhelper.def dxhelper.obj -out:dxhelper.lib
link @dxhelper.rsp


----------------------------------------------DXHELPER.RSP-----------------------
--------------------
/NODEFAULTLIB
/RELEASE
-align:0x1000
-entry:_DllMainCRTStartup@12
-dll
-debug:full
-debugtype:cv
-base:0x20000000
-out:dxhelper.dll
dxhelper.obj
libc.lib
kernel32.lib
user32.lib
winmm.lib
dsetup.lib
dxhelper.exp

---------------------------------------Excerpts from
SETUP.RUL---------------------------------------

        //
        // DLL declarations (at top of file)
        //

        prototype LONG DXHELPER.my_DirectXSetup();

#define DSETUPERR_BADWINDOWSVERSION     -1
#define DSETUPERR_SOURCEFILENOTFOUND    -2
#define DSETUPERR_BADSOURCESIZE         -3
#define DSETUPERR_BADSOURCETIME         -4
#define DSETUPERR_NOCOPY                -5
#define DSETUPERR_OUTOFDISKSPACE        -6
#define DSETUPERR_CANTFINDINF           -7
#define DSETUPERR_CANTFINDDIR           -8
#define DSETUPERR_INTERNAL              -9

	.	.	.

        //
        // Perform DirectX driver installation
        //

DoDirectXSetup:

        ChangeDirectory(SUPPORTDIR);

        UseDLL(SUPPORTDIR ^ "DXHELPER.DLL");

        nDirectXResult = my_DirectXSetup();

        UnUseDLL(SUPPORTDIR ^ "DXHELPER.DLL");

        switch (nDirectXResult)

           case 0:                              // Success, no reboot needed

           case 1:                              // Success, reboot needed

           case DSETUPERR_BADWINDOWSVERSION:

              MessageBox("Bad Windows version reported by DirectXSetup",
WARNING);
              exit;

           case DSETUPERR_SOURCEFILENOTFOUND:

              MessageBox("Source file not found by DirectXSetup", WARNING);
              exit;

           case DSETUPERR_BADSOURCESIZE:

              MessageBox("Source file could not be verified by DirectXSetup",
WARNING);
              exit;

           case DSETUPERR_BADSOURCETIME:

              MessageBox("DirectXSetup reported incorrect source file
timestamp", WARNING);
              exit;

           case DSETUPERR_NOCOPY:

              MessageBox("DirectXSetup reported incorrect or invalid source
file", WARNING);
              exit;

           case DSETUPERR_CANTFINDINF:

              MessageBox("DirectXSetup could not find a required .INF file",
WARNING);
              exit;

           case DSETUPERR_OUTOFDISKSPACE:

              MessageBox("DirectXSetup ran out of disk space!", WARNING);
              exit;

           case DSETUPERR_CANTFINDDIR:

              MessageBox("DirectXSetup could not find the working directory",
WARNING);
              exit;

           case DSETUPERR_INTERNAL:

              MessageBox("DirectXSetup reported an internal error", WARNING);
              exit;

        endswitch;

-------------------------------At the end of
SETUP.RUL...------------------------------------------

        if (nDirectXResult = 0) then
           szMsg = "Setup is now complete.  You may run Wing Commander III from
" +
              "the Start / Programs menu!";
           MessageBox(szMsg, INFORMATION);
        else
           SdFinishReboot("Setup Complete",
                          "Setup has finished copying files to your "+
                              "computer.  Additionally, Setup has installed "+
                              "the Microsoft DirectX components for
high-performance "+
                              "sound and graphics under Windows.\n\nYou will
need to "+
                              "restart your computer to complete the
installation "+
                              "process.",
                          SYS_BOOTMACHINE,
                          "Once your system has restarted, you may run Wing
Commander "+
                              "III from the Start / Programs menu!",
                          0);
        endif;

