Newsgroup: it.comp.programmare.win32
Titolo: Nt/ZwQuerySystemInformation - enumerare file aperti

hola a todos
sto sviluppando un software di backup che tra le sue varie
funzionalità ti dice, se trova un file aperto mentre esegue il backup,
qual'è il programma che lo sta usando
a primo impatto ho usato il software della 
sysinternals.com
, handle,
che fa esattamente questo, ovvero estrarre l'elenco degli handle legati
ai processi e restituirti le varie informazioni, solo che rallentava
troppo l'esecuzione del mio software, cosi ho deciso di scrivermi il
codice necessario per fare il tutto
dopo varie ricerche ho scoperto l'esistenza della chiamata
NtQuerySystemInformation (e del relativo wrapper
ZwQuerySystemInformation), praticamente non documentata e dopo aver
capito come si usava leggendo varie mezze documentazioni e sorgenti di
Wine/ReactOS sono riuscito a estrarre l'elenco degli handle aperti nel
sistema.
Dopo una giornata di lavoro pensavo di essere riuscito nel mio intento,
ma mi sbagliavo.
Stamattina, dopo aver completato il software implementando la lettura
del nome dell'oggetto e del tipo dell'oggetto ho scoperto che, si
ricevo gli handle aperti nel sistema, ma tra questi non sono presenti i
file aperti!
Cosi sono andato sul forum della sysinternals e li ho trovato un po di
post inerenti all'argomento ed ho visto che usavano +/- lo stesso
sistema che ho usato io ... il problema è che neanche il loro codice
mi dava l'handle dei file aperti!
Ora ... qualcuno ha idea di come fare a risolvere sto problema?
grazie a tutti!
-------
qui c'è un'estratto dei dati stampati a video:
 1320      404  File            firefox.exe       \Device\WS2IFSL
 1320      416  File            firefox.exe       \Device\Afd
 1320      420  File            firefox.exe       \Device\WS2IFSL
 1320      424  File            firefox.exe       \Device\Tcp
 1320      436  File            firefox.exe       \Device\Afd
 1320      440  File            firefox.exe       \Device\Tcp
 1320      444  File            firefox.exe       \Device\Afd
 1320      448  File            firefox.exe       \Device\Tcp
 1320      452  File            firefox.exe       \Device\Tcp
 1320      456  File            firefox.exe       \Device\WS2IFSL
