+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
+<group>
<module name="advapi32_winetest" type="win32cui" installbase="bin" installname="advapi32_winetest.exe" allowwarnings="true">
<include base="advapi32_winetest">.</include>
<define name="__USE_W32API" />
<library>advapi32</library>
<library>kernel32</library>
<library>ntdll</library>
+ <library>uuid</library>
+ <library>ole32</library>
+ <file>cred.c</file>
+ <file>crypt.c</file>
+ <file>crypt_lmhash.c</file>
+ <file>crypt_md4.c</file>
+ <file>crypt_md5.c</file>
+ <file>crypt_sha.c</file>
+ <file>lsa.c</file>
<file>registry.c</file>
<file>security.c</file>
+ <file>service.c</file>
<file>testlist.c</file>
</module>
+</group>
--- /dev/null
+/*
+ * Credential Function Tests
+ *
+ * Copyright 2007 Robert Shearman
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wincred.h"
+
+#include "wine/test.h"
+
+static BOOL (WINAPI *pCredDeleteA)(LPCSTR,DWORD,DWORD);
+static BOOL (WINAPI *pCredEnumerateA)(LPCSTR,DWORD,DWORD *,PCREDENTIALA **);
+static VOID (WINAPI *pCredFree)(PVOID);
+static BOOL (WINAPI *pCredGetSessionTypes)(DWORD,LPDWORD);
+static BOOL (WINAPI *pCredReadA)(LPCSTR,DWORD,DWORD,PCREDENTIALA *);
+static BOOL (WINAPI *pCredRenameA)(LPCSTR,LPCSTR,DWORD,DWORD);
+static BOOL (WINAPI *pCredWriteA)(PCREDENTIALA,DWORD);
+
+#define TEST_TARGET_NAME "credtest.winehq.org"
+#define TEST_TARGET_NAME2 "credtest2.winehq.org"
+static const WCHAR TEST_PASSWORD[] = {'p','4','$','$','w','0','r','d','!',0};
+
+static void test_CredReadA(void)
+{
+ BOOL ret;
+ PCREDENTIALA cred;
+
+ SetLastError(0xdeadbeef);
+ ret = pCredReadA(TEST_TARGET_NAME, -1, 0, &cred);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "CredReadA should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
+ GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pCredReadA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0xdeadbeef, &cred);
+ ok(!ret && ( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER ),
+ "CredReadA should have failed with ERROR_INVALID_FLAGS or ERROR_INVALID_PARAMETER instead of %d\n",
+ GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pCredReadA(NULL, CRED_TYPE_GENERIC, 0, &cred);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "CredReadA should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
+ GetLastError());
+}
+
+static void test_CredWriteA(void)
+{
+ CREDENTIALA new_cred;
+ BOOL ret;
+
+ SetLastError(0xdeadbeef);
+ ret = pCredWriteA(NULL, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "CredWriteA should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
+ GetLastError());
+
+ new_cred.Flags = 0;
+ new_cred.Type = CRED_TYPE_GENERIC;
+ new_cred.TargetName = NULL;
+ new_cred.Comment = (char *)"Comment";
+ new_cred.CredentialBlobSize = 0;
+ new_cred.CredentialBlob = NULL;
+ new_cred.Persist = CRED_PERSIST_ENTERPRISE;
+ new_cred.AttributeCount = 0;
+ new_cred.Attributes = NULL;
+ new_cred.TargetAlias = NULL;
+ new_cred.UserName = (char *)"winetest";
+
+ SetLastError(0xdeadbeef);
+ ret = pCredWriteA(&new_cred, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "CredWriteA should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
+ GetLastError());
+
+ new_cred.TargetName = (char *)TEST_TARGET_NAME;
+ new_cred.Type = CRED_TYPE_DOMAIN_PASSWORD;
+
+ SetLastError(0xdeadbeef);
+ ret = pCredWriteA(&new_cred, 0);
+ ok(!ret && ( GetLastError() == ERROR_BAD_USERNAME || GetLastError() == ERROR_NO_SUCH_LOGON_SESSION /* Vista */ ),
+ "CredWrite with username without domain should return ERROR_BAD_USERNAME or ERROR_NO_SUCH_LOGON_SESSION not %d\n", GetLastError());
+
+ new_cred.UserName = NULL;
+ SetLastError(0xdeadbeef);
+ ret = pCredWriteA(&new_cred, 0);
+ ok(!ret && GetLastError() == ERROR_BAD_USERNAME,
+ "CredWriteA with NULL username should have failed with ERROR_BAD_USERNAME instead of %d\n",
+ GetLastError());
+}
+
+static void test_CredDeleteA(void)
+{
+ BOOL ret;
+
+ SetLastError(0xdeadbeef);
+ ret = pCredDeleteA(TEST_TARGET_NAME, -1, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "CredDeleteA should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
+ GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pCredDeleteA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0xdeadbeef);
+ ok(!ret && ( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER /* Vista */ ),
+ "CredDeleteA should have failed with ERROR_INVALID_FLAGS or ERROR_INVALID_PARAMETER instead of %d\n",
+ GetLastError());
+}
+
+static void check_blob(int line, DWORD cred_type, PCREDENTIALA cred)
+{
+ if (cred_type == CRED_TYPE_DOMAIN_PASSWORD)
+ {
+ todo_wine
+ ok_(__FILE__, line)(cred->CredentialBlobSize == 0, "expected CredentialBlobSize of 0 but got %d\n", cred->CredentialBlobSize);
+ todo_wine
+ ok_(__FILE__, line)(!cred->CredentialBlob, "expected NULL credentials but got %p\n", cred->CredentialBlob);
+ }
+ else
+ {
+ DWORD size=sizeof(TEST_PASSWORD);
+ ok_(__FILE__, line)(cred->CredentialBlobSize == size, "expected CredentialBlobSize of %u but got %u\n", size, cred->CredentialBlobSize);
+ ok_(__FILE__, line)(cred->CredentialBlob != NULL, "CredentialBlob should be present\n");
+ if (cred->CredentialBlob)
+ ok_(__FILE__, line)(!memcmp(cred->CredentialBlob, TEST_PASSWORD, size), "wrong CredentialBlob\n");
+ }
+}
+
+static void test_generic(void)
+{
+ BOOL ret;
+ DWORD count, i;
+ PCREDENTIALA *creds;
+ CREDENTIALA new_cred;
+ PCREDENTIALA cred;
+ BOOL found = FALSE;
+
+ new_cred.Flags = 0;
+ new_cred.Type = CRED_TYPE_GENERIC;
+ new_cred.TargetName = (char *)TEST_TARGET_NAME;
+ new_cred.Comment = (char *)"Comment";
+ new_cred.CredentialBlobSize = sizeof(TEST_PASSWORD);
+ new_cred.CredentialBlob = (LPBYTE)TEST_PASSWORD;
+ new_cred.Persist = CRED_PERSIST_ENTERPRISE;
+ new_cred.AttributeCount = 0;
+ new_cred.Attributes = NULL;
+ new_cred.TargetAlias = NULL;
+ new_cred.UserName = (char *)"winetest";
+
+ ret = pCredWriteA(&new_cred, 0);
+ ok(ret, "CredWriteA failed with error %d\n", GetLastError());
+
+ ret = pCredEnumerateA(NULL, 0, &count, &creds);
+ ok(ret, "CredEnumerateA failed with error %d\n", GetLastError());
+
+ for (i = 0; i < count; i++)
+ {
+ if (!strcmp(creds[i]->TargetName, TEST_TARGET_NAME))
+ {
+ ok(creds[i]->Type == CRED_TYPE_GENERIC, "expected creds[%d]->Type CRED_TYPE_GENERIC but got %d\n", i, creds[i]->Type);
+ ok(!creds[i]->Flags, "expected creds[%d]->Flags 0 but got 0x%x\n", i, creds[i]->Flags);
+ ok(!strcmp(creds[i]->Comment, "Comment"), "expected creds[%d]->Comment \"Comment\" but got \"%s\"\n", i, creds[i]->Comment);
+ check_blob(__LINE__, CRED_TYPE_GENERIC, creds[i]);
+ ok(creds[i]->Persist, "expected creds[%d]->Persist CRED_PERSIST_ENTERPRISE but got %d\n", i, creds[i]->Persist);
+ ok(!strcmp(creds[i]->UserName, "winetest"), "expected creds[%d]->UserName \"winetest\" but got \"%s\"\n", i, creds[i]->UserName);
+ found = TRUE;
+ }
+ }
+ pCredFree(creds);
+ ok(found, "credentials not found\n");
+
+ ret = pCredReadA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0, &cred);
+ ok(ret, "CredReadA failed with error %d\n", GetLastError());
+ pCredFree(cred);
+
+ ret = pCredDeleteA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0);
+ ok(ret, "CredDeleteA failed with error %d\n", GetLastError());
+}
+
+static void test_domain_password(DWORD cred_type)
+{
+ BOOL ret;
+ DWORD count, i;
+ PCREDENTIALA *creds;
+ CREDENTIALA new_cred;
+ PCREDENTIALA cred;
+ BOOL found = FALSE;
+
+ new_cred.Flags = 0;
+ new_cred.Type = cred_type;
+ new_cred.TargetName = (char *)TEST_TARGET_NAME;
+ new_cred.Comment = (char *)"Comment";
+ new_cred.CredentialBlobSize = sizeof(TEST_PASSWORD);
+ new_cred.CredentialBlob = (LPBYTE)TEST_PASSWORD;
+ new_cred.Persist = CRED_PERSIST_ENTERPRISE;
+ new_cred.AttributeCount = 0;
+ new_cred.Attributes = NULL;
+ new_cred.TargetAlias = NULL;
+ new_cred.UserName = (char *)"test\\winetest";
+ ret = pCredWriteA(&new_cred, 0);
+ ok(ret, "CredWriteA failed with error %d\n", GetLastError());
+
+ ret = pCredEnumerateA(NULL, 0, &count, &creds);
+ ok(ret, "CredEnumerateA failed with error %d\n", GetLastError());
+
+ for (i = 0; i < count; i++)
+ {
+ if (!strcmp(creds[i]->TargetName, TEST_TARGET_NAME))
+ {
+ ok(creds[i]->Type == cred_type, "expected creds[%d]->Type CRED_TYPE_DOMAIN_PASSWORD but got %d\n", i, creds[i]->Type);
+ ok(!creds[i]->Flags, "expected creds[%d]->Flags 0 but got 0x%x\n", i, creds[i]->Flags);
+ ok(!strcmp(creds[i]->Comment, "Comment"), "expected creds[%d]->Comment \"Comment\" but got \"%s\"\n", i, creds[i]->Comment);
+ check_blob(__LINE__, cred_type, creds[i]);
+ ok(creds[i]->Persist, "expected creds[%d]->Persist CRED_PERSIST_ENTERPRISE but got %d\n", i, creds[i]->Persist);
+ ok(!strcmp(creds[i]->UserName, "test\\winetest"), "expected creds[%d]->UserName \"winetest\" but got \"%s\"\n", i, creds[i]->UserName);
+ found = TRUE;
+ }
+ }
+ pCredFree(creds);
+ ok(found, "credentials not found\n");
+
+ ret = pCredReadA(TEST_TARGET_NAME, cred_type, 0, &cred);
+ ok(ret, "CredReadA failed with error %d\n", GetLastError());
+ if (ret) /* don't check the values of cred, if CredReadA failed. */
+ {
+ check_blob(__LINE__, cred_type, cred);
+ pCredFree(cred);
+ }
+
+ ret = pCredDeleteA(TEST_TARGET_NAME, cred_type, 0);
+ ok(ret, "CredDeleteA failed with error %d\n", GetLastError());
+}
+
+START_TEST(cred)
+{
+ DWORD persists[CRED_TYPE_MAXIMUM];
+
+ pCredEnumerateA = (void *)GetProcAddress(GetModuleHandle("advapi32.dll"), "CredEnumerateA");
+ pCredFree = (void *)GetProcAddress(GetModuleHandle("advapi32.dll"), "CredFree");
+ pCredGetSessionTypes = (void *)GetProcAddress(GetModuleHandle("advapi32.dll"), "CredGetSessionTypes");
+ pCredWriteA = (void *)GetProcAddress(GetModuleHandle("advapi32.dll"), "CredWriteA");
+ pCredDeleteA = (void *)GetProcAddress(GetModuleHandle("advapi32.dll"), "CredDeleteA");
+ pCredReadA = (void *)GetProcAddress(GetModuleHandle("advapi32.dll"), "CredReadA");
+ pCredRenameA = (void *)GetProcAddress(GetModuleHandle("advapi32.dll"), "CredRenameA");
+
+ if (!pCredEnumerateA || !pCredFree || !pCredWriteA || !pCredDeleteA ||
+ !pCredReadA)
+ {
+ skip("credentials functions not present in advapi32.dll\n");
+ return;
+ }
+
+ if (pCredGetSessionTypes)
+ {
+ BOOL ret;
+ DWORD i;
+ ret = pCredGetSessionTypes(CRED_TYPE_MAXIMUM, persists);
+ ok(ret, "CredGetSessionTypes failed with error %d\n", GetLastError());
+ ok(persists[0] == CRED_PERSIST_NONE, "persists[0] = %u instead of CRED_PERSIST_NONE\n", persists[0]);
+ for (i=0; i < CRED_TYPE_MAXIMUM; i++)
+ ok(persists[i] <= CRED_PERSIST_ENTERPRISE, "bad value for persists[%u]: %u\n", i, persists[i]);
+ }
+ else
+ memset(persists, CRED_PERSIST_ENTERPRISE, sizeof(persists));
+
+ test_CredReadA();
+ test_CredWriteA();
+ test_CredDeleteA();
+
+ trace("generic:\n");
+ if (persists[CRED_TYPE_GENERIC] == CRED_PERSIST_NONE)
+ skip("CRED_TYPE_GENERIC credentials are not supported or are disabled. Skipping\n");
+ else
+ test_generic();
+
+ trace("domain password:\n");
+ if (persists[CRED_TYPE_DOMAIN_PASSWORD] == CRED_PERSIST_NONE)
+ skip("CRED_TYPE_DOMAIN_PASSWORD credentials are not supported or are disabled. Skipping\n");
+ else
+ test_domain_password(CRED_TYPE_DOMAIN_PASSWORD);
+
+ trace("domain visible password:\n");
+ if (persists[CRED_TYPE_DOMAIN_VISIBLE_PASSWORD] == CRED_PERSIST_NONE)
+ skip("CRED_TYPE_DOMAIN_VISIBLE_PASSWORD credentials are not supported or are disabled. Skipping\n");
+ else
+ test_domain_password(CRED_TYPE_DOMAIN_VISIBLE_PASSWORD);
+}
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
static const char szBadKeySet[] = "wine_test_bad_keyset";
#define NON_DEF_PROV_TYPE 999
-static HMODULE hadvapi32;
static BOOL (WINAPI *pCryptAcquireContextA)(HCRYPTPROV*,LPCSTR,LPCSTR,DWORD,DWORD);
static BOOL (WINAPI *pCryptEnumProviderTypesA)(DWORD, DWORD*, DWORD, DWORD*, LPSTR, DWORD*);
static BOOL (WINAPI *pCryptEnumProvidersA)(DWORD, DWORD*, DWORD, DWORD*, LPSTR, DWORD*);
static void init_function_pointers(void)
{
- hadvapi32 = GetModuleHandleA("advapi32.dll");
-
- if(hadvapi32)
- {
- pCryptAcquireContextA = (void*)GetProcAddress(hadvapi32, "CryptAcquireContextA");
- pCryptEnumProviderTypesA = (void*)GetProcAddress(hadvapi32, "CryptEnumProviderTypesA");
- pCryptEnumProvidersA = (void*)GetProcAddress(hadvapi32, "CryptEnumProvidersA");
- pCryptGetDefaultProviderA = (void*)GetProcAddress(hadvapi32, "CryptGetDefaultProviderA");
- pCryptReleaseContext = (void*)GetProcAddress(hadvapi32, "CryptReleaseContext");
- pCryptSetProviderExA = (void*)GetProcAddress(hadvapi32, "CryptSetProviderExA");
- pCryptCreateHash = (void*)GetProcAddress(hadvapi32, "CryptCreateHash");
- pCryptDestroyHash = (void*)GetProcAddress(hadvapi32, "CryptDestroyHash");
- pCryptGenRandom = (void*)GetProcAddress(hadvapi32, "CryptGenRandom");
- pCryptContextAddRef = (void*)GetProcAddress(hadvapi32, "CryptContextAddRef");
- pCryptGenKey = (void*)GetProcAddress(hadvapi32, "CryptGenKey");
- pCryptDestroyKey = (void*)GetProcAddress(hadvapi32, "CryptDestroyKey");
- pCryptDecrypt = (void*)GetProcAddress(hadvapi32, "CryptDecrypt");
- pCryptDeriveKey = (void*)GetProcAddress(hadvapi32, "CryptDeriveKey");
- pCryptDuplicateHash = (void*)GetProcAddress(hadvapi32, "CryptDuplicateHash");
- pCryptDuplicateKey = (void*)GetProcAddress(hadvapi32, "CryptDuplicateKey");
- pCryptEncrypt = (void*)GetProcAddress(hadvapi32, "CryptEncrypt");
- pCryptExportKey = (void*)GetProcAddress(hadvapi32, "CryptExportKey");
- pCryptGetHashParam = (void*)GetProcAddress(hadvapi32, "CryptGetHashParam");
- pCryptGetKeyParam = (void*)GetProcAddress(hadvapi32, "CryptGetKeyParam");
- pCryptGetProvParam = (void*)GetProcAddress(hadvapi32, "CryptGetProvParam");
- pCryptGetUserKey = (void*)GetProcAddress(hadvapi32, "CryptGetUserKey");
- pCryptHashData = (void*)GetProcAddress(hadvapi32, "CryptHashData");
- pCryptHashSessionKey = (void*)GetProcAddress(hadvapi32, "CryptHashSessionKey");
- pCryptImportKey = (void*)GetProcAddress(hadvapi32, "CryptImportKey");
- pCryptSignHashW = (void*)GetProcAddress(hadvapi32, "CryptSignHashW");
- pCryptSetHashParam = (void*)GetProcAddress(hadvapi32, "CryptSetHashParam");
- pCryptSetKeyParam = (void*)GetProcAddress(hadvapi32, "CryptSetKeyParam");
- pCryptSetProvParam = (void*)GetProcAddress(hadvapi32, "CryptSetProvParam");
- pCryptVerifySignatureW = (void*)GetProcAddress(hadvapi32, "CryptVerifySignatureW");
- }
+ HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
+
+ pCryptAcquireContextA = (void*)GetProcAddress(hadvapi32, "CryptAcquireContextA");
+ pCryptEnumProviderTypesA = (void*)GetProcAddress(hadvapi32, "CryptEnumProviderTypesA");
+ pCryptEnumProvidersA = (void*)GetProcAddress(hadvapi32, "CryptEnumProvidersA");
+ pCryptGetDefaultProviderA = (void*)GetProcAddress(hadvapi32, "CryptGetDefaultProviderA");
+ pCryptReleaseContext = (void*)GetProcAddress(hadvapi32, "CryptReleaseContext");
+ pCryptSetProviderExA = (void*)GetProcAddress(hadvapi32, "CryptSetProviderExA");
+ pCryptCreateHash = (void*)GetProcAddress(hadvapi32, "CryptCreateHash");
+ pCryptDestroyHash = (void*)GetProcAddress(hadvapi32, "CryptDestroyHash");
+ pCryptGenRandom = (void*)GetProcAddress(hadvapi32, "CryptGenRandom");
+ pCryptContextAddRef = (void*)GetProcAddress(hadvapi32, "CryptContextAddRef");
+ pCryptGenKey = (void*)GetProcAddress(hadvapi32, "CryptGenKey");
+ pCryptDestroyKey = (void*)GetProcAddress(hadvapi32, "CryptDestroyKey");
+ pCryptDecrypt = (void*)GetProcAddress(hadvapi32, "CryptDecrypt");
+ pCryptDeriveKey = (void*)GetProcAddress(hadvapi32, "CryptDeriveKey");
+ pCryptDuplicateHash = (void*)GetProcAddress(hadvapi32, "CryptDuplicateHash");
+ pCryptDuplicateKey = (void*)GetProcAddress(hadvapi32, "CryptDuplicateKey");
+ pCryptEncrypt = (void*)GetProcAddress(hadvapi32, "CryptEncrypt");
+ pCryptExportKey = (void*)GetProcAddress(hadvapi32, "CryptExportKey");
+ pCryptGetHashParam = (void*)GetProcAddress(hadvapi32, "CryptGetHashParam");
+ pCryptGetKeyParam = (void*)GetProcAddress(hadvapi32, "CryptGetKeyParam");
+ pCryptGetProvParam = (void*)GetProcAddress(hadvapi32, "CryptGetProvParam");
+ pCryptGetUserKey = (void*)GetProcAddress(hadvapi32, "CryptGetUserKey");
+ pCryptHashData = (void*)GetProcAddress(hadvapi32, "CryptHashData");
+ pCryptHashSessionKey = (void*)GetProcAddress(hadvapi32, "CryptHashSessionKey");
+ pCryptImportKey = (void*)GetProcAddress(hadvapi32, "CryptImportKey");
+ pCryptSignHashW = (void*)GetProcAddress(hadvapi32, "CryptSignHashW");
+ pCryptSetHashParam = (void*)GetProcAddress(hadvapi32, "CryptSetHashParam");
+ pCryptSetKeyParam = (void*)GetProcAddress(hadvapi32, "CryptSetKeyParam");
+ pCryptSetProvParam = (void*)GetProcAddress(hadvapi32, "CryptSetProvParam");
+ pCryptVerifySignatureW = (void*)GetProcAddress(hadvapi32, "CryptVerifySignatureW");
}
static void init_environment(void)
{
HCRYPTPROV hProv;
-
+
/* Ensure that container "wine_test_keyset" does exist */
if (!pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0))
{
{
BOOL result;
HCRYPTPROV hProv;
+ DWORD GLE;
- /* Provoke all kinds of error conditions (which are easy to provoke).
+ /* Provoke all kinds of error conditions (which are easy to provoke).
* The order of the error tests seems to match Windows XP's rsaenh.dll CSP,
* but since this is likely to change between CSP versions, we don't check
* this. Please don't change the order of tests. */
result = pCryptAcquireContextA(&hProv, NULL, NULL, 0, 0);
- ok(!result && GetLastError()==NTE_BAD_PROV_TYPE, "%ld\n", GetLastError());
-
+ ok(!result && GetLastError()==NTE_BAD_PROV_TYPE, "%d\n", GetLastError());
+
result = pCryptAcquireContextA(&hProv, NULL, NULL, 1000, 0);
- ok(!result && GetLastError()==NTE_BAD_PROV_TYPE, "%ld\n", GetLastError());
+ ok(!result && GetLastError()==NTE_BAD_PROV_TYPE, "%d\n", GetLastError());
result = pCryptAcquireContextA(&hProv, NULL, NULL, NON_DEF_PROV_TYPE, 0);
- ok(!result && GetLastError()==NTE_PROV_TYPE_NOT_DEF, "%ld\n", GetLastError());
-
+ ok(!result && GetLastError()==NTE_PROV_TYPE_NOT_DEF, "%d\n", GetLastError());
+
result = pCryptAcquireContextA(&hProv, szKeySet, szNonExistentProv, PROV_RSA_FULL, 0);
- ok(!result && GetLastError()==NTE_KEYSET_NOT_DEF, "%ld\n", GetLastError());
+ ok(!result && GetLastError()==NTE_KEYSET_NOT_DEF, "%d\n", GetLastError());
result = pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, NON_DEF_PROV_TYPE, 0);
- ok(!result && GetLastError()==NTE_PROV_TYPE_NO_MATCH, "%ld\n", GetLastError());
-
+ ok(!result && GetLastError()==NTE_PROV_TYPE_NO_MATCH, "%d\n", GetLastError());
+
/* This test fails under Win2k SP4:
result = TRUE, GetLastError() == ERROR_INVALID_PARAMETER
SetLastError(0xdeadbeef);
result = pCryptAcquireContextA(NULL, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0);
- ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%d/%ld\n", result, GetLastError());
+ ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%d/%d\n", result, GetLastError());
*/
-
+
/* Last not least, try to really acquire a context. */
hProv = 0;
SetLastError(0xdeadbeef);
result = pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0);
- ok(result && (GetLastError() == ERROR_ENVVAR_NOT_FOUND || GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_RING2_STACK_IN_USE || GetLastError() == NTE_FAIL), "%d/%ld\n", result, GetLastError());
-
- if (hProv)
+ GLE = GetLastError();
+ ok(result && (GLE == ERROR_ENVVAR_NOT_FOUND ||
+ GLE == ERROR_SUCCESS ||
+ GLE == ERROR_RING2_STACK_IN_USE ||
+ GLE == NTE_FAIL ||
+ GLE == ERROR_NOT_LOGGED_ON), "%d/%d\n", result, GLE);
+
+ if (hProv)
pCryptReleaseContext(hProv, 0);
/* Try again, witch an empty ("\0") szProvider parameter */
hProv = 0;
SetLastError(0xdeadbeef);
result = pCryptAcquireContextA(&hProv, szKeySet, "", PROV_RSA_FULL, 0);
- ok(result && (GetLastError() == ERROR_ENVVAR_NOT_FOUND || GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_RING2_STACK_IN_USE || GetLastError() == NTE_FAIL), "%d/%ld\n", result, GetLastError());
-
- if (hProv)
+ GLE = GetLastError();
+ ok(result && (GLE == ERROR_ENVVAR_NOT_FOUND ||
+ GLE == ERROR_SUCCESS ||
+ GLE == ERROR_RING2_STACK_IN_USE ||
+ GLE == NTE_FAIL ||
+ GLE == ERROR_NOT_LOGGED_ON), "%d/%d\n", result, GetLastError());
+
+ if (hProv)
pCryptReleaseContext(hProv, 0);
}
BYTE temp;
DWORD dwLen, dwTemp;
- /* This is to document incorrect api usage in the
+ /* This is to document incorrect api usage in the
* "Uru - Ages beyond Myst Demo" installer as reported by Paul Vriens.
*
- * The installer destroys a hash object after having released the context
- * with which the hash was created. This is not allowed according to MSDN,
- * since CryptReleaseContext destroys all hash and key objects belonging to
- * the respective context. However, while wine used to crash, Windows is more
+ * The installer destroys a hash object after having released the context
+ * with which the hash was created. This is not allowed according to MSDN,
+ * since CryptReleaseContext destroys all hash and key objects belonging to
+ * the respective context. However, while wine used to crash, Windows is more
* robust here and returns an ERROR_INVALID_PARAMETER code.
*/
-
- result = pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv,
+
+ result = pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
- ok (result, "%08lx\n", GetLastError());
+ ok (result, "%08x\n", GetLastError());
if (!result) return;
result = pCryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
- ok (result, "%ld\n", GetLastError());
+ ok (result, "%d\n", GetLastError());
if (!result) return;
result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey);
- ok (result, "%ld\n", GetLastError());
+ ok (result, "%d\n", GetLastError());
if (!result) return;
result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey2);
- ok (result, "%ld\n", GetLastError());
+ ok (result, "%d\n", GetLastError());
if (!result) return;
result = pCryptDestroyKey(hKey2);
- ok (result, "%ld\n", GetLastError());
+ ok (result, "%d\n", GetLastError());
- dwTemp = CRYPT_MODE_ECB;
+ dwTemp = CRYPT_MODE_ECB;
result = pCryptSetKeyParam(hKey2, KP_MODE, (BYTE*)&dwTemp, sizeof(DWORD));
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
-
- result = pCryptAcquireContextA(&hProv2, szBadKeySet, NULL, PROV_RSA_FULL,
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
+
+ result = pCryptAcquireContextA(&hProv2, szBadKeySet, NULL, PROV_RSA_FULL,
CRYPT_DELETEKEYSET);
- ok (result, "%ld\n", GetLastError());
+ ok (result, "%d\n", GetLastError());
if (!result) return;
-
+
result = pCryptReleaseContext(hProv, 0);
- ok (result, "%ld\n", GetLastError());
+ ok (result, "%d\n", GetLastError());
if (!result) return;
result = pCryptReleaseContext(hProv, 0);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptGenRandom(hProv, 1, &temp);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
#ifdef CRASHES_ON_NT40
result = pCryptContextAddRef(hProv, NULL, 0);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
#endif
result = pCryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash2);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
dwLen = 1;
result = pCryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, &temp, &dwLen);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
dwLen = 1;
result = pCryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, &temp, &dwLen, 1);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey2);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
#ifdef CRASHES_ON_NT40
result = pCryptDuplicateHash(hHash, NULL, 0, &hHash2);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptDuplicateKey(hKey, NULL, 0, &hKey2);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
#endif
dwLen = 1;
result = pCryptExportKey(hKey, (HCRYPTPROV)NULL, 0, 0, &temp, &dwLen);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey2);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
dwLen = 1;
result = pCryptGetHashParam(hHash, 0, &temp, &dwLen, 0);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
dwLen = 1;
result = pCryptGetKeyParam(hKey, 0, &temp, &dwLen, 0);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
dwLen = 1;
result = pCryptGetProvParam(hProv, 0, &temp, &dwLen, 0);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
-
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
+
result = pCryptGetUserKey(hProv, 0, &hKey2);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptHashData(hHash, &temp, 1, 0);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptHashSessionKey(hHash, hKey, 0);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptImportKey(hProv, &temp, 1, (HCRYPTKEY)NULL, 0, &hKey2);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
- dwLen = 1;
- result = pCryptSignHashW(hHash, 0, NULL, 0, &temp, &dwLen);
- ok (!result && (GetLastError() == ERROR_INVALID_PARAMETER ||
- GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "%ld\n", GetLastError());
+ if (pCryptSignHashW)
+ {
+ dwLen = 1;
+ result = pCryptSignHashW(hHash, 0, NULL, 0, &temp, &dwLen);
+ ok (!result && (GetLastError() == ERROR_INVALID_PARAMETER ||
+ GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "%d\n", GetLastError());
+ }
+ else
+ skip("CryptSignHashW is not available\n");
result = pCryptSetKeyParam(hKey, 0, &temp, 1);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptSetHashParam(hHash, 0, &temp, 1);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptSetProvParam(hProv, 0, &temp, 1);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
- result = pCryptVerifySignatureW(hHash, &temp, 1, hKey, NULL, 0);
- ok (!result && (GetLastError() == ERROR_INVALID_PARAMETER ||
- GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "%ld\n", GetLastError());
+ if (pCryptVerifySignatureW)
+ {
+ result = pCryptVerifySignatureW(hHash, &temp, 1, hKey, NULL, 0);
+ ok (!result && (GetLastError() == ERROR_INVALID_PARAMETER ||
+ GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "%d\n", GetLastError());
+ }
+ else
+ skip("CryptVerifySignatureW is not available\n");
result = pCryptDestroyHash(hHash);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
-
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
+
result = pCryptDestroyKey(hKey);
- ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
}
-static BOOL FindProvRegVals(DWORD dwIndex, DWORD *pdwProvType, LPSTR *pszProvName,
+static const BYTE privKey[] = {
+ 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
+ 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
+ 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
+ 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
+ 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
+ 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
+ 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
+ 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
+ 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
+ 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
+ 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
+ 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
+ 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
+ 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
+ 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
+ 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
+ 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
+ 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
+ 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
+ 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
+ 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
+ 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
+ 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
+ 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
+
+static void test_verify_sig(void)
+{
+ BOOL ret;
+ HCRYPTPROV prov;
+ HCRYPTKEY key;
+ HCRYPTHASH hash;
+ BYTE bogus[] = { 0 };
+
+ if (!pCryptVerifySignatureW)
+ {
+ skip("CryptVerifySignatureW is not available\n");
+ return;
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = pCryptVerifySignatureW(0, NULL, 0, 0, NULL, 0);
+ if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("CryptVerifySignatureW is not implemented\n");
+ return;
+ }
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ ret = pCryptAcquireContextA(&prov, szKeySet, NULL, PROV_RSA_FULL,
+ CRYPT_NEWKEYSET);
+ if (!ret && GetLastError() == NTE_EXISTS)
+ ret = pCryptAcquireContextA(&prov, szKeySet, NULL, PROV_RSA_FULL, 0);
+ ret = pCryptImportKey(prov, (LPBYTE)privKey, sizeof(privKey), 0, 0, &key);
+ ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
+ ret = pCryptCreateHash(prov, CALG_MD5, 0, 0, &hash);
+ ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pCryptVerifySignatureW(hash, NULL, 0, 0, NULL, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pCryptVerifySignatureW(0, NULL, 0, key, NULL, 0);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pCryptVerifySignatureW(hash, NULL, 0, key, NULL, 0);
+ ok(!ret && (GetLastError() == NTE_BAD_SIGNATURE ||
+ GetLastError() == ERROR_INVALID_PARAMETER),
+ "Expected NTE_BAD_SIGNATURE or ERROR_INVALID_PARAMETER, got %08x\n",
+ GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pCryptVerifySignatureW(hash, NULL, sizeof(bogus), key, NULL, 0);
+ ok(!ret && (GetLastError() == NTE_BAD_SIGNATURE ||
+ GetLastError() == ERROR_INVALID_PARAMETER),
+ "Expected NTE_BAD_SIGNATURE or ERROR_INVALID_PARAMETER, got %08x\n",
+ GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pCryptVerifySignatureW(hash, bogus, 0, key, NULL, 0);
+ ok(!ret && GetLastError() == NTE_BAD_SIGNATURE,
+ "Expected NTE_BAD_SIGNATURE, got %08x\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = pCryptVerifySignatureW(hash, bogus, sizeof(bogus), key, NULL, 0);
+ ok(!ret && GetLastError() == NTE_BAD_SIGNATURE,
+ "Expected NTE_BAD_SIGNATURE, got %08x\n", GetLastError());
+ pCryptDestroyKey(key);
+ pCryptDestroyHash(hash);
+ pCryptReleaseContext(prov, 0);
+}
+
+static BOOL FindProvRegVals(DWORD dwIndex, DWORD *pdwProvType, LPSTR *pszProvName,
DWORD *pcbProvName, DWORD *pdwProvCount)
{
HKEY hKey;
HKEY subkey;
DWORD size = sizeof(DWORD);
-
+
if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider", &hKey))
return FALSE;
-
- RegQueryInfoKey(hKey, NULL, NULL, NULL, pdwProvCount, pcbProvName,
+
+ RegQueryInfoKey(hKey, NULL, NULL, NULL, pdwProvCount, pcbProvName,
NULL, NULL, NULL, NULL, NULL, NULL);
(*pcbProvName)++;
-
+
if (!(*pszProvName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, *pcbProvName))))
return FALSE;
-
+
RegEnumKeyEx(hKey, dwIndex, *pszProvName, pcbProvName, NULL, NULL, NULL, NULL);
(*pcbProvName)++;
RegOpenKey(hKey, *pszProvName, &subkey);
- RegQueryValueEx(subkey, "Type", NULL, NULL, (BYTE*)pdwProvType, &size);
-
+ RegQueryValueEx(subkey, "Type", NULL, NULL, (LPBYTE)pdwProvType, &size);
+
RegCloseKey(subkey);
RegCloseKey(hKey);
-
+
return TRUE;
}
DWORD dwType;
DWORD provCount;
DWORD dwIndex = 0;
-
+
/* actual results */
CHAR *provider = NULL;
DWORD providerLen;
DWORD type;
DWORD count;
- BOOL result;
+ DWORD result;
DWORD notNull = 5;
DWORD notZeroFlags = 5;
-
+
if(!pCryptEnumProvidersA)
{
- trace("skipping CryptEnumProviders tests\n");
+ skip("CryptEnumProvidersA is not available\n");
return;
}
-
+
if (!FindProvRegVals(dwIndex, &dwType, &pszProvName, &cbName, &provCount))
- return;
-
+ {
+ skip("Could not find providers in registry\n");
+ return;
+ }
+
/* check pdwReserved flag for NULL */
result = pCryptEnumProvidersA(dwIndex, ¬Null, 0, &type, NULL, &providerLen);
- ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
-
+ ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
+
/* check dwFlags == 0 */
result = pCryptEnumProvidersA(dwIndex, NULL, notZeroFlags, &type, NULL, &providerLen);
- ok(!result && GetLastError()==NTE_BAD_FLAGS, "%ld\n", GetLastError());
-
+ ok(!result && GetLastError()==NTE_BAD_FLAGS, "%d\n", GetLastError());
+
/* alloc provider to half the size required
* cbName holds the size required */
providerLen = cbName / 2;
return;
result = pCryptEnumProvidersA(dwIndex, NULL, 0, &type, provider, &providerLen);
- ok(!result && GetLastError()==ERROR_MORE_DATA, "expected %i, got %ld\n",
+ ok(!result && GetLastError()==ERROR_MORE_DATA, "expected %i, got %d\n",
ERROR_MORE_DATA, GetLastError());
LocalFree(provider);
- /* loop through the providers to get the number of providers
+ /* loop through the providers to get the number of providers
* after loop ends, count should be provCount + 1 so subtract 1
* to get actual number of providers */
count = 0;
;
count--;
ok(count==provCount, "expected %i, got %i\n", (int)provCount, (int)count);
-
+
/* loop past the actual number of providers to get the error
* ERROR_NO_MORE_ITEMS */
for (count = 0; count < provCount + 1; count++)
result = pCryptEnumProvidersA(count, NULL, 0, &type, NULL, &providerLen);
- ok(!result && GetLastError()==ERROR_NO_MORE_ITEMS, "expected %i, got %ld\n",
+ ok(!result && GetLastError()==ERROR_NO_MORE_ITEMS, "expected %i, got %d\n",
ERROR_NO_MORE_ITEMS, GetLastError());
-
+
/* check expected versus actual values returned */
result = pCryptEnumProvidersA(dwIndex, NULL, 0, &type, NULL, &providerLen);
ok(result && providerLen==cbName, "expected %i, got %i\n", (int)cbName, (int)providerLen);
if (!(provider = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, providerLen))))
return;
-
+
+ providerLen = 0xdeadbeef;
result = pCryptEnumProvidersA(dwIndex, NULL, 0, &type, provider, &providerLen);
- ok(result && type==dwType, "expected %ld, got %ld\n",
- dwType, type);
- ok(result && !strcmp(pszProvName, provider), "expected %s, got %s\n", pszProvName, provider);
- ok(result && cbName==providerLen, "expected %ld, got %ld\n",
- cbName, providerLen);
+ ok(result, "expected TRUE, got %d\n", result);
+ ok(type==dwType, "expected %d, got %d\n", dwType, type);
+ if (pszProvName)
+ ok(!strcmp(pszProvName, provider), "expected %s, got %s\n", pszProvName, provider);
+ ok(cbName==providerLen, "expected %d, got %d\n", cbName, providerLen);
LocalFree(provider);
}
-static BOOL FindProvTypesRegVals(DWORD dwIndex, DWORD *pdwProvType, LPSTR *pszTypeName,
+static BOOL FindProvTypesRegVals(DWORD dwIndex, DWORD *pdwProvType, LPSTR *pszTypeName,
DWORD *pcbTypeName, DWORD *pdwTypeCount)
{
HKEY hKey;
HKEY hSubKey;
PSTR ch;
-
+
if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
return FALSE;
-
+
if (RegQueryInfoKey(hKey, NULL, NULL, NULL, pdwTypeCount, pcbTypeName, NULL,
NULL, NULL, NULL, NULL, NULL))
return FALSE;
(*pcbTypeName)++;
-
+
if (!(*pszTypeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, *pcbTypeName))))
return FALSE;
-
+
if (RegEnumKeyEx(hKey, dwIndex, *pszTypeName, pcbTypeName, NULL, NULL, NULL, NULL))
return FALSE;
(*pcbTypeName)++;
*pdwProvType = *(--ch) - '0';
*pdwProvType += (*(--ch) - '0') * 10;
*pdwProvType += (*(--ch) - '0') * 100;
-
+
if (RegOpenKey(hKey, *pszTypeName, &hSubKey))
return FALSE;
-
+
if (RegQueryValueEx(hSubKey, "TypeName", NULL, NULL, NULL, pcbTypeName))
return FALSE;
if (!(*pszTypeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, *pcbTypeName))))
return FALSE;
-
- if (RegQueryValueEx(hSubKey, "TypeName", NULL, NULL, *pszTypeName, pcbTypeName))
+
+ if (RegQueryValueEx(hSubKey, "TypeName", NULL, NULL, (LPBYTE)*pszTypeName, pcbTypeName))
return FALSE;
-
+
RegCloseKey(hSubKey);
RegCloseKey(hKey);
-
+
return TRUE;
}
-static void test_enum_provider_types()
+static void test_enum_provider_types(void)
{
/* expected values */
DWORD dwProvType;
LPSTR pszTypeName = NULL;
DWORD cbTypeName;
DWORD dwTypeCount;
-
+
/* actual values */
DWORD index = 0;
DWORD provType;
DWORD result;
DWORD notNull = 5;
DWORD notZeroFlags = 5;
-
+
if(!pCryptEnumProviderTypesA)
{
- trace("skipping CryptEnumProviderTypes tests\n");
+ skip("CryptEnumProviderTypesA is not available\n");
return;
}
-
+
if (!FindProvTypesRegVals(index, &dwProvType, &pszTypeName, &cbTypeName, &dwTypeCount))
{
- trace("could not find provider types in registry, skipping the test\n");
+ skip("Could not find provider types in registry\n");
return;
}
-
+
/* check pdwReserved for NULL */
result = pCryptEnumProviderTypesA(index, ¬Null, 0, &provType, typeName, &typeNameSize);
- ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %ld\n",
+ ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %d\n",
ERROR_INVALID_PARAMETER, GetLastError());
-
+
/* check dwFlags == zero */
result = pCryptEnumProviderTypesA(index, NULL, notZeroFlags, &provType, typeName, &typeNameSize);
- ok(!result && GetLastError()==NTE_BAD_FLAGS, "expected %i, got %ld\n",
+ ok(!result && GetLastError()==NTE_BAD_FLAGS, "expected %i, got %d\n",
ERROR_INVALID_PARAMETER, GetLastError());
-
+
/* alloc provider type to half the size required
* cbTypeName holds the size required */
typeNameSize = cbTypeName / 2;
ok(!result && GetLastError()==ERROR_MORE_DATA, "expected 0/ERROR_MORE_DATA, got %d/%08lx\n",
result, GetLastError());
*/
-
+
LocalFree(typeName);
-
- /* loop through the provider types to get the number of provider types
+
+ /* loop through the provider types to get the number of provider types
* after loop ends, count should be dwTypeCount + 1 so subtract 1
* to get actual number of provider types */
typeCount = 0;
while(pCryptEnumProviderTypesA(typeCount++, NULL, 0, &provType, NULL, &typeNameSize))
;
typeCount--;
- ok(typeCount==dwTypeCount, "expected %ld, got %ld\n", dwTypeCount, typeCount);
-
+ ok(typeCount==dwTypeCount, "expected %d, got %d\n", dwTypeCount, typeCount);
+
/* loop past the actual number of provider types to get the error
* ERROR_NO_MORE_ITEMS */
for (typeCount = 0; typeCount < dwTypeCount + 1; typeCount++)
result = pCryptEnumProviderTypesA(typeCount, NULL, 0, &provType, NULL, &typeNameSize);
- ok(!result && GetLastError()==ERROR_NO_MORE_ITEMS, "expected %i, got %ld\n",
+ ok(!result && GetLastError()==ERROR_NO_MORE_ITEMS, "expected %i, got %d\n",
ERROR_NO_MORE_ITEMS, GetLastError());
-
+
/* check expected versus actual values returned */
result = pCryptEnumProviderTypesA(index, NULL, 0, &provType, NULL, &typeNameSize);
- ok(result && typeNameSize==cbTypeName, "expected %ld, got %ld\n", cbTypeName, typeNameSize);
+ ok(result && typeNameSize==cbTypeName, "expected %d, got %d\n", cbTypeName, typeNameSize);
if (!(typeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, typeNameSize))))
return;
-
+
typeNameSize = 0xdeadbeef;
result = pCryptEnumProviderTypesA(index, NULL, 0, &provType, typeName, &typeNameSize);
- ok(result, "expected TRUE, got %ld\n", result);
- ok(provType==dwProvType, "expected %ld, got %ld\n", dwProvType, provType);
+ ok(result, "expected TRUE, got %d\n", result);
+ ok(provType==dwProvType, "expected %d, got %d\n", dwProvType, provType);
if (pszTypeName)
ok(!strcmp(pszTypeName, typeName), "expected %s, got %s\n", pszTypeName, typeName);
- ok(typeNameSize==cbTypeName, "expected %ld, got %ld\n", cbTypeName, typeNameSize);
-
+ ok(typeNameSize==cbTypeName, "expected %d, got %d\n", cbTypeName, typeNameSize);
+
LocalFree(typeName);
}
PSTR keyname;
PSTR ptr;
DWORD user = dwFlags & CRYPT_USER_DEFAULT;
-
- LPSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
- LPSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
-
- keyname = LocalAlloc(LMEM_ZEROINIT, (user ? strlen(USERSTR) : strlen(MACHINESTR)) + 1);
+
+ LPCSTR machinestr = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
+ LPCSTR userstr = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
+
+ keyname = LocalAlloc(LMEM_ZEROINIT, (user ? strlen(userstr) : strlen(machinestr)) + 1);
if (keyname)
{
- user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
+ user ? strcpy(keyname, userstr) : strcpy(keyname, machinestr);
ptr = keyname + strlen(keyname);
*(--ptr) = (dwProvType % 10) + '0';
*(--ptr) = ((dwProvType / 10) % 10) + '0';
*(--ptr) = (dwProvType / 100) + '0';
} else
return FALSE;
-
+
if (RegOpenKey((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
{
LocalFree(keyname);
return FALSE;
}
LocalFree(keyname);
-
- if (RegQueryValueEx(hKey, "Name", NULL, NULL, *pszProvName, pcbProvName))
+
+ if (RegQueryValueEx(hKey, "Name", NULL, NULL, (LPBYTE)*pszProvName, pcbProvName))
{
if (GetLastError() != ERROR_MORE_DATA)
SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
return FALSE;
}
-
+
if (!(*pszProvName = LocalAlloc(LMEM_ZEROINIT, *pcbProvName)))
return FALSE;
-
- if (RegQueryValueEx(hKey, "Name", NULL, NULL, *pszProvName, pcbProvName))
+
+ if (RegQueryValueEx(hKey, "Name", NULL, NULL, (LPBYTE)*pszProvName, pcbProvName))
{
if (GetLastError() != ERROR_MORE_DATA)
SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
return FALSE;
}
-
+
RegCloseKey(hKey);
-
+
return TRUE;
}
-static void test_get_default_provider()
+static void test_get_default_provider(void)
{
/* expected results */
DWORD dwProvType = PROV_RSA_FULL;
DWORD dwFlags = CRYPT_MACHINE_DEFAULT;
LPSTR pszProvName = NULL;
DWORD cbProvName;
-
+
/* actual results */
DWORD provType = PROV_RSA_FULL;
DWORD flags = CRYPT_MACHINE_DEFAULT;
DWORD provNameSize;
DWORD result;
DWORD notNull = 5;
-
+
if(!pCryptGetDefaultProviderA)
{
- trace("skipping CryptGetDefaultProvider tests\n");
+ skip("CryptGetDefaultProviderA is not available\n");
return;
}
-
- FindDfltProvRegVals(dwProvType, dwFlags, &pszProvName, &cbProvName);
-
+
+ if(!FindDfltProvRegVals(dwProvType, dwFlags, &pszProvName, &cbProvName))
+ {
+ skip("Could not find default provider in registry\n");
+ return;
+ }
+
/* check pdwReserved for NULL */
result = pCryptGetDefaultProviderA(provType, ¬Null, flags, provName, &provNameSize);
- ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %ld\n",
+ ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %d\n",
ERROR_INVALID_PARAMETER, GetLastError());
-
+
/* check for invalid flag */
flags = 0xdeadbeef;
result = pCryptGetDefaultProviderA(provType, NULL, flags, provName, &provNameSize);
- ok(!result && GetLastError()==NTE_BAD_FLAGS, "expected %ld, got %ld\n",
+ ok(!result && GetLastError()==NTE_BAD_FLAGS, "expected %d, got %d\n",
NTE_BAD_FLAGS, GetLastError());
flags = CRYPT_MACHINE_DEFAULT;
-
+
/* check for invalid prov type */
provType = 0xdeadbeef;
result = pCryptGetDefaultProviderA(provType, NULL, flags, provName, &provNameSize);
ok(!result && (GetLastError() == NTE_BAD_PROV_TYPE ||
GetLastError() == ERROR_INVALID_PARAMETER),
- "expected NTE_BAD_PROV_TYPE or ERROR_INVALID_PARAMETER, got %ld/%ld\n",
+ "expected NTE_BAD_PROV_TYPE or ERROR_INVALID_PARAMETER, got %d/%d\n",
result, GetLastError());
provType = PROV_RSA_FULL;
-
+
SetLastError(0);
-
+
/* alloc provName to half the size required
* cbProvName holds the size required */
provNameSize = cbProvName / 2;
if (!(provName = LocalAlloc(LMEM_ZEROINIT, provNameSize)))
return;
-
+
result = pCryptGetDefaultProviderA(provType, NULL, flags, provName, &provNameSize);
- ok(!result && GetLastError()==ERROR_MORE_DATA, "expected %i, got %ld\n",
+ ok(!result && GetLastError()==ERROR_MORE_DATA, "expected %i, got %d\n",
ERROR_MORE_DATA, GetLastError());
-
+
LocalFree(provName);
-
+
/* check expected versus actual values returned */
result = pCryptGetDefaultProviderA(provType, NULL, flags, NULL, &provNameSize);
- ok(result && provNameSize==cbProvName, "expected %ld, got %ld\n", cbProvName, provNameSize);
+ ok(result && provNameSize==cbProvName, "expected %d, got %d\n", cbProvName, provNameSize);
provNameSize = cbProvName;
-
+
if (!(provName = LocalAlloc(LMEM_ZEROINIT, provNameSize)))
return;
-
+
+ provNameSize = 0xdeadbeef;
result = pCryptGetDefaultProviderA(provType, NULL, flags, provName, &provNameSize);
- ok(result && !strcmp(pszProvName, provName), "expected %s, got %s\n", pszProvName, provName);
- ok(result && provNameSize==cbProvName, "expected %ld, got %ld\n", cbProvName, provNameSize);
+ ok(result, "expected TRUE, got %d\n", result);
+ if(pszProvName)
+ ok(!strcmp(pszProvName, provName), "expected %s, got %s\n", pszProvName, provName);
+ ok(provNameSize==cbProvName, "expected %d, got %d\n", cbProvName, provNameSize);
LocalFree(provName);
}
-static void test_set_provider_ex()
+static void test_set_provider_ex(void)
{
DWORD result;
DWORD notNull = 5;
-
+
/* results */
LPSTR pszProvName = NULL;
DWORD cbProvName;
-
+
if(!pCryptGetDefaultProviderA || !pCryptSetProviderExA)
{
- trace("skipping CryptSetProviderEx tests\n");
+ skip("CryptGetDefaultProviderA and/or CryptSetProviderExA are not available\n");
return;
}
/* check pdwReserved for NULL */
result = pCryptSetProviderExA(MS_DEF_PROV, PROV_RSA_FULL, ¬Null, CRYPT_MACHINE_DEFAULT);
- ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %ld\n",
+ ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %d\n",
ERROR_INVALID_PARAMETER, GetLastError());
/* remove the default provider and then set it to MS_DEF_PROV/PROV_RSA_FULL */
+ SetLastError(0xdeadbeef);
result = pCryptSetProviderExA(MS_DEF_PROV, PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT | CRYPT_DELETE_DEFAULT);
- ok(result, "%ld\n", GetLastError());
+ if (!result && (GetLastError() == ERROR_ACCESS_DENIED))
+ {
+ skip("Not enough rights to remove the default provider\n");
+ return;
+ }
+ ok(result, "%d\n", GetLastError());
result = pCryptSetProviderExA(MS_DEF_PROV, PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT);
- ok(result, "%ld\n", GetLastError());
-
+ ok(result, "%d\n", GetLastError());
+
/* call CryptGetDefaultProvider to see if they match */
result = pCryptGetDefaultProviderA(PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT, NULL, &cbProvName);
if (!(pszProvName = LocalAlloc(LMEM_ZEROINIT, cbProvName)))
result = pCryptGetDefaultProviderA(PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT, pszProvName, &cbProvName);
ok(result && !strcmp(MS_DEF_PROV, pszProvName), "expected %s, got %s\n", MS_DEF_PROV, pszProvName);
- ok(result && cbProvName==(strlen(MS_DEF_PROV) + 1), "expected %i, got %ld\n", (strlen(MS_DEF_PROV) + 1), cbProvName);
+ ok(result && cbProvName==(strlen(MS_DEF_PROV) + 1), "expected %i, got %d\n", (lstrlenA(MS_DEF_PROV) + 1), cbProvName);
LocalFree(pszProvName);
}
+static void test_machine_guid(void)
+{
+ char originalGuid[40];
+ LONG r;
+ HKEY key;
+ DWORD size;
+ HCRYPTPROV hCryptProv;
+ BOOL restoreGuid = FALSE, ret;
+
+ r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography",
+ 0, KEY_ALL_ACCESS, &key);
+ if (r != ERROR_SUCCESS)
+ {
+ skip("couldn't open HKLM\\Software\\Microsoft\\Cryptography\n");
+ return;
+ }
+ /* Cache existing MachineGuid, and delete it */
+ size = sizeof(originalGuid);
+ r = RegQueryValueExA(key, "MachineGuid", NULL, NULL, (BYTE *)originalGuid,
+ &size);
+ if (r == ERROR_SUCCESS)
+ {
+ restoreGuid = TRUE;
+ r = RegDeleteValueA(key, "MachineGuid");
+ ok(!r, "RegDeleteValueA failed: %d\n", r);
+ }
+ else
+ ok(r == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n",
+ r);
+ /* Create and release a provider */
+ ret = pCryptAcquireContextA(&hCryptProv, szKeySet, NULL, PROV_RSA_FULL, 0);
+ ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
+ CryptReleaseContext(hCryptProv, 0);
+
+ if (restoreGuid)
+ RegSetValueExA(key, "MachineGuid", 0, REG_SZ, (const BYTE *)originalGuid,
+ strlen(originalGuid)+1);
+ RegCloseKey(key);
+}
+
START_TEST(crypt)
{
init_function_pointers();
init_environment();
test_acquire_context();
test_incorrect_api_usage();
+ test_verify_sig();
+ test_machine_guid();
clean_up_environment();
}
-
+
test_enum_providers();
test_enum_provider_types();
test_get_default_provider();
/*
- * Unit tests for SystemFunction006 (LMHash?)
+ * Unit tests for SystemFunctionXXX (LMHash?)
*
* Copyright 2004 Hans Leidekker
+ * Copyright 2006 Mike McCormack
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
+#include "winternl.h"
+struct ustring {
+ DWORD Length;
+ DWORD MaximumLength;
+ unsigned char *Buffer;
+};
+
+typedef NTSTATUS (WINAPI *fnSystemFunction001)(const BYTE *, const BYTE *, LPBYTE);
+typedef NTSTATUS (WINAPI *fnSystemFunction002)(const BYTE *, const BYTE *, LPBYTE);
+typedef NTSTATUS (WINAPI *fnSystemFunction003)(const BYTE *, LPBYTE);
+typedef NTSTATUS (WINAPI *fnSystemFunction004)(const struct ustring *, const struct ustring *, struct ustring *);
+typedef NTSTATUS (WINAPI *fnSystemFunction005)(const struct ustring *, const struct ustring *, struct ustring *);
typedef VOID (WINAPI *fnSystemFunction006)( PCSTR passwd, PSTR lmhash );
+typedef NTSTATUS (WINAPI *fnSystemFunction008)(const BYTE *, const BYTE *, LPBYTE);
+typedef NTSTATUS (WINAPI *fnSystemFunction009)(const BYTE *, const BYTE *, LPBYTE);
+typedef int (WINAPI *descrypt)(unsigned char *, unsigned char *, unsigned char *);
+typedef NTSTATUS (WINAPI *fnSystemFunction030)(void*, void*);
+typedef NTSTATUS (WINAPI *fnSystemFunction032)(struct ustring *, struct ustring *);
+
+fnSystemFunction001 pSystemFunction001;
+fnSystemFunction002 pSystemFunction002;
+fnSystemFunction003 pSystemFunction003;
+fnSystemFunction004 pSystemFunction004;
+fnSystemFunction004 pSystemFunction005;
fnSystemFunction006 pSystemFunction006;
+fnSystemFunction008 pSystemFunction008;
+fnSystemFunction008 pSystemFunction009;
+
+/* encrypt two blocks */
+descrypt pSystemFunction012;
+descrypt pSystemFunction014;
+descrypt pSystemFunction016;
+descrypt pSystemFunction018;
+descrypt pSystemFunction020;
+descrypt pSystemFunction022;
+
+/* decrypt two blocks */
+descrypt pSystemFunction013;
+descrypt pSystemFunction015;
+descrypt pSystemFunction017;
+descrypt pSystemFunction019;
+descrypt pSystemFunction021;
+descrypt pSystemFunction023;
+
+/* encrypt two blocks with a 32bit key */
+descrypt pSystemFunction024;
+descrypt pSystemFunction025;
-static void test_SystemFunction006()
+/* decrypt two blocks with a 32bit key */
+descrypt pSystemFunction026;
+descrypt pSystemFunction027;
+
+typedef int (WINAPI *memcmpfunc)(unsigned char *, unsigned char *);
+memcmpfunc pSystemFunction030;
+memcmpfunc pSystemFunction031;
+
+fnSystemFunction032 pSystemFunction032;
+
+static void test_SystemFunction006(void)
{
- static unsigned char lmhash[16 + 1];
+ char lmhash[16 + 1];
- unsigned char passwd[] = { 's','e','c','r','e','t', 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char expect[] =
+ char passwd[] = { 's','e','c','r','e','t', 0, 0, 0, 0, 0, 0, 0, 0 };
+ unsigned char expect[] =
{ 0x85, 0xf5, 0x28, 0x9f, 0x09, 0xdc, 0xa7, 0xeb,
0xaa, 0xd3, 0xb4, 0x35, 0xb5, 0x14, 0x04, 0xee };
lmhash[12], lmhash[13], lmhash[14], lmhash[15] );
}
+static void test_SystemFunction008(void)
+{
+ /* example data from http://davenport.sourceforge.net/ntlm.html */
+ unsigned char hash[0x40] = {
+ 0xff, 0x37, 0x50, 0xbc, 0xc2, 0xb2, 0x24, 0x12,
+ 0xc2, 0x26, 0x5b, 0x23, 0x73, 0x4e, 0x0d, 0xac };
+ unsigned char challenge[0x40] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ unsigned char expected[0x18] = {
+ 0xc3, 0x37, 0xcd, 0x5c, 0xbd, 0x44, 0xfc, 0x97,
+ 0x82, 0xa6, 0x67, 0xaf, 0x6d, 0x42, 0x7c, 0x6d,
+ 0xe6, 0x7c, 0x20, 0xc2, 0xd3, 0xe7, 0x7c, 0x56 };
+ unsigned char output[0x18];
+ NTSTATUS r;
+
+ r = pSystemFunction008(0,0,0);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+
+ r = pSystemFunction008(challenge,0,0);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+
+ r = pSystemFunction008(challenge, hash, 0);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+
+ /* crashes */
+ if (0)
+ {
+ r = pSystemFunction008(challenge, 0, output);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+ }
+
+ r = pSystemFunction008(0, 0, output);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+
+ memset(output, 0, sizeof output);
+ r = pSystemFunction008(challenge, hash, output);
+ ok( r == STATUS_SUCCESS, "wrong error code\n");
+
+ ok( !memcmp(output, expected, sizeof expected), "response wrong\n");
+}
+
+static void test_SystemFunction001(void)
+{
+ unsigned char key[8] = { 0xff, 0x37, 0x50, 0xbc, 0xc2, 0xb2, 0x24, 0 };
+ unsigned char data[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ unsigned char expected[8] = { 0xc3, 0x37, 0xcd, 0x5c, 0xbd, 0x44, 0xfc, 0x97 };
+ unsigned char output[16];
+ NTSTATUS r;
+
+ r = pSystemFunction001(0,0,0);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+
+ memset(output, 0, sizeof output);
+
+ r = pSystemFunction001(data,key,output);
+ ok( r == STATUS_SUCCESS, "wrong error code\n");
+
+ ok(!memcmp(output, expected, sizeof expected), "response wrong\n");
+}
+
+static void test_SystemFunction002(void)
+{
+ /* reverse of SystemFunction001 */
+ unsigned char key[8] = { 0xff, 0x37, 0x50, 0xbc, 0xc2, 0xb2, 0x24, 0 };
+ unsigned char expected[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ unsigned char data[8] = { 0xc3, 0x37, 0xcd, 0x5c, 0xbd, 0x44, 0xfc, 0x97 };
+ unsigned char output[8];
+ int r;
+
+ memset(output, 0, sizeof output);
+ r = pSystemFunction002(data, key, output);
+ ok(r == STATUS_SUCCESS, "function failed\n");
+ ok(!memcmp(output, expected, sizeof expected), "response wrong\n");
+}
+
+static void test_SystemFunction032(void)
+{
+ struct ustring key, data;
+ unsigned char szKey[] = { 'f','o','o',0 };
+ unsigned char szData[8] = { 'b','a','r',0 };
+ unsigned char expected[] = {0x28, 0xb9, 0xf8, 0xe1};
+ int r;
+
+ /* crashes: pSystemFunction032(NULL,NULL); */
+
+ key.Buffer = szKey;
+ key.Length = sizeof szKey;
+ key.MaximumLength = key.Length;
+
+ data.Buffer = szData;
+ data.Length = 4;
+ data.MaximumLength = 8;
+
+ r = pSystemFunction032(&data, &key);
+ ok(r == STATUS_SUCCESS, "function failed\n");
+
+ ok(!memcmp(expected, data.Buffer, data.Length), "wrong result\n");
+}
+
+static void test_SystemFunction003(void)
+{
+ unsigned char output[8], data[8];
+ unsigned char key[7] = { 0xff, 0x37, 0x50, 0xbc, 0xc2, 0xb2, 0x24 };
+ unsigned char exp1[8] = { 0x9d, 0x21, 0xc8, 0x86, 0x6c, 0x21, 0xcf, 0x43 };
+ char exp2[] = "KGS!@#$%";
+ int r;
+
+ r = pSystemFunction003(NULL, NULL);
+ ok(r == STATUS_UNSUCCESSFUL, "function failed\n");
+
+ r = pSystemFunction003(key, NULL);
+ ok(r == STATUS_UNSUCCESSFUL, "function failed\n");
+
+ memset(data, 0, sizeof data);
+ r = pSystemFunction003(key, data);
+ ok(r == STATUS_SUCCESS, "function failed\n");
+ ok( !memcmp(exp1, data, sizeof data), "decrypted message wrong\n");
+
+ memset(output, 0, sizeof output);
+ r = pSystemFunction002(data, key, output);
+
+ ok( !memcmp(exp2, output, sizeof output), "decrypted message wrong\n");
+}
+
+static void test_SystemFunction004(void)
+{
+ unsigned char inbuf[0x100], keybuf[0x100], resbuf[0x100];
+ unsigned char output[8];
+ int r;
+ struct ustring in, key, out;
+
+ /* crash
+ r = pSystemFunction004(NULL, NULL, NULL);
+ ok(r == STATUS_UNSUCCESSFUL, "function failed\n");
+ */
+
+ memset(inbuf, 0, sizeof inbuf);
+ memset(keybuf, 0, sizeof keybuf);
+ memset(resbuf, 0, sizeof resbuf);
+
+ in.Buffer = NULL;
+ in.Length = in.MaximumLength = 0;
+
+ key.Buffer = NULL;
+ key.Length = key.MaximumLength = 0;
+
+ out.Buffer = NULL;
+ out.Length = out.MaximumLength = 0;
+
+ r = pSystemFunction004(&in, &key, &out);
+ ok(r == STATUS_INVALID_PARAMETER_2, "function failed\n");
+
+ key.Buffer = keybuf;
+ key.Length = 0x100;
+ key.MaximumLength = 0x100;
+
+ r = pSystemFunction004(&in, &key, (struct ustring *)&out);
+ ok(r == STATUS_BUFFER_TOO_SMALL, "function failed\n");
+
+ in.Buffer = inbuf;
+ in.Length = 0x0c;
+ in.MaximumLength = 0;
+
+ /* add two identical blocks... */
+ inbuf[0] = 1;
+ inbuf[1] = 2;
+ inbuf[2] = 3;
+ inbuf[3] = 4;
+
+ inbuf[8] = 1;
+ inbuf[9] = 2;
+ inbuf[10] = 3;
+ inbuf[11] = 4;
+
+ /* check that the Length field is really obeyed */
+ keybuf[6] = 1;
+
+ key.Buffer = keybuf;
+ key.Length = 6;
+ key.MaximumLength = 0;
+
+ keybuf[1] = 0x33;
+
+ out.Buffer = resbuf;
+ out.Length = 0;
+ out.MaximumLength = 0x40;
+ r = pSystemFunction004(&in, &key, &out);
+ ok(r == STATUS_SUCCESS, "function failed\n");
+
+ keybuf[6] = 0;
+
+ memset(output, 0, sizeof output);
+ r = pSystemFunction002(out.Buffer, key.Buffer, output);
+
+ ok(((unsigned int*)output)[0] == in.Length, "crypted length wrong\n");
+ ok(((unsigned int*)output)[1] == 1, "crypted value wrong\n");
+
+ memset(output, 0, sizeof output);
+ r = pSystemFunction002(out.Buffer+8, key.Buffer, output);
+ ok(!memcmp(output, inbuf, sizeof output), "crypted data wrong\n");
+
+ memset(output, 0, sizeof output);
+ r = pSystemFunction002(out.Buffer+16, key.Buffer, output);
+ ok(!memcmp(output, inbuf, sizeof output), "crypted data wrong\n");
+}
+
+static void test_SystemFunction005(void)
+{
+ char output[0x40], result[0x40];
+ int r;
+ struct ustring in, key, out, res;
+ static char datastr[] = "twinkle twinkle little star";
+ static char keystr[] = "byolnim";
+
+ in.Buffer = (unsigned char *)datastr;
+ in.Length = strlen(datastr);
+ in.MaximumLength = 0;
+
+ key.Buffer = (unsigned char *)keystr;
+ key.Length = strlen(keystr);
+ key.MaximumLength = 0;
+
+ out.Buffer = (unsigned char *)output;
+ out.Length = out.MaximumLength = sizeof output;
+
+ r = pSystemFunction004(&in, &key, &out);
+ ok(r == STATUS_SUCCESS, "function failed\n");
+
+ memset(result, 0, sizeof result);
+ res.Buffer = (unsigned char *)result;
+ res.Length = 0;
+ res.MaximumLength = sizeof result;
+
+ r = pSystemFunction005(&out, &key, &res);
+ ok(r == STATUS_SUCCESS, "function failed\n");
+
+ r = pSystemFunction005(&out, &key, &res);
+ ok(r == STATUS_SUCCESS, "function failed\n");
+
+ ok(res.Length == in.Length, "Length wrong\n");
+ ok(!memcmp(res.Buffer, in.Buffer, in.Length), "data wrong\n");
+
+ out.Length = 0;
+ out.MaximumLength = 0;
+ r = pSystemFunction005(&out, &key, &res);
+ ok(r == STATUS_SUCCESS, "function failed\n");
+
+ ok(res.Length == in.Length, "Length wrong\n");
+ ok(!memcmp(res.Buffer, in.Buffer, in.Length), "data wrong\n");
+
+ res.MaximumLength = 0;
+ r = pSystemFunction005(&out, &key, &res);
+ ok(r == STATUS_BUFFER_TOO_SMALL, "function failed\n");
+
+ key.Length = 1;
+ r = pSystemFunction005(&out, &key, &res);
+ ok(r == STATUS_UNKNOWN_REVISION, "function failed\n");
+
+ key.Length = 0;
+ r = pSystemFunction005(&out, &key, &res);
+ ok(r == STATUS_INVALID_PARAMETER_2, "function failed\n");
+}
+
+static void test_SystemFunction009(void)
+{
+ unsigned char hash[0x10] = {
+ 0xff, 0x37, 0x50, 0xbc, 0xc2, 0xb2, 0x24, 0x12,
+ 0xc2, 0x26, 0x5b, 0x23, 0x73, 0x4e, 0x0d, 0xac };
+ unsigned char challenge[8] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ unsigned char expected[0x18] = {
+ 0xc3, 0x37, 0xcd, 0x5c, 0xbd, 0x44, 0xfc, 0x97,
+ 0x82, 0xa6, 0x67, 0xaf, 0x6d, 0x42, 0x7c, 0x6d,
+ 0xe6, 0x7c, 0x20, 0xc2, 0xd3, 0xe7, 0x7c, 0x56 };
+ unsigned char output[0x18];
+ int r;
+
+ memset(output, 0, sizeof output);
+ r = pSystemFunction009(challenge, hash, output);
+ ok( r == STATUS_SUCCESS, "wrong error code\n");
+ ok(!memcmp(output, expected, sizeof expected), "response wrong\n");
+}
+
+static unsigned char des_key[] = {
+ 0xff, 0x37, 0x50, 0xbc, 0xc2, 0xb2, 0x24,
+ 0xff, 0x37, 0x50, 0xbc, 0xc2, 0xb2, 0x24,
+};
+static unsigned char des_plaintext[] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0
+};
+static unsigned char des_ciphertext[] = {
+ 0xc3, 0x37, 0xcd, 0x5c, 0xbd, 0x44, 0xfc, 0x97,
+ 0xc3, 0x37, 0xcd, 0x5c, 0xbd, 0x44, 0xfc, 0x97, 0
+};
+
+/* test functions that encrypt two DES blocks */
+static void test_SystemFunction_encrypt(descrypt func, int num)
+{
+ unsigned char output[0x11];
+ int r;
+
+ if (!func)
+ {
+ skip("SystemFunction%03d is not available\n", num);
+ return;
+ }
+
+ r = func(NULL, NULL, NULL);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+
+ memset(output, 0, sizeof output);
+ r = func(des_plaintext, des_key, output);
+ ok( r == STATUS_SUCCESS, "wrong error code\n");
+ ok( !memcmp(des_ciphertext, output, sizeof des_ciphertext), "ciphertext wrong (%d)\n", num);
+}
+
+/* test functions that decrypt two DES blocks */
+static void test_SystemFunction_decrypt(descrypt func, int num)
+{
+ unsigned char output[0x11];
+ int r;
+
+ if (!func)
+ {
+ skip("SystemFunction%03d is not available\n", num);
+ return;
+ }
+
+ r = func(NULL, NULL, NULL);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+
+ memset(output, 0, sizeof output);
+
+ r = func(des_ciphertext, des_key, output);
+ ok( r == STATUS_SUCCESS, "wrong error code\n");
+ ok( !memcmp(des_plaintext, output, sizeof des_plaintext), "plaintext wrong (%d)\n", num);
+}
+
+static unsigned char des_ciphertext32[] = {
+ 0x69, 0x51, 0x35, 0x69, 0x0d, 0x29, 0x24, 0xad,
+ 0x23, 0x6d, 0xfd, 0x43, 0x0d, 0xd3, 0x25, 0x81, 0
+};
+
+static void test_SystemFunction_enc32(descrypt func, int num)
+{
+ unsigned char key[4], output[0x11];
+ int r;
+
+ if (!func)
+ {
+ skip("SystemFunction%03d is not available\n", num);
+ return;
+ }
+
+ memset(output, 0, sizeof output);
+
+ /* two keys are generated using 4 bytes, repeated 4 times ... */
+ memcpy(key, "foo", 4);
+
+ r = func(des_plaintext, key, output);
+ ok( r == STATUS_SUCCESS, "wrong error code (%d)\n", num);
+
+ ok( !memcmp( output, des_ciphertext32, sizeof des_ciphertext32), "ciphertext wrong (%d)\n", num);
+}
+
+static void test_SystemFunction_dec32(descrypt func, int num)
+{
+ unsigned char key[4], output[0x11];
+ int r;
+
+ if (!func)
+ {
+ skip("SystemFunction%03d is not available\n", num);
+ return;
+ }
+
+ memset(output, 0, sizeof output);
+
+ /* two keys are generated using 4 bytes, repeated 4 times ... */
+ memcpy(key, "foo", 4);
+
+ r = func(des_ciphertext32, key, output);
+ ok( r == STATUS_SUCCESS, "wrong error code (%d)\n", num);
+
+ ok( !memcmp( output, des_plaintext, sizeof des_plaintext), "plaintext wrong (%d)\n", num);
+}
+
+static void test_memcmpfunc(memcmpfunc fn)
+{
+ unsigned char arg1[0x20], arg2[0x20];
+ int r;
+
+ if (!fn)
+ {
+ skip("function is not available\n");
+ return;
+ }
+
+ if (0)
+ {
+ /* crashes */
+ r = fn(NULL, NULL);
+ }
+
+ memset(arg1, 0, sizeof arg1);
+ memset(arg2, 0, sizeof arg2);
+ arg1[0x10] = 1;
+
+ r = fn(arg1, arg2);
+ ok( r == 1, "wrong error code\n");
+
+ memset(arg1, 1, sizeof arg1);
+ memset(arg2, 1, sizeof arg2);
+ arg1[0x10] = 0;
+
+ r = fn(arg1, arg2);
+ ok( r == 1, "wrong error code\n");
+
+ memset(arg1, 0, sizeof arg1);
+ memset(arg2, 1, sizeof arg2);
+
+ r = fn(arg1, arg2);
+ ok( r == 0, "wrong error code\n");
+
+ memset(arg1, 1, sizeof arg1);
+ memset(arg2, 0, sizeof arg2);
+
+ r = fn(arg1, arg2);
+ ok( r == 0, "wrong error code\n");
+}
+
START_TEST(crypt_lmhash)
{
- HMODULE module;
+ HMODULE module = GetModuleHandleA("advapi32.dll");
- if (!(module = LoadLibrary("advapi32.dll"))) return;
+ pSystemFunction001 = (fnSystemFunction001)GetProcAddress( module, "SystemFunction001" );
+ if (pSystemFunction001)
+ test_SystemFunction001();
+ else
+ skip("SystemFunction001 is not available\n");
- pSystemFunction006 = (fnSystemFunction006)GetProcAddress( module, "SystemFunction006" );
+ pSystemFunction002 = (fnSystemFunction002)GetProcAddress( module, "SystemFunction002" );
+ if (pSystemFunction002)
+ test_SystemFunction002();
+ else
+ skip("SystemFunction002 is not available\n");
- if (!pSystemFunction006) goto out;
+ pSystemFunction003 = (fnSystemFunction003)GetProcAddress( module, "SystemFunction003" );
+ if (pSystemFunction003)
+ test_SystemFunction003();
+ else
+ skip("SystemFunction002 is not available\n");
- if (pSystemFunction006)
+ pSystemFunction004 = (fnSystemFunction004)GetProcAddress( module, "SystemFunction004" );
+ if (pSystemFunction004)
+ test_SystemFunction004();
+ else
+ skip("SystemFunction004 is not available\n");
+
+ pSystemFunction005 = (fnSystemFunction005)GetProcAddress( module, "SystemFunction005" );
+ if (pSystemFunction005)
+ test_SystemFunction005();
+ else
+ skip("SystemFunction005 is not available\n");
+
+ pSystemFunction006 = (fnSystemFunction006)GetProcAddress( module, "SystemFunction006" );
+ if (pSystemFunction006)
test_SystemFunction006();
+ else
+ skip("SystemFunction006 is not available\n");
+
+ pSystemFunction008 = (fnSystemFunction008)GetProcAddress( module, "SystemFunction008" );
+ if (pSystemFunction008)
+ test_SystemFunction008();
+ else
+ skip("SystemFunction008 is not available\n");
+
+ pSystemFunction009 = (fnSystemFunction009)GetProcAddress( module, "SystemFunction009" );
+ if (pSystemFunction009)
+ test_SystemFunction009();
+ else
+ skip("SystemFunction009 is not available\n");
+
+ pSystemFunction012 = (descrypt) GetProcAddress( module, "SystemFunction012");
+ pSystemFunction013 = (descrypt) GetProcAddress( module, "SystemFunction013");
+ pSystemFunction014 = (descrypt) GetProcAddress( module, "SystemFunction014");
+ pSystemFunction015 = (descrypt) GetProcAddress( module, "SystemFunction015");
+ pSystemFunction016 = (descrypt) GetProcAddress( module, "SystemFunction016");
+ pSystemFunction017 = (descrypt) GetProcAddress( module, "SystemFunction017");
+ pSystemFunction018 = (descrypt) GetProcAddress( module, "SystemFunction018");
+ pSystemFunction019 = (descrypt) GetProcAddress( module, "SystemFunction019");
+ pSystemFunction020 = (descrypt) GetProcAddress( module, "SystemFunction020");
+ pSystemFunction021 = (descrypt) GetProcAddress( module, "SystemFunction021");
+ pSystemFunction022 = (descrypt) GetProcAddress( module, "SystemFunction022");
+ pSystemFunction023 = (descrypt) GetProcAddress( module, "SystemFunction023");
+
+ /* these all encrypt two DES blocks */
+ test_SystemFunction_encrypt(pSystemFunction012, 12);
+ test_SystemFunction_encrypt(pSystemFunction014, 14);
+ test_SystemFunction_encrypt(pSystemFunction016, 16);
+ test_SystemFunction_encrypt(pSystemFunction018, 18);
+ test_SystemFunction_encrypt(pSystemFunction020, 20);
+ test_SystemFunction_encrypt(pSystemFunction022, 22);
+
+ /* these all decrypt two DES blocks */
+ test_SystemFunction_decrypt(pSystemFunction013, 13);
+ test_SystemFunction_decrypt(pSystemFunction015, 15);
+ test_SystemFunction_decrypt(pSystemFunction017, 17);
+ test_SystemFunction_decrypt(pSystemFunction019, 19);
+ test_SystemFunction_decrypt(pSystemFunction021, 21);
+ test_SystemFunction_decrypt(pSystemFunction023, 23);
+
+ pSystemFunction024 = (descrypt) GetProcAddress( module, "SystemFunction024");
+ pSystemFunction025 = (descrypt) GetProcAddress( module, "SystemFunction025");
+ pSystemFunction026 = (descrypt) GetProcAddress( module, "SystemFunction026");
+ pSystemFunction027 = (descrypt) GetProcAddress( module, "SystemFunction027");
+
+ /* these encrypt two DES blocks with a short key */
+ test_SystemFunction_enc32(pSystemFunction024, 24);
+ test_SystemFunction_enc32(pSystemFunction026, 26);
+
+ /* these descrypt two DES blocks with a short key */
+ test_SystemFunction_dec32(pSystemFunction025, 25);
+ test_SystemFunction_dec32(pSystemFunction027, 27);
+
+ pSystemFunction030 = (memcmpfunc) GetProcAddress( module, "SystemFunction030" );
+ pSystemFunction031 = (memcmpfunc) GetProcAddress( module, "SystemFunction031" );
+
+ test_memcmpfunc(pSystemFunction030);
+ test_memcmpfunc(pSystemFunction031);
-out:
- FreeLibrary( module );
+ pSystemFunction032 = (fnSystemFunction032)GetProcAddress( module, "SystemFunction032" );
+ if (pSystemFunction032)
+ test_SystemFunction032();
+ else
+ skip("SystemFunction032 is not available\n");
}
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
+#include "winternl.h"
typedef struct
{
typedef VOID (WINAPI *fnMD4Init)( MD4_CTX *ctx );
typedef VOID (WINAPI *fnMD4Update)( MD4_CTX *ctx, const unsigned char *src, const int len );
typedef VOID (WINAPI *fnMD4Final)( MD4_CTX *ctx );
+typedef int (WINAPI *fnSystemFunction007)(const UNICODE_STRING *, LPBYTE);
+typedef int (WINAPI *md4hashfunc)(LPVOID, const LPBYTE, LPBYTE);
fnMD4Init pMD4Init;
fnMD4Update pMD4Update;
fnMD4Final pMD4Final;
+fnSystemFunction007 pSystemFunction007;
+md4hashfunc pSystemFunction010;
+md4hashfunc pSystemFunction011;
#define ctxcmp( a, b ) memcmp( (char*)a, (char*)b, FIELD_OFFSET( MD4_CTX, in ) )
-void test_md4_ctx()
+static void test_md4_ctx(void)
{
static unsigned char message[] =
"In our Life there's If"
"In our business there is Sin"
"In our bodies, there is Die";
- int size = strlen( message );
- HMODULE module;
+ int size = sizeof(message) - 1;
MD4_CTX ctx;
- MD4_CTX ctx_initialized =
+ MD4_CTX ctx_initialized =
{
{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 },
{ 0, 0 }
{ 0x5f, 0xd3, 0x9b, 0x29, 0x47, 0x53, 0x47, 0xaf,
0xa5, 0xba, 0x0c, 0x05, 0xff, 0xc0, 0xc7, 0xda };
- if (!(module = LoadLibrary( "advapi32.dll" ))) return;
-
- pMD4Init = (fnMD4Init)GetProcAddress( module, "MD4Init" );
- pMD4Update = (fnMD4Update)GetProcAddress( module, "MD4Update" );
- pMD4Final = (fnMD4Final)GetProcAddress( module, "MD4Final" );
-
- if (!pMD4Init || !pMD4Update || !pMD4Final) goto out;
memset( &ctx, 0, sizeof(ctx) );
pMD4Init( &ctx );
ok( ctxcmp( &ctx, &ctx_initialized ), "context has changed\n" );
ok( !memcmp( ctx.digest, expect, sizeof(expect) ), "incorrect result\n" );
-out:
- FreeLibrary( module );
+}
+
+static void test_SystemFunction007(void)
+{
+ int r;
+ UNICODE_STRING str;
+ BYTE output[0x10];
+ BYTE expected[0x10] = { 0x24, 0x0a, 0xf0, 0x9d, 0x84, 0x1c, 0xda, 0xcf,
+ 0x56, 0xeb, 0x6b, 0x96, 0x55, 0xec, 0xcf, 0x0a };
+ WCHAR szFoo[] = {'f','o','o',0 };
+
+ if (0)
+ {
+ /* crashes on Windows */
+ r = pSystemFunction007(NULL, NULL);
+ ok( r == STATUS_UNSUCCESSFUL, "wrong error code\n");
+ }
+
+ str.Buffer = szFoo;
+ str.Length = 4*sizeof(WCHAR);
+ str.MaximumLength = str.Length;
+
+ memset(output, 0, sizeof output);
+ r = pSystemFunction007(&str, output);
+ ok( r == STATUS_SUCCESS, "wrong error code\n");
+
+ ok(!memcmp(output, expected, sizeof expected), "response wrong\n");
+}
+
+static void test_md4hashfunc(md4hashfunc func)
+{
+ unsigned char expected[0x10] = {
+ 0x48, 0x7c, 0x3f, 0x5e, 0x2b, 0x0d, 0x6a, 0x79,
+ 0x32, 0x4e, 0xcd, 0xbe, 0x9c, 0x15, 0x16, 0x6f };
+ unsigned char in[0x10], output[0x10];
+ int r;
+
+ memset(in, 0, sizeof in);
+ memset(output, 0, sizeof output);
+ r = func(0, in, output);
+ ok( r == STATUS_SUCCESS, "wrong error code\n");
+ ok( !memcmp(expected, output, sizeof output), "output wrong\n");
}
START_TEST(crypt_md4)
{
- test_md4_ctx();
+ HMODULE module;
+
+ module = GetModuleHandleA( "advapi32.dll" );
+
+ pMD4Init = (fnMD4Init)GetProcAddress( module, "MD4Init" );
+ pMD4Update = (fnMD4Update)GetProcAddress( module, "MD4Update" );
+ pMD4Final = (fnMD4Final)GetProcAddress( module, "MD4Final" );
+
+ if (pMD4Init && pMD4Update && pMD4Final)
+ test_md4_ctx();
+ else
+ skip("MD4Init and/or MD4Update and/or MD4Final are not available\n");
+
+ pSystemFunction007 = (fnSystemFunction007)GetProcAddress( module, "SystemFunction007" );
+ if (pSystemFunction007)
+ test_SystemFunction007();
+ else
+ skip("SystemFunction007 is not available\n");
+
+ pSystemFunction010 = (md4hashfunc)GetProcAddress( module, "SystemFunction010" );
+ if (pSystemFunction010)
+ test_md4hashfunc(pSystemFunction010);
+ else
+ skip("SystemFunction010 is not available\n");
+
+ pSystemFunction011 = (md4hashfunc)GetProcAddress( module, "SystemFunction011" );
+ if (pSystemFunction011)
+ test_md4hashfunc(pSystemFunction011);
+ else
+ skip("SystemFunction011 is not available\n");
}
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#define ctxcmp( a, b ) memcmp( (char*)a, (char*)b, FIELD_OFFSET( MD5_CTX, in ) )
-void test_md5_ctx()
+static void test_md5_ctx(void)
{
static unsigned char message[] =
"In our Life there's If"
"In our business there is Sin"
"In our bodies, there is Die";
- int size = strlen( message );
+ int size = sizeof(message) - 1;
HMODULE module;
MD5_CTX ctx;
- MD5_CTX ctx_initialized =
+ MD5_CTX ctx_initialized =
{
{ 0, 0 },
{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }
{ 0x43, 0x03, 0xdd, 0x8c, 0x60, 0xd9, 0x3a, 0x22,
0x0b, 0x28, 0xd0, 0xb2, 0x65, 0x93, 0xd0, 0x36 };
- if (!(module = LoadLibrary( "advapi32.dll" ))) return;
+ module = GetModuleHandleA("advapi32.dll");
pMD5Init = (fnMD5Init)GetProcAddress( module, "MD5Init" );
pMD5Update = (fnMD5Update)GetProcAddress( module, "MD5Update" );
pMD5Final = (fnMD5Final)GetProcAddress( module, "MD5Final" );
- if (!pMD5Init || !pMD5Update || !pMD5Final) goto out;
+ if (!pMD5Init || !pMD5Update || !pMD5Final)
+ {
+ skip("Needed functions are not available\n");
+ return;
+ }
memset( &ctx, 0, sizeof(ctx) );
pMD5Init( &ctx );
pMD5Final( &ctx );
ok( ctxcmp( &ctx, &ctx_initialized ), "context has changed\n" );
ok( !memcmp( ctx.digest, expect, sizeof(expect) ), "incorrect result\n" );
-
-out:
- FreeLibrary( module );
}
START_TEST(crypt_md5)
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
UCHAR Buffer[64];
} SHA_CTX, *PSHA_CTX;
-#define ctxcmp(a,b) memcmp((char*)a, (char*)b, FIELD_OFFSET(SHA_CTX, Buffer))
-
static void test_sha_ctx(void)
{
FARPROC pA_SHAInit, pA_SHAUpdate, pA_SHAFinal;
ULONG test_buffer_size = strlen(test_buffer);
HMODULE hmod;
SHA_CTX ctx;
- SHA_CTX ctx_initialized = {{0, 0, 0, 0, 0}, {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}, {0, 0}};
- SHA_CTX ctx_update1 = {{0, 0, 0, 0, 0}, {0xdbe5eba8, 0x6b4335ca, 0xf7c94abe, 0xc9f34e31, 0x311023f0}, {0, 0x67}};
- SHA_CTX ctx_update2 = {{0, 0, 0, 0, 0}, {0x5ecc818d, 0x52498169, 0xf6758559, 0xd035a164, 0x871dd125}, {0, 0xce}};
ULONG result[5];
ULONG result_correct[5] = {0xe014f93, 0xe09791ec, 0x6dcf96c8, 0x8e9385fc, 0x1611c1bb};
- hmod = LoadLibrary("advapi32.dll");
+ hmod = GetModuleHandleA("advapi32.dll");
pA_SHAInit = GetProcAddress(hmod, "A_SHAInit");
pA_SHAUpdate = GetProcAddress(hmod, "A_SHAUpdate");
pA_SHAFinal = GetProcAddress(hmod, "A_SHAFinal");
- if (!pA_SHAInit || !pA_SHAUpdate || !pA_SHAFinal) return;
+ if (!pA_SHAInit || !pA_SHAUpdate || !pA_SHAFinal)
+ {
+ skip("A_SHAInit and/or A_SHAUpdate and/or A_SHAFinal are not available\n");
+ return;
+ }
RtlZeroMemory(&ctx, sizeof(ctx));
pA_SHAInit(&ctx);
- ok(!ctxcmp(&ctx, &ctx_initialized), "invalid initialization\n");
-
pA_SHAUpdate(&ctx, test_buffer, test_buffer_size);
- ok(!ctxcmp(&ctx, &ctx_update1), "update doesn't work correctly\n");
-
pA_SHAUpdate(&ctx, test_buffer, test_buffer_size);
- ok(!ctxcmp(&ctx, &ctx_update2), "update doesn't work correctly\n");
-
pA_SHAFinal(&ctx, result);
- ok(!ctxcmp(&ctx, &ctx_initialized), "context hasn't been reinitialized\n");
ok(!memcmp(result, result_correct, sizeof(result)), "incorrect result\n");
-
- FreeLibrary(hmod);
}
START_TEST(crypt_sha)
--- /dev/null
+/*
+ * Unit tests for lsa functions
+ *
+ * Copyright (c) 2006 Robert Reif
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "ntsecapi.h"
+#include "sddl.h"
+#include "winnls.h"
+#include "objbase.h"
+#define INITGUID
+#include "guiddef.h"
+#include "wine/test.h"
+
+static HMODULE hadvapi32;
+static NTSTATUS (WINAPI *pLsaClose)(LSA_HANDLE);
+static NTSTATUS (WINAPI *pLsaFreeMemory)(PVOID);
+static NTSTATUS (WINAPI *pLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE);
+static NTSTATUS (WINAPI *pLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*);
+static BOOL (WINAPI *pConvertSidToStringSidA)(PSID pSid, LPSTR *str);
+
+static BOOL init(void)
+{
+ hadvapi32 = GetModuleHandle("advapi32.dll");
+
+ pLsaClose = (void*)GetProcAddress(hadvapi32, "LsaClose");
+ pLsaFreeMemory = (void*)GetProcAddress(hadvapi32, "LsaFreeMemory");
+ pLsaOpenPolicy = (void*)GetProcAddress(hadvapi32, "LsaOpenPolicy");
+ pLsaQueryInformationPolicy = (void*)GetProcAddress(hadvapi32, "LsaQueryInformationPolicy");
+ pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
+
+ if (pLsaClose && pLsaFreeMemory && pLsaOpenPolicy && pLsaQueryInformationPolicy && pConvertSidToStringSidA)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void test_lsa(void)
+{
+ NTSTATUS status;
+ LSA_HANDLE handle;
+ LSA_OBJECT_ATTRIBUTES object_attributes;
+
+ ZeroMemory(&object_attributes, sizeof(object_attributes));
+ object_attributes.Length = sizeof(object_attributes);
+
+ status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle);
+ ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
+ "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);
+
+ /* try a more restricted access mask if necessary */
+ if (status == STATUS_ACCESS_DENIED) {
+ trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n");
+ status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle);
+ ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status);
+ }
+
+ if (status == STATUS_SUCCESS) {
+ PPOLICY_AUDIT_EVENTS_INFO audit_events_info;
+ PPOLICY_PRIMARY_DOMAIN_INFO primary_domain_info;
+ PPOLICY_ACCOUNT_DOMAIN_INFO account_domain_info;
+ PPOLICY_DNS_DOMAIN_INFO dns_domain_info;
+
+ status = pLsaQueryInformationPolicy(handle, PolicyAuditEventsInformation, (PVOID*)&audit_events_info);
+ if (status == STATUS_ACCESS_DENIED)
+ skip("Not enough rights to retrieve PolicyAuditEventsInformation\n");
+ else
+ ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyAuditEventsInformation) failed, returned 0x%08x\n", status);
+ if (status == STATUS_SUCCESS) {
+ pLsaFreeMemory((LPVOID)audit_events_info);
+ }
+
+ status = pLsaQueryInformationPolicy(handle, PolicyPrimaryDomainInformation, (PVOID*)&primary_domain_info);
+ ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyPrimaryDomainInformation) failed, returned 0x%08x\n", status);
+ if (status == STATUS_SUCCESS) {
+ ok(primary_domain_info->Sid==0,"Sid should be NULL on the local computer\n");
+ if (primary_domain_info->Sid) {
+ LPSTR strsid;
+ if (pConvertSidToStringSidA(primary_domain_info->Sid, &strsid))
+ {
+ if (primary_domain_info->Name.Buffer) {
+ LPSTR name = NULL;
+ UINT len;
+ len = WideCharToMultiByte( CP_ACP, 0, primary_domain_info->Name.Buffer, -1, NULL, 0, NULL, NULL );
+ name = LocalAlloc( 0, len );
+ WideCharToMultiByte( CP_ACP, 0, primary_domain_info->Name.Buffer, -1, name, len, NULL, NULL );
+ trace(" name: %s sid: %s\n", name, strsid);
+ LocalFree( name );
+ } else
+ trace(" name: NULL sid: %s\n", strsid);
+ LocalFree( strsid );
+ }
+ else
+ trace("invalid sid\n");
+ }
+ pLsaFreeMemory((LPVOID)primary_domain_info);
+ }
+
+ status = pLsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (PVOID*)&account_domain_info);
+ ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) failed, returned 0x%08x\n", status);
+ if (status == STATUS_SUCCESS) {
+ pLsaFreeMemory((LPVOID)account_domain_info);
+ }
+
+ /* This isn't supported in NT4 */
+ status = pLsaQueryInformationPolicy(handle, PolicyDnsDomainInformation, (PVOID*)&dns_domain_info);
+ ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER,
+ "LsaQueryInformationPolicy(PolicyDnsDomainInformation) failed, returned 0x%08x\n", status);
+ if (status == STATUS_SUCCESS) {
+ ok(IsEqualGUID(&dns_domain_info->DomainGuid, &GUID_NULL), "DomainGUID should be GUID_NULL on local computer\n");
+ ok(dns_domain_info->Sid==0,"Sid should be NULL on the local computer\n");
+ if (dns_domain_info->Sid || !IsEqualGUID(&dns_domain_info->DomainGuid, &GUID_NULL)) {
+ LPSTR strsid = NULL;
+ LPSTR name = NULL;
+ LPSTR domain = NULL;
+ LPSTR forest = NULL;
+ LPSTR guidstr = NULL;
+ WCHAR guidstrW[64];
+ UINT len;
+ guidstrW[0] = '\0';
+ pConvertSidToStringSidA(dns_domain_info->Sid, &strsid);
+ StringFromGUID2(&dns_domain_info->DomainGuid, guidstrW, sizeof(guidstrW)/sizeof(WCHAR));
+ len = WideCharToMultiByte( CP_ACP, 0, guidstrW, -1, NULL, 0, NULL, NULL );
+ guidstr = LocalAlloc( 0, len );
+ WideCharToMultiByte( CP_ACP, 0, guidstrW, -1, guidstr, len, NULL, NULL );
+ if (dns_domain_info->Name.Buffer) {
+ len = WideCharToMultiByte( CP_ACP, 0, dns_domain_info->Name.Buffer, -1, NULL, 0, NULL, NULL );
+ name = LocalAlloc( 0, len );
+ WideCharToMultiByte( CP_ACP, 0, dns_domain_info->Name.Buffer, -1, name, len, NULL, NULL );
+ }
+ if (dns_domain_info->DnsDomainName.Buffer) {
+ len = WideCharToMultiByte( CP_ACP, 0, dns_domain_info->DnsDomainName.Buffer, -1, NULL, 0, NULL, NULL );
+ domain = LocalAlloc( 0, len );
+ WideCharToMultiByte( CP_ACP, 0, dns_domain_info->DnsDomainName.Buffer, -1, domain, len, NULL, NULL );
+ }
+ if (dns_domain_info->DnsForestName.Buffer) {
+ len = WideCharToMultiByte( CP_ACP, 0, dns_domain_info->DnsForestName.Buffer, -1, NULL, 0, NULL, NULL );
+ forest = LocalAlloc( 0, len );
+ WideCharToMultiByte( CP_ACP, 0, dns_domain_info->DnsForestName.Buffer, -1, forest, len, NULL, NULL );
+ }
+ trace(" name: %s domain: %s forest: %s guid: %s sid: %s\n",
+ name ? name : "NULL", domain ? domain : "NULL",
+ forest ? forest : "NULL", guidstr, strsid ? strsid : "NULL");
+ LocalFree( name );
+ LocalFree( forest );
+ LocalFree( domain );
+ LocalFree( guidstr );
+ LocalFree( strsid );
+ }
+ pLsaFreeMemory((LPVOID)dns_domain_info);
+ }
+
+ status = pLsaClose(handle);
+ ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
+ }
+}
+
+START_TEST(lsa)
+{
+ if (!init()) {
+ skip("Needed functions are not available\n");
+ return;
+ }
+
+ test_lsa();
+}
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
+#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
+#include "winsvc.h"
#include "winerror.h"
static HKEY hkey_main;
+static DWORD GLE;
static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
static const char * sTestpath2 = "%FOO%\\subdir1";
+static HMODULE hadvapi32;
+static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD);
+static DWORD (WINAPI *pRegDeleteTreeA)(HKEY,LPCSTR);
+
+
+
+/* Debugging functions from wine/libs/wine/debug.c */
+
+/* allocate some tmp string space */
+/* FIXME: this is not 100% thread-safe */
+static char *get_temp_buffer( int size )
+{
+ static char *list[32];
+ static long pos;
+ char *ret;
+ int idx;
+
+ idx = ++pos % (sizeof(list)/sizeof(list[0]));
+ if ((ret = realloc( list[idx], size ))) list[idx] = ret;
+ return ret;
+}
+
+static const char *wine_debugstr_an( const char *str, int n )
+{
+ static const char hex[16] = "0123456789abcdef";
+ char *dst, *res;
+ size_t size;
+
+ if (!((ULONG_PTR)str >> 16))
+ {
+ if (!str) return "(null)";
+ res = get_temp_buffer( 6 );
+ sprintf( res, "#%04x", LOWORD(str) );
+ return res;
+ }
+ if (n == -1) n = strlen(str);
+ if (n < 0) n = 0;
+ size = 10 + min( 300, n * 4 );
+ dst = res = get_temp_buffer( size );
+ *dst++ = '"';
+ while (n-- > 0 && dst <= res + size - 9)
+ {
+ unsigned char c = *str++;
+ switch (c)
+ {
+ case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+ case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+ case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+ case '"': *dst++ = '\\'; *dst++ = '"'; break;
+ case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+ default:
+ if (c >= ' ' && c <= 126)
+ *dst++ = c;
+ else
+ {
+ *dst++ = '\\';
+ *dst++ = 'x';
+ *dst++ = hex[(c >> 4) & 0x0f];
+ *dst++ = hex[c & 0x0f];
+ }
+ }
+ }
+ *dst++ = '"';
+ if (n > 0)
+ {
+ *dst++ = '.';
+ *dst++ = '.';
+ *dst++ = '.';
+ }
+ *dst++ = 0;
+ return res;
+}
+
+static const char *wine_debugstr_wn( const WCHAR *str, int n )
+{
+ char *dst, *res;
+ size_t size;
+
+ if (!HIWORD(str))
+ {
+ if (!str) return "(null)";
+ res = get_temp_buffer( 6 );
+ sprintf( res, "#%04x", LOWORD(str) );
+ return res;
+ }
+ if (n == -1) n = lstrlenW(str);
+ if (n < 0) n = 0;
+ size = 12 + min( 300, n * 5);
+ dst = res = get_temp_buffer( n * 5 + 7 );
+ *dst++ = 'L';
+ *dst++ = '"';
+ while (n-- > 0 && dst <= res + size - 10)
+ {
+ WCHAR c = *str++;
+ switch (c)
+ {
+ case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+ case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+ case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+ case '"': *dst++ = '\\'; *dst++ = '"'; break;
+ case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+ default:
+ if (c >= ' ' && c <= 126)
+ *dst++ = (char)c;
+ else
+ {
+ *dst++ = '\\';
+ sprintf(dst,"%04x",c);
+ dst+=4;
+ }
+ }
+ }
+ *dst++ = '"';
+ if (n > 0)
+ {
+ *dst++ = '.';
+ *dst++ = '.';
+ *dst++ = '.';
+ }
+ *dst = 0;
+ return res;
+}
+
+
+#define ADVAPI32_GET_PROC(func) \
+ p ## func = (void*)GetProcAddress(hadvapi32, #func); \
+ if(!p ## func) \
+ trace("GetProcAddress(%s) failed\n", #func);
+
+static void InitFunctionPtrs(void)
+{
+ hadvapi32 = GetModuleHandleA("advapi32.dll");
+
+ /* This function was introduced with Windows 2003 SP1 */
+ ADVAPI32_GET_PROC(RegGetValueA)
+ ADVAPI32_GET_PROC(RegDeleteTreeA)
+}
+
/* delete key and all its subkeys */
static DWORD delete_key( HKEY hkey )
{
static void setup_main_key(void)
{
- if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
+ if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main ));
}
+static void test_hkey_main_Value_A(LPCSTR name, LPCSTR string,
+ DWORD full_byte_len)
+{
+ DWORD ret, type, cbData;
+ DWORD str_byte_len;
+ LPSTR value;
+ static const char nA[]={'N', 0};
+
+ type=0xdeadbeef;
+ cbData=0xdeadbeef;
+ /* When successful RegQueryValueExA() leaves GLE as is,
+ * so we must reset it to detect unimplemented functions.
+ */
+ SetLastError(0xdeadbeef);
+ ret = RegQueryValueExA(hkey_main, name, NULL, &type, NULL, &cbData);
+ GLE = GetLastError();
+ ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%d\n", ret, GLE);
+ /* It is wrong for the Ansi version to not be implemented */
+ ok(GLE == 0xdeadbeef, "RegQueryValueExA set GLE = %u\n", GLE);
+ if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
+
+ str_byte_len = (string ? lstrlenA(string) : 0) + 1;
+ ok(type == REG_SZ, "RegQueryValueExA returned type %d\n", type);
+ ok(cbData == full_byte_len || cbData == str_byte_len /* Win9x */,
+ "cbData=%d instead of %d or %d\n", cbData, full_byte_len, str_byte_len);
+
+ value = HeapAlloc(GetProcessHeap(), 0, (cbData+2)*sizeof(*value));
+ strcpy(value, nA);
+ type=0xdeadbeef;
+ ret = RegQueryValueExA(hkey_main, name, NULL, &type, (BYTE*)value, &cbData);
+ GLE = GetLastError();
+ ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%d\n", ret, GLE);
+ if (!string)
+ {
+ /* When cbData == 0, RegQueryValueExA() should not modify the buffer */
+ ok(strcmp(value, nA) == 0 || (cbData == 1 && *value == '\0') /* Win9x */,
+ "RegQueryValueExA failed: '%s' != '%s'\n", value, string);
+ }
+ else
+ {
+ ok(memcmp(value, string, cbData) == 0, "RegQueryValueExA failed: %s/%d != %s/%d\n",
+ wine_debugstr_an(value, cbData), cbData,
+ wine_debugstr_an(string, full_byte_len), full_byte_len);
+ }
+ HeapFree(GetProcessHeap(), 0, value);
+}
+
+static void test_hkey_main_Value_W(LPCWSTR name, LPCWSTR string,
+ DWORD full_byte_len)
+{
+ DWORD ret, type, cbData;
+ LPWSTR value;
+ static const WCHAR nW[]={'N', 0};
+
+ type=0xdeadbeef;
+ cbData=0xdeadbeef;
+ /* When successful RegQueryValueExW() leaves GLE as is,
+ * so we must reset it to detect unimplemented functions.
+ */
+ SetLastError(0xdeadbeef);
+ ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData);
+ GLE = GetLastError();
+ ok(ret == ERROR_SUCCESS, "RegQueryValueExW failed: %d, GLE=%d\n", ret, GLE);
+ if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
+
+ ok(type == REG_SZ, "RegQueryValueExW returned type %d\n", type);
+ ok(cbData == full_byte_len,
+ "cbData=%d instead of %d\n", cbData, full_byte_len);
+
+ value = HeapAlloc(GetProcessHeap(), 0, (cbData+2)*sizeof(*value));
+ lstrcpyW(value, nW);
+ type=0xdeadbeef;
+ ret = RegQueryValueExW(hkey_main, name, NULL, &type, (BYTE*)value, &cbData);
+ GLE = GetLastError();
+ ok(ret == ERROR_SUCCESS, "RegQueryValueExW failed: %d, GLE=%d\n", ret, GLE);
+ if (!string)
+ {
+ /* When cbData == 0, RegQueryValueExW() should not modify the buffer */
+ string=nW;
+ }
+ ok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%d != %s/%d\n",
+ wine_debugstr_wn(value, cbData / sizeof(WCHAR)), cbData,
+ wine_debugstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len);
+ HeapFree(GetProcessHeap(), 0, value);
+}
+
+static void test_set_value(void)
+{
+ DWORD ret;
+
+ static const WCHAR name1W[] = {'C','l','e','a','n','S','i','n','g','l','e','S','t','r','i','n','g', 0};
+ static const WCHAR name2W[] = {'S','o','m','e','I','n','t','r','a','Z','e','r','o','e','d','S','t','r','i','n','g', 0};
+ static const WCHAR emptyW[] = {0};
+ static const WCHAR string1W[] = {'T','h','i','s','N','e','v','e','r','B','r','e','a','k','s', 0};
+ static const WCHAR string2W[] = {'T','h','i','s', 0 ,'B','r','e','a','k','s', 0 , 0 ,'A', 0 , 0 , 0 , 'L','o','t', 0 , 0 , 0 , 0, 0};
+ static const WCHAR substring2W[] = {'T','h','i','s',0};
+
+ static const char name1A[] = "CleanSingleString";
+ static const char name2A[] = "SomeIntraZeroedString";
+ static const char emptyA[] = "";
+ static const char string1A[] = "ThisNeverBreaks";
+ static const char string2A[] = "This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
+ static const char substring2A[] = "This";
+
+ if (0)
+ {
+ /* Crashes on NT4, Windows 2000 and XP SP1 */
+ ret = RegSetValueA(hkey_main, NULL, REG_SZ, NULL, 0);
+ ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret);
+ }
+
+ ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, sizeof(string1A));
+ ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
+ test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
+
+ /* RegSetValueA ignores the size passed in */
+ ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, 4);
+ ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
+ test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
+
+ /* stops at first null */
+ ret = RegSetValueA(hkey_main, NULL, REG_SZ, string2A, sizeof(string2A));
+ ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
+ test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
+
+ /* only REG_SZ is supported */
+ ret = RegSetValueA(hkey_main, NULL, REG_BINARY, string2A, sizeof(string2A));
+ ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
+ ret = RegSetValueA(hkey_main, NULL, REG_EXPAND_SZ, string2A, sizeof(string2A));
+ ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
+ ret = RegSetValueA(hkey_main, NULL, REG_MULTI_SZ, string2A, sizeof(string2A));
+ ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
+
+ /* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does).
+ * Surprisingly enough we're supposed to get zero bytes out of it.
+ */
+ ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, 0);
+ ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(name1A, NULL, 0);
+ test_hkey_main_Value_W(name1W, NULL, 0);
+
+ /* test RegSetValueExA with an empty string */
+ ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, sizeof(emptyA));
+ ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(name1A, emptyA, sizeof(emptyA));
+ test_hkey_main_Value_W(name1W, emptyW, sizeof(emptyW));
+
+ /* test RegSetValueExA with off-by-one size */
+ ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A)-sizeof(string1A[0]));
+ ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
+ test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
+
+ /* test RegSetValueExA with normal string */
+ ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A));
+ ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
+ test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
+
+ /* test RegSetValueExA with intrazeroed string */
+ ret = RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)string2A, sizeof(string2A));
+ ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
+ test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
+
+ /* 9x doesn't support W-calls, so don't test them then */
+ if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
+
+ if (0)
+ {
+ /* Crashes on NT4, Windows 2000 and XP SP1 */
+ ret = RegSetValueW(hkey_main, NULL, REG_SZ, NULL, 0);
+ ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret);
+ }
+
+ ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, sizeof(string1W));
+ ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
+ test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
+
+ /* RegSetValueA ignores the size passed in */
+ ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, 4 * sizeof(string1W[0]));
+ ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
+ test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
+
+ /* stops at first null */
+ ret = RegSetValueW(hkey_main, NULL, REG_SZ, string2W, sizeof(string2W));
+ ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
+ test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
+
+ /* only REG_SZ is supported */
+ ret = RegSetValueW(hkey_main, NULL, REG_BINARY, string2W, sizeof(string2W));
+ ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
+ ret = RegSetValueW(hkey_main, NULL, REG_EXPAND_SZ, string2W, sizeof(string2W));
+ ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
+ ret = RegSetValueW(hkey_main, NULL, REG_MULTI_SZ, string2W, sizeof(string2W));
+ ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
+
+ /* test RegSetValueExW with off-by-one size */
+ ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W)-sizeof(string1W[0]));
+ ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
+ test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
+
+ /* test RegSetValueExW with normal string */
+ ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W));
+ ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
+ test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
+
+ /* test RegSetValueExW with intrazeroed string */
+ ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)string2W, sizeof(string2W));
+ ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
+ test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
+ test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
+}
+
static void create_test_entries(void)
{
+ static const DWORD qw[2] = { 0x12345678, 0x87654321 };
+
SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
- ok(!RegSetValueExA(hkey_main,"Test1",0,REG_EXPAND_SZ, sTestpath1, strlen(sTestpath1)+1),
+ ok(!RegSetValueExA(hkey_main,"TP1_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
+ "RegSetValueExA failed\n");
+ ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
"RegSetValueExA failed\n");
- ok(!RegSetValueExA(hkey_main,"Test2",0,REG_SZ, sTestpath1, strlen(sTestpath1)+1),
+ ok(!RegSetValueExA(hkey_main,"TP1_ZB_SZ",0,REG_SZ, NULL, 0),
+ "RegSetValueExA failed\n");
+ ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1),
"RegSetValueExA failed\n");
- ok(!RegSetValueExA(hkey_main,"Test3",0,REG_EXPAND_SZ, sTestpath2, strlen(sTestpath2)+1),
+ ok(!RegSetValueExA(hkey_main,"DWORD",0,REG_DWORD, (const BYTE *)qw, 4),
+ "RegSetValueExA failed\n");
+ ok(!RegSetValueExA(hkey_main,"BIN32",0,REG_BINARY, (const BYTE *)qw, 4),
+ "RegSetValueExA failed\n");
+ ok(!RegSetValueExA(hkey_main,"BIN64",0,REG_BINARY, (const BYTE *)qw, 8),
"RegSetValueExA failed\n");
}
-
+
static void test_enum_value(void)
{
DWORD res;
/* create the working key for new 'Test' value */
res = RegCreateKeyA( hkey_main, "TestKey", &test_key );
- ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res);
+ ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res);
/* check NULL data with zero length */
res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 );
if (GetVersion() & 0x80000000)
- ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %ld\n", res );
+ ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %d\n", res );
else
- ok( !res, "RegSetValueExA returned %ld\n", res );
+ ok( !res, "RegSetValueExA returned %d\n", res );
res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 );
- ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %ld\n", res );
+ ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 );
- ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %ld\n", res );
+ ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
- res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (BYTE *)"foobar", 7 );
- ok( res == 0, "RegSetValueExA failed error %ld\n", res );
+ res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (const BYTE *)"foobar", 7 );
+ ok( res == 0, "RegSetValueExA failed error %d\n", res );
/* overflow both name and data */
val_count = 2;
type = 1234;
strcpy( value, "xxxxxxxxxx" );
strcpy( data, "xxxxxxxxxx" );
- res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
- ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
- ok( val_count == 2, "val_count set to %ld\n", val_count );
- ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+ res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
+ ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
+ ok( val_count == 2, "val_count set to %d\n", val_count );
+ ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
type = 1234;
strcpy( value, "xxxxxxxxxx" );
strcpy( data, "xxxxxxxxxx" );
- res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
- ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
+ res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
+ ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
/* Win9x returns 2 as specified by MSDN but NT returns 3... */
- ok( val_count == 2 || val_count == 3, "val_count set to %ld\n", val_count );
- ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
-#if 0
- /* v5.1.2600.0 (XP Home) does not touch value or data in this case */
- ok( !strcmp( value, "Te" ), "value set to '%s' instead of 'Te'\n", value );
- ok( !strcmp( data, "foobar" ), "data set to '%s' instead of 'foobar'\n", data );
-#endif
+ ok( val_count == 2 || val_count == 3, "val_count set to %d\n", val_count );
+ ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
+ /* v5.1.2600.0 (XP Home and Professional) does not touch value or data in this case */
+ ok( !strcmp( value, "Te" ) || !strcmp( value, "xxxxxxxxxx" ),
+ "value set to '%s' instead of 'Te' or 'xxxxxxxxxx'\n", value );
+ ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ),
+ "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
/* overflow empty name */
val_count = 0;
type = 1234;
strcpy( value, "xxxxxxxxxx" );
strcpy( data, "xxxxxxxxxx" );
- res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
- ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
- ok( val_count == 0, "val_count set to %ld\n", val_count );
- ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+ res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
+ ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
+ ok( val_count == 0, "val_count set to %d\n", val_count );
+ ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
-#if 0
- /* v5.1.2600.0 (XP Home) does not touch data in this case */
- ok( !strcmp( data, "foobar" ), "data set to '%s' instead of 'foobar'\n", data );
-#endif
+ /* v5.1.2600.0 (XP Home and Professional) does not touch data in this case */
+ ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ),
+ "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
/* overflow data */
val_count = 20;
type = 1234;
strcpy( value, "xxxxxxxxxx" );
strcpy( data, "xxxxxxxxxx" );
- res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
- ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
- ok( val_count == 20, "val_count set to %ld\n", val_count );
- ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+ res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
+ ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
+ ok( val_count == 20, "val_count set to %d\n", val_count );
+ ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
type = 1234;
strcpy( value, "xxxxxxxxxx" );
strcpy( data, "xxxxxxxxxx" );
- res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
- ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
- ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
- ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+ res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
+ ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
+ ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
+ ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data );
/* Unicode tests */
- SetLastError(0);
+ SetLastError(0xdeadbeef);
res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
- return;
- ok( res == 0, "RegSetValueExW failed error %ld\n", res );
+ {
+ skip("RegSetValueExW is not implemented\n");
+ goto cleanup;
+ }
+ ok( res == 0, "RegSetValueExW failed error %d\n", res );
/* overflow both name and data */
val_count = 2;
memcpy( valueW, xxxW, sizeof(xxxW) );
memcpy( dataW, xxxW, sizeof(xxxW) );
res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
- ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
- ok( val_count == 2, "val_count set to %ld\n", val_count );
- ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+ ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
+ ok( val_count == 2, "val_count set to %d\n", val_count );
+ ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
memcpy( valueW, xxxW, sizeof(xxxW) );
memcpy( dataW, xxxW, sizeof(xxxW) );
res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
- ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
- ok( val_count == 3, "val_count set to %ld\n", val_count );
- ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+ ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
+ ok( val_count == 3, "val_count set to %d\n", val_count );
+ ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
memcpy( valueW, xxxW, sizeof(xxxW) );
memcpy( dataW, xxxW, sizeof(xxxW) );
res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
- ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
- ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
- ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+ ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
+ ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
+ ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
memcpy( valueW, xxxW, sizeof(xxxW) );
memcpy( dataW, xxxW, sizeof(xxxW) );
res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
- ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
- ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
- ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
- ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+ ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
+ ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
+ ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
+ ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" );
+
+cleanup:
+ RegDeleteKeyA(test_key, "");
+ RegCloseKey(test_key);
}
-static void test_query_value_ex()
+static void test_query_value_ex(void)
{
DWORD ret;
DWORD size;
DWORD type;
+ BYTE buffer[10];
+
+ ret = RegQueryValueExA(hkey_main, "TP1_SZ", NULL, &type, NULL, &size);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+ ok(size == strlen(sTestpath1) + 1, "(%d,%d)\n", (DWORD)strlen(sTestpath1) + 1, size);
+ ok(type == REG_SZ, "type %d is not REG_SZ\n", type);
+
+ type = 0xdeadbeef;
+ size = 0xdeadbeef;
+ ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, NULL, &size);
+ ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
+ /* the type parameter is cleared on Win9x, but is set to a random value on
+ * NT, so don't do that test there. The size parameter is left untouched on Win9x
+ * but cleared on NT+, this can be tested on all platforms.
+ */
+ if (GetVersion() & 0x80000000)
+ {
+ ok(type == 0, "type should have been set to 0 instead of 0x%x\n", type);
+ ok(size == 0xdeadbeef, "size should have been left untouched (0xdeadbeef)\n");
+ }
+ else
+ {
+ trace("test_query_value_ex: type set to: 0x%08x\n", type);
+ ok(size == 0, "size should have been set to 0 instead of %d\n", size);
+ }
- ret = RegQueryValueExA(hkey_main, "Test2", NULL, &type, NULL, &size);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
- ok(size == strlen(sTestpath1) + 1, "(%ld,%ld)\n", (DWORD)strlen(sTestpath1) + 1, size);
- ok(type == REG_SZ, "type %ld is not REG_SZ\n", type);
+ size = sizeof(buffer);
+ ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, buffer, &size);
+ ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
+ ok(size == sizeof(buffer), "size shouldn't have been changed to %d\n", size);
+
+ size = 4;
+ ret = RegQueryValueExA(hkey_main, "BIN32", NULL, &size, buffer, &size);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
}
-static void test_reg_open_key()
+static void test_get_value(void)
+{
+ DWORD ret;
+ DWORD size;
+ DWORD type;
+ DWORD dw, qw[2];
+ CHAR buf[80];
+ CHAR expanded[] = "bar\\subdir1";
+ CHAR expanded2[] = "ImARatherLongButIndeedNeededString\\subdir1";
+
+ if(!pRegGetValueA)
+ {
+ skip("RegGetValue not available on this platform\n");
+ return;
+ }
+
+ /* Invalid parameter */
+ ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, NULL);
+ ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret);
+
+ /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */
+ size = type = dw = 0xdeadbeef;
+ ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ ok(size == 4, "size=%d\n", size);
+ ok(type == REG_DWORD, "type=%d\n", type);
+ ok(dw == 0x12345678, "dw=%d\n", dw);
+
+ /* Query by subkey-name */
+ ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD, NULL, NULL, NULL);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+
+ /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */
+ size = type = dw = 0xdeadbeef;
+ ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_BINARY, &type, &dw, &size);
+ ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
+ /* Although the function failed all values are retrieved */
+ ok(size == 4, "size=%d\n", size);
+ ok(type == REG_DWORD, "type=%d\n", type);
+ ok(dw == 0x12345678, "dw=%d\n", dw);
+
+ /* Test RRF_ZEROONFAILURE */
+ type = dw = 0xdeadbeef; size = 4;
+ ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, &dw, &size);
+ ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
+ /* Again all values are retrieved ... */
+ ok(size == 4, "size=%d\n", size);
+ ok(type == REG_DWORD, "type=%d\n", type);
+ /* ... except the buffer, which is zeroed out */
+ ok(dw == 0, "dw=%d\n", dw);
+
+ /* Test RRF_ZEROONFAILURE with a NULL buffer... */
+ type = size = 0xbadbeef;
+ ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, NULL, &size);
+ ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
+ ok(size == 4, "size=%d\n", size);
+ ok(type == REG_DWORD, "type=%d\n", type);
+
+ /* Query REG_DWORD using RRF_RT_DWORD (ok) */
+ size = type = dw = 0xdeadbeef;
+ ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_DWORD, &type, &dw, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ ok(size == 4, "size=%d\n", size);
+ ok(type == REG_DWORD, "type=%d\n", type);
+ ok(dw == 0x12345678, "dw=%d\n", dw);
+
+ /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */
+ size = type = dw = 0xdeadbeef;
+ ret = pRegGetValueA(hkey_main, NULL, "BIN32", RRF_RT_DWORD, &type, &dw, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ ok(size == 4, "size=%d\n", size);
+ ok(type == REG_BINARY, "type=%d\n", type);
+ ok(dw == 0x12345678, "dw=%d\n", dw);
+
+ /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */
+ qw[0] = qw[1] = size = type = 0xdeadbeef;
+ ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_DWORD, &type, qw, &size);
+ ok(ret == ERROR_DATATYPE_MISMATCH, "ret=%d\n", ret);
+ ok(size == 8, "size=%d\n", size);
+ ok(type == REG_BINARY, "type=%d\n", type);
+ ok(qw[0] == 0x12345678 &&
+ qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
+
+ /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */
+ type = dw = 0xdeadbeef; size = 4;
+ ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_REG_BINARY, &type, &dw, &size);
+ ok(ret == ERROR_MORE_DATA, "ret=%d\n", ret);
+ ok(dw == 0xdeadbeef, "dw=%d\n", dw);
+ ok(size == 8, "size=%d\n", size);
+
+ /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */
+ qw[0] = qw[1] = size = type = 0xdeadbeef;
+ ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_QWORD, &type, qw, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ ok(size == 8, "size=%d\n", size);
+ ok(type == REG_BINARY, "type=%d\n", type);
+ ok(qw[0] == 0x12345678 &&
+ qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
+
+ /* Query REG_SZ using RRF_RT_REG_SZ (ok) */
+ buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, buf, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
+ ok(type == REG_SZ, "type=%d\n", type);
+ ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
+
+ /* Query REG_SZ using RRF_RT_REG_SZ and no buffer (ok) */
+ type = 0xdeadbeef; size = 0;
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, NULL, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
+ ok(size == strlen(sTestpath1)+1 || size == strlen(sTestpath1)+2,
+ "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
+ ok(type == REG_SZ, "type=%d\n", type);
+
+ /* Query REG_SZ using RRF_RT_REG_SZ on a zero-byte value (ok) */
+ strcpy(buf, sTestpath1);
+ type = 0xdeadbeef;
+ size = sizeof(buf);
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_ZB_SZ", RRF_RT_REG_SZ, &type, buf, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
+ ok(size == 0 ||
+ size == 1, /* win2k3 */
+ "size=%d\n", size);
+ ok(type == REG_SZ, "type=%d\n", type);
+ ok(!strcmp(sTestpath1, buf) ||
+ !strcmp(buf, ""),
+ "Expected \"%s\" or \"\", got \"%s\"\n", sTestpath1, buf);
+
+ /* Query REG_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (ok) */
+ buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, &type, buf, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
+ ok(type == REG_SZ, "type=%d\n", type);
+ ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
+
+ /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ and no buffer (ok, expands) */
+ size = 0;
+ ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, NULL, NULL, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ ok((size == strlen(expanded2)+1) || /* win2k3 SP1 */
+ (size == strlen(expanded2)+2) || /* win2k3 SP2 */
+ (size == strlen(sTestpath2)+1),
+ "strlen(expanded2)=%d, strlen(sTestpath2)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
+
+ /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */
+ buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
+ ok((size == strlen(expanded)+1) || (size == strlen(sTestpath1)+1),
+ "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
+ ok(type == REG_SZ, "type=%d\n", type);
+ ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
+
+ /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands a lot) */
+ buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
+ ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath2 length + 1 here. */
+ ok((size == strlen(expanded2)+1) || (size == strlen(sTestpath2)+1),
+ "strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
+ ok(type == REG_SZ, "type=%d\n", type);
+ ok(!strcmp(expanded2, buf), "expanded2=\"%s\" buf=\"%s\"\n", expanded2, buf);
+
+ /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND (ok, doesn't expand) */
+ buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, &type, buf, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
+ ok(type == REG_EXPAND_SZ, "type=%d\n", type);
+ ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
+
+ /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND and no buffer (ok, doesn't expand) */
+ size = 0xbadbeef;
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, NULL, NULL, &size);
+ ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
+ /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
+ ok(size == strlen(sTestpath1)+1 || size == strlen(sTestpath1)+2,
+ "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
+
+ /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, NULL, NULL, NULL);
+ ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
+
+ /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */
+ ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL);
+ ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret);
+}
+
+static void test_reg_open_key(void)
{
DWORD ret = 0;
HKEY hkResult = NULL;
/* successful open */
ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
ok(hkResult != NULL, "expected hkResult != NULL\n");
hkPreserve = hkResult;
- /* open same key twice */
- ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
- ok(hkResult != hkPreserve, "epxected hkResult != hkPreserve\n");
- ok(hkResult != NULL, "hkResult != NULL\n");
- RegCloseKey(hkResult);
-
- /* open nonexistent key
- * check that hkResult is set to NULL
- */
- hkResult = hkPreserve;
- ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
- ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
- ok(hkResult == NULL, "expected hkResult == NULL\n");
-
- /* open the same nonexistent key again to make sure the key wasn't created */
- hkResult = hkPreserve;
- ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
- ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
- ok(hkResult == NULL, "expected hkResult == NULL\n");
-
- /* send in NULL lpSubKey
- * check that hkResult receives the value of hKey
- */
- hkResult = hkPreserve;
- ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
- ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
-
- /* send empty-string in lpSubKey */
- hkResult = hkPreserve;
- ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
- ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
-
- /* send in NULL lpSubKey and NULL hKey
- * hkResult is set to NULL
- */
- hkResult = hkPreserve;
- ret = RegOpenKeyA(NULL, NULL, &hkResult);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
- ok(hkResult == NULL, "expected hkResult == NULL\n");
+ /* these tests fail on Win9x, but we want to be compatible with NT, so
+ * run them if we can */
+ if (!(GetVersion() & 0x80000000))
+ {
+ /* open same key twice */
+ ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+ ok(hkResult != hkPreserve, "epxected hkResult != hkPreserve\n");
+ ok(hkResult != NULL, "hkResult != NULL\n");
+ RegCloseKey(hkResult);
+
+ /* open nonexistent key
+ * check that hkResult is set to NULL
+ */
+ hkResult = hkPreserve;
+ ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
+ ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
+ ok(hkResult == NULL, "expected hkResult == NULL\n");
+
+ /* open the same nonexistent key again to make sure the key wasn't created */
+ hkResult = hkPreserve;
+ ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
+ ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
+ ok(hkResult == NULL, "expected hkResult == NULL\n");
+
+ /* send in NULL lpSubKey
+ * check that hkResult receives the value of hKey
+ */
+ hkResult = hkPreserve;
+ ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+ ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
+
+ /* send empty-string in lpSubKey */
+ hkResult = hkPreserve;
+ ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+ ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
+
+ /* send in NULL lpSubKey and NULL hKey
+ * hkResult is set to NULL
+ */
+ hkResult = hkPreserve;
+ ret = RegOpenKeyA(NULL, NULL, &hkResult);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+ ok(hkResult == NULL, "expected hkResult == NULL\n");
+ }
/* only send NULL hKey
* the value of hkResult remains unchanged
hkResult = hkPreserve;
ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult);
ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
- "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
+ "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
RegCloseKey(hkResult);
/* send in NULL hkResult */
ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
- ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
+ ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
+
+ /* beginning backslash character */
+ ret = RegOpenKeyA(HKEY_CURRENT_USER, "\\Software\\Wine\\Test", &hkResult);
+ ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */
+ ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */
+ , "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
}
-static void test_reg_close_key()
+static void test_reg_create_key(void)
+{
+ LONG ret;
+ HKEY hkey1, hkey2;
+ ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
+ ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
+ /* should succeed: all versions of Windows ignore the access rights
+ * to the parent handle */
+ ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey2, NULL);
+ ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
+
+ /* clean up */
+ RegDeleteKey(hkey2, "");
+ RegDeleteKey(hkey1, "");
+
+ /* beginning backslash character */
+ ret = RegCreateKeyExA(hkey_main, "\\Subkey3", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
+ if (!(GetVersion() & 0x80000000))
+ ok(ret == ERROR_BAD_PATHNAME, "expected ERROR_BAD_PATHNAME, got %d\n", ret);
+ else {
+ ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
+ RegDeleteKey(hkey1, NULL);
+ }
+}
+
+static void test_reg_close_key(void)
{
DWORD ret = 0;
HKEY hkHandle;
*/
ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle);
ret = RegCloseKey(hkHandle);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
/* try to close the key twice */
ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */
ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_SUCCESS,
- "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %ld\n", ret);
-
+ "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %d\n", ret);
+
/* try to close a NULL handle */
ret = RegCloseKey(NULL);
ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
- "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
+ "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
+
+ /* Check to see if we didn't potentially close our main handle, which could happen on win98 as
+ * win98 doesn't give a new handle when the same key is opened.
+ * Not re-opening will make some next tests fail.
+ */
+ if (hkey_main == hkHandle)
+ {
+ trace("The main handle is most likely closed, so re-opening\n");
+ RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main );
+ }
}
-static void test_reg_delete_key()
+static void test_reg_delete_key(void)
{
DWORD ret;
- HKEY hkResult = NULL;
ret = RegDeleteKey(hkey_main, NULL);
- ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_ACCESS_DENIED,
- "expected ERROR_INVALID_PARAMETER or ERROR_ACCESS_DENIED, got %ld\n", ret);
-
- ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Tost", &hkResult);
-
- ret = RegDeleteValue(hkResult, "noExists");
- ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
-
- ret = RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Tost");
-
- ret = RegCloseKey(hkResult);
+ /* There is a bug in NT4 and W2K that doesn't check if the subkey is NULL. If
+ * there are also no subkeys available it will delete the key pointed to by hkey_main.
+ * Not re-creating will make some next tests fail.
+ */
+ if (ret == ERROR_SUCCESS)
+ {
+ trace("We are probably running on NT4 or W2K as the main key is deleted,"
+ " re-creating the main key\n");
+ setup_main_key();
+ }
+ else
+ ok(ret == ERROR_INVALID_PARAMETER ||
+ ret == ERROR_ACCESS_DENIED ||
+ ret == ERROR_BADKEY, /* Win95 */
+ "ret=%d\n", ret);
}
-static void test_reg_save_key()
+static void test_reg_save_key(void)
{
DWORD ret;
ret = RegSaveKey(hkey_main, "saved_key", NULL);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
}
-static void test_reg_load_key()
+static void test_reg_load_key(void)
{
DWORD ret;
HKEY hkHandle;
ret = RegLoadKey(HKEY_LOCAL_MACHINE, "Test", "saved_key");
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
ret = RegOpenKey(HKEY_LOCAL_MACHINE, "Test", &hkHandle);
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
RegCloseKey(hkHandle);
}
-static void test_reg_unload_key()
+static void test_reg_unload_key(void)
{
DWORD ret;
ret = RegUnLoadKey(HKEY_LOCAL_MACHINE, "Test");
- ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+ ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
DeleteFile("saved_key");
+ DeleteFile("saved_key.LOG");
}
static BOOL set_privileges(LPCSTR privilege, BOOL set)
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
-
+
if (set)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
return TRUE;
}
+/* tests that show that RegConnectRegistry and
+ OpenSCManager accept computer names without the
+ \\ prefix (what MSDN says). */
+static void test_regconnectregistry( void)
+{
+ CHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
+ CHAR netwName[MAX_COMPUTERNAME_LENGTH + 3]; /* 2 chars for double backslash */
+ DWORD len = sizeof(compName) ;
+ BOOL ret;
+ LONG retl;
+ HKEY hkey;
+ SC_HANDLE schnd;
+
+ SetLastError(0xdeadbeef);
+ ret = GetComputerNameA(compName, &len);
+ ok( ret, "GetComputerName failed err = %d\n", GetLastError());
+ if( !ret) return;
+
+ lstrcpyA(netwName, "\\\\");
+ lstrcpynA(netwName+2, compName, MAX_COMPUTERNAME_LENGTH + 1);
+
+ retl = RegConnectRegistryA( compName, HKEY_LOCAL_MACHINE, &hkey);
+ ok( !retl ||
+ retl == ERROR_DLL_INIT_FAILED ||
+ retl == ERROR_BAD_NETPATH, /* some win2k */
+ "RegConnectRegistryA failed err = %d\n", retl);
+ if( !retl) RegCloseKey( hkey);
+
+ retl = RegConnectRegistryA( netwName, HKEY_LOCAL_MACHINE, &hkey);
+ ok( !retl ||
+ retl == ERROR_DLL_INIT_FAILED ||
+ retl == ERROR_BAD_NETPATH, /* some win2k */
+ "RegConnectRegistryA failed err = %d\n", retl);
+ if( !retl) RegCloseKey( hkey);
+
+ SetLastError(0xdeadbeef);
+ schnd = OpenSCManagerA( compName, NULL, GENERIC_READ);
+ if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("OpenSCManagerA is not implemented\n");
+ return;
+ }
+
+ ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError());
+ CloseServiceHandle( schnd);
+
+ SetLastError(0xdeadbeef);
+ schnd = OpenSCManagerA( netwName, NULL, GENERIC_READ);
+ ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError());
+ CloseServiceHandle( schnd);
+
+}
+
+static void test_reg_query_value(void)
+{
+ HKEY subkey;
+ CHAR val[MAX_PATH];
+ WCHAR valW[5];
+ LONG size, ret;
+
+ static const WCHAR expected[] = {'d','a','t','a',0};
+
+ ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+
+ ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+
+ /* try an invalid hkey */
+ SetLastError(0xdeadbeef);
+ size = MAX_PATH;
+ ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size);
+ ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 98 returns BADKEY */
+ "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a NULL hkey */
+ SetLastError(0xdeadbeef);
+ size = MAX_PATH;
+ ret = RegQueryValueA(NULL, "subkey", val, &size);
+ ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 98 returns BADKEY */
+ "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a NULL value */
+ size = MAX_PATH;
+ ret = RegQueryValueA(hkey_main, "subkey", NULL, &size);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ok(size == 5, "Expected 5, got %d\n", size);
+
+ /* try a NULL size */
+ SetLastError(0xdeadbeef);
+ val[0] = '\0';
+ ret = RegQueryValueA(hkey_main, "subkey", val, NULL);
+ ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(lstrlenA(val) == 0, "Expected val to be untouched, got %s\n", val);
+
+ /* try a NULL value and size */
+ ret = RegQueryValueA(hkey_main, "subkey", NULL, NULL);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+
+ /* try a size too small */
+ SetLastError(0xdeadbeef);
+ val[0] = '\0';
+ size = 1;
+ ret = RegQueryValueA(hkey_main, "subkey", val, &size);
+ ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(lstrlenA(val) == 0, "Expected val to be untouched, got %s\n", val);
+ ok(size == 5, "Expected 5, got %d\n", size);
+
+ /* successfully read the value using 'subkey' */
+ size = MAX_PATH;
+ ret = RegQueryValueA(hkey_main, "subkey", val, &size);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
+ ok(size == 5, "Expected 5, got %d\n", size);
+
+ /* successfully read the value using the subkey key */
+ size = MAX_PATH;
+ ret = RegQueryValueA(subkey, NULL, val, &size);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
+ ok(size == 5, "Expected 5, got %d\n", size);
+
+ /* unicode - try size too small */
+ SetLastError(0xdeadbeef);
+ valW[0] = '\0';
+ size = 0;
+ ret = RegQueryValueW(subkey, NULL, valW, &size);
+ if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("RegQueryValueW is not implemented\n");
+ goto cleanup;
+ }
+ ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(lstrlenW(valW) == 0, "Expected valW to be untouched\n");
+ ok(size == sizeof(expected), "Got wrong size: %d\n", size);
+
+ /* unicode - try size in WCHARS */
+ SetLastError(0xdeadbeef);
+ size = sizeof(valW) / sizeof(WCHAR);
+ ret = RegQueryValueW(subkey, NULL, valW, &size);
+ ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(lstrlenW(valW) == 0, "Expected valW to be untouched\n");
+ ok(size == sizeof(expected), "Got wrong size: %d\n", size);
+
+ /* unicode - successfully read the value */
+ size = sizeof(valW);
+ ret = RegQueryValueW(subkey, NULL, valW, &size);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ok(!lstrcmpW(valW, expected), "Got wrong value\n");
+ ok(size == sizeof(expected), "Got wrong size: %d\n", size);
+
+ /* unicode - set the value without a NULL terminator */
+ ret = RegSetValueW(subkey, NULL, REG_SZ, expected, sizeof(expected)-sizeof(WCHAR));
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+
+ /* unicode - read the unterminated value, value is terminated for us */
+ memset(valW, 'a', sizeof(valW));
+ size = sizeof(valW);
+ ret = RegQueryValueW(subkey, NULL, valW, &size);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ok(!lstrcmpW(valW, expected), "Got wrong value\n");
+ ok(size == sizeof(expected), "Got wrong size: %d\n", size);
+
+cleanup:
+ RegDeleteKeyA(subkey, "");
+ RegCloseKey(subkey);
+}
+
+static void test_reg_delete_tree(void)
+{
+ CHAR buffer[MAX_PATH];
+ HKEY subkey, subkey2;
+ LONG size, ret;
+
+ if(!pRegDeleteTreeA) {
+ skip("Skipping RegDeleteTreeA tests, function not present\n");
+ return;
+ }
+
+ ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegSetValueA(subkey2, NULL, REG_SZ, "data2", 5);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegCloseKey(subkey2);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+
+ ret = pRegDeleteTreeA(subkey, "subkey2");
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
+ "subkey2 was not deleted\n");
+ size = MAX_PATH;
+ ok(!RegQueryValueA(subkey, NULL, buffer, &size),
+ "Default value of subkey not longer present\n");
+
+ ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegCloseKey(subkey2);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = pRegDeleteTreeA(hkey_main, "subkey\\subkey2");
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
+ "subkey2 was not deleted\n");
+ ok(!RegQueryValueA(subkey, NULL, buffer, &size),
+ "Default value of subkey not longer present\n");
+
+ ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegCloseKey(subkey2);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegCreateKeyA(subkey, "subkey3", &subkey2);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegCloseKey(subkey2);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = RegSetValueA(subkey, "value", REG_SZ, "data2", 5);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ret = pRegDeleteTreeA(subkey, NULL);
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
+ ok(!RegOpenKeyA(hkey_main, "subkey", &subkey),
+ "subkey was deleted\n");
+ ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
+ "subkey2 was not deleted\n");
+ ok(RegOpenKeyA(subkey, "subkey3", &subkey2),
+ "subkey3 was not deleted\n");
+ size = MAX_PATH;
+ ret = RegQueryValueA(subkey, NULL, buffer, &size);
+ ok(ret == ERROR_SUCCESS,
+ "Default value of subkey is not present\n");
+ ok(!lstrlenA(buffer),
+ "Expected length 0 got length %u(%s)\n", lstrlenA(buffer), buffer);
+ size = MAX_PATH;
+ ok(RegQueryValueA(subkey, "value", buffer, &size),
+ "Value is still present\n");
+
+ ret = pRegDeleteTreeA(hkey_main, "not-here");
+ ok(ret == ERROR_FILE_NOT_FOUND,
+ "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
+}
+
START_TEST(registry)
{
+ /* Load pointers for functions that are not available in all Windows versions */
+ InitFunctionPtrs();
+
setup_main_key();
+ test_set_value();
create_test_entries();
test_enum_value();
test_query_value_ex();
+ test_get_value();
test_reg_open_key();
+ test_reg_create_key();
test_reg_close_key();
test_reg_delete_key();
+ test_reg_query_value();
/* SaveKey/LoadKey require the SE_BACKUP_NAME privilege to be set */
if (set_privileges(SE_BACKUP_NAME, TRUE) &&
set_privileges(SE_BACKUP_NAME, FALSE);
set_privileges(SE_RESTORE_NAME, FALSE);
}
+
+ test_reg_delete_tree();
+
/* cleanup */
delete_key( hkey_main );
+
+ test_regconnectregistry();
}
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define _WIN32_WINNT 0x0501
-
+#include <stdarg.h>
#include <stdio.h>
-#include "wine/test.h"
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "aclapi.h"
#include "winnt.h"
+#include "sddl.h"
+#include "ntsecapi.h"
+#include "lmcons.h"
+
+#include "wine/test.h"
+
+/* copied from Wine winternl.h - not included in the Windows SDK */
+typedef enum _OBJECT_INFORMATION_CLASS {
+ ObjectBasicInformation,
+ ObjectNameInformation,
+ ObjectTypeInformation,
+ ObjectAllInformation,
+ ObjectDataInformation
+} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
+
+typedef struct _OBJECT_BASIC_INFORMATION {
+ ULONG Attributes;
+ ACCESS_MASK GrantedAccess;
+ ULONG HandleCount;
+ ULONG PointerCount;
+ ULONG PagedPoolUsage;
+ ULONG NonPagedPoolUsage;
+ ULONG Reserved[3];
+ ULONG NameInformationLength;
+ ULONG TypeInformationLength;
+ ULONG SecurityDescriptorLength;
+ LARGE_INTEGER CreateTime;
+} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
+
+#define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format " got " format "\n", (value), (ret)); }
-typedef BOOL (WINAPI *fnBuildTrusteeWithSidA)( TRUSTEE *trustee, PSID psid );
-typedef BOOL (WINAPI *fnBuildTrusteeWithNameA)( TRUSTEE *trustee, LPSTR str );
+static BOOL (WINAPI *pAddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
+static BOOL (WINAPI *pAddAccessDeniedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
+static BOOL (WINAPI *pAddAuditAccessAceEx)(PACL, DWORD, DWORD, DWORD, PSID, BOOL, BOOL);
+typedef VOID (WINAPI *fnBuildTrusteeWithSidA)( PTRUSTEEA pTrustee, PSID pSid );
+typedef VOID (WINAPI *fnBuildTrusteeWithNameA)( PTRUSTEEA pTrustee, LPSTR pName );
+typedef VOID (WINAPI *fnBuildTrusteeWithObjectsAndNameA)( PTRUSTEEA pTrustee,
+ POBJECTS_AND_NAME_A pObjName,
+ SE_OBJECT_TYPE ObjectType,
+ LPSTR ObjectTypeName,
+ LPSTR InheritedObjectTypeName,
+ LPSTR Name );
+typedef VOID (WINAPI *fnBuildTrusteeWithObjectsAndSidA)( PTRUSTEEA pTrustee,
+ POBJECTS_AND_SID pObjSid,
+ GUID* pObjectGuid,
+ GUID* pInheritedObjectGuid,
+ PSID pSid );
+typedef LPSTR (WINAPI *fnGetTrusteeNameA)( PTRUSTEEA pTrustee );
+typedef BOOL (WINAPI *fnMakeSelfRelativeSD)( PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD );
typedef BOOL (WINAPI *fnConvertSidToStringSidA)( PSID pSid, LPSTR *str );
typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid );
+static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD,
+ PSECURITY_DESCRIPTOR*, PULONG );
+static BOOL (WINAPI *pConvertSecurityDescriptorToStringSecurityDescriptorA)(PSECURITY_DESCRIPTOR, DWORD,
+ SECURITY_INFORMATION, LPSTR *, PULONG );
typedef BOOL (WINAPI *fnGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
+ PSID*, PSID*, PACL*, PACL*,
+ PSECURITY_DESCRIPTOR*);
+typedef DWORD (WINAPI *fnRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);
+typedef BOOL (WINAPI *fnCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*);
+typedef BOOL (WINAPI *fnDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
+ SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
+
+typedef NTSTATUS (WINAPI *fnLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*);
+typedef NTSTATUS (WINAPI *fnLsaClose)(LSA_HANDLE);
+typedef NTSTATUS (WINAPI *fnLsaFreeMemory)(PVOID);
+typedef NTSTATUS (WINAPI *fnLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE);
+static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
+static DWORD (WINAPI *pSetEntriesInAclW)(ULONG, PEXPLICIT_ACCESSW, PACL, PACL*);
+static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR_CONTROL,
+ SECURITY_DESCRIPTOR_CONTROL);
static HMODULE hmod;
+static int myARGC;
+static char** myARGV;
fnBuildTrusteeWithSidA pBuildTrusteeWithSidA;
fnBuildTrusteeWithNameA pBuildTrusteeWithNameA;
+fnBuildTrusteeWithObjectsAndNameA pBuildTrusteeWithObjectsAndNameA;
+fnBuildTrusteeWithObjectsAndSidA pBuildTrusteeWithObjectsAndSidA;
+fnGetTrusteeNameA pGetTrusteeNameA;
+fnMakeSelfRelativeSD pMakeSelfRelativeSD;
fnConvertSidToStringSidA pConvertSidToStringSidA;
fnConvertStringSidToSidA pConvertStringSidToSidA;
fnGetFileSecurityA pGetFileSecurityA;
+fnRtlAdjustPrivilege pRtlAdjustPrivilege;
+fnCreateWellKnownSid pCreateWellKnownSid;
+fnDuplicateTokenEx pDuplicateTokenEx;
+fnLsaQueryInformationPolicy pLsaQueryInformationPolicy;
+fnLsaClose pLsaClose;
+fnLsaFreeMemory pLsaFreeMemory;
+fnLsaOpenPolicy pLsaOpenPolicy;
struct sidRef
{
static void init(void)
{
+ HMODULE hntdll;
+
+ hntdll = GetModuleHandleA("ntdll.dll");
+ pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" );
+
hmod = GetModuleHandle("advapi32.dll");
+ pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx");
+ pAddAccessDeniedAceEx = (void *)GetProcAddress(hmod, "AddAccessDeniedAceEx");
+ pAddAuditAccessAceEx = (void *)GetProcAddress(hmod, "AddAuditAccessAceEx");
+ pConvertStringSecurityDescriptorToSecurityDescriptorA =
+ (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" );
+ pConvertSecurityDescriptorToStringSecurityDescriptorA =
+ (void *)GetProcAddress(hmod, "ConvertSecurityDescriptorToStringSecurityDescriptorA" );
+ pCreateWellKnownSid = (fnCreateWellKnownSid)GetProcAddress( hmod, "CreateWellKnownSid" );
+ pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA");
+ pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD");
+ pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW");
+ pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
+
+ myARGC = winetest_get_mainargs( &myARGV );
+}
+
+static void test_str_sid(const char *str_sid)
+{
+ PSID psid;
+ char *temp;
+
+ if (pConvertStringSidToSidA(str_sid, &psid))
+ {
+ if (pConvertSidToStringSidA(psid, &temp))
+ {
+ trace(" %s: %s\n", str_sid, temp);
+ LocalFree(temp);
+ }
+ LocalFree(psid);
+ }
+ else
+ {
+ if (GetLastError() != ERROR_INVALID_SID)
+ trace(" %s: couldn't be converted, returned %d\n", str_sid, GetLastError());
+ else
+ trace(" %s: couldn't be converted\n", str_sid);
+ }
}
-void test_sid()
+static void test_sid(void)
{
struct sidRef refs[] = {
{ { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" },
const char noSubAuthStr[] = "S-1-5";
unsigned int i;
PSID psid = NULL;
+ SID *pisid;
BOOL r;
LPSTR str = NULL;
if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
return;
ok( GetLastError() == ERROR_INVALID_PARAMETER,
- "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
+ "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
GetLastError() );
r = pConvertStringSidToSidA( refs[0].refStr, NULL );
ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
- "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
+ "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
GetLastError() );
r = pConvertStringSidToSidA( NULL, &str );
ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
- "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
+ "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
GetLastError() );
r = pConvertStringSidToSidA( noSubAuthStr, &psid );
ok( !r,
"expected failure with no sub authorities\n" );
ok( GetLastError() == ERROR_INVALID_SID,
- "expected GetLastError() is ERROR_INVALID_SID, got %ld\n",
+ "expected GetLastError() is ERROR_INVALID_SID, got %d\n",
GetLastError() );
+ ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid), "ConvertStringSidToSidA failed\n");
+ pisid = (SID *)psid;
+ ok(pisid->SubAuthorityCount == 4, "Invalid sub authority count - expected 4, got %d\n", pisid->SubAuthorityCount);
+ ok(pisid->SubAuthority[0] == 21, "Invalid subauthority 0 - expceted 21, got %d\n", pisid->SubAuthority[0]);
+ ok(pisid->SubAuthority[3] == 4576, "Invalid subauthority 0 - expceted 4576, got %d\n", pisid->SubAuthority[3]);
+ LocalFree(str);
+
for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ )
{
PISID pisid;
!memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value,
sizeof(refs[i].auth) ),
"string sid %s didn't parse to expected value\n"
- "(got 0x%04x%08lx, expected 0x%04x%08lx)\n",
+ "(got 0x%04x%08x, expected 0x%04x%08x)\n",
refs[i].refStr,
MAKEWORD( pisid->IdentifierAuthority.Value[1],
pisid->IdentifierAuthority.Value[0] ),
if( psid )
LocalFree( psid );
}
+
+ trace("String SIDs:\n");
+ test_str_sid("AO");
+ test_str_sid("RU");
+ test_str_sid("AN");
+ test_str_sid("AU");
+ test_str_sid("BA");
+ test_str_sid("BG");
+ test_str_sid("BO");
+ test_str_sid("BU");
+ test_str_sid("CA");
+ test_str_sid("CG");
+ test_str_sid("CO");
+ test_str_sid("DA");
+ test_str_sid("DC");
+ test_str_sid("DD");
+ test_str_sid("DG");
+ test_str_sid("DU");
+ test_str_sid("EA");
+ test_str_sid("ED");
+ test_str_sid("WD");
+ test_str_sid("PA");
+ test_str_sid("IU");
+ test_str_sid("LA");
+ test_str_sid("LG");
+ test_str_sid("LS");
+ test_str_sid("SY");
+ test_str_sid("NU");
+ test_str_sid("NO");
+ test_str_sid("NS");
+ test_str_sid("PO");
+ test_str_sid("PS");
+ test_str_sid("PU");
+ test_str_sid("RS");
+ test_str_sid("RD");
+ test_str_sid("RE");
+ test_str_sid("RC");
+ test_str_sid("SA");
+ test_str_sid("SO");
+ test_str_sid("SU");
}
-void test_trustee()
+static void test_trustee(void)
{
+ GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}};
+ GUID InheritedObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};
+ GUID ZeroGuid;
+ OBJECTS_AND_NAME_ oan;
+ OBJECTS_AND_SID oas;
TRUSTEE trustee;
PSID psid;
- LPSTR str = "2jjj";
-
+ char szObjectTypeName[] = "ObjectTypeName";
+ char szInheritedObjectTypeName[] = "InheritedObjectTypeName";
+ char szTrusteeName[] = "szTrusteeName";
SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
+ memset( &ZeroGuid, 0x00, sizeof (ZeroGuid) );
+
pBuildTrusteeWithSidA = (fnBuildTrusteeWithSidA)
GetProcAddress( hmod, "BuildTrusteeWithSidA" );
pBuildTrusteeWithNameA = (fnBuildTrusteeWithNameA)
GetProcAddress( hmod, "BuildTrusteeWithNameA" );
- if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA)
+ pBuildTrusteeWithObjectsAndNameA = (fnBuildTrusteeWithObjectsAndNameA)
+ GetProcAddress (hmod, "BuildTrusteeWithObjectsAndNameA" );
+ pBuildTrusteeWithObjectsAndSidA = (fnBuildTrusteeWithObjectsAndSidA)
+ GetProcAddress (hmod, "BuildTrusteeWithObjectsAndSidA" );
+ pGetTrusteeNameA = (fnGetTrusteeNameA)
+ GetProcAddress (hmod, "GetTrusteeNameA" );
+ if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA ||
+ !pBuildTrusteeWithObjectsAndNameA || !pBuildTrusteeWithObjectsAndSidA ||
+ !pGetTrusteeNameA )
return;
if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) )
return;
}
+ /* test BuildTrusteeWithSidA */
memset( &trustee, 0xff, sizeof trustee );
pBuildTrusteeWithSidA( &trustee, psid );
ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
- ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
+ ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
"MultipleTrusteeOperation wrong\n");
ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n");
ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
ok( trustee.ptstrName == (LPSTR) psid, "ptstrName wrong\n" );
+
+ /* test BuildTrusteeWithObjectsAndSidA (test 1) */
+ memset( &trustee, 0xff, sizeof trustee );
+ memset( &oas, 0xff, sizeof(oas) );
+ pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, &ObjectType,
+ &InheritedObjectType, psid);
+
+ ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
+ ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
+ ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
+ ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
+ ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
+
+ ok(oas.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
+ ok(!memcmp(&oas.ObjectTypeGuid, &ObjectType, sizeof(GUID)), "ObjectTypeGuid wrong\n");
+ ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
+ ok(oas.pSid == psid, "pSid wrong\n");
+
+ /* test GetTrusteeNameA */
+ ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oas, "GetTrusteeName returned wrong value\n");
+
+ /* test BuildTrusteeWithObjectsAndSidA (test 2) */
+ memset( &trustee, 0xff, sizeof trustee );
+ memset( &oas, 0xff, sizeof(oas) );
+ pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, NULL,
+ &InheritedObjectType, psid);
+
+ ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
+ ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
+ ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
+ ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
+ ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
+
+ ok(oas.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
+ ok(!memcmp(&oas.ObjectTypeGuid, &ZeroGuid, sizeof(GUID)), "ObjectTypeGuid wrong\n");
+ ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
+ ok(oas.pSid == psid, "pSid wrong\n");
+
FreeSid( psid );
/* test BuildTrusteeWithNameA */
memset( &trustee, 0xff, sizeof trustee );
- pBuildTrusteeWithNameA( &trustee, str );
+ pBuildTrusteeWithNameA( &trustee, szTrusteeName );
ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
- ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
+ ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
"MultipleTrusteeOperation wrong\n");
ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n");
ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
- ok( trustee.ptstrName == str, "ptstrName wrong\n" );
-}
+ ok( trustee.ptstrName == szTrusteeName, "ptstrName wrong\n" );
+
+ /* test BuildTrusteeWithObjectsAndNameA (test 1) */
+ memset( &trustee, 0xff, sizeof trustee );
+ memset( &oan, 0xff, sizeof(oan) );
+ pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
+ szInheritedObjectTypeName, szTrusteeName);
+
+ ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
+ ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
+ ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
+ ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
+ ok(trustee.ptstrName == (LPTSTR)&oan, "ptstrName wrong\n");
+
+ ok(oan.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
+ ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
+ ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
+ ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
+
+ /* test GetTrusteeNameA */
+ ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oan, "GetTrusteeName returned wrong value\n");
+
+ /* test BuildTrusteeWithObjectsAndNameA (test 2) */
+ memset( &trustee, 0xff, sizeof trustee );
+ memset( &oan, 0xff, sizeof(oan) );
+ pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, NULL,
+ szInheritedObjectTypeName, szTrusteeName);
+
+ ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
+ ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
+ ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
+ ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
+ ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
+
+ ok(oan.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
+ ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
+ ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
+ ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
+ /* test BuildTrusteeWithObjectsAndNameA (test 3) */
+ memset( &trustee, 0xff, sizeof trustee );
+ memset( &oan, 0xff, sizeof(oan) );
+ pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
+ NULL, szTrusteeName);
+
+ ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
+ ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
+ ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
+ ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
+ ok(trustee.ptstrName == (LPTSTR)&oan, "ptstrName wrong\n");
+
+ ok(oan.ObjectsPresent == ACE_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
+ ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
+ ok(oan.InheritedObjectTypeName == NULL, "InheritedObjectTypeName wrong\n");
+ ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
+}
+
/* If the first isn't defined, assume none is */
#ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
#define SE_MIN_WELL_KNOWN_PRIVILEGE 2L
return;
ok(ret,
- "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
+ "AllocateLocallyUniqueId failed: %d\n", GetLastError());
ret = pAllocateLocallyUniqueId(&luid2);
ok( ret,
- "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
+ "AllocateLocallyUniqueId failed: %d\n", GetLastError());
ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0,
"AllocateLocallyUniqueId returned a well-known LUID\n");
ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart,
"AllocateLocallyUniqueId returned non-unique LUIDs\n");
ret = pAllocateLocallyUniqueId(NULL);
ok( !ret && GetLastError() == ERROR_NOACCESS,
- "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %ld\n",
+ "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %d\n",
GetLastError());
}
static void test_lookupPrivilegeName(void)
{
- BOOL (WINAPI *pLookupPrivilegeNameA)(LPSTR, PLUID, LPSTR, LPDWORD);
+ BOOL (WINAPI *pLookupPrivilegeNameA)(LPCSTR, PLUID, LPSTR, LPDWORD);
char buf[MAX_PATH]; /* arbitrary, seems long enough */
DWORD cchName = sizeof(buf);
LUID luid = { 0, 0 };
luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName);
ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
- "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %ld\n",
+ "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %d\n",
GetLastError());
ok(cchName == strlen("SeCreateTokenPrivilege") + 1,
"LookupPrivilegeNameA returned an incorrect required length for\n"
- "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName,
- strlen("SeCreateTokenPrivilege") + 1);
+ "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
+ lstrlenA("SeCreateTokenPrivilege") + 1);
/* check a known value and its returned length on success */
cchName = sizeof(buf);
ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) &&
cchName == strlen("SeCreateTokenPrivilege"),
"LookupPrivilegeNameA returned an incorrect output length for\n"
- "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName,
+ "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
(int)strlen("SeCreateTokenPrivilege"));
/* check known values */
for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i < SE_MAX_WELL_KNOWN_PRIVILEGE; i++)
cchName = sizeof(buf);
ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
- "LookupPrivilegeNameA(0.%ld) failed: %ld\n", i, GetLastError());
+ "LookupPrivilegeNameA(0.%d) failed: %d\n", i, GetLastError());
}
/* check a bogus LUID */
luid.LowPart = 0xdeadbeef;
cchName = sizeof(buf);
ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
- "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
+ "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
GetLastError());
/* check on a bogus system */
luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
cchName = sizeof(buf);
ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
- "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE: %ld\n",
+ "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE: %d\n",
GetLastError());
}
/* check a bogus system name */
ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
- "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE: %ld\n",
+ "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE: %d\n",
GetLastError());
/* check a NULL string */
ret = pLookupPrivilegeValueA(NULL, 0, &luid);
ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
- "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
+ "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
GetLastError());
/* check a bogus privilege name */
ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid);
ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
- "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
+ "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
GetLastError());
/* check case insensitive */
ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid);
ok( ret,
- "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %ld\n",
+ "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %d\n",
GetLastError());
for (i = 0; i < sizeof(privs) / sizeof(privs[0]); i++)
{
strcpy(directory, "\\Should not exist");
SetLastError(NO_ERROR);
- result = GetFileSecurityA( directory,OWNER_SECURITY_INFORMATION,
- (PSECURITY_DESCRIPTOR)buffer,0x40,&outSize);
- ok(!result, "GetFileSecurityA should fail for not existing directories/files\n");
+ result = pGetFileSecurityA( directory,OWNER_SECURITY_INFORMATION,buffer,0x40,&outSize);
+ ok(!result, "GetFileSecurityA should fail for not existing directories/files\n");
ok( (GetLastError() == ERROR_FILE_NOT_FOUND ) ||
- (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) ,
+ (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) ,
"last error ERROR_FILE_NOT_FOUND / ERROR_CALL_NOT_IMPLEMENTED (98) "
- "expected, got %ld\n", GetLastError());
+ "expected, got %d\n", GetLastError());
+}
+
+static void test_AccessCheck(void)
+{
+ PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
+ PACL Acl = NULL;
+ SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
+ SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
+ SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
+ GENERIC_MAPPING Mapping = { KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS };
+ ACCESS_MASK Access;
+ BOOL AccessStatus;
+ HANDLE Token;
+ HANDLE ProcessToken;
+ BOOL ret;
+ DWORD PrivSetLen;
+ PRIVILEGE_SET *PrivSet;
+ BOOL res;
+ HMODULE NtDllModule;
+ BOOLEAN Enabled;
+ DWORD err;
+
+ NtDllModule = GetModuleHandle("ntdll.dll");
+ if (!NtDllModule)
+ {
+ skip("not running on NT, skipping test\n");
+ return;
+ }
+ pRtlAdjustPrivilege = (fnRtlAdjustPrivilege)
+ GetProcAddress(NtDllModule, "RtlAdjustPrivilege");
+ if (!pRtlAdjustPrivilege)
+ {
+ skip("missing RtlAdjustPrivilege, skipping test\n");
+ return;
+ }
+
+ Acl = HeapAlloc(GetProcessHeap(), 0, 256);
+ res = InitializeAcl(Acl, 256, ACL_REVISION);
+ if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("ACLs not implemented - skipping tests\n");
+ HeapFree(GetProcessHeap(), 0, Acl);
+ return;
+ }
+ ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+
+ res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
+ ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
+ res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
+ ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
+ res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
+ ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
+ SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+ res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
+ ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
+
+ res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
+ ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+
+ PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
+ PrivSet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PrivSetLen);
+ PrivSet->PrivilegeCount = 16;
+
+ res = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &ProcessToken);
+ ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
+
+ pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, FALSE, TRUE, &Enabled);
+
+ res = DuplicateToken(ProcessToken, SecurityImpersonation, &Token);
+ ok(res, "DuplicateToken failed with error %d\n", GetLastError());
+
+ /* SD without owner/group */
+ SetLastError(0xdeadbeef);
+ Access = AccessStatus = 0xdeadbeef;
+ ret = AccessCheck(SecurityDescriptor, Token, KEY_QUERY_VALUE, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ err = GetLastError();
+ ok(!ret && err == ERROR_INVALID_SECURITY_DESCR, "AccessCheck should have "
+ "failed with ERROR_INVALID_SECURITY_DESCR, instead of %d\n", err);
+ ok(Access == 0xdeadbeef && AccessStatus == 0xdeadbeef,
+ "Access and/or AccessStatus were changed!\n");
+
+ /* Set owner and group */
+ res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
+ ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, TRUE);
+ ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+
+ /* Generic access mask */
+ SetLastError(0xdeadbeef);
+ ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ err = GetLastError();
+ ok(!ret && err == ERROR_GENERIC_NOT_MAPPED, "AccessCheck should have failed "
+ "with ERROR_GENERIC_NOT_MAPPED, instead of %d\n", err);
+ ok(Access == 0xdeadbeef && AccessStatus == 0xdeadbeef,
+ "Access and/or AccessStatus were changed!\n");
+
+ /* sd with no dacl present */
+ ret = SetSecurityDescriptorDacl(SecurityDescriptor, FALSE, NULL, FALSE);
+ ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret, "AccessCheck failed with error %d\n", GetLastError());
+ ok(AccessStatus && (Access == KEY_READ),
+ "AccessCheck failed to grant access with error %d\n",
+ GetLastError());
+
+ /* sd with NULL dacl */
+ ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, NULL, FALSE);
+ ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret, "AccessCheck failed with error %d\n", GetLastError());
+ ok(AccessStatus && (Access == KEY_READ),
+ "AccessCheck failed to grant access with error %d\n",
+ GetLastError());
+
+ /* sd with blank dacl */
+ ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
+ ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret, "AccessCheck failed with error %d\n", GetLastError());
+ err = GetLastError();
+ ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
+ "with ERROR_ACCESS_DENIED, instead of %d\n", err);
+ ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
+
+ res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, EveryoneSid);
+ ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
+
+ res = AddAccessDeniedAce(Acl, ACL_REVISION, KEY_SET_VALUE, AdminSid);
+ ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
+
+ /* sd with dacl */
+ ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret, "AccessCheck failed with error %d\n", GetLastError());
+ ok(AccessStatus && (Access == KEY_READ),
+ "AccessCheck failed to grant access with error %d\n",
+ GetLastError());
+
+ ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret, "AccessCheck failed with error %d\n", GetLastError());
+ ok(AccessStatus,
+ "AccessCheck failed to grant any access with error %d\n",
+ GetLastError());
+ trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08x\n", Access);
+
+ /* Access denied by SD */
+ SetLastError(0xdeadbeef);
+ ret = AccessCheck(SecurityDescriptor, Token, KEY_WRITE, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret, "AccessCheck failed with error %d\n", GetLastError());
+ err = GetLastError();
+ ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
+ "with ERROR_ACCESS_DENIED, instead of %d\n", err);
+ ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
+
+ SetLastError(0);
+ PrivSet->PrivilegeCount = 16;
+ ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret && !AccessStatus && GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
+ "AccessCheck should have failed with ERROR_PRIVILEGE_NOT_HELD, instead of %d\n",
+ GetLastError());
+
+ ret = ImpersonateLoggedOnUser(Token);
+ ok(ret, "ImpersonateLoggedOnUser failed with error %d\n", GetLastError());
+ ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled);
+ if (!ret)
+ {
+ SetLastError(0);
+ PrivSet->PrivilegeCount = 16;
+ ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret && AccessStatus && GetLastError() == 0,
+ "AccessCheck should have succeeded, error %d\n",
+ GetLastError());
+ ok(Access == ACCESS_SYSTEM_SECURITY,
+ "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n",
+ Access);
+ }
+ else
+ trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n",
+ ret);
+ ret = RevertToSelf();
+ ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
+
+ /* test INHERIT_ONLY_ACE */
+ ret = InitializeAcl(Acl, 256, ACL_REVISION);
+ ok(ret, "InitializeAcl failed with error %d\n", GetLastError());
+
+ /* NT doesn't have AddAccessAllowedAceEx. Skipping this call/test doesn't influence
+ * the next ones.
+ */
+ if (pAddAccessAllowedAceEx)
+ {
+ ret = pAddAccessAllowedAceEx(Acl, ACL_REVISION, INHERIT_ONLY_ACE, KEY_READ, EveryoneSid);
+ ok(ret, "AddAccessAllowedAceEx failed with error %d\n", GetLastError());
+ }
+ else
+ skip("AddAccessAllowedAceEx is not available\n");
+
+ ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ ok(ret, "AccessCheck failed with error %d\n", GetLastError());
+ err = GetLastError();
+ ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
+ "with ERROR_ACCESS_DENIED, instead of %d\n", err);
+ ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
+
+ CloseHandle(Token);
+
+ res = DuplicateToken(ProcessToken, SecurityAnonymous, &Token);
+ ok(res, "DuplicateToken failed with error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ err = GetLastError();
+ ok(!ret && err == ERROR_BAD_IMPERSONATION_LEVEL, "AccessCheck should have failed "
+ "with ERROR_BAD_IMPERSONATION_LEVEL, instead of %d\n", err);
+
+ CloseHandle(Token);
+
+ SetLastError(0xdeadbeef);
+ ret = AccessCheck(SecurityDescriptor, ProcessToken, KEY_READ, &Mapping,
+ PrivSet, &PrivSetLen, &Access, &AccessStatus);
+ err = GetLastError();
+ ok(!ret && err == ERROR_NO_IMPERSONATION_TOKEN, "AccessCheck should have failed "
+ "with ERROR_NO_IMPERSONATION_TOKEN, instead of %d\n", err);
+
+ CloseHandle(ProcessToken);
+
+ if (EveryoneSid)
+ FreeSid(EveryoneSid);
+ if (AdminSid)
+ FreeSid(AdminSid);
+ if (UsersSid)
+ FreeSid(UsersSid);
+ HeapFree(GetProcessHeap(), 0, Acl);
+ HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
+ HeapFree(GetProcessHeap(), 0, PrivSet);
+}
+
+/* test GetTokenInformation for the various attributes */
+static void test_token_attr(void)
+{
+ HANDLE Token, ImpersonationToken;
+ DWORD Size;
+ TOKEN_PRIVILEGES *Privileges;
+ TOKEN_GROUPS *Groups;
+ TOKEN_USER *User;
+ BOOL ret;
+ DWORD i, GLE;
+ LPSTR SidString;
+ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+
+ /* cygwin-like use case */
+ SetLastError(0xdeadbeef);
+ ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token);
+ if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ skip("OpenProcessToken is not implemented\n");
+ return;
+ }
+ ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
+ if (ret)
+ {
+ BYTE buf[1024];
+ Size = sizeof(buf);
+ ret = GetTokenInformation(Token, TokenUser,(void*)buf, Size, &Size);
+ ok(ret, "GetTokenInformation failed with error %d\n", GetLastError());
+ Size = sizeof(ImpersonationLevel);
+ ret = GetTokenInformation(Token, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
+ GLE = GetLastError();
+ ok(!ret && (GLE == ERROR_INVALID_PARAMETER), "GetTokenInformation(TokenImpersonationLevel) on primary token should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GLE);
+ CloseHandle(Token);
+ }
+
+ if(!pConvertSidToStringSidA)
+ {
+ skip("ConvertSidToStringSidA is not available\n");
+ return;
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &Token);
+ ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
+
+ /* groups */
+ ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size);
+ Groups = HeapAlloc(GetProcessHeap(), 0, Size);
+ ret = GetTokenInformation(Token, TokenGroups, Groups, Size, &Size);
+ ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError());
+ trace("TokenGroups:\n");
+ for (i = 0; i < Groups->GroupCount; i++)
+ {
+ DWORD NameLength = 255;
+ TCHAR Name[255];
+ DWORD DomainLength = 255;
+ TCHAR Domain[255];
+ SID_NAME_USE SidNameUse;
+ pConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
+ Name[0] = '\0';
+ Domain[0] = '\0';
+ ret = LookupAccountSid(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
+ if (ret)
+ trace("\t%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes);
+ else
+ trace("\t%s, attr: 0x%08x LookupAccountSid failed with error %d\n", SidString, Groups->Groups[i].Attributes, GetLastError());
+ LocalFree(SidString);
+ }
+ HeapFree(GetProcessHeap(), 0, Groups);
+
+ /* user */
+ ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
+ ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
+ "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+ User = HeapAlloc(GetProcessHeap(), 0, Size);
+ ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
+ ok(ret,
+ "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+
+ pConvertSidToStringSidA(User->User.Sid, &SidString);
+ trace("TokenUser: %s attr: 0x%08x\n", SidString, User->User.Attributes);
+ LocalFree(SidString);
+ HeapFree(GetProcessHeap(), 0, User);
+
+ /* privileges */
+ ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
+ ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
+ "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
+ Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
+ ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
+ ok(ret,
+ "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
+ trace("TokenPrivileges:\n");
+ for (i = 0; i < Privileges->PrivilegeCount; i++)
+ {
+ TCHAR Name[256];
+ DWORD NameLen = sizeof(Name)/sizeof(Name[0]);
+ LookupPrivilegeName(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen);
+ trace("\t%s, 0x%x\n", Name, Privileges->Privileges[i].Attributes);
+ }
+ HeapFree(GetProcessHeap(), 0, Privileges);
+
+ ret = DuplicateToken(Token, SecurityAnonymous, &ImpersonationToken);
+ ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
+
+ Size = sizeof(ImpersonationLevel);
+ ret = GetTokenInformation(ImpersonationToken, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
+ ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
+ ok(ImpersonationLevel == SecurityAnonymous, "ImpersonationLevel should have been SecurityAnonymous instead of %d\n", ImpersonationLevel);
+
+ CloseHandle(ImpersonationToken);
+ CloseHandle(Token);
+}
+
+typedef union _MAX_SID
+{
+ SID sid;
+ char max[SECURITY_MAX_SID_SIZE];
+} MAX_SID;
+
+static void test_sid_str(PSID * sid)
+{
+ char *str_sid;
+ BOOL ret = pConvertSidToStringSidA(sid, &str_sid);
+ ok(ret, "ConvertSidToStringSidA() failed: %d\n", GetLastError());
+ if (ret)
+ {
+ char account[MAX_PATH], domain[MAX_PATH];
+ SID_NAME_USE use;
+ DWORD acc_size = MAX_PATH;
+ DWORD dom_size = MAX_PATH;
+ ret = LookupAccountSid(NULL, sid, account, &acc_size, domain, &dom_size, &use);
+ ok(ret || (!ret && (GetLastError() == ERROR_NONE_MAPPED)),
+ "LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError());
+ if (ret)
+ trace(" %s %s\\%s %d\n", str_sid, domain, account, use);
+ else if (GetLastError() == ERROR_NONE_MAPPED)
+ trace(" %s couldn't be mapped\n", str_sid);
+ LocalFree(str_sid);
+ }
+}
+
+struct well_known_sid_value
+{
+ BOOL without_domain;
+ const char *sid_string;
+} well_known_sid_values[] = {
+/* 0 */ {TRUE, "S-1-0-0"}, {TRUE, "S-1-1-0"}, {TRUE, "S-1-2-0"}, {TRUE, "S-1-3-0"},
+/* 4 */ {TRUE, "S-1-3-1"}, {TRUE, "S-1-3-2"}, {TRUE, "S-1-3-3"}, {TRUE, "S-1-5"},
+/* 8 */ {FALSE, "S-1-5-1"}, {TRUE, "S-1-5-2"}, {TRUE, "S-1-5-3"}, {TRUE, "S-1-5-4"},
+/* 12 */ {TRUE, "S-1-5-6"}, {TRUE, "S-1-5-7"}, {TRUE, "S-1-5-8"}, {TRUE, "S-1-5-9"},
+/* 16 */ {TRUE, "S-1-5-10"}, {TRUE, "S-1-5-11"}, {TRUE, "S-1-5-12"}, {TRUE, "S-1-5-13"},
+/* 20 */ {TRUE, "S-1-5-14"}, {FALSE, NULL}, {TRUE, "S-1-5-18"}, {TRUE, "S-1-5-19"},
+/* 24 */ {TRUE, "S-1-5-20"}, {TRUE, "S-1-5-32"},
+/* 26 */ {FALSE, "S-1-5-32-544"}, {TRUE, "S-1-5-32-545"}, {TRUE, "S-1-5-32-546"},
+/* 29 */ {TRUE, "S-1-5-32-547"}, {TRUE, "S-1-5-32-548"}, {TRUE, "S-1-5-32-549"},
+/* 32 */ {TRUE, "S-1-5-32-550"}, {TRUE, "S-1-5-32-551"}, {TRUE, "S-1-5-32-552"},
+/* 35 */ {TRUE, "S-1-5-32-554"}, {TRUE, "S-1-5-32-555"}, {TRUE, "S-1-5-32-556"},
+/* 38 */ {FALSE, "S-1-5-21-12-23-34-45-56-500"}, {FALSE, "S-1-5-21-12-23-34-45-56-501"},
+/* 40 */ {FALSE, "S-1-5-21-12-23-34-45-56-502"}, {FALSE, "S-1-5-21-12-23-34-45-56-512"},
+/* 42 */ {FALSE, "S-1-5-21-12-23-34-45-56-513"}, {FALSE, "S-1-5-21-12-23-34-45-56-514"},
+/* 44 */ {FALSE, "S-1-5-21-12-23-34-45-56-515"}, {FALSE, "S-1-5-21-12-23-34-45-56-516"},
+/* 46 */ {FALSE, "S-1-5-21-12-23-34-45-56-517"}, {FALSE, "S-1-5-21-12-23-34-45-56-518"},
+/* 48 */ {FALSE, "S-1-5-21-12-23-34-45-56-519"}, {FALSE, "S-1-5-21-12-23-34-45-56-520"},
+/* 50 */ {FALSE, "S-1-5-21-12-23-34-45-56-553"},
+/* Added in Windows Server 2003 */
+/* 51 */ {TRUE, "S-1-5-64-10"}, {TRUE, "S-1-5-64-21"}, {TRUE, "S-1-5-64-14"},
+/* 54 */ {TRUE, "S-1-5-15"}, {TRUE, "S-1-5-1000"}, {FALSE, "S-1-5-32-557"},
+/* 57 */ {TRUE, "S-1-5-32-558"}, {TRUE, "S-1-5-32-559"}, {TRUE, "S-1-5-32-560"},
+/* 60 */ {TRUE, "S-1-5-32-561"}, {TRUE, "S-1-5-32-562"},
+/* Added in Windows Vista: */
+/* 62 */ {TRUE, "S-1-5-32-568"},
+/* 63 */ {TRUE, "S-1-5-17"}, {FALSE, "S-1-5-32-569"}, {TRUE, "S-1-16-0"},
+/* 66 */ {TRUE, "S-1-16-4096"}, {TRUE, "S-1-16-8192"}, {TRUE, "S-1-16-12288"},
+/* 69 */ {TRUE, "S-1-16-16384"}, {TRUE, "S-1-5-33"}, {TRUE, "S-1-3-4"},
+/* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"}, {FALSE, "S-1-5-21-12-23-34-45-56-572"},
+/* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"}
+};
+
+static void test_CreateWellKnownSid()
+{
+ SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
+ PSID domainsid;
+ int i;
+
+ if (!pCreateWellKnownSid)
+ {
+ skip("CreateWellKnownSid not available\n");
+ return;
+ }
+
+ /* a domain sid usually have three subauthorities but we test that CreateWellKnownSid doesn't check it */
+ AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
+
+ for (i = 0; i < sizeof(well_known_sid_values)/sizeof(well_known_sid_values[0]); i++)
+ {
+ struct well_known_sid_value *value = &well_known_sid_values[i];
+ char sid_buffer[SECURITY_MAX_SID_SIZE];
+ LPSTR str;
+ DWORD cb;
+
+ if (value->sid_string == NULL)
+ continue;
+
+ if (i > WinAccountRasAndIasServersSid)
+ {
+ /* These SIDs aren't implemented by all Windows versions - detect it and break the loop */
+ cb = sizeof(sid_buffer);
+ if (!pCreateWellKnownSid(i, domainsid, sid_buffer, &cb))
+ {
+ skip("Well known SIDs starting from %d are not implemented\n", i);
+ break;
+ }
+ }
+
+ cb = sizeof(sid_buffer);
+ ok(pCreateWellKnownSid(i, value->without_domain ? NULL : domainsid, sid_buffer, &cb), "Couldn't create well known sid %d\n", i);
+ expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
+ ok(IsValidSid(sid_buffer), "The sid is not valid\n");
+ ok(pConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n");
+ ok(strcmp(str, value->sid_string) == 0, "SID mismatch - expected %s, got %s\n",
+ value->sid_string, str);
+ LocalFree(str);
+
+ if (value->without_domain)
+ {
+ char buf2[SECURITY_MAX_SID_SIZE];
+ cb = sizeof(buf2);
+ ok(pCreateWellKnownSid(i, domainsid, buf2, &cb), "Couldn't create well known sid %d with optional domain\n", i);
+ expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
+ ok(memcmp(buf2, sid_buffer, cb) == 0, "SID create with domain is different than without (%d)\n", i);
+ }
+ }
+}
+
+static void test_LookupAccountSid(void)
+{
+ SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
+ CHAR accountA[MAX_PATH], domainA[MAX_PATH];
+ DWORD acc_sizeA, dom_sizeA;
+ DWORD real_acc_sizeA, real_dom_sizeA;
+ WCHAR accountW[MAX_PATH], domainW[MAX_PATH];
+ DWORD acc_sizeW, dom_sizeW;
+ DWORD real_acc_sizeW, real_dom_sizeW;
+ PSID pUsersSid = NULL;
+ SID_NAME_USE use;
+ BOOL ret;
+ DWORD size;
+ MAX_SID max_sid;
+ CHAR *str_sidA;
+ int i;
+
+ /* native windows crashes if account size, domain size, or name use is NULL */
+
+ ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pUsersSid);
+ ok(ret || (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED),
+ "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
+ /* not running on NT so give up */
+ if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ return;
+
+ real_acc_sizeA = MAX_PATH;
+ real_dom_sizeA = MAX_PATH;
+ ret = LookupAccountSidA(NULL, pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
+ ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
+
+ /* try NULL account */
+ acc_sizeA = MAX_PATH;
+ dom_sizeA = MAX_PATH;
+ ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
+ ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
+
+ /* try NULL domain */
+ acc_sizeA = MAX_PATH;
+ dom_sizeA = MAX_PATH;
+ ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
+ ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
+
+ /* try a small account buffer */
+ acc_sizeA = 1;
+ dom_sizeA = MAX_PATH;
+ accountA[0] = 0;
+ ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
+ ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
+
+ /* try a 0 sized account buffer */
+ acc_sizeA = 0;
+ dom_sizeA = MAX_PATH;
+ accountA[0] = 0;
+ ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
+ /* this can fail or succeed depending on OS version but the size will always be returned */
+ ok(acc_sizeA == real_acc_sizeA + 1,
+ "LookupAccountSidA() Expected acc_size = %u, got %u\n",
+ real_acc_sizeA + 1, acc_sizeA);
+
+ /* try a 0 sized account buffer */
+ acc_sizeA = 0;
+ dom_sizeA = MAX_PATH;
+ ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
+ /* this can fail or succeed depending on OS version but the size will always be returned */
+ ok(acc_sizeA == real_acc_sizeA + 1,
+ "LookupAccountSid() Expected acc_size = %u, got %u\n",
+ real_acc_sizeA + 1, acc_sizeA);
+
+ /* try a small domain buffer */
+ dom_sizeA = 1;
+ acc_sizeA = MAX_PATH;
+ accountA[0] = 0;
+ ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
+ ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
+
+ /* try a 0 sized domain buffer */
+ dom_sizeA = 0;
+ acc_sizeA = MAX_PATH;
+ accountA[0] = 0;
+ ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
+ /* this can fail or succeed depending on OS version but the size will always be returned */
+ ok(dom_sizeA == real_dom_sizeA + 1,
+ "LookupAccountSidA() Expected dom_size = %u, got %u\n",
+ real_dom_sizeA + 1, dom_sizeA);
+
+ /* try a 0 sized domain buffer */
+ dom_sizeA = 0;
+ acc_sizeA = MAX_PATH;
+ ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
+ /* this can fail or succeed depending on OS version but the size will always be returned */
+ ok(dom_sizeA == real_dom_sizeA + 1,
+ "LookupAccountSidA() Expected dom_size = %u, got %u\n",
+ real_dom_sizeA + 1, dom_sizeA);
+
+ real_acc_sizeW = MAX_PATH;
+ real_dom_sizeW = MAX_PATH;
+ ret = LookupAccountSidW(NULL, pUsersSid, accountW, &real_acc_sizeW, domainW, &real_dom_sizeW, &use);
+ ok(ret, "LookupAccountSidW() Expected TRUE, got FALSE\n");
+
+ /* native windows crashes if domainW or accountW is NULL */
+
+ /* try a small account buffer */
+ acc_sizeW = 1;
+ dom_sizeW = MAX_PATH;
+ accountW[0] = 0;
+ ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
+ ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
+
+ /* try a 0 sized account buffer */
+ acc_sizeW = 0;
+ dom_sizeW = MAX_PATH;
+ accountW[0] = 0;
+ ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
+ /* this can fail or succeed depending on OS version but the size will always be returned */
+ ok(acc_sizeW == real_acc_sizeW + 1,
+ "LookupAccountSidW() Expected acc_size = %u, got %u\n",
+ real_acc_sizeW + 1, acc_sizeW);
+
+ /* try a 0 sized account buffer */
+ acc_sizeW = 0;
+ dom_sizeW = MAX_PATH;
+ ret = LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, domainW, &dom_sizeW, &use);
+ /* this can fail or succeed depending on OS version but the size will always be returned */
+ ok(acc_sizeW == real_acc_sizeW + 1,
+ "LookupAccountSidW() Expected acc_size = %u, got %u\n",
+ real_acc_sizeW + 1, acc_sizeW);
+
+ /* try a small domain buffer */
+ dom_sizeW = 1;
+ acc_sizeW = MAX_PATH;
+ accountW[0] = 0;
+ ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
+ ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
+
+ /* try a 0 sized domain buffer */
+ dom_sizeW = 0;
+ acc_sizeW = MAX_PATH;
+ accountW[0] = 0;
+ ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
+ /* this can fail or succeed depending on OS version but the size will always be returned */
+ ok(dom_sizeW == real_dom_sizeW + 1,
+ "LookupAccountSidW() Expected dom_size = %u, got %u\n",
+ real_dom_sizeW + 1, dom_sizeW);
+
+ /* try a 0 sized domain buffer */
+ dom_sizeW = 0;
+ acc_sizeW = MAX_PATH;
+ ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, NULL, &dom_sizeW, &use);
+ /* this can fail or succeed depending on OS version but the size will always be returned */
+ ok(dom_sizeW == real_dom_sizeW + 1,
+ "LookupAccountSidW() Expected dom_size = %u, got %u\n",
+ real_dom_sizeW + 1, dom_sizeW);
+
+ FreeSid(pUsersSid);
+
+ if (pCreateWellKnownSid && pConvertSidToStringSidA)
+ {
+ trace("Well Known SIDs:\n");
+ for (i = 0; i <= 60; i++)
+ {
+ size = SECURITY_MAX_SID_SIZE;
+ if (pCreateWellKnownSid(i, NULL, &max_sid.sid, &size))
+ {
+ if (pConvertSidToStringSidA(&max_sid.sid, &str_sidA))
+ {
+ acc_sizeA = MAX_PATH;
+ dom_sizeA = MAX_PATH;
+ if (LookupAccountSidA(NULL, &max_sid.sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use))
+ trace(" %d: %s %s\\%s %d\n", i, str_sidA, domainA, accountA, use);
+ LocalFree(str_sidA);
+ }
+ }
+ else
+ {
+ if (GetLastError() != ERROR_INVALID_PARAMETER)
+ trace(" CreateWellKnownSid(%d) failed: %d\n", i, GetLastError());
+ else
+ trace(" %d: not supported\n", i);
+ }
+ }
+
+ pLsaQueryInformationPolicy = (fnLsaQueryInformationPolicy)GetProcAddress( hmod, "LsaQueryInformationPolicy");
+ pLsaOpenPolicy = (fnLsaOpenPolicy)GetProcAddress( hmod, "LsaOpenPolicy");
+ pLsaFreeMemory = (fnLsaFreeMemory)GetProcAddress( hmod, "LsaFreeMemory");
+ pLsaClose = (fnLsaClose)GetProcAddress( hmod, "LsaClose");
+
+ if (pLsaQueryInformationPolicy && pLsaOpenPolicy && pLsaFreeMemory && pLsaClose)
+ {
+ NTSTATUS status;
+ LSA_HANDLE handle;
+ LSA_OBJECT_ATTRIBUTES object_attributes;
+
+ ZeroMemory(&object_attributes, sizeof(object_attributes));
+ object_attributes.Length = sizeof(object_attributes);
+
+ status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle);
+ ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
+ "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);
+
+ /* try a more restricted access mask if necessary */
+ if (status == STATUS_ACCESS_DENIED) {
+ trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n");
+ status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle);
+ ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status);
+ }
+
+ if (status == STATUS_SUCCESS)
+ {
+ PPOLICY_ACCOUNT_DOMAIN_INFO info;
+ status = pLsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (PVOID*)&info);
+ ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy() failed, returned 0x%08x\n", status);
+ if (status == STATUS_SUCCESS)
+ {
+ ok(info->DomainSid!=0, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) missing SID\n");
+ if (info->DomainSid)
+ {
+ int count = *GetSidSubAuthorityCount(info->DomainSid);
+ CopySid(GetSidLengthRequired(count), &max_sid, info->DomainSid);
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_ADMIN;
+ max_sid.sid.SubAuthorityCount = count + 1;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_GUEST;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ADMINS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_USERS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_GUESTS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_COMPUTERS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CONTROLLERS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CERT_ADMINS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_SCHEMA_ADMINS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ENTERPRISE_ADMINS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_POLICY_ADMINS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = DOMAIN_ALIAS_RID_RAS_SERVERS;
+ test_sid_str((PSID)&max_sid.sid);
+ max_sid.sid.SubAuthority[count] = 1000; /* first user account */
+ test_sid_str((PSID)&max_sid.sid);
+ }
+
+ pLsaFreeMemory((LPVOID)info);
+ }
+
+ status = pLsaClose(handle);
+ ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
+ }
+ }
+ }
+}
+
+static void get_sid_info(PSID psid, LPSTR *user, LPSTR *dom)
+{
+ static CHAR account[UNLEN + 1];
+ static CHAR domain[UNLEN + 1];
+ DWORD size, dom_size;
+ SID_NAME_USE use;
+
+ *user = account;
+ *dom = domain;
+
+ size = dom_size = UNLEN + 1;
+ account[0] = '\0';
+ domain[0] = '\0';
+ LookupAccountSidA(NULL, psid, account, &size, domain, &dom_size, &use);
+}
+
+static void test_LookupAccountName(void)
+{
+ DWORD sid_size, domain_size, user_size;
+ DWORD sid_save, domain_save;
+ CHAR user_name[UNLEN + 1];
+ SID_NAME_USE sid_use;
+ LPSTR domain, account, sid_dom;
+ PSID psid;
+ BOOL ret;
+
+ /* native crashes if (assuming all other parameters correct):
+ * - peUse is NULL
+ * - Sid is NULL and cbSid is > 0
+ * - cbSid or cchReferencedDomainName are NULL
+ * - ReferencedDomainName is NULL and cchReferencedDomainName is the correct size
+ */
+
+ user_size = UNLEN + 1;
+ SetLastError(0xdeadbeef);
+ ret = GetUserNameA(user_name, &user_size);
+ if (!ret && (GetLastError() == ERROR_NOT_LOGGED_ON))
+ {
+ /* Probably on win9x where the user used 'Cancel' instead of properly logging in */
+ skip("Cannot get the user name (win9x and not logged in properly)\n");
+ return;
+ }
+ ok(ret, "Failed to get user name : %d\n", GetLastError());
+
+ /* get sizes */
+ sid_size = 0;
+ domain_size = 0;
+ sid_use = 0xcafebabe;
+ SetLastError(0xdeadbeef);
+ ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
+ if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ skip("LookupAccountNameA is not implemented\n");
+ return;
+ }
+ ok(!ret, "Expected 0, got %d\n", ret);
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(sid_size != 0, "Expected non-zero sid size\n");
+ ok(domain_size != 0, "Expected non-zero domain size\n");
+ ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
+
+ sid_save = sid_size;
+ domain_save = domain_size;
+
+ psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
+ domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
+
+ /* try valid account name */
+ ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, domain, &domain_size, &sid_use);
+ get_sid_info(psid, &account, &sid_dom);
+ ok(ret, "Failed to lookup account name\n");
+ ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size);
+ todo_wine
+ {
+ ok(!lstrcmp(account, user_name), "Expected %s, got %s\n", user_name, account);
+ ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
+ ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size);
+ ok(lstrlen(domain) == domain_size, "Expected %d\n", lstrlen(domain));
+ ok(sid_use == SidTypeUser, "Expected SidTypeUser, got %d\n", sid_use);
+ }
+ domain_size = domain_save;
+ sid_size = sid_save;
+
+ if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH)
+ {
+ skip("Non-english locale (test with hardcoded 'Everyone')\n");
+ }
+ else
+ {
+ ret = LookupAccountNameA(NULL, "Everyone", psid, &sid_size, domain, &domain_size, &sid_use);
+ get_sid_info(psid, &account, &sid_dom);
+ ok(ret, "Failed to lookup account name\n");
+ ok(sid_size != 0, "sid_size was zero\n");
+ ok(!lstrcmp(account, "Everyone"), "Expected Everyone, got %s\n", account);
+ todo_wine
+ ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
+ ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
+ todo_wine
+ ok(lstrlen(domain) == domain_size, "Expected %d, got %d\n", lstrlen(domain), domain_size);
+ ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeUser, got %d\n", sid_use);
+ domain_size = domain_save;
+ }
+
+ /* NULL Sid with zero sid size */
+ SetLastError(0xdeadbeef);
+ sid_size = 0;
+ ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
+ ok(!ret, "Expected 0, got %d\n", ret);
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
+ ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
+
+ /* try cchReferencedDomainName - 1 */
+ SetLastError(0xdeadbeef);
+ domain_size--;
+ ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
+ ok(!ret, "Expected 0, got %d\n", ret);
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
+ ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
+
+ /* NULL ReferencedDomainName with zero domain name size */
+ SetLastError(0xdeadbeef);
+ domain_size = 0;
+ ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, NULL, &domain_size, &sid_use);
+ ok(!ret, "Expected 0, got %d\n", ret);
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
+ ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
+
+ HeapFree(GetProcessHeap(), 0, psid);
+ HeapFree(GetProcessHeap(), 0, domain);
+
+ /* get sizes for NULL account name */
+ sid_size = 0;
+ domain_size = 0;
+ sid_use = 0xcafebabe;
+ SetLastError(0xdeadbeef);
+ ret = LookupAccountNameA(NULL, NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
+ ok(!ret, "Expected 0, got %d\n", ret);
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(sid_size != 0, "Expected non-zero sid size\n");
+ ok(domain_size != 0, "Expected non-zero domain size\n");
+ ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
+
+ psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
+ domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
+
+ /* try NULL account name */
+ ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use);
+ get_sid_info(psid, &account, &sid_dom);
+ ok(ret, "Failed to lookup account name\n");
+ todo_wine
+ {
+ /* Using a fixed string will not work on different locales */
+ ok(!lstrcmp(account, domain),
+ "Got %s for account and %s for domain, these should be the same\n",
+ account, domain);
+ ok(sid_use == SidTypeDomain, "Expected SidTypeDomain, got %d\n", SidTypeDomain);
+ }
+
+ /* try an invalid account name */
+ SetLastError(0xdeadbeef);
+ sid_size = 0;
+ domain_size = 0;
+ ret = LookupAccountNameA(NULL, "oogabooga", NULL, &sid_size, NULL, &domain_size, &sid_use);
+ ok(!ret, "Expected 0, got %d\n", ret);
+ todo_wine
+ {
+ ok(GetLastError() == ERROR_NONE_MAPPED,
+ "Expected ERROR_NONE_MAPPED, got %d\n", GetLastError());
+ ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
+ ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
+ }
+
+ HeapFree(GetProcessHeap(), 0, psid);
+ HeapFree(GetProcessHeap(), 0, domain);
+}
+
+static void test_security_descriptor(void)
+{
+ SECURITY_DESCRIPTOR sd;
+ char buf[8192];
+ DWORD size;
+ BOOL isDefault, isPresent, ret;
+ PACL pacl;
+ PSID psid;
+
+ SetLastError(0xdeadbeef);
+ ret = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
+ if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("InitializeSecurityDescriptor is not implemented\n");
+ return;
+ }
+
+ ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
+ expect_eq(psid, NULL, PSID, "%p");
+ expect_eq(isDefault, FALSE, BOOL, "%d");
+ sd.Control |= SE_DACL_PRESENT | SE_SACL_PRESENT;
+
+ SetLastError(0xdeadbeef);
+ size = 5;
+ expect_eq(MakeSelfRelativeSD(&sd, buf, &size), FALSE, BOOL, "%d");
+ expect_eq(GetLastError(), ERROR_INSUFFICIENT_BUFFER, DWORD, "%u");
+ ok(size > 5, "Size not increased\n");
+ if (size <= 8192)
+ {
+ expect_eq(MakeSelfRelativeSD(&sd, buf, &size), TRUE, BOOL, "%d");
+ ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
+ expect_eq(psid, NULL, PSID, "%p");
+ expect_eq(isDefault, FALSE, BOOL, "%d");
+ ok(GetSecurityDescriptorGroup(&sd, &psid, &isDefault), "GetSecurityDescriptorGroup failed\n");
+ expect_eq(psid, NULL, PSID, "%p");
+ expect_eq(isDefault, FALSE, BOOL, "%d");
+ ok(GetSecurityDescriptorDacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorDacl failed\n");
+ expect_eq(isPresent, TRUE, BOOL, "%d");
+ expect_eq(psid, NULL, PSID, "%p");
+ expect_eq(isDefault, FALSE, BOOL, "%d");
+ ok(GetSecurityDescriptorSacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorSacl failed\n");
+ expect_eq(isPresent, TRUE, BOOL, "%d");
+ expect_eq(psid, NULL, PSID, "%p");
+ expect_eq(isDefault, FALSE, BOOL, "%d");
+ }
+}
+
+#define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,__LINE__)
+static void test_granted_access(HANDLE handle, ACCESS_MASK access, int line)
+{
+ OBJECT_BASIC_INFORMATION obj_info;
+ NTSTATUS status;
+
+ if (!pNtQueryObject)
+ {
+ skip_(__FILE__, line)("Not NT platform - skipping tests\n");
+ return;
+ }
+
+ status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
+ sizeof(obj_info), NULL );
+ ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
+ ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
+ "be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
+}
+
+#define CHECK_SET_SECURITY(o,i,e) \
+ do{ \
+ BOOL res; \
+ DWORD err; \
+ SetLastError( 0xdeadbeef ); \
+ res = SetKernelObjectSecurity( o, i, SecurityDescriptor ); \
+ err = GetLastError(); \
+ if (e == ERROR_SUCCESS) \
+ ok(res, "SetKernelObjectSecurity failed with %d\n", err); \
+ else \
+ ok(!res && err == e, "SetKernelObjectSecurity should have failed " \
+ "with %s, instead of %d\n", #e, err); \
+ }while(0)
+
+static void test_process_security(void)
+{
+ BOOL res;
+ char owner[32], group[32];
+ PSID AdminSid = NULL, UsersSid = NULL;
+ PACL Acl = NULL;
+ SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
+ char buffer[MAX_PATH];
+ PROCESS_INFORMATION info;
+ STARTUPINFOA startup;
+ SECURITY_ATTRIBUTES psa;
+ HANDLE token, event;
+ DWORD tmp;
+
+ Acl = HeapAlloc(GetProcessHeap(), 0, 256);
+ res = InitializeAcl(Acl, 256, ACL_REVISION);
+ if (!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("ACLs not implemented - skipping tests\n");
+ HeapFree(GetProcessHeap(), 0, Acl);
+ return;
+ }
+ ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+
+ /* get owner from the token we might be running as a user not admin */
+ res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token );
+ ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
+ if (!res)
+ {
+ HeapFree(GetProcessHeap(), 0, Acl);
+ return;
+ }
+
+ res = GetTokenInformation( token, TokenOwner, owner, sizeof(owner), &tmp );
+ ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
+ AdminSid = ((TOKEN_OWNER*)owner)->Owner;
+ res = GetTokenInformation( token, TokenPrimaryGroup, group, sizeof(group), &tmp );
+ ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
+ UsersSid = ((TOKEN_PRIMARY_GROUP*)group)->PrimaryGroup;
+
+ CloseHandle( token );
+ if (!res)
+ {
+ HeapFree(GetProcessHeap(), 0, Acl);
+ return;
+ }
+
+ res = AddAccessDeniedAce(Acl, ACL_REVISION, PROCESS_VM_READ, AdminSid);
+ ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
+ res = AddAccessAllowedAce(Acl, ACL_REVISION, PROCESS_ALL_ACCESS, AdminSid);
+ ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
+
+ SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
+ res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
+ ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
+
+ event = CreateEvent( NULL, TRUE, TRUE, "test_event" );
+ ok(event != NULL, "CreateEvent %d\n", GetLastError());
+
+ SecurityDescriptor->Revision = 0;
+ CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_UNKNOWN_REVISION );
+ SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
+
+ CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
+ CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
+ CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
+ CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+ /* NULL DACL is valid and means default DACL from token */
+ SecurityDescriptor->Control |= SE_DACL_PRESENT;
+ CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+
+ /* Set owner and group and dacl */
+ res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
+ ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
+ res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
+ ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
+ res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
+ ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+
+ sprintf(buffer, "%s tests/security.c test", myARGV[0]);
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_SHOWNORMAL;
+
+ psa.nLength = sizeof(psa);
+ psa.lpSecurityDescriptor = SecurityDescriptor;
+ psa.bInheritHandle = TRUE;
+
+ /* Doesn't matter what ACL say we should get full access for ourselves */
+ ok(CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
+ "CreateProcess with err:%d\n", GetLastError());
+ TEST_GRANTED_ACCESS( info.hProcess, PROCESS_ALL_ACCESS );
+ winetest_wait_child_process( info.hProcess );
+
+ CloseHandle( info.hProcess );
+ CloseHandle( info.hThread );
+ CloseHandle( event );
+ HeapFree(GetProcessHeap(), 0, Acl);
+ HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
+}
+
+static void test_process_security_child(void)
+{
+ HANDLE handle, handle1;
+ BOOL ret;
+ DWORD err;
+
+ handle = OpenProcess( PROCESS_TERMINATE, FALSE, GetCurrentProcessId() );
+ ok(handle != NULL, "OpenProcess(PROCESS_TERMINATE) with err:%d\n", GetLastError());
+ TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
+
+ ok(DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
+ &handle1, 0, TRUE, DUPLICATE_SAME_ACCESS ),
+ "duplicating handle err:%d\n", GetLastError());
+ TEST_GRANTED_ACCESS( handle1, PROCESS_TERMINATE );
+
+ CloseHandle( handle1 );
+
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
+ &handle1, PROCESS_ALL_ACCESS, TRUE, 0 );
+ err = GetLastError();
+ todo_wine
+ ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed "
+ "with STATUS_ACCESS_DENIED, instead of err:%d\n", err);
+
+ CloseHandle( handle );
+
+ /* These two should fail - they are denied by ACL */
+ handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() );
+ todo_wine
+ ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n");
+ handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
+ todo_wine
+ ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
+
+ /* Documented privilege elevation */
+ ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
+ &handle, 0, TRUE, DUPLICATE_SAME_ACCESS ),
+ "duplicating handle err:%d\n", GetLastError());
+ TEST_GRANTED_ACCESS( handle, PROCESS_ALL_ACCESS );
+
+ CloseHandle( handle );
+
+ /* Same only explicitly asking for all access rights */
+ ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
+ &handle, PROCESS_ALL_ACCESS, TRUE, 0 ),
+ "duplicating handle err:%d\n", GetLastError());
+ TEST_GRANTED_ACCESS( handle, PROCESS_ALL_ACCESS );
+ ok(DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
+ &handle1, PROCESS_VM_READ, TRUE, 0 ),
+ "duplicating handle err:%d\n", GetLastError());
+ TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
+ CloseHandle( handle1 );
+ CloseHandle( handle );
+}
+
+static void test_impersonation_level(void)
+{
+ HANDLE Token, ProcessToken;
+ HANDLE Token2;
+ DWORD Size;
+ TOKEN_PRIVILEGES *Privileges;
+ TOKEN_USER *User;
+ PRIVILEGE_SET *PrivilegeSet;
+ BOOL AccessGranted;
+ BOOL ret;
+ HKEY hkey;
+ DWORD error;
+
+ pDuplicateTokenEx = (fnDuplicateTokenEx) GetProcAddress(hmod, "DuplicateTokenEx");
+ if( !pDuplicateTokenEx ) {
+ skip("DuplicateTokenEx is not available\n");
+ return;
+ }
+ SetLastError(0xdeadbeef);
+ ret = ImpersonateSelf(SecurityAnonymous);
+ if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ skip("ImpersonateSelf is not implemented\n");
+ return;
+ }
+ ok(ret, "ImpersonateSelf(SecurityAnonymous) failed with error %d\n", GetLastError());
+ ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
+ ok(!ret, "OpenThreadToken should have failed\n");
+ error = GetLastError();
+ ok(error == ERROR_CANT_OPEN_ANONYMOUS, "OpenThreadToken on anonymous token should have returned ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error);
+ /* can't perform access check when opening object against an anonymous impersonation token */
+ todo_wine {
+ error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
+ ok(error == ERROR_INVALID_HANDLE, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE instead of %d\n", error);
+ }
+ RevertToSelf();
+
+ ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
+ ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
+
+ ret = pDuplicateTokenEx(ProcessToken,
+ TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, NULL,
+ SecurityAnonymous, TokenImpersonation, &Token);
+ ok(ret, "DuplicateTokenEx failed with error %d\n", GetLastError());
+ /* can't increase the impersonation level */
+ ret = DuplicateToken(Token, SecurityIdentification, &Token2);
+ error = GetLastError();
+ ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL,
+ "Duplicating a token and increasing the impersonation level should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
+ /* we can query anything from an anonymous token, including the user */
+ ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
+ error = GetLastError();
+ ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
+ User = (TOKEN_USER *)HeapAlloc(GetProcessHeap(), 0, Size);
+ ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
+ ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, User);
+
+ /* PrivilegeCheck fails with SecurityAnonymous level */
+ ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
+ error = GetLastError();
+ ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
+ Privileges = (TOKEN_PRIVILEGES *)HeapAlloc(GetProcessHeap(), 0, Size);
+ ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
+ ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
+
+ PrivilegeSet = (PRIVILEGE_SET *)HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount]));
+ PrivilegeSet->PrivilegeCount = Privileges->PrivilegeCount;
+ memcpy(PrivilegeSet->Privilege, Privileges->Privileges, PrivilegeSet->PrivilegeCount * sizeof(PrivilegeSet->Privilege[0]));
+ PrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
+ HeapFree(GetProcessHeap(), 0, Privileges);
+
+ ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
+ error = GetLastError();
+ ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL, "PrivilegeCheck for SecurityAnonymous token should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
+
+ CloseHandle(Token);
+
+ ret = ImpersonateSelf(SecurityIdentification);
+ ok(ret, "ImpersonateSelf(SecurityIdentification) failed with error %d\n", GetLastError());
+ ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
+ ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
+
+ /* can't perform access check when opening object against an identification impersonation token */
+ error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
+ todo_wine {
+ ok(error == ERROR_INVALID_HANDLE, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE instead of %d\n", error);
+ }
+ ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
+ ok(ret, "PrivilegeCheck for SecurityIdentification failed with error %d\n", GetLastError());
+ CloseHandle(Token);
+ RevertToSelf();
+
+ ret = ImpersonateSelf(SecurityImpersonation);
+ ok(ret, "ImpersonateSelf(SecurityImpersonation) failed with error %d\n", GetLastError());
+ ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
+ ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
+ error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
+ ok(error == ERROR_SUCCESS, "RegOpenKeyEx should have succeeded instead of failing with %d\n", error);
+ RegCloseKey(hkey);
+ ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
+ ok(ret, "PrivilegeCheck for SecurityImpersonation failed with error %d\n", GetLastError());
+ RevertToSelf();
+
+ CloseHandle(Token);
+ CloseHandle(ProcessToken);
+
+ HeapFree(GetProcessHeap(), 0, PrivilegeSet);
+}
+
+static void test_SetEntriesInAcl(void)
+{
+ DWORD res;
+ PSID EveryoneSid = NULL, UsersSid = NULL;
+ PACL OldAcl = NULL, NewAcl;
+ SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
+ SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
+ EXPLICIT_ACCESSW ExplicitAccess;
+ static const WCHAR wszEveryone[] = {'E','v','e','r','y','o','n','e',0};
+
+ if (!pSetEntriesInAclW)
+ {
+ skip("SetEntriesInAclW is not available\n");
+ return;
+ }
+
+ NewAcl = (PACL)0xdeadbeef;
+ res = pSetEntriesInAclW(0, NULL, NULL, &NewAcl);
+ if(res == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("SetEntriesInAclW is not implemented\n");
+ return;
+ }
+ ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+ ok(NewAcl == NULL, "NewAcl=%p, expected NULL\n", NewAcl);
+
+ OldAcl = HeapAlloc(GetProcessHeap(), 0, 256);
+ res = InitializeAcl(OldAcl, 256, ACL_REVISION);
+ if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("ACLs not implemented - skipping tests\n");
+ HeapFree(GetProcessHeap(), 0, OldAcl);
+ return;
+ }
+ ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+
+ res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
+ ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
+ res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
+ ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
+ res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid);
+ ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
+
+ ExplicitAccess.grfAccessPermissions = KEY_WRITE;
+ ExplicitAccess.grfAccessMode = GRANT_ACCESS;
+ ExplicitAccess.grfInheritance = NO_INHERITANCE;
+ ExplicitAccess.Trustee.pMultipleTrustee = NULL;
+ ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+ ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
+ ExplicitAccess.Trustee.ptstrName = (LPWSTR)EveryoneSid;
+ res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
+ ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+ ok(NewAcl != NULL, "returned acl was NULL\n");
+ LocalFree(NewAcl);
+
+ if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH)
+ {
+ skip("Non-english locale (test with hardcoded 'Everyone')\n");
+ }
+ else
+ {
+ ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_USER;
+ ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszEveryone;
+ res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
+ ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+ ok(NewAcl != NULL, "returned acl was NULL\n");
+ LocalFree(NewAcl);
+
+ ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM;
+ res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
+ ok(res == ERROR_INVALID_PARAMETER, "SetEntriesInAclW failed: %u\n", res);
+ ok(NewAcl == NULL, "returned acl wasn't NULL: %p\n", NewAcl);
+ LocalFree(NewAcl);
+
+ ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_USER;
+ ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE;
+ res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
+ ok(res == ERROR_INVALID_PARAMETER, "SetEntriesInAclW failed: %u\n", res);
+ ok(NewAcl == NULL, "returned acl wasn't NULL: %p\n", NewAcl);
+ LocalFree(NewAcl);
+
+ ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+ ExplicitAccess.grfAccessMode = SET_ACCESS;
+ res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
+ ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+ ok(NewAcl != NULL, "returned acl was NULL\n");
+ LocalFree(NewAcl);
+ }
+
+ ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
+ ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ ExplicitAccess.Trustee.ptstrName = (LPWSTR)UsersSid;
+ res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
+ ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+ ok(NewAcl != NULL, "returned acl was NULL\n");
+ LocalFree(NewAcl);
+
+ LocalFree(UsersSid);
+ LocalFree(EveryoneSid);
+ HeapFree(GetProcessHeap(), 0, OldAcl);
+}
+
+static void test_GetNamedSecurityInfoA(void)
+{
+ PSECURITY_DESCRIPTOR pSecDesc;
+ DWORD revision;
+ SECURITY_DESCRIPTOR_CONTROL control;
+ PSID owner;
+ PSID group;
+ BOOL owner_defaulted;
+ BOOL group_defaulted;
+ DWORD error;
+ BOOL ret;
+ CHAR windows_dir[MAX_PATH];
+
+ if (!pGetNamedSecurityInfoA)
+ {
+ skip("GetNamedSecurityInfoA is not available\n");
+ return;
+ }
+
+ ret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
+ ok(ret, "GetWindowsDirectory failed with error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSecDesc);
+ if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ skip("GetNamedSecurityInfoA is not implemented\n");
+ return;
+ }
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+
+ ret = GetSecurityDescriptorControl(pSecDesc, &control, &revision);
+ ok(ret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
+ ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT),
+ "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
+ ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %d instead of 1\n", revision);
+ ret = GetSecurityDescriptorOwner(pSecDesc, &owner, &owner_defaulted);
+ ok(ret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ ok(owner != NULL, "owner should not be NULL\n");
+ ret = GetSecurityDescriptorGroup(pSecDesc, &group, &group_defaulted);
+ ok(ret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ ok(group != NULL, "group should not be NULL\n");
+}
+
+static void test_ConvertStringSecurityDescriptor(void)
+{
+ BOOL ret;
+ PSECURITY_DESCRIPTOR pSD;
+
+ if (!pConvertStringSecurityDescriptorToSecurityDescriptorA)
+ {
+ skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n");
+ return;
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;GA;;;WD)", 0xdeadbeef, &pSD, NULL);
+ ok(!ret && GetLastError() == ERROR_UNKNOWN_REVISION,
+ "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_UNKNOWN_REVISION instead of %d\n",
+ GetLastError());
+
+ /* test ACE string type */
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(D;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "ERROR:(D;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
+ GetLastError());
+
+ /* test ACE string access rights */
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;GRGWGX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;RCSDWDWO;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "S:(AU;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+
+ /* test ACE string access right error case */
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(A;;ROB;;;WD)", SDDL_REVISION_1, &pSD, NULL);
+ todo_wine
+ ok(!ret && GetLastError() == ERROR_INVALID_ACL,
+ "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_ACL instead of %d\n",
+ GetLastError());
+
+ /* test ACE string SID */
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(D;;GA;;;S-1-0-0)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
+ LocalFree(pSD);
+
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, &pSD, NULL);
+ ok(!ret, "Expected failure, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_ACL || GetLastError() == ERROR_INVALID_SID,
+ "Expected ERROR_INVALID_ACL or ERROR_INVALID_SID, got %d\n", GetLastError());
+}
+
+static void test_ConvertSecurityDescriptorToString()
+{
+ SECURITY_DESCRIPTOR desc;
+ SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
+ LPSTR string;
+ DWORD size;
+ PSID psid, psid2;
+ PACL pacl;
+ char sid_buf[256];
+ char acl_buf[8192];
+ ULONG len;
+
+ if (!pConvertSecurityDescriptorToStringSecurityDescriptorA)
+ {
+ skip("ConvertSecurityDescriptorToStringSecurityDescriptor is not available\n");
+ return;
+ }
+ if (!pCreateWellKnownSid)
+ {
+ skip("CreateWellKnownSid is not available\n");
+ return;
+ }
+
+/* It seems Windows XP adds an extra character to the length of the string for each ACE in an ACL. We
+ * don't replicate this feature so we only test len >= strlen+1. */
+#define CHECK_RESULT_AND_FREE(exp_str) \
+ ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \
+ ok(len >= (lstrlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", lstrlen(exp_str) + 1, len); \
+ LocalFree(string);
+
+#define CHECK_ONE_OF_AND_FREE(exp_str1, exp_str2) \
+ ok(strcmp(string, (exp_str1)) == 0 || strcmp(string, (exp_str2)) == 0, "String mismatch (expected\n\"%s\" or\n\"%s\", got\n\"%s\")\n", (exp_str1), (exp_str2), string); \
+ ok(len >= (strlen(string) + 1), "Length mismatch (expected %d, got %d)\n", lstrlen(string) + 1, len); \
+ LocalFree(string);
+
+ InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("");
+
+ size = 4096;
+ pCreateWellKnownSid(WinLocalSid, NULL, sid_buf, &size);
+ SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, FALSE);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:S-1-2-0");
+
+ SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, TRUE);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:S-1-2-0");
+
+ size = sizeof(sid_buf);
+ pCreateWellKnownSid(WinLocalSystemSid, NULL, sid_buf, &size);
+ SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, TRUE);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SY");
+
+ pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid);
+ SetSecurityDescriptorGroup(&desc, psid, TRUE);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576");
+
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, GROUP_SECURITY_INFORMATION, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
+
+ pacl = (PACL)acl_buf;
+ InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
+ SetSecurityDescriptorDacl(&desc, TRUE, pacl, TRUE);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
+
+ SetSecurityDescriptorDacl(&desc, TRUE, pacl, FALSE);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
+
+ pConvertStringSidToSidA("S-1-5-6", &psid2);
+ pAddAccessAllowedAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, 0xf0000000, psid2);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)");
+
+ pAddAccessAllowedAceEx(pacl, ACL_REVISION, INHERIT_ONLY_ACE|INHERITED_ACE, 0x00000003, psid2);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)");
+
+ pAddAccessDeniedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0xffffffff, psid);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)");
+
+
+ pacl = (PACL)acl_buf;
+ InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
+ SetSecurityDescriptorSacl(&desc, TRUE, pacl, FALSE);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:");
+
+ /* fails in win2k */
+ SetSecurityDescriptorDacl(&desc, TRUE, NULL, FALSE);
+ pAddAuditAccessAceEx(pacl, ACL_REVISION, VALID_INHERIT_FLAGS, KEY_READ|KEY_WRITE, psid2, TRUE, TRUE);
+ if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
+ {
+ CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)", /* XP */
+ "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)" /* Vista */);
+ }
+
+ /* fails in win2k */
+ pAddAuditAccessAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, FILE_GENERIC_READ|FILE_GENERIC_WRITE, psid2, TRUE, FALSE);
+ if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
+ {
+ CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", /* XP */
+ "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)" /* Vista */);
+ }
+}
+
+static void test_PrivateObjectSecurity(void)
+{
+ SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
+ SECURITY_DESCRIPTOR_CONTROL ctrl;
+ PSECURITY_DESCRIPTOR sec;
+ DWORD dwDescSize;
+ DWORD dwRevision;
+ DWORD retSize;
+ LPSTR string;
+ ULONG len;
+ PSECURITY_DESCRIPTOR buf;
+
+ if (!pConvertStringSecurityDescriptorToSecurityDescriptorA)
+ {
+ skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n");
+ return;
+ }
+
+ ok(pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "O:SY"
+ "G:S-1-5-21-93476-23408-4576"
+ "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
+ "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
+ buf = HeapAlloc(GetProcessHeap(), 0, dwDescSize);
+ pSetSecurityDescriptorControl(sec, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
+ GetSecurityDescriptorControl(sec, &ctrl, &dwRevision);
+ todo_wine expect_eq(ctrl, 0x9014, int, "%x");
+
+ ok(GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION, buf, dwDescSize, &retSize),
+ "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
+ ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
+ GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
+ expect_eq(ctrl, 0x8000, int, "%x");
+
+ ok(GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, buf, dwDescSize, &retSize),
+ "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
+ ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed err=%u\n", GetLastError());
+ CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)");
+ GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
+ expect_eq(ctrl, 0x8004, int, "%x");
+
+ ok(GetPrivateObjectSecurity(sec, sec_info, buf, dwDescSize, &retSize),
+ "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
+ ok(retSize == dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
+ ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
+ CHECK_RESULT_AND_FREE("O:SY"
+ "G:S-1-5-21-93476-23408-4576"
+ "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
+ "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)");
+ GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
+ expect_eq(ctrl, 0x8014, int, "%x");
+
+ SetLastError(0xdeadbeef);
+ ok(GetPrivateObjectSecurity(sec, sec_info, buf, 5, &retSize) == FALSE, "GetPrivateObjectSecurity should have failed\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected error ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
+
+ LocalFree(sec);
+ HeapFree(GetProcessHeap(), 0, buf);
+}
+#undef CHECK_RESULT_AND_FREE
+#undef CHECK_ONE_OF_AND_FREE
+
+static void test_acls(void)
+{
+ char buffer[256];
+ PACL pAcl = (PACL)buffer;
+ BOOL ret;
+
+ SetLastError(0xdeadbeef);
+ ret = InitializeAcl(pAcl, sizeof(ACL) - 1, ACL_REVISION);
+ if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ skip("InitializeAcl is not implemented\n");
+ return;
+ }
+
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InitializeAcl with too small a buffer should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = InitializeAcl(pAcl, 0xffffffff, ACL_REVISION);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl with too large a buffer should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION1);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(ACL_REVISION1) should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
+
+ ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION2);
+ ok(ret, "InitializeAcl(ACL_REVISION2) failed with error %d\n", GetLastError());
+
+ ret = IsValidAcl(pAcl);
+ ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
+
+ ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION3);
+ ok(ret, "InitializeAcl(ACL_REVISION3) failed with error %d\n", GetLastError());
+
+ ret = IsValidAcl(pAcl);
+ ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
+
+ ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION4);
+ ok(ret, "InitializeAcl(ACL_REVISION4) failed with error %d\n", GetLastError());
+
+ ret = IsValidAcl(pAcl);
+ ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = InitializeAcl(pAcl, sizeof(buffer), -1);
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(-1) failed with error %d\n", GetLastError());
}
START_TEST(security)
{
init();
if (!hmod) return;
+
+ if (myARGC >= 3)
+ {
+ test_process_security_child();
+ return;
+ }
test_sid();
test_trustee();
test_luid();
+ test_CreateWellKnownSid();
test_FileSecurity();
+ test_AccessCheck();
+ test_token_attr();
+ test_LookupAccountSid();
+ test_LookupAccountName();
+ test_security_descriptor();
+ test_process_security();
+ test_impersonation_level();
+ test_SetEntriesInAcl();
+ test_GetNamedSecurityInfoA();
+ test_ConvertStringSecurityDescriptor();
+ test_ConvertSecurityDescriptorToString();
+ test_PrivateObjectSecurity();
+ test_acls();
}
--- /dev/null
+/*
+ * Unit tests for service functions
+ *
+ * Copyright (c) 2007 Paul Vriens
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "winsvc.h"
+#include "winnls.h"
+#include "lmcons.h"
+
+#include "wine/test.h"
+
+static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */
+
+static void test_open_scm(void)
+{
+ SC_HANDLE scm_handle;
+
+ /* No access rights */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, NULL, 0);
+ ok(scm_handle != NULL, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3, Vista */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+ CloseServiceHandle(scm_handle);
+
+ /* Unknown database name */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, "DoesNotExist", SC_MANAGER_CONNECT);
+ ok(!scm_handle, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
+ CloseServiceHandle(scm_handle); /* Just in case */
+
+ /* MSDN says only ServiceActive is allowed, or NULL */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, SERVICES_FAILED_DATABASEA, SC_MANAGER_CONNECT);
+ ok(!scm_handle, "Expected failure\n");
+ ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError());
+ CloseServiceHandle(scm_handle); /* Just in case */
+
+ /* Remote unknown host */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
+ ok(!scm_handle, "Expected failure\n");
+ todo_wine
+ ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE, "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
+ CloseServiceHandle(scm_handle); /* Just in case */
+
+ /* Proper call with an empty hostname */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
+ ok(scm_handle != NULL, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3, Vista */ ||
+ GetLastError() == ERROR_ENVVAR_NOT_FOUND /* NT4 */ ||
+ GetLastError() == 0xdeadbeef /* XP */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING, ERROR_ENVVAR_NOT_FOUND or 0xdeadbeef, got %d\n", GetLastError());
+ CloseServiceHandle(scm_handle);
+
+ /* Again a correct one */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+ ok(scm_handle != NULL, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3, Vista */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+ CloseServiceHandle(scm_handle);
+}
+
+static void test_open_svc(void)
+{
+ SC_HANDLE scm_handle, svc_handle;
+ CHAR displayname[4096];
+ DWORD displaysize;
+
+ /* All NULL (invalid access rights) */
+ SetLastError(0xdeadbeef);
+ svc_handle = OpenServiceA(NULL, NULL, 0);
+ ok(!svc_handle, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
+
+ /* NULL service */
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+ SetLastError(0xdeadbeef);
+ svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
+ ok(!svc_handle, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
+ GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
+ "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Nonexistent service */
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+ SetLastError(0xdeadbeef);
+ svc_handle = OpenServiceA(scm_handle, "deadbeef", GENERIC_READ);
+ ok(!svc_handle, "Expected failure\n");
+ ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
+ CloseServiceHandle(scm_handle);
+
+ /* Proper SCM handle but different access rights */
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+ SetLastError(0xdeadbeef);
+ svc_handle = OpenServiceA(scm_handle, "Spooler", GENERIC_WRITE);
+ if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
+ skip("Not enough rights to get a handle to the service\n");
+ else
+ {
+ ok(svc_handle != NULL, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3, Vista */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == 0xdeadbeef /* XP, NT4 */,
+ "Expected ERROR_SUCCESS or 0xdeadbeef, got %d\n", GetLastError());
+ CloseServiceHandle(svc_handle);
+ }
+
+ /* Test to show we can't open a service with the displayname */
+
+ /* Retrieve the needed size for the buffer */
+ displaysize = 0;
+ GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
+ /* Get the displayname */
+ GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
+ /* Try to open the service with this displayname */
+ svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ);
+ ok(!svc_handle, "Expected failure\n");
+ ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
+ /* Just in case */
+ CloseServiceHandle(svc_handle);
+
+ CloseServiceHandle(scm_handle);
+}
+
+static void test_create_delete_svc(void)
+{
+ SC_HANDLE scm_handle, svc_handle1;
+ CHAR username[UNLEN + 1], domain[MAX_PATH];
+ DWORD user_size = UNLEN + 1;
+ CHAR account[UNLEN + 3];
+ static const CHAR servicename [] = "Winetest";
+ static const CHAR pathname [] = "we_dont_care.exe";
+ static const CHAR empty [] = "";
+ static const CHAR password [] = "secret";
+ BOOL spooler_exists = FALSE;
+ BOOL ret;
+ CHAR display[4096];
+ DWORD display_size = sizeof(display);
+
+ /* Get the username and turn it into an account to be used in some tests */
+ GetUserNameA(username, &user_size);
+ /* Get the domainname to cater for that situation */
+ if (GetEnvironmentVariableA("USERDOMAIN", domain, MAX_PATH))
+ sprintf(account, "%s\\%s", domain, username);
+ else
+ sprintf(account, ".\\%s", username);
+
+ /* All NULL */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+
+ /* Only a valid handle to the Service Control Manager */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
+ GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
+ "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Now with a servicename */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
+ GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
+ "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Or just a binary name */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
+ GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
+ "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Both servicename and binary name (We only have connect rights) */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+
+ /* They can even be empty at this stage of parameter checking */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+
+ /* Open the Service Control Manager with minimal rights for creation
+ * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
+ */
+ CloseServiceHandle(scm_handle);
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
+ if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
+ {
+ skip("Not enough rights to get a handle to the manager\n");
+ return;
+ }
+
+ /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
+
+ /* Empty strings for servicename and binary name are checked */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
+
+ /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
+ * an ERROR_INVALID_PARAMETER)
+ */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DISABLED, 0, empty, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
+
+ /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
+ * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
+ */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_FILE_SYSTEM_DRIVER | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
+ * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
+ */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, account, password);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Illegal (start-type is not a mask and should only be one of the possibilities)
+ * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
+ * it's most likely not the wanted start-type)
+ */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_AUTO_START | SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* The service already exists (check first, just in case) */
+ svc_handle1 = OpenServiceA(scm_handle, spooler, GENERIC_READ);
+ if (svc_handle1)
+ {
+ spooler_exists = TRUE;
+ CloseServiceHandle(svc_handle1);
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, spooler, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_SERVICE_EXISTS, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError());
+ }
+ else
+ skip("Spooler service doesn't exist\n");
+
+ /* To find an existing displayname we check the 'Spooler' service. Although the registry
+ * doesn't show DisplayName on NT4, this call will return a displayname which is equal
+ * to the servicename and can't be used as well for a new displayname.
+ */
+ if (spooler_exists)
+ {
+ ret = GetServiceDisplayNameA(scm_handle, spooler, display, &display_size);
+
+ if (!ret)
+ skip("Could not retrieve a displayname for the Spooler service\n");
+ else
+ {
+ svc_handle1 = CreateServiceA(scm_handle, servicename, display, 0, SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(!svc_handle1, "Expected failure\n");
+ ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME,
+ "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError());
+ }
+ }
+ else
+ skip("Could not retrieve a displayname (Spooler service doesn't exist)\n");
+
+ /* Windows doesn't care about the access rights for creation (which makes
+ * sense as there is no service yet) as long as there are sufficient
+ * rights to the manager.
+ */
+ SetLastError(0xdeadbeef);
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(svc_handle1 != NULL, "Could not create the service : %d\n", GetLastError());
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3, Vista */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+
+ /* DeleteService however must have proper rights */
+ SetLastError(0xdeadbeef);
+ ret = DeleteService(svc_handle1);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_ACCESS_DENIED,
+ "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+
+ /* Open the service with minimal rights for deletion.
+ * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
+ */
+ CloseServiceHandle(svc_handle1);
+ svc_handle1 = OpenServiceA(scm_handle, servicename, DELETE);
+
+ /* Now that we have the proper rights, we should be able to delete */
+ SetLastError(0xdeadbeef);
+ ret = DeleteService(svc_handle1);
+ ok(ret, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+
+ CloseServiceHandle(svc_handle1);
+
+ CloseServiceHandle(scm_handle);
+
+ /* Wait a while. One of the following tests also does a CreateService for the
+ * same servicename and this would result in an ERROR_SERVICE_MARKED_FOR_DELETE
+ * error if we do this to quick. Vista seems more picky then the others.
+ */
+ Sleep(1000);
+
+ /* And a final NULL check */
+ SetLastError(0xdeadbeef);
+ ret = DeleteService(NULL);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+}
+
+static void test_get_displayname(void)
+{
+ SC_HANDLE scm_handle, svc_handle;
+ BOOL ret;
+ CHAR displayname[4096];
+ WCHAR displaynameW[2048];
+ DWORD displaysize, tempsize, tempsizeW;
+ static const CHAR deadbeef[] = "Deadbeef";
+ static const WCHAR spoolerW[] = {'S','p','o','o','l','e','r',0};
+ static const CHAR servicename[] = "Winetest";
+ static const CHAR pathname[] = "we_dont_care.exe";
+
+ /* Having NULL for the size of the buffer will crash on W2K3 */
+
+ SetLastError(0xdeadbeef);
+ ret = GetServiceDisplayNameA(NULL, NULL, NULL, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+
+ SetLastError(0xdeadbeef);
+ ret = GetServiceDisplayNameA(scm_handle, NULL, NULL, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
+ GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
+ "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ displaysize = sizeof(displayname);
+ ret = GetServiceDisplayNameA(scm_handle, NULL, displayname, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
+ GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
+ "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* Test for nonexistent service */
+ SetLastError(0xdeadbeef);
+ displaysize = -1;
+ ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
+ "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
+
+ /* Check if 'Spooler' exists */
+ svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
+ if (!svc_handle)
+ {
+ skip("Spooler service doesn't exist\n");
+ CloseServiceHandle(scm_handle);
+ return;
+ }
+ CloseServiceHandle(svc_handle);
+
+ /* Retrieve the needed size for the buffer */
+ SetLastError(0xdeadbeef);
+ displaysize = -1;
+ ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ tempsize = displaysize;
+
+ displaysize = 0;
+ ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(displaysize == tempsize, "Buffer size mismatch (%d vs %d)\n", tempsize, displaysize);
+
+ /* Buffer is too small */
+ SetLastError(0xdeadbeef);
+ displaysize = (tempsize / 2);
+ ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(displaysize == tempsize, "Expected the needed buffersize\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ /* First try with a buffer that should be big enough to hold
+ * the ANSI string (and terminating character). This succeeds on Windows
+ * although when asked (see above 2 tests) it will return twice the needed size.
+ */
+ SetLastError(0xdeadbeef);
+ displaysize = (tempsize / 2) + 1;
+ ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
+ ok(ret, "Expected success\n");
+ ok(displaysize == ((tempsize / 2) + 1), "Expected no change for the needed buffer size\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+
+ /* Now with the original returned size */
+ SetLastError(0xdeadbeef);
+ displaysize = tempsize;
+ ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
+ ok(ret, "Expected success\n");
+ ok(displaysize == tempsize, "Expected no change for the needed buffer size\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+
+ /* And with a bigger than needed buffer */
+ SetLastError(0xdeadbeef);
+ displaysize = tempsize * 2;
+ ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
+ ok(ret, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+ /* Test that shows that if the buffersize is enough, it's not changed */
+ ok(displaysize == tempsize * 2, "Expected no change for the needed buffer size\n");
+ ok(lstrlen(displayname) == tempsize/2,
+ "Expected the buffer to be twice the length of the string\n") ;
+
+ /* Do the buffer(size) tests also for GetServiceDisplayNameW */
+ SetLastError(0xdeadbeef);
+ displaysize = -1;
+ ret = GetServiceDisplayNameW(scm_handle, spoolerW, NULL, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ /* Buffer is too small */
+ SetLastError(0xdeadbeef);
+ tempsizeW = displaysize;
+ displaysize = tempsizeW / 2;
+ ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(displaysize = tempsizeW, "Expected the needed buffersize\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ /* Now with the original returned size */
+ SetLastError(0xdeadbeef);
+ displaysize = tempsizeW;
+ ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(displaysize = tempsizeW, "Expected the needed buffersize\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ /* And with a bigger than needed buffer */
+ SetLastError(0xdeadbeef);
+ displaysize = tempsizeW + 1; /* This caters for the null terminating character */
+ ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
+ ok(ret, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+ ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
+ ok(lstrlenW(displaynameW) == displaysize,
+ "Expected the buffer to be the length of the string\n") ;
+ ok(tempsize / 2 == tempsizeW,
+ "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
+
+ CloseServiceHandle(scm_handle);
+
+ /* Test for a service without a displayname (which is valid). This should return
+ * the servicename itself.
+ */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
+ if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
+ {
+ skip("Not enough rights to get a handle to the manager\n");
+ return;
+ }
+
+ SetLastError(0xdeadbeef);
+ svc_handle = CreateServiceA(scm_handle, servicename, NULL, DELETE,
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
+ if (!svc_handle)
+ {
+ CloseServiceHandle(scm_handle);
+ return;
+ }
+
+ /* Retrieve the needed size for the buffer */
+ SetLastError(0xdeadbeef);
+ displaysize = -1;
+ ret = GetServiceDisplayNameA(scm_handle, servicename, NULL, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(displaysize == lstrlen(servicename) * 2,
+ "Expected the displaysize to be twice the size of the servicename\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ /* Buffer is too small */
+ SetLastError(0xdeadbeef);
+ tempsize = displaysize;
+ displaysize = (tempsize / 2);
+ ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
+ ok(!ret, "Expected failure\n");
+ ok(displaysize == tempsize, "Expected the needed buffersize\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ /* Get the displayname */
+ SetLastError(0xdeadbeef);
+ ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
+ ok(ret, "Expected success\n");
+ ok(!lstrcmpi(displayname, servicename),
+ "Expected displayname to be %s, got %s\n", servicename, displayname);
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+
+ /* Delete the service */
+ ret = DeleteService(svc_handle);
+ ok(ret, "Expected success\n");
+
+ CloseServiceHandle(svc_handle);
+ CloseServiceHandle(scm_handle);
+
+ /* Wait a while. Just in case one of the following tests does a CreateService again */
+ Sleep(1000);
+}
+
+static void test_get_servicekeyname(void)
+{
+ SC_HANDLE scm_handle, svc_handle;
+ CHAR servicename[4096];
+ CHAR displayname[4096];
+ WCHAR servicenameW[4096];
+ WCHAR displaynameW[4096];
+ DWORD servicesize, displaysize, tempsize;
+ BOOL ret;
+ static const CHAR deadbeef[] = "Deadbeef";
+ static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
+
+ /* Having NULL for the size of the buffer will crash on W2K3 */
+
+ SetLastError(0xdeadbeef);
+ ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE,
+ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+
+ servicesize = 200;
+ SetLastError(0xdeadbeef);
+ ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &servicesize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
+ GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
+ "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
+
+ /* Valid handle and buffer but no displayname */
+ servicesize = 200;
+ SetLastError(0xdeadbeef);
+ ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
+ GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
+ "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ todo_wine ok(servicesize == 200, "Service size expected 1, got %d\n", servicesize);
+
+ /* Test for nonexistent displayname */
+ SetLastError(0xdeadbeef);
+ ret = GetServiceKeyNameA(scm_handle, deadbeef, NULL, &servicesize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
+ "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
+ todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
+
+ servicesize = 15;
+ strcpy(servicename, "ABC");
+ ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
+ ok(!ret, "Expected failure\n");
+ todo_wine ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
+ ok(servicename[0] == 0, "Service name not empty\n");
+
+ servicesize = 15;
+ servicenameW[0] = 'A';
+ ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
+ ok(!ret, "Expected failure\n");
+ todo_wine ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
+ ok(servicenameW[0] == 0, "Service name not empty\n");
+
+ servicesize = 0;
+ strcpy(servicename, "ABC");
+ ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
+ ok(!ret, "Expected failure\n");
+ todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
+ ok(servicename[0] == 'A', "Service name changed\n");
+
+ servicesize = 0;
+ servicenameW[0] = 'A';
+ ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
+ ok(!ret, "Expected failure\n");
+ todo_wine ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
+ ok(servicenameW[0] == 'A', "Service name changed\n");
+
+ /* Check if 'Spooler' exists */
+ svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
+ if (!svc_handle)
+ {
+ skip("Spooler service doesn't exist\n");
+ CloseServiceHandle(scm_handle);
+ return;
+ }
+ CloseServiceHandle(svc_handle);
+
+ /* Get the displayname for the 'Spooler' service */
+ GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
+ GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
+
+ /* Retrieve the needed size for the buffer */
+ SetLastError(0xdeadbeef);
+ servicesize = 0;
+ ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ /* Valid call with the correct buffersize */
+ SetLastError(0xdeadbeef);
+ tempsize = servicesize;
+ servicesize *= 2;
+ ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize);
+ ok(ret, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+ if (ret)
+ {
+ ok(lstrlen(servicename) == tempsize/2,
+ "Expected the buffer to be twice the length of the string\n") ;
+ ok(!lstrcmpi(servicename, spooler), "Expected %s, got %s\n", spooler, servicename);
+ ok(servicesize == (tempsize * 2),
+ "Expected servicesize not to change if buffer not insufficient\n") ;
+ }
+
+ MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2);
+ SetLastError(0xdeadbeef);
+ servicesize *= 2;
+ ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
+ ok(ret, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+ if (ret)
+ {
+ ok(lstrlen(servicename) == tempsize/2,
+ "Expected the buffer to be twice the length of the string\n") ;
+ ok(servicesize == lstrlenW(servicenameW),
+ "Expected servicesize not to change if buffer not insufficient\n") ;
+ }
+
+ SetLastError(0xdeadbeef);
+ servicesize = 3;
+ ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(servicenameW[0] == 0, "Buffer not empty\n");
+
+ CloseServiceHandle(scm_handle);
+}
+
+static void test_close(void)
+{
+ SC_HANDLE handle;
+ BOOL ret;
+
+ /* NULL handle */
+ SetLastError(0xdeadbeef);
+ ret = CloseServiceHandle(NULL);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
+
+ /* Proper call */
+ handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+ SetLastError(0xdeadbeef);
+ ret = CloseServiceHandle(handle);
+ ok(ret, "Expected success\n");
+ ok(GetLastError() == ERROR_IO_PENDING /* W2K */ ||
+ GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+}
+
+static void test_sequence(void)
+{
+ SC_HANDLE scm_handle, svc_handle;
+ BOOL ret;
+ QUERY_SERVICE_CONFIGA *config;
+ DWORD given, needed;
+ static const CHAR servicename [] = "Winetest";
+ static const CHAR displayname [] = "Winetest dummy service";
+ static const CHAR displayname2[] = "Winetest dummy service (2)";
+ static const CHAR pathname [] = "we_dont_care.exe";
+ static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
+ static const CHAR password [] = "";
+ static const CHAR empty [] = "";
+ static const CHAR localsystem [] = "LocalSystem";
+
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
+
+ if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
+ {
+ skip("Not enough rights to get a handle to the manager\n");
+ return;
+ }
+ else
+ ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError());
+
+ if (!scm_handle) return;
+
+ /* Create a dummy service */
+ SetLastError(0xdeadbeef);
+ svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
+ SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
+ pathname, NULL, NULL, dependencies, NULL, password);
+
+ if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
+ {
+ /* We try and open the service and do the rest of the tests. Some could
+ * fail if the tests were changed between these runs.
+ */
+ trace("Deletion probably didn't work last time\n");
+ SetLastError(0xdeadbeef);
+ svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
+ if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
+ {
+ skip("Not enough rights to open the service\n");
+ CloseServiceHandle(scm_handle);
+ return;
+ }
+ ok(svc_handle != NULL, "Could not open the service : %d\n", GetLastError());
+ }
+ else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
+ {
+ skip("Not enough rights to create the service\n");
+ CloseServiceHandle(scm_handle);
+ return;
+ }
+ else
+ ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
+
+ if (!svc_handle) return;
+
+ /* TODO:
+ * Before we do a QueryServiceConfig we should check the registry. This will make sure
+ * that the correct keys are used.
+ */
+
+ /* Request the size for the buffer */
+ SetLastError(0xdeadbeef);
+ ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ config = HeapAlloc(GetProcessHeap(), 0, needed);
+ given = needed;
+ SetLastError(0xdeadbeef);
+ ret = QueryServiceConfigA(svc_handle, config, given, &needed);
+ ok(ret, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+ todo_wine
+ {
+ ok(given == needed, "Expected the given (%d) and needed (%d) buffersizes to be equal\n", given, needed);
+ }
+ ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
+ config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
+ ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
+ "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
+ ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
+ ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %d\n", config->dwErrorControl);
+ ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
+ ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
+ ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
+ /* TODO: Show the double 0 terminated string */
+ todo_wine
+ {
+ ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
+ }
+ ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
+ ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
+
+ ok(ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_ERROR_NORMAL, NULL, "TestGroup2", NULL, NULL, NULL, NULL, displayname2),
+ "ChangeServiceConfig failed (err=%d)\n", GetLastError());
+
+ QueryServiceConfigA(svc_handle, NULL, 0, &needed);
+ config = HeapReAlloc(GetProcessHeap(), 0, config, needed);
+ ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n");
+ ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
+ config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
+ ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
+ "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
+ ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
+ ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %d\n", config->dwErrorControl);
+ ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
+ ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup);
+ ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
+ ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
+ ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName);
+
+ SetLastError(0xdeadbeef);
+ ret = DeleteService(svc_handle);
+ ok(ret, "Expected success\n");
+ ok(GetLastError() == ERROR_SUCCESS /* W2K3 */||
+ GetLastError() == 0xdeadbeef /* NT4, XP, Vista */ ||
+ GetLastError() == ERROR_IO_PENDING /* W2K */,
+ "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
+
+ CloseServiceHandle(svc_handle);
+
+ /* Wait a while. The following test does a CreateService again */
+ Sleep(1000);
+
+ CloseServiceHandle(scm_handle);
+ HeapFree(GetProcessHeap(), 0, config);
+}
+
+static void test_queryconfig2(void)
+{
+ SC_HANDLE scm_handle, svc_handle;
+ BOOL ret;
+ DWORD expected, needed;
+ BYTE buffer[MAX_PATH];
+ LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer;
+ static const CHAR servicename [] = "Winetest";
+ static const CHAR displayname [] = "Winetest dummy service";
+ static const CHAR pathname [] = "we_dont_care.exe";
+ static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
+ static const CHAR password [] = "";
+ static const CHAR description [] = "Description";
+ HMODULE dllhandle = GetModuleHandleA("advapi32.dll");
+ BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID)
+ = (void*)GetProcAddress(dllhandle, "ChangeServiceConfig2A");
+ BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD)
+ = (void*)GetProcAddress(dllhandle, "QueryServiceConfig2A");
+ BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD)
+ = (void*)GetProcAddress(dllhandle, "QueryServiceConfig2W");
+ if(!pQueryServiceConfig2A)
+ {
+ skip("function QueryServiceConfig2A not present\n");
+ return;
+ }
+
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
+
+ if (!scm_handle)
+ {
+ if(GetLastError() == ERROR_ACCESS_DENIED)
+ skip("Not enough rights to get a handle to the manager\n");
+ else
+ ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError());
+ return;
+ }
+
+ /* Create a dummy service */
+ SetLastError(0xdeadbeef);
+ svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
+ SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
+ pathname, NULL, NULL, dependencies, NULL, password);
+
+ if (!svc_handle)
+ {
+ if(GetLastError() == ERROR_SERVICE_EXISTS)
+ {
+ /* We try and open the service and do the rest of the tests. Some could
+ * fail if the tests were changed between these runs.
+ */
+ trace("Deletion probably didn't work last time\n");
+ SetLastError(0xdeadbeef);
+ svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
+ if (!svc_handle)
+ {
+ if(GetLastError() == ERROR_ACCESS_DENIED)
+ skip("Not enough rights to open the service\n");
+ else
+ ok(FALSE, "Could not open the service : %d\n", GetLastError());
+ CloseServiceHandle(scm_handle);
+ return;
+ }
+ }
+ if (GetLastError() == ERROR_ACCESS_DENIED)
+ {
+ skip("Not enough rights to create the service\n");
+ CloseServiceHandle(scm_handle);
+ return;
+ }
+ ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
+ if (!svc_handle)
+ {
+ CloseServiceHandle(scm_handle);
+ return;
+ }
+ }
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok((ERROR_INVALID_ADDRESS == GetLastError()) || (ERROR_INSUFFICIENT_BUFFER == GetLastError()),
+ "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
+
+ needed = 0;
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
+
+ needed = 0;
+ pConfig->lpDescription = (LPSTR)0xdeadbeef;
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
+ ok(!pConfig->lpDescription, "expected lpDescription to be NULL, got %p\n", pConfig->lpDescription);
+
+ SetLastError(0xdeadbeef);
+ needed = 0;
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
+
+ if(!pChangeServiceConfig2A)
+ {
+ skip("function ChangeServiceConfig2A not present\n");
+ goto cleanup;
+ }
+
+ pConfig->lpDescription = (LPSTR) description;
+ ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer);
+ ok(ret, "ChangeServiceConfig2A failed\n");
+ if (!ret) {
+ goto cleanup;
+ }
+
+ SetLastError(0xdeadbeef);
+ needed = 0;
+ expected = sizeof(SERVICE_DESCRIPTIONA) + sizeof(description) * sizeof(WCHAR); /* !! */
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed);
+
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed-1,&needed);
+ ok(!ret, "expected QueryServiceConfig2A to fail\n");
+ ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed,&needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
+ "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
+
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed + 1,&needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
+ "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
+
+ if(!pQueryServiceConfig2W)
+ {
+ skip("function QueryServiceConfig2W not present\n");
+ goto cleanup;
+ }
+ SetLastError(0xdeadbeef);
+ needed = 0;
+ expected = sizeof(SERVICE_DESCRIPTIONW) + sizeof(WCHAR) * sizeof(description);
+ ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
+ ok(!ret, "expected QueryServiceConfig2W to fail\n");
+ ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed);
+
+ SetLastError(0xdeadbeef);
+ ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
+ ok(ret, "expected QueryServiceConfig2W to succeed\n");
+
+cleanup:
+ DeleteService(svc_handle);
+
+ CloseServiceHandle(svc_handle);
+
+ /* Wait a while. The following test does a CreateService again */
+ Sleep(1000);
+
+ CloseServiceHandle(scm_handle);
+}
+
+static void test_refcount(void)
+{
+ SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5;
+ static const CHAR servicename [] = "Winetest";
+ static const CHAR pathname [] = "we_dont_care.exe";
+ BOOL ret;
+
+ /* Get a handle to the Service Control Manager */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
+ if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
+ {
+ skip("Not enough rights to get a handle to the manager\n");
+ return;
+ }
+
+ /* Create a service */
+ svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(svc_handle1 != NULL, "Expected success\n");
+
+ /* Get a handle to this new service */
+ svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
+ ok(svc_handle2 != NULL, "Expected success\n");
+
+ /* Get another handle to this new service */
+ svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
+ ok(svc_handle3 != NULL, "Expected success\n");
+
+ /* Check if we can close the handle to the Service Control Manager */
+ ret = CloseServiceHandle(scm_handle);
+ ok(ret, "Expected success\n");
+
+ /* Get a new handle to the Service Control Manager */
+ scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
+ ok(scm_handle != NULL, "Expected success\n");
+
+ /* Get a handle to this new service */
+ svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
+ ok(svc_handle4 != NULL, "Expected success\n");
+
+ /* Delete the service */
+ ret = DeleteService(svc_handle4);
+ ok(ret, "Expected success\n");
+
+ /* We cannot create the same service again as it's still marked as 'being deleted'.
+ * The reason is that we still have 4 open handles to this service even though we
+ * closed the handle to the Service Control Manager in between.
+ */
+ SetLastError(0xdeadbeef);
+ svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ todo_wine
+ {
+ ok(!svc_handle5, "Expected failure\n");
+ ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE,
+ "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError());
+ }
+
+ /* FIXME: Remove this when Wine is fixed */
+ if (svc_handle5)
+ {
+ DeleteService(svc_handle5);
+ CloseServiceHandle(svc_handle5);
+ }
+
+ /* Close all the handles to the service and try again */
+ ret = CloseServiceHandle(svc_handle4);
+ ok(ret, "Expected success\n");
+ ret = CloseServiceHandle(svc_handle3);
+ ok(ret, "Expected success\n");
+ ret = CloseServiceHandle(svc_handle2);
+ ok(ret, "Expected success\n");
+ ret = CloseServiceHandle(svc_handle1);
+ ok(ret, "Expected success\n");
+
+ /* Wait a while. Doing a CreateService too soon will result again
+ * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
+ */
+ Sleep(1000);
+
+ /* We succeed now as all handles are closed (tested this also with a long SLeep() */
+ svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
+ ok(svc_handle5 != NULL, "Expected success\n");
+
+ /* Delete the service */
+ ret = DeleteService(svc_handle5);
+ ok(ret, "Expected success\n");
+
+ /* Wait a while. Just in case one of the following tests does a CreateService again */
+ Sleep(1000);
+
+ CloseServiceHandle(svc_handle5);
+ CloseServiceHandle(scm_handle);
+}
+
+START_TEST(service)
+{
+ SC_HANDLE scm_handle;
+
+ /* Bail out if we are on win98 */
+ SetLastError(0xdeadbeef);
+ scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
+
+ if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
+ return;
+ }
+ CloseServiceHandle(scm_handle);
+
+ /* First some parameter checking */
+ test_open_scm();
+ test_open_svc();
+ test_create_delete_svc();
+ test_get_displayname();
+ test_get_servicekeyname();
+ test_close();
+ /* Test the creation, querying and deletion of a service */
+ test_sequence();
+ test_queryconfig2();
+ /* The main reason for this test is to check if any refcounting is used
+ * and what the rules are
+ */
+ test_refcount();
+}
#define STANDALONE
#include "wine/test.h"
+extern void func_cred(void);
extern void func_crypt(void);
extern void func_crypt_lmhash(void);
extern void func_crypt_md4(void);
extern void func_lsa(void);
extern void func_registry(void);
extern void func_security(void);
+extern void func_service(void);
const struct test winetest_testlist[] =
{
-/* { "crypt", func_crypt },
+ { "cred", func_cred },
+ { "crypt", func_crypt },
{ "crypt_lmhash", func_crypt_lmhash },
{ "crypt_md4", func_crypt_md4 },
{ "crypt_md5", func_crypt_md5 },
{ "crypt_sha", func_crypt_sha },
{ "lsa", func_lsa },
-*/ { "registry", func_registry },
+ { "registry", func_registry },
{ "security", func_security },
+ { "service", func_service },
{ 0, 0 }
};
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<group>
-<module name="advpack_winetest" type="win32cui" installbase="bin" installname="advpack_winetest.exe" allowwarnings="true" entrypoint="0">
+<module name="advpack_winetest" type="win32cui" installbase="bin" installname="advpack_winetest.exe" allowwarnings="true">
<include base="advpack_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
return ret;
}
-#define FIELD_LEN 16
-
-static BOOL check_ini_contents(LPSTR filename, BOOL add)
-{
- CHAR field[FIELD_LEN];
- BOOL ret = TRUE, match;
-
- GetPrivateProfileStringA("backup", "one", NULL, field, FIELD_LEN, filename);
- match = !lstrcmpA(field, "-1,0,0,0,0,0,-1");
- if ((add && !match) || (!add && match)) {
- trace("first test: got %s\n", field);
- ret = FALSE;
- }
-
- GetPrivateProfileStringA("backup", "two", NULL, field, FIELD_LEN, filename);
- if (lstrcmpA(field, "-1,0,0,0,0,0,-1")) {
- trace("second test: got %s\n", field);
- ret = FALSE;
- }
-
- GetPrivateProfileStringA("backup", "three", NULL, field, FIELD_LEN, filename);
- match = !lstrcmpA(field, "-1,0,0,0,0,0,-1");
- if ((add && !match) || (!add && match)) {
- trace("third test: got %s\n", field);
- ret = FALSE;
- }
-
- return ret;
-}
-
static void test_AddDelBackupEntry(void)
{
HRESULT res;
res = pAddDelBackupEntry("one\0two\0three\0", "c:\\", "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(check_ini_file_attr(path), "Expected ini file to be hidden\n");
- ok(check_ini_contents(path, TRUE), "Expected ini contents to match\n");
ok(DeleteFileA(path), "Expected path to exist\n");
lstrcpyA(path, CURR_DIR);
res = pAddDelBackupEntry("one\0two\0three\0", "backup", "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(!check_ini_file_attr(path), "Expected ini file to not be hidden\n");
- ok(!check_ini_contents(path, TRUE), "Expected ini contents to not match\n");
ok(!DeleteFileA(path), "Expected path to not exist\n");
/* try an existent, relative backup directory */
res = pAddDelBackupEntry("one\0two\0three\0", "backup", "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(check_ini_file_attr(path), "Expected ini file to be hidden\n");
- ok(check_ini_contents(path, TRUE), "Expected ini contents to match\n");
ok(DeleteFileA(path), "Expected path to exist\n");
RemoveDirectoryA("backup");
/* try a NULL backup dir, INI is created in the windows directory */
res = pAddDelBackupEntry("one\0two\0three\0", NULL, "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
- ok(check_ini_contents(path, TRUE), "Expected ini contents to match\n");
/* remove the entries with AADBE_DEL_ENTRY */
SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL);
res = pAddDelBackupEntry("one\0three\0", NULL, "basename", AADBE_DEL_ENTRY);
SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
- ok(check_ini_contents(path, FALSE), "Expected ini contents to match\n");
ok(DeleteFileA(path), "Expected path to exist\n");
}
/* extract all files in the cab to nonexistent destination directory */
hr = pExtractFiles("extract.cab", destFolder, 0, NULL, NULL, 0);
- ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND),
- "Expected %d, got %d\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), hr);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) ||
+ hr == E_FAIL, /* win95 */
+ "Expected %08x or %08x, got %08x\n", E_FAIL,
+ HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), hr);
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(!RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to not exist\n");
static void test_AdvInstallFile(void)
{
HRESULT hr;
+ HMODULE hmod;
char CURR_DIR[MAX_PATH];
char destFolder[MAX_PATH];
+ hmod = LoadLibrary("setupapi.dll");
+ if (!hmod)
+ {
+ skip("setupapi.dll not present\n");
+ return;
+ }
+
+ FreeLibrary(hmod);
+
GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
lstrcpyA(destFolder, CURR_DIR);
ole_ok(acl->lpVtbl->Expand(acl, exp));
ok(acl1->expcount == 1, "expcount - expected 1, got %d\n", acl1->expcount);
- ok(acl2->expcount == 0, "expcount - expected 0, got %d\n", acl2->expcount);
+ ok(acl2->expcount == 0 /* XP */ || acl2->expcount == 1 /* Vista */,
+ "expcount - expected 0 or 1, got %d\n", acl2->expcount);
ole_ok(obj->lpVtbl->Next(obj, 15, wstrtab, &i));
ok(i == 1, "Expected i == 1, got %d\n", i);
ole_ok(obj->lpVtbl->Next(obj, 15, wstrtab, &i));
ole_ok(acl->lpVtbl->Expand(acl, exp));
ok(acl1->expcount == 2, "expcount - expected 1, got %d\n", acl1->expcount);
- ok(acl2->expcount == 0, "expcount - expected 0, got %d\n", acl2->expcount);
+ ok(acl2->expcount == 0 /* XP */ || acl2->expcount == 2 /* Vista */,
+ "expcount - expected 0 or 2, got %d\n", acl2->expcount);
acl1->expret = S_FALSE;
ole_ok(acl->lpVtbl->Expand(acl, exp));
ok(acl1->expcount == 3, "expcount - expected 1, got %d\n", acl1->expcount);
- ok(acl2->expcount == 1, "expcount - expected 0, got %d\n", acl2->expcount);
+ ok(acl2->expcount == 1 /* XP */ || acl2->expcount == 3 /* Vista */,
+ "expcount - expected 0 or 3, got %d\n", acl2->expcount);
acl1->expret = E_NOTIMPL;
ole_ok(acl->lpVtbl->Expand(acl, exp));
ok(acl1->expcount == 4, "expcount - expected 1, got %d\n", acl1->expcount);
- ok(acl2->expcount == 2, "expcount - expected 0, got %d\n", acl2->expcount);
+ ok(acl2->expcount == 2 /* XP */ || acl2->expcount == 4 /* Vista */,
+ "expcount - expected 0 or 4, got %d\n", acl2->expcount);
acl2->expret = E_OUTOFMEMORY;
ok(acl->lpVtbl->Expand(acl, exp) == E_OUTOFMEMORY, "Unexpected Expand return\n");
acl2->expret = E_FAIL;