// ref.h : the base utility for life-cycle control by reference // // Author: Gongbing // // Create: 2017-05-20 #pragma once #ifdef _AS_DLL_ #ifdef _NET_EXPORTS_ #define PORT_API(ret) __declspec(dllexport) ret __stdcall #define PORT_API_CALL(ret, call_) __declspec(dllexport) ret call_ #else #define PORT_API(ret) __declspec(dllimport) ret __stdcall #define PORT_API_CALL(ret, call_) __declspec(dllimport) ret call_ #ifdef _DEBUG #pragma comment(lib, "./Debug/base_util.lib") #else #pragma comment(lib, "./Release/base_util.lib") #endif #endif #else #define PORT_API(ret) ret __stdcall #define PORT_API_CALL(ret, call_) ret call_ #ifndef _BASE_EXPORTS_ #ifdef _DEBUG #pragma comment(lib, "base_util.lib") #else #pragma comment(lib, "base_util.lib") #endif #endif #endif //#define STRUCT_ALIGN(bytes) \ // #pragma pack(push) \ // #pragma pack(bytes) //#define STRUCT_ALIGN_END \ // #pragma pack(pop) #define COM_API_DECLARE(ret, decl) virtual ret __stdcall decl = 0 #define COM_API_DECLARE_NON_PURE(ret, decl) virtual ret __stdcall decl #define COM_API_OVERRIDE(ret, decl) virtual ret __stdcall decl override #define COM_API_IMPLEMENT(cls, ret, decl) ret __stdcall cls##::decl #define ALIGN_MEMORY(n, align) ((n + align - 1) / (align) * (align)) #define _TO_UNICODE_(str) L##str #define UNICODE_STR(str) _TO_UNICODE_(str) // refferer simulating-COM namespace ref_util { // // rule: // // if a member of container owns the container pointer, the member should release the container pointer // in an explicit function like 'stop'; the container could release the member pointer in destructor!!! // __declspec(novtable) struct IRef { COM_API_DECLARE(long, add_ref(void)); COM_API_DECLARE(long, release(void)); }; class refer : public IRef { volatile long m_ref; public: refer() : m_ref(1) {} protected: virtual ~refer() {} public: COM_API_OVERRIDE(long, add_ref(void)) { return InterlockedIncrement(&m_ref); } COM_API_OVERRIDE(long, release(void)) { long ref = InterlockedDecrement(&m_ref); if (ref <= 0) delete this; return ref; } }; template class auto_pointer { T* m_ptr; public: auto_pointer() : m_ptr(NULL) {} auto_pointer(T* ptr) : m_ptr(ptr) {} auto_pointer(const auto_pointer& r) { m_ptr = r.m_ptr; if (m_ptr) m_ptr->add_ref(); } ~auto_pointer() { if (m_ptr) m_ptr->release(); } public: auto_pointer& operator=(T* ptr) { if (m_ptr) m_ptr->release(); m_ptr = ptr; return *this; } auto_pointer& operator=(const auto_pointer& r) { if (m_ptr) m_ptr->release(); m_ptr = r.m_ptr; if (m_ptr) m_ptr->add_ref(); return *this; } T* ptr(void) { return m_ptr; } T* operator->(void) { return m_ptr; } bool is_empty(void) { return m_ptr == NULL; } }; } #define IMPL_REF_BY_REFER() \ COM_API_OVERRIDE(long, add_ref(void)) \ { \ return ref_util::refer::add_ref(); \ } \ COM_API_OVERRIDE(long, release(void)) \ { \ return ref_util::refer::release(); \ } // inter-module data namespace inter_module_data { enum data_flag { // commonly DATA_FLAG_UNKNOWN = 0, DATA_FLAG_ERROR, // the parameter 'len' is contains the error code, total is extension info for 'len' DATA_FLAG_FINAL, // data is final result for the api which you called DATA_FLAG_INSTAR, // data is instar for your api, and finally will notified with flag DATA_TYPE_FINAL DATA_FLAG_OVER, // all data has been transfered, parameter data, len and total are all invalid DATA_FLAG_GET_VAL, // (const wchar_t*)data, 'len' is bytes of data, 'total' is set_data // call (set_data)total(const wchar_t* data, bytes of 'data', 0, DATA_FLAG_FINAL, param) DATA_FLAG_DEBUG_INFO, // for http data DATA_FLAG_HTTP_HEAD = 100, // http(s) response head DATA_FLAG_302, // 301 or 302 to new url, the data contains the url. in this case, return SET_RESULT_CONTINUE to jump, SET_RESULT_DISCARD to stop jumping // for remote thread DATA_FLAG_REMOTE_THREAD_INSTRUCT = 200, // to fill the remote thread code in given address DATA_FLAG_REMOTE_THREAD_PARAMETER, // to fill the remote thread parameter in given address // the parameter data, len and total will be all set to ZERO if unused DATA_FALG_SVC_ENTER = 300, // service callback, called when initailizing, parameter 'data' is pointing to proc_util::ICmd* DATA_FALG_SVC_TIMER, // service callback, called when timer is set, parameter 'len' is the count base from ZERO DATA_FALG_SVC_CONTROL, // service callback, called when service control is invoked, parameter 'len' is the control code DATA_FALG_SVC_EXIT, // service callback, called when service exiting // for un-assembly DATA_FLAG_UNASM_SET_LABEL = 1000, // set the label address, data is label, len is address, other has no mean DATA_FLAG_UNASM_GET_LABEL, // query the label address. data is label, param is a pointer points to the UINT64 variable to receive the address }; // return true to continue, false to stop enum set_result { SET_RESULT_CONTINUE = ERROR_SUCCESS, // continue doing the task of the calling api SET_RESULT_UNKNOWN = -100, // omit this value SET_RESULT_DISCARD, // discard this data handling. i.e. it will stop jump to new url if flag is DATA_FLAG_302 SET_RESULT_STOP, // this will stop all operations of the api you calling }; // real usage of these parameters, see the API which use this callback ... typedef set_result(__stdcall* set_data)(const char* data // data buffer , UINT64 len // bytes of data in data-buffer or error code if flag was DATA_FLAG_ERROR , UINT64 total // total bytes of the data for the api which you called , data_flag flag // data flag , void* param); // user defined data, and passing it when call the callback } #define INTER_MODULE_CALLBACK(name) \ inter_module_data::set_result __stdcall name(const char* data, UINT64 len, UINT64 total, inter_module_data::data_flag flag, void* param) #define INTER_MODULE_CALLBACK_VAR(name) \ inter_module_data::set_result (__stdcall *name)(const char* data, UINT64 len, UINT64 total, inter_module_data::data_flag flag, void* param)