/*++

	Program Description:

        prints out rptag info..

	Modification History:

		09/29/97        anandn          created
        modified from rptag_stress.c code..

--*/


#include "rpget.h"


THREAD CHAR gszLogMsg[LINE_LENGTH];	// log message string, local to thread

USHORT gMaxDataBuffSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE -
			FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer);


//
// main
//
 
VOID __cdecl main(INT argc, CHAR* argv[]) {

	BOOL fSuccess;

	OPTIONS Options;	// command line options
	

	PBYTE pOutBuff = NULL;

	PUCHAR pDataBuff;
	USHORT usDataBuffSize;

    if (argc<2) {
        printf("Usage: %s filename\n",argv[0]);
        ExitProcess(1);
    }
    
	fSuccess = RPGet( argv[1], &pOutBuff );

	if ( ! fSuccess ) {
        printf("ERROR: RPGet failed\n");
        ExitProcess(1);
    }

	//
	// print out rp buffer
	//

    printf("\n");
    printf("ReparseTag = %Xh\n",  
        (((PREPARSE_DATA_BUFFER) pOutBuff)->ReparseTag));

    printf("ReparseDataLength = %d\n", 
        ((PREPARSE_DATA_BUFFER) pOutBuff)->ReparseDataLength);

    printf("Reserved = %d\n", 
        ((PREPARSE_DATA_BUFFER) pOutBuff)->Reserved);

    printf("Dumping GenericReparseBuffer:\n");

    DumpBuff((PBYTE) (((PREPARSE_DATA_BUFFER) pOutBuff)->GenericReparseBuffer.DataBuffer), 
        (WORD) ((PREPARSE_DATA_BUFFER) pOutBuff)->ReparseDataLength);

}




BOOL
RPGet( CHAR szFileName[], BYTE **ppOutBuff) 
{

	BOOL fSuccess;
	DWORD dwRc = 0;
	DWORD gle;
	DWORD dwOutBuffLen;

	HANDLE hFile;

	__try {


		hFile = RPOpen( szFileName, "rpf" );

        // if open fails..try as directory..

        if (hFile == INVALID_HANDLE_VALUE) {
            hFile = RPOpen( szFileName, "rpd" );
        }

        if (hFile == INVALID_HANDLE_VALUE) {
            printf("error opening %s\n", szFileName);
            return FALSE;
        }
		
		dwOutBuffLen = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;

		*ppOutBuff = (PBYTE) calloc( dwOutBuffLen, 1);

		if (NULL == *ppOutBuff) {
            printf("error callocing OutBuff in RPGet\n");
			return FALSE;
		}


        SetLastError( ERROR_SUCCESS );

		//
		// try the fsctl..
		//
	
		fSuccess = DeviceIoControl( hFile,
			FSCTL_GET_REPARSE_POINT,
			NULL,
			0,
			*ppOutBuff,
			dwOutBuffLen,
			&dwRc,
			NULL);

        printf("dwRc= %ld\n", dwRc);

		if ( ! fSuccess ) {

			gle = GetLastError();

				    printf("ERROR: FSCTL_GET_REPARSE_POINT in RPGet\n");
                    printf("GLE  : %ld\n",GetLastError());
					return FALSE;
		}

		return TRUE;

	} __finally {

	}
}


VOID
DumpBuff( PBYTE pData, WORD wSize )
{

	WORD i=0;
	WORD j=0;
	CHAR szData[LINE_LENGTH];
    WORD NumLines;

    NumLines = wSize/8;
   
    if (NumLines) {
 
	for( i=0; i < NumLines; i++) {

		szData[0] = '\0';

		for( j=0; j<8; j++) {

    		sprintf(szData,TEXT("%s %02X"), szData, *(pData + i*8 + j));

			if (j==3) {
				sprintf(szData, TEXT("%s -"), szData);
			}

		}
		
		sprintf(szData, TEXT("%s  "), szData);

		for( j=0; j<8; j++) {

			if (*(pData + i*8 + j) >  ' ') {
				sprintf(szData,TEXT("%s%c"), szData, *(pData + i*8 + j));
			} else {
				sprintf(szData,TEXT("%s."), szData);
		    }

		}

	  sprintf(gszLogMsg, TEXT("%05d:%s"), i*8, szData);
	  printf("%s\n", gszLogMsg );

      }
    }

    wSize %= 8;

    if (wSize) { 

		szData[0] = '\0';

		for( j=0; j<8; j++) {

			if (j >= wSize) {
				sprintf(szData,TEXT("%s   "), szData);
			} else {
				sprintf(szData,TEXT("%s %02X"), szData, *(pData + i*8 + j));
			}

			if (j==3) {
				sprintf(szData, TEXT("%s -"), szData);
			}

		}
		
		sprintf(szData, TEXT("%s  "), szData);

		for( j=0; j<8; j++) {

			if (j >= wSize) {
				sprintf(szData,TEXT("%s "), szData);
			} else {

				if (*(pData + i*8 + j) >  ' ') {
					sprintf(szData,TEXT("%s%c"), szData, *(pData + i*8 + j));
				} else {
					sprintf(szData,TEXT("%s."), szData);
			    }
			}

		}

	sprintf(gszLogMsg, TEXT("%05d:%s"), i*8, szData);
	printf("%s\n", gszLogMsg );

    }
}




