Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /branches/ttcomtester/teraterm/teraterm/winjump.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10521 - (hide annotations) (download) (as text)
Fri Jan 20 16:03:38 2023 UTC (14 months, 2 weeks ago) by zmatsuo
File MIME type: text/x-csrc
File size: 24663 byte(s)
add communication test tool
1 yutakapon 4385 // based on PuTTY source code
2     /*
3     * winjump.c: support for Windows 7 jump lists.
4     *
5     * The Windows 7 jumplist is a customizable list defined by the
6     * application. It is persistent across application restarts: the OS
7     * maintains the list when the app is not running. The list is shown
8     * when the user right-clicks on the taskbar button of a running app
9     * or a pinned non-running application. We use the jumplist to
10     * maintain a list of recently started saved sessions, started either
11     * by doubleclicking on a saved session, or with the command line
12     * "-load" parameter.
13     *
14     * Since the jumplist is write-only: it can only be replaced and the
15     * current list cannot be read, we must maintain the contents of the
16     * list persistantly in the registry. The file winstore.h contains
17     * functions to directly manipulate these registry entries. This file
18     * contains higher level functions to manipulate the jumplist.
19     */
20    
21 doda 6806 /*
22 nmaya 9048 * Copyright (C) 2011- TeraTerm Project
23 doda 6806 * All rights reserved.
24     *
25 doda 6841 * Redistribution and use in source and binary forms, with or without
26     * modification, are permitted provided that the following conditions
27     * are met:
28 doda 6806 *
29 doda 6841 * 1. Redistributions of source code must retain the above copyright
30     * notice, this list of conditions and the following disclaimer.
31     * 2. Redistributions in binary form must reproduce the above copyright
32     * notice, this list of conditions and the following disclaimer in the
33     * documentation and/or other materials provided with the distribution.
34     * 3. The name of the author may not be used to endorse or promote products
35     * derived from this software without specific prior written permission.
36 doda 6806 *
37 doda 6841 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
38     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
40     * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
41     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
46     * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 doda 6806 */
48    
49 yutakapon 4385 #include <windows.h>
50     #include <assert.h>
51     #include <stdio.h>
52 doda 4506 #include <string.h>
53     #include <shlobj.h>
54 zmatsuo 8391 #if !defined(_CRTDBG_MAP_ALLOC)
55     #define _CRTDBG_MAP_ALLOC
56     #endif
57     #include <stdlib.h>
58 zmatsuo 7536 #include <crtdbg.h>
59 zmatsuo 9230 #if defined(__MINGW32__) || defined(_INC_SDKDDKVER)
60     #define HAS_PROPKEY_H 1
61     #endif
62     #if defined(HAS_PROPKEY_H)
63     #include <propkey.h>
64     #endif
65 yutakapon 4385
66     #include "winjump.h"
67     #include "teraterm.h"
68     #include "tttypes.h"
69    
70     #define MAX_JUMPLIST_ITEMS 30 /* PuTTY will never show more items in
71     * the jumplist than this, regardless of
72     * user preferences. */
73    
74     /*
75     * COM structures and functions.
76     */
77     #ifndef PROPERTYKEY_DEFINED
78     #define PROPERTYKEY_DEFINED
79     typedef struct _tagpropertykey {
80     GUID fmtid;
81     DWORD pid;
82     } PROPERTYKEY;
83     #endif
84     #ifndef _REFPROPVARIANT_DEFINED
85     #define _REFPROPVARIANT_DEFINED
86     typedef PROPVARIANT *REFPROPVARIANT;
87     #endif
88    
89 doda 6519 #ifndef __ICustomDestinationList_INTERFACE_DEFINED__
90 zmatsuo 9230
91     static const IID IID_ICustomDestinationList = {
92     0x6332debf, 0x87b5, 0x4670, {0x90,0xc0,0x5e,0x57,0xb4,0x08,0xa4,0x9e}
93     };
94    
95 yutakapon 4385 typedef struct ICustomDestinationListVtbl {
96     HRESULT ( __stdcall *QueryInterface ) (
97     /* [in] ICustomDestinationList*/ void *This,
98     /* [in] */ const GUID * const riid,
99     /* [out] */ void **ppvObject);
100    
101     ULONG ( __stdcall *AddRef )(
102     /* [in] ICustomDestinationList*/ void *This);
103    
104     ULONG ( __stdcall *Release )(
105     /* [in] ICustomDestinationList*/ void *This);
106    
107     HRESULT ( __stdcall *SetAppID )(
108     /* [in] ICustomDestinationList*/ void *This,
109     /* [string][in] */ LPCWSTR pszAppID);
110    
111     HRESULT ( __stdcall *BeginList )(
112     /* [in] ICustomDestinationList*/ void *This,
113     /* [out] */ UINT *pcMinSlots,
114     /* [in] */ const GUID * const riid,
115     /* [out] */ void **ppv);
116    
117     HRESULT ( __stdcall *AppendCategory )(
118     /* [in] ICustomDestinationList*/ void *This,
119     /* [string][in] */ LPCWSTR pszCategory,
120     /* [in] IObjectArray*/ void *poa);
121    
122     HRESULT ( __stdcall *AppendKnownCategory )(
123     /* [in] ICustomDestinationList*/ void *This,
124     /* [in] KNOWNDESTCATEGORY*/ int category);
125    
126     HRESULT ( __stdcall *AddUserTasks )(
127     /* [in] ICustomDestinationList*/ void *This,
128     /* [in] IObjectArray*/ void *poa);
129    
130     HRESULT ( __stdcall *CommitList )(
131     /* [in] ICustomDestinationList*/ void *This);
132    
133     HRESULT ( __stdcall *GetRemovedDestinations )(
134     /* [in] ICustomDestinationList*/ void *This,
135     /* [in] */ const IID * const riid,
136     /* [out] */ void **ppv);
137    
138     HRESULT ( __stdcall *DeleteList )(
139     /* [in] ICustomDestinationList*/ void *This,
140     /* [string][unique][in] */ LPCWSTR pszAppID);
141    
142     HRESULT ( __stdcall *AbortList )(
143     /* [in] ICustomDestinationList*/ void *This);
144    
145     } ICustomDestinationListVtbl;
146    
147     typedef struct ICustomDestinationList
148     {
149     ICustomDestinationListVtbl *lpVtbl;
150     } ICustomDestinationList;
151 doda 6519 #endif
152 yutakapon 4385
153 doda 6519 #ifndef __IObjectArray_INTERFACE_DEFINED__
154 zmatsuo 9230
155     static const IID IID_IObjectArray = {
156     0x92ca9dcd, 0x5622, 0x4bba, {0xa8,0x05,0x5e,0x9f,0x54,0x1b,0xd8,0xc9}
157     };
158    
159 yutakapon 4385 typedef struct IObjectArrayVtbl
160     {
161     HRESULT ( __stdcall *QueryInterface )(
162     /* [in] IObjectArray*/ void *This,
163     /* [in] */ const GUID * const riid,
164     /* [out] */ void **ppvObject);
165    
166     ULONG ( __stdcall *AddRef )(
167     /* [in] IObjectArray*/ void *This);
168    
169     ULONG ( __stdcall *Release )(
170     /* [in] IObjectArray*/ void *This);
171    
172     HRESULT ( __stdcall *GetCount )(
173     /* [in] IObjectArray*/ void *This,
174     /* [out] */ UINT *pcObjects);
175    
176     HRESULT ( __stdcall *GetAt )(
177     /* [in] IObjectArray*/ void *This,
178     /* [in] */ UINT uiIndex,
179     /* [in] */ const GUID * const riid,
180     /* [out] */ void **ppv);
181    
182     } IObjectArrayVtbl;
183    
184     typedef struct IObjectArray
185     {
186     IObjectArrayVtbl *lpVtbl;
187     } IObjectArray;
188 doda 6519 #endif
189 yutakapon 4385
190 doda 6519 #ifndef __IShellLink_INTERFACE_DEFINED__
191     #define __IShellLink_INTERFACE_DEFINED__
192 yutakapon 4385 typedef struct IShellLinkVtbl
193     {
194     HRESULT ( __stdcall *QueryInterface )(
195     /* [in] IShellLink*/ void *This,
196     /* [in] */ const GUID * const riid,
197     /* [out] */ void **ppvObject);
198    
199     ULONG ( __stdcall *AddRef )(
200     /* [in] IShellLink*/ void *This);
201    
202     ULONG ( __stdcall *Release )(
203     /* [in] IShellLink*/ void *This);
204    
205     HRESULT ( __stdcall *GetPath )(
206     /* [in] IShellLink*/ void *This,
207     /* [string][out] */ LPSTR pszFile,
208     /* [in] */ int cch,
209     /* [unique][out][in] */ WIN32_FIND_DATAA *pfd,
210     /* [in] */ DWORD fFlags);
211    
212     HRESULT ( __stdcall *GetIDList )(
213     /* [in] IShellLink*/ void *This,
214     /* [out] LPITEMIDLIST*/ void **ppidl);
215    
216     HRESULT ( __stdcall *SetIDList )(
217     /* [in] IShellLink*/ void *This,
218     /* [in] LPITEMIDLIST*/ void *pidl);
219    
220     HRESULT ( __stdcall *GetDescription )(
221     /* [in] IShellLink*/ void *This,
222     /* [string][out] */ LPSTR pszName,
223     /* [in] */ int cch);
224    
225     HRESULT ( __stdcall *SetDescription )(
226     /* [in] IShellLink*/ void *This,
227     /* [string][in] */ LPCSTR pszName);
228    
229     HRESULT ( __stdcall *GetWorkingDirectory )(
230     /* [in] IShellLink*/ void *This,
231     /* [string][out] */ LPSTR pszDir,
232     /* [in] */ int cch);
233    
234     HRESULT ( __stdcall *SetWorkingDirectory )(
235     /* [in] IShellLink*/ void *This,
236     /* [string][in] */ LPCSTR pszDir);
237    
238     HRESULT ( __stdcall *GetArguments )(
239     /* [in] IShellLink*/ void *This,
240     /* [string][out] */ LPSTR pszArgs,
241     /* [in] */ int cch);
242    
243     HRESULT ( __stdcall *SetArguments )(
244     /* [in] IShellLink*/ void *This,
245     /* [string][in] */ LPCSTR pszArgs);
246    
247     HRESULT ( __stdcall *GetHotkey )(
248     /* [in] IShellLink*/ void *This,
249     /* [out] */ WORD *pwHotkey);
250    
251     HRESULT ( __stdcall *SetHotkey )(
252     /* [in] IShellLink*/ void *This,
253     /* [in] */ WORD wHotkey);
254    
255     HRESULT ( __stdcall *GetShowCmd )(
256     /* [in] IShellLink*/ void *This,
257     /* [out] */ int *piShowCmd);
258    
259     HRESULT ( __stdcall *SetShowCmd )(
260     /* [in] IShellLink*/ void *This,
261     /* [in] */ int iShowCmd);
262    
263     HRESULT ( __stdcall *GetIconLocation )(
264     /* [in] IShellLink*/ void *This,
265     /* [string][out] */ LPSTR pszIconPath,
266     /* [in] */ int cch,
267     /* [out] */ int *piIcon);
268    
269     HRESULT ( __stdcall *SetIconLocation )(
270     /* [in] IShellLink*/ void *This,
271     /* [string][in] */ LPCSTR pszIconPath,
272     /* [in] */ int iIcon);
273    
274     HRESULT ( __stdcall *SetRelativePath )(
275     /* [in] IShellLink*/ void *This,
276     /* [string][in] */ LPCSTR pszPathRel,
277     /* [in] */ DWORD dwReserved);
278    
279     HRESULT ( __stdcall *Resolve )(
280     /* [in] IShellLink*/ void *This,
281     /* [unique][in] */ HWND hwnd,
282     /* [in] */ DWORD fFlags);
283    
284     HRESULT ( __stdcall *SetPath )(
285     /* [in] IShellLink*/ void *This,
286     /* [string][in] */ LPCSTR pszFile);
287    
288     } IShellLinkVtbl;
289 doda 6519 #endif
290 yutakapon 4385
291 doda 6519 #ifndef __IObjectCollection_INTERFACE_DEFINED__
292     #define __IObjectCollection_INTERFACE_DEFINED__
293 yutakapon 4385 typedef struct IObjectCollectionVtbl
294     {
295     HRESULT ( __stdcall *QueryInterface )(
296     /* [in] IShellLink*/ void *This,
297     /* [in] */ const GUID * const riid,
298     /* [out] */ void **ppvObject);
299    
300     ULONG ( __stdcall *AddRef )(
301     /* [in] IShellLink*/ void *This);
302    
303     ULONG ( __stdcall *Release )(
304     /* [in] IShellLink*/ void *This);
305    
306     HRESULT ( __stdcall *GetCount )(
307     /* [in] IShellLink*/ void *This,
308     /* [out] */ UINT *pcObjects);
309    
310     HRESULT ( __stdcall *GetAt )(
311     /* [in] IShellLink*/ void *This,
312     /* [in] */ UINT uiIndex,
313     /* [in] */ const GUID * const riid,
314     /* [iid_is][out] */ void **ppv);
315    
316     HRESULT ( __stdcall *AddObject )(
317     /* [in] IShellLink*/ void *This,
318     /* [in] */ void *punk);
319    
320     HRESULT ( __stdcall *AddFromArray )(
321     /* [in] IShellLink*/ void *This,
322     /* [in] */ IObjectArray *poaSource);
323    
324     HRESULT ( __stdcall *RemoveObjectAt )(
325     /* [in] IShellLink*/ void *This,
326     /* [in] */ UINT uiIndex);
327    
328     HRESULT ( __stdcall *Clear )(
329     /* [in] IShellLink*/ void *This);
330    
331     } IObjectCollectionVtbl;
332    
333     typedef struct IObjectCollection
334     {
335     IObjectCollectionVtbl *lpVtbl;
336     } IObjectCollection;
337 yutakapon 4724 #endif
338 yutakapon 4385
339 doda 6519 #ifndef __IPropertyStore_INTERFACE_DEFINED__
340 zmatsuo 9230
341     static const IID IID_IPropertyStore = {
342     0x886d8eeb, 0x8cf2, 0x4446, {0x8d,0x02,0xcd,0xba,0x1d,0xbd,0xcf,0x99}
343     };
344    
345 yutakapon 4385 typedef struct IPropertyStoreVtbl
346     {
347     HRESULT ( __stdcall *QueryInterface )(
348     /* [in] IPropertyStore*/ void *This,
349     /* [in] */ const GUID * const riid,
350     /* [iid_is][out] */ void **ppvObject);
351    
352     ULONG ( __stdcall *AddRef )(
353     /* [in] IPropertyStore*/ void *This);
354    
355     ULONG ( __stdcall *Release )(
356     /* [in] IPropertyStore*/ void *This);
357    
358     HRESULT ( __stdcall *GetCount )(
359     /* [in] IPropertyStore*/ void *This,
360     /* [out] */ DWORD *cProps);
361    
362     HRESULT ( __stdcall *GetAt )(
363     /* [in] IPropertyStore*/ void *This,
364     /* [in] */ DWORD iProp,
365     /* [out] */ PROPERTYKEY *pkey);
366    
367     HRESULT ( __stdcall *GetValue )(
368     /* [in] IPropertyStore*/ void *This,
369     /* [in] */ const PROPERTYKEY * const key,
370     /* [out] */ PROPVARIANT *pv);
371    
372     HRESULT ( __stdcall *SetValue )(
373     /* [in] IPropertyStore*/ void *This,
374     /* [in] */ const PROPERTYKEY * const key,
375     /* [in] */ REFPROPVARIANT propvar);
376    
377     HRESULT ( __stdcall *Commit )(
378     /* [in] IPropertyStore*/ void *This);
379     } IPropertyStoreVtbl;
380    
381     typedef struct IPropertyStore
382     {
383     IPropertyStoreVtbl *lpVtbl;
384     } IPropertyStore;
385 yutakapon 4705 #endif
386 yutakapon 4385
387 zmatsuo 9230 #if !defined(__MINGW32__) && !defined(__ShellCoreObjects_LIBRARY_DEFINED__)
388 yutakapon 4385 static const CLSID CLSID_DestinationList = {
389     0x77f10cf0, 0x3db5, 0x4966, {0xb5,0x20,0xb7,0xc5,0x4f,0xd3,0x5e,0xd6}
390     };
391     static const CLSID CLSID_ShellLink = {
392     0x00021401, 0x0000, 0x0000, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}
393     };
394     static const CLSID CLSID_EnumerableObjectCollection = {
395     0x2d3468c1, 0x36a7, 0x43b6, {0xac,0x24,0xd3,0xf0,0x2f,0xd9,0x60,0x7a}
396     };
397     static const IID IID_IObjectCollection = {
398     0x5632b1a4, 0xe38a, 0x400a, {0x92,0x8a,0xd4,0xcd,0x63,0x23,0x02,0x95}
399     };
400     static const IID IID_IShellLink = {
401     0x000214ee, 0x0000, 0x0000, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}
402     };
403 zmatsuo 7536 #endif
404 zmatsuo 9230
405     #if !defined(HAS_PROPKEY_H)
406 yutakapon 4385 static const PROPERTYKEY PKEY_Title = {
407     {0xf29f85e0, 0x4ff9, 0x1068, {0xab,0x91,0x08,0x00,0x2b,0x27,0xb3,0xd9}},
408     0x00000002
409     };
410 zmatsuo 9230 #endif
411 yutakapon 4385
412     /* Type-checking macro to provide arguments for CoCreateInstance() etc.
413     * The pointer arithmetic is a compile-time pointer type check that 'obj'
414     * really is a 'type **', but is intended to have no effect at runtime. */
415     #define COMPTR(type, obj) &IID_##type, \
416     (void **)(void *)((obj) + (sizeof((obj)-(type **)(obj))) \
417     - (sizeof((obj)-(type **)(obj))))
418    
419 doda 4506 // LPCWSTR AppID = L"TeraTermProject.TeraTerm.ttermpro";
420 yutakapon 4385
421     static char *IniFile = NULL;
422    
423 doda 4481 BOOL isJumpListSupported(void)
424 yutakapon 4385 {
425 yutakapon 6286 return IsWindows7OrLater();
426 yutakapon 4385 }
427    
428     /*
429     * Function to make an IShellLink describing a particular PuTTY
430     * command. If 'appname' is null, the command run will be the one
431     * returned by GetModuleFileName, i.e. our own executable; if it's
432     * non-null then it will be assumed to be a filename in the same
433     * directory as our own executable, and the return value will be NULL
434     * if that file doesn't exist.
435     *
436     * If 'sessionname' is null then no command line will be passed to the
437     * program. If it's non-null, the command line will be that text
438     * prefixed with an @ (to load a PuTTY saved session).
439     *
440     * Hence, you can launch a saved session using make_shell_link(NULL,
441     * sessionname), and launch another app using e.g.
442     * make_shell_link("puttygen.exe", NULL).
443     */
444     static IShellLink *make_shell_link(const char *appname,
445     const char *sessionname)
446     {
447 yutakapon 5939 IShellLink *ret;
448     char *app_path, *param_string, *desc_string, *tmp_ptr;
449     static char tt_path[2048];
450     //void *psettings_tmp;
451     IPropertyStore *pPS;
452     PROPVARIANT pv;
453 yutakapon 5940 HRESULT result;
454 yutakapon 4385
455 yutakapon 5939 /* Retrieve path to executable. */
456     if (!tt_path[0])
457     GetModuleFileName(NULL, tt_path, sizeof(tt_path) - 1);
458 yutakapon 4385
459 yutakapon 5939 if (appname) {
460 zmatsuo 9036 size_t len;
461 yutakapon 5939 tmp_ptr = strrchr(tt_path, '\\');
462     len = (tmp_ptr - tt_path) + strlen(appname) + 2;
463     app_path = malloc(len);
464     strncpy_s(app_path, len, tt_path, (tmp_ptr - tt_path + 1));
465     strcat_s(app_path, len, appname);
466     }
467     else {
468     app_path = _strdup(tt_path);
469     }
470 yutakapon 4385
471 yutakapon 5939 /* Create the new item. */
472     if (!SUCCEEDED(CoCreateInstance(&CLSID_ShellLink, NULL,
473     CLSCTX_INPROC_SERVER,
474     COMPTR(IShellLink, &ret))))
475     return NULL;
476 yutakapon 4385
477 yutakapon 5939 /* Set path, parameters, icon and description. */
478 yutakapon 5940 result = ret->lpVtbl->SetPath(ret, app_path);
479 zmatsuo 9036 #if _DEBUG
480 yutakapon 5940 if (result != S_OK)
481     OutputDebugPrintf("SetPath failed. (%ld)\n", result);
482 zmatsuo 9036 #endif
483 yutakapon 4385
484     param_string = _strdup(sessionname);
485 yutakapon 5940 result = ret->lpVtbl->SetArguments(ret, param_string);
486 zmatsuo 9036 #if _DEBUG
487 yutakapon 5940 if (result != S_OK)
488     OutputDebugPrintf("SetArguments failed. (%ld)\n", result);
489 zmatsuo 9036 #endif
490 yutakapon 5939 free(param_string);
491 yutakapon 4385
492     desc_string = _strdup("Connect to Tera Term session");
493 yutakapon 5940 result = ret->lpVtbl->SetDescription(ret, desc_string);
494 zmatsuo 9036 #if _DEBUG
495 yutakapon 5940 if (result != S_OK)
496     OutputDebugPrintf("SetDescription failed. (%ld)\n", result);
497 zmatsuo 9036 #endif
498 yutakapon 5939 free(desc_string);
499 yutakapon 4385
500 yutakapon 5940 result = ret->lpVtbl->SetIconLocation(ret, app_path, 0);
501 zmatsuo 9036 #if _DEBUG
502 yutakapon 5940 if (result != S_OK)
503     OutputDebugPrintf("SetIconLocation failed. (%ld)\n", result);
504 zmatsuo 9036 #endif
505 yutakapon 4385
506 yutakapon 5939 /* To set the link title, we require the property store of the link. */
507     if (SUCCEEDED(ret->lpVtbl->QueryInterface(ret, COMPTR(IPropertyStore, &pPS)))) {
508     PropVariantInit(&pv);
509     pv.vt = VT_LPSTR;
510     pv.pszVal = _strdup(sessionname);
511 yutakapon 5940 result = pPS->lpVtbl->SetValue(pPS, &PKEY_Title, &pv);
512 zmatsuo 9036 #if _DEBUG
513 yutakapon 5940 if (result != S_OK)
514     OutputDebugPrintf("SetValue failed. (%ld)\n", result);
515 zmatsuo 9036 #endif
516 yutakapon 5939 free(pv.pszVal);
517 yutakapon 5940 result = pPS->lpVtbl->Commit(pPS);
518 zmatsuo 9036 #if _DEBUG
519 yutakapon 5940 if (result != S_OK)
520     OutputDebugPrintf("Commit failed. (%ld)\n", result);
521 zmatsuo 9036 #endif
522 yutakapon 5940 result = pPS->lpVtbl->Release(pPS);
523 zmatsuo 9036 #if _DEBUG
524 yutakapon 5940 if (result != S_OK)
525     OutputDebugPrintf("Release shell link failed. (%ld)\n", result);
526 zmatsuo 9036 #endif
527 yutakapon 5939 }
528 yutakapon 4385
529 doda 8429 free(app_path);
530    
531 yutakapon 5939 return ret;
532 yutakapon 4385 }
533    
534     /* Updates jumplist from registry. */
535     static void update_jumplist_from_registry(void)
536     {
537 yutakapon 5939 char EntName[128];
538     char TempHost[1024];
539 doda 4506
540 yutakapon 5939 const char *piterator = TempHost;
541     UINT num_items;
542     UINT nremoved;
543     int i;
544 yutakapon 5940 HRESULT result;
545 yutakapon 4385
546 yutakapon 5939 /* Variables used by the cleanup code must be initialised to NULL,
547     * so that we don't try to free or release them if they were never
548     * set up. */
549     ICustomDestinationList *pCDL = NULL;
550     IObjectCollection *collection = NULL;
551     IObjectArray *array = NULL;
552     IShellLink *link = NULL;
553     IObjectArray *pRemoved = NULL;
554     int need_abort = FALSE;
555 yutakapon 4385
556 yutakapon 5939 /*
557     * Create an ICustomDestinationList: the top-level object which
558     * deals with jump list management.
559     */
560     if (!SUCCEEDED(CoCreateInstance(&CLSID_DestinationList, NULL,
561     CLSCTX_INPROC_SERVER,
562     COMPTR(ICustomDestinationList, &pCDL))))
563     goto cleanup;
564 yutakapon 4385
565 yutakapon 5939 /*
566     * Call its BeginList method to start compiling a list. This gives
567     * us back 'num_items' (a hint derived from systemwide
568     * configuration about how many things to put on the list) and
569     * 'pRemoved' (user configuration about things to leave off the
570     * list).
571     */
572     if (!SUCCEEDED(pCDL->lpVtbl->BeginList(pCDL, &num_items,
573     COMPTR(IObjectArray, &pRemoved))))
574     goto cleanup;
575     need_abort = TRUE;
576     if (!SUCCEEDED(pRemoved->lpVtbl->GetCount(pRemoved, &nremoved)))
577     nremoved = 0;
578 yutakapon 4385
579 yutakapon 5939 /*
580     * Create an object collection to form the 'Recent Sessions'
581     * category on the jump list.
582     */
583     if (!SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection,
584     NULL, CLSCTX_INPROC_SERVER,
585     COMPTR(IObjectCollection, &collection))))
586     goto cleanup;
587 yutakapon 4385
588 yutakapon 5939 /*
589     * Go through the jump list entries from the registry and add each
590     * one to the collection.
591     */
592     for (i = 1; i <= MAX_JUMPLIST_ITEMS; i++) {
593     _snprintf_s(EntName, sizeof(EntName), _TRUNCATE, "Host%d", i);
594     GetPrivateProfileString("Hosts", EntName, "", TempHost, sizeof(TempHost), IniFile);
595     if (strlen(TempHost) == 0) {
596     break;
597     }
598 yutakapon 4385
599 zmatsuo 9036 #if _DEBUG
600 yutakapon 5939 OutputDebugPrintf("%s\n", piterator);
601 zmatsuo 9036 #endif
602 yutakapon 5939 link = make_shell_link(NULL, piterator);
603     if (link) {
604     UINT j;
605     int found;
606 yutakapon 4385
607 yutakapon 5939 /*
608     * Check that the link isn't in the user-removed list.
609     */
610     for (j = 0, found = FALSE; j < nremoved && !found; j++) {
611     IShellLink *rlink;
612     if (SUCCEEDED(pRemoved->lpVtbl->GetAt
613     (pRemoved, j, COMPTR(IShellLink, &rlink)))) {
614     char desc1[2048], desc2[2048];
615     if (SUCCEEDED(link->lpVtbl->GetDescription
616     (link, desc1, sizeof(desc1) - 1)) &&
617     SUCCEEDED(rlink->lpVtbl->GetDescription
618     (rlink, desc2, sizeof(desc2) - 1)) &&
619     !strcmp(desc1, desc2)) {
620     found = TRUE;
621     }
622 yutakapon 5940 result = rlink->lpVtbl->Release(rlink);
623 zmatsuo 9036 #if _DEBUG
624 yutakapon 5940 if (result != S_OK)
625     OutputDebugPrintf("Release rlink failed. (%ld)\n", result);
626 zmatsuo 9036 #endif
627 yutakapon 5939 }
628     }
629 yutakapon 4385
630 yutakapon 5939 if (!found) {
631 yutakapon 5940 result = collection->lpVtbl->AddObject(collection, (IUnknown *)link);
632 zmatsuo 9036 #if _DEBUG
633 yutakapon 5940 if (result != S_OK)
634     OutputDebugPrintf("AddObject link failed. (%ld)\n", result);
635 zmatsuo 9036 #endif
636 yutakapon 5939 }
637 yutakapon 4385
638 yutakapon 5940 result = link->lpVtbl->Release(link);
639 zmatsuo 9036 #if _DEBUG
640 yutakapon 5940 if (result != S_OK)
641     OutputDebugPrintf("Release link failed. (%ld)\n", result);
642 zmatsuo 9036 #endif
643 yutakapon 5939 link = NULL;
644     }
645 doda 4506 }
646 yutakapon 4385
647 yutakapon 5939 /*
648     * Get the array form of the collection we've just constructed,
649     * and put it in the jump list.
650     */
651     if (!SUCCEEDED(collection->lpVtbl->QueryInterface
652     (collection, COMPTR(IObjectArray, &array))))
653     goto cleanup;
654 yutakapon 4385
655 yutakapon 5940 result = pCDL->lpVtbl->AppendCategory(pCDL, L"Recent Sessions", array);
656 zmatsuo 9036 #if _DEBUG
657 yutakapon 5940 if (result != S_OK)
658     OutputDebugPrintf("AppendCategory array failed. (%ld)\n", result);
659 zmatsuo 9036 #endif
660 yutakapon 4385
661 yutakapon 5939 /*
662     * Create an object collection to form the 'Tasks' category on the
663     * jump list.
664     */
665     if (!SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection,
666     NULL, CLSCTX_INPROC_SERVER,
667     COMPTR(IObjectCollection, &collection))))
668     goto cleanup;
669 yutakapon 4385
670 yutakapon 5939 /*
671     * Get the array form of the collection we've just constructed,
672     * and put it in the jump list.
673     */
674     if (!SUCCEEDED(collection->lpVtbl->QueryInterface
675     (collection, COMPTR(IObjectArray, &array))))
676     goto cleanup;
677 yutakapon 4385
678 yutakapon 5940 result = pCDL->lpVtbl->AddUserTasks(pCDL, array);
679 zmatsuo 9036 #if _DEBUG
680 yutakapon 5940 if (result != S_OK)
681     OutputDebugPrintf("AddUserTasks array failed. (0x%x)\n", result);
682 zmatsuo 9036 #endif
683 yutakapon 4385
684 yutakapon 5939 /*
685     * Now we can clean up the array and collection variables, so as
686     * to be able to reuse them.
687     */
688 yutakapon 5940 result = array->lpVtbl->Release(array);
689 zmatsuo 9036 #if _DEBUG
690 yutakapon 5940 if (result != S_OK)
691     OutputDebugPrintf("Release array failed. (%ld)\n", result);
692 zmatsuo 9036 #endif
693 yutakapon 5939 array = NULL;
694 yutakapon 5940 result = collection->lpVtbl->Release(collection);
695 zmatsuo 9036 #if _DEBUG
696 yutakapon 5940 if (result != S_OK)
697     OutputDebugPrintf("Release collection failed. (%ld)\n", result);
698 zmatsuo 9036 #endif
699 yutakapon 5939 collection = NULL;
700 yutakapon 4385
701 yutakapon 5939 /*
702     * Create another object collection to form the user tasks
703     * category.
704     */
705     if (!SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection,
706     NULL, CLSCTX_INPROC_SERVER,
707     COMPTR(IObjectCollection, &collection))))
708     goto cleanup;
709 yutakapon 4385
710 yutakapon 5939 /*
711     * Get the array form of the collection we've just constructed,
712     * and put it in the jump list.
713     */
714     if (!SUCCEEDED(collection->lpVtbl->QueryInterface
715     (collection, COMPTR(IObjectArray, &array))))
716     goto cleanup;
717 yutakapon 4385
718 yutakapon 5940 result = pCDL->lpVtbl->AddUserTasks(pCDL, array);
719 zmatsuo 9036 #if _DEBUG
720 yutakapon 5940 if (result != S_OK)
721     OutputDebugPrintf("AddUserTasks array2 failed. (0x%x)\n", result);
722 zmatsuo 9036 #endif
723 yutakapon 4385
724 yutakapon 5939 /*
725     * Now we can clean up the array and collection variables, so as
726     * to be able to reuse them.
727     */
728 yutakapon 5940 result = array->lpVtbl->Release(array);
729 zmatsuo 9036 #if _DEBUG
730 yutakapon 5940 if (result != S_OK)
731     OutputDebugPrintf("Release array2 failed. (%ld)\n", result);
732 zmatsuo 9036 #endif
733 yutakapon 5939 array = NULL;
734 yutakapon 5940 result = collection->lpVtbl->Release(collection);
735 zmatsuo 9036 #if _DEBUG
736 yutakapon 5940 if (result != S_OK)
737     OutputDebugPrintf("Release collection2 failed. (%ld)\n", result);
738 zmatsuo 9036 #endif
739 yutakapon 5939 collection = NULL;
740 yutakapon 4385
741 yutakapon 5939 /*
742     * Commit the jump list.
743     */
744 yutakapon 5940 result = pCDL->lpVtbl->CommitList(pCDL);
745 zmatsuo 9036 #if _DEBUG
746 yutakapon 5940 if (result != S_OK)
747     OutputDebugPrintf("CommitList failed. (%ld)\n", result);
748 zmatsuo 9036 #endif
749 yutakapon 5939 need_abort = FALSE;
750 yutakapon 4385
751 yutakapon 5939 /*
752     * Clean up.
753     */
754     cleanup:
755     if (pRemoved) pRemoved->lpVtbl->Release(pRemoved);
756     if (pCDL && need_abort) pCDL->lpVtbl->AbortList(pCDL);
757     if (pCDL) pCDL->lpVtbl->Release(pCDL);
758     if (collection) collection->lpVtbl->Release(collection);
759     if (array) array->lpVtbl->Release(array);
760     if (link) link->lpVtbl->Release(link);
761 yutakapon 4385 }
762    
763 doda 4506 void add_to_recent_docs(const char * const sessionname)
764     {
765     IShellLink *link = NULL;
766    
767     link = make_shell_link(NULL, sessionname);
768    
769     SHAddToRecentDocs(6 /* SHARD_LINK */, link);
770    
771     return;
772     }
773    
774 yutakapon 4385 /* Clears the entire jumplist. */
775     void clear_jumplist(void)
776     {
777 yutakapon 5939 ICustomDestinationList *pCDL;
778 yutakapon 4385
779 yutakapon 5939 if (CoCreateInstance(&CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER,
780     COMPTR(ICustomDestinationList, &pCDL)) == S_OK) {
781     pCDL->lpVtbl->DeleteList(pCDL, NULL);
782     pCDL->lpVtbl->Release(pCDL);
783     }
784 yutakapon 4385
785     }
786    
787     /* Adds a saved session to the Windows 7 jumplist. */
788     void add_session_to_jumplist(const char * const sessionname, char *inifile)
789     {
790 yutakapon 5939 if (!isJumpListSupported())
791     return; /* do nothing on pre-Win7 systems */
792 yutakapon 4385
793 yutakapon 5939 // add_to_recent_docs(sessionname);
794 doda 4506
795 yutakapon 5939 IniFile = inifile;
796 yutakapon 4385
797 yutakapon 5939 update_jumplist_from_registry();
798     return;
799 yutakapon 4385 }
800    
801     /* Removes a saved session from the Windows jumplist. */
802     void remove_session_from_jumplist(const char * const sessionname)
803     {
804 yutakapon 5939 if (!isJumpListSupported())
805     return; /* do nothing on pre-Win7 systems */
806 yutakapon 4385
807 yutakapon 5939 update_jumplist_from_registry();
808     return;
809 yutakapon 4385 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26