ReactOS 0.4.17-dev-966-gf06eace
dplayx_messages.c
Go to the documentation of this file.
1/* DirectPlay & DirectPlayLobby messaging 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 * NOTES
20 * o Messaging interface required for both DirectPlay and DirectPlayLobby.
21 */
22
23#include <stdarg.h>
24#include <string.h>
25#include <limits.h>
26#include "windef.h"
27#include "winbase.h"
28#include "wingdi.h"
29#include "winuser.h"
30#include "winerror.h"
31
32#include "dplayx_messages.h"
33#include "dplay_global.h"
34#include "dplayx_global.h"
35#include "name_server.h"
36#include "wine/debug.h"
37
39
40typedef struct tagMSGTHREADINFO
41{
47
48static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
50 WORD *replyCommandIds, DWORD replyCommandIdCount, void **lplpReplyMsg,
51 DWORD *lpdwMsgBodySize, void **replyMsgHeader );
52
53
54/* Create the message reception thread to allow the application to receive
55 * asynchronous message reception
56 */
58 HANDLE hDeath, HANDLE hConnRead )
59{
60 DWORD dwMsgThreadId;
61 LPMSGTHREADINFO lpThreadInfo;
63
64 lpThreadInfo = malloc( sizeof( *lpThreadInfo ) );
65 if( lpThreadInfo == NULL )
66 {
67 return 0;
68 }
69
70 /* The notify event may or may not exist. Depends if async comm or not */
71 if( hNotifyEvent &&
72 !DuplicateHandle( GetCurrentProcess(), hNotifyEvent,
73 GetCurrentProcess(), &lpThreadInfo->hNotifyEvent,
75 {
76 ERR( "Unable to duplicate event handle\n" );
77 goto error;
78 }
79
80 /* These 3 handles don't need to be duplicated because we don't keep a
81 * reference to them where they're created. They're created specifically
82 * for the message thread
83 */
84 lpThreadInfo->hStart = hStart;
85 lpThreadInfo->hDeath = hDeath;
86 lpThreadInfo->hSettingRead = hConnRead;
87
88 hThread = CreateThread( NULL, /* Security attribs */
89 0, /* Stack */
90 DPL_MSG_ThreadMain, /* Msg reception function */
91 lpThreadInfo, /* Msg reception func parameter */
92 0, /* Flags */
93 &dwMsgThreadId /* Updated with thread id */
94 );
95 if ( hThread == NULL )
96 {
97 ERR( "Unable to create msg thread\n" );
98 goto error;
99 }
100
102
103 return dwMsgThreadId;
104
105error:
106
107 free( lpThreadInfo );
108
109 return 0;
110}
111
113{
114 LPMSGTHREADINFO lpThreadInfo = lpContext;
115 DWORD dwWaitResult;
116
117 TRACE( "Msg thread created. Waiting on app startup\n" );
118
119 /* Wait to ensure that the lobby application is started w/ 1 min timeout */
120 dwWaitResult = WaitForSingleObject( lpThreadInfo->hStart, 10000 /* 10 sec */ );
121 if( dwWaitResult == WAIT_TIMEOUT )
122 {
123 FIXME( "Should signal app/wait creation failure (0x%08lx)\n", dwWaitResult );
124 goto end_of_thread;
125 }
126
127 /* Close this handle as it's not needed anymore */
128 CloseHandle( lpThreadInfo->hStart );
129 lpThreadInfo->hStart = 0;
130
131 /* Wait until the lobby knows what it is */
132 dwWaitResult = WaitForSingleObject( lpThreadInfo->hSettingRead, INFINITE );
133 if( dwWaitResult == WAIT_TIMEOUT )
134 {
135 ERR( "App Read connection setting timeout fail (0x%08lx)\n", dwWaitResult );
136 }
137
138 /* Close this handle as it's not needed anymore */
139 CloseHandle( lpThreadInfo->hSettingRead );
140 lpThreadInfo->hSettingRead = 0;
141
142 TRACE( "App created && initialized starting main message reception loop\n" );
143
144 for ( ;; )
145 {
146 MSG lobbyMsg;
147 GetMessageW( &lobbyMsg, 0, 0, 0 );
148 }
149
150end_of_thread:
151 TRACE( "Msg thread exiting!\n" );
152 free( lpThreadInfo );
153
154 return 0;
155}
156
157/* DP messaging stuff */
159 DP_MSG_REPLY_STRUCT_LIST *lpReplyStructList, WORD *replyCommandIds,
160 DWORD replyCommandIdCount )
161{
162 lpReplyStructList->replyExpected.hReceipt = CreateEventW( NULL, FALSE, FALSE, NULL );
163 lpReplyStructList->replyExpected.expectedReplies = replyCommandIds;
164 lpReplyStructList->replyExpected.expectedReplyCount = replyCommandIdCount;
165 lpReplyStructList->replyExpected.lpReplyMsg = NULL;
166 lpReplyStructList->replyExpected.dwMsgBodySize = 0;
167
168 /* Insert into the message queue while locked */
169 EnterCriticalSection( &This->lock );
170 DPQ_INSERT( This->dp2->repliesExpected, lpReplyStructList, repliesExpected );
171 LeaveCriticalSection( &This->lock );
172
173 return lpReplyStructList->replyExpected.hReceipt;
174}
175
177 WORD commandId )
178{
180 DWORD i;
181
182 EnterCriticalSection( &This->lock );
183
184 for( reply = DPQ_FIRST( This->dp2->repliesExpected ); reply;
185 reply = DPQ_NEXT( reply->repliesExpected ) )
186 {
187 for( i = 0; i < reply->replyExpected.expectedReplyCount; ++i )
188 {
189 if( reply->replyExpected.expectedReplies[ i ] == commandId )
190 {
191 DPQ_REMOVE( This->dp2->repliesExpected, reply, repliesExpected );
192 LeaveCriticalSection( &This->lock );
193 return reply;
194 }
195 }
196 }
197
198 LeaveCriticalSection( &This->lock );
199
200 return NULL;
201}
202
203static
205{
206 EnterCriticalSection( &This->lock );
207 DPQ_REMOVE( This->dp2->repliesExpected, lpReplyStructList, repliesExpected );
208 LeaveCriticalSection( &This->lock );
209}
210
211static
213 LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize, void **replyMsgHeader )
214{
215 CloseHandle( lpReplyStructList->replyExpected.hReceipt );
216
217 *lplpReplyMsg = lpReplyStructList->replyExpected.lpReplyMsg;
218 *lpdwMsgBodySize = lpReplyStructList->replyExpected.dwMsgBodySize;
219 *replyMsgHeader = lpReplyStructList->replyExpected.replyMsgHeader;
220}
221
223{
224 DWORD size = 0;
225 DWORD i;
226 for ( i = 0; i < bufferCount; ++i )
227 size += buffers[ i ].len;
228 return size;
229}
230
232{
233 LPVOID lpMsg;
234 void *msgHeader;
236 DWORD dwMsgSize;
237 HRESULT hr = DP_OK;
238
239 /* Compose dplay message envelope */
243
244 /* Compose the body of the message */
245 msgBody.dwFlags = dwFlags;
246
247 /* Send the message */
248 {
249 WORD replyCommand = DPMSGCMD_NEWPLAYERIDREPLY;
250 SGBUFFER buffers[ 2 ] = { 0 };
251 DPSP_SENDEXDATA data = { 0 };
252
253 buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize;
254 buffers[ 1 ].len = sizeof( msgBody );
255 buffers[ 1 ].pData = (UCHAR *) &msgBody;
256
257 data.lpISP = This->dp2->spData.lpISP;
258 data.dwFlags = DPSEND_GUARANTEED;
259 data.idPlayerTo = 0; /* Name server */
260 data.idPlayerFrom = 0; /* Sending from DP */
261 data.lpSendBuffers = buffers;
262 data.cBuffers = ARRAYSIZE( buffers );
263 data.dwMessageSize = DP_MSG_ComputeMessageSize( data.lpSendBuffers, data.cBuffers );
264 data.bSystemMessage = TRUE; /* Allow reply to be sent */
265
266 TRACE( "Asking for player id w/ dwFlags 0x%08lx\n",
267 msgBody.dwFlags );
268
269 hr = DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, &replyCommand, 1,
270 &lpMsg, &dwMsgSize, &msgHeader );
271 }
272
273 /* Need to examine the data and extract the new player id */
274 if( SUCCEEDED(hr) )
275 {
277
278 if ( dwMsgSize < sizeof( DPMSG_NEWPLAYERIDREPLY ) )
279 {
280 free( msgHeader );
281 free( lpMsg );
282 return DPERR_GENERIC;
283 }
284 lpcReply = lpMsg;
285
286 if ( FAILED( lpcReply->result ) )
287 {
288 hr = lpcReply->result;
289 free( msgHeader );
290 free( lpMsg );
291 return hr;
292 }
293
294 *lpdpidAllocatedId = lpcReply->dpidNewPlayerId;
295
296 TRACE( "Received reply for id = 0x%08lx\n", lpcReply->dpidNewPlayerId );
297
298 free( msgHeader );
299 free( lpMsg );
300 }
301
302 return hr;
303}
304
305static HRESULT DP_MSG_ReadString( char *data, DWORD *inoutOffset, DWORD maxSize, WCHAR **string )
306{
307 DWORD offset = *inoutOffset;
310
311 if( maxSize - offset < sizeof( WCHAR ) )
312 return DPERR_GENERIC;
313
314 maxLength = (maxSize - offset) / sizeof( WCHAR );
315 length = wcsnlen( (WCHAR *) &data[ offset ], maxLength );
316 if( length == maxLength )
317 return DPERR_GENERIC;
318
319 *string = (WCHAR *) &data[ offset ];
320 *inoutOffset = offset + (length + 1) * sizeof( WCHAR );
321
322 return DP_OK;
323}
324
325static HRESULT DP_MSG_ReadSizedString( char *data, DWORD *inoutOffset, DWORD maxSize, DWORD size,
326 WCHAR **string )
327{
328 DWORD length = size / sizeof( WCHAR ) - 1;
329 DWORD offset = *inoutOffset;
330
331 if( maxSize - offset < size )
332 return DPERR_GENERIC;
333
334 if ( ((WCHAR *) &data[ offset ])[ length ] != L'\0' )
335 return DPERR_GENERIC;
336
337 *string = (WCHAR *) &data[ offset ];
338 *inoutOffset = offset + size;
339
340 return DP_OK;
341}
342
343static HRESULT DP_MSG_ReadInteger( char *data, DWORD *inoutOffset, DWORD maxSize, DWORD size,
344 DWORD *value )
345{
346 DWORD offset = *inoutOffset;
347
348 switch ( size )
349 {
350 case 0:
351 *value = 0;
352 break;
353 case 1:
354 if( maxSize - offset < 1 )
355 return DPERR_GENERIC;
356 *value = *(BYTE *) &data[ offset ];
357 *inoutOffset = offset + 1;
358 break;
359 case 2:
360 if( maxSize - offset < 2 )
361 return DPERR_GENERIC;
362 *value = *(WORD *) &data[ offset ];
363 *inoutOffset = offset + 2;
364 break;
365 case 3:
366 if( maxSize - offset < 4 )
367 return DPERR_GENERIC;
368 *value = *(DWORD *) &data[ offset ];
369 *inoutOffset = offset + 4;
370 break;
371 }
372
373 return DP_OK;
374}
375
376HRESULT DP_MSG_ReadPackedPlayer( char *data, DWORD *inoutOffset, DWORD maxSize,
377 DPPLAYERINFO *playerInfo )
378{
379 DPLAYI_PACKEDPLAYER *packedPlayer;
380 DWORD offset = *inoutOffset;
381 HRESULT hr;
382
383 memset( playerInfo, 0, sizeof( DPPLAYERINFO ) );
384
385 if( maxSize - offset < sizeof( DPLAYI_PACKEDPLAYER ) )
386 return DPERR_GENERIC;
387 packedPlayer = (DPLAYI_PACKEDPLAYER *) &data[ offset ];
388 offset += sizeof( DPLAYI_PACKEDPLAYER );
389
390 playerInfo->flags = packedPlayer->flags;
391 playerInfo->id = packedPlayer->id;
392 playerInfo->versionOrSystemPlayerId = packedPlayer->version;
393 playerInfo->playerDataLength = packedPlayer->playerDataLength;
394 playerInfo->spDataLength = packedPlayer->spDataLength;
395 playerInfo->playerCount = packedPlayer->playerCount;
396 playerInfo->parentId = packedPlayer->parentId;
397
398 if( packedPlayer->shortNameLength )
399 {
400 hr = DP_MSG_ReadSizedString( data, &offset, maxSize, packedPlayer->shortNameLength,
401 &playerInfo->name.lpszShortName );
402 if( FAILED( hr ) )
403 return hr;
404 }
405
406 if( packedPlayer->longNameLength )
407 {
408 hr = DP_MSG_ReadSizedString( data, &offset, maxSize, packedPlayer->longNameLength,
409 &playerInfo->name.lpszLongName );
410 if( FAILED( hr ) )
411 return hr;
412 }
413
414 if( playerInfo->spDataLength )
415 {
416 if( maxSize - offset < playerInfo->spDataLength )
417 return DPERR_GENERIC;
418 playerInfo->spData = &data[ offset ];
419 offset += playerInfo->spDataLength;
420 }
421
422 if( playerInfo->playerDataLength )
423 {
424 if( maxSize - offset < playerInfo->playerDataLength )
425 return DPERR_GENERIC;
426 playerInfo->playerData = &data[ offset ];
427 offset += playerInfo->playerDataLength;
428 }
429
430 if( playerInfo->playerCount )
431 {
432 if( UINT_MAX / sizeof( DPID ) < playerInfo->playerCount )
433 return DPERR_GENERIC;
434 if( maxSize - offset < playerInfo->playerCount * sizeof( DPID ) )
435 return DPERR_GENERIC;
436 playerInfo->playerIds = (DPID *) &data[ offset ];
437 offset += playerInfo->playerCount * sizeof( DPID );
438 }
439
440 *inoutOffset = offset;
441
442 return S_OK;
443}
444
445static HRESULT DP_MSG_ReadSuperPackedPlayer( char *data, DWORD *inoutOffset, DWORD maxSize,
446 DPPLAYERINFO *playerInfo )
447{
448 DPLAYI_SUPERPACKEDPLAYER *packedPlayer;
449 DWORD offset = *inoutOffset;
450 HRESULT hr;
451
452 memset( playerInfo, 0, sizeof( DPPLAYERINFO ) );
453
454 if( maxSize - offset < sizeof( DPLAYI_SUPERPACKEDPLAYER ) )
455 return DPERR_GENERIC;
456 packedPlayer = (DPLAYI_SUPERPACKEDPLAYER *) &data[ offset ];
457 offset += sizeof( DPLAYI_SUPERPACKEDPLAYER );
458
459 playerInfo->flags = packedPlayer->flags;
460 playerInfo->id = packedPlayer->id;
461 playerInfo->versionOrSystemPlayerId = packedPlayer->versionOrSystemPlayerId;
462
464 {
465 hr = DP_MSG_ReadString( data, &offset, maxSize, &playerInfo->name.lpszShortName );
466 if ( FAILED( hr ) )
467 return hr;
468 }
469
471 {
472 hr = DP_MSG_ReadString( data, &offset, maxSize, &playerInfo->name.lpszLongName );
473 if ( FAILED( hr ) )
474 return hr;
475 }
476
477 hr = DP_MSG_ReadInteger( data, &offset, maxSize,
479 &playerInfo->playerDataLength );
480 if ( FAILED( hr ) )
481 return hr;
482
483 if( playerInfo->playerDataLength )
484 {
485 if( maxSize - offset < playerInfo->playerDataLength )
486 return DPERR_GENERIC;
487 playerInfo->playerData = &data[ offset ];
488 offset += playerInfo->playerDataLength;
489 }
490
491 hr = DP_MSG_ReadInteger( data, &offset, maxSize,
493 &playerInfo->spDataLength );
494 if ( FAILED( hr ) )
495 return hr;
496
497 if( playerInfo->spDataLength )
498 {
499 if( maxSize - offset < playerInfo->spDataLength )
500 return DPERR_GENERIC;
501 playerInfo->spData = &data[ offset ];
502 offset += playerInfo->spDataLength;
503 }
504
505 hr = DP_MSG_ReadInteger( data, &offset, maxSize,
507 &playerInfo->playerCount );
508 if ( FAILED( hr ) )
509 return hr;
510
511 if( playerInfo->playerCount )
512 {
513 if( UINT_MAX / sizeof( DPID ) < playerInfo->playerCount )
514 return DPERR_GENERIC;
515 if( maxSize - offset < playerInfo->playerCount * sizeof( DPID ) )
516 return DPERR_GENERIC;
517 playerInfo->playerIds = (DPID *) &data[ offset ];
518 offset += playerInfo->playerCount * sizeof( DPID );
519 }
520
522 {
523 if( maxSize - offset < sizeof( DPID ) )
524 return DPERR_GENERIC;
525 playerInfo->parentId = *(DPID *) &data[ offset ];
526 offset += sizeof( DPID );
527 }
528
529 hr = DP_MSG_ReadInteger( data, &offset, maxSize,
531 &playerInfo->shortcutCount );
532 if ( FAILED( hr ) )
533 return hr;
534
535 if( playerInfo->shortcutCount )
536 {
537 if( UINT_MAX / sizeof( DPID ) < playerInfo->shortcutCount )
538 return DPERR_GENERIC;
539 if( maxSize - offset < playerInfo->shortcutCount * sizeof( DPID ) )
540 return DPERR_GENERIC;
541 playerInfo->shortcutIds = (DPID *) &data[ offset ];
542 offset += playerInfo->shortcutCount * sizeof( DPID );
543 }
544
545 *inoutOffset = offset;
546
547 return S_OK;
548}
549
551{
552 LPVOID lpMsg;
554 DWORD dwMsgSize;
555 DPLAYI_PACKEDPLAYER playerInfo;
556 void *spPlayerData;
557 DWORD spPlayerDataSize;
558 void *msgHeader;
559 HRESULT hr;
560
561 hr = IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, dpidServer,
562 &spPlayerData, &spPlayerDataSize, DPSET_REMOTE );
563 if( FAILED( hr ) )
564 return hr;
565
569 msgBody.toId = 0;
570 msgBody.playerId = dpidServer;
571 msgBody.groupId = 0;
572 msgBody.createOffset = sizeof( msgBody );
573 msgBody.passwordOffset = sizeof( msgBody ) + sizeof( playerInfo ) + spPlayerDataSize;
574
575 playerInfo.size = sizeof( playerInfo ) + spPlayerDataSize;
577 playerInfo.id = dpidServer;
578 playerInfo.shortNameLength = 0;
579 playerInfo.longNameLength = 0;
580 playerInfo.spDataLength = spPlayerDataSize;
581 playerInfo.playerDataLength = 0;
582 playerInfo.playerCount = 0;
583 playerInfo.systemPlayerId = dpidServer;
584 playerInfo.fixedSize = sizeof( playerInfo );
585 playerInfo.version = DPMSGVER_DP6;
586 playerInfo.parentId = 0;
587
588 /* Send the message */
589 {
592 SGBUFFER buffers[ 6 ] = { 0 };
593 DPSP_SENDEXDATA data = { 0 };
594
595 buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize;
596 buffers[ 1 ].len = sizeof( msgBody );
597 buffers[ 1 ].pData = (UCHAR *) &msgBody;
598 buffers[ 2 ].len = sizeof( playerInfo );
599 buffers[ 2 ].pData = (UCHAR *) &playerInfo;
600 buffers[ 3 ].len = spPlayerDataSize;
601 buffers[ 3 ].pData = (UCHAR *) spPlayerData;
602 buffers[ 4 ].len = (password ? (lstrlenW( password ) + 1) : 1) * sizeof( WCHAR );
603 buffers[ 4 ].pData = (UCHAR *) (password ? password : L"");
604 buffers[ 5 ].len = sizeof( This->dp2->lpSessionDesc->dwReserved1 );
605 buffers[ 5 ].pData = (UCHAR *) &This->dp2->lpSessionDesc->dwReserved1;
606
607 data.lpISP = This->dp2->spData.lpISP;
608 data.dwFlags = DPSEND_GUARANTEED;
609 data.idPlayerTo = 0; /* Name server */
610 data.idPlayerFrom = dpidServer; /* Sending from session server */
611 data.lpSendBuffers = buffers;
612 data.cBuffers = ARRAYSIZE( buffers );
613 data.dwMessageSize = DP_MSG_ComputeMessageSize( data.lpSendBuffers, data.cBuffers );
614 data.bSystemMessage = TRUE; /* Allow reply to be sent */
615
616 TRACE( "Sending forward player request with 0x%08lx\n", dpidServer );
617
620 replyCommands, ARRAYSIZE( replyCommands ),
621 &lpMsg, &dwMsgSize, &msgHeader );
622 }
623
624 /* Need to examine the data and extract the new player id */
625 if( lpMsg != NULL )
626 {
627 DPMSG_SENDENVELOPE *envelope;
628
629 if( dwMsgSize < sizeof( DPMSG_SENDENVELOPE ) )
630 {
631 free( msgHeader );
632 free( lpMsg );
633 return DPERR_GENERIC;
634 }
635 envelope = (DPMSG_SENDENVELOPE *) lpMsg;
636
638 {
639 DPSP_MSG_SUPERENUMPLAYERSREPLY *enumPlayersReply;
641 int i;
642
643 if( dwMsgSize < sizeof( DPSP_MSG_SUPERENUMPLAYERSREPLY ) )
644 {
645 free( msgHeader );
646 free( lpMsg );
647 return DPERR_GENERIC;
648 }
649 enumPlayersReply = (DPSP_MSG_SUPERENUMPLAYERSREPLY *) envelope;
650
651 offset = enumPlayersReply->packedOffset;
652 for( i = 0; i < enumPlayersReply->playerCount; ++i )
653 {
654 DPPLAYERINFO playerInfo;
655
656 hr = DP_MSG_ReadSuperPackedPlayer( (char *) enumPlayersReply, &offset, dwMsgSize,
657 &playerInfo );
658 if( FAILED( hr ) )
659 {
660 free( msgHeader );
661 free( lpMsg );
662 return hr;
663 }
664
665 if ( playerInfo.id == dpidServer )
666 continue;
667
668 hr = DP_CreatePlayer( This, msgHeader, &playerInfo.id, &playerInfo.name,
669 playerInfo.playerData, playerInfo.playerDataLength, playerInfo.spData,
670 playerInfo.spDataLength, playerInfo.flags & ~DPLAYI_PLAYER_PLAYERLOCAL, NULL,
671 NULL, FALSE );
672 if( FAILED( hr ) )
673 {
674 free( msgHeader );
675 free( lpMsg );
676 return hr;
677 }
678 }
679 for( i = 0; i < enumPlayersReply->groupCount; ++i )
680 {
681 DPPLAYERINFO playerInfo;
682 int j;
683
684 hr = DP_MSG_ReadSuperPackedPlayer( (char *) enumPlayersReply, &offset, dwMsgSize,
685 &playerInfo );
686 if( FAILED( hr ) )
687 {
688 free( msgHeader );
689 free( lpMsg );
690 return hr;
691 }
692
693 hr = DP_CreateGroup( This, msgHeader, &playerInfo.id, &playerInfo.name,
694 playerInfo.playerData, playerInfo.playerDataLength,
695 playerInfo.flags & ~DPLAYI_PLAYER_PLAYERLOCAL, playerInfo.parentId,
696 FALSE );
697 if( FAILED( hr ) )
698 {
699 free( msgHeader );
700 free( lpMsg );
701 return hr;
702 }
703
704 for( j = 0; j < playerInfo.playerCount; ++j )
705 {
706 hr = DP_AddPlayerToGroup( This, playerInfo.id, playerInfo.playerIds[ j ] );
707 if( FAILED( hr ) )
708 {
709 free( msgHeader );
710 free( lpMsg );
711 return hr;
712 }
713 }
714 }
715 }
716 else if( envelope->wCommandId == DPMSGCMD_GETNAMETABLEREPLY )
717 {
718 FIXME( "Name Table reply received: stub\n" );
719 }
720 else if( envelope->wCommandId == DPMSGCMD_FORWARDADDPLAYERNACK )
721 {
722 DPSP_MSG_ADDFORWARDREPLY *addForwardReply;
723
724 if( dwMsgSize < sizeof( DPSP_MSG_ADDFORWARDREPLY ) )
725 {
726 free( msgHeader );
727 free( lpMsg );
728 return DPERR_GENERIC;
729 }
730 addForwardReply = (DPSP_MSG_ADDFORWARDREPLY *) envelope;
731
732 hr = addForwardReply->error;
733
734 free( msgHeader );
735 free( lpMsg );
736
737 return hr;
738 }
739 free( msgHeader );
740 free( lpMsg );
741 }
742
743 return hr;
744}
745
747 DPNAME *name, void *playerData, DWORD playerDataSize,
748 DPID systemPlayerId )
749{
750 DPSP_SENDTOGROUPEXDATA sendData;
751 DPLAYI_PACKEDPLAYER playerInfo;
752 SGBUFFER buffers[ 8 ] = { 0 };
753 UCHAR reserved[ 6 ] = { 0 };
754 DWORD shortNameLength = 0;
755 DWORD longNameLength = 0;
757 DWORD spPlayerDataSize;
758 void *spPlayerData;
759 HRESULT hr;
760
761 hr = IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, id, &spPlayerData, &spPlayerDataSize,
762 DPSET_REMOTE );
763 if( FAILED( hr ) )
764 return hr;
765
766 if ( name->lpszShortName )
767 shortNameLength = ( lstrlenW( name->lpszShortName ) + 1 ) * sizeof( WCHAR );
768
769 if ( name->lpszLongName )
770 longNameLength = ( lstrlenW( name->lpszLongName ) + 1 ) * sizeof( WCHAR );
771
772 msg.envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
773 msg.envelope.wCommandId = DPMSGCMD_CREATESESSION;
774 msg.envelope.wVersion = DPMSGVER_DP6;
775 msg.toId = 0;
776 msg.playerId = id;
777 msg.groupId = 0;
778 msg.createOffset = sizeof( DPMSG_CREATESESSION );
779 msg.passwordOffset = 0;
780
781 playerInfo.size = sizeof( DPLAYI_PACKEDPLAYER ) + shortNameLength + longNameLength
782 + spPlayerDataSize + playerDataSize;
783 playerInfo.flags = flags;
784 playerInfo.id = id;
785 playerInfo.shortNameLength = shortNameLength;
786 playerInfo.longNameLength = longNameLength;
787 playerInfo.spDataLength = spPlayerDataSize;
788 playerInfo.playerDataLength = playerDataSize;
789 playerInfo.playerCount = 0;
790 playerInfo.systemPlayerId = systemPlayerId;
791 playerInfo.fixedSize = sizeof( DPLAYI_PACKEDPLAYER );
792 playerInfo.version = DPMSGVER_DP6;
793 playerInfo.parentId = 0;
794
795 buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize;
796 buffers[ 0 ].pData = NULL;
797 buffers[ 1 ].len = sizeof( msg );
798 buffers[ 1 ].pData = (UCHAR *)&msg;
799 buffers[ 2 ].len = sizeof( playerInfo );
800 buffers[ 2 ].pData = (UCHAR *)&playerInfo;
801 buffers[ 3 ].len = shortNameLength;
802 buffers[ 3 ].pData = (UCHAR *)name->lpszShortName;
803 buffers[ 4 ].len = longNameLength;
804 buffers[ 4 ].pData = (UCHAR *)name->lpszLongName;
805 buffers[ 5 ].len = spPlayerDataSize;
806 buffers[ 5 ].pData = spPlayerData;
807 buffers[ 6 ].len = playerDataSize;
808 buffers[ 6 ].pData = playerData;
809 buffers[ 7 ].len = sizeof( reserved );
810 buffers[ 7 ].pData = reserved;
811
812 sendData.lpISP = This->dp2->spData.lpISP;
813 sendData.dwFlags = DPSEND_GUARANTEED;
814 sendData.idGroupTo = toId;
815 sendData.idPlayerFrom = This->dp2->systemPlayerId;
816 sendData.lpSendBuffers = buffers;
817 sendData.cBuffers = ARRAYSIZE( buffers );
818 sendData.dwMessageSize = DP_MSG_ComputeMessageSize( sendData.lpSendBuffers, sendData.cBuffers );
819 sendData.dwPriority = 0;
820 sendData.dwTimeout = 0;
821 sendData.lpDPContext = NULL;
822 sendData.lpdwSPMsgID = NULL;
823
824 hr = (*This->dp2->spData.lpCB->SendToGroupEx)( &sendData );
825 if( FAILED( hr ) )
826 {
827 ERR( "SendToGroupEx failed: %s\n", DPLAYX_HresultToString( hr ) );
828 return hr;
829 }
830
831 return DP_OK;
832}
833
835{
836 DPSP_SENDTOGROUPEXDATA sendData;
838 SGBUFFER buffers[ 2 ] = { 0 };
839 HRESULT hr;
840
841 msg.envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
842 msg.envelope.wCommandId = DPMSGCMD_ADDPLAYERTOGROUP;
843 msg.envelope.wVersion = DPMSGVER_DP6;
844 msg.toId = 0;
845 msg.playerId = playerId;
846 msg.groupId = groupId;
847 msg.createOffset = 0;
848 msg.passwordOffset = 0;
849
850 buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize;
851 buffers[ 0 ].pData = NULL;
852 buffers[ 1 ].len = sizeof( msg );
853 buffers[ 1 ].pData = (UCHAR *)&msg;
854
855 sendData.lpISP = This->dp2->spData.lpISP;
856 sendData.dwFlags = DPSEND_GUARANTEED;
857 sendData.idGroupTo = toId;
858 sendData.idPlayerFrom = This->dp2->systemPlayerId;
859 sendData.lpSendBuffers = buffers;
860 sendData.cBuffers = ARRAYSIZE( buffers );
861 sendData.dwMessageSize = DP_MSG_ComputeMessageSize( sendData.lpSendBuffers, sendData.cBuffers );
862 sendData.dwPriority = 0;
863 sendData.dwTimeout = 0;
864 sendData.lpDPContext = NULL;
865 sendData.lpdwSPMsgID = NULL;
866
867 hr = (*This->dp2->spData.lpCB->SendToGroupEx)( &sendData );
868 if( FAILED( hr ) )
869 {
870 ERR( "SendToGroupEx failed: %s\n", DPLAYX_HresultToString( hr ) );
871 return hr;
872 }
873
874 return DP_OK;
875}
876
878{
879 SGBUFFER buffers[ 2 ] = { 0 };
880 DPSP_SENDEXDATA sendData;
882 HRESULT hr;
883
884 msg.envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
885 msg.envelope.wCommandId = DPMSGCMD_PINGREPLY;
886 msg.envelope.wVersion = DPMSGVER_DP6;
887 msg.fromId = fromId;
888 msg.tickCount = tickCount;
889
890 buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize;
891 buffers[ 0 ].pData = NULL;
892 buffers[ 1 ].len = sizeof( msg );
893 buffers[ 1 ].pData = (UCHAR *)&msg;
894
895 sendData.lpISP = This->dp2->spData.lpISP;
896 sendData.dwFlags = 0;
897 sendData.idPlayerTo = toId;
898 sendData.idPlayerFrom = This->dp2->systemPlayerId;
899 sendData.lpSendBuffers = buffers;
900 sendData.cBuffers = ARRAYSIZE( buffers );
901 sendData.dwMessageSize = DP_MSG_ComputeMessageSize( sendData.lpSendBuffers, sendData.cBuffers );
902 sendData.dwPriority = 0;
903 sendData.dwTimeout = 0;
904 sendData.lpDPContext = NULL;
905 sendData.lpdwSPMsgID = NULL;
906 sendData.bSystemMessage = TRUE;
907
908 hr = (*This->dp2->spData.lpCB->SendEx)( &sendData );
909 if( FAILED( hr ) )
910 {
911 ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) );
912 return hr;
913 }
914
915 return DP_OK;
916}
917
919{
920 SGBUFFER buffers[ 2 ] = { 0 };
922 DPSP_SENDEXDATA sendData;
923 HRESULT hr;
924
925 msg.envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
926 msg.envelope.wCommandId = DPMSGCMD_ADDFORWARDACK;
927 msg.envelope.wVersion = DPMSGVER_DP6;
928 msg.id = id;
929
930 buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize;
931 buffers[ 0 ].pData = NULL;
932 buffers[ 1 ].len = sizeof( msg );
933 buffers[ 1 ].pData = (UCHAR *)&msg;
934
935 sendData.lpISP = This->dp2->spData.lpISP;
936 sendData.dwFlags = DPSEND_GUARANTEED;
937 sendData.idPlayerTo = 0;
938 sendData.idPlayerFrom = This->dp2->systemPlayerId;
939 sendData.lpSendBuffers = buffers;
940 sendData.cBuffers = ARRAYSIZE( buffers );
941 sendData.dwMessageSize = DP_MSG_ComputeMessageSize( sendData.lpSendBuffers, sendData.cBuffers );
942 sendData.dwPriority = 0;
943 sendData.dwTimeout = 0;
944 sendData.lpDPContext = NULL;
945 sendData.lpdwSPMsgID = NULL;
946 sendData.bSystemMessage = TRUE;
947
948 hr = (*This->dp2->spData.lpCB->SendEx)( &sendData );
949 if( FAILED( hr ) )
950 {
951 ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) );
952 return hr;
953 }
954
955 return DP_OK;
956}
957
958/* Queue up a structure indicating that we want a reply of type wReplyCommandId. DPlay does
959 * not seem to offer any way of uniquely differentiating between replies of the same type
960 * relative to the request sent. There is an implicit assumption that there will be no
961 * ordering issues on sends and receives from the opposite machine. No wonder MS is not
962 * a networking company.
963 */
965 WORD *replyCommandIds, DWORD replyCommandIdCount, void **lplpReplyMsg,
966 DWORD *lpdwMsgBodySize, void **replyMsgHeader )
967{
968 HRESULT hr;
969 HANDLE hMsgReceipt;
970 DP_MSG_REPLY_STRUCT_LIST replyStructList;
971 DWORD dwWaitReturn;
972
973 /* Setup for receipt */
974 hMsgReceipt = DP_MSG_BuildAndLinkReplyStruct( This, &replyStructList,
975 replyCommandIds, replyCommandIdCount );
976
977 TRACE( "Sending msg and expecting reply within %lu ticks\n", dwWaitTime );
978 hr = (*This->dp2->spData.lpCB->SendEx)( lpData );
979
980 if( FAILED(hr) )
981 {
982 ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) );
983 DP_MSG_UnlinkReplyStruct( This, &replyStructList );
984 DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize, replyMsgHeader );
985 return hr;
986 }
987
988 /* The reply message will trigger the hMsgReceipt event effectively switching
989 * control back to this thread. See DP_MSG_ReplyReceived.
990 */
991 dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime );
992 if( dwWaitReturn != WAIT_OBJECT_0 )
993 {
994 ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
995 DP_MSG_UnlinkReplyStruct( This, &replyStructList );
996 DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize, replyMsgHeader );
997 return DPERR_TIMEOUT;
998 }
999
1000 /* Clean Up */
1001 DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize, replyMsgHeader );
1002 return DP_OK;
1003}
1004
1005/* Determine if there is a matching request for this incoming message and then copy
1006 * all important data. It is quite silly to have to copy the message, but the documents
1007 * indicate that a copy is taken. Silly really.
1008 */
1009void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, const void *lpcMsgBody,
1010 DWORD dwMsgBodySize, const void *msgHeader )
1011{
1012 LPDP_MSG_REPLY_STRUCT_LIST lpReplyList;
1013
1014#if 0
1015 if( wCommandId == DPMSGCMD_FORWARDADDPLAYER )
1016 {
1017 DebugBreak();
1018 }
1019#endif
1020
1021 /* Find, and immediately remove (to avoid double triggering), the appropriate entry. Call locked to
1022 * avoid problems.
1023 */
1024 lpReplyList = DP_MSG_FindAndUnlinkReplyStruct( This, wCommandId );
1025
1026 if( lpReplyList != NULL )
1027 {
1028 lpReplyList->replyExpected.dwMsgBodySize = dwMsgBodySize;
1029 lpReplyList->replyExpected.lpReplyMsg = malloc( dwMsgBodySize );
1030 lpReplyList->replyExpected.replyMsgHeader = malloc( This->dp2->spData.dwSPHeaderSize );
1031 CopyMemory( lpReplyList->replyExpected.lpReplyMsg,
1032 lpcMsgBody, dwMsgBodySize );
1034 msgHeader, This->dp2->spData.dwSPHeaderSize );
1035
1036 /* Signal the thread which sent the message that it has a reply */
1037 SetEvent( lpReplyList->replyExpected.hReceipt );
1038 }
1039 else
1040 {
1041 ERR( "No receipt event set - only expecting in reply mode\n" );
1042 DebugBreak();
1043 }
1044}
1045
1047{
1048 LPVOID lpMsg;
1049 void *msgHeader;
1050 DPMSG_SENDENVELOPE msgBody;
1051 DWORD dwMsgSize;
1052
1053 /* Compose dplay message envelope */
1054 msgBody.dwMagic = DPMSGMAGIC_DPLAYMSG;
1056 msgBody.wVersion = DPMSGVER_DP6;
1057
1058 /* Send the message to ourselves */
1059 {
1060 WORD replyCommand = DPMSGCMD_JUSTENVELOPE;
1061 SGBUFFER buffers[ 2 ] = { 0 };
1062 DPSP_SENDEXDATA data = { 0 };
1063
1064 buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize;
1065 buffers[ 1 ].len = sizeof( msgBody );
1066 buffers[ 1 ].pData = (UCHAR *) &msgBody;
1067
1068 data.lpISP = This->dp2->spData.lpISP;
1069 data.dwFlags = 0;
1070 data.idPlayerTo = dpidSelf; /* Sending to session server */
1071 data.idPlayerFrom = 0; /* Sending from session server */
1072 data.lpSendBuffers = buffers;
1073 data.cBuffers = ARRAYSIZE( buffers );
1074 data.dwMessageSize = DP_MSG_ComputeMessageSize( data.lpSendBuffers, data.cBuffers );
1075 data.bSystemMessage = TRUE; /* Allow reply to be sent */
1076
1079 &replyCommand, 1,
1080 &lpMsg, &dwMsgSize, &msgHeader );
1081 }
1082}
#define msg(x)
Definition: auth_time.c:54
#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 ARRAYSIZE(a)
Definition: cat.c:25
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define GetCurrentProcess()
Definition: compat.h:759
#define CALLBACK
Definition: compat.h:35
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
_ACRTIMP size_t __cdecl wcsnlen(const wchar_t *, size_t)
Definition: wcs.c:2925
#define UINT_MAX
Definition: limits.h:27
HRESULT DP_CreatePlayer(IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags, HANDLE hEvent, struct PlayerData **playerData, BOOL bAnsi)
Definition: dplay.c:1823
HRESULT DP_AddPlayerToGroup(IDirectPlayImpl *This, DPID group, DPID player)
Definition: dplay.c:1210
HRESULT DP_CreateGroup(IDirectPlayImpl *This, void *msgHeader, const DPID *lpid, const DPNAME *lpName, void *data, DWORD dataSize, DWORD dwFlags, DPID idParent, BOOL bAnsi)
Definition: dplay.c:1386
#define DPERR_GENERIC
Definition: dplay.h:99
#define DPSET_REMOTE
Definition: dplay.h:1056
#define DPSEND_GUARANTEED
Definition: dplay.h:1038
#define DPERR_TIMEOUT
Definition: dplay.h:116
#define DP_OK
Definition: dplay.h:88
DWORD DPID
Definition: dplay.h:158
#define IDirectPlaySP_GetSPPlayerData(p, a, b, c, d)
Definition: dplaysp.h:104
#define DPLAYI_PLAYER_PLAYERLOCAL
Definition: dplaysp.h:59
#define DPLAYI_PLAYER_SYSPLAYER
Definition: dplaysp.h:56
LPCSTR DPLAYX_HresultToString(HRESULT hr)
HRESULT DP_MSG_ReadPackedPlayer(char *data, DWORD *inoutOffset, DWORD maxSize, DPPLAYERINFO *playerInfo)
static HRESULT DP_MSG_ReadString(char *data, DWORD *inoutOffset, DWORD maxSize, WCHAR **string)
struct tagMSGTHREADINFO * LPMSGTHREADINFO
void DP_MSG_ReplyReceived(IDirectPlayImpl *This, WORD wCommandId, const void *lpcMsgBody, DWORD dwMsgBodySize, const void *msgHeader)
static void DP_MSG_UnlinkReplyStruct(IDirectPlayImpl *This, DP_MSG_REPLY_STRUCT_LIST *lpReplyStructList)
static HRESULT DP_MSG_ReadSizedString(char *data, DWORD *inoutOffset, DWORD maxSize, DWORD size, WCHAR **string)
static void DP_MSG_CleanReplyStruct(LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList, LPVOID *lplpReplyMsg, LPDWORD lpdwMsgBodySize, void **replyMsgHeader)
struct tagMSGTHREADINFO MSGTHREADINFO
HRESULT DP_MSG_SendAddPlayerToGroup(IDirectPlayImpl *This, DPID toId, DPID playerId, DPID groupId)
HRESULT DP_MSG_ForwardPlayerCreation(IDirectPlayImpl *This, DPID dpidServer, WCHAR *password)
DWORD CreateLobbyMessageReceptionThread(HANDLE hNotifyEvent, HANDLE hStart, HANDLE hDeath, HANDLE hConnRead)
static HRESULT DP_MSG_ExpectReply(IDirectPlayImpl *This, DPSP_SENDEXDATA *data, DWORD dwWaitTime, WORD *replyCommandIds, DWORD replyCommandIdCount, void **lplpReplyMsg, DWORD *lpdwMsgBodySize, void **replyMsgHeader)
void DP_MSG_ToSelf(IDirectPlayImpl *This, DPID dpidSelf)
HRESULT DP_MSG_SendPingReply(IDirectPlayImpl *This, DPID toId, DPID fromId, DWORD tickCount)
HRESULT DP_MSG_SendAddForwardAck(IDirectPlayImpl *This, DPID id)
static HRESULT DP_MSG_ReadSuperPackedPlayer(char *data, DWORD *inoutOffset, DWORD maxSize, DPPLAYERINFO *playerInfo)
static DP_MSG_REPLY_STRUCT_LIST * DP_MSG_FindAndUnlinkReplyStruct(IDirectPlayImpl *This, WORD commandId)
HRESULT DP_MSG_SendRequestPlayerId(IDirectPlayImpl *This, DWORD dwFlags, DPID *lpdpidAllocatedId)
DWORD DP_MSG_ComputeMessageSize(SGBUFFER *buffers, DWORD bufferCount)
static HRESULT DP_MSG_ReadInteger(char *data, DWORD *inoutOffset, DWORD maxSize, DWORD size, DWORD *value)
static DWORD CALLBACK DPL_MSG_ThreadMain(LPVOID lpContext)
static HANDLE DP_MSG_BuildAndLinkReplyStruct(IDirectPlayImpl *This, DP_MSG_REPLY_STRUCT_LIST *lpReplyStructList, WORD *replyCommandIds, DWORD replyCommandIdCount)
HRESULT DP_MSG_SendCreatePlayer(IDirectPlayImpl *This, DPID toId, DPID id, DWORD flags, DPNAME *name, void *playerData, DWORD playerDataSize, DPID systemPlayerId)
#define DPLAYI_SUPERPACKEDPLAYER_PLAYER_DATA_LENGTH_SIZE(mask)
#define DPMSGCMD_SUPERENUMPLAYERSREPLY
#define DPMSGVER_DP6
#define DPMSGCMD_CREATESESSION
#define DPLAYI_SUPERPACKEDPLAYER_SHORT_NAME_PRESENT
#define DPMSGCMD_GETNAMETABLEREPLY
#define DPLAYI_SUPERPACKEDPLAYER_SP_DATA_LENGTH_SIZE(mask)
struct tagDPMSG_CREATESESSION DPMSG_CREATESESSION
#define DPMSG_WAIT_5_SECS
#define DPLAYI_SUPERPACKEDPLAYER_LONG_NAME_PRESENT
#define DPMSGCMD_PINGREPLY
#define DPMSGCMD_ADDPLAYERTOGROUP
#define DPMSGCMD_FORWARDADDPLAYER
#define DPLAYI_SUPERPACKEDPLAYER_PARENT_ID_PRESENT
#define DPMSGCMD_REQUESTNEWPLAYERID
#define DPMSGCMD_ADDFORWARDACK
#define DPMSGCMD_NEWPLAYERIDREPLY
#define DPMSG_WAIT_60_SECS
#define DPMSGCMD_JUSTENVELOPE
#define DPMSGCMD_FORWARDADDPLAYERNACK
#define DPLAYI_SUPERPACKEDPLAYER_SHORTCUT_COUNT_SIZE(mask)
#define DPMSGMAGIC_DPLAYMSG
#define DPLAYI_SUPERPACKEDPLAYER_PLAYER_COUNT_SIZE(mask)
#define DPMSG_DEFAULT_WAIT_TIME
#define DPQ_INSERT(a, b, c)
Definition: dplayx_queue.h:34
#define DPQ_NEXT(elem)
Definition: dplayx_queue.h:67
#define DPQ_FIRST(head)
Definition: dplayx_queue.h:61
#define DPQ_REMOVE(head, elm, field)
Definition: dplayx_queue.h:82
#define L(x)
Definition: resources.c:13
r reserved
Definition: btrfs.c:3006
#define INFINITE
Definition: serial.h:102
unsigned short WORD
Definition: ntddk_ex.h:93
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
GLintptr offset
Definition: glext.h:5920
GLsizei maxLength
Definition: glext.h:6877
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum GLsizei len
Definition: glext.h:6722
const GLuint * buffers
Definition: glext.h:5916
GLuint id
Definition: glext.h:5910
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
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 GLint GLint j
Definition: glfuncs.h:250
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define CopyMemory
Definition: minwinbase.h:29
#define error(str)
Definition: mkdosfs.c:1605
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
HANDLE hThread
Definition: wizard.c:28
short WCHAR
Definition: pedump.c:58
BOOL WINAPI GetMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
DWORD playerDataLength
DPID * shortcutIds
DWORD versionOrSystemPlayerId
Definition: name.c:39
DPMSG_SENDENVELOPE envelope
DPMSG_SENDENVELOPE envelope
LPWSTR lpszLongName
Definition: dplay.h:199
LPWSTR lpszShortName
Definition: dplay.h:193
LPDWORD lpdwSPMsgID
Definition: dplaysp.h:248
IDirectPlaySP * lpISP
Definition: dplaysp.h:238
DWORD dwMessageSize
Definition: dplaysp.h:244
LPSGBUFFER lpSendBuffers
Definition: dplaysp.h:242
LPVOID lpDPContext
Definition: dplaysp.h:247
LPSGBUFFER lpSendBuffers
Definition: dplaysp.h:258
IDirectPlaySP * lpISP
Definition: dplaysp.h:254
DP_MSG_REPLY_STRUCT replyExpected
Definition: dplay_global.h:73
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
unsigned char UCHAR
Definition: typedefs.h:53
uint32_t * LPDWORD
Definition: typedefs.h:59
Definition: pdh_main.c:64
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI DebugBreak(void)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define DUPLICATE_SAME_ACCESS
unsigned char BYTE
Definition: xxhash.c:193