2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
20 #include "afsd_init.h"
35 // The following is defined if you want to receive Power notifications,
36 // including Hibernation, and also subsequent flushing of AFS volumes
38 #define REGISTER_POWER_NOTIFICATIONS 1
39 #define FLUSH_VOLUME 1
43 #include "afsd_flushvol.h"
45 extern void afsi_log(char *pattern, ...);
47 HANDLE hAFSDMainThread = NULL;
49 HANDLE WaitToTerminate;
54 unsigned int MainThreadId;
58 extern int traceOnPanic;
59 extern HANDLE afsi_file;
61 int powerEventsRegistered = 0;
64 * Notifier function for use by osi_panic
66 static void afsd_notifier(char *msgp, char *filep, long line)
73 sprintf(tbuffer, "Error at file %s, line %d: %s",
76 sprintf(tbuffer, "Error at unknown location: %s", msgp);
78 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
80 ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, line, NULL, 1, 0, ptbuf, NULL);
81 DeregisterEventSource(h);
85 osi_LogEnable(afsd_logp);
87 afsd_ForceTrace(TRUE);
90 afsi_log("--- begin dump ---");
91 cm_DumpSCache(afsi_file, "a");
93 cm_dnlcDump(afsi_file, "a");
95 cm_DumpBufHashTable(afsi_file, "a");
96 smb_DumpVCP(afsi_file, "a");
97 afsi_log("--- end dump ---");
101 SetEvent(WaitToTerminate);
104 if (GetCurrentThreadId() == MainThreadId)
105 longjmp(notifier_jmp, 1);
112 * For use miscellaneously in smb.c; need to do better
114 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
119 static SERVICE_STATUS ServiceStatus;
120 static SERVICE_STATUS_HANDLE StatusHandle;
123 afsd_ServiceFlushVolume(DWORD dwlpEventData)
125 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
128 ** If UI bit is not set, user interaction is not possible
129 ** BUT, since we are a NON-interactive service, and therefore
130 ** have NO user I/O, it doesn't much matter.
131 ** This benign code left here as example of how to find this out
133 BOOL bUI = (dwlpEventData & 1);
136 if ( PowerNotificationThreadNotify() )
142 /* flush was unsuccessful, or timeout - deny shutdown */
143 dwRet = ERROR_NETWORK_BUSY;
146 /* to deny hibernate, simply return
147 // any value besides NO_ERROR.
149 // dwRet = ERROR_NETWORK_BUSY;
156 /* service control handler used in nt4 only for backward compat. */
158 afsd_ServiceControlHandler(DWORD ctrlCode)
161 DWORD dummyLen, doTrace;
165 case SERVICE_CONTROL_STOP:
167 RpcMgmtStopServerListening(NULL);
169 /* Force trace if requested */
170 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
172 0, KEY_QUERY_VALUE, &parmKey);
173 if (code != ERROR_SUCCESS)
176 dummyLen = sizeof(doTrace);
177 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
179 (BYTE *) &doTrace, &dummyLen);
180 RegCloseKey (parmKey);
181 if (code != ERROR_SUCCESS)
184 afsd_ForceTrace(FALSE);
185 buf_ForceTrace(FALSE);
189 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
190 ServiceStatus.dwWin32ExitCode = NO_ERROR;
191 ServiceStatus.dwCheckPoint = 1;
192 ServiceStatus.dwWaitHint = 10000;
193 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
194 SetServiceStatus(StatusHandle, &ServiceStatus);
195 SetEvent(WaitToTerminate);
197 case SERVICE_CONTROL_INTERROGATE:
198 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
199 ServiceStatus.dwWin32ExitCode = NO_ERROR;
200 ServiceStatus.dwCheckPoint = 0;
201 ServiceStatus.dwWaitHint = 0;
202 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
203 SetServiceStatus(StatusHandle, &ServiceStatus);
205 /* XXX handle system shutdown */
206 /* XXX handle pause & continue */
212 ** Extended ServiceControlHandler that provides Event types
213 ** for monitoring Power events, for example.
216 afsd_ServiceControlHandlerEx(
224 DWORD dummyLen, doTrace;
226 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
230 case SERVICE_CONTROL_STOP:
232 RpcMgmtStopServerListening(NULL);
234 /* Force trace if requested */
235 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
237 0, KEY_QUERY_VALUE, &parmKey);
238 if (code != ERROR_SUCCESS)
241 dummyLen = sizeof(doTrace);
242 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
244 (BYTE *) &doTrace, &dummyLen);
245 RegCloseKey (parmKey);
246 if (code != ERROR_SUCCESS)
249 afsd_ForceTrace(FALSE);
250 buf_ForceTrace(FALSE);
254 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
255 ServiceStatus.dwWin32ExitCode = NO_ERROR;
256 ServiceStatus.dwCheckPoint = 1;
257 ServiceStatus.dwWaitHint = 10000;
258 ServiceStatus.dwControlsAccepted = 0;
259 SetServiceStatus(StatusHandle, &ServiceStatus);
260 SetEvent(WaitToTerminate);
264 case SERVICE_CONTROL_INTERROGATE:
265 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
266 ServiceStatus.dwWin32ExitCode = NO_ERROR;
267 ServiceStatus.dwCheckPoint = 0;
268 ServiceStatus.dwWaitHint = 0;
269 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
270 SetServiceStatus(StatusHandle, &ServiceStatus);
274 /* XXX handle system shutdown */
275 /* XXX handle pause & continue */
276 case SERVICE_CONTROL_POWEREVENT:
279 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
280 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
281 ** Return any error code to deny request,
282 ** i.e. as if returning BROADCAST_QUERY_DENY
284 if (powerEventsRegistered) {
285 switch((int) dwEventType)
287 case PBT_APMQUERYSUSPEND:
288 case PBT_APMQUERYSTANDBY:
292 dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);
298 /* allow remaining case PBT_WhatEver */
301 case PBT_APMRESUMECRITICAL:
302 case PBT_APMRESUMESUSPEND:
303 case PBT_APMRESUMESTANDBY:
304 case PBT_APMBATTERYLOW:
305 case PBT_APMPOWERSTATUSCHANGE:
306 case PBT_APMOEMEVENT:
307 case PBT_APMRESUMEAUTOMATIC:
313 } /* end switch(ctrlCode) */
317 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
319 * Mount a drive into AFS if there global mapping
321 /* DEE Could check first if we are run as SYSTEM */
322 #define MAX_RETRIES 30
323 static void MountGlobalDrives(void)
325 char szAfsPath[_MAX_PATH];
326 char szDriveToMapTo[5];
330 DWORD dwIndex = 0, dwRetry = 0;
332 DWORD dwSubMountSize;
333 char szSubMount[256];
336 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
338 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
339 if (dwResult != ERROR_SUCCESS)
342 while (dwRetry < MAX_RETRIES) {
343 dwDriveSize = sizeof(szDriveToMapTo);
344 dwSubMountSize = sizeof(szSubMount);
345 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
346 if (dwResult != ERROR_MORE_DATA) {
347 if (dwResult != ERROR_SUCCESS) {
348 if (dwResult != ERROR_NO_MORE_ITEMS)
349 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
354 for ( ; dwRetry < MAX_RETRIES; dwRetry++)
357 memset (&nr, 0x00, sizeof(NETRESOURCE));
359 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
361 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
362 nr.dwType=RESOURCETYPE_DISK;
363 nr.lpLocalName=szDriveToMapTo;
364 nr.lpRemoteName=szAfsPath;
365 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
366 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
368 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
369 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
370 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
371 if (dwResult == NO_ERROR) {
374 /* wait for smb server to come up */
375 Sleep((DWORD)1000 /* miliseconds */);
377 /* Disconnect any previous mappings */
378 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
385 static void DismountGlobalDrives()
387 char szAfsPath[_MAX_PATH];
388 char szDriveToMapTo[5];
394 DWORD dwSubMountSize;
395 char szSubMount[256];
398 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
400 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
401 if (dwResult != ERROR_SUCCESS)
405 dwDriveSize = sizeof(szDriveToMapTo);
406 dwSubMountSize = sizeof(szSubMount);
407 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
408 if (dwResult != ERROR_MORE_DATA) {
409 if (dwResult != ERROR_SUCCESS) {
410 if (dwResult != ERROR_NO_MORE_ITEMS)
411 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
416 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
418 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
419 dwResult = WNetCancelConnection(szAfsPath, TRUE);
421 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
428 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
430 DWORD dwVersionHandle;
431 LPVOID pVersionInfo = 0;
433 LPDWORD pLangInfo = 0;
434 LPTSTR szVersion = 0;
436 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
437 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
440 afsi_log("GetFileVersionInfoSize failed");
441 return GetLastError();
444 pVersionInfo = malloc(size);
446 afsi_log("out of memory 1");
447 return ERROR_NOT_ENOUGH_MEMORY;
450 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
451 if (retval = GetLastError())
453 afsi_log("GetFileVersionInfo failed: %d", retval);
457 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
458 (LPVOID*)&pLangInfo, &len);
459 if (retval = GetLastError())
461 afsi_log("VerQueryValue 1 failed: %d", retval);
466 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
467 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
469 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
470 if (retval = GetLastError())
472 /* try again with language 409 since the old binaries were tagged wrong */
474 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
477 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
478 if (retval = GetLastError()) {
479 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
483 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
484 szOutput[dwOutput - 1] = 0;
493 BOOL VerifyTrust(CHAR * filename)
495 WINTRUST_DATA fTrust;
496 WINTRUST_FILE_INFO finfo;
497 GUID trustAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
498 GUID subject = WIN_TRUST_SUBJTYPE_RAW_FILEEX;
499 wchar_t wfilename[260];
502 if (filename == NULL )
505 mbstowcs(wfilename, filename, 260);
507 finfo.cbStruct = sizeof(finfo);
508 finfo.pcwszFilePath= wfilename;
509 finfo.hFile = INVALID_HANDLE_VALUE;
510 finfo.pgKnownSubject = &subject;
512 fTrust.cbStruct = sizeof(fTrust);
513 fTrust.pPolicyCallbackData = NULL;
514 fTrust.pSIPClientData = NULL;
515 fTrust.dwUIChoice = WTD_UI_NONE;
516 fTrust.fdwRevocationChecks = WTD_REVOKE_NONE;
517 fTrust.dwUnionChoice = WTD_CHOICE_FILE;
518 fTrust.pFile = &finfo;
519 fTrust.dwStateAction = WTD_STATEACTION_IGNORE;
520 fTrust.hWVTStateData = NULL;
521 fTrust.pwszURLReference = NULL;
522 fTrust.dwProvFlags = WTD_SAFER_FLAG | WTD_REVOCATION_CHECK_NONE;
523 fTrust.dwUIContext = WTD_UICONTEXT_EXECUTE;
525 ret = WinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, &fTrust);
527 if (ret == ERROR_SUCCESS) {
530 DWORD gle = GetLastError();
532 case TRUST_E_PROVIDER_UNKNOWN:
533 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
535 case TRUST_E_NOSIGNATURE:
536 afsi_log("VerifyTrust failed: Unsigned executable");
538 case TRUST_E_EXPLICIT_DISTRUST:
539 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
541 case TRUST_E_SUBJECT_NOT_TRUSTED:
542 afsi_log("VerifyTrust failed: File is not trusted");
544 case CRYPT_E_SECURITY_SETTINGS:
545 afsi_log("VerifyTrust failed: local security options prevent verification");
548 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
554 BOOL AFSModulesVerify(void)
557 CHAR afsdVersion[128];
558 CHAR modVersion[128];
559 CHAR checkName[1024];
560 BOOL trustVerified = FALSE;
567 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
570 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
573 afsi_log("%s version %s", filename, afsdVersion);
575 trustVerified = VerifyTrust(filename);
577 // Get a list of all the modules in this process.
578 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
579 FALSE, GetCurrentProcessId());
581 if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
583 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
585 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
587 char szModName[2048];
589 // Get the full path to the module's file.
590 if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName)))
592 lstrcpy(checkName, szModName);
595 if ( strstr(checkName, "afspthread.dll") ||
596 strstr(checkName, "afsauthent.dll") ||
597 strstr(checkName, "afsrpc.dll") ||
598 strstr(checkName, "libafsconf.dll") ||
599 strstr(checkName, "libosi.dll") )
601 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
606 afsi_log("%s version %s", szModName, modVersion);
607 if (strcmp(afsdVersion,modVersion)) {
608 afsi_log("Version mismatch: %s", szModName);
611 if ( trustVerified && !VerifyTrust(szModName) ) {
612 afsi_log("Signature Verification failed: %s", szModName);
620 CloseHandle(hProcess);
624 typedef BOOL ( APIENTRY * AfsdInitHook )(void);
625 #define AFSD_INIT_HOOK "AfsdInitHook"
626 #define AFSD_HOOK_DLL "afsdhook.dll"
629 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
632 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
633 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
635 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
636 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
638 void afsd_Main(DWORD argc, LPTSTR *argv)
647 AfsdInitHook initHook;
650 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
651 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
654 osi_InitPanic(afsd_notifier);
655 osi_InitTraceOption();
661 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
662 if ( GetLastError() == ERROR_ALREADY_EXISTS )
663 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
666 hAdvApi32 = LoadLibrary("advapi32.dll");
667 if (hAdvApi32 == NULL)
669 afsi_log("Fatal: cannot load advapi32.dll");
673 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
674 if (pRegisterServiceCtrlHandlerEx)
676 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
677 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
681 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
684 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
685 ServiceStatus.dwServiceSpecificExitCode = 0;
686 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
687 ServiceStatus.dwWin32ExitCode = NO_ERROR;
688 ServiceStatus.dwCheckPoint = 1;
689 ServiceStatus.dwWaitHint = 30000;
690 /* accept Power Events */
691 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
692 SetServiceStatus(StatusHandle, &ServiceStatus);
696 HANDLE h; char *ptbuf[1];
697 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
698 ptbuf[0] = "AFS start pending";
699 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
700 DeregisterEventSource(h);
703 #ifdef REGISTER_POWER_NOTIFICATIONS
710 /* see if we should handle power notifications */
711 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE, &hkParm);
712 if (code == ERROR_SUCCESS) {
713 dummyLen = sizeof(bpower);
714 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
715 (BYTE *) &bpower, &dummyLen);
717 if(code != ERROR_SUCCESS)
722 /* create thread used to flush cache */
724 PowerNotificationThreadCreate();
725 powerEventsRegistered = 1;
730 /* Verify the versions of the DLLs which were loaded */
731 if (!AFSModulesVerify()) {
732 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
733 ServiceStatus.dwWin32ExitCode = NO_ERROR;
734 ServiceStatus.dwCheckPoint = 0;
735 ServiceStatus.dwWaitHint = 0;
736 ServiceStatus.dwControlsAccepted = 0;
737 SetServiceStatus(StatusHandle, &ServiceStatus);
739 /* exit if initialization failed */
743 /* allow an exit to be called prior to any initialization */
744 hInitHookDll = LoadLibrary(AFSD_HOOK_DLL);
748 initHook = ( AfsdInitHook ) GetProcAddress(hInitHookDll, AFSD_INIT_HOOK);
753 FreeLibrary(hInitHookDll);
758 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
759 ServiceStatus.dwWin32ExitCode = NO_ERROR;
760 ServiceStatus.dwCheckPoint = 0;
761 ServiceStatus.dwWaitHint = 0;
762 ServiceStatus.dwControlsAccepted = 0;
763 SetServiceStatus(StatusHandle, &ServiceStatus);
765 /* exit if initialization failed */
770 /* allow another 15 seconds to start */
771 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
772 ServiceStatus.dwServiceSpecificExitCode = 0;
773 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
774 ServiceStatus.dwWin32ExitCode = NO_ERROR;
775 ServiceStatus.dwCheckPoint = 2;
776 ServiceStatus.dwWaitHint = 20000;
777 /* accept Power Events */
778 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
779 SetServiceStatus(StatusHandle, &ServiceStatus);
784 MainThreadId = GetCurrentThreadId();
785 jmpret = setjmp(notifier_jmp);
790 code = afsd_InitCM(&reason);
792 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
793 osi_panic(reason, __FILE__, __LINE__);
797 ServiceStatus.dwCheckPoint++;
798 ServiceStatus.dwWaitHint -= 5000;
799 SetServiceStatus(StatusHandle, &ServiceStatus);
801 code = afsd_InitDaemons(&reason);
803 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
804 osi_panic(reason, __FILE__, __LINE__);
808 ServiceStatus.dwCheckPoint++;
809 ServiceStatus.dwWaitHint -= 5000;
810 SetServiceStatus(StatusHandle, &ServiceStatus);
812 code = afsd_InitSMB(&reason, MessageBox);
814 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
815 osi_panic(reason, __FILE__, __LINE__);
821 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
822 ServiceStatus.dwWin32ExitCode = NO_ERROR;
823 ServiceStatus.dwCheckPoint = 0;
824 ServiceStatus.dwWaitHint = 0;
826 /* accept Power events */
827 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
828 SetServiceStatus(StatusHandle, &ServiceStatus);
831 HANDLE h; char *ptbuf[1];
832 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
833 ptbuf[0] = "AFS running";
834 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
835 DeregisterEventSource(h);
839 WaitForSingleObject(WaitToTerminate, INFINITE);
842 HANDLE h; char *ptbuf[1];
843 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
844 ptbuf[0] = "AFS quitting";
845 ReportEvent(h, GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
846 0, 0, NULL, 1, 0, ptbuf, NULL);
847 DeregisterEventSource(h);
850 DismountGlobalDrives();
854 #ifdef REGISTER_POWER_NOTIFICATIONS
855 /* terminate thread used to flush cache */
856 if (powerEventsRegistered)
857 PowerNotificationThreadExit();
860 /* Remove the ExceptionFilter */
861 SetUnhandledExceptionFilter(NULL);
863 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
864 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
865 ServiceStatus.dwCheckPoint = 0;
866 ServiceStatus.dwWaitHint = 0;
867 ServiceStatus.dwControlsAccepted = 0;
868 SetServiceStatus(StatusHandle, &ServiceStatus);
871 DWORD __stdcall afsdMain_thread(void* notUsed)
873 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
874 afsd_Main(1, (LPTSTR*)argv);
881 static SERVICE_TABLE_ENTRY dispatchTable[] = {
882 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
886 if (!StartServiceCtrlDispatcher(dispatchTable))
888 LONG status = GetLastError();
889 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
892 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
894 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
896 SetEvent(WaitToTerminate);
900 if ( hAFSDMainThread ) {
901 WaitForSingleObject( hAFSDMainThread, INFINITE );
902 CloseHandle( hAFSDMainThread );