diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql
index f5b6d176..43fabbd1 100644
--- a/WebsitePanel/Database/update_db.sql
+++ b/WebsitePanel/Database/update_db.sql
@@ -4338,3 +4338,9 @@ WHERE
RETURN
GO
+
+IF NOT EXISTS (SELECT * FROM [dbo].[Quotas] WHERE [QuotaName] = 'EnterpriseStorage.DriveMaps')
+BEGIN
+INSERT [dbo].[Quotas] ([QuotaID], [GroupID],[QuotaOrder], [QuotaName], [QuotaDescription], [QuotaTypeID], [ServiceQuota], [ItemTypeID]) VALUES (468, 44, 2, N'EnterpriseStorage.DriveMaps', N'Use Drive Maps', 1, 0, NULL)
+END
+GO
diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Packages/Quotas.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Packages/Quotas.cs
index a351f386..c3e2660e 100644
--- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Packages/Quotas.cs
+++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Packages/Quotas.cs
@@ -250,7 +250,8 @@ order by rg.groupOrder
public const string HELICON_ZOO = "HeliconZoo.*";
public const string ENTERPRISESTORAGE_DISKSTORAGESPACE = "EnterpriseStorage.DiskStorageSpace";
- public const string ENTERPRISESTORAGE_FOLDERS = "EnterpriseStorage.Folders";
+ public const string ENTERPRISESTORAGE_FOLDERS = "EnterpriseStorage.Folders";
+ public const string ENTERPRICESTORAGE_DRIVEMAPS = "EnterpriseStorage.DriveMaps";
}
}
diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/EnterpriseStorageProxy.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/EnterpriseStorageProxy.cs
index b02f51d3..85b215ef 100644
--- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/EnterpriseStorageProxy.cs
+++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/EnterpriseStorageProxy.cs
@@ -92,6 +92,16 @@ namespace WebsitePanel.EnterpriseServer
private System.Threading.SendOrPostCallback GetStatisticsByOrganizationOperationCompleted;
+ private System.Threading.SendOrPostCallback CreateMappedDriveOperationCompleted;
+
+ private System.Threading.SendOrPostCallback DeleteMappedDriveOperationCompleted;
+
+ private System.Threading.SendOrPostCallback GetDriveMapsPagedOperationCompleted;
+
+ private System.Threading.SendOrPostCallback GetUsedDriveLettersOperationCompleted;
+
+ private System.Threading.SendOrPostCallback GetNotMappedEnterpriseFoldersOperationCompleted;
+
///
public esEnterpriseStorage()
{
@@ -152,6 +162,21 @@ namespace WebsitePanel.EnterpriseServer
///
public event GetStatisticsByOrganizationCompletedEventHandler GetStatisticsByOrganizationCompleted;
+ ///
+ public event CreateMappedDriveCompletedEventHandler CreateMappedDriveCompleted;
+
+ ///
+ public event DeleteMappedDriveCompletedEventHandler DeleteMappedDriveCompleted;
+
+ ///
+ public event GetDriveMapsPagedCompletedEventHandler GetDriveMapsPagedCompleted;
+
+ ///
+ public event GetUsedDriveLettersCompletedEventHandler GetUsedDriveLettersCompleted;
+
+ ///
+ public event GetNotMappedEnterpriseFoldersCompletedEventHandler GetNotMappedEnterpriseFoldersCompleted;
+
///
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/CheckFileServicesInstallation", RequestNamespace = "http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace = "http://smbsaas/websitepanel/enterpriseserver", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public bool CheckFileServicesInstallation(int serviceId)
@@ -1115,6 +1140,278 @@ namespace WebsitePanel.EnterpriseServer
}
}
+ ///
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/CreateMappedDrive", RequestNamespace = "http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace = "http://smbsaas/websitepanel/enterpriseserver", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ public ResultObject CreateMappedDrive(int packageId, int itemId, string driveLetter, string labelAs, string folderName)
+ {
+ object[] results = this.Invoke("CreateMappedDrive", new object[] {
+ packageId,
+ itemId,
+ driveLetter,
+ labelAs,
+ folderName});
+ return ((ResultObject)(results[0]));
+ }
+
+ ///
+ public System.IAsyncResult BeginCreateMappedDrive(int packageId, int itemId, string driveLetter, string labelAs, string folderName, System.AsyncCallback callback, object asyncState)
+ {
+ return this.BeginInvoke("CreateMappedDrive", new object[] {
+ packageId,
+ itemId,
+ driveLetter,
+ labelAs,
+ folderName}, callback, asyncState);
+ }
+
+ ///
+ public ResultObject EndCreateMappedDrive(System.IAsyncResult asyncResult)
+ {
+ object[] results = this.EndInvoke(asyncResult);
+ return ((ResultObject)(results[0]));
+ }
+
+ ///
+ public void CreateMappedDriveAsync(int packageId, int itemId, string driveLetter, string labelAs, string folderName)
+ {
+ this.CreateMappedDriveAsync(packageId, itemId, driveLetter, labelAs, folderName, null);
+ }
+
+ ///
+ public void CreateMappedDriveAsync(int packageId, int itemId, string driveLetter, string labelAs, string folderName, object userState)
+ {
+ if ((this.CreateMappedDriveOperationCompleted == null))
+ {
+ this.CreateMappedDriveOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCreateMappedDriveOperationCompleted);
+ }
+ this.InvokeAsync("CreateMappedDrive", new object[] {
+ packageId,
+ itemId,
+ driveLetter,
+ labelAs,
+ folderName}, this.CreateMappedDriveOperationCompleted, userState);
+ }
+
+ private void OnCreateMappedDriveOperationCompleted(object arg)
+ {
+ if ((this.CreateMappedDriveCompleted != null))
+ {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.CreateMappedDriveCompleted(this, new CreateMappedDriveCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ ///
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/DeleteMappedDrive", RequestNamespace = "http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace = "http://smbsaas/websitepanel/enterpriseserver", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ public ResultObject DeleteMappedDrive(int itemId, string driveLetter)
+ {
+ object[] results = this.Invoke("DeleteMappedDrive", new object[] {
+ itemId,
+ driveLetter});
+ return ((ResultObject)(results[0]));
+ }
+
+ ///
+ public System.IAsyncResult BeginDeleteMappedDrive(int itemId, string driveLetter, System.AsyncCallback callback, object asyncState)
+ {
+ return this.BeginInvoke("DeleteMappedDrive", new object[] {
+ itemId,
+ driveLetter}, callback, asyncState);
+ }
+
+ ///
+ public ResultObject EndDeleteMappedDrive(System.IAsyncResult asyncResult)
+ {
+ object[] results = this.EndInvoke(asyncResult);
+ return ((ResultObject)(results[0]));
+ }
+
+ ///
+ public void DeleteMappedDriveAsync(int itemId, string driveLetter)
+ {
+ this.DeleteMappedDriveAsync(itemId, driveLetter, null);
+ }
+
+ ///
+ public void DeleteMappedDriveAsync(int itemId, string driveLetter, object userState)
+ {
+ if ((this.DeleteMappedDriveOperationCompleted == null))
+ {
+ this.DeleteMappedDriveOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteMappedDriveOperationCompleted);
+ }
+ this.InvokeAsync("DeleteMappedDrive", new object[] {
+ itemId,
+ driveLetter}, this.DeleteMappedDriveOperationCompleted, userState);
+ }
+
+ private void OnDeleteMappedDriveOperationCompleted(object arg)
+ {
+ if ((this.DeleteMappedDriveCompleted != null))
+ {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.DeleteMappedDriveCompleted(this, new DeleteMappedDriveCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ ///
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetDriveMapsPaged", RequestNamespace = "http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace = "http://smbsaas/websitepanel/enterpriseserver", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ public MappedDrivesPaged GetDriveMapsPaged(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows)
+ {
+ object[] results = this.Invoke("GetDriveMapsPaged", new object[] {
+ itemId,
+ filterValue,
+ sortColumn,
+ startRow,
+ maximumRows});
+ return ((MappedDrivesPaged)(results[0]));
+ }
+
+ ///
+ public System.IAsyncResult BeginGetDriveMapsPaged(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows, System.AsyncCallback callback, object asyncState)
+ {
+ return this.BeginInvoke("GetDriveMapsPaged", new object[] {
+ itemId,
+ filterValue,
+ sortColumn,
+ startRow,
+ maximumRows}, callback, asyncState);
+ }
+
+ ///
+ public MappedDrivesPaged EndGetDriveMapsPaged(System.IAsyncResult asyncResult)
+ {
+ object[] results = this.EndInvoke(asyncResult);
+ return ((MappedDrivesPaged)(results[0]));
+ }
+
+ ///
+ public void GetDriveMapsPagedAsync(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows)
+ {
+ this.GetDriveMapsPagedAsync(itemId, filterValue, sortColumn, startRow, maximumRows, null);
+ }
+
+ ///
+ public void GetDriveMapsPagedAsync(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows, object userState)
+ {
+ if ((this.GetDriveMapsPagedOperationCompleted == null))
+ {
+ this.GetDriveMapsPagedOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetDriveMapsPagedOperationCompleted);
+ }
+ this.InvokeAsync("GetDriveMapsPaged", new object[] {
+ itemId,
+ filterValue,
+ sortColumn,
+ startRow,
+ maximumRows}, this.GetDriveMapsPagedOperationCompleted, userState);
+ }
+
+ private void OnGetDriveMapsPagedOperationCompleted(object arg)
+ {
+ if ((this.GetDriveMapsPagedCompleted != null))
+ {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.GetDriveMapsPagedCompleted(this, new GetDriveMapsPagedCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ ///
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetUsedDriveLetters", RequestNamespace = "http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace = "http://smbsaas/websitepanel/enterpriseserver", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ public string[] GetUsedDriveLetters(int itemId)
+ {
+ object[] results = this.Invoke("GetUsedDriveLetters", new object[] {
+ itemId});
+ return ((string[])(results[0]));
+ }
+
+ ///
+ public System.IAsyncResult BeginGetUsedDriveLetters(int itemId, System.AsyncCallback callback, object asyncState)
+ {
+ return this.BeginInvoke("GetUsedDriveLetters", new object[] {
+ itemId}, callback, asyncState);
+ }
+
+ ///
+ public string[] EndGetUsedDriveLetters(System.IAsyncResult asyncResult)
+ {
+ object[] results = this.EndInvoke(asyncResult);
+ return ((string[])(results[0]));
+ }
+
+ ///
+ public void GetUsedDriveLettersAsync(int itemId)
+ {
+ this.GetUsedDriveLettersAsync(itemId, null);
+ }
+
+ ///
+ public void GetUsedDriveLettersAsync(int itemId, object userState)
+ {
+ if ((this.GetUsedDriveLettersOperationCompleted == null))
+ {
+ this.GetUsedDriveLettersOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetUsedDriveLettersOperationCompleted);
+ }
+ this.InvokeAsync("GetUsedDriveLetters", new object[] {
+ itemId}, this.GetUsedDriveLettersOperationCompleted, userState);
+ }
+
+ private void OnGetUsedDriveLettersOperationCompleted(object arg)
+ {
+ if ((this.GetUsedDriveLettersCompleted != null))
+ {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.GetUsedDriveLettersCompleted(this, new GetUsedDriveLettersCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ ///
+ [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetNotMappedEnterpriseFolders", RequestNamespace = "http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace = "http://smbsaas/websitepanel/enterpriseserver", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
+ public SystemFile[] GetNotMappedEnterpriseFolders(int itemId)
+ {
+ object[] results = this.Invoke("GetNotMappedEnterpriseFolders", new object[] {
+ itemId});
+ return ((SystemFile[])(results[0]));
+ }
+
+ ///
+ public System.IAsyncResult BeginGetNotMappedEnterpriseFolders(int itemId, System.AsyncCallback callback, object asyncState)
+ {
+ return this.BeginInvoke("GetNotMappedEnterpriseFolders", new object[] {
+ itemId}, callback, asyncState);
+ }
+
+ ///
+ public SystemFile[] EndGetNotMappedEnterpriseFolders(System.IAsyncResult asyncResult)
+ {
+ object[] results = this.EndInvoke(asyncResult);
+ return ((SystemFile[])(results[0]));
+ }
+
+ ///
+ public void GetNotMappedEnterpriseFoldersAsync(int itemId)
+ {
+ this.GetNotMappedEnterpriseFoldersAsync(itemId, null);
+ }
+
+ ///
+ public void GetNotMappedEnterpriseFoldersAsync(int itemId, object userState)
+ {
+ if ((this.GetNotMappedEnterpriseFoldersOperationCompleted == null))
+ {
+ this.GetNotMappedEnterpriseFoldersOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetNotMappedEnterpriseFoldersOperationCompleted);
+ }
+ this.InvokeAsync("GetNotMappedEnterpriseFolders", new object[] {
+ itemId}, this.GetNotMappedEnterpriseFoldersOperationCompleted, userState);
+ }
+
+ private void OnGetNotMappedEnterpriseFoldersOperationCompleted(object arg)
+ {
+ if ((this.GetNotMappedEnterpriseFoldersCompleted != null))
+ {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.GetNotMappedEnterpriseFoldersCompleted(this, new GetNotMappedEnterpriseFoldersCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
///
public new void CancelAsync(object userState)
{
@@ -1609,4 +1906,154 @@ namespace WebsitePanel.EnterpriseServer
}
}
}
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ public delegate void CreateMappedDriveCompletedEventHandler(object sender, CreateMappedDriveCompletedEventArgs e);
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class CreateMappedDriveCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+ {
+
+ private object[] results;
+
+ internal CreateMappedDriveCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState)
+ {
+ this.results = results;
+ }
+
+ ///
+ public ResultObject Result
+ {
+ get
+ {
+ this.RaiseExceptionIfNecessary();
+ return ((ResultObject)(this.results[0]));
+ }
+ }
+ }
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ public delegate void DeleteMappedDriveCompletedEventHandler(object sender, DeleteMappedDriveCompletedEventArgs e);
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class DeleteMappedDriveCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+ {
+
+ private object[] results;
+
+ internal DeleteMappedDriveCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState)
+ {
+ this.results = results;
+ }
+
+ ///
+ public ResultObject Result
+ {
+ get
+ {
+ this.RaiseExceptionIfNecessary();
+ return ((ResultObject)(this.results[0]));
+ }
+ }
+ }
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ public delegate void GetDriveMapsPagedCompletedEventHandler(object sender, GetDriveMapsPagedCompletedEventArgs e);
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class GetDriveMapsPagedCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+ {
+
+ private object[] results;
+
+ internal GetDriveMapsPagedCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState)
+ {
+ this.results = results;
+ }
+
+ ///
+ public MappedDrivesPaged Result
+ {
+ get
+ {
+ this.RaiseExceptionIfNecessary();
+ return ((MappedDrivesPaged)(this.results[0]));
+ }
+ }
+ }
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ public delegate void GetUsedDriveLettersCompletedEventHandler(object sender, GetUsedDriveLettersCompletedEventArgs e);
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class GetUsedDriveLettersCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+ {
+
+ private object[] results;
+
+ internal GetUsedDriveLettersCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState)
+ {
+ this.results = results;
+ }
+
+ ///
+ public string[] Result
+ {
+ get
+ {
+ this.RaiseExceptionIfNecessary();
+ return ((string[])(this.results[0]));
+ }
+ }
+ }
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ public delegate void GetNotMappedEnterpriseFoldersCompletedEventHandler(object sender, GetNotMappedEnterpriseFoldersCompletedEventArgs e);
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class GetNotMappedEnterpriseFoldersCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
+ {
+
+ private object[] results;
+
+ internal GetNotMappedEnterpriseFoldersCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState)
+ {
+ this.results = results;
+ }
+
+ ///
+ public SystemFile[] Result
+ {
+ get
+ {
+ this.RaiseExceptionIfNecessary();
+ return ((SystemFile[])(this.results[0]));
+ }
+ }
+ }
}
diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs
index 42044528..058461da 100644
--- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs
+++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs
@@ -305,7 +305,7 @@ namespace WebsitePanel.EnterpriseServer
EnterpriseStorageController.DeleteWebDavDirectory(packageId, usersDomain, org.OrganizationId);
EnterpriseStorageController.DeleteFolder(itemId);
-
+ EnterpriseStorageController.DeleteMappedDrivesGPO(itemId);
}
}
catch (Exception ex)
@@ -577,6 +577,12 @@ namespace WebsitePanel.EnterpriseServer
es.DeleteFolder(org.OrganizationId, folderName, webDavSetting);
+ string path = string.Format(@"\\{0}@SSL\{1}\{2}", webDavSetting.Domain.Split('.')[0], org.OrganizationId, folderName);
+
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ orgProxy.DeleteMappedDriveByPath(org.OrganizationId, path);
+
DataProvider.DeleteEnterpriseFolder(itemId, folderName);
}
catch (Exception ex)
@@ -659,6 +665,21 @@ namespace WebsitePanel.EnterpriseServer
List folders = es.GetFolders(org.OrganizationId, webDavSettings).Where(x => x.Name.Contains(filterValue)).ToList();
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ List mappedDrives = orgProxy.GetDriveMaps(org.OrganizationId).ToList();
+
+ foreach (MappedDrive drive in mappedDrives)
+ {
+ foreach (SystemFile folder in folders)
+ {
+ if (drive.Path.Split('\\').Last() == folder.Name)
+ {
+ folder.DriveLetter = drive.DriveLetter;
+ }
+ }
+ }
+
switch (sortColumn)
{
case "Size":
@@ -786,6 +807,8 @@ namespace WebsitePanel.EnterpriseServer
DataProvider.GetEnterpriseFolder(itemId, folder));
es.SetFolderWebDavRules(org.OrganizationId, folder, webDavSetting, rules);
+
+ EnterpriseStorageController.SetDriveMapsTargetingFilter(org, permission, folder);
}
catch (Exception ex)
{
@@ -890,6 +913,7 @@ namespace WebsitePanel.EnterpriseServer
|| account.AccountType == ExchangeAccountType.DefaultSecurityGroup)
{
rule.Roles.Add(permission.Account);
+ permission.IsGroup = true;
}
else
{
@@ -1196,5 +1220,331 @@ namespace WebsitePanel.EnterpriseServer
}
#endregion
+
+ #region Drive Mapping
+
+ public static ResultObject CreateMappedDrive(int packageId, int itemId, string driveLetter, string labelAs, string folderName)
+ {
+ return CreateMappedDriveInternal(packageId, itemId, driveLetter, labelAs, folderName);
+ }
+
+ protected static ResultObject CreateMappedDriveInternal(int packageId, int itemId, string driveLetter, string labelAs, string folderName)
+ {
+ ResultObject result = TaskManager.StartResultTask("ENTERPRISE_STORAGE", "CREATE_MAPPED_DRIVE", itemId);
+
+ try
+ {
+ // load organization
+ Organization org = OrganizationController.GetOrganization(itemId);
+ if (org == null)
+ {
+ result.IsSuccess = false;
+ result.AddError("", new NullReferenceException("Organization not found"));
+ return result;
+ }
+
+ int esServiceId = PackageController.GetPackageServiceId(packageId, ResourceGroups.EnterpriseStorage);
+
+ if (esServiceId != 0)
+ {
+ var webDavSetting = ObjectUtils.FillObjectFromDataReader(
+ DataProvider.GetEnterpriseFolder(itemId, folderName));
+
+ string path = string.Format(@"\\{0}@SSL\{1}\{2}", webDavSetting.Domain.Split('.')[0], org.OrganizationId, folderName);
+
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ if (orgProxy.CreateMappedDrive(org.OrganizationId, driveLetter, labelAs, path) == 0)
+ {
+ var folder = GetFolder(itemId, folderName);
+
+ EnterpriseStorageController.SetDriveMapsTargetingFilter(org, ConvertToESPermission(itemId, folder.Rules), folderName);
+ }
+ else
+ {
+ result.AddError("", new Exception("Organization already has mapped drive for this folder"));
+ return result;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ result.AddError("ENTERPRISE_STORAGE_CREATE_MAPPED_DRIVE", ex);
+ }
+ finally
+ {
+ if (!result.IsSuccess)
+ {
+ TaskManager.CompleteResultTask(result);
+ }
+ else
+ {
+ TaskManager.CompleteResultTask();
+ }
+ }
+
+ return result;
+ }
+
+ public static ResultObject DeleteMappedDrive(int itemId, string driveLetter)
+ {
+ return DeleteMappedDriveInternal(itemId, driveLetter);
+ }
+
+ protected static ResultObject DeleteMappedDriveInternal(int itemId, string driveLetter)
+ {
+ ResultObject result = TaskManager.StartResultTask("ENTERPRISE_STORAGE", "DELETE_MAPPED_DRIVE", itemId);
+
+ try
+ {
+ // load organization
+ Organization org = OrganizationController.GetOrganization(itemId);
+ if (org == null)
+ {
+ result.IsSuccess = false;
+ result.AddError("", new NullReferenceException("Organization not found"));
+ return result;
+ }
+
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ orgProxy.DeleteMappedDrive(org.OrganizationId, driveLetter);
+ }
+ catch (Exception ex)
+ {
+ result.AddError("ENTERPRISE_STORAGE_DELETE_MAPPED_DRIVE", ex);
+ }
+ finally
+ {
+ if (!result.IsSuccess)
+ {
+ TaskManager.CompleteResultTask(result);
+ }
+ else
+ {
+ TaskManager.CompleteResultTask();
+ }
+ }
+
+ return result;
+ }
+
+ public static MappedDrivesPaged GetDriveMapsPaged(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows)
+ {
+ return GetDriveMapsPagedInternal(itemId, filterValue, sortColumn, startRow, maximumRows);
+ }
+
+ protected static MappedDrivesPaged GetDriveMapsPagedInternal(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows)
+ {
+ MappedDrivesPaged result = new MappedDrivesPaged();
+
+ try
+ {
+ // load organization
+ Organization org = OrganizationController.GetOrganization(itemId);
+
+ if (org == null)
+ {
+ return null;
+ }
+
+ EnterpriseStorage es = GetEnterpriseStorage(GetEnterpriseStorageServiceID(org.PackageId));
+
+ var webDavSettings = ObjectUtils.CreateListFromDataReader(
+ DataProvider.GetEnterpriseFolders(itemId)).ToArray();
+
+ List folders = es.GetFolders(org.OrganizationId, webDavSettings).ToList();
+
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ List mappedDrives = orgProxy.GetDriveMaps(org.OrganizationId).Where(x => x.LabelAs.Contains(filterValue)).ToList();
+ List resultItems = new List();
+
+ foreach (MappedDrive drive in mappedDrives)
+ {
+ foreach (SystemFile folder in folders)
+ {
+ if (drive.Path.Split('\\').Last() == folder.Name)
+ {
+ drive.Folder = folder;
+ resultItems.Add(drive);
+ }
+ }
+ }
+
+ mappedDrives = resultItems;
+
+ switch (sortColumn)
+ {
+ case "Label":
+ mappedDrives = mappedDrives.OrderBy(x => x.LabelAs).ToList();
+ break;
+ default:
+ mappedDrives = mappedDrives.OrderBy(x => x.DriveLetter).ToList();
+ break;
+ }
+
+ result.RecordsCount = mappedDrives.Count;
+ result.PageItems = mappedDrives.Skip(startRow).Take(maximumRows).ToArray();
+
+ }
+ catch (Exception ex) { throw ex; }
+
+ return result;
+ }
+
+ public static string[] GetUsedDriveLetters(int itemId)
+ {
+ return GetUsedDriveLettersInternal(itemId);
+ }
+
+ protected static string[] GetUsedDriveLettersInternal(int itemId)
+ {
+ List driveLetters = new List();
+
+ try
+ {
+ // load organization
+ Organization org = OrganizationController.GetOrganization(itemId);
+
+ if (org == null)
+ {
+ return null;
+ }
+
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ driveLetters = orgProxy.GetDriveMaps(org.OrganizationId).Select(x => x.DriveLetter).ToList();
+ }
+ catch (Exception ex) { throw ex; }
+
+ return driveLetters.ToArray();
+
+ }
+
+ public static SystemFile[] GetNotMappedEnterpriseFolders(int itemId)
+ {
+ return GetNotMappedEnterpriseFoldersInternal(itemId);
+ }
+
+ protected static SystemFile[] GetNotMappedEnterpriseFoldersInternal(int itemId)
+ {
+ List folders = new List();
+ try
+ {
+ // load organization
+ Organization org = OrganizationController.GetOrganization(itemId);
+
+ if (org == null)
+ {
+ return null;
+ }
+
+ if (CheckUsersDomainExistsInternal(itemId, org.PackageId))
+ {
+ EnterpriseStorage es = GetEnterpriseStorage(GetEnterpriseStorageServiceID(org.PackageId));
+
+ var webDavSettings = ObjectUtils.CreateListFromDataReader(
+ DataProvider.GetEnterpriseFolders(itemId)).ToArray();
+
+ folders = es.GetFolders(org.OrganizationId, webDavSettings).ToList();
+
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ List drives = orgProxy.GetDriveMaps(org.OrganizationId).ToList();
+
+ foreach (MappedDrive drive in drives)
+ {
+ foreach (SystemFile folder in folders)
+ {
+ if (drive.Path.Split('\\').Last() == folder.Name)
+ {
+ folders.Remove(folder);
+ break;
+ }
+ }
+ }
+ }
+ }
+ catch (Exception ex) { throw ex; }
+
+ return folders.ToArray();
+ }
+
+ private static ResultObject SetDriveMapsTargetingFilter(Organization org, ESPermission[] permissions, string folderName)
+ {
+ ResultObject result = TaskManager.StartResultTask("ENTERPRISE_STORAGE", "SET_MAPPED_DRIVE_TARGETING_FILTER");
+
+ try
+ {
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ List accounts = new List();
+
+ foreach (var permission in permissions)
+ {
+ accounts.Add(ObjectUtils.FillObjectFromDataReader(DataProvider.GetExchangeAccountByAccountName(org.Id, permission.Account)));
+ }
+
+ orgProxy.SetDriveMapsTargetingFilter(org.OrganizationId, accounts.ToArray(), folderName);
+ }
+ catch (Exception ex)
+ {
+ result.AddError("ENTERPRISE_STORAGE_SET_MAPPED_DRIVE_TARGETING_FILTER", ex);
+ }
+ finally
+ {
+ if (!result.IsSuccess)
+ {
+ TaskManager.CompleteResultTask(result);
+ }
+ else
+ {
+ TaskManager.CompleteResultTask();
+ }
+ }
+
+ return result;
+ }
+
+ private static ResultObject DeleteMappedDrivesGPO(int itemId)
+ {
+ ResultObject result = TaskManager.StartResultTask("ENTERPRISE_STORAGE", "DELETE_MAPPED_DRIVES_GPO", itemId);
+
+ try
+ {
+ // load organization
+ Organization org = OrganizationController.GetOrganization(itemId);
+ if (org == null)
+ {
+ result.IsSuccess = false;
+ result.AddError("", new NullReferenceException("Organization not found"));
+ return result;
+ }
+
+ Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId);
+
+ orgProxy.DeleteMappedDrivesGPO(org.OrganizationId);
+ }
+ catch (Exception ex)
+ {
+ result.AddError("ENTERPRISE_STORAGE_DELETE_MAPPED_DRIVES_GPO", ex);
+ }
+ finally
+ {
+ if (!result.IsSuccess)
+ {
+ TaskManager.CompleteResultTask(result);
+ }
+ else
+ {
+ TaskManager.CompleteResultTask();
+ }
+ }
+
+ return result;
+ }
+
+ #endregion
}
}
diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esEnterpriseStorage.asmx.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esEnterpriseStorage.asmx.cs
index 19e58d80..8f81ab72 100644
--- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esEnterpriseStorage.asmx.cs
+++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esEnterpriseStorage.asmx.cs
@@ -174,5 +174,39 @@ namespace WebsitePanel.EnterpriseServer
}
#endregion
+
+ #region Drive Mapping
+
+ [WebMethod]
+ public ResultObject CreateMappedDrive(int packageId, int itemId, string driveLetter, string labelAs, string folderName)
+ {
+ return EnterpriseStorageController.CreateMappedDrive(packageId, itemId, driveLetter, labelAs, folderName);
+ }
+
+ [WebMethod]
+ public ResultObject DeleteMappedDrive(int itemId, string driveLetter)
+ {
+ return EnterpriseStorageController.DeleteMappedDrive(itemId, driveLetter);
+ }
+
+ [WebMethod]
+ public MappedDrivesPaged GetDriveMapsPaged(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows)
+ {
+ return EnterpriseStorageController.GetDriveMapsPaged(itemId, filterValue, sortColumn, startRow, maximumRows);
+ }
+
+ [WebMethod]
+ public string[] GetUsedDriveLetters(int itemId)
+ {
+ return EnterpriseStorageController.GetUsedDriveLetters(itemId);
+ }
+
+ [WebMethod]
+ public SystemFile[] GetNotMappedEnterpriseFolders(int itemId)
+ {
+ return EnterpriseStorageController.GetNotMappedEnterpriseFolders(itemId);
+ }
+
+ #endregion
}
}
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/Errors.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/Errors.cs
index ddc514cb..4559255b 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/Errors.cs
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/Errors.cs
@@ -32,5 +32,6 @@ namespace WebsitePanel.Providers.HostedSolution
{
public const int OK = 0;
public const int AD_OBJECT_ALREADY_EXISTS = -1;
+ public const int MAPPED_DRIVE_ALREADY_EXISTS = -2;
}
}
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs
index ae4a233b..829684c2 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs
@@ -26,6 +26,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+using WebsitePanel.Providers.OS;
using WebsitePanel.Providers.ResultObjects;
namespace WebsitePanel.Providers.HostedSolution
@@ -78,5 +79,17 @@ namespace WebsitePanel.Providers.HostedSolution
string GetSamAccountNameByUserPrincipalName(string organizationId, string userPrincipalName);
bool DoesSamAccountNameExist(string accountName);
+
+ MappedDrive[] GetDriveMaps(string organizationId);
+
+ int CreateMappedDrive(string organizationId, string drive, string labelAs, string path);
+
+ void DeleteMappedDrive(string organizationId, string drive);
+
+ void DeleteMappedDriveByPath(string organizationId, string path);
+
+ void DeleteMappedDrivesGPO(string organizationId);
+
+ void SetDriveMapsTargetingFilter(string organizationId, ExchangeAccount[] accounts, string folderName);
}
}
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrive.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrive.cs
new file mode 100644
index 00000000..2a34a2d0
--- /dev/null
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrive.cs
@@ -0,0 +1,80 @@
+// Copyright (c) 2014, Outercurve Foundation.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// - Neither the name of the Outercurve Foundation nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+using System;
+
+namespace WebsitePanel.Providers.OS
+{
+ ///
+ /// Summary description for MappedDrive.
+ ///
+ [Serializable]
+ public class MappedDrive
+ {
+ private string path;
+ private string labelAs;
+ private string driveLetter;
+ private SystemFile folder;
+
+ public MappedDrive()
+ {
+ }
+
+ public MappedDrive(string path, string labelAs, string driveLetter)
+ {
+ this.Path = path;
+ this.LabelAs = labelAs;
+ this.DriveLetter = driveLetter;
+ SystemFile folder = null;
+ }
+
+ public string Path
+ {
+ get { return this.path; }
+ set { this.path = value; }
+ }
+
+ public string LabelAs
+ {
+ get { return this.labelAs; }
+ set { this.labelAs = value; }
+ }
+
+ public string DriveLetter
+ {
+ get { return this.driveLetter; }
+ set { this.driveLetter = value; }
+ }
+
+ public SystemFile Folder
+ {
+ get { return this.folder; }
+ set { this.folder = value; }
+ }
+ }
+}
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrivesPaged.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrivesPaged.cs
new file mode 100644
index 00000000..35a0603d
--- /dev/null
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrivesPaged.cs
@@ -0,0 +1,20 @@
+namespace WebsitePanel.Providers.OS
+{
+ public class MappedDrivesPaged
+ {
+ int recordsCount;
+ MappedDrive[] pageItems;
+
+ public int RecordsCount
+ {
+ get { return this.recordsCount; }
+ set { this.recordsCount = value; }
+ }
+
+ public MappedDrive[] PageItems
+ {
+ get { return this.pageItems; }
+ set { this.pageItems = value; }
+ }
+ }
+}
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/SystemFile.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/SystemFile.cs
index b7ba39ce..7ec99ac7 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/SystemFile.cs
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/SystemFile.cs
@@ -49,6 +49,7 @@ namespace WebsitePanel.Providers.OS
private int fsrmQuotaMB;
private int frsmQuotaGB;
private QuotaType fsrmQuotaType = QuotaType.Soft;
+ private string driveLetter;
public SystemFile()
{
@@ -142,5 +143,11 @@ namespace WebsitePanel.Providers.OS
get { return this.url; }
set { this.url = value; }
}
+
+ public string DriveLetter
+ {
+ get { return this.driveLetter; }
+ set { this.driveLetter = value; }
+ }
}
}
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj
index 6a3141a3..2ab48c12 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj
@@ -117,6 +117,8 @@
+
+
diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs
index 0781138d..f2faeb9c 100644
--- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs
+++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs
@@ -27,17 +27,35 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
+using System.IO;
+using System.Xml;
+using System.Linq;
+using System.Text;
+using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.DirectoryServices;
using System.Globalization;
-using System.Text;
+
+using System.Management.Automation;
+using System.Management.Automation.Runspaces;
+
using WebsitePanel.Providers.Common;
using WebsitePanel.Providers.ResultObjects;
+using WebsitePanel.Providers.OS;
namespace WebsitePanel.Providers.HostedSolution
{
public class OrganizationProvider : HostingServiceProviderBase, IOrganization
{
+ #region Constants
+
+ private const string GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE = @"\\{0}\SYSVOL\{0}\Policies\{1}\User\Preferences\Drives";
+ private const string DRIVES_CLSID = "{8FDDCC1A-0C3C-43cd-A6B4-71A6DF20DA8C}";
+ private const string DRIVE_CLSID = "{935D1B74-9CB8-4e3c-9914-7DD559B7A417}";
+
+ #endregion
+
#region Properties
private string RootOU
@@ -61,6 +79,36 @@ namespace WebsitePanel.Providers.HostedSolution
#region Helpers
+ private string GetObjectTargetAccountName(string accountName, string domain)
+ {
+ string part = domain.Split('.')[0].ToUpperInvariant();
+
+ return string.Format("{0}\\{1}", part, accountName);
+ }
+
+ private string GetOrganizationTargetPath(string organizationId)
+ {
+ StringBuilder sb = new StringBuilder();
+ // append provider
+ AppendOUPath(sb, organizationId);
+ AppendOUPath(sb, RootOU);
+ AppendDomainPath(sb, RootDomain);
+
+ return sb.ToString();
+ }
+
+ private string GetObjectTargetPath(string organizationId, string objName)
+ {
+ StringBuilder sb = new StringBuilder();
+ // append provider
+ AppendCNPath(sb, objName);
+ AppendOUPath(sb, organizationId);
+ AppendOUPath(sb, RootOU);
+ AppendDomainPath(sb, RootDomain);
+
+ return sb.ToString();
+ }
+
private string GetOrganizationPath(string organizationId)
{
StringBuilder sb = new StringBuilder();
@@ -1097,6 +1145,702 @@ namespace WebsitePanel.Providers.HostedSolution
#endregion
+ #region Drive Mapping
+
+ public MappedDrive[] GetDriveMaps(string organizationId)
+ {
+ return GetDriveMapsInternal(organizationId);
+ }
+
+ internal MappedDrive[] GetDriveMapsInternal(string organizationId)
+ {
+ HostedSolutionLog.LogStart("GetDriveMapsInternal");
+ HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId);
+
+ if (string.IsNullOrEmpty(organizationId))
+ throw new ArgumentNullException("organizationId");
+
+ string gpoId;
+
+ if (!CheckMappedDriveGpoExists(organizationId, out gpoId))
+ {
+ CreateAndLinkMappedDrivesGPO(organizationId, out gpoId);
+ }
+
+ ArrayList items = new ArrayList();
+
+ if (!string.IsNullOrEmpty(gpoId))
+ {
+ string path = string.Format("{0}\\{1}",
+ string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId),
+ "Drives.xml");
+
+ // open xml document
+ XmlDocument xml = new XmlDocument();
+ xml.Load(path);
+
+ HostedSolutionLog.LogEnd("GetDriveMapsInternal");
+
+ return GetDrivesFromXML(xml, items);
+ }
+
+ HostedSolutionLog.LogEnd("GetDriveMapsInternal");
+
+ return (MappedDrive[])items.ToArray(typeof(MappedDrive));
+ }
+
+ public int CreateMappedDrive(string organizationId, string drive, string labelAs, string path)
+ {
+ return CreateMappedDriveInternal(organizationId, drive, labelAs, path);
+ }
+
+ internal int CreateMappedDriveInternal(string organizationId, string drive, string labelAs, string path)
+ {
+ HostedSolutionLog.LogStart("CreateMappedDriveInternal");
+ HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId);
+ HostedSolutionLog.DebugInfo("driveLetter : {0}:", drive);
+
+ if (string.IsNullOrEmpty(organizationId))
+ throw new ArgumentNullException("organizationId");
+
+ if (string.IsNullOrEmpty(drive))
+ throw new ArgumentNullException("driveLetter");
+
+ string gpoId;
+
+ if (!CheckMappedDriveGpoExists(organizationId, out gpoId))
+ {
+ CreateAndLinkMappedDrivesGPO(organizationId, out gpoId);
+ }
+
+ if (CheckMappedDriveExists(organizationId, path))
+ {
+ return Errors.MAPPED_DRIVE_ALREADY_EXISTS;
+ }
+
+ if (!string.IsNullOrEmpty(gpoId))
+ {
+ string drivesXmlPath = string.Format("{0}\\{1}",
+ string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId),
+ "Drives.xml");
+ // open xml document
+ XmlDocument xml = new XmlDocument();
+ xml.Load(drivesXmlPath);
+
+ XmlNode drivesNode = xml.SelectSingleNode("(/*)");
+ XmlNode driveNode = CreateDriveNode(xml, drive, labelAs, path);
+
+ drivesNode.AppendChild(driveNode);
+
+ xml.Save(drivesXmlPath);
+ }
+
+ HostedSolutionLog.LogEnd("CreateMappedDriveInternal");
+
+ return Errors.OK;
+ }
+
+ public void DeleteMappedDriveByPath(string organizationId, string path)
+ {
+ DeleteMappedDriveByPathInternal(organizationId, path);
+ }
+
+ internal void DeleteMappedDriveByPathInternal(string organizationId, string path)
+ {
+ MappedDrive drive = GetDriveMaps(organizationId).Where(x => x.Path == path).FirstOrDefault();
+
+ if (drive != null)
+ {
+ DeleteMappedDriveInternal(organizationId, drive.DriveLetter);
+ }
+ }
+
+ public void DeleteMappedDrive(string organizationId, string drive)
+ {
+ DeleteMappedDriveInternal(organizationId, drive);
+ }
+
+ internal void DeleteMappedDriveInternal(string organizationId, string drive)
+ {
+ HostedSolutionLog.LogStart("DeleteMappedDriveInternal");
+ HostedSolutionLog.DebugInfo("driveLetter : {0}:", drive);
+ HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId);
+
+ if (string.IsNullOrEmpty(organizationId))
+ throw new ArgumentNullException("organizationId");
+
+ if (string.IsNullOrEmpty(drive))
+ throw new ArgumentNullException("driveLetter");
+
+ string gpoId;
+
+ if (!CheckMappedDriveGpoExists(organizationId, out gpoId))
+ {
+ CreateAndLinkMappedDrivesGPO(organizationId, out gpoId);
+ }
+
+ if (!string.IsNullOrEmpty(gpoId))
+ {
+ string path = string.Format("{0}\\{1}",
+ string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId),
+ "Drives.xml");
+
+ // open xml document
+ XmlDocument xml = new XmlDocument();
+ xml.Load(path);
+
+ XmlNode x = xml.SelectSingleNode(string.Format("/Drives/Drive[@name='{0}:']", drive));
+ if (x != null)
+ {
+ x.ParentNode.RemoveChild(x);
+ }
+
+ xml.Save(path);
+ }
+
+ HostedSolutionLog.LogEnd("DeleteMappedDriveInternal");
+ }
+
+ public void DeleteMappedDrivesGPO(string organizationId)
+ {
+ DeleteMappedDrivesGPOInternal(organizationId);
+ }
+
+ internal void DeleteMappedDrivesGPOInternal(string organizationId)
+ {
+ HostedSolutionLog.LogStart("DeleteMappedDrivesGPOInternal");
+ HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId);
+
+ Runspace runSpace = null;
+
+ try
+ {
+ runSpace = OpenRunspace();
+
+ ImportGroupPolicyMolude(runSpace);
+
+ string gpoName = string.Format("{0}-mapped-drives", organizationId);
+
+ //create new gpo
+ Command cmd = new Command("Remove-GPO");
+ cmd.Parameters.Add("Name", gpoName);
+
+ ExecuteShellCommand(runSpace, cmd);
+ }
+ catch (Exception ex)
+ {
+ CloseRunspace(runSpace);
+ }
+ finally
+ {
+ CloseRunspace(runSpace);
+
+ HostedSolutionLog.LogEnd("DeleteMappedDrivesGPOInternal");
+ }
+ }
+
+ public void SetDriveMapsTargetingFilter(string organizationId, ExchangeAccount[] accounts, string folderName)
+ {
+ SetDriveMapsTargetingFilterInternal(organizationId, accounts, folderName);
+ }
+
+ internal void SetDriveMapsTargetingFilterInternal(string organizationId, ExchangeAccount[] accounts, string folderName)
+ {
+ HostedSolutionLog.LogStart("SetDriveMapsTargetingFilterInternal");
+ HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId);
+ HostedSolutionLog.DebugInfo("folderName : {0}", folderName);
+
+ if (string.IsNullOrEmpty(organizationId))
+ throw new ArgumentNullException("organizationId");
+
+ if (string.IsNullOrEmpty(folderName))
+ throw new ArgumentNullException("folderName");
+
+ Runspace runSpace = null;
+
+ try
+ {
+ runSpace = OpenRunspace();
+
+ //import grouppolicy module
+ ImportGroupPolicyMolude(runSpace);
+
+ Dictionary sidAccountPairs = new Dictionary();
+
+ Command cmd;
+
+ foreach (var account in accounts)
+ {
+ string pathObj = GetObjectTargetPath(organizationId, account.AccountName);
+
+ if (IsGroup(account))
+ {
+ //get group sid
+ cmd = new Command("Get-ADGroup");
+ cmd.Parameters.Add("SearchBase", pathObj);
+ cmd.Parameters.Add("Filter", "*");
+
+ Collection result = ExecuteShellCommand(runSpace, cmd);
+
+ if (result != null && result.Count > 0)
+ {
+ PSObject group = result[0];
+
+ sidAccountPairs.Add(GetPSObjectProperty(group, "SID").ToString(), account);
+ }
+ }
+ else
+ {
+ //get user sid
+ cmd = new Command("Get-ADUser");
+ cmd.Parameters.Add("SearchBase", pathObj);
+ cmd.Parameters.Add("Filter", "*");
+
+ Collection result = ExecuteShellCommand(runSpace, cmd);
+
+ if (result != null && result.Count > 0)
+ {
+ PSObject user = result[0];
+
+ sidAccountPairs.Add(GetPSObjectProperty(user, "SID").ToString(), account);
+ }
+ }
+ }
+
+ string gpoId;
+
+ if (!CheckMappedDriveGpoExists(organizationId, out gpoId))
+ {
+ CreateAndLinkMappedDrivesGPO(organizationId, out gpoId);
+ }
+
+ if (!string.IsNullOrEmpty(gpoId))
+ {
+ string drivesXmlPath = string.Format("{0}\\{1}",
+ string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId),
+ "Drives.xml");
+ // open xml document
+ XmlDocument xml = new XmlDocument();
+ xml.Load(drivesXmlPath);
+
+ XmlNodeList drives = xml.SelectNodes(string.Format("./Drives/Drive[contains(Properties/@path,'{0}')]", folderName));
+
+ foreach (XmlNode driveNode in drives)
+ {
+ XmlNodeList childNodes = driveNode.ChildNodes;
+
+ if (childNodes.Count > 1)
+ {
+ //delete existing filters
+ driveNode.LastChild.ParentNode.RemoveChild(driveNode.LastChild);
+ }
+
+ XmlNode newFiltersNode = CreateFiltersNode(xml, sidAccountPairs);
+
+ driveNode.AppendChild(newFiltersNode);
+ }
+
+ xml.Save(drivesXmlPath);
+ }
+ }
+ catch (Exception ex)
+ {
+
+ }
+ finally
+ {
+ CloseRunspace(runSpace);
+
+ HostedSolutionLog.LogEnd("SetDriveMapsTargetingFilterInternal");
+ }
+ }
+
+ private void CreateAndLinkMappedDrivesGPO(string organizationId, out string gpoId)
+ {
+ Runspace runSpace = null;
+
+ try
+ {
+ runSpace = OpenRunspace();
+
+ ImportGroupPolicyMolude(runSpace);
+
+ string gpoName = string.Format("{0}-mapped-drives", organizationId);
+ string pathOU = GetOrganizationTargetPath(organizationId);
+
+ //create new gpo
+ Command cmd = new Command("New-GPO");
+ cmd.Parameters.Add("Name", gpoName);
+
+ Collection result = ExecuteShellCommand(runSpace, cmd);
+
+ gpoId = null;
+
+ if (result != null && result.Count > 0)
+ {
+ PSObject gpo = result[0];
+ //get gpo id
+ gpoId = ((Guid)GetPSObjectProperty(gpo, "Id")).ToString("B");
+
+ }
+
+ //create gpo link
+ cmd = new Command("New-GPLink");
+ cmd.Parameters.Add("Name", gpoName);
+ cmd.Parameters.Add("Target", pathOU);
+
+ ExecuteShellCommand(runSpace, cmd);
+
+ //create empty drives.xml file for for gpo drives mapping
+ CreateDrivesXmlEmpty(string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId), "Drives.xml");
+ }
+ catch (Exception ex)
+ {
+ gpoId = null;
+ CloseRunspace(runSpace);
+ }
+ finally
+ {
+ CloseRunspace(runSpace);
+ }
+ }
+
+ private bool CheckMappedDriveGpoExists(string organizationId, out string gpoId)
+ {
+ Runspace runSpace = null;
+
+ try
+ {
+ runSpace = OpenRunspace();
+
+ ImportGroupPolicyMolude(runSpace);
+
+ string gpoName = string.Format("{0}-mapped-drives", organizationId);
+
+ Command cmd = new Command("Get-GPO");
+ cmd.Parameters.Add("Name", gpoName);
+
+ Collection result = ExecuteShellCommand(runSpace, cmd);
+
+ gpoId = null;
+
+ if (result != null && result.Count > 0)
+ {
+ PSObject gpo = result[0];
+ gpoId = ((Guid)GetPSObjectProperty(gpo, "Id")).ToString("B");
+ }
+ }
+ finally
+ {
+ CloseRunspace(runSpace);
+ }
+
+ return string.IsNullOrEmpty(gpoId) ? false : true;
+ }
+
+ private bool CheckMappedDriveExists(string organizationId, string path)
+ {
+ bool exists = false;
+
+ MappedDrive[] drives = GetDriveMapsInternal(organizationId);
+
+ foreach (var item in drives)
+ {
+ if (item.Path == path)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ return exists;
+ }
+
+ #region Drive Mapping Helpers
+
+ private void ImportGroupPolicyMolude(Runspace runSpace)
+ {
+ Command cmd = new Command("Import-Module");
+ cmd.Parameters.Add("Name", "grouppolicy");
+
+ ExecuteShellCommand(runSpace, cmd);
+ }
+
+ private void CreateDrivesXmlEmpty(string path, string fileName)
+ {
+ DirectoryInfo drivesDirectory = new DirectoryInfo(path);
+
+ if (!drivesDirectory.Exists)
+ {
+ drivesDirectory.Create();
+ }
+
+ XmlDocument doc = new XmlDocument();
+
+ XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
+ doc.AppendChild(docNode);
+
+ XmlNode drivesNode = doc.CreateElement("Drives");
+
+ XmlAttribute drivesAttribute = doc.CreateAttribute("clsid");
+ drivesAttribute.Value = DRIVES_CLSID;
+ drivesNode.Attributes.Append(drivesAttribute);
+
+ doc.AppendChild(drivesNode);
+
+ doc.Save(string.Format("{0}\\{1}", path, fileName));
+ }
+
+ private XmlNode CreateDriveNode(XmlDocument xml, string drive, string labelAs, string path)
+ {
+ XmlNode driveNode = xml.CreateElement("Drive");
+ XmlNode propertiesNode = xml.CreateElement("Properties");;
+
+ XmlAttribute clsidAttr = xml.CreateAttribute("clsid");
+ XmlAttribute nameAttr = xml.CreateAttribute("name");
+ XmlAttribute statusAttr = xml.CreateAttribute("status");
+ XmlAttribute imageAttr = xml.CreateAttribute("image");
+ XmlAttribute changedAttr = xml.CreateAttribute("changed");
+ XmlAttribute uidAttr = xml.CreateAttribute("uid");
+ XmlAttribute bypassErrorsAttr = xml.CreateAttribute("bypassErrors");
+
+ XmlAttribute actionPropAttr = xml.CreateAttribute("action");
+ XmlAttribute thisDrivePropAttr = xml.CreateAttribute("thisDrive");
+ XmlAttribute allDrivesPropAttr = xml.CreateAttribute("allDrives");
+ XmlAttribute userNamePropAttr = xml.CreateAttribute("userName");
+ XmlAttribute pathPropAttr = xml.CreateAttribute("path");
+ XmlAttribute labelPropAttr = xml.CreateAttribute("label");
+ XmlAttribute persistentPropAttr = xml.CreateAttribute("persistent");
+ XmlAttribute useLetterPropAttr = xml.CreateAttribute("useLetter");
+ XmlAttribute letterPropAttr = xml.CreateAttribute("letter");
+
+ clsidAttr.Value = DRIVE_CLSID;
+ nameAttr.Value = string.Format("{0}:", drive);
+ statusAttr.Value = string.Format("{0}:", drive);
+ imageAttr.Value = (1).ToString();
+ changedAttr.Value = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
+ uidAttr.Value = Guid.NewGuid().ToString("B");
+ bypassErrorsAttr.Value = (1).ToString();
+
+ actionPropAttr.Value = "R";
+ thisDrivePropAttr.Value = "NOCHANGE";
+ allDrivesPropAttr.Value = "NOCHANGE";
+ userNamePropAttr.Value = string.Empty;
+ pathPropAttr.Value = path;
+ labelPropAttr.Value = labelAs;
+ persistentPropAttr.Value = (1).ToString();
+ useLetterPropAttr.Value = (1).ToString();
+ letterPropAttr.Value = drive;
+
+ driveNode.Attributes.Append(clsidAttr);
+ driveNode.Attributes.Append(nameAttr);
+ driveNode.Attributes.Append(statusAttr);
+ driveNode.Attributes.Append(imageAttr);
+ driveNode.Attributes.Append(changedAttr);
+ driveNode.Attributes.Append(uidAttr);
+ driveNode.Attributes.Append(bypassErrorsAttr);
+
+ propertiesNode.Attributes.Append(actionPropAttr);
+ propertiesNode.Attributes.Append(thisDrivePropAttr);
+ propertiesNode.Attributes.Append(allDrivesPropAttr);
+ propertiesNode.Attributes.Append(userNamePropAttr);
+ propertiesNode.Attributes.Append(pathPropAttr);
+ propertiesNode.Attributes.Append(labelPropAttr);
+ propertiesNode.Attributes.Append(persistentPropAttr);
+ propertiesNode.Attributes.Append(useLetterPropAttr);
+ propertiesNode.Attributes.Append(letterPropAttr);
+
+ driveNode.AppendChild(propertiesNode);
+
+ return driveNode;
+ }
+
+ private XmlNode CreateFiltersNode(XmlDocument xml, Dictionary accounts)
+ {
+ XmlNode filtersNode = xml.CreateElement("Filters");
+
+ foreach (var pair in accounts)
+ {
+ XmlAttribute boolAttr = xml.CreateAttribute("bool");
+ XmlAttribute notAttr = xml.CreateAttribute("not");
+ XmlAttribute userContextAttr = xml.CreateAttribute("userContext");
+ XmlAttribute primaryGroupAttr = xml.CreateAttribute("primaryGroup");
+ XmlAttribute localGroupAttr = xml.CreateAttribute("localGroup");
+ XmlAttribute nameAttr = xml.CreateAttribute("name");
+ XmlAttribute sidAttr = xml.CreateAttribute("sid");
+
+ boolAttr.Value = "AND";
+ notAttr.Value = (0).ToString();
+ userContextAttr.Value = (1).ToString();
+ primaryGroupAttr.Value = (0).ToString();
+ localGroupAttr.Value = (0).ToString();
+
+ if (IsGroup(pair.Value))
+ {
+ XmlNode filterGroupNode = xml.CreateElement("FilterGroup");
+
+ nameAttr.Value = GetObjectTargetAccountName(pair.Value.AccountName, RootDomain);
+ sidAttr.Value = pair.Key;
+
+ filterGroupNode.Attributes.Append(boolAttr);
+ filterGroupNode.Attributes.Append(notAttr);
+ filterGroupNode.Attributes.Append(nameAttr);
+ filterGroupNode.Attributes.Append(sidAttr);
+ filterGroupNode.Attributes.Append(userContextAttr);
+ filterGroupNode.Attributes.Append(primaryGroupAttr);
+ filterGroupNode.Attributes.Append(localGroupAttr);
+
+ filtersNode.AppendChild(filterGroupNode);
+ }
+ else
+ {
+ XmlNode filterUserNode = xml.CreateElement("FilterUser");
+
+ nameAttr.Value = GetObjectTargetAccountName(pair.Value.AccountName, RootDomain);
+ sidAttr.Value = pair.Key;
+
+ filterUserNode.Attributes.Append(boolAttr);
+ filterUserNode.Attributes.Append(notAttr);
+ filterUserNode.Attributes.Append(nameAttr);
+ filterUserNode.Attributes.Append(sidAttr);
+
+ filtersNode.AppendChild(filterUserNode);
+ }
+ }
+
+ return filtersNode;
+ }
+
+ private MappedDrive[] GetDrivesFromXML(XmlDocument xml, ArrayList items)
+ {
+ XmlNodeList drives = xml.SelectNodes("./Drives/Drive");
+
+ foreach (XmlNode driveNode in drives)
+ {
+ XmlNode props = driveNode.ChildNodes[0];
+
+ MappedDrive item = new MappedDrive(props.Attributes["path"].Value,
+ props.Attributes["label"].Value,
+ props.Attributes["letter"].Value);
+ items.Add(item);
+ }
+
+ return (MappedDrive[])items.ToArray(typeof(MappedDrive));
+ }
+
+ private bool IsGroup(ExchangeAccount account)
+ {
+ return (account.AccountType == ExchangeAccountType.SecurityGroup || account.AccountType == ExchangeAccountType.DefaultSecurityGroup);
+ }
+
+ #endregion
+
+ #endregion
+
+ #region PowerShell integration
+
+ private static RunspaceConfiguration runspaceConfiguration = null;
+
+ internal virtual Runspace OpenRunspace()
+ {
+ HostedSolutionLog.LogStart("OpenRunspace");
+
+ if (runspaceConfiguration == null)
+ {
+ runspaceConfiguration = RunspaceConfiguration.Create();
+ }
+ Runspace runSpace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
+ //
+ runSpace.Open();
+ //
+ runSpace.SessionStateProxy.SetVariable("ConfirmPreference", "none");
+ HostedSolutionLog.LogEnd("OpenRunspace");
+ return runSpace;
+ }
+
+ internal void CloseRunspace(Runspace runspace)
+ {
+ try
+ {
+ if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened)
+ {
+ runspace.Close();
+ }
+ }
+ catch (Exception ex)
+ {
+ HostedSolutionLog.LogError("Runspace error", ex);
+ }
+ }
+
+ internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd)
+ {
+ return ExecuteShellCommand(runSpace, cmd, false);
+ }
+
+ internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController)
+ {
+ object[] errors;
+ return ExecuteShellCommand(runSpace, cmd, useDomainController, out errors);
+ }
+
+ internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, out object[] errors)
+ {
+ return ExecuteShellCommand(runSpace, cmd, true, out errors);
+ }
+
+ internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController, out object[] errors)
+ {
+ HostedSolutionLog.LogStart("ExecuteShellCommand");
+ List