added first draft of RequestPull Dialog
[TortoiseGit.git] / src / TortoisePlink / Windows / WINPGNTC.C
blob3bfafc972c94f08ee59566dfe422274c5d9aba69
1 /*\r
2  * Pageant client code.\r
3  */\r
4 \r
5 #include <stdio.h>\r
6 #include <stdlib.h>\r
7 \r
8 #include "putty.h"\r
9 \r
10 #define AGENT_COPYDATA_ID 0x804e50ba   /* random goop */\r
11 #define AGENT_MAX_MSGLEN  8192\r
13 int agent_exists(void)\r
14 {\r
15     HWND hwnd;\r
16     hwnd = FindWindow("Pageant", "Pageant");\r
17     if (!hwnd)\r
18         return FALSE;\r
19     else\r
20         return TRUE;\r
21 }\r
23 /*\r
24  * Unfortunately, this asynchronous agent request mechanism doesn't\r
25  * appear to work terribly well. I'm going to comment it out for\r
26  * the moment, and see if I can come up with a better one :-/\r
27  */\r
28 #ifdef WINDOWS_ASYNC_AGENT\r
30 struct agent_query_data {\r
31     COPYDATASTRUCT cds;\r
32     unsigned char *mapping;\r
33     HANDLE handle;\r
34     char *mapname;\r
35     HWND hwnd;\r
36     void (*callback)(void *, void *, int);\r
37     void *callback_ctx;\r
38 };\r
40 DWORD WINAPI agent_query_thread(LPVOID param)\r
41 {\r
42     struct agent_query_data *data = (struct agent_query_data *)param;\r
43     unsigned char *ret;\r
44     int id, retlen;\r
46     id = SendMessage(data->hwnd, WM_COPYDATA, (WPARAM) NULL,\r
47                      (LPARAM) &data->cds);\r
48     ret = NULL;\r
49     if (id > 0) {\r
50         retlen = 4 + GET_32BIT(data->mapping);\r
51         ret = snewn(retlen, unsigned char);\r
52         if (ret) {\r
53             memcpy(ret, data->mapping, retlen);\r
54         }\r
55     }\r
56     if (!ret)\r
57         retlen = 0;\r
58     UnmapViewOfFile(data->mapping);\r
59     CloseHandle(data->handle);\r
60     sfree(data->mapname);\r
62     agent_schedule_callback(data->callback, data->callback_ctx, ret, retlen);\r
64     return 0;\r
65 }\r
67 #endif\r
69 int agent_query(void *in, int inlen, void **out, int *outlen,\r
70                 void (*callback)(void *, void *, int), void *callback_ctx)\r
71 {\r
72     HWND hwnd;\r
73     char *mapname;\r
74     HANDLE filemap;\r
75     unsigned char *p, *ret;\r
76     int id, retlen;\r
77     COPYDATASTRUCT cds;\r
79     *out = NULL;\r
80     *outlen = 0;\r
82     hwnd = FindWindow("Pageant", "Pageant");\r
83     if (!hwnd)\r
84         return 1;                      /* *out == NULL, so failure */\r
85     mapname = dupprintf("PageantRequest%08x", (unsigned)GetCurrentThreadId());\r
86     filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,\r
87                                 0, AGENT_MAX_MSGLEN, mapname);\r
88     if (filemap == NULL || filemap == INVALID_HANDLE_VALUE)\r
89         return 1;                      /* *out == NULL, so failure */\r
90     p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);\r
91     memcpy(p, in, inlen);\r
92     cds.dwData = AGENT_COPYDATA_ID;\r
93     cds.cbData = 1 + strlen(mapname);\r
94     cds.lpData = mapname;\r
95 #ifdef WINDOWS_ASYNC_AGENT\r
96     if (callback != NULL && !(flags & FLAG_SYNCAGENT)) {\r
97         /*\r
98          * We need an asynchronous Pageant request. Since I know of\r
99          * no way to stop SendMessage from blocking the thread it's\r
100          * called in, I see no option but to start a fresh thread.\r
101          * When we're done we'll PostMessage the result back to our\r
102          * main window, so that the callback is done in the primary\r
103          * thread to avoid concurrency.\r
104          */\r
105         struct agent_query_data *data = snew(struct agent_query_data);\r
106         DWORD threadid;\r
107         data->mapping = p;\r
108         data->handle = filemap;\r
109         data->mapname = mapname;\r
110         data->callback = callback;\r
111         data->callback_ctx = callback_ctx;\r
112         data->cds = cds;               /* structure copy */\r
113         data->hwnd = hwnd;\r
114         if (CreateThread(NULL, 0, agent_query_thread, data, 0, &threadid))\r
115             return 0;\r
116         sfree(data);\r
117     }\r
118 #endif\r
120     /*\r
121      * The user either passed a null callback (indicating that the\r
122      * query is required to be synchronous) or CreateThread failed.\r
123      * Either way, we need a synchronous request.\r
124      */\r
125     id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);\r
126     if (id > 0) {\r
127         retlen = 4 + GET_32BIT(p);\r
128         ret = snewn(retlen, unsigned char);\r
129         if (ret) {\r
130             memcpy(ret, p, retlen);\r
131             *out = ret;\r
132             *outlen = retlen;\r
133         }\r
134     }\r
135     UnmapViewOfFile(p);\r
136     CloseHandle(filemap);\r
137     return 1;\r