Source code of Windows XP (NT5)
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.

567 lines
13 KiB

  1. // EmDebugSession.cpp : Implementation of CEmDebugSession
  2. #include "stdafx.h"
  3. #include "Emsvc.h"
  4. #include "EmDebugSession.h"
  5. /////////////////////////////////////////////////////////////////////////////
  6. // CEmDebugSession
  7. STDMETHODIMP CEmDebugSession::InterfaceSupportsErrorInfo(REFIID riid)
  8. {
  9. static const IID* arr[] =
  10. {
  11. &IID_IEmDebugSession
  12. };
  13. for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
  14. {
  15. if (::InlineIsEqualGUID(*arr[i],riid))
  16. return S_OK;
  17. }
  18. return S_FALSE;
  19. }
  20. STDMETHODIMP
  21. CEmDebugSession::DebugEx
  22. (
  23. IN BSTR bstrEmObj,
  24. IN SessionType eSessType,
  25. IN BSTR bstrEcxFilePath,
  26. IN LONG lParam,
  27. IN OPT VARIANT vtUserName,
  28. IN OPT VARIANT vtPassword,
  29. IN OPT VARIANT vtPort,
  30. IN OPT VARIANT vtNotifyAdmin,
  31. IN OPT VARIANT vtAltSymPath
  32. )
  33. {
  34. ATLTRACE(_T("CEmDebugSession::DebugEx\n"));
  35. _ASSERTE(bstrEmObj != NULL);
  36. HRESULT hr = E_FAIL;
  37. PEmObject pEmObj = NULL;
  38. PEMSession pEmSess = NULL;
  39. BSTR bstrUserName = GetBSTR(vtUserName);
  40. BSTR bstrPassword = GetBSTR(vtPassword);
  41. BSTR bstrNotificationString = GetBSTR(vtNotifyAdmin);
  42. BSTR bstrAltSymPath = GetBSTR(vtAltSymPath);
  43. UINT nPort = GetInteger(vtPort);
  44. EmObject EmObj;
  45. m_pcs->ReadLock();
  46. __try {
  47. do
  48. {
  49. if( (bstrEmObj == NULL) ||
  50. (vtUserName.vt != VT_EMPTY && IsBSTR(vtUserName) == FALSE) ||
  51. (vtPassword.vt != VT_EMPTY && IsBSTR(vtPassword) == FALSE) ||
  52. (vtPort.vt != VT_EMPTY && IsInteger(vtPort) == FALSE) ||
  53. (vtNotifyAdmin.vt != VT_EMPTY && IsBSTR(vtNotifyAdmin) == FALSE) ||
  54. (vtAltSymPath.vt != VT_EMPTY && IsBSTR(vtAltSymPath) == FALSE)
  55. )
  56. {
  57. hr = E_INVALIDARG;
  58. break;
  59. }
  60. pEmObj = GetEmObj(bstrEmObj);
  61. _ASSERTE( pEmObj != NULL );
  62. //
  63. // If it is being debugged already this call should not
  64. // have been made..
  65. //
  66. // hr = m_pASTManager->IsAlreadyBeingDebugged(pEmObj);
  67. LONG lStatus = 0L;
  68. hr = m_pASTManager->GetSessionStatus( m_pEmObj->guidstream, &lStatus );
  69. FAILEDHR_BREAK(hr);
  70. // if( hr == S_OK ) {
  71. if( HIWORD(lStatus) > HIWORD(STAT_SESS_NOT_STARTED) ) {
  72. hr = EMERROR_PROCESSBEINGDEBUGGED;
  73. break;
  74. }
  75. ZeroMemory((void *)&EmObj, sizeof EmObj);
  76. if( eSessType == SessType_Automatic ) {
  77. hr = StartAutomaticSession(
  78. (lParam & RECURSIVE_MODE),
  79. bstrEcxFilePath,
  80. bstrNotificationString,
  81. bstrAltSymPath,
  82. (lParam & PRODUCE_MINI_DUMP),
  83. (lParam & PRODUCE_USER_DUMP)
  84. );
  85. EmObj.type2 = SessType_Automatic;
  86. EmObj.dateStart = CServiceModule::GetCurrentTime();
  87. m_pASTManager->UpdateSessObject( m_pEmObj->guidstream,
  88. EMOBJ_FLD_TYPE2 | EMOBJ_FLD_DATESTART,
  89. &EmObj
  90. );
  91. }
  92. else {
  93. hr = StartManualSession(
  94. bstrEcxFilePath,
  95. nPort,
  96. bstrUserName,
  97. bstrPassword,
  98. (lParam && BLOCK_INCOMING_IPCALLS),
  99. bstrAltSymPath
  100. );
  101. FAILEDHR_BREAK(hr);
  102. EmObj.type2 = SessType_Manual;
  103. EmObj.dateStart = CServiceModule::GetCurrentTime();
  104. m_pASTManager->UpdateSessObject( m_pEmObj->guidstream,
  105. EMOBJ_FLD_TYPE2 | EMOBJ_FLD_DATESTART,
  106. &EmObj
  107. );
  108. }
  109. }
  110. while( false );
  111. if(SUCCEEDED(hr)) {
  112. m_pASTManager->SetSessionStatus(
  113. pEmObj->guidstream,
  114. STAT_SESS_DEBUG_IN_PROGRESS_NONE,
  115. hr,
  116. NULL
  117. );
  118. SetMyselfAsMaster();
  119. m_pASTManager->GetSession(pEmObj->guidstream, &pEmSess);
  120. ::SysFreeString(bstrEmObj);
  121. bstrEmObj = CopyBSTR((LPBYTE)pEmSess->pEmObj, sizeof EmObject);
  122. }
  123. }
  124. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  125. hr = E_UNEXPECTED;
  126. _ASSERTE( false );
  127. }
  128. m_pcs->ReadUnlock();
  129. return hr;
  130. }
  131. STDMETHODIMP CEmDebugSession::StopDebug(BOOL bForceStop)
  132. {
  133. ATLTRACE(_T("CEmDebugSession::StopDebug\n"));
  134. HRESULT hr = E_FAIL;
  135. LONG lStatus = 0L;
  136. m_pcs->ReadLock();
  137. __try {
  138. hr = m_pASTManager->GetSessionStatus( m_pEmObj->guidstream, &lStatus );
  139. if( FAILED(hr) ) { return hr; }
  140. if( !(lStatus & STAT_SESS_DEBUG_IN_PROGRESS ) ) {
  141. return (hr = EMERROR_PROCESSNOTBEINGDEBUGGED);
  142. }
  143. hr = CanTakeOwnership();
  144. if( bForceStop && hr == EMERROR_SESSIONORPHANED ) {
  145. hr = m_pASTManager->AdoptThisSession( m_pEmObj->guidstream );
  146. if( SUCCEEDED(hr) ) {
  147. SetMyselfAsMaster();
  148. hr = S_OK;
  149. }
  150. }
  151. if( hr == S_OK ) { hr = m_pEmSessThrd->StopDebugging(); }
  152. }
  153. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  154. hr = E_UNEXPECTED;
  155. _ASSERTE( false );
  156. }
  157. m_pcs->ReadUnlock();
  158. return hr;
  159. }
  160. STDMETHODIMP
  161. CEmDebugSession::GenerateDumpFile
  162. (
  163. IN UINT nDumpType
  164. )
  165. {
  166. ATLTRACE(_T("CEmDebugSession::GenerateDumpFile\n"));
  167. HRESULT hr = E_FAIL,
  168. hrStat = E_FAIL;
  169. LONG lStatus = 0L;
  170. m_pcs->ReadLock();
  171. __try {
  172. // we don't need this check any more, coz we allow anybody and everybody
  173. // to generate dump files.. :(
  174. // if( AmITheMaster() == FALSE ) { return EMERROR_NOTOWNER; }
  175. hr = m_pEmSessThrd->CreateDumpFile( nDumpType );
  176. }
  177. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  178. hr = E_UNEXPECTED;
  179. _ASSERTE( false );
  180. }
  181. m_pcs->ReadUnlock();
  182. return hr;
  183. }
  184. STDMETHODIMP
  185. CEmDebugSession::GetStatus
  186. (
  187. IN OUT BSTR bstrEmObj
  188. )
  189. {
  190. ATLTRACE(_T("CEmDebugSession::GetStatus\n"));
  191. _ASSERTE(bstrEmObj != NULL);
  192. HRESULT hr = E_FAIL;
  193. PEMSession pEmSess = NULL;
  194. PEmObject pEmObj = NULL;
  195. m_pcs->ReadLock();
  196. __try {
  197. do
  198. {
  199. if( bstrEmObj == NULL ){
  200. hr = E_INVALIDARG;
  201. break;
  202. }
  203. /*
  204. // everyone should be able to call Refresh..
  205. if( AmITheMaster() == FALSE ) {
  206. hr = EMERROR_NOTOWNER;
  207. break;
  208. }
  209. */
  210. pEmObj = GetEmObj(bstrEmObj);
  211. // This should never happen
  212. hr = EMERROR_INVALIDPROCESS;
  213. if(m_pASTManager->GetSession(pEmObj->guidstream, &pEmSess) == S_OK){
  214. ::SysFreeString(bstrEmObj);
  215. bstrEmObj = CopyBSTR((LPBYTE)pEmSess->pEmObj, sizeof EmObject);
  216. hr = S_OK;
  217. }
  218. }
  219. while( false );
  220. }
  221. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  222. hr = E_UNEXPECTED;
  223. _ASSERTE( false );
  224. }
  225. m_pcs->ReadUnlock();
  226. return hr;
  227. }
  228. bool CEmDebugSession::AmITheMaster()
  229. {
  230. ATLTRACE(_T("CEmDebugSession::AmITheMaster\n"));
  231. return (m_bMaster);
  232. }
  233. HRESULT
  234. CEmDebugSession::StartAutomaticSession
  235. (
  236. IN BOOL bRecursive,
  237. IN BSTR bstrEcxFilePath,
  238. IN BSTR bstrNotificationString,
  239. IN BSTR bstrAltSymPath,
  240. IN BOOL bGenMiniDumpFile,
  241. IN BOOL bGenUserDumpFile
  242. )
  243. {
  244. ATLTRACE(_T("CEmDebugSession::StartAutomaticSession\n"));
  245. _ASSERTE(bstrEcxFilePath != NULL);
  246. HRESULT hr = E_FAIL;
  247. m_pcs->ReadLock();
  248. __try {
  249. do
  250. {
  251. if( bstrEcxFilePath == NULL ) {
  252. hr = E_INVALIDARG;
  253. break;
  254. }
  255. hr = m_pEmSessThrd->InitAutomaticSession(
  256. bRecursive,
  257. bstrEcxFilePath,
  258. bstrNotificationString,
  259. bstrAltSymPath,
  260. bGenMiniDumpFile,
  261. bGenUserDumpFile
  262. );
  263. FAILEDHR_BREAK(hr);
  264. hr = HRESULT_FROM_WIN32(m_pEmSessThrd->Start());
  265. FAILEDHR_BREAK(hr);
  266. WaitForSingleObject( m_pEmSessThrd->m_hCDBStarted, INFINITE );
  267. }
  268. while( false );
  269. }
  270. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  271. hr = E_UNEXPECTED;
  272. _ASSERTE( false );
  273. }
  274. m_pcs->ReadUnlock();
  275. return hr;
  276. }
  277. HRESULT
  278. CEmDebugSession::StartManualSession
  279. (
  280. IN BSTR bstrEcxFilePath,
  281. IN UINT nPort,
  282. IN BSTR bstrUserName,
  283. IN BSTR bstrPassword,
  284. IN BOOL bBlockIncomingIPConnections,
  285. IN BSTR bstrAltSymPath
  286. )
  287. {
  288. ATLTRACE(_T("CEmDebugSession::StartManualSession\n"));
  289. _ASSERTE( nPort != NULL );
  290. _ASSERTE( bstrUserName != NULL );
  291. _ASSERTE( bstrPassword != NULL );
  292. HRESULT hr = E_FAIL;
  293. m_pcs->ReadLock();
  294. __try {
  295. do
  296. {
  297. if( ( nPort == NULL ) ||
  298. ( bstrUserName == NULL )||
  299. ( bstrPassword == NULL ) ) {
  300. hr = E_INVALIDARG;
  301. break;
  302. }
  303. if( m_pASTManager->IsPortInUse(nPort) == TRUE ) {
  304. hr = EMERROR_PORTINUSE;
  305. break;
  306. }
  307. hr = m_pEmSessThrd->InitManualSession(
  308. bstrEcxFilePath,
  309. nPort,
  310. bstrUserName,
  311. bstrPassword,
  312. bBlockIncomingIPConnections,
  313. bstrAltSymPath
  314. );
  315. FAILEDHR_BREAK(hr);
  316. hr = HRESULT_FROM_WIN32(m_pEmSessThrd->Start());
  317. FAILEDHR_BREAK(hr);
  318. WaitForSingleObject( m_pEmSessThrd->m_hCDBStarted, INFINITE );
  319. }
  320. while( false );
  321. }
  322. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  323. hr = E_UNEXPECTED;
  324. _ASSERTE( false );
  325. }
  326. m_pcs->ReadUnlock();
  327. return hr;
  328. }
  329. STDMETHODIMP
  330. CEmDebugSession::Debug
  331. (
  332. IN OUT BSTR bstrEmObj,
  333. IN SessionType eSessType
  334. )
  335. {
  336. return E_NOTIMPL;
  337. }
  338. STDMETHODIMP CEmDebugSession::CancelDebug(BOOL bForceCancel)
  339. {
  340. ATLTRACE(_T("CEmDebugSession::CancelDebug\n"));
  341. HRESULT hr = E_FAIL;
  342. LONG lStatus = 0L;
  343. m_pcs->ReadLock();
  344. __try {
  345. hr = m_pASTManager->GetSessionStatus( m_pEmObj->guidstream, &lStatus );
  346. if( FAILED(hr) ) { return hr; }
  347. if( !(lStatus & STAT_SESS_DEBUG_IN_PROGRESS ) ) {
  348. return (hr = EMERROR_PROCESSNOTBEINGDEBUGGED);
  349. }
  350. hr = CanTakeOwnership();
  351. if( bForceCancel && hr == EMERROR_SESSIONORPHANED ) {
  352. hr = m_pASTManager->AdoptThisSession( m_pEmObj->guidstream );
  353. if( SUCCEEDED(hr) ) { SetMyselfAsMaster(); hr = S_OK; }
  354. }
  355. if( hr == S_OK ) { hr = m_pEmSessThrd->CancelDebugging(); }
  356. }
  357. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  358. hr = E_UNEXPECTED;
  359. _ASSERTE( false );
  360. }
  361. m_pcs->ReadUnlock();
  362. return hr;
  363. }
  364. void CEmDebugSession::SetMyselfAsMaster(bool bMaster /* = true */)
  365. {
  366. m_bMaster = bMaster;
  367. }
  368. HRESULT CEmDebugSession::CanTakeOwnership()
  369. {
  370. HRESULT hr = E_FAIL,
  371. hrStat = E_FAIL;
  372. LONG lStatus = 0L;
  373. m_pcs->ReadLock();
  374. __try
  375. {
  376. do
  377. {
  378. m_pASTManager->GetSessionStatus( m_pEmObj->guidstream, &lStatus, &hrStat );
  379. if( HIWORD(lStatus) < HIWORD(STAT_SESS_DEBUG_IN_PROGRESS) ) {
  380. hr = EMERROR_PROCESSNOTBEINGDEBUGGED;
  381. break;
  382. }
  383. // if I am the master, I can do anything to the session..
  384. if( AmITheMaster() == true ) { hr = S_OK; break; }
  385. hr = m_pASTManager->IsSessionOrphaned( m_pEmObj->guidstream );
  386. if( FAILED(hr) ) { break; }
  387. // am not the master and the session is orphaned..
  388. if( hr == S_OK ) { hr = EMERROR_SESSIONORPHANED; break; }
  389. // am not the master and the session is not orphaned..
  390. hr = E_ACCESSDENIED;
  391. }
  392. while( false );
  393. }
  394. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  395. hr = E_UNEXPECTED;
  396. _ASSERTE( false );
  397. }
  398. m_pcs->ReadUnlock();
  399. return hr;
  400. }
  401. STDMETHODIMP CEmDebugSession::AdoptOrphan()
  402. {
  403. HRESULT hr = E_FAIL;
  404. m_pcs->ReadLock();
  405. __try
  406. {
  407. hr = CanTakeOwnership();
  408. if( hr == EMERROR_SESSIONORPHANED ) {
  409. hr = m_pASTManager->AdoptThisSession( m_pEmObj->guidstream );
  410. if( SUCCEEDED(hr) ) { SetMyselfAsMaster(); hr = S_OK; }
  411. }
  412. }
  413. __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
  414. hr = E_UNEXPECTED;
  415. _ASSERTE( false );
  416. }
  417. m_pcs->ReadUnlock();
  418. return hr;
  419. }