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;
46 unsigned int MainThreadId;
50 extern int traceOnPanic;
51 extern HANDLE afsi_file;
53 int powerEventsRegistered = 0;
56 * Notifier function for use by osi_panic
58 static void afsd_notifier(char *msgp, char *filep, long line)
65 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION,
68 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG, msgp);
72 osi_LogEnable(afsd_logp);
74 afsd_ForceTrace(TRUE);
77 afsi_log("--- begin dump ---");
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);
93 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
94 for (i = 0; i < WORKER_THREADS; i++)
95 CloseHandle(hAFSDWorkerThread[i]);
99 if (GetCurrentThreadId() == MainThreadId)
100 longjmp(notifier_jmp, 1);
103 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
104 ServiceStatus.dwWin32ExitCode = NO_ERROR;
105 ServiceStatus.dwCheckPoint = 0;
106 ServiceStatus.dwWaitHint = 0;
107 ServiceStatus.dwControlsAccepted = 0;
108 SetServiceStatus(StatusHandle, &ServiceStatus);
114 * For use miscellaneously in smb.c; need to do better
116 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
122 afsd_ServiceFlushVolume(DWORD dwlpEventData)
124 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
127 ** If UI bit is not set, user interaction is not possible
128 ** BUT, since we are a NON-interactive service, and therefore
129 ** have NO user I/O, it doesn't much matter.
130 ** This benign code left here as example of how to find this out
132 BOOL bUI = (dwlpEventData & 1);
135 if ( PowerNotificationThreadNotify() )
141 /* flush was unsuccessful, or timeout - deny shutdown */
142 dwRet = ERROR_NETWORK_BUSY;
145 /* to deny hibernate, simply return
146 // any value besides NO_ERROR.
148 // dwRet = ERROR_NETWORK_BUSY;
155 /* service control handler used in nt4 only for backward compat. */
157 afsd_ServiceControlHandler(DWORD ctrlCode)
160 DWORD dummyLen, doTrace;
164 case SERVICE_CONTROL_SHUTDOWN:
165 case SERVICE_CONTROL_STOP:
166 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
167 ServiceStatus.dwWin32ExitCode = NO_ERROR;
168 ServiceStatus.dwCheckPoint = 1;
169 ServiceStatus.dwWaitHint = 30000;
170 ServiceStatus.dwControlsAccepted = 0;
171 SetServiceStatus(StatusHandle, &ServiceStatus);
173 if (ctrlCode == SERVICE_CONTROL_STOP)
174 afsi_log("SERVICE_CONTROL_STOP");
176 afsi_log("SERVICE_CONTROL_SHUTDOWN");
178 /* Write all dirty buffers back to server */
179 if ( !lana_OnlyLoopback() )
182 /* Force trace if requested */
183 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
184 AFSREG_CLT_SVC_PARAM_SUBKEY,
185 0, KEY_QUERY_VALUE, &parmKey);
186 if (code != ERROR_SUCCESS)
189 dummyLen = sizeof(doTrace);
190 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
192 (BYTE *) &doTrace, &dummyLen);
193 RegCloseKey (parmKey);
194 if (code != ERROR_SUCCESS)
197 afsd_ForceTrace(FALSE);
198 buf_ForceTrace(FALSE);
202 SetEvent(WaitToTerminate);
205 case SERVICE_CONTROL_INTERROGATE:
206 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
207 ServiceStatus.dwWin32ExitCode = NO_ERROR;
208 ServiceStatus.dwCheckPoint = 0;
209 ServiceStatus.dwWaitHint = 0;
210 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
211 SetServiceStatus(StatusHandle, &ServiceStatus);
213 /* XXX handle system shutdown */
214 /* XXX handle pause & continue */
220 ** Extended ServiceControlHandler that provides Event types
221 ** for monitoring Power events, for example.
224 afsd_ServiceControlHandlerEx(
232 DWORD dummyLen, doTrace;
234 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
235 OSVERSIONINFO osVersion;
237 /* Get the version of Windows */
238 memset(&osVersion, 0x00, sizeof(osVersion));
239 osVersion.dwOSVersionInfoSize = sizeof(osVersion);
240 GetVersionEx(&osVersion);
244 case SERVICE_CONTROL_SHUTDOWN:
245 case 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() )
313 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
316 case PBT_APMQUERYSTANDBY:
317 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
318 /* Write all dirty buffers back to server */
319 if ( !lana_OnlyLoopback() )
321 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
325 /* allow remaining case PBT_WhatEver */
327 afsi_log("SERVICE_CONTROL_APMSUSPEND");
328 if (osVersion.dwMajorVersion >= 6)
333 afsi_log("SERVICE_CONTROL_APMSTANDBY");
334 if (osVersion.dwMajorVersion >= 6)
338 case PBT_APMRESUMECRITICAL:
339 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
340 if (osVersion.dwMajorVersion >= 6)
341 smb_RestartListeners();
344 case PBT_APMRESUMESUSPEND:
345 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
346 if (osVersion.dwMajorVersion >= 6)
347 smb_RestartListeners();
350 case PBT_APMRESUMESTANDBY:
351 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
352 if (osVersion.dwMajorVersion >= 6)
353 smb_RestartListeners();
356 case PBT_APMBATTERYLOW:
357 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
360 case PBT_APMPOWERSTATUSCHANGE:
362 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
366 case PBT_APMOEMEVENT:
368 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
372 case PBT_APMRESUMEAUTOMATIC:
373 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
374 if (osVersion.dwMajorVersion >= 6)
375 smb_RestartListeners();
379 afsi_log("SERVICE_CONTROL_unknown");
385 case SERVICE_CONTROL_CUSTOM_DUMP:
387 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
388 GenerateMiniDump(NULL);
392 } /* end switch(ctrlCode) */
396 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
398 * Mount a drive into AFS if there global mapping
400 /* DEE Could check first if we are run as SYSTEM */
401 #define MAX_RETRIES 10
402 #define MAX_DRIVES 23
403 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
406 char szAfsPath[_MAX_PATH];
408 char szDriveToMapTo[5];
412 DWORD dwIndex = 0, dwRetry = 0;
414 DWORD dwSubMountSize;
415 char szSubMount[256];
418 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
420 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
421 if (dwResult != ERROR_SUCCESS)
424 while (dwIndex < MAX_DRIVES) {
425 dwDriveSize = sizeof(szDriveToMapTo);
426 dwSubMountSize = sizeof(szSubMount);
427 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
428 if (dwResult != ERROR_MORE_DATA) {
429 if (dwResult != ERROR_SUCCESS) {
430 if (dwResult != ERROR_NO_MORE_ITEMS)
431 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
437 for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
440 memset (&nr, 0x00, sizeof(NETRESOURCE));
442 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
444 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
445 nr.dwType=RESOURCETYPE_DISK;
446 nr.lpLocalName=szDriveToMapTo;
447 nr.lpRemoteName=szAfsPath;
448 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
449 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
451 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
452 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
453 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
454 if (dwResult == NO_ERROR) {
457 /* wait for smb server to come up */
458 Sleep((DWORD)1000 /* miliseconds */);
460 /* Disconnect any previous mappings */
461 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
464 /* FIXFIX: implement */
465 afsi_log("GlobalAutoMap of %s to %s not implemented", szDriveToMapTo, szSubMount);
473 static HANDLE hThreadMountGlobalDrives = NULL;
475 static void MountGlobalDrives()
479 hThreadMountGlobalDrives = CreateThread(NULL, 0, MountGlobalDrivesThread, 0, 0, &tid);
481 if ( hThreadMountGlobalDrives ) {
482 DWORD rc = WaitForSingleObject( hThreadMountGlobalDrives, 15000 );
483 if (rc == WAIT_TIMEOUT) {
484 afsi_log("GlobalAutoMap thread failed to complete after 15 seconds");
485 } else if (rc == WAIT_OBJECT_0) {
486 afsi_log("GlobalAutoMap thread completed");
487 CloseHandle( hThreadMountGlobalDrives );
488 hThreadMountGlobalDrives = NULL;
493 static void DismountGlobalDrives()
496 char szAfsPath[_MAX_PATH];
497 char szDriveToMapTo[5];
499 DWORD dwSubMountSize;
500 char szSubMount[256];
508 if ( hThreadMountGlobalDrives ) {
509 DWORD rc = WaitForSingleObject(hThreadMountGlobalDrives, 0);
511 if (rc == WAIT_TIMEOUT) {
512 afsi_log("GlobalAutoMap thread failed to complete before service shutdown");
514 else if (rc == WAIT_OBJECT_0) {
515 afsi_log("GlobalAutoMap thread completed");
516 CloseHandle( hThreadMountGlobalDrives );
517 hThreadMountGlobalDrives = NULL;
521 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
523 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
524 if (dwResult != ERROR_SUCCESS)
528 /* FIXFIX: implement */
530 while (dwIndex < MAX_DRIVES) {
531 dwDriveSize = sizeof(szDriveToMapTo);
532 dwSubMountSize = sizeof(szSubMount);
533 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
534 if (dwResult != ERROR_MORE_DATA) {
535 if (dwResult != ERROR_SUCCESS) {
536 if (dwResult != ERROR_NO_MORE_ITEMS)
537 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
542 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
544 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
545 dwResult = WNetCancelConnection(szAfsPath, TRUE);
547 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
555 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
557 DWORD dwVersionHandle;
558 LPVOID pVersionInfo = 0;
560 LPDWORD pLangInfo = 0;
561 LPTSTR szVersion = 0;
563 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
564 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
567 afsi_log("GetFileVersionInfoSize failed");
568 return GetLastError();
571 pVersionInfo = malloc(size);
573 afsi_log("out of memory 1");
574 return ERROR_NOT_ENOUGH_MEMORY;
577 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
578 if (retval = GetLastError())
580 afsi_log("GetFileVersionInfo failed: %d", retval);
584 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
585 (LPVOID*)&pLangInfo, &len);
586 if (retval = GetLastError())
588 afsi_log("VerQueryValue 1 failed: %d", retval);
593 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
594 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
596 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
597 if (retval = GetLastError())
599 /* try again with language 409 since the old binaries were tagged wrong */
601 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
604 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
605 if (retval = GetLastError()) {
606 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
610 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
611 szOutput[dwOutput - 1] = 0;
620 static HINSTANCE hCrypt32;
621 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
622 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
623 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
624 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
625 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
626 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
627 HCRYPTMSG* phMsg, const void** ppvContext);
628 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
629 void* pvData, DWORD* pcbData);
630 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
631 DWORD dwFindFlags, DWORD dwFindType,
632 const void* pvFindPara,
633 PCCERT_CONTEXT pPrevCertContext);
634 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
635 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
636 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
637 PCERT_INFO pCertId2);
638 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
640 void LoadCrypt32(void)
642 hCrypt32 = LoadLibrary("crypt32");
646 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
647 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
648 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
649 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
650 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
651 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
652 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
653 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
655 if ( !pCertGetNameString ||
656 !pCryptQueryObject ||
657 !pCryptMsgGetParam ||
658 !pCertFindCertificateInStore ||
661 !pCertCompareCertificate ||
662 !pCertFreeCertificateContext)
664 FreeLibrary(hCrypt32);
669 void UnloadCrypt32(void)
671 FreeLibrary(hCrypt32);
674 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
676 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
678 wchar_t wfilename[260];
684 HCERTSTORE hStore = NULL;
685 HCRYPTMSG hMsg = NULL;
686 PCMSG_SIGNER_INFO pSignerInfo = NULL;
687 PCCERT_CONTEXT pCertContext = NULL;
690 if ( hCrypt32 == NULL )
693 ZeroMemory(&CertInfo, sizeof(CertInfo));
694 mbstowcs(wfilename, filename, 260);
696 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
698 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
699 CERT_QUERY_FORMAT_FLAG_BINARY,
709 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
715 fResult = pCryptMsgGetParam(hMsg,
716 CMSG_SIGNER_INFO_PARAM,
722 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
728 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
730 fResult = pCryptMsgGetParam(hMsg,
731 CMSG_SIGNER_INFO_PARAM,
737 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
743 CertInfo.Issuer = pSignerInfo->Issuer;
744 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
746 pCertContext = pCertFindCertificateInStore(hStore,
749 CERT_FIND_SUBJECT_CERT,
754 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
762 LocalFree(pSignerInfo);
765 CertFreeCertificateContext(pCertContext);*/
768 pCertCloseStore(hStore,0);
771 pCryptMsgClose(hMsg);
776 BOOL VerifyTrust(CHAR * filename)
778 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
779 WIN_TRUST_SUBJECT_FILE fSubjectFile;
780 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
781 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
782 wchar_t wfilename[260];
784 BOOL success = FALSE;
786 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
789 if (filename == NULL )
792 hWinTrust = LoadLibrary("wintrust");
796 if (((FARPROC) pWinVerifyTrust =
797 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
799 FreeLibrary(hWinTrust);
803 mbstowcs(wfilename, filename, 260);
805 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
807 fSubjectFile.lpPath = wfilename;
808 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
809 FALSE, GetCurrentProcessId());
810 fContextWSubject.SubjectType = &subject;
811 fContextWSubject.Subject = &fSubjectFile;
813 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
815 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
816 CloseHandle( fSubjectFile.hFile );
817 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
818 CloseHandle( fContextWSubject.hClientToken );
820 if (ret == ERROR_SUCCESS) {
823 DWORD gle = GetLastError();
825 case TRUST_E_PROVIDER_UNKNOWN:
826 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
828 case TRUST_E_NOSIGNATURE:
829 afsi_log("VerifyTrust failed: Unsigned executable");
831 case TRUST_E_EXPLICIT_DISTRUST:
832 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
834 case TRUST_E_SUBJECT_NOT_TRUSTED:
835 afsi_log("VerifyTrust failed: File is not trusted");
837 case TRUST_E_BAD_DIGEST:
838 afsi_log("VerifyTrust failed: Executable has been modified");
840 case CRYPT_E_SECURITY_SETTINGS:
841 afsi_log("VerifyTrust failed: local security options prevent verification");
844 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
848 FreeLibrary(hWinTrust);
852 void LogCertCtx(PCCERT_CONTEXT pCtx) {
854 LPTSTR szName = NULL;
856 if ( hCrypt32 == NULL )
859 // Get Issuer name size.
860 if (!(dwData = pCertGetNameString(pCtx,
861 CERT_NAME_SIMPLE_DISPLAY_TYPE,
862 CERT_NAME_ISSUER_FLAG,
866 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
870 // Allocate memory for Issuer name.
871 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
874 if (!(pCertGetNameString(pCtx,
875 CERT_NAME_SIMPLE_DISPLAY_TYPE,
876 CERT_NAME_ISSUER_FLAG,
880 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
884 // print Issuer name.
885 afsi_log("Issuer Name: %s", szName);
889 // Get Subject name size.
890 if (!(dwData = pCertGetNameString(pCtx,
891 CERT_NAME_SIMPLE_DISPLAY_TYPE,
896 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
900 // Allocate memory for subject name.
901 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
904 if (!(pCertGetNameString(pCtx,
905 CERT_NAME_SIMPLE_DISPLAY_TYPE,
910 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
914 // Print Subject Name.
915 afsi_log("Subject Name: %s", szName);
923 BOOL AFSModulesVerify(void)
926 CHAR afsdVersion[128];
927 CHAR modVersion[128];
928 CHAR checkName[1024];
929 BOOL trustVerified = FALSE;
935 PCCERT_CONTEXT pCtxService = NULL;
937 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
938 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
939 DWORD dummyLen, code;
940 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
941 DWORD verifyServiceSig = TRUE;
944 hPSAPI = LoadLibrary("psapi");
946 if ( hPSAPI == NULL )
949 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
952 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
955 afsi_log("%s version %s", filename, afsdVersion);
957 if (((FARPROC) pGetModuleFileNameExA =
958 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
959 ((FARPROC) pEnumProcessModules =
960 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
967 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
968 AFSREG_CLT_SVC_PARAM_SUBKEY,
969 0, KEY_QUERY_VALUE, &parmKey);
970 if (code == ERROR_SUCCESS) {
971 dummyLen = sizeof(cacheSize);
972 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
973 (BYTE *) &cacheSize, &dummyLen);
974 RegCloseKey (parmKey);
977 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
978 0, KEY_QUERY_VALUE, &parmKey);
979 if (code == ERROR_SUCCESS) {
980 dummyLen = sizeof(verifyServiceSig);
981 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
982 (BYTE *) &verifyServiceSig, &dummyLen);
983 RegCloseKey (parmKey);
986 if (verifyServiceSig && cacheSize < 716800) {
987 trustVerified = VerifyTrust(filename);
989 afsi_log("Signature Verification disabled");
995 // get a certificate context for the signer of afsd_service.
996 pCtxService = GetCertCtx(filename);
998 LogCertCtx(pCtxService);
1001 // Get a list of all the modules in this process.
1002 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
1003 FALSE, GetCurrentProcessId());
1005 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
1007 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
1009 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
1011 char szModName[2048];
1013 // Get the full path to the module's file.
1014 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
1016 lstrcpy(checkName, szModName);
1019 if ( strstr(checkName, "afspthread.dll") ||
1020 strstr(checkName, "afsauthent.dll") ||
1021 strstr(checkName, "afsrpc.dll") ||
1022 strstr(checkName, "libafsconf.dll") ||
1023 strstr(checkName, "libosi.dll") )
1025 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1030 afsi_log("%s version %s", szModName, modVersion);
1031 if (strcmp(afsdVersion,modVersion)) {
1032 afsi_log("Version mismatch: %s", szModName);
1035 if ( trustVerified ) {
1036 if ( !VerifyTrust(szModName) ) {
1037 afsi_log("Signature Verification failed: %s", szModName);
1040 else if (pCtxService) {
1041 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1043 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1044 pCtxService->pCertInfo,
1046 afsi_log("Certificate mismatch: %s", szModName);
1054 pCertFreeCertificateContext(pCtx);
1063 pCertFreeCertificateContext(pCtxService);
1067 FreeLibrary(hPSAPI);
1069 CloseHandle(hProcess);
1074 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1077 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1078 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1080 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1081 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1084 afsd_Main(DWORD argc, LPTSTR *argv)
1098 afsd_DbgBreakAllocInit();
1099 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1100 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1103 afsd_SetUnhandledExceptionFilter();
1105 osi_InitPanic(afsd_notifier);
1106 osi_InitTraceOption();
1112 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1113 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1114 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1117 hAdvApi32 = LoadLibrary("advapi32.dll");
1118 if (hAdvApi32 == NULL)
1120 afsi_log("Fatal: cannot load advapi32.dll");
1124 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1125 if (pRegisterServiceCtrlHandlerEx)
1127 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1128 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1132 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1135 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1136 ServiceStatus.dwServiceSpecificExitCode = 0;
1137 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1138 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1139 ServiceStatus.dwCheckPoint = 1;
1140 ServiceStatus.dwWaitHint = 30000;
1141 /* accept Power Events */
1142 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1143 SetServiceStatus(StatusHandle, &ServiceStatus);
1146 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
1148 #ifdef REGISTER_POWER_NOTIFICATIONS
1155 /* see if we should handle power notifications */
1156 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1157 0, KEY_QUERY_VALUE, &hkParm);
1158 if (code == ERROR_SUCCESS) {
1159 dummyLen = sizeof(bpower);
1160 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1161 (BYTE *) &bpower, &dummyLen);
1163 if(code != ERROR_SUCCESS)
1166 RegCloseKey(hkParm);
1168 /* create thread used to flush cache */
1170 PowerNotificationThreadCreate();
1171 powerEventsRegistered = 1;
1176 /* Verify the versions of the DLLs which were loaded */
1177 if (!AFSModulesVerify()) {
1178 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1179 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1180 ServiceStatus.dwCheckPoint = 0;
1181 ServiceStatus.dwWaitHint = 0;
1182 ServiceStatus.dwControlsAccepted = 0;
1183 SetServiceStatus(StatusHandle, &ServiceStatus);
1185 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
1187 /* exit if initialization failed */
1191 /* allow an exit to be called prior to any initialization */
1192 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1196 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1199 hookRc = initHook();
1201 FreeLibrary(hHookDll);
1204 if (hookRc == FALSE)
1206 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1207 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1208 ServiceStatus.dwCheckPoint = 0;
1209 ServiceStatus.dwWaitHint = 0;
1210 ServiceStatus.dwControlsAccepted = 0;
1211 SetServiceStatus(StatusHandle, &ServiceStatus);
1213 /* exit if initialization failed */
1218 /* allow another 15 seconds to start */
1219 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1220 ServiceStatus.dwServiceSpecificExitCode = 0;
1221 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1222 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1223 ServiceStatus.dwCheckPoint = 2;
1224 ServiceStatus.dwWaitHint = 20000;
1225 /* accept Power Events */
1226 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1227 SetServiceStatus(StatusHandle, &ServiceStatus);
1232 MainThreadId = GetCurrentThreadId();
1233 jmpret = setjmp(notifier_jmp);
1238 code = afsd_InitCM(&reason);
1240 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1241 osi_panic(reason, __FILE__, __LINE__);
1245 ServiceStatus.dwCheckPoint++;
1246 ServiceStatus.dwWaitHint -= 5000;
1247 SetServiceStatus(StatusHandle, &ServiceStatus);
1249 code = afsd_InitDaemons(&reason);
1251 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1252 osi_panic(reason, __FILE__, __LINE__);
1255 /* allow an exit to be called post rx initialization */
1256 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1260 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1263 hookRc = rxStartedHook();
1265 FreeLibrary(hHookDll);
1268 if (hookRc == FALSE)
1270 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1271 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1272 ServiceStatus.dwCheckPoint = 0;
1273 ServiceStatus.dwWaitHint = 0;
1274 ServiceStatus.dwControlsAccepted = 0;
1275 SetServiceStatus(StatusHandle, &ServiceStatus);
1277 /* exit if initialization failed */
1283 ServiceStatus.dwCheckPoint++;
1284 ServiceStatus.dwWaitHint -= 5000;
1285 SetServiceStatus(StatusHandle, &ServiceStatus);
1288 /* the following ifdef chooses the mode of operation for the service. to enable
1289 * a runtime flag (instead of compile-time), pioctl() would need to dynamically
1290 * determine the mode, in order to use the correct ioctl special-file path. */
1292 code = afsd_InitSMB(&reason, MessageBox);
1294 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1295 osi_panic(reason, __FILE__, __LINE__);
1298 code = ifs_Init(&reason);
1300 afsi_log("ifs_Init failed: %s (code = %d)", reason, code);
1301 osi_panic(reason, __FILE__, __LINE__);
1303 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1304 hAFSDWorkerThread[cnt] = CreateThread(NULL, 0, ifs_MainLoop, 0, 0, NULL);
1307 /* allow an exit to be called post smb initialization */
1308 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1312 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1315 hookRc = smbStartedHook();
1317 FreeLibrary(hHookDll);
1320 if (hookRc == FALSE)
1322 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1323 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1324 ServiceStatus.dwCheckPoint = 0;
1325 ServiceStatus.dwWaitHint = 0;
1326 ServiceStatus.dwControlsAccepted = 0;
1327 SetServiceStatus(StatusHandle, &ServiceStatus);
1329 /* exit if initialization failed */
1334 MountGlobalDrives();
1337 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1338 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1339 ServiceStatus.dwCheckPoint = 0;
1340 ServiceStatus.dwWaitHint = 0;
1342 /* accept Power events */
1343 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1344 SetServiceStatus(StatusHandle, &ServiceStatus);
1347 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
1350 /* allow an exit to be called when started */
1351 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1355 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1358 hookRc = startedHook();
1360 FreeLibrary(hHookDll);
1363 if (hookRc == FALSE)
1365 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1366 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1367 ServiceStatus.dwCheckPoint = 0;
1368 ServiceStatus.dwWaitHint = 0;
1369 ServiceStatus.dwControlsAccepted = 0;
1370 SetServiceStatus(StatusHandle, &ServiceStatus);
1372 /* exit if initialization failed */
1378 WaitForSingleObject(WaitToTerminate, INFINITE);
1380 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
1381 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1382 CloseHandle(hAFSDWorkerThread[cnt]);
1385 afsi_log("Received Termination Signal, Stopping Service");
1388 LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP);
1390 LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
1392 /* allow an exit to be called prior to stopping the service */
1393 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1397 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1400 hookRc = stoppingHook();
1402 FreeLibrary(hHookDll);
1405 if (hookRc == FALSE)
1407 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1408 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1409 ServiceStatus.dwCheckPoint = 0;
1410 ServiceStatus.dwWaitHint = 0;
1411 ServiceStatus.dwControlsAccepted = 0;
1412 SetServiceStatus(StatusHandle, &ServiceStatus);
1414 /* exit if initialization failed */
1420 #ifdef AFS_FREELANCE_CLIENT
1421 cm_FreelanceShutdown();
1422 afsi_log("Freelance Shutdown complete");
1425 DismountGlobalDrives();
1426 afsi_log("Global Drives dismounted");
1428 cm_DaemonShutdown();
1429 afsi_log("Daemon shutdown complete");
1434 afsi_log("Buffer shutdown complete");
1437 afsi_log("rx finalization complete");
1441 afsi_log("smb shutdown complete");
1446 cm_ReleaseAllLocks();
1449 afsi_log("rx finalization complete");
1451 cm_ShutdownMappedMemory();
1453 #ifdef REGISTER_POWER_NOTIFICATIONS
1454 /* terminate thread used to flush cache */
1455 if (powerEventsRegistered)
1456 PowerNotificationThreadExit();
1459 /* allow an exit to be called after stopping the service */
1460 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1464 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1467 hookRc = stoppedHook();
1469 FreeLibrary(hHookDll);
1473 /* Remove the ExceptionFilter */
1474 SetUnhandledExceptionFilter(NULL);
1476 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1477 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1478 ServiceStatus.dwCheckPoint = 0;
1479 ServiceStatus.dwWaitHint = 0;
1480 ServiceStatus.dwControlsAccepted = 0;
1481 SetServiceStatus(StatusHandle, &ServiceStatus);
1484 DWORD __stdcall afsdMain_thread(void* notUsed)
1486 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1487 afsd_Main(1, (LPTSTR*)argv);
1493 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1497 main(int argc, char * argv[])
1499 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1500 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1505 for (i = 1; i < argc; i++) {
1506 if (!stricmp(argv[i],"--validate-cache")) {
1507 if (++i != argc - 1) {
1512 return cm_ValidateMappedMemory(argv[i]);
1519 if (!StartServiceCtrlDispatcher(dispatchTable))
1521 LONG status = GetLastError();
1522 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1525 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1527 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1529 SetEvent(WaitToTerminate);
1536 if ( hAFSDMainThread ) {
1537 WaitForSingleObject( hAFSDMainThread, INFINITE );
1538 CloseHandle( hAFSDMainThread );