wenjiang's profilemorning的个人空间PhotosBlogLists Tools Help
June 30

实现了VC6 的 __FUNCTION__,附上一个调试辅助类

利用 dbg api 实现了 vc6 下的 __FUNCTION__ ,意外发现 在使用 /ZI 时 VC7.1 的 __LINE__ 的实现很有意思.
 
源代码:
#ifdef __cplusplus
class clsT1
{
public:
 virtual void Test(int x=0)
 {
  DbgPrint(_T("测试\n"));
 }
};
class clsT2:public clsT1
{
public:
 void Test(int x=0)
 {
  DbgPrint(_T("测试\n"));
  clsT1::Test(x);
 }
};
#endif
int main(int argc, char* argv[])
{
 _TRACE_FUNCTION_();
 DbgPrintA("测试\n");
 DbgPrintW(L"测试\n");
#ifdef __cplusplus
 clsT2  _t2;
 _t2.Test();
#endif
//  getchar();
 return 0;
}
 
输出效果:
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(30) : <main>: ++
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(31) : <main>: 测试
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(32) : <main>: 测试
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(21) : <clsT2::Test>:测试
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(12) : <clsT1::Test>:测试
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(30) : <main>: --,Escaped:0
 
头文件(兼容C源代码,多线程安全的,因为内部的部分实现使用了线程存储,如果有人知道如何追踪C代码的函数过程的,请分享):
//------------------------------------------------------------------------------------------------------------------------------------------
// 参数
// _DBG_LIB_NAME ,用于控制输出的前缀
// 开关,关掉输出
#ifndef _DBG_GLOBAL_SWITCH
 #define _DBG_GLOBAL_SWITCH 1
#endif
// 开关,是否总是使用 outputdebugstring,即使是在命令行模式下
#ifndef _DBG_FORCEDBGSTR_SWITCH
 #define _DBG_FORCEDBGSTR_SWITCH 0
#endif
//  开关,是否仅显示 函数名(隐去 文件名,行号)
#ifndef _DBG_SIMPLE_SWITCH
 #define _DBG_SIMPLE_SWITCH 0
#endif
// 优化 assert 的行为
// assert 使用 MessageBox 提示,但是这会导致一些程序无法中断下来
// _ASSERT 会循环 MessageBox,不断弹出对话框
#ifndef _DBG_BREAKIN_ASSERT
#define _DBG_BREAKIN_ASSERT 1
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C"{
#endif
// 取 EIP
LIBBASE_API DWORD WINAPI GetEIP();
// __FUNCIOTN__ 模拟
#ifdef __SIMU_FUNCTION__
 LIBBASE_API LPCSTR WINAPI GetFUNCTIONA(DWORD64 Address);
 LIBBASE_API LPCWSTR WINAPI GetFUNCTIONW(DWORD64 Address);
 #undef __FUNCTION__
 #undef __WFUNCTION__
 #define __FUNCTION__  GetFUNCTIONA(GetEIP())
 #define __WFUNCTION__  GetFUNCTIONW(GetEIP())
#endif
// __LINE__ 修正
#if _MSC_VER==1310
 // 在 VC7.1 中,当设为 /ZI 时,__LINE__ 是 __LINE__Var + 1,所以,下面两个宏将无法正确展开
 #define __SIMU_LINENO__
 #undef __LINENO__
 #undef __WLINENO__
 LIBBASE_API LPCSTR WINAPI GetLINENOA(DWORD dwLine);
 LIBBASE_API LPCWSTR WINAPI GetLINENOW(DWORD dwLine);
 #define __LINENO__  GetLINENOA(__LINE__)
 #define __WLINENO__  GetLINENOW(__LINE__)
#endif
// 通用字符串连接
LIBBASE_API LPCSTR WINAPI LOC_STR_LINKA(LPCSTR psz,...);
LIBBASE_API LPCWSTR WINAPI LOC_STR_LINKW(LPCWSTR psz,...);
#ifdef __cplusplus
};
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 预格式化
#if _DBG_SIMPLE_SWITCH
 #ifndef __SIMU_FUNCTION__
  #define DEF_LOC_STDOUT_A "<" __FUNCTION__ ">: "
  #define DEF_LOC_STDOUT_W L"<" __WFUNCTION__ L">: "
 #else
  #define DEF_LOC_STDOUT_A LOC_STR_LINKA("<",__FUNCTION__,">: ",NULL)
  #define DEF_LOC_STDOUT_W LOC_STR_LINKW(L"<",__WFUNCTION__,L">: ",NULL)
 #endif
