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 = ERROR_EXCEPTION_IN_SERVICE;
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 */
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 &&
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) {
341 switch((int) dwEventType)
343 case PBT_APMQUERYSUSPEND:
344 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
345 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSUSPEND");
346 /* Write all dirty buffers back to server */
349 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
350 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
353 case PBT_APMQUERYSTANDBY:
354 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
355 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSTANDBY");
356 /* Write all dirty buffers back to server */
359 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
360 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
364 /* allow remaining case PBT_WhatEver */
366 afsi_log("SERVICE_CONTROL_APMSUSPEND");
367 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSUSPEND");
368 if (!powerStateSuspended) {
369 powerStateSuspended = 1;
370 if (osVersion.dwMajorVersion >= 6)
371 smb_StopListeners(0);
378 afsi_log("SERVICE_CONTROL_APMSUSPEND complete");
379 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSUSPEND complete");
382 afsi_log("SERVICE_CONTROL_APMSTANDBY");
383 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSTANDBY");
384 if (!powerStateSuspended) {
385 powerStateSuspended = 1;
386 if (osVersion.dwMajorVersion >= 6)
387 smb_StopListeners(0);
393 afsi_log("SERVICE_CONTROL_APMSTANDBY complete");
394 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSTANDBY complete");
396 case PBT_APMRESUMECRITICAL:
397 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
398 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMECRITICAL");
399 if (powerStateSuspended) {
400 powerStateSuspended = 0;
401 if (osVersion.dwMajorVersion >= 6)
402 smb_RestartListeners(0);
403 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS
404 | CM_FLAG_CHECKUPSERVERS, NULL);
409 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL complete");
410 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMECRITICAL complete");
412 case PBT_APMRESUMESUSPEND:
413 /* User logged in after suspend */
414 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
415 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESUSPEND");
416 if (powerStateSuspended) {
417 powerStateSuspended = 0;
418 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS
419 | CM_FLAG_CHECKUPSERVERS, NULL);
420 if (osVersion.dwMajorVersion >= 6)
421 smb_RestartListeners(0);
422 if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
423 smb_SetLanAdapterChangeDetected();
429 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND complete");
430 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESUSPEND complete");
432 case PBT_APMRESUMESTANDBY:
433 /* User logged in after standby */
434 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
435 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESTANDBY");
436 if (powerStateSuspended) {
437 powerStateSuspended = 0;
438 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS
439 | CM_FLAG_CHECKUPSERVERS, NULL);
440 if (osVersion.dwMajorVersion >= 6)
441 smb_RestartListeners(0);
442 if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
443 smb_SetLanAdapterChangeDetected();
449 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY complete");
450 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESTANDBY complete");
452 case PBT_APMBATTERYLOW:
453 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
454 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMBATTERYLOW");
457 case PBT_APMPOWERSTATUSCHANGE:
459 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
461 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
464 case PBT_APMOEMEVENT:
466 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
468 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMOEMEVENT");
471 case PBT_APMRESUMEAUTOMATIC:
472 /* This is the message delivered once all devices are up */
473 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
474 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMEAUTOMATIC");
475 if (powerStateSuspended) {
476 powerStateSuspended = 0;
477 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS
478 | CM_FLAG_CHECKUPSERVERS, NULL);
479 if (osVersion.dwMajorVersion >= 6)
480 smb_RestartListeners(0);
481 if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
482 smb_SetLanAdapterChangeDetected();
488 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC complete");
489 osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMEAUTOMATIC complete");
492 afsi_log("SERVICE_CONTROL_unknown");
493 osi_Log1(afsd_logp, "SERVICE_CONTROL_unknown: 0x%x", dwEventType);
499 case SERVICE_CONTROL_CUSTOM_DUMP:
501 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
502 GenerateMiniDump(NULL);
506 } /* end switch(ctrlCode) */
510 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
512 * Mount a drive into AFS if there global mapping
514 /* DEE Could check first if we are run as SYSTEM */
515 #define MAX_RETRIES 10
516 #define MAX_DRIVES 23
517 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
519 char szAfsPath[_MAX_PATH];
520 char szDriveToMapTo[5];
524 DWORD dwIndex = 0, dwRetry = 0;
526 DWORD dwSubMountSize;
527 char szSubMount[256];
530 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
532 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
533 if (dwResult != ERROR_SUCCESS)
536 while (dwIndex < MAX_DRIVES) {
537 dwDriveSize = sizeof(szDriveToMapTo);
538 dwSubMountSize = sizeof(szSubMount);
539 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
540 if (dwResult != ERROR_MORE_DATA) {
541 if (dwResult != ERROR_SUCCESS) {
542 if (dwResult != ERROR_NO_MORE_ITEMS)
543 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
548 for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
551 memset (&nr, 0x00, sizeof(NETRESOURCE));
553 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
555 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
556 nr.dwType=RESOURCETYPE_DISK;
557 nr.lpLocalName=strlen(szDriveToMapTo) > 0 ? szDriveToMapTo : NULL;
558 nr.lpRemoteName=szAfsPath;
559 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
560 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
562 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
563 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
564 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
565 if (dwResult == NO_ERROR) {
568 /* wait for smb server to come up */
569 Sleep((DWORD)1000 /* miliseconds */);
571 /* Disconnect any previous mappings */
572 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
580 static HANDLE hThreadMountGlobalDrives = NULL;
582 static void MountGlobalDrives()
586 hThreadMountGlobalDrives = CreateThread(NULL, 0, MountGlobalDrivesThread, 0, 0, &tid);
588 if ( hThreadMountGlobalDrives ) {
589 DWORD rc = WaitForSingleObject( hThreadMountGlobalDrives, 15000 );
590 if (rc == WAIT_TIMEOUT) {
591 afsi_log("GlobalAutoMap thread failed to complete after 15 seconds");
592 } else if (rc == WAIT_OBJECT_0) {
593 afsi_log("GlobalAutoMap thread completed");
594 CloseHandle( hThreadMountGlobalDrives );
595 hThreadMountGlobalDrives = NULL;
600 static void DismountGlobalDrives()
602 char szAfsPath[_MAX_PATH];
603 char szDriveToMapTo[5];
605 DWORD dwSubMountSize;
606 char szSubMount[256];
613 if ( hThreadMountGlobalDrives ) {
614 DWORD rc = WaitForSingleObject(hThreadMountGlobalDrives, 0);
616 if (rc == WAIT_TIMEOUT) {
617 afsi_log("GlobalAutoMap thread failed to complete before service shutdown");
619 else if (rc == WAIT_OBJECT_0) {
620 afsi_log("GlobalAutoMap thread completed");
621 CloseHandle( hThreadMountGlobalDrives );
622 hThreadMountGlobalDrives = NULL;
626 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
628 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
629 if (dwResult != ERROR_SUCCESS)
632 while (dwIndex < MAX_DRIVES) {
633 dwDriveSize = sizeof(szDriveToMapTo);
634 dwSubMountSize = sizeof(szSubMount);
635 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
636 if (dwResult != ERROR_MORE_DATA) {
637 if (dwResult != ERROR_SUCCESS) {
638 if (dwResult != ERROR_NO_MORE_ITEMS)
639 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
644 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
646 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
647 dwResult = WNetCancelConnection(szAfsPath, TRUE);
649 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
656 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
658 DWORD dwVersionHandle;
659 LPVOID pVersionInfo = 0;
661 LPDWORD pLangInfo = 0;
662 LPTSTR szVersion = 0;
664 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
665 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
668 afsi_log("GetFileVersionInfoSize(%s) failed", filename);
669 return GetLastError();
672 pVersionInfo = malloc(size);
674 afsi_log("out of memory 1");
675 return ERROR_NOT_ENOUGH_MEMORY;
678 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
679 if (retval = GetLastError())
681 afsi_log("GetFileVersionInfo failed: %d", retval);
685 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
686 (LPVOID*)&pLangInfo, &len);
687 if (retval = GetLastError())
689 afsi_log("VerQueryValue 1 failed: %d", retval);
694 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
695 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
697 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
698 if (retval = GetLastError())
700 /* try again with language 409 since the old binaries were tagged wrong */
702 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
705 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
706 if (retval = GetLastError()) {
707 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
711 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
712 szOutput[dwOutput - 1] = 0;
721 static HINSTANCE hCrypt32;
722 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
723 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
724 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
725 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
726 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
727 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
728 HCRYPTMSG* phMsg, const void** ppvContext);
729 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
730 void* pvData, DWORD* pcbData);
731 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
732 DWORD dwFindFlags, DWORD dwFindType,
733 const void* pvFindPara,
734 PCCERT_CONTEXT pPrevCertContext);
735 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
736 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
737 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
738 PCERT_INFO pCertId2);
739 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
741 void LoadCrypt32(void)
743 hCrypt32 = LoadLibrary("crypt32");
747 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
748 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
749 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
750 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
751 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
752 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
753 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
754 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
756 if ( !pCertGetNameString ||
757 !pCryptQueryObject ||
758 !pCryptMsgGetParam ||
759 !pCertFindCertificateInStore ||
762 !pCertCompareCertificate ||
763 !pCertFreeCertificateContext)
765 FreeLibrary(hCrypt32);
770 void UnloadCrypt32(void)
772 FreeLibrary(hCrypt32);
775 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
777 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
779 wchar_t wfilename[260];
785 HCERTSTORE hStore = NULL;
786 HCRYPTMSG hMsg = NULL;
787 PCMSG_SIGNER_INFO pSignerInfo = NULL;
788 PCCERT_CONTEXT pCertContext = NULL;
791 if ( hCrypt32 == NULL )
794 ZeroMemory(&CertInfo, sizeof(CertInfo));
795 mbstowcs(wfilename, filename, 260);
797 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
799 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
800 CERT_QUERY_FORMAT_FLAG_BINARY,
810 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
816 fResult = pCryptMsgGetParam(hMsg,
817 CMSG_SIGNER_INFO_PARAM,
823 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
829 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
831 fResult = pCryptMsgGetParam(hMsg,
832 CMSG_SIGNER_INFO_PARAM,
838 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
844 CertInfo.Issuer = pSignerInfo->Issuer;
845 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
847 pCertContext = pCertFindCertificateInStore(hStore,
850 CERT_FIND_SUBJECT_CERT,
855 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
863 LocalFree(pSignerInfo);
866 CertFreeCertificateContext(pCertContext);*/
869 pCertCloseStore(hStore,0);
872 pCryptMsgClose(hMsg);
877 BOOL VerifyTrust(CHAR * filename)
879 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
880 WIN_TRUST_SUBJECT_FILE fSubjectFile;
881 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
882 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
883 wchar_t wfilename[260];
885 BOOL success = FALSE;
887 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
890 if (filename == NULL )
893 hWinTrust = LoadLibrary("wintrust");
897 if (((FARPROC) pWinVerifyTrust =
898 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
900 FreeLibrary(hWinTrust);
904 mbstowcs(wfilename, filename, 260);
906 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
908 fSubjectFile.lpPath = wfilename;
909 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
910 FALSE, GetCurrentProcessId());
911 fContextWSubject.SubjectType = &subject;
912 fContextWSubject.Subject = &fSubjectFile;
914 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
916 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
917 CloseHandle( fSubjectFile.hFile );
918 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
919 CloseHandle( fContextWSubject.hClientToken );
921 if (ret == ERROR_SUCCESS) {
924 DWORD gle = GetLastError();
926 case TRUST_E_PROVIDER_UNKNOWN:
927 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
929 case TRUST_E_NOSIGNATURE:
930 afsi_log("VerifyTrust failed: Unsigned executable");
932 case TRUST_E_EXPLICIT_DISTRUST:
933 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
935 case TRUST_E_SUBJECT_NOT_TRUSTED:
936 afsi_log("VerifyTrust failed: File is not trusted");
938 case TRUST_E_BAD_DIGEST:
939 afsi_log("VerifyTrust failed: Executable has been modified");
941 case CRYPT_E_SECURITY_SETTINGS:
942 afsi_log("VerifyTrust failed: local security options prevent verification");
945 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
949 FreeLibrary(hWinTrust);
953 void LogCertCtx(PCCERT_CONTEXT pCtx) {
955 LPTSTR szName = NULL;
957 if ( hCrypt32 == NULL )
960 // Get Issuer name size.
961 if (!(dwData = pCertGetNameString(pCtx,
962 CERT_NAME_SIMPLE_DISPLAY_TYPE,
963 CERT_NAME_ISSUER_FLAG,
967 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
971 // Allocate memory for Issuer name.
972 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
975 if (!(pCertGetNameString(pCtx,
976 CERT_NAME_SIMPLE_DISPLAY_TYPE,
977 CERT_NAME_ISSUER_FLAG,
981 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
985 // print Issuer name.
986 afsi_log("Issuer Name: %s", szName);
990 // Get Subject name size.
991 if (!(dwData = pCertGetNameString(pCtx,
992 CERT_NAME_SIMPLE_DISPLAY_TYPE,
997 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
1001 // Allocate memory for subject name.
1002 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
1004 // Get subject name.
1005 if (!(pCertGetNameString(pCtx,
1006 CERT_NAME_SIMPLE_DISPLAY_TYPE,
1011 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
1015 // Print Subject Name.
1016 afsi_log("Subject Name: %s", szName);
1024 BOOL AFSModulesVerify(void)
1026 CHAR filename[1024];
1027 CHAR afsdVersion[128];
1028 CHAR modVersion[128];
1029 CHAR checkName[1024];
1030 BOOL trustVerified = FALSE;
1031 HMODULE hMods[1024];
1035 BOOL success = TRUE;
1036 PCCERT_CONTEXT pCtxService = NULL;
1038 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
1039 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
1040 DWORD dummyLen, code;
1041 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
1042 DWORD verifyServiceSig = TRUE;
1045 hPSAPI = LoadLibrary("psapi");
1047 if ( hPSAPI == NULL )
1050 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
1053 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
1056 afsi_log("%s version %s", filename, afsdVersion);
1058 if (((FARPROC) pGetModuleFileNameExA =
1059 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
1060 ((FARPROC) pEnumProcessModules =
1061 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
1063 FreeLibrary(hPSAPI);
1068 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1069 AFSREG_CLT_SVC_PARAM_SUBKEY,
1070 0, KEY_QUERY_VALUE, &parmKey);
1071 if (code == ERROR_SUCCESS) {
1072 dummyLen = sizeof(cacheSize);
1073 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
1074 (BYTE *) &cacheSize, &dummyLen);
1075 RegCloseKey (parmKey);
1078 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
1079 0, KEY_QUERY_VALUE, &parmKey);
1080 if (code == ERROR_SUCCESS) {
1081 dummyLen = sizeof(verifyServiceSig);
1082 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
1083 (BYTE *) &verifyServiceSig, &dummyLen);
1084 RegCloseKey (parmKey);
1087 if (verifyServiceSig
1089 && cacheSize < 716800
1092 trustVerified = VerifyTrust(filename);
1094 afsi_log("Signature Verification disabled");
1097 if (trustVerified) {
1100 // get a certificate context for the signer of afsd_service.
1101 pCtxService = GetCertCtx(filename);
1103 LogCertCtx(pCtxService);
1106 // Get a list of all the modules in this process.
1107 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
1108 FALSE, GetCurrentProcessId());
1110 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
1112 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
1114 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
1116 char szModName[2048];
1118 // Get the full path to the module's file.
1119 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
1121 lstrcpy(checkName, szModName);
1124 if ( strstr(checkName, "afspthread.dll") ||
1125 strstr(checkName, "afsauthent.dll") ||
1126 strstr(checkName, "afsrpc.dll") ||
1127 strstr(checkName, "libafsconf.dll") ||
1128 strstr(checkName, "libosi.dll") )
1130 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1135 afsi_log("%s version %s", szModName, modVersion);
1136 if (strcmp(afsdVersion,modVersion)) {
1137 afsi_log("Version mismatch: %s", szModName);
1140 if ( trustVerified ) {
1141 if ( !VerifyTrust(szModName) ) {
1142 afsi_log("Signature Verification failed: %s", szModName);
1145 else if (pCtxService) {
1146 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1148 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1149 pCtxService->pCertInfo,
1151 afsi_log("Certificate mismatch: %s", szModName);
1159 pCertFreeCertificateContext(pCtx);
1168 pCertFreeCertificateContext(pCtxService);
1172 FreeLibrary(hPSAPI);
1174 CloseHandle(hProcess);
1179 * Add or remove the specified service from the Network Provider "Order" value
1182 * str : target string
1183 * str2: string to add/remove
1184 * bInst: == 1 if string should be added to target if not already there, otherwise remove string from target if present.
1185 * if before != NULL, add string before
1197 npi_CheckAndAddRemove(char *str, const char *str2, int bInst,
1200 char *target = NULL;
1201 char *charset = NULL;
1202 char *match, *bmatch;
1204 enum INP_ERR rv = inp_err_error;
1206 code = asprintf(&target, ",%s,", str);
1210 code = asprintf(&charset, ",%s,", str2);
1214 match = strstr(target, charset);
1215 if (match && bInst) {
1216 if (before != NULL) {
1217 bmatch = strstr(target, before);
1218 if (bmatch == NULL || bmatch > match) {
1219 rv = inp_err_present;
1223 strcpy(str+(match-target), match + strlen(str2) + 2);
1224 str[strlen(str)-1] = '\0';
1227 rv = inp_err_present;
1232 if (match == NULL && !bInst) {
1233 rv = inp_err_absent;
1237 if (before == NULL || (bmatch = strstr(str, before)) == NULL) {
1238 /* append to list */
1242 /* insert before str2 */
1243 size_t s2len = strlen(str2);
1244 memmove(bmatch + s2len + 1, bmatch, strlen(bmatch) + 1);
1245 memcpy(bmatch, str2, s2len);
1246 bmatch[s2len] = ',';
1252 /* remove from list */
1253 strcpy(str + (match-target), match + strlen(str2) + 2);
1254 str[strlen(str)-1] = '\0';
1255 rv = inp_err_removed;
1266 InstNetProvider(const char *svcname, int bInst, const char *before)
1268 const char *strOrder = NULL;
1269 HKEY hkOrder = NULL;
1274 rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_NP_ORDER, 0,
1275 KEY_READ | KEY_WRITE, &hkOrder);
1276 if (rv != ERROR_SUCCESS)
1280 rv = RegQueryValueEx(hkOrder, AFSREG_NP_ORDER_VALUE,
1281 NULL, NULL, NULL, &dwSize);
1282 if (rv != ERROR_SUCCESS)
1285 strOrder = malloc(dwSize + 2 + strlen(svcname));
1287 rv = RegQueryValueEx(hkOrder, AFSREG_NP_ORDER_VALUE,
1288 NULL, NULL, (LPBYTE) strOrder, &dwSize);
1289 if (rv != ERROR_SUCCESS)
1292 switch(npi_CheckAndAddRemove(strOrder, svcname , bInst, before)) {
1294 case inp_err_removed:
1295 dwSize = strlen(strOrder) + 1;
1296 rv = RegSetValueEx(hkOrder, AFSREG_NP_ORDER_VALUE, 0, REG_SZ,
1303 RegCloseKey(hkOrder);
1309 clientServiceProviderKeyExists(void)
1314 rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1315 AFSREG_CLT_SVC_PROVIDER_KEY, 0,
1317 if (rv == ERROR_SUCCESS)
1320 return (rv == ERROR_SUCCESS);
1324 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1327 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1328 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1330 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1331 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1334 afsd_Main(DWORD argc, LPTSTR *argv)
1346 void afsd_DbgBreakAllocInit();
1348 afsd_DbgBreakAllocInit();
1349 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1350 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1353 afsd_SetUnhandledExceptionFilter();
1355 osi_InitPanic(afsd_notifier);
1356 osi_InitTraceOption();
1358 hKernel32 = LoadLibrary("kernel32.dll");
1359 if (hKernel32 == NULL)
1361 afsi_log("Fatal: cannot load kernel32.dll");
1364 pRtlCaptureContext = GetProcAddress(hKernel32, "RtlCaptureContext");
1370 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1371 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1372 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1375 hAdvApi32 = LoadLibrary("advapi32.dll");
1376 if (hAdvApi32 == NULL)
1378 afsi_log("Fatal: cannot load advapi32.dll");
1382 if (bRunningAsService) {
1383 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1384 if (pRegisterServiceCtrlHandlerEx)
1386 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1387 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1391 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1394 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1395 ServiceStatus.dwServiceSpecificExitCode = 0;
1396 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1397 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1398 ServiceStatus.dwCheckPoint = 1;
1399 ServiceStatus.dwWaitHint = 120000;
1400 /* accept Power Events */
1401 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1402 SetServiceStatus(StatusHandle, &ServiceStatus);
1406 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
1408 #ifdef REGISTER_POWER_NOTIFICATIONS
1415 /* see if we should handle power notifications */
1416 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1417 0, KEY_QUERY_VALUE, &hkParm);
1418 if (code == ERROR_SUCCESS) {
1419 dummyLen = sizeof(bpower);
1420 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1421 (BYTE *) &bpower, &dummyLen);
1423 if(code != ERROR_SUCCESS)
1426 RegCloseKey(hkParm);
1428 /* create thread used to flush cache */
1430 PowerNotificationThreadCreate();
1431 powerEventsRegistered = 1;
1436 /* Verify the versions of the DLLs which were loaded */
1437 if (!AFSModulesVerify()) {
1438 if (bRunningAsService) {
1439 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1440 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1441 ServiceStatus.dwCheckPoint = 0;
1442 ServiceStatus.dwWaitHint = 0;
1443 ServiceStatus.dwControlsAccepted = 0;
1444 SetServiceStatus(StatusHandle, &ServiceStatus);
1446 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
1448 /* exit if initialization failed */
1452 /* allow an exit to be called prior to any initialization */
1453 hHookDll = cm_LoadAfsdHookLib();
1457 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1460 hookRc = initHook();
1462 FreeLibrary(hHookDll);
1465 if (hookRc == FALSE)
1467 if (bRunningAsService) {
1468 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1469 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1470 ServiceStatus.dwCheckPoint = 0;
1471 ServiceStatus.dwWaitHint = 0;
1472 ServiceStatus.dwControlsAccepted = 0;
1473 SetServiceStatus(StatusHandle, &ServiceStatus);
1475 /* exit if initialization failed */
1480 /* allow another 120 seconds to start */
1481 if (bRunningAsService) {
1482 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1483 ServiceStatus.dwServiceSpecificExitCode = 0;
1484 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1485 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1486 ServiceStatus.dwCheckPoint = 2;
1487 ServiceStatus.dwWaitHint = 120000;
1488 /* accept Power Events */
1489 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1490 SetServiceStatus(StatusHandle, &ServiceStatus);
1495 /* Perform Volume Status Notification Initialization */
1496 cm_VolStatus_Initialization();
1499 MainThreadId = GetCurrentThreadId();
1500 jmpret = setjmp(notifier_jmp);
1505 code = afsd_InitCM(&reason);
1507 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1508 osi_panic(reason, __FILE__, __LINE__);
1512 if (bRunningAsService) {
1513 ServiceStatus.dwCheckPoint = 3;
1514 ServiceStatus.dwWaitHint = 30000;
1515 SetServiceStatus(StatusHandle, &ServiceStatus);
1518 /* allow an exit to be called post rx initialization */
1519 hHookDll = cm_LoadAfsdHookLib();
1523 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1526 hookRc = rxStartedHook();
1528 FreeLibrary(hHookDll);
1531 if (hookRc == FALSE)
1533 if (bRunningAsService) {
1534 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1535 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1536 ServiceStatus.dwCheckPoint = 0;
1537 ServiceStatus.dwWaitHint = 0;
1538 ServiceStatus.dwControlsAccepted = 0;
1539 SetServiceStatus(StatusHandle, &ServiceStatus);
1541 /* exit if initialization failed */
1547 if (bRunningAsService) {
1548 ServiceStatus.dwCheckPoint = 4;
1549 ServiceStatus.dwWaitHint = 15000;
1550 SetServiceStatus(StatusHandle, &ServiceStatus);
1554 /* Notify any volume status handlers that the cache manager has started */
1555 cm_VolStatus_Service_Started();
1557 code = RDR_Initialize();
1558 if ( code == ERROR_SERVICE_DISABLED) {
1559 afsi_log("RDR_Initialize failed: 1058 (Unable to load AFSRedirLib.sys)");
1560 osi_panic(reason, __FILE__, __LINE__);
1562 RDR_Initialized = !code;
1563 afsi_log("RDR_Initialize returned: (code = %d)", code);
1566 if (RDR_Initialized) {
1567 if (cm_sysNameCount)
1568 RDR_SysName( AFS_SYSNAME_ARCH_32BIT, cm_sysNameCount, cm_sysNameList );
1570 if (cm_sysName64Count)
1571 RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysName64Count, cm_sysName64List );
1572 else if (cm_sysNameCount)
1573 RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysNameCount, cm_sysNameList );
1576 InstNetProvider("AFSRedirector", TRUE, "LanmanWorkstation");
1578 InstNetProvider("AFSRedirector", FALSE, NULL);
1581 InstNetProvider("TransarcAFSDaemon", clientServiceProviderKeyExists(),
1585 * Set the default for the SMB interface based upon the state of the
1586 * Redirector interface.
1588 smb_Enabled = !RDR_Initialized;
1590 code = afsd_InitSMB(&reason, MessageBox);
1591 if (smb_Enabled && code != 0) {
1592 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1593 osi_panic(reason, __FILE__, __LINE__);
1596 if (!smb_Enabled && !RDR_Initialized) {
1597 afsi_log("Neither RDR nor SMB interfaces available");
1598 osi_panic(reason, __FILE__, __LINE__);
1601 /* allow an exit to be called post smb initialization */
1602 hHookDll = cm_LoadAfsdHookLib();
1606 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1609 hookRc = smbStartedHook();
1611 FreeLibrary(hHookDll);
1614 if (hookRc == FALSE)
1616 if (bRunningAsService) {
1617 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1618 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1619 ServiceStatus.dwCheckPoint = 0;
1620 ServiceStatus.dwWaitHint = 0;
1621 ServiceStatus.dwControlsAccepted = 0;
1622 SetServiceStatus(StatusHandle, &ServiceStatus);
1624 /* exit if initialization failed */
1629 MountGlobalDrives();
1631 code = afsd_InitDaemons(&reason);
1633 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1634 osi_panic(reason, __FILE__, __LINE__);
1638 if (bRunningAsService) {
1639 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1640 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1641 ServiceStatus.dwCheckPoint = 5;
1642 ServiceStatus.dwWaitHint = 0;
1644 /* accept Power events */
1645 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1646 SetServiceStatus(StatusHandle, &ServiceStatus);
1650 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
1653 /* allow an exit to be called when started */
1654 hHookDll = cm_LoadAfsdHookLib();
1658 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1661 hookRc = startedHook();
1663 FreeLibrary(hHookDll);
1666 if (hookRc == FALSE)
1668 if (bRunningAsService) {
1669 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1670 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1671 ServiceStatus.dwCheckPoint = 0;
1672 ServiceStatus.dwWaitHint = 0;
1673 ServiceStatus.dwControlsAccepted = 0;
1674 SetServiceStatus(StatusHandle, &ServiceStatus);
1676 /* exit if initialization failed */
1681 WaitForSingleObject(WaitToTerminate, INFINITE);
1683 if (bRunningAsService) {
1684 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
1685 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1686 ServiceStatus.dwCheckPoint = 6;
1687 ServiceStatus.dwWaitHint = 120000;
1688 ServiceStatus.dwControlsAccepted = 0;
1689 SetServiceStatus(StatusHandle, &ServiceStatus);
1691 afsi_log("Received Termination Signal, Stopping Service");
1694 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP);
1696 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
1698 /* allow an exit to be called prior to stopping the service */
1699 hHookDll = cm_LoadAfsdHookLib();
1703 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1706 hookRc = stoppingHook();
1708 FreeLibrary(hHookDll);
1713 #ifdef AFS_FREELANCE_CLIENT
1714 cm_FreelanceShutdown();
1715 afsi_log("Freelance Shutdown complete");
1718 DismountGlobalDrives();
1719 afsi_log("Global Drives dismounted");
1721 if (RDR_Initialized) {
1722 RDR_ShutdownNotify();
1723 cm_VolStatus_SetRDRNotifications(FALSE);
1724 afsi_log("RDR notified of shutdown");
1728 afsi_log("smb shutdown complete");
1730 cm_ReleaseAllLocks();
1732 cm_DaemonShutdown();
1733 afsi_log("Daemon shutdown complete");
1736 afsi_log("Buffer shutdown complete");
1742 cm_ShutdownMappedMemory();
1744 if (RDR_Initialized) {
1745 RDR_ShutdownFinal();
1746 afsi_log("RDR shutdown complete");
1750 afsi_log("rx finalization complete");
1752 #ifdef REGISTER_POWER_NOTIFICATIONS
1753 /* terminate thread used to flush cache */
1754 if (powerEventsRegistered)
1755 PowerNotificationThreadExit();
1760 cm_BPlusDumpStats();
1763 /* Notify any Volume Status Handlers that we are stopped */
1764 cm_VolStatus_Service_Stopped();
1766 /* Cleanup any Volume Status Notification Handler */
1767 cm_VolStatus_Finalize();
1769 /* allow an exit to be called after stopping the service */
1770 hHookDll = cm_LoadAfsdHookLib();
1774 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1777 hookRc = stoppedHook();
1779 FreeLibrary(hHookDll);
1783 /* Remove the ExceptionFilter */
1784 SetUnhandledExceptionFilter(NULL);
1786 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPED);
1788 if (bRunningAsService) {
1789 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1790 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1791 ServiceStatus.dwCheckPoint = 7;
1792 ServiceStatus.dwWaitHint = 0;
1793 ServiceStatus.dwControlsAccepted = 0;
1794 SetServiceStatus(StatusHandle, &ServiceStatus);
1798 DWORD __stdcall afsdMain_thread(void* notUsed)
1800 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1801 afsd_Main(1, (LPTSTR*)argv);
1807 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1811 main(int argc, char * argv[])
1813 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1814 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1819 for (i = 1; i < argc; i++) {
1820 if (!stricmp(argv[i],"--validate-cache")) {
1821 if (++i != argc - 1) {
1826 return cm_ValidateMappedMemory(argv[i]);
1833 if (!StartServiceCtrlDispatcher(dispatchTable))
1835 LONG status = GetLastError();
1836 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1840 bRunningAsService = FALSE;
1842 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1844 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1846 SetEvent(WaitToTerminate);
1850 if ( hAFSDMainThread ) {
1851 WaitForSingleObject( hAFSDMainThread, INFINITE );
1852 CloseHandle( hAFSDMainThread );