394 lines
10 KiB
C
394 lines
10 KiB
C
|
|
||
|
/****************************************************************************\
|
||
|
*
|
||
|
*
|
||
|
* Module: ntphys.c
|
||
|
*
|
||
|
* Description: This module contains the logic for accessing the
|
||
|
* floppy drive directly from the dskimage utility.
|
||
|
* Function prototypes reside in physdisk.h.
|
||
|
*
|
||
|
* Comments: This utility was not ported from the OS/2 version.
|
||
|
* It was developed separately. This file is written
|
||
|
* as NT native code.
|
||
|
*
|
||
|
* Author: Kenneth S. Gregg (kengr)
|
||
|
*
|
||
|
* Copyright (c) 1991 Microsoft Corporation
|
||
|
*
|
||
|
* History: 10/20/91 - original version (kengr)
|
||
|
* 09/12/92 - correctly detect unformatted floppies
|
||
|
* 09/12/92 - correctly detect SCSI flopticals
|
||
|
*
|
||
|
*
|
||
|
\****************************************************************************/
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
//typedef unsigned long DWORD;
|
||
|
//typedef int BOOL;
|
||
|
//typedef void *HANDLE;
|
||
|
//typedef void *LPVOID;
|
||
|
//typedef char CHAR;
|
||
|
|
||
|
#include "physdisk.h"
|
||
|
|
||
|
|
||
|
#define FLOPPY_RETRIES 3 /* seems to recover from most CRCs */
|
||
|
|
||
|
|
||
|
/* The following structure defines all data global to this module. These
|
||
|
* items are required for communication between various functions.
|
||
|
*/
|
||
|
|
||
|
static struct _GLOBAL {
|
||
|
BOOL fDiskOpen;
|
||
|
HANDLE hDisk;
|
||
|
} global = { FALSE, NULL };
|
||
|
|
||
|
|
||
|
static USHORT VerifyFloppyDevice(
|
||
|
CHAR chDriveLetter)
|
||
|
{
|
||
|
CHAR chMovingDriveLetter;
|
||
|
CHAR achBuffer[] = "X:\\";
|
||
|
USHORT usFloppyCounter = 0;
|
||
|
|
||
|
chDriveLetter = toupper(chDriveLetter);
|
||
|
|
||
|
for (chMovingDriveLetter = 'A';
|
||
|
chMovingDriveLetter <= 'Z';
|
||
|
chMovingDriveLetter++) {
|
||
|
sprintf(achBuffer, "%c:\\", chMovingDriveLetter);
|
||
|
|
||
|
if (GetDriveType(achBuffer) == DRIVE_REMOVABLE) {
|
||
|
usFloppyCounter++;
|
||
|
//printf("Drive %c is a floppy (%d)\n",
|
||
|
// chMovingDriveLetter,
|
||
|
// usFloppyCounter);
|
||
|
|
||
|
if (chDriveLetter == chMovingDriveLetter) {
|
||
|
return(usFloppyCounter);
|
||
|
}
|
||
|
} else {
|
||
|
if (chDriveLetter == chMovingDriveLetter) {
|
||
|
return(0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL ProcessedNTError(
|
||
|
NTSTATUS ntstatus)
|
||
|
{
|
||
|
switch (ntstatus) {
|
||
|
case STATUS_UNRECOGNIZED_MEDIA:
|
||
|
printf("The diskette is not formatted properly.\n" \
|
||
|
"Please check the diskette, or reformat.\n");
|
||
|
return (TRUE);
|
||
|
|
||
|
default:
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
/****************************************************************************\
|
||
|
*
|
||
|
*
|
||
|
* Function: WaitForIO
|
||
|
*
|
||
|
* Description: This internal function provides a common mechanism to
|
||
|
* wait for floppy I/O completion. It is use by both the
|
||
|
* read and write functions.
|
||
|
*
|
||
|
* Arguments: none
|
||
|
*
|
||
|
* Returns: Boolean, TRUE if wait operation succeeded.
|
||
|
*
|
||
|
* Comments: This function is dependent upon the NT native layer.
|
||
|
*
|
||
|
*
|
||
|
\****************************************************************************/
|
||
|
|
||
|
static BOOL WaitForIO()
|
||
|
{
|
||
|
NTSTATUS ntstatus;
|
||
|
|
||
|
ntstatus = NtWaitForSingleObject(global.hDisk,
|
||
|
TRUE,
|
||
|
NULL);
|
||
|
|
||
|
if (!NT_SUCCESS(ntstatus)) {
|
||
|
printf("I/O wait on floppy failed: %08lX\n", ntstatus);
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************\
|
||
|
*
|
||
|
*
|
||
|
* Function: OpenFloppy
|
||
|
*
|
||
|
* Description: This external function provides initial access to the
|
||
|
* floppy drive. It opens the entire volume in raw mode,
|
||
|
* to allow access to all sectors.
|
||
|
*
|
||
|
* Arguments: Drive letter of floppy to be accessed.
|
||
|
*
|
||
|
* Returns: Boolean, TRUE if all operations succeeded.
|
||
|
*
|
||
|
* Comments: This function is dependent upon the NT native layer.
|
||
|
* It is assumed that the caller verified that this is
|
||
|
* indeed a floppy drive. No check for this is made here.
|
||
|
*
|
||
|
*
|
||
|
\****************************************************************************/
|
||
|
|
||
|
BOOL OpenFloppy(
|
||
|
CHAR chDriveLetter)
|
||
|
{
|
||
|
CHAR achFileName[] = "\\Device\\FloppyX";
|
||
|
STRING strNameString;
|
||
|
UNICODE_STRING ustrUnicodeString;
|
||
|
OBJECT_ATTRIBUTES obja;
|
||
|
IO_STATUS_BLOCK iosb;
|
||
|
NTSTATUS ntstatus;
|
||
|
USHORT usFloppyDeviceNumber;
|
||
|
|
||
|
if (global.fDiskOpen) {
|
||
|
printf("Floppy already open\n");
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
usFloppyDeviceNumber = VerifyFloppyDevice(chDriveLetter);
|
||
|
|
||
|
if (usFloppyDeviceNumber == 0) {
|
||
|
printf("%c is not a floppy device\n", chDriveLetter);
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
sprintf(achFileName,
|
||
|
"\\Device\\Floppy%d",
|
||
|
usFloppyDeviceNumber - 1);
|
||
|
|
||
|
RtlInitString(&strNameString,
|
||
|
achFileName);
|
||
|
|
||
|
ntstatus = RtlAnsiStringToUnicodeString(&ustrUnicodeString,
|
||
|
&strNameString,
|
||
|
TRUE);
|
||
|
|
||
|
if (!NT_SUCCESS(ntstatus)) {
|
||
|
printf("Unable to convert device name to unicode: %08lX\n", ntstatus);
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
InitializeObjectAttributes(&obja,
|
||
|
&ustrUnicodeString,
|
||
|
0,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
ntstatus = NtOpenFile(&global.hDisk,
|
||
|
FILE_READ_DATA |
|
||
|
FILE_WRITE_DATA |
|
||
|
SYNCHRONIZE,
|
||
|
&obja,
|
||
|
&iosb,
|
||
|
FILE_SHARE_READ |
|
||
|
FILE_SHARE_WRITE |
|
||
|
FILE_SHARE_DELETE,
|
||
|
FILE_SYNCHRONOUS_IO_ALERT);
|
||
|
|
||
|
if (!NT_SUCCESS(ntstatus)) {
|
||
|
if (!ProcessedNTError(ntstatus)) {
|
||
|
printf("Could not open drive: %08lX\n", ntstatus);
|
||
|
}
|
||
|
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
global.fDiskOpen = TRUE;
|
||
|
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************\
|
||
|
*
|
||
|
*
|
||
|
* Function: CloseFloppy
|
||
|
*
|
||
|
* Description: This external function provides cleanup services for the
|
||
|
* floppy drive. It simply closes the floppy drive.
|
||
|
*
|
||
|
* Arguments: none
|
||
|
*
|
||
|
* Returns: Boolean, TRUE if all operations succeeded.
|
||
|
*
|
||
|
* Comments: This function is dependent upon the NT native layer.
|
||
|
*
|
||
|
*
|
||
|
\****************************************************************************/
|
||
|
|
||
|
BOOL CloseFloppy(VOID)
|
||
|
{
|
||
|
NTSTATUS ntstatus;
|
||
|
|
||
|
if (!global.fDiskOpen) {
|
||
|
printf("Floppy is not open\n");
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
ntstatus = NtClose(global.hDisk);
|
||
|
|
||
|
if (!NT_SUCCESS(ntstatus)) {
|
||
|
if (!ProcessedNTError(ntstatus)) {
|
||
|
printf("Could not close drive: %08lX\n", ntstatus);
|
||
|
}
|
||
|
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
global.fDiskOpen = FALSE;
|
||
|
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************\
|
||
|
*
|
||
|
*
|
||
|
* Function: ReadFloppy
|
||
|
*
|
||
|
* Description: This external function provides a mechanism to read a
|
||
|
* block from the floppy drive into a user buffer.
|
||
|
*
|
||
|
* Arguments: Offset bytes from the start of the floppy to start read.
|
||
|
* Number of bytes to read.
|
||
|
* Destination user buffer for data.
|
||
|
*
|
||
|
* Returns: Boolean, TRUE if all operations succeeded.
|
||
|
*
|
||
|
* Comments: This function is dependent upon the NT native layer.
|
||
|
*
|
||
|
*
|
||
|
\****************************************************************************/
|
||
|
|
||
|
BOOL ReadFloppy(
|
||
|
DWORD dwOffset,
|
||
|
DWORD dwSize,
|
||
|
LPVOID lpBuffer)
|
||
|
{
|
||
|
LARGE_INTEGER liReadPosition;
|
||
|
IO_STATUS_BLOCK iosb;
|
||
|
NTSTATUS ntstatus;
|
||
|
DWORD dwRetries;
|
||
|
|
||
|
if (!global.fDiskOpen) {
|
||
|
printf("Floppy is not open\n");
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
liReadPosition.LowPart = (ULONG) dwOffset;
|
||
|
liReadPosition.HighPart = 0L;
|
||
|
|
||
|
dwRetries = FLOPPY_RETRIES;
|
||
|
|
||
|
do {
|
||
|
ntstatus = NtReadFile(global.hDisk,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&iosb,
|
||
|
(PVOID) lpBuffer,
|
||
|
dwSize,
|
||
|
&liReadPosition,
|
||
|
NULL);
|
||
|
} while ((dwRetries--) && (!NT_SUCCESS(ntstatus)));
|
||
|
|
||
|
if (!NT_SUCCESS(ntstatus)) {
|
||
|
if (!ProcessedNTError(ntstatus)) {
|
||
|
printf("Could not read drive: %08lX\n", ntstatus);
|
||
|
}
|
||
|
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
return (WaitForIO());
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************\
|
||
|
*
|
||
|
*
|
||
|
* Function: WriteFloppy
|
||
|
*
|
||
|
* Description: This external function provides a mechanism to write a
|
||
|
* block onto the floppy drive from a user buffer.
|
||
|
*
|
||
|
* Arguments: Offset bytes from the start of the floppy to start write.
|
||
|
* Number of bytes to write.
|
||
|
* Source user buffer containing data to write.
|
||
|
*
|
||
|
* Returns: Boolean, TRUE if all operations succeeded.
|
||
|
*
|
||
|
* Comments: This function is dependent upon the NT native layer.
|
||
|
*
|
||
|
*
|
||
|
\****************************************************************************/
|
||
|
|
||
|
BOOL WriteFloppy(
|
||
|
DWORD dwOffset,
|
||
|
DWORD dwSize,
|
||
|
LPVOID lpBuffer)
|
||
|
{
|
||
|
LARGE_INTEGER liWritePosition;
|
||
|
IO_STATUS_BLOCK iosb;
|
||
|
NTSTATUS ntstatus;
|
||
|
DWORD dwRetries;
|
||
|
|
||
|
if (!global.fDiskOpen) {
|
||
|
printf("Floppy is not open\n");
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
liWritePosition.LowPart = (ULONG) dwOffset;
|
||
|
liWritePosition.HighPart = 0L;
|
||
|
|
||
|
dwRetries = FLOPPY_RETRIES;
|
||
|
|
||
|
do {
|
||
|
ntstatus = NtWriteFile(global.hDisk,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&iosb,
|
||
|
(PVOID) lpBuffer,
|
||
|
dwSize,
|
||
|
&liWritePosition,
|
||
|
NULL);
|
||
|
} while ((dwRetries--) && (!NT_SUCCESS(ntstatus)));
|
||
|
|
||
|
if (!NT_SUCCESS(ntstatus)) {
|
||
|
if (!ProcessedNTError(ntstatus)) {
|
||
|
printf("Could not write drive: %08lX\n", ntstatus);
|
||
|
}
|
||
|
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
return (WaitForIO());
|
||
|
}
|
||
|
|