Ejemplo n.º 1
0
/* Updates jumplist from registry. */
static void update_jumplist_from_registry(void)
{
    const char *piterator;
    UINT num_items;
    int jumplist_counter;
    UINT nremoved;

    /* Variables used by the cleanup code must be initialised to NULL,
     * so that we don't try to free or release them if they were never
     * set up. */
    ICustomDestinationList *pCDL = NULL;
    char *pjumplist_reg_entries = NULL;
    IObjectCollection *collection = NULL;
    IObjectArray *array = NULL;
    IShellLink *link = NULL;
    IObjectArray *pRemoved = NULL;
    bool need_abort = false;

    /*
     * Create an ICustomDestinationList: the top-level object which
     * deals with jump list management.
     */
    if (!SUCCEEDED(CoCreateInstance(&CLSID_DestinationList, NULL,
                                    CLSCTX_INPROC_SERVER,
                                    COMPTR(ICustomDestinationList, &pCDL))))
        goto cleanup;

    /*
     * Call its BeginList method to start compiling a list. This gives
     * us back 'num_items' (a hint derived from systemwide
     * configuration about how many things to put on the list) and
     * 'pRemoved' (user configuration about things to leave off the
     * list).
     */
    if (!SUCCEEDED(pCDL->lpVtbl->BeginList(pCDL, &num_items,
                                           COMPTR(IObjectArray, &pRemoved))))
        goto cleanup;
    need_abort = true;
    if (!SUCCEEDED(pRemoved->lpVtbl->GetCount(pRemoved, &nremoved)))
        nremoved = 0;

    /*
     * Create an object collection to form the 'Recent Sessions'
     * category on the jump list.
     */
    if (!SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection,
                                    NULL, CLSCTX_INPROC_SERVER,
                                    COMPTR(IObjectCollection, &collection))))
        goto cleanup;

    /*
     * Go through the jump list entries from the registry and add each
     * one to the collection.
     */
    pjumplist_reg_entries = get_jumplist_registry_entries();
    piterator = pjumplist_reg_entries;
    jumplist_counter = 0;
    while (*piterator != '\0' &&
           (jumplist_counter < min(MAX_JUMPLIST_ITEMS, (int) num_items))) {
        link = make_shell_link(NULL, piterator);
        if (link) {
            UINT i;
            bool found;

            /*
             * Check that the link isn't in the user-removed list.
             */
            for (i = 0, found = false; i < nremoved && !found; i++) {
                IShellLink *rlink;
                if (SUCCEEDED(pRemoved->lpVtbl->GetAt
                              (pRemoved, i, COMPTR(IShellLink, &rlink)))) {
                    char desc1[2048], desc2[2048];
                    if (SUCCEEDED(link->lpVtbl->GetDescription
                                  (link, desc1, sizeof(desc1)-1)) &&
                        SUCCEEDED(rlink->lpVtbl->GetDescription
                                  (rlink, desc2, sizeof(desc2)-1)) &&
                        !strcmp(desc1, desc2)) {
                        found = true;
                    }
                    rlink->lpVtbl->Release(rlink);
                }
            }

            if (!found) {
                collection->lpVtbl->AddObject(collection, link);
                jumplist_counter++;
            }

            link->lpVtbl->Release(link);
            link = NULL;
        }
        piterator += strlen(piterator) + 1;
    }
    sfree(pjumplist_reg_entries);
    pjumplist_reg_entries = NULL;

    /*
     * Get the array form of the collection we've just constructed,
     * and put it in the jump list.
     */
    if (!SUCCEEDED(collection->lpVtbl->QueryInterface
                   (collection, COMPTR(IObjectArray, &array))))
        goto cleanup;

    pCDL->lpVtbl->AppendCategory(pCDL, L"Recent Sessions", array);

    /*
     * Create an object collection to form the 'Tasks' category on the
     * jump list.
     */
    if (!SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection,
                                    NULL, CLSCTX_INPROC_SERVER,
                                    COMPTR(IObjectCollection, &collection))))
        goto cleanup;

    /*
     * Add task entries for PuTTYgen and Pageant.
     */
    piterator = "Pageant.exe\0PuTTYgen.exe\0\0";
    while (*piterator != '\0') {
        link = make_shell_link(piterator, NULL);
        if (link) {
            collection->lpVtbl->AddObject(collection, link);
            link->lpVtbl->Release(link);
            link = NULL;
        }
        piterator += strlen(piterator) + 1;
    }

    /*
     * Get the array form of the collection we've just constructed,
     * and put it in the jump list.
     */
    if (!SUCCEEDED(collection->lpVtbl->QueryInterface
                   (collection, COMPTR(IObjectArray, &array))))
        goto cleanup;

    pCDL->lpVtbl->AddUserTasks(pCDL, array);

    /*
     * Now we can clean up the array and collection variables, so as
     * to be able to reuse them.
     */
    array->lpVtbl->Release(array);
    array = NULL;
    collection->lpVtbl->Release(collection);
    collection = NULL;

    /*
     * Create another object collection to form the user tasks
     * category.
     */
    if (!SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection,
                                    NULL, CLSCTX_INPROC_SERVER,
                                    COMPTR(IObjectCollection, &collection))))
        goto cleanup;

    /*
     * Get the array form of the collection we've just constructed,
     * and put it in the jump list.
     */
    if (!SUCCEEDED(collection->lpVtbl->QueryInterface
                   (collection, COMPTR(IObjectArray, &array))))
        goto cleanup;

    pCDL->lpVtbl->AddUserTasks(pCDL, array);

    /*
     * Now we can clean up the array and collection variables, so as
     * to be able to reuse them.
     */
    array->lpVtbl->Release(array);
    array = NULL;
    collection->lpVtbl->Release(collection);
    collection = NULL;

    /*
     * Commit the jump list.
     */
    pCDL->lpVtbl->CommitList(pCDL);
    need_abort = false;

    /*
     * Clean up.
     */
  cleanup:
    if (pRemoved) pRemoved->lpVtbl->Release(pRemoved);
    if (pCDL && need_abort) pCDL->lpVtbl->AbortList(pCDL);
    if (pCDL) pCDL->lpVtbl->Release(pCDL);
    if (collection) collection->lpVtbl->Release(collection);
    if (array) array->lpVtbl->Release(array);
    if (link) link->lpVtbl->Release(link);
    sfree(pjumplist_reg_entries);
}
Ejemplo n.º 2
0
/* Updates jumplist from registry. */
void update_jumplist_from_registry (void)
{
    ICustomDestinationList *pCDL;                        /* ICustomDestinationList is the COM Object used to create application jumplists. */
    char *pjumplist_reg_entries, *piterator;              
    char *param_string, *desc_string;                     
    IPropertyStore *pPS;
    PROPVARIANT pv;
    IObjectCollection *pjumplist_items;                  
    IObjectArray *pjumplist_items_as_array;
    IShellLink *pSL[MAX_JUMPLIST_ITEMS], *pcurrent_link; 
    IObjectArray *pRemoved;                              /* Items removed by user from jump list. These may not be re-added. We don't use this, because IShellLink
                                                               items can't be removed from the jumplist, only pinned. */
    UINT num_items;
    int jumplist_counter;
    HKEY psettings_tmp;
    char b[2048], *p, *q, *r, *putty_path;
    

    /* Retrieve path to Putty executable. */
    GetModuleFileName(NULL, b, sizeof(b) - 1);
    r = b;
    p = strrchr(b, '\\');
    if (p && p >= r) r = p+1;
    q = strrchr(b, ':');
    if (q && q >= r) r = q+1;
    strcpy(r, "putty.exe");
    putty_path = dupstr(b);

    pjumplist_reg_entries = get_jumplist_registry_entries();
    
    if (CoCreateInstance(&CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, &IID_ICustomDestinationList, &pCDL) == S_OK) {        
        
        if (SUCCEEDED(pCDL->lpVtbl->BeginList(pCDL, &num_items, &IID_IObjectArray, &pRemoved))) {
          
            if (SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, &IID_IObjectCollection, &pjumplist_items))) {
	            
                /* Walk through the jumplist entries from the registry and add them to the new jumplist. */ 
                piterator = pjumplist_reg_entries;
                jumplist_counter = 0;
                while (*piterator != '\0' && (jumplist_counter < min(MAX_JUMPLIST_ITEMS,(int) num_items)) )
                {
                   /* Check if this is a valid session, otherwise don't add. */
                   psettings_tmp = open_settings_r(piterator);
                   if (psettings_tmp != NULL )
                   {
                       close_settings_r(psettings_tmp);
                         
                       /* Create and add the new item to the list. */
                       if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, &(pSL[jumplist_counter]) ))) {

                            pcurrent_link = pSL[jumplist_counter];
                            /* Set path, parameters, icon and description. */
                            pcurrent_link->lpVtbl->SetPath(pcurrent_link, putty_path);

                            param_string = snewn(7 + strlen(piterator) + 1 + 1, char);
                            strcpy(param_string, "-load \"");
                            strcat(param_string, piterator);
                            strcat(param_string, "\"");
                            pcurrent_link->lpVtbl->SetArguments(pcurrent_link, param_string);
                            sfree(param_string);

                            desc_string = snewn(20 + strlen(piterator) + 1 + 1, char);
                            strcpy(desc_string, "Connect to session '");
                            strcat(desc_string, piterator);
                            strcat(desc_string, "'");
                            pcurrent_link->lpVtbl->SetDescription(pcurrent_link, desc_string);
                            sfree(desc_string);

                            pcurrent_link->lpVtbl->SetIconLocation(pcurrent_link, putty_path, 0);

                            /* To set the link title, we require the property store of the link. */
                            if (SUCCEEDED(pcurrent_link->lpVtbl->QueryInterface(pcurrent_link, &IID_IPropertyStore, &pPS))) {                    
                                PropVariantInit(&pv);
                                pv.vt = VT_LPSTR;
                                pv.pszVal = dupstr(piterator);
                                pPS->lpVtbl->SetValue(pPS, &PKEY_Title, &pv);
                                sfree(pv.pszVal);
                                pPS->lpVtbl->Commit(pPS);

                                /* Add link to jumplist. */
                                pjumplist_items->lpVtbl->AddObject(pjumplist_items, pcurrent_link);		
                       
	                            pPS->lpVtbl->Release(pPS);
                            }
                            
                            ++jumplist_counter;
                        }            
                    }
                    
                    piterator += strlen(piterator) + 1;
                }
                
                /* Now commit the jumplist. */
                if (SUCCEEDED( pjumplist_items->lpVtbl->QueryInterface(pjumplist_items, &IID_IObjectArray, &pjumplist_items_as_array) )) {
                    pCDL->lpVtbl->AppendCategory(pCDL, L"Recent Sessions", pjumplist_items_as_array);
                    pCDL->lpVtbl->CommitList(pCDL);
                    pjumplist_items_as_array->lpVtbl->Release(pjumplist_items_as_array);
                }

                /* Release COM objects used for the Shell links. */
                --jumplist_counter;
                while (jumplist_counter >= 0)
                {
                    pSL[jumplist_counter]->lpVtbl->Release(pSL[jumplist_counter]);
                    --jumplist_counter;
                }
                
                pjumplist_items->lpVtbl->Release(pjumplist_items);
            }