GetCurrentProcess得到得到的称之为"伪句柄"
只是一个标识,你可以发现,其实就是返回$FFFFFFFF,
每个进程得句柄都是一样得,只是实用于进程内部得使用.
如果你想得到实际得句柄,在进程间进行通讯,必需要进行转化,
调用DuplicateHandle,注意,得实句柄使用完成以后,你必须要调用CloseHandle去关闭.
其实,你应该明白了为何"伪句柄"得存在,就是使用简单,不用关闭,
不会造成内存泄漏.

同样道理,GetCurrentThread也是伪句柄,其值永远是$FFFFFFFE,只是适用于线程内部得使用.

DuplicateHandle() :

在系统中,对象分两类:核心对象和用户对象.如进程对象,线程对象,文件映射 
对象等就是核心对象;而向窗口,菜单等都是用户对象. 
两者是有差别的,用于标示用户对象的句柄是系统唯一的,也就是说,一个进程 
完全可以对另外一个进程中的用户对象进行操作,比如两个进程间通信的方法之一, 
就是发送消息.正是由于窗口是用户对象,所以句柄是系统唯一,通过FindWindow(), 
得到另外一个进程的窗口句柄,然后用SendMessage(),让hWnd的窗口过程来处理消 
息,实现了进程间的通信.因此,对于用户对象,你根本不用DuplicateHandle(),直接 
把句柄拿来用就行了. 
而核心对象则不一样.核心对象是为了加强系统的稳定性,因此,核心对象句柄是 
进程相关的,在每一个进程中都有一个核心对象表,每一个对象的索引(不完全是)作为内和对象的句柄,从而实现进程相关.同一个对象在不同的进程中可能有不 同的索引,即句柄.对核心对象进行操作时,系统还要进行安全检验,看一下你是否有权来操作这个对象.因此你不能同用户对象一样,直接把句柄拿过来用.比方 说,你想操作另一个进程中的文件映射对象,这个文件映射对象句柄在那个进程中假设是0x000001,但在你的进程中,很有可能0x00000001时表 示另一个核心对象,此时的操作就永远不会成功,甚至会产生灾难性的后果.此时,就有必要用DuplicateHandle().

-----------------------------------------------------------------------------------------------------------------

用DublicateHandle实现文件站坑:

#include <windows.h>

BOOL OccupyFile( LPCTSTR lpFileName );

int main()
{
OccupyFile("c:\\aaa111.txt");

return 0;
}

void RaiseToDebugP()
{
HANDLE hToken;
HANDLE hProcess = GetCurrentProcess();
if ( OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) )
{
TOKEN_PRIVILEGES tkp;
if ( LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid) )
{
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

BOOL bREt = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0) ;
}
CloseHandle(hToken);
}    
}

BOOL OccupyFile( LPCTSTR lpFileName )
{
BOOL    bRet;

RaiseToDebugP();

HANDLE hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, 4);    // 4为system进程号

if ( hProcess == NULL )
{
hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, 8);        // 2K下是 8??

if ( hProcess == NULL )
return FALSE;
}

HANDLE hFile;
HANDLE hTargetHandle;

hFile = CreateFile( lpFileName, GENERIC_READ, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);

if ( hFile == INVALID_HANDLE_VALUE )
{
CloseHandle( hProcess );
return FALSE;
}

bRet = DuplicateHandle( GetCurrentProcess(), hFile, hProcess, &hTargetHandle, 
0, FALSE, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE);

CloseHandle( hProcess );

return bRet;
}

 
The DuplicateHandle function duplicates an object handle. The duplicate handle refers to the same object as the original handle.Therefore, any changes to the object are reflected through both handles.For example, the current file mark for a file handle is always the same for both handles.
BOOL DuplicateHandle(HANDLE hSourceProcessHandle,  // handle to source processHANDLE hSourceHandle,         // handle to duplicateHANDLE hTargetProcessHandle,  // handle to target processLPHANDLE lpTargetHandle,      // duplicate handleDWORD dwDesiredAccess,        // requested accessBOOL bInheritHandle,          // handle inheritance optionDWORD dwOptions               // optional actions
);
hTargetProcessHandlehSourceHandle,是任意类型的内核对象句柄,而且这个句柄和调用duplicatehandle的进程无关

