ReactOS 0.4.17-dev-966-gf06eace
name_server.c
Go to the documentation of this file.
1/* DPLAYX.DLL name server implementation
2 *
3 * Copyright 2000-2001 - Peter Hunnisett
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20/* NOTE: Methods with the NS_ prefix are name server methods */
21
22#include <stdarg.h>
23#include <string.h>
24
25#include "windef.h"
26#include "winbase.h"
27#include "winnls.h"
28#include "wine/debug.h"
29#include "mmsystem.h"
30
31#include "dplayx_global.h"
32#include "name_server.h"
33#include "wine/dplaysp.h"
34#include "dplayx_messages.h"
35#include "dplayx_queue.h"
36
37/* FIXME: Need to create a crit section, store and use it */
38
40
41#ifdef __REACTOS__
42/* wcsnlen is only exported from msvcrt for NT6+ */
43static inline size_t compat_wcsnlen(const WCHAR *str, size_t size)
44{
45 size_t i;
46 for (i = 0; i < size && str[i]; ++i);
47 return i;
48}
49#define wcsnlen compat_wcsnlen
50#endif
51
52/* NS specific structures */
54{
55 DPQ_ENTRY(NSCacheData) walkNext;
57
58 LONG ref;
59
60 DWORD dwTime; /* Time at which data was last known valid */
62 LPDPSESSIONDESC2 dataA;
63
64 LPVOID lpNSAddrHdr;
65
66};
68
69struct NSCache
70{
71 lpNSCacheData present; /* keep track of what is to be looked at when walking */
72
73 DPQ_HEAD(NSCacheData) walkFirst;
75
76 BOOL bNsIsLocal;
77 LPVOID lpLocalAddrHdr; /* FIXME: Not yet used */
78 LPVOID lpRemoteAddrHdr; /* FIXME: Not yet used */
79};
80typedef struct NSCache NSCache, *lpNSCache;
81
82/* Function prototypes */
83static DPQ_DECL_DELETECB( cbReleaseNSNode, lpNSCacheData );
84
85/* Name Server functions
86 * ---------------------
87 */
89{
90 lpNSCache lpCache = (lpNSCache)lpNSInfo;
91
92 lpCache->bNsIsLocal = TRUE;
93}
94
95static DPQ_DECL_COMPARECB( cbUglyPig, GUID )
96{
97 return IsEqualGUID( elem1, elem2 );
98}
99
100/* Store the given NS remote address for future reference */
102 DWORD dwHdrSize,
104 DWORD msgSize,
105 LPVOID lpNSInfo )
106{
107 lpNSCache lpCache = (lpNSCache)lpNSInfo;
108 lpNSCacheData lpCacheNode;
109 DPSESSIONDESC2 dpsd;
110 DWORD maxNameLength;
111 DWORD nameLength;
112
113 TRACE( "%p, %p, %p\n", lpcNSAddrHdr, lpcMsg, lpNSInfo );
114
115 if ( msgSize < sizeof( DPMSG_ENUMSESSIONSREPLY ) + sizeof( WCHAR ) )
116 return;
117
118 maxNameLength = (msgSize - sizeof( DPMSG_ENUMSESSIONSREPLY )) / sizeof( WCHAR );
119 nameLength = wcsnlen( (WCHAR *) (lpcMsg + 1), maxNameLength );
120 if ( nameLength == maxNameLength )
121 return;
122
123 /* See if we can find this session. If we can, remove it as it's a dup */
124 DPQ_REMOVE_ENTRY_CB( lpCache->first, next, data->guidInstance, cbUglyPig,
125 lpcMsg->sd.guidInstance, lpCacheNode );
126
127 if( lpCacheNode != NULL )
128 {
129 TRACE( "Duplicate session entry for %s removed - updated version kept\n",
130 debugstr_guid( &lpCacheNode->data->guidInstance ) );
131 cbReleaseNSNode( lpCacheNode );
132 }
133
134 /* Add this to the list */
135 lpCacheNode = calloc( 1, sizeof( *lpCacheNode ) );
136
137 if( lpCacheNode == NULL )
138 {
139 ERR( "no memory for NS node\n" );
140 return;
141 }
142
143 lpCacheNode->lpNSAddrHdr = malloc( dwHdrSize );
144 CopyMemory( lpCacheNode->lpNSAddrHdr, lpcNSAddrHdr, dwHdrSize );
145
146 dpsd = lpcMsg->sd;
147 dpsd.lpszSessionName = (WCHAR *) (lpcMsg + 1);
148 dpsd.lpszPassword = NULL;
149
150 lpCacheNode->data = DP_DuplicateSessionDesc( &dpsd, FALSE, FALSE );
151
152 if( lpCacheNode->data == NULL )
153 {
154 ERR( "no memory for SESSIONDESC2\n" );
155 free( lpCacheNode );
156 return;
157 }
158
159 lpCacheNode->dataA = DP_DuplicateSessionDesc( &dpsd, TRUE, FALSE );
160
161 if( lpCacheNode->dataA == NULL )
162 {
163 ERR( "no memory for SESSIONDESC2\n" );
164 free( lpCacheNode->data );
165 free( lpCacheNode );
166 return;
167 }
168
169 lpCacheNode->ref = 1;
170 lpCacheNode->dwTime = timeGetTime();
171
172 DPQ_INSERT(lpCache->first, lpCacheNode, next );
173
174 /* Use this message as an opportunity to weed out any old sessions so
175 * that we don't enum them again
176 */
177 NS_PruneSessionCache( lpNSInfo );
178}
179
180void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize )
181{
182 lpNSCache lpCache = (lpNSCache)lpNSInfo;
183
184 lpCache->lpLocalAddrHdr = malloc( dwHdrSize );
185
186 CopyMemory( lpCache->lpLocalAddrHdr, lpHdr, dwHdrSize );
187}
188
189/* This function is responsible for sending a request for all other known
190 nameservers to send us what sessions they have registered locally
191 */
195 const SPINITDATA *lpSpData )
196
197{
200 DWORD passwordSize = 0;
201
202 TRACE( "enumerating for guid %s\n", debugstr_guid( lpcGuid ) );
203
204 if ( password )
205 passwordSize = (wcslen( password ) + 1) * sizeof( WCHAR );
206
207 data.dwMessageSize = lpSpData->dwSPHeaderSize + sizeof( *lpMsg ) + passwordSize;
208 data.lpMessage = calloc( 1, data.dwMessageSize );
209 data.lpISP = lpSpData->lpISP;
210 data.bReturnStatus = (dwFlags & DPENUMSESSIONS_RETURNSTATUS) != 0;
211
212
213 lpMsg = (LPDPMSG_ENUMSESSIONSREQUEST)(((BYTE*)data.lpMessage)+lpSpData->dwSPHeaderSize);
214
215 /* Setup EnumSession request message */
219
220 lpMsg->passwordOffset = password ? sizeof( DPMSG_ENUMSESSIONSREQUEST ) : 0;
221 lpMsg->dwFlags = dwFlags;
222
223 lpMsg->guidApplication = *lpcGuid;
224
225 memcpy( lpMsg + 1, password, passwordSize );
226
227 return (lpSpData->lpCB->EnumSessions)( &data );
228}
229
230/* Delete a name server node which has been allocated on the heap */
231static DPQ_DECL_DELETECB( cbReleaseNSNode, lpNSCacheData )
232{
234
235 if ( ref )
236 return;
237
238 free( elem->dataA );
239 free( elem->data );
240 free( elem->lpNSAddrHdr );
241 free( elem );
242}
243
244/* Render all data in a session cache invalid */
246{
247 lpNSCache lpCache = (lpNSCache)lpNSInfo;
248
249 if( lpCache == NULL )
250 {
251 ERR( ": invalidate nonexistent cache\n" );
252 return;
253 }
254
255 DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbReleaseNSNode );
256
257 lpCache->bNsIsLocal = FALSE;
258
259}
260
261/* Create and initialize a session cache */
263{
264 lpNSCache lpCache = calloc( 1, sizeof( *lpCache ) );
265
266 *lplpNSInfo = lpCache;
267
268 if( lpCache == NULL )
269 {
270 return FALSE;
271 }
272
273 DPQ_INIT(lpCache->walkFirst);
274 DPQ_INIT(lpCache->first);
275 lpCache->present = NULL;
276
277 lpCache->bNsIsLocal = FALSE;
278
279 return TRUE;
280}
281
282/* Delete a session cache */
284{
287}
288
289/* Reinitialize the present pointer for this cache */
291{
292 NSCache *cache = (NSCache *) lpNSInfo;
294
295 DPQ_DELETEQ( cache->walkFirst, walkNext, lpNSCacheData, cbReleaseNSNode );
296
297 for( data = DPQ_FIRST( cache->first ); data; data = DPQ_NEXT( data->next ) )
298 {
299 InterlockedIncrement( &data->ref );
300 DPQ_INSERT( cache->walkFirst, data, walkNext );
301 }
302
303 ((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->walkFirst.lpQHFirst;
304}
305
306LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo, void **spMessageHeader, BOOL ansi )
307{
308 LPDPSESSIONDESC2 lpSessionDesc;
309 lpNSCache lpCache = (lpNSCache)lpNSInfo;
310
311 /* Test for end of the list */
312 if( lpCache->present == NULL )
313 {
314 return NULL;
315 }
316
317 lpSessionDesc = ansi ? lpCache->present->dataA : lpCache->present->data;
318
319 if( spMessageHeader )
320 *spMessageHeader = lpCache->present->lpNSAddrHdr;
321
322 /* Advance tracking pointer */
323 lpCache->present = lpCache->present->walkNext.lpQNext;
324
325 return lpSessionDesc;
326}
327
328/* This method should check to see if there are any sessions which are
329 * older than the criteria. If so, just delete that information.
330 */
331/* FIXME: This needs to be called by some periodic timer */
333{
334 lpNSCache lpCache = lpNSInfo;
335
336 const DWORD dwPresentTime = timeGetTime();
337 const DWORD dwPrunePeriod = DPMSG_WAIT_60_SECS; /* is 60 secs enough? */
338
339 /* This silly little algorithm is based on the fact we keep entries in
340 * the queue in a time based order. It also assumes that it is not possible
341 * to wrap around over yourself (which is not unreasonable).
342 * The if statements verify if the first entry in the queue is less
343 * than dwPrunePeriod old depending on the "clock" roll over.
344 */
345 for( ;; )
346 {
347 lpNSCacheData lpFirstData;
348
349 if( DPQ_IS_EMPTY(lpCache->first) )
350 {
351 /* Nothing to prune */
352 break;
353 }
354
355 /* Deal with time in a wrap around safe manner - unsigned arithmetic.
356 * Check the difference in time */
357 if( (dwPresentTime - (DPQ_FIRST(lpCache->first)->dwTime)) < dwPrunePeriod )
358 {
359 /* First entry has not expired yet; don't prune */
360 break;
361 }
362
363 lpFirstData = DPQ_FIRST(lpCache->first);
364 DPQ_REMOVE( lpCache->first, DPQ_FIRST(lpCache->first), next );
365 cbReleaseNSNode( lpFirstData );
366 }
367
368}
369
370/* NAME SERVER Message stuff */
371void NS_ReplyToEnumSessionsRequest( const void *lpcMsg, void **lplpReplyData, DWORD *lpdwReplySize,
372 IDirectPlayImpl *lpDP )
373{
375 DWORD dwVariableSize;
376 DWORD dwVariableLen;
377 /* LPCDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpcMsg; */
378
379 /* FIXME: Should handle ANSI or WIDECHAR input. Currently just ANSI input */
380 FIXME( ": few fixed + need to check request for response, might need UNICODE input ability.\n" );
381
382 dwVariableLen = MultiByteToWideChar( CP_ACP, 0,
384 -1, NULL, 0 );
385 dwVariableSize = dwVariableLen * sizeof( WCHAR );
386
387 *lpdwReplySize = lpDP->dp2->spData.dwSPHeaderSize +
388 sizeof( *rmsg ) + dwVariableSize;
389 *lplpReplyData = calloc( 1, *lpdwReplySize );
390
391 rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)*lplpReplyData +
392 lpDP->dp2->spData.dwSPHeaderSize);
393
397
398 CopyMemory( &rmsg->sd, lpDP->dp2->lpSessionDesc,
399 lpDP->dp2->lpSessionDesc->dwSize );
400 rmsg->dwUnknown = 0x0000005c;
402 (LPWSTR)(rmsg+1), dwVariableLen );
403}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
static UCHAR password[]
Definition: bcrypt.c:520
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CP_ACP
Definition: compat.h:109
#define MultiByteToWideChar
Definition: compat.h:110
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
_ACRTIMP size_t __cdecl wcsnlen(const wchar_t *, size_t)
Definition: wcs.c:2925
DWORD WINAPI timeGetTime(void)
Definition: time.c:466
DPSESSIONDESC2 * DP_DuplicateSessionDesc(const DPSESSIONDESC2 *src, BOOL dstAnsi, BOOL srcAnsi)
Definition: dplay.c:4579
#define DPENUMSESSIONS_RETURNSTATUS
Definition: dplay.h:1021
struct tagDPMSG_ENUMSESSIONSREQUEST * LPDPMSG_ENUMSESSIONSREQUEST
#define DPMSGVER_DP6
#define DPMSGCMD_ENUMSESSIONSREQUEST
struct tagDPMSG_ENUMSESSIONSREPLY DPMSG_ENUMSESSIONSREPLY
struct tagDPMSG_ENUMSESSIONSREPLY * LPDPMSG_ENUMSESSIONSREPLY
#define DPMSGCMD_ENUMSESSIONSREPLY
#define DPMSG_WAIT_60_SECS
struct tagDPMSG_ENUMSESSIONSREQUEST DPMSG_ENUMSESSIONSREQUEST
#define DPMSGMAGIC_DPLAYMSG
#define DPQ_INIT(head)
Definition: dplayx_queue.h:54
#define DPQ_INSERT(a, b, c)
Definition: dplayx_queue.h:34
#define DPQ_ENTRY(type)
Definition: dplayx_queue.h:45
#define DPQ_DECL_COMPARECB(name, type)
Definition: dplayx_queue.h:151
#define DPQ_HEAD(type)
Definition: dplayx_queue.h:39
#define DPQ_REMOVE_ENTRY_CB(head, elm, field, compare_cb, fieldToCompare, rc)
Definition: dplayx_queue.h:181
#define DPQ_NEXT(elem)
Definition: dplayx_queue.h:67
#define DPQ_FIRST(head)
Definition: dplayx_queue.h:61
#define DPQ_DELETEQ(head, field, type, df)
Definition: dplayx_queue.h:199
#define DPQ_IS_EMPTY(head)
Definition: dplayx_queue.h:64
#define DPQ_REMOVE(head, elm, field)
Definition: dplayx_queue.h:82
#define DPQ_DECL_DELETECB(name, type)
Definition: dplayx_queue.h:211
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
const GLint * first
Definition: glext.h:5794
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define debugstr_guid
Definition: kernel32.h:35
#define CopyMemory
Definition: minwinbase.h:29
CONST void * LPCVOID
Definition: minwindef.h:164
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static size_t elem
Definition: string.c:71
HRESULT NS_SendSessionRequestBroadcast(LPCGUID lpcGuid, DWORD dwFlags, WCHAR *password, const SPINITDATA *lpSpData)
Definition: name_server.c:192
void NS_SetLocalComputerAsNameServer(LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo)
Definition: name_server.c:88
BOOL NS_InitializeSessionCache(LPVOID *lplpNSInfo)
Definition: name_server.c:262
void NS_InvalidateSessionCache(LPVOID lpNSInfo)
Definition: name_server.c:245
void NS_ReplyToEnumSessionsRequest(const void *lpcMsg, void **lplpReplyData, DWORD *lpdwReplySize, IDirectPlayImpl *lpDP)
Definition: name_server.c:371
void NS_AddRemoteComputerAsNameServer(LPCVOID lpcNSAddrHdr, DWORD dwHdrSize, LPCDPMSG_ENUMSESSIONSREPLY lpcMsg, DWORD msgSize, LPVOID lpNSInfo)
Definition: name_server.c:101
void NS_ResetSessionEnumeration(LPVOID lpNSInfo)
Definition: name_server.c:290
void NS_PruneSessionCache(LPVOID lpNSInfo)
Definition: name_server.c:332
struct NSCache * lpNSCache
Definition: name_server.c:80
LPDPSESSIONDESC2 NS_WalkSessions(LPVOID lpNSInfo, void **spMessageHeader, BOOL ansi)
Definition: name_server.c:306
struct NSCacheData * lpNSCacheData
Definition: name_server.c:67
void NS_SetLocalAddr(LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize)
Definition: name_server.c:180
void NS_DeleteSessionCache(LPVOID lpNSInfo)
Definition: name_server.c:283
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
static unsigned __int64 next
Definition: rand_nt.c:6
#define calloc
Definition: rosglue.h:14
const WCHAR * str
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwTime
Definition: solitaire.cpp:27
DirectPlay2Data * dp2
Definition: dplay_global.h:225
lpNSCacheData present
Definition: name_server.c:71
Definition: cache.c:41
Definition: send.c:48
DPMSG_SENDENVELOPE envelope
LPSTR lpszSessionNameA
Definition: dplay.h:244
LPWSTR lpszPassword
Definition: dplay.h:249
LPWSTR lpszSessionName
Definition: dplay.h:243
GUID guidInstance
Definition: dplay.h:234
DWORD dwSize
Definition: dplay.h:232
LPDPSP_ENUMSESSIONS EnumSessions
Definition: dplaysp.h:326
LPDPSESSIONDESC2 lpSessionDesc
Definition: dplay_global.h:189
LPDPSP_SPCALLBACKS lpCB
Definition: dplaysp.h:354
IDirectPlaySP * lpISP
Definition: dplaysp.h:355
DWORD dwSPHeaderSize
Definition: dplaysp.h:360
uint16_t * LPWSTR
Definition: typedefs.h:56
static UINT WPARAM LPARAM BOOL ansi
Definition: misc.c:135
unsigned char BYTE
Definition: xxhash.c:193