tags:

views:

140

answers:

6

I'm trying to test if standard library (kernel32.dll) have one of the function.

Code snippet for test:

extern void CreateProcessA (void);
int
main (void)
{
  CreateProcessA ();
  return 0;
}

The code compiles and links as follow:

cl /c test.c
link test.obj kernel32.lib

This code can be compiled well with Visual C++, but cannot link:

test.obj : error LNK2019: unresolved external symbol _CreateProcessA referenced in function _main

But function CreateProcessA does exists in kernel32.dll, you no?

How to link it properly?

P.S. I don't want to run this code, just check that function exists (if code compiles and links - function exists).

+6  A: 

To see if the function exists, you use

dumpbin /exports kernel32.dll | findstr CreateProcess

You didn't even use the right prototype, so of course the linker can't find the correct function. The naming convention is completely off, and CreateProcess is really a macro (that expands to either CreateProcessA or W depending on UNICODE).

(You don't need to link against kernel32.lib explicitly as that's already done by default by cl.exe)

Instead of declaring the prototype yourself, #include <windows.h>.

Alex
A: 

I think this is a bad idea, but if you want to do it, you need to link with the kernel32.lib export library.

anon
A: 

You must include windows.h in order to get the correct prototype:

#include <windows.h>
int
main (void)
{
  CreateProcess(); // will cause warning due to incorrect parameter list
  return 0;
}

Is there a particular reason you don't want to include windows.h?

JesperE
You don't need the correct prototype for C linkage.
anon
But it's not C linkage in this case - CreateProcess uses stdcall which means that the name is decorated with the number of bytes of stack used for parameters - his declaration doesn't include it.
Larry Osterman
Wow! Larry is on Stack Overflow! Hi Larry!
Alex
+2  A: 

Right now you are declaring your own version of CreateProcess(). Since you did not provide the body (code), the linker doesnt know where to check to find the function to execute.

In order to call CreateProcess from kernel32.lib, you need to include the proper headers

#include <windows.h>

If the compiler doesnt know windows.h then probably Platform SDK for windows isnt installed correctly.

you will also need to link with the proper lib

#pragma comment(lib, "kernel32.lib")

You should also read the documentation about createprocess since it takes a gazillion of parametetrs

BOOL WINAPI CreateProcess(
  __in_opt     LPCTSTR lpApplicationName,
  __inout_opt  LPTSTR lpCommandLine,
  __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in         BOOL bInheritHandles,
  __in         DWORD dwCreationFlags,
  __in_opt     LPVOID lpEnvironment,
  __in_opt     LPCTSTR lpCurrentDirectory,
  __in         LPSTARTUPINFO lpStartupInfo,
  __out        LPPROCESS_INFORMATION lpProcessInformation
);

You should search for CreateProcess examples across the interwebs and maybe consider switching to c++ since you're on windows

Eric
A: 

For starters, put in a proper header file for the prototypes, <windows.h>, as this is a Windows source, add the kernel32.lib for your linker, remove that prototype as it is incorrect. Your main function is debatable as to whether you are creating a command line program or a windows program - if it is the latter, that should read 'WinMain'.

If you look in the MSDN for the function 'CreateProcess', scroll down and you will see the 'Library', that is the hint to tell you which library you need to link for it to work properly.

Hope this helps, Best regards, Tom.

tommieb75
+3  A: 

Kernel32.dll exports the function as "CreateProcessA", note the missing leading underscore. The only way to convince the linker to use that export is by linking kernel32.lib, an import library supplied by the Windows SDK.

You'll then run into the next problem, the import library declares the export as _CreateProcess@40. This is a name decoration applied by the __stdcall calling convention. That calling convention was explicitly designed to catch your mistake, you didn't declare the function properly. The @40 part of the name indicates the number of bytes needed in the stack frame to pass the arguments.

So, to make it work you should #include <windows.h> to get the proper function declaration and link kernel32.lib to get the proper export name.

Hans Passant
Not only that but the symbol is decorated further, prefixed with `__imp_`. So you also need a `__declspec(dllimport)` to get the right naming. But of course, that's done by `<windows.h>`.
Alex