1 /* dplayx.dll global data implementation.
3 * Copyright 1999 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
9 /* NOTE: Methods that begin with DPLAYX_ are used for dealing with
10 * dplayx.dll data which is accessible from all processes.
14 #include "debugtools.h"
17 #include "heap.h" /* Really shouldn't be using those HEAP_strdupA interfaces should I? */
19 #include "dplayx_global.h"
21 DEFAULT_DEBUG_CHANNEL(dplay);
23 /* FIXME: Need to do all that fun other dll referencing type of stuff */
24 /* FIXME: Need to allocate a giant static area */
26 /* Static data for all processes */
27 static LPSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
28 static HANDLE hDplayxSema;
32 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX sema\n" ); \
33 WaitForSingleObject( hDplayxSema, INFINITE ); TRACE( "Through wait\n" )
34 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
35 TRACE( "DPLAYX Sema released\n" ); /* FIXME: Is this correct? */
38 /* HACK for simple global data right now */
39 enum { numSupportedLobbies = 32 };
40 typedef struct tagDirectPlayLobbyData
43 DPSESSIONDESC2 sessionDesc;
50 DWORD dwAppLaunchedFromID;
51 } DirectPlayLobbyData, *lpDirectPlayLobbyData;
53 static DirectPlayLobbyData lobbyData[ numSupportedLobbies ];
55 /* Function prototypes */
56 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, lpDirectPlayLobbyData* dplData );
57 void DPLAYX_InitializeLobbyDataEntry( lpDirectPlayLobbyData lpData );
63 /***************************************************************************
64 * Called to initialize the global data. This will only be used on the
66 ***************************************************************************/
67 void DPLAYX_ConstructData(void)
71 TRACE( "DPLAYX dll loaded - construct called\n" );
73 /* Create a semahopre to block access to DPLAYX global data structs
74 It starts unblocked, and allows up to 65000 users blocked on it. Seems reasonable
76 hDplayxSema = CreateSemaphoreA( NULL, 1, 65000, lpszDplayxSemaName );
80 /* Really don't have any choice but to continue... */
81 ERR( "Semaphore creation error 0x%08lx\n", GetLastError() );
84 /* Set all lobbies to be "empty" */
85 for( i=0; i < numSupportedLobbies; i++ )
87 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
92 /***************************************************************************
93 * Called to destroy all global data. This will only be used on the
94 * unloading of the dll
95 ***************************************************************************/
96 void DPLAYX_DestructData(void)
98 TRACE( "DPLAYX dll unloaded - destruct called\n" );
100 /* delete the semaphore */
101 CloseHandle( hDplayxSema );
105 void DPLAYX_InitializeLobbyDataEntry( lpDirectPlayLobbyData lpData )
107 ZeroMemory( lpData, sizeof( *lpData ) );
109 /* Set the handle to a better invalid value */
110 lpData->hReceiveEvent = INVALID_HANDLE_VALUE;
113 /* NOTE: This must be called with the semaphore aquired.
114 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
115 * is only valid if TRUE is returned.
117 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, lpDirectPlayLobbyData* lplpDplData )
125 dwAppID = GetCurrentProcessId();
126 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
129 for( i=0; i < numSupportedLobbies; i++ )
131 if( lobbyData[ i ].dwAppID == dwAppID )
133 /* This process is lobbied */
134 *lplpDplData = &lobbyData[ i ];
142 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
143 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent )
147 /* 0 is the marker for unused application data slots */
153 DPLAYX_AquireSemaphore();
155 /* Find an empty space in the list and insert the data */
156 for( i=0; i < numSupportedLobbies; i++ )
158 if( lobbyData[ i ].dwAppID == 0 )
160 /* This process is now lobbied */
161 lobbyData[ i ].dwAppID = dwAppID;
162 lobbyData[ i ].hReceiveEvent = hReceiveEvent;
163 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
165 DPLAYX_ReleaseSemaphore();
170 DPLAYX_ReleaseSemaphore();
174 /* I'm not sure when I'm going to need this, but here it is */
175 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
179 DPLAYX_AquireSemaphore();
181 /* Find an empty space in the list and insert the data */
182 for( i=0; i < numSupportedLobbies; i++ )
184 if( lobbyData[ i ].dwAppID == dwAppID )
186 /* Mark this entry unused */
187 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
189 DPLAYX_ReleaseSemaphore();
194 DPLAYX_ReleaseSemaphore();
195 ERR( "Unable to find global entry for application\n" );
199 HRESULT DPLAYX_GetConnectionSettingsA
202 LPDWORD lpdwDataSize )
204 lpDirectPlayLobbyData lpDplData;
205 LPDPLCONNECTION lpDplConnection;
207 /* Verify buffer size */
208 if ( ( lpData == NULL ) ||
209 ( *lpdwDataSize < sizeof( DPLCONNECTION ) )
212 *lpdwDataSize = sizeof( DPLCONNECTION );
214 return DPERR_BUFFERTOOSMALL;
217 DPLAYX_AquireSemaphore();
219 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
221 DPLAYX_ReleaseSemaphore();
222 return DPERR_NOTLOBBIED;
225 /* Copy the information */
226 lpDplConnection = (LPDPLCONNECTION)lpData;
228 /* Copy everything we've got into here */
229 /* Need to actually store the stuff here. Check if we've already allocated each field first. */
230 lpDplConnection->dwSize = sizeof( DPLCONNECTION );
231 lpDplConnection->dwFlags = lpDplData->dwConnFlags;
233 /* Copy LPDPSESSIONDESC2 struct */
234 lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->sessionDesc ) );
235 memcpy( lpDplConnection->lpSessionDesc, &lpDplData->sessionDesc, sizeof( lpDplData->sessionDesc ) );
237 if( lpDplData->sessionDesc.sess.lpszSessionNameA )
239 lpDplConnection->lpSessionDesc->sess.lpszSessionNameA =
240 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.sess.lpszSessionNameA );
243 if( lpDplData->sessionDesc.pass.lpszPasswordA )
245 lpDplConnection->lpSessionDesc->pass.lpszPasswordA =
246 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.pass.lpszPasswordA );
249 lpDplConnection->lpSessionDesc->dwReserved1 = lpDplData->sessionDesc.dwReserved1;
250 lpDplConnection->lpSessionDesc->dwReserved2 = lpDplData->sessionDesc.dwReserved2;
252 /* Copy DPNAME struct - seems to be optional - check for existance first */
253 lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->playerName ) );
254 memcpy( lpDplConnection->lpPlayerName, &(lpDplData->playerName), sizeof( lpDplData->playerName ) );
256 if( lpDplData->playerName.psn.lpszShortNameA )
258 lpDplConnection->lpPlayerName->psn.lpszShortNameA =
259 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.psn.lpszShortNameA );
262 if( lpDplData->playerName.pln.lpszLongNameA )
264 lpDplConnection->lpPlayerName->pln.lpszLongNameA =
265 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.pln.lpszLongNameA );
268 memcpy( &lpDplConnection->guidSP, &lpDplData->guidSP, sizeof( lpDplData->guidSP ) );
270 lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->dwAddressSize );
271 memcpy( lpDplConnection->lpAddress, lpDplData->lpAddress, lpDplData->dwAddressSize );
273 lpDplConnection->dwAddressSize = lpDplData->dwAddressSize;
275 /* FIXME: Send a message - or only the first time? */
277 DPLAYX_ReleaseSemaphore();
282 HRESULT DPLAYX_GetConnectionSettingsW
285 LPDWORD lpdwDataSize )
287 lpDirectPlayLobbyData lpDplData;
288 LPDPLCONNECTION lpDplConnection;
290 /* Verify buffer size */
291 if ( ( lpData == NULL ) ||
292 ( *lpdwDataSize < sizeof( DPLCONNECTION ) )
295 *lpdwDataSize = sizeof( DPLCONNECTION );
297 return DPERR_BUFFERTOOSMALL;
300 DPLAYX_AquireSemaphore();
302 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
304 DPLAYX_ReleaseSemaphore();
305 return DPERR_NOTLOBBIED;
308 /* Copy the information */
309 lpDplConnection = (LPDPLCONNECTION)lpData;
311 /* Copy everything we've got into here */
312 /* Need to actually store the stuff here. Check if we've already allocated each field first. */
313 lpDplConnection->dwSize = sizeof( DPLCONNECTION );
314 lpDplConnection->dwFlags = lpDplData->dwConnFlags;
316 /* Copy LPDPSESSIONDESC2 struct */
317 lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->sessionDesc ) );
318 memcpy( lpDplConnection->lpSessionDesc, &lpDplData->sessionDesc, sizeof( lpDplData->sessionDesc ) );
320 if( lpDplData->sessionDesc.sess.lpszSessionName )
322 lpDplConnection->lpSessionDesc->sess.lpszSessionName =
323 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.sess.lpszSessionName );
326 if( lpDplData->sessionDesc.pass.lpszPassword )
328 lpDplConnection->lpSessionDesc->pass.lpszPassword =
329 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.pass.lpszPassword );
332 lpDplConnection->lpSessionDesc->dwReserved1 = lpDplData->sessionDesc.dwReserved1;
333 lpDplConnection->lpSessionDesc->dwReserved2 = lpDplData->sessionDesc.dwReserved2;
335 /* Copy DPNAME struct - seems to be optional - check for existance first */
336 lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->playerName ) );
337 memcpy( lpDplConnection->lpPlayerName, &(lpDplData->playerName), sizeof( lpDplData->playerName ) );
339 if( lpDplData->playerName.psn.lpszShortName )
341 lpDplConnection->lpPlayerName->psn.lpszShortName =
342 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.psn.lpszShortName );
345 if( lpDplData->playerName.pln.lpszLongName )
347 lpDplConnection->lpPlayerName->pln.lpszLongName =
348 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.pln.lpszLongName );
351 memcpy( &lpDplConnection->guidSP, &lpDplData->guidSP, sizeof( lpDplData->guidSP ) );
353 lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->dwAddressSize );
354 memcpy( lpDplConnection->lpAddress, lpDplData->lpAddress, lpDplData->dwAddressSize );
356 lpDplConnection->dwAddressSize = lpDplData->dwAddressSize;
358 /* FIXME: Send a message - or only the first time? */
360 DPLAYX_ReleaseSemaphore();
366 HRESULT DPLAYX_SetConnectionSettingsA
369 LPDPLCONNECTION lpConn )
371 lpDirectPlayLobbyData lpDplData;
373 /* Paramater check */
374 if( dwFlags || !lpConn )
376 ERR("invalid parameters.\n");
377 return DPERR_INVALIDPARAMS;
380 /* Store information */
381 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
383 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
384 lpConn->dwSize, sizeof( DPLCONNECTION ) );
386 return DPERR_INVALIDPARAMS;
391 dwAppID = GetCurrentProcessId();
394 DPLAYX_AquireSemaphore();
396 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
398 /* FIXME: Create a new entry for this dwAppID? */
399 DPLAYX_ReleaseSemaphore();
401 return DPERR_GENERIC;
404 /* Store information */
405 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
407 DPLAYX_ReleaseSemaphore();
409 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
410 lpConn->dwSize, sizeof( DPLCONNECTION ) );
412 return DPERR_INVALIDPARAMS;
415 /* Need to investigate the lpConn->lpSessionDesc to figure out
416 * what type of session we need to join/create.
418 if( (!lpConn->lpSessionDesc ) ||
419 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
422 DPLAYX_ReleaseSemaphore();
424 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
425 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
427 return DPERR_INVALIDPARAMS;
430 /* FIXME: How do I store this stuff so that it can be read by all processes? Static area? What about strings? Ewww...large global shared */
432 /* Need to actually store the stuff here. Check if we've already allocated each field first. */
433 lpDplData->dwConnFlags = lpConn->dwFlags;
435 /* Copy LPDPSESSIONDESC2 struct - this is required */
436 memcpy( &lpDplData->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
438 /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
439 if( lpConn->lpSessionDesc->sess.lpszSessionNameA )
440 lpDplData->sessionDesc.sess.lpszSessionNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionNameA );
442 lpDplData->sessionDesc.sess.lpszSessionNameA = NULL;
444 if( lpConn->lpSessionDesc->pass.lpszPasswordA )
445 lpDplData->sessionDesc.pass.lpszPasswordA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPasswordA );
447 lpDplData->sessionDesc.pass.lpszPasswordA = NULL;
449 lpDplData->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
450 lpDplData->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
452 /* Copy DPNAME struct - seems to be optional - check for existance first */
453 if( lpConn->lpPlayerName )
455 memcpy( &lpDplData->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
457 if( lpConn->lpPlayerName->psn.lpszShortNameA )
458 lpDplData->playerName.psn.lpszShortNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortNameA );
460 if( lpConn->lpPlayerName->pln.lpszLongNameA )
461 lpDplData->playerName.pln.lpszLongNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongNameA );
465 memcpy( &lpDplData->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
467 lpDplData->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
468 memcpy( lpDplData->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
470 lpDplData->dwAddressSize = lpConn->dwAddressSize;
472 /* FIXME: Send a message - I think */
474 DPLAYX_ReleaseSemaphore();
479 HRESULT DPLAYX_SetConnectionSettingsW
482 LPDPLCONNECTION lpConn )
484 lpDirectPlayLobbyData lpDplData;
486 /* Paramater check */
487 if( dwFlags || !lpConn )
489 ERR("invalid parameters.\n");
490 return DPERR_INVALIDPARAMS;
493 /* Store information */
494 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
496 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
497 lpConn->dwSize, sizeof( DPLCONNECTION ) );
499 return DPERR_INVALIDPARAMS;
504 dwAppID = GetCurrentProcessId();
507 DPLAYX_AquireSemaphore();
509 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
511 DPLAYX_ReleaseSemaphore();
512 return DPERR_NOTLOBBIED;
515 /* Need to investigate the lpConn->lpSessionDesc to figure out
516 * what type of session we need to join/create.
518 if( (!lpConn->lpSessionDesc ) ||
519 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
522 DPLAYX_ReleaseSemaphore();
524 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
525 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
527 return DPERR_INVALIDPARAMS;
530 /* FIXME: How do I store this stuff so that it can be read by all processes? Static area? What about strings? Ewww...large global shared */
532 /* Need to actually store the stuff here. Check if we've already allocated each field first. */
533 lpDplData->dwConnFlags = lpConn->dwFlags;
535 /* Copy LPDPSESSIONDESC2 struct - this is required */
536 memcpy( &lpDplData->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
538 /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
539 if( lpConn->lpSessionDesc->sess.lpszSessionName )
540 lpDplData->sessionDesc.sess.lpszSessionName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionName );
542 lpDplData->sessionDesc.sess.lpszSessionName = NULL;
544 if( lpConn->lpSessionDesc->pass.lpszPassword )
545 lpDplData->sessionDesc.pass.lpszPassword = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPassword );
547 lpDplData->sessionDesc.pass.lpszPassword = NULL;
549 lpDplData->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
550 lpDplData->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
552 /* Copy DPNAME struct - seems to be optional - check for existance first */
553 if( lpConn->lpPlayerName )
555 memcpy( &lpDplData->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
557 if( lpConn->lpPlayerName->psn.lpszShortName )
558 lpDplData->playerName.psn.lpszShortName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortName );
560 if( lpConn->lpPlayerName->pln.lpszLongName )
561 lpDplData->playerName.pln.lpszLongName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongName );
565 memcpy( &lpDplData->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
567 lpDplData->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
568 memcpy( lpDplData->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
570 lpDplData->dwAddressSize = lpConn->dwAddressSize;
572 /* FIXME: Send a message - I think */
574 DPLAYX_ReleaseSemaphore();
579 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
580 with the correct string printed in the case where the HRESULT is not
581 known. You'll just get the last hr passed in printed. This can change
582 over time if this method is used alot :) */
583 LPCSTR DPLAYX_HresultToString(HRESULT hr)
585 static char szTempStr[12];
591 case DPERR_ALREADYINITIALIZED:
592 return "DPERR_ALREADYINITIALIZED";
593 case DPERR_ACCESSDENIED:
594 return "DPERR_ACCESSDENIED";
595 case DPERR_ACTIVEPLAYERS:
596 return "DPERR_ACTIVEPLAYERS";
597 case DPERR_BUFFERTOOSMALL:
598 return "DPERR_BUFFERTOOSMALL";
599 case DPERR_CANTADDPLAYER:
600 return "DPERR_CANTADDPLAYER";
601 case DPERR_CANTCREATEGROUP:
602 return "DPERR_CANTCREATEGROUP";
603 case DPERR_CANTCREATEPLAYER:
604 return "DPERR_CANTCREATEPLAYER";
605 case DPERR_CANTCREATESESSION:
606 return "DPERR_CANTCREATESESSION";
607 case DPERR_CAPSNOTAVAILABLEYET:
608 return "DPERR_CAPSNOTAVAILABLEYET";
609 case DPERR_EXCEPTION:
610 return "DPERR_EXCEPTION";
612 return "DPERR_GENERIC";
613 case DPERR_INVALIDFLAGS:
614 return "DPERR_INVALIDFLAGS";
615 case DPERR_INVALIDOBJECT:
616 return "DPERR_INVALIDOBJECT";
617 case DPERR_INVALIDPARAMS:
618 return "DPERR_INVALIDPARAMS";
619 case DPERR_INVALIDPLAYER:
620 return "DPERR_INVALIDPLAYER";
621 case DPERR_INVALIDGROUP:
622 return "DPERR_INVALIDGROUP";
624 return "DPERR_NOCAPS";
625 case DPERR_NOCONNECTION:
626 return "DPERR_NOCONNECTION";
627 case DPERR_OUTOFMEMORY:
628 return "DPERR_OUTOFMEMORY";
629 case DPERR_NOMESSAGES:
630 return "DPERR_NOMESSAGES";
631 case DPERR_NONAMESERVERFOUND:
632 return "DPERR_NONAMESERVERFOUND";
633 case DPERR_NOPLAYERS:
634 return "DPERR_NOPLAYERS";
635 case DPERR_NOSESSIONS:
636 return "DPERR_NOSESSIONS";
637 /* This one isn't defined yet in WINE sources. I don't know the value
639 return "DPERR_PENDING";
641 case DPERR_SENDTOOBIG:
642 return "DPERR_SENDTOOBIG";
644 return "DPERR_TIMEOUT";
645 case DPERR_UNAVAILABLE:
646 return "DPERR_UNAVAILABLE";
647 case DPERR_UNSUPPORTED:
648 return "DPERR_UNSUPPORTED";
651 case DPERR_USERCANCEL:
652 return "DPERR_USERCANCEL";
653 case DPERR_NOINTERFACE:
654 return "DPERR_NOINTERFACE";
655 case DPERR_CANNOTCREATESERVER:
656 return "DPERR_CANNOTCREATESERVER";
657 case DPERR_PLAYERLOST:
658 return "DPERR_PLAYERLOST";
659 case DPERR_SESSIONLOST:
660 return "DPERR_SESSIONLOST";
661 case DPERR_UNINITIALIZED:
662 return "DPERR_UNINITIALIZED";
663 case DPERR_NONEWPLAYERS:
664 return "DPERR_NONEWPLAYERS";
665 case DPERR_INVALIDPASSWORD:
666 return "DPERR_INVALIDPASSWORD";
667 case DPERR_CONNECTING:
668 return "DPERR_CONNECTING";
669 case DPERR_CONNECTIONLOST:
670 return "DPERR_CONNECTIONLOST";
671 case DPERR_UNKNOWNMESSAGE:
672 return "DPERR_UNKNOWNMESSAGE";
673 case DPERR_CANCELFAILED:
674 return "DPERR_CANCELFAILED";
675 case DPERR_INVALIDPRIORITY:
676 return "DPERR_INVALIDPRIORITY";
677 case DPERR_NOTHANDLED:
678 return "DPERR_NOTHANDLED";
679 case DPERR_CANCELLED:
680 return "DPERR_CANCELLED";
682 return "DPERR_ABORTED";
683 case DPERR_BUFFERTOOLARGE:
684 return "DPERR_BUFFERTOOLARGE";
685 case DPERR_CANTCREATEPROCESS:
686 return "DPERR_CANTCREATEPROCESS";
687 case DPERR_APPNOTSTARTED:
688 return "DPERR_APPNOTSTARTED";
689 case DPERR_INVALIDINTERFACE:
690 return "DPERR_INVALIDINTERFACE";
691 case DPERR_NOSERVICEPROVIDER:
692 return "DPERR_NOSERVICEPROVIDER";
693 case DPERR_UNKNOWNAPPLICATION:
694 return "DPERR_UNKNOWNAPPLICATION";
695 case DPERR_NOTLOBBIED:
696 return "DPERR_NOTLOBBIED";
697 case DPERR_SERVICEPROVIDERLOADED:
698 return "DPERR_SERVICEPROVIDERLOADED";
699 case DPERR_ALREADYREGISTERED:
700 return "DPERR_ALREADYREGISTERED";
701 case DPERR_NOTREGISTERED:
702 return "DPERR_NOTREGISTERED";
703 case DPERR_AUTHENTICATIONFAILED:
704 return "DPERR_AUTHENTICATIONFAILED";
705 case DPERR_CANTLOADSSPI:
706 return "DPERR_CANTLOADSSPI";
707 case DPERR_ENCRYPTIONFAILED:
708 return "DPERR_ENCRYPTIONFAILED";
709 case DPERR_SIGNFAILED:
710 return "DPERR_SIGNFAILED";
711 case DPERR_CANTLOADSECURITYPACKAGE:
712 return "DPERR_CANTLOADSECURITYPACKAGE";
713 case DPERR_ENCRYPTIONNOTSUPPORTED:
714 return "DPERR_ENCRYPTIONNOTSUPPORTED";
715 case DPERR_CANTLOADCAPI:
716 return "DPERR_CANTLOADCAPI";
717 case DPERR_NOTLOGGEDIN:
718 return "DPERR_NOTLOGGEDIN";
719 case DPERR_LOGONDENIED:
720 return "DPERR_LOGONDENIED";
722 /* For errors not in the list, return HRESULT as a string
723 This part is not thread safe */
724 WARN( "Unknown error 0x%08lx\n", hr );
725 sprintf( szTempStr, "0x%08lx", hr );