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 ---");
103 SetEvent(WaitToTerminate);
106 if (GetCurrentThreadId() == MainThreadId)
107 longjmp(notifier_jmp, 1);
114 * For use miscellaneously in smb.c; need to do better
116 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
121 static SERVICE_STATUS ServiceStatus;
122 static SERVICE_STATUS_HANDLE StatusHandle;
125 afsd_ServiceFlushVolume(DWORD dwlpEventData)
127 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
130 ** If UI bit is not set, user interaction is not possible
131 ** BUT, since we are a NON-interactive service, and therefore
132 ** have NO user I/O, it doesn't much matter.
133 ** This benign code left here as example of how to find this out
135 BOOL bUI = (dwlpEventData & 1);
138 if ( PowerNotificationThreadNotify() )
144 /* flush was unsuccessful, or timeout - deny shutdown */
145 dwRet = ERROR_NETWORK_BUSY;
148 /* to deny hibernate, simply return
149 // any value besides NO_ERROR.
151 // dwRet = ERROR_NETWORK_BUSY;
158 /* service control handler used in nt4 only for backward compat. */
160 afsd_ServiceControlHandler(DWORD ctrlCode)
163 DWORD dummyLen, doTrace;
167 case SERVICE_CONTROL_STOP:
169 RpcMgmtStopServerListening(NULL);
171 /* Force trace if requested */
172 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
174 0, KEY_QUERY_VALUE, &parmKey);
175 if (code != ERROR_SUCCESS)
178 dummyLen = sizeof(doTrace);
179 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
181 (BYTE *) &doTrace, &dummyLen);
182 RegCloseKey (parmKey);
183 if (code != ERROR_SUCCESS)
186 afsd_ForceTrace(FALSE);
187 buf_ForceTrace(FALSE);
191 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
192 ServiceStatus.dwWin32ExitCode = NO_ERROR;
193 ServiceStatus.dwCheckPoint = 1;
194 ServiceStatus.dwWaitHint = 10000;
195 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
196 SetServiceStatus(StatusHandle, &ServiceStatus);
197 SetEvent(WaitToTerminate);
199 case SERVICE_CONTROL_INTERROGATE:
200 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
201 ServiceStatus.dwWin32ExitCode = NO_ERROR;
202 ServiceStatus.dwCheckPoint = 0;
203 ServiceStatus.dwWaitHint = 0;
204 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
205 SetServiceStatus(StatusHandle, &ServiceStatus);
207 /* XXX handle system shutdown */
208 /* XXX handle pause & continue */
214 ** Extended ServiceControlHandler that provides Event types
215 ** for monitoring Power events, for example.
218 afsd_ServiceControlHandlerEx(
226 DWORD dummyLen, doTrace;
228 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
232 case SERVICE_CONTROL_STOP:
234 RpcMgmtStopServerListening(NULL);
236 /* Force trace if requested */
237 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
239 0, KEY_QUERY_VALUE, &parmKey);
240 if (code != ERROR_SUCCESS)
243 dummyLen = sizeof(doTrace);
244 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
246 (BYTE *) &doTrace, &dummyLen);
247 RegCloseKey (parmKey);
248 if (code != ERROR_SUCCESS)
251 afsd_ForceTrace(FALSE);
252 buf_ForceTrace(FALSE);
256 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
257 ServiceStatus.dwWin32ExitCode = NO_ERROR;
258 ServiceStatus.dwCheckPoint = 1;
259 ServiceStatus.dwWaitHint = 10000;
260 ServiceStatus.dwControlsAccepted = 0;
261 SetServiceStatus(StatusHandle, &ServiceStatus);
262 SetEvent(WaitToTerminate);
266 case SERVICE_CONTROL_INTERROGATE:
267 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
268 ServiceStatus.dwWin32ExitCode = NO_ERROR;
269 ServiceStatus.dwCheckPoint = 0;
270 ServiceStatus.dwWaitHint = 0;
271 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
272 SetServiceStatus(StatusHandle, &ServiceStatus);
276 /* XXX handle system shutdown */
277 /* XXX handle pause & continue */
278 case SERVICE_CONTROL_POWEREVENT:
281 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
282 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
283 ** Return any error code to deny request,
284 ** i.e. as if returning BROADCAST_QUERY_DENY
286 if (powerEventsRegistered) {
287 switch((int) dwEventType)
289 case PBT_APMQUERYSUSPEND:
290 case PBT_APMQUERYSTANDBY:
294 dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);
300 /* allow remaining case PBT_WhatEver */
303 case PBT_APMRESUMECRITICAL:
304 case PBT_APMRESUMESUSPEND:
305 case PBT_APMRESUMESTANDBY:
306 case PBT_APMBATTERYLOW:
307 case PBT_APMPOWERSTATUSCHANGE:
308 case PBT_APMOEMEVENT:
309 case PBT_APMRESUMEAUTOMATIC:
315 } /* end switch(ctrlCode) */
319 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
321 * Mount a drive into AFS if there global mapping
323 /* DEE Could check first if we are run as SYSTEM */
324 #define MAX_RETRIES 30
325 static void MountGlobalDrives(void)
327 char szAfsPath[_MAX_PATH];
328 char szDriveToMapTo[5];
332 DWORD dwIndex = 0, dwRetry = 0;
334 DWORD dwSubMountSize;
335 char szSubMount[256];
338 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
340 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
341 if (dwResult != ERROR_SUCCESS)
344 while (dwRetry < MAX_RETRIES) {
345 dwDriveSize = sizeof(szDriveToMapTo);
346 dwSubMountSize = sizeof(szSubMount);
347 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
348 if (dwResult != ERROR_MORE_DATA) {
349 if (dwResult != ERROR_SUCCESS) {
350 if (dwResult != ERROR_NO_MORE_ITEMS)
351 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
356 for ( ; dwRetry < MAX_RETRIES; dwRetry++)
359 memset (&nr, 0x00, sizeof(NETRESOURCE));
361 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
363 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
364 nr.dwType=RESOURCETYPE_DISK;
365 nr.lpLocalName=szDriveToMapTo;
366 nr.lpRemoteName=szAfsPath;
367 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
368 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
370 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
371 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
372 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
373 if (dwResult == NO_ERROR) {
376 /* wait for smb server to come up */
377 Sleep((DWORD)1000 /* miliseconds */);
379 /* Disconnect any previous mappings */
380 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
387 static void DismountGlobalDrives()
389 char szAfsPath[_MAX_PATH];
390 char szDriveToMapTo[5];
396 DWORD dwSubMountSize;
397 char szSubMount[256];
400 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
402 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
403 if (dwResult != ERROR_SUCCESS)
407 dwDriveSize = sizeof(szDriveToMapTo);
408 dwSubMountSize = sizeof(szSubMount);
409 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
410 if (dwResult != ERROR_MORE_DATA) {
411 if (dwResult != ERROR_SUCCESS) {
412 if (dwResult != ERROR_NO_MORE_ITEMS)
413 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
418 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
420 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
421 dwResult = WNetCancelConnection(szAfsPath, TRUE);
423 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
430 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
432 DWORD dwVersionHandle;
433 LPVOID pVersionInfo = 0;
435 LPDWORD pLangInfo = 0;
436 LPTSTR szVersion = 0;
438 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
439 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
442 afsi_log("GetFileVersionInfoSize failed");
443 return GetLastError();
446 pVersionInfo = malloc(size);
448 afsi_log("out of memory 1");
449 return ERROR_NOT_ENOUGH_MEMORY;
452 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
453 if (retval = GetLastError())
455 afsi_log("GetFileVersionInfo failed: %d", retval);
459 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
460 (LPVOID*)&pLangInfo, &len);
461 if (retval = GetLastError())
463 afsi_log("VerQueryValue 1 failed: %d", retval);
468 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
469 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
471 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
472 if (retval = GetLastError())
474 /* try again with language 409 since the old binaries were tagged wrong */
476 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
479 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
480 if (retval = GetLastError()) {
481 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
485 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
486 szOutput[dwOutput - 1] = 0;
495 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
497 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
499 wchar_t wfilename[260];
505 HCERTSTORE hStore = NULL;
506 HCRYPTMSG hMsg = NULL;
507 PCMSG_SIGNER_INFO pSignerInfo = NULL;
508 PCCERT_CONTEXT pCertContext = NULL;
511 ZeroMemory(&CertInfo, sizeof(CertInfo));
512 mbstowcs(wfilename, filename, 260);
514 fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
516 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
517 CERT_QUERY_FORMAT_FLAG_BINARY,
527 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
533 fResult = CryptMsgGetParam(hMsg,
534 CMSG_SIGNER_INFO_PARAM,
540 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
546 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
548 fResult = CryptMsgGetParam(hMsg,
549 CMSG_SIGNER_INFO_PARAM,
555 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
561 CertInfo.Issuer = pSignerInfo->Issuer;
562 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
564 pCertContext = CertFindCertificateInStore(hStore,
567 CERT_FIND_SUBJECT_CERT,
572 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
580 LocalFree(pSignerInfo);
583 CertFreeCertificateContext(pCertContext);*/
586 CertCloseStore(hStore,0);
594 BOOL VerifyTrust(CHAR * filename)
596 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
597 WIN_TRUST_SUBJECT_FILE fSubjectFile;
598 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
599 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
600 wchar_t wfilename[260];
603 if (filename == NULL )
606 mbstowcs(wfilename, filename, 260);
608 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
610 fSubjectFile.lpPath = wfilename;
611 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
612 FALSE, GetCurrentProcessId());
613 fContextWSubject.SubjectType = &subject;
614 fContextWSubject.Subject = &fSubjectFile;
616 ret = WinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, &fContextWSubject);
618 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
619 CloseHandle( fSubjectFile.hFile );
620 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
621 CloseHandle( fContextWSubject.hClientToken );
623 if (ret == ERROR_SUCCESS) {
626 DWORD gle = GetLastError();
628 case TRUST_E_PROVIDER_UNKNOWN:
629 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
631 case TRUST_E_NOSIGNATURE:
632 afsi_log("VerifyTrust failed: Unsigned executable");
634 case TRUST_E_EXPLICIT_DISTRUST:
635 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
637 case TRUST_E_SUBJECT_NOT_TRUSTED:
638 afsi_log("VerifyTrust failed: File is not trusted");
640 case CRYPT_E_SECURITY_SETTINGS:
641 afsi_log("VerifyTrust failed: local security options prevent verification");
644 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
650 void LogCertCtx(PCCERT_CONTEXT pCtx) {
652 LPTSTR szName = NULL;
654 // Get Issuer name size.
655 if (!(dwData = CertGetNameString(pCtx,
656 CERT_NAME_SIMPLE_DISPLAY_TYPE,
657 CERT_NAME_ISSUER_FLAG,
661 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
665 // Allocate memory for Issuer name.
666 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
669 if (!(CertGetNameString(pCtx,
670 CERT_NAME_SIMPLE_DISPLAY_TYPE,
671 CERT_NAME_ISSUER_FLAG,
675 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
679 // print Issuer name.
680 afsi_log("Issuer Name: %s", szName);
684 // Get Subject name size.
685 if (!(dwData = CertGetNameString(pCtx,
686 CERT_NAME_SIMPLE_DISPLAY_TYPE,
691 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
695 // Allocate memory for subject name.
696 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
699 if (!(CertGetNameString(pCtx,
700 CERT_NAME_SIMPLE_DISPLAY_TYPE,
705 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
709 // Print Subject Name.
710 afsi_log("Subject Name: %s", szName);
718 BOOL AFSModulesVerify(void)
721 CHAR afsdVersion[128];
722 CHAR modVersion[128];
723 CHAR checkName[1024];
724 BOOL trustVerified = FALSE;
730 PCCERT_CONTEXT pCtxService = NULL;
732 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
735 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
738 afsi_log("%s version %s", filename, afsdVersion);
740 trustVerified = VerifyTrust(filename);
743 // get a certificate context for the signer of afsd_service.
744 pCtxService = GetCertCtx(filename);
746 LogCertCtx(pCtxService);
749 // Get a list of all the modules in this process.
750 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
751 FALSE, GetCurrentProcessId());
753 if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
755 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
757 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
759 char szModName[2048];
761 // Get the full path to the module's file.
762 if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName)))
764 lstrcpy(checkName, szModName);
767 if ( strstr(checkName, "afspthread.dll") ||
768 strstr(checkName, "afsauthent.dll") ||
769 strstr(checkName, "afsrpc.dll") ||
770 strstr(checkName, "libafsconf.dll") ||
771 strstr(checkName, "libosi.dll") )
773 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
778 afsi_log("%s version %s", szModName, modVersion);
779 if (strcmp(afsdVersion,modVersion)) {
780 afsi_log("Version mismatch: %s", szModName);
783 if ( trustVerified ) {
784 if ( !VerifyTrust(szModName) ) {
785 afsi_log("Signature Verification failed: %s", szModName);
788 else if (pCtxService) {
789 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
791 if (!pCtx || !CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
792 pCtxService->pCertInfo,
794 afsi_log("Certificate mismatch: %s", szModName);
802 CertFreeCertificateContext(pCtx);
811 CertFreeCertificateContext(pCtxService);
813 CloseHandle(hProcess);
817 typedef BOOL ( APIENTRY * AfsdInitHook )(void);
818 #define AFSD_INIT_HOOK "AfsdInitHook"
819 #define AFSD_HOOK_DLL "afsdhook.dll"
822 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
825 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
826 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
828 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
829 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
831 void afsd_Main(DWORD argc, LPTSTR *argv)
840 AfsdInitHook initHook;
843 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
844 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
847 osi_InitPanic(afsd_notifier);
848 osi_InitTraceOption();
854 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
855 if ( GetLastError() == ERROR_ALREADY_EXISTS )
856 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
859 hAdvApi32 = LoadLibrary("advapi32.dll");
860 if (hAdvApi32 == NULL)
862 afsi_log("Fatal: cannot load advapi32.dll");
866 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
867 if (pRegisterServiceCtrlHandlerEx)
869 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
870 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
874 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
877 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
878 ServiceStatus.dwServiceSpecificExitCode = 0;
879 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
880 ServiceStatus.dwWin32ExitCode = NO_ERROR;
881 ServiceStatus.dwCheckPoint = 1;
882 ServiceStatus.dwWaitHint = 30000;
883 /* accept Power Events */
884 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
885 SetServiceStatus(StatusHandle, &ServiceStatus);
889 HANDLE h; char *ptbuf[1];
890 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
891 ptbuf[0] = "AFS start pending";
892 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
893 DeregisterEventSource(h);
896 #ifdef REGISTER_POWER_NOTIFICATIONS
903 /* see if we should handle power notifications */
904 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE, &hkParm);
905 if (code == ERROR_SUCCESS) {
906 dummyLen = sizeof(bpower);
907 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
908 (BYTE *) &bpower, &dummyLen);
910 if(code != ERROR_SUCCESS)
915 /* create thread used to flush cache */
917 PowerNotificationThreadCreate();
918 powerEventsRegistered = 1;
923 /* Verify the versions of the DLLs which were loaded */
924 if (!AFSModulesVerify()) {
925 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
926 ServiceStatus.dwWin32ExitCode = NO_ERROR;
927 ServiceStatus.dwCheckPoint = 0;
928 ServiceStatus.dwWaitHint = 0;
929 ServiceStatus.dwControlsAccepted = 0;
930 SetServiceStatus(StatusHandle, &ServiceStatus);
932 /* exit if initialization failed */
936 /* allow an exit to be called prior to any initialization */
937 hInitHookDll = LoadLibrary(AFSD_HOOK_DLL);
941 initHook = ( AfsdInitHook ) GetProcAddress(hInitHookDll, AFSD_INIT_HOOK);
946 FreeLibrary(hInitHookDll);
951 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
952 ServiceStatus.dwWin32ExitCode = NO_ERROR;
953 ServiceStatus.dwCheckPoint = 0;
954 ServiceStatus.dwWaitHint = 0;
955 ServiceStatus.dwControlsAccepted = 0;
956 SetServiceStatus(StatusHandle, &ServiceStatus);
958 /* exit if initialization failed */
963 /* allow another 15 seconds to start */
964 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
965 ServiceStatus.dwServiceSpecificExitCode = 0;
966 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
967 ServiceStatus.dwWin32ExitCode = NO_ERROR;
968 ServiceStatus.dwCheckPoint = 2;
969 ServiceStatus.dwWaitHint = 20000;
970 /* accept Power Events */
971 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
972 SetServiceStatus(StatusHandle, &ServiceStatus);
977 MainThreadId = GetCurrentThreadId();
978 jmpret = setjmp(notifier_jmp);
983 code = afsd_InitCM(&reason);
985 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
986 osi_panic(reason, __FILE__, __LINE__);
990 ServiceStatus.dwCheckPoint++;
991 ServiceStatus.dwWaitHint -= 5000;
992 SetServiceStatus(StatusHandle, &ServiceStatus);
994 code = afsd_InitDaemons(&reason);
996 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
997 osi_panic(reason, __FILE__, __LINE__);
1001 ServiceStatus.dwCheckPoint++;
1002 ServiceStatus.dwWaitHint -= 5000;
1003 SetServiceStatus(StatusHandle, &ServiceStatus);
1005 code = afsd_InitSMB(&reason, MessageBox);
1007 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1008 osi_panic(reason, __FILE__, __LINE__);
1011 MountGlobalDrives();
1014 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1015 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1016 ServiceStatus.dwCheckPoint = 0;
1017 ServiceStatus.dwWaitHint = 0;
1019 /* accept Power events */
1020 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
1021 SetServiceStatus(StatusHandle, &ServiceStatus);
1024 HANDLE h; char *ptbuf[1];
1025 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1026 ptbuf[0] = "AFS running";
1027 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1028 DeregisterEventSource(h);
1032 WaitForSingleObject(WaitToTerminate, INFINITE);
1035 HANDLE h; char *ptbuf[1];
1036 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1037 ptbuf[0] = "AFS quitting";
1038 ReportEvent(h, GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
1039 0, 0, NULL, 1, 0, ptbuf, NULL);
1040 DeregisterEventSource(h);
1043 DismountGlobalDrives();
1047 #ifdef REGISTER_POWER_NOTIFICATIONS
1048 /* terminate thread used to flush cache */
1049 if (powerEventsRegistered)
1050 PowerNotificationThreadExit();
1053 /* Remove the ExceptionFilter */
1054 SetUnhandledExceptionFilter(NULL);
1056 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1057 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1058 ServiceStatus.dwCheckPoint = 0;
1059 ServiceStatus.dwWaitHint = 0;
1060 ServiceStatus.dwControlsAccepted = 0;
1061 SetServiceStatus(StatusHandle, &ServiceStatus);
1064 DWORD __stdcall afsdMain_thread(void* notUsed)
1066 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1067 afsd_Main(1, (LPTSTR*)argv);
1074 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1075 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1079 if (!StartServiceCtrlDispatcher(dispatchTable))
1081 LONG status = GetLastError();
1082 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1085 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1087 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1089 SetEvent(WaitToTerminate);
1093 if ( hAFSDMainThread ) {
1094 WaitForSingleObject( hAFSDMainThread, INFINITE );
1095 CloseHandle( hAFSDMainThread );