//
//  Simple wrapper for NtCreateFile
//

NTSTATUS
OpenObject (
           WCHAR *pwszFile,
           ULONG CreateOptions,
           ULONG DesiredAccess,
           ULONG ShareAccess,
           ULONG CreateDisposition,
           IO_STATUS_BLOCK *IoStatusBlock,
           HANDLE *ObjectHandle)
{
    NTSTATUS Status;
    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING str;

    RtlDosPathNameToNtPathName_U(
                                pwszFile,
                                &str,
                                NULL,
                                NULL);

    InitializeObjectAttributes(
                              &ObjectAttributes,
                              &str,
                              OBJ_CASE_INSENSITIVE,
                              NULL,
                              NULL);

    Status = NtCreateFile(
                         ObjectHandle,
                         DesiredAccess | SYNCHRONIZE,
                         &ObjectAttributes,
                         IoStatusBlock,
                         NULL,                    // pallocationsize (none!)
                         FILE_ATTRIBUTE_NORMAL,
                         ShareAccess,
                         CreateDisposition,
                         CreateOptions,
                         NULL,                    // EA buffer (none!)
                         0);

    RtlFreeHeap (RtlProcessHeap(), 0, str.Buffer);

    if (!NT_SUCCESS( Status )) {
        printf("NtCreateFile Status %Xh\n", Status);
    }

    return (Status);
}



//----------------------------------------------------------------------------
//
//  RPOpen
//
// This function opens a file / directory in the specified mode 
// and if unsuccessful returns NULL
// INPUT - NAME and OPTION
//
//----------------------------------------------------------------------------


HANDLE
RPOpen (LPSTR szFileName, 
        LPSTR szOption )
{
    DWORD   dwOption = 0;
    DWORD   dwAccess = 0;
    DWORD   dwDisposition = 0;
    HANDLE  hFile;
    NTSTATUS Status ;
    DWORD dwLastErr ;

    IO_STATUS_BLOCK IoStatusBlock ;

    WCHAR   wszFileName[MAX_PATH];


    if (!_stricmp (szOption, "rpf")) {

        dwOption      = FILE_NON_DIRECTORY_FILE |
                        FILE_OPEN_REPARSE_POINT;

        dwAccess      = FILE_READ_DATA |
                        FILE_WRITE_DATA |
                        FILE_WRITE_ATTRIBUTES |
                        FILE_READ_ATTRIBUTES;

        dwDisposition = FILE_OPEN_IF ;

    } else if (!_stricmp (szOption, "rpd")) {

        dwOption      = FILE_OPEN_REPARSE_POINT;


        dwAccess      = FILE_WRITE_DATA ;


        dwDisposition = FILE_OPEN_IF ;

    } else if (!_stricmp (szOption, "d")) {

        dwOption      =  FILE_OPEN_REPARSE_POINT ;

        dwAccess      =  FILE_WRITE_DATA ;

        dwDisposition = FILE_OPEN_IF ;

    } else if (!_stricmp (szOption, "f")) {

        dwOption      = FILE_NON_DIRECTORY_FILE;

        dwAccess      = FILE_READ_DATA |
                        FILE_WRITE_DATA    |
                        FILE_LIST_DIRECTORY |
                        FILE_WRITE_ATTRIBUTES |
                        FILE_READ_ATTRIBUTES;

        dwDisposition = OPEN_ALWAYS ;
    }

    SzToWsz (wszFileName, szFileName);   

    if ( (0 == lstrcmp ( szOption , "f") )  || 
         (0 == lstrcmp ( szOption , "rpf") ) ) {

        hFile = CreateFile ( szFileName ,
                             GENERIC_READ | GENERIC_WRITE   ,
							 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                             NULL ,
                             dwDisposition ,
                             dwOption | FILE_OPEN_NO_RECALL,
                             NULL ) ;


        if ( INVALID_HANDLE_VALUE == hFile ) {
          //  printf( TEXT("ERROR: CreateFile in RPOpen\n") );
		}

    } else {

        Status = OpenObject (wszFileName,
                             dwOption,
                             dwAccess,
                             FILE_SHARE_READ |
                             FILE_SHARE_WRITE |
                             FILE_SHARE_DELETE,
                             dwDisposition,
                             &IoStatusBlock,
                             &hFile);

        if (!NT_SUCCESS (Status)) {
            printf( TEXT("OpenObject in RPOpen\n") );
        }

    }

    return hFile;
}


VOID
SzToWsz (
        OUT WCHAR *Unicode,
        IN char *Ansi
        )
{
    while (*Unicode++ = *Ansi++)
        ;
}



VOID
WszToSz (
        OUT char *Ansi,
        IN WCHAR *Unicode
        )
{
    while (*Ansi++ = (char) *Unicode++)
        ;
}