We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

ReadFile() problem

pushpop
pushpop asked
on
Medium Priority
1,369 Views
Last Modified: 2012-06-27
Hi,

I'm writing a win32 program which will display the contents of the master boot record of a disk.
However, I'm new to WIN32 and whenever i use the readFile command, it fails.

Below is my code, excuse the errors:

//filename: main.cpp
//function: draws the main program window
//author:  

#include <windows.h>
#include "Resource.h"
#include <iostream.h>

//---------------------------------------------------------------------------
HWND hWnd;
LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
void read_mbr();

char * drive = "\\\\.\\PhysicalDrive0";
char buffer[20];
HWND hWndJump;
HANDLE hfile;

//---------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                           LPSTR lpCmdLine, int nCmdShow)
{
      DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLGFIRST),
                hWnd, reinterpret_cast<DLGPROC>(DlgProc));
      read_mbr();

      return FALSE;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{

      switch(Msg)
      {
      case WM_INITDIALOG:   //when the dialog box is instantiated..
      
      hfile = CreateFile(drive,GENERIC_READ,
                     FILE_SHARE_READ|FILE_SHARE_WRITE,
                     NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                     NULL);
      if(hfile==INVALID_HANDLE_VALUE)
      {
            
            MessageBox(hWnd,"Error opening drive","Error!",MB_OK);
            return FALSE;
      }
   
      
      hWndJump = GetDlgItem(hWndDlg,IDJUMPINSTR);  /*Get text box handle*/

   
      if(ReadFile(hfile,buffer,20,NULL,NULL)==FALSE)  /*read first 20 bytes of MBR*/
      {
            
                  MessageBox(hWnd,"error reading file","Error!",MB_OK);
      }
      
      SetWindowText(hWndJump,buffer);
            return TRUE;

            case WM_COMMAND:      // command received?
            switch(wParam)
            {
                  case IDOK:        //finished
                  EndDialog(hWndDlg, 0);
                  return TRUE;
                  break;
            
                  case IDCANCEL:// i want out
                  EndDialog(hWndDlg, 0);
                  return TRUE;
                  break;

                  case IDABOUT:// about the program
                  MessageBox(hWndDlg, "BlackLight for Windows v 0.1\n"
                                                "Written By \n"
                                                "Compiled using MS Visual C++ 6.0\n"
                                                "Please note the developer offers no warranty\n"
                                                "implied or otherwise as regards the use of this program\n"
                                                "This program was written in the hope of it being useful\n"
                                                "but there are NO guarantees offered in terms of performance\n"
                                                "safety, reliability or otherwise",
                                                "About BlackLight", MB_OK);
                  
                  return TRUE;
                  break;
            }
      }

      return FALSE;
}

Comment
Watch Question

CERTIFIED EXPERT

Commented:
retreive the error with GetLastError()

look at this:

http://www.microsoft.com/whdc/driver/tips/OverlappedIo.mspx

ike

Author

Commented:
Thanks,

Unfortunately, as i said I'm new to this. It all seems unnecessarily complicated to be honest; i was able to accomplish this with 7 lines of code in C, and yet, with WIN32, it requires non-intuitive functions with a ludicrous amount of parameters, all of which are microsoft proprietary datatypes. You cant just call GetLastError(), you need to parse the output using another function, FormatMessage. I thought APIs were supposed to make life easier as opposed to harder??
AxterSenior Software Engineer

Commented:
FYI:
>>#include <iostream.h>

iostream.h is not part of the C++ standard, and should not be used in any new code.  It's not portable, and will not compile on modern compilers like VC++ 7.x and 8.0.

You should use the extensionless version which is part of the C++ standard, and it is portable.
#include <iostream>
using namespace std;

Some STL *.h libraries have bugs in them, because these libraries are no longer being maintained by the compiler manufature.

Author

Commented:
Update: GetLastError() is returning error "the parameter is incorrect" - anybody know what could cause this

rgds
pushpop

Commented:
Two things:

You have to specify LPDWORD bytesRead and you have to read at least the sector size (512 bytes for example)

This works for me:

...
if(ReadFile(hDevice, buffer, 512, &dwBytesRead, NULL)==FALSE)  /*read first 20 bytes of MBR*/
...

Dont forge to increase your buffer size.

Bernd

Author

Commented:
Bernd: Thanks for that! I tried reading data in sector-sized chunks, but it didn't work, but I didn't specify LPDWORD bytesRead, so i'll try that and let you know how I'm getting on. I'm using Visual C++ 6.0, if that makes a difference, thougl I wouldnt expect it to!

Thanks to everyone for your help so far :-)

rgds

pushpop

Author

Commented:
Ok, I got that working, but now I'm having another problem. The buffer is being prematurely truncated, and I think it's because there are 0-value bytes that the program is mistaking for null-terminators. Could anyone offer any help?

here is the code:

//filename: main.cpp
//function: draws the main program window
//author:  

#include <windows.h>
#include "Resource.h"
#include <cstring>                                                //header file which contains message values
#include <iostream>
#include <cstring>
using namespace std;
#include <string.h>

