11 #include "afsd_init.h"
12 #include "lanahelper.h"
16 #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 WaitToTerminate;
39 static int GlobalStatus;
42 unsigned int MainThreadId;
46 extern int traceOnPanic;
47 extern HANDLE afsi_file;
49 static int powerEventsRegistered = 0;
50 extern int powerStateSuspended = 0;
53 * Notifier function for use by osi_panic
55 static void afsd_notifier(char *msgp, char *filep, long line)
58 msgp = "unspecified assert";
61 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION,
64 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG, msgp);
68 osi_LogEnable(afsd_logp);
70 afsd_ForceTrace(TRUE);
73 afsi_log("--- begin dump ---");
74 cm_MemDumpDirStats(afsi_file, "a", 0);
75 cm_MemDumpBPlusStats(afsi_file, "a", 0);
76 cm_DumpCells(afsi_file, "a", 0);
77 cm_DumpVolumes(afsi_file, "a", 0);
78 cm_DumpSCache(afsi_file, "a", 0);
80 cm_dnlcDump(afsi_file, "a");
82 cm_DumpBufHashTable(afsi_file, "a", 0);
83 smb_DumpVCP(afsi_file, "a", 0);
84 afsi_log("--- end dump ---");
87 if (IsDebuggerPresent())
91 SetEvent(WaitToTerminate);
94 if (GetCurrentThreadId() == MainThreadId)
95 longjmp(notifier_jmp, 1);
98 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
99 ServiceStatus.dwWin32ExitCode = NO_ERROR;
100 ServiceStatus.dwCheckPoint = 0;
101 ServiceStatus.dwWaitHint = 0;
102 ServiceStatus.dwControlsAccepted = 0;
103 SetServiceStatus(StatusHandle, &ServiceStatus);
109 * For use miscellaneously in smb.c; need to do better
111 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
117 afsd_ServiceFlushVolume(DWORD dwlpEventData)
119 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
122 ** If UI bit is not set, user interaction is not possible
123 ** BUT, since we are a NON-interactive service, and therefore
124 ** have NO user I/O, it doesn't much matter.
125 ** This benign code left here as example of how to find this out
127 BOOL bUI = (dwlpEventData & 1);
130 if ( PowerNotificationThreadNotify() )
136 /* flush was unsuccessful, or timeout - deny shutdown */
137 dwRet = ERROR_NETWORK_BUSY;
140 /* to deny hibernate, simply return
141 // any value besides NO_ERROR.
143 // dwRet = ERROR_NETWORK_BUSY;
150 /* service control handler used in nt4 only for backward compat. */
152 afsd_ServiceControlHandler(DWORD ctrlCode)
155 DWORD dummyLen, doTrace;
159 case SERVICE_CONTROL_SHUTDOWN:
160 case SERVICE_CONTROL_STOP:
161 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
162 ServiceStatus.dwWin32ExitCode = NO_ERROR;
163 ServiceStatus.dwCheckPoint = 1;
164 ServiceStatus.dwWaitHint = 30000;
165 ServiceStatus.dwControlsAccepted = 0;
166 SetServiceStatus(StatusHandle, &ServiceStatus);
168 if (ctrlCode == SERVICE_CONTROL_STOP)
169 afsi_log("SERVICE_CONTROL_STOP");
171 afsi_log("SERVICE_CONTROL_SHUTDOWN");
173 /* Write all dirty buffers back to server */
174 if ( !lana_OnlyLoopback() )
177 /* Force trace if requested */
178 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
179 AFSREG_CLT_SVC_PARAM_SUBKEY,
180 0, KEY_QUERY_VALUE, &parmKey);
181 if (code != ERROR_SUCCESS)
184 dummyLen = sizeof(doTrace);
185 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
187 (BYTE *) &doTrace, &dummyLen);
188 RegCloseKey (parmKey);
189 if (code != ERROR_SUCCESS)
192 afsd_ForceTrace(FALSE);
193 buf_ForceTrace(FALSE);
197 SetEvent(WaitToTerminate);
200 case SERVICE_CONTROL_INTERROGATE:
201 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
202 ServiceStatus.dwWin32ExitCode = NO_ERROR;
203 ServiceStatus.dwCheckPoint = 0;
204 ServiceStatus.dwWaitHint = 0;
205 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
206 SetServiceStatus(StatusHandle, &ServiceStatus);
208 /* XXX handle system shutdown */
209 /* XXX handle pause & continue */
215 ** Extended ServiceControlHandler that provides Event types
216 ** for monitoring Power events, for example.
219 afsd_ServiceControlHandlerEx(
227 DWORD dummyLen, doTrace;
229 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
230 OSVERSIONINFO osVersion;
232 /* Get the version of Windows */
233 memset(&osVersion, 0x00, sizeof(osVersion));
234 osVersion.dwOSVersionInfoSize = sizeof(osVersion);
235 GetVersionEx(&osVersion);
239 case SERVICE_CONTROL_SHUTDOWN:
240 case SERVICE_CONTROL_STOP:
241 if (ctrlCode == SERVICE_CONTROL_SHUTDOWN)
242 afsi_log("SERVICE_CONTROL_SHUTDOWN");
244 afsi_log("SERVICE_CONTROL_STOP");
246 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
247 ServiceStatus.dwWin32ExitCode = NO_ERROR;
248 ServiceStatus.dwCheckPoint = 1;
249 ServiceStatus.dwWaitHint = 30000;
250 ServiceStatus.dwControlsAccepted = 0;
251 SetServiceStatus(StatusHandle, &ServiceStatus);
253 /* Write all dirty buffers back to server */
254 if ( !lana_OnlyLoopback() )
257 /* Force trace if requested */
258 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
259 AFSREG_CLT_SVC_PARAM_SUBKEY,
260 0, KEY_QUERY_VALUE, &parmKey);
261 if (code != ERROR_SUCCESS)
264 dummyLen = sizeof(doTrace);
265 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
267 (BYTE *) &doTrace, &dummyLen);
268 RegCloseKey (parmKey);
269 if (code != ERROR_SUCCESS)
272 afsd_ForceTrace(FALSE);
273 buf_ForceTrace(FALSE);
277 SetEvent(WaitToTerminate);
281 case SERVICE_CONTROL_INTERROGATE:
282 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
283 ServiceStatus.dwWin32ExitCode = NO_ERROR;
284 ServiceStatus.dwCheckPoint = 0;
285 ServiceStatus.dwWaitHint = 0;
286 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
287 SetServiceStatus(StatusHandle, &ServiceStatus);
288 afsi_log("SERVICE_CONTROL_INTERROGATE");
292 /* XXX handle system shutdown */
293 /* XXX handle pause & continue */
294 case SERVICE_CONTROL_POWEREVENT:
297 afsi_log("SERVICE_CONTROL_POWEREVENT");
300 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
301 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
302 ** Return any error code to deny request,
303 ** i.e. as if returning BROADCAST_QUERY_DENY
305 if (powerEventsRegistered) {
306 switch((int) dwEventType)
308 case PBT_APMQUERYSUSPEND:
309 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
310 /* Write all dirty buffers back to server */
311 if ( !lana_OnlyLoopback() ) {
315 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
318 case PBT_APMQUERYSTANDBY:
319 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
320 /* Write all dirty buffers back to server */
321 if ( !lana_OnlyLoopback() ) {
325 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
329 /* allow remaining case PBT_WhatEver */
331 afsi_log("SERVICE_CONTROL_APMSUSPEND");
332 powerStateSuspended = 1;
333 if (osVersion.dwMajorVersion >= 6) {
335 smb_StopListeners(0);
340 afsi_log("SERVICE_CONTROL_APMSTANDBY");
341 powerStateSuspended = 1;
342 if (osVersion.dwMajorVersion >= 6) {
344 smb_StopListeners(0);
348 case PBT_APMRESUMECRITICAL:
349 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
350 if (osVersion.dwMajorVersion >= 6)
351 smb_RestartListeners(0);
354 case PBT_APMRESUMESUSPEND:
355 /* User logged in after suspend */
356 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
359 case PBT_APMRESUMESTANDBY:
360 /* User logged in after standby */
361 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
364 case PBT_APMBATTERYLOW:
365 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
368 case PBT_APMPOWERSTATUSCHANGE:
370 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
374 case PBT_APMOEMEVENT:
376 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
380 case PBT_APMRESUMEAUTOMATIC:
381 /* This is the message delivered once all devices are up */
382 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
383 powerStateSuspended = 0;
384 if (osVersion.dwMajorVersion >= 6) {
385 smb_SetLanAdapterChangeDetected();
390 afsi_log("SERVICE_CONTROL_unknown");
396 case SERVICE_CONTROL_CUSTOM_DUMP:
398 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
399 GenerateMiniDump(NULL);
403 } /* end switch(ctrlCode) */
407 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
409 * Mount a drive into AFS if there global mapping
411 /* DEE Could check first if we are run as SYSTEM */
412 #define MAX_RETRIES 10
413 #define MAX_DRIVES 23
414 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
416 char szAfsPath[_MAX_PATH];
417 char szDriveToMapTo[5];
421 DWORD dwIndex = 0, dwRetry = 0;
423 DWORD dwSubMountSize;
424 char szSubMount[256];
427 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
429 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
430 if (dwResult != ERROR_SUCCESS)
433 while (dwIndex < MAX_DRIVES) {
434 dwDriveSize = sizeof(szDriveToMapTo);
435 dwSubMountSize = sizeof(szSubMount);
436 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
437 if (dwResult != ERROR_MORE_DATA) {
438 if (dwResult != ERROR_SUCCESS) {
439 if (dwResult != ERROR_NO_MORE_ITEMS)
440 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
445 for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
448 memset (&nr, 0x00, sizeof(NETRESOURCE));
450 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
452 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
453 nr.dwType=RESOURCETYPE_DISK;
454 nr.lpLocalName=szDriveToMapTo;
455 nr.lpRemoteName=szAfsPath;
456 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
457 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
459 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
460 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
461 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
462 if (dwResult == NO_ERROR) {
465 /* wait for smb server to come up */
466 Sleep((DWORD)1000 /* miliseconds */);
468 /* Disconnect any previous mappings */
469 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
477 static HANDLE hThreadMountGlobalDrives = NULL;
479 static void MountGlobalDrives()
483 hThreadMountGlobalDrives = CreateThread(NULL, 0, MountGlobalDrivesThread, 0, 0, &tid);
485 if ( hThreadMountGlobalDrives ) {
486 DWORD rc = WaitForSingleObject( hThreadMountGlobalDrives, 15000 );
487 if (rc == WAIT_TIMEOUT) {
488 afsi_log("GlobalAutoMap thread failed to complete after 15 seconds");
489 } else if (rc == WAIT_OBJECT_0) {
490 afsi_log("GlobalAutoMap thread completed");
491 CloseHandle( hThreadMountGlobalDrives );
492 hThreadMountGlobalDrives = NULL;
497 static void DismountGlobalDrives()
499 char szAfsPath[_MAX_PATH];
500 char szDriveToMapTo[5];
502 DWORD dwSubMountSize;
503 char szSubMount[256];
510 if ( hThreadMountGlobalDrives ) {
511 DWORD rc = WaitForSingleObject(hThreadMountGlobalDrives, 0);
513 if (rc == WAIT_TIMEOUT) {
514 afsi_log("GlobalAutoMap thread failed to complete before service shutdown");
516 else if (rc == WAIT_OBJECT_0) {
517 afsi_log("GlobalAutoMap thread completed");
518 CloseHandle( hThreadMountGlobalDrives );
519 hThreadMountGlobalDrives = NULL;
523 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
525 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
526 if (dwResult != ERROR_SUCCESS)
529 while (dwIndex < MAX_DRIVES) {
530 dwDriveSize = sizeof(szDriveToMapTo);
531 dwSubMountSize = sizeof(szSubMount);
532 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
533 if (dwResult != ERROR_MORE_DATA) {
534 if (dwResult != ERROR_SUCCESS) {
535 if (dwResult != ERROR_NO_MORE_ITEMS)
536 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
541 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
543 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
544 dwResult = WNetCancelConnection(szAfsPath, TRUE);
546 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
553 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
555 DWORD dwVersionHandle;
556 LPVOID pVersionInfo = 0;
558 LPDWORD pLangInfo = 0;
559 LPTSTR szVersion = 0;
561 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
562 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
565 afsi_log("GetFileVersionInfoSize failed");
566 return GetLastError();
569 pVersionInfo = malloc(size);
571 afsi_log("out of memory 1");
572 return ERROR_NOT_ENOUGH_MEMORY;
575 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
576 if (retval = GetLastError())
578 afsi_log("GetFileVersionInfo failed: %d", retval);
582 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
583 (LPVOID*)&pLangInfo, &len);
584 if (retval = GetLastError())
586 afsi_log("VerQueryValue 1 failed: %d", retval);
591 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
592 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
594 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
595 if (retval = GetLastError())
597 /* try again with language 409 since the old binaries were tagged wrong */
599 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
602 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
603 if (retval = GetLastError()) {
604 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
608 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
609 szOutput[dwOutput - 1] = 0;
618 static HINSTANCE hCrypt32;
619 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
620 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
621 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
622 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
623 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
624 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
625 HCRYPTMSG* phMsg, const void** ppvContext);
626 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
627 void* pvData, DWORD* pcbData);
628 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
629 DWORD dwFindFlags, DWORD dwFindType,
630 const void* pvFindPara,
631 PCCERT_CONTEXT pPrevCertContext);
632 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
633 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
634 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
635 PCERT_INFO pCertId2);
636 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
638 void LoadCrypt32(void)
640 hCrypt32 = LoadLibrary("crypt32");
644 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
645 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
646 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
647 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
648 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
649 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
650 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
651 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
653 if ( !pCertGetNameString ||
654 !pCryptQueryObject ||
655 !pCryptMsgGetParam ||
656 !pCertFindCertificateInStore ||
659 !pCertCompareCertificate ||
660 !pCertFreeCertificateContext)
662 FreeLibrary(hCrypt32);
667 void UnloadCrypt32(void)
669 FreeLibrary(hCrypt32);
672 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
674 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
676 wchar_t wfilename[260];
682 HCERTSTORE hStore = NULL;
683 HCRYPTMSG hMsg = NULL;
684 PCMSG_SIGNER_INFO pSignerInfo = NULL;
685 PCCERT_CONTEXT pCertContext = NULL;
688 if ( hCrypt32 == NULL )
691 ZeroMemory(&CertInfo, sizeof(CertInfo));
692 mbstowcs(wfilename, filename, 260);
694 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
696 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
697 CERT_QUERY_FORMAT_FLAG_BINARY,
707 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
713 fResult = pCryptMsgGetParam(hMsg,
714 CMSG_SIGNER_INFO_PARAM,
720 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
726 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
728 fResult = pCryptMsgGetParam(hMsg,
729 CMSG_SIGNER_INFO_PARAM,
735 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
741 CertInfo.Issuer = pSignerInfo->Issuer;
742 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
744 pCertContext = pCertFindCertificateInStore(hStore,
747 CERT_FIND_SUBJECT_CERT,
752 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
760 LocalFree(pSignerInfo);
763 CertFreeCertificateContext(pCertContext);*/
766 pCertCloseStore(hStore,0);
769 pCryptMsgClose(hMsg);
774 BOOL VerifyTrust(CHAR * filename)
776 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
777 WIN_TRUST_SUBJECT_FILE fSubjectFile;
778 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
779 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
780 wchar_t wfilename[260];
782 BOOL success = FALSE;
784 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
787 if (filename == NULL )
790 hWinTrust = LoadLibrary("wintrust");
794 if (((FARPROC) pWinVerifyTrust =
795 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
797 FreeLibrary(hWinTrust);
801 mbstowcs(wfilename, filename, 260);
803 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
805 fSubjectFile.lpPath = wfilename;
806 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
807 FALSE, GetCurrentProcessId());
808 fContextWSubject.SubjectType = &subject;
809 fContextWSubject.Subject = &fSubjectFile;
811 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
813 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
814 CloseHandle( fSubjectFile.hFile );
815 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
816 CloseHandle( fContextWSubject.hClientToken );
818 if (ret == ERROR_SUCCESS) {
821 DWORD gle = GetLastError();
823 case TRUST_E_PROVIDER_UNKNOWN:
824 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
826 case TRUST_E_NOSIGNATURE:
827 afsi_log("VerifyTrust failed: Unsigned executable");
829 case TRUST_E_EXPLICIT_DISTRUST:
830 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
832 case TRUST_E_SUBJECT_NOT_TRUSTED:
833 afsi_log("VerifyTrust failed: File is not trusted");
835 case TRUST_E_BAD_DIGEST:
836 afsi_log("VerifyTrust failed: Executable has been modified");
838 case CRYPT_E_SECURITY_SETTINGS:
839 afsi_log("VerifyTrust failed: local security options prevent verification");
842 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
846 FreeLibrary(hWinTrust);
850 void LogCertCtx(PCCERT_CONTEXT pCtx) {
852 LPTSTR szName = NULL;
854 if ( hCrypt32 == NULL )
857 // Get Issuer name size.
858 if (!(dwData = pCertGetNameString(pCtx,
859 CERT_NAME_SIMPLE_DISPLAY_TYPE,
860 CERT_NAME_ISSUER_FLAG,
864 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
868 // Allocate memory for Issuer name.
869 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
872 if (!(pCertGetNameString(pCtx,
873 CERT_NAME_SIMPLE_DISPLAY_TYPE,
874 CERT_NAME_ISSUER_FLAG,
878 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
882 // print Issuer name.
883 afsi_log("Issuer Name: %s", szName);
887 // Get Subject name size.
888 if (!(dwData = pCertGetNameString(pCtx,
889 CERT_NAME_SIMPLE_DISPLAY_TYPE,
894 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
898 // Allocate memory for subject name.
899 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
902 if (!(pCertGetNameString(pCtx,
903 CERT_NAME_SIMPLE_DISPLAY_TYPE,
908 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
912 // Print Subject Name.
913 afsi_log("Subject Name: %s", szName);
921 BOOL AFSModulesVerify(void)
924 CHAR afsdVersion[128];
925 CHAR modVersion[128];
926 CHAR checkName[1024];
927 BOOL trustVerified = FALSE;
933 PCCERT_CONTEXT pCtxService = NULL;
935 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
936 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
937 DWORD dummyLen, code;
938 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
939 DWORD verifyServiceSig = TRUE;
942 hPSAPI = LoadLibrary("psapi");
944 if ( hPSAPI == NULL )
947 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
950 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
953 afsi_log("%s version %s", filename, afsdVersion);
955 if (((FARPROC) pGetModuleFileNameExA =
956 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
957 ((FARPROC) pEnumProcessModules =
958 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
965 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
966 AFSREG_CLT_SVC_PARAM_SUBKEY,
967 0, KEY_QUERY_VALUE, &parmKey);
968 if (code == ERROR_SUCCESS) {
969 dummyLen = sizeof(cacheSize);
970 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
971 (BYTE *) &cacheSize, &dummyLen);
972 RegCloseKey (parmKey);
975 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
976 0, KEY_QUERY_VALUE, &parmKey);
977 if (code == ERROR_SUCCESS) {
978 dummyLen = sizeof(verifyServiceSig);
979 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
980 (BYTE *) &verifyServiceSig, &dummyLen);
981 RegCloseKey (parmKey);
986 && cacheSize < 716800
989 trustVerified = VerifyTrust(filename);
991 afsi_log("Signature Verification disabled");
997 // get a certificate context for the signer of afsd_service.
998 pCtxService = GetCertCtx(filename);
1000 LogCertCtx(pCtxService);
1003 // Get a list of all the modules in this process.
1004 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
1005 FALSE, GetCurrentProcessId());
1007 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
1009 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
1011 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
1013 char szModName[2048];
1015 // Get the full path to the module's file.
1016 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
1018 lstrcpy(checkName, szModName);
1021 if ( strstr(checkName, "afspthread.dll") ||
1022 strstr(checkName, "afsauthent.dll") ||
1023 strstr(checkName, "afsrpc.dll") ||
1024 strstr(checkName, "libafsconf.dll") ||
1025 strstr(checkName, "libosi.dll") )
1027 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1032 afsi_log("%s version %s", szModName, modVersion);
1033 if (strcmp(afsdVersion,modVersion)) {
1034 afsi_log("Version mismatch: %s", szModName);
1037 if ( trustVerified ) {
1038 if ( !VerifyTrust(szModName) ) {
1039 afsi_log("Signature Verification failed: %s", szModName);
1042 else if (pCtxService) {
1043 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1045 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1046 pCtxService->pCertInfo,
1048 afsi_log("Certificate mismatch: %s", szModName);
1056 pCertFreeCertificateContext(pCtx);
1065 pCertFreeCertificateContext(pCtxService);
1069 FreeLibrary(hPSAPI);
1071 CloseHandle(hProcess);
1076 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1079 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1080 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1082 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1083 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1086 afsd_Main(DWORD argc, LPTSTR *argv)
1097 afsd_DbgBreakAllocInit();
1098 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1099 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1102 afsd_SetUnhandledExceptionFilter();
1104 osi_InitPanic(afsd_notifier);
1105 osi_InitTraceOption();
1111 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1112 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1113 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1116 hAdvApi32 = LoadLibrary("advapi32.dll");
1117 if (hAdvApi32 == NULL)
1119 afsi_log("Fatal: cannot load advapi32.dll");
1123 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1124 if (pRegisterServiceCtrlHandlerEx)
1126 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1127 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1131 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1134 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1135 ServiceStatus.dwServiceSpecificExitCode = 0;
1136 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1137 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1138 ServiceStatus.dwCheckPoint = 1;
1139 ServiceStatus.dwWaitHint = 120000;
1140 /* accept Power Events */
1141 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1142 SetServiceStatus(StatusHandle, &ServiceStatus);
1145 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
1147 #ifdef REGISTER_POWER_NOTIFICATIONS
1154 /* see if we should handle power notifications */
1155 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1156 0, KEY_QUERY_VALUE, &hkParm);
1157 if (code == ERROR_SUCCESS) {
1158 dummyLen = sizeof(bpower);
1159 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1160 (BYTE *) &bpower, &dummyLen);
1162 if(code != ERROR_SUCCESS)
1165 RegCloseKey(hkParm);
1167 /* create thread used to flush cache */
1169 PowerNotificationThreadCreate();
1170 powerEventsRegistered = 1;
1175 /* Verify the versions of the DLLs which were loaded */
1176 if (!AFSModulesVerify()) {
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 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
1186 /* exit if initialization failed */
1190 /* allow an exit to be called prior to any initialization */
1191 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1195 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1198 hookRc = initHook();
1200 FreeLibrary(hHookDll);
1203 if (hookRc == FALSE)
1205 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1206 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1207 ServiceStatus.dwCheckPoint = 0;
1208 ServiceStatus.dwWaitHint = 0;
1209 ServiceStatus.dwControlsAccepted = 0;
1210 SetServiceStatus(StatusHandle, &ServiceStatus);
1212 /* exit if initialization failed */
1217 /* allow another 120 seconds to start */
1218 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1219 ServiceStatus.dwServiceSpecificExitCode = 0;
1220 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1221 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1222 ServiceStatus.dwCheckPoint = 2;
1223 ServiceStatus.dwWaitHint = 120000;
1224 /* accept Power Events */
1225 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1226 SetServiceStatus(StatusHandle, &ServiceStatus);
1230 /* Perform Volume Status Notification Initialization */
1231 cm_VolStatus_Initialization();
1234 MainThreadId = GetCurrentThreadId();
1235 jmpret = setjmp(notifier_jmp);
1240 code = afsd_InitCM(&reason);
1242 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1243 osi_panic(reason, __FILE__, __LINE__);
1247 ServiceStatus.dwCheckPoint = 3;
1248 ServiceStatus.dwWaitHint = 30000;
1249 SetServiceStatus(StatusHandle, &ServiceStatus);
1251 code = afsd_InitDaemons(&reason);
1253 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1254 osi_panic(reason, __FILE__, __LINE__);
1257 /* allow an exit to be called post rx initialization */
1258 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1262 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1265 hookRc = rxStartedHook();
1267 FreeLibrary(hHookDll);
1270 if (hookRc == FALSE)
1272 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1273 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1274 ServiceStatus.dwCheckPoint = 0;
1275 ServiceStatus.dwWaitHint = 0;
1276 ServiceStatus.dwControlsAccepted = 0;
1277 SetServiceStatus(StatusHandle, &ServiceStatus);
1279 /* exit if initialization failed */
1285 ServiceStatus.dwCheckPoint = 4;
1286 ServiceStatus.dwWaitHint = 15000;
1287 SetServiceStatus(StatusHandle, &ServiceStatus);
1290 /* Notify any volume status handlers that the cache manager has started */
1291 cm_VolStatus_Service_Started();
1293 /* the following ifdef chooses the mode of operation for the service. to enable
1294 * a runtime flag (instead of compile-time), pioctl() would need to dynamically
1295 * determine the mode, in order to use the correct ioctl special-file path. */
1296 code = afsd_InitSMB(&reason, MessageBox);
1298 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1299 osi_panic(reason, __FILE__, __LINE__);
1302 /* allow an exit to be called post smb initialization */
1303 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1307 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1310 hookRc = smbStartedHook();
1312 FreeLibrary(hHookDll);
1315 if (hookRc == FALSE)
1317 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1318 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1319 ServiceStatus.dwCheckPoint = 0;
1320 ServiceStatus.dwWaitHint = 0;
1321 ServiceStatus.dwControlsAccepted = 0;
1322 SetServiceStatus(StatusHandle, &ServiceStatus);
1324 /* exit if initialization failed */
1329 MountGlobalDrives();
1332 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1333 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1334 ServiceStatus.dwCheckPoint = 5;
1335 ServiceStatus.dwWaitHint = 0;
1337 /* accept Power events */
1338 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1339 SetServiceStatus(StatusHandle, &ServiceStatus);
1342 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
1345 /* allow an exit to be called when started */
1346 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1350 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1353 hookRc = startedHook();
1355 FreeLibrary(hHookDll);
1358 if (hookRc == FALSE)
1360 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1361 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1362 ServiceStatus.dwCheckPoint = 0;
1363 ServiceStatus.dwWaitHint = 0;
1364 ServiceStatus.dwControlsAccepted = 0;
1365 SetServiceStatus(StatusHandle, &ServiceStatus);
1367 /* exit if initialization failed */
1372 WaitForSingleObject(WaitToTerminate, INFINITE);
1374 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
1375 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1376 ServiceStatus.dwCheckPoint = 6;
1377 ServiceStatus.dwWaitHint = 120000;
1378 ServiceStatus.dwControlsAccepted = 0;
1379 SetServiceStatus(StatusHandle, &ServiceStatus);
1381 afsi_log("Received Termination Signal, Stopping Service");
1384 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP);
1386 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
1388 /* allow an exit to be called prior to stopping the service */
1389 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1393 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1396 hookRc = stoppingHook();
1398 FreeLibrary(hHookDll);
1403 #ifdef AFS_FREELANCE_CLIENT
1404 cm_FreelanceShutdown();
1405 afsi_log("Freelance Shutdown complete");
1408 DismountGlobalDrives();
1409 afsi_log("Global Drives dismounted");
1411 cm_DaemonShutdown();
1412 afsi_log("Daemon shutdown complete");
1417 afsi_log("Buffer shutdown complete");
1420 afsi_log("rx finalization complete");
1423 afsi_log("smb shutdown complete");
1427 cm_ReleaseAllLocks();
1430 afsi_log("rx finalization complete");
1432 cm_ShutdownMappedMemory();
1434 #ifdef REGISTER_POWER_NOTIFICATIONS
1435 /* terminate thread used to flush cache */
1436 if (powerEventsRegistered)
1437 PowerNotificationThreadExit();
1442 cm_BPlusDumpStats();
1445 /* Notify any Volume Status Handlers that we are stopped */
1446 cm_VolStatus_Service_Stopped();
1448 /* Cleanup any Volume Status Notification Handler */
1449 cm_VolStatus_Finalize();
1451 /* allow an exit to be called after stopping the service */
1452 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1456 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1459 hookRc = stoppedHook();
1461 FreeLibrary(hHookDll);
1465 /* Remove the ExceptionFilter */
1466 SetUnhandledExceptionFilter(NULL);
1468 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1469 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1470 ServiceStatus.dwCheckPoint = 7;
1471 ServiceStatus.dwWaitHint = 0;
1472 ServiceStatus.dwControlsAccepted = 0;
1473 SetServiceStatus(StatusHandle, &ServiceStatus);
1476 DWORD __stdcall afsdMain_thread(void* notUsed)
1478 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1479 afsd_Main(1, (LPTSTR*)argv);
1485 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1489 main(int argc, char * argv[])
1491 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1492 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1497 for (i = 1; i < argc; i++) {
1498 if (!stricmp(argv[i],"--validate-cache")) {
1499 if (++i != argc - 1) {
1504 return cm_ValidateMappedMemory(argv[i]);
1511 if (!StartServiceCtrlDispatcher(dispatchTable))
1513 LONG status = GetLastError();
1514 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1517 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1519 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1521 SetEvent(WaitToTerminate);
1525 if ( hAFSDMainThread ) {
1526 WaitForSingleObject( hAFSDMainThread, INFINITE );
1527 CloseHandle( hAFSDMainThread );