/*****************************************************************************
* Copyright (c) 1990-99 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 copyrighted work of Digi International
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
* prohibited.
* 
* Restricted Rights Legend
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7031 or
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -
* Restricted Rights at 48 CFR 52.227-19, as applicable.
*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
*
*****************************************************************************/

#include <windows.h>
#include <setupapi.h>
#include <tchar.h>
#include <stdio.h>
#include <string.h>

#include "oemupgex.h"
#include "oemupgex.cpp"

HMODULE								g_hNetupgrdDll;
NetUpgradeAddSectionPrototype       g_pfnAddSection;
NetUpgradeAddLineToSectionPrototype g_pfnAddLineToSection;
TCHAR                               g_szWorkingDir[MAX_PATH]; 

VENDORINFO g_DigiVendorInfo =
{
    TEXT("Digi International Inc."),
    TEXT("(612) 912-3456"),
    TEXT("http://www.digi.com"),
    TEXT("Please visit our website for further information")
};


#if _DEBUG
TCHAR DbgBuffer[2048];
#endif
                                              
#define PARAMS_FILE                             TEXT( "%ls.reg" )

//============================================================================
// Values for Sync cards.
//
//
//============================================================================


  

//----------------------------------------------------------------------------
// Function:    DLLMAIN
//
// This is the DLL entrypoint handler. 
//----------------------------------------------------------------------------

BOOL
WINAPI
DLLMAIN(
    HINSTANCE hInstance,
    DWORD dwReason,
    PVOID pUnused
    ) 
{

    switch(dwReason) {
        case DLL_PROCESS_ATTACH:
        
            DisableThreadLibraryCalls(hInstance);

            break;
 
        case DLL_PROCESS_DETACH:

            break;

        default:

            break;
    }

    return TRUE;
}


///////////////////////////////////////////////////////////////////////////////
//
// Using RegSaveKey/RegLoadKey requires having the SeBackupPrivelege
//

HANDLE           hToken;
TOKEN_PRIVILEGES tp;
LUID             luid;

VOID EnableBackupPrivelege()
{
   OpenProcessToken( GetCurrentProcess(), 
                     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
                     &hToken ) ;
   LookupPrivilegeValue( NULL, TEXT( "SeBackupPrivilege" ), &luid );
   tp.PrivilegeCount           = 1;
   tp.Privileges[0].Luid       = luid;
   tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
   AdjustTokenPrivileges( hToken, FALSE, &tp,
                          sizeof(TOKEN_PRIVILEGES), NULL, NULL );

}

VOID DisableBackupPrivelege()
{
   AdjustTokenPrivileges( hToken, TRUE, &tp, sizeof(TOKEN_PRIVILEGES),
                          NULL, NULL );
}


EXTERN_C LONG __declspec(dllexport) __stdcall
PreUpgradeInitialize(IN  LPCTSTR         szWorkingDir,
                     IN  NetUpgradeInfo* pNetUpgradeInfo,
                     OUT VENDORINFO*     pviVendorInfo,
                     OUT DWORD*          pdwFlags,
                     OUT LPVOID          pvReserved)
{
   DWORD dwError=ERROR_SUCCESS;

#if _DEBUG
	wsprintf( DbgBuffer, TEXT("DGWANLUP: Enter PreUpgradeInitialize\n") );
	OutputDebugString( DbgBuffer );
	wsprintf( DbgBuffer, TEXT("DGWANLUP: szWorkingDir = %ls\n"),szWorkingDir);
	OutputDebugString( DbgBuffer );
#endif

	// get function address of the two exported functions
	// for writing into the answerfile
	//
	g_hNetupgrdDll = GetModuleHandle(TEXT("netupgrd.dll"));

	if (g_hNetupgrdDll == NULL)
	{
		dwError = ERROR_DLL_INIT_FAILED;
		goto Exit_PreUpgradeInitialize;
	}
	else
	{   
		g_pfnAddSection = (NetUpgradeAddSectionPrototype)GetProcAddress(g_hNetupgrdDll, c_szNetUpgradeAddSection);
		g_pfnAddLineToSection = (NetUpgradeAddLineToSectionPrototype)GetProcAddress(g_hNetupgrdDll, c_szNetUpgradeAddLineToSection);

		if (!g_pfnAddSection || !g_pfnAddLineToSection)
		{
			// this should never occur
			//
			dwError = ERROR_CALL_NOT_IMPLEMENTED;
			goto Exit_PreUpgradeInitialize;
		}
	}

   if ( szWorkingDir == NULL )
   {   
      dwError = ERROR_INVALID_PARAMETER;
      goto Exit_PreUpgradeInitialize;
   } 
   
   wcscpy(g_szWorkingDir,szWorkingDir);
   if ( g_szWorkingDir[wcslen(g_szWorkingDir)-1] == _T('\\') )
   {
		g_szWorkingDir[wcslen(g_szWorkingDir)-1] = _T('\0'); 
   }
   
Exit_PreUpgradeInitialize:
   
#if _DEBUG
	wsprintf( DbgBuffer, TEXT( "DGWANLUP: Exiting PreUpgradeInitialize with status %d\n" ),dwError  );
	OutputDebugString( DbgBuffer );
#endif

   return dwError;
}


