mirror of
https://github.com/reactos/reactos.git
synced 2024-08-05 19:11:16 +00:00
- Implement some security functions regedit relies on
- fixes bug 1336 - by Thomas Weidenmueller svn path=/trunk/; revision=21248
This commit is contained in:
parent
66ef58378d
commit
daa4402f55
|
@ -513,9 +513,6 @@ FreeInheritedFromArray (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DWORD ErrorCode;
|
DWORD ErrorCode;
|
||||||
|
|
||||||
/* pfnArray is not yet used */
|
|
||||||
UNREFERENCED_PARAMETER(pfnArray);
|
|
||||||
|
|
||||||
ErrorCode = CheckNtMartaPresent();
|
ErrorCode = CheckNtMartaPresent();
|
||||||
if (ErrorCode == ERROR_SUCCESS)
|
if (ErrorCode == ERROR_SUCCESS)
|
||||||
|
@ -523,7 +520,7 @@ FreeInheritedFromArray (
|
||||||
/* call the MARTA provider */
|
/* call the MARTA provider */
|
||||||
ErrorCode = AccFreeIndexArray(pInheritArray,
|
ErrorCode = AccFreeIndexArray(pInheritArray,
|
||||||
AceCnt,
|
AceCnt,
|
||||||
NULL);
|
pfnArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode;
|
return ErrorCode;
|
||||||
|
|
|
@ -38,7 +38,7 @@ HINSTANCE hDllInstance;
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccRewriteGetHandleRights(HANDLE handle,
|
AccRewriteGetHandleRights(HANDLE handle,
|
||||||
SE_OBJECT_TYPE ObjectType,
|
SE_OBJECT_TYPE ObjectType,
|
||||||
SECURITY_INFORMATION SecurityInfo,
|
SECURITY_INFORMATION SecurityInfo,
|
||||||
|
@ -227,7 +227,7 @@ Cleanup:
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccRewriteSetHandleRights(HANDLE handle,
|
AccRewriteSetHandleRights(HANDLE handle,
|
||||||
SE_OBJECT_TYPE ObjectType,
|
SE_OBJECT_TYPE ObjectType,
|
||||||
SECURITY_INFORMATION SecurityInfo,
|
SECURITY_INFORMATION SecurityInfo,
|
||||||
|
@ -303,12 +303,280 @@ AccRewriteSetHandleRights(HANDLE handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static DWORD
|
||||||
|
AccpOpenNamedObject(LPWSTR pObjectName,
|
||||||
|
SE_OBJECT_TYPE ObjectType,
|
||||||
|
SECURITY_INFORMATION SecurityInfo,
|
||||||
|
PHANDLE Handle,
|
||||||
|
PHANDLE Handle2,
|
||||||
|
BOOL Write)
|
||||||
|
{
|
||||||
|
LPWSTR lpPath;
|
||||||
|
ACCESS_MASK DesiredAccess = (ACCESS_MASK)0;
|
||||||
|
DWORD Ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
/* determine the required access rights */
|
||||||
|
switch (ObjectType)
|
||||||
|
{
|
||||||
|
case SE_REGISTRY_KEY:
|
||||||
|
case SE_FILE_OBJECT:
|
||||||
|
case SE_KERNEL_OBJECT:
|
||||||
|
case SE_SERVICE:
|
||||||
|
case SE_WINDOW_OBJECT:
|
||||||
|
if (Write)
|
||||||
|
{
|
||||||
|
if (SecurityInfo & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
|
||||||
|
DesiredAccess |= WRITE_OWNER;
|
||||||
|
if (SecurityInfo & DACL_SECURITY_INFORMATION)
|
||||||
|
DesiredAccess |= WRITE_DAC;
|
||||||
|
if (SecurityInfo & SACL_SECURITY_INFORMATION)
|
||||||
|
DesiredAccess |= ACCESS_SYSTEM_SECURITY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SecurityInfo & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||||
|
DACL_SECURITY_INFORMATION))
|
||||||
|
DesiredAccess |= READ_CONTROL;
|
||||||
|
if (SecurityInfo & SACL_SECURITY_INFORMATION)
|
||||||
|
DesiredAccess |= ACCESS_SYSTEM_SECURITY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make a copy of the path if we're modifying the string */
|
||||||
|
switch (ObjectType)
|
||||||
|
{
|
||||||
|
case SE_REGISTRY_KEY:
|
||||||
|
case SE_SERVICE:
|
||||||
|
lpPath = (LPWSTR)LocalAlloc(LMEM_FIXED,
|
||||||
|
(wcslen(pObjectName) + 1) * sizeof(WCHAR));
|
||||||
|
if (lpPath == NULL)
|
||||||
|
{
|
||||||
|
Ret = GetLastError();
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
wcscpy(lpPath,
|
||||||
|
pObjectName);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
lpPath = pObjectName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open a handle to the path depending on the object type */
|
||||||
|
switch (ObjectType)
|
||||||
|
{
|
||||||
|
case SE_REGISTRY_KEY:
|
||||||
|
{
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
HKEY hRootKey;
|
||||||
|
LPCWSTR szRootKey;
|
||||||
|
} AccRegRootKeys[] =
|
||||||
|
{
|
||||||
|
{HKEY_CLASSES_ROOT, L"CLASSES_ROOT"},
|
||||||
|
{HKEY_CURRENT_USER, L"CURRENT_USER"},
|
||||||
|
{HKEY_LOCAL_MACHINE, L"MACHINE"},
|
||||||
|
{HKEY_USERS, L"USERS"},
|
||||||
|
{HKEY_CURRENT_CONFIG, L"CONFIG"},
|
||||||
|
};
|
||||||
|
LPWSTR lpMachineName, lpRootKeyName, lpKeyName;
|
||||||
|
HKEY hRootKey = NULL;
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
/* parse the registry path */
|
||||||
|
if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
|
||||||
|
{
|
||||||
|
lpMachineName = lpPath;
|
||||||
|
|
||||||
|
lpRootKeyName = wcschr(lpPath + 2,
|
||||||
|
L'\\');
|
||||||
|
if (lpRootKeyName == NULL)
|
||||||
|
goto ParseRegErr;
|
||||||
|
else
|
||||||
|
*(lpRootKeyName++) = L'\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lpMachineName = NULL;
|
||||||
|
lpRootKeyName = lpPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
lpKeyName = wcschr(lpRootKeyName,
|
||||||
|
L'\\');
|
||||||
|
if (lpKeyName != NULL)
|
||||||
|
{
|
||||||
|
*(lpKeyName++) = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
i != sizeof(AccRegRootKeys) / sizeof(AccRegRootKeys[0]);
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
if (!wcsicmp(lpRootKeyName,
|
||||||
|
AccRegRootKeys[i].szRootKey))
|
||||||
|
{
|
||||||
|
hRootKey = AccRegRootKeys[i].hRootKey;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hRootKey == NULL)
|
||||||
|
{
|
||||||
|
ParseRegErr:
|
||||||
|
/* FIXME - right error code? */
|
||||||
|
Ret = ERROR_INVALID_PARAMETER;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open the registry key */
|
||||||
|
if (lpMachineName != NULL)
|
||||||
|
{
|
||||||
|
Ret = RegConnectRegistry(lpMachineName,
|
||||||
|
hRootKey,
|
||||||
|
(PHKEY)Handle2);
|
||||||
|
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
goto Cleanup;
|
||||||
|
|
||||||
|
hRootKey = (HKEY)(*Handle2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ret = RegOpenKeyEx(hRootKey,
|
||||||
|
lpKeyName,
|
||||||
|
0,
|
||||||
|
(REGSAM)DesiredAccess,
|
||||||
|
(PHKEY)Handle);
|
||||||
|
if (Ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (*Handle2 != NULL)
|
||||||
|
{
|
||||||
|
RegCloseKey((HKEY)(*Handle2));
|
||||||
|
}
|
||||||
|
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SE_SERVICE:
|
||||||
|
{
|
||||||
|
LPWSTR lpServiceName, lpMachineName;
|
||||||
|
|
||||||
|
/* parse the service path */
|
||||||
|
if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
|
||||||
|
{
|
||||||
|
DesiredAccess |= SC_MANAGER_CONNECT;
|
||||||
|
|
||||||
|
lpMachineName = lpPath;
|
||||||
|
|
||||||
|
lpServiceName = wcschr(lpPath + 2,
|
||||||
|
L'\\');
|
||||||
|
if (lpServiceName == NULL)
|
||||||
|
{
|
||||||
|
/* FIXME - right error code? */
|
||||||
|
Ret = ERROR_INVALID_PARAMETER;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*(lpServiceName++) = L'\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lpMachineName = NULL;
|
||||||
|
lpServiceName = lpPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open the service */
|
||||||
|
*Handle2 = (HANDLE)OpenSCManager(lpMachineName,
|
||||||
|
NULL,
|
||||||
|
(DWORD)DesiredAccess);
|
||||||
|
if (*Handle2 == NULL)
|
||||||
|
{
|
||||||
|
goto FailOpenService;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesiredAccess &= ~SC_MANAGER_CONNECT;
|
||||||
|
*Handle = (HANDLE)OpenService((SC_HANDLE)(*Handle2),
|
||||||
|
lpServiceName,
|
||||||
|
DesiredAccess);
|
||||||
|
if (*Handle == NULL)
|
||||||
|
{
|
||||||
|
if (*Handle2 != NULL)
|
||||||
|
{
|
||||||
|
CloseServiceHandle((SC_HANDLE)(*Handle2));
|
||||||
|
}
|
||||||
|
|
||||||
|
FailOpenService:
|
||||||
|
Ret = GetLastError();
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
Ret = ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
if (lpPath != NULL)
|
||||||
|
{
|
||||||
|
LocalFree((HLOCAL)lpPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
AccpCloseObjectHandle(SE_OBJECT_TYPE ObjectType,
|
||||||
|
HANDLE Handle,
|
||||||
|
HANDLE Handle2)
|
||||||
|
{
|
||||||
|
ASSERT(Handle != NULL);
|
||||||
|
|
||||||
|
/* close allocated handlees depending on the object type */
|
||||||
|
switch (ObjectType)
|
||||||
|
{
|
||||||
|
case SE_REGISTRY_KEY:
|
||||||
|
RegCloseKey((HKEY)Handle);
|
||||||
|
if (Handle2 != NULL)
|
||||||
|
RegCloseKey((HKEY)Handle2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SE_FILE_OBJECT:
|
||||||
|
case SE_KERNEL_OBJECT:
|
||||||
|
case SE_WINDOW_OBJECT:
|
||||||
|
CloseHandle(Handle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SE_SERVICE:
|
||||||
|
CloseServiceHandle((SC_HANDLE)Handle);
|
||||||
|
ASSERT(Handle2 != NULL);
|
||||||
|
CloseServiceHandle((SC_HANDLE)Handle2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* AccRewriteGetNamedRights EXPORTED
|
* AccRewriteGetNamedRights EXPORTED
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccRewriteGetNamedRights(LPWSTR pObjectName,
|
AccRewriteGetNamedRights(LPWSTR pObjectName,
|
||||||
SE_OBJECT_TYPE ObjectType,
|
SE_OBJECT_TYPE ObjectType,
|
||||||
SECURITY_INFORMATION SecurityInfo,
|
SECURITY_INFORMATION SecurityInfo,
|
||||||
|
@ -318,8 +586,46 @@ AccRewriteGetNamedRights(LPWSTR pObjectName,
|
||||||
PACL* ppSacl,
|
PACL* ppSacl,
|
||||||
PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
|
PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
HANDLE Handle = NULL;
|
||||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
HANDLE Handle2 = NULL;
|
||||||
|
DWORD LastErr;
|
||||||
|
DWORD Ret;
|
||||||
|
|
||||||
|
/* save the last error code */
|
||||||
|
LastErr = GetLastError();
|
||||||
|
|
||||||
|
/* create the handle */
|
||||||
|
Ret = AccpOpenNamedObject(pObjectName,
|
||||||
|
ObjectType,
|
||||||
|
SecurityInfo,
|
||||||
|
&Handle,
|
||||||
|
&Handle2,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
if (Ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ASSERT(Handle != NULL);
|
||||||
|
|
||||||
|
/* perform the operation */
|
||||||
|
Ret = AccRewriteGetHandleRights(Handle,
|
||||||
|
ObjectType,
|
||||||
|
SecurityInfo,
|
||||||
|
ppsidOwner,
|
||||||
|
ppsidGroup,
|
||||||
|
ppDacl,
|
||||||
|
ppSacl,
|
||||||
|
ppSecurityDescriptor);
|
||||||
|
|
||||||
|
/* close opened handles */
|
||||||
|
AccpCloseObjectHandle(ObjectType,
|
||||||
|
Handle,
|
||||||
|
Handle2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore the last error code */
|
||||||
|
SetLastError(LastErr);
|
||||||
|
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -328,14 +634,48 @@ AccRewriteGetNamedRights(LPWSTR pObjectName,
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccRewriteSetNamedRights(LPWSTR pObjectName,
|
AccRewriteSetNamedRights(LPWSTR pObjectName,
|
||||||
SE_OBJECT_TYPE ObjectType,
|
SE_OBJECT_TYPE ObjectType,
|
||||||
SECURITY_INFORMATION SecurityInfo,
|
SECURITY_INFORMATION SecurityInfo,
|
||||||
PSECURITY_DESCRIPTOR pSecurityDescriptor)
|
PSECURITY_DESCRIPTOR pSecurityDescriptor)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
HANDLE Handle = NULL;
|
||||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
HANDLE Handle2 = NULL;
|
||||||
|
DWORD LastErr;
|
||||||
|
DWORD Ret;
|
||||||
|
|
||||||
|
/* save the last error code */
|
||||||
|
LastErr = GetLastError();
|
||||||
|
|
||||||
|
/* create the handle */
|
||||||
|
Ret = AccpOpenNamedObject(pObjectName,
|
||||||
|
ObjectType,
|
||||||
|
SecurityInfo,
|
||||||
|
&Handle,
|
||||||
|
&Handle2,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
if (Ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ASSERT(Handle != NULL);
|
||||||
|
|
||||||
|
/* perform the operation */
|
||||||
|
Ret = AccRewriteSetHandleRights(Handle,
|
||||||
|
ObjectType,
|
||||||
|
SecurityInfo,
|
||||||
|
pSecurityDescriptor);
|
||||||
|
|
||||||
|
/* close opened handles */
|
||||||
|
AccpCloseObjectHandle(ObjectType,
|
||||||
|
Handle,
|
||||||
|
Handle2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore the last error code */
|
||||||
|
SetLastError(LastErr);
|
||||||
|
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -344,7 +684,7 @@ AccRewriteSetNamedRights(LPWSTR pObjectName,
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,
|
AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,
|
||||||
PEXPLICIT_ACCESS_W pListOfExplicitEntries,
|
PEXPLICIT_ACCESS_W pListOfExplicitEntries,
|
||||||
PACL OldAcl,
|
PACL OldAcl,
|
||||||
|
@ -360,7 +700,7 @@ AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccGetInheritanceSource(LPWSTR pObjectName,
|
AccGetInheritanceSource(LPWSTR pObjectName,
|
||||||
SE_OBJECT_TYPE ObjectType,
|
SE_OBJECT_TYPE ObjectType,
|
||||||
SECURITY_INFORMATION SecurityInfo,
|
SECURITY_INFORMATION SecurityInfo,
|
||||||
|
@ -380,15 +720,28 @@ AccGetInheritanceSource(LPWSTR pObjectName,
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* AccFreeIndexArray EXPORTED
|
* AccFreeIndexArray EXPORTED
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccFreeIndexArray(PINHERITED_FROMW pInheritArray,
|
AccFreeIndexArray(PINHERITED_FROMW pInheritArray,
|
||||||
USHORT AceCnt,
|
USHORT AceCnt,
|
||||||
PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL)
|
PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
UNREFERENCED_PARAMETER(pfnArray);
|
||||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
||||||
|
while (AceCnt != 0)
|
||||||
|
{
|
||||||
|
if (pInheritArray->AncestorName != NULL)
|
||||||
|
{
|
||||||
|
LocalFree((HLOCAL)pInheritArray->AncestorName);
|
||||||
|
pInheritArray->AncestorName = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInheritArray++;
|
||||||
|
AceCnt--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -397,7 +750,7 @@ AccFreeIndexArray(PINHERITED_FROMW pInheritArray,
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccRewriteGetExplicitEntriesFromAcl(PACL pacl,
|
AccRewriteGetExplicitEntriesFromAcl(PACL pacl,
|
||||||
PULONG pcCountOfExplicitEntries,
|
PULONG pcCountOfExplicitEntries,
|
||||||
PEXPLICIT_ACCESS_W* pListOfExplicitEntries)
|
PEXPLICIT_ACCESS_W* pListOfExplicitEntries)
|
||||||
|
@ -412,7 +765,7 @@ AccRewriteGetExplicitEntriesFromAcl(PACL pacl,
|
||||||
*
|
*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
DWORD STDCALL
|
DWORD WINAPI
|
||||||
AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,
|
AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,
|
||||||
SE_OBJECT_TYPE ObjectType,
|
SE_OBJECT_TYPE ObjectType,
|
||||||
SECURITY_INFORMATION SecurityInfo,
|
SECURITY_INFORMATION SecurityInfo,
|
||||||
|
@ -430,7 +783,7 @@ AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOL STDCALL
|
BOOL WINAPI
|
||||||
DllMain(IN HINSTANCE hinstDLL,
|
DllMain(IN HINSTANCE hinstDLL,
|
||||||
IN DWORD dwReason,
|
IN DWORD dwReason,
|
||||||
IN LPVOID lpvReserved)
|
IN LPVOID lpvReserved)
|
||||||
|
|
Loading…
Reference in a new issue