mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / adsldp / tests / ldap.c
blobfe9801a3972d3a6d16dc781c65e40b9914968d7b
1 /*
2 * LDAPNamespace Tests
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
29 #include "iads.h"
30 #include "adserr.h"
31 #include "adshlp.h"
33 #include "wine/test.h"
35 #include "initguid.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);
40 static const struct
42 const WCHAR *path;
43 HRESULT hr, hr_ads_open, hr_ads_get;
44 const WCHAR *user, *password;
45 LONG flags;
46 } test[] =
48 { L"invalid", MK_E_SYNTAX, E_ADS_BAD_PATHNAME, E_FAIL },
49 { L"LDAP", MK_E_SYNTAX, E_ADS_BAD_PATHNAME, E_FAIL },
50 { L"LDAP:", S_OK },
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)
69 HRESULT hr;
70 IUnknown *unk;
71 IADs *ads;
72 IADsOpenDSObject *ads_open;
73 IDispatch *disp;
74 BSTR path, user, password;
75 int i;
77 hr = CoCreateInstance(&CLSID_LDAPNamespace, 0, CLSCTX_INPROC_SERVER, &IID_IADs, (void **)&ads);
78 ok(hr == S_OK, "got %#x\n", hr);
79 IADs_Release(ads);
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))
100 SysFreeString(path);
101 skip("server is down\n");
102 break;
104 ok(hr == test[i].hr || hr == test[i].hr_ads_open, "%d: got %#x, expected %#x\n", i, hr, test[i].hr);
105 if (hr == S_OK)
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))
111 SysFreeString(path);
112 skip("server is down\n");
113 break;
115 ok(hr == test[i].hr || hr == test[i].hr_ads_get, "%d: got %#x, expected %#x\n", i, hr, test[i].hr);
116 if (hr == S_OK)
117 IADs_Release(ads);
119 hr = ADsGetObject(path, &IID_IDispatch, (void **)&disp);
120 if (hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN))
122 SysFreeString(path);
123 skip("server is down\n");
124 break;
126 ok(hr == test[i].hr || hr == test[i].hr_ads_get, "%d: got %#x, expected %#x\n", i, hr, test[i].hr);
127 if (hr == S_OK)
128 IDispatch_Release(disp);
130 SysFreeString(path);
131 SysFreeString(user);
132 SysFreeString(password);
136 IADsOpenDSObject_Release(ads_open);
137 IUnknown_Release(unk);
140 static void test_ParseDisplayName(void)
142 HRESULT hr;
143 IBindCtx *bc;
144 IParseDisplayName *parse;
145 IMoniker *mk;
146 IUnknown *unk;
147 CLSID clsid;
148 BSTR path;
149 ULONG count;
150 int i;
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);
169 count = 0xdeadbeef;
170 hr = IParseDisplayName_ParseDisplayName(parse, bc, path, &count, &mk);
171 if (hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN))
173 SysFreeString(path);
174 skip("server is down\n");
175 break;
177 ok(hr == test[i].hr || hr == test[i].hr_ads_open, "%d: got %#x, expected %#x\n", i, hr, test[i].hr);
178 if (hr == S_OK)
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);
189 SysFreeString(path);
191 count = 0xdeadbeef;
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);
195 if (hr == S_OK)
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);
211 struct result
213 const WCHAR *name;
214 ADSTYPEENUM type;
215 const WCHAR *values[16];
218 struct search
220 const WCHAR *dn;
221 ADS_SCOPEENUM scope;
222 struct result res[16];
225 static void do_search(const struct search *s)
227 HRESULT hr;
228 IDirectorySearch *ds;
229 ADS_SEARCHPREF_INFO pref;
230 ADS_SEARCH_HANDLE sh;
231 ADS_SEARCH_COLUMN col;
232 LPWSTR name;
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");
241 return;
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);
256 res = s->res;
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)
264 DWORD i;
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);
290 FreeADsMem(name);
291 res++;
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 } },
311 { 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 } },
325 { 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 } },
344 { NULL }
347 HRESULT hr;
348 IDirectorySearch *ds;
349 ADS_SEARCHPREF_INFO pref;
350 ADS_SEARCH_HANDLE sh;
351 ADS_SEARCH_COLUMN col;
352 LPWSTR name;
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");
361 return;
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");
369 return;
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);
397 todo_wine
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)
404 DWORD i;
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);
412 printf("{ ");
413 for (i = 0; i < col.dwNumValues; i++)
414 printf("%s, ", wine_dbgstr_w(col.pADsValues[i].CaseIgnoreString));
415 printf("NULL }\n");
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);
431 name = NULL;
432 hr = IDirectorySearch_GetNextColumnName(ds, sh, &name);
433 todo_wine
434 ok(hr == S_OK || broken(hr == S_ADS_NOMORE_COLUMNS) /* XP */, "got %#x\n", hr);
435 todo_wine
436 ok((name && !wcscmp(name, L"ADsPath")) || broken(!name) /* XP */, "got %s\n", wine_dbgstr_w(name));
437 FreeADsMem(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)
474 HRESULT hr;
475 IDirectoryObject *dirobj;
476 IUnknown *unk;
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");
486 return;
488 ok(hr == S_OK, "got %#x\n", hr);
490 hr = IDirectoryObject_QueryInterface(dirobj, &IID_IADsOpenDSObject, (void **)&unk);
491 todo_wine
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);
539 if (hr == S_OK)
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);
552 START_TEST(ldap)
554 HRESULT hr;
556 hr = CoInitialize(NULL);
557 ok(hr == S_OK, "got %#x\n", hr);
559 test_LDAP();
560 test_ParseDisplayName();
561 test_DirectorySearch();
562 test_DirectoryObject();
564 CoUninitialize();