You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
906 lines
22 KiB
906 lines
22 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: dplaysvr.c
|
|
* Content: dplay winsock shared .exe - allows multiple apps to share
|
|
* a single winsock port
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 2/10/97 andyco created it from ddhelp
|
|
* 29-jan-98 sohailm added support for stream enum sessions
|
|
* 1/12/2000 aarono added support for rsip
|
|
* 11/29/2000 aarono B#228292: prefix bug initialize path in WinMain()
|
|
*
|
|
***************************************************************************/
|
|
|
|
#ifdef WINNT
|
|
#ifdef DBG
|
|
#undef DEBUG
|
|
#define DEBUG
|
|
#endif
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include "dplaysvr.h"
|
|
#include "newdpf.h"
|
|
#include "memalloc.h"
|
|
#include "dphelp.h"
|
|
#if USE_RSIP
|
|
#include "rsip.h"
|
|
#elif USE_NATHELP
|
|
#include "dpnathlp.h"
|
|
#endif
|
|
|
|
#if USE_RSIP
|
|
BOOL bRsip;
|
|
#endif
|
|
|
|
#if USE_NATHELP
|
|
extern BOOL natGetCapsUpdate(VOID);
|
|
extern BOOL natInit(VOID);
|
|
extern VOID natFini(VOID);
|
|
extern HRESULT natRegisterUDPPort(DWORD port);
|
|
extern IDirectPlayNATHelp *g_pINatHelp;
|
|
#endif
|
|
|
|
HANDLE hInstApp;
|
|
BOOL bNoCallbacks;
|
|
CRITICAL_SECTION gcsCritSection; // the crit section we take in winmain
|
|
// this is a global so dphelp can take it before
|
|
// forwarding enum requests that come in on its
|
|
// receive thread (manbugs 3907)
|
|
int gnCSCount; // dplaysvr lock count
|
|
|
|
/*
|
|
* Externs
|
|
*/
|
|
extern RECEIVELIST gReceiveList;
|
|
extern FDS gReadfds;
|
|
|
|
|
|
// we watch every dplay process so when it exits we
|
|
// make sure it cleaned up...
|
|
typedef struct _PROCESSDATA
|
|
{
|
|
struct _PROCESSDATA *link;
|
|
DWORD pid;
|
|
} PROCESSDATA, *LPPROCESSDATA;
|
|
|
|
LPPROCESSDATA lpProcessList; // list of all processes that are registered
|
|
// with us
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// Globals
|
|
//**********************************************************************
|
|
BOOL g_fDaclInited = FALSE;
|
|
SECURITY_ATTRIBUTES g_sa;
|
|
BYTE g_abSD[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
|
PSECURITY_ATTRIBUTES g_psa = NULL;
|
|
PACL g_pEveryoneACL = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* ThreadProc
|
|
*
|
|
* Open a process and wait for it to terminate
|
|
*/
|
|
DWORD WINAPI ThreadProc( LPVOID *pdata )
|
|
{
|
|
HANDLE hproc;
|
|
DWORD rc;
|
|
LPPROCESSDATA ppd;
|
|
LPPROCESSDATA curr;
|
|
LPPROCESSDATA prev;
|
|
PROCESSDATA pd;
|
|
DPHELPDATA hd;
|
|
|
|
ppd = (LPPROCESSDATA) pdata;
|
|
|
|
/*
|
|
* get a handle to the process that attached to DDRAW
|
|
*/
|
|
DPF( 2, "Watchdog thread started for pid %08lx", ppd->pid );
|
|
|
|
hproc = OpenProcess( PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
|
|
FALSE, ppd->pid );
|
|
if( hproc == NULL )
|
|
{
|
|
DPF( 1, "OpenProcess for %08lx failed!", ppd->pid );
|
|
ExitThread( 0 );
|
|
}
|
|
|
|
/*
|
|
* wait for process to die
|
|
*/
|
|
rc = WaitForSingleObject( hproc, INFINITE );
|
|
if( rc == WAIT_FAILED )
|
|
{
|
|
DPF( 1, "Wait for process %08lx failed", ppd->pid );
|
|
CloseHandle( hproc );
|
|
ExitThread( 0 );
|
|
}
|
|
|
|
/*
|
|
* remove process from the list of watched processes
|
|
*/
|
|
ENTER_DPLAYSVR();
|
|
pd = *ppd;
|
|
curr = lpProcessList;
|
|
prev = NULL;
|
|
while( curr != NULL )
|
|
{
|
|
if( curr == ppd )
|
|
{
|
|
if( prev == NULL )
|
|
{
|
|
lpProcessList = curr->link;
|
|
}
|
|
else
|
|
{
|
|
prev->link = curr->link;
|
|
}
|
|
DPF( 2, "PID %08lx removed from list", ppd->pid );
|
|
MemFree( curr );
|
|
break;
|
|
}
|
|
prev = curr;
|
|
curr = curr->link;
|
|
}
|
|
|
|
if( bNoCallbacks )
|
|
{
|
|
DPF( 1, "No callbacks allowed: leaving thread early" );
|
|
LEAVE_DPLAYSVR();
|
|
CloseHandle( hproc );
|
|
ExitThread( 0 );
|
|
}
|
|
|
|
|
|
// clean up!
|
|
|
|
memset(&hd,0,sizeof(hd));
|
|
hd.pid = pd.pid;
|
|
DPlayHelp_DeleteServer(&hd,TRUE);
|
|
|
|
LEAVE_DPLAYSVR();
|
|
CloseHandle( hproc );
|
|
|
|
ExitThread( 0 );
|
|
|
|
return 0;
|
|
|
|
} /* ThreadProc */
|
|
|
|
/*
|
|
* MainWndProc
|
|
*/
|
|
LONG_PTR __stdcall MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch(message)
|
|
{
|
|
case WM_ENDSESSION:
|
|
/*
|
|
* shoot ourselves in the head
|
|
*/
|
|
if( lParam == FALSE )
|
|
{
|
|
DPF( 3, "WM_ENDSESSION" );
|
|
ENTER_DPLAYSVR();
|
|
DPF( 1, "Setting NO CALLBACKS" );
|
|
bNoCallbacks = TRUE;
|
|
LEAVE_DPLAYSVR();
|
|
}
|
|
else
|
|
{
|
|
DPF( 3, "User logging off" );
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
} /* MainWndProc */
|
|
|
|
/*
|
|
* WindowThreadProc
|
|
*/
|
|
void WindowThreadProc( LPVOID pdata )
|
|
{
|
|
static char szClassName[] = "DPlayHelpWndClass";
|
|
WNDCLASS cls;
|
|
MSG msg;
|
|
HWND hwnd;
|
|
|
|
/*
|
|
* build class and create window
|
|
*/
|
|
cls.lpszClassName = szClassName;
|
|
cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
|
cls.hInstance = hInstApp;
|
|
cls.hIcon = NULL;
|
|
cls.hCursor = NULL;
|
|
cls.lpszMenuName = NULL;
|
|
cls.style = 0;
|
|
cls.lpfnWndProc = MainWndProc;
|
|
cls.cbWndExtra = 0;
|
|
cls.cbClsExtra = 0;
|
|
|
|
if( !RegisterClass( &cls ) )
|
|
{
|
|
DPF( 1, "RegisterClass FAILED!" );
|
|
ExitThread( 0 );
|
|
}
|
|
|
|
hwnd = CreateWindow( szClassName, szClassName,
|
|
WS_POPUP, 0, 0, 0, 0, NULL, NULL, hInstApp, NULL);
|
|
|
|
if( hwnd == NULL )
|
|
{
|
|
DPF( 1, "No monitor window!" );
|
|
ExitThread( 0 );
|
|
}
|
|
|
|
/*
|
|
* pump the messages
|
|
*/
|
|
while( GetMessage( &msg, NULL, 0, 0 ) )
|
|
{
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
}
|
|
DPF( 1, "Exiting WindowThreadProc" );
|
|
ExitThread( 1 );
|
|
|
|
} /* WindowThreadProc */
|
|
|
|
//
|
|
// called by by DPlayHelp_AddServer when we get a new process attached.
|
|
// we wait for the process to go away, and then make sure it cleaned
|
|
// all its registered servers up.
|
|
//
|
|
void WatchNewPid(LPDPHELPDATA phd)
|
|
{
|
|
LPPROCESSDATA ppd;
|
|
BOOL found;
|
|
DWORD tid;
|
|
|
|
DPF( 1, "watching new pid" );
|
|
|
|
ENTER_DPLAYSVR();
|
|
|
|
ppd = lpProcessList;
|
|
found = FALSE;
|
|
while( ppd != NULL )
|
|
{
|
|
if( ppd->pid == phd->pid )
|
|
{
|
|
DPF( 2, "Have thread for process %08lx already", phd->pid );
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
ppd = ppd->link;
|
|
}
|
|
|
|
/*
|
|
* couldn't find anyone waiting on this process, so create
|
|
* a brand spanking new thread
|
|
*/
|
|
if( !found )
|
|
{
|
|
DPF( 2, "Allocating new thread for process %08lx",phd->pid );
|
|
ppd = MemAlloc( sizeof( PROCESSDATA ) );
|
|
if( ppd != NULL )
|
|
{
|
|
HANDLE h;
|
|
|
|
ppd->link = lpProcessList;
|
|
lpProcessList = ppd;
|
|
ppd->pid = phd->pid;
|
|
h = CreateThread(NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE) ThreadProc,
|
|
(LPVOID)ppd,
|
|
0,
|
|
(LPDWORD)&tid);
|
|
if( h != NULL )
|
|
{
|
|
DPF( 2, "Thread %08lx created",tid);
|
|
CloseHandle( h );
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
DPF( 0, "COULD NOT CREATE HELPER THREAD FOR PID %08lx", phd->pid );
|
|
DebugBreak(); //_asm int 3;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
DPF( 0, "OUT OF MEMORY CREATING HELPER THREAD FOR PID %08lx", phd->pid );
|
|
DebugBreak(); //_asm int 3;
|
|
#endif
|
|
}
|
|
}
|
|
LEAVE_DPLAYSVR();
|
|
|
|
} // WatchNewPid
|
|
|
|
typedef DWORD (WINAPI *PFNREGISTERSERVICE)(DWORD,DWORD);
|
|
// nt's winbase.h doesn't have these constants - we need them
|
|
// so we can compile. taken from \proj\dev\inc\winbase.h
|
|
#ifndef RSP_UNREGISTER_SERVICE
|
|
#define RSP_UNREGISTER_SERVICE 0x00000000
|
|
#endif
|
|
#ifndef RSP_SIMPLE_SERVICE
|
|
#define RSP_SIMPLE_SERVICE 0x00000001
|
|
#endif
|
|
|
|
// on Win95, we want to call RegisterServiceProcess
|
|
// but, it's not available on NT, so we can't import it directly
|
|
// here we try to find it dynamically in kernel32. if we find it,
|
|
// we call it, otherwise we assume we're on NT and it's not avaible
|
|
void MakeMeService()
|
|
{
|
|
HANDLE hLib;
|
|
PFNREGISTERSERVICE pfnRegisterServiceProcess;
|
|
|
|
hLib = LoadLibrary("kernel32.dll");
|
|
if (!hLib)
|
|
{
|
|
// wacky!
|
|
DPF(1,"could not load library kernel32 to register service proc");
|
|
return;
|
|
}
|
|
|
|
pfnRegisterServiceProcess = (PFNREGISTERSERVICE)GetProcAddress(hLib,"RegisterServiceProcess");
|
|
if (!pfnRegisterServiceProcess)
|
|
{
|
|
// this is expected on NT
|
|
DPF(3,"could not register service process - expected on NT");
|
|
FreeLibrary(hLib);
|
|
return ;
|
|
}
|
|
|
|
pfnRegisterServiceProcess( 0, RSP_SIMPLE_SERVICE );
|
|
FreeLibrary(hLib);
|
|
|
|
return ;
|
|
} // MakeMeService
|
|
|
|
// on Win95, we want to call RegisterServiceProcess to Unregister
|
|
// (see MakeMeService)
|
|
void StopServiceProcess()
|
|
{
|
|
HANDLE hLib;
|
|
PFNREGISTERSERVICE pfnRegisterServiceProcess;
|
|
|
|
hLib = LoadLibrary("kernel32.dll");
|
|
if (!hLib)
|
|
{
|
|
// wacky!
|
|
DPF(1,"could not load library kernel32 to register service proc");
|
|
return;
|
|
}
|
|
|
|
pfnRegisterServiceProcess = (PFNREGISTERSERVICE)GetProcAddress(hLib,"RegisterServiceProcess");
|
|
if (!pfnRegisterServiceProcess)
|
|
{
|
|
// this is expected on NT
|
|
DPF(3,"could not unregister service process - not avail - not tragic");
|
|
FreeLibrary(hLib);
|
|
return ;
|
|
}
|
|
|
|
// unregistered!
|
|
pfnRegisterServiceProcess( 0, RSP_UNREGISTER_SERVICE );
|
|
FreeLibrary(hLib);
|
|
|
|
return ;
|
|
|
|
} // StopServiceProcess
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNGetNullDacl - Get a SECURITY_ATTRIBUTE structure that specifies a
|
|
// NULL DACL which is accessible by all users.
|
|
// Taken from IDirectPlay8 code base.
|
|
//
|
|
// Entry: Nothing
|
|
//
|
|
// Exit: PSECURITY_ATTRIBUTES
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNGetNullDacl"
|
|
PSECURITY_ATTRIBUTES DNGetNullDacl()
|
|
{
|
|
PSID psidEveryone = NULL;
|
|
SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY;
|
|
DWORD dwAclSize;
|
|
|
|
// This is done to make this function independent of DNOSIndirectionInit so that the debug
|
|
// layer can call it before the indirection layer is initialized.
|
|
if (!g_fDaclInited)
|
|
{
|
|
if (!InitializeSecurityDescriptor((SECURITY_DESCRIPTOR*)g_abSD, SECURITY_DESCRIPTOR_REVISION))
|
|
{
|
|
DPF(0, "Failed to initialize security descriptor" );
|
|
goto Error;
|
|
}
|
|
|
|
// Create SID for the Everyone group.
|
|
if (!AllocateAndInitializeSid(&siaWorld, 1, SECURITY_WORLD_RID, 0,
|
|
0, 0, 0, 0, 0, 0, &psidEveryone))
|
|
{
|
|
DPF(0, "Failed to allocate Everyone SID" );
|
|
goto Error;
|
|
}
|
|
|
|
dwAclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidEveryone) - sizeof(DWORD);
|
|
|
|
// Allocate the ACL, this won't be a tracked allocation and we will let process cleanup destroy it
|
|
g_pEveryoneACL = (PACL)HeapAlloc(GetProcessHeap(), 0, dwAclSize);
|
|
if (g_pEveryoneACL == NULL)
|
|
{
|
|
DPF(0, "Failed to allocate ACL buffer" );
|
|
goto Error;
|
|
}
|
|
|
|
// Intialize the ACL.
|
|
if (!InitializeAcl(g_pEveryoneACL, dwAclSize, ACL_REVISION))
|
|
{
|
|
DPF(0, "Failed to initialize ACL" );
|
|
goto Error;
|
|
}
|
|
|
|
// Add the ACE.
|
|
if (!AddAccessAllowedAce(g_pEveryoneACL, ACL_REVISION, GENERIC_ALL, psidEveryone))
|
|
{
|
|
DPF(0, "Failed to add ACE to ACL" );
|
|
goto Error;
|
|
}
|
|
|
|
// We no longer need the SID that was allocated.
|
|
FreeSid(psidEveryone);
|
|
psidEveryone = NULL;
|
|
|
|
// Add the ACL to the security descriptor..
|
|
if (!SetSecurityDescriptorDacl((SECURITY_DESCRIPTOR*)g_abSD, TRUE, g_pEveryoneACL, FALSE))
|
|
{
|
|
DPF(0, "Failed to add ACL to security descriptor" );
|
|
goto Error;
|
|
}
|
|
|
|
g_sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
g_sa.lpSecurityDescriptor = g_abSD;
|
|
g_sa.bInheritHandle = FALSE;
|
|
|
|
g_psa = &g_sa;
|
|
|
|
g_fDaclInited = TRUE;
|
|
}
|
|
Error:
|
|
if (psidEveryone)
|
|
{
|
|
FreeSid(psidEveryone);
|
|
psidEveryone = NULL;
|
|
}
|
|
return g_psa;
|
|
}
|
|
//**********************************************************************
|
|
|
|
/*
|
|
* WinMain
|
|
*/
|
|
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
DWORD tid;
|
|
DWORD rc;
|
|
OSVERSIONINFOA VersionInfo;
|
|
BOOL fUseGlobalNamespace;
|
|
HANDLE hstartevent;
|
|
HANDLE hstartupevent;
|
|
HANDLE hmutex;
|
|
HANDLE hackevent;
|
|
LPDPHELPDATA phd;
|
|
HANDLE hsharedmem;
|
|
HANDLE h;
|
|
char szSystemDir[MAX_PATH*sizeof(WCHAR)];
|
|
|
|
DWORD tWait;
|
|
|
|
#if (USE_RSIP || USE_NATHELP)
|
|
DWORD tLast;
|
|
DWORD tNow;
|
|
#define RSIP_RENEW_TEST_INTERVAL 60000
|
|
#endif
|
|
|
|
|
|
DPFINIT();
|
|
DPF( 2, "*** dplaysvr STARTED, PID=%08lx ***", GetCurrentProcessId() );
|
|
|
|
if( !MemInit() )
|
|
{
|
|
DPF( 1, "Could not init memory manager" );
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Set our working directory to the system directory.
|
|
* This prevents us from holding network connections open
|
|
* forever if the first DirectDraw app that we run is across
|
|
* a network connection.
|
|
*/
|
|
memset(szSystemDir, 0, sizeof(WCHAR));
|
|
GetSystemDirectory(szSystemDir, sizeof(szSystemDir));
|
|
SetCurrentDirectory(szSystemDir);
|
|
|
|
|
|
// Determine if we're running on NT.
|
|
memset(&VersionInfo, 0, sizeof(VersionInfo));
|
|
VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
|
|
if (GetVersionExA(&VersionInfo))
|
|
{
|
|
if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
DPF(2, "Running on NT version %u.%u.%u, using global namespace.",
|
|
VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion, VersionInfo.dwBuildNumber);
|
|
fUseGlobalNamespace = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DPF(2, "Running on 9x version %u.%u.%u, not using global namespace.",
|
|
VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion, LOWORD(VersionInfo.dwBuildNumber));
|
|
fUseGlobalNamespace = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = GetLastError();
|
|
DPF(0, "Could not determine OS version (err = %u), assuming global namespace not needed.", rc);
|
|
fUseGlobalNamespace = FALSE;
|
|
}
|
|
|
|
|
|
// try to register ourselves as a service so user can't see us
|
|
// in task list
|
|
MakeMeService();
|
|
|
|
#if 0
|
|
|
|
// andyco - not sure if we need this...
|
|
|
|
/*
|
|
* We must guarantee that DPHELP unloads after the last ddraw app,
|
|
* since ctrl-alt-del may have happened while an app held the ddraw
|
|
* lock, and DPHELP needs to clean up orphaned cheap ddraw mutex
|
|
* locks.
|
|
*/
|
|
if ( ! SetProcessShutdownParameters(0x100,SHUTDOWN_NORETRY) )
|
|
{
|
|
DPF(0,"dplaysvr could not set itself to shutdown last!");
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
hInstApp = hInstance;
|
|
|
|
/*
|
|
* create startup event
|
|
*/
|
|
if (fUseGlobalNamespace)
|
|
{
|
|
hstartupevent = CreateEvent( DNGetNullDacl(), TRUE, FALSE, "Global\\" DPHELP_STARTUP_EVENT_NAME );
|
|
}
|
|
else
|
|
{
|
|
hstartupevent = CreateEvent( NULL, TRUE, FALSE, DPHELP_STARTUP_EVENT_NAME );
|
|
}
|
|
if( hstartupevent == NULL )
|
|
{
|
|
DPF( 1, "Could not create startup event!" );
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* create shared memory area
|
|
*/
|
|
if (fUseGlobalNamespace)
|
|
{
|
|
hsharedmem = CreateFileMapping( INVALID_HANDLE_VALUE, DNGetNullDacl(),
|
|
PAGE_READWRITE, 0, sizeof( DPHELPDATA ),
|
|
"Global\\" DPHELP_SHARED_NAME );
|
|
}
|
|
else
|
|
{
|
|
hsharedmem = CreateFileMapping( INVALID_HANDLE_VALUE, NULL,
|
|
PAGE_READWRITE, 0, sizeof( DPHELPDATA ),
|
|
DPHELP_SHARED_NAME );
|
|
}
|
|
if( hsharedmem == NULL )
|
|
{
|
|
DPF( 1, "Could not create file mapping!" );
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* create mutex for people who want to use the shared memory area
|
|
*/
|
|
if (fUseGlobalNamespace)
|
|
{
|
|
hmutex = CreateMutex( DNGetNullDacl(), FALSE, "Global\\" DPHELP_MUTEX_NAME );
|
|
}
|
|
else
|
|
{
|
|
hmutex = CreateMutex( NULL, FALSE, DPHELP_MUTEX_NAME );
|
|
}
|
|
if( hmutex == NULL )
|
|
{
|
|
DPF( 1, "Could not create mutex " DPHELP_MUTEX_NAME );
|
|
CloseHandle( hsharedmem );
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* create events
|
|
*/
|
|
if (fUseGlobalNamespace)
|
|
{
|
|
hstartevent = CreateEvent( DNGetNullDacl(), FALSE, FALSE, "Global\\" DPHELP_EVENT_NAME );
|
|
}
|
|
else
|
|
{
|
|
hstartevent = CreateEvent( NULL, FALSE, FALSE, DPHELP_EVENT_NAME );
|
|
}
|
|
if( hstartevent == NULL )
|
|
{
|
|
DPF( 1, "Could not create event " DPHELP_EVENT_NAME );
|
|
CloseHandle( hmutex );
|
|
CloseHandle( hsharedmem );
|
|
return 0;
|
|
}
|
|
|
|
if (fUseGlobalNamespace)
|
|
{
|
|
hackevent = CreateEvent( DNGetNullDacl(), FALSE, FALSE, "Global\\" DPHELP_ACK_EVENT_NAME );
|
|
}
|
|
else
|
|
{
|
|
hackevent = CreateEvent( NULL, FALSE, FALSE, DPHELP_ACK_EVENT_NAME );
|
|
}
|
|
if( hackevent == NULL )
|
|
{
|
|
DPF( 1, "Could not create event " DPHELP_ACK_EVENT_NAME );
|
|
CloseHandle( hmutex );
|
|
CloseHandle( hsharedmem );
|
|
CloseHandle( hstartevent );
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Create window so we can get messages
|
|
*/
|
|
h = CreateThread(NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE) WindowThreadProc,
|
|
NULL,
|
|
0,
|
|
(LPDWORD)&tid );
|
|
if( h == NULL )
|
|
{
|
|
DPF( 1, "Create of WindowThreadProc FAILED!" );
|
|
CloseHandle( hackevent );
|
|
CloseHandle( hmutex );
|
|
CloseHandle( hsharedmem );
|
|
CloseHandle( hstartevent );
|
|
return 0;
|
|
}
|
|
CloseHandle( h );
|
|
|
|
/*
|
|
* serialize access to us
|
|
*/
|
|
INIT_DPLAYSVR_CSECT();
|
|
|
|
|
|
|
|
|
|
if (!gbIPStarted)
|
|
{
|
|
rc = StartupIP();
|
|
if (FAILED(rc))
|
|
{
|
|
DPF_ERR("dphelp : could not init wsock ! not adding server");
|
|
return (rc);
|
|
}
|
|
}
|
|
|
|
#if USE_RSIP
|
|
|
|
bRsip=rsipInit();
|
|
if(bRsip){
|
|
rsipListenPort(FALSE, SERVER_DGRAM_PORT, NULL, NULL);
|
|
}
|
|
#endif
|
|
|
|
#if USE_NATHELP
|
|
natInit();
|
|
if(g_pINatHelp){
|
|
natRegisterUDPPort(SERVER_DGRAM_PORT);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* let invoker and anyone else who comes along know we exist
|
|
*/
|
|
SetEvent( hstartupevent );
|
|
|
|
tLast=tNow=timeGetTime();
|
|
|
|
/*
|
|
* loop forever, processing requests
|
|
*/
|
|
while( 1 )
|
|
{
|
|
|
|
wait:
|
|
tWait=(tLast+RSIP_RENEW_TEST_INTERVAL)-tNow;
|
|
if((int)tWait < 0){
|
|
tWait=0;
|
|
}
|
|
ASSERT(!(tWait &0x80000000));
|
|
|
|
/*
|
|
* wait to be notified of a request
|
|
*/
|
|
DPF( 1, "Waiting for next request" );
|
|
rc = WaitForSingleObject( hstartevent, tWait );
|
|
|
|
#if (USE_RSIP || USE_NATHELP)
|
|
tNow=timeGetTime();
|
|
if(rc==WAIT_TIMEOUT)
|
|
{
|
|
tLast=tNow;
|
|
#if USE_RSIP
|
|
if(bRsip) {rsipPortExtend(tNow);}
|
|
#elif USE_NATHELP
|
|
if(g_pINatHelp){natGetCapsUpdate();}
|
|
#endif
|
|
goto wait;
|
|
}
|
|
#endif
|
|
|
|
if( rc == WAIT_FAILED )
|
|
{
|
|
DPF( 1, "Wait FAILED!!!" );
|
|
continue;
|
|
}
|
|
|
|
ENTER_DPLAYSVR();
|
|
phd = (LPDPHELPDATA) MapViewOfFile( hsharedmem, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
|
|
if( phd == NULL )
|
|
{
|
|
DPF( 1, "Could not create view of file!" );
|
|
LEAVE_DPLAYSVR();
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* find out what we need to do
|
|
*/
|
|
switch( phd->req )
|
|
{
|
|
case DPHELPREQ_SUICIDE:
|
|
DPF( 1, "DPHELPREQ_SUICIDE" );
|
|
|
|
|
|
#if USE_RSIP
|
|
if(bRsip){
|
|
rsipFini();
|
|
}
|
|
#endif
|
|
#if USE_NATHELP
|
|
if(g_pINatHelp){
|
|
natFini();
|
|
}
|
|
#endif
|
|
DPlayHelp_FreeServerList();
|
|
|
|
SetEvent( hackevent );
|
|
CloseHandle( hmutex );
|
|
UnmapViewOfFile( phd );
|
|
CloseHandle( hsharedmem );
|
|
CloseHandle( hstartevent );
|
|
if (gReceiveList.pConnection)
|
|
{
|
|
MemFree(gReceiveList.pConnection);
|
|
}
|
|
if (gReadfds.pfdbigset)
|
|
{
|
|
MemFree(gReadfds.pfdbigset);
|
|
}
|
|
FINI_DPLAYSVR_CSECT();
|
|
|
|
// This should be done after functions that use a Dacl will no longer be
|
|
// called (CreateMutex, CreateFile, etc).
|
|
if (g_pEveryoneACL)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, g_pEveryoneACL);
|
|
g_pEveryoneACL = NULL;
|
|
g_psa = NULL;
|
|
g_fDaclInited = FALSE;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
MemState();
|
|
#endif
|
|
DPF( 3, "Good Night Gracie" );
|
|
TerminateProcess( GetCurrentProcess(), 0 );
|
|
break;
|
|
|
|
case DPHELPREQ_RETURNHELPERPID:
|
|
|
|
DPF( 2, "DDHELPREQ_RETURNHELPERPID" );
|
|
phd->pid = GetCurrentProcessId();
|
|
break;
|
|
|
|
|
|
case DPHELPREQ_DPLAYADDSERVER:
|
|
|
|
DPF( 2, "DPHELPREQ_DPLAYADDSERVER" );
|
|
phd->hr = DPlayHelp_AddServer(phd);
|
|
#if USE_RSIP
|
|
if(!bRsip){
|
|
bRsip=rsipInit();
|
|
if(bRsip){
|
|
rsipListenPort(FALSE, SERVER_DGRAM_PORT, NULL, NULL);
|
|
}
|
|
}
|
|
#endif
|
|
#if USE_NATHELP
|
|
if(!g_pINatHelp){
|
|
natInit();
|
|
if(g_pINatHelp){
|
|
natRegisterUDPPort(SERVER_DGRAM_PORT);
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case DPHELPREQ_DPLAYDELETESERVER:
|
|
|
|
DPF( 2, "DPHELPREQ_DPLAYDELETESERVER" );
|
|
DPlayHelp_DeleteServer(phd,FALSE);
|
|
break;
|
|
|
|
default:
|
|
DPF( 1, "helper - Unknown Request???" );
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* let caller know we've got the news
|
|
*/
|
|
UnmapViewOfFile( phd );
|
|
SetEvent( hackevent );
|
|
LEAVE_DPLAYSVR();
|
|
}
|
|
|
|
StopServiceProcess();
|
|
|
|
} /* WinMain */
|
|
|