windows-nt/Source/XPSP1/NT/com/mobile/syncmgr/dll/reg.cpp
2020-09-26 16:20:57 +08:00

4862 lines
141 KiB
C++

//+-------------------------------------------------------------------------
//
// 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 <eventsys.h> // include event system
#include <sens.h>
#include <sensevts.h>
#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; i<iNumConnections; i++)
{
smChkTo(EH_Err3,RegCreateUserSubKey (hKeyUser,
lpConnectionSettings[i].pszConnectionName,
KEY_WRITE | KEY_READ,
&hkeyConnection));
if (-1 != lpConnectionSettings[i].dwLogon)
{
if (0 != lpConnectionSettings[i].dwLogon)
{
dwLogonDefault = lpConnectionSettings[i].dwLogon;
}
smChkTo(EH_Err4,RegSetValueEx(hkeyConnection,TEXT("Logon"),NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[i].dwLogon),
sizeof(DWORD)));
}
if (-1 != lpConnectionSettings[i].dwLogoff)
{
if (0 != lpConnectionSettings[i].dwLogoff)
{
dwLogoffDefault = lpConnectionSettings[i].dwLogoff;
}
smChkTo(EH_Err4,RegSetValueEx(hkeyConnection,TEXT("Logoff"),NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[i].dwLogoff),
sizeof(DWORD)));
}
if (-1 != lpConnectionSettings[i].dwPromptMeFirst)
{
smChkTo(EH_Err4,RegSetValueEx(hkeyConnection,TEXT("PromptMeFirst"),NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[i].dwPromptMeFirst),
sizeof(DWORD)));
}
RegCloseKey(hkeyConnection);
}
// update the toplevel User information
RegUpdateUserAutosyncKey(hKeyUser,TRUE /* fForce */);
// update the top-level key
RegUpdateAutoSyncKeyValue(hAutoSync,dwLogonDefault,dwLogoffDefault);
RegCloseKey(hKeyUser);
RegCloseKey(hAutoSync);
// update our global sens state based on Autosync and Registration
if (fSetMachineState)
{
RegRegisterForEvents(FALSE /* fUninstall */);
}
CMutexRegistry.Leave();
return TRUE;
EH_Err4:
RegCloseKey(hkeyConnection);
EH_Err3:
RegCloseKey(hKeyUser);
EH_Err2:
RegCloseKey(hAutoSync);
EH_Err:
CMutexRegistry.Leave();
return FALSE;
}
/****************************************************************************
Scheduled Sync Registry Functions
***************************************************************************F-F*/
//--------------------------------------------------------------------------------
//
// FUNCTION: RegGetSchedFriendlyName(LPCTSTR ptszScheduleGUIDName,
// LPTSTR ptstrFriendlyName)
//
// PURPOSE: Get the friendly name of this Schedule.
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDAPI_(BOOL) RegGetSchedFriendlyName(LPCTSTR ptszScheduleGUIDName,
LPTSTR ptstrFriendlyName)
{
BOOL fResult = FALSE;
HKEY hkeySchedName;
DWORD dwType = REG_SZ;
DWORD dwDataSize = (MAX_PATH + 1) * sizeof(TCHAR);
HKEY hKeyUser;
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE);
if (NULL == hKeyUser)
{
return FALSE;
}
if (NOERROR == RegOpenKeyEx (hKeyUser, ptszScheduleGUIDName, 0,KEY_READ,
&hkeySchedName))
{
if (ERROR_SUCCESS == RegQueryValueEx(hkeySchedName,TEXT("FriendlyName"),NULL, &dwType,
(LPBYTE) ptstrFriendlyName, &dwDataSize))
{
fResult = TRUE;
}
RegCloseKey(hkeySchedName);
}
RegCloseKey(hKeyUser);
return fResult;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: RegSetSchedFriendlyName(LPCTSTR ptszScheduleGUIDName,
// LPCTSTR ptstrFriendlyName)
//
// PURPOSE: Set the friendly name of this Schedule.
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDAPI_(BOOL) RegSetSchedFriendlyName(LPCTSTR ptszScheduleGUIDName,
LPCTSTR ptstrFriendlyName)
{
SCODE sc;
HKEY hkeySchedName;
DWORD dwType = REG_SZ;
HKEY hKeyUser;
CMutex CMutexRegistry(NULL, FALSE,SZ_REGSITRYMUTEXNAME);
CMutexRegistry.Enter();
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_WRITE | KEY_READ,TRUE);
if (NULL == hKeyUser)
{
goto EH_Err;
}
smChkTo(EH_Err3,RegCreateUserSubKey (hKeyUser, ptszScheduleGUIDName,
KEY_WRITE | KEY_READ,
&hkeySchedName));
smChkTo(EH_Err4,RegSetValueEx (hkeySchedName,TEXT("FriendlyName"),NULL,
dwType,
(LPBYTE) ptstrFriendlyName,
(lstrlen(ptstrFriendlyName) + 1)*sizeof(TCHAR)));
RegCloseKey(hkeySchedName);
RegCloseKey(hKeyUser);
CMutexRegistry.Leave();
return TRUE;
EH_Err4:
RegCloseKey(hkeySchedName);
EH_Err3:
RegCloseKey(hKeyUser);
EH_Err:
CMutexRegistry.Leave();
return FALSE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: RegGetSchedSyncSettings( LPCONNECTIONSETTINGS lpConnectionSettings,
TCHAR *pszSchedName)
Summary: Gets the MakeAutoConnection user selections.
If no selections on this connection, the default is FALSE
Returns: Returns TRUE if successful, FALSE otherwise
------------------------------------------------------------------------F-F*/
STDAPI_(BOOL) RegGetSchedSyncSettings(LPCONNECTIONSETTINGS lpConnectionSettings,
TCHAR *pszSchedName)
{
SCODE sc;
HKEY hkeySchedName,
hkeyConnection;
DWORD dwType = REG_DWORD;
DWORD dwDataSize = sizeof(DWORD);
HKEY hKeyUser;
// Set these first to default values, in case there are no current
// user preferences in the registry
lpConnectionSettings->dwConnType = 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; i<iNumConnections; i++)
{
if (ERROR_SUCCESS != RegCreateUserSubKey (hKeyUser,
lpConnectionSettings[i].pszConnectionName,
KEY_WRITE | KEY_READ,
&hkeyConnection))
{
goto EH_Err3;
}
hr = RegSetValueEx(hkeyConnection,TEXT("IdleEnabled"),NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[i].dwIdleEnabled),
sizeof(DWORD));
if (lpConnectionSettings[i].dwIdleEnabled)
{
dwTopLevelDefaultValue = lpConnectionSettings[i].dwIdleEnabled;
}
RegCloseKey(hkeyConnection);
}
// write out the global idle information for Retry minutes and DelayIdleShutDown.
// then call function to reg/unregister with TS.
Assert(hkeyIdleSync); // should have already returned if this failed.
if (iNumConnections) // make sure at least one connection
{
// ONLY UPDATE SETTINGS IF NOT -1;
if (-1 != lpConnectionSettings[0].ulIdleRetryMinutes)
{
hr = RegSetValueEx(hKeyUser,SZ_IDLERETRYMINUTESKEY,NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[0].ulIdleRetryMinutes),
sizeof(DWORD));
}
if (-1 != lpConnectionSettings[0].ulDelayIdleShutDownTime)
{
hr = RegSetValueEx(hKeyUser,SZ_IDLEDELAYSHUTDOWNTIMEKEY,NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[0].ulDelayIdleShutDownTime),
sizeof(DWORD));
}
if (-1 != lpConnectionSettings[0].dwRepeatSynchronization)
{
hr = RegSetValueEx(hKeyUser,SZ_IDLEREPEATESYNCHRONIZATIONKEY,NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[0].dwRepeatSynchronization),
sizeof(DWORD));
}
if (-1 != lpConnectionSettings[0].ulIdleWaitMinutes)
{
hr = RegSetValueEx(hKeyUser,SZ_IDLEWAITAFTERIDLEMINUTESKEY,NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[0].ulIdleWaitMinutes),
sizeof(DWORD));
}
if (-1 != lpConnectionSettings[0].dwRunOnBatteries)
{
hr = RegSetValueEx(hKeyUser,SZ_IDLERUNONBATTERIESKEY,NULL, REG_DWORD,
(LPBYTE) &(lpConnectionSettings[0].dwRunOnBatteries),
sizeof(DWORD));
}
ulWaitMinutes = lpConnectionSettings[0].ulIdleWaitMinutes;
fRunOnBatteries = lpConnectionSettings[0].dwRunOnBatteries;
// if -1 is passed in for ulWait or fRun on Batteries we need to
// get these and set them up so they can be passed onto Task Schedule
if (-1 == ulWaitMinutes)
{
dwType = REG_DWORD ;
dwDataSize = sizeof(ulWaitMinutes);
if (!(ERROR_SUCCESS == RegQueryValueEx(hKeyUser,SZ_IDLEWAITAFTERIDLEMINUTESKEY,NULL, &dwType,
(LPBYTE) &ulWaitMinutes,
&dwDataSize)) )
{
ulWaitMinutes = UL_DEFAULTIDLEWAITMINUTES;
}
}
if (-1 == fRunOnBatteries)
{
dwType = REG_DWORD ;
dwDataSize = sizeof(fRunOnBatteries);
if (!(ERROR_SUCCESS == RegQueryValueEx(hKeyUser,SZ_IDLERUNONBATTERIESKEY,NULL, &dwType,
(LPBYTE) &fRunOnBatteries,
&dwDataSize)) )
{
fRunOnBatteries = UL_DEFAULTFRUNONBATTERIES;
}
}
}
RegUpdateUserIdleKey(hKeyUser,TRUE /* fForce */); // set userlevel IdleFlags
// read in dwIdleEnabled key now that the UserKey is Updated.
dwType = REG_DWORD ;
dwDataSize = sizeof(DWORD);
if (!(ERROR_SUCCESS == RegQueryValueEx(hKeyUser,TEXT("IdleEnabled"),NULL, &dwType,
(LPBYTE) &dwIdleEnabled,
&dwDataSize)) )
{
AssertSz(0,"Unable to query User IdleEnabledKey");
dwIdleEnabled = FALSE;
}
RegCloseKey(hKeyUser);
// update the toplevel IdleSyncInfo
RegUpdateIdleKeyValue(hkeyIdleSync,dwTopLevelDefaultValue);
RegCloseKey(hkeyIdleSync);
CMutexRegistry.Leave();
RegRegisterForIdleTrigger(dwIdleEnabled,ulWaitMinutes,fRunOnBatteries);
return TRUE;
EH_Err3:
RegCloseKey(hKeyUser);
EH_Err2:
RegCloseKey(hkeyIdleSync);
EH_Err:
CMutexRegistry.Leave();
return FALSE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: RegRegisterForIdleTrigger()
Summary: Sets or removes the Idle trigger.
Returns: Returns TRUE if successful, FALSE otherwise
------------------------------------------------------------------------F-F*/
STDAPI_(BOOL) RegRegisterForIdleTrigger(BOOL fRegister,ULONG ulWaitMinutes,BOOL fRunOnBatteries)
{
HRESULT hr;
CSyncMgrSynchronize *pSyncMgrSynchronize;
LPSYNCSCHEDULEMGR pScheduleMgr;
// Review - Currently the mobsync dll is registered as apartment
// and this function can be called from Logon/Logoff which is FreeThreaded
// Correct fix is to change DLL to be registered as BOTH but until then
// just create the class directly.
#ifdef _WHENREGUPDATED
hr = CoCreateInstance(CLSID_SyncMgr,NULL,CLSCTX_ALL,
IID_ISyncScheduleMgr,(void **) &pScheduleMgr);
#endif // _WHENREGUPDATED
pSyncMgrSynchronize = new CSyncMgrSynchronize;
hr = E_OUTOFMEMORY;
if (pSyncMgrSynchronize)
{
hr = pSyncMgrSynchronize->QueryInterface(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<CONNECTIONSETTINGS> 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<CONNECTIONSETTINGS> 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<CONNECTIONSETTINGS> 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<CONNECTIONSETTINGS> 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;
}