21 out of 52 rated this helpful - Rate this topic

GetModuleFileName function

Applies to: desktop apps only

Retrieves the fully qualified path for the file that contains the specified module. The module must have been loaded by the current process.

To locate the file for a module that was loaded by another process, use the GetModuleFileNameEx function.

Syntax

DWORD WINAPI GetModuleFileName(
  __in_opt  HMODULE hModule,
  __out     LPTSTR lpFilename,
  __in      DWORD nSize
);

Parameters

hModule [in, optional]

A handle to the loaded module whose path is being requested. If this parameter is NULL, GetModuleFileName retrieves the path of the executable file of the current process.

The GetModuleFileName function does not retrieve the path for modules that were loaded using the LOAD_LIBRARY_AS_DATAFILE flag. For more information, see LoadLibraryEx.

lpFilename [out]

A pointer to a buffer that receives the fully qualified path of the module. If the length of the path is less than the size that the nSize parameter specifies, the function succeeds and the path is returned as a null-terminated string.

If the length of the path exceeds the size that the nSize parameter specifies, the function succeeds and the string is truncated to nSize characters including the terminating null character.

Windows XP:  The string is truncated to nSize characters and is not null-terminated.

The string returned will use the same format that was specified when the module was loaded. Therefore, the path can be a long or short file name, and can use the prefix "\\?\". For more information, see Naming a File.

nSize [in]

The size of the lpFilename buffer, in TCHARs.

Return value

If the function succeeds, the return value is the length of the string that is copied to the buffer, in characters, not including the terminating null character. If the buffer is too small to hold the module name, the string is truncated to nSize characters including the terminating null character, the function returns nSize, and the function sets the last error to ERROR_INSUFFICIENT_BUFFER.

Windows XP:  If the buffer is too small to hold the module name, the function returns nSize. The last error code remains ERROR_SUCCESS. If nSize is zero, the return value is zero and the last error code is ERROR_SUCCESS.

If the function fails, the return value is 0 (zero). To get extended error information, call GetLastError.

Remarks

If a DLL is loaded in two processes, its file name in one process may differ in case from its file name in the other process.

The global variable _pgmptr is automatically initialized to the full path of the executable file, and can be used to retrieve the full path name of an executable file.

Examples

For an example, see Installing a Service.

Requirements

Minimum supported client

Windows XP

Minimum supported server

Windows Server 2003

Header

Winbase.h (include Windows.h)

Library

Kernel32.lib

DLL

Kernel32.dll

Unicode and ANSI names

GetModuleFileNameW (Unicode) and GetModuleFileNameA (ANSI)

See also

Dynamic-Link Library Functions
GetModuleFileNameEx
GetModuleHandle
LoadLibrary
LoadLibraryEx

 

 

Send comments about this topic to Microsoft

Build date: 3/6/2012

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
C++ Wrapper for this function

Here's a C++ wrapper for this function that takes care of appropriate buffer sizing and error checking. You may want to upgrade it to use TCHARs for unicode-aware applications.

<pre>std::string WindowsEnvironment::getExectablePath() {
  std::vector&lt;char&gt; executablePath(MAX_PATH);

  // Try to get the executable path with a buffer of MAX_PATH characters.
  DWORD result = ::GetModuleFileNameA(
    nullptr, &executablePath[0], static_cast&lt;DWORD&gt;(executablePath.size())
  );

  // As long the function returns the buffer size, it is indicating that the buffer
  // was too small. Keep enlarging the buffer by a factor of 2 until it fits.
  while(result == executablePath.size()) {
    executablePath.resize(executablePath.size() * 2);
    result = ::GetModuleFileNameA(
      nullptr, &executablePath[0], static_cast&lt;DWORD&gt;(executablePath.size())
    );
  }

  // If the function returned 0, something went wrong
  if(result == 0) {
    throw std::runtime_error("GetModuleFileName() failed");
  }

  // We've got the path, construct a standard string from it
  return std::string(executablePath.begin(), executablePath.begin() + result);
}</pre>

Problem on WoW64
If called from a WoW64 context -- a 32-bit application running under 64-bit Windows XP -- and the module is a system or driver module loaded from C:\WINDOWS\SysWOW64, then GetModuleFileName will return a File-system redirected path C:\WINDOWS\system32\...

This is probably by design, and passing that file name to CreateFile() to open the binary file will redirect back to the same file correctly.

However, calling Wow64DisableWow64FsRedirection() before calling GetModuleFileName() does NOT turn off this redirection give you the correct file name!! If you need the "true" file name for a module, this won't give it to you.

For example, a 32-bit program that does the following:
  • Call Wow64DisableWow64FsRedirection() to disable file redirection.
  • Call GetModuleHandle() to get the handle of a driver DLL that is already loaded. Since this is a 32-bit application, the module is actually in %windir%\SysWOW64\foo.dll.
  • Call GetModuleFileName() to get the file name. This will return something like %windir%\System32\foo.dll
  • Call CreateFile() to open the file. Since FS redirection is turned off, this will open the 64-bit version of the module, not the file that is actually loaded!
(This assumes, of course, that the 32-bit and 64-bit system modules have the same base name. If they don't, the CreateFile() will just fail. For example, the ATI Catalyst driver installs 32-bit %windir%\SysWOW64\aticaldd.dll and 64-bit %windir%\system32\aticaldd64.dll. In this example, the string passed to CreateFile would be %windir%\system32\aticaldd.dll, and CreateFile would fail with a "no such file" error.)

IMHO this should be considered a bug in either Wow64DisableWow64FsRedirection or GetModuleFileName; I'm not sure which one should be blamed.

I haven't tested this on Vista or Win7, but XP Professional 64-bit certainly behaves this way.
_pgmptr
The remarks mention the global variable_pgmptr.
This global variable is only valid in applications compiled with the ASCII libraries. When using unicode libraries _wpgmptr should be used instead.

There is a macro _tpgmptr defined in tchar.h which will automatically use the correct variable for the project configuration.

Note that this variable is considered unsafe. _get_pgmptr, _get_wpgmptr and _get_tpgmptr should be used instead if GetModuleFileName can't be.
Windows Mobile handles

For Windows Mobile Process ID can be used directly as handle.