#else
 #ifndef _DBG_LIB_NAME
  #define __DBG_LIB_NAMEA ""
  #define __DBG_LIB_NAMEW L""
 #else
  #define __DBG_LIB_NAMEA "(" _DBG_LIB_NAME ")"
  #define __DBG_LIB_NAMEW L"(" _L(_DBG_LIB_NAME) L")"
 #endif
 #if !defined(__SIMU_FUNCTION__) && !defined(__SIMU_LINENO__)
  #define DEF_LOC_STDOUT_A __FILE__ "("__LINENO__") : " __DBG_LIB_NAMEA "<" __FUNCTION__ ">: "
  #define DEF_LOC_STDOUT_W __WFILE__ L"(" __WLINENO__ L") : " __DBG_LIB_NAMEW L"<" __WFUNCTION__ L">: "
 #else
  #define DEF_LOC_STDOUT_A LOC_STR_LINKA(__FILE__,"(",__LINENO__,") : ",__DBG_LIB_NAMEA,"<",__FUNCTION__,">: ",NULL)
  #define DEF_LOC_STDOUT_W LOC_STR_LINKW(__WFILE__,L"(",__WLINENO__,L") : ",__DBG_LIB_NAMEW,L"<",__WFUNCTION__,L">: ",NULL)
 #endif
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 内部参数
#define MAX_BDGBUFF 4096
//------------------------------------------------------------------------------------------------------------------------------------------
// 计时
#ifdef __cplusplus
extern "C"{
#endif
LIBBASE_API ULONGLONG WINAPI GetPerformaceCount();
#ifdef __cplusplus
};
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 输出工具
#ifdef __cplusplus // 对 C 代码不可见
template<class _Ty>
class dbgwriter_dbg
{
public:
 void put(const _Ty* str){}
};
template<class _Ty>
class dbgwriter_con
{
public:
 void put(const _Ty* str){}
};
template<>
void dbgwriter_dbg<CHAR>::put(const CHAR* str)
{
 OutputDebugStringA(str);
}
template<>
void dbgwriter_dbg<WCHAR>::put(const WCHAR* str)
{
 OutputDebugStringW(str);
}
template<>
void dbgwriter_con<CHAR>::put(const CHAR* str)
{
 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hStdOut != INVALID_HANDLE_VALUE)
 {
  DWORD dwRet;
  WriteConsoleA(hStdOut,str,strlen(str),&dwRet,NULL);
 }
}
template<>
void dbgwriter_con<WCHAR>::put(const WCHAR* str)
{
 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hStdOut != INVALID_HANDLE_VALUE)
 {
  DWORD dwRet;
  WriteConsoleW(hStdOut,str,wcslen(str),&dwRet,NULL);
 }
}
typedef dbgwriter_con<CHAR>  dbgwriter_conA;
typedef dbgwriter_con<WCHAR> dbgwriter_conW;
typedef dbgwriter_dbg<CHAR>  dbgwriter_dbgA;
typedef dbgwriter_dbg<WCHAR> dbgwriter_dbgW;
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 行调试
#ifdef __cplusplus
extern "C"{
#endif
typedef void (WINAPI* PFNDBGPRINT_DBGA)(LPCSTR str, ...);
typedef void (WINAPI* PFNDBGPRINT_DBGW)(LPCWSTR str, ...);
typedef void (WINAPI* PFNDBGPRINT_CONA)(LPCSTR str, ...);
typedef void (WINAPI* PFNDBGPRINT_CONW)(LPCWSTR str, ...);
typedef void (WINAPI* PFNDBGPRINTV_DBGA)(LPCSTR ptzFormat, va_list vlArgs);
typedef void (WINAPI* PFNDBGPRINTV_DBGW)(LPCWSTR ptzFormat, va_list vlArgs);
typedef void (WINAPI* PFNDBGPRINTV_CONA)(LPCSTR ptzFormat, va_list vlArgs);
typedef void (WINAPI* PFNDBGPRINTV_CONW)(LPCWSTR ptzFormat, va_list vlArgs);
LIBBASE_API PFNDBGPRINT_DBGA WINAPI _DbgPrint_DBGA(LPCSTR pszTag);
LIBBASE_API PFNDBGPRINT_DBGW WINAPI _DbgPrint_DBGW(LPCWSTR pszTag);
LIBBASE_API PFNDBGPRINT_CONA WINAPI _DbgPrint_CONA(LPCSTR pszTag);
LIBBASE_API PFNDBGPRINT_CONW WINAPI _DbgPrint_CONW(LPCWSTR pszTag);
LIBBASE_API PFNDBGPRINTV_DBGA WINAPI _DbgPrintV_DBGA(LPCSTR pszTag);
LIBBASE_API PFNDBGPRINTV_DBGW WINAPI _DbgPrintV_DBGW(LPCWSTR pszTag);
LIBBASE_API PFNDBGPRINTV_CONA WINAPI _DbgPrintV_CONA(LPCSTR pszTag);
LIBBASE_API PFNDBGPRINTV_CONW WINAPI _DbgPrintV_CONW(LPCWSTR pszTag);
#ifdef __cplusplus
};
#endif
#define DbgPrint_CONA _DbgPrint_CONA(DEF_LOC_STDOUT_A)
#define DbgPrint_CONW _DbgPrint_CONW(DEF_LOC_STDOUT_W)
#define DbgPrint_DBGA _DbgPrint_DBGA(DEF_LOC_STDOUT_A)
#define DbgPrint_DBGW _DbgPrint_DBGW(DEF_LOC_STDOUT_W)
#define DbgPrintV_CONA _DbgPrintV_CONA(DEF_LOC_STDOUT_A)
#define DbgPrintV_CONW _DbgPrintV_CONW(DEF_LOC_STDOUT_W)
#define DbgPrintV_DBGA _DbgPrintV_DBGA(DEF_LOC_STDOUT_A)
#define DbgPrintV_DBGW _DbgPrintV_DBGW(DEF_LOC_STDOUT_W)
#ifdef _UNICODE
 #define DbgPrint_CON DbgPrint_CONW
 #define DbgPrint_DBG DbgPrint_DBGW
 #define DbgPrintV_CON DbgPrintV_CONW
 #define DbgPrintV_DBG DbgPrintV_DBGW
#else
 #define DbgPrint_CON DbgPrint_CONA
 #define DbgPrint_DBG DbgPrint_DBGA
 #define DbgPrintV_CON DbgPrintV_CONA
 #define DbgPrintV_DBG DbgPrintV_DBGA
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
//函数过程追踪
#ifdef __cplusplus // 对 C 代码不可见
template <class _Wy>
class DBGFUNCTRACE
{
protected:
 CStdString m_strTag;//必须保存原始字符串,而不是指针,因为可能对方是临时内存块
 ULONGLONG dwEnter;
public:
 DBGFUNCTRACE(LPCTSTR pszTag)
 {
  m_strTag=pszTag?pszTag:_T("");
  
  CStdString _str;
  _str.Format(_T("%s++\n"),m_strTag.c_str());
  _Wy().put(_str.c_str());
  dwEnter = GetPerformaceCount();
 }
 ~DBGFUNCTRACE()
 {
  CStdString _str;
  _str.Format(_T("%s--,Escaped:%lu\n"),m_strTag.c_str(),GetPerformaceCount() - dwEnter);
  _Wy().put(_str.c_str());
 }
};
#ifdef _UNICODE
 #define _TRACE_FUNCTION_CON() DBGFUNCTRACE<dbgwriter_conW> _FuncTrace ## __LINE__(DEF_LOC_STDOUT_W);
 #define _TRACE_FUNCTION_DBG() DBGFUNCTRACE<dbgwriter_dbgW> _FuncTrace ## __LINE__(DEF_LOC_STDOUT_W);
#else
 #define _TRACE_FUNCTION_CON() DBGFUNCTRACE<dbgwriter_conA> _FuncTrace ## __LINE__(DEF_LOC_STDOUT_A);
 #define _TRACE_FUNCTION_DBG() DBGFUNCTRACE<dbgwriter_dbgA> _FuncTrace ## __LINE__(DEF_LOC_STDOUT_A);
#endif
#else // !__cplusplus
#define _TRACE_FUNCTION_CON() // C 编译方式下不支持
#define _TRACE_FUNCTION_DBG() // C 编译方式下不支持
#endif

//------------------------------------------------------------------------------------------------------------------------------------------
//这是最终的映射
#if (_DBG_GLOBAL_SWITCH && ((defined(_DBG) && _DBG) || defined(_DEBUG)))
 #if  defined(_CONSOLE) && (_DBG_FORCEDBGSTR_SWITCH==0)
  #define DbgPrintA      DbgPrint_CONA
  #define DbgPrintW      DbgPrint_CONW
  #define DbgPrintVA      DbgPrintV_CONA
  #define DbgPrintVW      DbgPrintV_CONW
  #define _TRACE_FUNCTION_()    _TRACE_FUNCTION_CON()
 #else
  #define DbgPrintA      DbgPrint_DBGA
  #define DbgPrintW      DbgPrint_DBGW
  #define DbgPrintVA      DbgPrintV_DBGA
  #define DbgPrintVW      DbgPrintV_DBGW
  #define _TRACE_FUNCTION_()    _TRACE_FUNCTION_DBG()
 #endif
