iTimothy

君看一叶舟,出没风波里

0%


  • 这是从文件里装放位图
  • *******************************************************************/ BOOL CXxxView::OnDraw(CDC* pDC) { HBITMAP bitmap,OldBitmap; bitmap = (HBITMAP)LoadImage(NULL,”xxx.bmp”,IMAGE_BITMAP, 0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION); CDC MemDC; MemDC.CreateCompatibleDC(pDC); OldBitmap=(HBITMAP)MemDC.SelectObject(bitmap); pDC->BitBlt(0,0,400,300,&MemDC;,0,0,SRCCOPY); MemDC.SelectObject(OldBitmap); return TRUE; }

学习VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于 编程者来说,最好改的错误莫过于编译错误,而一般说来发生连接错误时, 编译都已通过。产生连接错误的原因非常多,尤其LNK2001错误,常常使人不 明其所以然。如果不深入地学习和理解VC++,要想改正连接错误LNK2001非 常困难。   初学者在学习VC++的过程中,遇到的LNK2001错误的错误消息主要为:   unresolved external symbol “symbol”(不确定的外部“符号”)。   如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或 标签,将产生此错误消息。一般来说,发生错误的原因有两个:一是所引用 的函数、变量不存在、拼写不正确或者使用错误;其次可能使用了不同版本 的连接库。   以下是可能产生LNK2001错误的原因:   一.由于编码错误导致的LNK2001。   1.不相匹配的程序代码或模块定义(.DEF)文件能导致LNK2001。例如, 如果在C++ 源文件内声明了一变量“var1”,却试图在另一文件内以变量 “VAR1”访问该变量,将发生该错误。   2.如果使用的内联函数是在.CPP文件内定义的,而不是在头文件内定 义将导致LNK2001错误。   3.调用函数时如果所用的参数类型同函数声明时的类型不符将会产生 LNK2001。   4.试图从基类的构造函数或析构函数中调用虚拟函数时将会导致LNK2001。   5.要注意函数和变量的可公用性,只有全局变量、函数是可公用的。   静态函数和静态变量具有相同的使用范围限制。当试图从文件外部访问 任何没有在该文件内声明的静态变量时将导致编译错误或LNK2001。   函数内声明的变量(局部变量) 只能在该函数的范围内使用。   C++ 的全局常量只有静态连接性能。这不同于C,如果试图在C++的 多个文件内使用全局变量也会产生LNK2001错误。一种解决的方法是需要时在 头文件中加入该常量的初始化代码,并在.CPP文件中包含该头文件;另一种 方法是使用时给该变量赋以常数。   二.由于编译和链接的设置而造成的LNK2001   1.如果编译时使用的是/NOD(/NODEFAULTLIB)选项,程序所需要的运行 库和MFC库在连接时由编译器写入目标文件模块, 但除非在文件中明确包含 这些库名,否则这些库不会被链接进工程文件。在这种情况下使用/NOD将导 致错误LNK2001。   2.如果没有为wWinMainCRTStartup设定程序入口,在使用Unicode和MFC 时将得到“unresolved external on _WinMain@16”的LNK2001错误信息。   3.使用/MD选项编译时,既然所有的运行库都被保留在动态链接库之内, 源文件中对“func”的引用,在目标文件里即对“__imp__func” 的引用。 如果试图使用静态库LIBC.LIB或LIBCMT.LIB进行连接,将在__imp__func上发 生LNK2001;如果不使用/MD选项编译,在使用MSVCxx.LIB连接时也会发生LNK2001。   4.使用/ML选项编译时,如用LIBCMT.LIB链接会在_errno上发生LNK2001。   5.当编译调试版的应用程序时,如果采用发行版模态库进行连接也会产 生LNK2001;同样,使用调试版模态库连接发行版应用程序时也会产生相同的 问题。   6.不同版本的库和编译器的混合使用也能产生问题,因为新版的库里可 能包含早先的版本没有的符号和说明。   7.在不同的模块使用内联和非内联的编译选项能够导致LNK2001。如果 创建C++库时打开了函数内联(/Ob1或/Ob2),但是在描述该函数的相应头 文件里却关闭了函数内联(没有inline关键字),这时将得到该错误信息。 为避免该问题的发生,应该在相应的头文件中用inline关键字标志内联函数。   8.不正确的/SUBSYSTEM或/ENTRY设置也能导致LNK2001。   其实,产生LNK2001的原因还有很多,以上的原因只是一部分而已,对初 学者来说这些就够理解一阵子了。但是,分析错误原因的目的是为了避免错 误的发生。LNK2001错误虽然比较困难,但是只要注意到了上述问题,还是能 够避免和予以解决的。

