Thread: IShellLink GetPath and Dev-C++...

  1. #1
    Registered User
    Join Date
    Feb 2005
    Posts
    11

    IShellLink GetPath and Dev-C++...

    The best match to a search for finding a shortcut's target is http://cboard.cprogramming.com/showthread.php?t=61943.

    But using Dev-C++ (4.9.9.2), I get several errors when using GetPath, here is the function...

    Code:
    char* getLinkTarget(char *sLink) {
          WIN32_FIND_DATA wfs;
    
          GetPath(sLink, MAX_PATH, &wfs, SLGP_RAWPATH);
          MessageBox(hWnd, wfs.cFileName, "GetPath", 0);
          return "";
    }
    Dev-C++ gives me the following errors...
    Code:
    [Warning] passing arg 1 of `GetPath' from incompatible pointer type
    [Warning] passing arg 2 of `GetPath' makes pointer from integer without a cast
    [Warning] passing arg 3 of `GetPath' from incompatible pointer type
    I program through trial and error (because my only learning path for C is the internet and C for Dummies). I've tried several types of typecasting with no real change. I also can't find any examples for c (other than that post which I copied and pasted to try and get to work, which it didn't.

    Any and all help is appreciated.

  2. #2
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Are you trying to call IShellLink::GetPath? If so, it needs to be called on a valid IShellLink object. The code in the linked thread is for C++ and will not compile in C. When faced with C++ code and you are using C, you have two choices.

    The first is to leave the code as C++ and include it in your project as a seperate .cpp file. You will have to prepend the C++ function definitions with extern "C" so that they can be called from C code:
    Code:
    extern "C" BOOL GetShortcutTarget(LPCTSTR szShortcutFile, LPTSTR szTarget, SIZE_T cchTarget)
    {
       ...
    Then you will have to create a prototype at the top of your C file:
    Code:
    BOOL GetShortcutTarget(LPCTSTR szShortcutFile, LPTSTR szTarget, SIZE_T cchTarget);
    With this done, you should be able to call the C++ functions from your .c files.

    The other option, which usually involves more work, is to convert the code from C++ to C. Here is the GetShortcutTarget function converted to C:
    Code:
    #include <windows.h>
    #include <objidl.h>   /* For IPersistFile */
    #include <shlobj.h>   /* For IShellLink */
    
    #if defined(_MSC_VER)
    #pragma comment(lib, "ole32.lib")
    #pragma comment(lib, "uuid.lib")
    #endif
    
    
    /*
     * GetShortcutTarget
     * Retrieves the path that a shortcut file points to.
     *
     * Paramaters:
     *    szShortcutFile    The path to the shortcut file.
     *    szTarget          Pointer to a buffer that will receive the target path.
     *                      The buffer length should be at least MAX_PATH characters.
     *    cchTarget         The size of the szTarget buffer, in characters.
     *
     * Return:
     *    A non-zero value is returned on success. If the function fails zero
     *    will be returned. GetLastError can NOT be called to get an additional error code.
     *
     * Runtime requirements:
     *    CoInitialize or CoInitializeEx must have been called before using this function.
     *
     * Compile requirements:
     *    C. Include <windows.h>, <objidl.h> & <shlobj.h>. Link "uuid.lib".
     */
    BOOL GetShortcutTarget(LPCTSTR szShortcutFile, LPTSTR szTarget, SIZE_T cchTarget)
    {
        IShellLink*    psl     = NULL;
        IPersistFile*  ppf     = NULL;
        BOOL           bResult = FALSE;
    
    #   if !defined(UNICODE)
            WCHAR wsz[MAX_PATH];
            if (0 == MultiByteToWideChar(CP_ACP, 0, szShortcutFile, -1, wsz, MAX_PATH) )
                goto cleanup;
    #   else
            LPCWSTR wsz = szShortcutFile;
    #   endif
    
        if (FAILED( CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void **) &psl) ))
            goto cleanup;
    
        if (FAILED( psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (void **) &ppf) ))
            goto cleanup;
    
        if (FAILED( ppf->lpVtbl->Load(ppf, wsz, STGM_READ) ))
            goto cleanup;
    
        if (NOERROR != psl->lpVtbl->GetPath(psl, szTarget, cchTarget, NULL, 0) )
            goto cleanup;
    
        bResult = TRUE;
    
    cleanup:
        if (ppf) ppf->lpVtbl->Release(ppf);
        if (psl) psl->lpVtbl->Release(psl);
        if (!bResult && cchTarget != 0) szTarget[0] = TEXT('\0');
        return bResult;
    }
    
    
    #if 1 /* Test code. */
    #include <stdio.h>
    #include <tchar.h>
    
    int main(void)
    {
        TCHAR szTarget[MAX_PATH];
    
        CoInitialize(NULL);
    
        GetShortcutTarget(
         TEXT("C:\\Documents and Settings\\All Users\\Start Menu\\")
         TEXT("Programs\\Accessories\\Calculator.lnk"),
             szTarget, MAX_PATH);
    
        _tprintf(TEXT("The shortcut target is '%s'.\n"), szTarget);
    
        CoUninitialize();
        getchar();
        return 0;
    }
    #endif
    To compile this with Dev-C++, add -luuid -lole32 to the Linker box under Project->Project Options->Parameters tab.

  3. #3
    Registered User
    Join Date
    Feb 2005
    Posts
    11

    Woo Hoo!

    I used the function and it works great! I very much appreciate the assistance. Thanks!

    I tried to give you some more reputation but since you helped me with my last problem I can't give it anymore, hopefully some verbal praise will suffice, great work!

Popular pages Recent additions subscribe to a feed