#else // DbgPrint
 #define DbgPrintA __noop
 #define DbgPrintW __noop
 #define DbgPrintVA __noop
 #define DbgPrintVW __noop
 #define _TRACE_FUNCTION_()
#endif // DbgPrint
#ifdef _UNICODE
 #define DbgPrint DbgPrintW
#else
 #define DbgPrint DbgPrintA
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C"{
#endif
LIBBASE_API void WINAPI assert_breakin(const char * exp, void * file, unsigned fileno);
#ifdef __cplusplus
};
#endif
#include <assert.h>
#include <crtdbg.h>
#if _DBG_BREAKIN_ASSERT
 #ifdef assert
  #undef assert
 #endif
 #ifdef _DEBUG
 #define assert(exp) (void)( (exp) || (assert_breakin(#exp, __FILE__, __LINE__), 0) )
 #else
  #define assert(exp)     ((void)0)
 #endif
#endif
#ifdef _ASSERT
 #undef _ASSERT
#endif
#ifdef ASSERT
 #undef ASSERT
#endif
#ifdef VERIFY
 #undef VERIFY
#endif
#define ASSERT(f)          assert(f)
#define _ASSERT(f)          assert(f)
#ifdef _DEBUG
 #define VERIFY(f)          ASSERT(f)
#else
 #define VERIFY(f)          ((void)(f))
#endif
June 28

I did not speak out

First they came for the socialists, and I did not speak out
because I was not socialist.
Then they came for the trade unionists, and I did not speak out
because I was not trade unionists.
Then  they came for the Jews, and I did not speak out
because I was not Jew.
Then they came for me, and there was no one left to speak for me.
  
  -- Pastor Martin Niemöller

June 25

email 有益工作效率

最近一段时间,除了偶尔看一下留言外,基本上没有用msn/qq,减少了中途被打岔的可能.
当然,也节省了近100M的内存.

几分钟收一次信,可以保证重要的信息不被错过.
June 24

完成一个轻量级的高速UI库

一直打算做的一件事,终于下决心行动起来并把它完成了.支持常见的格式,也支持不常见的各种bmp变形格式,支持多种加载/绘图方式,在非常追求性能的情况下,可以使用32位缓存绘图方式,速度极快.
May 29

被VC2005耍了

vc++ 2005 generates wrong code when using /O2 /arch:SSE in some circumstances

很隐蔽的一个bug,首次遇到,费了好大的劲才发现
May 28

删掉 VAX,VS2005立刻快了好多!

同一个版本配合VC6,感觉速度还是挺快的.
配合VC2005,感觉VC2005启动超级慢,删了之后非常快!
why?
May 20

义乌广电开始强行推广数字电视了

近期,原来的有线电视就要被强制停止信号了,义乌广电要求必须安装数字电视.费用比原来贵了1000左右/年.
在义乌的老外可以使用卫星电视,本地人要使用则强行拆除并处罚款,原因是为了维护国家安全.汗,难道不看广电的节目,就不爱国了吗?
这和前几年政府强征农民耕地一模一样啊.这么没人管管呢?
点击查看 义乌丹桂苑 的资讯.
点击查看 义乌的违规征地 的资讯.
May 19

做了一个 v8 的包装接口

使用 SDK方式编程,可以进行 js 和C++ 之间的互相调用,使用这个模块不需要接触 v8的内部实现,接口简洁.
对于原来不具有和 JS双向通讯的代码,只需加入少量代码即可,此外,模块支持 VC6及以后版本.
此外,发现 v8 的速度真是相当爽啊.
 
the sample is simple,哈哈
 
class Window
{
public:
 Window()
 {
  minWidth=0;
  minHeight=0;
  maxWidth=0;
  maxHeight=0;
 }
protected:
//方法
 int msgbox(LPCTSTR text,LPCTSTR title)
 {
  return MessageBox(NULL,text,title,0);
 }
 void showwindows(int dwFlag,int dwFlag2)
 {
  DbgPrint(_T("参数:%d,%d"),dwFlag,dwFlag2);
 }
 BOOL Gettrue()
 {
  return true;
 }
 BOOL Getfalse()
 {
  return FALSE;
 }
 int Getflag()
 {
  return 135;
 }
 void Print(LPCTSTR str)
 {
  DbgPrint(_T("window:%s\n"),str);
 }
 BOOL GetCaptionbyvar(BSTR* pstr)
 {
  *pstr=m_strCaption.AllocSysString();
  return TRUE;
 } 
//属性:
protected:
 void SetminWidth(UINT nNewVal)
 {
  minWidth=nNewVal;
 }
 UINT GetminWidth()
 {
  return minWidth;
 }
 void SetCaption(LPCTSTR szCaption)
 {
  DbgPrint(_T("new Caption:%s"),szCaption);
  m_strCaption=szCaption;
 }
 BSTR GetCaption()
 {
  DbgPrint(_T("now Caption:%s"),(LPCTSTR)m_strCaption);
  return m_strCaption.AllocSysString();
 }
 
//消息
public:
 void OnLoad()
 {
  m_jsengine->Invoke(this,"OnLoad");
 }
 void OnUnLoad()
 {
  m_jsengine->Invoke(this,"OnUnLoad");
 }
 int test(int nVal)
 {
  _variant_t varResult;
  m_jsengine->Invoke(this,"test",&varResult,nVal);
  return varResult;
 }
public:
 UINT minWidth;
 UINT minHeight;
 UINT maxWidth;
 UINT maxHeight;
 CStdString m_strCaption;
 JS_DECLARE_DISPATCH_MAP();
 JS_DECLARE_EVENT_MAP();
};

//假想的窗口对象(唯一实例)
JS_BEGIN_DISPATCH_MAP(Window)
 JS_DISP_FUNCTION(Window,showwindows,VT_EMPTY,VTS_I4 VTS_I4)
 JS_DISP_FUNCTION(Window,Getflag,VT_I4,VTS_NONE)
 JS_DISP_FUNCTION(Window,Print,VT_EMPTY,VTS_BSTR)
 JS_DISP_FUNCTION(Window,msgbox,VT_I4,VTS_BSTR VTS_BSTR)
 JS_DISP_FUNCTION(Window,Gettrue,VT_BOOL,VTS_NONE)
 JS_DISP_FUNCTION(Window,Getfalse,VT_BOOL,VTS_NONE)