MSG msg; if(::PeekMessage(&msg;,NULL,0,0,PM_REMOVE)){ if(msg.message==WM_QUIT) { ::PostQuitMessage(-1); }

if(!AfxGetApp()->PreTranslageMessage(&msg;)) { ::TranslateMessage(&msg;); ::DispatchMessage(&msg;); }

核心代码片断:

void CLoadLibraryTestDlg::OnLoad() { typedef int (WINAPI * MyFun)(HWND,LPCTSTR,LPCTSTR,UINT); MyFun fun=NULL; HINSTANCE hHandle; hHandle=LoadLibrary(“user32.dll”); fun=(int (WINAPI *)(HWND,LPCTSTR,LPCTSTR,UINT))::GetProcAddress(hHandle,”MessageBoxA”); if(fun!=NULL) { fun(NULL,”hahahahahahahaha”,”success :)”,MB_OK); } }

// Injection.cpp : 定义控制台应用程序的入口点。 //

#include “stdafx.h” #include “Injection.h” #ifdef _DEBUG #define new DEBUG_NEW #endif

// 唯一的应用程序对象

CWinApp theApp;

using namespace std;

typedef struct _RemotePara{//参数结构 char pMessageBox[12]; DWORD dwMessageBox; }RemotePara; //远程线程 DWORD __stdcall ThreadProc (RemotePara *lpPara){ typedef int (__stdcall *MMessageBoxA)(HWND,LPCTSTR,LPCTSTR,DWORD);//定义MessageBox函数 MMessageBoxA myMessageBoxA; myMessageBoxA =(MMessageBoxA) lpPara->dwMessageBox ;//得到函数入口地址 myMessageBoxA(NULL,lpPara->pMessageBox ,lpPara->pMessageBox,0);//call return 0; } void EnableDebugPriv();//提升应用级调试权限

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { const DWORD THREADSIZE=1024*4; DWORD byte_write; EnableDebugPriv();//提升权限 HANDLE hWnd = ::OpenProcess (PROCESS_ALL_ACCESS,FALSE,760); if(!hWnd)return 0; void *pRemoteThread =::VirtualAllocEx(hWnd,0,THREADSIZE,MEM_COMMIT| MEM_RESERVE,PAGE_EXECUTE_READWRITE); if(!pRemoteThread)return 0; if(!::WriteProcessMemory(hWnd,pRemoteThread,&ThreadProc;,THREADSIZE,0)) return 0;

//再付值 RemotePara myRemotePara; ::ZeroMemory(&myRemotePara;,sizeof(RemotePara)); HINSTANCE hUser32 = ::LoadLibrary (“user32.dll”); myRemotePara.dwMessageBox =(DWORD) ::GetProcAddress (hUser32 , “MessageBoxA”); strcat(myRemotePara.pMessageBox,”hello\0”); //写进目标进程 RemotePara *pRemotePara =(RemotePara *) ::VirtualAllocEx (hWnd ,0,sizeof(RemotePara),MEM_COMMIT,PAGE_READWRITE);//注意申请空间时的页面属性 if(!pRemotePara)return 0; if(!::WriteProcessMemory (hWnd ,pRemotePara,&myRemotePara;,sizeof myRemotePara,0))return 0;

//启动线程 HANDLE hThread = ::CreateRemoteThread (hWnd ,0,0,(DWORD (__stdcall *)(void *))pRemoteThread ,pRemotePara,0,&byte;_write); if(!hThread){ return 0; } return 0; }

void EnableDebugPriv( void ) { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp;

if ( ! OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken; ) ) return; if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue; ) ){ CloseHandle( hToken ); return; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp;, sizeof tkp, NULL, NULL ) ) CloseHandle( hToken ); }

核心代码片断:

if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken;)) { MessageBox(“OpenProcessToken failed!”); }

    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,&tkp.Privileges;[0].Luid); //获得本地机唯一的标识
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken, FALSE, &tkp;, 0,(PTOKEN_PRIVILEGES) NULL, 0); //调整获得的权限

    if (GetLastError() != ERROR_SUCCESS)
    {
        MessageBox("切换系统级权限失败!");
    }

    fResult =InitiateSystemShutdown(
         NULL,                                  // 要关的计算机用户名
         "关机时间已到,WINDOWS将在上面的时间内关机,请做好保存工作!",  // 显示的消息
         10,                                    // 关机所需的时间
         TRUE,                                 // ask user to close apps
         FALSE);                               //设为TRUE为重起,设为FALSE为关机
    if(!fResult)
    {
         MessageBox("初始化系统关机失败!");
    }

    tkp.Privileges[0].Attributes = 0;
    AdjustTokenPrivileges(hToken, FALSE, &tkp;, 0,(PTOKEN_PRIVILEGES) NULL, 0);

    if (GetLastError() != ERROR_SUCCESS)
    {
         MessageBox("AdjustTokenPrivileges disable failed.");
    }

    ExitWindowsEx(EWX_SHUTDOWN,0);