Handle to the process that is to receive the duplicated handle. The handle must have PROCESS_DUP_HANDLE access.

==============

其实就是把该文件的句柄(真正的句柄)复制给了system进程。

==============

函数比较:

GetCurrentProcess():

GetCurrentProcess得到得到的称之为"伪句柄"
只是一个标识,你可以发现,其实就是返回$FFFFFFFF,
每个进程得句柄都是一样得,只是实用于进程内部得使用.
如果你想得到实际得句柄,在进程间进行通讯,必需要进行转化,
调用DuplicateHandle,注意,得实句柄使用完成以后,你必须要调用CloseHandle去关闭.
其实,你应该明白了为何"伪句柄"得存在,就是使用简单,不用关闭,
不会造成内存泄漏.

同样道理,GetCurrentThread也是伪句柄,其值永远是$FFFFFFFE,只是适用于线程内部得使用.

DuplicateHandle() :

在系统中,对象分两类:核心对象和用户对象.如进程对象,线程对象,文件映射 
对象等就是核心对象;而向窗口,菜单等都是用户对象. 
两者是有差别的,用于标示用户对象的句柄是系统唯一的,也就是说,一个进程 
完全可以对另外一个进程中的用户对象进行操作,比如两个进程间通信的方法之一, 
就是发送消息.正是由于窗口是用户对象,所以句柄是系统唯一,通过FindWindow(), 
得到另外一个进程的窗口句柄,然后用SendMessage(),让hWnd的窗口过程来处理消 
息,实现了进程间的通信.因此,对于用户对象,你根本不用DuplicateHandle(),直接 
把句柄拿来用就行了. 
而核心对象则不一样.核心对象是为了加强系统的稳定性,因此,核心对象句柄是 
进程相关的,在每一个进程中都有一个核心对象表,每一个对象的索引(不完全是)作为内和对象的句柄,从而实现进程相关.同一个对象在不同的进程中可能有不 同的索引,即句柄.对核心对象进行操作时,系统还要进行安全检验,看一下你是否有权来操作这个对象.因此你不能同用户对象一样,直接把句柄拿过来用.比方 说,你想操作另一个进程中的文件映射对象,这个文件映射对象句柄在那个进程中假设是0x000001,但在你的进程中,很有可能0x00000001时表 示另一个核心对象,此时的操作就永远不会成功,甚至会产生灾难性的后果.此时,就有必要用DuplicateHandle().

===========================================

The state of a mutex object is signaled when it is not owned by any thread. The creating thread can use the bInitialOwner flag to request immediate ownership of the mutex. Otherwise, a thread must use one of the wait functions to request ownership. When the mutex's state is signaled, one waiting thread is granted ownership, the mutex's state changes to nonsignaled, and the wait function returns. Only one thread can own a mutex at any given time. The owning thread uses the ReleaseMutex function to release its ownership.

对比一下开源程序的代码

(题外话:

普通的主线程建立子线程的时候通常都是在子线程变为有信号该函数才返回,也就是说在子线程结束运行后就是signaled的了

如下面的代码:

int main(int argc, char* argv[])
{
HANDLE hThread;
DWORD dwThreadId;

// 创建一个线程
hThread = ::CreateThread (
NULL,   // 默认安全属性
NULL,   // 默认堆栈大小
ThreadProc, // 线程入口地址(执行线程的函数)
NULL,   // 传给函数的参数
0,   // 指定线程立即运行
&dwThreadId); // 返回线程的ID号
printf(" Now another thread has been created. ID = %d \n", dwThreadId);

// 等待新线程运行结束
::WaitForSingleObject (hThread, INFINITE);
::CloseHandle (hThread);
return 0;
}

)

