- Remove DummyKcb hacks since we now have a real, valid KCB.
- Get rid of the cm worker thread and related code, this should fix a couple of random registry bugchecks and corruption.
- This is a slow transition to using CM_KEY_BODY and KCB.
svn path=/trunk/; revision=29986
KPROCESSOR_MODE PreviousMode;
UNICODE_STRING CapturedClass = {0};
HANDLE hKey;
+ PCM_KEY_NODE Node, ParentNode;
PAGED_CODE();
if (RemainingPath.Length == 0)
{
/* Fail if the key has been deleted */
- if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
+ if (((PKEY_OBJECT) Object)->KeyControlBlock->Delete)
{
PostCreateKeyInfo.Object = NULL;
PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
/* Create the key */
- Status = CmpDoCreate(&((PKEY_OBJECT)Object)->RegistryHive->Hive,
- ((PKEY_OBJECT)Object)->KeyCellOffset,
+ Status = CmpDoCreate(((PKEY_OBJECT)Object)->KeyControlBlock->KeyHive,
+ ((PKEY_OBJECT)Object)->KeyControlBlock->KeyCell,
NULL,
&RemainingPath,
KernelMode,
RtlCreateUnicodeString(&KeyObject->Name, Start);
- KeyObject->KeyCell->Parent = KeyObject->ParentKey->KeyCellOffset;
- KeyObject->KeyCell->Security = KeyObject->ParentKey->KeyCell->Security;
- KeyObject->ValueCache.ValueList = KeyObject->KeyCell->ValueList.List;
- KeyObject->ValueCache.Count = KeyObject->KeyCell->ValueList.Count;
+ ParentNode = (PCM_KEY_NODE)HvGetCell(KeyObject->ParentKey->KeyControlBlock->KeyHive,
+ KeyObject->ParentKey->KeyControlBlock->KeyCell);
+
+ Node = (PCM_KEY_NODE)HvGetCell(KeyObject->KeyControlBlock->KeyHive,
+ KeyObject->KeyControlBlock->KeyCell);
+
+ Node->Parent = KeyObject->ParentKey->KeyControlBlock->KeyCell;
+ Node->Security = ParentNode->Security;
+
+ KeyObject->KeyControlBlock->ValueCache.ValueList = Node->ValueList.List;
+ KeyObject->KeyControlBlock->ValueCache.Count = Node->ValueList.Count;
DPRINT("RemainingPath: %wZ\n", &RemainingPath);
VERIFY_KEY_OBJECT(KeyObject);
- RegistryHive = KeyObject->RegistryHive;
+ RegistryHive = (PCMHIVE)KeyObject->KeyControlBlock->KeyHive;
/* Acquire hive lock */
KeEnterCriticalRegion();
RtlFreeUnicodeString(&RemainingPath);
/* Fail if the key has been deleted */
- if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
+ if (((PKEY_OBJECT)Object)->KeyControlBlock->Delete)
{
Status = STATUS_UNSUCCESSFUL;
goto openkey_cleanup;
Status = CmiCallRegisteredCallbacks(RegNtPreDeleteKey, &DeleteKeyInfo);
if (NT_SUCCESS(Status))
{
- /* HACK: Setup the Dummy KCB */
- CM_KEY_CONTROL_BLOCK DummyKcb = {0};
- DummyKcb.KeyHive = &KeyObject->RegistryHive->Hive;
- DummyKcb.KeyCell = KeyObject->KeyCellOffset;
-
/* Call the internal API */
- Status = CmDeleteKey(&DummyKcb);
+ Status = CmDeleteKey(KeyObject->KeyControlBlock);
/* Remove the keep-alive reference */
ObDereferenceObject(KeyObject);
- if (KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
+ if (KeyObject->KeyControlBlock->KeyHive !=
+ KeyObject->ParentKey->KeyControlBlock->KeyHive)
{
/* Dereference again */
ObDereferenceObject(KeyObject);
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo);
if (NT_SUCCESS(Status))
{
- /* HACK: Setup the Dummy KCB */
- CM_KEY_CONTROL_BLOCK DummyKcb = {0};
- DummyKcb.KeyHive = &KeyObject->RegistryHive->Hive;
- DummyKcb.KeyCell = KeyObject->KeyCellOffset;
-
/* Call the internal API */
- Status = CmEnumerateKey(&DummyKcb,
+ Status = CmEnumerateKey(KeyObject->KeyControlBlock,
Index,
KeyInformationClass,
KeyInformation,
&EnumerateValueKeyInfo);
if (NT_SUCCESS(Status))
{
- /* HACK: Setup the Dummy KCB */
- CM_KEY_CONTROL_BLOCK DummyKcb = {0};
- DummyKcb.KeyHive = &KeyObject->RegistryHive->Hive;
- DummyKcb.KeyCell = KeyObject->KeyCellOffset;
-
/* Call the internal API */
- Status = CmEnumerateValueKey(&DummyKcb,
+ Status = CmEnumerateValueKey(KeyObject->KeyControlBlock,
Index,
KeyValueInformationClass,
KeyValueInformation,
Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo);
if (NT_SUCCESS(Status))
{
- /* HACK: Setup the Dummy KCB */
- CM_KEY_CONTROL_BLOCK DummyKcb = {0};
- DummyKcb.KeyHive = &KeyObject->RegistryHive->Hive;
- DummyKcb.KeyCell = KeyObject->KeyCellOffset;
-
/* Call the internal API */
- Status = CmQueryKey(&DummyKcb,
+ Status = CmQueryKey(KeyObject->KeyControlBlock,
KeyInformationClass,
KeyInformation,
Length,
Status = CmiCallRegisteredCallbacks(RegNtPreQueryValueKey, &QueryValueKeyInfo);
if (NT_SUCCESS(Status))
{
- /* HACK: Setup the Dummy KCB */
- CM_KEY_CONTROL_BLOCK DummyKcb = {0};
- DummyKcb.KeyHive = &KeyObject->RegistryHive->Hive;
- DummyKcb.KeyCell = KeyObject->KeyCellOffset;
-
/* Call the internal API */
- Status = CmQueryValueKey(&DummyKcb,
+ Status = CmQueryValueKey(KeyObject->KeyControlBlock,
*ValueName,
KeyValueInformationClass,
KeyValueInformation,
/* Do the callback */
Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo);
if (NT_SUCCESS(Status))
- {
- /* HACK: Setup the Dummy KCB */
- CM_KEY_CONTROL_BLOCK DummyKcb = {0};
- DummyKcb.KeyHive = &KeyObject->RegistryHive->Hive;
- DummyKcb.KeyCell = KeyObject->KeyCellOffset;
-
+ {
/* Call the internal API */
- Status = CmSetValueKey(&DummyKcb,
+ Status = CmSetValueKey(KeyObject->KeyControlBlock,
ValueName,
Type,
Data,
&DeleteValueKeyInfo);
if (NT_SUCCESS(Status))
{
- /* HACK: Setup the Dummy KCB */
- CM_KEY_CONTROL_BLOCK DummyKcb = {0};
- DummyKcb.KeyHive = &KeyObject->RegistryHive->Hive;
- DummyKcb.KeyCell = KeyObject->KeyCellOffset;
-
/* Call the internal API */
- Status = CmDeleteValueKey(&DummyKcb, *ValueName);
+ Status = CmDeleteValueKey(KeyObject->KeyControlBlock, *ValueName);
/* Do the post callback */
PostOperationInfo.Object = (PVOID)KeyObject;
ERESOURCE CmpRegistryLock;
-KTIMER CmiWorkerTimer;
LIST_ENTRY CmiKeyObjectListHead;
LIST_ENTRY CmiConnectedHiveList;
-ULONG CmiTimer = 0; /* gets incremented every 5 seconds (CmiWorkerTimer) */
volatile BOOLEAN CmiHiveSyncEnabled = FALSE;
volatile BOOLEAN CmiHiveSyncPending = FALSE;
extern LIST_ENTRY CmiCallbackHead;
extern FAST_MUTEX CmiCallbackLock;
-/* FUNCTIONS ****************************************************************/
-
-/* Debugging helper functions: */
-/* CmiVerifyHiveListIntegrity */
-/* CmiVerifyHiveListIntegrityWhileLocked */
-/* These functions are normally unused. However, should any of the asserts */
-/* checking for registry loops in CmiWorkerThread start to trigger, it is */
-/* recommended to add liberal amounts of calls to this function throughout */
-/* suspect code. This function is due to its iterative nature not intended */
-/* to be called during normal circumstances, but as a debugging aid. */
-static
-VOID
-NTAPI
-CmipVerifyHiveListIntegrity(BOOLEAN IsLocked)
-{
- PLIST_ENTRY CurrentEntry;
- if (!IsLocked)
- {
- /* Acquire hive lock */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
- }
-
- if (IsListEmpty(&CmiKeyObjectListHead))
- {
- ASSERT(CmiKeyObjectListHead.Blink == CmiKeyObjectListHead.Flink);
- }
- /* walk the list both forwards and backwards */
- CurrentEntry = CmiKeyObjectListHead.Flink;
- while (CurrentEntry != &CmiKeyObjectListHead)
- {
- ASSERT(CurrentEntry->Blink != CurrentEntry);
- ASSERT(CurrentEntry->Flink != CurrentEntry);
- CurrentEntry = CurrentEntry->Flink;
- }
-
- CurrentEntry = CmiKeyObjectListHead.Blink;
- while (CurrentEntry != &CmiKeyObjectListHead)
- {
- ASSERT(CurrentEntry->Blink != CurrentEntry);
- ASSERT(CurrentEntry->Flink != CurrentEntry);
- CurrentEntry = CurrentEntry->Blink;
- }
-
- if (!IsLocked)
- {
- ExReleaseResourceLite(&CmpRegistryLock);
- KeLeaveCriticalRegion();
- }
-}
-
-VOID NTAPI CmiVerifyHiveListIntegrity() { CmipVerifyHiveListIntegrity(FALSE); }
-VOID NTAPI CmiVerifyHiveListIntegrityWhileLocked() { CmipVerifyHiveListIntegrity(TRUE); }
-
-
-
-VOID
-NTAPI
-CmiWorkerThread(PVOID Param)
-{
- NTSTATUS Status;
- PLIST_ENTRY CurrentEntry;
- PKEY_OBJECT CurrentKey;
- ULONG Count; /* how many objects have been dereferenced each pass */
-
- /* Loop forever, getting woken up every 5 seconds by CmiWorkerTimer */
-
- while (1)
- {
- Status = KeWaitForSingleObject(&CmiWorkerTimer,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- if (Status == STATUS_SUCCESS)
- {
- DPRINT("CmiWorkerThread\n");
-
- /* Acquire hive lock */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
-
- CmiTimer++;
-
- Count = 0;
- CurrentEntry = CmiKeyObjectListHead.Blink;
- while (CurrentEntry != &CmiKeyObjectListHead)
- {
- CurrentKey = CONTAINING_RECORD(CurrentEntry, KEY_OBJECT, ListEntry);
- if (CurrentKey->TimeStamp + 120 > CmiTimer)
- {
- /* The object was accessed in the last 10min */
- break;
- }
- if (1 == ObGetObjectPointerCount(CurrentKey) &&
- !(CurrentKey->Flags & KO_MARKED_FOR_DELETE))
- {
- /* PointerCount is 1, and it's not marked for delete */
- ObDereferenceObject(CurrentKey);
- if (CurrentEntry == CmiKeyObjectListHead.Blink)
- {
- DPRINT("Registry loop detected! Crashing\n");
- KEBUGCHECK(0);
- }
- CurrentEntry = CmiKeyObjectListHead.Blink;
- Count++;
- }
- else
- {
- /* PointerCount was not 1, or it was marked for delete */
- if (CurrentEntry == CurrentEntry->Blink)
- {
- DPRINT("Registry loop detected! Crashing\n");
- KEBUGCHECK(0);
- }
- CurrentEntry = CurrentEntry->Blink;
- }
- }
- ExReleaseResourceLite(&CmpRegistryLock);
- KeLeaveCriticalRegion();
-
- DPRINT("Removed %d key objects\n", Count);
- }
- else
- {
- KEBUGCHECK(0);
- }
- }
-}
-
PVOID
NTAPI
CmpRosGetHardwareHive(OUT PULONG Length)
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
/* Insert it into the global list (we don't have KCBs here) */
- InsertTailList(&CmiKeyObjectListHead, &KeyObject->ListEntry);
+ InsertTailList(&CmiKeyObjectListHead, &KeyObject->KeyBodyList);
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
DPRINT ("SubName %S\n", SubName);
/* Create the key */
- Status = CmpDoCreate(&ParentKey->RegistryHive->Hive,
- ParentKey->KeyCellOffset,
+ Status = CmpDoCreate(ParentKey->KeyControlBlock->KeyHive,
+ ParentKey->KeyControlBlock->KeyCell,
NULL,
&RemainingPath,
KernelMode,
return STATUS_INSUFFICIENT_RESOURCES;
}
- NewKey->KeyCellOffset = RegistryHive->Hive.BaseBlock->RootCell;
- NewKey->KeyCell = (PVOID)HvGetCell(&RegistryHive->Hive, NewKey->KeyCellOffset);
- NewKey->RegistryHive = RegistryHive;
+ NewKey->KeyControlBlock->KeyCell = RegistryHive->Hive.BaseBlock->RootCell;
+ NewKey->KeyControlBlock->KeyHive = &RegistryHive->Hive;
Status = RtlpCreateUnicodeString(&NewKey->Name,
SubName, NonPagedPool);
UNICODE_STRING KeyName;
PWSTR *Path = &RemainingName->Buffer;
PCM_KEY_CONTROL_BLOCK ParentKcb = NULL, Kcb;
-
+ PCM_KEY_NODE Node;
+
ParsedKey = ParsedObject;
VERIFY_KEY_OBJECT(ParsedKey);
if (FoundObject == NULL)
{
/* Search for the subkey */
- BlockOffset = CmpFindSubKeyByName(&ParsedKey->RegistryHive->Hive,
- ParsedKey->KeyCell,
+ Node = (PCM_KEY_NODE)HvGetCell(ParsedKey->KeyControlBlock->KeyHive,
+ ParsedKey->KeyControlBlock->KeyCell);
+
+ BlockOffset = CmpFindSubKeyByName(ParsedKey->KeyControlBlock->KeyHive,
+ Node,
&KeyName);
if (BlockOffset == HCELL_NIL)
{
}
/* Get the node */
- SubKeyCell = (PCM_KEY_NODE)HvGetCell(&ParsedKey->RegistryHive->Hive, BlockOffset);
+ SubKeyCell = (PCM_KEY_NODE)HvGetCell(ParsedKey->KeyControlBlock->KeyHive, BlockOffset);
if ((SubKeyCell->Flags & KEY_SYM_LINK) &&
!((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)))
{
RtlInitUnicodeString(&LinkPath, NULL);
- Status = CmiGetLinkTarget(ParsedKey->RegistryHive,
+ Status = CmiGetLinkTarget((PCMHIVE)ParsedKey->KeyControlBlock->KeyHive,
SubKeyCell,
&LinkPath);
if (NT_SUCCESS(Status))
ObReferenceObject(FoundObject);
/* Create the KCB */
- Kcb = CmpCreateKeyControlBlock(&ParsedKey->RegistryHive->Hive,
+ Kcb = CmpCreateKeyControlBlock(ParsedKey->KeyControlBlock->KeyHive,
BlockOffset,
SubKeyCell,
ParentKcb,
}
FoundObject->KeyControlBlock = Kcb;
- FoundObject->Flags = 0;
- FoundObject->KeyCell = SubKeyCell;
- FoundObject->KeyCellOffset = BlockOffset;
- FoundObject->RegistryHive = ParsedKey->RegistryHive;
- InsertTailList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
+ ASSERT(FoundObject->KeyControlBlock->KeyHive == ParsedKey->KeyControlBlock->KeyHive);
+ InsertTailList(&CmiKeyObjectListHead, &FoundObject->KeyBodyList);
RtlpCreateUnicodeString(&FoundObject->Name, KeyName.Buffer, NonPagedPool);
CmiAddKeyToList(ParsedKey, FoundObject);
DPRINT("Created object 0x%p\n", FoundObject);
}
else
{
- if ((FoundObject->KeyCell->Flags & KEY_SYM_LINK) &&
+ Node = (PCM_KEY_NODE)HvGetCell(FoundObject->KeyControlBlock->KeyHive,
+ FoundObject->KeyControlBlock->KeyCell);
+
+ if ((Node->Flags & KEY_SYM_LINK) &&
!((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)))
{
DPRINT("Found link\n");
RtlInitUnicodeString(&LinkPath, NULL);
- Status = CmiGetLinkTarget(FoundObject->RegistryHive,
- FoundObject->KeyCell,
+ Status = CmiGetLinkTarget((PCMHIVE)FoundObject->KeyControlBlock->KeyHive,
+ Node,
&LinkPath);
if (NT_SUCCESS(Status))
{
}
}
- RemoveEntryList(&FoundObject->ListEntry);
- InsertHeadList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
- FoundObject->TimeStamp = CmiTimer;
+ RemoveEntryList(&FoundObject->KeyBodyList);
+ InsertHeadList(&CmiKeyObjectListHead, &FoundObject->KeyBodyList);
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
- RemoveEntryList(&KeyObject->ListEntry);
+ RemoveEntryList(&KeyObject->KeyBodyList);
RtlFreeUnicodeString(&KeyObject->Name);
- ASSERT((KeyObject->Flags & KO_MARKED_FOR_DELETE) == FALSE);
+ ASSERT((KeyObject->KeyControlBlock->Delete) == FALSE);
ObDereferenceObject (ParentKeyObject);
if (Index < Parent->SubKeyCounts)
{
- if (CurKey->Flags & KO_MARKED_FOR_DELETE)
+ if (CurKey->KeyControlBlock->Delete)
{
CHECKPOINT;
*ReturnedObject = NULL;
#define IsNoFileHive(Hive) ((Hive)->Flags & HIVE_NO_FILE)\r
typedef struct _KEY_OBJECT\r
{\r
- CSHORT Type;\r
- CSHORT Size;\r
- ULONG Flags;\r
+ ULONG Type;\r
UNICODE_STRING Name;\r
- PCMHIVE RegistryHive;\r
- HCELL_INDEX KeyCellOffset;\r
- PCM_KEY_NODE KeyCell;\r
struct _KEY_OBJECT *ParentKey;\r
- LIST_ENTRY ListEntry;\r
+ LIST_ENTRY KeyBodyList;\r
ULONG SubKeyCounts;\r
ULONG SizeOfSubKeys;\r
struct _KEY_OBJECT **SubKeys;\r
- ULONG TimeStamp;\r
- LIST_ENTRY HiveList;\r
- CACHED_CHILD_LIST ValueCache;\r
PCM_KEY_CONTROL_BLOCK KeyControlBlock;\r
} KEY_OBJECT, *PKEY_OBJECT;\r
extern PCMHIVE CmiVolatileHive;\r
\r
/* Now fill out the Cm object */\r
KeyBody->KeyControlBlock = Kcb;\r
- KeyBody->KeyCell = KeyNode;\r
- KeyBody->KeyCellOffset = *KeyCell;\r
- KeyBody->Flags = 0;\r
KeyBody->SubKeyCounts = 0;\r
KeyBody->SubKeys = NULL;\r
KeyBody->SizeOfSubKeys = 0;\r
KeyBody->ParentKey = Parent;\r
- KeyBody->RegistryHive = KeyBody->ParentKey->RegistryHive;\r
- InsertTailList(&CmiKeyObjectListHead, &KeyBody->ListEntry);\r
+ InsertTailList(&CmiKeyObjectListHead, &KeyBody->KeyBodyList);\r
\r
Quickie:\r
/* Check if we got here because of failure */\r
ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock);\r
\r
/* Check if the parent is being deleted */\r
- #define KO_MARKED_FOR_DELETE 0x00000001\r
- if (Parent->Flags & KO_MARKED_FOR_DELETE)\r
+ if (Parent->KeyControlBlock->Delete)\r
{\r
/* It has, quit */\r
ASSERT(FALSE);\r
}\r
\r
/* Sanity check */\r
- ASSERT(Cell == Parent->KeyCellOffset);\r
+ ASSERT(Cell == Parent->KeyControlBlock->KeyCell);\r
\r
/* Get the parent type */\r
ParentType = HvGetCellType(Cell);\r
}\r
\r
/* Don't allow children under symlinks */\r
- if (Parent->Flags & KEY_SYM_LINK)\r
+ if (Parent->KeyControlBlock->Flags & KEY_SYM_LINK)\r
{\r
/* Fail */\r
ASSERT(FALSE);\r
}\r
\r
/* Sanity checks */\r
- ASSERT(KeyBody->ParentKey->KeyCellOffset == Cell);\r
- ASSERT(&KeyBody->ParentKey->RegistryHive->Hive == Hive);\r
+ ASSERT(KeyBody->ParentKey->KeyControlBlock->KeyCell == Cell);\r
+ ASSERT(KeyBody->ParentKey->KeyControlBlock->KeyHive == Hive);\r
ASSERT(KeyBody->ParentKey == Parent);\r
\r
/* Update the timestamp */\r
if (!Kcb) return FALSE;\r
\r
/* Initialize the object */\r
-#if 0\r
RootKey->Type = TAG('k', 'v', '0', '2');\r
RootKey->KeyControlBlock = Kcb;\r
+#if 0\r
RootKey->NotifyBlock = NULL;\r
RootKey->ProcessID = PsGetCurrentProcessId();\r
#else\r
RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool);\r
- RootKey->KeyControlBlock = Kcb;\r
- RootKey->RegistryHive = CmiVolatileHive;\r
- RootKey->KeyCellOffset = RootIndex;\r
- RootKey->KeyCell = KeyCell;\r
RootKey->ParentKey = RootKey;\r
- RootKey->Flags = 0;\r
RootKey->SubKeyCounts = 0;\r
RootKey->SubKeys = NULL;\r
RootKey->SizeOfSubKeys = 0;\r
UNICODE_STRING KeyName;\r
HANDLE KeyHandle;\r
NTSTATUS Status;\r
- LARGE_INTEGER DueTime;\r
- HANDLE ThreadHandle;\r
- CLIENT_ID ThreadId;\r
PCMHIVE HardwareHive;\r
PVOID BaseAddress;\r
ULONG Length;\r
/* OLD CM: Initialize the key object list */\r
InitializeListHead(&CmiKeyObjectListHead);\r
InitializeListHead(&CmiConnectedHiveList);\r
-\r
- /* OLD CM: Initialize the worker timer */\r
- KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);\r
-\r
- /* OLD CM: Initialize the worker thread */\r
- Status = PsCreateSystemThread(&ThreadHandle,\r
- THREAD_ALL_ACCESS,\r
- NULL,\r
- NULL,\r
- &ThreadId,\r
- CmiWorkerThread,\r
- NULL);\r
- if (!NT_SUCCESS(Status)) return FALSE;\r
-\r
- /* OLD CM: Start the timer */\r
- DueTime.QuadPart = -1;\r
- KeSetTimerEx(&CmiWorkerTimer, DueTime, 5000, NULL); /* 5sec */\r
#endif\r
\r
/* Create the key object types */\r