Соответственно, при обращении к нему другого процесса, счетчик увеличивается на 1.
Отвечу за Grom.
Как известно из Win32API для использования чего-то надо получить handle этого чего-то. Что такое этот handle?
Каждый процесс имеет таблицу, называемую handle table. Не будем вдаваться в структуру этой таблицы, так как она меняется с разными версиями системы. Записи этой таблицы- указатели на объекты ядра,вернее сказать объекты подсистемы Executive, которая находится над ядром. Объекты executive включают в себя и объекты ядра, причем объект ядра обычно в самом начале, то есть нет разницы между указателем на объект ядра и объект executive, просто объект executive больше по размеру, например начало структуры, описывающей процесс выглядит вот так
typedef struct _EPROCESS
{
/*000*/ KPROCESS Pcb;
/*06C*/ NTSTATUS ExitStatus;
/*070*/ KEVENT LockEvent;
/*080*/ DWORD LockCount;
/*084*/ DWORD d084;
/*088*/ LARGE_INTEGER CreateTime;
/*090*/ LARGE_INTEGER ExitTime;
/*098*/ PVOID LockOwner;
/*09C*/ DWORD UniqueProcessId;
.......................
} EPROCESS;
При этом EPROCESS- объект подсистемы EXECUTIVE, а первый член этой структуры Pcb- это объект ядра KPROCESS.
Так вот handle- это просто индекс в таблице handle table. Только имейте в виду, что например в Win2k в handle на самом деле три индекса, то есть он поделен на три части и в каждой из них- индекс, что обусловлено применением промежуточных таблиц для уменьшения суммарного размера таблицы( сделано точно так же как в процессрах Intel подсистема трансляции виртуального адреса в физический).
У каждого процесса своя таблица описателей (handle table). Таким образом, каждый процесс должен каким то образом занести в свою таблицу указатель на объект, что и делается путем открытия объекта(CreateFile и т.д.) или наследования описателя(что означает копирование записи из таблицы одного процесса в таблицу другого, причем по одинаковым индексам), и в том и в другом случае произойдет увеличение счетчика. Вот это и имел в виду Grom.
Каждый объект в ядре имеет заголовок(header). Интересно отметить, что указатель на объект, который возвращают все ф-ции и который и надо передавать ф-циям, указывает не на этот заголовок, а на тело самого объекта( например, описываемого структурой EPROCESS), чтобы получить указатель на заголовок надо отнять 0x18h байт от указателя на тело объекта. То есть заголовок находится перед телом объекта и его тщательно скрывают. Структура заголовка такая
typedef struct _OBJECT_HEADER
{
/*000*/ DWORD PointerCount; // number of references
/*004*/ DWORD HandleCount; // number of open handles
/*008*/ POBJECT_TYPE ObjectType;
/*00C*/ BYTE NameOffset; // -> OBJECT_NAME
/*00D*/ BYTE HandleDBOffset; // -> OBJECT_HANDLE_DB
/*00E*/ BYTE QuotaChargesOffset; // -> OBJECT_QUOTA_CHARGES
/*00F*/ BYTE ObjectFlags; // OB_FLAG_*
/*010*/ union
{ // OB_FLAG_CREATE_INFO ? ObjectCreateInfo : QuotaBlock
/*010*/ PQUOTA_BLOCK QuotaBlock;
/*010*/ POBJECT_CREATE_INFO ObjectCreateInfo;
/*014*/ };
/*014*/ PSECURITY_DESCRIPTOR SecurityDescriptor;
/*018*/ }
OBJECT_HEADER,
* POBJECT_HEADER,
**PPOBJECT_HEADER;
Как нетрудно догадаться HandleCount- счетчик числа открытых описателей этого объекта, вот он то и изменяется при открытии и закрытии объекта.
И еще очень интересный факт- над этим OBJECT_HEADER может находится еще до 4 структур, описывающих объект, эти структуры содержат имя объекта и другую инфу об объекте.