From:	SMTP%"tvo@software-ag.de" 15-JAN-1998 16:29:54.41
To:	timb%vytalnet.com.jon@brilig.demon.co.uk
CC:	ntdev@atria.com
Subj:	[ntdev] somewhat working sample to enumerate ntfs file streams

Return-Path: owner-ntdev@atria.com
Received: by arisia.gce.com (UCX V4.1-12C, OpenVMS V7.1 VAX);
	Thu, 15 Jan 1998 16:28:06 -0500
Received: from gw.atria.com (gw.atria.com [192.88.237.2]) by mercury.mv.net (8.8.8/mem-971025) with SMTP id KAA17231 for <everhart@arisia.gce.com>; Thu, 15 Jan 1998 10:01:44 -0500 (EST)
Received: by gw.atria.com id <GAA02301@gw.atria.com> Thu, 15 Jan 1998 06:04:23 -0500    
Received: from server1.software-ag.de by gw.atria.com id <GAA02296@gw.atria.com> Thu, 15 Jan 1998 06:04:18 -0500    
Received: from server3.software-ag.de by server1.software-ag.de; (5.65v3.2/1.1.8.2/21Dec95-0433PM)
	id AA10986; Thu, 15 Jan 1998 12:05:17 +0100
Received: from suncool1.software-ag.de by server3.software-ag.de; (5.65v3.2/1.1.8.2/21Dec95-0542PM)
	id AA05970; Thu, 15 Jan 1998 12:05:16 +0100
Received: by suncool1.software-ag.de (SMI-8.6/SMI-SVR4)
	id MAA08866; Thu, 15 Jan 1998 12:03:55 +0100
Date: Thu, 15 Jan 1998 12:03:55 +0100
Message-Id: <199801151103.MAA08866@suncool1.software-ag.de>
From: Thomas Vogler <tvo@software-ag.de>
To: timb%vytalnet.com.jon@brilig.demon.co.uk
Cc: ntdev@atria.com
Subject: [ntdev] somewhat working sample to enumerate ntfs file streams
Reply-To: tvo@software-ag.de
Sender: owner-ntdev@atria.com
Precedence: bulk
X-Majordomo-Taboo: ntdev

hi,

since i found no compiling and working sample on how to enumerate ntfs
streams, i include the code below.

yes, its bad since its using undocumented functionality.

yes, its bad since it does not check for errors.

yes, its bad since there is code stolen from various headers.

if someone improves this program, let me know...

to make it work, just make a visual c++ console application and
include the file below as the onliest source module into it.

--start of file--
#include <windows.h>
#include <stdio.h>

// instead of 
//
// #include <ntddk.h>
//
// i do the few required things by cut and paste from various
// places. i dunno how the above #include can be made to compile using
// visual studio

typedef LONG NTSTATUS;

