IDE disk geometry
Michael Ost
most at museresearch.com
Tue Sep 20 19:11:49 CDT 2005
Any suggestions for a good "wineish" way to implement an IOCTL_ call for
an IDE disk?
My winelib app is hosting a Windows DLL that is making an
IOCTL_DISK_DRIVE_GET_GEOMETRY call on an IDE hard disk. ntdll/file.c
NtDeviceIoControlFile is passing this off to ntdll/cdrom.c
CDROM_DeviceIoControl and, of course, since it is not a cdrom disk, that
fails.
I have some code that reads geometry information out of
/proc/ide/hd?/geometry that is working fine. But I am not sure how to
integrate it into ntdll.
Should I put my code in CDROM_DeviceIoControl? Or handle it in
NtDeviceIoControlFile? Should I pass all other IoControlCodes except
IOCTL_DISK_DRIVE_GET_GEOMETRY for a verifiable IDE drive on to the
CDROM_... function?
If anyone has a background in this code, you probably have an idea
straight off how best to fit it in.
Thanks for any help. Patch against wine-20050419 is attached for
illustrative purposes. ... mo
-------------- next part --------------
--- dlls/ntdll/file.c.20050419 2005-09-20 09:49:54.000000000 -0700
+++ dlls/ntdll/file.c 2005-09-20 17:10:17.000000000 -0700
@@ -790,6 +790,113 @@
return io_status->u.Status;
}
+/***********************************************************************
+ * FILE_IdeDeviceIoControlFile (INTERNAL)
+ *
+ * Handle device IO control for ide disks. Returns TRUE if
+ * DeviceHandle is an IDE disk, else FALSE.
+ */
+static BOOL FILE_IdeDeviceIoControlFile(HANDLE DeviceHandle, HANDLE hEvent,
+ PIO_APC_ROUTINE UserApcRoutine,
+ PVOID UserApcContext,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ ULONG IoControlCode,
+ PVOID InputBuffer,
+ ULONG InputBufferSize,
+ PVOID OutputBuffer,
+ ULONG OutputBufferSize)
+{
+#if !linux
+ return FALSE;
+#else
+ BOOL releaseFd = FALSE;
+ BOOL isIde = FALSE;
+ NTSTATUS status = STATUS_SUCCESS;
+ DWORD sz = 0;
+
+ int fd;
+ FILE* file;
+ int length;
+ char linkPath[64];
+ char path[MAX_PATH];
+ char letter;
+ struct stat st;
+
+ if ((status = wine_server_handle_to_fd( DeviceHandle, 0, &fd, NULL )) != STATUS_SUCCESS)
+ goto out;
+ releaseFd = TRUE;
+
+ // does the file descriptor point to an entry in /proc/ide?
+ // todo - isn't there a system call to get a name from a dev_t and ino_t?
+ snprintf(linkPath, sizeof(linkPath), "/proc/%d/fd/%d", getpid(), fd);
+ length = readlink(linkPath, path, sizeof(path));
+ if (length != -1)
+ path[length] = '\0';
+ else {
+ // bad proc format?
+ goto out;
+ }
+
+ // see if the device exists in /proc/ide
+puts(path); //todo
+ if (sscanf(path, "/dev/hd%c", &letter) != 1)
+ goto out;
+ snprintf(path, sizeof(path), "/proc/ide/hd%c", letter);
+ if (stat(path, &st) == -1)
+ goto out;
+ isIde = TRUE;
+
+ IoStatusBlock->Information = 0;
+ switch (IoControlCode)
+ {
+ case IOCTL_DISK_GET_DRIVE_GEOMETRY:
+ strcat(path, "/geometry");
+
+ if (OutputBuffer == 0)
+ IoStatusBlock->u.Status = STATUS_INVALID_PARAMETER;
+ else if (OutputBufferSize < sizeof(DISK_GEOMETRY))
+ IoStatusBlock->u.Status = STATUS_BUFFER_TOO_SMALL;
+ else if ((file = fopen(path, "r")) != 0) {
+ int cylinders, heads, sectors;
+ if (fscanf(file, "physical %d/%d/%d", &cylinders, &heads, §ors) == 3) {
+ DISK_GEOMETRY* geometry = (DISK_GEOMETRY*) OutputBuffer;
+ geometry->Cylinders.QuadPart = cylinders;
+ geometry->MediaType = FixedMedia;
+ geometry->TracksPerCylinder = heads;
+ geometry->SectorsPerTrack = sectors;
+ // todo - is this always 512, or where is it?
+ geometry->BytesPerSector = 512;
+
+ sz = sizeof(DISK_GEOMETRY);
+ IoStatusBlock->u.Status = STATUS_SUCCESS;
+ }
+ else // unknown proc format
+ IoStatusBlock->u.Status = STATUS_INVALID_PARAMETER;
+
+ fclose(file);
+ }
+ else // unknown proc format
+ IoStatusBlock->u.Status = STATUS_INVALID_PARAMETER;
+ break;
+
+ default:
+ FIXME("Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n",
+ IoControlCode, IoControlCode >> 16, (IoControlCode >> 14) & 3,
+ (IoControlCode >> 2) & 0xFFF, IoControlCode & 3);
+ IoStatusBlock->u.Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+out:
+ if (releaseFd)
+ wine_server_release_fd( DeviceHandle, fd );
+ if (isIde && hEvent)
+ NtSetEvent(hEvent, NULL);
+
+ return isIde;
+#endif
+}
+
/**************************************************************************
* NtDeviceIoControlFile [NTDLL.@]
* ZwDeviceIoControlFile [NTDLL.@]
@@ -827,6 +934,12 @@
IoStatusBlock, IoControlCode,
InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize);
+ if (FILE_IdeDeviceIoControlFile(DeviceHandle, hEvent, UserApcRoutine, UserApcContext,
+ IoStatusBlock, IoControlCode, InputBuffer, InputBufferSize,
+ OutputBuffer, OutputBufferSize)) {
+ return IoStatusBlock->u.Status;
+ }
+
if (CDROM_DeviceIoControl(DeviceHandle, hEvent,
UserApcRoutine, UserApcContext,
IoStatusBlock, IoControlCode,
@@ -1878,3 +1991,4 @@
return ret;
}
+
More information about the wine-devel
mailing list