|
The Builder pattern always hides the method of creation from the client code and it resided at the object itself that u wanted to create. if u would like to compose different object that has same kind of template, u always can use Template pattern for abstract together with Composite pattern for the tree type linking. To create this composite pattern you always has Factory method pattern to assist you to reach to the Builder pattern for creation during run time.
The whole thing u assemble it together should be called Compound Patterns.
Remember to use back all standard terms unless you really has created a new way of approach to the design pattern. My intention is not to mislead developers...
the pattern "language" that i mention above(title) is not programming language, but the way we communicate to each other in developers community. Anyone could discuss the finding or works but one should use back the standard term instead of creating new terms to explain.
from,
-= aLbert =-
|
|
|
|
|
** Mediator.h **
class MediatorClient;
class AbstractMediator
{
public:
virtual void Register(MediatorClient *client)
{ ASSERT(!"PURE VIRTUAL!"); }
public:
virtual void Send(std::string from, std::string to, std::string message)
{ ASSERT(!"PURE VIRTUAL!"); }
};
class Hub : public AbstractMediator
{
private:
std::map<std::string,MediatorClient*> clients;
public:
void Register(MediatorClient *client);
void Send(std::string from, std::string to, std::string message);
void Connect(MediatorClient *client);
void Send(std::string from, std::string to, LPCTSTR message, int length);
};
class MediatorClient
{
private:
Hub *hub;
private:
std::string name;
public:
MediatorClient(std::string name)
{
this->name = name;
}
public:
std::string GetName()
{
return this->name;
}
public:
void SetHub(Hub *hub)
{
this->hub = hub;
}
Hub* GetHub()
{
return this->hub;
}
public:
void SendToHub(std::string to, std::string message)
{
hub->Send(name, to, message);
}
void SendToHub(std::string to, LPCTSTR message, int length)
{
hub->Send(name, to, message, length);
}
public:
virtual void Receive(std::string from, std::string message)
{
ASSERT(!"Target Client Receive NOT OVERRIDED!!!");
}
virtual void Receive(std::string from, LPCTSTR message, int length)
{
ASSERT(!"Target Client Receive NOT OVERRIDED!!!");
}
};
** Mediator.cpp **
void Hub::Register(MediatorClient *client)
{
MediatorClient* pExistingClient = clients[client->GetName()];
if(pExistingClient == 0)
{
clients[client->GetName()] = client;
}
client->SetHub(this);
}
void Hub::Send(std::string from, std::string to, std::string message)
{
MediatorClient *pTo = (MediatorClient*)clients[to];
if(pTo != 0)
{
pTo->Receive(from, message);
}
else
{
ASSERT(!"Target Client NOT REGISTERED!!!");
}
}
void Hub::Connect(MediatorClient *client)
{
Register(client);
}
void Hub::Send(std::string from, std::string to, LPCTSTR message, int length)
{
MediatorClient *pTo = (MediatorClient*)clients[to];
if(pTo != 0)
{
pTo->Receive(from, message, length);
}
else
{
ASSERT(!"Target Client NOT REGISTERED!!!");
}
}
from,
-= aLbert =-
|
|
|
|
|
** MACROS **
#ifndef __STIBASEBUILDER_H__
#define __STIBASEBUILDER_H__
#define DECLARE_STIBASEBUILDER() \
struct ISTIBase { \
BOOL (*WhatIsThis)(LPSTR lpName); \
BOOL (*Version)(LPSTR lpName); \
BOOL (*Add)(STI::Module::STIModule **pModule); \
BOOL (*Release)(STI::Module::STIModule **pModule); \
}; \
struct ISTIBaseBuilder { \
ISTIBase *pISTIBase; \
};
#define IMPLEMENT_STIBASEBUILDER(Name,ClassName) \
char STIName[] = #Name; \
static BOOL staticWhatIsThis(LPSTR lpName) { \
strcpy(lpName, STIName); \
return 0; \
} \
char STIVersion[] = "1.00.00.00"; \
static BOOL staticVersion(LPSTR lpName) { \
strcpy(lpName, STIVersion); \
return 0; \
} \
static BOOL staticAdd(STI::Module::STIModule **pModule) { \
*pModule = new ClassName; \
return 0; \
} \
static BOOL staticRelease(STI::Module::STIModule **pModule) { \
delete *pModule; \
*pModule = NULL; \
return 0; \
} \
static ISTIBaseBuilder I##Name##BuilderObj; \
static ISTIBase I##Name##Obj = { \
staticWhatIsThis, \
staticVersion, \
staticAdd, \
staticRelease \
}; \
extern "C" __declspec(dllexport) \
BOOL STIGetClassObject(LPSTR lpName, ISTIBaseBuilder *builder) { \
strcpy(lpName, STIName); \
*builder = I##Name##BuilderObj; \
return 0; \
} \
extern "C" __declspec(dllexport) \
BOOL STICanUnloadClassObject() { \
return 0; \
}
#define SET_STIVERSION(Version) \
{ \
strcpy(STIVersion, Version); \
}
#define REGISTER_STIBASEBUILDER(Name) \
{ \
I##Name##BuilderObj.pISTIBase = (ISTIBase *)&I##Name##Obj; \
}
#endif // __STIBASEBUILDER_H__
** USING IT **
IMPLEMENT_STIBASEBUILDER(STIModule,STI::Module::STIModule);
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("STIModule.DLL Initializing!\n");
AfxInitExtensionModule(STIModuleDLL, hInstance);
new CDynLinkLibrary(STIModuleDLL);
REGISTER_STIBASEBUILDER(STIModule);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("STIModule.DLL Terminating!\n");
}
return 1;
}
from,
-= aLbert =-
|
|
|
|
|
can template specialisation replace callback?
i wish to replace callback by template specialisation.
is anyone come to this b4 and knowing that is multi-thread safe?
my application goes like this, many instance from our working code
is registering function pointer(for callback) to the library.
so that the library will notify us whenever it completed its job.
the answer to this question was found in the book, Complete Guide to Template Programming.
the specialise template can reside at client code, it actually override the abstract
template in the library. During compilation time, the linker will check is there a specialise
template defined and link accordingly.
from,
-= aLbert =-
|
|
|
|
|
class tagtree
{
...
public:
std::map<CString,tagtree*> mapControllee;
};
** working code **
tagtree *tt;
tagtree *ttController;
tt = AddNode(...);
ttController = tt;
tt = AddNode(...);
ttController->mapControlle[strName] = tt <- crash in compare <xtree> down to _tcmp lpsz 0xcdcdcdcd
;
http://www.dinkumware.com/vc_fixes.html[^]
from,
-= aLbert =-
|
|
|
|
|
<code>void CServer::WriteToMemory()
{
mutex.Lock();
switch memory page
...
...
write something
...
...
mutex.Unlock();
}
void CServer::ReadFromMemory()
{
mutex.Lock();
get last writen memory page
mutex.Unlock();
...
...
read something
...
...
}</code>
from,
-= aLbert =-
|
|
|
|
|
References
1. "Three ways to inject your code into another process" by Robert Kuster.
http://www.codeproject.com/threads/winspy.asp
2. "Remote Library" by António Feijão.
http://www.codeproject.com/win32/remote.asp
3. "PrcHelp" by Radim Picha.
http://www.apihooks.com/OUT/CPRPICHA.ZIP
4. "Windows 95 System Programming Secrets" by Matt Pietrek.
http://www.wheaty.net/
5. "Windows NT/2000 Native API Reference" by Gary Nebbett.
http://www.amazon.com/exec/obidos/ASIN/1578701996/systemsinternals
6. "A Crash Course on the Depths of Win32 Structured Exception Handling" by Matt Pietrek.
http://www.microsoft.com/msj/0197/exception/exception.aspx
7. "Enumerating Windows Processes" by Alex Fedotov.
http://www.alexfedotov.com/articles/enumproc.asp
For Win9x stuff see [4] (99 % of the Win9x code comes from this book).
I don't know any equivalent book for NT, but two usefull books (not directly related to remote code injection) are:
- "Undocumented Windows NT" by P. Dabak, M. Borate, S. Phadke (http://www.windowsitlibrary.com/Documents/Book.cfm?DocumentID=356)
- "Microsoft Windows Internals, 4th ed." by M. Russinovich, D. Solomon
from,
-= aLbert =-
|
|
|
|
|