Solved

How do I know who is locking the file in my C++ codes ?

Posted on 2013-12-28
6
1,162 Views
Last Modified: 2013-12-29
Hello Experts,

I'm looking for C++ sample code to determine WHO IS LOCKING THE FILE ?
I want to know the process ID of locking specific file.
I know that Process Explorer can do that.
I want to do it in my C++ program.

I guess OpenProcess() and DuplicateHandle() are the key, but I don't know how to implement.

Windows 7 32bit

Please advice
Nobuo Miwa
0
Comment
Question by:NobMiwa
  • 3
  • 2
6 Comments
 
LVL 13

Expert Comment

by:AielloJ
ID: 39743622
NobMiwa,

I don't believe it's possible since file handle information is stored in kernel space.  There are function calls that will tell you the name of the application that has the file open ( IFileIsInUse::GetAppName() ) but not the user.  Even then, the other application opening the file would have to have been written to be cooperative.

Best regards,

AielloJ
0
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 39743966
>> I guess OpenProcess() and DuplicateHandle() are the key, but I don't know how to
>> implement.

They're not really the key. You will need to use Windows' Native API (http://netcode.cz/img/83/nativeapi.html) , in particular get a copy of the global handle table by calling 'ZwQuerySystemInformation(SystemHandleInformation,...);' and checking the referenced handles /PIDs. The following code does this, the the structure definitions were taken from Gary Nebbett' book "Native API Reference" (which also contains samples from which this snippet is derived). All you need to do is compiling this and link with ntdll.lib, which comes with the DDK. Alternatively, you could load the Zw* functions dynamically.

#define UNICODE
#define _UNICODE
#include <tchar.h>
#include <stdio.h>

#pragma warning ( disable: 4768)
#include <map>

typedef enum _SYSTEM_INFORMATION_CLASS
{
    SystemHandleInformation = 16,

} SYSTEM_INFORMATION_CLASS;

typedef	struct	_SYSTEM_HANDLE_INFORMATION
{
    ULONG		ProcessId;
    UCHAR		ObjectTypeNumber;
    UCHAR		Flags;
    USHORT		Handle;
    PVOID		Object;
    ACCESS_MASK	GrantedAccess;

}	SYSTEM_HANDLE_INFORMATION,	*PSYSTEM_HANDLE_INFORMATION;

typedef enum _OBJECT_INFORMATION_CLASS
{
    ObjectBasicInformation,
    ObjectNameInformation,
    ObjectTypeInformation,
    ObjectAllTypesInformation,
    ObjectHandleInformation
}	OBJECT_INFORMATION_CLASS;

typedef struct	_OBJECT_BASIC_INFORMATION
{
    ULONG			Attributes;
    ACCESS_MASK		GrantedAccess;
    ULONG			HandleCount;
    ULONG			PointerCount;
    ULONG			PagedPoolUsage;
    ULONG			NonPagedPoolUsage;
    ULONG			Reserved	[	3];
    ULONG			NameInformationLength;
    ULONG			TypeInformationLength;
    ULONG			SecurityDescriptorLength;
    LARGE_INTEGER	CreateTime;

}	OBJECT_BASIC_INFORMATION,	*POBJECT_BASIC_INFORMATION;	

typedef	struct	_OBJECT_TYPE_INFORMATION
{
    UNICODE_STRING	Name;
    ULONG			ObjectCount;
    ULONG			HandleCount;
    ULONG			Reserved1	[	4];
    ULONG			PeakObjectCount;
    ULONG			PeakHandleCount;
    ULONG			Reserved2	[	4];
    ULONG			InvalidAttributes;
    GENERIC_MAPPING	GenericMapping;
    ULONG			ValidAccess;
    UCHAR			Unknown;
    BOOLEAN			MaintainHandleDatabase;
    NT::POOL_TYPE	PoolType;
    ULONG			PagedPoolUsage;
    ULONG			NonPagedPoolUsage;

}	OBJECT_TYPE_INFORMATION,	*POBJECT_TYPE_INFORMATION;

typedef	struct	_OBJECT_NAME_INFORMATION
{
    UNICODE_STRING	Name;
}	OBJECT_NAME_INFORMATION,	*POBJECT_NAME_INFORMATION;


typedef std::map<ULONG, ULONG> pid_map;


extern "C"
NTSTATUS
__stdcall
ZwQuerySystemInformation	(	SYSTEM_INFORMATION_CLASS,
                                PVOID,
                                ULONG,
                                PULONG
                            );

extern "C"
NTSTATUS
__stdcall
ZwQueryObject				(	HANDLE,
                                OBJECT_INFORMATION_CLASS,
                                PVOID,
                                ULONG,
                                PULONG
                            );

extern "C"
NTSTATUS
__stdcall
ZwDuplicateObject			(	HANDLE,
                                HANDLE,
                                HANDLE,
                                PHANDLE,
                                ACCESS_MASK,
                                ULONG,
                                ULONG
                            );

POBJECT_NAME_INFORMATION	
GetObjectNameInformation	(	HANDLE	__hObject, wchar_t* __pwszTypeFilter)
{
    NTSTATUS					_ntStatus;
    OBJECT_BASIC_INFORMATION	_obi;
    POBJECT_TYPE_INFORMATION	_poti;
    POBJECT_NAME_INFORMATION	_poni;
    ULONG						_ul;
    
    ZwQueryObject	(	__hObject,
                        ObjectBasicInformation,
                        &_obi,
                        sizeof	(	_obi),
                        &_ul
                    );

    _ul	=		_obi.TypeInformationLength	+	2;

    _poti	=	( POBJECT_TYPE_INFORMATION)	new	char	[	_ul];

    _ntStatus	=	ZwQueryObject	(	__hObject,
                                        ObjectTypeInformation,
                                        _poti,
                                        _ul,
                                        &_ul
                                    );

    if	(	__pwszTypeFilter	&&	!wcscmp	(	_poti->Name.Buffer, __pwszTypeFilter))
        {
            delete	[]	_poti;

            return	NULL;
        }

    _ul	=		!_obi.NameInformationLength	
            ?	MAX_PATH * sizeof ( WCHAR)
            :	_obi.NameInformationLength;

    _poni	=	( POBJECT_NAME_INFORMATION)	new	char	[	_ul];

    _ntStatus	=	ZwQueryObject	(	__hObject,
                                        ObjectNameInformation,
                                        _poni,
                                        _ul,
                                        &_ul
                                    );

/*
    wprintf	(	L"Obj 0x%8.8x %.*s %.*s\n",	
                __hObject,
                _poni->Name.Length / 2,
                _poni->Name.Buffer,
                _poti->Name.Length / 2,
                _poti->Name.Buffer
            );
*/

    delete	[]	_poti;

    return	(	_poni);
}

void	PrintObjectUsers	(	wchar_t*	__pwszObj,	wchar_t*	__pwszTypeFilter)
{

    pid_map						_pid_map;
    ULONG						_ulPID;
    NTSTATUS					_ntStatus;

    HANDLE						_hObject;
    HANDLE						_hProcess;

    PSYSTEM_HANDLE_INFORMATION	_pshi;
    POBJECT_NAME_INFORMATION	_poni;

    ULONG						_ul		=	0x1000;
    PULONG						_pul	=	new	ULONG	[	_ul];

//	hProcess	=	OpenProcess	(	PROCESS_DUP_HANDLE,	FALSE,	dwPID);

    while	(	STATUS_INFO_LENGTH_MISMATCH	==	ZwQuerySystemInformation	(	SystemHandleInformation,
                                                                                _pul,
                                                                                _ul	*	sizeof	(	ULONG),
                                                                                0
                                                                            )
            )	delete	[]	_pul,	_pul	=	new	ULONG	[	_ul	*=	2];

    _pshi	=	( PSYSTEM_HANDLE_INFORMATION)	( _pul	+	1);

    for	(	ULONG	_i	=	0;	_i	<	*_pul;	_i++)
        {
            _ulPID		=	_pshi	[	_i].ProcessId;

            _hObject	=	NULL;

            _hProcess	=	OpenProcess	(	PROCESS_DUP_HANDLE,	
                                            FALSE,	
                                            _ulPID
                                        );

            if	(	!_hProcess)
                {
                    //wprintf	(	L"FAILED to 'OpenProcess()' for PID %d\n",	_ulPID);
                    continue;
                }

            ZwDuplicateObject	(	_hProcess,
                                    ( HANDLE)	_pshi	[	_i].Handle,
                                    NtCurrentProcess	(),
                                    &_hObject,
                                    0,
                                    0,
                                    DUPLICATE_SAME_ATTRIBUTES
                                );

            if	(	!_hObject)
                {
                    wprintf	(	L"FAILED to 'ZwDuplicateObject()' for PID %d\n",	_ulPID);
                    continue;
                }

            if	(	_hObject)
                {
                    _poni	=	GetObjectNameInformation	(	_hObject, __pwszTypeFilter);

                    if	(	!_poni)	continue;

                    if	(	!_poni->Name.Length)	continue;

                    if	(	wcsstr	(	_poni->Name.Buffer,	__pwszObj))
                        {
                            pid_map::iterator	_i_map	=	_pid_map.find	(	_ulPID);

//							if	(	_i_map	==	_pid_map.end	())
                                {
                                    wprintf	(	L"PID: %d\tNAME: %s\n",
                                                _ulPID,
                                                _poni->Name.Buffer
                                            );

//									_pid_map.insert	(	pid_map::value_type	(	_ulPID,	_ulPID));
                                }
                        }

                    delete	[]	_poni;

                }

            CloseHandle	(	_hObject);
            CloseHandle	(	_hProcess);

        }

    delete	[]	_pul;
}


int	wmain	(	int			__wargc,
                wchar_t**	__wargv
            )
{
    wchar_t*	__pwc;


    if	(	2	!=	__wargc)
            return	(	-1);

    PrintObjectUsers	(	*( __wargv	+	1),	NULL);

    return	(	0);

}

Open in new window


BTW, that also was a subject in http://www.experts-exchange.com/Programming/Languages/CPP/Q_21310246.html
0
 

Author Comment

by:NobMiwa
ID: 39744372
Hello,

Thank you for the information.

I found the one of solution, it works fine on my C++Builder XE2.
But I don't know that is correct...

	HANDLE hProcess = OpenProcess(
				PROCESS_ALL_ACCESS,
				FALSE,
				pid);
	HANDLE handle;
	for(int t=1;t<1000;t++){
		// Duplicate the handle
		if( ::DuplicateHandle(hProcess,
					 (HANDLE)t,
					 GetCurrentProcess(),
					 &handle,
					 GENERIC_READ,
					 FALSE,
					 0) ) {

			wchar_t  path[1024];
			ZeroMemory(path,sizeof(path));
			DWORD rt = GetFinalPathNameByHandle(handle,
			     path,
			     sizeof(path)-1,
			     FILE_NAME_NORMALIZED);
			if (rt>0) {
			    // fullpath here
			}
		}
	}

Open in new window

0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 86

Expert Comment

by:jkr
ID: 39745281
Might work, to find a file's name but: How do you obtain the PID you are using in the above? That's what my example does ;o)
0
 

Author Comment

by:NobMiwa
ID: 39745550
Hello,

I customize my code that is using NtQuerySystemInformation and it works.
So now I could get correct file handle now.

I got process ID list from followings..

Process32FirstW(hSnap, &pe32);
Process32FirstW(hSnap, &pe32);

Thank you for the hint.

Nobuo Miwa
0
 

Author Closing Comment

by:NobMiwa
ID: 39745551
Thank you !
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now