Разрешая ссылку - последующие


Похожие части кода, которую я недавно выложил, как:

Разрешая ссылку

У меня есть еще один кусок кода, который не может быть легко извлечен из В способ:

#define THROW_LAST_WINDOWS_ERROR()\
    WindowsApi::Exception::Throw(::GetLastError(), __FILE__,  __LINE__)

#define THROW_MANUAL_WINDOWS_ERROR(x)\
    WindowsApi::Exception::Throw(x, __FILE__,  __LINE__)

Process CreateNormalProcess(
    ProcessSnapshot *parent,
    const UNICODE_STRING& name, 
    const unsigned __int32 pid,
    const std::vector<ToolHelpThread>& threads
    )
{
    std::wstring nameStr(name.Buffer, name.Length/sizeof(wchar_t));
    std::wstring commandLine;
    std::wstring mainModulePath;
    std::wstring error;
    std::vector<Module> modules;
    try
    {
        using WindowsApi::Dll::NtDll;
        using WindowsApi::AutoArray;
        HANDLE hProc = OpenProcess(
            PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE,
            pid);
        if (hProc == 0)
        {
            THROW_LAST_WINDOWS_ERROR();
        }

        //Populate the process environment block
        NtDll ntDll;
        PEB peb;
        AutoArray procInfoBuf = ntDll.NtQueryInformationProcess(
            ProcessBasicInformation,
            hProc,
            sizeof(PROCESS_BASIC_INFORMATION)
            );
        BOOL rpmError = ReadProcessMemory(
            hProc,
            procInfoBuf.GetAs<PROCESS_BASIC_INFORMATION>()->PebBaseAddress,
            &peb,
            sizeof(peb),
            0);
        if (rpmError == 0)
        {
            THROW_LAST_WINDOWS_ERROR();
        }

        RTL_USER_PROCESS_PARAMETERS procParameters;
        rpmError = ReadProcessMemory(hProc,
            peb.ProcessParameters,
            &procParameters,
            sizeof(procParameters),
            0);
        if (rpmError == 0)
        {
            THROW_LAST_WINDOWS_ERROR();
        }

        commandLine.assign(ReadRemoteUnicodeString(hProc,
            procParameters.CommandLine));
        mainModulePath.assign(ReadRemoteUnicodeString(hProc,
            procParameters.ImagePathName));

        PEB_LDR_DATA ldrData;
        rpmError = ReadProcessMemory(hProc,
            peb.Ldr,
            static_cast<void *>(&ldrData),
            sizeof(PEB_LDR_DATA),
            0);
        if (rpmError == 0)
        {
            THROW_LAST_WINDOWS_ERROR();
        }

        void * endPointer = static_cast<void *>
            (reinterpret_cast<char *>(peb.Ldr) + (reinterpret_cast<char *>(&ldrData.InLoadOrderModuleList) - reinterpret_cast<char *>(&ldrData)));
        void * currentListEntry = ldrData.InLoadOrderModuleList.Flink;
        while (currentListEntry != endPointer)
        {
            LDR_MODULE loaderModule;
            rpmError = ReadProcessMemory(
                hProc,
                currentListEntry,
                &loaderModule,
                sizeof(loaderModule),
                0);
            if (rpmError == 0)
            {
                THROW_LAST_WINDOWS_ERROR();
            }
            std::wstring moduleName = ReadRemoteUnicodeString(hProc, loaderModule.FullDllName);
            modules.push_back(Module(
                moduleName,
                loaderModule.BaseAddress,
                loaderModule.SizeOfImage
                ));
            currentListEntry = loaderModule.InLoadOrderModuleList.Flink;
        }

        CloseHandle(hProc);
    }
    catch (const ErrorAccessDeniedException&)
    {
        error.assign(L"ERROR: Could not access additional information because access "
            L"was denied while attempting to open the process. Are you admin? Do you "
            L"have SeDebugPrivilege?");
    }
    catch (const ErrorInvalidParameterException&)
    {
        error.assign(L"ERROR: The process terminated before additional information "
            L"could be extracted");
    }
    catch (const ErrorPartialCopyException&)
    {
        error.assign(L"ERROR: Couldn't copy a data structure from this process. Either "
            L"the process terminated before information extraction, or you are running "
            L"the 32 bit version of pevFind on a 64 bit machine.");
    }

    if (!error.empty())
    {
        if (nameStr.empty())
        {
            nameStr = error;
        }
        if (commandLine.empty())
        {
            commandLine = error;
        }
        if (mainModulePath.empty())
        {
            mainModulePath = error;
        }
    }

    return Process(
        parent,
        pid,
        nameStr, 
        commandLine,
        mainModulePath,
        threads,
        modules);
}