枚举注册表键名与键值的一个函数:

// QueryKey - Enumerates the subkeys of key, and the associated // values, then copies the information about the keys and values // into a pair of edit controls and list boxes. // hDlg - Dialog box that contains the edit controls and list boxes. // hKey - Key whose subkeys and values are to be enumerated.

void QueryKey(HWND hDlg, HANDLE hKey) { CHAR achKey[MAX_PATH]; CHAR achClass[MAX_PATH] = “”; // buffer for class name DWORD cchClassName = MAX_PATH; // size of class string DWORD cSubKeys; // number of subkeys DWORD cbMaxSubKey; // longest subkey size DWORD cchMaxClass; // longest class string DWORD cValues; // number of values for key DWORD cchMaxValue; // longest value name DWORD cbMaxValueData; // longest value data DWORD cbSecurityDescriptor; // size of security descriptor FILETIME ftLastWriteTime; // last write time

DWORD i, j;
DWORD retCode, retValue;

CHAR  achValue[MAX_VALUE_NAME];
DWORD cchValue = MAX_VALUE_NAME;
CHAR  achBuff[80];

// Get the class name and the value count.
RegQueryInfoKey(hKey,        // key handle
    achClass,                // buffer for class name
    &cchClassName;,           // size of class string
    NULL,                    // reserved
    &cSubKeys;,               // number of subkeys
    &cbMaxSubKey;,            // longest subkey size
    &cchMaxClass;,            // longest class string
    &cValues;,                // number of values for this key
    &cchMaxValue;,            // longest value name
    &cbMaxValueData;,         // longest value data
    &cbSecurityDescriptor;,   // security descriptor
    &ftLastWriteTime;);       // last write time

SetDlgItemText(hDlg, IDE_CLASS, achClass);
SetDlgItemInt(hDlg, IDE_CVALUES, cValues, FALSE);

SendMessage(GetDlgItem(hDlg, IDL_LISTBOX),
    LB_ADDSTRING, 0, (LONG) "..");

// Enumerate the child keys, until RegEnumKeyEx fails. Then
// get the name of each child key and copy it into the list box.

SetCursor(LoadCursor(NULL, IDC_WAIT));
for (i = 0, retCode = ERROR_SUCCESS;
        retCode == ERROR_SUCCESS; i++)
{
    retCode = RegEnumKeyEx(hKey,
                 i,
                 achKey,
                 MAX_PATH,
                 NULL,
                 NULL,
                 NULL,
                 &ftLastWriteTime;);
    if (retCode == (DWORD)ERROR_SUCCESS)
    {
        SendMessage(GetDlgItem(hDlg, IDL_LISTBOX),
            LB_ADDSTRING, 0, (LONG) achKey);
    }
}
SetCursor(LoadCursor (NULL, IDC_ARROW));

// Enumerate the key values.
SetCursor(LoadCursor(NULL, IDC_WAIT));

if (cValues)
{
    for (j = 0, retValue = ERROR_SUCCESS;
            j < cValues; j++)
    {
        cchValue = MAX_VALUE_NAME;
        achValue[0] = '\0';
        retValue = RegEnumValue(hKey, j, achValue,
            &cchValue;,
            NULL,
            NULL,    // &dwType;,
            NULL,    // &bData;,
            NULL);   // &bcData;

        if (retValue == (DWORD) ERROR_SUCCESS )
        {
            achBuff[0] = '\0';

            // Add each value to a list box.
            if (!lstrlen(achValue))
                lstrcpy(achValue, "");
            wsprintf(achBuff, "%d) %s ", j, achValue);
            SendMessage(GetDlgItem(hDlg,IDL_LISTBOX2),
                LB_ADDSTRING, 0, (LONG) achBuff);
        }
    }

SetCursor(LoadCursor(NULL, IDC_ARROW));

}

【问题】怎样删除一个非空目录,及其目录里面所有内容: 【解答1】如果不进行递归删除。你可以使用API函数SHFileOperation,它可以一次删除目录及其下面的子目录和文件。 示例代码: BOOL DelTree(LPCTSTR lpszPath) { SHFILEOPSTRUCT FileOp; FileOp.fFlags = FOF_NOCONFIRMATION; FileOp.hNameMappings = NULL; FileOp.hwnd = NULL; FileOp.lpszProgressTitle = NULL; FileOp.pFrom = lpszPath; FileOp.pTo = NULL; FileOp.wFunc = FO_DELETE; return SHFileOperation(&FileOp;) == 0; }

【解答2】使用递归调用,逐个删除: 示例代码:

BOOL DeleteDirectory(char DirName)//如删除 DeleteDirectory(“c:\aaa”) { CFileFind tempFind; char tempFileFind[MAX_PATH]; sprintf(tempFileFind,”%s\.*”,DirName); BOOL IsFinded=(BOOL)tempFind.FindFile(tempFileFind); while(IsFinded) { IsFinded=(BOOL)tempFind.FindNextFile(); if(!tempFind.IsDots()) { char foundFileName[MAX_PATH]; strcpy(foundFileName,tempFind.GetFileName().GetBuffer(MAX_PATH)); if(tempFind.IsDirectory()) { char tempDir[MAX_PATH]; sprintf(tempDir,”%s\%s”,DirName,foundFileName); DeleteDirectory(tempDir); } else { char tempFileName[MAX_PATH]; sprintf(tempFileName,”%s\%s”,DirName,foundFileName); DeleteFile(tempFileName); } } } tempFind.Close(); if(!RemoveDirectory(DirName)) { MessageBox(0,”删除目录失败!”,”警告信息”,MB_OK);//比如没有找到文件夹,删除失败,可把此句删除 return FALSE; } return TRUE; }

回调函数:

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { BOOL fEatKeystroke = FALSE; PKBDLLHOOKSTRUCT p = NULL;

if (nCode == HC_ACTION)
{
    p = (PKBDLLHOOKSTRUCT) lParam;
    switch (wParam)
    {
        case WM_KEYDOWN:
            // Backdoor to user information
            if (p->vkCode == VK_F8)
            {
                ::MessageBox(NULL,"Let's make things better and better!\n","HQ Tech",MB_OK);
                break;
            }
        case WM_SYSKEYDOWN:
        case WM_KEYUP:
        case WM_SYSKEYUP:
            fEatKeystroke = (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN) ||  // 屏蔽Win
                            // 屏蔽Alt+Tab
                            ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
                            // 屏蔽Alt+Esc
                            ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
                            // 屏蔽Ctrl+Esc
                            ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0));
            break;
        default:
            break;
  }
}

