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();
223 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
224 return DPERR_NOTLOBBIED;
227 /* Copy the information */
228 lpDplConnection = (LPDPLCONNECTION)lpData;
230 /* Copy everything we've got into here */
231 /* Need to actually store the stuff here. Check if we've already allocated each field first. */
232 lpDplConnection->dwSize = sizeof( DPLCONNECTION );
233 lpDplConnection->dwFlags = lpDplData->dwConnFlags;
235 /* Copy LPDPSESSIONDESC2 struct */
236 lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->sessionDesc ) );
237 memcpy( lpDplConnection->lpSessionDesc, &lpDplData->sessionDesc, sizeof( lpDplData->sessionDesc ) );
239 if( lpDplData->sessionDesc.sess.lpszSessionNameA )
241 lpDplConnection->lpSessionDesc->sess.lpszSessionNameA =
242 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.sess.lpszSessionNameA );
245 if( lpDplData->sessionDesc.pass.lpszPasswordA )
247 lpDplConnection->lpSessionDesc->pass.lpszPasswordA =
248 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.pass.lpszPasswordA );
251 lpDplConnection->lpSessionDesc->dwReserved1 = lpDplData->sessionDesc.dwReserved1;
252 lpDplConnection->lpSessionDesc->dwReserved2 = lpDplData->sessionDesc.dwReserved2;
254 /* Copy DPNAME struct - seems to be optional - check for existance first */
255 lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->playerName ) );
256 memcpy( lpDplConnection->lpPlayerName, &(lpDplData->playerName), sizeof( lpDplData->playerName ) );
258 if( lpDplData->playerName.psn.lpszShortNameA )
260 lpDplConnection->lpPlayerName->psn.lpszShortNameA =
261 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.psn.lpszShortNameA );
264 if( lpDplData->playerName.pln.lpszLongNameA )
266 lpDplConnection->lpPlayerName->pln.lpszLongNameA =
267 HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.pln.lpszLongNameA );
270 memcpy( &lpDplConnection->guidSP, &lpDplData->guidSP, sizeof( lpDplData->guidSP ) );
272 lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->dwAddressSize );
273 memcpy( lpDplConnection->lpAddress, lpDplData->lpAddress, lpDplData->dwAddressSize );
275 lpDplConnection->dwAddressSize = lpDplData->dwAddressSize;
277 /* FIXME: Send a message - or only the first time? */
279 DPLAYX_ReleaseSemaphore();
284 HRESULT DPLAYX_GetConnectionSettingsW
287 LPDWORD lpdwDataSize )
289 lpDirectPlayLobbyData lpDplData;
290 LPDPLCONNECTION lpDplConnection;
292 /* Verify buffer size */
293 if ( ( lpData == NULL ) ||
294 ( *lpdwDataSize < sizeof( DPLCONNECTION ) )
297 *lpdwDataSize = sizeof( DPLCONNECTION );
299 return DPERR_BUFFERTOOSMALL;
302 DPLAYX_AquireSemaphore();
304 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
306 DPLAYX_ReleaseSemaphore();
307 return DPERR_NOTLOBBIED;
310 /* Copy the information */
311 lpDplConnection = (LPDPLCONNECTION)lpData;
313 /* Copy everything we've got into here */
314 /* Need to actually store the stuff here. Check if we've already allocated each field first. */
315 lpDplConnection->dwSize = sizeof( DPLCONNECTION );
316 lpDplConnection->dwFlags = lpDplData->dwConnFlags;
318 /* Copy LPDPSESSIONDESC2 struct */
319 lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->sessionDesc ) );
320 memcpy( lpDplConnection->lpSessionDesc, &lpDplData->sessionDesc, sizeof( lpDplData->sessionDesc ) );
322 if( lpDplData->sessionDesc.sess.lpszSessionName )
324 lpDplConnection->lpSessionDesc->sess.lpszSessionName =
325 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.sess.lpszSessionName );
328 if( lpDplData->sessionDesc.pass.lpszPassword )
330 lpDplConnection->lpSessionDesc->pass.lpszPassword =
331 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.pass.lpszPassword );
334 lpDplConnection->lpSessionDesc->dwReserved1 = lpDplData->sessionDesc.dwReserved1;
335 lpDplConnection->lpSessionDesc->dwReserved2 = lpDplData->sessionDesc.dwReserved2;
337 /* Copy DPNAME struct - seems to be optional - check for existance first */
338 lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->playerName ) );
339 memcpy( lpDplConnection->lpPlayerName, &(lpDplData->playerName), sizeof( lpDplData->playerName ) );
341 if( lpDplData->playerName.psn.lpszShortName )
343 lpDplConnection->lpPlayerName->psn.lpszShortName =
344 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.psn.lpszShortName );
347 if( lpDplData->playerName.pln.lpszLongName )
349 lpDplConnection->lpPlayerName->pln.lpszLongName =
350 HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.pln.lpszLongName );
353 memcpy( &lpDplConnection->guidSP, &lpDplData->guidSP, sizeof( lpDplData->guidSP ) );
355 lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->dwAddressSize );
356 memcpy( lpDplConnection->lpAddress, lpDplData->lpAddress, lpDplData->dwAddressSize );
358 lpDplConnection->dwAddressSize = lpDplData->dwAddressSize;
360 /* FIXME: Send a message - or only the first time? */
362 DPLAYX_ReleaseSemaphore();
368 HRESULT DPLAYX_SetConnectionSettingsA
371 LPDPLCONNECTION lpConn )
373 lpDirectPlayLobbyData lpDplData;
375 /* Paramater check */
376 if( dwFlags || !lpConn )
378 ERR("invalid parameters.\n");
379 return DPERR_INVALIDPARAMS;
382 /* Store information */
383 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
385 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
386 lpConn->dwSize, sizeof( DPLCONNECTION ) );
388 return DPERR_INVALIDPARAMS;
393 dwAppID = GetCurrentProcessId();
396 DPLAYX_AquireSemaphore();
398 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
400 /* FIXME: Create a new entry for this dwAppID? */
401 DPLAYX_ReleaseSemaphore();
403 return DPERR_GENERIC;
406 /* Store information */
407 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
409 DPLAYX_ReleaseSemaphore();
411 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
412 lpConn->dwSize, sizeof( DPLCONNECTION ) );
414 return DPERR_INVALIDPARAMS;
417 /* Need to investigate the lpConn->lpSessionDesc to figure out
418 * what type of session we need to join/create.
420 if( (!lpConn->lpSessionDesc ) ||
421 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
424 DPLAYX_ReleaseSemaphore();
426 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
427 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
429 return DPERR_INVALIDPARAMS;
432 /* 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 */
434 /* Need to actually store the stuff here. Check if we've already allocated each field first. */
435 lpDplData->dwConnFlags = lpConn->dwFlags;
437 /* Copy LPDPSESSIONDESC2 struct - this is required */
438 memcpy( &lpDplData->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
440 /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
441 if( lpConn->lpSessionDesc->sess.lpszSessionNameA )
442 lpDplData->sessionDesc.sess.lpszSessionNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionNameA );
444 lpDplData->sessionDesc.sess.lpszSessionNameA = NULL;
446 if( lpConn->lpSessionDesc->pass.lpszPasswordA )
447 lpDplData->sessionDesc.pass.lpszPasswordA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPasswordA );
449 lpDplData->sessionDesc.pass.lpszPasswordA = NULL;
451 lpDplData->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
452 lpDplData->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
454 /* Copy DPNAME struct - seems to be optional - check for existance first */
455 if( lpConn->lpPlayerName )
457 memcpy( &lpDplData->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
459 if( lpConn->lpPlayerName->psn.lpszShortNameA )
460 lpDplData->playerName.psn.lpszShortNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortNameA );
462 if( lpConn->lpPlayerName->pln.lpszLongNameA )
463 lpDplData->playerName.pln.lpszLongNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongNameA );
467 memcpy( &lpDplData->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
469 lpDplData->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
470 memcpy( lpDplData->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
472 lpDplData->dwAddressSize = lpConn->dwAddressSize;
474 /* FIXME: Send a message - I think */
476 DPLAYX_ReleaseSemaphore();
481 HRESULT DPLAYX_SetConnectionSettingsW
484 LPDPLCONNECTION lpConn )
486 lpDirectPlayLobbyData lpDplData;
488 /* Paramater check */
489 if( dwFlags || !lpConn )
491 ERR("invalid parameters.\n");
492 return DPERR_INVALIDPARAMS;
495 /* Store information */
496 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
498 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
499 lpConn->dwSize, sizeof( DPLCONNECTION ) );
501 return DPERR_INVALIDPARAMS;
506 dwAppID = GetCurrentProcessId();
509 DPLAYX_AquireSemaphore();
511 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
513 DPLAYX_ReleaseSemaphore();
514 return DPERR_NOTLOBBIED;
517 /* Need to investigate the lpConn->lpSessionDesc to figure out
518 * what type of session we need to join/create.
520 if( (!lpConn->lpSessionDesc ) ||
521 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
524 DPLAYX_ReleaseSemaphore();
526 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
527 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
529 return DPERR_INVALIDPARAMS;
532 /* 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 */
534 /* Need to actually store the stuff here. Check if we've already allocated each field first. */
535 lpDplData->dwConnFlags = lpConn->dwFlags;
537 /* Copy LPDPSESSIONDESC2 struct - this is required */
538 memcpy( &lpDplData->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
540 /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
541 if( lpConn->lpSessionDesc->sess.lpszSessionName )
542 lpDplData->sessionDesc.sess.lpszSessionName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionName );
544 lpDplData->sessionDesc.sess.lpszSessionName = NULL;
546 if( lpConn->lpSessionDesc->pass.lpszPassword )
547 lpDplData->sessionDesc.pass.lpszPassword = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPassword );
549 lpDplData->sessionDesc.pass.lpszPassword = NULL;
551 lpDplData->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
552 lpDplData->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
554 /* Copy DPNAME struct - seems to be optional - check for existance first */
555 if( lpConn->lpPlayerName )
557 memcpy( &lpDplData->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
559 if( lpConn->lpPlayerName->psn.lpszShortName )
560 lpDplData->playerName.psn.lpszShortName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortName );
562 if( lpConn->lpPlayerName->pln.lpszLongName )
563 lpDplData->playerName.pln.lpszLongName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongName );
567 memcpy( &lpDplData->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
569 lpDplData->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
570 memcpy( lpDplData->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
572 lpDplData->dwAddressSize = lpConn->dwAddressSize;
574 /* FIXME: Send a message - I think */
576 DPLAYX_ReleaseSemaphore();
581 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
582 with the correct string printed in the case where the HRESULT is not
583 known. You'll just get the last hr passed in printed. This can change
584 over time if this method is used alot :) */
585 LPCSTR DPLAYX_HresultToString(HRESULT hr)
587 static char szTempStr[12];
593 case DPERR_ALREADYINITIALIZED:
594 return "DPERR_ALREADYINITIALIZED";
595 case DPERR_ACCESSDENIED:
596 return "DPERR_ACCESSDENIED";
597 case DPERR_ACTIVEPLAYERS:
598 return "DPERR_ACTIVEPLAYERS";
599 case DPERR_BUFFERTOOSMALL:
600 return "DPERR_BUFFERTOOSMALL";
601 case DPERR_CANTADDPLAYER:
602 return "DPERR_CANTADDPLAYER";
603 case DPERR_CANTCREATEGROUP:
604 return "DPERR_CANTCREATEGROUP";
605 case DPERR_CANTCREATEPLAYER:
606 return "DPERR_CANTCREATEPLAYER";
607 case DPERR_CANTCREATESESSION:
608 return "DPERR_CANTCREATESESSION";
609 case DPERR_CAPSNOTAVAILABLEYET:
610 return "DPERR_CAPSNOTAVAILABLEYET";
611 case DPERR_EXCEPTION:
612 return "DPERR_EXCEPTION";
614 return "DPERR_GENERIC";
615 case DPERR_INVALIDFLAGS:
616 return "DPERR_INVALIDFLAGS";
617 case DPERR_INVALIDOBJECT:
618 return "DPERR_INVALIDOBJECT";
619 case DPERR_INVALIDPARAMS:
620 return "DPERR_INVALIDPARAMS";
621 case DPERR_INVALIDPLAYER:
622 return "DPERR_INVALIDPLAYER";
623 case DPERR_INVALIDGROUP:
624 return "DPERR_INVALIDGROUP";
626 return "DPERR_NOCAPS";
627 case DPERR_NOCONNECTION:
628 return "DPERR_NOCONNECTION";
629 case DPERR_OUTOFMEMORY:
630 return "DPERR_OUTOFMEMORY";
631 case DPERR_NOMESSAGES:
632 return "DPERR_NOMESSAGES";
633 case DPERR_NONAMESERVERFOUND:
634 return "DPERR_NONAMESERVERFOUND";
635 case DPERR_NOPLAYERS:
636 return "DPERR_NOPLAYERS";
637 case DPERR_NOSESSIONS:
638 return "DPERR_NOSESSIONS";
639 /* This one isn't defined yet in WINE sources. I don't know the value
641 return "DPERR_PENDING";
643 case DPERR_SENDTOOBIG:
644 return "DPERR_SENDTOOBIG";
646 return "DPERR_TIMEOUT";
647 case DPERR_UNAVAILABLE:
648 return "DPERR_UNAVAILABLE";
649 case DPERR_UNSUPPORTED:
650 return "DPERR_UNSUPPORTED";
653 case DPERR_USERCANCEL:
654 return "DPERR_USERCANCEL";
655 case DPERR_NOINTERFACE:
656 return "DPERR_NOINTERFACE";
657 case DPERR_CANNOTCREATESERVER:
658 return "DPERR_CANNOTCREATESERVER";
659 case DPERR_PLAYERLOST:
660 return "DPERR_PLAYERLOST";
661 case DPERR_SESSIONLOST:
662 return "DPERR_SESSIONLOST";
663 case DPERR_UNINITIALIZED:
664 return "DPERR_UNINITIALIZED";
665 case DPERR_NONEWPLAYERS:
666 return "DPERR_NONEWPLAYERS";
667 case DPERR_INVALIDPASSWORD:
668 return "DPERR_INVALIDPASSWORD";
669 case DPERR_CONNECTING:
670 return "DPERR_CONNECTING";
671 case DPERR_CONNECTIONLOST:
672 return "DPERR_CONNECTIONLOST";
673 case DPERR_UNKNOWNMESSAGE:
674 return "DPERR_UNKNOWNMESSAGE";
675 case DPERR_CANCELFAILED:
676 return "DPERR_CANCELFAILED";
677 case DPERR_INVALIDPRIORITY:
678 return "DPERR_INVALIDPRIORITY";
679 case DPERR_NOTHANDLED:
680 return "DPERR_NOTHANDLED";
681 case DPERR_CANCELLED:
682 return "DPERR_CANCELLED";
684 return "DPERR_ABORTED";
685 case DPERR_BUFFERTOOLARGE:
686 return "DPERR_BUFFERTOOLARGE";
687 case DPERR_CANTCREATEPROCESS:
688 return "DPERR_CANTCREATEPROCESS";
689 case DPERR_APPNOTSTARTED:
690 return "DPERR_APPNOTSTARTED";
691 case DPERR_INVALIDINTERFACE:
692 return "DPERR_INVALIDINTERFACE";
693 case DPERR_NOSERVICEPROVIDER:
694 return "DPERR_NOSERVICEPROVIDER";
695 case DPERR_UNKNOWNAPPLICATION:
696 return "DPERR_UNKNOWNAPPLICATION";
697 case DPERR_NOTLOBBIED:
698 return "DPERR_NOTLOBBIED";
699 case DPERR_SERVICEPROVIDERLOADED:
700 return "DPERR_SERVICEPROVIDERLOADED";
701 case DPERR_ALREADYREGISTERED:
702 return "DPERR_ALREADYREGISTERED";
703 case DPERR_NOTREGISTERED:
704 return "DPERR_NOTREGISTERED";
705 case DPERR_AUTHENTICATIONFAILED:
706 return "DPERR_AUTHENTICATIONFAILED";
707 case DPERR_CANTLOADSSPI:
708 return "DPERR_CANTLOADSSPI";
709 case DPERR_ENCRYPTIONFAILED:
710 return "DPERR_ENCRYPTIONFAILED";
711 case DPERR_SIGNFAILED:
712 return "DPERR_SIGNFAILED";
713 case DPERR_CANTLOADSECURITYPACKAGE:
714 return "DPERR_CANTLOADSECURITYPACKAGE";
715 case DPERR_ENCRYPTIONNOTSUPPORTED:
716 return "DPERR_ENCRYPTIONNOTSUPPORTED";
717 case DPERR_CANTLOADCAPI:
718 return "DPERR_CANTLOADCAPI";
719 case DPERR_NOTLOGGEDIN:
720 return "DPERR_NOTLOGGEDIN";
721 case DPERR_LOGONDENIED:
722 return "DPERR_LOGONDENIED";
724 /* For errors not in the list, return HRESULT as a string
725 This part is not thread safe */
726 WARN( "Unknown error 0x%08lx\n", hr );
727 sprintf( szTempStr, "0x%08lx", hr );