mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 10:45:24 +00:00
- Fix file logging to be asynchronous and more robust
- Convert to unicode svn path=/trunk/; revision=35854
This commit is contained in:
parent
e504422cb3
commit
5a12bfa450
|
@ -32,16 +32,16 @@ SendLine(SOCKET sock, LPSTR lpLine)
|
|||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("Chargen: Not sent enough bytes"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Chargen: Not sent enough bytes", 0, 0, LOG_FILE);
|
||||
}
|
||||
}
|
||||
else if (retVal == SOCKET_ERROR)
|
||||
{
|
||||
LogEvent(_T("Chargen: Socket error\n"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"Chargen: Socket error\n", WSAGetLastError(), 0, LOG_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("Chargen: unknown error\n"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"Chargen: unknown error\n", WSAGetLastError(), 0, LOG_ERROR);
|
||||
}
|
||||
|
||||
return bRet;;
|
||||
|
@ -100,21 +100,21 @@ ChargenHandler(VOID* sock_)
|
|||
|
||||
if (!GenerateChars(sock))
|
||||
{
|
||||
LogEvent(_T("Chargen: Char generation failed"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Chargen: Char generation failed", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("Chargen: Shutting connection down..."), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Chargen: Shutting connection down...", 0, 0, LOG_FILE);
|
||||
if (ShutdownConnection(sock, FALSE))
|
||||
{
|
||||
LogEvent(_T("Chargen: Connection is down"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Chargen: Connection is down", 0, 0, LOG_FILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("Chargen: Connection shutdown failed"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Chargen: Connection shutdown failed", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("Chargen: Terminating thread"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Chargen: Terminating thread", 0, 0, LOG_FILE);
|
||||
ExitThread(retVal);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ SendTime(SOCKET sock, CHAR *time)
|
|||
DWORD stringSize = strlen(time) + 1;
|
||||
if (send(sock, time, stringSize, 0) == SOCKET_ERROR)
|
||||
{
|
||||
LogEvent(_T("DayTime: Error sending data"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"DayTime: Error sending data", WSAGetLastError(), 0, LOG_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -41,15 +41,15 @@ DaytimeHandler(VOID* Sock_)
|
|||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("DayTime: Shutting connection down"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"DayTime: Shutting connection down", 0, 0, LOG_FILE);
|
||||
if (ShutdownConnection(Sock, FALSE))
|
||||
LogEvent(_T("DayTime: Connection is down"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"DayTime: Connection is down", 0, 0, LOG_FILE);
|
||||
else
|
||||
{
|
||||
LogEvent(_T("DayTime: Connection shutdown failed"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"DayTime: Connection shutdown failed", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("DayTime: Terminating thread"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"DayTime: Terminating thread", 0, 0, LOG_FILE);
|
||||
ExitThread(retVal);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
static BOOL
|
||||
RecieveIncomingPackets(SOCKET sock)
|
||||
{
|
||||
char readBuffer[BUFSIZE];
|
||||
CHAR readBuffer[BUFSIZE];
|
||||
INT readBytes;
|
||||
|
||||
do
|
||||
|
@ -24,18 +24,18 @@ RecieveIncomingPackets(SOCKET sock)
|
|||
{
|
||||
TCHAR logBuf[256];
|
||||
|
||||
_stprintf(logBuf, _T("Discard: Received %d bytes from client"), readBytes);
|
||||
_swprintf(logBuf, L"Discard: Received %d bytes from client", readBytes);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
}
|
||||
else if (readBytes == SOCKET_ERROR)
|
||||
{
|
||||
LogEvent(_T("Discard: Socket Error"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"Discard: Socket Error", WSAGetLastError(), 0, LOG_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
} while ((readBytes > 0) && (!bShutdown));
|
||||
|
||||
if (!bShutdown)
|
||||
LogEvent(_T("Discard: Connection closed by peer"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Discard: Connection closed by peer", 0, 0, LOG_FILE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -48,21 +48,21 @@ DiscardHandler(VOID* sock_)
|
|||
|
||||
if (!RecieveIncomingPackets(sock))
|
||||
{
|
||||
LogEvent(_T("Discard: RecieveIncomingPackets failed"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Discard: RecieveIncomingPackets failed", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("Discard: Shutting connection down"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Discard: Shutting connection down", 0, 0, LOG_FILE);
|
||||
if (ShutdownConnection(sock, TRUE))
|
||||
{
|
||||
LogEvent(_T("Discard: Connection is down."), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Discard: Connection is down.", 0, 0, LOG_FILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("Discard: Connection shutdown failed"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Discard: Connection shutdown failed", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("Discard: Terminating thread"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Discard: Terminating thread", 0, 0, LOG_FILE);
|
||||
ExitThread(retVal);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ static BOOL
|
|||
EchoIncomingPackets(SOCKET sock)
|
||||
{
|
||||
CHAR readBuffer[RECV_BUF];
|
||||
TCHAR logBuf[256];
|
||||
WCHAR logBuf[256];
|
||||
INT totalSentBytes;
|
||||
INT readBytes;
|
||||
INT retVal;
|
||||
|
@ -25,7 +25,7 @@ EchoIncomingPackets(SOCKET sock)
|
|||
readBytes = recv(sock, readBuffer, RECV_BUF, 0);
|
||||
if (readBytes > 0)
|
||||
{
|
||||
_stprintf(logBuf, _T("Received %d bytes from client"), readBytes);
|
||||
_swprintf(logBuf, L"Received %d bytes from client", readBytes);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
|
||||
totalSentBytes = 0;
|
||||
|
@ -34,33 +34,33 @@ EchoIncomingPackets(SOCKET sock)
|
|||
retVal = send(sock, readBuffer + totalSentBytes, readBytes - totalSentBytes, 0);
|
||||
if (retVal > 0)
|
||||
{
|
||||
_stprintf(logBuf, _T("Sent %d bytes back to client"), retVal);
|
||||
_swprintf(logBuf, L"Sent %d bytes back to client", retVal);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
totalSentBytes += retVal;
|
||||
}
|
||||
else if (retVal == SOCKET_ERROR)
|
||||
{
|
||||
LogEvent(_T("Echo: socket error"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"Echo: socket error", WSAGetLastError(), 0, LOG_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Client closed connection before we could reply to
|
||||
all the data it sent, so quit early. */
|
||||
LogEvent(_T("Peer unexpectedly dropped connection!"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Peer unexpectedly dropped connection!", 0, 0, LOG_FILE);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (readBytes == SOCKET_ERROR)
|
||||
{
|
||||
LogEvent(_T("Echo: socket error"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"Echo: socket error", WSAGetLastError(), 0, LOG_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
} while ((readBytes != 0) && (!bShutdown));
|
||||
|
||||
if (!bShutdown)
|
||||
LogEvent(_T("Echo: Connection closed by peer"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Echo: Connection closed by peer", 0, 0, LOG_FILE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -73,22 +73,22 @@ EchoHandler(VOID* sock_)
|
|||
|
||||
if (!EchoIncomingPackets(sock))
|
||||
{
|
||||
LogEvent(_T("Echo: EchoIncomingPackets failed"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Echo: EchoIncomingPackets failed", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("Echo: Shutting connection down"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Echo: Shutting connection down", 0, 0, LOG_FILE);
|
||||
|
||||
if (ShutdownConnection(sock, TRUE))
|
||||
{
|
||||
LogEvent(_T("Echo: Connection is down"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Echo: Connection is down", 0, 0, LOG_FILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("Echo: Connection shutdown failed"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Echo: Connection shutdown failed", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("Echo: Terminating thread"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Echo: Terminating thread", 0, 0, LOG_FILE);
|
||||
ExitThread(retVal);
|
||||
}
|
||||
|
|
|
@ -11,31 +11,35 @@
|
|||
|
||||
#define DEBUG
|
||||
|
||||
static LPTSTR lpEventSource = _T("tcpsvcs");
|
||||
static LPCTSTR lpLogFileName = _T("C:\\tcpsvcs_log.log");
|
||||
static HANDLE hLogFile;
|
||||
static LPWSTR lpEventSource = L"tcpsvcs";
|
||||
static LPCWSTR lpLogFileName = L"C:\\tcpsvcs_log.log";
|
||||
static HANDLE hLogFile = NULL;
|
||||
|
||||
static BOOL bWaitingOnRead = FALSE;
|
||||
static OVERLAPPED olWrite;
|
||||
|
||||
|
||||
// needs work
|
||||
static VOID
|
||||
LogToEventLog(LPCTSTR lpMsg,
|
||||
LogToEventLog(LPCWSTR lpMsg,
|
||||
DWORD errNum,
|
||||
DWORD exitCode,
|
||||
UINT flags)
|
||||
{
|
||||
HANDLE hEventLog;
|
||||
|
||||
hEventLog = RegisterEventSource(NULL, lpEventSource);
|
||||
hEventLog = RegisterEventSourceW(NULL, lpEventSource);
|
||||
if (hEventLog)
|
||||
{
|
||||
ReportEvent(hEventLog,
|
||||
(flags & LOG_ERROR) ? EVENTLOG_ERROR_TYPE : EVENTLOG_SUCCESS,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
&lpMsg,
|
||||
NULL);
|
||||
ReportEventW(hEventLog,
|
||||
(flags & LOG_ERROR) ? EVENTLOG_ERROR_TYPE : EVENTLOG_SUCCESS,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
&lpMsg,
|
||||
NULL);
|
||||
|
||||
CloseEventLog(hEventLog);
|
||||
}
|
||||
|
@ -44,45 +48,45 @@ LogToEventLog(LPCTSTR lpMsg,
|
|||
static BOOL
|
||||
OpenLogFile()
|
||||
{
|
||||
hLogFile = CreateFile(lpLogFileName,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hLogFile == INVALID_HANDLE_VALUE)
|
||||
hLogFile = CreateFileW(lpLogFileName,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if (hLogFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hLogFile = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID
|
||||
LogToFile(LPCTSTR lpMsg,
|
||||
LogToFile(LPCWSTR lpMsg,
|
||||
DWORD errNum,
|
||||
DWORD exitCode,
|
||||
UINT flags)
|
||||
{
|
||||
LPTSTR lpFullMsg = NULL;
|
||||
LPWSTR lpFullMsg = NULL;
|
||||
DWORD msgLen;
|
||||
|
||||
if (!OpenLogFile())
|
||||
return;
|
||||
|
||||
msgLen = _tcslen(lpMsg) + 1;
|
||||
msgLen = wcslen(lpMsg) + 1;
|
||||
|
||||
if (flags & LOG_ERROR)
|
||||
{
|
||||
LPVOID lpSysMsg;
|
||||
DWORD eMsgLen;
|
||||
|
||||
eMsgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
errNum,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpSysMsg,
|
||||
0,
|
||||
NULL);
|
||||
eMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
errNum,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpSysMsg,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
msgLen = msgLen + eMsgLen + 40;
|
||||
|
||||
|
@ -91,9 +95,9 @@ LogToFile(LPCTSTR lpMsg,
|
|||
msgLen * sizeof(TCHAR));
|
||||
if (lpFullMsg)
|
||||
{
|
||||
_sntprintf(lpFullMsg,
|
||||
_snwprintf(lpFullMsg,
|
||||
msgLen,
|
||||
_T("%s : %s\tErrNum = %lu ExitCode = %lu\r\n"),
|
||||
L"%s : %s\tErrNum = %lu ExitCode = %lu\r\n",
|
||||
lpMsg,
|
||||
lpSysMsg,
|
||||
errNum,
|
||||
|
@ -112,9 +116,9 @@ LogToFile(LPCTSTR lpMsg,
|
|||
msgLen * sizeof(TCHAR));
|
||||
if (lpFullMsg)
|
||||
{
|
||||
_sntprintf(lpFullMsg,
|
||||
_snwprintf(lpFullMsg,
|
||||
msgLen,
|
||||
_T("%s\r\n"),
|
||||
L"%s\r\n",
|
||||
lpMsg);
|
||||
}
|
||||
}
|
||||
|
@ -122,17 +126,50 @@ LogToFile(LPCTSTR lpMsg,
|
|||
if (lpFullMsg)
|
||||
{
|
||||
DWORD bytesWritten;
|
||||
DWORD dwRet;
|
||||
BOOL bRet;
|
||||
|
||||
SetFilePointer(hLogFile, 0, NULL, FILE_END);
|
||||
|
||||
WriteFile(hLogFile,
|
||||
lpFullMsg,
|
||||
_tcslen(lpFullMsg) * sizeof(TCHAR),
|
||||
&bytesWritten,
|
||||
NULL);
|
||||
if (bytesWritten == 0)
|
||||
bRet = WriteFile(hLogFile,
|
||||
lpFullMsg,
|
||||
wcslen(lpFullMsg) * sizeof(WCHAR),
|
||||
&bytesWritten,
|
||||
&olWrite);
|
||||
if (!bRet)
|
||||
{
|
||||
LogToEventLog(_T("Failed to write to log file"),
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
{
|
||||
bRet = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write is pending
|
||||
dwRet = WaitForSingleObject(olWrite.hEvent, INFINITE);
|
||||
|
||||
switch (dwRet)
|
||||
{
|
||||
// event has been signaled
|
||||
case WAIT_OBJECT_0:
|
||||
{
|
||||
bRet = GetOverlappedResult(hLogFile,
|
||||
&olWrite,
|
||||
&bytesWritten,
|
||||
FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// An error has occurred in WaitForSingleObject.
|
||||
// This usually indicates a problem with the
|
||||
// OVERLAPPED structure's event handle.
|
||||
bRet = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bRet || bytesWritten == 0)
|
||||
{
|
||||
LogToEventLog(L"Failed to write to log file",
|
||||
GetLastError(),
|
||||
0,
|
||||
LOG_EVENTLOG | LOG_ERROR);
|
||||
|
@ -143,8 +180,6 @@ LogToFile(LPCTSTR lpMsg,
|
|||
lpFullMsg);
|
||||
}
|
||||
|
||||
CloseHandle(hLogFile);
|
||||
|
||||
if (exitCode > 0)
|
||||
ExitProcess(exitCode);
|
||||
}
|
||||
|
@ -152,7 +187,7 @@ LogToFile(LPCTSTR lpMsg,
|
|||
|
||||
|
||||
VOID
|
||||
LogEvent(LPCTSTR lpMsg,
|
||||
LogEvent(LPCWSTR lpMsg,
|
||||
DWORD errNum,
|
||||
DWORD exitCode,
|
||||
UINT flags)
|
||||
|
@ -165,39 +200,64 @@ LogEvent(LPCTSTR lpMsg,
|
|||
LogToEventLog(lpMsg, errNum, exitCode, flags);
|
||||
}
|
||||
|
||||
VOID
|
||||
BOOL
|
||||
InitLogging()
|
||||
{
|
||||
WCHAR wcBom = 0xFEFF;
|
||||
#ifdef DEBUG
|
||||
BOOL bRet = FALSE;
|
||||
|
||||
DeleteFile(lpLogFileName);
|
||||
|
||||
#ifdef _UNICODE
|
||||
if (OpenLogFile())
|
||||
ZeroMemory(&olWrite, sizeof(OVERLAPPED));
|
||||
olWrite.Offset = 0xFFFFFFFF;
|
||||
olWrite.OffsetHigh = 0xFFFFFFFF;
|
||||
olWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (olWrite.hEvent)
|
||||
{
|
||||
DWORD bytesWritten;
|
||||
DeleteFileW(lpLogFileName);
|
||||
|
||||
WriteFile(hLogFile,
|
||||
&wcBom,
|
||||
sizeof(WCHAR),
|
||||
&bytesWritten,
|
||||
NULL);
|
||||
if (bytesWritten == 0)
|
||||
if (OpenLogFile())
|
||||
{
|
||||
LogToEventLog(_T("Failed to write to log file"),
|
||||
GetLastError(),
|
||||
0,
|
||||
LOG_EVENTLOG | LOG_ERROR);
|
||||
}
|
||||
WCHAR wcBom = 0xFEFF;
|
||||
DWORD bytesWritten;
|
||||
|
||||
CloseHandle(hLogFile);
|
||||
bRet = WriteFile(hLogFile,
|
||||
&wcBom,
|
||||
sizeof(WCHAR),
|
||||
&bytesWritten,
|
||||
&olWrite);
|
||||
if (!bRet)
|
||||
{
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
{
|
||||
LogToEventLog(L"Failed to write to log file",
|
||||
GetLastError(),
|
||||
0,
|
||||
LOG_EVENTLOG | LOG_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
bRet = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bRet;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID
|
||||
UninitLogging()
|
||||
{
|
||||
FlushFileBuffers(hLogFile);
|
||||
CloseHandle(hLogFile);
|
||||
if (hLogFile)
|
||||
{
|
||||
FlushFileBuffers(hLogFile);
|
||||
CloseHandle(hLogFile);
|
||||
}
|
||||
|
||||
if (olWrite.hEvent)
|
||||
{
|
||||
CloseHandle(olWrite.hEvent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include "tcpsvcs.h"
|
||||
|
||||
static LPCTSTR lpFilePath = _T("\\drivers\\etc\\quotes");
|
||||
static WCHAR szFilePath[] = L"\\drivers\\etc\\quotes";
|
||||
|
||||
static BOOL
|
||||
SendQuote(SOCKET sock, char* Quote)
|
||||
|
@ -25,33 +25,33 @@ static BOOL
|
|||
RetrieveQuote(SOCKET sock)
|
||||
{
|
||||
HANDLE hFile;
|
||||
TCHAR lpFullPath[MAX_PATH + 20];
|
||||
WCHAR szFullPath[MAX_PATH + 20];
|
||||
DWORD dwBytesRead;
|
||||
LPSTR lpQuotes;
|
||||
LPSTR lpStr;
|
||||
DWORD quoteNum;
|
||||
DWORD NumQuotes = 0;
|
||||
INT quoteNum;
|
||||
INT NumQuotes = 0;
|
||||
INT i;
|
||||
|
||||
if(!GetSystemDirectory(lpFullPath, MAX_PATH))
|
||||
if(!GetSystemDirectoryW(szFullPath, MAX_PATH))
|
||||
{
|
||||
LogEvent(_T("QOTD: Getting system path failed"), GetLastError(), 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Getting system path failed", GetLastError(), 0, LOG_FILE);
|
||||
return FALSE;
|
||||
}
|
||||
_tcscat(lpFullPath, lpFilePath);
|
||||
wcscat(szFullPath, szFilePath);
|
||||
|
||||
|
||||
LogEvent(_T("QOTD: Opening quotes file"), 0, 0, LOG_FILE);
|
||||
hFile = CreateFile(lpFullPath,
|
||||
GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
LogEvent(L"QOTD: Opening quotes file", 0, 0, LOG_FILE);
|
||||
hFile = CreateFileW(szFullPath,
|
||||
GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LogEvent(_T("QOTD: Error opening quotes file"), GetLastError(), 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Error opening quotes file", GetLastError(), 0, LOG_FILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -105,7 +105,7 @@ RetrieveQuote(SOCKET sock)
|
|||
|
||||
/* send the quote */
|
||||
if (!SendQuote(sock, lpStart))
|
||||
LogEvent(_T("QOTD: Error sending data"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Error sending data", 0, 0, LOG_FILE);
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -133,22 +133,22 @@ QotdHandler(VOID* sock_)
|
|||
|
||||
if (!RetrieveQuote(sock))
|
||||
{
|
||||
LogEvent(_T("QOTD: Error retrieving quote"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Error retrieving quote", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("QOTD: Shutting connection down"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Shutting connection down", 0, 0, LOG_FILE);
|
||||
if (ShutdownConnection(sock, FALSE))
|
||||
{
|
||||
LogEvent(_T("QOTD: Connection is down"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Connection is down", 0, 0, LOG_FILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("QOTD: Connection shutdown failed"), 0, 0, LOG_FILE);
|
||||
LogEvent(_T("QOTD: Terminating thread"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Connection shutdown failed", 0, 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Terminating thread", 0, 0, LOG_FILE);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
LogEvent(_T("QOTD: Terminating thread"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"QOTD: Terminating thread", 0, 0, LOG_FILE);
|
||||
ExitThread(retVal);
|
||||
}
|
||||
|
|
|
@ -33,17 +33,17 @@ SetUpListener(USHORT Port)
|
|||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("listen() failed"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"listen() failed", WSAGetLastError(), 0, LOG_ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("bind() failed"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"bind() failed", WSAGetLastError(), 0, LOG_ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("socket() failed"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"socket() failed", WSAGetLastError(), 0, LOG_ERROR);
|
||||
}
|
||||
|
||||
return bSetup ? sock : INVALID_SOCKET;
|
||||
|
@ -53,14 +53,14 @@ SetUpListener(USHORT Port)
|
|||
static VOID
|
||||
AcceptConnections(SOCKET listeningSocket,
|
||||
LPTHREAD_START_ROUTINE lpService,
|
||||
LPTSTR lpName)
|
||||
LPWSTR lpName)
|
||||
{
|
||||
SOCKADDR_IN client;
|
||||
SOCKET sock;
|
||||
HANDLE hThread;
|
||||
TIMEVAL timeVal;
|
||||
FD_SET readFD;
|
||||
TCHAR logBuf[256];
|
||||
WCHAR logBuf[256];
|
||||
INT timeOut = 2000;
|
||||
|
||||
timeVal.tv_sec = timeOut / 1000;
|
||||
|
@ -83,14 +83,14 @@ AcceptConnections(SOCKET listeningSocket,
|
|||
sock = accept(listeningSocket, (SOCKADDR*)&client, &addrSize);
|
||||
if (sock != INVALID_SOCKET)
|
||||
{
|
||||
_stprintf(logBuf,
|
||||
_T("Accepted connection to %s server from %s:%d"),
|
||||
_swprintf(logBuf,
|
||||
L"Accepted connection to %s server from %S:%d",
|
||||
lpName,
|
||||
inet_ntoa(client.sin_addr),
|
||||
ntohs(client.sin_port));
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
|
||||
_stprintf(logBuf, _T("Creating worker thread for %s"), lpName);
|
||||
_swprintf(logBuf, L"Creating worker thread for %s", lpName);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
|
||||
if (!bShutdown)
|
||||
|
@ -102,7 +102,7 @@ AcceptConnections(SOCKET listeningSocket,
|
|||
}
|
||||
else
|
||||
{
|
||||
_stprintf(logBuf, _T("Failed to start worker thread for the %s server"),
|
||||
_swprintf(logBuf, L"Failed to start worker thread for the %s server",
|
||||
lpName);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
}
|
||||
|
@ -110,13 +110,13 @@ AcceptConnections(SOCKET listeningSocket,
|
|||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("accept failed"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"accept failed", WSAGetLastError(), 0, LOG_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (selRet == SOCKET_ERROR)
|
||||
{
|
||||
LogEvent(_T("select failed"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"select failed", WSAGetLastError(), 0, LOG_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,14 +125,14 @@ BOOL
|
|||
ShutdownConnection(SOCKET sock,
|
||||
BOOL bRec)
|
||||
{
|
||||
TCHAR logBuf[256];
|
||||
WCHAR logBuf[256];
|
||||
|
||||
/* Disallow any further data sends. This will tell the other side
|
||||
that we want to go away now. If we skip this step, we don't
|
||||
shut the connection down nicely. */
|
||||
if (shutdown(sock, SD_SEND) == SOCKET_ERROR)
|
||||
{
|
||||
LogEvent(_T("Error in shutdown()"), WSAGetLastError(), 0, LOG_ERROR);
|
||||
LogEvent(L"Error in shutdown()", WSAGetLastError(), 0, LOG_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ ShutdownConnection(SOCKET sock,
|
|||
ret = recv(sock, readBuffer, BUF, 0);
|
||||
if (ret >= 0)
|
||||
{
|
||||
_stprintf(logBuf, _T("FYI, received %d unexpected bytes during shutdown"), ret);
|
||||
_swprintf(logBuf, L"FYI, received %d unexpected bytes during shutdown", ret);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
}
|
||||
} while (ret > 0);
|
||||
|
@ -169,7 +169,7 @@ StartServer(LPVOID lpParam)
|
|||
|
||||
pServices = (PSERVICES)lpParam;
|
||||
|
||||
_stprintf(logBuf, _T("Starting %s server"), pServices->Name);
|
||||
_swprintf(logBuf, L"Starting %s server", pServices->lpName);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
|
||||
if (!bShutdown)
|
||||
|
@ -177,23 +177,23 @@ StartServer(LPVOID lpParam)
|
|||
listeningSocket = SetUpListener(htons(pServices->Port));
|
||||
if (!bShutdown && listeningSocket != INVALID_SOCKET)
|
||||
{
|
||||
_stprintf(logBuf,
|
||||
_T("%s is waiting for connections on port %d"),
|
||||
pServices->Name,
|
||||
_swprintf(logBuf,
|
||||
L"%s is waiting for connections on port %d",
|
||||
pServices->lpName,
|
||||
pServices->Port);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
|
||||
AcceptConnections(listeningSocket, pServices->Service, pServices->Name);
|
||||
AcceptConnections(listeningSocket, pServices->lpService, pServices->lpName);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent(_T("Socket error when setting up listener"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Socket error when setting up listener", 0, 0, LOG_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
_stprintf(logBuf,
|
||||
_T("Exiting %s thread"),
|
||||
pServices->Name);
|
||||
_swprintf(logBuf,
|
||||
L"Exiting %s thread",
|
||||
pServices->lpName);
|
||||
LogEvent(logBuf, 0, 0, LOG_FILE);
|
||||
ExitThread(0);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include "tcpsvcs.h"
|
||||
|
||||
static LPTSTR ServiceName = _T("tcpsvcs");
|
||||
static WCHAR ServiceName[] = L"tcpsvcs";
|
||||
|
||||
volatile BOOL bShutdown = FALSE;
|
||||
volatile BOOL bPause = FALSE;
|
||||
|
@ -23,11 +23,11 @@ typedef struct _ServiceInfo
|
|||
static SERVICES
|
||||
Services[NUM_SERVICES] =
|
||||
{
|
||||
{ECHO_PORT, _T("Echo"), EchoHandler},
|
||||
{DISCARD_PORT, _T("Discard"), DiscardHandler},
|
||||
{DAYTIME_PORT, _T("Daytime"), DaytimeHandler},
|
||||
{QOTD_PORT, _T("QOTD"), QotdHandler},
|
||||
{CHARGEN_PORT, _T("Chargen"), ChargenHandler}
|
||||
{ECHO_PORT, L"Echo", EchoHandler},
|
||||
{DISCARD_PORT, L"Discard", DiscardHandler},
|
||||
{DAYTIME_PORT, L"Daytime", DaytimeHandler},
|
||||
{QOTD_PORT, L"QOTD", QotdHandler},
|
||||
{CHARGEN_PORT, L"Chargen", ChargenHandler}
|
||||
};
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ UpdateStatus(PSERVICEINFO pServInfo,
|
|||
DWORD NewStatus,
|
||||
DWORD Check)
|
||||
{
|
||||
TCHAR szSet[50];
|
||||
WCHAR szSet[50];
|
||||
|
||||
if (Check > 0)
|
||||
pServInfo->servStatus.dwCheckPoint += Check;
|
||||
|
@ -46,15 +46,15 @@ UpdateStatus(PSERVICEINFO pServInfo,
|
|||
if (NewStatus > 0)
|
||||
pServInfo->servStatus.dwCurrentState = NewStatus;
|
||||
|
||||
_sntprintf(szSet,
|
||||
_snwprintf(szSet,
|
||||
49,
|
||||
_T("Service state 0x%lu, CheckPoint %lu"),
|
||||
L"Service state 0x%lu, CheckPoint %lu",
|
||||
pServInfo->servStatus.dwCurrentState,
|
||||
pServInfo->servStatus.dwCheckPoint);
|
||||
LogEvent(szSet, 0, 0, LOG_FILE);
|
||||
|
||||
if (!SetServiceStatus(pServInfo->hStatus, &pServInfo->servStatus))
|
||||
LogEvent(_T("Cannot set service status"), GetLastError(), 0, LOG_ALL);
|
||||
LogEvent(L"Cannot set service status", GetLastError(), 0, LOG_ALL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,25 +64,25 @@ CreateServers(PSERVICEINFO pServInfo)
|
|||
DWORD dwThreadId[NUM_SERVICES];
|
||||
HANDLE hThread[NUM_SERVICES];
|
||||
WSADATA wsaData;
|
||||
TCHAR buf[256];
|
||||
WCHAR buf[256];
|
||||
INT i;
|
||||
DWORD RetVal;
|
||||
|
||||
if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
|
||||
{
|
||||
_stprintf(buf, _T("WSAStartup() failed : %lu\n"), RetVal);
|
||||
_swprintf(buf, L"WSAStartup() failed : %lu\n", RetVal);
|
||||
LogEvent(buf, 0, 100, LOG_ALL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UpdateStatus(pServInfo, 0, 1);
|
||||
|
||||
LogEvent(_T("\nCreating server Threads"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"\nCreating server Threads", 0, 0, LOG_FILE);
|
||||
|
||||
/* Create worker threads. */
|
||||
for(i = 0; i < NUM_SERVICES; i++)
|
||||
for (i = 0; i < NUM_SERVICES; i++)
|
||||
{
|
||||
_stprintf(buf, _T("Creating thread for %s server"), Services[i].Name);
|
||||
_swprintf(buf, L"Creating thread for %s server", Services[i].lpName);
|
||||
LogEvent(buf, 0, 0, LOG_FILE);
|
||||
|
||||
hThread[i] = CreateThread(NULL,
|
||||
|
@ -94,26 +94,26 @@ CreateServers(PSERVICEINFO pServInfo)
|
|||
|
||||
if (hThread[i] == NULL)
|
||||
{
|
||||
_stprintf(buf, _T("\nFailed to start %s server\n"), Services[i].Name);
|
||||
_swprintf(buf, L"\nFailed to start %s server\n", Services[i].lpName);
|
||||
LogEvent(buf, GetLastError(), 0, LOG_ALL);
|
||||
}
|
||||
|
||||
UpdateStatus(pServInfo, 0, 1);
|
||||
}
|
||||
|
||||
LogEvent(_T("Setting service status to running"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Setting service status to running", 0, 0, LOG_FILE);
|
||||
UpdateStatus(pServInfo, SERVICE_RUNNING, 0);
|
||||
|
||||
/* Wait until all threads have terminated. */
|
||||
WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
|
||||
|
||||
for(i = 0; i < NUM_SERVICES; i++)
|
||||
for (i = 0; i < NUM_SERVICES; i++)
|
||||
{
|
||||
if (hThread[i] != NULL)
|
||||
CloseHandle(hThread[i]);
|
||||
}
|
||||
|
||||
LogEvent(_T("Detaching Winsock2"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Detaching Winsock2", 0, 0, LOG_FILE);
|
||||
WSACleanup();
|
||||
|
||||
return 0;
|
||||
|
@ -131,7 +131,7 @@ ServerCtrlHandler(DWORD dwControl,
|
|||
{
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
case SERVICE_CONTROL_STOP:
|
||||
LogEvent(_T("\nSetting the service to SERVICE_STOP_PENDING"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"\nSetting the service to SERVICE_STOP_PENDING", 0, 0, LOG_FILE);
|
||||
InterlockedExchange((LONG *)&bShutdown, TRUE);
|
||||
pServInfo->servStatus.dwWin32ExitCode = 0;
|
||||
pServInfo->servStatus.dwWaitHint = 0;
|
||||
|
@ -139,13 +139,13 @@ ServerCtrlHandler(DWORD dwControl,
|
|||
break;
|
||||
|
||||
case SERVICE_CONTROL_PAUSE: /* not yet implemented */
|
||||
LogEvent(_T("Setting the service to SERVICE_PAUSED"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Setting the service to SERVICE_PAUSED", 0, 0, LOG_FILE);
|
||||
InterlockedExchange((LONG *)&bPause, TRUE);
|
||||
UpdateStatus(pServInfo, SERVICE_PAUSED, 0);
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_CONTINUE:
|
||||
LogEvent(_T("Setting the service to SERVICE_RUNNING"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Setting the service to SERVICE_RUNNING", 0, 0, LOG_FILE);
|
||||
InterlockedExchange((LONG *)&bPause, FALSE);
|
||||
UpdateStatus(pServInfo, SERVICE_RUNNING, 0);
|
||||
break;
|
||||
|
@ -155,19 +155,19 @@ ServerCtrlHandler(DWORD dwControl,
|
|||
|
||||
default:
|
||||
if (dwControl > 127 && dwControl < 256) /* user defined */
|
||||
LogEvent(_T("User defined control code"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"User defined control code", 0, 0, LOG_FILE);
|
||||
else
|
||||
LogEvent(_T("ERROR: Bad control code"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"ERROR: Bad control code", 0, 0, LOG_FILE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ServiceMain(DWORD argc, LPTSTR argv[])
|
||||
ServiceMain(DWORD argc, LPWSTR argv[])
|
||||
{
|
||||
SERVICEINFO servInfo;
|
||||
|
||||
LogEvent (_T("Entering ServiceMain."), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Entering ServiceMain.", 0, 0, LOG_FILE);
|
||||
|
||||
servInfo.servStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
servInfo.servStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
|
@ -177,12 +177,12 @@ ServiceMain(DWORD argc, LPTSTR argv[])
|
|||
servInfo.servStatus.dwCheckPoint = 0;
|
||||
servInfo.servStatus.dwWaitHint = 2 * CS_TIMEOUT;
|
||||
|
||||
LogEvent(_T("Registering service control handler"), 0, 0, LOG_FILE);
|
||||
servInfo.hStatus = RegisterServiceCtrlHandlerEx(ServiceName,
|
||||
(LPHANDLER_FUNCTION_EX)ServerCtrlHandler,
|
||||
&servInfo);
|
||||
LogEvent(L"Registering service control handler", 0, 0, LOG_FILE);
|
||||
servInfo.hStatus = RegisterServiceCtrlHandlerExW(ServiceName,
|
||||
(LPHANDLER_FUNCTION_EX)ServerCtrlHandler,
|
||||
&servInfo);
|
||||
if (!servInfo.hStatus)
|
||||
LogEvent(_T("Failed to register service\n"), GetLastError(), 100, LOG_ALL);
|
||||
LogEvent(L"Failed to register service", GetLastError(), 100, LOG_ALL);
|
||||
|
||||
UpdateStatus(&servInfo, SERVICE_START_PENDING, 1);
|
||||
|
||||
|
@ -193,27 +193,28 @@ ServiceMain(DWORD argc, LPTSTR argv[])
|
|||
return;
|
||||
}
|
||||
|
||||
LogEvent(_T("Service threads shut down. Set SERVICE_STOPPED status"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Service threads shut down. Set SERVICE_STOPPED status", 0, 0, LOG_FILE);
|
||||
UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
|
||||
|
||||
LogEvent(_T("Leaving ServiceMain\n"), 0, 0, LOG_FILE);
|
||||
LogEvent(L"Leaving ServiceMain\n", 0, 0, LOG_FILE);
|
||||
}
|
||||
|
||||
|
||||
int _tmain (int argc, LPTSTR argv [])
|
||||
{
|
||||
SERVICE_TABLE_ENTRY ServiceTable[] =
|
||||
SERVICE_TABLE_ENTRYW ServiceTable[] =
|
||||
{
|
||||
{ServiceName, ServiceMain},
|
||||
{NULL, NULL }
|
||||
};
|
||||
|
||||
InitLogging();
|
||||
if (InitLogging())
|
||||
{
|
||||
if (!StartServiceCtrlDispatcherW(ServiceTable))
|
||||
LogEvent(L"failed to start the service control dispatcher", GetLastError(), 101, LOG_ALL);
|
||||
|
||||
if (!StartServiceCtrlDispatcher(ServiceTable))
|
||||
LogEvent(_T("failed to start the service control dispatcher"), GetLastError(), 101, LOG_ALL);
|
||||
|
||||
UninitLogging();
|
||||
UninitLogging();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
#include <tchar.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define _swprintf swprintf
|
||||
#endif
|
||||
|
||||
#define LOG_FILE 1
|
||||
#define LOG_EVENTLOG 2
|
||||
#define LOG_ERROR 4
|
||||
|
@ -20,19 +24,20 @@
|
|||
|
||||
|
||||
/* data structure to pass to threads */
|
||||
typedef struct _Services {
|
||||
typedef struct _Services
|
||||
{
|
||||
USHORT Port;
|
||||
TCHAR *Name;
|
||||
LPTHREAD_START_ROUTINE Service;
|
||||
LPWSTR lpName;
|
||||
LPTHREAD_START_ROUTINE lpService;
|
||||
} SERVICES, *PSERVICES;
|
||||
|
||||
extern volatile BOOL bShutdown;
|
||||
extern volatile BOOL bPause;
|
||||
|
||||
/* logging functions */
|
||||
VOID InitLogging();
|
||||
BOOL InitLogging();
|
||||
VOID UninitLogging();
|
||||
VOID LogEvent(LPCTSTR lpMsg, DWORD errNum, DWORD exitCode, UINT flags);
|
||||
VOID LogEvent(LPCWSTR lpMsg, DWORD errNum, DWORD exitCode, UINT flags);
|
||||
|
||||
/* skelserver functions */
|
||||
DWORD WINAPI StartServer(LPVOID lpParam);
|
||||
|
|
Loading…
Reference in a new issue