594 lines
14 KiB
C++
594 lines
14 KiB
C++
//+------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1997
|
|
//
|
|
// File: csmain.cxx
|
|
//
|
|
// Contents: Main cxx for Directory Class Access Implementation
|
|
// Local Server.
|
|
//
|
|
// Author: DebiM
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "cstore.hxx"
|
|
|
|
|
|
//
|
|
// Link list pointer for Class Containers Seen
|
|
//
|
|
CLASSCONTAINER *gpContainerHead = NULL;
|
|
|
|
//
|
|
// Link list pointer for User Profiles Seen
|
|
//
|
|
USERPROFILE *gpUserHead = NULL;
|
|
|
|
//
|
|
// Class Factory Objects
|
|
//
|
|
long ObjectCount = 0;
|
|
|
|
CAppContainerCF * pCF = NULL;
|
|
CClassAccessCF * pCSAccessCF = NULL;
|
|
extern CClassContainerCF *g_pCF;
|
|
|
|
//IClassAccess * gpClassAccess = NULL;
|
|
|
|
//
|
|
// Critical Section for Sid List
|
|
//
|
|
CRITICAL_SECTION ClassStoreBindList;
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Following are used for Supporting Test Scenarios thru FlushSidCache.
|
|
WCHAR pwszDebugPath [_MAX_PATH];
|
|
BOOL fDebugPath = FALSE;
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
//
|
|
// ResetClassStoreState
|
|
// --------------------
|
|
//
|
|
// Synopsis: Calling this will close all Class Containers
|
|
// in use and also cleanup state information about all user sids
|
|
// that have initiated Class Store requests.
|
|
// This routine is called at during shut down of
|
|
// Class Store Server.
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
|
|
void ResetClassStoreState()
|
|
//
|
|
// This routine is called at during shut down of Class Store Server
|
|
//
|
|
{
|
|
//
|
|
// Check if there are any outstanding open Class Stores
|
|
//
|
|
|
|
CLASSCONTAINER *pCS = gpContainerHead, *pCSTemp;
|
|
|
|
while (pCS != NULL)
|
|
{
|
|
if (pCS->gpClassStore)
|
|
{
|
|
(pCS->gpClassStore)->Release();
|
|
pCS->gpClassStore = NULL;
|
|
CSDbgPrint(("Found open container and closed.\n"));
|
|
}
|
|
|
|
if (pCS->pszClassStorePath)
|
|
{
|
|
CoTaskMemFree (pCS->pszClassStorePath);
|
|
pCS->pszClassStorePath = NULL;
|
|
}
|
|
pCSTemp = pCS->pNextClassStore;
|
|
CoTaskMemFree (pCS);
|
|
pCS = pCSTemp;
|
|
}
|
|
|
|
gpContainerHead = NULL;
|
|
|
|
|
|
USERPROFILE *pUser = gpUserHead, *pUserTemp;
|
|
while (pUser != NULL)
|
|
{
|
|
if (pUser->pCachedSid)
|
|
CoTaskMemFree (pUser->pCachedSid);
|
|
|
|
if (pUser->pUserStoreList)
|
|
CoTaskMemFree (pUser->pUserStoreList);
|
|
|
|
pUser->cUserStoreCount = 0;
|
|
|
|
pUserTemp = pUser->pNextUser;
|
|
CoTaskMemFree (pUser);
|
|
pUser = pUserTemp;
|
|
}
|
|
|
|
gpUserHead = NULL;
|
|
|
|
CSDbgPrint(("ResetClassStoreState completed.\n"));
|
|
}
|
|
|
|
//
|
|
// ResetUserState
|
|
// --------------
|
|
//
|
|
// Synopsis: Calling this will flush all state information
|
|
// about all user sids that have initiated
|
|
// Class Store requests.
|
|
//
|
|
// It is called by the special test entry point
|
|
// FlushSidCache.
|
|
//
|
|
// Arguments: LPOLESTR pwszNewPath as the new Class Store path for All
|
|
//
|
|
// Returns: None
|
|
//
|
|
|
|
|
|
void ResetUserState(LPOLESTR pwszNewPath)
|
|
//
|
|
{
|
|
USERPROFILE *pUser = gpUserHead, *pUserTemp;
|
|
while (pUser != NULL)
|
|
{
|
|
if (pUser->pCachedSid)
|
|
CoTaskMemFree (pUser->pCachedSid);
|
|
|
|
pUser->cUserStoreCount = 0;
|
|
|
|
pUserTemp = pUser->pNextUser;
|
|
CoTaskMemFree (pUser);
|
|
pUser = pUserTemp;
|
|
}
|
|
|
|
gpUserHead = NULL;
|
|
wcscpy (&pwszDebugPath[0], pwszNewPath);
|
|
fDebugPath = TRUE;
|
|
|
|
CSDbgPrint(("ResetUserState completed.\n"));
|
|
}
|
|
|
|
//
|
|
// Uninitialize
|
|
// -------------
|
|
//
|
|
// Synopsis: Class Store Server Uninitialization.
|
|
// Disconnects from all Class Containers in use.
|
|
// Flushes out all State information using ResetClassStoreState.
|
|
// Unregisters Server registrations etc..
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
|
|
void Uninitialize()
|
|
{
|
|
//
|
|
// Cleanup all open containers
|
|
//
|
|
|
|
//ResetClassStoreState();
|
|
//
|
|
// release the Class Factory objects
|
|
//
|
|
if (pCF)
|
|
pCF->Release();
|
|
if (pCSAccessCF)
|
|
pCSAccessCF->Release();
|
|
|
|
if (g_pCF)
|
|
g_pCF->Release();
|
|
//
|
|
// get rid of the critical section
|
|
//
|
|
|
|
DeleteCriticalSection(&ClassStoreBindList);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// FlushSidCache
|
|
// -------------
|
|
//
|
|
// Synopsis: Supported for Testing Only. Not exposed thru any header.
|
|
// Calling this empties out Class Store Cache.
|
|
//
|
|
// Arguments: pwszNewPath
|
|
//
|
|
// Returns: S_OK
|
|
//
|
|
|
|
HRESULT FlushSidCache (LPOLESTR pwszNewPath)
|
|
{
|
|
|
|
EnterCriticalSection (&ClassStoreBindList);
|
|
|
|
ResetUserState(pwszNewPath);
|
|
|
|
LeaveCriticalSection (&ClassStoreBindList);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: InitializeClassStore
|
|
//
|
|
// History: 7-25-96 DebiM Created
|
|
//
|
|
// This entry point is called at DLL attach
|
|
//----------------------------------------------------------------------------
|
|
BOOL InitializeClassStore(BOOL fInit)
|
|
{
|
|
HRESULT hr;
|
|
BOOL bStatus;
|
|
|
|
ObjectCount = 1;
|
|
/*
|
|
ACL * pAcl;
|
|
DWORD AclSize;
|
|
SECURITY_DESCRIPTOR * pSD;
|
|
|
|
SID LocalSystemSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID };
|
|
SID InteractiveSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, SECURITY_INTERACTIVE_RID };
|
|
|
|
|
|
// Started manually. Don't go away.
|
|
AclSize = sizeof(ACL) + 2 * sizeof(ACCESS_ALLOWED_ACE) + 2 * sizeof(SID);
|
|
|
|
pSD = (SECURITY_DESCRIPTOR *)
|
|
PrivMemAlloc( sizeof(SECURITY_DESCRIPTOR) + 2 * sizeof(SID) + AclSize );
|
|
|
|
if ( ! pSD )
|
|
return FALSE;
|
|
|
|
bStatus = TRUE;
|
|
pAcl = (ACL *) ( ((BYTE *)&pSD[1]) + 2 * sizeof(SID) );
|
|
|
|
if ( ! InitializeAcl( pAcl, AclSize, ACL_REVISION2 ) ||
|
|
! AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE, &LocalSystemSid ) ||
|
|
! AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE, &InteractiveSid ) )
|
|
bStatus = FALSE;
|
|
|
|
if ( ! InitializeSecurityDescriptor( pSD, SECURITY_DESCRIPTOR_REVISION ) ||
|
|
! SetSecurityDescriptorDacl( pSD, TRUE, pAcl, FALSE ) ||
|
|
! SetSecurityDescriptorGroup( pSD, &LocalSystemSid, FALSE ) ||
|
|
! SetSecurityDescriptorOwner( pSD, &LocalSystemSid, FALSE ) )
|
|
bStatus = FALSE;
|
|
|
|
if ( bStatus )
|
|
{
|
|
hr = CoInitializeSecurity(
|
|
pSD,
|
|
-1,
|
|
NULL,
|
|
NULL,
|
|
RPC_C_AUTHN_LEVEL_CONNECT,
|
|
RPC_C_IMP_LEVEL_IDENTIFY,
|
|
NULL,
|
|
EOAC_NONE,
|
|
NULL );
|
|
}
|
|
|
|
PrivMemFree( pSD );
|
|
|
|
if ( ! bStatus || (hr != S_OK) )
|
|
{
|
|
CSDbgPrint(("Class Store: Couldn't initialize security\n"));
|
|
}
|
|
*/
|
|
|
|
|
|
/*
|
|
if (fInit)
|
|
{
|
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
if (hr)
|
|
CSDbgPrint(("RPCSS : CoInitialize returned 0x%x.\n", hr));
|
|
}
|
|
*/
|
|
|
|
pCF = new CAppContainerCF();
|
|
pCSAccessCF = new CClassAccessCF();
|
|
|
|
NTSTATUS status = RtlInitializeCriticalSection(&ClassStoreBindList);
|
|
|
|
/* hr = pCSAccessCF->CreateInstance( NULL, IID_IClassAccess, (void **) &gpClassAccess );
|
|
|
|
if ( hr != S_OK )
|
|
{
|
|
CSDbgPrint(("RPCSS : Counldn't create ClassAccess 0x%x\n", hr));
|
|
return FALSE;
|
|
}
|
|
*/
|
|
g_pCF = new CClassContainerCF;
|
|
|
|
if (!pCF || !pCSAccessCF || !g_pCF || !NT_SUCCESS(status))
|
|
{
|
|
ASSERT(FALSE);
|
|
goto fail;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
fail:
|
|
if (pCF)
|
|
delete pCF;
|
|
if (pCSAccessCF)
|
|
delete pCSAccessCF;
|
|
if (g_pCF)
|
|
{
|
|
delete g_pCF;
|
|
g_pCF = NULL;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
/*
|
|
|
|
// Globals
|
|
HINSTANCE g_hInst = NULL;
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Function: DllGetClassObject
|
|
//
|
|
// Synopsis: Standard DLL entrypoint for locating class factories
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
STDAPI
|
|
DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID FAR* ppv)
|
|
{
|
|
HRESULT hr;
|
|
size_t i;
|
|
|
|
if (IsEqualCLSID(clsid, CLSID_ClassAccess))
|
|
{
|
|
return pCSAccessCF->QueryInterface(iid, ppv);
|
|
}
|
|
|
|
*ppv = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Function: DllCanUnloadNow
|
|
//
|
|
// Synopsis: Standard DLL entrypoint to determine if DLL can be unloaded
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDAPI
|
|
DllCanUnloadNow(void)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = S_FALSE;
|
|
|
|
//
|
|
// BugBug
|
|
//
|
|
if (ulObjectCount > 0)
|
|
hr = S_FALSE;
|
|
else
|
|
hr = S_OK;
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Function: LibMain
|
|
//
|
|
// Synopsis: Standard DLL initialization entrypoint
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _CRTAPI1
|
|
LibMain(HINSTANCE hInst, ULONG ulReason, LPVOID pvReserved)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbSize = _MAX_PATH;
|
|
WCHAR wszUserName [_MAX_PATH];
|
|
|
|
switch (ulReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
DisableThreadLibraryCalls(hInst);
|
|
g_hInst = hInst;
|
|
InitializeClassStore();
|
|
break;
|
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
Uninitialize();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DllMain
|
|
//
|
|
// Synopsis: entry point for NT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
|
|
{
|
|
return LibMain((HINSTANCE)hDll, dwReason, lpReserved);
|
|
}
|
|
*/
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CsGetClassAccess
|
|
//
|
|
// Synopsis: Returns an instantiated interface to the Class Store
|
|
// Co-ordinator object in Rpcss.
|
|
//
|
|
// Arguments: [ppIClassAccess] - where to put class access interface pointer
|
|
//
|
|
// Returns: S_OK - Got a Class Access Successfully
|
|
// E_FAIL
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
STDAPI CsGetClassAccess(
|
|
IClassAccess ** ppIClassAccess)
|
|
{
|
|
HRESULT hr;
|
|
*ppIClassAccess = NULL;
|
|
|
|
hr = pCSAccessCF->CreateInstance( NULL,
|
|
IID_IClassAccess,
|
|
(void **)ppIClassAccess);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// CsEnumApps (DebiM 11/7/97)
|
|
//
|
|
// Returns an enumerator for packages in the Class Store (s).
|
|
// The enumerator works across all class stores in the calling users profile.
|
|
//
|
|
//
|
|
// This is used by:
|
|
// - Add/Remove programs to select Corporate Apps
|
|
// - winlogon to obtain the list of assigned apps
|
|
//
|
|
// Arguments:
|
|
// [in]
|
|
// pszPackageName : Optional Wildcard string for PackageName
|
|
// pLastUsn : Optional Time Stamp for new packages
|
|
// pCategory : Optional CategoryId
|
|
// dwAppFlags : Per APPINFO_xxx in objbase.h
|
|
// [out]
|
|
// ppIEnumPackage : Returned Interface Pointer
|
|
//
|
|
// Returns :
|
|
// S_OK or E_NO_CLASSSTORE
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI
|
|
CsEnumApps(
|
|
LPOLESTR pszPackageName, // Wildcard string for PackageName
|
|
GUID *pCategory, // CategoryId
|
|
ULONGLONG *pLastUsn, // Time Stamp for new packages
|
|
DWORD dwAppFlags, // Per APPINFO_xxx in objbase.h
|
|
IEnumPackage **ppIEnumPackage // Returned Interface Pointer
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IClassAccess * pIClassAccess = NULL;
|
|
|
|
*ppIEnumPackage = NULL;
|
|
|
|
//
|
|
// Get an IClassAccess
|
|
//
|
|
hr = CsGetClassAccess(&pIClassAccess);
|
|
if (!SUCCEEDED(hr))
|
|
return hr;
|
|
|
|
//
|
|
// Get the enumerator
|
|
//
|
|
hr = pIClassAccess->EnumPackages (
|
|
pszPackageName,
|
|
pCategory,
|
|
pLastUsn,
|
|
dwAppFlags,
|
|
ppIEnumPackage
|
|
);
|
|
|
|
pIClassAccess->Release();
|
|
return hr;
|
|
}
|
|
|
|
void
|
|
GetDefaultPlatform(CSPLATFORM *pPlatform)
|
|
{
|
|
OSVERSIONINFO VersionInformation;
|
|
|
|
VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx(&VersionInformation);
|
|
|
|
pPlatform->dwPlatformId = VersionInformation.dwPlatformId;
|
|
pPlatform->dwVersionHi = VersionInformation.dwMajorVersion;
|
|
pPlatform->dwVersionLo = VersionInformation.dwMinorVersion;
|
|
pPlatform->dwProcessorArch = DEFAULT_ARCHITECTURE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// CsGetAppInfo
|
|
//
|
|
// Looks up the given class specification in the DS. If an application for
|
|
// this class specification is found, then the application details are returned.
|
|
//
|
|
// Arguments :
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI
|
|
CsGetAppInfo(
|
|
uCLSSPEC * pClassSpec, // Class Spec (GUID/Ext/MIME)
|
|
QUERYCONTEXT * pQueryContext,
|
|
INSTALLINFO * pInstallInfo
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
QUERYCONTEXT QueryContext;
|
|
IClassAccess * pIClassAccess = NULL;
|
|
|
|
if ( pQueryContext )
|
|
{
|
|
QueryContext = *pQueryContext;
|
|
}
|
|
else
|
|
{
|
|
QueryContext.dwContext = CLSCTX_ALL;
|
|
GetDefaultPlatform( &QueryContext.Platform );
|
|
QueryContext.Locale = GetThreadLocale();
|
|
QueryContext.dwVersionHi = (DWORD) -1;
|
|
QueryContext.dwVersionLo = (DWORD) -1;
|
|
}
|
|
|
|
//
|
|
// Get an IClassAccess
|
|
//
|
|
hr = CsGetClassAccess(&pIClassAccess);
|
|
if (!SUCCEEDED(hr))
|
|
return hr;
|
|
hr = pIClassAccess->GetAppInfo(pClassSpec, &QueryContext, pInstallInfo );
|
|
pIClassAccess->Release();
|
|
return hr;
|
|
}
|
|
|