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.

2523 lines
61 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. crdb.cpp
  5. Abstract:
  6. Handles database queries for crash buckets
  7. Environment:
  8. User Mode.
  9. --*/
  10. #include "precomp.h"
  11. #define STRSAFE_NO_DEPRECATE
  12. #include <strsafe.h>
  13. #include <shlwapi.h>
  14. #include <fcntl.h>
  15. #include <io.h>
  16. #include <stdio.h>
  17. #include "ocamon.h"
  18. #define LvlDatabaseInitDone 1
  19. #define LvlCrashAddedToDB 2
  20. #define LvlCustomerDbUpdate 4
  21. #define LvlMessageQReply 8
  22. LPOLESTR g_lpwszGetAll = L"SELECT * from CrashInstances";
  23. LPOLESTR g_lpwszCrashInstanceTable = L"CrashInstances";
  24. LPOLESTR g_lpwszBucketTable = L"BucketToInt";
  25. LPOLESTR g_lpwszBucketMapTable = L"BucketToCrash";
  26. LPOLESTR g_lpwszMachineInfoTable = L"MachineDescription";
  27. LPOLESTR g_lpwszOverClkTable = L"OverClocked";
  28. LPOLESTR g_lpwszSolutionsTable = L"SolutionMap";
  29. LPOLESTR g_lpwszRaidTable = L"RaidBugs";
  30. LPSTR g_lpszBaseUrl = "https://oca.microsoft.com/secure/response.asp?";
  31. CrashDatabaseHandler *g_CrDb = NULL;
  32. CustDatabaseHandler *g_CustDb = NULL;
  33. SolutionDatabaseHandler *g_SolDb = NULL;
  34. BOOL g_ComInitialized = FALSE;
  35. static bool fResetFilter = false;
  36. void
  37. ansi2wchr(
  38. const PCHAR astr,
  39. PWCHAR wstr
  40. );
  41. HRESULT
  42. ExtDllInitDynamicCalls(
  43. PDEBUG_CONTROL3 DebugControl
  44. )
  45. //
  46. // Load Ole32 and OleAut32 dlls
  47. //
  48. {
  49. HRESULT Hr;
  50. ULONG EngineOptions;
  51. if ((Hr = DebugControl->GetEngineOptions(&EngineOptions)) == S_OK)
  52. {
  53. if (EngineOptions & DEBUG_ENGOPT_DISALLOW_NETWORK_PATHS)
  54. {
  55. // Do not use ole32 APIs when we disallow network paths
  56. return E_FAIL;
  57. }
  58. if ((Hr = InitDynamicCalls(&g_Ole32CallsDesc)) != S_OK)
  59. {
  60. return Hr;
  61. }
  62. if ((Hr = InitDynamicCalls(&g_OleAut32CallsDesc)) != S_OK)
  63. {
  64. return Hr;
  65. }
  66. if ((Hr = InitDynamicCalls(&g_ShlWapiCallsDesc)) != S_OK)
  67. {
  68. return Hr;
  69. }
  70. return S_OK;
  71. }
  72. return Hr;
  73. }
  74. void BuildCrashId(ULONG UpTime, ULONG CrashTime, PULONG64 pCID)
  75. {
  76. ULONG64 u64 = CrashTime;
  77. *pCID = (u64 << 32) + UpTime;
  78. }
  79. #ifdef _NEED_EVENT_LOGS_
  80. LPCSTR c_szEventLogKey = "System\\CurrentControlSet\\Services\\EventLog\\Application";
  81. LPCSTR c_szEventLogSource = "OcaDbAddCrash";
  82. LPCSTR c_szEventLogMsgFile = "EventMessageFile";
  83. LPCSTR c_szEventLogTypes = "TypesSupported";
  84. HRESULT
  85. SetupEventLogging(
  86. void
  87. )
  88. {
  89. HKEY hEvLog = NULL;
  90. HKEY hEvLogSource = NULL;
  91. LONG err = ERROR_SUCCESS;
  92. CHAR AppName[MAX_PATH];
  93. if ((err = RegOpenKey(HKEY_LOCAL_MACHINE,
  94. c_szEventLogKey, &hEvLog)) != ERROR_SUCCESS)
  95. {
  96. return HRESULT_FROM_WIN32( err );
  97. }
  98. if ((err = RegOpenKey(hEvLog, c_szEventLogSource,
  99. &hEvLogSource)) != ERROR_SUCCESS)
  100. {
  101. DWORD AllowTypes;
  102. //
  103. // OCA logging hasn't been registered on this system yet
  104. // try to setup the registry values for logging
  105. //
  106. err = RegCreateKey(hEvLog, c_szEventLogSource, &hEvLogSource);
  107. if (err != ERROR_SUCCESS)
  108. {
  109. goto Exit;
  110. }
  111. if (!GetModuleFileName(NULL, AppName, sizeof(AppName)))
  112. {
  113. err = GetLastError();
  114. goto Exit;
  115. } else
  116. {
  117. PSTR FileName = strrchr(AppName, '\\');
  118. if (FileName)
  119. {
  120. StringCbCopy(FileName+1, sizeof(AppName) - strlen(FileName), "winext\\ext.dll");
  121. }
  122. }
  123. if ((err = RegSetValueEx(hEvLogSource, c_szEventLogMsgFile, 0,
  124. REG_SZ, (BYTE *) AppName,
  125. strlen(AppName)+1)) != ERROR_SUCCESS)
  126. {
  127. goto Exit;
  128. }
  129. AllowTypes = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
  130. if ((err = RegSetValueEx(hEvLogSource, c_szEventLogTypes, 0,
  131. REG_DWORD, (BYTE *) &AllowTypes,
  132. sizeof(AllowTypes))) != ERROR_SUCCESS)
  133. {
  134. goto Exit;
  135. }
  136. } else
  137. {
  138. //
  139. // Assume we have values set up propperly...
  140. //
  141. }
  142. Exit:
  143. if (hEvLog != NULL)
  144. {
  145. RegCloseKey(hEvLog);
  146. }
  147. if (hEvLogSource != NULL)
  148. {
  149. RegCloseKey(hEvLogSource);
  150. }
  151. return HRESULT_FROM_WIN32(err);
  152. }
  153. void
  154. DbAddCrashEventLog(
  155. HRESULT hrAddCrash,
  156. DWORD LevelFinished,
  157. PCRASH_INSTANCE Crash
  158. )
  159. {
  160. HANDLE hEventSrc;
  161. HRESULT Hr;
  162. CHAR LogBuffer[2048];
  163. if (FAILED(SetupEventLogging()))
  164. {
  165. return;
  166. }
  167. hEventSrc = RegisterEventSource(NULL, c_szEventLogSource);
  168. if (hEventSrc == NULL ||
  169. hEventSrc == INVALID_HANDLE_VALUE)
  170. {
  171. return;
  172. }
  173. Hr = StringCbPrintf(LogBuffer, sizeof(LogBuffer),
  174. "GUID: %s\n"
  175. "BUCKET: %s\n"
  176. "GENERIC_BUCKET: %s\n"
  177. "SOLUTION_ID: 0x%03lx\n"
  178. "SOLUTION_TYPE: %ld\n"
  179. "ARCHIVE_PATH: %s\n"
  180. "RESULT: 0x%08lx\n",
  181. Crash->MesgGuid,
  182. Crash->Bucket,
  183. Crash->DefaultBucket,
  184. Crash->SolutionId,
  185. Crash->SolutionType,
  186. Crash->Path,
  187. hrAddCrash);
  188. if (Hr == S_OK)
  189. {
  190. WORD wCategory = 0;
  191. LPCSTR pStringArr = LogBuffer;
  192. ReportEvent(hEventSrc,
  193. EVENTLOG_INFORMATION_TYPE,
  194. wCategory,
  195. FAILED(hrAddCrash) ? EXT_ADDCRASH_FAILED : EXT_CRASH_SOLVED,
  196. NULL,
  197. 1,
  198. 0,
  199. &pStringArr,
  200. NULL);
  201. }
  202. DeregisterEventSource(hEventSrc);
  203. }
  204. #endif // _NEED_EVENT_LOGS_
  205. void
  206. DbAddCrashReportToMonitor(
  207. HRESULT hrAddCrash,
  208. DWORD LevelFinished,
  209. PCRASH_INSTANCE Crash
  210. )
  211. {
  212. HANDLE hPipe;
  213. DWORD dwMode, cbWritten;
  214. OCAKD_MONITOR_MESSAGE Msg;
  215. OVERLAPPED WriteOverlapped;
  216. Msg.MessageId = OKD_MESSAGE_DEBUGGER_RESULT;
  217. Msg.u.KdResult.SizeOfStruct = sizeof(Msg.u.KdResult);
  218. Msg.u.KdResult.hrAddCrash = hrAddCrash;
  219. Msg.u.KdResult.SolutionId = Crash->SolutionId;
  220. Msg.u.KdResult.ResponseType = Crash->SolutionType;
  221. Msg.u.KdResult.CrashGuid[0] = 0;
  222. Msg.u.KdResult.BucketId[0] = 0;
  223. Msg.u.KdResult.ArchivePath[0] = 0;
  224. if (Crash->MesgGuid)
  225. {
  226. StringCbCopy(Msg.u.KdResult.CrashGuid, sizeof(Msg.u.KdResult.CrashGuid),
  227. Crash->MesgGuid);
  228. }
  229. if (Crash->Bucket)
  230. {
  231. StringCbCopy(Msg.u.KdResult.BucketId, sizeof(Msg.u.KdResult.BucketId),
  232. Crash->Bucket);
  233. }
  234. if (Crash->ArchiveFileName)
  235. {
  236. StringCbCopy(Msg.u.KdResult.ArchivePath, sizeof(Msg.u.KdResult.ArchivePath),
  237. Crash->ArchiveFileName);
  238. }
  239. for (;;)
  240. {
  241. hPipe = CreateFile(c_tszCollectPipeName, FILE_WRITE_DATA,
  242. 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
  243. NULL);
  244. if (hPipe != INVALID_HANDLE_VALUE)
  245. {
  246. break;
  247. }
  248. if (GetLastError() != ERROR_PIPE_BUSY)
  249. {
  250. return;
  251. }
  252. if (!WaitNamedPipe(c_tszCollectPipeName, 5*60*1000))
  253. {
  254. return;
  255. }
  256. }
  257. // We are now connected to pipe
  258. // Set the message mode on pipe
  259. /* dwMode = PIPE_READMODE_MESSAGE;
  260. if (!SetNamedPipeHandleState(hPipe, &dwMode,
  261. NULL, NULL))
  262. {
  263. CloseHandle(hPipe);
  264. return;
  265. }
  266. */
  267. WriteOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  268. if (WriteOverlapped.hEvent != NULL)
  269. {
  270. // Send crash information to monitor pipe
  271. if (!WriteFile(hPipe, (LPVOID) &Msg, sizeof(Msg),
  272. &cbWritten, &WriteOverlapped))
  273. {
  274. if (GetLastError() == ERROR_IO_PENDING ||
  275. !GetOverlappedResult(hPipe, &WriteOverlapped, &cbWritten,
  276. TRUE))
  277. {
  278. // failed to write, exit silently
  279. // Its up to monitor if it is keeping track of kds launched
  280. }
  281. }
  282. CloseHandle(WriteOverlapped.hEvent);
  283. }
  284. FlushFileBuffers(hPipe);
  285. CloseHandle(hPipe);
  286. return;
  287. }
  288. void
  289. OcaKdLog(
  290. LPSTR Qual,
  291. LPSTR szMesg1,
  292. LPSTR szMesg2,
  293. ULONG Err
  294. )
  295. {
  296. BOOL bOnce = FALSE;
  297. PSTR szLogFile;
  298. if (szLogFile = g_pTriager->GetFollowupStr("debugger-params",
  299. "dbfailurelog"))
  300. {
  301. int hLogFile;
  302. CHAR Log[300];
  303. hLogFile = _open(szLogFile, O_APPEND | O_CREAT | O_RDWR,
  304. S_IREAD | S_IWRITE);
  305. if (hLogFile != -1 &&
  306. StringCbPrintf(Log, sizeof(Log), "%15s: %0lx - %20s, %s\n",
  307. Qual, Err, szMesg1, szMesg2) == S_OK)
  308. {
  309. _write(hLogFile, Log, strlen(Log));
  310. _close(hLogFile);
  311. }
  312. }
  313. }
  314. BOOL
  315. OpenSysDataFileFromCab(
  316. CHAR *CabFile,
  317. HANDLE *FileHandle
  318. )
  319. {
  320. CHAR SysDataFile[2 * MAX_PATH];
  321. INT_PTR CabFh;
  322. HRESULT Status;
  323. Status = ExpandDumpCab(CabFile,
  324. _O_CREAT | _O_EXCL | _O_TEMPORARY,
  325. "sysdata.xml",
  326. SysDataFile, DIMA(SysDataFile),
  327. &CabFh);
  328. if (Status != S_OK)
  329. {
  330. goto exitSysDataFileOpen;
  331. }
  332. *FileHandle = CreateFile(SysDataFile, GENERIC_READ,
  333. FILE_SHARE_READ | FILE_SHARE_WRITE |
  334. FILE_SHARE_DELETE,
  335. NULL,
  336. OPEN_EXISTING,
  337. FILE_ATTRIBUTE_NORMAL,
  338. NULL);
  339. if (*FileHandle == NULL || *FileHandle == INVALID_HANDLE_VALUE)
  340. {
  341. Status = E_FAIL;
  342. }
  343. if (CabFh >= 0)
  344. {
  345. // no longer needed
  346. _close((int)CabFh);
  347. }
  348. exitSysDataFileOpen:
  349. return Status == S_OK;
  350. }
  351. ULONG
  352. ScanForId(
  353. PVOID pBuffer,
  354. ULONG64 Size
  355. )
  356. {
  357. const WCHAR cwszOEMIdTag[] = L"<HARDWAREID>PCI\\VEN_";
  358. PWCHAR Scan, Match, End;
  359. ULONG FreqId = 0;
  360. #define MAX_OEM_IDS 50
  361. struct {
  362. ULONG Id;
  363. ULONG Count;
  364. } FoundIds[MAX_OEM_IDS] = {0};
  365. Scan = (PWCHAR) pBuffer;
  366. End = (PWCHAR) ( ((PCHAR) pBuffer) + (ULONG_PTR) Size );
  367. while (Scan < End)
  368. {
  369. Match = (PWCHAR) &cwszOEMIdTag[0];
  370. while (*Scan++ == *Match++);
  371. if (!*Match)
  372. {
  373. --Scan;
  374. // Match the tag
  375. // <HARDWAREID>PCI\VEN_8086&amp;DEV_2532&amp;SUBSYS_00000000&amp;REV_02</HARDWAREID>
  376. // ^ Scan
  377. WCHAR Line[61], *Subsys;
  378. ULONG Id1 = 0, Id2 = 0;
  379. StringCbCopyNW(Line, sizeof(Line),Scan, sizeof(Line) - sizeof(WCHAR));
  380. swscanf(Line, L"%lx", &Id1);
  381. Subsys = wcsstr(Line, L"SUBSYS_");
  382. if (Subsys)
  383. {
  384. Subsys += 7;
  385. swscanf(Subsys, L"%lx", &Id2);
  386. Id2 &= 0xffff;
  387. if (Id2 != Id1 && Id2 != 0)
  388. {
  389. // We foud a oem Id, store it
  390. for (int i = 0; i<MAX_OEM_IDS; i++)
  391. {
  392. if (FoundIds[i].Id == Id2)
  393. {
  394. FoundIds[i].Count++;
  395. } else if (FoundIds[i].Id == 0)
  396. {
  397. FoundIds[i].Count = 1;
  398. FoundIds[i].Id = Id2;
  399. }
  400. }
  401. }
  402. }
  403. // dprintf("PCI\\VEN_%ws\n Id1 %lx Id2 %lx\n", Line, Id1, Id2);
  404. }
  405. }
  406. ULONG Count = 0;
  407. for (int i = 0; i<MAX_OEM_IDS; i++)
  408. {
  409. if (FoundIds[i].Count > Count)
  410. {
  411. FreqId = FoundIds[i].Id;
  412. }
  413. }
  414. // dprintf("Found %lx\n", FreqId);
  415. return FreqId;
  416. }
  417. ULONG
  418. GetOEMId(
  419. PCHAR szCabFile
  420. )
  421. {
  422. ULONG SizeLow, SizeHigh;
  423. HANDLE hSysDataFile = NULL, hMap = NULL;
  424. PVOID pFileMap = NULL;
  425. ULONG OEMId = 0;
  426. if (!OpenSysDataFileFromCab(szCabFile, &hSysDataFile))
  427. {
  428. goto exitGetOEMID;
  429. }
  430. SizeLow = GetFileSize(hSysDataFile, &SizeHigh);
  431. ULONG BytesRead;
  432. hMap = CreateFileMapping(hSysDataFile, NULL, PAGE_READONLY,
  433. 0, 0, NULL);
  434. if (hMap == NULL)
  435. {
  436. goto exitGetOEMID;
  437. }
  438. pFileMap = MapViewOfFile(hMap, FILE_MAP_READ,
  439. 0, 0, 0);
  440. if (!pFileMap)
  441. {
  442. goto exitGetOEMID;
  443. }
  444. OEMId = ScanForId(pFileMap, SizeLow + ((ULONG64)SizeHigh << 32));
  445. exitGetOEMID:
  446. if (pFileMap)
  447. {
  448. UnmapViewOfFile(pFileMap);
  449. }
  450. if (hMap)
  451. {
  452. CloseHandle(hMap);
  453. }
  454. if (hSysDataFile)
  455. {
  456. CloseHandle(hSysDataFile);
  457. }
  458. return OEMId;
  459. }
  460. CVar::CVar()
  461. {
  462. g_OleAut32Calls.VariantInit(this);
  463. }
  464. CVar::CVar(VARTYPE vt, SCODE scode)
  465. {
  466. g_OleAut32Calls.VariantInit(this);
  467. this->vt = vt;
  468. this->scode = scode;
  469. }
  470. CVar::CVar(VARIANT var)
  471. {
  472. *this = var;
  473. }
  474. CVar::~CVar()
  475. {
  476. g_OleAut32Calls.VariantClear(this);
  477. }
  478. // ASSIGNMENT OPS.
  479. CVar &
  480. CVar::operator=(PCWSTR pcwstr)
  481. {
  482. g_OleAut32Calls.VariantClear(this);
  483. if (NULL == (this->bstrVal = g_OleAut32Calls.SysAllocStringLen(pcwstr, wcslen(pcwstr))))
  484. throw E_OUTOFMEMORY;
  485. this->vt = VT_BSTR;
  486. return *this;
  487. }
  488. CVar &
  489. CVar::operator=(VARIANT var)
  490. {
  491. HRESULT hr;
  492. g_OleAut32Calls.VariantClear(this);
  493. if (FAILED(hr = g_OleAut32Calls.VariantCopy(this, &var)))
  494. throw hr;
  495. return *this;
  496. }
  497. // CAST OPS.
  498. // doesn't change type. only returns BSTR if variant is of type
  499. // bstr. asserts otherwise.
  500. CVar::operator BSTR() const
  501. {
  502. if(VT_BSTR == this->vt)
  503. return this->bstrVal;
  504. else
  505. return NULL;
  506. }
  507. HRESULT
  508. CVar::Clear()
  509. {
  510. return g_OleAut32Calls.VariantClear(this);
  511. }
  512. BOOL
  513. CCrashInstance::InitData(
  514. PCRASH_INSTANCE Crash
  515. )
  516. {
  517. SYSTEMTIME Systime;
  518. if (!Crash || !Crash->Build || !Crash->Bucket || !Crash->Path)
  519. {
  520. return FALSE;
  521. }
  522. if (strlen(Crash->Path) < sizeof(m_sz_Path))
  523. {
  524. CopyString(m_sz_Path, Crash->Path, sizeof(m_sz_Path));
  525. }
  526. else
  527. {
  528. return FALSE;
  529. }
  530. m_iBuild = Crash->Build;
  531. m_iCpuId = Crash->uCpu;
  532. BuildCrashId(Crash->UpTime, Crash->CrashTime, &m_CrashId);
  533. // GetSystemTime(&Systime);
  534. // m_Date = Systime.wYear
  535. m_lSourceStatus = 0;
  536. m_lBuildSatus = 0;
  537. m_lPathStatus = 0;
  538. m_lCrashIdStatus = 0;
  539. return TRUE;
  540. }
  541. void
  542. CCrashInstance::OutPut()
  543. {
  544. dprintf("%I64lx, %s\n",
  545. m_CrashId,
  546. m_sz_Path);
  547. dprintf("Build %ld, CPU Id %I64lx\n",
  548. m_iBuild,
  549. m_iCpuId);
  550. }
  551. BOOL
  552. CBucketMap::InitData(
  553. ULONG64 CrashId,
  554. PCHAR Bucket
  555. )
  556. {
  557. m_CrashId = CrashId;
  558. if (!Bucket)
  559. {
  560. return FALSE;
  561. }
  562. if (strlen(Bucket) < sizeof(m_sz_BucketId))
  563. {
  564. CopyString(m_sz_BucketId, Bucket, sizeof(m_sz_BucketId));
  565. }
  566. else
  567. {
  568. return FALSE;
  569. }
  570. return TRUE;
  571. }
  572. BOOL
  573. COverClocked::InitData(
  574. ULONG64 CrashId
  575. )
  576. {
  577. m_CrashId = CrashId;
  578. m_lCrashIdStatus = 0;
  579. return TRUE;
  580. }
  581. BOOL
  582. CMachineInfo::InitData(
  583. ULONG64 CpuId,
  584. PSTR Desc
  585. )
  586. {
  587. if (Desc && strlen(Desc) < sizeof(m_sz_Desc))
  588. {
  589. CopyString(m_sz_Desc, Desc, sizeof(m_sz_Desc));
  590. }
  591. else
  592. {
  593. m_sz_Desc[0] = 0;
  594. }
  595. m_iCpuId = CpuId;
  596. return TRUE;
  597. }
  598. void
  599. CBucketSolution::Output()
  600. {
  601. dprintf("Solution for bucket %s:\n%s\nFixed in %s\n",
  602. m_sz_BucketId,
  603. m_sz_SolText,
  604. m_sz_OSVersion);
  605. return;
  606. }
  607. HRESULT
  608. ArchiveCrash(
  609. PSTR OriginalPath,
  610. PSTR ShareName,
  611. PSTR DestFileName OPTIONAL,
  612. PSTR ArchivedPath,
  613. ULONG SizeofArchivedPath
  614. )
  615. //
  616. // Copy over crashfile to the share
  617. //
  618. {
  619. CHAR CopyTo[MAX_PATH], Date[20];
  620. PCHAR FileName;
  621. SYSTEMTIME Time;
  622. if (!OriginalPath || !ShareName)
  623. {
  624. dprintf("Invalid original dumppath or archive share\n");
  625. return E_FAIL;
  626. }
  627. GetLocalTime(&Time);
  628. StringCbPrintf(Date, sizeof(Date), "%02ld-%02ld-%04ld",
  629. Time.wMonth,
  630. Time.wDay,
  631. Time.wYear);
  632. StringCbCopy(CopyTo, sizeof(CopyTo), ShareName);
  633. StringCbCat(CopyTo, sizeof(CopyTo), "\\");
  634. StringCbCat(CopyTo, sizeof(CopyTo), Date);
  635. StringCbCat(CopyTo, sizeof(CopyTo), "\\");
  636. if (!g_ShlWapiCalls.PathIsDirectoryA(CopyTo))
  637. {
  638. CreateDirectory(CopyTo, NULL);
  639. }
  640. if (DestFileName != NULL && DestFileName[0] != '\0')
  641. {
  642. FileName = DestFileName;
  643. } else
  644. {
  645. FileName = strrchr(OriginalPath, '\\');
  646. if (!FileName)
  647. {
  648. dprintf("Bad filename in '%s'\n", OriginalPath);
  649. return E_FAIL;
  650. }
  651. }
  652. if (*FileName == '\\')
  653. {
  654. FileName++;
  655. }
  656. StringCbCat(CopyTo, sizeof(CopyTo), FileName);
  657. if (!CopyFile(OriginalPath, CopyTo, TRUE))
  658. {
  659. dprintf("Cannot Copy %s to %s\n", OriginalPath, CopyTo);
  660. return E_FAIL;
  661. }
  662. StringCchCopy(ArchivedPath, SizeofArchivedPath, CopyTo);
  663. return S_OK;
  664. }
  665. HRESULT
  666. MQNotifyCrashProcessed(
  667. PCRASH_INSTANCE Crash
  668. )
  669. {
  670. WCHAR wszGuid[50], wszMQConnectStr[100], wszMQMessage[2*MAX_PATH];
  671. typedef HRESULT (WINAPI* MQSENDMSGPROC)(LPWSTR, LPWSTR, LPWSTR);
  672. MQSENDMSGPROC SendMQMessageText;
  673. ULONG64 hMQExt = 0;
  674. HRESULT Hr;
  675. PSTR BaseUrl;
  676. HINSTANCE hMod;
  677. if (!(BaseUrl = g_pTriager->GetFollowupStr("debugger-params",
  678. "solutionurl")))
  679. {
  680. BaseUrl = g_lpszBaseUrl;
  681. }
  682. if (!Crash->MqConnectStr || !Crash->MesgGuid)
  683. {
  684. return E_INVALIDARG;
  685. }
  686. if ((StringCbPrintfW(wszGuid, sizeof(wszGuid), L"%S", Crash->MesgGuid) != S_OK) ||
  687. (StringCbPrintfW(wszMQConnectStr, sizeof(wszMQConnectStr), L"%S", Crash->MqConnectStr) != S_OK))
  688. {
  689. return E_FAIL;
  690. }
  691. if (Crash->SourceId == CiSrcCER ||
  692. Crash->SourceId == CiSrcStress)
  693. {
  694. Hr = StringCbPrintfW(wszMQMessage, sizeof(wszMQMessage),
  695. L"%Ssid=%ld&State=%ld&szSBucket=%S&iSBucket=%ld&szGBucket=%S&iGBucket=%ld&gsid=%ld",
  696. BaseUrl,
  697. (Crash->SolutionId ? Crash->SolutionId : -1),
  698. Crash->SolutionType != CiSolFixed && Crash->SolutionType != CiSolWorkaround,
  699. Crash->Bucket,
  700. Crash->iBucket,
  701. Crash->DefaultBucket,
  702. Crash->iDefaultBucket,
  703. (Crash->GenericSolId ? Crash->GenericSolId : -1)
  704. );
  705. } else
  706. {
  707. ULONG State, Solution;
  708. //
  709. // Set the tracking state for caller
  710. //
  711. if (Crash->SolutionType == CiSolFixed ||
  712. Crash->SolutionType == CiSolWorkaround)
  713. {
  714. State = 0;
  715. } else
  716. {
  717. State = 1;
  718. }
  719. Solution = Crash->SolutionId && (Crash->SolutionId != -1) ? Crash->SolutionId : Crash->GenericSolId;
  720. if (Solution)
  721. {
  722. Hr = StringCbPrintfW(wszMQMessage, sizeof(wszMQMessage),
  723. L"%Ssid=%ld&State=%ld",
  724. BaseUrl,
  725. Solution,
  726. State);
  727. }
  728. else
  729. {
  730. Hr = StringCbPrintfW(wszMQMessage, sizeof(wszMQMessage),
  731. L"NO_SOLUTION");
  732. }
  733. }
  734. hMod = LoadLibrary("winxp\\mqext.dll");
  735. if (hMod == NULL)
  736. {
  737. hMod = LoadLibrary("oca\\mqext.dll");
  738. if (hMod == NULL)
  739. {
  740. return HRESULT_FROM_WIN32(GetLastError());
  741. }
  742. }
  743. SendMQMessageText = (MQSENDMSGPROC) GetProcAddress(hMod, "_EFN_SendMQMessageText");
  744. if (SendMQMessageText != NULL)
  745. {
  746. Hr = SendMQMessageText(wszMQConnectStr, wszGuid, wszMQMessage);
  747. } else
  748. {
  749. Hr = HRESULT_FROM_WIN32(GetLastError());
  750. }
  751. FreeLibrary(hMod);
  752. return E_FAIL;
  753. }
  754. ULONG
  755. GetAdoCommandTimeOut()
  756. {
  757. #define DEFAULT_TIMEOUT 200
  758. PSTR String;
  759. ULONG TimeOut;
  760. TimeOut = 0;
  761. String = g_pTriager->GetFollowupStr("debugger-params", "DbCommandTimeout");
  762. if (String)
  763. {
  764. TimeOut = atoi(String);
  765. }
  766. if (!TimeOut)
  767. {
  768. TimeOut = DEFAULT_TIMEOUT;
  769. }
  770. return TimeOut;
  771. }
  772. ULONG
  773. GetAdoConnectionTimeOut()
  774. {
  775. #define DEFAULT_CONNECTION_TIMEOUT 5
  776. PSTR String;
  777. ULONG TimeOut;
  778. TimeOut = 0;
  779. String = g_pTriager->GetFollowupStr("debugger-params", "DbConnectionTimeout");
  780. if (String)
  781. {
  782. TimeOut = atoi(String);
  783. }
  784. if (!TimeOut)
  785. {
  786. TimeOut = DEFAULT_CONNECTION_TIMEOUT;
  787. }
  788. return TimeOut;
  789. }
  790. HRESULT
  791. InitializeDatabaseHandlers(
  792. PDEBUG_CONTROL3 DebugControl,
  793. ULONG Flags
  794. )
  795. {
  796. HRESULT Hr;
  797. ULONG EngineOptions;
  798. if (!ExtensionApis.lpOutputRoutine)
  799. {
  800. ExtensionApis.nSize = sizeof (ExtensionApis);
  801. if ((Hr = DebugControl->GetWindbgExtensionApis64(&ExtensionApis)) != S_OK) {
  802. return Hr;
  803. }
  804. }
  805. if ((Hr = ExtDllInitDynamicCalls(DebugControl)) != S_OK)
  806. {
  807. return Hr;
  808. }
  809. if (!g_pTriager)
  810. {
  811. g_pTriager = new CTriager();
  812. }
  813. if (!g_CrDb || !g_CustDb || !g_SolDb)
  814. {
  815. if (!g_ComInitialized)
  816. {
  817. if (FAILED(Hr = g_Ole32Calls.CoInitializeEx(NULL, COM_THREAD_MODEL)))
  818. {
  819. dprintf("CoInitialize failed %lx\n", Hr);
  820. return Hr;
  821. }
  822. g_ComInitialized = TRUE;
  823. }
  824. if (!g_CrDb && (Flags & 1))
  825. {
  826. g_CrDb = new CrashDatabaseHandler();
  827. if (!g_CrDb)
  828. {
  829. return E_OUTOFMEMORY;
  830. }
  831. }
  832. if (!g_CustDb && (Flags & 2))
  833. {
  834. g_CustDb = new CustDatabaseHandler();
  835. if (!g_CustDb)
  836. {
  837. return E_OUTOFMEMORY;
  838. }
  839. }
  840. if (!g_SolDb && (Flags & 4))
  841. {
  842. g_SolDb = new SolutionDatabaseHandler();
  843. if (!g_SolDb)
  844. {
  845. return E_OUTOFMEMORY;
  846. }
  847. }
  848. }
  849. if (g_CrDb && !g_CrDb->IsConnected() && (Flags & 1))
  850. {
  851. if (!g_CrDb->ConnectToDataBase())
  852. {
  853. return E_FAIL;
  854. }
  855. }
  856. if (g_CustDb && !g_CustDb->IsConnected() && (Flags & 2))
  857. {
  858. if (!g_CustDb->ConnectToDataBase())
  859. {
  860. return E_FAIL;
  861. }
  862. }
  863. if (g_SolDb && !g_SolDb->IsConnected() && (Flags & 4))
  864. {
  865. if (!g_SolDb->ConnectToDataBase())
  866. {
  867. return E_FAIL;
  868. }
  869. }
  870. return S_OK;
  871. }
  872. HRESULT
  873. UnInitializeDatabaseHandlers(
  874. BOOL bUninitCom
  875. )
  876. {
  877. if (g_CrDb)
  878. {
  879. delete g_CrDb;
  880. }
  881. if (g_CustDb)
  882. {
  883. delete g_CustDb;
  884. }
  885. if (g_SolDb)
  886. {
  887. delete g_SolDb;
  888. }
  889. g_CrDb = NULL;
  890. g_CustDb = NULL;
  891. g_SolDb = NULL;
  892. if (g_ComInitialized && bUninitCom)
  893. {
  894. g_Ole32Calls.CoUninitialize();
  895. g_ComInitialized = FALSE;
  896. }
  897. return S_OK;
  898. }
  899. HRESULT
  900. ReportSolution(
  901. PCRASH_INSTANCE Crash
  902. )
  903. {
  904. HRESULT Hr = S_OK;
  905. if (!Crash->SolutionId ||
  906. (Crash->SourceId == CiSrcCER && !Crash->GenericSolId))
  907. {
  908. // Get the solution, we need generic bucket solution for CER even if sBugcket is solved
  909. Hr = g_SolDb->CheckSolutionExists(Crash->Bucket, Crash->DefaultBucket,
  910. &Crash->SolutionId, (PULONG) &Crash->SolutionType,
  911. (PULONG) &Crash->GenericSolId,
  912. (Crash->SourceId == CiSrcCER) ? 1 : 0);
  913. if (FAILED(Hr) || !Crash->SolutionId)
  914. {
  915. Crash->SolutionId = -1;
  916. Crash->SolutionType = CiSolUnsolved;
  917. }
  918. }
  919. if (Crash->SolutionId != -1)
  920. {
  921. OcaKdLog(Crash->MesgGuid, "SOLVED", Crash->Bucket, Crash->SolutionId);
  922. } else
  923. {
  924. OcaKdLog(Crash->MesgGuid, "UNSOLVED", Crash->Bucket, Hr);
  925. }
  926. if (Crash->SourceId == CiSrcCER)
  927. {
  928. // get bucket ids
  929. }
  930. //
  931. // Check if we have info to connect to solution queue and a solution exists
  932. //
  933. // if (Crash->SolutionId)
  934. {
  935. if (Crash->MesgGuid && Crash->MqConnectStr &&
  936. Crash->MesgGuid[0] && Crash->MqConnectStr[0])
  937. {
  938. // Notify the sender that crash has been processed
  939. MQNotifyCrashProcessed(Crash);
  940. }
  941. }
  942. return S_OK;
  943. }
  944. HRESULT
  945. _EFN_DbAddCrashDirect(
  946. PCRASH_INSTANCE Crash,
  947. PDEBUG_CONTROL3 DebugControl
  948. )
  949. {
  950. ULONG LevelCompleted;
  951. HRESULT Hr=S_OK;
  952. ULONG SleepFor;
  953. LevelCompleted = 0;
  954. SleepFor = 0;
  955. ReTry:
  956. if (SleepFor > 5)
  957. {
  958. dprintf("Could not succeed after %ld tries, quitting.\n", SleepFor);
  959. DbAddCrashReportToMonitor(Hr, LevelCompleted, Crash);
  960. return Hr;
  961. }
  962. else if (SleepFor)
  963. {
  964. dprintf("Level Finished %lx, sleep for %ld sec before retry.\n", LevelCompleted, SleepFor);
  965. Sleep(SleepFor*1000);
  966. }
  967. if (!(LevelCompleted & LvlDatabaseInitDone))
  968. {
  969. ULONG Flags = 1;
  970. if (!Crash->bResetBucket)
  971. {
  972. if (!Crash->SolutionId ||
  973. (Crash->SourceId == CiSrcCER &&
  974. Crash->GenericSolId == 0))
  975. {
  976. Flags |= 4;
  977. }
  978. }
  979. if (Crash->bUpdateCustomer)
  980. {
  981. Flags |= 2;
  982. }
  983. if ((Hr = InitializeDatabaseHandlers(DebugControl, Flags)) != S_OK)
  984. {
  985. dprintf("Initializtion error.\n");
  986. ++SleepFor;
  987. goto ReTry;
  988. }
  989. LevelCompleted |= LvlDatabaseInitDone;
  990. }
  991. while (!(LevelCompleted & LvlMessageQReply) ||
  992. !(LevelCompleted & LvlCrashAddedToDB))
  993. {
  994. if (!(LevelCompleted & LvlMessageQReply) &&
  995. ((Crash->SourceId != CiSrcCER) || (LevelCompleted & LvlCrashAddedToDB)))
  996. // For CER we need ibuckets to report solution
  997. {
  998. if (!Crash->bResetBucket)
  999. {
  1000. ReportSolution(Crash); // Ignore return value, we fail quietly if there is
  1001. // any problem in reporting solution to Q
  1002. }
  1003. LevelCompleted |= LvlMessageQReply;
  1004. }
  1005. if (!(LevelCompleted & LvlCrashAddedToDB))
  1006. {
  1007. Hr = g_CrDb->AddCrashInstance(Crash);
  1008. if (FAILED(Hr))
  1009. {
  1010. ++SleepFor;
  1011. goto ReTry;
  1012. }
  1013. LevelCompleted |= LvlCrashAddedToDB;
  1014. }
  1015. if (Crash->SourceId == CiSrcCER && Crash->iBucket == 0)
  1016. {
  1017. g_CrDb->LookupCrashBucket(Crash->Bucket, &Crash->iBucket,
  1018. Crash->DefaultBucket, &Crash->iDefaultBucket);
  1019. }
  1020. }
  1021. //
  1022. // Only update the customer DB for kernel mode failures as the user
  1023. // mode failures don't go in that DB.
  1024. //
  1025. if (!(LevelCompleted & LvlCustomerDbUpdate))
  1026. {
  1027. if (Crash->bUpdateCustomer &&
  1028. (Crash->FailureType == DEBUG_FLR_KERNEL))
  1029. {
  1030. if (Crash->iBucket && Crash->iDefaultBucket)
  1031. {
  1032. Hr = g_CustDb->AddCrashToDB(Crash);
  1033. if (FAILED(Hr))
  1034. {
  1035. ++SleepFor;
  1036. goto ReTry;
  1037. }
  1038. }
  1039. else
  1040. {
  1041. dprintf("Cannot retrieve bucket Ids\n");
  1042. Hr = E_FAIL;
  1043. }
  1044. }
  1045. LevelCompleted |= LvlCustomerDbUpdate;
  1046. }
  1047. DbAddCrashReportToMonitor(Hr, LevelCompleted, Crash);
  1048. return Hr;
  1049. }
  1050. //
  1051. // DatabaseHandler Methods
  1052. //
  1053. DatabaseHandler::DatabaseHandler()
  1054. {
  1055. m_piConnection = NULL;
  1056. m_piCrRecordSet = NULL;
  1057. m_fConnected = FALSE;
  1058. m_fRecordsetEmpty = TRUE;
  1059. m_pADOResult = NULL;
  1060. m_fPrintIt = FALSE;
  1061. m_piCrCommandObj = NULL;
  1062. }
  1063. DatabaseHandler::~DatabaseHandler()
  1064. {
  1065. if (m_piCrRecordSet != NULL)
  1066. {
  1067. m_piCrRecordSet->Release();
  1068. }
  1069. if (m_piCrCommandObj != NULL)
  1070. {
  1071. m_piCrCommandObj->Release();
  1072. }
  1073. if (m_piConnection != NULL)
  1074. {
  1075. if (m_fConnected)
  1076. {
  1077. m_piConnection->Close();
  1078. m_fConnected = FALSE;
  1079. }
  1080. m_piConnection->Release();
  1081. }
  1082. m_piCrRecordSet = NULL;
  1083. m_piConnection = NULL;
  1084. }
  1085. BOOL
  1086. DatabaseHandler::ConnectToDataBase(
  1087. LPSTR szDB
  1088. )
  1089. {
  1090. HRESULT Hr = S_OK;
  1091. WCHAR szConnectStr[200];
  1092. PSTR String;
  1093. String = g_pTriager->GetFollowupStr("debugger-params", szDB);
  1094. if (!String)
  1095. {
  1096. return FALSE;
  1097. }
  1098. // bstrConnect = (PCRDB_ADOBSTR) &szConnectStr[0];
  1099. // bstrConnect->dwLength = sizeof(szConnectStr)/sizeof(WCHAR) - sizeof(DWORD);
  1100. ansi2wchr(String, szConnectStr);
  1101. CVar vNull(VT_ERROR, DISP_E_PARAMNOTFOUND);
  1102. CVar bstrConnect(VT_ERROR, DISP_E_PARAMNOTFOUND);
  1103. __try
  1104. {
  1105. if ((Hr = g_Ole32Calls.CoCreateInstance(CLSID_CADOConnection,
  1106. NULL,
  1107. CLSCTX_INPROC_SERVER,
  1108. IID_IADOConnection,
  1109. (LPVOID *)&m_piConnection)) != S_OK)
  1110. {
  1111. dprintf("CoCreate failed for connection %lx\n", Hr);
  1112. return FALSE;
  1113. }
  1114. m_piConnection->put_ConnectionTimeout(GetAdoConnectionTimeOut());
  1115. bstrConnect = szConnectStr;
  1116. if (bstrConnect == NULL)
  1117. {
  1118. return FALSE;
  1119. }
  1120. if ((Hr = m_piConnection->put_ConnectionString((BSTR)bstrConnect)) != S_OK)
  1121. {
  1122. dprintf("put_ConnectionString ( %ws ) failed %lx\n", szConnectStr, Hr);
  1123. return FALSE;
  1124. }
  1125. if ((Hr = m_piConnection->Open(NULL,
  1126. NULL, NULL,
  1127. adConnectUnspecified)) != S_OK)
  1128. {
  1129. dprintf("Debugger %s Connection::Open failed %lx\n\n", m_szDbName, Hr);
  1130. return FALSE;
  1131. }
  1132. m_fConnected = TRUE;
  1133. // Set command timeout to 60, crashdatabase is huge and commands
  1134. // takte long time
  1135. m_piConnection->put_CommandTimeout(GetAdoCommandTimeOut());
  1136. if ((Hr = g_Ole32Calls.CoCreateInstance(CLSID_CADORecordset,
  1137. NULL,
  1138. CLSCTX_INPROC_SERVER,
  1139. IID_IADORecordset,
  1140. (LPVOID *)&m_piCrRecordSet)) != S_OK )
  1141. {
  1142. dprintf("CoCreate failed for recordset %lx\n", Hr);
  1143. return FALSE;
  1144. }
  1145. if ((Hr = m_piCrRecordSet->putref_ActiveConnection(m_piConnection)) != S_OK)
  1146. {
  1147. dprintf("putref_ActiveConn failed %lx\n", Hr);
  1148. return FALSE;
  1149. }
  1150. if ((Hr = g_Ole32Calls.CoCreateInstance(CLSID_CADOCommand,
  1151. NULL,
  1152. CLSCTX_INPROC_SERVER,
  1153. IID_IADOCommand15,
  1154. (LPVOID *)&m_piCrCommandObj)) != S_OK )
  1155. {
  1156. dprintf("CoCreate failed for Command %lx\n", Hr);
  1157. return FALSE;
  1158. }
  1159. if ((Hr = m_piCrCommandObj->putref_ActiveConnection(m_piConnection)) != S_OK)
  1160. {
  1161. dprintf("putref_ActiveConn failed %lx\n", Hr);
  1162. return FALSE;
  1163. }
  1164. }
  1165. __except (Hr)
  1166. {
  1167. dprintf("Unhandled exception %lx\n", Hr);
  1168. return (FALSE);
  1169. }
  1170. return TRUE;
  1171. }
  1172. HRESULT
  1173. DatabaseHandler::GetRecords(
  1174. PULONG Count,
  1175. BOOL bEnumerateAll
  1176. )
  1177. {
  1178. HRESULT hr;
  1179. CVar vSource(VT_ERROR, DISP_E_PARAMNOTFOUND);
  1180. CVar vNull(VT_ERROR, DISP_E_PARAMNOTFOUND);
  1181. LONG State;
  1182. // dprintf("Executing %ws\n", m_wszQueryCommand);
  1183. if (!m_fConnected || !m_wszQueryCommand[0])
  1184. {
  1185. dprintf("Not connected\n");
  1186. return E_FAIL;
  1187. }
  1188. __try
  1189. {
  1190. vSource = m_wszQueryCommand;
  1191. if (m_piCrRecordSet == NULL)
  1192. {
  1193. if ((hr = g_Ole32Calls.CoCreateInstance(CLSID_CADORecordset,
  1194. NULL,
  1195. CLSCTX_INPROC_SERVER,
  1196. IID_IADORecordset,
  1197. (LPVOID *)&m_piCrRecordSet)) != S_OK )
  1198. {
  1199. dprintf("CoCreate failed for recordset %lx\n", hr);
  1200. return hr;
  1201. }
  1202. if ((hr = m_piCrRecordSet->putref_ActiveConnection(m_piConnection)) != S_OK)
  1203. {
  1204. dprintf("putref_ActiveConn failed %lx\n", hr);
  1205. goto Cleanup;
  1206. }
  1207. }
  1208. if ((hr = m_piCrRecordSet->Open(vSource, vNull, adOpenKeyset, adLockReadOnly, adCmdText)) != S_OK)
  1209. {
  1210. if (m_fPrintIt)
  1211. {
  1212. dprintf("RecordSet::Open Failed %lx, \n %ws \n", hr, m_wszQueryCommand);
  1213. }
  1214. goto Cleanup;
  1215. }
  1216. if (Count)
  1217. {
  1218. ADO_LONGPTR MaxRec;
  1219. if ((hr = m_piCrRecordSet->get_RecordCount(&MaxRec)) != S_OK)
  1220. {
  1221. *Count = 0;
  1222. hr = S_FALSE;
  1223. }
  1224. *Count = (ULONG) MaxRec;
  1225. }
  1226. if (bEnumerateAll)
  1227. {
  1228. if ((hr = EnumerateAllRows()) != S_OK)
  1229. {
  1230. // dprintf("Cannot enumerate rows %lx\n", hr);
  1231. }
  1232. }
  1233. }
  1234. __except (hr)
  1235. {
  1236. dprintf("Unhandled Exception in GetRecordForFollowup %lx\n", hr);
  1237. return hr;
  1238. }
  1239. Cleanup:
  1240. State = -1;
  1241. m_piCrRecordSet->get_State(&State);
  1242. if (State & 1)
  1243. {
  1244. m_piCrRecordSet->Close();
  1245. }
  1246. m_piCrRecordSet->Release();
  1247. m_piCrRecordSet = NULL;
  1248. return hr;
  1249. }
  1250. HRESULT
  1251. DatabaseHandler::EnumerateAllRows(
  1252. void
  1253. )
  1254. {
  1255. VARIANT avarRecords;
  1256. HRESULT Hr;
  1257. ADO_LONGPTR MaxRec;
  1258. ULONG Count=0;
  1259. CHAR Text[100];
  1260. CVar vNull(VT_ERROR, DISP_E_PARAMNOTFOUND);
  1261. IADORecordBinding *picRs = NULL;
  1262. COutputQueryRecords *QueryResult;
  1263. CCrashInstance CrashInstance;
  1264. if (m_pADOResult)
  1265. {
  1266. QueryResult = m_pADOResult;
  1267. } else
  1268. {
  1269. QueryResult = &CrashInstance;
  1270. }
  1271. __try
  1272. {
  1273. ULONG lUbound;
  1274. LONG State = -1;
  1275. if ((Hr = m_piCrRecordSet->get_RecordCount(&MaxRec)) != S_OK)
  1276. {
  1277. Hr = S_FALSE;
  1278. }
  1279. Count = (ULONG) MaxRec;
  1280. if (m_fPrintIt)
  1281. {
  1282. // dprintf("Enumerating %lx rows\n", MaxRec);
  1283. }
  1284. picRs = NULL;
  1285. m_piCrRecordSet->get_State(&State);
  1286. if ((Hr = m_piCrRecordSet->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&picRs)) != S_OK)
  1287. {
  1288. dprintf("RecordSet::QueryInterface (IADORecordBinding) Failed %lx, State %lx\n", Hr, State);
  1289. return Hr;
  1290. }
  1291. //Bind the Recordset
  1292. if ((Hr = picRs->BindToRecordset(QueryResult)) != S_OK)
  1293. {
  1294. dprintf("RecordSet::BindToRecordset (IADORecordBinding) Failed %lx, State %lx\n", Hr, State);
  1295. picRs->Release();
  1296. return Hr;
  1297. }
  1298. while (1)
  1299. {
  1300. VARIANT_BOOL IsEof;
  1301. if (m_piCrRecordSet->get_EOF(&IsEof) == S_OK)
  1302. {
  1303. if (IsEof)
  1304. {
  1305. // preserve last valut for the caller
  1306. m_piCrRecordSet->MovePrevious();
  1307. break;
  1308. }
  1309. }
  1310. if (m_pADOResult && m_fPrintIt)
  1311. {
  1312. m_pADOResult->Output();
  1313. } else
  1314. {
  1315. // CrashInstance.OutPut();
  1316. }
  1317. --Count;
  1318. if (m_piCrRecordSet->MoveNext() != S_OK)
  1319. {
  1320. break;
  1321. }
  1322. }
  1323. if (picRs)
  1324. {
  1325. picRs->Release();
  1326. }
  1327. }
  1328. __except (Hr)
  1329. {
  1330. dprintf("Unhandled Exception in EnumerateAllRows %lx\n", Hr);
  1331. return Hr;
  1332. }
  1333. return S_OK;
  1334. }
  1335. //
  1336. // CrashDatabaseHandler Methods
  1337. //
  1338. CrashDatabaseHandler::CrashDatabaseHandler()
  1339. {
  1340. m_szDbName = "CrashDb";
  1341. }
  1342. CrashDatabaseHandler::~CrashDatabaseHandler()
  1343. {
  1344. }
  1345. HRESULT
  1346. CrashDatabaseHandler::BuildQueryForCrashInstance(
  1347. PCRASH_INSTANCE Crash
  1348. )
  1349. {
  1350. ULONG64 CrashId;
  1351. BuildCrashId(Crash->UpTime, Crash->CrashTime, &CrashId);
  1352. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1353. L"SELECT * FROM %ws WHERE CrashId = %I64ld",
  1354. g_lpwszCrashInstanceTable,
  1355. CrashId
  1356. );
  1357. return S_OK;
  1358. }
  1359. BOOL
  1360. CrashDatabaseHandler::CheckCrashExists(
  1361. PCRASH_INSTANCE Crash
  1362. )
  1363. {
  1364. ULONG nRecords = 0;
  1365. CCheckCrashExists Exists;
  1366. Exists.m_CrashIdExists = 0;
  1367. m_pADOResult = &Exists;
  1368. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1369. L"sp_CheckCrashExists '%S'",
  1370. Crash->MesgGuid);
  1371. HRESULT Hr = GetRecords(&nRecords, TRUE);
  1372. m_pADOResult = NULL;
  1373. if (FAILED(Hr) || !Exists.m_CrashIdExists)
  1374. {
  1375. return FALSE;
  1376. }
  1377. return TRUE;
  1378. }
  1379. BOOL
  1380. CrashDatabaseHandler::CheckSRExists(
  1381. PSTR szSR,
  1382. PCRASH_INSTANCE Crash
  1383. )
  1384. {
  1385. ULONG nRecords = 0;
  1386. CIntValue Exists;
  1387. Exists.m_dw_Value1 = 0;
  1388. m_pADOResult = &Exists;
  1389. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1390. L"sp_CheckSRExists '%S'",
  1391. szSR);
  1392. HRESULT Hr = GetRecords(&nRecords, TRUE);
  1393. m_pADOResult = NULL;
  1394. if (FAILED(Hr) || !Exists.m_dw_Value1)
  1395. {
  1396. return FALSE;
  1397. }
  1398. return TRUE;
  1399. }
  1400. HRESULT
  1401. CrashDatabaseHandler::LinkCrashToSR(
  1402. PSTR szSR,
  1403. PCRASH_INSTANCE Crash
  1404. )
  1405. {
  1406. HRESULT Hr;
  1407. ULONG nRecords = 0;
  1408. CIntValue lnk;
  1409. lnk.m_dw_Value1 = 0;
  1410. m_pADOResult = &lnk;
  1411. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1412. L"sp_LinkCrashSR '%S', '%S'",
  1413. szSR,
  1414. Crash->MesgGuid);
  1415. Hr = GetRecords(&nRecords, TRUE);
  1416. m_pADOResult = NULL;
  1417. if (!lnk.m_dw_Value1)
  1418. {
  1419. return E_FAIL;
  1420. }
  1421. return Hr;
  1422. }
  1423. HRESULT
  1424. CrashDatabaseHandler::FindSRBuckets(
  1425. PSTR szSR,
  1426. PSTR szSBucket,
  1427. ULONG sBucketSize,
  1428. PSTR szGBucket,
  1429. ULONG gBucketSize
  1430. )
  1431. {
  1432. HRESULT Hr;
  1433. ULONG nRecords = 0;
  1434. CRetriveBucket Buckets;
  1435. Buckets.m_sz_gBucketId[0] = Buckets.m_sz_sBucketId[0] = 0;
  1436. m_pADOResult = &Buckets;
  1437. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1438. L"sp_RetriveSRBuckets '%S'",
  1439. szSR);
  1440. Hr = GetRecords(&nRecords, TRUE);
  1441. m_pADOResult = NULL;
  1442. if (FAILED(Hr) || !Buckets.m_sz_gBucketId[0])
  1443. {
  1444. return Hr;
  1445. }
  1446. StringCchCopy(szSBucket, sBucketSize, Buckets.m_sz_sBucketId);
  1447. StringCchCopy(szGBucket, gBucketSize, Buckets.m_sz_gBucketId);
  1448. return Hr;
  1449. }
  1450. HRESULT
  1451. CrashDatabaseHandler::GetBucketComments(
  1452. PSTR szBuckt,
  1453. PSTR szComments,
  1454. ULONG SizeofComment,
  1455. PULONG pBugId
  1456. )
  1457. {
  1458. HRESULT Hr;
  1459. ULONG nRecords = 0;
  1460. CBugAndComment Comments;
  1461. Comments.m_dw_BugId = 0;
  1462. Comments.m_sz_CommentBy[0] = Comments.m_sz_Comments[0] = 0;
  1463. m_pADOResult = &Comments;
  1464. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1465. L"sp_GetBucketComments '%S'",
  1466. szBuckt);
  1467. Hr = GetRecords(&nRecords, TRUE);
  1468. m_pADOResult = NULL;
  1469. if (FAILED(Hr))
  1470. {
  1471. return Hr;
  1472. }
  1473. if (Comments.m_dw_BugId == 0 &&
  1474. Comments.m_sz_Comments[0] == 0)
  1475. {
  1476. return E_FAIL;
  1477. }
  1478. StringCchCopy(szComments, SizeofComment, Comments.m_sz_Comments);
  1479. *pBugId = Comments.m_dw_BugId;
  1480. return Hr;
  1481. }
  1482. HRESULT
  1483. CrashDatabaseHandler::AddCrashInstance(
  1484. PCRASH_INSTANCE Crash
  1485. )
  1486. {
  1487. HRESULT Hr = S_OK;
  1488. PSTR OriginalPath = Crash->Path;
  1489. if (!Crash->bResetBucket &&
  1490. (Crash->SolutionId != 0) &&
  1491. (Crash->iBucket != -1) &&
  1492. (Crash->SolutionType == CiSolFixed))
  1493. {
  1494. //
  1495. // No need to add this to CrashDB, just update the count
  1496. //
  1497. Crash->bExpendableDump = TRUE;
  1498. Hr = UpdateBucketCount(Crash);
  1499. } else
  1500. {
  1501. PSTR ArchiveShare, ArchParam;
  1502. ULONG index;
  1503. CHAR ArchivePath[MAX_PATH];
  1504. ArchParam = ArchivePath;
  1505. StringCchPrintf(ArchParam, MAX_PATH, "archshare-k-%s",
  1506. (Crash->DumpClass == DEBUG_DUMP_SMALL) ? "mini" : "full");
  1507. ArchiveShare = g_pTriager->GetFollowupStr("debugger-params", ArchParam);
  1508. ArchivePath[0] = 0;
  1509. if ((Crash->bExpendableDump) || Crash->bResetBucket ||
  1510. ((Hr = ArchiveCrash(Crash->Path, ArchiveShare, Crash->ArchiveFileName,
  1511. ArchivePath, sizeof(ArchivePath))) == S_OK))
  1512. {
  1513. if (!Crash->bExpendableDump && !Crash->bResetBucket)
  1514. {
  1515. Crash->Path = ArchivePath;
  1516. Crash->OEMId = GetOEMId(OriginalPath);
  1517. }
  1518. Crash->bExpendableDump = TRUE;
  1519. Hr = AddCrashToDBByStoreProc(Crash);
  1520. Crash->Path = OriginalPath;
  1521. if (SUCCEEDED(Hr) && Crash->PssSr && Crash->PssSr[0])
  1522. {
  1523. Hr = LinkCrashToSR(Crash->PssSr, Crash);
  1524. OcaKdLog(Crash->MesgGuid, "CRASH SR", Crash->PssSr, Hr);
  1525. }
  1526. } else
  1527. {
  1528. dprintf("ArchiveCrash failed with %lx\n", Hr);
  1529. }
  1530. OcaKdLog(Crash->MesgGuid, "ARCHIVED CRASH", ArchivePath, Hr);
  1531. }
  1532. if (OriginalPath && SUCCEEDED(Hr) &&
  1533. (Crash->SourceId != CiSrcErClient) &&
  1534. (Crash->SourceId != CiSrcUser) &&
  1535. !Crash->bResetBucket)
  1536. {
  1537. DeleteFile(OriginalPath);
  1538. }
  1539. return Hr;
  1540. }
  1541. HRESULT
  1542. CrashDatabaseHandler::AddCrashToDBByStoreProc(
  1543. PCRASH_INSTANCE Crash
  1544. )
  1545. {
  1546. HRESULT Hr;
  1547. CVar vNull(VT_ERROR, DISP_E_PARAMNOTFOUND);
  1548. CIntValue IntValue;
  1549. ULONG sBucket, gBucket;
  1550. Hr = S_OK;
  1551. if (Crash->SourceId == CiSrcManualFullDump)
  1552. {
  1553. // we already have a FailureType field to show full dumps
  1554. Crash->SourceId = CiSrcManual;
  1555. }
  1556. Crash->ServicePack %= 10000;
  1557. dprintf("ADDING CRASH:\n");
  1558. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1559. L"EXEC sp_AddCrashInstance2 "
  1560. L" @ip_retriageBucket = %ld, "
  1561. L" @ip_Bucketid = '%S', "
  1562. L" @ip_Path = '%S', "
  1563. L" @ip_FollowUp = '%S', "
  1564. L" @ip_BuildNo = %ld, "
  1565. L" @ip_Source = %ld, "
  1566. L" @ip_CpuId = %I64ld, "
  1567. L" @ip_OverClocked = %ld, "
  1568. L" @ip_Guid = '%S', "
  1569. L" @ip_gBucketId = '%S', "
  1570. L" @ip_DriverName = '%S', "
  1571. L" @ip_Type = %ld, "
  1572. L" @ip_UpTime = %ld, "
  1573. L" @ip_SKU = %ld,"
  1574. L" @ip_LangId = 0,"
  1575. L" @ip_OemId = %ld\n",
  1576. Crash->bResetBucket,
  1577. Crash->Bucket,
  1578. Crash->Path,
  1579. Crash->Followup,
  1580. Crash->Build * 10000 + Crash->ServicePack,
  1581. Crash->SourceId,
  1582. Crash->uCpu,
  1583. Crash->OverClocked,
  1584. Crash->MesgGuid,
  1585. Crash->DefaultBucket,
  1586. Crash->FaultyDriver,
  1587. Crash->FailureType | ((Crash->DumpClass == DEBUG_DUMP_SMALL) ? 0 : 4),
  1588. Crash->UpTime,
  1589. Crash->Sku,
  1590. Crash->OEMId
  1591. );
  1592. m_pADOResult = &IntValue;
  1593. __try
  1594. {
  1595. // Build query for store proc
  1596. // LATER: modify this to use adStoreProc Interface instead of query
  1597. ULONG nRecords;
  1598. IntValue.m_dw_Value1 = 0;
  1599. m_fPrintIt = TRUE;
  1600. if (!strcmp(Crash->Bucket, "BAD_DUMPFILE"))
  1601. {
  1602. sBucket = gBucket = -1;
  1603. }
  1604. else
  1605. {
  1606. sBucket = gBucket = 0;
  1607. // This proc returns sBucket and gBucket on success
  1608. // CALL FindBucketId directly to get those
  1609. dprintf("%ws", m_wszQueryCommand);
  1610. Hr = FindBucketId(&sBucket, &gBucket);
  1611. dprintf("%d %d \n", sBucket, gBucket);
  1612. m_fPrintIt = FALSE;
  1613. if (FAILED(Hr))
  1614. {
  1615. dprintf("GerRecord Failed %lx for store proc AddCrashToDBByStoreProc \n", Hr);
  1616. dprintf("Query:\n%ws\n", m_wszQueryCommand);
  1617. return Hr;
  1618. }
  1619. if (!CheckCrashExists(Crash))
  1620. {
  1621. dprintf("Crash could not be added to crash database: %s\n", Crash->MesgGuid);
  1622. Hr = E_FAIL;
  1623. }
  1624. else
  1625. {
  1626. dprintf("Crash instance %s now exists in DB\n", Crash->MesgGuid);
  1627. }
  1628. // Get Integer mappings for buckets
  1629. if (!sBucket || !gBucket)
  1630. {
  1631. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1632. L"sp_GetIntBucket '%S', '%S'",
  1633. Crash->Bucket, Crash->DefaultBucket);
  1634. //
  1635. // Now Try finding with explicit query
  1636. //
  1637. FindBucketId(&sBucket, &gBucket);
  1638. if (!sBucket || !gBucket)
  1639. {
  1640. dprintf("Unable to retrive int bucketids from crashdb\n");
  1641. Hr = E_FAIL;
  1642. }
  1643. }
  1644. }
  1645. Crash->iBucket = sBucket;
  1646. Crash->iDefaultBucket = gBucket;
  1647. }
  1648. __except (Hr)
  1649. {
  1650. dprintf("Unhandled Exception in AddCrashToDB %lx\n", Hr);
  1651. return Hr;
  1652. }
  1653. return Hr;
  1654. }
  1655. HRESULT
  1656. CrashDatabaseHandler::UpdateBucketCount(
  1657. PCRASH_INSTANCE Crash
  1658. )
  1659. {
  1660. HRESULT Hr;
  1661. ULONG sBucket, Count;
  1662. CIntValue RetVal;
  1663. dprintf("Update Bucket Count:\n");
  1664. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1665. L"EXEC sp_UpdateCount '%S', %ld",
  1666. Crash->Bucket,
  1667. Crash->Build * 10000 + Crash->ServicePack
  1668. );
  1669. __try
  1670. {
  1671. // Build query for store proc
  1672. // LATER: modify this to use adStoreProc Interface instead of query
  1673. ULONG nRecords;
  1674. // This proc returns sBucket and gBucket on success
  1675. // CALL FindBucketId directly to get those
  1676. dprintf("%ws", m_wszQueryCommand);
  1677. m_pADOResult = &RetVal;
  1678. Hr = GetRecords(&Count, FALSE);
  1679. m_pADOResult = NULL;
  1680. dprintf("sp_UpdateCount returned %d \n", RetVal.m_dw_Value1);
  1681. }
  1682. __except (Hr)
  1683. {
  1684. dprintf("Unhandled Exception in UpdateBucketCount %lx\n", Hr);
  1685. return Hr;
  1686. }
  1687. return Hr;
  1688. }
  1689. HRESULT
  1690. CrashDatabaseHandler::FindRaidBug(
  1691. PSTR Bucket,
  1692. PULONG RaidBug
  1693. )
  1694. {
  1695. WCHAR wszBkt[100];
  1696. CBucketRaid BktRaid;
  1697. ULONG Count=0;
  1698. HRESULT result;
  1699. if (Bucket && strlen(Bucket) < sizeof(wszBkt)/sizeof(WCHAR))
  1700. {
  1701. ansi2wchr(Bucket, wszBkt);
  1702. }
  1703. StringCchPrintfW(m_wszQueryCommand,
  1704. sizeof(m_wszQueryCommand)/sizeof(WCHAR),
  1705. L"SELECT BucketId, BugId from %ws b, %ws r "
  1706. L" WHERE BucketId='%ws' AND b.iBucket = r.iBucket",
  1707. g_lpwszBucketTable,
  1708. g_lpwszRaidTable,
  1709. wszBkt);
  1710. m_pADOResult = &BktRaid;
  1711. result = GetRecords(&Count, TRUE);
  1712. if (Count == 0)
  1713. {
  1714. result = S_FALSE;
  1715. }
  1716. if (result == S_OK)
  1717. {
  1718. *RaidBug = BktRaid.m_dw_Raid;
  1719. }
  1720. m_pADOResult = NULL;
  1721. return result;
  1722. }
  1723. HRESULT
  1724. CrashDatabaseHandler::FindBucketId(
  1725. PULONG isBucket,
  1726. PULONG igBucket
  1727. )
  1728. {
  1729. CGetIntBucket BktIds;
  1730. CBuckets Bkt;
  1731. ULONG Count=0;
  1732. HRESULT result;
  1733. BktIds.m_iBucket1 = BktIds.m_iBucket2 = 0;
  1734. m_pADOResult = &BktIds;
  1735. result = GetRecords(&Count, TRUE);
  1736. if (result == S_OK)
  1737. {
  1738. //
  1739. // BUGBUG - what is this supposed to check ?
  1740. //
  1741. if (Count == 0)
  1742. {
  1743. result = S_FALSE;
  1744. }
  1745. *isBucket = BktIds.m_iBucket1;
  1746. *igBucket = BktIds.m_iBucket2;
  1747. }
  1748. //dprintf("%ws : %ld, %ld\n", m_wszQueryCommand, *isBucket, *igBucket);
  1749. m_pADOResult = NULL;
  1750. return result;
  1751. }
  1752. HRESULT
  1753. CrashDatabaseHandler::LookupCrashBucket(
  1754. PSTR SBucket,
  1755. PULONG iSBucket,
  1756. PSTR GBucket,
  1757. PULONG iGBucket
  1758. )
  1759. {
  1760. HRESULT Hr = S_OK;
  1761. ULONG Dummy;
  1762. if (!m_fConnected)
  1763. {
  1764. return E_FAIL;
  1765. }
  1766. Hr = StringCchPrintfW(m_wszQueryCommand,
  1767. sizeof(m_wszQueryCommand)/sizeof(WCHAR),
  1768. L"sp_GetIntBucket '%S', '%S'",
  1769. SBucket, GBucket ? GBucket : "");
  1770. if (Hr == S_OK)
  1771. {
  1772. Hr = FindBucketId(iSBucket, iGBucket ? iGBucket : &Dummy);
  1773. }
  1774. return Hr;
  1775. }
  1776. //
  1777. // CustDatabaseHandler Methods
  1778. //
  1779. CustDatabaseHandler::CustDatabaseHandler()
  1780. {
  1781. m_szDbName = "CustomerDb";
  1782. }
  1783. CustDatabaseHandler::~CustDatabaseHandler()
  1784. {
  1785. }
  1786. HRESULT
  1787. CustDatabaseHandler::AddCrashToDB(
  1788. PCRASH_INSTANCE Crash
  1789. )
  1790. {
  1791. if (!m_fConnected)
  1792. {
  1793. return E_FAIL;
  1794. }
  1795. HRESULT Hr = S_OK;
  1796. CVar vNull(VT_ERROR, DISP_E_PARAMNOTFOUND);
  1797. PCHAR CallSp;
  1798. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1799. L"SetDBGResults '%S', %ld, '%S', %ld, '%S', %ld, %ld, '%S'",
  1800. Crash->MesgGuid,
  1801. Crash->iDefaultBucket,
  1802. Crash->DefaultBucket,
  1803. Crash->iBucket,
  1804. Crash->Bucket,
  1805. Crash->StopCode,
  1806. Crash->bSendMail ? 1 : 0,
  1807. Crash->OriginalDumpFileName);
  1808. ULONG nRecords;
  1809. CIntValue ReturnVal;
  1810. ReturnVal.m_dw_Value1 = 0;
  1811. m_fPrintIt = TRUE;
  1812. m_pADOResult = &ReturnVal;
  1813. Hr = GetRecords(&nRecords, TRUE);
  1814. m_fPrintIt = FALSE;
  1815. dprintf("Query:\n%ws\n", m_wszQueryCommand);
  1816. if ((Hr == S_OK) && (ReturnVal.m_dw_Value1 == 0))
  1817. {
  1818. Hr = E_FAIL;
  1819. }
  1820. m_pADOResult = NULL;
  1821. if (FAILED(Hr))
  1822. {
  1823. dprintf("GerRecord Failed %lx for store proc SetDBGResults on AddToCustomerDb \n", Hr);
  1824. } else
  1825. {
  1826. dprintf("Added to customer DB (%ld)\n", ReturnVal.m_dw_Value1);
  1827. }
  1828. return Hr;
  1829. }
  1830. //
  1831. // SolutionDatabaseHandler Methods
  1832. //
  1833. SolutionDatabaseHandler::SolutionDatabaseHandler()
  1834. {
  1835. m_szDbName = "SolutionDb";
  1836. }
  1837. SolutionDatabaseHandler::~SolutionDatabaseHandler()
  1838. {
  1839. }
  1840. HRESULT
  1841. SolutionDatabaseHandler::GetSolution(
  1842. PCRASH_INSTANCE Crash
  1843. )
  1844. {
  1845. HRESULT Hr = S_OK;
  1846. if (!m_fConnected)
  1847. {
  1848. return E_FAIL;
  1849. }
  1850. return E_NOTIMPL;
  1851. }
  1852. HRESULT
  1853. SolutionDatabaseHandler::CheckSolutionExists(
  1854. PSTR szSBucket,
  1855. PSTR szGBucket,
  1856. PULONG pSolnId,
  1857. PULONG pSolutionType,
  1858. PULONG pgSolutionId,
  1859. BOOL bForcegSolLookup
  1860. )
  1861. {
  1862. HRESULT Hr = S_OK;
  1863. ULONG nRecords = 0;
  1864. CIntValue3 SolnId;
  1865. if (!m_fConnected)
  1866. {
  1867. return E_FAIL;
  1868. }
  1869. SolnId.m_dw_Value1 = 0;
  1870. m_pADOResult = &SolnId;
  1871. StringCbPrintfW(
  1872. m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1873. L"sp_CheckForSolution '%S', '<Driver>', 0, '%S', %ld",
  1874. szSBucket,
  1875. szGBucket ? szGBucket : "",
  1876. bForcegSolLookup // we need gbucket solution
  1877. );
  1878. // returns: SolutionId, SolutionType, gSolutionId
  1879. Hr = GetRecords(&nRecords, TRUE);
  1880. m_pADOResult = NULL;
  1881. if (FAILED(Hr))
  1882. {
  1883. return Hr;
  1884. }
  1885. if (!SolnId.m_dw_Value1 && !SolnId.m_dw_Value3)
  1886. {
  1887. return E_FAIL;
  1888. }
  1889. *pSolnId = SolnId.m_dw_Value1;
  1890. if (pSolutionType)
  1891. {
  1892. *pSolutionType = SolnId.m_dw_Value2;
  1893. }
  1894. if (pgSolutionId)
  1895. {
  1896. *pgSolutionId = SolnId.m_dw_Value3;
  1897. }
  1898. return S_OK;
  1899. }
  1900. HRESULT
  1901. SolutionDatabaseHandler::GetSolutionFromDB(
  1902. PSTR szBucket,
  1903. PSTR szGBucket,
  1904. LPSTR DriverName,
  1905. ULONG TimeStamp,
  1906. ULONG OS,
  1907. OUT PSTR pszSolution,
  1908. ULONG SolutionBufferSize,
  1909. OUT PULONG pSolutionId,
  1910. OUT PULONG pSolutionType,
  1911. OUT PULONG pGenericSolutionId
  1912. )
  1913. {
  1914. if (!m_fConnected)
  1915. {
  1916. return E_FAIL;
  1917. }
  1918. HRESULT Hr = S_OK;
  1919. PSTR BaseUrl;
  1920. ULONG SolnId = 0, GenSolId = 0;
  1921. if (!(BaseUrl = g_pTriager->GetFollowupStr("debugger-params",
  1922. "solutionurl")))
  1923. {
  1924. BaseUrl = g_lpszBaseUrl;
  1925. }
  1926. if ((Hr = CheckSolutionExists(szBucket, szGBucket, &SolnId,
  1927. pSolutionType, &GenSolId,
  1928. TRUE)) == S_OK)
  1929. {
  1930. *pSolutionId = SolnId;
  1931. if (pGenericSolutionId)
  1932. {
  1933. *pGenericSolutionId = GenSolId;
  1934. }
  1935. if (!SolnId && !GenSolId)
  1936. {
  1937. Hr = S_FALSE;
  1938. }
  1939. else if (pszSolution && SolnId)
  1940. {
  1941. Hr = StringCbPrintfA(pszSolution, SolutionBufferSize,
  1942. "%ssid=%ld&State=1",
  1943. BaseUrl,
  1944. SolnId);
  1945. } else if (!SolnId)
  1946. {
  1947. Hr = S_FALSE;
  1948. }
  1949. }
  1950. return Hr;
  1951. }
  1952. HRESULT
  1953. SolutionDatabaseHandler::GetSolutiontext(
  1954. PSTR szBucket,
  1955. PSTR szSolText,
  1956. ULONG SolTextSize
  1957. )
  1958. {
  1959. HRESULT Hr;
  1960. ULONG nRecords = 0;
  1961. CSolutionDesc Solution;
  1962. Solution.m_dw_SolType = 0;
  1963. Solution.m_sz_Solution[0] = 0;
  1964. m_pADOResult = &Solution;
  1965. StringCbPrintfW(m_wszQueryCommand, sizeof(m_wszQueryCommand),
  1966. L"sp_GetBucketSolution '%S', ''",
  1967. szBucket);
  1968. Hr = GetRecords(&nRecords, TRUE);
  1969. m_pADOResult = NULL;
  1970. if (FAILED(Hr))
  1971. {
  1972. return Hr;
  1973. }
  1974. if (Solution.m_dw_SolType == 0 &&
  1975. Solution.m_sz_Solution[0] == 0)
  1976. {
  1977. return E_FAIL;
  1978. }
  1979. StringCchCopy(szSolText, SolTextSize, Solution.m_sz_Solution);
  1980. return Hr;
  1981. }
  1982. HRESULT
  1983. SolutionDatabaseHandler::PrintBucketInfo(
  1984. PSTR sBucket,
  1985. PSTR gBucket
  1986. )
  1987. {
  1988. HRESULT Hr = S_OK;
  1989. CHAR SolutionText[MAX_PATH];
  1990. dprintf("BUCKET ID : %s\n", sBucket);
  1991. if (SUCCEEDED(GetSolutiontext(sBucket, SolutionText, sizeof(SolutionText))))
  1992. {
  1993. dprintf("ISSUE IS SOLVED : %s\n\n", SolutionText);
  1994. } else
  1995. {
  1996. dprintf("ISSUE IS UNSOLVED\n");
  1997. }
  1998. return Hr;
  1999. }
  2000. HRESULT
  2001. SolutionDatabaseHandler::AddKnownFailureToDB(LPSTR Bucket)
  2002. {
  2003. if (!m_fConnected)
  2004. {
  2005. return E_FAIL;
  2006. }
  2007. HRESULT Hr = S_OK;
  2008. return Hr;
  2009. }
  2010. HRESULT
  2011. BuildGuidForSR(
  2012. PSTR szSR,
  2013. PSTR Guid,
  2014. ULONG GuidSize
  2015. )
  2016. {
  2017. GUID srGuid = {0};
  2018. PUCHAR szTempGuid = NULL;
  2019. HRESULT hr = g_Ole32Calls.CoCreateGuid(&srGuid);
  2020. if (FAILED(hr))
  2021. {
  2022. return hr;
  2023. }
  2024. hr = UuidToString(&srGuid, &szTempGuid);
  2025. if (hr == S_OK)
  2026. {
  2027. hr = StringCchCopy(Guid, GuidSize, (PCHAR) szTempGuid);
  2028. RpcStringFree(&szTempGuid);
  2029. }
  2030. return hr;
  2031. }
  2032. HRESULT
  2033. FindSrInfo(
  2034. PSTR szSR,
  2035. PSTR szDumpPath,
  2036. PDEBUG_CONTROL3 DebugControl
  2037. )
  2038. {
  2039. HRESULT Hr;
  2040. CHAR szSBucket[100], szGBucket[100];
  2041. CHAR BktComment[200];
  2042. ULONG BugId;
  2043. if (!szSR || *szSR == '\0')
  2044. {
  2045. return E_FAIL;
  2046. }
  2047. if (FAILED(Hr = InitializeDatabaseHandlers(DebugControl ? DebugControl : g_ExtControl, 5)))
  2048. {
  2049. return Hr;
  2050. }
  2051. BktComment[0] = 0;
  2052. BugId = 0;
  2053. // Validate if SR# is present in DB
  2054. if (g_CrDb->CheckSRExists(szSR, NULL))
  2055. {
  2056. // SR present info DB
  2057. if (szDumpPath && *szDumpPath != '\0')
  2058. {
  2059. // we already have an entry
  2060. Hr = E_INVALIDARG;
  2061. dprintf("\n\nThere is already an entry in DB for SR %s. It cannot be linked to another\n"
  2062. "dumpfile. Specifiy only the SR ID to retrive the crash info.\n",
  2063. szSR);
  2064. } else
  2065. {
  2066. // Get bucket info
  2067. dprintf("\nFound entry for %s in database.\n\n", szSR);
  2068. Hr = g_CrDb->FindSRBuckets(szSR, szSBucket, sizeof(szSBucket),
  2069. szGBucket, sizeof(szGBucket));
  2070. if (SUCCEEDED(Hr))
  2071. {
  2072. g_CrDb->GetBucketComments(szSBucket, BktComment, sizeof(BktComment),
  2073. &BugId);
  2074. Hr = S_OK;
  2075. }
  2076. }
  2077. } else if (szDumpPath && *szDumpPath != '\0')
  2078. {
  2079. CRASH_INSTANCE Crash = {0};
  2080. CHAR szGUID[50];
  2081. PCHAR Ext;
  2082. Ext = strrchr(szDumpPath, '.');
  2083. if (Ext == NULL || _stricmp(Ext, ".cab"))
  2084. {
  2085. dprintf("\n\nERROR: %s is not CABed dump.\n Please add only the CAB dumps through ticket.\n\n",
  2086. szDumpPath);
  2087. Hr = E_INVALIDARG;
  2088. } else if ((Hr = BuildGuidForSR(szSR, szGUID, sizeof(szGUID))) == S_OK)
  2089. {
  2090. CHAR FileName[100];
  2091. StringCchCopy(FileName, sizeof(FileName) - 5, szSR);
  2092. StringCchCat(FileName, sizeof(FileName), ".cab");
  2093. Crash.MesgGuid = szGUID;
  2094. Crash.PssSr = szSR;
  2095. Crash.ArchiveFileName = FileName;
  2096. Crash.Bucket = szSBucket;
  2097. Crash.BucketSize = sizeof(szSBucket);
  2098. Crash.DefaultBucket = szGBucket;
  2099. Crash.DefaultBucketSize = sizeof(szGBucket);
  2100. Crash.Path = szDumpPath;
  2101. // Add crash entry to DB
  2102. Hr = AddCrashToDB(2, &Crash);
  2103. if (Hr == S_OK)
  2104. {
  2105. // Hr = g_CrDb->LinkCrashToSR(szSR, &Crash);
  2106. if (SUCCEEDED(Hr))
  2107. {
  2108. g_CrDb->GetBucketComments(szSBucket, BktComment, sizeof(BktComment),
  2109. &BugId);
  2110. Hr = S_OK;
  2111. }
  2112. }
  2113. }
  2114. // Get bucket info
  2115. } else
  2116. {
  2117. dprintf("SR %s does not exist in database\n", szSR);
  2118. Hr = S_FALSE;
  2119. }
  2120. CHAR szSolution[300];
  2121. ULONG SolutionId;
  2122. if (Hr == S_OK)
  2123. {
  2124. // Print comment, bug id, solution
  2125. if (BugId != 0)
  2126. {
  2127. dprintf("KNOWN BUG # %ld\n\n", BugId);
  2128. }
  2129. if (BktComment[0])
  2130. {
  2131. dprintf("DEV COMMENT ON ISSUE : %s\n\n", BktComment);
  2132. }
  2133. if (g_SolDb->PrintBucketInfo(szSBucket, szGBucket))
  2134. {
  2135. }
  2136. }
  2137. UnInitializeDatabaseHandlers( TRUE );
  2138. return Hr;
  2139. }
  2140. HRESULT
  2141. _EFN_FindSrInfo(
  2142. PSTR szSR,
  2143. PSTR szDumpPath,
  2144. PDEBUG_CONTROL3 DebugControl
  2145. )
  2146. {
  2147. return FindSrInfo(szSR, szDumpPath, DebugControl);
  2148. }
  2149. DECLARE_API( ticket )
  2150. {
  2151. HRESULT Hr = S_OK;
  2152. CHAR szSR[100] = {0}, szDumpPath[MAX_PATH] = {0};
  2153. INIT_API();
  2154. if (sscanf(args, "%100s %240s", szSR, szDumpPath))
  2155. {
  2156. Hr = FindSrInfo(szSR, szDumpPath, g_ExtControl);
  2157. } else
  2158. {
  2159. dprintf("Usage: !ticket <SR#> <dumppath>\n");
  2160. }
  2161. EXIT_API();
  2162. return Hr;
  2163. }