Index: /trunk/src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp	(revision 96764)
+++ /trunk/src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp	(revision 96765)
@@ -488,7 +488,12 @@
  * @param   dwDisposition   The disposition towards existing certificates when
  *                          adding it.  CERT_STORE_ADD_NEW is a safe one.
- */
-static bool addCertToStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
-{
+ * @param   pfAlreadyExists Where to indicate whether the certificate was
+ *                          already present and not replaced.
+ */
+static bool addCertToStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition,
+                                 bool *pfAlreadyExists)
+{
+    *pfAlreadyExists = false;
+
     /*
      * Read the certificate file first.
@@ -514,5 +519,10 @@
                 fRc = true;
             else
-                RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
+            {
+                DWORD const dwErr = GetLastError();
+                *pfAlreadyExists = fRc = dwErr == CRYPT_E_EXISTS;
+                if (!fRc)
+                    RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(dwErr));
+            }
         }
         else
@@ -533,5 +543,5 @@
  */
 static RTEXITCODE addCertToStoreByFilePattern(DWORD dwDst, const char *pszStoreNm, const char *pszStoreDesc,
-                                              const char *pszFilePattern, RTEXITCODE rcExit, uint32_t *pcImports)
+                                              const char *pszFilePattern, bool fForce, RTEXITCODE rcExit, uint32_t *pcImports)
 {
     PCRTPATHGLOBENTRY pResultHead;
@@ -541,6 +551,15 @@
         for (PCRTPATHGLOBENTRY pCur = pResultHead; pCur; pCur = pCur->pNext)
         {
-            if (addCertToStoreByFile(dwDst, pszStoreNm, pCur->szPath, CERT_STORE_ADD_NEW))
-                RTMsgInfo("Successfully added '%s' as %s", pCur->szPath, pszStoreDesc);
+            bool fAlreadyExists = false;
+            if (addCertToStoreByFile(dwDst, pszStoreNm, pCur->szPath,
+                                     !fForce ? CERT_STORE_ADD_NEW : CERT_STORE_ADD_REPLACE_EXISTING,
+                                     &fAlreadyExists))
+            {
+                if (!fAlreadyExists)
+                    RTMsgInfo("Successfully added '%s' to the %s store", pCur->szPath, pszStoreDesc);
+                else
+                    RTMsgInfo("Certificate '%s' is already present in the %s store and was not re-added or updated.",
+                              pCur->szPath, pszStoreNm);
+            }
             else
                 rcExit = RTEXITCODE_FAILURE;
@@ -551,5 +570,5 @@
     else
     {
-        rcExit = RTMsgErrorExit(RTEXITCODE_SUCCESS, "glob failed on '%s': %Rrc", pszFilePattern, rc);
+        rcExit = RTMsgErrorExitFailure("glob failed on '%s': %Rrc", pszFilePattern, rc);
         *pcImports += 1;
     }
@@ -678,5 +697,6 @@
 
             case 'h':
-                RTPrintf("Usage: VBoxCertUtil display-all [-v|--verbose] [-q|--quiet]\n");
+                RTStrmWrappedPrintf(g_pStdOut, RTSTRMWRAPPED_F_HANGING_INDENT,
+                                    "Usage: VBoxCertUtil display-all [-v|--verbose] [-q|--quiet]\n");
                 return RTEXITCODE_SUCCESS;
 
@@ -723,15 +743,17 @@
 
             case 'h':
-                RTPrintf("Usage: VBoxCertUtil root-exists <full-subject-name> [alternative-subject-name [...]]\n"
-                         "\n"
-                         "Exit code: 10 if not found, 0 if found.\n"
-                         "\n"
-                         "The names are on the form 'C=US; O=Company; OU=some unit; CN=a cert name'\n"
-                         "where semi-colon is the X.500 attribute separator and spaces surrounding it\n"
-                         "the type (CN, OU, ) and '=' are generally ignored.\n"
-                         "\n"
-                         "At verbosity level 2, the full subject name of each certificate in the store\n"
-                         "will be listed as the search progresses.  These can be used as search input.\n"
-                         );
+                RTStrmWrappedPrintf(g_pStdOut, RTSTRMWRAPPED_F_HANGING_INDENT,
+                                    "Usage: VBoxCertUtil root-exists <full-subject-name> [alternative-subject-name [...]]\n");
+                RTStrmWrappedPrintf(g_pStdOut, 0,
+                                    "\n"
+                                    "Exit code: 10 if not found, 0 if found.\n"
+                                    "\n"
+                                    "The names are on the form 'C=US; O=Company; OU=some unit; CN=a cert name' "
+                                    "where semi-colon is the X.500 attribute separator and spaces surrounding it "
+                                    "the type (CN, OU, ) and '=' are generally ignored.\n"
+                                    "\n"
+                                    "At verbosity level 2, the full subject name of each certificate in the store "
+                                    "will be listed as the search progresses.  These can be used as search input.\n"
+                                    );
                 return RTEXITCODE_SUCCESS;
 
@@ -781,5 +803,6 @@
 
             case 'h':
-                RTPrintf("Usage: VBoxCertUtil remove-root <root-cert-file>\n");
+                RTStrmWrappedPrintf(g_pStdOut, RTSTRMWRAPPED_F_HANGING_INDENT,
+                                    "Usage: VBoxCertUtil remove-root <root-cert-file>\n");
                 return RTEXITCODE_SUCCESS;
 
@@ -827,5 +850,6 @@
 
             case 'h':
-                RTPrintf("Usage: VBoxCertUtil remove-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
+                RTStrmWrappedPrintf(g_pStdOut, RTSTRMWRAPPED_F_HANGING_INDENT,
+                                    "Usage: VBoxCertUtil remove-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
                 return RTEXITCODE_SUCCESS;
 
@@ -861,9 +885,12 @@
     static const RTGETOPTDEF s_aOptions[] =
     {
+        { "--add-if-new",   'a',    RTGETOPT_REQ_NOTHING },
+        { "--force",        'f',    RTGETOPT_REQ_NOTHING },
         VCU_COMMON_OPTION_DEFINITIONS(),
     };
 
-    RTEXITCODE          rcExit = RTEXITCODE_SUCCESS;
-    unsigned            cImports = 0;
+    RTEXITCODE          rcExit    = RTEXITCODE_SUCCESS;
+    unsigned            cImports  = 0;
+    bool                fForce    = false;
     RTGETOPTUNION       ValueUnion;
     RTGETOPTSTATE       GetState;
@@ -876,11 +903,20 @@
             VCU_COMMON_OPTION_HANDLING();
 
+            case 'a':
+                fForce = false;
+                break;
+
+            case 'f':
+                fForce = false;
+                break;
+
             case 'h':
-                RTPrintf("Usage: VBoxCertUtil add-root <root-cert>\n");
+                RTStrmWrappedPrintf(g_pStdOut, RTSTRMWRAPPED_F_HANGING_INDENT,
+                                    "Usage: VBoxCertUtil add-root [--force|--add-if-new] <root-cert>\n");
                 return RTEXITCODE_SUCCESS;
 
             case VINF_GETOPT_NOT_OPTION:
                 rcExit = addCertToStoreByFilePattern(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", "root",
-                                                     ValueUnion.psz, rcExit, &cImports);
+                                                     ValueUnion.psz, fForce, rcExit, &cImports);
                 break;
 
@@ -905,10 +941,13 @@
     static const RTGETOPTDEF s_aOptions[] =
     {
-        { "--root",     'r',    RTGETOPT_REQ_STRING },
+        { "--root",         'r',    RTGETOPT_REQ_STRING },
+        { "--add-if-new",   'a',    RTGETOPT_REQ_NOTHING },
+        { "--force",        'f',    RTGETOPT_REQ_NOTHING },
         VCU_COMMON_OPTION_DEFINITIONS(),
     };
 
-    RTEXITCODE          rcExit = RTEXITCODE_SUCCESS;
-    unsigned            cImports = 0;
+    RTEXITCODE          rcExit    = RTEXITCODE_SUCCESS;
+    bool                fForce    = false;
+    unsigned            cImports  = 0;
     RTGETOPTUNION       ValueUnion;
     RTGETOPTSTATE       GetState;
@@ -921,16 +960,26 @@
             VCU_COMMON_OPTION_HANDLING();
 
+            case 'a':
+                fForce = false;
+                break;
+
+            case 'f':
+                fForce = false;
+                break;
+
             case 'h':
-                RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
+                RTStrmWrappedPrintf(g_pStdOut, RTSTRMWRAPPED_F_HANGING_INDENT,
+                                    "Usage: VBoxCertUtil add-trusted-publisher [--force|--add-if-new] "
+                                    "[--root <root-cert>] <trusted-cert>\n");
                 return RTEXITCODE_SUCCESS;
 
             case 'r':
                 rcExit = addCertToStoreByFilePattern(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", "root",
-                                                     ValueUnion.psz, rcExit, &cImports);
+                                                     ValueUnion.psz, fForce, rcExit, &cImports);
                 break;
 
             case VINF_GETOPT_NOT_OPTION:
                 rcExit = addCertToStoreByFilePattern(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", "trusted publisher",
-                                                     ValueUnion.psz, rcExit, &cImports);
+                                                     ValueUnion.psz, fForce, rcExit, &cImports);
                 break;
 
