/*++
Copyright (c) 1994-1995 Microsoft Corporation
Module Name:
Support.c
Abstract:
Support routines for compact utility
Author:
Matthew Bradburn [mattbr] 05-Oct-1994
Revision History:
--*/
#define UNICODE
#define _UNICODE
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <windows.h>
#include "support.h"
#include "msg.h"
//
// Declare routines to put out internationalized messages
//
typedef enum {
READ_ACCESS,
WRITE_ACCESS
} STREAMACCESS;
HANDLE
GetStandardStream(
IN HANDLE Handle,
IN STREAMACCESS Access
);
HANDLE hInput;
HANDLE hOutput;
HANDLE hError;
#define STDIN 0
#define STDOUT 1
#define STDERR 2
BOOL ConsoleInput;
BOOL ConsoleOutput;
BOOL ConsoleError;
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;
}
VOID
InitializeIoStreams()
{
#ifdef FE_SB
LANGID LangId;
switch (GetConsoleOutputCP()) {
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 );
break;
}
SetThreadLocale( MAKELCID(LangId, SORT_DEFAULT) );
#endif
hInput = GetStdHandle(STD_INPUT_HANDLE);
ConsoleInput = FileIsConsole(STDIN);
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
ConsoleOutput = FileIsConsole(STDOUT);
hError = GetStdHandle(STD_ERROR_HANDLE);
ConsoleError = FileIsConsole(STDERR);
}
TCHAR DisplayBuffer[4096];
CHAR DisplayBuffer2[4096];
VOID
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);
}
VOID
DisplayErr(
PTCHAR Prefix,
DWORD MsgNum,
...
)
{
DWORD len, bytes_written;
BOOL success;
DWORD status;
va_list ap;
ULONG i;
va_start(ap, MsgNum);
if (NULL != Prefix) {
lstrcpy(DisplayBuffer, Prefix);
lstrcat(DisplayBuffer, TEXT(": "));
} else {
DisplayBuffer[0] = UNICODE_NULL;
}
i = lstrlen(DisplayBuffer);
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, MsgNum, 0,
DisplayBuffer + i, 4096 - i, &ap);
if (ConsoleError) {
success = WriteConsole(hError, (LPVOID)DisplayBuffer, len + i,
&bytes_written, NULL);
} else {
CharToOem(DisplayBuffer, DisplayBuffer2);
success = WriteFile(hError, (LPVOID)DisplayBuffer2, len + i,
&bytes_written, NULL);
}
if (!success) {
status = GetLastError();
}
va_end(ap);
}
BOOLEAN
IsNtldr(
PTCHAR Path
)
/*++
Routine Description:
Used to keep the user from compressing \NTLDR (which would prevent
the machine from booting).
Arguments:
Path - the path to examine.
Return Value:
TRUE - the path looks like \ntldr.
FALSE - the path does not look like \ntldr.
--*/
{
PTCHAR pch;
// try "X:\ntldr"
if (0 == lstricmp(Path + 2, TEXT("\\ntldr"))) {
return TRUE;
}
// try "\\machine\share\ntldr"
if ('\\' == Path[0] && '\\' != Path[1]) {
pch = lstrchr(Path + 2, '\\');
if (NULL == pch) {
return FALSE;
}
pch = lstrchr(pch + 1, '\\');
if (NULL == pch) {
return FALSE;
}
if (0 == lstricmp(pch, TEXT("\\ntldr"))) {
return TRUE;
}
}
return FALSE;
}
BOOLEAN
IsUncRoot(
PTCHAR Path
)
/*++
Routine Description:
Determine whether the given path is of the form \\server\share.
Arguments:
Path - the path to examine.
Return Value:
TRUE - the path looks like a unc share name.
FALSE - the path does not look like that.
--*/
{
PTCHAR pch;
if ('\\' != *Path || '\\' != *(Path + 1)) {
return FALSE;
}
pch = lstrchr(Path + 2, '\\');
if (NULL == pch) {
//
// There is no slash to seperate server and share.
//
return FALSE;
}
pch = lstrchr(pch + 1, '\\');
if (NULL != pch) {
//
// There are additional component -- no match.
//
return FALSE;
}
if ('\\' == *(Path + lstrlen(Path))) {
//
// The string ends in slash -- it doesn't match.
//
return FALSE;
}
return TRUE;
}
ULONG
FormatFileSize(
IN PLARGE_INTEGER FileSize,
IN DWORD Width,
OUT PTCHAR FormattedSize,
IN BOOLEAN Commas
)
{
TCHAR Buffer[100];
PTCHAR s, s1;
ULONG DigitIndex, Digit;
ULONG Size;
LARGE_INTEGER TempSize;
s = &Buffer[ 99 ];
*s = TEXT('\0');
DigitIndex = 0;
TempSize = *FileSize;
while (TempSize.HighPart != 0) {
if (TempSize.HighPart != 0) {
Digit = (ULONG)(TempSize.QuadPart % 10);
TempSize.QuadPart = TempSize.QuadPart / 10;
} else {
Digit = TempSize.LowPart % 10;
TempSize.LowPart = TempSize.LowPart / 10;
}
*--s = (TCHAR)(TEXT('0') + Digit);
if ((++DigitIndex % 3) == 0 && Commas) {
*--s = TEXT(',');
}
}
Size = TempSize.LowPart;
while (Size != 0) {
*--s = (TCHAR)(TEXT('0') + (Size % 10));
Size = Size / 10;
if ((++DigitIndex % 3) == 0 && Commas) {
*--s = TEXT(',');
}
}
if (DigitIndex == 0) {
*--s = TEXT('0');
} else if (Commas && *s == TEXT(',')) {
s += 1;
}
Size = lstrlen( s );
if (Width != 0 && Size < Width) {
s1 = FormattedSize;
while (Width > Size) {
Width -= 1;
*s1++ = TEXT(' ');
}
lstrcpy( s1, s );
} else {
lstrcpy( FormattedSize, s );
}
return lstrlen( FormattedSize );
}