Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1388 lines
34 KiB

/****************************** Module Header ******************************\
* Module Name: winutil.c
*
* Copyright (c) 1991, Microsoft Corporation
*
* Implements windows specific utility functions
*
* History:
* 12-09-91 Davidc Created.
\***************************************************************************/
#include "msgina.h"
#include <stdio.h>
#include <wchar.h>
//
// Define this if you want a verbose commentary from these routines
//
// #define VERBOSE_UTILS
#ifdef VERBOSE_UTILS
#define VerbosePrint(s) WLPrint(s)
#else
#define VerbosePrint(s)
#endif
/***************************************************************************\
* SetupSystemMenu
*
* Purpose : Does any manipulation required for a dialog system menu.
* Should be called during WM_INITDIALOG processing for a dialog
*
* History:
* 12-09-91 Davidc Created.
\***************************************************************************/
VOID
SetupSystemMenu(
HWND hDlg
)
{
// Remove the Close item from the system menu if we don't
// have a CANCEL button
if (GetDlgItem(hDlg, IDCANCEL) == NULL) {
HMENU hMenu = GetSystemMenu(hDlg, FALSE);
if (hMenu)
{
DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
}
}
}
/***************************************************************************\
* CentreWindow
*
* Purpose : Positions a window so that it is centred in its parent
*
* History:
* 12-09-91 Davidc Created.
\***************************************************************************/
VOID
CentreWindow(
HWND hwnd
)
{
RECT rect;
LONG dx, dy;
LONG dxParent, dyParent;
LONG Style;
// Get window rect
GetWindowRect(hwnd, &rect);
dx = rect.right - rect.left;
dy = rect.bottom - rect.top;
// Get parent rect
Style = GetWindowLong(hwnd, GWL_STYLE);
if ((Style & WS_CHILD) == 0) {
// Return the desktop windows size (size of main screen)
dxParent = GetSystemMetrics(SM_CXSCREEN);
dyParent = GetSystemMetrics(SM_CYSCREEN);
} else {
HWND hwndParent;
RECT rectParent;
hwndParent = GetParent(hwnd);
if (hwndParent == NULL) {
hwndParent = GetDesktopWindow();
}
GetWindowRect(hwndParent, &rectParent);
dxParent = rectParent.right - rectParent.left;
dyParent = rectParent.bottom - rectParent.top;
}
// Centre the child in the parent
rect.left = (dxParent - dx) / 2;
rect.top = (dyParent - dy) / 3;
// Move the child into position
SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, 0, 0, SWP_NOSIZE);
SetForegroundWindow(hwnd);
}
/***************************************************************************\
* SetPasswordFocus
*
* Sets the focus window in a dialog to the first empty control in
* the list IDD_LOGON_DOMAIN, IDD_NEW_PASSWORD
* This routine would normally be called during WM_INITDIALOG processing.
*
* Returns FALSE if the focus was set, otherwise TRUE - this value can
* be used as the return value to the WM_INITDIALOG message.
*
* History:
* 12-09-91 Davidc Created.
\***************************************************************************/
BOOL
SetPasswordFocus(
HWND hDlg
)
{
int ids[] = { IDD_LOGON_NAME,
IDD_LOGON_DOMAIN,
IDD_LOGON_PASSWORD,
IDD_UNLOCK_PASSWORD,
IDD_CHANGEPWD_OLD,
IDD_CHANGEPWD_NEW,
IDD_NEW_PASSWORD
};
SHORT Index;
HWND hwndFocus = NULL;
// Set focus to first enabled, visible, empty field
for (Index = 0; Index < sizeof(ids)/sizeof(*ids); Index ++) {
int idControl = ids[Index];
HWND hwndControl;
hwndControl = GetDlgItem(hDlg, idControl);
if (hwndControl != NULL) {
if ( (GetWindowTextLength(hwndControl) == 0) &&
((GetWindowLong(hwndControl, GWL_STYLE) &
(WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)) {
hwndFocus = hwndControl;
break;
}
}
}
if (hwndFocus != NULL) {
SetFocus(hwndFocus);
}
return(hwndFocus == NULL);
}
//
// Globals used to store cursor handles for SetupCursor
//
static HCURSOR hCursorArrow = NULL;
static HCURSOR hCursorWait = NULL;
/***************************************************************************\
* SetupCursor
*
* Sets the cursor to an hourglass if fWait = TRUE, otherwise sets it
* to an arrow.
*
* History:
* 12-09-91 Davidc Created.
\***************************************************************************/
VOID
SetupCursor(
BOOL fWait
)
{
if (hCursorArrow == NULL) {
hCursorArrow = LoadCursor(NULL, IDC_ARROW);
}
if (hCursorWait == NULL) {
hCursorWait = LoadCursor(NULL, IDC_WAIT);
}
SetCursor(fWait ? hCursorWait : hCursorArrow);
}
/****************************************************************************
FUNCTION: TimeFieldsToSystemTime
PURPOSE: Converts a TIME_FIELDS structure into a SYSTEMTIME structure
RETURNS : nothing
History:
05-15-93 RobertRe Created.
****************************************************************************/
VOID
TimeFieldsToSystemTime(
IN PTIME_FIELDS TimeFields,
OUT LPSYSTEMTIME SystemTime
)
{
SystemTime->wYear = TimeFields->Year ;
SystemTime->wMonth = TimeFields->Month ;
SystemTime->wDayOfWeek = TimeFields->Weekday ;
SystemTime->wDay = TimeFields->Day ;
SystemTime->wHour = TimeFields->Hour ;
SystemTime->wMinute = TimeFields->Minute ;
SystemTime->wSecond = TimeFields->Second ;
SystemTime->wMilliseconds = TimeFields->Milliseconds;
return;
}
/****************************************************************************
FUNCTION: FormatTime
PURPOSE: Converts a system time into a readable string(in local time).
if flags contains FT_TIME the time appears in the string
if flags contains FT_DATE the date appears in the string.
if both values appear, the string contains date then time.
RETURNS : TRUE on success, FALSE on failure
****************************************************************************/
BOOL
FormatTime(
IN PTIME Time,
IN OUT PWCHAR Buffer,
IN ULONG BufferLength,
IN USHORT Flags
)
{
NTSTATUS Status;
TIME_FIELDS TimeFields;
TIME LocalTime;
SYSTEMTIME SystemTime;
//
// Terminate the string in case they didn't pass any flags
//
if (BufferLength > 0) {
Buffer[0] = 0;
}
//
// Convert the system time to local time
//
Status = RtlSystemTimeToLocalTime(Time, &LocalTime);
if (!NT_SUCCESS(Status)) {
WLPrint(("Failed to convert system time to local time, status = 0x%lx", Status));
return(FALSE);
}
//
// Split the time into its components
//
RtlTimeToTimeFields(&LocalTime, &TimeFields);
TimeFieldsToSystemTime( &TimeFields, &SystemTime );
//
// Format the string
//
if (Flags & FT_DATE) {
int Length;
WCHAR DateString[256];
Length = GetDateFormatW(GetUserDefaultLCID(),
DATE_SHORTDATE | LOCALE_NOUSEROVERRIDE,
&SystemTime,
NULL,
DateString,
256
);
Length = _snwprintf( Buffer,
BufferLength,
TEXT("%s"),
DateString
);
Buffer += Length;
BufferLength -= Length;
}
if (Flags & FT_TIME) {
int Length;
WCHAR TimeString[256];
if (Flags & FT_DATE) {
if (BufferLength > 0) {
*Buffer++ = TEXT(' ');
BufferLength --;
}
}
Length = GetTimeFormatW(GetUserDefaultLCID(),
LOCALE_NOUSEROVERRIDE,
&SystemTime,
NULL,
TimeString,
256
);
_snwprintf(Buffer, BufferLength,
TEXT("%s"),
TimeString
);
}
return(TRUE);
}
/***************************************************************************\
* DuplicateUnicodeString
*
* Purpose : Allocates space for new string then copies new into old.
* The new string is always 0 terminated
* The new string should be free using RtlFreeUnicodeString()
*
* Returns : TRUE on success, FALSE on failure
*
* History:
* 11-04-92 Davidc Created.
\***************************************************************************/
BOOL
DuplicateUnicodeString(
PUNICODE_STRING OutString,
PUNICODE_STRING InString
)
{
NTSTATUS Status;
ANSI_STRING AnsiString;
ASSERT( OutString != NULL );
ASSERT( InString != NULL );
//
// This sucks, but we cannot get at the rtl allocation routine
// so we can't do the allocation ourselves
//
Status = RtlUnicodeStringToAnsiString(&AnsiString, InString, TRUE);
if (NT_SUCCESS(Status)) {
Status = RtlAnsiStringToUnicodeString(OutString, &AnsiString, TRUE);
RtlFreeAnsiString(&AnsiString);
}
return(NT_SUCCESS(Status));
}
/***************************************************************************\
* UnicodeStringToString
*
* Purpose : Converts a unicode string to it's local format and allocates
* space for it. The returned NULL terminated string can be freed
* using Free()
*
* Returns : Pointer to NULL terminated string or NULL on failure.
*
* History:
* 11-04-92 Davidc Created.
\***************************************************************************/
LPTSTR
UnicodeStringToString(
PUNICODE_STRING UnicodeString
)
{
LPTSTR String;
ULONG BytesRequired = sizeof(TCHAR)*(UnicodeString->Length + 1);
String = Alloc(BytesRequired);
if (String != NULL) {
if (UnicodeString->Length && UnicodeString->Buffer ) {
lstrcpy(String, UnicodeString->Buffer);
} else {
Free(String);
String = 0;
}
}
return(String);
}
/***************************************************************************\
* FUNCTION: PaintBitmapWindow
*
* PURPOSE: Paints a bitmap in the specified dialog control window
*
* RETURNS: TRUE on success, FALSE on failure
*
* HISTORY:
*
* 01-29-92 Davidc Created.
*
\***************************************************************************/
BOOL
PaintBitmapWindow(
HWND hDlg,
HINSTANCE hInstance,
int ControlId,
WORD BitmapId
)
{
HWND hwndWindow;
RECT rcWindow;
PAINTSTRUCT PaintStruct;
HDC hdcDlg;
HDC hdcBitmap;
HBITMAP hbmBitmap;
HBITMAP hbmSave;
BITMAP BitmapInfo;
LONG cxBitmap, cyBitmap;
LONG cxWindow, cyWindow;
LONG cxBorder, cyBorder;
//
// Get the bitmap control window
//
hwndWindow = GetDlgItem(hDlg, ControlId);
if (hwndWindow == NULL) {
DebugLog((DEB_ERROR, "PaintBitmapWindow: couldn't find bitmap window id = %d in dialog 0x%lx\n", ControlId, hDlg));
return(FALSE);
}
//
// Get the position of the bitmap window relative to the dialog
//
GetWindowRect(hwndWindow, &rcWindow);
cxWindow = rcWindow.right - rcWindow.left;
cyWindow = rcWindow.bottom - rcWindow.top;
ScreenToClient(hDlg, &(((LPPOINT)&rcWindow)[0]));
ScreenToClient(hDlg, &(((LPPOINT)&rcWindow)[1]));
//
// Get a DC for the dialog window
//
hdcDlg = BeginPaint(hDlg, &PaintStruct);
if (hdcDlg == NULL) {
DebugLog((DEB_ERROR, "PaintBitmapWindow : Couldn't get DC for dialog window\n"));
return(FALSE);
}
//
// Get a DC for the bitmap
//
hdcBitmap = CreateCompatibleDC(hdcDlg);
hbmBitmap = LoadBitmap(hInstance, (LPTSTR) MAKEINTRESOURCE(BitmapId));
hbmSave = SelectObject(hdcBitmap, hbmBitmap);
//
// Get bitmap size
//
GetObject(hbmBitmap, sizeof(BitmapInfo), (LPVOID)&BitmapInfo);
cxBitmap = BitmapInfo.bmWidth;
cyBitmap = BitmapInfo.bmHeight;
//
// Calculate space around bitmap when centred in window
//
cxBorder = (cxWindow - cxBitmap) / 2;
cyBorder = (cyWindow - cyBitmap) / 2;
//
// Adjust the window rectangle to the size of the bitmap
//
InflateRect(&rcWindow, -cxBorder, -cyBorder);
//
// Copy the bitmap to the screen (centred in the bitmap window)
//
BitBlt(hdcDlg, rcWindow.left, rcWindow.top, cxBitmap, cyBitmap,
hdcBitmap, 0, 0, SRCCOPY);
//
// Put the original object back in the bitmap DC
//
SelectObject(hdcBitmap, hbmSave);
//
// Free up the bitmap DC
//
DeleteDC(hdcBitmap);
//
// Free the bitmap
//
DeleteObject(hbmBitmap);
//
// Release the DC for the dialog window
//
return EndPaint(hDlg, &PaintStruct);
}
/***************************************************************************\
* FUNCTION: OpenIniFileUserMapping
*
* PURPOSE: Forces the ini file mapping apis to reference the current user's
* registry.
*
* RETURNS: TRUE on success, FALSE on failure
*
* HISTORY:
*
* 24-Aug-92 Davidc Created.
*
\***************************************************************************/
BOOL
OpenIniFileUserMapping(
PGLOBALS pGlobals
)
{
BOOL Result;
HANDLE ImpersonationHandle;
//
// Impersonate the user
//
ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL);
if (ImpersonationHandle == NULL) {
DebugLog((DEB_ERROR, "OpenIniFileUserMapping failed to impersonate user"));
return(FALSE);
}
Result = OpenProfileUserMapping();
if (!Result) {
DebugLog((DEB_ERROR, "OpenProfileUserMapping failed, error = %d", GetLastError()));
}
//
// Revert to being 'ourself'
//
if (!StopImpersonating(ImpersonationHandle)) {
DebugLog((DEB_ERROR, "OpenIniFileUserMapping failed to revert to self"));
}
return(Result);
}
/***************************************************************************\
* FUNCTION: CloseIniFileUserMapping
*
* PURPOSE: Closes the ini file mapping to the user's registry such
* that future use of the ini apis will fail if they reference
* the user's registry.
*
* RETURNS: Nothing
*
* HISTORY:
*
* 24-Aug-92 Davidc Created.
*
\***************************************************************************/
VOID
CloseIniFileUserMapping(
PGLOBALS pGlobals
)
{
BOOL Result;
Result = CloseProfileUserMapping();
if (!Result) {
DebugLog((DEB_ERROR, "CloseProfileUserMapping failed, error = %d", GetLastError()));
}
UNREFERENCED_PARAMETER(pGlobals);
}
/***************************************************************************\
* FUNCTION: AllocAndGetDlgItemText
*
* PURPOSE: Allocates memory for and returns pointer to a copy of the text
* in the specified dialog control.
* The returned string should be freed using Free()
*
* RETURNS: Pointer to copy of dlg item text, or NULL on failure.
*
* HISTORY:
*
* 9-Sep-92 Davidc Created.
*
\***************************************************************************/
LPTSTR
AllocAndGetDlgItemText(
HWND hDlg,
int iItem
)
{
HWND hwnd;
LPTSTR String;
LONG Length;
LONG BytesRequired;
LONG LengthCopied;
//
// Go find the window handle of the control
//
hwnd = GetDlgItem(hDlg, iItem);
if (hwnd == NULL) {
DebugLog((DEB_ERROR, "AllocAndGetDlgItemText : Couldn't find control %d in dialog 0x%lx", iItem, hDlg));
ASSERT(hwnd != NULL);
return(NULL);
}
//
// Get the length of the control's text
//
Length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
if (Length < 0) {
DebugLog((DEB_ERROR, "AllocAndGetDlgItemText : Dialog control text length < 0 (%d)", Length));
ASSERT(Length >= 0);
return(NULL);
}
//
// Calculate the bytes required for the string.
// The length doesn't include the terminator
//
Length ++; // Add one for terminator
BytesRequired = Length * sizeof(TCHAR);
String = (LPTSTR)Alloc(BytesRequired);
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndGetDlgItemText : Failed to allocate %d bytes for dialog control text", BytesRequired));
return(NULL);
}
//
// Fill in the allocated block with the text
//
LengthCopied = SendMessage(hwnd, WM_GETTEXT, Length, (LPARAM)String);
if (LengthCopied != (Length - 1)) {
DebugLog((DEB_ERROR, "AllocAndGetDlgItemText : WM_GETTEXT for %d chars only copied %d chars", Length-1, LengthCopied));
ASSERT(LengthCopied == (Length - 1));
Free(String);
return(NULL);
}
return(String);
}
/***************************************************************************\
* FUNCTION: AllocAndGetPrivateProfileString
*
* PURPOSE: Allocates memory for and returns pointer to a copy of the
* specified profile string
* The returned string should be freed using Free()
*
* RETURNS: Pointer to copy of profile string or NULL on failure.
*
* HISTORY:
*
* 12-Nov-92 Davidc Created.
*
\***************************************************************************/
LPTSTR
AllocAndGetPrivateProfileString(
LPCTSTR lpAppName,
LPCTSTR lpKeyName,
LPCTSTR lpDefault,
LPCTSTR lpFileName
)
{
LPTSTR String;
LONG LengthAllocated;
LONG LengthCopied;
//
// Pick a random buffer length, if it's not big enough reallocate
// it and try again until it is.
//
LengthAllocated = TYPICAL_STRING_LENGTH;
String = Alloc(LengthAllocated * sizeof(TCHAR));
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndGetPrivateProfileString : Failed to allocate %d bytes for string", LengthAllocated * sizeof(TCHAR)));
return(NULL);
}
while (TRUE) {
LengthCopied = GetPrivateProfileString( lpAppName,
lpKeyName,
lpDefault,
String,
LengthAllocated,
lpFileName
);
//
// If the returned value is our passed size - 1 (weird way for error)
// then our buffer is too small. Make it bigger and start over again.
//
if (LengthCopied == (LengthAllocated - 1)) {
VerbosePrint(("AllocAndGetPrivateProfileString: Failed with buffer length = %d, reallocating and retrying", LengthAllocated));
LengthAllocated *= 2;
String = ReAlloc(String, LengthAllocated * sizeof(TCHAR));
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndGetPrivateProfileString : Failed to reallocate %d bytes for string", LengthAllocated * sizeof(TCHAR)));
break;
}
//
// Go back and try to read it again
//
} else {
//
// Success!
//
break;
}
}
return(String);
}
/***************************************************************************\
* FUNCTION: WritePrivateProfileInt
*
* PURPOSE: Writes out an integer to a profile file
*
* RETURNS: TRUE on success, FALSE on failure
*
* HISTORY:
*
* 12-Nov-92 Davidc Created.
*
\***************************************************************************/
BOOL
WritePrivateProfileInt(
LPCTSTR lpAppName,
LPCTSTR lpKeyName,
UINT Value,
LPCTSTR lpFileName
)
{
NTSTATUS Status;
TCHAR String[30];
UNICODE_STRING UniString;
UniString.MaximumLength = 30;
UniString.Buffer = String;
Status = RtlIntegerToUnicodeString(Value,10,&UniString);
if (!NT_SUCCESS(Status)) {
return(FALSE);
}
return (WritePrivateProfileString(lpAppName, lpKeyName, UniString.Buffer, lpFileName));
}
/***************************************************************************\
* FUNCTION: AllocAndExpandEnvironmentStrings
*
* PURPOSE: Allocates memory for and returns pointer to buffer containing
* the passed string expanded to include environment strings
* The returned buffer should be freed using Free()
*
* RETURNS: Pointer to expanded string or NULL on failure.
*
* HISTORY:
*
* 21-Dec-92 Davidc Created.
*
\***************************************************************************/
LPTSTR
AllocAndExpandEnvironmentStrings(
LPCTSTR lpszSrc
)
{
LPTSTR String;
LONG LengthAllocated;
LONG LengthCopied;
//
// Pick a random buffer length, if it's not big enough reallocate
// it and try again until it is.
//
LengthAllocated = lstrlen(lpszSrc) + TYPICAL_STRING_LENGTH;
String = Alloc(LengthAllocated * sizeof(TCHAR));
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndExpandEnvironmentStrings : Failed to allocate %d bytes for string", LengthAllocated * sizeof(TCHAR)));
return(NULL);
}
while (TRUE) {
LengthCopied = ExpandEnvironmentStrings( lpszSrc,
String,
LengthAllocated
);
if (LengthCopied == 0) {
DebugLog((DEB_ERROR, "AllocAndExpandEnvironmentStrings : ExpandEnvironmentStrings failed, error = %d", GetLastError()));
Free(String);
String = NULL;
break;
}
//
// If the buffer was too small, make it bigger and try again
//
if (LengthCopied > LengthAllocated) {
VerbosePrint(("AllocAndExpandEnvironmentStrings: Failed with buffer length = %d, reallocating to %d and retrying (retry should succeed)", LengthAllocated, LengthCopied));
String = ReAlloc(String, LengthCopied * sizeof(TCHAR));
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndExpandEnvironmentStrings : Failed to reallocate %d bytes for string", LengthAllocated * sizeof(TCHAR)));
break;
}
//
// Go back and try to expand the string again
//
} else {
//
// Success!
//
break;
}
}
return(String);
}
/***************************************************************************\
* FUNCTION: AllocAndRegEnumKey
*
* PURPOSE: Allocates memory for and returns pointer to buffer containing
* the next registry sub-key name under the specified key
* The returned buffer should be freed using Free()
*
* RETURNS: Pointer to sub-key name or NULL on failure. The reason for the
* error can be obtains using GetLastError()
*
* HISTORY:
*
* 21-Dec-92 Davidc Created.
*
\***************************************************************************/
LPTSTR
AllocAndRegEnumKey(
HKEY hKey,
DWORD iSubKey
)
{
LPTSTR String;
LONG LengthAllocated;
//
// Pick a random buffer length, if it's not big enough reallocate
// it and try again until it is.
//
LengthAllocated = TYPICAL_STRING_LENGTH;
String = Alloc(LengthAllocated * sizeof(TCHAR));
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndRegEnumKey : Failed to allocate %d bytes for string", LengthAllocated * sizeof(TCHAR)));
return(NULL);
}
while (TRUE) {
DWORD Error = RegEnumKey(hKey, iSubKey, String, LengthAllocated);
if (Error == ERROR_SUCCESS) {
break;
}
if (Error != ERROR_MORE_DATA) {
if (Error != ERROR_NO_MORE_ITEMS) {
DebugLog((DEB_ERROR, "AllocAndRegEnumKey : RegEnumKey failed, error = %d", Error));
}
Free(String);
String = NULL;
SetLastError(Error);
break;
}
//
// The buffer was too small, make it bigger and try again
//
VerbosePrint(("AllocAndRegEnumKey: Failed with buffer length = %d, reallocating and retrying", LengthAllocated));
LengthAllocated *= 2;
String = ReAlloc(String, LengthAllocated * sizeof(TCHAR));
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndRegEnumKey : Failed to reallocate %d bytes for string", LengthAllocated * sizeof(TCHAR)));
break;
}
}
return(String);
}
/***************************************************************************\
* FUNCTION: AllocAndRegQueryValueEx
*
* PURPOSE: Version of RegQueryValueEx that returns value in allocated buffer.
* The returned buffer should be freed using Free()
*
* RETURNS: Pointer to key value or NULL on failure. The reason for the
* error can be obtains using GetLastError()
*
* HISTORY:
*
* 15-Jan-93 Davidc Created.
*
\***************************************************************************/
LPTSTR
AllocAndRegQueryValueEx(
HKEY hKey,
LPTSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType
)
{
LPTSTR String;
DWORD BytesAllocated;
//
// Pick a random buffer length, if it's not big enough reallocate
// it and try again until it is.
//
BytesAllocated = TYPICAL_STRING_LENGTH * sizeof(TCHAR);
String = Alloc(BytesAllocated);
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndRegQueryValueEx : Failed to allocate %d bytes for string", BytesAllocated));
return(NULL);
}
while (TRUE) {
DWORD Error;
DWORD BytesReturned = BytesAllocated;
Error = RegQueryValueEx(hKey,
lpValueName,
lpReserved,
lpType,
(LPBYTE)String,
&BytesReturned);
if (Error == ERROR_SUCCESS) {
break;
}
if (Error != ERROR_MORE_DATA) {
DebugLog((DEB_ERROR, "AllocAndRegQueryValueEx : RegQueryValueEx failed, error = %d", Error));
Free(String);
String = NULL;
SetLastError(Error);
break;
}
//
// The buffer was too small, make it bigger and try again
//
VerbosePrint(("AllocAndRegQueryValueEx: Failed with buffer length = %d bytes, reallocating and retrying", BytesAllocated));
BytesAllocated *= 2;
String = ReAlloc(String, BytesAllocated);
if (String == NULL) {
DebugLog((DEB_ERROR, "AllocAndRegQueryValueEx : Failed to reallocate %d bytes for string", BytesAllocated));
break;
}
}
return(String);
}
/***************************************************************************\
* HandleComboBoxOK
*
* Deals with UI requirements when OK is selected in a dialog when the
* focus is on or in a combo-box.
*
* This routine should be called from a dialog proc that contains a
* combo-box when a WM_COMMAND, IDOK is received.
*
* Returns TRUE if the message was dealt with and the caller should ignore it,
* FALSE if this routine did nothing with it and the caller should process it
* normally.
*
* History:
* 24-Sep-92 Davidc Created.
\***************************************************************************/
BOOL
HandleComboBoxOK(
HWND hDlg,
int ComboBoxId
)
{
HWND hwndFocus = GetFocus();
HWND hwndCB = GetDlgItem(hDlg, ComboBoxId);
//
// Hitting enter on a combo-box with the list showing should simply
// hide the list.
// We check for focus window being a child of the combo-box to
// handle non-list style combo-boxes which have the focus on
// the child edit control.
//
if ((hwndFocus == hwndCB) || IsChild(hwndCB, hwndFocus)) {
if (SendMessage(hwndCB, CB_GETDROPPEDSTATE, 0, 0)) {
//
// Make the list-box disappear and we're done.
//
SendMessage(hwndCB, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0);
return(TRUE);
}
}
//
// We didn't do anything
//
return(FALSE);
}
/***************************************************************************\
* FUNCTION: SetEnvironmentULong
*
* PURPOSE: Sets the value of an environment variable to the string
* representation of the passed data.
*
* RETURNS: TRUE on success, FALSE on failure
*
* HISTORY:
*
* 01-12-93 Davidc Created.
*
\***************************************************************************/
BOOL
SetEnvironmentULong(
LPTSTR Variable,
ULONG Value
)
{
TCHAR Buffer[10];
int Result;
Result = _snwprintf(Buffer, sizeof(Buffer), TEXT("%x"), Value);
ASSERT(Result < sizeof(Buffer));
return (SetEnvironmentVariable(Variable, Buffer));
}
/***************************************************************************\
* FUNCTION: SetEnvironmentLargeInt
*
* PURPOSE: Sets the value of an environment variable to the string
* representation of the passed data.
*
* RETURNS: TRUE on success, FALSE on failure
*
* HISTORY:
*
* 01-12-93 Davidc Created.
*
\***************************************************************************/
BOOL
SetEnvironmentLargeInt(
LPTSTR Variable,
LARGE_INTEGER Value
)
{
TCHAR Buffer[20];
int Result;
Result = _snwprintf(Buffer, sizeof(Buffer), TEXT("%x:%x"), Value.HighPart, Value.LowPart);
ASSERT(Result < sizeof(Buffer));
return (SetEnvironmentVariable(Variable, Buffer));
}
/***************************************************************************\
* FUNCTION: EncodeMultiSzW
*
* PURPOSE: Converts a multi-sz string and encodes it to look like
* a single string.
*
* We replace the terminators between strings
* with the TERMINATOR_REPLACEMENT character. We replace
* existing occurrences of the replacement character with
* two of them.
*
* RETURNS: Pointer to encoded string or NULL on failure.
* The returned buffer should be freed using Free()
*
* HISTORY:
*
* 01-12-93 Davidc Created.
*
\***************************************************************************/
#define TERMINATOR_REPLACEMENT TEXT(',')
LPWSTR
EncodeMultiSzW(
IN LPWSTR MultiSz
)
{
DWORD Length;
DWORD NewLength;
LPWSTR NewBuffer;
LPWSTR p, q;
DWORD ExtraCharacters;
//
// First calculate the length of the new string (with replacements)
//
p = MultiSz;
ExtraCharacters = 0;
while (*p) {
while (*p) {
if (*p == TERMINATOR_REPLACEMENT) {
ExtraCharacters ++;
}
p ++;
}
p ++;
}
Length = p - MultiSz; // p points at 'second' (final) null terminator
NewLength = Length + ExtraCharacters;
//
// Allocate space for the new string
//
NewBuffer = Alloc((NewLength + 1) * sizeof(WCHAR));
if (NewBuffer == NULL) {
DebugLog((DEB_ERROR, "EncodeMultiSz: failed to allocate space for %d bytes", (NewLength + 1) * sizeof(WCHAR)));
return(NULL);
}
//
// Copy the string into the new buffer making replacements as we go
//
p = MultiSz;
q = NewBuffer;
while (*p) {
while (*p) {
*q = *p;
if (*p == TERMINATOR_REPLACEMENT) {
q ++;
*q = TERMINATOR_REPLACEMENT;
}
p ++;
q ++;
}
*q = TERMINATOR_REPLACEMENT;
p ++;
q ++;
}
ASSERT((DWORD)(q - NewBuffer) == NewLength);
//
// Add terminator
//
*q = 0;
return(NewBuffer);
}
/***************************************************************************\
* TimeoutMessageBox
*
* Same as a normal message box, but times out if there is no user input
* for the specified number of seconds
* For convenience, this api takes string resource ids rather than string
* pointers as input. The resources are loaded from the .exe module
*
* 12-05-91 Davidc Created.
\***************************************************************************/
DLG_RETURN_TYPE TimeoutMessageBox(
HWND hwnd,
UINT IdText,
UINT IdCaption,
UINT wType,
TIMEOUT Timeout)
{
TCHAR CaptionBuffer[MAX_STRING_BYTES];
PTCHAR Caption = CaptionBuffer;
TCHAR Text[MAX_STRING_BYTES];
LoadString(hDllInstance, IdText, Text, MAX_STRING_LENGTH);
if (IdCaption != 0) {
LoadString(hDllInstance, IdCaption, Caption, MAX_STRING_LENGTH);
} else {
Caption = NULL;
}
return TimeoutMessageBoxlpstr(hwnd, Text, Caption, wType, Timeout);
}
/***************************************************************************\
* TimeoutMessageBoxlpstr
*
* Same as a normal message box, but times out if there is no user input
* for the specified number of seconds
*
* 12-05-91 Davidc Created.
\***************************************************************************/
DLG_RETURN_TYPE TimeoutMessageBoxlpstr(
HWND hwnd,
LPTSTR Text,
LPTSTR Caption,
UINT wType,
TIMEOUT Timeout)
{
int Result;
DLG_RETURN_TYPE DlgResult;
// Set up input timeout
pWlxFuncs->WlxSetTimeout(hGlobalWlx, Timeout);
DlgResult = pWlxFuncs->WlxMessageBox( hGlobalWlx,
hwnd,
Text,
Caption,
wType);
return(DlgResult);
}
PWSTR
DupString(PWSTR pszString)
{
DWORD cbString;
PWSTR pszNewString;
cbString = (wcslen(pszString) + 1) * sizeof(WCHAR);
pszNewString = LocalAlloc(LMEM_FIXED, cbString);
if (pszNewString)
{
CopyMemory(pszNewString, pszString, cbString);
}
return(pszNewString);
}
PWSTR
DupUnicodeString(PUNICODE_STRING pString)
{
PWSTR pszNewString;
if (pString->Length)
{
pszNewString = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, pString->Length + sizeof(WCHAR));
if (pszNewString)
{
CopyMemory(pszNewString, pString->Buffer, pString->Length);
}
}
else
pszNewString = NULL;
return(pszNewString);
}