1149 lines
32 KiB
C
1149 lines
32 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1994 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
OSChecks.C
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
functions to used to determine the Operating System(s) installed
|
|||
|
on the current system.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Bob Watson (a-robw)
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
23 Dec 94
|
|||
|
|
|||
|
--*/
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <c2dll.h>
|
|||
|
#include <c2inc.h>
|
|||
|
#include <c2utils.h>
|
|||
|
#include <strings.h>
|
|||
|
#include "c2funcs.h"
|
|||
|
#include "c2funres.h"
|
|||
|
|
|||
|
// define action codes here. They are only meaningful in the
|
|||
|
// context of this module.
|
|||
|
|
|||
|
#define AC_NO_CHANGE 0
|
|||
|
#define AC_UPDATE 1
|
|||
|
//
|
|||
|
// for the action value, these are bits in a bit-mask used to
|
|||
|
// describe the action to take in the SET procedure
|
|||
|
//
|
|||
|
#define AV_DELETE_DOS 1
|
|||
|
#define AV_SET_TIMEOUT 2
|
|||
|
#define AV_SET_DEFAULT 4
|
|||
|
|
|||
|
#define SECURE C2DLL_C2
|
|||
|
//
|
|||
|
// define local macros
|
|||
|
//
|
|||
|
#define MALLOC(size) (PVOID)LocalAlloc(LPTR,size)
|
|||
|
#define FREE(block) {LocalFree(block); block = NULL;}
|
|||
|
//
|
|||
|
// Unicode Specific macros
|
|||
|
//
|
|||
|
#if _UNICODE
|
|||
|
#define DriveLetterToArcPath(a) DriveLetterToArcPathW(a)
|
|||
|
|
|||
|
#else // not unicode
|
|||
|
#define DriveLetterToArcPath(a) DriveLetterToArcPathA(a)
|
|||
|
|
|||
|
#endif
|
|||
|
//
|
|||
|
// Leave as array because some code uses sizeof(ArcNameDirectory)
|
|||
|
//
|
|||
|
WCHAR ArcNameDirectory[] = L"\\ArcName";
|
|||
|
BOOL bTargetsDefined = FALSE;
|
|||
|
PWSTR DosDeviceTargets[24];
|
|||
|
//
|
|||
|
//
|
|||
|
// Helper macro to make object attribute initialization a little cleaner.
|
|||
|
//
|
|||
|
#define INIT_OBJA(Obja,UnicodeString,UnicodeText) \
|
|||
|
\
|
|||
|
RtlInitUnicodeString((UnicodeString),(UnicodeText)); \
|
|||
|
\
|
|||
|
InitializeObjectAttributes( \
|
|||
|
(Obja), \
|
|||
|
(UnicodeString), \
|
|||
|
OBJ_CASE_INSENSITIVE, \
|
|||
|
NULL, \
|
|||
|
NULL \
|
|||
|
)
|
|||
|
|
|||
|
static
|
|||
|
BOOL
|
|||
|
IsIntelProcessor()
|
|||
|
{
|
|||
|
SYSTEM_INFO si;
|
|||
|
|
|||
|
memset (&si, 0, sizeof(si));
|
|||
|
|
|||
|
GetSystemInfo(&si);
|
|||
|
|
|||
|
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
|
|||
|
return TRUE;
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
VOID
|
|||
|
DnConcatenatePaths(
|
|||
|
IN OUT PWSTR Path1,
|
|||
|
IN PWSTR Path2,
|
|||
|
IN DWORD BufferSizeBytes
|
|||
|
)
|
|||
|
{
|
|||
|
BOOL NeedBackslash = TRUE;
|
|||
|
DWORD l = lstrlenW(Path1);
|
|||
|
DWORD BufferSizeChars;
|
|||
|
|
|||
|
BufferSizeChars = (BufferSizeBytes >= sizeof(WCHAR))
|
|||
|
? ((BufferSizeBytes/sizeof(WCHAR))-1) // leave room for nul
|
|||
|
: 0;
|
|||
|
|
|||
|
//
|
|||
|
// Determine whether we need to stick a backslash
|
|||
|
// between the components.
|
|||
|
//
|
|||
|
if(l && (Path1[l-1] == L'\\')) {
|
|||
|
|
|||
|
NeedBackslash = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if(*Path2 == L'\\') {
|
|||
|
|
|||
|
if(NeedBackslash) {
|
|||
|
NeedBackslash = FALSE;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Not only do we not need a backslash, but we
|
|||
|
// need to eliminate one before concatenating.
|
|||
|
//
|
|||
|
Path2++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Append backslash if necessary and if it fits.
|
|||
|
//
|
|||
|
if(NeedBackslash && (l < BufferSizeChars)) {
|
|||
|
lstrcatW(Path1,L"\\");
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Append second part of string to first part if it fits.
|
|||
|
//
|
|||
|
if(l+lstrlenW(Path2) < BufferSizeChars) {
|
|||
|
lstrcatW(Path1,Path2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
PWSTR
|
|||
|
DupString(
|
|||
|
IN PWSTR String
|
|||
|
)
|
|||
|
{
|
|||
|
PWSTR p;
|
|||
|
|
|||
|
p = MALLOC((lstrlenW(String)+1)*sizeof(WCHAR));
|
|||
|
lstrcpyW(p,String);
|
|||
|
return(p);
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
VOID
|
|||
|
InitDriveNameTranslations(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
WCHAR DriveName[3];
|
|||
|
WCHAR Drive;
|
|||
|
WCHAR DriveRoot[4];
|
|||
|
WCHAR Buffer[512];
|
|||
|
|
|||
|
DriveName[1] = L':';
|
|||
|
DriveName[2] = 0;
|
|||
|
|
|||
|
DriveRoot[0] = L' ';
|
|||
|
DriveRoot[1] = L':';
|
|||
|
DriveRoot[2] = L'\\';
|
|||
|
DriveRoot[3] = 0;
|
|||
|
//
|
|||
|
// Calculate NT names for all local hard disks C-Z.
|
|||
|
//
|
|||
|
for(Drive=L'C'; Drive<=L'Z'; Drive++) {
|
|||
|
|
|||
|
DosDeviceTargets[Drive-L'C'] = NULL;
|
|||
|
|
|||
|
DriveRoot[0] = Drive;
|
|||
|
if(GetDriveTypeW(DriveRoot) == DRIVE_FIXED) {
|
|||
|
|
|||
|
DriveName[0] = Drive;
|
|||
|
|
|||
|
// BUGBUG: this could be a mem leak...
|
|||
|
|
|||
|
if(QueryDosDeviceW(DriveName,Buffer,(sizeof(Buffer)/sizeof(WCHAR)))) {
|
|||
|
DosDeviceTargets[Drive-L'C'] = DupString(Buffer);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
PWSTR
|
|||
|
DriveLetterToArcPathW(
|
|||
|
IN WCHAR DriveLetter
|
|||
|
)
|
|||
|
{
|
|||
|
UNICODE_STRING UnicodeString;
|
|||
|
HANDLE DirectoryHandle;
|
|||
|
HANDLE ObjectHandle;
|
|||
|
OBJECT_ATTRIBUTES Obja;
|
|||
|
NTSTATUS Status;
|
|||
|
BOOL RestartScan;
|
|||
|
DWORD Context;
|
|||
|
BOOL MoreEntries;
|
|||
|
PWSTR ArcName;
|
|||
|
UCHAR Buffer[1024];
|
|||
|
POBJECT_DIRECTORY_INFORMATION DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
|
|||
|
PWSTR ArcPath;
|
|||
|
PWSTR NtPath;
|
|||
|
|
|||
|
NtPath = DosDeviceTargets[towupper(DriveLetter) - L'C'];
|
|||
|
if(!NtPath) {
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Assume failure.
|
|||
|
//
|
|||
|
ArcPath = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Open the \ArcName directory.
|
|||
|
//
|
|||
|
INIT_OBJA(&Obja,&UnicodeString,ArcNameDirectory);
|
|||
|
|
|||
|
Status = NtOpenDirectoryObject(&DirectoryHandle,DIRECTORY_QUERY,&Obja);
|
|||
|
|
|||
|
if(NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
RestartScan = TRUE;
|
|||
|
Context = 0;
|
|||
|
MoreEntries = TRUE;
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
Status = NtQueryDirectoryObject(
|
|||
|
(HANDLE)DirectoryHandle,
|
|||
|
(PVOID)&Buffer[0],
|
|||
|
(ULONG)sizeof(Buffer),
|
|||
|
(BOOLEAN)TRUE, // return single entry
|
|||
|
(BOOLEAN)RestartScan,
|
|||
|
(PULONG)&Context,
|
|||
|
(PULONG)NULL // return length
|
|||
|
);
|
|||
|
|
|||
|
if(NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
_wcslwr(DirInfo->Name.Buffer);
|
|||
|
|
|||
|
//
|
|||
|
// Make sure this name is a symbolic link.
|
|||
|
//
|
|||
|
if(DirInfo->Name.Length
|
|||
|
&& (DirInfo->TypeName.Length >= (sizeof(L"SymbolicLink") - sizeof(WCHAR)))
|
|||
|
&& !_wcsnicmp(DirInfo->TypeName.Buffer,L"SymbolicLink",12))
|
|||
|
{
|
|||
|
ArcName = MALLOC(DirInfo->Name.Length + sizeof(ArcNameDirectory) + sizeof(WCHAR));
|
|||
|
|
|||
|
wcscpy(ArcName,ArcNameDirectory);
|
|||
|
DnConcatenatePaths(ArcName,DirInfo->Name.Buffer,(DWORD)(-1));
|
|||
|
|
|||
|
//
|
|||
|
// We have the entire arc name in ArcName. Now open it as a symbolic link.
|
|||
|
//
|
|||
|
INIT_OBJA(&Obja,&UnicodeString,ArcName);
|
|||
|
|
|||
|
Status = NtOpenSymbolicLinkObject(
|
|||
|
&ObjectHandle,
|
|||
|
READ_CONTROL | SYMBOLIC_LINK_QUERY,
|
|||
|
&Obja
|
|||
|
);
|
|||
|
|
|||
|
if(NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// Finally, query the object to get the link target.
|
|||
|
//
|
|||
|
UnicodeString.Buffer = (PWSTR)Buffer;
|
|||
|
UnicodeString.Length = 0;
|
|||
|
UnicodeString.MaximumLength = sizeof(Buffer);
|
|||
|
|
|||
|
Status = NtQuerySymbolicLinkObject(
|
|||
|
ObjectHandle,
|
|||
|
&UnicodeString,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if(NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// nul-terminate the returned string
|
|||
|
//
|
|||
|
UnicodeString.Buffer[UnicodeString.Length/sizeof(WCHAR)] = 0;
|
|||
|
|
|||
|
if(!_wcsicmp(UnicodeString.Buffer,NtPath)) {
|
|||
|
|
|||
|
ArcPath = ArcName
|
|||
|
+ (sizeof(ArcNameDirectory)/sizeof(WCHAR));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NtClose(ObjectHandle);
|
|||
|
}
|
|||
|
|
|||
|
if(!ArcPath) {
|
|||
|
FREE(ArcName);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
MoreEntries = FALSE;
|
|||
|
if(Status == STATUS_NO_MORE_ENTRIES) {
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
RestartScan = FALSE;
|
|||
|
|
|||
|
} while(MoreEntries && !ArcPath);
|
|||
|
|
|||
|
NtClose(DirectoryHandle);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// ArcPath points into thje middle of a buffer.
|
|||
|
// The caller needs to be able to free it, so place it in its
|
|||
|
// own buffer here.
|
|||
|
//
|
|||
|
if(ArcPath) {
|
|||
|
ArcPath = DupString(ArcPath);
|
|||
|
FREE(ArcName);
|
|||
|
}
|
|||
|
|
|||
|
return(ArcPath);
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
WCHAR
|
|||
|
ArcPathToDriveLetter(
|
|||
|
IN PWSTR ArcPath
|
|||
|
)
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
HANDLE ObjectHandle;
|
|||
|
OBJECT_ATTRIBUTES Obja;
|
|||
|
UNICODE_STRING UnicodeString;
|
|||
|
UCHAR Buffer[1024];
|
|||
|
WCHAR DriveLetter;
|
|||
|
WCHAR drive;
|
|||
|
PWSTR arcPath;
|
|||
|
|
|||
|
//
|
|||
|
// Assume failure
|
|||
|
//
|
|||
|
DriveLetter = 0;
|
|||
|
|
|||
|
arcPath = MALLOC(((wcslen(ArcPath)+1)*sizeof(WCHAR)) + sizeof(ArcNameDirectory));
|
|||
|
wcscpy(arcPath,ArcNameDirectory);
|
|||
|
wcscat(arcPath,L"\\");
|
|||
|
wcscat(arcPath,ArcPath);
|
|||
|
|
|||
|
INIT_OBJA(&Obja,&UnicodeString,arcPath);
|
|||
|
|
|||
|
Status = NtOpenSymbolicLinkObject(
|
|||
|
&ObjectHandle,
|
|||
|
READ_CONTROL | SYMBOLIC_LINK_QUERY,
|
|||
|
&Obja
|
|||
|
);
|
|||
|
|
|||
|
if(NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// Query the object to get the link target.
|
|||
|
//
|
|||
|
UnicodeString.Buffer = (PWSTR)Buffer;
|
|||
|
UnicodeString.Length = 0;
|
|||
|
UnicodeString.MaximumLength = sizeof(Buffer);
|
|||
|
|
|||
|
Status = NtQuerySymbolicLinkObject(
|
|||
|
ObjectHandle,
|
|||
|
&UnicodeString,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if(NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
UnicodeString.Buffer[UnicodeString.Length/sizeof(WCHAR)] = 0;
|
|||
|
|
|||
|
for(drive=L'C'; drive<=L'Z'; drive++) {
|
|||
|
|
|||
|
if(DosDeviceTargets[drive-L'C']
|
|||
|
&& !_wcsicmp(UnicodeString.Buffer,DosDeviceTargets[drive-L'C']))
|
|||
|
{
|
|||
|
DriveLetter = drive;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NtClose(ObjectHandle);
|
|||
|
}
|
|||
|
|
|||
|
FREE(arcPath);
|
|||
|
|
|||
|
return(DriveLetter);
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
BOOL
|
|||
|
IsBootIniTimeoutZero (
|
|||
|
)
|
|||
|
{
|
|||
|
TCHAR szTimeOut[MAX_PATH];
|
|||
|
LONG lRetLen;
|
|||
|
LONG lTimeOut;
|
|||
|
|
|||
|
lRetLen = GetPrivateProfileString (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_LOADER_SECTION),
|
|||
|
GetStringResource (GetDllInstance(), IDS_TIMEOUT),
|
|||
|
cmszEmptyString,
|
|||
|
szTimeOut,
|
|||
|
MAX_PATH,
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_PATH));
|
|||
|
|
|||
|
if (lRetLen > 0) {
|
|||
|
lTimeOut = _tcstol (szTimeOut, NULL, 10);
|
|||
|
// note that 0 is returned if the string cannot be translated!
|
|||
|
if (lTimeOut > 0) {
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// no time out string found
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
LPSTR
|
|||
|
DriveLetterToArcPathA (
|
|||
|
IN CHAR DriveLetter
|
|||
|
)
|
|||
|
{
|
|||
|
WCHAR wDriveLetter;
|
|||
|
PWSTR wszArcPath;
|
|||
|
LPSTR szArcPath;
|
|||
|
int nRetLen;
|
|||
|
|
|||
|
wDriveLetter = (WCHAR)DriveLetter;
|
|||
|
|
|||
|
wszArcPath = DriveLetterToArcPathW(wDriveLetter);
|
|||
|
if (wszArcPath != NULL) {
|
|||
|
// convert back to ASCII
|
|||
|
nRetLen = lstrlenW(wszArcPath);
|
|||
|
szArcPath = MALLOC (nRetLen+1);
|
|||
|
if (szArcPath != NULL) {
|
|||
|
wcstombs (szArcPath, wszArcPath, nRetLen);
|
|||
|
}
|
|||
|
} else {
|
|||
|
szArcPath = NULL;
|
|||
|
}
|
|||
|
return szArcPath;
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
LONG
|
|||
|
GetArcWindowsPath (
|
|||
|
OUT LPTSTR szArcPath, // buffer to write path to
|
|||
|
IN DWORD dwChars // buffer length in chars
|
|||
|
)
|
|||
|
{
|
|||
|
TCHAR szDosWindowsDir[MAX_PATH];
|
|||
|
LPTSTR szArcWindowsDrive;
|
|||
|
DWORD dwBufReqd;
|
|||
|
|
|||
|
if (szArcPath != NULL) {
|
|||
|
if (GetWindowsDirectory(szDosWindowsDir, MAX_PATH) > 0) {
|
|||
|
// convert Dos path to Arc Path
|
|||
|
szArcWindowsDrive = DriveLetterToArcPath(szDosWindowsDir[0]);
|
|||
|
if (szArcWindowsDrive != NULL) {
|
|||
|
// make sure there's room in the buffer
|
|||
|
dwBufReqd = lstrlen(szArcWindowsDrive) +
|
|||
|
lstrlen(&szDosWindowsDir[2]);
|
|||
|
if (dwBufReqd < dwChars) {
|
|||
|
// theres room so copy and
|
|||
|
// make full path
|
|||
|
lstrcpy (szArcPath, szArcWindowsDrive);
|
|||
|
lstrcat (szArcPath, &szDosWindowsDir[2]);
|
|||
|
} else {
|
|||
|
// insufficient room so return 0
|
|||
|
dwBufReqd = 0;
|
|||
|
*szArcPath = 0;
|
|||
|
}
|
|||
|
// release memory allocated by conversion
|
|||
|
FREE (szArcWindowsDrive);
|
|||
|
} else {
|
|||
|
// unable to convert drive to arc path so return 0
|
|||
|
dwBufReqd = 0;
|
|||
|
*szArcPath = 0;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// unable to get current windows dir so return 0
|
|||
|
dwBufReqd = 0;
|
|||
|
*szArcPath = 0;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// empty or null buffer passed so just return 0 len
|
|||
|
dwBufReqd = 0;
|
|||
|
}
|
|||
|
return (LONG)dwBufReqd;
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
BOOL
|
|||
|
IsCurrentSystemDefault (
|
|||
|
)
|
|||
|
{
|
|||
|
TCHAR szArcWindowsDir[MAX_PATH*2];
|
|||
|
TCHAR szArcDefaultDir[MAX_PATH];
|
|||
|
LONG lStatus;
|
|||
|
BOOL bReturn;
|
|||
|
|
|||
|
if (GetArcWindowsPath(szArcWindowsDir, MAX_PATH*2) > 0) {
|
|||
|
// get boot.ini default from [Boot Loader] section
|
|||
|
lStatus = GetPrivateProfileString (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_LOADER_SECTION),
|
|||
|
GetStringResource (GetDllInstance(), IDS_DEFAULT_KEY),
|
|||
|
cszEmptyString,
|
|||
|
&szArcDefaultDir[0],
|
|||
|
MAX_PATH,
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME));
|
|||
|
if (lStatus > 0) {
|
|||
|
if (lstrcmpi (szArcDefaultDir, szArcWindowsDir) == 0) {
|
|||
|
// default is current system
|
|||
|
bReturn = TRUE;
|
|||
|
} else {
|
|||
|
// default is not current system
|
|||
|
bReturn = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
//unable to get windows dir
|
|||
|
bReturn = FALSE;
|
|||
|
}
|
|||
|
return bReturn;
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
BOOL
|
|||
|
ZeroFileByName (
|
|||
|
IN LPCTSTR szFileName
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwOldAttrib = 0;
|
|||
|
DWORD dwNewAttrib = 0;
|
|||
|
HANDLE hFile;
|
|||
|
BOOL bReturn = FALSE;
|
|||
|
|
|||
|
if (FileExists (szFileName)) {
|
|||
|
// save the original attributes for later
|
|||
|
dwOldAttrib = GetFileAttributes (szFileName);
|
|||
|
|
|||
|
// set file attributes on file to allow modification
|
|||
|
SetFileAttributes (szFileName, FILE_ATTRIBUTE_NORMAL);
|
|||
|
|
|||
|
// make sure it went OK
|
|||
|
dwNewAttrib = GetFileAttributes (szFileName);
|
|||
|
|
|||
|
if (dwNewAttrib == FILE_ATTRIBUTE_NORMAL) {
|
|||
|
hFile = CreateFile (
|
|||
|
szFileName,
|
|||
|
GENERIC_WRITE,
|
|||
|
0L, // no sharing while this is done
|
|||
|
NULL, // no security
|
|||
|
TRUNCATE_EXISTING,
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|||
|
CloseHandle (hFile);
|
|||
|
bReturn = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// reset the attributes
|
|||
|
|
|||
|
SetFileAttributes (szFileName, dwOldAttrib);
|
|||
|
}
|
|||
|
} else {
|
|||
|
// file doesn't exist so it's already 0'd
|
|||
|
bReturn = TRUE;
|
|||
|
}
|
|||
|
return bReturn;
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
BOOL
|
|||
|
DeleteDosFiles (
|
|||
|
)
|
|||
|
{
|
|||
|
BOOL bReturn;
|
|||
|
|
|||
|
bReturn = ZeroFileByName (
|
|||
|
GetStringResource(GetDllInstance(), IDS_IO_SYS));
|
|||
|
|
|||
|
if (bReturn) {
|
|||
|
bReturn = ZeroFileByName (
|
|||
|
GetStringResource(GetDllInstance(), IDS_MSDOS_SYS));
|
|||
|
}
|
|||
|
|
|||
|
if (bReturn) {
|
|||
|
bReturn = ZeroFileByName (
|
|||
|
GetStringResource(GetDllInstance(), IDS_PCDOS_SYS));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return bReturn;
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
BOOL
|
|||
|
SetBootIniTimeoutToZero (
|
|||
|
)
|
|||
|
{
|
|||
|
BOOL bReturn = TRUE;
|
|||
|
DWORD dwNewBootIniAttrib = 0;
|
|||
|
DWORD dwOrigBootIniAttrib = 0;
|
|||
|
|
|||
|
// save the original attributes for later
|
|||
|
dwOrigBootIniAttrib = GetFileAttributes (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME));
|
|||
|
|
|||
|
// set file attributes on Boot.INI file
|
|||
|
SetFileAttributes (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME),
|
|||
|
FILE_ATTRIBUTE_NORMAL);
|
|||
|
|
|||
|
// make sure it went OK
|
|||
|
dwNewBootIniAttrib = GetFileAttributes (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME));
|
|||
|
|
|||
|
if (dwNewBootIniAttrib == FILE_ATTRIBUTE_NORMAL) {
|
|||
|
bReturn = WritePrivateProfileString (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_LOADER_SECTION),
|
|||
|
GetStringResource (GetDllInstance(), IDS_TIMEOUT),
|
|||
|
GetStringResource (GetDllInstance(), IDS_0),
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_PATH));
|
|||
|
|
|||
|
// reset file attributes on Boot.INI file
|
|||
|
SetFileAttributes (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME),
|
|||
|
dwOrigBootIniAttrib);
|
|||
|
return bReturn;
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
BOOL
|
|||
|
SetBootDefaultToCurrentSystem (
|
|||
|
)
|
|||
|
{
|
|||
|
TCHAR szArcSystemPath[MAX_PATH*2];
|
|||
|
BOOL bReturn = TRUE;
|
|||
|
DWORD dwNewBootIniAttrib = 0;
|
|||
|
DWORD dwOrigBootIniAttrib = 0;
|
|||
|
|
|||
|
// save the original attributes for later
|
|||
|
dwOrigBootIniAttrib = GetFileAttributes (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME));
|
|||
|
|
|||
|
// set file attributes on Boot.INI file
|
|||
|
SetFileAttributes (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME),
|
|||
|
FILE_ATTRIBUTE_NORMAL);
|
|||
|
|
|||
|
// make sure it went OK
|
|||
|
dwNewBootIniAttrib = GetFileAttributes (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME));
|
|||
|
|
|||
|
if (dwNewBootIniAttrib == FILE_ATTRIBUTE_NORMAL) {
|
|||
|
// file set OK so continue and get new path for ini
|
|||
|
if (GetArcWindowsPath(szArcSystemPath, MAX_PATH*2) > 0) {
|
|||
|
bReturn = WritePrivateProfileString (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_LOADER_SECTION),
|
|||
|
GetStringResource (GetDllInstance(), IDS_DEFAULT_KEY),
|
|||
|
szArcSystemPath,
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_PATH));
|
|||
|
|
|||
|
// reset file attributes on Boot.INI file
|
|||
|
SetFileAttributes (
|
|||
|
GetStringResource (GetDllInstance(), IDS_BOOT_INI_FILENAME),
|
|||
|
dwOrigBootIniAttrib);
|
|||
|
}
|
|||
|
return bReturn;
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static
|
|||
|
BOOL
|
|||
|
IsDosOnSystem (
|
|||
|
)
|
|||
|
{
|
|||
|
BOOL bFileFound;
|
|||
|
LPCTSTR szFileToCheck;
|
|||
|
|
|||
|
szFileToCheck = GetStringResource(GetDllInstance(), IDS_IO_SYS);
|
|||
|
bFileFound = FileExists(szFileToCheck);
|
|||
|
if (bFileFound) {
|
|||
|
// check to see if it's really there
|
|||
|
if (GetFileSizeFromPath(szFileToCheck) == 0) {
|
|||
|
// just a name so reset flag
|
|||
|
bFileFound = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!bFileFound) {
|
|||
|
szFileToCheck = GetStringResource(GetDllInstance(), IDS_MSDOS_SYS);
|
|||
|
bFileFound = FileExists(szFileToCheck);
|
|||
|
if (bFileFound) {
|
|||
|
// check to see if it's really there
|
|||
|
if (GetFileSizeFromPath(szFileToCheck) == 0) {
|
|||
|
// just a name so reset flag
|
|||
|
bFileFound = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!bFileFound) {
|
|||
|
szFileToCheck = GetStringResource(GetDllInstance(), IDS_PCDOS_SYS);
|
|||
|
bFileFound = FileExists(szFileToCheck);
|
|||
|
if (bFileFound) {
|
|||
|
// check to see if it's really there
|
|||
|
if (GetFileSizeFromPath(szFileToCheck) == 0) {
|
|||
|
// just a name so reset flag
|
|||
|
bFileFound = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return bFileFound;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
BOOL CALLBACK
|
|||
|
C2OpSysDlgProc(
|
|||
|
IN HWND hDlg, // window handle of the dialog box
|
|||
|
IN UINT message, // type of message
|
|||
|
IN WPARAM wParam,
|
|||
|
IN LPARAM lParam
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Window procedure for Operating System List Box
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Standard DlgProc arguments
|
|||
|
|
|||
|
ReturnValue:
|
|||
|
|
|||
|
TRUE the message was handled by this routine
|
|||
|
FALSE DefDialogProc should handle the message
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
LONG lItemCount = 0;
|
|||
|
static LPDWORD lpdwActionMask;
|
|||
|
DWORD dwAction;
|
|||
|
LONG lIndex;
|
|||
|
LONG lItems;
|
|||
|
|
|||
|
switch (message) {
|
|||
|
case WM_INITDIALOG:
|
|||
|
// bail out here if an invalid param was passed
|
|||
|
if (lParam == 0) {
|
|||
|
EndDialog (hDlg, IDCANCEL);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
// save pointer to param
|
|||
|
lpdwActionMask = (LPDWORD)lParam;
|
|||
|
|
|||
|
// set the dialog box caption and static text
|
|||
|
SetDlgItemText (hDlg, IDC_TEXT,
|
|||
|
GetStringResource (GetDllInstance(), IDS_OS_DLG_TEXT));
|
|||
|
SetWindowText (hDlg,
|
|||
|
GetStringResource (GetDllInstance(), IDS_OS_CAPTION));
|
|||
|
|
|||
|
// load list box with characteristics that are not C2
|
|||
|
if (IsDosOnSystem()) {
|
|||
|
lIndex = SendDlgItemMessage (hDlg, IDC_LIST_BOX,
|
|||
|
LB_ADDSTRING, 0,
|
|||
|
(LPARAM)GetStringResource (GetDllInstance(), IDS_DOS_ON_SYSTEM));
|
|||
|
if (lIndex != LB_ERR) {
|
|||
|
lItemCount++;
|
|||
|
SendDlgItemMessage (hDlg, IDC_LIST_BOX, LB_SETITEMDATA,
|
|||
|
(WPARAM)lIndex, (LPARAM)AV_DELETE_DOS);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!IsBootIniTimeoutZero()) {
|
|||
|
lIndex = SendDlgItemMessage (hDlg, IDC_LIST_BOX,
|
|||
|
LB_ADDSTRING, 0,
|
|||
|
(LPARAM)GetStringResource (GetDllInstance(), IDS_TIMEOUT_NOT_ZERO));
|
|||
|
if (lIndex != LB_ERR) {
|
|||
|
lItemCount++;
|
|||
|
SendDlgItemMessage (hDlg, IDC_LIST_BOX, LB_SETITEMDATA,
|
|||
|
(WPARAM)lIndex, (LPARAM)AV_SET_TIMEOUT);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// check for current system defined as default
|
|||
|
if (!IsCurrentSystemDefault()) {
|
|||
|
lIndex = SendDlgItemMessage (hDlg, IDC_LIST_BOX, LB_ADDSTRING, 0,
|
|||
|
(LPARAM)GetStringResource (GetDllInstance(), IDS_CURRENT_SYS_NOT_DEFAULT));
|
|||
|
if (lIndex != LB_ERR) {
|
|||
|
lItemCount++;
|
|||
|
SendDlgItemMessage (hDlg, IDC_LIST_BOX, LB_SETITEMDATA,
|
|||
|
(WPARAM)lIndex, (LPARAM)AV_SET_DEFAULT);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SetFocus (GetDlgItem (hDlg, IDOK)); // set focus to OK Button
|
|||
|
return FALSE; // we don't want Windows to set the focus
|
|||
|
|
|||
|
case WM_COMMAND:
|
|||
|
switch (LOWORD(wParam)){
|
|||
|
case IDC_C2:
|
|||
|
if (HIWORD(wParam) == BN_CLICKED) {
|
|||
|
// select all entries in the list box
|
|||
|
SendDlgItemMessage (hDlg, IDC_LIST_BOX,
|
|||
|
LB_SETSEL, TRUE, (LPARAM)-1);
|
|||
|
return TRUE;
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
case IDOK:
|
|||
|
dwAction = 0;
|
|||
|
// scan through list box to see which Items are to be
|
|||
|
// changed (if any)
|
|||
|
lItems = SendDlgItemMessage (hDlg, IDC_LIST_BOX, LB_GETCOUNT,
|
|||
|
0, 0);
|
|||
|
for (lIndex = 0; lIndex < lItems; lIndex++) {
|
|||
|
// if item is selected, then "or" it's value to the mask
|
|||
|
// i.e. set it's bit
|
|||
|
if (SendDlgItemMessage (hDlg, IDC_LIST_BOX, LB_GETSEL, (WPARAM)lIndex, 0) != 0) {
|
|||
|
dwAction |= (DWORD) SendDlgItemMessage (hDlg, IDC_LIST_BOX,
|
|||
|
LB_GETITEMDATA, (WPARAM)lIndex, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// update action value with flag bits
|
|||
|
*lpdwActionMask = dwAction;
|
|||
|
|
|||
|
// fall through to next case
|
|||
|
case IDCANCEL:
|
|||
|
if (HIWORD(wParam) == BN_CLICKED) {
|
|||
|
// exit and return button that caused exit
|
|||
|
EndDialog (hDlg, (int)LOWORD(wParam));
|
|||
|
return TRUE;
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
case IDC_HELP:
|
|||
|
PostMessage (GetParent(hDlg), UM_SHOW_CONTEXT_HELP, 0, 0);
|
|||
|
return TRUE;
|
|||
|
|
|||
|
default:
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
default:
|
|||
|
return (FALSE); // Didn't process the message
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LONG
|
|||
|
C2QueryOpSystems (
|
|||
|
IN LPARAM lParam
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Function called to find out the operating system(s) installed
|
|||
|
on the system. For C2 compliance, ONLY Windows NT is
|
|||
|
allowed on the system.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pointer to the Dll data block passed as an LPARAM.
|
|||
|
|
|||
|
ReturnValue:
|
|||
|
|
|||
|
ERROR_SUCCESS if the function succeeds otherwise a
|
|||
|
WIN32 error is returned if an error occurs
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PC2DLL_DATA pC2Data;
|
|||
|
|
|||
|
if (lParam != 0) {
|
|||
|
SET_WAIT_CURSOR;
|
|||
|
|
|||
|
if (!bTargetsDefined) {
|
|||
|
InitDriveNameTranslations();
|
|||
|
bTargetsDefined = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
pC2Data = (PC2DLL_DATA)lParam;
|
|||
|
pC2Data->lC2Compliance = SECURE; // assume true for now
|
|||
|
// check for DOS files found on system
|
|||
|
if (IsDosOnSystem()) {
|
|||
|
pC2Data->lC2Compliance = C2DLL_NOT_SECURE;
|
|||
|
lstrcpy (pC2Data->szStatusName,
|
|||
|
GetStringResource (GetDllInstance(), IDS_DOS_ON_SYSTEM));
|
|||
|
}
|
|||
|
|
|||
|
// check for boot.ini timeout > 0
|
|||
|
if (pC2Data->lC2Compliance == SECURE) {
|
|||
|
if (!IsBootIniTimeoutZero()) {
|
|||
|
pC2Data->lC2Compliance = C2DLL_NOT_SECURE;
|
|||
|
lstrcpy (pC2Data->szStatusName,
|
|||
|
GetStringResource (GetDllInstance(), IDS_TIMEOUT_NOT_ZERO));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// check for current system defined as default
|
|||
|
if (pC2Data->lC2Compliance == SECURE) {
|
|||
|
if (!IsCurrentSystemDefault()) {
|
|||
|
pC2Data->lC2Compliance = C2DLL_NOT_SECURE;
|
|||
|
lstrcpy (pC2Data->szStatusName,
|
|||
|
GetStringResource (GetDllInstance(), IDS_CURRENT_SYS_NOT_DEFAULT));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pC2Data->lC2Compliance == SECURE) {
|
|||
|
lstrcpy (pC2Data->szStatusName,
|
|||
|
GetStringResource (GetDllInstance(), IDS_OS_OK));
|
|||
|
}
|
|||
|
SET_ARROW_CURSOR;
|
|||
|
} else {
|
|||
|
return ERROR_BAD_ARGUMENTS;
|
|||
|
}
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
LONG
|
|||
|
C2SetOpSystems (
|
|||
|
IN LPARAM lParam
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Function called to change the current state of this configuration
|
|||
|
item based on an action code passed in the DLL data block. If
|
|||
|
this function successfully sets the state of the configuration
|
|||
|
item, then the C2 Compliance flag and the Status string to reflect
|
|||
|
the new value of the configuration item.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pointer to the Dll data block passed as an LPARAM.
|
|||
|
|
|||
|
ReturnValue:
|
|||
|
|
|||
|
ERROR_SUCCESS if the function succeeds otherwise a
|
|||
|
WIN32 error is returned if an error occurs
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PC2DLL_DATA pC2Data;
|
|||
|
|
|||
|
if (lParam != 0) {
|
|||
|
pC2Data = (PC2DLL_DATA)lParam;
|
|||
|
if ((pC2Data->lActionCode == AC_UPDATE) && (pC2Data->lActionValue != 0)) {
|
|||
|
SET_WAIT_CURSOR;
|
|||
|
|
|||
|
if (pC2Data->lActionValue & AV_DELETE_DOS) {
|
|||
|
if (DisplayDllMessageBox (
|
|||
|
pC2Data->hWnd,
|
|||
|
IDS_OS_DELETE_DOS_FILES,
|
|||
|
IDS_OS_CAPTION,
|
|||
|
MBOKCANCEL_EXCLAIM | MB_DEFBUTTON2) == IDOK) {
|
|||
|
DeleteDosFiles();
|
|||
|
}
|
|||
|
}
|
|||
|
if (pC2Data->lActionValue & AV_SET_TIMEOUT) {
|
|||
|
if (IsIntelProcessor()) {
|
|||
|
if (DisplayDllMessageBox (
|
|||
|
pC2Data->hWnd,
|
|||
|
IDS_OS_ZERO_BOOT_TIMEOUT,
|
|||
|
IDS_OS_CAPTION,
|
|||
|
MBOKCANCEL_EXCLAIM | MB_DEFBUTTON2) == IDOK) {
|
|||
|
SetBootIniTimeoutToZero();
|
|||
|
}
|
|||
|
} else {
|
|||
|
DisplayDllMessageBox (
|
|||
|
pC2Data->hWnd,
|
|||
|
IDS_OS_RISC_BOOT_TIMEOUT,
|
|||
|
IDS_OS_CAPTION,
|
|||
|
MBOK_EXCLAIM);
|
|||
|
}
|
|||
|
}
|
|||
|
if (pC2Data->lActionValue & AV_SET_DEFAULT) {
|
|||
|
SetBootDefaultToCurrentSystem ();
|
|||
|
}
|
|||
|
|
|||
|
// now check to see what happened
|
|||
|
|
|||
|
pC2Data->lC2Compliance = SECURE; // assume true for now
|
|||
|
// check for DOS files found on system
|
|||
|
if (IsDosOnSystem()) {
|
|||
|
pC2Data->lC2Compliance = C2DLL_NOT_SECURE;
|
|||
|
lstrcpy (pC2Data->szStatusName,
|
|||
|
GetStringResource (GetDllInstance(), IDS_DOS_ON_SYSTEM));
|
|||
|
}
|
|||
|
|
|||
|
// check for boot.ini timeout > 0
|
|||
|
if (pC2Data->lC2Compliance == SECURE) {
|
|||
|
if (!IsBootIniTimeoutZero()) {
|
|||
|
pC2Data->lC2Compliance = C2DLL_NOT_SECURE;
|
|||
|
lstrcpy (pC2Data->szStatusName,
|
|||
|
GetStringResource (GetDllInstance(), IDS_TIMEOUT_NOT_ZERO));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// check for current system defined as default
|
|||
|
if (pC2Data->lC2Compliance == SECURE) {
|
|||
|
if (!IsCurrentSystemDefault()) {
|
|||
|
pC2Data->lC2Compliance = C2DLL_NOT_SECURE;
|
|||
|
lstrcpy (pC2Data->szStatusName,
|
|||
|
GetStringResource (GetDllInstance(), IDS_CURRENT_SYS_NOT_DEFAULT));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pC2Data->lC2Compliance == SECURE) {
|
|||
|
lstrcpy (pC2Data->szStatusName,
|
|||
|
GetStringResource (GetDllInstance(), IDS_OS_OK));
|
|||
|
}
|
|||
|
SET_ARROW_CURSOR;
|
|||
|
}
|
|||
|
|
|||
|
pC2Data->lActionCode = 0;
|
|||
|
|
|||
|
} else {
|
|||
|
return ERROR_BAD_ARGUMENTS;
|
|||
|
}
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
LONG
|
|||
|
C2DisplayOpSystems (
|
|||
|
IN LPARAM lParam
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Function called to display more information on the configuration
|
|||
|
item and provide the user with the option to change the current
|
|||
|
setting (if appropriate). If the User "OK's" out of the UI,
|
|||
|
then the action code field in the DLL data block is set to the
|
|||
|
appropriate (and configuration item-specific) action code so the
|
|||
|
"Set" function can be called to perform the desired action. If
|
|||
|
the user Cancels out of the UI, then the Action code field is
|
|||
|
set to 0 (no action) and no action is performed.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pointer to the Dll data block passed as an LPARAM.
|
|||
|
|
|||
|
ReturnValue:
|
|||
|
|
|||
|
ERROR_SUCCESS if the function succeeds otherwise a
|
|||
|
WIN32 error is returned if an error occurs
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PC2DLL_DATA pC2Data;
|
|||
|
INT nDlgBoxReturn;
|
|||
|
LONG lDlgBoxParam;
|
|||
|
|
|||
|
if (lParam != 0) {
|
|||
|
pC2Data = (PC2DLL_DATA)lParam;
|
|||
|
// check the C2 Compliance flag to see if the list box or
|
|||
|
// message box should be displayed
|
|||
|
if (pC2Data->lC2Compliance == SECURE) {
|
|||
|
// all volumes are OK so just pop a message box
|
|||
|
lDlgBoxParam = 0;
|
|||
|
DisplayDllMessageBox (
|
|||
|
pC2Data->hWnd,
|
|||
|
IDS_OS_OK,
|
|||
|
IDS_OS_CAPTION,
|
|||
|
MBOK_INFO);
|
|||
|
pC2Data->lActionCode = 0;
|
|||
|
pC2Data->lActionValue = 0;
|
|||
|
} else {
|
|||
|
//one or more volumes are not NTFS so display the list box
|
|||
|
// listing the ones that arent.
|
|||
|
nDlgBoxReturn = DialogBoxParam (
|
|||
|
GetDllInstance(),
|
|||
|
MAKEINTRESOURCE (IDD_LIST_DLG),
|
|||
|
pC2Data->hWnd,
|
|||
|
C2OpSysDlgProc,
|
|||
|
(LPARAM)&lDlgBoxParam);
|
|||
|
if (nDlgBoxReturn == IDOK) {
|
|||
|
pC2Data->lActionCode = 1;
|
|||
|
pC2Data->lActionValue = lDlgBoxParam;
|
|||
|
} else {
|
|||
|
pC2Data->lActionCode = 0;
|
|||
|
pC2Data->lActionValue = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
return ERROR_BAD_ARGUMENTS;
|
|||
|
}
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|