Sync with trunk head (part 1 of 2)

svn path=/branches/header-work/; revision=46262
This commit is contained in:
Amine Khaldi 2010-03-18 15:37:13 +00:00
commit b797eef5ea
143 changed files with 15887 additions and 8167 deletions

View file

@ -126,7 +126,6 @@ InitializeTabCtrl(HWND hwndDlg, PDXDIAG_CONTEXT pContext)
pContext->hDialogs[4] = CreateDialogParamW(hInst, MAKEINTRESOURCEW(IDD_HELP_DIALOG), hTabCtrlWnd, HelpPageWndProc, (LPARAM)pContext);
/* insert tab ctrl items */
InsertTabCtrlItem(hTabCtrlWnd, 0, MAKEINTRESOURCEW(IDS_SYSTEM_DIALOG));
InitializeDisplayAdapters(pContext);
InitializeDirectSoundPage(pContext);
@ -188,8 +187,19 @@ DxDiagWndProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
if (LOWORD(wParam) == IDC_BUTTON_NEXT)
{
//TODO
/* handle next button */
INT CurSel;
/* retrieve current page */
CurSel = TabCtrl_GetCurSel(hTabCtrlWnd);
CurSel++;
/* enable/disable next button */
EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_NEXT),
(CurSel != TabCtrl_GetItemCount(hTabCtrlWnd) - 1));
/* switch to next page */
SendMessageW(hTabCtrlWnd, TCM_SETCURSEL, CurSel, 0L);
return TRUE;
}
@ -210,6 +220,12 @@ DxDiagWndProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
pnmh = (LPNMHDR)lParam;
if ((pnmh->hwndFrom == hTabCtrlWnd) && (pnmh->idFrom == IDC_TAB_CONTROL) && (pnmh->code == TCN_SELCHANGE))
{
INT CurSel = TabCtrl_GetCurSel(hTabCtrlWnd);
/* enable/disable next button */
EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_NEXT),
(CurSel != TabCtrl_GetItemCount(hTabCtrlWnd) - 1));
TabCtrl_OnSelChange(pContext);
}
break;

View file

@ -17,7 +17,6 @@ GetRegValue(HKEY hBaseKey, LPWSTR SubKey, LPWSTR ValueName, DWORD Type, LPWSTR R
DWORD dwType;
DWORD dwSize;
if (RegOpenKeyExW(hBaseKey, SubKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
return FALSE;
@ -25,10 +24,10 @@ GetRegValue(HKEY hBaseKey, LPWSTR SubKey, LPWSTR ValueName, DWORD Type, LPWSTR R
res = RegQueryValueExW(hKey, ValueName, NULL, &dwType, (LPBYTE)Result, &dwSize);
RegCloseKey(hKey);
if (dwType != Type)
if (res != ERROR_SUCCESS)
return FALSE;
if (res != ERROR_SUCCESS)
if (dwType != Type)
return FALSE;
if (Size == sizeof(DWORD))

View file

@ -8,35 +8,35 @@ Description = The most popular and one of the best free Web Browsers out there.
Size = 7.1M
Category = 5
URLSite = http://www.mozilla.com/en-US/
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/en-US/Firefox%20Setup%203.0.17.exe
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/en-US/Firefox%20Setup%203.0.18.exe
CDPath = none
[Section.0407]
Description = Der populärste und einer der besten freien Webbrowser.
Size = 6.9M
URLSite = http://www.mozilla-europe.org/de/
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/de/Firefox%20Setup%203.0.17.exe
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/de/Firefox%20Setup%203.0.18.exe
[Section.040a]
Description = El más popular y uno de los mejores navegadores web gratuitos que hay.
Size = 7.0M
URLSite = http://www.mozilla-europe.org/es/
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/es-ES/Firefox%20Setup%203.0.17.exe
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/es-ES/Firefox%20Setup%203.0.18.exe
[Section.0414]
Description = Mest populære og best også gratis nettleserene der ute.
Size = 6.9M
URLSite = http://www.mozilla-europe.org/no/
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/nb-NO/Firefox%20Setup%203.0.17.exe
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/nb-NO/Firefox%20Setup%203.0.18.exe
[Section.0415]
Description = Najpopularniejsza i jedna z najlepszych darmowych przeglądarek internetowych.
Size = 7.8M
URLSite = http://www.mozilla-europe.org/pl/
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/pl/Firefox%20Setup%203.0.17.exe
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/pl/Firefox%20Setup%203.0.18.exe
[Section.0419]
Description = Один из самых популярных и лучших бесплатных браузеров.
Size = 7.4M
URLSite = http://www.mozilla-europe.org/ru/
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/ru/Firefox%20Setup%203.0.17.exe
URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/ru/Firefox%20Setup%203.0.18.exe

View file

@ -8,23 +8,23 @@ Description = THE Open Source Office Suite.
Size = 127MB
Category = 6
URLSite = http://www.openoffice.org/
URLDownload = http://ftp.plusline.de/OpenOffice/stable/2.4.3/OOo_2.4.3_Win32Intel_install_en-US.exe
URLDownload = ftp://archive.services.openoffice.org/pub/openoffice-archive/stable/2.4.3/OOo_2.4.3_Win32Intel_install_en-US.exe
CDPath = none
[Section.0407]
Description = DIE Open Source Office Suite.
URLSite = http://de.openoffice.org/
Size = 114.2MB
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/de/2.4.3/OOo_2.4.3_Win32Intel_install_de.exe
URLDownload = ftp://archive.services.openoffice.org/pub/openoffice-archive/localized/de/2.4.3/OOo_2.4.3_Win32Intel_install_de.exe
[Section.040a]
Description = La suite de ofimática de código abierto.
URLSite = http://es.openoffice.org/
Size = 113.9MB
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/es/2.4.3/OOo_2.4.3_Win32Intel_install_es.exe
URLDownload = ftp://archive.services.openoffice.org/pub/openoffice-archive/localized/es/2.4.3/OOo_2.4.3_Win32Intel_install_es.exe
[Section.0415]
URLSite = http://pl.openoffice.org/
Description = Otwarty pakiet biurowy.
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/pl/2.4.2/OOo_2.4.2_Win32Intel_install_pl.exe
URLDownload = ftp://archive.services.openoffice.org/pub/openoffice-archive/localized/pl/2.4.2/OOo_2.4.2_Win32Intel_install_pl.exe
Size = 113.9M

View file

@ -2,30 +2,30 @@
[Section]
Name = OpenOffice 3.0
Version = 3.1.1
Version = 3.2.0
Licence = LGPL
Description = THE Open Source Office Suite.
Size = 134.3MB
Size = 135.4MB
Category = 6
URLSite = http://www.openoffice.org/
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/stable/3.1.1/OOo_3.1.1_Win32Intel_install_en-US.exe
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/stable/3.2.0/OOo_3.2.0_Win32Intel_install_en-US.exe
CDPath = none
[Section.0407]
Description = DIE Open Source Office Suite.
URLSite = http://de.openoffice.org/
Size = 142.9MB
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/de/3.1.1/OOo_3.1.1_Win32Intel_install_de.exe
Size = 145.8MB
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/de/3.2.0/OOo_3.2.0_Win32Intel_install_de.exe
[Section.040a]
Description = La suite de ofimática de código abierto.
URLSite = http://es.openoffice.org/
Version = 3.1.0
Size = 130.0MB
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/es/3.1.0/OOo_3.1.0_Win32Intel_install_es.exe
Size = 119.4MB
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/es/3.2.0/OOo_3.2.0_Win32Intel_install_es.exe
[Section.0415]
Description = Otwarty pakiet biurowy.
URLSite = http://pl.openoffice.org/
Size = 147.1MB
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/pl/3.1.1/OOo_3.1.1_Win32Intel_install_pl.exe
Size = 133.2MB
URLDownload = http://ftp.tu-chemnitz.de/pub/openoffice/localized/pl/3.2.0/OOo_3.2.0_Win32Intel_install_pl.exe

View file

@ -2,13 +2,13 @@
[Section]
Name = SciTE
Version = 2.02
Version = 2.03
Licence = Freeware
Description = SciTE is a SCIntilla based Text Editor. Originally built to demonstrate Scintilla, it has grown to be a generally useful editor with facilities for building and running programs.
Size = 0.6M
Category = 7
URLSite = http://www.scintilla.org/
URLDownload = http://ovh.dl.sourceforge.net/sourceforge/scintilla/Sc202.exe
URLDownload = http://ovh.dl.sourceforge.net/sourceforge/scintilla/Sc203.exe
CDPath = none
[Section.0407]

View file

@ -21,20 +21,76 @@ static SERVICE_TABLE_ENTRYW ServiceTable[2] =
{ NULL, NULL }
};
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE ServiceStatusHandle;
BOOL onLiveCD = FALSE; // On livecd events will go to debug output only
HANDLE MyHeap = NULL;
/* FUNCTIONS ****************************************************************/
static VOID
UpdateServiceStatus(DWORD dwState)
{
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = dwState;
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
if (dwState == SERVICE_START_PENDING ||
dwState == SERVICE_STOP_PENDING ||
dwState == SERVICE_PAUSE_PENDING ||
dwState == SERVICE_CONTINUE_PENDING)
ServiceStatus.dwWaitHint = 10000;
else
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
}
static DWORD WINAPI
ServiceControlHandler(DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
/* FIXME */
DPRINT1("ServiceControlHandler() called (control code %lu)\n", dwControl);
return ERROR_SUCCESS;
DPRINT("ServiceControlHandler() called\n");
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
DPRINT(" SERVICE_CONTROL_STOP received\n");
UpdateServiceStatus(SERVICE_STOPPED);
return ERROR_SUCCESS;
case SERVICE_CONTROL_PAUSE:
DPRINT(" SERVICE_CONTROL_PAUSE received\n");
UpdateServiceStatus(SERVICE_PAUSED);
return ERROR_SUCCESS;
case SERVICE_CONTROL_CONTINUE:
DPRINT(" SERVICE_CONTROL_CONTINUE received\n");
UpdateServiceStatus(SERVICE_RUNNING);
return ERROR_SUCCESS;
case SERVICE_CONTROL_INTERROGATE:
DPRINT(" SERVICE_CONTROL_INTERROGATE received\n");
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
return ERROR_SUCCESS;
case SERVICE_CONTROL_SHUTDOWN:
DPRINT(" SERVICE_CONTROL_SHUTDOWN received\n");
UpdateServiceStatus(SERVICE_STOPPED);
return ERROR_SUCCESS;
default :
DPRINT1(" Control %lu received\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
}
@ -83,8 +139,6 @@ static VOID CALLBACK
ServiceMain(DWORD argc,
LPWSTR *argv)
{
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE ServiceStatusHandle;
DWORD dwError;
UNREFERENCED_PARAMETER(argc);
@ -102,31 +156,20 @@ ServiceMain(DWORD argc,
return;
}
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwWin32ExitCode = NO_ERROR;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 2000;
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
UpdateServiceStatus(SERVICE_START_PENDING);
dwError = ServiceInit();
if (dwError != ERROR_SUCCESS)
{
DPRINT1("Service stopped\n");
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
DPRINT("Service stopped (dwError: %lu\n", dwError);
UpdateServiceStatus(SERVICE_START_PENDING);
}
else
{
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
DPRINT("Service started\n");
UpdateServiceStatus(SERVICE_RUNNING);
}
SetServiceStatus(ServiceStatusHandle,
&ServiceStatus);
DPRINT("ServiceMain() done\n");
}

View file

@ -44,7 +44,8 @@ typedef struct _IO_ERROR_LPC
#define ELF_LOGFILE_ARCHIVE_SET 8
/* FIXME: MSDN reads that the following two structs are in winnt.h. Are they? */
typedef struct _EVENTLOGHEADER {
typedef struct _EVENTLOGHEADER
{
ULONG HeaderSize;
ULONG Signature;
ULONG MajorVersion;
@ -59,7 +60,8 @@ typedef struct _EVENTLOGHEADER {
ULONG EndHeaderSize;
} EVENTLOGHEADER, *PEVENTLOGHEADER;
typedef struct _EVENTLOGEOF {
typedef struct _EVENTLOGEOF
{
ULONG RecordSizeBeginning;
ULONG Ones;
ULONG Twos;
@ -72,13 +74,13 @@ typedef struct _EVENTLOGEOF {
ULONG RecordSizeEnd;
} EVENTLOGEOF, *PEVENTLOGEOF;
typedef struct
typedef struct _EVENT_OFFSET_INFO
{
ULONG EventNumber;
ULONG EventOffset;
} EVENT_OFFSET_INFO, *PEVENT_OFFSET_INFO;
typedef struct
typedef struct _LOGFILE
{
HANDLE hFile;
EVENTLOGHEADER Header;

View file

@ -480,45 +480,29 @@ NTSTATUS ElfrOpenELA(
DWORD MinorVersion,
IELF_HANDLE *LogHandle)
{
UNICODE_STRING UNCServerNameW = { 0, 0, NULL };
UNICODE_STRING ModuleNameW = { 0, 0, NULL };
UNICODE_STRING RegModuleNameW = { 0, 0, NULL };
NTSTATUS Status;
UNICODE_STRING ModuleNameW;
if (UNCServerName &&
!RtlCreateUnicodeStringFromAsciiz(&UNCServerNameW, UNCServerName))
{
return STATUS_NO_MEMORY;
}
if ((MajorVersion != 1) || (MinorVersion != 1))
return STATUS_INVALID_PARAMETER;
if (ModuleName &&
!RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
{
RtlFreeUnicodeString(&UNCServerNameW);
return STATUS_NO_MEMORY;
}
/* RegModuleName must be an empty string */
if (RegModuleName->Length > 0)
return STATUS_INVALID_PARAMETER;
if (RegModuleName &&
!RtlAnsiStringToUnicodeString(&RegModuleNameW, (PANSI_STRING)RegModuleName, TRUE))
{
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
return STATUS_NO_MEMORY;
}
RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
Status = ElfrOpenELW(
UNCServerName ? UNCServerNameW.Buffer : NULL,
ModuleName ? (PRPC_UNICODE_STRING)&ModuleNameW : NULL,
RegModuleName ? (PRPC_UNICODE_STRING)&RegModuleNameW : NULL,
MajorVersion,
MinorVersion,
LogHandle);
/* FIXME: Must verify that caller has read access */
*LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer, FALSE);
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
RtlFreeUnicodeString(&RegModuleNameW);
return Status;
if (*LogHandle == NULL)
{
return STATUS_INVALID_PARAMETER;
}
return STATUS_SUCCESS;
}
@ -531,45 +515,32 @@ NTSTATUS ElfrRegisterEventSourceA(
DWORD MinorVersion,
IELF_HANDLE *LogHandle)
{
UNICODE_STRING UNCServerNameW = { 0, 0, NULL };
UNICODE_STRING ModuleNameW = { 0, 0, NULL };
if (UNCServerName &&
!RtlCreateUnicodeStringFromAsciiz(&UNCServerNameW, UNCServerName))
{
return STATUS_NO_MEMORY;
}
if (ModuleName &&
!RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
{
RtlFreeUnicodeString(&UNCServerNameW);
return STATUS_NO_MEMORY;
}
/* RegModuleName must be an empty string */
if (RegModuleName->Length > 0)
{
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
return STATUS_INVALID_PARAMETER;
}
if ((MajorVersion != 1) || (MinorVersion != 1))
{
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
return STATUS_INVALID_PARAMETER;
}
/*FIXME: UNCServerName must specify the server or empty for local */
/*FIXME: Must verify that caller has write access */
/* FIXME: Must verify that caller has write access */
*LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer,
TRUE);
RtlFreeUnicodeString(&UNCServerNameW);
RtlFreeUnicodeString(&ModuleNameW);
return STATUS_SUCCESS;
@ -661,8 +632,32 @@ NTSTATUS ElfrGetLogInformation(
DWORD cbBufSize,
DWORD *pcbBytesNeeded)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status = STATUS_SUCCESS;
/* FIXME: check handle first */
switch (InfoLevel)
{
case EVENTLOG_FULL_INFO:
{
LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer;
*pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
{
return STATUS_BUFFER_TOO_SMALL;
}
efi->dwFull = 0; /* FIXME */
}
break;
default:
Status = STATUS_INVALID_LEVEL;
break;
}
return Status;
}

View file

@ -3,6 +3,7 @@
<group xmlns:xi="http://www.w3.org/2001/XInclude">
<property name="BASEADDRESS_REGTESTS" value="0x07000000" />
<property name="BASEADDRESS_NOTIFYHOOK" value="0x08000000" />
<property name="BASEADDRESS_FAULTREP" value="0x107A0000" />
<property name="BASEADDRESS_QMGRPRXY" value="0x1f710000" />
<property name="BASEADDRESS_CRYPTDLG" value="0x209c0000" />
<property name="BASEADDRESS_COMCAT" value="0x20a50000" />

View file

@ -286,6 +286,7 @@ dll\win32\dwmapi\dwmapi.dll 1
dll\win32\devmgr\devmgr.dll 1
dll\win32\dhcpcsvc\dhcpcsvc.dll 1
dll\win32\dnsapi\dnsapi.dll 1
dll\win32\faultrep\faultrep.dll 1
dll\win32\fmifs\fmifs.dll 1
dll\win32\fusion\fusion.dll 1
dll\win32\gdi32\gdi32.dll 1

View file

@ -232,7 +232,7 @@ WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
PVOID DriverBase;
// Separate the path to file name and directory path
sprintf(DriverPath, "%S", FilePath->Buffer);
snprintf(DriverPath, sizeof(DriverPath), "%wZ", FilePath);
DriverNamePos = strrchr(DriverPath, '\\');
if (DriverNamePos != NULL)
{
@ -261,7 +261,7 @@ WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
}
// It's not loaded, we have to load it
sprintf(FullPath,"%s%S", BootPath, FilePath->Buffer);
snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
if (!Status)
return FALSE;

View file

@ -42,12 +42,25 @@ public:
HRESULT STDMETHODCALLTYPE KsQueryExtendedSize(OUT ULONG* ExtendedSize);
HRESULT STDMETHODCALLTYPE KsSetMediaType(IN const AM_MEDIA_TYPE* AmMediaType);
CKsDataTypeHandler() : m_Ref(0){};
virtual ~CKsDataTypeHandler(){};
CKsDataTypeHandler() : m_Ref(0), m_Type(0){};
virtual ~CKsDataTypeHandler()
{
if (m_Type)
{
if (m_Type->pbFormat)
CoTaskMemFree(m_Type->pbFormat);
if (m_Type->pUnk)
m_Type->pUnk->Release();
CoTaskMemFree(m_Type);
}
};
protected:
//CMediaType * m_Type;
LONG m_Ref;
AM_MEDIA_TYPE * m_Type;
};
@ -85,8 +98,68 @@ STDMETHODCALLTYPE
CKsDataTypeHandler::KsIsMediaTypeInRanges(
IN PVOID DataRanges)
{
OutputDebugString("UNIMPLEMENTED\n");
return E_NOTIMPL;
PKSMULTIPLE_ITEM DataList;
PKSDATARANGE DataRange;
ULONG Index;
HRESULT hr = S_FALSE;
OutputDebugStringW(L"CKsDataTypeHandler::KsIsMediaTypeInRanges\n");
DataList = (PKSMULTIPLE_ITEM)DataRanges;
DataRange = (PKSDATARANGE)(DataList + 1);
for(Index = 0; Index < DataList->Count; Index++)
{
BOOL bMatch = FALSE;
if (DataRange->FormatSize >= sizeof(KSDATARANGE))
{
bMatch = IsEqualGUID(DataRange->MajorFormat, GUID_NULL);
}
if (!bMatch && DataRange->FormatSize >= sizeof(KSDATARANGE_AUDIO))
{
bMatch = IsEqualGUID(DataRange->MajorFormat, MEDIATYPE_Audio);
}
if (bMatch)
{
if (IsEqualGUID(DataRange->SubFormat, m_Type->subtype) ||
IsEqualGUID(DataRange->SubFormat, GUID_NULL))
{
if (IsEqualGUID(DataRange->Specifier, m_Type->formattype) ||
IsEqualGUID(DataRange->Specifier, GUID_NULL))
{
if (!IsEqualGUID(m_Type->formattype, FORMAT_WaveFormatEx) && !IsEqualGUID(DataRange->Specifier, FORMAT_WaveFormatEx))
{
//found match
hr = S_OK;
break;
}
if (DataRange->FormatSize >= sizeof(KSDATARANGE_AUDIO) && m_Type->cbFormat >= sizeof(WAVEFORMATEX))
{
LPWAVEFORMATEX Format = (LPWAVEFORMATEX)m_Type->pbFormat;
PKSDATARANGE_AUDIO AudioRange = (PKSDATARANGE_AUDIO)DataRange;
if (Format->nSamplesPerSec >= AudioRange->MinimumSampleFrequency &&
Format->nSamplesPerSec <= AudioRange->MaximumSampleFrequency &&
Format->wBitsPerSample >= AudioRange->MinimumSampleFrequency &&
Format->wBitsPerSample <= AudioRange->MaximumBitsPerSample &&
Format->nChannels <= AudioRange->MaximumChannels)
{
// found match
hr = S_OK;
break;
}
}
}
}
}
DataRange = (PKSDATARANGE)(((ULONG_PTR)DataRange + DataRange->FormatSize + 7) & ~7);
}
return S_OK;
}
HRESULT
@ -106,7 +179,6 @@ CKsDataTypeHandler::KsQueryExtendedSize(
{
/* no header extension required */
*ExtendedSize = 0;
return NOERROR;
}
@ -115,19 +187,38 @@ STDMETHODCALLTYPE
CKsDataTypeHandler::KsSetMediaType(
IN const AM_MEDIA_TYPE* AmMediaType)
{
#if 0
OutputDebugString("CKsDataTypeHandler::KsSetMediaType\n");
if (m_Type)
{
/* media type can only be set once */
return E_FAIL;
}
#endif
/*
* TODO: allocate CMediaType and copy parameters
*/
OutputDebugString("UNIMPLEMENTED\n");
return E_NOTIMPL;
m_Type = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
if (!m_Type)
return E_OUTOFMEMORY;
CopyMemory(m_Type, AmMediaType, sizeof(AM_MEDIA_TYPE));
if (m_Type->cbFormat)
{
m_Type->pbFormat = (BYTE*)CoTaskMemAlloc(m_Type->cbFormat);
if (!m_Type->pbFormat)
{
CoTaskMemFree(m_Type);
return E_OUTOFMEMORY;
}
CopyMemory(m_Type->pbFormat, AmMediaType->pbFormat, m_Type->cbFormat);
}
if (m_Type->pUnk)
m_Type->pUnk->AddRef();
return S_OK;
}
HRESULT
@ -138,7 +229,6 @@ CKsDataTypeHandler_Constructor (
LPVOID * ppv)
{
OutputDebugStringW(L"CKsDataTypeHandler_Constructor\n");
CKsDataTypeHandler * handler = new CKsDataTypeHandler();
if (!handler)

View file

@ -1,20 +1,21 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
* FILE: dll/directx/ksproxy/input_cpp.cpp
* FILE: dll/directx/ksproxy/input_pin.cpp
* PURPOSE: InputPin of Proxy Filter
*
* PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
*/
#include "precomp.h"
const GUID IID_IKsPinEx = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}};
const GUID IID_IKsPinPipe = {0xe539cd90, 0xa8b4, 0x11d1, {0x81, 0x89, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}};
const GUID IID_IKsPinEx = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}};
#ifndef _MSC_VER
const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
#endif
#ifndef _MSC_VER
KSPIN_INTERFACE StandardPinInterface =
{
{STATIC_KSINTERFACESETID_Standard},
@ -52,15 +53,13 @@ class CInputPin : public IPin,
public IKsControl,
public IKsObject,
public IKsPinEx,
public IMemInputPin
/*
public IQualityControl,
public IMemInputPin,
public IKsPinPipe,
public ISpecifyPropertyPages,
public IStreamBuilder,
public IKsPinFactory,
public IKsAggregateControl
*/
public IStreamBuilder,
public IKsAggregateControl,
public IQualityControl,
public ISpecifyPropertyPages
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
@ -81,6 +80,19 @@ public:
return m_Ref;
}
//IKsPinPipe
HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
IPin* STDMETHODCALLTYPE KsGetConnectedPin();
IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation);
HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator);
ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag();
HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag);
GUID STDMETHODCALLTYPE KsGetPinBusCache();
HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus);
PWCHAR STDMETHODCALLTYPE KsGetPinName();
PWCHAR STDMETHODCALLTYPE KsGetFilterName();
//IPin methods
HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
@ -98,6 +110,9 @@ public:
HRESULT STDMETHODCALLTYPE EndFlush();
HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
// ISpecifyPropertyPages
HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
//IKsObject methods
HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
@ -136,11 +151,26 @@ public:
HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
HRESULT STDMETHODCALLTYPE ReceiveCanBlock( void);
//IKsPinFactory
HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
//IStreamBuilder
HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph);
HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
//IKsAggregateControl
HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
//IQualityControl
HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q);
HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc);
//---------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hFilter(hFilter), m_hPin(0), m_PinId(PinId), m_MemAllocator(0), m_IoCount(0), m_Communication(Communication), m_Pin(0), m_ReadOnly(0){};
CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication);
virtual ~CInputPin(){};
protected:
@ -157,8 +187,42 @@ protected:
KSPIN_MEDIUM m_Medium;
IPin * m_Pin;
BOOL m_ReadOnly;
IKsInterfaceHandler * m_InterfaceHandler;
IKsAllocatorEx * m_KsAllocatorEx;
ULONG m_PipeAllocatorFlag;
BOOL m_bPinBusCacheInitialized;
GUID m_PinBusCache;
LPWSTR m_FilterName;
FRAMING_PROP m_FramingProp[4];
PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
};
CInputPin::CInputPin(
IBaseFilter * ParentFilter,
LPCWSTR PinName,
HANDLE hFilter,
ULONG PinId,
KSPIN_COMMUNICATION Communication) : m_Ref(0),
m_ParentFilter(ParentFilter),
m_PinName(PinName),
m_hFilter(hFilter),
m_hPin(INVALID_HANDLE_VALUE),
m_PinId(PinId),
m_MemAllocator(0),
m_IoCount(0),
m_Communication(Communication),
m_Pin(0),
m_ReadOnly(0),
m_InterfaceHandler(0),
m_KsAllocatorEx(0),
m_PipeAllocatorFlag(0),
m_bPinBusCacheInitialized(0),
m_FilterName(0)
{
ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
}
HRESULT
STDMETHODCALLTYPE
CInputPin::QueryInterface(
@ -205,7 +269,44 @@ CInputPin::QueryInterface(
reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsPinPipe))
{
*Output = (IKsPinPipe*)(this);
reinterpret_cast<IKsPinPipe*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsPinFactory))
{
*Output = (IKsPinFactory*)(this);
reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
return NOERROR;
}
#if 0
else if (IsEqualGUID(refiid, IID_IStreamBuilder))
{
*Output = (IStreamBuilder*)(this);
reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
return NOERROR;
}
#endif
else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
{
*Output = (IKsAggregateControl*)(this);
reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IQualityControl))
{
*Output = (IQualityControl*)(this);
reinterpret_cast<IQualityControl*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
{
*Output = (ISpecifyPropertyPages*)(this);
reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
return NOERROR;
}
WCHAR Buffer[MAX_PATH];
LPOLESTR lpstr;
@ -216,6 +317,249 @@ CInputPin::QueryInterface(
return E_NOINTERFACE;
}
//-------------------------------------------------------------------
// IQualityControl interface
//
HRESULT
STDMETHODCALLTYPE
CInputPin::Notify(
IBaseFilter *pSelf,
Quality q)
{
OutputDebugStringW(L"CInputPin::Notify NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
CInputPin::SetSink(
IQualityControl *piqc)
{
OutputDebugStringW(L"CInputPin::SetSink NotImplemented\n");
return E_NOTIMPL;
}
//-------------------------------------------------------------------
// IKsAggregateControl interface
//
HRESULT
STDMETHODCALLTYPE
CInputPin::KsAddAggregate(
IN REFGUID AggregateClass)
{
OutputDebugStringW(L"CInputPin::KsAddAggregate NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
CInputPin::KsRemoveAggregate(
REFGUID AggregateClass)
{
OutputDebugStringW(L"CInputPin::KsRemoveAggregate NotImplemented\n");
return E_NOTIMPL;
}
//-------------------------------------------------------------------
// IStreamBuilder
//
HRESULT
STDMETHODCALLTYPE
CInputPin::Render(
IPin *ppinOut,
IGraphBuilder *pGraph)
{
OutputDebugStringW(L"CInputPin::Render\n");
return S_OK;
}
HRESULT
STDMETHODCALLTYPE
CInputPin::Backout(
IPin *ppinOut,
IGraphBuilder *pGraph)
{
OutputDebugStringW(L"CInputPin::Backout\n");
return S_OK;
}
//-------------------------------------------------------------------
// IKsPinFactory
//
HRESULT
STDMETHODCALLTYPE
CInputPin::KsPinFactory(
ULONG* PinFactory)
{
OutputDebugStringW(L"CInputPin::KsPinFactory\n");
*PinFactory = m_PinId;
return S_OK;
}
//-------------------------------------------------------------------
// IKsPinPipe
//
HRESULT
STDMETHODCALLTYPE
CInputPin::KsGetPinFramingCache(
PKSALLOCATOR_FRAMING_EX *FramingEx,
PFRAMING_PROP FramingProp,
FRAMING_CACHE_OPS Option)
{
if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast)
{
// invalid argument
return E_INVALIDARG;
}
// get framing properties
*FramingProp = m_FramingProp[Option];
*FramingEx = m_FramingEx[Option];
return NOERROR;
}
HRESULT
STDMETHODCALLTYPE
CInputPin::KsSetPinFramingCache(
PKSALLOCATOR_FRAMING_EX FramingEx,
PFRAMING_PROP FramingProp,
FRAMING_CACHE_OPS Option)
{
ULONG Index;
ULONG RefCount = 0;
if (m_FramingEx[Option])
{
for(Index = 1; Index < 4; Index++)
{
if (m_FramingEx[Index] == m_FramingEx[Option])
RefCount++;
}
if (RefCount == 1)
{
// existing framing is only used once
CoTaskMemFree(m_FramingEx[Option]);
}
}
// store framing
m_FramingEx[Option] = FramingEx;
m_FramingProp[Option] = *FramingProp;
return S_OK;
}
IPin*
STDMETHODCALLTYPE
CInputPin::KsGetConnectedPin()
{
return m_Pin;
}
IKsAllocatorEx*
STDMETHODCALLTYPE
CInputPin::KsGetPipe(
KSPEEKOPERATION Operation)
{
if (Operation == KsPeekOperation_AddRef)
{
if (m_KsAllocatorEx)
m_KsAllocatorEx->AddRef();
}
return m_KsAllocatorEx;
}
HRESULT
STDMETHODCALLTYPE
CInputPin::KsSetPipe(
IKsAllocatorEx *KsAllocator)
{
if (KsAllocator)
KsAllocator->AddRef();
if (m_KsAllocatorEx)
m_KsAllocatorEx->Release();
m_KsAllocatorEx = KsAllocator;
return NOERROR;
}
ULONG
STDMETHODCALLTYPE
CInputPin::KsGetPipeAllocatorFlag()
{
return m_PipeAllocatorFlag;
}
HRESULT
STDMETHODCALLTYPE
CInputPin::KsSetPipeAllocatorFlag(
ULONG Flag)
{
m_PipeAllocatorFlag = Flag;
return NOERROR;
}
GUID
STDMETHODCALLTYPE
CInputPin::KsGetPinBusCache()
{
if (!m_bPinBusCacheInitialized)
{
CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID));
m_bPinBusCacheInitialized = TRUE;
}
return m_PinBusCache;
}
HRESULT
STDMETHODCALLTYPE
CInputPin::KsSetPinBusCache(
GUID Bus)
{
CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID));
return NOERROR;
}
PWCHAR
STDMETHODCALLTYPE
CInputPin::KsGetPinName()
{
return (PWCHAR)m_PinName;
}
PWCHAR
STDMETHODCALLTYPE
CInputPin::KsGetFilterName()
{
return m_FilterName;
}
//-------------------------------------------------------------------
// ISpecifyPropertyPages
//
HRESULT
STDMETHODCALLTYPE
CInputPin::GetPages(CAUUID *pPages)
{
if (!pPages)
return E_POINTER;
pPages->cElems = 0;
pPages->pElems = NULL;
return S_OK;
}
//-------------------------------------------------------------------
// IMemInputPin
@ -299,7 +643,6 @@ CInputPin::ReceiveCanBlock( void)
return S_FALSE;
}
//-------------------------------------------------------------------
// IKsPin
//
@ -641,16 +984,17 @@ CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
if (m_Pin)
{
// already connected
return VFW_E_ALREADY_CONNECTED;
}
// first check format
hr = CheckFormat(pmt);
if (FAILED(hr))
{
// format is not supported
return hr;
if (FAILED(CheckFormat(pmt)))
return hr;
}
hr = CreatePin(pmt);
if (FAILED(hr))
@ -658,9 +1002,8 @@ CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
return hr;
}
//FIXME create pin
m_Pin = pConnector;
m_Pin->AddRef();
m_Pin = pConnector;
m_Pin->AddRef();
return S_OK;
}
@ -828,6 +1171,7 @@ CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
return E_NOTIMPL;
}
//-------------------------------------------------------------------
HRESULT
STDMETHODCALLTYPE
@ -900,6 +1244,7 @@ CInputPin::CreatePin(
PKSMULTIPLE_ITEM InterfaceList;
PKSPIN_MEDIUM Medium;
PKSPIN_INTERFACE Interface;
IKsInterfaceHandler * InterfaceHandler;
HRESULT hr;
// query for pin medium
@ -938,8 +1283,43 @@ CInputPin::CreatePin(
Interface = &StandardPinInterface;
}
// now create pin
hr = CreatePinHandle(Medium, Interface, pmt);
if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE)
{
// now load the IKsInterfaceHandler plugin
hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler);
if (FAILED(hr))
{
// failed to load interface handler plugin
OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n");
CoTaskMemFree(MediumList);
CoTaskMemFree(InterfaceList);
return hr;
}
// now set the pin
hr = InterfaceHandler->KsSetPin((IKsPin*)this);
if (FAILED(hr))
{
// failed to load interface handler plugin
OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n");
InterfaceHandler->Release();
CoTaskMemFree(MediumList);
CoTaskMemFree(InterfaceList);
return hr;
}
// store interface handler
m_InterfaceHandler = InterfaceHandler;
// now create pin
hr = CreatePinHandle(Medium, Interface, pmt);
if (FAILED(hr))
{
m_InterfaceHandler->Release();
m_InterfaceHandler = InterfaceHandler;
}
}
// free medium / interface / dataformat
CoTaskMemFree(MediumList);

View file

@ -35,14 +35,27 @@ public:
HRESULT STDMETHODCALLTYPE KsProcessMediaSamples(IKsDataTypeHandler *KsDataTypeHandler, IMediaSample** SampleList, PLONG SampleCount, KSIOOPERATION IoOperation, PKSSTREAM_SEGMENT *StreamSegment);
HRESULT STDMETHODCALLTYPE KsCompleteIo(PKSSTREAM_SEGMENT StreamSegment);
CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL){};
CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL), m_Pin(0){};
virtual ~CKsInterfaceHandler(){};
protected:
LONG m_Ref;
HANDLE m_Handle;
IKsPinEx * m_Pin;
};
typedef struct
{
KSSTREAM_SEGMENT StreamSegment;
IMediaSample * MediaSample[64];
ULONG SampleCount;
ULONG ExtendedSize;
PKSSTREAM_HEADER StreamHeader;
OVERLAPPED Overlapped;
}KSSTREAM_SEGMENT_EXT, *PKSSTREAM_SEGMENT_EXT;
HRESULT
STDMETHODCALLTYPE
CKsInterfaceHandler::QueryInterface(
@ -66,22 +79,43 @@ CKsInterfaceHandler::KsSetPin(
{
HRESULT hr;
IKsObject * KsObject;
IKsPinEx * Pin;
// check if IKsObject is supported
hr = KsPin->QueryInterface(IID_IKsObject, (void**)&KsObject);
// get IKsPinEx interface
hr = KsPin->QueryInterface(IID_IKsPinEx, (void**)&Pin);
if (SUCCEEDED(hr))
{
// get pin handle
m_Handle = KsObject->KsGetObjectHandle();
// check if IKsObject is supported
hr = KsPin->QueryInterface(IID_IKsObject, (void**)&KsObject);
// release IKsObject interface
KsObject->Release();
if (!m_Handle)
if (SUCCEEDED(hr))
{
// expected a file handle
return E_UNEXPECTED;
// get pin handle
m_Handle = KsObject->KsGetObjectHandle();
// release IKsObject interface
KsObject->Release();
if (!m_Handle)
{
// expected a file handle
hr = E_UNEXPECTED;
Pin->Release();
}
else
{
if (m_Pin)
{
// release old interface
m_Pin->Release();
}
m_Pin = Pin;
}
}
else
{
//release IKsPinEx interface
Pin->Release();
}
}
@ -96,19 +130,330 @@ CKsInterfaceHandler::KsProcessMediaSamples(
IMediaSample** SampleList,
PLONG SampleCount,
KSIOOPERATION IoOperation,
PKSSTREAM_SEGMENT *StreamSegment)
PKSSTREAM_SEGMENT *OutStreamSegment)
{
OutputDebugString("UNIMPLEMENTED\n");
return E_NOTIMPL;
PKSSTREAM_SEGMENT_EXT StreamSegment;
ULONG ExtendedSize, Index, BytesReturned;
HRESULT hr = S_OK;
OutputDebugString("CKsInterfaceHandler::KsProcessMediaSamples\n");
// sanity check
assert(*SampleCount);
if (*SampleCount == 0 || *SampleCount < 0)
return E_FAIL;
// zero stream segment
*OutStreamSegment = NULL;
// allocate stream segment
StreamSegment = (PKSSTREAM_SEGMENT_EXT)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT));
if (!StreamSegment)
return E_OUTOFMEMORY;
// zero stream segment
ZeroMemory(StreamSegment, sizeof(KSSTREAM_SEGMENT_EXT));
//allocate event
StreamSegment->StreamSegment.CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!StreamSegment->StreamSegment.CompletionEvent)
{
// failed to create event
CoTaskMemFree(StreamSegment);
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
}
// increase our own reference count
AddRef();
// setup stream segment
StreamSegment->StreamSegment.KsDataTypeHandler = KsDataTypeHandler;
StreamSegment->StreamSegment.KsInterfaceHandler = (IKsInterfaceHandler*)this;
StreamSegment->StreamSegment.IoOperation = IoOperation;
StreamSegment->Overlapped.hEvent = StreamSegment->StreamSegment.CompletionEvent;
// ge extension size
ExtendedSize = 0;
if (KsDataTypeHandler)
{
// query extension size
KsDataTypeHandler->KsQueryExtendedSize(&ExtendedSize);
if (ExtendedSize)
{
// increment reference count
KsDataTypeHandler->AddRef();
}
else
{
// no need for the datatype handler
StreamSegment->StreamSegment.KsDataTypeHandler = NULL;
}
}
StreamSegment->ExtendedSize = ExtendedSize;
StreamSegment->SampleCount = (ULONG)*SampleCount;
// calculate stream header size count
ULONG StreamHeaderSize = StreamSegment->SampleCount * (sizeof(KSSTREAM_HEADER) + ExtendedSize);
// allocate stream header
StreamSegment->StreamHeader = (PKSSTREAM_HEADER)CoTaskMemAlloc(StreamHeaderSize);
if (!StreamSegment->StreamHeader)
{
// not enough memory
CloseHandle(StreamSegment->StreamSegment.CompletionEvent);
if (StreamSegment->StreamSegment.KsDataTypeHandler)
StreamSegment->StreamSegment.KsDataTypeHandler->Release();
// free stream segment
CoTaskMemFree(StreamSegment);
//release our reference count
Release();
return E_OUTOFMEMORY;
}
// zero stream headers
ZeroMemory(StreamSegment->StreamHeader, StreamHeaderSize);
PKSSTREAM_HEADER CurStreamHeader = StreamSegment->StreamHeader;
// initialize all stream headers
for(Index = 0; Index < StreamSegment->SampleCount; Index++)
{
if (ExtendedSize)
{
// initialize extended size
hr = KsDataTypeHandler->KsPrepareIoOperation(SampleList[Index], (CurStreamHeader + 1), IoOperation);
// sanity check
assert(hr == NOERROR);
}
// query for IMediaSample2 interface
IMediaSample2 * MediaSample;
AM_SAMPLE2_PROPERTIES Properties;
hr = SampleList[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample);
if (SUCCEEDED(hr))
{
//get properties
hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
//release IMediaSample2 interface
MediaSample->Release();
}
else
{
// get properties
hr = SampleList[Index]->GetPointer((BYTE**)&Properties.pbBuffer);
assert(hr == NOERROR);
hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop);
assert(hr == NOERROR);
Properties.dwSampleFlags = 0;
if (SampleList[Index]->IsDiscontinuity() == S_OK)
Properties.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
if (SampleList[Index]->IsPreroll() == S_OK)
Properties.dwSampleFlags |= AM_SAMPLE_PREROLL;
if (SampleList[Index]->IsSyncPoint() == S_OK)
Properties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
}
WCHAR Buffer[100];
swprintf(Buffer, L"BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u\n", Properties.cbBuffer, Properties.pbBuffer, ExtendedSize, Properties.lActual);
OutputDebugStringW(Buffer);
CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize;
CurStreamHeader->PresentationTime.Denominator = 1;
CurStreamHeader->PresentationTime.Numerator = 1;
CurStreamHeader->FrameExtent = Properties.cbBuffer;
CurStreamHeader->Data = Properties.pbBuffer;
if (IoOperation == KsIoOperation_Write)
{
// set flags
CurStreamHeader->OptionsFlags = Properties.dwSampleFlags;
CurStreamHeader->DataUsed = Properties.lActual;
// increment reference count
SampleList[Index]->AddRef();
}
// store sample in stream segment
StreamSegment->MediaSample[Index] = SampleList[Index];
// move to next header
CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size);
}
// submit to device
m_Pin->KsIncrementPendingIoCount();
if (DeviceIoControl(m_Handle,
IoOperation == KsIoOperation_Write ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM,
NULL, 0,
StreamSegment->StreamHeader,
StreamHeaderSize,
&BytesReturned,
&StreamSegment->Overlapped))
{
// signal completion
SetEvent(StreamSegment->StreamSegment.CompletionEvent);
hr = S_OK;
*OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment;
}
else
{
if (GetLastError() == ERROR_IO_PENDING)
{
*OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment;
hr = S_OK;
}
}
return hr;
}
HRESULT
STDMETHODCALLTYPE
CKsInterfaceHandler::KsCompleteIo(
PKSSTREAM_SEGMENT StreamSegment)
PKSSTREAM_SEGMENT InStreamSegment)
{
OutputDebugString("UNIMPLEMENTED\n");
return E_NOTIMPL;
PKSSTREAM_SEGMENT_EXT StreamSegment;
PKSSTREAM_HEADER CurStreamHeader;
DWORD dwError = ERROR_SUCCESS, BytesReturned;
BOOL bOverlapped;
ULONG Index;
HRESULT hr;
IMediaSample2 * MediaSample;
AM_SAMPLE2_PROPERTIES Properties;
REFERENCE_TIME Start, Stop;
OutputDebugStringW(L"CKsInterfaceHandler::KsCompleteIo\n");
// get private stream segment
StreamSegment = (PKSSTREAM_SEGMENT_EXT)InStreamSegment;
// get result
bOverlapped = GetOverlappedResult(m_Handle, &StreamSegment->Overlapped, &BytesReturned, FALSE);
dwError = GetLastError();
CurStreamHeader = StreamSegment->StreamHeader;
//iterate through all stream headers
for(Index = 0; Index < StreamSegment->SampleCount; Index++)
{
if (!bOverlapped)
{
// operation failed
m_Pin->KsNotifyError(StreamSegment->MediaSample[Index], MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, dwError));
}
// query IMediaSample2 interface
hr = StreamSegment->MediaSample[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample);
if (SUCCEEDED(hr))
{
// media sample properties
hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
if (SUCCEEDED(hr))
{
//update media sample properties
Properties.dwTypeSpecificFlags = CurStreamHeader->TypeSpecificFlags;
Properties.dwSampleFlags |= (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY);
MediaSample->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
}
// release IMediaSample2 interface
MediaSample->Release();
}
// was an extended header used
if (StreamSegment->ExtendedSize)
{
// unprepare stream header extension
StreamSegment->StreamSegment.KsDataTypeHandler->KsCompleteIoOperation(StreamSegment->MediaSample[Index], (CurStreamHeader + 1), StreamSegment->StreamSegment.IoOperation, bOverlapped == FALSE);
}
Start = 0;
Stop = 0;
if (bOverlapped && StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read)
{
// update common media sample details
StreamSegment->MediaSample[Index]->SetSyncPoint((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT));
StreamSegment->MediaSample[Index]->SetPreroll((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_PREROLL));
StreamSegment->MediaSample[Index]->SetDiscontinuity((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY));
if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEVALID)
{
// use valid timestamp
Start = CurStreamHeader->PresentationTime.Time;
if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DURATIONVALID)
{
Stop = CurStreamHeader->PresentationTime.Time + CurStreamHeader->Duration;
}
}
}
// now set time
hr = StreamSegment->MediaSample[Index]->SetTime(&Start, &Stop);
if (FAILED(hr))
{
// use start time
StreamSegment->MediaSample[Index]->SetTime(&Start, &Start);
}
// set valid data length
StreamSegment->MediaSample[Index]->SetActualDataLength(CurStreamHeader->DataUsed);
if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read)
{
if (bOverlapped)
{
// deliver sample
m_Pin->KsDeliver(StreamSegment->MediaSample[Index], CurStreamHeader->OptionsFlags);
}
}
else if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Write)
{
// release media sample reference
StreamSegment->MediaSample[Index]->Release();
}
CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size);
}
// delete stream headers
CoTaskMemFree(StreamSegment->StreamHeader);
if (StreamSegment->StreamSegment.KsDataTypeHandler)
{
// release reference
StreamSegment->StreamSegment.KsDataTypeHandler->Release();
}
// decrement pending i/o count
m_Pin->KsDecrementPendingIoCount();
//notify of completion
m_Pin->KsMediaSamplesCompleted(InStreamSegment);
//destroy stream segment
CoTaskMemFree(StreamSegment);
//release reference to ourselves
Release();
// done
// Event handle is closed by caller
return S_OK;
}
HRESULT

View file

@ -13,10 +13,10 @@
const GUID CLSID_KsClockForwarder = {0x877e4351, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
const GUID CLSID_KsQualityForwarder = {0xe05592e4, 0xc0b5, 0x11d0, {0xa4, 0x39, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96}};
const GUID CLSID_KsIBasicAudioInterfaceHandler = {0xb9f8ac3e, 0x0f71, 0x11d2, {0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d}};
#ifndef _MSC_VER
const GUID CLSID_KsIBasicAudioInterfaceHandler = {0xb9f8ac3e, 0x0f71, 0x11d2, {0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d}};
const GUID KSPROPSETID_Pin = {0x8C134960, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
const GUID KSINTERFACESETID_Standard = {STATIC_KSINTERFACESETID_Standard};
const GUID CLSID_Proxy = {0x17CCA71B, 0xECD7, 0x11D0, {0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};

View file

@ -33,6 +33,7 @@
<file>interface.cpp</file>
<file>ksproxy.cpp</file>
<file>ksproxy.rc</file>
<file>node.cpp</file>
<file>output_pin.cpp</file>
<file>proxy.cpp</file>
<file>qualityforward.cpp</file>

View file

@ -0,0 +1,157 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
* FILE: dll/directx/ksproxy/node.cpp
* PURPOSE: Control Node
*
* PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
*/
#include "precomp.h"
class CKsNode : public IKsControl
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef()
{
InterlockedIncrement(&m_Ref);
return m_Ref;
}
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
delete this;
return 0;
}
return m_Ref;
}
//IKsControl
HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
CKsNode(IUnknown * pUnkOuter, HANDLE Handle) : m_Ref(0), m_pUnkOuter(pUnkOuter), m_Handle(Handle){};
virtual ~CKsNode()
{
CloseHandle(m_Handle);
};
protected:
LONG m_Ref;
IUnknown * m_pUnkOuter;
HANDLE m_Handle;
};
HRESULT
STDMETHODCALLTYPE
CKsNode::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
if (IsEqualGUID(refiid, IID_IUnknown) ||
IsEqualGUID(refiid, IID_IKsControl))
{
*Output = PVOID(this);
reinterpret_cast<IUnknown*>(*Output)->AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
//-------------------------------------------------------------------
// IKsControl
//
HRESULT
STDMETHODCALLTYPE
CKsNode::KsProperty(
PKSPROPERTY Property,
ULONG PropertyLength,
LPVOID PropertyData,
ULONG DataLength,
ULONG* BytesReturned)
{
assert(m_Handle != 0);
return KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
}
HRESULT
STDMETHODCALLTYPE
CKsNode::KsMethod(
PKSMETHOD Method,
ULONG MethodLength,
LPVOID MethodData,
ULONG DataLength,
ULONG* BytesReturned)
{
assert(m_Handle != 0);
return KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
}
HRESULT
STDMETHODCALLTYPE
CKsNode::KsEvent(
PKSEVENT Event,
ULONG EventLength,
LPVOID EventData,
ULONG DataLength,
ULONG* BytesReturned)
{
assert(m_Handle != 0);
if (EventLength)
return KsSynchronousDeviceControl(m_Handle, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
else
return KsSynchronousDeviceControl(m_Handle, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
}
HRESULT
WINAPI
CKsNode_Constructor(
IUnknown * pUnkOuter,
HANDLE ParentHandle,
ULONG NodeId,
ACCESS_MASK DesiredAccess,
REFIID riid,
LPVOID * ppv)
{
HRESULT hr;
HANDLE handle;
KSNODE_CREATE NodeCreate;
OutputDebugStringW(L"CKsNode_Constructor\n");
//setup request
NodeCreate.CreateFlags = 0;
NodeCreate.Node = NodeId;
hr = KsCreateTopologyNode(ParentHandle, &NodeCreate, DesiredAccess, &handle);
if (hr != NOERROR)
{
OutputDebugString("CKsNode_Constructor failed to open device\n");
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, hr);
}
CKsNode * quality = new CKsNode(pUnkOuter, handle);
if (!quality)
{
// free clock handle
CloseHandle(handle);
return E_OUTOFMEMORY;
}
if (FAILED(quality->QueryInterface(riid, ppv)))
{
/* not supported */
delete quality;
return E_NOINTERFACE;
}
return NOERROR;
}

View file

@ -1,33 +1,29 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
* FILE: dll/directx/ksproxy/input_cpp.cpp
* PURPOSE: InputPin of Proxy Filter
* FILE: dll/directx/ksproxy/output_pin.cpp
* PURPOSE: OutputPin of Proxy Filter
*
* PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
*/
#include "precomp.h"
#ifndef _MSC_VER
const GUID IID_IKsPinFactory = {0xCD5EBE6BL, 0x8B6E, 0x11D1, {0x8A, 0xE0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
#endif
class COutputPin : public IPin,
public IKsObject,
public IKsPropertySet,
public IStreamBuilder,
public IKsPinFactory,
public ISpecifyPropertyPages,
// public IKsPinPipe,
public IKsControl
/*
public IQualityControl,
public IKsPinEx,
public IKsAggregateControl
public IMediaSeeking,
public IAMStreamConfig,
public IMemAllocatorNotifyCallbackTemp
*/
public IKsPinEx,
public IKsPinPipe,
public IKsControl,
public IKsAggregateControl,
public IQualityControl,
public IMediaSeeking,
public IAMBufferNegotiation,
public IAMStreamConfig,
public IMemAllocatorNotifyCallbackTemp
{
public:
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
@ -48,6 +44,23 @@ public:
return m_Ref;
}
//IKsPin
HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList);
HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList);
HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium);
HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium);
HRESULT STDMETHODCALLTYPE KsPropagateAcquire();
HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags);
HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment);
IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation);
HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator);
HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator();
LONG STDMETHODCALLTYPE KsIncrementPendingIoCount();
LONG STDMETHODCALLTYPE KsDecrementPendingIoCount();
HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta);
// IKsPinEx
VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr);
//IKsPinPipe
HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
@ -101,6 +114,46 @@ public:
//IKsPinFactory
HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
//IKsAggregateControl
HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass);
HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
//IQualityControl
HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q);
HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc);
//IMediaSeeking
HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities);
HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities);
HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat);
HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat);
HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat);
HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat);
HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat);
HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration);
HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop);
HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent);
HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat);
HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags);
HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop);
HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest);
HRESULT STDMETHODCALLTYPE SetRate(double dRate);
HRESULT STDMETHODCALLTYPE GetRate(double *pdRate);
HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll);
//IAMBufferNegotiation
HRESULT STDMETHODCALLTYPE SuggestAllocatorProperties(const ALLOCATOR_PROPERTIES *pprop);
HRESULT STDMETHODCALLTYPE GetAllocatorProperties(ALLOCATOR_PROPERTIES *pprop);
//IAMStreamConfig
HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt);
HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize);
HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **ppmt, BYTE *pSCC);
//IMemAllocatorNotifyCallbackTemp
HRESULT STDMETHODCALLTYPE NotifyRelease();
COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId);
virtual ~COutputPin();
@ -112,6 +165,20 @@ protected:
ULONG m_PinId;
IKsObject * m_KsObjectParent;
IPin * m_Pin;
IKsAllocatorEx * m_KsAllocatorEx;
ULONG m_PipeAllocatorFlag;
BOOL m_bPinBusCacheInitialized;
GUID m_PinBusCache;
LPWSTR m_FilterName;
FRAMING_PROP m_FramingProp[4];
PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
IMemAllocator * m_MemAllocator;
LONG m_IoCount;
KSPIN_COMMUNICATION m_Communication;
KSPIN_INTERFACE m_Interface;
KSPIN_MEDIUM m_Medium;
IMediaSeeking * m_FilterMediaSeeking;
};
COutputPin::~COutputPin()
@ -123,13 +190,32 @@ COutputPin::~COutputPin()
COutputPin::COutputPin(
IBaseFilter * ParentFilter,
LPCWSTR PinName,
ULONG PinId) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hPin(0), m_PinId(PinId), m_KsObjectParent(0), m_Pin(0)
ULONG PinId) : m_Ref(0),
m_ParentFilter(ParentFilter),
m_PinName(PinName),
m_hPin(INVALID_HANDLE_VALUE),
m_PinId(PinId),
m_KsObjectParent(0),
m_Pin(0),
m_KsAllocatorEx(0),
m_PipeAllocatorFlag(0),
m_bPinBusCacheInitialized(0),
m_FilterName(0),
m_MemAllocator(0),
m_IoCount(0),
m_Communication(KSPIN_COMMUNICATION_NONE),
m_FilterMediaSeeking(0)
{
HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&m_KsObjectParent);
assert(hr == S_OK);
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&m_FilterMediaSeeking);
assert(hr == S_OK);
ZeroMemory(m_FramingProp, sizeof(m_FramingProp));
ZeroMemory(m_FramingEx, sizeof(m_FramingEx));
};
HRESULT
@ -142,50 +228,102 @@ COutputPin::QueryInterface(
if (IsEqualGUID(refiid, IID_IUnknown) ||
IsEqualGUID(refiid, IID_IPin))
{
OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n");
*Output = PVOID(this);
reinterpret_cast<IUnknown*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsObject))
{
OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n");
*Output = (IKsObject*)(this);
reinterpret_cast<IKsObject*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx))
{
*Output = (IKsPinEx*)(this);
reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsPinPipe))
{
*Output = (IKsPinPipe*)(this);
reinterpret_cast<IKsPinPipe*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
{
*Output = (IKsAggregateControl*)(this);
reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IQualityControl))
{
*Output = (IQualityControl*)(this);
reinterpret_cast<IQualityControl*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsPropertySet))
{
OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n");
DebugBreak();
*Output = (IKsPropertySet*)(this);
reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsControl))
{
OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n");
*Output = (IKsControl*)(this);
reinterpret_cast<IKsControl*>(*Output)->AddRef();
return NOERROR;
}
#if 0
else if (IsEqualGUID(refiid, IID_IStreamBuilder))
{
*Output = (IStreamBuilder*)(this);
reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
return NOERROR;
}
#endif
else if (IsEqualGUID(refiid, IID_IKsPinFactory))
{
OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n");
*Output = (IKsPinFactory*)(this);
reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
{
OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n");
*Output = (ISpecifyPropertyPages*)(this);
reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IBaseFilter))
else if (IsEqualGUID(refiid, IID_IMediaSeeking))
{
OutputDebugStringW(L"COutputPin::QueryInterface query IID_IBaseFilter\n");
DebugBreak();
*Output = (IMediaSeeking*)(this);
reinterpret_cast<IMediaSeeking*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation))
{
*Output = (IAMBufferNegotiation*)(this);
reinterpret_cast<IAMBufferNegotiation*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IAMStreamConfig))
{
*Output = (IAMStreamConfig*)(this);
reinterpret_cast<IAMStreamConfig*>(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp))
{
*Output = (IMemAllocatorNotifyCallbackTemp*)(this);
reinterpret_cast<IMemAllocatorNotifyCallbackTemp*>(*Output)->AddRef();
return NOERROR;
}
WCHAR Buffer[MAX_PATH];
@ -198,6 +336,580 @@ COutputPin::QueryInterface(
return E_NOINTERFACE;
}
//-------------------------------------------------------------------
// IAMBufferNegotiation interface
//
HRESULT
STDMETHODCALLTYPE
COutputPin::SuggestAllocatorProperties(
const ALLOCATOR_PROPERTIES *pprop)
{
OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetAllocatorProperties(
ALLOCATOR_PROPERTIES *pprop)
{
OutputDebugStringW(L"COutputPin::GetAllocatorProperties NotImplemented\n");
return E_NOTIMPL;
}
//-------------------------------------------------------------------
// IAMStreamConfig interface
//
HRESULT
STDMETHODCALLTYPE
COutputPin::SetFormat(
AM_MEDIA_TYPE *pmt)
{
OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetFormat(AM_MEDIA_TYPE **ppmt)
{
OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetNumberOfCapabilities(
int *piCount,
int *piSize)
{
OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetStreamCaps(
int iIndex,
AM_MEDIA_TYPE **ppmt,
BYTE *pSCC)
{
OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n");
return E_NOTIMPL;
}
//-------------------------------------------------------------------
// IMemAllocatorNotifyCallbackTemp interface
//
HRESULT
STDMETHODCALLTYPE
COutputPin::NotifyRelease()
{
OutputDebugStringW(L"COutputPin::NotifyRelease NotImplemented\n");
return E_NOTIMPL;
}
//-------------------------------------------------------------------
// IMediaSeeking interface
//
HRESULT
STDMETHODCALLTYPE
COutputPin::GetCapabilities(
DWORD *pCapabilities)
{
return m_FilterMediaSeeking->GetCapabilities(pCapabilities);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::CheckCapabilities(
DWORD *pCapabilities)
{
return m_FilterMediaSeeking->CheckCapabilities(pCapabilities);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::IsFormatSupported(
const GUID *pFormat)
{
return m_FilterMediaSeeking->IsFormatSupported(pFormat);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::QueryPreferredFormat(
GUID *pFormat)
{
return m_FilterMediaSeeking->QueryPreferredFormat(pFormat);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetTimeFormat(
GUID *pFormat)
{
return m_FilterMediaSeeking->GetTimeFormat(pFormat);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::IsUsingTimeFormat(
const GUID *pFormat)
{
return m_FilterMediaSeeking->IsUsingTimeFormat(pFormat);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::SetTimeFormat(
const GUID *pFormat)
{
return m_FilterMediaSeeking->SetTimeFormat(pFormat);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetDuration(
LONGLONG *pDuration)
{
return m_FilterMediaSeeking->GetDuration(pDuration);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetStopPosition(
LONGLONG *pStop)
{
return m_FilterMediaSeeking->GetStopPosition(pStop);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetCurrentPosition(
LONGLONG *pCurrent)
{
return m_FilterMediaSeeking->GetCurrentPosition(pCurrent);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::ConvertTimeFormat(
LONGLONG *pTarget,
const GUID *pTargetFormat,
LONGLONG Source,
const GUID *pSourceFormat)
{
return m_FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::SetPositions(
LONGLONG *pCurrent,
DWORD dwCurrentFlags,
LONGLONG *pStop,
DWORD dwStopFlags)
{
return m_FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetPositions(
LONGLONG *pCurrent,
LONGLONG *pStop)
{
return m_FilterMediaSeeking->GetPositions(pCurrent, pStop);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetAvailable(
LONGLONG *pEarliest,
LONGLONG *pLatest)
{
return m_FilterMediaSeeking->GetAvailable(pEarliest, pLatest);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::SetRate(
double dRate)
{
return m_FilterMediaSeeking->SetRate(dRate);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetRate(
double *pdRate)
{
return m_FilterMediaSeeking->GetRate(pdRate);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::GetPreroll(
LONGLONG *pllPreroll)
{
return m_FilterMediaSeeking->GetPreroll(pllPreroll);
}
//-------------------------------------------------------------------
// IQualityControl interface
//
HRESULT
STDMETHODCALLTYPE
COutputPin::Notify(
IBaseFilter *pSelf,
Quality q)
{
OutputDebugStringW(L"COutputPin::Notify NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::SetSink(
IQualityControl *piqc)
{
OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n");
return E_NOTIMPL;
}
//-------------------------------------------------------------------
// IKsAggregateControl interface
//
HRESULT
STDMETHODCALLTYPE
COutputPin::KsAddAggregate(
IN REFGUID AggregateClass)
{
OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsRemoveAggregate(
REFGUID AggregateClass)
{
OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n");
return E_NOTIMPL;
}
//-------------------------------------------------------------------
// IKsPin
//
HRESULT
STDMETHODCALLTYPE
COutputPin::KsQueryMediums(
PKSMULTIPLE_ITEM* MediumList)
{
HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle();
return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsQueryInterfaces(
PKSMULTIPLE_ITEM* InterfaceList)
{
HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle();
return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsCreateSinkPinHandle(
KSPIN_INTERFACE& Interface,
KSPIN_MEDIUM& Medium)
{
OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsGetCurrentCommunication(
KSPIN_COMMUNICATION *Communication,
KSPIN_INTERFACE *Interface,
KSPIN_MEDIUM *Medium)
{
if (Communication)
{
*Communication = m_Communication;
}
if (Interface)
{
if (!m_hPin)
return VFW_E_NOT_CONNECTED;
CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
}
if (Medium)
{
if (!m_hPin)
return VFW_E_NOT_CONNECTED;
CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
}
return NOERROR;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsPropagateAcquire()
{
OutputDebugStringW(L"COutputPin::KsPropagateAcquire NotImplemented\n");
return E_NOTIMPL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsDeliver(
IMediaSample* Sample,
ULONG Flags)
{
return E_FAIL;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
{
return NOERROR;
}
IMemAllocator *
STDMETHODCALLTYPE
COutputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
{
if (Operation == KsPeekOperation_AddRef)
{
// add reference on allocator
m_MemAllocator->AddRef();
}
return m_MemAllocator;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
{
if (MemAllocator)
{
MemAllocator->AddRef();
}
if (m_MemAllocator)
{
m_MemAllocator->Release();
}
m_MemAllocator = MemAllocator;
return NOERROR;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsRenegotiateAllocator()
{
return E_FAIL;
}
LONG
STDMETHODCALLTYPE
COutputPin::KsIncrementPendingIoCount()
{
return InterlockedIncrement((volatile LONG*)&m_IoCount);
}
LONG
STDMETHODCALLTYPE
COutputPin::KsDecrementPendingIoCount()
{
return InterlockedDecrement((volatile LONG*)&m_IoCount);
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsQualityNotify(
ULONG Proportion,
REFERENCE_TIME TimeDelta)
{
OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n");
return E_NOTIMPL;
}
//-------------------------------------------------------------------
// IKsPinEx
//
VOID
STDMETHODCALLTYPE
COutputPin::KsNotifyError(
IMediaSample* Sample,
HRESULT hr)
{
OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n");
}
//-------------------------------------------------------------------
// IKsPinPipe
//
HRESULT
STDMETHODCALLTYPE
COutputPin::KsGetPinFramingCache(
PKSALLOCATOR_FRAMING_EX *FramingEx,
PFRAMING_PROP FramingProp,
FRAMING_CACHE_OPS Option)
{
if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast)
{
// invalid argument
return E_INVALIDARG;
}
// get framing properties
*FramingProp = m_FramingProp[Option];
*FramingEx = m_FramingEx[Option];
return NOERROR;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsSetPinFramingCache(
PKSALLOCATOR_FRAMING_EX FramingEx,
PFRAMING_PROP FramingProp,
FRAMING_CACHE_OPS Option)
{
ULONG Index;
ULONG RefCount = 0;
if (m_FramingEx[Option])
{
for(Index = 1; Index < 4; Index++)
{
if (m_FramingEx[Index] == m_FramingEx[Option])
RefCount++;
}
if (RefCount == 1)
{
// existing framing is only used once
CoTaskMemFree(m_FramingEx[Option]);
}
}
// store framing
m_FramingEx[Option] = FramingEx;
m_FramingProp[Option] = *FramingProp;
return S_OK;
}
IPin*
STDMETHODCALLTYPE
COutputPin::KsGetConnectedPin()
{
return m_Pin;
}
IKsAllocatorEx*
STDMETHODCALLTYPE
COutputPin::KsGetPipe(
KSPEEKOPERATION Operation)
{
if (Operation == KsPeekOperation_AddRef)
{
if (m_KsAllocatorEx)
m_KsAllocatorEx->AddRef();
}
return m_KsAllocatorEx;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsSetPipe(
IKsAllocatorEx *KsAllocator)
{
if (KsAllocator)
KsAllocator->AddRef();
if (m_KsAllocatorEx)
m_KsAllocatorEx->Release();
m_KsAllocatorEx = KsAllocator;
return NOERROR;
}
ULONG
STDMETHODCALLTYPE
COutputPin::KsGetPipeAllocatorFlag()
{
return m_PipeAllocatorFlag;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsSetPipeAllocatorFlag(
ULONG Flag)
{
m_PipeAllocatorFlag = Flag;
return NOERROR;
}
GUID
STDMETHODCALLTYPE
COutputPin::KsGetPinBusCache()
{
if (!m_bPinBusCacheInitialized)
{
CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID));
m_bPinBusCacheInitialized = TRUE;
}
return m_PinBusCache;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::KsSetPinBusCache(
GUID Bus)
{
CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID));
return NOERROR;
}
PWCHAR
STDMETHODCALLTYPE
COutputPin::KsGetPinName()
{
return (PWCHAR)m_PinName;
}
PWCHAR
STDMETHODCALLTYPE
COutputPin::KsGetFilterName()
{
return m_FilterName;
}
//-------------------------------------------------------------------
// ISpecifyPropertyPages
//
@ -226,6 +938,7 @@ STDMETHODCALLTYPE
COutputPin::KsPinFactory(
ULONG* PinFactory)
{
OutputDebugStringW(L"COutputPin::KsPinFactory\n");
*PinFactory = m_PinId;
return S_OK;
}
@ -241,6 +954,7 @@ COutputPin::Render(
IPin *ppinOut,
IGraphBuilder *pGraph)
{
OutputDebugStringW(L"COutputPin::Render\n");
return S_OK;
}
@ -250,6 +964,7 @@ COutputPin::Backout(
IPin *ppinOut,
IGraphBuilder *pGraph)
{
OutputDebugStringW(L"COutputPin::Backout\n");
return S_OK;
}
//-------------------------------------------------------------------
@ -259,6 +974,7 @@ HANDLE
STDMETHODCALLTYPE
COutputPin::KsGetObjectHandle()
{
OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n");
assert(m_hPin);
return m_hPin;
}
@ -276,6 +992,7 @@ COutputPin::KsProperty(
ULONG* BytesReturned)
{
assert(m_hPin != 0);
OutputDebugStringW(L"COutputPin::KsProperty\n");
return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
}
@ -289,6 +1006,7 @@ COutputPin::KsMethod(
ULONG* BytesReturned)
{
assert(m_hPin != 0);
OutputDebugStringW(L"COutputPin::KsMethod\n");
return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
}
@ -303,6 +1021,8 @@ COutputPin::KsEvent(
{
assert(m_hPin != 0);
OutputDebugStringW(L"COutputPin::KsEvent\n");
if (EventLength)
return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
else
@ -325,6 +1045,8 @@ COutputPin::Set(
{
ULONG BytesReturned;
OutputDebugStringW(L"COutputPin::Set\n");
if (cbInstanceData)
{
PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
@ -367,6 +1089,8 @@ COutputPin::Get(
{
ULONG BytesReturned;
OutputDebugStringW(L"COutputPin::Get\n");
if (cbInstanceData)
{
PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
@ -406,6 +1130,8 @@ COutputPin::QuerySupported(
KSPROPERTY Property;
ULONG BytesReturned;
OutputDebugStringW(L"COutputPin::QuerySupported\n");
Property.Set = guidPropSet;
Property.Id = dwPropID;
Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
@ -470,12 +1196,15 @@ HRESULT
STDMETHODCALLTYPE
COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
{
OutputDebugStringW(L"COutputPin::ReceiveConnection\n");
return E_UNEXPECTED;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::Disconnect( void)
{
OutputDebugStringW(L"COutputPin::Disconnect\n");
if (!m_Pin)
{
// pin was not connected
@ -495,6 +1224,8 @@ HRESULT
STDMETHODCALLTYPE
COutputPin::ConnectedTo(IPin **pPin)
{
OutputDebugStringW(L"COutputPin::ConnectedTo\n");
if (!pPin)
return E_POINTER;
@ -520,6 +1251,8 @@ HRESULT
STDMETHODCALLTYPE
COutputPin::QueryPinInfo(PIN_INFO *pInfo)
{
OutputDebugStringW(L"COutputPin::QueryPinInfo\n");
wcscpy(pInfo->achName, m_PinName);
pInfo->dir = PINDIR_OUTPUT;
pInfo->pFilter = m_ParentFilter;
@ -531,6 +1264,8 @@ HRESULT
STDMETHODCALLTYPE
COutputPin::QueryDirection(PIN_DIRECTION *pPinDir)
{
OutputDebugStringW(L"COutputPin::QueryDirection\n");
if (pPinDir)
{
*pPinDir = PINDIR_OUTPUT;
@ -543,6 +1278,8 @@ HRESULT
STDMETHODCALLTYPE
COutputPin::QueryId(LPWSTR *Id)
{
OutputDebugStringW(L"COutputPin::QueryId\n");
*Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
if (!*Id)
return E_OUTOFMEMORY;
@ -580,10 +1317,10 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
// query media type count
hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
if (FAILED(hr) || !MediaTypeCount)
{
{
OutputDebugStringW(L"COutputPin::EnumMediaTypes failed1\n");
return hr;
}
}
// allocate media types
MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
@ -605,7 +1342,7 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
{
// failed
CoTaskMemFree(MediaTypes);
OutputDebugStringW(L"COutputPin::EnumMediaTypes failed2\n");
OutputDebugStringW(L"COutputPin::EnumMediaTypes failed\n");
return hr;
}
}

View file

@ -19,8 +19,23 @@
#include <stdio.h>
#include <vector>
#include <assert.h>
#include <ksmedia.h>
//#include <debug.h>
interface DECLSPEC_UUID("877E4351-6FEA-11D0-B863-00AA00A216A1") IKsClock;
#undef INTERFACE
#define INTERFACE IKsClock
DECLARE_INTERFACE_(IKsClock, IUnknown)
{
STDMETHOD_(HANDLE, KsGetClockHandle)(
THIS
) PURE;
};
typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
typedef struct {
@ -139,4 +154,19 @@ CEnumMediaTypes_fnConstructor(
REFIID riid,
LPVOID * ppv);
/* node.cpp */
HRESULT
WINAPI
CKsNode_Constructor(
IUnknown * pUnkOuter,
HANDLE ParentHandle,
ULONG NodeId,
ACCESS_MASK DesiredAccess,
REFIID riid,
LPVOID * ppv);
extern const GUID IID_IKsObject;
extern const GUID IID_IKsPinEx;
extern const GUID IID_IKsAggregateControl;
extern const GUID IID_IKsPinPipe;
extern const GUID IID_IKsPinFactory;

File diff suppressed because it is too large Load diff

View file

@ -92,7 +92,7 @@ KsiCreateObjectType( HANDLE hHandle,
*
*--*/
KSDDKAPI
NTSTATUS
DWORD
NTAPI
KsCreateAllocator(HANDLE ConnectionHandle,
PKSALLOCATOR_FRAMING AllocatorFraming,
@ -130,7 +130,7 @@ KsCreateAllocator(HANDLE ConnectionHandle,
*
*--*/
KSDDKAPI
NTSTATUS
DWORD
NTAPI
KsCreateClock(HANDLE ConnectionHandle,
PKSCLOCK_CREATE ClockCreate,
@ -225,7 +225,7 @@ KsCreatePin(HANDLE FilterHandle,
*
*--*/
KSDDKAPI
NTSTATUS
DWORD
NTAPI
KsCreateTopologyNode(HANDLE ParentHandle,
PKSNODE_CREATE NodeCreate,

View file

@ -1916,9 +1916,9 @@ RegpApplyRestrictions(DWORD dwFlags,
{
DWORD cbExpect = 0;
if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD)
if ((dwFlags & RRF_RT_ANY) == RRF_RT_DWORD)
cbExpect = 4;
else if ((dwFlags & RRF_RT_QWORD) == RRF_RT_QWORD)
else if ((dwFlags & RRF_RT_ANY) == RRF_RT_QWORD)
cbExpect = 8;
if (cbExpect && cbData != cbExpect)

View file

@ -805,6 +805,9 @@ static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
return FALSE;
}
while (*StringSid == ' ')
StringSid++;
*cBytes = ComputeStringSidSize(StringSid);
if (!pisid) /* Simply compute the size */
{

View file

@ -42,7 +42,7 @@ EVENTLOG_HANDLE_A_bind(EVENTLOG_HANDLE_A UNCServerName)
status = RpcStringBindingComposeA(NULL,
(UCHAR *)"ncacn_np",
(UCHAR *)UNCServerName,
(UCHAR *)"\\pipe\\ntsvcs",
(UCHAR *)"\\pipe\\EventLog",
NULL,
(UCHAR **)&pszStringBinding);
if (status)
@ -147,20 +147,17 @@ BOOL WINAPI
BackupEventLogA(IN HANDLE hEventLog,
IN LPCSTR lpBackupFileName)
{
RPC_STRING BackupFileName;
ANSI_STRING BackupFileName;
NTSTATUS Status;
TRACE("%p, %s\n", hEventLog, lpBackupFileName);
BackupFileName.Buffer = (LPSTR)lpBackupFileName;
BackupFileName.Length = BackupFileName.MaximumLength =
lpBackupFileName ? strlen(lpBackupFileName) : 0;
BackupFileName.MaximumLength += sizeof(CHAR);
RtlInitAnsiString(&BackupFileName, lpBackupFileName);
RpcTryExcept
{
Status = ElfrBackupELFA(hEventLog,
&BackupFileName);
(PRPC_STRING)&BackupFileName);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
@ -188,20 +185,17 @@ BOOL WINAPI
BackupEventLogW(IN HANDLE hEventLog,
IN LPCWSTR lpBackupFileName)
{
RPC_UNICODE_STRING BackupFileName;
UNICODE_STRING BackupFileName;
NTSTATUS Status;
TRACE("%p, %s\n", hEventLog, debugstr_w(lpBackupFileName));
BackupFileName.Buffer = (LPWSTR)lpBackupFileName;
BackupFileName.Length = BackupFileName.MaximumLength =
lpBackupFileName ? wcslen(lpBackupFileName) * sizeof(WCHAR) : 0;
BackupFileName.MaximumLength += sizeof(WCHAR);
RtlInitUnicodeString(&BackupFileName, lpBackupFileName);
RpcTryExcept
{
Status = ElfrBackupELFW(hEventLog,
&BackupFileName);
(PRPC_UNICODE_STRING)&BackupFileName);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
@ -226,20 +220,17 @@ BOOL WINAPI
ClearEventLogA(IN HANDLE hEventLog,
IN LPCSTR lpBackupFileName)
{
RPC_STRING BackupFileName;
ANSI_STRING BackupFileName;
NTSTATUS Status;
TRACE("%p, %s\n", hEventLog, lpBackupFileName);
BackupFileName.Buffer = (LPSTR)lpBackupFileName;
BackupFileName.Length = BackupFileName.MaximumLength =
lpBackupFileName ? strlen(lpBackupFileName) : 0;
BackupFileName.MaximumLength += sizeof(CHAR);
RtlInitAnsiString(&BackupFileName, lpBackupFileName);
RpcTryExcept
{
Status = ElfrClearELFA(hEventLog,
&BackupFileName);
(PRPC_STRING)&BackupFileName);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
@ -264,20 +255,17 @@ BOOL WINAPI
ClearEventLogW(IN HANDLE hEventLog,
IN LPCWSTR lpBackupFileName)
{
RPC_UNICODE_STRING BackupFileName;
UNICODE_STRING BackupFileName;
NTSTATUS Status;
TRACE("%p, %s\n", hEventLog, debugstr_w(lpBackupFileName));
BackupFileName.Buffer = (LPWSTR)lpBackupFileName;
BackupFileName.Length = BackupFileName.MaximumLength =
lpBackupFileName ? wcslen(lpBackupFileName) * sizeof(WCHAR) : 0;
BackupFileName.MaximumLength += sizeof(WCHAR);
RtlInitUnicodeString(&BackupFileName,lpBackupFileName);
RpcTryExcept
{
Status = ElfrClearELFW(hEventLog,
&BackupFileName);
(PRPC_UNICODE_STRING)&BackupFileName);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
@ -380,6 +368,12 @@ GetEventLogInformation(IN HANDLE hEventLog,
{
NTSTATUS Status;
if (dwInfoLevel != EVENTLOG_FULL_INFO)
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
RpcTryExcept
{
Status = ElfrGetLogInformation(hEventLog,
@ -562,21 +556,18 @@ HANDLE WINAPI
OpenBackupEventLogW(IN LPCWSTR lpUNCServerName,
IN LPCWSTR lpFileName)
{
RPC_UNICODE_STRING FileName;
UNICODE_STRING FileName;
IELF_HANDLE LogHandle;
NTSTATUS Status;
TRACE("%s, %s\n", debugstr_w(lpUNCServerName), debugstr_w(lpFileName));
FileName.Buffer = (LPWSTR)lpFileName;
FileName.Length = FileName.MaximumLength =
lpFileName ? wcslen(lpFileName) * sizeof(WCHAR) : 0;
FileName.MaximumLength += sizeof(WCHAR);
RtlInitUnicodeString(&FileName, lpFileName);
RpcTryExcept
{
Status = ElfrOpenBELW((LPWSTR)lpUNCServerName,
&FileName,
(PRPC_UNICODE_STRING)&FileName,
1,
1,
&LogHandle);
@ -903,21 +894,18 @@ HANDLE WINAPI
RegisterEventSourceW(IN LPCWSTR lpUNCServerName,
IN LPCWSTR lpSourceName)
{
RPC_UNICODE_STRING SourceName;
UNICODE_STRING SourceName;
IELF_HANDLE LogHandle;
NTSTATUS Status;
TRACE("%s, %s\n", debugstr_w(lpUNCServerName), debugstr_w(lpSourceName));
SourceName.Buffer = (LPWSTR)lpSourceName;
SourceName.Length = SourceName.MaximumLength =
lpSourceName ? wcslen(lpSourceName) * sizeof(WCHAR) : 0;
SourceName.MaximumLength += sizeof(WCHAR);
RtlInitUnicodeString(&SourceName, lpSourceName);
RpcTryExcept
{
Status = ElfrRegisterEventSourceW((LPWSTR)lpUNCServerName,
&SourceName,
(PRPC_UNICODE_STRING)&SourceName,
&EmptyStringU,
1,
1,

View file

@ -131,61 +131,6 @@ SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
}
handle_t __RPC_USER
RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus)
{
handle_t hBinding = NULL;
LPWSTR pszStringBinding;
RPC_STATUS status;
TRACE("RPC_SERVICE_STATUS_HANDLE_bind() called\n");
status = RpcStringBindingComposeW(NULL,
L"ncacn_np",
NULL,
L"\\pipe\\ntsvcs",
NULL,
&pszStringBinding);
if (status != RPC_S_OK)
{
ERR("RpcStringBindingCompose returned 0x%x\n", status);
return NULL;
}
/* Set the binding handle that will be used to bind to the server. */
status = RpcBindingFromStringBindingW(pszStringBinding,
&hBinding);
if (status != RPC_S_OK)
{
ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
}
status = RpcStringFreeW(&pszStringBinding);
if (status != RPC_S_OK)
{
ERR("RpcStringFree returned 0x%x\n", status);
}
return hBinding;
}
void __RPC_USER
RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus,
handle_t hBinding)
{
RPC_STATUS status;
TRACE("RPC_SERVICE_STATUS_HANDLE_unbind() called\n");
status = RpcBindingFree(&hBinding);
if (status != RPC_S_OK)
{
ERR("RpcBindingFree returned 0x%x\n", status);
}
}
DWORD
ScmRpcStatusToWinError(RPC_STATUS Status)
{

View file

@ -41,10 +41,87 @@ typedef struct _ACTIVE_SERVICE
static DWORD dwActiveServiceCount = 0;
static PACTIVE_SERVICE lpActiveServices = NULL;
static handle_t hStatusBinding = NULL;
/* FUNCTIONS *****************************************************************/
handle_t __RPC_USER
RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus)
{
return hStatusBinding;
}
void __RPC_USER
RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus,
handle_t hBinding)
{
}
static RPC_STATUS
ScCreateStatusBinding(VOID)
{
LPWSTR pszStringBinding;
RPC_STATUS status;
TRACE("ScCreateStatusBinding() called\n");
status = RpcStringBindingComposeW(NULL,
L"ncacn_np",
NULL,
L"\\pipe\\ntsvcs",
NULL,
&pszStringBinding);
if (status != RPC_S_OK)
{
ERR("RpcStringBindingCompose returned 0x%x\n", status);
return status;
}
/* Set the binding handle that will be used to bind to the server. */
status = RpcBindingFromStringBindingW(pszStringBinding,
&hStatusBinding);
if (status != RPC_S_OK)
{
ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
}
status = RpcStringFreeW(&pszStringBinding);
if (status != RPC_S_OK)
{
ERR("RpcStringFree returned 0x%x\n", status);
}
return status;
}
static RPC_STATUS
ScDestroyStatusBinding(VOID)
{
RPC_STATUS status;
TRACE("ScDestroyStatusBinding() called\n");
if (hStatusBinding == NULL)
return RPC_S_OK;
status = RpcBindingFree(&hStatusBinding);
if (status != RPC_S_OK)
{
ERR("RpcBindingFree returned 0x%x\n", status);
}
else
{
hStatusBinding = NULL;
}
return status;
}
static PACTIVE_SERVICE
ScLookupServiceByServiceName(LPCWSTR lpServiceName)
{
@ -259,7 +336,6 @@ ScConnectControlPipe(HANDLE *hPipe)
TRACE("Sent Process ID %lu\n", dwProcessId);
return ERROR_SUCCESS;
}
@ -403,7 +479,7 @@ ScServiceDispatcher(HANDLE hPipe,
}
else
{
dwError = ERROR_NOT_FOUND;
dwError = ERROR_SERVICE_DOES_NOT_EXIST;
}
ReplyPacket.dwError = dwError;
@ -747,7 +823,12 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
return FALSE;
}
ScCreateStatusBinding();
ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
ScDestroyStatusBinding();
CloseHandle(hPipe);
/* Free the message buffer */
@ -837,7 +918,12 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
return FALSE;
}
ScCreateStatusBinding();
ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
ScDestroyStatusBinding();
CloseHandle(hPipe);
/* Free the message buffer */

View file

@ -108,12 +108,18 @@ static int coff_add_file(struct CoffFileSet* coff_files, struct module* module,
if (coff_files->nfiles + 1 >= coff_files->nfiles_alloc)
{
coff_files->nfiles_alloc += 10;
coff_files->files = (coff_files->files) ?
HeapReAlloc(GetProcessHeap(), 0, coff_files->files,
coff_files->nfiles_alloc * sizeof(struct CoffFile)) :
HeapAlloc(GetProcessHeap(), 0,
coff_files->nfiles_alloc * sizeof(struct CoffFile));
if (coff_files->files)
{
coff_files->nfiles_alloc *= 2;
coff_files->files = HeapReAlloc(GetProcessHeap(), 0, coff_files->files,
coff_files->nfiles_alloc * sizeof(struct CoffFile));
}
else
{
coff_files->nfiles_alloc = 16;
coff_files->files = HeapAlloc(GetProcessHeap(), 0,
coff_files->nfiles_alloc * sizeof(struct CoffFile));
}
}
file = coff_files->files + coff_files->nfiles;
file->startaddr = 0xffffffff;
@ -132,7 +138,7 @@ static void coff_add_symbol(struct CoffFile* coff_file, struct symt* sym)
{
if (coff_file->neps + 1 >= coff_file->neps_alloc)
{
coff_file->neps_alloc += 10;
coff_file->neps_alloc *= 2;
coff_file->entries = (coff_file->entries) ?
HeapReAlloc(GetProcessHeap(), 0, coff_file->entries,
coff_file->neps_alloc * sizeof(struct symt*)) :
@ -389,6 +395,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg)
{
if (coff_files.files[j].entries != NULL)
{
symt_cmp_addr_module = msc_dbg->module;
qsort(coff_files.files[j].entries, coff_files.files[j].neps,
sizeof(struct symt*), symt_cmp_addr);
}
@ -413,7 +420,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg)
for (;;)
{
if (l+1 >= coff_files.files[j].neps) break;
symt_get_info(coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
symt_get_info(msc_dbg->module, coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
if (((msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress) < addr))
break;
l++;
@ -426,7 +433,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg)
* start of the function, so we need to subtract that offset
* first.
*/
symt_get_info(coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
symt_get_info(msc_dbg->module, coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
symt_add_func_line(msc_dbg->module, (struct symt_function*)coff_files.files[j].entries[l+1],
coff_files.files[j].compiland->source, linepnt->Linenumber,
msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress - addr);

View file

@ -0,0 +1,412 @@
/*
* File cpu_i386.c
*
* Copyright (C) 2009-2009, Eric Pouech.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h"
#include "wine/winbase16.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
#define STEP_FLAG 0x00000100 /* single step flag */
#define V86_FLAG 0x00020000
#define IS_VM86_MODE(ctx) (ctx->EFlags & V86_FLAG)
#ifdef __i386__
static ADDRESS_MODE get_selector_type(HANDLE hThread, const CONTEXT* ctx, WORD sel)
{
LDT_ENTRY le;
if (IS_VM86_MODE(ctx)) return AddrModeReal;
/* null or system selector */
if (!(sel & 4) || ((sel >> 3) < 17)) return AddrModeFlat;
if (hThread && GetThreadSelectorEntry(hThread, sel, &le))
return le.HighWord.Bits.Default_Big ? AddrMode1632 : AddrMode1616;
/* selector doesn't exist */
return -1;
}
static unsigned i386_build_addr(HANDLE hThread, const CONTEXT* ctx, ADDRESS64* addr,
unsigned seg, unsigned long offset)
{
addr->Mode = AddrModeFlat;
addr->Segment = seg;
addr->Offset = offset;
if (seg)
{
switch (addr->Mode = get_selector_type(hThread, ctx, seg))
{
case AddrModeReal:
case AddrMode1616:
addr->Offset &= 0xffff;
break;
case AddrModeFlat:
case AddrMode1632:
break;
default:
return FALSE;
}
}
return TRUE;
}
#endif
static unsigned i386_get_addr(HANDLE hThread, const CONTEXT* ctx,
enum cpu_addr ca, ADDRESS64* addr)
{
#ifdef __i386__
switch (ca)
{
case cpu_addr_pc: return i386_build_addr(hThread, ctx, addr, ctx->SegCs, ctx->Eip);
case cpu_addr_stack: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Esp);
case cpu_addr_frame: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Ebp);
}
#endif
return FALSE;
}
enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
/* indexes in Reserved array */
#define __CurrentMode 0
#define __CurrentSwitch 1
#define __NextSwitch 2
#define curr_mode (frame->Reserved[__CurrentMode])
#define curr_switch (frame->Reserved[__CurrentSwitch])
#define next_switch (frame->Reserved[__NextSwitch])
static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
{
STACK32FRAME frame32;
STACK16FRAME frame16;
char ch;
ADDRESS64 tmp;
DWORD p;
WORD val;
BOOL do_switch;
/* sanity check */
if (curr_mode >= stm_done) return FALSE;
TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%p nSwitch=%p\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
(void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch);
if (curr_mode == stm_start)
{
THREAD_BASIC_INFORMATION info;
if ((frame->AddrPC.Mode == AddrModeFlat) &&
(frame->AddrFrame.Mode != AddrModeFlat))
{
WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
goto done_err;
}
/* Init done */
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ? stm_32bit : stm_16bit;
/* cur_switch holds address of WOW32Reserved field in TEB in debuggee
* address space
*/
if (NtQueryInformationThread(csw->hThread, ThreadBasicInformation, &info,
sizeof(info), NULL) == STATUS_SUCCESS)
{
curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, WOW32Reserved);
if (!sw_read_mem(csw, curr_switch, &p, sizeof(p)))
{
WARN("Can't read TEB:WOW32Reserved\n");
goto done_err;
}
next_switch = p;
if (!next_switch) /* no 16-bit stack */
{
curr_switch = 0;
}
else if (curr_mode == stm_16bit)
{
if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
goto done_err;
}
curr_switch = (DWORD)frame32.frame16;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(curr_switch);
tmp.Offset = OFFSETOF(curr_switch);
if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
curr_switch = 0xFFFFFFFF;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(csw, &tmp);
if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
curr_switch = (DWORD_PTR)frame16.frame32;
if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
curr_switch = 0xFFFFFFFF;
}
}
else
/* FIXME: this will allow to work when we're not attached to a live target,
* but the 16 <=> 32 switch facility won't be available.
*/
curr_switch = 0;
frame->AddrReturn.Mode = frame->AddrStack.Mode = (curr_mode == stm_16bit) ? AddrMode1616 : AddrModeFlat;
/* don't set up AddrStack on first call. Either the caller has set it up, or
* we will get it in the next frame
*/
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
}
else
{
if (frame->AddrFrame.Offset == 0) goto done_err;
if (frame->AddrFrame.Mode == AddrModeFlat)
{
assert(curr_mode == stm_32bit);
do_switch = curr_switch && frame->AddrFrame.Offset >= curr_switch;
}
else
{
assert(curr_mode == stm_16bit);
do_switch = curr_switch &&
frame->AddrFrame.Segment == SELECTOROF(curr_switch) &&
frame->AddrFrame.Offset >= OFFSETOF(curr_switch);
}
if (do_switch)
{
if (curr_mode == stm_16bit)
{
if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
goto done_err;
}
frame->AddrPC.Mode = AddrModeFlat;
frame->AddrPC.Segment = 0;
frame->AddrPC.Offset = frame32.retaddr;
frame->AddrFrame.Mode = AddrModeFlat;
frame->AddrFrame.Segment = 0;
frame->AddrFrame.Offset = frame32.ebp;
frame->AddrStack.Mode = AddrModeFlat;
frame->AddrStack.Segment = 0;
frame->AddrReturn.Mode = AddrModeFlat;
frame->AddrReturn.Segment = 0;
next_switch = curr_switch;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(csw, &tmp);
if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
curr_switch = (DWORD_PTR)frame16.frame32;
curr_mode = stm_32bit;
if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
curr_switch = 0;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(csw, &tmp);
if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
TRACE("Got a 16 bit stack switch:"
"\n\tframe32: %08lx"
"\n\tedx:%08x ecx:%08x ebp:%08x"
"\n\tds:%04x es:%04x fs:%04x gs:%04x"
"\n\tcall_from_ip:%08x module_cs:%04x relay=%08x"
"\n\tentry_ip:%04x entry_point:%08x"
"\n\tbp:%04x ip:%04x cs:%04x\n",
(unsigned long)frame16.frame32,
frame16.edx, frame16.ecx, frame16.ebp,
frame16.ds, frame16.es, frame16.fs, frame16.gs,
frame16.callfrom_ip, frame16.module_cs, frame16.relay,
frame16.entry_ip, frame16.entry_point,
frame16.bp, frame16.ip, frame16.cs);
frame->AddrPC.Mode = AddrMode1616;
frame->AddrPC.Segment = frame16.cs;
frame->AddrPC.Offset = frame16.ip;
frame->AddrFrame.Mode = AddrMode1616;
frame->AddrFrame.Segment = SELECTOROF(next_switch);
frame->AddrFrame.Offset = frame16.bp;
frame->AddrStack.Mode = AddrMode1616;
frame->AddrStack.Segment = SELECTOROF(next_switch);
frame->AddrReturn.Mode = AddrMode1616;
frame->AddrReturn.Segment = frame16.cs;
next_switch = curr_switch;
if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
goto done_err;
}
curr_switch = (DWORD)frame32.frame16;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(curr_switch);
tmp.Offset = OFFSETOF(curr_switch);
if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
curr_switch = 0;
curr_mode = stm_16bit;
}
}
else
{
frame->AddrPC = frame->AddrReturn;
if (curr_mode == stm_16bit)
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
/* "pop up" previous BP value */
if (!sw_read_mem(csw, sw_xlat_addr(csw, &frame->AddrFrame),
&val, sizeof(WORD)))
goto done_err;
frame->AddrFrame.Offset = val;
}
else
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
/* "pop up" previous EBP value */
if (!sw_read_mem(csw, frame->AddrFrame.Offset,
&frame->AddrFrame.Offset, sizeof(DWORD)))
goto done_err;
}
}
}
if (curr_mode == stm_16bit)
{
unsigned int i;
p = sw_xlat_addr(csw, &frame->AddrFrame);
if (!sw_read_mem(csw, p + sizeof(WORD), &val, sizeof(WORD)))
goto done_err;
frame->AddrReturn.Offset = val;
/* get potential cs if a far call was used */
if (!sw_read_mem(csw, p + 2 * sizeof(WORD), &val, sizeof(WORD)))
goto done_err;
if (frame->AddrFrame.Offset & 1)
frame->AddrReturn.Segment = val; /* far call assumed */
else
{
/* not explicitly marked as far call,
* but check whether it could be anyway
*/
if ((val & 7) == 7 && val != frame->AddrReturn.Segment)
{
LDT_ENTRY le;
if (GetThreadSelectorEntry(csw->hThread, val, &le) &&
(le.HighWord.Bits.Type & 0x08)) /* code segment */
{
/* it is very uncommon to push a code segment cs as
* a parameter, so this should work in most cases
*/
frame->AddrReturn.Segment = val;
}
}
}
frame->AddrFrame.Offset &= ~1;
/* we "pop" parameters as 16 bit entities... of course, this won't
* work if the parameter is in fact bigger than 16bit, but
* there's no way to know that here
*/
for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
{
sw_read_mem(csw, p + (2 + i) * sizeof(WORD), &val, sizeof(val));
frame->Params[i] = val;
}
}
else
{
if (!sw_read_mem(csw, frame->AddrFrame.Offset + sizeof(DWORD),
&frame->AddrReturn.Offset, sizeof(DWORD)))
{
WARN("Cannot read new frame offset %p\n",
(void*)(DWORD_PTR)(frame->AddrFrame.Offset + (int)sizeof(DWORD)));
goto done_err;
}
sw_read_mem(csw, frame->AddrFrame.Offset + 2 * sizeof(DWORD),
frame->Params, sizeof(frame->Params));
}
frame->Far = TRUE;
frame->Virtual = TRUE;
p = sw_xlat_addr(csw, &frame->AddrPC);
if (p && sw_module_base(csw, p))
frame->FuncTableEntry = sw_table_access(csw, p);
else
frame->FuncTableEntry = NULL;
TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%p nSwitch=%p FuncTable=%p\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
(void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch, frame->FuncTableEntry);
return TRUE;
done_err:
curr_mode = stm_done;
return FALSE;
}
struct cpu cpu_i386 = {
IMAGE_FILE_MACHINE_I386,
4,
i386_get_addr,
i386_stack_walk,
};

View file

@ -0,0 +1,62 @@
/*
* File cpu_ppc.c
*
* Copyright (C) 2009-2009, Eric Pouech.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
static unsigned ppc_get_addr(HANDLE hThread, const CONTEXT* ctx,
enum cpu_addr ca, ADDRESS64* addr)
{
switch (ca)
{
#if defined(__powerpc__)
case cpu_addr_pc:
addr->Mode = AddrModeFlat;
addr->Segment = 0; /* don't need segment */
addr->Offset = ctx->Iar;
return TRUE;
#endif
default:
case cpu_addr_stack:
case cpu_addr_frame:
FIXME("not done\n");
}
return FALSE;
}
static BOOL ppc_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
{
FIXME("not done\n");
return FALSE;
}
struct cpu cpu_ppc = {
IMAGE_FILE_MACHINE_POWERPC,
4,
ppc_get_addr,
ppc_stack_walk,
};

View file

@ -0,0 +1,132 @@
/*
* File cpu_x86_64.c
*
* Copyright (C) 2009-2009, Eric Pouech.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
static unsigned x86_64_get_addr(HANDLE hThread, const CONTEXT* ctx,
enum cpu_addr ca, ADDRESS64* addr)
{
addr->Mode = AddrModeFlat;
switch (ca)
{
#ifdef __x86_64__
case cpu_addr_pc: addr->Segment = ctx->SegCs; addr->Offset = ctx->Rip; return TRUE;
case cpu_addr_stack: addr->Segment = ctx->SegSs; addr->Offset = ctx->Rsp; return TRUE;
case cpu_addr_frame: addr->Segment = ctx->SegSs; addr->Offset = ctx->Rbp; return TRUE;
#endif
default: addr->Mode = -1;
return FALSE;
}
}
enum st_mode {stm_start, stm_64bit, stm_done};
/* indexes in Reserved array */
#define __CurrentMode 0
#define __CurrentSwitch 1
#define __NextSwitch 2
#define curr_mode (frame->Reserved[__CurrentMode])
#define curr_switch (frame->Reserved[__CurrentSwitch])
#define next_switch (frame->Reserved[__NextSwitch])
static BOOL x86_64_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
{
/* sanity check */
if (curr_mode >= stm_done) return FALSE;
assert(!csw->is32);
TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : "64bit");
if (curr_mode == stm_start)
{
if ((frame->AddrPC.Mode == AddrModeFlat) &&
(frame->AddrFrame.Mode != AddrModeFlat))
{
WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
goto done_err;
}
/* Init done */
curr_mode = stm_64bit;
curr_switch = 0;
frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrModeFlat;
/* don't set up AddrStack on first call. Either the caller has set it up, or
* we will get it in the next frame
*/
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
}
else
{
if (frame->AddrReturn.Offset == 0) goto done_err;
frame->AddrPC = frame->AddrReturn;
}
if (!sw_read_mem(csw, frame->AddrStack.Offset,
&frame->AddrReturn.Offset, sizeof(DWORD64)))
{
WARN("Cannot read new frame offset %s\n",
wine_dbgstr_longlong(frame->AddrFrame.Offset + sizeof(DWORD64)));
goto done_err;
}
/* FIXME: simplistic stuff... need to handle both dwarf & PE stack information */
frame->AddrStack.Offset += sizeof(DWORD64);
memset(&frame->Params, 0, sizeof(frame->Params));
frame->Far = TRUE;
frame->Virtual = TRUE;
if (frame->AddrPC.Offset && sw_module_base(csw, frame->AddrPC.Offset))
frame->FuncTableEntry = sw_table_access(csw, frame->AddrPC.Offset);
else
frame->FuncTableEntry = NULL;
TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s FuncTable=%p\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : "64bit",
frame->FuncTableEntry);
return TRUE;
done_err:
curr_mode = stm_done;
return FALSE;
}
struct cpu cpu_x86_64 = {
IMAGE_FILE_MACHINE_AMD64,
8,
x86_64_get_addr,
x86_64_stack_walk,
};

149
dll/win32/dbghelp/crc32.c Normal file
View file

@ -0,0 +1,149 @@
/*
* File crc32.c - calculate CRC32 checksum of a file
*
* Copyright (C) 1996, Eric Youngdale.
* 1999-2007 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdio.h>
#include "dbghelp_private.h"
/* Copyright (C) 1986 Gary S. Brown. Modified by Robert Shearman. You may use
the following calc_crc32 code or tables extracted from it, as desired without
restriction. */
/**********************************************************************\
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|* this polynomial is or will be included in CCITT V.41, which *|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|* errors by a factor of 10^-5 over 16-bit FCS. *|
\**********************************************************************/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* 1. The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
/* be they sixteen or thirty-two bits wide. You simply choose the */
/* appropriate table. Alternatively, because the table can be */
/* generated at runtime, you can start by generating the table for */
/* the polynomial in question and use exactly the same "updcrc", */
/* if your application needn't simultaneously handle two CRC */
/* polynomials. (Note, however, that XMODEM is strange.) */
/* */
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
/* */
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
DWORD calc_crc32(int fd)
{
#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
static const DWORD crc_32_tab[] =
{ /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
int i, r;
unsigned char buffer[8192];
DWORD crc = ~0;
_lseek(fd, 0, SEEK_SET);
while ((r = _read(fd, buffer, sizeof(buffer))) > 0)
{
for (i = 0; i < r; i++) crc = UPDC32(buffer[i], crc);
}
return ~crc;
#undef UPDC32
}

View file

@ -106,7 +106,7 @@ struct process* process_find_by_handle(HANDLE hProcess)
*/
BOOL validate_addr64(DWORD64 addr)
{
if (addr >> 32)
if (sizeof(void*) == sizeof(int) && (addr >> 32))
{
FIXME("Unsupported address %s\n", wine_dbgstr_longlong(addr));
SetLastError(ERROR_INVALID_PARAMETER);
@ -133,6 +133,48 @@ void* fetch_buffer(struct process* pcs, unsigned size)
return pcs->buffer;
}
const char* wine_dbgstr_addr(const ADDRESS64* addr)
{
if (!addr) return "(null)";
switch (addr->Mode)
{
case AddrModeFlat:
return wine_dbg_sprintf("flat<%s>", wine_dbgstr_longlong(addr->Offset));
case AddrMode1616:
return wine_dbg_sprintf("1616<%04x:%04x>", addr->Segment, (DWORD)addr->Offset);
case AddrMode1632:
return wine_dbg_sprintf("1632<%04x:%08x>", addr->Segment, (DWORD)addr->Offset);
case AddrModeReal:
return wine_dbg_sprintf("real<%04x:%04x>", addr->Segment, (DWORD)addr->Offset);
default:
return "unknown";
}
}
extern struct cpu cpu_i386, cpu_x86_64;
static struct cpu* dbghelp_cpus[] = {&cpu_i386, &cpu_x86_64, NULL};
struct cpu* dbghelp_current_cpu =
#if defined(__i386__)
&cpu_i386
#elif defined(__x86_64__)
&cpu_x86_64
#else
#error define support for your CPU
#endif
;
struct cpu* cpu_find(DWORD machine)
{
struct cpu** cpu;
for (cpu = dbghelp_cpus ; *cpu; cpu++)
{
if (cpu[0]->machine == machine) return cpu[0];
}
return NULL;
}
/******************************************************************
* SymSetSearchPathW (DBGHELP.@)
*
@ -211,16 +253,16 @@ BOOL WINAPI SymGetSearchPath(HANDLE hProcess, PSTR szSearchPath,
* SymInitialize helper: loads in dbghelp all known (and loaded modules)
* this assumes that hProcess is a handle on a valid process
*/
static BOOL WINAPI process_invade_cb(PCSTR name, ULONG base, ULONG size, PVOID user)
static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOID user)
{
char tmp[MAX_PATH];
WCHAR tmp[MAX_PATH];
HANDLE hProcess = user;
if (!GetModuleFileNameExA(hProcess, (HMODULE)base,
tmp, sizeof(tmp)))
lstrcpynA(tmp, name, sizeof(tmp));
if (!GetModuleFileNameExW(hProcess, (HMODULE)(DWORD_PTR)base,
tmp, sizeof(tmp) / sizeof(WCHAR)))
lstrcpynW(tmp, name, sizeof(tmp) / sizeof(WCHAR));
SymLoadModule(hProcess, 0, tmp, name, base, size);
SymLoadModuleExW(hProcess, 0, tmp, name, base, size, NULL, 0);
return TRUE;
}
@ -232,7 +274,8 @@ static BOOL check_live_target(struct process* pcs)
{
if (!GetProcessId(pcs->handle)) return FALSE;
if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) return FALSE;
elf_read_wine_loader_dbg_info(pcs);
if (!elf_read_wine_loader_dbg_info(pcs))
macho_read_wine_loader_dbg_info(pcs);
return TRUE;
}
@ -325,8 +368,9 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP
if (check_live_target(pcs))
{
if (fInvadeProcess)
EnumerateLoadedModules(hProcess, process_invade_cb, hProcess);
EnumerateLoadedModulesW64(hProcess, process_invade_cb, hProcess);
elf_synchronize_module_list(pcs);
macho_synchronize_module_list(pcs);
}
else if (fInvadeProcess)
{
@ -459,25 +503,25 @@ BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame,
*/
static BOOL CALLBACK reg_cb64to32(HANDLE hProcess, ULONG action, ULONG64 data, ULONG64 user)
{
PSYMBOL_REGISTERED_CALLBACK cb32 = (PSYMBOL_REGISTERED_CALLBACK)(DWORD)(user >> 32);
DWORD user32 = (DWORD)user;
struct process* pcs = process_find_by_handle(hProcess);
void* data32;
IMAGEHLP_DEFERRED_SYMBOL_LOAD64* idsl64;
IMAGEHLP_DEFERRED_SYMBOL_LOAD idsl;
if (!pcs) return FALSE;
switch (action)
{
case CBA_DEBUG_INFO:
case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
case CBA_SET_OPTIONS:
case CBA_SYMBOLS_UNLOADED:
data32 = (void*)(DWORD)data;
data32 = (void*)(DWORD_PTR)data;
break;
case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
case CBA_DEFERRED_SYMBOL_LOAD_PARTIAL:
case CBA_DEFERRED_SYMBOL_LOAD_START:
idsl64 = (IMAGEHLP_DEFERRED_SYMBOL_LOAD64*)(DWORD)data;
idsl64 = (IMAGEHLP_DEFERRED_SYMBOL_LOAD64*)(DWORD_PTR)data;
if (!validate_addr64(idsl64->BaseOfImage))
return FALSE;
idsl.SizeOfStruct = sizeof(idsl);
@ -495,7 +539,7 @@ static BOOL CALLBACK reg_cb64to32(HANDLE hProcess, ULONG action, ULONG64 data, U
FIXME("No mapping for action %u\n", action);
return FALSE;
}
return cb32(hProcess, action, data32, (PVOID)user32);
return pcs->reg_cb32(hProcess, action, data32, (PVOID)(DWORD_PTR)user);
}
/******************************************************************
@ -522,7 +566,7 @@ BOOL pcs_callback(const struct process* pcs, ULONG action, void* data)
case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
case CBA_DEFERRED_SYMBOL_LOAD_PARTIAL:
case CBA_DEFERRED_SYMBOL_LOAD_START:
idslW = (IMAGEHLP_DEFERRED_SYMBOL_LOADW64*)(DWORD)data;
idslW = data;
idsl.SizeOfStruct = sizeof(idsl);
idsl.BaseOfImage = idslW->BaseOfImage;
idsl.CheckSum = idslW->CheckSum;
@ -548,14 +592,16 @@ BOOL pcs_callback(const struct process* pcs, ULONG action, void* data)
*
* Helper for registering a callback.
*/
static BOOL sym_register_cb(HANDLE hProcess,
static BOOL sym_register_cb(HANDLE hProcess,
PSYMBOL_REGISTERED_CALLBACK64 cb,
PSYMBOL_REGISTERED_CALLBACK cb32,
DWORD64 user, BOOL unicode)
{
struct process* pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
pcs->reg_cb = cb;
pcs->reg_cb32 = cb32;
pcs->reg_is_unicode = unicode;
pcs->reg_user = user;
@ -569,10 +615,9 @@ BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
PVOID UserContext)
{
DWORD64 tmp = ((ULONGLONG)(DWORD)CallbackFunction << 32) | (DWORD)UserContext;
TRACE("(%p, %p, %p)\n",
hProcess, CallbackFunction, UserContext);
return sym_register_cb(hProcess, reg_cb64to32, tmp, FALSE);
return sym_register_cb(hProcess, reg_cb64to32, CallbackFunction, (DWORD_PTR)UserContext, FALSE);
}
/***********************************************************************
@ -584,7 +629,7 @@ BOOL WINAPI SymRegisterCallback64(HANDLE hProcess,
{
TRACE("(%p, %p, %s)\n",
hProcess, CallbackFunction, wine_dbgstr_longlong(UserContext));
return sym_register_cb(hProcess, CallbackFunction, UserContext, FALSE);
return sym_register_cb(hProcess, CallbackFunction, NULL, UserContext, FALSE);
}
/***********************************************************************
@ -596,7 +641,7 @@ BOOL WINAPI SymRegisterCallbackW64(HANDLE hProcess,
{
TRACE("(%p, %p, %s)\n",
hProcess, CallbackFunction, wine_dbgstr_longlong(UserContext));
return sym_register_cb(hProcess, CallbackFunction, UserContext, TRUE);
return sym_register_cb(hProcess, CallbackFunction, NULL, UserContext, TRUE);
}
/* This is imagehlp version not dbghelp !! */

View file

@ -9,10 +9,15 @@
<define name="_WINE" />
<define name="HAVE_REGEX_H" />
<file>coff.c</file>
<file>cpu_i386.c</file>
<file>cpu_ppc.c</file>
<file>cpu_x86_64.c</file>
<file>crc32.c</file>
<file>dbghelp.c</file>
<file>dwarf.c</file>
<file>elf_module.c</file>
<file>image.c</file>
<file>macho_module.c</file>
<file>memory.c</file>
<file>minidump.c</file>
<file>module.c</file>
@ -27,6 +32,7 @@
<file>storage.c</file>
<file>symbol.c</file>
<file>type.c</file>
<file>version.rc</file>
<library>wine</library>
<library>psapi</library>
<library>version</library>

View file

@ -29,6 +29,7 @@
#include "objbase.h"
#include "oaidl.h"
#include "winnls.h"
#include "wine/list.h"
#include "wine/unicode.h"
#include "cvconst.h"
@ -37,13 +38,14 @@
struct pool /* poor's man */
{
struct pool_arena* first;
unsigned arena_size;
struct list arena_list;
struct list arena_full;
size_t arena_size;
};
void pool_init(struct pool* a, unsigned arena_size);
void pool_init(struct pool* a, size_t arena_size);
void pool_destroy(struct pool* a);
void* pool_alloc(struct pool* a, unsigned len);
void* pool_alloc(struct pool* a, size_t len);
char* pool_strdup(struct pool* a, const char* str);
struct vector
@ -96,7 +98,6 @@ void hash_table_init(struct pool* pool, struct hash_table* ht,
unsigned num_buckets);
void hash_table_destroy(struct hash_table* ht);
void hash_table_add(struct hash_table* ht, struct hash_table_elt* elt);
unsigned hash_table_hash(const char* name, unsigned num_buckets);
struct hash_table_iter
{
@ -116,7 +117,7 @@ void* hash_table_iter_up(struct hash_table_iter* hti);
extern unsigned dbghelp_options;
/* some more Wine extensions */
#define SYMOPT_WINE_WITH_ELF_MODULES 0x40000000
#define SYMOPT_WINE_WITH_NATIVE_MODULES 0x40000000
enum location_kind {loc_error, /* reg is the error code */
loc_absolute, /* offset is the location */
@ -226,8 +227,6 @@ struct symt_public
struct symt* container; /* compiland */
unsigned long address;
unsigned long size;
unsigned in_code : 1,
is_function : 1;
};
struct symt_thunk
@ -245,7 +244,7 @@ struct symt_array
{
struct symt symt;
int start;
int end;
int end; /* end index if > 0, or -array_len (in bytes) if < 0 */
struct symt* base_type;
struct symt* index_type;
};
@ -308,6 +307,7 @@ enum module_type
DMT_UNKNOWN, /* for lookup, not actually used for a module */
DMT_ELF, /* a real ELF shared module */
DMT_PE, /* a native or builtin PE module */
DMT_MACHO, /* a real Mach-O shared module */
DMT_PDB, /* .PDB file */
DMT_DBG, /* .DBG file */
};
@ -327,12 +327,17 @@ struct module
struct elf_module_info* elf_info;
struct dwarf2_module_info_s*dwarf2_info;
struct macho_module_info* macho_info;
/* memory allocation pool */
struct pool pool;
/* symbols & symbol tables */
struct vector vsymt;
int sortlist_valid;
unsigned num_sorttab; /* number of symbols with addresses */
unsigned num_symbols;
unsigned sorttab_size;
struct symt_ht** addr_sorttab;
struct hash_table ht_symbols;
void (*loc_compute)(struct process* pcs,
@ -355,8 +360,9 @@ struct process
struct process* next;
HANDLE handle;
WCHAR* search_path;
PSYMBOL_REGISTERED_CALLBACK64 reg_cb;
PSYMBOL_REGISTERED_CALLBACK reg_cb32;
BOOL reg_is_unicode;
DWORD64 reg_user;
@ -411,17 +417,62 @@ struct pdb_lookup
} u;
};
struct cpu_stack_walk
{
HANDLE hProcess;
HANDLE hThread;
BOOL is32;
union
{
struct
{
PREAD_PROCESS_MEMORY_ROUTINE f_read_mem;
PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr;
PFUNCTION_TABLE_ACCESS_ROUTINE f_tabl_acs;
PGET_MODULE_BASE_ROUTINE f_modl_bas;
} s32;
struct
{
PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem;
PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr;
PFUNCTION_TABLE_ACCESS_ROUTINE64 f_tabl_acs;
PGET_MODULE_BASE_ROUTINE64 f_modl_bas;
} s64;
} u;
};
enum cpu_addr {cpu_addr_pc, cpu_addr_stack, cpu_addr_frame};
struct cpu
{
DWORD machine;
DWORD word_size;
/* address manipulation */
unsigned (*get_addr)(HANDLE hThread, const CONTEXT* ctx,
enum cpu_addr, ADDRESS64* addr);
/* stack manipulation */
BOOL (*stack_walk)(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame);
};
extern struct cpu* dbghelp_current_cpu;
/* dbghelp.c */
extern struct process* process_find_by_handle(HANDLE hProcess);
extern HANDLE hMsvcrt;
extern BOOL validate_addr64(DWORD64 addr);
extern BOOL pcs_callback(const struct process* pcs, ULONG action, void* data);
extern void* fetch_buffer(struct process* pcs, unsigned size);
extern const char* wine_dbgstr_addr(const ADDRESS64* addr);
extern struct cpu* cpu_find(DWORD);
/* crc32.c */
extern DWORD calc_crc32(int fd);
typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
/* elf_module.c */
#define ELF_NO_MAP ((const void*)0xffffffff)
typedef BOOL (*elf_enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
extern BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb, void*);
#define ELF_NO_MAP ((const void*)-1)
extern BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb, void*);
extern BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum);
struct elf_file_map;
extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap);
@ -431,21 +482,27 @@ extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs);
extern BOOL elf_synchronize_module_list(struct process* pcs);
struct elf_thunk_area;
extern int elf_is_in_thunk_area(unsigned long addr, const struct elf_thunk_area* thunks);
extern DWORD WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS* addr);
/* macho_module.c */
#define MACHO_NO_MAP ((const void*)-1)
extern BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb, void*);
extern BOOL macho_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum);
struct macho_file_map;
extern BOOL macho_load_debug_info(struct module* module, struct macho_file_map* fmap);
extern struct module*
macho_load_module(struct process* pcs, const WCHAR* name, unsigned long);
extern BOOL macho_read_wine_loader_dbg_info(struct process* pcs);
extern BOOL macho_synchronize_module_list(struct process* pcs);
/* module.c */
extern const WCHAR S_ElfW[];
extern const WCHAR S_WineLoaderW[];
extern const WCHAR S_WinePThreadW[];
extern const WCHAR S_WineKThreadW[];
extern const WCHAR S_WineW[];
extern const WCHAR S_SlashW[];
extern struct module*
module_find_by_addr(const struct process* pcs, unsigned long addr,
enum module_type type);
extern struct module*
module_find_by_name(const struct process* pcs,
const WCHAR* name);
extern struct module*
module_find_by_nameA(const struct process* pcs,
const char* name);
@ -456,11 +513,8 @@ extern BOOL module_get_debug(struct module_pair*);
extern struct module*
module_new(struct process* pcs, const WCHAR* name,
enum module_type type, BOOL virtual,
unsigned long addr, unsigned long size,
DWORD64 addr, DWORD64 size,
unsigned long stamp, unsigned long checksum);
extern struct module*
module_get_container(const struct process* pcs,
const struct module* inner);
extern struct module*
module_get_containee(const struct process* pcs,
const struct module* inner);
@ -485,13 +539,13 @@ extern BOOL path_find_symbol_file(const struct process* pcs, PCSTR full_
BOOL* is_unmatched);
/* pe_module.c */
extern BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth);
extern BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth);
extern struct module*
pe_load_native_module(struct process* pcs, const WCHAR* name,
HANDLE hFile, DWORD base, DWORD size);
extern struct module*
pe_load_builtin_module(struct process* pcs, const WCHAR* name,
DWORD base, DWORD size);
DWORD64 base, DWORD64 size);
extern BOOL pe_load_debug_info(const struct process* pcs,
struct module* module);
/* source.c */
@ -499,9 +553,14 @@ extern unsigned source_new(struct module* module, const char* basedir, const
extern const char* source_get(const struct module* module, unsigned idx);
/* stabs.c */
typedef void (*stabs_def_cb)(struct module* module, unsigned long load_offset,
const char* name, unsigned long offset,
BOOL is_public, BOOL is_global, unsigned char other,
struct symt_compiland* compiland, void* user);
extern BOOL stabs_parse(struct module* module, unsigned long load_offset,
const void* stabs, int stablen,
const char* strs, int strtablen);
const char* strs, int strtablen,
stabs_def_cb callback, void* user);
/* dwarf.c */
extern BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
@ -512,12 +571,19 @@ extern BOOL dwarf2_parse(struct module* module, unsigned long load_offse
const unsigned char* line, unsigned int line_size,
const unsigned char* loclist, unsigned int loclist_size);
/* stack.c */
extern BOOL sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz);
extern DWORD64 sw_xlat_addr(struct cpu_stack_walk* csw, ADDRESS64* addr);
extern void* sw_table_access(struct cpu_stack_walk* csw, DWORD64 addr);
extern DWORD64 sw_module_base(struct cpu_stack_walk* csw, DWORD64 addr);
/* symbol.c */
extern const char* symt_get_name(const struct symt* sym);
extern struct module* symt_cmp_addr_module;
extern int symt_cmp_addr(const void* p1, const void* p2);
extern void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si);
extern struct symt_ht*
symt_find_nearest(struct module* module, DWORD addr);
symt_find_nearest(struct module* module, DWORD_PTR addr);
extern struct symt_compiland*
symt_new_compiland(struct module* module, unsigned long address,
unsigned src_idx);
@ -525,8 +591,7 @@ extern struct symt_public*
symt_new_public(struct module* module,
struct symt_compiland* parent,
const char* typename,
unsigned long address, unsigned size,
BOOL in_code, BOOL is_func);
unsigned long address, unsigned size);
extern struct symt_data*
symt_new_global_variable(struct module* module,
struct symt_compiland* parent,
@ -540,7 +605,7 @@ extern struct symt_function*
unsigned long addr, unsigned long size,
struct symt* type);
extern BOOL symt_normalize_function(struct module* module,
struct symt_function* func);
const struct symt_function* func);
extern void symt_add_func_line(struct module* module,
struct symt_function* func,
unsigned source_idx, int line_num,
@ -558,7 +623,7 @@ extern struct symt_block*
unsigned pc, unsigned len);
extern struct symt_block*
symt_close_func_block(struct module* module,
struct symt_function* func,
const struct symt_function* func,
struct symt_block* block, unsigned pc);
extern struct symt_hierarchy_point*
symt_add_function_point(struct module* module,
@ -568,8 +633,8 @@ extern struct symt_hierarchy_point*
const char* name);
extern BOOL symt_fill_func_line_info(const struct module* module,
const struct symt_function* func,
DWORD addr, IMAGEHLP_LINE* line);
extern BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE line);
DWORD64 addr, IMAGEHLP_LINE64* line);
extern BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line);
extern struct symt_thunk*
symt_new_thunk(struct module* module,
struct symt_compiland* parent,
@ -584,10 +649,12 @@ extern struct symt_hierarchy_point*
symt_new_label(struct module* module,
struct symt_compiland* compiland,
const char* name, unsigned long address);
extern struct symt* symt_index2ptr(struct module* module, DWORD id);
extern DWORD symt_ptr2index(struct module* module, const struct symt* sym);
/* type.c */
extern void symt_init_basic(struct module* module);
extern BOOL symt_get_info(const struct symt* type,
extern BOOL symt_get_info(struct module* module, const struct symt* type,
IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo);
extern struct symt_basic*
symt_new_basic(struct module* module, enum BasicType,

View file

@ -72,7 +72,7 @@ static void dump(const void* ptr, unsigned len)
int i, j;
BYTE msg[128];
static const char hexof[] = "0123456789abcdef";
const BYTE* x = (const BYTE*)ptr;
const BYTE* x = ptr;
for (i = 0; i < len; i += 16)
{
@ -217,7 +217,7 @@ static unsigned char dwarf2_parse_byte(dwarf2_traverse_context_t* ctx)
static unsigned short dwarf2_get_u2(const unsigned char* ptr)
{
return *(const unsigned short*)ptr;
return *(const UINT16*)ptr;
}
static unsigned short dwarf2_parse_u2(dwarf2_traverse_context_t* ctx)
@ -229,7 +229,7 @@ static unsigned short dwarf2_parse_u2(dwarf2_traverse_context_t* ctx)
static unsigned long dwarf2_get_u4(const unsigned char* ptr)
{
return *(const unsigned long*)ptr;
return *(const UINT32*)ptr;
}
static unsigned long dwarf2_parse_u4(dwarf2_traverse_context_t* ctx)
@ -239,6 +239,18 @@ static unsigned long dwarf2_parse_u4(dwarf2_traverse_context_t* ctx)
return uvalue;
}
static DWORD64 dwarf2_get_u8(const unsigned char* ptr)
{
return *(const UINT64*)ptr;
}
static DWORD64 dwarf2_parse_u8(dwarf2_traverse_context_t* ctx)
{
DWORD64 uvalue = dwarf2_get_u8(ctx->data);
ctx->data += 8;
return uvalue;
}
static unsigned long dwarf2_get_leb128_as_unsigned(const unsigned char* ptr, const unsigned char** end)
{
unsigned long ret = 0;
@ -309,6 +321,13 @@ static unsigned dwarf2_leb128_length(const dwarf2_traverse_context_t* ctx)
return ret + 1;
}
/******************************************************************
* dwarf2_get_addr
*
* Returns an address.
* We assume that in all cases word size from Dwarf matches the size of
* addresses in platform where the exec is compiled.
*/
static unsigned long dwarf2_get_addr(const unsigned char* ptr, unsigned word_size)
{
unsigned long ret;
@ -318,6 +337,9 @@ static unsigned long dwarf2_get_addr(const unsigned char* ptr, unsigned word_siz
case 4:
ret = dwarf2_get_u4(ptr);
break;
case 8:
ret = dwarf2_get_u8(ptr);
break;
default:
FIXME("Unsupported Word Size %u\n", word_size);
ret = 0;
@ -490,7 +512,9 @@ static void dwarf2_fill_attr(const dwarf2_parse_context_t* ctx,
break;
case DW_FORM_data8:
FIXME("Unhandled 64bits support\n");
attr->u.block.size = 8;
attr->u.block.ptr = data;
data += 8;
break;
case DW_FORM_ref1:
@ -652,7 +676,7 @@ static enum location_error
compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
HANDLE hproc, const struct location* frame)
{
unsigned long stack[64];
DWORD_PTR tmp, stack[64];
unsigned stk;
unsigned char op;
BOOL piece_found = FALSE;
@ -665,27 +689,11 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
while (ctx->data < ctx->end_data)
{
op = dwarf2_parse_byte(ctx);
switch (op)
if (op >= DW_OP_lit0 && op <= DW_OP_lit31)
stack[++stk] = op - DW_OP_lit0;
else if (op >= DW_OP_reg0 && op <= DW_OP_reg31)
{
case DW_OP_addr: stack[++stk] = dwarf2_parse_addr(ctx); break;
case DW_OP_const1u: stack[++stk] = dwarf2_parse_byte(ctx); break;
case DW_OP_const1s: stack[++stk] = (long)(signed char)dwarf2_parse_byte(ctx); break;
case DW_OP_const2u: stack[++stk] = dwarf2_parse_u2(ctx); break;
case DW_OP_const2s: stack[++stk] = (long)(short)dwarf2_parse_u2(ctx); break;
case DW_OP_const4u: stack[++stk] = dwarf2_parse_u4(ctx); break;
case DW_OP_const4s: stack[++stk] = dwarf2_parse_u4(ctx); break;
case DW_OP_constu: stack[++stk] = dwarf2_leb128_as_unsigned(ctx); break;
case DW_OP_consts: stack[++stk] = dwarf2_leb128_as_signed(ctx); break;
case DW_OP_plus_uconst:
stack[stk] += dwarf2_leb128_as_unsigned(ctx); break;
case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3:
case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7:
case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11:
case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15:
case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19:
case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23:
case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27:
case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31:
/* dbghelp APIs don't know how to cope with this anyway
* (for example 'long long' stored in two registers)
* FIXME: We should tell winedbg how to deal with it (sigh)
@ -698,15 +706,9 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
loc->reg = dwarf2_map_register(op - DW_OP_reg0);
}
loc->kind = loc_register;
break;
case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3:
case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7:
case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11:
case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15:
case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19:
case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23:
case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27:
case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31:
}
else if (op >= DW_OP_breg0 && op <= DW_OP_breg31)
{
/* dbghelp APIs don't know how to cope with this anyway
* (for example 'long long' stored in two registers)
* FIXME: We should tell winedbg how to deal with it (sigh)
@ -714,13 +716,71 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
if (!piece_found)
{
if (loc->reg != Wine_DW_no_register)
FIXME("Only supporting one reg (%d -> %d)\n",
FIXME("Only supporting one breg (%d -> %d)\n",
loc->reg, dwarf2_map_register(op - DW_OP_breg0));
loc->reg = dwarf2_map_register(op - DW_OP_breg0);
}
stack[++stk] = dwarf2_leb128_as_signed(ctx);
loc->kind = loc_regrel;
break;
}
else switch (op)
{
case DW_OP_nop: break;
case DW_OP_addr: stack[++stk] = dwarf2_parse_addr(ctx); break;
case DW_OP_const1u: stack[++stk] = dwarf2_parse_byte(ctx); break;
case DW_OP_const1s: stack[++stk] = dwarf2_parse_byte(ctx); break;
case DW_OP_const2u: stack[++stk] = dwarf2_parse_u2(ctx); break;
case DW_OP_const2s: stack[++stk] = dwarf2_parse_u2(ctx); break;
case DW_OP_const4u: stack[++stk] = dwarf2_parse_u4(ctx); break;
case DW_OP_const4s: stack[++stk] = dwarf2_parse_u4(ctx); break;
case DW_OP_const8u: stack[++stk] = dwarf2_parse_u8(ctx); break;
case DW_OP_const8s: stack[++stk] = dwarf2_parse_u8(ctx); break;
case DW_OP_constu: stack[++stk] = dwarf2_leb128_as_unsigned(ctx); break;
case DW_OP_consts: stack[++stk] = dwarf2_leb128_as_signed(ctx); break;
case DW_OP_dup: stack[stk + 1] = stack[stk]; stk++; break;
case DW_OP_drop: stk--; break;
case DW_OP_over: stack[stk + 1] = stack[stk - 1]; stk++; break;
case DW_OP_pick: stack[stk + 1] = stack[stk - dwarf2_parse_byte(ctx)]; stk++; break;
case DW_OP_swap: tmp = stack[stk]; stack[stk] = stack[stk-1]; stack[stk-1] = tmp; break;
case DW_OP_rot: tmp = stack[stk]; stack[stk] = stack[stk-1]; stack[stk-1] = stack[stk-2]; stack[stk-2] = tmp; break;
case DW_OP_abs: stack[stk] = labs(stack[stk]); break;
case DW_OP_neg: stack[stk] = -stack[stk]; break;
case DW_OP_not: stack[stk] = ~stack[stk]; break;
case DW_OP_and: stack[stk-1] &= stack[stk]; stk--; break;
case DW_OP_or: stack[stk-1] |= stack[stk]; stk--; break;
case DW_OP_minus: stack[stk-1] -= stack[stk]; stk--; break;
case DW_OP_mul: stack[stk-1] *= stack[stk]; stk--; break;
case DW_OP_plus: stack[stk-1] += stack[stk]; stk--; break;
case DW_OP_xor: stack[stk-1] ^= stack[stk]; stk--; break;
case DW_OP_shl: stack[stk-1] <<= stack[stk]; stk--; break;
case DW_OP_shr: stack[stk-1] >>= stack[stk]; stk--; break;
case DW_OP_plus_uconst: stack[stk] += dwarf2_leb128_as_unsigned(ctx); break;
case DW_OP_shra: stack[stk-1] = stack[stk-1] / (1 << stack[stk]); stk--; break;
case DW_OP_div: stack[stk-1] = stack[stk-1] / stack[stk]; stk--; break;
case DW_OP_mod: stack[stk-1] = stack[stk-1] % stack[stk]; stk--; break;
case DW_OP_ge: stack[stk-1] = (stack[stk-1] >= stack[stk]); stk--; break;
case DW_OP_gt: stack[stk-1] = (stack[stk-1] > stack[stk]); stk--; break;
case DW_OP_le: stack[stk-1] = (stack[stk-1] <= stack[stk]); stk--; break;
case DW_OP_lt: stack[stk-1] = (stack[stk-1] < stack[stk]); stk--; break;
case DW_OP_eq: stack[stk-1] = (stack[stk-1] == stack[stk]); stk--; break;
case DW_OP_ne: stack[stk-1] = (stack[stk-1] != stack[stk]); stk--; break;
case DW_OP_skip: tmp = dwarf2_parse_u2(ctx); ctx->data += tmp; break;
case DW_OP_bra: tmp = dwarf2_parse_u2(ctx); if (!stack[stk--]) ctx->data += tmp; break;
case DW_OP_regx:
if (loc->reg != Wine_DW_no_register)
FIXME("Only supporting one regx\n");
loc->reg = dwarf2_map_register(dwarf2_leb128_as_unsigned(ctx));
loc->kind = loc_register;
break;
case DW_OP_bregx:
tmp = dwarf2_leb128_as_unsigned(ctx);
ctx->data++;
if (loc->reg != Wine_DW_no_register)
FIXME("Only supporting one regx\n");
loc->reg = dwarf2_map_register(tmp) + dwarf2_leb128_as_signed(ctx);
loc->kind = loc_register;
break;
case DW_OP_fbreg:
if (loc->reg != Wine_DW_no_register)
FIXME("Only supporting one reg (%d -> -2)\n", loc->reg);
@ -765,12 +825,12 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
}
if (hproc)
{
DWORD addr = stack[stk--];
DWORD deref;
DWORD_PTR addr = stack[stk--];
DWORD_PTR deref;
if (!ReadProcessMemory(hproc, (void*)addr, &deref, sizeof(deref), NULL))
{
WARN("Couldn't read memory at %x\n", addr);
WARN("Couldn't read memory at %lx\n", addr);
return loc_err_cant_read;
}
stack[++stk] = deref;
@ -780,8 +840,46 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
loc->kind = loc_dwarf2_block;
}
break;
case DW_OP_deref_size:
if (!stk)
{
FIXME("Unexpected empty stack\n");
return loc_err_internal;
}
if (loc->reg != Wine_DW_no_register)
{
WARN("Too complex expression for deref\n");
return loc_err_too_complex;
}
if (hproc)
{
DWORD_PTR addr = stack[stk--];
BYTE derefsize = dwarf2_parse_byte(ctx);
DWORD64 deref;
if (!ReadProcessMemory(hproc, (void*)addr, &deref, derefsize, NULL))
{
WARN("Couldn't read memory at %lx\n", addr);
return loc_err_cant_read;
}
switch (derefsize)
{
case 1: stack[++stk] = *(unsigned char*)&deref; break;
case 2: stack[++stk] = *(unsigned short*)&deref; break;
case 4: stack[++stk] = *(DWORD*)&deref; break;
case 8: if (ctx->word_size >= derefsize) stack[++stk] = deref; break;
}
}
else
{
loc->kind = loc_dwarf2_block;
}
break;
default:
FIXME("Unhandled attr op: %x\n", op);
if (op < DW_OP_lo_user) /* as DW_OP_hi_user is 0xFF, we don't need to test against it */
FIXME("Unhandled attr op: %x\n", op);
/* FIXME else unhandled extension */
return loc_err_internal;
}
}
@ -1163,7 +1261,8 @@ static void dwarf2_parse_udt_member(dwarf2_parse_context_t* ctx,
if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &nbytes))
{
DWORD64 size;
nbytes.u.uvalue = symt_get_info(elt_type, TI_GET_LENGTH, &size) ? (unsigned long)size : 0;
nbytes.u.uvalue = symt_get_info(ctx->module, elt_type, TI_GET_LENGTH, &size) ?
(unsigned long)size : 0;
}
bit_offset.u.uvalue = nbytes.u.uvalue * 8 - bit_offset.u.uvalue - bit_size.u.uvalue;
}
@ -1214,6 +1313,10 @@ static struct symt* dwarf2_parse_udt_type(dwarf2_parse_context_t* ctx,
case DW_TAG_union_type:
case DW_TAG_typedef:
/* FIXME: we need to handle nested udt definitions */
case DW_TAG_inheritance:
case DW_TAG_subprogram:
case DW_TAG_variable:
/* FIXME: some C++ related stuff */
break;
default:
FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
@ -1334,6 +1437,8 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
switch (loc.kind)
{
case loc_error:
break;
case loc_absolute:
/* it's a global variable */
/* FIXME: we don't handle its scope yet */
@ -1389,11 +1494,28 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
v.n1.n2.n3.byref = pool_strdup(&subpgm->ctx->module->pool, value.u.string);
break;
case DW_FORM_data8:
case DW_FORM_block:
case DW_FORM_block1:
case DW_FORM_block2:
case DW_FORM_block4:
v.n1.n2.vt = VT_I4;
switch (value.u.block.size)
{
case 1: v.n1.n2.n3.lVal = *(BYTE*)value.u.block.ptr; break;
case 2: v.n1.n2.n3.lVal = *(USHORT*)value.u.block.ptr; break;
case 4: v.n1.n2.n3.lVal = *(DWORD*)value.u.block.ptr; break;
default:
v.n1.n2.vt = VT_I1 | VT_BYREF;
v.n1.n2.n3.byref = pool_alloc(&subpgm->ctx->module->pool, value.u.block.size);
memcpy(v.n1.n2.n3.byref, value.u.block.ptr, value.u.block.size);
}
break;
case DW_FORM_data8:
v.n1.n2.vt = VT_I1 | VT_BYREF;
v.n1.n2.n3.byref = pool_alloc(&subpgm->ctx->module->pool, value.u.block.size);
memcpy(v.n1.n2.n3.byref, value.u.block.ptr, value.u.block.size);
break;
default:
FIXME("Unsupported form for const value %s (%lx)\n",
@ -1786,6 +1908,11 @@ static void dwarf2_load_one_entry(dwarf2_parse_context_t* ctx,
dwarf2_parse_variable(&subpgm, NULL, di);
}
break;
/* silence a couple of C++ defines */
case DW_TAG_namespace:
case DW_TAG_imported_module:
case DW_TAG_imported_declaration:
break;
default:
FIXME("Unhandled Tag type 0x%lx at %s, for %lu\n",
di->abbrev->tag, dwarf2_debug_ctx(ctx), di->abbrev->entry_code);
@ -2010,7 +2137,7 @@ static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections,
cu_ctx.word_size = dwarf2_parse_byte(&cu_ctx);
TRACE("Compilation Unit Header found at 0x%x:\n",
comp_unit_start - sections[section_debug].address);
(int)(comp_unit_start - sections[section_debug].address));
TRACE("- length: %lu\n", cu_length);
TRACE("- version: %u\n", cu_version);
TRACE("- abbrev_offset: %lu\n", cu_abbrev_offset);

View file

@ -376,6 +376,18 @@ typedef enum dwarf_operation_e
DW_OP_call2 = 0x98,
DW_OP_call4 = 0x99,
DW_OP_call_ref = 0x9a,
DW_OP_form_tls_address = 0x9b,
DW_OP_call_frame_cfa = 0x9c,
DW_OP_bit_piece = 0x9d,
/* Implementation defined extensions */
DW_OP_lo_user = 0xe0,
DW_OP_hi_user = 0xff,
/* GNU extensions */
DW_OP_GNU_push_tls_address = 0xe0,
DW_OP_GNU_uninit = 0xf0,
DW_OP_GNU_encoded_addr = 0xf1,
} dwarf_operation_t;
enum dwarf_calling_convention

View file

@ -77,7 +77,7 @@
struct elf_module_info
{
unsigned long elf_addr;
DWORD_PTR elf_addr;
unsigned short elf_mark : 1,
elf_loader : 1;
};
@ -93,22 +93,36 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
struct elf_info
{
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
unsigned long dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
DWORD_PTR dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
const WCHAR* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */
};
#ifdef _WIN64
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Shdr Elf64_Shdr
#define Elf_Phdr Elf64_Phdr
#define Elf_Dyn Elf64_Dyn
#define Elf_Sym Elf64_Sym
#else
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Dyn Elf32_Dyn
#define Elf_Sym Elf32_Sym
#endif
/* structure holding information while handling an ELF image
* allows one by one section mapping for memory savings
*/
struct elf_file_map
{
Elf32_Ehdr elfhdr;
Elf_Ehdr elfhdr;
size_t elf_size;
size_t elf_start;
struct
{
Elf32_Shdr shdr;
Elf_Shdr shdr;
const char* mapped;
}* sect;
int fd;
@ -125,7 +139,7 @@ struct elf_section_map
struct symtab_elt
{
struct hash_table_elt ht_elt;
const Elf32_Sym* symp;
const Elf_Sym* symp;
struct symt_compiland* compiland;
unsigned used;
};
@ -237,7 +251,7 @@ static void elf_end_find(struct elf_file_map* fmap)
*
* Get the size of an ELF section
*/
static inline unsigned elf_get_map_size(struct elf_section_map* esm)
static inline unsigned elf_get_map_size(const struct elf_section_map* esm)
{
if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum)
return 0;
@ -254,7 +268,7 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap)
static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
struct stat statbuf;
int i;
Elf32_Phdr phdr;
Elf_Phdr phdr;
unsigned tmp, page_mask = getpagesize() - 1;
char* filename;
unsigned len;
@ -279,7 +293,12 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap)
/* and check for an ELF header */
if (memcmp(fmap->elfhdr.e_ident,
elf_signature, sizeof(elf_signature))) goto done;
/* and check 32 vs 64 size according to current machine */
#ifdef _WIN64
if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS64) goto done;
#else
if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done;
#endif
fmap->sect = HeapAlloc(GetProcessHeap(), 0,
fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
if (!fmap->sect) goto done;
@ -350,7 +369,7 @@ int elf_is_in_thunk_area(unsigned long addr,
{
unsigned i;
for (i = 0; thunks[i].symname; i++)
if (thunks) for (i = 0; thunks[i].symname; i++)
{
if (addr >= thunks[i].rva_start && addr < thunks[i].rva_end)
return i;
@ -372,13 +391,13 @@ static void elf_hash_symtab(struct module* module, struct pool* pool,
const char* symname;
struct symt_compiland* compiland = NULL;
const char* ptr;
const Elf32_Sym* symp;
const Elf_Sym* symp;
struct symtab_elt* ste;
struct elf_section_map esm, esm_str;
if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) &&
!elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return;
if ((symp = (const Elf32_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return;
if ((symp = (const Elf_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return;
esm_str.fmap = fmap;
esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link;
if ((strp = elf_map_section(&esm_str)) == ELF_NO_MAP) return;
@ -471,9 +490,9 @@ static void elf_hash_symtab(struct module* module, struct pool* pool,
*
* lookup a symbol by name in our internal hash table for the symtab
*/
static const Elf32_Sym* elf_lookup_symtab(const struct module* module,
static const Elf_Sym* elf_lookup_symtab(const struct module* module,
const struct hash_table* ht_symtab,
const char* name, struct symt* compiland)
const char* name, const struct symt* compiland)
{
struct symtab_elt* weak_result = NULL; /* without compiland name */
struct symtab_elt* result = NULL;
@ -490,7 +509,7 @@ static const Elf32_Sym* elf_lookup_symtab(const struct module* module,
if (compiland)
{
compiland_name = source_get(module,
((struct symt_compiland*)compiland)->source);
((const struct symt_compiland*)compiland)->source);
compiland_basename = strrchr(compiland_name, '/');
if (!compiland_basename++) compiland_basename = compiland_name;
}
@ -542,12 +561,12 @@ static const Elf32_Sym* elf_lookup_symtab(const struct module* module,
* - get any relevant information (address & size) from the bits we got from the
* stabs debugging information
*/
static void elf_finish_stabs_info(struct module* module, struct hash_table* symtab)
static void elf_finish_stabs_info(struct module* module, const struct hash_table* symtab)
{
struct hash_table_iter hti;
void* ptr;
struct symt_ht* sym;
const Elf32_Sym* symp;
const Elf_Sym* symp;
hash_table_iter_init(&module->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti)))
@ -623,13 +642,13 @@ static void elf_finish_stabs_info(struct module* module, struct hash_table* symt
*
* creating the thunk objects for a wine native DLL
*/
static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symtab,
static int elf_new_wine_thunks(struct module* module, const struct hash_table* ht_symtab,
const struct elf_thunk_area* thunks)
{
int j;
struct hash_table_iter hti;
struct symtab_elt* ste;
DWORD addr;
DWORD_PTR addr;
struct symt_ht* symt;
hash_table_iter_init(ht_symtab, &hti, NULL);
@ -650,8 +669,8 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
ULONG64 ref_addr;
symt = symt_find_nearest(module, addr);
if (symt)
symt_get_info(&symt->symt, TI_GET_ADDRESS, &ref_addr);
if (symt && !symt_get_info(module, &symt->symt, TI_GET_ADDRESS, &ref_addr))
ref_addr = addr;
if (!symt || addr != ref_addr)
{
/* creating public symbols for all the ELF symbols which haven't been
@ -687,9 +706,9 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
ULONG64 xaddr = 0, xsize = 0;
DWORD kind = -1;
symt_get_info(&symt->symt, TI_GET_ADDRESS, &xaddr);
symt_get_info(&symt->symt, TI_GET_LENGTH, &xsize);
symt_get_info(&symt->symt, TI_GET_DATAKIND, &kind);
symt_get_info(module, &symt->symt, TI_GET_ADDRESS, &xaddr);
symt_get_info(module, &symt->symt, TI_GET_LENGTH, &xsize);
symt_get_info(module, &symt->symt, TI_GET_DATAKIND, &kind);
/* If none of symbols has a correct size, we consider they are both markers
* Hence, we can silence this warning
@ -698,7 +717,7 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
*/
if ((xsize || ste->symp->st_size) &&
(kind == (ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL) ? DataIsFileStatic : DataIsGlobal))
FIXME("Duplicate in %s: %s<%08x-%08x> %s<%s-%s>\n",
FIXME("Duplicate in %s: %s<%08lx-%08x> %s<%s-%s>\n",
debugstr_w(module->module.ModuleName),
ste->ht_elt.name, addr, (unsigned int)ste->symp->st_size,
symt->hash_elt.name,
@ -716,7 +735,7 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
*
* Creates a set of public symbols from an ELF symtab
*/
static int elf_new_public_symbols(struct module* module, struct hash_table* symtab)
static int elf_new_public_symbols(struct module* module, const struct hash_table* symtab)
{
struct hash_table_iter hti;
struct symtab_elt* ste;
@ -730,142 +749,19 @@ static int elf_new_public_symbols(struct module* module, struct hash_table* symt
{
symt_new_public(module, ste->compiland, ste->ht_elt.name,
module->elf_info->elf_addr + ste->symp->st_value,
ste->symp->st_size, TRUE /* FIXME */,
ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC);
ste->symp->st_size);
}
return TRUE;
}
/* Copyright (C) 1986 Gary S. Brown. Modified by Robert Shearman. You may use
the following calc_crc32 code or tables extracted from it, as desired without
restriction. */
/**********************************************************************\
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|* this polynomial is or will be included in CCITT V.41, which *|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|* errors by a factor of 10^-5 over 16-bit FCS. *|
\**********************************************************************/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* 1. The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
/* be they sixteen or thirty-two bits wide. You simply choose the */
/* appropriate table. Alternatively, because the table can be */
/* generated at runtime, you can start by generating the table for */
/* the polynomial in question and use exactly the same "updcrc", */
/* if your application needn't simultaneously handle two CRC */
/* polynomials. (Note, however, that XMODEM is strange.) */
/* */
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
/* */
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
static DWORD calc_crc32(struct elf_file_map* fmap)
{
#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
static const DWORD crc_32_tab[] =
{ /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
int i, r;
unsigned char buffer[256];
DWORD crc = ~0;
lseek(fmap->fd, 0, SEEK_SET);
while ((r = read(fmap->fd, buffer, sizeof(buffer))) > 0)
{
for (i = 0; i < r; i++) crc = UPDC32(buffer[i], crc);
}
return ~crc;
#undef UPDC32
}
static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, DWORD crc)
{
BOOL ret;
if (!elf_map_file(file, fmap)) return FALSE;
if (!(ret = crc == calc_crc32(fmap)))
if (!(ret = crc == calc_crc32(fmap->fd)))
{
WARN("Bad CRC for file %s (got %08x while expecting %08x)\n",
debugstr_w(file), calc_crc32(fmap), crc);
debugstr_w(file), calc_crc32(fmap->fd), crc);
elf_unmap_file(fmap);
}
return ret;
@ -952,7 +848,7 @@ found:
* Parses a .gnu_debuglink section and loads the debug info from
* the external file specified there.
*/
static BOOL elf_debuglink_parse(struct elf_file_map* fmap, struct module* module,
static BOOL elf_debuglink_parse(struct elf_file_map* fmap, const struct module* module,
const BYTE* debuglink)
{
/* The content of a debug link section is:
@ -1039,7 +935,8 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
/* OK, now just parse all of the stabs. */
lret = stabs_parse(module, module->elf_info->elf_addr,
stab, elf_get_map_size(&stab_sect),
stabstr, elf_get_map_size(&stabstr_sect));
stabstr, elf_get_map_size(&stabstr_sect),
NULL, NULL);
if (lret)
/* and fill in the missing information for stabs */
elf_finish_stabs_info(module, ht_symtab);
@ -1160,7 +1057,7 @@ BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base,
if (!elf_map_file(name, &fmap)) return FALSE;
if (base) *base = fmap.elf_start;
*size = fmap.elf_size;
*checksum = calc_crc32(&fmap);
*checksum = calc_crc32(fmap.fd);
elf_unmap_file(&fmap);
return TRUE;
}
@ -1184,7 +1081,7 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
if (!elf_map_file(filename, &fmap)) goto leave;
if (!elf_map_file(filename, &fmap)) return ret;
/* Next, we need to find a few of the internal ELF headers within
* this thing. We need the main executable header, and the section
@ -1206,7 +1103,7 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &esm))
{
Elf32_Dyn dyn;
Elf_Dyn dyn;
char* ptr = (char*)fmap.sect[esm.sidx].shdr.sh_addr;
unsigned long len;
@ -1234,7 +1131,7 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
if (!elf_module_info) goto leave;
elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE,
(load_offset) ? load_offset : fmap.elf_start,
fmap.elf_size, 0, calc_crc32(&fmap));
fmap.elf_size, 0, calc_crc32(fmap.fd));
if (!elf_info->module)
{
HeapFree(GetProcessHeap(), 0, elf_module_info);
@ -1389,7 +1286,7 @@ static BOOL elf_search_and_load_file(struct process* pcs, const WCHAR* filename,
*/
static BOOL elf_enum_modules_internal(const struct process* pcs,
const WCHAR* main_name,
elf_enum_modules_cb cb, void* user)
enum_modules_cb cb, void* user)
{
struct r_debug dbg_hdr;
void* lm_addr;
@ -1492,9 +1389,7 @@ static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
const char* ptr;
/* All binaries are loaded with WINELOADER (if run from tree) or by the
* main executable (either wine-kthread or wine-pthread)
* FIXME: the heuristic used to know whether we need to load wine-pthread
* or wine-kthread is not 100% safe
* main executable
*/
if ((ptr = getenv("WINELOADER")))
{
@ -1504,8 +1399,7 @@ static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
}
else
{
ret = elf_search_and_load_file(pcs, S_WineKThreadW, 0, elf_info) ||
elf_search_and_load_file(pcs, S_WinePThreadW, 0, elf_info);
ret = elf_search_and_load_file(pcs, S_WineW, 0, elf_info);
}
return ret;
}
@ -1533,7 +1427,7 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
* This function doesn't require that someone has called SymInitialize
* on this very process.
*/
BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user)
{
struct process pcs;
struct elf_info elf_info;
@ -1638,7 +1532,7 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
return FALSE;
}
BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user)
{
return FALSE;
}

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
struct dump_memory
{
ULONG base;
ULONG64 base;
ULONG size;
ULONG rva;
};
@ -42,7 +42,7 @@ struct dump_memory
struct dump_module
{
unsigned is_elf;
ULONG base;
ULONG64 base;
ULONG size;
DWORD timestamp;
DWORD checksum;
@ -59,6 +59,7 @@ struct dump_context
/* module information */
struct dump_module* modules;
unsigned num_modules;
unsigned alloc_modules;
/* exception information */
/* output information */
MINIDUMP_TYPE type;
@ -66,6 +67,7 @@ struct dump_context
RVA rva;
struct dump_memory* mem;
unsigned num_mem;
unsigned alloc_mem;
/* callback information */
MINIDUMP_CALLBACK_INFORMATION* cb;
};
@ -98,10 +100,9 @@ static BOOL fetch_processes_info(struct dump_context* dc)
dc->spi = dc->pcs_buffer;
for (;;)
{
if (dc->spi->dwProcessID == dc->pid) return TRUE;
if (!dc->spi->dwOffset) break;
dc->spi = (SYSTEM_PROCESS_INFORMATION*)
((char*)dc->spi + dc->spi->dwOffset);
if (HandleToUlong(dc->spi->UniqueProcessId) == dc->pid) return TRUE;
if (!dc->spi->NextEntryOffset) break;
dc->spi = (SYSTEM_PROCESS_INFORMATION*)((char*)dc->spi + dc->spi->NextEntryOffset);
}
}
HeapFree(GetProcessHeap(), 0, dc->pcs_buffer);
@ -114,58 +115,25 @@ static void fetch_thread_stack(struct dump_context* dc, const void* teb_addr,
const CONTEXT* ctx, MINIDUMP_MEMORY_DESCRIPTOR* mmd)
{
NT_TIB tib;
ADDRESS64 addr;
if (ReadProcessMemory(dc->hProcess, teb_addr, &tib, sizeof(tib), NULL))
if (ReadProcessMemory(dc->hProcess, teb_addr, &tib, sizeof(tib), NULL) &&
dbghelp_current_cpu &&
dbghelp_current_cpu->get_addr(NULL /* FIXME */, ctx, cpu_addr_stack, &addr) && addr.Mode == AddrModeFlat)
{
#ifdef __i386__
/* limiting the stack dumping to the size actually used */
if (ctx->Esp){
/* make sure ESP is within the established range of the stack. It could have
if (addr.Offset)
{
addr.Offset -= dbghelp_current_cpu->word_size;
/* make sure stack pointer is within the established range of the stack. It could have
been clobbered by whatever caused the original exception. */
if (ctx->Esp - 4 < (ULONG_PTR)tib.StackLimit || ctx->Esp - 4 > (ULONG_PTR)tib.StackBase)
if (addr.Offset < (ULONG_PTR)tib.StackLimit || addr.Offset > (ULONG_PTR)tib.StackBase)
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
else
mmd->StartOfMemoryRange = (ctx->Esp - 4);
mmd->StartOfMemoryRange = addr.Offset;
}
else
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
#elif defined(__powerpc__)
if (ctx->Iar){
/* make sure IAR is within the established range of the stack. It could have
been clobbered by whatever caused the original exception. */
if (ctx->Iar - 4 < (ULONG_PTR)tib.StackLimit || ctx->Iar - 4 > (ULONG_PTR)tib.StackBase)
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
else
mmd->StartOfMemoryRange = (ctx->Iar - 4);
}
else
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
#elif defined(__x86_64__)
if (ctx->Rsp){
/* make sure RSP is within the established range of the stack. It could have
been clobbered by whatever caused the original exception. */
if (ctx->Rsp - 8 < (ULONG_PTR)tib.StackLimit || ctx->Rsp - 8 > (ULONG_PTR)tib.StackBase)
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
else
mmd->StartOfMemoryRange = (ctx->Rsp - 8);
}
else
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
#else
#error unsupported CPU
#endif
mmd->Memory.DataSize = (ULONG_PTR)tib.StackBase - mmd->StartOfMemoryRange;
}
}
@ -179,13 +147,13 @@ static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx,
const MINIDUMP_EXCEPTION_INFORMATION* except,
MINIDUMP_THREAD* mdThd, CONTEXT* ctx)
{
DWORD tid = dc->spi->ti[thd_idx].dwThreadID;
DWORD tid = HandleToUlong(dc->spi->ti[thd_idx].ClientId.UniqueThread);
HANDLE hThread;
THREAD_BASIC_INFORMATION tbi;
memset(ctx, 0, sizeof(*ctx));
mdThd->ThreadId = dc->spi->ti[thd_idx].dwThreadID;
mdThd->ThreadId = tid;
mdThd->SuspendCount = 0;
mdThd->Teb = 0;
mdThd->Stack.StartOfMemoryRange = 0;
@ -198,8 +166,7 @@ static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx,
if ((hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid)) == NULL)
{
FIXME("Couldn't open thread %u (%u)\n",
dc->spi->ti[thd_idx].dwThreadID, GetLastError());
FIXME("Couldn't open thread %u (%u)\n", tid, GetLastError());
return FALSE;
}
@ -230,7 +197,7 @@ static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx,
ReadProcessMemory(dc->hProcess, except->ExceptionPointers,
&ep, sizeof(ep), NULL);
ReadProcessMemory(dc->hProcess, ep.ContextRecord,
&ctx, sizeof(ctx), NULL);
&lctx, sizeof(lctx), NULL);
pctx = &lctx;
}
else pctx = except->ExceptionPointers->ContextRecord;
@ -251,27 +218,38 @@ static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx,
* Add a module to a dump context
*/
static BOOL add_module(struct dump_context* dc, const WCHAR* name,
DWORD base, DWORD size, DWORD timestamp, DWORD checksum,
DWORD64 base, DWORD size, DWORD timestamp, DWORD checksum,
BOOL is_elf)
{
if (!dc->modules)
{
dc->alloc_modules = 32;
dc->modules = HeapAlloc(GetProcessHeap(), 0,
++dc->num_modules * sizeof(*dc->modules));
else
dc->alloc_modules * sizeof(*dc->modules));
}
else if(dc->num_modules >= dc->alloc_modules)
{
dc->alloc_modules *= 2;
dc->modules = HeapReAlloc(GetProcessHeap(), 0, dc->modules,
++dc->num_modules * sizeof(*dc->modules));
if (!dc->modules) return FALSE;
dc->alloc_modules * sizeof(*dc->modules));
}
if (!dc->modules)
{
dc->alloc_modules = dc->num_modules = 0;
return FALSE;
}
if (is_elf ||
!GetModuleFileNameExW(dc->hProcess, (HMODULE)base,
dc->modules[dc->num_modules - 1].name,
sizeof(dc->modules[dc->num_modules - 1].name) / sizeof(WCHAR)))
lstrcpynW(dc->modules[dc->num_modules - 1].name, name,
sizeof(dc->modules[dc->num_modules - 1].name) / sizeof(WCHAR));
dc->modules[dc->num_modules - 1].base = base;
dc->modules[dc->num_modules - 1].size = size;
dc->modules[dc->num_modules - 1].timestamp = timestamp;
dc->modules[dc->num_modules - 1].checksum = checksum;
dc->modules[dc->num_modules - 1].is_elf = is_elf;
!GetModuleFileNameExW(dc->hProcess, (HMODULE)(DWORD_PTR)base,
dc->modules[dc->num_modules].name,
sizeof(dc->modules[dc->num_modules].name) / sizeof(WCHAR)))
lstrcpynW(dc->modules[dc->num_modules].name, name,
sizeof(dc->modules[dc->num_modules].name) / sizeof(WCHAR));
dc->modules[dc->num_modules].base = base;
dc->modules[dc->num_modules].size = size;
dc->modules[dc->num_modules].timestamp = timestamp;
dc->modules[dc->num_modules].checksum = checksum;
dc->modules[dc->num_modules].is_elf = is_elf;
dc->num_modules++;
return TRUE;
}
@ -284,13 +262,13 @@ static BOOL add_module(struct dump_context* dc, const WCHAR* name,
static BOOL WINAPI fetch_pe_module_info_cb(PCWSTR name, DWORD64 base, ULONG size,
PVOID user)
{
struct dump_context* dc = (struct dump_context*)user;
struct dump_context* dc = user;
IMAGE_NT_HEADERS nth;
if (!validate_addr64(base)) return FALSE;
if (pe_load_nt_header(dc->hProcess, base, &nth))
add_module((struct dump_context*)user, name, base, size,
add_module(user, name, base, size,
nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum,
FALSE);
return TRUE;
@ -304,7 +282,7 @@ static BOOL WINAPI fetch_pe_module_info_cb(PCWSTR name, DWORD64 base, ULONG size
static BOOL fetch_elf_module_info_cb(const WCHAR* name, unsigned long base,
void* user)
{
struct dump_context* dc = (struct dump_context*)user;
struct dump_context* dc = user;
DWORD rbase, size, checksum;
/* FIXME: there's no relevant timestamp on ELF modules */
@ -318,6 +296,27 @@ static BOOL fetch_elf_module_info_cb(const WCHAR* name, unsigned long base,
return TRUE;
}
/******************************************************************
* fetch_macho_module_info_cb
*
* Callback for accumulating in dump_context a Mach-O modules set
*/
static BOOL fetch_macho_module_info_cb(const WCHAR* name, unsigned long base,
void* user)
{
struct dump_context* dc = (struct dump_context*)user;
DWORD rbase, size, checksum;
/* FIXME: there's no relevant timestamp on Mach-O modules */
/* NB: if we have a non-null base from the live-target use it. If we have
* a null base, then grab its base address from Mach-O file.
*/
if (!macho_fetch_file_info(name, &rbase, &size, &checksum))
size = checksum = 0;
add_module(dc, name, base ? base : rbase, size, 0 /* FIXME */, checksum, TRUE);
return TRUE;
}
static void fetch_modules_info(struct dump_context* dc)
{
EnumerateLoadedModulesW64(dc->hProcess, fetch_pe_module_info_cb, dc);
@ -327,6 +326,7 @@ static void fetch_modules_info(struct dump_context* dc)
* a given application in a post mortem debugging condition.
*/
elf_enum_modules(dc->hProcess, fetch_elf_module_info_cb, dc);
macho_enum_modules(dc->hProcess, fetch_macho_module_info_cb, dc);
}
static void fetch_module_versioninfo(LPCWSTR filename, VS_FIXEDFILEINFO* ffi)
@ -361,18 +361,25 @@ static void fetch_module_versioninfo(LPCWSTR filename, VS_FIXEDFILEINFO* ffi)
*/
static void add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva)
{
if (dc->mem)
dc->mem = HeapReAlloc(GetProcessHeap(), 0, dc->mem,
++dc->num_mem * sizeof(*dc->mem));
else
dc->mem = HeapAlloc(GetProcessHeap(), 0, ++dc->num_mem * sizeof(*dc->mem));
if (!dc->mem)
{
dc->alloc_mem = 32;
dc->mem = HeapAlloc(GetProcessHeap(), 0, dc->alloc_mem * sizeof(*dc->mem));
}
else if (dc->num_mem >= dc->alloc_mem)
{
dc->alloc_mem *= 2;
dc->mem = HeapReAlloc(GetProcessHeap(), 0, dc->mem,
dc->alloc_mem * sizeof(*dc->mem));
}
if (dc->mem)
{
dc->mem[dc->num_mem - 1].base = base;
dc->mem[dc->num_mem - 1].size = size;
dc->mem[dc->num_mem - 1].rva = rva;
dc->mem[dc->num_mem].base = base;
dc->mem[dc->num_mem].size = size;
dc->mem[dc->num_mem].rva = rva;
dc->num_mem++;
}
else dc->num_mem = 0;
else dc->num_mem = dc->alloc_mem = 0;
}
/******************************************************************
@ -394,7 +401,7 @@ static void writeat(struct dump_context* dc, RVA rva, const void* data, unsigned
* writes a new chunk of data to the minidump, increasing the current
* rva in dc
*/
static void append(struct dump_context* dc, void* data, unsigned size)
static void append(struct dump_context* dc, const void* data, unsigned size)
{
writeat(dc, dc->rva, data, size);
dc->rva += size;
@ -683,7 +690,7 @@ static unsigned dump_threads(struct dump_context* dc,
{
MINIDUMP_THREAD mdThd;
MINIDUMP_THREAD_LIST mdThdList;
unsigned i;
unsigned i, sz;
RVA rva_base;
DWORD flags_out;
CONTEXT ctx;
@ -691,8 +698,7 @@ static unsigned dump_threads(struct dump_context* dc,
mdThdList.NumberOfThreads = 0;
rva_base = dc->rva;
dc->rva += sizeof(mdThdList.NumberOfThreads) +
dc->spi->dwThreadCount * sizeof(mdThd);
dc->rva += sz = sizeof(mdThdList.NumberOfThreads) + dc->spi->dwThreadCount * sizeof(mdThd);
for (i = 0; i < dc->spi->dwThreadCount; i++)
{
@ -713,7 +719,7 @@ static unsigned dump_threads(struct dump_context* dc,
cbin.ProcessId = dc->pid;
cbin.ProcessHandle = dc->hProcess;
cbin.CallbackType = ThreadCallback;
cbin.u.Thread.ThreadId = dc->spi->ti[i].dwThreadID;
cbin.u.Thread.ThreadId = HandleToUlong(dc->spi->ti[i].ClientId.UniqueThread);
cbin.u.Thread.ThreadHandle = 0; /* FIXME */
cbin.u.Thread.Context = ctx;
cbin.u.Thread.SizeOfContext = sizeof(CONTEXT);
@ -760,7 +766,7 @@ static unsigned dump_threads(struct dump_context* dc,
writeat(dc, rva_base,
&mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads));
return dc->rva - rva_base;
return sz;
}
/******************************************************************
@ -795,7 +801,7 @@ static unsigned dump_memory_info(struct dump_context* dc)
{
len = min(dc->mem[i].size - pos, sizeof(tmp));
if (ReadProcessMemory(dc->hProcess,
(void*)(dc->mem[i].base + pos),
(void*)(DWORD_PTR)(dc->mem[i].base + pos),
tmp, len, NULL))
WriteFile(dc->hFile, tmp, len, &written, NULL);
}
@ -847,10 +853,12 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile,
dc.pid = pid;
dc.modules = NULL;
dc.num_modules = 0;
dc.alloc_modules = 0;
dc.cb = CallbackParam;
dc.type = DumpType;
dc.mem = NULL;
dc.num_mem = 0;
dc.alloc_mem = 0;
dc.rva = 0;
if (!fetch_processes_info(&dc)) return FALSE;
@ -973,7 +981,7 @@ BOOL WINAPI MiniDumpReadDumpStream(PVOID base, ULONG str_idx,
PMINIDUMP_DIRECTORY* pdir,
PVOID* stream, ULONG* size)
{
MINIDUMP_HEADER* mdHead = (MINIDUMP_HEADER*)base;
MINIDUMP_HEADER* mdHead = base;
if (mdHead->Signature == MINIDUMP_SIGNATURE)
{
@ -985,9 +993,9 @@ BOOL WINAPI MiniDumpReadDumpStream(PVOID base, ULONG str_idx,
{
if (dir->StreamType == str_idx)
{
*pdir = dir;
*stream = (char*)base + dir->Location.Rva;
*size = dir->Location.DataSize;
if (pdir) *pdir = dir;
if (stream) *stream = (char*)base + dir->Location.Rva;
if (size) *size = dir->Location.DataSize;
return TRUE;
}
}

View file

@ -35,10 +35,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
const WCHAR S_ElfW[] = {'<','e','l','f','>','\0'};
const WCHAR S_WineLoaderW[] = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'};
static const WCHAR S_DotSoW[] = {'.','s','o','\0'};
static const WCHAR S_DotDylibW[] = {'.','d','y','l','i','b','\0'};
static const WCHAR S_DotPdbW[] = {'.','p','d','b','\0'};
static const WCHAR S_DotDbgW[] = {'.','d','b','g','\0'};
const WCHAR S_WinePThreadW[] = {'w','i','n','e','-','p','t','h','r','e','a','d','\0'};
const WCHAR S_WineKThreadW[] = {'w','i','n','e','-','k','t','h','r','e','a','d','\0'};
const WCHAR S_WineW[] = {'w','i','n','e',0};
const WCHAR S_SlashW[] = {'/','\0'};
static const WCHAR S_AcmW[] = {'.','a','c','m','\0'};
@ -87,9 +87,7 @@ static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size)
out[len] = '\0';
if (len > 4 && (l = match_ext(out, len)))
out[len - l] = '\0';
else if (len > 12 &&
(!strcmpiW(out + len - 12, S_WinePThreadW) ||
!strcmpiW(out + len - 12, S_WineKThreadW)))
else if (len > 4 && !strcmpiW(out + len - 4, S_WineW))
lstrcpynW(out, S_WineLoaderW, size);
else
{
@ -114,6 +112,7 @@ static const char* get_module_type(enum module_type type, BOOL virtual)
{
case DMT_ELF: return virtual ? "Virtual ELF" : "ELF";
case DMT_PE: return virtual ? "Virtual PE" : "PE";
case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O";
default: return "---";
}
}
@ -123,20 +122,21 @@ static const char* get_module_type(enum module_type type, BOOL virtual)
*/
struct module* module_new(struct process* pcs, const WCHAR* name,
enum module_type type, BOOL virtual,
unsigned long mod_addr, unsigned long size,
DWORD64 mod_addr, DWORD64 size,
unsigned long stamp, unsigned long checksum)
{
struct module* module;
assert(type == DMT_ELF || type == DMT_PE);
assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO);
if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module))))
return NULL;
module->next = pcs->lmodules;
pcs->lmodules = module;
TRACE("=> %s %08lx-%08lx %s\n",
get_module_type(type, virtual), mod_addr, mod_addr + size,
TRACE("=> %s %s-%s %s\n",
get_module_type(type, virtual),
wine_dbgstr_longlong(mod_addr), wine_dbgstr_longlong(mod_addr + size),
debugstr_w(name));
pool_init(&module->pool, 65536);
@ -169,7 +169,12 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
module->type = type;
module->is_virtual = virtual ? TRUE : FALSE;
module->sortlist_valid = FALSE;
module->sorttab_size = 0;
module->addr_sorttab = NULL;
module->num_sorttab = 0;
module->num_symbols = 0;
vector_init(&module->vsymt, sizeof(struct symt*), 128);
/* FIXME: this seems a bit too high (on a per module basis)
* need some statistics about this
*/
@ -188,7 +193,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
* module_find_by_name
*
*/
struct module* module_find_by_name(const struct process* pcs, const WCHAR* name)
static struct module* module_find_by_name(const struct process* pcs, const WCHAR* name)
{
struct module* module;
@ -238,7 +243,7 @@ struct module* module_is_already_loaded(const struct process* pcs, const WCHAR*
* module_get_container
*
*/
struct module* module_get_container(const struct process* pcs,
static struct module* module_get_container(const struct process* pcs,
const struct module* inner)
{
struct module* module;
@ -319,6 +324,9 @@ BOOL module_get_debug(struct module_pair* pair)
ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
&idslW64);
break;
case DMT_MACHO:
ret = macho_load_debug_info(pair->effective, NULL);
break;
default:
ret = FALSE;
break;
@ -344,7 +352,8 @@ struct module* module_find_by_addr(const struct process* pcs, unsigned long addr
if (type == DMT_UNKNOWN)
{
if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
(module = module_find_by_addr(pcs, addr, DMT_ELF)))
(module = module_find_by_addr(pcs, addr, DMT_ELF)) ||
(module = module_find_by_addr(pcs, addr, DMT_MACHO)))
return module;
}
else
@ -361,13 +370,13 @@ struct module* module_find_by_addr(const struct process* pcs, unsigned long addr
}
/******************************************************************
* module_is_elf_container_loaded
* module_is_container_loaded
*
* checks whether the ELF container, for a (supposed) PE builtin is
* checks whether the native container, for a (supposed) PE builtin is
* already loaded
*/
static BOOL module_is_elf_container_loaded(const struct process* pcs,
const WCHAR* ImageName, DWORD base)
static BOOL module_is_container_loaded(const struct process* pcs,
const WCHAR* ImageName, DWORD64 base)
{
size_t len;
struct module* module;
@ -379,7 +388,7 @@ static BOOL module_is_elf_container_loaded(const struct process* pcs,
for (module = pcs->lmodules; module; module = module->next)
{
if (module->type == DMT_ELF &&
if ((module->type == DMT_ELF || module->type == DMT_MACHO) &&
base >= module->module.BaseOfImage &&
base < module->module.BaseOfImage + module->module.ImageSize)
{
@ -419,8 +428,17 @@ enum module_type module_get_type_by_name(const WCHAR* name)
} while (len);
/* check for terminating .so or .so.[digit] */
/* FIXME: Can't rely solely on extension; have to check magic or
* stop using .so on Mac OS X. For now, base on platform. */
if (len > 3 && !memcmp(name + len - 3, S_DotSoW, 3))
#ifdef __APPLE__
return DMT_MACHO;
#else
return DMT_ELF;
#endif
if (len > 6 && !strncmpiW(name + len - 6, S_DotDylibW, 6))
return DMT_MACHO;
if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4))
return DMT_PDB;
@ -428,16 +446,27 @@ enum module_type module_get_type_by_name(const WCHAR* name)
if (len > 4 && !strncmpiW(name + len - 4, S_DotDbgW, 4))
return DMT_DBG;
/* wine-[kp]thread is also an ELF module */
if (((len > 12 && name[len - 13] == '/') || len == 12) &&
(!strncmpiW(name + len - 12, S_WinePThreadW, 12) ||
!strncmpiW(name + len - 12, S_WineKThreadW, 12)))
/* wine is also a native module (Mach-O on Mac OS X, ELF elsewhere) */
if (((len > 4 && name[len - 5] == '/') || len == 4) && !strcmpiW(name + len - 4, S_WineW))
{
#ifdef __APPLE__
return DMT_MACHO;
#else
return DMT_ELF;
#endif
}
return DMT_PE;
}
/******************************************************************
* refresh_module_list
*/
static BOOL refresh_module_list(struct process* pcs)
{
/* force transparent ELF and Mach-O loading / unloading */
return elf_synchronize_module_list(pcs) || macho_synchronize_module_list(pcs);
}
/***********************************************************************
* SymLoadModule (DBGHELP.@)
*/
@ -508,8 +537,9 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (Flags & SLMFLAG_VIRTUAL)
{
if (!wImageName) return FALSE;
module = module_new(pcs, wImageName, module_get_type_by_name(wImageName),
TRUE, (DWORD)BaseOfDll, SizeOfDll, 0, 0);
TRUE, BaseOfDll, SizeOfDll, 0, 0);
if (!module) return FALSE;
if (wModuleName) module_set_module(module, wModuleName);
module->module.SymType = SymVirtual;
@ -519,8 +549,7 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (Flags & ~(SLMFLAG_VIRTUAL))
FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName));
/* force transparent ELF loading / unloading */
elf_synchronize_module_list(pcs);
refresh_module_list(pcs);
/* this is a Wine extension to the API just to redo the synchronisation */
if (!wImageName && !hFile) return 0;
@ -531,7 +560,7 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (wImageName)
{
module = module_is_already_loaded(pcs, wImageName);
if (!module && module_is_elf_container_loaded(pcs, wImageName, BaseOfDll))
if (!module && module_is_container_loaded(pcs, wImageName, BaseOfDll))
{
/* force the loading of DLL as builtin */
module = pe_load_builtin_module(pcs, wImageName, BaseOfDll, SizeOfDll);
@ -540,11 +569,22 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (!module)
{
/* otherwise, try a regular PE module */
if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)))
if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)) &&
wImageName)
{
/* and finally and ELF module */
if (module_get_type_by_name(wImageName) == DMT_ELF)
module = elf_load_module(pcs, wImageName, BaseOfDll);
/* and finally an ELF or Mach-O module */
switch (module_get_type_by_name(wImageName))
{
case DMT_ELF:
module = elf_load_module(pcs, wImageName, BaseOfDll);
break;
case DMT_MACHO:
module = macho_load_module(pcs, wImageName, BaseOfDll);
break;
default:
/* Ignored */
break;
}
}
}
if (!module)
@ -558,7 +598,8 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
*/
if (wModuleName)
module_set_module(module, wModuleName);
lstrcpynW(module->module.ImageName, wImageName,
if (wImageName)
lstrcpynW(module->module.ImageName, wImageName,
sizeof(module->module.ImageName) / sizeof(WCHAR));
return module->module.BaseOfImage;
@ -715,7 +756,8 @@ BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess,
for (module = pcs->lmodules; module; module = module->next)
{
if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) &&
(module->type == DMT_ELF || module->type == DMT_MACHO))
continue;
if (!EnumModulesCallback(module->module.ModuleName,
module->module.BaseOfImage, UserContext))
@ -1008,7 +1050,9 @@ DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
void module_reset_debug_info(struct module* module)
{
module->sortlist_valid = TRUE;
module->sorttab_size = 0;
module->addr_sorttab = NULL;
module->num_sorttab = module->num_symbols = 0;
hash_table_destroy(&module->ht_symbols);
module->ht_symbols.num_buckets = 0;
module->ht_symbols.buckets = NULL;
@ -1020,3 +1064,17 @@ void module_reset_debug_info(struct module* module)
module->sources_used = module->sources_alloc = 0;
module->sources = NULL;
}
/******************************************************************
* SymRefreshModuleList (DBGHELP.@)
*/
BOOL WINAPI SymRefreshModuleList(HANDLE hProcess)
{
struct process* pcs;
TRACE("(%p)\n", hProcess);
if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
return refresh_module_list(pcs);
}

View file

@ -71,7 +71,7 @@ static void dump(const void* ptr, unsigned len)
unsigned int i, j;
char msg[128];
const char* hexof = "0123456789abcdef";
const BYTE* x = (const BYTE*)ptr;
const BYTE* x = ptr;
for (i = 0; i < len; i += 16)
{
@ -95,7 +95,7 @@ static void dump(const void* ptr, unsigned len)
* Process CodeView type information.
*/
#define MAX_BUILTIN_TYPES 0x0480
#define MAX_BUILTIN_TYPES 0x0604
#define FIRST_DEFINABLE_TYPE 0x1000
static struct symt* cv_basic_types[MAX_BUILTIN_TYPES];
@ -113,6 +113,7 @@ static struct cv_defined_module*cv_current_module;
static void codeview_init_basic_types(struct module* module)
{
struct symt_udt* udt;
/*
* These are the common builtin types that are used by VC++.
*/
@ -169,6 +170,12 @@ static void codeview_init_basic_types(struct module* module)
cv_basic_types[T_32PINT8] = &symt_new_pointer(module, cv_basic_types[T_INT8])->symt;
cv_basic_types[T_32PUINT8] = &symt_new_pointer(module, cv_basic_types[T_UINT8])->symt;
cv_basic_types[T_32PHRESULT]= &symt_new_pointer(module, cv_basic_types[T_HRESULT])->symt;
/* The .pdb file can refer to 64 bit pointers values even on 32 bits applications. */
udt = symt_new_udt(module, "PVOID64", 8, UdtStruct);
symt_add_udt_element(module, udt, "ptr64_low", cv_basic_types[T_LONG], 0, 32);
symt_add_udt_element(module, udt, "ptr64_high", cv_basic_types[T_LONG], 32, 32);
cv_basic_types[0x603]= &udt->symt;
}
static int leaf_as_variant(VARIANT* v, const unsigned short int* leaf)
@ -486,18 +493,23 @@ static int codeview_add_type(unsigned int typeno, struct symt* dt)
if ((typeno >> 24) != 0)
FIXME("No module index while inserting type-id assumption is wrong %x\n",
typeno);
while (typeno - FIRST_DEFINABLE_TYPE >= cv_current_module->num_defined_types)
if (typeno - FIRST_DEFINABLE_TYPE >= cv_current_module->num_defined_types)
{
cv_current_module->num_defined_types += 0x100;
if (cv_current_module->defined_types)
{
cv_current_module->num_defined_types = max( cv_current_module->num_defined_types * 2,
typeno - FIRST_DEFINABLE_TYPE + 1 );
cv_current_module->defined_types = HeapReAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, cv_current_module->defined_types,
cv_current_module->num_defined_types * sizeof(struct symt*));
}
else
{
cv_current_module->num_defined_types = max( 256, typeno - FIRST_DEFINABLE_TYPE + 1 );
cv_current_module->defined_types = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
cv_current_module->num_defined_types * sizeof(struct symt*));
}
if (cv_current_module->defined_types == NULL) return FALSE;
}
if (cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE])
@ -581,15 +593,8 @@ static struct symt* codeview_add_type_array(struct codeview_type_parse* ctp,
{
struct symt* elem = codeview_fetch_type(ctp, elemtype, FALSE);
struct symt* index = codeview_fetch_type(ctp, indextype, FALSE);
DWORD arr_max = 0;
if (elem)
{
DWORD64 elem_size;
symt_get_info(elem, TI_GET_LENGTH, &elem_size);
if (elem_size) arr_max = arr_len / (DWORD)elem_size;
}
return &symt_new_array(ctp->module, 0, arr_max, elem, index)->symt;
return &symt_new_array(ctp->module, 0, -arr_len, elem, index)->symt;
}
static int codeview_add_type_enum_field_list(struct module* module,
@ -669,7 +674,7 @@ static void codeview_add_udt_element(struct codeview_type_parse* ctp,
if (subtype)
{
DWORD64 elem_size = 0;
symt_get_info(subtype, TI_GET_LENGTH, &elem_size);
symt_get_info(ctp->module, subtype, TI_GET_LENGTH, &elem_size);
symt_add_udt_element(ctp->module, symt, name, subtype,
value << 3, (DWORD)elem_size << 3);
}
@ -1357,48 +1362,72 @@ static void codeview_snarf_linetab(const struct msc_debug_info* msc_dbg, const B
}
static void codeview_snarf_linetab2(const struct msc_debug_info* msc_dbg, const BYTE* linetab, DWORD size,
const char* strimage, DWORD strsize)
const char* strimage, DWORD strsize)
{
DWORD offset;
unsigned i;
DWORD addr;
const struct codeview_linetab2_block* lbh;
const struct codeview_linetab2_file* fd;
const struct codeview_linetab2* lt2;
const struct codeview_linetab2* lt2_files = NULL;
const struct codeview_lt2blk_lines* lines_blk;
const struct codeview_linetab2_file*fd;
unsigned source;
struct symt_function* func;
if (*(const DWORD*)linetab != 0x000000f4) return;
offset = *((const DWORD*)linetab + 1);
for (lbh = (const struct codeview_linetab2_block*)(linetab + 8 + offset);
(const BYTE*)lbh < linetab + size;
lbh = (const struct codeview_linetab2_block*)((const char*)lbh + 8 + lbh->size_of_block))
/* locate LT2_FILES_BLOCK (if any) */
lt2 = (const struct codeview_linetab2*)linetab;
while ((const BYTE*)(lt2 + 1) < linetab + size)
{
if (lbh->header != 0x000000f2)
/* FIXME: should also check that whole lbh fits in linetab + size */
if (lt2->header == LT2_FILES_BLOCK)
{
TRACE("block end %x\n", lbh->header);
lt2_files = lt2;
break;
}
addr = codeview_get_address(msc_dbg, lbh->seg, lbh->start);
TRACE("block from %04x:%08x #%x (%x lines)\n",
lbh->seg, lbh->start, lbh->size, lbh->nlines);
fd = (const struct codeview_linetab2_file*)(linetab + 8 + lbh->file_offset);
/* FIXME: should check that string is within strimage + strsize */
source = source_new(msc_dbg->module, NULL, strimage + fd->offset);
func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr);
/* FIXME: at least labels support line numbers */
if (!func || func->symt.tag != SymTagFunction)
lt2 = codeview_linetab2_next_block(lt2);
}
if (!lt2_files)
{
TRACE("No LT2_FILES_BLOCK found\n");
return;
}
lt2 = (const struct codeview_linetab2*)linetab;
while ((const BYTE*)(lt2 + 1) < linetab + size)
{
/* FIXME: should also check that whole lines_blk fits in linetab + size */
switch (lt2->header)
{
WARN("--not a func at %04x:%08x %x tag=%d\n",
lbh->seg, lbh->start, addr, func ? func->symt.tag : -1);
case LT2_LINES_BLOCK:
lines_blk = (const struct codeview_lt2blk_lines*)lt2;
/* FIXME: should check that file_offset is within the LT2_FILES_BLOCK we've seen */
addr = codeview_get_address(msc_dbg, lines_blk->seg, lines_blk->start);
TRACE("block from %04x:%08x #%x (%x lines)\n",
lines_blk->seg, lines_blk->start, lines_blk->size, lines_blk->nlines);
fd = (const struct codeview_linetab2_file*)((const char*)lt2_files + 8 + lines_blk->file_offset);
/* FIXME: should check that string is within strimage + strsize */
source = source_new(msc_dbg->module, NULL, strimage + fd->offset);
func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr);
/* FIXME: at least labels support line numbers */
if (!func || func->symt.tag != SymTagFunction)
{
WARN("--not a func at %04x:%08x %x tag=%d\n",
lines_blk->seg, lines_blk->start, addr, func ? func->symt.tag : -1);
break;
}
for (i = 0; i < lines_blk->nlines; i++)
{
symt_add_func_line(msc_dbg->module, func, source,
lines_blk->l[i].lineno ^ 0x80000000,
lines_blk->l[i].offset);
}
break;
case LT2_FILES_BLOCK: /* skip */
break;
default:
TRACE("Block end %x\n", lt2->header);
lt2 = (const struct codeview_linetab2*)((const char*)linetab + size);
continue;
}
for (i = 0; i < lbh->nlines; i++)
{
symt_add_func_line(msc_dbg->module, func, source,
lbh->l[i].lineno ^ 0x80000000, lbh->l[i].offset - lbh->start);
}
lt2 = codeview_linetab2_next_block(lt2);
}
}
@ -1897,8 +1926,7 @@ static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYT
{
symt_new_public(msc_dbg->module, compiland,
terminate_string(&sym->data_v1.p_name),
codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset),
1, TRUE /* FIXME */, TRUE /* FIXME */);
codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset), 1);
}
break;
case S_PUB_V2: /* FIXME is this really a 'data_v2' structure ?? */
@ -1906,8 +1934,7 @@ static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYT
{
symt_new_public(msc_dbg->module, compiland,
terminate_string(&sym->data_v2.p_name),
codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset),
1, TRUE /* FIXME */, TRUE /* FIXME */);
codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset), 1);
}
break;
@ -1916,8 +1943,7 @@ static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYT
{
symt_new_public(msc_dbg->module, compiland,
sym->data_v3.name,
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
1, FALSE /* FIXME */, FALSE);
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset), 1);
}
break;
case S_PUB_FUNC1_V3:
@ -1928,8 +1954,7 @@ static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYT
{
symt_new_public(msc_dbg->module, compiland,
sym->data_v3.name,
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
1, TRUE /* FIXME */, TRUE);
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset), 1);
}
#endif
break;
@ -2150,7 +2175,7 @@ static void pdb_convert_symbol_file(const PDB_SYMBOLS* symbols,
{
if (symbols->version < 19970000)
{
const PDB_SYMBOL_FILE *sym_file = (const PDB_SYMBOL_FILE*)image;
const PDB_SYMBOL_FILE *sym_file = image;
memset(sfile, 0, sizeof(*sfile));
sfile->file = sym_file->file;
sfile->range.index = sym_file->range.index;
@ -2217,7 +2242,8 @@ static void pdb_process_types(const struct msc_debug_info* msc_dbg,
case 19950410: /* VC 4.0 */
case 19951122:
case 19961031: /* VC 5.0 / 6.0 */
case 19990903:
case 19990903: /* VC 7.0 */
case 20040203: /* VC 8.0 */
break;
default:
ERR("-Unknown type info version %d\n", types.version);
@ -2385,7 +2411,7 @@ static void pdb_process_symbol_imports(const struct process* pcs,
imp = (const PDB_SYMBOL_IMPORT*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) +
symbols->module_size + symbols->offset_size +
symbols->hash_size + symbols->srcmodule_size);
first = (const char*)imp;
first = imp;
last = (const char*)imp + symbols->pdbimport_size;
while (imp < (const PDB_SYMBOL_IMPORT*)last)
{
@ -2524,7 +2550,7 @@ static BOOL pdb_process_internal(const struct process* pcs,
}
file_name = (const char*)file + size;
file_name += strlen(file_name) + 1;
file = (BYTE*)((DWORD)(file_name + strlen(file_name) + 1 + 3) & ~3);
file = (BYTE*)((DWORD_PTR)(file_name + strlen(file_name) + 1 + 3) & ~3);
}
/* finish the remaining public and global information */
if (globalimage)

View file

@ -234,7 +234,7 @@ static BOOL do_searchW(PCWSTR file, PWSTR buffer, BOOL recurse,
strcpyW(buffer + pos, fd.cFileName);
if (recurse && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
found = do_searchW(file, buffer, TRUE, cb, user);
else if (SymMatchFileNameW(buffer, (WCHAR*)file, NULL, NULL))
else if (SymMatchFileNameW(buffer, file, NULL, NULL))
{
if (!cb || cb(buffer, user)) found = TRUE;
}
@ -340,13 +340,13 @@ struct sffip
*/
static BOOL CALLBACK sffip_cb(PCWSTR buffer, PVOID user)
{
struct sffip* s = (struct sffip*)user;
struct sffip* s = user;
if (!s->cb) return TRUE;
/* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite
* convention to stop/continue enumeration. sigh.
*/
return !(s->cb)((WCHAR*)buffer, s->user);
return !(s->cb)(buffer, s->user);
}
/******************************************************************
@ -461,7 +461,7 @@ struct module_find
*/
static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
{
struct module_find* mf = (struct module_find*)user;
struct module_find* mf = user;
DWORD size, checksum, timestamp;
unsigned matched = 0;
@ -522,6 +522,21 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
return FALSE;
}
break;
case DMT_MACHO:
if (macho_fetch_file_info(buffer, 0, &size, &checksum))
{
matched++;
if (checksum == mf->dw1) matched++;
else
WARN("Found %s, but wrong checksums: %08x %08x\n",
debugstr_w(buffer), checksum, mf->dw1);
}
else
{
WARN("Couldn't read %s\n", debugstr_w(buffer));
return FALSE;
}
break;
case DMT_PDB:
{
struct pdb_lookup pdb_lookup;
@ -580,7 +595,7 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
{
const IMAGE_SEPARATE_DEBUG_HEADER* hdr;
hdr = (const IMAGE_SEPARATE_DEBUG_HEADER*)mapping;
hdr = mapping;
if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE)
{

View file

@ -35,6 +35,141 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
/******************************************************************
* pe_locate_with_coff_symbol_table
*
* Use the COFF symbol table (if any) from the IMAGE_FILE_HEADER to set the absolute address
* of global symbols.
* Mingw32 requires this for stabs debug information as address for global variables isn't filled in
* (this is similar to what is done in elf_module.c when using the .symtab ELF section)
*/
static BOOL pe_locate_with_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, void* mapping)
{
const IMAGE_SYMBOL* isym;
int i, numsym, naux;
const char* strtable;
char tmp[9];
const char* name;
struct hash_table_iter hti;
void* ptr;
struct symt_data* sym;
const IMAGE_SECTION_HEADER* sect;
numsym = nth->FileHeader.NumberOfSymbols;
if (!nth->FileHeader.PointerToSymbolTable || !numsym)
return TRUE;
isym = (const IMAGE_SYMBOL*)((char*)mapping + nth->FileHeader.PointerToSymbolTable);
/* FIXME: no way to get strtable size */
strtable = (const char*)&isym[numsym];
sect = IMAGE_FIRST_SECTION(nth);
for (i = 0; i < numsym; i+= naux, isym += naux)
{
if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
isym->SectionNumber > 0 && isym->SectionNumber <= nth->FileHeader.NumberOfSections)
{
if (isym->N.Name.Short)
{
name = memcpy(tmp, isym->N.ShortName, 8);
tmp[8] = '\0';
}
else name = strtable + isym->N.Name.Long;
if (name[0] == '_') name++;
hash_table_iter_init(&module->ht_symbols, &hti, name);
while ((ptr = hash_table_iter_up(&hti)))
{
sym = GET_ENTRY(ptr, struct symt_data, hash_elt);
if (sym->symt.tag == SymTagData &&
(sym->kind == DataIsGlobal || sym->kind == DataIsFileStatic) &&
!strcmp(sym->hash_elt.name, name))
{
TRACE("Changing absolute address for %d.%s: %lx -> %s\n",
isym->SectionNumber, name, sym->u.var.offset,
wine_dbgstr_longlong(module->module.BaseOfImage +
sect[isym->SectionNumber - 1].VirtualAddress + isym->Value));
sym->u.var.offset = module->module.BaseOfImage +
sect[isym->SectionNumber - 1].VirtualAddress + isym->Value;
break;
}
}
}
naux = isym->NumberOfAuxSymbols + 1;
}
return TRUE;
}
/******************************************************************
* pe_load_coff_symbol_table
*
* Load public symbols out of the COFF symbol table (if any).
*/
static BOOL pe_load_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, void* mapping)
{
const IMAGE_SYMBOL* isym;
int i, numsym, naux;
const char* strtable;
char tmp[9];
const char* name;
const char* lastfilename = NULL;
struct symt_compiland* compiland = NULL;
const IMAGE_SECTION_HEADER* sect;
numsym = nth->FileHeader.NumberOfSymbols;
if (!nth->FileHeader.PointerToSymbolTable || !numsym)
return TRUE;
isym = (const IMAGE_SYMBOL*)((char*)mapping + nth->FileHeader.PointerToSymbolTable);
/* FIXME: no way to get strtable size */
strtable = (const char*)&isym[numsym];
sect = IMAGE_FIRST_SECTION(nth);
for (i = 0; i < numsym; i+= naux, isym += naux)
{
if (isym->StorageClass == IMAGE_SYM_CLASS_FILE)
{
lastfilename = (const char*)(isym + 1);
compiland = NULL;
}
if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
isym->SectionNumber > 0 && isym->SectionNumber <= nth->FileHeader.NumberOfSections)
{
if (isym->N.Name.Short)
{
name = memcpy(tmp, isym->N.ShortName, 8);
tmp[8] = '\0';
}
else name = strtable + isym->N.Name.Long;
if (name[0] == '_') name++;
if (!compiland && lastfilename)
compiland = symt_new_compiland(module, 0,
source_new(module, NULL, lastfilename));
symt_new_public(module, compiland, name,
module->module.BaseOfImage + sect[isym->SectionNumber - 1].VirtualAddress + isym->Value,
1);
}
naux = isym->NumberOfAuxSymbols + 1;
}
module->module.SymType = SymCoff;
module->module.LineNumbers = FALSE;
module->module.GlobalSymbols = FALSE;
module->module.TypeInfo = FALSE;
module->module.SourceIndexed = FALSE;
module->module.Publics = TRUE;
return TRUE;
}
static inline void* pe_get_sect(IMAGE_NT_HEADERS* nth, void* mapping,
IMAGE_SECTION_HEADER* sect)
{
return (sect) ? RtlImageRvaToVa(nth, mapping, sect->VirtualAddress, NULL) : NULL;
}
static inline DWORD pe_get_sect_size(IMAGE_SECTION_HEADER* sect)
{
return (sect) ? sect->SizeOfRawData : 0;
}
/******************************************************************
* pe_load_stabs
*
@ -45,37 +180,85 @@ static BOOL pe_load_stabs(const struct process* pcs, struct module* module,
void* mapping, IMAGE_NT_HEADERS* nth)
{
IMAGE_SECTION_HEADER* section;
int i, stabsize = 0, stabstrsize = 0;
unsigned int stabs = 0, stabstr = 0;
IMAGE_SECTION_HEADER* sect_stabs = NULL;
IMAGE_SECTION_HEADER* sect_stabstr = NULL;
int i;
BOOL ret = FALSE;
section = (IMAGE_SECTION_HEADER*)
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
if (!strcasecmp((const char*)section->Name, ".stab"))
{
stabs = section->VirtualAddress;
stabsize = section->SizeOfRawData;
}
else if (!strncasecmp((const char*)section->Name, ".stabstr", 8))
{
stabstr = section->VirtualAddress;
stabstrsize = section->SizeOfRawData;
}
if (!strcasecmp((const char*)section->Name, ".stab")) sect_stabs = section;
else if (!strncasecmp((const char*)section->Name, ".stabstr", 8)) sect_stabstr = section;
}
if (stabstrsize && stabsize)
if (sect_stabs && sect_stabstr)
{
ret = stabs_parse(module,
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
RtlImageRvaToVa(nth, mapping, stabs, NULL),
stabsize,
RtlImageRvaToVa(nth, mapping, stabstr, NULL),
stabstrsize);
ret = stabs_parse(module,
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
pe_get_sect(nth, mapping, sect_stabs), pe_get_sect_size(sect_stabs),
pe_get_sect(nth, mapping, sect_stabstr), pe_get_sect_size(sect_stabstr),
NULL, NULL);
if (ret) pe_locate_with_coff_symbol_table(module, nth, mapping);
}
TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load");
return ret;
}
/******************************************************************
* pe_load_dwarf
*
* look for dwarf information in PE header (it's also a way for the mingw compiler
* to provide its debugging information)
*/
static BOOL pe_load_dwarf(const struct process* pcs, struct module* module,
void* mapping, IMAGE_NT_HEADERS* nth)
{
IMAGE_SECTION_HEADER* section;
IMAGE_SECTION_HEADER* sect_debuginfo = NULL;
IMAGE_SECTION_HEADER* sect_debugstr = NULL;
IMAGE_SECTION_HEADER* sect_debugabbrev = NULL;
IMAGE_SECTION_HEADER* sect_debugline = NULL;
IMAGE_SECTION_HEADER* sect_debugloc = NULL;
int i;
const char* strtable;
const char* sectname;
BOOL ret = FALSE;
if (nth->FileHeader.PointerToSymbolTable && nth->FileHeader.NumberOfSymbols)
/* FIXME: no way to get strtable size */
strtable = (const char*)mapping + nth->FileHeader.PointerToSymbolTable +
nth->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL);
else strtable = NULL;
section = (IMAGE_SECTION_HEADER*)
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
sectname = (const char*)section->Name;
/* long section names start with a '/' (at least on MinGW32) */
if (*sectname == '/' && strtable)
sectname = strtable + atoi(sectname + 1);
if (!strcasecmp(sectname, ".debug_info")) sect_debuginfo = section;
else if (!strcasecmp(sectname, ".debug_str")) sect_debugstr = section;
else if (!strcasecmp(sectname, ".debug_abbrev")) sect_debugabbrev = section;
else if (!strcasecmp(sectname, ".debug_line")) sect_debugline = section;
else if (!strcasecmp(sectname, ".debug_loc")) sect_debugloc = section;
}
if (sect_debuginfo)
{
ret = dwarf2_parse(module,
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
NULL, /* FIXME: some thunks to deal with ? */
pe_get_sect(nth, mapping, sect_debuginfo), pe_get_sect_size(sect_debuginfo),
pe_get_sect(nth, mapping, sect_debugabbrev), pe_get_sect_size(sect_debugabbrev),
pe_get_sect(nth, mapping, sect_debugstr), pe_get_sect_size(sect_debugstr),
pe_get_sect(nth, mapping, sect_debugline), pe_get_sect_size(sect_debugline),
pe_get_sect(nth, mapping, sect_debugloc), pe_get_sect_size(sect_debugloc));
}
TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load");
return ret;
}
@ -133,7 +316,7 @@ static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module,
*/
static BOOL pe_load_msc_debug_info(const struct process* pcs,
struct module* module,
void* mapping, IMAGE_NT_HEADERS* nth)
void* mapping, const IMAGE_NT_HEADERS* nth)
{
BOOL ret = FALSE;
const IMAGE_DATA_DIRECTORY* dir;
@ -181,7 +364,7 @@ static BOOL pe_load_msc_debug_info(const struct process* pcs,
*/
static BOOL pe_load_export_debug_info(const struct process* pcs,
struct module* module,
void* mapping, IMAGE_NT_HEADERS* nth)
void* mapping, const IMAGE_NT_HEADERS* nth)
{
unsigned int i;
const IMAGE_EXPORT_DIRECTORY* exports;
@ -193,14 +376,12 @@ static BOOL pe_load_export_debug_info(const struct process* pcs,
#if 0
/* Add start of DLL (better use the (yet unimplemented) Exe SymTag for this) */
/* FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */
symt_new_public(module, NULL, module->module.ModuleName, base, 1,
TRUE /* FIXME */, TRUE /* FIXME */);
symt_new_public(module, NULL, module->module.ModuleName, base, 1);
#endif
/* Add entry point */
symt_new_public(module, NULL, "EntryPoint",
base + nth->OptionalHeader.AddressOfEntryPoint, 1,
TRUE, TRUE);
base + nth->OptionalHeader.AddressOfEntryPoint, 1);
#if 0
/* FIXME: we'd better store addresses linked to sections rather than
absolute values */
@ -211,8 +392,7 @@ static BOOL pe_load_export_debug_info(const struct process* pcs,
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
symt_new_public(module, NULL, section->Name,
RtlImageRvaToVa(nth, mapping, section->VirtualAddress, NULL),
1, TRUE /* FIXME */, TRUE /* FIXME */);
RtlImageRvaToVa(nth, mapping, section->VirtualAddress, NULL), 1);
}
#endif
@ -237,8 +417,7 @@ static BOOL pe_load_export_debug_info(const struct process* pcs,
if (!names[i]) continue;
symt_new_public(module, NULL,
RtlImageRvaToVa(nth, mapping, names[i], NULL),
base + functions[ordinals[i]],
1, TRUE /* FIXME */, TRUE /* FIXME */);
base + functions[ordinals[i]], 1);
}
for (i = 0; i < exports->NumberOfFunctions; i++)
@ -249,8 +428,7 @@ static BOOL pe_load_export_debug_info(const struct process* pcs,
if ((ordinals[j] == i) && names[j]) break;
if (j < exports->NumberOfNames) continue;
snprintf(buffer, sizeof(buffer), "%d", i + exports->Base);
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 1,
TRUE /* FIXME */, TRUE /* FIXME */);
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 1);
}
}
}
@ -284,7 +462,9 @@ BOOL pe_load_debug_info(const struct process* pcs, struct module* module)
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
{
ret = pe_load_stabs(pcs, module, mapping, nth) ||
pe_load_msc_debug_info(pcs, module, mapping, nth);
pe_load_dwarf(pcs, module, mapping, nth) ||
pe_load_msc_debug_info(pcs, module, mapping, nth) ||
pe_load_coff_symbol_table(module, nth, mapping);
/* if we still have no debug info (we could only get SymExport at this
* point), then do the SymExport except if we have an ELF container,
* in which case we'll rely on the export's on the ELF side
@ -367,13 +547,13 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name,
* pe_load_nt_header
*
*/
BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth)
BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth)
{
IMAGE_DOS_HEADER dos;
return ReadProcessMemory(hProc, (char*)base, &dos, sizeof(dos), NULL) &&
return ReadProcessMemory(hProc, (char*)(DWORD_PTR)base, &dos, sizeof(dos), NULL) &&
dos.e_magic == IMAGE_DOS_SIGNATURE &&
ReadProcessMemory(hProc, (char*)(base + dos.e_lfanew),
ReadProcessMemory(hProc, (char*)(DWORD_PTR)(base + dos.e_lfanew),
nth, sizeof(*nth), NULL) &&
nth->Signature == IMAGE_NT_SIGNATURE;
}
@ -383,7 +563,7 @@ BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth)
*
*/
struct module* pe_load_builtin_module(struct process* pcs, const WCHAR* name,
DWORD base, DWORD size)
DWORD64 base, DWORD64 size)
{
struct module* module = NULL;
@ -435,7 +615,7 @@ PVOID WINAPI ImageDirectoryEntryToDataEx( PVOID base, BOOLEAN image, USHORT dir,
*size = nt->OptionalHeader.DataDirectory[dir].Size;
if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)base + addr;
return RtlImageRvaToVa( nt, (HMODULE)base, addr, section );
return RtlImageRvaToVa( nt, base, addr, section );
}
/***********************************************************************

View file

@ -309,42 +309,6 @@ SymGetHomeDirectoryW(DWORD dwType,
return NULL;
}
BOOL WINAPI
SymGetLineFromName64(HANDLE hProcess,
PCSTR pszModuleName,
PCSTR pszFileName,
DWORD dwLineNumber,
PLONG plDisplacement,
PIMAGEHLP_LINE64 Line)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetLineFromName(HANDLE hProcess,
PCSTR pszModuleName,
PCSTR pszFileName,
DWORD dwLineNumber,
PLONG plDisplacement,
PIMAGEHLP_LINE Line)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetLineFromNameW64(HANDLE hProcess,
PCWSTR pszModuleName,
PCWSTR pszFileName,
DWORD dwLineNumber,
PLONG lpDisplacement,
PIMAGEHLP_LINEW64 Line)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetLineNextW64(HANDLE hProcess,
PIMAGEHLP_LINEW64 Line)
@ -459,31 +423,6 @@ SymGetSourceVarFromTokenW(
return FALSE;
}
BOOL WINAPI
SymGetSymFromName64(HANDLE hProcess,
PCSTR pszName,
PIMAGEHLP_SYMBOL64 Symbol)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetSymNext64(HANDLE hProcess,
PIMAGEHLP_SYMBOL64 Symbol)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetSymPrev64(HANDLE hProcess,
PIMAGEHLP_SYMBOL64 Symbol)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetSymbolFile(HANDLE hProcess,
PCSTR pszSymPath,
@ -581,16 +520,6 @@ SymPrevW(HANDLE hProcess,
return FALSE;
}
BOOL
WINAPI
SymRefreshModuleList(
HANDLE hProcess)
{
UNIMPLEMENTED;
return FALSE;
}
PCHAR WINAPI
SymSetHomeDirectory(HANDLE hProcess,
PCSTR pszDir)
@ -766,15 +695,6 @@ SymSrvStoreSupplementW(HANDLE hProcess,
return NULL;
}
BOOL WINAPI
SymUnDName64(PIMAGEHLP_SYMBOL64 Symbol,
PSTR pszUndecoratedName,
DWORD dwUndecoratedNameLength)
{
UNIMPLEMENTED;
return FALSE;
}
DWORD WINAPI
UnDecorateSymbolNameW(PCWSTR DecoratedName,
PWSTR pszUnDecoratedName,

View file

@ -26,9 +26,6 @@
#include "dbghelp_private.h"
#include "wine/debug.h"
#ifdef HAVE_REGEX_H
# include <regex.h>
#endif
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
@ -79,13 +76,18 @@ unsigned source_new(struct module* module, const char* base, const char* name)
int len = strlen(full) + 1;
if (module->sources_used + len + 1 > module->sources_alloc)
{
/* Alloc by block of 256 bytes */
module->sources_alloc = (module->sources_used + len + 1 + 255) & ~255;
if (!module->sources)
{
module->sources_alloc = (module->sources_used + len + 1 + 255) & ~255;
module->sources = HeapAlloc(GetProcessHeap(), 0, module->sources_alloc);
}
else
{
module->sources_alloc = max( module->sources_alloc * 2,
(module->sources_used + len + 1 + 255) & ~255 );
module->sources = HeapReAlloc(GetProcessHeap(), 0, module->sources,
module->sources_alloc);
}
}
ret = module->sources_used;
memcpy(module->sources + module->sources_used, full, len);
@ -154,116 +156,6 @@ BOOL WINAPI SymEnumSourceFiles(HANDLE hProcess, ULONG64 ModBase, PCSTR Mask,
return TRUE;
}
static inline void re_append(char** mask, unsigned* len, char ch)
{
*mask = HeapReAlloc(GetProcessHeap(), 0, *mask, ++(*len));
(*mask)[*len - 2] = ch;
}
static BOOL compile_regex(regex_t* re, const char* srcfile)
{
char* mask;
unsigned len = 1;
mask = HeapAlloc(GetProcessHeap(), 0, 1);
re_append(&mask, &len, '^');
if (!srcfile || !*srcfile) re_append(&mask, &len, '*');
else while (*srcfile)
{
switch (*srcfile)
{
case '\\':
case '/':
re_append(&mask, &len, '[');
re_append(&mask, &len, '\\');
re_append(&mask, &len, '\\');
re_append(&mask, &len, '/');
re_append(&mask, &len, ']');
break;
case '.':
re_append(&mask, &len, '\\');
re_append(&mask, &len, '.');
break;
default:
re_append(&mask, &len, *srcfile);
break;
}
srcfile++;
}
re_append(&mask, &len, '$');
mask[len - 1] = '\0';
len = regcomp(re, mask, REG_NOSUB);
HeapFree(GetProcessHeap(), 0, mask);
if (len)
{
FIXME("Couldn't compile %s\n", mask);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
/******************************************************************
* SymEnumLines (DBGHELP.@)
*
*/
BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland,
PCSTR srcfile, PSYM_ENUMLINES_CALLBACK cb, PVOID user)
{
struct module_pair pair;
struct hash_table_iter hti;
struct symt_ht* sym;
regex_t re;
struct line_info* dli;
void* ptr;
SRCCODEINFO sci;
const char* file;
if (!cb) return FALSE;
if (!(dbghelp_options & SYMOPT_LOAD_LINES)) return TRUE;
pair.pcs = process_find_by_handle(hProcess);
if (!pair.pcs) return FALSE;
if (compiland) FIXME("Unsupported yet (filtering on compiland %s)\n", compiland);
pair.requested = module_find_by_addr(pair.pcs, base, DMT_UNKNOWN);
if (!module_get_debug(&pair)) return FALSE;
if (!compile_regex(&re, srcfile)) return FALSE;
sci.SizeOfStruct = sizeof(sci);
sci.ModBase = base;
hash_table_iter_init(&pair.effective->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti)))
{
unsigned int i;
sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
if (sym->symt.tag != SymTagFunction) continue;
sci.FileName[0] = '\0';
for (i=0; i<vector_length(&((struct symt_function*)sym)->vlines); i++)
{
dli = vector_at(&((struct symt_function*)sym)->vlines, i);
if (dli->is_source_file)
{
file = source_get(pair.effective, dli->u.source_file);
if (regexec(&re, file, 0, NULL, 0) != 0) file = "";
strcpy(sci.FileName, file);
}
else if (sci.FileName[0])
{
sci.Key = dli;
sci.Obj[0] = '\0'; /* FIXME */
sci.LineNumber = dli->line_number;
sci.Address = dli->u.pc_offset;
if (!cb(&sci, user)) break;
}
}
}
regfree(&re);
return TRUE;
}
/******************************************************************
* SymGetSourceFileToken (DBGHELP.@)
*

View file

@ -26,7 +26,7 @@
* The "stabs" debug format
* by Julia Menapace, Jim Kingdon, David Mackenzie
* of Cygnus Support
* available (hopefully) from http:\\sources.redhat.com\gdb\onlinedocs
* available (hopefully) from http://sources.redhat.com/gdb/onlinedocs
*/
#include "config.h"
@ -53,6 +53,10 @@
#include <assert.h>
#include <stdarg.h>
#ifdef HAVE_MACH_O_NLIST_H
# include <mach-o/nlist.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
@ -65,9 +69,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
#define strtoull _strtoui64
/* Masks for n_type field */
#ifndef N_STAB
#define N_STAB 0xe0
#endif
#ifndef N_TYPE
#define N_TYPE 0x1e
#endif
#ifndef N_EXT
#define N_EXT 0x01
#endif
/* Values for (n_type & N_TYPE) */
#ifndef N_UNDF
#define N_UNDF 0x00
#endif
#ifndef N_ABS
#define N_ABS 0x02
#endif
#define N_GSYM 0x20
#define N_FUN 0x24
@ -81,6 +100,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
#define N_SLINE 0x44
#define N_ENSYM 0x4e
#define N_SO 0x64
#define N_OSO 0x66
#define N_LSYM 0x80
#define N_BINCL 0x82
#define N_SOL 0x84
@ -162,14 +182,18 @@ static int stabs_new_include(const char* file, unsigned long val)
{
if (num_include_def == num_alloc_include_def)
{
num_alloc_include_def += 256;
if (!include_defs)
include_defs = HeapAlloc(GetProcessHeap(), 0,
{
num_alloc_include_def = 256;
include_defs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(include_defs[0]) * num_alloc_include_def);
}
else
include_defs = HeapReAlloc(GetProcessHeap(), 0, include_defs,
{
num_alloc_include_def *= 2;
include_defs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, include_defs,
sizeof(include_defs[0]) * num_alloc_include_def);
memset(include_defs + num_include_def, 0, sizeof(include_defs[0]) * 256);
}
}
include_defs[num_include_def].name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(file) + 1), file);
include_defs[num_include_def].value = val;
@ -244,13 +268,13 @@ static struct symt** stabs_find_ref(long filenr, long subnr)
{
if (cu_nrofentries <= subnr)
{
cu_nrofentries = max( cu_nrofentries * 2, subnr + 1 );
if (!cu_vector)
cu_vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(cu_vector[0]) * (subnr+1));
cu_vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(cu_vector[0]) * cu_nrofentries);
else
cu_vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
cu_vector, sizeof(cu_vector[0]) * (subnr+1));
cu_nrofentries = subnr + 1;
cu_vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
cu_vector, sizeof(cu_vector[0]) * cu_nrofentries);
}
ret = &cu_vector[subnr];
}
@ -263,13 +287,13 @@ static struct symt** stabs_find_ref(long filenr, long subnr)
if (idef->nrofentries <= subnr)
{
idef->nrofentries = max( idef->nrofentries * 2, subnr + 1 );
if (!idef->vector)
idef->vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(idef->vector[0]) * (subnr+1));
idef->vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(idef->vector[0]) * idef->nrofentries);
else
idef->vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
idef->vector, sizeof(idef->vector[0]) * (subnr+1));
idef->nrofentries = subnr + 1;
idef->vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
idef->vector, sizeof(idef->vector[0]) * idef->nrofentries);
}
ret = &idef->vector[subnr];
}
@ -630,25 +654,21 @@ static inline int stabs_pts_read_aggregate(struct ParseTypedefData* ptd,
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &adt) == -1);
if (doadd)
if (doadd && adt)
{
char tmp[256];
WCHAR* name;
DWORD64 size;
symt_get_info(adt, TI_GET_SYMNAME, &name);
strcpy(tmp, "__inherited_class_");
WideCharToMultiByte(CP_ACP, 0, name, -1,
tmp + strlen(tmp), sizeof(tmp) - strlen(tmp),
NULL, NULL);
HeapFree(GetProcessHeap(), 0, name);
strcat(tmp, symt_get_name(adt));
/* FIXME: TI_GET_LENGTH will not always work, especially when adt
* has just been seen as a forward definition and not the real stuff
* yet.
* As we don't use much the size of members in structs, this may not
* be much of a problem
*/
symt_get_info(adt, TI_GET_LENGTH, &size);
symt_get_info(ptd->module, adt, TI_GET_LENGTH, &size);
symt_add_udt_element(ptd->module, sdt, tmp, adt, ofs, (DWORD)size * 8);
}
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
@ -1094,6 +1114,12 @@ static struct symt* stabs_parse_type(const char* stab)
return *stabs_read_type_enum(&c);
}
enum pending_obj_kind
{
PENDING_VAR,
PENDING_LINE,
};
struct pending_loc_var
{
char name[256];
@ -1102,44 +1128,99 @@ struct pending_loc_var
struct location loc;
};
struct pending_block
struct pending_line
{
struct pending_loc_var* vars;
int source_idx;
int line_num;
unsigned long offset;
unsigned long load_offset;
};
struct pending_object
{
enum pending_obj_kind tag;
union {
struct pending_loc_var var;
struct pending_line line;
} u;
};
struct pending_list
{
struct pending_object* objs;
unsigned num;
unsigned allocated;
};
static inline void pending_add(struct pending_block* pending, const char* name,
enum DataKind dt, const struct location* loc)
static inline void pending_make_room(struct pending_list* pending)
{
if (pending->num == pending->allocated)
{
pending->allocated += 8;
if (!pending->vars)
pending->vars = HeapAlloc(GetProcessHeap(), 0,
pending->allocated * sizeof(pending->vars[0]));
else
pending->vars = HeapReAlloc(GetProcessHeap(), 0, pending->vars,
pending->allocated * sizeof(pending->vars[0]));
if (!pending->objs)
{
pending->allocated = 8;
pending->objs = HeapAlloc(GetProcessHeap(), 0,
pending->allocated * sizeof(pending->objs[0]));
}
else
{
pending->allocated *= 2;
pending->objs = HeapReAlloc(GetProcessHeap(), 0, pending->objs,
pending->allocated * sizeof(pending->objs[0]));
}
}
stab_strcpy(pending->vars[pending->num].name,
sizeof(pending->vars[pending->num].name), name);
pending->vars[pending->num].type = stabs_parse_type(name);
pending->vars[pending->num].kind = dt;
pending->vars[pending->num].loc = *loc;
}
static inline void pending_add_var(struct pending_list* pending, const char* name,
enum DataKind dt, const struct location* loc)
{
pending_make_room(pending);
pending->objs[pending->num].tag = PENDING_VAR;
stab_strcpy(pending->objs[pending->num].u.var.name,
sizeof(pending->objs[pending->num].u.var.name), name);
pending->objs[pending->num].u.var.type = stabs_parse_type(name);
pending->objs[pending->num].u.var.kind = dt;
pending->objs[pending->num].u.var.loc = *loc;
pending->num++;
}
static void pending_flush(struct pending_block* pending, struct module* module,
static inline void pending_add_line(struct pending_list* pending, int source_idx,
int line_num, unsigned long offset,
unsigned long load_offset)
{
pending_make_room(pending);
pending->objs[pending->num].tag = PENDING_LINE;
pending->objs[pending->num].u.line.source_idx = source_idx;
pending->objs[pending->num].u.line.line_num = line_num;
pending->objs[pending->num].u.line.offset = offset;
pending->objs[pending->num].u.line.load_offset = load_offset;
pending->num++;
}
static void pending_flush(struct pending_list* pending, struct module* module,
struct symt_function* func, struct symt_block* block)
{
unsigned int i;
for (i = 0; i < pending->num; i++)
{
symt_add_func_local(module, func,
pending->vars[i].kind, &pending->vars[i].loc,
block, pending->vars[i].type, pending->vars[i].name);
switch (pending->objs[i].tag)
{
case PENDING_VAR:
symt_add_func_local(module, func,
pending->objs[i].u.var.kind, &pending->objs[i].u.var.loc,
block, pending->objs[i].u.var.type, pending->objs[i].u.var.name);
break;
case PENDING_LINE:
if (module->type == DMT_MACHO)
pending->objs[i].u.line.offset -= func->address - pending->objs[i].u.line.load_offset;
symt_add_func_line(module, func, pending->objs[i].u.line.source_idx,
pending->objs[i].u.line.line_num, pending->objs[i].u.line.offset);
break;
default:
ERR("Unknown pending object tag %u\n", (unsigned)pending->objs[i].tag);
break;
}
}
pending->num = 0;
}
@ -1156,7 +1237,7 @@ static void pending_flush(struct pending_block* pending, struct module* module,
static void stabs_finalize_function(struct module* module, struct symt_function* func,
unsigned long size)
{
IMAGEHLP_LINE il;
IMAGEHLP_LINE64 il;
struct location loc;
if (!func) return;
@ -1175,9 +1256,25 @@ static void stabs_finalize_function(struct module* module, struct symt_function*
if (size) func->size = size;
}
static inline void stabbuf_append(char **buf, unsigned *buf_size, const char *str)
{
unsigned str_len, buf_len;
str_len = strlen(str);
buf_len = strlen(*buf);
if(str_len+buf_len >= *buf_size) {
*buf_size += buf_len + str_len;
*buf = HeapReAlloc(GetProcessHeap(), 0, *buf, *buf_size);
}
strcpy(*buf+buf_len, str);
}
BOOL stabs_parse(struct module* module, unsigned long load_offset,
const void* pv_stab_ptr, int stablen,
const char* strs, int strtablen)
const char* strs, int strtablen,
stabs_def_cb callback, void* user)
{
struct symt_function* curr_func = NULL;
struct symt_block* block = NULL;
@ -1195,16 +1292,19 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
unsigned incl[32];
int incl_stk = -1;
int source_idx = -1;
struct pending_block pending;
struct pending_list pending_block;
struct pending_list pending_func;
BOOL ret = TRUE;
struct location loc;
unsigned char type;
nstab = stablen / sizeof(struct stab_nlist);
strs_end = strs + strtablen;
memset(srcpath, 0, sizeof(srcpath));
memset(stabs_basic, 0, sizeof(stabs_basic));
memset(&pending, 0, sizeof(pending));
memset(&pending_block, 0, sizeof(pending_block));
memset(&pending_func, 0, sizeof(pending_func));
/*
* Allocate a buffer into which we can build stab strings for cases
@ -1230,23 +1330,22 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
* next record. Repeat the process until we find a stab without the
* '/' character, as this indicates we have the whole thing.
*/
unsigned len = strlen(ptr);
if (strlen(stabbuff) + len > stabbufflen)
{
stabbufflen += 65536;
stabbuff = HeapReAlloc(GetProcessHeap(), 0, stabbuff, stabbufflen);
}
strncat(stabbuff, ptr, len - 1);
stabbuf_append(&stabbuff, &stabbufflen, ptr);
continue;
}
else if (stabbuff[0] != '\0')
{
strcat(stabbuff, ptr);
stabbuf_append(&stabbuff, &stabbufflen, ptr);
ptr = stabbuff;
}
if (stab_ptr->n_type & N_STAB)
type = stab_ptr->n_type;
else
type = (stab_ptr->n_type & N_TYPE);
/* only symbol entries contain a typedef */
switch (stab_ptr->n_type)
switch (type)
{
case N_GSYM:
case N_LCSYM:
@ -1263,7 +1362,8 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
*/
if (ptr != stabbuff)
{
strcpy(stabbuff, ptr);
stabbuff[0] = 0;
stabbuf_append(&stabbuff, &stabbufflen, ptr);
ptr = stabbuff;
}
stab_strcpy(symname, sizeof(symname), ptr);
@ -1276,7 +1376,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
}
}
switch (stab_ptr->n_type)
switch (type)
{
case N_GSYM:
/*
@ -1305,7 +1405,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
{
block = symt_open_func_block(module, curr_func, block,
stab_ptr->n_value, 0);
pending_flush(&pending, module, curr_func, block);
pending_flush(&pending_block, module, curr_func, block);
}
break;
case N_RBRAC:
@ -1356,6 +1456,22 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
case 17:
case 18:
case 19: loc.reg = CV_REG_ST0 + stab_ptr->n_value - 12; break;
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28: loc.reg = CV_REG_XMM0 + stab_ptr->n_value - 21; break;
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36: loc.reg = CV_REG_MM0 + stab_ptr->n_value - 29; break;
default:
FIXME("Unknown register value (%lu)\n", stab_ptr->n_value);
loc.reg = CV_REG_NONE;
@ -1373,7 +1489,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
param_type);
}
else
pending_add(&pending, ptr, DataIsLocal, &loc);
pending_add_var(&pending_block, ptr, DataIsLocal, &loc);
}
break;
case N_LSYM:
@ -1381,19 +1497,24 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
loc.kind = loc_regrel;
loc.reg = 0; /* FIXME */
loc.offset = stab_ptr->n_value;
if (curr_func != NULL) pending_add(&pending, ptr, DataIsLocal, &loc);
if (curr_func != NULL) pending_add_var(&pending_block, ptr, DataIsLocal, &loc);
break;
case N_SLINE:
/*
* This is a line number. These are always relative to the start
* of the function (N_FUN), and this makes the lookup easier.
*/
assert(source_idx >= 0);
if (curr_func != NULL)
{
assert(source_idx >= 0);
unsigned long offset = stab_ptr->n_value;
if (module->type == DMT_MACHO)
offset -= curr_func->address - load_offset;
symt_add_func_line(module, curr_func, source_idx,
stab_ptr->n_desc, stab_ptr->n_value);
stab_ptr->n_desc, offset);
}
else pending_add_line(&pending_func, source_idx, stab_ptr->n_desc,
stab_ptr->n_value, load_offset);
break;
case N_FUN:
/*
@ -1428,6 +1549,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
curr_func = symt_new_function(module, compiland, symname,
load_offset + stab_ptr->n_value, 0,
&func_type->symt);
pending_flush(&pending_func, module, curr_func, NULL);
}
else
{
@ -1508,10 +1630,38 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
break;
case N_BNSYM:
case N_ENSYM:
case N_OSO:
/* Always ignore these, they seem to be used only on Darwin. */
break;
case N_ABS:
#ifdef N_SECT
case N_SECT:
#endif
/* FIXME: Other definition types (N_TEXT, N_DATA, N_BSS, ...)? */
if (callback)
{
BOOL is_public = (stab_ptr->n_type & N_EXT);
BOOL is_global = is_public;
#ifdef N_PEXT
/* "private extern"; shared among compilation units in a shared
* library, but not accessible from outside the library. */
if (stab_ptr->n_type & N_PEXT)
{
is_public = FALSE;
is_global = TRUE;
}
#endif
if (*ptr == '_') ptr++;
stab_strcpy(symname, sizeof(symname), ptr);
callback(module, load_offset, symname, stab_ptr->n_value,
is_public, is_global, stab_ptr->n_other, compiland, user);
}
break;
default:
ERR("Unknown stab type 0x%02x\n", stab_ptr->n_type);
ERR("Unknown stab type 0x%02x\n", type);
break;
}
stabbuff[0] = '\0';
@ -1529,7 +1679,8 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
done:
HeapFree(GetProcessHeap(), 0, stabbuff);
stabs_free_includes();
HeapFree(GetProcessHeap(), 0, pending.vars);
HeapFree(GetProcessHeap(), 0, pending_block.objs);
HeapFree(GetProcessHeap(), 0, pending_func.objs);
return ret;
}

View file

@ -27,40 +27,45 @@
#include <string.h>
#include <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h"
#include "winternl.h"
#include "wine/winbase16.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
static const char* wine_dbgstr_addr(const ADDRESS* addr)
static DWORD64 WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS64* addr)
{
if (!addr) return "(null)";
LDT_ENTRY le;
switch (addr->Mode)
{
case AddrModeFlat:
return wine_dbg_sprintf("flat<%08x>", addr->Offset);
case AddrMode1616:
return wine_dbg_sprintf("1616<%04x:%04x>", addr->Segment, addr->Offset);
if (GetThreadSelectorEntry(hThread, addr->Segment, &le))
return (le.HighWord.Bits.BaseHi << 24) +
(le.HighWord.Bits.BaseMid << 16) + le.BaseLow + LOWORD(addr->Offset);
break;
case AddrMode1632:
return wine_dbg_sprintf("1632<%04x:%08x>", addr->Segment, addr->Offset);
if (GetThreadSelectorEntry(hThread, addr->Segment, &le))
return (le.HighWord.Bits.BaseHi << 24) +
(le.HighWord.Bits.BaseMid << 16) + le.BaseLow + addr->Offset;
break;
case AddrModeReal:
return wine_dbg_sprintf("real<%04x:%04x>", addr->Segment, addr->Offset);
return (DWORD)(LOWORD(addr->Segment) << 4) + addr->Offset;
case AddrModeFlat:
return addr->Offset;
default:
return "unknown";
FIXME("Unsupported (yet) mode (%x)\n", addr->Mode);
return 0;
}
FIXME("Failed to linearize address %04x:%s (mode %x)\n",
addr->Segment, wine_dbgstr_longlong(addr->Offset), addr->Mode);
return 0;
}
static BOOL CALLBACK read_mem(HANDLE hProcess, DWORD addr, void* buffer,
DWORD size, LPDWORD nread)
{
SIZE_T r;
if (!ReadProcessMemory(hProcess, (void*)addr, buffer, size, &r)) return FALSE;
if (!ReadProcessMemory(hProcess, (void*)(DWORD_PTR)addr, buffer, size, &r)) return FALSE;
if (nread) *nread = r;
return TRUE;
}
@ -74,39 +79,6 @@ static BOOL CALLBACK read_mem64(HANDLE hProcess, DWORD64 addr, void* buffer,
return TRUE;
}
/* indexes in Reserved array */
#define __CurrentMode 0
#define __CurrentSwitch 1
#define __NextSwitch 2
#define curr_mode (frame->Reserved[__CurrentMode])
#define curr_switch (frame->Reserved[__CurrentSwitch])
#define next_switch (frame->Reserved[__NextSwitch])
struct stack_walk_callback
{
HANDLE hProcess;
HANDLE hThread;
BOOL is32;
union
{
struct
{
PREAD_PROCESS_MEMORY_ROUTINE f_read_mem;
PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr;
PFUNCTION_TABLE_ACCESS_ROUTINE f_tabl_acs;
PGET_MODULE_BASE_ROUTINE f_modl_bas;
} s32;
struct
{
PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem;
PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr;
PFUNCTION_TABLE_ACCESS_ROUTINE64 f_tabl_acs;
PGET_MODULE_BASE_ROUTINE64 f_modl_bas;
} s64;
} u;
};
static inline void addr_32to64(const ADDRESS* addr32, ADDRESS64* addr64)
{
addr64->Offset = (ULONG64)addr32->Offset;
@ -121,379 +93,113 @@ static inline void addr_64to32(const ADDRESS64* addr64, ADDRESS* addr32)
addr32->Mode = addr64->Mode;
}
static inline BOOL sw_read_mem(struct stack_walk_callback* cb, DWORD addr, void* ptr, DWORD sz)
BOOL sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz)
{
if (cb->is32)
return cb->u.s32.f_read_mem(cb->hProcess, addr, ptr, sz, NULL);
if (csw->is32)
return csw->u.s32.f_read_mem(csw->hProcess, addr, ptr, sz, NULL);
else
return cb->u.s64.f_read_mem(cb->hProcess, addr, ptr, sz, NULL);
return csw->u.s64.f_read_mem(csw->hProcess, addr, ptr, sz, NULL);
}
static inline DWORD sw_xlat_addr(struct stack_walk_callback* cb, ADDRESS* addr)
DWORD64 sw_xlat_addr(struct cpu_stack_walk* csw, ADDRESS64* addr)
{
if (addr->Mode == AddrModeFlat) return addr->Offset;
if (cb->is32) return cb->u.s32.f_xlat_adr(cb->hProcess, cb->hThread, addr);
if (cb->u.s64.f_xlat_adr)
if (csw->is32)
{
ADDRESS64 addr64;
ADDRESS addr32;
addr_32to64(addr, &addr64);
return cb->u.s64.f_xlat_adr(cb->hProcess, cb->hThread, &addr64);
addr_64to32(addr, &addr32);
return csw->u.s32.f_xlat_adr(csw->hProcess, csw->hThread, &addr32);
}
return addr_to_linear(cb->hProcess, cb->hThread, addr);
else if (csw->u.s64.f_xlat_adr)
return csw->u.s64.f_xlat_adr(csw->hProcess, csw->hThread, addr);
return addr_to_linear(csw->hProcess, csw->hThread, addr);
}
static inline void* sw_tabl_acs(struct stack_walk_callback* cb, DWORD addr)
void* sw_table_access(struct cpu_stack_walk* csw, DWORD64 addr)
{
if (cb->is32)
return cb->u.s32.f_tabl_acs(cb->hProcess, addr);
if (csw->is32)
return csw->u.s32.f_tabl_acs(csw->hProcess, addr);
else
return cb->u.s64.f_tabl_acs(cb->hProcess, addr);
return csw->u.s64.f_tabl_acs(csw->hProcess, addr);
}
static inline DWORD sw_modl_bas(struct stack_walk_callback* cb, DWORD addr)
DWORD64 sw_module_base(struct cpu_stack_walk* csw, DWORD64 addr)
{
if (cb->is32)
return cb->u.s32.f_modl_bas(cb->hProcess, addr);
if (csw->is32)
return csw->u.s32.f_modl_bas(csw->hProcess, addr);
else
return cb->u.s64.f_modl_bas(cb->hProcess, addr);
}
static BOOL stack_walk(struct stack_walk_callback* cb, LPSTACKFRAME frame)
{
STACK32FRAME frame32;
STACK16FRAME frame16;
char ch;
ADDRESS tmp;
DWORD p;
WORD val;
BOOL do_switch;
/* sanity check */
if (curr_mode >= stm_done) return FALSE;
TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%08x nSwitch=%08x\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
curr_switch, next_switch);
if (curr_mode == stm_start)
{
THREAD_BASIC_INFORMATION info;
if ((frame->AddrPC.Mode == AddrModeFlat) &&
(frame->AddrFrame.Mode != AddrModeFlat))
{
WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
goto done_err;
}
/* Init done */
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ?
stm_32bit : stm_16bit;
/* cur_switch holds address of WOW32Reserved field in TEB in debuggee
* address space
*/
if (NtQueryInformationThread(cb->hThread, ThreadBasicInformation, &info,
sizeof(info), NULL) == STATUS_SUCCESS)
{
curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, WOW32Reserved);
if (!sw_read_mem(cb, curr_switch, &next_switch, sizeof(next_switch)))
{
WARN("Can't read TEB:WOW32Reserved\n");
goto done_err;
}
if (curr_mode == stm_16bit)
{
if (!sw_read_mem(cb, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame 0x%08x\n", next_switch);
goto done_err;
}
curr_switch = (DWORD)frame32.frame16;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(curr_switch);
tmp.Offset = OFFSETOF(curr_switch);
if (!sw_read_mem(cb, sw_xlat_addr(cb, &tmp), &ch, sizeof(ch)))
curr_switch = 0xFFFFFFFF;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(cb, &tmp);
if (!sw_read_mem(cb, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
curr_switch = (DWORD)frame16.frame32;
if (!sw_read_mem(cb, curr_switch, &ch, sizeof(ch)))
curr_switch = 0xFFFFFFFF;
}
}
else
/* FIXME: this will allow to work when we're not attached to a live target,
* but the 16 <=> 32 switch facility won't be available.
*/
curr_switch = 0;
frame->AddrReturn.Mode = frame->AddrStack.Mode = (curr_mode == stm_16bit) ? AddrMode1616 : AddrModeFlat;
/* don't set up AddrStack on first call. Either the caller has set it up, or
* we will get it in the next frame
*/
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
}
else
{
if (frame->AddrFrame.Offset == 0) goto done_err;
if (frame->AddrFrame.Mode == AddrModeFlat)
{
assert(curr_mode == stm_32bit);
do_switch = curr_switch && frame->AddrFrame.Offset >= curr_switch;
}
else
{
assert(curr_mode == stm_16bit);
do_switch = curr_switch &&
frame->AddrFrame.Segment == SELECTOROF(curr_switch) &&
frame->AddrFrame.Offset >= OFFSETOF(curr_switch);
}
if (do_switch)
{
if (curr_mode == stm_16bit)
{
if (!sw_read_mem(cb, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame 0x%08x\n", next_switch);
goto done_err;
}
frame->AddrPC.Mode = AddrModeFlat;
frame->AddrPC.Segment = 0;
frame->AddrPC.Offset = frame32.retaddr;
frame->AddrFrame.Mode = AddrModeFlat;
frame->AddrFrame.Segment = 0;
frame->AddrFrame.Offset = frame32.ebp;
frame->AddrStack.Mode = AddrModeFlat;
frame->AddrStack.Segment = 0;
frame->AddrReturn.Mode = AddrModeFlat;
frame->AddrReturn.Segment = 0;
next_switch = curr_switch;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(cb, &tmp);
if (!sw_read_mem(cb, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
curr_switch = (DWORD)frame16.frame32;
curr_mode = stm_32bit;
if (!sw_read_mem(cb, curr_switch, &ch, sizeof(ch)))
curr_switch = 0;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(cb, &tmp);
if (!sw_read_mem(cb, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
TRACE("Got a 16 bit stack switch:"
"\n\tframe32: %08lx"
"\n\tedx:%08x ecx:%08x ebp:%08x"
"\n\tds:%04x es:%04x fs:%04x gs:%04x"
"\n\tcall_from_ip:%08x module_cs:%04x relay=%08x"
"\n\tentry_ip:%04x entry_point:%08x"
"\n\tbp:%04x ip:%04x cs:%04x\n",
(unsigned long)frame16.frame32,
frame16.edx, frame16.ecx, frame16.ebp,
frame16.ds, frame16.es, frame16.fs, frame16.gs,
frame16.callfrom_ip, frame16.module_cs, frame16.relay,
frame16.entry_ip, frame16.entry_point,
frame16.bp, frame16.ip, frame16.cs);
frame->AddrPC.Mode = AddrMode1616;
frame->AddrPC.Segment = frame16.cs;
frame->AddrPC.Offset = frame16.ip;
frame->AddrFrame.Mode = AddrMode1616;
frame->AddrFrame.Segment = SELECTOROF(next_switch);
frame->AddrFrame.Offset = frame16.bp;
frame->AddrStack.Mode = AddrMode1616;
frame->AddrStack.Segment = SELECTOROF(next_switch);
frame->AddrReturn.Mode = AddrMode1616;
frame->AddrReturn.Segment = frame16.cs;
next_switch = curr_switch;
if (!sw_read_mem(cb, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame 0x%08x\n", next_switch);
goto done_err;
}
curr_switch = (DWORD)frame32.frame16;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(curr_switch);
tmp.Offset = OFFSETOF(curr_switch);
if (!sw_read_mem(cb, sw_xlat_addr(cb, &tmp), &ch, sizeof(ch)))
curr_switch = 0;
curr_mode = stm_16bit;
}
}
else
{
frame->AddrPC = frame->AddrReturn;
if (curr_mode == stm_16bit)
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
/* "pop up" previous BP value */
if (!sw_read_mem(cb, sw_xlat_addr(cb, &frame->AddrFrame),
&val, sizeof(WORD)))
goto done_err;
frame->AddrFrame.Offset = val;
}
else
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
/* "pop up" previous EBP value */
if (!sw_read_mem(cb, frame->AddrFrame.Offset,
&frame->AddrFrame.Offset, sizeof(DWORD)))
goto done_err;
}
}
}
if (curr_mode == stm_16bit)
{
unsigned int i;
p = sw_xlat_addr(cb, &frame->AddrFrame);
if (!sw_read_mem(cb, p + sizeof(WORD), &val, sizeof(WORD)))
goto done_err;
frame->AddrReturn.Offset = val;
/* get potential cs if a far call was used */
if (!sw_read_mem(cb, p + 2 * sizeof(WORD), &val, sizeof(WORD)))
goto done_err;
if (frame->AddrFrame.Offset & 1)
frame->AddrReturn.Segment = val; /* far call assumed */
else
{
/* not explicitly marked as far call,
* but check whether it could be anyway
*/
if ((val & 7) == 7 && val != frame->AddrReturn.Segment)
{
LDT_ENTRY le;
if (GetThreadSelectorEntry(cb->hThread, val, &le) &&
(le.HighWord.Bits.Type & 0x08)) /* code segment */
{
/* it is very uncommon to push a code segment cs as
* a parameter, so this should work in most cases
*/
frame->AddrReturn.Segment = val;
}
}
}
frame->AddrFrame.Offset &= ~1;
/* we "pop" parameters as 16 bit entities... of course, this won't
* work if the parameter is in fact bigger than 16bit, but
* there's no way to know that here
*/
for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
{
sw_read_mem(cb, p + (2 + i) * sizeof(WORD), &val, sizeof(val));
frame->Params[i] = val;
}
}
else
{
if (!sw_read_mem(cb, frame->AddrFrame.Offset + sizeof(DWORD),
&frame->AddrReturn.Offset, sizeof(DWORD)))
{
WARN("Cannot read new frame offset %08x\n", frame->AddrFrame.Offset + (int)sizeof(DWORD));
goto done_err;
}
sw_read_mem(cb, frame->AddrFrame.Offset + 2 * sizeof(DWORD),
frame->Params, sizeof(frame->Params));
}
frame->Far = TRUE;
frame->Virtual = TRUE;
p = sw_xlat_addr(cb, &frame->AddrPC);
if (p && sw_modl_bas(cb, p))
frame->FuncTableEntry = sw_tabl_acs(cb, p);
else
frame->FuncTableEntry = NULL;
TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%08x nSwitch=%08x FuncTable=%p\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
curr_switch, next_switch, frame->FuncTableEntry);
return TRUE;
done_err:
curr_mode = stm_done;
return FALSE;
return csw->u.s64.f_modl_bas(csw->hProcess, addr);
}
/***********************************************************************
* StackWalk (DBGHELP.@)
*/
BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
LPSTACKFRAME frame, PVOID ctx,
LPSTACKFRAME frame32, PVOID ctx,
PREAD_PROCESS_MEMORY_ROUTINE f_read_mem,
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr)
{
struct stack_walk_callback swcb;
struct cpu_stack_walk csw;
STACKFRAME64 frame64;
BOOL ret;
struct cpu* cpu;
TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p)\n",
MachineType, hProcess, hThread, frame, ctx,
MachineType, hProcess, hThread, frame32, ctx,
f_read_mem, FunctionTableAccessRoutine,
GetModuleBaseRoutine, f_xlat_adr);
if (MachineType != IMAGE_FILE_MACHINE_I386)
if (!(cpu = cpu_find(MachineType)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
swcb.hProcess = hProcess;
swcb.hThread = hThread;
swcb.is32 = TRUE;
/* sigh... MS isn't even consistent in the func prototypes */
swcb.u.s32.f_read_mem = (f_read_mem) ? f_read_mem : read_mem;
swcb.u.s32.f_xlat_adr = (f_xlat_adr) ? f_xlat_adr : addr_to_linear;
swcb.u.s32.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess;
swcb.u.s32.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase;
addr_32to64(&frame32->AddrPC, &frame64.AddrPC);
addr_32to64(&frame32->AddrReturn, &frame64.AddrReturn);
addr_32to64(&frame32->AddrFrame, &frame64.AddrFrame);
addr_32to64(&frame32->AddrStack, &frame64.AddrStack);
addr_32to64(&frame32->AddrBStore, &frame64.AddrBStore);
frame64.FuncTableEntry = frame32->FuncTableEntry; /* FIXME */
frame64.Far = frame32->Far;
frame64.Virtual = frame32->Virtual;
frame64.Reserved[0] = frame32->Reserved[0];
frame64.Reserved[1] = frame32->Reserved[1];
frame64.Reserved[2] = frame32->Reserved[2];
/* we don't handle KdHelp */
return stack_walk(&swcb, frame);
csw.hProcess = hProcess;
csw.hThread = hThread;
csw.is32 = TRUE;
/* sigh... MS isn't even consistent in the func prototypes */
csw.u.s32.f_read_mem = (f_read_mem) ? f_read_mem : read_mem;
csw.u.s32.f_xlat_adr = f_xlat_adr;
csw.u.s32.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess;
csw.u.s32.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase;
if ((ret = cpu->stack_walk(&csw, &frame64)))
{
addr_64to32(&frame64.AddrPC, &frame32->AddrPC);
addr_64to32(&frame64.AddrReturn, &frame32->AddrReturn);
addr_64to32(&frame64.AddrFrame, &frame32->AddrFrame);
addr_64to32(&frame64.AddrStack, &frame32->AddrStack);
addr_64to32(&frame64.AddrBStore, &frame32->AddrBStore);
frame32->FuncTableEntry = frame64.FuncTableEntry; /* FIXME */
frame32->Params[0] = frame64.Params[0];
frame32->Params[1] = frame64.Params[1];
frame32->Params[2] = frame64.Params[2];
frame32->Params[3] = frame64.Params[3];
frame32->Far = frame64.Far;
frame32->Virtual = frame64.Virtual;
frame32->Reserved[0] = frame64.Reserved[0];
frame32->Reserved[1] = frame64.Reserved[1];
frame32->Reserved[2] = frame64.Reserved[2];
}
return ret;
}
@ -501,78 +207,49 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
* StackWalk64 (DBGHELP.@)
*/
BOOL WINAPI StackWalk64(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
LPSTACKFRAME64 frame64, PVOID ctx,
LPSTACKFRAME64 frame, PVOID ctx,
PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr)
{
struct stack_walk_callback swcb;
STACKFRAME frame32;
BOOL ret;
struct cpu_stack_walk csw;
struct cpu* cpu;
TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p)\n",
MachineType, hProcess, hThread, frame64, ctx,
MachineType, hProcess, hThread, frame, ctx,
f_read_mem, FunctionTableAccessRoutine,
GetModuleBaseRoutine, f_xlat_adr);
if (MachineType != IMAGE_FILE_MACHINE_I386)
if (!(cpu = cpu_find(MachineType)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
addr_64to32(&frame64->AddrPC, &frame32.AddrPC);
addr_64to32(&frame64->AddrReturn, &frame32.AddrReturn);
addr_64to32(&frame64->AddrFrame, &frame32.AddrFrame);
addr_64to32(&frame64->AddrStack, &frame32.AddrStack);
addr_64to32(&frame64->AddrBStore, &frame32.AddrBStore);
frame32.FuncTableEntry = frame64->FuncTableEntry; /* FIXME */
frame32.Far = frame64->Far;
frame32.Virtual = frame64->Virtual;
frame32.Reserved[0] = (ULONG)frame64->Reserved[0];
frame32.Reserved[1] = (ULONG)frame64->Reserved[1];
frame32.Reserved[2] = (ULONG)frame64->Reserved[2];
/* we don't handle KdHelp */
swcb.hProcess = hProcess;
swcb.hThread = hThread;
swcb.is32 = FALSE;
csw.hProcess = hProcess;
csw.hThread = hThread;
csw.is32 = FALSE;
/* sigh... MS isn't even consistent in the func prototypes */
swcb.u.s64.f_read_mem = (f_read_mem) ? f_read_mem : read_mem64;
swcb.u.s64.f_xlat_adr = f_xlat_adr;
swcb.u.s64.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess64;
swcb.u.s64.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase64;
csw.u.s64.f_read_mem = (f_read_mem) ? f_read_mem : read_mem64;
csw.u.s64.f_xlat_adr = (f_xlat_adr) ? f_xlat_adr : addr_to_linear;
csw.u.s64.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess64;
csw.u.s64.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase64;
ret = stack_walk(&swcb, &frame32);
if (!cpu->stack_walk(&csw, frame)) return FALSE;
addr_32to64(&frame32.AddrPC, &frame64->AddrPC);
addr_32to64(&frame32.AddrReturn, &frame64->AddrReturn);
addr_32to64(&frame32.AddrFrame, &frame64->AddrFrame);
addr_32to64(&frame32.AddrStack, &frame64->AddrStack);
addr_32to64(&frame32.AddrBStore, &frame64->AddrBStore);
frame64->FuncTableEntry = frame32.FuncTableEntry; /* FIXME */
frame64->Params[0] = frame32.Params[0];
frame64->Params[1] = frame32.Params[1];
frame64->Params[2] = frame32.Params[2];
frame64->Params[3] = frame32.Params[3];
frame64->Far = frame32.Far;
frame64->Virtual = frame32.Virtual;
frame64->Reserved[0] = frame32.Reserved[0];
frame64->Reserved[1] = frame32.Reserved[1];
frame64->Reserved[2] = frame32.Reserved[2];
/* we don't handle KdHelp */
frame64->KdHelp.Thread = 0xC000FADE;
frame64->KdHelp.ThCallbackStack = 0x10;
frame64->KdHelp.ThCallbackBStore = 0;
frame64->KdHelp.NextCallback = 0;
frame64->KdHelp.FramePointer = 0;
frame64->KdHelp.KiCallUserMode = 0xD000DAFE;
frame64->KdHelp.KeUserCallbackDispatcher = 0xE000F000;
frame64->KdHelp.SystemRangeStart = 0xC0000000;
frame64->KdHelp.Reserved[0] /* KiUserExceptionDispatcher */ = 0xE0005000;
frame->KdHelp.Thread = 0xC000FADE;
frame->KdHelp.ThCallbackStack = 0x10;
frame->KdHelp.ThCallbackBStore = 0;
frame->KdHelp.NextCallback = 0;
frame->KdHelp.FramePointer = 0;
frame->KdHelp.KiCallUserMode = 0xD000DAFE;
frame->KdHelp.KeUserCallbackDispatcher = 0xE000F000;
frame->KdHelp.SystemRangeStart = 0xC0000000;
frame->KdHelp.Reserved[0] /* KiUserExceptionDispatcher */ = 0xE0005000;
return ret;
return TRUE;
}
/******************************************************************

View file

@ -34,14 +34,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
struct pool_arena
{
struct pool_arena* next;
char* current;
struct list entry;
char *current;
char *end;
};
void pool_init(struct pool* a, unsigned arena_size)
void pool_init(struct pool* a, size_t arena_size)
{
list_init( &a->arena_list );
list_init( &a->arena_full );
a->arena_size = arena_size;
a->first = NULL;
}
void pool_destroy(struct pool* pool)
@ -50,58 +52,73 @@ void pool_destroy(struct pool* pool)
struct pool_arena* next;
#ifdef USE_STATS
unsigned alloc, used, num;
size_t alloc, used, num;
alloc = used = num = 0;
arena = pool->first;
while (arena)
LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry )
{
alloc += pool->arena_size;
alloc += arena->end - (char *)arena;
used += arena->current - (char*)arena;
num++;
}
LIST_FOR_EACH_ENTRY( arena, &pool->arena_full, struct pool_arena, entry )
{
alloc += arena->end - (char *)arena;
used += arena->current - (char*)arena;
num++;
arena = arena->next;
}
if (alloc == 0) alloc = 1; /* avoid division by zero */
FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n"
"\t\t\t\tnon-allocation ratio: %.2f%%\n",
pool, alloc >> 10, used >> 10, num, 100.0 - (float)used / (float)alloc * 100.0);
FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas, non-allocation ratio: %.2f%%\n",
pool, (unsigned)(alloc >> 10), (unsigned)(used >> 10), (unsigned)num,
100.0 - (float)used / (float)alloc * 100.0);
#endif
arena = pool->first;
while (arena)
LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_list, struct pool_arena, entry )
{
next = arena->next;
list_remove( &arena->entry );
HeapFree(GetProcessHeap(), 0, arena);
}
LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_full, struct pool_arena, entry )
{
list_remove( &arena->entry );
HeapFree(GetProcessHeap(), 0, arena);
arena = next;
}
pool_init(pool, 0);
}
void* pool_alloc(struct pool* pool, unsigned len)
void* pool_alloc(struct pool* pool, size_t len)
{
struct pool_arena* arena;
void* ret;
size_t size;
len = (len + 3) & ~3; /* round up size on DWORD boundary */
assert(sizeof(struct pool_arena) + len <= pool->arena_size && len);
for (arena = pool->first; arena; arena = arena->next)
LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry )
{
if ((char*)arena + pool->arena_size - arena->current >= len)
if (arena->end - arena->current >= len)
{
ret = arena->current;
arena->current += len;
if (arena->current + 16 >= arena->end)
{
list_remove( &arena->entry );
list_add_tail( &pool->arena_full, &arena->entry );
}
return ret;
}
}
arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size);
if (!arena) {ERR("OOM\n");return NULL;}
size = max( pool->arena_size, len );
arena = HeapAlloc(GetProcessHeap(), 0, size + sizeof(struct pool_arena));
if (!arena) return NULL;
ret = (char*)arena + sizeof(*arena);
arena->next = pool->first;
pool->first = arena;
ret = arena + 1;
arena->current = (char*)ret + len;
arena->end = (char*)ret + size;
if (arena->current + 16 >= arena->end)
list_add_tail( &pool->arena_full, &arena->entry );
else
list_add_head( &pool->arena_list, &arena->entry );
return ret;
}
@ -298,7 +315,7 @@ unsigned sparse_array_length(const struct sparse_array* sa)
return sa->elements.num_elts;
}
unsigned hash_table_hash(const char* name, unsigned num_buckets)
static unsigned hash_table_hash(const char* name, unsigned num_buckets)
{
unsigned hash = 0;
while (*name)

File diff suppressed because it is too large Load diff

View file

@ -304,6 +304,21 @@ struct symt_array* symt_new_array(struct module* module, int min, int max,
return sym;
}
static inline DWORD symt_array_count(struct module* module, const struct symt_array* array)
{
if (array->end < 0)
{
DWORD64 elem_size;
/* One could want to also set the array->end field in array, but we won't do it
* as long as all the get_type() helpers use const objects
*/
if (symt_get_info(module, array->base_type, TI_GET_LENGTH, &elem_size) && elem_size)
return -array->end / (DWORD)elem_size;
return 0;
}
return array->end - array->start + 1;
}
struct symt_function_signature* symt_new_function_signature(struct module* module,
struct symt* ret_type,
enum CV_call_e call_conv)
@ -400,9 +415,9 @@ BOOL WINAPI SymEnumTypes(HANDLE hProcess, ULONG64 BaseOfDll,
for (i=0; i<vector_length(&pair.effective->vtypes); i++)
{
type = *(struct symt**)vector_at(&pair.effective->vtypes, i);
sym_info->TypeIndex = (DWORD)type;
sym_info->TypeIndex = symt_ptr2index(pair.effective, type);
sym_info->info = 0; /* FIXME */
symt_get_info(type, TI_GET_LENGTH, &size);
symt_get_info(pair.effective, type, TI_GET_LENGTH, &size);
sym_info->Size = size;
sym_info->ModBase = pair.requested->module.BaseOfImage;
sym_info->Flags = 0; /* FIXME */
@ -462,8 +477,8 @@ BOOL WINAPI SymEnumTypesW(HANDLE hProcess, ULONG64 BaseOfDll,
*
* Retrieves information about a symt (either symbol or type)
*/
BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
void* pInfo)
BOOL symt_get_info(struct module* module, const struct symt* type,
IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo)
{
unsigned len;
@ -495,7 +510,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
for (i = 0; i < tifp->Count; i++)
{
if (!(pt = vector_at(v, tifp->Start + i))) return FALSE;
tifp->ChildId[i] = (DWORD)*pt;
tifp->ChildId[i] = symt_ptr2index(module, *pt);
}
}
break;
@ -522,7 +537,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
case SymTagFuncDebugStart:
case SymTagFuncDebugEnd:
case SymTagLabel:
if (!symt_get_info(((const struct symt_hierarchy_point*)type)->parent,
if (!symt_get_info(module, ((const struct symt_hierarchy_point*)type)->parent,
req, pInfo))
return FALSE;
X(ULONG64) += ((const struct symt_hierarchy_point*)type)->loc.offset;
@ -597,8 +612,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagArrayType:
X(DWORD) = ((const struct symt_array*)type)->end -
((const struct symt_array*)type)->start + 1;
X(DWORD) = symt_array_count(module, (const struct symt_array*)type);
break;
case SymTagFunctionType:
/* this seems to be wrong for (future) C++ methods, where 'this' parameter
@ -639,18 +653,17 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
return FALSE;
X(DWORD64) = ((const struct symt_data*)type)->u.member.length;
break;
case SymTagArrayType:
if (!symt_get_info(((const struct symt_array*)type)->base_type,
case SymTagArrayType:
if (!symt_get_info(module, ((const struct symt_array*)type)->base_type,
TI_GET_LENGTH, pInfo))
return FALSE;
X(DWORD64) *= ((const struct symt_array*)type)->end -
((const struct symt_array*)type)->start + 1;
X(DWORD64) *= symt_array_count(module, (const struct symt_array*)type);
break;
case SymTagPublicSymbol:
X(DWORD64) = ((const struct symt_public*)type)->size;
break;
case SymTagTypedef:
return symt_get_info(((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
return symt_get_info(module, ((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
case SymTagThunk:
X(DWORD64) = ((const struct symt_thunk*)type)->size;
break;
@ -670,19 +683,19 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagBlock:
X(DWORD) = (DWORD)((const struct symt_block*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_block*)type)->container);
break;
case SymTagData:
X(DWORD) = (DWORD)((const struct symt_data*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->container);
break;
case SymTagFunction:
X(DWORD) = (DWORD)((const struct symt_function*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->container);
break;
case SymTagThunk:
X(DWORD) = (DWORD)((const struct symt_thunk*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_thunk*)type)->container);
break;
case SymTagFunctionArgType:
X(DWORD) = (DWORD)((const struct symt_function_arg_type*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->container);
break;
default:
FIXME("Unsupported sym-tag %s for get-lexical-parent\n",
@ -750,29 +763,29 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
{
/* hierarchical => hierarchical */
case SymTagArrayType:
X(DWORD) = (DWORD)((const struct symt_array*)type)->base_type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->base_type);
break;
case SymTagPointerType:
X(DWORD) = (DWORD)((const struct symt_pointer*)type)->pointsto;
X(DWORD) = symt_ptr2index(module, ((const struct symt_pointer*)type)->pointsto);
break;
case SymTagFunctionType:
X(DWORD) = (DWORD)((const struct symt_function_signature*)type)->rettype;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function_signature*)type)->rettype);
break;
case SymTagTypedef:
X(DWORD) = (DWORD)((const struct symt_typedef*)type)->type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_typedef*)type)->type);
break;
/* lexical => hierarchical */
case SymTagData:
X(DWORD) = (DWORD)((const struct symt_data*)type)->type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->type);
break;
case SymTagFunction:
X(DWORD) = (DWORD)((const struct symt_function*)type)->type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->type);
break;
case SymTagEnum:
X(DWORD) = (DWORD)((const struct symt_enum*)type)->base_type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_enum*)type)->base_type);
break;
case SymTagFunctionArgType:
X(DWORD) = (DWORD)((const struct symt_function_arg_type*)type)->arg_type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->arg_type);
break;
default:
FIXME("Unsupported sym-tag %s for get-type\n",
@ -806,7 +819,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
break;
case TI_GET_ARRAYINDEXTYPEID:
if (type->tag != SymTagArrayType) return FALSE;
X(DWORD) = (DWORD)((const struct symt_array*)type)->index_type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->index_type);
break;
case TI_GET_CLASSPARENTID:
@ -854,7 +867,7 @@ BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase,
return FALSE;
}
return symt_get_info((struct symt*)TypeId, GetType, pInfo);
return symt_get_info(pair.effective, symt_index2ptr(pair.effective, TypeId), GetType, pInfo);
}
/******************************************************************
@ -865,15 +878,15 @@ BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll,
PCSTR Name, PSYMBOL_INFO Symbol)
{
struct process* pcs = process_find_by_handle(hProcess);
struct module* module;
struct module_pair pair;
struct symt* type;
if (!pcs) return FALSE;
module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
if (!module) return FALSE;
type = symt_find_type_by_name(module, SymTagNull, Name);
pair.requested = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
if (!module_get_debug(&pair)) return FALSE;
type = symt_find_type_by_name(pair.effective, SymTagNull, Name);
if (!type) return FALSE;
Symbol->TypeIndex = (DWORD)type;
Symbol->TypeIndex = symt_ptr2index(pair.effective, type);
return TRUE;
}

View file

@ -0,0 +1,26 @@
/*
* Copyright 2009 Louis Lenders
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define WINE_FILEDESCRIPTION_STR "Wine Image Helper"
#define WINE_FILENAME_STR "dbghelp.dll"
#define WINE_FILEVERSION 5,1,2600,3264
#define WINE_FILEVERSION_STR "5.1.2600.3264"
#define WINE_PRODUCTVERSION 5,1,2600,3264
#define WINE_PRODUCTVERSION_STR "5.1.2600.3264"
#include "wine/wine_common_ver.rc"

View file

@ -0,0 +1,130 @@
/* Fault report handling
*
* Copyright 2007 Peter Dons Tychsen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winreg.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "errorrep.h"
WINE_DEFAULT_DEBUG_CHANNEL(faultrep);
static const WCHAR SZ_EXCLUSIONLIST_KEY[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'P','C','H','e','a','l','t','h','\\',
'E','r','r','o','r','R','e','p','o','r','t','i','n','g','\\',
'E','x','c','l','u','s','i','o','n','L','i','s','t', 0};
/*************************************************************************
* AddERExcludedApplicationW [FAULTREP.@]
*
* Adds an application to a list of applications for which fault reports
* shouldn't be generated
*
* PARAMS
* lpAppFileName [I] The filename of the application executable
*
* RETURNS
* TRUE on success, FALSE of failure
*
* NOTES
* Wine doesn't use this data but stores it in the registry (in the same place
* as Windows would) in case it will be useful in a future version
*
* According to MSDN this function should succeed even if the user has no write
* access to HKLM. This probably means that there is no error checking.
*/
BOOL WINAPI AddERExcludedApplicationW(LPCWSTR lpAppFileName)
{
WCHAR *bslash;
DWORD value = 1;
HKEY hkey;
TRACE("(%s)\n", wine_dbgstr_w(lpAppFileName));
bslash = strrchrW(lpAppFileName, '\\');
if (bslash != NULL)
lpAppFileName = bslash + 1;
if (*lpAppFileName == '\0')
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!RegCreateKeyW(HKEY_LOCAL_MACHINE, SZ_EXCLUSIONLIST_KEY, &hkey))
{
RegSetValueExW(hkey, lpAppFileName, 0, REG_DWORD, (LPBYTE)&value, sizeof(value));
RegCloseKey(hkey);
}
return TRUE;
}
/*************************************************************************
* AddERExcludedApplicationA [FAULTREP.@]
*
* See AddERExcludedApplicationW
*/
BOOL WINAPI AddERExcludedApplicationA(LPCSTR lpAppFileName)
{
int len = MultiByteToWideChar(CP_ACP, 0, lpAppFileName, -1, NULL, 0);
WCHAR *wstr;
BOOL ret;
TRACE("(%s)\n", wine_dbgstr_a(lpAppFileName));
if (len == 0)
return FALSE;
wstr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
MultiByteToWideChar(CP_ACP, 0, lpAppFileName, -1, wstr, len);
ret = AddERExcludedApplicationW(wstr);
HeapFree(GetProcessHeap(), 0, wstr);
return ret;
}
/*************************************************************************
* ReportFault [FAULTREP.@]
*/
EFaultRepRetVal WINAPI ReportFault(LPEXCEPTION_POINTERS pep, DWORD dwOpt)
{
FIXME("%p 0x%x stub\n", pep, dwOpt);
return frrvOk;
}
/***********************************************************************
* DllMain.
*/
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{
switch(reason)
{
case DLL_WINE_PREATTACH:
return FALSE;
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(inst);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View file

@ -0,0 +1,9 @@
<module name="faultrep" type="win32dll" baseaddress="${BASEADDRESS_FAULTREP}" installbase="system32" installname="faultrep.dll">
<importlibrary definition="faultrep.spec" />
<include base="fusion">.</include>
<include base="ReactOS">include/reactos/wine</include>
<define name="__WINESRC__" />
<library>wine</library>
<library>advapi32</library>
<file>faultrep.c</file>
</module>

View file

@ -0,0 +1,14 @@
@ stdcall AddERExcludedApplicationA(str)
@ stdcall AddERExcludedApplicationW(wstr)
@ stub CreateMinidumpA
@ stub CreateMinidumpW
@ stub ReportEREvent
@ stub ReportEREventDW
@ stdcall ReportFault(ptr long)
@ stub ReportFaultDWM
@ stub ReportFaultFromQueue
@ stub ReportFaultToQueue
@ stub ReportHang
@ stub ReportKernelFaultA
@ stub ReportKernelFaultDWW
@ stub ReportKernelFaultW

View file

@ -837,6 +837,12 @@ SearchPathA (
DWORD RetValue = 0;
NTSTATUS Status = STATUS_SUCCESS;
if (!lpFileName)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
RtlInitAnsiString (&Path,
(LPSTR)lpPath);
RtlInitAnsiString (&FileName,
@ -985,6 +991,12 @@ SearchPathW(LPCWSTR lpPath,
{
DWORD ret = 0;
if (!lpFileName || !lpFileName[0])
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/* If the name contains an explicit path, ignore the path */
if (ContainsPath(lpFileName))
{

View file

@ -993,7 +993,7 @@ static INT PROFILE_GetSectionNames( LPWSTR buffer, UINT len )
*
*/
static INT PROFILE_GetString( LPCWSTR section, LPCWSTR key_name,
LPCWSTR def_val, LPWSTR buffer, UINT len, BOOL win32 )
LPCWSTR def_val, LPWSTR buffer, UINT len )
{
PROFILEKEY *key = NULL;
static const WCHAR empty_strW[] = { 0 };
@ -1114,16 +1114,12 @@ UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )
return GetPrivateProfileIntW( section, entry, def_val, L"win.ini" );
}
/*
* if win32, copy:
* - Section names if 'section' is NULL
* - Keys in a Section if 'entry' is NULL
* (see MSDN doc for GetPrivateProfileString)
/***********************************************************************
* GetPrivateProfileStringW (KERNEL32.@)
*/
static int PROFILE_GetPrivateProfileString( LPCWSTR section, LPCWSTR entry,
LPCWSTR def_val, LPWSTR buffer,
UINT len, LPCWSTR filename,
BOOL win32 )
DWORD WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
LPCWSTR def_val, LPWSTR buffer,
DWORD len, LPCWSTR filename )
{
int ret;
LPWSTR defval_tmp = NULL;
@ -1141,30 +1137,30 @@ static int PROFILE_GetPrivateProfileString( LPCWSTR section, LPCWSTR entry,
if (p >= def_val)
{
int len = (int)(p - def_val) + 1;
int len = (int)(p - def_val) + 1;
defval_tmp = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
if (!defval_tmp) return 0;
memcpy(defval_tmp, def_val, len * sizeof(WCHAR));
defval_tmp[len] = '\0';
def_val = defval_tmp;
defval_tmp = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
if (!defval_tmp) return 0;
memcpy(defval_tmp, def_val, len * sizeof(WCHAR));
defval_tmp[len] = '\0';
def_val = defval_tmp;
}
}
RtlEnterCriticalSection( &PROFILE_CritSect );
if (PROFILE_Open( filename, FALSE )) {
if (win32 && (section == NULL))
if (section == NULL)
ret = PROFILE_GetSectionNames(buffer, len);
else
/* PROFILE_GetString can handle the 'entry == NULL' case */
ret = PROFILE_GetString( section, entry, def_val, buffer, len, win32 );
ret = PROFILE_GetString( section, entry, def_val, buffer, len );
} else if (buffer && def_val) {
lstrcpynW( buffer, def_val, len );
ret = wcslen( buffer );
}
else
ret = 0;
else
ret = 0;
RtlLeaveCriticalSection( &PROFILE_CritSect );
@ -1175,7 +1171,6 @@ static int PROFILE_GetPrivateProfileString( LPCWSTR section, LPCWSTR entry,
return ret;
}
/***********************************************************************
* GetPrivateProfileStringA (KERNEL32.@)
*/
@ -1219,21 +1214,6 @@ DWORD WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
return ret;
}
/***********************************************************************
* GetPrivateProfileStringW (KERNEL32.@)
*/
DWORD WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
LPCWSTR def_val, LPWSTR buffer,
DWORD len, LPCWSTR filename )
{
DPRINT("(%S, %S, %S, %p, %d, %S)\n",
section, entry, def_val, buffer, len, filename);
return PROFILE_GetPrivateProfileString( section, entry, def_val,
buffer, len, filename, TRUE );
}
/***********************************************************************
* GetProfileStringA (KERNEL32.@)
*/
@ -1244,7 +1224,6 @@ DWORD WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val,
buffer, len, "win.ini" );
}
/***********************************************************************
* GetProfileStringW (KERNEL32.@)
*/
@ -1853,10 +1832,19 @@ WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
/***********************************************************************
* CloseProfileUserMapping
* OpenProfileUserMapping (KERNEL32.@)
*/
BOOL WINAPI
CloseProfileUserMapping(VOID)
BOOL WINAPI OpenProfileUserMapping(VOID)
{
DPRINT1("(), stub!\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* CloseProfileUserMapping (KERNEL32.@)
*/
BOOL WINAPI CloseProfileUserMapping(VOID)
{
DPRINT1("(), stub!\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

View file

@ -1156,14 +1156,6 @@ OpenDataFile(HANDLE hFile, DWORD dwUnused)
return FALSE;
}
BOOL
WINAPI
OpenProfileUserMapping(VOID)
{
STUB;
return FALSE;
}
BOOL
WINAPI
PrivMoveFileIdentityW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3)

View file

@ -495,7 +495,7 @@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
static const WCHAR p1W[] = {'%','1',0};
WCHAR sTemp [MAX_PATH];
szExt = (LPWSTR) PathFindExtensionW(szFullPath);
szExt = PathFindExtensionW(szFullPath);
TRACE("szExt=%s\n", debugstr_w(szExt));
if ( szExt &&
HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&

View file

@ -1673,6 +1673,14 @@ UINT WINAPI SHAddFromPropSheetExtArray(HPSXA hpsxa, LPFNADDPROPSHEETPAGE lpfnAdd
return 0;
}
/*************************************************************************
* SHCreatePropSheetExtArray [SHELL32.168]
*/
HPSXA WINAPI SHCreatePropSheetExtArray(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface)
{
return SHCreatePropSheetExtArrayEx(hKey, pszSubKey, max_iface, NULL);
}
/*************************************************************************
* SHCreatePropSheetExtArrayEx [SHELL32.194]
*/
@ -1780,15 +1788,6 @@ HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_
return (HPSXA)psxa;
}
/*************************************************************************
* SHCreatePropSheetExtArray [SHELL32.168]
*/
HPSXA WINAPI SHCreatePropSheetExtArray(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface)
{
return SHCreatePropSheetExtArrayEx(hKey, pszSubKey, max_iface, NULL);
}
/*************************************************************************
* SHReplaceFromPropSheetExtArray [SHELL32.170]
*/

View file

@ -531,9 +531,15 @@ static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest)
static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists)
{
BOOL ret;
DWORD attribs;
TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bFailIfExists ? "failIfExists" : "");
/* Destination file may already exist with read only attribute */
attribs = GetFileAttributesW(dest);
if (IsAttrib(attribs, FILE_ATTRIBUTE_READONLY))
SetFileAttributesW(dest, attribs & ~FILE_ATTRIBUTE_READONLY);
ret = CopyFileW(src, dest, bFailIfExists);
if (ret)
{
@ -1479,7 +1485,7 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
/*************************************************************************
* SHFreeNameMappings [shell32.246]
*
* Free the mapping handle returned by SHFileoperation if FOF_WANTSMAPPINGHANDLE
* Free the mapping handle returned by SHFileOperation if FOF_WANTSMAPPINGHANDLE
* was specified.
*
* PARAMS
@ -1496,12 +1502,12 @@ void WINAPI SHFreeNameMappings(HANDLE hNameMapping)
for (; i>= 0; i--)
{
LPSHNAMEMAPPINGW lp = DSA_GetItemPtr((HDSA)hNameMapping, i);
LPSHNAMEMAPPINGW lp = DSA_GetItemPtr(hNameMapping, i);
SHFree(lp->pszOldPath);
SHFree(lp->pszNewPath);
}
DSA_Destroy((HDSA)hNameMapping);
DSA_Destroy(hNameMapping);
}
}

File diff suppressed because it is too large Load diff

View file

@ -103,6 +103,9 @@
<directory name="dnsapi">
<xi:include href="dnsapi/dnsapi.rbuild" />
</directory>
<directory name="faultrep">
<xi:include href="faultrep/faultrep.rbuild" />
</directory>
<directory name="fmifs">
<xi:include href="fmifs/fmifs.rbuild" />
</directory>

View file

@ -23,6 +23,10 @@
#include "config.h"
#include "wine/port.h"
#if defined(__MINGW32__) || defined (_MSC_VER)
#include <ws2tcpip.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@ -48,7 +52,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet);
* Cookies are currently memory only.
* Cookies are NOT THREAD SAFE
* Cookies could use A LOT OF MEMORY. We need some kind of memory management here!
* Cookies should care about the expiry time
*/
typedef struct _cookie_domain cookie_domain;
@ -62,7 +65,7 @@ struct _cookie
LPWSTR lpCookieName;
LPWSTR lpCookieData;
time_t expiry; /* FIXME: not used */
FILETIME expiry;
};
struct _cookie_domain
@ -76,7 +79,7 @@ struct _cookie_domain
static struct list domain_list = LIST_INIT(domain_list);
static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data);
static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data, FILETIME expiry);
static cookie *COOKIE_findCookie(cookie_domain *domain, LPCWSTR lpszCookieName);
static void COOKIE_deleteCookie(cookie *deadCookie, BOOL deleteDomain);
static cookie_domain *COOKIE_addDomain(LPCWSTR domain, LPCWSTR path);
@ -84,24 +87,16 @@ static void COOKIE_deleteDomain(cookie_domain *deadDomain);
/* adds a cookie to the domain */
static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data)
static cookie *COOKIE_addCookie(cookie_domain *domain, LPCWSTR name, LPCWSTR data, FILETIME expiry)
{
cookie *newCookie = HeapAlloc(GetProcessHeap(), 0, sizeof(cookie));
list_init(&newCookie->entry);
newCookie->lpCookieName = NULL;
newCookie->lpCookieData = NULL;
if (name)
{
newCookie->lpCookieName = HeapAlloc(GetProcessHeap(), 0, (strlenW(name) + 1)*sizeof(WCHAR));
lstrcpyW(newCookie->lpCookieName, name);
}
if (data)
{
newCookie->lpCookieData = HeapAlloc(GetProcessHeap(), 0, (strlenW(data) + 1)*sizeof(WCHAR));
lstrcpyW(newCookie->lpCookieData, data);
}
newCookie->expiry = expiry;
newCookie->lpCookieName = heap_strdupW(name);
newCookie->lpCookieData = heap_strdupW(data);
TRACE("added cookie %p (data is %s)\n", newCookie, debugstr_w(data) );
@ -156,17 +151,8 @@ static cookie_domain *COOKIE_addDomain(LPCWSTR domain, LPCWSTR path)
list_init(&newDomain->cookie_list);
newDomain->lpCookieDomain = NULL;
newDomain->lpCookiePath = NULL;
if (domain)
{
newDomain->lpCookieDomain = HeapAlloc(GetProcessHeap(), 0, (strlenW(domain) + 1)*sizeof(WCHAR));
strcpyW(newDomain->lpCookieDomain, domain);
}
if (path)
{
newDomain->lpCookiePath = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1)*sizeof(WCHAR));
lstrcpyW(newDomain->lpCookiePath, path);
}
newDomain->lpCookieDomain = heap_strdupW(domain);
newDomain->lpCookiePath = heap_strdupW(path);
list_add_tail(&domain_list, &newDomain->entry);
@ -191,7 +177,28 @@ static BOOL COOKIE_crackUrlSimple(LPCWSTR lpszUrl, LPWSTR hostName, int hostName
UrlComponents.dwHostNameLength = hostNameLen;
UrlComponents.dwUrlPathLength = pathLen;
return InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents);
if (!InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents)) return FALSE;
/* discard the webpage off the end of the path */
if (UrlComponents.dwUrlPathLength)
{
if (path[UrlComponents.dwUrlPathLength - 1] != '/')
{
WCHAR *ptr;
if ((ptr = strrchrW(path, '/'))) *(++ptr) = 0;
else
{
path[0] = '/';
path[1] = 0;
}
}
}
else if (pathLen >= 2)
{
path[0] = '/';
path[1] = 0;
}
return TRUE;
}
/* match a domain. domain must match if the domain is not NULL. path must match if the path is not NULL */
@ -215,11 +222,22 @@ 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 (strcmpW(lpszCookiePath, searchDomain->lpCookiePath))
if (allow_partial)
{
len = lstrlenW(searchDomain->lpCookiePath);
if (strncmpiW(searchDomain->lpCookiePath, lpszCookiePath, len)!=0)
return FALSE;
}
else if (strcmpW(lpszCookiePath, searchDomain->lpCookiePath))
return FALSE;
}
return TRUE;
}
@ -262,6 +280,7 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName,
struct list * cursor;
unsigned int cnt = 0, domain_count = 0, cookie_count = 0;
WCHAR hostName[2048], path[2048];
FILETIME tm;
TRACE("(%s, %s, %p, %p)\n", debugstr_w(lpszUrl),debugstr_w(lpszCookieName),
lpCookieData, lpdwSize);
@ -276,10 +295,12 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName,
ret = COOKIE_crackUrlSimple(lpszUrl, hostName, sizeof(hostName)/sizeof(hostName[0]), path, sizeof(path)/sizeof(path[0]));
if (!ret || !hostName[0]) return FALSE;
GetSystemTimeAsFileTime(&tm);
LIST_FOR_EACH(cursor, &domain_list)
{
cookie_domain *cookiesDomain = LIST_ENTRY(cursor, cookie_domain, entry);
if (COOKIE_matchDomain(hostName, NULL /* FIXME: path */, cookiesDomain, TRUE))
if (COOKIE_matchDomain(hostName, path, cookiesDomain, TRUE))
{
struct list * cursor;
domain_count++;
@ -288,6 +309,14 @@ BOOL WINAPI InternetGetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName,
LIST_FOR_EACH(cursor, &cookiesDomain->cookie_list)
{
cookie *thisCookie = LIST_ENTRY(cursor, cookie, entry);
/* check for expiry */
if ((thisCookie->expiry.dwLowDateTime != 0 || thisCookie->expiry.dwHighDateTime != 0) && CompareFileTime(&tm,&thisCookie->expiry) > 0)
{
TRACE("Found expired cookie. deleting\n");
COOKIE_deleteCookie(thisCookie, FALSE);
continue;
}
if (lpCookieData == NULL) /* return the size of the buffer required to lpdwSize */
{
unsigned int len;
@ -356,27 +385,16 @@ BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
LPSTR lpCookieData, LPDWORD lpdwSize)
{
DWORD len;
LPWSTR szCookieData = NULL, szUrl = NULL, szCookieName = NULL;
LPWSTR szCookieData = NULL, url, name;
BOOL r;
TRACE("(%s,%s,%p)\n", debugstr_a(lpszUrl), debugstr_a(lpszCookieName),
lpCookieData);
if( lpszUrl )
{
len = MultiByteToWideChar( CP_ACP, 0, lpszUrl, -1, NULL, 0 );
szUrl = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, lpszUrl, -1, szUrl, len );
}
url = heap_strdupAtoW(lpszUrl);
name = heap_strdupAtoW(lpszCookieName);
if( lpszCookieName )
{
len = MultiByteToWideChar( CP_ACP, 0, lpszCookieName, -1, NULL, 0 );
szCookieName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, lpszCookieName, -1, szCookieName, len );
}
r = InternetGetCookieW( szUrl, szCookieName, NULL, &len );
r = InternetGetCookieW( url, name, NULL, &len );
if( r )
{
szCookieData = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
@ -386,7 +404,7 @@ BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
}
else
{
r = InternetGetCookieW( szUrl, szCookieName, szCookieData, &len );
r = InternetGetCookieW( url, name, szCookieData, &len );
*lpdwSize = WideCharToMultiByte( CP_ACP, 0, szCookieData, len,
lpCookieData, *lpdwSize, NULL, NULL );
@ -394,8 +412,8 @@ BOOL WINAPI InternetGetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
}
HeapFree( GetProcessHeap(), 0, szCookieData );
HeapFree( GetProcessHeap(), 0, szCookieName );
HeapFree( GetProcessHeap(), 0, szUrl );
HeapFree( GetProcessHeap(), 0, name );
HeapFree( GetProcessHeap(), 0, url );
return r;
}
@ -405,27 +423,129 @@ static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWST
cookie_domain *thisCookieDomain = NULL;
cookie *thisCookie;
struct list *cursor;
LPWSTR data, value;
WCHAR *ptr;
FILETIME expiry;
BOOL expired = FALSE;
value = data = heap_strdupW(cookie_data);
if (!data)
{
ERR("could not allocate %zu bytes for the cookie data buffer\n", (strlenW(cookie_data) + 1) * sizeof(WCHAR));
return FALSE;
}
memset(&expiry,0,sizeof(expiry));
/* lots of information can be parsed out of the cookie value */
ptr = data;
for (;;)
{
static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0};
static const WCHAR szPath[] = {'p','a','t','h','=',0};
static const WCHAR szExpires[] = {'e','x','p','i','r','e','s','=',0};
static const WCHAR szSecure[] = {'s','e','c','u','r','e',0};
static const WCHAR szHttpOnly[] = {'h','t','t','p','o','n','l','y',0};
if (!(ptr = strchrW(ptr,';'))) break;
*ptr++ = 0;
if (value != data)
HeapFree(GetProcessHeap(), 0, value);
value = HeapAlloc(GetProcessHeap(), 0, (ptr - data) * sizeof(WCHAR));
if (value == NULL)
{
HeapFree(GetProcessHeap(), 0, data);
ERR("could not allocate %zu bytes for the cookie value buffer\n", (ptr - data) * sizeof(WCHAR));
return FALSE;
}
strcpyW(value, data);
while (*ptr == ' ') ptr++; /* whitespace */
if (strncmpiW(ptr, szDomain, 7) == 0)
{
ptr+=strlenW(szDomain);
domain = ptr;
TRACE("Parsing new domain %s\n",debugstr_w(domain));
}
else if (strncmpiW(ptr, szPath, 5) == 0)
{
ptr+=strlenW(szPath);
path = ptr;
TRACE("Parsing new path %s\n",debugstr_w(path));
}
else if (strncmpiW(ptr, szExpires, 8) == 0)
{
FILETIME ft;
SYSTEMTIME st;
FIXME("persistent cookies not handled (%s)\n",debugstr_w(ptr));
ptr+=strlenW(szExpires);
if (InternetTimeToSystemTimeW(ptr, &st, 0))
{
SystemTimeToFileTime(&st, &expiry);
GetSystemTimeAsFileTime(&ft);
if (CompareFileTime(&ft,&expiry) > 0)
{
TRACE("Cookie already expired.\n");
expired = TRUE;
}
}
}
else if (strncmpiW(ptr, szSecure, 6) == 0)
{
FIXME("secure not handled (%s)\n",debugstr_w(ptr));
ptr += strlenW(szSecure);
}
else if (strncmpiW(ptr, szHttpOnly, 8) == 0)
{
FIXME("httponly not handled (%s)\n",debugstr_w(ptr));
ptr += strlenW(szHttpOnly);
}
else if (*ptr)
{
FIXME("Unknown additional option %s\n",debugstr_w(ptr));
break;
}
}
LIST_FOR_EACH(cursor, &domain_list)
{
thisCookieDomain = LIST_ENTRY(cursor, cookie_domain, entry);
if (COOKIE_matchDomain(domain, NULL /* FIXME: path */, thisCookieDomain, FALSE))
if (COOKIE_matchDomain(domain, path, thisCookieDomain, FALSE))
break;
thisCookieDomain = NULL;
}
if (!thisCookieDomain)
thisCookieDomain = COOKIE_addDomain(domain, path);
{
if (!expired)
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);
TRACE("setting cookie %s=%s for domain %s\n", debugstr_w(cookie_name),
debugstr_w(cookie_data), debugstr_w(thisCookieDomain->lpCookieDomain));
TRACE("setting cookie %s=%s for domain %s path %s\n", debugstr_w(cookie_name),
debugstr_w(value), debugstr_w(thisCookieDomain->lpCookieDomain),debugstr_w(thisCookieDomain->lpCookiePath));
if (!COOKIE_addCookie(thisCookieDomain, cookie_name, cookie_data))
if (!expired && !COOKIE_addCookie(thisCookieDomain, cookie_name, value, expiry))
{
HeapFree(GetProcessHeap(),0,data);
if (value != data) HeapFree(GetProcessHeap(), 0, value);
return FALSE;
}
HeapFree(GetProcessHeap(),0,data);
if (value != data) HeapFree(GetProcessHeap(), 0, value);
return TRUE;
}
@ -454,28 +574,26 @@ BOOL WINAPI InternetSetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName,
return FALSE;
}
hostName[0] = path[0] = 0;
hostName[0] = 0;
ret = COOKIE_crackUrlSimple(lpszUrl, hostName, sizeof(hostName)/sizeof(hostName[0]), path, sizeof(path)/sizeof(path[0]));
if (!ret || !hostName[0]) return FALSE;
if (!lpszCookieName)
{
unsigned int len;
WCHAR *cookie, *data;
len = strlenW(lpCookieData);
if (!(cookie = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
cookie = heap_strdupW(lpCookieData);
if (!cookie)
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
strcpyW(cookie, lpCookieData);
/* some apps (or is it us??) try to add a cookie with no cookie name, but
* the cookie data in the form of name[=data].
*/
if (!(data = strchrW(cookie, '='))) data = cookie + len;
else data++;
if (!(data = strchrW(cookie, '='))) data = cookie + strlenW(cookie);
else *data++ = 0;
ret = set_cookie(hostName, path, cookie, data);
@ -499,39 +617,21 @@ BOOL WINAPI InternetSetCookieW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName,
BOOL WINAPI InternetSetCookieA(LPCSTR lpszUrl, LPCSTR lpszCookieName,
LPCSTR lpCookieData)
{
DWORD len;
LPWSTR szCookieData = NULL, szUrl = NULL, szCookieName = NULL;
LPWSTR data, url, name;
BOOL r;
TRACE("(%s,%s,%s)\n", debugstr_a(lpszUrl),
debugstr_a(lpszCookieName), debugstr_a(lpCookieData));
if( lpszUrl )
{
len = MultiByteToWideChar( CP_ACP, 0, lpszUrl, -1, NULL, 0 );
szUrl = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, lpszUrl, -1, szUrl, len );
}
url = heap_strdupAtoW(lpszUrl);
name = heap_strdupAtoW(lpszCookieName);
data = heap_strdupAtoW(lpCookieData);
if( lpszCookieName )
{
len = MultiByteToWideChar( CP_ACP, 0, lpszCookieName, -1, NULL, 0 );
szCookieName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, lpszCookieName, -1, szCookieName, len );
}
r = InternetSetCookieW( url, name, data );
if( lpCookieData )
{
len = MultiByteToWideChar( CP_ACP, 0, lpCookieData, -1, NULL, 0 );
szCookieData = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, lpCookieData, -1, szCookieData, len );
}
r = InternetSetCookieW( szUrl, szCookieName, szCookieData );
HeapFree( GetProcessHeap(), 0, szCookieData );
HeapFree( GetProcessHeap(), 0, szCookieName );
HeapFree( GetProcessHeap(), 0, szUrl );
HeapFree( GetProcessHeap(), 0, data );
HeapFree( GetProcessHeap(), 0, name );
HeapFree( GetProcessHeap(), 0, url );
return r;
}
@ -692,3 +792,28 @@ BOOL WINAPI InternetSetPerSiteCookieDecisionW( LPCWSTR pchHostName, DWORD dwDeci
FIXME("(%s, 0x%08x) stub\n", debugstr_w(pchHostName), dwDecision);
return FALSE;
}
/***********************************************************************
* IsDomainLegalCookieDomainW (WININET.@)
*/
BOOL WINAPI IsDomainLegalCookieDomainW( LPCWSTR s1, LPCWSTR s2 )
{
const WCHAR *p;
FIXME("(%s, %s)\n", debugstr_w(s1), debugstr_w(s2));
if (!s1 || !s2)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (s1[0] == '.' || !s1[0] || s2[0] == '.' || !s2[0])
{
SetLastError(ERROR_INVALID_NAME);
return FALSE;
}
if (!(p = strchrW(s2, '.'))) return FALSE;
if (strchrW(p + 1, '.') && !strcmpW(p + 1, s1)) return TRUE;
else if (!strcmpW(s1, s2)) return TRUE;
return FALSE;
}

View file

@ -21,6 +21,10 @@
#include "config.h"
#include "wine/port.h"
#if defined(__MINGW32__) || defined (_MSC_VER)
#include <ws2tcpip.h>
#endif
#include <stdarg.h>
#include "windef.h"
@ -58,22 +62,23 @@ struct WININET_ErrorDlgParams
*/
static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
{
LPWININETHTTPREQW lpwhr;
LPWININETHTTPSESSIONW lpwhs = NULL;
LPWININETAPPINFOW hIC = NULL;
http_request_t *lpwhr;
http_session_t *lpwhs = NULL;
appinfo_t *hIC = NULL;
BOOL ret = FALSE;
LPWSTR p;
lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
lpwhr = (http_request_t*) WININET_GetObject( hRequest );
if (NULL == lpwhr)
return FALSE;
return FALSE;
lpwhs = lpwhr->lpHttpSession;
if (NULL == lpwhs)
return FALSE;
goto done;
hIC = lpwhs->lpAppInfo;
if (NULL == hIC)
return FALSE;
goto done;
lstrcpynW(szBuf, hIC->lpszProxy, sz);
@ -82,7 +87,39 @@ static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
if (p)
*p = 0;
return TRUE;
ret = TRUE;
done:
WININET_Release( &lpwhr->hdr );
return ret;
}
/***********************************************************************
* WININET_GetServer
*
* Determine the name of the web server
*/
static BOOL WININET_GetServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
{
http_request_t *lpwhr;
http_session_t *lpwhs = NULL;
BOOL ret = FALSE;
lpwhr = (http_request_t*) WININET_GetObject( hRequest );
if (NULL == lpwhr)
return FALSE;
lpwhs = lpwhr->lpHttpSession;
if (NULL == lpwhs)
goto done;
lstrcpynW(szBuf, lpwhs->lpszHostName, sz);
ret = TRUE;
done:
WININET_Release( &lpwhr->hdr );
return ret;
}
/***********************************************************************
@ -90,16 +127,20 @@ static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
*
* Determine the name of the (basic) Authentication realm
*/
static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz, BOOL proxy )
{
LPWSTR p, q;
DWORD index;
DWORD index, query;
static const WCHAR szRealm[] = { 'r','e','a','l','m','=',0 };
/* extract the Realm from the proxy response and show it */
if (proxy)
query = HTTP_QUERY_PROXY_AUTHENTICATE;
else
query = HTTP_QUERY_WWW_AUTHENTICATE;
/* extract the Realm from the response and show it */
index = 0;
if( !HttpQueryInfoW( hRequest, HTTP_QUERY_PROXY_AUTHENTICATE,
szBuf, &sz, &index) )
if( !HttpQueryInfoW( hRequest, query, szBuf, &sz, &index) )
return FALSE;
/*
@ -109,11 +150,10 @@ static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
p = strchrW( szBuf, ' ' );
if( !p || strncmpW( p+1, szRealm, strlenW(szRealm) ) )
{
ERR("proxy response wrong? (%s)\n", debugstr_w(szBuf));
ERR("response wrong? (%s)\n", debugstr_w(szBuf));
return FALSE;
}
/* remove quotes */
p += 7;
if( *p == '"' )
@ -194,44 +234,62 @@ static BOOL WININET_GetSetPassword( HWND hdlg, LPCWSTR szServer,
}
/***********************************************************************
* WININET_SetProxyAuthorization
* WININET_SetAuthorization
*/
static BOOL WININET_SetProxyAuthorization( HINTERNET hRequest,
LPWSTR username, LPWSTR password )
static BOOL WININET_SetAuthorization( HINTERNET hRequest, LPWSTR username,
LPWSTR password, BOOL proxy )
{
LPWININETHTTPREQW lpwhr;
LPWININETHTTPSESSIONW lpwhs;
LPWININETAPPINFOW hIC;
LPWSTR p;
http_request_t *lpwhr;
http_session_t *lpwhs;
BOOL ret = FALSE;
LPWSTR p, q;
lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
lpwhr = (http_request_t*) 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);
return FALSE;
goto done;
}
hIC = lpwhs->lpAppInfo;
p = HeapAlloc( GetProcessHeap(), 0, (strlenW( username ) + 1)*sizeof(WCHAR) );
p = heap_strdupW(username);
if( !p )
return FALSE;
lstrcpyW( p, username );
hIC->lpszProxyUsername = p;
goto done;
p = HeapAlloc( GetProcessHeap(), 0, (strlenW( password ) + 1)*sizeof(WCHAR) );
if( !p )
return FALSE;
lstrcpyW( p, password );
hIC->lpszProxyPassword = p;
q = heap_strdupW(password);
if( !q )
{
HeapFree(GetProcessHeap(), 0, username);
goto done;
}
return TRUE;
if (proxy)
{
appinfo_t *hIC = lpwhs->lpAppInfo;
HeapFree(GetProcessHeap(), 0, hIC->lpszProxyUsername);
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;
}
ret = TRUE;
done:
WININET_Release( &lpwhr->hdr );
return ret;
}
/***********************************************************************
@ -254,7 +312,7 @@ static INT_PTR WINAPI WININET_ProxyPasswordDialog(
/* extract the Realm from the proxy response and show it */
if( WININET_GetAuthRealm( params->hRequest,
szRealm, sizeof szRealm/sizeof(WCHAR)) )
szRealm, sizeof szRealm/sizeof(WCHAR), TRUE ) )
{
hitem = GetDlgItem( hdlg, IDC_REALM );
SetWindowTextW( hitem, szRealm );
@ -297,13 +355,97 @@ static INT_PTR WINAPI WININET_ProxyPasswordDialog(
if( hitem &&
SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
WININET_GetAuthRealm( params->hRequest,
szRealm, sizeof szRealm/sizeof(WCHAR)) &&
szRealm, sizeof szRealm/sizeof(WCHAR), TRUE ) &&
WININET_GetProxyServer( params->hRequest,
szServer, sizeof szServer/sizeof(WCHAR)) )
{
WININET_GetSetPassword( hdlg, szServer, szRealm, TRUE );
}
WININET_SetProxyAuthorization( params->hRequest, username, password );
WININET_SetAuthorization( params->hRequest, username, password, TRUE );
EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
return TRUE;
}
if( wParam == IDCANCEL )
{
EndDialog( hdlg, 0 );
return TRUE;
}
break;
}
return FALSE;
}
/***********************************************************************
* WININET_PasswordDialog
*/
static INT_PTR WINAPI WININET_PasswordDialog(
HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
HWND hitem;
struct WININET_ErrorDlgParams *params;
WCHAR szRealm[0x80], szServer[0x80];
if( uMsg == WM_INITDIALOG )
{
TRACE("WM_INITDIALOG (%08lx)\n", lParam);
/* save the parameter list */
params = (struct WININET_ErrorDlgParams*) lParam;
SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
/* extract the Realm from the response and show it */
if( WININET_GetAuthRealm( params->hRequest,
szRealm, sizeof szRealm/sizeof(WCHAR), FALSE ) )
{
hitem = GetDlgItem( hdlg, IDC_REALM );
SetWindowTextW( hitem, szRealm );
}
/* extract the name of the server */
if( WININET_GetServer( params->hRequest,
szServer, sizeof szServer/sizeof(WCHAR)) )
{
hitem = GetDlgItem( hdlg, IDC_SERVER );
SetWindowTextW( hitem, szServer );
}
WININET_GetSetPassword( hdlg, szServer, szRealm, FALSE );
return TRUE;
}
params = (struct WININET_ErrorDlgParams*)
GetWindowLongPtrW( hdlg, GWLP_USERDATA );
switch( uMsg )
{
case WM_COMMAND:
if( wParam == IDOK )
{
WCHAR username[0x20], password[0x20];
username[0] = 0;
hitem = GetDlgItem( hdlg, IDC_USERNAME );
if( hitem )
GetWindowTextW( hitem, username, sizeof username/sizeof(WCHAR) );
password[0] = 0;
hitem = GetDlgItem( hdlg, IDC_PASSWORD );
if( hitem )
GetWindowTextW( hitem, password, sizeof password/sizeof(WCHAR) );
hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
if( hitem &&
SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
WININET_GetAuthRealm( params->hRequest,
szRealm, sizeof szRealm/sizeof(WCHAR), FALSE ) &&
WININET_GetServer( params->hRequest,
szServer, sizeof szServer/sizeof(WCHAR)) )
{
WININET_GetSetPassword( hdlg, szServer, szRealm, TRUE );
}
WININET_SetAuthorization( params->hRequest, username, password, FALSE );
EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
return TRUE;
@ -362,17 +504,23 @@ DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest,
switch( dwError )
{
case ERROR_SUCCESS:
if( !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
return 0;
dwStatus = WININET_GetConnectionStatus( hRequest );
if( HTTP_STATUS_PROXY_AUTH_REQ != dwStatus )
return ERROR_SUCCESS;
return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
case ERROR_INTERNET_INCORRECT_PASSWORD:
return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
if( !dwError && !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
return 0;
dwStatus = WININET_GetConnectionStatus( hRequest );
switch (dwStatus)
{
case HTTP_STATUS_PROXY_AUTH_REQ:
return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
case HTTP_STATUS_DENIED:
return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_AUTHDLG ),
hWnd, WININET_PasswordDialog, (LPARAM) &params );
default:
WARN("unhandled status %u\n", dwStatus);
return 0;
}
case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
case ERROR_INTERNET_INVALID_CA:

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -42,12 +42,7 @@
# include <sys/socket.h>
#endif
#if defined(__MINGW32__) || defined (_MSC_VER)
#include "ws2tcpip.h"
#ifndef MSG_WAITALL
#define MSG_WAITALL 0
#endif
#else
#if !defined(__MINGW32__) && !defined(_MSC_VER)
#define closesocket close
#define ioctlsocket ioctl
#endif /* __MINGW32__ */
@ -62,33 +57,51 @@ typedef struct
BOOL useSSL;
int socketFD;
void *ssl_s;
char *peek_msg;
char *peek_msg_mem;
size_t peek_len;
} WININET_NETCONNECTION;
static inline LPWSTR WININET_strdupW( LPCWSTR str )
static inline LPWSTR heap_strdupW(LPCWSTR str)
{
LPWSTR ret = HeapAlloc( GetProcessHeap(), 0, (strlenW(str) + 1)*sizeof(WCHAR) );
if (ret) strcpyW( ret, str );
LPWSTR ret = NULL;
if(str) {
DWORD size;
size = (strlenW(str)+1)*sizeof(WCHAR);
ret = HeapAlloc(GetProcessHeap(), 0, size);
if(ret)
memcpy(ret, str, size);
}
return ret;
}
static inline LPWSTR WININET_strdup_AtoW( LPCSTR str )
static inline WCHAR *heap_strdupAtoW(const char *str)
{
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);
LPWSTR ret = NULL;
if(str) {
DWORD len;
len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
if(ret)
MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
}
return ret;
}
static inline LPSTR WININET_strdup_WtoA( LPCWSTR str )
static inline char *heap_strdupWtoA(LPCWSTR str)
{
int len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
LPSTR ret = HeapAlloc( GetProcessHeap(), 0, len );
if (ret)
WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL);
char *ret = NULL;
if(str) {
DWORD size = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
ret = HeapAlloc(GetProcessHeap(), 0, size);
if(ret)
WideCharToMultiByte(CP_ACP, 0, str, -1, ret, size, NULL, NULL);
}
return ret;
}
@ -124,24 +137,25 @@ typedef enum
#define INET_OPENURL 0x0001
#define INET_CALLBACKW 0x0002
typedef struct _WININETHANDLEHEADER WININETHANDLEHEADER, *LPWININETHANDLEHEADER;
typedef struct _object_header_t object_header_t;
typedef struct {
void (*Destroy)(WININETHANDLEHEADER*);
void (*CloseConnection)(WININETHANDLEHEADER*);
DWORD (*QueryOption)(WININETHANDLEHEADER*,DWORD,void*,DWORD*,BOOL);
DWORD (*SetOption)(WININETHANDLEHEADER*,DWORD,void*,DWORD);
DWORD (*ReadFile)(WININETHANDLEHEADER*,void*,DWORD,DWORD*);
DWORD (*ReadFileExA)(WININETHANDLEHEADER*,INTERNET_BUFFERSA*,DWORD,DWORD_PTR);
BOOL (*WriteFile)(WININETHANDLEHEADER*,const void*,DWORD,DWORD*);
DWORD (*QueryDataAvailable)(WININETHANDLEHEADER*,DWORD*,DWORD,DWORD_PTR);
DWORD (*FindNextFileW)(WININETHANDLEHEADER*,void*);
} HANDLEHEADERVtbl;
void (*Destroy)(object_header_t*);
void (*CloseConnection)(object_header_t*);
DWORD (*QueryOption)(object_header_t*,DWORD,void*,DWORD*,BOOL);
DWORD (*SetOption)(object_header_t*,DWORD,void*,DWORD);
DWORD (*ReadFile)(object_header_t*,void*,DWORD,DWORD*);
DWORD (*ReadFileExA)(object_header_t*,INTERNET_BUFFERSA*,DWORD,DWORD_PTR);
DWORD (*ReadFileExW)(object_header_t*,INTERNET_BUFFERSW*,DWORD,DWORD_PTR);
DWORD (*WriteFile)(object_header_t*,const void*,DWORD,DWORD*);
DWORD (*QueryDataAvailable)(object_header_t*,DWORD*,DWORD,DWORD_PTR);
DWORD (*FindNextFileW)(object_header_t*,void*);
} object_vtbl_t;
struct _WININETHANDLEHEADER
struct _object_header_t
{
WH_TYPE htype;
const HANDLEHEADERVtbl *vtbl;
const object_vtbl_t *vtbl;
HINTERNET hInternet;
DWORD dwFlags;
DWORD_PTR dwContext;
@ -156,28 +170,29 @@ struct _WININETHANDLEHEADER
typedef struct
{
WININETHANDLEHEADER hdr;
object_header_t hdr;
LPWSTR lpszAgent;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
LPWSTR lpszProxyUsername;
LPWSTR lpszProxyPassword;
DWORD dwAccessType;
} WININETAPPINFOW, *LPWININETAPPINFOW;
} appinfo_t;
typedef struct
{
WININETHANDLEHEADER hdr;
WININETAPPINFOW *lpAppInfo;
object_header_t hdr;
appinfo_t *lpAppInfo;
LPWSTR lpszHostName; /* the final destination of the request */
LPWSTR lpszServerName; /* the name of the server we directly connect to */
LPWSTR lpszUserName;
LPWSTR lpszPassword;
INTERNET_PORT nHostPort; /* the final destination port of the request */
INTERNET_PORT nServerPort; /* the port of the server we directly connect to */
struct sockaddr_in socketAddress;
} WININETHTTPSESSIONW, *LPWININETHTTPSESSIONW;
struct sockaddr_storage socketAddress;
socklen_t sa_len;
} http_session_t;
#define HDR_ISREQUEST 0x0001
#define HDR_COMMADELIMITED 0x0002
@ -194,25 +209,38 @@ typedef struct
struct HttpAuthInfo;
typedef struct gzip_stream_t gzip_stream_t;
typedef struct
{
WININETHANDLEHEADER hdr;
WININETHTTPSESSIONW *lpHttpSession;
object_header_t hdr;
http_session_t *lpHttpSession;
LPWSTR lpszPath;
LPWSTR lpszVerb;
LPWSTR lpszRawHeaders;
WININET_NETCONNECTION netConnection;
LPWSTR lpszVersion;
LPWSTR lpszStatusText;
DWORD dwContentLength; /* total number of bytes to be read */
DWORD dwContentRead; /* bytes of the content read so far */
DWORD dwBytesToWrite;
DWORD dwBytesWritten;
HTTPHEADERW *pCustHeaders;
DWORD nCustHeaders;
HANDLE hCacheFile;
LPWSTR lpszCacheFile;
struct HttpAuthInfo *pAuthInfo;
struct HttpAuthInfo *pProxyAuthInfo;
} WININETHTTPREQW, *LPWININETHTTPREQW;
CRITICAL_SECTION read_section; /* section to protect the following fields */
DWORD dwContentLength; /* total number of bytes to be read */
DWORD dwContentRead; /* bytes of the content read so far */
BOOL read_chunked; /* are we reading in chunked mode? */
DWORD read_pos; /* current read position in read_buf */
DWORD read_size; /* valid data size in read_buf */
BYTE read_buf[4096]; /* buffer for already read but not returned data */
BOOL decoding;
gzip_stream_t *gzip_stream;
} http_request_t;
@ -297,6 +325,12 @@ struct WORKREQ_HTTPSENDREQUESTW
BOOL bEndRequest;
};
struct WORKREQ_HTTPENDREQUESTW
{
DWORD dwFlags;
DWORD_PTR dwContext;
};
struct WORKREQ_SENDCALLBACK
{
DWORD_PTR dwContext;
@ -320,10 +354,15 @@ struct WORKREQ_INTERNETREADFILEEXA
LPINTERNET_BUFFERSA lpBuffersOut;
};
struct WORKREQ_INTERNETREADFILEEXW
{
LPINTERNET_BUFFERSW lpBuffersOut;
};
typedef struct WORKREQ
{
void (*asyncproc)(struct WORKREQ*);
WININETHANDLEHEADER *hdr;
object_header_t *hdr;
union {
struct WORKREQ_FTPPUTFILEW FtpPutFileW;
@ -338,77 +377,69 @@ typedef struct WORKREQ
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;
HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info );
LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet );
LPWININETHANDLEHEADER WININET_AddRef( LPWININETHANDLEHEADER info );
BOOL WININET_Release( LPWININETHANDLEHEADER info );
HINTERNET WININET_AllocHandle( object_header_t *info );
object_header_t *WININET_GetObject( HINTERNET hinternet );
object_header_t *WININET_AddRef( object_header_t *info );
BOOL WININET_Release( object_header_t *info );
BOOL WININET_FreeHandle( HINTERNET hinternet );
DWORD INET_QueryOption(DWORD,void*,DWORD*,BOOL);
time_t ConvertTimeString(LPCWSTR asctime);
HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
HINTERNET FTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext,
DWORD dwInternalFlags);
HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext,
DWORD dwInternalFlags);
DWORD HTTP_Connect(appinfo_t*,LPCWSTR,
INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext,
DWORD dwInternalFlags, HINTERNET*);
BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
struct sockaddr_in *psa);
struct sockaddr *psa, socklen_t *sa_len);
void INTERNET_SetLastError(DWORD dwError);
DWORD INTERNET_GetLastError(void);
BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest);
DWORD INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest);
LPSTR INTERNET_GetResponseBuffer(void);
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen);
BOOLAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength,
DWORD dwContentLength, BOOL bEndRequest);
INTERNETAPI HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
DWORD dwFlags, DWORD_PTR dwContext);
BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr);
VOID SendAsyncCallback(LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext,
VOID SendAsyncCallback(object_header_t *hdr, DWORD_PTR dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInfo,
DWORD dwStatusInfoLength);
VOID INTERNET_SendCallback(LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext,
VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInfo,
DWORD dwStatusInfoLength);
LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW lpwhr, LPCWSTR header);
BOOL NETCON_connected(WININET_NETCONNECTION *connection);
BOOL NETCON_init(WININET_NETCONNECTION *connnection, BOOL useSSL);
BOOL NETCON_create(WININET_NETCONNECTION *connection, int domain,
DWORD NETCON_init(WININET_NETCONNECTION *connnection, BOOL useSSL);
void NETCON_unload(void);
DWORD NETCON_create(WININET_NETCONNECTION *connection, int domain,
int type, int protocol);
BOOL NETCON_close(WININET_NETCONNECTION *connection);
BOOL NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
DWORD NETCON_close(WININET_NETCONNECTION *connection);
DWORD NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
unsigned int addrlen);
BOOL NETCON_secure_connect(WININET_NETCONNECTION *connection, LPCWSTR hostname);
BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname);
DWORD NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
int *sent /* out */);
BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
int *recvd /* out */);
BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available);
BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer);
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection);
DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value);
int sock_get_error(int);
extern void URLCacheContainers_CreateDefaults(void);
extern void URLCacheContainers_DeleteAll(void);

View file

@ -23,6 +23,12 @@
#include "config.h"
#include "wine/port.h"
#define NONAMELESSUNION
#if defined(__MINGW32__) || defined (_MSC_VER)
#include <ws2tcpip.h>
#endif
#include <sys/types.h>
#ifdef HAVE_POLL_H
#include <poll.h>
@ -33,10 +39,12 @@
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@ -55,9 +63,6 @@
#undef FAR
#undef DSA
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#include <stdarg.h>
#include <stdlib.h>
@ -81,7 +86,7 @@
#include "winsock2.h"
#define RESPONSE_TIMEOUT 30 /* FROM internet.c */
#define sock_get_error(x) WSAGetLastError()
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
@ -95,11 +100,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet);
#include <openssl/err.h>
static CRITICAL_SECTION init_ssl_cs;
static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
{
0, 0, &init_ssl_cs,
{ &init_ssl_cs_debug.ProcessLocksList,
&init_ssl_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
};
static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
static void *OpenSSL_ssl_handle;
static void *OpenSSL_crypto_handle;
static SSL_METHOD *meth;
static SSL_CTX *ctx;
static int hostname_idx;
static int error_idx;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
@ -107,6 +124,7 @@ static SSL_CTX *ctx;
MAKE_FUNCPTR(SSL_library_init);
MAKE_FUNCPTR(SSL_load_error_strings);
MAKE_FUNCPTR(SSLv23_method);
MAKE_FUNCPTR(SSL_CTX_free);
MAKE_FUNCPTR(SSL_CTX_new);
MAKE_FUNCPTR(SSL_new);
MAKE_FUNCPTR(SSL_free);
@ -115,46 +133,240 @@ MAKE_FUNCPTR(SSL_connect);
MAKE_FUNCPTR(SSL_shutdown);
MAKE_FUNCPTR(SSL_write);
MAKE_FUNCPTR(SSL_read);
MAKE_FUNCPTR(SSL_pending);
MAKE_FUNCPTR(SSL_get_ex_new_index);
MAKE_FUNCPTR(SSL_get_ex_data);
MAKE_FUNCPTR(SSL_set_ex_data);
MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx);
MAKE_FUNCPTR(SSL_get_verify_result);
MAKE_FUNCPTR(SSL_get_peer_certificate);
MAKE_FUNCPTR(SSL_CTX_get_timeout);
MAKE_FUNCPTR(SSL_CTX_set_timeout);
MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths);
MAKE_FUNCPTR(i2d_X509);
MAKE_FUNCPTR(SSL_CTX_set_verify);
MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data);
/* OpenSSL's libcrypto functions that we use */
MAKE_FUNCPTR(BIO_new_fp);
MAKE_FUNCPTR(CRYPTO_num_locks);
MAKE_FUNCPTR(CRYPTO_set_id_callback);
MAKE_FUNCPTR(CRYPTO_set_locking_callback);
MAKE_FUNCPTR(ERR_free_strings);
MAKE_FUNCPTR(ERR_get_error);
MAKE_FUNCPTR(ERR_error_string);
MAKE_FUNCPTR(i2d_X509);
MAKE_FUNCPTR(sk_num);
MAKE_FUNCPTR(sk_value);
#undef MAKE_FUNCPTR
static CRITICAL_SECTION *ssl_locks;
static unsigned int num_ssl_locks;
static unsigned long ssl_thread_id(void)
{
return GetCurrentThreadId();
}
static void ssl_lock_callback(int mode, int type, const char *file, int line)
{
if (mode & CRYPTO_LOCK)
EnterCriticalSection(&ssl_locks[type]);
else
LeaveCriticalSection(&ssl_locks[type]);
}
static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
{
unsigned char* buffer,*p;
INT len;
BOOL malloced = FALSE;
PCCERT_CONTEXT ret;
p = NULL;
len = pi2d_X509(cert,&p);
/*
* SSL 0.9.7 and above malloc the buffer if it is null.
* however earlier version do not and so we would need to alloc the buffer.
*
* see the i2d_X509 man page for more details.
*/
if (!p)
{
buffer = HeapAlloc(GetProcessHeap(),0,len);
p = buffer;
len = pi2d_X509(cert,&p);
}
else
{
buffer = p;
malloced = TRUE;
}
ret = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
if (malloced)
free(buffer);
else
HeapFree(GetProcessHeap(),0,buffer);
return ret;
}
static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store,
WCHAR *server)
{
BOOL ret;
CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
PCCERT_CHAIN_CONTEXT chain;
char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
char *server_auth[] = { oid_server_auth };
DWORD err = ERROR_SUCCESS;
TRACE("verifying %s\n", debugstr_w(server));
chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
if ((ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 0,
NULL, &chain)))
{
if (chain->TrustStatus.dwErrorStatus)
{
if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
err = ERROR_INTERNET_SEC_CERT_DATE_INVALID;
else if (chain->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_UNTRUSTED_ROOT)
err = ERROR_INTERNET_INVALID_CA;
else if ((chain->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_OFFLINE_REVOCATION) ||
(chain->TrustStatus.dwErrorStatus &
CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
err = ERROR_INTERNET_SEC_CERT_NO_REV;
else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
err = ERROR_INTERNET_SEC_CERT_REVOKED;
else if (chain->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
err = ERROR_INTERNET_SEC_INVALID_CERT;
else
err = ERROR_INTERNET_SEC_INVALID_CERT;
}
else
{
CERT_CHAIN_POLICY_PARA policyPara;
SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
CERT_CHAIN_POLICY_STATUS policyStatus;
sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
sslExtraPolicyPara.pwszServerName = server;
policyPara.cbSize = sizeof(policyPara);
policyPara.dwFlags = 0;
policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
chain, &policyPara, &policyStatus);
/* Any error in the policy status indicates that the
* policy couldn't be verified.
*/
if (ret && policyStatus.dwError)
{
if (policyStatus.dwError == CERT_E_CN_NO_MATCH)
err = ERROR_INTERNET_SEC_CERT_CN_INVALID;
else
err = ERROR_INTERNET_SEC_INVALID_CERT;
}
}
CertFreeCertificateChain(chain);
}
TRACE("returning %08x\n", err);
return err;
}
static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
{
SSL *ssl;
WCHAR *server;
BOOL ret = FALSE;
ssl = pX509_STORE_CTX_get_ex_data(ctx,
pSSL_get_ex_data_X509_STORE_CTX_idx());
server = pSSL_get_ex_data(ssl, hostname_idx);
if (preverify_ok)
{
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
if (store)
{
X509 *cert;
int i;
PCCERT_CONTEXT endCert = NULL;
ret = TRUE;
for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++)
{
PCCERT_CONTEXT context;
cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i);
if ((context = X509_to_cert_context(cert)))
{
if (i == 0)
ret = CertAddCertificateContextToStore(store, context,
CERT_STORE_ADD_ALWAYS, &endCert);
else
ret = CertAddCertificateContextToStore(store, context,
CERT_STORE_ADD_ALWAYS, NULL);
CertFreeCertificateContext(context);
}
}
if (!endCert) ret = FALSE;
if (ret)
{
DWORD_PTR err = netconn_verify_cert(endCert, store, server);
if (err)
{
pSSL_set_ex_data(ssl, error_idx, (void *)err);
ret = FALSE;
}
}
CertFreeCertificateContext(endCert);
CertCloseStore(store, 0);
}
}
return ret;
}
#endif
BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
{
connection->useSSL = FALSE;
connection->socketFD = -1;
if (useSSL)
{
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
int i;
TRACE("using SSL connection\n");
EnterCriticalSection(&init_ssl_cs);
if (OpenSSL_ssl_handle) /* already initialized everything */
return TRUE;
{
LeaveCriticalSection(&init_ssl_cs);
return ERROR_SUCCESS;
}
OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
if (!OpenSSL_ssl_handle)
{
ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
SONAME_LIBSSL);
INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
return FALSE;
LeaveCriticalSection(&init_ssl_cs);
return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
}
OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
if (!OpenSSL_crypto_handle)
{
ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
SONAME_LIBCRYPTO);
INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
return FALSE;
LeaveCriticalSection(&init_ssl_cs);
return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
}
/* mmm nice ugly macroness */
@ -163,13 +375,14 @@ BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
if (!p##x) \
{ \
ERR("failed to load symbol %s\n", #x); \
INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); \
return FALSE; \
LeaveCriticalSection(&init_ssl_cs); \
return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
}
DYNSSL(SSL_library_init);
DYNSSL(SSL_load_error_strings);
DYNSSL(SSLv23_method);
DYNSSL(SSL_CTX_free);
DYNSSL(SSL_CTX_new);
DYNSSL(SSL_new);
DYNSSL(SSL_free);
@ -178,12 +391,18 @@ BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
DYNSSL(SSL_shutdown);
DYNSSL(SSL_write);
DYNSSL(SSL_read);
DYNSSL(SSL_pending);
DYNSSL(SSL_get_ex_new_index);
DYNSSL(SSL_get_ex_data);
DYNSSL(SSL_set_ex_data);
DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx);
DYNSSL(SSL_get_verify_result);
DYNSSL(SSL_get_peer_certificate);
DYNSSL(SSL_CTX_get_timeout);
DYNSSL(SSL_CTX_set_timeout);
DYNSSL(SSL_CTX_set_default_verify_paths);
DYNSSL(i2d_X509);
DYNSSL(SSL_CTX_set_verify);
DYNSSL(X509_STORE_CTX_get_ex_data);
#undef DYNSSL
#define DYNCRYPTO(x) \
@ -191,12 +410,19 @@ BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
if (!p##x) \
{ \
ERR("failed to load symbol %s\n", #x); \
INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); \
return FALSE; \
LeaveCriticalSection(&init_ssl_cs); \
return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
}
DYNCRYPTO(BIO_new_fp);
DYNCRYPTO(CRYPTO_num_locks);
DYNCRYPTO(CRYPTO_set_id_callback);
DYNCRYPTO(CRYPTO_set_locking_callback);
DYNCRYPTO(ERR_free_strings);
DYNCRYPTO(ERR_get_error);
DYNCRYPTO(ERR_error_string);
DYNCRYPTO(i2d_X509);
DYNCRYPTO(sk_num);
DYNCRYPTO(sk_value);
#undef DYNCRYPTO
pSSL_library_init();
@ -204,15 +430,75 @@ BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
meth = pSSLv23_method();
connection->peek_msg = NULL;
connection->peek_msg_mem = NULL;
ctx = pSSL_CTX_new(meth);
if (!pSSL_CTX_set_default_verify_paths(ctx))
{
ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
pERR_error_string(pERR_get_error(), 0));
LeaveCriticalSection(&init_ssl_cs);
return ERROR_OUTOFMEMORY;
}
hostname_idx = pSSL_get_ex_new_index(0, (void *)"hostname index",
NULL, NULL, NULL);
if (hostname_idx == -1)
{
ERR("SSL_get_ex_new_index failed; %s\n",
pERR_error_string(pERR_get_error(), 0));
LeaveCriticalSection(&init_ssl_cs);
return ERROR_OUTOFMEMORY;
}
error_idx = pSSL_get_ex_new_index(0, (void *)"error index",
NULL, NULL, NULL);
if (error_idx == -1)
{
ERR("SSL_get_ex_new_index failed; %s\n",
pERR_error_string(pERR_get_error(), 0));
LeaveCriticalSection(&init_ssl_cs);
return ERROR_OUTOFMEMORY;
}
pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify);
pCRYPTO_set_id_callback(ssl_thread_id);
num_ssl_locks = pCRYPTO_num_locks();
ssl_locks = HeapAlloc(GetProcessHeap(), 0, num_ssl_locks * sizeof(CRITICAL_SECTION));
if (!ssl_locks)
{
LeaveCriticalSection(&init_ssl_cs);
return ERROR_OUTOFMEMORY;
}
for (i = 0; i < num_ssl_locks; i++)
InitializeCriticalSection(&ssl_locks[i]);
pCRYPTO_set_locking_callback(ssl_lock_callback);
LeaveCriticalSection(&init_ssl_cs);
#else
FIXME("can't use SSL, not compiled in.\n");
INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
return FALSE;
return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
#endif
}
return TRUE;
return ERROR_SUCCESS;
}
void NETCON_unload(void)
{
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
if (OpenSSL_crypto_handle)
{
pERR_free_strings();
wine_dlclose(OpenSSL_crypto_handle, NULL, 0);
}
if (OpenSSL_ssl_handle)
{
if (ctx)
pSSL_CTX_free(ctx);
wine_dlclose(OpenSSL_ssl_handle, NULL, 0);
}
if (ssl_locks)
{
int i;
for (i = 0; i < num_ssl_locks; i++) DeleteCriticalSection(&ssl_locks[i]);
HeapFree(GetProcessHeap(), 0, ssl_locks);
}
#endif
}
BOOL NETCON_connected(WININET_NETCONNECTION *connection)
@ -223,9 +509,8 @@ BOOL NETCON_connected(WININET_NETCONNECTION *connection)
return TRUE;
}
#if 0
/* translate a unix error code into a winsock one */
static int sock_get_error( int err )
int sock_get_error( int err )
{
#if !defined(__MINGW32__) && !defined (_MSC_VER)
switch (err)
@ -290,47 +575,39 @@ static int sock_get_error( int err )
#endif
return err;
}
#endif
/******************************************************************************
* NETCON_create
* Basically calls 'socket()'
*/
BOOL NETCON_create(WININET_NETCONNECTION *connection, int domain,
DWORD NETCON_create(WININET_NETCONNECTION *connection, int domain,
int type, int protocol)
{
#ifdef SONAME_LIBSSL
if (connection->useSSL)
return FALSE;
return ERROR_NOT_SUPPORTED;
#endif
connection->socketFD = socket(domain, type, protocol);
if (connection->socketFD == -1)
{
INTERNET_SetLastError(sock_get_error(errno));
return FALSE;
}
return TRUE;
return sock_get_error(errno);
return ERROR_SUCCESS;
}
/******************************************************************************
* NETCON_close
* Basically calls 'close()' unless we should use SSL
*/
BOOL NETCON_close(WININET_NETCONNECTION *connection)
DWORD NETCON_close(WININET_NETCONNECTION *connection)
{
int result;
if (!NETCON_connected(connection)) return FALSE;
if (!NETCON_connected(connection)) return ERROR_SUCCESS;
#ifdef SONAME_LIBSSL
if (connection->useSSL)
{
HeapFree(GetProcessHeap(),0,connection->peek_msg_mem);
connection->peek_msg = NULL;
connection->peek_msg_mem = NULL;
connection->peek_len = 0;
pSSL_shutdown(connection->ssl_s);
pSSL_free(connection->ssl_s);
connection->ssl_s = NULL;
@ -343,52 +620,34 @@ BOOL NETCON_close(WININET_NETCONNECTION *connection)
connection->socketFD = -1;
if (result == -1)
{
INTERNET_SetLastError(sock_get_error(errno));
return FALSE;
}
return TRUE;
return sock_get_error(errno);
return ERROR_SUCCESS;
}
#ifdef SONAME_LIBSSL
static BOOL check_hostname(X509 *cert, char *hostname)
{
/* FIXME: implement */
return TRUE;
}
#endif
/******************************************************************************
* NETCON_secure_connect
* Initiates a secure connection over an existing plaintext connection.
*/
BOOL NETCON_secure_connect(WININET_NETCONNECTION *connection, LPCWSTR hostname)
DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
{
DWORD res = ERROR_NOT_SUPPORTED;
#ifdef SONAME_LIBSSL
long verify_res;
X509 *cert;
int len;
char *hostname_unix;
/* can't connect if we are already connected */
if (connection->useSSL)
{
ERR("already connected\n");
return FALSE;
return ERROR_INTERNET_CANNOT_CONNECT;
}
ctx = pSSL_CTX_new(meth);
if (!pSSL_CTX_set_default_verify_paths(ctx))
{
ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
pERR_error_string(pERR_get_error(), 0));
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
connection->ssl_s = pSSL_new(ctx);
if (!connection->ssl_s)
{
ERR("SSL_new failed: %s\n",
pERR_error_string(pERR_get_error(), 0));
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
res = ERROR_OUTOFMEMORY;
goto fail;
}
@ -396,23 +655,25 @@ BOOL NETCON_secure_connect(WININET_NETCONNECTION *connection, LPCWSTR hostname)
{
ERR("SSL_set_fd failed: %s\n",
pERR_error_string(pERR_get_error(), 0));
INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
goto fail;
}
if (pSSL_connect(connection->ssl_s) <= 0)
{
ERR("SSL_connect failed: %s\n",
pERR_error_string(pERR_get_error(), 0));
INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
res = (DWORD_PTR)pSSL_get_ex_data(connection->ssl_s, error_idx);
if (!res)
res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
ERR("SSL_connect failed: %d\n", res);
goto fail;
}
pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname);
cert = pSSL_get_peer_certificate(connection->ssl_s);
if (!cert)
{
ERR("no certificate for server %s\n", debugstr_w(hostname));
/* FIXME: is this the best error? */
INTERNET_SetLastError(ERROR_INTERNET_INVALID_CA);
res = ERROR_INTERNET_INVALID_CA;
goto fail;
}
verify_res = pSSL_get_verify_result(connection->ssl_s);
@ -423,25 +684,8 @@ BOOL NETCON_secure_connect(WININET_NETCONNECTION *connection, LPCWSTR hostname)
* the moment */
}
len = WideCharToMultiByte(CP_UNIXCP, 0, hostname, -1, NULL, 0, NULL, NULL);
hostname_unix = HeapAlloc(GetProcessHeap(), 0, len);
if (!hostname_unix)
{
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
goto fail;
}
WideCharToMultiByte(CP_UNIXCP, 0, hostname, -1, hostname_unix, len, NULL, NULL);
if (!check_hostname(cert, hostname_unix))
{
HeapFree(GetProcessHeap(), 0, hostname_unix);
INTERNET_SetLastError(ERROR_INTERNET_SEC_CERT_CN_INVALID);
goto fail;
}
HeapFree(GetProcessHeap(), 0, hostname_unix);
connection->useSSL = TRUE;
return TRUE;
return ERROR_SUCCESS;
fail:
if (connection->ssl_s)
@ -451,32 +695,29 @@ fail:
connection->ssl_s = NULL;
}
#endif
return FALSE;
return res;
}
/******************************************************************************
* NETCON_connect
* Connects to the specified address.
*/
BOOL NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
DWORD NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
unsigned int addrlen)
{
int result;
if (!NETCON_connected(connection)) return FALSE;
result = connect(connection->socketFD, serv_addr, addrlen);
if (result == -1)
{
WARN("Unable to connect to host (%s)\n", strerror(errno));
INTERNET_SetLastError(sock_get_error(errno));
closesocket(connection->socketFD);
connection->socketFD = -1;
return FALSE;
return sock_get_error(errno);
}
return TRUE;
return ERROR_SUCCESS;
}
/******************************************************************************
@ -484,19 +725,16 @@ BOOL NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *se
* Basically calls 'send()' unless we should use SSL
* number of chars send is put in *sent
*/
BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
DWORD NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
int *sent /* out */)
{
if (!NETCON_connected(connection)) return FALSE;
if (!NETCON_connected(connection)) return ERROR_INTERNET_CONNECTION_ABORTED;
if (!connection->useSSL)
{
*sent = send(connection->socketFD, msg, len, flags);
if (*sent == -1)
{
INTERNET_SetLastError(sock_get_error(errno));
return FALSE;
}
return TRUE;
return sock_get_error(errno);
return ERROR_SUCCESS;
}
else
{
@ -505,10 +743,10 @@ BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len,
FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
*sent = pSSL_write(connection->ssl_s, msg, len);
if (*sent < 1 && len)
return FALSE;
return TRUE;
return ERROR_INTERNET_CONNECTION_ABORTED;
return ERROR_SUCCESS;
#else
return FALSE;
return ERROR_NOT_SUPPORTED;
#endif
}
}
@ -518,77 +756,25 @@ BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len,
* Basically calls 'recv()' unless we should use SSL
* number of chars received is put in *recvd
*/
BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
int *recvd /* out */)
{
*recvd = 0;
if (!NETCON_connected(connection)) return FALSE;
if (!NETCON_connected(connection)) return ERROR_INTERNET_CONNECTION_ABORTED;
if (!len)
return TRUE;
return ERROR_SUCCESS;
if (!connection->useSSL)
{
*recvd = recv(connection->socketFD, buf, len, flags);
if (*recvd == -1)
{
INTERNET_SetLastError(sock_get_error(errno));
return FALSE;
}
return TRUE;
return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS;
}
else
{
#ifdef SONAME_LIBSSL
if (flags & ~(MSG_PEEK|MSG_WAITALL))
FIXME("SSL_read does not support the following flag: %08x\n", flags);
/* this ugly hack is all for MSG_PEEK. eww gross */
if (flags & MSG_PEEK && !connection->peek_msg)
{
connection->peek_msg = connection->peek_msg_mem = HeapAlloc(GetProcessHeap(), 0, (sizeof(char) * len) + 1);
}
else if (flags & MSG_PEEK && connection->peek_msg)
{
if (len < connection->peek_len)
FIXME("buffer isn't big enough. Do the expect us to wrap?\n");
*recvd = min(len, connection->peek_len);
memcpy(buf, connection->peek_msg, *recvd);
return TRUE;
}
else if (connection->peek_msg)
{
*recvd = min(len, connection->peek_len);
memcpy(buf, connection->peek_msg, *recvd);
connection->peek_len -= *recvd;
connection->peek_msg += *recvd;
if (connection->peek_len == 0)
{
HeapFree(GetProcessHeap(), 0, connection->peek_msg_mem);
connection->peek_msg_mem = NULL;
connection->peek_msg = NULL;
}
/* check if we got enough data from the peek buffer */
if (!(flags & MSG_WAITALL) || (*recvd == len))
return TRUE;
/* otherwise, fall through */
}
*recvd += pSSL_read(connection->ssl_s, (char*)buf + *recvd, len - *recvd);
if (flags & MSG_PEEK) /* must copy stuff into buffer */
{
connection->peek_len = *recvd;
if (!*recvd)
{
HeapFree(GetProcessHeap(), 0, connection->peek_msg_mem);
connection->peek_msg_mem = NULL;
connection->peek_msg = NULL;
}
else
memcpy(connection->peek_msg, buf, *recvd);
}
if (*recvd < 1 && len)
return FALSE;
return TRUE;
*recvd = pSSL_read(connection->ssl_s, buf, len);
return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
#else
return FALSE;
return ERROR_NOT_SUPPORTED;
#endif
}
}
@ -604,13 +790,9 @@ BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *avail
if (!NETCON_connected(connection))
return FALSE;
#ifdef SONAME_LIBSSL
if (connection->peek_msg) *available = connection->peek_len;
#endif
#ifdef FIONREAD
if (!connection->useSSL)
{
#ifdef FIONREAD
int unread;
int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread);
if (!retval)
@ -618,155 +800,28 @@ BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *avail
TRACE("%d bytes of queued, but unread data\n", unread);
*available += unread;
}
}
#endif
return TRUE;
}
/******************************************************************************
* 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
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 FALSE;
#else
return FALSE;
*available = pSSL_pending(connection->ssl_s);
#endif
}
return TRUE;
}
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
{
#ifdef SONAME_LIBSSL
X509* cert;
unsigned char* buffer,*p;
INT len;
BOOL malloced = FALSE;
LPCVOID r = NULL;
if (!connection->useSSL)
return NULL;
cert = pSSL_get_peer_certificate(connection->ssl_s);
p = NULL;
len = pi2d_X509(cert,&p);
/*
* SSL 0.9.7 and above malloc the buffer if it is null.
* however earlier version do not and so we would need to alloc the buffer.
*
* see the i2d_X509 man page for more details.
*/
if (!p)
{
buffer = HeapAlloc(GetProcessHeap(),0,len);
p = buffer;
len = pi2d_X509(cert,&p);
}
else
{
buffer = p;
malloced = TRUE;
}
r = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
if (malloced)
free(buffer);
else
HeapFree(GetProcessHeap(),0,buffer);
r = X509_to_cert_context(cert);
return r;
#else
return NULL;
@ -788,7 +843,7 @@ DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value
tv.tv_usec = (value % 1000) * 1000;
result = setsockopt(connection->socketFD, SOL_SOCKET,
send ? SO_SNDTIMEO : SO_RCVTIMEO, &tv,
send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv,
sizeof(tv));
if (result == -1)

View file

@ -18,6 +18,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <windef.h>
#include <winuser.h>
#define IDD_AUTHDLG 0x399
#define IDD_PROXYDLG 0x400
#define IDC_PROXY 0x401
@ -25,5 +29,6 @@
#define IDC_USERNAME 0x403
#define IDC_PASSWORD 0x404
#define IDC_SAVEPASSWORD 0x405
#define IDC_SERVER 0x406
#define IDS_LANCONNECTION 0x500

View file

@ -43,24 +43,28 @@
#include "wininet_Bg.rc"
#include "wininet_Cs.rc"
#include "wininet_Da.rc"
#include "wininet_De.rc"
#include "wininet_En.rc"
#include "wininet_Eo.rc"
#include "wininet_Es.rc"
#include "wininet_Fi.rc"
#include "wininet_Fr.rc"
#include "wininet_Hu.rc"
#include "wininet_It.rc"
#include "wininet_Ja.rc"
#include "wininet_Ko.rc"
#include "wininet_Nl.rc"
#include "wininet_No.rc"
#include "wininet_Pl.rc"
#include "wininet_Sv.rc"
#include "wininet_Uk.rc"
#include "wininet_Tr.rc"
/* UTF-8 */
#include "wininet_De.rc"
#include "wininet_Fr.rc"
#include "wininet_Ja.rc"
#include "wininet_Lt.rc"
#include "wininet_No.rc"
#include "wininet_Pt.rc"
#include "wininet_Ro.rc"
#include "wininet_Ru.rc"
#include "wininet_Si.rc"
#include "wininet_Sv.rc"
#include "wininet_Uk.rc"
#include "wininet_Tr.rc"
#include "wininet_Zh.rc"

View file

@ -465,7 +465,6 @@ static void URLCacheContainer_CloseIndex(URLCACHECONTAINER * pContainer)
static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix, LPCWSTR path, LPWSTR mutex_name)
{
URLCACHECONTAINER * pContainer = HeapAlloc(GetProcessHeap(), 0, sizeof(URLCACHECONTAINER));
int path_len = strlenW(path);
int cache_prefix_len = strlenW(cache_prefix);
if (!pContainer)
@ -476,15 +475,13 @@ static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix, LPCWSTR path,
pContainer->hMapping = NULL;
pContainer->file_size = 0;
pContainer->path = HeapAlloc(GetProcessHeap(), 0, (path_len + 1) * sizeof(WCHAR));
pContainer->path = heap_strdupW(path);
if (!pContainer->path)
{
HeapFree(GetProcessHeap(), 0, pContainer);
return FALSE;
}
memcpy(pContainer->path, path, (path_len + 1) * sizeof(WCHAR));
pContainer->cache_prefix = HeapAlloc(GetProcessHeap(), 0, (cache_prefix_len + 1) * sizeof(WCHAR));
if (!pContainer->cache_prefix)
{
@ -593,6 +590,9 @@ static DWORD URLCacheContainers_FindContainerW(LPCWSTR lpwszUrl, URLCACHECONTAIN
TRACE("searching for prefix for URL: %s\n", debugstr_w(lpwszUrl));
if(!lpwszUrl)
return ERROR_INVALID_PARAMETER;
LIST_FOR_EACH_ENTRY(pContainer, &UrlContainers, URLCACHECONTAINER, entry)
{
int prefix_len = strlenW(pContainer->cache_prefix);
@ -609,17 +609,15 @@ static DWORD URLCacheContainers_FindContainerW(LPCWSTR lpwszUrl, URLCACHECONTAIN
static DWORD URLCacheContainers_FindContainerA(LPCSTR lpszUrl, URLCACHECONTAINER ** ppContainer)
{
LPWSTR url = NULL;
DWORD ret;
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 GetLastError();
if (lpszUrl && !(url = heap_strdupAtoW(lpszUrl)))
return ERROR_OUTOFMEMORY;
ret = URLCacheContainers_FindContainerW(url, ppContainer);
HeapFree(GetProcessHeap(), 0, url);
return ret;
}
static BOOL URLCacheContainers_Enum(LPCWSTR lpwszSearchPattern, DWORD dwIndex, URLCACHECONTAINER ** ppContainer)
@ -692,6 +690,7 @@ static LPURLCACHE_HEADER URLCacheContainer_LockIndex(URLCACHECONTAINER * pContai
* of the memory mapped file */
if (pHeader->dwFileSize != pContainer->file_size)
{
UnmapViewOfFile( pHeader );
URLCacheContainer_CloseIndex(pContainer);
error = URLCacheContainer_OpenIndex(pContainer);
if (error != ERROR_SUCCESS)
@ -1240,17 +1239,15 @@ static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct
static BOOL URLCache_FindHashW(LPCURLCACHE_HEADER pHeader, LPCWSTR lpszUrl, struct _HASH_ENTRY ** ppHashEntry)
{
LPSTR urlA;
int url_len;
BOOL ret;
url_len = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
urlA = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(CHAR));
urlA = heap_strdupWtoA(lpszUrl);
if (!urlA)
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, urlA, url_len, NULL, NULL);
ret = URLCache_FindHash(pHeader, urlA, ppHashEntry);
HeapFree(GetProcessHeap(), 0, urlA);
return ret;
@ -1451,6 +1448,28 @@ static BOOL URLCache_EnumHashTableEntries(LPCURLCACHE_HEADER pHeader, const HASH
return FALSE;
}
/***********************************************************************
* FreeUrlCacheSpaceA (WININET.@)
*
*/
BOOL WINAPI FreeUrlCacheSpaceA(LPCSTR lpszCachePath, DWORD dwSize, DWORD dwFilter)
{
FIXME("stub!\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* FreeUrlCacheSpaceW (WININET.@)
*
*/
BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR lpszCachePath, DWORD dwSize, DWORD dwFilter)
{
FIXME("stub!\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* GetUrlCacheEntryInfoExA (WININET.@)
*
@ -1482,7 +1501,11 @@ BOOL WINAPI GetUrlCacheEntryInfoExA(
return FALSE;
}
if (dwFlags != 0)
{
FIXME("Undocumented flag(s): %x\n", dwFlags);
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
return GetUrlCacheEntryInfoA(lpszUrl, lpCacheEntryInfo, lpdwCacheEntryInfoBufSize);
}
@ -1682,7 +1705,11 @@ BOOL WINAPI GetUrlCacheEntryInfoExW(
return FALSE;
}
if (dwFlags != 0)
{
FIXME("Undocumented flag(s): %x\n", dwFlags);
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
return GetUrlCacheEntryInfoW(lpszUrl, lpCacheEntryInfo, lpdwCacheEntryInfoBufSize);
}
@ -1869,6 +1896,13 @@ BOOL WINAPI RetrieveUrlCacheEntryFileA(
}
pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
if (!pUrlEntry->dwOffsetLocalName)
{
URLCacheContainer_UnlockIndex(pContainer, pHeader);
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
TRACE("Found URL: %s\n", (LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl);
TRACE("Header info: %s\n", (LPBYTE)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo);
@ -1958,6 +1992,13 @@ BOOL WINAPI RetrieveUrlCacheEntryFileW(
}
pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
if (!pUrlEntry->dwOffsetLocalName)
{
URLCacheContainer_UnlockIndex(pContainer, pHeader);
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
TRACE("Found URL: %s\n", (LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl);
TRACE("Header info: %s\n", (LPBYTE)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo);
@ -2142,21 +2183,16 @@ BOOL WINAPI CreateUrlCacheEntryA(
IN DWORD dwReserved
)
{
DWORD len;
WCHAR *url_name;
WCHAR *file_extension;
WCHAR file_name[MAX_PATH];
BOOL bSuccess = FALSE;
DWORD dwError = 0;
if ((len = MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, NULL, 0)) != 0 &&
(url_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0)
if (lpszUrlName && (url_name = heap_strdupAtoW(lpszUrlName)))
{
MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, url_name, len);
if ((len = MultiByteToWideChar(CP_ACP, 0, lpszFileExtension, -1, NULL, 0)) != 0 &&
(file_extension = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0)
if (lpszFileExtension && (file_extension = heap_strdupAtoW(lpszFileExtension)))
{
MultiByteToWideChar(CP_ACP, 0, lpszFileExtension, -1, file_extension, len);
if (CreateUrlCacheEntryW(url_name, dwExpectedFileSize, file_extension, file_name, dwReserved))
{
if (WideCharToMultiByte(CP_ACP, 0, file_name, -1, lpszFileName, MAX_PATH, NULL, NULL) < MAX_PATH)
@ -2211,7 +2247,11 @@ BOOL WINAPI CreateUrlCacheEntryW(
BOOL bFound = FALSE;
int count;
DWORD error;
HANDLE hFile;
FILETIME ft;
static const WCHAR szWWW[] = {'w','w','w',0};
static const WCHAR fmt[] = {'%','0','8','X','%','s',0};
TRACE("(%s, 0x%08x, %s, %p, 0x%08x)\n",
debugstr_w(lpszUrlName),
@ -2221,11 +2261,7 @@ BOOL WINAPI CreateUrlCacheEntryW(
dwReserved);
if (dwReserved)
{
ERR("dwReserved != 0\n");
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
FIXME("dwReserved 0x%08x\n", dwReserved);
lpszUrlEnd = lpszUrlName + strlenW(lpszUrlName);
@ -2318,7 +2354,6 @@ BOOL WINAPI CreateUrlCacheEntryW(
for (i = 0; i < 255; i++)
{
static const WCHAR szFormat[] = {'[','%','u',']','%','s',0};
HANDLE hFile;
WCHAR *p;
wsprintfW(lpszFileNameNoPath + countnoextension, szFormat, i, szExtension);
@ -2346,6 +2381,18 @@ BOOL WINAPI CreateUrlCacheEntryW(
}
}
GetSystemTimeAsFileTime(&ft);
wsprintfW(lpszFileNameNoPath + countnoextension, fmt, ft.dwLowDateTime, szExtension);
TRACE("Trying: %s\n", debugstr_w(lpszFileName));
hFile = CreateFileW(lpszFileName, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
return TRUE;
}
WARN("Could not find a unique filename\n");
return FALSE;
}
@ -2447,25 +2494,17 @@ static BOOL CommitUrlCacheEntryInternal(
if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
return FALSE;
len = WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, NULL, 0, NULL, NULL);
lpszUrlNameA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
lpszUrlNameA = heap_strdupWtoA(lpszUrlName);
if (!lpszUrlNameA)
{
error = GetLastError();
goto cleanup;
}
WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, lpszUrlNameA, len, NULL, NULL);
if (lpszFileExtension)
if (lpszFileExtension && !(lpszFileExtensionA = heap_strdupWtoA(lpszFileExtension)))
{
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);
error = GetLastError();
goto cleanup;
}
if (URLCache_FindHash(pHeader, lpszUrlNameA, &pHashEntry))
@ -2622,7 +2661,6 @@ BOOL WINAPI CommitUrlCacheEntryA(
IN LPCSTR lpszOriginalUrl
)
{
DWORD len;
WCHAR *url_name = NULL;
WCHAR *local_file_name = NULL;
WCHAR *original_url = NULL;
@ -2638,35 +2676,27 @@ BOOL WINAPI CommitUrlCacheEntryA(
debugstr_a(lpszFileExtension),
debugstr_a(lpszOriginalUrl));
len = MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, NULL, 0);
url_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
url_name = heap_strdupAtoW(lpszUrlName);
if (!url_name)
goto cleanup;
MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, url_name, len);
if (lpszLocalFileName)
{
len = MultiByteToWideChar(CP_ACP, 0, lpszLocalFileName, -1, NULL, 0);
local_file_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
local_file_name = heap_strdupAtoW(lpszLocalFileName);
if (!local_file_name)
goto cleanup;
MultiByteToWideChar(CP_ACP, 0, lpszLocalFileName, -1, local_file_name, len);
}
if (lpszFileExtension)
{
len = MultiByteToWideChar(CP_ACP, 0, lpszFileExtension, -1, NULL, 0);
file_extension = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
file_extension = heap_strdupAtoW(lpszFileExtension);
if (!file_extension)
goto cleanup;
MultiByteToWideChar(CP_ACP, 0, lpszFileExtension, -1, file_extension, len);
}
if (lpszOriginalUrl)
{
len = MultiByteToWideChar(CP_ACP, 0, lpszOriginalUrl, -1, NULL, 0);
original_url = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
original_url = heap_strdupAtoW(lpszOriginalUrl);
if (!original_url)
goto cleanup;
MultiByteToWideChar(CP_ACP, 0, lpszOriginalUrl, -1, original_url, len);
}
bSuccess = CommitUrlCacheEntryInternal(url_name, local_file_name, ExpireTime, LastModifiedTime,
@ -2712,12 +2742,8 @@ BOOL WINAPI CommitUrlCacheEntryW(
debugstr_w(lpszFileExtension),
debugstr_w(lpszOriginalUrl));
if (!lpHeaderInfo ||
((len = WideCharToMultiByte(CP_ACP, 0, lpHeaderInfo, -1, NULL, 0, NULL, NULL)) != 0 &&
(header_info = HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR) * len)) != 0))
if (!lpHeaderInfo || (header_info = heap_strdupWtoA(lpHeaderInfo)))
{
if (header_info)
WideCharToMultiByte(CP_ACP, 0, lpHeaderInfo, -1, header_info, len, NULL, NULL);
if (CommitUrlCacheEntryInternal(lpszUrlName, lpszLocalFileName, ExpireTime, LastModifiedTime,
CacheEntryType, (LPBYTE)header_info, len, lpszFileExtension, lpszOriginalUrl))
{
@ -2940,19 +2966,16 @@ BOOL WINAPI DeleteUrlCacheEntryW(LPCWSTR lpszUrlName)
struct _HASH_ENTRY * pHashEntry;
CACHEFILE_ENTRY * pEntry;
LPSTR urlA;
int url_len;
DWORD error;
TRACE("(%s)\n", debugstr_w(lpszUrlName));
url_len = WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, NULL, 0, NULL, NULL);
urlA = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(CHAR));
urlA = heap_strdupWtoA(lpszUrlName);
if (!urlA)
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, urlA, url_len, NULL, NULL);
error = URLCacheContainers_FindContainerW(lpszUrlName, &pContainer);
if (error != ERROR_SUCCESS)
@ -3133,14 +3156,12 @@ INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern,
pEntryHandle->dwMagic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC;
if (lpszUrlSearchPattern)
{
int len = MultiByteToWideChar(CP_ACP, 0, lpszUrlSearchPattern, -1, NULL, 0);
pEntryHandle->lpszUrlSearchPattern = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
pEntryHandle->lpszUrlSearchPattern = heap_strdupAtoW(lpszUrlSearchPattern);
if (!pEntryHandle->lpszUrlSearchPattern)
{
HeapFree(GetProcessHeap(), 0, pEntryHandle);
return NULL;
}
MultiByteToWideChar(CP_ACP, 0, lpszUrlSearchPattern, -1, pEntryHandle->lpszUrlSearchPattern, len);
}
else
pEntryHandle->lpszUrlSearchPattern = NULL;
@ -3174,14 +3195,12 @@ INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern,
pEntryHandle->dwMagic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC;
if (lpszUrlSearchPattern)
{
int len = strlenW(lpszUrlSearchPattern);
pEntryHandle->lpszUrlSearchPattern = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
pEntryHandle->lpszUrlSearchPattern = heap_strdupW(lpszUrlSearchPattern);
if (!pEntryHandle->lpszUrlSearchPattern)
{
HeapFree(GetProcessHeap(), 0, pEntryHandle);
return NULL;
}
memcpy(pEntryHandle->lpszUrlSearchPattern, lpszUrlSearchPattern, (len + 1) * sizeof(WCHAR));
}
else
pEntryHandle->lpszUrlSearchPattern = NULL;
@ -3623,10 +3642,26 @@ BOOL WINAPI IsUrlCacheEntryExpiredW( LPCWSTR url, DWORD dwFlags, FILETIME* pftLa
/***********************************************************************
* GetDiskInfoA (WININET.@)
*/
BOOL WINAPI GetDiskInfoA(PCSTR p0, PDWORD p1, PDWORDLONG p2, PDWORDLONG p3)
BOOL WINAPI GetDiskInfoA(PCSTR path, PDWORD cluster_size, PDWORDLONG free, PDWORDLONG total)
{
FIXME("(%p, %p, %p, %p)\n", p0, p1, p2, p3);
return FALSE;
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);
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;
}
/***********************************************************************
@ -3637,3 +3672,12 @@ DWORD WINAPI RegisterUrlCacheNotification(LPVOID a, DWORD b, DWORD c, DWORD d, D
FIXME("(%p %x %x %x %x %x)\n", a, b, c, d, e, f);
return 0;
}
/***********************************************************************
* IncrementUrlCacheHeaderData (WININET.@)
*/
BOOL WINAPI IncrementUrlCacheHeaderData(DWORD index, LPDWORD data)
{
FIXME("(%u, %p)\n", index, data);
return FALSE;
}

View file

@ -25,6 +25,10 @@
#include "config.h"
#include "wine/port.h"
#if defined(__MINGW32__) || defined (_MSC_VER)
#include <ws2tcpip.h>
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@ -40,6 +44,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
#ifndef HAVE_GETADDRINFO
/* critical section to protect non-reentrant gethostbyname() */
static CRITICAL_SECTION cs_gethostbyname;
static CRITICAL_SECTION_DEBUG critsect_debug =
@ -50,6 +56,8 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
};
static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 };
#endif
#define TIME_STRING_LEN 30
time_t ConvertTimeString(LPCWSTR asctime)
@ -137,12 +145,18 @@ time_t ConvertTimeString(LPCWSTR asctime)
BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
struct sockaddr_in *psa)
struct sockaddr *psa, socklen_t *sa_len)
{
WCHAR *found;
char *name;
int len, sz;
#ifdef HAVE_GETADDRINFO
struct addrinfo *res, hints;
int ret;
#else
struct hostent *phe;
struct sockaddr_in *sin = (struct sockaddr_in *)psa;
#endif
TRACE("%s\n", debugstr_w(lpszServerName));
@ -158,27 +172,75 @@ BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort,
len = strlenW(lpszServerName);
sz = WideCharToMultiByte( CP_UNIXCP, 0, lpszServerName, len, NULL, 0, NULL, NULL );
name = HeapAlloc(GetProcessHeap(), 0, sz+1);
if (!(name = HeapAlloc( GetProcessHeap(), 0, sz + 1 ))) return FALSE;
WideCharToMultiByte( CP_UNIXCP, 0, lpszServerName, len, name, sz, NULL, NULL );
name[sz] = 0;
#ifdef HAVE_GETADDRINFO
memset( &hints, 0, sizeof(struct addrinfo) );
/* Prefer IPv4 to IPv6 addresses, since some servers do not listen on
* their IPv6 addresses even though they have IPv6 addresses in the DNS.
*/
hints.ai_family = AF_INET;
ret = getaddrinfo( name, NULL, &hints, &res );
HeapFree( GetProcessHeap(), 0, name );
if (ret != 0)
{
TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(lpszServerName), gai_strerror(ret));
hints.ai_family = AF_INET6;
ret = getaddrinfo( name, NULL, &hints, &res );
if (ret != 0)
{
TRACE("failed to get address of %s (%s)\n", debugstr_w(lpszServerName), gai_strerror(ret));
return FALSE;
}
}
if (*sa_len < res->ai_addrlen)
{
WARN("address too small\n");
freeaddrinfo( res );
return FALSE;
}
*sa_len = res->ai_addrlen;
memcpy( psa, res->ai_addr, res->ai_addrlen );
/* Copy port */
switch (res->ai_family)
{
case AF_INET:
((struct sockaddr_in *)psa)->sin_port = htons(nServerPort);
break;
case AF_INET6:
((struct sockaddr_in6 *)psa)->sin6_port = htons(nServerPort);
break;
}
freeaddrinfo( res );
#else
EnterCriticalSection( &cs_gethostbyname );
phe = gethostbyname(name);
HeapFree( GetProcessHeap(), 0, name );
if (NULL == phe)
{
TRACE("Failed to get hostname: (%s)\n", debugstr_w(lpszServerName) );
TRACE("failed to get address of %s (%d)\n", debugstr_w(lpszServerName), h_errno);
LeaveCriticalSection( &cs_gethostbyname );
return FALSE;
}
memset(psa,0,sizeof(struct sockaddr_in));
memcpy((char *)&psa->sin_addr, phe->h_addr, phe->h_length);
psa->sin_family = phe->h_addrtype;
psa->sin_port = htons(nServerPort);
if (*sa_len < sizeof(struct sockaddr_in))
{
WARN("address too small\n");
LeaveCriticalSection( &cs_gethostbyname );
return FALSE;
}
*sa_len = sizeof(struct sockaddr_in);
memset(sin,0,sizeof(struct sockaddr_in));
memcpy((char *)&sin->sin_addr, phe->h_addr, phe->h_length);
sin->sin_family = phe->h_addrtype;
sin->sin_port = htons(nServerPort);
LeaveCriticalSection( &cs_gethostbyname );
#endif
return TRUE;
}
@ -224,7 +286,7 @@ static const char *get_callback_name(DWORD dwInternetStatus) {
return "Unknown";
}
VOID INTERNET_SendCallback(LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext,
VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInfo,
DWORD dwStatusInfoLength)
{
@ -244,11 +306,11 @@ VOID INTERNET_SendCallback(LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext,
case INTERNET_STATUS_NAME_RESOLVED:
case INTERNET_STATUS_CONNECTING_TO_SERVER:
case INTERNET_STATUS_CONNECTED_TO_SERVER:
lpvNewInfo = WININET_strdup_AtoW(lpvStatusInfo);
lpvNewInfo = heap_strdupAtoW(lpvStatusInfo);
break;
case INTERNET_STATUS_RESOLVING_NAME:
case INTERNET_STATUS_REDIRECT:
lpvNewInfo = WININET_strdupW(lpvStatusInfo);
lpvNewInfo = heap_strdupW(lpvStatusInfo);
break;
}
}else {
@ -262,7 +324,7 @@ VOID INTERNET_SendCallback(LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext,
break;
case INTERNET_STATUS_RESOLVING_NAME:
case INTERNET_STATUS_REDIRECT:
lpvNewInfo = WININET_strdup_WtoA(lpvStatusInfo);
lpvNewInfo = heap_strdupWtoA(lpvStatusInfo);
break;
}
}
@ -294,7 +356,7 @@ static void SendAsyncCallbackProc(WORKREQUEST *workRequest)
HeapFree(GetProcessHeap(), 0, req->lpvStatusInfo);
}
VOID SendAsyncCallback(LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext,
void SendAsyncCallback(object_header_t *hdr, DWORD_PTR dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInfo,
DWORD dwStatusInfoLength)
{

View file

@ -22,6 +22,7 @@
<library>secur32</library>
<library>crypt32</library>
<library>ws2_32</library>
<library>pseh</library>
<file>cookie.c</file>
<file>dialogs.c</file>
<file>ftp.c</file>

View file

@ -1,5 +1,5 @@
101 stub -noname DoConnectoidsExist
102 stub -noname GetDiskInfoA
102 stdcall -noname GetDiskInfoA(str ptr ptr ptr)
103 stub -noname PerformOperationOverUrlCacheA
104 stub -noname HttpCheckDavComplianceA
105 stub -noname HttpCheckDavComplianceW
@ -9,7 +9,7 @@
111 stub -noname ExportCookieFileW
112 stub -noname IsProfilesEnabled
116 stub -noname IsDomainlegalCookieDomainA
117 stub -noname IsDomainLegalCookieDomainW
117 stdcall -noname IsDomainLegalCookieDomainW(wstr wstr)
118 stub -noname FindP3PPolicySymbol
120 stub -noname MapResourceToPolicy
121 stub -noname GetP3PPolicy
@ -50,8 +50,8 @@
@ stdcall FindNextUrlCacheGroup(long ptr ptr)
@ stub ForceNexusLookup
@ stub ForceNexusLookupExW
@ stub FreeUrlCacheSpaceA
@ stub FreeUrlCacheSpaceW
@ stdcall FreeUrlCacheSpaceA(str long long)
@ stdcall FreeUrlCacheSpaceW(wstr long long)
@ stdcall FtpCommandA(long long long str ptr ptr)
@ stdcall FtpCommandW(long long long wstr ptr ptr)
@ stdcall FtpCreateDirectoryA(ptr str)
@ -109,7 +109,7 @@
@ stdcall HttpSendRequestExA(long ptr ptr long long)
@ stdcall HttpSendRequestExW(long ptr ptr long long)
@ stdcall HttpSendRequestW(ptr wstr long ptr long)
@ stub IncrementUrlCacheHeaderData
@ stdcall IncrementUrlCacheHeaderData(long ptr)
@ stub InternetAlgIdToStringA
@ stub InternetAlgIdToStringW
@ stdcall InternetAttemptConnect(long)
@ -213,10 +213,10 @@
@ stdcall IsUrlCacheEntryExpiredW(wstr long ptr)
@ stub LoadUrlCacheContent
@ stub ParseX509EncodedCertificateForListBoxEntry
@ stub PrivacyGetZonePreferenceW # (long long ptr ptr ptr)
@ stub PrivacySetZonePreferenceW # (long long long wstr)
@ stdcall PrivacyGetZonePreferenceW(long long ptr ptr ptr)
@ stdcall PrivacySetZonePreferenceW(long long long wstr)
@ stdcall ReadUrlCacheEntryStream(ptr long ptr ptr long)
@ stub RegisterUrlCacheNotification
@ stdcall RegisterUrlCacheNotification(ptr long long long long long)
@ stdcall ResumeSuspendedDownload(long long)
@ stdcall RetrieveUrlCacheEntryFileA(str ptr ptr long)
@ stdcall RetrieveUrlCacheEntryFileW(wstr ptr ptr long)

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
/* Czech strings in CP1250 */

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_DANISH, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -1,5 +1,6 @@
/*
* Copyright 2004 Henning Gerhardt
* Copyright 2009 André Hentschel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -16,6 +17,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
#pragma code_page(65001)
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
@ -25,8 +30,8 @@ FONT 8, "MS Shell Dlg"
{
LTEXT "Geben Sie Benutzernamen und Kennwort ein:", -1, 40, 6, 150, 15
LTEXT "Proxy", -1, 40, 26, 50, 10
LTEXT "Realm", -1, 40, 46, 50, 10
LTEXT "Ben&utzername", -1, 40, 66, 50, 10
LTEXT "Bereich", -1, 40, 46, 50, 10
LTEXT "Ben&utzer", -1, 40, 66, 50, 10
LTEXT "Kenn&wort", -1, 40, 86, 50, 10
LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
@ -38,6 +43,26 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "Abbrechen", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Benutzeranmeldung"
FONT 8, "MS Shell Dlg"
{
LTEXT "Geben Sie Benutzernamen und Kennwort ein:", -1, 40, 6, 150, 15
LTEXT "Server", -1, 40, 26, 50, 10
LTEXT "Bereich", -1, 40, 46, 50, 10
LTEXT "Benutzer", -1, 40, 66, 50, 10
LTEXT "Kennwort", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "Dieses &Kennwort speichern (unsicher)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Abbrechen", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "LAN Verbindung"

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
@ -38,6 +40,26 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "Cancel", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Authentication Required"
FONT 8, "MS Shell Dlg"
{
LTEXT "Please enter your username and password:", -1, 40, 6, 150, 15
LTEXT "Server", -1, 40, 26, 50, 10
LTEXT "Realm", -1, 40, 46, 50, 10
LTEXT "User", -1, 40, 66, 50, 10
LTEXT "Password", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Save this password (insecure)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Cancel", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "LAN Connection"

View file

@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_ESPERANTO, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_FINNISH, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -3,8 +3,9 @@
* French language support
*
* Copyright 2003 Mike McCormack for CodeWeavers
* Copyright 2003 Vincent Béron
* Copyright 2003 Vincent Béron
* Copyright 2005 Jonathan Ernst
* Copyright 2009 Frédéric Delanoy
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -21,29 +22,54 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
/* UTF-8 */
#pragma code_page(65001)
LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 218, 150
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Entrez le mot de passe réseau"
CAPTION "Entrez le mot de passe réseau"
FONT 8, "MS Shell Dlg"
{
LTEXT "Entrez votre nom d'utilisateur et votre mot de passe :", -1, 40, 6, 150, 15
LTEXT "Mandataire", -1, 40, 26, 50, 10
LTEXT "Domaine", -1, 40, 46, 50, 10
LTEXT "Utilisateur", -1, 40, 66, 50, 10
LTEXT "Mot de passe", -1, 40, 86, 50, 10
LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Enregistrer ce mot de passe (risqué)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Annuler", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
LTEXT "Entrez votre nom d'utilisateur et votre mot de passe :", -1, 10, 8, 173, 12
LTEXT "Serveur mandataire", -1, 10, 28, 50, 17
LTEXT "Domaine", -1, 10, 50, 50, 10
LTEXT "Utilisateur", -1, 10, 71, 50, 10
LTEXT "Mot de passe", -1, 10, 90, 50, 10
LTEXT "" IDC_PROXY, 58, 28, 150, 14, 0
LTEXT "" IDC_REALM, 58, 48, 150, 14, 0
EDITTEXT IDC_USERNAME, 58, 68, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 58, 88, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Enregistrer ce mot de passe (risqué)", IDC_SAVEPASSWORD,
58, 108, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 87, 128, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Annuler", IDCANCEL, 147, 128, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 218, 150
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Authentification requise"
FONT 8, "MS Shell Dlg"
{
LTEXT "Entrez votre nom d'utilisateur et votre mot de passe :", -1, 10, 8, 173, 12
LTEXT "Serveur", -1, 10, 28, 50, 17
LTEXT "Domaine", -1, 10, 50, 50, 10
LTEXT "Utilisateur", -1, 10, 71, 50, 10
LTEXT "Mot de passe", -1, 10, 90, 50, 10
LTEXT "" IDC_SERVER, 58, 28, 150, 14, 0
LTEXT "" IDC_REALM, 58, 48, 150, 14, 0
EDITTEXT IDC_USERNAME, 58, 68, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 58, 88, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Enregistrer ce mot de passe (risqué)", IDC_SAVEPASSWORD,
58, 108, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 87, 128, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Annuler", IDCANCEL, 147, 128, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "Connexion LAN"
IDS_LANCONNECTION "Connexion réseau local (LAN)"
}

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
@ -40,6 +42,26 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "Annulla", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Autenticazione richiesta"
FONT 8, "MS Shell Dlg"
{
LTEXT "Inserire il nome utente e la password:", -1, 40, 6, 150, 15
LTEXT "Server", -1, 40, 26, 50, 10
LTEXT "Realm", -1, 40, 46, 50, 10
LTEXT "Utente", -1, 40, 66, 50, 10
LTEXT "Password", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Memorizza la password (RISCHIOSO)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Annulla", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "Connessione LAN"

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
/* UTF-8 */
#pragma code_page(65001)
@ -45,5 +47,3 @@ STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "LAN 接続"
}
#pragma code_page(default)

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -0,0 +1,69 @@
/*
* Copyright 2009 Aurimas Fišeras <aurimas@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
/* UTF-8 */
#pragma code_page(65001)
LANGUAGE LANG_LITHUANIAN, SUBLANG_NEUTRAL
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Įveskite tinklo slaptažodį"
FONT 8, "MS Shell Dlg"
{
LTEXT "Įveskite savo naudotojo vardą ir slaptažodį:", -1, 40, 6, 150, 15
LTEXT "Įgaliot. serv.", -1, 40, 26, 50, 10
LTEXT "Sritis", -1, 40, 46, 50, 10
LTEXT "Naudotojas", -1, 40, 66, 50, 10
LTEXT "Slaptažodis", -1, 40, 86, 50, 10
LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "Į&rašyti šį slaptažodį (nesaugu)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "Gerai", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Atsisakyti", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Reikalingas tapatumo nustatymas"
FONT 8, "MS Shell Dlg"
{
LTEXT "Įveskite savo naudotojo vardą ir slaptažodį:", -1, 40, 6, 150, 15
LTEXT "Serveris", -1, 40, 26, 50, 10
LTEXT "Sritis", -1, 40, 46, 50, 10
LTEXT "Naudotojas", -1, 40, 66, 50, 10
LTEXT "Slaptažodis", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "Į&rašyti šį slaptažodį (nesaugu)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "Gerai", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Atsisakyti", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "Vietinio tinklo ryšys"
}

View file

@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
@ -40,6 +42,26 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "Annuleren", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Authenticatie vereist"
FONT 8, "MS Shell Dlg"
{
LTEXT "Voer uw gebruikersnaam en wachtwoord in:", -1, 40, 6, 150, 15
LTEXT "Server", -1, 40, 26, 50, 10
LTEXT "Realm", -1, 40, 46, 50, 10
LTEXT "Gebruikersnaam", -1, 40, 66, 50, 10
LTEXT "Wachtwoord", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Wachtwoord opslaan (onveilig)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Annuleren", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "LAN Verbinding"

View file

@ -1,5 +1,5 @@
/*
* Copyright 2005 Alexander N. Sørnes <alex@thehandofagony.com>
* Copyright 2005-2009 Alexander N. Sørnes <alex@thehandofagony.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -16,6 +16,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
#pragma code_page(65001)
LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
@ -25,7 +29,7 @@ FONT 8, "MS Shell Dlg"
{
LTEXT "Skriv inn brukernavnet og passordet ditt:", -1, 40, 6, 150, 15
LTEXT "Mellomtjener", -1, 40, 26, 50, 10
LTEXT "Område", -1, 40, 46, 50, 10
LTEXT "Område", -1, 40, 46, 50, 10
LTEXT "Bruker", -1, 40, 66, 50, 10
LTEXT "Passord", -1, 40, 86, 50, 10
LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0
@ -38,6 +42,26 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "Avbryt", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Pålogging"
FONT 8, "MS Shell Dlg"
{
LTEXT "Oppgi brukernavn og passord:", -1, 40, 6, 150, 15
LTEXT "Tjener", -1, 40, 26, 50, 10
LTEXT "Område", -1, 40, 46, 50, 10
LTEXT "Bruker", -1, 40, 66, 50, 10
LTEXT "Passord", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "Lagre pa&ssordet (sikkerhetsrisiko)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Avbryt", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "Lokal nettverksforbindelse"

View file

@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -1,6 +1,7 @@
/*
* Copyright 2003 Marcelo Duarte
* Copyright 2006-2007 Américo José Melo
* Copyright 2006-2007 Américo José Melo
* Copyright 2009 Ricardo Filipe
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -17,6 +18,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
#pragma code_page(65001)
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
@ -24,10 +29,10 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Entrar Senha da Rede"
FONT 8, "MS Shell Dlg"
{
LTEXT "Por favor, entre com o nome de usuário e a senha:", -1, 40, 6, 150, 15
LTEXT "Por favor, entre com o nome de usuário e a senha:", -1, 40, 6, 150, 15
LTEXT "Proxy", -1, 40, 26, 50, 10
LTEXT "Realm", -1, 40, 46, 50, 10
LTEXT "Usuário", -1, 40, 66, 50, 10
LTEXT "Usuário", -1, 40, 66, 50, 10
LTEXT "Senha", -1, 40, 86, 50, 10
LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
@ -61,17 +66,36 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "Cancelar", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Autenticação necessária"
FONT 8, "MS Shell Dlg"
{
LTEXT "Por favor insira o seu nome de utilizador e palavra-passe:", -1, 40, 6, 150, 15
LTEXT "Servidor", -1, 40, 26, 50, 10
LTEXT "Reino", -1, 40, 46, 50, 10
LTEXT "Utilizador", -1, 40, 66, 50, 10
LTEXT "Palavra-passe", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Guardar esta palavra-passe (inseguro)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Cancelar", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "Conexão LAN"
IDS_LANCONNECTION "Conexão LAN"
}
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "Ligação LAN"
IDS_LANCONNECTION "Ligação LAN"
}

View file

@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
#pragma code_page(65001)
@ -28,7 +30,7 @@ FONT 8, "MS Shell Dlg"
{
LTEXT "Introduceți numele de utilizator și parola:", -1, 40, 6, 150, 15
LTEXT "Proxy", -1, 40, 26, 50, 10
LTEXT "Realm", -1, 40, 46, 50, 10
LTEXT "Domeniu", -1, 40, 46, 50, 10
LTEXT "Utilizator", -1, 40, 66, 50, 10
LTEXT "Parolă", -1, 40, 86, 50, 10
LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0
@ -41,9 +43,27 @@ FONT 8, "MS Shell Dlg"
PUSHBUTTON "Renunță", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Autentificare necesară"
FONT 8, "MS Shell Dlg"
{
LTEXT "Introduceți numele de utilizator și parola:", -1, 40, 6, 150, 15
LTEXT "Server", -1, 40, 26, 50, 10
LTEXT "Domeniu", -1, 40, 46, 50, 10
LTEXT "Utilizator", -1, 40, 66, 50, 10
LTEXT "Parolă", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Salvează această parolă (nesigur)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Renunță", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "Conexiune LAN"
}
#pragma code_page(default)

View file

@ -18,29 +18,54 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
/* UTF-8 */
#pragma code_page(65001)
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Ввод сетевого пароля"
CAPTION "Ввод сетевого пароля"
FONT 8, "MS Shell Dlg"
{
LTEXT "Введите имя пользователя и пароль:", -1, 40, 6, 150, 15
LTEXT "Прокси", -1, 40, 26, 50, 10
LTEXT "Домен", -1, 40, 46, 50, 10
LTEXT "Пользователь", -1, 40, 66, 50, 10
LTEXT "Пароль", -1, 40, 86, 50, 10
LTEXT "Введите имя пользователя и пароль:", -1, 40, 6, 150, 15
LTEXT "Прокси", -1, 40, 26, 50, 10
LTEXT "Домен", -1, 40, 46, 50, 10
LTEXT "Пользователь", -1, 40, 66, 50, 10
LTEXT "Пароль", -1, 40, 86, 50, 10
LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Сохранить этот пароль (небезопасно)", IDC_SAVEPASSWORD,
CHECKBOX "&Сохранить этот пароль (небезопасно)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Отмена", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
PUSHBUTTON "Отмена", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
IDD_AUTHDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Требуется идентификация"
FONT 8, "MS Shell Dlg"
{
LTEXT "Введите имя пользователя и пароль:", -1, 40, 6, 150, 15
LTEXT "Сервер", -1, 40, 26, 50, 10
LTEXT "Домен", -1, 40, 46, 50, 10
LTEXT "Пользователь", -1, 40, 66, 50, 10
LTEXT "Пароль", -1, 40, 86, 50, 10
LTEXT "" IDC_SERVER, 80, 26, 150, 14, 0
LTEXT "" IDC_REALM, 80, 46, 150, 14, 0
EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD
CHECKBOX "&Сохранить этот пароль (небезопасно)", IDC_SAVEPASSWORD,
80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON
PUSHBUTTON "Отмена", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP
}
STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "Сетевое подключение"
IDS_LANCONNECTION "Сетевое подключение"
}

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
#pragma code_page(65001)
LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT
@ -44,5 +46,3 @@ STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "LAN povezava"
}
#pragma code_page(default)

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

View file

@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "resource.h"
LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154

Some files were not shown because too many files have changed in this diff Show more