Example #1
0
HRESULT
CALLBACK
lbl(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes=S_OK;
    INIT_API();

    #if VERBOSE >= 2
    dprintf("[sync] !lbl called\n");
    #endif

    if (!Args || !*Args) {
        dprintf("[sync] !lbl <comment to add>\n");
        return E_FAIL;
    }

    hRes=TunnelSend("[sync]{\"type\":\"lbl\",\"msg\":\"%s\",\"base\":%llu,\"offset\":%llu}\n", Args, g_Base, g_Offset);

    return hRes;
}
Example #2
0
HRESULT
CALLBACK
modunmap(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes;
    ULONG64 ModBase=0;
    ULONG RemainderIndex;
    DEBUG_VALUE DebugValue = {};
    INIT_API();

    if (!Args || !*Args)
    {
        dprintf("[sync] !modunmap <mod base>\n");
        return E_FAIL;
    }

    /*
    msdn: Evaluate method evaluates an expression, returning the result.
    */
    hRes=g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT64, &DebugValue, &RemainderIndex);
    if(FAILED(hRes))
    {
        dprintf("[sync] modunmap: failed to evaluate module base\n");
        return E_FAIL;
    }

    ModBase = (ULONG64)DebugValue.I64;

    /*
    msdn: The RemoveSyntheticModule method removes a synthetic module from the module list
          the debugger maintains for the current process.
    */
    hRes=g_ExtSymbols3->RemoveSyntheticModule(ModBase);
    if(FAILED(hRes))
    {
        dprintf("[sync] modunmap: RemoveSyntheticModule failed\n");
        return E_FAIL;
    }

    return hRes;
}
Example #3
0
HRESULT
CALLBACK
syncoff(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes=S_OK;
    UNREFERENCED_PARAMETER(Args);
    INIT_API();

    #if VERBOSE >= 2
    dprintf("[sync] !syncoff  command called\n");
    #endif

    if(!g_Synchronized)
        return hRes;

    ReleasePollTimer();
    hRes=TunnelClose();
    dprintf("[sync] sync is now disabled\n");

    return hRes;
}
Example #4
0
HRESULT
CALLBACK
DebugExtensionInitialize(PULONG Version, PULONG Flags)
{
    IDebugClient4 *DebugClient;
    PDEBUG_CONTROL DebugControl;
    HRESULT Hr;

    *Version = DEBUG_EXTENSION_VERSION(1, 0);
    *Flags = 0;
    Hr = S_OK;

    if ((Hr = DebugCreate(__uuidof(IDebugClient),
                          (void **)&DebugClient)) != S_OK)
    {
        return Hr;
    }

    if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
                                          (void **)&DebugControl)) == S_OK)
    {

        //
        // Get the windbg-style extension APIS
        //
        ExtensionApis.nSize = sizeof (ExtensionApis);
        Hr = DebugControl->GetWindbgExtensionApis64(&ExtensionApis);

        IDebugClient4 *Client = DebugClient;

        INIT_API();
        DebugControl->Release();

    }
    //DebugClient->Release();



    return Hr;
}
Example #5
0
HRESULT
CALLBACK
jmpto(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes;
    ULONG64 Base, Offset =0;
    ULONG NameSize=0;
    ULONG RemainderIndex;
    DEBUG_VALUE DebugValue = {};
    INIT_API();

    if (!Args || !*Args)
    {
        dprintf("[sync] !jumpto <expression>\n");
        return E_FAIL;
    }

    /*
    msdn: Evaluate method evaluates an expression, returning the result.
    */
    hRes=g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT64, &DebugValue, &RemainderIndex);
    if(FAILED(hRes))
    {
        dprintf("[sync] jumpto: failed to evaluate expression\n");
        return E_FAIL;
    }

    Offset = (ULONG64)DebugValue.I64;

    /*
    msdn: GetModuleByOffset method searches through the target's modules for one
    whose memory allocation includes the specified location.
    */
    hRes=g_ExtSymbols->GetModuleByOffset(Offset, 0, NULL, &Base);
    if(FAILED(hRes))
    {
        dprintf("[sync] jumpto: failed to get module base for address 0x%x\n", Base);
        return E_FAIL;
    }

    /*
    Update module name stored in g_NameBuffer
    msdn: GetModuleNameString  method returns the name of the specified module.
    */
    hRes=g_ExtSymbols2->GetModuleNameString(DEBUG_MODNAME_LOADED_IMAGE, DEBUG_ANY_ID, Base, g_NameBuffer, MAX_NAME, &NameSize);
    if(!(SUCCEEDED(hRes) & (NameSize>0) & (((char) *g_NameBuffer)!=0)))
    {
        dprintf("[sync] jumpto: failed to get module name for target address\n");
        return E_FAIL;
    }

    // Check if we are in a new module
    if(g_Base != Base)
    {
        // Update base address of current active module
        g_Base = Base;

        hRes=TunnelSend("[notice]{\"type\":\"module\",\"path\":\"%s\"}\n", g_NameBuffer);
        if(FAILED(hRes))
            return hRes;
    }

    hRes=TunnelSend("[sync]{\"type\":\"loc\",\"base\":%llu,\"offset\":%llu}\n", Base, Offset);

    return hRes;
}
Example #6
0
HRESULT
CALLBACK
sync(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes=S_OK;
    PCSTR Host;
    PSTR pszId=NULL;

    INIT_API();

    // Reset global state
    g_Base = NULL;
    g_Offset = NULL;

    #if VERBOSE >= 2
    dprintf("[sync] sync function called\n");
    #endif

    if(g_Synchronized)
    {
        dprintf("[sync] sync update\n");
        UpdateState();
        goto exit;
    }

    if (!Args || !*Args) {
        dprintf("[sync] No argument found, using default host (%s:%s)\n", g_DefaultHost, g_DefaultPort);
        Host=g_DefaultHost;
    }else{
        Host=Args;
    }

    if(FAILED(hRes=TunnelCreate(Host, g_DefaultPort)))
    {
        dprintf("[sync] sync failed\n");
        goto exit;
    }

    dprintf("[sync] probing sync\n");

    if(FAILED(hRes=Identity(&pszId)))
    {
        dprintf("[sync] get identity failed\n");
        goto exit;
    }

    hRes=TunnelSend("[notice]{\"type\":\"new_dbg\",\"msg\":\"dbg connect - %s\"}\n", pszId);
    if(SUCCEEDED(hRes))
    {
        dprintf("[sync] sync is now enabled with host %s\n", Host);
        UpdateState();
        CreatePollTimer();
    }
    else
    {
        dprintf("[sync] sync aborted\n");
    }

exit:
    if(!(pszId==NULL))
        free(pszId);

    return hRes;
}
Example #7
0
HRESULT
CALLBACK
modcheck(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes;
    DWORD cbBinary;
    int NbBytesRecvd = 0;
    LPSTR pszResString= NULL;
    CHAR *msg = NULL;
    CHAR *type;
    CHAR cmd[64] = {0};
    BOOL bUsePdb = TRUE;

    INIT_API();

    if(!g_Synchronized)
    {
        dprintf("[sync] please enable sync\n");
        return E_FAIL;
    }

    if (!(*g_NameBuffer))
    {
        dprintf("[sync] no module\n");
        return E_FAIL;
    }

    // check args
    // md5 is accepted only with local debuggee
    if (!Args || !*Args) {
        bUsePdb=TRUE;
    }
    else if(strcmp("md5", Args)==0)
    {
        bUsePdb=FALSE;

        if (!(IsLocalDebuggee()))
        {
            dprintf("[sync] can't use md5 check with non local debuggee\n");
            return E_FAIL;
        }
    }
    else
        dprintf("[sync] unknown argument, defaulting to pdb match\n");

    // The debugger does not know if an IDB client
    // is actually connected to the dispatcher.

    // First disable tunnel polling for commands (happy race...)
    ReleasePollTimer();

    // default behavior is to used !IToldYouSo  command.
    if (bUsePdb)
    {
        type = "pdb";
        _snprintf_s(cmd, 64, _TRUNCATE , "!itoldyouso  %x", g_Base);

        // g_CommandBuffer first four bytes should contains
        // return value for command exec
        hRes=LocalCmd(Client, cmd);
        if (FAILED(hRes) || FAILED(*g_CommandBuffer))
        {
            dprintf("[sync] failed to evaluate !ItoldYouSo  command\n");
            goto Exit;
        }

        cbBinary = (DWORD) strlen(g_CommandBuffer+4);
        if (cbBinary == 0)
        {
            dprintf("     ItoldYouSo return empty result\n");
            goto Exit;
        }

        dprintf("%s\n", g_CommandBuffer+4);

        hRes=ToBase64((const byte *)g_CommandBuffer+4, cbBinary, &pszResString);
        if (FAILED(hRes))
        {
            dprintf("[sync] modcheck ToBase64 failed\n");
            goto Exit;
        }
    }
    else
    {
        type="md5";
        hRes=modmd5(&pszResString);
        if (FAILED(hRes))
        {
            dprintf("[sync] modcheck modmd5 failed\n");
            goto Exit;
        }

        dprintf("       MD5: %s\n", pszResString);
    }

    hRes = TunnelSend("[sync]{\"type\":\"modcheck\",\"%s\":\"%s\"}\n", type, pszResString);
    if (FAILED(hRes))
    {
        dprintf("[sync] modcheck send failed\n");
        goto Exit;
    }

    // Let time for the IDB client to reply if it exists
    Sleep(150);

    // Poll tunnel
    hRes=TunnelPoll(&NbBytesRecvd, &msg);
    if (FAILED(hRes))
    {
        dprintf("[sync] modcheck poll failed\n");
        goto Exit;
    }
    else
    {
        if ((NbBytesRecvd>0) & (msg != NULL))
            dprintf("%s\n", msg);
        else
            dprintf("    -> no reply, make sure an idb is enabled first\n");
    }

Exit:
    // Re-enable tunnel polling
    CreatePollTimer();

    if (pszResString)
        free(pszResString);
    if (msg)
        free(msg);

    return hRes;
}
Example #8
0
HRESULT
CALLBACK
bpcmds(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes=S_OK;
    char *msg, *decoded, *query;
    LPSTR pszString;
    int NbBytesRecvd;
    size_t cbBinary;
    INIT_API();

    #if VERBOSE >= 2
    dprintf("[sync] !bpcmds  called\n");
    #endif

    if(!g_Synchronized)
    {
        dprintf("[sync] please enable sync\n");
        return E_FAIL;
    }

    if (!Args || !*Args){
        msg = "query";
    } else {
        msg = (char *)Args;
    }

    if ((strncmp("load", msg, 4)==0) || (strncmp("query", msg, 5)==0))
    {
        dprintf("[sync] query idb for bpcmds\n");
        hRes=TunnelSend("[sync]{\"type\":\"bps_get\"}\n");
    }
    else if(strncmp("save", msg, 4)==0)
    {
        dprintf("[sync] dumping bpcmds to idb\n");

        hRes=LocalCmd(Client, ".bpcmds");

        // g_CommandBuffer first four bytes should contains
        // return value for command exec
        if (FAILED(hRes) || FAILED(*g_CommandBuffer))
        {
            dprintf("[sync] failed to evaluate .bpcmds command\n");
            return E_FAIL;
        }

        cbBinary = strlen(g_CommandBuffer+4);
        dprintf("%s\n", g_CommandBuffer);

        hRes = ToBase64((const byte *)g_CommandBuffer+4, (unsigned int)cbBinary, &pszString);
        if (SUCCEEDED(hRes)) {
            hRes = TunnelSend("[sync]{\"type\":\"bps_set\",\"msg\":\"%s\"}\n", pszString);
            free(pszString);
        }
    }
    else
    {
        dprintf("[sync] usage !bpcmds <||query|save|load|\n");
        return E_FAIL;
    }

    // Check if we failed to query the idb client
    if (FAILED(hRes)){
        dprintf("[sync] !bpcmds failed\n");
        return hRes;
    }

    // Get result from idb client
    hRes=TunnelReceive(&NbBytesRecvd, &query);
    if (!(SUCCEEDED(hRes) & (NbBytesRecvd>0) & (query != NULL)))
    {
        dprintf("[sync] !bpcmds failed\n");
        return hRes;
    }

    // Handle result
    if(strncmp("load", msg, 4)==0)
    {
        hRes = FromBase64(query, (BYTE **)(&decoded));
        if (SUCCEEDED(hRes)) {
            hRes = ExecCmdList(decoded);
            free(decoded);
        }
    }
    else if(strncmp("query", msg, 4)==0)
    {
        hRes = FromBase64(query, (BYTE **)(&decoded));
        if (SUCCEEDED(hRes)) {
            dprintf("[sync] idb's saved bpcmds:\n %s\n", decoded);
            free(decoded);
        }
    }
    else
    {
        dprintf("%s\n", query);
    }

    free(query);
    return hRes;
}
Example #9
0
HRESULT
CALLBACK
modmap(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes;
    ULONG64 ModBase=0;
    ULONG ModSize;
    ULONG RemainderIndex;

    DEBUG_VALUE DebugValue = {};
    INIT_API();

    if (!Args || !*Args)
    {
        dprintf("[sync] !modmap <mod base> <mod size> <mod name>\n");
        return E_FAIL;
    }

    /*
    msdn: Evaluate method evaluates an expression, returning the result.
    */
    hRes=g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT64, &DebugValue, &RemainderIndex);
    if(FAILED(hRes))
    {
        dprintf("[sync] modmap: failed to evaluate module base\n");
        return E_FAIL;
    }

    ModBase = (ULONG64)DebugValue.I64;
    Args += RemainderIndex;

    hRes=g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT32, &DebugValue, &RemainderIndex);
    if(FAILED(hRes))
    {
        dprintf("[sync] modmap: failed to evaluate module size\n");
        return E_FAIL;
    }

    ModSize = (ULONG64)DebugValue.I32;
    Args += RemainderIndex;

    StrTrim((LPSTR)Args, " ");

    if (!*Args)
    {
        dprintf("[sync] modmap: failed to evaluate module name\n");
        return E_FAIL;
    }

    /*
    msdn: The AddSyntheticModule method adds a synthetic module to the module list the debugger
          maintains for the current process.
    */
    hRes=g_ExtSymbols3->AddSyntheticModule(ModBase, ModSize, Args, Args, DEBUG_ADDSYNTHMOD_DEFAULT);
    if(FAILED(hRes))
    {
        dprintf("[sync] modmap: AddSyntheticModule failed\n");
        return E_FAIL;
    }

    /*
    msdn: The AddSyntheticSymbol method adds a synthetic symbol to a module in the current process.
    */
    hRes=g_ExtSymbols3->AddSyntheticSymbol(ModBase, ModSize, Args, DEBUG_ADDSYNTHSYM_DEFAULT, NULL);
    if(FAILED(hRes))
    {
        dprintf("[sync] modmap: AddSyntheticSymbol failed\n");
        hRes=g_ExtSymbols3->RemoveSyntheticModule(ModBase);
        return E_FAIL;
    }

    return hRes;
}
Example #10
0
/*
  Sample extension to read and dump a struct on target

  This reads the struct _EXCEPTION_RECORD which is defined as:

  typedef struct _EXCEPTION_RECORD {
    NTSTATUS ExceptionCode;
    ULONG ExceptionFlags;
    struct _EXCEPTION_RECORD *ExceptionRecord;
    PVOID ExceptionAddress;
    ULONG NumberParameters;
    ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
    } EXCEPTION_RECORD;
*/
HRESULT CALLBACK
structsample(PDEBUG_CLIENT4 Client, PCSTR args)
{
    ULONG64 Address;
    INIT_API();

    Address = GetExpression(args);

    DWORD Buffer[4], cb;

    // Read and display first 4 dwords at Address
    if (ReadMemory(Address, &Buffer, sizeof(Buffer), &cb) && cb == sizeof(Buffer)) {
        dprintf("%p: %08lx %08lx %08lx %08lx\n\n", Address,
                Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
    }

    //
    // Method 1 to dump a struct
    //
    dprintf("Method 1:\n");
    // Inititalze type read from the Address
    if (InitTypeRead(Address, _EXCEPTION_RECORD) != 0) {
        dprintf("Error in reading _EXCEPTION_RECORD at %p", // Use %p to print pointer values
                Address);
    } else {
        // read and dump the fields
        dprintf("_EXCEPTION_RECORD @ %p\n", Address);
        dprintf("\tExceptionCode           : %lx\n", (ULONG) ReadField(ExceptionCode));
        dprintf("\tExceptionAddress        : %p\n", ReadField(ExceptionAddress));
        dprintf("\tExceptionInformation[1] : %I64lx\n", ReadField(ExceptionInformation[1]));
        // And so on...
    }

    //
    // Method 2 to read a struct
    //
    ULONG64 ExceptionInformation_1, ExceptionAddress, ExceptionCode;
    dprintf("\n\nMethod 2:\n");
    // Read and dump the fields by specifying type and address individually
    if (GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionCode", ExceptionCode)) {
        dprintf("Error in reading _EXCEPTION_RECORD at %p\n",
                Address);
    } else {
        // Pointers are read as ULONG64 values
        GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionAddress", ExceptionAddress);
        GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionInformation[1]", ExceptionInformation_1);
        // And so on..

        dprintf("_EXCEPTION_RECORD @ %p\n", Address);
        dprintf("\tExceptionCode           : %lx\n", ExceptionCode);
        dprintf("\tExceptionAddress        : %p\n", ExceptionAddress);
        dprintf("\tExceptionInformation[1] : %I64lx\n", ExceptionInformation_1);
    }

    ULONG64 Module;
    ULONG   i, TypeId;
    CHAR Name[MAX_PATH];
    //
    // To get/list field names
    //
    g_ExtSymbols->GetSymbolTypeId("_EXCEPTION_RECORD", &TypeId, &Module);
    dprintf("Fields of _EXCEPTION_RECORD\n");
    for (i=0; ;i++) {
        HRESULT Hr;
        ULONG Offset=0;

        Hr = g_ExtSymbols->GetFieldName(Module, TypeId, i, Name, MAX_PATH, NULL);
        if (Hr == S_OK) {
            g_ExtSymbols->GetFieldOffset(Module, TypeId, Name, &Offset);
            dprintf("%lx (+%03lx) %s\n", i, Offset, Name);
        } else if (Hr == E_INVALIDARG) {
            // All Fields done
            break;
        } else {
            dprintf("GetFieldName Failed %lx\n", Hr);
            break;
        }
    }

    //
    // Get name for an enumerate
    //
    //     typedef enum {
    //        Enum1,
    //        Enum2,
    //        Enum3,
    //     } TEST_ENUM;
    //
    ULONG   ValueOfEnum = 0;
    g_ExtSymbols->GetSymbolTypeId("TEST_ENUM", &TypeId, &Module);
    g_ExtSymbols->GetConstantName(Module, TypeId, ValueOfEnum, Name, MAX_PATH, NULL);
    dprintf("Testenum %I64lx == %s\n", ExceptionCode, Name);
    // This prints out, Testenum 0 == Enum1

    //
    // Read an array
    //
    //    typedef struct FOO_TYPE {
    //      ULONG Bar;
    //      ULONG Bar2;
    //    } FOO_TYPE;
    //
    //    FOO_TYPE sampleArray[20];
    ULONG Bar, Bar2;
    CHAR TypeName[100];
    for (i=0; i<20; i++) {
        sprintf_s(TypeName, sizeof(TypeName), "sampleArray[%lx]", i);
        if (GetFieldValue(0, TypeName, "Bar", Bar))
            break;
        GetFieldValue(0, TypeName, "Bar2", Bar2);
        dprintf("%16s -  Bar %2ld  Bar2 %ld\n", TypeName, Bar, Bar2);
    }

    EXIT_API();
    return S_OK;
}
Example #11
0
/*
   Extension to look at locals through IDebugSymbolGroup interface

        Usage: !symgrptest [args]

        To demontrate local/args lookup, this will go through the stack
        and set scope with the instruction of the stack frame and
        enumerate all the locals/arguments for the frame function
*/
HRESULT CALLBACK
symgrptest(PDEBUG_CLIENT4 Client, PCSTR args)
{
    HRESULT hRes;
    IDebugSymbolGroup *pDbgSymGroup;
    ULONG ulCount, nFrames;
    DEBUG_STACK_FRAME Stack[50];
    ULONG SymGroupType;

    INIT_API();

    if (!_stricmp(args, "args"))
    {
        // Disply only the arguments
        SymGroupType = DEBUG_SCOPE_GROUP_ARGUMENTS;
    } else
    {
        // Display all the locals
        SymGroupType = DEBUG_SCOPE_GROUP_LOCALS;
    }

    //
    // Get the current stack
    //
    if ((hRes = g_ExtControl->GetStackTrace(0, 0, 0, &Stack[0], 50, &nFrames)) != S_OK) {
        dprintf("Stacktrace failed - %lx\n", hRes);
        nFrames = 0;
    }

    // Create a local symbol group client
    if ((hRes = g_ExtSymbols->
         GetScopeSymbolGroup(SymGroupType,
                             NULL, &pDbgSymGroup)) == E_NOTIMPL)
    {
        EXIT_API();
        return S_OK;
    }

    while (nFrames) {
        //
        // Enumerate locals for this frame
        //
        --nFrames;

        // Set scope at this frame
        g_ExtSymbols->SetScope(0, &Stack[nFrames], NULL, 0);

        // refresh the symbol group with current scope
        if ((hRes = g_ExtSymbols->
             GetScopeSymbolGroup(DEBUG_SCOPE_GROUP_LOCALS,
                                 pDbgSymGroup, &pDbgSymGroup)) == E_NOTIMPL)
        {
            break;
        }
        hRes =
            pDbgSymGroup->GetNumberSymbols ( &ulCount);

        dprintf("\n\n>Scope Frame %lx: %lx Symbols\n",nFrames,ulCount);

        PDEBUG_SYMBOL_PARAMETERS pSymParams = new DEBUG_SYMBOL_PARAMETERS[ ulCount ] ;
        if (ulCount)
        {
            // Get all symbols for the frame
            hRes =
                pDbgSymGroup->GetSymbolParameters (0,
                                               ulCount    ,
                                               pSymParams);
        }
        if ( S_OK == hRes )
        {
            for ( ULONG i = 0 ; i < ulCount ; i++ )
            {
                TCHAR szName[ MAX_PATH ], *pName;
                ULONG ulSize;
                DEBUG_VALUE Value;

                // Lookup symbol name and print
                pName = &szName[1];
                hRes = pDbgSymGroup->GetSymbolName ( i,
                                                     pName,
                                                     MAX_PATH - 1,
                                                     &ulSize ) ;
                if (SUCCEEDED(hRes))
                {
                    // Prefix ! so this is evaluated as symbol
                    szName[0] = '!';
                    hRes = g_ExtControl->Evaluate(szName,
                                                  DEBUG_VALUE_INVALID,
                                                  &Value, NULL);
                    if (SUCCEEDED(hRes))
                    {
                        dprintf("%lx: %32s = 0x%p\n", i, pName, Value.I64);
                    }
                }
            }
        }
        delete []pSymParams;
    }
    pDbgSymGroup->Release();
    EXIT_API();
    return S_OK;
}
Example #12
0
HRESULT CALLBACK pe(PDEBUG_CLIENT4 Client, PCSTR args)
{
	INIT_API();
	ULONG_PTR        ulAddress = 0;
	ULONG_PTR        ulBase = 0;
	ULONG_PTR        ulImageSize = 0;
	HRESULT          result = S_OK;
	ULONG            ulSetionCount = 0;
	BOOL             bAllPrint = TRUE;
	BOOL             bPrintDosHeard = FALSE;
	BOOL             bPrintNtHeard = FALSE;
	BOOL             bSection = FALSE;
	BOOL             bImport = FALSE;
	BOOL             bExport = FALSE;

	IMAGE_DATA_DIRECTORY  DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = { 0 };
	if ( args == NULL)
	{
		result = S_FALSE;
		goto ex;
	}do
	{
		const char * split = " ";
		char * p = NULL, *params = NULL, *next = NULL;
		params = new char[strlen(args) + 1];
		if (params == NULL)
		{
			result = S_FALSE;
			goto ex;
		}
		_try
		{
			memset(params, 0, strlen(args) + 1);
			strcpy_s(params, strlen(args) + 1, args);
			p = strtok_s(params, split, &next);
			while (p != NULL)
			{
				if (_stricmp(p, "-section") == 0)
				{
					bAllPrint = FALSE;
					bSection = TRUE;
				}
				else if (_stricmp(p, "-dos") == 0)
				{
					bAllPrint = FALSE;
					bPrintDosHeard = TRUE;
				}
				else if (_stricmp(p, "-nt") == 0)
				{
					bAllPrint = FALSE;
					bPrintNtHeard = TRUE;
				}
				else if (_stricmp(p, "-import") == 0)
				{
					bAllPrint = FALSE;
					bImport = TRUE;
				}
				else if (_stricmp(p, "-export") == 0)
				{
					bAllPrint = FALSE;
					bExport = TRUE;
				}
				else if (p)
				{
					char *endptr = NULL;
					ulAddress = str2ull(p, &endptr, 16);
					ulBase = ulAddress;
				}
				p = strtok_s(NULL, split, &next);
			}
		}_finally
		{
			if (params)
			{
				delete[]params;
				params = NULL;
			}
		}
	} while (FALSE);

	if (ulAddress == 0)
	{
		result = S_FALSE;
		goto ex;
	}
	if (result = PE_PrintDosHeard(&ulAddress, bAllPrint | bPrintDosHeard) != S_OK)
	{
		goto ex;
	}
	if (result = PE_PrintNtHeard(&ulAddress, bAllPrint | bPrintNtHeard, &ulSetionCount, DataDirectory, &ulImageSize) != S_OK)
	{
		goto ex;
	}
	if (result = PE_PrintSection(&ulAddress, ulSetionCount, bAllPrint | bSection) != S_OK)
	{
		goto ex;
	}
	PBYTE    pImage = new BYTE[ulImageSize];
	if (pImage == NULL)
	{
		result = S_FALSE;
		goto ex;
	}
	_try
	{
		ULONG   ulReadSize = 0;
		memset(pImage, 0, ulImageSize);
		result = g_ExtDataSpaces->ReadVirtual(ulBase, pImage, ulImageSize, &ulReadSize);
		if (result != S_OK)
		{
			dprintf("读取虚拟地址 %x 错误 \n", ulBase);
			goto ex;
		}
		if (ulReadSize != ulImageSize)
		{
			dprintf("读取数据长度错误。 \n");
			result = S_FALSE;
			goto ex;
		}
		if (result = PE_PrintImport(pImage, DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT], bAllPrint | bImport) != S_OK)
		{
			goto ex;
		}
		if (result = PE_PrintExport(pImage, DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT], ulBase, bAllPrint | bExport) != S_OK)
		{
			goto ex;
		}
	}_finally
	{
		if (pImage)
		{
			delete[]pImage;
			pImage = NULL;
		}
	}

ex:

	EXIT_API();
	return result;
}