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.
 
 
 
 
 
 

651 lines
13 KiB

/*++
Copyright (c) 1990-2003 Microsoft Corporation
All Rights Reserved
Module Name:
util.c
// @@BEGIN_DDKSPLIT
Abstract:
This module provides all the utility functions for localmon.
Revision History:
// @@END_DDKSPLIT
--*/
#include "precomp.h"
#pragma hdrstop
//
// These globals are needed so that AddPort can call
// SPOOLSS!EnumPorts to see whether the port to be added
// already exists.
// @@BEGIN_DDKSPLIT
// They will be initialized the first time AddPort is called.
//
// !! LATER !!
//
// This is common code. move PortExists into the router.
//
// @@END_DDKSPLIT
HMODULE hSpoolssDll = NULL;
FARPROC pfnSpoolssEnumPorts = NULL;
VOID
LcmRemoveColon(
LPWSTR pName)
{
DWORD Length;
Length = wcslen(pName);
if (pName[Length-1] == L':')
pName[Length-1] = 0;
}
BOOL
IsCOMPort(
LPWSTR pPort
)
{
//
// Must begin with szLcmCOM
//
if ( _wcsnicmp( pPort, szLcmCOM, 3 ) )
{
return FALSE;
}
//
// wcslen guarenteed >= 3
//
return pPort[ wcslen( pPort ) - 1 ] == L':';
}
BOOL
IsLPTPort(
LPWSTR pPort
)
{
//
// Must begin with szLcmLPT
//
if ( _wcsnicmp( pPort, szLcmLPT, 3 ) )
{
return FALSE;
}
//
// wcslen guarenteed >= 3
//
return pPort[ wcslen( pPort ) - 1 ] == L':';
}
#define NEXTVAL(pch) \
while( *pch && ( *pch != L',' ) ) \
pch++; \
if( *pch ) \
pch++
BOOL
GetIniCommValues(
LPWSTR pName,
LPDCB pdcb,
LPCOMMTIMEOUTS pcto
)
{
BOOL bRet = FALSE;
DWORD rc, dwCharCount = 10;
LPVOID pszEntry = NULL;
do {
FreeSplMem(pszEntry);
dwCharCount *= 2;
pszEntry = AllocSplMem(dwCharCount*sizeof(WCHAR));
if ( !pszEntry ||
!(rc = GetProfileString(szPorts, pName, szNULL,
pszEntry, dwCharCount)) )
goto Done;
} while ( rc >= dwCharCount - 2 );
bRet = BuildCommDCB((LPWSTR)pszEntry, pdcb);
pcto->WriteTotalTimeoutConstant = GetProfileInt(szWindows,
szINIKey_TransmissionRetryTimeout,
45 );
pcto->WriteTotalTimeoutConstant*=1000;
Done:
FreeSplMem(pszEntry);
return bRet;
}
/* PortExists
*
* Calls EnumPorts to check whether the port name already exists.
* This asks every monitor, rather than just this one.
* The function will return TRUE if the specified port is in the list.
* If an error occurs, the return is FALSE and the variable pointed
* to by pError contains the return from GetLastError().
* The caller must therefore always check that *pError == NO_ERROR.
*/
BOOL
PortExists(
LPWSTR pName,
LPWSTR pPortName,
PDWORD pError
)
{
DWORD cbNeeded;
DWORD cReturned;
DWORD cbPorts;
LPPORT_INFO_1 pPorts;
DWORD i;
BOOL Found = TRUE;
*pError = NO_ERROR;
if (!hSpoolssDll) {
hSpoolssDll = LoadLibrary(L"SPOOLSS.DLL");
if (hSpoolssDll) {
pfnSpoolssEnumPorts = GetProcAddress(hSpoolssDll,
"EnumPortsW");
if (!pfnSpoolssEnumPorts) {
*pError = GetLastError();
FreeLibrary(hSpoolssDll);
hSpoolssDll = NULL;
}
} else {
*pError = GetLastError();
}
}
if (!pfnSpoolssEnumPorts)
return FALSE;
if (!(*pfnSpoolssEnumPorts)(pName, 1, NULL, 0, &cbNeeded, &cReturned))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
cbPorts = cbNeeded;
pPorts = AllocSplMem(cbPorts);
if (pPorts)
{
if ((*pfnSpoolssEnumPorts)(pName, 1, (LPBYTE)pPorts, cbPorts,
&cbNeeded, &cReturned))
{
Found = FALSE;
for (i = 0; i < cReturned; i++)
{
if (!lstrcmpi(pPorts[i].pName, pPortName))
Found = TRUE;
}
}
}
FreeSplMem(pPorts);
}
}
else
Found = FALSE;
return Found;
}
VOID
LcmSplInSem(
VOID
)
{
if (LcmSpoolerSection.OwningThread != (HANDLE) UIntToPtr(GetCurrentThreadId())) {
DBGMSG(DBG_ERROR, ("Not in spooler semaphore\n"));
}
}
VOID
LcmSplOutSem(
VOID
)
{
if (LcmSpoolerSection.OwningThread == (HANDLE) UIntToPtr(GetCurrentThreadId())) {
DBGMSG(DBG_ERROR, ("Inside spooler semaphore !!\n"));
}
}
VOID
LcmEnterSplSem(
VOID
)
{
EnterCriticalSection(&LcmSpoolerSection);
}
VOID
LcmLeaveSplSem(
VOID
)
{
#if DBG
LcmSplInSem();
#endif
LeaveCriticalSection(&LcmSpoolerSection);
}
PINIENTRY
LcmFindName(
PINIENTRY pIniKey,
LPWSTR pName
)
{
if (pName) {
while (pIniKey) {
if (!lstrcmpi(pIniKey->pName, pName)) {
return pIniKey;
}
pIniKey=pIniKey->pNext;
}
}
return FALSE;
}
PINIENTRY
LcmFindIniKey(
PINIENTRY pIniEntry,
LPWSTR pName
)
{
if (!pName)
return NULL;
LcmSplInSem();
while (pIniEntry && lstrcmpi(pName, pIniEntry->pName))
pIniEntry = pIniEntry->pNext;
return pIniEntry;
}
LPBYTE
PackStrings(
LPWSTR *pSource,
LPBYTE pDest,
DWORD *DestOffsets,
LPBYTE pEnd
)
{
while (*DestOffsets != -1) {
if (*pSource) {
size_t cbString = wcslen(*pSource)*sizeof(WCHAR) + sizeof(WCHAR);
pEnd-= cbString;
StringCbCopy ((LPWSTR) pEnd, cbString, *pSource);;
*(LPWSTR UNALIGNED *)(pDest+*DestOffsets)= (LPWSTR) pEnd;
} else
*(LPWSTR UNALIGNED *)(pDest+*DestOffsets)=0;
pSource++;
DestOffsets++;
}
return pEnd;
}
/* LcmMessage
*
* Displays a LcmMessage by loading the strings whose IDs are passed into
* the function, and substituting the supplied variable argument list
* using the varargs macros.
*
*/
int LcmMessage(HWND hwnd, DWORD Type, int CaptionID, int TextID, ...)
{
WCHAR MsgText[256];
WCHAR MsgFormat[256];
WCHAR MsgCaption[40];
va_list vargs;
if( ( LoadString( LcmhInst, TextID, MsgFormat,
sizeof MsgFormat / sizeof *MsgFormat ) > 0 )
&& ( LoadString( LcmhInst, CaptionID, MsgCaption,
sizeof MsgCaption / sizeof *MsgCaption ) > 0 ) )
{
va_start( vargs, TextID );
StringCchVPrintf (MsgText, COUNTOF (MsgText), MsgFormat, vargs );
va_end( vargs );
return MessageBox(hwnd, MsgText, MsgCaption, Type);
}
else
return 0;
}
/*
*
*/
LPTSTR
LcmGetErrorString(
DWORD Error
)
{
TCHAR Buffer[1024];
LPTSTR pErrorString = NULL;
if( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
NULL, Error, 0, Buffer,
COUNTOF(Buffer), NULL )
== 0 )
LoadString( LcmhInst, IDS_UNKNOWN_ERROR,
Buffer, COUNTOF(Buffer) );
pErrorString = AllocSplStr(Buffer);
return pErrorString;
}
DWORD ReportError( HWND hwndParent,
DWORD idTitle,
DWORD idDefaultError )
{
DWORD ErrorID;
DWORD MsgType;
LPTSTR pErrorString;
ErrorID = GetLastError( );
if( ErrorID == ERROR_ACCESS_DENIED )
MsgType = MSG_INFORMATION;
else
MsgType = MSG_ERROR;
pErrorString = LcmGetErrorString( ErrorID );
LcmMessage( hwndParent, MsgType, idTitle,
idDefaultError, pErrorString );
FreeSplStr( pErrorString );
return ErrorID;
}
// @@BEGIN_DDKSPLIT
#ifndef INTERNAL
// @@END_DDKSPLIT
LPWSTR
AllocSplStr(
LPWSTR pStr
)
/*++
Routine Description:
This function will allocate enough local memory to store the specified
string, and copy that string to the allocated memory
Arguments:
pStr - Pointer to the string that needs to be allocated and stored
Return Value:
NON-NULL - A pointer to the allocated memory containing the string
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
LPWSTR pMem;
DWORD cbStr;
if (!pStr) {
return NULL;
}
cbStr = wcslen(pStr)*sizeof(WCHAR) + sizeof(WCHAR);
if (pMem = AllocSplMem( cbStr )) {
CopyMemory( pMem, pStr, cbStr );
}
return pMem;
}
LPVOID
AllocSplMem(
DWORD cbAlloc
)
{
PVOID pvMemory;
pvMemory = GlobalAlloc(GMEM_FIXED, cbAlloc);
if( pvMemory ){
ZeroMemory( pvMemory, cbAlloc );
}
return pvMemory;
}
// @@BEGIN_DDKSPLIT
#endif
// @@END_DDKSPLIT
DWORD
WINAPIV
StrNCatBuffW(
IN PWSTR pszBuffer,
IN UINT cchBuffer,
...
)
/*++
Description:
This routine concatenates a set of null terminated strings
into the provided buffer. The last argument must be a NULL
to signify the end of the argument list. This only called
from LocalMon by functions that use WCHARS.
Arguments:
pszBuffer - pointer buffer where to place the concatenated
string.
cchBuffer - character count of the provided buffer including
the null terminator.
... - variable number of string to concatenate.
Returns:
ERROR_SUCCESS if new concatenated string is returned,
or ERROR_XXX if an error occurred.
Notes:
The caller must pass valid strings as arguments to this routine,
if an integer or other parameter is passed the routine will either
crash or fail abnormally. Since this is an internal routine
we are not in try except block for performance reasons.
--*/
{
DWORD dwRetval = ERROR_INVALID_PARAMETER;
PCWSTR pszTemp = NULL;
PWSTR pszDest = NULL;
va_list pArgs;
//
// Validate the pointer where to return the buffer.
//
if (pszBuffer && cchBuffer)
{
//
// Assume success.
//
dwRetval = ERROR_SUCCESS;
//
// Get pointer to argument frame.
//
va_start(pArgs, cchBuffer);
//
// Get temp destination pointer.
//
pszDest = pszBuffer;
//
// Insure we have space for the null terminator.
//
cchBuffer--;
//
// Collect all the arguments.
//
for ( ; ; )
{
//
// Get pointer to the next argument.
//
pszTemp = va_arg(pArgs, PCWSTR);
if (!pszTemp)
{
break;
}
//
// Copy the data into the destination buffer.
//
for ( ; cchBuffer; cchBuffer-- )
{
if (!(*pszDest = *pszTemp))
{
break;
}
pszDest++, pszTemp++;
}
//
// If were unable to write all the strings to the buffer,
// set the error code and nuke the incomplete copied strings.
//
if (!cchBuffer && pszTemp && *pszTemp)
{
dwRetval = ERROR_BUFFER_OVERFLOW;
*pszBuffer = L'\0';
break;
}
}
//
// Terminate the buffer always.
//
*pszDest = L'\0';
va_end(pArgs);
}
//
// Set the last error in case the caller forgets to.
//
if (dwRetval != ERROR_SUCCESS)
{
SetLastError(dwRetval);
}
return dwRetval;
}
/* PortIsValid
*
* Validate the port by attempting to create/open it.
*/
BOOL
PortIsValid(
LPWSTR pPortName
)
{
HANDLE hFile;
BOOL Valid;
//
// For COM and LPT ports, no verification
//
if ( IS_COM_PORT( pPortName ) ||
IS_LPT_PORT( pPortName ) ||
IS_FILE_PORT( pPortName ) )
{
return TRUE;
}
hFile = CreateFile(pPortName,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
hFile = CreateFile(pPortName,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
}
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
Valid = TRUE;
} else {
Valid = FALSE;
}
return Valid;
}