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.
 
 
 
 
 
 

801 lines
35 KiB

/****************************************************************************/
/* Module: nutint.cpp */
/* */
/* Purpose: Utilities - Win32 version */
/* */
/* Copyright(C) Microsoft Corporation 1997-1998 */
/****************************************************************************/
#include <adcg.h>
#undef TRC_FILE
#define TRC_FILE "nutint"
#define TRC_GROUP TRC_GROUP_UTILITIES
extern "C" {
#include <atrcapi.h>
#ifndef OS_WINCE
#include <process.h>
#endif
}
#include "autil.h"
/****************************************************************************/
/* Name: UTStartThread */
/* */
/* Purpose: Start a new thread */
/* */
/* Returns: TRUE if successful, FALSE otherwise */
/* */
/* Params: IN entryFunction - pointer to thread entry point */
/* OUT threadID - thread ID */
/* */
/* Operation: Call UTThreadEntry: new thread (Win32) / immediate (Win16) */
/* */
/****************************************************************************/
DCBOOL DCINTERNAL CUT::UTStartThread( UTTHREAD_PROC entryFunction,
PUT_THREAD_DATA pThreadData,
PDCVOID threadParam )
{
HANDLE hndArray[2];
DCUINT32 rc = FALSE;
DWORD dwrc;
DWORD threadID;
UT_THREAD_INFO info;
DC_BEGIN_FN("UTStartThread");
info.pFunc = entryFunction;
/************************************************************************/
/* For Win32, create a thread - use an Event to signal when the thread */
/* has started OK. */
/* Create event - initially non-signalled; manual control. */
/************************************************************************/
hndArray[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hndArray[0] == 0)
{
TRC_SYSTEM_ERROR("CreateEvent");
DC_QUIT;
}
TRC_NRM((TB, _T("event %p created - now create thread"), hndArray[0]));
info.sync = (ULONG_PTR)hndArray[0];
info.threadParam = threadParam;
/************************************************************************/
/* Start a new thread to run the DC-Share core task. */
/* Use C runtime (which calls CreateThread) to avoid memory leaks. */
/************************************************************************/
hndArray[1] = (HANDLE)
#if i386
_beginthreadex
#else
CreateThread
#endif
(NULL, /* security - default */
0, /* stack size - default */
#if i386
((unsigned (__stdcall *)(void*))UTStaticThreadEntry),
#else
((unsigned long (__stdcall *)(void*))UTStaticThreadEntry),
#endif
(PDCVOID)&info, /* thread parameter */
0, /* creation flags */
#if i386
(unsigned *)&threadID /* thread ID */
#else
(unsigned long *)&threadID/* thread ID */
#endif
);
if (hndArray[1] == 0)
{
/********************************************************************/
/* Failed! */
/********************************************************************/
TRC_SYSTEM_ERROR("_beginthreadex");
DC_QUIT;
}
TRC_NRM((TB, _T("thread %p created - now wait signal"), hndArray[1]));
/************************************************************************/
/* Wait for thread exit or event to be set. */
/************************************************************************/
dwrc = WaitForMultipleObjects(2, hndArray, FALSE, INFINITE);
switch (dwrc)
{
case WAIT_OBJECT_0:
{
/****************************************************************/
/* Event triggered - thread initialised OK. */
/****************************************************************/
TRC_NRM((TB, _T("event signalled")));
rc = TRUE;
}
break;
case WAIT_OBJECT_0 + 1:
{
/****************************************************************/
/* Thread exit */
/****************************************************************/
if (GetExitCodeThread(hndArray[1], &dwrc))
{
TRC_ERR((TB, _T("Thread exited with rc %x"), dwrc));
}
else
{
TRC_ERR((TB, _T("Thread exited with unknown rc")));
}
}
break;
default:
{
TRC_NRM((TB, _T("Wait returned %d"), dwrc));
}
break;
}
pThreadData->threadID = threadID;
pThreadData->threadHnd = (ULONG_PTR)(hndArray[1]);
TRC_ALT((TB, _T("Thread ID %#x handle %#x started"),
pThreadData->threadID, pThreadData->threadHnd));
DC_EXIT_POINT:
/************************************************************************/
/* Destroy event object. */
/************************************************************************/
if (hndArray[0] != 0)
{
TRC_NRM((TB, _T("Destroy event object")));
CloseHandle(hndArray[0]);
}
DC_END_FN();
return(rc);
} /* UTStartThread */
/****************************************************************************/
/* Name: UTStaticThreadEntry */
/* */
/* Purpose: STATIC Thread entry point. */
/* */
/* Returns: 0 */
/* */
/* Params: IN pInfo - pointer to thread entry function+sync object */
/* */
/* Operation: signal started OK and call the thread enty function - which */
/* enters a message loop. */
/* */
/****************************************************************************/
DCUINT WINAPI CUT::UTStaticThreadEntry(UT_THREAD_INFO * pInfo)
{
UTTHREAD_PROC pFunc;
PDCVOID pThreadParam;
DC_BEGIN_FN("UTStaticThreadEntry");
/************************************************************************/
/* Take a copy of the target function, before signalling that the */
/* thread has started. */
/************************************************************************/
pFunc = pInfo->pFunc;
/************************************************************************/
/* Take a copy of the instance info before signalling that the */
/* thread has started. */
/************************************************************************/
pThreadParam = pInfo->threadParam;
/************************************************************************/
/* Flag that initialisation has succeeded. */
/* NOTE: from now on, pInfo is not valid. Set it to NULL to make sure */
/* no-one tries to dereference it. */
/************************************************************************/
SetEvent((HANDLE)pInfo->sync);
pInfo = NULL;
/************************************************************************/
/* Call the thread entry point. This executes a message loop. */
/************************************************************************/
pFunc(pThreadParam);
DC_END_FN();
return(0);
}
/****************************************************************************/
/* Name: UTStopThread */
/* */
/* Purpose: End a child thread */
/* */
/* Returns: TRUE if successful, FALSE otherwise */
/* */
/* Params: IN threadData - thread data */
/* */
/* Operation: Post WM_QUIT to the thread. */
/* */
/****************************************************************************/
DCBOOL DCINTERNAL CUT::UTStopThread(UT_THREAD_DATA threadData,
BOOL fPumpMessages)
{
DCBOOL rc;
DWORD retval;
DWORD dwThreadTimeout;
DC_BEGIN_FN("UTStopThread");
//
// Bail out if we try to end a thread that never got created in the first
// place
//
if (0 == threadData.threadID) {
rc = FALSE;
TRC_ERR((TB, _T("Trying to end thread ID %#x hnd: 0x%x"),
threadData.threadID,
threadData.threadHnd));
DC_QUIT;
}
//
// Post WM_QUIT to the thread.
//
TRC_NRM((TB, _T("Attempt to stop thread %#x"), threadData.threadID));
if (PostThreadMessage(threadData.threadID, WM_QUIT, 0, 0))
{
rc = TRUE;
}
else
{
TRC_ERR((TB, _T("Failed to end thread ID %#x"), threadData.threadID));
rc = FALSE;
}
//
// Free build waits forever, checked build can be set to timeout
// to help debug deadlocks. A lot of problems become apparent
// in stress if the wait times out and the code is allowed to continue.
//
#ifdef DC_DEBUG
dwThreadTimeout = _UT.dwDebugThreadWaitTimeout;
#else
dwThreadTimeout = INFINITE;
#endif
//
// Wait for thread to complete.
//
TRC_NRM((TB, _T("Wait for thread %#x to die"), threadData.threadID));
if (fPumpMessages) {
retval = CUT::UT_WaitWithMessageLoop((HANDLE)(threadData.threadHnd),
dwThreadTimeout);
}
else {
retval = WaitForSingleObject((HANDLE)(threadData.threadHnd),
dwThreadTimeout);
}
if (retval == WAIT_TIMEOUT)
{
TRC_ABORT((TB,
_T("Timeout waiting for threadID %#x handle %#x termination"),
threadData.threadID, threadData.threadHnd));
}
else
{
TRC_ALT((TB, _T("Thread id %#x exited."), threadData.threadID));
}
DC_EXIT_POINT:
DC_END_FN();
return(rc);
} /* UTStopThread */
/****************************************************************************/
/* FUNCTION: UTGetCurrentTime(...) */
/* */
/* DESCRIPTION: */
/* ============ */
/* Get the current system time. */
/* */
/* PARAMETERS: */
/* =========== */
/* pTime : pointer to the time structure to be filled with the */
/* current time. */
/* */
/* RETURNS: */
/* ======== */
/* Nothing. */
/* */
/****************************************************************************/
DCVOID DCINTERNAL CUT::UTGetCurrentTime(PDC_TIME pTime)
{
SYSTEMTIME sysTime;
DC_BEGIN_FN("UTGetCurrentTime");
/************************************************************************/
/* Get the system time */
/************************************************************************/
GetSystemTime(&sysTime);
/************************************************************************/
/* Now convert it to a DC_TIME - this isn't hard since the structures */
/* are very similar. */
/************************************************************************/
pTime->hour = (DCUINT8)sysTime.wHour;
pTime->min = (DCUINT8)sysTime.wMinute;
pTime->sec = (DCUINT8)sysTime.wSecond;
pTime->hundredths = (DCUINT8)(sysTime.wMilliseconds / 10);
DC_END_FN();
return;
} /* UTGetCurrentTime */
/****************************************************************************/
/* FUNCTION: UTGetCurrentDate(...) */
/* */
/* DESCRIPTION: */
/* ============ */
/* Get the current system date. */
/* */
/* PARAMETERS: */
/* =========== */
/* pDate : pointer to the date structure to be filled with the */
/* current date. */
/* */
/* RETURNS: */
/* ======== */
/* Nothing. */
/* */
/****************************************************************************/
DCVOID DCINTERNAL CUT::UTGetCurrentDate(PDC_DATE pDate)
{
SYSTEMTIME sysTime;
DC_BEGIN_FN("UTGetCurrentDate");
/************************************************************************/
/* Get the system time */
/************************************************************************/
GetSystemTime(&sysTime);
/************************************************************************/
/* Now convert it to a DC_DATE - this isn't hard since the structures */
/* are very similar. */
/************************************************************************/
pDate->day = (DCUINT8)sysTime.wDay;
pDate->month = (DCUINT8)sysTime.wMonth;
pDate->year = (DCUINT16)sysTime.wYear;
DC_END_FN();
return;
} /* UTGetCurrentDate */
/****************************************************************************/
/* Name: UTReadEntry */
/* */
/* Purpose: Read an entry from the given section of the registry */
/* */
/* Returns: TRUE if successful, FALSE otherwise */
/* */
/* Params: . */
/* topLevelKey : one of: */
/* - HKEY_CURRENT_USER */
/* - HKEY_LOCAL_MACHINE */
/* pSection : the section name to read from. The product prefix */
/* string is prepended to give the full name. */
/* pEntry : the entry name to read. */
/* pBuffer : a buffer to read the entry to. */
/* bufferSize : the size of the buffer. */
/* expectedDataType : the type of data stored in the entry. */
/* */
/****************************************************************************/
DCBOOL DCINTERNAL CUT::UTReadEntry(HKEY topLevelKey,
PDCTCHAR pSection,
PDCTCHAR pEntry,
PDCUINT8 pBuffer,
DCINT bufferSize,
DCINT32 expectedDataType)
{
LONG sysrc;
HKEY key;
DCINT32 dataType;
DCINT32 dataSize;
DCTCHAR subKey[UT_MAX_SUBKEY];
DCBOOL keyOpen = FALSE;
DCBOOL rc = FALSE;
DC_BEGIN_FN("UTReadEntry");
/************************************************************************/
/* Get a subkey for the value. */
/************************************************************************/
UtMakeSubKey(subKey, SIZE_TCHARS(subKey), pSection);
/************************************************************************/
/* Try to open the key. If the entry does not exist, RegOpenKeyEx will */
/* fail. */
/************************************************************************/
sysrc = RegOpenKeyEx(topLevelKey,
subKey,
0, /* reserved */
KEY_READ,
&key);
if (sysrc != ERROR_SUCCESS)
{
/********************************************************************/
/* Don't trace an error here since the subkey may not exist... */
/********************************************************************/
TRC_NRM((TB, _T("Failed to open key %s, rc = %ld"), subKey, sysrc));
DC_QUIT;
}
keyOpen = TRUE;
/************************************************************************/
/* We successfully opened the key so now try to read the value. Again */
/* it may not exist. */
/************************************************************************/
dataSize = (DCINT32)bufferSize;
sysrc = RegQueryValueEx(key,
pEntry,
0, /* reserved */
(LPDWORD)&dataType,
(LPBYTE)pBuffer,
(LPDWORD)&dataSize);
if (sysrc != ERROR_SUCCESS)
{
TRC_NRM((TB, _T("Failed to read value of [%s] %s, rc = %ld"),
pSection,
pEntry,
sysrc));
DC_QUIT;
}
/************************************************************************/
/* Check that the type is correct. Special case: allow REG_BINARY */
/* instead of REG_DWORD, as long as the length is 32 bits. */
/************************************************************************/
if ((dataType != expectedDataType) &&
((dataType != REG_BINARY) ||
(expectedDataType != REG_DWORD) ||
(dataSize != 4)))
{
TRC_ALT((TB,_T("Read value from [%s] %s, but type is %ld - expected %ld"),
pSection,
pEntry,
dataType,
expectedDataType));
DC_QUIT;
}
rc = TRUE;
DC_EXIT_POINT:
/************************************************************************/
/* Close the key (if required). */
/************************************************************************/
if (keyOpen)
{
sysrc = RegCloseKey(key);
if (sysrc != ERROR_SUCCESS)
{
TRC_ERR((TB, _T("Failed to close key, rc = %ld"), sysrc));
}
}
DC_END_FN();
return(rc);
} /* UTReadEntry */
/****************************************************************************/
/* Name: UTWriteEntry */
/* */
/* Purpose: Write an entry to the given section of the registry */
/* */
/* Returns: TRUE if successful, FALSE otherwise */
/* */
/* Params: . */
/* topLevelKey : one of: */
/* - HKEY_CURRENT_USER */
/* - HKEY_LOCAL_MACHINE */
/* pSection : the section name to write to. The product prefix */
/* string is prepended to give the full name. */
/* pEntry : the entry name to write */
/* pData : a pointer to the data to write */
/* dataSize : the size of the data to be written. For strings */
/* this must include the NULL terminator */
/* expectedDataType : the type of data to be written */
/* */
/****************************************************************************/
DCBOOL DCINTERNAL CUT::UTWriteEntry(HKEY topLevelKey,
PDCTCHAR pSection,
PDCTCHAR pEntry,
PDCUINT8 pData,
DCINT dataSize,
DCINT32 dataType)
{
LONG sysrc;
HKEY key;
DCTCHAR subKey[UT_MAX_SUBKEY];
DWORD disposition;
DCBOOL keyOpen = FALSE;
DCBOOL rc = FALSE;
DC_BEGIN_FN("UTWriteEntry");
/************************************************************************/
/* Get a subkey for the value. */
/************************************************************************/
UtMakeSubKey(subKey, SIZE_TCHARS(subKey), pSection);
/************************************************************************/
/* Try to create the key. If the entry already exists, RegCreateKeyEx */
/* will open the existing entry. */
/************************************************************************/
sysrc = RegCreateKeyEx(topLevelKey,
subKey,
0, /* reserved */
NULL, /* class */
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL, /* security attributes */
&key,
&disposition);
if (sysrc != ERROR_SUCCESS)
{
TRC_ERR((TB, _T("Failed to create / open key %s, rc = %ld"),
subKey, sysrc));
DC_QUIT;
}
keyOpen = TRUE;
TRC_NRM((TB, _T("%s key %s"),
(disposition == REG_CREATED_NEW_KEY) ? "Created" : "Opened",
subKey));
/************************************************************************/
/* We've got the key, so set the value. */
/************************************************************************/
sysrc = RegSetValueEx(key,
pEntry,
0, /* reserved */
dataType,
(LPBYTE)pData,
(DCINT32)dataSize);
if (sysrc != ERROR_SUCCESS)
{
TRC_ERR((TB, _T("Failed to write value to [%s] %s, rc = %ld"),
pSection,
pEntry,
sysrc));
DC_QUIT;
}
rc = TRUE;
DC_EXIT_POINT:
/************************************************************************/
/* Close the key (if required) */
/************************************************************************/
if (keyOpen)
{
sysrc = RegCloseKey(key);
if (sysrc != ERROR_SUCCESS)
{
TRC_ERR((TB, _T("Failed to close key, rc = %ld"), sysrc));
}
}
DC_END_FN();
return(rc);
} /* UTWriteEntry */
/****************************************************************************/
/* Name: UTDeleteEntry */
/* */
/* Purpose: Deletes an entry from the registry */
/* */
/* Returns: TRUE if successful, FALSE otherwise */
/* */
/* Params: IN pSection - the section name of the entry to delete */
/* IN pEntry - the actual entry to delete */
/* */
/****************************************************************************/
DCBOOL DCINTERNAL CUT::UTDeleteEntry(PDCTCHAR pSection,
PDCTCHAR pEntry)
{
LONG sysrc;
HKEY key;
DCTCHAR subKey[UT_MAX_SUBKEY];
DCBOOL keyOpen = FALSE;
DCBOOL rc = FALSE;
DC_BEGIN_FN("UTDeleteEntry");
/************************************************************************/
/* Get a subkey for the value. */
/************************************************************************/
UtMakeSubKey(subKey, SIZE_TCHARS(subKey), pSection);
/************************************************************************/
/* Try to open the key. If the entry does not exist, RegOpenKeyEx will */
/* fail. */
/************************************************************************/
sysrc = RegOpenKeyEx(HKEY_CURRENT_USER,
subKey,
0, /* reserved */
KEY_WRITE,
&key);
if (sysrc != ERROR_SUCCESS)
{
/********************************************************************/
/* Don't trace an error here since the subkey may not exist... */
/********************************************************************/
TRC_NRM((TB, _T("Failed to open key %s, rc = %ld"), subKey, sysrc));
DC_QUIT;
}
keyOpen = TRUE;
/************************************************************************/
/* Now try to delete the entry. */
/************************************************************************/
sysrc = RegDeleteValue(key, pEntry);
if (sysrc != ERROR_SUCCESS)
{
/********************************************************************/
/* We failed to delete the entry - this is quite acceptable as it */
/* may never have existed... */
/********************************************************************/
TRC_NRM((TB, _T("Failed to delete entry %s from section %s"),
pEntry,
pSection));
}
rc = TRUE;
DC_EXIT_POINT:
/************************************************************************/
/* Close the key (if required). */
/************************************************************************/
if (keyOpen)
{
sysrc = RegCloseKey(key);
if (sysrc != ERROR_SUCCESS)
{
TRC_ERR((TB, _T("Failed to close key, rc = %ld"), sysrc));
}
}
DC_END_FN();
return(rc);
} /* UTDeleteEntry */
/****************************************************************************/
/* Name: UTEnumRegistry */
/* */
/* Purpose: Enumerate keys from registry */
/* */
/* Returns: TRUE - registry key returned */
/* FALSE - no more registry keys to enumerate */
/* */
/* Params: IN pSection - registy section */
/* IN index - index of key to enumerate */
/* OUT pBuffer - output buffer */
/* IN bufferSize - output buffer size */
/* */
/* Operation: */
/* */
/****************************************************************************/
DCBOOL DCINTERNAL CUT::UTEnumRegistry( PDCTCHAR pSection,
DCUINT32 index,
PDCTCHAR pBuffer,
PDCINT pBufferSize )
{
LONG sysrc;
DCTCHAR subKey[UT_MAX_SUBKEY];
DCBOOL rc = FALSE;
FILETIME fileTime;
DC_BEGIN_FN("UTEnumRegistry");
/************************************************************************/
/* Get a subkey for the value. */
/************************************************************************/
UtMakeSubKey(subKey, SIZE_TCHARS(subKey), pSection);
/************************************************************************/
/* First time - open the key. Try HKCU first. */
/************************************************************************/
if (index == 0)
{
sysrc = RegOpenKeyEx(HKEY_CURRENT_USER,
subKey,
0,
KEY_READ,
&_UT.enumHKey);
TRC_NRM((TB, _T("Open HKCU %s, rc %d"), subKey, sysrc));
if (sysrc != ERROR_SUCCESS)
{
/****************************************************************/
/* Didn't find HKCU - try HKLM */
/****************************************************************/
sysrc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
subKey,
0,
KEY_READ,
&_UT.enumHKey);
TRC_NRM((TB, _T("Open HKLM %s, rc %d"), subKey, sysrc));
if (sysrc != ERROR_SUCCESS)
{
/************************************************************/
/* Didn't find HKLM either - give up */
/************************************************************/
TRC_ALT((TB, _T("Didn't find subkey %s - give up"), subKey));
DC_QUIT;
}
}
}
TRC_ASSERT((_UT.enumHKey != 0), (TB,_T("0 hKey")));
/************************************************************************/
/* If we get here, we have opened a key - do the enumeration now */
/************************************************************************/
sysrc = RegEnumKeyEx(_UT.enumHKey,
index,
pBuffer,
(PDCUINT32)pBufferSize,
NULL, NULL, NULL,
&fileTime);
/************************************************************************/
/* If it worked, set the return code */
/************************************************************************/
if (sysrc == ERROR_SUCCESS)
{
TRC_NRM((TB, _T("Enumerated key OK")));
rc = TRUE;
}
else
{
/********************************************************************/
/* End of enumeration - close the key */
/********************************************************************/
TRC_NRM((TB, _T("End of enumeration, rc %ld"), sysrc));
sysrc = RegCloseKey(_UT.enumHKey);
if (sysrc != ERROR_SUCCESS)
{
TRC_ERR((TB, _T("Failed to close key, rc = %ld"), sysrc));
}
_UT.enumHKey = 0;
}
DC_EXIT_POINT:
DC_END_FN();
return(rc);
} /* UTEnumRegistry */