mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1384 lines
32 KiB
1384 lines
32 KiB
/*++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Utils.C
|
|
|
|
Abstract:
|
|
|
|
a collection of utility functions used by other routines.
|
|
|
|
Author:
|
|
|
|
Bob Watson (a-robw)
|
|
|
|
Revision History:
|
|
|
|
24 Aug 1994 Written
|
|
|
|
--*/
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <io.h>
|
|
#include <fcntl.h>
|
|
#include <sys\stat.h>
|
|
#include "c2inc.h"
|
|
#include "c2utils.h"
|
|
#include "strings.h"
|
|
|
|
#define NUM_BUFS 4
|
|
|
|
//
|
|
// local "helper" functions
|
|
//
|
|
|
|
static
|
|
BOOL
|
|
MediaPresent (
|
|
IN LPCTSTR szPath,
|
|
IN BOOL bPresentAndValid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
determines if the specified path is present and available
|
|
|
|
Arguments:
|
|
|
|
IN LPCTSTR szPath
|
|
path to examine (Must be a DOS path)
|
|
|
|
Return Value:
|
|
|
|
TRUE: path is available
|
|
FALSE: unable to find/open path
|
|
|
|
--*/
|
|
{
|
|
BOOL bMediaPresent = FALSE;
|
|
TCHAR szDev[8];
|
|
DWORD dwBytes = 0;
|
|
DWORD dwAttrib;
|
|
DWORD dwLastError = ERROR_SUCCESS;
|
|
UINT nErrorMode;
|
|
|
|
if (!IsUncPath(szPath)) {
|
|
// build device name string
|
|
szDev[0] = szPath[0];
|
|
szDev[1] = cColon;
|
|
szDev[2] = cBackslash;
|
|
szDev[3] = 0;
|
|
|
|
// disable windows error message popup
|
|
nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
|
|
|
dwAttrib = QuietGetFileAttributes (szDev);
|
|
if ((dwAttrib != 0xFFFFFFFF) && ((dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) {
|
|
// if the root dir is a dir, then it must be present and formatted
|
|
bMediaPresent = TRUE;
|
|
} else {
|
|
// otherwise see if it's present and not formatted or not present
|
|
dwLastError = GetMyLastError();
|
|
if (dwLastError == ERROR_NOT_READY) {
|
|
// then no disk in drive
|
|
bMediaPresent = FALSE;
|
|
} else if ((dwLastError == ERROR_FILE_NOT_FOUND) ||
|
|
(dwLastError == ERROR_UNRECOGNIZED_MEDIA)) {
|
|
// then and UNFORMATTED disk is in drive
|
|
if (bPresentAndValid) {
|
|
// this isn't good enough if it's supposed to be formatted
|
|
bMediaPresent = FALSE;
|
|
} else {
|
|
// we're just looking for a disk so this is OK
|
|
bMediaPresent = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetErrorMode (nErrorMode); // restore old error mode
|
|
} else {
|
|
// assume UNC path devices are present
|
|
bMediaPresent = TRUE;
|
|
}
|
|
return bMediaPresent;
|
|
}
|
|
|
|
//
|
|
// Global functions
|
|
//
|
|
DWORD
|
|
QuietGetFileAttributes (
|
|
IN LPCTSTR lpszFileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads the attributes of the path in lpzsFileName without triggering
|
|
any Windows error dialog if there's an OS error (e.g. drive not
|
|
ready)
|
|
|
|
Arguments:
|
|
|
|
IN LPCTSTR lpszFileName
|
|
path to retrieve attributes from
|
|
|
|
Return Value:
|
|
|
|
file attributes DWORD returned from GetFileAttributes or
|
|
0xFFFFFFFF if unable to open path.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwReturn;
|
|
UINT nErrorMode;
|
|
unsigned uAttrib; // used in WIN 16 builds only
|
|
|
|
// disable windows error message popup
|
|
nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
|
#ifdef WIN32
|
|
dwReturn = GetFileAttributes (lpszFileName);
|
|
uAttrib = 0; // to prevent unused var error in WIN32 build
|
|
#else // WIN16
|
|
|
|
if (_dos_getfileattr (lpszFileName, &uAttrib) == 0) {
|
|
dwReturn = uAttrib;
|
|
} else {
|
|
dwReturn = 0xFFFFFFFF;
|
|
SetLastError (ERROR_FILE_NOT_FOUND);
|
|
}
|
|
#endif
|
|
SetErrorMode (nErrorMode); // restore old error mode
|
|
return dwReturn;
|
|
}
|
|
|
|
BOOL
|
|
EnableSecurityPriv (
|
|
)
|
|
{
|
|
HANDLE hToken;
|
|
LUID SeSecurityNameValue;
|
|
TOKEN_PRIVILEGES tkp;
|
|
|
|
/* Retrieve a handle of the access token. */
|
|
|
|
if (!OpenProcessToken(GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
&hToken)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Enable the SE_SECURITY_NAME privilege
|
|
*/
|
|
|
|
if (!LookupPrivilegeValue((LPCTSTR) NULL,
|
|
SE_SECURITY_NAME,
|
|
&SeSecurityNameValue)) {
|
|
return FALSE;
|
|
}
|
|
|
|
tkp.PrivilegeCount = 1;
|
|
tkp.Privileges[0].Luid = SeSecurityNameValue;
|
|
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
AdjustTokenPrivileges(hToken,
|
|
FALSE,
|
|
&tkp,
|
|
sizeof(TOKEN_PRIVILEGES),
|
|
(PTOKEN_PRIVILEGES) NULL,
|
|
(PDWORD) NULL);
|
|
|
|
if (GetLastError() != ERROR_SUCCESS) {
|
|
return FALSE;
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
EnableAllPriv (
|
|
)
|
|
/*++
|
|
|
|
|
|
Routine Description:
|
|
|
|
This routine enables all privileges in the token.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
HANDLE Token;
|
|
ULONG ReturnLength, Index;
|
|
PTOKEN_PRIVILEGES NewState;
|
|
BOOL Result;
|
|
|
|
Token = NULL;
|
|
NewState = NULL;
|
|
|
|
Result = OpenProcessToken( GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
&Token
|
|
);
|
|
if (Result) {
|
|
ReturnLength = 4096;
|
|
NewState = malloc( ReturnLength );
|
|
Result = (BOOL)(NewState != NULL);
|
|
if (Result) {
|
|
Result = GetTokenInformation( Token, // TokenHandle
|
|
TokenPrivileges, // TokenInformationClass
|
|
NewState, // TokenInformation
|
|
ReturnLength, // TokenInformationLength
|
|
&ReturnLength // ReturnLength
|
|
);
|
|
|
|
if (Result) {
|
|
//
|
|
// Set the state settings so that all privileges are enabled...
|
|
//
|
|
|
|
if (NewState->PrivilegeCount > 0) {
|
|
for (Index = 0; Index < NewState->PrivilegeCount; Index++ ) {
|
|
NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
|
|
}
|
|
}
|
|
|
|
Result = AdjustTokenPrivileges( Token, // TokenHandle
|
|
FALSE, // DisableAllPrivileges
|
|
NewState, // NewState (OPTIONAL)
|
|
ReturnLength, // BufferLength
|
|
NULL, // PreviousState (OPTIONAL)
|
|
&ReturnLength // ReturnLength
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NewState != NULL) {
|
|
free( NewState );
|
|
}
|
|
|
|
if (Token != NULL) {
|
|
CloseHandle( Token );
|
|
}
|
|
|
|
return( Result );
|
|
}
|
|
|
|
#ifdef _UNICODE
|
|
FARPROC
|
|
GetProcAddressW (
|
|
IN HMODULE hModule,
|
|
IN LPCWSTR lpwszProc
|
|
)
|
|
{
|
|
LPSTR szProc;
|
|
LONG lProcLen;
|
|
LONG lAnsiLen;
|
|
FARPROC lpReturn;
|
|
|
|
lProcLen = lstrlen(lpwszProc);
|
|
szProc = GLOBAL_ALLOC (lProcLen + 1);
|
|
|
|
if (szProc != NULL) {
|
|
lAnsiLen = wcstombs (szProc, lpwszProc, lProcLen);
|
|
if (lAnsiLen == lProcLen) {
|
|
lpReturn = GetProcAddress (
|
|
hModule,
|
|
szProc);
|
|
} else {
|
|
lpReturn = NULL;
|
|
}
|
|
// free allocated string buffer
|
|
GLOBAL_FREE_IF_ALLOC (szProc);
|
|
} else {
|
|
lpReturn = NULL;
|
|
}
|
|
return lpReturn;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _UNICODE
|
|
HFILE
|
|
OpenFileW(
|
|
LPCTSTR lpwszFile,
|
|
LPWOFSTRUCT lpWOpenBuff,
|
|
UINT fuMode
|
|
)
|
|
{
|
|
LPSTR szFileName;
|
|
OFSTRUCT ofStruct;
|
|
HFILE hReturn;
|
|
LONG lFileNameLen;
|
|
LONG lAnsiNameLen;
|
|
|
|
// check arguments
|
|
if ((lpwszFile == NULL) || (lpWOpenBuff == NULL)) {
|
|
SetLastError (ERROR_INVALID_PARAMETER);
|
|
hReturn = HFILE_ERROR;
|
|
} else {
|
|
lFileNameLen = lstrlen(lpwszFile);
|
|
szFileName = GLOBAL_ALLOC (lFileNameLen + 1);
|
|
if (szFileName != NULL) {
|
|
lAnsiNameLen = wcstombs (szFileName, lpwszFile, lFileNameLen);
|
|
if (lAnsiNameLen == lFileNameLen) {
|
|
hReturn = OpenFile (
|
|
szFileName,
|
|
&ofStruct,
|
|
fuMode);
|
|
|
|
if (hReturn != HFILE_ERROR){
|
|
lpWOpenBuff->cBytes = ofStruct.cBytes;
|
|
lpWOpenBuff->fFixedDisk = ofStruct.fFixedDisk;
|
|
lpWOpenBuff->nErrCode = ofStruct.nErrCode;
|
|
lpWOpenBuff->Reserved1 = ofStruct.Reserved1;
|
|
lpWOpenBuff->Reserved2 = ofStruct.Reserved2;
|
|
lAnsiNameLen = strlen (ofStruct.szPathName);
|
|
mbstowcs (lpWOpenBuff->szPathName,
|
|
ofStruct.szPathName, lAnsiNameLen);
|
|
}
|
|
}
|
|
GLOBAL_FREE_IF_ALLOC (szFileName);
|
|
} else {
|
|
SetLastError (ERROR_OUTOFMEMORY);
|
|
hReturn = HFILE_ERROR;
|
|
}
|
|
}
|
|
return hReturn;
|
|
}
|
|
#endif
|
|
|
|
BOOL
|
|
TrimSpaces (
|
|
IN OUT LPTSTR szString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Trims leading and trailing spaces from szString argument, modifying
|
|
the buffer passed in
|
|
|
|
Arguments:
|
|
|
|
IN OUT LPTSTR szString
|
|
buffer to process
|
|
|
|
Return Value:
|
|
|
|
TRUE if string was modified
|
|
FALSE if not
|
|
|
|
--*/
|
|
{
|
|
LPTSTR szSource;
|
|
LPTSTR szDest;
|
|
LPTSTR szLast;
|
|
BOOL bChars;
|
|
|
|
szLast = szSource = szDest = szString;
|
|
bChars = FALSE;
|
|
|
|
while (*szSource != 0) {
|
|
// skip leading non-space chars
|
|
if (*szSource > cSpace) {
|
|
szLast = szDest;
|
|
bChars = TRUE;
|
|
}
|
|
if (bChars) {
|
|
// remember last non-space character
|
|
// copy source to destination & increment both
|
|
*szDest++ = *szSource++;
|
|
} else {
|
|
szSource++;
|
|
}
|
|
}
|
|
|
|
if (bChars) {
|
|
*++szLast = 0; // terminate after last non-space char
|
|
} else {
|
|
// string was all spaces so return an empty (0-len) string
|
|
*szString = 0;
|
|
}
|
|
|
|
return (szLast != szSource);
|
|
}
|
|
|
|
BOOL
|
|
IsUncPath (
|
|
IN LPCTSTR szPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
examines path as a string looking for "tell-tale" double
|
|
backslash indicating the machine name syntax of a UNC path
|
|
|
|
Arguments:
|
|
|
|
IN LPCTSTR szPath
|
|
path to examine
|
|
|
|
Return Value:
|
|
|
|
TRUE if \\ found at start of string
|
|
FALSE if not
|
|
|
|
--*/
|
|
{
|
|
LPTSTR szPtChar;
|
|
|
|
szPtChar = (LPTSTR)szPath;
|
|
if (*szPtChar == cBackslash) {
|
|
if (*++szPtChar == cBackslash) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
LPTSTR
|
|
GetFileNameFromPath (
|
|
IN LPCTSTR szPath
|
|
)
|
|
{
|
|
LPTSTR szLastBs;
|
|
LPTSTR szThisChar;
|
|
|
|
szLastBs = (LPTSTR)szPath;
|
|
|
|
for (szThisChar = (LPTSTR)szPath; *szThisChar != 0; szThisChar++) {
|
|
if (*szThisChar == cBackslash) {
|
|
szLastBs = szThisChar;
|
|
}
|
|
}
|
|
if (*szLastBs == cBackslash) {
|
|
szLastBs++;
|
|
}
|
|
return szLastBs;
|
|
}
|
|
|
|
BOOL
|
|
CenterWindow (
|
|
HWND hwndChild,
|
|
HWND hwndParent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Centers the child window in the Parent window
|
|
|
|
Arguments:
|
|
|
|
HWND hwndChild,
|
|
handle of child window to center
|
|
|
|
HWND hwndParent
|
|
handle of parent window to center child window in
|
|
|
|
ReturnValue:
|
|
|
|
Return value of SetWindowPos
|
|
|
|
--*/
|
|
{
|
|
RECT rChild, rParent;
|
|
LONG wChild, hChild, wParent, hParent;
|
|
LONG wScreen, hScreen, xNew, yNew;
|
|
HDC hdc;
|
|
|
|
// Get the Height and Width of the child window
|
|
GetWindowRect (hwndChild, &rChild);
|
|
wChild = rChild.right - rChild.left;
|
|
hChild = rChild.bottom - rChild.top;
|
|
|
|
// Get the Height and Width of the parent window
|
|
GetWindowRect (hwndParent, &rParent);
|
|
wParent = rParent.right - rParent.left;
|
|
hParent = rParent.bottom - rParent.top;
|
|
|
|
// Get the display limits
|
|
hdc = GetDC (hwndChild);
|
|
wScreen = GetDeviceCaps (hdc, HORZRES);
|
|
hScreen = GetDeviceCaps (hdc, VERTRES);
|
|
ReleaseDC (hwndChild, hdc);
|
|
|
|
// Calculate new X position, then adjust for screen
|
|
xNew = rParent.left + ((wParent - wChild) /2);
|
|
if (xNew < 0) {
|
|
xNew = 0;
|
|
} else if ((xNew+wChild) > wScreen) {
|
|
xNew = wScreen - wChild;
|
|
}
|
|
|
|
// Calculate new Y position, then adjust for screen
|
|
yNew = rParent.top + ((hParent - hChild) /2);
|
|
if (yNew < 0) {
|
|
yNew = 0;
|
|
} else if ((yNew+hChild) > hScreen) {
|
|
yNew = hScreen - hChild;
|
|
}
|
|
|
|
// Set it, and return
|
|
return SetWindowPos (hwndChild, NULL,
|
|
(int)xNew, (int)yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|
|
|
|
UINT
|
|
GetDriveTypeFromDosPath (
|
|
IN LPCTSTR szDosPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Strips the filename and path from the path in the argument and returns
|
|
the drive type as returned by the GetDriveType Win32 API fn.
|
|
|
|
Arguments:
|
|
|
|
IN LPCTSTR szDosPath
|
|
dos path in the format: <Drive>:\path... This format is NOT checked
|
|
by the function!
|
|
|
|
Return Value:
|
|
|
|
DRIVE TYPE value returned by the GetDriveType API.
|
|
|
|
--*/
|
|
{
|
|
#ifdef WIN32
|
|
TCHAR szRootDir[4];
|
|
|
|
szRootDir[0] = szDosPath[0];
|
|
szRootDir[1] = cColon;
|
|
szRootDir[2] = cBackslash;
|
|
szRootDir[3] = 0;
|
|
#else // win16 version isn't as robust
|
|
int szRootDir; // not really an SZ, but it keeps the call compatible
|
|
TCHAR szLocalPath[4];
|
|
|
|
szLocalPath[0] = szDosPath[0];
|
|
szLocalPath[1] = 0;
|
|
|
|
_strupr(szLocalPath);
|
|
szRootDir = szLocalPath[0] - cA;
|
|
#endif
|
|
|
|
return (GetDriveType(szRootDir));
|
|
}
|
|
|
|
LPCTSTR
|
|
GetItemFromIniEntry (
|
|
IN LPCTSTR szEntry,
|
|
IN DWORD dwItem
|
|
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
returns nth item from comma separated list returned from
|
|
inf file. leaves (double)quoted strings intact.
|
|
|
|
Arguments:
|
|
|
|
IN LPCTSTR szEntry
|
|
entry string returned from INF file
|
|
|
|
IN DWORD dwItem
|
|
1-based index indicating which item to return. (i.e. 1= first item
|
|
in list, 2= second, etc.)
|
|
|
|
|
|
Return Value:
|
|
|
|
pointer to buffer containing desired entry in string. Note, this
|
|
routine may only be called 4 times before the string
|
|
buffer is re-used. (i.e. don't use this function more than
|
|
4 times in single function call!!)
|
|
|
|
--*/
|
|
{
|
|
static TCHAR szReturnBuffer[4][MAX_PATH];
|
|
static LONG dwBuff;
|
|
LPTSTR szSource, szDest;
|
|
DWORD dwThisItem;
|
|
|
|
dwBuff = ++dwBuff % 4; // wrap buffer index
|
|
|
|
szSource = (LPTSTR)szEntry;
|
|
szDest = &szReturnBuffer[dwBuff][0];
|
|
|
|
// clear previous contents
|
|
memset (szDest, 0, (MAX_PATH * sizeof(TCHAR)));
|
|
|
|
// go past ini key
|
|
while ((*szSource != cEqual) && (*szSource != 0)) szSource++;
|
|
if (*szSource == 0){
|
|
// no equals found so start at beginning
|
|
// presumably this is just the "value"
|
|
szSource = (LPTSTR)szEntry;
|
|
} else {
|
|
szSource++;
|
|
}
|
|
dwThisItem = 1;
|
|
while (dwThisItem < dwItem) {
|
|
if (*szSource != 0) {
|
|
while ((*szSource != cComma) && (*szSource != 0)) {
|
|
if (*szSource == cDoubleQuote) {
|
|
// if this is a quote, then go to the close quote
|
|
szSource++;
|
|
while ((*szSource != cDoubleQuote) && (*szSource != 0)) szSource++;
|
|
}
|
|
if (*szSource != 0) szSource++;
|
|
}
|
|
}
|
|
dwThisItem++;
|
|
if (*szSource != 0) szSource++;
|
|
}
|
|
// copy this entry to the return buffer
|
|
if (*szSource != 0) {
|
|
while ((*szSource != cComma) && (*szSource != 0)) {
|
|
if (*szSource == cDoubleQuote) {
|
|
// if this is a quote, then go to the close quote
|
|
// don't copy quotes!
|
|
szSource++;
|
|
while ((*szSource != cDoubleQuote) && (*szSource != 0)) {
|
|
*szDest++ = *szSource++;
|
|
}
|
|
if (*szSource != 0) szSource++;
|
|
} else {
|
|
*szDest++ = *szSource++;
|
|
}
|
|
}
|
|
*szDest = 0;
|
|
}
|
|
|
|
// remove any leading and/or trailing spaces
|
|
|
|
TrimSpaces (&szReturnBuffer[dwBuff][0]);
|
|
|
|
return &szReturnBuffer[dwBuff][0];
|
|
}
|
|
|
|
LPCTSTR
|
|
GetStringResource (
|
|
IN HANDLE hInstance,
|
|
IN UINT nId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
look up string resource and return string
|
|
|
|
Arguments:
|
|
|
|
IN UINT nId
|
|
Resource ID of string to look up
|
|
|
|
Return Value:
|
|
|
|
pointer to string referenced by ID in arg list
|
|
|
|
--*/
|
|
{
|
|
static TCHAR szBufArray[NUM_BUFS][SMALL_BUFFER_SIZE];
|
|
static DWORD dwIndex;
|
|
LPTSTR szBuffer;
|
|
DWORD dwLength;
|
|
|
|
HANDLE hMod;
|
|
|
|
if (hInstance != NULL) {
|
|
hMod = hInstance;
|
|
} else {
|
|
hMod = GetModuleHandle(NULL);
|
|
}
|
|
|
|
dwIndex++;
|
|
dwIndex %= NUM_BUFS;
|
|
szBuffer = &szBufArray[dwIndex][0];
|
|
|
|
// clear previous contents
|
|
memset (szBuffer, 0, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
|
|
|
dwLength = LoadString (
|
|
hMod,
|
|
nId,
|
|
szBuffer,
|
|
SMALL_BUFFER_SIZE);
|
|
|
|
return (LPCTSTR)szBuffer;
|
|
}
|
|
|
|
LPCTSTR
|
|
GetQuotedStringResource (
|
|
IN HANDLE hInstance,
|
|
IN UINT nId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
look up string resource and return string inside double quotes
|
|
|
|
Arguments:
|
|
|
|
IN HANDLE hInstance
|
|
handle to application instance
|
|
|
|
IN UINT nId
|
|
Resource ID of string to look up
|
|
|
|
Return Value:
|
|
|
|
pointer to string referenced by ID in arg list
|
|
|
|
--*/
|
|
{
|
|
static TCHAR szBufArray[NUM_BUFS][SMALL_BUFFER_SIZE];
|
|
static DWORD dwIndex;
|
|
LPTSTR szBuffer;
|
|
DWORD dwLength;
|
|
|
|
HANDLE hMod;
|
|
|
|
if (hInstance != NULL) {
|
|
hMod = hInstance;
|
|
} else {
|
|
hMod = GetModuleHandle(NULL);
|
|
}
|
|
|
|
dwIndex++;
|
|
dwIndex %= NUM_BUFS;
|
|
szBuffer = &szBufArray[dwIndex][0];
|
|
|
|
// clear previous contents
|
|
memset (szBuffer, 0, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
|
|
|
szBuffer[0] = cSpace;
|
|
szBuffer[1] = cSpace;
|
|
szBuffer[2] = cDoubleQuote;
|
|
|
|
dwLength = LoadString (
|
|
hMod,
|
|
nId,
|
|
&szBuffer[3],
|
|
SMALL_BUFFER_SIZE);
|
|
|
|
lstrcat(szBuffer, cszDoubleQuote);
|
|
|
|
return (LPCTSTR)szBuffer;
|
|
}
|
|
|
|
LPCTSTR
|
|
EnquoteString (
|
|
IN LPCTSTR szInString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
return the input string wrapped in double quotes
|
|
|
|
Arguments:
|
|
|
|
IN LPCTSTR szInString
|
|
|
|
Return Value:
|
|
|
|
pointer to string buffer containing a copy of szInString enclosed
|
|
in double quotes
|
|
|
|
--*/
|
|
{
|
|
static TCHAR szBufArray[NUM_BUFS][SMALL_BUFFER_SIZE];
|
|
static DWORD dwIndex;
|
|
LPTSTR szBuffer;
|
|
|
|
dwIndex++;
|
|
dwIndex %= NUM_BUFS;
|
|
szBuffer = &szBufArray[dwIndex][0];
|
|
|
|
// clear previous contents
|
|
memset (szBuffer, 0, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
|
|
|
|
szBuffer[0] = cSpace;
|
|
szBuffer[1] = cSpace;
|
|
szBuffer[2] = cDoubleQuote;
|
|
lstrcpy (&szBuffer[3], szInString);
|
|
lstrcat (szBuffer, cszDoubleQuote);
|
|
|
|
return (LPCTSTR)szBuffer;
|
|
}
|
|
|
|
LONG
|
|
GetExpandedFileName (
|
|
IN LPTSTR szInFileName,
|
|
IN DWORD dwMaxExpandedSize,
|
|
OUT LPTSTR szExpandedFileName,
|
|
OUT LPTSTR *pFileNamePart
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
expands any environment variables in InFileName, then gets the
|
|
fully qualified pathname of the result and returns that in the
|
|
buffer provided by the caller
|
|
|
|
Arguments:
|
|
|
|
IN LPTSTR szInFileName input file string to expand
|
|
IN DWORD dwMaxExpandedSize size of output Buffer
|
|
OUT LPTSTR szExpandedFileName buffer to recieve expanded name
|
|
OUT LPTSTR *pFileNamePart pointer to filename in output buffer
|
|
|
|
ReturnValue:
|
|
|
|
WIN32 error status of procedure
|
|
|
|
--*/
|
|
{
|
|
LPTSTR szEnvBuffer;
|
|
|
|
LPTSTR szPathReturn;
|
|
|
|
LONG lStatus;
|
|
DWORD dwSize;
|
|
|
|
// validate arguments
|
|
|
|
if ((szInFileName != NULL) &&
|
|
(dwMaxExpandedSize != 0)) {
|
|
|
|
#ifdef WIN32
|
|
|
|
// allocate working buffers
|
|
|
|
szEnvBuffer = (LPTSTR)GLOBAL_ALLOC (((dwMaxExpandedSize + 1) * sizeof(TCHAR)));
|
|
|
|
if (szEnvBuffer != NULL) {
|
|
|
|
// expand env. strings if any
|
|
|
|
dwSize = ExpandEnvironmentStrings (
|
|
szInFileName,
|
|
szEnvBuffer,
|
|
(GlobalSize(szEnvBuffer) / sizeof(TCHAR)));
|
|
|
|
if (dwSize != 0) {
|
|
// get full pathname
|
|
CLEAR_FIRST_FOUR_BYTES(szExpandedFileName);
|
|
if (GetFullPathName (
|
|
szEnvBuffer,
|
|
dwMaxExpandedSize,
|
|
szExpandedFileName,
|
|
&szPathReturn) > 0) {
|
|
if (pFileNamePart != NULL) {
|
|
*pFileNamePart = szPathReturn;
|
|
}
|
|
lStatus = ERROR_SUCCESS;
|
|
} else {
|
|
// unable to get full path name
|
|
lStatus = ERROR_BAD_PATHNAME;
|
|
}
|
|
|
|
} else {
|
|
// error expanding env strings
|
|
lStatus = GetMyLastError();
|
|
}
|
|
} else {
|
|
lStatus == ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
GLOBAL_FREE_IF_ALLOC (szEnvBuffer);
|
|
#else // if WIN16
|
|
strncpy (szExpandedFileName, szInFileName, (size_t)dwMaxExpandedSize);
|
|
lStatus = ERROR_SUCCESS;
|
|
// unreferenced vars in WIN 16 mode
|
|
dwSize = dwSize;
|
|
szEnvBuffer = szEnvBuffer;
|
|
szPathReturn = szPathReturn;
|
|
#endif
|
|
} else {
|
|
lStatus = ERROR_INVALID_PARAMETER; // bad argument
|
|
}
|
|
|
|
return lStatus;
|
|
}
|
|
|
|
LONG
|
|
CreateDirectoryFromPath (
|
|
IN LPCTSTR szPath,
|
|
IN LPSECURITY_ATTRIBUTES lpSA
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the directory specified in szPath and any other "higher"
|
|
directories in the specified path that don't exist.
|
|
|
|
Arguments:
|
|
|
|
IN LPCTSTR szPath
|
|
directory path to create (assumed to be a DOS path, not a UNC)
|
|
|
|
IN LPSECURITY_ATTRIBUTES lpSA
|
|
pointer to security attributes argument used by CreateDirectory
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE (non-zero) if directory(ies) created
|
|
FALSE if error (GetMyLastError to find out why)
|
|
|
|
--*/
|
|
{
|
|
LPTSTR szLocalPath;
|
|
LPTSTR szEnd;
|
|
LONG lReturn = 0L;
|
|
|
|
szLocalPath = (LPTSTR)GLOBAL_ALLOC (MAX_PATH_BYTES);
|
|
|
|
if (szLocalPath == NULL) {
|
|
SetLastError (ERROR_OUTOFMEMORY);
|
|
return 0;
|
|
} else {
|
|
// so far so good...
|
|
SetLastError (ERROR_SUCCESS); // initialize error value to SUCCESS
|
|
}
|
|
|
|
GetExpandedFileName (
|
|
(LPTSTR)szPath,
|
|
MAX_PATH,
|
|
szLocalPath,
|
|
NULL);
|
|
|
|
szEnd = &szLocalPath[3];
|
|
|
|
if (*szEnd != 0) {
|
|
// then there are sub dirs to create
|
|
while (*szEnd != 0) {
|
|
// go to next backslash
|
|
while ((*szEnd != cBackslash) && (*szEnd != 0)) szEnd++;
|
|
if (*szEnd == cBackslash) {
|
|
// terminate path here and create directory
|
|
*szEnd = 0;
|
|
if (!CreateDirectory (szLocalPath, lpSA)) {
|
|
// see what the error was and "adjust" it if necessary
|
|
if (GetMyLastError() == ERROR_ALREADY_EXISTS) {
|
|
// this is OK
|
|
SetLastError (ERROR_SUCCESS);
|
|
} else {
|
|
lReturn = 0;
|
|
}
|
|
} else {
|
|
// directory created successfully so update count
|
|
lReturn++;
|
|
}
|
|
// replace backslash and go to next dir
|
|
*szEnd++ = cBackslash;
|
|
}
|
|
}
|
|
// create last dir in path now
|
|
if (!CreateDirectory (szLocalPath, lpSA)) {
|
|
// see what the error was and "adjust" it if necessary
|
|
if (GetMyLastError() == ERROR_ALREADY_EXISTS) {
|
|
// this is OK
|
|
SetLastError (ERROR_SUCCESS);
|
|
lReturn++;
|
|
} else {
|
|
lReturn = 0;
|
|
}
|
|
} else {
|
|
// directory created successfully
|
|
lReturn++;
|
|
}
|
|
} else {
|
|
// else this is a root dir only so return success.
|
|
lReturn = 1;
|
|
}
|
|
GLOBAL_FREE_IF_ALLOC (szLocalPath);
|
|
return lReturn;
|
|
}
|
|
|
|
BOOL
|
|
FileExists (
|
|
IN LPCTSTR szPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
returns TRUE if the file in the path argument exists (NOTE: that
|
|
the file is not actually opened to save time, rather the
|
|
directory entry is read in order to determine existence)
|
|
|
|
Arguments:
|
|
|
|
szPath pointer to filename to look up
|
|
|
|
Return Value:
|
|
|
|
TRUE if file exists
|
|
FALSE if file not found
|
|
|
|
--*/
|
|
{
|
|
BOOL bMediaPresent;
|
|
UINT nDriveType;
|
|
DWORD dwAttr;
|
|
|
|
nDriveType = GetDriveTypeFromDosPath((LPTSTR)szPath);
|
|
if ((nDriveType == DRIVE_REMOVABLE) || (nDriveType == DRIVE_CDROM)) {
|
|
// see if a formatted drive is really there
|
|
bMediaPresent = MediaPresent(szPath, TRUE);
|
|
} else {
|
|
// if drive is not removable, then assume it's there
|
|
bMediaPresent = TRUE;
|
|
}
|
|
|
|
// try to get inforation on the file
|
|
dwAttr = QuietGetFileAttributes ((LPTSTR)szPath);
|
|
if (dwAttr == 0xFFFFFFFF) {
|
|
// unable to obtain attributes, so assume it's not there
|
|
// or we can't access it
|
|
return FALSE;
|
|
} else {
|
|
// found, so close it and return TRUE
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
LPCTSTR
|
|
GetKeyFromIniEntry (
|
|
IN LPCTSTR szEntry
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
static TCHAR szReturnBuffer[MAX_PATH];
|
|
LPTSTR szSource, szDest;
|
|
|
|
szSource = (LPTSTR)szEntry;
|
|
szDest = &szReturnBuffer[0];
|
|
|
|
// clear previous contents
|
|
memset (szDest, 0, (MAX_PATH * sizeof(TCHAR)));
|
|
|
|
*szDest = 0;
|
|
|
|
if (*szSource != 0) {
|
|
while ((*szSource != cEqual) && (*szSource != 0)) {
|
|
*szDest++ = *szSource++;
|
|
}
|
|
*szDest = 0;
|
|
}
|
|
|
|
TrimSpaces(szReturnBuffer);
|
|
return szReturnBuffer;
|
|
}
|
|
|
|
DWORD
|
|
StripQuotes (
|
|
IN OUT LPSTR szBuff
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
removes all double quote characters (") from the string in the argument.
|
|
this function modifies the contents of the buffer passed in the argument
|
|
list.
|
|
|
|
Arguments:
|
|
|
|
IN OUT LPSTR szBuff
|
|
string to removed quote characters from
|
|
|
|
Return Value:
|
|
|
|
length of new string in characters
|
|
|
|
--*/
|
|
{
|
|
LPSTR szSrcChar;
|
|
LPSTR szDestChar;
|
|
|
|
DWORD dwCharCount;
|
|
|
|
szSrcChar = szBuff;
|
|
szDestChar = szBuff;
|
|
dwCharCount = 0;
|
|
|
|
while (*szSrcChar != '\0') {
|
|
if (*szSrcChar != '\"') {
|
|
*szDestChar = *szSrcChar;
|
|
szDestChar++;
|
|
dwCharCount++;
|
|
}
|
|
szSrcChar++;
|
|
}
|
|
*szDestChar = '\0';
|
|
|
|
return dwCharCount;
|
|
}
|
|
|
|
BOOL
|
|
GetFilePath (
|
|
IN LPCTSTR szFileName,
|
|
OUT LPTSTR szPathBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Scans for the file specified in the argument list.
|
|
The OpenFile function looks in the following directories in
|
|
the following order for the INF.
|
|
|
|
1 The current directory.
|
|
|
|
2 The Windows directory (the directory containing WIN.COM),
|
|
whose path the GetWindowsDirectory function retrieves.
|
|
|
|
3 The Windows system directory (the directory containing
|
|
such system files as GDI.EXE), whose path the GetSystemDirectory
|
|
function retrieves.
|
|
|
|
4 The directory containing the executable file for the
|
|
current task; the GetModuleFileName function obtains the
|
|
path of this directory.
|
|
|
|
5 The directories listed in the PATH environment variable.
|
|
|
|
6 The list of directories mapped in a network.
|
|
|
|
Arguments:
|
|
|
|
szFileName base filename of file to find
|
|
szPathBuffer buffer that application inf file path is written to.
|
|
|
|
Return Value:
|
|
|
|
TRUE if a file path is written to szPathBuffer
|
|
FALSE if no file is found and szPathBuffer is empty
|
|
|
|
--*/
|
|
{
|
|
TOFSTRUCT ofFile;
|
|
HFILE hFile;
|
|
|
|
hFile = OpenFileT (
|
|
szFileName,
|
|
&ofFile,
|
|
OF_SEARCH);
|
|
|
|
if (hFile != HFILE_ERROR) {
|
|
// file found (and opened!) successfully
|
|
lstrcpy (szPathBuffer, ofFile.szPathName);
|
|
_lclose(hFile); // close file handle for now.
|
|
return TRUE;
|
|
} else {
|
|
*szPathBuffer = 0;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
GetInfPath (
|
|
IN HWND hWnd,
|
|
IN UINT nFileNameId,
|
|
OUT LPTSTR szPathBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Scans for the INF file described by the string resource ID in the arg
|
|
list. The OpenFile function looks in the following directories in
|
|
the following order for the INF.
|
|
|
|
1 The current directory.
|
|
|
|
2 The Windows directory (the directory containing WIN.COM),
|
|
whose path the GetWindowsDirectory function retrieves.
|
|
|
|
3 The Windows system directory (the directory containing
|
|
such system files as GDI.EXE), whose path the GetSystemDirectory
|
|
function retrieves.
|
|
|
|
4 The directory containing the executable file for the
|
|
current task; the GetModuleFileName function obtains the
|
|
path of this directory.
|
|
|
|
5 The directories listed in the PATH environment variable.
|
|
|
|
6 The list of directories mapped in a network.
|
|
|
|
Arguments:
|
|
|
|
hWnd Window handle of application main window
|
|
nFileNameId ID of string resource containing filename to locate
|
|
szPathBuffer buffer that application inf file path is written to.
|
|
|
|
Return Value:
|
|
|
|
TRUE if a file path is written to szPathBuffer
|
|
FALSE if no file is found and szPathBuffer is empty
|
|
|
|
--*/
|
|
{
|
|
return GetFilePath(
|
|
GetStringResource (GET_INSTANCE(hWnd), nFileNameId),
|
|
szPathBuffer);
|
|
}
|
|
|
|
BOOL
|
|
DrawRaisedShading (
|
|
IN LPRECT prShadeWnd,
|
|
IN LPPAINTSTRUCT ps,
|
|
IN LONG lDepth,
|
|
IN HPEN hpenHighlight,
|
|
IN HPEN hpenShadow
|
|
)
|
|
{
|
|
LONG lLineDepth;
|
|
RECT rWnd; // local window rectangle dimensions
|
|
|
|
rWnd = *prShadeWnd; // make local copy of rectangle
|
|
|
|
// adjust rectangle to fit within client area
|
|
rWnd.right -= 1;
|
|
rWnd.bottom -= 1;
|
|
|
|
if ((lDepth > 0) &&
|
|
(lDepth < (rWnd.bottom / 2)) &&
|
|
(lDepth < (rWnd.right / 2))) {
|
|
|
|
// draw shading line
|
|
for (lLineDepth = 0; lLineDepth < lDepth; lLineDepth++) {
|
|
// start at bottom left corner and draw highlight
|
|
SelectObject (ps->hdc, hpenHighlight);
|
|
MoveToEx (ps->hdc, rWnd.left, rWnd.bottom, NULL);
|
|
LineTo (ps->hdc, rWnd.left, rWnd.top);
|
|
LineTo (ps->hdc, rWnd.right, rWnd.top);
|
|
|
|
// draw shadow lines
|
|
SelectObject (ps->hdc, hpenShadow);
|
|
LineTo (ps->hdc, rWnd.right, rWnd.bottom);
|
|
LineTo (ps->hdc, rWnd.left-1, rWnd.bottom);
|
|
|
|
// shrink rectangle for next iteration
|
|
rWnd.top += 1;
|
|
rWnd.left += 1;
|
|
if (rWnd.left < rWnd.right) rWnd.right -= 1;
|
|
if (rWnd.top < rWnd.bottom) rWnd.bottom -= 1;
|
|
}
|
|
|
|
return TRUE;
|
|
} else {
|
|
// depth is bigger than window
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
DrawSeparatorLine (
|
|
IN LPRECT lprLine,
|
|
IN LPPAINTSTRUCT ps,
|
|
IN HPEN hpenLine
|
|
)
|
|
{
|
|
SelectObject (ps->hdc, hpenLine);
|
|
return Rectangle (ps->hdc,
|
|
lprLine->left,
|
|
lprLine->top,
|
|
lprLine->right,
|
|
lprLine->bottom);
|
|
}
|
|
|
|
DWORD
|
|
GetFileSizeFromPath (
|
|
LPCTSTR szPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
returns the size of the file specified in szPath (if it exists)
|
|
(up to 4 GB)
|
|
|
|
returns 0 byte size if:
|
|
the file could not be found
|
|
the file is 0 bytes long
|
|
|
|
Arguments:
|
|
|
|
szPath path and name of file to query
|
|
|
|
Return Value:
|
|
see description
|
|
|
|
--*/
|
|
{
|
|
HANDLE hFile;
|
|
DWORD dwSize, dwHiSize;
|
|
|
|
if (FileExists(szPath)) {
|
|
hFile = CreateFile(szPath,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
dwSize = GetFileSize (hFile, &dwHiSize);
|
|
if (dwSize == 0xFFFFFFFF) {
|
|
// an error so return 0
|
|
dwSize = 0;
|
|
} else if (dwHiSize > 0) {
|
|
// file is > 4GB so return Max Int
|
|
dwSize = 0xFFFFFFFF;
|
|
} else {
|
|
// file size was returned and <= 4GB so return size
|
|
}
|
|
CloseHandle (hFile);
|
|
return dwSize;
|
|
} else {
|
|
return 0; // unable to open file
|
|
}
|
|
} else {
|
|
return 0; // file not found
|
|
}
|
|
}
|