// TestDnsImports.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "TestDnsImports.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// The one and only application object

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;
	HMODULE                 hModule = ::GetModuleHandle(NULL);
    SC_HANDLE               schSCManager;
    SC_HANDLE               schService;
    BOOL                    bRet;
    SERVICE_STATUS          stServiceStatus;
    SERVICE_STATUS_PROCESS  stServiceProcessStatus;
    DWORD                   cbBytesNeeded;
    HANDLE                  hDnsProcess;
    CTestDnsImports         *pTestDnsImports;
    argc; argv; envp;
    if (hModule != NULL)
	{
		// initialize MFC and print and error on failure
		if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			// TODO: change error code to suit your needs
			_tprintf(_T("Fatal Error: MFC initialization failed\n"));
			nRetCode = 1;
		}
		else
		{
            schSCManager = OpenSCManager(
                NULL,                 // local machine
                NULL,                 // ServicesActive database
                SC_MANAGER_ALL_ACCESS // full access rights
                );
            assert(NULL != schSCManager);
            schService = OpenService(
                schSCManager,
                _T("DNS"),
                SERVICE_ALL_ACCESS
                );
            assert(NULL != schService);
            bRet = CloseServiceHandle(schSCManager);
            RtlZeroMemory(
                &stServiceProcessStatus,
                sizeof(stServiceProcessStatus)
                );
            RtlZeroMemory(
                &stServiceStatus,
                sizeof(stServiceStatus)
                );
            bRet = QueryServiceStatusEx(
                schService,
                SC_STATUS_PROCESS_INFO,
                (LPBYTE) &stServiceProcessStatus,
                sizeof(stServiceProcessStatus),
                &cbBytesNeeded
                );
            assert(SERVICE_RUNNING == stServiceProcessStatus.dwCurrentState);
            bRet = CloseServiceHandle(schService);
            hDnsProcess = OpenProcess(
                PROCESS_ALL_ACCESS,
                FALSE,
                stServiceProcessStatus.dwProcessId
                );
            assert(NULL != hDnsProcess);
            pTestDnsImports = new CTestDnsImports(hDnsProcess);
            pTestDnsImports->PrintMainImports();
            delete pTestDnsImports;
            bRet = CloseHandle(hDnsProcess);
        }
	}
	else
	{
		// TODO: change error code to suit your needs
		_tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
		nRetCode = 1;
	}
	return nRetCode;
}


CTestDnsImports::CTestDnsImports(
    HANDLE hProcessHandle
    )
: CModule32HLP(hProcessHandle)
{
}


CTestDnsImports::~CTestDnsImports()
{
}


void CTestDnsImports::PrintMainImports()
{
    PLDR_DATA_TABLE_ENTRY   pResult;
    REAL_IMPORT_DESCRIPTOR  stImportDescriptor;
    PWSTR       pwsCurrentModuleName;
    PCSTR       psCurrentModuleName = NULL;
    bool        bResult;
    pResult = GetFirstModuleInfoEntry();
    assert(NULL != pResult);
    pwsCurrentModuleName = GetModuleNameW();
    bResult = EnumImportStart(pwsCurrentModuleName);
    assert(bResult);
    RtlZeroMemory(
        &stImportDescriptor,
        sizeof(stImportDescriptor)
        );
    while (EnumImportNext(stImportDescriptor))
    {
        if (psCurrentModuleName != stImportDescriptor.szCalledModuleName)
        {
            psCurrentModuleName = stImportDescriptor.szCalledModuleName;
            _tprintf(
                _T("%S\n"),
                psCurrentModuleName
                );
        }
        _tprintf(
            _T("\t%S %p\n"),
            stImportDescriptor.szFunctionName,
            m_pImportThunkArray[stImportDescriptor.dwThunkIndex]
            );
    }
    EnumImportStop();
}
