/*
*******************************************************************************
* Copyright (c) 1996-97 Digi International Inc., All Rights Reserved          *
*                                                                             *
* This  software  contains  proprietary  and  confidential   information   of *
* Digi International  Inc.   By  accepting  transfer  of this copy, Recipient *
* agrees to retain this software in  confidence,  to  prevent  disclosure  to *
* others,  and  to make no  use of this software other than that for which it *
* was delivered.  This is an unpublished copyright work  Digi   International *
* Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is *
* strictly prohibited.                                                        *
*                                                                             *
* Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc. *
* Confidential  when   combined   with   the   aggregated  modules  for  this *
* product) OBJECT CODE ONLY SOURCE MATERIALS                                  *
*                                                                             *
* (C) COPYRIGHT Digi International Inc. 1996-97                               *
*                                                                             *
* All Rights Reserved                                                         *
*                                                                             *
* US   Government   Users   Restricted   Rights   -   Use,   duplication   or *
* disclosure  restricted by GSA ADP Schedule Contract with Digi International *
* Inc.                                                                        *
*                                                                             *
*******************************************************************************
*/

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <crtdbg.h>

#include "detect.h"
#include "detectisa.h"
#include "detectpci.h"

#include "resource.h"


static HINSTANCE ghInstance = NULL;
static HWND ghwndParent = NULL;

extern int WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
{
   UNREFERENCED_PARAMETER(lpReserved);

   switch (dwReason)
   {
      case DLL_PROCESS_ATTACH:
      {
         DebugOutput(TEXT("Initializing!\n"));
         ghInstance = hInstance;
         break;
      }

      case DLL_PROCESS_DETACH:
      {
         DebugOutput(TEXT("Terminating!\n"));
         break;
      }

      default: break;
   }

    return 1;
}

extern void GetString(int const nID, TCHAR * const pszMsg, int const cchMax)
{
   _ASSERTE(ghInstance != NULL);
   _ASSERTE(pszMsg != NULL);
   _ASSERTE(cchMax > 0);

	if ((ghInstance != NULL) && (pszMsg != NULL) && (cchMax > 0))
      LoadString(ghInstance, nID, pszMsg, cchMax);
}

extern int Message(int const nID, int const uiType)
{
   static TCHAR szTitle[256] = TEXT("");
	TCHAR szMsg[256] = TEXT("");

   _ASSERTE(IsWindow(ghwndParent));

   if (szTitle[0] == TEXT('\0'))
      GetString(IDS_APPNAME, szTitle, sizeof(szTitle));

	GetString(nID, szMsg, sizeof(szMsg));
	return MessageBox(ghwndParent, szMsg, szTitle, uiType);
}

static BOOL ValidComponent(char const * const pszComponent)
{
	BOOL fValid = FALSE;
	static char const * const apszValidComponent[] =
	{
		"SyncPort",
		"Sync570",
      "DigiRAS",
	};
	int i;

   _ASSERTE(pszComponent != NULL);

   if (pszComponent != NULL)
   {
	   for (i = 0; !fValid && i < ElementCount(apszValidComponent); i++)
		   fValid = (strcmp(pszComponent, apszValidComponent[i]) == 0);
   }
	
	return fValid;
}


/*
	DetectEntry

	called by inf to enumerate adapters

	arguments are:
					Parent HWND
					Component name [INF $(Option)]
               Bus type
					Bus number

               If PCI:
                  Slot number

               Else if ISA:
					   list of used IO base addresses
					   list of used Mem base addresses
					   list of used IRQs

	ppszTextOut is the result:
		{ "FAIL"		   Any failure, or
		  "NO"		   The user does not want to detect, or
        "SUCCESS"    On success.
		  { , , } }	   On success an INF format list of
	                     BusNumber,  SlotNumber, VendorId, DeviceId, SubVendorId, SubSystemId, RevisionId
                     or
                        IOBase, Membase, IRQ
                     for the first adapter found.
*/

