Из моего приложения веб-сервера мне нужно проверить размер физического сектора жесткого диска, на котором находится приложение. Для этого я использую DeviceIoControl
с IOCTL_STORAGE_QUERY_PROPERTY
для запроса StorageAccessAlignmentProperty
. Проблема в том, что когда я пытаюсь запустить эти команды с веб-сервера, я получаю сообщение об ошибке «Отказано в доступе».
Как я могу получить размер физического сектора жесткого диска, на котором находится inetpub, из приложения веб-сервера??
Я знаю из https://msdn.microsoft.com/windows/compatibility/advanced-format-disk-compatibility-update, что в Windows 8 Microsoft представила новый API, который позволяет совершать вызовы из непривилегированного приложения. API представляет собой новый информационный класс FileFsSectorSizeInformation
со связанной структурой FILE_FS_SECTOR_SIZE_INFORMATION
, но я не знаю, как заставить его работать с Delphi.
Это мой фактический код, который не работает (написан в Delphi):
{~~~~~~~~~~~~~~~~~~~~~~~~~}
procedure _CheckSectorSize;
type
STORAGE_PROPERTY_ID = (StorageDeviceProperty = 0,
StorageAdapterProperty,
StorageDeviceIdProperty,
StorageDeviceUniqueIdProperty,
StorageDeviceWriteCacheProperty,
StorageMiniportProperty,
StorageAccessAlignmentProperty,
StorageDeviceSeekPenaltyProperty,
StorageDeviceTrimProperty,
StorageDeviceWriteAggregationProperty,
StorageDeviceDeviceTelemetryProperty,
StorageDeviceLBProvisioningProperty,
StorageDevicePowerProperty,
StorageDeviceCopyOffloadProperty,
StorageDeviceResiliencyProperty,
StorageDeviceMediumProductType,
StorageAdapterCryptoProperty,
StorageDeviceIoCapabilityProperty = 48,
StorageAdapterProtocolSpecificProperty,
StorageDeviceProtocolSpecificProperty,
StorageAdapterTemperatureProperty,
StorageDeviceTemperatureProperty,
StorageAdapterPhysicalTopologyProperty,
StorageDevicePhysicalTopologyProperty,
StorageDeviceAttributesProperty);
STORAGE_QUERY_TYPE = (PropertyStandardQuery = 0,
PropertyExistsQuery = 1,
PropertyMaskQuery = 2,
PropertyQueryMaxDefined = 3);
_STORAGE_PROPERTY_QUERY = packed record
PropertyId: STORAGE_PROPERTY_ID;
QueryType: STORAGE_QUERY_TYPE;
AdditionalParameters: array[0..9] of Byte;
end;
_STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR = packed record
Version: DWORD; // Contains the size of this structure, in bytes. The value of this member will change as members are added to the structure.
Size: DWORD; // Specifies the total size of the data returned, in bytes. This may include data that follows this structure.
BytesPerCacheLine: DWORD; // The number of bytes in a cache line of the device.
BytesOffsetForCacheAlignment: DWORD; // The address offset necessary for proper cache access alignment, in bytes.
BytesPerLogicalSector: DWORD; // The number of bytes in a logical sector of the device.
BytesPerPhysicalSector: DWORD; // The number of bytes in a physical sector of the device.
BytesOffsetForSectorAlignment: DWORD; // The logical sector offset within the first physical sector where the first logical sector is placed, in bytes.
end;
var
aVolumePath: array[0..MAX_PATH] of AnsiChar;
aVolumeName: array[0..MAX_PATH] of AnsiChar;
hFile: THANDLE;
inbuf: _STORAGE_PROPERTY_QUERY;
outbuf: _STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR;
dwLen: DWORD;
i: integer;
begin
// Convert the directory to a Volume Name
aVolumePath[0] := #$00;
if not GetVolumePathNameA(pAnsiChar(DFRooter_HayStackDirectory), // _In_ LPCTSTR lpszFileName,
aVolumePath, // _Out_ LPTSTR lpszVolumePathName,
length(aVolumePath)) then raiseLastOsError; // _In_ DWORD cchBufferLength
aVolumeName[0] := #$00;
if not GetVolumeNameForVolumeMountPointA(aVolumePath, // _In_ LPCTSTR lpszVolumeMountPoint,
aVolumeName, // _Out_ LPTSTR lpszVolumeName,
length(aVolumeName)) then raiseLastOsError; // _In_ DWORD cchBufferLength
// Opening a physical device so no trailing '\'. Trailing '\' would open the ROOT DIR instead of the volume
for i := 1 to High(aVolumeName) do
if aVolumeName[i] = #0 then begin
if aVolumeName[i-1] = '\' then aVolumeName[i-1] := #0;
break;
end;
//create the file
hFile := CreateFileA(PAnsiChar(@aVolumeName[0]), // _In_ LPCTSTR lpFileName,
GENERIC_READ, // _In_ DWORD dwDesiredAccess,
FILE_SHARE_READ or FILE_SHARE_WRITE, //_In_ DWORD dwShareMode,
0, // _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
OPEN_EXISTING, // _In_ DWORD dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL, // _In_ DWORD dwFlagsAndAttributes,
0); // _In_opt_ HANDLE hTemplateFile
if (hFile = INVALID_HANDLE_VALUE) then raiseLastOsError;
try
ZeroMemory(@inbuf, SizeOf(inbuf));
ZeroMemory(@outbuf, SizeOf(outbuf));
inbuf.QueryType := PropertyStandardQuery;
inbuf.PropertyId := StorageAccessAlignmentProperty;
outbuf.Size := sizeOf(outbuf);
if not DeviceIoControl(hFile, // _In_ HANDLE hDevice,
IOCTL_STORAGE_QUERY_PROPERTY, // _In_ DWORD dwIoControlCode,
@inbuf, // _In_opt_ LPVOID lpInBuffer,
sizeof(inbuf), // _In_ DWORD nInBufferSize,
@outbuf, // _Out_opt_ LPVOID lpOutBuffer,
sizeof(outbuf), // _In_ DWORD nOutBufferSize,
dwLen, // _Out_opt_ LPDWORD lpBytesReturned,
nil) then raiseLastOsError; // _Inout_opt_ LPOVERLAPPED lpOverlapped
finally
CloseHandle(hFile);
end;
end;
IOCTL_STORAGE_QUERY_PROPERTY
не нужны никакие привилегии. он работает нормально даже из процесса с низкой целостностью. также вы можете использовать, скажем,IOCTL_DISK_GET_DRIVE_GEOMETRY
- также принимать любой дескриптор диска и работать с процессом с низкой целостностью - person RbMm   schedule 17.02.2018GENERIC_READ
доступ. используйте 0 здесь - person RbMm   schedule 17.02.2018GENERIC_READ
, который здесь не нужен - person RbMm   schedule 17.02.2018