Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

959 lines
25 KiB

  1. // ==++==
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // ==--==
  6. #include <windows.h>
  7. #include "dbglog.h"
  8. #include "wininet.h"
  9. #include "util.h"
  10. //#include "lock.h"
  11. #include "version.h"
  12. extern HINSTANCE g_hInst;
  13. extern WCHAR g_FusionDllPath[MAX_PATH+1];
  14. #define XSP_APP_CACHE_DIR L"Temporary ASP.NET Files"
  15. #define XSP_FUSION_LOG_DIR L"Bind Logs"
  16. #define REG_KEY_FUSION_SETTINGS TEXT("Software\\Microsoft\\Fusion\\Installer\\1.0.0.0\\")
  17. #define DLTYPE_DEFAULT L"DEFAULT"
  18. #define DLTYPE_FOREGROUND L"Foreground"
  19. #define DLTYPE_BACKGROUND L"Background"
  20. WCHAR g_wzEXEPath[MAX_PATH+1];
  21. DWORD g_dwDisableLog;
  22. DWORD g_dwForceLog;
  23. DWORD g_dwLogFailures;
  24. DWORD g_dwLoggingLevel=1;
  25. void GetExePath()
  26. {
  27. static BOOL bFirstTime=TRUE;
  28. if(bFirstTime)
  29. {
  30. if (!GetModuleFileNameW(NULL, g_wzEXEPath, MAX_PATH)) {
  31. lstrcpyW(g_wzEXEPath, L"Unknown");
  32. }
  33. bFirstTime=FALSE;
  34. }
  35. }
  36. BOOL IsHosted()
  37. {
  38. return FALSE;
  39. }
  40. HRESULT GetRegValues()
  41. {
  42. DWORD dwSize;
  43. DWORD dwType;
  44. DWORD lResult;
  45. HKEY hkey=0;
  46. DWORD dwValue=0;
  47. lResult = RegOpenKeyEx(HKEY_CURRENT_USER, REG_KEY_FUSION_SETTINGS, 0, KEY_READ, &hkey);
  48. if(lResult == ERROR_SUCCESS) {
  49. // Get Logging Level
  50. dwSize = sizeof(DWORD);
  51. lResult = RegQueryValueEx(hkey, REG_VAL_FUSION_LOG_LEVEL, NULL,
  52. &dwType, (LPBYTE)&dwValue, &dwSize);
  53. if (lResult != ERROR_SUCCESS) {
  54. g_dwLoggingLevel = 0;
  55. }
  56. else
  57. {
  58. g_dwLoggingLevel = dwValue;
  59. }
  60. // Get Log Failures
  61. dwSize = sizeof(DWORD);
  62. lResult = RegQueryValueEx(hkey, REG_VAL_FUSION_LOG_FAILURES, NULL,
  63. &dwType, (LPBYTE)&dwValue, &dwSize);
  64. if (lResult != ERROR_SUCCESS) {
  65. g_dwLogFailures = 0;
  66. }
  67. else
  68. {
  69. g_dwLogFailures = dwValue;
  70. }
  71. }
  72. return S_OK;
  73. }
  74. HRESULT CreateLogObject(CDebugLog **ppdbglog, LPCWSTR szCodebase)
  75. {
  76. HRESULT hr = S_OK;
  77. MAKE_ERROR_MACROS_STATIC(hr);
  78. IF_FAILED_EXIT(CDebugLog::Create(NULL, NULL, ppdbglog));
  79. // hr = GetRegValues();
  80. exit:
  81. return hr;
  82. }
  83. //
  84. // CDebugLogElement Class
  85. //
  86. HRESULT CDebugLogElement::Create(DWORD dwDetailLvl, LPCWSTR pwzMsg,
  87. CDebugLogElement **ppLogElem)
  88. {
  89. HRESULT hr = S_OK;
  90. CDebugLogElement *pLogElem = NULL;
  91. if (!ppLogElem || !pwzMsg) {
  92. hr = E_INVALIDARG;
  93. goto Exit;
  94. }
  95. *ppLogElem = NULL;
  96. pLogElem = FUSION_NEW_SINGLETON(CDebugLogElement(dwDetailLvl));
  97. if (!pLogElem) {
  98. hr = E_OUTOFMEMORY;
  99. goto Exit;
  100. }
  101. hr = pLogElem->Init(pwzMsg);
  102. if (FAILED(hr)) {
  103. SAFEDELETE(pLogElem);
  104. goto Exit;
  105. }
  106. *ppLogElem = pLogElem;
  107. Exit:
  108. return hr;
  109. }
  110. CDebugLogElement::CDebugLogElement(DWORD dwDetailLvl)
  111. : _pszMsg(NULL)
  112. , _dwDetailLvl(dwDetailLvl)
  113. {
  114. }
  115. CDebugLogElement::~CDebugLogElement()
  116. {
  117. SAFEDELETEARRAY(_pszMsg);
  118. }
  119. HRESULT CDebugLogElement::Init(LPCWSTR pwzMsg)
  120. {
  121. HRESULT hr = S_OK;
  122. ASSERT(pwzMsg);
  123. _pszMsg = WSTRDupDynamic(pwzMsg);
  124. if (!_pszMsg) {
  125. hr = E_OUTOFMEMORY;
  126. goto Exit;
  127. }
  128. Exit:
  129. return hr;
  130. }
  131. /*******************************************************************
  132. NAME: Unicode2Ansi
  133. SYNOPSIS: Converts a unicode widechar string to ansi (MBCS)
  134. NOTES: Caller must free out parameter using delete
  135. ********************************************************************/
  136. HRESULT Unicode2Ansi(const wchar_t *src, char ** dest)
  137. {
  138. if ((src == NULL) || (dest == NULL))
  139. return E_INVALIDARG;
  140. // find out required buffer size and allocate it.
  141. int len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
  142. *dest = NEW(char [len*sizeof(char)]);
  143. if (!*dest)
  144. return E_OUTOFMEMORY;
  145. // Now do the actual conversion
  146. if ((WideCharToMultiByte(CP_ACP, 0, src, -1, *dest, len*sizeof(char),
  147. NULL, NULL)) != 0)
  148. return S_OK;
  149. else
  150. return HRESULT_FROM_WIN32(GetLastError());
  151. }
  152. HRESULT CDebugLogElement::Dump(HANDLE hFile)
  153. {
  154. HRESULT hr = S_OK;
  155. DWORD dwLen = 0;
  156. DWORD dwWritten = 0;
  157. DWORD dwSize = 0;
  158. DWORD dwBufSize = 0;
  159. LPSTR szBuf = NULL;
  160. BOOL bRet;
  161. if (!hFile) {
  162. hr = E_INVALIDARG;
  163. goto Exit;
  164. }
  165. dwSize = lstrlenW(_pszMsg) + 1;
  166. hr = Unicode2Ansi(_pszMsg, &szBuf);
  167. if(FAILED(hr))
  168. goto Exit;
  169. bRet = WriteFile(hFile, szBuf, strlen(szBuf), &dwWritten, NULL);
  170. if (!bRet) {
  171. hr = HRESULT_FROM_WIN32(GetLastError());
  172. goto Exit;
  173. }
  174. Exit:
  175. SAFEDELETEARRAY(szBuf);
  176. return hr;
  177. }
  178. //
  179. // CDebugLog Class
  180. //
  181. HRESULT CDebugLog::Create(IApplicationContext *pAppCtx, LPCWSTR pwzAsmName,
  182. CDebugLog **ppdl)
  183. {
  184. HRESULT hr = S_OK;
  185. CDebugLog *pdl = NULL;
  186. *ppdl = NULL;
  187. pdl = NEW(CDebugLog);
  188. if (!pdl) {
  189. hr = E_OUTOFMEMORY;
  190. goto Exit;
  191. }
  192. hr = pdl->Init(pAppCtx, pwzAsmName);
  193. if (FAILED(hr)) {
  194. delete pdl;
  195. pdl = NULL;
  196. goto Exit;
  197. }
  198. *ppdl = pdl;
  199. Exit:
  200. return hr;
  201. }
  202. CDebugLog::CDebugLog()
  203. : _pwzAsmName(NULL)
  204. , _cRef(1)
  205. , _bLogToWininet(TRUE)
  206. , _dwNumEntries(0)
  207. , _hr(S_OK)
  208. , _wzEXEName(NULL)
  209. , _bWroteDetails(FALSE)
  210. {
  211. _szLogPath[0] = L'\0';
  212. InitializeCriticalSection(&_cs);
  213. GetExePath();
  214. }
  215. CDebugLog::~CDebugLog()
  216. {
  217. LISTNODE pos = NULL;
  218. CDebugLogElement *pLogElem = NULL;
  219. pos = _listDbgMsg.GetHeadPosition();
  220. while (pos) {
  221. pLogElem = _listDbgMsg.GetNext(pos);
  222. SAFEDELETE(pLogElem);
  223. }
  224. _listDbgMsg.RemoveAll();
  225. SAFEDELETEARRAY(_pwzAsmName);
  226. SAFEDELETEARRAY(_wzEXEName);
  227. DeleteCriticalSection(&_cs);
  228. }
  229. HRESULT CDebugLog::Init(IApplicationContext *pAppCtx, LPCWSTR pwzAsmName)
  230. {
  231. HRESULT hr = S_OK;
  232. BOOL bIsHosted = FALSE;
  233. DWORD dwSize;
  234. DWORD dwType;
  235. DWORD lResult;
  236. DWORD dwAttr;
  237. HKEY hkey;
  238. LPWSTR wzAppName = NULL;
  239. LPWSTR wzEXEName = NULL;
  240. hr = _sDLType.Assign(DLTYPE_DEFAULT);
  241. if (wzAppName && lstrlenW(wzAppName)) {
  242. _wzEXEName = WSTRDupDynamic(wzAppName);
  243. if (!_wzEXEName) {
  244. hr = E_OUTOFMEMORY;
  245. goto Exit;
  246. }
  247. }
  248. else {
  249. LPWSTR wzFileName;
  250. // Didn't find EXE name in appctx. Use the .EXE name.
  251. wzFileName = PathFindFileName(g_wzEXEPath);
  252. ASSERT(wzFileName);
  253. hr = _sAppName.Assign(wzFileName);
  254. _wzEXEName = WSTRDupDynamic(wzFileName);
  255. if (!_wzEXEName) {
  256. hr = E_OUTOFMEMORY;
  257. goto Exit;
  258. }
  259. }
  260. // Log path
  261. lResult = RegOpenKeyEx(HKEY_CURRENT_USER, REG_KEY_FUSION_SETTINGS, 0, KEY_READ, &hkey);
  262. if (lResult == ERROR_SUCCESS) {
  263. dwSize = MAX_PATH;
  264. lResult = RegQueryValueEx(hkey, REG_VAL_FUSION_LOG_PATH, NULL,
  265. &dwType, (LPBYTE)_szLogPath, &dwSize);
  266. if (lResult == ERROR_SUCCESS) {
  267. PathRemoveBackslashW(_szLogPath);
  268. }
  269. else {
  270. _szLogPath[0] = L'\0';
  271. }
  272. RegCloseKey(hkey);
  273. dwAttr = GetFileAttributesW(_szLogPath);
  274. if (dwAttr != -1 && (dwAttr & FILE_ATTRIBUTE_DIRECTORY)) {
  275. _bLogToWininet = FALSE;
  276. }
  277. }
  278. /*
  279. bIsHosted = IsHosted();
  280. if (bIsHosted && !lstrlenW(_szLogPath)) {
  281. BOOL bRet;
  282. WCHAR wzCorSystemDir[MAX_PATH];
  283. WCHAR wzXSPAppCacheDir[MAX_PATH];
  284. if (!GetCorSystemDirectory(wzCorSystemDir)) {
  285. hr = HRESULT_FROM_WIN32(GetLastError());
  286. goto Exit;
  287. }
  288. PathRemoveBackslash(wzCorSystemDir);
  289. wnsprintfW(wzXSPAppCacheDir, MAX_PATH, L"%ws\\%ws", wzCorSystemDir,
  290. XSP_APP_CACHE_DIR);
  291. dwAttr = GetFileAttributes(wzXSPAppCacheDir);
  292. if (dwAttr == -1) {
  293. bRet = CreateDirectory(wzXSPAppCacheDir, NULL);
  294. if (!bRet) {
  295. hr = HRESULT_FROM_WIN32(GetLastError());
  296. goto Exit;
  297. }
  298. }
  299. wnsprintfW(_szLogPath, MAX_PATH, L"%ws\\%ws", wzXSPAppCacheDir, XSP_FUSION_LOG_DIR);
  300. dwAttr = GetFileAttributes(_szLogPath);
  301. if (dwAttr == -1) {
  302. bRet = CreateDirectory(_szLogPath, NULL);
  303. if (!bRet) {
  304. hr = HRESULT_FROM_WIN32(GetLastError());
  305. goto Exit;
  306. }
  307. }
  308. _bLogToWininet = FALSE;
  309. }
  310. */
  311. Exit:
  312. SAFEDELETEARRAY(wzAppName);
  313. return hr;
  314. }
  315. HRESULT CDebugLog::SetAsmName(LPCWSTR pwzAsmName)
  316. {
  317. HRESULT hr = S_OK;
  318. int iLen;
  319. if (_pwzAsmName) {
  320. // You can only set the name once.
  321. hr = S_FALSE;
  322. goto Exit;
  323. }
  324. if (!pwzAsmName) {
  325. hr = E_INVALIDARG;
  326. goto Exit;
  327. }
  328. iLen = lstrlenW(pwzAsmName) + 1;
  329. _pwzAsmName = NEW(WCHAR[iLen]);
  330. if (!_pwzAsmName) {
  331. hr = E_OUTOFMEMORY;
  332. goto Exit;
  333. }
  334. lstrcpyW(_pwzAsmName, pwzAsmName);
  335. Exit:
  336. return hr;
  337. }
  338. HRESULT CDebugLog::SetDownloadType(DWORD dwFlags)
  339. {
  340. HRESULT hr = S_OK;
  341. int iLen;
  342. if(dwFlags & DOWNLOAD_FLAGS_PROGRESS_UI)
  343. IF_FAILED_EXIT(_sDLType.Assign(DLTYPE_FOREGROUND));
  344. else
  345. IF_FAILED_EXIT(_sDLType.Assign(DLTYPE_BACKGROUND));
  346. exit:
  347. return hr;
  348. }
  349. HRESULT CDebugLog::SetAppName(LPCWSTR pwzAppName)
  350. {
  351. HRESULT hr = S_OK;
  352. int iLen;
  353. ASSERT(pwzAppName);
  354. IF_FAILED_EXIT(_sAppName.Assign(pwzAppName));
  355. exit:
  356. return hr;
  357. }
  358. //
  359. // IUnknown
  360. //
  361. STDMETHODIMP CDebugLog::QueryInterface(REFIID riid, void **ppv)
  362. {
  363. HRESULT hr = E_FAIL;
  364. /*
  365. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IFusionBindLog)) {
  366. *ppv = static_cast<IFusionBindLog *>(this);
  367. }
  368. else {
  369. *ppv = NULL;
  370. hr = E_NOINTERFACE;
  371. }
  372. if (*ppv) {
  373. AddRef();
  374. }
  375. */
  376. return hr;
  377. }
  378. STDMETHODIMP_(ULONG) CDebugLog::AddRef()
  379. {
  380. return InterlockedIncrement(&_cRef);
  381. }
  382. STDMETHODIMP_(ULONG) CDebugLog::Release()
  383. {
  384. ULONG ulRef;
  385. ulRef = InterlockedDecrement(&_cRef);
  386. if (ulRef == 0) {
  387. delete this;
  388. }
  389. return ulRef;
  390. }
  391. //
  392. // IFusionBindLog
  393. //
  394. STDMETHODIMP CDebugLog::GetResultCode()
  395. {
  396. return _hr;
  397. }
  398. HRESULT CDebugLog::GetLoggedMsgs(DWORD dwDetailLevel, CString& sLogMsgs )
  399. {
  400. HRESULT hr = S_OK;
  401. MAKE_ERROR_MACROS_STATIC(hr);
  402. BOOL bHaveMsgs = FALSE;
  403. LISTNODE pos = NULL;
  404. CDebugLogElement *pLogElem = NULL;
  405. pos = _listDbgMsg.GetHeadPosition();
  406. while (pos) {
  407. pLogElem = _listDbgMsg.GetNext(pos);
  408. ASSERT(pLogElem);
  409. if (pLogElem->_dwDetailLvl <= dwDetailLevel) {
  410. IF_FAILED_EXIT(sLogMsgs.Append(pLogElem->_pszMsg));
  411. IF_FAILED_EXIT(sLogMsgs.Append( L"\r\n"));
  412. bHaveMsgs = TRUE;
  413. }
  414. }
  415. if(bHaveMsgs == FALSE)
  416. hr = S_FALSE;
  417. exit:
  418. return hr;
  419. }
  420. STDMETHODIMP CDebugLog::GetBindLog(DWORD dwDetailLevel, LPWSTR pwzDebugLog,
  421. DWORD *pcbDebugLog)
  422. {
  423. HRESULT hr = S_OK;
  424. LISTNODE pos = NULL;
  425. DWORD dwCharsReqd;
  426. CDebugLogElement *pLogElem = NULL;
  427. if (!pcbDebugLog) {
  428. hr = E_INVALIDARG;
  429. goto Exit;
  430. }
  431. pos = _listDbgMsg.GetHeadPosition();
  432. if (!pos) {
  433. // No entries in debug log!
  434. hr = S_FALSE;
  435. goto Exit;
  436. }
  437. // Calculate total size (entries + new line chars + NULL)
  438. dwCharsReqd = 0;
  439. while (pos) {
  440. pLogElem = _listDbgMsg.GetNext(pos);
  441. ASSERT(pLogElem);
  442. if (pLogElem->_dwDetailLvl <= dwDetailLevel) {
  443. dwCharsReqd += lstrlenW(pLogElem->_pszMsg) * sizeof(WCHAR);
  444. dwCharsReqd += sizeof(L"\r\n");
  445. }
  446. }
  447. dwCharsReqd += 1; // NULL char
  448. if (!pwzDebugLog || *pcbDebugLog < dwCharsReqd) {
  449. *pcbDebugLog = dwCharsReqd;
  450. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  451. goto Exit;
  452. }
  453. *pwzDebugLog = L'\0';
  454. pos = _listDbgMsg.GetHeadPosition();
  455. while (pos) {
  456. pLogElem = _listDbgMsg.GetNext(pos);
  457. ASSERT(pLogElem);
  458. if (pLogElem->_dwDetailLvl <= dwDetailLevel) {
  459. StrCatW(pwzDebugLog, pLogElem->_pszMsg);
  460. StrCatW(pwzDebugLog, L"\r\n");
  461. }
  462. }
  463. ASSERT((DWORD)lstrlenW(pwzDebugLog) * sizeof(WCHAR) < dwCharsReqd);
  464. Exit:
  465. return hr;
  466. }
  467. //
  468. // CDebugLog helpers
  469. //
  470. HRESULT CDebugLog::SetResultCode(HRESULT hr)
  471. {
  472. _hr = hr;
  473. return S_OK;
  474. }
  475. HRESULT CDebugLog::DebugOut(DWORD dwDetailLvl, LPWSTR pwzFormatString, ...)
  476. {
  477. HRESULT hr = S_OK;
  478. va_list args;
  479. LPWSTR wzFormatString = NULL;
  480. LPWSTR wzDebugStr = NULL;
  481. /*
  482. wzFormatString = NEW(WCHAR[MAX_DBG_STR_LEN]);
  483. if (!wzFormatString) {
  484. hr = E_OUTOFMEMORY;
  485. goto Exit;
  486. }
  487. */
  488. wzDebugStr = NEW(WCHAR[MAX_DBG_STR_LEN]);
  489. if (!wzDebugStr) {
  490. hr = E_OUTOFMEMORY;
  491. goto Exit;
  492. }
  493. /*
  494. wzFormatString[0] = L'\0';
  495. if (!WszLoadString(g_hInst, dwResId, wzFormatString, MAX_DBG_STR_LEN)) {
  496. hr = HRESULT_FROM_WIN32(GetLastError());
  497. goto Exit;
  498. }
  499. */
  500. va_start(args, pwzFormatString);
  501. wvnsprintfW(wzDebugStr, MAX_DBG_STR_LEN, pwzFormatString, args);
  502. va_end(args);
  503. hr = LogMessage(dwDetailLvl, wzDebugStr, FALSE);
  504. if (FAILED(hr)) {
  505. goto Exit;
  506. }
  507. Exit:
  508. SAFEDELETEARRAY(wzDebugStr);
  509. SAFEDELETEARRAY(wzFormatString);
  510. return hr;
  511. }
  512. HRESULT CDebugLog::LogMessage(DWORD dwDetailLvl, LPCWSTR wzDebugStr, BOOL bPrepend)
  513. {
  514. HRESULT hr = S_OK;
  515. CDebugLogElement *pLogElem = NULL;
  516. hr = CDebugLogElement::Create(dwDetailLvl, wzDebugStr, &pLogElem);
  517. if (FAILED(hr)) {
  518. goto Exit;
  519. }
  520. _dwNumEntries += 1;
  521. if (bPrepend) {
  522. _listDbgMsg.AddHead(pLogElem);
  523. }
  524. else {
  525. _listDbgMsg.AddTail(pLogElem);
  526. }
  527. Exit:
  528. return hr;
  529. }
  530. HRESULT CDebugLog::DumpDebugLog(DWORD dwDetailLvl, HRESULT hrLog)
  531. {
  532. HRESULT hr = S_OK;
  533. HANDLE hFile = INVALID_HANDLE_VALUE;
  534. LISTNODE pos = NULL;
  535. LPWSTR wzUrlName=NULL;
  536. CDebugLogElement *pLogElem = NULL;
  537. WCHAR *wzExtension = L"HTM";
  538. WCHAR wzFileName[MAX_PATH];
  539. WCHAR wzSiteName[MAX_PATH];
  540. WCHAR wzAppLogDir[MAX_PATH];
  541. LPWSTR wzEXEName = NULL;
  542. LPWSTR wzResourceName = NULL;
  543. FILETIME ftTime;
  544. FILETIME ftExpireTime;
  545. DWORD dwBytes;
  546. DWORD dwSize;
  547. BOOL bRet;
  548. // CCriticalSection cs(&_cs);
  549. /*
  550. if (!g_dwLogFailures && !g_dwForceLog) {
  551. return S_FALSE;
  552. }
  553. */
  554. /*
  555. hr = cs.Lock();
  556. if (FAILED(hr)) {
  557. return hr;
  558. }
  559. */
  560. pos = _listDbgMsg.GetHeadPosition();
  561. if (!pos) {
  562. hr = S_FALSE;
  563. goto Exit;
  564. }
  565. wzUrlName = NEW(WCHAR[MAX_URL_LENGTH+1]);
  566. if (!wzUrlName)
  567. {
  568. hr = E_OUTOFMEMORY;
  569. goto Exit;
  570. }
  571. // Build the log entry URL and Wininet cache file
  572. wnsprintfW(wzUrlName, MAX_URL_LENGTH, L"?ClickOnceErrorLog!exe=%ws!name=%ws", _sAppName._pwz, _sDLType._pwz);
  573. if( dwDetailLvl == -1)
  574. {
  575. dwDetailLvl = g_dwLoggingLevel;
  576. }
  577. if (_bLogToWininet) {
  578. // Replace all characters > 0x80 with '?'
  579. dwSize = lstrlenW(wzUrlName);
  580. for (unsigned i = 0; i < dwSize; i++) {
  581. if (wzUrlName[i] > 0x80) {
  582. wzUrlName[i] = L'?';
  583. }
  584. }
  585. bRet = CreateUrlCacheEntryW(wzUrlName, 0, wzExtension, wzFileName, 0);
  586. if (!bRet) {
  587. goto Exit;
  588. }
  589. }
  590. else {
  591. wnsprintfW(wzAppLogDir, MAX_PATH, L"%ws\\%ws", _szLogPath, _wzEXEName);
  592. if (GetFileAttributes(wzAppLogDir) == -1) {
  593. BOOL bRet;
  594. bRet = CreateDirectory(wzAppLogDir, NULL);
  595. if (!bRet) {
  596. hr = HRESULT_FROM_WIN32(GetLastError());
  597. goto Exit;
  598. }
  599. }
  600. if (PathIsURLW(_pwzAsmName)) {
  601. // This was a where-ref bind. We can't spit out a filename w/
  602. // the URL of the bind because the URL has invalid filename chars.
  603. // The best we can do is show that it was a where-ref bind, and
  604. // give the filename, and maybe the site.
  605. dwSize = MAX_PATH;
  606. hr = UrlGetPartW(_pwzAsmName, wzSiteName, &dwSize, URL_PART_HOSTNAME, 0);
  607. if (FAILED(hr)) {
  608. goto Exit;
  609. }
  610. wzResourceName = PathFindFileName(_pwzAsmName);
  611. ASSERT(wzResourceName);
  612. if (!lstrlenW(wzSiteName)) {
  613. lstrcpyW(wzSiteName, L"LocalMachine");
  614. }
  615. wnsprintfW(wzFileName, MAX_PATH, L"%ws\\FusionBindError!exe=%ws!name=WhereRefBind!Host=(%ws)!FileName=(%ws).HTM",
  616. wzAppLogDir, _wzEXEName, wzSiteName, wzResourceName);
  617. }
  618. else {
  619. wnsprintfW(wzFileName, MAX_PATH, L"%ws\\FusionBindError!exe=%ws!name=%ws.HTM", wzAppLogDir, _wzEXEName, _pwzAsmName);
  620. }
  621. }
  622. // Create the and write the log file
  623. hr = CreateLogFile(&hFile, wzFileName, _wzEXEName, hrLog);
  624. if (FAILED(hr)) {
  625. goto Exit;
  626. }
  627. pos = _listDbgMsg.GetHeadPosition();
  628. while (pos) {
  629. pLogElem = _listDbgMsg.GetNext(pos);
  630. ASSERT(pLogElem);
  631. if (pLogElem->_dwDetailLvl <= dwDetailLvl) {
  632. pLogElem->Dump(hFile);
  633. WriteFile(hFile, DEBUG_LOG_NEW_LINE, lstrlenW(DEBUG_LOG_NEW_LINE) * sizeof(WCHAR),
  634. &dwBytes, NULL);
  635. }
  636. }
  637. // Close the log file and commit the wininet cache entry
  638. hr = CloseLogFile(&hFile);
  639. if (FAILED(hr)) {
  640. goto Exit;
  641. }
  642. if (_bLogToWininet) {
  643. GetSystemTimeAsFileTime(&ftTime);
  644. ftExpireTime.dwLowDateTime = (DWORD)0;
  645. ftExpireTime.dwHighDateTime = (DWORD)0;
  646. bRet = CommitUrlCacheEntryW(wzUrlName, wzFileName, ftExpireTime, ftTime,
  647. NORMAL_CACHE_ENTRY, NULL, 0, NULL, 0);
  648. if (!bRet) {
  649. hr = FusionpHresultFromLastError();
  650. goto Exit;
  651. }
  652. }
  653. Exit:
  654. // cs.Unlock();
  655. SAFEDELETEARRAY(wzUrlName);
  656. return hr;
  657. }
  658. HRESULT CDebugLog::CloseLogFile(HANDLE *phFile)
  659. {
  660. HRESULT hr = S_OK;
  661. DWORD dwBytes;
  662. if (!phFile) {
  663. hr = E_INVALIDARG;
  664. goto Exit;
  665. }
  666. WriteFile(*phFile, DEBUG_LOG_HTML_END, lstrlenW(DEBUG_LOG_HTML_END) * sizeof(WCHAR),
  667. &dwBytes, NULL);
  668. CloseHandle(*phFile);
  669. *phFile = INVALID_HANDLE_VALUE;
  670. Exit:
  671. return hr;
  672. }
  673. HRESULT CDebugLog::CreateLogFile(HANDLE *phFile, LPCWSTR wzFileName,
  674. LPCWSTR wzEXEName, HRESULT hrLog)
  675. {
  676. HRESULT hr = S_OK;
  677. SYSTEMTIME systime;
  678. LPWSTR pwzFormatMessage = NULL;
  679. DWORD dwFMResult = 0;
  680. LPWSTR wzBuffer = NULL;
  681. LPWSTR wzBuf = NULL;
  682. LPWSTR wzResultText = NULL;
  683. WCHAR wzDateBuffer[MAX_DATE_LEN];
  684. WCHAR wzTimeBuffer[MAX_DATE_LEN];
  685. if (!phFile || !wzFileName || !wzEXEName) {
  686. hr = E_INVALIDARG;
  687. goto Exit;
  688. }
  689. wzBuffer = NEW(WCHAR[MAX_DBG_STR_LEN]);
  690. if (!wzBuffer) {
  691. hr = E_OUTOFMEMORY;
  692. goto Exit;
  693. }
  694. wzBuf = NEW(WCHAR[MAX_DBG_STR_LEN]);
  695. if (!wzBuffer) {
  696. hr = E_OUTOFMEMORY;
  697. goto Exit;
  698. }
  699. wzResultText = NEW(WCHAR[MAX_DBG_STR_LEN]);
  700. if (!wzResultText) {
  701. hr = E_OUTOFMEMORY;
  702. goto Exit;
  703. }
  704. *phFile = CreateFile(wzFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  705. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  706. if (*phFile == INVALID_HANDLE_VALUE) {
  707. hr = HRESULT_FROM_WIN32(GetLastError());
  708. goto Exit;
  709. }
  710. if (!_bWroteDetails) {
  711. // Details
  712. LogMessage(0, ID_COL_DETAILED_LOG, TRUE);
  713. // Executable path
  714. wnsprintfW(wzBuffer, MAX_DBG_STR_LEN, L"%ws %ws", ID_COL_EXECUTABLE, g_wzEXEPath);
  715. LogMessage(0, wzBuffer, TRUE);
  716. dwFMResult = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  717. FORMAT_MESSAGE_FROM_SYSTEM, 0, hrLog, 0,
  718. (LPWSTR)&pwzFormatMessage, 0, NULL);
  719. if (dwFMResult) {
  720. wnsprintfW(wzBuffer, MAX_DBG_STR_LEN, ID_COL_FINAL_HR, hrLog, pwzFormatMessage);
  721. }
  722. else {
  723. WCHAR wzNoDescription[MAX_DBG_STR_LEN] = L" ";
  724. wnsprintfW(wzBuffer, MAX_DBG_STR_LEN, ID_COL_FINAL_HR, hrLog, wzNoDescription);
  725. }
  726. LogMessage(0, wzBuffer, TRUE);
  727. // Header text
  728. GetLocalTime(&systime);
  729. if (!GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &systime, NULL, wzDateBuffer, MAX_DATE_LEN)) {
  730. hr = HRESULT_FROM_WIN32(GetLastError());
  731. goto Exit;
  732. }
  733. if (!GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &systime, NULL, wzTimeBuffer, MAX_DATE_LEN)) {
  734. hr = HRESULT_FROM_WIN32(GetLastError());
  735. goto Exit;
  736. }
  737. wnsprintfW(wzBuffer, MAX_DBG_STR_LEN, L"%ws (%ws @ %ws) *** (Version=%ws)\n", ID_COL_HEADER_TEXT, wzDateBuffer, wzTimeBuffer, VER_PRODUCTVERSION_STR_L);
  738. LogMessage(0, wzBuffer, TRUE);
  739. // HTML start/end
  740. LogMessage(0, DEBUG_LOG_HTML_START, TRUE);
  741. LogMessage(0, DEBUG_LOG_HTML_META_LANGUAGE, TRUE);
  742. _bWroteDetails = TRUE;
  743. }
  744. Exit:
  745. if (pwzFormatMessage) {
  746. LocalFree(pwzFormatMessage);
  747. }
  748. SAFEDELETEARRAY(wzBuffer);
  749. SAFEDELETEARRAY(wzBuf);
  750. SAFEDELETEARRAY(wzResultText);
  751. return hr;
  752. }