//Copyright (c) 1998 - 1999 Microsoft Corporation /******************************************************************************* * * security.c * * WinStation ACL editing functions (based on code from NT PRINTMAN security.c) * * copyright notice: Copyright 1995, Citrix Systems Inc. * * $Author: donm $ Butch Davis * * $Log: N:\nt\private\utils\citrix\winutils\tscfg\VCS\security.c $ * * Rev 1.12 19 Mar 1998 16:38:40 donm * was looking for old help file * * Rev 1.11 20 Sep 1996 20:37:18 butchd * update * * Rev 1.10 19 Sep 1996 15:58:44 butchd * update * * Rev 1.9 12 Sep 1996 16:16:38 butchd * update * *******************************************************************************/ /* * We must compile for UNICODE because of ACL edit structures & interface, which * is UNICODE-only. */ #ifndef UNICODE #define UNICODE 1 #endif #ifndef _UNICODE #define _UNICODE 1 #endif /* * include files */ #include #include #include #include #include #include #include #include #include "defines.h" #include "resource.h" #include "security.h" #include "common.h" #include /* * Global variables for WINUTILS Common functions. */ LPCTSTR WinUtilsAppName; HWND WinUtilsAppWindow; HINSTANCE WinUtilsAppInstance; //////////////////////////////////////////////////////////////////////////////// // typedefs, defines, persistant storage, and private function prototypes /* * Indexes into the APPLICATION_ACCESSES structure: */ #define PERMS_SPECIAL_QUERY 0 /* query information access */ #define PERMS_SPECIAL_SET 1 /* set information access */ #define PERMS_SPECIAL_RESET 2 /* reset access */ #define PERMS_SPECIAL_SHADOW 3 /* shadow access */ #define PERMS_SPECIAL_LOGON 4 /* logon access */ #define PERMS_SPECIAL_LOGOFF 5 /* logoff access */ #define PERMS_SPECIAL_MSG 6 /* message access */ #define PERMS_SPECIAL_CONNECT 7 /* connect access */ #define PERMS_SPECIAL_DISCONNECT 8 /* disconnect access */ #define PERMS_SPECIAL_DELETE 9 /* delete access */ #define PERMS_RESOURCE_NOACCESS 10 /* no access grouping */ #define PERMS_RESOURCE_GUEST 11 /* guest access grouping */ #define PERMS_RESOURCE_USER 12 /* user access grouping */ #define PERMS_RESOURCE_ADMIN 13 /* all (admin) access grouping */ #define PERMS_COUNT 14 /* Total number of permissions */ /* * Typedefs and static storage. */ typedef struct _SECURITY_CONTEXT { PWINSTATIONNAME pWSName; } SECURITY_CONTEXT, *PSECURITY_CONTEXT; /* * We need this structure even though we're not doing generic access mapping. */ GENERIC_MAPPING GenericMapping = { /* GenericMapping: */ GENERIC_READ, /* GenericRead */ GENERIC_WRITE, /* GenericWrite */ GENERIC_EXECUTE, /* GenericExecute */ GENERIC_ALL /* GenericAll */ }; WCHAR szLWinCfgHlp[] = L"TSCFG.HLP"; TCHAR szAclEdit[] = TEXT("ACLEDIT"); /* DLL containing ACL Edit Dialog */ char szSedDiscretionaryAclEditor[] = "SedDiscretionaryAclEditor"; LPWSTR pwstrWinStation = NULL; LPWSTR pwstrSpecial = NULL; #define IDD_BASE 0x20000 // makehelp.bat uses this base offset to form HIDD_ symbol SED_HELP_INFO PermissionsHelpInfo = { /* HelpInfo */ szLWinCfgHlp, IDD_HELP_PERMISSIONS_MAIN+IDD_BASE, IDD_HELP_PERMISSIONS_SPECIAL_ACCESS+IDD_BASE, 0, IDD_HELP_PERMISSIONS_ADD_USER+IDD_BASE, IDD_HELP_PERMISSIONS_LOCAL_GROUP+IDD_BASE, IDD_HELP_PERMISSIONS_GLOBAL_GROUP+IDD_BASE, IDD_HELP_PERMISSIONS_FIND_ACCOUNT+IDD_BASE }; SED_OBJECT_TYPE_DESCRIPTOR ObjectTypeDescriptor = { SED_REVISION1, /* Revision */ FALSE, /* IsContainer */ FALSE, /* AllowNewObjectPerms */ FALSE, /* MapSpecificPermsToGeneric */ &GenericMapping, /* GenericMapping */ NULL, /* GenericMappingNewObjects */ NULL, /* ObjectTypeName */ NULL, /* HelpInfo */ NULL, /* ApplyToSubContainerTitle */ NULL, /* ApplyToObjectsTitle */ NULL, /* ApplyToSubContainerConfirmation */ NULL, /* SpecialObjectAccessTitle */ NULL /* SpecialNewObjectAccessTitle */ }; /* * Application accesses passed to the discretionary ACL editor. */ SED_APPLICATION_ACCESS pDiscretionaryAccessGroup[PERMS_COUNT] = { /* query (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, /* Type */ WINSTATION_QUERY, /* AccessMask1 */ 0, /* AccessMask2 */ NULL /* PermissionTitle */ }, /* set (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_SET, 0, NULL }, /* reset (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_RESET, 0, NULL }, /* shadow (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_SHADOW, 0, NULL }, /* logon (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_LOGON, 0, NULL }, /* logoff (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_LOGOFF, 0, NULL }, /* message (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_MSG, 0, NULL }, /* connect (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_CONNECT, 0, NULL }, /* disconnect (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_DISCONNECT, 0, NULL }, /* delete (Special...) */ { SED_DESC_TYPE_RESOURCE_SPECIAL, DELETE, 0, NULL }, /* no access (grouping): */ { SED_DESC_TYPE_RESOURCE, 0, 0, NULL }, /* guest access (grouping) */ { SED_DESC_TYPE_RESOURCE, WINSTATION_GUEST_ACCESS, 0, NULL }, /* user access (grouping) */ { SED_DESC_TYPE_RESOURCE, WINSTATION_USER_ACCESS, 0, NULL }, /* administrator access (grouping) */ { SED_DESC_TYPE_RESOURCE, GENERIC_ALL, // maps to WINSTATION_ALL_ACCESS on WinStationOpen() 0, NULL } }; #define PRIV_SECURITY 0 #define PRIV_COUNT 1 LUID SecurityValue; /* * Definitions from SEDAPI.H: * (unfortunately we have to do this if we want to link dynamically) */ typedef DWORD (WINAPI *SED_DISCRETIONARY_ACL_EDITOR)( HWND Owner, HANDLE Instance, LPWSTR Server, PSED_OBJECT_TYPE_DESCRIPTOR ObjectType, PSED_APPLICATION_ACCESSES ApplicationAccesses, LPWSTR ObjectName, PSED_FUNC_APPLY_SEC_CALLBACK ApplySecurityCallbackRoutine, ULONG CallbackContext, PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN CouldntReadDacl, BOOLEAN CantWriteDacl, LPDWORD SEDStatusReturn, DWORD Flags ); SED_DISCRETIONARY_ACL_EDITOR lpfnSedDiscretionaryAclEditor = NULL; /* * Private function prototypes (public prototypes are in security.h). */ DWORD SetWinStationSecurity( PWINSTATIONNAME pWSName, PSECURITY_DESCRIPTOR pSecurityDescriptor ); DWORD ValidateSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor); FARPROC LoadLibraryGetProcAddress( HWND hwnd, LPTSTR LibraryName, LPCSTR ProcName, PHANDLE phLibrary ); void InitializeSecurityStrings( ); VOID ReportSecurityFailure(HWND hwnd, DWORD ErrorResource, LPCTSTR String, DWORD Error); LPVOID AllocSplMem( DWORD cb ); BOOL FreeSplMem( LPVOID pMem ); LPWSTR GetUnicodeString( int id ); DWORD WINAPI SedCallback( HWND hwndParent, HANDLE hInstance, ULONG CallBackContext, PSECURITY_DESCRIPTOR pNewSecurityDescriptor, PSECURITY_DESCRIPTOR pSecDescNewObjects, BOOLEAN ApplyToSubContainers, BOOLEAN ApplyToSubObjects, LPDWORD StatusReturn ); //////////////////////////////////////////////////////////////////////////////// // public functions /******************************************************************************* * * CallPermissionsDialog (public function) * * Call the SedDiscretionaryAclEditor() function in ACLEDIT dll. * * ENTRY: * hwnd (input) * window handle of parent for ACL edit dialog. * bAdmin (input) * TRUE if user is an Administrator (can write to WinStation registry) * FALSE otherwise (permissions will be read-only). * pWSName (input) * Name of WinStation to edit security for. * EXIT: * (BOOL) TRUE if any winstations were modified; FALSE otherwise. * ******************************************************************************/ BOOL CallPermissionsDialog( HWND hwnd, BOOL bAdmin, PWINSTATIONNAME pWSName ) { SECURITY_CONTEXT SecurityContext; BOOLEAN CantWriteDacl; SED_APPLICATION_ACCESSES ApplicationAccesses; HANDLE hLibrary; PSECURITY_DESCRIPTOR pSecurityDescriptor; DWORD Status = SED_STATUS_NOT_MODIFIED; DWORD Error; HCURSOR hOldCursor; hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); /* * Get the current WinStation security */ if ( (Error = GetWinStationSecurity(pWSName, &pSecurityDescriptor)) != ERROR_SUCCESS ) { ReportSecurityFailure( hwnd, IDP_ERROR_GET_SECURITY_WINSTATION, pWSName, Error ); SetCursor(hOldCursor); return(FALSE); } /* * If we're not allowed access to write to WinStation registry, flag such. */ CantWriteDacl = !(BOOL)bAdmin; if( !lpfnSedDiscretionaryAclEditor ) lpfnSedDiscretionaryAclEditor = (SED_DISCRETIONARY_ACL_EDITOR)LoadLibraryGetProcAddress( hwnd, szAclEdit, szSedDiscretionaryAclEditor, &hLibrary); if( lpfnSedDiscretionaryAclEditor ) { InitializeSecurityStrings( ); ObjectTypeDescriptor.ObjectTypeName = pwstrWinStation; /* * Pass all the permissions to the ACL editor, * and set up the type required: */ ApplicationAccesses.Count = PERMS_COUNT; ApplicationAccesses.AccessGroup = pDiscretionaryAccessGroup; ApplicationAccesses.DefaultPermName = pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle; ObjectTypeDescriptor.HelpInfo = &PermissionsHelpInfo; ObjectTypeDescriptor.SpecialObjectAccessTitle = pwstrSpecial; SecurityContext.pWSName = pWSName; Error = (*lpfnSedDiscretionaryAclEditor ) (hwnd, NULL, NULL, &ObjectTypeDescriptor, &ApplicationAccesses, pWSName, (PSED_FUNC_APPLY_SEC_CALLBACK)SedCallback, (ULONG)&SecurityContext, pSecurityDescriptor, FALSE, CantWriteDacl, &Status, 0); if( Error != ERROR_SUCCESS ) ReportSecurityFailure(hwnd, IDP_ERROR_PERMISSIONS_EDITOR_FAILED, NULL, Error); } SetCursor(hOldCursor); LocalFree(pSecurityDescriptor); return( ((Status == SED_STATUS_NOT_MODIFIED) || (Status == SED_STATUS_NOT_ALL_MODIFIED)) ? FALSE : TRUE ); } // end CallPermissionsDialog /******************************************************************************* * * GetWinStationSecurityA (public function - ANSI stub) * * (see GetWinStationSecurityW) * * ENTRY: * (see GetWinStationSecurityW) * EXIT: * (see GetWinStationSecurityW) * ******************************************************************************/ DWORD GetWinStationSecurityA( PWINSTATIONNAMEA pWSName, PSECURITY_DESCRIPTOR *ppSecurityDescriptor ) { WINSTATIONNAMEW WSNameW; /* * Copy ANSI WinStation name to UNICODE and call GetWinStationNameW(). */ mbstowcs(WSNameW, pWSName, sizeof(WSNameW)); return( GetWinStationSecurityW(WSNameW, ppSecurityDescriptor) ); } // GetWinStationSecurityA /******************************************************************************* * * GetWinStationSecurityW (public function - UNICODE) * * Obtain the security descriptor for the specified WinStation. If the * WinStation does not have a security descriptor associated with it, * will quietly call GetDefaultWinStationSecurity() to get the default * security descriptor for it. * * ENTRY: * pWSName (input) * UNICODE name of WinStation to get security descriptor for. * ppSecurityDescriptor (output) * on success, set to pointer to allocated memory containing the * WinStation's security descriptor. * EXIT: * ERROR_SUCCESS if all is OK; error code and *pSecurityDescriptor set to * NULL if error. * * NOTE: on success, the memory pointed to by *ppSecurityDescriptor should be * LocalFree()'d by the caller when the security descriptor is no longer * needed. * ******************************************************************************/ DWORD GetWinStationSecurityW( PWINSTATIONNAMEW pWSName, PSECURITY_DESCRIPTOR *ppSecurityDescriptor ) { DWORD Error, SDLength, SDLengthRequired; *ppSecurityDescriptor = NULL; if ( (Error = RegWinStationQuerySecurity( SERVERNAME_CURRENT, pWSName, NULL, 0, &SDLengthRequired )) == ERROR_INSUFFICIENT_BUFFER ) { if ( !(*ppSecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc( 0, SDLength = SDLengthRequired)) ) { Error = ERROR_NOT_ENOUGH_MEMORY; } else { Error = RegWinStationQuerySecurity( SERVERNAME_CURRENT, pWSName, *ppSecurityDescriptor, SDLength, &SDLengthRequired ); } } else { /* * Unexpected error. If 'not found', fetch the default WinStation SD. */ if ( Error == ERROR_FILE_NOT_FOUND ) return( GetDefaultWinStationSecurity(ppSecurityDescriptor) ); } /* * Check for a valid SD before returning. */ if ( Error == ERROR_SUCCESS ) { Error = ValidateSecurityDescriptor(*ppSecurityDescriptor); } else if ( *ppSecurityDescriptor ) { LocalFree(*ppSecurityDescriptor); *ppSecurityDescriptor = NULL; } return(Error); } // GetWinStationSecurityW /******************************************************************************* * * GetDefaultWinStationSecurity (public function) * * Obtain the default WinStation security descriptor. * * ENTRY: * ppSecurityDescriptor (output) * on success, set to pointer to allocated memory containing the * default WinStation security descriptor. * EXIT: * ERROR_SUCCESS if all is OK; error code and *pSecurityDescriptor set to * NULL if error. * * NOTE: on success, the memory pointed to by *ppSecurityDescriptor should be * LocalFree()'d by the caller when the security descriptor is no longer * needed. * ******************************************************************************/ DWORD GetDefaultWinStationSecurity( PSECURITY_DESCRIPTOR *ppSecurityDescriptor ) { DWORD Error, SDLength, SDLengthRequired; *ppSecurityDescriptor = NULL; if ( (Error = RegWinStationQueryDefaultSecurity( SERVERNAME_CURRENT, NULL, 0, &SDLengthRequired )) == ERROR_INSUFFICIENT_BUFFER ) { if ( !(*ppSecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc( 0, SDLength = SDLengthRequired)) ) { Error = ERROR_NOT_ENOUGH_MEMORY; } else { Error = RegWinStationQueryDefaultSecurity( SERVERNAME_CURRENT, *ppSecurityDescriptor, SDLength, &SDLengthRequired ); } } /* * Check for a valid SD before returning. */ if ( Error == ERROR_SUCCESS ) { Error = ValidateSecurityDescriptor(*ppSecurityDescriptor); } else if ( *ppSecurityDescriptor ) { LocalFree(*ppSecurityDescriptor); *ppSecurityDescriptor = NULL; } return(Error); } // GetDefaultWinStationSecurity /******************************************************************************* * * FreeSecurityStrings (public function) * * Free allocated memory for ACL edit string resources. This function * should be called when the application exits. * * ENTRY: * EXIT: * ******************************************************************************/ void FreeSecurityStrings( ) { /* * Only perform free if the strings have been allocated and loaded. */ if( pwstrWinStation ) { FreeSplMem(pwstrWinStation); FreeSplMem(pwstrSpecial); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_QUERY].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_SET].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_RESET].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_SHADOW].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGON].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGOFF].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_MSG].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_CONNECT].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_DISCONNECT].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_DELETE].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_NOACCESS].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_GUEST].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_ADMIN].PermissionTitle); } } // end FreeSecurityStrings //////////////////////////////////////////////////////////////////////////////// // private functions /******************************************************************************* * * InitializeSecurityStrings (private function) * * Allocate and load ACL editing string resources if not done already. * The application should call the public FreeSecurityStrings() function * to free allocated memory when the application exits. * * ENTRY: * EXIT: * ******************************************************************************/ void InitializeSecurityStrings() { if( !pwstrWinStation ) { pwstrWinStation = GetUnicodeString(IDS_WINSTATION); pwstrSpecial = GetUnicodeString(IDS_SPECIALACCESS); pDiscretionaryAccessGroup[PERMS_SPECIAL_QUERY].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_QUERY); pDiscretionaryAccessGroup[PERMS_SPECIAL_SET].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_SET); pDiscretionaryAccessGroup[PERMS_SPECIAL_RESET].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_RESET); pDiscretionaryAccessGroup[PERMS_SPECIAL_SHADOW].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_SHADOW); pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGON].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_LOGON); pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGOFF].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_LOGOFF); pDiscretionaryAccessGroup[PERMS_SPECIAL_MSG].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_MSG); pDiscretionaryAccessGroup[PERMS_SPECIAL_CONNECT].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_CONNECT); pDiscretionaryAccessGroup[PERMS_SPECIAL_DISCONNECT].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_DISCONNECT); pDiscretionaryAccessGroup[PERMS_SPECIAL_DELETE].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_DELETE); pDiscretionaryAccessGroup[PERMS_RESOURCE_NOACCESS].PermissionTitle = GetUnicodeString(IDS_PERMS_RESOURCE_NOACCESS); pDiscretionaryAccessGroup[PERMS_RESOURCE_GUEST].PermissionTitle = GetUnicodeString(IDS_PERMS_RESORUCE_GUEST); pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle = GetUnicodeString(IDS_PERMS_RESORUCE_USER); pDiscretionaryAccessGroup[PERMS_RESOURCE_ADMIN].PermissionTitle = GetUnicodeString(IDS_PERMS_RESOURCE_ADMIN); } } // end InitializeSecurityStrings /******************************************************************************* * * ReportSecurityFailure (private function) * * Output an appropriate error message for security failure. * * ENTRY: * hwnd (input) * window handle of parent for message box. * ErrorResource (input) * resource ID of error format string. * String (input) * If not NULL, points to string to output as part of message. * Error (input) * Error code * EXIT: * * NOTE: all ErrorResource format strings should specify a %d for Error code * and %S for system error message string as the last two substitution * arguments. The %S is optional, and must be present in the format * string if the String argument is non-NULL. * ******************************************************************************/ VOID ReportSecurityFailure(HWND hwnd, DWORD ErrorResource, LPCTSTR String, DWORD Error) { HWND hwndSave = WinUtilsAppWindow; /* * Set parent window in WinUtilsAppWindow global for use * by STANDARD_ERROR_MESSAGE macro (StandardErrorMessage function). */ WinUtilsAppWindow = hwnd; if ( String ) STANDARD_ERROR_MESSAGE((WINAPPSTUFF, LOGONID_NONE, Error, ErrorResource, String)) else STANDARD_ERROR_MESSAGE((WINAPPSTUFF, LOGONID_NONE, Error, ErrorResource)) /* * Restore original WinUtilsAppWindow to global. */ WinUtilsAppWindow = hwndSave; } // end ReportSecurityFailure /******************************************************************************* * * SedCallback (private function) * * Callback function from ACL edit dialog DLL * * ENTRY: * (see sedapi.h) * EXIT: * (see sedapi.h) * ******************************************************************************/ DWORD WINAPI SedCallback( HWND hwndParent, HANDLE hInstance, ULONG CallBackContext, PSECURITY_DESCRIPTOR pUpdatedSecurityDescriptor, PSECURITY_DESCRIPTOR pSecDescNewObjects, BOOLEAN ApplyToSubContainers, BOOLEAN ApplyToSubObjects, LPDWORD StatusReturn ) { WINSTATIONNAME WSName; PSECURITY_CONTEXT pSecurityContext; DWORD Error; BOOL OK = TRUE; pSecurityContext = (PSECURITY_CONTEXT)CallBackContext; /* * Apply security to the WinStation. */ lstrcpy(WSName, pSecurityContext->pWSName); if ( (Error = SetWinStationSecurity( WSName, pUpdatedSecurityDescriptor)) != ERROR_SUCCESS ) { ReportSecurityFailure( hwndParent, IDP_ERROR_SET_SECURITY_WINSTATION, WSName, Error ); OK = FALSE; *StatusReturn = SED_STATUS_NOT_ALL_MODIFIED; } if ( OK == TRUE ) *StatusReturn = SED_STATUS_MODIFIED; return( OK ? 0 : 1 ); } // end SedCallback /******************************************************************************* * * LoadLibraryGetProcAddress (private function) * * Load the specified library and retrieve FARPROC pointer to specified * procedure's entry point. * * ENTRY: * hwnd (input) * window handle of owner for error message display * LibraryName (input) * name of library dll to load * ProcName (input) * name of library procedure to reference * phLibrary (output) * set to handle of loaded library on return * EXIT: * FARPROC pointer to library procedure's entry point. * ******************************************************************************/ FARPROC LoadLibraryGetProcAddress( HWND hwnd, LPTSTR LibraryName, LPCSTR ProcName, PHANDLE phLibrary ) { HANDLE hLibrary; FARPROC lpfn = NULL; hLibrary = LoadLibrary(LibraryName); if ( hLibrary ) { lpfn = GetProcAddress(hLibrary, ProcName); if(!lpfn) { ERROR_MESSAGE(( IDP_ERROR_COULDNOTFINDPROCEDURE, ProcName, LibraryName )) FreeLibrary(hLibrary); } } else ERROR_MESSAGE((IDP_ERROR_COULDNOTLOADLIBRARY, LibraryName)) *phLibrary = hLibrary; return(lpfn); } // end LoadLibraryGetProcAddress /******************************************************************************* * * AllocSplMem (private function) * * Allocate and zero-fill specified amount of memory. * * ENTRY: * cb (input) * number of bytes to allocate * EXIT: * LPVOID pointer to allocated memory; NULL if error. * ******************************************************************************/ LPVOID AllocSplMem( DWORD cb ) { return(LocalAlloc(LPTR, cb)); } // end AllocSplMem /******************************************************************************* * * FreeSplMem (private function) * * Free the specified memory block. * * ENTRY: * pMem (input) * memory to free * EXIT: * TRUE if sucess; FALSE if error. * ******************************************************************************/ BOOL FreeSplMem( LPVOID pMem ) { return( LocalFree((HLOCAL)pMem) == NULL ); } // end FreeSplMem /******************************************************************************* * * GetUnicodeString (private function) * * Load a resource string and allocate/save in memory block. * * ENTRY: * id (input) * resource id of string to get * EXIT: * pointer to allocated and loaded UNICODE string * ******************************************************************************/ LPWSTR GetUnicodeString(int id) { WCHAR ResString[256]; DWORD length = 0; LPWSTR pUnicode; DWORD cbUnicode; length = LoadStringW(NULL, id, ResString, 256); cbUnicode = (length * sizeof(WCHAR)) + sizeof(WCHAR); pUnicode = AllocSplMem(cbUnicode); if( pUnicode ) memcpy(pUnicode, ResString, cbUnicode); return(pUnicode); } // end GetUnicodeString /******************************************************************************* * * ValidateSecurityDescriptor (private function) * * Check the specified security descriptor for valid structure as well as * valid ACLs and SIDs. * * ENTRY: * pSecurityDescriptor (input) * Security descriptor to validate. * EXIT: * ERROR_SUCCESS if valid; error otherwise. * ******************************************************************************/ DWORD ValidateSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor) { DWORD Error = ERROR_SUCCESS; if ( !IsValidSecurityDescriptor(pSecurityDescriptor) ) { Error = GetLastError(); } else { BOOL bAclPresent, bDefaulted; PACL pACL; PSID pSID; for ( ; ; ) { if ( !GetSecurityDescriptorDacl( pSecurityDescriptor, &bAclPresent, &pACL, &bDefaulted ) ) { Error = GetLastError(); break; } if ( bAclPresent && pACL ) if ( !IsValidAcl(pACL) ) { Error = GetLastError(); break; } if ( !GetSecurityDescriptorSacl( pSecurityDescriptor, &bAclPresent, &pACL, &bDefaulted ) ) { Error = GetLastError(); break; } if ( bAclPresent && pACL ) if ( !IsValidAcl(pACL) ) { Error = GetLastError(); break; } if ( !GetSecurityDescriptorOwner( pSecurityDescriptor, &pSID, &bDefaulted ) ) { Error = GetLastError(); break; } if ( pSID ) if ( !IsValidSid(pSID) ) { Error = GetLastError(); break; } if ( !GetSecurityDescriptorGroup( pSecurityDescriptor, &pSID, &bDefaulted ) ) { Error = GetLastError(); break; } if ( pSID ) if ( !IsValidSid(pSID) ) { Error = GetLastError(); break; } break; } } return(Error); } // end ValidateSecurityDescriptor /******************************************************************************* * * SetWinStationSecurity (private function) * * Set the specified WinStation's registry and kernel object security. * * ENTRY: * pWSName (input) * Name of WinStation to set security for. * pSecurityDescriptor (input) * Security descriptor to set for winstation. * EXIT: * ERROR_SUCCESS if valid; error otherwise. * ******************************************************************************/ DWORD SetWinStationSecurity( PWINSTATIONNAME pWSName, PSECURITY_DESCRIPTOR pSecurityDescriptor ) { DWORD Error = ERROR_SUCCESS; Error = RegWinStationSetSecurity( SERVERNAME_CURRENT, pWSName, pSecurityDescriptor, GetSecurityDescriptorLength(pSecurityDescriptor) ); return(Error); } // SetWinStationSecurity