// TypeLibraryBrowserDlg.cpp : implementation file
//

#include "stdafx.h"
#include "TypeLibraryBrowser.h"
#include "TypeLibraryBrowserDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTypeLibraryBrowserDlg dialog

CTypeLibraryBrowserDlg::CTypeLibraryBrowserDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTypeLibraryBrowserDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTypeLibraryBrowserDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTypeLibraryBrowserDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTypeLibraryBrowserDlg)
	DDX_Control(pDX, IDC_LIST1, m_List);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTypeLibraryBrowserDlg, CDialog)
	//{{AFX_MSG_MAP(CTypeLibraryBrowserDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, OnOpenSelected)
	ON_BN_CLICKED(IDC_BUTTON2, OnByFileName)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTypeLibraryBrowserDlg message handlers

BOOL CTypeLibraryBrowserDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
/*
Initialize List Control
*/

	m_List.InsertColumn (0, "Name") ;
	m_List.InsertColumn (1, "Ver") ;
	m_List.InsertColumn (2, "Lang") ;
	m_List.InsertColumn (3, "GUID") ;
	m_List.InsertColumn (4, "Path") ;

	m_List.SetColumnWidth (0, 200) ;
	m_List.SetColumnWidth (1, 50) ;
	m_List.SetColumnWidth (2, 50) ;
	m_List.SetColumnWidth (3, 200) ;
	m_List.SetColumnWidth (4, 200) ;


/*
Open a key to the type library section of the registry
*/

	HKEY hTypeLibKey ;
	RegOpenKey (HKEY_CLASSES_ROOT, "TypeLib", &hTypeLibKey) ;
			             
/*
For each key, find the human-readable name of the type lib, and
the path to the type library. Put the name in the list box, and the 
path as the lParam of the entry. 
*/
			             
	DWORD dwIndex = 0 ;
	char strTypeLibGuid [64] ;

	while (RegEnumKey(hTypeLibKey, dwIndex, strTypeLibGuid, sizeof(strTypeLibGuid)) == ERROR_SUCCESS)
	{
		HKEY hVerKey ;
		RegOpenKey (hTypeLibKey, strTypeLibGuid, &hVerKey) ;  // open type lib ID key

/*
Iterate through the version numbers under the type lib key. Each
should have a name associated with it. Put the name in the list box.
*/
		
		DWORD VerIndex = 0 ;
		char VerString [64] ;

		while (RegEnumKey (hVerKey, VerIndex, VerString, sizeof(VerString)) == ERROR_SUCCESS)
		{
			char AppName [256] ;
			long AppNameLength = sizeof (AppName) ;  
			RegQueryValue (hVerKey, VerString, AppName,  &AppNameLength) ;				

/*
For each version, enumerate the locales
*/
			HKEY hLocKey ;
			RegOpenKey (hVerKey, VerString, &hLocKey) ;  // open type lib ID key

			DWORD LocIndex = 0;
			char LocString [64] ;

			while (RegEnumKey (hLocKey, LocIndex, LocString, sizeof(LocString)) == ERROR_SUCCESS)
			{

				if (_stricmp (LocString, "FLAGS") != 0 && _stricmp (LocString, "HELPDIR") != 0)
				{
/*
Get the path string from the Win32 key under the locale.
*/
					HKEY hPathKey ;
					RegOpenKey (hLocKey, LocString, &hPathKey) ;

					char PathName [256] ;
					long PathNameLength = sizeof (PathName) ;  
					RegQueryValue (hPathKey, "Win32", PathName,  &PathNameLength) ;				
					RegCloseKey (hPathKey) ;

/*
Fill list control with data.
*/
					int nItem = m_List.InsertItem (dwIndex, AppName) ;
					m_List.SetItem (nItem, 1, LVIF_TEXT, VerString, 0,0,0,0) ;
					m_List.SetItem (nItem, 2, LVIF_TEXT, LocString, 0,0,0,0) ;
					m_List.SetItem (nItem, 3, LVIF_TEXT, strTypeLibGuid, 0, 0, 0, 0) ;
					m_List.SetItem (nItem, 4, LVIF_TEXT, PathName, 0, 0, 0, 0) ;

				}

				LocIndex ++ ;
			}
			


			RegCloseKey (hLocKey) ;
			VerIndex ++ ;
		}


	    RegCloseKey (hVerKey) ;
		dwIndex ++ ; 	// 0-based
	}
			
	RegCloseKey (hTypeLibKey) ;
	

	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CTypeLibraryBrowserDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CTypeLibraryBrowserDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

/*
User clicked "Open Selected". Open and display type library
selected by user from list control, based on registry information.
*/

void CTypeLibraryBrowserDlg::OnOpenSelected() 
{
	USES_CONVERSION ;
	POSITION pos = m_List.GetFirstSelectedItemPosition ( ) ;

	if (pos != NULL) 
	{
		int nItem = m_List.GetNextSelectedItem(pos);
/*
Convert type library ID from registry string.
*/
		UUID TypeLibID ;
		CLSIDFromString (A2W(m_List.GetItemText (nItem, 3)), &TypeLibID) ;

/*
Convert version and locale from registry string.
*/
		CString strVersion = m_List.GetItemText (nItem, 1) ;
		CString strLocale = m_List.GetItemText (nItem, 2) ;

		double dVersion = atof (strVersion) ;

		unsigned short wVerMajor = (short) dVersion ;
		unsigned short wVerMinor = ((short) (dVersion * 10.0)) - (wVerMajor * 10) ;

/*
Open type library based on registry information.
*/
		
		LoadRegTypeLib (
			TypeLibID,				// Type library UUID
			wVerMajor,				// major version
			wVerMinor,				// minor version
			atoi (strLocale) ,		// locale ID
			&m_pTypeLib ) ;


/*
Show type library dialog box to user.
*/
		CDisplayTypeLibDlg dlg (NULL) ;
		dlg.m_pTypeLib = m_pTypeLib ;
		dlg.DoModal ( ) ;

	}
}

/*
User clicked "By File Name". 
*/


void CTypeLibraryBrowserDlg::OnByFileName() 
{
	USES_CONVERSION ;

/*
Display dialog box allowing user to choose type library files.
*/

	CFileDialog dlg  (TRUE)  ;
	dlg.m_ofn.lpstrFilter = "Possible Type Libraries (*.tlb, *.dll, *.exe)\0*.tlb;*.dll;*.exe\0" ;

	if (dlg.DoModal ( ) == IDOK)
	{
/*
Open type library file selected by user.
*/
		HRESULT hr = LoadTypeLib (A2W(dlg.GetPathName ( )), &m_pTypeLib) ;
		
		if (hr != S_OK)
		{
		  CString out ;
		  out.Format ("Couldn't load specified type library, hr = 0x%x", hr) ;
		  AfxMessageBox (out) ;
		}

/*
Display dialog box to user.
*/

		CDisplayTypeLibDlg dlg (NULL) ;
		dlg.m_pTypeLib = m_pTypeLib ;
		dlg.DoModal ( ) ;
	}
}
