Create Symbolic Link on Windows using C++ - winapi

I would like to create symbolic links to my data from my program in a cross-platform manner. For *nix systems, there is the symlink. For Windows, I found the function CreateSymbolicLink from this answer in SO and I am running it in this way:
int test = CreateSymbolicLink(input_fileName.c_str(), ouput_fileName.c_str(), 0);
But test always returns 0, which means that the function failed (and the file specified in output_fileName is indeed non-existent). What am I doing wrong?
Thanks in advance!
UPDATE:
I did run GetLastError right after the above call:
DWORD err = GetLastError();
with err = 1314. Thanks #David
UPDATE 2:
According to #David's reply, Windows does not let non-admins create soft-links. I am keeping the question open if a future iteration of Win API changes this. Then I will update the answer. As of 26/March/2015, #David's answer is correct.

From the documentation:
If the function fails, the return value is zero. To get extended error information, call GetLastError.
You don't appear to have called GetLastError. You should do so. A likely error code is ERROR_PRIVILEGE_NOT_HELD which has value 1314. You'll get this if the calling process does not have enough rights. You need to be running as an elevated administrator to use this function.

use c++17 create_symlin instead https://en.cppreference.com/w/cpp/filesystem/create_symlink
It works fine.

I grabbed the USB stick that was formatted as FAT for my test. the above code should work if you are using the correct volume format and you are in the Administrator Group. If you are in Windows 10 you should not need to Adjust Token Privileges, and you do not need UNC for the parameters.

Related

Win32::OLE::Const can't find 64-bit MS Office constants

We have a legacy perl code base that includes the below line:
use Win32::OLE::Const 'Microsoft Excel';
This has worked traditionally but is not working on newer 64-bit installations, such as Windows 10.
The error appears to be in the OLE.xs source as below, but I have a limited understanding of Windows functions and XS in general.
err = RegQueryValueA(hKeyLangid, "win32", szFile, &cbFile);
If this query fails, it never calls Win32::OLE::Const::_Typelib which is the function that stores the result. Checking my registry, the keys are indeed Win64 and not win32. Other keys that worked either have just win32 or both.
Is there a way to resolve this issue without editing the legacy module? It is widely used and any changes would involve some risk so I'm looking at alternatives first.
I'm aware we can do the below, but it doesn't stop the other Win32::OLE::Const line causing an error if it's not removed.
my $Excel = Win32::OLE->new('Excel.Application', 'Quit');
my $xl = Win32::OLE::Const->Load($Excel);
I'll provide a fix in case anyone wants to use it. It's not clear to me whether Win32::OLE is still being maintained, as the issues list at https://rt.cpan.org/Public/Bug/Display.html?id=48858 raised this exact item a number of months ago, so I'm not sure where to submit a patch.
As noted in that link there are a few ways to resolve this (such as giving preference to the win64 entry if both exist), however I've decided it would be best in our case to only query the win64 folder if win32 does not return anything useful.
To do this, in OLE.xs search for win32 and change as below.
err = RegQueryValueA(hKeyLangid, "win32", szFile, &cbFile);
// check win64 if win32 failed
if (err != ERROR_SUCCESS || cbFile <= 1)
err = RegQueryValueA(hKeyLangid, "win64", szFile, &cbFile);

What exactly does SE_ERR_ASSOCINCOMPLETE mean?

I was unable to find any hint of the exact meaning of the SE_ERR_ASSOCINCOMPLETE ShellExecute return value.
I know that MSDN says "The file name association is incomplete or invalid", but what exactly does that mean? In what situations can it occur?
The best information on this can be found in the documentation. Which supplies the text:
The file name association is incomplete or invalid.
Which is what you've found out. To be honest it seems reasonably clear what it means, specifically that there is something wrong with the file association that has prevented the function from completing.
As to what SE_ERR_ASSOCINCOMPLETE means in full gory detail, that is an exhaustive list of all possible failure modes, you'll likely never find out. This is a deprecated function that exists solely to maintain backwards compatibility. The chances of Microsoft offering more insight into its works are vanishingly small.
The smart play here is not to call ShellExecute. Its error handling is crippled. Instead use ShellExecuteEx. When that fails, use GetLastError to get a Win32 error code.
Read more about that in Raymond Chen's article, Why does ShellExecute return SE_ERR_ACCESSDENIED for nearly everything? And then ask yourself what is the point of trying to gain a full understanding of the error codes that this function returns when most of the time you'll get SE_ERR_ACCESSDENIED.