//---------------------------------------------------------------------------
HWND hWnd;
LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK AboutProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam);

char * drive ="\\\\.\\PhysicalDrive0";
char * temp;
BYTE buffer[513];
HWND hWndJump;
HWND hWndEdit;
HANDLE hfile;
LPVOID lpMsgBuf;
DWORD bytesRead;
HINSTANCE hInst;
//---------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                           LPSTR lpCmdLine, int nCmdShow)
{
      DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLGFIRST),                              //make the dialog
                hWnd, reinterpret_cast<DLGPROC>(DlgProc));



      hInst = hInstance;
      return FALSE;

      
}
//---------------------------------------------------------------------------
LRESULT CALLBACK AboutProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
            HWND textBoxHandle = GetDlgItem(hWndDlg,IDD_ABOUTTEXT);
            char * aboutMsg =   "Copyright \251 2006 Eric Chubb\n\n"
            "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT "
            "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, "
            "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
            "MERCHANTABILITY, FITNESS FOR A PARTICULAR "
            "PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE "
            "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES "
            "OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, "
            "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN "
            "CONNECTION WITH THE SOFTWARE OR THE USE OR "
            "OTHER DEALINGS IN THE SOFTWARE.\n\n"
            "Version history: 0.1 - Basic disk analysis implemented - "
            "Master boot record only";
      switch(Msg)
            {
                  case WM_INITDIALOG:      
                        
                        SetWindowText(textBoxHandle,aboutMsg);
                        return TRUE;
                  
                  case WM_COMMAND:
                        
                        switch(wParam)
                        {
                              case IDC_OKBUTT:      
                        
                              EndDialog(hWndDlg,0);
                              return TRUE;
                        }

                        
            }
            return FALSE;
                  
}



LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
      hWndEdit = GetDlgItem(hWndDlg,IDC_EDIT1);
      switch(Msg)
      {
            case WM_INITDIALOG:      
                              
                              //when the dialog box is instantiated..

                  return TRUE;
                  
            
                  
                  case WM_COMMAND:      // command received?
                  
                  
                        switch(wParam)
                        {
                              case IDD_ABOUTBUTTON:// about the program
                  
                            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT),
                              hWnd, (DLGPROC)AboutProc);
                                                
                                            return FALSE;
                              
                        case IDOK:       
                              hfile = CreateFile(drive,GENERIC_READ,                   //open drive
                     FILE_SHARE_READ|FILE_SHARE_WRITE,
                     NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                     NULL);
      
      
                  if(hfile==INVALID_HANDLE_VALUE)                                          //if the device cant be mounted
                                                                                                      //print why
                  {
                  
                              FormatMessage(                                                      //woeful formatting prerequisite
                              FORMAT_MESSAGE_ALLOCATE_BUFFER |                        //converts the DWORD error value
                                                                                                      //returned by GetLastError()
                            FORMAT_MESSAGE_FROM_SYSTEM |                              //into a string and prints it
                              FORMAT_MESSAGE_IGNORE_INSERTS,
                              NULL,
                              GetLastError(),
                              0, // Default language
                              (LPTSTR) &lpMsgBuf,
                              0,
                              NULL );
                              MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error opening device", MB_OK | MB_ICONWARNING );

                  
                        return FALSE;
                        break;
                        
                        
                  }
   
            
                  hWndJump = GetDlgItem(hWndDlg,IDJUMPINSTR);                        //Get text box handle

                  if(ReadFile(hfile,buffer,512,&bytesRead,NULL)==FALSE)                        //read first 512 bytes of MBR or say whats wrong
                  {
                              FormatMessage(
                              FORMAT_MESSAGE_ALLOCATE_BUFFER |
                            FORMAT_MESSAGE_FROM_SYSTEM |
                              FORMAT_MESSAGE_IGNORE_INSERTS,
                              NULL,
                              GetLastError(),
                              0, // Default language
                              (LPTSTR) &lpMsgBuf,
                              0,
                              NULL );
                              MessageBox( NULL, (LPCSTR)lpMsgBuf, "Disk read error", MB_OK | MB_ICONWARNING );
                              SetWindowText(hWndJump,"device error");
                              return FALSE;
                        
                  }
      
      
                  //SetWindowText(hWndJump,buffer);
                  temp = reinterpret_cast<TCHAR *>(buffer);
                  SetWindowText(hWndEdit,temp);
                  return TRUE;
            
                  
            
                  case IDCANCEL:// i want out
                        EndDialog(hWndDlg, 0);
                        return TRUE;

                        break;
                        

                  
            }
      }
      return FALSE;

      
}


//---------------------------------------------------------------------------
Commented:
If you print out the data as string data, the NULL byte will of course truncate the string.

You may want to convert it to hex values or replace unprintable characters with dots for example...


for (i=0; i<bytesRead; i++)
{
  if (buffer[i] < 0x20)
    buffer[i] = '.';
}

buffer[bytesRead] = '\0'; // Make sure we can print out a truncated string.


Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
Ok thanks I'll try it this evening and let you know how I got on

Author

Commented:
Thanks for your answer, it worked a treat!
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.