Access Denied when initialize Disk - delphi

I have following code:
if (APartitionStyle = 0) then //mbr
begin
hDevice := CreateFile(
PChar(ADisk),
GENERIC_WRITE and GENERIC_READ,
FILE_SHARE_WRITE and FILE_SHARE_READ,
nil,
OPEN_EXISTING,
0,
0);
error := SysErrorMessage(GetLastError);
if (hDevice = INVALID_HANDLE_VALUE) then
begin
error := SysErrorMessage(GetLastError);
result := error;
end;
dwIoControlCode := IOCTL_DISK_CREATE_DISK;
dsk.PartitionStyle := PARTITION_STYLE_MBR;
dsk.mbr.Signature := Random(9999);
lpInBuffer := #dsk;
nInBufferSize := sizeof(CREATE_DISK);
lpOutBuffer := nil;
nOutBufferSize := 0;
lpOverlapped := nil;
bresult := DeviceIOControl(
hDevice,
dwIoControlCode,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize,
lpBytesReturned,
lpOverlapped);
if not bresult then
begin
error := SysErrorMessage(GetLastError);
result := error;
end;
I have executed the code as administrator or system and as user (with admin privilegs).
I have read something like: Driver is locked. Is there something missing in the code?
The handle is successfully created. On DeviceIOControl I get an error "Access Denied".

You are passing incorrect values to CreateFile(). You are using the and operator to combine bit flags:
hDevice := CreateFile(
PChar(ADisk),
GENERIC_WRITE and GENERIC_READ, { = 0 ! }
FILE_SHARE_WRITE and FILE_SHARE_READ, { = 0 ! }
nil,
OPEN_EXISTING,
0,
0);
You need to use the or operator instead:
hDevice := CreateFile(
PChar(ADisk),
GENERIC_WRITE or GENERIC_READ, { = $C0000000 ! }
FILE_SHARE_WRITE or FILE_SHARE_READ, { = $00000003 ! }
nil,
OPEN_EXISTING,
0,
0);

Related

Get file/folder list of group permission

