11 #include "afsd_init.h"
12 #include "lanahelper.h"
16 #include <WINNT\afsreg.h>
30 //#define REGISTER_POWER_NOTIFICATIONS 1
31 #include "afsd_flushvol.h"
33 extern void afsi_log(char *pattern, ...);
35 static SERVICE_STATUS ServiceStatus;
36 static SERVICE_STATUS_HANDLE StatusHandle;
38 HANDLE hAFSDMainThread = NULL;
40 HANDLE WaitToTerminate;
42 static int GlobalStatus;
45 unsigned int MainThreadId;
49 extern int traceOnPanic;
50 extern HANDLE afsi_file;
52 static int powerEventsRegistered = 0;
53 extern int powerStateSuspended = 0;
56 * Notifier function for use by osi_panic
58 static void afsd_notifier(char *msgp, char *filep, long line)
61 msgp = "unspecified assert";
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_MemDumpDirStats(afsi_file, "a", 0);
78 cm_MemDumpBPlusStats(afsi_file, "a", 0);
79 cm_DumpCells(afsi_file, "a", 0);
80 cm_DumpVolumes(afsi_file, "a", 0);
81 cm_DumpSCache(afsi_file, "a", 0);
83 cm_dnlcDump(afsi_file, "a");
85 cm_DumpBufHashTable(afsi_file, "a", 0);
86 smb_DumpVCP(afsi_file, "a", 0);
87 afsi_log("--- end dump ---");
90 if (IsDebuggerPresent())
94 SetEvent(WaitToTerminate);
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 */
177 if ( !lana_OnlyLoopback() )
180 /* Force trace if requested */
181 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
182 AFSREG_CLT_SVC_PARAM_SUBKEY,
183 0, KEY_QUERY_VALUE, &parmKey);
184 if (code != ERROR_SUCCESS)
187 dummyLen = sizeof(doTrace);
188 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
190 (BYTE *) &doTrace, &dummyLen);
191 RegCloseKey (parmKey);
192 if (code != ERROR_SUCCESS)
195 afsd_ForceTrace(FALSE);
196 buf_ForceTrace(FALSE);
200 SetEvent(WaitToTerminate);
203 case SERVICE_CONTROL_INTERROGATE:
204 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
205 ServiceStatus.dwWin32ExitCode = NO_ERROR;
206 ServiceStatus.dwCheckPoint = 0;
207 ServiceStatus.dwWaitHint = 0;
208 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
209 SetServiceStatus(StatusHandle, &ServiceStatus);
211 /* XXX handle system shutdown */
212 /* XXX handle pause & continue */
218 ** Extended ServiceControlHandler that provides Event types
219 ** for monitoring Power events, for example.
222 afsd_ServiceControlHandlerEx(
230 DWORD dummyLen, doTrace;
232 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
233 OSVERSIONINFO osVersion;
235 /* Get the version of Windows */
236 memset(&osVersion, 0x00, sizeof(osVersion));
237 osVersion.dwOSVersionInfoSize = sizeof(osVersion);
238 GetVersionEx(&osVersion);
242 case SERVICE_CONTROL_SHUTDOWN:
243 case SERVICE_CONTROL_STOP:
244 if (ctrlCode == SERVICE_CONTROL_SHUTDOWN)
245 afsi_log("SERVICE_CONTROL_SHUTDOWN");
247 afsi_log("SERVICE_CONTROL_STOP");
249 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
250 ServiceStatus.dwWin32ExitCode = NO_ERROR;
251 ServiceStatus.dwCheckPoint = 1;
252 ServiceStatus.dwWaitHint = 30000;
253 ServiceStatus.dwControlsAccepted = 0;
254 SetServiceStatus(StatusHandle, &ServiceStatus);
256 /* Write all dirty buffers back to server */
257 if ( !lana_OnlyLoopback() )
260 /* Force trace if requested */
261 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
262 AFSREG_CLT_SVC_PARAM_SUBKEY,
263 0, KEY_QUERY_VALUE, &parmKey);
264 if (code != ERROR_SUCCESS)
267 dummyLen = sizeof(doTrace);
268 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
270 (BYTE *) &doTrace, &dummyLen);
271 RegCloseKey (parmKey);
272 if (code != ERROR_SUCCESS)
275 afsd_ForceTrace(FALSE);
276 buf_ForceTrace(FALSE);
280 SetEvent(WaitToTerminate);
284 case SERVICE_CONTROL_INTERROGATE:
285 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
286 ServiceStatus.dwWin32ExitCode = NO_ERROR;
287 ServiceStatus.dwCheckPoint = 0;
288 ServiceStatus.dwWaitHint = 0;
289 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
290 SetServiceStatus(StatusHandle, &ServiceStatus);
291 afsi_log("SERVICE_CONTROL_INTERROGATE");
295 /* XXX handle system shutdown */
296 /* XXX handle pause & continue */
297 case SERVICE_CONTROL_POWEREVENT:
300 afsi_log("SERVICE_CONTROL_POWEREVENT");
303 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
304 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
305 ** Return any error code to deny request,
306 ** i.e. as if returning BROADCAST_QUERY_DENY
308 if (powerEventsRegistered) {
309 switch((int) dwEventType)
311 case PBT_APMQUERYSUSPEND:
312 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
313 /* Write all dirty buffers back to server */
314 if ( !lana_OnlyLoopback() ) {
318 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
321 case PBT_APMQUERYSTANDBY:
322 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
323 /* Write all dirty buffers back to server */
324 if ( !lana_OnlyLoopback() ) {
328 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
332 /* allow remaining case PBT_WhatEver */
334 afsi_log("SERVICE_CONTROL_APMSUSPEND");
335 powerStateSuspended = 1;
336 if (osVersion.dwMajorVersion >= 6) {
338 smb_StopListeners(0);
343 afsi_log("SERVICE_CONTROL_APMSTANDBY");
344 powerStateSuspended = 1;
345 if (osVersion.dwMajorVersion >= 6) {
347 smb_StopListeners(0);
351 case PBT_APMRESUMECRITICAL:
352 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
353 if (osVersion.dwMajorVersion >= 6)
354 smb_RestartListeners(0);
357 case PBT_APMRESUMESUSPEND:
358 /* User logged in after suspend */
359 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
362 case PBT_APMRESUMESTANDBY:
363 /* User logged in after standby */
364 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
367 case PBT_APMBATTERYLOW:
368 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
371 case PBT_APMPOWERSTATUSCHANGE:
373 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
377 case PBT_APMOEMEVENT:
379 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
383 case PBT_APMRESUMEAUTOMATIC:
384 /* This is the message delivered once all devices are up */
385 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
386 powerStateSuspended = 0;
387 if (osVersion.dwMajorVersion >= 6) {
388 smb_SetLanAdapterChangeDetected();
393 afsi_log("SERVICE_CONTROL_unknown");
399 case SERVICE_CONTROL_CUSTOM_DUMP:
401 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
402 GenerateMiniDump(NULL);
406 } /* end switch(ctrlCode) */
410 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
412 * Mount a drive into AFS if there global mapping
414 /* DEE Could check first if we are run as SYSTEM */
415 #define MAX_RETRIES 10
416 #define MAX_DRIVES 23
417 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
419 char szAfsPath[_MAX_PATH];
420 char szDriveToMapTo[5];
424 DWORD dwIndex = 0, dwRetry = 0;
426 DWORD dwSubMountSize;
427 char szSubMount[256];
430 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
432 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
433 if (dwResult != ERROR_SUCCESS)
436 while (dwIndex < MAX_DRIVES) {
437 dwDriveSize = sizeof(szDriveToMapTo);
438 dwSubMountSize = sizeof(szSubMount);
439 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
440 if (dwResult != ERROR_MORE_DATA) {
441 if (dwResult != ERROR_SUCCESS) {
442 if (dwResult != ERROR_NO_MORE_ITEMS)
443 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
448 for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
451 memset (&nr, 0x00, sizeof(NETRESOURCE));
453 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
455 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
456 nr.dwType=RESOURCETYPE_DISK;
457 nr.lpLocalName=szDriveToMapTo;
458 nr.lpRemoteName=szAfsPath;
459 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
460 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
462 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
463 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
464 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
465 if (dwResult == NO_ERROR) {
468 /* wait for smb server to come up */
469 Sleep((DWORD)1000 /* miliseconds */);
471 /* Disconnect any previous mappings */
472 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
480 static HANDLE hThreadMountGlobalDrives = NULL;
482 static void MountGlobalDrives()
486 hThreadMountGlobalDrives = CreateThread(NULL, 0, MountGlobalDrivesThread, 0, 0, &tid);
488 if ( hThreadMountGlobalDrives ) {
489 DWORD rc = WaitForSingleObject( hThreadMountGlobalDrives, 15000 );
490 if (rc == WAIT_TIMEOUT) {
491 afsi_log("GlobalAutoMap thread failed to complete after 15 seconds");
492 } else if (rc == WAIT_OBJECT_0) {
493 afsi_log("GlobalAutoMap thread completed");
494 CloseHandle( hThreadMountGlobalDrives );
495 hThreadMountGlobalDrives = NULL;
500 static void DismountGlobalDrives()
502 char szAfsPath[_MAX_PATH];
503 char szDriveToMapTo[5];
505 DWORD dwSubMountSize;
506 char szSubMount[256];
513 if ( hThreadMountGlobalDrives ) {
514 DWORD rc = WaitForSingleObject(hThreadMountGlobalDrives, 0);
516 if (rc == WAIT_TIMEOUT) {
517 afsi_log("GlobalAutoMap thread failed to complete before service shutdown");
519 else if (rc == WAIT_OBJECT_0) {
520 afsi_log("GlobalAutoMap thread completed");
521 CloseHandle( hThreadMountGlobalDrives );
522 hThreadMountGlobalDrives = NULL;
526 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
528 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
529 if (dwResult != ERROR_SUCCESS)
532 while (dwIndex < MAX_DRIVES) {
533 dwDriveSize = sizeof(szDriveToMapTo);
534 dwSubMountSize = sizeof(szSubMount);
535 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
536 if (dwResult != ERROR_MORE_DATA) {
537 if (dwResult != ERROR_SUCCESS) {
538 if (dwResult != ERROR_NO_MORE_ITEMS)
539 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
544 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
546 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
547 dwResult = WNetCancelConnection(szAfsPath, TRUE);
549 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
556 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
558 DWORD dwVersionHandle;
559 LPVOID pVersionInfo = 0;
561 LPDWORD pLangInfo = 0;
562 LPTSTR szVersion = 0;
564 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
565 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
568 afsi_log("GetFileVersionInfoSize failed");
569 return GetLastError();
572 pVersionInfo = malloc(size);
574 afsi_log("out of memory 1");
575 return ERROR_NOT_ENOUGH_MEMORY;
578 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
579 if (retval = GetLastError())
581 afsi_log("GetFileVersionInfo failed: %d", retval);
585 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
586 (LPVOID*)&pLangInfo, &len);
587 if (retval = GetLastError())
589 afsi_log("VerQueryValue 1 failed: %d", retval);
594 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
595 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
597 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
598 if (retval = GetLastError())
600 /* try again with language 409 since the old binaries were tagged wrong */
602 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
605 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
606 if (retval = GetLastError()) {
607 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
611 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
612 szOutput[dwOutput - 1] = 0;
621 static HINSTANCE hCrypt32;
622 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
623 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
624 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
625 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
626 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
627 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
628 HCRYPTMSG* phMsg, const void** ppvContext);
629 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
630 void* pvData, DWORD* pcbData);
631 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
632 DWORD dwFindFlags, DWORD dwFindType,
633 const void* pvFindPara,
634 PCCERT_CONTEXT pPrevCertContext);
635 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
636 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
637 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
638 PCERT_INFO pCertId2);
639 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
641 void LoadCrypt32(void)
643 hCrypt32 = LoadLibrary("crypt32");
647 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
648 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
649 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
650 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
651 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
652 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
653 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
654 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
656 if ( !pCertGetNameString ||
657 !pCryptQueryObject ||
658 !pCryptMsgGetParam ||
659 !pCertFindCertificateInStore ||
662 !pCertCompareCertificate ||
663 !pCertFreeCertificateContext)
665 FreeLibrary(hCrypt32);
670 void UnloadCrypt32(void)
672 FreeLibrary(hCrypt32);
675 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
677 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
679 wchar_t wfilename[260];
685 HCERTSTORE hStore = NULL;
686 HCRYPTMSG hMsg = NULL;
687 PCMSG_SIGNER_INFO pSignerInfo = NULL;
688 PCCERT_CONTEXT pCertContext = NULL;
691 if ( hCrypt32 == NULL )
694 ZeroMemory(&CertInfo, sizeof(CertInfo));
695 mbstowcs(wfilename, filename, 260);
697 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
699 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
700 CERT_QUERY_FORMAT_FLAG_BINARY,
710 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
716 fResult = pCryptMsgGetParam(hMsg,
717 CMSG_SIGNER_INFO_PARAM,
723 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
729 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
731 fResult = pCryptMsgGetParam(hMsg,
732 CMSG_SIGNER_INFO_PARAM,
738 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
744 CertInfo.Issuer = pSignerInfo->Issuer;
745 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
747 pCertContext = pCertFindCertificateInStore(hStore,
750 CERT_FIND_SUBJECT_CERT,
755 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
763 LocalFree(pSignerInfo);
766 CertFreeCertificateContext(pCertContext);*/
769 pCertCloseStore(hStore,0);
772 pCryptMsgClose(hMsg);
777 BOOL VerifyTrust(CHAR * filename)
779 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
780 WIN_TRUST_SUBJECT_FILE fSubjectFile;
781 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
782 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
783 wchar_t wfilename[260];
785 BOOL success = FALSE;
787 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
790 if (filename == NULL )
793 hWinTrust = LoadLibrary("wintrust");
797 if (((FARPROC) pWinVerifyTrust =
798 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
800 FreeLibrary(hWinTrust);
804 mbstowcs(wfilename, filename, 260);
806 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
808 fSubjectFile.lpPath = wfilename;
809 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
810 FALSE, GetCurrentProcessId());
811 fContextWSubject.SubjectType = &subject;
812 fContextWSubject.Subject = &fSubjectFile;
814 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
816 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
817 CloseHandle( fSubjectFile.hFile );
818 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
819 CloseHandle( fContextWSubject.hClientToken );
821 if (ret == ERROR_SUCCESS) {
824 DWORD gle = GetLastError();
826 case TRUST_E_PROVIDER_UNKNOWN:
827 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
829 case TRUST_E_NOSIGNATURE:
830 afsi_log("VerifyTrust failed: Unsigned executable");
832 case TRUST_E_EXPLICIT_DISTRUST:
833 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
835 case TRUST_E_SUBJECT_NOT_TRUSTED:
836 afsi_log("VerifyTrust failed: File is not trusted");
838 case TRUST_E_BAD_DIGEST:
839 afsi_log("VerifyTrust failed: Executable has been modified");
841 case CRYPT_E_SECURITY_SETTINGS:
842 afsi_log("VerifyTrust failed: local security options prevent verification");
845 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
849 FreeLibrary(hWinTrust);
853 void LogCertCtx(PCCERT_CONTEXT pCtx) {
855 LPTSTR szName = NULL;
857 if ( hCrypt32 == NULL )
860 // Get Issuer name size.
861 if (!(dwData = pCertGetNameString(pCtx,
862 CERT_NAME_SIMPLE_DISPLAY_TYPE,
863 CERT_NAME_ISSUER_FLAG,
867 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
871 // Allocate memory for Issuer name.
872 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
875 if (!(pCertGetNameString(pCtx,
876 CERT_NAME_SIMPLE_DISPLAY_TYPE,
877 CERT_NAME_ISSUER_FLAG,
881 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
885 // print Issuer name.
886 afsi_log("Issuer Name: %s", szName);
890 // Get Subject name size.
891 if (!(dwData = pCertGetNameString(pCtx,
892 CERT_NAME_SIMPLE_DISPLAY_TYPE,
897 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
901 // Allocate memory for subject name.
902 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
905 if (!(pCertGetNameString(pCtx,
906 CERT_NAME_SIMPLE_DISPLAY_TYPE,
911 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
915 // Print Subject Name.
916 afsi_log("Subject Name: %s", szName);
924 BOOL AFSModulesVerify(void)
927 CHAR afsdVersion[128];
928 CHAR modVersion[128];
929 CHAR checkName[1024];
930 BOOL trustVerified = FALSE;
936 PCCERT_CONTEXT pCtxService = NULL;
938 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
939 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
940 DWORD dummyLen, code;
941 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
942 DWORD verifyServiceSig = TRUE;
945 hPSAPI = LoadLibrary("psapi");
947 if ( hPSAPI == NULL )
950 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
953 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
956 afsi_log("%s version %s", filename, afsdVersion);
958 if (((FARPROC) pGetModuleFileNameExA =
959 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
960 ((FARPROC) pEnumProcessModules =
961 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
968 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
969 AFSREG_CLT_SVC_PARAM_SUBKEY,
970 0, KEY_QUERY_VALUE, &parmKey);
971 if (code == ERROR_SUCCESS) {
972 dummyLen = sizeof(cacheSize);
973 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
974 (BYTE *) &cacheSize, &dummyLen);
975 RegCloseKey (parmKey);
978 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
979 0, KEY_QUERY_VALUE, &parmKey);
980 if (code == ERROR_SUCCESS) {
981 dummyLen = sizeof(verifyServiceSig);
982 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
983 (BYTE *) &verifyServiceSig, &dummyLen);
984 RegCloseKey (parmKey);
989 && cacheSize < 716800
992 trustVerified = VerifyTrust(filename);
994 afsi_log("Signature Verification disabled");
1000 // get a certificate context for the signer of afsd_service.
1001 pCtxService = GetCertCtx(filename);
1003 LogCertCtx(pCtxService);
1006 // Get a list of all the modules in this process.
1007 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
1008 FALSE, GetCurrentProcessId());
1010 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
1012 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
1014 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
1016 char szModName[2048];
1018 // Get the full path to the module's file.
1019 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
1021 lstrcpy(checkName, szModName);
1024 if ( strstr(checkName, "afspthread.dll") ||
1025 strstr(checkName, "afsauthent.dll") ||
1026 strstr(checkName, "afsrpc.dll") ||
1027 strstr(checkName, "libafsconf.dll") ||
1028 strstr(checkName, "libosi.dll") )
1030 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1035 afsi_log("%s version %s", szModName, modVersion);
1036 if (strcmp(afsdVersion,modVersion)) {
1037 afsi_log("Version mismatch: %s", szModName);
1040 if ( trustVerified ) {
1041 if ( !VerifyTrust(szModName) ) {
1042 afsi_log("Signature Verification failed: %s", szModName);
1045 else if (pCtxService) {
1046 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1048 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1049 pCtxService->pCertInfo,
1051 afsi_log("Certificate mismatch: %s", szModName);
1059 pCertFreeCertificateContext(pCtx);
1068 pCertFreeCertificateContext(pCtxService);
1072 FreeLibrary(hPSAPI);
1074 CloseHandle(hProcess);
1079 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1082 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1083 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1085 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1086 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1089 afsd_Main(DWORD argc, LPTSTR *argv)
1100 void afsd_DbgBreakAllocInit();
1102 afsd_DbgBreakAllocInit();
1103 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1104 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1107 afsd_SetUnhandledExceptionFilter();
1109 osi_InitPanic(afsd_notifier);
1110 osi_InitTraceOption();
1116 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1117 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1118 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1121 hAdvApi32 = LoadLibrary("advapi32.dll");
1122 if (hAdvApi32 == NULL)
1124 afsi_log("Fatal: cannot load advapi32.dll");
1128 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1129 if (pRegisterServiceCtrlHandlerEx)
1131 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1132 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1136 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1139 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1140 ServiceStatus.dwServiceSpecificExitCode = 0;
1141 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1142 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1143 ServiceStatus.dwCheckPoint = 1;
1144 ServiceStatus.dwWaitHint = 120000;
1145 /* accept Power Events */
1146 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1147 SetServiceStatus(StatusHandle, &ServiceStatus);
1150 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
1152 #ifdef REGISTER_POWER_NOTIFICATIONS
1159 /* see if we should handle power notifications */
1160 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1161 0, KEY_QUERY_VALUE, &hkParm);
1162 if (code == ERROR_SUCCESS) {
1163 dummyLen = sizeof(bpower);
1164 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1165 (BYTE *) &bpower, &dummyLen);
1167 if(code != ERROR_SUCCESS)
1170 RegCloseKey(hkParm);
1172 /* create thread used to flush cache */
1174 PowerNotificationThreadCreate();
1175 powerEventsRegistered = 1;
1180 /* Verify the versions of the DLLs which were loaded */
1181 if (!AFSModulesVerify()) {
1182 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1183 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1184 ServiceStatus.dwCheckPoint = 0;
1185 ServiceStatus.dwWaitHint = 0;
1186 ServiceStatus.dwControlsAccepted = 0;
1187 SetServiceStatus(StatusHandle, &ServiceStatus);
1189 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
1191 /* exit if initialization failed */
1195 /* allow an exit to be called prior to any initialization */
1196 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1200 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1203 hookRc = initHook();
1205 FreeLibrary(hHookDll);
1208 if (hookRc == FALSE)
1210 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1211 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1212 ServiceStatus.dwCheckPoint = 0;
1213 ServiceStatus.dwWaitHint = 0;
1214 ServiceStatus.dwControlsAccepted = 0;
1215 SetServiceStatus(StatusHandle, &ServiceStatus);
1217 /* exit if initialization failed */
1222 /* allow another 120 seconds to start */
1223 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1224 ServiceStatus.dwServiceSpecificExitCode = 0;
1225 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1226 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1227 ServiceStatus.dwCheckPoint = 2;
1228 ServiceStatus.dwWaitHint = 120000;
1229 /* accept Power Events */
1230 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1231 SetServiceStatus(StatusHandle, &ServiceStatus);
1235 /* Perform Volume Status Notification Initialization */
1236 cm_VolStatus_Initialization();
1239 MainThreadId = GetCurrentThreadId();
1240 jmpret = setjmp(notifier_jmp);
1245 code = afsd_InitCM(&reason);
1247 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1248 osi_panic(reason, __FILE__, __LINE__);
1252 ServiceStatus.dwCheckPoint = 3;
1253 ServiceStatus.dwWaitHint = 30000;
1254 SetServiceStatus(StatusHandle, &ServiceStatus);
1256 code = afsd_InitDaemons(&reason);
1258 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1259 osi_panic(reason, __FILE__, __LINE__);
1262 /* allow an exit to be called post rx initialization */
1263 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1267 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1270 hookRc = rxStartedHook();
1272 FreeLibrary(hHookDll);
1275 if (hookRc == FALSE)
1277 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1278 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1279 ServiceStatus.dwCheckPoint = 0;
1280 ServiceStatus.dwWaitHint = 0;
1281 ServiceStatus.dwControlsAccepted = 0;
1282 SetServiceStatus(StatusHandle, &ServiceStatus);
1284 /* exit if initialization failed */
1290 ServiceStatus.dwCheckPoint = 4;
1291 ServiceStatus.dwWaitHint = 15000;
1292 SetServiceStatus(StatusHandle, &ServiceStatus);
1295 /* Notify any volume status handlers that the cache manager has started */
1296 cm_VolStatus_Service_Started();
1298 /* the following ifdef chooses the mode of operation for the service. to enable
1299 * a runtime flag (instead of compile-time), pioctl() would need to dynamically
1300 * determine the mode, in order to use the correct ioctl special-file path. */
1301 code = afsd_InitSMB(&reason, MessageBox);
1303 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1304 osi_panic(reason, __FILE__, __LINE__);
1307 /* allow an exit to be called post smb initialization */
1308 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1312 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1315 hookRc = smbStartedHook();
1317 FreeLibrary(hHookDll);
1320 if (hookRc == FALSE)
1322 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1323 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1324 ServiceStatus.dwCheckPoint = 0;
1325 ServiceStatus.dwWaitHint = 0;
1326 ServiceStatus.dwControlsAccepted = 0;
1327 SetServiceStatus(StatusHandle, &ServiceStatus);
1329 /* exit if initialization failed */
1334 MountGlobalDrives();
1337 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1338 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1339 ServiceStatus.dwCheckPoint = 5;
1340 ServiceStatus.dwWaitHint = 0;
1342 /* accept Power events */
1343 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1344 SetServiceStatus(StatusHandle, &ServiceStatus);
1347 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
1350 /* allow an exit to be called when started */
1351 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1355 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1358 hookRc = startedHook();
1360 FreeLibrary(hHookDll);
1363 if (hookRc == FALSE)
1365 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1366 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1367 ServiceStatus.dwCheckPoint = 0;
1368 ServiceStatus.dwWaitHint = 0;
1369 ServiceStatus.dwControlsAccepted = 0;
1370 SetServiceStatus(StatusHandle, &ServiceStatus);
1372 /* exit if initialization failed */
1377 WaitForSingleObject(WaitToTerminate, INFINITE);
1379 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
1380 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1381 ServiceStatus.dwCheckPoint = 6;
1382 ServiceStatus.dwWaitHint = 120000;
1383 ServiceStatus.dwControlsAccepted = 0;
1384 SetServiceStatus(StatusHandle, &ServiceStatus);
1386 afsi_log("Received Termination Signal, Stopping Service");
1389 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP);
1391 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
1393 /* allow an exit to be called prior to stopping the service */
1394 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1398 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1401 hookRc = stoppingHook();
1403 FreeLibrary(hHookDll);
1408 #ifdef AFS_FREELANCE_CLIENT
1409 cm_FreelanceShutdown();
1410 afsi_log("Freelance Shutdown complete");
1413 DismountGlobalDrives();
1414 afsi_log("Global Drives dismounted");
1416 cm_DaemonShutdown();
1417 afsi_log("Daemon shutdown complete");
1422 afsi_log("Buffer shutdown complete");
1425 afsi_log("rx finalization complete");
1428 afsi_log("smb shutdown complete");
1432 cm_ReleaseAllLocks();
1435 afsi_log("rx finalization complete");
1437 cm_ShutdownMappedMemory();
1439 #ifdef REGISTER_POWER_NOTIFICATIONS
1440 /* terminate thread used to flush cache */
1441 if (powerEventsRegistered)
1442 PowerNotificationThreadExit();
1447 cm_BPlusDumpStats();
1450 /* Notify any Volume Status Handlers that we are stopped */
1451 cm_VolStatus_Service_Stopped();
1453 /* Cleanup any Volume Status Notification Handler */
1454 cm_VolStatus_Finalize();
1456 /* allow an exit to be called after stopping the service */
1457 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1461 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1464 hookRc = stoppedHook();
1466 FreeLibrary(hHookDll);
1470 /* Remove the ExceptionFilter */
1471 SetUnhandledExceptionFilter(NULL);
1473 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1474 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1475 ServiceStatus.dwCheckPoint = 7;
1476 ServiceStatus.dwWaitHint = 0;
1477 ServiceStatus.dwControlsAccepted = 0;
1478 SetServiceStatus(StatusHandle, &ServiceStatus);
1481 DWORD __stdcall afsdMain_thread(void* notUsed)
1483 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1484 afsd_Main(1, (LPTSTR*)argv);
1490 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1494 main(int argc, char * argv[])
1496 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1497 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1502 for (i = 1; i < argc; i++) {
1503 if (!stricmp(argv[i],"--validate-cache")) {
1504 if (++i != argc - 1) {
1509 return cm_ValidateMappedMemory(argv[i]);
1516 if (!StartServiceCtrlDispatcher(dispatchTable))
1518 LONG status = GetLastError();
1519 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1522 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1524 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1526 SetEvent(WaitToTerminate);
1530 if ( hAFSDMainThread ) {
1531 WaitForSingleObject( hAFSDMainThread, INFINITE );
1532 CloseHandle( hAFSDMainThread );