//  JS_DISP_FUNCTION(Window,GetCaptionbyvar,VT_BOOL,VTS_PBSTR)
 JS_DISP_PROPERTY(Window,minWidth,VT_I4)
 JS_DISP_PROPERTY(Window,Caption,VT_BSTR)
// JS_DISP_PROPERTY(Window,minheight,VT_I4)
JS_END_DISPATCH_MAP()
 
 
 g_jsengine=CreateJSEngine();
 if(g_jsengine->LoadFile(szFile))
 {
  if (g_jsengine->Compile())
  {
 //   g_jsengine->AddGlobalFunction("Print",Print);
    Window g_win;
    Window2 g_win2;
    g_jsengine->RegisterGlobalClass("WINDOW",g_win.GetDispMap(),g_win.GetEventMap());
    g_jsengine->RegisterGlobalClass("wiNDOw2",g_win2.GetDispMap());
    g_win.SetJSEngine(g_jsengine);
    g_win2.SetJSEngine(g_jsengine);
    g_jsengine->CreateGlobalObject("WIndow","wIN",&g_win);
    g_jsengine->CreateGlobalObject("winDOW2","WIn2",&g_win2);
 //   g_jsengine->AddInstanceFunction("win2","Print2",Print2);
   
    if (g_jsengine->Run())
    {
      g_win.OnLoad();
      DbgPrint_CON(_T("脚本Result:%s\n"),g_jsengine->GetResult());
      DbgPrint_CON(_T("minWidth:%d,minHeight:%d,maxWidth:%d,maxHeight:%d\n"),  \
       g_win.minWidth,g_win.minHeight,g_win.maxWidth,g_win.maxHeight);
      int x=g_win.test(11);
      DbgPrint_CON(_T("返回新数值:%d\n"),x);
      
      g_win.OnUnLoad();
    }
    else
    {
     DbgPrint_CON(_T("脚本执行错误!\n"));
     DbgPrint_CON(_T("Script:\t\t%s\n"),g_jsengine->GetJSFileName());
     DbgPrint_CON(_T("Line:\t\t%d\n"),g_jsengine->GetLastErrorLineNo());
     DbgPrint_CON(_T("Source:\t\t%s\n"),g_jsengine->GetLastErrorSourceLine());
     DbgPrint_CON(_T("Error:\t\t%s\n"),g_jsengine->GetLastErrorMessage());
    }
  }
  else
  {
    DbgPrint_CON(_T("脚本编译错误!\n"));
    DbgPrint_CON(_T("Script:\t\t%s\n"),g_jsengine->GetJSFileName());
    DbgPrint_CON(_T("Line:\t\t%d\n"),g_jsengine->GetLastErrorLineNo());
    DbgPrint_CON(_T("Source:\t\t%s\n"),g_jsengine->GetLastErrorSourceLine());
    DbgPrint_CON(_T("Error:\t\t%s\n"),g_jsengine->GetLastErrorMessage());
  }
 }
 else
 {
  DbgPrint_CON(_T("脚本加载失败!\n"));
 }
 
 DeleteJSEngine(g_jsengine);
 
 
May 12

vcpkg 更新到 4.7

最近的主要更新是
 
1.增加了cryptdll 模块,编译过程中自动加密dll,这可以较好的对抗逆向分析
2.修正一处vc patch
3.完成环境变量的处理
 
v.4.70 (2009.5.12)
1.解决4.65遗留的问题,现在,变量将在识别平台后进行解析,4.66引入的操作被取消
2./implib 不再必须,cryptdll可以自动处理文件格式,重写了cryptdll的重建dll/lib的算法
3.修正VC字体补丁
v4.69 (2009.5.7)
1.添加 cryptdll 功能,仅对 windows 子系统,且包含 /implib 的项目有效,文件生成时自动抹掉导出表的函数名
 
 
配套的VCLoader 改动如下:
1.绝大部分代码进行了重写
2.现在编译器设置和使用习惯信息分开保存,使用习惯记录了每个编译器的使用次数,每个工程所用的编译器,启动时如果能读取到这个工程上次所用的编译器,那么会优先推荐这个编译器,否则,推荐使用次数最多的编译器.
 
 
May 01

来,破解手机QQ2008!

今天早上用了一下手机QQ,给我的印象是功能还不错,操作很方便,广告也挺多,一个早上被 系统消息烦了好像4次.另外,很多基于网页的功能很容易点开.

于是,打开反汇编工具,通过分析,发现只需做小小修改即可去掉不少多余的东西.
以下内容适合 最新官网上的适合Nokia 3230的QQ2008(手机QQ2008(S60 V2)正式版 Build064).

1.工具
反汇编: IDA(如果你只需要修改,则不需要此工具)
16进制修改: Ultraedit(你可以任意选择自己喜欢的16进制编辑器)
2.原理
根据sybian的http连接方式找到相应代码
根据ARM指令集修改具体代码
3.修改方法
把手机里面的TmtHttpEngine_0xA0008D31.dll拷贝到PC,用任意16进制编辑工具打开这个文件,定位到 0x326F,把原来的 1A 改成 0A.
4.效果
修改后:手机通讯网/QQ空间/社区等所有网页形式的功能均失效,聊天正常.
April 30

Vypress Chat 破解

家里几天计算机常常需要互传文件,例如拷贝一下照片,音乐什么的.但是家人都不太熟悉FTP等方式,遇到要传文件时还得开gtalk之类的,甚为麻烦.
最近发现 Vypress Chat 还不错,主要是不需要服务器,每台计算机开机自动运行即可.
 
官方网站上最新的是 2.1.6,30天试用期.开启OD,发现差不多可以秒杀.修改后,自动成为注册版,授权数当然也足够了.
 
原代码如下:
0041D110      833D 247C4D00>cmp     dword ptr [4D7C24], 0            ;  注册验证
0041D117      74 0F         je      short 0041D128
0041D119      833D 287C4D00>cmp     dword ptr [4D7C28], 0
0041D120      74 06         je      short 0041D128
0041D122      B8 01000000   mov     eax, 1
0041D127      C3            retn
0041D128      33C0          xor     eax, eax
0041D12A  \.  C3            retn
 
修改后:
0041D110  /$  833D 247C4D00>cmp     dword ptr [4D7C24], 0
0041D117  |.  B8 01000000   mov     eax, 1
0041D11C  |.  75 0C         jnz     short 0041D12A
0041D11E  |.  A3 247C4D00   mov     dword ptr [4D7C24], eax   ;是否已注册,非0即可
0041D123  |.  B4 FF         mov     ah, 0FF       ;授权数,会做网内验证,所以越多越好,0xff01 授权
0041D125  |.  A3 287C4D00   mov     dword ptr [4D7C28], eax
0041D12A  \> \C3            retn
 
