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_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);
96 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
97 for (i = 0; i < WORKER_THREADS; i++)
98 CloseHandle(hAFSDWorkerThread[i]);
102 if (GetCurrentThreadId() == MainThreadId)
103 longjmp(notifier_jmp, 1);
106 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
107 ServiceStatus.dwWin32ExitCode = NO_ERROR;
108 ServiceStatus.dwCheckPoint = 0;
109 ServiceStatus.dwWaitHint = 0;
110 ServiceStatus.dwControlsAccepted = 0;
111 SetServiceStatus(StatusHandle, &ServiceStatus);
117 * For use miscellaneously in smb.c; need to do better
119 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
125 afsd_ServiceFlushVolume(DWORD dwlpEventData)
127 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
130 ** If UI bit is not set, user interaction is not possible
131 ** BUT, since we are a NON-interactive service, and therefore
132 ** have NO user I/O, it doesn't much matter.
133 ** This benign code left here as example of how to find this out
135 BOOL bUI = (dwlpEventData & 1);
138 if ( PowerNotificationThreadNotify() )
144 /* flush was unsuccessful, or timeout - deny shutdown */
145 dwRet = ERROR_NETWORK_BUSY;
148 /* to deny hibernate, simply return
149 // any value besides NO_ERROR.
151 // dwRet = ERROR_NETWORK_BUSY;
158 /* service control handler used in nt4 only for backward compat. */
160 afsd_ServiceControlHandler(DWORD ctrlCode)
163 DWORD dummyLen, doTrace;
167 case SERVICE_CONTROL_SHUTDOWN:
168 case SERVICE_CONTROL_STOP:
169 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
170 ServiceStatus.dwWin32ExitCode = NO_ERROR;
171 ServiceStatus.dwCheckPoint = 1;
172 ServiceStatus.dwWaitHint = 30000;
173 ServiceStatus.dwControlsAccepted = 0;
174 SetServiceStatus(StatusHandle, &ServiceStatus);
176 if (ctrlCode == SERVICE_CONTROL_STOP)
177 afsi_log("SERVICE_CONTROL_STOP");
179 afsi_log("SERVICE_CONTROL_SHUTDOWN");
181 /* Write all dirty buffers back to server */
182 if ( !lana_OnlyLoopback() )
185 /* Force trace if requested */
186 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
187 AFSREG_CLT_SVC_PARAM_SUBKEY,
188 0, KEY_QUERY_VALUE, &parmKey);
189 if (code != ERROR_SUCCESS)
192 dummyLen = sizeof(doTrace);
193 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
195 (BYTE *) &doTrace, &dummyLen);
196 RegCloseKey (parmKey);
197 if (code != ERROR_SUCCESS)
200 afsd_ForceTrace(FALSE);
201 buf_ForceTrace(FALSE);
205 SetEvent(WaitToTerminate);
208 case SERVICE_CONTROL_INTERROGATE:
209 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
210 ServiceStatus.dwWin32ExitCode = NO_ERROR;
211 ServiceStatus.dwCheckPoint = 0;
212 ServiceStatus.dwWaitHint = 0;
213 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
214 SetServiceStatus(StatusHandle, &ServiceStatus);
216 /* XXX handle system shutdown */
217 /* XXX handle pause & continue */
223 ** Extended ServiceControlHandler that provides Event types
224 ** for monitoring Power events, for example.
227 afsd_ServiceControlHandlerEx(
235 DWORD dummyLen, doTrace;
237 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
238 OSVERSIONINFO osVersion;
240 /* Get the version of Windows */
241 memset(&osVersion, 0x00, sizeof(osVersion));
242 osVersion.dwOSVersionInfoSize = sizeof(osVersion);
243 GetVersionEx(&osVersion);
247 case SERVICE_CONTROL_SHUTDOWN:
248 case 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() )
316 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
319 case PBT_APMQUERYSTANDBY:
320 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
321 /* Write all dirty buffers back to server */
322 if ( !lana_OnlyLoopback() )
324 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
328 /* allow remaining case PBT_WhatEver */
330 afsi_log("SERVICE_CONTROL_APMSUSPEND");
331 powerStateSuspended = 1;
332 if (osVersion.dwMajorVersion >= 6)
337 afsi_log("SERVICE_CONTROL_APMSTANDBY");
338 powerStateSuspended = 1;
339 if (osVersion.dwMajorVersion >= 6)
343 case PBT_APMRESUMECRITICAL:
344 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
345 if (osVersion.dwMajorVersion >= 6)
346 smb_RestartListeners();
349 case PBT_APMRESUMESUSPEND:
350 /* User logged in after suspend */
351 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
354 case PBT_APMRESUMESTANDBY:
355 /* User logged in after standby */
356 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
359 case PBT_APMBATTERYLOW:
360 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
363 case PBT_APMPOWERSTATUSCHANGE:
365 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
369 case PBT_APMOEMEVENT:
371 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
375 case PBT_APMRESUMEAUTOMATIC:
376 /* This is the message delivered once all devices are up */
377 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
378 powerStateSuspended = 0;
379 if (osVersion.dwMajorVersion >= 6)
380 smb_RestartListeners();
384 afsi_log("SERVICE_CONTROL_unknown");
390 case SERVICE_CONTROL_CUSTOM_DUMP:
392 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
393 GenerateMiniDump(NULL);
397 } /* end switch(ctrlCode) */
401 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
403 * Mount a drive into AFS if there global mapping
405 /* DEE Could check first if we are run as SYSTEM */
406 #define MAX_RETRIES 10
407 #define MAX_DRIVES 23
408 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
411 char szAfsPath[_MAX_PATH];
413 char szDriveToMapTo[5];
417 DWORD dwIndex = 0, dwRetry = 0;
419 DWORD dwSubMountSize;
420 char szSubMount[256];
423 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
425 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
426 if (dwResult != ERROR_SUCCESS)
429 while (dwIndex < MAX_DRIVES) {
430 dwDriveSize = sizeof(szDriveToMapTo);
431 dwSubMountSize = sizeof(szSubMount);
432 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
433 if (dwResult != ERROR_MORE_DATA) {
434 if (dwResult != ERROR_SUCCESS) {
435 if (dwResult != ERROR_NO_MORE_ITEMS)
436 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
442 for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
445 memset (&nr, 0x00, sizeof(NETRESOURCE));
447 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
449 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
450 nr.dwType=RESOURCETYPE_DISK;
451 nr.lpLocalName=szDriveToMapTo;
452 nr.lpRemoteName=szAfsPath;
453 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
454 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
456 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
457 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
458 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
459 if (dwResult == NO_ERROR) {
462 /* wait for smb server to come up */
463 Sleep((DWORD)1000 /* miliseconds */);
465 /* Disconnect any previous mappings */
466 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
469 /* FIXFIX: implement */
470 afsi_log("GlobalAutoMap of %s to %s not implemented", szDriveToMapTo, szSubMount);
478 static HANDLE hThreadMountGlobalDrives = NULL;
480 static void MountGlobalDrives()
484 hThreadMountGlobalDrives = CreateThread(NULL, 0, MountGlobalDrivesThread, 0, 0, &tid);
486 if ( hThreadMountGlobalDrives ) {
487 DWORD rc = WaitForSingleObject( hThreadMountGlobalDrives, 15000 );
488 if (rc == WAIT_TIMEOUT) {
489 afsi_log("GlobalAutoMap thread failed to complete after 15 seconds");
490 } else if (rc == WAIT_OBJECT_0) {
491 afsi_log("GlobalAutoMap thread completed");
492 CloseHandle( hThreadMountGlobalDrives );
493 hThreadMountGlobalDrives = NULL;
498 static void DismountGlobalDrives()
501 char szAfsPath[_MAX_PATH];
502 char szDriveToMapTo[5];
504 DWORD dwSubMountSize;
505 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)
533 /* FIXFIX: implement */
535 while (dwIndex < MAX_DRIVES) {
536 dwDriveSize = sizeof(szDriveToMapTo);
537 dwSubMountSize = sizeof(szSubMount);
538 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
539 if (dwResult != ERROR_MORE_DATA) {
540 if (dwResult != ERROR_SUCCESS) {
541 if (dwResult != ERROR_NO_MORE_ITEMS)
542 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
547 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
549 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
550 dwResult = WNetCancelConnection(szAfsPath, TRUE);
552 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
560 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
562 DWORD dwVersionHandle;
563 LPVOID pVersionInfo = 0;
565 LPDWORD pLangInfo = 0;
566 LPTSTR szVersion = 0;
568 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
569 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
572 afsi_log("GetFileVersionInfoSize failed");
573 return GetLastError();
576 pVersionInfo = malloc(size);
578 afsi_log("out of memory 1");
579 return ERROR_NOT_ENOUGH_MEMORY;
582 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
583 if (retval = GetLastError())
585 afsi_log("GetFileVersionInfo failed: %d", retval);
589 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
590 (LPVOID*)&pLangInfo, &len);
591 if (retval = GetLastError())
593 afsi_log("VerQueryValue 1 failed: %d", retval);
598 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
599 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
601 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
602 if (retval = GetLastError())
604 /* try again with language 409 since the old binaries were tagged wrong */
606 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
609 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
610 if (retval = GetLastError()) {
611 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
615 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
616 szOutput[dwOutput - 1] = 0;
625 static HINSTANCE hCrypt32;
626 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
627 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
628 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
629 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
630 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
631 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
632 HCRYPTMSG* phMsg, const void** ppvContext);
633 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
634 void* pvData, DWORD* pcbData);
635 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
636 DWORD dwFindFlags, DWORD dwFindType,
637 const void* pvFindPara,
638 PCCERT_CONTEXT pPrevCertContext);
639 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
640 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
641 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
642 PCERT_INFO pCertId2);
643 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
645 void LoadCrypt32(void)
647 hCrypt32 = LoadLibrary("crypt32");
651 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
652 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
653 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
654 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
655 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
656 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
657 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
658 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
660 if ( !pCertGetNameString ||
661 !pCryptQueryObject ||
662 !pCryptMsgGetParam ||
663 !pCertFindCertificateInStore ||
666 !pCertCompareCertificate ||
667 !pCertFreeCertificateContext)
669 FreeLibrary(hCrypt32);
674 void UnloadCrypt32(void)
676 FreeLibrary(hCrypt32);
679 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
681 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
683 wchar_t wfilename[260];
689 HCERTSTORE hStore = NULL;
690 HCRYPTMSG hMsg = NULL;
691 PCMSG_SIGNER_INFO pSignerInfo = NULL;
692 PCCERT_CONTEXT pCertContext = NULL;
695 if ( hCrypt32 == NULL )
698 ZeroMemory(&CertInfo, sizeof(CertInfo));
699 mbstowcs(wfilename, filename, 260);
701 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
703 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
704 CERT_QUERY_FORMAT_FLAG_BINARY,
714 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
720 fResult = pCryptMsgGetParam(hMsg,
721 CMSG_SIGNER_INFO_PARAM,
727 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
733 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
735 fResult = pCryptMsgGetParam(hMsg,
736 CMSG_SIGNER_INFO_PARAM,
742 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
748 CertInfo.Issuer = pSignerInfo->Issuer;
749 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
751 pCertContext = pCertFindCertificateInStore(hStore,
754 CERT_FIND_SUBJECT_CERT,
759 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
767 LocalFree(pSignerInfo);
770 CertFreeCertificateContext(pCertContext);*/
773 pCertCloseStore(hStore,0);
776 pCryptMsgClose(hMsg);
781 BOOL VerifyTrust(CHAR * filename)
783 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
784 WIN_TRUST_SUBJECT_FILE fSubjectFile;
785 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
786 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
787 wchar_t wfilename[260];
789 BOOL success = FALSE;
791 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
794 if (filename == NULL )
797 hWinTrust = LoadLibrary("wintrust");
801 if (((FARPROC) pWinVerifyTrust =
802 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
804 FreeLibrary(hWinTrust);
808 mbstowcs(wfilename, filename, 260);
810 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
812 fSubjectFile.lpPath = wfilename;
813 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
814 FALSE, GetCurrentProcessId());
815 fContextWSubject.SubjectType = &subject;
816 fContextWSubject.Subject = &fSubjectFile;
818 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
820 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
821 CloseHandle( fSubjectFile.hFile );
822 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
823 CloseHandle( fContextWSubject.hClientToken );
825 if (ret == ERROR_SUCCESS) {
828 DWORD gle = GetLastError();
830 case TRUST_E_PROVIDER_UNKNOWN:
831 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
833 case TRUST_E_NOSIGNATURE:
834 afsi_log("VerifyTrust failed: Unsigned executable");
836 case TRUST_E_EXPLICIT_DISTRUST:
837 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
839 case TRUST_E_SUBJECT_NOT_TRUSTED:
840 afsi_log("VerifyTrust failed: File is not trusted");
842 case TRUST_E_BAD_DIGEST:
843 afsi_log("VerifyTrust failed: Executable has been modified");
845 case CRYPT_E_SECURITY_SETTINGS:
846 afsi_log("VerifyTrust failed: local security options prevent verification");
849 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
853 FreeLibrary(hWinTrust);
857 void LogCertCtx(PCCERT_CONTEXT pCtx) {
859 LPTSTR szName = NULL;
861 if ( hCrypt32 == NULL )
864 // Get Issuer name size.
865 if (!(dwData = pCertGetNameString(pCtx,
866 CERT_NAME_SIMPLE_DISPLAY_TYPE,
867 CERT_NAME_ISSUER_FLAG,
871 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
875 // Allocate memory for Issuer name.
876 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
879 if (!(pCertGetNameString(pCtx,
880 CERT_NAME_SIMPLE_DISPLAY_TYPE,
881 CERT_NAME_ISSUER_FLAG,
885 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
889 // print Issuer name.
890 afsi_log("Issuer Name: %s", szName);
894 // Get Subject name size.
895 if (!(dwData = pCertGetNameString(pCtx,
896 CERT_NAME_SIMPLE_DISPLAY_TYPE,
901 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
905 // Allocate memory for subject name.
906 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
909 if (!(pCertGetNameString(pCtx,
910 CERT_NAME_SIMPLE_DISPLAY_TYPE,
915 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
919 // Print Subject Name.
920 afsi_log("Subject Name: %s", szName);
928 BOOL AFSModulesVerify(void)
931 CHAR afsdVersion[128];
932 CHAR modVersion[128];
933 CHAR checkName[1024];
934 BOOL trustVerified = FALSE;
940 PCCERT_CONTEXT pCtxService = NULL;
942 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
943 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
944 DWORD dummyLen, code;
945 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
946 DWORD verifyServiceSig = TRUE;
949 hPSAPI = LoadLibrary("psapi");
951 if ( hPSAPI == NULL )
954 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
957 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
960 afsi_log("%s version %s", filename, afsdVersion);
962 if (((FARPROC) pGetModuleFileNameExA =
963 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
964 ((FARPROC) pEnumProcessModules =
965 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
972 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
973 AFSREG_CLT_SVC_PARAM_SUBKEY,
974 0, KEY_QUERY_VALUE, &parmKey);
975 if (code == ERROR_SUCCESS) {
976 dummyLen = sizeof(cacheSize);
977 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
978 (BYTE *) &cacheSize, &dummyLen);
979 RegCloseKey (parmKey);
982 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
983 0, KEY_QUERY_VALUE, &parmKey);
984 if (code == ERROR_SUCCESS) {
985 dummyLen = sizeof(verifyServiceSig);
986 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
987 (BYTE *) &verifyServiceSig, &dummyLen);
988 RegCloseKey (parmKey);
991 if (verifyServiceSig && 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)
1103 afsd_DbgBreakAllocInit();
1104 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1105 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1108 afsd_SetUnhandledExceptionFilter();
1110 osi_InitPanic(afsd_notifier);
1111 osi_InitTraceOption();
1117 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1118 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1119 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1122 hAdvApi32 = LoadLibrary("advapi32.dll");
1123 if (hAdvApi32 == NULL)
1125 afsi_log("Fatal: cannot load advapi32.dll");
1129 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1130 if (pRegisterServiceCtrlHandlerEx)
1132 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1133 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1137 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1140 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1141 ServiceStatus.dwServiceSpecificExitCode = 0;
1142 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1143 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1144 ServiceStatus.dwCheckPoint = 1;
1145 ServiceStatus.dwWaitHint = 30000;
1146 /* accept Power Events */
1147 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1148 SetServiceStatus(StatusHandle, &ServiceStatus);
1151 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
1153 #ifdef REGISTER_POWER_NOTIFICATIONS
1160 /* see if we should handle power notifications */
1161 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1162 0, KEY_QUERY_VALUE, &hkParm);
1163 if (code == ERROR_SUCCESS) {
1164 dummyLen = sizeof(bpower);
1165 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1166 (BYTE *) &bpower, &dummyLen);
1168 if(code != ERROR_SUCCESS)
1171 RegCloseKey(hkParm);
1173 /* create thread used to flush cache */
1175 PowerNotificationThreadCreate();
1176 powerEventsRegistered = 1;
1181 /* Verify the versions of the DLLs which were loaded */
1182 if (!AFSModulesVerify()) {
1183 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1184 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1185 ServiceStatus.dwCheckPoint = 0;
1186 ServiceStatus.dwWaitHint = 0;
1187 ServiceStatus.dwControlsAccepted = 0;
1188 SetServiceStatus(StatusHandle, &ServiceStatus);
1190 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
1192 /* exit if initialization failed */
1196 /* allow an exit to be called prior to any initialization */
1197 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1201 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1204 hookRc = initHook();
1206 FreeLibrary(hHookDll);
1209 if (hookRc == FALSE)
1211 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1212 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1213 ServiceStatus.dwCheckPoint = 0;
1214 ServiceStatus.dwWaitHint = 0;
1215 ServiceStatus.dwControlsAccepted = 0;
1216 SetServiceStatus(StatusHandle, &ServiceStatus);
1218 /* exit if initialization failed */
1223 /* allow another 15 seconds to start */
1224 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1225 ServiceStatus.dwServiceSpecificExitCode = 0;
1226 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1227 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1228 ServiceStatus.dwCheckPoint = 2;
1229 ServiceStatus.dwWaitHint = 20000;
1230 /* accept Power Events */
1231 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1232 SetServiceStatus(StatusHandle, &ServiceStatus);
1237 MainThreadId = GetCurrentThreadId();
1238 jmpret = setjmp(notifier_jmp);
1243 code = afsd_InitCM(&reason);
1245 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1246 osi_panic(reason, __FILE__, __LINE__);
1250 ServiceStatus.dwCheckPoint++;
1251 ServiceStatus.dwWaitHint -= 5000;
1252 SetServiceStatus(StatusHandle, &ServiceStatus);
1254 code = afsd_InitDaemons(&reason);
1256 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1257 osi_panic(reason, __FILE__, __LINE__);
1260 /* allow an exit to be called post rx initialization */
1261 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1265 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1268 hookRc = rxStartedHook();
1270 FreeLibrary(hHookDll);
1273 if (hookRc == FALSE)
1275 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1276 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1277 ServiceStatus.dwCheckPoint = 0;
1278 ServiceStatus.dwWaitHint = 0;
1279 ServiceStatus.dwControlsAccepted = 0;
1280 SetServiceStatus(StatusHandle, &ServiceStatus);
1282 /* exit if initialization failed */
1288 ServiceStatus.dwCheckPoint++;
1289 ServiceStatus.dwWaitHint -= 5000;
1290 SetServiceStatus(StatusHandle, &ServiceStatus);
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. */
1297 code = afsd_InitSMB(&reason, MessageBox);
1299 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1300 osi_panic(reason, __FILE__, __LINE__);
1303 code = ifs_Init(&reason);
1305 afsi_log("ifs_Init failed: %s (code = %d)", reason, code);
1306 osi_panic(reason, __FILE__, __LINE__);
1308 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1309 hAFSDWorkerThread[cnt] = CreateThread(NULL, 0, ifs_MainLoop, 0, 0, NULL);
1312 /* allow an exit to be called post smb initialization */
1313 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1317 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1320 hookRc = smbStartedHook();
1322 FreeLibrary(hHookDll);
1325 if (hookRc == FALSE)
1327 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1328 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1329 ServiceStatus.dwCheckPoint = 0;
1330 ServiceStatus.dwWaitHint = 0;
1331 ServiceStatus.dwControlsAccepted = 0;
1332 SetServiceStatus(StatusHandle, &ServiceStatus);
1334 /* exit if initialization failed */
1339 MountGlobalDrives();
1342 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1343 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1344 ServiceStatus.dwCheckPoint = 0;
1345 ServiceStatus.dwWaitHint = 0;
1347 /* accept Power events */
1348 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1349 SetServiceStatus(StatusHandle, &ServiceStatus);
1352 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
1355 /* allow an exit to be called when started */
1356 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1360 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1363 hookRc = startedHook();
1365 FreeLibrary(hHookDll);
1368 if (hookRc == FALSE)
1370 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1371 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1372 ServiceStatus.dwCheckPoint = 0;
1373 ServiceStatus.dwWaitHint = 0;
1374 ServiceStatus.dwControlsAccepted = 0;
1375 SetServiceStatus(StatusHandle, &ServiceStatus);
1377 /* exit if initialization failed */
1383 WaitForSingleObject(WaitToTerminate, INFINITE);
1385 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
1386 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1387 CloseHandle(hAFSDWorkerThread[cnt]);
1390 afsi_log("Received Termination Signal, Stopping Service");
1393 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP);
1395 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
1397 /* allow an exit to be called prior to stopping the service */
1398 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1402 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1405 hookRc = stoppingHook();
1407 FreeLibrary(hHookDll);
1410 if (hookRc == FALSE)
1412 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1413 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1414 ServiceStatus.dwCheckPoint = 0;
1415 ServiceStatus.dwWaitHint = 0;
1416 ServiceStatus.dwControlsAccepted = 0;
1417 SetServiceStatus(StatusHandle, &ServiceStatus);
1419 /* exit if initialization failed */
1425 #ifdef AFS_FREELANCE_CLIENT
1426 cm_FreelanceShutdown();
1427 afsi_log("Freelance Shutdown complete");
1430 DismountGlobalDrives();
1431 afsi_log("Global Drives dismounted");
1433 cm_DaemonShutdown();
1434 afsi_log("Daemon shutdown complete");
1439 afsi_log("Buffer shutdown complete");
1442 afsi_log("rx finalization complete");
1446 afsi_log("smb shutdown complete");
1451 cm_ReleaseAllLocks();
1454 afsi_log("rx finalization complete");
1456 cm_ShutdownMappedMemory();
1458 #ifdef REGISTER_POWER_NOTIFICATIONS
1459 /* terminate thread used to flush cache */
1460 if (powerEventsRegistered)
1461 PowerNotificationThreadExit();
1464 /* allow an exit to be called after stopping the service */
1465 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1469 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1472 hookRc = stoppedHook();
1474 FreeLibrary(hHookDll);
1478 /* Remove the ExceptionFilter */
1479 SetUnhandledExceptionFilter(NULL);
1481 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1482 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1483 ServiceStatus.dwCheckPoint = 0;
1484 ServiceStatus.dwWaitHint = 0;
1485 ServiceStatus.dwControlsAccepted = 0;
1486 SetServiceStatus(StatusHandle, &ServiceStatus);
1489 DWORD __stdcall afsdMain_thread(void* notUsed)
1491 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1492 afsd_Main(1, (LPTSTR*)argv);
1498 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1502 main(int argc, char * argv[])
1504 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1505 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1510 for (i = 1; i < argc; i++) {
1511 if (!stricmp(argv[i],"--validate-cache")) {
1512 if (++i != argc - 1) {
1517 return cm_ValidateMappedMemory(argv[i]);
1524 if (!StartServiceCtrlDispatcher(dispatchTable))
1526 LONG status = GetLastError();
1527 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1530 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1532 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1534 SetEvent(WaitToTerminate);
1541 if ( hAFSDMainThread ) {
1542 WaitForSingleObject( hAFSDMainThread, INFINITE );
1543 CloseHandle( hAFSDMainThread );