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.

651 lines
16 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <stdio.h>
  5. #include <windows.h>
  6. #include <winbase.h>
  7. #include <lmcons.h>
  8. #include <lmalert.h>
  9. #include <ntiodump.h>
  10. #define INITGUID
  11. #include <dbgeng.h>
  12. #include <guiddef.h>
  13. #include <cmnutil.hpp>
  14. #include "extsfns.h"
  15. #include <lmuse.h>
  16. #include <lmerr.h>
  17. #include <strsafe.h>
  18. #include "inetupld.h"
  19. PSTR g_AppName;
  20. PSTR g_ArchiveShare = NULL;
  21. //
  22. // Outputcallbacks for ticket
  23. //
  24. class DumpChkOutputCallbacks : public IDebugOutputCallbacks
  25. {
  26. public:
  27. // IUnknown.
  28. STDMETHOD(QueryInterface)(
  29. THIS_
  30. IN REFIID InterfaceId,
  31. OUT PVOID* Interface
  32. );
  33. STDMETHOD_(ULONG, AddRef)(
  34. THIS
  35. );
  36. STDMETHOD_(ULONG, Release)(
  37. THIS
  38. );
  39. // IDebugOutputCallbacks.
  40. STDMETHOD(Output)(
  41. THIS_
  42. IN ULONG Mask,
  43. IN PCSTR Text
  44. );
  45. };
  46. STDMETHODIMP
  47. DumpChkOutputCallbacks::QueryInterface(
  48. THIS_
  49. IN REFIID InterfaceId,
  50. OUT PVOID* Interface
  51. )
  52. {
  53. *Interface = NULL;
  54. if (IsEqualIID(InterfaceId, IID_IUnknown) ||
  55. IsEqualIID(InterfaceId, IID_IDebugOutputCallbacks))
  56. {
  57. *Interface = (IDebugOutputCallbacks *)this;
  58. AddRef();
  59. return S_OK;
  60. }
  61. else
  62. {
  63. return E_NOINTERFACE;
  64. }
  65. }
  66. STDMETHODIMP_(ULONG)
  67. DumpChkOutputCallbacks::AddRef(
  68. THIS
  69. )
  70. {
  71. // This class is designed to be static so
  72. // there's no true refcount.
  73. return 1;
  74. }
  75. STDMETHODIMP_(ULONG)
  76. DumpChkOutputCallbacks::Release(
  77. THIS
  78. )
  79. {
  80. // This class is designed to be static so
  81. // there's no true refcount.
  82. return 0;
  83. }
  84. STDMETHODIMP
  85. DumpChkOutputCallbacks::Output(
  86. THIS_
  87. IN ULONG Mask,
  88. IN PCSTR Text
  89. )
  90. {
  91. if (Text) fputs(Text, stdout);
  92. fflush(stdout);
  93. return S_OK;
  94. }
  95. DumpChkOutputCallbacks g_OutputCallback;
  96. DWORD WINAPI
  97. DisplayStatus(
  98. LPVOID Context
  99. )
  100. {
  101. POCA_UPLOADFILE pUpload = (POCA_UPLOADFILE) Context;
  102. DWORD percent;
  103. while (1)
  104. {
  105. percent = pUpload->GetPercentComplete();
  106. if (percent > 100)
  107. {
  108. fprintf(stderr, "Upload complete. \n");
  109. return 1;
  110. }
  111. fprintf(stderr, "Uploading: %02ld%% done.\r", percent);
  112. Sleep(700);
  113. }
  114. return 1;
  115. }
  116. void
  117. UploadDumpFile(
  118. PSTR DumpFile,
  119. PSTR SR
  120. )
  121. {
  122. HRESULT Hr = S_OK;
  123. WCHAR wszLocalDump[MAX_PATH] = {0};
  124. WCHAR wszRemoteName[MAX_PATH] = {0};
  125. WCHAR ResultUrl[MAX_PATH];
  126. WCHAR IsapiUrl[MAX_PATH];
  127. POCA_UPLOADFILE pUpload;
  128. HANDLE hThread = NULL;
  129. DWORD dwThreadId;
  130. PSTR FileExtension;
  131. FileExtension = DumpFile + strlen(DumpFile) - 4;
  132. if (_stricmp(FileExtension, ".cab"))
  133. {
  134. fprintf(stderr, "Please upload only the cab dump files.\n");
  135. return;
  136. }
  137. if (!OcaUpldCreate(&pUpload))
  138. {
  139. fprintf(stderr, "Cannot create UPLOAD object\n");
  140. return;
  141. }
  142. if (!MultiByteToWideChar(CP_ACP,0, DumpFile, strlen(DumpFile), wszLocalDump,
  143. MAX_PATH))
  144. {
  145. fprintf(stderr, "Cannot conver %s to widechar\n", DumpFile);
  146. Hr = E_FAIL;
  147. }
  148. if (SUCCEEDED(Hr))
  149. {
  150. if ((Hr = pUpload->InitializeSession(L"910", wszLocalDump)) != S_OK )
  151. {
  152. fprintf(stderr, "Initilaize Upload session failed %lx.\n", Hr);
  153. }
  154. }
  155. if (SUCCEEDED(Hr))
  156. {
  157. if ((Hr = StringCbPrintfW(wszRemoteName, sizeof(wszRemoteName), L"/OCA/%S.cab", SR)) != S_OK)
  158. {
  159. fprintf(stderr, "Error in generating remote file name %lx \n", Hr);
  160. }
  161. }
  162. if (SUCCEEDED(Hr))
  163. {
  164. hThread = CreateThread(NULL, 0, &DisplayStatus, (PVOID) pUpload,
  165. 0, &dwThreadId);
  166. if ((Hr = pUpload->SendFile(wszRemoteName, FALSE)) != S_OK)
  167. {
  168. fprintf(stderr, "Send dumpfile failed %lx.\n", Hr);
  169. }
  170. pUpload->UnInitialize();
  171. }
  172. if (Hr == S_OK)
  173. {
  174. if ((Hr = StringCbPrintfW(IsapiUrl,sizeof( IsapiUrl ),
  175. L"/isapi/oca_extension.dll?id=%S.cab&Type=%ld&SR=%S",
  176. SR,
  177. 8,
  178. SR)) != S_OK)
  179. {
  180. fprintf(stderr, "Cannot build IsapiUrl string. %lx\n", Hr);
  181. }
  182. }
  183. if (SUCCEEDED(Hr))
  184. {
  185. Hr = pUpload->GetUrlPageData(IsapiUrl, ResultUrl, sizeof(ResultUrl));
  186. Sleep(700);// To let DisplayStatus finish
  187. if (Hr != S_OK)
  188. {
  189. fprintf(stderr, "Cannot isapi return URL %lx\n", Hr);
  190. } else
  191. {
  192. fprintf(stderr, "File succesfully uploaded as %s.cab\n", SR);
  193. fprintf(stderr, "Received response URL: %ws\n", ResultUrl);
  194. }
  195. }
  196. if (hThread && hThread != INVALID_HANDLE_VALUE)
  197. {
  198. TerminateThread(hThread, 1);
  199. CloseHandle(hThread);
  200. }
  201. pUpload->UnInitialize();
  202. pUpload->Release();
  203. return;
  204. }
  205. void
  206. Usage(void)
  207. {
  208. fprintf(stderr, "Usage: %s [-i <imgpath>] [-y <sympath>] -s SR [-d <dumpfile>]\n", g_AppName);
  209. }
  210. HRESULT GetPasswdInput(
  211. LPWSTR wszPwd,
  212. ULONG PwdSize)
  213. {
  214. int err;
  215. DWORD mode;
  216. WCHAR Buff[51];
  217. fprintf(stdout, "Enter Password to connect to archive server: ");
  218. GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
  219. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
  220. (~(ENABLE_ECHO_INPUT)) & mode);
  221. if (scanf("%50ws", Buff) == 0)
  222. {
  223. return E_FAIL;
  224. }
  225. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
  226. fprintf(stdout, "\n");
  227. return StringCbCopyW(wszPwd, PwdSize, Buff);
  228. }
  229. //
  230. // This add access to Share
  231. //
  232. HRESULT
  233. NetworkAccessShare(
  234. PSTR szShare,
  235. LPWSTR szPassword
  236. )
  237. {
  238. USE_INFO_2 UseInfo;
  239. WCHAR wszShare[MAX_PATH], wszDomain[MAX_PATH], *pDir;
  240. if (MultiByteToWideChar(CP_ACP, 0, szShare, strlen(szShare)+1,
  241. wszShare, sizeof(wszShare)/sizeof(WCHAR)) == FALSE)
  242. {
  243. return E_FAIL;
  244. }
  245. StringCbCopyW(wszDomain, sizeof(wszDomain), &wszShare[2]);
  246. pDir = wcsrchr(wszDomain, L'\\');
  247. if (pDir == NULL)
  248. {
  249. // bad share name
  250. return FALSE;
  251. }
  252. *pDir = 0;
  253. UseInfo.ui2_local = NULL;
  254. UseInfo.ui2_remote = wszShare;
  255. UseInfo.ui2_password = szPassword;
  256. UseInfo.ui2_username = L"OcaArchive";
  257. UseInfo.ui2_domainname = wszDomain;
  258. UseInfo.ui2_asg_type = 0;
  259. UseInfo.ui2_status = 0;
  260. if (NetUseAdd(NULL, 2, (LPBYTE) &UseInfo, NULL) != NERR_Success)
  261. {
  262. return E_FAIL;
  263. }
  264. return S_OK;
  265. }
  266. //
  267. // Deletes any access granted to a remote share
  268. //
  269. HRESULT
  270. NetworkDeleteShare(
  271. void
  272. )
  273. {
  274. WCHAR wszShare[MAX_PATH];
  275. if (g_ArchiveShare == NULL)
  276. {
  277. return S_OK;
  278. }
  279. if (MultiByteToWideChar(CP_ACP, 0, g_ArchiveShare, strlen(g_ArchiveShare)+1,
  280. wszShare, sizeof(wszShare)/sizeof(WCHAR)) == FALSE)
  281. {
  282. return E_FAIL;
  283. }
  284. if (NetUseDel(NULL, wszShare, USE_NOFORCE) != NERR_Success)
  285. {
  286. return E_FAIL;
  287. }
  288. return S_OK;
  289. }
  290. //
  291. // This grants users archive access to OCA share for archiving dumps
  292. //
  293. BOOL
  294. AddArchiveAccess(
  295. PDEBUG_CLIENT4 Client,
  296. PDEBUG_CONTROL3 DebugControl,
  297. ULONG Qualifier
  298. )
  299. {
  300. HMODULE Ext = NULL;
  301. EXT_TRIAGE_FOLLOWUP fnGetFollowup;
  302. DEBUG_TRIAGE_FOLLOWUP_INFO Info;
  303. CHAR szShare[MAX_PATH];
  304. WCHAR Passwd[100];
  305. PSTR szLookup1 = "debugger-params!archshare-k-full";
  306. PSTR szLookup2 = "debugger-params!archshare-k-mini";
  307. PSTR szLookup;
  308. if (DebugControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol",
  309. (FARPROC*)&fnGetFollowup) != S_OK)
  310. {
  311. return FALSE;
  312. }
  313. if (Qualifier == DEBUG_DUMP_FULL)
  314. {
  315. szLookup = szLookup1;
  316. } else
  317. {
  318. szLookup = szLookup2;
  319. }
  320. Info.SizeOfStruct = sizeof(Info);
  321. Info.OwnerName = szShare;
  322. Info.OwnerNameSize = sizeof(szShare);
  323. if ((*fnGetFollowup)((PDEBUG_CLIENT) Client, szLookup, &Info) <= TRIAGE_FOLLOWUP_IGNORE)
  324. {
  325. return FALSE;
  326. }
  327. if (GetPasswdInput(Passwd, sizeof(Passwd)) != S_OK)
  328. {
  329. return FALSE;
  330. }
  331. //
  332. // Grant Access to szShare
  333. //
  334. if (NetworkAccessShare(szShare, Passwd) != S_OK)
  335. {
  336. return FALSE;
  337. }
  338. g_ArchiveShare = szShare;
  339. return TRUE;
  340. }
  341. HRESULT
  342. CreateCabinetFromDump(
  343. PCSTR DumpFile,
  344. PSTR CabFile,
  345. ULONG cbCabFile
  346. )
  347. {
  348. HRESULT Status;
  349. CHAR TempFile[MAX_PATH];
  350. PSTR Tail;
  351. Tail = strrchr(DumpFile, '\\');
  352. if (Tail == NULL) {
  353. Tail = (PSTR) DumpFile;
  354. } else {
  355. ++Tail;
  356. }
  357. if (!GetTempPathA(cbCabFile, CabFile)) {
  358. StringCbCopy(CabFile, cbCabFile, ".\\");
  359. }
  360. // Use the CAB name as the dump file name so the
  361. // name in the CAB will match.
  362. StringCbCat(CabFile, cbCabFile, Tail);
  363. StringCbCat(CabFile, cbCabFile, ".cab" );
  364. fprintf(stdout, "\nCreating %s, this could take some time...\n", CabFile);
  365. fflush(stdout);
  366. if ((Status = CreateDumpCab(CabFile)) != S_OK) {
  367. fprintf(stderr, "Unable to create CAB, %s\n", FormatStatusCode(Status));
  368. return Status;
  369. }
  370. else {
  371. //
  372. // add dump file.
  373. //
  374. Status = AddToDumpCab(DumpFile);
  375. CloseDumpCab();
  376. }
  377. return S_OK;
  378. }
  379. typedef HRESULT (WINAPI * RETRIVETICKET)(
  380. PSTR szSR,
  381. PSTR szPath,
  382. PDEBUG_CONTROL3 DebugControl
  383. );
  384. HRESULT
  385. RetriveSrTicket(
  386. PTSTR szSR
  387. )
  388. {
  389. HRESULT Hr = S_OK;
  390. IDebugClient4 *DebugClient;
  391. IDebugControl3 *DebugControl;
  392. HMODULE Ext = NULL;
  393. RETRIVETICKET fnTicket;
  394. if ((Hr = DebugCreate(__uuidof(IDebugClient),
  395. (void **)&DebugClient)) != S_OK) {
  396. fprintf(stderr, "Cannot initialize DebugClient\n");
  397. return Hr;
  398. }
  399. if ((DebugClient->QueryInterface(__uuidof(IDebugControl3),
  400. (void **)&DebugControl) != S_OK)) {
  401. fprintf(stderr, "QueryInterface failed for DebugClient\n");
  402. return Hr;
  403. }
  404. DebugClient->SetOutputCallbacks(&g_OutputCallback);
  405. Ext = LoadLibrary("winext\\ext.dll");
  406. if (!Ext) {
  407. fprintf(stderr,"Cannot load ext.dll.\n");
  408. Hr = E_FAIL;
  409. } else {
  410. fnTicket = (RETRIVETICKET) GetProcAddress(Ext, "_EFN_FindSrInfo");
  411. if (!fnTicket) {
  412. fprintf(stderr, "Cannot find _EFN_FindSrInfo\n");
  413. Hr = E_FAIL;
  414. } else {
  415. Hr = fnTicket(szSR, NULL, DebugControl);
  416. }
  417. }
  418. DebugControl->Release();
  419. DebugClient->Release();
  420. return Hr;
  421. }
  422. HRESULT
  423. AddSrTicket(
  424. PTSTR szSR,
  425. PTSTR szDumpFile,
  426. PTSTR szSymbolPath,
  427. PTSTR szImagePath
  428. )
  429. {
  430. HRESULT Hr = E_FAIL;
  431. IDebugClient4 *DebugClient;
  432. IDebugControl3 *DebugControl;
  433. IDebugSymbols2 *DebugSymbols;
  434. IDebugSystemObjects3 *DebugSysObjects;
  435. RETRIVETICKET fnTicket;
  436. CHAR Buffer[MAX_PATH*2];
  437. CHAR szCabFile[MAX_PATH];
  438. if ((Hr = DebugCreate(__uuidof(IDebugClient),
  439. (void **)&DebugClient)) != S_OK) {
  440. fprintf(stderr, "Cannot initialize DebugClient\n");
  441. return Hr;
  442. }
  443. if ((DebugClient->QueryInterface(__uuidof(IDebugControl3),
  444. (void **)&DebugControl) != S_OK) ||
  445. (DebugClient->QueryInterface(__uuidof(IDebugSymbols2),
  446. (void **)&DebugSymbols) != S_OK) ||
  447. (DebugClient->QueryInterface(__uuidof(IDebugSystemObjects3),
  448. (void **)&DebugSysObjects) != S_OK)) {
  449. fprintf(stderr, "QueryInterface failed for DebugClient\n");
  450. return Hr;
  451. }
  452. DebugClient->SetOutputCallbacks(&g_OutputCallback);
  453. StringCbPrintf(Buffer, sizeof(Buffer),"Loading dump file %s\n", szDumpFile);
  454. g_OutputCallback.Output(-1, Buffer);
  455. if ((Hr = DebugClient->OpenDumpFile(szDumpFile)) != S_OK) {
  456. fprintf(stderr, "**** DebugClient cannot open DumpFile - error %lx\n", Hr);
  457. if (Hr == HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT)) {
  458. fprintf(stderr, "DumpFile is corrupt\n");
  459. }
  460. return Hr;
  461. }
  462. if (szSymbolPath) {
  463. DebugSymbols->SetSymbolPath(szSymbolPath);
  464. }
  465. if (szImagePath) {
  466. DebugSymbols->SetImagePath(szImagePath);
  467. }
  468. DebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
  469. DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "version", DEBUG_EXECUTE_DEFAULT);
  470. ULONG Class, Qual;
  471. if ((Hr = DebugControl->GetDebuggeeType(&Class, &Qual)) != S_OK) {
  472. Class = Qual = 0;
  473. }
  474. if (Class == DEBUG_CLASS_USER_WINDOWS) {
  475. //
  476. // User Mode dump
  477. //
  478. fprintf(stderr, "Usermode dumps are not handled\n");
  479. } else {
  480. //
  481. // Kernel Mode dump
  482. //
  483. CHAR ExtensionCmd[100];
  484. DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "!analyze -v", DEBUG_EXECUTE_DEFAULT);
  485. if (DebugControl->GetExtensionFunction(0, "FindSrInfo",
  486. (FARPROC*)&fnTicket) != S_OK) {
  487. fnTicket = NULL;
  488. }
  489. if (!fnTicket) {
  490. g_OutputCallback.Output(0, "Cannot find _EFN_FindSrInfo\n");
  491. Hr = E_FAIL;
  492. } else {
  493. g_OutputCallback.Output(0, "Checking if SR exists in DB\n");
  494. Hr = fnTicket(szSR, NULL, DebugControl);
  495. }
  496. // StringCchPrintf(ExtensionCmd, sizeof(ExtensionCmd), "!ticket %s", szSR);
  497. // if (DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, ExtensionCmd, DEBUG_EXECUTE_DEFAULT) == S_FALSE)
  498. if (Hr == S_FALSE) {
  499. if (_stricmp(szDumpFile + strlen(szDumpFile) - 4, ".cab")) {
  500. if ((Hr = CreateCabinetFromDump(szDumpFile, szCabFile,
  501. sizeof(szCabFile))) != S_OK) {
  502. g_OutputCallback.Output(0,"Could not cab the dump file\n");
  503. }
  504. } else {
  505. StringCbCopy(szCabFile, sizeof(szCabFile), szDumpFile);
  506. }
  507. g_OutputCallback.Output(0,"... uploading dump file to the server\n");
  508. UploadDumpFile(szCabFile, szSR);
  509. if (strcmp(szCabFile, szDumpFile)) {
  510. DeleteFile(szCabFile);
  511. }
  512. }
  513. }
  514. DebugSysObjects->Release();
  515. DebugControl->Release();
  516. DebugSymbols->Release();
  517. DebugClient->Release();
  518. return S_OK;
  519. }
  520. void
  521. __cdecl
  522. main (
  523. int Argc,
  524. PCHAR *Argv
  525. )
  526. {
  527. LONG arg;
  528. PCHAR DumpFileName = NULL;
  529. PCHAR SymbolPath = NULL;
  530. PCHAR ImagePath = NULL;
  531. PCHAR SR = NULL;
  532. g_AppName = Argv[0];
  533. for (arg = 1; arg < Argc; arg++) {
  534. if (Argv[arg][0] == '-' || Argv[arg][0] == '/') {
  535. switch (Argv[arg][1]) {
  536. case 'd':
  537. case 'D':
  538. if (++arg < Argc) {
  539. DumpFileName = Argv[arg];
  540. }
  541. break;
  542. case 's':
  543. case 'S':
  544. if (++arg < Argc) {
  545. SR = Argv[arg];
  546. }
  547. break;
  548. case 'i':
  549. case 'I':
  550. if (++arg < Argc) {
  551. ImagePath = Argv[arg];
  552. }
  553. break;
  554. case 'y':
  555. case 'Y':
  556. if (++arg < Argc) {
  557. SymbolPath = Argv[arg];
  558. }
  559. break;
  560. default:
  561. break;
  562. }
  563. }
  564. }
  565. if (!SR) {
  566. Usage();
  567. return;
  568. } else if (!DumpFileName) {
  569. RetriveSrTicket(SR);
  570. return;
  571. }
  572. if (SymbolPath == NULL) {
  573. SymbolPath = "SRV*";
  574. }
  575. AddSrTicket(SR, DumpFileName, SymbolPath, ImagePath);
  576. return;
  577. }