Extended the winmm joystick API calls to support the new Linux
[wine] / dlls / dplayx / dplayx_global.c
1 /* dplayx.dll global data implementation.
2  *
3  * Copyright 1999 - Peter Hunnisett
4  *
5  * <presently under construction - contact hunnise@nortelnetworks.com>
6  *
7  */
8
9 /* NOTE: Methods that begin with DPLAYX_ are used for dealing with 
10  *       dplayx.dll data which is accessible from all processes.
11  */ 
12
13 #include "debugtools.h"
14 #include "winbase.h"
15 #include "winerror.h"
16 #include "heap.h"  /* Really shouldn't be using those HEAP_strdupA interfaces should I? */
17
18 #include "dplayx_global.h"
19
20 DEFAULT_DEBUG_CHANNEL(dplay)
21
22 /* FIXME: Need to do all that fun other dll referencing type of stuff */
23 /* FIXME: Need to allocate a giant static area */
24
25 /* Static data for all processes */
26 static LPSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
27 static HANDLE hDplayxSema;
28
29
30
31 #define DPLAYX_AquireSemaphore()  TRACE( "Waiting for DPLAYX sema\n" ); \
32                                   WaitForSingleObject( hDplayxSema, INFINITE ); TRACE( "Through wait\n" )
33 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
34                                   TRACE( "DPLAYX Sema released\n" ); /* FIXME: Is this correct? */
35
36
37 /* HACK for simple global data right now */ 
38 enum { numSupportedLobbies = 32 };
39 typedef struct tagDirectPlayLobbyData
40 {
41   DWORD           dwConnFlags;
42   DPSESSIONDESC2  sessionDesc;
43   DPNAME          playerName;
44   GUID            guidSP;
45   LPVOID          lpAddress;
46   DWORD           dwAddressSize;
47   DWORD           dwAppID;
48   HANDLE          hReceiveEvent;
49   DWORD           dwAppLaunchedFromID;
50 } DirectPlayLobbyData, *lpDirectPlayLobbyData;
51
52 static DirectPlayLobbyData lobbyData[ numSupportedLobbies ];
53
54 /* Function prototypes */
55 BOOL  DPLAYX_IsAppIdLobbied( DWORD dwAppId, lpDirectPlayLobbyData* dplData );
56 void DPLAYX_InitializeLobbyDataEntry( lpDirectPlayLobbyData lpData );
57
58
59
60
61
62 /*************************************************************************** 
63  * Called to initialize the global data. This will only be used on the 
64  * loading of the dll 
65  ***************************************************************************/ 
66 void DPLAYX_ConstructData(void)
67 {
68   UINT i;
69
70   TRACE( "DPLAYX dll loaded - construct called\n" );
71
72   /* Create a semahopre to block access to DPLAYX global data structs 
73      It starts unblocked, and allows up to 65000 users blocked on it. Seems reasonable
74      for the time being */
75   hDplayxSema = CreateSemaphoreA( NULL, 1, 65000, lpszDplayxSemaName ); 
76
77   if( !hDplayxSema )
78   {
79     /* Really don't have any choice but to continue... */
80     ERR( "Semaphore creation error 0x%08lx\n", GetLastError() );
81   }
82
83   /* Set all lobbies to be "empty" */ 
84   for( i=0; i < numSupportedLobbies; i++ )
85   {
86     DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
87   }
88
89 }
90
91 /*************************************************************************** 
92  * Called to destroy all global data. This will only be used on the 
93  * unloading of the dll 
94  ***************************************************************************/ 
95 void DPLAYX_DestructData(void)
96 {
97   TRACE( "DPLAYX dll unloaded - destruct called\n" );
98
99   /* delete the semaphore */
100   CloseHandle( hDplayxSema );
101 }
102
103
104 void DPLAYX_InitializeLobbyDataEntry( lpDirectPlayLobbyData lpData )
105 {
106   ZeroMemory( lpData, sizeof( *lpData ) );
107
108   /* Set the handle to a better invalid value */
109   lpData->hReceiveEvent = INVALID_HANDLE_VALUE;
110 }
111
112 /* NOTE: This must be called with the semaphore aquired. 
113  * TRUE/FALSE with a pointer to it's data returned. Pointer data is
114  * is only valid if TRUE is returned.
115  */
116 BOOL  DPLAYX_IsAppIdLobbied( DWORD dwAppID, lpDirectPlayLobbyData* lplpDplData )
117 {
118   INT i;
119
120   *lplpDplData = NULL;
121
122   if( dwAppID == 0 )
123   {
124     dwAppID = GetCurrentProcessId();
125     TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
126   }
127
128   for( i=0; i < numSupportedLobbies; i++ )
129   {
130     if( lobbyData[ i ].dwAppID == dwAppID )
131     {
132       /* This process is lobbied */ 
133       *lplpDplData = &lobbyData[ i ];
134       return TRUE;
135     }
136   }
137
138   return FALSE;
139 }
140
141 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure.  */
142 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent )
143 {
144   UINT i;
145
146   /* 0 is the marker for unused application data slots */
147   if( dwAppID == 0 )
148   {
149     return FALSE;
150   } 
151
152   DPLAYX_AquireSemaphore();
153
154   /* Find an empty space in the list and insert the data */
155   for( i=0; i < numSupportedLobbies; i++ )
156   {
157     if( lobbyData[ i ].dwAppID == 0 )
158     {
159       /* This process is now lobbied */
160       lobbyData[ i ].dwAppID             = dwAppID;
161       lobbyData[ i ].hReceiveEvent       = hReceiveEvent;
162       lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
163
164       DPLAYX_ReleaseSemaphore();
165       return TRUE;
166     }
167   }
168
169   DPLAYX_ReleaseSemaphore();
170   return FALSE;
171 }
172
173 /* I'm not sure when I'm going to need this, but here it is */
174 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID ) 
175 {
176   UINT i;
177
178   DPLAYX_AquireSemaphore();
179
180   /* Find an empty space in the list and insert the data */
181   for( i=0; i < numSupportedLobbies; i++ )
182   {
183     if( lobbyData[ i ].dwAppID == dwAppID )
184     {
185       /* Mark this entry unused */
186       DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
187
188       DPLAYX_ReleaseSemaphore();
189       return TRUE;
190     }
191   }
192
193   DPLAYX_ReleaseSemaphore();
194   ERR( "Unable to find global entry for application\n" );
195   return FALSE;
196 }
197
198 HRESULT DPLAYX_GetConnectionSettingsA
199 ( DWORD dwAppID,
200   LPVOID lpData,
201   LPDWORD lpdwDataSize )
202 {
203   lpDirectPlayLobbyData lpDplData;
204   LPDPLCONNECTION lpDplConnection;
205
206   /* Verify buffer size */
207   if ( ( lpData == NULL ) ||
208        ( *lpdwDataSize < sizeof( DPLCONNECTION ) )
209      )
210   {
211     *lpdwDataSize = sizeof( DPLCONNECTION );
212
213     return DPERR_BUFFERTOOSMALL;
214   }
215
216   DPLAYX_AquireSemaphore();
217
218   if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
219   {
220     DPLAYX_ReleaseSemaphore();
221     return DPERR_NOTLOBBIED;
222   }
223
224   /* Copy the information */
225   lpDplConnection = (LPDPLCONNECTION)lpData;
226
227   /* Copy everything we've got into here */
228   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
229   lpDplConnection->dwSize = sizeof( DPLCONNECTION );
230   lpDplConnection->dwFlags = lpDplData->dwConnFlags;
231
232   /* Copy LPDPSESSIONDESC2 struct */
233   lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->sessionDesc ) );
234   memcpy( lpDplConnection->lpSessionDesc, &lpDplData->sessionDesc, sizeof( lpDplData->sessionDesc ) );
235
236   if( lpDplData->sessionDesc.sess.lpszSessionNameA )
237   {
238     lpDplConnection->lpSessionDesc->sess.lpszSessionNameA =
239       HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.sess.lpszSessionNameA );
240   }
241
242   if( lpDplData->sessionDesc.pass.lpszPasswordA )
243   {
244     lpDplConnection->lpSessionDesc->pass.lpszPasswordA =
245       HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.pass.lpszPasswordA );
246   }
247
248   lpDplConnection->lpSessionDesc->dwReserved1 = lpDplData->sessionDesc.dwReserved1;
249   lpDplConnection->lpSessionDesc->dwReserved2 = lpDplData->sessionDesc.dwReserved2;
250
251   /* Copy DPNAME struct - seems to be optional - check for existance first */
252   lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->playerName ) );
253   memcpy( lpDplConnection->lpPlayerName, &(lpDplData->playerName), sizeof( lpDplData->playerName ) );
254
255   if( lpDplData->playerName.psn.lpszShortNameA )
256   {
257     lpDplConnection->lpPlayerName->psn.lpszShortNameA =
258       HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.psn.lpszShortNameA );
259   }
260
261   if( lpDplData->playerName.pln.lpszLongNameA )
262   {
263     lpDplConnection->lpPlayerName->pln.lpszLongNameA =
264       HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.pln.lpszLongNameA );
265   }
266
267   memcpy( &lpDplConnection->guidSP, &lpDplData->guidSP, sizeof( lpDplData->guidSP ) );
268
269   lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->dwAddressSize );
270   memcpy( lpDplConnection->lpAddress, lpDplData->lpAddress, lpDplData->dwAddressSize );
271
272   lpDplConnection->dwAddressSize = lpDplData->dwAddressSize;
273
274   /* FIXME: Send a message - or only the first time? */
275
276   DPLAYX_ReleaseSemaphore();
277
278   return DP_OK;
279 }
280
281 HRESULT DPLAYX_GetConnectionSettingsW
282 ( DWORD dwAppID,
283   LPVOID lpData,
284   LPDWORD lpdwDataSize )
285 {
286   lpDirectPlayLobbyData lpDplData;
287   LPDPLCONNECTION lpDplConnection;
288
289   /* Verify buffer size */
290   if ( ( lpData == NULL ) ||
291        ( *lpdwDataSize < sizeof( DPLCONNECTION ) )
292      )
293   {
294     *lpdwDataSize = sizeof( DPLCONNECTION );
295
296     return DPERR_BUFFERTOOSMALL;
297   }
298
299   DPLAYX_AquireSemaphore();
300
301   if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
302   {
303     DPLAYX_ReleaseSemaphore();
304     return DPERR_NOTLOBBIED;
305   }
306
307   /* Copy the information */
308   lpDplConnection = (LPDPLCONNECTION)lpData;
309
310   /* Copy everything we've got into here */
311   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
312   lpDplConnection->dwSize = sizeof( DPLCONNECTION );
313   lpDplConnection->dwFlags = lpDplData->dwConnFlags;
314
315   /* Copy LPDPSESSIONDESC2 struct */
316   lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->sessionDesc ) );
317   memcpy( lpDplConnection->lpSessionDesc, &lpDplData->sessionDesc, sizeof( lpDplData->sessionDesc ) );
318
319   if( lpDplData->sessionDesc.sess.lpszSessionName )
320   {
321     lpDplConnection->lpSessionDesc->sess.lpszSessionName =
322       HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.sess.lpszSessionName );
323   }
324
325   if( lpDplData->sessionDesc.pass.lpszPassword )
326   {
327     lpDplConnection->lpSessionDesc->pass.lpszPassword =
328       HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.pass.lpszPassword );
329   }
330
331   lpDplConnection->lpSessionDesc->dwReserved1 = lpDplData->sessionDesc.dwReserved1;
332   lpDplConnection->lpSessionDesc->dwReserved2 = lpDplData->sessionDesc.dwReserved2;
333
334   /* Copy DPNAME struct - seems to be optional - check for existance first */
335   lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->playerName ) );
336   memcpy( lpDplConnection->lpPlayerName, &(lpDplData->playerName), sizeof( lpDplData->playerName ) );
337
338   if( lpDplData->playerName.psn.lpszShortName )
339   {
340     lpDplConnection->lpPlayerName->psn.lpszShortName =
341       HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.psn.lpszShortName );
342   }
343
344   if( lpDplData->playerName.pln.lpszLongName )
345   {
346     lpDplConnection->lpPlayerName->pln.lpszLongName =
347       HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.pln.lpszLongName );
348   }
349
350   memcpy( &lpDplConnection->guidSP, &lpDplData->guidSP, sizeof( lpDplData->guidSP ) );
351
352   lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->dwAddressSize );
353   memcpy( lpDplConnection->lpAddress, lpDplData->lpAddress, lpDplData->dwAddressSize );
354
355   lpDplConnection->dwAddressSize = lpDplData->dwAddressSize;
356
357   /* FIXME: Send a message - or only the first time? */
358
359   DPLAYX_ReleaseSemaphore();
360
361   return DP_OK;
362 }
363
364
365 HRESULT DPLAYX_SetConnectionSettingsA
366 ( DWORD dwFlags,
367   DWORD dwAppID,
368   LPDPLCONNECTION lpConn )
369 {
370   lpDirectPlayLobbyData lpDplData;
371
372   /* Paramater check */
373   if( dwFlags || !lpConn )
374   {
375     ERR("invalid parameters.\n");
376     return DPERR_INVALIDPARAMS;
377   }
378
379   /* Store information */
380   if(  lpConn->dwSize != sizeof(DPLCONNECTION) )
381   {
382     ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
383          lpConn->dwSize, sizeof( DPLCONNECTION ) );
384
385     return DPERR_INVALIDPARAMS;
386   }
387
388   if( dwAppID == 0 )
389   {
390     dwAppID = GetCurrentProcessId();
391   }
392
393   DPLAYX_AquireSemaphore();
394
395   if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
396   {
397     /* FIXME: Create a new entry for this dwAppID? */
398     DPLAYX_ReleaseSemaphore();
399
400     return DPERR_GENERIC;
401   }
402
403   /* Store information */
404   if(  lpConn->dwSize != sizeof(DPLCONNECTION) )
405   {
406     DPLAYX_ReleaseSemaphore();
407
408     ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
409          lpConn->dwSize, sizeof( DPLCONNECTION ) );
410
411     return DPERR_INVALIDPARAMS;
412   }
413
414   /* Need to investigate the lpConn->lpSessionDesc to figure out
415    * what type of session we need to join/create.
416    */
417   if(  (!lpConn->lpSessionDesc ) ||
418        ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
419     )
420   {
421     DPLAYX_ReleaseSemaphore();
422
423     ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
424          lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
425
426     return DPERR_INVALIDPARAMS;
427   }
428
429   /* 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 */ 
430
431   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
432   lpDplData->dwConnFlags = lpConn->dwFlags;
433
434   /* Copy LPDPSESSIONDESC2 struct - this is required */
435   memcpy( &lpDplData->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
436
437   /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
438   if( lpConn->lpSessionDesc->sess.lpszSessionNameA )
439     lpDplData->sessionDesc.sess.lpszSessionNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionNameA );
440   else
441     lpDplData->sessionDesc.sess.lpszSessionNameA = NULL;
442
443   if( lpConn->lpSessionDesc->pass.lpszPasswordA )
444     lpDplData->sessionDesc.pass.lpszPasswordA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPasswordA );
445   else
446     lpDplData->sessionDesc.pass.lpszPasswordA = NULL;
447
448   lpDplData->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
449   lpDplData->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
450
451   /* Copy DPNAME struct - seems to be optional - check for existance first */
452   if( lpConn->lpPlayerName )
453   {
454      memcpy( &lpDplData->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
455
456      if( lpConn->lpPlayerName->psn.lpszShortNameA )
457        lpDplData->playerName.psn.lpszShortNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortNameA );
458
459      if( lpConn->lpPlayerName->pln.lpszLongNameA )
460        lpDplData->playerName.pln.lpszLongNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongNameA );
461
462   }
463
464   memcpy( &lpDplData->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
465
466   lpDplData->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
467   memcpy( lpDplData->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
468
469   lpDplData->dwAddressSize = lpConn->dwAddressSize;
470
471   /* FIXME: Send a message - I think */
472
473   DPLAYX_ReleaseSemaphore();
474
475   return DP_OK;
476 }
477
478 HRESULT DPLAYX_SetConnectionSettingsW
479 ( DWORD dwFlags,
480   DWORD dwAppID,
481   LPDPLCONNECTION lpConn )
482 {
483   lpDirectPlayLobbyData lpDplData;
484
485   /* Paramater check */
486   if( dwFlags || !lpConn )
487   {
488     ERR("invalid parameters.\n");
489     return DPERR_INVALIDPARAMS;
490   }
491
492   /* Store information */
493   if(  lpConn->dwSize != sizeof(DPLCONNECTION) )
494   {
495     ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
496          lpConn->dwSize, sizeof( DPLCONNECTION ) );
497
498     return DPERR_INVALIDPARAMS;
499   }
500
501   if( dwAppID == 0 )
502   {
503     dwAppID = GetCurrentProcessId();
504   }
505
506   DPLAYX_AquireSemaphore();
507
508   if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
509   {
510     DPLAYX_ReleaseSemaphore();
511     return DPERR_NOTLOBBIED;
512   }
513
514   /* Need to investigate the lpConn->lpSessionDesc to figure out
515    * what type of session we need to join/create.
516    */
517   if(  (!lpConn->lpSessionDesc ) ||
518        ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
519     )
520   {
521     DPLAYX_ReleaseSemaphore();
522
523     ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
524          lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
525
526     return DPERR_INVALIDPARAMS;
527   }
528
529   /* 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 */ 
530
531   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
532   lpDplData->dwConnFlags = lpConn->dwFlags;
533
534   /* Copy LPDPSESSIONDESC2 struct - this is required */
535   memcpy( &lpDplData->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
536
537   /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
538   if( lpConn->lpSessionDesc->sess.lpszSessionName )
539     lpDplData->sessionDesc.sess.lpszSessionName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionName );
540   else
541     lpDplData->sessionDesc.sess.lpszSessionName = NULL;
542
543   if( lpConn->lpSessionDesc->pass.lpszPassword )
544     lpDplData->sessionDesc.pass.lpszPassword = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPassword );
545   else
546     lpDplData->sessionDesc.pass.lpszPassword = NULL;
547
548   lpDplData->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
549   lpDplData->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
550
551   /* Copy DPNAME struct - seems to be optional - check for existance first */
552   if( lpConn->lpPlayerName )
553   {
554      memcpy( &lpDplData->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
555
556      if( lpConn->lpPlayerName->psn.lpszShortName )
557        lpDplData->playerName.psn.lpszShortName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortName );
558
559      if( lpConn->lpPlayerName->pln.lpszLongName )
560        lpDplData->playerName.pln.lpszLongName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongName );
561
562   }
563
564   memcpy( &lpDplData->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
565
566   lpDplData->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
567   memcpy( lpDplData->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
568
569   lpDplData->dwAddressSize = lpConn->dwAddressSize;
570
571   /* FIXME: Send a message - I think */
572
573   DPLAYX_ReleaseSemaphore();
574
575   return DP_OK;
576 }
577
578 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up 
579          with the correct string printed in the case where the HRESULT is not
580          known. You'll just get the last hr passed in printed. This can change
581          over time if this method is used alot :) */
582 LPCSTR DPLAYX_HresultToString(HRESULT hr)
583 {
584   static char szTempStr[12];
585
586   switch (hr)
587   {
588     case DP_OK:  
589       return "DP_OK";
590     case DPERR_ALREADYINITIALIZED: 
591       return "DPERR_ALREADYINITIALIZED";
592     case DPERR_ACCESSDENIED: 
593       return "DPERR_ACCESSDENIED";
594     case DPERR_ACTIVEPLAYERS: 
595       return "DPERR_ACTIVEPLAYERS";
596     case DPERR_BUFFERTOOSMALL: 
597       return "DPERR_BUFFERTOOSMALL";
598     case DPERR_CANTADDPLAYER: 
599       return "DPERR_CANTADDPLAYER";
600     case DPERR_CANTCREATEGROUP: 
601       return "DPERR_CANTCREATEGROUP";
602     case DPERR_CANTCREATEPLAYER: 
603       return "DPERR_CANTCREATEPLAYER";
604     case DPERR_CANTCREATESESSION: 
605       return "DPERR_CANTCREATESESSION";
606     case DPERR_CAPSNOTAVAILABLEYET: 
607       return "DPERR_CAPSNOTAVAILABLEYET";
608     case DPERR_EXCEPTION: 
609       return "DPERR_EXCEPTION";
610     case DPERR_GENERIC: 
611       return "DPERR_GENERIC";
612     case DPERR_INVALIDFLAGS: 
613       return "DPERR_INVALIDFLAGS";
614     case DPERR_INVALIDOBJECT: 
615       return "DPERR_INVALIDOBJECT";
616     case DPERR_INVALIDPARAMS: 
617       return "DPERR_INVALIDPARAMS";
618     case DPERR_INVALIDPLAYER: 
619       return "DPERR_INVALIDPLAYER";
620     case DPERR_INVALIDGROUP: 
621       return "DPERR_INVALIDGROUP";
622     case DPERR_NOCAPS: 
623       return "DPERR_NOCAPS";
624     case DPERR_NOCONNECTION: 
625       return "DPERR_NOCONNECTION";
626     case DPERR_OUTOFMEMORY: 
627       return "DPERR_OUTOFMEMORY";
628     case DPERR_NOMESSAGES: 
629       return "DPERR_NOMESSAGES";
630     case DPERR_NONAMESERVERFOUND: 
631       return "DPERR_NONAMESERVERFOUND";
632     case DPERR_NOPLAYERS: 
633       return "DPERR_NOPLAYERS";
634     case DPERR_NOSESSIONS: 
635       return "DPERR_NOSESSIONS";
636 /* This one isn't defined yet in WINE sources. I don't know the value
637     case DPERR_PENDING: 
638       return "DPERR_PENDING";
639 */
640     case DPERR_SENDTOOBIG: 
641       return "DPERR_SENDTOOBIG";
642     case DPERR_TIMEOUT: 
643       return "DPERR_TIMEOUT";
644     case DPERR_UNAVAILABLE: 
645       return "DPERR_UNAVAILABLE";
646     case DPERR_UNSUPPORTED: 
647       return "DPERR_UNSUPPORTED";
648     case DPERR_BUSY: 
649       return "DPERR_BUSY";
650     case DPERR_USERCANCEL: 
651       return "DPERR_USERCANCEL";
652     case DPERR_NOINTERFACE: 
653       return "DPERR_NOINTERFACE";
654     case DPERR_CANNOTCREATESERVER: 
655       return "DPERR_CANNOTCREATESERVER";
656     case DPERR_PLAYERLOST: 
657       return "DPERR_PLAYERLOST";
658     case DPERR_SESSIONLOST: 
659       return "DPERR_SESSIONLOST";
660     case DPERR_UNINITIALIZED: 
661       return "DPERR_UNINITIALIZED";
662     case DPERR_NONEWPLAYERS: 
663       return "DPERR_NONEWPLAYERS";
664     case DPERR_INVALIDPASSWORD: 
665       return "DPERR_INVALIDPASSWORD";
666     case DPERR_CONNECTING: 
667       return "DPERR_CONNECTING";
668     case DPERR_CONNECTIONLOST: 
669       return "DPERR_CONNECTIONLOST";
670     case DPERR_UNKNOWNMESSAGE:
671       return "DPERR_UNKNOWNMESSAGE";
672     case DPERR_CANCELFAILED: 
673       return "DPERR_CANCELFAILED";
674     case DPERR_INVALIDPRIORITY: 
675       return "DPERR_INVALIDPRIORITY";
676     case DPERR_NOTHANDLED: 
677       return "DPERR_NOTHANDLED";
678     case DPERR_CANCELLED: 
679       return "DPERR_CANCELLED";
680     case DPERR_ABORTED: 
681       return "DPERR_ABORTED";
682     case DPERR_BUFFERTOOLARGE: 
683       return "DPERR_BUFFERTOOLARGE";
684     case DPERR_CANTCREATEPROCESS: 
685       return "DPERR_CANTCREATEPROCESS";
686     case DPERR_APPNOTSTARTED: 
687       return "DPERR_APPNOTSTARTED";
688     case DPERR_INVALIDINTERFACE: 
689       return "DPERR_INVALIDINTERFACE";
690     case DPERR_NOSERVICEPROVIDER: 
691       return "DPERR_NOSERVICEPROVIDER";
692     case DPERR_UNKNOWNAPPLICATION: 
693       return "DPERR_UNKNOWNAPPLICATION";
694     case DPERR_NOTLOBBIED: 
695       return "DPERR_NOTLOBBIED";
696     case DPERR_SERVICEPROVIDERLOADED: 
697       return "DPERR_SERVICEPROVIDERLOADED";
698     case DPERR_ALREADYREGISTERED: 
699       return "DPERR_ALREADYREGISTERED";
700     case DPERR_NOTREGISTERED: 
701       return "DPERR_NOTREGISTERED";
702     case DPERR_AUTHENTICATIONFAILED: 
703       return "DPERR_AUTHENTICATIONFAILED";
704     case DPERR_CANTLOADSSPI: 
705       return "DPERR_CANTLOADSSPI";
706     case DPERR_ENCRYPTIONFAILED: 
707       return "DPERR_ENCRYPTIONFAILED";
708     case DPERR_SIGNFAILED: 
709       return "DPERR_SIGNFAILED";
710     case DPERR_CANTLOADSECURITYPACKAGE: 
711       return "DPERR_CANTLOADSECURITYPACKAGE";
712     case DPERR_ENCRYPTIONNOTSUPPORTED: 
713       return "DPERR_ENCRYPTIONNOTSUPPORTED";
714     case DPERR_CANTLOADCAPI: 
715       return "DPERR_CANTLOADCAPI";
716     case DPERR_NOTLOGGEDIN: 
717       return "DPERR_NOTLOGGEDIN";
718     case DPERR_LOGONDENIED: 
719       return "DPERR_LOGONDENIED";
720     default:
721       /* For errors not in the list, return HRESULT as a string
722          This part is not thread safe */
723       WARN( "Unknown error 0x%08lx\n", hr );
724       sprintf( szTempStr, "0x%08lx", hr );
725       return szTempStr;
726   }
727 }
728