Owen Rudge : imagehlp: Implement ImageAddCertificate.
Alexandre Julliard
julliard at winehq.org
Fri Dec 4 09:11:29 CST 2009
Module: wine
Branch: master
Commit: 1f6d24565cc3a4ea75747bc8c836a884253602aa
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1f6d24565cc3a4ea75747bc8c836a884253602aa
Author: Owen Rudge <orudge at codeweavers.com>
Date: Thu Dec 3 13:51:02 2009 -0600
imagehlp: Implement ImageAddCertificate.
---
dlls/imagehlp/integrity.c | 166 +++++++++++++++++++++++++++++++++++++-
dlls/imagehlp/tests/integrity.c | 10 +-
2 files changed, 166 insertions(+), 10 deletions(-)
diff --git a/dlls/imagehlp/integrity.c b/dlls/imagehlp/integrity.c
index a46c853..6a13c53 100644
--- a/dlls/imagehlp/integrity.c
+++ b/dlls/imagehlp/integrity.c
@@ -167,6 +167,67 @@ static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle,
}
/***********************************************************************
+ * IMAGEHLP_SetSecurityDirOffset (INTERNAL)
+ *
+ * Read a file's PE header, and update the offset and size of the
+ * security directory.
+ */
+static BOOL IMAGEHLP_SetSecurityDirOffset(HANDLE handle,
+ DWORD dwOfs, DWORD dwSize)
+{
+ IMAGE_NT_HEADERS32 nt_hdr32;
+ IMAGE_NT_HEADERS64 nt_hdr64;
+ IMAGE_DATA_DIRECTORY *sd;
+ int ret, nt_hdr_size = 0;
+ DWORD pe_offset;
+ void *nt_hdr;
+ DWORD count;
+ BOOL r;
+
+ ret = IMAGEHLP_GetNTHeaders(handle, &pe_offset, &nt_hdr32, &nt_hdr64);
+
+ if (ret == HDR_NT32)
+ {
+ sd = &nt_hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
+
+ nt_hdr = &nt_hdr32;
+ nt_hdr_size = sizeof(IMAGE_NT_HEADERS32);
+ }
+ else if (ret == HDR_NT64)
+ {
+ sd = &nt_hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
+
+ nt_hdr = &nt_hdr64;
+ nt_hdr_size = sizeof(IMAGE_NT_HEADERS64);
+ }
+ else
+ return FALSE;
+
+ sd->Size = dwSize;
+ sd->VirtualAddress = dwOfs;
+
+ TRACE("size = %x addr = %x\n", sd->Size, sd->VirtualAddress);
+
+ /* write the header back again */
+ count = SetFilePointer(handle, pe_offset, NULL, FILE_BEGIN);
+
+ if (count == INVALID_SET_FILE_POINTER)
+ return FALSE;
+
+ count = 0;
+
+ r = WriteFile(handle, nt_hdr, nt_hdr_size, &count, NULL);
+
+ if (!r)
+ return FALSE;
+
+ if (count != nt_hdr_size)
+ return FALSE;
+
+ return TRUE;
+}
+
+/***********************************************************************
* IMAGEHLP_GetCertificateOffset (INTERNAL)
*
* Read a file's PE header, and return the offset and size of the
@@ -227,16 +288,111 @@ static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num,
/***********************************************************************
* ImageAddCertificate (IMAGEHLP.@)
+ *
+ * Adds the specified certificate to the security directory of
+ * open PE file.
*/
BOOL WINAPI ImageAddCertificate(
HANDLE FileHandle, LPWIN_CERTIFICATE Certificate, PDWORD Index)
{
- FIXME("(%p, %p, %p): stub\n",
- FileHandle, Certificate, Index
- );
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD size = 0, count = 0, offset = 0, sd_VirtualAddr = 0, index = 0;
+ WIN_CERTIFICATE hdr;
+ const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate;
+ BOOL r;
+
+ TRACE("(%p, %p, %p)\n", FileHandle, Certificate, Index);
+
+ r = IMAGEHLP_GetSecurityDirOffset(FileHandle, &sd_VirtualAddr, &size);
+
+ /* If we've already got a security directory, find the end of it */
+ if ((r) && (sd_VirtualAddr != 0))
+ {
+ offset = 0;
+ index = 0;
+ count = 0;
+
+ /* Check if the security directory is at the end of the file.
+ If not, we should probably relocate it. */
+ if (GetFileSize(FileHandle, NULL) != sd_VirtualAddr + size)
+ {
+ FIXME("Security directory already present but not located at EOF, not adding certificate\n");
+
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return FALSE;
+ }
+
+ while (offset < size)
+ {
+ /* read the length of the current certificate */
+ count = SetFilePointer (FileHandle, sd_VirtualAddr + offset,
+ NULL, FILE_BEGIN);
+
+ if (count == INVALID_SET_FILE_POINTER)
+ return FALSE;
+
+ r = ReadFile(FileHandle, &hdr, cert_hdr_size, &count, NULL);
+
+ if (!r)
+ return FALSE;
+
+ if (count != cert_hdr_size)
+ return FALSE;
+
+ /* check the certificate is not too big or too small */
+ if (hdr.dwLength < cert_hdr_size)
+ return FALSE;
+
+ if (hdr.dwLength > (size-offset))
+ return FALSE;
+
+ /* next certificate */
+ offset += hdr.dwLength;
+
+ /* padded out to the nearest 8-byte boundary */
+ if (hdr.dwLength % 8)
+ offset += 8 - (hdr.dwLength % 8);
+
+ index++;
+ }
+
+ count = SetFilePointer (FileHandle, sd_VirtualAddr + offset, NULL, FILE_BEGIN);
+
+ if (count == INVALID_SET_FILE_POINTER)
+ return FALSE;
+ }
+ else
+ {
+ sd_VirtualAddr = SetFilePointer(FileHandle, 0, NULL, FILE_END);
+
+ if (sd_VirtualAddr == INVALID_SET_FILE_POINTER)
+ return FALSE;
+ }
+
+ /* Write the certificate to the file */
+ r = WriteFile(FileHandle, Certificate, Certificate->dwLength, &count, NULL);
+
+ if (!r)
+ return FALSE;
+
+ /* Pad out if necessary */
+ if (Certificate->dwLength % 8)
+ {
+ char null[8];
+
+ ZeroMemory(null, 8);
+ WriteFile(FileHandle, null, 8 - (Certificate->dwLength % 8), NULL, NULL);
+
+ size += 8 - (Certificate->dwLength % 8);
+ }
+
+ size += Certificate->dwLength;
+
+ /* Update the security directory offset and size */
+ if (!IMAGEHLP_SetSecurityDirOffset(FileHandle, sd_VirtualAddr, size))
+ return FALSE;
+
+ return TRUE;
}
/***********************************************************************
diff --git a/dlls/imagehlp/tests/integrity.c b/dlls/imagehlp/tests/integrity.c
index 01fd4e9..e89167c 100644
--- a/dlls/imagehlp/tests/integrity.c
+++ b/dlls/imagehlp/tests/integrity.c
@@ -146,7 +146,7 @@ static void test_add_certificate(void)
cert->wCertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA;
CopyMemory(cert->bCertificate, test_cert_data, sizeof(test_cert_data));
- todo_wine ok(pImageAddCertificate(hFile, cert, &index), "Unable to add certificate to image, error %x\n", GetLastError());
+ ok(pImageAddCertificate(hFile, cert, &index), "Unable to add certificate to image, error %x\n", GetLastError());
HeapFree(GetProcessHeap(), 0, cert);
CloseHandle(hFile);
@@ -170,7 +170,7 @@ static void test_get_certificate(void)
ret = pImageGetCertificateData(hFile, 0, NULL, &cert_len);
err = GetLastError();
- todo_wine ok ((ret == FALSE) && (err == ERROR_INSUFFICIENT_BUFFER), "ImageGetCertificateData gave unexpected result; ret=%d / err=%x\n", ret, err);
+ ok ((ret == FALSE) && (err == ERROR_INSUFFICIENT_BUFFER), "ImageGetCertificateData gave unexpected result; ret=%d / err=%x\n", ret, err);
cert = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cert_len);
@@ -181,8 +181,8 @@ static void test_get_certificate(void)
return;
}
- todo_wine ok(ret = pImageGetCertificateData(hFile, 0, cert, &cert_len), "Unable to retrieve certificate; err=%x\n", GetLastError());
- todo_wine ok(memcmp(cert->bCertificate, test_cert_data, cert_len - sizeof(WIN_CERTIFICATE)) == 0, "Certificate retrieved did not match original\n");
+ ok(ret = pImageGetCertificateData(hFile, 0, cert, &cert_len), "Unable to retrieve certificate; err=%x\n", GetLastError());
+ ok(memcmp(cert->bCertificate, test_cert_data, cert_len - sizeof(WIN_CERTIFICATE)) == 0, "Certificate retrieved did not match original\n");
HeapFree(GetProcessHeap(), 0, cert);
CloseHandle(hFile);
@@ -204,7 +204,7 @@ static void test_remove_certificate(void)
todo_wine ok (pImageRemoveCertificate(hFile, 0), "Unable to remove certificate from file; err=%x\n", GetLastError());
/* Test to see if the certificate has actually been removed */
- ok(pImageGetCertificateHeader(hFile, 0, &cert) == FALSE, "Certificate header retrieval succeeded when it should have failed\n");
+ todo_wine ok(pImageGetCertificateHeader(hFile, 0, &cert) == FALSE, "Certificate header retrieval succeeded when it should have failed\n");
CloseHandle(hFile);
}
More information about the wine-cvs
mailing list