I have installed a HP Printer and added it to my list of Printer devices.
I am trying to use the following code:
QString printerName = "HP Designjet 500 24+HPGL2 Card";
DWORD infoSize, numBytes;
HANDLE hPrinter;
bool ok = OpenPrinter( ( LPWSTR )printerName.utf16(), ( LPHANDLE )&hPrinter, 0 );
if ( !ok )
{
qErrnoWarning( "QWin32PrintEngine::initialize: OpenPrinter failed" );
return;
}
GetPrinter( hPrinter, 2, NULL, 0, &infoSize );
HGLOBAL hMem;
hMem = GlobalAlloc( GHND, infoSize );
PRINTER_INFO_2 *pInfo;
pInfo = ( PRINTER_INFO_2* )GlobalLock( hMem );
ok = GetPrinter( hPrinter, 2, ( LPBYTE )pInfo, infoSize, &numBytes );
if ( !ok )
{
qErrnoWarning( "QWin32PrintEngine::initialize: GetPrinter failed" );
}
DEVMODE *devMode;
devMode = pInfo->pDevMode;
HDC hdc = NULL;
hdc = CreateDC( NULL, ( LPCWSTR )printerName.utf16(), 0, devMode );
Now,the CreateDC() method fails.I even tried to return the Error using GetLastError() method, and it returned as "203",which corresponds to "ERROR_ENVVAR_NOT_FOUND".
I am completely clueless as of now.
I would be really glad,if someone can help me regarding this.
Thanks in Advance.
I want to run netstat -ano command using popen.
And I want to show the result of executing the command through MFC List Control.
Run the following code from the win32 console project and it will run correctly.
However, if run it on MFC project, popen("netstat -ano *.c","r") result is null.
The development environment is VC6.0.
Please let me know why null is coming. Thank you :)
FILE *fp = NULL;
char line[10240];
char* network[5];
int nIndexNetwork = 0;
if( (fp=popen("netstat -ano *.c","r")) == NULL)
{
printf("[%d:%s]\n", errno, strerror(errno));
CString str;
str.Format("%d",errno);
GetDlgItem(IDC_EDIT1)->SetWindowText(str);
return 1;
}
while(fgets(line, 10240, fp) != NULL)
{
char *word = strtok(line, " ");
while (word != NULL) // 자른 문자열이 나오지 않을 때까지 반복
{
network[nIndexNetwork] = word;
nIndexNetwork++;
printf("%s\n", network[nIndexNetwork-1]); // 자른 문자열 출력
word = strtok(NULL, " "); // 다음 문자열을 잘라서 포인터를 반환
}
nIndexNetwork = 0;
m_ctlList_network.AddItem(network[4],
network[0],
network[1],
network[2],
network[3]);
}
pclose(fp);
return 0;
It does not look like popen will work in a Win32 app. You will have to use, Creating a Child Process with Redirected Input and Output. I have used this example to get the output of a process and display it in MFC. It is not as simple as popen, but it works. I have not worked with this code in years but will post it. This first part just goes in some tool box, it is reusable for any process.
//console_pipe.h
// the console_pipe.cpp declarations .....................................................
//C style use
HRESULT RunProcess( HWND hWnd //Window to 'SendMessage' to
,WORD idPost //ID for message with the data pointer in wparam
,WORD idEnd //ID for message notifying the process has ended
,LPCTSTR psFileExe //Path.File of process to run
,LPCTSTR psCmdLine= NULL //command line
);
//C++
extern HANDLE hGlobalThread;
extern HANDLE hChildProcess;
class RunPipeConsoleProcess
{
HANDLE hProcess;
WORD idPost;
WORD idEnd;
CString strExeFile;
CString strArguments;
public:
void SetMessageIDs( WORD inPost, WORD inEnd ) { idPost= inPost; idEnd= inEnd; }
void SetExecutable( LPCTSTR psExe ) { strExeFile= psExe; }
void SetArguments( LPCTSTR psArg ) { strArguments= psArg; }
bool StartThread( HWND hPostTo ) { hProcess= hChildProcess; return RunProcess( hPostTo, idPost, idEnd, strExeFile, strExeFile + strArguments ) == S_OK; }
bool StopThread( )
{
if( hGlobalThread && hProcess )
TerminateProcess( hProcess, -1 );
// ::PostThreadMessage( (DWORD)hGlobalThread, ID_CONSOLE_THREAD_STOP, 0, 0 );
return true;
}
};
//console_pipe.cpp
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#ifndef DWORD
typedef unsigned long DWORD;
#endif
#define CONPIPE_BUF_SIZE 1024
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
Redirect.c
Description:
This sample illustrates how to spawn a child console based
application with redirected standard handles.
The following import libraries are required:
user32.lib
Dave McPherson (davemm) 11-March-98
Modified 6-30-12 for use with MFC, Dan Bloomquist
RunProcess(...)
Creates a process running in its own thread. The process
is expected to use STDOUT to notify the condition of the process.
This call will return after starting the process with
the handle of the process. All you should need to do is
check for NULL, this means the process failed to start.
There will be no input to the process, it is expected
to work on its own after starting. A worker thread will
gather the STDOUT a line at a time and send it back to
the window specified.
TODO: The comments below reflect sending data to the
process input pipe. Here we are only interested in the
output of the process.
--*/
#pragma comment(lib, "User32.lib")
void DisplayError(TCHAR *pszAPI);
void ReadAndHandleOutput(HANDLE hPipeRead);
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr,
LPCTSTR psPathFile,
LPCTSTR psCommandLine );
DWORD WINAPI GetAndSendInputThread( LPVOID lpvThreadParam );
HANDLE hChildProcess = NULL;
HANDLE hStdIn = NULL; // Handle to parents std input.
BOOL bRunThread = TRUE;
HWND hPostMessage= NULL;
HANDLE hOutputRead= NULL;
HANDLE hInputRead= NULL;
HANDLE hInputWrite= NULL;
WORD idGlbPost;
WORD idGlbEnd;
HANDLE hGlobalThread;
HRESULT RunProcess( HWND hWnd //Window to 'SendMessage' to
,WORD idPost //ID for message with the data pointer in wparam
,WORD idEnd //ID for message notifying the process has ended
,LPCTSTR psFileExe //Path.File of process to run
,LPCTSTR psCmdLine
)
{
hPostMessage= hWnd;
HANDLE hOutputReadTmp;
HANDLE hOutputWrite;
HANDLE hInputWriteTmp;
HANDLE hErrorWrite;
DWORD ThreadId;
SECURITY_ATTRIBUTES sa;
idGlbPost= idPost;
idGlbEnd= idEnd;
// Set up the security attributes struct.
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
// Create the child output pipe.
if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
DisplayError(_T("CreatePipe"));
// Create a duplicate of the output write handle for the std error
// write handle. This is necessary in case the child application
// closes one of its std output handles.
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
GetCurrentProcess(),&hErrorWrite,0,
TRUE,DUPLICATE_SAME_ACCESS))
DisplayError(_T("DuplicateHandle"));
// Create the child input pipe.
if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
DisplayError(_T("CreatePipe"));
// Create new output read handle and the input write handles. Set
// the Properties to FALSE. Otherwise, the child inherits the
// properties and, as a result, non-closeable handles to the pipes
// are created.
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
GetCurrentProcess(),
&hOutputRead, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
DisplayError(_T("DupliateHandle"));
if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
GetCurrentProcess(),
&hInputWrite, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
DisplayError(_T("DupliateHandle"));
// Close inheritable copies of the handles you do not want to be
// inherited.
if (!CloseHandle(hOutputReadTmp)) DisplayError(_T("CloseHandle hOutputReadTmp"));
if (!CloseHandle(hInputWriteTmp)) DisplayError(_T("CloseHandle hInputWriteTmp"));
// Get std input handle so you can close it and force the ReadFile to
// fail when you want the input thread to exit.
if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) ==
INVALID_HANDLE_VALUE )
DisplayError(_T("GetStdHandle"));
PrepAndLaunchRedirectedChild( hOutputWrite, hInputRead, hErrorWrite, psFileExe, psCmdLine );
// Close pipe handles (do not continue to modify the parent).
// You need to make sure that no handles to the write end of the
// output pipe are maintained in this process or else the pipe will
// not close when the child process exits and the ReadFile will hang.
if (!CloseHandle(hOutputWrite)) DisplayError(_T("CloseHandle hOutputWrite"));
if (!CloseHandle(hInputRead )) DisplayError(_T("CloseHandle hInputRead"));
if (!CloseHandle(hErrorWrite)) DisplayError(_T("CloseHandle hErrorWrite"));
// Launch the thread that gets the input and sends it to the child.
hGlobalThread= CreateThread( NULL, 0, GetAndSendInputThread, (LPVOID)hOutputRead, 0, &ThreadId );
if (hGlobalThread == NULL)
return -1;
return 0;
}
///////////////////////////////////////////////////////////////////////
// PrepAndLaunchRedirectedChild
// Sets up STARTUPINFO structure, and launches redirected child.
///////////////////////////////////////////////////////////////////////
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr,
LPCTSTR psPathFile,
LPCTSTR psCommandLine )
{
//static int test= 0;
//ASSERT( ! test++ );
PROCESS_INFORMATION pi;
STARTUPINFO si;
// Set up the start up info struct.
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hChildStdOut;
si.hStdInput = hChildStdIn;
si.hStdError = hChildStdErr;
// Use this if you want to hide the child:
// si.wShowWindow = SW_HIDE;
// Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
// use the wShowWindow flags.
// Launch the process that you want to redirect (in this case,
// Child.exe). Make sure Child.exe is in the same directory as
// redirect.c launch redirect from a command line to prevent location
// confusion.
BOOL bSuccess = FALSE;
bSuccess = CreateProcess(
psPathFile, // app console
const_cast< LPTSTR >( psCommandLine ), //command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NO_WINDOW, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&si, // STARTUPINFO pointer
&pi // receives PROCESS_INFORMATION
);
// If an error occurs, exit the application.
if ( ! bSuccess )
{
DWORD err= GetLastError( );
DisplayError( TEXT( "CreateProcess" ) );
}
//if (!CreateProcess(NULL,psTestFile,NULL,NULL,TRUE,
// CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
// DisplayError(_T("CreateProcess");
// Set global child process handle to cause threads to exit.
hChildProcess= pi.hProcess;
// Close any unnecessary handles.
if( ! CloseHandle( pi.hThread ) )
DisplayError( _T("CloseHandle pi.hThread") );
}
///////////////////////////////////////////////////////////////////////
// ReadAndHandleOutput
// Monitors handle for input. Exits when child exits or pipe breaks.
///////////////////////////////////////////////////////////////////////
//#include <boost/iostreams/device/file_descriptor.hpp>
//#include <boost/iostreams/stream.hpp>
void ReadAndHandleOutput( HANDLE hPipeRead )
{
ASSERT( false );
int file_descriptor= _open_osfhandle( (intptr_t)hPipeRead, 0 );
FILE* file= _fdopen( file_descriptor, "r" );
std::ifstream stream( file );
std::string line;
//loop until stream empty
for( ; std::getline( stream, line ); )
{
SendMessage( hPostMessage, idGlbPost, (LPARAM)line.c_str( ), 0 );
TRACE( "line: %s\n", line.c_str( ) );
}
//should be so
ASSERT( GetLastError( ) == ERROR_BROKEN_PIPE );
if (!CloseHandle(hStdIn)) DisplayError(_T("CloseHandle hStdIn"));
if (!CloseHandle(hOutputRead)) DisplayError(_T("CloseHandle hOutputRead"));
if (!CloseHandle(hInputWrite)) DisplayError(_T("CloseHandle hInputWrite"));
}
///////////////////////////////////////////////////////////////////////
// GetAndSendInputThread
// Thread procedure that monitors the console for input and sends input
// to the child process through the input pipe.
// This thread ends when the child application exits.
///////////////////////////////////////////////////////////////////////
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
{
HANDLE hPipeRead= (HANDLE)lpvThreadParam;
int file_descriptor= _open_osfhandle( (intptr_t)hPipeRead, 0 );
FILE* file= _fdopen( file_descriptor, "r" );
std::ifstream stream( file );
std::string line;
//loop until stream empty
for( ; std::getline( stream, line ); )
{
SendMessage( hPostMessage, idGlbPost, (LPARAM)line.c_str( ), 0 );
TRACE( "line: %s\n", line.c_str( ) );
}
//should be so
return 1;
ASSERT( GetLastError( ) == ERROR_BROKEN_PIPE );
//if (!CloseHandle(hStdIn)) DisplayError(_T("CloseHandle"));
if (!CloseHandle(hOutputRead)) DisplayError(_T("CloseHandle hOutputRead"));
if (!CloseHandle(hInputWrite)) DisplayError(_T("CloseHandle hInputWrite"));
SendMessage( hPostMessage, idGlbEnd, 0, 0 );
return 1;
}
///////////////////////////////////////////////////////////////////////
// DisplayError
// Displays the error number and corresponding message.
///////////////////////////////////////////////////////////////////////
void DisplayError(TCHAR *pszAPI)
{
TRACE( "DisplayError: %s\n", pszAPI );
return;
// return;
LPVOID lpvMessageBuffer;
TCHAR szPrintBuffer[CONPIPE_BUF_SIZE];
DWORD nCharsWritten;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvMessageBuffer, 0, NULL);
StringCbPrintf(szPrintBuffer, CONPIPE_BUF_SIZE,
_T("ERROR: API = %s.\n error code = %d.\n message = %s.\n"),
pszAPI, GetLastError(), (TCHAR *)lpvMessageBuffer);
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),szPrintBuffer,
lstrlen(szPrintBuffer),&nCharsWritten,NULL);
LocalFree(lpvMessageBuffer);
//ExitProcess(GetLastError());
}
Now, in your dialog or whatever declaration, add the member:
RunPipeConsoleProcess pipes;
Then when you are ready, do the likes of:
pipes.SetMessageIDs( ID_CONSOLE_OUTPUT_WIN, ID_CONSOLE_OUTPUT_DONE );
pipes.SetExecutable( "netstat" );
pipes.SetArguments( "-ano );
if( ! pipes.StartThread( *this ) )
{
cEditStat.SetSel( -1, -1 );
cEditStat.ReplaceSel( _T("Failed to start JPEG Resize/Move Process\r\n") );
return;
}
The thread running the process will send messages with the IDs:
ID_CONSOLE_OUTPUT_WIN and ID_CONSOLE_OUTPUT_DONE
So add to your message map:
ON_MESSAGE( ID_CONSOLE_OUTPUT_WIN, OnPostConsoleWnd )
ON_MESSAGE( ID_CONSOLE_OUTPUT_DONE, OnPostConsoleWndDone )
OnPostConsoleWnd will get the output from the process in wparam.
I am trying to read some pages of memory of a 32 bit process using VirtualQueryEx using Visual Studio 2012.
However when I run the program I get VirtualQueryEx Error 6: Invalid Handle. However there is no error with the handle itself [hProcess] and I am passing in the appropriate parameters. What could be it?
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
// Forward declarations:
BOOL GetProcessList( );
BOOL ListProcessModules( DWORD dwPID );
BOOL ListProcessThreads( DWORD dwOwnerPID );
void printError( TCHAR* msg );
int main( void )
{
GetProcessList( );
system("pause");
return 0;
}
BOOL GetProcessList( )
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
return( FALSE );
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof( PROCESSENTRY32 );
// Retrieve information about the first process,
// and exit if unsuccessful
if( !Process32First( hProcessSnap, &pe32 ) )
{
printError( TEXT("Process32First") ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
//If the process name equals foo_process.exe
if (!_tcscmp(pe32.szExeFile, _T("foo_process.exe")))
{
hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, pe32.th32ProcessID );
if( hProcess == NULL )
printError( TEXT("OpenProcess") );
unsigned char *addr = NULL;
MEMORY_BASIC_INFORMATION meminfo;
if (VirtualQueryEx(hProcess, addr, &meminfo, sizeof(meminfo)) == 0){
printError( TEXT("VirtualQueryEx") );
//return FALSE;
}
}
} while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
void printError( TCHAR* msg )
{
...
}
EDIT: Handle has value:
EDIT 2: More Info:
Windows 7 64bit platform.
Visual Studio 2012 (32 bit debugger) ran
as Administrator
Process is *32 (32bit)
unsigned char *addr = NULL;
You're asking VirtualQueryEx to Query address 0 which is not valid, causing the failure.
How could I decide if my application is running under LocalSystem Account or not? Is there an easy way to do that?
Thanks!
Thanks for your help, but I might have found a way. Not the best, I know, but it works.
BOOL CheckIfRunningAsSYSTEM( VOID )
{
DWORD i, dwSize = 0, dwResult = 0;
HANDLE hToken;
PTOKEN_USER Ptoken_User;
// Open a handle to the access token for the calling process.
if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
{
printf( "OpenProcessToken Error %u\n", GetLastError() );
return FALSE;
}
// Call GetTokenInformation to get the buffer size.
if ( !GetTokenInformation( hToken, TokenUser, NULL, dwSize, &dwSize ) )
{
dwResult = GetLastError();
if ( dwResult != ERROR_INSUFFICIENT_BUFFER )
{
printf( "GetTokenInformation Error %u\n", dwResult );
return FALSE;
}
}
// Allocate the buffer.
Ptoken_User = ( PTOKEN_USER )GlobalAlloc( GPTR, dwSize );
// Call GetTokenInformation again to get the group information.
if ( !GetTokenInformation( hToken, TokenUser, Ptoken_User, dwSize, &dwSize ) )
{
printf( "GetTokenInformation Error %u\n", GetLastError() );
return FALSE;
}
LPWSTR SID = NULL;
if ( !ConvertSidToStringSidW( Ptoken_User->User.Sid, &SID ) )
{
printf( "\nConvertSidToStringSidW failed. Error = %d", GetLastError() );
return FALSE;
}
else printf( "\nConvertSidToStringSidW succeeded." );
if ( _wcsicmp( L"S-1-5-18", SID ) == 0 ) printf( "\nRunning under SYSTEM" );
else printf( "\nNOT running under SYSTEM" );
if ( Ptoken_User ) GlobalFree( Ptoken_User );
return TRUE;
}//CheckIfRunningAsSYSTEM
I would need to retrieve the serial number from my USB memory, namely the hard disk's serial number that the manufacturer assigns. For this reason I cannot use GetVolumeInformation() as suggested in some other threads. I would need to have the "unique" number
I kindly ask you if you can share an example in C++ and Windows environment (Visual c++)
Thanks!
You can check out this article:- http://oroboro.com/usb-serial-number/
#include <WinIOCtl.h>
#include <api/usbioctl.h>
#include <Setupapi.h>
DEFINE_GUID( GUID_DEVINTERFACE_USB_DISK,
0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2,
0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b );
void getDeviceInfo( int vol )
{
UsbDeviceInfo info;
// get the device handle
char devicePath[7] = "\\\\.\\#:";
devicePath[4] = (char)( vol + 'A' );
HANDLE deviceHandle = CreateFile( devicePath, 0,
FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL );
if ( deviceHandle == INVALID_HANDLE_VALUE )
return;
// to get the device number
DWORD volumeDeviceNumber = getDeviceNumber( deviceHandle );
CloseHandle( deviceHandle );
// Get device interface info set handle
// for all devices attached to the system
HDEVINFO hDevInfo = SetupDiGetClassDevs(
&GUID_DEVINTERFACE_USB_DISK, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
if ( hDevInfo == INVALID_HANDLE_VALUE )
return;
// Get a context structure for the device interface
// of a device information set.
BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
spdid.cbSize = sizeof( spdid );
DWORD dwIndex = 0;
while ( true )
{
if ( ! SetupDiEnumDeviceInterfaces( hDevInfo, NULL,
&GUID_DEVINTERFACE_USB_DISK,
dwIndex, &spdid ))
break;
DWORD dwSize = 0;
SetupDiGetDeviceInterfaceDetail( hDevInfo, &spdid, NULL,
0, &dwSize, NULL );
if (( dwSize != 0 ) && ( dwSize <= sizeof( Buf )))
{
pspdidd->cbSize = sizeof( *pspdidd ); // 5 Bytes!
ZeroMemory((PVOID)&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
long res = SetupDiGetDeviceInterfaceDetail(
hDevInfo, &spdid, pspdidd,
dwSize, &dwSize, &spdd );
if ( res )
{
HANDLE hDrive = CreateFile( pspdidd->DevicePath,0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if ( hDrive != INVALID_HANDLE_VALUE )
{
DWORD usbDeviceNumber = getDeviceNumber( hDrive );
if ( usbDeviceNumber == volumeDeviceNumber )
{
fprintf( "%s", pspdidd->DevicePath );
}
}
CloseHandle( hDrive );
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return;
}
You get the device number by calling DeviceIOControl() with the handle to your device:
DWORD getDeviceNumber( HANDLE deviceHandle )
{
STORAGE_DEVICE_NUMBER sdn;
sdn.DeviceNumber = -1;
DWORD dwBytesReturned = 0;
if ( !DeviceIoControl( deviceHandle,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &sdn, sizeof( sdn ),
&dwBytesReturned, NULL ) )
{
// handle error - like a bad handle.
return U32_MAX;
}
return sdn.DeviceNumber;
}
Next here is a method to recognize if a volume is removable media (e.g. like a usb or firewire disk):
bool isRemovableMedia( s32 vol )
{
char rootPath[5] = "#:\\";
rootPath[0] = (char)( vol + 'A' );
char szDosDeviceName[MAX_PATH];
char dosDevicePath[3] = "#:";
// get the drive type
UINT DriveType = GetDriveType( rootPath );
if ( DriveType != DRIVE_REMOVABLE )
return false;
dosDevicePath[0] = (char)( vol + 'A' );
QueryDosDevice( dosDevicePath, szDosDeviceName, MAX_PATH );
if ( strstr( szDosDeviceName,"\\Floppy") != NULL )
{
// its a floppy
return false;
}
return true;
}