Windows2003-3790/sdktools/he/he.c

516 lines
13 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*****************************************************************/
/** Microsoft LAN Manager **/
/** Copyright(c) Microsoft Corp., 1988-1991 **/
/*****************************************************************/
/**** he - HexEdit a file
*
* Wrapper to HexEdit function to allow file (or drive) editting
*
* Written: Ken Reneris
*
*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntdddisk.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <windows.h>
#include "hexedit.h"
NTSTATUS fncRead(HANDLE, ULONGLONG, PUCHAR, DWORD);
NTSTATUS fncWrite(HANDLE, ULONGLONG, PUCHAR, DWORD);
void EditFile (char *name);
void ReadIni ();
WORD vAttrList, vAttrTitle, vAttrHigh;
VOID __cdecl
main (argc, argv)
USHORT argc;
char *argv[];
{
char *argument = argv[1];
if (argc < 2) {
printf ("he fname\n");
exit (1);
}
ReadIni ();
if ((strncmp(argv[1], "\\\\.\\", 4)) == 0) {
char *cp;
int index;
// Insure there is a backslash on the DosName being opened.
for (cp = argv[1], index = 0; *cp; *cp++, index++) {
// action in for loop
}
cp--;
if (*cp != '\\') {
// Need to add backslash to name.
argument = GlobalAlloc (0,index + 4);
if (!argument) {
printf("Out of memory\n");
exit (1);
}
for (cp = argv[1], index = 0; argument[index] = *cp; *cp++, index++) {
// action in for loop
}
argument[index] = '\\';
argument[index + 1] = '\0';
}
}
EditFile (argument);
}
void
EditFile (
char *name
)
{
FILE_ALIGNMENT_INFORMATION AlignmentInfo;
PDISK_GEOMETRY_EX DiskGeo;
ULONGLONG li;
struct HexEditParm ei;
USHORT rc, rc1, i, l;
PWSTR WideName;
OBJECT_ATTRIBUTES oa;
NTSTATUS status;
UNICODE_STRING NtDriveName;
ANSI_STRING NtDriveNameAnsi;
IO_STATUS_BLOCK status_block;
UCHAR GeoBuf[ 8*1024];
UCHAR Root[12];
//
// Try to open & edit as regular filename
//
memset ((PUCHAR) &ei, 0, sizeof (ei));
ei.ename = name;
ei.flag = FHE_VERIFYONCE | FHE_SAVESCRN | FHE_JUMP;
ei.read = fncRead;
ei.write = fncWrite;
ei.ioalign = 1;
ei.Console = INVALID_HANDLE_VALUE;
ei.AttrNorm = vAttrList;
ei.AttrHigh = vAttrTitle;
ei.AttrReverse = vAttrHigh;
ei.handle = CreateFile (
name,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if (ei.handle == INVALID_HANDLE_VALUE) {
// Try for just read access
ei.handle = CreateFile (
name,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
}
if (ei.handle != INVALID_HANDLE_VALUE) {
ULONG High = 0;
ei.totlen = 0;
ei.totlen = SetFilePointer (ei.handle, 0, &High, FILE_END);
ei.totlen |= ((ULONGLONG)High) << 32;
HexEdit (&ei);
return;
}
rc = (USHORT)GetLastError ();
//
// Try expanding the name from dosname to ntname.
// Since regular name failed, assume a sector edit
//
l = strlen(name)+1;
WideName = GlobalAlloc (0,l * sizeof(WCHAR));
if (!WideName) {
printf("Out of memory\n");
exit(1);
}
ZeroMemory(WideName, l*sizeof(WCHAR));
for(i=0; i < l; i++)
WideName[i] = name[i];
// OK, now get the corresponding NT name
rc1 = RtlDosPathNameToNtPathName_U (
WideName,
&NtDriveName,
NULL,
NULL );
if (!rc1) {
printf ("Open error %d\n", rc);
exit (rc);
}
// If the NT drive name has a trailing backslash, remove it.
l = NtDriveName.Length/sizeof(WCHAR);
if( NtDriveName.Buffer[l-1] == '\\' ) {
NtDriveName.Buffer[l-1] = 0;
NtDriveName.Length -= sizeof(WCHAR);
}
InitializeObjectAttributes(
&oa,
&NtDriveName,
OBJ_CASE_INSENSITIVE,
0,
0 );
status = NtOpenFile(
&ei.handle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&oa,
&status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT );
if (!NT_SUCCESS(status)) {
// try for just read access
status = NtOpenFile(
&ei.handle,
SYNCHRONIZE | FILE_READ_DATA,
&oa,
&status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT );
}
if (!NT_SUCCESS(status)) {
NtDriveName.Length = strlen(name) * sizeof(WCHAR);
NtDriveName.Buffer = WideName;
InitializeObjectAttributes(
&oa,
&NtDriveName,
OBJ_CASE_INSENSITIVE,
0,
0 );
status = NtOpenFile(
&ei.handle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&oa,
&status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT );
if (!NT_SUCCESS(status)) {
// try for just read access
status = NtOpenFile(
&ei.handle,
SYNCHRONIZE | FILE_READ_DATA,
&oa,
&status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT );
}
}
RtlUnicodeStringToAnsiString (&NtDriveNameAnsi, &NtDriveName, TRUE);
ei.ename = NtDriveNameAnsi.Buffer;
if (!NT_SUCCESS(status)) {
printf ("%s open error %lx\n", ei.ename, status);
exit (status);
}
/*
NtQueryInformationFile(
ei.handle,
&status_block,
&AlignmentInfo,
sizeof( AlignmentInfo ),
FileAlignmentInformation );
ei.ioalign = AlignmentInfo.AlignmentRequirement;
*/
ei.ioalign = 0;
ei.totlen = 0;
if (NtDriveNameAnsi.Buffer[ NtDriveNameAnsi.Length - 1] == ':') {
sprintf( Root, "%c:\\", NtDriveNameAnsi.Buffer[ NtDriveNameAnsi.Length - 2]);
//
// For non-cdrom drive letter opens, we need to use
// get partition info, not get disk info, for the partition size.
//
if (DRIVE_CDROM != GetDriveType( Root)) {
PPARTITION_INFORMATION Part = (PVOID)GeoBuf;
status = NtDeviceIoControlFile(
ei.handle,
0,
NULL,
NULL,
&status_block,
IOCTL_DISK_GET_PARTITION_INFO,
NULL,
0,
GeoBuf,
sizeof( GeoBuf) );
if (NT_SUCCESS(status)) {
ei.totlen = Part->PartitionLength.QuadPart;
}
}
}
//
// Get sectorsize and, if we haven't got it already, disk/partition size
//
status = NtDeviceIoControlFile( ei.handle,
0,
NULL,
NULL,
&status_block,
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
NULL,
0,
GeoBuf,
sizeof( GeoBuf) );
if (NT_SUCCESS(status)) {
DiskGeo = (PVOID)GeoBuf;
if (ei.ioalign < DiskGeo->Geometry.BytesPerSector) {
ei.ioalign = DiskGeo->Geometry.BytesPerSector;
}
if (0 == ei.totlen) {
ei.totlen = DiskGeo->DiskSize.QuadPart;
}
}
else {
//
// The EX call failed, try the old one. GPT discs seem
// to fail the EX call.
//
PDISK_GEOMETRY OldGeo;
status = NtDeviceIoControlFile( ei.handle,
0,
NULL,
NULL,
&status_block,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
GeoBuf,
sizeof( GeoBuf) );
if (NT_SUCCESS(status)) {
OldGeo = (PVOID)GeoBuf;
if (ei.ioalign < OldGeo->BytesPerSector) {
ei.ioalign = OldGeo->BytesPerSector;
}
if (0 == ei.totlen) {
ei.totlen = OldGeo->Cylinders.QuadPart * OldGeo->BytesPerSector *
OldGeo->SectorsPerTrack * OldGeo->TracksPerCylinder;
}
}
}
//
// Last resort for partition/disk size.
//
if (0 == ei.totlen) {
ULONG High = 0;
if (ei.ioalign < 0x200) {
ei.ioalign = 0x200;
}
ei.totlen = 0;
ei.totlen = SetFilePointer (ei.handle, 0, &High, FILE_END);
ei.totlen |= ((ULONGLONG)High) << 32;
}
//
// If a filesystem is mounted, we need to enable extended
// DASD io in order to read the whole volume. Ignore result,
// not all FSs support it.
//
status = NtDeviceIoControlFile(
ei.handle,
0,
NULL,
NULL,
&status_block,
FSCTL_ALLOW_EXTENDED_DASD_IO,
NULL,
0,
NULL,
0);
ei.flag = FHE_VERIFYALL | FHE_PROMPTSEC | FHE_SAVESCRN | FHE_JUMP;
HexEdit (&ei);
}
NTSTATUS fncRead (HANDLE h, ULONGLONG loc, PUCHAR data, DWORD len)
{
DWORD l, br;
ULONG High = (ULONG)(loc >> 32);
l = SetFilePointer (h, (ULONG)loc, &High, FILE_BEGIN);
if (l == -1)
return GetLastError();
if (!ReadFile (h, data, len, &br, NULL))
return GetLastError();
return (br != len ? ERROR_READ_FAULT : 0);
}
NTSTATUS fncWrite (HANDLE h, ULONGLONG loc, PUCHAR data, DWORD len)
{
DWORD l, bw;
ULONG High = (ULONG)(loc >> 32);
l = SetFilePointer (h, (ULONG)loc, &High, FILE_BEGIN);
if (l == -1)
return GetLastError();
if (!WriteFile (h, data, len, &bw, NULL))
return GetLastError();
return (bw != len ? ERROR_WRITE_FAULT : 0);
}
/*** xtoi - Hex to int
*
* Entry:
* pt - pointer to hex number
*
* Return:
* value of hex number
*
*/
unsigned xtoi (pt)
char *pt;
{
unsigned u;
char c;
u = 0;
while (c = *(pt++)) {
if (c >= 'a' && c <= 'f')
c -= 'a' - 'A';
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
u = u << 4 | c - (c >= 'A' ? 'A'-10 : '0');
}
return (u);
}
void
ReadIni ()
{
static char Delim[] = " :=;\t\r\n";
FILE *fp;
char *env, *verb, *value;
char s [200];
long l;
env = getenv ("INIT");
if (env == NULL)
return;
if ((strlen(env) + sizeof ("\\TOOLS.INI") + 1) > sizeof(s))
return;
strcpy (s, env);
strcat (s, "\\TOOLS.INI"); // just use list ini section
fp = fopen (s, "r");
if (fp == NULL)
return;
while (fgets (s, 200, fp) != NULL) {
if (s[0] != '[')
continue;
_strupr (s);
if (strstr (s, "LIST") == NULL)
continue;
/*
* ini file found w/ "list" keyword. Now read it.
*/
while (fgets (s, 200, fp) != NULL) {
if (s[0] == '[')
break;
verb = strtok (s, Delim);
value = strtok (NULL, Delim);
if (verb == NULL)
continue;
if (value == NULL)
value = "";
_strupr (verb);
if (strcmp (verb, "LCOLOR") == 0) vAttrList = (WORD)xtoi(value);
else if (strcmp (verb, "TCOLOR") == 0) vAttrTitle= (WORD)xtoi(value);
else if (strcmp (verb, "HCOLOR") == 0) vAttrHigh = (WORD)xtoi(value);
}
break;
}
fclose (fp);
}