mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 22:18:13 +00:00
Sync with trunk head (part 1 of 2)
svn path=/branches/header-work/; revision=46262
This commit is contained in:
commit
b797eef5ea
143 changed files with 15887 additions and 8167 deletions
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}};
|
||||
|
|
|
@ -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>
|
||||
|
|
157
dll/directx/ksproxy/node.cpp
Normal file
157
dll/directx/ksproxy/node.cpp
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
412
dll/win32/dbghelp/cpu_i386.c
Normal file
412
dll/win32/dbghelp/cpu_i386.c
Normal 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,
|
||||
};
|
62
dll/win32/dbghelp/cpu_ppc.c
Normal file
62
dll/win32/dbghelp/cpu_ppc.c
Normal 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,
|
||||
};
|
132
dll/win32/dbghelp/cpu_x86_64.c
Normal file
132
dll/win32/dbghelp/cpu_x86_64.c
Normal 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
149
dll/win32/dbghelp/crc32.c
Normal 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
|
||||
}
|
|
@ -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 !! */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
1434
dll/win32/dbghelp/macho_module.c
Normal file
1434
dll/win32/dbghelp/macho_module.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.@)
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
|
26
dll/win32/dbghelp/version.rc
Normal file
26
dll/win32/dbghelp/version.rc
Normal 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"
|
130
dll/win32/faultrep/faultrep.c
Normal file
130
dll/win32/faultrep/faultrep.c
Normal 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;
|
||||
}
|
9
dll/win32/faultrep/faultrep.rbuild
Normal file
9
dll/win32/faultrep/faultrep.rbuild
Normal 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>
|
14
dll/win32/faultrep/faultrep.spec
Normal file
14
dll/win32/faultrep/faultrep.spec
Normal 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
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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]
|
||||
*/
|
||||
|
|
|
@ -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
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) ¶ms );
|
||||
|
||||
case ERROR_INTERNET_INCORRECT_PASSWORD:
|
||||
return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
|
||||
hWnd, WININET_ProxyPasswordDialog, (LPARAM) ¶ms );
|
||||
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) ¶ms );
|
||||
case HTTP_STATUS_DENIED:
|
||||
return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_AUTHDLG ),
|
||||
hWnd, WININET_PasswordDialog, (LPARAM) ¶ms );
|
||||
default:
|
||||
WARN("unhandled status %u\n", dwStatus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ERROR_INTERNET_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
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
69
dll/win32/wininet/wininet_Lt.rc
Normal file
69
dll/win32/wininet/wininet_Lt.rc
Normal 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"
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 "Сетевое подключение"
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue