Is this PInvoke code correct and reliable?

◇◆丶佛笑我妖孽 提交于 2019-11-29 03:05:05

Calling the native method will never raise an exception. If the file deletion fails, for whatever reason, the call to DeleteFile returns false.

Your P/Invoke code is good. You are correctly using Unicode characters, setting SetLastError to true and the parameter marshalling is correct. To check for errors look for the value of the boolean return from DeleteFile. If it is false (i.e. the call failed) then call Marshal.GetLastWin32Error to find out the Win32 error code.

The most obvious causes for the function to fail are:

  1. The file does not exist.
  2. The alternate stream is not present.
  3. The process does not have sufficient rights to delete the alternate stream.

For 1 and 2 an error code of ERROR_FILE_NOT_FOUND will be returned. For 3 you will be given an error code of ERROR_ACCESS_DENIED.

I made a small refinement to the code. You can now just pass your startup path to the UnblockPath() function and it will automatically unblock all of the files and sub directory files for your executable. It could be refined further to only search for .exe, .dll, etc.

[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteFile(string name);

public static void UnblockPath(string path)
{
    string[] files = System.IO.Directory.GetFiles(path);
    string[] dirs = System.IO.Directory.GetDirectories(path);

    foreach (string file in files)
    {
        UnblockFile(file);
    }

    foreach (string dir in dirs)
    {
        UnblockPath(dir);
    }

}

public static bool UnblockFile(string fileName)
{
    return DeleteFile(fileName + ":Zone.Identifier");
}
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;

internal class Zone
{
    public static void WriteAlternateStream(string path, string text)
    {
        const int GENERIC_WRITE = 1073741824;
        const int FILE_SHARE_WRITE = 2;
        const int OPEN_ALWAYS = 4;
        var stream = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_ALWAYS, 0, IntPtr.Zero);
        using (FileStream fs = new FileStream(stream, FileAccess.Write))
        {
            using (StreamWriter sw = new StreamWriter(fs))
            {
                sw.Write(text);
            }
        }
    }
    public static void Id()
    {
        var x = Application.ExecutablePath + ":Zone.Identifier";
        WriteAlternateStream(x, "[ZoneTransfer]\r\nZoneId=3");
    }
    # region Imports
    [DllImport("kernel32.dll", EntryPoint = "CreateFileW")]
    public static extern System.IntPtr CreateFileW(
        [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName,
        uint dwDesiredAccess,
        uint dwShareMode,
        [InAttribute()] IntPtr lpSecurityAttributes,
        uint dwCreationDisposition,
        uint dwFlagsAndAttributes,
        [InAttribute()] IntPtr hTemplateFile
    );
    #endregion
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!