简体   繁体   English

GetModuleFileNameEx,访问被拒绝错误

[英]GetModuleFileNameEx, Access Denied Error

I'm trying to get the name of all my open processes. 我正在尝试获取所有打开进程的名称。 This is what I have: 这就是我所拥有的:

   #include "stdafx.h"
#include <Psapi.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int iCmdShow)
{
    bool _result;
    DWORD *pProcessIds = new DWORD[1000];
    DWORD cb;
    DWORD pBytesReturned;

    _result =  EnumProcesses(pProcessIds, 1000, &pBytesReturned);

    HANDLE hndProccesse;


    for (int i = 0; i < pBytesReturned / sizeof(DWORD); ++i)
    {
        hndProccesse =   OpenProcess(STANDARD_RIGHTS_ALL,  false, *pProcessIds);
        DWORD _len;

        DWORD _len2 =0;
        LPWSTR lpFilename = new WCHAR[100];
        _len =GetModuleFileNameEx(hndProccesse,NULL, lpFilename, _len2);
        DWORD _errr;
        _errr =  GetLastError();
        MessageBox(NULL, lpFilename, NULL, 0);
        CloseHandle(hndProccesse);

        pProcessIds ++;



    }

    return 0;
}

Everything is working fine upto GetModuleFileNameEx which is giving an Access Denied Error (5). 一切正常,直到GetModuleFileNameEx给出访问拒绝错误(5)。

Also this is whats displaying on the message box: 这也是消息框中显示的内容: 在此处输入图片说明

Any Ideas? 有任何想法吗?

The fourth argument to GetModuleFileNameEx() has to be the size of the array passed in the third argument. GetModuleFileNameEx()的第四个参数必须是在第三个参数中传递的数组的大小。 You pass in _len2 . 您传入_len2 But you set _len2 to zero, not to the size of your lpFilename array (100). 但是您将_len2设置为零,而不是lpFilename数组的大小(100)。 So GetModuleFileNameEx() sees it has nothing to do, and doesn't even touch your lpFilename array. 因此, GetModuleFileNameEx()认为它无关紧要,甚至都没有触及lpFilename数组。 Heap data isn't necessarily initialized to zeroes, so lpFilename still contains random garbage, hence the random message box contents. 堆数据不一定要初始化为零,因此lpFilename仍然包含随机垃圾,因此是随机消息框的内容。

I am going to guess that GetModuleFileNameEx() returned zero because it didn't need to write anything, but didn't set the last error code because nothing failed, so the access denied error is left over from an earlier part of the program. 我将猜测GetModuleFileNameEx()返回零是因为它不需要编写任何内容,但是由于没有任何失败而没有设置最后的错误代码,因此该程序的较早部分遗留下了拒绝访问错误。

Some more notes: 更多注意事项:

Keep in mind what Jonathan Potter said about the proper way to check error returns from Windows API functions. 请记住,乔纳森·波特(Jonathan Potter)所说的有关检查Windows API函数返回的错误的正确方法。 You have you return value from GetModuleFileNameEx() in _len . 您从_len GetModuleFileNameEx()返回值。 MSDN says GetModuleFileNameEx() returns zero on error. MSDN说, GetModuleFileNameEx()在出错时返回零。 So you need to check _len to see if it equals zero before getting the last error value, otherwise it won't be meaningful. 因此,您需要在获取最后一个错误值之前检查_len以查看其是否等于零,否则它将没有意义。 As mentioned earlier, GetModuleFileNameEx() doesn't have to clear the last error value if it succeeds. 如前所述,如果成功, GetModuleFileNameEx()不必清除最后一个错误值。

HANDLE hndProccesse = new HANDLE; is definitely wrong, but is not a bug in your program (it is a memory leak, though!). 肯定是错误的,但不是程序中的错误(尽管这内存泄漏!)。 HANDLE itself is a pointer, which is why the new was allowed to run. HANDLE本身是一个指针,这就是允许new运行的原因。 But doing so is meaningless, as HANDLE s are returned by the operating system and generally shouldn't be used as pointers. 但是这样做是没有意义的,因为HANDLE是由操作系统返回的,通常不应用作指针。 Consider them opaque values instead. 可以考虑将它们视为不透明值。

On the subject of memory leaks, you never delete[] each of the lpFilename s you create in your loop, nor do you delete[] pProcessIds . 关于内存泄漏,您永远不要delete[]在循环中创建的每个lpFilename ,也不要delete[] pProcessIds This might not be important for the small program you posted above, but if your program ever grows you'll definitely want to fix that. 对于您上面发布的小程序来说,这可能并不重要,但是如果您的程序不断增长,那么您肯定会解决该问题。

In general, use MAX_PATH as the nominal length of a filename buffer instead of 100. This is what the various shell functions use. 通常,使用MAX_PATH作为文件名缓冲区的标称长度而不是100。这就是各种Shell函数使用的名称。 (Longer won't hurt either, but shorter will.) (更长的时间也不会伤害,但是会更短。)

You need to use FormatMessage to get a useful error description. 您需要使用FormatMessage获得有用的错误描述。 An example is shown below.. This example is exactly like yours but all it does is incorporate error checking. 下面显示了一个示例。此示例与您的示例完全相同,但所做的只是合并了错误检查。 IT DOES NOT SOLVE THE PROBLEM! 它不能解决问题!

#include <windows.h>
#include <Psapi.h>

void ShowError(DWORD err)
{
    LPTSTR lpMsgBuf = nullptr;
    FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
    MessageBoxA(NULL, lpMsgBuf, "ERROR", 0);
    LocalFree(lpMsgBuf);
}

int main()
{
    DWORD* pProcessIds = new DWORD[1000];
    DWORD pBytesReturned = 0;

    bool res =  EnumProcesses(&pProcessIds[0], 1000, &pBytesReturned);

    if (!res)
    {
        DWORD err = GetLastError();
        MessageBoxW(NULL, L"ENUMPROCESSES FAILED", L"Error", 0);
        ShowError(err);
        delete[] pProcessIds;
        return EXIT_FAILURE;
    }

    for (unsigned int i = 0; i < pBytesReturned / sizeof(DWORD); ++i)
    {
        if (pProcessIds[i] == 0) //error.. process id is 0..
            continue;

        wchar_t lpFilename[256] = {0};
        HANDLE hndProccess =   OpenProcess(STANDARD_RIGHTS_ALL,  false, pProcessIds[i]);

        if (hndProccess == NULL || hndProccess == INVALID_HANDLE_VALUE)
        {
            DWORD err = GetLastError();
            MessageBoxW(NULL, L"FAILED TO OPEN PROCESS", L"ERROR", 0);
            ShowError(err);
            delete[] pProcessIds;
            return EXIT_FAILURE;
        }

        int len = GetModuleFileNameExW(hndProccess, NULL, lpFilename, sizeof(lpFilename) / sizeof(lpFilename[0]));
        if (len <= 0)
        {
            DWORD err = GetLastError();
            if (err)
            {
                MessageBoxW(NULL, L"FAILED TO GET MODULEFILENAME", L"ERROR", 0);
                ShowError(err);
                delete[] pProcessIds;
                return EXIT_FAILURE;
            }
        }          

        CloseHandle(hndProccess);

        MessageBoxW(NULL, lpFilename, L"NAME", 0);
    }

    delete[] pProcessIds;
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM