//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1998. // // File: Reg.cpp // // Contents: Registration routines // // Classes: // // Notes: // // History: 05-Nov-97 rogerg Created. // 11-18-97 susia Added Autosync and user reg key functions // //-------------------------------------------------------------------------- #include "precomp.h" #ifdef _SENS #include // include event system #include #include #endif // _SENS // temporariy define new mstask flag in case hasn't // propogated to sdk\inc #ifndef TASK_FLAG_RUN_ONLY_IF_LOGGED_ON #define TASK_FLAG_RUN_ONLY_IF_LOGGED_ON (0x2000) #endif // TASK_FLAG_RUN_ONLY_IF_LOGGED_ON extern HINSTANCE g_hmodThisDll; // Handle to this DLL itself. extern OSVERSIONINFOA g_OSVersionInfo; extern CRITICAL_SECTION g_DllCriticalSection; // Global Critical Section for this DLL // only return success on NT 5.0 BOOL GetUserDefaultSecurityAttribs(SECURITY_ATTRIBUTES *psa ,PSECURITY_DESCRIPTOR psd, PACL *ppOutAcl) { BOOL bRetVal; int cbAcl; PACL pAcl = NULL; PSID pInteractiveUserSid = NULL; PSID pLocalSystemSid = NULL; PSID pAdminsSid = NULL; SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = SECURITY_NT_AUTHORITY; *ppOutAcl = NULL; bRetVal = FALSE; // in the structure. bRetVal = InitializeSecurityDescriptor( psd, // Pointer to SD SECURITY_DESCRIPTOR_REVISION // SD revision ); if (!bRetVal) { AssertSz(0,"Unable to Init SecurityDescriptor"); goto errRtn; } // setup acls. bRetVal = AllocateAndInitializeSid( &LocalSystemAuthority, // Pointer to identifier authority 1, // Count of subauthority SECURITY_INTERACTIVE_RID, // Subauthority 0 0, // Subauthority 1 0, // Subauthority 2 0, // Subauthority 3 0, // Subauthority 4 0, // Subauthority 5 0, // Subauthority 6 0, // Subauthority 7 &pInteractiveUserSid // pointer to pointer to SID ); if (!bRetVal) { AssertSz(0,"Alocate sid failed"); goto errRtn; } bRetVal = AllocateAndInitializeSid( &LocalSystemAuthority, // Pointer to identifier authority 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, // Subauthority 3 0, // Subauthority 4 0, // Subauthority 5 0, // Subauthority 6 0, // Subauthority 7 &pAdminsSid // pointer to pointer to SID ); if (!bRetVal) { AssertSz(0,"Alocate sid failed"); goto errRtn; } bRetVal = AllocateAndInitializeSid( &LocalSystemAuthority,// Pointer to identifier authority 1, // Count of subauthority SECURITY_LOCAL_SYSTEM_RID, // Subauthority 0 0, // Subauthority 1 0, // Subauthority 2 0, // Subauthority 3 0, // Subauthority 4 0, // Subauthority 5 0, // Subauthority 6 0, // Subauthority 7 &pLocalSystemSid // pointer to pointer to SID ); if (!bRetVal) { AssertSz(0,"Alocate sid failed"); goto errRtn; } cbAcl = sizeof (ACL) + 3 * sizeof (ACCESS_ALLOWED_ACE) + GetLengthSid(pInteractiveUserSid) + GetLengthSid(pLocalSystemSid) + GetLengthSid(pAdminsSid); pAcl = (PACL) new char[cbAcl]; if (NULL == pAcl) { bRetVal = FALSE; AssertSz(0,"unable to alloc ACL"); goto errRtn; } bRetVal = InitializeAcl( pAcl, // Pointer to the ACL cbAcl, // Size of ACL ACL_REVISION // Revision level of ACL ); if (!bRetVal) { AssertSz(0,"InitAcl failed"); goto errRtn; } bRetVal = AddAccessAllowedAce( pAcl, // Pointer to the ACL ACL_REVISION, // ACL revision level SPECIFIC_RIGHTS_ALL | GENERIC_READ | DELETE , // Access Mask pInteractiveUserSid // Pointer to SID ); if (!bRetVal) { AssertSz(0,"AddAccessAllowed Failed"); goto errRtn; } bRetVal = AddAccessAllowedAce( pAcl, // Pointer to the ACL ACL_REVISION, // ACL revision level GENERIC_ALL, // Access Mask pAdminsSid // Pointer to SID ); if (!bRetVal) { AssertSz(0,"AddAccessAllowed Failed"); goto errRtn; } bRetVal = AddAccessAllowedAce( pAcl, // Pointer to the ACL ACL_REVISION, // ACL revision level GENERIC_ALL, // Access Mask pLocalSystemSid // Pointer to SID ); if (!bRetVal) { AssertSz(0,"AddAccessAllowed Failed"); goto errRtn; } bRetVal = SetSecurityDescriptorDacl(psd,TRUE,pAcl,FALSE); if (!bRetVal) { AssertSz(0,"SetSecurityDescirptorDacl Failed"); goto errRtn; } psa->nLength = sizeof(SECURITY_ATTRIBUTES); psa->lpSecurityDescriptor = psd; psa->bInheritHandle = FALSE; errRtn: if (pInteractiveUserSid) { FreeSid(pInteractiveUserSid); } if (pLocalSystemSid) { FreeSid(pLocalSystemSid); } if (pAdminsSid) { FreeSid(pAdminsSid); } // // On failure, we clean the ACL up. On success, the caller cleans // it up after using it. // if (FALSE == bRetVal) { if (pAcl) { delete pAcl; } } else { Assert(pAcl); *ppOutAcl = pAcl; } return bRetVal; } const WCHAR SZ_USERSIDKEY[] = TEXT("SID"); // calls regOpen or create based on fCreate param LONG RegGetKeyHelper(HKEY hkey,LPCWSTR pszKey,REGSAM samDesired,BOOL fCreate, HKEY *phkResult,DWORD *pdwDisposition) { LONG lRet = -1; Assert(pdwDisposition); *pdwDisposition = 0; if (fCreate) { lRet = RegCreateKeyEx(hkey,pszKey,0,NULL,REG_OPTION_NON_VOLATILE, samDesired,NULL,phkResult,pdwDisposition); } else { lRet = RegOpenKeyEx(hkey,pszKey,0,samDesired,phkResult); if (ERROR_SUCCESS == lRet) { *pdwDisposition = REG_OPENED_EXISTING_KEY; } } return lRet; } // called to create a new UserKey or subkey LONG RegCreateUserSubKey( HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, PHKEY phkResult) { LONG lRet; DWORD dwDisposition; lRet = RegCreateKeyEx(hKey,lpSubKey,0,NULL,REG_OPTION_NON_VOLATILE, samDesired,NULL,phkResult,&dwDisposition); if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId) { // !! if subkey contains \\ don't traverse back through the list if ( (ERROR_SUCCESS == lRet) && (REG_CREATED_NEW_KEY == dwDisposition)) { HKEY hKeySecurity; SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; PACL pOutAcl; if (ERROR_SUCCESS == RegOpenKeyEx(hKey, lpSubKey, REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) ) { if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl)) { RegSetKeySecurity(hKeySecurity, (SECURITY_INFORMATION) DACL_SECURITY_INFORMATION, &sd); delete pOutAcl; } RegCloseKey(hKeySecurity); } } } return lRet; } STDAPI_(HKEY) RegOpenUserKey(HKEY hkeyParent,REGSAM samDesired,BOOL fCreate,BOOL fCleanReg) { TCHAR pszDomainAndUser[MAX_DOMANDANDMACHINENAMESIZE]; HKEY hKeyUser; BOOL fSetUserSid = FALSE; WCHAR szUserSID[MAX_PATH + 1]; DWORD dwType; DWORD dwDisposition; LONG ret; GetDefaultDomainAndUserName(pszDomainAndUser,TEXT("_"),MAX_DOMANDANDMACHINENAMESIZE); // If suppose to clean the settings for the user/ delete the key if (fCleanReg) { RegDeleteKeyNT(hkeyParent,pszDomainAndUser); } if (ERROR_SUCCESS != (ret = RegGetKeyHelper(hkeyParent,pszDomainAndUser,samDesired,fCreate, &hKeyUser,&dwDisposition))) { hKeyUser = NULL; } // On NT 5.0 Verify sid matches and if doesn't blow away any settings. // then create again. if (hKeyUser && (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)) { WCHAR szRegSID[MAX_PATH + 1]; DWORD dwDataSize; dwDataSize = ARRAY_SIZE(szRegSID); if (ERROR_SUCCESS !=RegQueryValueEx(hKeyUser, SZ_USERSIDKEY,NULL, &dwType, (LPBYTE) szRegSID, &dwDataSize)) { fSetUserSid = TRUE; // if have to set the sid need to make sure openned // with set Value and if didn't close key and // let create re-open it with the desired access. if (!(samDesired & KEY_SET_VALUE)) { RegCloseKey(hKeyUser); hKeyUser = NULL; } } else { dwDataSize = ARRAY_SIZE(szUserSID); if (GetUserTextualSid(szUserSID, &dwDataSize)) { if (lstrcmp(szRegSID, szUserSID)) { // if don't have access privledges // to delete the User this will fail. // may want a call into SENS to delete the // User Key on Failure. RegCloseKey(hKeyUser); hKeyUser = NULL; // set to NULL so check below fails. RegDeleteKeyNT(hkeyParent,pszDomainAndUser); } } } } if (NULL == hKeyUser) { if (ERROR_SUCCESS != (ret = RegGetKeyHelper(hkeyParent,pszDomainAndUser, samDesired,fCreate, &hKeyUser,&dwDisposition))) { hKeyUser = NULL; } else { if (REG_CREATED_NEW_KEY == dwDisposition) { fSetUserSid = TRUE; } } } // on creation setup the security if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId) { if ( (ERROR_SUCCESS == ret) && (REG_CREATED_NEW_KEY == dwDisposition)) { HKEY hKeySecurity; SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; PACL pOutAcl; // !! should have own call for sync type key security if (ERROR_SUCCESS == RegOpenKeyEx(hkeyParent,pszDomainAndUser, REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) ) { if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl)) { RegSetKeySecurity(hKeySecurity, (SECURITY_INFORMATION) DACL_SECURITY_INFORMATION, &sd); delete pOutAcl; } RegCloseKey(hKeySecurity); } } } // setup the User sid. // depends on key being openned with KEY_SET_VALUE if (hKeyUser && fSetUserSid && (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId) && (samDesired & KEY_SET_VALUE)) { WCHAR szUserSID[MAX_PATH + 1]; DWORD dwDataSize; dwDataSize = ARRAY_SIZE(szUserSID); if (GetUserTextualSid(szUserSID, &dwDataSize)) { DWORD dwType = REG_SZ; RegSetValueEx (hKeyUser,SZ_USERSIDKEY,NULL, dwType, (LPBYTE) szUserSID, (lstrlen(szUserSID) + 1)*sizeof(WCHAR)); } } return hKeyUser; } STDAPI_(HKEY) RegGetSyncTypeKey(DWORD dwSyncType,REGSAM samDesired,BOOL fCreate) { HKEY hKeySyncType; LPCWSTR pszKey; LONG ret; DWORD dwDisposition; // get appropriate key to open based on sync type switch(dwSyncType) { case SYNCTYPE_MANUAL: pszKey = MANUALSYNC_REGKEY; break; case SYNCTYPE_AUTOSYNC: pszKey = AUTOSYNC_REGKEY; break; case SYNCTYPE_IDLE: pszKey = IDLESYNC_REGKEY; break; case SYNCTYPE_SCHEDULED: pszKey = SCHEDSYNC_REGKEY; break; case SYNCTYPE_PROGRESS: pszKey = PROGRESS_REGKEY; break; default: AssertSz(0,"Unknown SyncType"); pszKey = NULL; break; } if (NULL == pszKey) { return NULL; } // first try to open the existing key if (ERROR_SUCCESS != (ret = RegGetKeyHelper(HKEY_LOCAL_MACHINE,pszKey,samDesired,fCreate, &hKeySyncType,&dwDisposition))) { // if can't open key try to create if (ERROR_ACCESS_DENIED == ret ) { // if access denied, call sens to reset // the security on the topelevel keys. SyncMgrExecCmd_ResetRegSecurity(); ret = RegGetKeyHelper(HKEY_LOCAL_MACHINE,pszKey,samDesired,fCreate, &hKeySyncType,&dwDisposition); } if (ERROR_SUCCESS != ret) { hKeySyncType = NULL; } } if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId) { if ( (ERROR_SUCCESS == ret) && (REG_CREATED_NEW_KEY == dwDisposition)) { HKEY hKeySecurity; SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; PACL pOutAcl; // !! should have own call for sync type key security if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,pszKey, REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) ) { if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl)) { RegSetKeySecurity(hKeySecurity, (SECURITY_INFORMATION) DACL_SECURITY_INFORMATION, &sd); delete pOutAcl; } RegCloseKey(hKeySecurity); } } } return hKeySyncType; } STDAPI_(HKEY) RegGetCurrentUserKey(DWORD dwSyncType,REGSAM samDesired,BOOL fCreate) { HKEY hKeySyncType; HKEY hKeyUser = NULL; hKeySyncType = RegGetSyncTypeKey(dwSyncType,samDesired ,fCreate); if (hKeySyncType) { hKeyUser = RegOpenUserKey(hKeySyncType,samDesired,fCreate,FALSE /* fClean */); RegCloseKey(hKeySyncType); } return hKeyUser; } // tries to open and set security if necessary on the handler keys. STDAPI_(HKEY) RegGetHandlerTopLevelKey(REGSAM samDesired) { HKEY hKeyTopLevel; LONG ret; DWORD dwDisposition; // if open failed then try a create. if (ERROR_SUCCESS != (ret = RegCreateKeyEx (HKEY_LOCAL_MACHINE,HANDLERS_REGKEY,0, NULL, REG_OPTION_NON_VOLATILE,samDesired,NULL, &hKeyTopLevel, &dwDisposition))) { // if got an access denige on the handlers key // call sens to reset. if (ERROR_ACCESS_DENIED == ret ) { // if access denied, call sens to reset // the security on the topelevel keys. // and try again SyncMgrExecCmd_ResetRegSecurity(); ret = RegCreateKeyEx (HKEY_LOCAL_MACHINE,HANDLERS_REGKEY,0, NULL, REG_OPTION_NON_VOLATILE,samDesired,NULL, &hKeyTopLevel, &dwDisposition); } if (ERROR_SUCCESS != ret) { hKeyTopLevel = NULL; } } if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId) { if ( (ERROR_SUCCESS == ret) && (REG_CREATED_NEW_KEY == dwDisposition)) { HKEY hKeySecurity; SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; PACL pOutAcl; // !! should have own call for toplevel handler key security if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, HANDLERS_REGKEY, REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) ) { if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl)) { RegSetKeySecurity(hKeySecurity, (SECURITY_INFORMATION) DACL_SECURITY_INFORMATION, &sd); delete pOutAcl; } RegCloseKey(hKeySecurity); } } } return hKeyTopLevel; } STDAPI_(HKEY) RegGetHandlerKey(HKEY hkeyParent,LPCWSTR pszHandlerClsid,REGSAM samDesired, BOOL fCreate) { HKEY hKeyHandler = NULL; LRESULT lRet; DWORD dwDisposition; if (ERROR_SUCCESS != (lRet = RegGetKeyHelper(hkeyParent,pszHandlerClsid,samDesired, fCreate,&hKeyHandler,&dwDisposition))) { hKeyHandler = NULL; } if (NULL == hKeyHandler) { // if got an access denied call sens to unlock if (ERROR_ACCESS_DENIED == lRet ) { // if access denied, call sens to reset // the security on the topelevel keys. // and try again SyncMgrExecCmd_ResetRegSecurity(); lRet = RegGetKeyHelper(hkeyParent,pszHandlerClsid,samDesired, fCreate,&hKeyHandler,&dwDisposition); } if (ERROR_SUCCESS != lRet) { hKeyHandler = NULL; } } if (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId) { if ( (ERROR_SUCCESS == lRet) && (REG_CREATED_NEW_KEY == dwDisposition)) { HKEY hKeySecurity; SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; PACL pOutAcl; // !! should have own call for handler key security if (ERROR_SUCCESS == RegOpenKeyEx(hkeyParent, pszHandlerClsid, REG_OPTION_OPEN_LINK, WRITE_DAC,&hKeySecurity) ) { if (GetUserDefaultSecurityAttribs(&sa,&sd,&pOutAcl)) { RegSetKeySecurity(hKeySecurity, (SECURITY_INFORMATION) DACL_SECURITY_INFORMATION, &sd); delete pOutAcl; } RegCloseKey(hKeySecurity); } } } return hKeyHandler; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: DWORD RegDeleteKeyNT(HKEY hStartKey , LPTSTR pKeyName ) Summary: Recursively delete a key on NT Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(DWORD) RegDeleteKeyNT(HKEY hStartKey , LPCWSTR pKeyName ) { DWORD dwRtn, dwSubKeyLength; LPTSTR pSubKey = NULL; TCHAR szSubKey[MAX_KEY_LENGTH]; // (256) this should be dynamic. HKEY hkey; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); // do not allow NULL or empty key name if ( pKeyName && lstrlen(pKeyName)) { if( (dwRtn=RegOpenKeyEx(hStartKey,pKeyName, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hkey )) == ERROR_SUCCESS) { while (dwRtn == ERROR_SUCCESS ) { dwSubKeyLength = MAX_KEY_LENGTH; dwRtn=RegEnumKeyEx( hkey, 0, // always index zero szSubKey, &dwSubKeyLength, NULL, NULL, NULL, NULL ); if(dwRtn == ERROR_NO_MORE_ITEMS) { dwRtn = RegDeleteKey(hStartKey, pKeyName); break; } else if(dwRtn == ERROR_SUCCESS) dwRtn=RegDeleteKeyNT(hkey, szSubKey); } RegCloseKey(hkey); // Do not save return code because error // has already occurred } } else dwRtn = ERROR_BADKEY; CMutexRegistry.Leave(); return dwRtn; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegGetProgressDetailsState() Summary: Gets the expanded or collapsed user preference for the progress dialog and the pushpin preference Returns: Returns TRUE if succeeded, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegGetProgressDetailsState(REFCLSID clsidDlg,BOOL *pfPushPin, BOOL *pfExpanded) { SCODE sc = S_FALSE; HKEY hkeyUserProgress,hkeyclsidDlg; DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); WCHAR wszCLSID[GUID_SIZE + 1]; if (0 == StringFromGUID2(clsidDlg, wszCLSID, GUID_SIZE)) { AssertSz(0,"Unable to make Guid a String"); return FALSE; } //Prgress dialog defaults to collapsed, pushpin out *pfExpanded = FALSE; *pfPushPin = FALSE; hkeyUserProgress = RegGetCurrentUserKey(SYNCTYPE_PROGRESS,KEY_READ,FALSE); if (hkeyUserProgress) { if (ERROR_SUCCESS == RegOpenKeyEx(hkeyUserProgress,wszCLSID,0,KEY_READ, &hkeyclsidDlg)) { RegQueryValueEx(hkeyclsidDlg,TEXT("Expanded"),NULL, &dwType, (LPBYTE) pfExpanded, &dwDataSize); dwType = REG_DWORD ; dwDataSize = sizeof(DWORD); RegQueryValueEx(hkeyclsidDlg,TEXT("PushPin"),NULL, &dwType, (LPBYTE) pfPushPin, &dwDataSize); RegCloseKey(hkeyclsidDlg); sc = S_OK; } RegCloseKey(hkeyUserProgress); } if (sc == S_OK) return TRUE; else return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegSetProgressDetailsState(BOOL fExpanded) Summary: Sets the expanded or collapsed user preference for the progress dialog Returns: Returns TRUE if succeeded, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegSetProgressDetailsState(REFCLSID clsidDlg,BOOL fPushPin, BOOL fExpanded) { BOOL fResult = FALSE; HKEY hkeyUserProgress,hkeyclsidDlg; WCHAR wszCLSID[GUID_SIZE + 1]; if (0 == StringFromGUID2(clsidDlg, wszCLSID, GUID_SIZE)) { AssertSz(0,"Unable to make Guid a String"); return FALSE; } CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); hkeyUserProgress = RegGetCurrentUserKey(SYNCTYPE_PROGRESS,KEY_WRITE | KEY_READ,TRUE); if (hkeyUserProgress) { if (ERROR_SUCCESS == RegCreateUserSubKey(hkeyUserProgress,wszCLSID, KEY_WRITE | KEY_READ, &hkeyclsidDlg)) { fResult = TRUE; if (ERROR_SUCCESS != RegSetValueEx(hkeyclsidDlg,TEXT("Expanded"),NULL, REG_DWORD, (LPBYTE) &(fExpanded), sizeof(DWORD))) { fResult = FALSE; } if (ERROR_SUCCESS == RegSetValueEx(hkeyclsidDlg,TEXT("PushPin"),NULL, REG_DWORD, (LPBYTE) &(fPushPin), sizeof(DWORD))) { fResult = FALSE; } RegCloseKey(hkeyclsidDlg); } RegCloseKey(hkeyUserProgress); } CMutexRegistry.Leave(); return fResult; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegGetSyncItemSettings( DWORD dwSyncType, CLSID clsidHandler, SYNCMGRITEMID ItemId, const TCHAR *pszConnectionName, DWORD *pdwCheckState, DWORD dwDefaultCheckState, TCHAR *pszSchedName) Summary: Gets the settings per handler, itemID, and connection name. If no selections on this connection, the default is ? Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegGetSyncItemSettings( DWORD dwSyncType, CLSID clsidHandler, SYNCMGRITEMID ItemId, const TCHAR *pszConnectionName, DWORD *pdwCheckState, DWORD dwDefaultCheckState, TCHAR *pszSchedName) { HKEY hKeyUser; *pdwCheckState = dwDefaultCheckState; // special case schedule if (SYNCTYPE_SCHEDULED == dwSyncType) { // items are always turned off by default and if no schedule name // don't bother. *pdwCheckState = FALSE; if (!pszSchedName) { return FALSE; } } // open the user key for the type hKeyUser = RegGetCurrentUserKey(dwSyncType,KEY_READ,FALSE); if (NULL == hKeyUser) { return FALSE; } // for a schedule we need to go ahead and open up the schedule name // key HKEY hKeySchedule = NULL; // Review if want GetCurrentUserKey to Handle this. if (SYNCTYPE_SCHEDULED == dwSyncType) { if (ERROR_SUCCESS != RegOpenKeyEx((hKeyUser), pszSchedName,0,KEY_READ, &hKeySchedule)) { hKeySchedule = NULL; RegCloseKey(hKeyUser); return FALSE; } } BOOL fResult; fResult = RegLookupSettings(hKeySchedule ? hKeySchedule : hKeyUser, clsidHandler, ItemId, pszConnectionName, pdwCheckState); if (hKeySchedule) { RegCloseKey(hKeySchedule); } if (hKeyUser) { RegCloseKey(hKeyUser); } return fResult; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegSetSyncItemSettings( DWORD dwSyncType, CLSID clsidHandler, SYNCMGRITEMID ItemId, const TCHAR *pszConnectionName, DWORD dwCheckState, TCHAR *pszSchedName) Summary: Sets the settings per handler, itemID, and connection name. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegSetSyncItemSettings( DWORD dwSyncType, CLSID clsidHandler, SYNCMGRITEMID ItemId, const TCHAR *pszConnectionName, DWORD dwCheckState, TCHAR *pszSchedName) { HKEY hKeyUser; if (SYNCTYPE_SCHEDULED == dwSyncType) { if (NULL == pszSchedName) { return FALSE; } } // open the user key for the type hKeyUser = RegGetCurrentUserKey(dwSyncType,KEY_WRITE | KEY_READ,TRUE); if (NULL == hKeyUser) { return FALSE; } // for a schedule we need to go ahead and open up the schedule name // key HKEY hKeySchedule = NULL; if (SYNCTYPE_SCHEDULED == dwSyncType) { if (ERROR_SUCCESS != RegCreateUserSubKey(hKeyUser, pszSchedName,KEY_WRITE | KEY_READ, &hKeySchedule)) { hKeySchedule = NULL; RegCloseKey(hKeyUser); return FALSE; } } BOOL fResult; fResult = RegWriteOutSettings(hKeySchedule ? hKeySchedule : hKeyUser, clsidHandler, ItemId, pszConnectionName, dwCheckState); if (hKeySchedule) { RegCloseKey(hKeySchedule); } if (hKeyUser) { RegCloseKey(hKeyUser); } return fResult; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegQueryLoadHandlerOnEvent( ) Summary: Determines if there is any reason to load this handler for the specified event and Connection Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegQueryLoadHandlerOnEvent(TCHAR *pszClsid,DWORD dwSyncFlags, TCHAR *pConnectionName) { BOOL fLoadHandler = FALSE; DWORD dwSyncType; switch(dwSyncFlags & SYNCMGRFLAG_EVENTMASK) { case SYNCMGRFLAG_CONNECT: case SYNCMGRFLAG_PENDINGDISCONNECT: { dwSyncType = SYNCTYPE_AUTOSYNC; } break; case SYNCMGRFLAG_IDLE: { dwSyncType = SYNCTYPE_IDLE; } break; default: AssertSz(0,"Unknown SyncType"); return FALSE; break; } // walk done the list openning keys. HKEY hkeySyncType; if (hkeySyncType = RegGetCurrentUserKey(dwSyncType,KEY_READ,FALSE)) { HKEY hkeyConnectionName; if (ERROR_SUCCESS == RegOpenKeyEx(hkeySyncType,pConnectionName,0,KEY_READ,&hkeyConnectionName)) { HKEY hkeyClsid; if (ERROR_SUCCESS == RegOpenKeyEx(hkeyConnectionName,pszClsid,0,KEY_READ,&hkeyClsid)) { DWORD dwType = REG_DWORD; DWORD dwDataSize = sizeof(DWORD); DWORD fQueryResult; if (ERROR_SUCCESS == RegQueryValueEx(hkeyClsid,TEXT("ItemsChecked"),NULL, &dwType, (LPBYTE) &fQueryResult, &dwDataSize)) { fLoadHandler = fQueryResult; } RegCloseKey(hkeyClsid); } RegCloseKey(hkeyConnectionName); } RegCloseKey(hkeySyncType); } return fLoadHandler; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegSetSyncHandlerSettings( ) Summary: Sets the handler settings for syncType and Connection. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegSetSyncHandlerSettings(DWORD dwSyncType, const TCHAR *pszConnectionName, CLSID clsidHandler, BOOL fItemsChecked) { HKEY hKeyUser; hKeyUser = RegGetCurrentUserKey(dwSyncType,KEY_WRITE | KEY_READ,TRUE); if (NULL == hKeyUser) { return FALSE; } SCODE sc; HKEY hkeyConnection; HKEY hkeyCLSID; DWORD dwType = REG_DWORD; DWORD dwDataSize = sizeof(DWORD); TCHAR szCLSID[(GUID_SIZE+1)]; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); smChkTo(EH_Err2,RegCreateUserSubKey(hKeyUser, pszConnectionName, KEY_WRITE | KEY_READ, &hkeyConnection)); StringFromGUID2(clsidHandler, szCLSID, 2*GUID_SIZE); // Write entries under CLSID. smChkTo(EH_Err3,RegCreateUserSubKey(hkeyConnection, szCLSID,KEY_WRITE | KEY_READ, &hkeyCLSID)); RegSetValueEx(hkeyCLSID,TEXT("ItemsChecked"),NULL, REG_DWORD, (LPBYTE) &fItemsChecked, sizeof(DWORD)); RegCloseKey(hKeyUser); RegCloseKey(hkeyConnection); RegCloseKey(hkeyCLSID); CMutexRegistry.Leave(); return TRUE; EH_Err3: RegCloseKey(hkeyConnection); EH_Err2: RegCloseKey(hKeyUser); CMutexRegistry.Leave(); return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegLookupSettings(const TCHAR *hkeyName, CLSID clsidHandler, SYNCMGRITEMID ItemID, const TCHAR *pszMachineName, const TCHAR *pszConnectionName, DWORD pdwCheckState) Summary: Gets the settings per handler, itemID, and connection name. Returns: Returns TRUE if there are settings for this item and connection, flase otherwise. ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegLookupSettings(HKEY hKeyUser, CLSID clsidHandler, SYNCMGRITEMID ItemID, const TCHAR *pszConnectionName, DWORD *pdwCheckState) { SCODE sc; HKEY hkeyConnection; HKEY hkeyItem; HKEY hKeyHandler; DWORD dwType = REG_SZ; DWORD dwDataSize = MAX_PATH + 1; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); TCHAR szID[GUID_SIZE+1]; TCHAR szCLSID[2*(GUID_SIZE+1)]; dwType = REG_DWORD; dwDataSize = sizeof(DWORD); smChkTo(EH_Err2,RegOpenKeyEx(hKeyUser, pszConnectionName,0,KEY_READ, &hkeyConnection)); StringFromGUID2(clsidHandler, szCLSID, 2*GUID_SIZE); StringFromGUID2(ItemID, szID, GUID_SIZE); // Read entries under CLSID. smChkTo(EH_Err3,RegOpenKeyEx((hkeyConnection), szCLSID, 0, KEY_READ, &hKeyHandler)); smChkTo(EH_Err4,RegOpenKeyEx((hKeyHandler), szID, 0, KEY_READ, &hkeyItem)); RegQueryValueEx(hkeyItem,TEXT("CheckState"),NULL, &dwType, (LPBYTE)pdwCheckState, &dwDataSize); RegCloseKey(hkeyConnection); RegCloseKey(hkeyItem); RegCloseKey(hKeyHandler); CMutexRegistry.Leave(); return TRUE; EH_Err4: RegCloseKey(hKeyHandler); EH_Err3: RegCloseKey(hkeyConnection); EH_Err2: CMutexRegistry.Leave(); return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegWriteOutSettings(const TCHAR *hkeyName, CLSID clsidHandler, SYNCMGRITEMID ItemID, const TCHAR *pszConnectionName, DWORD dwCheckState) Summary: Sets the settings per handler, itemID, and connection name. Returns: Returns TRUE if we can set them, FALSE if there is an error ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegWriteOutSettings(HKEY hKeyUser, CLSID clsidHandler, SYNCMGRITEMID ItemID, const TCHAR *pszConnectionName, DWORD dwCheckState) { SCODE sc; HKEY hkeyConnection; HKEY hKeyHandler; HKEY hkeyItem; DWORD dwType = REG_SZ; DWORD dwDataSize = MAX_PATH; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); TCHAR szID[GUID_SIZE+1]; TCHAR szCLSID[2*(GUID_SIZE+1)]; smChkTo(EH_Err2,RegCreateUserSubKey(hKeyUser, pszConnectionName,KEY_WRITE | KEY_READ, &hkeyConnection)); StringFromGUID2(clsidHandler, szCLSID, 2*GUID_SIZE); StringFromGUID2(ItemID, szID, GUID_SIZE); smChkTo(EH_Err3,RegCreateUserSubKey(hkeyConnection, szCLSID,KEY_WRITE | KEY_READ, &hKeyHandler)); // Write entries under CLSID. smChkTo(EH_Err4,RegCreateUserSubKey(hKeyHandler, szID,KEY_WRITE | KEY_READ, &hkeyItem)); RegSetValueEx(hkeyItem,TEXT("CheckState"),NULL, REG_DWORD, (LPBYTE) &dwCheckState, sizeof(DWORD)); RegCloseKey(hkeyConnection); RegCloseKey(hkeyItem); RegCloseKey(hKeyHandler); CMutexRegistry.Leave(); return TRUE; EH_Err4: RegCloseKey(hKeyHandler); EH_Err3: RegCloseKey(hkeyConnection); EH_Err2: CMutexRegistry.Leave(); return FALSE; } /**************************************************************************** AutoSync Registry Functions ***************************************************************************F-F*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegGetAutoSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings) Summary: Gets the logon, logoff and prompt me first user selections. If no selections on this connection, the default is ? Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegGetAutoSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings) { SCODE sc; HKEY hkeyConnection; DWORD dwType = REG_SZ ; DWORD dwDataSize = MAX_PATH; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); // Set these first to default values, in case there are no current // user preferences in the registry lpConnectionSettings->dwLogon = FALSE; lpConnectionSettings->dwLogoff = FALSE; lpConnectionSettings->dwPromptMeFirst = FALSE; HKEY hKeyUser; hKeyUser = RegGetCurrentUserKey(SYNCTYPE_AUTOSYNC,KEY_READ,FALSE); if (NULL == hKeyUser) { goto EH_Err; } dwType = REG_DWORD ; dwDataSize = sizeof(DWORD); smChkTo(EH_Err3,RegOpenKeyEx(hKeyUser, lpConnectionSettings->pszConnectionName,0,KEY_READ, &hkeyConnection)); RegQueryValueEx(hkeyConnection,TEXT("Logon"),NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwLogon), &dwDataSize); dwDataSize = sizeof(DWORD); RegQueryValueEx(hkeyConnection,TEXT("Logoff"),NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwLogoff), &dwDataSize); dwDataSize = sizeof(DWORD); RegQueryValueEx(hkeyConnection,TEXT("PromptMeFirst"),NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwPromptMeFirst), &dwDataSize); RegCloseKey(hkeyConnection); RegCloseKey(hKeyUser); CMutexRegistry.Leave(); return TRUE; EH_Err3: RegCloseKey(hKeyUser); EH_Err: CMutexRegistry.Leave(); return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegUpdateUserAutosyncKey Summary: given an Autosync User Key makes sure it is in the latest format and if not updates it. Returns: ------------------------------------------------------------------------F-F*/ void RegUpdateUserAutosyncKey(HKEY hkeyUser,BOOL fForce) { DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); DWORD dwUserLogonLogoff; DWORD dwIndex = 0; TCHAR lpName[MAX_PATH]; DWORD cbName = MAX_PATH; DWORD dwLogon = 0; DWORD dwLogoff = 0; if (!fForce && (ERROR_SUCCESS == RegQueryValueEx(hkeyUser,TEXT("Logon"),NULL, &dwType, (LPBYTE) &dwUserLogonLogoff, &dwDataSize)) ) { // if can open Logon Key this is up to date. return; } // need to enum connection names and update the toplevel information. while ( ERROR_SUCCESS == RegEnumKey(hkeyUser,dwIndex, lpName,cbName) ) { LONG lRet; HKEY hKeyConnection; lRet = RegOpenKeyEx( hkeyUser, lpName, NULL, KEY_READ, &hKeyConnection ); if (ERROR_SUCCESS == lRet) { dwDataSize = sizeof(DWORD); if (ERROR_SUCCESS == RegQueryValueEx(hKeyConnection,TEXT("Logon"),NULL, &dwType, (LPBYTE) &dwUserLogonLogoff, &dwDataSize) ) { dwLogon |= dwUserLogonLogoff; } dwDataSize = sizeof(DWORD); if (ERROR_SUCCESS == RegQueryValueEx(hKeyConnection,TEXT("Logoff"),NULL, &dwType, (LPBYTE) &dwUserLogonLogoff, &dwDataSize) ) { dwLogoff |= dwUserLogonLogoff; } RegCloseKey(hKeyConnection); } dwIndex++; } // write out new flags even if errors occured. work thing that happens is // we don't set up someones autosync automatically. RegSetValueEx(hkeyUser,TEXT("Logon"),NULL, REG_DWORD, (LPBYTE) &(dwLogon), sizeof(DWORD)); RegSetValueEx(hkeyUser,TEXT("Logoff"),NULL, REG_DWORD, (LPBYTE) &(dwLogoff), sizeof(DWORD)); RegWriteTimeStamp(hkeyUser); } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegUpdateAutoSyncKeyValueSettings Summary: walks through the UserList Updating the AutoSync Returns: ------------------------------------------------------------------------F-F*/ void RegUpdateAutoSyncKeyValue(HKEY hkeyAutoSync,DWORD dwLogonDefault,DWORD dwLogoffDefault) { DWORD dwIndex = 0; WCHAR lpName[MAX_PATH]; DWORD cbName = MAX_PATH; LONG lRet; DWORD dwLogon = 0; DWORD dwLogoff = 0; BOOL fSetLogon,fSetLogoff; // need to walk the autosync user key and set the top level information // based on whther someone logon/logoff CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); while ( ERROR_SUCCESS == (lRet = RegEnumKey(hkeyAutoSync,dwIndex, lpName,cbName) )) { DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); DWORD dwUserLogonLogoff; HKEY hKeyDomainUser; lRet = RegOpenKeyEx( hkeyAutoSync, lpName, NULL, KEY_READ, &hKeyDomainUser ); if (ERROR_SUCCESS == lRet) { // If Query fails don't want to count this as a failed to enum // error so don't set lRet if (ERROR_SUCCESS == (RegQueryValueEx(hKeyDomainUser,TEXT("Logon"),NULL, &dwType, (LPBYTE) &dwUserLogonLogoff, &dwDataSize) )) { dwLogon |= dwUserLogonLogoff; } dwDataSize = sizeof(DWORD); if (ERROR_SUCCESS == lRet) { if (ERROR_SUCCESS == (RegQueryValueEx(hKeyDomainUser,TEXT("Logoff"),NULL, &dwType, (LPBYTE) &dwUserLogonLogoff, &dwDataSize) ) ) { dwLogoff |= dwUserLogonLogoff; } } RegCloseKey(hKeyDomainUser); } if (ERROR_SUCCESS != lRet) { break; } dwIndex++; } fSetLogon = FALSE; fSetLogoff = FALSE; // if an error occured, then use the passed in defaults, // if set to 1, else don't set. if ( (ERROR_SUCCESS != lRet) && (ERROR_NO_MORE_ITEMS != lRet)) { if ( (-1 != dwLogonDefault) && (0 != dwLogonDefault)) { fSetLogon = TRUE; dwLogon = dwLogonDefault; } if ( (-1 != dwLogoffDefault) && (0 != dwLogoffDefault)) { fSetLogoff = TRUE; dwLogoff = dwLogoffDefault; } } else { fSetLogon = TRUE; fSetLogoff = TRUE; } // write out new flags even if errors occured. work thing that happens is // we don't set up someones autosync automatically. if (fSetLogon) { RegSetValueEx(hkeyAutoSync,TEXT("Logon"),NULL, REG_DWORD, (LPBYTE) &(dwLogon), sizeof(DWORD)); } if (fSetLogoff) { RegSetValueEx(hkeyAutoSync,TEXT("Logoff"),NULL, REG_DWORD, (LPBYTE) &(dwLogoff), sizeof(DWORD)); } RegWriteTimeStamp(hkeyAutoSync); CMutexRegistry.Leave(); } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegUpdateUserIdleKey Summary: given an Idle User Key makes sure it is in the latest format and if not updates it. Returns: ------------------------------------------------------------------------F-F*/ void RegUpdateUserIdleKey(HKEY hkeyUser,BOOL fForce) { DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); DWORD dwUserIdleEnabled; DWORD dwIndex = 0; TCHAR lpName[MAX_PATH]; DWORD cbName = MAX_PATH; DWORD dwIdleEnabled = 0; if (!fForce && (ERROR_SUCCESS == RegQueryValueEx(hkeyUser,TEXT("IdleEnabled"),NULL, &dwType, (LPBYTE) &dwUserIdleEnabled, &dwDataSize)) ) { // if can open Logon Key this is up to date. return; } // need to enum connection names and update the toplevel information. while ( ERROR_SUCCESS == RegEnumKey(hkeyUser,dwIndex, lpName,cbName) ) { LONG lRet; HKEY hKeyConnection; lRet = RegOpenKeyEx( hkeyUser, lpName, NULL, KEY_READ, &hKeyConnection ); if (ERROR_SUCCESS == lRet) { dwDataSize = sizeof(DWORD); if (ERROR_SUCCESS == RegQueryValueEx(hKeyConnection,TEXT("IdleEnabled"),NULL, &dwType, (LPBYTE) &dwUserIdleEnabled, &dwDataSize) ) { dwIdleEnabled |= dwUserIdleEnabled; } RegCloseKey(hKeyConnection); } dwIndex++; } // write out new flags even if errors occured. work thing that happens is // we don't set up someones autosync automatically. RegSetValueEx(hkeyUser,TEXT("IdleEnabled"),NULL, REG_DWORD, (LPBYTE) &(dwIdleEnabled), sizeof(DWORD)); RegWriteTimeStamp(hkeyUser); } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegUpdateIdleKeyValue Summary: walks through the UserList Updating the Idle RegKey Returns: ------------------------------------------------------------------------F-F*/ void RegUpdateIdleKeyValue(HKEY hkeyIdle,DWORD dwDefault) { DWORD dwIndex = 0; WCHAR lpName[MAX_PATH]; DWORD cbName = MAX_PATH; DWORD dwIdleEnabled = 0; LONG lRet = -1; BOOL fSetDefault; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); // need to walk the idle user key and set the top level information // based on whther someone logon/logoff fSetDefault = FALSE; while ( ERROR_SUCCESS == (lRet = RegEnumKey(hkeyIdle,dwIndex, lpName,cbName)) ) { DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); DWORD dwUserIdleEnabled; HKEY hKeyDomainUser; lRet = RegOpenKeyEx( hkeyIdle, lpName, NULL, KEY_READ, &hKeyDomainUser ); if (ERROR_SUCCESS == lRet) { // if query fails don't consider this an error as far as // setDefault goes. if (ERROR_SUCCESS == (RegQueryValueEx(hKeyDomainUser,TEXT("IdleEnabled"),NULL, &dwType, (LPBYTE) &dwUserIdleEnabled, &dwDataSize) )) { dwIdleEnabled |= dwUserIdleEnabled; } RegCloseKey(hKeyDomainUser); } if (ERROR_SUCCESS != lRet) { break; } dwIndex++; } // if an error occured, then use the passed in defaults, // if set to 1, else don't set. if ( (ERROR_SUCCESS != lRet) && (ERROR_NO_MORE_ITEMS != lRet)) { if ( (-1 != dwDefault) && (0 != dwDefault)) { fSetDefault = TRUE; dwIdleEnabled = dwDefault; } } else { fSetDefault = TRUE; } // write out new flags even if errors occured. work thing that happens is // we don't set up someones autosync automatically. if (fSetDefault) { RegSetValueEx(hkeyIdle,TEXT("IdleEnabled"),NULL, REG_DWORD, (LPBYTE) &(dwIdleEnabled), sizeof(DWORD)); } RegWriteTimeStamp(hkeyIdle); CMutexRegistry.Leave(); } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegSetAutoSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings, int iNumConnections) Summary: Sets the logon, logoff and prompt me first user selections. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegSetAutoSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings, int iNumConnections, CRasUI *pRas, BOOL fCleanReg, BOOL fSetMachineState, BOOL fPerUser) { SCODE sc = S_OK; HKEY hAutoSync; HKEY hKeyUser; HKEY hkeyConnection; DWORD dwUserConfigured = 1; DWORD dwLogonDefault = -1; DWORD dwLogoffDefault = -1; int i; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); // make sure keys are converted to newest format RegUpdateTopLevelKeys(); Assert(-1 != TRUE); // we rely on TRUE boolean being something other than -1 hAutoSync = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_WRITE| KEY_READ,TRUE); if (NULL == hAutoSync) { goto EH_Err; } hKeyUser = RegOpenUserKey(hAutoSync,KEY_WRITE| KEY_READ,TRUE,fCleanReg); if (NULL == hKeyUser) { goto EH_Err2; } if (fPerUser) { smChkTo(EH_Err3,RegSetValueEx(hKeyUser,TEXT("UserConfigured"),NULL, REG_DWORD, (LPBYTE) &dwUserConfigured, sizeof(DWORD))); } else { DWORD dwType = REG_DWORD; DWORD dwDataSize = sizeof(DWORD); //If this value isn't added yet, if (ERROR_SUCCESS == RegQueryValueEx(hKeyUser,TEXT("UserConfigured"),NULL, &dwType, (LPBYTE) &dwUserConfigured, &dwDataSize)) { //if the user setup their configuration, we won't override on a //subsequent handler registration. if (dwUserConfigured) { RegCloseKey(hKeyUser); RegCloseKey(hAutoSync); CMutexRegistry.Leave(); return TRUE; } } } for (i=0; idwConnType = SYNCSCHEDINFO_FLAGS_CONNECTION_LAN; lpConnectionSettings->dwMakeConnection = FALSE; lpConnectionSettings->dwHidden = FALSE; lpConnectionSettings->dwReadOnly = FALSE; hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE); if (NULL == hKeyUser) { goto EH_Err2; } smChkTo(EH_Err3,RegOpenKeyEx (hKeyUser, pszSchedName,0,KEY_READ, &hkeySchedName)); smChkTo(EH_Err4,RegQueryValueEx(hkeySchedName,TEXT("ScheduleHidden"),NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwHidden), &dwDataSize)); dwDataSize = sizeof(DWORD); smChkTo(EH_Err4,RegQueryValueEx(hkeySchedName,TEXT("ScheduleReadOnly"),NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwReadOnly), &dwDataSize)); smChkTo(EH_Err4,RegOpenKeyEx (hkeySchedName, lpConnectionSettings->pszConnectionName, 0,KEY_READ, &hkeyConnection)); dwDataSize = sizeof(DWORD); smChkTo(EH_Err5,RegQueryValueEx(hkeyConnection,TEXT("MakeAutoConnection"),NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwMakeConnection), &dwDataSize)); dwDataSize = sizeof(DWORD); smChkTo(EH_Err5,RegQueryValueEx(hkeyConnection,TEXT("Connection Type"),NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwConnType), &dwDataSize)); RegCloseKey(hkeyConnection); RegCloseKey(hkeySchedName); RegCloseKey(hKeyUser); return TRUE; EH_Err5: RegCloseKey(hkeyConnection); EH_Err4: RegCloseKey(hkeySchedName); EH_Err3: RegCloseKey(hKeyUser); EH_Err2: return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegSetSchedSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings, TCHAR *pszSchedName) Summary: Sets the hidden and readonly schedule flags. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegSetSchedSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings, TCHAR *pszSchedName) { SCODE sc; HKEY hKeyUser, hkeySchedName, hkeyConnection; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ | KEY_WRITE,TRUE); if (NULL == hKeyUser) { goto EH_Err; } smChkTo(EH_Err3,RegCreateUserSubKey (hKeyUser, pszSchedName, KEY_WRITE | KEY_READ, &hkeySchedName)); smChkTo(EH_Err4,RegSetValueEx(hkeySchedName,TEXT("ScheduleHidden"),NULL, REG_DWORD, (LPBYTE) &(lpConnectionSettings->dwHidden), sizeof(DWORD))); smChkTo(EH_Err4,RegSetValueEx(hkeySchedName,TEXT("ScheduleReadOnly"),NULL, REG_DWORD, (LPBYTE) &(lpConnectionSettings->dwReadOnly), sizeof(DWORD))); smChkTo(EH_Err4,RegCreateUserSubKey ( hkeySchedName, lpConnectionSettings->pszConnectionName, KEY_WRITE | KEY_READ, &hkeyConnection)); smChkTo(EH_Err5,RegSetValueEx(hkeyConnection,TEXT("MakeAutoConnection"),NULL, REG_DWORD, (LPBYTE) &(lpConnectionSettings->dwMakeConnection), sizeof(DWORD))); smChkTo(EH_Err5,RegSetValueEx(hkeyConnection,TEXT("Connection Type"),NULL, REG_DWORD, (LPBYTE) &(lpConnectionSettings->dwConnType), sizeof(DWORD))); RegCloseKey(hkeyConnection); RegCloseKey(hkeySchedName); RegCloseKey(hKeyUser); CMutexRegistry.Leave(); return TRUE; EH_Err5: RegCloseKey(hkeyConnection); EH_Err4: RegCloseKey(hkeySchedName); EH_Err3: RegCloseKey(hKeyUser); EH_Err: CMutexRegistry.Leave(); return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegGetSchedConnectionName(TCHAR *pszSchedName, TCHAR *pszConnectionName, DWORD cbConnectionName) Summary: returns the Connection Name for the Scheduled Item. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegGetSchedConnectionName(TCHAR *pszSchedName,TCHAR *pszConnectionName, DWORD cbConnectionName) { SCODE sc; BOOL fResult = FALSE; HKEY hKeyUser,hkeySchedName; DWORD dwIndex = 0; DWORD cb = cbConnectionName; DWORD dwType = REG_DWORD; DWORD dwDataSize = sizeof(DWORD); //First Set the connectionName to a default. // for now we always assume a LAN card is present. // if add support for connection manager should // update this. LoadString(g_hmodThisDll, IDS_LAN_CONNECTION, pszConnectionName, cbConnectionName); hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE); if (NULL == hKeyUser) { goto EH_Err; } smChkTo(EH_Err3, RegOpenKeyEx (hKeyUser,pszSchedName, 0,KEY_READ, &hkeySchedName)); // next enumeration of keys is the names of the Schedules connection // currently just have one so only get the first. if ( ERROR_SUCCESS == (sc = RegEnumKeyEx(hkeySchedName,dwIndex, pszConnectionName,&cb,NULL,NULL,NULL,NULL)) ) { fResult = TRUE; } RegCloseKey(hkeySchedName); RegCloseKey(hKeyUser); return fResult; EH_Err3: RegCloseKey(hKeyUser); EH_Err: return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: BOOL RegSetSIDForSchedule( TCHAR *pszSchedName) Summary: sets the SID for this schedule Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegSetSIDForSchedule(TCHAR *pszSchedName) { SCODE sc; HKEY hkeySchedName; TCHAR pszSID[MAX_PATH + 1]; DWORD dwSize = MAX_PATH; DWORD dwType = REG_SZ; if (!GetUserTextualSid(pszSID, &dwSize)) { return FALSE; } CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); HKEY hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ | KEY_WRITE,TRUE); if (NULL == hKeyUser) { goto EH_Err2; } smChkTo(EH_Err3,RegCreateUserSubKey (hKeyUser, pszSchedName, KEY_WRITE | KEY_READ, &hkeySchedName)); smChkTo(EH_Err4,RegSetValueEx (hkeySchedName,TEXT("SID"),NULL, dwType, (LPBYTE) pszSID, (lstrlen(pszSID) + 1)*sizeof(TCHAR))); RegCloseKey(hkeySchedName); RegCloseKey(hKeyUser); CMutexRegistry.Leave(); return TRUE; EH_Err4: RegCloseKey(hkeySchedName); EH_Err3: RegCloseKey(hKeyUser); EH_Err2: CMutexRegistry.Leave(); return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: BOOL RegGetSIDForSchedule( TCHAR *ptszTextualSidSched, DWORD *dwSizeSid, TCHAR *pszSchedName) Summary: returns the SID for this schedule Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegGetSIDForSchedule(TCHAR *ptszTextualSidSched, DWORD *pdwSizeSid, TCHAR *pszSchedName) { SCODE sc; HKEY hkeySchedName; DWORD dwIndex = 0; DWORD dwType = REG_SZ; DWORD dwSizeSidSave = *pdwSizeSid, dwSizeSidSave2 = *pdwSizeSid; DWORD dwTouched = TRUE; ptszTextualSidSched[0] = TEXT('\0'); *pdwSizeSid = 0; HKEY hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE); if (NULL == hKeyUser) { goto EH_Err2; } smChkTo(EH_Err3, RegOpenKeyEx (hKeyUser,pszSchedName, 0,KEY_READ, &hkeySchedName)); if (ERROR_SUCCESS != (sc = RegQueryValueEx(hkeySchedName,TEXT("SID"),NULL, &dwType, (LPBYTE) ptszTextualSidSched, &dwSizeSidSave))) { //handle migration from schedules without SIDs // like from Beta to current builds RegSetSIDForSchedule(pszSchedName); RegQueryValueEx(hkeySchedName,TEXT("SID"),NULL, &dwType, (LPBYTE) ptszTextualSidSched, &dwSizeSidSave2); *pdwSizeSid = dwSizeSidSave2; } else { *pdwSizeSid = dwSizeSidSave; } RegCloseKey(hkeySchedName); RegCloseKey(hKeyUser); return TRUE; EH_Err3: RegCloseKey(hKeyUser); EH_Err2: return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL RemoveScheduledJobFile(TCHAR *pszTaskName) Summary: Remove the TaskScheduler .job file Note: Try to use ITask->Delete first Call only when TaskScheduler isn't present or if ITask->Delete failed Returns: Returns TRUE always ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RemoveScheduledJobFile(TCHAR *pszTaskName) { SCODE sc; TCHAR pszFullFileName[MAX_PATH+1]; TCHAR pszTaskFolderPath[MAX_PATH+1]; HKEY hkeyTaskSchedulerPath; DWORD dwType = REG_SZ; DWORD dwDataSize = MAX_PATH * sizeof(TCHAR); if (ERROR_SUCCESS == (sc = RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\SchedulingAgent"), NULL,KEY_READ,&hkeyTaskSchedulerPath))) { sc = RegQueryValueEx(hkeyTaskSchedulerPath,TEXT("TasksFolder"), NULL, &dwType, (LPBYTE) pszTaskFolderPath, &dwDataSize); RegCloseKey(hkeyTaskSchedulerPath); } //If this get doesn't exist then bail. if (ERROR_SUCCESS != sc) { return FALSE; } ExpandEnvironmentStrings(pszTaskFolderPath,pszFullFileName,MAX_PATH); wcscat(pszFullFileName, L"\\"); wcscat(pszFullFileName,pszTaskName); //if we fail this, ignore the error. We tried, there isn't much else we can do. //So we have a turd file. sc = DeleteFile(pszFullFileName); return TRUE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL RegRemoveScheduledTask(TCHAR *pszTaskName) Summary: Remove the Scheduled task info from the registry. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegRemoveScheduledTask(TCHAR *pszTaskName) { HKEY hKeyUser; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ | KEY_WRITE,FALSE); if (hKeyUser) { RegDeleteKeyNT(hKeyUser, pszTaskName); RegCloseKey(hKeyUser); } CMutexRegistry.Leave(); return TRUE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL RegUninstallSchedules() Summary: Uninstall the scheduled tasks. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegUninstallSchedules() { SCODE sc; ITaskScheduler *pITaskScheduler = NULL; HKEY hkeySchedSync; // Obtain a task scheduler class instance. sc = CoCreateInstance( CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (VOID **)&pITaskScheduler); if (NOERROR != sc) { pITaskScheduler = NULL; } //now go through and delete the schedules hkeySchedSync = RegGetSyncTypeKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE); if (hkeySchedSync) { int iUserCount = 0; while (sc == ERROR_SUCCESS ) { HKEY hkeyDomainUser; TCHAR szDomainUser[MAX_KEY_LENGTH]; SCODE sc2; DWORD dwDataSize; dwDataSize = MAX_KEY_LENGTH; sc = RegEnumKeyEx(hkeySchedSync,iUserCount,szDomainUser,&dwDataSize,NULL,NULL,NULL,NULL); iUserCount++; if(sc == ERROR_NO_MORE_ITEMS) { break; } sc2 = RegOpenKeyEx (hkeySchedSync,szDomainUser,0,KEY_READ, &hkeyDomainUser); if (ERROR_SUCCESS == sc2) { int iScheduleCount = 0; while (sc2 == ERROR_SUCCESS ) { TCHAR ptszScheduleGUIDName[MAX_KEY_LENGTH]; //Add 4 to ensure that we can hold the .job extension if necessary WCHAR pwszScheduleGUIDName[MAX_SCHEDULENAMESIZE + 4]; dwDataSize = MAX_KEY_LENGTH; sc2 = RegEnumKeyEx(hkeyDomainUser,iScheduleCount,ptszScheduleGUIDName,&dwDataSize,NULL,NULL,NULL,NULL); iScheduleCount++; if(sc2 == ERROR_NO_MORE_ITEMS) { continue; } else { ConvertString(pwszScheduleGUIDName,ptszScheduleGUIDName,MAX_SCHEDULENAMESIZE); if ((!pITaskScheduler) || FAILED(pITaskScheduler->Delete(pwszScheduleGUIDName))) { wcscat(pwszScheduleGUIDName, L".job"); RemoveScheduledJobFile(pwszScheduleGUIDName); } } } RegCloseKey(hkeyDomainUser); } } RegCloseKey(hkeySchedSync); } if (pITaskScheduler) { pITaskScheduler->Release(); } RegDeleteKeyNT(HKEY_LOCAL_MACHINE, SCHEDSYNC_REGKEY); return TRUE; } /**************************************************************************** Idle Registry Functions ***************************************************************************F-F*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegGetIdleSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings) Summary: Gets the Idle Specific settings. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegGetIdleSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings) { SCODE sc; HKEY hkeyConnection; DWORD dwType = REG_SZ ; DWORD dwDataSize = MAX_PATH; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); // set up defaults lpConnectionSettings->dwIdleEnabled = 0; // following are really per user not per connection lpConnectionSettings->ulIdleWaitMinutes = UL_DEFAULTIDLEWAITMINUTES; lpConnectionSettings->ulIdleRetryMinutes = UL_DEFAULTIDLERETRYMINUTES; lpConnectionSettings->ulDelayIdleShutDownTime = UL_DELAYIDLESHUTDOWNTIME; lpConnectionSettings->dwRepeatSynchronization = UL_DEFAULTREPEATSYNCHRONIZATION; lpConnectionSettings->dwRunOnBatteries = UL_DEFAULTFRUNONBATTERIES; HKEY hKeyUser = RegGetCurrentUserKey(SYNCTYPE_IDLE,KEY_READ,FALSE); if (NULL == hKeyUser) { goto EH_Err2; } dwType = REG_DWORD ; dwDataSize = sizeof(DWORD); // if got the Idle key open then fill in global settings RegQueryValueEx(hKeyUser,SZ_IDLEWAITAFTERIDLEMINUTESKEY,NULL, &dwType, (LPBYTE) &(lpConnectionSettings->ulIdleWaitMinutes), &dwDataSize); dwDataSize = sizeof(DWORD); RegQueryValueEx(hKeyUser,SZ_IDLEREPEATESYNCHRONIZATIONKEY,NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwRepeatSynchronization), &dwDataSize); dwDataSize = sizeof(DWORD); RegQueryValueEx(hKeyUser,SZ_IDLERETRYMINUTESKEY,NULL, &dwType, (LPBYTE) &(lpConnectionSettings->ulIdleRetryMinutes), &dwDataSize); dwDataSize = sizeof(DWORD); RegQueryValueEx(hKeyUser,SZ_IDLEDELAYSHUTDOWNTIMEKEY,NULL, &dwType, (LPBYTE) &(lpConnectionSettings->ulDelayIdleShutDownTime), &dwDataSize); dwDataSize = sizeof(DWORD); RegQueryValueEx(hKeyUser,SZ_IDLERUNONBATTERIESKEY,NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwRunOnBatteries), &dwDataSize); smChkTo(EH_Err3,RegOpenKeyEx(hKeyUser, lpConnectionSettings->pszConnectionName,0,KEY_READ, &hkeyConnection)); dwDataSize = sizeof(DWORD); RegQueryValueEx(hkeyConnection,TEXT("IdleEnabled"),NULL, &dwType, (LPBYTE) &(lpConnectionSettings->dwIdleEnabled), &dwDataSize); RegCloseKey(hkeyConnection); RegCloseKey(hKeyUser); CMutexRegistry.Leave(); return TRUE; EH_Err3: RegCloseKey(hKeyUser); EH_Err2: CMutexRegistry.Leave(); return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: RegSetIdleSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings, int iNumConnections, CRasUI *pRas, BOOL fCleanReg, BOOL fPerUser) Summary: Sets the Idle Information user selections. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegSetIdleSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings, int iNumConnections, CRasUI *pRas, BOOL fCleanReg, BOOL fPerUser) { HKEY hkeyIdleSync = NULL; HKEY hKeyUser;; HKEY hkeyConnection; HRESULT hr; ULONG ulWaitMinutes = UL_DEFAULTWAITMINUTES; DWORD dwIdleEnabled; BOOL fRunOnBatteries = UL_DEFAULTFRUNONBATTERIES; int i; DWORD dwType; DWORD dwDataSize; DWORD dwUserConfigured; DWORD dwTopLevelDefaultValue = -1; RegUpdateTopLevelKeys(); // make sure top-level keys are latest version CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); Assert(-1 != TRUE); // we rely on TRUE boolean being something other than -1 hkeyIdleSync = RegGetSyncTypeKey(SYNCTYPE_IDLE,KEY_WRITE| KEY_READ,TRUE); if (NULL == hkeyIdleSync) { goto EH_Err; } hKeyUser = RegOpenUserKey(hkeyIdleSync,KEY_WRITE| KEY_READ,TRUE,fCleanReg); if (NULL == hKeyUser) { goto EH_Err2; } if (fPerUser) { dwUserConfigured = 1; if (ERROR_SUCCESS != RegSetValueEx(hKeyUser,TEXT("UserConfigured"),NULL, REG_DWORD, (LPBYTE) &dwUserConfigured, sizeof(DWORD))) { goto EH_Err3; } } else { dwType = REG_DWORD; dwDataSize = sizeof(DWORD); //If this value isn't added yet, if (ERROR_SUCCESS == RegQueryValueEx(hKeyUser,TEXT("UserConfigured"),NULL, &dwType, (LPBYTE) &dwUserConfigured, &dwDataSize)) { //if the user setup their configuration, we won't override on a //subsequent handler registration. if (dwUserConfigured) { RegCloseKey(hkeyIdleSync); RegCloseKey(hKeyUser); CMutexRegistry.Leave(); return TRUE; } } } for (i=0; iQueryInterface(IID_ISyncScheduleMgr,(void **) &pScheduleMgr); pSyncMgrSynchronize->Release(); } if (NOERROR != hr) { return FALSE; } if (fRegister) { ISyncSchedule *pSyncSchedule = NULL; SYNCSCHEDULECOOKIE SyncScheduleCookie; BOOL fNewlyCreated = FALSE; HRESULT hr = E_FAIL; SyncScheduleCookie = GUID_IDLESCHEDULE; // if there isn't an existing schedule create one, else update // the existing. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == (hr = pScheduleMgr->OpenSchedule(&SyncScheduleCookie,0,&pSyncSchedule))) { SyncScheduleCookie = GUID_IDLESCHEDULE; // see if it is an exiting schedule. hr = pScheduleMgr->CreateSchedule(L"Idle",0,&SyncScheduleCookie,&pSyncSchedule); fNewlyCreated = TRUE; } // If created or found a schedule update the trigger settings. if (NOERROR == hr) { ITaskTrigger *pTrigger; pSyncSchedule->SetFlags(SYNCSCHEDINFO_FLAGS_READONLY | SYNCSCHEDINFO_FLAGS_HIDDEN); if (NOERROR == pSyncSchedule->GetTrigger(&pTrigger)) { TASK_TRIGGER trigger; ITask *pTask; trigger.cbTriggerSize = sizeof(TASK_TRIGGER); if (SUCCEEDED(pTrigger->GetTrigger(&trigger))) { DWORD dwFlags; // need to set Idle, ULONG ulWaitMinutes,BOOL fRunOnBatteries trigger.cbTriggerSize = sizeof(TASK_TRIGGER); trigger.TriggerType = TASK_EVENT_TRIGGER_ON_IDLE; trigger.rgFlags = 0; pTrigger->SetTrigger(&trigger); if (SUCCEEDED(pSyncSchedule->GetITask(&pTask))) { // set up if run on battery. if (SUCCEEDED(pTask->GetFlags(&dwFlags))) { dwFlags &= ~TASK_FLAG_DONT_START_IF_ON_BATTERIES; dwFlags |= !fRunOnBatteries ? TASK_FLAG_DONT_START_IF_ON_BATTERIES : 0; dwFlags |= TASK_FLAG_RUN_ONLY_IF_LOGGED_ON; // don't require password. pTask->SetFlags(dwFlags); } // if this schedule was just created, get the current user name and reset // account information password to NULL, If existing schedule don't change // since user may have added a password for schedule to run while not logged on. if (fNewlyCreated) { TCHAR szAccountName[MAX_DOMANDANDMACHINENAMESIZE]; WCHAR *pszAccountName = NULL; DWORD dwAccountName = sizeof(szAccountName); #ifndef _UNICODE WCHAR pwszDomainAndUser[MAX_DOMANDANDMACHINENAMESIZE]; #endif // _UNICODE // Review, this never returns an errorl *szAccountName = TCHAR('\0'); GetDefaultDomainAndUserName( (LPTSTR) &szAccountName,TEXT("\\"),dwAccountName); #ifndef _UNICODE // if we are compiled as ansi need to convert to wchar pszAccountName = pwszDomainAndUser; MultiByteToWideChar(CP_ACP, 0, szAccountName, -1, pwszDomainAndUser,sizeof(pwszDomainAndUser)); #else pszAccountName = szAccountName; #endif _UNICODE Assert(pszAccountName); if (pszAccountName) { pTask->SetAccountInformation(pszAccountName,NULL); } } // set up the IdleWaitTime. pTask->SetIdleWait((WORD) ulWaitMinutes,1); // turn off the option to kill task after xxx minutes. pTask->SetMaxRunTime(INFINITE); pTask->Release(); } pTrigger->Release(); } pSyncSchedule->Save(); } pSyncSchedule->Release(); } } else { SYNCSCHEDULECOOKIE SyncScheduleCookie = GUID_IDLESCHEDULE; // see if there is an existing schedule and if so remove it. pScheduleMgr->RemoveSchedule(&SyncScheduleCookie); } pScheduleMgr->Release(); // set the temporary sens flags according so it can start on an idle trigger. // not an error to not be able to get and set key since sens will // be running anyways eventually. HKEY hkeyAutoSync; DWORD dwFlags = 0; DWORD dwType = REG_DWORD; DWORD dwDataSize = sizeof(DWORD); CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); hkeyAutoSync = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_WRITE | KEY_READ,TRUE); if (NULL == hkeyAutoSync) { CMutexRegistry.Leave(); return FALSE; } if (ERROR_SUCCESS == RegQueryValueEx(hkeyAutoSync,TEXT("Flags"),NULL, &dwType, (LPBYTE) &(dwFlags),&dwDataSize)) { // Here we are setting Idle only so retail the other settings. dwFlags &= ~AUTOSYNC_IDLE; dwFlags |= (fRegister? AUTOSYNC_IDLE : 0); RegSetValueEx(hkeyAutoSync,TEXT("Flags"),NULL, REG_DWORD, (LPBYTE) &(dwFlags), sizeof(DWORD)); } RegCloseKey(hkeyAutoSync); CMutexRegistry.Leave(); return TRUE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL RegGetSyncSettings(DWORD dwSyncType,LPCONNECTIONSETTINGS lpConnectionSettings) Summary: Get ConnectionSettings appropriate to the synctype.. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegGetSyncSettings(DWORD dwSyncType,LPCONNECTIONSETTINGS lpConnectionSettings) { switch(dwSyncType) { case SYNCTYPE_AUTOSYNC: return RegGetAutoSyncSettings(lpConnectionSettings); break; case SYNCTYPE_IDLE: return RegGetIdleSyncSettings(lpConnectionSettings); break; default: AssertSz(0,"Unknown SyncType in RegGetSyncSettings"); break; } return FALSE; } /**************************************************************************** Manual Sync Registry Functions ***************************************************************************F-F*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL RegRemoveManualSyncSettings(TCHAR *pszTaskName) Summary: Remove the manual settings info from the registry. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegRemoveManualSyncSettings(TCHAR *pszConnectionName) { HKEY hkeyUser; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); hkeyUser = RegGetCurrentUserKey(SYNCTYPE_MANUAL,KEY_WRITE | KEY_READ,FALSE); if (hkeyUser) { RegDeleteKeyNT(hkeyUser, pszConnectionName); RegCloseKey(hkeyUser); } CMutexRegistry.Leave(); return TRUE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL RegWriteEvents(BOOL fWanLogon,BOOL fWanLogoff,BOOL fLanLogon,BOOL fLanLogoff) Summary: Write out the Wan/Lan Logon/Logoff preferences fo SENS knows whether to invoke us. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ // Run key under HKLM const WCHAR wszRunKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"); const WCHAR wszRunKeyCommandLine[] = TEXT("%SystemRoot%\\system32\\mobsync.exe /logon"); STDAPI_(BOOL) RegWriteEvents(BOOL Logon,BOOL Logoff) { HRESULT hr; HKEY hkeyAutoSync; DWORD dwFlags = 0; DWORD dwType = REG_DWORD; DWORD dwDataSize = sizeof(DWORD); CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); hkeyAutoSync = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_WRITE | KEY_READ,TRUE); if (NULL == hkeyAutoSync) { CMutexRegistry.Leave(); return FALSE; } RegQueryValueEx(hkeyAutoSync,TEXT("Flags"),NULL, &dwType, (LPBYTE) &(dwFlags), &dwDataSize); // Review, Shouldn't need to worry about schedule/idle once IsNetworkAlive // is setup properly. Leave for now first time anyone sets idle or schedule // stuck // Here we are setting autosync only, // so retain the registry settings for scheduled and idle. dwFlags &= ~(AUTOSYNC_WAN_LOGON | AUTOSYNC_LAN_LOGON | AUTOSYNC_LOGONWITHRUNKEY | AUTOSYNC_WAN_LOGOFF | AUTOSYNC_LAN_LOGOFF); // don't set logoff flags unless on platform logoff is supported // // !!! warning, if you change this also need to update settings // and registry which are the other places we block this. if ((VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId && g_OSVersionInfo.dwMajorVersion >= 5) ) { dwFlags |= (Logoff ? AUTOSYNC_WAN_LOGOFF : 0); dwFlags |= (Logoff ? AUTOSYNC_LAN_LOGOFF : 0); } // Since now use Run key instead of SENS always set both Logon Flags // that SENS looks for to do a CreateProcess on us to FALSE. // Then set the AUTOSYNC_LOGONWITHRUNKEY key to true so sens still gets loaded. dwFlags |= (Logon ? AUTOSYNC_LOGONWITHRUNKEY : 0); hr = RegSetValueEx(hkeyAutoSync,TEXT("Flags"),NULL, REG_DWORD, (LPBYTE) &(dwFlags), sizeof(DWORD)); RegCloseKey(hkeyAutoSync); // now add /delete the run key appropriately. HKEY hKeyRun; // call private RegOpen since don't want to set security on RunKey if (ERROR_SUCCESS == RegOpenKeyExXp(HKEY_LOCAL_MACHINE,wszRunKey, NULL,KEY_READ | KEY_WRITE,&hKeyRun,FALSE /*fSetSecurity*/)) { if (Logon) { RegSetValueEx(hKeyRun, SZ_SYNCMGRNAME, 0, REG_EXPAND_SZ, (BYTE *) wszRunKeyCommandLine,(lstrlen(wszRunKeyCommandLine) + 1)*sizeof(TCHAR)); } else { RegDeleteValue(hKeyRun, SZ_SYNCMGRNAME); } RegCloseKey(hKeyRun); } else { // if can't open run key try calling SENS if that fails give up. SyncMgrExecCmd_UpdateRunKey(Logon); } CMutexRegistry.Leave(); return TRUE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL RegFixRunKey(BOOL fScheduled) Summary: The original version of SyncMgr for WinMe/Win2000 wrote the "run" value as "mobsync.exe /logon". Since this is not a fully- qualified path to the mobsync.exe image, the system's search path is utilized to locate the image. This can create an opportunity for someone to build a 'trojan' mobsync.exe, place it in the search path ahead of the real mobsync.exe and have the 'trojan' code run whenever a synchronization is invoked. To fix this, the path must be stored in the registry using fully-qualified syntax. i.e. "%SystemRoot%\System32\mobsync.exe /logon" This function is called from DllRegisterServer to correct this registry entry during setup. Returns: Always returns TRUE. ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegFixRunKey(void) { HKEY hKeyRun; // call private RegOpen since don't want to set security on RunKey if (ERROR_SUCCESS == RegOpenKeyExXp(HKEY_LOCAL_MACHINE, wszRunKey, NULL, KEY_READ | KEY_WRITE, &hKeyRun, FALSE /*fSetSecurity*/)) { TCHAR szRunValue[MAX_PATH]; DWORD cbValue = sizeof(szRunValue); DWORD dwType; if (ERROR_SUCCESS == RegQueryValueEx(hKeyRun, SZ_SYNCMGRNAME, NULL, &dwType, (LPBYTE)szRunValue, &cbValue)) { if (REG_SZ == dwType && 0 == lstrcmp(szRunValue, TEXT("mobsync.exe /logon"))) { // // Upgrade only if it's our original value. // RegSetValueEx(hKeyRun, SZ_SYNCMGRNAME, 0, REG_EXPAND_SZ, (BYTE *)wszRunKeyCommandLine, (lstrlen(wszRunKeyCommandLine) + 1) * sizeof(TCHAR)); } } RegCloseKey(hKeyRun); } return TRUE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL RegRegisterForScheduledTasks(BOOL fScheduled) Summary: Register/unregister for scheduled tasks so SENS knows whether to invoke us. Returns: Returns TRUE if successful, FALSE otherwise ------------------------------------------------------------------------F-F*/ STDAPI_(BOOL) RegRegisterForScheduledTasks(BOOL fScheduled) { HKEY hkeyAutoSync; DWORD dwFlags = 0; DWORD dwType = REG_DWORD; DWORD dwDataSize = sizeof(DWORD); CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); hkeyAutoSync = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_WRITE | KEY_READ,TRUE); if (NULL == hkeyAutoSync) { CMutexRegistry.Leave(); return FALSE; } RegQueryValueEx(hkeyAutoSync,TEXT("Flags"),NULL, &dwType, (LPBYTE) &(dwFlags), &dwDataSize); // Here we are setting schedsync only, // so retain the registry settings for autosync and idle. dwFlags &= AUTOSYNC_WAN_LOGON | AUTOSYNC_WAN_LOGOFF | AUTOSYNC_LAN_LOGON | AUTOSYNC_LAN_LOGOFF | AUTOSYNC_IDLE; dwFlags |= (fScheduled? AUTOSYNC_SCHEDULED : 0); RegSetValueEx(hkeyAutoSync,TEXT("Flags"),NULL, REG_DWORD, (LPBYTE) &(dwFlags), sizeof(DWORD)); RegCloseKey(hkeyAutoSync); CMutexRegistry.Leave(); return TRUE; } //+--------------------------------------------------------------------------- // // Member: RegGetCombinedUserRegFlags, private // // Synopsis: Gets an or'ing together of user settings for setting up globals. // // Arguments: [dwSyncMgrRegisterFlags] - On Success gets set to flags // on failure they are set to zero // // Returns: Appropriate status code // // Modifies: // // History: 24-Aug-98 rogerg Created. // //---------------------------------------------------------------------------- BOOL RegGetCombinedUserRegFlags(DWORD *pdwSyncMgrRegisterFlags) { HKEY hkey; BOOL fResult = TRUE; DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); *pdwSyncMgrRegisterFlags = 0; // update the AutoSync Key hkey = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_READ,FALSE); if (hkey) { DWORD dwUserLogonLogoff; if (ERROR_SUCCESS == RegQueryValueEx(hkey,TEXT("Logon"),NULL, &dwType, (LPBYTE) &dwUserLogonLogoff, &dwDataSize) ) { *pdwSyncMgrRegisterFlags |= dwUserLogonLogoff ? SYNCMGRREGISTERFLAG_CONNECT : 0; } dwDataSize = sizeof(DWORD); if (ERROR_SUCCESS == RegQueryValueEx(hkey,TEXT("Logoff"),NULL, &dwType, (LPBYTE) &dwUserLogonLogoff, &dwDataSize) ) { *pdwSyncMgrRegisterFlags |= dwUserLogonLogoff ? SYNCMGRREGISTERFLAG_PENDINGDISCONNECT : 0; } RegCloseKey(hkey); } // update the Idle Key hkey = RegGetSyncTypeKey(SYNCTYPE_IDLE,KEY_READ,FALSE); if (hkey) { DWORD dwIdleEnabled; dwDataSize = sizeof(DWORD); if (ERROR_SUCCESS == RegQueryValueEx(hkey,TEXT("IdleEnabled"),NULL, &dwType, (LPBYTE) &dwIdleEnabled, &dwDataSize) ) { *pdwSyncMgrRegisterFlags |= dwIdleEnabled ? SYNCMGRREGISTERFLAG_IDLE : 0; } RegCloseKey(hkey); } return TRUE; // always return true but don't set flags on error. } //+--------------------------------------------------------------------------- // // Member: RegGetCombinedHandlerRegFlags, private // // Synopsis: Gets an or'ing together of handler registration Keys // // Arguments: [dwSyncMgrRegisterFlags] - On Success gets set to flags // on failure they are set to zero // [ft] - On Success filed with timestamp // // Returns: Appropriate status code // // Modifies: // // History: 24-Aug-98 rogerg Created. // //---------------------------------------------------------------------------- BOOL RegGetCombinedHandlerRegFlags(DWORD *pdwSyncMgrRegisterFlags,FILETIME *pft) { HKEY hkey; BOOL fResult = TRUE; DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); *pdwSyncMgrRegisterFlags = 0; hkey = RegGetHandlerTopLevelKey(KEY_READ); if (hkey) { DWORD dwRegistrationFlags; if (ERROR_SUCCESS == RegQueryValueEx(hkey,SZ_REGISTRATIONFLAGSKEY,NULL, &dwType, (LPBYTE) &dwRegistrationFlags, &dwDataSize) ) { *pdwSyncMgrRegisterFlags = dwRegistrationFlags; } RegGetTimeStamp(hkey,pft); RegCloseKey(hkey); } return TRUE; // always return true but don't set flags on error. } //+--------------------------------------------------------------------------- // // Member: RegGetChangedHandlerFlags, private // // Synopsis: Gets an or'ing together of handler registration Keys // that have changed since the given FILETIME // // Arguments: [pft] - Pointer to FileTime for Compare // [pdwChangedFlags] - On Success filed with flags that channged // // Returns: TRUE if could gather flags. // // Modifies: // // History: 24-Aug-98 rogerg Created. // //---------------------------------------------------------------------------- BOOL RegGetChangedHandlerFlags(FILETIME *pft,DWORD *pdwHandlerChandedFlags) { HKEY hkeyHandler; *pdwHandlerChandedFlags = 0; hkeyHandler = RegGetHandlerTopLevelKey(KEY_READ); if (hkeyHandler) { TCHAR lpName[MAX_PATH + 1]; DWORD cbName = MAX_PATH; DWORD dwRegistrationFlags = 0; FILETIME ftHandlerReg; DWORD dwIndex = 0; DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); DWORD dwHandlerRegFlags; LONG lRet; HKEY hKeyClsid; // enumerate the keys while ( ERROR_SUCCESS == RegEnumKey(hkeyHandler,dwIndex,lpName,cbName) ) { lRet = RegOpenKeyEx( hkeyHandler, lpName, NULL, KEY_READ, &hKeyClsid ); if (ERROR_SUCCESS == lRet) { RegGetTimeStamp(hKeyClsid,&ftHandlerReg); // handler reg is new time than our gvien time add it to the flags. if (CompareFileTime(pft,&ftHandlerReg) < 0) { if (ERROR_SUCCESS == RegQueryValueEx(hKeyClsid,SZ_REGISTRATIONFLAGSKEY,NULL, &dwType, (LPBYTE) &dwHandlerRegFlags, &dwDataSize) ) { dwRegistrationFlags |= dwHandlerRegFlags; } } RegCloseKey(hKeyClsid); } dwIndex++; } *pdwHandlerChandedFlags = dwRegistrationFlags; RegCloseKey(hkeyHandler); } return TRUE; } //+--------------------------------------------------------------------------- // // Member: RegRegisterForEvents, private // // Synopsis: Registers/UnRegisters for appropriate SENS and WinLogon Events. // and any other per machine registration we need to do // // Arguments: [fUninstall] - set to true by uninstall to force us to unregister // regardless of current machine state. // // Returns: Appropriate status code // // Modifies: // // History: 05-Nov-97 rogerg Created. // //---------------------------------------------------------------------------- // !!!Warning - Assumes toplevel key information is up to date. STDAPI RegRegisterForEvents(BOOL fUninstall) { HRESULT hr = NOERROR; BOOL fLogon = FALSE; BOOL fLogoff = FALSE; BOOL fIdle = FALSE; #ifdef _SENS IEventSystem *pEventSystem; #endif // _SENS CCriticalSection cCritSect(&g_DllCriticalSection,GetCurrentThreadId()); cCritSect.Enter(); if (!fUninstall) { FILETIME ftHandlerReg; DWORD dwSyncMgrUsersRegisterFlags; // or'ing of all Users settings DWORD dwSyncMgrHandlerRegisterFlags; // or'ing of all handler settings. DWORD dwCombinedFlags; // or together user and handler. // if not an uninstall determine the true machine state // if Logon set for handler or user set or if handler // wants an idle set. // If Logoff set we register for Logoff. RegGetCombinedUserRegFlags(&dwSyncMgrUsersRegisterFlags); RegGetCombinedHandlerRegFlags(&dwSyncMgrHandlerRegisterFlags,&ftHandlerReg); dwCombinedFlags = dwSyncMgrUsersRegisterFlags | dwSyncMgrHandlerRegisterFlags; if ( (dwCombinedFlags & SYNCMGRREGISTERFLAG_CONNECT) || (dwSyncMgrHandlerRegisterFlags & SYNCMGRREGISTERFLAG_IDLE) ) { fLogon = TRUE; } if ( (dwCombinedFlags & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) ) { fLogoff = TRUE; } } // update Registry entries for SENS to lookup RegWriteEvents(fLogon,fLogoff); #ifdef _SENS // we were able to load ole automation so reg/unreg with the event system. hr = CoCreateInstance(CLSID_CEventSystem,NULL,CLSCTX_SERVER,IID_IEventSystem, (LPVOID *) &pEventSystem); if (SUCCEEDED(hr)) { IEventSubscription *pIEventSubscription; WCHAR szGuid[GUID_SIZE+1]; BSTR bstrSubscriberID = NULL; BSTR bstrPROGID_EventSubscription = NULL; bstrPROGID_EventSubscription = SysAllocString(PROGID_EventSubscription); StringFromGUID2(GUID_SENSSUBSCRIBER_SYNCMGRP,szGuid, GUID_SIZE); bstrSubscriberID = SysAllocString(szGuid); if (bstrSubscriberID && bstrPROGID_EventSubscription) { // register for RasConnect hr = CoCreateInstance( CLSID_CEventSubscription, NULL, CLSCTX_SERVER, IID_IEventSubscription, (LPVOID *) &pIEventSubscription ); } else { hr = E_OUTOFMEMORY; } if (SUCCEEDED(hr)) { BSTR bstrPublisherID = NULL; BSTR bstrSubscriptionID = NULL; BSTR bstrSubscriptionName = NULL; BSTR bstrSubscriberCLSID = NULL; BSTR bstrEventID = NULL; BSTR bstrEventClassID = NULL; BSTR bstrIID = NULL; // if there are any events, register with ens for messages. if (fLogon) { StringFromGUID2(GUID_SENSLOGONSUBSCRIPTION_SYNCMGRP,szGuid, GUID_SIZE); bstrSubscriptionID = SysAllocString(szGuid); if (bstrSubscriptionID && SUCCEEDED(hr)) { hr = pIEventSubscription->put_SubscriptionID(bstrSubscriptionID); } StringFromGUID2(CLSID_SyncMgrp,szGuid, GUID_SIZE); bstrSubscriberCLSID = SysAllocString(szGuid); if (bstrSubscriberCLSID && SUCCEEDED(hr)) { hr = pIEventSubscription->put_SubscriberCLSID(bstrSubscriberCLSID); } StringFromGUID2(SENSGUID_PUBLISHER,szGuid, GUID_SIZE); bstrPublisherID = SysAllocString(szGuid); if (bstrPublisherID && SUCCEEDED(hr)) { hr = pIEventSubscription->put_PublisherID(bstrPublisherID); } bstrSubscriptionName = SysAllocString(SZ_SYNCMGRNAME); if (bstrSubscriptionName && SUCCEEDED(hr)) { hr = pIEventSubscription->put_SubscriptionName(bstrSubscriptionName); } bstrEventID = SysAllocString(L"ConnectionMade"); if (bstrEventID && SUCCEEDED(hr)) { hr = pIEventSubscription->put_MethodName(bstrEventID); } StringFromGUID2(SENSGUID_EVENTCLASS_NETWORK,szGuid,GUID_SIZE); bstrEventClassID = SysAllocString(szGuid); if (bstrEventClassID && SUCCEEDED(hr)) { hr = pIEventSubscription->put_EventClassID(bstrEventClassID); } // set this up for roaming if (SUCCEEDED(hr)) { // hr = pIEventSubscription->put_PerUser(TRUE); // don't register PerUser for Nw } StringFromGUID2(IID_ISensNetwork,szGuid,GUID_SIZE); bstrIID = SysAllocString(szGuid); if (bstrIID && SUCCEEDED(hr)) { hr = pIEventSubscription->put_InterfaceID(bstrIID); } if (SUCCEEDED(hr)) { hr = pEventSystem->Store(bstrPROGID_EventSubscription,pIEventSubscription); } if (bstrIID) { SysFreeString(bstrIID); } if (bstrPublisherID) SysFreeString(bstrPublisherID); if (bstrSubscriberCLSID) SysFreeString(bstrSubscriberCLSID); if (bstrEventClassID) SysFreeString(bstrEventClassID); if (bstrEventID) SysFreeString(bstrEventID); if (bstrSubscriptionID) SysFreeString(bstrSubscriptionID); if (bstrSubscriptionName) SysFreeString(bstrSubscriptionName); } else // don't need to be registered, remove. { if (NOERROR == hr) { int errorIndex; bstrSubscriptionID = SysAllocString(L"SubscriptionID={6295df30-35ee-11d1-8707-00C04FD93327}"); if (bstrSubscriptionID) { hr = pEventSystem->Remove(bstrPROGID_EventSubscription,bstrSubscriptionID /* QUERY */,&errorIndex); SysFreeString(bstrSubscriptionID); } } } pIEventSubscription->Release(); } if (bstrSubscriberID) { SysFreeString(bstrSubscriberID); } if (bstrPROGID_EventSubscription) { SysFreeString(bstrPROGID_EventSubscription); } pEventSystem->Release(); } #endif // _SENS cCritSect.Leave(); return hr; } // helper functions for handler registration STDAPI_(BOOL) RegGetTimeStamp(HKEY hKey, FILETIME *pft) { DWORD dwType; FILETIME ft; LONG lr; DWORD dwSize = sizeof(FILETIME); Assert(pft); lr = RegQueryValueEx( hKey, SZ_REGISTRATIONTIMESTAMPKEY, NULL, &dwType, (BYTE *)&ft, &dwSize ); if ( lr == ERROR_SUCCESS ) { Assert( dwSize == sizeof(FILETIME) && dwType == REG_BINARY ); *pft = ft; } else { // set the filetime to way back when to // any compares will just say older instead // of having to check success code (*pft).dwLowDateTime = 0; (*pft).dwHighDateTime = 0; } return TRUE; } STDAPI_(BOOL) RegWriteTimeStamp(HKEY hkey) { SYSTEMTIME sysTime; FILETIME ft; LONG lr = -1; GetSystemTime(&sysTime); // void can't check for errors if (SystemTimeToFileTime(&sysTime,&ft) ) { CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); // write out the UpdateTime lr = RegSetValueEx( hkey, SZ_REGISTRATIONTIMESTAMPKEY, NULL, REG_BINARY, (BYTE *)&ft, sizeof(ft) ); CMutexRegistry.Leave(); } return (ERROR_SUCCESS == lr) ? TRUE : FALSE; } //+--------------------------------------------------------------------------- // // Function: UpdateHandlerKeyInformation // // Synopsis: Updates the top-level handler key information // // Arguments: // // Returns: void // // Modifies: enumerates the handlers underneath the given key // updating the registrationFlags which is an || or // all registered handler flags and then updates the // timestamp on this key // // History: 05-Nov-97 rogerg Created. // //---------------------------------------------------------------------------- void UpdateHandlerKeyInformation(HKEY hKeyHandler) { DWORD dwSyncMgrTopLevelRegisterFlags = 0; DWORD dwIndex = 0; TCHAR lpName[MAX_PATH]; DWORD cbName = MAX_PATH; while ( ERROR_SUCCESS == RegEnumKey(hKeyHandler,dwIndex, lpName,cbName) ) { DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); DWORD dwHandlerRegFlags; LONG lRet; HKEY hKeyClsid; lRet = RegOpenKeyEx( hKeyHandler, lpName, NULL, KEY_READ, &hKeyClsid ); if (ERROR_SUCCESS == lRet) { if (ERROR_SUCCESS == RegQueryValueEx(hKeyClsid,SZ_REGISTRATIONFLAGSKEY,NULL, &dwType, (LPBYTE) &dwHandlerRegFlags, &dwDataSize) ) { dwSyncMgrTopLevelRegisterFlags |= dwHandlerRegFlags; } RegCloseKey(hKeyClsid); } dwIndex++; } // not much we can do if RegFlags are messed up other than assert and mask out Assert(dwSyncMgrTopLevelRegisterFlags <= SYNCMGRREGISTERFLAGS_MASK); dwSyncMgrTopLevelRegisterFlags &= SYNCMGRREGISTERFLAGS_MASK; // write out new flags even if errors occured. work thing that happens is // we don't set up someones autosync automatically. RegSetValueEx(hKeyHandler,SZ_REGISTRATIONFLAGSKEY,NULL, REG_DWORD, (LPBYTE) &(dwSyncMgrTopLevelRegisterFlags), sizeof(DWORD)); RegWriteTimeStamp(hKeyHandler); } //+--------------------------------------------------------------------------- // // Function: RegUpdateTopLevelKeys // // Synopsis: Looks at toplevel AutoSync,Idle, etc. keys and determines // if they need to be updated and if so goes for it. // // Arguments: // // Returns: Appropriate status code // // Modifies: set pfFirstRegistration out param to true if this is // the first handler that has registered so we can setup defaults. // // History: 24-Aug-98 rogerg Created. // //---------------------------------------------------------------------------- STDAPI_(void) RegUpdateTopLevelKeys() { HKEY hkey; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); // update the AutoSync Key hkey = RegGetSyncTypeKey(SYNCTYPE_AUTOSYNC,KEY_READ | KEY_WRITE,TRUE); if (hkey) { DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); DWORD dwUserLogonLogoff; // see if has a logon value and if it is either newly created or // old format. Call Update to setthings up if (ERROR_SUCCESS != RegQueryValueEx(hkey,TEXT("Logon"),NULL, &dwType, (LPBYTE) &dwUserLogonLogoff, &dwDataSize) ) { RegUpdateAutoSyncKeyValue(hkey,-1,-1); } RegCloseKey(hkey); } // update the Idle Key hkey = RegGetSyncTypeKey(SYNCTYPE_IDLE,KEY_READ | KEY_WRITE,TRUE); if (hkey) { DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); DWORD dwIdleEnabled; // see if has a Idle value and if it is either newly created or // old format. Call Update to setthings up if (ERROR_SUCCESS != RegQueryValueEx(hkey,TEXT("IdleEnabled"),NULL, &dwType, (LPBYTE) &dwIdleEnabled, &dwDataSize) ) { RegUpdateIdleKeyValue(hkey,-1); } RegCloseKey(hkey); } CMutexRegistry.Leave(); } //+--------------------------------------------------------------------------- // // Function: RegRegisterHandler // // Synopsis: Registers Handlers with SyncMgr. // // Arguments: // // Returns: Appropriate status code // // Modifies: set pfFirstRegistration out param to true if this is // the first handler that has registered so we can setup defaults. // // History: 05-Nov-97 rogerg Created. // //---------------------------------------------------------------------------- STDAPI_(BOOL) RegRegisterHandler(REFCLSID rclsidHandler, WCHAR const* pwszDescription, DWORD dwSyncMgrRegisterFlags, BOOL *pfFirstRegistration) { LONG lRet; RegUpdateTopLevelKeys(); // make sure other top-level keys are up to date. CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); *pfFirstRegistration = FALSE; HKEY hKeyHandler; hKeyHandler = RegGetHandlerTopLevelKey(KEY_READ | KEY_WRITE); if (NULL == hKeyHandler) { CMutexRegistry.Leave(); return FALSE; } XRegKey xRegKeyHandler( hKeyHandler ); // // Check if this is the first handler being registerd // TCHAR szGuid[GUID_SIZE+1]; DWORD cbGuid = GUID_SIZE+1; lRet = RegEnumKeyEx( hKeyHandler, 0, szGuid, &cbGuid, NULL, NULL, NULL, NULL ); if ( lRet != ERROR_SUCCESS ) *pfFirstRegistration = TRUE; // // Convert guid and description to TCHAR // TCHAR *pszDesc; BOOL fOk = FALSE; StringFromGUID2( rclsidHandler, szGuid, GUID_SIZE+1 ); pszDesc = (TCHAR *)pwszDescription; // write out the registration flags. If fail go ahead // and succed registration anyways. if (hKeyHandler) { HKEY hKeyClsid; hKeyClsid = RegGetHandlerKey(hKeyHandler,szGuid,KEY_WRITE | KEY_READ,TRUE); if (hKeyClsid) { fOk = TRUE; // if make handle key say registered okay if (pszDesc) { RegSetValueEx(hKeyClsid,NULL,NULL, REG_SZ, (LPBYTE) pszDesc, (lstrlen(pszDesc) +1)*sizeof(TCHAR)); } RegSetValueEx(hKeyClsid,SZ_REGISTRATIONFLAGSKEY,NULL, REG_DWORD, (LPBYTE) &(dwSyncMgrRegisterFlags), sizeof(DWORD)); // update the TimeStamp on the handler clsid RegWriteTimeStamp(hKeyClsid); RegCloseKey( hKeyClsid ); // update the toplevel key UpdateHandlerKeyInformation(hKeyHandler); } } // update the user information. RegSetUserDefaults(); RegRegisterForEvents(FALSE /* fUninstall */); CMutexRegistry.Leave(); return fOk; } //+--------------------------------------------------------------------------- // // Function: RegRegRemoveHandler // // Synopsis: UnRegisters Handlers with SyncMgr. // // Arguments: // // Returns: Appropriate status code // // Modifies: set pfAllHandlerUnRegistered out param to true if this is // the last handler that needs to be unregistered before // turning off our defaults.. // // History: 05-Nov-97 rogerg Created. // //---------------------------------------------------------------------------- STDAPI_(BOOL) RegRegRemoveHandler(REFCLSID rclsidHandler) { HKEY hKeyHandler; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); hKeyHandler = RegGetHandlerTopLevelKey(KEY_WRITE | KEY_READ); if (NULL == hKeyHandler) { // // Non-existent key, so nothing to remove // CMutexRegistry.Leave(); return TRUE; } XRegKey xKeyHandler( hKeyHandler ); TCHAR szGuid[GUID_SIZE+1]; #ifdef _UNICODE StringFromGUID2( rclsidHandler, szGuid, GUID_SIZE+1 ); #else WCHAR wszGuid[GUID_SIZE+1]; StringFromGUID2( rclsidHandler, wszGuid, GUID_SIZE+1 ); BOOL fOk = ConvertString( szGuid, wszGuid, GUID_SIZE+1 ); Assert( fOk ); #endif HKEY hKeyClsid; hKeyClsid = RegGetHandlerKey(hKeyHandler,szGuid,KEY_WRITE | KEY_READ,FALSE); if (hKeyClsid) { RegCloseKey( hKeyClsid ); RegDeleteKey( hKeyHandler, szGuid ); // update the toplevel key UpdateHandlerKeyInformation(hKeyHandler); } else { // // Non-existent key, so nothing to remove // } RegRegisterForEvents(FALSE /* fUninstall */); // UPDATE EVENT REGISTRATION. CMutexRegistry.Leave(); return TRUE; } //+--------------------------------------------------------------------------- // // Function: RegGetHandlerRegistrationInfo // // Synopsis: Gets Information of the specified handler. // // Arguments: // // Returns: Appropriate status code // // Modifies: pdwSyncMgrRegisterFlags // // History: 20-Aug-98 rogerg Created. // //---------------------------------------------------------------------------- STDAPI_(BOOL) RegGetHandlerRegistrationInfo(REFCLSID rclsidHandler,LPDWORD pdwSyncMgrRegisterFlags) { HKEY hKeyHandler; *pdwSyncMgrRegisterFlags = 0; hKeyHandler = RegGetHandlerTopLevelKey(KEY_READ); if (NULL == hKeyHandler) { // // Non-existent key // return FALSE; } XRegKey xKeyHandler( hKeyHandler ); TCHAR szGuid[GUID_SIZE+1]; #ifdef _UNICODE StringFromGUID2( rclsidHandler, szGuid, GUID_SIZE+1 ); #else WCHAR wszGuid[GUID_SIZE+1]; StringFromGUID2( rclsidHandler, wszGuid, GUID_SIZE+1 ); BOOL fOk = ConvertString( szGuid, wszGuid, GUID_SIZE+1 ); Assert( fOk ); #endif HKEY hKeyClsid; BOOL fResult = FALSE; hKeyClsid = RegGetHandlerKey(hKeyHandler,szGuid,KEY_READ,FALSE); if (hKeyClsid) { DWORD dwType = REG_DWORD ; DWORD dwDataSize = sizeof(DWORD); LONG lRet; lRet = RegQueryValueEx(hKeyClsid,SZ_REGISTRATIONFLAGSKEY,NULL, &dwType, (LPBYTE) pdwSyncMgrRegisterFlags, &dwDataSize); RegCloseKey( hKeyClsid ); fResult = (ERROR_SUCCESS == lRet) ? TRUE : FALSE; } else { // // Non-existent key, so nothing to remove // } return fResult; } //+--------------------------------------------------------------------------- // // Function: RegSetUserDefaults // // Synopsis: Registers default values for auto and idle sync // // Setup based on Handler and UserPreferences // // History: 20-May-98 SitaramR Created // //---------------------------------------------------------------------------- STDAPI_(void) RegSetUserDefaults() { HKEY hKeyUser = NULL; BOOL fLogon = FALSE; BOOL fLogoff = FALSE; FILETIME ftHandlerReg; DWORD dwHandlerRegistrationFlags; CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME); CMutexRegistry.Enter(); // get the combined handler registration toplevel flags and timeStamp // to see if should bother enumerating the rest. if (!RegGetCombinedHandlerRegFlags(&dwHandlerRegistrationFlags,&ftHandlerReg)) { CMutexRegistry.Leave(); return; } if (0 != (dwHandlerRegistrationFlags & (SYNCMGRREGISTERFLAG_CONNECT | SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) ) ) { // See if AutoSync key needs to be updated hKeyUser = RegGetCurrentUserKey(SYNCTYPE_AUTOSYNC,KEY_WRITE | KEY_READ,TRUE); if (hKeyUser) { FILETIME ftUserAutoSync; // if got the User get the timestamp and see if it is older than the handlers // If this is a new user filetime will be 0 RegGetTimeStamp(hKeyUser,&ftUserAutoSync); if (CompareFileTime(&ftUserAutoSync,&ftHandlerReg) < 0) { DWORD dwHandlerChangedFlags; // need to walk through handlers and update what we need to set based // on each handlers timestamp since we don't want a handler that registered // for idle to cause us to turn AutoSync back on and vis-a-versa if (RegGetChangedHandlerFlags(&ftUserAutoSync,&dwHandlerChangedFlags)) { BOOL fLogon = (dwHandlerChangedFlags & SYNCMGRREGISTERFLAG_CONNECT) ? TRUE : FALSE; BOOL fLogoff = (dwHandlerChangedFlags & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) ? TRUE : FALSE; RegSetAutoSyncDefaults(fLogon,fLogoff); } } RegCloseKey(hKeyUser); hKeyUser = NULL; } } if (0 != (dwHandlerRegistrationFlags & SYNCMGRREGISTERFLAG_IDLE ) ) { // now check for Idle same logic as above could probably combine // into a function // See if AutoSync key needs to be updated hKeyUser = RegGetCurrentUserKey(SYNCTYPE_IDLE, KEY_WRITE | KEY_READ,TRUE); if (hKeyUser) { FILETIME ftUserIdleSync; // if got the User get the timestamp and see if it is older than the handlers // If this is a new user filetime will be 0 RegGetTimeStamp(hKeyUser,&ftUserIdleSync); if (CompareFileTime(&ftUserIdleSync,&ftHandlerReg) < 0) { DWORD dwHandlerChangedFlags; // need to walk through handlers and update what we need to set based // on each handlers timestamp since we don't want a handler that registered // for AutoSync to cause us to turn Idle back on and vis-a-versa if (RegGetChangedHandlerFlags(&ftUserIdleSync,&dwHandlerChangedFlags)) { if (dwHandlerChangedFlags & SYNCMGRREGISTERFLAG_IDLE) { RegSetIdleSyncDefaults(TRUE); } } } RegCloseKey(hKeyUser); hKeyUser = NULL; } } CMutexRegistry.Leave(); } //+--------------------------------------------------------------------------- // // Function: RegSetAutoSyncDefaults // // Synopsis: Registers default values for auto sync // // History: 20-May-98 SitaramR Created // //---------------------------------------------------------------------------- STDAPI_(void) RegSetAutoSyncDefaults(BOOL fLogon,BOOL fLogoff) { CONNECTIONSETTINGS *pConnection = (LPCONNECTIONSETTINGS) ALLOC(sizeof(CONNECTIONSETTINGS)); if ( pConnection == 0 ) return; XPtr xConnection( pConnection ); INT iRet = LoadString(g_hmodThisDll, IDS_LAN_CONNECTION, pConnection->pszConnectionName, ARRAYLEN(pConnection->pszConnectionName) ); Assert( iRet != 0 ); // -1 values are ignored by RegSetAutoSyncSettings. // if not turning on leave the User Preferences alone, pConnection->dwConnType = 0; pConnection->dwLogon = fLogon ? TRUE : -1; pConnection->dwLogoff = fLogoff ? TRUE : -1; pConnection->dwPromptMeFirst = -1; pConnection->dwMakeConnection = -1; pConnection->dwIdleEnabled = -1; // since this bases settings on what is already set no need to // do a cleanreg or update the machine state RegSetAutoSyncSettings(pConnection, 1, 0, FALSE /* fCleanReg */, FALSE /* fSetMachineState */, FALSE /* fPerUser */); } //+--------------------------------------------------------------------------- // // Function: RegSetUserAutoSyncDefaults // // Synopsis: Registers user default values for auto sync // // History: 39-March-99 rogerg Created // //---------------------------------------------------------------------------- STDAPI RegSetUserAutoSyncDefaults(DWORD dwSyncMgrRegisterMask, DWORD dwSyncMgrRegisterFlags) { // if not changing either logon or logoff just return if (!(dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_CONNECT) && !(dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) ) { return NOERROR; } CONNECTIONSETTINGS *pConnection = (LPCONNECTIONSETTINGS) ALLOC(sizeof(CONNECTIONSETTINGS)); if ( pConnection == 0 ) return E_OUTOFMEMORY; XPtr xConnection( pConnection ); INT iRet = LoadString(g_hmodThisDll, IDS_LAN_CONNECTION, pConnection->pszConnectionName, ARRAYLEN(pConnection->pszConnectionName) ); Assert( iRet != 0 ); // -1 values are ignored by RegSetAutoSyncSettings. // if not turning on leave the User Preferences alone, pConnection->dwConnType = 0; pConnection->dwLogon = -1; pConnection->dwLogoff = -1; pConnection->dwPromptMeFirst = -1; pConnection->dwMakeConnection = -1; pConnection->dwIdleEnabled = -1; if (dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_CONNECT) { pConnection->dwLogon = (dwSyncMgrRegisterFlags & SYNCMGRREGISTERFLAG_CONNECT) ? TRUE : FALSE; } if (dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) { pConnection->dwLogoff = (dwSyncMgrRegisterFlags & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) ? TRUE : FALSE; } // since this bases settings on what is already set no need to // do a cleanreg or update the machine state RegSetAutoSyncSettings(pConnection, 1, 0, FALSE /* fCleanReg */, TRUE /* fSetMachineState */, TRUE /* fPerUser */); return NOERROR; } //+--------------------------------------------------------------------------- // // Function: RegSetIdleSyncDefaults // // Synopsis: Registers default values for idle sync // // History: 20-May-98 SitaramR Created // //---------------------------------------------------------------------------- STDAPI_(void) RegSetIdleSyncDefaults(BOOL fIdle) { Assert(fIdle); // for now this should only be called when true; if (!fIdle) { return; } CONNECTIONSETTINGS *pConnection = (LPCONNECTIONSETTINGS) ALLOC(sizeof(CONNECTIONSETTINGS)); if ( pConnection == 0 ) return; XPtr xConnection( pConnection ); INT iRet = LoadString(g_hmodThisDll, IDS_LAN_CONNECTION, pConnection->pszConnectionName, ARRAYLEN(pConnection->pszConnectionName) ); Assert( iRet != 0 ); pConnection->dwConnType = 0; pConnection->dwLogon = -1; pConnection->dwLogoff = -1; pConnection->dwPromptMeFirst = -1; pConnection->dwMakeConnection = -1; pConnection->dwIdleEnabled = TRUE; // set all userLevel items to -1 so user gets the defaults if new // but keep their settings if have already tweaked them. pConnection->ulIdleRetryMinutes = -1; pConnection->ulDelayIdleShutDownTime = -1; pConnection->dwRepeatSynchronization = -1; pConnection->ulIdleWaitMinutes = -1; pConnection->dwRunOnBatteries = -1; RegSetIdleSyncSettings(pConnection, 1, 0, FALSE /* fCleanReg */, FALSE /* fPerUser */); } //+--------------------------------------------------------------------------- // // Function: RegSetIdleSyncDefaults // // Synopsis: Registers default values for idle sync // // History: 30-March-99 ROGERG Created // //---------------------------------------------------------------------------- STDAPI RegSetUserIdleSyncDefaults(DWORD dwSyncMgrRegisterMask, DWORD dwSyncMgrRegisterFlags) { // RegSetIdleSyncSettings doesn't handle idle enabled of -1 so only // call if Idle actually is set in the flags, if not just return if (!(dwSyncMgrRegisterMask & SYNCMGRREGISTERFLAG_IDLE)) { return NOERROR; } CONNECTIONSETTINGS *pConnection = (LPCONNECTIONSETTINGS) ALLOC(sizeof(CONNECTIONSETTINGS)); if ( pConnection == 0 ) return E_OUTOFMEMORY; XPtr xConnection( pConnection ); INT iRet = LoadString(g_hmodThisDll, IDS_LAN_CONNECTION, pConnection->pszConnectionName, ARRAYLEN(pConnection->pszConnectionName) ); Assert( iRet != 0 ); pConnection->dwConnType = 0; pConnection->dwLogon = -1; pConnection->dwLogoff = -1; pConnection->dwPromptMeFirst = -1; pConnection->dwMakeConnection = -1; pConnection->dwIdleEnabled = (SYNCMGRREGISTERFLAG_IDLE & dwSyncMgrRegisterFlags) ? TRUE : FALSE; // set all userLevel items to -1 so user gets the defaults if new // but keep their settings if have already tweaked them. pConnection->ulIdleRetryMinutes = -1; pConnection->ulDelayIdleShutDownTime = -1; pConnection->dwRepeatSynchronization = -1; pConnection->ulIdleWaitMinutes = -1; pConnection->dwRunOnBatteries = -1; RegSetIdleSyncSettings(pConnection, 1, 0, FALSE /* fCleanReg */, TRUE /* fPerUser */); return NOERROR; } //+--------------------------------------------------------------------------- // // Function: RegGetUserRegisterFlags // // Synopsis: returns current registration flags for the User. // // History: 30-March-99 ROGERG Created // //---------------------------------------------------------------------------- STDAPI RegGetUserRegisterFlags(LPDWORD pdwSyncMgrRegisterFlags) { CONNECTIONSETTINGS connectSettings; *pdwSyncMgrRegisterFlags = 0; INT iRet = LoadString(g_hmodThisDll, IDS_LAN_CONNECTION, connectSettings.pszConnectionName, ARRAYLEN(connectSettings.pszConnectionName) ); if (0 == iRet) { Assert( iRet != 0 ); return E_UNEXPECTED; } RegGetSyncSettings(SYNCTYPE_AUTOSYNC,&connectSettings); if (connectSettings.dwLogon) { *pdwSyncMgrRegisterFlags |= (SYNCMGRREGISTERFLAG_CONNECT); } if (connectSettings.dwLogoff) { *pdwSyncMgrRegisterFlags |= (SYNCMGRREGISTERFLAG_PENDINGDISCONNECT); } RegGetSyncSettings(SYNCTYPE_IDLE,&connectSettings); if (connectSettings.dwIdleEnabled) { *pdwSyncMgrRegisterFlags |= (SYNCMGRREGISTERFLAG_IDLE); } return NOERROR; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function: BOOL RegSchedHandlerItemsChecked(TCHAR *pszHandlerName, TCHAR *pszConnectionName, TCHAR *pszScheduleName) Summary: Determine if any items are checked on this handler for this schedule Returns: Returns TRUE if one or more are checked, FALSE otherwise ------------------------------------------------------------------------F-F*/ BOOL RegSchedHandlerItemsChecked(TCHAR *pszHandlerName, TCHAR *pszConnectionName, TCHAR *pszScheduleName) { SCODE sc; HKEY hKeyUser, hkeySchedName, hkeyConnection, hkeyHandler, hkeyItem; DWORD cbName = MAX_PATH, dwIndex = 0, dwCheckState = 0, dwType = REG_DWORD, dwDataSize = sizeof(DWORD); BOOL fItemsChecked = FALSE; TCHAR lpName[MAX_PATH + 1]; hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE); if (NULL == hKeyUser) { return FALSE; } smChkTo(EH_Err3,RegOpenKeyEx (hKeyUser, pszScheduleName,0,KEY_READ, &hkeySchedName)); smChkTo(EH_Err4,RegOpenKeyEx (hkeySchedName, pszConnectionName, 0,KEY_READ, &hkeyConnection)); smChkTo(EH_Err5,RegOpenKeyEx (hkeyConnection, pszHandlerName, 0,KEY_READ, &hkeyHandler)); // need to enum handler items. while ( ERROR_SUCCESS == RegEnumKey(hkeyHandler,dwIndex, lpName,cbName) ) { LONG lRet; lRet = RegOpenKeyEx( hkeyHandler, lpName, NULL, KEY_READ, &hkeyItem); if (ERROR_SUCCESS == lRet) { RegQueryValueEx(hkeyItem,TEXT("CheckState"), NULL, &dwType, (LPBYTE) &dwCheckState, &dwDataSize); RegCloseKey(hkeyItem); } else { goto EH_Err5; } if (dwCheckState) { fItemsChecked = TRUE; break; } dwIndex++; } RegCloseKey(hkeyHandler); RegCloseKey(hkeyConnection); RegCloseKey(hkeySchedName); RegCloseKey(hKeyUser); return fItemsChecked; EH_Err5: RegCloseKey(hkeyConnection); EH_Err4: RegCloseKey(hkeySchedName); EH_Err3: RegCloseKey(hKeyUser); return fItemsChecked; }