[07/10] wintrust: Implement CryptCATEnumerateMember.
Hans Leidekker
hans at codeweavers.com
Mon Dec 22 07:20:04 CST 2008
Based on work done by Maarten Lankhorst.
-Hans
diff --git a/dlls/wintrust/crypt.c b/dlls/wintrust/crypt.c
index 4055c55..e9432f0 100644
--- a/dlls/wintrust/crypt.c
+++ b/dlls/wintrust/crypt.c
@@ -496,12 +496,208 @@ BOOL WINAPI CryptCATClose(HANDLE hCatalog)
return TRUE;
}
+static BOOL guid_from_string(const WCHAR *str, GUID *guid)
+{
+ unsigned int i = 0;
+ unsigned char *b = (unsigned char *)guid;
+ const WCHAR *p = str;
+
+ while (i <= 37)
+ {
+ switch (i)
+ {
+ case 0:
+ if (*p != '{') return FALSE;
+ break;
+
+ case 9: case 14: case 19: case 24:
+ if (*p != '-') return FALSE;
+ break;
+
+ case 37:
+ if (*p != '}') return FALSE;
+ break;
+
+ default:
+ {
+ WCHAR c1 = p[0], c2 = p[1];
+ unsigned char byte;
+
+ if (c1 >= '0' && c1 <= '9') c1 = c1 - '0';
+ else if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10;
+ else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10;
+ else return FALSE;
+
+ if (c2 >= '0' && c2 <= '9') c2 = c2 - '0';
+ else if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10;
+ else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10;
+ else return FALSE;
+
+ byte = c1 << 4 | c2;
+
+ switch (i)
+ {
+#ifndef WORDS_BIGENDIAN
+ case 1: b[3] = byte; break;
+ case 3: b[2] = byte; break;
+ case 5: b[1] = byte; break;
+ case 7: b[0] = byte; b += 4; break;
+ case 10: case 15: b[1] = byte; break;
+ case 12: case 17: b[0] = byte; b += 2; break;
+#endif
+ default: b[0] = byte; b++; break;
+ }
+ p++; i++;
+ }
+ }
+ p++; i++;
+ }
+ return TRUE;
+}
+
/***********************************************************************
* CryptCATEnumerateMember (WINTRUST.@)
*/
-CRYPTCATMEMBER *WINAPI CryptCATEnumerateMember(HANDLE hCatalog, CRYPTCATMEMBER* pPrevMember)
+CRYPTCATMEMBER * WINAPI CryptCATEnumerateMember(HANDLE hCatalog, CRYPTCATMEMBER *prev)
{
- FIXME("(%p, %p) stub\n", hCatalog, pPrevMember);
+ struct cryptcat *cc = hCatalog;
+ CRYPTCATMEMBER *member = prev;
+ CTL_ENTRY *entry;
+ DWORD size, i;
+
+ TRACE("%p, %p\n", hCatalog, prev);
+
+ if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ /* dumping the contents makes me think that dwReserved is the iteration number */
+ if (!member)
+ {
+ if (!(member = HeapAlloc(GetProcessHeap(), 0, sizeof(*member))))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+ member->cbStruct = sizeof(*member);
+ member->pwszFileName = member->pwszReferenceTag = NULL;
+ member->dwReserved = 0;
+ member->hReserved = NULL;
+ member->gSubjectType = cc->subject;
+ member->fdwMemberFlags = 0;
+ member->pIndirectData = NULL;
+ member->dwCertVersion = cc->inner->dwVersion;
+ }
+ else member->dwReserved++;
+
+ if (member->dwReserved >= cc->inner->cCTLEntry)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto error;
+ }
+
+ /* list them backwards, like native */
+ entry = &cc->inner->rgCTLEntry[cc->inner->cCTLEntry - member->dwReserved - 1];
+
+ member->sEncodedIndirectData.cbData = member->sEncodedMemberInfo.cbData = 0;
+ member->sEncodedIndirectData.pbData = member->sEncodedMemberInfo.pbData = NULL;
+ HeapFree(GetProcessHeap(), 0, member->pIndirectData);
+ member->pIndirectData = NULL;
+
+ for (i = 0; i < entry->cAttribute; i++)
+ {
+ CRYPT_ATTRIBUTE *attr = entry->rgAttribute + i;
+
+ if (attr->cValue != 1)
+ {
+ ERR("Can't handle attr->cValue of %u\n", attr->cValue);
+ continue;
+ }
+ if (!strcmp(attr->pszObjId, CAT_MEMBERINFO_OBJID))
+ {
+ CAT_MEMBERINFO *mi;
+ BOOL ret;
+
+ member->sEncodedMemberInfo.cbData = attr->rgValue->cbData;
+ member->sEncodedMemberInfo.pbData = attr->rgValue->pbData;
+
+ CryptDecodeObject(cc->encoding, CAT_MEMBERINFO_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, NULL, &size);
+
+ if (!(mi = HeapAlloc(GetProcessHeap(), 0, size)))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ goto error;
+ }
+ ret = CryptDecodeObject(cc->encoding, CAT_MEMBERINFO_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, mi, &size);
+ if (ret)
+ {
+ member->dwCertVersion = mi->dwCertVersion;
+ if (!guid_from_string(mi->pwszSubjGuid, &member->gSubjectType))
+ {
+ HeapFree(GetProcessHeap(), 0, mi);
+ goto error;
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, mi);
+ if (!ret) goto error;
+ }
+ else if (!strcmp(attr->pszObjId, SPC_INDIRECT_DATA_OBJID))
+ {
+ /* SPC_INDIRECT_DATA_CONTENT is equal to SIP_INDIRECT_DATA */
+
+ member->sEncodedIndirectData.cbData = attr->rgValue->cbData;
+ member->sEncodedIndirectData.pbData = attr->rgValue->pbData;
+
+ CryptDecodeObject(cc->encoding, SPC_INDIRECT_DATA_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, NULL, &size);
+
+ if (!(member->pIndirectData = HeapAlloc(GetProcessHeap(), 0, size)))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ goto error;
+ }
+ CryptDecodeObject(cc->encoding, SPC_INDIRECT_DATA_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, member->pIndirectData, &size);
+ }
+ else
+ /* this object id should probably be handled in CryptCATEnumerateAttr */
+ FIXME("unhandled object id \"%s\"\n", attr->pszObjId);
+ }
+
+ if (!member->sEncodedMemberInfo.cbData || !member->sEncodedIndirectData.cbData)
+ {
+ ERR("Corrupted catalog entry?\n");
+ SetLastError(CRYPT_E_ATTRIBUTES_MISSING);
+ goto error;
+ }
+ size = (2 * member->pIndirectData->Digest.cbData + 1) * sizeof(WCHAR);
+ if (member->pwszReferenceTag)
+ member->pwszReferenceTag = HeapReAlloc(GetProcessHeap(), 0, member->pwszReferenceTag, size);
+ else
+ member->pwszReferenceTag = HeapAlloc(GetProcessHeap(), 0, size);
+
+ if (!member->pwszReferenceTag)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ goto error;
+ }
+ /* FIXME: reference tag is usually the file hash but doesn't have to be */
+ for (i = 0; i < member->pIndirectData->Digest.cbData; i++)
+ {
+ DWORD sub;
+
+ sub = member->pIndirectData->Digest.pbData[i] >> 4;
+ member->pwszReferenceTag[i * 2] = (sub < 10 ? '0' + sub : 'A' + sub - 10);
+ sub = member->pIndirectData->Digest.pbData[i] & 0xf;
+ member->pwszReferenceTag[i * 2 + 1] = (sub < 10 ? '0' + sub : 'A' + sub - 10);
+ }
+ member->pwszReferenceTag[i * 2] = 0;
+ return member;
+
+error:
+ HeapFree(GetProcessHeap(), 0, member->pIndirectData);
+ HeapFree(GetProcessHeap(), 0, member->pwszReferenceTag);
+ HeapFree(GetProcessHeap(), 0, member);
return NULL;
}
More information about the wine-patches
mailing list