示例#1
0
文件: timer.c 项目: pvpgn/d2gs
/*********************************************************************
 * Purpose: to initialize the timer
 * Return: TRUE(success) or FALSE(failed)
 *********************************************************************/
int D2GSTimerInitialize(void)
{
    DWORD	dwThreadId;

    /* create stop event */
    hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!hStopEvent) {
        D2GSEventLog("D2GSTimerInitialize",
                     "Failed in creating event object. Code: %lu", GetLastError());
        return FALSE;
    }

    /* create the working thread */
    ghTimerThread = CreateThread(NULL, 0, D2GSTimerProcessor, NULL, 0, &dwThreadId);
    if (!ghTimerThread) {
        D2GSEventLog("D2GSTimerInitialize",
                     "Can't CreateThread D2GSTimerProcessor. Code: %lu", GetLastError());
        CleanupRoutineForTimer();
        return FALSE;
    }

    /* add to the cleanup routine list */
    if (CleanupRoutineInsert(CleanupRoutineForTimer, "D2GS Timer")) {
        return TRUE;
    } else {
        /* do some cleanup before quiting */
        CleanupRoutineForTimer();
        return FALSE;
    }

} /* End of D2GSTimerInitialize() */
示例#2
0
文件: vars.c 项目: pvpgn/d2gs11
/*********************************************************************
 * Purpose: to initialize the global variables
 * Return: TRUE or FALSE
 *********************************************************************/
int D2GSVarsInitialize(void)
{
    DWORD	val;

    ZeroMemory(&d2gsconf, sizeof(d2gsconf));
    bGERunning = FALSE;

    /* calculate file checksum */
    val = VersionCheck();
    if (!val) {
        D2GSEventLog("D2GSVarsInitialize", "Failed calculating file checksum");
        return FALSE;
    }
    d2gsconf.checksum = val;

    /* initialize char list table */
    if (charlist_init(DEFAULT_HASHTBL_LEN)!=0) {
        D2GSEventLog("D2GSVarsInitialize", "Failed initialize charlist table");
        return FALSE;
    }

    /* initialize the CriticalSection Objects */
    InitializeCriticalSection(&csGameList);

    if (CleanupRoutineInsert(CleanupRoutineForVars, "Global Variables")) {
        return TRUE;
    } else {
        /* do some cleanup before quiting */
        CleanupRoutineForVars();
        return FALSE;
    }

} /* End of D2GSVarsInitialize() */
示例#3
0
文件: timer.c 项目: pvpgn/d2gs
/*********************************************************************
 * Purpose: timer processor
 * Return: return value of the thread
 *********************************************************************/
DWORD WINAPI D2GSTimerProcessor(LPVOID lpParameter)
{
    DWORD	dwWait;
    int		WaitSeq = 0;
    int		WaitSeq2 = 0;

    srand(time(NULL));
    while(TRUE)
    {
        dwWait = WaitForSingleObject(hStopEvent, TIMER_TICK_IN_MS);
        if (dwWait==WAIT_FAILED) {
            D2GSEventLog("D2GSTimerProcessor",
                         "WaitForSingleObject failed. Code: %lu", GetLastError());
            continue;
        } else if (dwWait==WAIT_OBJECT_0) {
            /* stop event be set, quit */
            D2GSEventLog("D2GSTimerProcessor", "Terminate timer thread");
            return TRUE;
        } else if (dwWait==WAIT_TIMEOUT) {
            /*char gamename[16];
            int i;
            DWORD x;*/
            /* a tick passed, call the routine to do something */
            WaitSeq ++;
            D2GSPendingCharTimerRoutine();
            D2GSGetDataRequestTimerRoutine();
            D2GSCalculateNetStatistic();
            D2GSSendMOTD();
            //just for test
            /*if (D2GSGetCurrentGameNumber()<(int)(d2gsconf.gsmaxgames))
            {
            	for (i = 0; i < 10; i ++) gamename[i] = 97 + rand() % 25;
            	gamename[10] = 0;
            	D2GSNewEmptyGame(gamename, "", "", 0x302004, 0x11, 0x22, 0x33, &x);
            }*/
            //
            if (WaitSeq > 10)
            {
                D2GSCheckGameLife();
                WaitSeq = 0;
            }
            S2STick();
        } else {
            continue;
        }
    }
    return 0;

} /* End of D2GSTimerProcessor() */
示例#4
0
文件: debug.c 项目: pvpgn/d2gs11
extern void DebugEventCallback(char const * module, int count, ...)
{
    SYSTEMTIME	st;
    va_list		ap;
    int		i,value;
    char		* name;
    char		function[MAX_LINE_LEN];

    if (!(d2gsconf.debugeventcallback)) return;
    GetLocalTime(&st);
    D2GSEventLog("DebugEventCallback","Event Called From Module \"%s\"",module);
    fprintf(hexstrm,"%d: Checking Module \"%s\" (%d)\tTime:%d.%d.%d.%d\n",\
            gdwTotalCount++,module,count,st.wHour,st.wMinute,\
            st.wSecond,st.wMilliseconds);
    sprintf (function,"%s(",module);
    va_start(ap,count);
    for (i=0; i<count; i++) {
        name=va_arg(ap, char *);
        value=va_arg(ap, int);
        strcat(function,name);
        if (i != count-1) strcat(function,", ");
        DebugDumpParam(name,value);
    }
    va_end(ap);
    strcat(function,")");
    fprintf(hexstrm,"Function: %s\n",function);
    fprintf(hexstrm,"\n\n");
    fflush(hexstrm);
    return;
}
示例#5
0
文件: d2ge.c 项目: pvpgn/d2gs109
/*********************************************************************
 * Purpose: D2 GE main thread
 * Return: return value of the thread
 *********************************************************************/
