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.

1612 lines
52 KiB

  1. // DBGLauncher.cpp : Implementation of WinMain
  2. // Note: Proxy/Stub Information
  3. // To build a separate proxy/stub DLL,
  4. // run nmake -f DBGLauncherps.mk in the project directory.
  5. #include "stdafx.h"
  6. #include "resource.h"
  7. #include "Messages.h"
  8. #include <time.h>
  9. #include <sys/timeb.h>
  10. #include <strsafe.h>
  11. #include "DBGLauncher_i.c"
  12. #include "ocamon.h"
  13. #define MAX_QUEUE_OPEN_RETRY 5
  14. static WCHAR strGuidMQTestType[] =
  15. L"{c30e0960-a2c0-11cf-9785-00608cb3e80c}";
  16. // Some useful macros
  17. #define RELEASE(punk) if (punk) { (punk)->Release(); (punk) = NULL; }
  18. #define ADDREF(punk) ((punk) ? (punk)->AddRef() : 0)
  19. CServiceModule _Module;
  20. HANDLE g_hStopEvent = NULL;
  21. BOOL g_ReadQueueFlag = TRUE;
  22. BEGIN_OBJECT_MAP(ObjectMap)
  23. END_OBJECT_MAP()
  24. LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
  25. {
  26. while (p1 != NULL && *p1 != NULL)
  27. {
  28. LPCTSTR p = p2;
  29. while (p != NULL && *p != NULL)
  30. {
  31. if (*p1 == *p)
  32. return CharNext(p1);
  33. p = CharNext(p);
  34. }
  35. p1 = CharNext(p1);
  36. }
  37. return NULL;
  38. }
  39. // Although some of these functions are big they are declared inline since they are only used once
  40. inline HRESULT CServiceModule::RegisterServer(BOOL bRegTypeLib, BOOL bService)
  41. {
  42. HRESULT hr = CoInitialize(NULL);
  43. if (FAILED(hr))
  44. return hr;
  45. // Remove any previous service since it may point to
  46. // the incorrect file
  47. Uninstall();
  48. SetupEventLog(FALSE);
  49. // Add service entries
  50. UpdateRegistryFromResource(IDR_DBGLauncher, TRUE);
  51. // Adjust the AppID for Local Server or Service
  52. CRegKey keyAppID;
  53. LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE);
  54. if (lRes != ERROR_SUCCESS)
  55. return lRes;
  56. CRegKey key;
  57. lRes = key.Open(keyAppID, _T("{5D3C7CA6-DF04-4864-897D-83BF996692B3}"), KEY_WRITE);
  58. if (lRes != ERROR_SUCCESS)
  59. return lRes;
  60. key.DeleteValue(_T("LocalService"));
  61. if (bService)
  62. {
  63. key.SetValue(_T("DBGLauncher"), _T("LocalService") );
  64. key.SetValue(_T("-Service"), _T("ServiceParameters"));
  65. // Create service
  66. Install();
  67. }
  68. // Add object entries
  69. hr = CComModule::RegisterServer(bRegTypeLib);
  70. CoUninitialize();
  71. return hr;
  72. }
  73. inline HRESULT CServiceModule::UnregisterServer()
  74. {
  75. HRESULT hr = CoInitialize(NULL);
  76. if (FAILED(hr))
  77. return hr;
  78. // Remove service entries
  79. UpdateRegistryFromResource(IDR_DBGLauncher, FALSE);
  80. // Remove service
  81. Uninstall();
  82. // Remove object entries
  83. CComModule::UnregisterServer(TRUE);
  84. CoUninitialize();
  85. return S_OK;
  86. }
  87. inline void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, UINT nServiceNameID, const GUID* plibid)
  88. {
  89. CComModule::Init(p, h, plibid);
  90. m_bService = TRUE;
  91. LoadString(h, nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR));
  92. // set up the initial service status
  93. m_hServiceStatus = NULL;
  94. m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  95. m_status.dwCurrentState = SERVICE_STOPPED;
  96. m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  97. m_status.dwWin32ExitCode = 0;
  98. m_status.dwServiceSpecificExitCode = 0;
  99. m_status.dwCheckPoint = 0;
  100. m_status.dwWaitHint = 0;
  101. //
  102. // Create Named Events
  103. //
  104. g_hStopEvent = CreateEvent(
  105. NULL,
  106. FALSE,
  107. FALSE,
  108. s_cszStopEvent
  109. );
  110. if(NULL == g_hStopEvent)
  111. {
  112. LogEvent( _T("Failed to create stop event: %s; hr=%ld"),
  113. s_cszStopEvent,
  114. GetLastError());
  115. }
  116. m_hMonNotifyPipe = NULL;
  117. }
  118. LONG CServiceModule::Unlock()
  119. {
  120. LONG l = CComModule::Unlock();
  121. if (l == 0 && !m_bService)
  122. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  123. return l;
  124. }
  125. BOOL CServiceModule::IsInstalled()
  126. {
  127. BOOL bResult = FALSE;
  128. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  129. if (hSCM != NULL)
  130. {
  131. SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG);
  132. if (hService != NULL)
  133. {
  134. bResult = TRUE;
  135. ::CloseServiceHandle(hService);
  136. }
  137. ::CloseServiceHandle(hSCM);
  138. }
  139. return bResult;
  140. }
  141. inline BOOL CServiceModule::Install()
  142. {
  143. if (IsInstalled())
  144. return TRUE;
  145. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  146. if (hSCM == NULL)
  147. {
  148. MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
  149. return FALSE;
  150. }
  151. SetupEventLog(TRUE);
  152. // Get the executable file path
  153. TCHAR szFilePath[_MAX_PATH];
  154. ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
  155. SC_HANDLE hService = ::CreateService(
  156. hSCM, m_szServiceName, m_szServiceName,
  157. SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
  158. SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
  159. szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);
  160. if (hService == NULL)
  161. {
  162. ::CloseServiceHandle(hSCM);
  163. MessageBox(NULL, _T("Couldn't create service"), m_szServiceName, MB_OK);
  164. return FALSE;
  165. }
  166. SERVICE_FAILURE_ACTIONS Failure;
  167. SC_ACTION Actions[3];
  168. Failure.cActions = 3;
  169. Failure.dwResetPeriod = 1200;
  170. Failure.lpCommand = _T("");
  171. Failure.lpRebootMsg = _T("");
  172. Failure.lpsaActions = Actions;
  173. Actions[0].Delay = 2000;
  174. Actions[0].Type = SC_ACTION_RESTART;
  175. Actions[1].Delay = 2000;
  176. Actions[1].Type = SC_ACTION_RESTART;
  177. Actions[2].Delay = 2000;
  178. Actions[2].Type = SC_ACTION_RESTART;
  179. ::CloseServiceHandle(hService);
  180. ::CloseServiceHandle(hSCM);
  181. return TRUE;
  182. }
  183. inline BOOL CServiceModule::Uninstall()
  184. {
  185. if (!IsInstalled())
  186. return TRUE;
  187. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  188. if (hSCM == NULL)
  189. {
  190. MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
  191. return FALSE;
  192. }
  193. SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE);
  194. if (hService == NULL)
  195. {
  196. ::CloseServiceHandle(hSCM);
  197. MessageBox(NULL, _T("Couldn't open service"), m_szServiceName, MB_OK);
  198. return FALSE;
  199. }
  200. SERVICE_STATUS status;
  201. ::ControlService(hService, SERVICE_CONTROL_STOP, &status);
  202. BOOL bDelete = ::DeleteService(hService);
  203. ::CloseServiceHandle(hService);
  204. ::CloseServiceHandle(hSCM);
  205. if (bDelete)
  206. return TRUE;
  207. MessageBox(NULL, _T("Service could not be deleted"), m_szServiceName, MB_OK);
  208. return FALSE;
  209. }
  210. ///////////////////////////////////////////////////////////////////////////////////////
  211. // Logging functions
  212. void CServiceModule::LogEvent(LPCTSTR pFormat, ...)
  213. {
  214. TCHAR chMsg[256];
  215. HANDLE hEventSource;
  216. LPTSTR lpszStrings[1];
  217. va_list pArg;
  218. va_start(pArg, pFormat);
  219. // _vstprintf(chMsg, pFormat, pArg);
  220. if (StringCbVPrintf(chMsg,sizeof chMsg, pFormat, pArg) != S_OK)
  221. {
  222. return;
  223. }
  224. va_end(pArg);
  225. lpszStrings[0] = chMsg;
  226. if (m_bService)
  227. {
  228. /* Get a handle to use with ReportEvent(). */
  229. hEventSource = RegisterEventSource(NULL, m_szServiceName);
  230. if (hEventSource != NULL)
  231. {
  232. /* Write to event log. */
  233. ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, EVENT_MESSAGE, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
  234. DeregisterEventSource(hEventSource);
  235. }
  236. }
  237. else
  238. {
  239. // As we are not running as a service, just write the error to the console.
  240. _putts(chMsg);
  241. }
  242. }
  243. //////////////////////////////////////////////////////////////////////////////////////////////
  244. // Service startup and registration
  245. inline void CServiceModule::Start()
  246. {
  247. SERVICE_TABLE_ENTRY st[] =
  248. {
  249. { m_szServiceName, _ServiceMain },
  250. { NULL, NULL }
  251. };
  252. if (m_bService && !::StartServiceCtrlDispatcher(st))
  253. {
  254. m_bService = FALSE;
  255. }
  256. if (m_bService == FALSE)
  257. Run();
  258. }
  259. inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
  260. {
  261. // Register the control request handler
  262. m_status.dwCurrentState = SERVICE_START_PENDING;
  263. m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
  264. if (m_hServiceStatus == NULL)
  265. {
  266. LogEvent(_T("Handler not installed"));
  267. return;
  268. }
  269. SetServiceStatus(SERVICE_START_PENDING);
  270. m_status.dwWin32ExitCode = S_OK;
  271. m_status.dwCheckPoint = 0;
  272. m_status.dwWaitHint = 0;
  273. // When the Run function returns, the service has stopped.
  274. Run();
  275. SetupEventLog(TRUE);
  276. SetServiceStatus(SERVICE_STOPPED);
  277. LogEvent(_T("Service stopped"));
  278. }
  279. inline void CServiceModule::Handler(DWORD dwOpcode)
  280. {
  281. switch (dwOpcode)
  282. {
  283. case SERVICE_CONTROL_STOP:
  284. SetServiceStatus(SERVICE_STOP_PENDING);
  285. // SetServiceStatus(SERVICE_STOP_PENDING);
  286. if(NULL != g_hStopEvent)
  287. {
  288. if(FALSE == SetEvent( g_hStopEvent ))
  289. {
  290. LogFatalEvent( _T("Unable to signal Stop Event; Error: %ld"), GetLastError());
  291. }
  292. CloseHandle( g_hStopEvent );
  293. }
  294. /// PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  295. // break;
  296. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  297. break;
  298. case SERVICE_CONTROL_PAUSE:
  299. break;
  300. case SERVICE_CONTROL_CONTINUE:
  301. break;
  302. case SERVICE_CONTROL_INTERROGATE:
  303. break;
  304. case SERVICE_CONTROL_SHUTDOWN:
  305. break;
  306. default:
  307. LogEvent(_T("Bad service request"));
  308. }
  309. }
  310. void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
  311. {
  312. _Module.ServiceMain(dwArgc, lpszArgv);
  313. }
  314. void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
  315. {
  316. _Module.Handler(dwOpcode);
  317. }
  318. void CServiceModule::SetServiceStatus(DWORD dwState)
  319. {
  320. m_status.dwCurrentState = dwState;
  321. ::SetServiceStatus(m_hServiceStatus, &m_status);
  322. }
  323. void CServiceModule::Run()
  324. {
  325. BYTE *byteVersionBuff = NULL;
  326. VS_FIXEDFILEINFO *pVersionInfo = NULL;
  327. UINT uLength = 0;
  328. _Module.dwThreadID = GetCurrentThreadId();
  329. TCHAR szFilePath[_MAX_PATH];
  330. DWORD dwPlaceHolder = 0;
  331. // HRESULT hr = CoInitialize(NULL);
  332. // If you are running on NT 4.0 or higher you can use the following call
  333. // instead to make the EXE free threaded.
  334. // This means that calls come in on a random RPC thread
  335. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  336. _ASSERTE(SUCCEEDED(hr));
  337. // This provides a NULL DACL which will allow access to everyone.
  338. CSecurityDescriptor sd;
  339. sd.InitializeFromThreadToken();
  340. hr = CoInitializeSecurity(sd, -1, NULL, NULL,
  341. RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
  342. _ASSERTE(SUCCEEDED(hr));
  343. hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
  344. _ASSERTE(SUCCEEDED(hr));
  345. ZeroMemory(szFilePath, sizeof szFilePath);
  346. ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
  347. if (szFilePath[0] != _T('\0'))
  348. {
  349. DWORD dwBufferSize = GetFileVersionInfoSize(szFilePath,&dwPlaceHolder);
  350. if (dwBufferSize > 0)
  351. byteVersionBuff = (BYTE*) malloc (dwBufferSize);
  352. if (byteVersionBuff)
  353. {
  354. GetFileVersionInfo(szFilePath,NULL,dwBufferSize,byteVersionBuff);
  355. VerQueryValue(byteVersionBuff,_T("\\"),(VOID **) &pVersionInfo, &uLength);
  356. LogEvent(_T("DbgLauncher service version: %d.%d.%d.%d Started."), HIWORD (pVersionInfo->dwFileVersionMS),LOWORD(pVersionInfo->dwFileVersionMS)
  357. ,HIWORD(pVersionInfo->dwFileVersionLS),LOWORD(pVersionInfo->dwFileVersionLS)) ;
  358. }
  359. }
  360. // DWORD NameLength = sizeof(TCHAR) * (MAX_COMPUTERNAME_LENGTH + 1);
  361. if (m_bService)
  362. SetServiceStatus(SERVICE_RUNNING);
  363. //
  364. // Execute Archive Service
  365. //
  366. try
  367. {
  368. PrepareForDebuggerLaunch();
  369. }
  370. catch(...)
  371. {
  372. LogEvent( _T("dbgLauncher Service CRASHED !!! "));
  373. }
  374. if (m_hMonNotifyPipe != NULL &&
  375. m_hMonNotifyPipe != INVALID_HANDLE_VALUE)
  376. {
  377. CloseHandle(m_hMonNotifyPipe);
  378. m_hMonNotifyPipe = NULL;
  379. }
  380. MSG msg;
  381. while (GetMessage(&msg, 0, 0, 0))
  382. DispatchMessage(&msg);
  383. _Module.RevokeClassObjects();
  384. CoUninitialize();
  385. }
  386. /////////////////////////////////////////////////////////////////////////////
  387. //
  388. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
  389. HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
  390. {
  391. lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
  392. _Module.Init(ObjectMap, hInstance, IDS_SERVICENAME, &LIBID_DBGLAUNCHERLib);
  393. _Module.m_bService = TRUE;
  394. TCHAR szTokens[] = _T("-/");
  395. LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
  396. while (lpszToken != NULL)
  397. {
  398. if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
  399. NORM_IGNORECASE,
  400. lpszToken,
  401. -1,
  402. _T("UnregServer"),
  403. -1 ) == CSTR_EQUAL)
  404. // if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
  405. return _Module.UnregisterServer();
  406. // Register as Local Server
  407. if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
  408. NORM_IGNORECASE,
  409. lpszToken,
  410. -1,
  411. _T("RegServer"),
  412. -1 ) == CSTR_EQUAL)
  413. //if (lstrcmpi(lpszToken, _T("RegServer"))==0)
  414. return _Module.RegisterServer(TRUE, FALSE);
  415. // Register as Service
  416. if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
  417. NORM_IGNORECASE,
  418. lpszToken,
  419. -1,
  420. _T("Service"),
  421. -1 ) == CSTR_EQUAL)
  422. // if (lstrcmpi(lpszToken, _T("Service"))==0)
  423. return _Module.RegisterServer(TRUE, TRUE);
  424. lpszToken = FindOneOf(lpszToken, szTokens);
  425. }
  426. // Are we Service or Local Server
  427. CRegKey keyAppID;
  428. LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ);
  429. if (lRes != ERROR_SUCCESS)
  430. return lRes;
  431. CRegKey key;
  432. lRes = key.Open(keyAppID, _T("{5D3C7CA6-DF04-4864-897D-83BF996692B3}"), KEY_READ);
  433. if (lRes != ERROR_SUCCESS)
  434. return lRes;
  435. TCHAR szValue[_MAX_PATH];
  436. DWORD dwLen = _MAX_PATH;
  437. lRes = key.QueryValue(szValue,_T("LocalService"), &dwLen);
  438. _Module.m_bService = FALSE;
  439. if (lRes == ERROR_SUCCESS)
  440. _Module.m_bService = TRUE;
  441. _Module.Start();
  442. // When we get here, the service has been stopped
  443. return _Module.m_status.dwWin32ExitCode;
  444. }
  445. BOOL
  446. CServiceModule::GetServiceParams(SVCPARAMS *ServiceParams)
  447. {
  448. HKEY hHKLM;
  449. HKEY hDbgLauncherKey;
  450. BYTE Buffer[MAX_PATH + 1];
  451. DWORD Type;
  452. DWORD BufferSize = MAX_PATH +1; // Set for largest value
  453. BOOL Status = TRUE;
  454. if(!RegConnectRegistry(NULL, HKEY_LOCAL_MACHINE, &hHKLM))
  455. {
  456. if(!RegOpenKeyEx(hHKLM,_T("Software\\Microsoft\\DbgLauncherSvc"), 0, KEY_ALL_ACCESS, &hDbgLauncherKey))
  457. {
  458. // Get the input queue directory path
  459. BufferSize = MAX_PATH +1;
  460. ZeroMemory(Buffer, BufferSize);
  461. if (RegQueryValueEx(hDbgLauncherKey,_T("DebuggerName"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
  462. {
  463. LogEvent(_T("Failed to get InputQueue value from registry."));
  464. Status = FALSE;
  465. }
  466. else
  467. {
  468. if (StringCbCopy (ServiceParams->DebuggerName, sizeof ServiceParams->DebuggerName,(TCHAR *) Buffer)!= S_OK)
  469. {
  470. LogEvent (_T("Failed to copy debuggername reg value to ServiceParams->DebuggerName"));
  471. Status = FALSE;
  472. }
  473. }
  474. BufferSize = MAX_PATH +1;
  475. ZeroMemory(Buffer, BufferSize);
  476. // Now get the Primary Queue connection string
  477. if (RegQueryValueEx(hDbgLauncherKey,_T("PrimaryQueue"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
  478. {
  479. LogEvent(_T("Failed to get PrimaryQueue value from registry."));
  480. Status = FALSE;
  481. }
  482. else
  483. {
  484. if (StringCbCopy(ServiceParams->PrimaryQueue,sizeof ServiceParams->PrimaryQueue, (TCHAR *) Buffer)!= S_OK)
  485. {
  486. LogEvent (_T("Failed to copy PrimaryQueue reg value to ServiceParams->PrimaryQueue"));
  487. Status = FALSE;
  488. }
  489. }
  490. BufferSize = MAX_PATH +1;
  491. ZeroMemory(Buffer, BufferSize);
  492. // Now get the Primary Queue connection string
  493. if (RegQueryValueEx(hDbgLauncherKey,_T("SecondaryQueue"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
  494. {
  495. LogEvent(_T("Failed to get SecondaryQueue value from registry."));
  496. Status = FALSE;
  497. }
  498. else
  499. {
  500. if (StringCbCopy(ServiceParams->SecondaryQueue,sizeof ServiceParams->SecondaryQueue, (TCHAR *) Buffer)!= S_OK)
  501. {
  502. LogEvent (_T("Failed to copy SecondaryQueue reg value to ServiceParams->SecondaryQueue"));
  503. Status = FALSE;
  504. }
  505. }
  506. BufferSize = MAX_PATH +1;
  507. ZeroMemory(Buffer, BufferSize);
  508. // now get the primary response queue
  509. if (RegQueryValueEx(hDbgLauncherKey,_T("PrimaryResponseQueue"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
  510. {
  511. LogEvent(_T("Failed to get Primary ResponseQueue value from registry."));
  512. Status = FALSE;
  513. }
  514. else
  515. {
  516. if (StringCbCopy(ServiceParams->PrimaryResponseQueue,sizeof ServiceParams->PrimaryResponseQueue, (TCHAR *) Buffer) != S_OK)
  517. {
  518. LogEvent (_T("Failed to copy PrimaryResponseQueue reg value to ServiceParams->PrimaryResponseQueue"));
  519. Status = FALSE;
  520. }
  521. }
  522. BufferSize = MAX_PATH +1;
  523. ZeroMemory(Buffer, BufferSize);
  524. // now get the secondary response queue
  525. if (RegQueryValueEx(hDbgLauncherKey,_T("SecondaryResponseQueue"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
  526. {
  527. LogEvent(_T("Failed to get Secondary ResponseQueue value from registry."));
  528. Status = FALSE;
  529. }
  530. else
  531. {
  532. if (StringCbCopy(ServiceParams->SecondaryResponseQueue,sizeof ServiceParams->SecondaryResponseQueue, (TCHAR *) Buffer)!= S_OK)
  533. {
  534. LogEvent (_T("Failed to copy SecondaryResponseQueue reg value to ServiceParams->SecondaryResponseQueue"));
  535. Status = FALSE;
  536. }
  537. }
  538. BufferSize = MAX_PATH +1;
  539. ZeroMemory(Buffer, BufferSize);
  540. // Now get the ini release point
  541. if (RegQueryValueEx(hDbgLauncherKey,_T("IniInstallLocation"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
  542. {
  543. LogEvent(_T("Failed to get IniInstallLocation Queue value from registry."));
  544. Status = FALSE;
  545. }
  546. else
  547. {
  548. if (StringCbCopy(ServiceParams->IniInstallLocation,sizeof ServiceParams->IniInstallLocation, (TCHAR *) Buffer)!= S_OK)
  549. {
  550. LogEvent (_T("Failed to copy IniInstallLocation reg value to ServiceParams->IniInstallLocation"));
  551. Status = FALSE;
  552. }
  553. }
  554. BufferSize = MAX_PATH +1;
  555. ZeroMemory(Buffer, BufferSize);
  556. // Now get the Symbols server connection string
  557. if (RegQueryValueEx(hDbgLauncherKey,_T("SymSrv"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
  558. {
  559. LogFatalEvent(_T("Failed to get the symbol server value from the registry."));
  560. Status = FALSE;
  561. }
  562. else
  563. {
  564. if (StringCbCopy(ServiceParams->Symsrv,sizeof ServiceParams->Symsrv, (TCHAR *) Buffer) != S_OK)
  565. {
  566. LogEvent (_T("Failed to copy Symsrv reg value to ServiceParams->Symsrv"));
  567. Status = FALSE;
  568. }
  569. }
  570. BufferSize = MAX_PATH +1;
  571. ZeroMemory(Buffer, BufferSize);
  572. // Now get the Delay -- Min time between kd launches
  573. if (RegQueryValueEx(hDbgLauncherKey,_T("Delay"), 0, &Type, Buffer, &BufferSize))
  574. {
  575. LogEvent(_T("Failed to get the min delay between dbg launches."));
  576. }
  577. else
  578. {
  579. ServiceParams->dwDelay = *((DWORD*)Buffer);
  580. }
  581. BufferSize = MAX_PATH +1;
  582. ZeroMemory(Buffer, BufferSize);
  583. // Now get the Primary Queue delay
  584. if (RegQueryValueEx(hDbgLauncherKey,_T("PrimaryInterval"), 0, &Type, Buffer, &BufferSize))
  585. {
  586. LogFatalEvent(_T("Failed to get the Primary queue wait interval."));
  587. Status = FALSE;
  588. }
  589. else
  590. {
  591. ServiceParams->dwPrimaryWait = *((DWORD*)Buffer);
  592. }
  593. BufferSize = MAX_PATH +1;
  594. ZeroMemory(Buffer, BufferSize);
  595. // Now get the Primary Queue delay
  596. if (RegQueryValueEx(hDbgLauncherKey,_T("IniWaitTime"), 0, &Type, Buffer, &BufferSize))
  597. {
  598. LogFatalEvent(_T("Failed to get the triage.Ini wait interval."));
  599. Status = FALSE;
  600. }
  601. else
  602. {
  603. ServiceParams->IniCheckWaitTime = *((DWORD*)Buffer);
  604. }
  605. BufferSize = MAX_PATH +1;
  606. ZeroMemory(Buffer, BufferSize);
  607. // Now get the Memory usage threshold
  608. if (RegQueryValueEx(hDbgLauncherKey,_T("MaxKdProcesses"), 0, &Type, Buffer, &BufferSize))
  609. {
  610. LogFatalEvent(_T("Failed to get the Max Kd Processes setting."));
  611. Status = FALSE;
  612. }
  613. else
  614. {
  615. ServiceParams->dwMaxKdProcesses = *((DWORD*)Buffer);
  616. }
  617. BufferSize = MAX_PATH +1;
  618. ZeroMemory(Buffer, BufferSize);
  619. // Now get the Memory usage threshold
  620. if (RegQueryValueEx(hDbgLauncherKey,_T("MaxDumpSize"), 0, &Type, Buffer, &BufferSize))
  621. {
  622. LogEvent(_T("Failed to get the Max Dump Size setting."));
  623. ServiceParams->dwMaxDumpSize = -1;
  624. }
  625. else
  626. {
  627. ServiceParams->dwMaxDumpSize = *((DWORD*)Buffer);
  628. }
  629. RegCloseKey(hHKLM);
  630. RegCloseKey(hDbgLauncherKey);
  631. return TRUE;
  632. }
  633. else
  634. {
  635. RegCloseKey(hHKLM);
  636. return FALSE;
  637. }
  638. }
  639. else
  640. return FALSE;
  641. }
  642. DWORD
  643. CServiceModule::CheckForIni (SVCPARAMS *ServiceParams)
  644. {
  645. FILETIME CreationTimeCurrent;
  646. FILETIME CreationTimeNew;
  647. TCHAR IniFileName[MAX_PATH];
  648. TCHAR DebuggerPath[MAX_PATH];
  649. TCHAR *Temp = NULL;
  650. HANDLE hFile = INVALID_HANDLE_VALUE;
  651. HANDLE hFile2 = INVALID_HANDLE_VALUE;
  652. ZeroMemory (&CreationTimeCurrent, sizeof FILETIME);
  653. ZeroMemory (&CreationTimeNew, sizeof FILETIME);
  654. if (_tcslen(ServiceParams->DebuggerName) + _tcslen(_T("\\winxp\\triage.ini")) < MAX_PATH)
  655. {
  656. if (StringCbCopy(DebuggerPath, sizeof DebuggerPath, ServiceParams->DebuggerName)!= S_OK)
  657. {
  658. LogEvent(_T("CheckForIni: Failed to build Debugger Path"));
  659. }
  660. Temp = DebuggerPath;
  661. Temp += _tcslen(DebuggerPath);
  662. if (Temp != DebuggerPath)
  663. {
  664. while(*Temp != _T('\\'))
  665. {
  666. -- Temp;
  667. }
  668. *(Temp+1) = _T('\0');
  669. }
  670. // Get the file path of the debugger remove the ocakd.exe string then add triage\\triage.ini
  671. if (StringCbCat (DebuggerPath,sizeof DebuggerPath, _T("winxp\\triage.ini")) != S_OK)
  672. {
  673. LogEvent(_T("CheckForIni: Failed to build debugger path"));
  674. }
  675. // Check to see if we need a new triage.ini file.
  676. // open a shared read handle to the existing ini file.
  677. hFile = CreateFile(DebuggerPath,
  678. GENERIC_READ,
  679. FILE_SHARE_READ,
  680. 0,
  681. OPEN_EXISTING,
  682. FILE_ATTRIBUTE_NORMAL,
  683. NULL);
  684. if (hFile != INVALID_HANDLE_VALUE)
  685. {
  686. // Get the time date stamp of the existing triage ini file.
  687. if ( GetFileTime(hFile,NULL,NULL,&CreationTimeCurrent) )
  688. {
  689. // Now get the filetime for the triage.ini replacement.
  690. hFile2 = CreateFile(ServiceParams->IniInstallLocation,
  691. GENERIC_READ,
  692. FILE_SHARE_READ,
  693. 0,
  694. OPEN_EXISTING,
  695. FILE_ATTRIBUTE_NORMAL,
  696. NULL);
  697. if (hFile2 != INVALID_HANDLE_VALUE)
  698. {
  699. if (GetFileTime(hFile2, NULL,NULL,&CreationTimeNew))
  700. {
  701. // LogEvent (_T("Comparing the creation times"));
  702. if ( CompareFileTime( &CreationTimeNew , &CreationTimeCurrent) == 1)
  703. {
  704. // copy the new file here.
  705. if (hFile != INVALID_HANDLE_VALUE)
  706. CloseHandle (hFile);
  707. if (hFile2 != INVALID_HANDLE_VALUE)
  708. CloseHandle (hFile2);
  709. if (CopyFile(ServiceParams->IniInstallLocation, DebuggerPath,FALSE) )
  710. {
  711. // LogEvent(_T("Successfully copied triage.ini from: %s to %s"),
  712. // ServiceParams->IniInstallLocation, DebuggerPath);
  713. ;
  714. }
  715. else
  716. {
  717. // LogEvent(_T("Copy of file:%s to %s failed\n error code: %d"),ServiceParams->IniInstallLocation, DebuggerPath, GetLastError());
  718. ;
  719. }
  720. }
  721. }
  722. if (hFile2 != INVALID_HANDLE_VALUE)
  723. CloseHandle (hFile2);
  724. }
  725. }
  726. if (hFile != INVALID_HANDLE_VALUE)
  727. CloseHandle (hFile);
  728. }
  729. }
  730. return 0;
  731. }
  732. HRESULT CServiceModule::ConnectToMSMQ(QUEUEHANDLE *hQueue, wchar_t *QueueConnectStr)
  733. /*++
  734. Routine Description:
  735. This function is called when the WWW service is shutdown.
  736. Arguments:
  737. dwFlags - HSE_TERM_ADVISORY_UNLOAD or HSE_TERM_MUST_UNLOAD
  738. Return Value:
  739. TRUE when extension is ready to be unloaded,
  740. --*/
  741. {
  742. HRESULT Hr = S_OK;
  743. DWORD i;
  744. i = 0;
  745. Hr = MQOpenQueue(QueueConnectStr,
  746. MQ_RECEIVE_ACCESS,
  747. MQ_DENY_NONE,
  748. hQueue);
  749. return Hr;
  750. }
  751. BOOL CServiceModule::Initialize(PSVCPARAMS pParams)
  752. {
  753. HRESULT hr;
  754. if (!GetServiceParams(pParams) )
  755. {
  756. LogFatalEvent(_T("Failed to read initialization data from the registry."));
  757. return FALSE;
  758. }
  759. //ConnectToMSMQ
  760. hr = ConnectToMSMQ(&(pParams->hPrimaryQueue),pParams->PrimaryQueue);
  761. if (SUCCEEDED(hr))
  762. {
  763. LogEvent(_T("Connected to primary Queue"));
  764. //pParams->PrimaryConnected = TRUE;
  765. }
  766. else
  767. {
  768. //pParams->PrimaryConnected = FALSE;
  769. LogEvent(_T("Cannot connected to primary Queue %s, error %lx"), pParams->PrimaryQueue, hr);
  770. }
  771. hr = ConnectToMSMQ(&(pParams->hSecondaryQueue),pParams->SecondaryQueue);
  772. if (SUCCEEDED(hr))
  773. {
  774. //pParams->PrimaryConnected = TRUE;
  775. LogEvent(_T("Connected to secondary Queue"));
  776. }
  777. else
  778. {
  779. //pParams->PrimaryConnected = FALSE;
  780. LogEvent(_T("Cannot connected to secondary Queue %s, error %lx"), pParams->SecondaryQueue, hr);
  781. }
  782. return TRUE;
  783. }
  784. BOOL CServiceModule::ReceiveQueueMessage(PSVCPARAMS pParams,
  785. wchar_t *RecMessageBody,
  786. wchar_t *szMessageGuid,
  787. BOOL *bUsePrimary,
  788. int *Type,
  789. wchar_t *szSR)
  790. {
  791. MSGPROPID PropIds[5];
  792. MQPROPVARIANT PropVariants[5];
  793. HRESULT hrProps[5];
  794. MQMSGPROPS MessageProps;
  795. DWORD i = 0;
  796. wchar_t RecLabel[100];
  797. wchar_t LocalRecBody[MAX_PATH];
  798. DWORD RecMessageBodySize = sizeof LocalRecBody;
  799. DWORD RecLabelLength = sizeof RecLabel;
  800. HRESULT hResult = 0;
  801. BOOL Status = FALSE;
  802. TCHAR *Temp = NULL;
  803. ZeroMemory(LocalRecBody,sizeof LocalRecBody);
  804. ZeroMemory(RecLabel,sizeof RecLabel);
  805. i = 0;
  806. PropIds[i] = PROPID_M_LABEL_LEN;
  807. PropVariants[i].vt = VT_UI4;
  808. PropVariants[i].ulVal = RecLabelLength;
  809. i++;
  810. PropIds[i] = PROPID_M_LABEL;
  811. PropVariants[i].vt = VT_LPWSTR;
  812. PropVariants[i].pwszVal = RecLabel;
  813. i++;
  814. MessageProps.aPropID = PropIds;
  815. MessageProps.aPropVar = PropVariants;
  816. MessageProps.aStatus = hrProps;
  817. MessageProps.cProp = i;
  818. // retrieve the current message
  819. i = 0;
  820. PropIds[i] = PROPID_M_LABEL_LEN;
  821. PropVariants[i].vt = VT_UI4;
  822. PropVariants[i].ulVal = RecLabelLength;
  823. i++;
  824. PropIds[i] = PROPID_M_LABEL;
  825. PropVariants[i].vt = VT_LPWSTR;
  826. PropVariants[i].pwszVal = RecLabel;
  827. i++;
  828. PropIds[i] = PROPID_M_BODY_SIZE;
  829. PropVariants[i].vt = VT_UI4;
  830. i++;
  831. PropIds[i] = PROPID_M_BODY_TYPE;
  832. PropVariants[i].vt = VT_UI4;
  833. i++;
  834. PropIds[i] = PROPID_M_BODY;
  835. PropVariants[i].vt = VT_VECTOR|VT_UI1;
  836. PropVariants[i].caub.pElems = (LPBYTE) LocalRecBody;
  837. PropVariants[i].caub.cElems = RecMessageBodySize;
  838. i++;
  839. MessageProps.aPropID = PropIds;
  840. MessageProps.aPropVar = PropVariants;
  841. MessageProps.aStatus = hrProps;
  842. MessageProps.cProp = i;
  843. hResult = MQReceiveMessage( pParams->hPrimaryQueue,
  844. 0,
  845. MQ_ACTION_RECEIVE,
  846. &MessageProps,
  847. NULL,
  848. NULL,
  849. NULL,
  850. MQ_NO_TRANSACTION);
  851. if (FAILED (hResult) )
  852. {
  853. if (hResult != (HRESULT) MQ_ERROR_IO_TIMEOUT)
  854. {
  855. if (hResult == (HRESULT) MQ_ERROR_QUEUE_NOT_AVAILABLE)
  856. {
  857. // Non Fatal Event
  858. LogFatalEvent(_T("The %s MSMQ is unavailable."), pParams->PrimaryQueue );
  859. }
  860. else
  861. {
  862. if (hResult == (HRESULT) MQ_ERROR_INVALID_HANDLE)
  863. {
  864. // Close the current handle and attempt to reconnect to the MSMQ
  865. MQCloseQueue( pParams->hPrimaryQueue );
  866. ConnectToMSMQ(&(pParams->hPrimaryQueue), pParams->PrimaryQueue );
  867. }
  868. }
  869. }
  870. //g_ReadQueueFlag = !g_ReadQueueFlag;
  871. hResult = MQReceiveMessage( pParams->hSecondaryQueue,
  872. 0,
  873. MQ_ACTION_RECEIVE,
  874. &MessageProps,
  875. NULL,
  876. NULL,
  877. NULL,
  878. MQ_NO_TRANSACTION);
  879. if (FAILED(hResult) )
  880. {
  881. Status = FALSE;
  882. if (hResult != (HRESULT)MQ_ERROR_IO_TIMEOUT)
  883. {
  884. if (hResult == (HRESULT)MQ_ERROR_QUEUE_NOT_AVAILABLE)
  885. {
  886. // Non Fatal Event
  887. LogFatalEvent(_T("The %s MSMQ is unavailable."), pParams->SecondaryQueue);
  888. }
  889. else
  890. {
  891. if (hResult == (HRESULT)MQ_ERROR_INVALID_HANDLE)
  892. {
  893. // Close the current handle and attempt to reconnect to the MSMQ
  894. MQCloseQueue(pParams->hSecondaryQueue);
  895. ConnectToMSMQ(&(pParams->hSecondaryQueue), pParams->SecondaryQueue);
  896. }
  897. }
  898. }
  899. return Status;
  900. }
  901. //
  902. // We have valid message from SecondaryQueue
  903. //
  904. }
  905. else
  906. {
  907. //
  908. // We have valid message from Primary Queue
  909. //
  910. }
  911. //
  912. // Copy the messge parameters
  913. //
  914. if (StringCbCopy(RecMessageBody,RecMessageBodySize, LocalRecBody) != S_OK)
  915. {
  916. LogEvent(_T("Failed to copy the recieved message body to RecMessageBody"));
  917. }
  918. if (StringCbCopy(szMessageGuid,RecLabelLength, RecLabel) != S_OK)
  919. {
  920. LogEvent(_T("Failed to copy the RecLabel into szMessageGuid."));
  921. }
  922. Status = TRUE;
  923. *bUsePrimary = TRUE;
  924. Temp = RecMessageBody;
  925. while ( (*Temp != _T(';')) && (*Temp != _T('\0')))
  926. {
  927. ++Temp;
  928. }
  929. if (*Temp != _T('\0'))
  930. {
  931. *Type = _wtoi (Temp+1);
  932. // terminate the string here.
  933. *Temp = _T('\0');
  934. }
  935. else
  936. {
  937. *Type = 1;
  938. }
  939. Temp = _tcsstr(LocalRecBody, _T(";SR="));
  940. if (Temp != NULL)
  941. {
  942. // we got a SR number in message
  943. Temp += 4;
  944. StringCbCopy(szSR, 50, Temp);
  945. } else
  946. {
  947. *szSR = _T('\0');
  948. }
  949. // Flip the read from queue flag for the next call
  950. //g_ReadQueueFlag = !g_ReadQueueFlag;
  951. return Status;
  952. }
  953. ULONG64
  954. CServiceModule::GetFileSize(
  955. LPWSTR wszFile
  956. )
  957. {
  958. HANDLE hFile;
  959. DWORD dwFileSize, dwFileSizeHi;
  960. hFile = CreateFileW(wszFile, GENERIC_READ,
  961. FILE_SHARE_READ, NULL,
  962. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  963. NULL);
  964. if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
  965. {
  966. dwFileSizeHi = 0;
  967. dwFileSize=::GetFileSize(hFile,&dwFileSizeHi);
  968. return (ULONG64) dwFileSize + ((ULONG64)dwFileSizeHi << 32);
  969. }
  970. return -1;
  971. }
  972. VOID
  973. CServiceModule::NotifyDebuggerLaunch(
  974. PDBADDCRASH_PARAMS pDbParams
  975. )
  976. {
  977. HANDLE hPipe;
  978. DWORD dwMode, cbWritten;
  979. OCAKD_MONITOR_MESSAGE Msg;
  980. OVERLAPPED WriteOverlapped;
  981. Msg.MessageId = OKD_MESSAGE_DBGLAUNCH_NOTIFY;
  982. Msg.u.DbglNotice.SizeOfStruct = sizeof(Msg.u.DbglNotice);
  983. Msg.u.DbglNotice.Source = pDbParams->Source;
  984. Msg.u.DbglNotice.nKdsRunning = m_DebuggerCount;
  985. if (StringCbPrintfA(Msg.u.DbglNotice.CrashGuid, sizeof(Msg.u.DbglNotice.CrashGuid),
  986. "%ws", pDbParams->Guid) != S_OK ||
  987. StringCbPrintfA(Msg.u.DbglNotice.OriginalPath,sizeof(Msg.u.DbglNotice.OriginalPath),
  988. "%ws", pDbParams->DumpPath) != S_OK)
  989. {
  990. return;
  991. }
  992. for (hPipe = m_hMonNotifyPipe;m_hMonNotifyPipe == NULL;)
  993. {
  994. hPipe = CreateFile(c_tszCollectPipeName, FILE_WRITE_DATA,
  995. 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
  996. NULL);
  997. if (hPipe != INVALID_HANDLE_VALUE)
  998. {
  999. m_hMonNotifyPipe = hPipe;
  1000. break;
  1001. }
  1002. if (GetLastError() != ERROR_PIPE_BUSY)
  1003. {
  1004. return;
  1005. }
  1006. // Do not wait long, this might block other processes
  1007. if (!WaitNamedPipe(c_tszCollectPipeName, 5*1000))
  1008. {
  1009. return;
  1010. }
  1011. }
  1012. // We are now connected to pipe
  1013. WriteOverlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
  1014. if (WriteOverlapped.hEvent != NULL)
  1015. {
  1016. // Send crash information to monitor pipe
  1017. if (!WriteFile(hPipe, (LPVOID) &Msg, sizeof(Msg),
  1018. &cbWritten, &WriteOverlapped))
  1019. {
  1020. if (GetLastError() == ERROR_NO_DATA ||
  1021. GetLastError() == ERROR_BAD_PIPE)
  1022. {
  1023. // Open a different pipe next time
  1024. CloseHandle(hPipe);
  1025. m_hMonNotifyPipe = NULL;
  1026. } else if (GetLastError() == ERROR_IO_PENDING ||
  1027. !GetOverlappedResult(hPipe, &WriteOverlapped, &cbWritten,
  1028. TRUE))
  1029. {
  1030. // failed to write, exit silently
  1031. // Its up to monitor if it is keeping track of kds launched
  1032. } else
  1033. {
  1034. // Open a different pipe next time
  1035. CloseHandle(hPipe);
  1036. m_hMonNotifyPipe = NULL;
  1037. }
  1038. }
  1039. CloseHandle(WriteOverlapped.hEvent);
  1040. }
  1041. FlushFileBuffers(hPipe);
  1042. return;
  1043. }
  1044. BOOL CServiceModule::LaunchDebugger(
  1045. PDBADDCRASH_PARAMS pDbParams,
  1046. PPROCESS_INFORMATION pDbgProcess
  1047. )
  1048. {
  1049. STARTUPINFO StartupInfo;
  1050. wchar_t CommandLine [1024];
  1051. wchar_t SrParam[100];
  1052. HRESULT hr;
  1053. ZeroMemory(&StartupInfo,sizeof(STARTUPINFO));
  1054. StartupInfo.cb = sizeof(STARTUPINFO);
  1055. if ((pDbParams->dwMaxDumpSize != 0) && (pDbParams->dwMaxDumpSize != -1) &&
  1056. (GetFileSize(pDbParams->DumpPath) > pDbParams->dwMaxDumpSize))
  1057. {
  1058. LogEvent(_T("Dump %s is too large, deleting file\n"), pDbParams->DumpPath);
  1059. DeleteFileW(pDbParams->DumpPath);
  1060. return FALSE;
  1061. }
  1062. if (pDbParams->SrNumber[0])
  1063. {
  1064. hr = StringCbPrintf(SrParam, sizeof(SrParam), _T(" -sr %s"), pDbParams->SrNumber);
  1065. if (hr != S_OK)
  1066. {
  1067. LogEvent(_T("Bad SR %s: %lx"), pDbParams->SrNumber, hr);
  1068. return FALSE;
  1069. }
  1070. } else
  1071. {
  1072. SrParam[0] = _T('\0');
  1073. }
  1074. if ((hr = StringCbPrintf(CommandLine,sizeof CommandLine,
  1075. _T("%s -i %s -y %s -z \"%s\" -c \"!dbaddcrash -source %d -g %s -s %s -p %s%s;q\""),
  1076. pDbParams->Debugger,
  1077. pDbParams->SymPath,
  1078. pDbParams->SymPath,
  1079. pDbParams->DumpPath,
  1080. pDbParams->Source,
  1081. pDbParams->Guid,
  1082. pDbParams->ResponseMQ,
  1083. pDbParams->DumpPath,
  1084. SrParam)) != S_OK)
  1085. {
  1086. LogEvent(_T("Failed to build command line: %lx"), hr);
  1087. }
  1088. //LogEvent(_T("CommandLine Guid=%s queue=%d"),szMessageLabel,bUsePrimary);
  1089. //LogEvent(_T("CommandLine Path=%s"),szFilePath);
  1090. //LogEvent(_T("CommandLine: %s"),CommandLine);
  1091. if (!CreateProcess(NULL,
  1092. CommandLine,
  1093. NULL,
  1094. NULL,
  1095. FALSE,
  1096. //CREATE_NEW_CONSOLE,
  1097. CREATE_NO_WINDOW,
  1098. NULL,
  1099. NULL,
  1100. &StartupInfo,
  1101. pDbgProcess))
  1102. {
  1103. hr = GetLastError();
  1104. LogEvent(_T("Failed to launch debugger. Commandline %s, error %lx\n"), CommandLine, hr);
  1105. return FALSE;
  1106. }
  1107. //
  1108. // Notify Site monitor of debugger launch
  1109. //
  1110. NotifyDebuggerLaunch(pDbParams);
  1111. return TRUE;
  1112. }
  1113. BOOL CServiceModule::PrepareForDebuggerLaunch()
  1114. {
  1115. HANDLE ProcessHandles[50];
  1116. PROCESS_INFORMATION ProcessInfo;
  1117. wchar_t szFilePath[MAX_PATH];
  1118. wchar_t szSR[100];
  1119. HRESULT hr = 0;
  1120. HANDLE hStopEvent = INVALID_HANDLE_VALUE;
  1121. SVCPARAMS ServiceParams;
  1122. DWORD dwIndex = 0;
  1123. DWORD FreeIndex = 0;
  1124. DWORD dwWaitResult = 0;
  1125. BOOL Done = FALSE;
  1126. __time64_t CurrentTime = 0;
  1127. __time64_t NextCheckTime = 0;
  1128. wchar_t szMessageLabel[255];
  1129. BOOL bUsePrimary = FALSE;
  1130. int Type = 1;
  1131. DBADDCRASH_PARAMS DbParams;
  1132. ZeroMemory (ProcessHandles,sizeof ProcessHandles);
  1133. ZeroMemory(&ServiceParams,sizeof SVCPARAMS);
  1134. ZeroMemory (szMessageLabel, sizeof szMessageLabel);
  1135. ZeroMemory (szFilePath, sizeof szFilePath);
  1136. ZeroMemory(&DbParams, sizeof(DbParams));
  1137. m_DebuggerCount = 0;
  1138. hStopEvent = OpenEvent(
  1139. EVENT_ALL_ACCESS,
  1140. FALSE,
  1141. s_cszStopEvent
  1142. );
  1143. if (hStopEvent == NULL)
  1144. {
  1145. LogFatalEvent(_T("Failed to open stop event. Terminating"));
  1146. goto Done;
  1147. }
  1148. // get reg data
  1149. // Insert the stop event into the ocakd queue
  1150. ++ m_DebuggerCount;
  1151. ProcessHandles[m_DebuggerCount -1] = hStopEvent;
  1152. if (!Initialize(&ServiceParams))
  1153. {
  1154. goto Done;
  1155. }
  1156. // fill the ocakd queue
  1157. Done = FALSE;
  1158. while ( (m_DebuggerCount <= ServiceParams.dwMaxKdProcesses+1 ) && (!Done))
  1159. {
  1160. if (!ReceiveQueueMessage(&ServiceParams, szFilePath, szMessageLabel, &bUsePrimary, &Type, szSR))
  1161. {
  1162. Done = TRUE;
  1163. }
  1164. else
  1165. {
  1166. DbParams.Debugger = ServiceParams.DebuggerName;
  1167. DbParams.DumpPath = szFilePath;
  1168. DbParams.Guid = szMessageLabel;
  1169. DbParams.SrNumber = szSR;
  1170. DbParams.ResponseMQ = (bUsePrimary) ?
  1171. ServiceParams.PrimaryResponseQueue : ServiceParams.SecondaryResponseQueue;
  1172. DbParams.SymPath = ServiceParams.Symsrv;
  1173. DbParams.Source = Type;
  1174. DbParams.dwMaxDumpSize = ServiceParams.dwMaxDumpSize;
  1175. if (LaunchDebugger(&DbParams, &ProcessInfo))
  1176. {
  1177. // LogEvent(_T("Launched: %s for file: %s with guid:%s and source: %d with return queue =%s"),
  1178. // ServiceParams.DebuggerName,szFilePath, szMessageLabel, Type, (bUsePrimary) ? ServiceParams.PrimaryResponseQueue : ServiceParams.SecondaryResponseQueue);
  1179. ++ m_DebuggerCount;
  1180. ProcessHandles[m_DebuggerCount -1] = ProcessInfo.hProcess;
  1181. CloseHandle( ProcessInfo.hThread );
  1182. } // end else
  1183. }// end else
  1184. } // end while
  1185. if (m_DebuggerCount > ServiceParams.dwMaxKdProcesses+1)
  1186. m_DebuggerCount = ServiceParams.dwMaxKdProcesses+1;
  1187. while (1)
  1188. {
  1189. _time64(&CurrentTime);
  1190. if (CurrentTime > NextCheckTime)
  1191. {
  1192. // LogEvent (_T("Checking for new ini file"));
  1193. CheckForIni (&ServiceParams);
  1194. NextCheckTime= CurrentTime + (ServiceParams.IniCheckWaitTime * 60);
  1195. // LogEvent (_T("Back from ini file check"));
  1196. }
  1197. // now wait for one of the processes to complete or hStopEvent to be signaled.
  1198. dwWaitResult = WaitForMultipleObjects(m_DebuggerCount, (HANDLE *)ProcessHandles, FALSE, ServiceParams.dwDelay);
  1199. if (dwWaitResult == WAIT_FAILED)
  1200. {
  1201. LogFatalEvent(_T("Failed while waiting for prcesses to complete error code: %d"), GetLastError());
  1202. goto Cleanup;
  1203. }
  1204. else
  1205. {
  1206. if (dwWaitResult-WAIT_OBJECT_0 == 0)
  1207. {
  1208. LogEvent(_T("Stop request received terminating"));
  1209. goto Cleanup;
  1210. }
  1211. else // we have an event we can take action on.
  1212. {
  1213. if ( dwWaitResult == WAIT_TIMEOUT)
  1214. {
  1215. // no process completed so let's fill any empty slots in the
  1216. // Process array.
  1217. if (m_DebuggerCount <= ServiceParams.dwMaxKdProcesses)
  1218. {
  1219. // fill the queue until m_DebuggerCount == ServiceParams.dwMaxKdProcesses
  1220. Done = FALSE;
  1221. dwIndex = 1;
  1222. while ( (!Done) && (m_DebuggerCount <= ServiceParams.dwMaxKdProcesses) )
  1223. {
  1224. if (ProcessHandles[dwIndex] == NULL)
  1225. {
  1226. if (ReceiveQueueMessage(&ServiceParams, szFilePath, szMessageLabel,&bUsePrimary,&Type,szSR))
  1227. {
  1228. DbParams.Debugger = ServiceParams.DebuggerName;
  1229. DbParams.DumpPath = szFilePath;
  1230. DbParams.Guid = szMessageLabel;
  1231. DbParams.SrNumber = szSR;
  1232. DbParams.ResponseMQ = (bUsePrimary) ?
  1233. ServiceParams.PrimaryResponseQueue : ServiceParams.SecondaryResponseQueue;
  1234. DbParams.SymPath = ServiceParams.Symsrv;
  1235. DbParams.Source = Type;
  1236. DbParams.dwMaxDumpSize = ServiceParams.dwMaxDumpSize;
  1237. if (LaunchDebugger(&DbParams, &ProcessInfo))
  1238. {
  1239. ProcessHandles[dwIndex] = ProcessInfo.hProcess;
  1240. CloseHandle( ProcessInfo.hThread );
  1241. ++m_DebuggerCount;
  1242. } // end else
  1243. }
  1244. else
  1245. {
  1246. Done = TRUE;
  1247. }
  1248. } // end if
  1249. ++dwIndex;
  1250. } // end while
  1251. }
  1252. } // end if
  1253. else // A kd process completed now lets clean it up and launch a new one.
  1254. {
  1255. FreeIndex = (dwWaitResult - WAIT_OBJECT_0);
  1256. // check to make sure we are within our array range.
  1257. if ( (FreeIndex > ServiceParams.dwMaxKdProcesses))
  1258. {
  1259. LogFatalEvent( _T("Invalid array index returned by WaitForMultipleObjects. \n Index = %d, Count = %d"), FreeIndex,m_DebuggerCount);
  1260. }
  1261. else
  1262. {
  1263. CloseHandle(ProcessHandles[FreeIndex]);
  1264. ProcessHandles[FreeIndex] = NULL;
  1265. // if the queue is not now empty take the last Process handle and replace the current one.
  1266. if (m_DebuggerCount > 2)
  1267. {
  1268. // We have to do this because NULLs are not allowed in the HANDLE Array.
  1269. ProcessHandles[FreeIndex] = ProcessHandles[m_DebuggerCount-1];
  1270. ProcessHandles[m_DebuggerCount-1] = NULL;
  1271. -- m_DebuggerCount;
  1272. }
  1273. else
  1274. {
  1275. --m_DebuggerCount;
  1276. }
  1277. if (ReceiveQueueMessage(&ServiceParams, szFilePath, szMessageLabel,&bUsePrimary, &Type, szSR))
  1278. {
  1279. DbParams.Debugger = ServiceParams.DebuggerName;
  1280. DbParams.DumpPath = szFilePath;
  1281. DbParams.Guid = szMessageLabel;
  1282. DbParams.SrNumber = szSR;
  1283. DbParams.ResponseMQ = (bUsePrimary) ?
  1284. ServiceParams.PrimaryResponseQueue : ServiceParams.SecondaryResponseQueue;
  1285. DbParams.SymPath = ServiceParams.Symsrv;
  1286. DbParams.Source = Type;
  1287. DbParams.dwMaxDumpSize = ServiceParams.dwMaxDumpSize;
  1288. if (LaunchDebugger(&DbParams, &ProcessInfo))
  1289. {
  1290. ++m_DebuggerCount;
  1291. ProcessHandles[m_DebuggerCount-1] = ProcessInfo.hProcess;
  1292. CloseHandle( ProcessInfo.hThread );
  1293. } // end else
  1294. } // end if
  1295. } // end else
  1296. } // end else
  1297. } // end else
  1298. } // end else
  1299. }// end while(1)
  1300. Cleanup:
  1301. //
  1302. // Cleanup - Close handle to the queue
  1303. //
  1304. Done:
  1305. // set the service status to stopped and return.
  1306. if (hStopEvent != INVALID_HANDLE_VALUE)
  1307. CloseHandle(hStopEvent);
  1308. return TRUE;
  1309. }
  1310. ///////////////////////////////////////////////////////////////////////////////////////
  1311. // Routine to Log Fatal Errors to NT Event Log
  1312. void CServiceModule::LogFatalEvent(LPCTSTR pFormat, ...)
  1313. {
  1314. TCHAR chMsg[256];
  1315. HANDLE hEventSource;
  1316. LPTSTR lpszStrings[1];
  1317. va_list pArg;
  1318. va_start(pArg, pFormat);
  1319. // _vstprintf(chMsg, pFormat, pArg);
  1320. if (StringCbVPrintf(chMsg,sizeof chMsg, pFormat, pArg)!= S_OK)
  1321. {
  1322. return;
  1323. }
  1324. va_end(pArg);
  1325. lpszStrings[0] = chMsg;
  1326. /* Get a handle to use with ReportEvent(). */
  1327. hEventSource = RegisterEventSource(NULL, _T("DBGLauncher"));
  1328. if (hEventSource != NULL)
  1329. {
  1330. /* Write to event log. */
  1331. ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, EVENT_ERROR, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
  1332. DeregisterEventSource(hEventSource);
  1333. }
  1334. }
  1335. ///////////////////////////////////////////////////////////////////////////////////////
  1336. // Routine to setup NT Event logging
  1337. HRESULT CServiceModule::SetupEventLog ( BOOL fSetup )
  1338. {
  1339. CRegKey key;
  1340. TCHAR szEventKey[MAX_PATH];
  1341. LONG lRes = 0;
  1342. if (StringCbCopy(szEventKey, sizeof szEventKey,s_cszEventLogKey)!= S_OK)
  1343. {
  1344. return E_FAIL;
  1345. }
  1346. if (StringCbCat(szEventKey,sizeof szEventKey, _T("\\")) != S_OK)
  1347. return E_FAIL;
  1348. if (StringCbCat(szEventKey, sizeof szEventKey,(LPTSTR)m_szServiceName) != S_OK)
  1349. return E_FAIL;
  1350. lRes = key.Create(HKEY_LOCAL_MACHINE, szEventKey);
  1351. if (lRes != ERROR_SUCCESS)
  1352. {
  1353. goto done;
  1354. }
  1355. if( TRUE == fSetup )
  1356. {
  1357. TCHAR szMyName[MAX_PATH];
  1358. GetModuleFileName(NULL, szMyName, (sizeof szMyName)/(sizeof szMyName[0]) );
  1359. key.SetValue(szMyName, _T("EventMessageFile"));
  1360. key.SetValue(EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE,
  1361. _T("TypesSupported"));
  1362. }
  1363. else
  1364. {
  1365. RegDeleteKey(HKEY_LOCAL_MACHINE, szEventKey);
  1366. }
  1367. done:
  1368. key.Close();
  1369. return HRESULT_FROM_WIN32(GetLastError());
  1370. }