写保护 USB 驱动器上出现 ShellExecuteEx 错误?

发布于 2024-11-19 02:06:09 字数 4243 浏览 1 评论 0 原文

我正在尝试在写保护的 USB 驱动器上测试应用程序,我想使用 ShellExecuteEx API(我需要使用此 API 调用,因为我需要 lpVerb := "runas")调用来执行第二个程序,但我通过 ShellExecuteEx 调用不断收到“写保护错误”。我似乎无法弄清楚正在尝试写入驱动器的内容,我没有写入驱动器的代码,我什至使用了最新的 Microsoft 标准用户分析器应用程序验证程序尝试验证尝试写入驱动器的内容,但没有成功。这是我不断收到的错误:

[ Write Protect Error ]

Write Protect Error

Nothing in the以下代码正在尝试写入此驱动器,ShellExecuteEx API 调用是否是执行我尝试执行的操作的错误方法?如果没有,我怎样才能避免弹出这个错误。任何帮助将不胜感激。

[ WP-ON.reg ]

REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies]
"WriteProtect"=dword:00000001

[ WP-OFF.reg ]

REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies]
"WriteProtect"=dword:00000000

注意: 每次注册表完成后,您都必须弹出并重新插入设备。已更新。

[project1.dpr]

program project1;

{.$APPTYPE CONSOLE}

uses
  Windows, SysUtils;

begin
  Windows.MessageBox(Windows.GetActiveWindow(),
    PChar('Hello World!'), PChar('project1'), MB_OK);
end.

[launch.manifest]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity processorArchitecture="x86" version="2.0.1.0" name="eyeClaxton.asInvoker.Launch" type="win32" />
<description>asInvoker Launch</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="x86" />
    </dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
        <requestedPrivileges>
            <requestedExecutionLevel level="asInvoker" uiAccess="false" />
        </requestedPrivileges>
    </security>
</trustInfo>
</assembly>

[launch.dpr]

program launch;

uses
  Windows, ShellAPI;

{$R 'MANIFEST.RES'}

procedure ShellEx(const theFilename, theParams: string);

  function RunAsAdmin(): Boolean;
  var
    OSVerInfo: TOSVersionInfo;
  begin
    OSVerInfo.dwOSVersionInfoSize := System.SizeOf(OSVerInfo);
    Result := (Windows.GetVersionEx(OSVerInfo)) and (OSVerInfo.dwMajorVersion > 5);
  end;

var
  ShellExInfo: TShellExecuteInfo;
  Directory: array[0..MAX_PATH] of Char;
begin
  Windows.ZeroMemory(@ShellExInfo, System.SizeOf(ShellExInfo));
  ShellExInfo.cbSize := System.SizeOf(TShellExecuteInfo);
  ShellExInfo.Wnd := Windows.GetActiveWindow();
  ShellExInfo.nShow := SW_SHOWNORMAL;
  ShellExInfo.fMask := SEE_MASK_FLAG_NO_UI;

  if (RunAsAdmin()) then  // If OS is greater than Windows XP
    ShellExInfo.lpVerb := PChar('runas');

  Windows.ZeroMemory(@Directory, System.SizeOf(Directory));
  Windows.GetCurrentDirectory(SizeOf(Directory), Directory);
  ShellExInfo.lpDirectory := PChar(string(Directory));
  ShellExInfo.lpFile := PChar('"' + string(Directory) + '\' + theFilename + '"');
  ShellExInfo.lpParameters := PChar('"' + theParams + '"');

  //
  // ShellExecuteEx causes a "Write Protect" error to popup.
  //
  if (not ShellAPI.ShellExecuteEx(@ShellExInfo)) then
    Windows.MessageBox(Windows.GetActiveWindow(),
      PChar('File ' + ShellExInfo.lpFile + ' not found!'),
      PChar('asInvoker Launch'), MB_OK or MB_ICONERROR);
end;

begin
  ShellEx('project1.exe', System.ParamStr(1));

end.

I'm trying to test an application on a write protected USB drive, I want to use the ShellExecuteEx API (I need to use this API call because I need the lpVerb := "runas") call to execute a second program, but I keep getting a "Write Protect Error" with the ShellExecuteEx call. I can’t seem to figure out what’s trying to write to the drive, I have no code that is writing to the drive and I even used the latest Microsoft Standard User Analyzer and Application Verifier to try and verify what is trying to write to the drive with no success. Here is the error I keep getting:

[ Write Protect Error ]

Write Protect Error

Nothing in the following code is trying to write to this drive, is the ShellExecuteEx API call the wrong way to do what I'm trying to do? If not, how can I get this error from popping up. Any help would be greatly appreciated.

[ WP-ON.reg ]

REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies]
"WriteProtect"=dword:00000001

[ WP-OFF.reg ]

REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies]
"WriteProtect"=dword:00000000

NOTE: You must eject and reinsert the device each time the registry has been updated.

[ project1.dpr ]

program project1;

{.$APPTYPE CONSOLE}

uses
  Windows, SysUtils;

begin
  Windows.MessageBox(Windows.GetActiveWindow(),
    PChar('Hello World!'), PChar('project1'), MB_OK);
end.

