I have created my own debugger application. It attaches to a process and creates a crash dump file. That works most of the time. The problem I have is that it will not work when the application being debugged is waiting for a mutex object (and this is the very problem that I want to debug).
Furthermore, I have created a simple test.exe application that just loops around and calls Sleep(100) but my debugger fails when it calls MiniDumpWriteDump on this application every time.
What am I doing wrong?
The error code I get returned from the code below is 2147942699 (0x8007012b)
void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
CONTEXT c;
memset( &c, 0, sizeof( c ) );
GetThreadContext( hThread, &c );
EXCEPTION_POINTERS ep;
memset( &ep, 0, sizeof( ep ) );
ep.ContextRecord = &c;
ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;
MINIDUMP_EXCEPTION_INFORMATION minidump_exception;
memset( &minidump_exception, 0, sizeof( minidump_exception ) );
minidump_exception .ThreadId = dwThreadId;
minidump_exception.ExceptionPointers = &ep;
minidump_exception.ClientPointers = true;
char txDumpPath[ MAX_PATH + 1 ];
sprintf( txDumpPath, "%s.dmp", txProcess );
HANDLE hFile = CreateFile( txDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile )
{
BOOL fSuccess;
SetLastError( 0L );
int nDumpOptions =
MiniDumpNormal
| MiniDumpWithDataSegs
| MiniDumpWithFullMemory
| MiniDumpWithHandleData
| MiniDumpFilterMemory
| MiniDumpScanMemory
| MiniDumpWithUnloadedModules
| MiniDumpWithIndirectlyReferencedMemory
| MiniDumpFilterModulePaths
| MiniDumpWithProcessThreadData
| MiniDumpWithPrivateReadWriteMemory
| MiniDumpWithoutOptionalData
;
fSuccess = MiniDumpWriteDump( hProcess,
dwProcessId,
hFile,
(MINIDUMP_TYPE) nDumpOptions,
&minidump_exception,
NULL,
NULL );
DWORD dwErr = GetLastError();
if( ! fSuccess )
printf( "MiniDumpWriteDump -FAILED (LastError:%u)\n", dwErr );
CloseHandle( hFile );
}
}
I have also tried increasing the privileges with the following code snippet which I borrowed from somebody else who seemed to have a similar problem:
BOOL SetDumpPrivileges()
{
BOOL fSuccess = FALSE;
HANDLE TokenHandle = NULL;
TOKEN_PRIVILEGES TokenPrivileges;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&TokenHandle))
{
printf("Could not get the process token");
goto Cleanup;
}
TokenPrivileges.PrivilegeCount = 1;
if (!LookupPrivilegeValue(NULL,
SE_DEBUG_NAME,
&TokenPrivileges.Privileges[0].Luid))
{
printf("Couldn't lookup SeDebugPrivilege name");
goto Cleanup;
}
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//Add privileges here.
if (!AdjustTokenPrivileges(TokenHandle,
FALSE,
&TokenPrivileges,
sizeof(TokenPrivileges),
NULL,
NULL))
{
printf("Could not revoke the debug privilege");
goto Cleanup;
}
fSuccess = TRUE;
Cleanup:
if (TokenHandle)
{
CloseHandle(TokenHandle);
}
return fSuccess;
}
I posted a question on MSDN and somebody kindly provided me the answer to my problem. Here's the link to the discussion, and the working code snippet I've copied below.
void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
CONTEXT c;
memset( &c, 0, sizeof( c ) );
HANDLE hThread;
c.ContextFlags = CONTEXT_FULL;
hThread = _OpenThread( THREAD_ALL_ACCESS, FALSE, dwThreadId );
GetThreadContext( hThread, &c );
EXCEPTION_POINTERS ep;
memset( &ep, 0, sizeof( ep ) );
ep.ContextRecord = &c;
ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;
MINIDUMP_EXCEPTION_INFORMATION minidump_exception;
memset( &minidump_exception, 0, sizeof( minidump_exception ) );
minidump_exception.ThreadId = dwThreadId;
minidump_exception.ExceptionPointers = &ep;
minidump_exception.ExceptionPointers->ContextRecord = &c;
minidump_exception.ClientPointers = false;
char txDumpPath[ MAX_PATH + 1 ];
time_t tNow = time( NULL );
struct tm *pTm = localtime( &tNow );
sprintf( txDumpPath, "%s.%02d%02d%04d_%02d%02d%02d.dmp",
txProcess,
pTm->tm_mday,
pTm->tm_mon,
pTm->tm_year,
pTm->tm_hour,
pTm->tm_min,
pTm->tm_sec );
HANDLE hFile = CreateFile( txDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
BOOL fSuccess;
printf( "hProcess : %d (0x%x)\n", hProcess, hProcess );
printf( "dwProcessId: %u (0x%lx)\n", dwProcessId, dwProcessId );
printf( "dwThreadId : %u (0x%lx)\n", dwThreadId, dwThreadId );
SetLastError( 0L );
fSuccess = MiniDumpWriteDump( hProcess,
dwProcessId,
hFile,
MiniDumpNormal,
&minidump_exception,
NULL,
NULL );
DWORD dwErr = GetLastError();
if( ! fSuccess )
{
printf( "MiniDumpWriteDump -FAILED (LastError:%u)\n", dwErr );
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
// Display the string.
printf( "%s\n", (LPCTSTR)lpMsgBuf );
// Free the buffer.
LocalFree( lpMsgBuf );
}
}
if( hThread )
CloseHandle( hThread );
}
Is this problem the same one as the other question I answered with this text?
Does it not include the mutex information even with flag MiniDumpWithHandleData, also it is possibly failing because some of the flags may not be compatible with the version of DebugHlp.dll you are calling against see: here
Related
I'm using MS visual c++ 2010 express to write a notepad program. I need to be able to save files from my tabbed interface ( each edit control is stored into a vector ). I can't seem to figure out how to save, depending on which edit control is visible to the user ( active tab ). Everything I've tried so far either doesn't save the contents or only saves from the first edit control. When the user adds a new file to the tabbed interface, it added that edit control to the back of the vector. This is my latest attempt:
std::vector<HWND>vect;
BOOL SaveTextFileFromEdit( HWND hEdit, LPCTSTR pszFileName )
{
HANDLE hFile;
BOOL bSuccess = FALSE;
hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
DWORD dwTextLength = GetWindowTextLength( hEdit );
if( dwTextLegth > 0 )
{
DWORD dwBufferSize = dwTextLength + 1;
LPSTR pszText = ( LPSTR )GlobalAlloc( GPTR, dwBufferSize );
if( pszText != NULL )
{
if( GetWindowText( hEdit, pszText, dwBufferSize ) )
{
DWORD dwWritten;
if( WriteFile( hFile, pszText, dwTextLength, &dwWritten, NULL ) )
bSuccess = TRUE;
}
GlobalFree( pszText );
}
}
CloseHandle( hFile );
}
return bSuccess;
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case ID_FILE_SAVEAS:
{
OPENFILENAME ofn;
char szFileName[ MAX_PATH ] = "";
ZeroMemory( &ofn, sizeof( ofn ) );
ofn.lStructSize = sizeof( ofn );
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = "txt";
ofn.flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
if( GetSaveFileName( &ofn ) )
{
HWND hEdit, hTabs;
hTabs = GetDlgItem( hwnd, IDC_MAIN_TAB );
int curTab = TabCtrl_GetCurSel( hTabs );
hEdit = GetDlgItem( hTabs, IDC_MAIN_EDIT );
// This is what i did have: hEdit = GetDlgItem( vect[ curTab ], IDC_MAIN_EDIT );
// Which wasn't saving anything
if( SaveTextFileFromEdit( hEdit, szFileName ) )
{
// EVERYTHING IS GOOD
}
}
}
break;
}
break;
}
return 0;
}
If the vector has each edit control's HWND then you don't need GetDlgItem at all: You already have the HWND that it would return.
hEdit = vect[ curTab ];
First of all some parts of the code are from Calling function in injected DLL but somewhere it doesn't work.
I have a question regarding DLL Injection: after I loaded the library into another process:
HANDLE InjectDLL(DWORD ProcessID, char *dllName)
{
HANDLE Proc;
char buf[50]={0};
LPVOID RemoteString, LoadLibAddy;
if(!ProcessID)
return NULL;
Proc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, ProcessID);
if(!Proc)
{
sprintf(buf, "OpenProcess() failed: %d", GetLastError());
MessageBox(NULL, buf, "Loader", NULL);
return NULL;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(dllName), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, dllName, strlen(dllName), NULL);
HANDLE hThread = CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
if( hThread != 0 ) {
WaitForSingleObject( hThread, INFINITE );
GetExitCodeThread( hThread, ( LPDWORD )&hInjected );
CloseHandle( hThread );
}
CloseHandle(Proc);
return hThread != 0 ? Proc : NULL;
}
I wanted to call a function from inside that space:
void* GetPayloadExportAddr( LPCSTR lpPath, HMODULE hPayloadBase, LPCSTR lpFunctionName )
{
// Load payload in our own virtual address space
HMODULE hLoaded = LoadLibrary( lpPath );
if( hLoaded == NULL ) {
return NULL;
} else {
void* lpFunc = GetProcAddress( hLoaded, lpFunctionName );
DWORD dwOffset = (char*)lpFunc - (char*)hLoaded;
FreeLibrary( hLoaded );
return (void*)((DWORD)hPayloadBase + dwOffset);
}
}
BOOL InitPayload( HANDLE hProcess, LPCSTR lpPath, HMODULE hPayloadBase)
{
void* lpInit = GetPayloadExportAddr( lpPath, hPayloadBase, "Start" );
if( lpInit == NULL ) {
return FALSE;
}
else {
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)lpInit, (LPVOID) NULL, 0, NULL );
if( hThread == NULL ) {
return FALSE;
}
else {
CloseHandle( hThread );
}
}
return TRUE;
}
The GetPayloadExportAddr returns the Current Location from IDA (i guess that is the space where my function starts).
So the problem is at the InitPayload function when I try to create the new thread, it fails to do so and I don't know why.
My dll is the following:
extern "C"
{
__declspec(dllexport) void* Start(LPVOID param)
{
MessageBox(NULL, L"Start", L"Hello", MB_OK);
return NULL;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
The thing is if I put the Start method at DLL_PROCESS_ATTACH it works, but otherwise it doesn't.
Your GetPayloadExportAddr() returns the address of the function in your local process. This address will not be the same in other processes if the base address of the module is different, which is common with DLL files which can be relocated if their PreferredImageBase is not available.
You should modify your GetPayloadExportAddr() function to return the offset. Then get the address of the module in the target process. Add these two together and that is the correct address for you to call in the target process.
I try to simulate fork using ZwCreateProcess. It seems to work when I
use some simple test program. But when I try to create a new process
using CreateProcess API in the forked child process. The child process
paused for a while (and so did parent process) and then crashed.
Could you give me some hint?
The following are the test code and fork reference implementation code:
/*****************************************************/
Test program code fragment:
if ((pid = fork()) < 0) {
printf("fork error");
return -1;
}
if (pid == 0) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &pi, sizeof(pi) );
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
//Child process will pause here for a while and then crash.
if(CreateProcess(_T("C:\\Windows\\notepad.exe"), NULL, NULL, NULL,
FALSE, 0, NULL, NULL, &si, &pi))
{
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}else{
// fputs("cann't create process", fp2);
}
}else{
//Parent code
}
/*****************************************************************************************************/
And the following is what I used the reference fork implementation code from internet:
int win32_fork()
{
HANDLE hProcess = 0;
HANDLE hThread = 0;
BOOL bReturn;
InheritAll();
OBJECT_ATTRIBUTES oa = {sizeof oa};
ZwCreateProcess(&hProcess, PROCESS_ALL_ACCESS, &oa,
0, 0, NULL, NULL, NULL);
CONTEXT context = {CONTEXT_FULL
| CONTEXT_DEBUG_REGISTERS
| CONTEXT_FLOATING_POINT};
ZwGetContextThread(NtCurrentThread(), &context);
context.Eip = ULONG(child);
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory( &mbi, sizeof( mbi ) );
ZwQueryVirtualMemory(NtCurrentProcess(), PVOID(context.Esp),
MemoryBasicInformation, &mbi, sizeof mbi,
0);
USER_STACK stack = {0, 0, PCHAR(mbi.BaseAddress) + mbi.RegionSize,
mbi.BaseAddress, mbi.AllocationBase};
CLIENT_ID cid;
ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa,
hProcess, &cid, &context, &stack, TRUE);
THREAD_BASIC_INFORMATION tbi;
ZeroMemory( &tbi, sizeof( tbi ) );
ZwQueryInformationThread(NtCurrentThread(),
ThreadBasicInformation,
&tbi, sizeof tbi, 0);
PNT_TIB tib = (PNT_TIB)tbi.TebBaseAddress;
ZwQueryInformationThread(hThread, ThreadBasicInformation,
&tbi, sizeof tbi, 0);
ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress,
&tib->ExceptionList, sizeof tib->ExceptionList,
0);
InformCsrss(hProcess, hThread,
ULONG(cid.UniqueProcess), ULONG(cid.UniqueThread));
ZwResumeThread(hThread, 0);
ZwClose(hThread);
ZwClose(hProcess);
return int(cid.UniqueProcess);
}
I am trying to make a small system tray program with only a context menu as its GUI.
However, I cannot get the tooltip to work. I properly setup NOTIFYICONDATA's szTip and everything else seems to work...what is preventing the tooltip from showing on mouseover?
void main()
{
int result;
hinst = GetModuleHandle( NULL );
memset( &wnd, 0, sizeof( wnd ) );
wnd.cbSize = sizeof( wnd );
wnd.lpszClassName = "MainWClass";
wnd.lpfnWndProc = MainWProc;
wnd.hInstance = hinst;
result = RegisterClassEx( &wnd );
hwnd = CreateWindowEx
(
0, //extended styles
wnd.lpszClassName, //class name
"Main Window", //window name
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZEBOX, //style tags
CW_USEDEFAULT, //horizontal position
CW_USEDEFAULT, //vertical position
CW_USEDEFAULT, //width
CW_USEDEFAULT, //height
(HWND) NULL, //parent window
(HMENU) NULL, //class menu
(HINSTANCE) wnd.hInstance, //some HINSTANCE pointer
NULL //Create Window Data?
);
nid.cbSize = sizeof( nid );
nid.hWnd = hwnd;
nid.uID = 1;
nid.uVersion = NOTIFYICON_VERSION_4;
nid.uCallbackMessage = WM_CONTEXTMENU;
nid.hIcon = LoadIcon( hinst, MAKEINTRESOURCE( IDI_ICON1 ) );
strcpy( nid.szTip, "My Tooltip!" );
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
if( ! Shell_NotifyIcon( NIM_ADD, &nid ) )
{
printf("Shell_NotifyIcon( NIM_ADD, &nid ) failed.\r\n");
Sleep( INFINITE );
}
if( ! Shell_NotifyIcon( NIM_SETVERSION, &nid ) )
{
printf("Shell_NotifyIcon( NIM_SETVERSION, &nid ) failed.\r\n");
Sleep( INFINITE );
}
UpdateWindow( hwnd );
while( true )
{
//Dispatch for main window
if( PeekMessage( &msg, hwnd, NULL, NULL, PM_REMOVE ) )
{
DispatchMessage( &msg );
}
}
}
try adding the NIF_SHOWTIP flag, according to MSDN, NOTIFYICON_VERSION_4 requires that the tooltip be userdrawn.
I am working on getting the device id from the usb device i plug...
The above application works on win-Xp but not in Windows 7
When i try to figure it i found that CM_Get_Parent () not works...
can anybody please guide me on why its not working ...and is there any compatible function which can work on windows 7
source code:
HDEVINFO hDevInfo;
GUID guid;
BYTE buffer[ 1024 ];
DWORD dwRequiredSize ;
WCHAR buf[ 1024 ];
DEVINST devInstParent;
WCHAR volume[1024];
int aLength, anIndex;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
SP_DEVINFO_DATA devInfoData;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetail;
guid = GUID_DEVINTERFACE_VOLUME;
hDevInfo = SetupDiGetClassDevs( &guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
if( hDevInfo == INVALID_HANDLE_VALUE )
{
qDebug() << "Error - SetupDiGetClassDevs failed\n";
}
for( DWORD dwIndex = 0;; dwIndex ++ )
{
ZeroMemory( &devInterfaceData, sizeof( devInterfaceData ) );
devInterfaceData.cbSize = sizeof(devInterfaceData );
if( !SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &guid,dwIndex, &devInterfaceData ) )
{
break;
}
ZeroMemory( &devInfoData, sizeof( devInfoData ) );
devInfoData.cbSize = sizeof(devInfoData);
pDevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer;
pDevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA );
// Get device interface detail data to get Device Instance from
// SP_DEVINFO_DATA and Device Path from SP_DEVICE_INTERFACE_DETAIL_DATA
SetupDiGetDeviceInterfaceDetail(
hDevInfo,&devInterfaceData,
pDevDetail, // SP_DEVICE_INTERFACE_DETAIL_DATA
1024,&dwRequiredSize,&devInfoData ); // SP_DEVINFO_DATA
CM_Get_Parent( &devInstParent,devInfoData.DevInst, 0 );
CM_Get_Parent( &devInstParent,devInstParent, 0 );
CM_Get_Device_ID( devInstParent, buf, 1024,0 );
}
The following a litle modified code
#include <Windows.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <tchar.h>
#include <stdio.h>
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
#pragma comment (lib, "setupapi.lib")
int main()
{
HDEVINFO hDevInfo;
GUID guid;
BYTE buffer[ 1024 ];
DWORD dwRequiredSize ;
DEVINST devInstParent;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
SP_DEVINFO_DATA devInfoData;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetail;
CONFIGRET status;
TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN];
BOOL bSuccess;
guid = GUID_DEVINTERFACE_VOLUME;
hDevInfo = SetupDiGetClassDevs( &guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
if( hDevInfo == INVALID_HANDLE_VALUE ) {
return 1;
}
for( DWORD dwIndex = 0;; dwIndex ++ ) {
ZeroMemory( &devInterfaceData, sizeof( devInterfaceData ));
devInterfaceData.cbSize = sizeof( devInterfaceData );
if( !SetupDiEnumDeviceInterfaces( hDevInfo, NULL, &guid, dwIndex, &devInterfaceData ) ) {
DWORD dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_NO_MORE_ITEMS)
break;
else
return 1; // ERROR!!!
}
ZeroMemory( &devInfoData, sizeof( devInfoData ) );
devInfoData.cbSize = sizeof( devInfoData);
pDevDetail = ( PSP_DEVICE_INTERFACE_DETAIL_DATA )buffer;
pDevDetail->cbSize = sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA );
// Get device interface detail data to get Device Instance from
// SP_DEVINFO_DATA and Device Path from SP_DEVICE_INTERFACE_DETAIL_DATA
bSuccess = SetupDiGetDeviceInterfaceDetail( hDevInfo,&devInterfaceData,
pDevDetail,// SP_DEVICE_INTERFACE_DETAIL_DATA
sizeof(buffer),&dwRequiredSize,&devInfoData ); // SP_DEVINFO_DATA
status = CM_Get_Device_ID (devInfoData.DevInst, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
if (status == CR_SUCCESS) {
_tprintf (TEXT("%s\n"), szDeviceInstanceID);
}
status = CM_Get_Parent( &devInstParent,devInfoData.DevInst, 0 );
if (status == CR_SUCCESS) {
status = CM_Get_Device_ID (devInstParent, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
if (status == CR_SUCCESS)
_tprintf (TEXT(" %s\n"), szDeviceInstanceID);
status = CM_Get_Parent( &devInstParent,devInstParent, 0 );
if (status == CR_SUCCESS) {
status = CM_Get_Device_ID( devInstParent, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
if (status == CR_SUCCESS) {
_tprintf (TEXT(" %s\n"), szDeviceInstanceID);
}
}
else {
continue;
}
}
else {
continue;
}
}
}
work without any problem on my Windows 7 computer and produce output like following:
SCSI\CDROM&VEN_ELBY&PROD_CLONEDRIVE&REV_1.4\1&2AFD7D61&0&000000
ROOT\SCSIADAPTER\0000
HTREE\ROOT\0
STORAGE\VOLUME\{21C004DA-0EB2-11DF-8C02-806E6F6E6963}#0000000000100000
ROOT\VOLMGR\0000
HTREE\ROOT\0
STORAGE\VOLUME\{21C004DA-0EB2-11DF-8C02-806E6F6E6963}#000000004B100000
ROOT\VOLMGR\0000
HTREE\ROOT\0
STORAGE\VOLUME\{21C004DA-0EB2-11DF-8C02-806E6F6E6963}#00000037C7A00000
ROOT\VOLMGR\0000
HTREE\ROOT\0
UPDATED based on the comment: On my Windows XP in the VMware the same utility produce the following output
FDC\GENERIC_FLOPPY_DRIVE\6&1435B2E2&0&0
ACPI\PNP0700\5&324D5432&0
ACPI\PNP0A05\4&5289E18&0
IDE\CDROMNECVMWAR_VMWARE_IDE_CDR10_______________1.00____\3031303030303030303030303030303030303130
PCIIDE\IDECHANNEL\4&23686003&0&1
PCI\VEN_8086&DEV_7111&SUBSYS_197615AD&REV_01\3&61AAA01&0&39
STORAGE\VOLUME\1&30A96598&0&SIGNATURE91929192OFFSET7E00LENGTH1FFD5AA00
ROOT\FTDISK\0000
HTREE\ROOT\0
Of cause it is another computer (a virtual computer) on the other operation system and we receive another list of devices. You current question was to make the function CM_Get_Parent() working on both Windows XP and Windows 7. The posted code do this like we can see. Or it is now work correctly on your Windows XP or Windows 7 computer?
How to get pid and vid (product id and ventor id) I described in Get information about disk drives result on windows7 - 32 bit system, but for any drive letters and not for the volume devices. One can easy change the code to show more information like Volume name, Bus name and other information. But this all is already another question.
UPDATED: I placed the extended version of program from Get information about disk drives result on windows7 - 32 bit system under http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.c because of restriction with the message size in stackoverflow.com. The test output looks like http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.txt