long SaveParametersToFile( HKEY hkeyParams, LPCTSTR szNT5InfId, LPCTSTR szSectionName, LPCTSTR szPreNT5InfId )
{

	DWORD		dwError=ERROR_SUCCESS;
	TCHAR       szFilePath[MAX_PATH];
	TCHAR       szFileName[MAX_PATH];
    TCHAR		TmpBuffer[256], TmpSection[256];

	// Construct the File Name
	wsprintf( szFileName, PARAMS_FILE, szSectionName );
	wsprintf( szFilePath, TEXT("%ls\\%ls"),g_szWorkingDir,szFileName);

#if _DEBUG
	wsprintf( DbgBuffer, TEXT( "DGWANLUP: Save Path Name = %ls\n" ), szFilePath  );
	OutputDebugString( DbgBuffer );
#endif

	// Delete file that may already exist from a previously aborted upgrade
	DeleteFile( szFilePath );

	// Obtain the Registry Priveleges and save the Parameters Key to a File
	EnableBackupPrivelege();
	dwError = RegSaveKey( hkeyParams, szFilePath, NULL );
	DisableBackupPrivelege();
   
   if ( dwError != ERROR_SUCCESS )
   {

#if _DEBUG
      wsprintf( DbgBuffer, TEXT("DGWANLUP: RegSaveKey failed: %d, Section: %ls, File: %s\n"),
                        dwError, szSectionName, szFilePath );
      OutputDebugString( DbgBuffer );
#endif

      goto Exit_SaveParametersToFile;
   }  
   
#if _DEBUG      
	wsprintf( DbgBuffer, TEXT("DGWANLUP: %ls params written to file %ls\n"),szSectionName, szFilePath);
	OutputDebugString( DbgBuffer );    
#endif

	// add the top level section
	g_pfnAddSection(szSectionName);

	// add the key InfToRunAfterInstall
    _stprintf(TmpBuffer, TEXT("InfToRunAfterInstall=\"\",%s.SectionToRun"), szSectionName);
    g_pfnAddLineToSection(szSectionName,TmpBuffer); 

    // Add Run Section...
    _stprintf(TmpSection, TEXT("%s.SectionToRun"), szSectionName);	
    g_pfnAddSection(TmpSection);
	
    // add the AddReg key
    _stprintf(TmpBuffer, TEXT("AddReg=%s.SectionToRun.AddReg"), szSectionName);
    g_pfnAddLineToSection(TmpSection,TmpBuffer);

    // now add the AddReg section
    _stprintf(TmpSection, TEXT("%s.SectionToRun.AddReg"), szSectionName);
    g_pfnAddSection(TmpSection);

	// add the File Name To the Registry
//	_stprintf(szTempLine, TEXT("ParamsFile=%s\n"),szFilePath);
//  g_pfnAddLineToSection(szSectionName, szTempLine); 

    _stprintf(TmpBuffer, TEXT("HKR,\"\\\",\"ParamsFile\",0x00000000,\"%s\""), szFilePath);
    g_pfnAddLineToSection(TmpSection,TmpBuffer);


Exit_SaveParametersToFile:    
   return dwError;
}   


long RestoreParametersFromFile( HKEY hkeyParams, LPCTSTR szSectionName)
{

	DWORD		dwError=ERROR_SUCCESS;
	TCHAR       szFilePath[MAX_PATH];
	TCHAR       szFileName[MAX_PATH];
   
	// Construct the File Name
	wsprintf( szFileName, PARAMS_FILE, szSectionName );
	wsprintf( szFilePath, TEXT("%ls\\%ls"),g_szWorkingDir,szFileName);

#if _DEBUG
	wsprintf( DbgBuffer, TEXT( "DGWANLUP: Restore File Name = %ls\n" ), szFilePath  );
	OutputDebugString( DbgBuffer );
#endif

	// Obtain the Registry Priveleges and Restore the Parameters Key to a File
	EnableBackupPrivelege();
	dwError = RegRestoreKey( hkeyParams, szFilePath, 0);
	DisableBackupPrivelege();
   
   if ( dwError != ERROR_SUCCESS )
   {

#if _DEBUG
      wsprintf( DbgBuffer, TEXT("DGWANLUP: RegRestoreKey failed: %d, Section: %ls, File: %ls\n"),
                        dwError, szSectionName, szFilePath );
      OutputDebugString( DbgBuffer );
#endif

      goto Exit_RestoreParametersFromFile;
   }  
   
#if _DEBUG      
	wsprintf( DbgBuffer, TEXT("DGWANLUP: %ls params restored from file %ls\n"),szSectionName, szFilePath);
	OutputDebugString( DbgBuffer );    
#endif
   
Exit_RestoreParametersFromFile:    
   return dwError;
}   

