1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00
gnupg/agent/w32main.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

307 lines
7.4 KiB
C
Raw Permalink Normal View History

/* w32main.c - W32 main entry pint and taskbar support for the GnuPG Agent
* Copyright (C) 2007 Free Software Foundation, Inc.
* Copyright 1996, 1998 Alexandre Julliard
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
2007-07-04 19:49:40 +00:00
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#ifndef HAVE_W32_SYSTEM
#error This module is only useful for the W32 version of gpg-agent
#endif
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <windows.h>
#include "../common/util.h"
#include "w32main.h"
/* The instance handle has received by WinMain. */
static HINSTANCE glob_hinst;
static HWND glob_hwnd;
/* Build an argv array from the command in CMDLINE. RESERVED is the
number of args to reserve before the first one. This code is based
on Alexandre Julliard's LGPLed wine-0.9.34/dlls/kernel32/process.c
and modified to fit into our framework. The function returns NULL
on error; on success an array with the arguments is returned. This
array has been allocated using a plain malloc (and not the usual
xtrymalloc). */
static char **
build_argv (char *cmdline_arg, int reserved)
{
int argc;
char **argv;
char *cmdline, *s, *arg, *d;
int in_quotes, bs_count;
cmdline = malloc (strlen (cmdline_arg) + 1);
if (!cmdline)
return NULL;
strcpy (cmdline, cmdline_arg);
/* First determine the required size of the array. */
argc = reserved + 1;
bs_count = 0;
in_quotes = 0;
s = cmdline;
for (;;)
{
if ( !*s || ((*s==' ' || *s=='\t') && !in_quotes)) /* A space. */
{
argc++;
/* Skip the remaining spaces. */
while (*s==' ' || *s=='\t')
s++;
if (!*s)
break;
bs_count = 0;
}
else if (*s=='\\')
{
bs_count++;
s++;
}
else if ( (*s == '\"') && !(bs_count & 1))
{
/* Unescaped '\"' */
in_quotes = !in_quotes;
bs_count=0;
s++;
}
else /* A regular character. */
{
bs_count = 0;
s++;
}
}
argv = xtrymalloc (argc * sizeof *argv);
if (!argv)
{
xfree (cmdline);
return NULL;
}
/* Now actually parse the command line. */
argc = reserved;
bs_count = 0;
in_quotes=0;
arg = d = s = cmdline;
while (*s)
{
if ((*s==' ' || *s=='\t') && !in_quotes)
{
/* Close the argument and copy it. */
*d = 0;
argv[argc++] = arg;
/* Skip the remaining spaces. */
do
s++;
while (*s==' ' || *s=='\t');
/* Start with a new argument */
arg = d = s;
bs_count = 0;
}
else if (*s=='\\')
{
*d++ = *s++;
bs_count++;
}
else if (*s=='\"')
{
if ( !(bs_count & 1) )
{
/* Preceded by an even number of backslashes, this is
half that number of backslashes, plus a '\"' which we
discard. */
d -= bs_count/2;
s++;
in_quotes = !in_quotes;
}
else
{
/* Preceded by an odd number of backslashes, this is
half that number of backslashes followed by a '\"'. */
d = d - bs_count/2 - 1;
*d++ ='\"';
s++;
}
bs_count=0;
}
else /* A regular character. */
{
*d++ = *s++;
bs_count = 0;
}
}
if (*arg)
{
*d = 0;
argv[argc++] = arg;
}
argv[argc] = NULL;
return argv;
}
/* Our window message processing function. */
static LRESULT CALLBACK
wndw_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_USER:
fprintf (stderr,"%s: received WM_%s\n", __func__, "USER" );
break;
}
return DefWindowProc (hwnd, msg, wparam, lparam);
}
/* This function is called to do some fast event polling and
processing. */
void
w32_poll_events (void)
{
/* MSG msg; */
/* fprintf (stderr,"%s: enter\n", __func__); */
/* while (PeekMessage (&msg, glob_hwnd, 0, 0, PM_REMOVE)) */
/* { */
/* DispatchMessage (&msg); */
/* } */
/* fprintf (stderr,"%s: leave\n", __func__); */
}
static void *
handle_taskbar (void *ctx)
{
WNDCLASS wndwclass = {0, wndw_proc, 0, 0, glob_hinst,
0, 0, 0, 0, "gpg-agent"};
NOTIFYICONDATA nid;
HWND hwnd;
MSG msg;
int rc;
if (!RegisterClass (&wndwclass))
{
log_error ("error registering window class\n");
ExitThread (0);
}
hwnd = CreateWindow ("gpg-agent", "gpg-agent",
0, 0, 0, 0, 0,
NULL, NULL, glob_hinst, NULL);
if (!hwnd)
{
log_error ("error creating main window\n");
ExitThread (0);
}
glob_hwnd = hwnd;
UpdateWindow (hwnd);
memset (&nid, 0, sizeof nid);
nid.cbSize = sizeof (nid);
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
nid.uCallbackMessage = WM_USER;
nid.hWnd = glob_hwnd;
nid.uID = 1;
nid.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (1));
mem2str (nid.szTip, GPG_AGENT_NAME " version "PACKAGE_VERSION,
sizeof nid.szTip);
Shell_NotifyIcon (NIM_ADD, &nid);
DestroyIcon (nid.hIcon);
fprintf (stderr, "%s: enter\n", __func__);
while ( (rc=GetMessage (&msg, hwnd, 0, 0)) )
{
if (rc == -1)
{
log_error ("getMessage failed: %s\n", w32_strerror (-1));
break;
}
TranslateMessage (&msg);
DispatchMessage (&msg);
}
fprintf (stderr,"%s: leave\n", __func__);
ExitThread (0);
return NULL;
}
/* This function initializes the Window system and sets up the taskbar
icon. We only have very limited GUI support just to give the
Fix typos found using codespell. * agent/cache.c: Fix typos. * agent/call-pinentry.c: Likewise. * agent/call-scd.c: Likewise. * agent/command-ssh.c: Likewise. * agent/command.c: Likewise. * agent/divert-scd.c: Likewise. * agent/findkey.c: Likewise. * agent/gpg-agent.c: Likewise. * agent/w32main.c: Likewise. * common/argparse.c: Likewise. * common/audit.c: Likewise. * common/audit.h: Likewise. * common/convert.c: Likewise. * common/dotlock.c: Likewise. * common/exechelp-posix.c: Likewise. * common/exechelp-w32.c: Likewise. * common/exechelp-w32ce.c: Likewise. * common/exechelp.h: Likewise. * common/helpfile.c: Likewise. * common/i18n.h: Likewise. * common/iobuf.c: Likewise. * common/iobuf.h: Likewise. * common/localename.c: Likewise. * common/logging.c: Likewise. * common/openpgp-oid.c: Likewise. * common/session-env.c: Likewise. * common/sexputil.c: Likewise. * common/sysutils.c: Likewise. * common/t-sexputil.c: Likewise. * common/ttyio.c: Likewise. * common/util.h: Likewise. * dirmngr/cdblib.c: Likewise. * dirmngr/certcache.c: Likewise. * dirmngr/crlcache.c: Likewise. * dirmngr/dirmngr-client.c: Likewise. * dirmngr/dirmngr.c: Likewise. * dirmngr/dirmngr_ldap.c: Likewise. * dirmngr/dns-stuff.c: Likewise. * dirmngr/http.c: Likewise. * dirmngr/ks-engine-hkp.c: Likewise. * dirmngr/ks-engine-ldap.c: Likewise. * dirmngr/ldap-wrapper.c: Likewise. * dirmngr/ldap.c: Likewise. * dirmngr/misc.c: Likewise. * dirmngr/ocsp.c: Likewise. * dirmngr/validate.c: Likewise. * g10/encrypt.c: Likewise. * g10/getkey.c: Likewise. * g10/gpg.c: Likewise. * g10/gpgv.c: Likewise. * g10/import.c: Likewise. * g10/keydb.c: Likewise. * g10/keydb.h: Likewise. * g10/keygen.c: Likewise. * g10/keyid.c: Likewise. * g10/keylist.c: Likewise. * g10/keyring.c: Likewise. * g10/mainproc.c: Likewise. * g10/misc.c: Likewise. * g10/options.h: Likewise. * g10/packet.h: Likewise. * g10/parse-packet.c: Likewise. * g10/pkclist.c: Likewise. * g10/pkglue.c: Likewise. * g10/plaintext.c: Likewise. * g10/server.c: Likewise. * g10/sig-check.c: Likewise. * g10/sqlite.c: Likewise. * g10/tdbio.c: Likewise. * g10/test-stubs.c: Likewise. * g10/tofu.c: Likewise. * g10/trust.c: Likewise. * g10/trustdb.c: Likewise. * g13/create.c: Likewise. * g13/mountinfo.c: Likewise. * kbx/keybox-blob.c: Likewise. * kbx/keybox-file.c: Likewise. * kbx/keybox-init.c: Likewise. * kbx/keybox-search-desc.h: Likewise. * kbx/keybox-search.c: Likewise. * kbx/keybox-update.c: Likewise. * scd/apdu.c: Likewise. * scd/app-openpgp.c: Likewise. * scd/app-p15.c: Likewise. * scd/app.c: Likewise. * scd/ccid-driver.c: Likewise. * scd/command.c: Likewise. * scd/iso7816.c: Likewise. * sm/base64.c: Likewise. * sm/call-agent.c: Likewise. * sm/call-dirmngr.c: Likewise. * sm/certchain.c: Likewise. * sm/gpgsm.c: Likewise. * sm/import.c: Likewise. * sm/keydb.c: Likewise. * sm/minip12.c: Likewise. * sm/qualified.c: Likewise. * sm/server.c: Likewise. * tools/gpg-check-pattern.c: Likewise. * tools/gpgconf-comp.c: Likewise. * tools/gpgkey2ssh.c: Likewise. * tools/gpgparsemail.c: Likewise. * tools/gpgtar.c: Likewise. * tools/rfc822parse.c: Likewise. * tools/symcryptrun.c: Likewise. Signed-off-by: Justus Winter <justus@g10code.com>
2015-11-16 12:41:46 +01:00
taskbar icon a little bit of life. This function is called once to
fire up the icon. */
int
w32_setup_taskbar (void)
{
SECURITY_ATTRIBUTES sa;
DWORD tid;
HANDLE th;
memset (&sa, 0, sizeof sa);
sa.nLength = sizeof sa;
sa.bInheritHandle = FALSE;
fprintf (stderr,"creating thread for the taskbar_event_loop...\n");
th = CreateThread (&sa, 128*1024,
(LPTHREAD_START_ROUTINE)handle_taskbar,
NULL, 0, &tid);
fprintf (stderr,"created thread %p tid=%d\n", th, (int)tid);
CloseHandle (th);
return 0;
}
/* The main entry point for the Windows version. We save away all GUI
related stuff, parse the command line and finally call the real
main. */
int WINAPI
WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
{
char **argv;
int argc;
/* We use the GetCommandLine function because that also includes the
program name in contrast to the CMDLINE arg. */
argv = build_argv (GetCommandLineA (), 0);
if (!argv)
return 2; /* Can't do much about a malloc failure. */
for (argc=0; argv[argc]; argc++)
;
glob_hinst = hinst;
return w32_main (argc, argv);
}