[ launch.manifest ]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity processorArchitecture="x86" version="2.0.1.0" name="eyeClaxton.asInvoker.Launch" type="win32" />
<description>asInvoker Launch</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="x86" />
    </dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
        <requestedPrivileges>
            <requestedExecutionLevel level="asInvoker" uiAccess="false" />
        </requestedPrivileges>
    </security>
</trustInfo>
</assembly>

[ launch.dpr ]

program launch;

uses
  Windows, ShellAPI;

{$R 'MANIFEST.RES'}

procedure ShellEx(const theFilename, theParams: string);

  function RunAsAdmin(): Boolean;
  var
    OSVerInfo: TOSVersionInfo;
  begin
    OSVerInfo.dwOSVersionInfoSize := System.SizeOf(OSVerInfo);
    Result := (Windows.GetVersionEx(OSVerInfo)) and (OSVerInfo.dwMajorVersion > 5);
  end;

var
  ShellExInfo: TShellExecuteInfo;
  Directory: array[0..MAX_PATH] of Char;
begin
  Windows.ZeroMemory(@ShellExInfo, System.SizeOf(ShellExInfo));
  ShellExInfo.cbSize := System.SizeOf(TShellExecuteInfo);
  ShellExInfo.Wnd := Windows.GetActiveWindow();
  ShellExInfo.nShow := SW_SHOWNORMAL;
  ShellExInfo.fMask := SEE_MASK_FLAG_NO_UI;

  if (RunAsAdmin()) then  // If OS is greater than Windows XP
    ShellExInfo.lpVerb := PChar('runas');

  Windows.ZeroMemory(@Directory, System.SizeOf(Directory));
  Windows.GetCurrentDirectory(SizeOf(Directory), Directory);
  ShellExInfo.lpDirectory := PChar(string(Directory));
  ShellExInfo.lpFile := PChar('"' + string(Directory) + '\' + theFilename + '"');
  ShellExInfo.lpParameters := PChar('"' + theParams + '"');

  //
  // ShellExecuteEx causes a "Write Protect" error to popup.
  //
  if (not ShellAPI.ShellExecuteEx(@ShellExInfo)) then
    Windows.MessageBox(Windows.GetActiveWindow(),
      PChar('File ' + ShellExInfo.lpFile + ' not found!'),
      PChar('asInvoker Launch'), MB_OK or MB_ICONERROR);
end;

begin
  ShellEx('project1.exe', System.ParamStr(1));

end.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

忘东忘西忘不掉你 2024-11-26 02:06:09

这个问题来自于 ShellExecuteEx 是一个相当复杂的过程,启动一个新的后台线程,然后调用大量 COM 内容。出于安全原因,应该在某处启用写入。

您可以尝试禁用UAC。但并不是一个好的解决方案。

当您查看以编程方式提升进程权限的相应解决方案时(有线清单是另一种静态提升方式),您只能找到两个 在此答案中引用

  • 使用 ShellExecuteEx 和 runas 参数;
  • 使用神奇的“Elevation:Administrator!new:”前缀创建一个提升的 COM 对象。

值得阅读整篇“Vista UAC:权威指南”文章了解 ShellExecuteEx 的工作原理。

所以这是我的答案:由于您需要运行具有提升权限的进程,并且没有现有的“CreateProcessElevated”API,只有良好的大ShellExecute,所以最简单的方法是使用清单文件第二个可执行文件。

如果您希望 project1.exe 文件以“AsInvoker”权限运行,但有意仅以管理员权限运行,则有两种可能性:

  • 使​​用外部 .manifest 文件,并且不要将该文件嵌入到exe 作为一种资源 - 然后用带有“AsInvoker”或“requireAdministrator”参数的一个版本替换 .manifest 内容 - 但在只读媒体上很困难,不是吗:;
  • 使用外部第三个可执行文件(我们将其称为 Elevate.exe),其中包含具有“requireAdministrator”级别的清单,它将启动第二个可执行文件。您可以提供 exe 和命令行作为此 Elevate.exe 程序的参数。

The issue comes from the fact ShellExecuteEx is quite a complex process, starting a new background thread, then calling a lot of COM stuff. Write should be enabled somewhere, for security reasons.

You may try to disable the UAC. But not a good solution.

When you look at the corresponding solutions to elevate a process rights programatically (wired manifest is another static way of elevation), you can only find the two quoted in this SO answer:

  • Use ShellExecuteEx with runas parameter;
  • Create an elevated COM Object with the magic "Elevation:Administrator!new:" prefix.

It's worth reading the whole "Vista UAC: The Definitive Guide" article to understand how ShellExecuteEx works.

So here is my answer: since you need to run a process with elevated rights, and there is no existing "CreateProcessElevated" API but only the good big ShellExecute, the most easy is to use a manifest file for the 2nd executable.

If you want your project1.exe file to run with "AsInvoker" rights, but only with administrator rights on purpose, you have two possibilities:

  • Use an external .manifest file, and do not embed the file to the exe as a resource - then replace the .manifest content with one version with either "AsInvoker" or "requireAdministrator" parameter - but difficult on a read-only media, isn't it :;
  • Use an external 3nd executable (we'll call it Elevate.exe), containing a manifest with the "requireAdministrator" level, which will launch the 2nd executable. You could provide the exe and command line as a parameter to this Elevate.exe program.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文