Winamp & Shoutcast Forums

Winamp & Shoutcast Forums (http://forums.winamp.com/index.php)
-   NSIS Discussion (http://forums.winamp.com/forumdisplay.php?f=65)
-   -   Reading physical drive (http://forums.winamp.com/showthread.php?t=377577)

simplix 21st May 2014 08:28

Reading physical drive
 
Good day!

I'm trying to read a physical drive, but I get an error. Please tell me how to do it?

code:
;File Access Modes
!define GENERIC_READ 0x80000000
!define GENERIC_WRITE 0x40000000
;File Sharing Modes
!define FILE_SHARE_READ 0x00000001
!define FILE_SHARE_WRITE 0x00000002
;File Creation Flags
!define OPEN_EXISTING 3
!define INVALID_HANDLE_VALUE -1

Section Main

StrCpy $3 "\\?\PhysicalDrive0"
System::Call "kernel32::CreateFile(t r3, i ${GENERIC_READ}|${GENERIC_WRITE}, \
i ${FILE_SHARE_READ}|${FILE_SHARE_WRITE}, i 0, i ${OPEN_EXISTING}, i 0, i 0) i .r2"
${If} $2 != ${INVALID_HANDLE_VALUE}
System::Alloc 1
Pop $0

System::Call "kernel32::ReadFile (i r2, i r0, i 1, *i .r4, i 0) ?e"
Pop $5

System::Call "kernel32::GetLastError() i() .r1"
MessageBox MB_ICONINFORMATION|MB_OK "Return code: $5, Error code: $1"

System::Free $0
System::Call "kernel32::CloseHandle(i r2) i.r3"
${Else}
StrCpy $5 "Error: CreateFile failed for \\?\PhysicalDrive0"
${EndIf}

SectionEnd



ReadFile must return non-zero, but it returns 0 and GetLastError returns 80.

Thanks for your help!

Afrow UK 21st May 2014 08:46

You've used ?e for your ReadFile call which means $5 contains the last error code already. Calling GetLastError yourself will not return what you expect as something else since your System call (or even the System plug-in itself) will have either cleared or set the last error code. Use i .s on the end of your ReadFile call instead of ?e (or use i .r5 and remove the Pop $5).

Stu

simplix 21st May 2014 08:55

Afrow UK, thank you. If I replace it to next code:
code:
System::Call "kernel32::ReadFile (i r2, i r0, i 1, *i .r4, i 0) i .r5"
MessageBox MB_ICONINFORMATION|MB_OK "Error code: $5"


When "$5" = "error".

jpderuiter 21st May 2014 09:23

A physical drive is named: \\.\PhysicalDrive... (so a dot instead of questionmark)
And as you have to escape the backslash, use
code:
StrCpy $3 "\\\\.\\PhysicalDrive0"

Afrow UK 21st May 2014 09:30

Remove the space after ReadFile and before the (.

Stu

Afrow UK 21st May 2014 09:33

Quote:

Originally Posted by jpderuiter (Post 2995699)
A physical drive is named: \\.\PhysicalDrive... (so a dot instead of questionmark)
And as you have to escape the backslash, use
code:
StrCpy $3 "\\\\.\\PhysicalDrive0"

You don't need to escape the backslashes in NSIS because they don't act as escape characters ($\ does).

Stu

simplix 21st May 2014 10:47

Thanks for help.

Quote:

Originally Posted by Afrow UK (Post 2995700)
Remove the space after ReadFile and before the (.

Stu

Oh, I totally forgot about it... But return code still 0 (if the function succeeds, the return value is nonzero).

Afrow UK 21st May 2014 11:52

I don't think this is possible any more:
http://support.microsoft.com/kb/942448

What exactly are you trying to do?

Stu

simplix 21st May 2014 12:24

I'm trying read drive on WinXP, but function must work on any system. I think this KB does not matter, because there is considered newer systems. In addition exists utilities that successfully read and write drive on any system, but don't have all needed functions, which can be implemented independently.

Quote:

Originally Posted by Afrow UK (Post 2995710)
What exactly are you trying to do?

This is for the treatment of drives from viruses in MBR and similar work. Now I use a third-party utility, but its capabilities are not always enough and want the flexibility to manage data.

jpderuiter 21st May 2014 12:58

Quote:

Originally Posted by Afrow UK (Post 2995702)
You don't need to escape the backslashes in NSIS because they don't act as escape characters ($\ does)

You're right, in NSIS you don't have to escape a backslash.
Anyway, this is where I got the idea of escaping:
http://forums.winamp.com/showpost.ph...41&postcount=2
It seems to have been working for f0rt

Afrow UK 21st May 2014 14:07

Quote:

Originally Posted by jpderuiter (Post 2995719)
You're right, in NSIS you don't have to escape a backslash.
Anyway, this is where I got the idea of escaping:
http://forums.winamp.com/showpost.ph...41&postcount=2
It seems to have been working for f0rt

You can thank the vBulletin's PHP code tag he used for that.

Stu

Afrow UK 21st May 2014 14:10

Quote:

Originally Posted by simplix (Post 2995717)
I'm trying read drive on WinXP, but function must work on any system. I think this KB does not matter, because there is considered newer systems. In addition exists utilities that successfully read and write drive on any system, but don't have all needed functions, which can be implemented independently.


This is for the treatment of drives from viruses in MBR and similar work. Now I use a third-party utility, but its capabilities are not always enough and want the flexibility to manage data.

The article was written before 7 and above was available but will likely apply to those operating systems too unless otherwise specified (everything I have found on Google suggests this is the case).

In order to access a disk directly on Vista and above it looks like you will need to be running as LOCAL SYSTEM, e.g. as a Windows service (or you can use PsExec).

Stu

simplix 21st May 2014 16:52

Quote:

Originally Posted by jpderuiter (Post 2995719)
Anyway, this is where I got the idea of escaping:
http://forums.winamp.com/showpost.ph...41&postcount=2
It seems to have been working for f0rt

My code is based on it. That code work, even if we replace "\\\\.\\" to "\\?\", otherwise handle of CreateFile will be -1.

Quote:

Originally Posted by Afrow UK (Post 2995724)
In order to access a disk directly on Vista and above it looks like you will need to be running as LOCAL SYSTEM, e.g. as a Windows service (or you can use PsExec).

There is no difference, the program starts with system privileges or administrator. Tested on WinXP and Win7.

Thank you all for your help, it is very valuable.

Afrow UK 21st May 2014 19:11

Does it work on XP but not on 7? Or does it work on neither?

This is the my code (ReadFile fails with 87 - invalid parameter).
code:
Section Main
StrCpy $3 "\\.\PhysicalDrive0"
System::Call "kernel32::CreateFile(t r3, i ${GENERIC_READ}, i 0, i 0, i ${OPEN_EXISTING}, i 0, i 0) i .r2"
${If} $2 != ${INVALID_HANDLE_VALUE}
System::Call "kernel32::ReadFile(i r2, t .r0, i 32, i .r4, i 0) ?e"
Pop $5
DetailPrint "Return code: $5, Return value: $0"
System::Call "kernel32::CloseHandle(i r2) i.r3"
${Else}
DetailPrint "Error: CreateFile failed for \\?\PhysicalDrive0"
${EndIf}
SectionEnd

Stu

simplix 21st May 2014 20:25

Quote:

Originally Posted by Afrow UK (Post 2995741)
ReadFile fails with 87 - invalid parameter

This code fails with 87 on WinXP and Win7. IMHO parameters of ReadFile is wrong. I got examples here, here and here.

simplix 21st May 2014 20:44

I found new exemple here and ReadFile works fine with files, but then I adapted this code to read drive - ReadFile fails.

Afrow UK 22nd May 2014 06:52

Quote:

Originally Posted by simplix (Post 2995745)
This code fails with 87 on WinXP and Win7. IMHO parameters of ReadFile is wrong. I got examples here, here and here.

I tested my code with a file and it works, so 87 must be telling you the handle is invalid. I will do some more tests if I can tonight but how about writing some C code instead? You can be sure you are getting the parameters right then.

Stu

Anders 22nd May 2014 08:57

System::Call "kernel32::ReadFile(i r2, t .r0, i 32, i .r4, i 0) ?e" should probably be *i.r4.

Afrow UK 22nd May 2014 10:59

Quote:

Originally Posted by Anders (Post 2995791)
System::Call "kernel32::ReadFile(i r2, t .r0, i 32, i .r4, i 0) ?e" should probably be *i.r4.

Tried that too. Still get 87.

Stu

simplix 22nd May 2014 12:30

I found working code in C here (Posted by nullptr: 09 January 2011 at 11:20am), which compiled in RAD Studio and successfully works even on Win7 x64. But still do not understand why it does not work in NSIS.

Anders 22nd May 2014 12:55

Quote:

RequestExecutionLevel admin
Section Main
!include LogicLib.nsh
!define GENERIC_READ 0x80000000
!define OPEN_EXISTING 3
!define FILE_SHARE_READ 0x00000001
!define FILE_SHARE_WRITE 0x00000002
!define INVALID_HANDLE_VALUE -1
StrCpy $3 "\\.\C:" ; Using "\\.\PhysicalDrive0" will succeed but it seems ReadFile only gives you a zero filled buffer?
System::Call "kernel32::CreateFile(t r3, i ${GENERIC_READ}, i ${FILE_SHARE_READ}|${FILE_SHARE_WRITE}, i 0, i ${OPEN_EXISTING}, i 0, i 0)i.r2 ?e"
Pop $5
${If} $2 <> ${INVALID_HANDLE_VALUE}
System::Call "kernel32::ReadFile(i r2, m.r0, i 512, *i.r4, i 0)i.r3 ?e" ; A read request < 512 bytes here will fail on my Win8 system
Pop $5
${If} $3 <> 0
DetailPrint "Read $4 bytes, ASCII-Data=$0|"
${Else}
DetailPrint "ReadFile failed: GetLastError=$5"
${EndIf}
System::Call "kernel32::CloseHandle(i r2)"
${Else}
DetailPrint "CreateFile failed: GetLastError=$5"
${EndIf}
SectionEnd
This gives me "...NTFS...".

Writing this type of low-level code with the system plugin is not a good idea, working with binary data or whatever you are reading is painful.

What are you really trying to do? Detect the filesystem type or something else?

simplix 22nd May 2014 13:46

Anders, thank you very much. The problem was that my request is less 512 bytes.
Quote:

Originally Posted by Anders (Post 2995804)
What are you really trying to do?

As I said before, it's for the treatment of MBR viruses. My project antisms.com (for now only in Russian, sorry) written on NSIS, and I thank very much all contributors of this forum.

Anders 22nd May 2014 15:45

Well, I think it would be much better to write a plugin, I don't see how all that system::call code is going to be manageable when the codebase gets larger...

simplix 22nd May 2014 16:15

Personally for me, much better to use WinAPI, because I do not know C, and any changes I make in the code immediately, without waiting for the author of the plugin.

Anders 22nd May 2014 16:32

IMHO you basically have to understand C and the WinAPI to really use the system plugin. You have to be able to transform the function declarations listed on MSDN or in a .h file and convert it to system syntax and you have to understand how C strings work and how pointers work if you are going to be reading anything other than strings from a text file.

Messing with the MBR is not something most people should be doing and certainly not if you don't have a basic understanding of C and it's structure layout/padding semantics and how it differs from the system plugin struct syntax. Also, as you have seen, reading from a disk at this low level might have alignment and/or buffer restrictions, you cannot just treat it as a normal file.

I personally would not trust a MBR tool if I knew it was written in NSIS.


All times are GMT. The time now is 17:18.

Copyright © 1999 - 2010 Nullsoft. All Rights Reserved.