我正在撰寫一個 C 本機方法來創建一個 Active Directory 用戶。我得到一個空指標例外。此代碼與Microsoft 官方檔案中的代碼完全相同。
我在評論中提到了我收到錯誤的那一行:
HRESULT CreateUserFromADs(
LPCWSTR pwszName,
LPCWSTR pwszSAMAccountName,
LPCWSTR pwszInitialPassword)
{
HRESULT hr;
CoInitialize(NULL);
IADsContainer* pUsers = NULL;
hr = ADsOpenObject(L"LDAP://WIN-F94H2MP3UJR.Test.local/CN=Users,DC=Test,DC=local", L"Administrator", L"Pass@12",
ADS_SECURE_AUTHENTICATION, // For secure authentication
IID_IADs,
(void**)&pUsers);
if (SUCCEEDED(hr))
{
IDispatch* pDisp = NULL;
CComBSTR sbstrName = "CN=";
sbstrName = pwszName;
// Create the new object in the User folder.
hr = pUsers->Create(CComBSTR("user"), sbstrName, &pDisp);
if (SUCCEEDED(hr))
{
IADsUser* padsUser = NULL;
// Get the IADs interface.
// Am getting null pointer exception here.
hr = pDisp->QueryInterface(IID_IADsUser,
(void**)&padsUser);
if (SUCCEEDED(hr))
{
CComBSTR sbstrProp;
/*
The sAMAccountName property is required on operating system
versions prior to Windows Server 2003.
The Windows Server 2003 operating system will create a
sAMAccountName value if one is not specified.
*/
CComVariant svar;
svar = pwszSAMAccountName;
sbstrProp = "sAMAccountName";
hr = padsUser->Put(sbstrProp, svar);
/*
Commit the new user to persistent memory.
The user does not exist until this is called.
*/
hr = padsUser->SetInfo();
/*
Set the initial password. This must be done after
SetInfo is called because the user object must
already exist on the server.
*/
hr = padsUser->SetPassword(CComBSTR(pwszInitialPassword));
/*
Set the pwdLastSet property to zero, which forces the
user to change the password the next time they log on.
*/
sbstrProp = "pwdLastSet";
svar = 0;
hr = padsUser->Put(sbstrProp, svar);
/*
Enable the user account by removing the
ADS_UF_ACCOUNTDISABLE flag from the userAccountControl
property. Also, remove the ADS_UF_PASSWD_NOTREQD and
ADS_UF_DONT_EXPIRE_PASSWD flags from the
userAccountControl property.
*/
svar.Clear();
sbstrProp = "userAccountControl";
hr = padsUser->Get(sbstrProp, &svar);
if (SUCCEEDED(hr))
{
svar = svar.lVal & ~(ADS_UF_ACCOUNTDISABLE |
ADS_UF_PASSWD_NOTREQD |
ADS_UF_DONT_EXPIRE_PASSWD);
hr = padsUser->Put(sbstrProp, svar);
hr = padsUser->SetInfo();
}
hr = padsUser->put_AccountDisabled(VARIANT_FALSE);
hr = padsUser->SetInfo();
padsUser->Release();
}
pDisp->Release();
}
pUsers->Release();
}
CoUninitialize();
return hr;
}
錯誤資訊是
拋出例外:讀取訪問沖突。
pDisp 為 nullptr。
uj5u.com熱心網友回復:
您要求ADsOpenObject()一個IADs*介面指標,但您將它存盤在一個IADsContainer*變數中。那是型別不匹配,IADs并且IADsContainer是不相關的介面。因此,當您呼叫 時pUsers->Create(),您實際上根本沒有IADsContainer::Create()呼叫,而是實際上在呼叫IADs::SetInfo(),它沒有為 分配任何內容pDisp,這就是它保持為 NULL 的原因。
您鏈接到的 Microsoft 檔案不會犯這個錯誤,它要求ADsOpenObject()使用IADsContainer.IADs
您的IID請求必須與您收到的變數型別相匹配。因此,更改IID_IADs為IID_IADsContainer:
IADsContainer* pUsers = NULL;
hr = ADsOpenObject(...,
IID_IADsContainer,
(void**)&pUsers);
您應該考慮使用IID_PPV_ARGS()宏來避免再次犯此錯誤:
IADsContainer* pUsers = NULL;
hr = ADsOpenObject(...,
IID_PPV_ARGS(&pUsers));
附帶說明,您的CreateUserFromADs()函式沒有CoInitialize()直接的業務呼叫,因此您應該洗掉該呼叫。在執行任何與 COM 相關的活動之前,呼叫執行緒負責呼叫CoInitialize/Ex()以建立其并發模型。不是由函式決定代表呼叫執行緒使用哪種并發模型。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/508311.html
上一篇:轉換整數型別
