11 #include "afsd_init.h"
15 #include <WINNT\afsreg.h>
27 //#define REGISTER_POWER_NOTIFICATIONS 1
28 #include "afsd_flushvol.h"
30 extern void afsi_log(char *pattern, ...);
32 static SERVICE_STATUS ServiceStatus;
33 static SERVICE_STATUS_HANDLE StatusHandle;
35 HANDLE hAFSDMainThread = NULL;
37 HANDLE hAFSDWorkerThread[WORKER_THREADS];
40 HANDLE WaitToTerminate;
45 unsigned int MainThreadId;
49 extern int traceOnPanic;
50 extern HANDLE afsi_file;
52 int powerEventsRegistered = 0;
55 * Notifier function for use by osi_panic
57 static void afsd_notifier(char *msgp, char *filep, long line)
64 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION,
67 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG, msgp);
71 osi_LogEnable(afsd_logp);
73 afsd_ForceTrace(TRUE);
76 afsi_log("--- begin dump ---");
77 cm_DumpSCache(afsi_file, "a", 0);
79 cm_dnlcDump(afsi_file, "a");
81 cm_DumpBufHashTable(afsi_file, "a", 0);
82 smb_DumpVCP(afsi_file, "a", 0);
83 afsi_log("--- end dump ---");
89 SetEvent(WaitToTerminate);
91 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
92 for (i = 0; i < WORKER_THREADS; i++)
93 CloseHandle(hAFSDWorkerThread[i]);
97 if (GetCurrentThreadId() == MainThreadId)
98 longjmp(notifier_jmp, 1);
101 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
102 ServiceStatus.dwWin32ExitCode = NO_ERROR;
103 ServiceStatus.dwCheckPoint = 0;
104 ServiceStatus.dwWaitHint = 0;
105 ServiceStatus.dwControlsAccepted = 0;
106 SetServiceStatus(StatusHandle, &ServiceStatus);
112 * For use miscellaneously in smb.c; need to do better
114 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
120 afsd_ServiceFlushVolume(DWORD dwlpEventData)
122 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
125 ** If UI bit is not set, user interaction is not possible
126 ** BUT, since we are a NON-interactive service, and therefore
127 ** have NO user I/O, it doesn't much matter.
128 ** This benign code left here as example of how to find this out
130 BOOL bUI = (dwlpEventData & 1);
133 if ( PowerNotificationThreadNotify() )
139 /* flush was unsuccessful, or timeout - deny shutdown */
140 dwRet = ERROR_NETWORK_BUSY;
143 /* to deny hibernate, simply return
144 // any value besides NO_ERROR.
146 // dwRet = ERROR_NETWORK_BUSY;
153 /* service control handler used in nt4 only for backward compat. */
155 afsd_ServiceControlHandler(DWORD ctrlCode)
158 DWORD dummyLen, doTrace;
162 case SERVICE_CONTROL_SHUTDOWN:
163 case SERVICE_CONTROL_STOP:
164 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
165 ServiceStatus.dwWin32ExitCode = NO_ERROR;
166 ServiceStatus.dwCheckPoint = 1;
167 ServiceStatus.dwWaitHint = 30000;
168 ServiceStatus.dwControlsAccepted = 0;
169 SetServiceStatus(StatusHandle, &ServiceStatus);
171 if (ctrlCode == SERVICE_CONTROL_STOP)
172 afsi_log("SERVICE_CONTROL_STOP");
174 afsi_log("SERVICE_CONTROL_SHUTDOWN");
176 /* Write all dirty buffers back to server */
179 /* Force trace if requested */
180 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
181 AFSREG_CLT_SVC_PARAM_SUBKEY,
182 0, KEY_QUERY_VALUE, &parmKey);
183 if (code != ERROR_SUCCESS)
186 dummyLen = sizeof(doTrace);
187 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
189 (BYTE *) &doTrace, &dummyLen);
190 RegCloseKey (parmKey);
191 if (code != ERROR_SUCCESS)
194 afsd_ForceTrace(FALSE);
195 buf_ForceTrace(FALSE);
199 SetEvent(WaitToTerminate);
202 case SERVICE_CONTROL_INTERROGATE:
203 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
204 ServiceStatus.dwWin32ExitCode = NO_ERROR;
205 ServiceStatus.dwCheckPoint = 0;
206 ServiceStatus.dwWaitHint = 0;
207 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
208 SetServiceStatus(StatusHandle, &ServiceStatus);
210 /* XXX handle system shutdown */
211 /* XXX handle pause & continue */
217 ** Extended ServiceControlHandler that provides Event types
218 ** for monitoring Power events, for example.
221 afsd_ServiceControlHandlerEx(
229 DWORD dummyLen, doTrace;
231 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
235 case SERVICE_CONTROL_SHUTDOWN:
236 case SERVICE_CONTROL_STOP:
237 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
238 ServiceStatus.dwWin32ExitCode = NO_ERROR;
239 ServiceStatus.dwCheckPoint = 1;
240 ServiceStatus.dwWaitHint = 30000;
241 ServiceStatus.dwControlsAccepted = 0;
242 SetServiceStatus(StatusHandle, &ServiceStatus);
244 /* Write all dirty buffers back to server */
247 /* Force trace if requested */
248 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
249 AFSREG_CLT_SVC_PARAM_SUBKEY,
250 0, KEY_QUERY_VALUE, &parmKey);
251 if (code != ERROR_SUCCESS)
254 dummyLen = sizeof(doTrace);
255 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
257 (BYTE *) &doTrace, &dummyLen);
258 RegCloseKey (parmKey);
259 if (code != ERROR_SUCCESS)
262 afsd_ForceTrace(FALSE);
263 buf_ForceTrace(FALSE);
267 SetEvent(WaitToTerminate);
271 case SERVICE_CONTROL_INTERROGATE:
272 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
273 ServiceStatus.dwWin32ExitCode = NO_ERROR;
274 ServiceStatus.dwCheckPoint = 0;
275 ServiceStatus.dwWaitHint = 0;
276 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
277 SetServiceStatus(StatusHandle, &ServiceStatus);
278 afsi_log("SERVICE_CONTROL_INTERROGATE");
282 /* XXX handle system shutdown */
283 /* XXX handle pause & continue */
284 case SERVICE_CONTROL_POWEREVENT:
287 afsi_log("SERVICE_CONTROL_POWEREVENT");
290 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
291 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
292 ** Return any error code to deny request,
293 ** i.e. as if returning BROADCAST_QUERY_DENY
295 if (powerEventsRegistered) {
296 switch((int) dwEventType)
298 case PBT_APMQUERYSUSPEND:
299 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
300 /* Write all dirty buffers back to server */
304 case PBT_APMQUERYSTANDBY:
305 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
306 /* Write all dirty buffers back to server */
311 /* allow remaining case PBT_WhatEver */
313 afsi_log("SERVICE_CONTROL_APMSUSPEND");
317 afsi_log("SERVICE_CONTROL_APMSTANDBY");
320 case PBT_APMRESUMECRITICAL:
321 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
324 case PBT_APMRESUMESUSPEND:
325 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
328 case PBT_APMRESUMESTANDBY:
329 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
332 case PBT_APMBATTERYLOW:
333 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
336 case PBT_APMPOWERSTATUSCHANGE:
338 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
342 case PBT_APMOEMEVENT:
344 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
348 case PBT_APMRESUMEAUTOMATIC:
349 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
353 afsi_log("SERVICE_CONTROL_unknown");
359 case SERVICE_CONTROL_CUSTOM_DUMP:
361 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
362 GenerateMiniDump(NULL);
366 } /* end switch(ctrlCode) */
370 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
372 * Mount a drive into AFS if there global mapping
374 /* DEE Could check first if we are run as SYSTEM */
375 #define MAX_RETRIES 10
376 #define MAX_DRIVES 23
377 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
380 char szAfsPath[_MAX_PATH];
382 char szDriveToMapTo[5];
386 DWORD dwIndex = 0, dwRetry = 0;
388 DWORD dwSubMountSize;
389 char szSubMount[256];
392 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
394 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
395 if (dwResult != ERROR_SUCCESS)
398 while (dwIndex < MAX_DRIVES) {
399 dwDriveSize = sizeof(szDriveToMapTo);
400 dwSubMountSize = sizeof(szSubMount);
401 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
402 if (dwResult != ERROR_MORE_DATA) {
403 if (dwResult != ERROR_SUCCESS) {
404 if (dwResult != ERROR_NO_MORE_ITEMS)
405 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
411 for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
414 memset (&nr, 0x00, sizeof(NETRESOURCE));
416 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
418 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
419 nr.dwType=RESOURCETYPE_DISK;
420 nr.lpLocalName=szDriveToMapTo;
421 nr.lpRemoteName=szAfsPath;
422 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
423 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
425 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
426 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
427 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
428 if (dwResult == NO_ERROR) {
431 /* wait for smb server to come up */
432 Sleep((DWORD)1000 /* miliseconds */);
434 /* Disconnect any previous mappings */
435 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
438 /* FIXFIX: implement */
439 afsi_log("GlobalAutoMap of %s to %s not implemented", szDriveToMapTo, szSubMount);
447 static HANDLE hThreadMountGlobalDrives = NULL;
449 static void MountGlobalDrives()
453 hThreadMountGlobalDrives = CreateThread(NULL, 0, MountGlobalDrivesThread, 0, 0, &tid);
455 if ( hThreadMountGlobalDrives ) {
456 DWORD rc = WaitForSingleObject( hThreadMountGlobalDrives, 15000 );
457 if (rc == WAIT_TIMEOUT) {
458 afsi_log("GlobalAutoMap thread failed to complete after 15 seconds");
459 } else if (rc == WAIT_OBJECT_0) {
460 afsi_log("GlobalAutoMap thread completed");
461 CloseHandle( hThreadMountGlobalDrives );
462 hThreadMountGlobalDrives = NULL;
467 static void DismountGlobalDrives()
470 char szAfsPath[_MAX_PATH];
471 char szDriveToMapTo[5];
473 DWORD dwSubMountSize;
474 char szSubMount[256];
482 if ( hThreadMountGlobalDrives ) {
483 DWORD rc = WaitForSingleObject(hThreadMountGlobalDrives, 0);
485 if (rc == WAIT_TIMEOUT) {
486 afsi_log("GlobalAutoMap thread failed to complete before service shutdown");
488 else if (rc == WAIT_OBJECT_0) {
489 afsi_log("GlobalAutoMap thread completed");
490 CloseHandle( hThreadMountGlobalDrives );
491 hThreadMountGlobalDrives = NULL;
495 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
497 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
498 if (dwResult != ERROR_SUCCESS)
502 /* FIXFIX: implement */
504 while (dwIndex < MAX_DRIVES) {
505 dwDriveSize = sizeof(szDriveToMapTo);
506 dwSubMountSize = sizeof(szSubMount);
507 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
508 if (dwResult != ERROR_MORE_DATA) {
509 if (dwResult != ERROR_SUCCESS) {
510 if (dwResult != ERROR_NO_MORE_ITEMS)
511 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
516 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
518 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
519 dwResult = WNetCancelConnection(szAfsPath, TRUE);
521 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
529 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
531 DWORD dwVersionHandle;
532 LPVOID pVersionInfo = 0;
534 LPDWORD pLangInfo = 0;
535 LPTSTR szVersion = 0;
537 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
538 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
541 afsi_log("GetFileVersionInfoSize failed");
542 return GetLastError();
545 pVersionInfo = malloc(size);
547 afsi_log("out of memory 1");
548 return ERROR_NOT_ENOUGH_MEMORY;
551 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
552 if (retval = GetLastError())
554 afsi_log("GetFileVersionInfo failed: %d", retval);
558 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
559 (LPVOID*)&pLangInfo, &len);
560 if (retval = GetLastError())
562 afsi_log("VerQueryValue 1 failed: %d", retval);
567 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
568 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
570 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
571 if (retval = GetLastError())
573 /* try again with language 409 since the old binaries were tagged wrong */
575 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
578 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
579 if (retval = GetLastError()) {
580 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
584 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
585 szOutput[dwOutput - 1] = 0;
594 static HINSTANCE hCrypt32;
595 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
596 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
597 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
598 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
599 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
600 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
601 HCRYPTMSG* phMsg, const void** ppvContext);
602 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
603 void* pvData, DWORD* pcbData);
604 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
605 DWORD dwFindFlags, DWORD dwFindType,
606 const void* pvFindPara,
607 PCCERT_CONTEXT pPrevCertContext);
608 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
609 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
610 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
611 PCERT_INFO pCertId2);
612 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
614 void LoadCrypt32(void)
616 hCrypt32 = LoadLibrary("crypt32");
620 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
621 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
622 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
623 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
624 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
625 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
626 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
627 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
629 if ( !pCertGetNameString ||
630 !pCryptQueryObject ||
631 !pCryptMsgGetParam ||
632 !pCertFindCertificateInStore ||
635 !pCertCompareCertificate ||
636 !pCertFreeCertificateContext)
638 FreeLibrary(hCrypt32);
643 void UnloadCrypt32(void)
645 FreeLibrary(hCrypt32);
648 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
650 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
652 wchar_t wfilename[260];
658 HCERTSTORE hStore = NULL;
659 HCRYPTMSG hMsg = NULL;
660 PCMSG_SIGNER_INFO pSignerInfo = NULL;
661 PCCERT_CONTEXT pCertContext = NULL;
664 if ( hCrypt32 == NULL )
667 ZeroMemory(&CertInfo, sizeof(CertInfo));
668 mbstowcs(wfilename, filename, 260);
670 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
672 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
673 CERT_QUERY_FORMAT_FLAG_BINARY,
683 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
689 fResult = pCryptMsgGetParam(hMsg,
690 CMSG_SIGNER_INFO_PARAM,
696 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
702 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
704 fResult = pCryptMsgGetParam(hMsg,
705 CMSG_SIGNER_INFO_PARAM,
711 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
717 CertInfo.Issuer = pSignerInfo->Issuer;
718 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
720 pCertContext = pCertFindCertificateInStore(hStore,
723 CERT_FIND_SUBJECT_CERT,
728 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
736 LocalFree(pSignerInfo);
739 CertFreeCertificateContext(pCertContext);*/
742 pCertCloseStore(hStore,0);
745 pCryptMsgClose(hMsg);
750 BOOL VerifyTrust(CHAR * filename)
752 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
753 WIN_TRUST_SUBJECT_FILE fSubjectFile;
754 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
755 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
756 wchar_t wfilename[260];
758 BOOL success = FALSE;
760 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
763 if (filename == NULL )
766 hWinTrust = LoadLibrary("wintrust");
770 if (((FARPROC) pWinVerifyTrust =
771 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
773 FreeLibrary(hWinTrust);
777 mbstowcs(wfilename, filename, 260);
779 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
781 fSubjectFile.lpPath = wfilename;
782 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
783 FALSE, GetCurrentProcessId());
784 fContextWSubject.SubjectType = &subject;
785 fContextWSubject.Subject = &fSubjectFile;
787 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
789 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
790 CloseHandle( fSubjectFile.hFile );
791 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
792 CloseHandle( fContextWSubject.hClientToken );
794 if (ret == ERROR_SUCCESS) {
797 DWORD gle = GetLastError();
799 case TRUST_E_PROVIDER_UNKNOWN:
800 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
802 case TRUST_E_NOSIGNATURE:
803 afsi_log("VerifyTrust failed: Unsigned executable");
805 case TRUST_E_EXPLICIT_DISTRUST:
806 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
808 case TRUST_E_SUBJECT_NOT_TRUSTED:
809 afsi_log("VerifyTrust failed: File is not trusted");
811 case TRUST_E_BAD_DIGEST:
812 afsi_log("VerifyTrust failed: Executable has been modified");
814 case CRYPT_E_SECURITY_SETTINGS:
815 afsi_log("VerifyTrust failed: local security options prevent verification");
818 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
822 FreeLibrary(hWinTrust);
826 void LogCertCtx(PCCERT_CONTEXT pCtx) {
828 LPTSTR szName = NULL;
830 if ( hCrypt32 == NULL )
833 // Get Issuer name size.
834 if (!(dwData = pCertGetNameString(pCtx,
835 CERT_NAME_SIMPLE_DISPLAY_TYPE,
836 CERT_NAME_ISSUER_FLAG,
840 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
844 // Allocate memory for Issuer name.
845 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
848 if (!(pCertGetNameString(pCtx,
849 CERT_NAME_SIMPLE_DISPLAY_TYPE,
850 CERT_NAME_ISSUER_FLAG,
854 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
858 // print Issuer name.
859 afsi_log("Issuer Name: %s", szName);
863 // Get Subject name size.
864 if (!(dwData = pCertGetNameString(pCtx,
865 CERT_NAME_SIMPLE_DISPLAY_TYPE,
870 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
874 // Allocate memory for subject name.
875 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
878 if (!(pCertGetNameString(pCtx,
879 CERT_NAME_SIMPLE_DISPLAY_TYPE,
884 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
888 // Print Subject Name.
889 afsi_log("Subject Name: %s", szName);
897 BOOL AFSModulesVerify(void)
900 CHAR afsdVersion[128];
901 CHAR modVersion[128];
902 CHAR checkName[1024];
903 BOOL trustVerified = FALSE;
909 PCCERT_CONTEXT pCtxService = NULL;
911 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
912 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
913 DWORD dummyLen, code;
914 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
915 DWORD verifyServiceSig = TRUE;
918 hPSAPI = LoadLibrary("psapi");
920 if ( hPSAPI == NULL )
923 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
926 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
929 afsi_log("%s version %s", filename, afsdVersion);
931 if (((FARPROC) pGetModuleFileNameExA =
932 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
933 ((FARPROC) pEnumProcessModules =
934 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
941 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
942 AFSREG_CLT_SVC_PARAM_SUBKEY,
943 0, KEY_QUERY_VALUE, &parmKey);
944 if (code == ERROR_SUCCESS) {
945 dummyLen = sizeof(cacheSize);
946 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
947 (BYTE *) &cacheSize, &dummyLen);
948 RegCloseKey (parmKey);
951 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
952 0, KEY_QUERY_VALUE, &parmKey);
953 if (code == ERROR_SUCCESS) {
954 dummyLen = sizeof(verifyServiceSig);
955 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
956 (BYTE *) &verifyServiceSig, &dummyLen);
957 RegCloseKey (parmKey);
960 if (verifyServiceSig && cacheSize < 716800) {
961 trustVerified = VerifyTrust(filename);
963 afsi_log("Signature Verification disabled");
969 // get a certificate context for the signer of afsd_service.
970 pCtxService = GetCertCtx(filename);
972 LogCertCtx(pCtxService);
975 // Get a list of all the modules in this process.
976 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
977 FALSE, GetCurrentProcessId());
979 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
981 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
983 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
985 char szModName[2048];
987 // Get the full path to the module's file.
988 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
990 lstrcpy(checkName, szModName);
993 if ( strstr(checkName, "afspthread.dll") ||
994 strstr(checkName, "afsauthent.dll") ||
995 strstr(checkName, "afsrpc.dll") ||
996 strstr(checkName, "libafsconf.dll") ||
997 strstr(checkName, "libosi.dll") )
999 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1004 afsi_log("%s version %s", szModName, modVersion);
1005 if (strcmp(afsdVersion,modVersion)) {
1006 afsi_log("Version mismatch: %s", szModName);
1009 if ( trustVerified ) {
1010 if ( !VerifyTrust(szModName) ) {
1011 afsi_log("Signature Verification failed: %s", szModName);
1014 else if (pCtxService) {
1015 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1017 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1018 pCtxService->pCertInfo,
1020 afsi_log("Certificate mismatch: %s", szModName);
1028 pCertFreeCertificateContext(pCtx);
1037 pCertFreeCertificateContext(pCtxService);
1041 FreeLibrary(hPSAPI);
1043 CloseHandle(hProcess);
1048 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1051 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1052 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1054 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1055 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1058 afsd_Main(DWORD argc, LPTSTR *argv)
1072 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1073 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1076 osi_InitPanic(afsd_notifier);
1077 osi_InitTraceOption();
1083 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1084 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1085 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1088 hAdvApi32 = LoadLibrary("advapi32.dll");
1089 if (hAdvApi32 == NULL)
1091 afsi_log("Fatal: cannot load advapi32.dll");
1095 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1096 if (pRegisterServiceCtrlHandlerEx)
1098 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1099 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1103 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1106 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1107 ServiceStatus.dwServiceSpecificExitCode = 0;
1108 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1109 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1110 ServiceStatus.dwCheckPoint = 1;
1111 ServiceStatus.dwWaitHint = 30000;
1112 /* accept Power Events */
1113 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1114 SetServiceStatus(StatusHandle, &ServiceStatus);
1117 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
1119 #ifdef REGISTER_POWER_NOTIFICATIONS
1126 /* see if we should handle power notifications */
1127 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1128 0, KEY_QUERY_VALUE, &hkParm);
1129 if (code == ERROR_SUCCESS) {
1130 dummyLen = sizeof(bpower);
1131 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1132 (BYTE *) &bpower, &dummyLen);
1134 if(code != ERROR_SUCCESS)
1137 RegCloseKey(hkParm);
1139 /* create thread used to flush cache */
1141 PowerNotificationThreadCreate();
1142 powerEventsRegistered = 1;
1147 /* Verify the versions of the DLLs which were loaded */
1148 if (!AFSModulesVerify()) {
1149 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1150 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1151 ServiceStatus.dwCheckPoint = 0;
1152 ServiceStatus.dwWaitHint = 0;
1153 ServiceStatus.dwControlsAccepted = 0;
1154 SetServiceStatus(StatusHandle, &ServiceStatus);
1156 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
1158 /* exit if initialization failed */
1162 /* allow an exit to be called prior to any initialization */
1163 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1167 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1170 hookRc = initHook();
1172 FreeLibrary(hHookDll);
1175 if (hookRc == FALSE)
1177 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1178 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1179 ServiceStatus.dwCheckPoint = 0;
1180 ServiceStatus.dwWaitHint = 0;
1181 ServiceStatus.dwControlsAccepted = 0;
1182 SetServiceStatus(StatusHandle, &ServiceStatus);
1184 /* exit if initialization failed */
1189 /* allow another 15 seconds to start */
1190 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1191 ServiceStatus.dwServiceSpecificExitCode = 0;
1192 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1193 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1194 ServiceStatus.dwCheckPoint = 2;
1195 ServiceStatus.dwWaitHint = 20000;
1196 /* accept Power Events */
1197 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1198 SetServiceStatus(StatusHandle, &ServiceStatus);
1203 MainThreadId = GetCurrentThreadId();
1204 jmpret = setjmp(notifier_jmp);
1209 code = afsd_InitCM(&reason);
1211 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1212 osi_panic(reason, __FILE__, __LINE__);
1216 ServiceStatus.dwCheckPoint++;
1217 ServiceStatus.dwWaitHint -= 5000;
1218 SetServiceStatus(StatusHandle, &ServiceStatus);
1220 code = afsd_InitDaemons(&reason);
1222 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1223 osi_panic(reason, __FILE__, __LINE__);
1226 /* allow an exit to be called post rx initialization */
1227 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1231 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1234 hookRc = rxStartedHook();
1236 FreeLibrary(hHookDll);
1239 if (hookRc == FALSE)
1241 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1242 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1243 ServiceStatus.dwCheckPoint = 0;
1244 ServiceStatus.dwWaitHint = 0;
1245 ServiceStatus.dwControlsAccepted = 0;
1246 SetServiceStatus(StatusHandle, &ServiceStatus);
1248 /* exit if initialization failed */
1254 ServiceStatus.dwCheckPoint++;
1255 ServiceStatus.dwWaitHint -= 5000;
1256 SetServiceStatus(StatusHandle, &ServiceStatus);
1259 /* the following ifdef chooses the mode of operation for the service. to enable
1260 * a runtime flag (instead of compile-time), pioctl() would need to dynamically
1261 * determine the mode, in order to use the correct ioctl special-file path. */
1263 code = afsd_InitSMB(&reason, MessageBox);
1265 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1266 osi_panic(reason, __FILE__, __LINE__);
1269 code = ifs_Init(&reason);
1271 afsi_log("ifs_Init failed: %s (code = %d)", reason, code);
1272 osi_panic(reason, __FILE__, __LINE__);
1274 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1275 hAFSDWorkerThread[cnt] = CreateThread(NULL, 0, ifs_MainLoop, 0, 0, NULL);
1278 /* allow an exit to be called post smb initialization */
1279 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1283 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1286 hookRc = smbStartedHook();
1288 FreeLibrary(hHookDll);
1291 if (hookRc == FALSE)
1293 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1294 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1295 ServiceStatus.dwCheckPoint = 0;
1296 ServiceStatus.dwWaitHint = 0;
1297 ServiceStatus.dwControlsAccepted = 0;
1298 SetServiceStatus(StatusHandle, &ServiceStatus);
1300 /* exit if initialization failed */
1305 MountGlobalDrives();
1308 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1309 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1310 ServiceStatus.dwCheckPoint = 0;
1311 ServiceStatus.dwWaitHint = 0;
1313 /* accept Power events */
1314 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1315 SetServiceStatus(StatusHandle, &ServiceStatus);
1318 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
1321 /* allow an exit to be called when started */
1322 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1326 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1329 hookRc = startedHook();
1331 FreeLibrary(hHookDll);
1334 if (hookRc == FALSE)
1336 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1337 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1338 ServiceStatus.dwCheckPoint = 0;
1339 ServiceStatus.dwWaitHint = 0;
1340 ServiceStatus.dwControlsAccepted = 0;
1341 SetServiceStatus(StatusHandle, &ServiceStatus);
1343 /* exit if initialization failed */
1349 WaitForSingleObject(WaitToTerminate, INFINITE);
1351 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
1352 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1353 CloseHandle(hAFSDWorkerThread[cnt]);
1356 afsi_log("Received Termination Signal, Stopping Service");
1359 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP);
1361 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
1363 /* allow an exit to be called prior to stopping the service */
1364 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1368 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1371 hookRc = stoppingHook();
1373 FreeLibrary(hHookDll);
1376 if (hookRc == FALSE)
1378 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1379 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1380 ServiceStatus.dwCheckPoint = 0;
1381 ServiceStatus.dwWaitHint = 0;
1382 ServiceStatus.dwControlsAccepted = 0;
1383 SetServiceStatus(StatusHandle, &ServiceStatus);
1385 /* exit if initialization failed */
1391 #ifdef AFS_FREELANCE_CLIENT
1392 cm_FreelanceShutdown();
1393 afsi_log("Freelance Shutdown complete");
1396 DismountGlobalDrives();
1397 afsi_log("Global Drives dismounted");
1399 cm_DaemonShutdown();
1400 afsi_log("Daemon shutdown complete");
1403 afsi_log("Buffer shutdown complete");
1406 afsi_log("rx finalization complete");
1410 afsi_log("smb shutdown complete");
1415 cm_ReleaseAllLocks();
1418 afsi_log("rx finalization complete");
1420 cm_ShutdownMappedMemory();
1422 #ifdef REGISTER_POWER_NOTIFICATIONS
1423 /* terminate thread used to flush cache */
1424 if (powerEventsRegistered)
1425 PowerNotificationThreadExit();
1428 /* allow an exit to be called after stopping the service */
1429 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1433 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1436 hookRc = stoppedHook();
1438 FreeLibrary(hHookDll);
1442 /* Remove the ExceptionFilter */
1443 SetUnhandledExceptionFilter(NULL);
1445 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1446 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1447 ServiceStatus.dwCheckPoint = 0;
1448 ServiceStatus.dwWaitHint = 0;
1449 ServiceStatus.dwControlsAccepted = 0;
1450 SetServiceStatus(StatusHandle, &ServiceStatus);
1453 DWORD __stdcall afsdMain_thread(void* notUsed)
1455 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1456 afsd_Main(1, (LPTSTR*)argv);
1462 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1466 main(int argc, char * argv[])
1468 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1469 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1474 for (i = 1; i < argc; i++) {
1475 if (!stricmp(argv[i],"--validate-cache")) {
1476 if (++i != argc - 1) {
1481 return cm_ValidateMappedMemory(argv[i]);
1488 if (!StartServiceCtrlDispatcher(dispatchTable))
1490 LONG status = GetLastError();
1491 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1494 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1496 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1498 SetEvent(WaitToTerminate);
1505 if ( hAFSDMainThread ) {
1506 WaitForSingleObject( hAFSDMainThread, INFINITE );
1507 CloseHandle( hAFSDMainThread );