FBServ Framework - NTServices in FreeBASIC

User contributed sources that have become inactive, deprecated, or generally unusable. But ... we don't really want to throw them away either.
voodooattack
Posts: 605
Joined: Feb 18, 2006 13:30
Location: Alexandria / Egypt
Contact:

FBServ Framework - NTServices in FreeBASIC

Post by voodooattack »

Hello there! :)

Here's my implemention of the Windows NT (2000, XP, 2003, Vista) service specifications..

I've finally finished it, and i guess its ready to be released.

Please check readme.txt for info on usage, i'm not rewriting all that stuff here :P


Download: http://voodooattack.sitesled.com/FB/FBServ.zip
Download v0.1: http://voodooattack.sitesled.com/FB/FBServ-0.1.zip
Download v0.2: http://voodooattack.sitesled.com/FB/FBServ-0.2.zip

All Comments, Feedback, Bug reports, criticism are welcome.. :)

EDIT:

-- New version 0.2
-- HOTFIXED

Code: Select all

  Change log:
  ~~~~~~~~~~~

        0.2
            ->  Hotfix: SrvInstallService() workaround for XPSP1 bug.

            ->  Hotfix: SrvGetServiceStatus() Error checking -thanks coderJeff

            --  New: External Control Application. [ConsoleControl.bas]
                You can use it for services without a command-line interface.
                Can Install/Uninstall/Start/Stop the service.

            --  Change: now undefining _ALLOWCMDLINE__ will completely remove
                other dependencies (Control functions, etc..)
                (exe file size can be slimmed down around ~11KB!!)

            --  New: NTMake.cmd: [Optional] allows linking to ntdll directly, 
                will replace msvcrt's imports with their faster low-level 
                equivalents:
                    
                    _itoa
                    memcpy
                    memset
                    strcat
                    strcpy
                    strlen
                    strrchr
                    tolower
                    toupper
                    _ultoa

                    perhaps even more..
                
                All replaced at FreeBASIC's run-time library level.. 
                Allows for almost 2x-4x speed on NT systems..

            --  Fixed service description handling on older systems.
                Will set it via registery directly, if ChangeServiceConfig2 
                Doesn't exist on the target system.

            --  Added optional memory compacting mechanism.
                Flushing the process' Physical memory (RAM) to the pagefile.
                can dramatically decrease physical memory usage..
 
            --  Many other changes/fixes..

        0.1
            --  Many minor fixes/changes.

        0.0
            --  First version..
Last edited by voodooattack on Apr 15, 2006 10:55, edited 3 times in total.
Imortis
Moderator
Posts: 1924
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Post by Imortis »

I haven't had a chance to fool with this, but it looks pretty solid. It it even half works, you did a great job. I've lookied into doing this kind of thing myself, and it was way over my head.
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

This is going to be very useful. I tried it out. Maybe it's just fb/header versions but to get it to compile I had to do the following (line numbers might slightly off):

Code: Select all

fbservice.bi (158): ErrorString should be passed as @ErrorString since FormatMessage is allocating the buffer.

fbservice.bi (824): Exit Sub should be Exit Function

fbservmain.bas (45): My version of FB did not like a goto inside a scope block that had local variables.  I changed it to an If then block.
After compiling it, I tried it out on WinXP. It installed and uninstalled correctly. I could not get the service to start. It returned ERROR_SERVICE_REQUEST_TIMEOUT. The only thing I could see that was obvious was that _HandlerEx does not always update the SCM with the status. But even after adding that, it just seems to timeout during StartSevice().

I think the framework is good, and there are lots of comments to guide a programmer through the setup.
voodooattack
Posts: 605
Joined: Feb 18, 2006 13:30
Location: Alexandria / Egypt
Contact:

Post by voodooattack »

Thanks alot guys :)
coderJeff wrote:This is going to be very useful. I tried it out. Maybe
it's just fb/header versions but to get it to compile I had to do the following (line numbers might slightly off):

Code: Select all

fbservice.bi (158): ErrorString should be passed as @ErrorString since FormatMessage is allocating the buffer.

fbservice.bi (824): Exit Sub should be Exit Function

fbservmain.bas (45): My version of FB did not like a goto inside a scope block that had local variables.  I changed it to an If then block.
After compiling it, I tried it out on WinXP. It installed and uninstalled correctly. I could not get the service to start. It returned ERROR_SERVICE_REQUEST_TIMEOUT. The only thing I could see that was obvious was that _HandlerEx does not always update the SCM with the status. But even after adding that, it just seems to timeout during StartSevice().

I think the framework is good, and there are lots of comments to guide a programmer through the setup.
What version are you using?
I've made this in FB 0.15b, i guess you're using 0.16b?

I think i'll have to install it and check where the problems is :-)

ERROR_SERVICE_REQUEST_TIMEOUT should occur if the service did not connect to the SCM..

Code: Select all

e = StartServiceCtrlDispatcher(_LPSrvTable)
a good idea could be removing the scope block..
i've used it so i dont preserve the variables throughout the full execution time. (bExit, curState)

as for debugging, i use a simple method to check variables/errors...

Code: Select all

MessageBox NULL,"_ServiceMain is starting..", _
                            _SERVICEDISPNAME__, _
                            MB_ICONINFORMATION OR MB_SERVICE_NOTIFICATION
... and so on :D
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

I reverted to my copy of fbc 15 and old windows headers and the code compiles fine as is. There are some issues wrt compiler versions but I can easily work around that.

It looks like everything that's needed is in the framework. Even though the service doesn't do anything, should it possible to start the service anyway? i.e. get it to the running state? Do I need to set/return something from one of the handler functions in MyService.bas to signal the service to start? I'm running on XPsp1.
voodooattack
Posts: 605
Joined: Feb 18, 2006 13:30
Location: Alexandria / Egypt
Contact:

Post by voodooattack »

coderJeff wrote:I reverted to my copy of fbc 15 and old windows headers and the code compiles fine as is. There are some issues wrt compiler versions but I can easily work around that.

It looks like everything that's needed is in the framework. Even though the service doesn't do anything, should it possible to start the service anyway? i.e. get it to the running state? Do I need to set/return something from one of the handler functions in MyService.bas to signal the service to start? I'm running on XPsp1.
the service can actually start/stop/pause/resume with no errors as-is..

no extra code is needed to boot it up.. you'll just get an empty service.. :)

since all it does is wait for a stop event..

Code: Select all

        While SvcStopPending(50) = 0
            'Main service code loop
            
        Wend
EDIT:

The loop above should work just like any gfx rendering loop.. you get an input, process it, produce output, only we're not dealing with keyboard inputs here :) ..

I'll try to write a small web server example..
i've already used this framework to build a service, called NoCUT to prevent ARP poisoning attacks on my network :D

that's actually why i made it, and since i was writing a service, i've decided to make it as reusable code instead (actual service code is separate from the framework it self) :)
Last edited by voodooattack on Apr 12, 2006 19:01, edited 1 time in total.
v1ctor
Site Admin
Posts: 3804
Joined: May 27, 2005 8:08
Location: SP / Bra[s]il
Contact:

Post by v1ctor »

It compiled in 0.16 with just the "Exit Sub should be Exit Function" change.

Using the commands /i, start, stop, /u in XP SP2 it seems ok (if 0 is the expected result, i didn't check the sources).
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

I don't know what I am doing wrong but the code will not run as-is. However, I did get it running (to a point).

* I re-dowloaded the zip.
* changed the exit sub to function so it would compile on fb16
* it compiled

* the service installed correctly with `myservice -i'
* but when starting it using `myservice start' it timed out.

* I traced the execution of `myservice start' and got
[Begin]
SrvParseArgs()
SrvStartService()
StartService() <--- This is where it times out

If I check MSDN on StartService():

Code: Select all

ERROR_SERVICE_REQUEST_TIMEOUT 
The process for the service was started, but it did not call StartServiceCtrlDispatcher, or the thread that called StartServiceCtrlDispatcher may be blocked in a control handler function. 
For me, StartServiceCtrlDispatcher() is never reached, never gets executed.

If I explicitly call _Service_Initialize(), starting the service works from the services MC, the command line, or using net start.

At the moment I am mystified why it is different on our systems.
Drago
Posts: 116
Joined: Aug 10, 2005 13:15

Post by Drago »

Hi there,

First
great code I think... five tumbs up !

btw:
after reading code, my opinion is that we have to replace the error :
Exit Sub with goto Ext: following rest of code...

for me it worked without Problem:
winxp home sp2

Rainer
voodooattack
Posts: 605
Joined: Feb 18, 2006 13:30
Location: Alexandria / Egypt
Contact:

Post by voodooattack »

Thanks :)
Drago wrote:Hi there,

First
great code I think... five tumbs up !

btw:
after reading code, my opinion is that we have to replace the error :
Exit Sub with goto Ext: following rest of code...

for me it worked without Problem:
winxp home sp2

Rainer

Indeed it is.. i guess this was the error.. if the function SrvParseArgs() did not return a value, then the execution will continue.. and the same thread that attempted to start the service will try to connect to the SCM, blocking the newly started process..

Perhaps this will fix coderJeff's issue..

EDIT: Uploaded a fixed version.. check 1st post.. :)
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

I think I found the problem. I'm also thinking it's related to differences between xp sp1 and sp2.

Even though functions like OpenSCManager() are succeeding, GetLastError() is returning 997, ERROR_IO_PENDING. On completion of SrvGetServiceStatus(), there is an error code in GetLastError() even though all of the individual API calls in SrvGetServiceStatus() succeeded. By checking the individual results for api calls in SrvGetServiceStatus() and explictity setting SetLastError(NO_ERROR) after each successful call, SrvGetServiceStatus() eventually returns with no errors. Then, back in the main part of the service framework, execution continues on and actually starts the service. woohoo!

It would probably be worthwhile to add the same checks/sets in the install/uninstall routines, for SP1 users anyway.

I would upgrade to SP2 except that it would break all my NetDDE stuff. I know, I know, I'll have to do it eventually .... damn M$ ....
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

Here's my version of FBServ that works with xpsp1 and nt4sp6.

Source: syslog.zip 40K

use mksyslog.bat to make.

It includes FBServ, a slightly modified wshelper from the freebasic examples dir and a *very* simple sys logger. Service listens on udp/514 and writes incoming messages to syslog.log file in the same directory as the service exe. Service has to be stopped to view the log. I'm going to use it to log messages from my router.

Aside from the problems of xpsp1, it was very easy to put together a service exe. voodooattack, very useful code you have put together.
voodooattack
Posts: 605
Joined: Feb 18, 2006 13:30
Location: Alexandria / Egypt
Contact:

Post by voodooattack »

coderJeff wrote:Here's my version of FBServ that works with xpsp1 and nt4sp6.

Source: syslog.zip 40K

use mksyslog.bat to make.

It includes FBServ, a slightly modified wshelper from the freebasic examples dir and a *very* simple sys logger. Service listens on udp/514 and writes incoming messages to syslog.log file in the same directory as the service exe. Service has to be stopped to view the log. I'm going to use it to log messages from my router.

Aside from the problems of xpsp1, it was very easy to put together a service exe. voodooattack, very useful code you have put together.
An awesome example mate :-)
Right now i'm in the phase of testing stuff i've been too lazy to test before..

for example the ConsoleHandler had a big issue, as a call back function that receives a ByRef parameter, and should be ByVal instead (fixed)

and:

Code: Select all

Sub ServiceInit(ByVal Argc As Integer, ByVal Argv as ZString PTR)
should be:

Code: Select all

Sub ServiceInit(ByVal Argc As Integer, ByVal Argv as ZString PTR PTR)
i've fixed all of this, but i'm still hunting down bugs as much as i can..

I plan to add more checks to the install/uninstall procedures as you suggested.. i think i'll make use of your syslogger to merge what you've fixed already..

also, i wish if you could send me the new FB declaration for the FormatMessage function, as im using .15b, this way i can make it compatible with both..

I'll be writing a RadASM template soon too.. :D

Thanks for all the help... :)
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Post by coderJeff »

Code: Select all

declare function FormatMessage alias "FormatMessageA" (byval as DWORD, byval as PCVOID, byval as DWORD, byval as DWORD, byval as LPSTR, byval as DWORD, byval as any ptr) as DWORD

Code: Select all

Public Function GetErrorString(ByVal Code As UInteger) As ZString PTR
  Dim ErrorString         As ZString PTR
  Call FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM Or _
     FORMAT_MESSAGE_ALLOCATE_BUFFER, _
     NULL, _
     Code, _
     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), _
     @ErrorString, _
     255, _
     NULL)
        
  Return ErrorString
End Function
A warning regarding pointer types on @ErrorString is generated, but it is the correct thing to pass toe FormatMessage when letting it do the allocation for you.
yetifoot
Posts: 1710
Joined: Sep 11, 2005 7:08
Location: England
Contact:

Post by yetifoot »

I posted a bit of a similar GetLastError wrapper here. The pointer passed is expected to be LPVOID. I deallocate it with LocalFree, this was the way that the WinAPI docs seemed to suggest, but i'm not 100% if thats any different from DeAllocate.

http://www.freebasic.net/forum/viewtopic.php?t=3375
Post Reply