474 lines
8.8 KiB
C
474 lines
8.8 KiB
C
/*++
|
||
|
||
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
|