0

私のアプリでは、アクティブ ディレクトリで DirSync を実行する必要があります。ただし、ページ サイズの検索設定パラメーターを指定しようとすると、検索設定でエラー (0x80005008、ADS_BAD_PARAMETER) が発生します。私がそれを与えなければ、それはうまくいきます。以下にコードスニペットを示します。

HRESULT DoDirSyncSearch(
            LPWSTR pszSearchFilter,  //  Search filter.
            LPWSTR *pAttributeNames, //  Attributes to retrieve.
            DWORD dwAttributes,      //  Number of attributes.
            PUCHAR *ppCookie,        //  Pointer to previous cookie.
            PULONG pulCookieLength,  //  Length of previous cookie.
            LPWSTR szDC)             //  Name of DC to bind to.
{
    IADs *pRootDSE = NULL;
    IDirectorySearch *pSearch = NULL;
    ADS_SEARCH_HANDLE hSearch = NULL;
    ADS_SEARCHPREF_INFO arSearchPrefs[4];
    ADS_PROV_SPECIFIC dirsync;
    ADS_SEARCH_COLUMN col;
    HRESULT hr = S_OK;
    VARIANT var;
    BOOL bUpdate = FALSE;
    DWORD dwCount = 0;
    BOOL noMoreData = false;
    DWORD dwError = ERROR_SUCCESS;
    WCHAR szError[512];
    WCHAR szProvider[512];

    //  Validate input parameters.
    if (!pulCookieLength || !ppCookie || !szDC) 
    {
        wprintf(L"Invalid parameter.\n");
        return E_FAIL;
    }

    LPOLESTR szDSPath = new OLECHAR[MAX_PATH];
    LPOLESTR szServerPath = new OLECHAR[MAX_PATH];
    VariantInit(&var);

    //  If cookie is non-NULL, this is an update. Otherwise, it is a full-read.
    if (*ppCookie)
        bUpdate = TRUE;
    CoInitialize(NULL);

    //  If there is a DC name from the previous USN sync, 
    //  include it in the binding string.
    if (szDC[0]) 
    {
        wcsncpy_s(szServerPath,MAX_PATH,L"LDAP://",MAX_PATH);
        wcsncat_s(szServerPath, MAX_PATH,szDC,MAX_PATH-wcslen(szServerPath));
        wcsncat_s(szServerPath, MAX_PATH,L"/",MAX_PATH-wcslen(szServerPath));
    }
    else
        wcsncpy_s(szServerPath, MAX_PATH,L"LDAP://",MAX_PATH);

    // Bind to root DSE.
    wcsncpy_s(szDSPath,MAX_PATH,szServerPath,MAX_PATH);
    wcsncat_s(szDSPath, MAX_PATH,L"rootDSE",MAX_PATH-wcslen(szDSPath));
    wprintf(L"RootDSE binding string: %s\n", szDSPath);
    hr = ADsGetObject(szDSPath, 
                  IID_IADs,
                  (void**)&pRootDSE);
    if (FAILED(hr)) 
    {
        wprintf(L"failed to bind to rootDSE: 0x%x\n", hr);
        goto cleanup;
    }

    //  Save the name of the DC connected to in order to connect to 
    //  the same DC on the next dirsync operation.
    if (! szDC[0])
    {
        hr = pRootDSE->Get(CComBSTR("DnsHostName"), &var);
        wcsncpy_s(szServerPath,MAX_PATH,L"LDAP://",MAX_PATH);
        wcsncat_s(szServerPath, MAX_PATH,var.bstrVal, MAX_PATH-wcslen(szServerPath));
        wcsncat_s(szServerPath, MAX_PATH,L"/", MAX_PATH-wcslen(szServerPath));
    }

    //  Get an IDirectorySearch pointer to the root of the domain partition.
    hr = pRootDSE->Get(CComBSTR("defaultNamingContext"), &var);
    wcsncpy_s(szDSPath,MAX_PATH,szServerPath,MAX_PATH);
    wcsncat_s(szDSPath, MAX_PATH,var.bstrVal, MAX_PATH - wcslen(szDSPath));
    hr = ADsGetObject(szDSPath, IID_IDirectorySearch, (void**) &pSearch);
    if (FAILED(hr)) 
    {
        wprintf(L"failed to get IDirectorySearch: 0x%x\n", hr);
        goto cleanup;
    }



    while(noMoreData == false) {

        //  Initialize the structure to pass in the cookie.
        //  On the first call, the cookie is NULL and the length is zero.
        //  On later calls, the cookie and length are the values returned by 
        //  the previous call.
        dirsync.dwLength = *pulCookieLength;
        dirsync.lpValue = *ppCookie;
        arSearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; 
        arSearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER; 
        arSearchPrefs[0].vValue.Integer = ADS_SCOPE_SUBTREE; 
        arSearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_DIRSYNC; 
        arSearchPrefs[1].vValue.dwType = ADSTYPE_PROV_SPECIFIC;
        arSearchPrefs[1].vValue.ProviderSpecific = dirsync;
        arSearchPrefs[2].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; 
        arSearchPrefs[2].vValue.dwType = ADSTYPE_INTEGER;
        arSearchPrefs[2].vValue.Integer = 100;
        hr = pSearch->SetSearchPreference(arSearchPrefs, 3); // this is where error is happening

        if (FAILED(hr)) 
        {
            wprintf(L"failed to set search prefs: 0x%x\n", hr);
            goto cleanup;
        }

        // Search for the objects indicated by the search filter.
        hr = pSearch->ExecuteSearch(pszSearchFilter,
                        pAttributeNames, dwAttributes, &hSearch );
        if (FAILED(hr)) 
        {
            wprintf(L"failed to set execute search: 0x%x\n", hr);
            goto cleanup;
        }

        //  Loop through the rows of the search result
        //  Each row is an object that has changed since the previous call.

        hr = pSearch->GetNextRow(hSearch);

        while ( SUCCEEDED(hr) && hr != S_ADS_NOMORE_ROWS )
        {
            hr = pSearch->GetColumn( hSearch, L"distinguishedName", &col );
            if ( SUCCEEDED(hr) ) 
            {
                wprintf(L"Distinguished Name: %s\n",col.pADsValues->CaseIgnoreString);
                pSearch->FreeColumn( &col );
            }

            dwCount++;
            hr = pSearch->GetNextRow( hSearch);
        }

        ADsGetLastError(&dwError, szError, 512, szProvider, 512);
        if(ERROR_MORE_DATA == dwError) 
        {
            noMoreData = false;
            wprintf(L"Trying to get cookie...\n");
            wprintf(L"Page ends here...\n");
            hr = pSearch->GetColumn( hSearch, ADS_DIRSYNC_COOKIE, &col );
            if ( SUCCEEDED(hr) ) {
                if (col.dwADsType == ADSTYPE_PROV_SPECIFIC && col.pADsValues) 
                {
                    wprintf(L"Got cookie\n");
                    *pulCookieLength = col.pADsValues->ProviderSpecific.dwLength;
                    *ppCookie = (PUCHAR) AllocADsMem (*pulCookieLength);
                    memcpy(*ppCookie, col.pADsValues->ProviderSpecific.lpValue, 
                        *pulCookieLength);
                }
                pSearch->FreeColumn( &col );
            } else {
                wprintf(L"no cookie: 0x%x\n", hr);
                wprintf(L"Error!! More data available but could not continue because of error in cookie retrieval...\n");
                noMoreData = true;
            }
        }
        else
            noMoreData = true;
    }
    wprintf(L"dwCount: %d\n", dwCount);

    //  After looping through the results, get the cookie.
    if (hr == S_ADS_NOMORE_ROWS ) 
    {
        if (ppCookie != NULL)
        {
            // Free the existing heap allocation
            GlobalFree (*ppCookie);
        }

        wprintf(L"Trying to get cookie...\n");
        hr = pSearch->GetColumn( hSearch, ADS_DIRSYNC_COOKIE, &col );
        if ( SUCCEEDED(hr) ) {
            if (col.dwADsType == ADSTYPE_PROV_SPECIFIC && col.pADsValues) 
            {
                wprintf(L"Got cookie\n");
                *pulCookieLength = col.pADsValues->ProviderSpecific.dwLength;
                *ppCookie = (PUCHAR) AllocADsMem (*pulCookieLength);
                memcpy(*ppCookie, col.pADsValues->ProviderSpecific.lpValue, 
                    *pulCookieLength);
            }
            pSearch->FreeColumn( &col );
        } else
            wprintf(L"no cookie: 0x%x\n", hr);
    }

cleanup:
    if (pRootDSE)
        pRootDSE->Release();
    if (hSearch)
        pSearch->CloseSearchHandle(hSearch);
    if (pSearch)
        pSearch->Release();

    VariantClear(&var);
    CoUninitialize();
    delete [] szServerPath;
    delete [] szDSPath;

    return hr;
}

