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.
 
 
 
 
 
 

746 lines
17 KiB

/*++
Copyright (c) 1990 - 1995 Microsoft Corporation
Module Name:
util.c
Abstract:
Client Side Utility Routines
Author:
Dave Snipp (DaveSn) 15-Mar-1991
Revision History:
--*/
#include <windows.h>
#include <winspool.h>
#include <lmerr.h>
#include <string.h>
#include <stdlib.h>
#include <tchar.h>
#include <stdio.h>
#include "client.h"
#include "browse.h"
TCHAR *szNetMsgDll = TEXT("NETMSG.DLL");
LPVOID
DllAllocSplMem(
DWORD cb
)
/*++
Routine Description:
This function will allocate local memory. It will possibly allocate extra
memory and fill this with debugging information for the debugging version.
Arguments:
cb - The amount of memory to allocate
Return Value:
NON-NULL - A pointer to the allocated memory
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
LPDWORD pMem;
DWORD cbNew;
cb = DWORD_ALIGN_UP(cb);
cbNew = cb+2*sizeof(DWORD);
pMem=(LPDWORD)LocalAlloc(LPTR, cbNew);
if (!pMem) {
DBGMSG( DBG_WARNING, ("Memory Allocation failed for %d bytes\n", cbNew ));
return 0;
}
*pMem=cb;
*(LPDWORD)((LPBYTE)pMem+cbNew-sizeof(DWORD))=0xdeadbeef;
return (LPVOID)(pMem+1);
}
BOOL
DllFreeSplMem(
LPVOID pMem
)
{
DWORD cbNew;
LPDWORD pNewMem;
pNewMem = pMem;
pNewMem--;
cbNew = *pNewMem;
if (*(LPDWORD)((LPBYTE)pMem + cbNew) != 0xdeadbeef) {
DBGMSG(DBG_ERROR, ("DllFreeSplMem Corrupt Memory in winspool : %0lx\n", pNewMem));
return FALSE;
}
memset(pNewMem, 0x65, cbNew);
LocalFree((LPVOID)pNewMem);
return TRUE;
}
LPVOID
ReallocSplMem(
LPVOID pOldMem,
DWORD cbOld,
DWORD cbNew
)
{
LPVOID pNewMem;
pNewMem=AllocSplMem(cbNew);
if (pOldMem) {
if (cbOld)
memcpy(pNewMem, pOldMem, min(cbNew, cbOld));
FreeSplMem(pOldMem);
}
return pNewMem;
}
LPTSTR
AllocSplStr(
LPTSTR 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.
--*/
{
LPTSTR pMem;
if (!pStr)
return 0;
if (pMem = AllocSplMem( _tcslen(pStr)*sizeof(TCHAR) + sizeof(TCHAR) ))
_tcscpy(pMem, pStr);
return pMem;
}
BOOL
DllFreeSplStr(
LPTSTR pStr
)
{
return pStr ?
DllFreeSplMem(pStr) :
FALSE;
}
BOOL
ReallocSplStr(
LPTSTR *ppStr,
LPTSTR pStr
)
{
LPWSTR pOldStr = *ppStr;
*ppStr=AllocSplStr(pStr);
FreeSplStr(pOldStr);
return TRUE;
}
/* EnumGeneric
*
* A function which calls the spooler Enum* APIs and handles all the
* memory reallocation stuff when it's needed.
* Saves lots of hassle.
*
* Parameters:
*
* fnEnum - The Enum* function to be called (e.g. EnumPrinters).
*
* Level - The level of information requested.
*
* ppEnumData - The address of a pointer to a buffer of cbBuf length
* to receive the data, which must have been allocated by
* AllocSplMem. The buffer pointer may be NULL.
* If the buffer is not large enough, the function will reallocate.
*
* cbBuf - The initial length of the buffer pointed to by *ppEnumData.
*
* pcbReturned - A pointer to a DWORD to receive the size of the buffer
* returned.
*
* pcReturned - The count of objects returned in the buffer.
*
* Arg1, Arg2, Arg3 - Arguments specific to the Enum* function called,
* as commented below.
*
* Returns:
*
* TRUE if the function is successful.
* A return of false occurs if the specific Enum* call fails
* or if the attempt to reallocate the buffer fails.
*
* Author:
*
* andrewbe, August 1992
*
*/
#define COMMON_ARGS Level, (LPBYTE)*ppEnumData, cbBuf, pcbReturned, pcReturned
BOOL
EnumGeneric(
IN PROC fnEnum,
IN DWORD Level,
IN PBYTE *ppEnumData,
IN DWORD cbBuf,
OUT LPDWORD pcbReturned,
OUT LPDWORD pcReturned,
IN PVOID Arg1,
IN PVOID Arg2,
IN PVOID Arg3 )
{
BOOL rc;
BOOL UnknownFunction = FALSE;
DWORD cbRealloc;
if( fnEnum == (PROC)EnumPrinters )
rc = EnumPrinters( (DWORD)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
// Flags Name
else if( fnEnum == (PROC)EnumJobs )
rc = EnumJobs( (HANDLE)Arg1, (DWORD)Arg2, (DWORD)Arg3, COMMON_ARGS );
// hPrinter FirstJob NoJobs
else if( fnEnum == (PROC)EnumPrinterDrivers )
rc = EnumPrinterDrivers( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
// pName pEnvironment
else if( fnEnum == (PROC)EnumForms )
rc = EnumForms( (HANDLE)Arg1, COMMON_ARGS );
// hPrinter
else if( fnEnum == (PROC)EnumMonitors )
rc = EnumMonitors( (LPTSTR)Arg1, COMMON_ARGS );
// pName
else if( fnEnum == (PROC)EnumPorts )
rc = EnumPorts( (LPTSTR)Arg1, COMMON_ARGS );
// pName
else if( fnEnum == (PROC)EnumPrintProcessors )
rc = EnumPrintProcessors( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
// pName pEnvironment
else
{
*ppEnumData = NULL;
UnknownFunction = TRUE;
}
if( ( rc == FALSE ) && ( UnknownFunction == FALSE ) )
{
if( GetLastError( ) == ERROR_INSUFFICIENT_BUFFER )
{
cbRealloc = *pcbReturned;
if( cbBuf == 0 )
*ppEnumData = AllocSplMem( cbRealloc );
else
*ppEnumData = ReallocSplMem( *ppEnumData, cbBuf, cbRealloc );
cbBuf = cbRealloc;
if( *ppEnumData )
{
if( fnEnum == (PROC)EnumPrinters )
rc = EnumPrinters( (DWORD)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
// Flags Name
else if( fnEnum == (PROC)EnumJobs )
rc = EnumJobs( (HANDLE)Arg1, (DWORD)Arg2, (DWORD)Arg3, COMMON_ARGS );
// hPrinter FirstJob NoJobs
else if( fnEnum == (PROC)EnumPrinterDrivers )
rc = EnumPrinterDrivers( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
// pName pEnvironment
else if( fnEnum == (PROC)EnumForms )
rc = EnumForms( (HANDLE)Arg1, COMMON_ARGS );
// hPrinter
else if( fnEnum == (PROC)EnumMonitors )
rc = EnumMonitors( (LPTSTR)Arg1, COMMON_ARGS );
// pName
else if( fnEnum == (PROC)EnumPorts )
rc = EnumPorts( (LPTSTR)Arg1, COMMON_ARGS );
// pName
else if( fnEnum == (PROC)EnumPrintProcessors )
rc = EnumPrintProcessors( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
// pName pEnvironment
/* If things haven't worked out, free up the buffer.
* We do this because otherwise the caller will not know
* whether the pointer is valid any more,
* since ReallocSplMem might have failed.
*/
if( rc == FALSE )
{
if( *ppEnumData )
FreeSplMem( *ppEnumData );
*ppEnumData = NULL;
*pcbReturned = 0;
*pcReturned = 0;
}
}
}
else
{
if( *ppEnumData )
FreeSplMem( *ppEnumData );
*ppEnumData = NULL;
*pcbReturned = 0;
*pcReturned = 0;
rc = FALSE;
}
}
else
*pcbReturned = cbBuf;
return rc;
}
/* GetGeneric
*
* A function which calls the spooler Get* APIs and handles all the
* memory reallocation stuff when it's needed.
* Based on the EnumGeneric function.
*
* Parameters:
*
* fnGet - The Get* function to be called (e.g. GetPrinters).
*
* Level - The level of information requested.
*
* ppGetData - The address of a pointer to a buffer of cbBuf length
* to receive the data, which must have been allocated by
* AllocSplMem. The buffer pointer may be NULL.
* If the buffer is not large enough, the function will reallocate.
*
* cbBuf - The initial length of the buffer pointed to by *ppGetData.
*
* pcbReturned - A pointer to a DWORD to receive the size of the buffer
* returned.
*
* Arg1, Arg2 - Arguments specific to the Get* function called,
* as commented below.
*
* Returns:
*
* TRUE if the function is successful.
* A return of false occurs if the specific Get* call fails
* or if the attempt to reallocate the buffer fails.
*
* Author:
*
* andrewbe, August 1992
*
*/
#define GET_ARGS Level, (LPBYTE)*ppGetData, cbBuf, pcbReturned
BOOL
GetGeneric(
IN PROC fnGet,
IN DWORD Level,
IN PBYTE *ppGetData,
IN DWORD cbBuf,
OUT LPDWORD pcbReturned,
IN PVOID Arg1,
IN PVOID Arg2 )
{
BOOL rc;
BOOL UnknownFunction = FALSE;
DWORD cbRealloc;
DWORD Error;
if( fnGet == (PROC)GetPrinter )
rc = GetPrinter( (HANDLE)Arg1, GET_ARGS );
// hPrinter
else
{
*ppGetData = NULL;
UnknownFunction = TRUE;
}
if( ( rc == FALSE ) && ( UnknownFunction == FALSE ) )
{
if( ( Error = GetLastError( ) ) == ERROR_INSUFFICIENT_BUFFER )
{
cbRealloc = *pcbReturned;
*ppGetData = ReallocSplMem( *ppGetData, cbBuf, cbRealloc );
cbBuf = cbRealloc;
if( *ppGetData )
{
if( fnGet == (PROC)GetPrinter )
rc = GetPrinter( (HANDLE)Arg1, GET_ARGS );
// hPrinter
/* If things haven't worked out, free up the buffer.
* We do this because otherwise the caller will not know
* whether the pointer is valid any more,
* since ReallocSplMem might have failed.
*/
if( rc == FALSE )
{
if( *ppGetData )
FreeSplMem( *ppGetData );
*ppGetData = NULL;
*pcbReturned = 0;
}
}
}
else
{
if( *ppGetData )
FreeSplMem( *ppGetData );
*ppGetData = NULL;
*pcbReturned = 0;
rc = FALSE;
}
}
else
*pcbReturned = cbBuf;
return rc;
}
/*
*
*/
#define ENTRYFIELD_LENGTH 256
LPTSTR AllocDlgItemText(HWND hwnd, int id)
{
TCHAR string[ENTRYFIELD_LENGTH];
GetDlgItemText (hwnd, id, string, COUNTOF(string));
return ( *string ? AllocSplStr(string) : NULL );
}
/*
*
*/
LPTSTR
GetErrorString(
DWORD Error
)
{
TCHAR Buffer[1024];
LPTSTR pErrorString = NULL;
DWORD dwFlags;
HANDLE hModule;
if ((Error >= NERR_BASE) && (Error <= MAX_NERR)){
hModule = LoadLibrary(szNetMsgDll);
dwFlags = FORMAT_MESSAGE_FROM_HMODULE;
}
else {
hModule = NULL;
dwFlags = FORMAT_MESSAGE_FROM_SYSTEM;
}
if( FormatMessage( dwFlags, hModule,
Error, 0, Buffer,
COUNTOF(Buffer), NULL )
== 0 )
LoadString( hInst, IDS_UNKNOWN_ERROR, Buffer,
COUNTOF(Buffer));
pErrorString = AllocSplStr(Buffer);
if (hModule) {
FreeLibrary(hModule);
}
return pErrorString;
}
DWORD ReportFailure( HWND hwndParent,
DWORD idTitle,
DWORD idDefaultError )
{
DWORD ErrorID;
DWORD MsgType;
LPTSTR pErrorString;
ErrorID = GetLastError( );
MsgType = MSG_ERROR;
pErrorString = GetErrorString( ErrorID );
Message( hwndParent, MsgType, idTitle,
idDefaultError, pErrorString );
FreeSplStr( pErrorString );
return ErrorID;
}
BOOL
ValidatePrinterHandle(
HANDLE hPrinter
)
{
PSPOOL pSpool = hPrinter;
BOOL bReturnValue = FALSE;
try {
if ( pSpool && (pSpool->signature == SP_SIGNATURE)) {
bReturnValue = TRUE;
}
} except (1) {
}
if ( !bReturnValue ) {
SetLastError( ERROR_INVALID_HANDLE );
}
return bReturnValue;
}
PSECURITY_DESCRIPTOR
BuildInputSD(
PSECURITY_DESCRIPTOR pPrinterSD,
PDWORD pSizeSD
)
/*++
--*/
{
SECURITY_DESCRIPTOR AbsoluteSD;
PSECURITY_DESCRIPTOR pRelative;
BOOL Defaulted = FALSE;
BOOL DaclPresent = FALSE;
BOOL SaclPresent = FALSE;
PSID pOwnerSid = NULL;
PSID pGroupSid = NULL;
PACL pDacl = NULL;
PACL pSacl = NULL;
DWORD SDLength = 0;
//
// Initialize *pSizeSD = 0;
//
*pSizeSD = 0;
if (!IsValidSecurityDescriptor(pPrinterSD)) {
return(NULL);
}
if (!InitializeSecurityDescriptor (&AbsoluteSD, SECURITY_DESCRIPTOR_REVISION1)) {
return(NULL);
}
if(!GetSecurityDescriptorOwner(pPrinterSD,
&pOwnerSid, &Defaulted)){
return(NULL);
}
SetSecurityDescriptorOwner(&AbsoluteSD,
pOwnerSid, Defaulted );
if(! GetSecurityDescriptorGroup( pPrinterSD,
&pGroupSid, &Defaulted )){
return(NULL);
}
SetSecurityDescriptorGroup( &AbsoluteSD,
pGroupSid, Defaulted );
if(!GetSecurityDescriptorDacl( pPrinterSD,
&DaclPresent, &pDacl, &Defaulted )){
return(NULL);
}
SetSecurityDescriptorDacl( &AbsoluteSD,
DaclPresent, pDacl, Defaulted );
if(!GetSecurityDescriptorSacl( pPrinterSD,
&SaclPresent, &pSacl, &Defaulted)){
return(NULL);
}
SetSecurityDescriptorSacl( &AbsoluteSD,
SaclPresent, pSacl, Defaulted );
SDLength = GetSecurityDescriptorLength( &AbsoluteSD);
pRelative = LocalAlloc(LPTR, SDLength);
if (!pRelative) {
return(NULL);
}
if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &SDLength)) {
LocalFree(pRelative);
return(NULL);
}
*pSizeSD = SDLength;
return(pRelative);
}
PKEYDATA
CreateTokenList(
LPWSTR pKeyData
)
{
DWORD cTokens;
DWORD cb;
PKEYDATA pResult;
LPWSTR pDest;
LPWSTR psz = pKeyData;
LPWSTR *ppToken;
if (!psz || !*psz)
return NULL;
cTokens=1;
/* Scan through the string looking for commas,
* ensuring that each is followed by a non-NULL character:
*/
while ((psz = wcschr(psz, L',')) && psz[1]) {
cTokens++;
psz++;
}
cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
if (!(pResult = (PKEYDATA)AllocSplMem(cb)))
return NULL;
pResult->cb = cb;
/* Initialise pDest to point beyond the token pointers:
*/
pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
(cTokens-1) * sizeof(LPWSTR));
/* Then copy the key data buffer there:
*/
wcscpy(pDest, pKeyData);
ppToken = pResult->pTokens;
/* Remember, wcstok has the side effect of replacing the delimiter
* by NULL, which is precisely what we want:
*/
psz = wcstok (pDest, L",");
while (psz) {
*ppToken++ = psz;
psz = wcstok (NULL, L",");
}
pResult->cTokens = cTokens;
return( pResult );
}
LPWSTR
GetPrinterPortList(
HANDLE hPrinter
)
{
LPBYTE pMem;
LPTSTR pPort;
DWORD dwPassed = 1024; //Try 1K to start with
LPPRINTER_INFO_2 pPrinter;
DWORD dwLevel = 2;
DWORD dwNeeded;
PKEYDATA pKeyData;
DWORD i = 0;
LPWSTR pPortNames = NULL;
pMem = AllocSplMem(dwPassed);
if (pMem == NULL) {
return FALSE;
}
if (!GetPrinter(hPrinter, dwLevel, pMem, dwPassed, &dwNeeded)) {
DBGMSG(DBG_TRACE, ("Last error is %d\n", GetLastError()));
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
return NULL;
}
pMem = ReallocSplMem(pMem, dwPassed, dwNeeded);
dwPassed = dwNeeded;
if (!GetPrinter(hPrinter, dwLevel, pMem, dwPassed, &dwNeeded)) {
FreeSplMem(pMem);
return (NULL);
}
}
pPrinter = (LPPRINTER_INFO_2)pMem;
//
// Fixes the null pPrinter->pPortName problem where
// downlevel may return null
//
if (!pPrinter->pPortName) {
FreeSplMem(pMem);
return(NULL);
}
pPortNames = AllocSplStr(pPrinter->pPortName);
FreeSplMem(pMem);
return(pPortNames);
}