Проблема здесь двоякая:

  1. Я не могу извлечь из дублируются если блоки в метод, потому что так надо, что они встроить __файл__ и __линия__.
  2. Я не могу поставить проверку в макро, потому что контролируемый способ занимает несколько строк:

    MYMACRO(
        Function(
        Call,
        Spanning,
        Multiple,
        Lines));
    

    не правильно расширяться.



834
9
задан 27 января 2011 в 03:01 Источник Поделиться
Комментарии
5 ответов

В MYMACRO звонок должен быть штраф.

#define D3DCALL(a) { auto __ = a; if (FAILED(__)) DXTrace(__FILE__, __LINE__, __, WIDEN(#a), TRUE); }
D3DCALL(D3DXCreateSphere(
D3DDev.get(),
radius,
slices,
slices,
&retval->Mesh._Myptr,
&retval->Adjacency._Myptr
));

Я использую это в мой собственный код все время. Главным образом, вы получите проблемы, если вы пытаетесь условной компиляции в вызове макроса.

5
ответ дан 27 января 2011 в 09:01 Источник Поделиться

Если вопрос в том, как взять что-то вроде этого:

HANDLE hProc = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE,
pid);
if (hProc == 0)
{
THROW_LAST_WINDOWS_ERROR();
}

И уменьшить ее на один-лайнер, я обычно использую проверьте макрос:

template<class Eval> RetVal Verify(Eval eval, static const string& file, unsigned line)
{
if( !eval )
throw MyException(error_string, file, line);
else
return eval;
}

#define verify(EVAL) (Verify(EVAL, __FILE__, __LINE__))

// ...

HANDLE hProc = verify( OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid ));

7
ответ дан 27 января 2011 в 09:01 Источник Поделиться

Этот ответ не лучший, но вы можете создать новую переменную каждый раз, когда вы присваиваете значение rpmError и иметь, если заявление, где последний, чтобы проверить, если любой из них равен 0.

Примечание: это не будет работать, если это абсолютно необходимо, чтобы эти ошибки бросаются до следующей проверки.

1
ответ дан 27 января 2011 в 06:01 Источник Поделиться

Взято из ответа Чарльза из вашего исходного поста, будет что-то вроде этой работы?

#define THROW_LAST_WINDOWS_ERROR(condition) ThrowOnFail(condition, __FILE__, __LINE__)

void ThrowOnFail(const BOOL condition, LPCSTR file_name, const int file_line)
{
if (!condition)
WindowsApi::Exception::Throw(::GetLastError(), file_name, file_line);
}

Затем обработка ошибок будет выглядеть примерно так:

THROW_LAST_WINDOWS_ERROR(ReadProcessMemory(hProc,
procInfoBuf.GetAs<PROCESS_BASIC_INFORMATION>()->PebBaseAddress,
&peb,
sizeof(peb),
0));
THROW_LAST_WINDOWS_ERROR(ReadProcessMemory(hProc,
peb.Ldr,
static_cast<void *>(&ldrData),
sizeof(PEB_LDR_DATA),
0));
// ...
while (currentListEntry != endPointer)
{
LDR_MODULE loaderModule;

THROW_LAST_WINDOWS_ERROR(ReadProcessMemory(
hProc,
currentListEntry,
&loaderModule,
sizeof(loaderModule),
0));

// ...
}

1
ответ дан 27 января 2011 в 09:01 Источник Поделиться

Вы также должны иметь вариант для явной проверки возвращаемых значений. Например, функция CreateFile возвращает INVALID_HANDLE_VALUE , который !=0.

Редактировать: Ах, я, кажется, понял теперь вопрос. Вы хотите знать, как добиться этого:

int x= foo();
if (x==error) { blah(); }

в макросе.

Самый простой способ заключается в разделении объявление переменной и задание переменных:

int x;
if ((x= foo())==error) { blah(); }

которое затем можно обернуть в макрос:

#define MYMACRO(x) if ((x)==error) { blah(); }

которые затем можно использовать в качестве:

int x;
MYMACRO(x= foo());

1
ответ дан 28 января 2011 в 05:01 Источник Поделиться