0650c5280d90319218494621adbb72e0d089e65c
[reactos.git] / reactos / lib / dplayx / dplayx_global.c
1 /* dplayx.dll global data implementation.
2 *
3 * Copyright 1999,2000 - Peter Hunnisett
4 *
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 *
21 * NOTES:
22 * o Implementation of all things which are associated with dplay on
23 * the computer - ie shared resources and such. Methods in this
24 * compilation unit should not call anything out side this unit
25 * excepting base windows services and an interface to start the
26 * messaging thread.
27 * o Methods that begin with DPLAYX_ are used for dealing with
28 * dplayx.dll data which is accessible from all processes.
29 *
30 */
31
32 #include <stdarg.h>
33 #include <string.h>
34
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "wine/debug.h"
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winerror.h"
41 #include "wine/unicode.h"
42
43 #include "wingdi.h"
44 #include "winuser.h"
45
46 #include "dplayx_global.h"
47 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
48
49 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
50
51 /* FIXME: Need to do all that fun other dll referencing type of stuff */
52
53 /* Static data for all processes */
54 static LPCSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
55 static HANDLE hDplayxSema;
56
57 static LPCSTR lpszDplayxFileMapping = "WINE_DPLAYX_FM";
58 static HANDLE hDplayxSharedMem;
59
60 static LPVOID lpSharedStaticData = NULL;
61
62
63 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
64 WaitForSingleObject( hDplayxSema, INFINITE );\
65 TRACE( "Through wait\n" )
66
67 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
68 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
69
70
71 /* HACK for simple global data right now */
72 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
73 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
74 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
75
76
77 /* FIXME: Is there no easier way? */
78
79 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
80 * Each block has 4 bytes which are 0 unless used */
81 #define dwBlockSize 512
82 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
83
84 typedef struct
85 {
86 DWORD used;
87 DWORD data[dwBlockSize-sizeof(DWORD)];
88 } DPLAYX_MEM_SLICE;
89
90 static DPLAYX_MEM_SLICE* lpMemArea;
91
92 void DPLAYX_PrivHeapFree( LPVOID addr );
93 void DPLAYX_PrivHeapFree( LPVOID addr )
94 {
95 LPVOID lpAddrStart;
96 DWORD dwBlockUsed;
97
98 /* Handle getting passed a NULL */
99 if( addr == NULL )
100 {
101 return;
102 }
103
104 lpAddrStart = (char*)addr - sizeof(DWORD); /* Find block header */
105 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
106
107 lpMemArea[ dwBlockUsed ].used = 0;
108 }
109
110 /* FIXME: This should be static, but is being used for a hack right now */
111 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
112 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
113 {
114 LPVOID lpvArea = NULL;
115 UINT uBlockUsed;
116
117 if( size > (dwBlockSize - sizeof(DWORD)) )
118 {
119 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
120 size = dwBlockSize - sizeof(DWORD);
121 }
122
123 /* Find blank area */
124 uBlockUsed = 0;
125 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
126
127 if( uBlockUsed <= dwMaxBlock )
128 {
129 /* Set the area used */
130 lpMemArea[ uBlockUsed ].used = 1;
131 lpvArea = &(lpMemArea[ uBlockUsed ].data);
132 }
133 else
134 {
135 ERR( "No free block found\n" );
136 return NULL;
137 }
138
139 if( flags & HEAP_ZERO_MEMORY )
140 {
141 ZeroMemory( lpvArea, size );
142 }
143
144 return lpvArea;
145 }
146
147 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
148 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
149 {
150 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
151 if(p) {
152 strcpy( p, str );
153 }
154 return p;
155 }
156
157 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
158 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
159 {
160 INT len = strlenW(str) + 1;
161 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
162 if(p) {
163 strcpyW( p, str );
164 }
165 return p;
166 }
167
168
169 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
170 typedef struct tagDPLAYX_LOBBYDATA
171 {
172 /* Points to lpConn + block of contiguous extra memory for dynamic parts
173 * of the struct directly following
174 */
175 LPDPLCONNECTION lpConn;
176
177 /* Information for dplobby interfaces */
178 DWORD dwAppID;
179 DWORD dwAppLaunchedFromID;
180
181 /* Should this lobby app send messages to creator at important life
182 * stages
183 */
184 HANDLE hInformOnAppStart;
185 HANDLE hInformOnAppDeath;
186 HANDLE hInformOnSettingRead;
187
188 /* Sundries */
189 BOOL bWaitForConnectionSettings;
190 DWORD dwLobbyMsgThreadId;
191
192
193 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
194
195 static DPLAYX_LOBBYDATA* lobbyData = NULL;
196 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
197
198 static DPSESSIONDESC2* sessionData = NULL;
199 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
200
201 /* Function prototypes */
202 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData );
203 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData );
204 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src );
205 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src );
206 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
207 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
208 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
209 LPCDPSESSIONDESC2 lpSessionSrc );
210
211
212
213 /***************************************************************************
214 * Called to initialize the global data. This will only be used on the
215 * loading of the dll
216 ***************************************************************************/
217 BOOL DPLAYX_ConstructData(void)
218 {
219 SECURITY_ATTRIBUTES s_attrib;
220 BOOL bInitializeSharedMemory = FALSE;
221 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
222 HANDLE hInformOnStart;
223
224 TRACE( "DPLAYX dll loaded - construct called\n" );
225
226 /* Create a semaphore to block access to DPLAYX global data structs */
227
228 s_attrib.bInheritHandle = TRUE;
229 s_attrib.lpSecurityDescriptor = NULL;
230 s_attrib.nLength = sizeof(s_attrib);
231
232 hDplayxSema = CreateSemaphoreA( &s_attrib, 1, 1, lpszDplayxSemaName );
233
234 /* First instance creates the semaphore. Others just use it */
235 if( GetLastError() == ERROR_SUCCESS )
236 {
237 TRACE( "Semaphore %p created\n", hDplayxSema );
238
239 /* The semaphore creator will also build the shared memory */
240 bInitializeSharedMemory = TRUE;
241 }
242 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
243 {
244 TRACE( "Found semaphore handle %p\n", hDplayxSema );
245 }
246 else
247 {
248 ERR( ": semaphore error %ld\n", GetLastError() );
249 return FALSE;
250 }
251
252 SetLastError( ERROR_SUCCESS );
253
254 DPLAYX_AquireSemaphore();
255
256 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
257 &s_attrib,
258 PAGE_READWRITE | SEC_COMMIT,
259 0,
260 dwTotalSharedSize,
261 lpszDplayxFileMapping );
262
263 if( GetLastError() == ERROR_SUCCESS )
264 {
265 TRACE( "File mapped %p created\n", hDplayxSharedMem );
266 }
267 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
268 {
269 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
270 }
271 else
272 {
273 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
274 return FALSE;
275 }
276
277 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
278 FILE_MAP_WRITE,
279 0, 0, 0, lpDesiredMemoryMapStart );
280
281 if( lpSharedStaticData == NULL )
282 {
283 ERR( ": unable to map static data into process memory space (%ld)\n",
284 GetLastError() );
285 return FALSE;
286 }
287 else
288 {
289 if( lpDesiredMemoryMapStart == lpSharedStaticData )
290 {
291 TRACE( "File mapped to %p\n", lpSharedStaticData );
292 }
293 else
294 {
295 /* Presently the shared data structures use pointers. If the
296 * files are no mapped into the same area, the pointers will no
297 * longer make any sense :(
298 * FIXME: In the future make the shared data structures have some
299 * sort of fixup to make them independent between data spaces.
300 * This will also require a rework of the session data stuff.
301 */
302 ERR( "File mapped to %p (not %p). Expect failure\n",
303 lpSharedStaticData, lpDesiredMemoryMapStart );
304 }
305 }
306
307 /* Dynamic area starts just after the static area */
308 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
309
310 /* FIXME: Crude hack */
311 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
312 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
313
314 /* Initialize shared data segments. */
315 if( bInitializeSharedMemory )
316 {
317 UINT i;
318
319 TRACE( "Initializing shared memory\n" );
320
321 /* Set all lobbies to be "empty" */
322 for( i=0; i < numSupportedLobbies; i++ )
323 {
324 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
325 }
326
327 /* Set all sessions to be "empty" */
328 for( i=0; i < numSupportedSessions; i++ )
329 {
330 sessionData[i].dwSize = 0;
331 }
332
333 /* Zero out the dynmaic area */
334 ZeroMemory( lpMemArea, dwDynamicSharedSize );
335
336 /* Just for fun sync the whole data area */
337 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
338 }
339
340 DPLAYX_ReleaseSemaphore();
341
342 /* Everything was created correctly. Signal the lobby client that
343 * we started up correctly
344 */
345 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
346 hInformOnStart
347 )
348 {
349 BOOL bSuccess;
350 bSuccess = SetEvent( hInformOnStart );
351 TRACE( "Signalling lobby app start event %p %s\n",
352 hInformOnStart, bSuccess ? "succeed" : "failed" );
353
354 /* Close out handle */
355 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
356 }
357
358 return TRUE;
359 }
360
361 /***************************************************************************
362 * Called to destroy all global data. This will only be used on the
363 * unloading of the dll
364 ***************************************************************************/
365 BOOL DPLAYX_DestructData(void)
366 {
367 HANDLE hInformOnDeath;
368
369 TRACE( "DPLAYX dll unloaded - destruct called\n" );
370
371 /* If required, inform that this app is dying */
372 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
373 hInformOnDeath
374 )
375 {
376 BOOL bSuccess;
377 bSuccess = SetEvent( hInformOnDeath );
378 TRACE( "Signalling lobby app death event %p %s\n",
379 hInformOnDeath, bSuccess ? "succeed" : "failed" );
380
381 /* Close out handle */
382 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
383 }
384
385 /* DO CLEAN UP (LAST) */
386
387 /* Delete the semaphore */
388 CloseHandle( hDplayxSema );
389
390 /* Delete shared memory file mapping */
391 UnmapViewOfFile( lpSharedStaticData );
392 CloseHandle( hDplayxSharedMem );
393
394 return FALSE;
395 }
396
397
398 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
399 {
400 ZeroMemory( lpData, sizeof( *lpData ) );
401 }
402
403 /* NOTE: This must be called with the semaphore aquired.
404 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
405 * is only valid if TRUE is returned.
406 */
407 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
408 {
409 UINT i;
410
411 *lplpDplData = NULL;
412
413 if( dwAppID == 0 )
414 {
415 dwAppID = GetCurrentProcessId();
416 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
417 }
418
419 for( i=0; i < numSupportedLobbies; i++ )
420 {
421 if( lobbyData[ i ].dwAppID == dwAppID )
422 {
423 /* This process is lobbied */
424 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
425 *lplpDplData = &lobbyData[ i ];
426 return TRUE;
427 }
428 }
429
430 return FALSE;
431 }
432
433 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
434 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
435 {
436 UINT i;
437
438 /* 0 is the marker for unused application data slots */
439 if( dwAppID == 0 )
440 {
441 return FALSE;
442 }
443
444 DPLAYX_AquireSemaphore();
445
446 /* Find an empty space in the list and insert the data */
447 for( i=0; i < numSupportedLobbies; i++ )
448 {
449 if( lobbyData[ i ].dwAppID == 0 )
450 {
451 /* This process is now lobbied */
452 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
453 i, dwAppID, GetCurrentProcessId() );
454
455 lobbyData[ i ].dwAppID = dwAppID;
456 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
457
458 /* FIXME: Where is the best place for this? In interface or here? */
459 lobbyData[ i ].hInformOnAppStart = 0;
460 lobbyData[ i ].hInformOnAppDeath = 0;
461 lobbyData[ i ].hInformOnSettingRead = 0;
462
463 DPLAYX_ReleaseSemaphore();
464 return TRUE;
465 }
466 }
467
468 ERR( "No empty lobbies\n" );
469
470 DPLAYX_ReleaseSemaphore();
471 return FALSE;
472 }
473
474 /* I'm not sure when I'm going to need this, but here it is */
475 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
476 {
477 UINT i;
478
479 DPLAYX_AquireSemaphore();
480
481 /* Find an empty space in the list and insert the data */
482 for( i=0; i < numSupportedLobbies; i++ )
483 {
484 if( lobbyData[ i ].dwAppID == dwAppID )
485 {
486 /* FIXME: Should free up anything unused. Tisk tisk :0 */
487 /* Mark this entry unused */
488 TRACE( "Marking lobbyData[%u] unused\n", i );
489 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
490
491 DPLAYX_ReleaseSemaphore();
492 return TRUE;
493 }
494 }
495
496 DPLAYX_ReleaseSemaphore();
497 ERR( "Unable to find global entry for application\n" );
498 return FALSE;
499 }
500
501 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
502 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
503 {
504 LPDPLAYX_LOBBYDATA lpLData;
505
506 /* Need to explictly give lobby application. Can't set for yourself */
507 if( dwAppID == 0 )
508 {
509 return FALSE;
510 }
511
512 DPLAYX_AquireSemaphore();
513
514 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
515 {
516 DPLAYX_ReleaseSemaphore();
517 return FALSE;
518 }
519
520 lpLData->hInformOnAppStart = hStart;
521 lpLData->hInformOnAppDeath = hDeath;
522 lpLData->hInformOnSettingRead = hConnRead;
523
524 DPLAYX_ReleaseSemaphore();
525
526 return TRUE;
527 }
528
529 BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
530 LPHANDLE lphDeath,
531 LPHANDLE lphConnRead,
532 BOOL bClearSetHandles )
533 {
534 LPDPLAYX_LOBBYDATA lpLData;
535
536 DPLAYX_AquireSemaphore();
537
538 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
539 {
540 DPLAYX_ReleaseSemaphore();
541 return FALSE;
542 }
543
544 if( lphStart != NULL )
545 {
546 if( lpLData->hInformOnAppStart == 0 )
547 {
548 DPLAYX_ReleaseSemaphore();
549 return FALSE;
550 }
551
552 *lphStart = lpLData->hInformOnAppStart;
553
554 if( bClearSetHandles )
555 {
556 CloseHandle( lpLData->hInformOnAppStart );
557 lpLData->hInformOnAppStart = 0;
558 }
559 }
560
561 if( lphDeath != NULL )
562 {
563 if( lpLData->hInformOnAppDeath == 0 )
564 {
565 DPLAYX_ReleaseSemaphore();
566 return FALSE;
567 }
568
569 *lphDeath = lpLData->hInformOnAppDeath;
570
571 if( bClearSetHandles )
572 {
573 CloseHandle( lpLData->hInformOnAppDeath );
574 lpLData->hInformOnAppDeath = 0;
575 }
576 }
577
578 if( lphConnRead != NULL )
579 {
580 if( lpLData->hInformOnSettingRead == 0 )
581 {
582 DPLAYX_ReleaseSemaphore();
583 return FALSE;
584 }
585
586 *lphConnRead = lpLData->hInformOnSettingRead;
587
588 if( bClearSetHandles )
589 {
590 CloseHandle( lpLData->hInformOnSettingRead );
591 lpLData->hInformOnSettingRead = 0;
592 }
593 }
594
595 DPLAYX_ReleaseSemaphore();
596
597 return TRUE;
598 }
599
600
601 HRESULT DPLAYX_GetConnectionSettingsA
602 ( DWORD dwAppID,
603 LPVOID lpData,
604 LPDWORD lpdwDataSize )
605 {
606 LPDPLAYX_LOBBYDATA lpDplData;
607 DWORD dwRequiredDataSize = 0;
608 HANDLE hInformOnSettingRead;
609
610 DPLAYX_AquireSemaphore();
611
612 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
613 {
614 DPLAYX_ReleaseSemaphore();
615
616 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
617 return DPERR_NOTLOBBIED;
618 }
619
620 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
621
622 /* Do they want to know the required buffer size or is the provided buffer
623 * big enough?
624 */
625 if ( ( lpData == NULL ) ||
626 ( *lpdwDataSize < dwRequiredDataSize )
627 )
628 {
629 DPLAYX_ReleaseSemaphore();
630
631 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
632
633 return DPERR_BUFFERTOOSMALL;
634 }
635
636 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
637
638 DPLAYX_ReleaseSemaphore();
639
640 /* They have gotten the information - signal the event if required */
641 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
642 hInformOnSettingRead
643 )
644 {
645 BOOL bSuccess;
646 bSuccess = SetEvent( hInformOnSettingRead );
647 TRACE( "Signalling setting read event %p %s\n",
648 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
649
650 /* Close out handle */
651 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
652 }
653
654 return DP_OK;
655 }
656
657 /* Assumption: Enough contiguous space was allocated at dest */
658 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
659 {
660 BYTE* lpStartOfFreeSpace;
661
662 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
663
664 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
665
666 /* Copy the LPDPSESSIONDESC2 structure if it exists */
667 if( src->lpSessionDesc )
668 {
669 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
670 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
671 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
672
673 /* Session names may or may not exist */
674 if( src->lpSessionDesc->lpszSessionNameA )
675 {
676 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->lpszSessionNameA );
677 dest->lpSessionDesc->lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
678 lpStartOfFreeSpace +=
679 strlen( (LPSTR)dest->lpSessionDesc->lpszSessionNameA ) + 1;
680 }
681
682 if( src->lpSessionDesc->lpszPasswordA )
683 {
684 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->lpszPasswordA );
685 dest->lpSessionDesc->lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
686 lpStartOfFreeSpace +=
687 strlen( (LPSTR)dest->lpSessionDesc->lpszPasswordA ) + 1;
688 }
689 }
690
691 /* DPNAME structure is optional */
692 if( src->lpPlayerName )
693 {
694 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
695 lpStartOfFreeSpace += sizeof( DPNAME );
696 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
697
698 if( src->lpPlayerName->lpszShortNameA )
699 {
700 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->lpszShortNameA );
701 dest->lpPlayerName->lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
702 lpStartOfFreeSpace +=
703 strlen( (LPSTR)dest->lpPlayerName->lpszShortNameA ) + 1;
704 }
705
706 if( src->lpPlayerName->lpszLongNameA )
707 {
708 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->lpszLongNameA );
709 dest->lpPlayerName->lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
710 lpStartOfFreeSpace +=
711 strlen( (LPSTR)dest->lpPlayerName->lpszLongName ) + 1 ;
712 }
713
714 }
715
716 /* Copy address if it exists */
717 if( src->lpAddress )
718 {
719 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
720 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
721 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
722 }
723 }
724
725 HRESULT DPLAYX_GetConnectionSettingsW
726 ( DWORD dwAppID,
727 LPVOID lpData,
728 LPDWORD lpdwDataSize )
729 {
730 LPDPLAYX_LOBBYDATA lpDplData;
731 DWORD dwRequiredDataSize = 0;
732 HANDLE hInformOnSettingRead;
733
734 DPLAYX_AquireSemaphore();
735
736 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
737 {
738 DPLAYX_ReleaseSemaphore();
739 return DPERR_NOTLOBBIED;
740 }
741
742 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
743
744 /* Do they want to know the required buffer size or is the provided buffer
745 * big enough?
746 */
747 if ( ( lpData == NULL ) ||
748 ( *lpdwDataSize < dwRequiredDataSize )
749 )
750 {
751 DPLAYX_ReleaseSemaphore();
752
753 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
754
755 return DPERR_BUFFERTOOSMALL;
756 }
757
758 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
759
760 DPLAYX_ReleaseSemaphore();
761
762 /* They have gotten the information - signal the event if required */
763 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
764 hInformOnSettingRead
765 )
766 {
767 BOOL bSuccess;
768 bSuccess = SetEvent( hInformOnSettingRead );
769 TRACE( "Signalling setting read event %p %s\n",
770 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
771
772 /* Close out handle */
773 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
774 }
775
776 return DP_OK;
777 }
778
779 /* Assumption: Enough contiguous space was allocated at dest */
780 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
781 {
782 BYTE* lpStartOfFreeSpace;
783
784 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
785
786 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
787
788 /* Copy the LPDPSESSIONDESC2 structure if it exists */
789 if( src->lpSessionDesc )
790 {
791 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
792 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
793 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
794
795 /* Session names may or may not exist */
796 if( src->lpSessionDesc->lpszSessionName )
797 {
798 strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->lpszSessionName );
799 src->lpSessionDesc->lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
800 lpStartOfFreeSpace += sizeof(WCHAR) *
801 ( strlenW( (LPWSTR)dest->lpSessionDesc->lpszSessionName ) + 1 );
802 }
803
804 if( src->lpSessionDesc->lpszPassword )
805 {
806 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->lpszPassword );
807 dest->lpSessionDesc->lpszPassword = (LPWSTR)lpStartOfFreeSpace;
808 lpStartOfFreeSpace += sizeof(WCHAR) *
809 ( strlenW( (LPWSTR)dest->lpSessionDesc->lpszPassword ) + 1 );
810 }
811 }
812
813 /* DPNAME structure is optional */
814 if( src->lpPlayerName )
815 {
816 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
817 lpStartOfFreeSpace += sizeof( DPNAME );
818 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
819
820 if( src->lpPlayerName->lpszShortName )
821 {
822 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->lpszShortName );
823 dest->lpPlayerName->lpszShortName = (LPWSTR)lpStartOfFreeSpace;
824 lpStartOfFreeSpace += sizeof(WCHAR) *
825 ( strlenW( (LPWSTR)dest->lpPlayerName->lpszShortName ) + 1 );
826 }
827
828 if( src->lpPlayerName->lpszLongName )
829 {
830 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->lpszLongName );
831 dest->lpPlayerName->lpszLongName = (LPWSTR)lpStartOfFreeSpace;
832 lpStartOfFreeSpace += sizeof(WCHAR) *
833 ( strlenW( (LPWSTR)dest->lpPlayerName->lpszLongName ) + 1 );
834 }
835
836 }
837
838 /* Copy address if it exists */
839 if( src->lpAddress )
840 {
841 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
842 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
843 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
844 }
845
846 }
847
848 /* Store the structure into the shared data structre. Ensure that allocs for
849 * variable length strings come from the shared data structure.
850 * FIXME: We need to free information as well
851 */
852 HRESULT DPLAYX_SetConnectionSettingsA
853 ( DWORD dwFlags,
854 DWORD dwAppID,
855 LPDPLCONNECTION lpConn )
856 {
857 LPDPLAYX_LOBBYDATA lpDplData;
858
859 /* Parameter check */
860 if( dwFlags || !lpConn )
861 {
862 ERR("invalid parameters.\n");
863 return DPERR_INVALIDPARAMS;
864 }
865
866 /* Store information */
867 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
868 {
869 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
870 lpConn->dwSize, sizeof( DPLCONNECTION ) );
871
872 return DPERR_INVALIDPARAMS;
873 }
874
875 DPLAYX_AquireSemaphore();
876
877 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
878 {
879 DPLAYX_ReleaseSemaphore();
880
881 return DPERR_NOTLOBBIED;
882 }
883
884 if( (!lpConn->lpSessionDesc ) ||
885 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
886 )
887 {
888 DPLAYX_ReleaseSemaphore();
889
890 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
891 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
892
893 return DPERR_INVALIDPARAMS;
894 }
895
896 /* Free the existing memory */
897 DPLAYX_PrivHeapFree( lpDplData->lpConn );
898
899 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
900 DPLAYX_SizeOfLobbyDataA( lpConn ) );
901
902 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
903
904
905 DPLAYX_ReleaseSemaphore();
906
907 /* FIXME: Send a message - I think */
908
909 return DP_OK;
910 }
911
912 /* Store the structure into the shared data structre. Ensure that allocs for
913 * variable length strings come from the shared data structure.
914 * FIXME: We need to free information as well
915 */
916 HRESULT DPLAYX_SetConnectionSettingsW
917 ( DWORD dwFlags,
918 DWORD dwAppID,
919 LPDPLCONNECTION lpConn )
920 {
921 LPDPLAYX_LOBBYDATA lpDplData;
922
923 /* Parameter check */
924 if( dwFlags || !lpConn )
925 {
926 ERR("invalid parameters.\n");
927 return DPERR_INVALIDPARAMS;
928 }
929
930 /* Store information */
931 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
932 {
933 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
934 lpConn->dwSize, sizeof( DPLCONNECTION ) );
935
936 return DPERR_INVALIDPARAMS;
937 }
938
939 DPLAYX_AquireSemaphore();
940
941 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
942 {
943 DPLAYX_ReleaseSemaphore();
944
945 return DPERR_NOTLOBBIED;
946 }
947
948 /* Free the existing memory */
949 DPLAYX_PrivHeapFree( lpDplData->lpConn );
950
951 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
952 DPLAYX_SizeOfLobbyDataW( lpConn ) );
953
954 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
955
956
957 DPLAYX_ReleaseSemaphore();
958
959 /* FIXME: Send a message - I think */
960
961 return DP_OK;
962 }
963
964 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
965 {
966 DWORD dwTotalSize = sizeof( DPLCONNECTION );
967
968 /* Just a safety check */
969 if( lpConn == NULL )
970 {
971 ERR( "lpConn is NULL\n" );
972 return 0;
973 }
974
975 if( lpConn->lpSessionDesc != NULL )
976 {
977 dwTotalSize += sizeof( DPSESSIONDESC2 );
978
979 if( lpConn->lpSessionDesc->lpszSessionNameA )
980 {
981 dwTotalSize += strlen( lpConn->lpSessionDesc->lpszSessionNameA ) + 1;
982 }
983
984 if( lpConn->lpSessionDesc->lpszPasswordA )
985 {
986 dwTotalSize += strlen( lpConn->lpSessionDesc->lpszPasswordA ) + 1;
987 }
988 }
989
990 if( lpConn->lpPlayerName != NULL )
991 {
992 dwTotalSize += sizeof( DPNAME );
993
994 if( lpConn->lpPlayerName->lpszShortNameA )
995 {
996 dwTotalSize += strlen( lpConn->lpPlayerName->lpszShortNameA ) + 1;
997 }
998
999 if( lpConn->lpPlayerName->lpszLongNameA )
1000 {
1001 dwTotalSize += strlen( lpConn->lpPlayerName->lpszLongNameA ) + 1;
1002 }
1003
1004 }
1005
1006 dwTotalSize += lpConn->dwAddressSize;
1007
1008 return dwTotalSize;
1009 }
1010
1011 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
1012 {
1013 DWORD dwTotalSize = sizeof( DPLCONNECTION );
1014
1015 /* Just a safety check */
1016 if( lpConn == NULL )
1017 {
1018 ERR( "lpConn is NULL\n" );
1019 return 0;
1020 }
1021
1022 if( lpConn->lpSessionDesc != NULL )
1023 {
1024 dwTotalSize += sizeof( DPSESSIONDESC2 );
1025
1026 if( lpConn->lpSessionDesc->lpszSessionName )
1027 {
1028 dwTotalSize += sizeof( WCHAR ) *
1029 ( strlenW( lpConn->lpSessionDesc->lpszSessionName ) + 1 );
1030 }
1031
1032 if( lpConn->lpSessionDesc->lpszPassword )
1033 {
1034 dwTotalSize += sizeof( WCHAR ) *
1035 ( strlenW( lpConn->lpSessionDesc->lpszPassword ) + 1 );
1036 }
1037 }
1038
1039 if( lpConn->lpPlayerName != NULL )
1040 {
1041 dwTotalSize += sizeof( DPNAME );
1042
1043 if( lpConn->lpPlayerName->lpszShortName )
1044 {
1045 dwTotalSize += sizeof( WCHAR ) *
1046 ( strlenW( lpConn->lpPlayerName->lpszShortName ) + 1 );
1047 }
1048
1049 if( lpConn->lpPlayerName->lpszLongName )
1050 {
1051 dwTotalSize += sizeof( WCHAR ) *
1052 ( strlenW( lpConn->lpPlayerName->lpszLongName ) + 1 );
1053 }
1054
1055 }
1056
1057 dwTotalSize += lpConn->dwAddressSize;
1058
1059 return dwTotalSize;
1060 }
1061
1062
1063
1064 static LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
1065 {
1066 LPDPSESSIONDESC2 lpSessionDest =
1067 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
1068 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
1069
1070 return lpSessionDest;
1071 }
1072
1073 /* Copy an ANSI session desc structure to the given buffer */
1074 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1075 LPCDPSESSIONDESC2 lpSessionSrc )
1076 {
1077 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1078
1079 if( lpSessionSrc->lpszSessionNameA )
1080 {
1081 if ((lpSessionDest->lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1082 strlen(lpSessionSrc->lpszSessionNameA)+1 )))
1083 strcpy( lpSessionDest->lpszSessionNameA, lpSessionSrc->lpszSessionNameA );
1084 }
1085 if( lpSessionSrc->lpszPasswordA )
1086 {
1087 if ((lpSessionDest->lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1088 strlen(lpSessionSrc->lpszPasswordA)+1 )))
1089 strcpy( lpSessionDest->lpszPasswordA, lpSessionSrc->lpszPasswordA );
1090 }
1091
1092 return TRUE;
1093 }
1094
1095 /* Start the index at 0. index will be updated to equal that which should
1096 be passed back into this function for the next element */
1097 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
1098 {
1099 for( ; (*index) < numSupportedSessions; (*index)++ )
1100 {
1101 if( sessionData[(*index)].dwSize != 0 )
1102 {
1103 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
1104 }
1105 }
1106
1107 /* No more sessions */
1108 return NULL;
1109 }
1110
1111 /* Start the index at 0. index will be updated to equal that which should
1112 be passed back into this function for the next element */
1113 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
1114 {
1115 for( ; (*index) < numSupportedSessions; (*index)++ )
1116 {
1117 if( sessionData[(*index)].dwSize != 0 )
1118 {
1119 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
1120 }
1121 }
1122
1123 /* No more sessions */
1124 return FALSE;
1125 }
1126
1127 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1128 {
1129 UINT i;
1130
1131 /* FIXME: Is this an error if it exists already? */
1132
1133 /* Crude/wrong implementation for now. Just always add to first empty spot */
1134 for( i=0; i < numSupportedSessions; i++ )
1135 {
1136 /* Is this one empty? */
1137 if( sessionData[i].dwSize == 0 )
1138 {
1139 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1140 break;
1141 }
1142 }
1143
1144 }
1145
1146 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1147 {
1148 LPDPLAYX_LOBBYDATA lpLobbyData;
1149
1150 DPLAYX_AquireSemaphore();
1151
1152 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1153 {
1154 DPLAYX_ReleaseSemaphore();
1155 return FALSE;
1156 }
1157
1158 lpLobbyData->bWaitForConnectionSettings = bWait;
1159
1160 DPLAYX_ReleaseSemaphore();
1161
1162 return TRUE;
1163 }
1164
1165 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1166 {
1167 UINT i;
1168 BOOL bFound = FALSE;
1169
1170 DPLAYX_AquireSemaphore();
1171
1172 for( i=0; i < numSupportedLobbies; i++ )
1173 {
1174 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1175 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1176 )
1177 {
1178 bFound = TRUE;
1179 break;
1180 }
1181 }
1182
1183 DPLAYX_ReleaseSemaphore();
1184
1185 return bFound;
1186 }
1187
1188 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1189 {
1190 LPDPLAYX_LOBBYDATA lpLobbyData;
1191
1192 DPLAYX_AquireSemaphore();
1193
1194 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1195 {
1196 DPLAYX_ReleaseSemaphore();
1197 return FALSE;
1198 }
1199
1200 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1201
1202 DPLAYX_ReleaseSemaphore();
1203
1204 return TRUE;
1205 }
1206
1207 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1208 with the correct string printed in the case where the HRESULT is not
1209 known. You will just get the last hr passed in. This can change
1210 over time if this method is used a lot :) */
1211 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1212 {
1213 static char szTempStr[12];
1214
1215 switch (hr)
1216 {
1217 case DP_OK:
1218 return "DP_OK";
1219 case DPERR_ALREADYINITIALIZED:
1220 return "DPERR_ALREADYINITIALIZED";
1221 case DPERR_ACCESSDENIED:
1222 return "DPERR_ACCESSDENIED";
1223 case DPERR_ACTIVEPLAYERS:
1224 return "DPERR_ACTIVEPLAYERS";
1225 case DPERR_BUFFERTOOSMALL:
1226 return "DPERR_BUFFERTOOSMALL";
1227 case DPERR_CANTADDPLAYER:
1228 return "DPERR_CANTADDPLAYER";
1229 case DPERR_CANTCREATEGROUP:
1230 return "DPERR_CANTCREATEGROUP";
1231 case DPERR_CANTCREATEPLAYER:
1232 return "DPERR_CANTCREATEPLAYER";
1233 case DPERR_CANTCREATESESSION:
1234 return "DPERR_CANTCREATESESSION";
1235 case DPERR_CAPSNOTAVAILABLEYET:
1236 return "DPERR_CAPSNOTAVAILABLEYET";
1237 case DPERR_EXCEPTION:
1238 return "DPERR_EXCEPTION";
1239 case DPERR_GENERIC:
1240 return "DPERR_GENERIC";
1241 case DPERR_INVALIDFLAGS:
1242 return "DPERR_INVALIDFLAGS";
1243 case DPERR_INVALIDOBJECT:
1244 return "DPERR_INVALIDOBJECT";
1245 case DPERR_INVALIDPARAMS:
1246 return "DPERR_INVALIDPARAMS";
1247 case DPERR_INVALIDPLAYER:
1248 return "DPERR_INVALIDPLAYER";
1249 case DPERR_INVALIDGROUP:
1250 return "DPERR_INVALIDGROUP";
1251 case DPERR_NOCAPS:
1252 return "DPERR_NOCAPS";
1253 case DPERR_NOCONNECTION:
1254 return "DPERR_NOCONNECTION";
1255 case DPERR_OUTOFMEMORY:
1256 return "DPERR_OUTOFMEMORY";
1257 case DPERR_NOMESSAGES:
1258 return "DPERR_NOMESSAGES";
1259 case DPERR_NONAMESERVERFOUND:
1260 return "DPERR_NONAMESERVERFOUND";
1261 case DPERR_NOPLAYERS:
1262 return "DPERR_NOPLAYERS";
1263 case DPERR_NOSESSIONS:
1264 return "DPERR_NOSESSIONS";
1265 case DPERR_PENDING:
1266 return "DPERR_PENDING";
1267 case DPERR_SENDTOOBIG:
1268 return "DPERR_SENDTOOBIG";
1269 case DPERR_TIMEOUT:
1270 return "DPERR_TIMEOUT";
1271 case DPERR_UNAVAILABLE:
1272 return "DPERR_UNAVAILABLE";
1273 case DPERR_UNSUPPORTED:
1274 return "DPERR_UNSUPPORTED";
1275 case DPERR_BUSY:
1276 return "DPERR_BUSY";
1277 case DPERR_USERCANCEL:
1278 return "DPERR_USERCANCEL";
1279 case DPERR_NOINTERFACE:
1280 return "DPERR_NOINTERFACE";
1281 case DPERR_CANNOTCREATESERVER:
1282 return "DPERR_CANNOTCREATESERVER";
1283 case DPERR_PLAYERLOST:
1284 return "DPERR_PLAYERLOST";
1285 case DPERR_SESSIONLOST:
1286 return "DPERR_SESSIONLOST";
1287 case DPERR_UNINITIALIZED:
1288 return "DPERR_UNINITIALIZED";
1289 case DPERR_NONEWPLAYERS:
1290 return "DPERR_NONEWPLAYERS";
1291 case DPERR_INVALIDPASSWORD:
1292 return "DPERR_INVALIDPASSWORD";
1293 case DPERR_CONNECTING:
1294 return "DPERR_CONNECTING";
1295 case DPERR_CONNECTIONLOST:
1296 return "DPERR_CONNECTIONLOST";
1297 case DPERR_UNKNOWNMESSAGE:
1298 return "DPERR_UNKNOWNMESSAGE";
1299 case DPERR_CANCELFAILED:
1300 return "DPERR_CANCELFAILED";
1301 case DPERR_INVALIDPRIORITY:
1302 return "DPERR_INVALIDPRIORITY";
1303 case DPERR_NOTHANDLED:
1304 return "DPERR_NOTHANDLED";
1305 case DPERR_CANCELLED:
1306 return "DPERR_CANCELLED";
1307 case DPERR_ABORTED:
1308 return "DPERR_ABORTED";
1309 case DPERR_BUFFERTOOLARGE:
1310 return "DPERR_BUFFERTOOLARGE";
1311 case DPERR_CANTCREATEPROCESS:
1312 return "DPERR_CANTCREATEPROCESS";
1313 case DPERR_APPNOTSTARTED:
1314 return "DPERR_APPNOTSTARTED";
1315 case DPERR_INVALIDINTERFACE:
1316 return "DPERR_INVALIDINTERFACE";
1317 case DPERR_NOSERVICEPROVIDER:
1318 return "DPERR_NOSERVICEPROVIDER";
1319 case DPERR_UNKNOWNAPPLICATION:
1320 return "DPERR_UNKNOWNAPPLICATION";
1321 case DPERR_NOTLOBBIED:
1322 return "DPERR_NOTLOBBIED";
1323 case DPERR_SERVICEPROVIDERLOADED:
1324 return "DPERR_SERVICEPROVIDERLOADED";
1325 case DPERR_ALREADYREGISTERED:
1326 return "DPERR_ALREADYREGISTERED";
1327 case DPERR_NOTREGISTERED:
1328 return "DPERR_NOTREGISTERED";
1329 case DPERR_AUTHENTICATIONFAILED:
1330 return "DPERR_AUTHENTICATIONFAILED";
1331 case DPERR_CANTLOADSSPI:
1332 return "DPERR_CANTLOADSSPI";
1333 case DPERR_ENCRYPTIONFAILED:
1334 return "DPERR_ENCRYPTIONFAILED";
1335 case DPERR_SIGNFAILED:
1336 return "DPERR_SIGNFAILED";
1337 case DPERR_CANTLOADSECURITYPACKAGE:
1338 return "DPERR_CANTLOADSECURITYPACKAGE";
1339 case DPERR_ENCRYPTIONNOTSUPPORTED:
1340 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1341 case DPERR_CANTLOADCAPI:
1342 return "DPERR_CANTLOADCAPI";
1343 case DPERR_NOTLOGGEDIN:
1344 return "DPERR_NOTLOGGEDIN";
1345 case DPERR_LOGONDENIED:
1346 return "DPERR_LOGONDENIED";
1347 default:
1348 /* For errors not in the list, return HRESULT as a string
1349 This part is not thread safe */
1350 WARN( "Unknown error 0x%08lx\n", hr );
1351 wsprintfA( szTempStr, "0x%08lx", hr );
1352 return szTempStr;
1353 }
1354 }