Index: src/installer-ca/dutil/dutil.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/installer-ca/dutil/dutil.cpp |
@@ -0,0 +1,448 @@ |
+//------------------------------------------------------------------------------------------------- |
+// <copyright file="dutil.cpp" company="Outercurve Foundation"> |
+// Copyright (c) 2004, Outercurve Foundation. |
+// This software is released under Microsoft Reciprocal License (MS-RL). |
+// The license and further copyright text can be found in the file |
+// LICENSE.TXT at the root directory of the distribution. |
+// </copyright> |
+// |
+// <summary> |
+// Utility layer that provides standard support for asserts, exit macros |
+// </summary> |
+//------------------------------------------------------------------------------------------------- |
+ |
+#include "../precomp.h" |
+ |
+// No need for OACR to warn us about using non-unicode APIs in this file. |
+#pragma prefast(disable:25068) |
+ |
+// Asserts & Tracing |
+ |
+const int DUTIL_STRING_BUFFER = 1024; |
+static HMODULE Dutil_hAssertModule = NULL; |
+static DUTIL_ASSERTDISPLAYFUNCTION Dutil_pfnDisplayAssert = NULL; |
+static BOOL Dutil_fNoAsserts = FALSE; |
+static REPORT_LEVEL Dutil_rlCurrentTrace = REPORT_STANDARD; |
+static BOOL Dutil_fTraceFilenames = FALSE; |
+ |
+ |
+/******************************************************************* |
+Dutil_SetAssertModule |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_SetAssertModule( |
+ __in HMODULE hAssertModule |
+ ) |
+{ |
+ Dutil_hAssertModule = hAssertModule; |
+} |
+ |
+ |
+/******************************************************************* |
+Dutil_SetAssertDisplayFunction |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_SetAssertDisplayFunction( |
+ __in DUTIL_ASSERTDISPLAYFUNCTION pfn |
+ ) |
+{ |
+ Dutil_pfnDisplayAssert = pfn; |
+} |
+ |
+ |
+/******************************************************************* |
+Dutil_AssertMsg |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_AssertMsg( |
+ __in_z LPCSTR szMessage |
+ ) |
+{ |
+ static BOOL fInAssert = FALSE; // TODO: make this thread safe (this is a cheap hack to prevent re-entrant Asserts) |
+ |
+ HRESULT hr = S_OK; |
+ DWORD er = ERROR_SUCCESS; |
+ |
+ int id = IDRETRY; |
+ HKEY hkDebug = NULL; |
+ HANDLE hAssertFile = INVALID_HANDLE_VALUE; |
+ char szPath[MAX_PATH] = { }; |
+ DWORD cch = 0; |
+ |
+ if (fInAssert) |
+ { |
+ return; |
+ } |
+ fInAssert = TRUE; |
+ |
+ char szMsg[DUTIL_STRING_BUFFER]; |
+ hr = ::StringCchCopyA(szMsg, countof(szMsg), szMessage); |
+ ExitOnFailure(hr, "failed to copy message while building assert message"); |
+ |
+ if (Dutil_pfnDisplayAssert) |
+ { |
+ // call custom function to display the assert string |
+ if (!Dutil_pfnDisplayAssert(szMsg)) |
+ { |
+ ExitFunction(); |
+ } |
+ } |
+ else |
+ { |
+ OutputDebugStringA(szMsg); |
+ } |
+ |
+ if (!Dutil_fNoAsserts) |
+ { |
+ er = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Delivery\\Debug", 0, KEY_QUERY_VALUE, &hkDebug); |
+ if (ERROR_SUCCESS == er) |
+ { |
+ cch = countof(szPath); |
+ er = ::RegQueryValueExA(hkDebug, "DeliveryAssertsLog", NULL, NULL, reinterpret_cast<BYTE*>(szPath), &cch); |
+ szPath[countof(szPath) - 1] = '\0'; // ensure string is null terminated since registry won't guarantee that. |
+ if (ERROR_SUCCESS == er) |
+ { |
+ hAssertFile = ::CreateFileA(szPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
+ if (INVALID_HANDLE_VALUE != hAssertFile) |
+ { |
+ ::SetFilePointer(hAssertFile, 0, 0, FILE_END); |
+ ::StringCchCatA(szMsg, countof(szMsg), "\r\n"); |
+ ::WriteFile(hAssertFile, szMsg, lstrlenA(szMsg), &cch, NULL); |
+ } |
+ } |
+ } |
+ |
+ // if anything went wrong while fooling around with the registry, just show the usual assert dialog box |
+ if (ERROR_SUCCESS != er) |
+ { |
+ hr = ::StringCchCatA(szMsg, countof(szMsg), "\nAbort=Debug, Retry=Skip, Ignore=Skip all"); |
+ ExitOnFailure(hr, "failed to concat string while building assert message"); |
+ |
+ id = ::MessageBoxA(0, szMsg, "Debug Assert Message", |
+ MB_SERVICE_NOTIFICATION | MB_TOPMOST | |
+ MB_DEFBUTTON2 | MB_ABORTRETRYIGNORE); |
+ } |
+ } |
+ |
+ if (id == IDABORT) |
+ { |
+ if (Dutil_hAssertModule) |
+ { |
+ ::GetModuleFileNameA(Dutil_hAssertModule, szPath, countof(szPath)); |
+ |
+ hr = ::StringCchPrintfA(szMsg, countof(szMsg), "Module is running from: %s\nIf you are not using pdb-stamping, place your PDB near the module and attach to process id: %d (0x%x)", szPath, ::GetCurrentProcessId(), ::GetCurrentProcessId()); |
+ if (SUCCEEDED(hr)) |
+ { |
+ ::MessageBoxA(0, szMsg, "Debug Assert Message", MB_SERVICE_NOTIFICATION | MB_TOPMOST | MB_OK); |
+ } |
+ } |
+ |
+ ::DebugBreak(); |
+ } |
+ else if (id == IDIGNORE) |
+ { |
+ Dutil_fNoAsserts = TRUE; |
+ } |
+ |
+LExit: |
+ ReleaseFileHandle(hAssertFile); |
+ ReleaseRegKey(hkDebug); |
+ fInAssert = FALSE; |
+} |
+ |
+ |
+/******************************************************************* |
+Dutil_Assert |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_Assert( |
+ __in_z LPCSTR szFile, |
+ __in int iLine |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ char szMessage[DUTIL_STRING_BUFFER] = { }; |
+ hr = ::StringCchPrintfA(szMessage, countof(szMessage), "Assertion failed in %s, %i", szFile, iLine); |
+ if (SUCCEEDED(hr)) |
+ { |
+ Dutil_AssertMsg(szMessage); |
+ } |
+ else |
+ { |
+ Dutil_AssertMsg("Assert failed to build string"); |
+ } |
+} |
+ |
+ |
+/******************************************************************* |
+Dutil_AssertSz |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_AssertSz( |
+ __in_z LPCSTR szFile, |
+ __in int iLine, |
+ __in_z __format_string LPCSTR szMsg |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ char szMessage[DUTIL_STRING_BUFFER] = { }; |
+ |
+ hr = ::StringCchPrintfA(szMessage, countof(szMessage), "Assertion failed in %s, %i\n%s", szFile, iLine, szMsg); |
+ if (SUCCEEDED(hr)) |
+ { |
+ Dutil_AssertMsg(szMessage); |
+ } |
+ else |
+ { |
+ Dutil_AssertMsg("Assert failed to build string"); |
+ } |
+} |
+ |
+ |
+/******************************************************************* |
+Dutil_TraceSetLevel |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_TraceSetLevel( |
+ __in REPORT_LEVEL rl, |
+ __in BOOL fTraceFilenames |
+ ) |
+{ |
+ Dutil_rlCurrentTrace = rl; |
+ Dutil_fTraceFilenames = fTraceFilenames; |
+} |
+ |
+ |
+/******************************************************************* |
+Dutil_TraceGetLevel |
+ |
+*******************************************************************/ |
+extern "C" REPORT_LEVEL DAPI Dutil_TraceGetLevel() |
+{ |
+ return Dutil_rlCurrentTrace; |
+} |
+ |
+ |
+/******************************************************************* |
+Dutil_Trace |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_Trace( |
+ __in_z LPCSTR szFile, |
+ __in int iLine, |
+ __in REPORT_LEVEL rl, |
+ __in_z __format_string LPCSTR szFormat, |
+ ... |
+ ) |
+{ |
+ AssertSz(REPORT_NONE != rl, "REPORT_NONE is not a valid tracing level"); |
+ |
+ HRESULT hr = S_OK; |
+ char szOutput[DUTIL_STRING_BUFFER] = { }; |
+ char szMsg[DUTIL_STRING_BUFFER] = { }; |
+ |
+ if (Dutil_rlCurrentTrace < rl) |
+ { |
+ return; |
+ } |
+ |
+ va_list args; |
+ va_start(args, szFormat); |
+ hr = ::StringCchVPrintfA(szOutput, countof(szOutput), szFormat, args); |
+ va_end(args); |
+ |
+ if (SUCCEEDED(hr)) |
+ { |
+ LPCSTR szPrefix = "Trace/u"; |
+ switch (rl) |
+ { |
+ case REPORT_STANDARD: |
+ szPrefix = "Trace/s"; |
+ break; |
+ case REPORT_VERBOSE: |
+ szPrefix = "Trace/v"; |
+ break; |
+ case REPORT_DEBUG: |
+ szPrefix = "Trace/d"; |
+ break; |
+ } |
+ |
+ if (Dutil_fTraceFilenames) |
+ { |
+ hr = ::StringCchPrintfA(szMsg, countof(szMsg), "%s [%s,%d]: %s\r\n", szPrefix, szFile, iLine, szOutput); |
+ } |
+ else |
+ { |
+ hr = ::StringCchPrintfA(szMsg, countof(szMsg), "%s: %s\r\n", szPrefix, szOutput); |
+ } |
+ |
+ if (SUCCEEDED(hr)) |
+ { |
+ OutputDebugStringA(szMsg); |
+ } |
+ // else fall through to the case below |
+ } |
+ |
+ if (FAILED(hr)) |
+ { |
+ if (Dutil_fTraceFilenames) |
+ { |
+ ::StringCchPrintfA(szMsg, countof(szMsg), "Trace [%s,%d]: message too long, skipping\r\n", szFile, iLine); |
+ } |
+ else |
+ { |
+ ::StringCchPrintfA(szMsg, countof(szMsg), "Trace: message too long, skipping\r\n"); |
+ } |
+ |
+ szMsg[countof(szMsg)-1] = '\0'; |
+ OutputDebugStringA(szMsg); |
+ } |
+} |
+ |
+ |
+/******************************************************************* |
+Dutil_TraceError |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_TraceError( |
+ __in_z LPCSTR szFile, |
+ __in int iLine, |
+ __in REPORT_LEVEL rl, |
+ __in HRESULT hrError, |
+ __in_z __format_string LPCSTR szFormat, |
+ ... |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ char szOutput[DUTIL_STRING_BUFFER] = { }; |
+ char szMsg[DUTIL_STRING_BUFFER] = { }; |
+ |
+ // if this is NOT an error report and we're not logging at this level, bail |
+ if (REPORT_ERROR != rl && Dutil_rlCurrentTrace < rl) |
+ { |
+ return; |
+ } |
+ |
+ va_list args; |
+ va_start(args, szFormat); |
+ hr = ::StringCchVPrintfA(szOutput, countof(szOutput), szFormat, args); |
+ va_end(args); |
+ |
+ if (SUCCEEDED(hr)) |
+ { |
+ if (Dutil_fTraceFilenames) |
+ { |
+ if (FAILED(hrError)) |
+ { |
+ hr = ::StringCchPrintfA(szMsg, countof(szMsg), "TraceError 0x%x [%s,%d]: %s\r\n", hrError, szFile, iLine, szOutput); |
+ } |
+ else |
+ { |
+ hr = ::StringCchPrintfA(szMsg, countof(szMsg), "TraceError [%s,%d]: %s\r\n", szFile, iLine, szOutput); |
+ } |
+ } |
+ else |
+ { |
+ if (FAILED(hrError)) |
+ { |
+ hr = ::StringCchPrintfA(szMsg, countof(szMsg), "TraceError 0x%x: %s\r\n", hrError, szOutput); |
+ } |
+ else |
+ { |
+ hr = ::StringCchPrintfA(szMsg, countof(szMsg), "TraceError: %s\r\n", szOutput); |
+ } |
+ } |
+ |
+ if (SUCCEEDED(hr)) |
+ { |
+ OutputDebugStringA(szMsg); |
+ } |
+ // else fall through to the failure case below |
+ } |
+ |
+ if (FAILED(hr)) |
+ { |
+ if (Dutil_fTraceFilenames) |
+ { |
+ if (FAILED(hrError)) |
+ { |
+ ::StringCchPrintfA(szMsg, countof(szMsg), "TraceError 0x%x [%s,%d]: message too long, skipping\r\n", hrError, szFile, iLine); |
+ } |
+ else |
+ { |
+ ::StringCchPrintfA(szMsg, countof(szMsg), "TraceError [%s,%d]: message too long, skipping\r\n", szFile, iLine); |
+ } |
+ } |
+ else |
+ { |
+ if (FAILED(hrError)) |
+ { |
+ ::StringCchPrintfA(szMsg, countof(szMsg), "TraceError 0x%x: message too long, skipping\r\n", hrError); |
+ } |
+ else |
+ { |
+ ::StringCchPrintfA(szMsg, countof(szMsg), "TraceError: message too long, skipping\r\n"); |
+ } |
+ } |
+ |
+ szMsg[countof(szMsg)-1] = '\0'; |
+ OutputDebugStringA(szMsg); |
+ } |
+} |
+ |
+ |
+ |
+/******************************************************************* |
+Dutil_RootFailure |
+ |
+*******************************************************************/ |
+extern "C" void DAPI Dutil_RootFailure( |
+ __in_z LPCSTR szFile, |
+ __in int iLine, |
+ __in HRESULT hrError |
+ ) |
+{ |
+#ifndef DEBUG |
+ UNREFERENCED_PARAMETER(szFile); |
+ UNREFERENCED_PARAMETER(iLine); |
+ UNREFERENCED_PARAMETER(hrError); |
+#endif // DEBUG |
+ |
+ TraceError2(hrError, "Root failure at %s:%d", szFile, iLine); |
+} |
+ |
+/******************************************************************* |
+ LoadSystemLibrary - Fully qualifies the path to a module in the |
+ Windows system directory and loads it. |
+ |
+ Returns |
+ E_MODNOTFOUND - The module could not be found. |
+ * - Another error occured. |
+********************************************************************/ |
+extern "C" HRESULT DAPI LoadSystemLibrary( |
+ __in_z LPCWSTR wzModuleName, |
+ __out HMODULE *phModule |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ DWORD cch = 0; |
+ WCHAR wzPath[MAX_PATH] = { }; |
+ |
+ cch = ::GetSystemDirectoryW(wzPath, MAX_PATH); |
+ ExitOnNullWithLastError(cch, hr, "Failed to get the Windows system directory."); |
+ |
+ if (L'\\' != wzPath[cch - 1]) |
+ { |
+ hr = ::StringCchCatNW(wzPath, MAX_PATH, L"\\", 1); |
+ ExitOnRootFailure(hr, "Failed to terminate the string with a backslash."); |
+ } |
+ |
+ hr = ::StringCchCatW(wzPath, MAX_PATH, wzModuleName); |
+ ExitOnRootFailure1(hr, "Failed to create the fully-qualified path to %ls.", wzModuleName); |
+ |
+ *phModule = ::LoadLibraryW(wzPath); |
+ ExitOnNullWithLastError1(*phModule, hr, "Failed to load the library %ls.", wzModuleName); |
+ |
+LExit: |
+ return hr; |
+} |