4 * Copyright 2019 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "wine/test.h"
36 DEFINE_GUID(CLSID_LDAP
,0x228d9a81,0xc302,0x11cf,0x9a,0xa4,0x00,0xaa,0x00,0x4a,0x56,0x91);
37 DEFINE_GUID(CLSID_LDAPNamespace
,0x228d9a82,0xc302,0x11cf,0x9a,0xa4,0x00,0xaa,0x00,0x4a,0x56,0x91);
38 DEFINE_OLEGUID(CLSID_PointerMoniker
,0x306,0,0);
43 HRESULT hr
, hr_ads_open
, hr_ads_get
;
44 const WCHAR
*user
, *password
;
48 { L
"invalid", MK_E_SYNTAX
, E_ADS_BAD_PATHNAME
, E_FAIL
},
49 { L
"LDAP", MK_E_SYNTAX
, E_ADS_BAD_PATHNAME
, E_FAIL
},
51 { L
"LDAP:/", E_ADS_BAD_PATHNAME
},
52 { L
"LDAP://", E_ADS_BAD_PATHNAME
},
53 { L
"LDAP://ldap.forumsys.com", S_OK
},
54 { L
"LDAP:///ldap.forumsys.com", E_ADS_BAD_PATHNAME
},
55 { L
"LDAP://ldap.forumsys.com:389", S_OK
},
56 { L
"LDAP://ldap.forumsys.com:389/DC=example,DC=com", S_OK
},
57 { L
"LDAP://ldap.forumsys.com/", E_ADS_BAD_PATHNAME
},
58 { L
"LDAP://ldap.forumsys.com/rootDSE", S_OK
},
59 { L
"LDAP://ldap.forumsys.com/rootDSE/", E_ADS_BAD_PATHNAME
},
60 { L
"LDAP://ldap.forumsys.com/rootDSE/invalid", E_ADS_BAD_PATHNAME
},
61 { L
"LDAP://ldap.forumsys.com/rootDSE", S_OK
, S_OK
, S_OK
, NULL
, NULL
, 0 },
62 { L
"LDAP://ldap.forumsys.com/rootDSE", S_OK
, S_OK
, S_OK
, L
"CN=read-only-admin,DC=example,DC=com", L
"password", 0 },
64 /*{ L"LDAP://invalid", __HRESULT_FROM_WIN32(ERROR_DS_INVALID_DN_SYNTAX) }, takes way too much time */
67 static void test_LDAP(void)
72 IADsOpenDSObject
*ads_open
;
74 BSTR path
, user
, password
;
77 hr
= CoCreateInstance(&CLSID_LDAPNamespace
, 0, CLSCTX_INPROC_SERVER
, &IID_IADs
, (void **)&ads
);
78 ok(hr
== S_OK
, "got %#x\n", hr
);
81 hr
= CoCreateInstance(&CLSID_LDAPNamespace
, 0, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&unk
);
82 ok(hr
== S_OK
, "got %#x\n", hr
);
84 hr
= IUnknown_QueryInterface(unk
, &IID_IDispatch
, (void **)&disp
);
85 ok(hr
== S_OK
, "got %#x\n", hr
);
86 IDispatch_Release(disp
);
88 hr
= IUnknown_QueryInterface(unk
, &IID_IADsOpenDSObject
, (void **)&ads_open
);
89 ok(hr
== S_OK
, "got %#x\n", hr
);
91 for (i
= 0; i
< ARRAY_SIZE(test
); i
++)
93 path
= SysAllocString(test
[i
].path
);
94 user
= test
[i
].user
? SysAllocString(test
[i
].user
) : NULL
;
95 password
= test
[i
].password
? SysAllocString(test
[i
].password
) : NULL
;
97 hr
= IADsOpenDSObject_OpenDSObject(ads_open
, path
, user
, password
, test
[i
].flags
, &disp
);
98 if (hr
== HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN
))
101 skip("server is down\n");
104 ok(hr
== test
[i
].hr
|| hr
== test
[i
].hr_ads_open
, "%d: got %#x, expected %#x\n", i
, hr
, test
[i
].hr
);
106 IDispatch_Release(disp
);
108 hr
= ADsOpenObject(path
, user
, password
, test
[i
].flags
, &IID_IADs
, (void **)&ads
);
109 if (hr
== HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN
))
112 skip("server is down\n");
115 ok(hr
== test
[i
].hr
|| hr
== test
[i
].hr_ads_get
, "%d: got %#x, expected %#x\n", i
, hr
, test
[i
].hr
);
119 hr
= ADsGetObject(path
, &IID_IDispatch
, (void **)&disp
);
120 if (hr
== HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN
))
123 skip("server is down\n");
126 ok(hr
== test
[i
].hr
|| hr
== test
[i
].hr_ads_get
, "%d: got %#x, expected %#x\n", i
, hr
, test
[i
].hr
);
128 IDispatch_Release(disp
);
132 SysFreeString(password
);
136 IADsOpenDSObject_Release(ads_open
);
137 IUnknown_Release(unk
);
140 static void test_ParseDisplayName(void)
144 IParseDisplayName
*parse
;
152 hr
= CoCreateInstance(&CLSID_LDAP
, 0, CLSCTX_INPROC_SERVER
, &IID_IParseDisplayName
, (void **)&parse
);
153 ok(hr
== S_OK
, "got %#x\n", hr
);
154 IParseDisplayName_Release(parse
);
156 hr
= CoCreateInstance(&CLSID_LDAP
, 0, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&unk
);
157 ok(hr
== S_OK
, "got %#x\n", hr
);
158 hr
= IUnknown_QueryInterface(unk
, &IID_IParseDisplayName
, (void **)&parse
);
159 ok(hr
== S_OK
, "got %#x\n", hr
);
160 IUnknown_Release(unk
);
162 hr
= CreateBindCtx(0, &bc
);
163 ok(hr
== S_OK
, "got %#x\n", hr
);
165 for (i
= 0; i
< ARRAY_SIZE(test
); i
++)
167 path
= SysAllocString(test
[i
].path
);
170 hr
= IParseDisplayName_ParseDisplayName(parse
, bc
, path
, &count
, &mk
);
171 if (hr
== HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN
))
174 skip("server is down\n");
177 ok(hr
== test
[i
].hr
|| hr
== test
[i
].hr_ads_open
, "%d: got %#x, expected %#x\n", i
, hr
, test
[i
].hr
);
180 ok(count
== lstrlenW(test
[i
].path
), "%d: got %d\n", i
, count
);
182 hr
= IMoniker_GetClassID(mk
, &clsid
);
183 ok(hr
== S_OK
, "got %#x\n", hr
);
184 ok(IsEqualGUID(&clsid
, &CLSID_PointerMoniker
), "%d: got %s\n", i
, wine_dbgstr_guid(&clsid
));
186 IMoniker_Release(mk
);
192 hr
= MkParseDisplayName(bc
, test
[i
].path
, &count
, &mk
);
193 todo_wine_if(i
== 0 || i
== 1 || i
== 11 || i
== 12)
194 ok(hr
== test
[i
].hr
, "%d: got %#x, expected %#x\n", i
, hr
, test
[i
].hr
);
197 ok(count
== lstrlenW(test
[i
].path
), "%d: got %d\n", i
, count
);
199 hr
= IMoniker_GetClassID(mk
, &clsid
);
200 ok(hr
== S_OK
, "got %#x\n", hr
);
201 ok(IsEqualGUID(&clsid
, &CLSID_PointerMoniker
), "%d: got %s\n", i
, wine_dbgstr_guid(&clsid
));
203 IMoniker_Release(mk
);
207 IBindCtx_Release(bc
);
208 IParseDisplayName_Release(parse
);
215 const WCHAR
*values
[16];
222 struct result res
[16];
225 static void do_search(const struct search
*s
)
228 IDirectorySearch
*ds
;
229 ADS_SEARCHPREF_INFO pref
;
230 ADS_SEARCH_HANDLE sh
;
231 ADS_SEARCH_COLUMN col
;
233 const struct result
*res
;
235 trace("search DN %s\n", wine_dbgstr_w(s
->dn
));
237 hr
= ADsGetObject(s
->dn
, &IID_IDirectorySearch
, (void **)&ds
);
238 if (hr
== HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN
))
240 skip("server is down\n");
243 ok(hr
== S_OK
, "got %#x\n", hr
);
245 pref
.dwSearchPref
= ADS_SEARCHPREF_SEARCH_SCOPE
;
246 pref
.vValue
.dwType
= ADSTYPE_INTEGER
;
247 pref
.vValue
.Integer
= s
->scope
;
248 pref
.dwStatus
= 0xdeadbeef;
249 hr
= IDirectorySearch_SetSearchPreference(ds
, &pref
, 1);
250 ok(hr
== S_OK
, "got %#x\n", hr
);
251 ok(pref
.dwStatus
== ADS_STATUS_S_OK
, "got %d\n", pref
.dwStatus
);
253 hr
= IDirectorySearch_ExecuteSearch(ds
, (WCHAR
*)L
"(objectClass=*)", NULL
, ~0, &sh
);
254 ok(hr
== S_OK
, "got %#x\n", hr
);
258 while ((hr
= IDirectorySearch_GetNextRow(ds
, sh
)) != S_ADS_NOMORE_ROWS
)
260 ok(hr
== S_OK
, "got %#x\n", hr
);
262 while ((hr
= IDirectorySearch_GetNextColumnName(ds
, sh
, &name
)) != S_ADS_NOMORE_COLUMNS
)
266 ok(hr
== S_OK
, "got %#x\n", hr
);
267 ok(res
->name
!= NULL
, "got extra row %s\n", wine_dbgstr_w(name
));
268 ok(!wcscmp(res
->name
, name
), "expected %s, got %s\n", wine_dbgstr_w(res
->name
), wine_dbgstr_w(name
));
270 memset(&col
, 0xde, sizeof(col
));
271 hr
= IDirectorySearch_GetColumn(ds
, sh
, name
, &col
);
272 ok(hr
== S_OK
, "got %#x\n", hr
);
274 ok(col
.dwADsType
== res
->type
, "got %d for %s\n", col
.dwADsType
, wine_dbgstr_w(name
));
276 for (i
= 0; i
< col
.dwNumValues
; i
++)
278 ok(col
.pADsValues
[i
].dwType
== col
.dwADsType
, "%u: got %d for %s\n", i
, col
.pADsValues
[i
].dwType
, wine_dbgstr_w(name
));
280 ok(res
->values
[i
] != NULL
, "expected to have more values for %s\n", wine_dbgstr_w(name
));
281 if (!res
->values
[i
]) break;
283 ok(!wcscmp(res
->values
[i
], col
.pADsValues
[i
].CaseIgnoreString
),
284 "expected %s, got %s\n", wine_dbgstr_w(res
->values
[i
]), wine_dbgstr_w(col
.pADsValues
[i
].CaseIgnoreString
));
287 ok(!res
->values
[i
], "expected extra value %s\n", wine_dbgstr_w(res
->values
[i
]));
289 IDirectorySearch_FreeColumn(ds
, &col
);
295 ok(res
->name
== NULL
, "there are more rows in test data: %s\n", wine_dbgstr_w(res
->name
));
297 hr
= IDirectorySearch_CloseSearchHandle(ds
, sh
);
298 ok(hr
== S_OK
, "got %#x\n", hr
);
300 IDirectorySearch_Release(ds
);
303 static void test_DirectorySearch(void)
305 static const struct search root_base
=
307 L
"LDAP://ldap.forumsys.com", ADS_SCOPE_BASE
,
309 { L
"objectClass", ADSTYPE_CASE_IGNORE_STRING
, { L
"top", L
"OpenLDAProotDSE", NULL
} },
310 { L
"ADsPath", ADSTYPE_CASE_IGNORE_STRING
, { L
"LDAP://ldap.forumsys.com/", NULL
} },
314 static const struct search scientists_base
=
316 L
"LDAP://ldap.forumsys.com/OU=scientists,DC=example,DC=com", ADS_SCOPE_BASE
,
318 { L
"uniqueMember", ADSTYPE_CASE_IGNORE_STRING
, { L
"uid=einstein,dc=example,dc=com",
319 L
"uid=galieleo,dc=example,dc=com", L
"uid=tesla,dc=example,dc=com", L
"uid=newton,dc=example,dc=com",
320 L
"uid=training,dc=example,dc=com", L
"uid=jmacy,dc=example,dc=com", NULL
} },
321 { L
"ou", ADSTYPE_CASE_IGNORE_STRING
, { L
"scientists", NULL
} },
322 { L
"cn", ADSTYPE_CASE_IGNORE_STRING
, { L
"Scientists", NULL
} },
323 { L
"objectClass", ADSTYPE_CASE_IGNORE_STRING
, { L
"groupOfUniqueNames", L
"top", NULL
} },
324 { L
"ADsPath", ADSTYPE_CASE_IGNORE_STRING
, { L
"LDAP://ldap.forumsys.com/ou=scientists,dc=example,dc=com", NULL
} },
328 static const struct search scientists_subtree
=
330 L
"LDAP://ldap.forumsys.com/OU=scientists,DC=example,DC=com", ADS_SCOPE_SUBTREE
,
332 { L
"uniqueMember", ADSTYPE_CASE_IGNORE_STRING
, { L
"uid=einstein,dc=example,dc=com",
333 L
"uid=galieleo,dc=example,dc=com", L
"uid=tesla,dc=example,dc=com", L
"uid=newton,dc=example,dc=com",
334 L
"uid=training,dc=example,dc=com", L
"uid=jmacy,dc=example,dc=com", NULL
} },
335 { L
"ou", ADSTYPE_CASE_IGNORE_STRING
, { L
"scientists", NULL
} },
336 { L
"cn", ADSTYPE_CASE_IGNORE_STRING
, { L
"Scientists", NULL
} },
337 { L
"objectClass", ADSTYPE_CASE_IGNORE_STRING
, { L
"groupOfUniqueNames", L
"top", NULL
} },
338 { L
"ADsPath", ADSTYPE_CASE_IGNORE_STRING
, { L
"LDAP://ldap.forumsys.com/ou=scientists,dc=example,dc=com", NULL
} },
339 { L
"uniqueMember", ADSTYPE_CASE_IGNORE_STRING
, { L
"uid=tesla,dc=example,dc=com", NULL
} },
340 { L
"ou", ADSTYPE_CASE_IGNORE_STRING
, { L
"italians", NULL
} },
341 { L
"cn", ADSTYPE_CASE_IGNORE_STRING
, { L
"Italians", NULL
} },
342 { L
"objectClass", ADSTYPE_CASE_IGNORE_STRING
, { L
"groupOfUniqueNames", L
"top", NULL
} },
343 { L
"ADsPath", ADSTYPE_CASE_IGNORE_STRING
, { L
"LDAP://ldap.forumsys.com/ou=italians,ou=scientists,dc=example,dc=com", NULL
} },
348 IDirectorySearch
*ds
;
349 ADS_SEARCHPREF_INFO pref
;
350 ADS_SEARCH_HANDLE sh
;
351 ADS_SEARCH_COLUMN col
;
354 hr
= ADsGetObject(L
"LDAP:", &IID_IDirectorySearch
, (void **)&ds
);
355 ok(hr
== E_NOINTERFACE
, "got %#x\n", hr
);
357 hr
= ADsGetObject(L
"LDAP://ldap.forumsys.com/rootDSE", &IID_IDirectorySearch
, (void **)&ds
);
358 if (hr
== HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN
))
360 skip("server is down\n");
363 ok(hr
== E_NOINTERFACE
, "got %#x\n", hr
);
365 hr
= ADsGetObject(L
"LDAP://ldap.forumsys.com", &IID_IDirectorySearch
, (void **)&ds
);
366 if (hr
== HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN
))
368 skip("server is down\n");
371 ok(hr
== S_OK
, "got %#x\n", hr
);
373 pref
.dwSearchPref
= ADS_SEARCHPREF_SEARCH_SCOPE
;
374 pref
.vValue
.dwType
= ADSTYPE_INTEGER
;
375 pref
.vValue
.Integer
= ADS_SCOPE_BASE
;
376 pref
.dwStatus
= 0xdeadbeef;
377 hr
= IDirectorySearch_SetSearchPreference(ds
, &pref
, 1);
378 ok(hr
== S_OK
, "got %#x\n", hr
);
379 ok(pref
.dwStatus
== ADS_STATUS_S_OK
, "got %d\n", pref
.dwStatus
);
381 hr
= IDirectorySearch_ExecuteSearch(ds
, (WCHAR
*)L
"(objectClass=*)", NULL
, ~0, NULL
);
382 ok(hr
== E_ADS_BAD_PARAMETER
, "got %#x\n", hr
);
384 if (0) /* crashes under XP */
386 hr
= IDirectorySearch_ExecuteSearch(ds
, (WCHAR
*)L
"(objectClass=*)", NULL
, 1, &sh
);
387 ok(hr
== E_ADS_BAD_PARAMETER
, "got %#x\n", hr
);
390 hr
= IDirectorySearch_ExecuteSearch(ds
, (WCHAR
*)L
"(objectClass=*)", NULL
, ~0, &sh
);
391 ok(hr
== S_OK
, "got %#x\n", hr
);
393 hr
= IDirectorySearch_GetNextColumnName(ds
, sh
, &name
);
394 ok(hr
== E_ADS_BAD_PARAMETER
, "got %#x\n", hr
);
396 hr
= IDirectorySearch_GetPreviousRow(ds
, sh
);
398 ok(hr
== E_ADS_BAD_PARAMETER
, "got %#x\n", hr
);
400 while (IDirectorySearch_GetNextRow(ds
, sh
) != S_ADS_NOMORE_ROWS
)
402 while (IDirectorySearch_GetNextColumnName(ds
, sh
, &name
) != S_ADS_NOMORE_COLUMNS
)
406 hr
= IDirectorySearch_GetColumn(ds
, sh
, name
, &col
);
407 ok(hr
== S_OK
, "got %#x for column %s\n", hr
, wine_dbgstr_w(name
));
409 if (winetest_debug
> 1) /* useful to create test arrays */
411 printf("Column %s (values type %d):\n", wine_dbgstr_w(name
), col
.dwADsType
);
413 for (i
= 0; i
< col
.dwNumValues
; i
++)
414 printf("%s, ", wine_dbgstr_w(col
.pADsValues
[i
].CaseIgnoreString
));
418 hr
= IDirectorySearch_FreeColumn(ds
, &col
);
419 ok(hr
== S_OK
, "got %#x\n", hr
);
422 name
= (void *)0xdeadbeef;
423 hr
= IDirectorySearch_GetNextColumnName(ds
, sh
, &name
);
424 ok(hr
== S_ADS_NOMORE_COLUMNS
|| broken(hr
== S_OK
) /* XP */, "got %#x\n", hr
);
425 ok(name
== NULL
|| broken(name
&& !wcscmp(name
, L
"ADsPath")) /* XP */, "got %p/%s\n", name
, wine_dbgstr_w(name
));
428 hr
= IDirectorySearch_GetNextRow(ds
, sh
);
429 ok(hr
== S_ADS_NOMORE_ROWS
, "got %#x\n", hr
);
432 hr
= IDirectorySearch_GetNextColumnName(ds
, sh
, &name
);
434 ok(hr
== S_OK
|| broken(hr
== S_ADS_NOMORE_COLUMNS
) /* XP */, "got %#x\n", hr
);
436 ok((name
&& !wcscmp(name
, L
"ADsPath")) || broken(!name
) /* XP */, "got %s\n", wine_dbgstr_w(name
));
439 name
= (void *)0xdeadbeef;
440 hr
= IDirectorySearch_GetNextColumnName(ds
, sh
, &name
);
441 ok(hr
== S_ADS_NOMORE_COLUMNS
|| broken(hr
== S_OK
) /* XP */, "got %#x\n", hr
);
442 ok(name
== NULL
|| broken(name
&& !wcscmp(name
, L
"ADsPath")) /* XP */, "got %p/%s\n", name
, wine_dbgstr_w(name
));
444 if (0) /* crashes under XP */
446 hr
= IDirectorySearch_GetColumn(ds
, sh
, NULL
, &col
);
447 ok(hr
== E_ADS_BAD_PARAMETER
, "got %#x\n", hr
);
450 hr
= IDirectorySearch_GetFirstRow(ds
, sh
);
451 ok(hr
== S_OK
, "got %#x\n", hr
);
453 memset(&col
, 0x55, sizeof(col
));
454 hr
= IDirectorySearch_GetColumn(ds
, sh
, (WCHAR
*)L
"deadbeef", &col
);
455 ok(hr
== E_ADS_COLUMN_NOT_SET
, "got %#x\n", hr
);
456 ok(!col
.pszAttrName
|| broken(col
.pszAttrName
!= NULL
) /* XP */, "got %p\n", col
.pszAttrName
);
457 ok(col
.dwADsType
== ADSTYPE_INVALID
|| broken(col
.dwADsType
!= ADSTYPE_INVALID
) /* XP */, "got %d\n", col
.dwADsType
);
458 ok(!col
.pADsValues
, "got %p\n", col
.pADsValues
);
459 ok(!col
.dwNumValues
, "got %u\n", col
.dwNumValues
);
460 ok(!col
.hReserved
, "got %p\n", col
.hReserved
);
462 hr
= IDirectorySearch_CloseSearchHandle(ds
, sh
);
463 ok(hr
== S_OK
, "got %#x\n", hr
);
465 IDirectorySearch_Release(ds
);
467 do_search(&root_base
);
468 do_search(&scientists_base
);
469 do_search(&scientists_subtree
);
472 static void test_DirectoryObject(void)
475 IDirectoryObject
*dirobj
;
477 IDirectorySearch
*ds
;
478 ADS_SEARCHPREF_INFO pref
[2];
479 ADS_SEARCH_HANDLE sh
;
480 ADS_SEARCH_COLUMN col
;
482 hr
= ADsGetObject(L
"LDAP://ldap.forumsys.com/OU=scientists,DC=example,DC=com", &IID_IDirectoryObject
, (void **)&dirobj
);
483 if (hr
== HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN
))
485 skip("server is down\n");
488 ok(hr
== S_OK
, "got %#x\n", hr
);
490 hr
= IDirectoryObject_QueryInterface(dirobj
, &IID_IADsOpenDSObject
, (void **)&unk
);
492 ok(hr
== E_NOINTERFACE
, "got %#x\n", hr
);
493 if (hr
== S_OK
) IUnknown_Release(unk
);
494 hr
= IDirectoryObject_QueryInterface(dirobj
, &IID_IDispatch
, (void **)&unk
);
495 ok(hr
== S_OK
, "got %#x\n", hr
);
496 IUnknown_Release(unk
);
497 hr
= IDirectoryObject_QueryInterface(dirobj
, &IID_IADs
, (void **)&unk
);
498 ok(hr
== S_OK
, "got %#x\n", hr
);
499 IUnknown_Release(unk
);
500 hr
= IDirectoryObject_QueryInterface(dirobj
, &IID_IDirectorySearch
, (void **)&ds
);
501 ok(hr
== S_OK
, "got %#x\n", hr
);
503 pref
[0].dwSearchPref
= ADS_SEARCHPREF_SEARCH_SCOPE
;
504 pref
[0].vValue
.dwType
= ADSTYPE_INTEGER
;
505 pref
[0].vValue
.Integer
= ADS_SCOPE_BASE
;
506 pref
[0].dwStatus
= 0xdeadbeef;
507 pref
[1].dwSearchPref
= ADS_SEARCHPREF_SECURITY_MASK
;
508 pref
[1].vValue
.dwType
= ADSTYPE_INTEGER
;
509 pref
[1].vValue
.Integer
= ADS_SECURITY_INFO_OWNER
| ADS_SECURITY_INFO_GROUP
| ADS_SECURITY_INFO_DACL
;
510 pref
[1].dwStatus
= 0xdeadbeef;
511 hr
= IDirectorySearch_SetSearchPreference(ds
, pref
, ARRAY_SIZE(pref
));
512 ok(hr
== S_ADS_ERRORSOCCURRED
, "got %#x\n", hr
);
513 ok(pref
[0].dwStatus
== ADS_STATUS_S_OK
, "got %d\n", pref
[0].dwStatus
);
514 /* ldap.forumsys.com doesn't support NT security, real ADs DC - does */
515 ok(pref
[1].dwStatus
== ADS_STATUS_INVALID_SEARCHPREF
, "got %d\n", pref
[1].dwStatus
);
517 hr
= IDirectorySearch_ExecuteSearch(ds
, (WCHAR
*)L
"(objectClass=*)", NULL
, ~0, &sh
);
518 ok(hr
== S_OK
, "got %#x\n", hr
);
520 hr
= IDirectorySearch_GetNextRow(ds
, sh
);
521 ok(hr
== S_OK
, "got %#x\n", hr
);
523 hr
= IDirectorySearch_GetColumn(ds
, sh
, (WCHAR
*)L
"nTSecurityDescriptor", &col
);
524 ok(hr
== E_ADS_COLUMN_NOT_SET
, "got %#x\n", hr
);
526 hr
= IDirectorySearch_CloseSearchHandle(ds
, sh
);
527 ok(hr
== S_OK
, "got %#x\n", hr
);
529 pref
[0].dwSearchPref
= ADS_SEARCHPREF_TOMBSTONE
;
530 pref
[0].vValue
.dwType
= ADSTYPE_BOOLEAN
;
531 pref
[0].vValue
.Integer
= 1;
532 pref
[0].dwStatus
= 0xdeadbeef;
533 hr
= IDirectorySearch_SetSearchPreference(ds
, pref
, 1);
534 ok(hr
== S_OK
, "got %#x\n", hr
);
535 ok(pref
[0].dwStatus
== ADS_STATUS_S_OK
, "got %d\n", pref
[0].dwStatus
);
537 hr
= IDirectorySearch_ExecuteSearch(ds
, (WCHAR
*)L
"(objectClass=*)", NULL
, ~0, &sh
);
538 ok(hr
== HRESULT_FROM_WIN32(ERROR_DS_UNAVAILABLE_CRIT_EXTENSION
) || broken(hr
== S_OK
) /* XP */, "got %#x\n", hr
);
541 hr
= IDirectorySearch_GetNextRow(ds
, sh
);
542 ok(hr
== HRESULT_FROM_WIN32(ERROR_DS_UNAVAILABLE_CRIT_EXTENSION
), "got %#x\n", hr
);
544 hr
= IDirectorySearch_CloseSearchHandle(ds
, sh
);
545 ok(hr
== S_OK
, "got %#x\n", hr
);
548 IDirectorySearch_Release(ds
);
549 IDirectoryObject_Release(dirobj
);
556 hr
= CoInitialize(NULL
);
557 ok(hr
== S_OK
, "got %#x\n", hr
);
560 test_ParseDisplayName();
561 test_DirectorySearch();
562 test_DirectoryObject();