对应文件偏移的修改从 0x1c510 开始.对比两者二进制差异部分进行修改
 
小技巧:
1.如何最小化启动
创建一个快捷方式,把 Run 项 设为 Minimized. 在启动组放入这样一个快捷方式即可,开机自动运行,不会出现主窗口.
如果不想通过快捷方式指定,那么修改 0x254c7,把74改成EB,这样,任何情况下启动总是最小化到托盘.
 
2.如何避免程序出现在托盘中
这个程序第二次运行时会自动激活原来的进程,所以,托盘区的图标可以算是多余的.去掉托盘图标可以节省托盘空间,也可以避免家人误推出进程导致无法发送消息
修改方法: 把 0x2d08C 处 的 6a 00 改成 6a 02
 
------------------------------------------------------------------以下是调试笔记------------------------------------------------------------------
调试笔记:
1.破解
将日期后调 30天以上,程序会弹出使用过期的提示,在diaglog相关函数上下断点,断下后,回溯堆栈即可找到
0041D110      833D 247C4D00>cmp     dword ptr [4D7C24], 0            ;  注册验证
0041D117      74 0F         je      short 0041D128
0041D119      833D 287C4D00>cmp     dword ptr [4D7C28], 0
0041D120      74 06         je      short 0041D128
0041D122      B8 01000000   mov     eax, 1
0041D127      C3            retn
0041D128      33C0          xor     eax, eax
0041D12A  \.  C3            retn
改成
0041D110  /$  833D 247C4D00>cmp     dword ptr [4D7C24], 0
0041D117  |.  B8 01000000   mov     eax, 1
0041D11C  |.  75 0C         jnz     short 0041D12A
0041D11E  |.  A3 247C4D00   mov     dword ptr [4D7C24], eax   ;是否已注册,非0即可
0041D123  |.  B4 FF         mov     ah, 0FF       ;授权数,会做网内验证,所以越多越好,0xff01 授权
0041D125  |.  A3 287C4D00   mov     dword ptr [4D7C28], eax
0041D12A  \> \C3            retn
 