mentre qui c'è un pezzo del codice sorgente:
LPWSTR GetObjectInfo(HANDLE hObject, OBJECT_INFORMATION_CLASS
objInfoClass)
{
	LPWSTR lpwsReturn = NULL;
	DWORD dwSize = sizeof(OBJECT_NAME_INFORMATION);
	POBJECT_NAME_INFORMATION pObjectInfo = (POBJECT_NAME_INFORMATION) new
BYTE[dwSize];
	NTSTATUS ntReturn = pNTQO(hObject, objInfoClass, pObjectInfo, dwSize,
&dwSize);
	if((ntReturn == STATUS_BUFFER_OVERFLOW) || (ntReturn ==
STATUS_INFO_LENGTH_MISMATCH))
	{
		delete pObjectInfo;
		pObjectInfo = (POBJECT_NAME_INFORMATION) new BYTE[dwSize];
		ntReturn = pNTQO(hObject, objInfoClass, pObjectInfo, dwSize,
&dwSize);
	}
	if((ntReturn >= STATUS_SUCCESS) && (pObjectInfo->Buffer != NULL))
	{
		lpwsReturn = (LPWSTR) new BYTE[pObjectInfo->Length + sizeof(WCHAR)];
		ZeroMemory(lpwsReturn, pObjectInfo->Length + sizeof(WCHAR));
		CopyMemory(lpwsReturn, pObjectInfo->Buffer, pObjectInfo->Length);
	}
	delete pObjectInfo;
	return lpwsReturn;
}
int main(int argc, char *argv[])
{
	pNTQO = (tNTQO)GetProcAddress(GetModuleHandle("NTDLL.DLL"),
"ZwQueryObject");
	pNTQSI = (tNTQSI)GetProcAddress(GetModuleHandle("NTDLL.DLL"),
"ZwQuerySystemInformation");
	if (pNTQO == NULL || pNTQSI == NULL)
	{
		printf("Unable to acquire addresses for ZwQueryObject or
ZwQuerySystemInformation!\nThis OS isin't Windows 2000 or Windows
XP!\n\n");
		return -1;
	}
	printf("File Handle List\n");
	printf("================\n\n");
	DWORD dwSize = sizeof(SYSTEM_HANDLE_INFORMATION);
	PSYSTEM_HANDLE_INFORMATION pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)
new BYTE[dwSize];
	NTSTATUS ntReturn = pNTQSI(SystemHandleInformation, pHandleInfo,
dwSize, &dwSize);
	if(ntReturn == STATUS_INFO_LENGTH_MISMATCH)
	{
		delete pHandleInfo;
		pHandleInfo = (PSYSTEM_HANDLE_INFORMATION) new BYTE[dwSize];
		ntReturn = pNTQSI(SystemHandleInformation, pHandleInfo, dwSize,
&dwSize);
	}
	if(ntReturn == STATUS_SUCCESS)
	{
		printf(" Found %d Handles.\n\n", pHandleInfo->uCount);
		printf("  PID\tHandle\t%-16s%-18sHandle Name\n", "Type", "Process
Name");
		for(DWORD dwIdx = 0; dwIdx < pHandleInfo->uCount; dwIdx++)
		{
			HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE |
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
				FALSE, pHandleInfo->Handles[dwIdx].uIdProcess);
			if(hProcess != INVALID_HANDLE_VALUE)
			{
				HANDLE hObject = NULL;
				if(DuplicateHandle(hProcess,
(HANDLE)pHandleInfo->Handles[dwIdx].Handle,
					GetCurrentProcess(), &hObject, STANDARD_RIGHTS_REQUIRED, FALSE, 0)
!= FALSE)
				{
					LPWSTR lpwsName = GetObjectInfo(hObject, ObjectNameInformation);
					LPWSTR lpwsType = GetObjectInfo(hObject, ObjectTypeInformation);
					if (wcscmp(lpwsType, L"File") == 0)
					{
						LPSTR lpszProcess = new CHAR[MAX_PATH];
						ZeroMemory(lpszProcess, MAX_PATH);
						GetModuleFileNameEx(hProcess, NULL, lpszProcess, MAX_PATH);
						printf("%5d\t%6d\t%-16ws%-18s%ws\n",
							pHandleInfo->Handles[dwIdx].uIdProcess,
pHandleInfo->Handles[dwIdx].Handle, lpwsType,
							((lstrlen(lpszProcess) >
0)?PathFindFileName(lpszProcess):"[System]"), lpwsName);
						delete lpszProcess;
					}
					delete lpwsName, lpwsType;
					CloseHandle(hObject);
				}
				CloseHandle(hProcess);
			}
		}
		printf("\n\n");
	}
	else
	{
		printf("Error while trying to allocate memory for System Handle
Information.\n");
	}
	delete pHandleInfo;
	return 0;
}
ri-grazie a tutti!


<snip...>
facendo un po' di ricerche ho trovato questo, parla di file quindi ...
http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827/
la WhoUsesFile() potrebbe essere quella che ti serve se sai le
directory da tenere sotto controllo e usi FindFirstChangeNotification()
e/o altri metodi similari, altrimenti approfondisci
ciao

grazissime
era una settimana e passa che cercavo sull'argomento e avevo trovato
solo quello
ora devo solo capire come funziona e reimplementalro in C#
grazissime di nuovo!

allora
sono riuscito a fare quello che dovevo fare usando questo sistema.
Non mi interessava più di tanto ricevere le notifiche perché posso
ciclarmi la tabella dei file usato, aggiornandola, ogni quando mi
serve, dato che durante il processo di backup il numero dei file
bloccati è decisamente ridotto, e comunque ad estrarre i dati ci sta
un'instante quindi non mi causa più sconvolgimenti di tanto
domattina, appena torno in ufficio, ricommento e posto il codice, dato
che è molto semplice e potrebbe servire a qualcuno: partendo da la si
può implementare tutto quello che si vuole dato che l'unica cosa che
fa è elencare handle processo, handle file e percorso file
non so come ringraziarti perché ero ormai arrivato ad un punto morto
perché cercavo solo in quella direzione e non avendo a disposizione il
DDK andavo pure sufficentemente alla cieca!
grazie!
ciao