///

这是一个开源的软件中的利用互斥对象判断是否运行有另一个本程序的拷贝的方法。。。

bool MyApp::OnInit()
{
// Check if program is already run

HANDLE hMutex;

// Create a mutex with no initial owner.

hMutex = CreateMutex( 
NULL,                       // no security attributes
FALSE,                      // initially not owned
"MutexToProtectDatabase"); // name of mutex

if (hMutex == NULL) 
return false;

/************************************微软已经说得很清楚了,Otherwise, a thread must use one of the wait functions to request ownership. 建立一个内核对象,程序运行结束的时候,不管是自己在程序的最后调用closehandle函数或是由windows替你去做这一切,都会释放内核对象。 因此当你的程序没有运行结束的时候,这一个内核对象是不会被释放的。因此,对象就一直处于无信号的状态。也就说明了这一个程序已经有一个拷贝在运行了

也可以这么说,只有当你的程序运行结束并释放内核对象后,这个你自己命名的内核对象才会消失,这时如果程序再次重新运行,由于该内核对象并没有被初始化,因次下面的代码的判断语句也就不会执行了,因次return语句得不到执行,程序也就不会exit了。
*****************************/
if (WaitForSingleObject(hMutex,0)==WAIT_TIMEOUT)
{
wxMessageBox("Only one copy of allowed!", “", wxOK | wxICON_INFORMATION);
return false;
}

再者由于内核对象是被内核所拥有的,因次内核对象的生存时间(姑且这么说)一般来说都会比程序长一些。

而我们正是利用了内核对象独立与程序的这一点来判断是否已经有一个程序运行。绝对可以说是高明。

说到这里,到底内核对象是什么呢?<programming application >l里面有:

http://hi.baidu.com/wpclub/blog/item/4112ad3f482c5fc67c1e713c.html

WaitForSingleObject

If the function succeeds, the return value indicates the event that caused the function to return. This value can be one of the following.

Value Meaning
WAIT_ABANDONED The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled.
WAIT_OBJECT_0 The state of the specified object is signaled.
WAIT_TIMEOUT The time-out interval elapsed, and the object's state is nonsignaled.

///

nosignaled表示正在被使用中

又在网上找到的另一个程序:

#include <Windows.h>

int
WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd
)
{
char strAppName[] = "OnlyOne";
HANDLE hMutex = NULL;

 //创建互斥对象
hMutex = CreateMutex(NULL, FALSE, strAppName);
if (hMutex != NULL)
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
MessageBox(NULL,TEXT("不是第一次运行这个程序。"),TEXT("OnlyOne"),MB_OK | MB_ICONINFORMATION);
//关闭互斥对象,退出程序
CloseHandle(hMutex);
return (-1);
} else
{
MessageBox(NULL,TEXT("第一次运行这个程序。"),TEXT("OnlyOne"),MB_OK | MB_ICONINFORMATION);
}
} else
{
MessageBox(NULL,TEXT("创建互斥对象失败。"),TEXT("OnlyOne"),MB_OK | MB_ICONINFORMATION);
}
//关闭互斥对象
CloseHandle(hMutex);
return (-1);

======================================

Example Code [C++]

The following example creates a mutex, duplicates a handle to the mutex, and passes it to another thread. Duplicating the handle ensures that the reference count is increased so that the mutex object will not be destroyed until both threads have closed the handle.
#include <windows.h>

DWORD CALLBACK ThreadProc(PVOID pvParam);

int main()
{
HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
HANDLE hMutexDup, hThread;
DWORD dwThreadId;

DuplicateHandle(GetCurrentProcess(), 
hMutex, 
GetCurrentProcess(),
&hMutexDup, 
0,
FALSE,
DUPLICATE_SAME_ACCESS);

hThread = CreateThread(NULL, 0, ThreadProc, 
(LPVOID) hMutexDup, 0, &dwThreadId);

// Perform work here, closing the handle when finished with the
// mutex. If the reference count is zero, the object is destroyed.
CloseHandle(hMutex);

// Wait for the worker thread to terminate and clean up.
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}

