• ベストアンサー

administratorのみ書き込み可能なフォルダにプログラムを通じて他のユーザーでファイル書き込みを実行したい

administratorの権限がないユーザーがadministratorのみ書き込み可能なフォルダにプログラムを通じて書き込みできるシステムを考えています。 アイデアとして作成したプログラムにadministratorで実行することができればうまくいくのではと思い、OSのサービス機能を調査しているところです。 もし経験があるかたがおりましたらお教えください。 またWindows2000でプログラムをサービスに登録する方法も探しています。 宜しくお願いします。 OS:Windows2000+SP2 開発プログラム:VB6.0+SP5

質問者が選んだベストアンサー

  • ベストアンサー
  • haporun
  • ベストアンサー率40% (230/562)
回答No.5

できました! STARTUPINFO構造体の定義を Public Type STARTUPINFO cb As Long lpReserved As Long lpDesktop As Long lpTitle As Long dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As Long End Type に変えてください。 イミディエイトウィンドウで ?createprocesswithlogon("名前", "ドメイン", "パスワード","c:\winnt\notepad.exe", vbnullstring, "c:\", 0, 0) などと入力してEnterをおすと、ユーザー名などが適切な場合、メモ帳がちゃんと起動します。 この関数の注意は、必ず実行時のディレクトリを指定しなければならないということです。 それ以外は、ドメインが省略されていたりしても、ユーザー名とパスワードさえしっかりしていれば、起動できるみたいです。 また、アプリケーション名はフルパスで指定してください。 はぁ、良かった。 原因は、スタートアップ構造体内の文字列でした。 これもUNICODEが原因です。 えっ? Cで? CはUNICODEも普通に扱えるので簡単に・・・、といいたいところですが、VC++にはどうもCreateProcessWithLogonW関数が定義されていないので、自分で探さなきゃならんみたいですね。 Win32アプリケーションを選択して、単純なアプリケーションを自動で生成。 #include "stdafx.h" int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ HMODULE hMod = GetModuleHandle("advapi32"); STARTUPINFOW si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); //↓ぐちゃぐちゃですが合ってます BOOL (__stdcall *CreateProcessWithLogonW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPCWSTR, LPWSTR, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION) = (BOOL (__stdcall *)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPCWSTR, LPWSTR, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION))GetProcAddress(hMod, "CreateProcessWithLogonW"); if(!CreateProcessWithLogonW){ MessageBox(0, "CreateProcessWithLogonW is not found", 0, 0); } CreateProcessWithLogonW( L"名前", L"ドメイン", L"パスワード", 0, L"c:\\winnt\\notepad.exe", NULL, 0, NULL, NULL, &si, &pi ); FreeLibrary(hMod); return 0; } 動作確認済みです。

その他の回答 (5)

  • haporun
  • ベストアンサー率40% (230/562)
回答No.6

あっ、追記です。 CreateProcessもWithLogonWもプロセスハンドルとスレッドハンドルを生成します。 これを開放せずに使いまくってると、リソースがつきでしまいます。 Public Declare Function CloseHandle Lib "kernel32" Alias "CloseHandle" (ByVal hObject As Long) As Long をモジュールの一番上に追加して、 End Functionの直前の行に CloseHandle PI.hThread CloseHandle PI.hProcess を追加してください。 Cのほうも使うんだったら、同様に!

mar0325
質問者

お礼

今回の件では大変お世話になりました。 とてもよい刺激になり、開発の励みになりました。 今後も宜しくお願いします

mar0325
質問者

補足

ありがとうございます。 引数で用いられているcur_dirですが、これはVBで予約語になっているようです。 この変数名を変えて実行しましたらうまくいきました。

  • haporun
  • ベストアンサー率40% (230/562)
回答No.4

CreateProcessなら、advai32じゃなくてkernel32の中にはいっています。 Lib "advapi32" をLib "kernel32" に書き換えるとCreateProcess見つかるでしょうが、多分参考になりません。 CreateProcessWithLogonWにはUNICODE版しか用意されていないので、VBから操作するのは面倒くさいからです。 私も強制終了の原因を調べているところです。 ちなみに、このコードを貼り付けて、モジュール内定義のCreateProcessWithLogonを呼び出したら、強制終了しましたか? もしかしたら、私のローカルエラーかもしれませんから。 # セキュリティポリシーに、別ユーザーでプロセスを実行するという権限が割り当てられてなかったら、だめだったような・・・。

mar0325
質問者

お礼

ありがとうございます。 haporunさんのプログラムをこちらで実行させていただきました。 メモリの読み込みエラーがでてしまいます。 参考までにCで作成したこの関数を公開していただけないでしょうか? 宜しくお願いします

  • haporun
  • ベストアンサー率40% (230/562)
回答No.3

ありゃ? 強制終了してしまいました。 原因不明・・・。 原因解明に努めてみます。 基本的にはこれでいいはずなんですが。

mar0325
質問者

お礼

ありがととうございます。 無理を言ってすみませんでした。 実は、私もCreateProcessを参考に開発したのですがうまくいきませんでした。 dll内に関数が見つからないというエラーで現在、ストップしています。

  • haporun
  • ベストアンサー率40% (230/562)
回答No.2

標準モジュールを作って Public Const SW_NORMAL = 1 Public Type STARTUPINFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As Long End Type Public Type PROCESS_INFORMATION hProcess As Long hThread As Long dwProcessId As Long dwThreadId As Long End Type Public Declare Function CreateProcessWithLogonW Lib "advapi32" ( _ lpUserName As Byte, _ lpDomain As Byte, _ lpPassword As Byte, _ ByVal dwLogonFlags As Long, _ lpApplicationName As Byte, _ lpCommandLine As Byte, _ ByVal dwCreationFlags As Long, _ ByVal lpEnvironment As Long, _ lpCurrentDirectory As Byte, _ lpStartupInfo As STARTUPINFO, _ lpProcessInformation As PROCESS_INFORMATION _ ) As Long Public Function CreateProcessWithLogon( _ Username As String, _ Domain As String, _ Pasword As String, _ Appname As String, _ Cmdline As String, _ CurDir As String, _ Optional ByVal LogonFlag As Long, _ Optional ByVal CreateFlag As Long = &H20 _ ) As Long Dim Usr() As Byte, Dom() As Byte, Pas() As Byte Dim Ap() As Byte, Cmd() As Byte, Cur() As Byte Dim SI As STARTUPINFO, PI As PROCESS_INFORMATION SI.cb = Len(SI) Usr = Username + vbNullChar: Dom = Domain + vbNullChar: Pas = Pasword + vbNullChar Ap = Appname + vbNullChar: Cmd = Cmdline + vbNullChar: Cur = CurDir + vbNullChar CreateProcessWithLogon = CreateProcessWithLogonW( _ Usr(0), _ Dom(0), _ Pas(0), _ LogonFlag, _ Ap(0), _ Cmd(0), _ CreateFlag, _ ByVal 0, _ Cur(0), _ SI, _ PI _ ) End Function これでどうでしょう。

  • haporun
  • ベストアンサー率40% (230/562)
回答No.1

CreateProcessWithLogonW関数を使いませう。 これである特定のプログラムを起動するプログラムを作って、そのプログラムが目的のフォルダに対して操作をします。 注意 ○ この関数はパスワードを引数として入れますが、リテラル値でパスワードを書かないように。 なにか暗号化処置を施すべきです。 ○ この関数は、たしかAPILOADERに載ってません。 ○ この関数はUNICODE版のみなので、文字列をByRef x As Byteで宣言するように。 ○ この関数で起動したプログラムが、他の任意のプログラムを起動できないように注意。

参考URL:
http://www.microsoft.com/JAPAN/developer/library/jpwinpf/_win32_createprocesswithlogonw.htm
mar0325
質問者

補足

ありがとうございます。今、参考URLを見ました。 実はAPIについては素人で,この関数の使い方を教えてください。 VBのサンプルプログラムをいただけると幸いです。 宜しくお願いします。