I'm using C# for WinForms app in VS2010 and I needed to create a directory in which the path was too large for the .NET methods (248 char limit, I believe) and ran across suggestions from google to use the Unicode Win32 CreateDirectory(). I had initially tried calling it using Unicode and passed parameters but after several failed attempts, I've reduced the code and am using EXACTLY the code found here:
http://www.pinvoke.net/default.aspx/Structures/SECURITY_ATTRIBUTES.html
I am still getting the same error:
System.AccessViolationException was caught Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Admittedly, I don't know anything about calling the Win32 functions, I'm really just pulling what I can find online and trying to learn. Can anyone tell me what I'm doing wrong? Removing non-essential code for the question, I have:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Text;
namespace RFCGenerator
{
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
public class RFC
{
[DllImport("kernel32.dll")]
static extern bool CreateDirectory(string lpPathName, SECURITY_ATTRIBUTES lpSecurityAttributes);
protected void CopyDirectory(Uri Source, Uri Destination)
{
SECURITY_ATTRIBUTES lpSecurityAttributes = new SECURITY_ATTRIBUTES();
DirectorySecurity security = new DirectorySecurity();
lpSecurityAttributes.nLength = Marshal.SizeOf(lpSecurityAttributes);
byte[] src = security.GetSecurityDescriptorBinaryForm();
IntPtr dest = Marshal.AllocHGlobal(src.Length);
Marshal.Copy(src, 0, dest, src.Length);
lpSecurityAttributes.lpSecurityDescriptor = dest;
string path = @"C:\Test";
CreateDirectory(path, lpSecurityAttributes);
}
}
}
UPDATE: using Hans' suggestion, I did get this to work locally. However, when I attempt to create a directory using a UNC address, such as passing in:
path = @"\\mydomain.com\foo\bar\newfolder"
I now get:
System.ComponentModel.Win32Exception was caught Message=The filename, directory name, or volume label syntax is incorrect
I have verified that \\mydomain.com\foo\bar\ does exist.
SOLUTION:
Using Hans' code and a minor modification to check if it's UNC path (reference: http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx, under "Maximum Path Length Limitation"):
string UnicodePath = (path.StartsWith(@"\\")) ? @"\\?\UNC\" + (path.Remove(0, 2)) : @"\\?\" + path;
if (!CreateDirectory(UnicodePath, IntPtr.Zero))
throw new System.ComponentModel.Win32Exception();