/[winpt]/trunk/Src/wptKeylist.cpp
ViewVC logotype

Annotation of /trunk/Src/wptKeylist.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 428 - (hide annotations)
Sat Apr 7 11:55:16 2012 UTC (12 years, 10 months ago) by twoaday
File size: 30243 byte(s)


1 werner 36 /* wptKeylist.cpp - Keylist element
2 twoaday 328 * Copyright (C) 2001-2006, 2009 Timo Schulz
3 werner 36 * Copyright (C) 2004 Andreas Jobs
4     *
5     * This file is part of WinPT.
6     *
7     * WinPT is free software; you can redistribute it and/or
8     * modify it under the terms of the GNU General Public License
9     * as published by the Free Software Foundation; either version 2
10     * of the License, or (at your option) any later version.
11     *
12     * WinPT is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15     * General Public License for more details.
16     */
17 werner 42 #ifdef HAVE_CONFIG_H
18     #include <config.h>
19     #endif
20    
21 werner 36 #include <windows.h>
22     #include <commctrl.h>
23     #include <time.h>
24    
25     #include "wptCommonCtl.h"
26     #include "wptTypes.h"
27     #include "wptGPG.h"
28     #include "wptKeylist.h"
29     #include "wptKeyManager.h"
30     #include "wptW32API.h"
31     #include "wptNLS.h"
32     #include "wptErrors.h"
33     #include "wptUTF8.h"
34     #include "wptRegistry.h"
35     #include "wptContext.h"
36 twoaday 133 #include "wptVersion.h"
37     #include "resource.h"
38 twoaday 278 #include "StringBuffer.h"
39 werner 36
40    
41     struct key_array_s {
42     char keyid[32];
43 twoaday 328 int checked;
44 werner 36 };
45    
46    
47     static key_array_s*
48 twoaday 278 key_array_new (DWORD items)
49 werner 36 {
50     key_array_s *ka;
51    
52 twoaday 133 if (items == 0)
53 twoaday 328 BUG (NULL);
54 werner 36 ka = new key_array_s[items + 1];
55 twoaday 133 if (!ka)
56     BUG (NULL);
57 twoaday 328 for (DWORD i = 0; i < items; i++)
58 twoaday 278 ka[i].checked = 0;
59 werner 36 return ka;
60 twoaday 133 }
61 werner 36
62     static void
63 twoaday 133 key_array_release (key_array_s *ka)
64 werner 36 {
65 twoaday 133 free_if_alloc (ka);
66     }
67 werner 36
68    
69 twoaday 133 /* Check if the keyid @keyid is in the key array @ka.
70     Return value: 1 if it exists, 0 otherwise. */
71 werner 36 static int
72 twoaday 278 key_array_search (key_array_s *ka, DWORD items, const char *keyid)
73 werner 36 {
74 twoaday 328 for (DWORD i = 0; i < items; i++) {
75     if (!stricmp (keyid, ka[i].keyid))
76 werner 36 return 1;
77     }
78     return 0;
79 twoaday 133 }
80 werner 36
81    
82 twoaday 328 /* Return if there is a secret for @key.
83     0 means success. */
84     static int
85     find_secret_key (gpgme_key_t key)
86     {
87     winpt_key_s skey;
88    
89     if (!key->subkeys->keyid)
90     return 0;
91     memset (&skey, 0, sizeof (skey));
92     if (winpt_get_seckey (key->subkeys->keyid, &skey))
93     return 0;
94     if (skey.ext && skey.ext->gloflags.divert_to_card)
95     return 2;
96     return skey.ctx? 1 : 0;
97     }
98    
99    
100     /* Update the gpgme key pointer of a single entry. */
101     static void
102     update_key (keylist_ctrl_t kl, int pos,
103     gpgme_key_t key)
104     {
105     if ((size_t)pos > kl->nkeys)
106     BUG (0);
107     kl->keys[pos] = key;
108     }
109    
110    
111     /* If @re_sorted == 0, then all keys from the key list control
112     are stored as references in the array.
113     Otherwise we just re-order the references in the array. */
114     static size_t
115     update_keys (keylist_ctrl_t kl, int re_sorted,
116     gpgme_key_t **r_list)
117     {
118     gpgme_key_t *rset;
119     gpgme_key_t key;
120     listview_ctrl_t lv = kl->lv;
121     struct keycache_s *c;
122     size_t k_pos;
123     int nkeys;
124    
125     nkeys = listview_count_items (lv, 0);
126     if (!nkeys)
127     BUG (0);
128    
129     if (!re_sorted) {
130     rset = (gpgme_key_t*)calloc (nkeys+1, sizeof (gpgme_key_t));
131     *r_list = rset;
132     }
133     else
134     rset = *r_list;
135     k_pos = 0;
136     for (int i = 0; i < nkeys; i++) {
137     key = km_get_key_ptr (kl, i, &c);
138     rset[k_pos++] = key;
139     }
140     return k_pos;
141     }
142    
143    
144 werner 36 gpgme_user_id_t
145     get_nth_userid (gpgme_key_t key, int idx)
146     {
147     gpgme_user_id_t t;
148    
149     if (!key->uids)
150     return NULL;
151     t = key->uids;
152     while (idx-- && t->next)
153     t = t->next;
154     return t;
155     }
156    
157    
158     int
159     count_userids (gpgme_key_t key)
160     {
161     gpgme_user_id_t u;
162     int n = 1;
163    
164     u = key->uids;
165     if (!u)
166     return 0;
167     while (u->next) {
168     u = u->next;
169     n++;
170     }
171     return n;
172     }
173    
174    
175     gpgme_subkey_t
176     get_nth_key (gpgme_key_t key, int idx)
177     {
178     gpgme_subkey_t t;
179    
180     if (!key->subkeys)
181     return NULL;
182     t = key->subkeys;
183     while (idx-- && t->next)
184     t = t->next;
185     return t;
186     }
187    
188    
189     int
190     count_subkeys (gpgme_key_t key)
191     {
192     gpgme_subkey_t k;
193     int n = 1;
194    
195     k = key->subkeys;
196     if (!k)
197     return 0;
198     while (k->next) {
199     k = k->next;
200     n++;
201     }
202     return n;
203     }
204    
205    
206 twoaday 133 /* Return the self signature of the key @keyid.
207     If first is set, the first self sig will be returned. */
208 werner 36 gpgme_key_sig_t
209 twoaday 208 get_selfsig (gpgme_key_sig_t sigs, const char *keyid, int first)
210 werner 36 {
211     gpgme_key_sig_t s, self_sig=NULL;
212     long timestamp=0;
213 twoaday 133 int off = 0;
214 werner 36
215 twoaday 133 if (strlen (keyid) == 8)
216     off = 8;
217    
218 twoaday 208 for (s = sigs; s; s = s->next) {
219 twoaday 133 if (!strcmp (s->keyid+off, keyid) && s->timestamp > timestamp) {
220 werner 36 self_sig = s;
221     timestamp = s->timestamp;
222 twoaday 278 if (first) /* do not search for later self sigs. */
223 werner 36 break;
224     }
225     }
226     return self_sig;
227     }
228    
229    
230     const char*
231     get_key_algo (gpgme_key_t key, int keyidx)
232     {
233     static char algo_id[128];
234     gpgme_subkey_t k;
235     char alg[32];
236     const char *subalg;
237 twoaday 328 int n;
238 werner 36
239     if (keyidx > 0) {
240     k = get_nth_key (key, keyidx-1);
241     subalg = get_key_pubalgo (k->pubkey_algo);
242 twoaday 133 _snprintf (algo_id, DIM (algo_id)-1, "%s", subalg);
243 werner 36 return algo_id;
244     }
245     strcpy (alg, get_key_pubalgo (key->subkeys->pubkey_algo));
246     n = count_subkeys (key);
247     if (n > 1) {
248 twoaday 207 do {
249     k = get_nth_key (key, --n);
250     if (k->revoked || k->expired)
251     continue;
252     else
253     break;
254     } while (n > 0);
255 werner 36 subalg = get_key_pubalgo (k->pubkey_algo);
256 twoaday 207 if (k == key->subkeys)
257     _snprintf (algo_id, DIM (algo_id)-1, "%s", subalg);
258     else
259     _snprintf (algo_id, DIM (algo_id)-1, "%s/%s", alg, subalg);
260 werner 36 return algo_id;
261     }
262     return get_key_pubalgo (key->subkeys->pubkey_algo);
263 twoaday 133 }
264 werner 36
265    
266     const char*
267 twoaday 41 get_key_created (long timestamp)
268 werner 36 {
269 twoaday 278 static char timebuf[128];
270 werner 36
271 twoaday 133 if (timestamp < 1)
272 werner 48 return "????" "-??" "-??";
273 twoaday 278 if (!get_locale_date (timestamp, timebuf, DIM (timebuf)-1))
274     return "????" "-??" "-??";
275 werner 36 return timebuf;
276 twoaday 129 }
277 werner 36
278    
279 twoaday 41 /* Return a string presentation of the time @timestamp. */
280 werner 36 const char*
281     get_key_expire_date (long timestamp)
282     {
283     static char timebuf[64];
284    
285 twoaday 133 if (timestamp == 0)
286 werner 36 return _("Never");
287 twoaday 278 if (!get_locale_date (timestamp, timebuf, DIM (timebuf)-1))
288     return "????" "-??" "-??";
289 werner 36 return timebuf;
290 twoaday 41 }
291 werner 36
292    
293     const char*
294     get_key_type (gpgme_key_t key)
295     {
296     int type = find_secret_key (key);
297    
298     if (type == 1)
299     return _("Key Pair");
300     else if (type == 2)
301     return _("Key Pair (Card)");
302     return _("Public Key");
303 twoaday 129 }
304 werner 36
305    
306     const char*
307     get_key_size (gpgme_key_t key, int keyidx)
308     {
309     static char size_id[64];
310     gpgme_subkey_t k;
311     int n, size_main, size_sub;
312    
313     if (keyidx > 0) {
314     k = get_nth_key (key, keyidx-1);
315     size_main = k->length;
316     _snprintf (size_id, DIM (size_id)-1, "%d", size_main);
317     return size_id;
318     }
319     size_main = key->subkeys->length;
320     n = count_subkeys (key);
321     if (n > 1) {
322     k = get_nth_key (key, n-1);
323     size_sub = k->length;
324 twoaday 271 _snprintf (size_id, DIM (size_id) - 1, "%d/%d",
325 twoaday 133 size_main, size_sub);
326 werner 36 return size_id;
327     }
328 twoaday 271 _snprintf (size_id, DIM (size_id) - 1, "%d", size_main);
329 werner 36 return size_id;
330 twoaday 129 }
331 werner 36
332    
333     const char*
334 twoaday 129 get_key_pubalgo2 (gpgme_pubkey_algo_t alg)
335     {
336     switch (alg) {
337     case GPGME_PK_DSA: return "D";
338     case GPGME_PK_RSA: return "R";
339     case GPGME_PK_ELG: return "G";
340     default: return "?";
341     }
342     return "?";
343     }
344    
345 twoaday 133
346 twoaday 129 const char*
347 werner 36 get_key_pubalgo (gpgme_pubkey_algo_t alg)
348     {
349     switch (alg) {
350     case GPGME_PK_DSA: return "DSA";
351     case GPGME_PK_ELG:
352     case GPGME_PK_ELG_E: return "ELG";
353 twoaday 226 case 0: /* XXX: do we still need this?? */
354     case GPGME_PK_RSA:
355     case GPGME_PK_RSA_S:
356     case GPGME_PK_RSA_E: return "RSA";
357 twoaday 73 default: return "???";
358 werner 36 }
359     return "???";
360     }
361    
362 twoaday 273
363 twoaday 133 const char*
364 werner 36 get_key_fpr (gpgme_key_t key)
365     {
366     static char fpr_md[64];
367     const char *fpr;
368     char t[16], tmp[40];
369 twoaday 328 size_t i;
370 werner 36
371     memset (fpr_md, 0, sizeof (fpr_md));
372     fpr = key->subkeys->fpr;
373     if (!fpr || !*fpr) {
374     memset (tmp, '0', 40);
375     fpr = tmp;
376     }
377     if (strlen (fpr) == 32) {
378     strcat (fpr_md, " ");
379     for (i=0; i < strlen (fpr)/2; i++) {
380     sprintf (t, "%c%c ", fpr[2*i], fpr[2*i+1]);
381     strcat (fpr_md, t);
382     }
383     }
384     else {
385     strcat (fpr_md, " ");
386     for (i = 0; i < strlen (fpr) / 4; i++) {
387     sprintf (t, "%c%c%c%c ", fpr[4*i], fpr[4*i+1], fpr[4*i+2], fpr[4*i+3]);
388     strcat (fpr_md, t);
389     }
390     }
391     return fpr_md;
392 twoaday 129 }
393 werner 36
394    
395 twoaday 205 /* Extract the key ID from the fingerprint.
396     A long ID will be converted into a short ID. */
397 twoaday 133 const char*
398 twoaday 205 get_keyid_from_fpr (const char *fpr)
399     {
400     if (!fpr)
401     return "????????";
402     if (strlen (fpr) == 40)
403     fpr += 32;
404     else if (strlen (fpr) == 32)
405     fpr += 24;
406     else if (strlen (fpr) == 16)
407     fpr += 8;
408     else
409     return "????????";
410     return fpr;
411     }
412    
413    
414     const char*
415 werner 36 get_key_trust2 (gpgme_key_t key, int val, int uididx, int listmode)
416     {
417     if (key)
418     val = key->owner_trust; /* uididx?? */
419     switch (val) {
420     case GPGME_VALIDITY_UNKNOWN:
421     case GPGME_VALIDITY_UNDEFINED:
422 twoaday 88 return _("None");
423 werner 36 case GPGME_VALIDITY_NEVER:
424 twoaday 88 return _("Never");
425 werner 36 case GPGME_VALIDITY_MARGINAL:
426 twoaday 88 return _("Marginal");
427 werner 36 case GPGME_VALIDITY_FULL:
428 twoaday 208 return _("Full");
429 werner 36 case GPGME_VALIDITY_ULTIMATE:
430 twoaday 208 return _("Ultimate");
431 werner 36 }
432     return "";
433     }
434    
435    
436 twoaday 167 const char*
437 werner 36 get_key_trust (gpgme_key_t key, int uididx, int listmode)
438     {
439     return get_key_trust2 (key, 0, uididx, listmode);
440     }
441    
442    
443 twoaday 167 const char*
444 werner 36 get_key_trust_str (int val)
445     {
446     return get_key_trust2 (NULL, val, 0, 0);
447     }
448    
449    
450 twoaday 50 /* Return the status of the key @key. */
451 werner 36 char*
452     get_key_status (gpgme_key_t key, int uididx, int listmode)
453     {
454     gpgme_user_id_t u;
455 twoaday 50 const char *attr;
456 werner 36 u32 key_attr =0;
457    
458     if (uididx < 0 || count_userids (key) > uididx)
459     uididx = 0;
460     if (listmode) {
461 twoaday 105 const char *s;
462 werner 36 if (key->revoked)
463 werner 48 s = _("Revoked");
464 werner 36 else if (key->expired)
465 werner 48 s = _("Expired");
466 werner 36 else if (key->disabled)
467 werner 48 s = _("Disabled");
468 twoaday 105 else
469     s = "";
470 werner 36 /* if the key has a special status, we don't continue to figure out
471 twoaday 133 the user-id validities. */
472 werner 48 if (*s)
473     return m_strdup (s);
474 werner 36 }
475     u = get_nth_userid (key, uididx);
476     key_attr = u->validity;
477     attr = get_key_trust2 (NULL, key_attr, 0, 0);
478 twoaday 50 return m_strdup (attr);
479     }
480 werner 36
481    
482 twoaday 167 /* Return human readable description of the key @key. */
483     char*
484     get_key_desc (gpgme_key_t key)
485     {
486     gpgme_key_t sk;
487     const char *state, *alg, *type;
488 twoaday 278 char *desc;
489     StringBuffer p;
490 twoaday 167
491     state = "";
492     if (key->disabled)
493     state = _("Disabled");
494     if (key->expired)
495     state = _("Expired");
496     if (key->revoked)
497     state = _("Revoked");
498 twoaday 278
499     /* If the fingerprint has 32 octets, we assume MD5 and thus
500     an old, version 3, RSA key which is called 'Legacy' by other
501     OpenPGP programs. */
502 twoaday 167 if (strlen (key->subkeys->fpr) == 32)
503     alg = "RSA Legacy";
504 twoaday 278 else
505     alg = "OpenPGP";
506 twoaday 167 type = _("public key");
507     if (!get_seckey (key->subkeys->keyid+8, &sk))
508     type = _("key pair");
509 twoaday 278 p = state;
510     p = p + " " + alg + " " + type;
511     desc = m_strdup (p.getBuffer ());
512     return desc;
513 twoaday 167 }
514    
515    
516 werner 36 /* Integer comparsion of @a and @b.
517     Return values: same as in strcmp. */
518     static inline int
519     int_cmp (int a, int b)
520     {
521     if (a == b) return 0;
522     else if (a > b) return 1;
523     else return -1;
524     return 0;
525     }
526    
527    
528     /* To allow to sort the keys, we need to take care of
529     the expired/revoke status also. */
530     static int
531     get_ext_validity (gpgme_key_t k)
532     {
533     if (k->revoked)
534     return GPGME_VALIDITY_ULTIMATE+1;
535     else if (k->expired)
536     return GPGME_VALIDITY_ULTIMATE+2;
537 twoaday 150 else if (k->disabled)
538     return GPGME_VALIDITY_ULTIMATE+3;
539 werner 36 return k->uids->validity;
540     }
541    
542    
543     /* List view sorting callback. */
544     static int CALLBACK
545     keylist_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby)
546     {
547 twoaday 205 struct keycache_s *aa, *bb;
548 werner 36 gpgme_key_t a, b;
549     int cmpresult = 0;
550    
551 twoaday 205 aa = (struct keycache_s *)first;
552     bb = (struct keycache_s *)second;
553     if (!aa || !bb)
554 werner 36 BUG (NULL);
555 twoaday 205 a = aa->key;
556     b = bb->key;
557 werner 36
558     switch (sortby & ~KEYLIST_SORT_DESC) {
559     case KEY_SORT_USERID:
560 twoaday 25 cmpresult = strcmpi (a->uids->uid, b->uids->uid);
561 werner 36 break;
562    
563     case KEY_SORT_KEYID:
564     cmpresult = strcmpi (a->subkeys->keyid+8,
565     b->subkeys->keyid+8);
566     break;
567    
568     case KEY_SORT_VALIDITY:
569     cmpresult = int_cmp (get_ext_validity (a),
570     get_ext_validity (b));
571     break;
572    
573     case KEY_SORT_OTRUST:
574     cmpresult = int_cmp (a->owner_trust, b->owner_trust);
575     break;
576    
577     case KEY_SORT_IS_SECRET:
578     get_seckey (a->subkeys->keyid, &a);
579     get_seckey (b->subkeys->keyid, &b);
580     cmpresult = int_cmp (a? a->secret : 0, b? b->secret : 0);
581     break;
582    
583     case KEY_SORT_LEN:
584     cmpresult = int_cmp (a->subkeys->length,
585     b->subkeys->length);
586     break;
587    
588     case KEY_SORT_CREATED:
589     cmpresult = int_cmp (a->subkeys->timestamp,
590     b->subkeys->timestamp);
591     break;
592    
593     case KEY_SORT_ALGO:
594     cmpresult = int_cmp (a->subkeys->pubkey_algo,
595     b->subkeys->pubkey_algo);
596     break;
597    
598     default:
599     cmpresult = strcmpi (a->uids->uid, b->uids->uid);
600     break;
601     }
602     if (sortby & KEYLIST_SORT_DESC)
603     return (~cmpresult + 1);
604     else
605     return cmpresult;
606     }
607    
608    
609     int
610 twoaday 328 keylist_add_groups (keylist_ctrl_t kl)
611 werner 36 {
612     return 0;
613 twoaday 133 }
614 werner 36
615    
616 twoaday 328 /* Synchronize the key array with the contents
617     of the keylist. */
618     void
619     keylist_sync (keylist_ctrl_t kl)
620     {
621     free (kl->keys);
622     kl->nkeys = update_keys (kl, 0, &kl->keys);
623     }
624    
625    
626 werner 36 /* Create a listview for listing keys. Use the mode given in @mode
627     and the control is given in @ctrl. */
628 twoaday 273 static void
629 werner 36 keylist_build (listview_ctrl_t *r_lv, HWND ctrl, int mode)
630     {
631 twoaday 105 struct listview_column_s klist_enc[] = {
632     {0, 242, (char *)_("User ID")},
633     {1, 80, (char *)_("Key ID")},
634     {3, 46, (char *)_("Size")},
635     {4, 50, (char *)_("Cipher")},
636     {5, 70, (char *)_("Validity")},
637     {0, 0, NULL}
638     };
639     struct listview_column_s klist[] = {
640 twoaday 129 {0, 240, (char *)_("User ID")},
641 twoaday 105 {1, 78, (char *)_("Key ID")},
642     {2, 52, (char *)_("Type")},
643 twoaday 129 {3, 66, (char *)_("Size")},
644     {4, 60, (char *)_("Cipher")},
645     {5, 66, (char *)_("Validity")},
646     {6, 58, (char *)_("Trust")},
647 twoaday 105 {7, 72, (char *)_("Creation")},
648     {0, 0, NULL}
649     };
650 twoaday 273 HICON ico[6];
651 werner 36 listview_ctrl_t lv;
652     listview_column_t col;
653 twoaday 328 int ncols = 0, ext_chkbox = 0;
654 werner 36
655 twoaday 208 listview_new (&lv, ctrl);
656 twoaday 176 if (mode & KEYLIST_ENCRYPT_MIN) {
657 werner 36 col = klist_enc;
658 twoaday 328 ncols = (DIM (klist_enc) - 1);
659     ext_chkbox = 1;
660 werner 36 }
661 twoaday 328 else if (mode & KEYLIST_SIGN) {
662 werner 36 col = klist_enc;
663 twoaday 328 ncols = (DIM (klist_enc) - 1) - 1;
664     ext_chkbox = 1;
665 werner 36 }
666     else {
667     col = klist;
668 twoaday 328 ncols = (DIM (klist) - 1);
669 werner 36 }
670    
671 twoaday 328 for (int j = 0; j < ncols; j++)
672 twoaday 219 listview_add_column (lv, &col[j]);
673 twoaday 133 listview_set_ext_style (lv);
674 twoaday 328 if (ext_chkbox)
675 twoaday 273 listview_set_chkbox_style (lv);
676 twoaday 133 ico[0] = LoadIcon (glob_hinst, (LPCTSTR)IDI_PUBKEY);
677     ico[1] = LoadIcon (glob_hinst, (LPCTSTR)IDI_KEYPAIR);
678 twoaday 273 ico[2] = LoadIcon (glob_hinst, (LPCTSTR)IDI_REV_KEYPAIR);
679     ico[3] = LoadIcon (glob_hinst, (LPCTSTR)IDI_REV_PUBKEY);
680     ico[4] = LoadIcon (glob_hinst, (LPCTSTR)IDI_SORT_DOWNARROW);
681     ico[5] = LoadIcon (glob_hinst, (LPCTSTR)IDI_SORT_UPARROW);
682 twoaday 428 listview_set_image_list (lv, 20, 16, ico, 6);
683 twoaday 150 listview_del_all_items (lv);
684 twoaday 328 listview_set_grid_style (lv);
685 werner 36 *r_lv = lv;
686     }
687    
688    
689     static void
690 twoaday 328 keylist_load_keycache (keylist_ctrl_t kl, int mode,
691 werner 36 gpg_keycache_t pubkc, gpg_keycache_t seckc)
692     {
693     gpgme_key_t key, skey;
694 twoaday 205 struct keycache_s *c;
695     const char *keyid;
696 werner 36
697 twoaday 328 gpg_keycache_rewind (pubkc);
698 werner 36 if (pubkc && seckc) {
699 twoaday 205 while (!gpg_keycache_next_key2 (pubkc, 0, &c, &key)) {
700 werner 36 keyid = key->subkeys->keyid;
701     if (keyid && !gpg_keycache_find_key (seckc, keyid, 0, &skey))
702 twoaday 328 keylist_add_key (kl, mode, c, key);
703     }
704 werner 36 }
705     else if (pubkc) {
706 twoaday 328 while (!gpg_keycache_next_key2 (pubkc, 0, &c, &key))
707     keylist_add_key (kl, mode, c, key);
708 werner 36 }
709     }
710    
711    
712     /* Load the list view @ctrl with the keys from the cache.
713     Return value: list view context on success. */
714 twoaday 328 keylist_ctrl_t
715 werner 36 keylist_load (HWND ctrl, gpg_keycache_t pubkc, gpg_keycache_t seckc,
716     int mode, int sortby)
717     {
718 twoaday 328 keylist_ctrl_t kl;
719    
720     kl = new keylist_ctrl_s;
721     keylist_build (&kl->lv, ctrl, mode);
722     keylist_load_keycache (kl, mode, pubkc, seckc);
723     kl->nkeys = update_keys (kl, 0, &kl->keys);
724     keylist_sort (kl, sortby);
725     return kl;
726 werner 36 }
727    
728    
729     /* Reload the given key list control @lv. */
730     int
731 twoaday 328 keylist_reload (keylist_ctrl_t kl, gpg_keycache_t pubkc, int mode, int sortby)
732 werner 36 {
733 twoaday 328 listview_del_all_items (kl->lv);
734     keylist_load_keycache (kl, mode, pubkc, NULL);
735     /* It is possible that the list shrinks or increases so we need to
736     rebuild the list again. */
737     free (kl->keys); kl->keys = NULL;
738     kl->nkeys = update_keys (kl, 0, &kl->keys);
739     keylist_sort (kl, sortby);
740 werner 36 return 0;
741     }
742    
743    
744     void
745 twoaday 328 keylist_delete (keylist_ctrl_t kl)
746 werner 36 {
747 twoaday 328 if (!kl)
748     return;
749     if (kl->keys != NULL) {
750     free (kl->keys);
751     kl->keys = NULL;
752 werner 36 }
753 twoaday 328 if (kl->lv != NULL) {
754     listview_release (kl->lv);
755     kl->lv = NULL;
756     }
757 werner 36 }
758    
759    
760    
761    
762 twoaday 273 /* Enumeration for possible key icons. */
763     enum key_icontype_t {
764     IMG_KEY_PUB = 0,
765     IMG_KEY_PAIR = 1,
766     IMG_KEY_PAIR_REV = 2,
767     IMG_KEY_PUB_REV = 3
768     };
769    
770    
771 werner 36 static int
772 twoaday 273 key_get_image_id (gpgme_key_t key)
773     {
774     if (find_secret_key (key))
775     return key->revoked ? IMG_KEY_PAIR_REV :IMG_KEY_PAIR;
776     if (key->revoked)
777     return IMG_KEY_PUB_REV;
778     return IMG_KEY_PUB;
779     }
780    
781    
782     static int
783 twoaday 205 do_addkey (listview_ctrl_t lv, struct keycache_s *ctx, gpgme_key_t key,
784     int uididx, int keyidx, int list)
785 twoaday 328 {
786 werner 36 gpgme_user_id_t u;
787     gpgme_subkey_t k;
788 twoaday 328 LV_ITEM lvi;
789 twoaday 273 char *p;
790 werner 36 const char *attr;
791 twoaday 273 int idx = 0;
792 werner 36
793     /* we check the pubkey algorithm here to make sure that no ElGamal
794     sign+encrypt key is used in _any_ mode */
795     if (list != 1 && key->subkeys->pubkey_algo == GPGME_PK_ELG) {
796 twoaday 128 log_debug ("ElGamal (E+S) key found: %s (%s)\n",
797 werner 36 key->uids->name, key->subkeys->keyid);
798     return 0;
799     }
800 twoaday 205
801     if (listview_add_item2 (lv, " ", (void *)ctx))
802 werner 36 return WPTERR_GENERAL;
803 twoaday 128
804 twoaday 205 attr = ctx->uids->uid;
805 werner 36 memset (&lvi, 0, sizeof lvi);
806 twoaday 133 lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
807 werner 36 lvi.pszText = (char *)attr;
808 twoaday 273 lvi.iImage = key_get_image_id (key);
809 twoaday 205 lvi.lParam = (LPARAM )ctx;
810 twoaday 128 if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
811 werner 36 return WPTERR_GENERAL;
812    
813     if (uididx == -1) { /* request the primary user-id of the key. */
814 twoaday 205 attr = ctx->uids->uid;
815 werner 36 uididx = 0;
816     }
817     else {
818     u = get_nth_userid (key, uididx);
819     if (!u || u->revoked || uididx < 0)
820 twoaday 133 uididx = 0;
821 werner 36 u = get_nth_userid (key, uididx);
822     attr = u->uid;
823     }
824 twoaday 133 if (attr == NULL || strlen (attr) < 5) { /* normal userids are > 5 chars */
825 werner 36 attr = _("Invalid User ID");
826     listview_add_sub_item (lv, 0, idx++, attr);
827     }
828 twoaday 204 else
829     listview_add_sub_item (lv, 0, idx++, attr);
830 werner 36 k = get_nth_key (key, keyidx);
831 twoaday 273 if (k && k->keyid != NULL) {
832     char keyid[16+1];
833    
834     _snprintf (keyid, DIM (keyid) -1, "0x%s", k->keyid + 8);
835     listview_add_sub_item (lv, 0, idx++, keyid);
836 werner 36 }
837     if (list > 0) {
838 twoaday 273 DWORD key_attr = find_secret_key (key);
839 werner 36 if (!key_attr)
840     attr = "pub";
841     else
842     attr = key_attr == 1? "pub/sec" : "pub/crd";
843     listview_add_sub_item (lv, 0, idx++, attr);
844     }
845     if (lv->cols >= 2) {
846     attr = get_key_size (key, list == -1? keyidx+1 : 0);
847 twoaday 273 if (attr != NULL)
848 werner 36 listview_add_sub_item (lv, 0, idx++, attr);
849     }
850     if (lv->cols >= 3) {
851     attr = get_key_algo (key, list == -1? keyidx+1 : 0);
852 twoaday 273 if (attr != NULL)
853 werner 36 listview_add_sub_item( lv, 0, idx++, attr);
854     }
855 twoaday 167 if (lv->cols >= 4) {
856 twoaday 273 p = get_key_status (key, uididx, list > 0? 1 : 0);
857     if (p != NULL)
858     listview_add_sub_item (lv, 0, idx++, p);
859 werner 36 free_if_alloc (p);
860     }
861     if (lv->cols >= 5) {
862     attr = get_key_trust (key, uididx, list > 0? 1 : 0);
863     listview_add_sub_item (lv, 0, idx++, attr);
864     }
865 twoaday 273 if (lv->cols >= 6) {
866 werner 36 k = get_nth_key (key, keyidx);
867 twoaday 273 if (k->timestamp > 0) {
868     attr = get_key_created (k->timestamp);
869     listview_add_sub_item (lv, 0, idx++, attr);
870     }
871 werner 36 }
872    
873     return 0;
874     }
875    
876    
877 twoaday 129 /* Update a single column @col but for each element in the
878     listview @lv. */
879 werner 36 void
880 twoaday 328 keylist_upd_col (keylist_ctrl_t kl, int col)
881 twoaday 129 {
882     gpgme_key_t key;
883     const char *s;
884 twoaday 167 char buf[32], *p;
885 twoaday 129
886 twoaday 328 for (int i=0; i < listview_count_items (kl->lv, 0); i++) {
887     key = km_get_key_ptr (kl, i, NULL);
888 twoaday 129 if (!key)
889     continue;
890     switch (col) {
891     case KM_COL_KEYID:
892 twoaday 271 _snprintf (buf, DIM (buf)-1, "0x%s", key->subkeys->keyid+8);
893 twoaday 328 listview_add_sub_item (kl->lv, i, col, buf);
894 twoaday 129 break;
895    
896     case KM_COL_CIPHER:
897     s = get_key_algo (key, 0);
898 twoaday 328 listview_add_sub_item (kl->lv, i, col, s);
899 twoaday 129 break;
900    
901     case KM_COL_TYPE:
902     s = find_secret_key (key)? "pub/sec" : "pub";
903 twoaday 328 listview_add_sub_item (kl->lv, i, col, s);
904 twoaday 129 break;
905    
906     case KM_COL_CREAT:
907     s = get_key_created (key->subkeys->timestamp);
908 twoaday 328 listview_add_sub_item (kl->lv, i, col, s);
909 twoaday 129 break;
910 twoaday 167
911     case KM_COL_DESC:
912     p = get_key_desc (key);
913 twoaday 328 listview_add_sub_item (kl->lv, i, col, p);
914 twoaday 167 free_if_alloc (p);
915     break;
916 twoaday 129 }
917     }
918     }
919    
920 twoaday 133
921 twoaday 129 /* Update the listview item at position @pos with the data from
922     the key @key. */
923     void
924 twoaday 328 keylist_upd_key (keylist_ctrl_t kl, int pos,
925 twoaday 205 struct keycache_s *ctx, gpgme_key_t key)
926 werner 36 {
927 twoaday 328 listview_ctrl_t lv = kl->lv;
928 twoaday 204 char *p;
929 werner 36 char tmp[32];
930    
931 twoaday 205 listview_set_item2 (lv, pos, (void *)ctx);
932 twoaday 328 update_key (kl, pos, key);
933 twoaday 205 /* the only mode we support is KEYLIST_LIST in the Key Manager */
934 werner 36
935 twoaday 328 const char *s = ctx->uids->uid;
936 twoaday 204 if (s)
937     listview_add_sub_item (lv, pos, KM_COL_UID, s);
938 werner 36
939     s = key->subkeys->keyid;
940     if (s) {
941     sprintf (tmp, "0x%s", s+8);
942 twoaday 167 listview_add_sub_item (lv, pos, KM_COL_KEYID, tmp);
943 werner 36 }
944    
945     s = find_secret_key (key)? "pub/sec" : "pub";
946 twoaday 167 listview_add_sub_item (lv, pos, KM_COL_TYPE, s);
947 werner 36
948     s = get_key_size (key, 0);
949     if (s)
950 twoaday 167 listview_add_sub_item (lv, pos, KM_COL_SIZE, s);
951 werner 36
952     s = get_key_algo (key, 0);
953     if (s)
954 twoaday 167 listview_add_sub_item (lv, pos, KM_COL_CIPHER, s);
955 werner 36
956 twoaday 167 p = get_key_status (key, 0, 1);
957     if (p) {
958     listview_add_sub_item (lv, pos, KM_COL_VALID, p);
959     free_if_alloc (p);
960     }
961 werner 36
962     s = get_key_trust (key, 0, 1);
963     if (s)
964 twoaday 167 listview_add_sub_item (lv, pos, KM_COL_TRUST, s);
965 werner 36
966     long t = key->subkeys->timestamp;
967     s = get_key_created (t);
968     if (s)
969 twoaday 167 listview_add_sub_item (lv, pos, KM_COL_CREAT, s);
970 werner 36 }
971    
972    
973     int
974 twoaday 328 keylist_add_key (keylist_ctrl_t kl, int mode,
975 twoaday 205 struct keycache_s *ctx, gpgme_key_t key)
976 twoaday 328 {
977 werner 36 gpgme_subkey_t k;
978 twoaday 328 listview_ctrl_t lv = kl->lv;
979     int uids, rc, i;
980 werner 36
981 twoaday 41 /* if the entire key is disabled, just return. */
982 twoaday 80 if (key->disabled && !(mode & KEYLIST_LIST))
983 twoaday 41 return 0;
984    
985 twoaday 328 for (k = key->subkeys, i = 0; i < count_subkeys (key); i++, k = k->next) {
986 werner 36 if (k->invalid) {
987 twoaday 328 log_debug ("keylist_add_key: invalid key \"%s\"\n",
988     key->uids->name);
989 werner 36 continue; /* Don't use invalid keys */
990     }
991    
992     if (mode & KEYLIST_ALL) {
993     uids = count_userids (key);
994 twoaday 205 rc = do_addkey (lv, ctx, key, uids, i, 0);
995 twoaday 128 if (rc)
996 werner 36 return rc;
997     }
998     else if (mode & KEYLIST_LIST)
999 twoaday 205 return do_addkey (lv, ctx, key, -1, i, 1);
1000 werner 36 else if (mode & KEYLIST_ENCRYPT) {
1001     if (k->can_encrypt && key_is_useable (k)) {
1002     if (mode & KEYLIST_FLAG_FILE) {
1003 twoaday 205 rc = do_addkey (lv, ctx, key, -1, i, -1);
1004 werner 36 if (rc)
1005     return rc;
1006     }
1007     else {
1008 twoaday 128 for (uids = 0; uids < count_userids (key); uids++) {
1009 twoaday 205 rc = do_addkey (lv, ctx, key, uids, i, -1);
1010 twoaday 128 if (rc)
1011 werner 36 return rc;
1012     }
1013     }
1014     }
1015     }
1016     else if (mode & KEYLIST_ENCRYPT_MIN) {
1017 twoaday 328 if (k->can_encrypt && key_is_useable (k)) {
1018 twoaday 205 rc = do_addkey (lv, ctx, key, -1, i, -1);
1019 werner 36 return rc;
1020     }
1021     }
1022     else if (mode & KEYLIST_SIGN) {
1023 twoaday 41 if (k->can_sign
1024     && find_secret_key (key)
1025     && key_is_useable (k)) {
1026 twoaday 205 rc = do_addkey (lv, ctx, key, -1, i, -1);
1027 twoaday 41 if (rc)
1028 werner 36 return rc;
1029     }
1030     }
1031     }
1032    
1033 twoaday 328 return 0;
1034 twoaday 133 }
1035 werner 36
1036    
1037     int
1038 twoaday 328 keylist_sort (keylist_ctrl_t kl, int sortby)
1039 twoaday 150 {
1040 twoaday 328 int ret = listview_sort_items (kl->lv, sortby, keylist_cmp_cb);
1041     kl->nkeys = update_keys (kl, 1, &kl->keys);
1042     return ret;
1043 werner 36 }
1044    
1045    
1046     /* Check that the validity @validity is at least >= marginal. */
1047     static int
1048 twoaday 133 key_check_validity (gpgme_key_t key)
1049     {
1050     gpgme_user_id_t u;
1051    
1052     for (u=key->uids; u; u =u->next) {
1053     if (u->validity >= GPGME_VALIDITY_MARGINAL)
1054     return -1;
1055     }
1056    
1057     return 0;
1058 werner 36 }
1059    
1060    
1061     /* Extract all selected recipients from the list @lv and return them
1062     as a vector. @r_force_trust is >= 1 if one of the recipients is not
1063     fully trusted. @r_count returns the number of selected keys.
1064     Return value: the key list on success, NULL otherwise. */
1065     gpgme_key_t*
1066 twoaday 328 keylist_get_recipients (keylist_ctrl_t kl, int *r_force_trust, size_t *r_count)
1067    
1068 werner 36 {
1069 twoaday 328 gpgme_key_t *keybuf, key;
1070     listview_ctrl_t lv = kl->lv;
1071 twoaday 133 key_array_s *ka = NULL;
1072 twoaday 328 keycache_s *c;
1073 twoaday 260 size_t count = 0;
1074     int force_trust = 0;
1075 twoaday 328 int nkeys, ka_pos = 0, rc = 0;
1076 werner 36 int k_pos=0;
1077    
1078 twoaday 328 nkeys = listview_count_items (lv, 0);
1079     ka = key_array_new (nkeys);
1080     keybuf = (gpgme_key_t*)calloc (nkeys+1, sizeof (gpgme_key_t));
1081 werner 36 if (!keybuf)
1082     BUG (NULL);
1083    
1084 twoaday 328 for (int j = 0; j < nkeys; j++) {
1085     if (listview_get_item_state (lv, j) || nkeys == 1) {
1086     key = km_get_key_ptr (kl, j, &c);
1087 twoaday 133 if (!key)
1088     BUG (0);
1089     if (!key_check_validity (key) &&
1090     !key_array_search (ka, ka_pos, key->subkeys->keyid)) {
1091 twoaday 278 StringBuffer warn;
1092 twoaday 328 warn = warn + c->uids->uid + ":\n\n";
1093     warn = warn +_("It is NOT certain that the key belongs to the person\n"
1094 twoaday 278 "named in the user ID. If you *really* know what you are\n"
1095 twoaday 328 "doing, you may answer the next question with no\n"
1096     "\nSkip this key?");
1097     rc = msg_box (NULL, warn.getBuffer(), _("Warning"), MB_WARN_ASK);
1098     if (reg_prefs.always_trust || rc == IDNO) {
1099 twoaday 133 keybuf[k_pos++] = key;
1100 werner 36 force_trust++;
1101     ka[ka_pos].checked = 1;
1102 twoaday 133 strcpy (ka[ka_pos++].keyid, key->subkeys->keyid);
1103 werner 36 count++;
1104     }
1105     }
1106     else {
1107 twoaday 133 keybuf[k_pos++] = key;
1108 werner 36 count++;
1109     }
1110     }
1111     }
1112     key_array_release (ka);
1113     if (r_force_trust)
1114     *r_force_trust = force_trust;
1115     if (r_count)
1116     *r_count = count;
1117     return keybuf;
1118     }
1119    
1120    
1121     static int
1122 twoaday 133 keylist_get_keyflags (gpgme_key_t key)
1123 werner 36 {
1124 twoaday 133 int flags = KEYFLAG_NONE;
1125 werner 36
1126 twoaday 133 if (key->revoked)
1127     flags |= KEYFLAG_REVOKED;
1128     if (key->expired)
1129     flags |= KEYFLAG_EXPIRED;
1130     if (key->disabled)
1131     flags |= KEYFLAG_DISABLED;
1132 werner 36
1133     return flags;
1134 twoaday 133 }
1135 werner 36
1136    
1137 twoaday 328
1138 werner 36 gpgme_key_t*
1139 twoaday 328 keylist_enum_recipients (keylist_ctrl_t kl, int listype, size_t *r_count)
1140 werner 36 {
1141 twoaday 133 gpgme_key_t *rset;
1142     gpgme_key_t key;
1143 twoaday 328 listview_ctrl_t lv = kl->lv;
1144     struct keycache_s *c;
1145     size_t k_pos;
1146     int nkeys, id;
1147 werner 36
1148 twoaday 328 nkeys = listview_count_items (lv, 0);
1149     if (!nkeys)
1150 werner 36 return 0;
1151 twoaday 328 rset = (gpgme_key_t*)calloc (nkeys+1, sizeof (gpgme_key_t));
1152 werner 36 if (!rset)
1153     BUG (NULL);
1154 twoaday 328 k_pos = 0;
1155     for (int i = 0; i < nkeys; i++) {
1156 twoaday 133 if (!listview_get_item_state (lv, i))
1157 werner 36 continue;
1158 twoaday 328 key = km_get_key_ptr (kl, i, &c);
1159 twoaday 133 switch (listype) {
1160 werner 36 case KEYLIST_LIST:
1161 twoaday 133 if (keylist_get_keyflags (key) & KEYFLAG_REVOKED) {
1162     id = printf_box (_("Recipients"), MB_INFO|MB_YESNO,
1163     _("KeyID %s.\nDo you really want to export a revoked key?"),
1164 twoaday 205 c->uids->uid);
1165 twoaday 133 if (id == IDNO)
1166     continue;
1167 werner 36 }
1168     break;
1169     }
1170 twoaday 133 rset[k_pos++] = key;
1171 werner 36 }
1172     if (r_count)
1173     *r_count = k_pos;
1174     return rset;
1175 twoaday 133 }
1176 werner 36
1177    
1178     void
1179 twoaday 133 seclist_destroy (keylist_t *list)
1180 werner 36 {
1181     keylist_t l2;
1182 twoaday 278
1183 werner 36 while (*list) {
1184     l2 = (*list)->next;
1185     safe_free (*list);
1186     *list = l2;
1187     }
1188 twoaday 328 *list = NULL;
1189 twoaday 133 }
1190 werner 36
1191    
1192     void
1193 twoaday 328 seclist_init (HWND dlg, int ctlid, int flags, keylist_t *ret_list)
1194 werner 36 {
1195 twoaday 328 gpg_keycache_t kc;
1196 werner 36 gpgme_key_t key = NULL;
1197     HWND kb;
1198     keylist_t list=NULL, l, l2;
1199 twoaday 328 long pos;
1200 werner 36
1201     SendDlgItemMessage (dlg, ctlid, CB_RESETCONTENT, 0, 0);
1202     kb = GetDlgItem (dlg, ctlid);
1203     kc = keycache_get_ctx (0);
1204     if (!kc)
1205     BUG (0);
1206     gpg_keycache_rewind (kc);
1207    
1208     while (!gpg_keycache_next_key (kc, 1, &key)) {
1209 twoaday 278 StringBuffer inf;
1210     char *uid;
1211 twoaday 41 const char *id;
1212 werner 36
1213 twoaday 278 if (key->disabled || !key_is_useable (key->subkeys))
1214     continue;
1215    
1216 werner 36 if (flags & KEYLIST_FLAG_SHORT)
1217     id = key->uids->name;
1218     else
1219     id = key->uids->uid;
1220 twoaday 278 if (!id || !key->subkeys->keyid)
1221     continue;
1222 werner 36
1223 twoaday 187 uid = utf8_to_native (id);
1224 twoaday 278 inf = uid;
1225     inf = inf + " (" + get_key_pubalgo (key->subkeys->pubkey_algo) + "/";
1226     inf = inf + "0x" + (key->subkeys->keyid+8) + ")";
1227    
1228     combox_add_string (kb, inf.getBuffer ());
1229     safe_free (uid);
1230 werner 36 l = (struct keylist_s *)calloc (1, sizeof * l);
1231     if (!l)
1232     BUG (0);
1233     l->key = key;
1234     if (!list)
1235     list = l;
1236     else {
1237     for( l2 = list; l2->next; l2 = l2->next )
1238     ;
1239     l2->next = l;
1240     }
1241     }
1242 twoaday 133 for (pos = 0, l2=list; pos < SendMessage (kb, CB_GETCOUNT, 0, 0);
1243     pos++, l2=l2->next)
1244     SendMessage (kb, CB_SETITEMDATA, pos, (LPARAM)(DWORD)l2->key);
1245     SendMessage (kb, CB_SETCURSEL, 0, 0);
1246 werner 36 *ret_list = list;
1247     }
1248    
1249 twoaday 328
1250 werner 36 /* Select a secret key from the combo box with the ID @ctlid.
1251     Return the code on success in @ret_key. */
1252     int
1253     seclist_select_key (HWND dlg, int ctlid, gpgme_key_t *ret_key)
1254     {
1255     int pos;
1256     DWORD k = 0;
1257    
1258     pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
1259     if (pos == CB_ERR) {
1260     msg_box (dlg, _("No key was selected."), _("Secret Key List"), MB_ERR);
1261     *ret_key = NULL;
1262     }
1263     else {
1264     k = SendDlgItemMessage (dlg, ctlid, CB_GETITEMDATA, pos, 0);
1265     *ret_key = (gpgme_key_t)k;
1266     }
1267     return k? 0 : -1;
1268     }
1269 twoaday 328
1270    
1271     LRESULT
1272     keylist_listview_notify (HWND hwnd, gpgme_key_t *keys,
1273     int ctlid, LPARAM lparam)
1274     {
1275     LPNMHDR lpnmh = (LPNMHDR) lparam;
1276    
1277     if (!lpnmh)
1278     BUG (NULL);
1279    
1280     /* Make sure the message is for the control and
1281     that we have a key list. */
1282     if (lpnmh->idFrom != (DWORD)ctlid || keys == NULL)
1283     return 0;
1284    
1285     switch (lpnmh->code) {
1286     case NM_CUSTOMDRAW:
1287     LPNMLVCUSTOMDRAW lplvcd;
1288     lplvcd = (LPNMLVCUSTOMDRAW)lparam;
1289     if (lplvcd->nmcd.dwDrawStage == CDDS_PREPAINT)
1290     return CDRF_NOTIFYITEMDRAW;
1291    
1292     if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
1293     LRESULT ret = CDRF_DODEFAULT;
1294     int pos = lplvcd->nmcd.dwItemSpec;
1295     HWND lv = GetDlgItem (hwnd, ctlid);
1296     gpgme_key_t key = keys[pos];
1297    
1298     if (key != NULL) {
1299     HFONT hfont = (HFONT)SendMessage (lv, WM_GETFONT, 0, 0);
1300     LOGFONT lf;
1301     if (!GetObject (hfont, sizeof (lf), &lf))
1302     BUG (NULL);
1303     if (key->revoked)
1304     lf.lfStrikeOut = TRUE;
1305     else if (key->expired)
1306     lf.lfItalic = TRUE;
1307     if (find_secret_key (key))
1308     lf.lfWeight = FW_SEMIBOLD;
1309     hfont = CreateFontIndirect (&lf);
1310     SelectObject (lplvcd->nmcd.hdc, hfont);
1311     if (pos & 1)
1312     lplvcd->clrTextBk = RGB (0xE5, 0xE5, 0xE5);
1313     ret = CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;
1314     }
1315     return ret;
1316     }
1317    
1318     if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT) {
1319     HFONT hfont = (HFONT)GetStockObject (DEFAULT_GUI_FONT);
1320     hfont = (HFONT)SelectObject (lplvcd->nmcd.hdc, hfont);
1321     DeleteObject (hfont);
1322     return CDRF_DODEFAULT;
1323     }
1324     return CDRF_DODEFAULT;
1325     }
1326    
1327     return 0;
1328     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26