app-openpgp changes
[gnupg.git] / agent / w32main.c
blob9fc3abbef5a1a9e6ebff7cf44295de30b09ac7ad
1 /* w32main.c - W32 main entry pint and taskbar support for the GnuPG Agent
2 * Copyright (C) 2007 Free Software Foundation, Inc.
3 * Copyright 1996, 1998 Alexandre Julliard
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG 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
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #ifndef HAVE_W32_SYSTEM
23 #error This module is only useful for the W32 version of gpg-agent
24 #endif
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <windows.h>
31 #include "util.h"
32 #include "w32main.h"
34 /* The instance handle has received by WinMain. */
35 static HINSTANCE glob_hinst;
36 static HWND glob_hwnd;
39 /* Build an argv array from the command in CMDLINE. RESERVED is the
40 number of args to reserve before the first one. This code is based
41 on Alexandre Julliard's LGPLed wine-0.9.34/dlls/kernel32/process.c
42 and modified to fit into our framework. The function returns NULL
43 on error; on success an arry with the argiments is returned. This
44 array has been allocaqted using a plain malloc (and not the usual
45 xtrymalloc). */
46 static char **
47 build_argv (char *cmdline_arg, int reserved)
49 int argc;
50 char **argv;
51 char *cmdline, *s, *arg, *d;
52 int in_quotes, bs_count;
54 cmdline = malloc (strlen (cmdline_arg) + 1);
55 if (!cmdline)
56 return NULL;
57 strcpy (cmdline, cmdline_arg);
59 /* First determine the required size of the array. */
60 argc = reserved + 1;
61 bs_count = 0;
62 in_quotes = 0;
63 s = cmdline;
64 for (;;)
66 if ( !*s || ((*s==' ' || *s=='\t') && !in_quotes)) /* A space. */
68 argc++;
69 /* Skip the remaining spaces. */
70 while (*s==' ' || *s=='\t')
71 s++;
72 if (!*s)
73 break;
74 bs_count = 0;
76 else if (*s=='\\')
78 bs_count++;
79 s++;
81 else if ( (*s == '\"') && !(bs_count & 1))
83 /* Unescaped '\"' */
84 in_quotes = !in_quotes;
85 bs_count=0;
86 s++;
88 else /* A regular character. */
90 bs_count = 0;
91 s++;
95 argv = xtrymalloc (argc * sizeof *argv);
96 if (!argv)
98 xfree (cmdline);
99 return NULL;
102 /* Now actually parse the command line. */
103 argc = reserved;
104 bs_count = 0;
105 in_quotes=0;
106 arg = d = s = cmdline;
107 while (*s)
109 if ((*s==' ' || *s=='\t') && !in_quotes)
111 /* Close the argument and copy it. */
112 *d = 0;
113 argv[argc++] = arg;
115 /* Skip the remaining spaces. */
117 s++;
118 while (*s==' ' || *s=='\t');
120 /* Start with a new argument */
121 arg = d = s;
122 bs_count = 0;
124 else if (*s=='\\')
126 *d++ = *s++;
127 bs_count++;
129 else if (*s=='\"')
131 if ( !(bs_count & 1) )
133 /* Preceded by an even number of backslashes, this is
134 half that number of backslashes, plus a '\"' which we
135 discard. */
136 d -= bs_count/2;
137 s++;
138 in_quotes = !in_quotes;
140 else
142 /* Preceded by an odd number of backslashes, this is
143 half that number of backslashes followed by a '\"'. */
144 d = d - bs_count/2 - 1;
145 *d++ ='\"';
146 s++;
148 bs_count=0;
150 else /* A regular character. */
152 *d++ = *s++;
153 bs_count = 0;
157 if (*arg)
159 *d = 0;
160 argv[argc++] = arg;
162 argv[argc] = NULL;
164 return argv;
169 /* Our window message processing function. */
170 static LRESULT CALLBACK
171 wndw_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
174 switch (msg)
176 case WM_USER:
177 fprintf (stderr,"%s: received WM_%s\n", __func__, "USER" );
178 break;
182 return DefWindowProc (hwnd, msg, wparam, lparam);
186 /* This function is called to do some fast event polling and
187 processing. */
188 void
189 w32_poll_events (void)
191 /* MSG msg; */
193 /* fprintf (stderr,"%s: enter\n", __func__); */
194 /* while (PeekMessage (&msg, glob_hwnd, 0, 0, PM_REMOVE)) */
195 /* { */
196 /* DispatchMessage (&msg); */
197 /* } */
198 /* fprintf (stderr,"%s: leave\n", __func__); */
203 static void *
204 handle_taskbar (void *ctx)
206 WNDCLASS wndwclass = {0, wndw_proc, 0, 0, glob_hinst,
207 0, 0, 0, 0, "gpg-agent"};
208 NOTIFYICONDATA nid;
209 HWND hwnd;
210 MSG msg;
211 int rc;
213 if (!RegisterClass (&wndwclass))
215 log_error ("error registering window class\n");
216 ExitThread (0);
218 hwnd = CreateWindow ("gpg-agent", "gpg-agent",
219 0, 0, 0, 0, 0,
220 NULL, NULL, glob_hinst, NULL);
221 if (!hwnd)
223 log_error ("error creating main window\n");
224 ExitThread (0);
226 glob_hwnd = hwnd;
227 UpdateWindow (hwnd);
229 memset (&nid, 0, sizeof nid);
230 nid.cbSize = sizeof (nid);
231 nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
232 nid.uCallbackMessage = WM_USER;
233 nid.hWnd = glob_hwnd;
234 nid.uID = 1;
235 nid.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (1));
236 mem2str (nid.szTip, "GnuPG Agent version "PACKAGE_VERSION,
237 sizeof nid.szTip);
238 Shell_NotifyIcon (NIM_ADD, &nid);
239 DestroyIcon (nid.hIcon);
241 fprintf (stderr, "%s: enter\n", __func__);
242 while ( (rc=GetMessage (&msg, hwnd, 0, 0)) )
244 if (rc == -1)
246 log_error ("getMessage failed: %s\n", w32_strerror (-1));
247 break;
249 TranslateMessage (&msg);
250 DispatchMessage (&msg);
252 fprintf (stderr,"%s: leave\n", __func__);
253 ExitThread (0);
254 return NULL;
259 /* This function initializes the Window system and sets up the taskbar
260 icon. We only have very limited GUI support just to give the
261 taskbar icon a little bit of life. This fucntion is called once to
262 fire up the icon. */
264 w32_setup_taskbar (void)
266 SECURITY_ATTRIBUTES sa;
267 DWORD tid;
268 HANDLE th;
270 memset (&sa, 0, sizeof sa);
271 sa.nLength = sizeof sa;
272 sa.bInheritHandle = FALSE;
274 fprintf (stderr,"creating thread for the taskbar_event_loop...\n");
275 th = CreateThread (&sa, 128*1024,
276 (LPTHREAD_START_ROUTINE)handle_taskbar,
277 NULL, 0, &tid);
278 fprintf (stderr,"created thread %p tid=%d\n", th, (int)tid);
280 CloseHandle (th);
282 return 0;
286 /* The main entry point for the Windows version. We save away all GUI
287 related stuff, parse the command line and finally call the real
288 main. */
289 int WINAPI
290 WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
292 char **argv;
293 int argc;
295 /* We use the GetCommandLine function because that also includes the
296 program name in contrast to the CMDLINE arg. */
297 argv = build_argv (GetCommandLineA (), 0);
298 if (!argv)
299 return 2; /* Can't do much about a malloc failure. */
300 for (argc=0; argv[argc]; argc++)
303 glob_hinst = hinst;
305 return w32_main (argc, argv);