OutputDebugString capture

In a previous question I asked about if any real-time enhanced versions of dbgview exist,
and ended trying to write my own, which worked out well except for one small snag
OpenMutex(MUTEX_ALL_ACCESS, FALSE, "DBWinMutex")
returns a handle to this mutex, except it returns NULL on windows2003 , anyone know why
this might be the case ?
The mutex doesn't necessarily exist. e.g. OutputDebugString attempts to create it, rather than open it.
Details here: http://www.unixwiz.net/techtips/outputdebugstring.html
Just in case, I faced similar permission issue when trying to use open mutex in MEX file.
This worked for me:
auto str = TEXT("MutexTest");
HANDLE h1 = OpenMutex(SYNCHRONIZE, FALSE, str);

Exaustive lists of all possible errors for various Windows API calls?

CreateFile for example. When I get INVALID_HANDLE_VALUE, what are all the possible values that can be returned by GetLastError? MSDN doesn't say. It mentions some and I can guess others, but how (if at all) can I be sure that my switch statement will never reach default?
Such a list doesn't exist and in fact you can't ever have such a list. In some future version of Windows a function may well start returning an error code that did not exist when you compiled your program.
The standard way to deal with this is handle any error codes that you know about that need special treatment, and let all others fall through to a default handler. Call FormatMessage() to get a descriptive text string for the error.

glGenBuffers is NULL giving a 0x0000000 access violation when using glew

> I have visual studio c++ express and a NVIDIA GeForce 7900 GS. I'm using glew to get at the openGL extensions. Calling glGenBuffers crashes as its a NULL pointer tho. I have an open GL context before I make the call ( wglGetCurrentContext() != NULL ). I'm calling glewInit() before the call. glewGetString( GLEW_VERSION ) is returning GLEW_VERSION_1_5. What am I doing wrong ? Is the card too old ? Is it the driver ?
Remember to make a glewInit() call in your code so that you get valid pointers to GL functions.
Hope it helps.
Without seeing your code it would be difficult to tell, but what you are attempting to do seems like it could be helped a lot by using GLee. It is designed to load all current extensions and you have the ability to check what is supported, e.g. :
#include <gl\GLee.h> // (no need to link to gl.h)
...
if (GLEE_ARB_multitexture) //is multitexture support available?
{
glMultiTexCoord2fARB(...); //safe to use multitexture
}
else
{
//fallback
}
The above was shamelessly copy/pasted from the GLee site, but it displays the functionality I'm trying to showcase.
You need to call glewInit() post having a valid context. And that would be, in the world of glew, after you've called glfwMakeContextCurrent(myWindow);
I have actually run into this problem with GLEW. For me, it was nullifying the function pointer for glGenerateMipmap. I fixed it by simply restoring the pointer to the appropriate function. This is my example in Linux:
glGenerateMipmap = (void(*)(GLenum))
glXGetProcAddressARB((GLubyte*)"glGenerateMipmap");
There is a WGL equivalent for glXGetProcAddress; I just don't remember the name off the top of my head. Try manually restoring the functions using this method. If you come across many functions that are null, something is definitely wrong in your setup process. The only other functions I recall having to restore were glGenVertexArrays, glBindVertexArray, and glDeleteVertexArrays. If your glGenBuffers is null, odds are that glBindBuffer and glDeleteBuffers are null as well. :(
Test if the desired extension is actually supported by checking the string returned by glGetString(GL_EXTENSIONS); if it's not there you know what's causing your problems.

Resources