11 #include "afsd_init.h"
12 #include "lanahelper.h"
16 #include <WINNT\afsreg.h>
28 //#define REGISTER_POWER_NOTIFICATIONS 1
29 #include "afsd_flushvol.h"
31 extern void afsi_log(char *pattern, ...);
33 static SERVICE_STATUS ServiceStatus;
34 static SERVICE_STATUS_HANDLE StatusHandle;
36 HANDLE hAFSDMainThread = NULL;
38 HANDLE hAFSDWorkerThread[WORKER_THREADS];
41 HANDLE WaitToTerminate;
43 static int GlobalStatus;
46 unsigned int MainThreadId;
50 extern int traceOnPanic;
51 extern HANDLE afsi_file;
53 static int powerEventsRegistered = 0;
54 extern int powerStateSuspended = 0;
57 * Notifier function for use by osi_panic
59 static void afsd_notifier(char *msgp, char *filep, long line)
66 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION,
69 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG, msgp);
73 osi_LogEnable(afsd_logp);
75 afsd_ForceTrace(TRUE);
78 afsi_log("--- begin dump ---");
79 cm_DumpSCache(afsi_file, "a", 0);
81 cm_dnlcDump(afsi_file, "a");
83 cm_DumpBufHashTable(afsi_file, "a", 0);
84 smb_DumpVCP(afsi_file, "a", 0);
85 afsi_log("--- end dump ---");
88 if (IsDebuggerPresent())
92 SetEvent(WaitToTerminate);
94 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
95 for (i = 0; i < WORKER_THREADS; i++)
96 CloseHandle(hAFSDWorkerThread[i]);
100 if (GetCurrentThreadId() == MainThreadId)
101 longjmp(notifier_jmp, 1);
104 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
105 ServiceStatus.dwWin32ExitCode = NO_ERROR;
106 ServiceStatus.dwCheckPoint = 0;
107 ServiceStatus.dwWaitHint = 0;
108 ServiceStatus.dwControlsAccepted = 0;
109 SetServiceStatus(StatusHandle, &ServiceStatus);
115 * For use miscellaneously in smb.c; need to do better
117 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
123 afsd_ServiceFlushVolume(DWORD dwlpEventData)
125 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
128 ** If UI bit is not set, user interaction is not possible
129 ** BUT, since we are a NON-interactive service, and therefore
130 ** have NO user I/O, it doesn't much matter.
131 ** This benign code left here as example of how to find this out
133 BOOL bUI = (dwlpEventData & 1);
136 if ( PowerNotificationThreadNotify() )
142 /* flush was unsuccessful, or timeout - deny shutdown */
143 dwRet = ERROR_NETWORK_BUSY;
146 /* to deny hibernate, simply return
147 // any value besides NO_ERROR.
149 // dwRet = ERROR_NETWORK_BUSY;
156 /* service control handler used in nt4 only for backward compat. */
158 afsd_ServiceControlHandler(DWORD ctrlCode)
161 DWORD dummyLen, doTrace;
165 case SERVICE_CONTROL_SHUTDOWN:
166 case SERVICE_CONTROL_STOP:
167 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
168 ServiceStatus.dwWin32ExitCode = NO_ERROR;
169 ServiceStatus.dwCheckPoint = 1;
170 ServiceStatus.dwWaitHint = 30000;
171 ServiceStatus.dwControlsAccepted = 0;
172 SetServiceStatus(StatusHandle, &ServiceStatus);
174 if (ctrlCode == SERVICE_CONTROL_STOP)
175 afsi_log("SERVICE_CONTROL_STOP");
177 afsi_log("SERVICE_CONTROL_SHUTDOWN");
179 /* Write all dirty buffers back to server */
180 if ( !lana_OnlyLoopback() )
183 /* Force trace if requested */
184 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
185 AFSREG_CLT_SVC_PARAM_SUBKEY,
186 0, KEY_QUERY_VALUE, &parmKey);
187 if (code != ERROR_SUCCESS)
190 dummyLen = sizeof(doTrace);
191 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
193 (BYTE *) &doTrace, &dummyLen);
194 RegCloseKey (parmKey);
195 if (code != ERROR_SUCCESS)
198 afsd_ForceTrace(FALSE);
199 buf_ForceTrace(FALSE);
203 SetEvent(WaitToTerminate);
206 case SERVICE_CONTROL_INTERROGATE:
207 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
208 ServiceStatus.dwWin32ExitCode = NO_ERROR;
209 ServiceStatus.dwCheckPoint = 0;
210 ServiceStatus.dwWaitHint = 0;
211 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
212 SetServiceStatus(StatusHandle, &ServiceStatus);
214 /* XXX handle system shutdown */
215 /* XXX handle pause & continue */
221 ** Extended ServiceControlHandler that provides Event types
222 ** for monitoring Power events, for example.
225 afsd_ServiceControlHandlerEx(
233 DWORD dummyLen, doTrace;
235 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
236 OSVERSIONINFO osVersion;
238 /* Get the version of Windows */
239 memset(&osVersion, 0x00, sizeof(osVersion));
240 osVersion.dwOSVersionInfoSize = sizeof(osVersion);
241 GetVersionEx(&osVersion);
245 case SERVICE_CONTROL_SHUTDOWN:
246 case SERVICE_CONTROL_STOP:
247 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
248 ServiceStatus.dwWin32ExitCode = NO_ERROR;
249 ServiceStatus.dwCheckPoint = 1;
250 ServiceStatus.dwWaitHint = 30000;
251 ServiceStatus.dwControlsAccepted = 0;
252 SetServiceStatus(StatusHandle, &ServiceStatus);
254 /* Write all dirty buffers back to server */
255 if ( !lana_OnlyLoopback() )
258 /* Force trace if requested */
259 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
260 AFSREG_CLT_SVC_PARAM_SUBKEY,
261 0, KEY_QUERY_VALUE, &parmKey);
262 if (code != ERROR_SUCCESS)
265 dummyLen = sizeof(doTrace);
266 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
268 (BYTE *) &doTrace, &dummyLen);
269 RegCloseKey (parmKey);
270 if (code != ERROR_SUCCESS)
273 afsd_ForceTrace(FALSE);
274 buf_ForceTrace(FALSE);
278 SetEvent(WaitToTerminate);
282 case SERVICE_CONTROL_INTERROGATE:
283 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
284 ServiceStatus.dwWin32ExitCode = NO_ERROR;
285 ServiceStatus.dwCheckPoint = 0;
286 ServiceStatus.dwWaitHint = 0;
287 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
288 SetServiceStatus(StatusHandle, &ServiceStatus);
289 afsi_log("SERVICE_CONTROL_INTERROGATE");
293 /* XXX handle system shutdown */
294 /* XXX handle pause & continue */
295 case SERVICE_CONTROL_POWEREVENT:
298 afsi_log("SERVICE_CONTROL_POWEREVENT");
301 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
302 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
303 ** Return any error code to deny request,
304 ** i.e. as if returning BROADCAST_QUERY_DENY
306 if (powerEventsRegistered) {
307 switch((int) dwEventType)
309 case PBT_APMQUERYSUSPEND:
310 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
311 /* Write all dirty buffers back to server */
312 if ( !lana_OnlyLoopback() )
314 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
317 case PBT_APMQUERYSTANDBY:
318 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
319 /* Write all dirty buffers back to server */
320 if ( !lana_OnlyLoopback() )
322 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
326 /* allow remaining case PBT_WhatEver */
328 afsi_log("SERVICE_CONTROL_APMSUSPEND");
329 powerStateSuspended = 1;
330 if (osVersion.dwMajorVersion >= 6)
335 afsi_log("SERVICE_CONTROL_APMSTANDBY");
336 powerStateSuspended = 1;
337 if (osVersion.dwMajorVersion >= 6)
341 case PBT_APMRESUMECRITICAL:
342 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
343 if (osVersion.dwMajorVersion >= 6)
344 smb_RestartListeners();
347 case PBT_APMRESUMESUSPEND:
348 /* User logged in after suspend */
349 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
352 case PBT_APMRESUMESTANDBY:
353 /* User logged in after standby */
354 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
357 case PBT_APMBATTERYLOW:
358 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
361 case PBT_APMPOWERSTATUSCHANGE:
363 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
367 case PBT_APMOEMEVENT:
369 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
373 case PBT_APMRESUMEAUTOMATIC:
374 /* This is the message delivered once all devices are up */
375 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
376 powerStateSuspended = 0;
377 if (osVersion.dwMajorVersion >= 6)
378 smb_RestartListeners();
382 afsi_log("SERVICE_CONTROL_unknown");
388 case SERVICE_CONTROL_CUSTOM_DUMP:
390 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
391 GenerateMiniDump(NULL);
395 } /* end switch(ctrlCode) */
399 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
401 * Mount a drive into AFS if there global mapping
403 /* DEE Could check first if we are run as SYSTEM */
404 #define MAX_RETRIES 10
405 #define MAX_DRIVES 23
406 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
409 char szAfsPath[_MAX_PATH];
411 char szDriveToMapTo[5];
415 DWORD dwIndex = 0, dwRetry = 0;
417 DWORD dwSubMountSize;
418 char szSubMount[256];
421 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
423 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
424 if (dwResult != ERROR_SUCCESS)
427 while (dwIndex < MAX_DRIVES) {
428 dwDriveSize = sizeof(szDriveToMapTo);
429 dwSubMountSize = sizeof(szSubMount);
430 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
431 if (dwResult != ERROR_MORE_DATA) {
432 if (dwResult != ERROR_SUCCESS) {
433 if (dwResult != ERROR_NO_MORE_ITEMS)
434 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
440 for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
443 memset (&nr, 0x00, sizeof(NETRESOURCE));
445 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
447 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
448 nr.dwType=RESOURCETYPE_DISK;
449 nr.lpLocalName=szDriveToMapTo;
450 nr.lpRemoteName=szAfsPath;
451 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
452 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
454 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
455 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
456 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
457 if (dwResult == NO_ERROR) {
460 /* wait for smb server to come up */
461 Sleep((DWORD)1000 /* miliseconds */);
463 /* Disconnect any previous mappings */
464 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
467 /* FIXFIX: implement */
468 afsi_log("GlobalAutoMap of %s to %s not implemented", szDriveToMapTo, szSubMount);
476 static HANDLE hThreadMountGlobalDrives = NULL;
478 static void MountGlobalDrives()
482 hThreadMountGlobalDrives = CreateThread(NULL, 0, MountGlobalDrivesThread, 0, 0, &tid);
484 if ( hThreadMountGlobalDrives ) {
485 DWORD rc = WaitForSingleObject( hThreadMountGlobalDrives, 15000 );
486 if (rc == WAIT_TIMEOUT) {
487 afsi_log("GlobalAutoMap thread failed to complete after 15 seconds");
488 } else if (rc == WAIT_OBJECT_0) {
489 afsi_log("GlobalAutoMap thread completed");
490 CloseHandle( hThreadMountGlobalDrives );
491 hThreadMountGlobalDrives = NULL;
496 static void DismountGlobalDrives()
499 char szAfsPath[_MAX_PATH];
500 char szDriveToMapTo[5];
502 DWORD dwSubMountSize;
503 char szSubMount[256];
511 if ( hThreadMountGlobalDrives ) {
512 DWORD rc = WaitForSingleObject(hThreadMountGlobalDrives, 0);
514 if (rc == WAIT_TIMEOUT) {
515 afsi_log("GlobalAutoMap thread failed to complete before service shutdown");
517 else if (rc == WAIT_OBJECT_0) {
518 afsi_log("GlobalAutoMap thread completed");
519 CloseHandle( hThreadMountGlobalDrives );
520 hThreadMountGlobalDrives = NULL;
524 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
526 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
527 if (dwResult != ERROR_SUCCESS)
531 /* FIXFIX: implement */
533 while (dwIndex < MAX_DRIVES) {
534 dwDriveSize = sizeof(szDriveToMapTo);
535 dwSubMountSize = sizeof(szSubMount);
536 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
537 if (dwResult != ERROR_MORE_DATA) {
538 if (dwResult != ERROR_SUCCESS) {
539 if (dwResult != ERROR_NO_MORE_ITEMS)
540 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
545 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
547 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
548 dwResult = WNetCancelConnection(szAfsPath, TRUE);
550 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
558 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
560 DWORD dwVersionHandle;
561 LPVOID pVersionInfo = 0;
563 LPDWORD pLangInfo = 0;
564 LPTSTR szVersion = 0;
566 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
567 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
570 afsi_log("GetFileVersionInfoSize failed");
571 return GetLastError();
574 pVersionInfo = malloc(size);
576 afsi_log("out of memory 1");
577 return ERROR_NOT_ENOUGH_MEMORY;
580 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
581 if (retval = GetLastError())
583 afsi_log("GetFileVersionInfo failed: %d", retval);
587 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
588 (LPVOID*)&pLangInfo, &len);
589 if (retval = GetLastError())
591 afsi_log("VerQueryValue 1 failed: %d", retval);
596 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
597 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
599 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
600 if (retval = GetLastError())
602 /* try again with language 409 since the old binaries were tagged wrong */
604 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
607 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
608 if (retval = GetLastError()) {
609 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
613 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
614 szOutput[dwOutput - 1] = 0;
623 static HINSTANCE hCrypt32;
624 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
625 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
626 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
627 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
628 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
629 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
630 HCRYPTMSG* phMsg, const void** ppvContext);
631 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
632 void* pvData, DWORD* pcbData);
633 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
634 DWORD dwFindFlags, DWORD dwFindType,
635 const void* pvFindPara,
636 PCCERT_CONTEXT pPrevCertContext);
637 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
638 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
639 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
640 PCERT_INFO pCertId2);
641 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
643 void LoadCrypt32(void)
645 hCrypt32 = LoadLibrary("crypt32");
649 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
650 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
651 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
652 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
653 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
654 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
655 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
656 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
658 if ( !pCertGetNameString ||
659 !pCryptQueryObject ||
660 !pCryptMsgGetParam ||
661 !pCertFindCertificateInStore ||
664 !pCertCompareCertificate ||
665 !pCertFreeCertificateContext)
667 FreeLibrary(hCrypt32);
672 void UnloadCrypt32(void)
674 FreeLibrary(hCrypt32);
677 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
679 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
681 wchar_t wfilename[260];
687 HCERTSTORE hStore = NULL;
688 HCRYPTMSG hMsg = NULL;
689 PCMSG_SIGNER_INFO pSignerInfo = NULL;
690 PCCERT_CONTEXT pCertContext = NULL;
693 if ( hCrypt32 == NULL )
696 ZeroMemory(&CertInfo, sizeof(CertInfo));
697 mbstowcs(wfilename, filename, 260);
699 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
701 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
702 CERT_QUERY_FORMAT_FLAG_BINARY,
712 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
718 fResult = pCryptMsgGetParam(hMsg,
719 CMSG_SIGNER_INFO_PARAM,
725 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
731 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
733 fResult = pCryptMsgGetParam(hMsg,
734 CMSG_SIGNER_INFO_PARAM,
740 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
746 CertInfo.Issuer = pSignerInfo->Issuer;
747 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
749 pCertContext = pCertFindCertificateInStore(hStore,
752 CERT_FIND_SUBJECT_CERT,
757 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
765 LocalFree(pSignerInfo);
768 CertFreeCertificateContext(pCertContext);*/
771 pCertCloseStore(hStore,0);
774 pCryptMsgClose(hMsg);
779 BOOL VerifyTrust(CHAR * filename)
781 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
782 WIN_TRUST_SUBJECT_FILE fSubjectFile;
783 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
784 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
785 wchar_t wfilename[260];
787 BOOL success = FALSE;
789 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
792 if (filename == NULL )
795 hWinTrust = LoadLibrary("wintrust");
799 if (((FARPROC) pWinVerifyTrust =
800 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
802 FreeLibrary(hWinTrust);
806 mbstowcs(wfilename, filename, 260);
808 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
810 fSubjectFile.lpPath = wfilename;
811 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
812 FALSE, GetCurrentProcessId());
813 fContextWSubject.SubjectType = &subject;
814 fContextWSubject.Subject = &fSubjectFile;
816 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
818 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
819 CloseHandle( fSubjectFile.hFile );
820 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
821 CloseHandle( fContextWSubject.hClientToken );
823 if (ret == ERROR_SUCCESS) {
826 DWORD gle = GetLastError();
828 case TRUST_E_PROVIDER_UNKNOWN:
829 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
831 case TRUST_E_NOSIGNATURE:
832 afsi_log("VerifyTrust failed: Unsigned executable");
834 case TRUST_E_EXPLICIT_DISTRUST:
835 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
837 case TRUST_E_SUBJECT_NOT_TRUSTED:
838 afsi_log("VerifyTrust failed: File is not trusted");
840 case TRUST_E_BAD_DIGEST:
841 afsi_log("VerifyTrust failed: Executable has been modified");
843 case CRYPT_E_SECURITY_SETTINGS:
844 afsi_log("VerifyTrust failed: local security options prevent verification");
847 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
851 FreeLibrary(hWinTrust);
855 void LogCertCtx(PCCERT_CONTEXT pCtx) {
857 LPTSTR szName = NULL;
859 if ( hCrypt32 == NULL )
862 // Get Issuer name size.
863 if (!(dwData = pCertGetNameString(pCtx,
864 CERT_NAME_SIMPLE_DISPLAY_TYPE,
865 CERT_NAME_ISSUER_FLAG,
869 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
873 // Allocate memory for Issuer name.
874 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
877 if (!(pCertGetNameString(pCtx,
878 CERT_NAME_SIMPLE_DISPLAY_TYPE,
879 CERT_NAME_ISSUER_FLAG,
883 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
887 // print Issuer name.
888 afsi_log("Issuer Name: %s", szName);
892 // Get Subject name size.
893 if (!(dwData = pCertGetNameString(pCtx,
894 CERT_NAME_SIMPLE_DISPLAY_TYPE,
899 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
903 // Allocate memory for subject name.
904 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
907 if (!(pCertGetNameString(pCtx,
908 CERT_NAME_SIMPLE_DISPLAY_TYPE,
913 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
917 // Print Subject Name.
918 afsi_log("Subject Name: %s", szName);
926 BOOL AFSModulesVerify(void)
929 CHAR afsdVersion[128];
930 CHAR modVersion[128];
931 CHAR checkName[1024];
932 BOOL trustVerified = FALSE;
938 PCCERT_CONTEXT pCtxService = NULL;
940 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
941 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
942 DWORD dummyLen, code;
943 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
944 DWORD verifyServiceSig = TRUE;
947 hPSAPI = LoadLibrary("psapi");
949 if ( hPSAPI == NULL )
952 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
955 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
958 afsi_log("%s version %s", filename, afsdVersion);
960 if (((FARPROC) pGetModuleFileNameExA =
961 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
962 ((FARPROC) pEnumProcessModules =
963 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
970 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
971 AFSREG_CLT_SVC_PARAM_SUBKEY,
972 0, KEY_QUERY_VALUE, &parmKey);
973 if (code == ERROR_SUCCESS) {
974 dummyLen = sizeof(cacheSize);
975 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
976 (BYTE *) &cacheSize, &dummyLen);
977 RegCloseKey (parmKey);
980 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
981 0, KEY_QUERY_VALUE, &parmKey);
982 if (code == ERROR_SUCCESS) {
983 dummyLen = sizeof(verifyServiceSig);
984 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
985 (BYTE *) &verifyServiceSig, &dummyLen);
986 RegCloseKey (parmKey);
989 if (verifyServiceSig && cacheSize < 716800) {
990 trustVerified = VerifyTrust(filename);
992 afsi_log("Signature Verification disabled");
998 // get a certificate context for the signer of afsd_service.
999 pCtxService = GetCertCtx(filename);
1001 LogCertCtx(pCtxService);
1004 // Get a list of all the modules in this process.
1005 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
1006 FALSE, GetCurrentProcessId());
1008 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
1010 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
1012 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
1014 char szModName[2048];
1016 // Get the full path to the module's file.
1017 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
1019 lstrcpy(checkName, szModName);
1022 if ( strstr(checkName, "afspthread.dll") ||
1023 strstr(checkName, "afsauthent.dll") ||
1024 strstr(checkName, "afsrpc.dll") ||
1025 strstr(checkName, "libafsconf.dll") ||
1026 strstr(checkName, "libosi.dll") )
1028 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1033 afsi_log("%s version %s", szModName, modVersion);
1034 if (strcmp(afsdVersion,modVersion)) {
1035 afsi_log("Version mismatch: %s", szModName);
1038 if ( trustVerified ) {
1039 if ( !VerifyTrust(szModName) ) {
1040 afsi_log("Signature Verification failed: %s", szModName);
1043 else if (pCtxService) {
1044 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1046 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1047 pCtxService->pCertInfo,
1049 afsi_log("Certificate mismatch: %s", szModName);
1057 pCertFreeCertificateContext(pCtx);
1066 pCertFreeCertificateContext(pCtxService);
1070 FreeLibrary(hPSAPI);
1072 CloseHandle(hProcess);
1077 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1080 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1081 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1083 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1084 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1087 afsd_Main(DWORD argc, LPTSTR *argv)
1101 afsd_DbgBreakAllocInit();
1102 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1103 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1106 afsd_SetUnhandledExceptionFilter();
1108 osi_InitPanic(afsd_notifier);
1109 osi_InitTraceOption();
1115 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1116 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1117 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1120 hAdvApi32 = LoadLibrary("advapi32.dll");
1121 if (hAdvApi32 == NULL)
1123 afsi_log("Fatal: cannot load advapi32.dll");
1127 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1128 if (pRegisterServiceCtrlHandlerEx)
1130 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1131 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1135 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1138 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1139 ServiceStatus.dwServiceSpecificExitCode = 0;
1140 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1141 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1142 ServiceStatus.dwCheckPoint = 1;
1143 ServiceStatus.dwWaitHint = 30000;
1144 /* accept Power Events */
1145 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1146 SetServiceStatus(StatusHandle, &ServiceStatus);
1149 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
1151 #ifdef REGISTER_POWER_NOTIFICATIONS
1158 /* see if we should handle power notifications */
1159 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1160 0, KEY_QUERY_VALUE, &hkParm);
1161 if (code == ERROR_SUCCESS) {
1162 dummyLen = sizeof(bpower);
1163 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1164 (BYTE *) &bpower, &dummyLen);
1166 if(code != ERROR_SUCCESS)
1169 RegCloseKey(hkParm);
1171 /* create thread used to flush cache */
1173 PowerNotificationThreadCreate();
1174 powerEventsRegistered = 1;
1179 /* Verify the versions of the DLLs which were loaded */
1180 if (!AFSModulesVerify()) {
1181 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1182 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1183 ServiceStatus.dwCheckPoint = 0;
1184 ServiceStatus.dwWaitHint = 0;
1185 ServiceStatus.dwControlsAccepted = 0;
1186 SetServiceStatus(StatusHandle, &ServiceStatus);
1188 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
1190 /* exit if initialization failed */
1194 /* allow an exit to be called prior to any initialization */
1195 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1199 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1202 hookRc = initHook();
1204 FreeLibrary(hHookDll);
1207 if (hookRc == FALSE)
1209 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1210 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1211 ServiceStatus.dwCheckPoint = 0;
1212 ServiceStatus.dwWaitHint = 0;
1213 ServiceStatus.dwControlsAccepted = 0;
1214 SetServiceStatus(StatusHandle, &ServiceStatus);
1216 /* exit if initialization failed */
1221 /* allow another 15 seconds to start */
1222 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1223 ServiceStatus.dwServiceSpecificExitCode = 0;
1224 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1225 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1226 ServiceStatus.dwCheckPoint = 2;
1227 ServiceStatus.dwWaitHint = 20000;
1228 /* accept Power Events */
1229 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1230 SetServiceStatus(StatusHandle, &ServiceStatus);
1235 MainThreadId = GetCurrentThreadId();
1236 jmpret = setjmp(notifier_jmp);
1241 code = afsd_InitCM(&reason);
1243 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1244 osi_panic(reason, __FILE__, __LINE__);
1248 ServiceStatus.dwCheckPoint++;
1249 ServiceStatus.dwWaitHint -= 5000;
1250 SetServiceStatus(StatusHandle, &ServiceStatus);
1252 code = afsd_InitDaemons(&reason);
1254 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1255 osi_panic(reason, __FILE__, __LINE__);
1258 /* allow an exit to be called post rx initialization */
1259 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1263 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1266 hookRc = rxStartedHook();
1268 FreeLibrary(hHookDll);
1271 if (hookRc == FALSE)
1273 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1274 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1275 ServiceStatus.dwCheckPoint = 0;
1276 ServiceStatus.dwWaitHint = 0;
1277 ServiceStatus.dwControlsAccepted = 0;
1278 SetServiceStatus(StatusHandle, &ServiceStatus);
1280 /* exit if initialization failed */
1286 ServiceStatus.dwCheckPoint++;
1287 ServiceStatus.dwWaitHint -= 5000;
1288 SetServiceStatus(StatusHandle, &ServiceStatus);
1291 /* the following ifdef chooses the mode of operation for the service. to enable
1292 * a runtime flag (instead of compile-time), pioctl() would need to dynamically
1293 * determine the mode, in order to use the correct ioctl special-file path. */
1295 code = afsd_InitSMB(&reason, MessageBox);
1297 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1298 osi_panic(reason, __FILE__, __LINE__);
1301 code = ifs_Init(&reason);
1303 afsi_log("ifs_Init failed: %s (code = %d)", reason, code);
1304 osi_panic(reason, __FILE__, __LINE__);
1306 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1307 hAFSDWorkerThread[cnt] = CreateThread(NULL, 0, ifs_MainLoop, 0, 0, NULL);
1310 /* allow an exit to be called post smb initialization */
1311 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1315 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1318 hookRc = smbStartedHook();
1320 FreeLibrary(hHookDll);
1323 if (hookRc == FALSE)
1325 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1326 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1327 ServiceStatus.dwCheckPoint = 0;
1328 ServiceStatus.dwWaitHint = 0;
1329 ServiceStatus.dwControlsAccepted = 0;
1330 SetServiceStatus(StatusHandle, &ServiceStatus);
1332 /* exit if initialization failed */
1337 MountGlobalDrives();
1340 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1341 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1342 ServiceStatus.dwCheckPoint = 0;
1343 ServiceStatus.dwWaitHint = 0;
1345 /* accept Power events */
1346 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1347 SetServiceStatus(StatusHandle, &ServiceStatus);
1350 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
1353 /* allow an exit to be called when started */
1354 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1358 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1361 hookRc = startedHook();
1363 FreeLibrary(hHookDll);
1366 if (hookRc == FALSE)
1368 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1369 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1370 ServiceStatus.dwCheckPoint = 0;
1371 ServiceStatus.dwWaitHint = 0;
1372 ServiceStatus.dwControlsAccepted = 0;
1373 SetServiceStatus(StatusHandle, &ServiceStatus);
1375 /* exit if initialization failed */
1381 WaitForSingleObject(WaitToTerminate, INFINITE);
1383 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
1384 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1385 CloseHandle(hAFSDWorkerThread[cnt]);
1388 afsi_log("Received Termination Signal, Stopping Service");
1391 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP);
1393 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
1395 /* allow an exit to be called prior to stopping the service */
1396 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1400 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1403 hookRc = stoppingHook();
1405 FreeLibrary(hHookDll);
1408 if (hookRc == FALSE)
1410 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1411 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1412 ServiceStatus.dwCheckPoint = 0;
1413 ServiceStatus.dwWaitHint = 0;
1414 ServiceStatus.dwControlsAccepted = 0;
1415 SetServiceStatus(StatusHandle, &ServiceStatus);
1417 /* exit if initialization failed */
1423 #ifdef AFS_FREELANCE_CLIENT
1424 cm_FreelanceShutdown();
1425 afsi_log("Freelance Shutdown complete");
1428 DismountGlobalDrives();
1429 afsi_log("Global Drives dismounted");
1431 cm_DaemonShutdown();
1432 afsi_log("Daemon shutdown complete");
1437 afsi_log("Buffer shutdown complete");
1440 afsi_log("rx finalization complete");
1444 afsi_log("smb shutdown complete");
1449 cm_ReleaseAllLocks();
1452 afsi_log("rx finalization complete");
1454 cm_ShutdownMappedMemory();
1456 #ifdef REGISTER_POWER_NOTIFICATIONS
1457 /* terminate thread used to flush cache */
1458 if (powerEventsRegistered)
1459 PowerNotificationThreadExit();
1462 /* allow an exit to be called after stopping the service */
1463 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1467 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1470 hookRc = stoppedHook();
1472 FreeLibrary(hHookDll);
1476 /* Remove the ExceptionFilter */
1477 SetUnhandledExceptionFilter(NULL);
1479 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1480 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1481 ServiceStatus.dwCheckPoint = 0;
1482 ServiceStatus.dwWaitHint = 0;
1483 ServiceStatus.dwControlsAccepted = 0;
1484 SetServiceStatus(StatusHandle, &ServiceStatus);
1487 DWORD __stdcall afsdMain_thread(void* notUsed)
1489 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1490 afsd_Main(1, (LPTSTR*)argv);
1496 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1500 main(int argc, char * argv[])
1502 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1503 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1508 for (i = 1; i < argc; i++) {
1509 if (!stricmp(argv[i],"--validate-cache")) {
1510 if (++i != argc - 1) {
1515 return cm_ValidateMappedMemory(argv[i]);
1522 if (!StartServiceCtrlDispatcher(dispatchTable))
1524 LONG status = GetLastError();
1525 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1528 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1530 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1532 SetEvent(WaitToTerminate);
1539 if ( hAFSDMainThread ) {
1540 WaitForSingleObject( hAFSDMainThread, INFINITE );
1541 CloseHandle( hAFSDMainThread );