windows-nt/Source/XPSP1/NT/enduser/stuff/hhsetup/util.cpp
2020-09-26 16:20:57 +08:00

399 lines
9.9 KiB
C++

#include <windows.h>
#include "util.h"
#ifndef ASSERT
#if defined(_DEBUG) || defined(DEBUG)
#define ASSERT(b) if(!b) MessageBox(NULL, "FAILED: #b", "ASSERT", MB_OK );
#else
#define ASSERT(b)
#endif
#endif
#define MAX_STRING_RESOURCE_LEN 1024
LPCSTR g_pszMsgBoxTitle = "HTML Help Dumper Tool";
int MsgBox(int idString, UINT nType)
{
char szMsg[MAX_STRING_RESOURCE_LEN + 1];
if (LoadString(GetModuleHandle(NULL), idString, szMsg,
sizeof(szMsg)) == 0) {
return 0;
}
return MessageBox(GetActiveWindow(), szMsg, g_pszMsgBoxTitle, nType);
}
int MsgBox(PCSTR pszMsg, UINT nType)
{
return MessageBox(GetActiveWindow(), pszMsg, g_pszMsgBoxTitle, nType);
}
PCSTR FindFilePortion( PCSTR pszFile )
{
PCSTR psz = strrchr(pszFile, '\\');
if (psz)
pszFile = psz + 1;
psz = strrchr(pszFile, '/');
if (psz)
return psz + 1;
psz = strrchr(pszFile, ':');
return (psz ? psz + 1 : pszFile);
}
typedef enum { JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC } MONTHS;
int DaysInMonth(int nMonth, int nYear)
{
switch( nMonth ) {
case SEP: case APR: case JUN: case NOV:
return 30;
case FEB:
return (nYear % 4) == 0 ? 29 : 28; // handle leap year
default:
return 31;
}
}
int JulianDate(int nDay, int nMonth, int nYear)
{
int nDayOfYear = 0;
int iMonth;
for( iMonth = JAN ; iMonth < nMonth ; iMonth++ )
nDayOfYear += DaysInMonth(iMonth, nYear);
return( (nYear % 10) * 1000 + nDayOfYear + nDay );
}
#define YRMASK 0xFE00
#define YRSHIFT 9
#define MONMASK 0x01E0
#define MONSHIFT 5
#define DAYMASK 0x001F
#define DAYSHIFT 0
#define HRMASK 0xF800
#define HRSHIFT 11
#define MINMASK 0x07E0
#define MINSHIFT 5
#define SECMASK 0x001F
#define SECSHIFT 0
HRESULT FileTimeToDateTimeString( FILETIME FileTime, LPTSTR pszDateTime )
{
HRESULT hr = S_FALSE;
WORD wDosDate = 0;
WORD wDosTime = 0;
if( FileTimeToDosDateTime( &FileTime, &wDosDate, &wDosTime ) ) {
DWORD dwDay = (wDosDate & DAYMASK) >> DAYSHIFT;
DWORD dwMonth = (wDosDate & MONMASK) >> MONSHIFT;
DWORD dwYear = (((wDosDate & YRMASK) >> YRSHIFT) + 80) % 100;
DWORD dwHour = (wDosTime & HRMASK) >> HRSHIFT;
DWORD dwMinute = (wDosTime & MINMASK) >> MINSHIFT;
DWORD dwSecond = ((wDosTime & SECMASK) >> SECSHIFT) * 2;
LPCSTR pszAMPM = NULL;
if( dwHour >= 12 )
pszAMPM = "PM";
else
pszAMPM = "AM";
if( dwHour > 12 )
dwHour -= 12;
if( dwHour == 0 )
dwHour = 12;
wsprintf( pszDateTime, "%02d/%02d/%02d %02d:%02d %s",
dwMonth, dwDay, dwYear, dwHour, dwMinute, pszAMPM );
hr = S_OK;
}
return hr;
}
int FileTimeToJulianDate( FILETIME FileTime )
{
int iReturn = 0;
WORD wDosDate = 0;
WORD wDosTime = 0;
if( FileTimeToDosDateTime( &FileTime, &wDosDate, &wDosTime ) ) {
DWORD dwDay = (wDosDate & DAYMASK) >> DAYSHIFT;
DWORD dwMonth = (wDosDate & MONMASK) >> MONSHIFT;
DWORD dwYear = ((wDosDate & YRMASK) >> YRSHIFT) + 1980;
iReturn = JulianDate( dwDay, dwMonth, dwYear );
}
return iReturn;
}
///////////////////////////////////////////////////////////
//
// Get the windows directory for the system or the user
//
// Note, Windows NT Terminal Server has changed the system API
// of GetWindowsDirectory to return a per-user system directory.
// Inorder to determine this condtion we need to check kernel32
// for the GetSystemWindowsDirectory API and if it exists use
// this one instead.
//
UINT HHGetWindowsDirectory( LPSTR lpBuffer, UINT uSize, UINT uiType )
{
UINT uiReturn = 0;
PFN_GETWINDOWSDIRECTORY pfnGetUsersWindowsDirectory = NULL;
PFN_GETWINDOWSDIRECTORY pfnGetSystemWindowsDirectory = NULL;
// determine which system API to call for each case
HINSTANCE hInst = LoadLibrary( "Kernel32" );
if( !hInst )
return uiReturn;
pfnGetSystemWindowsDirectory = (PFN_GETWINDOWSDIRECTORY) GetProcAddress( hInst, "GetSystemWindowsDirectoryA" );
pfnGetUsersWindowsDirectory = (PFN_GETWINDOWSDIRECTORY) GetProcAddress( hInst, "GetWindowsDirectoryA" );
ASSERT( pfnGetUsersWindowsDirectory ); // if NULL then we have a bug!
if( !pfnGetSystemWindowsDirectory ) {
pfnGetSystemWindowsDirectory = pfnGetUsersWindowsDirectory;
}
if( uiType == HH_SYSTEM_WINDOWS_DIRECTORY )
uiReturn = pfnGetSystemWindowsDirectory( lpBuffer, uSize );
else if( uiType == HH_USERS_WINDOWS_DIRECTORY )
uiReturn = pfnGetUsersWindowsDirectory( lpBuffer, uSize );
else
uiReturn = 0;
FreeLibrary( hInst );
return uiReturn;
}
LPSTR CatPath(LPSTR lpTop, LPCSTR lpTail)
{
//
// make sure we have a slash at the end of the first element
//
LPSTR p;
p = lpTop + strlen(lpTop);
p = CharPrev(lpTop,p);
if (*p != '\\' && *p != '/')
{
strcat(lpTop,"\\");
}
//
// strip any leading slash from the second element
//
while (*lpTail == '\\') lpTail = CharNext(lpTail);
//
// add them together
//
strcat(lpTop, lpTail);
return lpTop;
}
#pragma data_seg(".text", "CODE")
static const char txtGlobal[] = "global.col";
static const char txtColReg[] = "hhcolreg.dat";
static const char txtHelp[] = "help";
static const char txtHHDat[] = "hh.dat";
#pragma data_seg()
///////////////////////////////////////////////////////////
//
// Get the help directory
//
// Note, this is always relative to the system's windows
// directory and not the user's windows directory.
// See HHGetWindowsDirectory for details on this.
//
UINT HHGetHelpDirectory( LPTSTR lpBuffer, UINT uSize )
{
UINT uiReturn = 0;
uiReturn = HHGetWindowsDirectory( lpBuffer, uSize );
CatPath( lpBuffer, txtHelp );
return uiReturn;
}
DWORD CreatePath(char *szPath)
{
char szTmp[MAX_PATH],*p,*q,szTmp2[MAX_PATH];
DWORD dwErr;
strcpy(szTmp2,szPath);
memset(szTmp,0,sizeof(szTmp));
q = szTmp2;
p = szTmp;
while (*q)
{
if (*q == '/' || *q == '\\')
{
if (szTmp[1] == ':' && strlen(szTmp) <= 3)
{
if(IsDBCSLeadByte(*q))
{
*p++ = *q++;
if(*q)
*p++ = *q++;
}
else
*p++ = *q++;
continue;
}
if (!::CreateDirectory(szTmp,0))
{
if ( (dwErr = GetLastError()) != ERROR_ALREADY_EXISTS)
return(dwErr);
}
}
if(IsDBCSLeadByte(*q))
{
*p++ = *q++;
if(*q)
*p++ = *q++;
}
else
*p++ = *q++;
}
if (!::CreateDirectory(szTmp,0))
{
if ((dwErr = GetLastError()) != ERROR_ALREADY_EXISTS)
return(dwErr);
}
return(FALSE);
}
///////////////////////////////////////////////////////////
//
// Get the full pathname to the global collections file
//
// Note, this is in always in the system's help directory.
//
UINT HHGetGlobalCollectionPathname( LPTSTR lpBuffer, UINT uSize, BOOL *pbNewPath )
{
UINT uiReturn = 0;
*pbNewPath = TRUE;
uiReturn = HHGetHelpDataPath( lpBuffer );
if (uiReturn != S_OK)
{
*pbNewPath = FALSE;
uiReturn = HHGetHelpDirectory( lpBuffer, uSize );
if( !IsDirectory(lpBuffer) )
CreatePath( lpBuffer );
}
CatPath( lpBuffer, txtColReg );
return uiReturn;
}
BOOL IsDirectory( LPCSTR lpszPathname )
{
DWORD dwAttribs = GetFileAttributes( lpszPathname );
if( dwAttribs != (DWORD) -1 )
if( dwAttribs & FILE_ATTRIBUTE_DIRECTORY )
return TRUE;
return FALSE;
}
static const char txtProfiles[] = "Profiles";
static const char txtUser[] = "Default User";
static const char txtAllUsers[] = "All Users";
static const char txtApplicationData[] = "Application Data";
static const char txtMicrosoft[] = "Microsoft";
static const char txtHTMLHelp[] = "HTML Help";
typedef HRESULT (WINAPI *PFN_SHGETFOLDERPATH)( HWND hWnd, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath );
#ifndef CSIDL_FLAG_CREATE
#define CSIDL_COMMON_APPDATA 0x0023
#define CSIDL_FLAG_CREATE 0x8000
#endif
///////////////////////////////////////////////////////////
//
// Get the full path to where the common help data files lives
// hhcolreg.dat, *.chw and *.chs
//
// Note, if the subdirectories of the path does not exist
// we will create them
//
HRESULT HHGetHelpDataPath( LPSTR pszPath )
{
HRESULT hResult = S_OK;
PFN_SHGETFOLDERPATH pfnSHGetFolderPath = NULL;
HINSTANCE hInst = LoadLibrary( "Shell32" );
if( !hInst )
return S_FALSE;
pfnSHGetFolderPath = (PFN_SHGETFOLDERPATH) GetProcAddress( hInst, "SHGetFolderPathA" );
// if this function does not exist then we need to similate the return path of
// "%windir%\Profiles\All Users\Application Data"
if( pfnSHGetFolderPath ) {
// now call it
hResult = pfnSHGetFolderPath( NULL, CSIDL_FLAG_CREATE | CSIDL_COMMON_APPDATA, NULL, 0, pszPath);
if (pszPath[0] == NULL)
{
FreeLibrary( hInst ); // since we already have a copy of Shell32 loaded, free it
return S_FALSE;
}
}
else
{
FreeLibrary( hInst ); // since we already have a copy of Shell32 loaded, free it
return S_FALSE;
}
FreeLibrary( hInst ); // since we already have a copy of Shell32 loaded, free it
// append "Microsoft"
CatPath( pszPath, txtMicrosoft );
if( !IsDirectory(pszPath) )
if( !CreateDirectory( pszPath, NULL ) )
return S_FALSE;
// append "HTML Help"
CatPath( pszPath, txtHTMLHelp );
if( !IsDirectory(pszPath) )
if( !CreateDirectory( pszPath, NULL ) )
return S_FALSE;
return hResult;
}
///////////////////////////////////////////////////////////
//
// Get the full pathname to the user's data file
//
// Note, this is always relative to the users's windows
// directory and not the system's windows directory.
// See HHGetWindowsDirectory for details on this.
//
UINT HHGetUsersDataPathname( LPTSTR lpBuffer, UINT uSize )
{
UINT uiReturn = 0;
uiReturn = HHGetWindowsDirectory( lpBuffer, uSize, HH_USERS_WINDOWS_DIRECTORY );
CatPath( lpBuffer, txtHHDat );
return uiReturn;
}