ΠΡΠ»ΠΈ ΡΠΏΠΈΡΠΎΠΊ Π°Π²ΡΠΎΡΠΈΠ·ΠΎΠ²Π°Π½Π½ΡΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΈΠ·Π²Π΅ΡΡΠ΅Π½ Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π·Π°ΠΏΡΡΠΊΠ° ΠΏΡΠΎΡΠ΅ΡΡΠ°, ΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΡ (custom) ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ IAccessControl, ΠΊΠΎΡΠΎΡΠ°Ρ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠ΄Π° ΠΏΡΠΎΠ²Π΅ΡΠΊΡ Π΄ΠΎΡΡΡΠΏΠ° Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π² ΡΠ²ΠΎΠ΅ΠΉ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΌΠ΅ΡΠΎΠ΄Π° IsAccessAllowed. ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΡΠ°ΠΌΠ° COM ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΌΠ΅ΡΠΎΠ΄ IsAccessAllowed, ΡΠΎ ΡΠ°ΠΊΠ°Ρ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½Π°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΌΠΎΠ³Π»Π° Π±Ρ Π±Π΅Π·ΠΎΡΠΈΠ±ΠΎΡΠ½ΠΎ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ E_NOTIMPL Π΄Π»Ρ Π²ΡΠ΅Ρ Π΄ΡΡΠ³ΠΈΡ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² IAccessControl. ΠΠΈΠΆΠ΅ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π° ΠΏΡΠΎΡΡΠ°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ IAccessControl, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡΠ°Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ ΠΎΠ±ΡΠ΅ΠΊΡΠ°ΠΌ ΠΏΡΠΎΡΠ΅ΡΡΠ° ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΠΌ Ρ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠΌ "x" Π² ΠΈΠΌΠ΅Π½Π°Ρ ΡΠ²ΠΎΠΈΡ ΡΡΠ΅ΡΠ½ΡΡ Π·Π°ΠΏΠΈΡΠ΅ΠΉ:
class XOnly : public IAccessControl {
// Unknown methods
// ΠΌΠ΅ΡΠΎΠ΄Ρ IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {
if (riid == IID_IAccessControl || riid == IID_IUnknown)
*ppv = static_cast<IAccessControl*>(this);
else
return (*ppv = 0), E_NOINTERFACE;
((IUnknown*)*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) AddRef(void) { return 2; }
STDMETHODIMP_(ULONG) Release(void) { return 1; }
// IAccessControl methods
// ΠΌΠ΅ΡΠΎΠ΄Ρ IAccessControl
STDMETHODIMP GrantAccessRights(ACTRL_ACCESSW *)
{ return E_NOTIMPL; }
STDMETHODIMP SetAccessRights(ACTRL_ACCESSW *)
{ return E_NOTIMPL; }
STDMETHODIMP SetOwner(PTRUSTEEW, PTRUSTEEW)
{ return E_NOTIMPL; }
STDMETHODIMP RevokeAccessRights(LPWSTR, ULONG, TRUSTEEW[])
{ return E_NOTIMPL; }
STDMETHODIMP GetAllAccessRights(LPWSTR, PACTRL_ACCESSW_ALLOCATE_ALL_NODES *,
PTRUSTEEW *, PTRUSTEEW *)
{ return E_NOTIMPL; }
// this is the only IAccessControl method called by COM
// ΡΡΠΎ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ ΠΌΠ΅ΡΠΎΠ΄ IAccessControl, Π²ΡΠ·Π²Π°Π½Π½ΡΠΉ COM
STDMETHODIMP IsAccessAllowed(
PTRUSTEEW pTrustee,
LPWSTR lpProperty,
ACCESS_RIGHTS AccessRights,
BOOL *pbIsAllowed)
{
// verify that trustee contains a string
// ΡΠ΄ΠΎΡΡΠΎΠ²Π΅ΡΡΠ΅ΠΌΡΡ, ΡΡΠΎ ΠΎΠΏΠ΅ΠΊΡΠ½ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΡΡΠΎΠΊΡ
if (pTrustee == 0 || pTrustee->TrusteeForm != TRUSTEE_IS_NAME)
return E_UNEXPECTED;
// look for X or x and grant/deny based on presence
// ΠΈΡΠ΅ΠΌ "X" ΠΈΠ»ΠΈ "x" ΠΈ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ Π΅Π³ΠΎ Π½Π°Π»ΠΈΡΠΈΡ
// ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅ΠΌ ΠΈΠ»ΠΈ Π·Π°ΠΏΡΠ΅ΡΠ°Π΅ΠΌ
*pbIsAllowed = wcsstr(pTrustee->ptstrName, L"x") != 0 ||
wcsstr(pTrustee->ptstrName, L"X") != 0;
return S_OK;
}
}
ΠΡΠ»ΠΈ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π²ΡΡΠ΅ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠ»Π°ΡΡΠ° C++ Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°Π½ c CoInitializeSecurity:
XOnly xo;
// declare an instance of the C++ class
// ΠΎΠ±ΡΡΠ²Π»ΡΠ΅ΠΌ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ ΠΊΠ»Π°ΡΡΠ° C++
hr = CoInitializeSecurity(static_cast<IAccessControl*>(&xo),
β1, 0, 0, RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IDENTIFY, 0,
EOAC_ACCESS_CONTROL,
// use IAccessControl
// ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ IAccessControl
0);
assert(SUCCEEDED(hr));
ΡΠΎ ΠΎΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ, Π½Π΅ ΠΈΠΌΠ΅ΡΡΠΈΡ "x" Π² ΠΈΠΌΠ΅Π½Π°Ρ ΡΠ²ΠΎΠΈΡ ΡΡΠ΅ΡΠ½ΡΡ Π·Π°ΠΏΠΈΡΠ΅ΠΉ, Π½ΠΈΠΊΠ°ΠΊΠΈΠ΅ ΠΏΠΎΡΡΡΠΏΠ°ΡΡΠΈΠ΅ Π²ΡΠ·ΠΎΠ²Ρ Π½Π΅ Π±ΡΠ΄ΡΡ ΠΏΡΠΈΠ½ΡΡΡ. ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΈΠΌΡ ΠΎΠΏΠ΅ΠΊΡΠ½Π° ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΏΡΠ΅ΡΠΈΠΊΡΠ° ΠΈΠΌΡ Π΄ΠΎΠΌΠ΅Π½Π°, ΡΡΠΎΡ ΠΏΡΠΎΡΡΠΎΠΉ ΡΠ΅ΡΡ ΡΠ°ΠΊΠΆΠ΅ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²ΠΈΡ Π΄ΠΎΡΡΡΠΏ ΡΡΠ΅ΡΠ½ΡΠΌ Π·Π°ΠΏΠΈΡΡΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ, ΠΏΡΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°ΡΠΈΡ ΠΊ Π΄ΠΎΠΌΠ΅Π½Π°ΠΌ, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΠΌ "x" Π² ΡΠ²ΠΎΠΈΡ ΠΈΠΌΠ΅Π½Π°Ρ . Π₯ΠΎΡΡ ΡΡΠΎΡ ΡΠ΅ΡΡ Π΄ΠΎΡΡΡΠΏΠ° Π²ΡΡΠ΄ Π»ΠΈ Π±ΡΠ΄Π΅Ρ ΡΠ»ΠΈΡΠΊΠΎΠΌ ΠΏΠΎΠ»Π΅Π·Π΅Π½, ΠΎΠ½ Π΄Π΅ΠΌΠΎΠ½ΡΡΡΠΈΡΡΠ΅Ρ ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ° IAccessControl Ρ CoInitializeSecurity.
Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΌΠ°ΡΠΊΠ΅ΡΠ°ΠΌΠΈ
ΠΠΎΠ΄ Windows NT ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΏΡΠΎΡΠ΅ΡΡ ΠΈΠΌΠ΅Π΅Ρ ΠΌΠ°ΡΠΊΠ΅Ρ Π΄ΠΎΡΡΡΠΏΠ° (access token), ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΡΡΠΈΠΉ ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΡ ΠΏΡΠΈΠ½ΡΠΈΠΏΠ°Π»Π° Π·Π°ΡΠΈΡΡ. ΠΡΠΎΡ ΠΌΠ°ΡΠΊΠ΅Ρ Π΄ΠΎΡΡΡΠΏΠ° ΡΠΎΠ·Π΄Π°Π΅ΡΡΡ Π²ΠΎ Π²ΡΠ΅ΠΌΡ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΏΡΠΎΡΠ΅ΡΡΠ° ΠΈ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ Π²ΠΈΠ΄Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ ΠΎ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅, Π² ΡΠΎΠΌ ΡΠΈΡΠ»Π΅ Π΅Π³ΠΎ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ Π·Π°ΡΠΈΡΡ NT (SID), ΡΠΏΠΈΡΠΎΠΊ Π³ΡΡΠΏΠΏ, ΠΊ ΠΊΠΎΡΠΎΡΡΠΌ ΠΏΡΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, Π° ΡΠ°ΠΊΠΆΠ΅ ΡΠΏΠΈΡΠΎΠΊ ΠΏΡΠΈΠ²ΠΈΠ»Π΅Π³ΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΠΌΠΈ ΠΎΠ½ ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΠΎΠΆΠ΅Ρ Π»ΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΏΡΠ΅ΠΊΡΠ°ΡΠ°ΡΡ ΡΠ°Π±ΠΎΡΡ ΡΠΈΡΡΠ΅ΠΌΡ, ΠΌΠΎΠΆΠ΅Ρ Π»ΠΈ ΠΎΠ½ ΠΌΠ΅Π½ΡΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΡ ΡΠ°ΡΠΎΠ²). ΠΠΎΠ³Π΄Π° ΠΏΡΠΎΡΠ΅ΡΡ ΠΏΡΡΠ°Π΅ΡΡΡ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ ΡΠ΅ΡΡΡΡΠ°ΠΌ ΡΠ΄ΡΠ° Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΊ ΡΠ°ΠΉΠ»Π°ΠΌ, ΠΊΠ»ΡΡΠ°ΠΌ ΡΠ΅Π΅ΡΡΡΠ°, ΡΠ΅ΠΌΠ°ΡΠΎΡΠ°ΠΌ), ΠΊΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΡΠΉ ΠΌΠΎΠ½ΠΈΡΠΎΡ Π·Π°ΡΠΈΡΡ NT (SRM β Security Reference Monitor) ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΠΌΠ°ΡΠΊΠ΅Ρ Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅ΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ Π² ΡΠ΅Π»ΡΡ Π°ΡΠ΄ΠΈΡΠ° (ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΡ Π΄Π΅ΠΉΡΡΠ²ΠΈΠΉ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ ΠΏΡΡΠ΅ΠΌ Π·Π°ΠΏΠΈΡΠΈ Π² ΠΆΡΡΠ½Π°Π» Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ Π²ΡΠ±ΡΠ°Π½Π½ΡΡ ΡΠΈΠΏΠΎΠ² ΡΠΎΠ±ΡΡΠΈΠΉ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ) ΠΈ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ Π΄ΠΎΡΡΡΠΏΠ°.
ΠΠΎΠ³Π΄Π° Π² ΠΏΡΠΎΡΠ΅ΡΡ ΠΏΠΎΡΡΡΠΏΠ°Π΅Ρ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ± ORPC-Π·Π°ΠΏΡΠΎΡΠ΅, COM ΠΎΡΠ³Π°Π½ΠΈΠ·ΡΠ΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π²ΡΠ·ΠΎΠ²Π° ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠ΅Π³ΠΎ ΠΌΠ΅ΡΠΎΠ΄Π° ΠΈΠ»ΠΈ Π² RPC-ΠΏΠΎΡΠΎΠΊΠ΅ (Π² ΡΠ»ΡΡΠ°Π΅ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², ΡΠ°ΡΠΏΠΎΠ»ΠΎΠΆΠ΅Π½Π½ΡΡ Π² ΠΠ’Π), ΠΈΠ»ΠΈ Π² ΠΏΠΎΡΠΎΠΊΠ΅, ΡΠΎΠ·Π΄Π°Π½Π½ΠΎΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΌ (Π² ΡΠ»ΡΡΠ°Π΅ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ², ΡΠ°ΡΠΏΠΎΠ»ΠΎΠΆΠ΅Π½Π½ΡΡ Π² STA). Π Π»ΡΠ±ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΠΌΠ΅ΡΠΎΠ΄ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΌΠ°ΡΠΊΠ΅ΡΠ° Π΄ΠΎΡΡΡΠΏΠ°, ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠ΅Π³ΠΎ Π΄Π°Π½Π½ΠΎΠΌΡ ΠΏΡΠΎΡΠ΅ΡΡΡ. Π ΡΠ΅Π»ΠΎΠΌ ΡΡΠΎΠ³ΠΎ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΡΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΏΡΠΎΠ³Π½ΠΎΠ·ΠΈΡΠΎΠ²Π°ΡΡ, ΠΊΠ°ΠΊΠΈΠ΅ ΠΏΡΠΈΠ²ΠΈΠ»Π΅Π³ΠΈΠΈ ΠΈ ΠΏΡΠ°Π²Π° Π±ΡΠ΄ΡΡ ΠΈΠΌΠ΅ΡΡ ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΡ, Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎ ΠΎΡ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊΠΎΠΉ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΎΡΡΡΠ΅ΡΡΠ²Π»ΡΠ΅Ρ Π·Π°ΠΏΡΠΎΡ. Π ΡΠΎ ΠΆΠ΅ Π²ΡΠ΅ΠΌΡ ΠΈΠ½ΠΎΠ³Π΄Π° Π±ΡΠ²Π°Π΅Ρ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, ΡΡΠΎΠ±Ρ ΠΌΠ΅ΡΠΎΠ΄ Π²ΡΠΏΠΎΠ»Π½ΡΠ»ΡΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΡΠ°Π² Π΄ΠΎΡΡΡΠΏΠ° ΠΊΠ»ΠΈΠ΅Π½ΡΠ°, Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅Π³ΠΎ ΠΌΠ΅ΡΠΎΠ΄; ΡΡΠΎΠ±Ρ ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ Π»ΠΈΠ±ΠΎ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΡΡ, Π»ΠΈΠ±ΠΎ ΡΡΠΈΠ»ΠΈΡΡ ΠΎΠ±ΡΡΠ½ΡΠ΅ ΠΏΡΠ°Π²Π° ΠΈ ΠΏΡΠΈΠ²ΠΈΠ»Π΅Π³ΠΈΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ°. ΠΠ»Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΈ ΡΠ°ΠΊΠΎΠ³ΠΎ ΡΡΠΈΠ»Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π² Windows NT Π΄ΠΎΠΏΡΡΠΊΠ°Π΅ΡΡΡ ΠΏΡΠΈΡΠ²ΠΎΠ΅Π½ΠΈΠ΅ ΠΌΠ°ΡΠΊΠ΅ΡΠΎΠ² Π·Π°ΡΠΈΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΌ ΠΏΠΎΡΠΎΠΊΠ°ΠΌ. ΠΡΠ»ΠΈ ΠΏΠΎΡΠΎΠΊ ΠΈΠΌΠ΅Π΅Ρ ΡΠ²ΠΎΠΉ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΉ ΠΌΠ°ΡΠΊΠ΅Ρ, ΠΊΠΎΠ½ΡΡΠΎΠ»ΡΠ½ΡΠΉ ΠΌΠΎΠ½ΠΈΡΠΎΡ Π·Π°ΡΠΈΡΡ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΠΌΠ°ΡΠΊΠ΅Ρ ΠΏΡΠΎΡΠ΅ΡΡΠ°. ΠΠΌΠ΅ΡΡΠΎ Π½Π΅Π³ΠΎ Π΄Π»Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π°ΡΠ΄ΠΈΡΠ° ΠΈ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ Π΄ΠΎΡΡΡΠΏΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΌΠ°ΡΠΊΠ΅Ρ, ΠΏΡΠΈΡΠ²ΠΎΠ΅Π½Π½ΡΠΉ ΠΏΠΎΡΠΎΠΊΡ. Π₯ΠΎΡΡ Π΅ΡΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΠΎ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΠΌΠ°ΡΠΊΠ΅ΡΡ ΠΈ ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°ΡΡ ΠΈΡ ΠΏΠΎΡΠΎΠΊΠ°ΠΌ, Π² COM ΠΏΡΠ΅Π΄ΡΡΠΌΠΎΡΡΠ΅Π½ Π³ΠΎΡΠ°Π·Π΄ΠΎ Π±ΠΎΠ»Π΅Π΅ ΠΏΡΡΠΌΠΎΠΉ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΌΠ°ΡΠΊΠ΅ΡΠ° Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ ORPC-Π·Π°ΠΏΡΠΎΡΠ°, ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ ΡΠ΅ΠΊΡΡΠΈΠΌ ΠΏΠΎΡΠΎΠΊΠΎΠΌ. ΠΡΠΎΡ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ ΡΠ°ΡΠΊΡΡΠ²Π°Π΅ΡΡΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²ΠΎΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ½ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π²ΡΠ·ΠΎΠ²Π°, ΡΠΎ Π΅ΡΡΡ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ°, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎΠ± ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΎΠ½Π½ΠΎΠΌ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠΈ ΡΠ΅ΡΠ²Π΅ΡΠ½ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ°.
ΠΠ°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ, ΡΡΠΎ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ Π²ΡΠ·ΠΎΠ²Π° ΡΠΎΠΏΠΎΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ Ρ ΠΏΠΎΡΠΎΠΊΠΎΠΌ, ΠΊΠΎΠ³Π΄Π° ORPC-Π·Π°ΠΏΡΠΎΡ Π½Π°ΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ Π½Π° ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ½ΡΡ Π·Π°Π³Π»ΡΡΠΊΡ. Π Π°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΏΠΎΠ»ΡΡΠ°ΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΡ Π²ΡΠ·ΠΎΠ²Π° ΡΠ΅ΡΠ΅Π· API-ΡΡΠ½ΠΊΡΠΈΡ CoGetCallContext. ΠΠΎΠ½ΡΠ΅ΠΊΡΡΠ½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ Π²ΡΠ·ΠΎΠ²Π° ΡΠ΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ IServerSecurity:
[local, object, uuid(0000013E-0000-0000-C000-000000000046)]
interface IServerSecurity : IUnknown {
// get caller's security settings
// ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ Π·Π°ΡΠΈΡΡ Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅ΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ HRESULT
QueryBlanket(
[out] DWORD *pAuthnSvc, // authentication pkg
// ΠΌΠΎΠ΄ΡΠ»Ρ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ
[out] DWORD *pAuthzSvc, // authorization pkg
// ΠΌΠΎΠ΄ΡΠ»Ρ Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΠΈ
[out] OLECHAR **pServerName, // server principal
// ΡΠ΅ΡΠ²Π΅ΡΠ½ΡΠΉ ΠΏΡΠΈΠ½ΡΠΈΠΏΠ°Π»
[out] DWORD *pAuthnLevel, // authentication level
// ΡΡΠΎΠ²Π΅Π½Ρ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ
[out] DWORD *pImpLevel, // impersonation level
// ΡΡΠΎΠ²Π΅Π½Ρ Π·Π°ΠΈΠΌΡΡΠ²ΠΎΠ²Π°Π½ΠΈΡ ΠΏΡΠ°Π²
[out] void **pPrivs, // client principal
// ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΈΠΉ ΠΏΡΠΈΠ½ΡΠΈΠΏΠ°Π»
[out] DWORD *pCaps // EOAC flags
// ΡΠ»Π°Π³ΠΈ EOAC
);
// start running with credentials of caller
// Π½Π°ΡΠΈΠ½Π°Π΅ΠΌ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΡΠΌΠΈ Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅ΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ
HRESULT ImpersonateClient(void);
// stop running with credentials of caller
// Π·Π°ΠΊΠ°Π½ΡΠΈΠ²Π°Π΅ΠΌ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΡΠΌΠΈ Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅ΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ
HRESULT RevertToSelf(void);
// test for impersonation
// ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π·Π°ΠΈΠΌΡΡΠ²ΠΎΠ²Π°Π½ΠΈΡ ΠΏΡΠ°Π²
BOOL IsImpersonating(void);
}
Π ΠΎΠ΄Π½ΠΎΠΌ ΠΈΠ· ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠΈΡ ΡΠ°Π·Π΄Π΅Π»ΠΎΠ² ΡΡΠΎΠΉ Π³Π»Π°Π²Ρ ΡΠΆΠ΅ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°Π»ΡΡ ΠΌΠ΅ΡΠΎΠ΄ QueryBlanket. ΠΡΡΠ°Π»ΡΠ½ΡΠ΅ ΡΡΠΈ ΠΌΠ΅ΡΠΎΠ΄Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ Π΄Π»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΠΌΠ°ΡΠΊΠ΅ΡΠ°ΠΌΠΈ ΠΏΠΎΡΠΎΠΊΠ° Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΌΠ΅ΡΠΎΠ΄Π°. ΠΠ΅ΡΠΎΠ΄ ImpersonateClient ΡΠΎΠ·Π΄Π°Π΅Ρ ΠΌΠ°ΡΠΊΠ΅Ρ Π΄ΠΎΡΡΡΠΏΠ°, ΠΎΡΠ½ΠΎΠ²Π°Π½Π½ΡΠΉ Π½Π° ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΡΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°, ΠΈ ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°Π΅Ρ ΡΡΠΎΡ ΠΌΠ°ΡΠΊΠ΅Ρ ΡΠ΅ΠΊΡΡΠ΅ΠΌΡ ΠΏΠΎΡΠΎΠΊΡ. ΠΠ°ΠΊ ΡΠΎΠ»ΡΠΊΠΎ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ IServerSecurity::ImpersonateClient, Π²ΡΠ΅ ΠΏΠΎΠΏΡΡΠΊΠΈ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ ΡΠ΅ΡΡΡΡΠ°ΠΌ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΎΠ½Π½ΠΎΠΉ ΡΠΈΡΡΠ΅ΠΌΡ Π±ΡΠ΄ΡΡ ΡΠ°Π·ΡΠ΅ΡΠ°ΡΡΡΡ ΠΈΠ»ΠΈ Π·Π°ΠΏΡΠ΅ΡΠ°ΡΡΡΡ Π² ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΈΠΈ Ρ ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΡΠΌΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°, Π° Π½Π΅ ΠΎΠ±ΡΠ΅ΠΊΡΠ°. ΠΠ΅ΡΠΎΠ΄ RevertToSelf Π·Π°ΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΏΡΠΎΡΠ΅ΡΡ Π²Π΅ΡΠ½ΡΡΡΡΡ ΠΊ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΌΠ°ΡΠΊΠ΅ΡΠ° Π΄ΠΎΡΡΡΠΏΠ°, ΠΏΡΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°ΡΠ΅Π³ΠΎ ΠΏΡΠΎΡΠ΅ΡΡΡ. ΠΡΠ»ΠΈ ΡΠ΅ΠΊΡΡΠΈΠΉ Π²ΡΠ·ΠΎΠ² ΠΌΠ΅ΡΠΎΠ΄Π° Π·Π°ΠΊΠ°Π½ΡΠΈΠ²Π°Π΅Ρ ΡΠ°Π±ΠΎΡΡ Π²ΠΎ Π²ΡΠ΅ΠΌΡ ΡΠ΅ΠΆΠΈΠΌΠ° Π·Π°ΠΈΠΌΡΡΠ²ΠΎΠ²Π°Π½ΠΈΡ ΠΏΡΠ°Π², ΡΠΎ COM Π½Π΅ΡΠ²Π½ΠΎ Π²Π΅ΡΠ½Π΅Ρ ΠΏΠΎΡΠΎΠΊ ΠΊ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΌΠ°ΡΠΊΠ΅ΡΠ° ΠΏΡΠΎΡΠ΅ΡΡΠ°. Π Π½Π°ΠΊΠΎΠ½Π΅Ρ, ΠΌΠ΅ΡΠΎΠ΄ IServerSecurity::IsImpersonating ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΏΠΎΡΠΎΠΊ: ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ° ΠΈΠ»ΠΈ ΠΌΠ°ΡΠΊΠ΅Ρ ΠΏΡΠΎΡΠ΅ΡΡΠ° ΠΎΠ±ΡΠ΅ΠΊΡΠ°. ΠΠΎΠ΄ΠΎΠ±Π½ΠΎ ΠΌΠ΅ΡΠΎΠ΄Ρ QueryBlanket, Π΄Π²Π° ΠΌΠ΅ΡΠΎΠ΄Π° IServerSecurity ΡΠ°ΠΊΠΆΠ΅ ΠΈΠΌΠ΅ΡΡ ΡΠ΄ΠΎΠ±Π½ΡΠ΅ ΠΎΠ±ΠΎΠ»ΠΎΡΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ Π²ΡΠ·ΡΠ²Π°ΡΡ CoGetCallContext ΠΈΠ·Π½ΡΡΡΠΈ ΠΈ Π·Π°ΡΠ΅ΠΌ Π²ΡΠ·ΡΠ²Π°ΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΉ ΠΌΠ΅ΡΠΎΠ΄:
HRESULT CoImpersonateClient(void);
HRESULT CoRevertToSelf(void);
Π ΠΎΠ±ΡΠ΅ΠΌ ΡΠ»ΡΡΠ°Π΅, Π΅ΡΠ»ΠΈ Π±ΡΠ΄Π΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ Π±ΠΎΠ»Π΅Π΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΌΠ΅ΡΠΎΠ΄Π° IServerSecurity, ΡΠΎ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½Π΅Π΅ Π±ΡΠ»ΠΎ Π±Ρ Π²ΡΠ·Π²Π°ΡΡ CoGetCallContext ΠΎΠ΄ΠΈΠ½ ΡΠ°Π·, Π° Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΌΠ΅ΡΠΎΠ΄Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠΈΡΡΡΡΠΈΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ IServerSecurity.
Π‘Π»Π΅Π΄ΡΡΡΠΈΠΉ ΠΊΠΎΠ΄ Π΄Π΅ΠΌΠΎΠ½ΡΡΡΠΈΡΡΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ½ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π²ΡΠ·ΠΎΠ²Π° Π΄Π»Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΡΠ°ΡΡΠΈ ΠΊΠΎΠ΄Π° ΠΌΠ΅ΡΠΎΠ΄Π° Ρ ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΡΠΌΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°:
STDMETHODIMP MyClass::ReadWrite(DWORD dwNew, DWORD *pdw0ld)
{
// execute using server's token to let anyone read the value
// Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΠΌ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΌΠ°ΡΠΊΠ΅ΡΠ° ΡΠ΅ΡΠ²Π΅ΡΠ°, ΡΡΠΎΠ±Ρ
// Π²ΡΠ΅ ΠΌΠΎΠ³Π»ΠΈ ΠΏΡΠΎΡΠΈΡΠ°ΡΡ Π΄Π°Π½Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅
ULONG cb;
HANDLE hfile = CreateFile(Β«C:\\file1.binΒ», GENERIC_READ,
0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hfile == INVALID_HANDLE_VALUE)
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
ReadFile(hfile, pdwOld, sizeof(DWORD), &cb, 0);
CloseHandle(hfile);
// get call context object
// ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ Π²ΡΠ·ΠΎΠ²Π°
IServerSecurlty *pss = 0;
HRESULT hr = CoGetCallContext(IID_IServerSecurity, (void**)&pss);
if (FAILED(hr)) return hr;
// set thread token to use caller's credentials
// ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΠΌΠ°ΡΠΊΠ΅Ρ ΠΏΠΎΡΠΎΠΊΠ° Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ
// ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΠΉ Π²ΡΠ·ΡΠ²Π°ΡΡΠ΅ΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ
hr = pss->ImpersonateClient();
assert(SUCCEEDED(hr));
// execute using client's token to let only users that can
// write to the file change the value
// Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΠΌ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΌΠ°ΡΠΊΠ΅ΡΠ° ΠΊΠ»ΠΈΠ΅Π½ΡΠ°, ΡΡΠΎΠ±Ρ
// ΠΈΠ·ΠΌΠ΅Π½ΡΡΡ ΡΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠ³Π»ΠΈ ΡΠΎΠ»ΡΠΊΠΎ ΡΠ΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΠΈ,
// ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈΠΌΠ΅ΡΡ ΠΏΡΠ°Π²ΠΎ Π·Π°ΠΏΠΈΡΡΠ²Π°ΡΡ Π² ΡΠ°ΠΉΠ»
hfile = CreateFile(Β«C:\\file2.binΒ»,
GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hfile == INVALID_HANDLE_VALUE)
hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
else {
WriteFile(hfile, &dwNew, sizeof(DWORD), &cb, 0);
CloseHandle(hfile);
}
// restore thread to use process-level token
// Π²ΠΎΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΡΠ΅ΠΆΠΈΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΏΠΎΡΠΎΠΊΠΎΠΌ ΠΌΠ°ΡΠΊΠ΅ΡΠ° ΠΏΡΠΎΡΠ΅ΡΡΠ°
pss->RevertToSelf();
// release call context
// ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅ΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π²ΡΠ·ΠΎΠ²Π°
pss->Release();
return hr;
}
ΠΡΠΌΠ΅ΡΠΈΠΌ, ΡΡΠΎ ΠΏΠ΅ΡΠ²ΡΠΉ Π²ΡΠ·ΠΎΠ² CreateFile Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΠΉ ΠΏΡΠΎΡΠ΅ΡΡΠ° ΠΎΠ±ΡΠ΅ΠΊΡΠ°, Π² ΡΠΎ Π²ΡΠ΅ΠΌΡ ΠΊΠ°ΠΊ Π²ΡΠΎΡΠΎΠΉ Π²ΡΠ·ΠΎΠ² β Ρ ΠΏΠΎΠ»Π½ΠΎΠΌΠΎΡΠΈΡΠΌΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°. ΠΡΠ»ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ ΠΈΠΌΠ΅Π΅Ρ ΠΏΡΠ°Π²Π° Π΄ΠΎΡΡΡΠΏΠ° Π΄Π»Ρ ΡΡΠ΅Π½ΠΈΡ/Π·Π°ΠΏΠΈΡΠΈ Π² ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΉ ΡΠ°ΠΉΠ», ΡΠΎ Π²ΡΠΎΡΠΎΠΉ Π²ΡΠ·ΠΎΠ² ΠΌΠ΅ΡΠΎΠ΄Π° CreateFile ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΡΠΏΠ΅ΡΠ½ΡΠΌ, Π΄Π°ΠΆΠ΅ Π΅ΡΠ»ΠΈ ΠΎΠ±ΡΡΠ½ΠΎ ΠΏΡΠΎΡΠ΅ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ ΡΡΠΎΠΌΡ ΡΠ°ΠΉΠ»Ρ.