tags:

views:

439

answers:

3
//window is an HWND
LPWSTR path = new WCHAR[1024];
DWORD  size = 1024;

GetWindowText(window, path, 1024);

HINSTANCE instance = (HINSTANCE)GetWindowLongPtr(window, GWLP_HINSTANCE);

QueryFullProcessImageName(instance, PROCESS_NAME_NATIVE, path, &size);

This code fails on the call to QueryFullProcessImageName(...) with an error code 6 [invalid handle]. GetWindowText succeeds, and GetWindowLong returns a non-zero HINSTANCE.

I'm pretty new to win32, so why this isn't working is beyond me. I believe both the HWND and HINSTANCE involved are valid...

Thanks

+3  A: 

Main problem:

For the function: QueryFullProcessImageName, the first parameter is not an HINSTANCE, it is the process handle. They are different. To get the current process Id you should use GetCurrentProcessId. Then pass that into OpenProcess to get the process handle.


Other Problem:

You should be using GetWindowLongPtr above instead of GetWindowLong. Using GetWindowLong would likely cause problems on x64 systems.


How to find out what your problem is on your own:

After most Win32 functions fail, you can find out the reason why by using GetLastError.

So after the call to QueryFullProcessImageName please do this:

DWORD dwLastError = GetLastError();
LPVOID lpMsgBuf;
std::string strErrorMessage;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,    0, NULL);
if (lpMsgBuf)
{
    strErrorMessage = (const TCHAR*)lpMsgBuf;
    LocalFree(lpMsgBuf);
}

You can also simply just call GetLastError() and lookup its return value here.

Brian R. Bondy
Question updated accordingly. Problem still exists though.
Kevin Montrose
@Kevin Montrose: I updated with the reason why
Brian R. Bondy
Fixed code:DWORD processID = 0; GetWindowThreadProcessId(window, HANDLE processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, processID);QueryFullProcessImageName(processHandle, PROCESS_NAME_NATIVE, path, Thanks.
Kevin Montrose
+1  A: 

Here's a function I coded for you, which has support for older versions of Windows (since QueryFullProcessImageName is for Windows Vista and newer).

#include <psapi.h>
#pragma  comment(lib, "psapi.lib")

#if WINVER >= 0x600
#  define PROCESS_GET_IMAGE_NAME (PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ)
#else
#  define PROCESS_GET_IMAGE_NAME (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ)
#endif

__checkReturn BOOL GetWindowFileNameW(__in HWND hWnd, __out_ecount_full_z(nLength) LPWSTR lpwszBuffer, __in SIZE_T nLength)
{
  HINSTANCE hInstance;
  HANDLE    hProcess;
  DWORD     dwProcessId;
#if WINVER >= 0x600
  DWORD     dwSize;
#endif
  BOOL      bRET = FALSE;

  hInstance = (HINSTANCE)GetWindowLongPtrW(hWnd, GWLP_HINSTANCE);
  if (hInstance != NULL)
  {
    GetWindowThreadProcessId(hWnd, &dwProcessId);
    hProcess = OpenProcess(PROCESS_GET_IMAGE_NAME, FALSE, dwProcessId);
    if (hProcess != NULL)
    {
#if WINVER >= 0x600
      if (LOWORD(GetVersion()) >= 6)
        bRET = QueryFullProcessImageNameW(hProcess, PROCESS_NAME_NATIVE, lpwszBuffer, &dwSize);
      else
#endif
        bRET = GetModuleFileNameExW(hProcess, hInstance, lpwszBuffer, nLength) != 0;
      CloseHandle(hProcess);
    }
  }
  return bRET;
}

Just a note, the PROCESS_VM_READ flag in Vista is just a fall through in case QueryFullProcessImageNameW fails and GetModuleHandleExW has to be used.

Irwin
A: 

> Here's a function I coded for you

Very bad.
psapi must not be linked statically (never)!

See MSDN samples.

Uh, I think it's quite clear that you don't know too much.
Irwin