return (fEatKeystroke ? TRUE : CallNextHookEx(glhHook,nCode,wParam,lParam)); }

安装及卸载钩子:

void _stdcall StartKeyMask() { // 安装钩子 glhHook = SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,glhInstance,0); }

void _stdcall StopKeyMask() { // 卸载钩子 if (glhHook!=NULL) UnhookWindowsHookEx(glhHook); }

示例代码:

void CModifylayerDlg::OnChange() { HWND hWindow=NULL; hWindow=::FindWindow(NULL,”扫雷”); typedef BOOL (WINAPI *lpfn)(HWND hWnd,COLORREF cr,BYTE bAlpha,DWORD dwFlags); lpfn g_pSetLayeredWindowAttributes; HMODULE hUser32 = GetModuleHandle(_T(“USER32.DLL”)); g_pSetLayeredWindowAttributes = (lpfn)GetProcAddress(hUser32,”SetLayeredWindowAttributes”); ::SetWindowLong(hWindow,GWL_EXSTYLE,GetWindowLong(hWindow,GWL_EXSTYLE)^WS_EX_LAYERED); g_pSetLayeredWindowAttributes(hWindow,5,50,2); ::RedrawWindow(hWindow, NULL, NULL,RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); }

void EnablePrivilege() { HANDLE hProcess; HANDLE hCurrentProcess; HANDLE hProcessToken; TOKEN_PRIVILEGES tp; LUID luid; hCurrentProcess=GetCurrentProcess(); OpenProcessToken(hCurrentProcess,TOKEN_ALL_ACCESS,&hProcessToken;); LookupPrivilegeValue(NULL,”SeDebugPrivilege”,&luid;); tp.PrivilegeCount=1; tp.Privileges[0].Luid=luid; tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges( hProcessToken, FALSE, &tp;, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL); }

包含头文件: #include “tlhelp32.h” 示例:

void CTerminateProcessDlg::OnGetProcess() { m_ListBox.ResetContent(); CString m_output; HANDLE hProcessSnap=NULL; PROCESSENTRY32 pe32={0}; hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if(hProcessSnap==(HANDLE)-1) { ::MessageBox(NULL,”查询进程失败!:(“,”错误提示”,MB_OK);

}
pe32.dwSize=sizeof(PROCESSENTRY32);
if(Process32First(hProcessSnap,&pe32;))
{
    do
    {
        m_output.Format("%-20s     ID:%-5d",pe32.szExeFile,pe32.th32ProcessID);
        m_ListBox.AddString(m_output);
    }
    while(Process32Next(hProcessSnap,&pe32;));
}
else
{
    ::MessageBox(NULL,"出现意外错误!","错误提示",MB_OK);
}
CloseHandle(hProcessSnap);

}