EXTERN_C LONG __declspec(dllexport) __stdcall
DoPreUpgradeProcessing(IN   HWND    hParentWindow,
                       IN   HKEY    hkeyParams,
                       IN   LPCTSTR szPreNT5InfId,
                       IN   LPCTSTR szPreNT5Instance,
                       IN   LPCTSTR szNT5InfId,
                       IN   LPCTSTR szSectionName,
                       OUT  VENDORINFO* pviVendorInfo,
                       OUT  DWORD*  pdwFlags,
                       IN   LPVOID  pvReserved)
{
   DWORD dwError=ERROR_SUCCESS;

#if _DEBUG
   wsprintf( DbgBuffer, TEXT("DGWANLUP: Enter DoPreUpgradeProcessing\n") );
   OutputDebugString( DbgBuffer );
   wsprintf( DbgBuffer, TEXT("DGWANLUP: szSectionName: %ls szPreNT5InfId: %ls szNT5InfId: %ls\n"),
                        szSectionName,szPreNT5InfId,szNT5InfId);
   OutputDebugString( DbgBuffer );
#endif

	if (g_pfnAddSection == NULL || g_pfnAddLineToSection == NULL )
	{   
		dwError = ERROR_DLL_INIT_FAILED;
		goto Exit_DoPreUpgradeProcessing;
	}      

	{

		// Write the Parameters Keys to the SIF File.  
		if (SaveParametersToFile( hkeyParams, szNT5InfId, szSectionName, szPreNT5InfId ) == ERROR_SUCCESS)
		{
			// Request Post Upgrade Processing
			*pdwFlags |= NUA_LOAD_POST_UPGRADE;
#if _DEBUG
			wsprintf( DbgBuffer, TEXT("DGWANLUP: Do Post Upgrade: %d\n"),*pdwFlags);
			OutputDebugString( DbgBuffer );
#endif
		}

	}
   
      
Exit_DoPreUpgradeProcessing:    
   return dwError;
}


EXTERN_C LONG __declspec(dllexport) __stdcall
PostUpgradeInitialize(IN  LPCTSTR         szWorkingDir,
                     IN  NetUpgradeInfo* pNetUpgradeInfo,
                     OUT VENDORINFO*     pviVendorInfo,
                     OUT LPVOID          pvReserved)
{
   DWORD dwError=ERROR_SUCCESS;

   DebugBreak();

#if _DEBUG
	wsprintf( DbgBuffer, TEXT("DGWANLUP: Enter PostUpgradeInitialize\n") );
	OutputDebugString( DbgBuffer );
	wsprintf( DbgBuffer, TEXT("DGWANLUP: szWorkingDir = %ls\n"),szWorkingDir);
	OutputDebugString( DbgBuffer );
#endif

   if ( szWorkingDir == NULL )
   {   
      dwError = ERROR_INVALID_PARAMETER;
      goto Exit_PostUpgradeInitialize;
   } 
   
   wcscpy(g_szWorkingDir,szWorkingDir);
   if ( g_szWorkingDir[wcslen(g_szWorkingDir)-1] == _T('\\') )
   {
		g_szWorkingDir[wcslen(g_szWorkingDir)-1] = _T('\0'); 
   }
   
Exit_PostUpgradeInitialize:
   
#if _DEBUG
	wsprintf( DbgBuffer, TEXT( "DGWANLUP: Exiting PostUpgradeInitialize with status %d\n" ),dwError  );
	OutputDebugString( DbgBuffer );
#endif

   return dwError;
}



EXTERN_C LONG __declspec(dllexport) __stdcall
DoPostUpgradeProcessing(IN   HWND    hParentWindow,
						IN   HKEY    hkeyParams,
						IN   LPCTSTR szPreNT5Instance,
						IN   LPCTSTR szNT5InfId,
						IN   HINF	 hinfAnswerFile,
						IN	 LPCTSTR szSectionName,
						OUT  VENDORINFO* pviVendorInfo,
						IN   LPVOID  pvReserved)
{
   DWORD dwError=ERROR_SUCCESS;

#if _DEBUG
   wsprintf( DbgBuffer, TEXT("DGWANLUP: Enter DoPostUpgradeProcessing\n") );
   OutputDebugString( DbgBuffer );
   wsprintf( DbgBuffer, TEXT("DGWANLUP: szSectionName: %ls szPreNT5Instance: %ls szNT5InfId: %s\n"),
                        szSectionName,szPreNT5Instance,szNT5InfId);
   OutputDebugString( DbgBuffer );
#endif

	if (g_pfnAddSection == NULL || g_pfnAddLineToSection == NULL )
	{   
		dwError = ERROR_DLL_INIT_FAILED;
		goto Exit_DoPostUpgradeProcessing;
	}      

	{

		// Retrieve the Driver Parameters Key and Write it to the new Driver Parameters Key
		RestoreParametersFromFile( hkeyParams, szSectionName);

	}   
   
      
Exit_DoPostUpgradeProcessing:    
   return dwError;
}