//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
// 
// AssemblyPropertiesPage.cpp : plik implementacji
//

#include "stdafx.h"
#include "AssemblyDoc.h"
#include "AssemblyView.h"
#include "AssemblyPropertiesPage.h"


// Okno dialogowe CAssemblyPropertiesPage

IMPLEMENT_DYNAMIC(CAssemblyPropertiesPage, CPropertyPage)
CAssemblyPropertiesPage::CAssemblyPropertiesPage()
	: CPropertyPage(CAssemblyPropertiesPage::IDD)
{
}

CAssemblyPropertiesPage::~CAssemblyPropertiesPage()
{
}

void CAssemblyPropertiesPage::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAssemblyPropertiesPage, CPropertyPage)
END_MESSAGE_MAP()


// Procedury obsługi wiadomości CAssemblyPropertiesPage
BOOL CAssemblyPropertiesPage::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	// Wypełnienie danymi
	CPropertySheet *pPropertySheet = STATIC_DOWNCAST(CPropertySheet, GetParent());
	CAssemblyView* pView = STATIC_DOWNCAST(CAssemblyView, pPropertySheet->GetParent());
	CAssemblyDoc* pDoc = pView->GetDocument();
	IMetaDataImport* pImport  = pDoc->MetaDataImportInterface();

	IMetaDataAssemblyImport *pAssemblyImport;
    HRESULT hr = pImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &pAssemblyImport);
    if (FAILED(hr))
	{
        TRACE("Działanie QueryInterace dla IID_IMetaDataAssemblyImport nie powiodło się. 0x%0X8\n", hr);
		return FALSE;
	}

    //STDMETHOD(GetAssemblyProps)(            // S_OK lub błąd.
    //    mdAssembly  mda,                    // [IN] Podzespół, którego właściwości są pobierane.
    //    const void  **ppbPublicKey,         // [OUT] Wskaźnik do klucza publicznego.
    //    ULONG       *pcbPublicKey,          // [OUT] Liczba bajtów w kluczu publicznym.
    //    ULONG       *pulHashAlgId,          // [OUT] Algorytm skrótu.
    //    LPWSTR      szName,                 // [OUT] Bufor do wypełnienia nazwą.
    //    ULONG       cchName,                // [IN] Wielkość bufora w znakach.
    //    ULONG       *pchName,               // [OUT] Rzeczywista liczba znaków w nazwie.
    //    ASSEMBLYMETADATA *pMetaData,        // [OUT] Metadane podzespołu.
    //    DWORD       *pdwAssemblyFlags) PURE;    // [OUT] Znaczniki.

    mdAssembly      mda;
    const BYTE      *pbPublicKey;
    ULONG           cbPublicKey;
    ULONG           ulHashAlgId;
    WCHAR           szName[STRING_BUFFER_LEN];
    ASSEMBLYMETADATA MetaData;
    DWORD           dwFlags;
	WCHAR			cBuffer[1024];
	WCHAR			tBuffer[16];

    hr = pAssemblyImport->GetAssemblyFromScope(&mda);
    if (hr == CLDB_E_RECORD_NOTFOUND)
        return FALSE;
    else
	if (FAILED(hr))
	{
		TRACE(_T("Działanie GetAssemblyFromScope() nie powiodło się. 0x%0X8\n"), hr);
		return FALSE;
	}

    // Uzyskanie wymaganych wielkości dla tablic wartości, procesorów itp.
    ZeroMemory(&MetaData, sizeof(ASSEMBLYMETADATA));
    hr = pAssemblyImport->GetAssemblyProps(mda, 
                                           NULL, NULL,    // Public Key.
                                           NULL,          // Hash Algorithm.
                                           NULL, 0, NULL, // Name.
                                           &MetaData,
                                           NULL);         // Flags.
    if (FAILED(hr))
	{
		TRACE(_T("Działanie GetAssemblyProps() nie powiodło się. 0x%0X8"), hr);
		return FALSE;
	}
    // Alokacja przestrzeni dla tablic w strukturze ASSEMBLYMETADATA.
    if (MetaData.cbLocale)
        MetaData.szLocale = (WCHAR *)_alloca(sizeof(WCHAR) * MetaData.cbLocale);
    if (MetaData.ulProcessor)
        MetaData.rProcessor = (DWORD *)_alloca(sizeof(DWORD) * MetaData.ulProcessor);
    if (MetaData.ulOS)
        MetaData.rOS = (OSINFO *)_alloca(sizeof(OSINFO) * MetaData.ulOS);
    hr = pAssemblyImport->GetAssemblyProps(mda, 
                                          (const void **)&pbPublicKey, &cbPublicKey,
                                          &ulHashAlgId,
                                          szName, STRING_BUFFER_LEN, NULL,
                                          &MetaData,
                                          &dwFlags);
    if (FAILED(hr))
	{
		TRACE(_T("Działanie GetAssemblyProps() nie powiodło się. 0x%0X8"), hr);
		return FALSE;
	}

	CEdit *pText = (CEdit *)GetDlgItem(IDC_ASSEMBLYTOKEN);
	wsprintf(cBuffer, _T("0x%0X8"), mda);
	pText->SetWindowText(cBuffer);

	pText = (CEdit *)GetDlgItem(IDC_ASSEMBLYNAME);
	pText->SetWindowText(szName);

	pText = (CEdit *)GetDlgItem(IDC_ASSEMBLYPUBLICKEY);
	memset(cBuffer, 0, sizeof(cBuffer));
	int lines = cbPublicKey/16;
	for(int i = 0; i < lines; i++)
	{
		int bytesToPrint = ((i+1)*16 > cbPublicKey) ? (cbPublicKey - (i*16) + 1) : 16;
		for(int j = 0; j < bytesToPrint; j++)
		{
			wsprintf(tBuffer, L"0x%02X ", pbPublicKey[i*16 + j]);
			wcscat(cBuffer, tBuffer);
		}
		wcscat(cBuffer, L"\r\n");
	}
	pText->SetWindowText(cBuffer);

	pText = (CEdit *)GetDlgItem(IDC_ASSEMBLYHASHALGO);
	wsprintf(cBuffer, _T("0x%0X8"), ulHashAlgId);
	pText->SetWindowText(cBuffer);

	pAssemblyImport->Release();
	pAssemblyImport = NULL;
	pImport->Release();

	return TRUE;  // zwrócenie TRUE, chyba że ognisko ustawiono na element sterujący
}
