1 /*	$NetBSD: hook.c,v 1.3 2014/12/10 04:37:56 christos Exp $	*/
2 
3 /*
4  * hook.c - Hooking Asynchronous Completion
5  */
6 
7 /*
8  * Copyright (c) 2000,2002 Japan Network Information Center.
9  * All rights reserved.
10  *
11  * By using this file, you agree to the terms and conditions set forth bellow.
12  *
13  * 			LICENSE TERMS AND CONDITIONS
14  *
15  * The following License Terms and Conditions apply, unless a different
16  * license is obtained from Japan Network Information Center ("JPNIC"),
17  * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
18  * Chiyoda-ku, Tokyo 101-0047, Japan.
19  *
20  * 1. Use, Modification and Redistribution (including distribution of any
21  *    modified or derived work) in source and/or binary forms is permitted
22  *    under this License Terms and Conditions.
23  *
24  * 2. Redistribution of source code must retain the copyright notices as they
25  *    appear in each source code file, this License Terms and Conditions.
26  *
27  * 3. Redistribution in binary form must reproduce the Copyright Notice,
28  *    this License Terms and Conditions, in the documentation and/or other
29  *    materials provided with the distribution.  For the purposes of binary
30  *    distribution the "Copyright Notice" refers to the following language:
31  *    "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
32  *
33  * 4. The name of JPNIC may not be used to endorse or promote products
34  *    derived from this Software without specific prior written approval of
35  *    JPNIC.
36  *
37  * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
38  *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39  *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
40  *    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JPNIC BE LIABLE
41  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46  *    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47  *    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
48  */
49 
50 #include <windows.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 
55 #include "wrapcommon.h"
56 
57 /*
58  * Hook Managements
59  */
60 
61 static  HHOOK   hookHandle = NULL ;
62 
63 typedef struct _HOOK    *HOOKPTR;
64 
65 typedef struct _HOOK {
66 	HOOKPTR     prev;
67 	HOOKPTR     next;
68 	idn_resconf_t ctx;
69 	HWND        hWnd;
70 	u_int       wMsg;
71 	char FAR    *pBuf;
72 } HOOKREC;
73 
74 static  HOOKREC hookList = { 0 } ;
75 
76 static void
77 hookListInit(void) {
78 	if (hookList.prev == NULL || hookList.next == NULL) {
79 		hookList.prev = &hookList;
80 		hookList.next = &hookList;
81 	}
82 }
83 
84 static HOOKPTR
85 hookListSearch(HWND hWnd, u_int wMsg) {
86 	HOOKPTR hp;
87 
88 	for (hp = hookList.next ; hp != &hookList ; hp = hp->next) {
89 		if (hp->hWnd == hWnd && hp->wMsg == wMsg) {
90 			return (hp);
91 		}
92 	}
93 	return (NULL);
94 }
95 
96 static BOOL
97 hookListAppend(HWND hWnd, u_int wMsg, char FAR *buf, idn_resconf_t ctx) {
98 	HOOKPTR hp, prev, next;
99 
100 	if ((hp = (HOOKPTR)malloc(sizeof(HOOKREC))) == NULL) {
101 		idnPrintf("cannot create hook record\n");
102 		return (FALSE);
103 	}
104 	memset(hp, 0, sizeof(*hp));
105 
106 	hp->ctx = ctx;
107 	hp->hWnd = hWnd;
108 	hp->wMsg = wMsg;
109 	hp->pBuf = buf;
110 
111 	prev = hookList.prev;
112 	next = prev->next;
113 	prev->next = hp;
114 	next->prev = hp;
115 	hp->next = next;
116 	hp->prev = prev;
117 
118 	return (TRUE);
119 }
120 
121 static void
122 hookListDelete(HOOKPTR hp)
123 {
124 	HOOKPTR prev, next;
125 
126 	prev = hp->prev;
127 	next = hp->next;
128 	prev->next = next;
129 	next->prev = prev;
130 
131 	free(hp);
132 }
133 
134 static void
135 hookListDone(void)
136 {
137 	HOOKPTR hp;
138 
139 	while ((hp = hookList.next) != &hookList) {
140 		hookListDelete(hp);
141 	}
142 }
143 
144 /*
145  * idnHookInit - initialize Hook Management
146  */
147 void
148 idnHookInit(void) {
149 	hookListInit();
150 }
151 
152 /*
153  * idnHookDone - finalize Hook Management
154  */
155 void
156 idnHookDone(void) {
157 	if (hookHandle != NULL) {
158 		UnhookWindowsHookEx(hookHandle);
159 		hookHandle = NULL;
160 	}
161 	hookListDone();
162 }
163 
164 /*
165  * hookProc - hookprocedure, used as WH_GETMESSAGE hook
166  */
167 LRESULT CALLBACK
168 hookProc(int nCode, WPARAM wParam, LPARAM lParam) {
169 	MSG             *pMsg;
170 	HOOKPTR         pHook;
171 	struct  hostent *pHost;
172 	char            nbuff[256];
173 	char            hbuff[256];
174 
175 	if (nCode < 0) {
176 		return (CallNextHookEx(hookHandle, nCode, wParam, lParam));
177 	} else if (nCode != HC_ACTION) {
178 		return (0);
179 	}
180 	if ((pMsg = (MSG *)lParam) == NULL) {
181 		return (0);
182 	}
183 	if ((pHook = hookListSearch(pMsg->hwnd, pMsg->message)) == NULL) {
184 		return (0);
185 	}
186 
187 	/*
188 	 * Convert the Host Name
189 	 */
190 	pHost = (struct hostent *)pHook->pBuf;
191 	idnPrintf("AsyncComplete Resulting <%s>\n",
192 		  dumpName(pHost->h_name, hbuff, sizeof(hbuff)));
193 	if (idnConvRsp(pHook->ctx, pHost->h_name,
194 		       nbuff, sizeof(nbuff)) == TRUE) {
195 		idnPrintf("AsyncComplete Converted <%s>\n",
196 			  dumpName(nbuff, hbuff, sizeof(hbuff)));
197 		strcpy(pHost->h_name, nbuff);
198 	}
199 
200 	/*
201 	 * Delete target
202 	 */
203 	hookListDelete(pHook);
204 
205 	return (0);
206 }
207 
208 /*
209  * idnHook - hook async. completion message
210  */
211 BOOL
212 idnHook(HWND hWnd, u_int wMsg, char FAR *buf, idn_resconf_t ctx)
213 {
214 	if (hookHandle == NULL) {
215 		hookHandle = SetWindowsHookEx(WH_GETMESSAGE, hookProc,
216 					      NULL, GetCurrentThreadId());
217 	}
218 	if (hookHandle == NULL) {
219 		idnPrintf("idnHook: cannot set hook\n");
220 		return (FALSE);
221 	}
222 	if (hookListAppend(hWnd, wMsg, buf, ctx) != TRUE) {
223 		return (FALSE);
224 	}
225 	return (TRUE);
226 }
227