Delphi - How to prevent application hang when writing to LPT port - delphi

I have an application what writes commands to some specialized printers directly on LPT1 port. The code looks like this:
AssignFile(t, 'LPT1');
Rewrite(t);
Write(t,#27 + '#'); // initialize
Sleep(50); // avoid buffer fill
Write(t,#27#32 + Chr(0)); // set default font
...
The problem is that when the printer is not connected to the port, the first Write instruction doesn't do anything, it just hangs up and the entire thread is locked.
Is there a way to define a timeout for these instructions, or can you recommend another library that could do this job? It would be great if it had a Write function similar to the one in Delphi, because the amount of code using this approach is very large, and it would be very hard to change all of it.

You can use SetCommTimeouts to configure a timeout for the printer handle. To get the handle from your TextFile variable, type-cast it to TTextRec and read the Handle field:
var
CommTimeouts: TCommTimeouts;
CommTimeouts.WriteTotalTimeoutConstant := DesiredTimeout;
Win32Check(SetCommTimeouts(TTextRec(t).Handle, CommTimeouts));
You may wish to call GetCommTimeouts first to discover the default values for the other fields before you set the ones you need.

Move your printing code to a separate thread. The built-in text-file functions don't have any timeout mechanism, but you can tell the OS to cancel any pending I/O operations whenever you decide that too much time has passed.
I'd start with CancelSynchronousIo, which cancels all I/O on a given thread. It should allow you to keep all your existing Write calls. Be prepared to handle when they fail upon being cancelled.
That function requires Windows Vista or higher, which shouldn't be a problem nowadays, but won't work if you still need support for Windows XP. In that case, you'll need to use CreateFile to open the port for overlapped I/O. Then you can use CancelIo or CancelIoEx. You'll need to replace all your Write calls since the built-in Delphi functions don't support overlapped operations.

Related

How does this `if not` statement work without parentheses in a new service application?

When creating a new Windows Service in Delphi, it inserts the following:
if not Application.DelayInitialize or Application.Installing then
Application.Initialize;
The author didn't bother including parentheses, so I'm trying to wrap my head around this. It translates to:
if (not Application.DelayInitialize) or Application.Installing then
Application.Initialize;
From what I understand, if both Application.DelayInitialize and Application.Installing are True, then it will go ahead and Initialize the service application. I don't understand why it would be initialized in this scenario - I'm pretty sure it shouldn't be initialized.
Can someone give me some clarification what I'm looking at here?
On a side note, I would never need to enable DelayInitialize as there's no need to be concerned with Server 2003. I would just like to understand what this code is actually meant to do the way it's written.
As the comment inserted in the project source when you create a service application explains, DelayInitialize exists for a specific reason: the requirement to call StartServiceCtrlDispatcher before CoRegisterClassObject. Whether you would need to set it or not, I presume, would really depend on if you need to call CoRegisterClassObject, not if you're targeting server 2003 or not (*). IOW, I wouldn't expect that comment to be updated with every new server version. YMMV, testing might be required.
The implied design here is that you use System.InitProc to call CoRegisterClassObject (**), similar to how the CoInitializeEx call is made by ComObj.pas. InitProc is called from Vcl.Forms.Application.Initialize which is called from Vcl.SvcMgr.TServiceApplication.Initialize.
Now, when Vcl.SvcMgr.TServiceApplication.Installing returns true, that means StartServiceCtrlDispatcher will not to be called. Because the main thread is not going to connect with the service control manager. Instead it will either install or uninstall services and then exit. Then the need for any delayed initialization will become void and in fact a delayed initialization cannot run since no service thread will run (***).
And so this is why the expression is written the way it is, there are no forgotten/missing parenthesis.
(*) D2007 has the comment at which time 2003 R2 is the last server.
(**) From the comment in the project source:
Windows 2003 Server requires StartServiceCtrlDispatcher to be called before CoRegisterClassObject, which can be called indirectly by Application.Initialize.
(***) This is where a delayed initialization is called, guarded by a flag in case there is more than one service in the executable.

Mixing Custom External File Handler with Micro Focus Default EXTFH

I have written a custom external file handler (EXTFH), but there are some cases where I want to revert to the Micro Focus EXTFH. The cases are on a file by file basis (as opposed to a filetype by filetype basis).
My idea is that upon OPEN, I place a marker in the FCD that tells the subsequent operations (READ, WRITE, CLOSE) as to which EXTFH is in use.
My EXTFH has control and the logic can be very simple if there is a place in the FCD that is guaranteed to not be corrupted by MicroFocus.
Is there a place in the FCD (fcd2.h and fcd3.h) that I can mark an open file as being opened by my EXTFH?
My worst case is that I keep a list of the fcd->handle pointers that I have allocated and if I allocated it, then direct to my EXTFH. If not, direct to the MF EXTFH.
Here is the documentation from Micro Focus on EXTFH:
http://supportline.microfocus.com/documentation/books/sx20books/fhexfh.htm
That is older documentation, but is appears to be pretty much up-to-date.
[edit to clarify how we will use detect which to use: We will use the extension on the file name to determine which file handler to use. For instance, if the extension is: .xyz, then use our EXTFH, otherwise use MF EXTFH]. It appears we can check the filename on every fileio, but I think it would be cleaner if we just checked upon OPEN. For subsequent calls for that file, we would just check something in the FCD.

Delphi : force unload injected module

i use this code to determine if a specific module has been injected to my application's process
(i use it to prevent some Packet Sniffer Softwares)
Var
H:Cardinal;
Begin
H:= GetModuleHandle('WSock32.dll');
if H >0 then FreeLibrary(H);
end;
the problem is when i call Freelibrary it do nothing !
i don't wanna show message then terminate the application i just want to unload the injected module silently
thanks in advance
Well, first of all I'll attempt to answer the question as asked. And then, I'll try to argue that you are asking the wrong question.
Modules are reference counted. It's possible that there are multiple references to this module. So, keep calling FreeLibrary:
procedure ForceRemove(const ModuleName: string);
var
hMod: HMODULE;
begin
hMod := GetModuleHandle(PChar(ModuleName));
if hMod=0 then
exit;
repeat
until not FreeLibrary(hMod);
end;
If you were paranoid you might choose to add an alternative termination of the loop to avoid looping indefinitely.
I don't really know that this will work in your scenario. For instance, it's quite plausible that your process links statically to WSock32. In which case no amount of calling FreeLibrary will kick it out. And even if you could kick it out, the fact that your process statically linked to it probably means it's going to fail pretty hard.
Even if you can kick it out, it seems likely that other code in your process will hold references to functions in the module. And so you'll just fail somewhere else. I can think of very few scenarios where it makes sense to kick a module out of your process with complete disregard for the other users of that module.
Now, let's step back and look at what you are doing. You are trying to remove a standard system DLL from your process because you believe that it is only present because your process is having its packets sniffed. That seems unlikely to be true.
Since you state that your process is subject to packet sniffing attack. That means that the process is communicating over TCP/IP. Which means that it probably uses system modules to carry out that communication. One of which is WSock32. So you very likely link statically to WSock32. How is your process going to work if you kill one of the modules used to supply its functionality?
Are you quite sure that the presence of WSock32 in your process indicates that your process is under attack? If a packet sniffer was going to inject a DLL into your process, why would it inject the WSock32 system DLL? Did you check whether or not your process, or one of its dependencies, statically links to WSock32?
I rather suspect that you've just mis-diagnosed what is happening.
Some other points:
GetModuleHandle returns, and FreeLibrary accepts an HMODULE. For 32 bit that is compatible with Cardinal, but not for 64 bit. Use HMODULE.
The not found condition for GetModuleHandle is that the return value is 0. Nowhere in the documentation is it stated that a value greater than 0 indicates success. I realise that Cardinal and HMODULE are unsigned, and so <>0 is the same as >0, but it really makes no sense to test >0. It leaves the programmer thinking, "what is so special about <0?"

Easiest way to find previous instance of an application

I have rewritten a VB6 application in Delphi. It should have only one instance running. How can I do this with minimum of code?
In VB6 we just have to use one single line of code
>
If App.PrevInstance Then
'Take some action
End If
On goggling I did find a solution but it is very length and we have to mess with .drp file.
I do not want to do that.
I want something simpler.
I have some code along the lines of:
var
AppMutex: THandle;
{ .... }
initialization
// Create the mutex
AppMutex := CreateMutex(nil, True, 'MY-APPLICATION-NAME');
if (AppMutex = 0) or (GetLastError = ERROR_ALREADY_EXISTS) then
begin
MessageDlg('My application is already running on this computer.'#13#10+
'You should close the other instance before starting a new one.',mtError,
[mbOK],0);
Halt;
end;
finalization
// Close the mutex
CloseHandle(AppMutex);
but I'm sure the answers in the thread that #mghie linked to are more helpful/richer features!
Edit: Note you can make this into a small unit in it's own right, then just use that unit in your project(s).
Note that in many cases, the user's expecation will be that launching the second instance results in the first instance being restored and brought to the foreground. Don't expect users to understand the difference between restoring a minimized/hidden app and launching from a shortcut or start menu.
In my experience one cannot decide in general wether an application my be started twice or not. It may be for instance perfectly valid to start the same application if it is started in another folder or under another user account or whatever. On the other hand it might be the case that two different applications may not run together if they are started in the same folder or so.
So besides the different approaches with mutexes and semaphores and handling race conditions, it is the wise selection of the mutex's or semaphore's name that handles the above combinations appropriately.
If an application may not run twice at all, take a GUID like name. You can even use the exe's filename if you can ignore that someone might rename it.
Restricting the one-time-start on a specific folder, you can take the exe path into account, but be aware that due to mappings different pathes may end up at the same exe.

What all APIs are affected by {$IOCHECKS OFF}?

We have some ancient Delphi code (might have even originated as Turbo Pascal code) that uses {$I-}, aka {$IOCHECKS
OFF}, which makes the code use IOResult instead of exceptions for disk I/O errors.
I want to get rid of the {$I-} and bring this code forward into the 1990s, but to do that, I'd like to know what all is affected by {$IOCHECKS OFF}. Does this only affect the crufty old built-in I/O functions like AssignFile / Reset / Rewrite / Append / CloseFile? Or does it affect more modern things like TFileStream as well? More importantly, what else might be affected that I'm not thinking of? (Delphi Basics suggests that it also affects MkDir and RmDir. If it affects those, there have to be more.)
The Delphi 2007 Help topic "Input output checking (Delphi)" (ms-help://borland.bds5/devcommon/compdirsinput_outputchecking_xml.html) says that this affects "I/O procedure[s]", and that "I/O procedures are described in the Delphi Language Guide." This doesn't help much, since CodeGear has never shipped a Language Guide, and the last time Borland shipped one was Delphi 5.
Which functions and classes behave differently under {$I-}?
EDIT: The accepted answer gives some great background, but here's the quick summary in alphabetized list form: {$IOCHECKS OFF} only affects the following routines from the System unit.
Append
BlockRead
BlockWrite
ChDir
CloseFile
Eof
Eoln
Erase
FilePos
FileSize
Flush
MkDir
Read
Readln
Rename
Reset
Rewrite
RmDir
Seek
SeekEof
SeekEoln
SetLineBreakStyle
Truncate
Write
Writeln
Since $I is a compiler directive, it can only affect compiler-generated code, and it can only affect code that actually gets compiled.
For those two reasons, it cannot affect things like TFileStream. It's a class in Classes.pas, which is a unit you don't compile. Any code in it is not affected by the $I directive. Furthermore, the compiler doesn't treat that class specially in any way. It's just another ordinary class.
The $I directive affects the language built-in functions that you've mentioned. The compiler generates calls to those functions specially. It also affects calls to write, writeln, and readln. It should also affect BlockRead and BlockWrite.
You can check the source code. Anything that calls SetInOutRes is susceptible to $I. That includes functions that open files (Append, Reset, and Rewrite), as well as anything else that accepts a parameter of type file or TextFile (Flush, BlockRead, BlockWrite, Erase, FilePos, Seek, FileSize, Read, Readln, Write, Writeln, Rename, Eof, SeekEof, Eoln, SeekEol, Truncate, SetLineBreakStyle, and CloseFile). Also, anything that calls InOutError (ChDir, MkDir, amd RmDir).
Notably absent from the list is AssignFile. That function doesn't actually do any I/O. It just sets up the file record so that Append, Reset, and Rewrite will know what to do.
I should point out that looking at the source code is just inference. The $I directive controls whether the compiler will insert calls to the __IOTest function in your own code after you call certain other functions. That function checks the value of InOutRes, and if it's not zero, it raises a run-time error (which may yield an exception if SysUtils is included in your program). We can't check the source code to directly find out what functions are affected by $I (since it's only called in compiler-generated code), so we're really just looking for which functions set InOutRes, with the assumption that they wouldn't bother doing that if they didn't know the compiler would check for it afterward.

Resources