typedef struct _IO_STATUS_BLOCK {
    NTSTATUS Status;
    ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef enum _FILE_INFORMATION_CLASS {
    FileDirectoryInformation = 1,
    FileFullDirectoryInformation,
    FileBothDirectoryInformation,
    FileBasicInformation,
    FileStandardInformation,
    FileInternalInformation,
    FileEaInformation,
    FileAccessInformation,
    FileNameInformation,
    FileRenameInformation,
    FileLinkInformation,
    FileNamesInformation,
    FileDispositionInformation,
    FilePositionInformation,
    FileFullEaInformation,
    FileModeInformation,
    FileAlignmentInformation,
    FileAllInformation,
    FileAllocationInformation,
    FileEndOfFileInformation,
    FileAlternateNameInformation,
    FileStreamInformation,
    FilePipeInformation,
    FilePipeLocalInformation,
    FilePipeRemoteInformation,
    FileMailslotQueryInformation,
    FileMailslotSetInformation,
    FileCompressionInformation,
    FileCopyOnWriteInformation,
    FileCompletionInformation,
    FileMoveClusterInformation,
    FileOleClassIdInformation,
    FileOleStateBitsInformation,
    FileNetworkOpenInformation,
    FileObjectIdInformation,
    FileOleAllInformation,
    FileOleDirectoryInformation,
    FileContentIndexInformation,
    FileInheritContentIndexInformation,
    FileOleInformation,
    FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;

typedef struct { // from o'Reillys WindowsNT File System Internals Book pg 485
	ULONG NextEntryOffset;
	ULONG StreamNameLength;
	LARGE_INTEGER StreamSize;
	LARGE_INTEGER StreamAllocationSize;
	WCHAR StreamName[1];
} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;

// from ntdef.h

#if !defined(MIDL_PASS)
#define DECLSPEC_IMPORT __declspec(dllimport)
#else
#define DECLSPEC_IMPORT
#endif

#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define NTAPI __stdcall
#else
#define _cdecl
#define NTAPI
#endif

//
// Define API decoration for direct importing system DLL references.
//

#if !defined(_NTSYSTEM_)
#define NTSYSAPI DECLSPEC_IMPORT
#else
#define NTSYSAPI
#endif

extern "C" {

	// from o'Reillys WindowsNT File System Internals Book pg 698

	typedef 
		NTSYSAPI 
		NTSTATUS 
			(NTAPI NtQueryInformationFileFunc) (HANDLE FileHandle,
												PIO_STATUS_BLOCK IoStatusBlock,
												PVOID FileInformation,
												ULONG Length,
												FILE_INFORMATION_CLASS FileInformationClass);

}

static void ListFile(char *pFileName)
{
	static class ListFileContext {

		private:

		HINSTANCE hDll;

		public:

		NtQueryInformationFileFunc *pQIF;

		// are constructors thread safe ???

		ListFileContext()
		{
			//printf ("Construct\n");

			hDll = LoadLibrary ("NTDLL.DLL");
			// check for error...

			pQIF = (NtQueryInformationFileFunc *) GetProcAddress (hDll, "NtQueryInformationFile");
			// check for error...

		}

		~ListFileContext()
		{
			//printf ("Destruct\n");

			FreeLibrary (hDll);
			// check for error...
		}

	} Context;

	IO_STATUS_BLOCK Iosb;
	unsigned char Buffer[2048];
	FILE_INFORMATION_CLASS eClass;
	FILE_STREAM_INFORMATION *pFsi;
	NTSTATUS rc;
	HANDLE hFile;

	// open the file

	hFile = CreateFile( pFileName,     // Filename
						GENERIC_READ,  // Access Mode
						FILE_SHARE_READ | FILE_SHARE_WRITE, // Sharing Mode
						NULL,          // Security Attributes
						OPEN_EXISTING, // Don't create a new file
						0,             // Don't care about attributes
						0 );           // Ignored for OPEN_EXISTING
	// check for error...

	printf ("file name = \"%s\"\n", pFileName);

	// query for its streams

	eClass = FileStreamInformation;

	rc = (Context.pQIF) (hFile,
						 &Iosb,
						 (PVOID) Buffer,
						 sizeof(Buffer),
						 eClass);
	// check for error...
	
	int nStream;

	for (pFsi = (FILE_STREAM_INFORMATION *) Buffer, nStream = 0;
		 1;
		 pFsi = (FILE_STREAM_INFORMATION *) ((BYTE *) pFsi + pFsi->NextEntryOffset), nStream++) {

		printf (" stream %d", nStream);

		printf (", length = 0x");
		if (pFsi->StreamSize.HighPart) {
			printf ("%08x", pFsi->StreamSize.HighPart);
		}
		printf ("%08x", pFsi->StreamSize.LowPart);

		printf (", allocation size = 0x");
		if (pFsi->StreamAllocationSize.HighPart) {
			printf ("%08x", pFsi->StreamAllocationSize.HighPart);
		}
		printf ("%08x", pFsi->StreamAllocationSize.LowPart);

		unsigned int nChar;

		printf (", name = \"");
		for (nChar = 0; nChar < (pFsi->StreamNameLength / sizeof(WCHAR)); nChar++) {
			printf ("%lc", pFsi->StreamName[nChar]);
		}
		printf ("\"\n");

		if (! pFsi->NextEntryOffset) {
			break;
		}

	}

	// Now to close the file handle

	CloseHandle( hFile );
	// check for error...

}

int main(int argc, char *argv[])
{
	int CurrentArgument;
	
	for (CurrentArgument = 1;
		 CurrentArgument < argc;
		 CurrentArgument++) {

		ListFile(argv[CurrentArgument]);

	}

	return 0;
}
--end of file --

-- 
+----------------------------------------------------------------------------+
| T. Vogler, mailto:tvo@software-ag.de, http://pcool/~tvo/                   |
+----------------------------------------------------------------------------+
| Phone: [49]-(6151)-92-0                           FAX: [49]-(6151)-92-???? |
+----------------------------------------------------------------------------+
| long main = 0xc8c70ff0;       /* halt your Pentium the hard way */         |
+----------------------------------------------------------------------------+
| PGP fingerprint: A4 D4 2A 60 B5 48 0F 43  3F EB C5 AC 96 79 A8 D2          |
+----------------------------------------------------------------------------+
| statements in here are my own and not neccesarily those of my employer     |
+----------------------------------------------------------------------------+
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[ To unsubscribe, send email to ntdev-request@atria.com with body
UNSUBSCRIBE (the subject is ignored). ]
