C++ - low level access to HDD/USB stick.

Hello,

Windows 7 & 10.
Compiler - gcc version 5.3.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project),
Windows Defender and my anti-virus turned off.

I've got a drive/USB stick formatted FAT32.
I'm using this code to access the first section of raw data.
The data I'm getting from the loop at lines 86 - 89 bear no relationship to the
Hex dump, its rubbish.
I'm pretty sure the 'searchfor' function is working OK.
Help Please. what mistake am I making?

Regards

Note: If you want to try, it will compile and run.
If you only have 'NTFS' partitions. change line 67 to 'NTFS'.
Change the 'drLetter' on line 65 to suit.

1
2
3
4
5
6
7
8
9
Hex dump
ëX.MSDOS5.0..." 
.....ø..?.ÿ.?...
†ú?.ï...........
................
€.)¸:.ÈNO NAME  
FAT32   3ɎѼô
{ŽÁŽÙ½.|ˆV@ˆN.ŠV
@´A»ªUÍ.r..ûUªu. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Program
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <assert.h>
#include <windows.h>
#include <string>
#include <cstdio>
#include <string.h>
#include <fstream>
#include <cstdint>
#include <vector>
#include <list>
#include <stdio.h>
#include <algorithm>
#include <cstring>

using namespace std;

//Declarations
int searchFor(char &buff, int size, std::string str);

//Functions
int searchFor(char buff[], int size, std::string str)
{
    //printf("buff[5] %x\n", buff[5]);
    char c_to_search[sizeof(str)];
    strncpy(c_to_search, str.c_str(), sizeof(c_to_search));
    //printf("XXX %s\n", c_to_search);
    int pos_search = 0; //
    int pos_text = 0; // counter
    int len_search = static_cast<int>(str.length());
    // watch static_cast for max & negative numbers

    //printf("%s - %i chars\n", c_to_search, len_search);

    for (pos_text = 0; pos_text < size - len_search; ++pos_text)
    {
        //printf("%i - check1\n", pos_text);
        if(buff[pos_text] == c_to_search[pos_search])
        {
            //printf("check2\n");
            ++pos_search;
            if(pos_search == len_search)
            {
//                printf("match at %d 0x%02xh to %d 0x%02xh\n",
//                       pos_text - len_search, pos_text - len_search,
//                       pos_text, pos_text);
                return (pos_text - len_search);
            }
        }
        else
        {
            pos_text -=pos_search;
            pos_search = 0;
        }
    }
    return (-1);
}

int main()
{
    char buff[523];

    std::string drLetter = "K"; // GET THE RIGHT DEVICE
    std::string device = ("\\\\.\\" + drLetter + ":");
    std::string fileType = "FAT32";

    std::FILE * fp = fopen(device.c_str(), "rb"); // read, binary

    if(!fp) {
        cerr << "Device '" + drLetter + "' could not be opened!" << endl;
        exit (101);
    }

    std::ifstream infile(device.c_str(), std::ios::in | std::ios::binary);
    if (!infile)
    {
        cerr << "Device '" + drLetter + "' Input could not be set!" << endl;
        exit (102);
    }

    fseek(fp, 0, SEEK_SET);   // reset to beginning of file
    infile.read(buff, sizeof(buff));   // read in the structure length

//    for (unsigned int i = 0; i < 523; i++)
//    {
//        printf("%i - %x - %c, ", i, buff[i], buff[i]);
//    }

    std::vector <string> sysList = { "FAT12", "FAT16", "FAT32", "NTFS"};

    if ( ! (std::find(sysList.begin(), sysList.end(), fileType) != sysList.end()) )
    {
        printf("Not in list of file types!\n");
        exit (100);
    }

    int pos = searchFor(buff, sizeof(buff), fileType);
    //printf("pos %i\n" , pos);
    if (pos == -1)
    {
        printf("Not a %s file system.\n", fileType.c_str());
        return (99);
    }
    else
    {
        printf("search file type at %i - %s\n\n", pos, fileType.c_str());
    }
    printf("found %s at pos %i\n\n\n", fileType.c_str(), pos);

    exit(0);
}

Last edited on
You don't check if the read actually succeeded; you don't check with gcount() that the number of bytes read was actually the number you requested.

The FILE pointer fp is not necessary for a couple reasons:
1. The file objects referenced by fp and by infile are independent, so you can't move the file pointer of one by seeking on the other.
2. std::fstream objects always start at the BOF anyway, unless you request something different.
Hello,

helios, thanks for your reply.

I've followed your advice, but getting 0 (zero) bytes read.

Regards

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
int main()
{
    char buff[523];
	
    std::string drLetter = "K"; // GET THE RIGHT DEVICE
    std::string device = ("\\\\.\\" + drLetter + ":");
    std::string fileType = "FAT32";

    std::vector <string> sysList = { "FAT12", "FAT16", "FAT32", "NTFS" };

    if ( ! (std::find(sysList.begin(), sysList.end(), fileType) != sysList.end()) )
    {
        printf("Not in list of file types!\n");
        exit (100);
    }

    std::ifstream infile(device.c_str(), std::ios::in | std::ios::binary);
    if (!infile)
    {
        cerr << "Device '" + drLetter + "' Input could not be set!" << endl;
        exit (102);
    }

    infile.read(buff, sizeof(buff));   // read in the structure length
    std::cout << "Read: " << infile.gcount() <<  " bytes" << std::endl;
    if (infile.gcount() == 0)
    {
        exit (999);
    }
	
    //for (unsigned int i = 0; i < 523; i++)
    //{
    //    printf("%i - %x - %c, ", i, buff[i], buff[i]);
    //}

    int pos = searchFor(buff, sizeof(buff), fileType);
    //printf("pos %i\n" , pos);
    if (pos == -1)
    {
        printf("Not a %s file system.\n", fileType.c_str());
        return (99);
    }
    else
    {
        printf("search file type at %i - %s\n\n", pos, fileType.c_str());
    }
    printf("found %s at pos %i\n\n", fileType.c_str(), pos);

    exit(0);
	
}
1
2
3
Output:-
Read: 0 bytes
...\test.exe exited with code 999
Last edited on
It works for me. Win 7 64 bit
Read: 523 bytes
search file type at 81 - FAT32

found FAT32 at pos 81

Hello,

I've got a triple boot system.
Windiows 7 - 32 bit
Windows 10 - 32 bit
Debian 8 - 64 bit

I've just tested on Win 7 & Win 10, getting the same results.

Output:-
Read: 0 bytes
...\test.exe exited with code 999


Now I'm lost. I can't believe its because of 32 bits.
Any suggestions?

Regards

Thomas1965 Can you tell me what compiler you are using?
I use VS 2015 CE.
I tried it also on my old Win7 32 bit and it worked there as well.

You could try to old fread function with perror, maybe it will give you an error msg.
Another option would be to use the WinApi ReadFile function and check GetLastError()
Line 25: sizeof(str) doesn't do what you think it does. It returns the constant size of class std::string, not the size of the string passed in (which is str.size()). It looks to me like you don't need c_to_search anyway. Just look in str.

Dumb question, but are you sure that the K: drive exists?
Hello,

Dumb question, but are you sure that the K: drive exists?
Yes, I tried on drive 'C', 'D', etc. as well.

Well now, I've just installed VS 2015 CE.
It works.

Will try changing the settings on the GNU/C++ compiler.

Thanks for all your help.

Regards


Last edited on
Do fix the sizeof(str) problem on line 25, even if the code appears to work. It's just working by accident.
Hello,

dhayden Thanks, I did.

Regards
Topic archived. No new replies allowed.