v77 v77 - 1 month ago 8
C Question

Using IShellLink bloats my executable to 20KB

Since a lot of time, I was using a function to create links in Windows. The source is in pure C:

void CreateLink(TCHAR *PathObj, TCHAR *PathLink, TCHAR *ArgV)
{
IShellLink *psl;
IPersistFile *ppf;

if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void**)&psl))) {
psl->lpVtbl->SetPath(psl, PathObj);
psl->lpVtbl->SetArguments(psl, ArgV);
if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (void**)&ppf))) {
ppf->lpVtbl->Save(ppf, PathLink, TRUE);
ppf->lpVtbl->Release(ppf);
}
psl->lpVtbl->Release(psl);
}
}


This function works perfectly, but I noticed that with MinGW 4.7.4, my executable was about 10KB bigger only because of this function.
I now have updated MinGW to the 5.3.0 version, and now this function increases the size of the executable by about 20KB.
Code is optimized for size (-Os) and symbols are stripped. In fact, this bloat is caused by the linker when it resolves "IID_IShellLink".

So, my question is: is there a way to avoid such a bloat?

v77 v77
Answer

Finally, I found how to solve this issue. We just have to define the GUIDs directly in the function. With that, the linker does no longer ask for the uuid library, the executable is as small as possible, and it works perfectly.
Both GUIDs can be found in objidl.h (MinGW 6.2.0).

void CreateLink(TCHAR *PathObj, TCHAR *PathLink, TCHAR *ArgV)
{
    GUID IID_IShellLinkW = {0x000214f9, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
    GUID IID_IPersistFile = {0x0000010b, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
    IShellLink *psl;
    IPersistFile *ppf;

    if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (void**)&psl))) {
        psl->lpVtbl->SetPath(psl, PathObj);
        psl->lpVtbl->SetArguments(psl, ArgV);
        if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (void**)&ppf))) {
            ppf->lpVtbl->Save(ppf, PathLink, TRUE);
            ppf->lpVtbl->Release(ppf);
        }
        psl->lpVtbl->Release(psl);
    }
}

This does not explain the meaning of the data included by the linker, but at least this answers the question.

Comments