最初の 2 つの設定、つまりスコープと DIRSYNC のみを指定した場合、次の行

hr = pSearch->SetSearchPreference(arSearchPrefs, 2);

エラーは発生しません。

なぜそれが起こっているのか、誰か助けてください。msdn からページングのオプションを指定する方法を確認しました: http://msdn.microsoft.com/en-us/library/windows/desktop/aa746414(v=vs.85).aspx

前もって感謝します!

4

1 に答える 1

0

MSDN リンクから:

ADS_SEARCHPREF_DIRSYNC

指定した状態以降のすべての変更を返す、ディレクトリ同期 (DirSync) 検索を指定します。ADSVALUE 構造体で、dwType メンバを ADS_PROV_SPECIFIC に設定します。ProviderSpecific メンバーは ADS_PROV_SPECIFIC 構造体であり、その lpValue メンバーは変更が取得される状態を示す Cookie を指定します。DirSync コントロールを初めて使用するときは、ADS_PROV_SPECIFIC 構造体の dwLength メンバーと lpValue メンバーをそれぞれゼロと NULL に設定します。IDirectorySearch::GetNextRow が S_ADS_NOMORE_ROWS を返すまで検索によって返された結果セットを読み取った後、IDirectorySearch::GetColumn を呼び出して、次の DirSync 検索で使用する Cookie を含む ADS_DIRSYNC_COOKIE 属性を取得します。詳細については、DirSync コントロールおよび LDAP_SERVER_DIRSYNC_OID を使用した変更のポーリングを参照してください。このフラグは、ADS_SEARCHPREF_PAGESIZE と組み合わせることはできません。呼び出し元には SE_SYNC_AGENT_NAME 権限が必要です。

于 2016-05-01T15:07:19.623 に答える