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 <afsconfig.h>
11 #include <afs/param.h>
23 #include "afsd_init.h"
24 #include "lanahelper.h"
28 #include <WINNT\afsreg.h>
42 //#define REGISTER_POWER_NOTIFICATIONS 1
43 #include "afsd_flushvol.h"
45 extern void afsi_log(char *pattern, ...);
47 static SERVICE_STATUS ServiceStatus;
48 static SERVICE_STATUS_HANDLE StatusHandle;
49 static BOOL bRunningAsService = TRUE;
51 HANDLE hAFSDMainThread = NULL;
53 HANDLE WaitToTerminate;
55 static int GlobalStatus;
58 unsigned int MainThreadId;
62 extern int traceOnPanic;
63 extern HANDLE afsi_file;
65 static int powerEventsRegistered = 0;
66 extern int powerStateSuspended = 0;
67 extern int RDR_Initialized = 0;
69 static VOID (WINAPI* pRtlCaptureContext)(PCONTEXT ContextRecord) = NULL;
72 * Notifier function for use by osi_panic
74 static void afsd_notifier(char *msgp, char *filep, long line)
79 msgp = "unspecified assert";
82 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION,
85 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG, msgp);
89 osi_LogEnable(afsd_logp);
91 afsd_ForceTrace(TRUE);
94 if (pRtlCaptureContext) {
95 pRtlCaptureContext(&context);
96 afsd_printStack(GetCurrentThread(), &context);
100 if (IsDebuggerPresent())
104 afsi_log("--- begin dump ---");
105 cm_MemDumpDirStats(afsi_file, "a", 0);
106 cm_MemDumpBPlusStats(afsi_file, "a", 0);
107 cm_DumpCells(afsi_file, "a", 0);
108 cm_DumpVolumes(afsi_file, "a", 0);
109 cm_DumpSCache(afsi_file, "a", 0);
110 cm_DumpBufHashTable(afsi_file, "a", 0);
111 cm_DumpServers(afsi_file, "a", 0);
112 smb_DumpVCP(afsi_file, "a", 0);
113 rx_DumpPackets(afsi_file, "a");
114 rx_DumpCalls(afsi_file, "a");
115 afsi_log("--- end dump ---");
117 GenerateMiniDump(NULL);
119 SetEvent(WaitToTerminate);
122 if (GetCurrentThreadId() == MainThreadId)
123 longjmp(notifier_jmp, 1);
126 if (bRunningAsService) {
127 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
128 ServiceStatus.dwWin32ExitCode = NO_ERROR;
129 ServiceStatus.dwCheckPoint = 0;
130 ServiceStatus.dwWaitHint = 0;
131 ServiceStatus.dwControlsAccepted = 0;
132 SetServiceStatus(StatusHandle, &ServiceStatus);
138 * For use miscellaneously in smb.c; need to do better
140 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
146 afsd_ServiceFlushVolume(DWORD dwlpEventData)
148 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
151 ** If UI bit is not set, user interaction is not possible
152 ** BUT, since we are a NON-interactive service, and therefore
153 ** have NO user I/O, it doesn't much matter.
154 ** This benign code left here as example of how to find this out
156 BOOL bUI = (dwlpEventData & 1);
159 if ( PowerNotificationThreadNotify() )
165 /* flush was unsuccessful, or timeout - deny shutdown */
166 dwRet = ERROR_NETWORK_BUSY;
169 /* to deny hibernate, simply return
170 // any value besides NO_ERROR.
172 // dwRet = ERROR_NETWORK_BUSY;
179 /* service control handler used in nt4 only for backward compat. */
181 afsd_ServiceControlHandler(DWORD ctrlCode)
184 DWORD dummyLen, doTrace;
188 case SERVICE_CONTROL_SHUTDOWN:
189 case SERVICE_CONTROL_STOP:
190 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
191 ServiceStatus.dwWin32ExitCode = NO_ERROR;
192 ServiceStatus.dwCheckPoint = 1;
193 ServiceStatus.dwWaitHint = 30000;
194 ServiceStatus.dwControlsAccepted = 0;
195 SetServiceStatus(StatusHandle, &ServiceStatus);
197 if (ctrlCode == SERVICE_CONTROL_STOP)
198 afsi_log("SERVICE_CONTROL_STOP");
200 afsi_log("SERVICE_CONTROL_SHUTDOWN");
202 /* Write all dirty buffers back to server */
203 if ( !lana_OnlyLoopback() )
206 /* Force trace if requested */
207 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
208 AFSREG_CLT_SVC_PARAM_SUBKEY,
209 0, KEY_QUERY_VALUE, &parmKey);
210 if (code != ERROR_SUCCESS)
213 dummyLen = sizeof(doTrace);
214 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
216 (BYTE *) &doTrace, &dummyLen);
217 RegCloseKey (parmKey);
218 if (code != ERROR_SUCCESS)
221 afsd_ForceTrace(FALSE);
222 buf_ForceTrace(FALSE);
226 SetEvent(WaitToTerminate);
229 case SERVICE_CONTROL_INTERROGATE:
230 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
231 ServiceStatus.dwWin32ExitCode = NO_ERROR;
232 ServiceStatus.dwCheckPoint = 0;
233 ServiceStatus.dwWaitHint = 0;
234 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
235 SetServiceStatus(StatusHandle, &ServiceStatus);
237 /* XXX handle system shutdown */
238 /* XXX handle pause & continue */
244 ** Extended ServiceControlHandler that provides Event types
245 ** for monitoring Power events, for example.
248 afsd_ServiceControlHandlerEx(
256 DWORD dummyLen, doTrace;
258 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
259 OSVERSIONINFO osVersion;
260 DWORD dwCurrentState = ServiceStatus.dwCurrentState;
262 /* Get the version of Windows */
263 memset(&osVersion, 0x00, sizeof(osVersion));
264 osVersion.dwOSVersionInfoSize = sizeof(osVersion);
265 GetVersionEx(&osVersion);
269 case SERVICE_CONTROL_SHUTDOWN:
270 case SERVICE_CONTROL_STOP:
271 if (ctrlCode == SERVICE_CONTROL_SHUTDOWN)
272 afsi_log("SERVICE_CONTROL_SHUTDOWN");
274 afsi_log("SERVICE_CONTROL_STOP");
276 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
277 ServiceStatus.dwWin32ExitCode = NO_ERROR;
278 ServiceStatus.dwCheckPoint = 1;
279 ServiceStatus.dwWaitHint = 30000;
280 ServiceStatus.dwControlsAccepted = 0;
281 SetServiceStatus(StatusHandle, &ServiceStatus);
283 /* Write all dirty buffers back to server */
284 if (dwCurrentState == SERVICE_RUNNING &&
285 !lana_OnlyLoopback() )
288 /* Force trace if requested */
289 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
290 AFSREG_CLT_SVC_PARAM_SUBKEY,
291 0, KEY_QUERY_VALUE, &parmKey);
292 if (code != ERROR_SUCCESS)
295 dummyLen = sizeof(doTrace);
296 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
298 (BYTE *) &doTrace, &dummyLen);
299 RegCloseKey (parmKey);
300 if (code != ERROR_SUCCESS)
303 afsd_ForceTrace(FALSE);
304 buf_ForceTrace(FALSE);
308 SetEvent(WaitToTerminate);
312 case SERVICE_CONTROL_INTERROGATE:
313 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
314 ServiceStatus.dwWin32ExitCode = NO_ERROR;
315 ServiceStatus.dwCheckPoint = 0;
316 ServiceStatus.dwWaitHint = 0;
317 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
318 SetServiceStatus(StatusHandle, &ServiceStatus);
319 afsi_log("SERVICE_CONTROL_INTERROGATE");
320 osi_Log0(afsd_logp, "SERVICE_CONTROL_INTERROGATE");
324 /* XXX handle system shutdown */
325 /* XXX handle pause & continue */
326 case SERVICE_CONTROL_POWEREVENT:
329 afsi_log("SERVICE_CONTROL_POWEREVENT");
331 osi_Log0(afsd_logp, "SERVICE_CONTROL_POWEREVENT");
333 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
334 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
335 ** Return any error code to deny request,
336 ** i.e. as if returning BROADCAST_QUERY_DENY
338 if (powerEventsRegistered) {
339 switch((int) dwEventType)
341 case PBT_APMQUERYSUSPEND:
342 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
343 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSUSPEND");
344 /* Write all dirty buffers back to server */
345 if ( !lana_OnlyLoopback() )
347 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
348 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
351 case PBT_APMQUERYSTANDBY:
352 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
353 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSTANDBY");
354 /* Write all dirty buffers back to server */
355 if ( !lana_OnlyLoopback() )
357 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
358 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
362 /* allow remaining case PBT_WhatEver */
364 afsi_log("SERVICE_CONTROL_APMSUSPEND");
365 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSUSPEND");
366 powerStateSuspended = 1;
367 if (osVersion.dwMajorVersion >= 6)
368 smb_StopListeners(0);
375 afsi_log("SERVICE_CONTROL_APMSUSPEND complete");
376 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSUSPEND complete");
379 afsi_log("SERVICE_CONTROL_APMSTANDBY");
380 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSTANDBY");
381 powerStateSuspended = 1;
382 if (osVersion.dwMajorVersion >= 6)
383 smb_StopListeners(0);
388 afsi_log("SERVICE_CONTROL_APMSTANDBY complete");
389 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSTANDBY complete");
391 case PBT_APMRESUMECRITICAL:
392 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
393 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMECRITICAL");
394 if (osVersion.dwMajorVersion >= 6)
395 smb_RestartListeners(0);
396 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
400 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL complete");
401 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMECRITICAL complete");
403 case PBT_APMRESUMESUSPEND:
404 /* User logged in after suspend */
405 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
406 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESUSPEND");
407 powerStateSuspended = 0;
408 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
409 if (osVersion.dwMajorVersion >= 6)
410 smb_RestartListeners(0);
411 if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
412 smb_SetLanAdapterChangeDetected();
417 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND complete");
418 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESUSPEND complete");
420 case PBT_APMRESUMESTANDBY:
421 /* User logged in after standby */
422 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
423 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESTANDBY");
424 powerStateSuspended = 0;
425 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
426 if (osVersion.dwMajorVersion >= 6)
427 smb_RestartListeners(0);
428 if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
429 smb_SetLanAdapterChangeDetected();
434 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY complete");
435 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESTANDBY complete");
437 case PBT_APMBATTERYLOW:
438 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
439 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMBATTERYLOW");
442 case PBT_APMPOWERSTATUSCHANGE:
444 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
446 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
449 case PBT_APMOEMEVENT:
451 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
453 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMOEMEVENT");
456 case PBT_APMRESUMEAUTOMATIC:
457 /* This is the message delivered once all devices are up */
458 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
459 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMEAUTOMATIC");
460 if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
461 smb_SetLanAdapterChangeDetected();
463 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
465 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC complete");
466 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMEAUTOMATIC complete");
469 afsi_log("SERVICE_CONTROL_unknown");
470 osi_Log1(afsd_logp, "SERVICE_CONTROL_unknown: 0x%x", dwEventType);
476 case SERVICE_CONTROL_CUSTOM_DUMP:
478 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
479 GenerateMiniDump(NULL);
483 } /* end switch(ctrlCode) */
487 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
489 * Mount a drive into AFS if there global mapping
491 /* DEE Could check first if we are run as SYSTEM */
492 #define MAX_RETRIES 10
493 #define MAX_DRIVES 23
494 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
496 char szAfsPath[_MAX_PATH];
497 char szDriveToMapTo[5];
501 DWORD dwIndex = 0, dwRetry = 0;
503 DWORD dwSubMountSize;
504 char szSubMount[256];
507 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
509 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
510 if (dwResult != ERROR_SUCCESS)
513 while (dwIndex < MAX_DRIVES) {
514 dwDriveSize = sizeof(szDriveToMapTo);
515 dwSubMountSize = sizeof(szSubMount);
516 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
517 if (dwResult != ERROR_MORE_DATA) {
518 if (dwResult != ERROR_SUCCESS) {
519 if (dwResult != ERROR_NO_MORE_ITEMS)
520 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
525 for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
528 memset (&nr, 0x00, sizeof(NETRESOURCE));
530 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
532 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
533 nr.dwType=RESOURCETYPE_DISK;
534 nr.lpLocalName=strlen(szDriveToMapTo) > 0 ? szDriveToMapTo : NULL;
535 nr.lpRemoteName=szAfsPath;
536 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
537 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
539 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
540 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
541 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
542 if (dwResult == NO_ERROR) {
545 /* wait for smb server to come up */
546 Sleep((DWORD)1000 /* miliseconds */);
548 /* Disconnect any previous mappings */
549 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
557 static HANDLE hThreadMountGlobalDrives = NULL;
559 static void MountGlobalDrives()
563 hThreadMountGlobalDrives = CreateThread(NULL, 0, MountGlobalDrivesThread, 0, 0, &tid);
565 if ( hThreadMountGlobalDrives ) {
566 DWORD rc = WaitForSingleObject( hThreadMountGlobalDrives, 15000 );
567 if (rc == WAIT_TIMEOUT) {
568 afsi_log("GlobalAutoMap thread failed to complete after 15 seconds");
569 } else if (rc == WAIT_OBJECT_0) {
570 afsi_log("GlobalAutoMap thread completed");
571 CloseHandle( hThreadMountGlobalDrives );
572 hThreadMountGlobalDrives = NULL;
577 static void DismountGlobalDrives()
579 char szAfsPath[_MAX_PATH];
580 char szDriveToMapTo[5];
582 DWORD dwSubMountSize;
583 char szSubMount[256];
590 if ( hThreadMountGlobalDrives ) {
591 DWORD rc = WaitForSingleObject(hThreadMountGlobalDrives, 0);
593 if (rc == WAIT_TIMEOUT) {
594 afsi_log("GlobalAutoMap thread failed to complete before service shutdown");
596 else if (rc == WAIT_OBJECT_0) {
597 afsi_log("GlobalAutoMap thread completed");
598 CloseHandle( hThreadMountGlobalDrives );
599 hThreadMountGlobalDrives = NULL;
603 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
605 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
606 if (dwResult != ERROR_SUCCESS)
609 while (dwIndex < MAX_DRIVES) {
610 dwDriveSize = sizeof(szDriveToMapTo);
611 dwSubMountSize = sizeof(szSubMount);
612 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
613 if (dwResult != ERROR_MORE_DATA) {
614 if (dwResult != ERROR_SUCCESS) {
615 if (dwResult != ERROR_NO_MORE_ITEMS)
616 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
621 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
623 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
624 dwResult = WNetCancelConnection(szAfsPath, TRUE);
626 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
633 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
635 DWORD dwVersionHandle;
636 LPVOID pVersionInfo = 0;
638 LPDWORD pLangInfo = 0;
639 LPTSTR szVersion = 0;
641 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
642 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
645 afsi_log("GetFileVersionInfoSize failed");
646 return GetLastError();
649 pVersionInfo = malloc(size);
651 afsi_log("out of memory 1");
652 return ERROR_NOT_ENOUGH_MEMORY;
655 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
656 if (retval = GetLastError())
658 afsi_log("GetFileVersionInfo failed: %d", retval);
662 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
663 (LPVOID*)&pLangInfo, &len);
664 if (retval = GetLastError())
666 afsi_log("VerQueryValue 1 failed: %d", retval);
671 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
672 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
674 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
675 if (retval = GetLastError())
677 /* try again with language 409 since the old binaries were tagged wrong */
679 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
682 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
683 if (retval = GetLastError()) {
684 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
688 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
689 szOutput[dwOutput - 1] = 0;
698 static HINSTANCE hCrypt32;
699 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
700 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
701 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
702 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
703 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
704 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
705 HCRYPTMSG* phMsg, const void** ppvContext);
706 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
707 void* pvData, DWORD* pcbData);
708 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
709 DWORD dwFindFlags, DWORD dwFindType,
710 const void* pvFindPara,
711 PCCERT_CONTEXT pPrevCertContext);
712 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
713 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
714 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
715 PCERT_INFO pCertId2);
716 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
718 void LoadCrypt32(void)
720 hCrypt32 = LoadLibrary("crypt32");
724 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
725 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
726 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
727 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
728 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
729 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
730 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
731 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
733 if ( !pCertGetNameString ||
734 !pCryptQueryObject ||
735 !pCryptMsgGetParam ||
736 !pCertFindCertificateInStore ||
739 !pCertCompareCertificate ||
740 !pCertFreeCertificateContext)
742 FreeLibrary(hCrypt32);
747 void UnloadCrypt32(void)
749 FreeLibrary(hCrypt32);
752 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
754 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
756 wchar_t wfilename[260];
762 HCERTSTORE hStore = NULL;
763 HCRYPTMSG hMsg = NULL;
764 PCMSG_SIGNER_INFO pSignerInfo = NULL;
765 PCCERT_CONTEXT pCertContext = NULL;
768 if ( hCrypt32 == NULL )
771 ZeroMemory(&CertInfo, sizeof(CertInfo));
772 mbstowcs(wfilename, filename, 260);
774 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
776 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
777 CERT_QUERY_FORMAT_FLAG_BINARY,
787 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
793 fResult = pCryptMsgGetParam(hMsg,
794 CMSG_SIGNER_INFO_PARAM,
800 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
806 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
808 fResult = pCryptMsgGetParam(hMsg,
809 CMSG_SIGNER_INFO_PARAM,
815 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
821 CertInfo.Issuer = pSignerInfo->Issuer;
822 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
824 pCertContext = pCertFindCertificateInStore(hStore,
827 CERT_FIND_SUBJECT_CERT,
832 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
840 LocalFree(pSignerInfo);
843 CertFreeCertificateContext(pCertContext);*/
846 pCertCloseStore(hStore,0);
849 pCryptMsgClose(hMsg);
854 BOOL VerifyTrust(CHAR * filename)
856 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
857 WIN_TRUST_SUBJECT_FILE fSubjectFile;
858 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
859 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
860 wchar_t wfilename[260];
862 BOOL success = FALSE;
864 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
867 if (filename == NULL )
870 hWinTrust = LoadLibrary("wintrust");
874 if (((FARPROC) pWinVerifyTrust =
875 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
877 FreeLibrary(hWinTrust);
881 mbstowcs(wfilename, filename, 260);
883 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
885 fSubjectFile.lpPath = wfilename;
886 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
887 FALSE, GetCurrentProcessId());
888 fContextWSubject.SubjectType = &subject;
889 fContextWSubject.Subject = &fSubjectFile;
891 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
893 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
894 CloseHandle( fSubjectFile.hFile );
895 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
896 CloseHandle( fContextWSubject.hClientToken );
898 if (ret == ERROR_SUCCESS) {
901 DWORD gle = GetLastError();
903 case TRUST_E_PROVIDER_UNKNOWN:
904 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
906 case TRUST_E_NOSIGNATURE:
907 afsi_log("VerifyTrust failed: Unsigned executable");
909 case TRUST_E_EXPLICIT_DISTRUST:
910 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
912 case TRUST_E_SUBJECT_NOT_TRUSTED:
913 afsi_log("VerifyTrust failed: File is not trusted");
915 case TRUST_E_BAD_DIGEST:
916 afsi_log("VerifyTrust failed: Executable has been modified");
918 case CRYPT_E_SECURITY_SETTINGS:
919 afsi_log("VerifyTrust failed: local security options prevent verification");
922 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
926 FreeLibrary(hWinTrust);
930 void LogCertCtx(PCCERT_CONTEXT pCtx) {
932 LPTSTR szName = NULL;
934 if ( hCrypt32 == NULL )
937 // Get Issuer name size.
938 if (!(dwData = pCertGetNameString(pCtx,
939 CERT_NAME_SIMPLE_DISPLAY_TYPE,
940 CERT_NAME_ISSUER_FLAG,
944 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
948 // Allocate memory for Issuer name.
949 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
952 if (!(pCertGetNameString(pCtx,
953 CERT_NAME_SIMPLE_DISPLAY_TYPE,
954 CERT_NAME_ISSUER_FLAG,
958 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
962 // print Issuer name.
963 afsi_log("Issuer Name: %s", szName);
967 // Get Subject name size.
968 if (!(dwData = pCertGetNameString(pCtx,
969 CERT_NAME_SIMPLE_DISPLAY_TYPE,
974 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
978 // Allocate memory for subject name.
979 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
982 if (!(pCertGetNameString(pCtx,
983 CERT_NAME_SIMPLE_DISPLAY_TYPE,
988 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
992 // Print Subject Name.
993 afsi_log("Subject Name: %s", szName);
1001 BOOL AFSModulesVerify(void)
1003 CHAR filename[1024];
1004 CHAR afsdVersion[128];
1005 CHAR modVersion[128];
1006 CHAR checkName[1024];
1007 BOOL trustVerified = FALSE;
1008 HMODULE hMods[1024];
1012 BOOL success = TRUE;
1013 PCCERT_CONTEXT pCtxService = NULL;
1015 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
1016 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
1017 DWORD dummyLen, code;
1018 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
1019 DWORD verifyServiceSig = TRUE;
1022 hPSAPI = LoadLibrary("psapi");
1024 if ( hPSAPI == NULL )
1027 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
1030 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
1033 afsi_log("%s version %s", filename, afsdVersion);
1035 if (((FARPROC) pGetModuleFileNameExA =
1036 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
1037 ((FARPROC) pEnumProcessModules =
1038 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
1040 FreeLibrary(hPSAPI);
1045 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1046 AFSREG_CLT_SVC_PARAM_SUBKEY,
1047 0, KEY_QUERY_VALUE, &parmKey);
1048 if (code == ERROR_SUCCESS) {
1049 dummyLen = sizeof(cacheSize);
1050 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
1051 (BYTE *) &cacheSize, &dummyLen);
1052 RegCloseKey (parmKey);
1055 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
1056 0, KEY_QUERY_VALUE, &parmKey);
1057 if (code == ERROR_SUCCESS) {
1058 dummyLen = sizeof(verifyServiceSig);
1059 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
1060 (BYTE *) &verifyServiceSig, &dummyLen);
1061 RegCloseKey (parmKey);
1064 if (verifyServiceSig
1066 && cacheSize < 716800
1069 trustVerified = VerifyTrust(filename);
1071 afsi_log("Signature Verification disabled");
1074 if (trustVerified) {
1077 // get a certificate context for the signer of afsd_service.
1078 pCtxService = GetCertCtx(filename);
1080 LogCertCtx(pCtxService);
1083 // Get a list of all the modules in this process.
1084 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
1085 FALSE, GetCurrentProcessId());
1087 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
1089 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
1091 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
1093 char szModName[2048];
1095 // Get the full path to the module's file.
1096 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
1098 lstrcpy(checkName, szModName);
1101 if ( strstr(checkName, "afspthread.dll") ||
1102 strstr(checkName, "afsauthent.dll") ||
1103 strstr(checkName, "afsrpc.dll") ||
1104 strstr(checkName, "libafsconf.dll") ||
1105 strstr(checkName, "libosi.dll") )
1107 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1112 afsi_log("%s version %s", szModName, modVersion);
1113 if (strcmp(afsdVersion,modVersion)) {
1114 afsi_log("Version mismatch: %s", szModName);
1117 if ( trustVerified ) {
1118 if ( !VerifyTrust(szModName) ) {
1119 afsi_log("Signature Verification failed: %s", szModName);
1122 else if (pCtxService) {
1123 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1125 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1126 pCtxService->pCertInfo,
1128 afsi_log("Certificate mismatch: %s", szModName);
1136 pCertFreeCertificateContext(pCtx);
1145 pCertFreeCertificateContext(pCtxService);
1149 FreeLibrary(hPSAPI);
1151 CloseHandle(hProcess);
1156 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1159 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1160 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1162 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1163 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1166 afsd_Main(DWORD argc, LPTSTR *argv)
1178 void afsd_DbgBreakAllocInit();
1180 afsd_DbgBreakAllocInit();
1181 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1182 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1185 afsd_SetUnhandledExceptionFilter();
1187 osi_InitPanic(afsd_notifier);
1188 osi_InitTraceOption();
1190 hKernel32 = LoadLibrary("kernel32.dll");
1191 if (hKernel32 == NULL)
1193 afsi_log("Fatal: cannot load kernel32.dll");
1196 pRtlCaptureContext = GetProcAddress(hKernel32, "RtlCaptureContext");
1202 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1203 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1204 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1207 hAdvApi32 = LoadLibrary("advapi32.dll");
1208 if (hAdvApi32 == NULL)
1210 afsi_log("Fatal: cannot load advapi32.dll");
1214 if (bRunningAsService) {
1215 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1216 if (pRegisterServiceCtrlHandlerEx)
1218 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1219 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1223 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1226 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1227 ServiceStatus.dwServiceSpecificExitCode = 0;
1228 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1229 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1230 ServiceStatus.dwCheckPoint = 1;
1231 ServiceStatus.dwWaitHint = 120000;
1232 /* accept Power Events */
1233 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1234 SetServiceStatus(StatusHandle, &ServiceStatus);
1238 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
1240 #ifdef REGISTER_POWER_NOTIFICATIONS
1247 /* see if we should handle power notifications */
1248 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1249 0, KEY_QUERY_VALUE, &hkParm);
1250 if (code == ERROR_SUCCESS) {
1251 dummyLen = sizeof(bpower);
1252 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1253 (BYTE *) &bpower, &dummyLen);
1255 if(code != ERROR_SUCCESS)
1258 RegCloseKey(hkParm);
1260 /* create thread used to flush cache */
1262 PowerNotificationThreadCreate();
1263 powerEventsRegistered = 1;
1268 /* Verify the versions of the DLLs which were loaded */
1269 if (!AFSModulesVerify()) {
1270 if (bRunningAsService) {
1271 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1272 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1273 ServiceStatus.dwCheckPoint = 0;
1274 ServiceStatus.dwWaitHint = 0;
1275 ServiceStatus.dwControlsAccepted = 0;
1276 SetServiceStatus(StatusHandle, &ServiceStatus);
1278 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
1280 /* exit if initialization failed */
1284 /* allow an exit to be called prior to any initialization */
1285 hHookDll = cm_LoadAfsdHookLib();
1289 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1292 hookRc = initHook();
1294 FreeLibrary(hHookDll);
1297 if (hookRc == FALSE)
1299 if (bRunningAsService) {
1300 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1301 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1302 ServiceStatus.dwCheckPoint = 0;
1303 ServiceStatus.dwWaitHint = 0;
1304 ServiceStatus.dwControlsAccepted = 0;
1305 SetServiceStatus(StatusHandle, &ServiceStatus);
1307 /* exit if initialization failed */
1312 /* allow another 120 seconds to start */
1313 if (bRunningAsService) {
1314 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1315 ServiceStatus.dwServiceSpecificExitCode = 0;
1316 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1317 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1318 ServiceStatus.dwCheckPoint = 2;
1319 ServiceStatus.dwWaitHint = 120000;
1320 /* accept Power Events */
1321 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1322 SetServiceStatus(StatusHandle, &ServiceStatus);
1327 /* Perform Volume Status Notification Initialization */
1328 cm_VolStatus_Initialization();
1331 MainThreadId = GetCurrentThreadId();
1332 jmpret = setjmp(notifier_jmp);
1337 code = afsd_InitCM(&reason);
1339 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1340 osi_panic(reason, __FILE__, __LINE__);
1344 if (bRunningAsService) {
1345 ServiceStatus.dwCheckPoint = 3;
1346 ServiceStatus.dwWaitHint = 30000;
1347 SetServiceStatus(StatusHandle, &ServiceStatus);
1350 /* allow an exit to be called post rx initialization */
1351 hHookDll = cm_LoadAfsdHookLib();
1355 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1358 hookRc = rxStartedHook();
1360 FreeLibrary(hHookDll);
1363 if (hookRc == FALSE)
1365 if (bRunningAsService) {
1366 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1367 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1368 ServiceStatus.dwCheckPoint = 0;
1369 ServiceStatus.dwWaitHint = 0;
1370 ServiceStatus.dwControlsAccepted = 0;
1371 SetServiceStatus(StatusHandle, &ServiceStatus);
1373 /* exit if initialization failed */
1379 if (bRunningAsService) {
1380 ServiceStatus.dwCheckPoint = 4;
1381 ServiceStatus.dwWaitHint = 15000;
1382 SetServiceStatus(StatusHandle, &ServiceStatus);
1386 /* Notify any volume status handlers that the cache manager has started */
1387 cm_VolStatus_Service_Started();
1389 code = RDR_Initialize();
1390 RDR_Initialized = !code;
1391 afsi_log("RDR_Initialize returned: (code = %d)", code);
1393 if (RDR_Initialized) {
1394 if (cm_sysNameCount)
1395 RDR_SysName( AFS_SYSNAME_ARCH_32BIT, cm_sysNameCount, cm_sysNameList );
1397 if (cm_sysName64Count)
1398 RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysName64Count, cm_sysName64List );
1399 else if (cm_sysNameCount)
1400 RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysNameCount, cm_sysNameList );
1405 * Set the default for the SMB interface based upon the state of the
1406 * Redirector interface.
1408 smb_Enabled = !RDR_Initialized;
1410 code = afsd_InitSMB(&reason, MessageBox);
1411 if (smb_Enabled && code != 0) {
1412 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1413 osi_panic(reason, __FILE__, __LINE__);
1416 if (!smb_Enabled && !RDR_Initialized) {
1417 afsi_log("Neither RDR nor SMB interfaces available");
1418 osi_panic(reason, __FILE__, __LINE__);
1421 /* allow an exit to be called post smb initialization */
1422 hHookDll = cm_LoadAfsdHookLib();
1426 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1429 hookRc = smbStartedHook();
1431 FreeLibrary(hHookDll);
1434 if (hookRc == FALSE)
1436 if (bRunningAsService) {
1437 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1438 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1439 ServiceStatus.dwCheckPoint = 0;
1440 ServiceStatus.dwWaitHint = 0;
1441 ServiceStatus.dwControlsAccepted = 0;
1442 SetServiceStatus(StatusHandle, &ServiceStatus);
1444 /* exit if initialization failed */
1449 MountGlobalDrives();
1451 code = afsd_InitDaemons(&reason);
1453 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1454 osi_panic(reason, __FILE__, __LINE__);
1458 if (bRunningAsService) {
1459 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1460 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1461 ServiceStatus.dwCheckPoint = 5;
1462 ServiceStatus.dwWaitHint = 0;
1464 /* accept Power events */
1465 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1466 SetServiceStatus(StatusHandle, &ServiceStatus);
1470 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
1473 /* allow an exit to be called when started */
1474 hHookDll = cm_LoadAfsdHookLib();
1478 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1481 hookRc = startedHook();
1483 FreeLibrary(hHookDll);
1486 if (hookRc == FALSE)
1488 if (bRunningAsService) {
1489 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1490 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1491 ServiceStatus.dwCheckPoint = 0;
1492 ServiceStatus.dwWaitHint = 0;
1493 ServiceStatus.dwControlsAccepted = 0;
1494 SetServiceStatus(StatusHandle, &ServiceStatus);
1496 /* exit if initialization failed */
1501 WaitForSingleObject(WaitToTerminate, INFINITE);
1503 if (bRunningAsService) {
1504 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
1505 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1506 ServiceStatus.dwCheckPoint = 6;
1507 ServiceStatus.dwWaitHint = 120000;
1508 ServiceStatus.dwControlsAccepted = 0;
1509 SetServiceStatus(StatusHandle, &ServiceStatus);
1511 afsi_log("Received Termination Signal, Stopping Service");
1514 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP);
1516 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
1518 /* allow an exit to be called prior to stopping the service */
1519 hHookDll = cm_LoadAfsdHookLib();
1523 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1526 hookRc = stoppingHook();
1528 FreeLibrary(hHookDll);
1533 #ifdef AFS_FREELANCE_CLIENT
1534 cm_FreelanceShutdown();
1535 afsi_log("Freelance Shutdown complete");
1538 DismountGlobalDrives();
1539 afsi_log("Global Drives dismounted");
1541 if (RDR_Initialized) {
1542 RDR_ShutdownNotify();
1543 cm_VolStatus_SetRDRNotifications(FALSE);
1544 afsi_log("RDR notified of shutdown");
1548 afsi_log("smb shutdown complete");
1550 cm_ReleaseAllLocks();
1552 cm_DaemonShutdown();
1553 afsi_log("Daemon shutdown complete");
1556 afsi_log("Buffer shutdown complete");
1562 cm_ShutdownMappedMemory();
1564 if (RDR_Initialized) {
1565 RDR_ShutdownFinal();
1566 afsi_log("RDR shutdown complete");
1570 afsi_log("rx finalization complete");
1572 #ifdef REGISTER_POWER_NOTIFICATIONS
1573 /* terminate thread used to flush cache */
1574 if (powerEventsRegistered)
1575 PowerNotificationThreadExit();
1580 cm_BPlusDumpStats();
1583 /* Notify any Volume Status Handlers that we are stopped */
1584 cm_VolStatus_Service_Stopped();
1586 /* Cleanup any Volume Status Notification Handler */
1587 cm_VolStatus_Finalize();
1589 /* allow an exit to be called after stopping the service */
1590 hHookDll = cm_LoadAfsdHookLib();
1594 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1597 hookRc = stoppedHook();
1599 FreeLibrary(hHookDll);
1603 /* Remove the ExceptionFilter */
1604 SetUnhandledExceptionFilter(NULL);
1606 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPED);
1608 if (bRunningAsService) {
1609 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1610 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1611 ServiceStatus.dwCheckPoint = 7;
1612 ServiceStatus.dwWaitHint = 0;
1613 ServiceStatus.dwControlsAccepted = 0;
1614 SetServiceStatus(StatusHandle, &ServiceStatus);
1618 DWORD __stdcall afsdMain_thread(void* notUsed)
1620 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1621 afsd_Main(1, (LPTSTR*)argv);
1627 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1631 main(int argc, char * argv[])
1633 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1634 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1639 for (i = 1; i < argc; i++) {
1640 if (!stricmp(argv[i],"--validate-cache")) {
1641 if (++i != argc - 1) {
1646 return cm_ValidateMappedMemory(argv[i]);
1653 if (!StartServiceCtrlDispatcher(dispatchTable))
1655 LONG status = GetLastError();
1656 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1660 bRunningAsService = FALSE;
1662 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1664 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1666 SetEvent(WaitToTerminate);
1670 if ( hAFSDMainThread ) {
1671 WaitForSingleObject( hAFSDMainThread, INFINITE );
1672 CloseHandle( hAFSDMainThread );