source: trunk/src/DPlayX/dplayx_global.cpp@ 4317

Last change on this file since 4317 was 4317, checked in by hugh, 25 years ago

Added ID tags

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