946 lines
26 KiB
C
946 lines
26 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
opk.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Common modules shared by OPK tools. Note: Source Depot requires that we
|
||
|
publish the .h (E:\NT\admin\published\ntsetup) and .lib
|
||
|
(E:\NT\public\internal\admin\lib).
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Brian Ku (briank) 06/20/2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
7/00 - Jason Cohen (jcohen)
|
||
|
Added in the rest of the common APIs form Millennium (need for lfnbk).
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
//
|
||
|
// Include file(s)
|
||
|
//
|
||
|
|
||
|
#include <pch.h>
|
||
|
#include <tchar.h>
|
||
|
#include <shlwapi.h>
|
||
|
|
||
|
|
||
|
//
|
||
|
// External Function(s):
|
||
|
//
|
||
|
|
||
|
LPTSTR AllocateString(HINSTANCE hInstance, UINT uID)
|
||
|
{
|
||
|
// ISSUE-2002/02/26-acosma - This sets a restriction of 256 characters on the buffer.
|
||
|
//
|
||
|
TCHAR szBuffer[256];
|
||
|
LPTSTR lpBuffer = NULL;
|
||
|
|
||
|
// Load the string from the resource and then allocate
|
||
|
// a buffer just big enough for it. Strings can exceed 256 characters.
|
||
|
//
|
||
|
if ( ( LoadString(hInstance, uID, szBuffer, sizeof(szBuffer) / sizeof(TCHAR)) ) &&
|
||
|
( lpBuffer = (LPTSTR) MALLOC(sizeof(TCHAR) * (lstrlen(szBuffer) + 1)) ) )
|
||
|
{
|
||
|
lstrcpy(lpBuffer, szBuffer);
|
||
|
}
|
||
|
|
||
|
// Return the allocated buffer, or NULL if there was an error.
|
||
|
//
|
||
|
return lpBuffer;
|
||
|
}
|
||
|
|
||
|
LPTSTR AllocateExpand(LPTSTR lpszBuffer)
|
||
|
{
|
||
|
LPTSTR lpszExpanded = NULL;
|
||
|
DWORD cbExpanded;
|
||
|
|
||
|
// First we need to get the size of the expanded buffer and
|
||
|
// allocate it.
|
||
|
//
|
||
|
if ( ( cbExpanded = ExpandEnvironmentStrings(lpszBuffer, NULL, 0) ) &&
|
||
|
( lpszExpanded = (LPTSTR) MALLOC(cbExpanded * sizeof(TCHAR)) ) )
|
||
|
{
|
||
|
// Now expand out the buffer.
|
||
|
//
|
||
|
if ( ( 0 == ExpandEnvironmentStrings(lpszBuffer, lpszExpanded, cbExpanded) ) ||
|
||
|
( NULLCHR == *lpszExpanded ) )
|
||
|
{
|
||
|
FREE(lpszExpanded);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the allocated buffer, or NULL if there was an error
|
||
|
// or nothing in the string.
|
||
|
//
|
||
|
return lpszExpanded;
|
||
|
}
|
||
|
|
||
|
LPTSTR AllocateStrRes(HINSTANCE hInstance, LPSTRRES lpsrTable, DWORD cbTable, LPTSTR lpString, LPTSTR * lplpReturn)
|
||
|
{
|
||
|
LPSTRRES lpsrSearch = lpsrTable;
|
||
|
LPTSTR lpReturn = NULL;
|
||
|
BOOL bFound;
|
||
|
|
||
|
// Init this return value.
|
||
|
//
|
||
|
if ( lplpReturn )
|
||
|
*lplpReturn = NULL;
|
||
|
|
||
|
// Try to find the friendly name for this string in our table.
|
||
|
//
|
||
|
while ( ( bFound = ((DWORD) (lpsrSearch - lpsrTable) < cbTable) ) &&
|
||
|
( lstrcmpi(lpString, lpsrSearch->lpStr) != 0 ) )
|
||
|
{
|
||
|
lpsrSearch++;
|
||
|
}
|
||
|
|
||
|
// If it was found, allocate the friendly name from the resource.
|
||
|
//
|
||
|
if ( bFound )
|
||
|
{
|
||
|
lpReturn = AllocateString(hInstance, lpsrSearch->uId);
|
||
|
if ( lplpReturn )
|
||
|
*lplpReturn = lpsrSearch->lpStr;
|
||
|
}
|
||
|
|
||
|
return lpReturn;
|
||
|
}
|
||
|
|
||
|
int MsgBoxLst(HWND hwndParent, LPTSTR lpFormat, LPTSTR lpCaption, UINT uType, va_list lpArgs)
|
||
|
{
|
||
|
INT nReturn;
|
||
|
DWORD dwCount = 0;
|
||
|
LPTSTR lpText = NULL;
|
||
|
|
||
|
// The format string is required.
|
||
|
//
|
||
|
if ( lpFormat )
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
// Allocate 1k of characters at a time.
|
||
|
//
|
||
|
dwCount += 1024;
|
||
|
|
||
|
// Free the previous buffer, if there was one.
|
||
|
//
|
||
|
FREE(lpText);
|
||
|
|
||
|
// Allocate a new buffer.
|
||
|
//
|
||
|
if ( lpText = MALLOC(dwCount * sizeof(TCHAR)) )
|
||
|
nReturn = _vsntprintf(lpText, dwCount, lpFormat, lpArgs);
|
||
|
else
|
||
|
nReturn = 0;
|
||
|
}
|
||
|
while ( nReturn < 0 );
|
||
|
|
||
|
// Make sure we have the format string.
|
||
|
//
|
||
|
if ( lpText )
|
||
|
{
|
||
|
// Display the message box.
|
||
|
//
|
||
|
nReturn = MessageBox(hwndParent, lpText, lpCaption, uType);
|
||
|
FREE(lpText);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
nReturn = 0;
|
||
|
|
||
|
// Return the return value of the MessageBox() call. If there was a memory
|
||
|
// error, 0 will be returned.
|
||
|
//
|
||
|
return nReturn;
|
||
|
}
|
||
|
|
||
|
int MsgBoxStr(HWND hwndParent, LPTSTR lpFormat, LPTSTR lpCaption, UINT uType, ...)
|
||
|
{
|
||
|
va_list lpArgs;
|
||
|
|
||
|
// Initialize the lpArgs parameter with va_start().
|
||
|
//
|
||
|
va_start(lpArgs, uType);
|
||
|
|
||
|
// Return the return value of the MessageBox() call. If there was a memory
|
||
|
// error, 0 will be returned. This is all
|
||
|
//
|
||
|
return MsgBoxLst(hwndParent, lpFormat, lpCaption, uType, lpArgs);
|
||
|
}
|
||
|
|
||
|
int MsgBox(HWND hwndParent, UINT uFormat, UINT uCaption, UINT uType, ...)
|
||
|
{
|
||
|
va_list lpArgs;
|
||
|
INT nReturn;
|
||
|
LPTSTR lpFormat = NULL,
|
||
|
lpCaption = NULL;
|
||
|
|
||
|
// Initialize the lpArgs parameter with va_start().
|
||
|
//
|
||
|
va_start(lpArgs, uType);
|
||
|
|
||
|
// Get the format and caption strings from the resource.
|
||
|
//
|
||
|
if ( uFormat )
|
||
|
lpFormat = AllocateString(NULL, uFormat);
|
||
|
if ( uCaption )
|
||
|
lpCaption = AllocateString(NULL, uCaption);
|
||
|
|
||
|
// Return the return value of the MessageBox() call. If there was a memory
|
||
|
// error, 0 will be returned.
|
||
|
//
|
||
|
nReturn = MsgBoxLst(hwndParent, lpFormat, lpCaption, uType, lpArgs);
|
||
|
|
||
|
// Free the format and caption strings.
|
||
|
//
|
||
|
FREE(lpFormat);
|
||
|
FREE(lpCaption);
|
||
|
|
||
|
// Return the value saved from the previous function call.
|
||
|
//
|
||
|
return nReturn;
|
||
|
}
|
||
|
|
||
|
void CenterDialog(HWND hwnd)
|
||
|
{
|
||
|
CenterDialogEx(NULL, hwnd);
|
||
|
}
|
||
|
|
||
|
|
||
|
void CenterDialogEx(HWND hParent, HWND hChild)
|
||
|
{
|
||
|
RECT rcChild,
|
||
|
rcParent;
|
||
|
|
||
|
if ( GetWindowRect(hChild, &rcChild) )
|
||
|
{
|
||
|
// If parent is specified center with respect to parent.
|
||
|
if ( hParent && (GetWindowRect(hParent, &rcParent)) )
|
||
|
SetWindowPos(hChild, NULL, ((rcParent.right + rcParent.left - (rcChild.right - rcChild.left)) / 2), ((rcParent.bottom + rcParent.top - (rcChild.bottom - rcChild.top)) / 2), 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
|
||
|
|
||
|
// Otherwise center with respect to screen.
|
||
|
//
|
||
|
else
|
||
|
SetWindowPos(hChild, NULL, ((GetSystemMetrics(SM_CXSCREEN) - (rcChild.right - rcChild.left)) / 2), ((GetSystemMetrics(SM_CYSCREEN) - (rcChild.bottom - rcChild.top)) / 2), 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
INT_PTR CALLBACK SimpleDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
switch (uMsg)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
//CenterDialog(hwnd);
|
||
|
return FALSE;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
EndDialog(hwnd, LOWORD(wParam));
|
||
|
return FALSE;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
INT_PTR SimpleDialogBox(HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent)
|
||
|
{
|
||
|
return DialogBox(hInstance, lpTemplate, hWndParent, SimpleDialogProc);
|
||
|
}
|
||
|
|
||
|
/****************************************************************************\
|
||
|
|
||
|
HFONT // Returns a valid handle to a font if it is
|
||
|
// successfully created, or NULL if something
|
||
|
// failed. The font handle should be deleteted
|
||
|
// with DeleteObject() when it is no longer
|
||
|
// needed.
|
||
|
|
||
|
GetFont( // This function creates a font based in the info
|
||
|
// passed in.
|
||
|
|
||
|
HWND hwndCtrl, // Handle to a control that is used for the
|
||
|
// default font characteristics. This may be
|
||
|
// NULL if not default is control is available.
|
||
|
|
||
|
LPTSTR lpFontName, // Points to a string that contains the name of
|
||
|
// the font to create. This parameter may be NULL
|
||
|
// if a valid control handle is passed in. In
|
||
|
// that case, the font of the control is used.
|
||
|
|
||
|
DWORD dwFontSize, // Point size to use for the font. If it is zero,
|
||
|
// the default is used.
|
||
|
|
||
|
BOOL bSymbol // If this is TRUE, the font is set to
|
||
|
// SYMBOL_CHARSET. Typically this is FALSE.
|
||
|
|
||
|
);
|
||
|
|
||
|
\****************************************************************************/
|
||
|
|
||
|
HFONT GetFont(HWND hwndCtrl, LPTSTR lpFontName, DWORD dwFontSize, LONG lFontWeight, BOOL bSymbol)
|
||
|
{
|
||
|
HFONT hFont;
|
||
|
LOGFONT lFont;
|
||
|
BOOL bGetFont;
|
||
|
|
||
|
// If the font name is passed in, then try to use that
|
||
|
// first before getting the font of the control.
|
||
|
//
|
||
|
if ( lpFontName && *lpFontName )
|
||
|
{
|
||
|
// Make sure the font name is not longer than
|
||
|
// 32 characters (including the NULL terminator).
|
||
|
//
|
||
|
if ( lstrlen(lpFontName) >= sizeof(lFont.lfFaceName) )
|
||
|
return NULL;
|
||
|
|
||
|
// Setup the structure to use to get the
|
||
|
// font we want.
|
||
|
//
|
||
|
ZeroMemory(&lFont, sizeof(LOGFONT));
|
||
|
lFont.lfCharSet = DEFAULT_CHARSET;
|
||
|
lstrcpy(lFont.lfFaceName, lpFontName);
|
||
|
}
|
||
|
|
||
|
// First try to get the font that we wanted.
|
||
|
//
|
||
|
if ( ( lpFontName == NULL ) ||
|
||
|
( *lpFontName == NULLCHR ) ||
|
||
|
( (hFont = CreateFontIndirect((LPLOGFONT) &lFont)) == NULL ) )
|
||
|
{
|
||
|
// Couldn't get the font we wanted, try the font of the control
|
||
|
// if a valid window handle was passed in.
|
||
|
//
|
||
|
if ( ( hwndCtrl == NULL ) ||
|
||
|
( (hFont = (HFONT) (WORD) SendMessage(hwndCtrl, WM_GETFONT, 0, 0L)) == NULL ) )
|
||
|
{
|
||
|
// All atempts to get the font failed. We must return NULL.
|
||
|
//
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the font we have now if we don't need to
|
||
|
// change the size or weight.
|
||
|
//
|
||
|
if ( (lFontWeight == 0) && (dwFontSize == 0) )
|
||
|
return hFont;
|
||
|
|
||
|
// We must have a valid HFONT now. Fill in the structure
|
||
|
// and setup the size and weight we wanted for it.
|
||
|
//
|
||
|
bGetFont = GetObject(hFont, sizeof(LOGFONT), (LPVOID) &lFont);
|
||
|
DeleteObject(hFont);
|
||
|
|
||
|
if ( bGetFont )
|
||
|
{
|
||
|
// Set the bold and point size of the font.
|
||
|
//
|
||
|
if ( lFontWeight )
|
||
|
lFont.lfWeight = lFontWeight;
|
||
|
if ( dwFontSize )
|
||
|
lFont.lfHeight = -MulDiv(dwFontSize, GetDeviceCaps(GetDC(NULL), LOGPIXELSY), 72);
|
||
|
if ( bSymbol )
|
||
|
lFont.lfCharSet = SYMBOL_CHARSET;
|
||
|
|
||
|
// Create the font.
|
||
|
//
|
||
|
hFont = CreateFontIndirect((LPLOGFONT) &lFont);
|
||
|
}
|
||
|
else
|
||
|
hFont = NULL;
|
||
|
|
||
|
return hFont;
|
||
|
}
|
||
|
|
||
|
void ShowEnableWindow(HWND hwnd, BOOL bShowEnable)
|
||
|
{
|
||
|
EnableWindow(hwnd, bShowEnable);
|
||
|
ShowWindow(hwnd, bShowEnable ? SW_SHOW : SW_HIDE);
|
||
|
}
|
||
|
|
||
|
/****************************************************************************\
|
||
|
|
||
|
BOOL // Returns TRUE if we are running a server OS.
|
||
|
|
||
|
IsServer( // This routine checks if we're running on a
|
||
|
// Server OS.
|
||
|
|
||
|
VOID
|
||
|
|
||
|
);
|
||
|
|
||
|
\****************************************************************************/
|
||
|
|
||
|
BOOL IsServer(VOID)
|
||
|
{
|
||
|
OSVERSIONINFOEX verInfo;
|
||
|
BOOL fReturn = FALSE;
|
||
|
|
||
|
verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||
|
if ( ( GetVersionEx((LPOSVERSIONINFO) &verInfo) ) &&
|
||
|
( verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) &&
|
||
|
( ( verInfo.wProductType == VER_NT_SERVER ) ||
|
||
|
( verInfo.wProductType == VER_NT_DOMAIN_CONTROLLER ) ) )
|
||
|
{
|
||
|
fReturn = TRUE;
|
||
|
}
|
||
|
|
||
|
return fReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL IsIA64()
|
||
|
/*++
|
||
|
===============================================================================
|
||
|
Routine Description:
|
||
|
|
||
|
This routine checks if we're running on a 64-bit machine.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None -
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - We are running on 64-bit machine.
|
||
|
FALSE - Not a 64-bit machine.
|
||
|
|
||
|
===============================================================================
|
||
|
--*/
|
||
|
{
|
||
|
BOOL fReturn = FALSE;
|
||
|
ULONG_PTR Wow64Info = 0;
|
||
|
DWORD dwSt = 0;
|
||
|
SYSTEM_INFO siSystemInfo;
|
||
|
|
||
|
ZeroMemory( &siSystemInfo, sizeof(SYSTEM_INFO) );
|
||
|
GetSystemInfo(&siSystemInfo);
|
||
|
|
||
|
if ( (siSystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ||
|
||
|
(siSystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) )
|
||
|
fReturn = TRUE;
|
||
|
|
||
|
|
||
|
if (!fReturn)
|
||
|
{
|
||
|
// Now make sure that GetSystemInfo isn't lying because we are in emulation mode.
|
||
|
|
||
|
dwSt = NtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, &Wow64Info, sizeof(Wow64Info), NULL);
|
||
|
if (!NT_SUCCESS(dwSt))
|
||
|
{
|
||
|
// Handle to process is bad, or the code is compiled 32-bit and running on NT4 or earlier.
|
||
|
// Do nothing
|
||
|
|
||
|
}
|
||
|
else if (Wow64Info)
|
||
|
{
|
||
|
// The process is 32-bit and is running inside WOW64.
|
||
|
// We are really on IA64 and running in 32-bit mode.
|
||
|
fReturn = TRUE;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
return fReturn;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL ValidDosName(LPCTSTR lpName)
|
||
|
{
|
||
|
LPCTSTR lpSearch = lpName;
|
||
|
int nDot = 0,
|
||
|
nSpot = 0,
|
||
|
nLen;
|
||
|
|
||
|
// Do the easy checks.
|
||
|
//
|
||
|
if ( ( lpSearch == NULL ) ||
|
||
|
( *lpSearch == NULLCHR ) ||
|
||
|
( (nLen = lstrlen(lpSearch)) > 12 ) )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Search the string.
|
||
|
//
|
||
|
for (; *lpSearch; lpSearch++)
|
||
|
{
|
||
|
// Check for dots.
|
||
|
//
|
||
|
if ( *lpSearch == _T('.') )
|
||
|
{
|
||
|
// Keep track of the number of dots.
|
||
|
//
|
||
|
nDot++;
|
||
|
nSpot = (int) (lpSearch - lpName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Check for valid characters.
|
||
|
//
|
||
|
if ( !( ( ( _T('0') <= *lpSearch ) && ( *lpSearch <= _T('9') ) ) ||
|
||
|
( ( _T('a') <= *lpSearch ) && ( *lpSearch <= _T('z') ) ) ||
|
||
|
( ( _T('A') <= *lpSearch ) && ( *lpSearch <= _T('Z') ) ) ||
|
||
|
( *lpSearch == _T('-') ) ||
|
||
|
( *lpSearch == _T('_') ) ||
|
||
|
( *lpSearch == _T('~') ) ) )
|
||
|
{
|
||
|
// Invalid character.
|
||
|
//
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Make sure the dot is in the right place.
|
||
|
//
|
||
|
if ( ( nDot > 1 ) ||
|
||
|
( ( nDot == 0 ) && ( nLen > 8 ) ) ||
|
||
|
( ( nDot == 1 ) && ( nSpot > 8 ) ) ||
|
||
|
( ( nDot == 1 ) && ( (nLen - nSpot) > 4 ) ) )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
DWORD GetLineArgs(LPTSTR lpSrc, LPTSTR ** lplplpArgs, LPTSTR * lplpAllArgs)
|
||
|
{
|
||
|
LPTSTR lpCmdLine,
|
||
|
lpArg,
|
||
|
lpDst;
|
||
|
DWORD dwArgs = 0;
|
||
|
BOOL bQuote;
|
||
|
|
||
|
// Fist make sure that we were passed in a valid pointer, we have a command
|
||
|
// line to parse, and that we were able to allocate the memory to hold it.
|
||
|
//
|
||
|
if ( ( lplplpArgs != NULL ) &&
|
||
|
( lpSrc ) &&
|
||
|
( *lpSrc ) &&
|
||
|
( lpCmdLine = (LPTSTR) MALLOC((lstrlen(lpSrc) + 1) * sizeof(TCHAR)) ) )
|
||
|
{
|
||
|
// Fist parse the command line into NULL terminated sub strings.
|
||
|
//
|
||
|
lpDst = lpCmdLine;
|
||
|
while ( *lpSrc )
|
||
|
{
|
||
|
// Eat the preceeding spaces.
|
||
|
//
|
||
|
while ( *lpSrc == _T(' ') )
|
||
|
lpSrc = CharNext(lpSrc);
|
||
|
|
||
|
// Make sure we still have an argument.
|
||
|
//
|
||
|
if ( *lpSrc == _T('\0') )
|
||
|
break;
|
||
|
|
||
|
// Return a pointer to all the command line args if they want one.
|
||
|
//
|
||
|
if ( ( dwArgs == 1 ) && lplpAllArgs )
|
||
|
*lplpAllArgs = lpSrc;
|
||
|
|
||
|
// Save the current arg pointer.
|
||
|
//
|
||
|
lpArg = lpDst;
|
||
|
dwArgs++;
|
||
|
|
||
|
// See if we are looking for the next quote or space.
|
||
|
//
|
||
|
if ( bQuote = (*lpSrc == _T('"')) )
|
||
|
lpSrc = CharNext(lpSrc);
|
||
|
|
||
|
// Copy the argument into our allocated buffer until we
|
||
|
// hit the separating character (which will always be a space).
|
||
|
//
|
||
|
while ( *lpSrc && ( bQuote || ( *lpSrc != _T(' ') ) ) )
|
||
|
{
|
||
|
// We special case the quote.
|
||
|
//
|
||
|
if ( *lpSrc == _T('"') )
|
||
|
{
|
||
|
// If the character before the quote is a backslash, then
|
||
|
// we don't count this as the separating quote.
|
||
|
//
|
||
|
LPTSTR lpPrev = CharPrev(lpCmdLine, lpDst);
|
||
|
if ( lpPrev && ( *lpPrev == _T('\\') ) )
|
||
|
*lpPrev = *lpSrc++;
|
||
|
else
|
||
|
{
|
||
|
// Since we have found the separating quote, set this to
|
||
|
// false so we look for the next space.
|
||
|
//
|
||
|
bQuote = FALSE;
|
||
|
lpSrc++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
*lpDst++ = *lpSrc++;
|
||
|
}
|
||
|
|
||
|
// NULL terminate this argument.
|
||
|
//
|
||
|
*lpDst++ = _T('\0');
|
||
|
}
|
||
|
|
||
|
// Now setup the pointers to each argument. Make sure we have some arguments
|
||
|
// to return and that we have the memory allocated for the array.
|
||
|
//
|
||
|
if ( *lpCmdLine && dwArgs && ( *lplplpArgs = (LPTSTR *) MALLOC(dwArgs * sizeof(LPTSTR)) ) )
|
||
|
{
|
||
|
DWORD dwCount = 0;
|
||
|
|
||
|
// Copy a pointer to each NULL terminated sub string into our
|
||
|
// array of arguments we are going to return.
|
||
|
//
|
||
|
do
|
||
|
{
|
||
|
*(*lplplpArgs + dwCount) = lpCmdLine;
|
||
|
lpCmdLine += lstrlen(lpCmdLine) + 1;
|
||
|
}
|
||
|
while ( ++dwCount < dwArgs );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Either there were no command line arguments, or the memory allocation
|
||
|
// failed for the list of arguments to return.
|
||
|
//
|
||
|
dwArgs = 0;
|
||
|
FREE(lpCmdLine);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return dwArgs;
|
||
|
}
|
||
|
|
||
|
DWORD GetCommandLineArgs(LPTSTR ** lplplpArgs)
|
||
|
{
|
||
|
return GetLineArgs(GetCommandLine(), lplplpArgs, NULL);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Generic singularly linked list pvItem must be allocated with MALLOC
|
||
|
//
|
||
|
BOOL FAddListItem(PGENERIC_LIST* ppList, PGENERIC_LIST** pppNewItem, PVOID pvItem)
|
||
|
{
|
||
|
if (pppNewItem && *pppNewItem == NULL)
|
||
|
*pppNewItem = ppList;
|
||
|
|
||
|
if (*pppNewItem) {
|
||
|
if (**pppNewItem = (PGENERIC_LIST)MALLOC(sizeof(GENERIC_LIST))) {
|
||
|
(**pppNewItem)->pNext = NULL;
|
||
|
(**pppNewItem)->pvItem = pvItem;
|
||
|
*pppNewItem = &((**pppNewItem)->pNext);
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void FreeList(PGENERIC_LIST pList)
|
||
|
{
|
||
|
while (pList) {
|
||
|
PGENERIC_LIST pTemp = pList;
|
||
|
pList = pList->pNext;
|
||
|
|
||
|
FREE(pTemp->pvItem);
|
||
|
FREE(pTemp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Find factory.exe from the current process, should be in same directory
|
||
|
//
|
||
|
BOOL FGetFactoryPath(LPTSTR pszFactoryPath)
|
||
|
{
|
||
|
// Attempt to locate FACTORY.EXE
|
||
|
//
|
||
|
// NTRAID#NTBUG9-549770-2002/02/26-acosma,georgeje - Possible buffer overflow.
|
||
|
//
|
||
|
if (pszFactoryPath && GetModuleFileName(NULL, pszFactoryPath, MAX_PATH)) {
|
||
|
if (PathRemoveFileSpec(pszFactoryPath)) {
|
||
|
PathAppend(pszFactoryPath, TEXT("FACTORY.EXE"));
|
||
|
if (FileExists(pszFactoryPath))
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Find sysprep.exe from the current process, should be in same directory
|
||
|
//
|
||
|
BOOL FGetSysprepPath(LPTSTR pszSysprepPath)
|
||
|
{
|
||
|
// Attempt to locate SYSPREP.EXE
|
||
|
//
|
||
|
// NTRAID#NTBUG9-549770-2002/02/26-acosma,georgeje - Possible buffer overflow.
|
||
|
//
|
||
|
if (pszSysprepPath && GetModuleFileName(NULL, pszSysprepPath, MAX_PATH)) {
|
||
|
if (PathRemoveFileSpec(pszSysprepPath)) {
|
||
|
PathAppend(pszSysprepPath, TEXT("SYSPREP.EXE"));
|
||
|
if (FileExists(pszSysprepPath))
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ConnectNetworkResource
|
||
|
//
|
||
|
// Purpose: This function allows the user to connect to a network resource with
|
||
|
// supplied credentials.
|
||
|
//
|
||
|
// Arguments: lpszPath: Network Resource that should be shared out
|
||
|
// lpszUsername: Username for credentials, can be in form of domain\username
|
||
|
// lpszPassword: Password to use for credentials
|
||
|
// bState: If set to TRUE we will add the connection, if FALSE we will
|
||
|
// attempt to delete the connection
|
||
|
//
|
||
|
// Returns: BOOL If the NetUse command was successful, TRUE is returned
|
||
|
//
|
||
|
//------------------------------------------------------------------------------------------------------
|
||
|
NET_API_STATUS ConnectNetworkResource(LPTSTR lpszPath, LPTSTR lpszUsername, LPTSTR lpszPassword, BOOL bState)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
USE_INFO_2 ui2;
|
||
|
NET_API_STATUS nerr_NetUse;
|
||
|
TCHAR szDomain[MAX_PATH] = NULLSTR,
|
||
|
szNetUse[MAX_PATH] = NULLSTR;
|
||
|
LPTSTR lpUser,
|
||
|
lpSearch;
|
||
|
|
||
|
// Zero out the user information structure
|
||
|
//
|
||
|
ZeroMemory(&ui2, sizeof(ui2));
|
||
|
|
||
|
// Copy the path into our buffer so we can work with it
|
||
|
//
|
||
|
lstrcpyn(szNetUse, lpszPath, AS(szNetUse));
|
||
|
StrRTrm(szNetUse, CHR_BACKSLASH);
|
||
|
|
||
|
if ( szNetUse[0] && PathIsUNC(szNetUse) )
|
||
|
{
|
||
|
// Disconnect from existing share
|
||
|
//
|
||
|
nerr_NetUse = NetUseDel(NULL, szNetUse, USE_NOFORCE);
|
||
|
|
||
|
// We need to Add a connection
|
||
|
//
|
||
|
if ( bState )
|
||
|
{
|
||
|
ui2.ui2_remote = szNetUse;
|
||
|
ui2.ui2_asg_type = USE_DISKDEV;
|
||
|
ui2.ui2_password = lpszPassword;
|
||
|
|
||
|
lstrcpyn(szDomain, lpszUsername, AS(szDomain));
|
||
|
|
||
|
// Break up the Domain\Username for the NetUse function
|
||
|
//
|
||
|
if (lpUser = StrChr(szDomain, CHR_BACKSLASH) )
|
||
|
{
|
||
|
// Put a NULL character after the domain part of the user name
|
||
|
// and advance the pointer to point to the actual user name.
|
||
|
//
|
||
|
*(lpUser++) = NULLCHR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Use the computer name in the path as the domain name.
|
||
|
//
|
||
|
if ( lpSearch = StrChr(szNetUse + 2, CHR_BACKSLASH) )
|
||
|
lstrcpyn(szDomain, szNetUse + 2, (int)((lpSearch - (szNetUse + 2)) + 1));
|
||
|
else
|
||
|
lstrcpyn(szDomain, szNetUse + 2, AS(szDomain));
|
||
|
|
||
|
lpUser = lpszUsername;
|
||
|
}
|
||
|
|
||
|
// Set the domain and user name pointers into our struct.
|
||
|
//
|
||
|
ui2.ui2_domainname = szDomain;
|
||
|
ui2.ui2_username = lpUser;
|
||
|
|
||
|
// Create a connect to the share
|
||
|
//
|
||
|
nerr_NetUse = NetUseAdd(NULL, 2, (LPBYTE) &ui2, NULL);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
nerr_NetUse = NERR_UseNotFound;
|
||
|
|
||
|
// Return failure/success
|
||
|
//
|
||
|
return nerr_NetUse;
|
||
|
}
|
||
|
|
||
|
BOOL GetUncShare(LPCTSTR lpszPath, LPTSTR lpszShare, DWORD cbShare)
|
||
|
{
|
||
|
BOOL bRet;
|
||
|
LPCTSTR lpSrc = lpszPath;
|
||
|
LPTSTR lpDst = lpszShare;
|
||
|
DWORD dwBackslashes,
|
||
|
dwCount;
|
||
|
|
||
|
// Make sure the path is a UNC by calling the shell function.
|
||
|
//
|
||
|
bRet = PathIsUNC(lpszPath);
|
||
|
|
||
|
// This will loop through the path string twice, each time coping all the
|
||
|
// backslashes and then all the non-backslashes. So if the string passed
|
||
|
// in was "\\COMPUTER\SHARE\DIR\FILE.NAME", the first pass will copy
|
||
|
// "\\COMPUTER" and the next pass would then copy "\SHARE" so the final
|
||
|
// string would then be "\\COMPUTER\SHARE". This loop also verifies there
|
||
|
// are the correct number of backslashes and non-backslashes. If there is
|
||
|
// no return buffer, then we just are verifing the share.
|
||
|
//
|
||
|
for ( dwBackslashes = 2; dwBackslashes && bRet; dwBackslashes-- )
|
||
|
{
|
||
|
// First copy the backslashes.
|
||
|
//
|
||
|
dwCount = 0;
|
||
|
while ( _T('\\') == *lpSrc )
|
||
|
{
|
||
|
if ( lpDst && cbShare )
|
||
|
{
|
||
|
*lpDst++ = *lpSrc;
|
||
|
cbShare--;
|
||
|
}
|
||
|
lpSrc++;
|
||
|
dwCount++;
|
||
|
}
|
||
|
|
||
|
// Make sure the number of backslashes is correct.
|
||
|
// The fist pass there should be two and the next
|
||
|
// pass should be just one.
|
||
|
//
|
||
|
if ( dwBackslashes != dwCount )
|
||
|
{
|
||
|
bRet = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Now copy the non-backslashes.
|
||
|
//
|
||
|
dwCount = 0;
|
||
|
while ( ( *lpSrc ) &&
|
||
|
( _T('\\') != *lpSrc ) )
|
||
|
{
|
||
|
if ( lpDst && cbShare )
|
||
|
{
|
||
|
*lpDst++ = *lpSrc;
|
||
|
cbShare--;
|
||
|
}
|
||
|
lpSrc++;
|
||
|
dwCount++;
|
||
|
}
|
||
|
|
||
|
// Make sure there was at least one non-backslash.
|
||
|
// character.
|
||
|
//
|
||
|
// Also if we are on the first pass and the path
|
||
|
// buffer is already empty, then we don't have the
|
||
|
// share part so just error out.
|
||
|
//
|
||
|
if ( ( 0 == dwCount ) ||
|
||
|
( ( 2 == dwBackslashes ) &&
|
||
|
( NULLCHR == *lpSrc ) ) )
|
||
|
{
|
||
|
bRet = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Only fix up the return buffer if there is one.
|
||
|
//
|
||
|
if ( lpszShare )
|
||
|
{
|
||
|
// Make sure that we didn't fail and that we still
|
||
|
// have room for the null terminator.
|
||
|
//
|
||
|
if ( bRet && cbShare )
|
||
|
{
|
||
|
// Don't forget to null terminate the return string.
|
||
|
//
|
||
|
*lpDst = NULLCHR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If we failed or ran out of buffer room, make sure
|
||
|
// we don't return anything.
|
||
|
//
|
||
|
*lpszShare = NULLCHR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
DWORD GetSkuType()
|
||
|
{
|
||
|
DWORD dwRet = 0;
|
||
|
OSVERSIONINFOEX osvi;
|
||
|
|
||
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
||
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||
|
|
||
|
if ( GetVersionEx((LPOSVERSIONINFO) &osvi) )
|
||
|
{
|
||
|
if ( VER_NT_WORKSTATION == osvi.wProductType )
|
||
|
{
|
||
|
if ( GET_FLAG(osvi.wSuiteMask, VER_SUITE_PERSONAL) )
|
||
|
{
|
||
|
dwRet = VER_SUITE_PERSONAL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwRet = VER_NT_WORKSTATION;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( GET_FLAG(osvi.wSuiteMask, VER_SUITE_DATACENTER) )
|
||
|
{
|
||
|
dwRet = VER_SUITE_DATACENTER;
|
||
|
}
|
||
|
else if ( GET_FLAG(osvi.wSuiteMask, VER_SUITE_ENTERPRISE) )
|
||
|
{
|
||
|
dwRet = VER_SUITE_ENTERPRISE;
|
||
|
}
|
||
|
else if ( GET_FLAG(osvi.wSuiteMask, VER_SUITE_BLADE) )
|
||
|
{
|
||
|
dwRet = VER_SUITE_BLADE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwRet = VER_NT_SERVER;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return dwRet;
|
||
|
}
|