/****************************************************************************/ // valinfo.h // // Copyright (C) 1997-1999 Microsoft Corp. /****************************************************************************/ #include "ValInfo.h" ValueFullInfo::ValueFullInfo( KeyNode *pKey ) : pInfo(NULL), pSzName(NULL), pKeyNode(NULL) { pKeyNode = pKey; KeyFullInfo *pKeyInfo; if ( NT_SUCCESS ( status = pKeyNode->GetFullInfo( &pKeyInfo) ) ) { size = sizeof(KEY_VALUE_FULL_INFORMATION) + (pKeyInfo->Ptr()->MaxValueNameLen + 1)*sizeof(WCHAR) + pKeyInfo->Ptr()->MaxValueDataLen; pInfo = ( KEY_VALUE_FULL_INFORMATION *)RtlAllocateHeap(RtlProcessHeap(), 0, size ); if (!pInfo) { status = STATUS_NO_MEMORY; } else status = STATUS_SUCCESS; } } PCWSTR ValueFullInfo::SzName() { if (!pSzName) { ULONG size = pInfo->NameLength + sizeof(WCHAR); pSzName = (PWSTR) RtlAllocateHeap(RtlProcessHeap(), 0, size ); if (!pSzName) { status = STATUS_NO_MEMORY; } else { wcsncpy( pSzName, pInfo->Name, pInfo->NameLength/sizeof(WCHAR) ); pSzName[ pInfo->NameLength/sizeof( WCHAR) ] = L'\0'; status = STATUS_SUCCESS; } } return pSzName; } BOOLEAN ValueFullInfo::Compare( ValueFullInfo *pOther ) { status = STATUS_SUCCESS; // we don't expect errors in here if ( pOther->Ptr()->Type != Ptr()->Type) { return FALSE; } if ( pOther->Ptr()->DataLength != Ptr()->DataLength) { return FALSE; } if ( pOther->Ptr()->NameLength != Ptr()->NameLength) { return FALSE; } for (ULONG i = 0; i < Ptr()->NameLength / sizeof( WCHAR) ; i++) { if ( Ptr()->Name[i] != pOther->Ptr()->Name[i]) { return FALSE; } } for (i = 0; i < Ptr()->DataLength; i++) { if ( ((PCHAR)( (PCHAR)Ptr() + Ptr()->DataOffset ))[i] != ((PCHAR) ( (PCHAR)(pOther->Ptr()) + pOther->Ptr()->DataOffset) )[i] ) return FALSE; } return TRUE; } ValueFullInfo::~ValueFullInfo() { if (pInfo) { RtlFreeHeap( RtlProcessHeap(), 0, pInfo); } if ( pSzName ) { RtlFreeHeap( RtlProcessHeap(), 0, pSzName ); } } NTSTATUS ValueFullInfo::Query(PCWSTR pValueName ) { ULONG resultSize; ULONG numberOfAttempts=0; if ( NT_SUCCESS( pKeyNode->Status() ) ) { UNICODE_STRING tmpName; RtlInitUnicodeString( &tmpName, pValueName); status = NtQueryValueKey( pKeyNode->Key() , &tmpName, Type(), Ptr(), Size(), &resultSize); if ( (status == STATUS_BUFFER_OVERFLOW ) || ( status == STATUS_BUFFER_TOO_SMALL ) ) { // @@@ this can never happen right? // Since the key param imposes a max size on any valule // under the key. } } else status = STATUS_OBJECT_NAME_NOT_FOUND; // need to call open or key is not found return status; } NTSTATUS ValueFullInfo::Delete(PCWSTR pValueName ) { UNICODE_STRING tmpName; RtlInitUnicodeString( &tmpName, pValueName); if (NT_SUCCESS( status = pKeyNode->Status() ) ) { status = NtDeleteValueKey( pKeyNode->Key(), &tmpName ); } return status; } NTSTATUS ValueFullInfo::Create( ValueFullInfo *pNew ) { UNICODE_STRING uniString; uniString.Buffer = pNew->Ptr()->Name; uniString.Length = (USHORT)pNew->Ptr()->NameLength; uniString.MaximumLength = uniString.Length + 2; if (NT_SUCCESS( status = pKeyNode->Status() ) ) { status = NtSetValueKey( pKeyNode->Key(), &uniString, 0, pNew->Ptr()->Type, (PCHAR)pNew->Ptr()+ pNew->Ptr()->DataOffset, pNew->Ptr()->DataLength); } return status; } void ValueFullInfo::Print( FILE *fp ) { fwprintf( fp, L"name=%ws, size= %d, type=%d \n", SzName(), Size(), Type() ); fwprintf( fp, L"DataOffset=%d, DataLength=%d, NameLength=%d \n", Ptr()->DataOffset, Ptr()->DataLength, Ptr()->NameLength ); for ( ULONG i =0; i < Ptr()->NameLength + Ptr()->DataLength; i++) { if ( !(i % 32) ) { fwprintf(fp,L"\n"); fwprintf(fp,L"i=%3d ,",i); } fwprintf( fp, L"%2x ", ((BYTE *)(Ptr()->Name))[i] ); } fwprintf(fp,L"\n"); fflush( fp ); } ValuePartialInfo::ValuePartialInfo( KeyNode *pKey , ULONG defaultSize ): pInfo(NULL), pKeyNode(NULL) { pKeyNode = pKey; if (defaultSize) { size = defaultSize; } else { size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG); pInfo = ( KEY_VALUE_PARTIAL_INFORMATION *)RtlAllocateHeap( RtlProcessHeap(), 0, size ); } if (!pInfo) { status = STATUS_NO_MEMORY; pInfo=NULL; } else status = STATUS_SUCCESS; } ValuePartialInfo::~ValuePartialInfo() { if (pInfo) { RtlFreeHeap( RtlProcessHeap(), 0, pInfo); } } NTSTATUS ValuePartialInfo::Query( PCWSTR pValueName ) { ULONG resultSize; ULONG numberOfAttempts=0; UNICODE_STRING tmpName; if (!pKeyNode->Key()) { // not having a key associated with this registry should mean that any further operation // must return an expected error status without calling the underlying nt apis, since // appverifier will detect such as a potential bug. status = STATUS_INVALID_HANDLE; return status; } RtlInitUnicodeString( &tmpName, pValueName); tryAgain: status = NtQueryValueKey(pKeyNode->Key(), &tmpName, Type(), Ptr(), Size(), &resultSize); if ( (status == STATUS_BUFFER_OVERFLOW ) || ( status == STATUS_BUFFER_TOO_SMALL ) ) { RtlFreeHeap( RtlProcessHeap(), 0, pInfo); size = resultSize; pInfo = ( KEY_VALUE_PARTIAL_INFORMATION *)RtlAllocateHeap( RtlProcessHeap(), 0, size ); numberOfAttempts++; if ( numberOfAttempts < 10 ) { goto tryAgain; } // else, we bail out, don't want to hang here, let the caller worry about this. } return status; } NTSTATUS ValuePartialInfo::Delete(PCWSTR pValueName ) { UNICODE_STRING tmpName; RtlInitUnicodeString( &tmpName, pValueName); if (!pKeyNode->Key()) { // not having a key associated with this registry should mean that any further operation // must return an expected error status without calling the underlying nt apis, since // appverifier will detect such as a potential bug. status = STATUS_INVALID_HANDLE; return status; } status = NtDeleteValueKey( pKeyNode->Key(), &tmpName ); return status; }