wintrust: Implementation of WintrustAddActionID.
diff --git a/dlls/wintrust/register.c b/dlls/wintrust/register.c
index 93b1fed..10ccbae 100644
--- a/dlls/wintrust/register.c
+++ b/dlls/wintrust/register.c
@@ -49,6 +49,48 @@
static const WCHAR DiagnosticPolicy[] = {'D','i','a','g','n','o','s','t','i','c','P','o','l','i','c','y','\\', 0};
static const WCHAR Cleanup[] = {'C','l','e','a','n','u','p','\\', 0};
+/***********************************************************************
+ * WINTRUST_WriteProviderToReg
+ *
+ * Helper function for WintrustAddActionID
+ *
+ */
+static LONG WINTRUST_WriteProviderToReg(WCHAR* GuidString,
+ const WCHAR* FunctionType,
+ CRYPT_TRUST_REG_ENTRY RegEntry)
+{
+ static const WCHAR Dll[] = {'$','D','L','L', 0};
+ static const WCHAR Function[] = {'$','F','u','n','c','t','i','o','n', 0};
+ WCHAR ProvKey[MAX_PATH];
+ HKEY Key;
+ LONG Res = ERROR_SUCCESS;
+
+ /* Create the needed key string */
+ ProvKey[0]='\0';
+ lstrcatW(ProvKey, Trust);
+ lstrcatW(ProvKey, FunctionType);
+ lstrcatW(ProvKey, GuidString);
+
+ if (!RegEntry.pwszDLLName || !RegEntry.pwszFunctionName)
+ return ERROR_INVALID_PARAMETER;
+
+ Res = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ProvKey, 0, NULL, 0, KEY_WRITE, NULL, &Key, NULL);
+ if (Res != ERROR_SUCCESS) goto error_close_key;
+
+ /* Create the $DLL entry */
+ Res = RegSetValueExW(Key, Dll, 0, REG_SZ, (BYTE*)RegEntry.pwszDLLName,
+ (lstrlenW(RegEntry.pwszDLLName) + 1)*sizeof(WCHAR));
+ if (Res != ERROR_SUCCESS) goto error_close_key;
+
+ /* Create the $Function entry */
+ Res = RegSetValueExW(Key, Function, 0, REG_SZ, (BYTE*)RegEntry.pwszFunctionName,
+ (lstrlenW(RegEntry.pwszFunctionName) + 1)*sizeof(WCHAR));
+
+error_close_key:
+ RegCloseKey(Key);
+
+ return Res;
+}
/***********************************************************************
* WintrustAddActionID (WINTRUST.@)
@@ -71,17 +113,77 @@
* to the registry. No verification takes place whether a DLL or it's
* entrypoints exist.
* Information in the registry will always be overwritten.
+ *
*/
BOOL WINAPI WintrustAddActionID( GUID* pgActionID, DWORD fdwFlags,
CRYPT_REGISTER_ACTIONID* psProvInfo)
{
- FIXME("%p %lx %p\n", pgActionID, fdwFlags, psProvInfo);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
+ '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
+ 'X','%','0','2','X','%','0','2','X','}', 0};
+
+ WCHAR GuidString[39];
+ LONG Res;
+ LONG WriteActionError = ERROR_SUCCESS;
+
+ TRACE("%p %lx %p\n", debugstr_guid(pgActionID), fdwFlags, psProvInfo);
+
+ /* Some sanity checks.
+ * We use the W2K3 last error as it makes more sense (W2K leaves the last error
+ * as is).
+ */
+ if (!pgActionID ||
+ !psProvInfo ||
+ (psProvInfo->cbStruct != sizeof(CRYPT_REGISTER_ACTIONID)))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* Create this string only once, instead of in the helper function */
+ wsprintfW(GuidString, wszFormat, pgActionID->Data1, pgActionID->Data2, pgActionID->Data3,
+ pgActionID->Data4[0], pgActionID->Data4[1], pgActionID->Data4[2], pgActionID->Data4[3],
+ pgActionID->Data4[4], pgActionID->Data4[5], pgActionID->Data4[6], pgActionID->Data4[7]);
+
+ /* Write the information to the registry */
+ Res = WINTRUST_WriteProviderToReg(GuidString, Initialization , psProvInfo->sInitProvider);
+ if (Res != ERROR_SUCCESS) WriteActionError = Res;
+ Res = WINTRUST_WriteProviderToReg(GuidString, Message , psProvInfo->sObjectProvider);
+ if (Res != ERROR_SUCCESS) WriteActionError = Res;
+ Res = WINTRUST_WriteProviderToReg(GuidString, Signature , psProvInfo->sSignatureProvider);
+ if (Res != ERROR_SUCCESS) WriteActionError = Res;
+ Res = WINTRUST_WriteProviderToReg(GuidString, Certificate , psProvInfo->sCertificateProvider);
+ if (Res != ERROR_SUCCESS) WriteActionError = Res;
+ Res = WINTRUST_WriteProviderToReg(GuidString, CertCheck , psProvInfo->sCertificatePolicyProvider);
+ if (Res != ERROR_SUCCESS) WriteActionError = Res;
+ Res = WINTRUST_WriteProviderToReg(GuidString, FinalPolicy , psProvInfo->sFinalPolicyProvider);
+ if (Res != ERROR_SUCCESS) WriteActionError = Res;
+ Res = WINTRUST_WriteProviderToReg(GuidString, DiagnosticPolicy, psProvInfo->sTestPolicyProvider);
+ if (Res != ERROR_SUCCESS) WriteActionError = Res;
+ Res = WINTRUST_WriteProviderToReg(GuidString, Cleanup , psProvInfo->sCleanupProvider);
+ if (Res != ERROR_SUCCESS) WriteActionError = Res;
+
+ /* Testing (by restricting access to the registry for some keys) shows that the last failing function
+ * will be used for last error.
+ * an error is the one used to propagate the last error.
+ * If the flag WT_ADD_ACTION_ID_RET_RESULT_FLAG is set and there are errors when adding the action
+ * we have to return FALSE. Errors includes both invalid entries as well as registry errors.
+ * Testing also showed that one error doesn't stop the registry writes. Every action will be dealt with.
+ */
+
+ if (WriteActionError != ERROR_SUCCESS)
+ {
+ SetLastError(WriteActionError);
+
+ if (fdwFlags == WT_ADD_ACTION_ID_RET_RESULT_FLAG)
+ return FALSE;
+ }
+
+ return TRUE;
}
/***********************************************************************
- * WINTRUST_RemoveProviderFromReg (WINTRUST.@)
+ * WINTRUST_RemoveProviderFromReg
*
* Helper function for WintrustRemoveActionID
*
diff --git a/dlls/wintrust/tests/register.c b/dlls/wintrust/tests/register.c
index 2a56c07..51804ac 100644
--- a/dlls/wintrust/tests/register.c
+++ b/dlls/wintrust/tests/register.c
@@ -70,47 +70,35 @@
SetLastError(0xdeadbeef);
ret = pWintrustAddActionID(NULL, 0, NULL);
ok (!ret, "Expected WintrustAddActionID to fail.\n");
- todo_wine
- {
- ok (GetLastError() == ERROR_INVALID_PARAMETER /* XP/W2K3 */ ||
- GetLastError() == 0xdeadbeef /* Win98/NT4/W2K */,
- "Expected ERROR_INVALID_PARAMETER(W2K3) or 0xdeadbeef(Win98/NT4/W2K), got %ld.\n", GetLastError());
- }
+ ok (GetLastError() == ERROR_INVALID_PARAMETER /* XP/W2K3 */ ||
+ GetLastError() == 0xdeadbeef /* Win98/NT4/W2K */,
+ "Expected ERROR_INVALID_PARAMETER(W2K3) or 0xdeadbeef(Win98/NT4/W2K), got %ld.\n", GetLastError());
/* NULL functions */
SetLastError(0xdeadbeef);
ret = pWintrustAddActionID(&ActionID, 0, NULL);
ok (!ret, "Expected WintrustAddActionID to fail.\n");
- todo_wine
- {
- ok (GetLastError() == ERROR_INVALID_PARAMETER /* XP/W2K3 */ ||
- GetLastError() == 0xdeadbeef /* Win98/NT4/W2K */,
- "Expected ERROR_INVALID_PARAMETER(W2K3) or 0xdeadbeef(Win98/NT4/W2K), got %ld.\n", GetLastError());
- }
+ ok (GetLastError() == ERROR_INVALID_PARAMETER /* XP/W2K3 */ ||
+ GetLastError() == 0xdeadbeef /* Win98/NT4/W2K */,
+ "Expected ERROR_INVALID_PARAMETER(W2K3) or 0xdeadbeef(Win98/NT4/W2K), got %ld.\n", GetLastError());
/* All OK (although no functions defined), except cbStruct is not set in ActionIDFunctions */
SetLastError(0xdeadbeef);
memset(&ActionIDFunctions, 0, sizeof(CRYPT_REGISTER_ACTIONID));
ret = pWintrustAddActionID(&ActionID, 0, &ActionIDFunctions);
ok (!ret, "Expected WintrustAddActionID to fail.\n");
- todo_wine
- {
- ok (GetLastError() == ERROR_INVALID_PARAMETER /* XP/W2K3 */ ||
- GetLastError() == 0xdeadbeef /* Win98/NT4/W2K */,
- "Expected ERROR_INVALID_PARAMETER(W2K3) or 0xdeadbeef(Win98/NT4/W2K), got %ld.\n", GetLastError());
- }
+ ok (GetLastError() == ERROR_INVALID_PARAMETER /* XP/W2K3 */ ||
+ GetLastError() == 0xdeadbeef /* Win98/NT4/W2K */,
+ "Expected ERROR_INVALID_PARAMETER(W2K3) or 0xdeadbeef(Win98/NT4/W2K), got %ld.\n", GetLastError());
/* All OK (although no functions defined) and cbStruct is set now */
SetLastError(0xdeadbeef);
memset(&ActionIDFunctions, 0, sizeof(CRYPT_REGISTER_ACTIONID));
ActionIDFunctions.cbStruct = sizeof(CRYPT_REGISTER_ACTIONID);
ret = pWintrustAddActionID(&ActionID, 0, &ActionIDFunctions);
- todo_wine
- {
- ok (ret, "Expected WintrustAddActionID to succeed.\n");
- ok (GetLastError() == ERROR_INVALID_PARAMETER /* W2K */,
- "Expected ERROR_INVALID_PARAMETER, got %ld.\n", GetLastError());
- }
+ ok (ret, "Expected WintrustAddActionID to succeed.\n");
+ ok (GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %ld.\n", GetLastError());
/* All OK and all (but 1) functions are correctly defined. The DLL and entrypoints
* are not present.
@@ -127,12 +115,9 @@
ActionIDFunctions.sCleanupProvider = DummyProvider;
SetLastError(0xdeadbeef);
ret = pWintrustAddActionID(&ActionID, 0, &ActionIDFunctions);
- todo_wine
- {
- ok (ret, "Expected WintrustAddActionID to succeed.\n");
- ok (GetLastError() == ERROR_INVALID_PARAMETER,
- "Expected ERROR_INVALID_PARAMETER, got %ld.\n", GetLastError());
- }
+ ok (ret, "Expected WintrustAddActionID to succeed.\n");
+ ok (GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %ld.\n", GetLastError());
/* All OK and all functions are correctly defined. The DLL and entrypoints
* are not present.
@@ -149,12 +134,9 @@
ActionIDFunctions.sCleanupProvider = DummyProvider;
SetLastError(0xdeadbeef);
ret = pWintrustAddActionID(&ActionID, 0, &ActionIDFunctions);
- todo_wine
- {
- ok (ret, "Expected WintrustAddActionID to succeed.\n");
- ok (GetLastError() == 0xdeadbeef,
- "Expected 0xdeadbeef, got %ld.\n", GetLastError());
- }
+ ok (ret, "Expected WintrustAddActionID to succeed.\n");
+ ok (GetLastError() == 0xdeadbeef,
+ "Expected 0xdeadbeef, got %ld.\n", GetLastError());
SetLastError(0xdeadbeef);
ret = pWintrustRemoveActionID(&ActionID);
diff --git a/include/wintrust.h b/include/wintrust.h
index 2e7917d..b04e134 100644
--- a/include/wintrust.h
+++ b/include/wintrust.h
@@ -297,6 +297,7 @@
#include <poppack.h>
+#define WT_ADD_ACTION_ID_RET_RESULT_FLAG 1
#ifdef __cplusplus
extern "C" {