/**************************************************************************** FILE: actestp.c PURPOSE: FUNCTIONS: COMMENTS: ****************************************************************************/ #include #include #include // IAccessControl interface definition #include #include #include #include #include "oactest.h" // header file generated by MIDL compiler void DecrementLockCount(); void IncrementLockCount(); void ObjectCreated(); void ObjectDestroyed(); const CLSID CLSID_COAccessControl_DCOM = {0x52c0e9e1,0xc0c0,0x11cf,{0xae,0xec,0x00,0xaa,0x00,0x44,0xfb,0x89}}; extern "C" const CLSID CLSID_COAccessControlTest; extern ULONG g_ulFrequency; DWORD g_dwRegister; long g_fClassRegistered = FALSE; // IAccessControlTest implementation class class CAccessControlTest : public IAccessControlTest { private: IUnknown *m_pIUnknown; IPersistStream *m_pIPersistStream; IAccessControl *m_pIAccessControl; ULONG m_cRef; BOOL m_bInitialized; // destructor ~CAccessControlTest() { DecrementLockCount(); ObjectDestroyed(); } public: // contructor CAccessControlTest() { m_cRef = 0; m_bInitialized = FALSE; ObjectCreated(); IncrementLockCount(); } STDMETHODIMP_(HRESULT) QueryInterface ( REFIID iid, void **ppv ); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); STDMETHODIMP_(HRESULT) TestServer ( LPSTR pszTestString ); STDMETHODIMP_(HRESULT) GetClassID ( CLSID *pClassID, DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) InitNewACL ( DOUBLE*pdMillisec ); STDMETHODIMP_(HRESULT) LoadACL ( LPCSTR pszFilename, DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) SaveACL ( LPCSTR pszFilename, BOOL fClearDirty, ULONG *pulBytesWritten, DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) GetSizeMax ( ULONG *pcdSize, DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) IsDirty ( DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) GrantAccessRights ( ULONG cCount, E_ACCESS_REQUEST *pAccessRequestList, DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) DenyAccessRights ( ULONG cCount, E_ACCESS_REQUEST pAccessRequestList[], DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) SetAccessRights ( ULONG cCount, E_ACCESS_REQUEST pAccessRequestList[], DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) ReplaceAllAccessRights ( ULONG cCount, E_EXPLICIT_ACCESS pExplicitAccessList[], DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) RevokeExplicitAccessRights ( ULONG cCount, E_TRUSTEE pTrustee[], DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) IsAccessPermitted ( E_TRUSTEE *pTrustee, DWORD grfAccessPermissions, DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) GetEffectiveAccessRights ( E_TRUSTEE *pTrustee, DWORD *pdwRights, DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) GetExplicitAccessRights ( ULONG *pcCount, PE_EXPLICIT_ACCESS *ppExplicitAccessList, DOUBLE *pdMillisec ); STDMETHODIMP_(HRESULT) RevertAccessRights ( ); STDMETHODIMP_(HRESULT) CommitAccessRights ( DWORD grfCommitFlags ); }; // CAccessControlTest //+------------------------------------------------------------------------- // // Method: CAccessControlTest::AddRef, public // // Synopsis: Increment reference count // // See Also: IUnknown::AddRef // //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CAccessControlTest::AddRef() { InterlockedIncrement((long *) &m_cRef); return m_cRef; } //+------------------------------------------------------------------------- // // Method: CAccessControlTest::Release, public // // Synopsis: Decrement DLL reference count // // Notes: After the m_cRef is decremented, the object may be // deleted by another thread. In order to make this code safe // for multiple threads, we have to access the object state // before decrementing m_cRef. // // See Also: IUnknown::Release. // //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CAccessControlTest::Release() { unsigned long count; count = m_cRef - 1; if(InterlockedDecrement((long *) &m_cRef) == 0) { count = 0; if(m_bInitialized) { m_pIUnknown->Release(); m_pIPersistStream->Release(); m_pIAccessControl->Release(); } delete this; } return count; } //+------------------------------------------------------------------------- // // Method: CAccessControlTest::QueryInterface, public // // Synopsis: Query for an interface on the class factory. // // See Also: IUnknown:QueryInterface // //-------------------------------------------------------------------------- STDMETHODIMP_(HRESULT) CAccessControlTest::QueryInterface ( REFIID iid, void **ppv ) { HRESULT hr; if (!m_bInitialized) { hr = CoCreateInstance( CLSID_COAccessControl_DCOM , NULL , CLSCTX_INPROC_SERVER , IID_IUnknown , (void **)&m_pIUnknown); if(FAILED(hr)) { printf("Failed to create an instance of COAccessControl\n."); return hr; } hr = m_pIUnknown->QueryInterface(IID_IPersistStream, (void **)&m_pIPersistStream); if(FAILED(hr)) { printf("Failed to query for the IPersistStream Interface.\n"); return hr; } hr = m_pIUnknown->QueryInterface(IID_IAccessControl, (void **)&m_pIAccessControl); if(FAILED(hr)) { printf("Failed to query for the IAccessControl interface.\n"); return hr; } m_bInitialized = TRUE; } if ( IsEqualGUID( iid, IID_IUnknown ) ) { *ppv = (IUnknown *) this; ((IUnknown *)(*ppv))->AddRef(); hr = S_OK; } else if (IsEqualGUID( iid, IID_IAccessControlTest)) { *ppv = (IUnknown *)(IAccessControlTest *)this; ((IAccessControlTest *)(*ppv))->AddRef(); hr = S_OK; } else { *ppv = 0; hr = E_NOINTERFACE; } return hr; } STDMETHODIMP_(HRESULT) CAccessControlTest::TestServer ( LPSTR pszTestString ) { printf("The test string is: %s\n", pszTestString); return S_OK; } STDMETHODIMP_(HRESULT) CAccessControlTest::GetClassID ( CLSID *pClassID, DOUBLE *pdMillisec ) { HRESULT localhr; CLSID clsid; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIPersistStream->GetClassID(&clsid); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pClassID = clsid; *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::InitNewACL ( DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIPersistStream->Load(NULL); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::LoadACL ( LPCSTR pszFilename, DOUBLE *pdMillisec ) { HRESULT localhr; IStream *pIStream = NULL; HANDLE FileHandle; DWORD dwFileSize; void *pvBuffer; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; // Open the file specified by the client FileHandle = CreateFileA( pszFilename , GENERIC_READ , FILE_SHARE_READ | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL ); if( FileHandle == INVALID_HANDLE_VALUE ) { printf("Cannot open file %s.\n", pszFilename); *pdMillisec = 0; return HRESULT_FROM_WIN32(GetLastError()); } // Get the size of the file dwFileSize = GetFileSize(FileHandle, NULL); // Create a buffer to hold the data in the file pvBuffer = CoTaskMemAlloc(dwFileSize); DWORD dwBytesRead; // Read the data of the opened file into a buffer if(!ReadFile( FileHandle , pvBuffer , dwFileSize , &dwBytesRead , NULL )) { return HRESULT_FROM_WIN32(GetLastError()); } // Once we have read the file data into a buffer, we can // close the file handle CloseHandle( FileHandle); // Create a stream on the the buffer localhr = CreateStreamOnHGlobal(NULL, TRUE, &pIStream); if (FAILED(localhr)) { printf("Cannot create stream object.\n"); CoTaskMemFree(pvBuffer); *pdMillisec = 0; return localhr; } // Load the data in the buffer into the IStream object localhr = pIStream->Write(pvBuffer, dwFileSize, NULL); // Release the local buffer CoTaskMemFree(pvBuffer); if (FAILED(localhr)) { printf("Failed to load data into stream object.\n"); *pdMillisec = 0; return localhr; } // Rewind the stream pointer the starting position LARGE_INTEGER li; li.LowPart = 0; li.HighPart = 0; localhr = pIStream->Seek(li, STREAM_SEEK_SET, NULL); if (FAILED(localhr)) { printf("Failed to set the stream pointer to the starting position.\n"); *pdMillisec = 0; return localhr; } QueryPerformanceCounter(&liCount1); localhr = m_pIPersistStream->Load(pIStream); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; // Release the local stream pointer pIStream->Release(); return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::SaveACL ( LPCSTR pszFilename, BOOL fClearDirty, ULONG *pulNumOfBytesWritten, DOUBLE *pdMillisec ) { HRESULT localhr; IStream *pIStream = NULL; HANDLE FileHandle; DWORD dwFileSize; void *pvBuffer; STATSTG StreamInfo; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; // Create a stream on the the buffer localhr = CreateStreamOnHGlobal(NULL, TRUE, &pIStream); if (FAILED(localhr)) { printf("Cannot create stream object.\n"); *pdMillisec = 0; return localhr; } QueryPerformanceCounter(&liCount1); localhr = m_pIPersistStream->Save(pIStream, fClearDirty); QueryPerformanceCounter(&liCount2); if(FAILED(localhr)) { *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } // Get the number of bytes written to the stream localhr = pIStream->Stat(&StreamInfo, STATFLAG_NONAME); if (FAILED(localhr)) { printf("Unable to get information about the local stream.\n"); *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } dwFileSize = StreamInfo.cbSize.LowPart; LARGE_INTEGER liOffset; liOffset.QuadPart = Int32x32To64(dwFileSize, -1); pIStream->Seek(liOffset,STREAM_SEEK_CUR, NULL); // Allocate a buffer to store the data in the stream pvBuffer = CoTaskMemAlloc(dwFileSize); // Write the stream localhr = pIStream->Read(pvBuffer, dwFileSize, NULL); if(FAILED(localhr)) { printf("Unable to write data from stream to buffer.\n"); CoTaskMemFree(pvBuffer); *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } // Open the file specified by the client FileHandle = CreateFileA( pszFilename , GENERIC_WRITE | GENERIC_READ , FILE_SHARE_READ | FILE_SHARE_WRITE , NULL , CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL ); if( FileHandle == INVALID_HANDLE_VALUE ) { printf("Cannot open file %s.\n", pszFilename); CoTaskMemFree(pvBuffer); *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return HRESULT_FROM_WIN32(GetLastError()); } // Read the data of the opened file into a buffer if(!WriteFile( FileHandle , pvBuffer , dwFileSize , pulNumOfBytesWritten , NULL )) { DWORD dwLastError; dwLastError = GetLastError(); printf("Write failed with error code %x.", dwLastError); } // Flush the file buffers FlushFileBuffers(FileHandle); // Close the file handle CloseHandle(FileHandle); CoTaskMemFree(pvBuffer); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; *pulNumOfBytesWritten = dwFileSize; // Release the local stream pointer pIStream->Release(); return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::GetSizeMax ( ULONG *pcdSize, DOUBLE *pdMillisec ) { ULARGE_INTEGER uliSize; HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIPersistStream->GetSizeMax(&uliSize); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pcdSize = uliSize.LowPart; *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::IsDirty ( DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIPersistStream->IsDirty(); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::GrantAccessRights ( ULONG cCount, E_ACCESS_REQUEST pAccessRequestList[], DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIAccessControl->GrantAccessRights(cCount, (ACCESS_REQUEST_W *)pAccessRequestList); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::SetAccessRights ( ULONG cCount, E_ACCESS_REQUEST pAccessRequestList[], DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIAccessControl->SetAccessRights(cCount, (ACCESS_REQUEST_W *)pAccessRequestList); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::DenyAccessRights ( ULONG cCount, E_ACCESS_REQUEST pAccessRequestList[], DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIAccessControl->DenyAccessRights(cCount, (ACCESS_REQUEST_W *)pAccessRequestList); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::ReplaceAllAccessRights ( ULONG cCount, E_EXPLICIT_ACCESS pExplicitAccessList[], DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIAccessControl->ReplaceAllAccessRights(cCount, (EXPLICIT_ACCESS_W *)pExplicitAccessList); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::RevokeExplicitAccessRights ( ULONG cCount, E_TRUSTEE pTrustee[], DOUBLE *pdMillisec ) { char *pszClientName; RPC_STATUS status; HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIAccessControl->RevokeExplicitAccessRights(cCount, (TRUSTEE_W *)pTrustee); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::IsAccessPermitted ( E_TRUSTEE *pTrustee, DWORD grfAccessPermissions, DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIAccessControl->IsAccessPermitted((TRUSTEE_W *)pTrustee, grfAccessPermissions); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::GetEffectiveAccessRights ( E_TRUSTEE *pTrustee, DWORD *pdwRights, DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIAccessControl->GetEffectiveAccessRights((TRUSTEE_W *)pTrustee, pdwRights); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::GetExplicitAccessRights ( ULONG *pcCount, PE_EXPLICIT_ACCESS *ppExplicitAccessList, DOUBLE *pdMillisec ) { HRESULT localhr; LARGE_INTEGER liCount1; LARGE_INTEGER liCount2; QueryPerformanceCounter(&liCount1); localhr = m_pIAccessControl->GetExplicitAccessRights(pcCount, (PEXPLICIT_ACCESS_W *)ppExplicitAccessList); QueryPerformanceCounter(&liCount2); // Assign calues to the out parameters *pdMillisec = ((DOUBLE)(liCount2.LowPart) - (DOUBLE)(liCount1.LowPart)) / (DOUBLE)(g_ulFrequency) * 1000.0; return localhr; } STDMETHODIMP_(HRESULT) CAccessControlTest::RevertAccessRights ( ) { return m_pIAccessControl->RevertAccessRights(); } STDMETHODIMP_(HRESULT) CAccessControlTest::CommitAccessRights ( DWORD grfCommitFlags ) { return m_pIAccessControl->CommitAccessRights(grfCommitFlags); } class CACTestClassFactory : public IClassFactory { private: unsigned long m_cRef; //destructor ~CACTestClassFactory() { ObjectDestroyed(); } public: //constructor CACTestClassFactory() { m_cRef = 0; ObjectCreated(); } HRESULT STDMETHODCALLTYPE QueryInterface( REFIID iid, void **ppv); ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release(); HRESULT STDMETHODCALLTYPE CreateInstance( IUnknown *punkOuter, REFIID riid, void **ppv); HRESULT STDMETHODCALLTYPE LockServer( BOOL fLock ); }; //+------------------------------------------------------------------------- // // Method: CACTestClassFactory::AddRef, public // // Synopsis: Increment DLL reference counts // // See Also: IUnknown::AddRef // //-------------------------------------------------------------------------- ULONG STDMETHODCALLTYPE CACTestClassFactory::AddRef() { InterlockedIncrement((long *) &m_cRef); return m_cRef; } //+------------------------------------------------------------------------- // // Method: CACTestClassFactory::CreateInstance, public // // Synopsis: Create an instance of CAccessControlTest. // // See Also: IClassFactory::CreateInstance // //-------------------------------------------------------------------------- HRESULT STDMETHODCALLTYPE CACTestClassFactory::CreateInstance ( IUnknown *punkOuter, REFIID riid, void **ppv ) { HRESULT hr; CAccessControlTest *pACTest; if(punkOuter != 0) { //The CAccessControlTest class doesn't support aggregation. return CLASS_E_NOAGGREGATION; } pACTest = new CAccessControlTest(); if(pACTest != 0) { hr = pACTest->QueryInterface(riid, ppv); } else { hr = E_OUTOFMEMORY; *ppv = 0; } return hr; } //+------------------------------------------------------------------------- // // Method: CACTestClassFactory::LockServer, public // // Synopsis: Lock the server in memory (by adding an extra reference) // // Notes: The class factory will be revoked when the lock count // is decremented to zero. LockServer(TRUE) will increment the // lock count and ensure that the class factory will // not be revoked. // // See Also: IClassFactory::LockServer // //-------------------------------------------------------------------------- HRESULT STDMETHODCALLTYPE CACTestClassFactory::LockServer( BOOL fLock ) { if (fLock == TRUE) IncrementLockCount(); else DecrementLockCount(); return S_OK; } //+------------------------------------------------------------------------- // // Method: CACTestClassFactory::QueryInterface, public // // Synopsis: Query for an interface on the class factory. // // See Also: IUnknown::QueryInterface // //-------------------------------------------------------------------------- HRESULT STDMETHODCALLTYPE CACTestClassFactory::QueryInterface ( REFIID iid, void **ppv ) { HRESULT hr; if ( IsEqualGUID( iid, IID_IUnknown) || IsEqualGUID( iid, IID_IClassFactory ) ) { *ppv = this; ((IUnknown *)(*ppv))->AddRef(); hr = S_OK; } else { *ppv = 0; hr = E_NOINTERFACE; } return hr; } //+------------------------------------------------------------------------- // // Method: CACTestClassFactory::Release, public // // Synopsis: Decrement DLL reference count // // See Also: IUnknown::Release // //-------------------------------------------------------------------------- ULONG STDMETHODCALLTYPE CACTestClassFactory::Release() { unsigned long count; count = m_cRef - 1; if(InterlockedDecrement((long *) &m_cRef) == 0) { count = 0; delete this; } return count; } //+------------------------------------------------------------------------- // // Function: RegisterClassFactory. // // Synopsis: Register the class factory if it is not currently registered. // //-------------------------------------------------------------------------- HRESULT RegisterClassFactory() { HRESULT hr; CACTestClassFactory *pClassFactory; if(InterlockedExchange(&g_fClassRegistered, TRUE) == FALSE) { pClassFactory = new CACTestClassFactory; if(pClassFactory != 0) { hr = CoRegisterClassObject(CLSID_COAccessControlTest, (IUnknown *) pClassFactory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &g_dwRegister); } else { hr = E_OUTOFMEMORY; } } else { hr = S_OK; } return hr; } //+------------------------------------------------------------------------- // // Function: RevokeClassFactory. // // Synopsis: Revoke the registered class factories if they have not // already been revoked. // //-------------------------------------------------------------------------- HRESULT RevokeClassFactory() { HRESULT hr; if(InterlockedExchange(&g_fClassRegistered, FALSE) == TRUE) { hr = CoRevokeClassObject(g_dwRegister); } else { hr = S_OK; } return hr; }