I'm developing a COM dll which is an add-in to MSoffice. Since I'm not creating any logs within add-in I would like to add a crash report generator into my add-in.
Hopefully 'Minidump' would be the best choice, but I have never use Minidump inside a COM object.
I appreciate if somebody can point out possibilities of creating such crash dump with minidump
inside a COM object.
Thank You
I suspect you should be able to use the technique described here, create a minidump.
The actual implementation is
straightforward. The following is a
simple example of how to use
MiniDumpWriteDump.
#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>
int GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
{
BOOL bMiniDumpSuccessful;
WCHAR szPath[MAX_PATH];
WCHAR szFileName[MAX_PATH];
WCHAR* szAppName = L"AppName";
WCHAR* szVersion = L"v1.0";
DWORD dwBufferSize = MAX_PATH;
HANDLE hDumpFile;
SYSTEMTIME stLocalTime;
MINIDUMP_EXCEPTION_INFORMATION ExpParam;
GetLocalTime( &stLocalTime );
GetTempPath( dwBufferSize, szPath );
StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );
CreateDirectory( szFileName, NULL );
StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
szPath, szAppName, szVersion,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId());
hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
ExpParam.ThreadId = GetCurrentThreadId();
ExpParam.ExceptionPointers = pExceptionPointers;
ExpParam.ClientPointers = TRUE;
bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);
return EXCEPTION_EXECUTE_HANDLER;
}
void SomeFunction()
{
__try
{
int *pBadPtr = NULL;
*pBadPtr = 0;
}
__except(GenerateDump(GetExceptionInformation()))
{
}
}
Related
I am trying to enumerate the MFT to get list of file names.
This code works when used in a Win32 project:
MFT_ENUM_DATA med;
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = ujd.NextUsn;
BYTE pData[sizeof(DWORDLONG) + 0x10000];
DWORD cb;
while (DeviceIoControl(handleToVolume, FSCTL_ENUM_USN_DATA, &med, sizeof(med),
pData, sizeof(pData), &cb, NULL) != FALSE) {
//do the processing
}
But when I use the same code in C++/CLI, DeviceIoControl gives false and GetLastError gives ERROR_INVALID_FUNCTION.
When the same code is translated into C#, it works.
Any idea what is happening?
check if you have this define:
#define FSCTL_ENUM_USN_DATA
CTL_CODE(FILE_DEVICE_FILE_SYSTEM,44,METHOD_NEITHER,FILE_READ_DATA)
and replace FILE_READ_DATA with FILE_ANY_ACCESS
I am using this win32 based C program to change the target of a shortcut from
["C:\Program Files\YP\YPseries\Bin\myexe.exe"] to
["C:\Program Files\YP\YPseries\Bin\myexe.exe" -Start UDCDevicePage]
excluding the square braces.
However when i use
WCHAR newTargetPath[] = L"\"C:\Program Files\YP\YP series\Bin\myexe.exe\" -Start UDCDevicePage";
in main, SetPath returns an E_INVALIDARG error code.
How can i pass an argument to myexe using IShellLink::SetPath function?
The program is given below:
HRESULT changeLinkTarget(LPCSTR pathLink, LPWSTR newTargetPath)
{
HRESULT hres;
IShellLink* psl;
WCHAR szGotPath[MAX_PATH];
WIN32_FIND_DATA wfd;
// Get a pointer to the IShellLink interface.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Get a pointer to the IPersistFile interface.
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (SUCCEEDED(hres))
{
WCHAR wsz[MAX_PATH];
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, pathLink, -1, wsz, MAX_PATH);
// Load the shortcut.
hres = ppf->Load(wsz, STGM_READ);
if (SUCCEEDED(hres))
{
// Get the path to the link target.
hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH);
if (SUCCEEDED(hres))
{
hres = psl->SetPath(newTargetPath);
hres = ppf->Save(wsz, TRUE); //save changes
}
else
{
// Handle the error
}
}
// Release the pointer to the IPersistFile interface.
ppf->Release();
}
// Release the pointer to the IShellLink interface.
psl->Release();
}
return hres;
}
int _tmain(int argc, _TCHAR* argv[])
{
char linkPath[128] = "C:\\Users\\Public\\Desktop\\YP series.lnk";
WCHAR newTargetPath[] = L"\"C:\\Program Files\\YP\\YP series\\Bin\\myexe.exe\" -Start UDCDevicePage";
CoInitialize(NULL); // initialize the COM subsystem
HRESULT ret = changeLinkTarget(linkPath, newTargetPath);
return 0;
}
Paths are usually just an exe; you seem to be trying to set the path to be an executable with some command-line args. Try instead using SetPath to just the exe - without the extra quotes - and use IShellLink::SetArguments() for the command-line parameters. SetPath is perhaps attempting to validate the param by checking that an exe with the name of the full string you pass it exists, which is likely failing causing the error.
I am trying to code an alternative to LoadLibrary function, based on the idea of calling the function LdrLoadDll from ntdll.
This function needs as a parameter the dll file to load, in a UNICODE_STRING format.
I really can't get what I am doing wrong here (string seems to be correctly initialized), but when LdrLoadDll is called, I get the following error:
Unhandled exception in "Test.exe" (NTDLL.DLL): 0xC0000005: Access Violation.
I use Visual C++ 6.0 for this test, and I am using Windows 7 64 bit.
I post full code here, thanks in advance for any help:
#include <Windows.h>
typedef LONG NTSTATUS; //To be used with VC++ 6, since NTSTATUS type is not defined
typedef struct _UNICODE_STRING { //UNICODE_STRING structure
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef NTSTATUS (WINAPI *fLdrLoadDll) //LdrLoadDll function prototype
(
IN PWCHAR PathToFile OPTIONAL,
IN ULONG Flags OPTIONAL,
IN PUNICODE_STRING ModuleFileName,
OUT PHANDLE ModuleHandle
);
/**************************************************************************
* RtlInitUnicodeString (NTDLL.#)
*
* Initializes a buffered unicode string.
*
* RETURNS
* Nothing.
*
* NOTES
* Assigns source to target->Buffer. The length of source is assigned to
* target->Length and target->MaximumLength. If source is NULL the length
* of source is assumed to be 0.
*/
void WINAPI RtlInitUnicodeString(
PUNICODE_STRING target, /* [I/O] Buffered unicode string to be initialized */
PCWSTR source) /* [I] '\0' terminated unicode string used to initialize target */
{
if ((target->Buffer = (PWSTR) source))
{
unsigned int length = lstrlenW(source) * sizeof(WCHAR);
if (length > 0xfffc)
length = 0xfffc;
target->Length = length;
target->MaximumLength = target->Length + sizeof(WCHAR);
}
else target->Length = target->MaximumLength = 0;
}
NTSTATUS LoadDll( LPCSTR lpFileName)
{
HMODULE hmodule = GetModuleHandleA("ntdll.dll");
fLdrLoadDll _LdrLoadDll = (fLdrLoadDll) GetProcAddress ( hmodule, "LdrLoadDll" );
int AnsiLen = lstrlenA(lpFileName);
BSTR WideStr = SysAllocStringLen(NULL, AnsiLen);
::MultiByteToWideChar(CP_ACP, 0, lpFileName, AnsiLen, WideStr, AnsiLen);
UNICODE_STRING usDllFile;
RtlInitUnicodeString(&usDllFile, WideStr); //Initialize UNICODE_STRING for LdrLoadDll function
::SysFreeString(WideStr);
NTSTATUS result = _LdrLoadDll(NULL, LOAD_WITH_ALTERED_SEARCH_PATH, &usDllFile,0); //Error on this line!
return result;
}
void main()
{
LoadDll("Kernel32.dll");
}
in
_LdrLoadDll(NULL, LOAD_WITH_ALTERED_SEARCH_PATH, &usDllFile,0);
last parameter can't be zero
you can't call SysFreeString before you call _LdrLoadDll,
since the usDllFile.buffer parameter points to this string
i have create one class and i need to use it with vector.
ref class Mur
{
public:
int debutX, debutY;
int finX, finY;
Mur (){}
Mur(int debutX, int debutY) {
this->debutX = debutX;
this->debutY = debutY;
finX = 0;
finY = 0;
}
~Mur()
{
}
int getX() { return debutX; }
int getY() { return debutY; }
bool estFinit() {
return (finX==0);
}
void finir(int x, int y){
finX = x;
finY = y;
}
};
}
When i try to use it
std::vector<Mur^> vMurs;
...
vMurs.push_back(gcnew Mur(i,j));
Error come in file "xmemory" at line 52 but i don't know this file xD
The compiler is objecting because you're trying to store a managed object in an unmanaged class. That cannot work, the garbage collector needs to be able to find object references so it can properly collect garbage. And since it cannot find unmanaged objects, it cannot find the managed reference either.
I'd strongly advice to not use STL/CLR, it combines all the disadvantages of STL with those of the CLR. If you really, really want to use vector<> then gcroot<> can solve the problem. However, using System::Collections::Generic::List<> is by far the best solution.
using namespace System::Collections::Generic;
...
List<Mur^>^ vMurs = gcnew List<Mur^>;
...
vMurs->Add(gcnew Mur(i, j));
I agree with Alexandre C. If you want to use a vector, you could use the STL/CLR (http://msdn.microsoft.com/en-us/library/bb385954.aspx) vector.
Try using
std::vector<gcroot<Mur ^> > vMurs;
...
vMurs.push_back(gcnew Mur(i,j));
Here is a code snippet
#include "stdafx.h"
#include <tchar.h>
#include <windows.h>
#include <dshow.h>
#include <ExDisp.h>
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
HRESULT hr = S_OK;
DWORD err = 0;
// Try to create graph builder
IGraphBuilder* pGraph = 0;
hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph );
err = GetLastError();
// Here, hr is E_ACCESSDENIED
// err is 5 (ERROR_ACCESS_DENIED)
// Try to create capture graph builder (succeeds)
ICaptureGraphBuilder2* pBuild = 0;
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuild );
err = GetLastError();
// Here, hr is S_OK
// err is 0 (ERROR_SUCCESS)
// Try to create IWebBrowser (succeeds)
IWebBrowser2* pBrowser = 0;
hr = CoCreateInstance (CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (LPVOID *)&pBrowser);
err = GetLastError();
// Here, hr is S_OK
// err is 0 (ERROR_SUCCESS)
return 0;
}
I'm trying to create IFilterGraph, which fails with E_ACCESSDENIED. On the other hand, creating other directshow objects works ok. The same with some other COM objects (tried with IWebBrowser2 as an example). Any idea what can be the problem? Thanks!
Well, that doesn't look good. It is the result of a Windows security problem. This would not normally fail, the coclass lives in c:\windows\system32\quartz.dll. There are many possible operations that could cause the failure, including having trouble reading the registry and loading the DLL.
Perhaps the best way to troubleshoot it is to use SysInternals' ProcMon and observe your program's actions. Pay attention to the Result column, you should see the error there. This ought to get you closer to finding out what security configuration problem might be the source.