DWORD WINAPI DetectEntry(DWORD const cArgs, char const * const apszArgs[], char const ** const ppszTextOut)
{
#define INFSTATUS_FAILURE 0
#define INFSTATUS_SUCCESS 1

   DWORD dwINFStatus = INFSTATUS_FAILURE;

#define INFTEXTOUT_FAILURE "FAIL"
#define INFTEXTOUT_NO      "NO"
#define INFTEXTOUT_SUCCESS "SUCCESS"

   static char szINFTextOut[256];

#if defined(_DEBUG)
   {
      DWORD i;
      DebugOutput(TEXT("DetectEntry arguments:\n"));
      for (i = 0; i < cArgs; i++) DebugOutput(TEXT("  apszArgs[%d] == %s\n"), i, apszArgs[i]);
   }
#endif

   sprintf(szINFTextOut, "{\"%s\"}", INFTEXTOUT_FAILURE);
   *ppszTextOut = szINFTextOut;

   ghwndParent = (HWND) strtoul(apszArgs[Arg_ParentWindow], NULL, 16);
   if (!IsWindow(ghwndParent))
   {
      DebugOutput(TEXT("Window handle passed in (0x%08x) is invalid.\n"), ghwndParent);
      ghwndParent = GetDesktopWindow();
      DebugOutput(TEXT("Using desktop window handle (0x%08x).\n"), ghwndParent);
   }

#if defined(VALIDATE_COMPONENT)
   _ASSERTE(ValidComponent(apszArgs[Arg_ComponentName]));
   if (!ValidComponent(apszArgs[Arg_ComponentName]))
      goto Exit;
#endif

   {
      INTERFACE_TYPE BusType = atoi(apszArgs[Arg_BusType]);
      DWORD BusNumber = atoi(apszArgs[Arg_BusNumber]);

      switch (BusType)
      {
         case Isa:
         {
            if (Message(IDS_DETECTYESNO, MB_YESNO | MB_DEFBUTTON2) != IDYES)
            {
               sprintf(szINFTextOut, "{\"%s\"}", INFTEXTOUT_NO);
            }
            else
            {
		         UINT MemBase = 0;
		         UINT IOBase = 0;
		         UINT IRQ = 0;

               if (!DetectISA(BusType, BusNumber, apszArgs[Arg_IOBaseList], apszArgs[Arg_MemBaseList], apszArgs[Arg_IRQList], &MemBase, &IOBase, &IRQ))
                  goto Exit;

               sprintf(szINFTextOut, "{\"%s\",\"{\"\"%d\"\",\"\"%d\"\",\"\"%d\"\"}\"}", INFTEXTOUT_SUCCESS, IOBase, MemBase, IRQ);
            }

            break;
         }

         case PCIBus:
         {
            DWORD SlotNumber = atoi(apszArgs[Arg_SlotNumber]);
            DIGI_PCI_DATA PciData = {0};

            if (!DetectPCI(BusNumber, SlotNumber, &PciData))
               goto Exit;

            sprintf(szINFTextOut, "{\"%s\",\"{\"\"%d\"\","
                                             "\"\"%d\"\","
                                             "\"\"%d\"\","
                                             "\"\"%d\"\","
                                             "\"\"%d\"\","
                                             "\"\"%d\"\","
                                             "\"\"%d\"\"}\"}",
                    INFTEXTOUT_SUCCESS,
                    PciData.BusNumber, PciData.SlotNumber, 
                    PciData.VendorId, PciData.DeviceId, PciData.SubVendorId, 
                    PciData.SubSystemId, PciData.RevisionId);

            break;
         }

         default:
         {
            _ASSERTE(FALSE);
            goto Exit;
            break;
         }
      }
   }

   dwINFStatus = INFSTATUS_SUCCESS;
      
Exit:
   DebugOutput(TEXT("Exiting DetectEntry(): dwINFStatus == %d, *ppszTextOut == %s\n"), dwINFStatus, *ppszTextOut);
   return dwINFStatus;
}