2.如何启动时自动最小化到托盘
建立一个快捷方式,将其设为最小化,发现可以自动最小化.当然,这不是最方便的,下断点 ShowWindows,检查调用
发现
004260B9  |.  8BB6 9C090000 mov     esi, dword ptr [esi+99C]
004260BF  |.  8BC6          mov     eax, esi
004260C1  |.  83C4 04       add     esp, 4
004260C4  |.  83E8 02       sub     eax, 2                           ;  Switch (cases 2..7)
004260C7  |.  74 48         je      short VyChat.00426111   ; 减 2 等于0 ,那么 参数是 SW_SHOWMINIMIZED
004260C9  |.  83E8 01       sub     eax, 1
004260CC  |.  74 1A         je      short VyChat.004260E8   ; 减 3 等于0 ,那么 参数是 SW_SHOWMAXIMIZED
004260CE  |.  83E8 04       sub     eax, 4
004260D1  |.  74 3E         je      short VyChat.00426111   ; 减 7 等于0 ,那么 参数是 SW_SHOWMINNOACTIVE
004260D3  |.  56            push    esi                              ; /ShowState; Default case of switch 004260C4;执行创建者指定的显示
004260D4  |.  53            push    ebx                              ; |hWnd
004260D5  |.  FF15 A4D44B00 call    dword ptr [<&USER32.ShowWindow>] ; \ShowWindow
004260DB  |.  53            push    ebx                              ; /hWnd
004260DC  |.  FF15 04D44B00 call    dword ptr [<&USER32.UpdateWindow>; \UpdateWindow
004260E2  |.  33C0          xor     eax, eax
004260E4  |.  5F            pop     edi
004260E5  |.  5E            pop     esi
004260E6  |.  59            pop     ecx
004260E7  |.  C3            retn
004260E8  |>  6A 03         push    3                                ; /ShowState = SW_SHOWMAXIMIZED; Case 3 of switch 004260C4;最大化方式的执行分支
004260EA  |.  53            push    ebx                              ; |hWnd
004260EB  |.  FF15 A4D44B00 call    dword ptr [<&USER32.ShowWindow>] ; \ShowWindow
004260F1  |.  53            push    ebx                              ; /hWnd
004260F2  |.  FF15 04D44B00 call    dword ptr [<&USER32.UpdateWindow>; \UpdateWindow
004260F8  |.  6A 00         push    0
004260FA  |.  68 30F00000   push    0F030
004260FF  |.  68 12010000   push    112
00426104  |.  53            push    ebx
00426105  |.  FF15 C8574D00 call    dword ptr [4D57C8]               ;  VyChat.004A2CEE
0042610B  |.  33C0          xor     eax, eax
0042610D  |.  5F            pop     edi
0042610E  |.  5E            pop     esi
0042610F  |.  59            pop     ecx
00426110  |.  C3            retn
00426111  |>  6A 00         push    0                                ;  Cases 2,7 of switch 004260C4;最小化或非激活方式的执行分支
00426113  |.  68 CD9C0000   push    9CCD
00426118  |.  68 11010000   push    111
0042611D  |.  53            push    ebx
0042611E  |.  FF15 C8574D00 call    dword ptr [4D57C8]               ;  VyChat.004A2CEE
00426124  |.  5F            pop     edi
00426125  |.  33C0          xor     eax, eax
00426127  |.  5E            pop     esi
00426128  |.  59            pop     ecx
00426129  \.  C3            retn
所以,很显然,如下方式修改即可
004260C7     /EB 48         jmp     short VyChat.00426111

程序启动后一律按最小化启动

3.如何去除托盘图标
去掉托盘图标可以节约托盘空间,如果需要激活主窗口,那么再次运行一下桌面的快捷方式,新进程会自动激活老进程并自己退出.
下断点: Shell_NotifyIconW
0042DC00  /$  53            push    ebx
0042DC01  |.  56            push    esi
0042DC02  |.  57            push    edi
0042DC03  |.  8BF0          mov     esi, eax
0042DC05  |.  E8 B6000000   call    VyChat.0042DCC0
0042DC0A  |.  68 B8030000   push    3B8
0042DC0F  |.  8DBE 68230000 lea     edi, dword ptr [esi+2368]
0042DC15  |.  6A 00         push    0
0042DC17  |.  57            push    edi
0042DC18  |.  E8 33940700   call    VyChat.004A7050
0042DC1D  |.  8B86 401F0000 mov     eax, dword ptr [esi+1F40]
0042DC23  |.  83C4 0C       add     esp, 0C
0042DC26  |.  833D 3C754D00>cmp     dword ptr [4D753C], 0
0042DC2D  |.  8986 6C230000 mov     dword ptr [esi+236C], eax
0042DC33  |.  C786 70230000>mov     dword ptr [esi+2370], 6C
0042DC3D  |.  C786 74230000>mov     dword ptr [esi+2374], 7
0042DC47  |.  C786 78230000>mov     dword ptr [esi+2378], 6D
0042DC51  |.  74 12         je      short VyChat.0042DC65
0042DC53  |.  C707 B8030000 mov     dword ptr [edi], 3B8
0042DC59  |.  C786 88260000>mov     dword ptr [esi+2688], 3
0042DC63  |.  EB 06         jmp     short VyChat.0042DC6B
0042DC65  |>  C707 98000000 mov     dword ptr [edi], 98
0042DC6B  |>  8B0D 20804D00 mov     ecx, dword ptr [4D8020]
0042DC71  |.  8B96 2C270000 mov     edx, dword ptr [esi+272C]
0042DC77  |.  41            inc     ecx
0042DC78  |.  C1E1 08       shl     ecx, 8
0042DC7B  |.  51            push    ecx                              ; /Style
0042DC7C  |.  6A 00         push    0                                ; |Index = 0
0042DC7E  |.  52            push    edx                              ; |hIml
0042DC7F  |.  FF15 7CD04B00 call    dword ptr [<&COMCTL32.ImageList_>; \ImageList_GetIcon
0042DC85  |.  8B1D 1C574D00 mov     ebx, dword ptr [4D571C]          ;  SHELL32.Shell_NotifyIconW
0042DC8B  |.  57            push    edi
0042DC8C      6A 00         push    0        ; 消息 NIM_ADD,改成 NIM_DELETE 即可
0042DC8E  |.  8986 7C230000 mov     dword ptr [esi+237C], eax
0042DC94  |.  FFD3          call    ebx
0042DC96  |.  833D 3C754D00>cmp     dword ptr [4D753C], 0
0042DC9D  |.  74 05         je      short VyChat.0042DCA4
0042DC9F  |.  57            push    edi
0042DCA0  |.  6A 04         push    4
0042DCA2  |.  FFD3          call    ebx
0042DCA4  |>  6A 00         push    0                                ; /Arg1 = 00000000
0042DCA6  |.  8BDE          mov     ebx, esi                         ; |
0042DCA8  |.  E8 4357FFFF   call    VyChat.004233F0                  ; \VyChat.004233F0
0042DCAD  |.  5F            pop     edi
0042DCAE  |.  5E            pop     esi
0042DCAF  |.  B8 01000000   mov     eax, 1
0042DCB4  |.  5B            pop     ebx
0042DCB5  \.  C3            retn
修改如下
0042DC8C      6A 02         push    2
启动后,程序不会往托盘添加图标,当然重建任务栏时也不会
 

双飞燕 WOP-353 优化驱动

今天晚上整理东西时,发现一个大学时用的双飞燕双滚轮鼠标,随手接上用了一下,水平滚轮看代码还是挺方便的,但是由于是几年前的鼠标,指针移动数度较慢.除了 双滚轮,另一个特点就是 连接线特别长,特别适合我在用的hp540本本,它的USB插槽在左侧,于是USB线需要特别长一点.

于是,写了一个小驱动优化了一下.
本驱动完全兼容官方驱动,可以独立安装,也可以配合官方驱动同时使用.
支持USB连接模式,不支持PS/2连接模式.

使用方法:
运行 installer.exe 进行安装/卸载即可,如果鼠标更换了USB插槽,需要再次执行安装.
 
 
April 27

百度3000万人民币收购天空软件四股力量暗战

 
2006年07月22日 01:22 财经时报
  本报记者 李国训
  早在两年前,国内几大利益集团就已围绕收购个人网站展开了竞赛。百度不过是这几大势力的一员
  这似乎是《教父》情节在国内互联网市场的重演:为了抢占更多资源,多家势力集团之间展开了长达数年的收购竞赛。
  国内互联网貌似平静的水面下,带着浓重江湖气息的暗流正在疯狂涌动。
  百度天价收购天空软件
  最近,国内知名个人网站“天空软件”站长张鹤在湖北老家长长松了口气。
  几个月前,张鹤成功将自己一手创立的网站卖了出去,售价相当可观不说,接手方的实力更是有目共睹,是国内互联网的龙头老大——百度。
  《财经时报》近日从多个可靠渠道获悉,早在今年5月,百度就以3000万元人民币的价格完成了对天空软件的最终收购。
  目前,百度已将天空软件的广告销售纳入了自有体系,并将针对天空软件进行更多内部整合工作。
  据悉,这也是迄今为止百度最为巨大的一次收购案例。
  2004年,百度宣称以5000万元收购国内最大网址站Hao123.com,实际收购金额仅为1000万元。而此次收购天空软件,百度开出的3000万元则是真金实银。
  “现在知道这事的人还很少。将来百度对外公布的话,收购数字有可能会是8000万甚至1亿元。但不可否认,这确实是国内个人网站最大的一次收购案。”某知情人士对此透露说。
  天空软件网站由张鹤创建于2001年,为国内最知名的软件下载网站之一,在ALEXA全球网站排名中名列351名,每日页面流量超过数百万。据知情人透露,这一网站目前的运营团队均在湖北境内,公司人数大约在10人左右。
  对于收购一事,当事双方均讳莫如深。
  7月20日,百度副总裁梁冬接受《财经时报》电话采访时表示,“基于对合作伙伴的尊重,我们有义务不对具体的合作发表评论。”但他承认,百度和一些网站已经达成了“形式各样的合作模式”。
  幕后势力操作软件收购
  实际上,百度收购不过是国内互联网暗流潜动的一个缩影。
  据一位不愿署名的人士透露,早在两年前,国内几大利益集团就已围绕收购个人网站展开了竞赛。百度不过是这几大势力的一员。
  “现在是互联网加速整合的一个高峰。”该人士评价说,“所不同的是,以前大家收购的是有像Hao123这样有巨大流量的个人网站,而现在,大家抢的是热门软件,以及天空软件这样的软件通道。”
  不久前,百度悄然收购了一款名为“千千静听”的MP3播放软件。在某家网站公布的十大下载量最大共享软件中,这款软件以18780836的高票名列第三名。据知情人透露,百度此次收购的价格也在百万元以上。
  作为国内最资深的互联网大佬,千橡集团总裁陈一舟更加热衷于类似的收购。2004年全资收购了国内最大的社区网站猫扑,从此一发不可收拾。2005年又继续收购著名IT社区DONEWS.迄今为止,陈一舟已收购了3家SP公司,以及DuDu等多个热门软件。
  2005年年底,陈一舟又悄悄收购了中国共享软件注册中心,并在此基础上成立了中国软件社区。“这个做法的目的很明确,就是先掌握软件渠道,为下一步收购国产软件打好基础。”一位接近陈一舟的人士向《财经时报》解释说。
  “最近,陈一舟和ZCOM展开了对FlashGet的竞购。尽管最后被ZCOM得手,但这个失败更加坚定了他收购其他软件的决心。”该人士声称。
  FlashGet又称网际快车,是国内最受欢迎的本土下载软件之一,以提高下载速度、批下载和下载文档管理的功能而闻名业内。不久前,获得凯雷 1000万美元投资的ZCOM智通无限科技有限公司以千万元的价格将之收购。此外,ZCOM还以500万元的价格收购了珊瑚虫版QQ软件。
  而据该人士透露,在ZCOM公司这两次收购案中,真正的幕后操盘手有可能是265.com的老总蔡文胜。原因很简单,尽管没有文字记载,但蔡文胜身为 ZCOM大股东的事实已在坊间广为流传。而他对于投资软件的爱好更可以以狂热来形容。迄今为止,他已直接投资或收购了包括动网、Verycd,以及周博通在内的多个软件及相关网站。
  “蔡文胜是互联网的一方诸侯,光他手上囤积的域名资源就价值数亿元。他的特点是喜欢通过小投资控制热门软件和网站,并和这些软件和网站实施捆绑。”上述人士透露说。
  此外,奇虎网CEO周鸿也被视为掀起互联网“暗战”的一个力量。这位3721创始人以及前雅虎中国总裁最近携手众多VC,已投资了包括奇虎、Discuz!、迅雷在内的多个软件及相关网站。
  “最近迅雷获得的新一轮投资是1亿美元,你从中可以想象这个P2P软件有多么值钱了。”某知名站长向《财经时报》透露说。
March 29

[转]向其他进程注入代码的方法

 
//...

// 1. 在远程进程中为szLibPath 分配内存
// 2. 写szLibPath到分配的内存
pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath),
                               MEM_COMMIT, PAGE_READWRITE );
::WriteProcessMemory( hProcess, pLibRemote, (void*)szLibPath,
                      sizeof(szLibPath), NULL );


// 加载 "LibSpy.dll" 到远程进程
// (通过 CreateRemoteThread & LoadLibrary)
hThread = ::CreateRemoteThread( hProcess, NULL, 0,
            (LPTHREAD_START_ROUTINE) ::GetProcAddress( hKernel32,
                                       "LoadLibraryA" ),
             pLibRemote, 0, NULL );
::WaitForSingleObject( hThread, INFINITE );

//取得DLL的基地址
::GetExitCodeThread( hThread, &hLibModule );

//扫尾工作
::CloseHandle( hThread );
::VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE );

我们放在DllMain中的真正要注入的代码(比如为SendMessage)现在已经被执行了(由于DLL_PROCESS_ATTACH),所以现在可以把DLL从目的进程中卸载了。

// 从目标进程卸载LibSpu.dll
// (通过 CreateRemoteThread & FreeLibrary)
hThread = ::CreateRemoteThread( hProcess, NULL, 0,
            (LPTHREAD_START_ROUTINE) ::GetProcAddress( hKernel32,
                                       "FreeLibrary" ),
            (void*)hLibModule, 0, NULL );
::WaitForSingleObject( hThread, INFINITE );

// 扫尾工作
::CloseHandle( hThread );

进程间通讯
    到目前为止,我们仅仅讨论了任何向远程进程注入DLL,然而,在多数情况下被注入的DLL需要和你的程序以某种方式通讯(记住,那个DLL是被映射到远程进程中的,而不是在你的本地程序中!)。以密码间谍为例:那个DLL需要知道包含了密码的的控件的句柄。很明显,这个句柄是不能在编译期间硬编码(hardcoded)进去的。同样,当DLL得到密码后,它也需要把密码发回我们的程序。

    幸运的是,这个问题有很多种解决方案:文件映射(Mapping),WM_COPYDATA,剪贴板等。还有一种非常便利的方法#pragma data_seg。这里我不想深入讨论因为它们在MSDN(看一下Interprocess Communications部分)或其他资料中都有很好的说明。我在LibSpy中使用的是#pragma data_seg。

    你可以在本文章的开头找到LibSpy及源代码的下载链接。

Ⅲ.CreateRemoteThread和WriteProcessMemory技术
示例程序:WinSpy

    另一种注入代码到其他进程地址空间的方法是使用WriteProcessMemory API。这次你不用编写一个独立的DLL而是直接复制你的代码到远程进程(WriteProcessMemory)并用CreateRemoteThread执行之。

    让我们看一下CreateRemoteThread的声明:
HANDLE CreateRemoteThread(
  HANDLE hProcess,        // handle to process to create thread in
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // pointer to security
                                             // attributes
  DWORD dwStackSize,      // initial thread stack size, in bytes
  LPTHREAD_START_ROUTINE lpStartAddress,     // pointer to thread
                                             // function
  LPVOID lpParameter,     // argument for new thread
  DWORD dwCreationFlags,  // creation flags
  LPDWORD lpThreadId      // pointer to returned thread identifier
);

和CreateThread相比,有一下不同:

●增加了hProcess参数。这是要在其中创建线程的进程的句柄。
●CreateRemoteThread的lpStartAddress参数必须指向远程进程的地址空间中的函数。这个函数必须存在于远程进程中,所以我们不能简单地传递一个本地ThreadFucn的地址,我们必须把代码复制到远程进程。
●同样,lpParameter参数指向的数据也必须存在于远程进程中,我们也必须复制它。

    现在,我们总结一下使用该技术的步骤:

    1. 得到远程进程的HANDLE(OpenProcess)。
    2. 在远程进程中为要注入的数据分配内存(VirtualAllocEx)、
    3. 把初始化后的INJDATA结构复制到分配的内存中(WriteProcessMemory)。
    4. 在远程进程中为要注入的数据分配内存(VirtualAllocEx)。
    5. 把ThreadFunc复制到分配的内存中(WriteProcessMemory)。
    6. 用CreateRemoteThread启动远程的ThreadFunc。
    7. 等待远程线程的结束(WaitForSingleObject)。
    8. 从远程进程取回指执行结果(ReadProcessMemory 或 GetExitCodeThread)。
    9. 释放第2、4步分配的内存(VirtualFreeEx)。
    10. 关闭第6、1步打开打开的句柄。

    另外,编写ThreadFunc时必须遵守以下规则:
    1. ThreadFunc不能调用除kernel32.dll和user32.dll之外动态库中的API函数。只有kernel32.dll和user32.dll(如果被加载)可以保证在本地和目的进程中的加载地址是一样的。(注意:user32并不一定被所有的Win32进程加载!)参考附录A。如果你需要调用其他库中的函数,在注入的代码中使用LoadLibrary和GetProcessAddress强制加载。如果由于某种原因,你需要的动态库已经被映射进了目的进程,你也可以使用GetMoudleHandle代替LoadLibrary。同样,如果你想在ThreadFunc中调用你自己的函数,那么就分别复制这些函数到远程进程并通过INJDATA把地址提供给ThreadFunc。
    2. 不要使用static字符串。把所有的字符串提供INJDATA传递。为什么?编译器会把所有的静态字符串放在可执行文件的“.data”段,而仅仅在代码中保留它们的引用(即指针)。这样,远程进程中的ThreadFunc就会执行不存在的内存数据(至少没有在它自己的内存空间中)。
    3. 去掉编译器的/GZ编译选项。这个选项是默认的(看附录B)。
    4. 要么把ThreadFunc和AfterThreadFunc声明为static,要么关闭编译器的“增量连接(incremental linking)”(看附录C)。
    5. ThreadFunc中的局部变量总大小必须小于4k字节(看附录D)。注意,当degug编译时,这4k中大约有10个字节会被事先占用。
    6. 如果有多于3个switch分支的case语句,必须像下面这样分割开,或用if-else if代替:

switch( expression ) {
    case constant1: statement1; goto END;
    case constant2: statement2; goto END;
    case constant3: statement2; goto END;
}
switch( expression ) {
    case constant4: statement4; goto END;
    case constant5: statement5; goto END;
    case constant6: statement6; goto END;
}
END:
(参考附录E)

    如果你不按照这些游戏规则玩的话,你注定会使目的进程挂掉!记住,不要妄想远程进程中的任何数据会和你本地进程中的数据存放在相同内存地址!(参看附录F)
(原话如此:You will almost certainly crash the target process if you don't play by those rules. Just remember: Don't assume anything in the target process is at the same address as it is in your process.)


GetWindowTextRemote(A/W)

    所有取得远程edit中文本的工作都被封装进这个函数:GetWindowTextRemote(A/W):
int GetWindowTextRemoteA( HANDLE hProcess, HWND hWnd, LPSTR  lpString );
int GetWindowTextRemoteW( HANDLE hProcess, HWND hWnd, LPWSTR lpString );

参数:
hProcess
 目的edit所在的进程句柄
hWnd
 目的edit的句柄
lpString
 接收字符串的缓冲

QQ校友,还不错!

试用了一下QQ校友录,感觉不错.
March 27

又下雨了

延期出行
March 25

VB,VC,Delphi,SDK笑话

话说PD国VB, VC,, Delphi, ,SDK一齐乘火车,走着走着,忽听咣一声响,火车头忽然裂为八瓣儿。火车走不了了。于是大家下车商讨对策。,SDK说:"这好办,看我的。",说着,,SDK从身后拿出铁镐,斧头,大锅等一干工具。别人都以为,SDK先要解决温饱问题,不想,SDK一边架锅一边提出自己的解决方案:"先砍一棵树,劈成木柴点起来,再在旁边岩壁上,挖一个矿井,产出铁矿石,练成钢后,便可以再造一个火车头了。"。我考,其余人一齐恶到在地,在地上齐喊Cancel。
这时VC,说:"火车头虽已四分五裂,但我们可以将这些部件的有用部分继承下来,做成一个新的。"。 Delphi点头称是,VB半懂不懂。VC,一看基本获得通过,挽起袖子准备干活,不想走到近前,发现对火车头不甚了解,但这也难不倒VC,,只见VC,轻点F1,本想获得一些帮助,不想弹出一对话框:本系统没有安装MSDN。正当VC,准备晕倒之时, Delphi从煤堆中翻出两张D版MSDN交给VC,,VC,用颤抖的双手将MSDN装上以后发现,这个版本的MSDN居然还是简体PD文版的,内容非常丰富,不仅有火车头,还有飞机头,汽车头等,另外还有各种动物的头,比如gui头。VC,点中火车头的热链接。"啊,天哪!",VC,终于昏倒在地。 Delphi与VB凑近一看,原来简体PD文版只是个噱头,真正的文档都是M$文版的。VC,的方案终告失败。此时天空蔚蓝的仿佛篮屏。
VB眼珠一转想出了一个办法,砍倒了一些树,VB居然用树做了一个象么象样但却比原来大许多倍的火车头。四人欢天喜地上了车,没想到火车纹丝不动, Delphi问:"这火车头怎么不动啊?"。VB说:"兄弟,您还不了解我么,我做的东东什么时候能自己动啊?","那怎么办!","不着急,有上帝呐"。这是天空中传来上帝耶和华·比尔盖茨的声音:"VB,我从小看着你长大的孩子啊,我赐予你的火车头32个人的力量,让它run吧。"。这时火车居然吱吱嘎嘎的行进起来,可是速度又慢又不稳定,没过多久火车又停了。
这时 Delphi正在车厢中溜达,他发现,车厢的最后端有些大大小小的可以控制的件。于是 Delphi招呼大家把这些件搬下车看看是什么东西,没想到这个中国式的车厢门太窄,于是大家就像蚂蚁似的续传着搬下了车。 Delphi照着读我把这些件拼凑起来,没想到居然是一个崭新的火车头, Delphi对着火车头道:"别看我对你的这些件们的内部不了解,但我能把你们拼起来。"。
于是众人上了火车,又前行了。

恭喜

妹妹通过教育局考试,成为教师啦
March 24

[转帖]义乌现象

 
     义乌已经是成了外国人抢劫中国财富的一个最重要的窗口,他们主要的手段就是在义乌做个办事处,谈好了就要你和义乌人谈,义乌人再给你一刀,我真的不明白,我们中国的产品为什么一定要贱卖,为什么不能卖个合理的价格,合理的价格收入是每个企业的生存来源,企业生存来源是每个职工收入的来源,难道这一点我们都不懂了吗,我们把本来就应该属于中国人的利润毫不留情的砍杀给了老外,自己还沾沾自喜,因为博得了外国人的喜欢,不要让老外再来抢劫我们。

       只有中国人自己的利益获得最大化才有发展的潜力。这样的杀鸡取蛋能发展的好吗,我表示严重的怀疑,这样就是应了老祖宗的一句话这就是穷折腾折腾穷,把企业吧自己都折腾完了还有什么可以做的。

      最好的就是企业有充足的利润化,职工有合理收入化,这样我们的国家才能正常的发展,这是发展的正常路线,现在这样不是我们想看到的,老外已经非常熟悉中国的规则,他们知道怎么抢劫我们,因为我们给了一个非常好的抢劫的窗口

 

wenjiang ye