Alternative to symlink in C++ Builder

310 views Asked by At

I'm currently trying to integrate a C code written for UNIX in C++ Builder. But a part of the code is using the function symlink :

if(!fname
|| (use_real_copy ? real_copy(path, fname) : symlink(path, fname))

I don't know how to replace it so it works in C++ Builder for Windows 64 bits, I've found the functions CreateSymbolicLinkW and CreateSymbolicLinkA that seem to be the equivalent for Windows but C++ Builder can't find them.

Do you have any idea of how I can get around this problem?

Thank you.

1

There are 1 answers

1
Remy Lebeau On BEST ANSWER

CreateSymbolicLink() is declared in winbase.h, which is #include'd by windows.h, which is #include'd by vcl.h in all VCL-based projects. If you are not creating a VCL project, make sure you have an #include <windows.h> statement in your code. Either way, also make sure that _WIN32_WINNT is defined to be at least 0x0600 (Vista+).

If the compiler still complains that CreateSymbolicLink() is undefined then you must be using an old version of C++Builder (CreateSymbolicLink() was added to C++Builder's copy of winbase.h in C++Builder 2007), in which case you will have to declare CreateSymbolicLink() manually in your own code, eg:

#define SYMBOLIC_LINK_FLAG_DIRECTORY            (0x1)

#define VALID_SYMBOLIC_LINK_FLAGS  SYMBOLIC_LINK_FLAG_DIRECTORY // & whatever other flags we think of!

WINBASEAPI
BOOLEAN
APIENTRY
CreateSymbolicLinkA (
    __in LPCSTR lpSymlinkFileName,
    __in LPCSTR lpTargetFileName,
    __in DWORD dwFlags
    );
WINBASEAPI
BOOLEAN
APIENTRY
CreateSymbolicLinkW (
    __in LPCWSTR lpSymlinkFileName,
    __in LPCWSTR lpTargetFileName,
    __in DWORD dwFlags
    );
#ifdef UNICODE
#define CreateSymbolicLink  CreateSymbolicLinkW
#else
#define CreateSymbolicLink  CreateSymbolicLinkA
#endif // !UNICODE

But then you have another problem to tackle - that version of C++Builder would also not have the CreateSymbolicLinkA and CreateSymbolicLinkW symbols in its copy of kernel32.lib for linking to the exported functions in kernel32.dll. So you would have to create a new .lib import library from a modern kernel32.dll that includes those symbols, and then add it to your project. At which point, it would probably be easier to just dynamically load CreateSymbolicLink() at runtime using GetProcAddress() instead:

typedef BOOLEAN (APIENTRY *LPFN_CSL)(LPCTSTR, LPCTSTR, DWORD);

LPFN_CSL lpCreateSymbolicLink = (LPFN_CSL) GetProcAddress(GetModuleHandle(TEXT("kernel32")),
    #ifdef UNICODE
    "CreateSymbolicLinkW"
    #else
    "CreateSymbolicLinkA"
    #endif
);
if (lpCreateSymbolicLink)
{
    // use lpCreateSymbolicLink(...) as needed...
}

Which will also allow your code to run on XP and earlier (if needed), since CreateSymbolicLink() was added in Vista.