digitalmars.D - service.d -- a skeletal service for Windows
- Gifford Hesketh (637/637) May 27 2004 /*
- David L. Davis (14/14) May 27 2004 Gifford: I really would like to take a good look at your work and downlo...
- J C Calvarese (8/25) May 27 2004 That's odd. I had no problem accessing these files in Mozilla
- David L. Davis (8/12) May 28 2004 J C Calvarese: Thanks, I've downloaded the D source code for a "Windows ...
- Gifford Hesketh (26/40) May 28 2004 I have put the code up for browsing here:
- David L. Davis (9/24) May 28 2004 Gifford: Thanks for putting the code up on to a web page, by the way, if...
/* ** service.d -- a skeletal service for Windows ** ** Created 2004-May-27 for the public domain by Gifford Hesketh ( first.last gmail.com ) */ import winbase; import winerror; import winnt; import winsvc; extern ( Windows ) { char * theServiceName = "service.d"; int main ( char[][] args ) { SERVICE_TABLE_ENTRY[] theServiceTable; theServiceTable.length = 2; theServiceTable[ 0 ].lpServiceName = theServiceName; theServiceTable[ 0 ].lpServiceProc = & ( ServiceMain ); theServiceTable[ 1 ].lpServiceName = null; theServiceTable[ 1 ].lpServiceProc = null; if ( ! ( StartServiceCtrlDispatcher ( theServiceTable ) ) ) { /* ** probably (?) run from the command line */ void * theSCM; OutputDebugString ( "! StartServiceCtrlDispatcher" ); theSCM = OpenSCManager ( null, null, SC_MANAGER_CREATE_SERVICE | DELETE ); if ( cast ( SC_HANDLE ) 0 != theSCM ) { void * theService; theService = OpenService ( theSCM, theServiceName, DELETE ); if ( cast ( SC_HANDLE ) 0 != theService ) { /* ** service exists; delete it */ if ( DeleteService ( theService ) ) { OutputDebugString ( ". DeleteService" ); } else { OutputDebugString ( "! DeleteService" ); } CloseServiceHandle ( theService ); } else { if ( ERROR_SERVICE_DOES_NOT_EXIST == GetLastError () ) { /* ** service does not exist; create it */ theService = CreateService ( theSCM, theServiceName, theServiceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, args[ 0 ], null, null, null, null, null ); if ( cast ( SC_HANDLE ) 0 == theService ) { OutputDebugString ( "! CreateService" ); } else { OutputDebugString ( ". CreateService" ); CloseServiceHandle ( theService ); } } } CloseServiceHandle ( theSCM ); } } else { /* ** the service has finished running */ OutputDebugString ( ". StartServiceCtrlDispatcher" ); } return 0; } // main () /* ** the name of this function is arbitrary */ void ServiceMain ( uint dwArgc, char * * lpszArgv ) { void * theEvent; SERVICE_STATUS theServiceStatus; SERVICE_STATUS_HANDLE theServiceStatusHandle; theServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; theServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE; theServiceStatus.dwWin32ExitCode = 0; theServiceStatus.dwServiceSpecificExitCode = 0; theServiceStatus.dwCheckPoint = 0; theServiceStatus.dwWaitHint = 0; theServiceStatusHandle = RegisterServiceCtrlHandler ( theServiceName, & ( ServiceCtrlHandler ) ); if ( cast ( SERVICE_STATUS_HANDLE ) 0 == theServiceStatusHandle ) { OutputDebugString ( "! RegisterServiceCtrlHandlerEx" ); } else { OutputDebugString ( ". RegisterServiceCtrlHandlerEx" ); } theServiceStatus.dwCurrentState = SERVICE_START_PENDING; if ( ! SetServiceStatus ( theServiceStatusHandle, &theServiceStatus)) { OutputDebugString ( "! SERVICE_START_PENDING" ); } else { OutputDebugString ( ". SERVICE_START_PENDING" ); } /* ** create a synchronization object so the control handler can notify when to stop */ theEvent = CreateEvent ( null, true, false, theServiceName ); if ( null == theEvent ) { theServiceStatus.dwCurrentState = SERVICE_STOPPED; if ( ! SetServiceStatus ( theServiceStatusHandle, & ( theServiceStatus ) ) ) { OutputDebugString ( "! SERVICE_STOPPED" ); } else { OutputDebugString ( ". SERVICE_STOPPED" ); } return; } theServiceStatus.dwCurrentState = SERVICE_RUNNING; if ( ! SetServiceStatus ( theServiceStatusHandle, & ( theServiceStatus ) ) ) { OutputDebugString ( "! SERVICE_RUNNING" ); } else { OutputDebugString ( ". SERVICE_RUNNING" ); } /* ** wait for notification to stop from the control handler */ WaitForSingleObject ( theEvent, INFINITE ); theServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; if ( ! SetServiceStatus ( theServiceStatusHandle, & ( theServiceStatus ) ) ) { OutputDebugString ( "! SERVICE_STOP_PENDING" ); } else { OutputDebugString ( ". SERVICE_STOP_PENDING" ); } /* ** deref the synchronization object */ CloseHandle ( theEvent ); theServiceStatus.dwCurrentState = SERVICE_STOPPED; if ( ! SetServiceStatus ( theServiceStatusHandle, & ( theServiceStatus ) ) ) { OutputDebugString ( "! SERVICE_STOPPED" ); } else { OutputDebugString ( ". SERVICE_STOPPED" ); } return; } // ServiceMain () /* ** the name of this function is arbitrary */ void ServiceCtrlHandler ( uint dwControl ) { void * theEvent; switch ( dwControl ) { case SERVICE_CONTROL_STOP: OutputDebugString ( ". SERVICE_CONTROL_STOP" ); theEvent = OpenEvent ( EVENT_MODIFY_STATE, false, theServiceName ); SetEvent ( theEvent ); CloseHandle ( theEvent ); break; case SERVICE_CONTROL_PAUSE: OutputDebugString ( ". SERVICE_CONTROL_PAUSE" ); break; case SERVICE_CONTROL_CONTINUE: OutputDebugString ( ". SERVICE_CONTROL_CONTINUE" ); break; case SERVICE_CONTROL_PARAMCHANGE: OutputDebugString ( ". SERVICE_CONTROL_PARAMCHANGE" ); break; case SERVICE_CONTROL_INTERROGATE: OutputDebugString ( ". SERVICE_CONTROL_INTERROGATE" ); break; case SERVICE_CONTROL_SHUTDOWN: OutputDebugString ( ". SERVICE_CONTROL_SHUTDOWN" ); break; default: OutputDebugString ( ". ServiceCtrlHandler" ); break; } return; } // ServiceCtrlHandler () } // extern ( Windows ) begin 666 winsvc.d M;6]D=6QE('=I;G-V8SL-" T*+RH-"BHJ(&QI;FL =VET:"!A9'9A<&DS,BYL M05-%(#T (E-E<G9I8V5S1F%I;&5D(CL-"F-O;G-T(&-H87( 4T-?1U)/55!? M241%3E1)1DE%4B ]("<K)SL-" T*8V]N<W0 =6EN="!315)624-%7TY/7T-( M0T5?0T].5%)/3%].151"24Y$4D5-3U9%(#T M3D=%(#T M(#T M(#T M24-%(#T M2$%.1T5?0T].1DE'(#T M(#T M,"P-" E315)624-%7TE.5$524D]'051%(#T M3E].3TY%(#T M93L-" EU:6YT($1E;&%Y.PT*?0T*86QI87, 4T-?04-424].("H 3%!30U]! M"75I;G0 9'=297-E=%!E<FEO9#L- M8VAA<B J(&QP0V]M;6%N9#L- M;VED("H 4T-?2$%.1$Q%.PT*86QI87, 4T-?2$%.1$Q%("H 3%!30U](04Y$ M"F5N=6T 4T-?4U1!5%537U194$4-"GL-" E30U]35$%455-?4%)/0T534U]) M3D9/(#T M4%)/0T534U])3D9/(#T M93L-" EU:6YT(&1W0V]N=')O;'-!8V-E<'1E9#L-" EU:6YT(&1W5VEN,S)% M97)V:6-E4W!E8VEF:6-%>&ET0V]D93L-" EU:6YT(&1W0VAE8VM0;VEN=#L- M14Y535]315)624-%7U-405154PT*>PT*"6-H87( *B!L<%-E<G9I8V5.86UE M.PT*"6-H87( *B!L<$1I<W!L87E.86UE.PT*"5-%4E9)0T5?4U1!5%53(%-E M0T5?4U1!5%537U!23T-%4U,-"GL-" EC:&%R("H ;'!397)V:6-E3F%M93L- M15-3(%-E<G9I8V53=&%T=7-0<F]C97-S.PT*?0T*86QI87, 14Y535]315)6 M"6-H87( *B!L<$QO8VM/=VYE<CL-" EU:6YT(&1W3&]C:T1U<F%T:6]N.PT* M<GE0871H3F%M93L-" EC:&%R("H ;'!,;V%D3W)D97)'<F]U<#L-" EU:6YT M15)624-%7TU!24Y?1E5.0U1)3TX ;'!397)V:6-E4')O8SL-"GT-" T*86QI M(&1W179E;G14>7!E+ T*"79O:60 *B!L<$5V96YT1&%T82P-" EV;VED("H M" EC:&%R("H ;'!":6YA<GE0871H3F%M92P-" EC:&%R("H ;'!,;V%D3W)D M97)'<F]U<"P-" EU:6YT("H ;'!D=U1A9TED+ T*"6-H87( *B!L<$1E<&5N M9&5N8VEE<RP-" EC:&%R("H ;'!397)V:6-E4W1A<G1.86UE+ T*"6-H87( M:6-E+ T*"75I;G0 9'=397)V:6-E5'EP92P-" EU:6YT(&1W4W1A<G14>7!E M4V5R=FEC95-T87)T3F%M92P-" EC:&%R("H ;'!087-S=V]R9"P-" EC:&%R M("H ;'!$:7-P;&%Y3F%M90T**3L-" T*=F5R<VEO;B H(%5.24-/1$4 *0T* M" EC:&%R("H ;'!":6YA<GE0871H3F%M92P-" EC:&%R("H ;'!,;V%D3W)D M97)'<F]U<"P-" EU:6YT("H ;'!D=U1A9TED+ T*"6-H87( *B!L<$1E<&5N M9&5N8VEE<RP-" EC:&%R("H ;'!397)V:6-E4W1A<G1.86UE+ T*"6-H87( M<GE0871H3F%M92P-" EC:&%R("H ;'!,;V%D3W)D97)'<F]U<"P-" EU:6YT M("H ;'!D=U1A9TED+ T*"6-H87( *B!L<$1E<&5N9&5N8VEE<RP-" EC:&%R M"D5N=6U$97!E;F1E;G1397)V:6-E<T$-"B -" E30U](04Y$3$4 :%-E<G9I M5$%455, ;'!397)V:6-E<RP-" EU:6YT(&-B0G5F4VEZ92P-" EU:6YT("H M<R!%;G5M1&5P96YD96YT4V5R=FEC97-7($5N=6U$97!E;F1E;G1397)V:6-E M<SL-"GT-"F5L<V4-"GL-" EA;&EA<R!%;G5M1&5P96YD96YT4V5R=FEC97-! M9V5R+ T*"75I;G0 9'=397)V:6-E5'EP92P-" EU:6YT(&1W4V5R=FEC95-T M871E+ T*"4Q014Y535]315)624-%7U-405154R!L<%-E<G9I8V5S+ T*"75I M;G0 8V)"=693:7IE+ T*"75I;G0 *B!P8V)">71E<TYE961E9"P-" EU:6YT M("H ;'!397)V:6-E<U)E='5R;F5D+ T*"75I;G0 *B!L<%)E<W5M94AA;F1L M90T**3L-" T*=F5R<VEO;B H(%5.24-/1$4 *0T*>PT*"6%L:6%S($5N=6U3 M97)V:6-E<U-T871U<U< 16YU;5-E<G9I8V5S4W1A='5S.PT*?0T*96QS90T* M>PT*"6%L:6%S($5N=6U397)V:6-E<U-T871U<T$ 16YU;5-E<G9I8V5S4W1A M=6EN=" J('!C8D)Y=&5S3F5E9&5D+ T*"75I;G0 *B!L<%-E<G9I8V5S4F5T M;&EA<R!%;G5M4V5R=FEC97-3=&%T=7-%>%< 16YU;5-E<G9I8V5S4W1A='5S M87E.86UE+ T*"6-H87( *B!L<%-E<G9I8V5.86UE+ T*"75I;G0 *B!L<&-C M:$)U9F9E< T**3L-" T*=F5R<VEO;B H(%5.24-/1$4 *0T*>PT*"6%L:6%S M($=E=%-E<G9I8V5+97E.86UE5R!'971397)V:6-E2V5Y3F%M93L-"GT-"F5L M<V4-"GL-" EA;&EA<R!'971397)V:6-E2V5Y3F%M94$ 1V5T4V5R=FEC94ME M" EC:&%R("H ;'!$:7-P;&%Y3F%M92P-" EU:6YT("H ;'!C8VA"=69F97(- M:6-E1&ES<&QA>4YA;657($=E=%-E<G9I8V5$:7-P;&%Y3F%M93L-"GT-"F5L M<V4-"GL-" EA;&EA<R!'971397)V:6-E1&ES<&QA>4YA;65!($=E=%-E<G9I M3F]T:69Y0F]O=$-O;F9I9U-T871U<PT** T*"6EN="!";V]T06-C97!T86)L M"E%U97)Y4V5R=FEC94-O;F9I9U<-"B -" E30U](04Y$3$4 :%-E<G9I8V4L M12!H4V5R=FEC92P-" EU:6YT(&1W26YF;TQE=F5L+ T*"75B>71E("H ;'!" M*B!L<$)U9F9E<BP-" EU:6YT(&-B0G5F4VEZ92P-" EU:6YT("H <&-B0GET M?0T*96QS90T*>PT*"6%L:6%S(%%U97)Y4V5R=FEC94-O;F9I9S)!(%%U97)Y M<RP-" EU:6YT(&-B0G5F4VEZ92P-" EU:6YT("H <&-B0GET97-.965D960- M<G9I8V5,;V-K4W1A='5S5R!1=65R>5-E<G9I8V5,;V-K4W1A='5S.PT*?0T* M96QS90T*>PT*"6%L:6%S(%%U97)Y4V5R=FEC94QO8VM3=&%T=7-!(%%U97)Y M4B!L<%-E8W5R:71Y1&5S8W)I<'1O<BP-" EU:6YT(&-B0G5F4VEZ92P-" EU M"E-%4E9)0T5?4U1!5%537TA!3D1,10T*4F5G:7-T97)397)V:6-E0W1R;$AA M:6-E0W1R;$AA;F1L97)!(%)E9VES=&5R4V5R=FEC94-T<FQ(86YD;&5R.PT* M0W1R;$AA;F1L97)%>$$-"B -" EC:&%R("H ;'!397)V:6-E3F%M92P-" E, M4$A!3D1,15)?1E5.0U1)3TY?15 ;'!(86YD;&5R4')O8RP-" EV;VED("H M*0T*>PT*"6%L:6%S(%)E9VES=&5R4V5R=FEC94-T<FQ(86YD;&5R17A7(%)E M87, 4F5G:7-T97)397)V:6-E0W1R;$AA;F1L97)%>$$ 4F5G:7-T97)397)V M:6-E0W1R;$AA;F1L97)%>#L- M= T*4V5T4V5R=FEC95-T871U<PT** T*"5-%4E9)0T5?4U1!5%537TA!3D1, M12!H4V5R=FEC95-T871U<RP-" E,4%-%4E9)0T5?4U1!5%53(&QP4V5R=FEC M:&5R00T** T*"5-%4E9)0T5?5$%"3$5?14Y44ED *B!L<%-E<G9I8V53=&%R M5PT** T*"5-%4E9)0T5?5$%"3$5?14Y44ED *B!L<%-E<G9I8V53=&%R=%1A M<G1397)V:6-E0W1R;$1I<W!A=&-H97)7(%-T87)T4V5R=FEC94-T<FQ$:7-P M871C:&5R.PT*?0T*96QS90T*>PT*"6%L:6%S(%-T87)T4V5R=FEC94-T<FQ$ M8VAA<B J("H ;'!397)V:6-E07)G5F5C=&]R<PT**3L-" T*=F5R<VEO;B H M(%5.24-/1$4 *0T*>PT*"6%L:6%S(%-T87)T4V5R=FEC95< 4W1A<G1397)V M:6-E.PT*?0T*96QS90T*>PT*"6%L:6%S(%-T87)T4V5R=FEC94$ 4W1A<G13 ` end begin 666 winbase.d M;G-T('5I;G0 159%3E1?34]$24997U-4051%(#T M4SL-"F%L:6%S(%-%0U5225197T%45%))0E5415, *B!,4%-%0U5225197T%4 M<$5V96YT071T<FEB=71E<RP-" EI;G0 8DUA;G5A;%)E<V5T+ T*"6EN="!B M<F5D06-C97-S+ T*"6EN="!B26YH97)I=$AA;F1L92P-" EC:&%R("H ;'!. M= T*5V%I=$9O<DUU;'1I<&QE3V)J96-T<PT** T*"75I;G0 ;D-O=6YT+ T* M00T** T*"6-H87( *B!L<$]U='!U=%-T<FEN9PT**3L-" T*=F]I9 T*3W5T M=6=3=')I;F=7($]U='!U=$1E8G5G4W1R:6YG.PT*?0T*96QS90T*>PT*"6%L M:6%S($]U='!U=$1E8G5G4W1R:6YG02!/=71P=71$96)U9U-T<FEN9SL-"GT- M;&5.86UE00T** T*"79O:60 *B!H36]D=6QE+ T*"6]U="!C:&%R("H ;'!& M:6QE3F%M95<-"B -" EV;VED("H :$UO9'5L92P-" EO=70 8VAA<B J(&QP M1$4 *0T*>PT*"6%L:6%S($=E=$UO9'5L949I;&5.86UE5R!'971-;V1U;&5& M:6QE3F%M93L-"GT-"F5L<V4-"GL-" EA;&EA<R!'971-;V1U;&5&:6QE3F%M /;B H(%=I;F1O=W, *0T* ` end begin 666 winerror.d ` end begin 666 winnt.d M(#T M1$%21%]224=(5%-?04Q,(#T M7U=2251%(#T M551%(#T M5D52(#T M0T]'3DE:15)?1%))5D52(#T M(#T M65!%7T%,3" ](%-%4E9)0T5?5TE.,S( ?"!315)624-%7T%$05!415( ?"!3 M15)624-%7T12259%4B!\(%-%4E9)0T5?24Y415)!0U1)5D5?4%)/0T534SL- M1$5-04Y$7U-405)4(#T M(#T M15)23U)?24=.3U)%(#T 6;W)T(&5X=&5R;B H(%=I;F1O=W, *0`` ` end
May 27 2004
Gifford: I really would like to take a good look at your work and download all the .d files, but I'm not sure how grab the encrypted ones. I thought by setting up my Outlook 2003 for this news group that it would help me over viewing this site in IE 6, but they look exactly the same. (Go Figure!) Anyway, I have a strong interest in making a windows service, I want to rewrite an old "C" audit program I wrote years ago that tracked program usage by user and such. And since I'm really enjoying "D's" great support for strings...I'd love to use D to recreate it with. Man, I've forgotten how many times I've had to type in lines and lines of malloc()s, strcpy()s, strcat()s and such, just to do the most simplest of string work. But with "D," no more of that sort of thing!!! Also, if you have a web site with these files in a .zip, or .rar, or even a html web page to copy & paste from, please point me to them! Thanks in Advance. :)
May 27 2004
David L. Davis wrote:Gifford: I really would like to take a good look at your work and download all the .d files, but I'm not sure how grab the encrypted ones. I thought by setting up my Outlook 2003 for this news group that it would help me over viewing this site in IE 6, but they look exactly the same. (Go Figure!)That's odd. I had no problem accessing these files in Mozilla Thunderbird. (I don't know why Outlook wouldn't be able to handle them.) I posted a .zip of the files at my website: http://jcc_7.tripod.com/d/win_service/index.htmlAnyway, I have a strong interest in making a windows service, I want to rewrite an old "C" audit program I wrote years ago that tracked program usage by user and such. And since I'm really enjoying "D's" great support for strings...I'd love to use D to recreate it with. Man, I've forgotten how many times I've had to type in lines and lines of malloc()s, strcpy()s, strcat()s and such, just to do the most simplest of string work. But with "D," no more of that sort of thing!!! Also, if you have a web site with these files in a .zip, or .rar, or even a html web page to copy & paste from, please point me to them! Thanks in Advance. :)-- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
May 27 2004
J C Calvarese: Thanks, I've downloaded the D source code for a "Windows Service" zip from your web site. I'm going to go back recheck my setup in Outlook, I must have done (or undone) something. But "the Outlook help, isn't very helpful"...and this is the first time I tried to set it up for a news group. Back to the drawing board. :) Thxs Again! P.S. And Gifford Hesketh, thanks for putting this code together to work with D! In article <c968m1$2lf1$1 digitaldaemon.com>, J C Calvarese says...That's odd. I had no problem accessing these files in Mozilla Thunderbird. (I don't know why Outlook wouldn't be able to handle them.) I posted a .zip of the files at my website: http://jcc_7.tripod.com/d/win_service/index.html
May 28 2004
I have put the code up for browsing here: http://users.adelphia.net/~4187/gifford/src/d/service/ FWIW, the last issue I pinned down was how to make code using "theServiceTable" compile and work. When I first made this in in January or Febrary, I had the variable declared as SERVICE_TABLE_ENTRY[2] -- and that worked. I have since updated to D 0.90, which would not succeed compiling the same code (it was actually linking that failed). I tried changing it to SERVICE_TABLE_ENTRY *, but I could not figure out how to get malloc() to happen. The D code that worked SERVICE_TABLE_ENTRY[] theServiceTable; theServiceTable.length = 2;is functionally very much like the same code I wrote in C: SERVICE_TABLE_ENTRY * pServiceTable; pServiceTable = ( SERVICE_TABLE_ENTRY * ) malloc ( 2 * sizeof ( SERVICE_TABLE_ENTRY ) ); "David L. Davis" <David_member pathlink.com> wrote in message news:c95svk$258v$1 digitaldaemon.com...Gifford: I really would like to take a good look at your work and downloadallthe .d files, but I'm not sure how grab the encrypted ones. I thought bysettingup my Outlook 2003 for this news group that it would help me over viewingthissite in IE 6, but they look exactly the same. (Go Figure!) Anyway, I have a strong interest in making a windows service, I want torewritean old "C" audit program I wrote years ago that tracked program usage byuserand such. And since I'm really enjoying "D's" great support forstrings...I'dlove to use D to recreate it with. Man, I've forgotten how many times I'vehadto type in lines and lines of malloc()s, strcpy()s, strcat()s and such,just todo the most simplest of string work. But with "D," no more of that sort of thing!!! Also, if you have a web site with these files in a .zip, or .rar, or evena htmlweb page to copy & paste from, please point me to them! Thanks in Advance. :)
May 28 2004
Gifford: Thanks for putting the code up on to a web page, by the way, if I create anything somewhat useful I'll share it with you, and anyone else who'll find a use for it. I'm thinking of digging up that old "C" audit (program usage/amount of time running/by user) code I was talking about before, if nothing else it might ->service<- (:P) as some example code. If I recall correctly, it was a simple but useful little app that ran in the background creating text usage log file. We'll see. :)) Thxs Again! In article <c981h4$29aj$1 digitaldaemon.com>, Gifford Hesketh says...I have put the code up for browsing here: http://users.adelphia.net/~4187/gifford/src/d/service/ FWIW, the last issue I pinned down was how to make code using "theServiceTable" compile and work. When I first made this in in January or Febrary, I had the variable declared as SERVICE_TABLE_ENTRY[2] -- and that worked. I have since updated to D 0.90, which would not succeed compiling the same code (it was actually linking that failed). I tried changing it to SERVICE_TABLE_ENTRY *, but I could not figure out how to get malloc() to happen. The D code that worked SERVICE_TABLE_ENTRY[] theServiceTable; theServiceTable.length = 2;is functionally very much like the same code I wrote in C: SERVICE_TABLE_ENTRY * pServiceTable; pServiceTable = ( SERVICE_TABLE_ENTRY * ) malloc ( 2 * sizeof ( SERVICE_TABLE_ENTRY ) );
May 28 2004