In Delphi, using WinAPI, I am try to get list of groups that have permission to file or folder, example group list:
What function or records I need to use to get these information?
I am try to using GetNamedSecurityInfoA but it fails - function return false and variables sidGrp with dacl are still nil, but variable sc (Security Descriptor) is initialized.
procedure TForm1.Button2Click(Sender: TObject);
var
sciezka: array [0 .. 256] of ansiChar;
sidOwn: PSID;
sidGrp: PSID;
dacl: PACL;
sacl: PACL;
sc: PSECURITY_DESCRIPTOR;
success: DWORD;
access: EXPLICIT_ACCESS_A;
sid_id_auth: _SID_IDENTIFIER_AUTHORITY;
hToken: THandle;
TokenUserPoint: pTokenUser;
bufferSize: DWORD;
BufferSize2: DWORD;
ptgGroups: PTokenGroups;
psidAdmin: PSID;
x: Integer;
const
SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
begin
Memo1.Lines.Clear();
ZeroMemory(#sciezka, Length(sciezka));
GetMem(ptgGroups, 1024);
bufferSize := 0;
System.AnsiStrings.StrLCopy(#sciezka, PAnsiChar(AnsiString(Edit1.Text)), Length(Edit1.Text));
// success := CheckFileAccess(string(sciezka), FILE_READ_DATA);
success := Cardinal(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY OR TOKEN_READ, hToken));
success := Cardinal(GetTokenInformation(hToken, TokenUser, ptgGroups, 1024, bufferSize));
GetMem(TokenUserPoint, BYTE(bufferSize));
//FillChar(TokenUserPoint, bufferSize, 0);
//success := Cardinal(GetTokenInformation(hToken, TokenUser, TokenUserPoint, bufferSize, BufferSize2));
sidOwn := nil;
sidGrp := nil;
dacl := nil;
sacl := nil;
sc := nil;
sid_id_auth.Value[0] := 2;
sid_id_auth.Value[1] := 3;
sid_id_auth.Value[2] := 5;
sid_id_auth.Value[3] := 0;
sid_id_auth.Value[4] := 0;
sid_id_auth.Value[5] := 0;
success := Cardinal(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, psidAdmin));
{$R-}
{ for x := 0 to ptgGroups.GroupCount - 1 do
if EqualSid(psidAdmin, ptgGroups.Groups[x].Sid) then
begin
Memo1.Lines.Add('Jest administrator');
Break;
end; }
{$R+}
// success := GetFileSecurityA(sciezka, GROUP_SECURITY_INFORMATION, sc, );
success := GetNamedSecurityInfoA(sciezka,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION,
nil,
sidGrp,
dacl,
nil,
sc
);
Memo1.Lines.Add('Funkcja zwróciła wartoć = ' + success.ToHexString());
if IsValidSid(sidOwn) then Memo1.Lines.Add('sidOwn - poprawne')
else Memo1.Lines.Add('sidOwn - niepoprawne');
if IsValidSid(sidGrp) then Memo1.Lines.Add('sidGrp - poprawne')
else Memo1.Lines.Add('sidGrp - niepoprawne');
if(sidOwn = nil) then
Memo1.Lines.Add('sidOwn is null');
if(sidGrp = nil) then
Memo1.Lines.Add('sidGrp is null');
end;
As #FredS said, the parameters use pointer of pointer, and you declare here:
sidGrp: PSID;
Dacl: PACL;
Sacl: PACL;
sidGrp := nil;
dacl := nil;
sacl := nil;
sc: PSECURITY_DESCRIPTOR;
success := GetNamedSecurityInfoA(sciezka,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION,
nil,
sidGrp,
dacl,
nil,
sc
);
which is equal to:
success := GetNamedSecurityInfoA(sciezka,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION,
nil,
nil,
nil,
nil,
nil
);
And you will get the return error: 87(ERROR_INVALID_PARAMETER)
According to the function document:
success := GetNamedSecurityInfoA(sciezka,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION,
nil,
#sidGrp,
#dacl,
nil,
sc
);

Webcamera supported video formats

