<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="iexplore" type="win32gui" installbase="system32" installname="iexplore.exe" unicode="no">
<include base="iexplore">.</include>
- <library>kernel32</library>
<library>user32</library>
<library>gdi32</library>
- <library>shdocvw</library>
+ <library>shdocvw</library>
<file>main.c</file>
<file>version.rc</file>
</module>
}
// get computers list
- Count = SetupGetLineCount(hTxtsetupSif, _T("Computer"));
- if (Count > 0)
- {
- SetupData.pComputers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * Count);
- if (SetupData.pComputers != NULL)
- {
- SetupData.CompCount = Count;
- Count = 0;
- if (SetupFindFirstLine(hTxtsetupSif, _T("Computer"), NULL, &InfContext))
- {
- do
- {
- SetupGetStringField(&InfContext,
- 0,
- SetupData.pComputers[Count].Id,
- sizeof(SetupData.pComputers[Count].Id) / sizeof(TCHAR),
- &LineLength);
-
- SetupGetStringField(&InfContext,
- 1,
- SetupData.pComputers[Count].Value,
- sizeof(SetupData.pComputers[Count].Value) / sizeof(TCHAR),
- &LineLength);
- ++Count;
- }
- while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.CompCount);
- }
- }
- }
+ SetupData.CompCount = LoadGenentry(hTxtsetupSif,_T("Computer"),SetupData.pComputers,&InfContext);
// get display list
- Count = SetupGetLineCount(hTxtsetupSif, _T("Display"));
- if (Count > 0)
- {
- SetupData.pDisplays = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * Count);
- if (SetupData.pDisplays != NULL)
- {
- SetupData.DispCount = Count;
- Count = 0;
+ SetupData.DispCount = LoadGenentry(hTxtsetupSif,_T("Display"),SetupData.pDisplays,&InfContext);
- if (SetupFindFirstLine(hTxtsetupSif, _T("Display"), NULL, &InfContext))
- {
- do
- {
- SetupGetStringField(&InfContext,
- 0,
- SetupData.pDisplays[Count].Id,
- sizeof(SetupData.pDisplays[Count].Id) / sizeof(TCHAR),
- &LineLength);
+ // get keyboard list
+ SetupData.KeybCount = LoadGenentry(hTxtsetupSif, _T("Keyboard"),SetupData.pKeyboards,&InfContext);
- {
- SetupGetStringField(&InfContext,
- 1,
+ // get install directory
+ if (SetupFindFirstLine(hTxtsetupSif, _T("SetupData"), _T("DefaultPath"), &InfContext))
- SetupData.pDisplays[Count].Value,
- sizeof(SetupData.pDisplays[Count].Value) / sizeof(TCHAR),
++ {
+ SetupGetStringField(&InfContext,
+ 1,
- &LineLength);
- }
+ SetupData.InstallDir,
+ sizeof(SetupData.InstallDir) / sizeof(TCHAR),
- ++Count;
+ &LineLength);
- while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.DispCount);
+ }
- }
-}
+ SetupCloseInfFile(hTxtsetupSif);
- }
+ }
+ }
- // get keyboard list
- Count = SetupGetLineCount(hTxtsetupSif, _T("Keyboard"));
- if (Count > 0)
+ LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY gen,PINFCONTEXT context)
-{
+ {
- SetupData.pKeyboards = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * Count);
- if (SetupData.pKeyboards != NULL)
- {
- SetupData.KeybCount = Count;
- Count = 0;
+ LONG TotalCount;
- if (SetupFindFirstLine(hTxtsetupSif, _T("Keyboard"), NULL, &InfContext))
+ TotalCount = SetupGetLineCount(hinf, name);
+ if (TotalCount > 0)
- {
+ {
+ gen = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * TotalCount);
+ if (gen != NULL)
+ {
+ if (SetupFindFirstLine(hinf, name, NULL, context))
+ {
+ LONG Count = 0;
- do
- {
+ do
+ {
- SetupGetStringField(&InfContext,
+ SetupGetStringField(context,
- 0,
+ 0,
- SetupData.pKeyboards[Count].Id,
- sizeof(SetupData.pKeyboards[Count].Id) / sizeof(TCHAR),
- &LineLength);
+ gen[Count].Id,
+ sizeof(gen[Count].Id) / sizeof(TCHAR),
+ NULL);
- SetupGetStringField(&InfContext,
+ SetupGetStringField(context,
- 1,
+ 1,
- SetupData.pKeyboards[Count].Value,
- sizeof(SetupData.pKeyboards[Count].Value) / sizeof(TCHAR),
- &LineLength);
- ++Count;
+ gen[Count].Value,
+ sizeof(gen[Count].Value) / sizeof(TCHAR),
+ NULL);
+ Count++;
- }
+ }
- while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.KeybCount);
+ while (SetupFindNextLine(context, context) && Count < TotalCount);
+ }
}
}
- }
- // get install directory
- if (SetupFindFirstLine(hTxtsetupSif, _T("SetupData"), _T("DefaultPath"), &InfContext))
- {
- SetupGetStringField(&InfContext,
- 1,
- SetupData.InstallDir,
- sizeof(SetupData.InstallDir) / sizeof(TCHAR),
- &LineLength);
+ return TotalCount;
-}
+ }
- SetupCloseInfFile(hTxtsetupSif);
- }
- }
BOOL isUnattendSetup()
{
boot\bootdata\bootcdregtest\regtest.cmd 7 optional
; Subsystems
-subsystems\win32\csrss\csrss.exe 1
-subsystems\win32\csrss\win32csr\win32csr.dll 1
-subsystems\ntvdm\ntvdm.exe 1
-subsystems\win32\win32k\win32k.sys 1
+;subsystems\win32\csrss\csrss.exe 1
+;subsystems\win32\csrss\win32csr\win32csr.dll 1
+;subsystems\ntvdm\ntvdm.exe 1
+;subsystems\win32\win32k\win32k.sys 1
; Optional/proprietary files
- modules\optional\kvmnet.inf 6 optional
- modules\optional\kvmnet.sys 2 optional
+ modules\optional\DroidSansFallback.ttf 3 optional
+ modules\optional\NOTICE_for_Droid_Font.txt 4 optional
+ modules\optional\netkvm2k.inf 6 optional
+ modules\optional\netkvm2k.cat 6 optional
+ modules\optional\netkvm.sys 2 optional
modules\optional\alcxwdm.inf 6 optional
modules\optional\alcxwdm.sys 2 optional
modules\optional\mfc42.dll 1 optional
<define name="WIN32" />
<define name="_WINDOWS" />
<define name="_MBCS" />
++ <define name="HAVE_STAT" />
<define name="HAVE_WIN32_THREADS" />
<define name="_REENTRANT" />
<define name="_WINSOCKAPI_" />
//SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
#if (WINVER >= 0x0500)
-- SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, (PVOID)pButtonData->g_ClickLockEnabled, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
++ SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, UlongToPtr(pButtonData->g_ClickLockEnabled), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
if (pButtonData->g_ClickLockEnabled)
SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, pButtonData->g_ClickLockTime, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
#endif
//#if (WINVER >= 0x0500)
if (pPointerData->bOrigCursorShadow != pPointerData->bCursorShadow)
{
-- SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bCursorShadow, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
++ SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
pPointerData->bOrigCursorShadow = pPointerData->bCursorShadow;
}
//#endif
else if (lppsn->hdr.code == PSN_RESET)
{
//#if (WINVER >= 0x0500)
-- SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bOrigCursorShadow, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
++ SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bOrigCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
//#endif
}
break;
}
DriverNameA[0] = 0;
- WideCharToMultiByte(CP_ACP, 0, ProductName, -1, DriverNameA, sizeof(DriverNameA) / sizeof(char), NULL, NULL);
+ if (ProductName)
+ {
+ WideCharToMultiByte(CP_ACP, 0, ProductName, -1, DriverNameA, sizeof(DriverNameA) / sizeof(char), NULL, NULL);
+ DriverNameA[(sizeof(DriverNameA) / sizeof(char))-1] = 0;
+ }
return lpDSEnumCallbackA(DeviceGuid, (LPSTR)Buffer, DriverNameA, lpContext);
}
MAX_PATH,
DosName,
NULL) == 0)
- return STATUS_DLL_NOT_FOUND;
+ {
+ /* try to find active context dll */
+ Status = find_actctx_dll(DllName->Buffer, DosName);
+ if(Status == STATUS_SUCCESS)
+ DPRINT("found %S for %S\n", DosName,DllName->Buffer);
+ else
+ return STATUS_DLL_NOT_FOUND;
+ }
if (!RtlDosPathNameToNtPathName_U (DosName,
&FullNtFileName,
OUT PULONG Disposition OPTIONAL,
OUT PULONG Cookie OPTIONAL)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ BOOLEAN Ret;
+ BOOLEAN CookieSet = FALSE;
+
+ if ((Flags != 0x01) && (Flags != 0x02))
+ return STATUS_INVALID_PARAMETER_1;
+
+ if (!Cookie) return STATUS_INVALID_PARAMETER_3;
+
+ /* Set some defaults for failure while verifying params */
+ _SEH2_TRY
+ {
+ *Cookie = 0;
+ CookieSet = TRUE;
+ if (Disposition) *Disposition = 0;
- }
++}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (CookieSet)
+ Status = STATUS_INVALID_PARAMETER_3;
+ else
+ Status = STATUS_INVALID_PARAMETER_2;
+ }
+ _SEH2_END;
+
+ if (Flags == 0x01)
+ {
+ DPRINT1("Warning: Reporting errors with exception not supported yet!\n");
+ RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
+ Status = STATUS_SUCCESS;
+
+ }
+ else
+ {
+ if (!Disposition) return STATUS_INVALID_PARAMETER_2;
+
+ Ret = RtlTryEnterCriticalSection(NtCurrentPeb()->LoaderLock);
+
+ if (Ret)
+ *Disposition = 0x01;
+ else
+ *Disposition = 0x02;
+
+ Status = STATUS_SUCCESS;
+ }
+
+ /* FIXME: Cookie is based on part of the thread id */
+ *Cookie = (ULONG)NtCurrentTeb()->RealClientId.UniqueThread;
+ return Status;
}
NTSTATUS
else
{
ret = TRUE;
- if ( TranslatedName )
+
+ dwAccountName = TranslatedName->Name.Length / sizeof(WCHAR);
+ if (ReferencedDomain && ReferencedDomain->Entries > 0)
+ dwDomainName = ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR);
+ else
+ dwDomainName = 0;
+
+ if (*pdwAccountName <= dwAccountName || *pdwDomainName <= dwDomainName)
{
- DWORD dwSrcLen = TranslatedName->Name.Length / sizeof(WCHAR);
- if ( *pdwAccountName <= dwSrcLen )
- {
- *pdwAccountName = dwSrcLen + 1;
+ /* One or two buffers are insufficient, add up a char for NULL termination */
+ *pdwAccountName = dwAccountName + 1;
+ *pdwDomainName = dwDomainName + 1;
- ret = FALSE;
+ ret = FALSE;
- }
- else
+ } else
- {
+ {
- *pdwAccountName = dwSrcLen;
- if (pAccountName)
- {
- RtlCopyMemory ( pAccountName, TranslatedName->Name.Buffer, TranslatedName->Name.Length );
- pAccountName[TranslatedName->Name.Length / sizeof(WCHAR)] = L'\0';
- }
- }
+ /* Lengths are sufficient, copy the data */
+ if(dwAccountName)
+ RtlCopyMemory(pAccountName, TranslatedName->Name.Buffer, dwAccountName * sizeof(WCHAR));
+ pAccountName[dwAccountName] = L'\0';
+
+ if(dwDomainName)
+ RtlCopyMemory(pDomainName, ReferencedDomain->Domains[0].Name.Buffer, dwDomainName * sizeof(WCHAR));
+ pDomainName[dwDomainName] = L'\0';
+
+ *pdwAccountName = dwAccountName;
+ *pdwDomainName = dwDomainName;
+
- if (peUse)
+ if ( peUse )
*peUse = TranslatedName->Use;
}
-
+
- if ( ReferencedDomain )
- {
- if ( ReferencedDomain->Entries > 0 )
- {
- DWORD dwSrcLen = ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR);
- if ( *pdwDomainName <= dwSrcLen )
- {
- *pdwDomainName = dwSrcLen + 1;
- ret = FALSE;
- }
- else
- {
- *pdwDomainName = dwSrcLen;
- if (pDomainName)
- {
- RtlCopyMemory ( pDomainName, ReferencedDomain->Domains[0].Name.Buffer, ReferencedDomain->Domains[0].Name.Length );
- pDomainName[ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR)] = L'\0';
- }
- }
- }
- }
-
if ( !ret )
SetLastError(ERROR_INSUFFICIENT_BUFFER);
}
LRESULT CToolbarProxy::OnAddBitmap(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
-- LRESULT result;
++ LONG result;
HRESULT hResult;
result = 0;
TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes);
needed = bytes + pad_bytes + 1;
- needed += (needed / 64 + 1) * strlen(sep);
+ if (sep)
+ needed += (needed / 64 + 1) * strlen(sep);
if (needed > *out_len)
{
*ptr++ = '=';
break;
}
- strcpy(ptr, sep);
+ if (sep)
+ strcpy(ptr, sep);
return ERROR_SUCCESS;
}
charsNeeded = 0;
encodeBase64A(pbBinary, cbBinary, sep, NULL, &charsNeeded);
- charsNeeded += strlen(sep);
+ if (sep)
+ charsNeeded += strlen(sep);
if (header)
charsNeeded += strlen(header) + strlen(sep);
if (trailer)
{
strcpy(ptr, header);
ptr += strlen(ptr);
- strcpy(ptr, sep);
- ptr += strlen(sep);
- }
+ if (sep)
+ {
+ strcpy(ptr, sep);
+ ptr += strlen(sep);
+ }
+ }
encodeBase64A(pbBinary, cbBinary, sep, ptr, &size);
ptr += size - 1;
if (trailer)
{
strcpy(ptr, trailer);
ptr += strlen(ptr);
- strcpy(ptr, sep);
- ptr += strlen(sep);
- }
+ if (sep)
+ {
+ strcpy(ptr, sep);
+ ptr += strlen(sep);
+ }
+ }
*pcchString = charsNeeded - 1;
}
else if (pszString)
}
}
else
- ret = compare_cert_by_name(pCertContext,
- CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT, dwFlags,
- &subject->pCertInfo->Issuer);
- return ret;
+ found = cert_compare_certs_in_store(store, prev,
+ compare_cert_by_name, CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT,
+ dwFlags, &subject->pCertInfo->Issuer);
+ return found;
}
- static BOOL compare_existing_cert(PCCERT_CONTEXT pCertContext, DWORD dwType,
- DWORD dwFlags, const void *pvPara)
+ static BOOL compare_cert_by_name_str(PCCERT_CONTEXT pCertContext,
+ DWORD dwType, DWORD dwFlags, const void *pvPara)
{
- PCCERT_CONTEXT toCompare = pvPara;
- return CertCompareCertificate(pCertContext->dwCertEncodingType,
- pCertContext->pCertInfo, toCompare->pCertInfo);
+ PCERT_NAME_BLOB name;
+ DWORD len;
+ BOOL ret = FALSE;
+
+ if (dwType & CERT_INFO_SUBJECT_FLAG)
+ name = &pCertContext->pCertInfo->Subject;
+ else
+ name = &pCertContext->pCertInfo->Issuer;
+ len = CertNameToStrW(pCertContext->dwCertEncodingType, name,
+ CERT_SIMPLE_NAME_STR, NULL, 0);
+ if (len)
+ {
+ LPWSTR str = CryptMemAlloc(len * sizeof(WCHAR));
+
+ if (str)
+ {
+ LPWSTR ptr;
+
+ CertNameToStrW(pCertContext->dwCertEncodingType, name,
+ CERT_SIMPLE_NAME_STR, str, len);
+ for (ptr = str; *ptr; ptr++)
+ *ptr = tolowerW(*ptr);
+ if (strstrW(str, pvPara))
+ ret = TRUE;
+ CryptMemFree(str);
- }
++}
+ }
+ return ret;
}
- static BOOL compare_cert_by_signature_hash(PCCERT_CONTEXT pCertContext, DWORD dwType,
- DWORD dwFlags, const void *pvPara)
+ static PCCERT_CONTEXT find_cert_by_name_str(HCERTSTORE store, DWORD dwType,
+ DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev)
{
- const CRYPT_HASH_BLOB *hash = pvPara;
- DWORD size = 0;
- BOOL ret;
+ PCCERT_CONTEXT found = NULL;
- ret = CertGetCertificateContextProperty(pCertContext,
- CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
- if (ret && size == hash->cbData)
+ TRACE("%s\n", debugstr_w(pvPara));
+
+ if (pvPara)
{
- LPBYTE buf = CryptMemAlloc(size);
+ DWORD len = strlenW(pvPara);
+ LPWSTR str = CryptMemAlloc((len + 1) * sizeof(WCHAR));
- if (buf)
+ if (str)
{
- CertGetCertificateContextProperty(pCertContext,
- CERT_SIGNATURE_HASH_PROP_ID, buf, &size);
- ret = !memcmp(buf, hash->pbData, size);
- CryptMemFree(buf);
+ LPCWSTR src;
+ LPWSTR dst;
+
+ for (src = pvPara, dst = str; *src; src++, dst++)
+ *dst = tolowerW(*src);
+ *dst = 0;
+ found = cert_compare_certs_in_store(store, prev,
+ compare_cert_by_name_str, dwType, dwFlags, str);
+ CryptMemFree(str);
}
}
else
break;
default:
FIXME("find type %08x unimplemented\n", dwType);
- compare = NULL;
}
- if (compare)
- {
- BOOL matches = FALSE;
-
- ret = pPrevCertContext;
- do {
- ret = CertEnumCertificatesInStore(hCertStore, ret);
- if (ret)
- matches = compare(ret, dwType, dwFlags, pvPara);
- } while (ret != NULL && !matches);
- if (!ret)
- SetLastError(CRYPT_E_NOT_FOUND);
- }
+ if (find)
+ ret = find(hCertStore, dwFlags, dwType, pvPara, pPrevCertContext);
+ else if (compare)
+ ret = cert_compare_certs_in_store(hCertStore, pPrevCertContext,
+ compare, dwType, dwFlags, pvPara);
else
- {
- SetLastError(CRYPT_E_NOT_FOUND);
ret = NULL;
- }
- if (!ret)
- SetLastError(CRYPT_E_NOT_FOUND);
++ if (!ret)
++ SetLastError(CRYPT_E_NOT_FOUND);
TRACE("returning %p\n", ret);
return ret;
}
assert(pSubjectIssuerBlob);
assert(pubKey);
- info->dwVersion = CERT_V3;
+ if (pExtensions && pExtensions->cExtension)
+ info->dwVersion = CERT_V3;
+ else
+ info->dwVersion = CERT_V1;
info->SerialNumber.cbData = pSerialNumber->cbData;
info->SerialNumber.pbData = pSerialNumber->pbData;
if (pSignatureAlgorithm)
cert = CertEnumCertificatesInStore(store, cert);
if (cert)
{
- size = sizeof(hash);
-
- ret = CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID,
- hash, &size);
- if (ret)
- {
- CRYPT_HASH_BLOB blob = { sizeof(hash), hash };
-
- check = CertFindCertificateInStore(rootStore,
- cert->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
- NULL);
- if (!check)
+ if (!(check = CRYPT_FindCertInStore(rootStore, cert)))
- ret = FALSE;
- else
- CertFreeCertificateContext(check);
- }
+ ret = FALSE;
+ else
+ CertFreeCertificateContext(check);
+ }
- }
} while (ret && cert);
if (cert)
CertFreeCertificateContext(cert);
if ((nameConstraints = CRYPT_GetNameConstraints(
chain->rgpElement[i]->pCertContext->pCertInfo)))
{
- for (j = i - 1; j >= 0; j--)
- {
- DWORD errorStatus = 0;
+ if (!CRYPT_IsValidNameConstraint(nameConstraints))
+ chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
+ CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT;
+ else
+ {
+ for (j = i - 1; j >= 0; j--)
+ {
+ DWORD errorStatus = 0;
- /* According to RFC 3280, self-signed certs don't have name
- * constraints checked unless they're the end cert.
- */
- if (j == 0 || !CRYPT_IsCertificateSelfSigned(
- chain->rgpElement[j]->pCertContext))
- {
- CRYPT_CheckNameConstraints(nameConstraints,
+ /* According to RFC 3280, self-signed certs don't have name
+ * constraints checked unless they're the end cert.
+ */
+ if (j == 0 || !CRYPT_IsCertificateSelfSigned(
+ chain->rgpElement[j]->pCertContext))
+ {
+ CRYPT_CheckNameConstraints(nameConstraints,
- chain->rgpElement[i]->pCertContext->pCertInfo,
+ chain->rgpElement[j]->pCertContext->pCertInfo,
- &errorStatus);
- chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
- errorStatus;
- }
+ &errorStatus);
+ chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
+ errorStatus;
}
}
++ }
LocalFree(nameConstraints);
}
}
return alternate;
}
- #define CHAIN_QUALITY_SIGNATURE_VALID 8
- #define CHAIN_QUALITY_TIME_VALID 4
- #define CHAIN_QUALITY_COMPLETE_CHAIN 2
+ #define CHAIN_QUALITY_SIGNATURE_VALID 0x16
+ #define CHAIN_QUALITY_TIME_VALID 8
+ #define CHAIN_QUALITY_COMPLETE_CHAIN 4
+ #define CHAIN_QUALITY_BASIC_CONSTRAINTS 2
-#define CHAIN_QUALITY_TRUSTED_ROOT 1
+#define CHAIN_QUALITY_TRUSTED_ROOT 1
#define CHAIN_QUALITY_HIGHEST \
CHAIN_QUALITY_SIGNATURE_VALID | CHAIN_QUALITY_TIME_VALID | \
PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
InterlockedIncrement(&baseContext->ref);
- }
+ TRACE("%p's ref count is %d\n", context, baseContext->ref);
+ if (baseContext->type == ContextTypeLink)
+ {
+ void *linkedContext = Context_GetLinkedContext(context, contextSize);
+ PBASE_CONTEXT linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
+ contextSize);
+
+ /* Add-ref the linked contexts too */
+ while (linkedContext && linkedBase->type == ContextTypeLink)
+ {
+ InterlockedIncrement(&linkedBase->ref);
+ TRACE("%p's ref count is %d\n", linkedContext, linkedBase->ref);
+ linkedContext = Context_GetLinkedContext(linkedContext,
+ contextSize);
+ if (linkedContext)
+ linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
+ contextSize);
+ else
+ linkedBase = NULL;
++}
+ if (linkedContext)
+ {
+ /* It's not a link context, so it wasn't add-ref'ed in the while
+ * loop, so add-ref it here.
+ */
+ linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
+ contextSize);
+ InterlockedIncrement(&linkedBase->ref);
+ TRACE("%p's ref count is %d\n", linkedContext, linkedBase->ref);
+ }
+ }
}
void *Context_GetExtra(const void *context, size_t contextSize)
ContextFreeFunc dataContextFree)
{
PBASE_CONTEXT base = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
+ BOOL ret = TRUE;
- if (InterlockedDecrement(&base->ref) == 0)
+ if (base->ref <= 0)
{
- TRACE("freeing %p\n", context);
- switch (base->type)
+ ERR("%p's ref count is %d\n", context, base->ref);
+ return FALSE;
+ }
+ if (base->type == ContextTypeLink)
- {
- /* The linked context is of the same type as this, so release
- * it as well, using the same offset and data free function.
- */
+ {
- case ContextTypeData:
- ContextPropertyList_Free(((PDATA_CONTEXT)base)->properties);
- dataContextFree(context);
- break;
- case ContextTypeLink:
+ /* The linked context is of the same type as this, so release
+ * it as well, using the same offset and data free function.
+ */
- Context_Release(CONTEXT_FROM_BASE_CONTEXT(
+ ret = Context_Release(CONTEXT_FROM_BASE_CONTEXT(
- ((PLINK_CONTEXT)base)->linked, contextSize), contextSize,
- dataContextFree);
- }
+ ((PLINK_CONTEXT)base)->linked, contextSize), contextSize,
+ dataContextFree);
- break;
- default:
- assert(0);
++ }
+ if (InterlockedDecrement(&base->ref) == 0)
+ {
+ TRACE("freeing %p\n", context);
+ if (base->type == ContextTypeData)
+ {
+ ContextPropertyList_Free(((PDATA_CONTEXT)base)->properties);
+ dataContextFree(context);
}
CryptMemFree(context);
}
return ret;
}
- void ContextList_Delete(struct ContextList *list, void *context)
+ BOOL ContextList_Remove(struct ContextList *list, void *context)
{
struct list *entry = ContextList_ContextToEntry(list, context);
+ BOOL inList = FALSE;
EnterCriticalSection(&list->cs);
- list_remove(entry);
+ if (!list_empty(entry))
+ {
+ list_remove(entry);
+ inList = TRUE;
+ }
LeaveCriticalSection(&list->cs);
- list->contextInterface->free(context);
+ if (inList)
+ list_init(entry);
+ return inList;
}
static void ContextList_Empty(struct ContextList *list)
PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT pCrlContext)
{
TRACE("(%p)\n", pCrlContext);
- Context_AddRef((void *)pCrlContext, sizeof(CRL_CONTEXT));
+ if (pCrlContext)
+ Context_AddRef((void *)pCrlContext, sizeof(CRL_CONTEXT));
return pCrlContext;
}
PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
{
TRACE("(%p)\n", pCtlContext);
- Context_AddRef((void *)pCtlContext, sizeof(CTL_CONTEXT));
+ if (pCtlContext)
+ Context_AddRef((void *)pCtlContext, sizeof(CTL_CONTEXT));
return pCtlContext;
}
: NULL, &items[i].size, &itemDecoded);
if (ret)
{
- /* Account for alignment padding */
- items[i].size = ALIGN_DWORD_PTR(items[i].size);
+ if (items[i].size < items[i].minSize)
+ items[i].size = items[i].minSize;
+ else if (items[i].size > items[i].minSize)
+ {
+ /* Account for alignment padding */
+ items[i].size = ALIGN_DWORD_PTR(items[i].size);
+ }
TRACE("item %d size: %d\n", i, items[i].size);
if (nextData && items[i].hasPointer &&
items[i].size > items[i].minSize)
{
BOOL ret = TRUE;
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
__TRY
{
- ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
- if (ret && pvStructInfo)
- {
- ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
- pcbStructInfo, *pcbStructInfo);
- if (ret)
- {
- CERT_EXTENSIONS *exts;
-
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- exts = pvStructInfo;
- exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
- sizeof(CERT_EXTENSIONS));
- ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
- pcbStructInfo, NULL);
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_EXTENSIONS, cExtension),
+ offsetof(CERT_EXTENSIONS, rgExtension),
+ sizeof(CERT_EXTENSIONS),
+ CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
+ offsetof(CERT_EXTENSION, pszObjId) };
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
- }
+ }
- }
- }
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
__TRY
{
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
+ sizeof(CERT_NAME_INFO),
CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
offsetof(CERT_RDN, rgRDNAttr) };
+ DWORD bytesNeeded;
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
+ NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ CERT_NAME_INFO *info;
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ info = pvStructInfo;
+ info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
+ sizeof(CERT_NAME_INFO));
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
+ &bytesNeeded, NULL);
- }
++ }
+ }
}
__EXCEPT_PAGE_FAULT
{
__TRY
{
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
+ sizeof(CERT_NAME_INFO),
CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
offsetof(CERT_RDN, rgRDNAttr) };
+ DWORD bytesNeeded;
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
+ NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ CERT_NAME_INFO *info;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ info = pvStructInfo;
+ info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
+ sizeof(CERT_NAME_INFO));
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
+ &bytesNeeded, NULL);
- }
++ }
+ }
}
__EXCEPT_PAGE_FAULT
{
__TRY
{
- DWORD bytesNeeded;
-
- if (!cbEncoded)
- SetLastError(CRYPT_E_ASN1_EOD);
- else if (pbEncoded[0] != ASN_SEQUENCEOF)
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- else if ((ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
- cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
- NULL)))
- {
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, bytesNeeded)))
- {
- PCRYPT_SMIME_CAPABILITIES capabilities;
-
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- capabilities = pvStructInfo;
- capabilities->rgCapability =
- (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
- sizeof(CRYPT_SMIME_CAPABILITIES));
- ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
- cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
- &bytesNeeded, NULL);
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
+ offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
+ sizeof(CRYPT_SMIME_CAPABILITIES),
+ CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
+ offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
- }
+ }
- }
- }
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
__TRY
{
- DWORD bytesNeeded;
+ struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
+ offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
+ sizeof(CRYPT_ATTRIBUTES),
+ CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
+ TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
- if (!cbEncoded)
- SetLastError(CRYPT_E_ASN1_EOD);
- else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
- cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
- NULL)))
- {
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, bytesNeeded)))
- {
- PCRYPT_ATTRIBUTES attrs;
-
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- attrs = pvStructInfo;
- attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
- sizeof(CRYPT_ATTRIBUTES));
- ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
- cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
- &bytesNeeded, NULL);
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
- }
+ }
- }
- }
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
case 1: /* rfc822Name */
case 2: /* dNSName */
case 6: /* uniformResourceIdentifier */
- bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
+ if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
+ {
+ SetLastError(CRYPT_E_ASN1_RULE);
+ ret = FALSE;
+ }
+ else
+ bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
break;
case 4: /* directoryName */
case 7: /* iPAddress */
{
DWORD len = CRYPT_GetMultiStringCharacterLen(multi);
- /* Copy remainder of string "left" */
- memmove(spotToRemove, spotToRemove + lstrlenW(toRemove) + 1,
- (len - (spotToRemove - multi)) * sizeof(WCHAR));
+ if (spotToRemove + lstrlenW(toRemove) + 2 >= multi + len)
+ {
+ /* Removing last string in list, terminate multi string directly */
+ *spotToRemove = 0;
+ *(spotToRemove + 1) = 0;
+ }
+ else
+ {
+ /* Copy remainder of string "left" */
+ memmove(spotToRemove, spotToRemove + lstrlenW(toRemove) + 1,
+ (len - (spotToRemove - multi)) * sizeof(WCHAR));
+ }
ret = TRUE;
}
else
CERT_STORE_ADD_NEW, &context);
}
else
- ret = CRYPT_ReadContextProp(contextInterface,
- context, &propHdr, buf, read);
+ {
+ if (!contextInterface)
+ {
+ WARN("prop id %d before a context id\n",
+ propHdr.propID);
+ ret = FALSE;
- }
++ }
+ else
+ ret = CRYPT_ReadContextProp(
+ contextInterface, context, &propHdr, buf,
+ read);
- }
++ }
}
}
else
*brush = GdipAlloc(sizeof(GpHatch));
if (!*brush) return OutOfMemory;
- switch (hatchstyle)
+ if (hatchstyle < sizeof(HatchBrushes) / sizeof(HatchBrushes[0]))
{
- case HatchStyleHorizontal:
- case HatchStyleVertical:
- case HatchStyleForwardDiagonal:
- case HatchStyleBackwardDiagonal:
- case HatchStyleCross:
- case HatchStyleDiagonalCross:
- /* Brushes that map to BS_HATCHED */
- (*brush)->brush.lb.lbStyle = BS_HATCHED;
- (*brush)->brush.lb.lbColor = fgcol;
- (*brush)->brush.lb.lbHatch = HatchStyleToHatch(hatchstyle);
- break;
+ HBITMAP hbmp;
+ HDC hdc;
+ BITMAPINFOHEADER bmih;
+ DWORD* bits;
+ int x, y;
- default:
+ hdc = CreateCompatibleDC(0);
+
+ if (hdc)
+ {
+ bmih.biSize = sizeof(bmih);
+ bmih.biWidth = 8;
+ bmih.biHeight = 8;
+ bmih.biPlanes = 1;
+ bmih.biBitCount = 32;
+ bmih.biCompression = BI_RGB;
+ bmih.biSizeImage = 0;
+
+ hbmp = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+
+ if (hbmp)
+ {
+ for (y=0; y<8; y++)
+ for (x=0; x<8; x++)
+ if ((HatchBrushes[hatchstyle][y] & (0x80 >> x)) != 0)
+ bits[y*8+x] = forecol;
+ else
+ bits[y*8+x] = backcol;
+ }
+ else
+ stat = GenericError;
+
+ DeleteDC(hdc);
+ }
+ else
+ stat = GenericError;
+
+ if (stat == Ok)
+ {
+ (*brush)->brush.lb.lbStyle = BS_PATTERN;
+ (*brush)->brush.lb.lbColor = 0;
+ (*brush)->brush.lb.lbHatch = (ULONG_PTR)hbmp;
+ (*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
+
+ DeleteObject(hbmp);
+ }
+ }
+ else
+ {
- FIXME("Unimplemented hatch style %d\n", hatchstyle);
+ FIXME("Unimplemented hatch style %d\n", hatchstyle);
- (*brush)->brush.lb.lbStyle = BS_SOLID;
- (*brush)->brush.lb.lbColor = fgcol;
- (*brush)->brush.lb.lbHatch = 0;
+ (*brush)->brush.lb.lbStyle = BS_SOLID;
+ (*brush)->brush.lb.lbColor = fgcol;
+ (*brush)->brush.lb.lbHatch = 0;
- break;
+ (*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
}
-
- (*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
+ if (stat == Ok)
+ {
- (*brush)->brush.bt = BrushTypeHatchFill;
- (*brush)->forecol = forecol;
- (*brush)->backcol = backcol;
- (*brush)->hatchstyle = hatchstyle;
+ (*brush)->brush.bt = BrushTypeHatchFill;
+ (*brush)->forecol = forecol;
+ (*brush)->backcol = backcol;
+ (*brush)->hatchstyle = hatchstyle;
+ }
+ else
+ {
+ GdipFree(*brush);
+ *brush = NULL;
+ }
- return Ok;
+ return stat;
}
/******************************************************************************
/* start_angle and end_angle are the iterative variables */
start_angle = startAngle;
- for(i = 0; i < count - 1; i += 3){
+ for(i = 0; i < MAX_ARC_PTS - 1; i += 3){
/* check if we've overshot the end angle */
if( sweepAngle > 0.0 )
+ {
+ if (start_angle >= endAngle) break;
end_angle = min(start_angle + M_PI_2, endAngle);
+ }
else
+ {
+ if (start_angle <= endAngle) break;
end_angle = max(start_angle - M_PI_2, endAngle);
+ }
- add_arc_part(&points[i], x1, y1, x2, y2, start_angle, end_angle, i == 0);
+ if (points)
+ add_arc_part(&points[i], x1, y1, x2, y2, start_angle, end_angle, i == 0);
start_angle += M_PI_2 * (sweepAngle < 0.0 ? -1.0 : 1.0);
}
<library>ole32</library>
<library>user32</library>
<library>gdi32</library>
- <library>kernel32</library>
<library>windowscodecs</library>
<library>ntdll</library>
+ <if property="ARCH" value="amd64">
+ <library>crt</library>
+ </if>
</module>
</group>
blendfac = (left_blendfac * (right_blendpos - position) +
right_blendfac * (position - left_blendpos)) / range;
}
- return blend_colors(brush->startcolor, brush->endcolor, blendfac);
+
+ if (brush->pblendcount == 0)
- }
+ return blend_colors(brush->startcolor, brush->endcolor, blendfac);
+ else
+ {
+ int i=1;
+ ARGB left_blendcolor, right_blendcolor;
+ REAL left_blendpos, right_blendpos;
+
+ /* locate the blend colors surrounding this position */
+ while (blendfac > brush->pblendpos[i])
+ i++;
+
+ /* interpolate between the blend colors */
+ left_blendpos = brush->pblendpos[i-1];
+ left_blendcolor = brush->pblendcolor[i-1];
+ right_blendpos = brush->pblendpos[i];
+ right_blendcolor = brush->pblendcolor[i];
+ blendfac = (blendfac - left_blendpos) / (right_blendpos - left_blendpos);
+ return blend_colors(left_blendcolor, right_blendcolor, blendfac);
++}
}
static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap* bitmap, INT x, INT y,
ARGB *color)
{
- static int calls;
+ BYTE r, g, b, a;
+ BYTE *row;
TRACE("%p %d %d %p\n", bitmap, x, y, color);
- if(!bitmap || !color)
+ if(!bitmap || !color ||
+ x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height)
return InvalidParameter;
- if(!(calls++))
- FIXME("not implemented\n");
-
- *color = 0xdeadbeef;
+ row = bitmap->bits+bitmap->stride*y;
- return NotImplemented;
- }
+ switch (bitmap->format)
+ {
+ case PixelFormat16bppGrayScale:
+ getpixel_16bppGrayScale(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat16bppRGB555:
+ getpixel_16bppRGB555(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat16bppRGB565:
+ getpixel_16bppRGB565(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat16bppARGB1555:
+ getpixel_16bppARGB1555(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat24bppRGB:
+ getpixel_24bppRGB(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat32bppRGB:
+ getpixel_32bppRGB(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat32bppARGB:
+ getpixel_32bppARGB(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat32bppPARGB:
+ getpixel_32bppPARGB(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat48bppRGB:
+ getpixel_48bppRGB(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat64bppARGB:
+ getpixel_64bppARGB(&r,&g,&b,&a,row,x);
+ break;
+ case PixelFormat64bppPARGB:
+ getpixel_64bppPARGB(&r,&g,&b,&a,row,x);
+ break;
+ default:
+ FIXME("not implemented for format 0x%x\n", bitmap->format);
+ return NotImplemented;
+}
+ *color = a<<24|r<<16|g<<8|b;
+
+ return Ok;
+ }
+
+ static inline void setpixel_16bppGrayScale(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ *((WORD*)(row)+x) = (r+g+b)*85;
+ }
+
+ static inline void setpixel_16bppRGB555(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ *((WORD*)(row)+x) = (r<<7&0x7c00)|
+ (g<<2&0x03e0)|
+ (b>>3&0x001f);
+ }
+
+ static inline void setpixel_16bppRGB565(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ *((WORD*)(row)+x) = (r<<8&0xf800)|
+ (g<<3&0x07e0)|
+ (b>>3&0x001f);
+ }
+
+ static inline void setpixel_16bppARGB1555(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ *((WORD*)(row)+x) = (a<<8&0x8000)|
+ (r<<7&0x7c00)|
+ (g<<2&0x03e0)|
+ (b>>3&0x001f);
+ }
+
+ static inline void setpixel_24bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ row[x*3+2] = r;
+ row[x*3+1] = g;
+ row[x*3] = b;
+ }
+
+ static inline void setpixel_32bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ *((DWORD*)(row)+x) = (r<<16)|(g<<8)|b;
+ }
+
+ static inline void setpixel_32bppARGB(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b;
+ }
+
+ static inline void setpixel_32bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ r = r * a / 255;
+ g = g * a / 255;
+ b = b * a / 255;
+ *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b;
+ }
+
+ static inline void setpixel_48bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ row[x*6+5] = row[x*6+4] = r;
+ row[x*6+3] = row[x*6+2] = g;
+ row[x*6+1] = row[x*6] = b;
+ }
+
+ static inline void setpixel_64bppARGB(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ UINT64 a64=a, r64=r, g64=g, b64=b;
+ *((UINT64*)(row)+x) = (a64<<56)|(a64<<48)|(r64<<40)|(r64<<32)|(g64<<24)|(g64<<16)|(b64<<8)|b64;
+ }
+
+ static inline void setpixel_64bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a,
+ BYTE *row, UINT x)
+ {
+ UINT64 a64, r64, g64, b64;
+ a64 = a * 257;
+ r64 = r * a / 255;
+ g64 = g * a / 255;
+ b64 = b * a / 255;
+ *((UINT64*)(row)+x) = (a64<<48)|(r64<<32)|(g64<<16)|b64;
+ }
+
GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap* bitmap, INT x, INT y,
ARGB color)
{
- static int calls;
+ BYTE a, r, g, b;
+ BYTE *row;
TRACE("bitmap:%p, x:%d, y:%d, color:%08x\n", bitmap, x, y, color);
- if(!bitmap)
+ if(!bitmap || x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height)
return InvalidParameter;
- if(!(calls++))
- FIXME("not implemented\n");
+ a = color>>24;
+ r = color>>16;
+ g = color>>8;
+ b = color;
+
+ row = bitmap->bits + bitmap->stride * y;
- return NotImplemented;
- }
+ switch (bitmap->format)
+ {
+ case PixelFormat16bppGrayScale:
+ setpixel_16bppGrayScale(r,g,b,a,row,x);
+ break;
+ case PixelFormat16bppRGB555:
+ setpixel_16bppRGB555(r,g,b,a,row,x);
+ break;
+ case PixelFormat16bppRGB565:
+ setpixel_16bppRGB565(r,g,b,a,row,x);
+ break;
+ case PixelFormat16bppARGB1555:
+ setpixel_16bppARGB1555(r,g,b,a,row,x);
+ break;
+ case PixelFormat24bppRGB:
+ setpixel_24bppRGB(r,g,b,a,row,x);
+ break;
+ case PixelFormat32bppRGB:
+ setpixel_32bppRGB(r,g,b,a,row,x);
+ break;
+ case PixelFormat32bppARGB:
+ setpixel_32bppARGB(r,g,b,a,row,x);
+ break;
+ case PixelFormat32bppPARGB:
+ setpixel_32bppPARGB(r,g,b,a,row,x);
+ break;
+ case PixelFormat48bppRGB:
+ setpixel_48bppRGB(r,g,b,a,row,x);
+ break;
+ case PixelFormat64bppARGB:
+ setpixel_64bppARGB(r,g,b,a,row,x);
+ break;
+ case PixelFormat64bppPARGB:
+ setpixel_64bppPARGB(r,g,b,a,row,x);
+ break;
+ default:
+ FIXME("not implemented for format 0x%x\n", bitmap->format);
+ return NotImplemented;
+}
+ return Ok;
+ }
+
/* This function returns a pointer to an array of pixels that represents the
* bitmap. The *entire* bitmap is locked according to the lock mode specified by
* flags. It is correct behavior that a user who calls this function with write
return decode_image_wic(stream, &CLSID_WICIcoDecoder, image);
}
- static GpStatus decode_image_jpeg(IStream* stream, REFCLSID clsid, GpImage **image)
- {
- return decode_image_wic(stream, &CLSID_WICJpegDecoder, image);
- }
-
- static GpStatus decode_image_gif(IStream* stream, REFCLSID clsid, GpImage **image)
- {
- return decode_image_wic(stream, &CLSID_WICGifDecoder, image);
- }
-
- static GpStatus decode_image_olepicture_bitmap(IStream* stream, REFCLSID clsid, GpImage **image)
+ static GpStatus decode_image_bmp(IStream* stream, REFCLSID clsid, GpImage **image)
{
- IPicture *pic;
- BITMAPINFO *pbmi;
- BITMAPCOREHEADER* bmch;
- HBITMAP hbm;
- HDC hdc;
+ GpStatus status;
+ GpBitmap* bitmap;
- TRACE("%p %p\n", stream, image);
+ status = decode_image_wic(stream, &CLSID_WICBmpDecoder, image);
- if(!stream || !image)
- return InvalidParameter;
+ bitmap = (GpBitmap*)*image;
- if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture,
- (LPVOID*) &pic) != S_OK){
- TRACE("Could not load picture\n");
- return GenericError;
+ if (status == Ok && bitmap->format == PixelFormat32bppARGB)
- {
++{
+ /* WIC supports bmp files with alpha, but gdiplus does not */
+ bitmap->format = PixelFormat32bppRGB;
}
- pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
- if (!pbmi)
- return OutOfMemory;
- *image = GdipAlloc(sizeof(GpBitmap));
- if(!*image){
- GdipFree(pbmi);
- return OutOfMemory;
+ return status;
-}
+ }
- (*image)->type = ImageTypeBitmap;
-
- (*((GpBitmap**) image))->width = ipicture_pixel_width(pic);
- (*((GpBitmap**) image))->height = ipicture_pixel_height(pic);
- /* get the pixel format */
- IPicture_get_Handle(pic, (OLE_HANDLE*)&hbm);
- IPicture_get_CurDC(pic, &hdc);
-
- (*((GpBitmap**) image))->hbitmap = hbm;
- (*((GpBitmap**) image))->hdc = hdc;
- (*((GpBitmap**) image))->bits = NULL;
-
- bmch = (BITMAPCOREHEADER*) (&pbmi->bmiHeader);
- bmch->bcSize = sizeof(BITMAPCOREHEADER);
-
- if(!hdc){
- HBITMAP old;
- hdc = CreateCompatibleDC(0);
- old = SelectObject(hdc, hbm);
- GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
- SelectObject(hdc, old);
- DeleteDC(hdc);
+ static GpStatus decode_image_jpeg(IStream* stream, REFCLSID clsid, GpImage **image)
+ {
+ return decode_image_wic(stream, &CLSID_WICJpegDecoder, image);
-}
+ }
- else
- GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
- switch(bmch->bcBitCount)
+ static GpStatus decode_image_png(IStream* stream, REFCLSID clsid, GpImage **image)
-{
+ {
- case 1:
- (*((GpBitmap**) image))->format = PixelFormat1bppIndexed;
- break;
- case 4:
- (*((GpBitmap**) image))->format = PixelFormat4bppIndexed;
- break;
- case 8:
- (*((GpBitmap**) image))->format = PixelFormat8bppIndexed;
- break;
- case 16:
- (*((GpBitmap**) image))->format = PixelFormat16bppRGB565;
- break;
- case 24:
- (*((GpBitmap**) image))->format = PixelFormat24bppRGB;
- break;
- case 32:
- (*((GpBitmap**) image))->format = PixelFormat32bppRGB;
- break;
- case 48:
- (*((GpBitmap**) image))->format = PixelFormat48bppRGB;
- break;
- default:
- FIXME("Bit depth %d is not fully supported yet\n", bmch->bcBitCount);
- (*((GpBitmap**) image))->format = (bmch->bcBitCount << 8) | PixelFormatGDI;
- break;
+ return decode_image_wic(stream, &CLSID_WICPngDecoder, image);
-}
+ }
- GdipFree(pbmi);
-
- (*image)->picture = pic;
- (*image)->flags = ImageFlagsNone;
-
- return Ok;
+ static GpStatus decode_image_gif(IStream* stream, REFCLSID clsid, GpImage **image)
+ {
+ return decode_image_wic(stream, &CLSID_WICGifDecoder, image);
}
static GpStatus decode_image_olepicture_metafile(IStream* stream, REFCLSID clsid, GpImage **image)
if (FAILED(hr)) return hresult_to_status(hr);
/* call on the image decoder to do the real work */
- return codec->decode_func(stream, &codec->info.Clsid, image);
+ stat = codec->decode_func(stream, &codec->info.Clsid, image);
+
+ /* take note of the original data format */
+ if (stat == Ok)
+ {
+ memcpy(&(*image)->format, &codec->info.FormatID, sizeof(GUID));
- }
++}
+
+ return stat;
}
/* FIXME: no ICM */
BasepCheckForReadOnlyResource(IN PVOID Ptr)
{
PVOID Data;
-- ULONG Size, OldProtect;
++ SIZE_T Size;
++ ULONG OldProtect;
MEMORY_BASIC_INFORMATION mbi;
NTSTATUS Status;
LONG Ret = EXCEPTION_CONTINUE_SEARCH;
@ stdcall AddAtomW(wstr)
@ stdcall AddConsoleAliasA(str str str) ;check
@ stdcall AddConsoleAliasW(wstr wstr wstr) ;check
+;@ stdcall -arch=x86_64 AddIntegrityLabelToBoundaryDescriptor ; Win 7
@ stdcall AddLocalAlternateComputerNameA(str ptr)
@ stdcall AddLocalAlternateComputerNameW(wstr ptr)
- ;@ stdcall AddRefActCtx(ptr)
+ @ stdcall AddRefActCtx(ptr)
+;@ stdcall AddSIDToBoundaryDescriptor ; Win 7
+;@ stdcall AddSecureMemoryCacheCallback ; Win 7
@ stdcall AddVectoredContinueHandler(long ptr) ntdll.RtlAddVectoredContinueHandler
@ stdcall AddVectoredExceptionHandler(long ptr) ntdll.RtlAddVectoredExceptionHandler
+;@ stdcall AdjustCalendarDate ; Win 7
@ stdcall AllocConsole()
-@ stub AllocLSCallback ; missing in XP SP3 and 2003 R2
+@ stub AllocLSCallback ; missing in XP SP3 and 2003 R2 and Win 7
@ stdcall AllocateUserPhysicalPages(long ptr ptr)
+;@ stdcall AllocateUserPhysicalPagesNuma ; Win 7
+;@ stdcall ApplicationRecoveryFinished ; Win 7
+;@ stdcall ApplicationRecoveryInProgress ; Win 7
@ stdcall AreFileApisANSI()
@ stdcall AssignProcessToJobObject(ptr ptr)
@ stdcall AttachConsole(long)
@ stdcall CopyFileA(str str long)
@ stdcall CopyFileExA (str str ptr ptr ptr long)
@ stdcall CopyFileExW (wstr wstr ptr ptr ptr long)
+;@ stdcall CopyFileTransactedA ; Win 7
+;@ stdcall CopyFileTransactedW ; Win 7
@ stdcall CopyFileW(wstr wstr long)
@ stdcall CopyLZFile(long long) LZCopy
- ;@ stdcall CreateActCtxA(ptr)
- ;@ stdcall CreateActCtxW(ptr)
+ @ stdcall CreateActCtxA(ptr)
+ @ stdcall CreateActCtxW(ptr)
+;@ stdcall CreateBoundaryDescriptorA ; Win 7
+;@ stdcall CreateBoundaryDescriptorW ; Win 7
@ stdcall CreateConsoleScreenBuffer(long long ptr long ptr)
@ stdcall CreateDirectoryA(str ptr)
@ stdcall CreateDirectoryExA(str str ptr)
@ stdcall CreateTimerQueue ()
@ stdcall CreateTimerQueueTimer(ptr long ptr ptr long long long)
@ stdcall CreateToolhelp32Snapshot(long long)
-@ stdcall CreateVirtualBuffer(long long long)
+;@ stdcall arch=x86_64 CreateUmsCompletionList
+;@ stdcall arch=x86_64 CreateUmsThreadContext
+@ stdcall CreateVirtualBuffer(long long long) ; missing in Win 7
@ stdcall CreateWaitableTimerA(ptr long str)
-@ stdcall CreateWaitableTimerW(ptr long wstr)
@ stdcall CreateWaitableTimerExA (ptr str long long)
@ stdcall CreateWaitableTimerExW (ptr wstr long long)
- @ stdcall CreateWaitableTimerW(ptr long wstr)
+ @ stdcall DeactivateActCtx(long ptr)
+;@ stdcall CtrlRoutine ; Win 7
- ;@ stdcall DeactivateActCtx(long ptr)
@ stdcall DebugActiveProcess(long)
@ stdcall DebugActiveProcessStop(long)
@ stdcall DebugBreak() ntdll.DbgBreakPoint
@ stdcall GetConsoleTitleW(ptr long)
@ stdcall GetConsoleWindow()
@ stdcall GetCurrencyFormatA(long long str ptr str long)
+;@ stdcall GetCurrencyFormatEx ; Win 7
@ stdcall GetCurrencyFormatW(long long str ptr str long)
- ;@ stdcall GetCurrentActCtx(ptr)
+ @ stdcall GetCurrentActCtx(ptr)
@ stdcall GetCurrentConsoleFont(long long ptr)
+;@ stdcall GetCurrentConsoleFontEx ; Win 7
@ stdcall GetCurrentDirectoryA(long ptr)
@ stdcall GetCurrentDirectoryW(long ptr)
@ stdcall GetCurrentProcess()
@ stdcall LocalShrink(long long)
@ stdcall LocalSize(long)
@ stdcall LocalUnlock(long)
- @ stub LocaleNameToLCID ; missing in XP SP3
+ ;@ stub LocaleNameToLCID ; missing in XP SP3
+;@ stdcall LocateExtendedFeature api-ms-win-core-xstate-l1-1-0.RtlLocateExtendedFeature ; Win 7
+;@ stdcall LocateLegacyContext api-ms-win-core-xstate-l1-1-0.RtlLocateLegacyContext ; Win 7
@ stdcall LockFile(long long long long long)
@ stdcall LockFileEx(long long long long long ptr)
@ stdcall LockResource(long)
@ stdcall ProcessIdToSessionId(long ptr)
@ stdcall PulseEvent(long)
@ stdcall PurgeComm(long long)
- ;@ stdcall QueryActCtxW(long ptr ptr long ptr long ptr)
+;@ stdcall QueryActCtxSettingsW ; Win 7
+ @ stdcall QueryActCtxW(long ptr ptr long ptr long ptr)
@ stdcall QueryDepthSList(ptr) ntdll.RtlQueryDepthSList
@ stdcall QueryDosDeviceA(str ptr long)
@ stdcall QueryDosDeviceW(wstr ptr long)
@ stdcall RegisterWaitForSingleObjectEx(long ptr ptr long long)
@ stdcall RegisterWowBaseHandlers(long)
@ stdcall RegisterWowExec(long)
- ;@ stdcall ReleaseActCtx(ptr)
+ @ stdcall ReleaseActCtx(ptr)
@ stdcall ReleaseMutex(long)
-@ stdcall ReleaseSemaphore(long long ptr)
+;@ stdcall ReleaseMutexWhenCallbackReturns ntdll.TpCallbackReleaseMutexOnCompletion ; Win 7
@ stdcall ReleaseSRWLockExclusive(ptr) ntdll.RtlReleaseSRWLockExclusive
@ stdcall ReleaseSRWLockShared(ptr) ntdll.RtlReleaseSRWLockShared
+@ stdcall ReleaseSemaphore(long long ptr)
+;@ stdcall ReleaseSemaphoreWhenCallbackReturns ntdll.TpCallbackReleaseSemaphoreOnCompletion ; Win 7
@ stdcall RemoveDirectoryA(str)
+;@ stdcall RemoveDirectoryTransactedA ; Win 7
+;@ stdcall RemoveDirectoryTransactedW ; Win 7
@ stdcall RemoveDirectoryW(wstr)
@ stdcall RemoveLocalAlternateComputerNameA(str long)
@ stdcall RemoveLocalAlternateComputerNameW(wstr long)
@ stdcall WriteProfileStringA(str str str)
@ stdcall WriteProfileStringW(wstr wstr wstr)
@ stdcall WriteTapemark(ptr long long long)
-@ stdcall WTSGetActiveConsoleSessionId()
+@ stdcall WTSGetActiveConsoleSessionId() ; missing in win 7
- ;@ stdcall ZombifyActCtx(ptr)
+ @ stdcall ZombifyActCtx(ptr)
-@ stub _DebugOut ; missing in XP SP3
-@ stub _DebugPrintf ; missing in XP SP3
+;@ stdcall -arch=x86_64 __C_specific_handler ntdll.__C_specific_handler
+;@ stdcall -arch=x86_64 __chkstk ntdll.__chkstk
+;@ stdcall -arch=x86_64 __misaligned_access ntdll.__misaligned_access
+@ stub _DebugOut ; missing in XP SP3 and Win 7
+@ stub _DebugPrintf ; missing in XP SP3 and Win 7
@ stdcall _hread(long ptr long)
@ stdcall _hwrite(long ptr long)
@ stdcall _lclose(long)
* Eric Pouech
* Jon Griffiths
* Dmitry Chapyshev (dmitry@reactos.org)
+ * Samuel Serapión
*/
+ /* synched with wine 1.1.26 */
+
#include <k32.h>
- #define NDEBUG
- #include <debug.h>
+ #include "wine/debug.h"
- #define ACTCTX_FLAGS_ALL (\
- ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
- ACTCTX_FLAG_LANGID_VALID |\
- ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
- ACTCTX_FLAG_RESOURCE_NAME_VALID |\
- ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
- ACTCTX_FLAG_APPLICATION_NAME_VALID |\
- ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
- ACTCTX_FLAG_HMODULE_VALID )
+ WINE_DEFAULT_DEBUG_CHANNEL(actctx);
#define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
- #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
- /*
- * @implemented
+ /***********************************************************************
+ * CreateActCtxA (KERNEL32.@)
+ *
+ * Create an activation context.
*/
- BOOL
- WINAPI
- FindActCtxSectionStringA(
- DWORD dwFlags,
- const GUID *lpExtensionGuid,
- ULONG ulSectionId,
- LPCSTR lpStringToFind,
- PACTCTX_SECTION_KEYED_DATA ReturnedData
- )
+ HANDLE WINAPI CreateActCtxA(PCACTCTXA pActCtx)
{
- BOOL bRetVal;
- LPWSTR lpStringToFindW = NULL;
+ ACTCTXW actw;
+ SIZE_T len;
+ HANDLE ret = INVALID_HANDLE_VALUE;
+ LPWSTR src = NULL, assdir = NULL, resname = NULL, appname = NULL;
+
+ TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
- /* Convert lpStringToFind */
- if (lpStringToFind)
+ if (!pActCtx || pActCtx->cbSize != sizeof(*pActCtx))
{
- BasepAnsiStringToHeapUnicodeString(lpStringToFind,
- (LPWSTR*) &lpStringToFindW);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
}
- /* Call the Unicode function */
- bRetVal = FindActCtxSectionStringW(dwFlags,
- lpExtensionGuid,
- ulSectionId,
- lpStringToFindW,
- ReturnedData);
-
- /* Clean up */
- if (lpStringToFindW)
- RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) lpStringToFindW);
-
- return bRetVal;
- }
-
-
- /*
- * @implemented
- */
- HANDLE
- WINAPI
- CreateActCtxA(
- PCACTCTXA pActCtx
- )
- {
- ACTCTXW pActCtxW;
- HANDLE hRetVal;
-
- ZeroMemory(&pActCtxW, sizeof(ACTCTXW));
- pActCtxW.cbSize = sizeof(ACTCTXW);
- pActCtxW.dwFlags = pActCtx->dwFlags;
- pActCtxW.wLangId = pActCtx->wLangId;
- pActCtxW.hModule = pActCtx->hModule;
- pActCtxW.wProcessorArchitecture = pActCtx->wProcessorArchitecture;
-
- pActCtxW.hModule = pActCtx->hModule;
-
- /* Convert ActCtx Strings */
+ actw.cbSize = sizeof(actw);
+ actw.dwFlags = pActCtx->dwFlags;
if (pActCtx->lpSource)
{
- BasepAnsiStringToHeapUnicodeString(pActCtx->lpSource,
- (LPWSTR*) &pActCtxW.lpSource);
+ len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpSource, -1, NULL, 0);
+ src = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!src) return INVALID_HANDLE_VALUE;
+ MultiByteToWideChar(CP_ACP, 0, pActCtx->lpSource, -1, src, len);
}
- if (pActCtx->lpAssemblyDirectory)
+ actw.lpSource = src;
+
+ if (actw.dwFlags & ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID)
+ actw.wProcessorArchitecture = pActCtx->wProcessorArchitecture;
+ if (actw.dwFlags & ACTCTX_FLAG_LANGID_VALID)
+ actw.wLangId = pActCtx->wLangId;
+ if (actw.dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID)
{
- BasepAnsiStringToHeapUnicodeString(pActCtx->lpAssemblyDirectory,
- (LPWSTR*) &pActCtxW.lpAssemblyDirectory);
+ len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpAssemblyDirectory, -1, NULL, 0);
+ assdir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!assdir) goto done;
+ MultiByteToWideChar(CP_ACP, 0, pActCtx->lpAssemblyDirectory, -1, assdir, len);
+ actw.lpAssemblyDirectory = assdir;
}
- if (HIWORD(pActCtx->lpResourceName))
+ if (actw.dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
{
- BasepAnsiStringToHeapUnicodeString(pActCtx->lpResourceName,
- (LPWSTR*) &pActCtxW.lpResourceName);
- }
- else
+ if ((ULONG_PTR)pActCtx->lpResourceName >> 16)
- {
+ {
- pActCtxW.lpResourceName = (LPWSTR) pActCtx->lpResourceName;
+ len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpResourceName, -1, NULL, 0);
+ resname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!resname) goto done;
+ MultiByteToWideChar(CP_ACP, 0, pActCtx->lpResourceName, -1, resname, len);
+ actw.lpResourceName = resname;
- }
+ }
- if (pActCtx->lpApplicationName)
+ else actw.lpResourceName = (LPCWSTR)pActCtx->lpResourceName;
+ }
+ if (actw.dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
{
- BasepAnsiStringToHeapUnicodeString(pActCtx->lpApplicationName,
- (LPWSTR*) &pActCtxW.lpApplicationName);
+ len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpApplicationName, -1, NULL, 0);
+ appname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!appname) goto done;
+ MultiByteToWideChar(CP_ACP, 0, pActCtx->lpApplicationName, -1, appname, len);
+ actw.lpApplicationName = appname;
}
- /* Call the Unicode function */
- hRetVal = CreateActCtxW(&pActCtxW);
+ if (actw.dwFlags & ACTCTX_FLAG_HMODULE_VALID)
+ actw.hModule = pActCtx->hModule;
- /* Clean up */
- RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) pActCtxW.lpSource);
- RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) pActCtxW.lpAssemblyDirectory);
- if (HIWORD(pActCtx->lpResourceName))
- RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) pActCtxW.lpResourceName);
- RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) pActCtxW.lpApplicationName);
+ ret = CreateActCtxW(&actw);
- return hRetVal;
+ done:
+ HeapFree(GetProcessHeap(), 0, src);
+ HeapFree(GetProcessHeap(), 0, assdir);
+ HeapFree(GetProcessHeap(), 0, resname);
+ HeapFree(GetProcessHeap(), 0, appname);
+ return ret;
}
- /*
- * @unimplemented
+ /***********************************************************************
+ * CreateActCtxW (KERNEL32.@)
+ *
+ * Create an activation context.
*/
- BOOL
- WINAPI
- ActivateActCtx(
- HANDLE hActCtx,
- ULONG_PTR *ulCookie
- )
+ HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx)
{
- NTSTATUS Status;
+ NTSTATUS status;
+ HANDLE hActCtx;
- DPRINT("ActivateActCtx(%p %p)\n", hActCtx, ulCookie );
+ TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
- Status = RtlActivateActivationContext(0, hActCtx, ulCookie);
- if (!NT_SUCCESS(Status))
+ if ((status = RtlCreateActivationContext(&hActCtx, (PVOID*)pActCtx)))
{
- SetLastError(RtlNtStatusToDosError(Status));
+ SetLastError(RtlNtStatusToDosError(status));
+ return INVALID_HANDLE_VALUE;
+ }
+ return hActCtx;
+ }
+
+ /***********************************************************************
+ * ActivateActCtx (KERNEL32.@)
+ *
+ * Activate an activation context.
+ */
+ BOOL WINAPI ActivateActCtx(HANDLE hActCtx, ULONG_PTR *ulCookie)
+ {
+ NTSTATUS status;
+
+ if ((status = RtlActivateActivationContext( 0, hActCtx, ulCookie )))
+ {
+ SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}
return TRUE;
return TRUE;
}
- /*
- * @unimplemented
+ /***********************************************************************
+ * FindActCtxSectionGuid (KERNEL32.@)
+ *
+ * Find information about a GUID in an activation context.
*/
- BOOL
- WINAPI
- QueryActCtxW(
- DWORD dwFlags,
- HANDLE hActCtx,
- PVOID pvSubInstance,
- ULONG ulInfoClass,
- PVOID pvBuffer,
- SIZE_T cbBuffer OPTIONAL,
- SIZE_T *pcbWrittenOrRequired OPTIONAL
- )
+ BOOL WINAPI FindActCtxSectionGuid(DWORD dwFlags, const GUID* lpExtGuid,
+ ULONG ulId, const GUID* lpSearchGuid,
+ PACTCTX_SECTION_KEYED_DATA pInfo)
{
- DPRINT("%s() is UNIMPLEMENTED!\n", __FUNCTION__);
- /* this makes Adobe Photoshop 7.0 happy */
+ FIXME("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid),
+ ulId, debugstr_guid(lpSearchGuid), pInfo);
- SetLastError( ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ SetLastError( ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
}
- /*
- * @unimplemented
+ /***********************************************************************
+ * QueryActCtxW (KERNEL32.@)
+ *
+ * Get information about an activation context.
*/
- VOID
- WINAPI
- ReleaseActCtx(
- HANDLE hActCtx
- )
+ BOOL WINAPI QueryActCtxW(DWORD dwFlags, HANDLE hActCtx, PVOID pvSubInst,
+ ULONG ulClass, PVOID pvBuff, SIZE_T cbBuff,
+ SIZE_T *pcbLen)
{
- DPRINT("ReleaseActCtx(%p)\n", hActCtx);
- RtlReleaseActivationContext(hActCtx);
- }
+ NTSTATUS status;
- /*
- * @unimplemented
- */
- BOOL
- WINAPI
- ZombifyActCtx(
- HANDLE hActCtx
- )
+ if ((status = RtlQueryInformationActivationContext( dwFlags, hActCtx, pvSubInst, ulClass,
+ pvBuff, cbBuff, pcbLen )))
- {
+{
- NTSTATUS Status;
- DPRINT("ZombifyActCtx(%p)\n", hActCtx);
-
- Status = RtlZombifyActivationContext(hActCtx);
- if (!NT_SUCCESS(Status))
- {
- SetLastError(RtlNtStatusToDosError(Status));
+ SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}
-
return TRUE;
}
TRACE("module = %p, id = %08x\n", module, id );
if (!module) module = GetModuleHandleW( NULL );
- Status = RtlFindMessage( module, (ULONG) RT_MESSAGETABLE, lang, id, &mre );
+ Status = RtlFindMessage( module, (ULONG_PTR) RT_MESSAGETABLE, lang, id, &mre );
if (!NT_SUCCESS(Status))
+ {
+ SetLastError( RtlNtStatusToDosError(Status) );
return NULL;
+ }
if (mre->Flags & MESSAGE_RESOURCE_UNICODE)
{
TRACE("module = %p, id = %08x\n", module, id );
if (!module) module = GetModuleHandleW( NULL );
- Status = RtlFindMessage( module, (ULONG) RT_MESSAGETABLE, lang, id, &mre );
+ Status = RtlFindMessage( module, (ULONG_PTR) RT_MESSAGETABLE, lang, id, &mre );
if (!NT_SUCCESS(Status))
+ {
+ SetLastError( RtlNtStatusToDosError(Status) );
return NULL;
+ }
if (mre->Flags & MESSAGE_RESOURCE_UNICODE)
{
/* Get the TEB */
Status = NtQueryInformationThread(hThread,
- ThreadBasicIformation,
+ ThreadBasicInformation,
&ThreadBasicInfo,
sizeof(ThreadBasicInfo),
- NULL);
-
+ &retLen);
+ if (NT_SUCCESS(Status))
+ {
- /* Allocate the Activation Context Stack */
- Status = RtlAllocateActivationContextStack(&ActivationContextStack);
+ /* Allocate the Activation Context Stack */
+ Status = RtlAllocateActivationContextStack(&ActivationContextStack);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
- Teb = ThreadBasicInfo.TebBaseAddress;
-
- /* Save it */
- Teb->ActivationContextStackPointer = ActivationContextStack;
-
- /* Query the Context */
- Status = RtlQueryInformationActivationContext(1,
- 0,
- NULL,
- ActivationContextBasicInformation,
- &ActivationCtxInfo,
- sizeof(ActivationCtxInfo),
+ Teb = ThreadBasicInfo.TebBaseAddress;
+
+ /* Save it */
+ Teb->ActivationContextStackPointer = ActivationContextStack;
+
+ /* Query the Context */
+ Status = RtlQueryInformationActivationContext(1,
+ 0,
+ NULL,
+ ActivationContextBasicInformation,
+ &ActivationCtxInfo,
+ sizeof(ActivationCtxInfo),
- NULL);
-
+ &retLen);
+ if (NT_SUCCESS(Status))
+ {
- /* Does it need to be activated? */
- if (!ActivationCtxInfo.hActCtx)
- {
- /* Activate it */
+ /* Does it need to be activated? */
+ if (!ActivationCtxInfo.hActCtx)
+ {
+ /* Activate it */
- Status = RtlActivateActivationContextEx(1,
- Teb,
+ Status = RtlActivateActivationContext(1,
- ActivationCtxInfo.hActCtx,
- &Cookie);
+ ActivationCtxInfo.hActCtx,
+ &Cookie);
+ if (!NT_SUCCESS(Status))
+ DPRINT1("RtlActivateActivationContext failed %x\n", Status);
- }
- }
++ }
++ }
+ else
+ DPRINT1("RtlQueryInformationActivationContext failed %x\n", Status);
}
+ else
+ DPRINT1("RtlAllocateActivationContextStack failed %x\n", Status);
}
#endif
return This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
if(wFlags == DISPATCH_CONSTRUCT) {
- FIXME("DISPATCH_CONSTRUCT not implemented\n");
- return E_NOTIMPL;
+ if(id == DISPID_VALUE) {
+ if(This->data->vtbl && This->data->vtbl->value) {
+ return This->data->vtbl->value(This->outer, lcid, wFlags, pdp,
+ pvarRes, pei, pspCaller);
- }
++ }
+ FIXME("DISPATCH_CONSTRUCT flag but missing value function\n");
+ return E_FAIL;
+ }
+ FIXME("DISPATCH_CONSTRUCT flag without DISPID_VALUE\n");
+ return E_FAIL;
}
if(is_dynamic_dispid(id)) {
if(FAILED(hres))
return hres;
- doc->nscontainer = NSContainer_Create(doc, NULL);
- list_init(&doc->bindings);
- doc->usermode = UNKNOWN_USERMODE;
- doc->readystate = READYSTATE_UNINITIALIZED;
-
- if(doc->nscontainer) {
- nsresult nsres;
- nsres = nsIWebBrowser_GetContentDOMWindow(doc->nscontainer->webbrowser, &nswindow);
- if(NS_FAILED(nsres))
- ERR("GetContentDOMWindow failed: %08x\n", nsres);
+ nsres = nsIWebBrowser_GetContentDOMWindow(doc->nscontainer->webbrowser, &nswindow);
+ if(NS_FAILED(nsres))
+ ERR("GetContentDOMWindow failed: %08x\n", nsres);
- }
- hres = HTMLWindow_Create(doc, nswindow, &doc->basedoc.window);
+ hres = HTMLWindow_Create(doc, nswindow, NULL /* FIXME */, &doc->basedoc.window);
if(nswindow)
nsIDOMWindow_Release(nswindow);
if(FAILED(hres)) {
TRACE("(%p)->(%p)\n", This, p);
- if(!This->content_window) {
- nsIDOMHTMLDocument *nshtmldoc;
- HTMLDocumentNode *content_doc;
- nsIDOMDocument *nsdoc;
- HTMLWindow *window;
- nsresult nsres;
- HRESULT hres;
-
- nsres = nsIDOMHTMLIFrameElement_GetContentDocument(This->nsiframe, &nsdoc);
- if(NS_FAILED(nsres)) {
- ERR("GetContentDocument failed: %08x\n", nsres);
- return E_FAIL;
- }
-
- if(!nsdoc) {
- FIXME("NULL contentDocument\n");
- return E_FAIL;
- }
-
- nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMHTMLDocument, (void**)&nshtmldoc);
- nsIDOMDocument_Release(nsdoc);
- if(NS_FAILED(nsres)) {
- ERR("Could not get nsIDOMHTMLDocument iface: %08x\n", nsres);
- return E_FAIL;
- }
-
- hres = create_content_window(This, nshtmldoc, &window);
- if(FAILED(hres)) {
- nsIDOMHTMLDocument_Release(nshtmldoc);
- return E_FAIL;
+ if(This->framebase.content_window) {
+ IHTMLWindow2_AddRef(HTMLWINDOW2(This->framebase.content_window));
+ *p = HTMLWINDOW2(This->framebase.content_window);
+ }else {
+ WARN("NULL content window\n");
+ *p = NULL;
- }
+ }
-
- hres = create_doc_from_nsdoc(nshtmldoc, This->element.node.doc->basedoc.doc_obj, window, &content_doc);
- nsIDOMHTMLDocument_Release(nshtmldoc);
- if(SUCCEEDED(hres))
- window_set_docnode(window, content_doc);
- else
- IHTMLWindow2_Release(HTMLWINDOW2(window));
- htmldoc_release(&content_doc->basedoc);
- if(FAILED(hres))
- return hres;
-
- This->content_window = window;
- }
-
- IHTMLWindow2_AddRef(HTMLWINDOW2(This->content_window));
- *p = HTMLWINDOW2(This->content_window);
return S_OK;
}
static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
{
HTMLLocation *This = HTMLLOCATION_THIS(iface);
- FIXME("(%p)->(%s)\n", This, debugstr_w(v));
- return E_NOTIMPL;
+
+ TRACE("(%p)->(%s)\n", This, debugstr_w(v));
+
+ if(!This->window || !This->window->doc) {
+ FIXME("No document available\n");
+ return E_FAIL;
- }
++}
+
+ return navigate_url(This->window->doc, v);
}
static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p)
if(FAILED(hres))
return hres;
- *p = SysAllocString(url);
- return *p ? S_OK : E_OUTOFMEMORY;
+ switch(url.nScheme) {
+ case INTERNET_SCHEME_FILE:
+ {
+ /* prepend a slash */
+ url_path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR));
+ if(!url_path)
+ return E_OUTOFMEMORY;
+ url_path[0] = '/';
+ memcpy(url_path + 1, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR));
+ url.lpszUrlPath = url_path;
+ url.dwUrlPathLength = url.dwUrlPathLength + 1;
- }
++}
+ break;
+
+ case INTERNET_SCHEME_HTTP:
+ case INTERNET_SCHEME_HTTPS:
+ case INTERNET_SCHEME_FTP:
+ if(!url.dwUrlPathLength) {
+ /* add a slash if it's blank */
+ url_path = url.lpszUrlPath = HeapAlloc(GetProcessHeap(), 0, 1 * sizeof(WCHAR));
+ if(!url.lpszUrlPath)
+ return E_OUTOFMEMORY;
+ url.lpszUrlPath[0] = '/';
+ url.dwUrlPathLength = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* replace \ with / */
+ for(i = 0; i < url.dwUrlPathLength; ++i)
+ if(url.lpszUrlPath[i] == '\\')
+ url.lpszUrlPath[i] = '/';
+
+ if(InternetCreateUrlW(&url, ICU_ESCAPE, NULL, &len)) {
+ FIXME("InternetCreateUrl succeeded with NULL buffer?\n");
+ ret = E_FAIL;
+ goto cleanup;
+ }
+
+ if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
+ SetLastError(0);
+ ret = E_FAIL;
+ goto cleanup;
+ }
+ SetLastError(0);
+
+ buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if(!buf) {
+ ret = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ if(!InternetCreateUrlW(&url, ICU_ESCAPE, buf, &len)) {
+ FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
+ SetLastError(0);
+ ret = E_FAIL;
+ goto cleanup;
+ }
+
+ *p = SysAllocStringLen(buf, len);
+ if(!*p) {
+ ret = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ ret = S_OK;
+
+ cleanup:
+ HeapFree(GetProcessHeap(), 0, buf);
+ HeapFree(GetProcessHeap(), 0, url_path);
+
+ return ret;
}
static HRESULT WINAPI HTMLLocation_put_protocol(IHTMLLocation *iface, BSTR v)
if(!p)
return E_POINTER;
- return E_NOTIMPL;
+ url.dwSchemeLength = 1;
+ hres = get_url_components(This, &url);
+ if(FAILED(hres))
+ return hres;
+
+ if(!url.dwSchemeLength) {
+ FIXME("Unexpected blank protocol\n");
- }
+ return E_NOTIMPL;
+ }else {
+ WCHAR buf[url.dwSchemeLength + 1];
+ memcpy(buf, url.lpszScheme, url.dwSchemeLength * sizeof(WCHAR));
+ buf[url.dwSchemeLength] = ':';
+ *p = SysAllocStringLen(buf, url.dwSchemeLength + 1);
++}
+ if(!*p)
+ return E_OUTOFMEMORY;
+ return S_OK;
}
static HRESULT WINAPI HTMLLocation_put_host(IHTMLLocation *iface, BSTR v)
if(!p)
return E_POINTER;
- return E_NOTIMPL;
+ url.dwHostNameLength = 1;
+ hres = get_url_components(This, &url);
+ if(FAILED(hres))
+ return hres;
+
+ if(!url.dwHostNameLength){
+ *p = NULL;
+ return S_OK;
- }
++}
+
+ if(url.nPort) {
+ /* <hostname>:<port> */
+ const WCHAR format[] = {'%','d',0};
+ DWORD len = url.dwHostNameLength + 1 + 5 + 1;
+ WCHAR buf[len];
+
+ memcpy(buf, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR));
+ buf[url.dwHostNameLength] = ':';
+ snprintfW(buf + url.dwHostNameLength + 1, 6, format, url.nPort);
+ *p = SysAllocString(buf);
+ }else
+ *p = SysAllocStringLen(url.lpszHostName, url.dwHostNameLength);
+
+ if(!*p)
+ return E_OUTOFMEMORY;
+ return S_OK;
}
static HRESULT WINAPI HTMLLocation_put_hostname(IHTMLLocation *iface, BSTR v)
if(!p)
return E_POINTER;
- return E_NOTIMPL;
+ url.dwHostNameLength = 1;
+ hres = get_url_components(This, &url);
+ if(FAILED(hres))
+ return hres;
+
+ if(!url.dwHostNameLength){
+ *p = NULL;
+ return S_OK;
- }
++}
+
+ *p = SysAllocStringLen(url.lpszHostName, url.dwHostNameLength);
+ if(!*p)
+ return E_OUTOFMEMORY;
+ return S_OK;
}
static HRESULT WINAPI HTMLLocation_put_port(IHTMLLocation *iface, BSTR v)
if(!p)
return E_POINTER;
- return E_NOTIMPL;
+ hres = get_url_components(This, &url);
+ if(FAILED(hres))
+ return hres;
+
+ if(url.nPort) {
+ const WCHAR format[] = {'%','d',0};
+ WCHAR buf[6];
+ snprintfW(buf, 6, format, url.nPort);
+ *p = SysAllocString(buf);
+ }else {
+ const WCHAR empty[] = {0};
+ *p = SysAllocString(empty);
- }
++}
+
+ if(!*p)
+ return E_OUTOFMEMORY;
+ return S_OK;
}
static HRESULT WINAPI HTMLLocation_put_pathname(IHTMLLocation *iface, BSTR v)
if(!p)
return E_POINTER;
- return E_NOTIMPL;
+ url.dwExtraInfoLength = 1;
+ hres = get_url_components(This, &url);
+ if(FAILED(hres))
+ return hres;
+
+ if(!url.dwExtraInfoLength){
+ *p = NULL;
+ return S_OK;
- }
++}
+
+ url.dwExtraInfoLength = strcspnW(url.lpszExtraInfo, hash);
+
+ *p = SysAllocStringLen(url.lpszExtraInfo, url.dwExtraInfoLength);
+
+ if(!*p)
+ return E_OUTOFMEMORY;
+ return S_OK;
}
static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
if(!p)
return E_POINTER;
- return E_NOTIMPL;
+ url.dwExtraInfoLength = 1;
+ hres = get_url_components(This, &url);
+ if(FAILED(hres))
+ return hres;
+
+ if(!url.dwExtraInfoLength){
+ *p = NULL;
+ return S_OK;
- }
++}
+
+ hash_pos = strcspnW(url.lpszExtraInfo, hash);
+ url.dwExtraInfoLength -= hash_pos;
+
+ *p = SysAllocStringLen(url.lpszExtraInfo + hash_pos, url.dwExtraInfoLength);
+
+ if(!*p)
+ return E_OUTOFMEMORY;
+ return S_OK;
}
static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL flag)
static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
{
HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ nsIDOMNode *nssibling = NULL;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
+ if(nssibling) {
+ *p = HTMLDOMNODE(get_node(This->doc, nssibling, TRUE));
+ IHTMLDOMNode_AddRef(*p);
+ }else {
+ *p = NULL;
- }
++}
+
+ return S_OK;
}
#undef HTMLDOMNODE_THIS
TRACE("(%p)->(%p)\n", This, p);
- *p = (IDispatch*)HTMLDOC(&This->doc->basedoc);
- IDispatch_AddRef(*p);
+ /* FIXME: Better check for document node */
+ if(This == &This->doc->node) {
+ *p = NULL;
+ }else {
+ *p = (IDispatch*)HTMLDOC(&This->doc->basedoc);
+ IDispatch_AddRef(*p);
+ }
return S_OK;
}
node->ref = 1;
node->doc = doc;
- nsIDOMNode_AddRef(nsnode);
+ if(nsnode)
+ nsIDOMNode_AddRef(nsnode);
node->nsnode = nsnode;
node->next = doc->nodes;
window->doc = doc_node;
if(doc_node)
htmldoc_addref(&doc_node->basedoc);
- }
+
+ if(window->doc_obj && window->doc_obj->basedoc.window == window) {
+ if(window->doc_obj->basedoc.doc_node)
+ htmldoc_release(&window->doc_obj->basedoc.doc_node->basedoc);
+ window->doc_obj->basedoc.doc_node = doc_node;
+ if(doc_node)
+ htmldoc_addref(&doc_node->basedoc);
++}
+ }
+
+ nsIDOMWindow *get_nsdoc_window(nsIDOMDocument *nsdoc)
+ {
+ nsIDOMDocumentView *nsdocview;
+ nsIDOMAbstractView *nsview;
+ nsIDOMWindow *nswindow;
+ nsresult nsres;
+
+ nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMDocumentView, (void**)&nsdocview);
+ nsIDOMDocument_Release(nsdoc);
+ if(NS_FAILED(nsres)) {
+ ERR("Could not get nsIDOMDocumentView iface: %08x\n", nsres);
+ return NULL;
+ }
+
+ nsres = nsIDOMDocumentView_GetDefaultView(nsdocview, &nsview);
+ nsIDOMDocumentView_Release(nsview);
+ if(NS_FAILED(nsres)) {
+ ERR("GetDefaultView failed: %08x\n", nsres);
+ return NULL;
+ }
+
+ nsres = nsIDOMAbstractView_QueryInterface(nsview, &IID_nsIDOMWindow, (void**)&nswindow);
+ nsIDOMAbstractView_Release(nsview);
+ if(NS_FAILED(nsres)) {
+ ERR("Coult not get nsIDOMWindow iface: %08x\n", nsres);
+ return NULL;
+ }
+
+ return nswindow;
+ }
+
+ static void release_children(HTMLWindow *This)
+ {
+ HTMLWindow *child;
+
+ while(!list_empty(&This->children)) {
+ child = LIST_ENTRY(list_tail(&This->children), HTMLWindow, sibling_entry);
+
+ list_remove(&child->sibling_entry);
+ child->parent = NULL;
+ IHTMLWindow2_Release(HTMLWINDOW2(child));
+ }
}
#define HTMLWINDOW2_THIS(iface) DEFINE_THIS(HTMLWindow, HTMLWindow2, iface)
static HRESULT WINAPI HTMLWindow2_get_length(IHTMLWindow2 *iface, LONG *p)
{
HTMLWindow *This = HTMLWINDOW2_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ nsIDOMWindowCollection *nscollection;
+ PRUint32 length;
+ nsresult nsres;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ nsres = nsIDOMWindow_GetFrames(This->nswindow, &nscollection);
+ if(NS_FAILED(nsres)) {
+ ERR("GetFrames failed: %08x\n", nsres);
+ return E_FAIL;
- }
++}
+
+ nsres = nsIDOMWindowCollection_GetLength(nscollection, &length);
+ nsIDOMWindowCollection_Release(nscollection);
+ if(NS_FAILED(nsres)) {
+ ERR("GetLength failed: %08x\n", nsres);
+ return E_FAIL;
+ }
+
+ *p = length;
+ return S_OK;
}
static HRESULT WINAPI HTMLWindow2_get_frames(IHTMLWindow2 *iface, IHTMLFramesCollection2 **p)
static HRESULT WINAPI HTMLWindow2_get_name(IHTMLWindow2 *iface, BSTR *p)
{
HTMLWindow *This = HTMLWINDOW2_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ nsAString name_str;
+ nsresult nsres;
+ HRESULT hres;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ nsAString_Init(&name_str, NULL);
+ nsres = nsIDOMWindow_GetName(This->nswindow, &name_str);
+ if(NS_SUCCEEDED(nsres)) {
+ const PRUnichar *name;
+
+ nsAString_GetData(&name_str, &name);
+ if(*name) {
+ *p = SysAllocString(name);
+ hres = *p ? S_OK : E_OUTOFMEMORY;
+ }else {
+ *p = NULL;
+ hres = S_OK;
- }
++}
+ }else {
+ ERR("GetName failed: %08x\n", nsres);
+ hres = E_FAIL;
+ }
+ nsAString_Finish(&name_str);
+
+ return hres;
}
static HRESULT WINAPI HTMLWindow2_get_parent(IHTMLWindow2 *iface, IHTMLWindow2 **p)
if(idx >= This->global_prop_cnt)
return DISP_E_MEMBERNOTFOUND;
- disp = get_script_disp(This->global_props[idx].script_host);
+ prop = This->global_props+idx;
+
+ switch(prop->type) {
+ case GLOBAL_SCRIPTVAR: {
+ IDispatchEx *dispex;
+ IDispatch *disp;
+
+ disp = get_script_disp(prop->script_host);
- if(!disp)
- return E_UNEXPECTED;
+ if(!disp)
+ return E_UNEXPECTED;
- hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
- if(SUCCEEDED(hres)) {
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
- TRACE("%s >>>\n", debugstr_w(This->global_props[idx].name));
- hres = IDispatchEx_InvokeEx(dispex, This->global_props[idx].id, lcid, flags, params, res, ei, caller);
+ TRACE("%s >>>\n", debugstr_w(prop->name));
+ hres = IDispatchEx_InvokeEx(dispex, prop->id, lcid, flags, params, res, ei, caller);
- if(hres == S_OK)
+ if(hres == S_OK)
- TRACE("%s <<<\n", debugstr_w(This->global_props[idx].name));
+ TRACE("%s <<<\n", debugstr_w(prop->name));
- else
+ else
- WARN("%s <<< %08x\n", debugstr_w(This->global_props[idx].name), hres);
+ WARN("%s <<< %08x\n", debugstr_w(prop->name), hres);
- IDispatchEx_Release(dispex);
- }else {
- FIXME("No IDispatchEx\n");
- }
+ IDispatchEx_Release(dispex);
+ }else {
+ FIXME("No IDispatchEx\n");
+ }
+ IDispatch_Release(disp);
+ break;
+ }
+ case GLOBAL_ELEMENTVAR: {
+ IHTMLElement *elem;
+
+ hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), prop->name, &elem);
+ if(FAILED(hres))
- return hres;
++ return hres;
+
+ if(!elem)
+ return DISP_E_MEMBERNOTFOUND;
+
+ V_VT(res) = VT_DISPATCH;
+ V_DISPATCH(res) = (IDispatch*)elem;
+ break;
- }
++}
+ default:
+ ERR("invalid type %d\n", prop->type);
+ hres = DISP_E_MEMBERNOTFOUND;
+ }
- IDispatch_Release(disp);
return hres;
}
}
if(find_global_prop(This, bstrName, grfdex, &script_host, &id)) {
- if(This->global_prop_cnt == This->global_prop_size) {
- global_prop_t *new_props;
- DWORD new_size;
-
- if(This->global_props) {
- new_size = This->global_prop_size*2;
- new_props = heap_realloc(This->global_props, new_size*sizeof(global_prop_t));
- }else {
- new_size = 16;
- new_props = heap_alloc(new_size*sizeof(global_prop_t));
- }
- if(!new_props)
+ global_prop_t *prop;
+
+ prop = alloc_global_prop(This, GLOBAL_SCRIPTVAR, bstrName);
+ if(!prop)
- return E_OUTOFMEMORY;
+ return E_OUTOFMEMORY;
- This->global_props = new_props;
- This->global_prop_size = new_size;
+
+ prop->script_host = script_host;
+ prop->id = id;
+
+ *pid = prop_to_dispid(This, prop);
+ return S_OK;
- }
+ }
- This->global_props[This->global_prop_cnt].name = heap_strdupW(bstrName);
- if(!This->global_props[This->global_prop_cnt].name)
- return E_OUTOFMEMORY;
+ hres = IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
+ if(hres != DISP_E_UNKNOWNNAME)
+ return hres;
- This->global_props[This->global_prop_cnt].script_host = script_host;
- This->global_props[This->global_prop_cnt].id = id;
+ if(This->doc) {
+ global_prop_t *prop;
+ IHTMLElement *elem;
+
+ hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), bstrName, &elem);
+ if(SUCCEEDED(hres) && elem) {
+ IHTMLElement_Release(elem);
+
+ prop = alloc_global_prop(This, GLOBAL_ELEMENTVAR, bstrName);
+ if(!prop)
- return E_OUTOFMEMORY;
++ return E_OUTOFMEMORY;
- *pid = MSHTML_DISPID_CUSTOM_MIN + (This->global_prop_cnt++);
+ *pid = prop_to_dispid(This, prop);
- return S_OK;
- }
+ return S_OK;
+ }
+ }
- return IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
+ return DISP_E_UNKNOWNNAME;
}
static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
if(!tmp)
return;
- nscontainer->mutation_queue = tmp->next;
+ doc->mutation_queue = tmp->next;
if(!tmp->next)
- nscontainer->mutation_queue_tail = NULL;
+ doc->mutation_queue_tail = NULL;
- nsISupports_Release(tmp->nsiface);
+ if(tmp->nsiface)
+ nsISupports_Release(tmp->nsiface);
heap_free(tmp);
}
push_mutation_queue(This, MUTATION_COMMENT, (nsISupports*)nscomment);
nsIDOMComment_Release(nscomment);
- add_script_runner(This);
+ }
+
+ nsres = nsISupports_QueryInterface(aContent, &IID_nsIDOMHTMLIFrameElement, (void**)&nsiframe);
+ if(NS_SUCCEEDED(nsres)) {
+ TRACE("iframe node\n");
+
+ push_mutation_queue(This, MUTATION_IFRAME, (nsISupports*)nsiframe);
+ nsIDOMHTMLIFrameElement_Release(nsiframe);
- }
++}
+
+ nsres = nsISupports_QueryInterface(aContent, &IID_nsIDOMHTMLFrameElement, (void**)&nsframe);
+ if(NS_SUCCEEDED(nsres)) {
+ TRACE("frame node\n");
+
+ push_mutation_queue(This, MUTATION_FRAME, (nsISupports*)nsframe);
+ nsIDOMHTMLFrameElement_Release(nsframe);
}
}
nsDocumentObserver_DoneAddingChildren
};
- void init_mutation(NSContainer *nscontainer)
+ void init_mutation(HTMLDocumentNode *doc)
+ {
+ nsIDOMNSDocument *nsdoc;
+ nsresult nsres;
+
+ doc->lpIDocumentObserverVtbl = &nsDocumentObserverVtbl;
+ doc->lpIRunnableVtbl = &nsRunnableVtbl;
+
+ nsres = nsIDOMHTMLDocument_QueryInterface(doc->nsdoc, &IID_nsIDOMNSDocument, (void**)&nsdoc);
+ if(NS_FAILED(nsres)) {
+ ERR("Could not get nsIDOMNSDocument: %08x\n", nsres);
+ return;
- }
++}
+
+ nsIDOMNSDocument_WineAddObserver(nsdoc, NSDOCOBS(doc));
+ nsIDOMNSDocument_Release(nsdoc);
+ }
+
+ void release_mutation(HTMLDocumentNode *doc)
{
- nscontainer->lpDocumentObserverVtbl = &nsDocumentObserverVtbl;
- nscontainer->lpRunnableVtbl = &nsRunnableVtbl;
+ nsIDOMNSDocument *nsdoc;
+ nsresult nsres;
+
+ nsres = nsIDOMHTMLDocument_QueryInterface(doc->nsdoc, &IID_nsIDOMNSDocument, (void**)&nsdoc);
+ if(NS_FAILED(nsres)) {
+ ERR("Could not get nsIDOMNSDocument: %08x\n", nsres);
+ return;
+ }
+
+ nsIDOMNSDocument_WineRemoveObserver(nsdoc, NSDOCOBS(doc));
+ nsIDOMNSDocument_Release(nsdoc);
}
on_start_nsrequest(This);
- /* events are reset when a new document URI is loaded, so re-initialise them here */
- if(This->bsc.doc && This->bsc.doc->doc_obj->bscallback == This && This->bsc.doc->doc_obj->nscontainer) {
- update_nsdocument(This->bsc.doc->doc_obj);
- init_nsevents(This->bsc.doc->doc_obj->nscontainer);
+ if(This->window)
+ update_window_doc(This->window);
- }
+ }
- }
This->bsc.readed += This->nsstream->buf_size;
if(!hlnf && !exec_shldocvw_67(doc, uri))
return FALSE;
- hres = IOleClientSite_QueryInterface(doc->client, &IID_IServiceProvider,
- (void**)&service_provider);
- if(SUCCEEDED(hres)) {
- IHlinkFrame *hlink_frame;
-
- hres = IServiceProvider_QueryService(service_provider, &IID_IHlinkFrame,
- &IID_IHlinkFrame, (void**)&hlink_frame);
- IServiceProvider_Release(service_provider);
- if(SUCCEEDED(hres)) {
- hlink_frame_navigate(&doc->basedoc, hlink_frame, uri, channel->post_data_stream, hlnf);
- IHlinkFrame_Release(hlink_frame);
-
- return FALSE;
+ hres = hlink_frame_navigate(&doc->basedoc, uri, channel->post_data_stream, hlnf);
+ return hres != S_OK;
-}
+ }
- }
-
- return TRUE;
- }
#define NSCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, HttpChannel, iface)
return NULL;
}
- nsIWineURI_GetNSContainer(wine_uri, &container);
+ nsIWineURI_GetWindow(wine_uri, &window);
nsIWineURI_Release(wine_uri);
- return container;
+ return window;
}
- static nsresult async_open_doc_uri(nsChannel *This, NSContainer *container,
- nsIStreamListener *listener, nsISupports *context, BOOL *open)
+ static HTMLWindow *get_channel_window(nsChannel *This)
{
- IMoniker *mon;
- HRESULT hres;
+ nsIRequestObserver *req_observer;
+ nsIWebProgress *web_progress;
+ nsIDOMWindow *nswindow;
+ HTMLWindow *window;
+ nsresult nsres;
- *open = FALSE;
+ if(!This->load_group) {
+ ERR("NULL load_group\n");
+ return NULL;
+ }
- if(container->bscallback) {
- channelbsc_set_channel(container->bscallback, This, listener, context);
+ nsres = nsILoadGroup_GetGroupObserver(This->load_group, &req_observer);
+ if(NS_FAILED(nsres) || !req_observer) {
+ ERR("GetGroupObserver failed: %08x\n", nsres);
+ return NULL;
+ }
- if(container->doc && container->doc->mime) {
- heap_free(This->content_type);
- This->content_type = heap_strdupWtoA(container->doc->mime);
+ nsres = nsIRequestObserver_QueryInterface(req_observer, &IID_nsIWebProgress, (void**)&web_progress);
+ nsIRequestObserver_Release(req_observer);
+ if(NS_FAILED(nsres)) {
+ ERR("Could not get nsIWebProgress iface: %08x\n", nsres);
+ return NULL;
- }
+ }
- return NS_OK;
- }else {
- BOOL cont = before_async_open(This, container);
-
- if(!cont) {
- TRACE("canceled\n");
- return NS_ERROR_UNEXPECTED;
+ nsres = nsIWebProgress_GetDOMWindow(web_progress, &nswindow);
+ nsIWebProgress_Release(web_progress);
+ if(NS_FAILED(nsres) || !nswindow) {
+ ERR("GetDOMWindow failed: %08x\n", nsres);
+ return NULL;
- }
+ }
- if(!container->doc) {
- return This->channel
- ? nsIChannel_AsyncOpen(This->channel, listener, context)
- : NS_ERROR_UNEXPECTED;
+ window = nswindow_to_window(nswindow);
+ nsIDOMWindow_Release(nswindow);
+
+ if(window)
+ IHTMLWindow2_AddRef(HTMLWINDOW2(window));
+ else
+ FIXME("NULL window for %p\n", nswindow);
+ return window;
-}
+ }
- hres = create_mon_for_nschannel(This, &mon);
- if(FAILED(hres)) {
- return NS_ERROR_UNEXPECTED;
+ typedef struct {
+ task_t header;
+ HTMLDocumentNode *doc;
+ nsChannelBSC *bscallback;
+ } start_binding_task_t;
+
+ static void start_binding_proc(task_t *_task)
+ {
+ start_binding_task_t *task = (start_binding_task_t*)_task;
+
+ start_binding(NULL, task->doc, (BSCallback*)task->bscallback, NULL);
-}
+ }
- set_current_mon(&container->doc->basedoc, mon);
- }
- *open = TRUE;
- return NS_OK;
+ typedef struct {
+ task_t header;
+ HTMLWindow *window;
+ nsChannelBSC *bscallback;
+ } start_doc_binding_task_t;
+
+ static void start_doc_binding_proc(task_t *_task)
+ {
+ start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
+
+ start_binding(task->window, NULL, (BSCallback*)task->bscallback, NULL);
+ IUnknown_Release((IUnknown*)task->bscallback);
}
- static nsresult async_open(nsChannel *This, NSContainer *container, nsIStreamListener *listener,
+ static nsresult async_open(nsChannel *This, HTMLWindow *window, BOOL is_doc_channel, nsIStreamListener *listener,
nsISupports *context)
{
nsChannelBSC *bscallback;
channelbsc_set_channel(bscallback, This, listener, context);
- task = heap_alloc(sizeof(task_t));
+ if(is_doc_channel) {
+ start_doc_binding_task_t *task;
- task->doc = &container->doc->basedoc;
- task->task_id = TASK_START_BINDING;
- task->next = NULL;
+ set_window_bscallback(window, bscallback);
+
+ task = heap_alloc(sizeof(start_doc_binding_task_t));
+ task->window = window;
- task->bscallback = bscallback;
+ task->bscallback = bscallback;
+ push_task(&task->header, start_doc_binding_proc, window->task_magic);
+ }else {
+ start_binding_task_t *task = heap_alloc(sizeof(start_binding_task_t));
- push_task(task);
+ task->doc = window->doc;
+ task->bscallback = bscallback;
+ push_task(&task->header, start_binding_proc, window->doc->basedoc.task_magic);
+ }
return NS_OK;
}
return S_OK;
}
- static void set_downloading(HTMLDocumentObj *doc)
+ void parse_complete(HTMLDocumentObj *doc)
{
- IOleCommandTarget *olecmd;
- HRESULT hres;
-
TRACE("(%p)\n", doc);
- if(doc->frame)
- IOleInPlaceFrame_SetStatusText(doc->frame, NULL /* FIXME */);
-
- if(!doc->client)
- return;
-
- hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
- if(SUCCEEDED(hres)) {
- VARIANT var;
-
- V_VT(&var) = VT_I4;
- V_I4(&var) = 1;
-
- IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETDOWNLOADSTATE, OLECMDEXECOPT_DONTPROMPTUSER,
- &var, NULL);
- IOleCommandTarget_Release(olecmd);
- }
-
- if(doc->hostui) {
- IDropTarget *drop_target = NULL;
-
- hres = IDocHostUIHandler_GetDropTarget(doc->hostui, NULL /* FIXME */, &drop_target);
- if(drop_target) {
- FIXME("Use IDropTarget\n");
- IDropTarget_Release(drop_target);
- }
-}
+ }
- }
-
- /* Calls undocumented 69 cmd of CGID_Explorer */
- static void call_explorer_69(HTMLDocumentObj *doc)
- {
- IOleCommandTarget *olecmd;
- VARIANT var;
- HRESULT hres;
-
- if(!doc->client)
- return;
-
- hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
- if(FAILED(hres))
- return;
-
- VariantInit(&var);
- hres = IOleCommandTarget_Exec(olecmd, &CGID_Explorer, 69, 0, NULL, &var);
- IOleCommandTarget_Release(olecmd);
- if(SUCCEEDED(hres) && V_VT(&var) != VT_NULL)
- FIXME("handle result\n");
- }
-
- static void set_parsecomplete(HTMLDocument *doc)
- {
- IOleCommandTarget *olecmd = NULL;
-
- TRACE("(%p)\n", doc);
-
- if(doc->doc_obj->usermode == EDITMODE)
- init_editor(doc);
-
- call_explorer_69(doc->doc_obj);
- call_property_onchanged(&doc->cp_propnotif, 1005);
- call_explorer_69(doc->doc_obj);
-
- /* FIXME: IE7 calls EnableModelless(TRUE), EnableModelless(FALSE) and sets interactive state here */
-
- doc->doc_obj->readystate = READYSTATE_INTERACTIVE;
- call_property_onchanged(&doc->cp_propnotif, DISPID_READYSTATE);
-
- if(doc->doc_obj->client)
- IOleClientSite_QueryInterface(doc->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
-
- if(olecmd) {
- VARIANT state, progress;
-
- V_VT(&progress) = VT_I4;
- V_I4(&progress) = 0;
- IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS, OLECMDEXECOPT_DONTPROMPTUSER,
- &progress, NULL);
-
- V_VT(&state) = VT_I4;
- V_I4(&state) = 0;
- IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETDOWNLOADSTATE, OLECMDEXECOPT_DONTPROMPTUSER,
- &state, NULL);
-
- IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 103, 0, NULL, NULL);
- IOleCommandTarget_Exec(olecmd, &CGID_MSHTML, IDM_PARSECOMPLETE, 0, NULL, NULL);
- IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_HTTPEQUIV_DONE, 0, NULL, NULL);
-
- IOleCommandTarget_Release(olecmd);
- }
-
- doc->doc_obj->readystate = READYSTATE_COMPLETE;
- call_property_onchanged(&doc->cp_propnotif, DISPID_READYSTATE);
-
- if(doc->doc_obj->frame) {
- static const WCHAR wszDone[] = {'D','o','n','e',0};
- IOleInPlaceFrame_SetStatusText(doc->doc_obj->frame, wszDone);
- }
-
- update_title(doc->doc_obj);
- }
-
- static void set_progress(HTMLDocument *doc)
- {
- IOleCommandTarget *olecmd = NULL;
- HRESULT hres;
-
- TRACE("(%p)\n", doc);
-
- if(doc->doc_obj->client)
- IOleClientSite_QueryInterface(doc->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
-
- if(olecmd) {
- VARIANT progress_max, progress;
-
- V_VT(&progress_max) = VT_I4;
- V_I4(&progress_max) = 0; /* FIXME */
- IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSMAX, OLECMDEXECOPT_DONTPROMPTUSER,
- &progress_max, NULL);
-
- V_VT(&progress) = VT_I4;
- V_I4(&progress) = 0; /* FIXME */
- IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS, OLECMDEXECOPT_DONTPROMPTUSER,
- &progress, NULL);
- }
-
- if(doc->doc_obj->usermode == EDITMODE && doc->doc_obj->hostui) {
- DOCHOSTUIINFO hostinfo;
-
- memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
- hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
- hres = IDocHostUIHandler_GetHostInfo(doc->doc_obj->hostui, &hostinfo);
- if(SUCCEEDED(hres))
- /* FIXME: use hostinfo */
- TRACE("hostinfo = {%u %08x %08x %s %s}\n",
- hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
- debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
- }
- }
-
- static void task_start_binding(HTMLDocument *doc, BSCallback *bscallback)
- {
- if(doc)
- start_binding(doc, bscallback, NULL);
- IUnknown_Release((IUnknown*)bscallback);
- }
-
- static void process_task(task_t *task)
- {
- switch(task->task_id) {
- case TASK_SETDOWNLOADSTATE:
- set_downloading(task->doc->doc_obj);
- break;
- case TASK_PARSECOMPLETE:
- set_parsecomplete(task->doc);
- break;
- case TASK_SETPROGRESS:
- set_progress(task->doc);
- break;
- case TASK_START_BINDING:
- task_start_binding(task->doc, (BSCallback*)task->bscallback);
- break;
- default:
- ERR("Wrong task_id %d\n", task->task_id);
- }
- }
static void call_timer_disp(IDispatch *disp)
{
return ERROR_FUNCTION_FAILED;
}
- if (!strncmpW(ptr, prefix, prefix_len))
- {
- *flags |= ENV_MOD_APPEND;
- *value += lstrlenW(prefix);
- }
- else if (lstrlenW(*value) >= prefix_len)
+ if (*value)
+ {
+ LPCWSTR ptr = *value;
+ if (!strncmpW(ptr, prefix, prefix_len))
+ {
+ *flags |= ENV_MOD_APPEND;
+ *value += lstrlenW(prefix);
+ }
+ else if (lstrlenW(*value) >= prefix_len)
+ {
+ ptr += lstrlenW(ptr) - prefix_len;
+ if (!lstrcmpW(ptr, prefix))
{
- ptr += lstrlenW(ptr) - prefix_len;
- if (!lstrcmpW(ptr, prefix))
- {
- *flags |= ENV_MOD_PREFIX;
- /* the "[~]" will be removed by deformat_string */;
- }
+ *flags |= ENV_MOD_PREFIX;
+ /* the "[~]" will be removed by deformat_string */;
}
}
++ }
if (check_flag_combo(*flags, ENV_ACT_SETALWAYS | ENV_ACT_SETABSENT) ||
check_flag_combo(*flags, ENV_ACT_REMOVEMATCH | ENV_ACT_SETABSENT) ||
lstrcpyW(newval, value);
}
- TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
- res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
+ if (newval)
+ {
+ TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
+ res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
+ }
+ else
+ res = ERROR_SUCCESS;
done:
if (env) RegCloseKey(env);
UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
{
- FIXME("(%d %s %i %i %p): stub\n", hInstall, debugstr_w(szFeature),
+ MSIPACKAGE *package;
+ MSIFEATURE *feature;
+ UINT ret;
+
+ TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
iCostTree, iState, piCost);
- if (piCost) *piCost = 0;
+
+ package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
+ if (!package)
+ {
+ HRESULT hr;
+ BSTR feature;
+ IWineMsiRemotePackage *remote_package;
+
+ remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
+ if (!remote_package)
+ return ERROR_INVALID_HANDLE;
+
+ feature = SysAllocString(szFeature);
+ if (!feature)
+ {
+ IWineMsiRemotePackage_Release(remote_package);
+ return ERROR_OUTOFMEMORY;
+ }
+
+ hr = IWineMsiRemotePackage_GetFeatureCost(remote_package, feature,
+ iCostTree, iState, piCost);
+
+ SysFreeString(feature);
+ IWineMsiRemotePackage_Release(remote_package);
+
+ if (FAILED(hr))
+ {
+ if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+ return HRESULT_CODE(hr);
+
+ return ERROR_FUNCTION_FAILED;
+ }
+
- return ERROR_SUCCESS;
- }
+ return ERROR_SUCCESS;
+}
+ feature = get_loaded_feature(package, szFeature);
+
+ if (feature)
+ ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
+ else
+ ret = ERROR_UNKNOWN_FEATURE;
+
+ msiobj_release( &package->hdr );
+ return ret;
+ }
+
/***********************************************************************
* MsiSetComponentStateA (MSI.@)
*/
gUIHandlerA(gUIContext, MB_RETRYCANCEL | INSTALLMESSAGE_ERROR, msg);
msi_free(msg);
}
- }
+ else if (gUIHandlerRecord)
+ {
+ MSIHANDLE rec = MsiCreateRecord(1);
+ MsiRecordSetStringW(rec, 0, error);
+ gUIHandlerRecord(gUIContext, MB_RETRYCANCEL | INSTALLMESSAGE_ERROR, rec);
+ MsiCloseHandle(rec);
++ }
}
msi_free(error);
{
INSTALLUI_HANDLERA prev = gUIHandlerA;
- TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
+ TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext);
+
gUIHandlerA = puiHandler;
- gUIFilter = dwMessageFilter;
- gUIContext = pvContext;
+ gUIHandlerW = NULL;
+ gUIFilter = dwMessageFilter;
+ gUIContext = pvContext;
return prev;
}
{
INSTALLUI_HANDLERW prev = gUIHandlerW;
- TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
+ TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext);
+
+ gUIHandlerA = NULL;
gUIHandlerW = puiHandler;
- gUIFilter = dwMessageFilter;
- gUIContext = pvContext;
+ gUIFilter = dwMessageFilter;
+ gUIContext = pvContext;
return prev;
}
static LONG dll_count;
/* the UI level */
-INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
-HWND gUIhwnd = 0;
-INSTALLUI_HANDLERA gUIHandlerA = NULL;
-INSTALLUI_HANDLERW gUIHandlerW = NULL;
+INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
+HWND gUIhwnd = 0;
+INSTALLUI_HANDLERA gUIHandlerA = NULL;
+INSTALLUI_HANDLERW gUIHandlerW = NULL;
+ INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL;
-DWORD gUIFilter = 0;
-LPVOID gUIContext = NULL;
+DWORD gUIFilter = 0;
+LPVOID gUIContext = NULL;
WCHAR gszLogFile[MAX_PATH];
HINSTANCE msi_hInstance;
}
}
- TRACE("(%p %x %x %s)\n", gUIHandlerA, gUIFilter, log_type,
- debugstr_w(message));
+ TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord,
+ gUIFilter, log_type, debugstr_w(message));
/* convert it to ASCII */
- len = WideCharToMultiByte( CP_ACP, 0, message, -1,
- NULL, 0, NULL, NULL );
+ len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
msg = msi_alloc( len );
- WideCharToMultiByte( CP_ACP, 0, message, -1,
- msg, len, NULL, NULL );
+ WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
- if (gUIHandlerA && (gUIFilter & log_type))
+ if (gUIHandlerW && (gUIFilter & log_type))
+ {
+ rc = gUIHandlerW( gUIContext, eMessageType, message );
+ }
+ else if (gUIHandlerA && (gUIFilter & log_type))
{
- rc = gUIHandlerA( gUIContext, eMessageType, msg );
+ rc = gUIHandlerA(gUIContext,eMessageType,msg);
}
+ else if (gUIHandlerRecord && (gUIFilter & log_type))
+ {
+ MSIHANDLE rec = MsiCreateRecord( 1 );
+ MsiRecordSetStringW( rec, 0, message );
+ rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
+ MsiCloseHandle( rec );
+ }
if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
INSTALLMESSAGE_PROGRESS))
}
}
msi_free( msg );
-
- msi_free( message );
+ msi_free( message);
switch (eMessageType & 0xff000000)
{
- <module name="msvcrt" type="win32dll" baseaddress="${BASEADDRESS_MSVCRT}" mangledsymbols="true" installbase="system32" installname="msvcrt.dll" iscrt="yes">
+ <module name="msvcrt" type="win32dll" baseaddress="${BASEADDRESS_MSVCRT}" installbase="system32" installname="msvcrt.dll" iscrt="yes">
- <importlibrary definition="msvcrt.def" />
+ <importlibrary definition="msvcrt-$(ARCH).def" />
<include base="msvcrt">.</include>
<include base="crt">include</include>
<define name="USE_MSVCRT_PREFIX" />
<module name="nddeapi" type="win32dll" baseaddress="${BASEADDRESS_NDDEAPI}" installbase="system32" installname="nddeapi.dll" allowwarnings="true" entrypoint="0">
- <importlibrary definition="nddeapi.spec" />
- <include base="nddeapi">.</include>
- <include base="ReactOS">include/reactos/wine</include>
- <define name="__WINESRC__" />
- <library>wine</library>
- <library>ntdll</library>
- <file>nddeapi.c</file>
+ <importlibrary definition="nddeapi.spec" />
+ <include base="nddeapi">.</include>
+ <include base="ReactOS">include/reactos/wine</include>
+ <define name="__WINESRC__" />
+ <library>wine</library>
- <library>kernel32</library>
+ <library>ntdll</library>
+ <file>nddeapi.c</file>
</module>
<module name="ntdsapi" type="win32dll" baseaddress="${BASEADDRESS_NTDSAPI}" installbase="system32" installname="ntdsapi.dll" allowwarnings="true" entrypoint="0">
- <importlibrary definition="ntdsapi.spec" />
- <include base="ntdsapi">.</include>
- <include base="ReactOS">include/reactos/wine</include>
- <define name="__WINESRC__" />
- <library>wine</library>
- <library>user32</library>
- <library>ntdll</library>
- <file>ntdsapi.c</file>
+ <importlibrary definition="ntdsapi.spec" />
+ <include base="ntdsapi">.</include>
+ <include base="ReactOS">include/reactos/wine</include>
+ <define name="__WINESRC__" />
+ <library>wine</library>
+ <library>user32</library>
- <library>kernel32</library>
+ <library>ntdll</library>
+ <file>ntdsapi.c</file>
</module>
<include base="ReactOS">include/reactos/wine</include>
<define name="__WINESRC__" />
<library>wine</library>
- <library>advapi32</library>
- <library>kernel32</library>
<file>proxyodbc.c</file>
</module>
--</group>
++</group>
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
- <group>
<module name="olecli32" type="win32dll" baseaddress="${BASEADDRESS_OLECLI32}" installbase="system32" installname="olecli32.dll" allowwarnings="true" entrypoint="0">
- <importlibrary definition="olecli32.spec" />
- <include base="olecli32">.</include>
- <include base="ReactOS">include/reactos/wine</include>
- <define name="__WINESRC__" />
- <file>olecli_main.c</file>
- <library>wine</library>
- <library>ole32</library>
- <library>gdi32</library>
- <library>ntdll</library>
+ <importlibrary definition="olecli32.spec" />
+ <include base="olecli32">.</include>
+ <include base="ReactOS">include/reactos/wine</include>
+ <define name="__WINESRC__" />
+ <file>olecli_main.c</file>
+ <library>wine</library>
+ <library>ole32</library>
+ <library>gdi32</library>
- <library>kernel32</library>
+ <library>ntdll</library>
</module>
- </group>
<module name="pdh" type="win32dll" baseaddress="${BASEADDRESS_PDH}" installbase="system32" installname="pdh.dll" allowwarnings="true" entrypoint="0">
- <importlibrary definition="pdh.spec" />
- <include base="pdh">.</include>
- <include base="ReactOS">include/reactos/wine</include>
- <define name="__WINESRC__" />
- <redefine name="_WIN32_WINNT">0x600</redefine>
- <library>wine</library>
- <library>ntdll</library>
- <file>pdh_main.c</file>
+ <importlibrary definition="pdh.spec" />
+ <include base="pdh">.</include>
+ <include base="ReactOS">include/reactos/wine</include>
+ <define name="__WINESRC__" />
+ <redefine name="_WIN32_WINNT">0x600</redefine>
+ <library>wine</library>
- <library>kernel32</library>
+ <library>ntdll</library>
+ <file>pdh_main.c</file>
</module>
<module name="printui" type="win32dll" baseaddress="${BASEADDRESS_PRINTUI}" installbase="system32" installname="printui.dll" allowwarnings="true" entrypoint="0">
- <importlibrary definition="printui.spec" />
- <include base="printui">.</include>
- <include base="ReactOS">include/reactos/wine</include>
- <define name="__WINESRC__" />
- <library>wine</library>
- <library>shell32</library>
- <library>ntdll</library>
- <file>printui.c</file>
- <file>printui.rc</file>
+ <importlibrary definition="printui.spec" />
+ <include base="printui">.</include>
+ <include base="ReactOS">include/reactos/wine</include>
+ <define name="__WINESRC__" />
+ <library>wine</library>
+ <library>shell32</library>
- <library>kernel32</library>
+ <library>ntdll</library>
+ <file>printui.c</file>
+ <file>printui.rc</file>
</module>
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, required ))) return FALSE;
- if (!SetupGetStringFieldA( context, index, buffer, required, NULL )) goto done;
+ if (!(ret = SetupGetStringFieldA( context, index, buffer, required, NULL ))) goto done;
}
- res = strtol( buffer, &end, 0 );
+ /* The call to SetupGetStringFieldA succeeded. If buffer is empty we have an optional field */
+ if (!*buffer) *result = 0;
+ else
+ {
- if (end != buffer && !*end)
+ res = strtol( buffer, &end, 0 );
- {
+ if (end != buffer && !*end) *result = res;
+ else
- *result = res;
- ret = TRUE;
+ {
- }
+ SetLastError( ERROR_INVALID_DATA );
+ ret = FALSE;
++ }
}
- else SetLastError( ERROR_INVALID_DATA );
done:
if (buffer != localbuff) HeapFree( GetProcessHeap(), 0, buffer );
}
--BOOL
++INT_PTR
CALLBACK
FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
{
psfi->dwAttributes = 0xffffffff;
}
- IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
+ if (psfParent)
+ IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
&(psfi->dwAttributes) );
}
GetSystemMetrics( SM_CXICON),
GetSystemMetrics( SM_CYICON),
&psfi->hIcon, 0, 1, 0);
- psfi->iIcon = icon_idx;
- }
+ if (ret != 0 && ret != 0xFFFFFFFF)
+ {
+ IconNotYetLoaded=FALSE;
+ psfi->iIcon = icon_idx;
}
}
}
}
++ }
else
{
if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON),
return 0x80041001;
}
- /* found scheme, set length of remainder */
- y->cchSuffix = lstrlenA(y->pszSuffix);
+ y->pszProtocol = x;
+ y->cchProtocol = ptr-x;
+ y->pszSuffix = ptr+1;
+ y->cchSuffix = strlen(y->pszSuffix);
- len = MultiByteToWideChar(CP_ACP, 0, y->pszProtocol, y->cchProtocol,
+ len = MultiByteToWideChar(CP_ACP, 0, x, ptr-x,
- scheme, sizeof(scheme)/sizeof(WCHAR));
+ scheme, sizeof(scheme)/sizeof(WCHAR));
y->nScheme = get_scheme_code(scheme, len);
return S_OK;
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
- <group>
<module name="sxs" type="win32dll" baseaddress="${BASEADDRESS_SXS}" installbase="system32" installname="sxs.dll" allowwarnings="true" entrypoint="0">
- <importlibrary definition="sxs.spec" />
- <include base="sxs">.</include>
- <include base="ReactOS">include/reactos/wine</include>
- <define name="__WINESRC__" />
- <file>sxs.c</file>
- <library>wine</library>
- <library>ntdll</library>
+ <importlibrary definition="sxs.spec" />
+ <include base="sxs">.</include>
+ <include base="ReactOS">include/reactos/wine</include>
+ <define name="__WINESRC__" />
+ <file>sxs.c</file>
+ <library>wine</library>
- <library>kernel32</library>
+ <library>ntdll</library>
</module>
- </group>
}
else /* Not a popup */
{
- if (*str == 0)
- flags = MF_SEPARATOR;
+ if(!unicode)
+ {
+ if (*str == 0)
+ flags = MF_SEPARATOR;
+ }
+ else
+ {
+ if (*(LPCWSTR)str == 0)
+ flags = MF_SEPARATOR;
+ }
if (flags & MF_SEPARATOR)
{
<module name="winfax" type="win32dll" baseaddress="${BASEADDRESS_WINFAX}" installbase="system32" installname="winfax.dll" allowwarnings="true" entrypoint="0">
- <importlibrary definition="winfax.spec" />
- <include base="winfax">.</include>
- <library>ntdll</library>
- <file>winfax.c</file>
- <file>winfax.rc</file>
+ <importlibrary definition="winfax.spec" />
+ <include base="winfax">.</include>
- <library>kernel32</library>
+ <library>ntdll</library>
+ <file>winfax.c</file>
+ <file>winfax.rc</file>
- </module>
+ </module>
UrlComponents.dwHostNameLength = hostNameLen;
UrlComponents.dwUrlPathLength = pathLen;
- rc = InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents);
-
- /* discard the webpage off the end of the path */
- if (pathLen > 0 && path[pathLen-1] != '/')
- {
- LPWSTR ptr;
- ptr = strrchrW(path,'/');
- if (ptr)
- *(++ptr) = 0;
- else
- {
- path[0] = '/';
- path[1] = 0;
+ return InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents);
-}
+ }
- }
- return rc;
- }
/* match a domain. domain must match if the domain is not NULL. path must match if the path is not NULL */
static BOOL COOKIE_matchDomain(LPCWSTR lpszCookieDomain, LPCWSTR lpszCookiePath,
}
if (lpszCookiePath)
{
- INT len;
TRACE("comparing paths: %s with %s\n", debugstr_w(lpszCookiePath), debugstr_w(searchDomain->lpCookiePath));
- /* paths match at the beginning. so a path of /foo would match
- * /foobar and /foo/bar
- */
if (!searchDomain->lpCookiePath)
return FALSE;
- if (allow_partial)
- {
- len = lstrlenW(searchDomain->lpCookiePath);
- if (strncmpiW(searchDomain->lpCookiePath, lpszCookiePath, len)!=0)
+ if (strcmpW(lpszCookiePath, searchDomain->lpCookiePath))
- return FALSE;
- }
+ return FALSE;
+ }
- else if (strcmpW(lpszCookiePath, searchDomain->lpCookiePath))
- return FALSE;
-
- }
return TRUE;
}
}
if (!thisCookieDomain)
- {
- if (!expired)
- thisCookieDomain = COOKIE_addDomain(domain, path);
+ thisCookieDomain = COOKIE_addDomain(domain, path);
- else
- {
- HeapFree(GetProcessHeap(),0,data);
- if (value != data) HeapFree(GetProcessHeap(), 0, value);
- return TRUE;
- }
- }
if ((thisCookie = COOKIE_findCookie(thisCookieDomain, cookie_name)))
COOKIE_deleteCookie(thisCookie, FALSE);
*/
static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
{
- http_request_t *lpwhr;
- http_session_t *lpwhs = NULL;
- appinfo_t *hIC = NULL;
- BOOL ret = FALSE;
+ LPWININETHTTPREQW lpwhr;
+ LPWININETHTTPSESSIONW lpwhs = NULL;
+ LPWININETAPPINFOW hIC = NULL;
LPWSTR p;
- lpwhr = (http_request_t*) WININET_GetObject( hRequest );
+ lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
if (NULL == lpwhr)
- return FALSE;
+ return FALSE;
lpwhs = lpwhr->lpHttpSession;
if (NULL == lpwhs)
}
/***********************************************************************
- * WININET_SetAuthorization
+ * WININET_SetProxyAuthorization
*/
- static BOOL WININET_SetAuthorization( HINTERNET hRequest, LPWSTR username,
- LPWSTR password, BOOL proxy )
+ static BOOL WININET_SetProxyAuthorization( HINTERNET hRequest,
+ LPWSTR username, LPWSTR password )
{
- http_request_t *lpwhr;
- http_session_t *lpwhs;
- BOOL ret = FALSE;
- LPWSTR p, q;
+ LPWININETHTTPREQW lpwhr;
+ LPWININETHTTPSESSIONW lpwhs;
+ LPWININETAPPINFOW hIC;
+ LPWSTR p;
- lpwhr = (http_request_t*) WININET_GetObject( hRequest );
+ lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
if( !lpwhr )
- return FALSE;
-
+ return FALSE;
+
lpwhs = lpwhr->lpHttpSession;
if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto done;
+ return FALSE;
}
- p = heap_strdupW(username);
- if( !p )
- goto done;
-
- q = heap_strdupW(password);
- if( !q )
- {
- HeapFree(GetProcessHeap(), 0, username);
- goto done;
- }
+ hIC = lpwhs->lpAppInfo;
- if (proxy)
- {
- appinfo_t *hIC = lpwhs->lpAppInfo;
+ p = HeapAlloc( GetProcessHeap(), 0, (strlenW( username ) + 1)*sizeof(WCHAR) );
+ if( !p )
+ return FALSE;
-
+
- HeapFree(GetProcessHeap(), 0, hIC->lpszProxyUsername);
+ lstrcpyW( p, username );
- hIC->lpszProxyUsername = p;
+ hIC->lpszProxyUsername = p;
- HeapFree(GetProcessHeap(), 0, hIC->lpszProxyPassword);
- hIC->lpszProxyPassword = q;
- }
- else
- {
- HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
- lpwhs->lpszUserName = p;
-
- HeapFree(GetProcessHeap(), 0, lpwhs->lpszPassword);
- lpwhs->lpszPassword = q;
- }
+ p = HeapAlloc( GetProcessHeap(), 0, (strlenW( password ) + 1)*sizeof(WCHAR) );
+ if( !p )
+ return FALSE;
-
+
- ret = TRUE;
+ lstrcpyW( p, password );
+ hIC->lpszProxyPassword = p;
- done:
- WININET_Release( &lpwhr->hdr );
- return ret;
+ return TRUE;
}
/***********************************************************************
switch( dwError )
{
case ERROR_SUCCESS:
- case ERROR_INTERNET_INCORRECT_PASSWORD:
- if( !dwError && !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
+ if( !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
return 0;
-
dwStatus = WININET_GetConnectionStatus( hRequest );
- switch (dwStatus)
- {
- case HTTP_STATUS_PROXY_AUTH_REQ:
+ if( HTTP_STATUS_PROXY_AUTH_REQ != dwStatus )
+ return ERROR_SUCCESS;
- return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
- hWnd, WININET_ProxyPasswordDialog, (LPARAM) ¶ms );
+ return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
+ hWnd, WININET_ProxyPasswordDialog, (LPARAM) ¶ms );
- case HTTP_STATUS_DENIED:
- return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_AUTHDLG ),
- hWnd, WININET_PasswordDialog, (LPARAM) ¶ms );
- default:
- WARN("unhandled status %u\n", dwStatus);
- return 0;
- }
+
+ case ERROR_INTERNET_INCORRECT_PASSWORD:
+ return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
+ hWnd, WININET_ProxyPasswordDialog, (LPARAM) ¶ms );
case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
case ERROR_INTERNET_INVALID_CA:
return bSuccess;
}
-
+ /***********************************************************************
+ * FtpOpenFileA (WININET.@)
+ *
+ * Open a remote file for writing or reading
+ *
+ * RETURNS
+ * HINTERNET handle on success
+ * NULL on failure
+ *
+ */
+ HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
+ LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
+ DWORD_PTR dwContext)
+ {
+ LPWSTR lpwzFileName;
+ HINTERNET ret;
++
+ lpwzFileName = lpszFileName?WININET_strdup_AtoW(lpszFileName):NULL;
+ ret = FtpOpenFileW(hFtpSession, lpwzFileName, fdwAccess, dwFlags, dwContext);
+ HeapFree(GetProcessHeap(), 0, lpwzFileName);
+ return ret;
+ }
+
+
+ static void AsyncFtpOpenFileProc(WORKREQUEST *workRequest)
+ {
+ struct WORKREQ_FTPOPENFILEW const *req = &workRequest->u.FtpOpenFileW;
+ LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+
+ TRACE("%p\n", lpwfs);
+
+ FTP_FtpOpenFileW(lpwfs, req->lpszFilename,
+ req->dwAccess, req->dwFlags, req->dwContext);
+ HeapFree(GetProcessHeap(), 0, req->lpszFilename);
+ }
+
+ /***********************************************************************
+ * FtpOpenFileW (WININET.@)
+ *
+ * Open a remote file for writing or reading
+ *
+ * RETURNS
+ * HINTERNET handle on success
+ * NULL on failure
+ *
+ */
+ HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession,
+ LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
+ DWORD_PTR dwContext)
+ {
+ LPWININETFTPSESSIONW lpwfs;
+ LPWININETAPPINFOW hIC = NULL;
+ HINTERNET r = NULL;
+
+ TRACE("(%p,%s,0x%08x,0x%08x,0x%08lx)\n", hFtpSession,
+ debugstr_w(lpszFileName), fdwAccess, dwFlags, dwContext);
+
+ lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
+ if (!lpwfs)
+ {
+ INTERNET_SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (WH_HFTPSESSION != lpwfs->hdr.htype)
+ {
+ INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
+ goto lend;
+ }
+
+ if ((!lpszFileName) ||
+ ((fdwAccess != GENERIC_READ) && (fdwAccess != GENERIC_WRITE)) ||
+ ((dwFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY))
+ {
+ INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+ goto lend;
+ }
+
+ if (lpwfs->download_in_progress != NULL)
+ {
+ INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
+ goto lend;
+ }
+
+ hIC = lpwfs->lpAppInfo;
+ if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ WORKREQUEST workRequest;
+ struct WORKREQ_FTPOPENFILEW *req;
+
+ workRequest.asyncproc = AsyncFtpOpenFileProc;
+ workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
+ req = &workRequest.u.FtpOpenFileW;
+ req->lpszFilename = WININET_strdupW(lpszFileName);
+ req->dwAccess = fdwAccess;
+ req->dwFlags = dwFlags;
+ req->dwContext = dwContext;
+
+ INTERNET_AsyncCall(&workRequest);
+ r = NULL;
+ }
+ else
+ {
+ r = FTP_FtpOpenFileW(lpwfs, lpszFileName, fdwAccess, dwFlags, dwContext);
+ }
+
+ lend:
+ WININET_Release( &lpwfs->hdr );
+
+ return r;
+ }
+
/***********************************************************************
* FTPFILE_Destroy(internal)
&iar, sizeof(INTERNET_ASYNC_RESULT));
}
- if(bSuccess) {
- FTP_ReceiveRequestData(lpwh, TRUE);
- }else {
- iar.dwResult = 0;
- iar.dwError = INTERNET_GetLastError();
+ iar.dwResult = (DWORD)bSuccess;
+ iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
- SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
- &iar, sizeof(INTERNET_ASYNC_RESULT));
- }
+ SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+ &iar, sizeof(INTERNET_ASYNC_RESULT));
+ }
- }
lend:
if( lpwh )
05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz
*/
else if(isdigit(pszToken[0]) && 8 == strlen(pszToken)) {
- int mon, mday, year, hour, min;
lpfp->permissions = 0xFFFF; /* No idea, put full permission :-) */
- sscanf(pszToken, "%d-%d-%d", &mon, &mday, &year);
- lpfp->tmLastModified.wDay = mday;
- lpfp->tmLastModified.wMonth = mon;
- lpfp->tmLastModified.wYear = year;
+ sscanf(pszToken, "%d-%d-%d",
+ &lpfp->tmLastModified.tm_mon,
+ &lpfp->tmLastModified.tm_mday,
+ &lpfp->tmLastModified.tm_year);
/* Hacky and bad Y2K protection :-) */
- if (lpfp->tmLastModified.wYear < 70) lpfp->tmLastModified.wYear += 2000;
+ if (lpfp->tmLastModified.tm_year < 70)
+ lpfp->tmLastModified.tm_year += 100;
-
+
pszToken = strtok(NULL, szSpace);
if(!pszToken) continue;
- sscanf(pszToken, "%d:%d", &hour, &min);
- lpfp->tmLastModified.wHour = hour;
- lpfp->tmLastModified.wMinute = min;
+ sscanf(pszToken, "%d:%d",
+ &lpfp->tmLastModified.tm_hour,
+ &lpfp->tmLastModified.tm_min);
if((pszToken[5] == 'P') && (pszToken[6] == 'M')) {
- lpfp->tmLastModified.wHour += 12;
+ lpfp->tmLastModified.tm_hour += 12;
}
- lpfp->tmLastModified.wSecond = 0;
+ lpfp->tmLastModified.tm_sec = 0;
- TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n",
- lpfp->tmLastModified.wHour, lpfp->tmLastModified.wMinute, lpfp->tmLastModified.wSecond,
- lpfp->tmLastModified.wYear, lpfp->tmLastModified.wMonth, lpfp->tmLastModified.wDay);
+ TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
+ lpfp->tmLastModified.tm_hour, lpfp->tmLastModified.tm_min, lpfp->tmLastModified.tm_sec,
+ (lpfp->tmLastModified.tm_year >= 100) ? lpfp->tmLastModified.tm_year - 100 : lpfp->tmLastModified.tm_year,
+ lpfp->tmLastModified.tm_mon, lpfp->tmLastModified.tm_mday);
-
+
pszToken = strtok(NULL, szSpace);
if(!pszToken) continue;
if(!strcasecmp(pszToken, "<DIR>")) {
int i;
LPCWSTR next_token;
- if (string)
- {
- /* empty string has no tokens */
- if (*string)
- tokens++;
- /* count tokens */
- for (i = 0; string[i]; i++)
- if (!strncmpW(string+i, token_string, strlenW(token_string)))
- {
- DWORD j;
+ /* empty string has no tokens */
+ if (*string)
tokens++;
- /* we want to skip over separators, but not the null terminator */
- for (j = 0; j < strlenW(token_string) - 1; j++)
- if (!string[i+j])
- break;
- i += j;
- }
+ /* count tokens */
+ for (i = 0; string[i]; i++)
- {
+ if (!strncmpW(string+i, token_string, strlenW(token_string)))
+ {
+ DWORD j;
+ tokens++;
+ /* we want to skip over separators, but not the null terminator */
+ for (j = 0; j < strlenW(token_string) - 1; j++)
+ if (!string[i+j])
+ break;
+ i += j;
+ }
- }
- }
/* add 1 for terminating NULL */
token_array = HeapAlloc(GetProcessHeap(), 0, (tokens+1) * sizeof(*token_array));
return requestString;
}
- static void HTTP_ProcessCookies( http_request_t *lpwhr )
+ static void HTTP_ProcessCookies( LPWININETHTTPREQW lpwhr )
{
+ static const WCHAR szSet_Cookie[] = { 'S','e','t','-','C','o','o','k','i','e',0 };
int HeaderIndex;
- int numCookies = 0;
LPHTTPHEADERW setCookieHeader;
- while((HeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSet_Cookie, numCookies, FALSE)) != -1)
- {
+ HeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSet_Cookie, 0, FALSE);
+ if (HeaderIndex == -1)
+ return;
- setCookieHeader = &lpwhr->pCustHeaders[HeaderIndex];
+ setCookieHeader = &lpwhr->pCustHeaders[HeaderIndex];
- if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && setCookieHeader->lpszValue)
- {
+ if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && setCookieHeader->lpszValue)
+ {
- int len;
- static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','%','s',0};
+ int nPosStart = 0, nPosEnd = 0, len;
+ static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','/',0};
+
+ while (setCookieHeader->lpszValue[nPosEnd] != '\0')
+ {
+ LPWSTR buf_cookie, cookie_name, cookie_data;
LPWSTR buf_url;
+ LPWSTR domain = NULL;
LPHTTPHEADERW Host;
- Host = HTTP_GetHeader(lpwhr, hostW);
- len = lstrlenW(Host->lpszValue) + 9 + lstrlenW(lpwhr->lpszPath);
- buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- sprintfW(buf_url, szFmt, Host->lpszValue, lpwhr->lpszPath);
- InternetSetCookieW(buf_url, NULL, setCookieHeader->lpszValue);
-
- HeapFree(GetProcessHeap(), 0, buf_url);
- }
- numCookies++;
- }
- }
-
- static void strip_spaces(LPWSTR start)
+ int nEqualPos = 0;
+ while (setCookieHeader->lpszValue[nPosEnd] != ';' && setCookieHeader->lpszValue[nPosEnd] != ',' &&
+ setCookieHeader->lpszValue[nPosEnd] != '\0')
- {
+{
- LPWSTR str = start;
- LPWSTR end;
-
- while (*str == ' ' && *str != '\0')
- str++;
-
- if (str != start)
- memmove(start, str, sizeof(WCHAR) * (strlenW(str) + 1));
-
- end = start + strlenW(start) - 1;
- while (end >= start && *end == ' ')
- {
- *end = '\0';
- end--;
+ nPosEnd++;
- }
+ }
- }
-
- static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue, LPWSTR *pszRealm )
+ if (setCookieHeader->lpszValue[nPosEnd] == ';')
- {
+{
- static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
- static const WCHAR szRealm[] = {'r','e','a','l','m'}; /* Note: not nul-terminated */
- BOOL is_basic;
- is_basic = !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) &&
- ((pszAuthValue[ARRAYSIZE(szBasic)] == ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]);
- if (is_basic && pszRealm)
+ /* fixme: not case sensitive, strcasestr is gnu only */
+ int nDomainPosEnd = 0;
+ int nDomainPosStart = 0, nDomainLength = 0;
+ static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0};
+ LPWSTR lpszDomain = strstrW(&setCookieHeader->lpszValue[nPosEnd], szDomain);
+ if (lpszDomain)
+ { /* they have specified their own domain, lets use it */
+ while (lpszDomain[nDomainPosEnd] != ';' && lpszDomain[nDomainPosEnd] != ',' &&
+ lpszDomain[nDomainPosEnd] != '\0')
- {
+ {
- LPCWSTR token;
- LPCWSTR ptr = &pszAuthValue[ARRAYSIZE(szBasic)];
- LPCWSTR realm;
- ptr++;
- *pszRealm=NULL;
- token = strchrW(ptr,'=');
- if (!token)
- return TRUE;
- realm = ptr;
- while (*realm == ' ' && *realm != '\0')
- realm++;
- if(!strncmpiW(realm, szRealm, ARRAYSIZE(szRealm)) &&
- (realm[ARRAYSIZE(szRealm)] == ' ' || realm[ARRAYSIZE(szRealm)] == '='))
- {
- token++;
- while (*token == ' ' && *token != '\0')
- token++;
- if (*token == '\0')
- return TRUE;
- *pszRealm = heap_strdupW(token);
- strip_spaces(*pszRealm);
+ nDomainPosEnd++;
- }
+ }
+ nDomainPosStart = strlenW(szDomain);
+ nDomainLength = (nDomainPosEnd - nDomainPosStart) + 1;
+ domain = HeapAlloc(GetProcessHeap(), 0, (nDomainLength + 1)*sizeof(WCHAR));
+ lstrcpynW(domain, &lpszDomain[nDomainPosStart], nDomainLength + 1);
- }
- }
+ }
-
- return is_basic;
+}
-
- static void destroy_authinfo( struct HttpAuthInfo *authinfo )
+ if (setCookieHeader->lpszValue[nPosEnd] == '\0') break;
+ buf_cookie = HeapAlloc(GetProcessHeap(), 0, ((nPosEnd - nPosStart) + 1)*sizeof(WCHAR));
+ lstrcpynW(buf_cookie, &setCookieHeader->lpszValue[nPosStart], (nPosEnd - nPosStart) + 1);
+ TRACE("%s\n", debugstr_w(buf_cookie));
+ while (buf_cookie[nEqualPos] != '=' && buf_cookie[nEqualPos] != '\0')
- {
+{
- if (!authinfo) return;
-
- if (SecIsValidHandle(&authinfo->ctx))
- DeleteSecurityContext(&authinfo->ctx);
- if (SecIsValidHandle(&authinfo->cred))
- FreeCredentialsHandle(&authinfo->cred);
-
- HeapFree(GetProcessHeap(), 0, authinfo->auth_data);
- HeapFree(GetProcessHeap(), 0, authinfo->scheme);
- HeapFree(GetProcessHeap(), 0, authinfo);
+ nEqualPos++;
- }
+}
-
- static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR *auth_data)
+ if (buf_cookie[nEqualPos] == '\0' || buf_cookie[nEqualPos + 1] == '\0')
- {
+{
- authorizationData *ad;
- UINT rc = 0;
-
- TRACE("Looking for authorization for %s:%s\n",debugstr_w(host),debugstr_w(realm));
-
- EnterCriticalSection(&authcache_cs);
- LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, authorizationData, entry)
- {
- if (!strcmpiW(host,ad->lpszwHost) && !strcmpW(realm,ad->lpszwRealm))
- {
- TRACE("Authorization found in cache\n");
- *auth_data = HeapAlloc(GetProcessHeap(),0,ad->AuthorizationLen);
- memcpy(*auth_data,ad->lpszAuthorization,ad->AuthorizationLen);
- rc = ad->AuthorizationLen;
+ HeapFree(GetProcessHeap(), 0, buf_cookie);
- break;
- }
+ break;
+ }
- }
- LeaveCriticalSection(&authcache_cs);
- return rc;
- }
- static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len)
- {
- struct list *cursor;
- authorizationData* ad = NULL;
+ cookie_name = HeapAlloc(GetProcessHeap(), 0, (nEqualPos + 1)*sizeof(WCHAR));
+ lstrcpynW(cookie_name, buf_cookie, nEqualPos + 1);
+ cookie_data = &buf_cookie[nEqualPos + 1];
- TRACE("caching authorization for %s:%s = %s\n",debugstr_w(host),debugstr_w(realm),debugstr_an(auth_data,auth_data_len));
+ Host = HTTP_GetHeader(lpwhr,szHost);
+ len = lstrlenW((domain ? domain : (Host?Host->lpszValue:NULL))) +
+ strlenW(lpwhr->lpszPath) + 9;
+ buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
+ sprintfW(buf_url, szFmt, (domain ? domain : (Host?Host->lpszValue:NULL))); /* FIXME PATH!!! */
+ InternetSetCookieW(buf_url, cookie_name, cookie_data);
- EnterCriticalSection(&authcache_cs);
- LIST_FOR_EACH(cursor, &basicAuthorizationCache)
- {
- authorizationData *check = LIST_ENTRY(cursor,authorizationData,entry);
- if (!strcmpiW(host,check->lpszwHost) && !strcmpW(realm,check->lpszwRealm))
- {
- ad = check;
- break;
+ HeapFree(GetProcessHeap(), 0, buf_url);
+ HeapFree(GetProcessHeap(), 0, buf_cookie);
+ HeapFree(GetProcessHeap(), 0, cookie_name);
+ HeapFree(GetProcessHeap(), 0, domain);
+ nPosStart = nPosEnd;
}
}
+ }
- if (ad)
+ static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue )
-{
+ {
- TRACE("Found match in cache, replacing\n");
- HeapFree(GetProcessHeap(),0,ad->lpszAuthorization);
- ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
- memcpy(ad->lpszAuthorization, auth_data, auth_data_len);
- ad->AuthorizationLen = auth_data_len;
- }
- else
- {
- ad = HeapAlloc(GetProcessHeap(),0,sizeof(authorizationData));
- ad->lpszwHost = heap_strdupW(host);
- ad->lpszwRealm = heap_strdupW(realm);
- ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
- memcpy(ad->lpszAuthorization, auth_data, auth_data_len);
- ad->AuthorizationLen = auth_data_len;
- list_add_head(&basicAuthorizationCache,&ad->entry);
- TRACE("authorization cached\n");
+ static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
+ return !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) &&
+ ((pszAuthValue[ARRAYSIZE(szBasic)] == ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]);
-}
+ }
- LeaveCriticalSection(&authcache_cs);
- }
- static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue,
+ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
struct HttpAuthInfo **ppAuthInfo,
- LPWSTR domain_and_username, LPWSTR password,
- LPWSTR host )
+ LPWSTR domain_and_username, LPWSTR password )
{
SECURITY_STATUS sec_status;
struct HttpAuthInfo *pAuthInfo = *ppAuthInfo;
{
int userlen;
int passlen;
- char *auth_data = NULL;
- UINT auth_data_len = 0;
+ char *auth_data;
- TRACE("basic authentication realm %s\n",debugstr_w(szRealm));
+ TRACE("basic authentication\n");
+
+ /* we don't cache credentials for basic authentication, so we can't
+ * retrieve them if the application didn't pass us any credentials */
+ if (!domain_and_username) return FALSE;
- if (!domain_and_username)
- {
- if (host && szRealm)
- auth_data_len = retrieve_cached_basic_authorization(host, szRealm,&auth_data);
- if (auth_data_len == 0)
- {
- HeapFree(GetProcessHeap(),0,szRealm);
- return FALSE;
- }
- }
- else
- {
- userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
- passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
+ userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
+ passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
- /* length includes a nul terminator, which will be re-used for the ':' */
- auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen);
- if (!auth_data)
- return FALSE;
+ /* length includes a nul terminator, which will be re-used for the ':' */
+ auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen);
+ if (!auth_data)
- {
- HeapFree(GetProcessHeap(),0,szRealm);
+ return FALSE;
- }
- WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
- auth_data[userlen] = ':';
- WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
+ auth_data[userlen] = ':';
+ WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
- auth_data_len = userlen + 1 + passlen;
- if (host && szRealm)
- cache_basic_authorization(host, szRealm, auth_data, auth_data_len);
- }
pAuthInfo->auth_data = auth_data;
- pAuthInfo->auth_data_len = auth_data_len;
+ pAuthInfo->auth_data_len = userlen + 1 + passlen;
pAuthInfo->finished = TRUE;
- HeapFree(GetProcessHeap(),0,szRealm);
return TRUE;
}
BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
{
- TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
+ LPINTERNET_BUFFERSA ptr;
+ LPINTERNET_BUFFERSW lpBuffersOutW,ptrW;
+ BOOL rc = FALSE;
- if (lpBuffersOut)
- {
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
+ TRACE("(%p, %p, %08x, %08lx): stub\n", hRequest, lpBuffersOut, dwFlags,
+ dwContext);
- return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
- }
+ ptr = lpBuffersOut;
+ if (ptr)
+ lpBuffersOutW = (LPINTERNET_BUFFERSW)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY, sizeof(INTERNET_BUFFERSW));
+ else
+ lpBuffersOutW = NULL;
- static BOOL HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PTR dwContext)
+ ptrW = lpBuffersOutW;
+ while (ptr)
- {
+{
- BOOL rc = FALSE;
- INT responseLen;
- DWORD dwBufferSize;
- INTERNET_ASYNC_RESULT iar;
-
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+ if (ptr->lpvBuffer && ptr->dwBufferLength)
+ ptrW->lpvBuffer = HeapAlloc(GetProcessHeap(),0,ptr->dwBufferLength);
+ ptrW->dwBufferLength = ptr->dwBufferLength;
+ ptrW->dwBufferTotal= ptr->dwBufferTotal;
- responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
- if (responseLen)
- rc = TRUE;
-
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
+ if (ptr->Next)
+ ptrW->Next = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
+ sizeof(INTERNET_BUFFERSW));
- /* process cookies here. Is this right? */
- HTTP_ProcessCookies(lpwhr);
+ ptr = ptr->Next;
+ ptrW = ptrW->Next;
+ }
- if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
+ rc = HttpEndRequestW(hRequest, lpBuffersOutW, dwFlags, dwContext);
- if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
+ if (lpBuffersOutW)
{
- DWORD dwCode,dwCodeLength = sizeof(DWORD);
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwCode, &dwCodeLength, NULL) &&
- (dwCode == 302 || dwCode == 301 || dwCode == 303))
+ ptrW = lpBuffersOutW;
+ while (ptrW)
{
- WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
- dwBufferSize=sizeof(szNewLocation);
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL))
- {
- if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
- {
- HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
- lpwhr->lpszVerb = heap_strdupW(szGET);
+ LPINTERNET_BUFFERSW ptrW2;
+
+ FIXME("Do we need to translate info out of these buffer?\n");
+
+ HeapFree(GetProcessHeap(),0,ptrW->lpvBuffer);
+ ptrW2 = ptrW->Next;
+ HeapFree(GetProcessHeap(),0,ptrW);
+ ptrW = ptrW2;
- }
- }
+ }
- HTTP_DrainContent(lpwhr);
- if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
- {
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
- new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
- rc = HTTP_HandleRedirect(lpwhr, new_url);
- if (rc)
- rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
- HeapFree( GetProcessHeap(), 0, new_url );
+ }
- }
- }
- }
-
- iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
- iar.dwError = rc ? 0 : INTERNET_GetLastError();
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_REQUEST_COMPLETE, &iar,
- sizeof(INTERNET_ASYNC_RESULT));
return rc;
}
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
if (lpwhr)
WININET_Release( &lpwhr->hdr );
- return FALSE;
+ return FALSE;
}
+
lpwhr->hdr.dwFlags |= dwFlags;
+ lpwhr->hdr.dwContext = dwContext;
- if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- WORKREQUEST work;
- struct WORKREQ_HTTPENDREQUESTW *request;
+ /* We appear to do nothing with lpBuffersOut.. is that correct? */
- work.asyncproc = AsyncHttpEndRequestProc;
- work.hdr = WININET_AddRef( &lpwhr->hdr );
+ SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+
+ responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
+ if (responseLen)
+ rc = TRUE;
- request = &work.u.HttpEndRequestW;
- request->dwFlags = dwFlags;
- request->dwContext = dwContext;
+ SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
- INTERNET_AsyncCall(&work);
- INTERNET_SetLastError(ERROR_IO_PENDING);
+ /* process cookies here. Is this right? */
+ HTTP_ProcessCookies(lpwhr);
+
+ dwBufferSize = sizeof(lpwhr->dwContentLength);
+ if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
+ &lpwhr->dwContentLength,&dwBufferSize,NULL))
+ lpwhr->dwContentLength = -1;
+
+ if (lpwhr->dwContentLength == 0)
+ HTTP_FinishedReading(lpwhr);
+
+ if(!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
+ {
+ DWORD dwCode,dwCodeLength=sizeof(DWORD);
+ if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,NULL) &&
+ (dwCode==302 || dwCode==301))
+ {
+ WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH];
+ dwBufferSize=sizeof(szNewLocation);
+ if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
+ {
+ /* redirects are always GETs */
+ HeapFree(GetProcessHeap(),0,lpwhr->lpszVerb);
+ lpwhr->lpszVerb = WININET_strdupW(szGET);
+ HTTP_DrainContent(lpwhr);
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_REDIRECT, szNewLocation,
+ dwBufferSize);
+ rc = HTTP_HandleRedirect(lpwhr, szNewLocation);
+ if (rc)
+ rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
- }
++ }
+ }
}
- else
- rc = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext);
WININET_Release( &lpwhr->hdr );
TRACE("%i <--\n",rc);
types = lpszAcceptTypes;
while (*types)
{
- __TRY
- {
- /* find out how many there are */
+ /* find out how many there are */
- if (*types && **types)
+ if (((ULONG_PTR)*types >> 16) && **types)
- {
- TRACE("accept type: %s\n", debugstr_a(*types));
- acceptTypesCount++;
- }
+ {
+ TRACE("accept type: %s\n", debugstr_a(*types));
+ acceptTypesCount++;
+ }
- }
- __EXCEPT_PAGE_FAULT
- {
- WARN("invalid accept type pointer\n");
- }
- __ENDTRY;
types++;
}
szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1));
if(lpwhr->hCacheFile)
CloseHandle(lpwhr->hCacheFile);
- HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
+ if(lpwhr->lpszCacheFile) {
+ DeleteFileW(lpwhr->lpszCacheFile); /* FIXME */
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
+ }
- DeleteCriticalSection( &lpwhr->read_section );
WININET_Release(&lpwhr->lpHttpSession->hdr);
- destroy_authinfo(lpwhr->pAuthInfo);
- destroy_authinfo(lpwhr->pProxyAuthInfo);
-
HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders);
if (!NETCON_connected(&lpwhr->netConnection))
return;
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
-
- NETCON_close(&lpwhr->netConnection);
-
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
- }
-
- static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
+ if (lpwhr->pAuthInfo)
- {
+{
- LPHTTPHEADERW host_header;
-
- static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
-
- host_header = HTTP_GetHeader(req, hostW);
- if(!host_header)
- return FALSE;
-
- sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
- return TRUE;
+ if (SecIsValidHandle(&lpwhr->pAuthInfo->ctx))
+ DeleteSecurityContext(&lpwhr->pAuthInfo->ctx);
+ if (SecIsValidHandle(&lpwhr->pAuthInfo->cred))
+ FreeCredentialsHandle(&lpwhr->pAuthInfo->cred);
+
+ HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->auth_data);
+ HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->scheme);
+ HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo);
+ lpwhr->pAuthInfo = NULL;
- }
+}
-
- static BOOL HTTP_KeepAlive(http_request_t *lpwhr)
+ if (lpwhr->pProxyAuthInfo)
- {
+{
- WCHAR szVersion[10];
- WCHAR szConnectionResponse[20];
- DWORD dwBufferSize = sizeof(szVersion);
- BOOL keepalive = FALSE;
+ if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->ctx))
+ DeleteSecurityContext(&lpwhr->pProxyAuthInfo->ctx);
+ if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->cred))
+ FreeCredentialsHandle(&lpwhr->pProxyAuthInfo->cred);
- /* as per RFC 2068, S8.1.2.1, if the client is HTTP/1.1 then assume that
- * the connection is keep-alive by default */
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion,
- &dwBufferSize, NULL) &&
- !strcmpiW(szVersion, g_szHttp1_1))
- {
- keepalive = TRUE;
+ HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->auth_data);
+ HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->scheme);
+ HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo);
+ lpwhr->pProxyAuthInfo = NULL;
}
- dwBufferSize = sizeof(szConnectionResponse);
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_PROXY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) ||
- HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL))
- {
- keepalive = !strcmpiW(szConnectionResponse, szKeepAlive);
- }
-
- return keepalive;
- }
-
- static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
- {
- http_request_t *req = (http_request_t*)hdr;
-
- switch(option) {
- case INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO:
- {
- http_session_t *lpwhs = req->lpHttpSession;
- INTERNET_DIAGNOSTIC_SOCKET_INFO *info = buffer;
-
- FIXME("INTERNET_DIAGNOSTIC_SOCKET_INFO stub\n");
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
- if (*size < sizeof(INTERNET_DIAGNOSTIC_SOCKET_INFO))
- return ERROR_INSUFFICIENT_BUFFER;
- *size = sizeof(INTERNET_DIAGNOSTIC_SOCKET_INFO);
- /* FIXME: can't get a SOCKET from our connection since we don't use
- * winsock
- */
- info->Socket = 0;
- /* FIXME: get source port from req->netConnection */
- info->SourcePort = 0;
- info->DestPort = lpwhs->nHostPort;
- info->Flags = 0;
- if (HTTP_KeepAlive(req))
- info->Flags |= IDSI_FLAG_KEEP_ALIVE;
- if (lpwhs->lpAppInfo->lpszProxy && lpwhs->lpAppInfo->lpszProxy[0] != 0)
- info->Flags |= IDSI_FLAG_PROXY;
- if (req->netConnection.useSSL)
- info->Flags |= IDSI_FLAG_SECURE;
+ NETCON_close(&lpwhr->netConnection);
- return ERROR_SUCCESS;
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
-}
+ }
- case INTERNET_OPTION_SECURITY_FLAGS:
+ static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
-{
+ {
- http_session_t *lpwhs;
- lpwhs = req->lpHttpSession;
-
- if (*size < sizeof(ULONG))
- return ERROR_INSUFFICIENT_BUFFER;
-
- *size = sizeof(DWORD);
- if (lpwhs->hdr.dwFlags & INTERNET_FLAG_SECURE)
- *(DWORD*)buffer = SECURITY_FLAG_SECURE;
- else
- *(DWORD*)buffer = 0;
- FIXME("Semi-STUB INTERNET_OPTION_SECURITY_FLAGS: %x\n",*(DWORD*)buffer);
- return ERROR_SUCCESS;
- }
+ WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
+ switch(option) {
case INTERNET_OPTION_HANDLE_TYPE:
TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
return ERROR_INTERNET_INVALID_OPTION;
}
- /* read some more data into the read buffer (the read section must be held) */
- static BOOL read_more_data( http_request_t *req, int maxlen )
+ static DWORD HTTP_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
{
- int len;
-
- if (req->read_pos)
- {
- /* move existing data to the start of the buffer */
- if(req->read_size)
- memmove( req->read_buf, req->read_buf + req->read_pos, req->read_size );
- req->read_pos = 0;
- }
+ int bytes_read;
- if (maxlen == -1) maxlen = sizeof(req->read_buf);
-
- if(!NETCON_recv( &req->netConnection, req->read_buf + req->read_size,
- maxlen - req->read_size, 0, &len ))
- return FALSE;
-
- req->read_size += len;
- return TRUE;
- }
+ if(!NETCON_recv(&req->netConnection, buffer, min(size, req->dwContentLength - req->dwContentRead),
+ sync ? MSG_WAITALL : 0, &bytes_read)) {
+ if(req->dwContentLength != -1 && req->dwContentRead != req->dwContentLength)
+ ERR("not all data received %d/%d\n", req->dwContentRead, req->dwContentLength);
- /* remove some amount of data from the read buffer (the read section must be held) */
- static void remove_data( http_request_t *req, int count )
- {
- if (!(req->read_size -= count)) req->read_pos = 0;
- else req->read_pos += count;
+ /* always return success, even if the network layer returns an error */
+ *read = 0;
+ HTTP_FinishedReading(req);
+ return ERROR_SUCCESS;
- }
+}
- static BOOL read_line( http_request_t *req, LPSTR buffer, DWORD *len )
- {
- int count, bytes_read, pos = 0;
+ req->dwContentRead += bytes_read;
+ *read = bytes_read;
- EnterCriticalSection( &req->read_section );
- for (;;)
- {
- BYTE *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size );
+ if(req->lpszCacheFile) {
+ BOOL res;
+ DWORD dwBytesWritten;
- if (eol)
- {
- count = eol - (req->read_buf + req->read_pos);
- bytes_read = count + 1;
+ res = WriteFile(req->hCacheFile, buffer, bytes_read, &dwBytesWritten, NULL);
+ if(!res)
+ WARN("WriteFile failed: %u\n", GetLastError());
- }
+ }
- else count = bytes_read = req->read_size;
- count = min( count, *len - pos );
- memcpy( buffer + pos, req->read_buf + req->read_pos, count );
- pos += count;
- remove_data( req, bytes_read );
- if (eol) break;
+ if(!bytes_read && (req->dwContentRead == req->dwContentLength))
+ HTTP_FinishedReading(req);
- if (!read_more_data( req, -1 ) || !req->read_size)
- {
- *len = 0;
- TRACE( "returning empty string\n" );
- LeaveCriticalSection( &req->read_section );
- return FALSE;
+ return ERROR_SUCCESS;
-}
+ }
- }
- LeaveCriticalSection( &req->read_section );
- if (pos < *len)
+ static DWORD get_chunk_size(const char *buffer)
-{
+ {
- if (pos && buffer[pos - 1] == '\r') pos--;
- *len = pos + 1;
- }
- buffer[*len - 1] = 0;
- TRACE( "returning %s\n", debugstr_a(buffer));
- return TRUE;
- }
+ const char *p;
+ DWORD size = 0;
- /* discard data contents until we reach end of line (the read section must be held) */
- static BOOL discard_eol( http_request_t *req )
+ for (p = buffer; *p; p++)
- {
+{
- do
- {
- BYTE *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size );
- if (eol)
- {
- remove_data( req, (eol + 1) - (req->read_buf + req->read_pos) );
- break;
+ if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0';
+ else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10;
+ else if (*p == ';') break;
- }
+ }
- req->read_pos = req->read_size = 0; /* discard everything */
- if (!read_more_data( req, -1 )) return FALSE;
- } while (req->read_size);
- return TRUE;
+ return size;
}
- /* read the size of the next chunk (the read section must be held) */
- static BOOL start_next_chunk( http_request_t *req )
+ static DWORD HTTP_ReadChunked(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
{
- DWORD chunk_size = 0;
+ char reply[MAX_REPLY_LEN], *p = buffer;
+ DWORD buflen, to_read, to_write = size;
+ int bytes_read;
- if (!req->dwContentLength) return TRUE;
- if (req->dwContentLength == req->dwContentRead)
- {
- /* read terminator for the previous chunk */
- if (!discard_eol( req )) return FALSE;
- req->dwContentLength = ~0u;
- req->dwContentRead = 0;
- }
+ *read = 0;
for (;;)
{
- while (req->read_size)
- {
- char ch = req->read_buf[req->read_pos];
- if (ch >= '0' && ch <= '9') chunk_size = chunk_size * 16 + ch - '0';
- else if (ch >= 'a' && ch <= 'f') chunk_size = chunk_size * 16 + ch - 'a' + 10;
- else if (ch >= 'A' && ch <= 'F') chunk_size = chunk_size * 16 + ch - 'A' + 10;
- else if (ch == ';' || ch == '\r' || ch == '\n')
- {
- TRACE( "reading %u byte chunk\n", chunk_size );
- req->dwContentLength = chunk_size;
- req->dwContentRead = 0;
- if (!discard_eol( req )) return FALSE;
- return TRUE;
- }
- remove_data( req, 1 );
- }
- if (!read_more_data( req, -1 )) return FALSE;
- if (!req->read_size)
- {
- req->dwContentLength = req->dwContentRead = 0;
- return TRUE;
- }
- }
- }
+ if (*read == size) break;
- /* check if we have reached the end of the data to read (the read section must be held) */
- static BOOL end_of_read_data( http_request_t *req )
+ if (req->dwContentLength == ~0UL) /* new chunk */
- {
+{
- if (req->gzip_stream) return req->gzip_stream->end_of_data && !req->gzip_stream->buf_size;
- if (req->read_chunked) return (req->dwContentLength == 0);
- if (req->dwContentLength == ~0u) return FALSE;
- return (req->dwContentLength == req->dwContentRead);
- }
+ buflen = sizeof(reply);
+ if (!NETCON_getNextLine(&req->netConnection, reply, &buflen)) break;
- /* fetch some more data into the read buffer (the read section must be held) */
- static BOOL refill_buffer( http_request_t *req )
+ if (!(req->dwContentLength = get_chunk_size(reply)))
- {
+{
- int len = sizeof(req->read_buf);
-
- if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
- {
- if (!start_next_chunk( req )) return FALSE;
+ /* zero sized chunk marks end of transfer; read any trailing headers and return */
+ HTTP_GetResponseHeaders(req, FALSE);
+ break;
- }
- }
+ }
-
- if (req->dwContentLength != ~0u) len = min( len, req->dwContentLength - req->dwContentRead );
- if (len <= req->read_size) return TRUE;
-
- if (!read_more_data( req, len )) return FALSE;
- if (!req->read_size) req->dwContentLength = req->dwContentRead = 0;
- return TRUE;
+}
+ to_read = min(to_write, req->dwContentLength - req->dwContentRead);
- static DWORD read_gzip_data(http_request_t *req, BYTE *buf, int size, BOOL sync, int *read_ret)
+ if (!NETCON_recv(&req->netConnection, p, to_read, sync ? MSG_WAITALL : 0, &bytes_read))
- {
+{
- DWORD ret = ERROR_SUCCESS;
- int read = 0;
-
- #ifdef HAVE_ZLIB
- z_stream *zstream = &req->gzip_stream->zstream;
- int zres;
+ if (bytes_read != to_read)
+ ERR("Not all data received %d/%d\n", bytes_read, to_read);
- while(read < size && !req->gzip_stream->end_of_data) {
- if(!req->read_size) {
- if(!sync || !refill_buffer(req))
+ /* always return success, even if the network layer returns an error */
+ *read = 0;
- break;
+ break;
}
+ if (!bytes_read) break;
- zstream->next_in = req->read_buf+req->read_pos;
- zstream->avail_in = req->read_size;
- zstream->next_out = buf+read;
- zstream->avail_out = size-read;
- zres = inflate(zstream, Z_FULL_FLUSH);
- read = size - zstream->avail_out;
- remove_data(req, req->read_size-zstream->avail_in);
- if(zres == Z_STREAM_END) {
- TRACE("end of data\n");
- req->gzip_stream->end_of_data = TRUE;
- inflateEnd(&req->gzip_stream->zstream);
- }else if(zres != Z_OK) {
- WARN("inflate failed %d\n", zres);
- if(!read)
- ret = ERROR_INTERNET_DECODING_FAILED;
- break;
- }
- }
- #endif
-
- *read_ret = read;
- return ret;
- }
+ req->dwContentRead += bytes_read;
+ to_write -= bytes_read;
+ *read += bytes_read;
- static void refill_gzip_buffer(http_request_t *req)
+ if (req->lpszCacheFile)
- {
+{
- DWORD res;
- int len;
-
- if(!req->gzip_stream || !req->read_size || req->gzip_stream->buf_size == sizeof(req->gzip_stream->buf))
- return;
+ DWORD dwBytesWritten;
- if(req->gzip_stream->buf_pos) {
- if(req->gzip_stream->buf_size)
- memmove(req->gzip_stream->buf, req->gzip_stream->buf + req->gzip_stream->buf_pos, req->gzip_stream->buf_size);
- req->gzip_stream->buf_pos = 0;
+ if (!WriteFile(req->hCacheFile, p, bytes_read, &dwBytesWritten, NULL))
+ WARN("WriteFile failed: %u\n", GetLastError());
- }
+ }
+ p += bytes_read;
- res = read_gzip_data(req, req->gzip_stream->buf + req->gzip_stream->buf_size,
- sizeof(req->gzip_stream->buf) - req->gzip_stream->buf_size, FALSE, &len);
- if(res == ERROR_SUCCESS)
- req->gzip_stream->buf_size += len;
- }
+ if (req->dwContentRead == req->dwContentLength) /* chunk complete */
+ {
+ req->dwContentRead = 0;
+ req->dwContentLength = ~0UL;
- /* return the size of data available to be read immediately (the read section must be held) */
- static DWORD get_avail_data( http_request_t *req )
+ buflen = sizeof(reply);
+ if (!NETCON_getNextLine(&req->netConnection, reply, &buflen))
- {
+{
- if (req->gzip_stream) {
- refill_gzip_buffer(req);
- return req->gzip_stream->buf_size;
+ ERR("Malformed chunk\n");
+ *read = 0;
+ break;
- }
- }
+ }
- if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
- return 0;
- return min( req->read_size, req->dwContentLength - req->dwContentRead );
+}
-
- static void HTTP_ReceiveRequestData(http_request_t *req, BOOL first_notif)
- {
- INTERNET_ASYNC_RESULT iar;
-
- TRACE("%p\n", req);
-
- EnterCriticalSection( &req->read_section );
- if (refill_buffer( req )) {
- iar.dwResult = (DWORD_PTR)req->hdr.hInternet;
- iar.dwError = first_notif ? 0 : get_avail_data(req);
- }else {
- iar.dwResult = 0;
- iar.dwError = INTERNET_GetLastError();
}
- LeaveCriticalSection( &req->read_section );
-
- INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar,
- sizeof(INTERNET_ASYNC_RESULT));
+ if (!*read) HTTP_FinishedReading(req);
+ return ERROR_SUCCESS;
}
- /* read data from the http connection (the read section must be held) */
- static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
+ static DWORD HTTPREQ_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
{
- BOOL finished_reading = FALSE;
- int len, bytes_read = 0;
- DWORD ret = ERROR_SUCCESS;
-
- EnterCriticalSection( &req->read_section );
+ WCHAR encoding[20];
+ DWORD buflen = sizeof(encoding);
+ static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0};
- if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
+ if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_TRANSFER_ENCODING, encoding, &buflen, NULL) &&
+ !strcmpiW(encoding, szChunked))
{
- if (!start_next_chunk( req )) goto done;
+ return HTTP_ReadChunked(req, buffer, size, read, sync);
}
-
- if(req->gzip_stream) {
- if(req->gzip_stream->buf_size) {
- bytes_read = min(req->gzip_stream->buf_size, size);
- memcpy(buffer, req->gzip_stream->buf + req->gzip_stream->buf_pos, bytes_read);
- req->gzip_stream->buf_pos += bytes_read;
- req->gzip_stream->buf_size -= bytes_read;
- }else if(!req->read_size && !req->gzip_stream->end_of_data) {
- refill_buffer(req);
- }
-
- if(size > bytes_read) {
- ret = read_gzip_data(req, (BYTE*)buffer+bytes_read, size-bytes_read, sync, &len);
- if(ret == ERROR_SUCCESS)
- bytes_read += len;
- }
-
- finished_reading = req->gzip_stream->end_of_data && !req->gzip_stream->buf_size;
- }else {
- if (req->dwContentLength != ~0u) size = min( size, req->dwContentLength - req->dwContentRead );
-
- if (req->read_size) {
- bytes_read = min( req->read_size, size );
- memcpy( buffer, req->read_buf + req->read_pos, bytes_read );
- remove_data( req, bytes_read );
- }
-
- if (size > bytes_read && (!bytes_read || sync)) {
- if (NETCON_recv( &req->netConnection, (char *)buffer + bytes_read, size - bytes_read,
- sync ? MSG_WAITALL : 0, &len))
- bytes_read += len;
- /* always return success, even if the network layer returns an error */
+ else
+ return HTTP_Read(req, buffer, size, read, sync);
-}
+ }
- finished_reading = !bytes_read && req->dwContentRead == req->dwContentLength;
- }
- done:
- req->dwContentRead += bytes_read;
- *read = bytes_read;
-
- TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, req->dwContentRead, req->dwContentLength );
- LeaveCriticalSection( &req->read_section );
-
- if(ret == ERROR_SUCCESS && req->lpszCacheFile) {
- BOOL res;
- DWORD dwBytesWritten;
-
- res = WriteFile(req->hCacheFile, buffer, bytes_read, &dwBytesWritten, NULL);
- if(!res)
- WARN("WriteFile failed: %u\n", GetLastError());
- }
-
- if(finished_reading)
- HTTP_FinishedReading(req);
-
- return ret;
- }
-
-
- static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read)
+ static DWORD HTTPREQ_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size, DWORD *read)
{
- http_request_t *req = (http_request_t*)hdr;
+ WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
return HTTPREQ_Read(req, buffer, size, read, TRUE);
}
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
- if ((hdr->dwFlags & INTERNET_FLAG_ASYNC) && !get_avail_data(req))
+ if (hdr->dwFlags & INTERNET_FLAG_ASYNC) {
+ DWORD available = 0;
+
+ NETCON_query_data_available(&req->netConnection, &available);
+ if (!available)
- {
- WORKREQUEST workRequest;
+ {
+ WORKREQUEST workRequest;
- if (TryEnterCriticalSection( &req->read_section ))
- {
- if (get_avail_data(req))
- {
- res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
- &buffers->dwBufferLength, FALSE);
- LeaveCriticalSection( &req->read_section );
- goto done;
- }
- LeaveCriticalSection( &req->read_section );
- }
-
- workRequest.asyncproc = HTTPREQ_AsyncReadFileExAProc;
+ workRequest.asyncproc = HTTPREQ_AsyncReadFileExProc;
- workRequest.hdr = WININET_AddRef(&req->hdr);
- workRequest.u.InternetReadFileExA.lpBuffersOut = buffers;
+ workRequest.hdr = WININET_AddRef(&req->hdr);
+ workRequest.u.InternetReadFileExA.lpBuffersOut = buffers;
- INTERNET_AsyncCall(&workRequest);
+ INTERNET_AsyncCall(&workRequest);
- return ERROR_IO_PENDING;
- }
+ return ERROR_IO_PENDING;
+ }
+ }
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
!(flags & IRF_NO_WAIT));
return res;
}
- static void HTTPREQ_AsyncReadFileExWProc(WORKREQUEST *workRequest)
+ static BOOL HTTPREQ_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWORD size, DWORD *written)
{
- struct WORKREQ_INTERNETREADFILEEXW const *data = &workRequest->u.InternetReadFileExW;
- http_request_t *req = (http_request_t*)workRequest->hdr;
- INTERNET_ASYNC_RESULT iar;
- DWORD res;
-
- TRACE("INTERNETREADFILEEXW %p\n", workRequest->hdr);
-
- res = HTTPREQ_Read(req, data->lpBuffersOut->lpvBuffer,
- data->lpBuffersOut->dwBufferLength, &data->lpBuffersOut->dwBufferLength, TRUE);
+ LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW)hdr;
- iar.dwResult = res == ERROR_SUCCESS;
- iar.dwError = res;
-
- INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
- INTERNET_STATUS_REQUEST_COMPLETE, &iar,
- sizeof(INTERNET_ASYNC_RESULT));
+ return NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written);
}
- static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffers,
- DWORD flags, DWORD_PTR context)
+ static void HTTPREQ_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest)
{
+ WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr;
+ INTERNET_ASYNC_RESULT iar;
+ char buffer[4048];
- http_request_t *req = (http_request_t*)hdr;
- DWORD res;
-
- if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
- FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
+ TRACE("%p\n", workRequest->hdr);
- if (buffers->dwStructSize != sizeof(*buffers))
- return ERROR_INVALID_PARAMETER;
+ iar.dwResult = NETCON_recv(&req->netConnection, buffer,
+ min(sizeof(buffer), req->dwContentLength - req->dwContentRead),
+ MSG_PEEK, (int *)&iar.dwError);
- INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
-
- if (hdr->dwFlags & INTERNET_FLAG_ASYNC)
- {
- WORKREQUEST workRequest;
-
- if (TryEnterCriticalSection( &req->read_section ))
- {
- if (get_avail_data(req))
- {
- res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
- &buffers->dwBufferLength, FALSE);
- LeaveCriticalSection( &req->read_section );
- goto done;
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
-}
+ }
- LeaveCriticalSection( &req->read_section );
- }
-
- workRequest.asyncproc = HTTPREQ_AsyncReadFileExWProc;
- workRequest.hdr = WININET_AddRef(&req->hdr);
- workRequest.u.InternetReadFileExW.lpBuffersOut = buffers;
-
- INTERNET_AsyncCall(&workRequest);
- return ERROR_IO_PENDING;
- }
-
- res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
- !(flags & IRF_NO_WAIT));
-
- done:
- if (res == ERROR_SUCCESS) {
- DWORD size = buffers->dwBufferLength;
- INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
- &size, sizeof(size));
- }
-
- return res;
- }
-
- static BOOL HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
+ static DWORD HTTPREQ_QueryDataAvailable(WININETHANDLEHEADER *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx)
{
- BOOL ret;
- http_request_t *lpwhr = (http_request_t*)hdr;
-
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
+ WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
+ BYTE buffer[4048];
+ BOOL async;
- *written = 0;
- if ((ret = NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written)))
- lpwhr->dwBytesWritten += *written;
-
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_SENT, written, sizeof(DWORD));
- return ret;
- }
+ TRACE("(%p %p %x %lx)\n", req, available, flags, ctx);
- static void HTTPREQ_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest)
- {
- http_request_t *req = (http_request_t*)workRequest->hdr;
+ if(!NETCON_query_data_available(&req->netConnection, available) || *available)
+ return ERROR_SUCCESS;
- HTTP_ReceiveRequestData(req, FALSE);
- }
+ /* Even if we are in async mode, we need to determine whether
+ * there is actually more data available. We do this by trying
+ * to peek only a single byte in async mode. */
+ async = (req->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) != 0;
- static DWORD HTTPREQ_QueryDataAvailable(object_header_t *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx)
+ if (NETCON_recv(&req->netConnection, buffer,
+ min(async ? 1 : sizeof(buffer), req->dwContentLength - req->dwContentRead),
+ MSG_PEEK, (int *)available) && async && *available)
- {
+{
- http_request_t *req = (http_request_t*)hdr;
-
- TRACE("(%p %p %x %lx)\n", req, available, flags, ctx);
-
- if (req->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
WORKREQUEST workRequest;
- /* never wait, if we can't enter the section we queue an async request right away */
- if (TryEnterCriticalSection( &req->read_section ))
- {
- if ((*available = get_avail_data( req ))) goto done;
- if (end_of_read_data( req )) goto done;
- LeaveCriticalSection( &req->read_section );
- }
-
+ *available = 0;
workRequest.asyncproc = HTTPREQ_AsyncQueryDataAvailableProc;
workRequest.hdr = WININET_AddRef( &req->hdr );
INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
- if (pszString)
- {
+
- for (i = 0; ppszRawHeaderLines[i]; i++)
- {
- DWORD len = strlenW(ppszRawHeaderLines[i]);
- memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR));
- pszString += len+1;
- }
- *pszString = '\0';
+ for (i = 0; ppszRawHeaderLines[i]; i++)
+ {
+ DWORD len = strlenW(ppszRawHeaderLines[i]);
+ memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR));
+ pszString += len+1;
+ }
+ *pszString = '\0';
- TRACE("returning data: %s\n", debugstr_wn(lpBuffer, size));
- }
+
+ TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, size));
+
*lpdwBufferLength = size * sizeof(WCHAR);
HTTP_FreeTokens(ppszRawHeaderLines);
INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
- if (lpBuffer)
- {
- memcpy(lpBuffer, lpwhr->lpszStatusText, (len+1)*sizeof(WCHAR));
+ memcpy(lpBuffer, lpwhr->lpszStatusText, (len + 1) * sizeof(WCHAR));
- TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len));
- }
*lpdwBufferLength = len * sizeof(WCHAR);
+
+ TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, len));
+
return TRUE;
}
break;
INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
- if (lpBuffer)
- {
- memcpy(lpBuffer, lpwhr->lpszVersion, (len+1)*sizeof(WCHAR));
+ memcpy(lpBuffer, lpwhr->lpszVersion, (len + 1) * sizeof(WCHAR));
- TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len));
- }
*lpdwBufferLength = len * sizeof(WCHAR);
+
+ TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, len));
+
return TRUE;
}
break;
return bSuccess;
}
- if (lpdwIndex && level != HTTP_QUERY_STATUS_CODE) (*lpdwIndex)++;
+ if (lpdwIndex)
+ (*lpdwIndex)++;
/* coalesce value to requested type */
- if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER && lpBuffer)
+ if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER)
{
- *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue);
- bSuccess = TRUE;
+ *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue);
- TRACE(" returning number: %d\n", *(int *)lpBuffer);
+ bSuccess = TRUE;
+
+ TRACE(" returning number : %d\n", *(int *)lpBuffer);
}
- else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer)
+ else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME)
{
time_t tmpTime;
struct tm tmpTM;
tmpTime = ConvertTimeString(lphttpHdr->lpszValue);
tmpTM = *gmtime(&tmpTime);
- STHook = (SYSTEMTIME *) lpBuffer;
+ STHook = (SYSTEMTIME *)lpBuffer;
+ if(STHook==NULL)
+ return bSuccess;
+
- STHook->wDay = tmpTM.tm_mday;
- STHook->wHour = tmpTM.tm_hour;
- STHook->wMilliseconds = 0;
- STHook->wMinute = tmpTM.tm_min;
- STHook->wDayOfWeek = tmpTM.tm_wday;
- STHook->wMonth = tmpTM.tm_mon + 1;
- STHook->wSecond = tmpTM.tm_sec;
- STHook->wYear = tmpTM.tm_year;
+ STHook->wDay = tmpTM.tm_mday;
+ STHook->wHour = tmpTM.tm_hour;
+ STHook->wMilliseconds = 0;
+ STHook->wMinute = tmpTM.tm_min;
+ STHook->wDayOfWeek = tmpTM.tm_wday;
+ STHook->wMonth = tmpTM.tm_mon + 1;
+ STHook->wSecond = tmpTM.tm_sec;
+ STHook->wYear = tmpTM.tm_year;
+
- bSuccess = TRUE;
+ bSuccess = TRUE;
- TRACE(" returning time : %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
- STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek,
- STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds);
+ TRACE(" returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
+ STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek,
+ STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds);
}
else if (lphttpHdr->lpszValue)
{
INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
return bSuccess;
}
- if (lpBuffer)
- {
+
- memcpy(lpBuffer, lphttpHdr->lpszValue, len);
+ memcpy(lpBuffer, lphttpHdr->lpszValue, len);
- TRACE(" returning string: %s\n", debugstr_w(lpBuffer));
- }
*lpdwBufferLength = len - sizeof(WCHAR);
bSuccess = TRUE;
+
+ TRACE(" returning string : %s\n", debugstr_w(lpBuffer));
}
return bSuccess;
}
req = &workRequest.u.HttpSendRequestW;
if (lpBuffersIn)
{
- /* FIXME: this should use dwHeadersLength or may not be necessary at all */
+ if (lpBuffersIn->lpcszHeader)
- req->lpszHeader = heap_strdupW(lpBuffersIn->lpcszHeader);
+ /* FIXME: this should use dwHeadersLength or may not be necessary at all */
+ req->lpszHeader = WININET_strdupW(lpBuffersIn->lpcszHeader);
+ else
+ req->lpszHeader = NULL;
req->dwHeaderLength = lpBuffersIn->dwHeadersLength;
req->lpOptional = lpBuffersIn->lpvBuffer;
req->dwOptionalLength = lpBuffersIn->dwBufferLength;
return result;
}
+ static BOOL HTTP_GetRequestURL(WININETHTTPREQW *req, LPWSTR buf)
+ {
+ LPHTTPHEADERW host_header;
+
+ static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
+
+ host_header = HTTP_GetHeader(req, szHost);
+ if(!host_header)
+ return FALSE;
+
+ sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
+ return TRUE;
+ }
+
/***********************************************************************
- * HTTP_GetRedirectURL (internal)
+ * HTTP_HandleRedirect (internal)
*/
- static LPWSTR HTTP_GetRedirectURL(http_request_t *lpwhr, LPCWSTR lpszUrl)
+ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl)
{
- static WCHAR szHttp[] = {'h','t','t','p',0};
- static WCHAR szHttps[] = {'h','t','t','p','s',0};
- DWORD url_length = 0;
- LPWSTR orig_url;
- LPWSTR combined_url;
-
- urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
- urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
- urlComponents.dwSchemeLength = 0;
- urlComponents.lpszHostName = lpwhs->lpszHostName;
- urlComponents.dwHostNameLength = 0;
- urlComponents.nPort = lpwhs->nHostPort;
- urlComponents.lpszUserName = lpwhs->lpszUserName;
- urlComponents.dwUserNameLength = 0;
- urlComponents.lpszPassword = NULL;
- urlComponents.dwPasswordLength = 0;
- urlComponents.lpszUrlPath = lpwhr->lpszPath;
- urlComponents.dwUrlPathLength = 0;
- urlComponents.lpszExtraInfo = NULL;
- urlComponents.dwExtraInfoLength = 0;
-
- if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) &&
- (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+ static const WCHAR szContentType[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
+ static const WCHAR szContentLength[] = {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0};
+ LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession;
+ LPWININETAPPINFOW hIC = lpwhs->lpAppInfo;
+ BOOL using_proxy = hIC->lpszProxy && hIC->lpszProxy[0];
+ WCHAR path[INTERNET_MAX_URL_LENGTH];
+ int index;
+
+ if(lpszUrl[0]=='/')
+ {
+ /* if it's an absolute path, keep the same session info */
+ lstrcpynW(path, lpszUrl, INTERNET_MAX_URL_LENGTH);
+ }
+ else
+ {
+ URL_COMPONENTSW urlComponents;
+ WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024];
- http_session_t *lpwhs = lpwhr->lpHttpSession;
- URL_COMPONENTSW urlComponents;
+ static WCHAR szHttp[] = {'h','t','t','p',0};
+ static WCHAR szHttps[] = {'h','t','t','p','s',0};
- return NULL;
+ DWORD url_length = 0;
+ LPWSTR orig_url;
+ LPWSTR combined_url;
+
+ urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
+ urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
+ urlComponents.dwSchemeLength = 0;
+ urlComponents.lpszHostName = lpwhs->lpszHostName;
+ urlComponents.dwHostNameLength = 0;
+ urlComponents.nPort = lpwhs->nHostPort;
+ urlComponents.lpszUserName = lpwhs->lpszUserName;
+ urlComponents.dwUserNameLength = 0;
+ urlComponents.lpszPassword = NULL;
+ urlComponents.dwPasswordLength = 0;
+ urlComponents.lpszUrlPath = lpwhr->lpszPath;
+ urlComponents.dwUrlPathLength = 0;
+ urlComponents.lpszExtraInfo = NULL;
+ urlComponents.dwExtraInfoLength = 0;
+
+ if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) &&
+ (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+ return FALSE;
- orig_url = HeapAlloc(GetProcessHeap(), 0, url_length);
+ orig_url = HeapAlloc(GetProcessHeap(), 0, url_length);
- /* convert from bytes to characters */
- url_length = url_length / sizeof(WCHAR) - 1;
- if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
+ /* convert from bytes to characters */
+ url_length = url_length / sizeof(WCHAR) - 1;
+ if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length))
+ {
+ HeapFree(GetProcessHeap(), 0, orig_url);
- return NULL;
+ return FALSE;
- }
+ }
- url_length = 0;
- if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) &&
- (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
+ url_length = 0;
+ if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) &&
+ (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+ {
+ HeapFree(GetProcessHeap(), 0, orig_url);
- return NULL;
+ return FALSE;
- }
- combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR));
+ }
+ combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR));
- if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
- HeapFree(GetProcessHeap(), 0, combined_url);
- return FALSE;
- }
+ if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY))
+ {
HeapFree(GetProcessHeap(), 0, orig_url);
- return NULL;
+ HeapFree(GetProcessHeap(), 0, combined_url);
- return combined_url;
- }
-
-
- /***********************************************************************
- * HTTP_HandleRedirect (internal)
- */
- static BOOL HTTP_HandleRedirect(http_request_t *lpwhr, LPCWSTR lpszUrl)
- {
- http_session_t *lpwhs = lpwhr->lpHttpSession;
- appinfo_t *hIC = lpwhs->lpAppInfo;
- BOOL using_proxy = hIC->lpszProxy && hIC->lpszProxy[0];
- WCHAR path[INTERNET_MAX_URL_LENGTH];
- int index;
-
- if(lpszUrl[0]=='/')
- {
- /* if it's an absolute path, keep the same session info */
- lstrcpynW(path, lpszUrl, INTERNET_MAX_URL_LENGTH);
- }
- else
- {
- URL_COMPONENTSW urlComponents;
- WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024];
- static WCHAR szHttp[] = {'h','t','t','p',0};
- static WCHAR szHttps[] = {'h','t','t','p','s',0};
++ return FALSE;
+ }
+ HeapFree(GetProcessHeap(), 0, orig_url);
userName[0] = 0;
hostName[0] = 0;
if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) &&
HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
{
- if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
- {
- HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
- lpwhr->lpszVerb = heap_strdupW(szGET);
- }
HTTP_DrainContent(lpwhr);
- if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
- {
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
- new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
- bSuccess = HTTP_HandleRedirect(lpwhr, new_url);
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_REDIRECT, szNewLocation,
+ dwBufferSize);
+ bSuccess = HTTP_HandleRedirect(lpwhr, szNewLocation);
- if (bSuccess)
- {
- HeapFree(GetProcessHeap(), 0, requestString);
- loop_next = TRUE;
+ if (bSuccess)
+ {
+ HeapFree(GetProcessHeap(), 0, requestString);
+ loop_next = TRUE;
+ }
- HeapFree( GetProcessHeap(), 0, new_url );
}
- redirected = TRUE;
}
-- }
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && bSuccess)
{
WCHAR szAuthValue[2048];
/* TODO: send notification for P3P header */
- if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- if (bSuccess)
- {
- if (lpwhr->dwBytesWritten == lpwhr->dwBytesToWrite) HTTP_ReceiveRequestData(lpwhr, TRUE);
- else
- {
- iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
+ iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
- iar.dwError = 0;
+ iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_REQUEST_COMPLETE, &iar,
- sizeof(INTERNET_ASYNC_RESULT));
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
- }
- }
- else
- {
- iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
- iar.dwError = INTERNET_GetLastError();
-
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_REQUEST_COMPLETE, &iar,
- sizeof(INTERNET_ASYNC_RESULT));
- }
- }
TRACE("<--\n");
if (bSuccess) INTERNET_SetLastError(ERROR_SUCCESS);
goto lend;
do {
- static const WCHAR szHundred[] = {'1','0','0',0};
/*
- * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code.
+ * HACK peek at the buffer
*/
buflen = MAX_REPLY_LEN;
- if (!read_line(lpwhr, bufferA, &buflen))
+ NETCON_recv(&lpwhr->netConnection, buffer, buflen, MSG_PEEK, &rc);
+
+ /*
+ * We should first receive 'HTTP/1.x nnn OK' where nnn is the status code.
+ */
+ memset(buffer, 0, MAX_REPLY_LEN);
+ if (!NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen))
goto lend;
- rc += buflen;
MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
- /* check is this a status code line? */
- if (!strncmpW(buffer, g_szHttp1_0, 4))
- {
+
- /* split the version from the status code */
- status_code = strchrW( buffer, ' ' );
- if( !status_code )
- goto lend;
- *status_code++=0;
+ /* split the version from the status code */
+ status_code = strchrW( buffer, ' ' );
+ if( !status_code )
+ goto lend;
+ *status_code++=0;
- /* split the status code from the status text */
- status_text = strchrW( status_code, ' ' );
- if( !status_text )
- goto lend;
- *status_text++=0;
+ /* split the status code from the status text */
+ status_text = strchrW( status_code, ' ' );
+ if( !status_text )
+ goto lend;
+ *status_text++=0;
- TRACE("version [%s] status code [%s] status text [%s]\n",
- debugstr_w(buffer), debugstr_w(status_code), debugstr_w(status_text) );
+ TRACE("version [%s] status code [%s] status text [%s]\n",
+ debugstr_w(buffer), debugstr_w(status_code), debugstr_w(status_text) );
- codeHundred = (!strcmpW(status_code, szHundred));
- }
- else if (!codeHundred)
- {
- FIXME("Non status line at head of response (%s)\n",debugstr_w(buffer));
- goto lend;
- }
- } while (codeHundred);
+ } while (!strcmpW(status_code, szHundred)); /* ignore "100 Continue" responses */
/* Add status code */
HTTP_ProcessHeader(lpwhr, szStatus, status_code,
LPWSTR * pFieldAndValue;
TRACE("got line %s, now interpreting\n", debugstr_a(bufferA));
-
- if (!bufferA[0]) break;
MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
- pFieldAndValue = HTTP_InterpretHttpHeader(buffer);
- if (pFieldAndValue)
- {
- while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
+ while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
+ {
- cchMaxRawHeaders *= 2;
+ cchMaxRawHeaders *= 2;
- temp = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
- if (temp == NULL) goto lend;
- lpszRawHeaders = temp;
+ lpszRawHeaders = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
+ }
- memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
- cchRawHeaders += (buflen-1);
- memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
- cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
- lpszRawHeaders[cchRawHeaders] = '\0';
+ memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
+ cchRawHeaders += (buflen-1);
+ memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
+ cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
+ lpszRawHeaders[cchRawHeaders] = '\0';
- HTTP_ProcessHeader(lpwhr, pFieldAndValue[0], pFieldAndValue[1],
- HTTP_ADDREQ_FLAG_ADD );
+ pFieldAndValue = HTTP_InterpretHttpHeader(buffer);
+ if (!pFieldAndValue)
+ break;
+
+ HTTP_ProcessHeader(lpwhr, pFieldAndValue[0], pFieldAndValue[1],
+ HTTP_ADDREQ_FLAG_ADD );
- HTTP_FreeTokens(pFieldAndValue);
- }
+ HTTP_FreeTokens(pFieldAndValue);
+ }
- }
else
{
cbreaks++;
FE(INTERNET_FLAG_TRANSFER_BINARY)
};
#undef FE
- unsigned int i;
+ int i;
-
+
for (i = 0; i < (sizeof(flag) / sizeof(flag[0])); i++) {
if (flag[i].val & dwFlags) {
TRACE(" %s", flag[i].name);
if(!buffer || bufsize < *size)
return ERROR_INSUFFICIENT_BUFFER;
- if (ai->lpszAgent)
- strcpyW(buffer, ai->lpszAgent);
+ strcpyW(buffer, ai->lpszAgent);
- else
- *(WCHAR *)buffer = 0;
- /* If the buffer is copied, the returned length doesn't include
- * the NULL terminator.
- */
- *size = len * sizeof(WCHAR);
}else {
- if (ai->lpszAgent)
- *size = WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, NULL, 0, NULL, NULL);
+ *size = WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, NULL, 0, NULL, NULL);
- else
- *size = 1;
if(!buffer || bufsize < *size)
return ERROR_INSUFFICIENT_BUFFER;
- if (ai->lpszAgent)
- WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, buffer, *size, NULL, NULL);
+ WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, buffer, *size, NULL, NULL);
- else
- *(char *)buffer = 0;
- /* If the buffer is copied, the returned length doesn't include
- * the NULL terminator.
- */
- *size -= 1;
}
return ERROR_SUCCESS;
if (ai->lpszProxyBypass)
proxyBypassBytesRequired = (lstrlenW(ai->lpszProxyBypass) + 1) * sizeof(WCHAR);
if (*size < sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired)
- {
- *size = sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired;
- return ERROR_INSUFFICIENT_BUFFER;
+ return ERROR_INSUFFICIENT_BUFFER;
- }
+
proxy = (LPWSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOW));
proxy_bypass = (LPWSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired);
HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
{
INTERNET_STATUS_CALLBACK retVal;
- object_header_t *lpwh;
+ LPWININETHANDLEHEADER lpwh;
- TRACE("%p\n", hInternet);
+ TRACE("0x%08x\n", (ULONG)hInternet);
-
+
if (!(lpwh = WININET_GetObject(hInternet)))
return INTERNET_INVALID_STATUS_CALLBACK;
BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
DWORD dwFlags, DWORD_PTR dwContext)
{
- object_header_t *hdr;
- DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ ERR("(%p, %p, 0x%x, 0x%lx): not implemented in native\n", hFile, lpBuffer, dwFlags, dwContext);
- TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffer, dwFlags, dwContext);
-
- hdr = WININET_GetObject(hFile);
- if (!hdr) {
- INTERNET_SetLastError(ERROR_INVALID_HANDLE);
+ INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
-}
+ return FALSE;
+ }
- if(hdr->vtbl->ReadFileExW)
- res = hdr->vtbl->ReadFileExW(hdr, lpBuffer, dwFlags, dwContext);
-
- WININET_Release(hdr);
-
- TRACE("-- %s (%u, bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE",
- res, lpBuffer->dwBufferLength);
-
- if(res != ERROR_SUCCESS)
- SetLastError(res);
- return res == ERROR_SUCCESS;
- }
-
DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
{
- static BOOL warn = TRUE;
-
switch(option) {
case INTERNET_OPTION_REQUEST_FLAGS:
TRACE("INTERNET_OPTION_REQUEST_FLAGS\n");
return ERROR_SUCCESS;
case INTERNET_OPTION_CONNECTED_STATE:
- if (warn) {
- FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n");
+ FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n");
- warn = FALSE;
- }
+
if (*size < sizeof(ULONG))
return ERROR_INSUFFICIENT_BUFFER;
{
case INTERNET_OPTION_CALLBACK:
{
- if (!lpwhh)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- return FALSE;
+ INTERNET_STATUS_CALLBACK callback = *(INTERNET_STATUS_CALLBACK *)lpBuffer;
+ ret = (set_status_callback(lpwhh, callback, TRUE) != INTERNET_INVALID_STATUS_CALLBACK);
+ break;
- }
+ }
- WININET_Release(lpwhh);
- INTERNET_SetLastError(ERROR_INTERNET_OPTION_NOT_SETTABLE);
- return FALSE;
- }
case INTERNET_OPTION_HTTP_VERSION:
{
HTTP_VERSION_INFO* pVersion=(HTTP_VERSION_INFO*)lpBuffer;
*/
BOOL WINAPI InternetCheckConnectionA(LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved)
{
- WCHAR *url = NULL;
+ WCHAR *szUrl;
+ INT len;
BOOL rc;
- if(lpszUrl) {
- url = heap_strdupAtoW(lpszUrl);
- if(!url)
+ len = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0);
+ if (!(szUrl = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR))))
- return FALSE;
+ return FALSE;
- }
-
- rc = InternetCheckConnectionW(url, dwFlags, dwReserved);
+ MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, szUrl, len);
+ rc = InternetCheckConnectionW(szUrl, dwFlags, dwReserved);
+ HeapFree(GetProcessHeap(), 0, szUrl);
-
+
- HeapFree(GetProcessHeap(), 0, url);
return rc;
}
workRequest.asyncproc = AsyncInternetOpenUrlProc;
workRequest.hdr = WININET_AddRef( &hIC->hdr );
- req = &workRequest.u.InternetOpenUrlW;
+ req = &workRequest.u.InternetOpenUrlW;
- req->lpszUrl = heap_strdupW(lpszUrl);
- req->lpszHeaders = heap_strdupW(lpszHeaders);
+ req->lpszUrl = WININET_strdupW(lpszUrl);
+ if (lpszHeaders)
+ req->lpszHeaders = WININET_strdupW(lpszHeaders);
+ else
+ req->lpszHeaders = 0;
req->dwHeadersLength = dwHeadersLength;
req->dwFlags = dwFlags;
req->dwContext = dwContext;
return ret;
}
- static inline WCHAR *heap_strdupAtoW(const char *str)
+ static inline LPWSTR WININET_strdup_AtoW( LPCSTR str )
{
- LPWSTR ret = NULL;
-
- if(str) {
- DWORD len;
-
- len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
- ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
+ int len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0);
+ LPWSTR ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
- if (ret)
- MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len);
+ if(ret)
+ MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
- }
-
return ret;
}
- static inline char *heap_strdupWtoA(LPCWSTR str)
+ static inline LPSTR WININET_strdup_WtoA( LPCWSTR str )
{
- char *ret = NULL;
-
- if(str) {
- DWORD size = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
- ret = HeapAlloc(GetProcessHeap(), 0, size);
+ int len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
+ LPSTR ret = HeapAlloc( GetProcessHeap(), 0, len );
- if (ret)
+ if(ret)
- WideCharToMultiByte(CP_ACP, 0, str, -1, ret, size, NULL, NULL);
- }
-
+ WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL);
return ret;
}
struct WORKREQ_FTPRENAMEFILEW FtpRenameFileW;
struct WORKREQ_FTPFINDNEXTW FtpFindNextW;
struct WORKREQ_HTTPSENDREQUESTW HttpSendRequestW;
- struct WORKREQ_HTTPENDREQUESTW HttpEndRequestW;
struct WORKREQ_SENDCALLBACK SendCallback;
- struct WORKREQ_INTERNETOPENURLW InternetOpenUrlW;
+ struct WORKREQ_INTERNETOPENURLW InternetOpenUrlW;
struct WORKREQ_INTERNETREADFILEEXA InternetReadFileExA;
- struct WORKREQ_INTERNETREADFILEEXW InternetReadFileExW;
} u;
} WORKREQUEST, *LPWORKREQUEST;
TRACE("%d bytes of queued, but unread data\n", unread);
*available += unread;
}
+ }
#endif
-}
+ return TRUE;
- else
- {
++ }
+
+ /******************************************************************************
+ * NETCON_getNextLine
+ */
+ BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer)
+ {
+
+ TRACE("\n");
+
+ if (!NETCON_connected(connection)) return FALSE;
+
+ if (!connection->useSSL)
+ {
+ struct timeval tv;
+ fd_set infd;
+ BOOL bSuccess = FALSE;
+ DWORD nRecv = 0;
+
+ FD_ZERO(&infd);
+ FD_SET(connection->socketFD, &infd);
+ tv.tv_sec=RESPONSE_TIMEOUT;
+ tv.tv_usec=0;
+
+ while (nRecv < *dwBuffer)
+ {
+ if (select(connection->socketFD+1,&infd,NULL,NULL,&tv) > 0)
+ {
+ if (recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0) <= 0)
+ {
+ INTERNET_SetLastError(sock_get_error(errno));
+ goto lend;
+ }
+
+ if (lpszBuffer[nRecv] == '\n')
+ {
+ bSuccess = TRUE;
+ break;
+ }
+ if (lpszBuffer[nRecv] != '\r')
+ nRecv++;
+ }
++ else
++ {
+ INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
+ goto lend;
+ }
+ }
+
+ lend: /* FIXME: don't use labels */
+ if (bSuccess)
+ {
+ lpszBuffer[nRecv++] = '\0';
+ *dwBuffer = nRecv;
+ TRACE(":%u %s\n", nRecv, lpszBuffer);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
}
else
{
#ifdef SONAME_LIBSSL
- *available = pSSL_pending(connection->ssl_s);
- #endif
+ long prev_timeout;
+ DWORD nRecv = 0;
+ BOOL success = TRUE;
+
+ prev_timeout = pSSL_CTX_get_timeout(ctx);
+ pSSL_CTX_set_timeout(ctx, RESPONSE_TIMEOUT);
+
+ while (nRecv < *dwBuffer)
+ {
+ int recv = 1;
+ if (!NETCON_recv(connection, &lpszBuffer[nRecv], 1, 0, &recv))
+ {
+ INTERNET_SetLastError(ERROR_CONNECTION_ABORTED);
+ success = FALSE;
- }
+ }
+
+ if (lpszBuffer[nRecv] == '\n')
+ {
+ success = TRUE;
+ break;
+ }
+ if (lpszBuffer[nRecv] != '\r')
+ nRecv++;
+ }
+
+ pSSL_CTX_set_timeout(ctx, prev_timeout);
+ if (success)
+ {
+ lpszBuffer[nRecv++] = '\0';
+ *dwBuffer = nRecv;
+ TRACE("_SSL:%u %s\n", nRecv, lpszBuffer);
- return TRUE;
- }
+ return TRUE;
+}
+ return FALSE;
+ #else
+ return FALSE;
+ #endif
+ }
+ }
+
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
{
static DWORD URLCacheContainers_FindContainerA(LPCSTR lpszUrl, URLCACHECONTAINER ** ppContainer)
{
- LPWSTR url = NULL;
DWORD ret;
-
- if (lpszUrl && !(url = heap_strdupAtoW(lpszUrl)))
- return ERROR_OUTOFMEMORY;
-
- ret = URLCacheContainers_FindContainerW(url, ppContainer);
- HeapFree(GetProcessHeap(), 0, url);
+ LPWSTR lpwszUrl;
+ int url_len = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0);
+ if (url_len && (lpwszUrl = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(WCHAR))))
+ {
+ MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, lpwszUrl, url_len);
+ ret = URLCacheContainers_FindContainerW(lpwszUrl, ppContainer);
+ HeapFree(GetProcessHeap(), 0, lpwszUrl);
- return ret;
- }
+ return ret;
+}
+ return GetLastError();
+ }
static BOOL URLCacheContainers_Enum(LPCWSTR lpwszSearchPattern, DWORD dwIndex, URLCACHECONTAINER ** ppContainer)
{
error = GetLastError();
goto cleanup;
}
+ WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, lpszUrlNameA, len, NULL, NULL);
- if (lpszFileExtension && !(lpszFileExtensionA = heap_strdupWtoA(lpszFileExtension)))
+ if (lpszFileExtension)
{
- error = GetLastError();
- goto cleanup;
- }
+ len = WideCharToMultiByte(CP_ACP, 0, lpszFileExtension, -1, NULL, 0, NULL, NULL);
+ lpszFileExtensionA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
+ if (!lpszFileExtensionA)
+ {
+ error = GetLastError();
+ goto cleanup;
+ }
+ WideCharToMultiByte(CP_ACP, 0, lpszFileExtension, -1, lpszFileExtensionA, len, NULL, NULL);
+ }
if (URLCache_FindHash(pHeader, lpszUrlNameA, &pHashEntry))
{
/***********************************************************************
* GetDiskInfoA (WININET.@)
*/
- BOOL WINAPI GetDiskInfoA(PCSTR path, PDWORD cluster_size, PDWORDLONG free, PDWORDLONG total)
+ BOOL WINAPI GetDiskInfoA(PCSTR p0, PDWORD p1, PDWORDLONG p2, PDWORDLONG p3)
{
- BOOL ret;
- ULARGE_INTEGER bytes_free, bytes_total;
-
- TRACE("(%s, %p, %p, %p)\n", debugstr_a(path), cluster_size, free, total);
-
- if (!path)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
+ FIXME("(%p, %p, %p, %p)\n", p0, p1, p2, p3);
- return FALSE;
-}
+ return FALSE;
+ }
- if ((ret = GetDiskFreeSpaceExA(path, NULL, &bytes_total, &bytes_free)))
- {
- if (cluster_size) *cluster_size = 1;
- if (free) *free = bytes_free.QuadPart;
- if (total) *total = bytes_total.QuadPart;
- }
- return ret;
- }
-
/***********************************************************************
* RegisterUrlCacheNotification (WININET.@)
*/
KsDiscardEvent(
IN PKSEVENT_ENTRY EventEntry)
{
- //UNIMPLEMENTED;
+ /* sanity check */
+ ASSERT(EventEntry->Object);
+
+ if (EventEntry->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EventEntry->NotificationType == KSEVENTF_EVENT_HANDLE)
+ {
+ /* release object */
+ ObDereferenceObject(EventEntry->Object);
- }
++}
+
+ /* free event entry */
+ ExFreePool(EventEntry);
}
KsGenerateEvent(
IN PKSEVENT_ENTRY EntryEvent)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
+ if (EntryEvent->NotificationType == KSEVENTF_EVENT_HANDLE || EntryEvent->NotificationType == KSEVENTF_EVENT_OBJECT)
+ {
+ /* signal event */
+ KeSetEvent(EntryEvent->Object, EntryEvent->Reserved, FALSE);
- }
++}
+ else if (EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_OBJECT)
+ {
+ /* release semaphore */
+ KeReleaseSemaphore(EntryEvent->Object, EntryEvent->Reserved, EntryEvent->SemaphoreAdjustment, FALSE);
+ }
+ else if (EntryEvent->NotificationType == KSEVENTF_DPC)
+ {
+ /* increment reference count to indicate dpc is pending */
+ InterlockedIncrement((PLONG)&EntryEvent->EventData->Dpc.ReferenceCount);
+ /* queue dpc */
+ KeInsertQueueDpc((PRKDPC)EntryEvent->Object, NULL, NULL);
+ }
+ else if (EntryEvent->NotificationType == KSEVENTF_WORKITEM)
+ {
+ /* queue work item */
+ ExQueueWorkItem((PWORK_QUEUE_ITEM)EntryEvent->Object, PtrToUlong(EntryEvent->BufferItem));
+ }
+ else if (EntryEvent->NotificationType == KSEVENTF_KSWORKITEM)
+ {
+ /* queue work item of ks worker */
+ return KsQueueWorkItem((PKSWORKER)EntryEvent->Object, (PWORK_QUEUE_ITEM)EntryEvent->DpcItem);
+ }
+ else
+ {
+ /* unsupported type requested */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ return STATUS_SUCCESS;
}
/*
switch(MinorFunction) {
case TDI_SEND:
case TDI_RECEIVE:
- TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
+ DisType = exAllocatePool(NonPagedPool, sizeof(DISCONNECT_TYPE));
+ if (DisType)
+ {
+ DisType->Type = TDI_DISCONNECT_RELEASE |
+ ((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0);
+ DisType->Context = TranContext->Handle.ConnectionContext;
+ DisType->Irp = Irp;
+
- break;
+ TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
+
+ if (!ChewCreate(DispDoDisconnect, DisType))
+ exFreePool(DisType);
+ }
+
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+ return;
case TDI_SEND_DATAGRAM:
if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
/*
* @implemented
*/
-
- VP_STATUS NTAPI
+ VP_STATUS
+ NTAPI
VideoPortEnableInterrupt(IN PVOID HwDeviceExtension)
{
- PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+#ifndef _M_AMD64
+ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
- BOOLEAN Status;
-
- TRACE_(VIDEOPRT, "VideoPortEnableInterrupt\n");
+ BOOLEAN InterruptValid;
- DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+ /* Get the device extension */
+ DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
- Status = HalEnableSystemInterrupt(
- DeviceExtension->InterruptVector,
+ /* Fail if the driver didn't register an ISR */
+ if (!DeviceExtension->DriverExtension->InitializationData.HwInterrupt)
+ {
+ /* No ISR, no interrupts */
+ return ERROR_INVALID_FUNCTION;
+ }
+
+ /* Re-enable the interrupt and return */
+ InterruptValid = HalEnableSystemInterrupt(DeviceExtension->InterruptVector,
- 0,
- DeviceExtension->InterruptLevel);
+ 0,
+ DeviceExtension->InterruptLevel);
- return Status ? NO_ERROR : ERROR_INVALID_PARAMETER;
+ /* Make sure the interrupt was valid */
+ ASSERT(InterruptValid == TRUE);
+
+ /* Return to caller */
+ return NO_ERROR;
+#else
+ /* FIXME: Function still present? If so what to use instead of HalEnableSystemInterrupt? */
+ UNIMPLEMENTED;
+ return ERROR_INVALID_FUNCTION;
+#endif
}
/*
* @implemented
*/
-
- VP_STATUS NTAPI
+ VP_STATUS
+ NTAPI
VideoPortDisableInterrupt(IN PVOID HwDeviceExtension)
{
- PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+#ifndef _M_AMD64
+ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
- BOOLEAN Status;
-
- TRACE_(VIDEOPRT, "VideoPortDisableInterrupt\n");
- DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+ /* Get the device extension */
+ DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
- Status = HalDisableSystemInterrupt(
- DeviceExtension->InterruptVector,
- 0);
+ /* Fail if the driver didn't register an ISR */
+ if (!DeviceExtension->DriverExtension->InitializationData.HwInterrupt)
+ {
+ /* No ISR, no interrupts */
+ return ERROR_INVALID_FUNCTION;
+ }
- return Status ? NO_ERROR : ERROR_INVALID_PARAMETER;
+ /* Disable the interrupt and return */
+ HalDisableSystemInterrupt(DeviceExtension->InterruptVector,
- 0);
++ 0);
+ return NO_ERROR;
+#else
+ /* FIXME: Function still present? If so what to use instead of HalDisableSystemInterrupt? */
+ UNIMPLEMENTED;
+ return ERROR_INVALID_FUNCTION;
+#endif
}
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- // access IrpTarget
- IrpTarget = (IIrpTarget *)IoStack->FileObject->FsContext;
-
+ // get dispatch context
+ DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext;
// let IrpTarget handle request
- return IrpTarget->Close(DeviceObject, Irp);
+ Status = DispatchContext->Target->Close(DeviceObject, Irp);
+
+ if (NT_SUCCESS(Status))
+ {
+ KsFreeObjectHeader(DispatchContext->ObjectHeader);
+ FreeItem(DispatchContext, TAG_PORTCLASS);
- }
++}
+ // done
+ return Status;
}
NTSTATUS
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
- IoStack->FileObject->FsContext = (PVOID)Target;
+ DispatchContext = (PDISPATCH_CONTEXT)AllocateItem(NonPagedPool, sizeof(DISPATCH_CONTEXT), TAG_PORTCLASS);
+ if (!DispatchContext)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ // allocate object header
Status = KsAllocateObjectHeader(&ObjectHeader, CreateItemCount, CreateItem, Irp, &DispatchTable);
- DPRINT("KsAllocateObjectHeader result %x\n", Status);
+
+ if (!NT_SUCCESS(Status))
+ {
+ // free dispatch context
+ FreeItem(DispatchContext, TAG_PORTCLASS);
+ // done
- return Status;
- }
++ return Status;
++}
+
+ // initialize dispatch context
+ DispatchContext->ObjectHeader = ObjectHeader;
+ DispatchContext->Target = Target;
+ DispatchContext->CreateItem = CreateItem;
+
+ // store dispatch context
+ IoStack->FileObject->FsContext = DispatchContext;
+
+ DPRINT("KsAllocateObjectHeader result %x Target %p Context %p\n", Status, Target, DispatchContext);
return Status;
}
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
+ PIO_STACK_LOCATION IoStack;
+ PPCLASS_DEVICE_EXTENSION DeviceExtension;
+ PQUERY_POWER_CONTEXT PwrContext;
+ POWER_STATE PowerState;
+ NTSTATUS Status = STATUS_SUCCESS;
+
DPRINT("PortClsPower called\n");
- // TODO
+ // get currrent stack location
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
+ if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER)
+ {
+ // just forward the request
+ Status = PcForwardIrpSynchronous(DeviceObject, Irp);
+
+ // start next power irp
+ PoStartNextPowerIrp(Irp);
+
+ // complete request
+ Irp->IoStatus.Status = Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
+ // done
+ return Status;
- }
++}
+
+
+ // get device extension
+ DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+ // get current request type
+ if (IoStack->Parameters.Power.Type == DevicePowerState)
+ {
+ // request for device power state
+ if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState)
+ {
+ // nothing has changed
+ if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
+ {
+ // only forward query requests
+ Status = PcForwardIrpSynchronous(DeviceObject, Irp);
+ }
+
+ // start next power irp
+ PoStartNextPowerIrp(Irp);
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+
+ if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
+ {
+ // check if there is a registered adapter power management
+ if (DeviceExtension->AdapterPowerManagement)
+ {
+ // it is query if the change can be changed
+ PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
+ Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState);
+
+ // sanity check
+ PC_ASSERT(Status == STATUS_SUCCESS);
+ }
+
+ // only forward query requests
+ PcForwardIrpSynchronous(DeviceObject, Irp);
+
+ // start next power irp
+ PoStartNextPowerIrp(Irp);
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+ else
+ {
+ // set power state
+ PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
+ PoSetPowerState(DeviceObject, DevicePowerState, PowerState);
+
+ // check if there is a registered adapter power management
+ if (DeviceExtension->AdapterPowerManagement)
+ {
+ // notify of a power change state
+ DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState);
+ }
+
+ // FIXME call all registered IPowerNotify interfaces via ISubdevice interface
+
+ // store new power state
+ DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState;
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+ }
+ else
+ {
+ // sanity check
+ PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState);
+
+ if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
+ {
+ // mark irp as pending
+ IoMarkIrpPending(Irp);
+
+ // allocate power completion context
+ PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS);
+
+ if (!PwrContext)
+ {
+ // no memory
+ PoStartNextPowerIrp(Irp);
+
+ // complete and forget
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+
+ // setup power context
+ PwrContext->Irp = Irp;
+ PwrContext->DeviceObject = DeviceObject;
+
+ // pass the irp down
+ PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState);
+ Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL);
+
+ // check for success
+ if (!NT_SUCCESS(Status))
+ {
+ // failed
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+
+ // done
+ return STATUS_PENDING;
+ }
+ else
+ {
+ // set power request
+ DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState;
+
+ // only forward query requests
+ Status = PcForwardIrpSynchronous(DeviceObject, Irp);
+
+ // start next power irp
+ PoStartNextPowerIrp(Irp);
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+ }
}
NTSTATUS
}
// get first stream header
- Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+
+ if (Irp->RequestorMode == UserMode)
+ Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+ else
+ Header = (PKSSTREAM_HEADER)Irp->UserBuffer;
+
+ // sanity check
+ PC_ASSERT(Header);
// calculate num headers
NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
PC_ASSERT(Header);
PC_ASSERT(Mdl);
- Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+ if (Irp->RequestorMode == UserMode)
+ {
+ Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+ }
if (!Header->Data)
{
return;
}
- // irp has been processed completly
+ // irp has been processed completly
NumData = 0;
- StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer;
+ if (m_Irp->RequestorMode == KernelMode)
+ StreamHeader = (PKSSTREAM_HEADER)m_Irp->UserBuffer;
+ else
+ StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer;
// loop all stream headers
for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++)
if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP)
{
- /* FIXME complete pending irps with successfull state */
+ // FIXME
+ // complete with successful state
Pin->m_IrpQueue->CancelBuffers();
}
- // store result
- Irp->IoStatus.Information = sizeof(KSSTATE);
-- }
-
+ // store result
+ Irp->IoStatus.Information = sizeof(KSSTATE);
- return Status;
++ }
}
else if (Request->Flags & KSPROPERTY_TYPE_GET)
{
BufferLength = Position - m_CommonBufferOffset;
m_Position.PlayOffset += BytesToCopy;
- }
+
+ if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
+ {
+ // normalize position
+ m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
}
}
++}
VOID
CPortPinWaveCyclic::UpdateCommonBufferOverlap(
m_Position.PlayOffset += BytesToCopy;
BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
- }
+
+ if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
+ {
+ // normalize position
+ m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
++ }
+
}
if (Gap == Length)
NTSTATUS
NTAPI
- CPortPinWaveCyclic::HandleKsProperty(
+ CPortPinWaveCyclic::DeviceIoControl(
+ IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
+ PIO_STACK_LOCATION IoStack;
PKSPROPERTY Property;
- NTSTATUS Status;
UNICODE_STRING GuidString;
- PIO_STACK_LOCATION IoStack;
-
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- DPRINT("IPortPinWave_HandleKsProperty entered\n");
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
+ ULONG Data = 0;
+ KSRESET ResetValue;
+ /* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
- if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
{
- DPRINT("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
-
+ /* handle property with subdevice descriptor */
- Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
+ Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
- if (Status == STATUS_NOT_FOUND)
- {
- Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+ if (Status == STATUS_NOT_FOUND)
+ {
+ Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
- RtlStringFromGUID(Property->Set, &GuidString);
- DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
- RtlFreeUnicodeString(&GuidString);
- }
+ RtlStringFromGUID(Property->Set, &GuidString);
+ DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
+ RtlFreeUnicodeString(&GuidString);
+ }
-
- if (Status != STATUS_PENDING)
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
{
- Irp->IoStatus.Status = Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ Status = PcHandleEnableEventWithTable(Irp, &m_Descriptor);
}
-
- return Status;
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
+ {
+ Status = PcHandleDisableEventWithTable(Irp, &m_Descriptor);
- }
+}
-
- NTSTATUS
- NTAPI
- CPortPinWaveCyclic::HandleKsStream(
- IN PIRP Irp)
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
- {
+{
- NTSTATUS Status;
- ULONG Data = 0;
- InterlockedIncrement((PLONG)&m_TotalPackets);
-
- DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
-
- Status = m_IrpQueue->AddMapping(Irp, &Data);
-
+ /// FIXME
+ Status = KsAcquireResetValue(Irp, &ResetValue);
+ DPRINT("Status %x Value %u\n", Status, ResetValue);
+ /* check for success */
- if (NT_SUCCESS(Status))
- {
+ if (NT_SUCCESS(Status))
+ {
- m_Position.WriteOffset += Data;
-
- return STATUS_PENDING;
+ if (ResetValue == KSRESET_BEGIN)
+ {
+ m_IrpQueue->CancelBuffers();
+ m_ResetState = KSRESET_BEGIN;
- }
+ }
-
- return Status;
+ else if (ResetValue == KSRESET_END)
+ {
+ m_ResetState = KSRESET_END;
- }
+}
-
- NTSTATUS
- NTAPI
- CPortPinWaveCyclic::DeviceIoControl(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+ }
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
- {
+{
- PIO_STACK_LOCATION IoStack;
+ /* increment total number of packets */
+ InterlockedIncrement((PLONG)&m_TotalPackets);
- IoStack = IoGetCurrentIrpStackLocation(Irp);
+ DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
+ /* is the device not currently reset */
+ if (m_ResetState == KSRESET_END)
+ {
+ /* add the mapping */
+ Status = m_IrpQueue->AddMapping(Irp, &Data);
- if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
+ /* check for success */
+ if (NT_SUCCESS(Status))
- {
+ {
- return HandleKsProperty(Irp);
+ m_Position.WriteOffset += Data;
+ Status = STATUS_PENDING;
- }
- }
+ }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
- {
- /// FIXME
- /// handle enable event
+ }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
+ else
- {
+ {
- /// FIXME
- /// handle disable event
+ /* reset request is currently in progress */
+ Status = STATUS_DEVICE_NOT_READY;
+ DPRINT1("NotReady\n");
- }
+ }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
- {
- /// FIXME
- /// handle reset state
- }
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
- {
- return HandleKsStream(Irp);
}
else
{
return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
}
- UNIMPLEMENTED
-
- Irp->IoStatus.Information = 0;
- Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ if (Status != STATUS_PENDING)
+ {
+ Irp->IoStatus.Status = Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
- return STATUS_UNSUCCESSFUL;
+ return Status;
}
NTSTATUS
// access property
Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
- // check if this a GUID_NULL request
- if (Status == STATUS_NOT_FOUND)
- if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
-- {
- if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
- return Status;
-
- // check if its a request for a topology node
- if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
- {
- // request is out of bounds
- Irp->IoStatus.Information = 0;
- return STATUS_INVALID_PARAMETER;
- }
+ if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
+ {
+ // request is out of bounds
+ Irp->IoStatus.Information = 0;
+ return STATUS_INVALID_PARAMETER;
+ }
- Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+ Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
- if (!Node->AutomationTable)
- {
- // request is out of bounds
- Irp->IoStatus.Information = 0;
- return STATUS_INVALID_PARAMETER;
- }
+ if (!Node->AutomationTable)
+ {
+ // request is out of bounds
+ Irp->IoStatus.Information = 0;
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ PC_ASSERT(Node->AutomationTable);
+ PC_ASSERT(Node->AutomationTable->PropertyCount);
+ PC_ASSERT(Node->AutomationTable->PropertyItemSize);
- PC_ASSERT(Node->AutomationTable);
- PC_ASSERT(Node->AutomationTable->PropertyCount);
- PC_ASSERT(Node->AutomationTable->PropertyItemSize);
-
- Buffer = (LPGUID)AllocateItem(NonPagedPool, sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
- if (!Buffer)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
- for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
- {
- BOOL Found = FALSE;
- for (SubIndex = 0; SubIndex < Count; Index++)
- {
- if (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
- {
- Found = TRUE;
- break;
- }
- }
- if (!Found)
- {
- RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
- Count++;
- }
- PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
- }
+ Buffer = (LPGUID)AllocateItem(NonPagedPool, sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
+ if (!Buffer)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
-
- ULONG Count = 0, SubIndex;
+ PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
+ for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
+ {
+ BOOL Found = FALSE;
+ for (SubIndex = 0; SubIndex < Count; Index++)
+ {
+ if (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
+ {
+ Found = TRUE;
+ break;
+ }
+ }
+ if (!Found)
+ {
+ RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
+ Count++;
+ }
+ PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
+ }
- Irp->IoStatus.Information = sizeof (GUID) * Count;
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (GUID) * Count)
- {
- // buffer too small
- FreeItem(Buffer, TAG_PORTCLASS);
- return STATUS_MORE_ENTRIES;
- }
-
- RtlMoveMemory(Irp->UserBuffer, Buffer, sizeof (GUID) * Count);
- FreeItem(Buffer, TAG_PORTCLASS);
- return STATUS_SUCCESS;
-}
+ // store result length
- else /*if (Property->Property.Flags == (KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY) ||
- Property->Property.Flags == (KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY) ||
- Property->Property.Flags == (KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY)) */
+ Irp->IoStatus.Information = sizeof (GUID) * Count;
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (GUID) * Count)
+ {
+ // buffer too small
+ FreeItem(Buffer, TAG_PORTCLASS);
+ return STATUS_MORE_ENTRIES;
+ }
+
+ RtlMoveMemory(Irp->UserBuffer, Buffer, sizeof (GUID) * Count);
+ FreeItem(Buffer, TAG_PORTCLASS);
+ return STATUS_SUCCESS;
+ }
-{
+
+ NTSTATUS
+ PcFindNodePropertyHandler(
+ PIRP Irp,
+ PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
+ OUT PPCPROPERTY_ITEM * OutPropertyItem)
- //UNICODE_STRING GuidString;
+ {
+ PPCNODE_DESCRIPTOR Node;
+ PPCPROPERTY_ITEM PropertyItem;
+ PIO_STACK_LOCATION IoStack;
+ PKSP_NODE Property;
+ ULONG Index;
+
+ // get current irp stack location
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ // access property
+ Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
- if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
- {
- // request is out of bounds
+ if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
+ {
+ // request is out of bounds
- Irp->IoStatus.Information = 0;
+ DPRINT("InvalidIndex %u %u\n", Property->NodeId, SubDeviceDescriptor->DeviceDescriptor->NodeCount);
- return STATUS_INVALID_PARAMETER;
- }
+ return STATUS_INVALID_PARAMETER;
+ }
- Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+ Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
- if (!Node->AutomationTable)
- {
- // request is out of bounds
- Irp->IoStatus.Information = 0;
- return STATUS_NOT_FOUND;
- }
+ if (!Node->AutomationTable)
+ {
+ // request is out of bounds
+ Irp->IoStatus.Information = 0;
+ return STATUS_NOT_FOUND;
+ }
- PC_ASSERT(Node->AutomationTable);
- PC_ASSERT(Node->AutomationTable->PropertyCount);
- PC_ASSERT(Node->AutomationTable->PropertyItemSize);
+ // sanity checks
+ PC_ASSERT(Node->AutomationTable);
+ PC_ASSERT(Node->AutomationTable->PropertyCount);
+ PC_ASSERT(Node->AutomationTable->PropertyItemSize);
- PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
+ PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
- for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
- {
- if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
- {
+ DPRINT("NodeId %u PropertyCount %u\n", Property->NodeId, Node->AutomationTable->PropertyCount);
- if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
+ for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
+ {
+ if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
+ {
-{
+ //found property handler
+ *OutPropertyItem = PropertyItem;
+ return STATUS_SUCCESS;
+ }
+ PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
+ }
+
+ // no handler yet found
+ DPRINT("NotFound\n");
+ return STATUS_NOT_FOUND;
+ }
+
+ NTSTATUS
+ PcNodeBasicSupportHandler(
+ PIRP Irp,
+ PPCPROPERTY_ITEM PropertyItem)
- if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
- {
+ {
- PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
+ PULONG Flags;
+ PIO_STACK_LOCATION IoStack;
+ PKSPROPERTY_DESCRIPTION Description;
+ PKSP_NODE Property;
+
+ // get current irp stack location
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ // access property
+ Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
- PULONG Flags = (PULONG)Irp->UserBuffer;
+ PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
+ Flags= (PULONG)Irp->UserBuffer;
- /* reset flags */
+ // reset flags
- *Flags = 0;
+ *Flags = 0;
- if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
- *Flags |= KSPROPERTY_TYPE_SET;
+ if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
+ *Flags |= KSPROPERTY_TYPE_SET;
- if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
- *Flags |= KSPROPERTY_TYPE_GET;
+ if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
+ *Flags |= KSPROPERTY_TYPE_GET;
- Irp->IoStatus.Information = sizeof(ULONG);
+ // store result length
+ Irp->IoStatus.Information = sizeof(ULONG);
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
- {
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
+ {
- /* get output buffer */
- PKSPROPERTY_DESCRIPTION Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
+ // get output buffer
+ Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
- /* store result */
+ // store result
- Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
- Description->PropTypeSet.Set = KSPROPTYPESETID_General;
- Description->PropTypeSet.Id = 0;
- Description->PropTypeSet.Flags = 0;
- Description->MembersListCount = 0;
- Description->Reserved = 0;
-
- Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
- }
- return STATUS_SUCCESS;
-}
+ Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
+ Description->PropTypeSet.Set = KSPROPTYPESETID_General;
+ Description->PropTypeSet.Id = 0;
+ Description->PropTypeSet.Flags = 0;
+ Description->MembersListCount = 0;
+ Description->Reserved = 0;
+
+ Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
+ }
+ return STATUS_SUCCESS;
+ }
+
+
+ NTSTATUS
+ PcHandleNodePropertyRequest(
+ PIRP Irp,
+ IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
+ {
+ PIO_STACK_LOCATION IoStack;
+ PPCPROPERTY_ITEM PropertyItem;
+ PPCPROPERTY_REQUEST PropertyRequest;
+ PKSP_NODE Property;
+ NTSTATUS Status;
+
+ // get current irp stack location
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
+ {
+ // certainly not a node property request
+ return STATUS_NOT_FOUND;
- }
+ }
+ // access property
+ Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+ if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
+ {
+ return PcHandleGuidNullRequest(Irp, SubDeviceDescriptor);
+ }
+
+ // find property handler
+ Status = PcFindNodePropertyHandler(Irp, SubDeviceDescriptor, &PropertyItem);
- PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
- if (!PropertyRequest)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
- PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
- PropertyRequest->Irp = Irp;
- PropertyRequest->Node = Property->NodeId;
- PropertyRequest->PropertyItem = PropertyItem;
- PropertyRequest->Verb = Property->Property.Flags;
- PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
- PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
- PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
- PropertyRequest->Value = Irp->UserBuffer;
-
- Status = PropertyItem->Handler(PropertyRequest);
-
- if (Status != STATUS_PENDING)
- {
+ // check for success
+ if (!NT_SUCCESS(Status))
+ {
+ // might not be a node property request
+ DPRINT("NotFound\n");
+ return STATUS_NOT_FOUND;
+ }
+
+ if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ // caller issued a basic property request
+ if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
+ {
+ // driver does not have a basic support handler
+ return PcNodeBasicSupportHandler(Irp, PropertyItem);
+ }
+ }
+
+ // allocate a property request
- PC_ASSERT(SubDeviceDescriptor->UnknownMiniport);
+ PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
+ if (!PropertyRequest)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
- //DPRINT("Status %x ValueSize %u
-
+ PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
+ PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
+ PropertyRequest->Irp = Irp;
+ PropertyRequest->Node = Property->NodeId;
+ PropertyRequest->PropertyItem = PropertyItem;
+ PropertyRequest->Verb = Property->Property.Flags;
+ PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
+ PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
+ PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+ PropertyRequest->Value = Irp->UserBuffer;
+
+ Status = PropertyItem->Handler(PropertyRequest);
+
+ if (Status != STATUS_PENDING)
+ {
- Irp->IoStatus.Information = PropertyRequest->ValueSize;
- ExFreePool(PropertyRequest);
- }
+ //request completed
- #if 0
- RtlStringFromGUID(Property->Property.Set, &GuidString);
- DPRINT("Id %u Flags %x Set %S FlagsItem %x Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, PropertyItem->Flags, Status);
- RtlFreeUnicodeString(&GuidString);
- #endif
+ Irp->IoStatus.Information = PropertyRequest->ValueSize;
+ ExFreePool(PropertyRequest);
+ }
- return Status;
-}
+
+ // done
+ DPRINT("Status %x\n", Status);
- PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
+ return Status;
+ }
- }
+
+ NTSTATUS
+ NTAPI
+ PcHandlePropertyWithTable(
+ IN PIRP Irp,
+ IN ULONG PropertySetCount,
+ IN PKSPROPERTY_SET PropertySet,
+ IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
+ {
+ NTSTATUS Status;
+
+ // try handle it as node property request
+ Status = PcHandleNodePropertyRequest(Irp, SubDeviceDescriptor);
+
+ if (Status == STATUS_NOT_FOUND)
+ {
+ // store device descriptor
+ KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
+
+ /* then try KsPropertyHandler */
+ Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet);
- #if 0
- RtlStringFromGUID(Property->Property.Set, &GuidString);
- DPRINT("Id %u Flags %x Set %S Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, Status);
- RtlFreeUnicodeString(&GuidString);
- #endif
- }
- }
+ }
+
return Status;
}
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
}
- }
-
+
+ EventItem = (PPCEVENT_ITEM)FilterDescription->AutomationTable->Events;
+ for(Index = 0; Index < FilterDescription->AutomationTable->EventCount; Index++)
+ {
+ RtlStringFromGUID(*EventItem->Set, &GuidString);
+ DPRINT1("EventIndex %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, EventItem->Id, EventItem->Flags);
+
+ EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + FilterDescription->AutomationTable->EventItemSize);
- }
+ }
++
++ }
+ }
+
+ if (FilterDescription->Nodes)
+ {
+ DPRINT1("NodeCount %u NodeSize %u expected %u\n", FilterDescription->NodeCount, FilterDescription->NodeSize, sizeof(PCNODE_DESCRIPTOR));
+ NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
+ for(Index = 0; Index < FilterDescription->NodeCount; Index++)
+ {
+ DPRINT("Index %u AutomationTable %p\n", Index, NodeDescriptor->AutomationTable);
+
+ if (NodeDescriptor->AutomationTable)
+ {
+ DPRINT1("Index %u EventCount %u\n", Index, NodeDescriptor->AutomationTable->EventCount);
+ EventItem = (PPCEVENT_ITEM)NodeDescriptor->AutomationTable->Events;
+ for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->EventCount; SubIndex++)
+ {
+ RtlStringFromGUID(*EventItem->Set, &GuidString);
+ DPRINT1("EventIndex %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, EventItem->Id, EventItem->Flags);
+
+ EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + FilterDescription->AutomationTable->EventItemSize);
++}
+
+ }
+
+
+ NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
}
+
+
+
}
#pragma code_seg()
int __cdecl _purecall (void)
{
- return 0;
+ return 0;
}
+
+ #else
+
+ extern "C" {
+ void __cxa_pure_virtual()
+ {
+ // put error handling here
+
+ DbgBreakPoint();
+
+ }
+ }
+ #endif
<?xml version="1.0"?>
<!DOCTYPE group SYSTEM "../../../../tools/rbuild/project.dtd">
<group xmlns:xi="http://www.w3.org/2001/XInclude">
- <directory name="mpu401">
+ <!--directory name="mpu401">
<xi:include href="mpu401/mpu401.rbuild" />
- </directory>
- <directory name="CMIDriver">
+ </directory-->
++ <!--directory name="CMIDriver">
+ <xi:include href="CMIDriver/cmidriver.rbuild" />
- </directory>
++ </directory-->
+
<!--directory name="sb16">
<xi:include href="sb16/sb16.rbuild" />
</directory-->
SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
return STATUS_SUCCESS;
}
- }
+ else if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
+ {
+ if (ClientInfo->hPins[Index].NotifyEvent)
+ {
+ ObDereferenceObject(ClientInfo->hPins[Index].NotifyEvent);
+ ClientInfo->hPins[Index].NotifyEvent = NULL;
++ }
+ }
}
SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
- WDMAUD_CLIENT *pClient;
+ PWDMAUD_CLIENT pClient;
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
ULONG Index;
+ KIRQL OldIrql;
- DPRINT("WdmAudCleanup\n");
+ /* get device extension */
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ /* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
- pClient = (WDMAUD_CLIENT*)IoStack->FileObject->FsContext;
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+
+ /* get client context struct */
+ pClient = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
- if (pClient)
- {
+ /* sanity check */
+ ASSERT(pClient);
+
+ /* acquire client context list lock */
+ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
+
+ /* remove entry */
+ RemoveEntryList(&pClient->Entry);
+
+ /* release lock */
+ KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
+
+ /* check if all audio pins have been closed */
- for (Index = 0; Index < pClient->NumPins; Index++)
- {
- DPRINT("Index %u Pin %p Type %x\n", Index, pClient->hPins[Index].Handle, pClient->hPins[Index].Type);
- if (pClient->hPins[Index].Handle && pClient->hPins[Index].Type != MIXER_DEVICE_TYPE)
- {
+ for (Index = 0; Index < pClient->NumPins; Index++)
+ {
+ DPRINT("Index %u Pin %p Type %x\n", Index, pClient->hPins[Index].Handle, pClient->hPins[Index].Type);
+ if (pClient->hPins[Index].Handle && pClient->hPins[Index].Type != MIXER_DEVICE_TYPE)
+ {
+ /* found an still open audio pin */
- ZwClose(pClient->hPins[Index].Handle);
- }
- }
+ ZwClose(pClient->hPins[Index].Handle);
+ }
+ }
- if (pClient->hPins)
- ExFreePool(pClient->hPins);
+ /* free pin array */
- {
+ if (pClient->hPins)
- }
+ ExFreePool(pClient->hPins);
- ExFreePool(pClient);
+ /* free client context struct */
- IoStack->FileObject->FsContext = NULL;
+ ExFreePool(pClient);
+
+ /* clear old client pointer */
- }
+ IoStack->FileObject->FsContext = NULL;
+ /* complete request */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
if (!bSet)
{
- for(Index = 0; Index < VolumeData->ValuesCount; Index++)
+ dwValue = GetVolumeControlIndex(VolumeData, (LONG)Value);
+ /* FIXME SEH */
+ Input->dwValue = dwValue;
+ }
+ else
- {
+ {
- if (VolumeData->Values[Index] > Value)
- {
- /* FIXME SEH */
- Input->dwValue = VolumeData->InputSteppingDelta * Index;
+ /* notify clients of a line change */
+ NotifyWdmAudClients(DeviceObject, MM_MIXM_CONTROL_CHANGE, DeviceInfo->hDevice, MixerControl->dwControlID);
+ }
- return Status;
-}
+ return Status;
+ }
+
+ NTSTATUS
+ NTAPI
+ WdmAudGetMixerEvent(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PWDMAUD_DEVICE_INFO DeviceInfo,
+ IN PWDMAUD_CLIENT ClientInfo)
+ {
+ PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+ PMIXER_EVENT Event = NULL;
+ PLIST_ENTRY Entry;
+ KIRQL OldIrql;
+
+ /* get device extension */
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* acquire client context lock */
+ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
+
+ /* point to first entry */
+ Entry = ClientInfo->MixerEventList.Flink;
+
+ while(Entry != &ClientInfo->MixerEventList)
+ {
+ /* get mixer event */
+ Event = (PMIXER_EVENT)CONTAINING_RECORD(Entry, MIXER_EVENT, Entry);
+
+ if (Event->hMixer == DeviceInfo->hDevice)
+ {
+ /* found an event for that particular device */
+ RemoveEntryList(&Event->Entry);
+ break;
}
- Input->dwValue = VolumeData->InputSteppingDelta * (VolumeData->ValuesCount-1);
+
+ /* no match found */
+ Event = NULL;
+
+ /* move to next entry */
+ Entry = Entry->Flink;
}
- return Status;
+ /* release client context lock */
+ KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
+
+ if (!Event)
+ {
+ /* no events available */
+ return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
- }
++}
+
+ /* store event result */
+ DeviceInfo->u.MixerEvent.hMixer = Event->hMixer;
+ DeviceInfo->u.MixerEvent.NotificationType = Event->NotificationType;
+ DeviceInfo->u.MixerEvent.Value = Event->Value;
+
+ /* free event info */
+ ExFreePool(Event);
+
+ /* done */
+ return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
}
- BOOLEAN
+ VOID
NTAPI
- HalDisableSystemInterrupt(
- ULONG Vector,
+ HalDisableSystemInterrupt(ULONG Vector,
- KIRQL Irql)
+ KIRQL Irql)
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED;
-
- return TRUE;
}
}
- BOOLEAN
+ VOID
NTAPI
- HalDisableSystemInterrupt(
- ULONG Vector,
+ HalDisableSystemInterrupt(ULONG Vector,
- KIRQL Irql)
+ KIRQL Irql)
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED;
-
- return TRUE;
}
VOID
.long 0xFFFFFFFB /* IRQL 30 */
.long 0xFFFFFFFB /* IRQL 31 */
- HalpSysIntHandler:
+ FindHigherIrqlMask:
+ .long 0xFFFFFFFE /* IRQL 0 */
+ .long 0xFFFFFFFC /* IRQL 1 */
+ .long 0xFFFFFFF8 /* IRQL 2 */
+ .long 0xFFFFFFF0 /* IRQL 3 */
+ .long 0x7FFFFF0 /* IRQL 4 */
+ .long 0x3FFFFF0 /* IRQL 5 */
+ .long 0x1FFFFF0 /* IRQL 6 */
+ .long 0x0FFFFF0 /* IRQL 7 */
+ .long 0x7FFFF0 /* IRQL 8 */
+ .long 0x3FFFF0 /* IRQL 9 */
+ .long 0x1FFFF0 /* IRQL 10 */
+ .long 0x0FFFF0 /* IRQL 11 */
+ .long 0x7FFF0 /* IRQL 12 */
+ .long 0x3FFF0 /* IRQL 13 */
+ .long 0x1FFF0 /* IRQL 14 */
+ .long 0x0FFF0 /* IRQL 15 */
+ .long 0x7FF0 /* IRQL 16 */
+ .long 0x3FF0 /* IRQL 17 */
+ .long 0x1FF0 /* IRQL 18 */
+ .long 0x1FF0 /* IRQL 19 */
+ .long 0x17F0 /* IRQL 20 */
+ .long 0x13F0 /* IRQL 21 */
+ .long 0x11F0 /* IRQL 22 */
+ .long 0x10F0 /* IRQL 23 */
+ .long 0x1070 /* IRQL 24 */
+ .long 0x1030 /* IRQL 25 */
+ .long 0x1010 /* IRQL 26 */
+ .long 0x10 /* IRQL 27 */
+ .long 0 /* IRQL 28 */
+ .long 0 /* IRQL 29 */
+ .long 0 /* IRQL 30 */
+ .long 0 /* IRQL 31 */
+
+ HalpSpecialDismissTable:
- .rept 7
+.rept 7
.long GenericIRQ /* IRQ 0-7 */
- .endr
+.endr
.long IRQ7 /* IRQ 7 */
- .rept 7
- .long GenericIRQ /* IRQ 8-15 */
+ .rept 5
+ .long GenericIRQ /* IRQ 8-12 */
- .endr
+.endr
+ .long IRQ13 /* IRQ 13 */
+ .long GenericIRQ /* IRQ 14 */
.long IRQ15 /* IRQ 15 */
- .rept 20
+.rept 20
.long GenericIRQ /* IRQ 16-35 */
- .endr
+.endr
#if DBG
.rept 172
.long InvalidIRQ /* IRQ 36-207 */
cmp ax, 0
jnz InitLoop
-/* Restore interrupts and return */
+ /* Read EISA Edge/Level Register */
+ mov edx, 0x4D1
+ in al, dx
+ mov ah, al
+ dec edx
+ in al, dx
+
+ /* Clear reserved bits and see if there's anything there */
+ and eax, 0xDEF8
+ cmp eax, 0xDEF8
+ jz NoEisa
+
+ /* FIXME */
+ //UNHANDLED_PATH
+
+ /* Restore interrupts and return */
+ NoEisa:
popf
pop esi
ret
_@KfLowerIrql@4:
@KfLowerIrql@4:
- /* Save flags since we'll disable interrupts */
- pushf
+ /* Cleanup IRQL */
+ and ecx, 0xFF
/* Validate IRQL */
- movzx ecx, cl
- #if DBG
+#if DBG
cmp cl, PCR[KPCR_IRQL]
ja InvalidIrql
- #endif
+#endif
+ /* Save flags since we'll disable interrupts */
+ pushf
+ cli
+
/* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
- cli
jbe SkipMask
/* Clear interrupt masks since there's a pending hardware interrupt */
_@KfRaiseIrql@4:
@KfRaiseIrql@4:
- /* Get the IRQL */
+ /* Get the IRQL */
- mov eax, PCR[KPCR_IRQL]
movzx ecx, cl
+ mov eax, PCR[KPCR_IRQL]
#if DBG
/* Validate it */
HalpLowerIrql (Irql, TRUE);
}
- BOOLEAN NTAPI
+ VOID
+ NTAPI
-HalDisableSystemInterrupt(ULONG Vector,
- KIRQL Irql)
+HalDisableSystemInterrupt (ULONG Vector,
+ KIRQL Irql)
{
ULONG irq;
_CRTIMP int __cdecl _iswcsym_l(wint_t _C,_locale_t _Locale);
_CRTIMP int __cdecl is_wctype(wint_t _C,wctype_t _Type);
#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || !defined (NO_OLDNAMES)
- int __cdecl iswblank(wint_t _C);
+ _CRTIMP int __cdecl iswblank(wint_t _C);
-#endif
+#endif
#endif
#ifndef _WDIRECT_DEFINED
typedef int HFILE;
typedef HICON HCURSOR;
typedef DWORD COLORREF;
++typedef DWORD* LPCOLORREF;
#ifdef _WIN64
typedef INT_PTR (FAR WINAPI *FARPROC)();
typedef INT_PTR (NEAR WINAPI *NEARPROC)();
MMRESULT
MmeCloseDevice(
-- IN DWORD PrivateHandle);
++ IN DWORD_PTR PrivateHandle);
MMRESULT
MmeGetPosition(
IN MMDEVICE_TYPE DeviceType,
IN DWORD DeviceId,
-- IN DWORD PrivateHandle,
++ IN DWORD_PTR PrivateHandle,
IN MMTIME* Time,
IN DWORD Size);
MMRESULT
MmeSetState(
-- IN DWORD PrivateHandle,
++ IN DWORD_PTR PrivateHandle,
IN BOOL bStart);
MMRESULT
MmeResetWavePlayback(
-- IN DWORD PrivateHandle);
++ IN DWORD_PTR PrivateHandle);
/*
PUNICODE_STRING ClassName);
#endif
--HANDLE
++DWORD_PTR
NTAPI
NtUserGetClipboardData(
UINT uFormat,
NTAPI
NtUserTranslateMessage(
LPMSG lpMsg,
-- HKL dwhkl );
++ UINT Flags );
BOOL
NTAPI
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
- <module name="bzip2" type="kernelmodedll" installbase="system32/drivers" installname="bzip2.dll">
+ <module name="bzip2" type="kernelmodedll" installbase="system32/drivers" installname="unbzip2.dll">
- <importlibrary definition="unbzip2.def" />
+ <importlibrary definition="unbzip2.spec" />
<define name="BZ_NO_STDIO" />
<define name="BZ_DECOMPRESS_ONLY" />
<library>ntoskrnl</library>
class CComObjectRootBase
{
public:
-- long m_dwRef;
++ LONG m_dwRef;
public:
CComObjectRootBase()
{
ULONG InternalAddRef()
{
ATLASSERT(m_dwRef >= 0);
-- return ThreadModel::Increment(reinterpret_cast<int *>(&m_dwRef));
++ return ThreadModel::Increment(&m_dwRef);
}
ULONG InternalRelease()
{
ATLASSERT(m_dwRef > 0);
-- return ThreadModel::Decrement(reinterpret_cast<int *>(&m_dwRef));
++ return ThreadModel::Decrement(&m_dwRef);
}
void Lock()
}
};
++#elif _AMD64_ //WARNING: NOT VERIFIED
++#pragma pack(push,1)
++struct thunkCode
++{
++ DWORD_PTR m_mov;
++ DWORD_PTR m_this;
++ BYTE m_jmp;
++ DWORD_PTR m_relproc;
++};
++#pragma pack(pop)
++
++class CWndProcThunk
++{
++public:
++ thunkCode m_thunk;
++ _AtlCreateWndData cd;
++public:
++ BOOL Init(WNDPROC proc, void *pThis)
++ {
++ m_thunk.m_mov = 0xffff8000042444C7LL;
++ m_thunk.m_this = (DWORD_PTR)pThis;
++ m_thunk.m_jmp = 0xe9;
++ m_thunk.m_relproc = DWORD_PTR(reinterpret_cast<char *>(proc) - (reinterpret_cast<char *>(this) + sizeof(thunkCode)));
++ return TRUE;
++ }
++
++ WNDPROC GetWNDPROC()
++ {
++ return reinterpret_cast<WNDPROC>(&m_thunk);
++ }
++};
#else
--#error Only X86 supported
++#error ARCH not supported
#endif
class CMessageMap
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
+ }
- exFreePool(Bucket);
+ Connection->SignalState = 0;
- }
+ }
- }
/* Things that can happen when we try the initial connection */
if( Connection->SignalState & SEL_CONNECT ) {
}
}
- return Connection->SignalState;
+ Connection->SignalState = 0;
+ Connection->Signalled = FALSE;
}
- static VOID DrainSignals() {
+ VOID DrainSignals() {
PCONNECTION_ENDPOINT Connection;
- PLIST_ENTRY CurrentEntry, NextEntry;
- ULONG NewState;
- KIRQL OldIrql;
+ PLIST_ENTRY ListEntry;
- KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
- CurrentEntry = SignalledConnectionsList.Flink;
- while (CurrentEntry != &SignalledConnectionsList)
- {
- NextEntry = CurrentEntry->Flink;
- Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT,
+ while( (ListEntry = ExInterlockedRemoveHeadList(&SignalledConnectionsList,
+ &SignalledConnectionsLock)) != NULL) {
+ Connection = CONTAINING_RECORD( ListEntry, CONNECTION_ENDPOINT,
SignalList );
-
- KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
- NewState = HandleSignalledConnection(Connection);
- KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
-
- if (NewState == SEL_FIN || NewState == 0)
- {
- RemoveEntryList(CurrentEntry);
+ HandleSignalledConnection( Connection );
+ }
-
- CurrentEntry = NextEntry;
}
- KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
--}
PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
PCONNECTION_ENDPOINT Connection =
{
Result = MmeGetSoundDeviceCapabilities(AUX_DEVICE_TYPE,
DeviceId,
- Parameter1,
- (PVOID) Parameter1,
++ (PVOID)Parameter1,
Parameter2);
break;
}
{
Result = MmeGetSoundDeviceCapabilities(MIDI_IN_DEVICE_TYPE,
DeviceId,
- Parameter1,
- (PVOID) Parameter1,
++ (PVOID)Parameter1,
Parameter2);
break;
}
{
Result = MmeGetSoundDeviceCapabilities(MIDI_OUT_DEVICE_TYPE,
DeviceId,
- Parameter1,
- (PVOID) Parameter1,
++ (PVOID)Parameter1,
Parameter2);
break;
}
MMRESULT
MmeGetLineInfo(
IN DWORD Message,
-- IN DWORD PrivateHandle,
-- IN DWORD Parameter1,
-- IN DWORD Parameter2)
++ IN DWORD_PTR PrivateHandle,
++ IN DWORD_PTR Parameter1,
++ IN DWORD_PTR Parameter2)
{
MMRESULT Result;
PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
MMRESULT
MmeCloseMixerDevice(
-- IN DWORD PrivateHandle)
++ IN DWORD_PTR PrivateHandle)
{
MMRESULT Result;
PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
}
/* Store the device instance pointer in the private handle - is DWORD safe here? */
-- *PrivateHandle = (DWORD) SoundDeviceInstance;
++ *PrivateHandle = (DWORD_PTR) SoundDeviceInstance;
/* Store the additional information we were given - FIXME: Need flags! */
SetSoundDeviceInstanceMmeData(SoundDeviceInstance,
{
Result = MmeGetSoundDeviceCapabilities(MIXER_DEVICE_TYPE,
DeviceId,
- Parameter1,
- (PVOID) Parameter1,
++ (PVOID)Parameter1,
Parameter2);
break;
}
MMRESULT
MmeSetState(
-- IN DWORD PrivateHandle,
++ IN DWORD_PTR PrivateHandle,
IN BOOL bStart)
{
MMRESULT Result;
return TranslateInternalMmResult(Result);
}
-- /* Store the device instance pointer in the private handle - is DWORD safe here? */
-- *PrivateHandle = (DWORD) SoundDeviceInstance;
++ /* Store the device instance pointer in the private handle */
++ *PrivateHandle = (DWORD_PTR)SoundDeviceInstance;
/* Store the additional information we were given - FIXME: Need flags! */
SetSoundDeviceInstanceMmeData(SoundDeviceInstance,
MMRESULT
MmeCloseDevice(
-- IN DWORD PrivateHandle)
++ IN DWORD_PTR PrivateHandle)
{
MMRESULT Result;
PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
MMRESULT
MmeResetWavePlayback(
-- IN DWORD PrivateHandle)
++ IN DWORD_PTR PrivateHandle)
{
PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
MmeGetPosition(
IN MMDEVICE_TYPE DeviceType,
IN DWORD DeviceId,
-- IN DWORD PrivateHandle,
++ IN DWORD_PTR PrivateHandle,
IN MMTIME* Time,
IN DWORD Size)
{
Result = MmeGetSoundDeviceCapabilities(WAVE_IN_DEVICE_TYPE,
DeviceId,
- Parameter1,
- (PVOID) Parameter1,
++ (PVOID)Parameter1,
Parameter2);
break;
}
{
Result = MmeGetSoundDeviceCapabilities(WAVE_OUT_DEVICE_TYPE,
DeviceId,
- Parameter1,
- (PVOID) Parameter1,
++ (PVOID)Parameter1,
Parameter2);
break;
}
DeviceId,
(LPWAVEOPENDESC) Parameter1,
Parameter2,
- (SIZE_T*)PrivateHandle);
- (DWORD*) PrivateHandle);
++ (DWORD*)PrivateHandle);
break;
}
<?xml version="1.0"?>
<!DOCTYPE group SYSTEM "../../../tools/rbuild/project.dtd">
<group xmlns:xi="http://www.w3.org/2001/XInclude">
- <directory name="legacy">
- <xi:include href="legacy/legacy.rbuild" />
- </directory>
- <directory name="shared">
- <xi:include href="shared/shared.rbuild" />
- </directory>
- <directory name="soundblaster">
- <xi:include href="soundblaster/soundblaster.rbuild" />
- </directory>
- <directory name="uartmidi">
- <xi:include href="uartmidi/uartmidi.rbuild" />
- </directory>
- <directory name="mmebuddy">
- <xi:include href="mmebuddy/mmebuddy.rbuild" />
- </directory>
- <directory name="mment4">
- <xi:include href="mment4/mment4.rbuild" />
- </directory>
-</group>
+ <directory name="legacy">
+ <xi:include href="legacy/legacy.rbuild" />
+ </directory>
+ <directory name="shared">
+ <xi:include href="shared/shared.rbuild" />
+ </directory>
+ <directory name="soundblaster">
+ <xi:include href="soundblaster/soundblaster.rbuild" />
+ </directory>
+ <directory name="uartmidi">
+ <xi:include href="uartmidi/uartmidi.rbuild" />
+ </directory>
- <ifnot property="ARCH" value="amd64">
- <directory name="mmebuddy">
- <xi:include href="mmebuddy/mmebuddy.rbuild" />
- </directory>
- </ifnot>
++ <directory name="mmebuddy">
++ <xi:include href="mmebuddy/mmebuddy.rbuild" />
++ </directory>
+ <directory name="mment4">
+ <xi:include href="mment4/mment4.rbuild" />
+ </directory>
+</group>
#define QUERY_ACTCTX_FLAG_ACTIVE (0x00000001)
#define ACTCTX_FLAGS_ALL (\
- ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
- ACTCTX_FLAG_LANGID_VALID |\
- ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
- ACTCTX_FLAG_RESOURCE_NAME_VALID |\
- ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
- ACTCTX_FLAG_APPLICATION_NAME_VALID |\
- ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
- ACTCTX_FLAG_HMODULE_VALID )
+ ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
+ ACTCTX_FLAG_LANGID_VALID |\
+ ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
+ ACTCTX_FLAG_RESOURCE_NAME_VALID |\
+ ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
+ ACTCTX_FLAG_APPLICATION_NAME_VALID |\
+ ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
+ ACTCTX_FLAG_HMODULE_VALID )
+ #define ACTCTX_MAGIC 0xC07E3E11
+
#define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
#define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
- /* INTERNAL FUNCTIONS *******************************************************/
- static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
+ typedef struct
{
- OBJECT_ATTRIBUTES attr;
- IO_STATUS_BLOCK io;
+ const WCHAR *ptr;
+ unsigned int len;
+ } xmlstr_t;
- attr.Length = sizeof(attr);
- attr.RootDirectory = 0;
- attr.Attributes = OBJ_CASE_INSENSITIVE;
- attr.ObjectName = name;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
- return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
+ typedef struct
+ {
+ const WCHAR *ptr;
+ const WCHAR *end;
+ } xmlbuf_t;
+
+ struct file_info
+ {
+ ULONG type;
+ WCHAR *info;
+ };
+
+ struct assembly_version
+ {
+ USHORT major;
+ USHORT minor;
+ USHORT build;
+ USHORT revision;
+ };
+
+ struct assembly_identity
+ {
+ WCHAR *name;
+ WCHAR *arch;
+ WCHAR *public_key;
+ WCHAR *language;
+ WCHAR *type;
+ struct assembly_version version;
+ BOOL optional;
+ };
+
+ struct entity
+ {
+ DWORD kind;
+ union
+ {
+ struct
+ {
+ WCHAR *tlbid;
+ WCHAR *version;
+ WCHAR *helpdir;
+ } typelib;
+ struct
+ {
+ WCHAR *clsid;
+ } comclass;
+ struct {
+ WCHAR *iid;
+ WCHAR *name;
+ } proxy;
+ struct
+ {
+ WCHAR *name;
+ } class;
+ struct
+ {
+ WCHAR *name;
+ WCHAR *clsid;
+ } clrclass;
+ struct
+ {
+ WCHAR *name;
+ WCHAR *clsid;
+ } clrsurrogate;
+ } u;
+ };
+
+ struct entity_array
+ {
+ struct entity *base;
+ unsigned int num;
+ unsigned int allocated;
+ };
+
+ struct dll_redirect
+ {
+ WCHAR *name;
+ WCHAR *hash;
+ struct entity_array entities;
+ };
+
+ enum assembly_type
+ {
+ APPLICATION_MANIFEST,
+ ASSEMBLY_MANIFEST,
+ ASSEMBLY_SHARED_MANIFEST,
+ };
+
+ struct assembly
+ {
+ enum assembly_type type;
+ struct assembly_identity id;
+ struct file_info manifest;
+ WCHAR *directory;
+ BOOL no_inherit;
+ struct dll_redirect *dlls;
+ unsigned int num_dlls;
+ unsigned int allocated_dlls;
+ struct entity_array entities;
+ };
+
+ typedef struct _ACTIVATION_CONTEXT
+ {
+ ULONG magic;
+ long ref_count;
+ struct file_info config;
+ struct file_info appdir;
+ struct assembly *assemblies;
+ unsigned int num_assemblies;
+ unsigned int allocated_assemblies;
+ } ACTIVATION_CONTEXT;
+
+ struct actctx_loader
+ {
+ ACTIVATION_CONTEXT *actctx;
+ struct assembly_identity *dependencies;
+ unsigned int num_dependencies;
+ unsigned int allocated_dependencies;
+ };
+
+ static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
+ static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
+ static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
+ static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
+ static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
+ static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
+ static const WCHAR comInterfaceExternalProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','E','x','t','e','r','n','a','l','P','r','o','x','y','S','t','u','b',0};
+ static const WCHAR comInterfaceProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','P','r','o','x','y','S','t','u','b',0};
+ static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
+ static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
+ static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
+ static const WCHAR fileW[] = {'f','i','l','e',0};
+ static const WCHAR asmv2hashW[] = {'a','s','m','v','2',':','h','a','s','h',0};
+ static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
+ static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
+ static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
+ static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
+
+ static const WCHAR clsidW[] = {'c','l','s','i','d',0};
+ static const WCHAR hashW[] = {'h','a','s','h',0};
+ static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
+ static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
+ static const WCHAR iidW[] = {'i','i','d',0};
+ static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
+ static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
+ static const WCHAR nameW[] = {'n','a','m','e',0};
+ static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
+ static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
+ static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
+ static const WCHAR processorArchitectureW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
+ static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
+ static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
+ static const WCHAR typeW[] = {'t','y','p','e',0};
+ static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
+ static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
+
+ static const WCHAR xmlW[] = {'?','x','m','l',0};
+ static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
+ static const WCHAR manifestv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
+
+ static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
+ static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
+
+ static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
+ static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
+
+ static WCHAR *strdupW(const WCHAR* str)
+ {
+ WCHAR* ptr;
+
+ if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
+ return NULL;
+ return strcpyW(ptr, str);
}
+ static WCHAR *xmlstrdupW(const xmlstr_t* str)
+ {
+ WCHAR *strW;
- /* FUNCTIONS ***************************************************************/
+ if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
+ {
+ memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
+ strW[str->len] = 0;
+ }
+ return strW;
+ }
- VOID
- NTAPI
- RtlAddRefActivationContext(PVOID Context)
+ static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
{
- UNIMPLEMENTED;
+ return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
}
- NTSTATUS
- NTAPI
- RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame,
- IN PVOID Context)
+ static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
}
- NTSTATUS
- NTAPI
- RtlAllocateActivationContextStack(IN PVOID *Context)
+ static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ return (xmlstr->len && xmlstr->ptr[0] == '/' &&
+ !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
}
- NTSTATUS
- NTAPI
- RtlGetActiveActivationContext(IN PVOID *Context)
+ static inline BOOL isxmlspace( WCHAR ch )
{
- /*
- if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
+ return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
+ }
+
+ static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
+ {
+ struct assembly *assembly;
+
+ if (actctx->num_assemblies == actctx->allocated_assemblies)
{
- *Context = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
- RtlAddRefActivationContext(*Context);
+ void *ptr;
+ unsigned int new_count;
+ if (actctx->assemblies)
+ {
+ new_count = actctx->allocated_assemblies * 2;
+ ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
+ actctx->assemblies, new_count * sizeof(*assembly) );
+ }
+ else
+ {
+ new_count = 4;
+ ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
+ }
+ if (!ptr) return NULL;
+ actctx->assemblies = ptr;
+ actctx->allocated_assemblies = new_count;
}
- else
- *Context = 0;
- */
- *Context = ACTCTX_FAKE_HANDLE;
- return STATUS_SUCCESS;
+
+ assembly = &actctx->assemblies[actctx->num_assemblies++];
+ assembly->type = at;
+ return assembly;
}
- VOID
- NTAPI
- RtlReleaseActivationContext(IN PVOID *Context)
+ static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
{
- UNIMPLEMENTED;
+ if (assembly->num_dlls == assembly->allocated_dlls)
+ {
+ void *ptr;
+ unsigned int new_count;
+ if (assembly->dlls)
+ {
+ new_count = assembly->allocated_dlls * 2;
+ ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
+ assembly->dlls, new_count * sizeof(*assembly->dlls) );
+ }
+ else
+ {
+ new_count = 4;
+ ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
+ }
+ if (!ptr) return NULL;
+ assembly->dlls = ptr;
+ assembly->allocated_dlls = new_count;
+ }
+ return &assembly->dlls[assembly->num_dlls++];
}
- NTSTATUS
- NTAPI
- RtlFindActivationContextSectionString(IN ULONG dwFlags,
- IN const GUID *ExtensionGuid,
- IN ULONG SectionType,
- IN PUNICODE_STRING SectionName,
- IN OUT PVOID ReturnedData)
+ static void free_assembly_identity(struct assembly_identity *ai)
{
- PACTCTX_SECTION_KEYED_DATA Data = ReturnedData;
+ RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
+ }
- UNIMPLEMENTED;
+ static struct entity* add_entity(struct entity_array *array, DWORD kind)
+ {
+ struct entity* entity;
- if (!Data || Data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) ||
- !SectionName || !SectionName->Buffer)
+ if (array->num == array->allocated)
{
- return STATUS_INVALID_PARAMETER;
+ void *ptr;
+ unsigned int new_count;
+ if (array->base)
+ {
+ new_count = array->allocated * 2;
+ ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
+ array->base, new_count * sizeof(*array->base) );
+ }
+ else
+ {
+ new_count = 4;
+ ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
+ }
+ if (!ptr) return NULL;
+ array->base = ptr;
+ array->allocated = new_count;
}
+ entity = &array->base[array->num++];
+ entity->kind = kind;
+ return entity;
+ }
- return STATUS_NOT_IMPLEMENTED;
+ static void free_entity_array(struct entity_array *array)
+ {
+ unsigned int i;
+ for (i = 0; i < array->num; i++)
+ {
+ struct entity *entity = &array->base[i];
+ switch (entity->kind)
+ {
+ case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.iid);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.name);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.version);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.name);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.clsid);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
+ break;
+ default:
+ DPRINT1("Unknown entity kind %d\n", entity->kind);
+ }
+ }
+ RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
}
- NTSTATUS
- NTAPI
- RtlQueryInformationActivationContext(DWORD dwFlags,
- PVOID Context,
- PVOID pvSubInstance,
- ULONG ulInfoClass,
- PVOID pvBuffer,
- SIZE_T cbBuffer OPTIONAL,
- SIZE_T *pcbWrittenOrRequired OPTIONAL)
+ static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ if (!str1) return !str2;
+ return str2 && !strcmpiW( str1, str2 );
}
- NTSTATUS
- NTAPI
- RtlQueryInformationActiveActivationContext(ULONG ulInfoClass,
- PVOID pvBuffer,
- SIZE_T cbBuffer OPTIONAL,
- SIZE_T *pcbWrittenOrRequired OPTIONAL)
+ static BOOL is_matching_identity( const struct assembly_identity *id1,
+ const struct assembly_identity *id2 )
{
- return RtlQueryInformationActivationContext(QUERY_ACTCTX_FLAG_ACTIVE,
- NULL,
- NULL,
- ulInfoClass,
- pvBuffer,
- cbBuffer,
- pcbWrittenOrRequired);
+ if (!is_matching_string( id1->name, id2->name )) return FALSE;
+ if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
+ if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
+
+ if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
+ {
+ static const WCHAR wildcardW[] = {'*',0};
+ if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
+ return FALSE;
+ }
+ if (id1->version.major != id2->version.major) return FALSE;
+ if (id1->version.minor != id2->version.minor) return FALSE;
+ if (id1->version.build > id2->version.build) return FALSE;
+ if (id1->version.build == id2->version.build &&
+ id1->version.revision > id2->version.revision) return FALSE;
+ return TRUE;
}
- NTSTATUS
- NTAPI
- RtlZombifyActivationContext(PVOID Context)
+ static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
+ struct assembly_identity* ai)
{
- UNIMPLEMENTED;
+ unsigned int i;
- if (Context == ACTCTX_FAKE_HANDLE)
- return STATUS_SUCCESS;
+ /* check if we already have that assembly */
- return STATUS_NOT_IMPLEMENTED;
+ for (i = 0; i < acl->actctx->num_assemblies; i++)
+ if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
+ {
+ DPRINT( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
+ ai->name, ai->arch, ai->version.major, ai->version.minor,
+ ai->version.build, ai->version.revision );
+ return TRUE;
+ }
+
+ for (i = 0; i < acl->num_dependencies; i++)
+ if (is_matching_identity( ai, &acl->dependencies[i] ))
+ {
+ DPRINT( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
+ ai->name, ai->arch, ai->version.major, ai->version.minor,
+ ai->version.build, ai->version.revision );
+ return TRUE;
+ }
+
+ if (acl->num_dependencies == acl->allocated_dependencies)
+ {
+ void *ptr;
+ unsigned int new_count;
+ if (acl->dependencies)
+ {
+ new_count = acl->allocated_dependencies * 2;
+ ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
+ new_count * sizeof(acl->dependencies[0]));
+ }
+ else
+ {
+ new_count = 4;
+ ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
+ }
+ if (!ptr) return FALSE;
+ acl->dependencies = ptr;
+ acl->allocated_dependencies = new_count;
+ }
+ acl->dependencies[acl->num_dependencies++] = *ai;
+
+ return TRUE;
}
- NTSTATUS
- NTAPI
- RtlDeactivateActivationContext(DWORD dwFlags,
- ULONG_PTR ulCookie)
+ static void free_depend_manifests(struct actctx_loader* acl)
{
- UNIMPLEMENTED;
+ unsigned int i;
+ for (i = 0; i < acl->num_dependencies; i++)
+ free_assembly_identity(&acl->dependencies[i]);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
+ }
- if (ulCookie == ACTCTX_FAKE_COOKIE)
- return STATUS_SUCCESS;
+ static WCHAR *build_assembly_dir(struct assembly_identity* ai)
+ {
+ static const WCHAR undW[] = {'_',0};
+ static const WCHAR noneW[] = {'n','o','n','e',0};
+ static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
- return STATUS_NOT_IMPLEMENTED;
+ const WCHAR *arch = ai->arch ? ai->arch : noneW;
+ const WCHAR *key = ai->public_key ? ai->public_key : noneW;
+ const WCHAR *lang = ai->language ? ai->language : noneW;
+ const WCHAR *name = ai->name ? ai->name : noneW;
+ SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
+ strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
+ WCHAR *ret;
+
+ if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
+
+ strcpyW( ret, arch );
+ strcatW( ret, undW );
+ strcatW( ret, name );
+ strcatW( ret, undW );
+ strcatW( ret, key );
+ strcatW( ret, undW );
+ sprintfW( ret + strlenW(ret), version_formatW,
+ ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
+ strcatW( ret, undW );
+ strcatW( ret, lang );
+ strcatW( ret, undW );
+ strcatW( ret, mskeyW );
+ return ret;
}
- NTSTATUS
- NTAPI
- RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
+ static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ WCHAR *p = buffer;
+
+ if (!str) return;
+ strcatW( buffer, prefix );
+ p += strlenW(p);
+ *p++ = '"';
+ strcpyW( p, str );
+ p += strlenW(p);
+ *p++ = '"';
+ *p = 0;
}
- NTSTATUS
- NTAPI
- RtlActivateActivationContext(IN ULONG Unknown, IN HANDLE Handle, OUT PULONG_PTR Cookie)
+ static WCHAR *build_assembly_id( const struct assembly_identity *ai )
{
- /*
- PRTL_ACTIVATION_CONTEXT_STACK_FRAME Frame;
+ static const WCHAR archW[] =
+ {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
+ static const WCHAR public_keyW[] =
+ {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
+ static const WCHAR typeW[] =
+ {',','t','y','p','e','=',0};
+ static const WCHAR versionW[] =
+ {',','v','e','r','s','i','o','n','=',0};
- Frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*Frame) );
- if (!Frame)
- return STATUS_NO_MEMORY;
+ WCHAR version[64], *ret;
+ SIZE_T size = 0;
- Frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
- Frame->ActivationContext = Handle;
- Frame->Flags = 0;
- NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = Frame;
- RtlAddRefActivationContext(Handle);
+ sprintfW( version, version_formatW,
+ ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
+ if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
+ if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
+ if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
+ if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
+ size += strlenW(versionW) + strlenW(version) + 2;
- *Cookie = (ULONG_PTR)Frame;
- DPRINT( "%p Cookie=%lx\n", Handle, *Cookie );
- */
+ if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
+ return NULL;
- UNIMPLEMENTED;
+ if (ai->name) strcpyW( ret, ai->name );
+ else *ret = 0;
+ append_string( ret, archW, ai->arch );
+ append_string( ret, public_keyW, ai->public_key );
+ append_string( ret, typeW, ai->type );
+ append_string( ret, versionW, version );
+ return ret;
+ }
- if (Cookie)
- *Cookie = ACTCTX_FAKE_COOKIE;
- return STATUS_SUCCESS;
+ static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
+ {
+ ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
+
+ if (!h || h == INVALID_HANDLE_VALUE) return NULL;
+ //__TRY
+ {
+ if (actctx && actctx->magic == ACTCTX_MAGIC) ret = actctx;
+ }
+ //__EXCEPT_PAGE_FAULT
+ {
+ }
+ //__ENDTRY
+ return ret;
}
- NTSTATUS
- NTAPI
- RtlCreateActivationContext(OUT PHANDLE Handle, IN OUT PVOID ReturnedData)
+ static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
{
- PCACTCTXW pActCtx = (PCACTCTXW) ReturnedData;
- UNICODE_STRING NameW;
- NTSTATUS Status = STATUS_SUCCESS;
- HANDLE hFile = INVALID_HANDLE_VALUE;
+ _InterlockedExchangeAdd( &actctx->ref_count, 1 );
+ }
- UNIMPLEMENTED;
+ static void actctx_release( ACTIVATION_CONTEXT *actctx )
+ {
+ if (_InterlockedExchangeAdd( &actctx->ref_count, -1 ) == 1)
+ {
+ unsigned int i, j;
- if (!pActCtx || (pActCtx->cbSize < sizeof(*pActCtx)) ||
- (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
- return STATUS_INVALID_PARAMETER;
-
- NameW.Buffer = NULL;
- if (pActCtx->lpSource)
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ free_entity_array( &dll->entities );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
+ }
+ RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
+ free_entity_array( &assembly->entities );
+ free_assembly_identity(&assembly->id);
+ }
+ RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
+ actctx->magic = 0;
+ RtlFreeHeap( RtlGetProcessHeap(), 0, actctx );
+ }
+ }
+
+ static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
+ BOOL* error, BOOL* end)
+ {
+ const WCHAR* ptr;
+
+ *error = TRUE;
+
+ while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
+ xmlbuf->ptr++;
+
+ if (xmlbuf->ptr == xmlbuf->end) return FALSE;
+
+ if (*xmlbuf->ptr == '/')
+ {
+ xmlbuf->ptr++;
+ if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
+ return FALSE;
+
+ xmlbuf->ptr++;
+ *end = TRUE;
+ *error = FALSE;
+ return FALSE;
+ }
+
+ if (*xmlbuf->ptr == '>')
+ {
+ xmlbuf->ptr++;
+ *error = FALSE;
+ return FALSE;
+ }
+
+ ptr = xmlbuf->ptr;
+ while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
+
+ if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
+
+ name->ptr = xmlbuf->ptr;
+ name->len = ptr-xmlbuf->ptr;
+ xmlbuf->ptr = ptr;
+
+ ptr++;
+ if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
+
+ value->ptr = ++ptr;
+ if (ptr == xmlbuf->end) return FALSE;
+
+ ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
+ if (!ptr)
+ {
+ xmlbuf->ptr = xmlbuf->end;
+ return FALSE;
+ }
+
+ value->len = ptr - value->ptr;
+ xmlbuf->ptr = ptr + 1;
+
+ if (xmlbuf->ptr == xmlbuf->end) return FALSE;
+
+ *error = FALSE;
+ return TRUE;
+ }
+
+ static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
+ {
+ const WCHAR* ptr;
+
+ for (;;)
{
- if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &NameW, NULL, NULL))
+ ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
+ if (!ptr)
{
- Status = STATUS_NO_SUCH_FILE;
- goto Error;
+ xmlbuf->ptr = xmlbuf->end;
+ return FALSE;
}
- Status = open_nt_file( &hFile, &NameW );
- if (!NT_SUCCESS(Status))
+ ptr++;
+ if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
{
- RtlFreeUnicodeString( &NameW );
- goto Error;
+ for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
+ if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
+
+ if (ptr + 3 > xmlbuf->end)
+ {
+ xmlbuf->ptr = xmlbuf->end;
+ return FALSE;
+ }
+ xmlbuf->ptr = ptr + 3;
}
+ else break;
}
- if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
+ xmlbuf->ptr = ptr;
+ while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
+ ptr++;
+
+ elem->ptr = xmlbuf->ptr;
+ elem->len = ptr - xmlbuf->ptr;
+ xmlbuf->ptr = ptr;
+ return xmlbuf->ptr != xmlbuf->end;
+ }
+
+ static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
+ {
+ /* FIXME: parse attributes */
+ const WCHAR *ptr;
+
+ for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
{
- /* if we have a resource it's a PE file */
- if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
+ if (ptr[0] == '?' && ptr[1] == '>')
{
+ xmlbuf->ptr = ptr + 2;
+ return TRUE;
}
- else if (pActCtx->lpSource)
+ }
+ return FALSE;
+ }
+
+ static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
+ {
+ const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
+
+ if (!ptr) return FALSE;
+
+ content->ptr = xmlbuf->ptr;
+ content->len = ptr - xmlbuf->ptr;
+ xmlbuf->ptr = ptr;
+
+ return TRUE;
+ }
+
+ static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
+ {
+ unsigned int ver[4];
+ unsigned int pos;
+ const WCHAR *curr;
+
+ /* major.minor.build.revision */
+ ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
+ for (curr = str->ptr; curr < str->ptr + str->len; curr++)
+ {
+ if (*curr >= '0' && *curr <= '9')
{
+ ver[pos] = ver[pos] * 10 + *curr - '0';
+ if (ver[pos] >= 0x10000) goto error;
}
- else
+ else if (*curr == '.')
{
- Status = STATUS_INVALID_PARAMETER;
+ if (++pos >= 4) goto error;
}
- }
- else
- {
- /* manifest file */
+ else goto error;
}
+ version->major = ver[0];
+ version->minor = ver[1];
+ version->build = ver[2];
+ version->revision = ver[3];
+ return TRUE;
+
+ error:
+ DPRINT1( "Wrong version definition in manifest file (%s)\n", str->ptr );
+ return FALSE;
+ }
+
+ static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name)
+ {
+ xmlstr_t elem;
+ if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
+ if (xmlstr_cmp(&elem, name)) return TRUE;
+ DPRINT1( "unexpected element %s\n", elem.ptr );
+ return FALSE;
+ }
- if (hFile)
- NtClose( hFile );
- if (NameW.Buffer)
- RtlFreeUnicodeString( &NameW );
+ static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
+ {
+ xmlstr_t attr_name, attr_value;
+ BOOL error;
- *Handle = ACTCTX_FAKE_HANDLE;
- return Status;
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
+ {
+ DPRINT1( "unexpected attr %s=%s\n", attr_name.ptr,
+ attr_value.ptr);
+ }
+ return !error;
+ }
- Error:
- if (hFile) NtClose( hFile );
- return Status;
+ static BOOL parse_end_element(xmlbuf_t *xmlbuf)
+ {
+ BOOL end = FALSE;
+ return parse_expect_no_attr(xmlbuf, &end) && !end;
+ }
+ static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name)
+ {
+ xmlstr_t elem;
+ if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
+ if (!xmlstr_cmp_end(&elem, name))
+ {
+ DPRINT1( "unexpected element %s\n", elem.ptr );
+ return FALSE;
+ }
+ return parse_end_element(xmlbuf);
}
- }
+
+ static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
+ {
+ xmlstr_t attr_name, attr_value, elem;
+ BOOL end = FALSE, error, ret = TRUE;
+
+ while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
+ if(error || end) return end;
+
+ while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
+ !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
+ break;
+ else
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+
+ return ret && parse_end_element(xmlbuf);
+ }
+
+ static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
+ struct assembly_identity* ai)
+ {
+ xmlstr_t attr_name, attr_value;
+ BOOL end = FALSE, error;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, nameW))
+ {
+ if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, typeW))
+ {
+ if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, versionW))
+ {
+ if (!parse_version(&attr_value, &ai->version)) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, processorArchitectureW))
+ {
+ if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
+ {
+ if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, languageW))
+ {
+ DPRINT1("Unsupported yet language attribute (%s)\n",
+ attr_value.ptr);
+ if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr,
+ attr_value.ptr);
+ }
+ }
+
+ if (error || end) return end;
+ return parse_expect_end_elem(xmlbuf, assemblyIdentityW);
+ }
+
+ static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+ {
+ xmlstr_t elem, attr_name, attr_value;
+ BOOL ret, end = FALSE, error;
+ struct entity* entity;
+
+ if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
+ return FALSE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, clsidW))
+ {
+ if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ if (error || end) return end;
+
+ while ((ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if (xmlstr_cmp_end(&elem, comClassW))
+ {
+ ret = parse_end_element(xmlbuf);
+ break;
+ }
+ else
+ {
+ DPRINT1("unknown elem %s\n", elem.ptr);
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+ }
+ return ret;
+ }
+
+ static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+ {
+ xmlstr_t attr_name, attr_value;
+ BOOL end = FALSE, error;
+ struct entity* entity;
+
+ if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
+ return FALSE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, iidW))
+ {
+ if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ if (xmlstr_cmp(&attr_name, nameW))
+ {
+ if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ if (error || end) return end;
+ return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW);
+ }
+
+ static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+ {
+ xmlstr_t attr_name, attr_value;
+ BOOL end = FALSE, error;
+ struct entity* entity;
+
+ if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
+ return FALSE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, tlbidW))
+ {
+ if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ if (xmlstr_cmp(&attr_name, versionW))
+ {
+ if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ if (xmlstr_cmp(&attr_name, helpdirW))
+ {
+ if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr , attr_value.ptr);
+ }
+ }
+
+ if (error || end) return end;
+ return parse_expect_end_elem(xmlbuf, typelibW);
+ }
+
+ static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+ {
+ xmlstr_t elem, content;
+ BOOL end = FALSE, ret = TRUE;
+ struct entity* entity;
+
+ if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
+ return FALSE;
+
+ if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
+ if (end) return FALSE;
+
+ if (!parse_text_content(xmlbuf, &content)) return FALSE;
+
+ if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
+
+ while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if (xmlstr_cmp_end(&elem, windowClassW))
+ {
+ ret = parse_end_element(xmlbuf);
+ break;
+ }
+ else
+ {
+ DPRINT1("unknown elem %s\n", elem.ptr);
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+ }
+
+ return ret;
+ }
+
+ static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
+ {
+ xmlstr_t attr_name, attr_value;
+ BOOL end = FALSE, error;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, oldVersionW))
+ {
+ DPRINT1("Not stored yet oldVersion=%s\n", attr_value.ptr);
+ }
+ else if (xmlstr_cmp(&attr_name, newVersionW))
+ {
+ DPRINT1("Not stored yet newVersion=%s\n", attr_value.ptr);
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ if (error || end) return end;
+ return parse_expect_end_elem(xmlbuf, bindingRedirectW);
+ }
+
+ static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
+ {
+ xmlstr_t elem, content;
+ BOOL end = FALSE, ret = TRUE;
+
+ if (!parse_expect_no_attr(xmlbuf, &end) || end ||
+ !parse_text_content(xmlbuf, &content))
+ return FALSE;
+
+ DPRINT("Got description %s\n", content.ptr);
+
+ while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if (xmlstr_cmp_end(&elem, descriptionW))
+ {
+ ret = parse_end_element(xmlbuf);
+ break;
+ }
+ else
+ {
+ DPRINT1("unknown elem %s\n", elem.ptr);
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+ }
+
+ return ret;
+ }
+
+ static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
+ struct assembly* assembly)
+ {
+ xmlstr_t attr_name, attr_value;
+ BOOL end = FALSE, error;
+ struct entity* entity;
+
+ entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
+ if (!entity) return FALSE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, iidW))
+ {
+ if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ if (xmlstr_cmp(&attr_name, nameW))
+ {
+ if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ if (error || end) return end;
+ return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW);
+ }
+
+ static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+ {
+ xmlstr_t attr_name, attr_value;
+ BOOL end = FALSE, error;
+ struct entity* entity;
+
+ entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
+ if (!entity) return FALSE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, nameW))
+ {
+ if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, clsidW))
+ {
+ if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ if (error || end) return end;
+ return parse_expect_end_elem(xmlbuf, clrClassW);
+ }
+
+ static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+ {
+ xmlstr_t attr_name, attr_value;
+ BOOL end = FALSE, error;
+ struct entity* entity;
+
+ entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
+ if (!entity) return FALSE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, nameW))
+ {
+ if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, clsidW))
+ {
+ if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ if (error || end) return end;
+ return parse_expect_end_elem(xmlbuf, clrSurrogateW);
+ }
+
+ static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
+ {
+ struct assembly_identity ai;
+ xmlstr_t elem;
+ BOOL end = FALSE, ret = TRUE;
+
+ if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
+
+ memset(&ai, 0, sizeof(ai));
+ ai.optional = optional;
+
+ if (!parse_expect_elem(xmlbuf, assemblyIdentityW) ||
+ !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
+ return FALSE;
+
+ /* store the newly found identity for later loading */
+ if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
+
+ while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if (xmlstr_cmp_end(&elem, dependentAssemblyW))
+ {
+ ret = parse_end_element(xmlbuf);
+ break;
+ }
+ else if (xmlstr_cmp(&elem, bindingRedirectW))
+ {
+ ret = parse_binding_redirect_elem(xmlbuf);
+ }
+ else
+ {
+ DPRINT1("unknown elem %s\n", elem.ptr);
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+ }
+
+ return ret;
+ }
+
+ static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
+ {
+ xmlstr_t attr_name, attr_value, elem;
+ BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, optionalW))
+ {
+ static const WCHAR yesW[] = {'y','e','s',0};
+ optional = xmlstr_cmpi( &attr_value, yesW );
+ DPRINT1("optional=%s\n", attr_value.ptr);
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if (xmlstr_cmp_end(&elem, dependencyW))
+ {
+ ret = parse_end_element(xmlbuf);
+ break;
+ }
+ else if (xmlstr_cmp(&elem, dependentAssemblyW))
+ {
+ ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
+ }
+ else
+ {
+ DPRINT1("unknown element %s\n", elem.ptr);
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+ }
+
+ return ret;
+ }
+
+ static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
+ {
+ BOOL end = FALSE;
+
+ if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
+ return end || parse_expect_end_elem(xmlbuf, noInheritW);
+ }
+
+ static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
+ {
+ BOOL end = FALSE;
+
+ if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
+ return end || parse_expect_end_elem(xmlbuf, noInheritableW);
+ }
+
+ static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+ {
+ xmlstr_t attr_name, attr_value, elem;
+ BOOL end = FALSE, error, ret = TRUE;
+ struct dll_redirect* dll;
+
+ if (!(dll = add_dll_redirect(assembly))) return FALSE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, nameW))
+ {
+ if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
+ DPRINT("name=%s\n", attr_value.ptr);
+ }
+ else if (xmlstr_cmp(&attr_name, hashW))
+ {
+ if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, hashalgW))
+ {
+ static const WCHAR sha1W[] = {'S','H','A','1',0};
+ if (!xmlstr_cmpi(&attr_value, sha1W))
+ DPRINT1("hashalg should be SHA1, got %s\n", attr_value.ptr);
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ if (error || !dll->name) return FALSE;
+ if (end) return TRUE;
+
+ while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if (xmlstr_cmp_end(&elem, fileW))
+ {
+ ret = parse_end_element(xmlbuf);
+ break;
+ }
+ else if (xmlstr_cmp(&elem, comClassW))
+ {
+ ret = parse_com_class_elem(xmlbuf, dll);
+ }
+ else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
+ {
+ ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
+ }
+ else if (xmlstr_cmp(&elem, asmv2hashW))
+ {
+ DPRINT1("asmv2hash (undocumented) not supported\n");
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+ else if (xmlstr_cmp(&elem, typelibW))
+ {
+ ret = parse_typelib_elem(xmlbuf, dll);
+ }
+ else if (xmlstr_cmp(&elem, windowClassW))
+ {
+ ret = parse_window_class_elem(xmlbuf, dll);
+ }
+ else
+ {
+ DPRINT1("unknown elem %s\n", elem.ptr);
+ ret = parse_unknown_elem( xmlbuf, &elem );
+ }
+ }
+
+ return ret;
+ }
+
+ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
+ struct assembly* assembly,
+ struct assembly_identity* expected_ai)
+ {
+ xmlstr_t attr_name, attr_value, elem;
+ BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
+
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
+ {
+ if (xmlstr_cmp(&attr_name, manifestVersionW))
+ {
+ static const WCHAR v10W[] = {'1','.','0',0};
+ if (!xmlstr_cmp(&attr_value, v10W))
+ {
+ DPRINT1("wrong version %s\n", attr_value.ptr);
+ return FALSE;
+ }
+ version = TRUE;
+ }
+ else if (xmlstr_cmp(&attr_name, xmlnsW))
+ {
+ if (!xmlstr_cmp(&attr_value, manifestv1W) && !xmlstr_cmp(&attr_value, manifestv3W))
+ {
+ DPRINT1("wrong namespace %s\n", attr_value.ptr);
+ return FALSE;
+ }
+ xmlns = TRUE;
+ }
+ else
+ {
+ DPRINT1("unknown attr %s=%s\n", attr_name.ptr, attr_value.ptr);
+ }
+ }
+
+ if (error || end || !xmlns || !version) return FALSE;
+ if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
+
+ if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
+ {
+ if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
+ return FALSE;
+ assembly->no_inherit = TRUE;
+ }
+
+ if (xmlstr_cmp(&elem, noInheritableW))
+ {
+ if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
+ return FALSE;
+ }
+ else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
+ assembly->no_inherit)
+ return FALSE;
+
+ while (ret)
+ {
+ if (xmlstr_cmp_end(&elem, assemblyW))
+ {
+ ret = parse_end_element(xmlbuf);
+ break;
+ }
+ else if (xmlstr_cmp(&elem, descriptionW))
+ {
+ ret = parse_description_elem(xmlbuf);
+ }
+ else if (xmlstr_cmp(&elem, comInterfaceExternalProxyStubW))
+ {
+ ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
+ }
+ else if (xmlstr_cmp(&elem, dependencyW))
+ {
+ ret = parse_dependency_elem(xmlbuf, acl);
+ }
+ else if (xmlstr_cmp(&elem, fileW))
+ {
+ ret = parse_file_elem(xmlbuf, assembly);
+ }
+ else if (xmlstr_cmp(&elem, clrClassW))
+ {
+ ret = parse_clr_class_elem(xmlbuf, assembly);
+ }
+ else if (xmlstr_cmp(&elem, clrSurrogateW))
+ {
+ ret = parse_clr_surrogate_elem(xmlbuf, assembly);
+ }
+ else if (xmlstr_cmp(&elem, assemblyIdentityW))
+ {
+ if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
+
+ if (expected_ai)
+ {
+ /* FIXME: more tests */
+ if (assembly->type == ASSEMBLY_MANIFEST &&
+ memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
+ {
+ DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
+ expected_ai->version.major, expected_ai->version.minor,
+ expected_ai->version.build, expected_ai->version.revision,
+ assembly->id.version.major, assembly->id.version.minor,
+ assembly->id.version.build, assembly->id.version.revision);
+ ret = FALSE;
+ }
+ else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
+ (assembly->id.version.major != expected_ai->version.major ||
+ assembly->id.version.minor != expected_ai->version.minor ||
+ assembly->id.version.build < expected_ai->version.build ||
+ (assembly->id.version.build == expected_ai->version.build &&
+ assembly->id.version.revision < expected_ai->version.revision)))
+ {
+ DPRINT1("wrong version for shared assembly manifest\n");
+ ret = FALSE;
+ }
+ }
+ }
+ else
+ {
+ DPRINT1("unknown element %s\n", elem.ptr);
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+ if (ret) ret = next_xml_elem(xmlbuf, &elem);
+ }
+
+ return ret;
+ }
+
+ static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
+ struct assembly_identity* ai, xmlbuf_t *xmlbuf )
+ {
+ xmlstr_t elem;
+
+ if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
+
+ if (xmlstr_cmp(&elem, xmlW) &&
+ (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
+ return STATUS_SXS_CANT_GEN_ACTCTX;
+
+ if (!xmlstr_cmp(&elem, assemblyW))
+ {
+ DPRINT1("root element is %s, not <assembly>\n", elem.ptr);
+ return STATUS_SXS_CANT_GEN_ACTCTX;
+ }
+
+ if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
+ {
+ DPRINT1("failed to parse manifest %s\n", assembly->manifest.info );
+ return STATUS_SXS_CANT_GEN_ACTCTX;
+ }
+
+ if (next_xml_elem(xmlbuf, &elem))
+ {
+ DPRINT1("unexpected element %s\n", elem.ptr);
+ return STATUS_SXS_CANT_GEN_ACTCTX;
+ }
+
+ if (xmlbuf->ptr != xmlbuf->end)
+ {
+ DPRINT1("parse error\n");
+ return STATUS_SXS_CANT_GEN_ACTCTX;
+ }
+ return STATUS_SUCCESS;
+ }
+
+ static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
+ LPCWSTR filename, LPCWSTR directory, BOOL shared,
+ const void *buffer, SIZE_T size )
+ {
+ xmlbuf_t xmlbuf;
+ NTSTATUS status;
+ struct assembly *assembly;
+ int unicode_tests;
+
+ DPRINT( "parsing manifest loaded from %s base dir %s\n", filename, directory );
+
+ if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
+ return STATUS_SXS_CANT_GEN_ACTCTX;
+
+ if (directory && !(assembly->directory = strdupW(directory)))
+ return STATUS_NO_MEMORY;
+
+ if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
+ assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
+ : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
+
+ unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
+ if (RtlIsTextUnicode( (PVOID) buffer, size, &unicode_tests ))
+ {
+ xmlbuf.ptr = buffer;
+ xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
+ status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
+ }
+ else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
+ {
+ const WCHAR *buf = buffer;
+ WCHAR *new_buff;
+ unsigned int i;
+
+ if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
+ return STATUS_NO_MEMORY;
+ for (i = 0; i < size / sizeof(WCHAR); i++)
+ new_buff[i] = RtlUshortByteSwap( buf[i] );
+ xmlbuf.ptr = new_buff;
+ xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
+ status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
+ }
+ else
+ {
+ /* let's assume utf-8 for now */
+ int len;
+
+ _SEH2_TRY
+ {
+ len = mbstowcs( NULL, buffer, size);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT1("Exception accessing buffer\n");
+ return STATUS_SXS_CANT_GEN_ACTCTX;
+ }
+ _SEH2_END;
+
+ DPRINT("len = %x\n", len);
+ WCHAR *new_buff;
+
+ if (len == -1)
+ {
+ DPRINT1( "utf-8 conversion failed\n" );
+ return STATUS_SXS_CANT_GEN_ACTCTX;
+ }
+ if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR) )))
+ return STATUS_NO_MEMORY;
+
+ mbstowcs( new_buff, buffer, len);
+ xmlbuf.ptr = new_buff;
+ DPRINT("Buffer %S\n", new_buff);
+ xmlbuf.end = xmlbuf.ptr + len;
+ status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
+
+ RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
+ }
+ return status;
+ }
+
+ static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
+ {
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.ObjectName = name;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
+ }
+
+ static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
+ {
+ NTSTATUS status;
+ ULONG magic;
+ LDR_DATA_TABLE_ENTRY *pldr;
+
+ LdrLockLoaderLock(0, NULL, &magic);
+ status = LdrFindEntryForAddress( module, &pldr );
+ if (status == STATUS_SUCCESS)
+ {
+ if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
+ pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
+ {
+ memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
+ str->Length = pldr->FullDllName.Length;
+ str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
+ }
+ else status = STATUS_NO_MEMORY;
+ }
+ LdrUnlockLoaderLock(0, magic);
+ return status;
+ }
+
+ static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
+ LPCWSTR filename, LPCWSTR directory, BOOL shared,
+ HANDLE hModule, LPCWSTR resname, ULONG lang )
+ {
+ NTSTATUS status;
+ UNICODE_STRING nameW;
+ LDR_RESOURCE_INFO info;
+ IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
+ void *ptr;
+
+ #if 0
+ if (TRACE_ON(actctx))
+ {
+ if (!filename && !get_module_filename( hModule, &nameW, 0 ))
+ {
+ DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
+ hModule, debugstr_w(nameW.Buffer) );
+ RtlFreeUnicodeString( &nameW );
- {
++}
+ else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
+ hModule, debugstr_w(filename) );
+ }
+ #endif
+
+ if (!resname) return STATUS_INVALID_PARAMETER;
+
+ info.Type = (ULONG_PTR)RT_MANIFEST;
+ info.Language = lang;
+ if (!((ULONG_PTR)resname >> 16))
- }
++{
+ info.Name = (ULONG_PTR)resname;
+ status = LdrFindResource_U(hModule, &info, 3, &entry);
- }
++}
+ else if (resname[0] == '#')
+ {
+ ULONG value;
+ RtlInitUnicodeString(&nameW, resname + 1);
+ if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
+ return STATUS_INVALID_PARAMETER;
+ info.Name = value;
+ status = LdrFindResource_U(hModule, &info, 3, &entry);
+ }
+ else
+ {
+ RtlCreateUnicodeString(&nameW, resname);
+ RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
+ info.Name = (ULONG_PTR)nameW.Buffer;
+ status = LdrFindResource_U(hModule, &info, 3, &entry);
+ RtlFreeUnicodeString(&nameW);
+ }
+ if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
+
+ if (status == STATUS_SUCCESS)
+ status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
+
+ return status;
+ }
+
+ static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
+ LPCWSTR filename, LPCWSTR directory, BOOL shared,
+ HANDLE file, LPCWSTR resname, ULONG lang )
+ {
+ HANDLE mapping;
+ OBJECT_ATTRIBUTES attr;
+ LARGE_INTEGER size;
+ LARGE_INTEGER offset;
+ NTSTATUS status;
+ SIZE_T count;
+ void *base;
+
+ DPRINT( "looking for res %s in %s\n", resname, filename );
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = NULL;
+ attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ size.QuadPart = 0;
+ status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
+ &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
+ if (status != STATUS_SUCCESS) return status;
+
+ offset.QuadPart = 0;
+ count = 0;
+ base = NULL;
+ status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
+ &count, ViewShare, 0, PAGE_READONLY );
+ NtClose( mapping );
+ if (status != STATUS_SUCCESS) return status;
+
+ if (RtlImageNtHeader(base)) /* we got a PE file */
+ {
+ HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
+ status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
-{
++}
+ else status = STATUS_INVALID_IMAGE_FORMAT;
+
+ NtUnmapViewOfSection( NtCurrentProcess(), base );
+ return status;
+ }
+
+ static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
+ LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
+ {
+ FILE_STANDARD_INFORMATION info;
+ IO_STATUS_BLOCK io;
+ HANDLE mapping;
+ OBJECT_ATTRIBUTES attr;
+ LARGE_INTEGER size;
+ LARGE_INTEGER offset;
+ NTSTATUS status;
+ SIZE_T count;
+ void *base;
+
+ DPRINT( "loading manifest file %S\n", filename );
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = NULL;
+ attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ size.QuadPart = 0;
+ status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
+ &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
+
+ if (status != STATUS_SUCCESS) return status;
+
+ offset.QuadPart = 0;
+ count = 0;
+ base = NULL;
+ status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
+ &count, ViewShare, 0, PAGE_READONLY );
+
+ if (status != STATUS_SUCCESS) return status;
+
+ /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
+ status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
+
+ if (status == STATUS_SUCCESS)
+ status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
+
+ NtUnmapViewOfSection( NtCurrentProcess(), base );
+ NtClose( mapping );
+ return status;
+ }
+
+ /* try to load the .manifest file associated to the file */
+ static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
+ LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
- }
++ {
+ static const WCHAR fmtW[] = { '.','%','l','u',0 };
+ WCHAR *buffer;
+ NTSTATUS status;
+ UNICODE_STRING nameW;
+ HANDLE file;
+ ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
+
+ if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
+
+ DPRINT( "looking for manifest associated with %s id %lu\n", filename, resid );
+
+ if (module) /* use the module filename */
+ {
+ UNICODE_STRING name;
+
+ if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
+ {
+ if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
+ strcatW( name.Buffer, dotManifestW );
+ if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
+ status = STATUS_RESOURCE_DATA_NOT_FOUND;
+ RtlFreeUnicodeString( &name );
- */
++ }
+ if (status) return status;
+ }
+ else
+ {
+ if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
+ (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
+ return STATUS_NO_MEMORY;
+ strcpyW( buffer, filename );
+ if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
+ strcatW( buffer, dotManifestW );
+ RtlInitUnicodeString( &nameW, buffer );
+ }
+
+ if (!open_nt_file( &file, &nameW ))
+ {
+ status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
+ NtClose( file );
+ }
+ else status = STATUS_RESOURCE_DATA_NOT_FOUND;
+ RtlFreeUnicodeString( &nameW );
+ return status;
+ }
+
+ static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
+ {
+ static const WCHAR lookup_fmtW[] =
+ {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
+ '*', /* FIXME */
+ '.','m','a','n','i','f','e','s','t',0};
+
+ WCHAR *lookup, *ret = NULL;
+ UNICODE_STRING lookup_us;
+ IO_STATUS_BLOCK io;
+ unsigned int data_pos = 0, data_len;
+ char buffer[8192];
+
+ if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
+ (strlenW(ai->arch) + strlenW(ai->name)
+ + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
+ + sizeof(lookup_fmtW) )))
+ return NULL;
+
+ sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, ai->version.major, ai->version.minor);
+ RtlInitUnicodeString( &lookup_us, lookup );
+
+ NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
+ FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
+ if (io.Status == STATUS_SUCCESS)
+ {
+ FILE_BOTH_DIR_INFORMATION *dir_info;
+ WCHAR *tmp;
+ ULONG build, revision;
+
+ data_len = io.Information;
+
+ for (;;)
+ {
+ if (data_pos >= data_len)
+ {
+ NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
+ FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
+ if (io.Status != STATUS_SUCCESS) break;
+ data_len = io.Information;
+ data_pos = 0;
+ }
+ dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
+
+ if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
+ else data_pos = data_len;
+
+ tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
+ build = atoiW(tmp);
+ if (build < ai->version.build) continue;
+ tmp = strchrW(tmp, '.') + 1;
+ revision = atoiW(tmp);
+ if (build == ai->version.build && revision < ai->version.revision)
+ continue;
+ ai->version.build = build;
+ ai->version.revision = revision;
+
+ if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength * sizeof(WCHAR) )))
+ {
+ memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
+ ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
+ }
+ break;
+ }
+ }
+ else DPRINT1("no matching file for %s\n", lookup);
+ RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
+ return ret;
+ }
+
+ static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
+ {
+ struct assembly_identity sxs_ai;
+ UNICODE_STRING path_us;
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+ WCHAR *path, *file = NULL;
+ HANDLE handle;
+
+ static const WCHAR manifest_dirW[] =
+ {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
+
+ if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
+
+ if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
+ ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
+ return STATUS_NO_MEMORY;
+
+ memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
+ memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
+
+ if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
+ {
+ RtlFreeHeap( RtlGetProcessHeap(), 0, path );
+ return STATUS_NO_SUCH_FILE;
+ }
+ RtlFreeHeap( RtlGetProcessHeap(), 0, path );
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.ObjectName = &path_us;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
+ {
+ sxs_ai = *ai;
+ file = lookup_manifest_file( handle, &sxs_ai );
+ NtClose( handle );
+ }
+ if (!file)
+ {
+ RtlFreeUnicodeString( &path_us );
+ return STATUS_NO_SUCH_FILE;
+ }
+
+ /* append file name to directory path */
+ if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
+ path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
+ {
+ RtlFreeHeap( RtlGetProcessHeap(), 0, file );
+ RtlFreeUnicodeString( &path_us );
+ return STATUS_NO_MEMORY;
+ }
+
+ path[path_us.Length/sizeof(WCHAR)] = '\\';
+ strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
+ RtlInitUnicodeString( &path_us, path );
+ *strrchrW(file, '.') = 0; /* remove .manifest extension */
+
+ if (!open_nt_file( &handle, &path_us ))
+ {
+ io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
+ NtClose( handle );
+ }
+ else io.Status = STATUS_NO_SUCH_FILE;
+
+ RtlFreeHeap( RtlGetProcessHeap(), 0, file );
+ RtlFreeUnicodeString( &path_us );
+ return io.Status;
+ }
+
+ static NTSTATUS lookup_assembly(struct actctx_loader* acl,
+ struct assembly_identity* ai)
+ {
+ static const WCHAR dotDllW[] = {'.','d','l','l',0};
+ unsigned int i;
+ WCHAR *buffer, *p, *directory;
+ NTSTATUS status;
+ UNICODE_STRING nameW;
+ HANDLE file;
+
+ DPRINT1( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
+ ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
+
+ if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
+
+ /* FIXME: add support for language specific lookup */
+
+ nameW.Buffer = NULL;
+ if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
+ (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
+ return STATUS_NO_MEMORY;
+
+ if (!(directory = build_assembly_dir( ai )))
+ {
+ RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
+ return STATUS_NO_MEMORY;
+ }
+
+ /* lookup in appdir\name.dll
+ * appdir\name.manifest
+ * appdir\name\name.dll
+ * appdir\name\name.manifest
- }
++ */
+ strcpyW( buffer, acl->actctx->appdir.info );
+ p = buffer + strlenW(buffer);
+ for (i = 0; i < 2; i++)
+ {
+ *p++ = '\\';
+ strcpyW( p, ai->name );
+ p += strlenW(p);
+
+ strcpyW( p, dotDllW );
+ if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
+ {
+ status = open_nt_file( &file, &nameW );
+ if (!status)
+ {
+ status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
+ (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
+ NtClose( file );
+ break;
+ }
+ RtlFreeUnicodeString( &nameW );
+ }
+
+ strcpyW( p, dotManifestW );
+ if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
+ {
+ status = open_nt_file( &file, &nameW );
+ if (!status)
+ {
+ status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
+ NtClose( file );
+ break;
+ }
+ RtlFreeUnicodeString( &nameW );
+ }
+ status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
+ }
+ RtlFreeUnicodeString( &nameW );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
+ return status;
+ }
+
+ static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
+ {
+ NTSTATUS status = STATUS_SUCCESS;
+ unsigned int i;
+
+ for (i = 0; i < acl->num_dependencies; i++)
+ {
+ if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
+ {
+ if (!acl->dependencies[i].optional)
+ {
+ DPRINT1( "Could not find dependent assembly %S\n", acl->dependencies[i].name );
+ status = STATUS_SXS_CANT_GEN_ACTCTX;
+ break;
+ }
+ }
+ }
+ /* FIXME should now iterate through all refs */
+ return status;
+ }
+
+ /* find the appropriate activation context for RtlQueryInformationActivationContext */
+ static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
+ {
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
+ {
+ if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
+ *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
+ }
+ else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
+ {
+ ULONG magic;
+ LDR_DATA_TABLE_ENTRY *pldr;
+
+ LdrLockLoaderLock( 0, NULL, &magic );
+ if (!LdrFindEntryForAddress( *handle, &pldr ))
+ {
+ if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
+ status = STATUS_DLL_NOT_FOUND;
+ else
+ *handle = pldr->EntryPointActivationContext;
+ }
+ else status = STATUS_DLL_NOT_FOUND;
+ LdrUnlockLoaderLock( 0, magic );
+ }
+ else if (!*handle && (class != ActivationContextBasicInformation))
+ *handle = process_actctx;
+
+ return status;
+ }
+
+ static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i)
+ {
+ data->ulDataFormatVersion = 1;
+ data->lpData = v1;
+ data->ulLength = 20; /* FIXME */
+ data->lpSectionGlobalData = NULL; /* FIXME */
+ data->ulSectionGlobalDataLength = 0; /* FIXME */
+ data->lpSectionBase = v2;
+ data->ulSectionTotalLength = 0; /* FIXME */
+ data->hActCtx = NULL;
+ if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = i + 1;
+
+ return STATUS_SUCCESS;
+ }
+
+ static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
+ PACTCTX_SECTION_KEYED_DATA data)
+ {
+ unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR);
+
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
+ return fill_keyed_data(data, dll, assembly, i);
-{
++}
+ }
+ return STATUS_SXS_KEY_NOT_FOUND;
+ }
+
+ static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
+ PACTCTX_SECTION_KEYED_DATA data)
+ {
+ unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR);
+
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ for (k = 0; k < dll->entities.num; k++)
+ {
+ struct entity *entity = &dll->entities.base[k];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
+ {
+ if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen])
+ return fill_keyed_data(data, entity, dll, i);
+ }
+ }
+ }
+ }
+ return STATUS_SXS_KEY_NOT_FOUND;
+ }
+
+ static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
+ const UNICODE_STRING *section_name,
+ DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
- }
++ {
+ NTSTATUS status;
+
+ switch (section_kind)
+ {
+ case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
+ status = find_dll_redirection(actctx, section_name, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
+ status = find_window_class(actctx, section_name, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
+ case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
+ case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
+ case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
+ case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
+ case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
+ DPRINT1("Unsupported yet section_kind %x\n", section_kind);
+ return STATUS_SXS_SECTION_NOT_FOUND;
+ default:
+ DPRINT1("Unknown section_kind %x\n", section_kind);
+ return STATUS_SXS_SECTION_NOT_FOUND;
+ }
+
+ if (status != STATUS_SUCCESS) return status;
+
+ if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
+ {
+ actctx_addref(actctx);
+ data->hActCtx = actctx;
+ }
+ return STATUS_SUCCESS;
+ }
+
+ /* initialize the activation context for the current process */
+ void actctx_init(void)
+ {
+ ACTCTXW ctx;
+ HANDLE handle;
+
+ ctx.cbSize = sizeof(ctx);
+ ctx.lpSource = NULL;
+ ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
+ ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
+ ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
+
+ if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
+ }
+
+ /* FUNCTIONS ***************************************************************/
+
+ NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, void *ptr )
+ {
+ const ACTCTXW *pActCtx = ptr;
+ const WCHAR *directory = NULL;
+ ACTIVATION_CONTEXT *actctx;
+ UNICODE_STRING nameW;
+ ULONG lang = 0;
+ NTSTATUS status = STATUS_NO_MEMORY;
+ HANDLE file = 0;
+ struct actctx_loader acl;
+
+ DPRINT("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
+
+ if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
+ (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
+ return STATUS_INVALID_PARAMETER;
+
+
+ if (!(actctx = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
+ return STATUS_NO_MEMORY;
+
+ actctx->magic = ACTCTX_MAGIC;
+ actctx->ref_count = 1;
+ actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
+ actctx->config.info = NULL;
+ actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
+ if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
+ {
+ if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
+ }
+ else
+ {
+ UNICODE_STRING dir;
+ WCHAR *p;
+
+ if ((status = get_module_filename( NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress, &dir, 0 )))
+ goto error;
+
+ if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
+ actctx->appdir.info = dir.Buffer;
- return STATUS_SUCCESS;
++}
+
+ nameW.Buffer = NULL;
+ if (pActCtx->lpSource)
+ {
+ if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
+ {
+ status = STATUS_NO_SUCH_FILE;
+ goto error;
+ }
+ status = open_nt_file( &file, &nameW );
+ if (status)
+ {
+ RtlFreeUnicodeString( &nameW );
+ goto error;
+ }
+ }
+
+ acl.actctx = actctx;
+ acl.dependencies = NULL;
+ acl.num_dependencies = 0;
+ acl.allocated_dependencies = 0;
+
+ if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
+ if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
+
+ if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
+ {
+ /* if we have a resource it's a PE file */
+ if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
+ {
+ status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
+ pActCtx->lpResourceName, lang );
+ if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
+ /* FIXME: what to do if pActCtx->lpSource is set */
+ status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
+ pActCtx->hModule, pActCtx->lpResourceName );
+ }
+ else if (pActCtx->lpSource)
+ {
+ status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
+ file, pActCtx->lpResourceName, lang );
+ if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
+ status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
+ NULL, pActCtx->lpResourceName );
+ }
+ else status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
+ }
+
+ if (file) NtClose( file );
+ RtlFreeUnicodeString( &nameW );
+
+ if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
+ free_depend_manifests( &acl );
+
+ if (status == STATUS_SUCCESS) *handle = actctx;
+ else actctx_release( actctx );
+
+ return status;
+
+ error:
+ if (file) NtClose( file );
+ actctx_release( actctx );
+ return status;
+ }
+
+ VOID
+ NTAPI
+ RtlAddRefActivationContext(HANDLE handle)
+ {
+ ACTIVATION_CONTEXT *actctx;
+
+ if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
+ }
+
+ VOID
+ NTAPI
+ RtlReleaseActivationContext( HANDLE handle )
+ {
+ ACTIVATION_CONTEXT *actctx;
+
+ if ((actctx = check_actctx( handle ))) actctx_release( actctx );
+ }
+
+ NTSTATUS
+ NTAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
+ {
+ RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
+
+ if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) )))
+ return STATUS_NO_MEMORY;
+
+ frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
+ frame->ActivationContext = handle;
+ frame->Flags = 0;
+
+ NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame;
+ RtlAddRefActivationContext( handle );
+
+ *cookie = (ULONG_PTR)frame;
+ DPRINT( "%p cookie=%lx\n", handle, *cookie );
- return STATUS_SUCCESS;
++ return STATUS_SUCCESS;
+ }
+
+
+ NTSTATUS
+ NTAPI
+ RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
+ {
+ RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
+
+ DPRINT( "%x cookie=%lx\n", flags, cookie );
+
+ /* find the right frame */
+ top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
+ for (frame = top; frame; frame = frame->Previous)
+ if ((ULONG_PTR)frame == cookie) break;
+
+ if (!frame)
+ RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
+
+ if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
+ RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
+
+ /* pop everything up to and including frame */
+ NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
+
+ while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
+ {
+ frame = top->Previous;
+ RtlReleaseActivationContext( top->ActivationContext );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, top );
+ top = frame;
+ }
+
- }
++ return STATUS_SUCCESS;
+ }
+
+ VOID
+ NTAPI RtlFreeThreadActivationContextStack(void)
+ {
+ RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
+
+ frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
+ while (frame)
+ {
+ RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
+ RtlReleaseActivationContext( frame->ActivationContext );
+ RtlFreeHeap( RtlGetProcessHeap(), 0, frame );
+ frame = prev;
- }
++}
+ NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
+ }
+
+
+ NTSTATUS
+ NTAPI RtlGetActiveActivationContext( HANDLE *handle )
+ {
+ if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
+ {
+ *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
+ RtlAddRefActivationContext( *handle );
- }
++}
+ else
+ *handle = 0;
+
+ return STATUS_SUCCESS;
+ }
+
+
+ BOOLEAN
+ NTAPI RtlIsActivationContextActive( HANDLE handle )
+ {
+ RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
+
+ for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous)
+ if (frame->ActivationContext == handle) return TRUE;
+ return FALSE;
+ }
+
+ NTSTATUS
+ NTAPI
+ RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
+ ULONG class, PVOID buffer,
+ SIZE_T bufsize, SIZE_T *retlen )
+ {
+ ACTIVATION_CONTEXT *actctx;
+ NTSTATUS status;
+
+ DPRINT("%08x %p %p %u %p %ld %p\n", flags, handle,
+ subinst, class, buffer, bufsize, retlen);
+
+ if (retlen) *retlen = 0;
+ if ((status = find_query_actctx( &handle, flags, class ))) return status;
+
+ switch (class)
+ {
+ case ActivationContextBasicInformation:
+ {
+ ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
+
+ if (retlen) *retlen = sizeof(*info);
+ if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
+
+ info->hActCtx = handle;
+ info->dwFlags = 0; /* FIXME */
+ if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
- {
++}
+ break;
+
+ case ActivationContextDetailedInformation:
-
++{
+ ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
+ struct assembly *assembly = NULL;
+ SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
+ LPWSTR ptr;
+
+ if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
+
+ if (actctx->num_assemblies) assembly = actctx->assemblies;
- {
++
+ if (assembly && assembly->manifest.info)
+ manifest_len = strlenW(assembly->manifest.info) + 1;
+ if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
+ if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
+ len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
+
+ if (retlen) *retlen = len;
+ if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
+
+ acdi->dwFlags = 0;
+ acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
+ acdi->ulAssemblyCount = actctx->num_assemblies;
+ acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
+ acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
+ acdi->ulRootConfigurationPathType = actctx->config.type;
+ acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
+ acdi->ulAppDirPathType = actctx->appdir.type;
+ acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
+ ptr = (LPWSTR)(acdi + 1);
+ if (manifest_len)
- {
++ {
+ acdi->lpRootManifestPath = ptr;
+ memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
+ ptr += manifest_len;
+ }
+ else acdi->lpRootManifestPath = NULL;
+ if (config_len)
- }
++ {
+ acdi->lpRootConfigurationPath = ptr;
+ memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
+ ptr += config_len;
- {
++ }
+ else acdi->lpRootConfigurationPath = NULL;
+ if (appdir_len)
- }
- else acdi->lpAppDirPath = NULL;
++ {
+ acdi->lpAppDirPath = ptr;
+ memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
- {
+ }
++ else acdi->lpAppDirPath = NULL;
++ }
+ break;
+
+ case AssemblyDetailedInformationInActivationContext:
- {
++ {
+ ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
+ struct assembly *assembly;
+ WCHAR *assembly_id;
+ DWORD index;
+ SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
+ LPWSTR ptr;
+
+ if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
+ if (!subinst) return STATUS_INVALID_PARAMETER;
+
+ index = *(DWORD*)subinst;
+ if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
+
+ assembly = &actctx->assemblies[index - 1];
+
+ if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
+ id_len = strlenW(assembly_id) + 1;
+ if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
+
+ if (assembly->manifest.info &&
+ (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
+ path_len = strlenW(assembly->manifest.info) + 1;
+
+ len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
+
+ if (retlen) *retlen = len;
+ if (!buffer || bufsize < len)
- }
++ {
+ RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
+ return STATUS_BUFFER_TOO_SMALL;
- {
++ }
+
+ afdi->ulFlags = 0; /* FIXME */
+ afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
+ afdi->ulManifestPathType = assembly->manifest.type;
+ afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
+ /* FIXME afdi->liManifestLastWriteTime = 0; */
+ afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
+ afdi->ulPolicyPathLength = 0;
+ /* FIXME afdi->liPolicyLastWriteTime = 0; */
+ afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
+ afdi->ulManifestVersionMajor = 1;
+ afdi->ulManifestVersionMinor = 0;
+ afdi->ulPolicyVersionMajor = 0; /* FIXME */
+ afdi->ulPolicyVersionMinor = 0; /* FIXME */
+ afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
+ ptr = (LPWSTR)(afdi + 1);
+ afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
+ memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
+ ptr += id_len;
+ if (path_len)
- }
++ {
+ afdi->lpAssemblyManifestPath = ptr;
+ memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
+ ptr += path_len;
+ } else afdi->lpAssemblyManifestPath = NULL;
+ afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
+ if (ad_len)
+ {
+ afdi->lpAssemblyDirectoryName = ptr;
+ memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
+ ptr += ad_len;
- }
++ }
+ else afdi->lpAssemblyDirectoryName = NULL;
+ RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
+ }
+ break;
+
+ case FileInformationInAssemblyOfAssemblyInActivationContext:
+ {
+ const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
+ ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
+ struct assembly *assembly;
+ struct dll_redirect *dll;
+ SIZE_T len, dll_len = 0;
+ LPWSTR ptr;
+
+ if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
+ if (!acqi) return STATUS_INVALID_PARAMETER;
+
+ if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
+ return STATUS_INVALID_PARAMETER;
+ assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
+
+ if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
+ return STATUS_INVALID_PARAMETER;
+ dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
+
+ if (dll->name) dll_len = strlenW(dll->name) + 1;
+ len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
+
+ if (!buffer || bufsize < len)
+ {
+ if (retlen) *retlen = len;
+ return STATUS_BUFFER_TOO_SMALL;
- }
++ }
+ if (retlen) *retlen = 0; /* yes that's what native does !! */
+ afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
+ afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
+ afdi->ulPathLength = 0; /* FIXME */
+ ptr = (LPWSTR)(afdi + 1);
+ if (dll_len)
+ {
+ afdi->lpFileName = ptr;
+ memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
+ } else afdi->lpFileName = NULL;
+ afdi->lpFilePath = NULL; /* FIXME */
-{
++ }
+ break;
+
+ default:
+ DPRINT( "class %u not implemented\n", class );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+ return STATUS_SUCCESS;
+ }
+
+ NTSTATUS
+ NTAPI
+ RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
+ UNICODE_STRING *section_name, PVOID ptr )
++ {
+ PACTCTX_SECTION_KEYED_DATA data = ptr;
+ NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
+
+ if (guid)
+ {
+ DPRINT1("expected guid == NULL\n");
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
+ {
+ DPRINT1("unknown flags %08x\n", flags);
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (!data || data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) ||
+ !section_name || !section_name->Buffer)
+ {
+ DPRINT1("invalid parameter\n");
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ ASSERT(NtCurrentTeb());
+ ASSERT(NtCurrentTeb()->ActivationContextStackPointer);
+
+ if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
+ {
+ ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
+ if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
+ }
+
+ if (status != STATUS_SUCCESS)
+ status = find_string( process_actctx, section_kind, section_name, flags, data );
+
+ return status;
+ }
+
+ /* Stubs */
+
+ NTSTATUS
+ NTAPI
+ RtlAllocateActivationContextStack(IN PVOID *Context)
+ {
+ PACTIVATION_CONTEXT_STACK ContextStack;
+ ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ACTIVATION_CONTEXT_STACK) );
+ if (!ContextStack)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ ContextStack->ActiveFrame = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
+ if (!ContextStack->ActiveFrame) return STATUS_NO_MEMORY;
+
+ *Context = ContextStack;
+
+ /* FIXME: Documentation on MSDN reads that activation contexts are only created
+ for modules that have a valid manifest file or resource */
+ actctx_init();
+
+ return STATUS_SUCCESS;
+ }
+
+ NTSTATUS
+ NTAPI
+ RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame,
+ IN PVOID Context)
+ {
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ NTSTATUS
+ NTAPI
+ RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
+ {
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+
+ NTSTATUS
+ NTAPI
+ RtlZombifyActivationContext(PVOID Context)
+ {
+ UNIMPLEMENTED;
+
+ if (Context == ACTCTX_FAKE_HANDLE)
+ return STATUS_SUCCESS;
+
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
<file>fmod.c</file>
<file>ldexp.c</file>
</directory>
- <file>j0_y0.c</file>
+ <!-- FIXME: we don't actually implement these... they recursively call themselves through an alias -->
+ <!--<file>j0_y0.c</file>
<file>j1_y1.c</file>
- <file>jn_yn.c</file>
+ <file>jn_yn.c</file>-->
</if>
<if property="ARCH" value="amd64">
- <directory name="i386">
- <file>atan2.c</file>
- <file>exp.c</file>
- <file>fmod.c</file>
- <file>ldexp.c</file>
+ <directory name="amd64">
+ <file>alldiv.S</file>
+ <file>atan.S</file>
+ <file>atan2.S</file>
+ <file>ceil.S</file>
+ <file>ceilf.S</file>
+ <file>cos.S</file>
+ <file>exp.S</file>
+ <file>fabs.S</file>
+ <file>floor.S</file>
+ <file>floorf.S</file>
+ <file>fmod.S</file>
+ <file>fmodf.S</file>
+ <file>ldexp.S</file>
+ <file>log.S</file>
+ <file>log10.S</file>
+ <file>pow.S</file>
+ <file>sin.S</file>
+ <file>sqrt.S</file>
+ <file>sqrtf.S</file>
+ <file>tan.S</file>
</directory>
- <file>j0_y0.c</file>
+ <!-- FIXME: we don't actually implement these... they recursively call themselves through an alias -->
+ <!--<file>j0_y0.c</file>
<file>j1_y1.c</file>
- <file>jn_yn.c</file>
+ <file>jn_yn.c</file>-->
</if>
<ifnot property="ARCH" value="i386">
<file>stubs.c</file>
/* Class 11 - Module Information */
QSI_DEF(SystemModuleInformation)
{
- extern LIST_ENTRY PsLoadedModuleList;
- return ExpQueryModuleInformation(&PsLoadedModuleList,
- NULL,
+ NTSTATUS Status;
+
+ /* Acquire system module list lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE);
+
+ /* Call the generic handler with the system module list */
+ Status = ExpQueryModuleInformation(&PsLoadedModuleList,
+ &MmLoadedUserImageList,
- (PRTL_PROCESS_MODULES)Buffer,
- Size,
- ReqSize);
+ (PRTL_PROCESS_MODULES)Buffer,
+ Size,
+ ReqSize);
+
+ /* Release list lock and return status */
+ ExReleaseResourceLite(&PsLoadedModuleResource);
+ KeLeaveCriticalRegion();
+ return Status;
}
/* Class 12 - Locks Information */
/* Class 27 - Unload Image */
SSI_DEF(SystemUnloadGdiDriverInformation)
{
- PLDR_DATA_TABLE_ENTRY LdrEntry;
- PLIST_ENTRY NextEntry;
- PVOID BaseAddr = *((PVOID*)Buffer);
+ PVOID SectionPointer = Buffer;
- if (Size != sizeof(PVOID))
+ /* Validate size */
- return STATUS_INFO_LENGTH_MISMATCH;
-
- if(KeGetPreviousMode() != KernelMode)
- return STATUS_PRIVILEGE_NOT_HELD;
-
- // Scan the module list
- NextEntry = PsLoadedModuleList.Flink;
- while(NextEntry != &PsLoadedModuleList)
+ if(Size != sizeof(PVOID))
{
- LdrEntry = CONTAINING_RECORD(NextEntry,
- LDR_DATA_TABLE_ENTRY,
- InLoadOrderLinks);
-
- if (LdrEntry->DllBase == BaseAddr)
- {
- // Found it.
- break;
+ /* Incorrect length, fail */
+ return STATUS_INFO_LENGTH_MISMATCH;
- }
+ }
- NextEntry = NextEntry->Flink;
- }
+ /* Only kernel mode can call this function */
+ if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
- // Check if we found the image
- if(NextEntry != &PsLoadedModuleList)
- {
- return MmUnloadSystemImage(LdrEntry);
- }
- else
- {
- DPRINT1("Image 0x%x not found.\n", BaseAddr);
- return STATUS_DLL_NOT_FOUND;
+ /* Unload the image */
+ MmUnloadSystemImage(SectionPointer);
+ return STATUS_SUCCESS;
-}
+ }
- }
-
/* Class 28 - Time Adjustment Information */
QSI_DEF(SystemTimeAdjustmentInformation)
{
return TRUE;
}
- if (MAXLONGLONG < (LONGLONG) FileOffset->QuadPart + Length) {
+ if (Length > MAXLONGLONG - FileOffset->QuadPart)
+ {
- IoStatus->Status = STATUS_INVALID_PARAMETER;
- IoStatus->Information = 0;
- return FALSE;
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ IoStatus->Information = 0;
+ return FALSE;
}
/* Get the offset and FCB header */
Offset.QuadPart = FileOffset->QuadPart + Length;
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
-
- if (Wait) {
+ if (Wait)
+ {
/* Use a Resource Acquire */
FsRtlEnterFileSystem();
- CcFastReadWait++;
+ CcFastReadWait++;
ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- } else {
- /* Acquire the resource without blocking */
- /* Return false and the I/O manager will retry using the standard IRP method. */
- /* Use a Resource Acquire */
+ }
+ else
+ {
+ /* Acquire the resource without blocking. Return false and the I/O manager
+ * will retry using the standard IRP method. Use a Resource Acquire.
+ */
FsRtlEnterFileSystem();
- if (!ExAcquireResourceSharedLite(FcbHeader->Resource, FALSE)) {
+ if (!ExAcquireResourceSharedLite(FcbHeader->Resource, FALSE))
+ {
- FsRtlExitFileSystem();
- FsRtlIncrementCcFastReadResourceMiss();
- return FALSE;
+ FsRtlExitFileSystem();
+ FsRtlIncrementCcFastReadResourceMiss();
+ return FALSE;
}
}
-
/* Check if this is a fast I/O cached file */
if (!(FileObject->PrivateCacheMap) ||
- (FcbHeader->IsFastIoPossible == FastIoIsNotPossible)) {
+ (FcbHeader->IsFastIoPossible == FastIoIsNotPossible))
+ {
/* It's not, so fail */
- Result = FALSE;
- goto Cleanup;
+ Result = FALSE;
+ goto Cleanup;
}
/* Check if we need to find out if fast I/O is available */
Result = FALSE;
goto Cleanup;
}
- }
+ }
/* Check if we read too much */
- if (Offset.QuadPart > FcbHeader->FileSize.QuadPart){
+ if (Offset.QuadPart > FcbHeader->FileSize.QuadPart)
+ {
/* We did, check if the file offset is past the end */
- if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart){
+ if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart)
+ {
/* Set end of file */
IoStatus->Status = STATUS_END_OF_FILE;
IoStatus->Information = 0;
}
/* Set this as top-level IRP */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
- _SEH2_TRY
- {
- /* Make sure the IO and file size is below 4GB */
+ _SEH2_TRY
+ {
+ /* Make sure the IO and file size is below 4GB */
- if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart )) {
+ if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart))
+ {
- /* Call the cache controller */
+ /* Call the cache controller */
- CcFastCopyRead (FileObject,FileOffset->LowPart,Length,PageCount,Buffer,IoStatus);
+ CcFastCopyRead(FileObject,
+ FileOffset->LowPart,
+ Length,
+ PageCount,
+ Buffer,
+ IoStatus);
+
- /* File was accessed */
- FileObject->Flags |= FO_FILE_FAST_IO_READ;
+ /* File was accessed */
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;
- if (IoStatus->Status != STATUS_END_OF_FILE) {
- ASSERT(( FcbHeader->FileSize.QuadPart) >= (FileOffset->QuadPart + IoStatus->Information));
- }
- } else {
+ if (IoStatus->Status != STATUS_END_OF_FILE)
+ {
+ ASSERT(FcbHeader->FileSize.QuadPart >=
+ FileOffset->QuadPart + IoStatus->Information);
- }
++ }
+ }
+ else
+ {
/* Call the cache controller */
- Result = CcCopyRead(FileObject, FileOffset, Length, Wait,Buffer, IoStatus);
+ Result = CcCopyRead(FileObject,
+ FileOffset,
+ Length,
+ Wait,
+ Buffer,
+ IoStatus);
+
/* File was accessed */
- FileObject->Flags |= FO_FILE_FAST_IO_READ;
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;
- if (Result == TRUE) {
+
+ if (Result == TRUE)
+ {
- ASSERT((IoStatus->Status == STATUS_END_OF_FILE) ||
+ ASSERT( (IoStatus->Status == STATUS_END_OF_FILE) ||
- ((LONGLONG)(FileOffset->QuadPart + IoStatus->Information) <= FcbHeader->FileSize.QuadPart)
- );
+ ((LONGLONG)(FileOffset->QuadPart + IoStatus->Information) <=
+ FcbHeader->FileSize.QuadPart));
- }
- }
+ }
+ }
/* Update the current file offset */
- if (Result == TRUE) {
+ if (Result == TRUE)
+ {
- FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
- }
- }
+ FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
+ }
+ }
- _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
+ {
+ Result = FALSE;
- } _SEH2_END;
+ }
+ _SEH2_END;
- PsGetCurrentThread()->TopLevelIrp = 0;
+ PsGetCurrentThread()->TopLevelIrp = 0;
/* Return to caller */
Cleanup:
ExReleaseResourceLite(FcbHeader->Resource);
FsRtlExitFileSystem();
- if (Result == FALSE) {
+ if (Result == FALSE)
+ {
CcFastReadNotPossible += 1;
- }
+ }
return Result;
-
}
Offset.QuadPart = FileOffset->QuadPart + Length;
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
- /* Nagar p.544 -- Check with Cc if we can write and check if the IO > 64kB (WDK macro) */
+ /* Nagar p.544.
+ * Check with Cc if we can write and check if the IO > 64kB (WDK macro).
+ */
- if ((CcCanIWrite(FileObject, Length, Wait, FALSE) == FALSE) ||
- (CcCopyWriteWontFlush(FileObject, FileOffset, Length) == FALSE) ||
+ if ( (CcCanIWrite(FileObject, Length,Wait, FALSE) == FALSE) ||
+ (CcCopyWriteWontFlush(FileObject,FileOffset,Length) == FALSE) ||
- ((FileObject->Flags & FO_WRITE_THROUGH )== TRUE)
- )
+ ((FileObject->Flags & FO_WRITE_THROUGH) == TRUE))
{
- return FALSE;
+ return FALSE;
}
/* No actual read */
FsRtlEnterFileSystem();
- /* Nagar p.544/545 -- The CcFastCopyWrite doesn't deal with filesize beyond 4GB*/
+ /* Nagar p.544/545.
+ * The CcFastCopyWrite doesn't deal with filesize beyond 4GB.
+ */
if (Wait && (FcbHeader->AllocationSize.HighPart == 0))
{
- /* If the file offset is not past the file size, then we can acquire the lock shared */
- if ((FileOffsetAppend == FALSE) && (Offset.LowPart <= FcbHeader->ValidDataLength.LowPart)){
+ /* If the file offset is not past the file size,
+ * then we can acquire the lock shared.
+ */
+ if ((FileOffsetAppend == FALSE) &&
+ (Offset.LowPart <= FcbHeader->ValidDataLength.LowPart))
+ {
- ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- ResourceAquiredShared = TRUE;
+ ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
+ ResourceAquiredShared = TRUE;
- } else {
+ }
+ else
+ {
- ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE);
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
}
- /* Nagar p.544/545 -- If we append, use the file size as offset. Also, check that we aren't crossing the 4GB boundary */
- if ((FileOffsetAppend == TRUE)) {
+ /* Nagar p.544/545.
+ * If we append, use the file size as offset.
+ * Also, check that we aren't crossing the 4GB boundary.
+ */
+ if (FileOffsetAppend == TRUE)
+ {
- Offset.LowPart = FcbHeader->FileSize.LowPart;
- NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
- b_4GB = (NewSize.LowPart < FcbHeader->FileSize.LowPart);
+ Offset.LowPart = FcbHeader->FileSize.LowPart;
+ NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
+ b_4GB = (NewSize.LowPart < FcbHeader->FileSize.LowPart);
- } else {
+ }
+ else
+ {
- Offset.LowPart = FileOffset->LowPart;
- NewSize.LowPart = FileOffset->LowPart + Length;
+ Offset.LowPart = FileOffset->LowPart;
+ NewSize.LowPart = FileOffset->LowPart + Length;
- b_4GB = ((NewSize.LowPart < FileOffset->LowPart) || (FileOffset->HighPart != 0));
+ b_4GB = (NewSize.LowPart < FileOffset->LowPart) ||
+ (FileOffset->HighPart != 0);
}
- /* Nagar p.544/545
- Make sure that caching is initated.
- That fast are allowed for this file stream.
- That we are not extending past the allocated size
- That we are not creating a hole bigger than 8k
- That we are not crossing the 4GB boundary
+ /* Nagar p.544/545.
+ * Make sure that caching is initated.
+ * That fast are allowed for this file stream.
+ * That we are not extending past the allocated size.
+ * That we are not creating a hole bigger than 8k.
+ * That we are not crossing the 4GB boundary.
- */
- if ((FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
+ */
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
- (Offset.LowPart < (FcbHeader->ValidDataLength.LowPart + 0x2000) ) &&
- !b_4GB
- )
+ (Offset.LowPart < FcbHeader->ValidDataLength.LowPart + 0x2000) &&
+ !b_4GB)
{
- /* If we are extending past the file size, we need to release the lock and acquire it
- exclusively, because we are going to need to update the FcbHeader */
- if (ResourceAquiredShared && (NewSize.LowPart > (FcbHeader->ValidDataLength.LowPart + 0x2000))) {
+ /* If we are extending past the file size, we need to
+ * release the lock and acquire it exclusively, because
+ * we are going to need to update the FcbHeader.
+ */
+ if (ResourceAquiredShared &&
+ (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart + 0x2000))
+ {
- /* Then we need to acquire the resource exclusive */
- ExReleaseResourceLite(FcbHeader->Resource);
- ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE);
+ /* Then we need to acquire the resource exclusive */
+ ExReleaseResourceLite(FcbHeader->Resource);
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
- if (FileOffsetAppend == TRUE) {
+ if (FileOffsetAppend == TRUE)
+ {
- Offset.LowPart = FcbHeader->FileSize.LowPart; // ??
- NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
+ Offset.LowPart = FcbHeader->FileSize.LowPart; // ??
+ NewSize.LowPart = FcbHeader->FileSize.LowPart + Length;
+
- /* Make sure we don't cross the 4GB boundary */
- b_4GB = (NewSize.LowPart < Offset.LowPart);
- }
+ /* Make sure we don't cross the 4GB boundary */
+ b_4GB = (NewSize.LowPart < Offset.LowPart);
+ }
/* Recheck some of the conditions since we let the lock go */
- if ((FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
- (FcbHeader->AllocationSize.HighPart == 0) &&
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
+ (FcbHeader->AllocationSize.HighPart == 0) &&
- !b_4GB
- )
+ !b_4GB)
- {
+ {
- } else
+ /* Do nothing? */
+ }
+ else
- {
- goto FailAndCleanup;
- }
- }
+ {
+ goto FailAndCleanup;
+ }
+ }
- }else
+ }
+ else
{
- goto FailAndCleanup;
+ goto FailAndCleanup;
}
- /* Check if we need to find out if fast I/O is available */
- if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
- {
- IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
- /* Sanity check */
- ASSERT(!KeIsExecutingDpc());
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
- /* Get the Fast I/O table */
- Device = IoGetRelatedDeviceObject(FileObject);
- FastIoDispatch = Device->DriverObject->FastIoDispatch;
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
- /* Sanity check */
- ASSERT(FastIoDispatch != NULL);
- ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+ /* Sanity check */
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
- /* Ask the driver if we can do it */
- if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
- FileOffsetAppend? &FcbHeader->FileSize:FileOffset,
+ FileOffsetAppend ?
+ &FcbHeader->FileSize :
+ FileOffset,
- Length,
- TRUE,
- LockKey,
- FALSE,
- &FastIoCheckIfPossibleStatus,
- Device))
- {
- /* It's not, fail */
- goto FailAndCleanup;
- }
- }
+ Length,
+ TRUE,
+ LockKey,
+ FALSE,
+ &FastIoCheckIfPossibleStatus,
+ Device))
+ {
+ /* It's not, fail */
+ goto FailAndCleanup;
+ }
+ }
- /* If we are going to extend the file then save the old file size
- in case the operation fails
+ /* If we are going to extend the file then save
+ * the old file size in case the operation fails.
- */
+ */
- if (NewSize.LowPart > FcbHeader->FileSize.LowPart) {
+ if (NewSize.LowPart > FcbHeader->FileSize.LowPart)
+ {
- FileSizeModified = TRUE;
- OldFileSize.LowPart = FcbHeader->FileSize.LowPart;
- OldValidDataLength.LowPart = FcbHeader->ValidDataLength.LowPart;
- FcbHeader->FileSize.LowPart = NewSize.LowPart;
- }
+ FileSizeModified = TRUE;
+ OldFileSize.LowPart = FcbHeader->FileSize.LowPart;
+ OldValidDataLength.LowPart = FcbHeader->ValidDataLength.LowPart;
+ FcbHeader->FileSize.LowPart = NewSize.LowPart;
+ }
- /* Set this as top-level IRP */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+ /* Set this as top-level IRP */
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
- _SEH2_TRY
- {
+ _SEH2_TRY
+ {
- if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart) {
+ if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart)
+ {
- LARGE_INTEGER OffsetVar;
- OffsetVar.LowPart = Offset.LowPart;
- OffsetVar.HighPart = 0;
- CcZeroData(FileObject, &FcbHeader->ValidDataLength, &OffsetVar, TRUE);
- }
-
- /* Call the cache manager */
- CcFastCopyWrite(FileObject, Offset.LowPart, Length, Buffer);
- }
+ LARGE_INTEGER OffsetVar;
+ OffsetVar.LowPart = Offset.LowPart;
+ OffsetVar.HighPart = 0;
+ CcZeroData(FileObject,&FcbHeader->ValidDataLength,&OffsetVar,TRUE);
+ }
+
+ /* Call the cache manager */
+ CcFastCopyWrite(FileObject,Offset.LowPart,Length,Buffer);
+ }
- _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
+ EXCEPTION_EXECUTE_HANDLER :
+ EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
+ {
+ Result = FALSE;
- } _SEH2_END;
+ }
+ _SEH2_END;
/* Remove ourselves at the top level component after the IO is done */
- PsGetCurrentThread()->TopLevelIrp = 0;
+ PsGetCurrentThread()->TopLevelIrp = 0;
- /* Did the operation succeed? */
+ /* Did the operation succeed ? */
- if (Result == TRUE) {
+ if (Result == TRUE)
+ {
- /* Update the valid file size if necessary */
+ /* Update the valid file size if necessary */
- if (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart){
+ if (NewSize.LowPart > FcbHeader->ValidDataLength.LowPart)
+ {
- FcbHeader->ValidDataLength.LowPart = NewSize.LowPart;
- }
+ FcbHeader->ValidDataLength.LowPart = NewSize.LowPart ;
+ }
/* Flag the file as modified */
- FileObject->Flags |= FO_FILE_MODIFIED;
+ FileObject->Flags |= FO_FILE_MODIFIED;
- /* Update the strucutres if the file size changed */
+ /* Update the strucutres if the file size changed */
- if (FileSizeModified) {
- ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.LowPart = NewSize.LowPart;
+ if (FileSizeModified)
+ {
+ SharedCacheMap =
+ (PSHARED_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;
+ SharedCacheMap->FileSize.LowPart = NewSize.LowPart;
- FileObject->Flags |= FO_FILE_SIZE_CHANGED;
- }
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;
+ }
/* Update the file object current file offset */
- FileObject->CurrentByteOffset.QuadPart = NewSize.LowPart;
+ FileObject->CurrentByteOffset.QuadPart = NewSize.LowPart;
- } else {
-
- /* Result == FALSE if we get here. */
- if (FileSizeModified) {
+ }
+ else
+ {
+ /* Result == FALSE if we get here */
+ if (FileSizeModified)
+ {
- /* If the file size was modified then restore the old file size */
+ /* If the file size was modified then restore the old file size */
- if(FcbHeader->PagingIoResource != NULL) {
- // Nagar P.544 Restore the old file size if operation didn't succeed.
+ if (FcbHeader->PagingIoResource != NULL)
+ {
+ /* Nagar P.544.
+ * Restore the old file size if operation didn't succeed.
+ */
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
- FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource,TRUE);
+ FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
+ FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
+ }
+ else
+ {
- /* If there is no lock and do it without */
- FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
- FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
- }
- }
+ /* If there is no lock and do it without */
+ FcbHeader->FileSize.LowPart = OldFileSize.LowPart;
+ FcbHeader->ValidDataLength.LowPart = OldValidDataLength.LowPart;
+ }
- } else {
+ }
+ else
+ {
+ /* Do nothing? */
- }
+ }
+ }
- goto Cleanup;
+ goto Cleanup;
+ }
+ else
+ {
+ LARGE_INTEGER OldFileSize;
- } else {
-
- LARGE_INTEGER OldFileSize;
+ #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405)
+ /* Silence incorrect GCC 4.5.x warning */
+ OldFileSize.QuadPart = 0;
+ #endif
- /* Sanity check */
- ASSERT(!KeIsExecutingDpc());
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
- // Nagar P.544
- /* Check if we need to acquire the resource exclusive */
+ /* Nagar P.544.
+ * Check if we need to acquire the resource exclusive.
+ */
- if ((FileOffsetAppend == FALSE) &&
+ if ( (FileOffsetAppend == FALSE) &&
- ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
- )
+ (FileOffset->QuadPart + Length <= FcbHeader->ValidDataLength.QuadPart))
- {
- /* Acquire the resource shared */
+ {
+ /* Acquire the resource shared */
- if (!ExAcquireResourceSharedLite(FcbHeader->Resource,Wait)) {
+ if (!ExAcquireResourceSharedLite(FcbHeader->Resource, Wait))
+ {
- goto LeaveCriticalAndFail;
- }
- ResourceAquiredShared = TRUE;
+ goto LeaveCriticalAndFail;
+ }
+ ResourceAquiredShared =TRUE;
- } else {
+ }
+ else
+ {
- /* Acquire the resource exclusive */
+ /* Acquire the resource exclusive */
- if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait)) {
+ if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource, Wait))
+ {
- goto LeaveCriticalAndFail;
- }
- }
+ goto LeaveCriticalAndFail;
+ }
+ }
- /* Check if we are appending */
+ /* Check if we are appending */
- if (FileOffsetAppend == TRUE) {
+ if (FileOffsetAppend == TRUE)
+ {
- Offset.QuadPart = FcbHeader->FileSize.QuadPart;
- NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
- } else {
+ }
+ else
+ {
- Offset.QuadPart = FileOffset->QuadPart;
- NewSize.QuadPart += FileOffset->QuadPart + Length;
- }
+ Offset.QuadPart = FileOffset->QuadPart;
+ NewSize.QuadPart += FileOffset->QuadPart + Length;
+ }
- /* Nagar p.544/545
- Make sure that caching is initated.
- That fast are allowed for this file stream.
- That we are not extending past the allocated size
- That we are not creating a hole bigger than 8k
+ /* Nagar p.544/545.
+ * Make sure that caching is initated.
+ * That fast are allowed for this file stream.
+ * That we are not extending past the allocated size.
+ * That we are not creating a hole bigger than 8k.
- */
- if ((FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ */
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- ((FcbHeader->ValidDataLength.QuadPart + 0x2000) > Offset.QuadPart) &&
- (MAXLONGLONG > (Offset.QuadPart + Length)) &&
- (FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart)
- )
+ (FcbHeader->ValidDataLength.QuadPart + 0x2000 > Offset.QuadPart) &&
+ (Length <= MAXLONGLONG - Offset.QuadPart) &&
+ (FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart))
- {
- /* Check if we can keep the lock shared */
+ {
+ /* Check if we can keep the lock shared */
- if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) {
+ if (ResourceAquiredShared &&
+ (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart))
+ {
- ExReleaseResourceLite(FcbHeader->Resource);
- if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource, Wait))
- {
- goto LeaveCriticalAndFail;
- }
+ ExReleaseResourceLite(FcbHeader->Resource);
+ if(!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait))
+ {
+ goto LeaveCriticalAndFail;
+ }
/* Compute the offset and the new filesize */
- if (FileOffsetAppend) {
+ if (FileOffsetAppend)
+ {
- Offset.QuadPart = FcbHeader->FileSize.QuadPart;
- NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
- }
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
+ }
- /* Recheck the above points since we released and reacquire the lock */
- if ((FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ /* Recheck the above points since we released and reacquire the lock */
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
- )
+ (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart))
- {
- /* Do nothing */
+ {
+ /* Do nothing */
- } else {
+ }
+ else
+ {
- goto FailAndCleanup;
- }
- }
+ goto FailAndCleanup;
+ }
+ }
- /* Check if we need to find out if fast I/O is available */
- if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
- {
- IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ IO_STATUS_BLOCK FastIoCheckIfPossibleStatus;
- /* Sanity check */
- ASSERT(!KeIsExecutingDpc());
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
- /* Get the Fast I/O table */
- Device = IoGetRelatedDeviceObject(FileObject);
- FastIoDispatch = Device->DriverObject->FastIoDispatch;
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
- /* Sanity check */
- ASSERT(FastIoDispatch != NULL);
- ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+ /* Sanity check */
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
- /* Ask the driver if we can do it */
- if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
- FileOffsetAppend? &FcbHeader->FileSize:FileOffset,
+ FileOffsetAppend ?
+ &FcbHeader->FileSize :
+ FileOffset,
- Length,
- TRUE,
- LockKey,
- FALSE,
- &FastIoCheckIfPossibleStatus,
- Device))
- {
- /* It's not, fail */
- goto FailAndCleanup;
- }
- }
+ Length,
+ TRUE,
+ LockKey,
+ FALSE,
+ &FastIoCheckIfPossibleStatus,
+ Device))
+ {
+ /* It's not, fail */
+ goto FailAndCleanup;
+ }
+ }
-
- /* If we are going to modify the filesize, save the old fs in case the operation fails */
- if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart) {
+ /* If we are going to modify the filesize,
+ * save the old fs in case the operation fails.
+ */
+ if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart)
+ {
- FileSizeModified = TRUE;
- OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
- OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
+ FileSizeModified = TRUE;
+ OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
+ OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
- /* If the high part of the filesize is going to change, grab the Paging IoResouce */
- if (NewSize.HighPart != FcbHeader->FileSize.HighPart && FcbHeader->PagingIoResource) {
+ /* If the high part of the filesize is going
+ * to change, grab the Paging IoResouce.
+ */
+ if (NewSize.HighPart != FcbHeader->FileSize.HighPart &&
+ FcbHeader->PagingIoResource)
+ {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
+ }
+ else
+ {
- FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
- }
- }
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
+ }
+ }
- /* Nagar p.544 */
- /* Set ourselves as top component */
+ /* Nagar p.544.
+ * Set ourselves as top component.
+ */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+
- _SEH2_TRY
- {
- BOOLEAN CallCc = TRUE;
+ _SEH2_TRY
+ {
+ BOOLEAN CallCc = TRUE;
- /* Check if there is a gap between the end of the file and the offset
- If yes, then we have to zero the data
+
+ /* Check if there is a gap between the end of the file
+ * and the offset. If yes, then we have to zero the data.
- */
+ */
- if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
- if (!(Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,Wait))) {
- /* If this operation fails, then we have to exit
- We can jump outside the SEH, so I a using a variable to exit
- normally
+ if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart)
+ {
+ if (!(Result = CcZeroData(FileObject,
+ &FcbHeader->ValidDataLength,
+ &Offset,
+ Wait)))
+ {
+ /* If this operation fails, then we have to exit. We can jump
+ * outside the SEH, so I a using a variable to exit normally.
- */
- CallCc = FALSE;
- }
- }
+ */
+ CallCc = FALSE;
+ }
+ }
/* Unless the CcZeroData failed, call the cache manager */
- if (CallCc) {
+ if (CallCc)
+ {
- Result = CcCopyWrite(FileObject, &Offset, Length, Wait, Buffer);
- }
+ Result = CcCopyWrite(FileObject,&Offset,Length, Wait, Buffer);
+ }
- }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ }
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
+ EXCEPTION_EXECUTE_HANDLER :
+ EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
+ {
+ Result = FALSE;
- } _SEH2_END;
+ }
+ _SEH2_END;
/* Reset the top component */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
/* Did the operation suceeded */
- if (Result) {
+ if (Result)
+ {
- /* Check if we need to update the filesize */
+ /* Check if we need to update the filesize */
- if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
- if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && FcbHeader->PagingIoResource) {
+ if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart)
+ {
+ if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart &&
+ FcbHeader->PagingIoResource)
+ {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
+ }
+ else
+ {
- FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
- }
- }
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
+ }
+ }
/* Flag the file as modified */
- FileObject->Flags |= FO_FILE_MODIFIED;
+ FileObject->Flags |= FO_FILE_MODIFIED;
+
- /* Check if the filesize has changed */
+ /* Check if the filesize has changed */
- if (FileSizeModified) {
+ if (FileSizeModified)
+ {
- /* Update the file sizes */
+ /* Update the file sizes */
- ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart = NewSize.QuadPart;
+ SharedCacheMap =
+ (PSHARED_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;
+ SharedCacheMap->FileSize.QuadPart = NewSize.QuadPart;
- FileObject->Flags |= FO_FILE_SIZE_CHANGED;
- }
-
- /* Update the current FO byte offset */
- FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart;
- }
- else
- {
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;
+ }
++
+ /* Update the current FO byte offset */
+ FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart;
+ }
+ else
+ {
- /* The operation did not succeed
- Reset the file size to what it should be
+ /* The operation did not succeed.
+ * Reset the file size to what it should be.
- */
+ */
- if (FileSizeModified) {
- if (FcbHeader->PagingIoResource) {
+ if (FileSizeModified)
+ {
+ if (FcbHeader->PagingIoResource)
+ {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
- FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
- }else{
+ }
+ else
+ {
- FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
- FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
- }
- }
- }
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
+ }
+ }
+ }
+
- goto Cleanup;
+ goto Cleanup;
- } else {
+ }
+ else
+ {
- goto FailAndCleanup;
- }
- }
+ goto FailAndCleanup;
+ }
-
- ASSERT(0);
+ }
LeaveCriticalAndFail:
+
FsRtlExitFileSystem();
return FALSE;
DeviceObject = IoGetRelatedDeviceObject(FileObject);
FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
- /* Check if we support Fast Calls, and check FastIoQueryStandardInfo */
- /* Call the function and see if it succeeds */
+ /* Check if we support Fast Calls, and check FastIoQueryStandardInfo.
+ * Call the function and see if it succeeds.
+ */
- if (!FastDispatch ||
- !FastDispatch->FastIoQueryStandardInfo ||
+ if ( !FastDispatch ||
+ !FastDispatch->FastIoQueryStandardInfo ||
- !FastDispatch->FastIoQueryStandardInfo(FileObject,TRUE,
- &Info,&IoStatus,DeviceObject))
+ !FastDispatch->FastIoQueryStandardInfo(FileObject,
+ TRUE,
+ &Info,
+ &IoStatus,
+ DeviceObject))
{
- /* If any of the above failed, then we are going to send an IRP to the device object */
- /* Initialize the even for the IO */
+ /* If any of the above failed, then we are going to send an
+ * IRP to the device object. Initialize the event for the IO.
+ */
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ KeInitializeEvent(&Event,NotificationEvent,FALSE);
+
/* Allocate the IRP */
- Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+ Irp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
+
if (Irp == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
IoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION;
IoStackLocation->FileObject = FileObject;
IoStackLocation->DeviceObject = DeviceObject;
- IoStackLocation->Parameters.QueryFile.Length = ALIGN_UP(sizeof(FILE_INFORMATION_CLASS),ULONG);
- IoStackLocation->Parameters.QueryFile.FileInformationClass = FileStandardInformation;
+ IoStackLocation->Parameters.QueryFile.Length =
+ ALIGN_UP(sizeof(FILE_INFORMATION_CLASS), ULONG);
+ IoStackLocation->Parameters.QueryFile.FileInformationClass =
+ FileStandardInformation;
/* Send the IRP to the related device object */
- Status = IoCallDriver(DeviceObject, Irp);
+ Status = IoCallDriver(DeviceObject,Irp);
/* Standard DDK IRP result processing */
if (Status == STATUS_PENDING)
CcMdlRead(FileObject, FileOffset, Length, MdlChain, IoStatus);
FileObject->Flags |= FO_FILE_FAST_IO_READ;
}
- _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
+ EXCEPTION_EXECUTE_HANDLER :
+ EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
+ {
+ Result = FALSE;
- } _SEH2_END;
+ }
+ _SEH2_END;
/* Remove the top-level IRP flag */
{
if (FileObject->Flags & FO_WRITE_THROUGH)
{
- return FALSE;
+ return FALSE;
}
-
/* Call the Cache Manager */
- CcMdlWriteComplete2(FileObject, FileOffset, MdlChain);
+ CcMdlWriteComplete2(FileObject,FileOffset,MdlChain);
return TRUE;
}
Offset.QuadPart = FileOffset->QuadPart + Length;
- /* Nagar p.544 -- Check with Cc if we can write */
- if ( (!CcCanIWrite(FileObject, Length,TRUE,FALSE))||
+ /* Nagar p.544.
+ * Check with Cc if we can write.
+ */
+ if (!CcCanIWrite(FileObject, Length, TRUE, FALSE) ||
- (FileObject->Flags & FO_WRITE_THROUGH))
+ (FileObject->Flags & FO_WRITE_THROUGH))
{
- return FALSE;
+ return FALSE;
}
IoStatus->Status = STATUS_SUCCESS;
FsRtlEnterFileSystem();
/* Check we are going to extend the file */
- if ((FileOffsetAppend == FALSE) &&
+ if ( (FileOffsetAppend == FALSE) &&
- ( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
- )
+ (FileOffset->QuadPart + Length <= FcbHeader->ValidDataLength.QuadPart))
- {
- /* Acquire the resource shared */
- ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- ResourceAquiredShared = TRUE;
+ {
+ /* Acquire the resource shared */
+ ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
+ ResourceAquiredShared =TRUE;
- } else
+ }
+ else
- {
- /* Acquire the resource exclusive */
- ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE);
- }
+ {
+ /* Acquire the resource exclusive */
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
+ }
- /* Check if we are appending */
+ /* Check if we are appending */
- if (FileOffsetAppend == TRUE) {
+ if (FileOffsetAppend == TRUE)
+ {
- Offset.QuadPart = FcbHeader->FileSize.QuadPart;
- NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
- } else
+ }
+ else
- {
- Offset.QuadPart = FileOffset->QuadPart;
- NewSize.QuadPart = FileOffset->QuadPart + Length;
- }
+ {
+ Offset.QuadPart = FileOffset->QuadPart;
+ NewSize.QuadPart = FileOffset->QuadPart + Length;
+ }
- if ((FileObject->PrivateCacheMap) &&
- (FcbHeader->IsFastIoPossible) &&
+ if ( (FileObject->PrivateCacheMap) &&
+ (FcbHeader->IsFastIoPossible) &&
- (MAXLONGLONG >= (LONGLONG) FileOffset->QuadPart + Length) &&
+ (Length <= MAXLONGLONG - FileOffset->QuadPart) &&
- (NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart))
+ (NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart) )
{
/* Check if we can keep the lock shared */
- if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) {
+ if (ResourceAquiredShared &&
+ (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart))
+ {
- ExReleaseResourceLite(FcbHeader->Resource);
- ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE);
+ ExReleaseResourceLite(FcbHeader->Resource);
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
/* Compute the offset and the new filesize */
- if (FileOffsetAppend) {
+ if (FileOffsetAppend)
+ {
- Offset.QuadPart = FcbHeader->FileSize.QuadPart;
- NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
- }
+ Offset.QuadPart = FcbHeader->FileSize.QuadPart;
+ NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
+ }
- /* Recheck the above points since we released and reacquire the lock */
- if ((FileObject->PrivateCacheMap != NULL) &&
- (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
+ /* Recheck the above points since we released and reacquire the lock */
+ if ( (FileObject->PrivateCacheMap != NULL) &&
+ (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
- (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
- )
+ (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart))
- {
- /* Do nothing */
+ {
+ /* Do nothing */
- } else {
+ }
+ else
+ {
- goto FailAndCleanup;
- }
- }
-
- /* Check if we need to find out if fast I/O is available */
- if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
- {
- /* Sanity check */
- /* ASSERT(!KeIsExecutingDpc()); */
-
- /* Get the Fast I/O table */
- Device = IoGetRelatedDeviceObject(FileObject);
- FastIoDispatch = Device->DriverObject->FastIoDispatch;
-
- /* Sanity check */
- ASSERT(FastIoDispatch != NULL);
- ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
-
- /* Ask the driver if we can do it */
- if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
- FileOffset,
- Length,
- TRUE,
- LockKey,
- FALSE,
- IoStatus,
- Device))
- {
- /* It's not, fail */
- goto FailAndCleanup;
- }
- }
+ goto FailAndCleanup;
+ }
+ }
+
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ /* Sanity check */
+ /* ASSERT(!KeIsExecutingDpc()); */
+
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
+
+ /* Sanity check */
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ FileOffset,
+ Length,
+ TRUE,
+ LockKey,
+ FALSE,
+ IoStatus,
+ Device))
+ {
+ /* It's not, fail */
+ goto FailAndCleanup;
+ }
+ }
- /* If we are going to modify the filesize, save the old fs in case the operation fails */
+ /* If we are going to modify the filesize,
+ * save the old fs in case the operation fails.
+ */
- if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart)
- {
- FileSizeModified = TRUE;
- OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
- OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
+ if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart)
+ {
+ FileSizeModified = TRUE;
+ OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
+ OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
- /* If the high part of the filesize is going to change, grab the Paging IoResouce */
- if (NewSize.HighPart != FcbHeader->FileSize.HighPart && FcbHeader->PagingIoResource)
+ /* If the high part of the filesize is going
+ * to change, grab the Paging IoResouce.
+ */
+ if (NewSize.HighPart != FcbHeader->FileSize.HighPart &&
+ FcbHeader->PagingIoResource)
- {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ {
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
+ }
+ else
+ {
- FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
- }
- }
+ FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
+ }
+ }
- /* Nagar p.544 */
- /* Set ourselves as top component */
+ /* Nagar p.544.
+ * Set ourselves as top component.
+ */
- PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
- _SEH2_TRY
- {
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+ _SEH2_TRY
+ {
- /* Check if there is a gap between the end of the file and the offset
- If yes, then we have to zero the data
+ /* Check if there is a gap between the end of the file and the offset.
+ * If yes, then we have to zero the data.
- */
+ */
- if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
- Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,TRUE);
+ if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart)
+ {
+ Result = CcZeroData(FileObject,
+ &FcbHeader->ValidDataLength,
+ &Offset,
+ TRUE);
- if (Result)
- {
+ if (Result)
+ {
- CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
+ CcPrepareMdlWrite(FileObject,
+ &Offset,
+ Length,
+ MdlChain,
+ IoStatus);
- }
+ }
- } else {
+ }
+ else
+ {
- CcPrepareMdlWrite(FileObject, &Offset, Length, MdlChain, IoStatus);
- }
+ CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
+ }
- }_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ }
+ _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
+ EXCEPTION_EXECUTE_HANDLER :
+ EXCEPTION_CONTINUE_SEARCH)
- {
- Result = FALSE;
+ {
+ Result = FALSE;
- } _SEH2_END;
+ }
+ _SEH2_END;
/* Reset the top component */
- PsGetCurrentThread()->TopLevelIrp = 0;
+ PsGetCurrentThread()->TopLevelIrp = 0;
/* Did the operation suceeded */
- if (Result) {
+ if (Result)
+ {
- /* Check if we need to update the filesize */
+ /* Check if we need to update the filesize */
- if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
- if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && FcbHeader->PagingIoResource) {
+ if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart)
+ {
+ if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart &&
+ FcbHeader->PagingIoResource)
+ {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
- } else {
+ }
+ else
+ {
- FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
- }
- }
+ FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
+ }
+ }
/* Flag the file as modified */
- FileObject->Flags |= FO_FILE_MODIFIED;
+ FileObject->Flags |= FO_FILE_MODIFIED;
+
- /* Check if the filesize has changed */
+ /* Check if the filesize has changed */
- if (FileSizeModified) {
- /* Update the file sizes */
- ((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart = NewSize.QuadPart;
+ if (FileSizeModified)
+ {
+ SharedCacheMap =
+ (PSHARED_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;
+ SharedCacheMap->FileSize.QuadPart = NewSize.QuadPart;
- FileObject->Flags |= FO_FILE_SIZE_CHANGED;
- }
- }
- else
- {
+ FileObject->Flags |= FO_FILE_SIZE_CHANGED;
+ }
-
+ }
+ else
+ {
- /* The operation did not succeed
- Reset the file size to what it should be
+ /* The operation did not succeed.
+ * Reset the file size to what it should be.
- */
+ */
- if (FileSizeModified) {
- if (FcbHeader->PagingIoResource) {
+ if (FileSizeModified)
+ {
+ if (FcbHeader->PagingIoResource)
+ {
- ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
- FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
- FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
- ExReleaseResourceLite(FcbHeader->PagingIoResource);
+ ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
+ ExReleaseResourceLite(FcbHeader->PagingIoResource);
- }else{
+ }
+ else
+ {
- FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
- FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
- }
- }
- }
+ FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
+ FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
+ }
+ }
+ }
- goto Cleanup;
+ goto Cleanup;
-
}
else
{
/* Special case for stack frame dumps */
case 'DsoR':
{
-- KeRosDumpStackFrames((PULONG)Buffer1, Buffer1Length);
++ KeRosDumpStackFrames((PULONG_PTR)Buffer1, Buffer1Length);
break;
}
#endif
USHORT OutStringLength;
/* Get the response string and length */
++#ifdef _X86_
OutString = (LPSTR)Context->Ebx;
OutStringLength = (USHORT)Context->Edi;
++#elif _AMD64_
++ OutString = (LPSTR)Context->Rbx;
++ OutStringLength = (USHORT)Context->Rdi;
++#else
++#error Unknown Architecture
++#endif
/* Call KDBG */
ReturnValue = KdpPrompt((LPSTR)ExceptionRecord->
OutStringLength);
/* Return the number of characters that we received */
++#ifdef _X86_
Context->Eax = ReturnValue;
++#elif _AMD64_
++ Context->Rax = ReturnValue;
++#else
++#error Unknown Architecture
++#endif
}
#endif
/* Check if this is an assertion failure */
if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE)
{
++#ifdef _X86_
/* Warn about it */
DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n",
(PVOID)Context->Eip);
/* Bump EIP to the instruction following the int 2C and return */
Context->Eip += 2;
++#elif _AMD64_
++#else
++ /* Warn about it */
++ DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n",
++ (PVOID)Context->Rip);
++
++ /* Bump RIP to the instruction following the int 2C and return */
++ Context->Rip += 2;
++
++#error Unknown Architecture
++#endif
return TRUE;
}
#endif
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/kdbg/amd64/kdb.c
+ * PURPOSE: Kernel Debugger
+ * PROGRAMMERS: Gregor Anich
+ * Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
++extern KSPIN_LOCK KdpSerialSpinLock;
++STRING KdpPromptString = RTL_CONSTANT_STRING("kdb:> ");
++
+/* GLOBALS *******************************************************************/
+
+ULONG KdbDebugState = 0; /* KDBG Settings (NOECHO, KDSERIAL) */
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+NTAPI
+KdbpGetCommandLineSettings(PCHAR p1)
+{
+ PCHAR p2;
+
+ while (p1 && (p2 = strchr(p1, ' ')))
+ {
+ p2++;
+
+ if (!_strnicmp(p2, "KDSERIAL", 8))
+ {
+ p2 += 8;
+ KdbDebugState |= KD_DEBUG_KDSERIAL;
+ KdpDebugMode.Serial = TRUE;
+ }
+ else if (!_strnicmp(p2, "KDNOECHO", 8))
+ {
+ p2 += 8;
+ KdbDebugState |= KD_DEBUG_KDNOECHO;
+ }
+
+ p1 = p2;
+ }
+}
+
+KD_CONTINUE_TYPE
+KdbEnterDebuggerException(
+ IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
+ IN KPROCESSOR_MODE PreviousMode,
+ IN PCONTEXT Context,
+ IN OUT PKTRAP_FRAME TrapFrame,
+ IN BOOLEAN FirstChance)
+{
+ UNIMPLEMENTED;
+ return 0;
+}
+
+VOID
+KdbpCliModuleLoaded(IN PUNICODE_STRING Name)
+{
+ UNIMPLEMENTED;
+}
+
+VOID
+KdbpCliInit()
+{
+ UNIMPLEMENTED;
+}
+
++ULONG
++NTAPI
++KdpPrompt(IN LPSTR InString,
++ IN USHORT InStringLength,
++ OUT LPSTR OutString,
++ IN USHORT OutStringLength)
++{
++ USHORT i;
++ CHAR Response;
++ ULONG DummyScanCode;
++ KIRQL OldIrql;
++
++ /* Acquire the printing spinlock without waiting at raised IRQL */
++ while (TRUE)
++ {
++ /* Wait when the spinlock becomes available */
++ while (!KeTestSpinLock(&KdpSerialSpinLock));
++
++ /* Spinlock was free, raise IRQL */
++ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
++
++ /* Try to get the spinlock */
++ if (KeTryToAcquireSpinLockAtDpcLevel(&KdpSerialSpinLock))
++ break;
++
++ /* Someone else got the spinlock, lower IRQL back */
++ KeLowerIrql(OldIrql);
++ }
++
++ /* Loop the string to send */
++ for (i = 0; i < InStringLength; i++)
++ {
++ /* Print it to serial */
++ KdPortPutByteEx(&SerialPortInfo, *(PCHAR)(InString + i));
++ }
++
++ /* Print a new line for log neatness */
++ KdPortPutByteEx(&SerialPortInfo, '\r');
++ KdPortPutByteEx(&SerialPortInfo, '\n');
++
++ /* Print the kdb prompt */
++ for (i = 0; i < KdpPromptString.Length; i++)
++ {
++ /* Print it to serial */
++ KdPortPutByteEx(&SerialPortInfo,
++ *(KdpPromptString.Buffer + i));
++ }
++
++ /* Loop the whole string */
++ for (i = 0; i < OutStringLength; i++)
++ {
++ /* Check if this is serial debugging mode */
++ if (KdbDebugState & KD_DEBUG_KDSERIAL)
++ {
++ /* Get the character from serial */
++ do
++ {
++ Response = KdbpTryGetCharSerial(MAXULONG);
++ } while (Response == -1);
++ }
++ else
++ {
++ /* Get the response from the keyboard */
++ do
++ {
++ Response = KdbpTryGetCharKeyboard(&DummyScanCode, MAXULONG);
++ } while (Response == -1);
++ }
++
++ /* Check for return */
++ if (Response == '\r')
++ {
++ /*
++ * We might need to discard the next '\n'.
++ * Wait a bit to make sure we receive it.
++ */
++ KeStallExecutionProcessor(100000);
++
++ /* Check the mode */
++ if (KdbDebugState & KD_DEBUG_KDSERIAL)
++ {
++ /* Read and discard the next character, if any */
++ KdbpTryGetCharSerial(5);
++ }
++ else
++ {
++ /* Read and discard the next character, if any */
++ KdbpTryGetCharKeyboard(&DummyScanCode, 5);
++ }
++
++ /*
++ * Null terminate the output string -- documentation states that
++ * DbgPrompt does not null terminate, but it does
++ */
++ *(PCHAR)(OutString + i) = 0;
++
++ /* Print a new line */
++ KdPortPutByteEx(&SerialPortInfo, '\r');
++ KdPortPutByteEx(&SerialPortInfo, '\n');
++
++ /* Release spinlock */
++ KiReleaseSpinLock(&KdpSerialSpinLock);
++
++ /* Lower IRQL back */
++ KeLowerIrql(OldIrql);
++
++ /* Return the length */
++ return OutStringLength + 1;
++ }
++
++ /* Write it back and print it to the log */
++ *(PCHAR)(OutString + i) = Response;
++ KdPortPutByteEx(&SerialPortInfo, Response);
++ }
++
++ /* Print a new line */
++ KdPortPutByteEx(&SerialPortInfo, '\r');
++ KdPortPutByteEx(&SerialPortInfo, '\n');
++
++ /* Release spinlock */
++ KiReleaseSpinLock(&KdpSerialSpinLock);
++
++ /* Lower IRQL back */
++ KeLowerIrql(OldIrql);
++
++ /* Return the length */
++ return OutStringLength;
++}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/mm/amd64/init.c
+ * PURPOSE: Memory Manager Initialization for amd64
+ *
+ * PROGRAMMERS: Timo kreuzer (timo.kreuzer@reactos.org)
+ * ReactOS Portable Systems Group
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include <ntoskrnl.h>
+//#define NDEBUG
+#include <debug.h>
+
+#include "../ARM3/miarm.h"
+
++#ifndef KDBG
+extern PMMPTE MmDebugPte;
++#endif
+
+/* GLOBALS *****************************************************************/
+
+/* Sizes */
+ULONG64 MmBootImageSize;
+ULONG64 MmMinimumNonPagedPoolSize = 256 * 1024;
+ULONG64 MmSizeOfNonPagedPoolInBytes;
+ULONG64 MmMaximumNonPagedPoolInBytes;
+ULONG64 MmMaximumNonPagedPoolPercent;
+ULONG64 MmMinAdditionNonPagedPoolPerMb = 32 * 1024;
+ULONG64 MmMaxAdditionNonPagedPoolPerMb = 400 * 1024;
+ULONG64 MmDefaultMaximumNonPagedPool = 1024 * 1024;
+ULONG64 MmSessionSize = MI_SESSION_SIZE;
+ULONG64 MmSessionViewSize = MI_SESSION_VIEW_SIZE;
+ULONG64 MmSessionPoolSize = MI_SESSION_POOL_SIZE;
+ULONG64 MmSessionImageSize = MI_SESSION_IMAGE_SIZE;
+ULONG64 MmSystemViewSize = MI_SYSTEM_VIEW_SIZE;
+ULONG64 MmSizeOfPagedPoolInBytes = MI_MIN_INIT_PAGED_POOLSIZE;
+ULONG64 MiNonPagedSystemSize;
+
+/* Address ranges */
+ULONG64 MmUserProbeAddress = 0x7FFFFFF0000ULL;
+PVOID MmHighestUserAddress = (PVOID)0x7FFFFFEFFFFULL;
+PVOID MmSystemRangeStart = (PVOID)0xFFFF080000000000ULL;
+PVOID MmSessionBase; // FFFFF90000000000 = MiSessionPoolStart
+PVOID MiSessionPoolStart; // FFFFF90000000000 = MiSessionPoolEnd - MmSessionPoolSize
+PVOID MiSessionPoolEnd; // = MiSessionViewStart
+PVOID MiSessionViewStart; // = MiSessionViewEnd - MmSessionViewSize
+PVOID MiSessionViewEnd; // FFFFF97FFF000000
+PVOID MiSessionImageStart; // ?FFFFF97FFF000000 = MiSessionImageEnd - MmSessionImageSize
+PVOID MiSessionImageEnd; // FFFFF98000000000 = MiSessionSpaceEnd
+PVOID MiSessionSpaceEnd = MI_SESSION_SPACE_END; // FFFFF98000000000
+PVOID MmSystemCacheStart; // FFFFF98000000000
+PVOID MmSystemCacheEnd; // FFFFFA8000000000
+PVOID MmPagedPoolStart = MI_PAGED_POOL_START; // FFFFFA8000000000
+PVOID MmPagedPoolEnd; // FFFFFAA000000000
+PVOID MiSystemViewStart;
+PVOID MmNonPagedSystemStart; // FFFFFAA000000000
+PVOID MmNonPagedPoolStart;
+PVOID MmNonPagedPoolExpansionStart;
+PVOID MmNonPagedPoolEnd = MI_NONPAGED_POOL_END; // 0xFFFFFAE000000000
+
+PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
+ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage = -1; // FIXME: ULONG64
+
+ULONG MmNumberOfSystemPtes;
+PMMPTE MmSystemPagePtes;
+MMSUPPORT MmSystemCacheWs;
+
+RTL_BITMAP MiPfnBitMap;
+ULONG64 MxPfnAllocation;
+ULONG64 MxPfnSizeInBytes;
+
+PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor;
+MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
+ULONG MiNumberDescriptors = 0;
+BOOLEAN MiIncludeType[LoaderMaximum];
+
+PFN_NUMBER MxFreePageBase;
+ULONG64 MxFreePageCount = 0;
+ULONG MxPhase = 0;
+
+PFN_NUMBER MmSystemPageDirectory;
+PFN_NUMBER MmSizeOfPagedPoolInPages = MI_MIN_INIT_PAGED_POOLSIZE / PAGE_SIZE;
+
+
+/* FUNCTIONS *****************************************************************/
+
+ULONG
+NoDbgPrint(const char *Format, ...)
+{
+ return 0;
+}
+
+VOID
+NTAPI
+MiEvaluateMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
+ PLIST_ENTRY ListEntry;
+ PFN_NUMBER LastPage;
+ ULONG i;
+
+ /* Get the size of the boot loader's image allocations */
+ MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned * PAGE_SIZE;
+ MmBootImageSize = ROUND_UP(MmBootImageSize, 4 * 1024 * 1024);
+
+ /* Instantiate memory that we don't consider RAM/usable */
+ for (i = 0; i < LoaderMaximum; i++) MiIncludeType[i] = TRUE;
+ MiIncludeType[LoaderBad] = FALSE;
+ MiIncludeType[LoaderFirmwarePermanent] = FALSE;
+ MiIncludeType[LoaderSpecialMemory] = FALSE;
+ MiIncludeType[LoaderBBTMemory] = FALSE;
+
+ /* Loop the memory descriptors */
+ for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ ListEntry != &LoaderBlock->MemoryDescriptorListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Get the memory descriptor */
+ MdBlock = CONTAINING_RECORD(ListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Count it */
+ MiNumberDescriptors++;
+
+ /* Skip pages that are not part of the PFN database */
+ if (!MiIncludeType[MdBlock->MemoryType])
+ {
+ continue;
+ }
+
+ /* Add this to the total of pages */
+ MmNumberOfPhysicalPages += MdBlock->PageCount;
+
+ /* Check if this is the new lowest page */
+ if (MdBlock->BasePage < MmLowestPhysicalPage)
+ {
+ /* Update the lowest page */
+ MmLowestPhysicalPage = MdBlock->BasePage;
+ }
+
+ /* Check if this is the new highest page */
+ LastPage = MdBlock->BasePage + MdBlock->PageCount - 1;
+ if (LastPage > MmHighestPhysicalPage)
+ {
+ /* Update the highest page */
+ MmHighestPhysicalPage = LastPage;
+ }
+
+ /* Check if this is currently free memory */
+ if ((MdBlock->MemoryType == LoaderFree) ||
+ (MdBlock->MemoryType == LoaderLoadedProgram) ||
+ (MdBlock->MemoryType == LoaderFirmwareTemporary) ||
+ (MdBlock->MemoryType == LoaderOsloaderStack))
+ {
+ /* Check if this is the largest memory descriptor */
+ if (MdBlock->PageCount > MxFreePageCount)
+ {
+ /* For now, it is */
+ MxFreeDescriptor = MdBlock;
+ MxFreePageBase = MdBlock->BasePage;
+ MxFreePageCount = MdBlock->PageCount;
+ }
+ }
+ }
+}
+
+PFN_NUMBER
+NTAPI
+MxAllocEarlyPage()
+{
+ PFN_NUMBER Pfn;
+
+ /* Make sure we have enough pages */
+ if (!MxFreePageCount)
+ {
+ /* Crash the system */
+ KeBugCheckEx(INSTALL_MORE_MEMORY,
+ MmNumberOfPhysicalPages,
+ MxFreeDescriptor->PageCount,
+ MxOldFreeDescriptor.PageCount,
+ 1);
+ }
+
+ /* Use our lowest usable free pages */
+ Pfn = MxFreePageBase;
+ MxFreePageBase++;
+ MxFreePageCount--;
+ return Pfn;
+}
+
+PFN_NUMBER
+NTAPI
+MxAllocPage()
+{
+ return (MxPhase == 0) ? MxAllocEarlyPage() : MmAllocPage(MC_SYSTEM, 0);
+}
+
+PMMPTE
+NTAPI
+MxGetPte(PVOID Address)
+{
+ PMMPTE Pte;
+ MMPTE TmplPte;
+
+ /* Setup template pte */
+ TmplPte.u.Long = 0;
+ TmplPte.u.Flush.Valid = 1;
+ TmplPte.u.Flush.Write = 1;
+
+ /* Get a pointer to the PXE */
+ Pte = MiAddressToPxe(Address);
+ if (!Pte->u.Hard.Valid)
+ {
+ /* It's not valid, map it! */
+ TmplPte.u.Hard.PageFrameNumber = MxAllocPage();
+ *Pte = TmplPte;
+ }
+
+ /* Get a pointer to the PPE */
+ Pte = MiAddressToPpe(Address);
+ if (!Pte->u.Hard.Valid)
+ {
+ /* It's not valid, map it! */
+ TmplPte.u.Hard.PageFrameNumber = MxAllocPage();
+ *Pte = TmplPte;
+ }
+
+ /* Get a pointer to the PDE */
+ Pte = MiAddressToPde(Address);
+ if (!Pte->u.Hard.Valid)
+ {
+ /* It's not valid, map it! */
+ TmplPte.u.Hard.PageFrameNumber = MxAllocPage();
+ *Pte = TmplPte;
+ }
+
+ /* Get a pointer to the PTE */
+ Pte = MiAddressToPte(Address);
+ return Pte;
+}
+
+VOID
+NTAPI
+MxMapPage(PVOID Address)
+{
+ MMPTE TmplPte, *Pte;
+
+ /* Setup template pte */
+ TmplPte.u.Long = 0;
+ TmplPte.u.Flush.Valid = 1;
+ TmplPte.u.Flush.Write = 1;
+ TmplPte.u.Hard.PageFrameNumber = MxAllocPage();
+
+ /* Get the PTE for that page */
+ Pte = MxGetPte(Address);
+ ASSERT(Pte->u.Hard.Valid == 0);
+
+ /* Map a physical page */
+ *Pte = TmplPte;
+}
+
+VOID
+MxMapPageRange(PVOID Address, ULONG64 PageCount)
+{
+ while (PageCount--)
+ {
+ /* Map the page */
+ MxMapPage(Address);
+
+ /* Goto next page */
+ Address = (PVOID)((ULONG64)Address + PAGE_SIZE);
+ }
+}
+
+VOID
+NTAPI
+MiPreparePfnDatabse(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
+ PLIST_ENTRY ListEntry;
+ PUCHAR Page, FirstPage;
+ SIZE_T Size;
+
+ /* Calculate the size of the PFN database and convert to pages */
+ MxPfnSizeInBytes = ROUND_TO_PAGES((MmHighestPhysicalPage + 1) * sizeof(MMPFN));
+ MxPfnAllocation = MxPfnSizeInBytes >> PAGE_SHIFT;
+
+ /* Simply start at hardcoded address */
+ MmPfnDatabase = MI_PFN_DATABASE;
+
+ /* Loop the memory descriptors */
+ for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ ListEntry != &LoaderBlock->MemoryDescriptorListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Get the memory descriptor */
+ MdBlock = CONTAINING_RECORD(ListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Skip pages that are not part of the PFN database */
+ if (MiIncludeType[MdBlock->MemoryType])
+ {
+ /* Get the base and size of this pfn database entry */
+ FirstPage = PAGE_ALIGN(&MmPfnDatabase[MdBlock->BasePage]);
+ Size = ROUND_TO_PAGES(MdBlock->PageCount * sizeof(MMPFN));
+
+ /* Loop the pages of this Pfn database entry */
+ for (Page = FirstPage; Page < FirstPage + Size; Page += PAGE_SIZE)
+ {
+ /* Is the page already mapped? */
+ if (!MmIsAddressValid(Page))
+ {
+ /* It's not, map it now */
+ MxMapPage(Page);
+ }
+ }
+
+ /* Zero out the pages */
+ RtlZeroMemory(FirstPage, Size);
+ }
+ }
+}
+
+
+VOID
+NTAPI
+MiInitializeSessionSpace(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ /* Set up session space */
+ MiSessionSpaceEnd = (PVOID)MI_SESSION_SPACE_END;
+
+ /* This is where we will load Win32k.sys and the video driver */
+ MiSessionImageEnd = MiSessionSpaceEnd;
+ MiSessionImageStart = (PCHAR)MiSessionImageEnd - MmSessionImageSize;
+
+ /* The view starts right below the session working set (itself below
+ * the image area) */
+ MiSessionViewEnd = MI_SESSION_VIEW_END;
+ MiSessionViewStart = (PCHAR)MiSessionViewEnd - MmSessionViewSize;
+ ASSERT(IS_PAGE_ALIGNED(MiSessionViewStart));
+
+ /* Session pool follows */
+ MiSessionPoolEnd = MiSessionViewStart;
+ MiSessionPoolStart = (PCHAR)MiSessionPoolEnd - MmSessionPoolSize;
+ ASSERT(IS_PAGE_ALIGNED(MiSessionPoolStart));
+
+ /* And it all begins here */
+ MmSessionBase = MiSessionPoolStart;
+
+ /* System view space ends at session space, so now that we know where
+ * this is, we can compute the base address of system view space itself. */
+ MiSystemViewStart = (PCHAR)MmSessionBase - MmSystemViewSize;
+ ASSERT(IS_PAGE_ALIGNED(MiSystemViewStart));
+
+ /* Sanity checks */
+ ASSERT(MiSessionViewEnd <= MiSessionImageStart);
+ ASSERT(MmSessionBase <= MiSessionPoolStart);
+}
+
+VOID
+MiInitializePageTable()
+{
+ ULONG64 PageFrameOffset;
+ MMPTE TmplPte, *Pte;
+ PFN_NUMBER PageCount;
+
+ /* HACK: don't use freeldr debug print anymore */
+ FrLdrDbgPrint = NoDbgPrint;
+
+ /* Get current directory base */
+ MmSystemPageDirectory = ((PMMPTE)PXE_SELFMAP)->u.Hard.PageFrameNumber;
+ PageFrameOffset = MmSystemPageDirectory << PAGE_SHIFT;
+ ASSERT(PageFrameOffset == __readcr3());
+
+ /* Set directory base for the system process */
+ PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PageFrameOffset;
+
+ /* Enable global pages */
+ __writecr4(__readcr4() | CR4_PGE);
+ ASSERT(__readcr4() & CR4_PGE);
+
+ /* Loop the user mode PXEs */
+ for (Pte = MiAddressToPxe(0);
+ Pte <= MiAddressToPxe(MmHighestUserAddress);
+ Pte++)
+ {
+ /* Zero the PXE, clear all mappings */
+ Pte->u.Long = 0;
+ }
+
+ /* Flush the TLB */
+ KeFlushCurrentTb();
+
+ /* Set up a template PTE */
+ TmplPte.u.Long = 0;
+ TmplPte.u.Flush.Valid = 1;
+ TmplPte.u.Flush.Write = 1;
+ HyperTemplatePte = TmplPte;
+
+ /* Create PDPTs (72 KB) for shared system address space,
+ * skip page tables and hyperspace */
+
+ /* Loop the PXEs */
+ for (Pte = MiAddressToPxe((PVOID)(HYPER_SPACE_END + 1));
+ Pte <= MiAddressToPxe(MI_HIGHEST_SYSTEM_ADDRESS);
+ Pte++)
+ {
+ /* Is the PXE already valid? */
+ if (!Pte->u.Hard.Valid)
+ {
+ /* It's not Initialize it */
+ TmplPte.u.Flush.PageFrameNumber = MxAllocPage();
+ *Pte = TmplPte;
+
+ /* Zero the page. The PXE is the PTE for the PDPT. */
+ RtlZeroMemory(MiPteToAddress(Pte), PAGE_SIZE);
+ }
+ }
+
+ /* Setup the mapping PTEs */
+ MmFirstReservedMappingPte = MxGetPte((PVOID)MI_MAPPING_RANGE_START);
+ MmFirstReservedMappingPte->u.Hard.PageFrameNumber = MI_HYPERSPACE_PTES;
+ MmLastReservedMappingPte = MiAddressToPte((PVOID)MI_MAPPING_RANGE_END);
+
++#ifndef KDBG
+ /* Setup debug mapping PTE */
+ MmDebugPte = MxGetPte(MI_DEBUG_MAPPING);
++#endif
+}
+
+VOID
+NTAPI
+MiBuildNonPagedPool(VOID)
+{
+ PMMPTE Pte;
+ PFN_COUNT PageCount;
+
+ /* Check if this is a machine with less than 256MB of RAM, and no overide */
+ if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) &&
+ !(MmSizeOfNonPagedPoolInBytes))
+ {
+ /* Force the non paged pool to be 2MB so we can reduce RAM usage */
+ MmSizeOfNonPagedPoolInBytes = 2 * 1024 * 1024;
+ }
+
+ /* Check if the user gave a ridicuously large nonpaged pool RAM size */
+ if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) >
+ (MmNumberOfPhysicalPages * 7 / 8))
+ {
+ /* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */
+ MmSizeOfNonPagedPoolInBytes = 0;
+ }
+
+ /* Check if no registry setting was set, or if the setting was too low */
+ if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize)
+ {
+ /* Start with the minimum (256 KB) and add 32 KB for each MB above 4 */
+ MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize;
+ MmSizeOfNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
+ 256 * MmMinAdditionNonPagedPoolPerMb;
+ }
+
+ /* Check if the registy setting or our dynamic calculation was too high */
+ if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE)
+ {
+ /* Set it to the maximum */
+ MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE;
+ }
+
+ /* Check if a percentage cap was set through the registry */
+ if (MmMaximumNonPagedPoolPercent)
+ {
+ /* Don't feel like supporting this right now */
+ UNIMPLEMENTED;
+ }
+
+ /* Page-align the nonpaged pool size */
+ MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1);
+
+ /* Now, check if there was a registry size for the maximum size */
+ if (!MmMaximumNonPagedPoolInBytes)
+ {
+ /* Start with the default (1MB) and add 400 KB for each MB above 4 */
+ MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool;
+ MmMaximumNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
+ 256 * MmMaxAdditionNonPagedPoolPerMb;
+ }
+
+ /* Don't let the maximum go too high */
+ if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE)
+ {
+ /* Set it to the upper limit */
+ MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE;
+ }
+
+ /* Put non paged pool to the end of the region */
+ MmNonPagedPoolStart = (PCHAR)MmNonPagedPoolEnd - MmMaximumNonPagedPoolInBytes;
+
+ /* Make sure it doesn't collide with the PFN database */
+ if ((PCHAR)MmNonPagedPoolStart < (PCHAR)MmPfnDatabase + MxPfnSizeInBytes)
+ {
+ /* Put non paged pool after the PFN database */
+ MmNonPagedPoolStart = (PCHAR)MmPfnDatabase + MxPfnSizeInBytes;
+ MmMaximumNonPagedPoolInBytes = (ULONG64)MmNonPagedPoolEnd -
+ (ULONG64)MmNonPagedPoolStart;
+ }
+
+ ASSERT(IS_PAGE_ALIGNED(MmNonPagedPoolStart));
+
+ /* Calculate the nonpaged pool expansion start region */
+ MmNonPagedPoolExpansionStart = (PCHAR)MmNonPagedPoolStart +
+ MmSizeOfNonPagedPoolInBytes;
+ ASSERT(IS_PAGE_ALIGNED(MmNonPagedPoolExpansionStart));
+
+ /* Map the nonpaged pool */
+ PageCount = (MmSizeOfNonPagedPoolInBytes + PAGE_SIZE - 1) / PAGE_SIZE;
+ MxMapPageRange(MmNonPagedPoolStart, PageCount);
+
+ /* Loop the non paged pool extension PTEs */
+ for (Pte = MiAddressToPte(MmNonPagedPoolExpansionStart);
+ Pte <= MiAddressToPte(MmNonPagedPoolEnd);
+ Pte++)
+ {
+ /* Create PXE, PPE, PDE and zero the PTE */
+ MxGetPte(MiPteToAddress(Pte))->u.Long = 0;
+ }
+
+ /* Initialize the ARM3 nonpaged pool */
+ MiInitializeArmPool();
+
+ /* Initialize the nonpaged pool */
+ InitializePool(NonPagedPool, 0);
+}
+
+VOID
+NTAPI
+MiBuildSystemPteSpace()
+{
+ PMMPTE Pte, StartPte, EndPte;
+
+ /* Use the default numer of system PTEs */
+ MmNumberOfSystemPtes = MI_NUMBER_SYSTEM_PTES;
+
+ /* System PTE pool is below the PFN database */
+ MiNonPagedSystemSize = (MmNumberOfSystemPtes + 1) * PAGE_SIZE;
+ MmNonPagedSystemStart = (PCHAR)MmPfnDatabase - MiNonPagedSystemSize;
+ MmNonPagedSystemStart = MM_ROUND_DOWN(MmNonPagedSystemStart, 512 * PAGE_SIZE);
+
+ /* Don't let it go below the minimum */
+ if (MmNonPagedSystemStart < (PVOID)MI_NON_PAGED_SYSTEM_START_MIN)
+ {
+ /* This is a hard-coded limit in the Windows NT address space */
+ MmNonPagedSystemStart = (PVOID)MI_NON_PAGED_SYSTEM_START_MIN;
+
+ /* Reduce the amount of system PTEs to reach this point */
+ MmNumberOfSystemPtes = ((ULONG64)MmPfnDatabase -
+ (ULONG64)MmNonPagedSystemStart) >>
+ PAGE_SHIFT;
+ MmNumberOfSystemPtes--;
+ ASSERT(MmNumberOfSystemPtes > 1000);
+ }
+
+ /* Set the range of system PTEs */
+ StartPte = MiAddressToPte(MI_SYSTEM_PTE_START);
+ EndPte = StartPte + MmNumberOfSystemPtes - 1;
+
+ /* Loop the system PTEs */
+ for (Pte = StartPte; Pte <= EndPte; Pte++)
+ {
+ /* Create PXE, PPE, PDE and zero the PTE */
+ MxGetPte(MiPteToAddress(Pte))->u.Long = 0;
+ }
+
+ /* Create the system PTE space */
+ Pte = MiAddressToPte(MI_SYSTEM_PTE_START);
+ MiInitializeSystemPtes(Pte, MmNumberOfSystemPtes, SystemPteSpace);
+
+ /* Reserve system PTEs for zeroing PTEs and clear them */
+ MiFirstReservedZeroingPte = MiReserveSystemPtes(MI_ZERO_PTES, SystemPteSpace);
+ RtlZeroMemory(MiFirstReservedZeroingPte, MI_ZERO_PTES * sizeof(MMPTE));
+
+ /* Set the counter to maximum */
+ MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = MI_ZERO_PTES - 1;
+}
+
+VOID
+NTAPI
+MiBuildPhysicalMemoryBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PPHYSICAL_MEMORY_DESCRIPTOR Buffer, NewBuffer;
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
+ PLIST_ENTRY ListEntry;
+ PFN_NUMBER NextPage = -1;
+ PULONG Bitmap;
+ ULONG Runs = 0;
+ ULONG Size, i;
+
+ /* Calculate size for the PFN bitmap */
+ Size = ROUND_UP(MmHighestPhysicalPage + 1, sizeof(ULONG));
+
+ /* Allocate the PFN bitmap */
+ Bitmap = ExAllocatePoolWithTag(NonPagedPool, Size, ' mM');
+
+ /* Allocate enough memory for the physical memory block */
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
+ sizeof(PHYSICAL_MEMORY_RUN) *
+ (MiNumberDescriptors - 1),
+ 'lMmM');
+ if (!Bitmap || !Buffer)
+ {
+ /* This is critical */
+ KeBugCheckEx(INSTALL_MORE_MEMORY,
+ MmNumberOfPhysicalPages,
+ MmLowestPhysicalPage,
+ MmHighestPhysicalPage,
+ 0x101);
+ }
+
+ /* Initialize the bitmap and clear all bits */
+ RtlInitializeBitMap(&MiPfnBitMap, Bitmap, MmHighestPhysicalPage + 1);
+ RtlClearAllBits(&MiPfnBitMap);
+
+ /* Loop the memory descriptors */
+ for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ ListEntry != &LoaderBlock->MemoryDescriptorListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Get the memory descriptor */
+ MdBlock = CONTAINING_RECORD(ListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Skip pages that are not part of the PFN database */
+ if (!MiIncludeType[MdBlock->MemoryType])
+ {
+ continue;
+ }
+
+ /* Does the memory block begin where the last ended? */
+ if (MdBlock->BasePage == NextPage)
+ {
+ /* Add it to the current run */
+ Buffer->Run[Runs - 1].PageCount += MdBlock->PageCount;
+ }
+ else
+ {
+ /* Create a new run */
+ Runs++;
+ Buffer->Run[Runs - 1].BasePage = MdBlock->BasePage;
+ Buffer->Run[Runs - 1].PageCount = MdBlock->PageCount;
+ }
+
+ /* Set the bits in the PFN bitmap */
+ RtlSetBits(&MiPfnBitMap, MdBlock->BasePage, MdBlock->PageCount);
+
+ /* Set the next page */
+ NextPage = MdBlock->BasePage + MdBlock->PageCount;
+ }
+
+ // FIXME: allocate a buffer of better size
+
+ Buffer->NumberOfRuns = Runs;
+ Buffer->NumberOfPages = MmNumberOfPhysicalPages;
+ MmPhysicalMemoryBlock = Buffer;
+}
+
+VOID
+NTAPI
+MiBuildPagedPool(VOID)
+{
+ PMMPTE Pte;
+ MMPTE TmplPte;
+ PFN_NUMBER PageFrameIndex;
+ KIRQL OldIrql;
+ ULONG Size, BitMapSize;
+
+ /* Default size for paged pool is 4 times non paged pool */
+ MmSizeOfPagedPoolInBytes = 4 * MmMaximumNonPagedPoolInBytes;
+
+ /* Make sure it doesn't overflow */
+ if (MmSizeOfPagedPoolInBytes > ((ULONG64)MmNonPagedSystemStart -
+ (ULONG64)MmPagedPoolStart))
+ {
+ MmSizeOfPagedPoolInBytes = (ULONG64)MmNonPagedSystemStart -
+ (ULONG64)MmPagedPoolStart;
+ }
+
+ /* Make sure paged pool is big enough */
+ if (MmSizeOfPagedPoolInBytes < MI_MIN_INIT_PAGED_POOLSIZE)
+ {
+ MmSizeOfPagedPoolInBytes = MI_MIN_INIT_PAGED_POOLSIZE;
+ }
+
+ /* Align down to a PDE boundary */
+ MmSizeOfPagedPoolInBytes = ROUND_DOWN(MmSizeOfPagedPoolInBytes,
+ 512 * PAGE_SIZE);
+ MmSizeOfPagedPoolInPages = MmSizeOfPagedPoolInBytes >> PAGE_SHIFT;
+
+ /* This is where paged pool ends */
+ MmPagedPoolEnd = (PCHAR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes - 1;
+
+ /* Sanity check */
+ ASSERT(MmPagedPoolEnd < MmNonPagedSystemStart);
+
+ /* setup a template PTE */
+ TmplPte.u.Long = 0;
+ TmplPte.u.Flush.Valid = 1;
+ TmplPte.u.Flush.Write = 1;
+
+ /* Make sure the PXE is valid */
+ Pte = MiAddressToPxe(MmPagedPoolStart);
+ if (!Pte->u.Flush.Valid)
+ {
+ /* Map it! */
+ TmplPte.u.Flush.PageFrameNumber = MmAllocPage(MC_SYSTEM, 0);
+ *Pte = TmplPte;
+ }
+
+ /* Map all page directories (max 128) */
+ for (Pte = MiAddressToPpe(MmPagedPoolStart);
+ Pte <= MiAddressToPpe(MmPagedPoolEnd);
+ Pte++)
+ {
+ if (!Pte->u.Flush.Valid)
+ {
+ /* Map it! */
+ TmplPte.u.Flush.PageFrameNumber = MxAllocPage();
+ *Pte = TmplPte;
+ }
+ }
+
+ /* Create and map the first PTE for paged pool */
+ Pte = MxGetPte(MmPagedPoolStart);
+ TmplPte.u.Flush.PageFrameNumber = MxAllocPage();
+ *Pte = TmplPte;
+
+ /* Save the first and last paged pool PTE */
+ MmPagedPoolInfo.FirstPteForPagedPool = MiAddressToPte(MmPagedPoolStart);
+ MmPagedPoolInfo.LastPteForPagedPool = MiAddressToPte(MmPagedPoolEnd);
+
+ MmPagedPoolInfo.NextPdeForPagedPoolExpansion =
+ MiAddressToPde(MmPagedPoolStart) + 1;
+
+ // We keep track of each page via a bit, so check how big the bitmap will
+ // have to be (make sure to align our page count such that it fits nicely
+ // into a 4-byte aligned bitmap.
+
+ /* The size of the bitmap in bits is the size in pages */
+ BitMapSize = MmSizeOfPagedPoolInPages;
+
+ /* Calculate buffer size in bytes, aligned to 32 bits */
+ Size = sizeof(RTL_BITMAP) + ROUND_UP(BitMapSize, 32) / 8;
+
+ // Allocate the allocation bitmap, which tells us which regions have not yet
+ // been mapped into memory
+
+ MmPagedPoolInfo.PagedPoolAllocationMap =
+ ExAllocatePoolWithTag(NonPagedPool, Size, ' mM');
+ ASSERT(MmPagedPoolInfo.PagedPoolAllocationMap);
+
+ // Initialize it such that at first, only the first page's worth of PTEs is
+ // marked as allocated (incidentially, the first PDE we allocated earlier).
+ RtlInitializeBitMap(MmPagedPoolInfo.PagedPoolAllocationMap,
+ (PULONG)(MmPagedPoolInfo.PagedPoolAllocationMap + 1),
+ BitMapSize);
+ RtlSetAllBits(MmPagedPoolInfo.PagedPoolAllocationMap);
+ RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap, 0, 512);
+
+ // We have a second bitmap, which keeps track of where allocations end.
+ // Given the allocation bitmap and a base address, we can therefore figure
+ // out which page is the last page of that allocation, and thus how big the
+ // entire allocation is.
+ MmPagedPoolInfo.EndOfPagedPoolBitmap =
+ ExAllocatePoolWithTag(NonPagedPool, Size, ' mM');
+ ASSERT(MmPagedPoolInfo.EndOfPagedPoolBitmap);
+
+ /* Initialize the bitmap */
+ RtlInitializeBitMap(MmPagedPoolInfo.EndOfPagedPoolBitmap,
+ (PULONG)(MmPagedPoolInfo.EndOfPagedPoolBitmap + 1),
+ BitMapSize);
+
+ /* No allocations, no allocation ends; clear all bits. */
+ RtlClearAllBits(MmPagedPoolInfo.EndOfPagedPoolBitmap);
+
+ /* Initialize the paged pool mutex */
+ KeInitializeGuardedMutex(&MmPagedPoolMutex);
+
+ /* Initialize the paged pool */
+ InitializePool(PagedPool, 0);
+}
+
+
+NTSTATUS
+NTAPI
+MmArmInitSystem(IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ if (Phase == 0)
+ {
+ /* Parse memory descriptors */
+ MiEvaluateMemoryDescriptors(LoaderBlock);
+
+ /* Prepare PFN database mappings */
+ MiPreparePfnDatabse(LoaderBlock);
+
+ /* Initialize the session space */
+ MiInitializeSessionSpace(LoaderBlock);
+
+ /* Initialize some mappings */
+ MiInitializePageTable();
+
+ /* Update the memory descriptor, to make sure the pages we used
+ won't get inserted into the PFN database */
+ MxOldFreeDescriptor = *MxFreeDescriptor;
+ MxFreeDescriptor->BasePage = MxFreePageBase;
+ MxFreeDescriptor->PageCount = MxFreePageCount;
+ }
+ else if (Phase == 1)
+ {
+ PMMPTE Pte;
+ ULONG OldCount;
+ PPHYSICAL_MEMORY_RUN Run;
+
+ /* The PFN database was created, restore the free descriptor */
+ *MxFreeDescriptor = MxOldFreeDescriptor;
+
+ /* Switch to phase 1 */
+ MxPhase = 1;
+
+ /* Initialize the nonpaged pool */
+ MiBuildNonPagedPool();
+
+ /* Initialize system PTE handling */
+ MiBuildSystemPteSpace();
+
+ /* Build the physical memory block */
+ MiBuildPhysicalMemoryBlock(LoaderBlock);
+
+ /* Size up paged pool and build the shadow system page directory */
+ MiBuildPagedPool();
+ }
+
+ return STATUS_SUCCESS;
+}
+
}
}
- /* PUBLIC FUNCTIONS ***********************************************************/
-
- /*
- * @implemented
- */
BOOLEAN NTAPI
- SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
- IN BOOLEAN SubjectContextLocked,
- IN ACCESS_MASK DesiredAccess,
- IN ACCESS_MASK PreviouslyGrantedAccess,
- OUT PPRIVILEGE_SET* Privileges,
- IN PGENERIC_MAPPING GenericMapping,
- IN KPROCESSOR_MODE AccessMode,
- OUT PACCESS_MASK GrantedAccess,
+ IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
+ IN BOOLEAN SubjectContextLocked,
+ IN ACCESS_MASK DesiredAccess,
+ IN ACCESS_MASK PreviouslyGrantedAccess,
+ OUT PPRIVILEGE_SET* Privileges,
+ IN PGENERIC_MAPPING GenericMapping,
+ IN KPROCESSOR_MODE AccessMode,
+ OUT PACCESS_MASK GrantedAccess,
- OUT PNTSTATUS AccessStatus)
+ OUT PNTSTATUS AccessStatus,
+ SECURITY_IMPERSONATION_LEVEL LowestImpersonationLevel)
{
LUID_AND_ATTRIBUTES Privilege;
ACCESS_MASK CurrentAccess, AccessMask;
SeLockSubjectContext(&SubjectSecurityContext);
/* Now perform the access check */
- SeAccessCheck(SecurityDescriptor,
+ SepAccessCheck(SecurityDescriptor,
- &SubjectSecurityContext,
- TRUE,
- DesiredAccess,
- 0,
- &PrivilegeSet, //FIXME
- GenericMapping,
- PreviousMode,
- GrantedAccess,
+ &SubjectSecurityContext,
+ TRUE,
+ DesiredAccess,
+ 0,
+ &PrivilegeSet, //FIXME
+ GenericMapping,
+ PreviousMode,
+ GrantedAccess,
- AccessStatus);
+ AccessStatus,
+ SecurityIdentification);
/* Unlock subject context and dereference the token */
SeUnlockSubjectContext(&SubjectSecurityContext);