📄 dplobby.c
字号:
static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication
( LPDIRECTPLAYLOBBYA iface,
DWORD dwFlags,
LPDWORD lpdwAppID,
LPDPLCONNECTION lpConn,
HANDLE hReceiveEvent )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
HRESULT hr;
RunApplicationEnumStruct enumData;
char temp[200];
STARTUPINFOA startupInfo;
PROCESS_INFORMATION newProcessInfo;
LPSTR appName;
DWORD dwSuspendCount;
HANDLE hStart, hDeath, hSettingRead;
TRACE( "(%p)->(0x%08lx,%p,%p,%p)\n",
This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
if( dwFlags != 0 )
{
return DPERR_INVALIDPARAMS;
}
if( DPLAYX_AnyLobbiesWaitingForConnSettings() )
{
FIXME( "Waiting lobby not being handled correctly\n" );
}
EnterCriticalSection( &This->unk->DPL_lock );
ZeroMemory( &enumData, sizeof( enumData ) );
enumData.This = This;
enumData.appGUID = lpConn->lpSessionDesc->guidApplication;
/* Our callback function will fill up the enumData structure with all the information
required to start a new process */
IDirectPlayLobby_EnumLocalApplications( iface, RunApplicationA_EnumLocalApplications,
(LPVOID)(&enumData), 0 );
/* First the application name */
strcpy( temp, enumData.lpszPath );
strcat( temp, "\\" );
strcat( temp, enumData.lpszFileName );
HeapFree( GetProcessHeap(), 0, enumData.lpszPath );
HeapFree( GetProcessHeap(), 0, enumData.lpszFileName );
if ((appName = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 ))) strcpy( appName, temp );
/* Now the command line */
strcat( temp, " " );
strcat( temp, enumData.lpszCommandLine );
HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
if ((enumData.lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 )))
strcpy( enumData.lpszCommandLine, temp );
ZeroMemory( &startupInfo, sizeof( startupInfo ) );
startupInfo.cb = sizeof( startupInfo );
/* FIXME: Should any fields be filled in? */
ZeroMemory( &newProcessInfo, sizeof( newProcessInfo ) );
if( !CreateProcessA( appName,
enumData.lpszCommandLine,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_SUSPENDED, /* Creation Flags */
NULL,
enumData.lpszCurrentDirectory,
&startupInfo,
&newProcessInfo
)
)
{
ERR( "Failed to create process for app %s\n", appName );
HeapFree( GetProcessHeap(), 0, appName );
HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
LeaveCriticalSection( &This->unk->DPL_lock );
return DPERR_CANTCREATEPROCESS;
}
HeapFree( GetProcessHeap(), 0, appName );
HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
/* Reserve this global application id! */
if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId ) )
{
ERR( "Unable to create global application data for 0x%08lx\n",
newProcessInfo.dwProcessId );
}
hr = IDirectPlayLobby_SetConnectionSettings( iface, 0, newProcessInfo.dwProcessId, lpConn );
if( hr != DP_OK )
{
ERR( "SetConnectionSettings failure %s\n", DPLAYX_HresultToString( hr ) );
LeaveCriticalSection( &This->unk->DPL_lock );
return hr;
}
/* Setup the handles for application notification */
DPL_CreateAndSetLobbyHandles( newProcessInfo.dwProcessId,
newProcessInfo.hProcess,
&hStart, &hDeath, &hSettingRead );
/* Setup the message thread ID */
This->dpl->dwMsgThread =
CreateLobbyMessageReceptionThread( hReceiveEvent, hStart, hDeath, hSettingRead );
DPLAYX_SetLobbyMsgThreadId( newProcessInfo.dwProcessId, This->dpl->dwMsgThread );
LeaveCriticalSection( &This->unk->DPL_lock );
/* Everything seems to have been set correctly, update the dwAppID */
*lpdwAppID = newProcessInfo.dwProcessId;
/* Unsuspend the process - should return the prev suspension count */
if( ( dwSuspendCount = ResumeThread( newProcessInfo.hThread ) ) != 1 )
{
ERR( "ResumeThread failed with 0x%08lx\n", dwSuspendCount );
}
return DP_OK;
}
static HRESULT WINAPI IDirectPlayLobbyWImpl_RunApplication
( LPDIRECTPLAYLOBBY iface,
DWORD dwFlags,
LPDWORD lpdwAppID,
LPDPLCONNECTION lpConn,
HANDLE hReceiveEvent )
{
IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
FIXME( "(%p)->(0x%08lx,%p,%p,%p):stub\n", This, dwFlags, lpdwAppID, lpConn, (void *)hReceiveEvent );
return DPERR_OUTOFMEMORY;
}
/********************************************************************
*
* Sends a message between the application and the lobby client.
* All messages are queued until received.
*
*/
static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage
( LPDIRECTPLAYLOBBYA iface,
DWORD dwFlags,
DWORD dwAppID,
LPVOID lpData,
DWORD dwDataSize )
{
FIXME(":stub\n");
return DPERR_OUTOFMEMORY;
}
static HRESULT WINAPI IDirectPlayLobbyWImpl_SendLobbyMessage
( LPDIRECTPLAYLOBBY iface,
DWORD dwFlags,
DWORD dwAppID,
LPVOID lpData,
DWORD dwDataSize )
{
FIXME(":stub\n");
return DPERR_OUTOFMEMORY;
}
/********************************************************************
*
* Modifies the DPLCONNECTION structure to contain all information
* needed to start and connect an application.
*
*/
static HRESULT WINAPI IDirectPlayLobbyWImpl_SetConnectionSettings
( LPDIRECTPLAYLOBBY iface,
DWORD dwFlags,
DWORD dwAppID,
LPDPLCONNECTION lpConn )
{
IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
HRESULT hr;
TRACE("(%p)->(0x%08lx,0x%08lx,%p)\n", This, dwFlags, dwAppID, lpConn );
EnterCriticalSection( &This->unk->DPL_lock );
hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
/* FIXME: Don't think that this is supposed to fail, but the docuementation
is somewhat sketchy. I'll try creating a lobby application
for this... */
if( hr == DPERR_NOTLOBBIED )
{
FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
if( dwAppID == 0 )
{
dwAppID = GetCurrentProcessId();
}
DPLAYX_CreateLobbyApplication( dwAppID );
hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
}
LeaveCriticalSection( &This->unk->DPL_lock );
return hr;
}
static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings
( LPDIRECTPLAYLOBBYA iface,
DWORD dwFlags,
DWORD dwAppID,
LPDPLCONNECTION lpConn )
{
IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
HRESULT hr;
TRACE("(%p)->(0x%08lx,0x%08lx,%p)\n", This, dwFlags, dwAppID, lpConn );
EnterCriticalSection( &This->unk->DPL_lock );
hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
/* FIXME: Don't think that this is supposed to fail, but the docuementation
is somewhat sketchy. I'll try creating a lobby application
for this... */
if( hr == DPERR_NOTLOBBIED )
{
FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
dwAppID = GetCurrentProcessId();
DPLAYX_CreateLobbyApplication( dwAppID );
hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
}
LeaveCriticalSection( &This->unk->DPL_lock );
return hr;
}
/********************************************************************
*
* Registers an event that will be set when a lobby message is received.
*
*/
static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent
( LPDIRECTPLAYLOBBYA iface,
DWORD dwFlags,
DWORD dwAppID,
HANDLE hReceiveEvent )
{
FIXME(":stub\n");
return DPERR_OUTOFMEMORY;
}
static HRESULT WINAPI IDirectPlayLobbyWImpl_SetLobbyMessageEvent
( LPDIRECTPLAYLOBBY iface,
DWORD dwFlags,
DWORD dwAppID,
HANDLE hReceiveEvent )
{
FIXME(":stub\n");
return DPERR_OUTOFMEMORY;
}
/* DPL 2 methods */
static HRESULT WINAPI IDirectPlayLobby2WImpl_CreateCompoundAddress
( LPDIRECTPLAYLOBBY2 iface,
LPCDPCOMPOUNDADDRESSELEMENT lpElements,
DWORD dwElementCount,
LPVOID lpAddress,
LPDWORD lpdwAddressSize )
{
return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, FALSE );
}
static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress
( LPDIRECTPLAYLOBBY2A iface,
LPCDPCOMPOUNDADDRESSELEMENT lpElements,
DWORD dwElementCount,
LPVOID lpAddress,
LPDWORD lpdwAddressSize )
{
return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, TRUE );
}
HRESULT DPL_CreateCompoundAddress
( LPCDPCOMPOUNDADDRESSELEMENT lpElements,
DWORD dwElementCount,
LPVOID lpAddress,
LPDWORD lpdwAddressSize,
BOOL bAnsiInterface )
{
DWORD dwSizeRequired = 0;
DWORD dwElements;
LPCDPCOMPOUNDADDRESSELEMENT lpOrigElements = lpElements;
TRACE("(%p,0x%08lx,%p,%p)\n", lpElements, dwElementCount, lpAddress, lpdwAddressSize );
/* Parameter check */
if( ( lpElements == NULL ) ||
( dwElementCount == 0 ) /* FIXME: Not sure if this is a failure case */
)
{
return DPERR_INVALIDPARAMS;
}
/* Add the total size chunk */
dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DWORD );
/* Calculate the size of the buffer required */
for ( dwElements = dwElementCount; dwElements > 0; --dwElements, ++lpElements )
{
if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
)
{
dwSizeRequired += sizeof( DPADDRESS ) + sizeof( GUID );
}
else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
)
{
if( !bAnsiInterface )
{
ERR( "Ansi GUIDs used for unicode interface\n" );
return DPERR_INVALIDFLAGS;
}
dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize;
}
else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
)
{
if( bAnsiInterface )
{
ERR( "Unicode GUIDs used for ansi interface\n" );
return DPERR_INVALIDFLAGS;
}
FIXME( "Right size for unicode interface?\n" );
dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize * sizeof( WCHAR );
}
else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
{
dwSizeRequired += sizeof( DPADDRESS ) + sizeof( WORD );
}
else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
{
FIXME( "Right size for unicode interface?\n" );
dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DPCOMPORTADDRESS ); /* FIXME: Right size? */
}
else
{
ERR( "Unknown GUID %s\n", debugstr_guid(&lpElements->guidDataType) );
return DPERR_INVALIDFLAGS;
}
}
/* The user wants to know how big a buffer to allocate for us */
if( ( lpAddress == NULL ) ||
( *lpdwAddressSize < dwSizeRequired )
)
{
*lpdwAddressSize = dwSizeRequired;
return DPERR_BUFFERTOOSMALL;
}
/* Add the total size chunk */
{
LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
CopyMemory( &lpdpAddress->guidDataType, &DPAID_TotalSize, sizeof( GUID ) );
lpdpAddress->dwDataSize = sizeof( DWORD );
lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
*(LPDWORD)lpAddress = dwSizeRequired;
lpAddress = (char *) lpAddress + sizeof( DWORD );
}
/* Calculate the size of the buffer required */
for( dwElements = dwElementCount, lpElements = lpOrigElements;
dwElements > 0;
--dwElements, ++lpElements )
{
if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
)
{
LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
sizeof( GUID ) );
lpdpAddress->dwDataSize = sizeof( GUID );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -