//+--------------------------------------------------------------------------- // // Microsoft Windows NT Security // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: ldapstor.cpp // // Contents: Ldap Store Provider implementation // // History: 17-Oct-97 kirtd Created // 01-Jan-02 philh Changed to internally use UNICODE Urls // //---------------------------------------------------------------------------- #include //+--------------------------------------------------------------------------- // // Member: CLdapStore::CLdapStore, public // // Synopsis: Constructor // //---------------------------------------------------------------------------- CLdapStore::CLdapStore ( OUT BOOL& rfResult ) : m_pBinding( NULL ), m_hCacheStore( NULL ), m_dwOpenFlags( 0 ), m_fDirty( FALSE ) { rfResult = TRUE; memset( &m_UrlComponents, 0, sizeof( m_UrlComponents ) ); if (! Pki_InitializeCriticalSection( &m_StoreLock )) { rfResult = FALSE; } } //+--------------------------------------------------------------------------- // // Member: CLdapStore::~CLdapStore, public // // Synopsis: Destructor // //---------------------------------------------------------------------------- CLdapStore::~CLdapStore () { DeleteCriticalSection( &m_StoreLock ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::OpenStore, public // // Synopsis: open store // //---------------------------------------------------------------------------- BOOL CLdapStore::OpenStore ( LPCSTR pszStoreProv, DWORD dwMsgAndCertEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void* pvPara, HCERTSTORE hCertStore, PCERT_STORE_PROV_INFO pStoreProvInfo ) { BOOL fResult = TRUE; DWORD dwRetrievalFlags; DWORD dwBindFlags; assert( m_pBinding == NULL ); assert( m_hCacheStore == NULL ); assert( m_dwOpenFlags == 0 ); assert( m_fDirty == FALSE ); m_dwOpenFlags = dwFlags; m_hCacheStore = hCertStore; if ( pvPara == NULL ) { SetLastError( (DWORD) E_INVALIDARG ); return( FALSE ); } if ( (dwFlags & CERT_STORE_UNSAFE_PHYSICAL_FLAG) && (dwFlags & CERT_LDAP_STORE_OPENED_FLAG) ) { SetLastError( (DWORD) E_INVALIDARG ); return( FALSE ); } __try { LPCWSTR pwszUrl; if (dwFlags & CERT_LDAP_STORE_OPENED_FLAG) { PCERT_LDAP_STORE_OPENED_PARA pOpenedPara; // Will set this before returning. Don't want to do an // unbind if the open fails. m_dwOpenFlags &= ~CERT_LDAP_STORE_UNBIND_FLAG; pOpenedPara = (PCERT_LDAP_STORE_OPENED_PARA) pvPara; m_pBinding = (LDAP *) pOpenedPara->pvLdapSessionHandle; pwszUrl = pOpenedPara->pwszLdapUrl; } else { pwszUrl = (LPCWSTR) pvPara; m_dwOpenFlags |= CERT_LDAP_STORE_UNBIND_FLAG; } if ( LdapCrackUrl( pwszUrl, &m_UrlComponents ) == FALSE ) { return( FALSE ); } } __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError( GetExceptionCode() ); return( FALSE ); } dwRetrievalFlags = 0; dwBindFlags = LDAP_BIND_AUTH_SSPI_ENABLE_FLAG | LDAP_BIND_AUTH_SIMPLE_ENABLE_FLAG; if (dwFlags & CERT_LDAP_STORE_SIGN_FLAG) { dwRetrievalFlags |= CRYPT_LDAP_SIGN_RETRIEVAL; dwBindFlags &= ~LDAP_BIND_AUTH_SIMPLE_ENABLE_FLAG; } if (dwFlags & CERT_LDAP_STORE_AREC_EXCLUSIVE_FLAG) { dwRetrievalFlags |= CRYPT_LDAP_AREC_EXCLUSIVE_RETRIEVAL; dwBindFlags &= ~LDAP_BIND_AUTH_SIMPLE_ENABLE_FLAG; } if (!( dwFlags & CERT_LDAP_STORE_OPENED_FLAG ) ) { fResult = LdapGetBindings( m_UrlComponents.pwszHost, m_UrlComponents.Port, dwRetrievalFlags, dwBindFlags, LDAP_STORE_TIMEOUT, NULL, &m_pBinding ); } if ( ( fResult == TRUE ) && !( dwFlags & CERT_STORE_READONLY_FLAG ) ) { fResult = LdapHasWriteAccess( m_pBinding, &m_UrlComponents, LDAP_STORE_TIMEOUT ); if ( fResult == FALSE ) { SetLastError( (DWORD) ERROR_ACCESS_DENIED ); } } if ( fResult == TRUE ) { if ( m_dwOpenFlags & CERT_STORE_DELETE_FLAG ) { m_fDirty = TRUE; fResult = InternalCommit( 0 ); if ( fResult == TRUE ) { pStoreProvInfo->dwStoreProvFlags = CERT_STORE_PROV_DELETED_FLAG; if (dwFlags & CERT_LDAP_STORE_UNBIND_FLAG) { m_dwOpenFlags |= CERT_LDAP_STORE_UNBIND_FLAG; } } CloseStore( 0 ); return( fResult ); } fResult = FillCacheStore( FALSE ); // Note, LDAP_REFERRAL gets mapped to ERROR_MORE_DATA. Sometimes // referral errors aren't detected until doing the ldap search. if ( !fResult && !(dwFlags & CERT_LDAP_STORE_OPENED_FLAG) && ((LDAP_BIND_AUTH_SSPI_ENABLE_FLAG | LDAP_BIND_AUTH_SIMPLE_ENABLE_FLAG) == dwBindFlags) && (ERROR_MORE_DATA == GetLastError()) ) { // Try again doing simple bind. LdapFreeBindings( m_pBinding ); m_pBinding = NULL; fResult = LdapGetBindings( m_UrlComponents.pwszHost, m_UrlComponents.Port, dwRetrievalFlags, LDAP_BIND_AUTH_SIMPLE_ENABLE_FLAG, LDAP_STORE_TIMEOUT, NULL, &m_pBinding ); if ( fResult ) { fResult = FillCacheStore( FALSE ); } } } if ( fResult == TRUE ) { pStoreProvInfo->cStoreProvFunc = LDAP_PROV_FUNC_COUNT; pStoreProvInfo->rgpvStoreProvFunc = (void **)rgpvLdapProvFunc; pStoreProvInfo->hStoreProv = (HCERTSTOREPROV)this; if (dwFlags & CERT_LDAP_STORE_UNBIND_FLAG) { m_dwOpenFlags |= CERT_LDAP_STORE_UNBIND_FLAG; } } else { CloseStore( 0 ); } return( fResult ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::CloseStore, public // // Synopsis: close the store // //---------------------------------------------------------------------------- VOID CLdapStore::CloseStore (DWORD dwFlags) { DWORD LastError = GetLastError(); EnterCriticalSection( &m_StoreLock ); InternalCommit( 0 ); LdapFreeUrlComponents( &m_UrlComponents ); memset( &m_UrlComponents, 0, sizeof( m_UrlComponents ) ); if (m_dwOpenFlags & CERT_LDAP_STORE_UNBIND_FLAG) { LdapFreeBindings( m_pBinding ); } m_pBinding = NULL; LeaveCriticalSection( &m_StoreLock ); SetLastError( LastError ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::DeleteCert, public // // Synopsis: delete cert from store // //---------------------------------------------------------------------------- BOOL CLdapStore::DeleteCert (PCCERT_CONTEXT pCertContext, DWORD dwFlags) { return( WriteCheckSetDirtyWithLock( CONTEXT_OID_CERTIFICATE, (LPVOID)pCertContext, 0 ) ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::DeleteCrl, public // // Synopsis: delete CRL from store // //---------------------------------------------------------------------------- BOOL CLdapStore::DeleteCrl (PCCRL_CONTEXT pCrlContext, DWORD dwFlags) { return( WriteCheckSetDirtyWithLock( CONTEXT_OID_CRL, (LPVOID)pCrlContext, 0 ) ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::DeleteCtl, public // // Synopsis: delete CTL from store // //---------------------------------------------------------------------------- BOOL CLdapStore::DeleteCtl (PCCTL_CONTEXT pCtlContext, DWORD dwFlags) { return( WriteCheckSetDirtyWithLock( CONTEXT_OID_CTL, (LPVOID)pCtlContext, 0 ) ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::SetCertProperty, public // // Synopsis: set a property on the cert // //---------------------------------------------------------------------------- BOOL CLdapStore::SetCertProperty ( PCCERT_CONTEXT pCertContext, DWORD dwPropId, DWORD dwFlags, const void* pvPara ) { // NOTENOTE: Properties are NOT persisted return( TRUE ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::SetCrlProperty, public // // Synopsis: set a property on the CRL // //---------------------------------------------------------------------------- BOOL CLdapStore::SetCrlProperty ( PCCRL_CONTEXT pCrlContext, DWORD dwPropId, DWORD dwFlags, const void* pvPara ) { // NOTENOTE: Properties are NOT persisted return( TRUE ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::SetCtlProperty, public // // Synopsis: set a property on the CTL // //---------------------------------------------------------------------------- BOOL CLdapStore::SetCtlProperty ( PCCTL_CONTEXT pCrlContext, DWORD dwPropId, DWORD dwFlags, const void* pvPara ) { // NOTENOTE: Properties are NOT persisted return( TRUE ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::WriteCert, public // // Synopsis: write cert to store // //---------------------------------------------------------------------------- BOOL CLdapStore::WriteCert (PCCERT_CONTEXT pCertContext, DWORD dwFlags) { return( WriteCheckSetDirtyWithLock( CONTEXT_OID_CERTIFICATE, (LPVOID)pCertContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::WriteCrl, public // // Synopsis: write CRL to store // //---------------------------------------------------------------------------- BOOL CLdapStore::WriteCrl (PCCRL_CONTEXT pCrlContext, DWORD dwFlags) { return( WriteCheckSetDirtyWithLock( CONTEXT_OID_CRL, (LPVOID)pCrlContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::WriteCtl, public // // Synopsis: write CTL to store // //---------------------------------------------------------------------------- BOOL CLdapStore::WriteCtl (PCCTL_CONTEXT pCtlContext, DWORD dwFlags) { return( WriteCheckSetDirtyWithLock( CONTEXT_OID_CTL, (LPVOID)pCtlContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::StoreControl, public // // Synopsis: store control dispatch // //---------------------------------------------------------------------------- BOOL CLdapStore::StoreControl (DWORD dwFlags, DWORD dwCtrlType, LPVOID pvCtrlPara) { switch ( dwCtrlType ) { case CERT_STORE_CTRL_COMMIT: return( Commit( dwFlags ) ); case CERT_STORE_CTRL_RESYNC: return( Resync() ); } SetLastError( (DWORD) ERROR_CALL_NOT_IMPLEMENTED ); return( FALSE ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::Commit, public // // Synopsis: commit the store // //---------------------------------------------------------------------------- BOOL CLdapStore::Commit (DWORD dwFlags) { BOOL fResult; EnterCriticalSection( &m_StoreLock ); fResult = InternalCommit( dwFlags ); LeaveCriticalSection( &m_StoreLock ); return( fResult ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::Resync, public // // Synopsis: resync the store // //---------------------------------------------------------------------------- BOOL CLdapStore::Resync () { BOOL fResult; EnterCriticalSection( &m_StoreLock ); fResult = FillCacheStore( TRUE ); LeaveCriticalSection( &m_StoreLock ); return( fResult ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::FillCacheStore, private // // Synopsis: fill the cache store // //---------------------------------------------------------------------------- BOOL CLdapStore::FillCacheStore (BOOL fClearCache) { BOOL fResult; CRYPT_BLOB_ARRAY cba; if ( fClearCache == TRUE ) { if ( ObjectContextDeleteAllObjectsFromStore( m_hCacheStore ) == FALSE ) { return( FALSE ); } } fResult = LdapSendReceiveUrlRequest( m_pBinding, &m_UrlComponents, 0, // dwRetrievalFlags LDAP_STORE_TIMEOUT, &cba, NULL ); if (fResult) { HCERTSTORE hStore = NULL; fResult = CreateObjectContext ( CRYPT_RETRIEVE_MULTIPLE_OBJECTS, &cba, CERT_QUERY_CONTENT_FLAG_CERT | CERT_QUERY_CONTENT_FLAG_CTL | CERT_QUERY_CONTENT_FLAG_CRL | CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | CERT_QUERY_CONTENT_FLAG_CERT_PAIR, FALSE, // fQuerySingleContext (LPVOID*) &hStore ); if (fResult) { fResult = I_CertUpdateStore( m_hCacheStore, hStore, 0, NULL ); CertCloseStore( hStore, 0 ); } CCryptBlobArray BlobArray( &cba, 0 ); BlobArray.FreeArray( TRUE ); } else if (GetLastError() == CRYPT_E_NOT_FOUND) { fResult = TRUE; } return( fResult ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::InternalCommit, private // // Synopsis: commit current changes // //---------------------------------------------------------------------------- BOOL CLdapStore::InternalCommit (DWORD dwFlags) { BOOL fResult = TRUE; LPCSTR pszContextOid = CONTEXT_OID_CERTIFICATE; LPVOID pvContext = NULL; struct berval** abv; struct berval** newabv; DWORD cbv = 0; DWORD cCount; DWORD cArray = MIN_BERVAL; if ( dwFlags & CERT_STORE_CTRL_COMMIT_CLEAR_FLAG ) { m_fDirty = FALSE; return( TRUE ); } if ( m_dwOpenFlags & CERT_STORE_READONLY_FLAG ) { SetLastError( (DWORD) ERROR_ACCESS_DENIED ); return( FALSE ); } if ( ( m_fDirty == FALSE ) && !( dwFlags & CERT_STORE_CTRL_COMMIT_FORCE_FLAG ) ) { return( TRUE ); } abv = (struct berval**)malloc( cArray * sizeof( struct berval* ) ); if ( abv == NULL ) { SetLastError( (DWORD) E_OUTOFMEMORY ); return( FALSE ); } memset( abv, 0, cArray * sizeof( struct berval * ) ); while ( ( fResult == TRUE ) && ( ( pvContext = ObjectContextEnumObjectsInStore( m_hCacheStore, pszContextOid, pvContext, &pszContextOid ) ) != NULL ) ) { abv[cbv] = (struct berval*)malloc( sizeof( struct berval ) ); if ( abv[cbv] != NULL ) { ObjectContextGetEncodedBits( pszContextOid, pvContext, &(abv[cbv]->bv_len), (LPBYTE *)&(abv[cbv]->bv_val) ); cbv += 1; } else { SetLastError( (DWORD) E_OUTOFMEMORY ); fResult = FALSE; ObjectContextFree( pszContextOid, pvContext ); } if ( cbv == ( cArray - 1 ) ) { newabv = (struct berval**)realloc( abv, ( cArray + GROW_BERVAL ) * sizeof( struct berval* ) ); if ( newabv != NULL ) { abv = newabv; memset( &abv[cArray], 0, GROW_BERVAL * sizeof( struct berval* ) ); cArray += GROW_BERVAL; } else { SetLastError( (DWORD) E_OUTOFMEMORY ); fResult = FALSE; } } } if ( fResult == TRUE ) { ULONG lderr; LDAPModW mod; LDAPModW* amod[2]; assert( m_UrlComponents.cAttr == 1 ); mod.mod_type = m_UrlComponents.apwszAttr[0]; mod.mod_op = LDAP_MOD_BVALUES; amod[0] = &mod; amod[1] = NULL; if ( cbv > 0 ) { mod.mod_op |= LDAP_MOD_REPLACE; mod.mod_bvalues = abv; } else { mod.mod_op |= LDAP_MOD_DELETE; mod.mod_bvalues = NULL; } if ( ( lderr = ldap_modify_sW( m_pBinding, m_UrlComponents.pwszDN, amod ) ) == LDAP_SUCCESS ) { m_fDirty = FALSE; } else { SetLastError( I_CryptNetLdapMapErrorToWin32( m_pBinding, lderr ) ); fResult = FALSE; } } for ( cCount = 0; cCount < cbv; cCount++ ) { free( abv[cCount] ); } free( abv ); return( fResult ); } //+--------------------------------------------------------------------------- // // Member: CLdapStore::WriteCheckSetDirtyWithLock, private // // Synopsis: if the store is writable, set the dirty flag taking the store // lock where appropriate // //---------------------------------------------------------------------------- BOOL CLdapStore::WriteCheckSetDirtyWithLock ( LPCSTR pszContextOid, LPVOID pvContext, DWORD dwFlags ) { if ( m_dwOpenFlags & CERT_STORE_READONLY_FLAG ) { SetLastError( (DWORD) ERROR_ACCESS_DENIED ); return( FALSE ); } EnterCriticalSection( &m_StoreLock ); if ( ( dwFlags >> 16 ) == CERT_STORE_ADD_ALWAYS ) { LPVOID pv; if ( ( pv = ObjectContextFindCorrespondingObject( m_hCacheStore, pszContextOid, pvContext ) ) != NULL ) { ObjectContextFree( pszContextOid, pv ); SetLastError( (DWORD) CRYPT_E_EXISTS ); LeaveCriticalSection( &m_StoreLock ); return( FALSE ); } } m_fDirty = TRUE; LeaveCriticalSection( &m_StoreLock ); return( TRUE ); } //+--------------------------------------------------------------------------- // // Function: LdapProvOpenStore // // Synopsis: provider open store entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvOpenStore ( IN LPCSTR pszStoreProv, IN DWORD dwMsgAndCertEncodingType, IN HCRYPTPROV hCryptProv, IN DWORD dwFlags, IN const void* pvPara, IN HCERTSTORE hCertStore, IN OUT PCERT_STORE_PROV_INFO pStoreProvInfo ) { BOOL fResult = FALSE; CLdapStore* pLdap; pLdap = new CLdapStore ( fResult ); if ( pLdap == NULL ) { SetLastError( (DWORD) E_OUTOFMEMORY ); return( FALSE ); } if ( fResult == FALSE ) { delete pLdap; return( FALSE ); } fResult = pLdap->OpenStore( pszStoreProv, dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara, hCertStore, pStoreProvInfo ); if ( fResult == FALSE ) { delete pLdap; } return( fResult ); } //+--------------------------------------------------------------------------- // // Function: LdapProvCloseStore // // Synopsis: provider close store entry point // //---------------------------------------------------------------------------- void WINAPI LdapProvCloseStore ( IN HCERTSTOREPROV hStoreProv, IN DWORD dwFlags ) { ( (CLdapStore *)hStoreProv )->CloseStore( dwFlags ); delete (CLdapStore *)hStoreProv; } //+--------------------------------------------------------------------------- // // Function: LdapProvDeleteCert // // Synopsis: provider delete certificate entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvDeleteCert ( IN HCERTSTOREPROV hStoreProv, IN PCCERT_CONTEXT pCertContext, IN DWORD dwFlags ) { return( ( (CLdapStore *)hStoreProv )->DeleteCert( pCertContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvDeleteCrl // // Synopsis: provider delete CRL entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvDeleteCrl ( IN HCERTSTOREPROV hStoreProv, IN PCCRL_CONTEXT pCrlContext, IN DWORD dwFlags ) { return( ( (CLdapStore *)hStoreProv )->DeleteCrl( pCrlContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvDeleteCtl // // Synopsis: provider delete CTL entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvDeleteCtl ( IN HCERTSTOREPROV hStoreProv, IN PCCTL_CONTEXT pCtlContext, IN DWORD dwFlags ) { return( ( (CLdapStore *)hStoreProv )->DeleteCtl( pCtlContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvSetCertProperty // // Synopsis: provider set certificate property entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvSetCertProperty ( IN HCERTSTOREPROV hStoreProv, IN PCCERT_CONTEXT pCertContext, IN DWORD dwPropId, IN DWORD dwFlags, IN const void* pvData ) { return( ( (CLdapStore *)hStoreProv )->SetCertProperty( pCertContext, dwPropId, dwFlags, pvData ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvSetCrlProperty // // Synopsis: provider set CRL property entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvSetCrlProperty ( IN HCERTSTOREPROV hStoreProv, IN PCCRL_CONTEXT pCrlContext, IN DWORD dwPropId, IN DWORD dwFlags, IN const void* pvData ) { return( ( (CLdapStore *)hStoreProv )->SetCrlProperty( pCrlContext, dwPropId, dwFlags, pvData ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvSetCtlProperty // // Synopsis: provider set CTL property entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvSetCtlProperty ( IN HCERTSTOREPROV hStoreProv, IN PCCTL_CONTEXT pCtlContext, IN DWORD dwPropId, IN DWORD dwFlags, IN const void* pvData ) { return( ( (CLdapStore *)hStoreProv )->SetCtlProperty( pCtlContext, dwPropId, dwFlags, pvData ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvWriteCert // // Synopsis: provider write certificate entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvWriteCert ( IN HCERTSTOREPROV hStoreProv, IN PCCERT_CONTEXT pCertContext, IN DWORD dwFlags ) { return( ( (CLdapStore *)hStoreProv )->WriteCert( pCertContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvWriteCrl // // Synopsis: provider write CRL entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvWriteCrl ( IN HCERTSTOREPROV hStoreProv, IN PCCRL_CONTEXT pCrlContext, IN DWORD dwFlags ) { return( ( (CLdapStore *)hStoreProv )->WriteCrl( pCrlContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvWriteCtl // // Synopsis: provider write CTL entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvWriteCtl ( IN HCERTSTOREPROV hStoreProv, IN PCCTL_CONTEXT pCtlContext, IN DWORD dwFlags ) { return( ( (CLdapStore *)hStoreProv )->WriteCtl( pCtlContext, dwFlags ) ); } //+--------------------------------------------------------------------------- // // Function: LdapProvStoreControl // // Synopsis: provider control entry point // //---------------------------------------------------------------------------- BOOL WINAPI LdapProvStoreControl ( IN HCERTSTOREPROV hStoreProv, IN DWORD dwFlags, IN DWORD dwCtrlType, IN LPVOID pvCtrlPara ) { return( ( (CLdapStore *)hStoreProv )->StoreControl( dwFlags, dwCtrlType, pvCtrlPara ) ); } //+--------------------------------------------------------------------------- // // Function: I_CryptNetGetUserDsStoreUrl // // Synopsis: get user DS store URL // //---------------------------------------------------------------------------- BOOL WINAPI I_CryptNetGetUserDsStoreUrl ( IN LPWSTR pwszUserAttribute, OUT LPWSTR* ppwszUrl ) { BOOL fResult; DWORD dwLastError = 0; WCHAR wszUser[MAX_PATH]; ULONG nUser = MAX_PATH; LPWSTR pwszUser = wszUser; HMODULE hModule = NULL; PFN_GETUSERNAMEEXW pfnGetUserNameExW = NULL; hModule = LoadLibraryA( "secur32.dll" ); if ( hModule == NULL ) { return( FALSE ); } pfnGetUserNameExW = (PFN_GETUSERNAMEEXW)GetProcAddress( hModule, "GetUserNameExW" ); if ( pfnGetUserNameExW == NULL ) { FreeLibrary( hModule ); return( FALSE ); } fResult = ( *pfnGetUserNameExW )( NameFullyQualifiedDN, pwszUser, &nUser ); if ( fResult == FALSE ) { if ( ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) || ( GetLastError() == ERROR_MORE_DATA ) ) { pwszUser = new WCHAR [nUser]; if ( pwszUser != NULL ) { fResult = ( *pfnGetUserNameExW )( NameFullyQualifiedDN, pwszUser, &nUser ); } else { SetLastError( (DWORD) E_OUTOFMEMORY ); fResult = FALSE; } } } if ( fResult == TRUE ) { DWORD cchUrl = 0; LPWSTR pwszUrl = NULL; cchUrl = wcslen(USER_DS_STORE_URL_PREFIX) + wcslen(pwszUser) + wcslen(USER_DS_STORE_URL_SEPARATOR) + wcslen(pwszUserAttribute) + 1; pwszUrl = (LPWSTR)CryptMemAlloc(cchUrl * sizeof(WCHAR)); if ( pwszUrl != NULL ) { wcscpy(pwszUrl, USER_DS_STORE_URL_PREFIX); wcscat(pwszUrl, pwszUser); wcscat(pwszUrl, USER_DS_STORE_URL_SEPARATOR); wcscat(pwszUrl, pwszUserAttribute); *ppwszUrl = pwszUrl; } else { SetLastError( (DWORD) E_OUTOFMEMORY ); fResult = FALSE; } } dwLastError = GetLastError(); if ( pwszUser != wszUser ) { delete [] pwszUser; } FreeLibrary( hModule ); SetLastError(dwLastError); return( fResult ); }