Creating a shortcut to VPN from C++

Posted on 2009-02-15
Last Modified: 2013-12-14
I need to create a link of one of the VPN connection (I create in the same program) to the desktop. I'm using C++ console application.
Is there a simple way to do that without adding any dependencies?
Question by:michaelst
    LVL 2

    Expert Comment

    The example I'm sending was extracted from MSDN library and opens the connection dialog for any connection, including VPN.
    You just call dial( "your connection name" ).

    If you need more control over your connection you can use the class provided in the following link
    With this class you can bypass the dialog and add your own UI.


    Author Comment

    I do not need to dial. I need to create a shortcut only.
    LVL 2

    Accepted Solution

    Sorry, I didn't understand your question.
    I briefly tested this code with VS9 and it works fine.
    The createPidl() function can be used for any type of object and retrives the right idl to use to create the .lnk file.
    The CreateLink() receives the folder, the link name ( used as both display and file ) and the pidl obtained in createPidl().
    Be aware that I didn't review or extensivelly tested this code, therefore you might find some  leak or some other bug. Use this just as a guide to write your own function.
    #include "shlobj.h"
    /* ------------------------------------------------------------------------- */
    int CreateLink( int nFolder, char * linkName , LPITEMIDLIST pidlToLink )
       //Check for empty strings ...
       if(NULL == linkName || NULL == pidlToLink )
          return -1;
       //File system directory that contains the directories for the
       //common program groups that appear on the Start menu for all
       // users.
       LPITEMIDLIST pidl;
       // Get a pointer to an item ID list that represents the path
       // of a special folder
       HRESULT hr = SHGetSpecialFolderLocation(NULL, nFolder, &pidl);
       // Convert the item ID list's binary representation into a file
       // system path
       TCHAR linkPath[_MAX_PATH];
       BOOL f = SHGetPathFromIDList(pidl, linkPath);
       // Allocate a pointer to an IMalloc interface
       LPMALLOC pMalloc;
       // Get the address of our task allocator's IMalloc interface
       hr = SHGetMalloc(&pMalloc);
       // Free the item ID list allocated by SHGetSpecialFolderLocation
       // Free our task allocator
       char linkFile[_MAX_PATH];
       sprintf_s( linkFile, sizeof( linkFile ) ,  "%s\\%s.lnk", linkPath, linkName );
        HRESULT hres = NULL;
        IShellLink* psl = NULL;
        // Get a pointer to the IShellLink interface.
        hres = CoCreateInstance(CLSID_ShellLink, NULL,
            CLSCTX_INPROC_SERVER, IID_IShellLink,
        if (SUCCEEDED(hres))
            IPersistFile* ppf = NULL;
            // Set the path to the shortcut target
            psl->SetIDList( pidlToLink );
            // Query IShellLink for the IPersistFile interface for
            // saving the shortcut in persistent storage.
            hres = psl->QueryInterface(IID_IPersistFile,
            if (SUCCEEDED(hres))
                WCHAR wsz[MAX_PATH];
                // Ensure that the string is ANSI.
                MultiByteToWideChar(CP_ACP, 0, linkFile, -1,
                    wsz, MAX_PATH);
                // Save the link by calling IPersistFile::Save.
                hres = ppf->Save(wsz, TRUE);
        return 0;
    /* ------------------------------------------------------------------------- */
    LPITEMIDLIST createPidl( int nFolder, char *name )
        LPITEMIDLIST pidlParent=NULL;
        LPITEMIDLIST pidlChild=NULL;
        LPITEMIDLIST pidlResult = NULL;
        LPSHELLFOLDER lpsfDesktop=NULL;
            goto CLEANUP;
        if (FAILED(SHGetSpecialFolderLocation(NULL, nFolder, &pidlParent) ) )
           goto CLEANUP;
        if ( FAILED( lpsfDesktop->BindToObject(pidlParent,NULL,IID_IShellFolder,(LPVOID*)&lpsf) ) )
            goto CLEANUP;
        IEnumIDList *lpei;
        if ( SUCCEEDED(lpsf->EnumObjects( NULL, 
                                          SHCONTF_NONFOLDERS | 
                                          SHCONTF_INCLUDEHIDDEN , 
                                          &lpei ) ) )
            while ( S_OK == lpei->Next(1 , &pidlChild , NULL ) )
                STRRET result;
                memset( &result , 0 , sizeof( result ) );
                if ( S_OK == lpsf->GetDisplayNameOf( pidlChild , 
                                                     &result ) )
                    char resultmb[1024];
                    if ( result.uType&STRRET_CSTR)
                        strcpy_s( resultmb, sizeof( resultmb ) , result.cStr );
                        WideCharToMultiByte(  CP_ACP, 
                                              resultmb , sizeof(resultmb), NULL, NULL );
                        CoTaskMemFree( result.pOleStr );
                    if ( 0 == _stricmp( name , resultmb ) )
                        pidlResult = ILCombine( pidlParent , pidlChild );
        if ( lpsfDesktop )
        if ( lpsf )
        ILFree( pidlParent );
        ILFree( pidlChild );
       return pidlResult;
    /* ------------------------------------------------------------------------- */
    int _tmain(int argc, _TCHAR* argv[])
        LPITEMIDLIST pidlConn = createPidl( CSIDL_CONNECTIONS, "your connection name here");
        CreateLink( CSIDL_DESKTOP , "test" ,  pidlConn );
        ILFree( pidlConn );
    	return 0;

    Open in new window


    Author Comment

    The code works with one problem - "linkPath" is a WCHAR. After I realized that everything is fine.
    LVL 2

    Expert Comment

    If you compile using multi byte chars instead of unicode it will work fine. I tested it before sending ( I did just one test but it worked fine ).
    Note that TCHAR resolves to wchar_t if you use unicode and to char if you use multi byte.
    But it was my bad anyways as I should have written the code using tprintf and the respective macros to cope with the consts.
    As I said before this was just an example to understand the API's involved.

    Author Comment

    No worries, I needed an example  how it works.So, thank you for you help.

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Enabling OSINT in Activity Based Intelligence

    Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

    zlib is a free compression library (a DLL) on which the popular gzip utility is built.  In this article, we'll see how to use the zlib functions to compress and decompress data in memory; that is, without needing to use a temporary file.  We'll be c…
    As more and more people are shifting to the latest .Net frameworks, the windows presentation framework is gaining importance by the day. Many people are now turning to WPF controls to provide a rich user experience. I have been using WPF controls fo…
    The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
    This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA.…

    759 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    12 Experts available now in Live!

    Get 1:1 Help Now