|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
delrp.c
This module contains a simple program to blatantly delete a reparse point of any kind.
Author:
Felipe Cabrera (Cabrera) 11-Jul-1997
Revision History:
--*/ #define UNICODE
#define _UNICODE
#include <stdio.h>
#include <stdlib.h> // exit
#include <io.h> // _get_osfhandle
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntioapi.h>
#include <windows.h>
#include <locale.h> // setlocale
//
//
// Functions forward referenced.
//
void SzToWsz ( OUT WCHAR *Unicode, IN char *Ansi );
void ScanArgs ( int argc, char **argv );
void __cdecl printmessage ( DWORD messageID, ... );
void __cdecl DisplayMsg ( DWORD MsgNum, ... );
int FileIsConsole ( int fh );
//
// I/O stream handles and variables.
//
HANDLE hInput; HANDLE hOutput; HANDLE hError;
#define STDIN 0
#define STDOUT 1
#define STDERR 2
BOOL ConsoleInput; BOOL ConsoleOutput; BOOL ConsoleError;
//
// Core control state vars
//
BOOLEAN NeedHelp;
#include "delrpmsg.h"
TCHAR Buf[1024]; // for displaying stuff
//
// Main
//
void __cdecl main( int argc, char **argv ) /*++
Routine Description:
Main procedure for pentnt.
First, we call a series of routines that build a state vector in some booleans.
We'll then act on these control variables:
NeedHelp - User has asked for help, or made a command error
Arguments:
argc - count of arguments, including the name of our proggram
argv - argument list - see command line syntax above
Return Value:
Exit(0) - the file was deleted
Exit(1) - a problem ocurred.
--*/
{ CHAR lBuf[16]; DWORD dwCodePage; LANGID LangId;
NTSTATUS Status = STATUS_SUCCESS; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Handle; UNICODE_STRING UnicodeName; IO_STATUS_BLOCK IoStatusBlock; BOOLEAN TranslationStatus; PVOID FreeBuffer; FILE_DISPOSITION_INFORMATION Disposition = {TRUE}; WCHAR WFileName[MAX_PATH];
//
// Build up state vector in global booleans.
//
ScanArgs(argc, argv);
//
// printf( "argc = %d NeedHelp = %d\n", argc, NeedHelp );
//
//
// Since FormatMessage checks the current TEB's locale, and the Locale for
// CHCP is initialized when the message class is initialized, the TEB has to
// be updated after the code page is changed successfully.
// Why are we doing this, you ask. Well, the FE guys have plans to add
// more than one set of language resources to this module, but not all
// the possible resources. So this limited set is what they plan for.
// If FormatMessage can't find the right language, it falls back to
// something hopefully useful.
//
dwCodePage = GetConsoleOutputCP();
sprintf(lBuf, ".%d", dwCodePage);
switch( dwCodePage ) { case 437: LangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); break; case 932: LangId = MAKELANGID( LANG_JAPANESE, SUBLANG_DEFAULT ); break; case 949: LangId = MAKELANGID( LANG_KOREAN, SUBLANG_KOREAN ); break; case 936: LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED ); break; case 950: LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL ); break; default: LangId = MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ); lBuf[0] = '\0'; break; }
SetThreadLocale( MAKELCID(LangId, SORT_DEFAULT) ); setlocale(LC_ALL, lBuf);
//
// Set the appropriate handles.
//
hInput = GetStdHandle(STD_INPUT_HANDLE); ConsoleInput = FileIsConsole(STDIN);
hOutput = GetStdHandle(STD_OUTPUT_HANDLE); ConsoleOutput = FileIsConsole(STDOUT);
hError = GetStdHandle(STD_ERROR_HANDLE); ConsoleError = FileIsConsole(STDERR);
//
// OK, we know the state of the command, do work
//
//
// If they asked for help, or did something that indicates they don't
// understand how the program works, print help and exit.
//
if (NeedHelp) { printmessage( MSG_DELRP_HELP ); exit(1); }
//
// Change the string to Unicode and pass down to open the file.
//
SzToWsz( WFileName, argv[1] );
TranslationStatus = RtlDosPathNameToNtPathName_U( WFileName, &UnicodeName, NULL, NULL );
if (!TranslationStatus) { printmessage( MSG_DELRP_WRONG_NAME ); exit(1); }
FreeBuffer = UnicodeName.Buffer;
InitializeObjectAttributes( &ObjectAttributes, &UnicodeName, OBJ_CASE_INSENSITIVE, NULL, NULL );
//
// printf( "Transformed unicode str is %Z\n", &UnicodeName );
//
//
// Open the file for delete access.
// Inhibit the reparse behavior using FILE_OPEN_REPARSE_POINT.
// This will get a handle to the entity whether the appropriate filter is or not in place.
//
Status = NtOpenFile( &Handle, (ACCESS_MASK)DELETE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT );
if (!NT_SUCCESS(Status)) {
SzToWsz( WFileName, argv[1] ); swprintf(&Buf[0], TEXT("%s"), WFileName); DisplayMsg(MSG_DELRP_OPEN_FAILED_NL, Buf);
// printmessage( MSG_DELRP_OPEN_FAILED );
RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); exit(1); }
RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
//
// Delete the file
//
Status = NtSetInformationFile( Handle, &IoStatusBlock, &Disposition, sizeof(Disposition), FileDispositionInformation );
NtClose(Handle);
if (!NT_SUCCESS(Status)) { printmessage( MSG_DELRP_DELETE_FAILED ); exit(1); }
exit(0); } // main
VOID ScanArgs( int argc, char **argv ) /*++
Routine Description:
ScanArgs - parse command line arguments, and set control flags to reflect what we find.
Sets NeedHelp.
Arguments:
argc - count of command line args
argv - argument vector
Return Value:
--*/ { int i;
NeedHelp = FALSE;
if ((argc == 1) || (argc > 3)) { NeedHelp = TRUE; goto done; }
//
// At this point argc == 2
//
if ((argv[1][0] == '/') && (argv[1][1] == '?') && (strlen(argv[1]) == 2)) { NeedHelp = TRUE; goto done; }
done: return; } // ScanArgs
//
// Changing a file name to wide characters.
//
void SzToWsz ( OUT WCHAR *Unicode, IN char *Ansi ) { while (*Unicode++ = *Ansi++) ; return; } // SzToWsz
//
// Call FormatMessage and dump the result. All messages to Stdout
//
void __cdecl printmessage ( DWORD messageID, ... ) { unsigned short messagebuffer[4096]; va_list ap;
va_start(ap, messageID);
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, messageID, 0, messagebuffer, 4095, &ap);
wprintf(messagebuffer);
va_end(ap); } // printmessage
TCHAR DisplayBuffer[4096]; CHAR DisplayBuffer2[4096];
void __cdecl DisplayMsg ( DWORD MsgNum, ... ) { DWORD len, bytes_written; BOOL success; DWORD status; va_list ap;
va_start(ap, MsgNum);
len = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, MsgNum, 0, DisplayBuffer, 4096, &ap);
if (ConsoleOutput) { success = WriteConsole(hOutput, (LPVOID)DisplayBuffer, len, &bytes_written, NULL);
} else { CharToOem(DisplayBuffer, DisplayBuffer2); success = WriteFile(hOutput, (LPVOID)DisplayBuffer2, len, &bytes_written, NULL); }
if (!success || bytes_written != len) { status = GetLastError(); }
va_end(ap); } // DisplayMsg
int FileIsConsole(int fh) { unsigned htype; DWORD dwMode; HANDLE hFile;
hFile = (HANDLE)_get_osfhandle(fh); htype = GetFileType(hFile); htype &= ~FILE_TYPE_REMOTE;
if (FILE_TYPE_CHAR == htype) {
switch (fh) { case STDIN: hFile = GetStdHandle(STD_INPUT_HANDLE); break; case STDOUT: hFile = GetStdHandle(STD_OUTPUT_HANDLE); break; case STDERR: hFile = GetStdHandle(STD_ERROR_HANDLE); break; }
if (GetConsoleMode(hFile, &dwMode)) { return TRUE; } }
return FALSE;
} // FileIsConsole
|