#include #include #include #include #include #include #include #include #include #define INITGUID #include #include #include #include "extsfns.h" #include #include #include #include "inetupld.h" PSTR g_AppName; PSTR g_ArchiveShare = NULL; // // Outputcallbacks for ticket // class DumpChkOutputCallbacks : public IDebugOutputCallbacks { public: // IUnknown. STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ); STDMETHOD_(ULONG, AddRef)( THIS ); STDMETHOD_(ULONG, Release)( THIS ); // IDebugOutputCallbacks. STDMETHOD(Output)( THIS_ IN ULONG Mask, IN PCSTR Text ); }; STDMETHODIMP DumpChkOutputCallbacks::QueryInterface( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ) { *Interface = NULL; if (IsEqualIID(InterfaceId, IID_IUnknown) || IsEqualIID(InterfaceId, IID_IDebugOutputCallbacks)) { *Interface = (IDebugOutputCallbacks *)this; AddRef(); return S_OK; } else { return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) DumpChkOutputCallbacks::AddRef( THIS ) { // This class is designed to be static so // there's no true refcount. return 1; } STDMETHODIMP_(ULONG) DumpChkOutputCallbacks::Release( THIS ) { // This class is designed to be static so // there's no true refcount. return 0; } STDMETHODIMP DumpChkOutputCallbacks::Output( THIS_ IN ULONG Mask, IN PCSTR Text ) { if (Text) fputs(Text, stdout); fflush(stdout); return S_OK; } DumpChkOutputCallbacks g_OutputCallback; DWORD WINAPI DisplayStatus( LPVOID Context ) { POCA_UPLOADFILE pUpload = (POCA_UPLOADFILE) Context; DWORD percent; while (1) { percent = pUpload->GetPercentComplete(); if (percent > 100) { fprintf(stderr, "Upload complete. \n"); return 1; } fprintf(stderr, "Uploading: %02ld%% done.\r", percent); Sleep(700); } return 1; } void UploadDumpFile( PSTR DumpFile, PSTR SR ) { HRESULT Hr = S_OK; WCHAR wszLocalDump[MAX_PATH] = {0}; WCHAR wszRemoteName[MAX_PATH] = {0}; WCHAR ResultUrl[MAX_PATH]; WCHAR IsapiUrl[MAX_PATH]; POCA_UPLOADFILE pUpload; HANDLE hThread = NULL; DWORD dwThreadId; PSTR FileExtension; FileExtension = DumpFile + strlen(DumpFile) - 4; if (_stricmp(FileExtension, ".cab")) { fprintf(stderr, "Please upload only the cab dump files.\n"); return; } if (!OcaUpldCreate(&pUpload)) { fprintf(stderr, "Cannot create UPLOAD object\n"); return; } if (!MultiByteToWideChar(CP_ACP,0, DumpFile, strlen(DumpFile), wszLocalDump, MAX_PATH)) { fprintf(stderr, "Cannot conver %s to widechar\n", DumpFile); Hr = E_FAIL; } if (SUCCEEDED(Hr)) { if ((Hr = pUpload->InitializeSession(L"910", wszLocalDump)) != S_OK ) { fprintf(stderr, "Initilaize Upload session failed %lx.\n", Hr); } } if (SUCCEEDED(Hr)) { if ((Hr = StringCbPrintfW(wszRemoteName, sizeof(wszRemoteName), L"/OCA/%S.cab", SR)) != S_OK) { fprintf(stderr, "Error in generating remote file name %lx \n", Hr); } } if (SUCCEEDED(Hr)) { hThread = CreateThread(NULL, 0, &DisplayStatus, (PVOID) pUpload, 0, &dwThreadId); if ((Hr = pUpload->SendFile(wszRemoteName, FALSE)) != S_OK) { fprintf(stderr, "Send dumpfile failed %lx.\n", Hr); } pUpload->UnInitialize(); } if (Hr == S_OK) { if ((Hr = StringCbPrintfW(IsapiUrl,sizeof( IsapiUrl ), L"/isapi/oca_extension.dll?id=%S.cab&Type=%ld&SR=%S", SR, 8, SR)) != S_OK) { fprintf(stderr, "Cannot build IsapiUrl string. %lx\n", Hr); } } if (SUCCEEDED(Hr)) { Hr = pUpload->GetUrlPageData(IsapiUrl, ResultUrl, sizeof(ResultUrl)); Sleep(700);// To let DisplayStatus finish if (Hr != S_OK) { fprintf(stderr, "Cannot isapi return URL %lx\n", Hr); } else { fprintf(stderr, "File succesfully uploaded as %s.cab\n", SR); fprintf(stderr, "Received response URL: %ws\n", ResultUrl); } } if (hThread && hThread != INVALID_HANDLE_VALUE) { TerminateThread(hThread, 1); CloseHandle(hThread); } pUpload->UnInitialize(); pUpload->Release(); return; } void Usage(void) { fprintf(stderr, "Usage: %s [-i ] [-y ] -s SR [-d ]\n", g_AppName); } HRESULT GetPasswdInput( LPWSTR wszPwd, ULONG PwdSize) { int err; DWORD mode; WCHAR Buff[51]; fprintf(stdout, "Enter Password to connect to archive server: "); GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode); SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), (~(ENABLE_ECHO_INPUT)) & mode); if (scanf("%50ws", Buff) == 0) { return E_FAIL; } SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode); fprintf(stdout, "\n"); return StringCbCopyW(wszPwd, PwdSize, Buff); } // // This add access to Share // HRESULT NetworkAccessShare( PSTR szShare, LPWSTR szPassword ) { USE_INFO_2 UseInfo; WCHAR wszShare[MAX_PATH], wszDomain[MAX_PATH], *pDir; if (MultiByteToWideChar(CP_ACP, 0, szShare, strlen(szShare)+1, wszShare, sizeof(wszShare)/sizeof(WCHAR)) == FALSE) { return E_FAIL; } StringCbCopyW(wszDomain, sizeof(wszDomain), &wszShare[2]); pDir = wcsrchr(wszDomain, L'\\'); if (pDir == NULL) { // bad share name return FALSE; } *pDir = 0; UseInfo.ui2_local = NULL; UseInfo.ui2_remote = wszShare; UseInfo.ui2_password = szPassword; UseInfo.ui2_username = L"OcaArchive"; UseInfo.ui2_domainname = wszDomain; UseInfo.ui2_asg_type = 0; UseInfo.ui2_status = 0; if (NetUseAdd(NULL, 2, (LPBYTE) &UseInfo, NULL) != NERR_Success) { return E_FAIL; } return S_OK; } // // Deletes any access granted to a remote share // HRESULT NetworkDeleteShare( void ) { WCHAR wszShare[MAX_PATH]; if (g_ArchiveShare == NULL) { return S_OK; } if (MultiByteToWideChar(CP_ACP, 0, g_ArchiveShare, strlen(g_ArchiveShare)+1, wszShare, sizeof(wszShare)/sizeof(WCHAR)) == FALSE) { return E_FAIL; } if (NetUseDel(NULL, wszShare, USE_NOFORCE) != NERR_Success) { return E_FAIL; } return S_OK; } // // This grants users archive access to OCA share for archiving dumps // BOOL AddArchiveAccess( PDEBUG_CLIENT4 Client, PDEBUG_CONTROL3 DebugControl, ULONG Qualifier ) { HMODULE Ext = NULL; EXT_TRIAGE_FOLLOWUP fnGetFollowup; DEBUG_TRIAGE_FOLLOWUP_INFO Info; CHAR szShare[MAX_PATH]; WCHAR Passwd[100]; PSTR szLookup1 = "debugger-params!archshare-k-full"; PSTR szLookup2 = "debugger-params!archshare-k-mini"; PSTR szLookup; if (DebugControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC*)&fnGetFollowup) != S_OK) { return FALSE; } if (Qualifier == DEBUG_DUMP_FULL) { szLookup = szLookup1; } else { szLookup = szLookup2; } Info.SizeOfStruct = sizeof(Info); Info.OwnerName = szShare; Info.OwnerNameSize = sizeof(szShare); if ((*fnGetFollowup)((PDEBUG_CLIENT) Client, szLookup, &Info) <= TRIAGE_FOLLOWUP_IGNORE) { return FALSE; } if (GetPasswdInput(Passwd, sizeof(Passwd)) != S_OK) { return FALSE; } // // Grant Access to szShare // if (NetworkAccessShare(szShare, Passwd) != S_OK) { return FALSE; } g_ArchiveShare = szShare; return TRUE; } HRESULT CreateCabinetFromDump( PCSTR DumpFile, PSTR CabFile, ULONG cbCabFile ) { HRESULT Status; CHAR TempFile[MAX_PATH]; PSTR Tail; Tail = strrchr(DumpFile, '\\'); if (Tail == NULL) { Tail = (PSTR) DumpFile; } else { ++Tail; } if (!GetTempPathA(cbCabFile, CabFile)) { StringCbCopy(CabFile, cbCabFile, ".\\"); } // Use the CAB name as the dump file name so the // name in the CAB will match. StringCbCat(CabFile, cbCabFile, Tail); StringCbCat(CabFile, cbCabFile, ".cab" ); fprintf(stdout, "\nCreating %s, this could take some time...\n", CabFile); fflush(stdout); if ((Status = CreateDumpCab(CabFile)) != S_OK) { fprintf(stderr, "Unable to create CAB, %s\n", FormatStatusCode(Status)); return Status; } else { // // add dump file. // Status = AddToDumpCab(DumpFile); CloseDumpCab(); } return S_OK; } typedef HRESULT (WINAPI * RETRIVETICKET)( PSTR szSR, PSTR szPath, PDEBUG_CONTROL3 DebugControl ); HRESULT RetriveSrTicket( PTSTR szSR ) { HRESULT Hr = S_OK; IDebugClient4 *DebugClient; IDebugControl3 *DebugControl; HMODULE Ext = NULL; RETRIVETICKET fnTicket; if ((Hr = DebugCreate(__uuidof(IDebugClient), (void **)&DebugClient)) != S_OK) { fprintf(stderr, "Cannot initialize DebugClient\n"); return Hr; } if ((DebugClient->QueryInterface(__uuidof(IDebugControl3), (void **)&DebugControl) != S_OK)) { fprintf(stderr, "QueryInterface failed for DebugClient\n"); return Hr; } DebugClient->SetOutputCallbacks(&g_OutputCallback); Ext = LoadLibrary("winext\\ext.dll"); if (!Ext) { fprintf(stderr,"Cannot load ext.dll.\n"); Hr = E_FAIL; } else { fnTicket = (RETRIVETICKET) GetProcAddress(Ext, "_EFN_FindSrInfo"); if (!fnTicket) { fprintf(stderr, "Cannot find _EFN_FindSrInfo\n"); Hr = E_FAIL; } else { Hr = fnTicket(szSR, NULL, DebugControl); } } DebugControl->Release(); DebugClient->Release(); return Hr; } HRESULT AddSrTicket( PTSTR szSR, PTSTR szDumpFile, PTSTR szSymbolPath, PTSTR szImagePath ) { HRESULT Hr = E_FAIL; IDebugClient4 *DebugClient; IDebugControl3 *DebugControl; IDebugSymbols2 *DebugSymbols; IDebugSystemObjects3 *DebugSysObjects; RETRIVETICKET fnTicket; CHAR Buffer[MAX_PATH*2]; CHAR szCabFile[MAX_PATH]; if ((Hr = DebugCreate(__uuidof(IDebugClient), (void **)&DebugClient)) != S_OK) { fprintf(stderr, "Cannot initialize DebugClient\n"); return Hr; } if ((DebugClient->QueryInterface(__uuidof(IDebugControl3), (void **)&DebugControl) != S_OK) || (DebugClient->QueryInterface(__uuidof(IDebugSymbols2), (void **)&DebugSymbols) != S_OK) || (DebugClient->QueryInterface(__uuidof(IDebugSystemObjects3), (void **)&DebugSysObjects) != S_OK)) { fprintf(stderr, "QueryInterface failed for DebugClient\n"); return Hr; } DebugClient->SetOutputCallbacks(&g_OutputCallback); StringCbPrintf(Buffer, sizeof(Buffer),"Loading dump file %s\n", szDumpFile); g_OutputCallback.Output(-1, Buffer); if ((Hr = DebugClient->OpenDumpFile(szDumpFile)) != S_OK) { fprintf(stderr, "**** DebugClient cannot open DumpFile - error %lx\n", Hr); if (Hr == HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT)) { fprintf(stderr, "DumpFile is corrupt\n"); } return Hr; } if (szSymbolPath) { DebugSymbols->SetSymbolPath(szSymbolPath); } if (szImagePath) { DebugSymbols->SetImagePath(szImagePath); } DebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE); DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "version", DEBUG_EXECUTE_DEFAULT); ULONG Class, Qual; if ((Hr = DebugControl->GetDebuggeeType(&Class, &Qual)) != S_OK) { Class = Qual = 0; } if (Class == DEBUG_CLASS_USER_WINDOWS) { // // User Mode dump // fprintf(stderr, "Usermode dumps are not handled\n"); } else { // // Kernel Mode dump // CHAR ExtensionCmd[100]; DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "!analyze -v", DEBUG_EXECUTE_DEFAULT); if (DebugControl->GetExtensionFunction(0, "FindSrInfo", (FARPROC*)&fnTicket) != S_OK) { fnTicket = NULL; } if (!fnTicket) { g_OutputCallback.Output(0, "Cannot find _EFN_FindSrInfo\n"); Hr = E_FAIL; } else { g_OutputCallback.Output(0, "Checking if SR exists in DB\n"); Hr = fnTicket(szSR, NULL, DebugControl); } // StringCchPrintf(ExtensionCmd, sizeof(ExtensionCmd), "!ticket %s", szSR); // if (DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, ExtensionCmd, DEBUG_EXECUTE_DEFAULT) == S_FALSE) if (Hr == S_FALSE) { if (_stricmp(szDumpFile + strlen(szDumpFile) - 4, ".cab")) { if ((Hr = CreateCabinetFromDump(szDumpFile, szCabFile, sizeof(szCabFile))) != S_OK) { g_OutputCallback.Output(0,"Could not cab the dump file\n"); } } else { StringCbCopy(szCabFile, sizeof(szCabFile), szDumpFile); } g_OutputCallback.Output(0,"... uploading dump file to the server\n"); UploadDumpFile(szCabFile, szSR); if (strcmp(szCabFile, szDumpFile)) { DeleteFile(szCabFile); } } } DebugSysObjects->Release(); DebugControl->Release(); DebugSymbols->Release(); DebugClient->Release(); return S_OK; } void __cdecl main ( int Argc, PCHAR *Argv ) { LONG arg; PCHAR DumpFileName = NULL; PCHAR SymbolPath = NULL; PCHAR ImagePath = NULL; PCHAR SR = NULL; g_AppName = Argv[0]; for (arg = 1; arg < Argc; arg++) { if (Argv[arg][0] == '-' || Argv[arg][0] == '/') { switch (Argv[arg][1]) { case 'd': case 'D': if (++arg < Argc) { DumpFileName = Argv[arg]; } break; case 's': case 'S': if (++arg < Argc) { SR = Argv[arg]; } break; case 'i': case 'I': if (++arg < Argc) { ImagePath = Argv[arg]; } break; case 'y': case 'Y': if (++arg < Argc) { SymbolPath = Argv[arg]; } break; default: break; } } } if (!SR) { Usage(); return; } else if (!DumpFileName) { RetriveSrTicket(SR); return; } if (SymbolPath == NULL) { SymbolPath = "SRV*"; } AddSrTicket(SR, DumpFileName, SymbolPath, ImagePath); return; }