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.
 
 
 
 
 
 

1411 lines
31 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
prtq32.c
Abstract:
Print queue administration.
Author:
Don Ryan (donryan) 14-Jun-1995
Environment:
User Mode - Win32
Revision History:
14-Jun-1995 donryan Munged from windows\printman\security.c.
--*/
///////////////////////////////////////////////////////////////////////////////
// //
// Include files //
// //
///////////////////////////////////////////////////////////////////////////////
#include "prtq32.h"
///////////////////////////////////////////////////////////////////////////////
// //
// Global variables //
// //
///////////////////////////////////////////////////////////////////////////////
HINSTANCE g_hInstance;
LPTSTR g_pszPrinter = NULL;
TCHAR g_szHlpFile[] = TEXT("prtman.hlp");
GENERIC_MAPPING g_GenericMappingPrinters =
{
PRINTER_READ,
PRINTER_WRITE,
PRINTER_EXECUTE,
PRINTER_ALL_ACCESS
};
GENERIC_MAPPING g_GenericMappingDocuments =
{
JOB_READ,
JOB_WRITE,
JOB_EXECUTE,
JOB_ALL_ACCESS
};
SED_HELP_INFO g_PermissionsHelpInfo =
{
g_szHlpFile,
ID_HELP_PERMISSIONS_MAIN_DLG,
0,
0,
ID_HELP_PERMISSIONS_ADD_USER_DLG,
ID_HELP_PERMISSIONS_LOCAL_GROUP,
ID_HELP_PERMISSIONS_GLOBAL_GROUP,
ID_HELP_PERMISSIONS_FIND_ACCOUNT
};
SED_HELP_INFO g_AuditingHelpInfo =
{
g_szHlpFile,
ID_HELP_AUDITING_MAIN_DLG,
0,
0,
ID_HELP_AUDITING_ADD_USER_DLG,
ID_HELP_AUDITING_LOCAL_GROUP,
ID_HELP_AUDITING_GLOBAL_GROUP,
ID_HELP_AUDITING_FIND_ACCOUNT
};
SED_HELP_INFO g_TakeOwnershipHelpInfo =
{
g_szHlpFile,
ID_HELP_TAKE_OWNERSHIP
};
SED_OBJECT_TYPE_DESCRIPTOR g_ObjectTypeDescriptor =
{
SED_REVISION1, // Revision
TRUE, // IsContainer
TRUE, // AllowNewObjectPerms
TRUE, // MapSpecificPermsToGeneric
&g_GenericMappingPrinters, // GenericMapping
&g_GenericMappingDocuments, // GenericMappingNewObjects
NULL, // ObjectTypeName
NULL, // HelpInfo
NULL, // ApplyToSubContainerTitle
NULL, // ApplyToObjectsTitle
NULL, // ApplyToSubContainerConfirmation
NULL, // SpecialObjectAccessTitle
NULL // SpecialNewObjectAccessTitle
};
// Application accesses passed to the discretionary ACL editor
// as well as the Take Ownership dialog.
SED_APPLICATION_ACCESS g_pDiscretionaryAccessGroup[PERMS_COUNT] =
{
// No Access:
{
SED_DESC_TYPE_CONT_AND_NEW_OBJECT, // Type
0, // AccessMask1
0, // AccessMask2
NULL // PermissionTitle
},
// Print permission:
{
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
// Document Administer permission:
{
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
STANDARD_RIGHTS_READ,
GENERIC_ALL,
NULL
},
// Administer permission:
{
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
GENERIC_ALL,
GENERIC_ALL,
NULL
}
};
// Application accesses passed to the system ACL editor:
SED_APPLICATION_ACCESS g_pSystemAccessGroup[PERMS_AUDIT_COUNT] =
{
// Print permission:
{
SED_DESC_TYPE_AUDIT,
PRINTER_ACCESS_USE,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
{
SED_DESC_TYPE_AUDIT,
PRINTER_ACCESS_ADMINISTER | ACCESS_SYSTEM_SECURITY,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
{
SED_DESC_TYPE_AUDIT,
DELETE,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
{
SED_DESC_TYPE_AUDIT,
WRITE_DAC,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
{
SED_DESC_TYPE_AUDIT,
WRITE_OWNER,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
}
};
///////////////////////////////////////////////////////////////////////////////
// //
// Private prototypes //
// //
///////////////////////////////////////////////////////////////////////////////
VOID
CallDiscretionaryAclEditor(
HWND hWnd,
PQUEUE pPrinterContext
);
VOID
CallSystemAclEditor(
HWND hWnd,
PQUEUE pPrinterContext
);
VOID
CallTakeOwnershipDialog(
HWND hWnd,
PQUEUE pPrinterContext
);
DWORD
SedCallback2(
HWND hwndParent,
HANDLE hInstance,
DWORD CallBackContext,
PSECURITY_DESCRIPTOR pUpdatedSecurityDescriptor,
PSECURITY_DESCRIPTOR pSecDescNewObjects,
BOOLEAN ApplyToSubContainers,
BOOLEAN ApplyToSubObjects,
LPDWORD StatusReturn
);
BOOL
BuildNewSecurityDescriptor(
PSECURITY_DESCRIPTOR pNewSecurityDescriptor,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR pUpdatedSecurityDescriptor
);
PSECURITY_DESCRIPTOR
AllocCopySecurityDescriptor(
PSECURITY_DESCRIPTOR pSecurityDescriptor,
PDWORD pLength
);
BOOL
OpenPrinterForSpecifiedAccess(
LPTSTR pName,
LPHANDLE pHandle,
DWORD AccessRequested,
LPTSTR* pServerName,
PDWORD pAccessGranted
);
BOOL
CheckPrinterAccessForAuditing(
LPTSTR pPrinterName,
PHANDLE phPrinter
);
BOOL
GetGeneric(
IN PROC fnGet,
IN DWORD Level,
IN PBYTE *ppGetData,
IN DWORD cbBuf,
OUT LPDWORD pcbReturned,
IN PVOID Arg1,
IN PVOID Arg2
);
VOID
InitializeStrings(
);
LPTSTR
GetStr(
int id
);
LPVOID
AllocSplMem(
DWORD cb
);
LPVOID
ReallocSplMem(
LPVOID lpOldMem,
DWORD cbNew
);
BOOL
FreeSplMem(
LPVOID pMem
);
LPTSTR
AllocSplStr(
LPTSTR lpStr
);
BOOL
FreeSplStr(
LPTSTR lpStr
);
PQUEUE
AllocQueue(
LPTSTR pPrinterName
);
BOOL
FreeQueue(
PQUEUE pQueue
);
///////////////////////////////////////////////////////////////////////////////
// //
// General routines //
// //
///////////////////////////////////////////////////////////////////////////////
int APIENTRY
InitializeDLL(
HINSTANCE hInstance,
DWORD dwReason,
LPVOID lpReserved
)
/*++
Routine Description:
Dll's entry point.
Arguments:
Same as DllEntryPoint.
Return Values:
Same as DllEntryPoint.
--*/
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hInstance = hInstance;
DisableThreadLibraryCalls(hInstance);
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Exported routines //
// //
///////////////////////////////////////////////////////////////////////////////
void APIENTRY
EditQACL2(
HWND hWnd,
LPTSTR pPrinterName,
UINT SedId
)
/*++
Routine Description:
Edit NT print queue permissions.
Arguments:
hWnd - parent window.
pPrinterName - unc print queue path.
SedId - procedure identifier.
Return Values:
None.
--*/
{
PQUEUE pQueue;
if (pQueue = AllocQueue(pPrinterName))
{
if (OpenPrinterForSpecifiedAccess(
pQueue->pPrinterName,
&pQueue->hPrinter,
PRINTER_ACCESS_HIGHEST_PERMITTED,
&pQueue->pServerName,
&pQueue->AccessGranted
))
{
InitializeStrings();
switch (SedId)
{
case SED_ID_PERMS:
CallDiscretionaryAclEditor(hWnd, pQueue);
break;
case SED_ID_AUDIT:
CallSystemAclEditor(hWnd, pQueue);
break;
case SED_ID_OWNER:
CallTakeOwnershipDialog(hWnd, pQueue);
break;
}
ClosePrinter(pQueue->hPrinter);
}
FreeQueue(pQueue);
}
}
///////////////////////////////////////////////////////////////////////////////
// //
// Dispatch routines //
// //
///////////////////////////////////////////////////////////////////////////////
VOID
CallDiscretionaryAclEditor(
HWND hWnd,
PQUEUE pPrinterContext
)
/*++
Routine Description:
Edit access privileges of print queue.
Arguments:
hWnd - parent window.
pPrinterContext - printer context.
Return Values:
None.
--*/
{
SECURITY_CONTEXT SecurityContext;
HANDLE hPrinterWriteDac;
BOOL CantWriteDacl;
SED_APPLICATION_ACCESSES ApplicationAccesses;
PPRINTER_INFO_3 pPrinterInfo3 = NULL;
DWORD cbPrinterInfo3;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
DWORD Status;
DWORD Error;
DWORD i;
SecurityContext.SecurityInformation = DACL_SECURITY_INFORMATION;
SecurityContext.pPrinterContext = pPrinterContext;
if( GetGeneric( (PROC)GetPrinter, 3, (PBYTE *)&pPrinterInfo3, 0,
&cbPrinterInfo3, (PVOID)pPrinterContext->hPrinter, NULL ) )
{
SecurityContext.hPrinter = pPrinterContext->hPrinter;
pSecurityDescriptor = pPrinterInfo3->pSecurityDescriptor;
SecurityContext.pSecurityDescriptor = pSecurityDescriptor;
/* Pass all the permissions to the ACL editor,
* and set up the type required:
*/
ApplicationAccesses.Count = PERMS_COUNT;
ApplicationAccesses.AccessGroup = g_pDiscretionaryAccessGroup;
ApplicationAccesses.DefaultPermName =
g_pDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
for( i = 0; i < PERMS_COUNT; i++ )
ApplicationAccesses.AccessGroup[i].Type =
SED_DESC_TYPE_CONT_AND_NEW_OBJECT;
g_ObjectTypeDescriptor.AllowNewObjectPerms = TRUE;
g_ObjectTypeDescriptor.HelpInfo = &g_PermissionsHelpInfo;
Error = SedDiscretionaryAclEditor(
hWnd,
g_hInstance,
pPrinterContext->pServerName,
&g_ObjectTypeDescriptor,
&ApplicationAccesses,
pPrinterContext->pPrinterName,
SedCallback2,
(DWORD)&SecurityContext,
pSecurityDescriptor,
FALSE,
(BOOLEAN)(!(pPrinterContext->AccessGranted & WRITE_DAC)),
&Status,
0
);
if( Error != NO_ERROR )
{
// CODEWORK...
}
FreeSplMem( pPrinterInfo3 );
}
else
{
// CODEWORK...
}
}
VOID
CallSystemAclEditor(
HWND hWnd,
PQUEUE pPrinterContext
)
/*++
Routine Description:
Edit auditing properties of print queue.
Arguments:
hWnd - parent window.
pPrinterContext - printer context.
Return Values:
None.
--*/
{
SECURITY_CONTEXT SecurityContext;
HANDLE hPrinterSystemAccess;
SED_APPLICATION_ACCESSES ApplicationAccesses;
PPRINTER_INFO_3 pPrinterInfo3 = NULL;
DWORD cbPrinterInfo3;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
DWORD Status;
DWORD Error;
if( !CheckPrinterAccessForAuditing( pPrinterContext->pPrinterName,
&hPrinterSystemAccess ) )
{
//
// CODEWORK...
//
return;
}
SecurityContext.SecurityInformation = SACL_SECURITY_INFORMATION;
SecurityContext.pPrinterContext = pPrinterContext;
SecurityContext.hPrinter = hPrinterSystemAccess;
if( GetGeneric( (PROC)GetPrinter, 3, (PBYTE *)&pPrinterInfo3, 0,
&cbPrinterInfo3, (PVOID)hPrinterSystemAccess, NULL ) )
{
pSecurityDescriptor = pPrinterInfo3->pSecurityDescriptor;
SecurityContext.pSecurityDescriptor = pSecurityDescriptor;
/* Pass only the Print and Administer permissions to the ACL editor,
* and set up the type required:
*/
ApplicationAccesses.Count = PERMS_AUDIT_COUNT;
ApplicationAccesses.AccessGroup = g_pSystemAccessGroup;
ApplicationAccesses.DefaultPermName =
g_pDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
g_ObjectTypeDescriptor.AllowNewObjectPerms = FALSE;
g_ObjectTypeDescriptor.HelpInfo = &g_AuditingHelpInfo;
Error = SedSystemAclEditor(
hWnd,
g_hInstance,
pPrinterContext->pServerName,
&g_ObjectTypeDescriptor,
&ApplicationAccesses,
pPrinterContext->pPrinterName,
SedCallback2,
(DWORD)&SecurityContext,
pSecurityDescriptor,
FALSE,
&Status,
0
);
if( Error != NO_ERROR )
{
//
// CODEWORK...
//
}
FreeSplMem( pPrinterInfo3 );
}
else
{
//
// CODEWORK...
//
}
ClosePrinter( hPrinterSystemAccess );
}
VOID
CallTakeOwnershipDialog(
HWND hWnd,
PQUEUE pPrinterContext
)
/*++
Routine Description:
Edit ownership of print queue.
Arguments:
hWnd - parent window.
pPrinterContext - printer context.
Return Values:
None.
--*/
{
SECURITY_CONTEXT SecurityContext;
HANDLE hPrinterWriteOwner;
BOOL CantWriteOwner;
BOOL CantReadOwner;
SED_APPLICATION_ACCESSES ApplicationAccesses;
PPRINTER_INFO_3 pPrinterInfo3 = NULL;
DWORD cbPrinterInfo3;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
DWORD Status;
DWORD Error;
DWORD i;
SecurityContext.SecurityInformation = OWNER_SECURITY_INFORMATION;
SecurityContext.pPrinterContext = pPrinterContext;
if( GetGeneric( (PROC)GetPrinter, 3, (PBYTE *)&pPrinterInfo3, 0,
&cbPrinterInfo3, (PVOID)pPrinterContext->hPrinter, NULL ) )
{
SecurityContext.hPrinter = pPrinterContext->hPrinter;
pSecurityDescriptor = pPrinterInfo3->pSecurityDescriptor;
SecurityContext.pSecurityDescriptor = pSecurityDescriptor;
ApplicationAccesses.Count = PERMS_COUNT;
ApplicationAccesses.AccessGroup = g_pDiscretionaryAccessGroup;
ApplicationAccesses.DefaultPermName =
g_pDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
for( i = 0; i < PERMS_COUNT; i++ )
ApplicationAccesses.AccessGroup[i].Type =
SED_DESC_TYPE_AUDIT;
Error = SedTakeOwnership(
hWnd,
g_hInstance,
pPrinterContext->pServerName,
g_pszPrinter,
pPrinterContext->pPrinterName,
1,
SedCallback2,
(DWORD)&SecurityContext,
pSecurityDescriptor,
FALSE,
(BOOLEAN)(!(pPrinterContext->AccessGranted & WRITE_OWNER)),
&Status,
&g_TakeOwnershipHelpInfo,
0
);
if( Error != NO_ERROR )
{
//
// CODEWORK...
//
}
FreeSplMem( pPrinterInfo3 );
}
else
{
//
// CODEWORK...
//
}
}
///////////////////////////////////////////////////////////////////////////////
// //
// Security callback routine //
// //
///////////////////////////////////////////////////////////////////////////////
DWORD
SedCallback2(
HWND hwndParent,
HANDLE hInstance,
DWORD CallBackContext,
PSECURITY_DESCRIPTOR pUpdatedSecurityDescriptor,
PSECURITY_DESCRIPTOR pSecDescNewObjects,
BOOLEAN ApplyToSubContainers,
BOOLEAN ApplyToSubObjects,
LPDWORD StatusReturn
)
/*++
Routine Description:
Called by acledit to process writes.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
PSECURITY_CONTEXT pSecurityContext;
SECURITY_DESCRIPTOR NewSecurityDescriptor;
PRINTER_INFO_3 PrinterInfo3;
PSECURITY_DESCRIPTOR pSelfRelativeSD = NULL;
DWORD cbSelfRelativeSD;
BOOL OK = FALSE;
pSecurityContext = (PSECURITY_CONTEXT)CallBackContext;
if( InitializeSecurityDescriptor( &NewSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION1 )
&& BuildNewSecurityDescriptor( &NewSecurityDescriptor,
pSecurityContext->SecurityInformation,
pUpdatedSecurityDescriptor ) )
pSelfRelativeSD = AllocCopySecurityDescriptor( &NewSecurityDescriptor,
&cbSelfRelativeSD );
if( pSelfRelativeSD )
{
PrinterInfo3.pSecurityDescriptor = pSelfRelativeSD;
OK = SetPrinter( pSecurityContext->hPrinter, 3, (PBYTE)&PrinterInfo3, 0 );
FreeSplMem( pSelfRelativeSD );
}
return ( OK ? 0 : 1 );
UNREFERENCED_PARAMETER(hwndParent);
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(CallBackContext);
UNREFERENCED_PARAMETER(pSecDescNewObjects);
UNREFERENCED_PARAMETER(ApplyToSubContainers);
UNREFERENCED_PARAMETER(ApplyToSubObjects);
UNREFERENCED_PARAMETER(StatusReturn);
}
///////////////////////////////////////////////////////////////////////////////
// //
// Support routines //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL
BuildNewSecurityDescriptor(
PSECURITY_DESCRIPTOR pNewSecurityDescriptor,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR pUpdatedSecurityDescriptor
)
/*++
Routine Description:
Builds new security desriptor.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
BOOL Defaulted = FALSE;
PSID pOwnerSid = NULL;
PSID pGroupSid = NULL;
BOOL DaclPresent = FALSE;
PACL pDacl = NULL;
BOOL SaclPresent = FALSE;
PACL pSacl = NULL;
BOOL OK = TRUE;
if( ( SecurityInformation == OWNER_SECURITY_INFORMATION )
&& GetSecurityDescriptorOwner( pUpdatedSecurityDescriptor,
&pOwnerSid, &Defaulted ) )
{
OK = SetSecurityDescriptorOwner( pNewSecurityDescriptor,
pOwnerSid, Defaulted );
}
if( ( SecurityInformation == DACL_SECURITY_INFORMATION )
&& GetSecurityDescriptorDacl( pUpdatedSecurityDescriptor,
&DaclPresent, &pDacl, &Defaulted ) )
{
OK = SetSecurityDescriptorDacl( pNewSecurityDescriptor,
DaclPresent, pDacl, Defaulted );
}
if( ( SecurityInformation == SACL_SECURITY_INFORMATION )
&& GetSecurityDescriptorSacl( pUpdatedSecurityDescriptor,
&SaclPresent, &pSacl, &Defaulted ) )
{
OK = SetSecurityDescriptorSacl( pNewSecurityDescriptor,
SaclPresent, pSacl, Defaulted );
}
return OK;
}
PSECURITY_DESCRIPTOR
AllocCopySecurityDescriptor(
PSECURITY_DESCRIPTOR pSecurityDescriptor,
PDWORD pLength
)
/*++
Routine Description:
Alloc copy of security descriptor.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
PSECURITY_DESCRIPTOR pSecurityDescriptorCopy;
DWORD Length;
Length = GetSecurityDescriptorLength(pSecurityDescriptor);
if(pSecurityDescriptorCopy = AllocSplMem(Length))
{
MakeSelfRelativeSD(pSecurityDescriptor,
pSecurityDescriptorCopy,
&Length);
*pLength = Length;
}
return pSecurityDescriptorCopy;
}
BOOL
OpenPrinterForSpecifiedAccess(
LPTSTR pName,
LPHANDLE pHandle,
DWORD AccessRequested,
LPTSTR* pServerName,
PDWORD pAccessGranted
)
/*++
Routine Description:
Obtains printer handle w/access.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
PRINTER_DEFAULTS PrinterDefaults;
BOOL rc = FALSE;
BOOL TryAll = FALSE;
PrinterDefaults.pDatatype = NULL;
PrinterDefaults.pDevMode = NULL;
switch( AccessRequested )
{
case PRINTER_ACCESS_HIGHEST_PERMITTED:
TryAll = TRUE;
/* fall through ... */
case PRINTER_ALL_ACCESS:
PrinterDefaults.DesiredAccess = PRINTER_ALL_ACCESS;
rc = OpenPrinter( pName, pHandle, &PrinterDefaults );
if( rc || !TryAll || (( GetLastError( ) != ERROR_ACCESS_DENIED ) &&
( GetLastError( ) != ERROR_PRIVILEGE_NOT_HELD)) )
break;
case PRINTER_READ:
PrinterDefaults.DesiredAccess = PRINTER_READ;
rc = OpenPrinter( pName, pHandle, &PrinterDefaults );
if( rc || !TryAll || (( GetLastError( ) != ERROR_ACCESS_DENIED ) &&
( GetLastError( ) != ERROR_PRIVILEGE_NOT_HELD)) )
break;
case READ_CONTROL:
PrinterDefaults.DesiredAccess = READ_CONTROL;
rc = OpenPrinter( pName, pHandle, &PrinterDefaults );
}
if( pAccessGranted )
{
if( rc )
*pAccessGranted = PrinterDefaults.DesiredAccess;
else
*pAccessGranted = PRINTER_ACCESS_DENIED;
}
if (pServerName)
{
if( rc )
{
TCHAR szServerName[MAX_PATH];
LPTSTR pSlash;
lstrcpy(szServerName, pName);
pSlash = StrChr( &szServerName[2], TEXT('\\'));
if (pSlash)
*pSlash = TEXT('\0'); // Terminate server at \\foo
*pServerName = AllocSplStr(szServerName);
}
else
*pServerName = NULL;
}
return rc;
}
BOOL
CheckPrinterAccessForAuditing(
LPTSTR pPrinterName,
PHANDLE phPrinter
)
/*++
Routine Description:
Grants system access if possible.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
PRINTER_DEFAULTS PrinterDefaults;
BOOL rc = FALSE;
PrinterDefaults.pDatatype = NULL;
PrinterDefaults.pDevMode = NULL;
PrinterDefaults.DesiredAccess = ACCESS_SYSTEM_SECURITY;
rc = OpenPrinter( pPrinterName, phPrinter, &PrinterDefaults );
return rc;
}
#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
)
/*++
Routine Description:
Wrapper around GetInfo calls.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
BOOL rc = FALSE;
BOOL UnknownFunction = FALSE;
DWORD cbRealloc;
if( fnGet == (PROC)GetPrinter )
rc = GetPrinter( (HANDLE)Arg1, GET_ARGS );
// hPrinter
else
{
*ppGetData = NULL;
UnknownFunction = TRUE;
}
if( ( rc == FALSE ) && ( UnknownFunction == FALSE ) )
{
if( GetLastError( ) == ERROR_INSUFFICIENT_BUFFER )
{
cbRealloc = *pcbReturned;
*ppGetData = (PBYTE)ReallocSplMem( *ppGetData, 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;
}
VOID
InitializeStrings(
)
/*++
Routine Description:
Wrapper around LocalAlloc.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
if( !g_pszPrinter )
{
g_pszPrinter = GetStr( IDS_PRINTER );
g_ObjectTypeDescriptor.ObjectTypeName = g_pszPrinter;
g_pDiscretionaryAccessGroup[PERMS_NOACC].PermissionTitle =
GetStr( IDS_NOACCESS );
g_pDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle =
GetStr( IDS_PRINT );
g_pDiscretionaryAccessGroup[PERMS_DOCAD].PermissionTitle =
GetStr( IDS_ADMINISTERDOCUMENTS );
g_pDiscretionaryAccessGroup[PERMS_ADMIN].PermissionTitle =
GetStr( IDS_ADMINISTER );
g_pSystemAccessGroup[PERMS_AUDIT_PRINT].PermissionTitle =
GetStr( IDS_AUDIT_PRINT );
g_pSystemAccessGroup[PERMS_AUDIT_ADMINISTER].PermissionTitle =
GetStr( IDS_AUDIT_ADMINISTER );
g_pSystemAccessGroup[PERMS_AUDIT_DELETE].PermissionTitle =
GetStr( IDS_AUDIT_DELETE );
g_pSystemAccessGroup[PERMS_AUDIT_CHANGE_PERMISSIONS].PermissionTitle =
GetStr( IDS_CHANGE_PERMISSIONS );
g_pSystemAccessGroup[PERMS_AUDIT_TAKE_OWNERSHIP].PermissionTitle =
GetStr( IDS_TAKE_OWNERSHIP );
}
}
LPTSTR
GetStr(
int id
)
/*++
Routine Description:
Load resource string.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
TCHAR ResString[MAX_PATH];
DWORD length = 0;
LPTSTR pStr;
DWORD cbStr;
length = LoadString(g_hInstance, id, ResString, sizeof(ResString)/sizeof(TCHAR));
cbStr = ( length * sizeof ( TCHAR ) + sizeof ( TCHAR ) );
pStr = (LPTSTR)AllocSplMem( cbStr );
if( pStr )
memcpy( pStr, ResString, cbStr );
return pStr;
}
LPVOID
AllocSplMem(
DWORD cb
)
/*++
Routine Description:
Wrapper around LocalAlloc.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
LPDWORD pMem;
if (!cb)
return(NULL);
pMem=(LPDWORD)LocalAlloc(LPTR, cb);
if (!pMem)
return NULL;
return (LPVOID)pMem;
}
LPVOID
ReallocSplMem(
LPVOID lpOldMem,
DWORD cbNew
)
/*++
Routine Description:
Wrapper around LocalReAlloc.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
if (lpOldMem)
return LocalReAlloc(lpOldMem, cbNew, LMEM_MOVEABLE);
else
return AllocSplMem(cbNew);
}
BOOL
FreeSplMem(
LPVOID pMem
)
/*++
Routine Description:
Wrapper around LocalFree.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
return LocalFree((HLOCAL)pMem) == NULL;
}
LPTSTR
AllocSplStr(
LPTSTR lpStr
)
/*++
Routine Description:
Alloc copy of string.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
LPTSTR lpMem;
if (!lpStr)
return 0;
if (lpMem = (LPTSTR)AllocSplMem( (lstrlen(lpStr) + 1 )*sizeof(TCHAR)))
lstrcpy(lpMem, lpStr);
return lpMem;
}
BOOL
FreeSplStr(
LPTSTR lpStr
)
/*++
Routine Description:
Free copy of string.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
return lpStr ? FreeSplMem(lpStr) : FALSE;
}
PQUEUE
AllocQueue(
LPTSTR pPrinterName
)
/*++
Routine Description:
Alloc queue context.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
PQUEUE pQueue;
if( ( pQueue = (PQUEUE)AllocSplMem( sizeof( QUEUE ) ) )
&&( pQueue->pPrinterName = AllocSplStr( pPrinterName ) ) )
{
pQueue->pServerName = NULL;
}
else
if( pQueue )
{
FreeSplMem( pQueue );
pQueue = NULL;
}
return pQueue;
}
BOOL
FreeQueue(
PQUEUE pQueue
)
/*++
Routine Description:
Free queue context.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
if(pQueue->pServerName)
FreeSplStr(pQueue->pServerName);
FreeSplStr(pQueue->pPrinterName);
FreeSplMem(pQueue);
return TRUE;
}