DWORD WINAPI D2GEThread(LPVOID lpParameter)
{
	DWORD			dwThreadId;
	DWORD			dwRetval;
	HANDLE			hObjects[2];
	DWORD			dwExitCode;
	HANDLE			hEvent;

	hEvent = (HANDLE)lpParameter;
	if (!hEvent) return FALSE;

	bGERunning = FALSE;
	gD2GSInfo.bStop = FALSE;
	hObjects[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
	gD2GSInfo.hEventInited = hObjects[0];
	if (!hObjects[0]) {
		D2GSEventLog("D2GEThread", "Error in CreateEvent. Code: %lu", GetLastError());
		SetEvent(hEvent);
		return FALSE;
	}

	hObjects[1] = CreateThread(NULL, 0, D2GSStart, &gD2GSInfo, 0, &dwThreadId);
	if (!hObjects[1]) {
		D2GSEventLog("D2GEThread", "Error Creating Server Thread. Code: %lu", GetLastError());
		CloseHandle(hObjects[0]);
		SetEvent(hEvent);
		return FALSE;
	} else {
		D2GSEventLog("D2GEThread", "Server Thread %lu Created", dwThreadId);
	}
	dwRetval = WaitForMultipleObjects(NELEMS(hObjects), hObjects, FALSE, D2GE_INIT_TIMEOUT);

	if (dwRetval==WAIT_FAILED) {
		D2GSEventLog("D2GEThread", "Wait Server Thread Failed. Code: %lu", GetLastError());
		SetEvent(hEvent);
	} else if (dwRetval==WAIT_TIMEOUT) {
		D2GSEventLog("D2GEThread", "Game Server Thread Timedout");
		SetEvent(hEvent);
	} else if (dwRetval==WAIT_OBJECT_0 + 1) {
		GetExitCodeThread(hObjects[1], &dwExitCode);
		D2GSEventLog("D2GEThread", "Game Server Thread Exit with %d", dwExitCode); 
		SetEvent(hEvent);
	} else if (dwRetval==WAIT_OBJECT_0) {
		D2GSEventLog("D2GEThread", "Game Server Thread Start Successfully");
		SetEvent(hEvent);
		bGERunning = TRUE;
	} else {
		D2GSEventLog("D2GEThread", "Wait Server Thread Returned %d", dwRetval);
		SetEvent(hEvent);
	}
	WaitForSingleObject(hObjects[1], INFINITE);
	CloseHandle(hObjects[0]);
	CloseHandle(hObjects[1]);
	bGERunning = FALSE;
	return TRUE;

} /* End of D2GEThread */
示例#6
0
文件: trunk.c 项目: 91D2/d2gs
int StartupTrunk()
{
	D2GSEventLog(__FUNCTION__, "Starting up Trunk...");
	trunkPipe = CreateFileA("\\\\.\\pipe\\d2gs_trunk_pipe_13", GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (!trunkPipe) return -1;
	CreateThread(NULL, 0, TrunkWorker, NULL, NULL, NULL);
	return 1;
}
示例#7
0
文件: d2ge.c 项目: pvpgn/d2gs109
/*********************************************************************
 * Purpose: to startup the D2 Game Engine
 * Return: TRUE(success) or FALSE(failed)
 *********************************************************************/
int D2GEStartup(void)
{
	HANDLE		hEvent;
	DWORD		dwThreadId;
	DWORD		dwWait;

	/* init GE thread */
	if (!D2GEThreadInit()) {
		D2GSEventLog("D2GEStartup", "Failed to Initialize Server");
		return FALSE;
	}

	/* create event for notification of GE startup */
	hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (!hEvent) return FALSE;

	/* startup the server thread */
	ghServerThread = CreateThread(NULL, 0, D2GEThread, (LPVOID)hEvent, 0, &dwThreadId);
	if (!ghServerThread) {
		D2GSEventLog("D2GEStartup", "Can't CreateThread D2GEThread. Code: %lu", GetLastError());
		CloseHandle(hEvent);
		return FALSE;
	}
	dwWait = WaitForSingleObject(hEvent, D2GE_INIT_TIMEOUT);
	if (dwWait!=WAIT_OBJECT_0) {
		CloseHandle(hEvent);
		return FALSE;
	}

	CloseHandle(hEvent);

	if (CleanupRoutineInsert(D2GECleanup, "Diablo II Game Engine")) {
		return TRUE;
	} else {
		/* do some cleanup before quiting */
		D2GECleanup();
		return FALSE;
	}

} /* End of D2GEStartup() */
示例#8
0
文件: d2ge.c 项目: pvpgn/d2gs109
/*********************************************************************
 * Purpose: called by Game Engine when error occur
 * Return: TRUE(success) or FALSE(failed)
 *********************************************************************/
static DWORD __stdcall D2GSErrorHandle(void)
{
	D2GSEventLog("D2GSErrorHandle", "Error occur, exiting...\n\n");

#ifdef DEBUG_ON_CONSOLE
	printf("Press Any Key to Continue");
	_getch();
#endif

	CloseServerMutex();
	ExitProcess(0);
	return 0;

} /* End of D2GSErrorHandle() */
示例#9
0
文件: trunk.c 项目: 91D2/d2gs
DWORD WINAPI TrunkWorker(LPVOID lpParam)
{
	char charname[17];
	int bytesRead;
	while (1)
	{
		if (ReadFile(trunkPipe, charname, 17, (LPDWORD)&bytesRead, NULL))
		{
			short port = 0;
#ifdef _STRESS_TEST
			DWORD dwGameId;
			int ge;
			printf("Creating %s\n", charname);
			ge = D2GSNewEmptyGame(charname, "", "", 0x300004, 0x11, 0x22, 0x33, &dwGameId);
			D2GSGameListInsert((UCHAR*)charname, (UCHAR*)"", (UCHAR*)"", (UCHAR*)charname, (UCHAR*)charname, (UCHAR*)"127.0.0.1", 1, 1,
					0, 0, dwGameId, ge);
			port = GetGEById(ge)->trunk_port;
#else
			D2CHARINFO* player = D2GSFindPendingCharByCharName((UCHAR*)charname);
			if (player != NULL)
			{
				port = GetGEById(player->ge)->trunk_port;
			}
#endif
			WriteFile(trunkPipe, &port, 2, (LPDWORD)&bytesRead, NULL);
		}
		else
		{
			int error = GetLastError();
			HANDLE StopEvent;
			if (error == ERROR_BROKEN_PIPE || error == ERROR_INVALID_HANDLE)
			{
				D2GSEventLog(__FUNCTION__, "Broken trunk detected, self destruction activated.");
				StopEvent = CreateEventA(0, 1, 0, D2GS_STOP_EVENT_NAME);
				if (StopEvent)
				{
					SetEvent(StopEvent);
					CloseHandle(StopEvent);
				}
				return 0;
			}
		}
	}
}
示例#10
0
文件: d2ge.c 项目: pvpgn/d2gs109
/*********************************************************************
 * Purpose: to initialize the D2 Game Engine thread
 * Return: TRUE(success) or FALSE(failed)
 *********************************************************************/
int D2GEThreadInit(void)
{
	if (!D2GSGetInterface()) {
		D2GSEventLog("D2GSThread", "Failed to Get Server Interface");
		return FALSE;
	}

	gD2GSInfo.szVersion				= D2GS_VERSION_STRING;
	gD2GSInfo.dwLibVersion			= D2GS_LIBRARY_VERSION;
	gD2GSInfo.bIsNT					= d2gsconf.enablentmode;
	gD2GSInfo.bEnablePatch			= d2gsconf.enablegepatch;
	gD2GSInfo.fpEventLog			= D2GEEventLog;
	gD2GSInfo.fpErrorHandle			= D2GSErrorHandle;
	gD2GSInfo.fpCallback			= EventCallbackTableInit();
	gD2GSInfo.bPreCache				= d2gsconf.enableprecachemode;
	gD2GSInfo.dwIdleSleep			= d2gsconf.idlesleep;
	gD2GSInfo.dwBusySleep			= d2gsconf.busysleep;
	gD2GSInfo.dwMaxGame				= d2gsconf.gemaxgames;
	gD2GSInfo.dwProcessAffinityMask = d2gsconf.multicpumask;
	return TRUE;

} /* D2GEThreadInit() */
示例#11
0
/*********************************************************************
 * Purpose: to read configurations to the D2GSCONFIGS structure
 * Return: TRUE(success) or FALSE(failed)
 *********************************************************************/
int D2GSReadConfig(void)
{
	HKEY		hKey;
	BOOL		result;
	u_long		ipaddr;
	DWORD		dwval;
	char		strbuf[256];

	result = FALSE;
	if (!RegkeyOpen(HKEY_LOCAL_MACHINE, REGKEY_ROOT, &hKey, KEY_READ)) {
		D2GSEventLog("D2GSReadConfig", "Can't open registry key '\\\\HKEY_LOCAL_MACHINE\\%s'", REGKEY_ROOT);
		//return result;
	}

	/* D2CSIP */
	if (!RegkeyReadString(hKey, REGKEY_D2CSIP, strbuf, sizeof(strbuf))) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s'", REGKEY_D2CSIP);
		goto tocloseregkey;
	}
	ipaddr = inet_addr(strbuf);
	if (ipaddr==INADDR_NONE) {
		D2GSEventLog("D2GSReadConfig", "Invalid D2CSIP '%s'", strbuf);
		goto tocloseregkey;
	}
	d2gsconf.d2csip = ipaddr;

	/* D2DBSIP */
	if (!RegkeyReadString(hKey, REGKEY_D2DBSIP, strbuf, sizeof(strbuf))) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s'", REGKEY_D2DBSIP);
		goto tocloseregkey;
	}
	ipaddr = inet_addr(strbuf);
	if (ipaddr==INADDR_NONE) {
		D2GSEventLog("D2GSReadConfig", "Invalid D2DBSIP '%s'", strbuf);
		goto tocloseregkey;
	}
	d2gsconf.d2dbsip = ipaddr;

	/* D2CSPORT */
	if (!RegkeyReadDWORD(hKey, REGKEY_D2CSPORT, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_D2CSPORT, DEFAULT_D2CS_PORT);
		d2gsconf.d2csport = DEFAULT_D2CS_PORT;
	} else
		d2gsconf.d2csport = htons((u_short)dwval);

	/* D2DBSPORT */
	if (!RegkeyReadDWORD(hKey, REGKEY_D2DBSPORT, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_D2DBSPORT, DEFAULT_D2DBS_PORT);
		d2gsconf.d2csport = DEFAULT_D2DBS_PORT;
	} else
		d2gsconf.d2dbsport = htons((short)dwval);

	/* MAXGAMES */
	if (!RegkeyReadDWORD(hKey, REGKEY_MAXGAMES, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_MAXGAMES, DEFAULT_MAX_GAMES);
		d2gsconf.gemaxgames = DEFAULT_MAX_GAMES;
	} else
		d2gsconf.gemaxgames = dwval;
	d2gsconf.gsmaxgames = 0;

	/* ENABLENTMODE */
	if (!RegkeyReadDWORD(hKey, REGKEY_ENABLENTMODE, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_ENABLENTMODE, DEFAULT_NT_MODE);
		d2gsconf.enablentmode = DEFAULT_NT_MODE;
	} else
		d2gsconf.enablentmode = (BOOL)dwval;

	/* ENABLEGEPATCH */
	if (!RegkeyReadDWORD(hKey, REGKEY_ENABLEGEPATCH, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_ENABLEGEPATCH, DEFAULT_GE_PATCH);
		d2gsconf.enablegepatch = DEFAULT_GE_PATCH;
	} else
		d2gsconf.enablegepatch = (BOOL)dwval;

	/* ENABLEPRECACHEMODE */
	if (!RegkeyReadDWORD(hKey, REGKEY_ENABLEPRECACHEMODE, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_ENABLEPRECACHEMODE, DEFAULT_PRECACHE_MODE);
		d2gsconf.enableprecachemode = DEFAULT_PRECACHE_MODE;
	} else
		d2gsconf.enableprecachemode = (BOOL)dwval;

	/* ENABLEGELOG */
	if (!RegkeyReadDWORD(hKey, REGKEY_ENABLEGELOG, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_ENABLEGELOG, DEFAULT_GE_LOG);
		d2gsconf.enablegelog = DEFAULT_GE_LOG;
	} else
		d2gsconf.enablegelog = (BOOL)dwval;

	/* ENABLEGSLOG */
	if (!RegkeyReadDWORD(hKey, REGKEY_ENABLEGSLOG, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_ENABLEGELOG, DEFAULT_GS_LOG);
		d2gsconf.enablegslog = DEFAULT_GS_LOG;
	} else
		d2gsconf.enablegslog = (BOOL)dwval;

	/* ENABLEGEMSG */
	if (!RegkeyReadDWORD(hKey, REGKEY_ENABLEGEMSG, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_ENABLEGEMSG, DEFAULT_GE_MSG);
		d2gsconf.enablegemsg = DEFAULT_GE_MSG;
	} else
		d2gsconf.enablegemsg = (BOOL)dwval;

	/* DEBUGNETPACKET */
	if (!RegkeyReadDWORD(hKey, REGKEY_DEBUGNETPACKET, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_DEBUGNETPACKET, DEFAULT_DEBUGNETPACKET);
		d2gsconf.debugnetpacket = DEFAULT_DEBUGNETPACKET;
	} else
		d2gsconf.debugnetpacket = (BOOL)dwval;

	/* DEBUGEVENTCALLBACK */
	if (!RegkeyReadDWORD(hKey, REGKEY_DEBUGEVENTCALLBACK, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_DEBUGEVENTCALLBACK, DEFAULT_DEBUGEVENTCALLBACK);
		d2gsconf.debugeventcallback = DEFAULT_DEBUGEVENTCALLBACK;
	} else
		d2gsconf.debugeventcallback = (BOOL)dwval;

	/* IDLESLEEP */
	if (!RegkeyReadDWORD(hKey, REGKEY_IDLESLEEP, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_IDLESLEEP, DEFAULT_IDLE_SLEEP);
		d2gsconf.idlesleep = DEFAULT_IDLE_SLEEP;
	} else
		d2gsconf.idlesleep = dwval;

	/* BUSYSLEEP */
	if (!RegkeyReadDWORD(hKey, REGKEY_BUSYSLEEP, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_BUSYSLEEP, DEFAULT_BUSY_SLEEP);
		d2gsconf.busysleep = DEFAULT_BUSY_SLEEP;
	} else
		d2gsconf.busysleep = dwval;

	/* CHARPENDINGTIMEOUT */
	if (!RegkeyReadDWORD(hKey, REGKEY_CHARPENDINGTIMEOUT, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_CHARPENDINGTIMEOUT, DEFAULT_CHARPENDINGTIMEOUT);
		d2gsconf.charpendingtimeout = DEFAULT_CHARPENDINGTIMEOUT;
	} else
		d2gsconf.charpendingtimeout = dwval;

	/* INTERVALRECONNECTD2CS */
	if (!RegkeyReadDWORD(hKey, REGKEY_INTERVALRECONNECTD2CS, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_INTERVALRECONNECTD2CS, DEFAULT_INTERVALRECONNECTD2CS);
		d2gsconf.intervalreconnectd2cs = DEFAULT_INTERVALRECONNECTD2CS;
	} else
		d2gsconf.intervalreconnectd2cs = dwval;

	/* ADMINPWD */
	ZeroMemory(d2gsconf.adminpwd, sizeof(d2gsconf.adminpwd));
	if (!RegkeyReadString(hKey, REGKEY_ADMINPWD, strbuf, sizeof(strbuf))) {
		strcpy(d2gsconf.adminpwd, "d2gsdmin");
	} else
		strncpy(d2gsconf.adminpwd, strbuf, sizeof(d2gsconf.adminpwd)-1);

	/* D2CSSECRECT */
	ZeroMemory(d2gsconf.d2cssecrect, sizeof(d2gsconf.d2cssecrect));
	if (!RegkeyReadString(hKey, REGKEY_D2CSSECRECT, strbuf, sizeof(strbuf))) {
		strcpy(d2gsconf.d2cssecrect, "");
	} else
		strncpy(d2gsconf.d2cssecrect, strbuf, sizeof(d2gsconf.d2cssecrect)-1);

	/* ADMINPORT */
	if (!RegkeyReadDWORD(hKey, REGKEY_ADMINPORT, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_ADMINPORT, DEFAULT_ADMIN_PORT);
		d2gsconf.adminport = DEFAULT_D2DBS_PORT;
	} else
		d2gsconf.adminport = htons((short)dwval);

	/* ADMINTIMEOUT */
	if (!RegkeyReadDWORD(hKey, REGKEY_ADMINTIMEOUT, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_ADMINTIMEOUT, DEFAULT_ADMIN_TIMEOUT);
		d2gsconf.admintimeout = DEFAULT_ADMIN_TIMEOUT;
	} else
		d2gsconf.admintimeout = dwval;

	/* MAXGAMELIFE */
	if (!RegkeyReadDWORD(hKey, REGKEY_MAXGAMELIFE, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_MAXGAMELIFE, DEFAULT_MAXGAMELIFE);
		d2gsconf.maxgamelife = DEFAULT_MAXGAMELIFE;
	} else
		d2gsconf.maxgamelife = dwval;

	/* GSSHUTDOWNINTERVAL */
	if (!RegkeyReadDWORD(hKey, REGKEY_GSSHUTDOWNINTERVAL, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_GSSHUTDOWNINTERVAL, DEFAULT_GS_SHUTDOWN_INTERVAL);
		d2gsconf.gsshutdowninterval = DEFAULT_GS_SHUTDOWN_INTERVAL;
	} else
		d2gsconf.gsshutdowninterval = dwval;

	/* MULTICPUMASK */
	if (!RegkeyReadDWORD(hKey, REGKEY_MULTICPUMASK, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_MULTICPUMASK, DEFAULT_MULTICPUMASK);
		d2gsconf.multicpumask = DEFAULT_MULTICPUMASK;
	} else
		d2gsconf.multicpumask = dwval;

	/* LISTENPORT */
	if (!RegkeyReadDWORD(hKey, REGKEY_LISTENPORT, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_LISTENPORT, DEFAULT_LISTENPORT);
		d2gsconf.listenport = DEFAULT_LISTENPORT;
	} else
		d2gsconf.listenport = dwval;

	/* LISTENADDR */
	ZeroMemory(d2gsconf.listenaddr, sizeof(d2gsconf.listenaddr));
	if (!RegkeyReadString(hKey, REGKEY_LISTENADDR, strbuf, sizeof(strbuf))) {
		strcpy(d2gsconf.listenaddr, "0.0.0.0");
	} else
		strncpy(d2gsconf.listenaddr, strbuf, sizeof(d2gsconf.listenaddr)-1);

	/* GETHREAD */
	if (!RegkeyReadDWORD(hKey, REGKEY_GETHREAD, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_GETHREAD, DEFAULT_GETHREAD);
		d2gsconf.gethread = DEFAULT_GETHREAD;
	} else
		d2gsconf.gethread = dwval;

	/* SYNPROT */
	if (!RegkeyReadDWORD(hKey, REGKEY_SYNPROT, &dwval)) {
		D2GSEventLog("D2GSReadConfig", "Can't read key '%s', set to default %d",
				REGKEY_SYNPROT, DEFAULT_SYNPROT);
		d2gsconf.synprot = DEFAULT_SYNPROT;
	} else
		d2gsconf.synprot = dwval;

	/* MOTD */
	ZeroMemory(d2gsconf.motd, sizeof(d2gsconf.motd));
	if (RegkeyReadString(hKey, REGKEY_MOTD, strbuf, sizeof(strbuf)))
		strncpy(d2gsconf.motd, strbuf, sizeof(d2gsconf.motd)-1);
	strcpy(d2gsconf.motd, strbuf);
	string_color(d2gsconf.motd);

	d2gsconf.eventmotd[0] = 0;
	d2gsconf.roomMotd[0] = 0;

	result = TRUE;

tocloseregkey:
	RegkeyClose(hKey);
	return result;

} /* End of D2GSReadConfig() */