I'm trying to get stream video from USB Web-camera in Delphi XE. Found a working example, but I can't figure out how to get all supported video formats (resolution, color depth, etc). This example works well with fixed Mediatype:
var
Form1: TForm1;
IniFile: TIniFile;
DeviceName: OleVariant;
PropertyName: IPropertyBag;
pDevEnum: ICreateDEvEnum;
pEnum: IEnumMoniker;
pMoniker: IMoniker;
MArray1: array of IMoniker;
FGraphBuilder: IGraphBuilder;
FCaptureGraphBuilder: ICaptureGraphBuilder2;
FMux: IBaseFilter;
FSink: IFileSinkFilter;
FMediaControl: IMediaControl;
FVideoWindow: IVideoWindow;
FVideoCaptureFilter: IBaseFilter;
FAudioCaptureFilter: IBaseFilter;
FVideoRect: TRect;
FBaseFilter: IBaseFilter;
FSampleGrabber: ISampleGrabber;
MediaType: AM_MEDIA_TYPE;
function TForm1.Initializ: HResult;
begin
Result := CoCreateInstance(CLSID_SystemDeviceEnum, NIL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, pDevEnum);
if Result <> S_OK then
EXIT;
Result := pDevEnum.CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
pEnum, 0);
if Result <> S_OK then
EXIT;
setlength(MArray1, 0);
while (S_OK = pEnum.Next(1, pMoniker, Nil)) do
begin
setlength(MArray1, length(MArray1) + 1);
MArray1[length(MArray1) - 1] := pMoniker;
Result := pMoniker.BindToStorage(NIL, NIL, IPropertyBag, PropertyName);
if FAILED(Result) then
Continue;
Result := PropertyName.Read('FriendlyName', DeviceName, NIL);
if FAILED(Result) then
Continue;
ListBox1.Items.Add(DeviceName);
end;
if ListBox1.Count = 0 then
begin
ShowMessage('Webcam not found!');
Result := E_FAIL;
EXIT;
end;
ListBox1.ItemIndex := 0;
Result := S_OK;
end;
function TForm1.CreateGraph: HResult;
var
pConfigMux: IConfigAviMux;
begin
FVideoCaptureFilter := NIL;
FVideoWindow := NIL;
FMediaControl := NIL;
FSampleGrabber := NIL;
FBaseFilter := NIL;
FCaptureGraphBuilder := NIL;
FGraphBuilder := NIL;
Result := CoCreateInstance(CLSID_FilterGraph, NIL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, FGraphBuilder);
if FAILED(Result) then
EXIT;
Result := CoCreateInstance(CLSID_SampleGrabber, NIL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, FBaseFilter);
if FAILED(Result) then
EXIT;
Result := CoCreateInstance(CLSID_CaptureGraphBuilder2, NIL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, FCaptureGraphBuilder);
if FAILED(Result) then
EXIT;
Result := FGraphBuilder.AddFilter(FBaseFilter, 'GRABBER');
if FAILED(Result) then
EXIT;
Result := FBaseFilter.QueryInterface(IID_ISampleGrabber, FSampleGrabber);
if FAILED(Result) then
EXIT;
if FSampleGrabber <> NIL then
begin
ZeroMemory(#MediaType, sizeof(AM_MEDIA_TYPE));
with MediaType do
begin
majortype := MEDIATYPE_Video;
subtype := MEDIASUBTYPE_RGB24;
formattype := FORMAT_VideoInfo;
end;
FSampleGrabber.SetMediaType(MediaType);
FSampleGrabber.SetBufferSamples(TRUE);
FSampleGrabber.SetOneShot(FALSE);
end;
Result := FCaptureGraphBuilder.SetFiltergraph(FGraphBuilder);
if FAILED(Result) then
EXIT;
if ListBox1.ItemIndex >= 0 then
begin
MArray1[ListBox1.ItemIndex].BindToObject(NIL, NIL, IID_IBaseFilter,
FVideoCaptureFilter);
FGraphBuilder.AddFilter(FVideoCaptureFilter, 'VideoCaptureFilter');
end;
Result := FCaptureGraphBuilder.RenderStream(#PIN_CATEGORY_PREVIEW, nil,
FVideoCaptureFilter, FBaseFilter, nil);
if FAILED(Result) then
EXIT;
Result := FGraphBuilder.QueryInterface(IID_IVideoWindow, FVideoWindow);
if FAILED(Result) then
EXIT;
FVideoWindow.put_WindowStyle(WS_CHILD or WS_CLIPSIBLINGS);
FVideoWindow.put_Owner(Panel1.Handle);
FVideoRect := Panel1.ClientRect;
FVideoWindow.SetWindowPosition(FVideoRect.Left, FVideoRect.Top,
FVideoRect.Right - FVideoRect.Left, FVideoRect.Bottom - FVideoRect.Top);
FVideoWindow.put_Visible(TRUE);
Result := FGraphBuilder.QueryInterface(IID_IMediaControl, FMediaControl);
if FAILED(Result) then
EXIT;
FMediaControl.Run();
end;
How can I get all webcam supported video formats to combobox? If I need something to add, please, post in comment, thanks.
The code snippet provided is not quite relevant and presumably is just what you have at the moment. To enumerate video formats you typically obtain an output pin of interest first, which you don't do in your code snippet and rely on RenderStream call to do dirty work for you.
Then, you obtain IAMStreamConfig interface pointer from the pin and enumerate the media types (formats). Alternatively you can enumerate using IPin::EnumMediaTypes, however IAMStreamConfig::GetStreamCaps is the canonical way, esp. for webcams.
Bonus code here:
// The TVideoSample class provides access to WebCams and similar Video-capture
// devices via DirectShow.
...
// Fills "FormatArr" with list of all supported video formats (resolution, compression etc...)
FUNCTION TVideoSample.LoadListOfResolution: HResult;
...

Piping between two programs Delphi

I want to make a program that will do piping between two programs
Getting input from first, giving it to second that will do processing on it and give it back to me which I will give back to first
if Input <> '-' then
InS := TFileStream.Create(Input, fmOpenRead or fmShareDenyWrite)
else
InS := THandleStream.Create(GetStdHandle(STD_INPUT_HANDLE));
if Output <> '-' then
OutS := TFileStream.Create(Output, fmCreate or fmShareExclusive)
else
OutS := THandleStream.Create(GetStdHandle(STD_OUTPUT_HANDLE));
FillChar(StartupInfo, sizeof(StartupInfo), 0);
FillChar(ProcessInfo, sizeof(ProcessInfo), 0);
SecurityAttributes.nLength := sizeof(SecurityAttributes);
SecurityAttributes.bInheritHandle := True;
SecurityAttributes.lpSecurityDescriptor := Nil;
CreatePipe(OutPipe, InPipe, #SecurityAttributes, 0);
StartupInfo.cb := sizeof(StartupInfo);
StartupInfo.wShowWindow := SW_HIDE;
StartupInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
StartupInfo.hStdInput := InPipe;
StartupInfo.hStdOutput := OutPipe;
Handle := CreateProcess(PChar(CLSAppInfo.CLSExeName),
PChar(Format('a - -', [])), nil, nil, True, 0, nil, PChar(GetCurrentDir),
StartupInfo, ProcessInfo);
if Handle then
begin
GetMem(Buffer, BLOCK_SIZE);
repeat
ReadByte := InS.Read(Buffer^, BLOCK_SIZE);
isOK := WriteFile(InPipe, Buffer^, ReadByte, WroteByte, nil);
WriteLn(ReadByte.ToString);
WriteLn(isOK.ToString());
if (not isOK) or (ReadByte = 0) then
break;
repeat
isOK := ReadFile(OutPipe, Buffer^, 255, ReadByte, nil);
if not isOK then
break;
if ReadByte = 0 then
break;
OutS.Write(Buffer, ReadByte);
until 0 = 1;
until 0 = 1;
FreeMem(Buffer);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
CloseHandle(InPipe);
CloseHandle(OutPipe);
OutS.Free;
InS.Free;
But this just starts the programs and the programs ends without doing anything

MAPISendMail access violation

I have a problem with MapiSendMail function of MAPI32.dll. Everything seems fine, message is completed, then I send it by winapi function, and i get an Access violation error, it happend in MAPISendMail. Here's the fragment of the code:
MAPIModule := LoadLibrary(PWideChar(MAPIDLL));
if MAPIModule = 0 then
Result := -1
else
try
#SM := GetProcAddress(MAPIModule, 'MAPISendMail');
if #SM <> nil then
begin
Result := SM(0, application.Handle, Msg, MAPI_DIALOG {or MAPI_LOGON_UI}, 0);
end
else
Result := 1;
finally
end;
Also I was trying to change GetProcAddres to MAPISendMailW or MAPISendMailHelper, but then #SM was nil.
#Edit1
function TMail._SendMAPIEmail(const aTo, aAtts: array of AnsiString; const body, subject, SenderName, SenderEmail: string; ShowError: Boolean = true): Integer;
var
SM: TFNMapiSendMail;
Msg: MapiMessage;
lpSender: MapiRecipDesc;
Recips: array of MapiRecipDesc;
Att: array of MapiFileDesc;
TempAttNames: array of pAnsiChar;
TempAttNamesAnsi: array of AnsiString;
TempAttPaths: array of pAnsiChar;
TempRecip: array of pAnsiChar;
p1, LenTo, LenAtts: Integer;
MAPIModule: HModule;
sError: String;
i: integer;
begin
try
FillChar(Msg, SizeOf(Msg), 0);
{ get the length of all arrays passed to this function }
LenTo := length(aTo);
if Trim(aAtts[0]) <> '' then
LenAtts := length(aAtts)
else
LenAtts := 0;
{ ... }
SetLength(Recips, LenTo);
SetLength(TempRecip, LenTo);
Setlength(Att, LenAtts);
SetLength(TempAttNames, LenAtts);
SetLength(TempAttPaths, LenAtts);
SetLength(TempAttNamesAnsi, LenAtts);
{ to }
for p1 := 0 to LenTo - 1 do
begin
FillChar(Recips[p1], SizeOf(Recips[p1]), 0);
Recips[p1].ulReserved := 0;
Recips[p1].ulRecipClass := MAPI_TO;
{ Upgrade }
Recips[p1].lpszName := '';
TempRecip[p1] := pAnsichar(aTo[p1]);
Recips[p1].lpszAddress := TempRecip[p1];
end;
{ atts }
for p1 := 0 to LenAtts - 1 do
begin
FillChar(Att[p1], SizeOf(Att[p1]), 0);
FillChar(TempAttPaths[p1], SizeOf(pAnsiChar), 0);
FillChar(TempAttNames[p1], SizeOf(pAnsiChar), 0);
FillChar(TempAttNamesAnsi[01], SizeOf(AnsiChar), 0);
Att[p1].ulReserved := 0;
Att[p1].flFlags := 0;
Att[p1].nPosition := Cardinal($FFFFFFFF);
{ Upgrade }
TempAttPaths[p1] := pAnsichar(aAtts[p1]);
Att[p1].lpszPathName := TempAttPaths[p1];
TempAttNamesAnsi[p1] := AnsiString((ExtractFileName(string(aAtts[p1]))));
TempAttNames[p1] := pAnsiChar(TempAttNamesAnsi[p1]);
Att[p1].lpszFileName := TempAttNames[p1];
end;
{ fill the message }
with Msg do
begin
ulReserved := 0;
if subject <> '' then
{ Upgrade }
lpszSubject := pAnsichar(AnsiString(subject));
if body <> '' then
{ Upgrade }
lpszNoteText := pAnsichar(AnsiString(body));
if SenderEmail <> '' then
begin
lpSender.ulRecipClass := MAPI_ORIG;
if SenderName = '' then
lpSender.lpszName := pAnsichar(AnsiString(SenderEmail))
else
lpSender.lpszName := pAnsichar(AnsiString(SenderName));
lpSender.lpszAddress := pAnsichar(AnsiString(SenderEmail));
lpSender.ulEIDSize := 0;
lpSender.lpEntryID := nil;
lpOriginator := #lpSender;
end
else
Msg.lpOriginator := nil;
Msg.lpszMessageType := nil;
Msg.lpszDateReceived := nil;
Msg.lpszConversationID := nil;
Msg.flFlags := 0;
Msg.nRecipCount := LenTo;
Msg.lpRecips := #Recips[0];
Msg.nFileCount := LenAtts;
Msg.lpFiles := #Att[0];
end;
MAPIModule := LoadLibrary(PWideChar(MAPIDLL));
if MAPIModule = 0 then
Result := -1
else
try
#SM := GetProcAddress(MAPIModule, 'MAPISendMail');
if #SM <> nil then
begin
//Result := MapiSendMail(0, application.Handle, Msg, MAPI_DIALOG, 0);
Result := SM(0, 0, Msg, MAPI_DIALOG {or MAPI_LOGON_UI}, 0);
end
else
Result := 1;
finally
if Assigned(Att) and (Msg.nFileCount > 0) then
begin
for i := 0 to Msg.nFileCount - 1 do
begin
if Assigned(Att[i].lpszPathName) then
Att[i].lpszPathName := nil;
if Assigned(Att[i].lpszFileName) then
Att[i].lpszFileName := nil;
//FreeMem(Att[i].lpszPathName);
//Dispose(Att[i].lpszPathname);
//StrDispose(Att[i].lpszPathName);
//Dispose(Att[i].lpszFileName);
//StrDispose(Att[i].lpszFileName);
end;
Att := nil;
end;
if Assigned(Recips) and (Msg.nRecipCount > 0) then
begin
for i := 0 to Msg.nRecipCount - 1 do
begin
if Assigned(Recips[i].lpszName) then
Recips[i].lpszName := nil;
if Assigned(Recips[i].lpszAddress) then
Recips[i].lpszAddress := nil;
//if Assigned(Recips[i].lpszName) then
//Dispose(Recips[i].lpszName);
//if Assigned(Recips[i].lpszAddress) then
//Dispose(Recips[i].lpszAddress);
end;
Recips := nil;
end;
end;
Under Win32
Under Win32 it should not be a problem. Just first try calling MapiSendMail with very simple MapiMessage and if it will work, add complexity little by little. Your code is just too complex to debug it visually. Did you call MapiSendMail with very simple MapiMessage, just for testing? Please try the following code, it works for sure:
procedure TestSendExA(const APath1, ACaption1, APath2, ACaption2: AnsiString);
var
R: Integer;
MSG: TMapiMessage;
F: Array [0..1] of TMapiFileDesc;
Recipients: array[0..1] of TMapiRecipDesc;
Originator : array[0..0] of TMapiRecipDesc;
begin
if not FileExists(APath1) or not FileExists(APath2) then raise Exception.Create('File not found');
FillChar(Msg, SizeOf(Msg), 0);
Msg.lpszSubject := 'testo';
Msg.lpszNoteText := 'Hi there!';
Msg.lpszDateReceived := '2015/01/25 12:34';
Msg.lpszConversationId := '1234.test#ritlabs.com';
Msg.flFlags := MAPI_RECEIPT_REQUESTED;
FillChar(Recipients, SizeOf(Recipients), 0);
with Recipients[0] do
begin
ulRecipClass := MAPI_TO;
lpszName := 'Maxim Masiutin';
lpszAddress := 'maxim.test#ritlabs.com';
end;
with Recipients[1] do
begin
ulRecipClass := MAPI_CC;
lpszName := 'Vasilii Pupkin';
lpszAddress := 'pupkin.test#ritlabs.com';
end;
FillChar(Originator, SizeOf(Originator), 0);
with Originator[0] do
begin
ulRecipClass := MAPI_TO;
lpszName := 'Maxim Masiutin';
lpszAddress := 'max#ritlabs.com';
end;
Msg.lpOriginator := #Originator;
Msg.nRecipCount := 2;
Msg.lpRecips := #Recipients;
Msg.nFileCount := 2;
Msg.lpFiles := #F;
FillChar(F, SizeOf(F), 0);
F[0].lpszPathName := PAnsiChar(APath1);
F[0].lpszFileName := PAnsiChar(ACaption1);
F[1].lpszPathName := PAnsiChar(APath2);
F[1].lpszFileName := PAnsiChar(ACaption2);
R := MAPISendMail(MapiSession, 0, Msg, 0, 0);
end;
The MapiSession in the above example is a handle to the session returned by MapiLogon.
This sample code requires that you pass two valid file paths to valid files in APath1 and APath2.
Under Win64
It is the record alignment of MapiMessage and other records that it is important when you work with Simple MAPI from Delphi: (1) make sure the records don't have "packed" prefix; and (2) make sure you have {$A8} compiler directive is explicitly specified before first record definition. This will work fine under both Win32 and Win64.

Readfile from pipe blocked

In the following code, I use "commandLine" parameter to create another process, but this subprocess possibly did not write sth into pipe, so the readfile function would block.
How to let it return if there is no data?
if (CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine), #saSecurity, #saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess))
then
sOutputString := '';
begin
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
Application.ProcessMessages();
until (dRunning <> WAIT_TIMEOUT);
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
repeat
dRead := 0;
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
// But it is blocked......
until (dRead < CReadBuffer);
end;
You can check if the named pipe contains data before reading from it
if PeekNamedPipe(hRead, nil, 0, nil, #dwBytesAvailable, nil) then
begin
if dwBytesAvailable > 0 then
begin
ReadFile(...);
end;
end;

Resources