From 4d5ec2d0bfcc8fc126b06a4b99e17f7ee39e5664 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Fri, 13 Jul 2012 08:19:36 +0000 Subject: [PATCH] [WINTRUST] - Sync to Wine 1.5.4 svn path=/trunk/; revision=56879 --- reactos/dll/win32/wintrust/CMakeLists.txt | 5 +- reactos/dll/win32/wintrust/crypt.c | 97 +++++++++++++--- reactos/dll/win32/wintrust/softpub.c | 113 ++++++++++++++++++- reactos/dll/win32/wintrust/wintrust.spec | 4 +- reactos/dll/win32/wintrust/wintrust_main.c | 28 +++++ reactos/dll/win32/wintrust/wintrust_priv.h | 12 +- reactos/dll/win32/wintrust/wintrust_ros.diff | 31 ----- reactos/media/doc/README.WINE | 2 +- 8 files changed, 232 insertions(+), 60 deletions(-) delete mode 100644 reactos/dll/win32/wintrust/wintrust_ros.diff diff --git a/reactos/dll/win32/wintrust/CMakeLists.txt b/reactos/dll/win32/wintrust/CMakeLists.txt index 9bb067775ef..5b8de9d57a8 100644 --- a/reactos/dll/win32/wintrust/CMakeLists.txt +++ b/reactos/dll/win32/wintrust/CMakeLists.txt @@ -2,15 +2,14 @@ add_definitions(-D__WINESRC__) include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) -set_rc_compiler() spec2def(wintrust.dll wintrust.spec ADD_IMPORTLIB) list(APPEND SOURCE + asn.c crypt.c register.c - wintrust_main.c - asn.c softpub.c + wintrust_main.c version.rc ${CMAKE_CURRENT_BINARY_DIR}/wintrust_stubs.c ${CMAKE_CURRENT_BINARY_DIR}/wintrust.def) diff --git a/reactos/dll/win32/wintrust/crypt.c b/reactos/dll/win32/wintrust/crypt.c index c41a56b1d1a..341f45bd59f 100644 --- a/reactos/dll/win32/wintrust/crypt.c +++ b/reactos/dll/win32/wintrust/crypt.c @@ -858,7 +858,6 @@ HANDLE WINAPI CryptCATOpen(LPWSTR pwszFileName, DWORD fdwOpenFlags, HCRYPTPROV h return INVALID_HANDLE_VALUE; } - if (!dwPublicVersion) dwPublicVersion = 0x00000100; if (!dwEncodingType) dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; if (fdwOpenFlags & CRYPTCAT_OPEN_ALWAYS) flags |= OPEN_ALWAYS; @@ -1017,16 +1016,27 @@ static BOOL WINTRUST_GetSignedMsgFromPEFile(SIP_SUBJECTINFO *pSubjectInfo, { BOOL ret; WIN_CERTIFICATE *pCert = NULL; + HANDLE file; TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, pcbSignedDataMsg, pbSignedDataMsg); + + if(pSubjectInfo->hFile && pSubjectInfo->hFile!=INVALID_HANDLE_VALUE) + file = pSubjectInfo->hFile; + else + { + file = CreateFileW(pSubjectInfo->pwsFileName, GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if(file == INVALID_HANDLE_VALUE) + return FALSE; + } if (!pbSignedDataMsg) { WIN_CERTIFICATE cert; /* app hasn't passed buffer, just get the length */ - ret = ImageGetCertificateHeader(pSubjectInfo->hFile, dwIndex, &cert); + ret = ImageGetCertificateHeader(file, dwIndex, &cert); if (ret) { switch (cert.wCertificateType) @@ -1045,7 +1055,7 @@ static BOOL WINTRUST_GetSignedMsgFromPEFile(SIP_SUBJECTINFO *pSubjectInfo, { DWORD len = 0; - ret = ImageGetCertificateData(pSubjectInfo->hFile, dwIndex, NULL, &len); + ret = ImageGetCertificateData(file, dwIndex, NULL, &len); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto error; pCert = HeapAlloc(GetProcessHeap(), 0, len); @@ -1054,10 +1064,10 @@ static BOOL WINTRUST_GetSignedMsgFromPEFile(SIP_SUBJECTINFO *pSubjectInfo, ret = FALSE; goto error; } - ret = ImageGetCertificateData(pSubjectInfo->hFile, dwIndex, pCert, - &len); + ret = ImageGetCertificateData(file, dwIndex, pCert, &len); if (!ret) goto error; + pCert->dwLength -= FIELD_OFFSET(WIN_CERTIFICATE, bCertificate); if (*pcbSignedDataMsg < pCert->dwLength) { *pcbSignedDataMsg = pCert->dwLength; @@ -1067,6 +1077,7 @@ static BOOL WINTRUST_GetSignedMsgFromPEFile(SIP_SUBJECTINFO *pSubjectInfo, else { memcpy(pbSignedDataMsg, pCert->bCertificate, pCert->dwLength); + *pcbSignedDataMsg = pCert->dwLength; switch (pCert->wCertificateType) { case WIN_CERT_TYPE_X509: @@ -1084,10 +1095,48 @@ static BOOL WINTRUST_GetSignedMsgFromPEFile(SIP_SUBJECTINFO *pSubjectInfo, } } error: + if(pSubjectInfo->hFile != file) + CloseHandle(file); HeapFree(GetProcessHeap(), 0, pCert); return ret; } +static BOOL WINTRUST_PutSignedMsgToPEFile(SIP_SUBJECTINFO* pSubjectInfo, DWORD pdwEncodingType, + DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg) +{ + WIN_CERTIFICATE *cert; + HANDLE file; + DWORD size; + BOOL ret; + + if(pSubjectInfo->hFile && pSubjectInfo->hFile!=INVALID_HANDLE_VALUE) + file = pSubjectInfo->hFile; + else + { + file = CreateFileW(pSubjectInfo->pwsFileName, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if(file == INVALID_HANDLE_VALUE) + return FALSE; + } + + /* int aligned WIN_CERTIFICATE structure with cbSignedDataMsg+1 bytes of data */ + size = FIELD_OFFSET(WIN_CERTIFICATE, bCertificate[cbSignedDataMsg+4]) & (~3); + cert = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + if(!cert) + return FALSE; + + cert->dwLength = size; + cert->wRevision = WIN_CERT_REVISION_2_0; + cert->wCertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA; + memcpy(cert->bCertificate, pbSignedDataMsg, cbSignedDataMsg); + ret = ImageAddCertificate(file, cert, pdwIndex); + + HeapFree(GetProcessHeap(), 0, cert); + if(file != pSubjectInfo->hFile) + CloseHandle(file); + return ret; +} + /* structure offsets */ #define cfhead_Signature (0x00) #define cfhead_CabinetSize (0x08) @@ -1297,23 +1346,31 @@ static BOOL WINTRUST_GetSignedMsgFromCatFile(SIP_SUBJECTINFO *pSubjectInfo, return ret; } +/* GUIDs used by CryptSIPGetSignedDataMsg and CryptSIPPutSignedDataMsg */ +static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47, + 0x00,0xC0,0x4F,0xC2,0x95,0xEE } }; +static const GUID cabGUID = { 0xC689AABA, 0x8E78, 0x11D0, { 0x8C,0x47, + 0x00,0xC0,0x4F,0xC2,0x95,0xEE } }; +static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47, + 0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; + /*********************************************************************** * CryptSIPGetSignedDataMsg (WINTRUST.@) */ BOOL WINAPI CryptSIPGetSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pdwEncodingType, DWORD dwIndex, DWORD* pcbSignedDataMsg, BYTE* pbSignedDataMsg) { - static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47, - 0x00,0xC0,0x4F,0xC2,0x95,0xEE } }; - static const GUID cabGUID = { 0xC689AABA, 0x8E78, 0x11D0, { 0x8C,0x47, - 0x00,0xC0,0x4F,0xC2,0x95,0xEE } }; - static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47, - 0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; BOOL ret; TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, pcbSignedDataMsg, pbSignedDataMsg); + if(!pSubjectInfo) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (!memcmp(pSubjectInfo->pgSubjectType, &unknown, sizeof(unknown))) ret = WINTRUST_GetSignedMsgFromPEFile(pSubjectInfo, pdwEncodingType, dwIndex, pcbSignedDataMsg, pbSignedDataMsg); @@ -1338,11 +1395,23 @@ BOOL WINAPI CryptSIPGetSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pdwEn * CryptSIPPutSignedDataMsg (WINTRUST.@) */ BOOL WINAPI CryptSIPPutSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD pdwEncodingType, - DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg) + DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg) { - FIXME("(%p %d %p %d %p) stub\n", pSubjectInfo, pdwEncodingType, pdwIndex, + TRACE("(%p %d %p %d %p)\n", pSubjectInfo, pdwEncodingType, pdwIndex, cbSignedDataMsg, pbSignedDataMsg); - + + if(!pSubjectInfo) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(!memcmp(pSubjectInfo->pgSubjectType, &unknown, sizeof(unknown))) + return WINTRUST_PutSignedMsgToPEFile(pSubjectInfo, pdwEncodingType, + pdwIndex, cbSignedDataMsg, pbSignedDataMsg); + else + FIXME("unimplemented for subject type %s\n", + debugstr_guid(pSubjectInfo->pgSubjectType)); + return FALSE; } diff --git a/reactos/dll/win32/wintrust/softpub.c b/reactos/dll/win32/wintrust/softpub.c index 9fa0d05d406..358ba01b6dd 100644 --- a/reactos/dll/win32/wintrust/softpub.c +++ b/reactos/dll/win32/wintrust/softpub.c @@ -24,6 +24,7 @@ #include "wintrust.h" #include "mssip.h" #include "softpub.h" +#include "winnls.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(wintrust); @@ -116,7 +117,20 @@ static DWORD SOFTPUB_GetFileSubject(CRYPT_PROVIDER_DATA *data) data->pWintrustData->u.pFile->pcwszFilePath, data->pWintrustData->u.pFile->hFile, &data->u.pPDSip->gSubject)) - err = GetLastError(); + { + LARGE_INTEGER fileSize; + DWORD sipError = GetLastError(); + + /* Special case for empty files: the error is expected to be + * TRUST_E_SUBJECT_FORM_UNKNOWN, rather than whatever + * CryptSIPRetrieveSubjectGuid returns. + */ + if (GetFileSizeEx(data->pWintrustData->u.pFile->hFile, &fileSize) + && !fileSize.QuadPart) + err = TRUST_E_SUBJECT_FORM_UNKNOWN; + else + err = sipError; + } } else data->u.pPDSip->gSubject = *data->pWintrustData->u.pFile->pgKnownSubject; @@ -469,6 +483,98 @@ static CMSG_SIGNER_INFO *WINTRUST_GetSigner(CRYPT_PROVIDER_DATA *data, return signerInfo; } +static BOOL WINTRUST_GetTimeFromCounterSigner( + const CMSG_CMS_SIGNER_INFO *counterSignerInfo, FILETIME *time) +{ + DWORD i; + BOOL foundTimeStamp = FALSE; + + for (i = 0; !foundTimeStamp && i < counterSignerInfo->AuthAttrs.cAttr; i++) + { + if (!strcmp(counterSignerInfo->AuthAttrs.rgAttr[i].pszObjId, + szOID_RSA_signingTime)) + { + const CRYPT_ATTRIBUTE *attr = + &counterSignerInfo->AuthAttrs.rgAttr[i]; + DWORD j; + + for (j = 0; !foundTimeStamp && j < attr->cValue; j++) + { + static const DWORD encoding = X509_ASN_ENCODING | + PKCS_7_ASN_ENCODING; + DWORD size = sizeof(FILETIME); + + foundTimeStamp = CryptDecodeObjectEx(encoding, + X509_CHOICE_OF_TIME, + attr->rgValue[j].pbData, attr->rgValue[j].cbData, 0, NULL, + time, &size); + } + } + } + return foundTimeStamp; +} + +static LPCSTR filetime_to_str(const FILETIME *time) +{ + static char date[80]; + char dateFmt[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */ + SYSTEMTIME sysTime; + + if (!time) return NULL; + + GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_SSHORTDATE, dateFmt, + sizeof(dateFmt) / sizeof(dateFmt[0])); + FileTimeToSystemTime(time, &sysTime); + GetDateFormatA(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, dateFmt, date, + sizeof(date) / sizeof(date[0])); + return date; +} + +static FILETIME WINTRUST_GetTimeFromSigner(const CRYPT_PROVIDER_DATA *data, + const CMSG_SIGNER_INFO *signerInfo) +{ + DWORD i; + FILETIME time; + BOOL foundTimeStamp = FALSE; + + for (i = 0; !foundTimeStamp && i < signerInfo->UnauthAttrs.cAttr; i++) + { + if (!strcmp(signerInfo->UnauthAttrs.rgAttr[i].pszObjId, + szOID_RSA_counterSign)) + { + const CRYPT_ATTRIBUTE *attr = &signerInfo->UnauthAttrs.rgAttr[i]; + DWORD j; + + for (j = 0; j < attr->cValue; j++) + { + static const DWORD encoding = X509_ASN_ENCODING | + PKCS_7_ASN_ENCODING; + CMSG_CMS_SIGNER_INFO *counterSignerInfo; + DWORD size; + BOOL ret = CryptDecodeObjectEx(encoding, CMS_SIGNER_INFO, + attr->rgValue[j].pbData, attr->rgValue[j].cbData, + CRYPT_DECODE_ALLOC_FLAG, NULL, &counterSignerInfo, &size); + if (ret) + { + /* FIXME: need to verify countersigner signature too */ + foundTimeStamp = WINTRUST_GetTimeFromCounterSigner( + counterSignerInfo, &time); + LocalFree(counterSignerInfo); + } + } + } + } + if (!foundTimeStamp) + { + TRACE("returning system time %s\n", + filetime_to_str(&data->sftSystemTime)); + time = data->sftSystemTime; + } + else + TRACE("returning time from message %s\n", filetime_to_str(&time)); + return time; +} + static DWORD WINTRUST_SaveSigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx) { DWORD err; @@ -479,7 +585,7 @@ static DWORD WINTRUST_SaveSigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx) CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } }; sgnr.psSigner = signerInfo; - sgnr.sftVerifyAsOf = data->sftSystemTime; + sgnr.sftVerifyAsOf = WINTRUST_GetTimeFromSigner(data, signerInfo); if (!data->psPfns->pfnAddSgnr2Chain(data, FALSE, signerIdx, &sgnr)) err = GetLastError(); else @@ -1101,7 +1207,8 @@ HRESULT WINAPI SoftpubCleanup(CRYPT_PROVIDER_DATA *data) CryptMsgClose(data->hMsg); if (data->fOpenedFile && - data->pWintrustData->dwUnionChoice == WTD_CHOICE_FILE) + data->pWintrustData->dwUnionChoice == WTD_CHOICE_FILE && + data->pWintrustData->u.pFile) CloseHandle(data->pWintrustData->u.pFile->hFile); return S_OK; diff --git a/reactos/dll/win32/wintrust/wintrust.spec b/reactos/dll/win32/wintrust/wintrust.spec index 0627711f5fb..b0332cf3dd1 100644 --- a/reactos/dll/win32/wintrust/wintrust.spec +++ b/reactos/dll/win32/wintrust/wintrust.spec @@ -45,12 +45,12 @@ @ stdcall DriverCleanupPolicy(ptr) @ stdcall DriverFinalPolicy(ptr) @ stdcall DriverInitializePolicy(ptr) -@ stub FindCertsByIssuer +@ stdcall FindCertsByIssuer(ptr ptr ptr ptr long wstr long) @ stdcall GenericChainCertificateTrust(ptr) @ stdcall GenericChainFinalProv(ptr) @ stdcall HTTPSCertificateTrust(ptr) @ stdcall HTTPSFinalProv(ptr) -@ stub IsCatalogFile +@ stdcall IsCatalogFile(ptr wstr) @ stub MsCatConstructHashTag @ stub MsCatFreeHashTag @ stub OfficeCleanupPolicy diff --git a/reactos/dll/win32/wintrust/wintrust_main.c b/reactos/dll/win32/wintrust/wintrust_main.c index 1c87b6ee07f..9b8dd85c737 100644 --- a/reactos/dll/win32/wintrust/wintrust_main.c +++ b/reactos/dll/win32/wintrust/wintrust_main.c @@ -1201,3 +1201,31 @@ HRESULT WINAPI WTHelperCertCheckValidSignature(CRYPT_PROVIDER_DATA *pProvData) FIXME("Stub\n"); return S_OK; } + +/*********************************************************************** + * IsCatalogFile + */ +BOOL WINAPI IsCatalogFile(HANDLE hFile, WCHAR *pwszFileName) +{ + static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; + GUID guid; + + TRACE("(%p, %s)\n", hFile, debugstr_w(pwszFileName)); + + if (!CryptSIPRetrieveSubjectGuid(pwszFileName, hFile, &guid)) + return FALSE; + return IsEqualGUID(&guid, &catGUID); +} + +/*********************************************************************** + * FindCertsByIssuer + */ +HRESULT WINAPI FindCertsByIssuer(PCERT_CHAIN pCertChains, DWORD *pcbCertChains, + DWORD *pcCertChains, BYTE* pbEncodedIssuerName, DWORD cbEncodedIssuerName, + LPCWSTR pwszPurpose, DWORD dwKeySpec) +{ + FIXME("(%p, %p, %p, %p, %d, %s, %d): stub\n", pCertChains, pcbCertChains, + pcCertChains, pbEncodedIssuerName, cbEncodedIssuerName, + debugstr_w(pwszPurpose), dwKeySpec); + return E_FAIL; +} diff --git a/reactos/dll/win32/wintrust/wintrust_priv.h b/reactos/dll/win32/wintrust/wintrust_priv.h index 148e161aee5..66c925ade5f 100644 --- a/reactos/dll/win32/wintrust/wintrust_priv.h +++ b/reactos/dll/win32/wintrust/wintrust_priv.h @@ -18,14 +18,14 @@ #ifndef __WINTRUST_PRIV_H__ #define __WINTRUST_PRIV_H__ -void * WINAPI WINTRUST_Alloc(DWORD cb) __WINE_ALLOC_SIZE(1); -void WINAPI WINTRUST_Free(void *p); -BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store); +void * WINAPI WINTRUST_Alloc(DWORD cb) __WINE_ALLOC_SIZE(1) DECLSPEC_HIDDEN; +void WINAPI WINTRUST_Free(void *p) DECLSPEC_HIDDEN; +BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store) DECLSPEC_HIDDEN; BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data, - BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr); + BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr) DECLSPEC_HIDDEN; BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner, - BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add); + BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add) DECLSPEC_HIDDEN; BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data, - CRYPT_PROVIDER_PRIVDATA *pPrivData2Add); + CRYPT_PROVIDER_PRIVDATA *pPrivData2Add) DECLSPEC_HIDDEN; #endif /* ndef __WINTRUST_PRIV_H__ */ diff --git a/reactos/dll/win32/wintrust/wintrust_ros.diff b/reactos/dll/win32/wintrust/wintrust_ros.diff deleted file mode 100644 index 65b5e777d15..00000000000 --- a/reactos/dll/win32/wintrust/wintrust_ros.diff +++ /dev/null @@ -1,31 +0,0 @@ -Index: wintrust_main.c -=================================================================== ---- wintrust_main.c (revision 23867) -+++ wintrust_main.c (working copy) -@@ -83,7 +83,26 @@ - */ - LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData ) - { -+ static const GUID gen_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; -+ - FIXME("%p %s %p\n", hwnd, debugstr_guid(ActionID), ActionData); -+ -+ /* Trust providers can be found at: -+ * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\CertCheck\ -+ * -+ * Process Explorer expects a correct implementation, so we -+ * return TRUST_E_PROVIDER_UNKNOWN. -+ * -+ * Girotel needs ERROR_SUCCESS. -+ * -+ * For now return TRUST_E_PROVIDER_UNKNOWN only when -+ * ActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2. -+ * -+ */ -+ -+ if (IsEqualCLSID(ActionID, &gen_verify_v2)) -+ return TRUST_E_PROVIDER_UNKNOWN; -+ - return ERROR_SUCCESS; - } - diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 3a9d6638ca5..8606f539e2c 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -189,7 +189,7 @@ reactos/dll/win32/wininet # Synced to Wine-1.5.4 reactos/dll/win32/winmm # Forked at Wine-20050628 reactos/dll/win32/winmm/midimap # Forked at Wine-20050628 reactos/dll/win32/winmm/wavemap # Forked at Wine-20050628 -reactos/dll/win32/wintrust # Autosync +reactos/dll/win32/wintrust # Synced to Wine-1.5.4 reactos/dll/win32/wldap32 # Autosync reactos/dll/win32/wmi # Synced to Wine-1.5.4 reactos/dll/win32/wtsapi32 # Synced to Wine-1.5.4