--- 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; } +