DWORD CALLBACK ThreadProc(PVOID pvParam)
{
HANDLE hMutex = (HANDLE)pvParam;

// Perform work here, closing the handle when finished with the
// mutex. If the reference count is zero, the object is destroyed.
CloseHandle(hMutex);
return 0;
}

------------------------------------------------------------------

先来了解一下 DuplicateHandle函数的作用

BOOL DuplicateHandle(
HANDLE hSourceProcessHandle, // handle to the source process
HANDLE hSourceHandle,         // handle to duplicate
HANDLE hTargetProcessHandle, // handle to process to duplicate to
LPHANDLE lpTargetHandle, // pointer to duplicate handle
DWORD dwDesiredAccess,    // access for duplicate handle
BOOL bInheritHandle,      // handle inheritance flag
DWORD dwOptions           // optional actions
)

说明 在指出一个现有系统对象当前句柄的情况下,为那个对象创建一个新句柄。当前句柄可能位于一个不同的进程

如果我们打开想要保护文件,并且不关闭文件句柄,这样文件就无法删除。
那要怎样保证句柄不被关闭呢?当进程退出的时候,即使不关闭句柄,windows系统也会帮你做清理工作,关闭句柄。这时我们可以利用win32 API DuplicateHandle来复制文件句柄到其他进程中,这样即使我们的进程结束了,文件句柄依然还没关闭。文件占坑保护就是利用这个事实来达到保护文件的目的。其他进程我们选哪个呢?csrss.exe system.exe winlogon.exe都可以。

代码如下:

BOOL ProtectFile(
IN LPCTSTR pszFilePath,
IN DWORD dwProcessId,
IN BOOL bFileCanBeRead
)
{
HANDLE hFile;
HANDLE hProcess;

// get the file handle

hFile = CreateFile(
pszFilePath, 
GENERIC_READ, 
(bFileCanBeRead ? FILE_SHARE_READ : 0), 
NULL, 
OPEN_EXISTING, 
FILE_ATTRIBUTE_NORMAL, 
NULL
);
if (hFile == INVALID_HANDLE_VALUE) 
{
return FALSE;
}

// open the process handle

hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
if (!hProcess) 
{
CloseHandle(hFile);
return FALSE;
}

// call duplicatehandle

BOOL fOk = DuplicateHandle(
GetCurrentProcess(),              // source process handle
hFile,                                     // source handle
hProcess,                              // target process handle
NULL,                                    // target handle, we don't care it
0,
FALSE,                                   
DUPLICATE_SAME_ACCESS
);

CloseHandle(hFile);
CloseHandle(hProcess);
return fOk;
}

上一篇>>  魔兽显血改建工具的制作及源码    下一篇>>  【转】强制删除正在运行的文件
类别:默认分类 |  | 添加到搜藏 | 分享到i 贴吧 | 浏览(1075) | 评论 (1)
网友评论
  • 回复1乱红喵喵2010-05-19 17:59
    打酱油的孩子喵过
 
发表评论
内 容:

