1/*$Header: /p/tcsh/cvsroot/tcsh/win32/nt.who.c,v 1.6 2006/03/05 08:59:36 amold Exp $*/
2/*-
3 * Copyright (c) 1980, 1991 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 *    may be used to endorse or promote products derived from this software
16 *    without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31/*
32 * nt.who.c: Support for who-like functions, using NETBIOS
33 * -amol
34 *
35 */
36#define WIN32_LEAN_AND_MEAN
37#include <windows.h>
38#include <nb30.h>
39#include <stdio.h>
40#include "sh.h"
41
42
43typedef struct _ASTAT_ {
44	ADAPTER_STATUS adapt;
45	NAME_BUFFER    NameBuff [10];
46} ASTAT;
47
48typedef struct _n_ctx {
49	NCB ncb;
50	u_char usr_name[NCBNAMSZ];
51	u_char mach_name[NCBNAMSZ];
52} ncb_ctx;
53
54typedef UCHAR (APIENTRY *netbios_func)(NCB *);
55
56
57static netbios_func p_Netbios =0;
58static int ginited = 0;
59
60static CRITICAL_SECTION nb_critter;
61static HMODULE hnetapi;
62
63
64extern int add_to_who_list(u_char *,u_char*);
65
66void init_netbios(void ) {
67
68
69	if (!ginited) {
70		hnetapi = LoadLibrary("NETAPI32.DLL");
71		if (!hnetapi)
72			return ;
73
74		p_Netbios = (netbios_func)GetProcAddress(hnetapi,"Netbios");
75
76		if (!p_Netbios )
77			return ;
78		ginited = 1;
79	}
80	InitializeCriticalSection(&nb_critter);
81}
82void cleanup_netbios(void) {
83	if (hnetapi){
84		DeleteCriticalSection(&nb_critter);
85		FreeLibrary(hnetapi);
86	}
87}
88void CALLBACK complete_ncb( NCB * p_ncb) {
89
90	int count,i;
91	ADAPTER_STATUS *p_ad;
92	ASTAT *pas;
93	char *p1;
94	ncb_ctx *ctx = (ncb_ctx *)p_ncb;
95
96	if (p_ncb->ncb_retcode)
97		goto end;
98
99	__try {
100
101		EnterCriticalSection(&nb_critter);
102		pas = ((ASTAT*) p_ncb->ncb_buffer);
103		p_ad = &pas->adapt;
104
105		count = p_ad->name_count;
106
107		if (count <=0 )
108			__leave;
109
110		if (ctx->usr_name[0] == 0) { //any user on given machine
111			for(i=0; i<count;i++) {
112				if (pas->NameBuff[i].name[15] == 03) { // unique name
113					if (!strncmp((char*)(pas->NameBuff[i].name),
114							 	 (char*)(p_ncb->ncb_callname),
115								 NCBNAMSZ)) {
116						continue;
117					}
118					else {
119						p1 = strchr((char*)(pas->NameBuff[i].name),' ');
120						if (p1)
121							*p1 = 0;
122						else
123							pas->NameBuff[i].name[15]= 0;
124						add_to_who_list(pas->NameBuff[i].name,
125								ctx->mach_name);
126						break;
127					}
128				}
129			}
130		}
131		else if (ctx->mach_name[0] == 0)  { // given user on any machine
132			for(i=0; i<count;i++) {
133				if (pas->NameBuff[i].name[15] == 03) { // unique name
134					if (!strncmp((char*)(pas->NameBuff[i].name),
135								 (char*)(p_ncb->ncb_callname),
136								 NCBNAMSZ))
137						continue;
138					else {
139						p1 = strchr((char*)(pas->NameBuff[i].name),' ');
140						if (p1)
141							*p1 = 0;
142						else
143							pas->NameBuff[i].name[15]= 0;
144
145						add_to_who_list(ctx->usr_name, pas->NameBuff[i].name);
146
147						break;
148					}
149				}
150			}
151		}
152		else { // specific user on specific machine
153			for(i=0; i<count;i++) {
154				if (pas->NameBuff[i].name[15] == 03) { // unique name
155					// skip computer name
156					if (!strncmp((char*)(pas->NameBuff[i].name),
157								 (char*)(p_ncb->ncb_callname),
158								 NCBNAMSZ)) {
159						continue;
160					}
161					else if (!strncmp((char*)(pas->NameBuff[i].name),
162									  (char*)(ctx->usr_name),
163									  lstrlen((char*)ctx->usr_name))) {
164						p1 = strchr((char*)pas->NameBuff[i].name,' ');
165						if (p1)
166							*p1 = 0;
167						else
168							pas->NameBuff[i].name[15]= 0;
169						add_to_who_list(pas->NameBuff[i].name,ctx->mach_name);
170						break;
171					}
172				}
173			}
174		}
175	}
176	__except(GetExceptionCode()) {
177		;
178	}
179	LeaveCriticalSection(&nb_critter);
180end:
181	heap_free(p_ncb->ncb_buffer);
182	heap_free(p_ncb);
183	return;
184}
185void start_ncbs (Char **vp) {
186
187	ncb_ctx * p_ctx;
188	NCB *Ncb;
189	Char **namevec = vp;
190	char *p1,*p2,*nb_name;
191	UCHAR uRetCode;
192	ASTAT *Adapter;
193
194	if (!ginited) {
195		init_netbios();
196	}
197	if (!ginited)
198		return;
199
200	for (namevec = vp;*namevec != NULL;namevec +=2) {
201
202		p_ctx = heap_alloc(sizeof(ncb_ctx));
203		Adapter = heap_alloc(sizeof(ASTAT));
204
205		Ncb = (NCB*)p_ctx;
206
207		memset( Ncb, 0, sizeof(NCB) );
208
209		Ncb->ncb_command = NCBRESET;
210		Ncb->ncb_lana_num = 0;
211
212		uRetCode = p_Netbios( Ncb );
213
214		if(uRetCode)
215			goto cleanup;
216
217		if  ((**namevec == '\0' ) || ( *(namevec +1) ==  NULL) ||
218				(**(namevec +1) == '\0') )
219			break;
220
221
222		p1 = short2str(*namevec);
223		if (!_stricmp(p1,"any") ) {
224			p_ctx->usr_name[0] = 0;
225		}
226		else {
227			StringCbCopy((char*)p_ctx->usr_name,sizeof(p_ctx->usr_name),p1);
228		}
229		p1 = (char*)&(p_ctx->usr_name[0]);
230
231		p2 = short2str(*(namevec+1));
232		//
233		// If machine is not "any", make it the callname
234		//
235		if (!_stricmp(p2,"any") ) {
236			p_ctx->mach_name[0] = 0;
237			nb_name = p1;
238		}
239		else {
240			StringCbCopy((char*)p_ctx->mach_name,sizeof(p_ctx->mach_name),p2);
241			nb_name = p2;
242		}
243
244		// do not permit any any
245		//
246		if( (p_ctx->mach_name[0] == 0) && (p_ctx->usr_name[0] == 0) )
247			goto cleanup;
248
249
250
251		memset( Ncb, 0, sizeof (NCB) );
252
253		Ncb->ncb_command = NCBASTAT | ASYNCH;
254		Ncb->ncb_lana_num = 0;
255
256		memset(Ncb->ncb_callname,' ',sizeof(Ncb->ncb_callname));
257
258		Ncb->ncb_callname[15]=03;
259
260		memcpy(Ncb->ncb_callname,nb_name,lstrlen(nb_name));
261
262		Ncb->ncb_buffer = (u_char *) Adapter;
263		Ncb->ncb_length = sizeof(*Adapter);
264
265		Ncb->ncb_post = complete_ncb;
266
267		uRetCode = p_Netbios( Ncb );
268	}
269	return;
270
271cleanup:
272	heap_free(Adapter);
273	heap_free(p_ctx);
274	return;
275}
276