X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/d70f60ae52b946d174468a4dff49702daa93dc9a..7440fd4419acfc9c784f142fb9dee3e64c9a18c2:/pageantc.c diff --git a/pageantc.c b/pageantc.c index 49b588eb..7d840f96 100644 --- a/pageantc.c +++ b/pageantc.c @@ -2,37 +2,72 @@ * Pageant client code. */ -#include #include #include +#include "putty.h" + #define AGENT_COPYDATA_ID 0x804e50ba /* random goop */ #define AGENT_MAX_MSGLEN 8192 -#ifdef TESTMODE -#define debug(x) (printf x) -#else -#define debug(x) -#endif - #define GET_32BIT(cp) \ (((unsigned long)(unsigned char)(cp)[0] << 24) | \ ((unsigned long)(unsigned char)(cp)[1] << 16) | \ ((unsigned long)(unsigned char)(cp)[2] << 8) | \ ((unsigned long)(unsigned char)(cp)[3])) -int agent_exists(void) { +int agent_exists(void) +{ HWND hwnd; hwnd = FindWindow("Pageant", "Pageant"); if (!hwnd) - return FALSE; + return FALSE; else - return TRUE; + return TRUE; +} + +struct agent_query_data { + COPYDATASTRUCT cds; + unsigned char *mapping; + HANDLE handle; + char *mapname; + HWND hwnd; + void (*callback)(void *, void *, int); + void *callback_ctx; +}; + +DWORD WINAPI agent_query_thread(LPVOID param) +{ + struct agent_query_data *data = (struct agent_query_data *)param; + unsigned char *ret; + int id, retlen; + + id = SendMessage(data->hwnd, WM_COPYDATA, (WPARAM) NULL, + (LPARAM) &data->cds); + ret = NULL; + if (id > 0) { + retlen = 4 + GET_32BIT(data->mapping); + ret = snewn(retlen, unsigned char); + if (ret) { + memcpy(ret, data->mapping, retlen); + } + } + if (!ret) + retlen = 0; + UnmapViewOfFile(data->mapping); + CloseHandle(data->handle); + sfree(data->mapname); + + agent_schedule_callback(data->callback, data->callback_ctx, ret, retlen); + + return 0; } -void agent_query(void *in, int inlen, void **out, int *outlen) { +int agent_query(void *in, int inlen, void **out, int *outlen, + void (*callback)(void *, void *, int), void *callback_ctx) +{ HWND hwnd; - char mapname[64]; + char *mapname; HANDLE filemap; unsigned char *p, *ret; int id, retlen; @@ -42,48 +77,57 @@ void agent_query(void *in, int inlen, void **out, int *outlen) { *outlen = 0; hwnd = FindWindow("Pageant", "Pageant"); - debug(("hwnd is %p\n", hwnd)); if (!hwnd) - return; - sprintf(mapname, "PageantRequest%08x", GetCurrentThreadId()); + return 1; /* *out == NULL, so failure */ + mapname = dupprintf("PageantRequest%08x", (unsigned)GetCurrentThreadId()); filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - 0, AGENT_MAX_MSGLEN, mapname); + 0, AGENT_MAX_MSGLEN, mapname); if (!filemap) - return; + return 1; /* *out == NULL, so failure */ p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0); memcpy(p, in, inlen); cds.dwData = AGENT_COPYDATA_ID; - cds.cbData = 1+strlen(mapname); + cds.cbData = 1 + strlen(mapname); cds.lpData = mapname; - id = SendMessage(hwnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds); - debug(("return is %d\n", id)); + if (callback != NULL && !(flags & FLAG_SYNCAGENT)) { + /* + * We need an asynchronous Pageant request. Since I know of + * no way to stop SendMessage from blocking the thread it's + * called in, I see no option but to start a fresh thread. + * When we're done we'll PostMessage the result back to our + * main window, so that the callback is done in the primary + * thread to avoid concurrency. + */ + struct agent_query_data *data = snew(struct agent_query_data); + DWORD threadid; + data->mapping = p; + data->handle = filemap; + data->mapname = mapname; + data->callback = callback; + data->callback_ctx = callback_ctx; + data->cds = cds; /* structure copy */ + data->hwnd = hwnd; + if (CreateThread(NULL, 0, agent_query_thread, data, 0, &threadid)) + return 0; + sfree(data); + } + + /* + * The user either passed a null callback (indicating that the + * query is required to be synchronous) or CreateThread failed. + * Either way, we need a synchronous request. + */ + id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) & cds); if (id > 0) { - retlen = 4 + GET_32BIT(p); - debug(("len is %d\n", retlen)); - ret = malloc(retlen); - if (ret) { - memcpy(ret, p, retlen); - *out = ret; - *outlen = retlen; - } + retlen = 4 + GET_32BIT(p); + ret = snewn(retlen, unsigned char); + if (ret) { + memcpy(ret, p, retlen); + *out = ret; + *outlen = retlen; + } } UnmapViewOfFile(p); CloseHandle(filemap); + return 1; } - -#ifdef TESTMODE - -int main(void) { - void *msg; - int len; - int i; - - agent_query("\0\0\0\1\1", 5, &msg, &len); - debug(("%d:", len)); - for (i = 0; i < len; i++) - debug((" %02x", ((unsigned char *)msg)[i])); - debug(("\n")); - return 0; -} - -#endif