DuplicateHandle GetCurrentProcess 实句柄 伪句柄相关推荐

  1. GetCurrentProcess 伪句柄

    0.思考 1.相关api GetCurrentProcess GetCurrentThread GetCurrentProcessId OpenProcess DuplicateHandle Clos ...

  2. DuplicateHandle 伪句柄 与 实句柄的应用

    如果把GetCurrentThread()返回值传递给一个HANDLE句柄,用它进行ResumeThread,结果肯定不是我们想要的.下面的例子详细描述了伪句柄的调用结果: #include &quo ...

  3. DuplicateHandle伪句柄与实句柄的应用二

    //扫描进程列表,获得进程名为 ConsoleApplication2.exe的进程句柄B,把当前进程A的伪 //句柄传递给B,在B进程中关闭它 #include "stdafx.h&quo ...

  4. R3下,遍历所有进程的伪句柄表,关闭指定句柄

    之所以产生这个想法,是在删除文件的时候有时会提示文件被占用了,然后让我们先关闭之后在来删除,但是我怎么知道哪个进程打开了我的文件? 于是就去网上了找了一份代码然后改了改,接着来说说是怎么实现功能的.首 ...

  5. 句柄和句柄类是不同!

    因为看到C++ Primer 上面有定义句柄类,概念不清晰,百度了一下"句柄",发现这方面的东西非常乱.纠结了半天,还搞烦躁了前辈. 后来发现句柄和句柄类是两个概念,句柄是wind ...

  6. 关于DuplicateHandle() 转换伪句柄成真实句柄值的疑问

    参考:http://topic.csdn.net/u/20100806/09/f89294ac-fcf7-4a05-bb00-8480c3793ecb.html

  7. oracle中句柄,释放句柄 – 提供7*24专业数据库(Oracle,SQL Server,MySQL等)恢复和Oracle技术服务@Tel:+86 13429648788 - 惜分飞...

    在很多时候,检查系统时候发现,由于某个Oracle的trace文件导致磁盘空间告警,因为业务需要不能让数据库down下来.这个时候你想到的方法可能是直接删除掉这个trace文件,如果是win系统,那恭 ...

  8. linux 句柄类型,句柄问题分析

    什么是句柄 句柄就是一个对象的标识符,只要获得对象的句柄,我们就可以对对象进行任意的操作,包括窗口,按钮,图标,输出设备,控件或者文件等: 句柄是一种特殊的智能指针,用一个唯一的整数值标识一个对象(即 ...

  9. python操作句柄_python句柄部分操作

    # 通过窗口类名.窗口标题获取控件句柄 hwnd = win32gui.FindWindow("ClassName", "TitleName") # 通过句柄设 ...

最新文章

  1. “一网打尽”Deepfake等换脸图像,微软提出升级版鉴别技术Face X-Ray​
  2. android扩散波动动画,使用WebGL制作图片的像素脉冲波(粒子化扩散波动)动画特效...
  3. Linux RHCS中心跳网络接口的指定
  4. asp.net返回值当文件下载问题
  5. python sklearn 梯度下降法_科学网—Python_机器学习_总结4:随机梯度下降算法 - 李军的博文...
  6. delphi 异步 调用 带参数_如何在 Spring 异步调用中传递上下文
  7. SAP HANA SQL获取当前日期
  8. 中国水系Android第一个版本
  9. 安卓短信转发qq邮箱
  10. C1驾考成都胜利考场科目二经验
  11. c语言怎么判断一个目录下面的文件是否为隐藏文件,怎么能显示出隐藏文件?...
  12. 如何根据快递单号物流信息自动识别快递状态
  13. iPhone通过CPU确定手机型号
  14. pythonn说句心里话_《说句心里话》笑力满格 “战神”常远颠覆自我
  15. Just Waiting for You!个性化推荐带你领略不一样的算法之美
  16. Spool Print Fool(CVE-2022-21999 )提权漏洞
  17. 【shaderforge学习笔记】 Specular(高光)通道
  18. RF无线射频电路设计基础
  19. Android productFlavors多环境配置
  20. 洛谷 P3380 bzoj3196 Tyvj1730 【模板】二逼平衡树(树套树)

热门文章

  1. thinkphp monolog日志写入失败问题解决
  2. [存储引擎] MySQL的存储引擎介绍
  3. 华为云计算之物理节点CNA安装教程
  4. CAS认证及代理访问举例
  5. 我们拜的“财神”到底是谁?
  6. bootstrap制作导航条案例
  7. 不同局域网共享打印机
  8. MyBatis注解实现like模糊查询
  9. SIFT特征提取实现地理位置的标注
  10. 读《包法利夫人》有感