www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 1695] New: Calling some functions out of PSAPI.dll corrupts stack

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1695

           Summary: Calling some functions out of PSAPI.dll corrupts stack
           Product: D
           Version: 2.007
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: critical
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: mail tobias-wassermann.de


1. Generate a lib with implib: implib /noi /system psapi.lib
C:\windows\system32\psapi.lib

2. Compile the following code with dmd ProcessFinder.d -L+psapi/noi

import std.stdio;
import std.c.windows.windows;

extern (Windows) HANDLE OpenProcess(uint dwDesiredAccess, BOOL bInheritHandle,
uint dwProcessId);    

extern (C) 
{
  BOOL EnumProcesses(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned);
  DWORD GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule, char* fileName,
uint size);  
  DWORD GetProcessImageFileNameA(HANDLE hProcess, LPSTR lpImageFileName, DWORD
nSize);
}

void main(char[][] args)
{
  uint[256] processIds;
  uint byteCount;
  char[] processFileName;
  int ret = EnumProcesses(processIds.ptr, processIds.length*uint.sizeof,
&byteCount);
  if(ret!=0)
  {
    for(uint i=0; i<processIds.length && i<byteCount/uint.sizeof; i++)
    {
      if(processIds[i]==0)
        continue;
      uint pid =  processIds[i];   


      HANDLE hProcess = OpenProcess(0x410 /* QueryInformation | VMRead */,
false, pid);
      if(cast(int)hProcess>0)
      {
        processFileName.length = 300;
        uint namelength = 0;
        //namelength = GetProcessImageFileNameA(hProcess, processFileName.ptr,
processFileName.length);
        namelength = GetModuleFileNameExA(hProcess, cast(HMODULE)0,
processFileName.ptr, processFileName.length);
        processFileName.length = namelength;
        writefln("=> %s", processFileName);        
        CloseHandle(hProcess);
      }
    }
  }
}

So what will happen? With commented out GetModuleFileNameExA()-call you will
get a list of correct process id's:





If you use GetModuleFileNameExA() the list will be incorrect:












id doesn't exist, the next real id is 1288.

3. After calling GetModuleFileNameExA() the stack will be corrupted, the
processIds-Array will be incorrect, if you comment out this call, all works
fine. The same behaviour if you call GetProcessImageFileNameA()

Strange thing: If you port the code to C and compile against DMC - same
problem! If you compile it with Microsoft Visual C++, you can also use
GetModuleFileNameExA() and GetProcessImageFileNameA() without any problems.
Seems to be an implib-issue?

See also the "Windows API: Strange behaviour after calling
GetModuleFileNameExA" entries within the digitalmars.D-newsgroup


-- 
Nov 27 2007
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1695


bugzilla digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |INVALID





The problem is declaring Windows API functions as being extern(C). They should
be extern(Windows). Stack corruption is the result of incorrectly declaring
what function calling convention to use.


-- 
Dec 29 2007
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1695


Denis Shelomovskij <verylonglogin.reg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
                 CC|                            |verylonglogin.reg gmail.com
            Version|2.007                       |unspecified
         Resolution|INVALID                     |
            Summary|Calling some functions out  |implib produces wrong *.lib
                   |of PSAPI.dll corrupts stack |files



14:58:05 MSD ---

 The problem is declaring Windows API functions as being extern(C). They should
 be extern(Windows). Stack corruption is the result of incorrectly declaring
 what function calling convention to use.
Looks like Walter like spending people time. As "extern(Windows)" and "extern(C)" functions has different symbol names the fact that the program links, runs and corrupts the stack just shows that `implib` generates incorrect *.lib files. Incorrect behavior example (DLL): implib /noi /system psapi-from-dll.lib %windir%\system32\psapi.dll --- pragma(lib, "psapi-from-dll.lib"); extern(C) nothrow extern void EnumProcesses(); // links fine void main() { auto p = &EnumProcesses; } --- More than that 'implib' works incorrect with '.def' files too. Incorrect behavior example (DEF): psapi.def (from mingw except library name is "PSAPI" instead of "PSAPI.DLL" because 'implib' stops on dot with error): --- LIBRARY PSAPI EXPORTS EnumProcesses 12 --- implib /noi /system psapi-from-def.lib psapi.def --- pragma(lib, "psapi-from-def.lib"); // Error 42: Symbol Undefined _EnumProcesses // or _EnumProcesses 12 for extern(Windows) extern(C) nothrow extern void EnumProcesses(int, int, int); void main() { auto p = &EnumProcesses; } --- The second issue is because 'implib' ignores '/system' switch for *.def files: implib /noi psapi-from-def-no-system.lib psapi.def produces exactly same *.lib file. The second issue has trivial workaround: one should prefix all symbols in *.def file with '_' by hands. E.g. such *.def file finally forces 'implib' to produce a correct *.lib: --- LIBRARY PSAPI EXPORTS _EnumProcesses 12 --- -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 21 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1695




15:03:45 MSD ---
Damn, sorry. This is the correct DEF file for 'implib':
---
LIBRARY PSAPI
EXPORTS
_EnumProcesses 12=EnumProcesses
---
(or the program will link but fail to run trying to search for
'_EnumProcesses 12' symbol in psapi.dll)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 21 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1695


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |RESOLVED
         Resolution|                            |WONTFIX



01:23:20 PDT ---
All /system does is prepend a _. See:

http://www.digitalmars.com/ctg/implib.html

The trouble is that the names in Windows systems DLLs use the extern (Windows)
calling convention, but they don't use the extern (Windows) mangled names. The
Windows mangled names have the  nn suffix.

The names happen to match up with the C names, but the stack treatment is
different, hence the crash.

There is nothing implib can do about this situation. The only thing you, as a
user, can do is create a correct module definition file in order to map the
internal and external names. Implib can't do that, as it doesn't have the
information to do it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 07 2013