Leaked source code of windows server 2003
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.
 
 
 
 
 
 

819 lines
24 KiB

#include "iernonce.h"
#include "resource.h"
//==================================================================
// AddPath()
//
void AddPath(LPTSTR szPath, LPCTSTR szName)
{
LPTSTR szTmp;
// Find end of the string
szTmp = szPath + lstrlen(szPath);
// If no trailing backslash then add one
if (szTmp > szPath && *(CharPrev(szPath, szTmp)) != TEXT('\\'))
*szTmp++ = TEXT('\\');
// Add new name to existing path string
while (*szName == TEXT(' '))
szName = CharNext(szName);
lstrcpy(szTmp, szName);
}
// function will upated the given buffer to parent dir
//
BOOL GetParentDir( LPTSTR szFolder )
{
LPTSTR lpTmp;
BOOL bRet = FALSE;
// remove the trailing '\\'
lpTmp = CharPrev( szFolder, (szFolder + lstrlen(szFolder)) );
lpTmp = CharPrev( szFolder, lpTmp );
while ( (lpTmp > szFolder) && (*lpTmp != TEXT('\\') ) )
{
lpTmp = CharPrev( szFolder, lpTmp );
}
if ( *lpTmp == TEXT('\\') )
{
if ( (lpTmp == szFolder) || (*CharPrev(szFolder, lpTmp)==TEXT(':') ) )
lpTmp = CharNext( lpTmp );
*lpTmp = TEXT('\0');
bRet = TRUE;
}
return bRet;
}
// This is the value for the major version 4.71
#define IE4_MS_VER 0x00040047
BOOL RunningOnIE4()
{
static BOOL fIsIE4 = 2;
TCHAR szFile[MAX_PATH];
#ifdef UNICODE
char szANSIFile[MAX_PATH];
#endif
DWORD dwMSVer;
DWORD dwLSVer;
if (fIsIE4 != 2)
return fIsIE4;
GetSystemDirectory(szFile, ARRAYSIZE(szFile));
AddPath(szFile, TEXT("shell32.dll"));
#ifdef UNICODE
WideCharToMultiByte(CP_ACP, 0, szFile, -1, szANSIFile, sizeof(szANSIFile), NULL, NULL);
#endif
GetVersionFromFile(
#ifdef UNICODE
szANSIFile,
#else
szFile,
#endif
&dwMSVer, &dwLSVer, TRUE);
fIsIE4 = dwMSVer >= IE4_MS_VER;
return fIsIE4;
}
/****************************************************\
FUNCTION: MsgWaitForMultipleObjectsLoop
PARAMETERS:
HANDLE hEvent - Pointer to the object-handle array of Objects
DWORD dwTimeout - Time out duration
DWORD return - Return is WAIT_FAILED or WAIT_OBJECT_0
DESCRIPTION:
Waits for the object (Process) to complete.
\***************************************************/
DWORD MsgWaitForMultipleObjectsLoop(HANDLE hEvent, DWORD dwTimeout)
{
MSG msg;
DWORD dwObject;
while (1)
{
// NB We need to let the run dialog become active so we have to half handle sent
// messages but we don't want to handle any input events or we'll swallow the
// type-ahead.
dwObject = MsgWaitForMultipleObjects(1, &hEvent, FALSE, dwTimeout, QS_ALLINPUT);
// Are we done waiting?
switch (dwObject) {
case WAIT_OBJECT_0:
case WAIT_FAILED:
return dwObject;
case WAIT_OBJECT_0 + 1:
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
DispatchMessage(&msg);
break;
}
}
// never gets here
// return dwObject;
}
void LogOff(BOOL bRestart)
{
if (g_bRunningOnNT)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// get a token from this process
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
// get the LUID for the shutdown privilege
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//get the shutdown privilege for this proces
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
}
}
ExitWindowsEx(bRestart?EWX_REBOOT|EWX_FORCE:EWX_LOGOFF, 0);
// this is a hack to prevent explorer from continue starting (In Integrated Shell)
// and runonce from continue processing other items.
// If we use a timer wait (which contains a messageloop), in browser only mode our
// process gets terminated before explorer and explorer would try and continue
// processing runonce items. With the while loop below this seem to not happen.
if (bRestart)
while (true) ;
}
//
// Performs a message box with the text and title string loaded from the string table.
void ReportError(DWORD dwFlags, UINT uiResourceNum, ...)
{
TCHAR szResourceStr[1024] = TEXT("");
va_list vaListOfMessages;
LPTSTR pszErrorString = NULL;
LoadString(g_hinst, uiResourceNum, szResourceStr, ARRAYSIZE(szResourceStr));
va_start(vaListOfMessages, uiResourceNum); // Initialize variable arguments.
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING,
(LPCVOID) szResourceStr, 0, 0, (LPTSTR) &pszErrorString, 0, &vaListOfMessages);
va_end(vaListOfMessages);
if (pszErrorString != NULL)
{
if (!(RRAEX_NO_ERROR_DIALOGS & dwFlags)) // Display Error dialog
{
if (*g_szTitleString == TEXT('\0')) // Initialize this only once
LoadString(g_hinst, IDS_RUNONCEEX_TITLE, g_szTitleString, ARRAYSIZE(g_szTitleString));
MessageBox(NULL, pszErrorString, g_szTitleString, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
}
// If there is a cllback then callback with error string
if (g_pCallbackProc)
g_pCallbackProc(0, 0, pszErrorString);
WriteToLog(pszErrorString);
WriteToLog(TEXT("\r\n"));
LocalFree(pszErrorString);
}
}
// copied from msdev\crt\src\atox.c
/***
*long AtoL(char *nptr) - Convert string to long
*
*Purpose:
* Converts ASCII string pointed to by nptr to binary.
* Overflow is not detected.
*
*Entry:
* nptr = ptr to string to convert
*
*Exit:
* return long int value of the string
*
*Exceptions:
* None - overflow is not detected.
*
*******************************************************************************/
long AtoL(const char *nptr)
{
int c; /* current char */
long total; /* current total */
int sign; /* if '-', then negative, otherwise positive */
// NOTE: no need to worry about DBCS chars here because IsSpace(c), IsDigit(c),
// '+' and '-' are "pure" ASCII chars, i.e., they are neither DBCS Leading nor
// DBCS Trailing bytes -- pritvi
/* skip whitespace */
while ( IsSpace((int)(unsigned char)*nptr) )
++nptr;
c = (int)(unsigned char)*nptr++;
sign = c; /* save sign indication */
if (c == '-' || c == '+')
c = (int)(unsigned char)*nptr++; /* skip sign */
total = 0;
while (IsDigit(c)) {
total = 10 * total + (c - '0'); /* accumulate digit */
c = (int)(unsigned char)*nptr++; /* get next char */
}
if (sign == '-')
return -total;
else
return total; /* return result, negated if necessary */
}
// returns a pointer to the arguments in a cmd type path or pointer to
// NULL if no args exist
//
// "foo.exe bar.txt" -> "bar.txt"
// "foo.exe" -> ""
//
// Spaces in filenames must be quoted.
// " "A long name.txt" bar.txt " -> "bar.txt"
STDAPI_(LPTSTR)
LocalPathGetArgs(
LPCTSTR pszPath) // copied from \\trango\slmadd\src\shell\shlwapi\path.c
{
BOOL fInQuotes = FALSE;
if (!pszPath)
return NULL;
while (*pszPath)
{
if (*pszPath == TEXT('"'))
fInQuotes = !fInQuotes;
else if (!fInQuotes && *pszPath == TEXT(' '))
return (LPTSTR)pszPath+1;
pszPath = CharNext(pszPath);
}
return (LPTSTR)pszPath;
}
/*----------------------------------------------------------
Purpose: If a path is contained in quotes then remove them.
Returns: --
Cond: --
*/
STDAPI_(void)
LocalPathUnquoteSpaces(
LPTSTR lpsz) // copied from \\trango\slmadd\src\shell\shlwapi\path.c
{
int cch;
cch = lstrlen(lpsz);
// Are the first and last chars quotes?
if (lpsz[0] == TEXT('"') && lpsz[cch-1] == TEXT('"'))
{
// Yep, remove them.
lpsz[cch-1] = TEXT('\0');
hmemcpy(lpsz, lpsz+1, (cch-1) * sizeof(TCHAR));
}
}
#ifdef UNICODE
LPWSTR FAR PASCAL LocalStrChrW(LPCWSTR lpStart, WORD wMatch)
// copied from \\trango\slmadd\src\shell\shlwapi\strings.c
{
for ( ; *lpStart; lpStart++)
{
// Need a tmp word since casting ptr to WORD * will
// fault on MIPS, ALPHA
WORD wTmp;
memcpy(&wTmp, lpStart, sizeof(WORD));
if (!ChrCmpW_inline(wTmp, wMatch))
{
return((LPWSTR)lpStart);
}
}
return (NULL);
}
__inline BOOL ChrCmpW_inline(WORD w1, WORD wMatch)
// copied from \\trango\slmadd\src\shell\shlwapi\strings.c
{
return(!(w1 == wMatch));
}
#else
/*
* StrChr - Find first occurrence of character in string
* Assumes lpStart points to start of null terminated string
* wMatch is the character to match
* returns ptr to the first occurrence of ch in str, NULL if not found.
*/
LPSTR FAR PASCAL LocalStrChrA(LPCSTR lpStart, WORD wMatch)
// copied from \\trango\slmadd\src\shell\shlwapi\strings.c
{
for ( ; *lpStart; lpStart = AnsiNext(lpStart))
{
if (!ChrCmpA_inline(*(UNALIGNED WORD FAR *)lpStart, wMatch))
return((LPSTR)lpStart);
}
return (NULL);
}
/*
* ChrCmp - Case sensitive character comparison for DBCS
* Assumes w1, wMatch are characters to be compared
* Return FALSE if they match, TRUE if no match
*/
__inline BOOL ChrCmpA_inline(WORD w1, WORD wMatch)
// copied from \\trango\slmadd\src\shell\shlwapi\strings.c
{
/* Most of the time this won't match, so test it first for speed.
*/
if (LOBYTE(w1) == LOBYTE(wMatch))
{
if (IsDBCSLeadByte(LOBYTE(w1)))
{
return(w1 != wMatch);
}
return FALSE;
}
return TRUE;
}
#endif
#ifdef UNICODE
/*----------------------------------------------------------
Purpose: Recursively delete the key, including all child values
and keys.
Returns:
Cond: --
*/
STDAPI_(DWORD)
LocalSHDeleteKeyW(
HKEY hkey,
LPCWSTR pwszSubKey) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
{
DWORD dwRet;
CHAR sz[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, pwszSubKey, -1, sz, ARRAYSIZE(sz), NULL, NULL);
if (g_bRunningOnNT)
{
dwRet = DeleteKeyRecursively(hkey, sz);
}
else
{
// On Win95, RegDeleteKey does what we want
dwRet = RegDeleteKeyA(hkey, sz);
}
RegFlushKey(hkey);
return dwRet;
}
#else
/*----------------------------------------------------------
Purpose: Recursively delete the key, including all child values
and keys.
Returns:
Cond: --
*/
STDAPI_(DWORD)
LocalSHDeleteKeyA(
HKEY hkey,
LPCSTR pszSubKey) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
{
DWORD dwRet;
if (g_bRunningOnNT)
{
dwRet = DeleteKeyRecursively(hkey, pszSubKey);
}
else
{
// On Win95, RegDeleteKey does what we want
dwRet = RegDeleteKeyA(hkey, pszSubKey);
}
RegFlushKey(hkey);
return dwRet;
}
#endif
/*----------------------------------------------------------
Purpose: Recursively delete the key, including all child values
and keys. Mimics what RegDeleteKey does in Win95.
Returns:
Cond: --
*/
DWORD
DeleteKeyRecursively(
HKEY hkey,
LPCSTR pszSubKey) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
{
DWORD dwRet;
HKEY hkSubKey;
// Open the subkey so we can enumerate any children
dwRet = RegOpenKeyExA(hkey, pszSubKey, 0, KEY_READ | KEY_WRITE, &hkSubKey);
if (ERROR_SUCCESS == dwRet)
{
DWORD dwIndex;
CHAR szSubKeyName[MAX_PATH + 1];
DWORD cchSubKeyName = ARRAYSIZE(szSubKeyName);
CHAR szClass[MAX_PATH];
DWORD cbClass = ARRAYSIZE(szClass);
// I can't just call RegEnumKey with an ever-increasing index, because
// I'm deleting the subkeys as I go, which alters the indices of the
// remaining subkeys in an implementation-dependent way. In order to
// be safe, I have to count backwards while deleting the subkeys.
// Find out how many subkeys there are
dwRet = RegQueryInfoKeyA(hkSubKey,
szClass,
&cbClass,
NULL,
&dwIndex, // The # of subkeys -- all we need
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if (NO_ERROR == dwRet)
{
// dwIndex is now the count of subkeys, but it needs to be
// zero-based for RegEnumKey, so I'll pre-decrement, rather
// than post-decrement.
while (ERROR_SUCCESS == RegEnumKeyA(hkSubKey, --dwIndex, szSubKeyName, cchSubKeyName))
{
DeleteKeyRecursively(hkSubKey, szSubKeyName);
}
}
RegCloseKey(hkSubKey);
dwRet = RegDeleteKeyA(hkey, pszSubKey);
}
return dwRet;
}
#ifdef UNICODE
/*----------------------------------------------------------
Purpose: Deletes a registry value. This opens and closes the
key in which the value resides.
On Win95, this function thunks and calls the ansi
version. On NT, this function calls the unicode
registry APIs directly.
Perf: if your code involves setting/getting a series
of values in the same key, it is better to open
the key once and set/get the values with the regular
Win32 registry functions, rather than using this
function repeatedly.
Returns:
Cond: --
*/
LocalSHDeleteValueW(
HKEY hkey,
LPCWSTR pwszSubKey,
LPCWSTR pwszValue) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
{
DWORD dwRet;
HKEY hkeyNew;
if (g_bRunningOnNT)
{
dwRet = RegOpenKeyExW(hkey, pwszSubKey, 0, KEY_SET_VALUE, &hkeyNew);
if (NO_ERROR == dwRet)
{
dwRet = RegDeleteValueW(hkeyNew, pwszValue);
RegFlushKey(hkeyNew);
RegCloseKey(hkeyNew);
}
}
else
{
CHAR szSubKey[MAX_PATH];
CHAR szValue[MAX_PATH];
LPSTR pszSubKey = NULL;
LPSTR pszValue = NULL;
if (pwszSubKey)
{
WideCharToMultiByte(CP_ACP, 0, pwszSubKey, -1, szSubKey, ARRAYSIZE(szSubKey), NULL, NULL);
pszSubKey = szSubKey;
}
if (pwszValue)
{
WideCharToMultiByte(CP_ACP, 0, pwszValue, -1, szValue, ARRAYSIZE(szValue), NULL, NULL);
pszValue = szValue;
}
dwRet = LocalSHDeleteValueA(hkey, pszSubKey, pszValue);
}
return dwRet;
}
#endif
/*----------------------------------------------------------
Purpose: Deletes a registry value. This opens and closes the
key in which the value resides.
Perf: if your code involves setting/getting a series
of values in the same key, it is better to open
the key once and set/get the values with the regular
Win32 registry functions, rather than using this
function repeatedly.
Returns:
Cond: --
*/
STDAPI_(DWORD)
LocalSHDeleteValueA(
HKEY hkey,
LPCSTR pszSubKey,
LPCSTR pszValue) // copied from \\trango\slmadd\src\shell\shlwapi\reg.c
{
DWORD dwRet;
HKEY hkeyNew;
dwRet = RegOpenKeyExA(hkey, pszSubKey, 0, KEY_SET_VALUE, &hkeyNew);
if (NO_ERROR == dwRet)
{
dwRet = RegDeleteValueA(hkeyNew, pszValue);
RegFlushKey(hkeyNew);
RegCloseKey(hkeyNew);
}
return dwRet;
}
LPTSTR GetLogFileName(LPCTSTR pcszLogFileKeyName, LPTSTR pszLogFileName, DWORD dwSizeInChars)
{
TCHAR szBuf[MAX_PATH];
*pszLogFileName = TEXT('\0');
szBuf[0] = TEXT('\0');
// get the name for the log file
GetProfileString(TEXT("IE4Setup"), pcszLogFileKeyName, TEXT(""), szBuf, ARRAYSIZE(szBuf));
if (*szBuf == TEXT('\0')) // check in the registry
{
HKEY hkSubKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\IE Setup\\Setup"), 0, KEY_READ, &hkSubKey) == ERROR_SUCCESS)
{
DWORD dwDataLen = sizeof(szBuf);
RegQueryValueEx(hkSubKey, pcszLogFileKeyName, NULL, NULL, (LPBYTE) szBuf, &dwDataLen);
RegCloseKey(hkSubKey);
}
}
if (*szBuf)
{
// crude way of determining if fully qualified path is specified or not.
if (szBuf[1] != TEXT(':'))
{
GetWindowsDirectory(pszLogFileName, dwSizeInChars); // default to windows dir
AddPath(pszLogFileName, szBuf);
}
else
lstrcpy(pszLogFileName, szBuf);
}
return pszLogFileName;
}
VOID StartLogging(LPCTSTR pcszLogFileName, DWORD dwCreationFlags)
{
if (*pcszLogFileName && (g_hLogFile = CreateFile(pcszLogFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, dwCreationFlags, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
{
SetFilePointer(g_hLogFile, 0, NULL, FILE_END);
WriteToLog(TEXT("\r\n"));
WriteToLog(TEXT("************************"));
WriteToLog(TEXT(" Begin logging "));
WriteToLog(TEXT("************************"));
WriteToLog(TEXT("\r\n"));
LogDateAndTime();
WriteToLog(TEXT("\r\n"));
}
}
VOID WriteToLog(LPCTSTR pcszFormatString, ...)
{
if (g_hLogFile != INVALID_HANDLE_VALUE)
{
va_list vaArgs;
LPTSTR pszFullErrMsg = NULL;
LPSTR pszANSIFullErrMsg;
DWORD dwBytesWritten;
#ifdef UNICODE
DWORD dwANSILen;
#endif
va_start(vaArgs, pcszFormatString);
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING,
(LPCVOID) pcszFormatString, 0, 0, (LPTSTR) &pszFullErrMsg, 0, &vaArgs);
va_end(vaArgs);
if (pszFullErrMsg != NULL)
{
#ifdef UNICODE
dwANSILen = lstrlen(pszFullErrMsg) + 1;
if ((pszANSIFullErrMsg = (LPSTR) LocalAlloc(LPTR, dwANSILen)) != NULL)
WideCharToMultiByte(CP_ACP, 0, pszFullErrMsg, -1, pszANSIFullErrMsg, dwANSILen, NULL, NULL);
#else
pszANSIFullErrMsg = pszFullErrMsg;
#endif
if (pszANSIFullErrMsg != NULL)
{
WriteFile(g_hLogFile, pszANSIFullErrMsg, lstrlen(pszANSIFullErrMsg), &dwBytesWritten, NULL);
#ifdef UNICODE
LocalFree(pszANSIFullErrMsg);
#endif
}
LocalFree(pszFullErrMsg);
}
}
}
VOID StopLogging()
{
LogDateAndTime();
WriteToLog(TEXT("************************"));
WriteToLog(TEXT(" End logging "));
WriteToLog(TEXT("************************"));
WriteToLog(TEXT("\r\n"));
if (g_hLogFile != INVALID_HANDLE_VALUE)
{
CloseHandle(g_hLogFile);
g_hLogFile = INVALID_HANDLE_VALUE;
}
}
VOID LogDateAndTime()
{
if (g_hLogFile != INVALID_HANDLE_VALUE)
{
SYSTEMTIME SystemTime;
GetLocalTime(&SystemTime);
WriteToLog(TEXT("Date: %1!02d!/%2!02d!/%3!04d! (mm/dd/yyyy)\tTime: %4!02d!:%5!02d!:%6!02d! (hh:mm:ss)\r\n"),
SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear,
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);
}
}
VOID LogFlags(DWORD dwFlags)
{
if (g_hLogFile != INVALID_HANDLE_VALUE)
{
WriteToLog(TEXT("RRA_DELETE = %1!lu!\r\n"), (dwFlags & RRA_DELETE) ? 1 : 0);
WriteToLog(TEXT("RRA_WAIT = %1!lu!\r\n"), (dwFlags & RRA_WAIT) ? 1 : 0);
WriteToLog(TEXT("RRAEX_NO_ERROR_DIALOGS = %1!lu!\r\n"), (dwFlags & RRAEX_NO_ERROR_DIALOGS) ? 1 : 0);
WriteToLog(TEXT("RRAEX_ERRORFILE = %1!lu!\r\n"), (dwFlags & RRAEX_ERRORFILE) ? 1 : 0);
WriteToLog(TEXT("RRAEX_LOG_FILE = %1!lu!\r\n"), (dwFlags & RRAEX_LOG_FILE) ? 1 : 0);
WriteToLog(TEXT("RRAEX_NO_EXCEPTION_TRAPPING = %1!lu!\r\n"), (dwFlags & RRAEX_NO_EXCEPTION_TRAPPING) ? 1 : 0);
WriteToLog(TEXT("RRAEX_NO_STATUS_DIALOG = %1!lu!\r\n"), (dwFlags & RRAEX_NO_STATUS_DIALOG) ? 1 : 0);
WriteToLog(TEXT("RRAEX_IGNORE_REG_FLAGS = %1!lu!\r\n"), (dwFlags & RRAEX_IGNORE_REG_FLAGS) ? 1 : 0);
WriteToLog(TEXT("RRAEX_CHECK_NT_ADMIN = %1!lu!\r\n"), (dwFlags & RRAEX_CHECK_NT_ADMIN) ? 1 : 0);
WriteToLog(TEXT("RRAEX_QUIT_IF_REBOOT_NEEDED = %1!lu!\r\n"), (dwFlags & RRAEX_QUIT_IF_REBOOT_NEEDED) ? 1 : 0);
#if 0
/****
WriteToLog(TEXT("RRAEX_BACKUP_SYSTEM_DAT = %1!lu!\r\n"), (dwFlags & RRAEX_BACKUP_SYSTEM_DAT) ? 1 : 0);
WriteToLog(TEXT("RRAEX_DELETE_SYSTEM_IE4 = %1!lu!\r\n"), (dwFlags & RRAEX_DELETE_SYSTEM_IE4) ? 1 : 0);
****/
#endif
#if 0
/**** enable this when explorer.exe is fixed (bug #30866)
WriteToLog(TEXT("RRAEX_CREATE_REGFILE = %1!lu!\r\n"), (dwFlags & RRAEX_CREATE_REGFILE) ? 1 : 0);
****/
#endif
}
}
// CRT stubs
//=--------------------------------------------------------------------------=
// these two things are here so the CRTs aren't needed. this is good.
//
// basically, the CRTs define this to pull in a bunch of stuff. we'll just
// define them here so we don't get an unresolved external.
//
// TODO: if you are going to use the CRTs, then remove this line.
//
extern "C" int _fltused = 1;
extern "C" int _cdecl _purecall(void)
{
// FAIL("Pure virtual function called.");
return 0;
}
void * _cdecl operator new
(
size_t size
)
{
return HeapAlloc(g_hHeap, 0, size);
}
//=---------------------------------------------------------------------------=
// overloaded delete
//=---------------------------------------------------------------------------=
// retail case just uses win32 Local* heap mgmt functions
//
// Parameters:
// void * - [in] free me!
//
// Notes:
//
void _cdecl operator delete ( void *ptr)
{
HeapFree(g_hHeap, 0, ptr);
}
void * _cdecl malloc(size_t n)
{
#ifdef _MALLOC_ZEROINIT
return HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, n);
#else
return HeapAlloc(g_hHeap, 0, n);
#endif
}
void * _cdecl calloc(size_t n, size_t s)
{
return HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, n * s);
}
void* _cdecl realloc(void* p, size_t n)
{
if (p == NULL)
return malloc(n);
return HeapReAlloc(g_hHeap, 0, p, n);
}
void _cdecl free(void* p)
{
if (p == NULL)
return;
HeapFree(g_hHeap, 0, p);
}