diff --git a/base/applications/dxdiag/dxdiag.c b/base/applications/dxdiag/dxdiag.c
index 3985fae208d..2c9bc701baf 100644
--- a/base/applications/dxdiag/dxdiag.c
+++ b/base/applications/dxdiag/dxdiag.c
@@ -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;
diff --git a/base/applications/dxdiag/system.c b/base/applications/dxdiag/system.c
index 33c1f9d5bde..311fc03cdf7 100644
--- a/base/applications/dxdiag/system.c
+++ b/base/applications/dxdiag/system.c
@@ -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))
diff --git a/base/applications/rapps/rapps/firefox3.txt b/base/applications/rapps/rapps/firefox3.txt
index d4d2272179a..072eee6407b 100644
--- a/base/applications/rapps/rapps/firefox3.txt
+++ b/base/applications/rapps/rapps/firefox3.txt
@@ -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
diff --git a/base/applications/rapps/rapps/openoffice2.4.txt b/base/applications/rapps/rapps/openoffice2.4.txt
index 81cae28edf9..d68f92e3418 100644
--- a/base/applications/rapps/rapps/openoffice2.4.txt
+++ b/base/applications/rapps/rapps/openoffice2.4.txt
@@ -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
diff --git a/base/applications/rapps/rapps/openoffice3.0.txt b/base/applications/rapps/rapps/openoffice3.0.txt
index ebfc63ede1c..b9ee71bd025 100644
--- a/base/applications/rapps/rapps/openoffice3.0.txt
+++ b/base/applications/rapps/rapps/openoffice3.0.txt
@@ -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
diff --git a/base/applications/rapps/rapps/scite.txt b/base/applications/rapps/rapps/scite.txt
index 5e2562dacbe..fc3d9d50cca 100644
--- a/base/applications/rapps/rapps/scite.txt
+++ b/base/applications/rapps/rapps/scite.txt
@@ -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]
diff --git a/base/services/eventlog/eventlog.c b/base/services/eventlog/eventlog.c
index 4f0120a662d..70663351ab5 100644
--- a/base/services/eventlog/eventlog.c
+++ b/base/services/eventlog/eventlog.c
@@ -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");
}
diff --git a/base/services/eventlog/eventlog.h b/base/services/eventlog/eventlog.h
index 4b9c6a8c341..df0ab151c41 100644
--- a/base/services/eventlog/eventlog.h
+++ b/base/services/eventlog/eventlog.h
@@ -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;
diff --git a/base/services/eventlog/rpc.c b/base/services/eventlog/rpc.c
index e3ef33d1611..d399d1e600f 100644
--- a/base/services/eventlog/rpc.c
+++ b/base/services/eventlog/rpc.c
@@ -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;
}
diff --git a/baseaddress.rbuild b/baseaddress.rbuild
index 6099bf8c332..cacc80f77f3 100644
--- a/baseaddress.rbuild
+++ b/baseaddress.rbuild
@@ -3,6 +3,7 @@
+
diff --git a/boot/bootdata/packages/reactos.dff b/boot/bootdata/packages/reactos.dff
index e5fb874f849..75db78068b1 100644
--- a/boot/bootdata/packages/reactos.dff
+++ b/boot/bootdata/packages/reactos.dff
@@ -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
diff --git a/boot/freeldr/freeldr/windows/winldr.c b/boot/freeldr/freeldr/windows/winldr.c
index 4ba7b1bcb29..f3f7cd199b7 100644
--- a/boot/freeldr/freeldr/windows/winldr.c
+++ b/boot/freeldr/freeldr/windows/winldr.c
@@ -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;
diff --git a/dll/directx/ksproxy/datatype.cpp b/dll/directx/ksproxy/datatype.cpp
index 3d132890dfd..5006b68a121 100644
--- a/dll/directx/ksproxy/datatype.cpp
+++ b/dll/directx/ksproxy/datatype.cpp
@@ -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)
diff --git a/dll/directx/ksproxy/input_pin.cpp b/dll/directx/ksproxy/input_pin.cpp
index ce2cef4600d..e95894f4efa 100644
--- a/dll/directx/ksproxy/input_pin.cpp
+++ b/dll/directx/ksproxy/input_pin.cpp
@@ -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(*Output)->AddRef();
return NOERROR;
}
-
+ else if (IsEqualGUID(refiid, IID_IKsPinPipe))
+ {
+ *Output = (IKsPinPipe*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IKsPinFactory))
+ {
+ *Output = (IKsPinFactory*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+#if 0
+ else if (IsEqualGUID(refiid, IID_IStreamBuilder))
+ {
+ *Output = (IStreamBuilder*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+#endif
+ else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
+ {
+ *Output = (IKsAggregateControl*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IQualityControl))
+ {
+ *Output = (IQualityControl*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
+ {
+ *Output = (ISpecifyPropertyPages*)(this);
+ reinterpret_cast(*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);
diff --git a/dll/directx/ksproxy/interface.cpp b/dll/directx/ksproxy/interface.cpp
index 4289cd1fc11..930f7e00b73 100644
--- a/dll/directx/ksproxy/interface.cpp
+++ b/dll/directx/ksproxy/interface.cpp
@@ -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
diff --git a/dll/directx/ksproxy/ksproxy.cpp b/dll/directx/ksproxy/ksproxy.cpp
index 237b0390427..f79a154574b 100644
--- a/dll/directx/ksproxy/ksproxy.cpp
+++ b/dll/directx/ksproxy/ksproxy.cpp
@@ -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}};
diff --git a/dll/directx/ksproxy/ksproxy.rbuild b/dll/directx/ksproxy/ksproxy.rbuild
index 440e279e86a..e5bc87e9b4a 100644
--- a/dll/directx/ksproxy/ksproxy.rbuild
+++ b/dll/directx/ksproxy/ksproxy.rbuild
@@ -33,6 +33,7 @@
interface.cpp
ksproxy.cpp
ksproxy.rc
+ node.cpp
output_pin.cpp
proxy.cpp
qualityforward.cpp
diff --git a/dll/directx/ksproxy/node.cpp b/dll/directx/ksproxy/node.cpp
new file mode 100644
index 00000000000..d2686bb96a4
--- /dev/null
+++ b/dll/directx/ksproxy/node.cpp
@@ -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(*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;
+}
diff --git a/dll/directx/ksproxy/output_pin.cpp b/dll/directx/ksproxy/output_pin.cpp
index d21f3832f15..52f9cc94f7a 100644
--- a/dll/directx/ksproxy/output_pin.cpp
+++ b/dll/directx/ksproxy/output_pin.cpp
@@ -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(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsObject))
{
+ OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n");
*Output = (IKsObject*)(this);
reinterpret_cast(*Output)->AddRef();
return NOERROR;
}
+ else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx))
+ {
+ *Output = (IKsPinEx*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IKsPinPipe))
+ {
+ *Output = (IKsPinPipe*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IKsAggregateControl))
+ {
+ *Output = (IKsAggregateControl*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IQualityControl))
+ {
+ *Output = (IQualityControl*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
else if (IsEqualGUID(refiid, IID_IKsPropertySet))
{
+ OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n");
+ DebugBreak();
*Output = (IKsPropertySet*)(this);
reinterpret_cast(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_IKsControl))
{
+ OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n");
*Output = (IKsControl*)(this);
reinterpret_cast(*Output)->AddRef();
return NOERROR;
}
+#if 0
else if (IsEqualGUID(refiid, IID_IStreamBuilder))
{
*Output = (IStreamBuilder*)(this);
reinterpret_cast(*Output)->AddRef();
return NOERROR;
}
+#endif
else if (IsEqualGUID(refiid, IID_IKsPinFactory))
{
+ OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n");
*Output = (IKsPinFactory*)(this);
reinterpret_cast(*Output)->AddRef();
return NOERROR;
}
else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
{
+ OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n");
*Output = (ISpecifyPropertyPages*)(this);
reinterpret_cast(*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(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation))
+ {
+ *Output = (IAMBufferNegotiation*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IAMStreamConfig))
+ {
+ *Output = (IAMStreamConfig*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp))
+ {
+ *Output = (IMemAllocatorNotifyCallbackTemp*)(this);
+ reinterpret_cast(*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;
}
}
diff --git a/dll/directx/ksproxy/precomp.h b/dll/directx/ksproxy/precomp.h
index 5078daef9a9..2ea89aa0887 100644
--- a/dll/directx/ksproxy/precomp.h
+++ b/dll/directx/ksproxy/precomp.h
@@ -19,8 +19,23 @@
#include
#include
#include
+#include
//#include
+
+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;
diff --git a/dll/directx/ksproxy/proxy.cpp b/dll/directx/ksproxy/proxy.cpp
index f74f22ba9f7..371176f2437 100644
--- a/dll/directx/ksproxy/proxy.cpp
+++ b/dll/directx/ksproxy/proxy.cpp
@@ -14,13 +14,17 @@ const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00,
const GUID IID_ISpecifyPropertyPages = {0xB196B28B, 0xBAB4, 0x101A, {0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}};
const GUID IID_IPersistStream = {0x00000109, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
const GUID KSPROPSETID_MediaSeeking = {0xEE904F0CL, 0xD09B, 0x11D0, {0xAB, 0xE9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSPROPSETID_Clock = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+const GUID KSEVENTSETID_Clock = {0x364D8E20L, 0x62C7, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+const GUID KSPROPSETID_Stream = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
+const GUID IID_IPersist = {0x0000010c, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
#endif
const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}};
const GUID IID_IKsAggregateControl = {0x7F40EAC0, 0x3947, 0x11D2, {0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
const GUID IID_IKsClockPropertySet = {0x5C5CBD84, 0xE755, 0x11D0, {0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
const GUID IID_IKsTopology = {0x28F54683, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
-
+const GUID IID_IKsClock = {0x877E4351, 0x6FEA, 0x11D0, {0xB8, 0x63, 0x00, 0xAA, 0x00, 0xA2, 0x16, 0xA1}};
/*
Needs IKsClock, IKsNotifyEvent
*/
@@ -35,6 +39,7 @@ class CKsProxy : public IBaseFilter,
public IReferenceClock,
public IMediaSeeking,
public IKsPropertySet,
+ public IKsClock,
public IKsClockPropertySet,
public IAMFilterMiscFlags,
public IKsControl,
@@ -148,6 +153,9 @@ public:
// IKsObject
HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
+ // IKsClock
+ HANDLE STDMETHODCALLTYPE KsGetClockHandle();
+
//IAMDeviceRemoval
HRESULT STDMETHODCALLTYPE DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink);
HRESULT STDMETHODCALLTYPE Reassociate(void);
@@ -163,7 +171,7 @@ public:
HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
- CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0) {};
+ CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0), m_hClock(0) {};
~CKsProxy()
{
if (m_hDevice)
@@ -178,6 +186,9 @@ public:
HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName);
HRESULT STDMETHODCALLTYPE GetPinCommunication(ULONG PinId, KSPIN_COMMUNICATION * Communication);
HRESULT STDMETHODCALLTYPE CreatePins();
+ HRESULT STDMETHODCALLTYPE GetMediaSeekingFormats(PKSMULTIPLE_ITEM *FormatList);
+ HRESULT STDMETHODCALLTYPE CreateClockInstance();
+ HRESULT STDMETHODCALLTYPE PerformClockProperty(ULONG PropertyId, ULONG PropertyFlags, PVOID OutputBuffer, ULONG OutputBufferSize);
protected:
LONG m_Ref;
IFilterGraph *m_pGraph;
@@ -188,6 +199,7 @@ protected:
PinVector m_Pins;
LPWSTR m_DevicePath;
CLSID m_DeviceInterfaceGUID;
+ HANDLE m_hClock;
};
HRESULT
@@ -196,7 +208,7 @@ CKsProxy::QueryInterface(
IN REFIID refiid,
OUT PVOID* Output)
{
- *Output = (PVOID)0xDEADDEAD;//NULL;
+ *Output = NULL;
if (IsEqualGUID(refiid, IID_IUnknown) ||
IsEqualGUID(refiid, IID_IBaseFilter))
@@ -223,14 +235,33 @@ CKsProxy::QueryInterface(
reinterpret_cast(*Output)->AddRef();
return NOERROR;
}
+ else if (IsEqualGUID(refiid, IID_IPersist))
+ {
+ *Output = (IPersistStream*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
else if (IsEqualGUID(refiid, IID_IKsObject))
{
*Output = (IKsObject*)(this);
reinterpret_cast(*Output)->AddRef();
return NOERROR;
}
+ else if (IsEqualGUID(refiid, IID_IKsClock))
+ {
+ *Output = (IKsClock*)(this);
+ reinterpret_cast(*Output)->AddRef();
+ return NOERROR;
+ }
else if (IsEqualGUID(refiid, IID_IReferenceClock))
{
+ if (!m_hClock)
+ {
+ HRESULT hr = CreateClockInstance();
+ if (FAILED(hr))
+ return hr;
+ }
+
*Output = (IReferenceClock*)(this);
reinterpret_cast(*Output)->AddRef();
return NOERROR;
@@ -273,6 +304,13 @@ CKsProxy::QueryInterface(
}
else if (IsEqualGUID(refiid, IID_IKsClockPropertySet))
{
+ if (!m_hClock)
+ {
+ HRESULT hr = CreateClockInstance();
+ if (FAILED(hr))
+ return hr;
+ }
+
*Output = (IKsClockPropertySet*)(this);
reinterpret_cast(*Output)->AddRef();
return NOERROR;
@@ -335,13 +373,110 @@ CKsProxy::GetPages(CAUUID *pPages)
//-------------------------------------------------------------------
// IKsClockPropertySet interface
//
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::CreateClockInstance()
+{
+ HRESULT hr;
+ HANDLE hPin = INVALID_HANDLE_VALUE;
+ ULONG Index;
+ PIN_DIRECTION PinDir;
+ IKsObject *pObject;
+ KSCLOCK_CREATE ClockCreate;
+
+ // find output pin and handle
+ for(Index = 0; Index < m_Pins.size(); Index++)
+ {
+ //get pin
+ IPin * pin = m_Pins[Index];
+ if (!pin)
+ continue;
+
+ // get direction
+ hr = pin->QueryDirection(&PinDir);
+ if (FAILED(hr))
+ continue;
+
+ // query IKsObject interface
+ hr = pin->QueryInterface(IID_IKsObject, (void**)&pObject);
+ if (FAILED(hr))
+ continue;
+
+
+ // get pin handle
+ hPin = pObject->KsGetObjectHandle();
+
+ //release IKsObject
+ pObject->Release();
+
+ if (hPin != INVALID_HANDLE_VALUE)
+ break;
+ }
+
+ if (hPin == INVALID_HANDLE_VALUE)
+ {
+ // clock can only be instantiated on a pin handle
+ return E_NOTIMPL;
+ }
+
+ if (m_hClock)
+ {
+ // release clock handle
+ CloseHandle(m_hClock);
+ }
+
+ //setup clock create request
+ ClockCreate.CreateFlags = 0;
+
+ // setup clock create request
+ hr = KsCreateClock(hPin, &ClockCreate, &m_hClock); // FIXME KsCreateClock returns NTSTATUS
+ if (SUCCEEDED(hr))
+ {
+ // failed to create clock
+ return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
+ }
+
+ return S_OK;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::PerformClockProperty(
+ ULONG PropertyId,
+ ULONG PropertyFlags,
+ PVOID OutputBuffer,
+ ULONG OutputBufferSize)
+{
+ KSPROPERTY Property;
+ HRESULT hr;
+ ULONG BytesReturned;
+
+ if (!m_hClock)
+ {
+ // create clock
+ hr = CreateClockInstance();
+ if (FAILED(hr))
+ return hr;
+ }
+
+ // setup request
+ Property.Set = KSPROPSETID_Clock;
+ Property.Id = PropertyId;
+ Property.Flags = PropertyFlags;
+
+ hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)OutputBuffer, OutputBufferSize, &BytesReturned);
+
+ return hr;
+}
+
HRESULT
STDMETHODCALLTYPE
CKsProxy::KsGetTime(
LONGLONG* Time)
{
- OutputDebugStringW(L"CKsProxy::KsGetTime NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsGetTime\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG));
}
HRESULT
@@ -349,8 +484,8 @@ STDMETHODCALLTYPE
CKsProxy::KsSetTime(
LONGLONG Time)
{
- OutputDebugStringW(L"CKsProxy::KsSetTime NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsSetTime\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG));
}
HRESULT
@@ -358,8 +493,8 @@ STDMETHODCALLTYPE
CKsProxy::KsGetPhysicalTime(
LONGLONG* Time)
{
- OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG));
}
HRESULT
@@ -368,7 +503,7 @@ CKsProxy::KsSetPhysicalTime(
LONGLONG Time)
{
OutputDebugStringW(L"CKsProxy::KsSetPhysicalTime NotImplemented\n");
- return E_NOTIMPL;
+ return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG));
}
HRESULT
@@ -376,8 +511,8 @@ STDMETHODCALLTYPE
CKsProxy::KsGetCorrelatedTime(
KSCORRELATED_TIME* CorrelatedTime)
{
- OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
}
HRESULT
@@ -385,8 +520,8 @@ STDMETHODCALLTYPE
CKsProxy::KsSetCorrelatedTime(
KSCORRELATED_TIME* CorrelatedTime)
{
- OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
}
HRESULT
@@ -394,8 +529,8 @@ STDMETHODCALLTYPE
CKsProxy::KsGetCorrelatedPhysicalTime(
KSCORRELATED_TIME* CorrelatedTime)
{
- OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
}
HRESULT
@@ -403,8 +538,8 @@ STDMETHODCALLTYPE
CKsProxy::KsSetCorrelatedPhysicalTime(
KSCORRELATED_TIME* CorrelatedTime)
{
- OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
}
HRESULT
@@ -412,8 +547,8 @@ STDMETHODCALLTYPE
CKsProxy::KsGetResolution(
KSRESOLUTION* Resolution)
{
- OutputDebugStringW(L"CKsProxy::KsGetResolution NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsGetResolution\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_RESOLUTION, KSPROPERTY_TYPE_GET, (PVOID)Resolution, sizeof(KSRESOLUTION));
}
HRESULT
@@ -421,8 +556,8 @@ STDMETHODCALLTYPE
CKsProxy::KsGetState(
KSSTATE* State)
{
- OutputDebugStringW(L"CKsProxy::KsGetState NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::KsGetState\n");
+ return PerformClockProperty(KSPROPERTY_CLOCK_STATE, KSPROPERTY_TYPE_GET, (PVOID)State, sizeof(KSSTATE));
}
//-------------------------------------------------------------------
@@ -433,8 +568,40 @@ STDMETHODCALLTYPE
CKsProxy::GetTime(
REFERENCE_TIME *pTime)
{
- OutputDebugStringW(L"CKsProxy::GetTime NotImplemented\n");
- return E_NOTIMPL;
+ HRESULT hr;
+ KSPROPERTY Property;
+ ULONG BytesReturned;
+
+ OutputDebugStringW(L"CKsProxy::GetTime\n");
+
+ if (!pTime)
+ return E_POINTER;
+
+ //
+ //FIXME locks
+ //
+
+ if (!m_hClock)
+ {
+ // create clock
+ hr = CreateClockInstance();
+ if (FAILED(hr))
+ return hr;
+ }
+
+ // setup request
+ Property.Set = KSPROPSETID_Clock;
+ Property.Id = KSPROPERTY_CLOCK_TIME;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ // perform request
+ hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pTime, sizeof(REFERENCE_TIME), &BytesReturned);
+
+ // TODO
+ // increment value
+ //
+
+ return hr;
}
HRESULT
@@ -445,8 +612,62 @@ CKsProxy::AdviseTime(
HEVENT hEvent,
DWORD_PTR *pdwAdviseCookie)
{
- OutputDebugStringW(L"CKsProxy::AdviseTime NotImplemented\n");
- return E_NOTIMPL;
+ HRESULT hr;
+ KSEVENT Property;
+ ULONG BytesReturned;
+ PKSEVENT_TIME_MARK Event;
+
+ OutputDebugStringW(L"CKsProxy::AdviseTime\n");
+
+ //
+ //FIXME locks
+ //
+
+ if (!pdwAdviseCookie)
+ return E_POINTER;
+
+ if (!m_hClock)
+ {
+ // create clock
+ hr = CreateClockInstance();
+ if (FAILED(hr))
+ return hr;
+ }
+
+ // allocate event entry
+ Event = (PKSEVENT_TIME_MARK)CoTaskMemAlloc(sizeof(KSEVENT_TIME_MARK));
+ if (Event)
+ {
+ // setup request
+ Property.Set = KSEVENTSETID_Clock;
+ Property.Id = KSEVENT_CLOCK_POSITION_MARK;
+ Property.Flags = KSEVENT_TYPE_ENABLE;
+
+ Event->EventData.NotificationType = KSEVENTF_EVENT_HANDLE;
+ Event->EventData.EventHandle.Event = (HANDLE)hEvent;
+ Event->EventData.Alignment.Alignment[0] = 0;
+ Event->EventData.Alignment.Alignment[1] = 0;
+ Event->MarkTime = baseTime + streamTime;
+
+ // perform request
+ hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSEVENT), (PVOID)Event, sizeof(KSEVENT_TIME_MARK), &BytesReturned);
+ if (SUCCEEDED(hr))
+ {
+ // store event handle
+ *pdwAdviseCookie = (DWORD_PTR)Event;
+ }
+ else
+ {
+ // failed to enable event
+ CoTaskMemFree(Event);
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ return hr;
}
HRESULT
@@ -457,8 +678,63 @@ CKsProxy::AdvisePeriodic(
HSEMAPHORE hSemaphore,
DWORD_PTR *pdwAdviseCookie)
{
- OutputDebugStringW(L"CKsProxy::AdvisePeriodic NotImplemented\n");
- return E_NOTIMPL;
+ HRESULT hr;
+ KSEVENT Property;
+ ULONG BytesReturned;
+ PKSEVENT_TIME_INTERVAL Event;
+
+ OutputDebugStringW(L"CKsProxy::AdvisePeriodic\n");
+
+ //
+ //FIXME locks
+ //
+
+ if (!pdwAdviseCookie)
+ return E_POINTER;
+
+ if (!m_hClock)
+ {
+ // create clock
+ hr = CreateClockInstance();
+ if (FAILED(hr))
+ return hr;
+ }
+
+ // allocate event entry
+ Event = (PKSEVENT_TIME_INTERVAL)CoTaskMemAlloc(sizeof(KSEVENT_TIME_INTERVAL));
+ if (Event)
+ {
+ // setup request
+ Property.Set = KSEVENTSETID_Clock;
+ Property.Id = KSEVENT_CLOCK_INTERVAL_MARK;
+ Property.Flags = KSEVENT_TYPE_ENABLE;
+
+ Event->EventData.NotificationType = KSEVENTF_SEMAPHORE_HANDLE;
+ Event->EventData.SemaphoreHandle.Semaphore = (HANDLE)hSemaphore;
+ Event->EventData.SemaphoreHandle.Reserved = 0;
+ Event->EventData.SemaphoreHandle.Adjustment = 1;
+ Event->TimeBase = startTime;
+ Event->Interval = periodTime;
+
+ // perform request
+ hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSEVENT), (PVOID)Event, sizeof(KSEVENT_TIME_INTERVAL), &BytesReturned);
+ if (SUCCEEDED(hr))
+ {
+ // store event handle
+ *pdwAdviseCookie = (DWORD_PTR)Event;
+ }
+ else
+ {
+ // failed to enable event
+ CoTaskMemFree(Event);
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ return hr;
}
HRESULT
@@ -466,8 +742,28 @@ STDMETHODCALLTYPE
CKsProxy::Unadvise(
DWORD_PTR dwAdviseCookie)
{
- OutputDebugStringW(L"CKsProxy::Unadvise NotImplemented\n");
- return E_NOTIMPL;
+ HRESULT hr;
+ ULONG BytesReturned;
+
+ OutputDebugStringW(L"CKsProxy::Unadvise\n");
+
+ if (m_hClock)
+ {
+ //lets disable the event
+ hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_DISABLE_EVENT, (PVOID)dwAdviseCookie, sizeof(KSEVENTDATA), 0, 0, &BytesReturned);
+ if (SUCCEEDED(hr))
+ {
+ // lets free event data
+ CoTaskMemFree((LPVOID)dwAdviseCookie);
+ }
+ }
+ else
+ {
+ // no clock available
+ hr = E_FAIL;
+ }
+
+ return hr;
}
//-------------------------------------------------------------------
@@ -478,8 +774,55 @@ STDMETHODCALLTYPE
CKsProxy::GetCapabilities(
DWORD *pCapabilities)
{
- OutputDebugStringW(L"CKsProxy::GetCapabilities NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ ULONG BytesReturned, Index;
+ HRESULT hr = S_OK;
+ DWORD TempCaps;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_CAPABILITIES;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ OutputDebugStringW(L"CKsProxy::GetCapabilities\n");
+
+ if (!pCapabilities)
+ return E_POINTER;
+
+
+ *pCapabilities = (KS_SEEKING_CanSeekAbsolute | KS_SEEKING_CanSeekForwards | KS_SEEKING_CanSeekBackwards | KS_SEEKING_CanGetCurrentPos |
+ KS_SEEKING_CanGetStopPos | KS_SEEKING_CanGetDuration | KS_SEEKING_CanPlayBackwards);
+
+ KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pCapabilities, sizeof(KS_SEEKING_CAPABILITIES), &BytesReturned);
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (FAILED(hr))
+ {
+ *pCapabilities = 0;
+ return hr;
+ }
+
+ TempCaps = 0;
+ // set time format
+ hr = pSeek->GetCapabilities(&TempCaps);
+ if (SUCCEEDED(hr))
+ {
+ // and with supported flags
+ *pCapabilities = (*pCapabilities & TempCaps);
+ }
+ // release IMediaSeeking interface
+ pSeek->Release();
+ }
+ return hr;
}
HRESULT
@@ -487,27 +830,49 @@ STDMETHODCALLTYPE
CKsProxy::CheckCapabilities(
DWORD *pCapabilities)
{
- OutputDebugStringW(L"CKsProxy::CheckCapabilities NotImplemented\n");
- return E_NOTIMPL;
+ DWORD Capabilities;
+ HRESULT hr;
+
+ OutputDebugStringW(L"CKsProxy::CheckCapabilities\n");
+
+ if (!pCapabilities)
+ return E_POINTER;
+
+ if (!*pCapabilities)
+ return E_FAIL;
+
+ hr = GetCapabilities(&Capabilities);
+ if (SUCCEEDED(hr))
+ {
+ if ((Capabilities | *pCapabilities) == Capabilities)
+ {
+ // all present
+ return S_OK;
+ }
+
+ Capabilities = (Capabilities & *pCapabilities);
+ if (Capabilities)
+ {
+ // not all present
+ *pCapabilities = Capabilities;
+ return S_FALSE;
+ }
+ // no capabilities are present
+ return E_FAIL;
+ }
+
+ return hr;
}
HRESULT
STDMETHODCALLTYPE
-CKsProxy::IsFormatSupported(
- const GUID *pFormat)
+CKsProxy::GetMediaSeekingFormats(
+ PKSMULTIPLE_ITEM *FormatList)
{
KSPROPERTY Property;
- PKSMULTIPLE_ITEM FormatList;
- LPGUID pGuid;
- ULONG Index;
- HRESULT hr = S_FALSE;
+ HRESULT hr;
ULONG BytesReturned;
- OutputDebugStringW(L"CKsProxy::IsFormatSupported\n");
-
- if (!pFormat)
- return E_POINTER;
-
Property.Set = KSPROPSETID_MediaSeeking;
Property.Id = KSPROPERTY_MEDIASEEKING_FORMATS;
Property.Flags = KSPROPERTY_TYPE_GET;
@@ -518,21 +883,49 @@ CKsProxy::IsFormatSupported(
if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
{
// allocate format list
- FormatList = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
- if (!FormatList)
+ *FormatList = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
+ if (!*FormatList)
{
// not enough memory
return E_OUTOFMEMORY;
}
// get format list
- hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)FormatList, BytesReturned, &BytesReturned);
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)*FormatList, BytesReturned, &BytesReturned);
if (FAILED(hr))
{
// failed to query format list
CoTaskMemFree(FormatList);
- return hr;
}
+ }
+ return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::IsFormatSupported(
+ const GUID *pFormat)
+{
+ PKSMULTIPLE_ITEM FormatList;
+ LPGUID pGuid;
+ ULONG Index;
+ HRESULT hr = S_FALSE;
+
+ WCHAR Buffer[100];
+ LPOLESTR pstr;
+ StringFromCLSID(*pFormat, &pstr);
+ swprintf(Buffer, L"CKsProxy::IsFormatSupported %s\n",pstr);
+ OutputDebugStringW(Buffer);
+
+ if (!pFormat)
+ return E_POINTER;
+
+ // get media formats
+ hr = GetMediaSeekingFormats(&FormatList);
+ if (SUCCEEDED(hr))
+ {
+ swprintf(Buffer, L"CKsProxy::IsFormatSupported NumFormat %lu\n",FormatList->Count);
+ OutputDebugStringW(Buffer);
//iterate through format list
pGuid = (LPGUID)(FormatList + 1);
@@ -540,14 +933,11 @@ CKsProxy::IsFormatSupported(
{
if (IsEqualGUID(*pGuid, *pFormat))
{
- OutputDebugStringW(L"CKsProxy::IsFormatSupported found format\n");
CoTaskMemFree(FormatList);
return S_OK;
}
pGuid++;
}
-
- OutputDebugStringW(L"CKsProxy::IsFormatSupported FormatNotFound\n");
// free format list
CoTaskMemFree(FormatList);
}
@@ -589,8 +979,55 @@ STDMETHODCALLTYPE
CKsProxy::QueryPreferredFormat(
GUID *pFormat)
{
- OutputDebugStringW(L"CKsProxy::QueryPreferredFormat NotImplemented\n");
- return E_NOTIMPL;
+ PKSMULTIPLE_ITEM FormatList;
+ HRESULT hr;
+ ULONG Index;
+
+ OutputDebugStringW(L"CKsProxy::QueryPreferredFormat\n");
+
+ if (!pFormat)
+ return E_POINTER;
+
+ hr = GetMediaSeekingFormats(&FormatList);
+ if (SUCCEEDED(hr))
+ {
+ if (FormatList->Count)
+ {
+ CopyMemory(pFormat, (FormatList + 1), sizeof(GUID));
+ CoTaskMemFree(FormatList);
+ return S_OK;
+ }
+ CoTaskMemFree(FormatList);
+ }
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // get preferred time format
+ hr = pSeek->QueryPreferredFormat(pFormat);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (hr != S_FALSE)
+ return hr;
+ }
+ }
+ hr = S_FALSE;
+ }
+
+ return hr;
}
HRESULT
@@ -598,8 +1035,45 @@ STDMETHODCALLTYPE
CKsProxy::GetTimeFormat(
GUID *pFormat)
{
- OutputDebugStringW(L"CKsProxy::GetTimeFormat NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ ULONG BytesReturned, Index;
+ HRESULT hr;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ OutputDebugStringW(L"CKsProxy::GetTimeFormat\n");
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned);
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ hr = E_NOTIMPL;
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // set time format
+ hr = pSeek->GetTimeFormat(pFormat);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (hr != S_FALSE)
+ break;
+ }
+ }
+ }
+ return hr;
}
HRESULT
@@ -607,8 +1081,17 @@ STDMETHODCALLTYPE
CKsProxy::IsUsingTimeFormat(
const GUID *pFormat)
{
- OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat NotImplemented\n");
- return E_NOTIMPL;
+ GUID Format;
+
+ OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat\n");
+
+ if (FAILED(QueryPreferredFormat(&Format)))
+ return S_FALSE;
+
+ if (IsEqualGUID(Format, *pFormat))
+ return S_OK;
+ else
+ return S_FALSE;
}
HRESULT
@@ -616,8 +1099,47 @@ STDMETHODCALLTYPE
CKsProxy::SetTimeFormat(
const GUID *pFormat)
{
- OutputDebugStringW(L"CKsProxy::SetTimeFormat NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ ULONG BytesReturned, Index;
+ HRESULT hr;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT;
+ Property.Flags = KSPROPERTY_TYPE_SET;
+
+ OutputDebugStringW(L"CKsProxy::SetTimeFormat\n");
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned);
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ hr = E_NOTIMPL;
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (FAILED(hr))
+ {
+ //not supported
+ break;
+ }
+ // set time format
+ hr = pSeek->SetTimeFormat(pFormat);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (FAILED(hr))
+ break;
+ }
+ }
+ return hr;
}
HRESULT
@@ -625,8 +1147,45 @@ STDMETHODCALLTYPE
CKsProxy::GetDuration(
LONGLONG *pDuration)
{
- OutputDebugStringW(L"CKsProxy::GetDuration NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ ULONG BytesReturned, Index;
+ HRESULT hr;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_DURATION;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ OutputDebugStringW(L"CKsProxy::GetDuration\n");
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pDuration, sizeof(LONGLONG), &BytesReturned);
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ hr = E_NOTIMPL;
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // get duration
+ hr = pSeek->GetStopPosition(pDuration);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (hr != S_FALSE) // plugin implements it
+ break;
+ }
+ }
+ }
+ return hr;
}
HRESULT
@@ -634,8 +1193,45 @@ STDMETHODCALLTYPE
CKsProxy::GetStopPosition(
LONGLONG *pStop)
{
- OutputDebugStringW(L"CKsProxy::GetStopPosition NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ ULONG BytesReturned, Index;
+ HRESULT hr;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_STOPPOSITION;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ OutputDebugStringW(L"CKsProxy::GetStopPosition\n");
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pStop, sizeof(LONGLONG), &BytesReturned);
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ hr = E_NOTIMPL;
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // get stop position
+ hr = pSeek->GetStopPosition(pStop);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (hr != S_FALSE) // plugin implements it
+ break;
+ }
+ }
+ }
+ return hr;
}
HRESULT
@@ -643,8 +1239,45 @@ STDMETHODCALLTYPE
CKsProxy::GetCurrentPosition(
LONGLONG *pCurrent)
{
- OutputDebugStringW(L"CKsProxy::GetCurrentPosition NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ ULONG BytesReturned, Index;
+ HRESULT hr;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_POSITION;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ OutputDebugStringW(L"CKsProxy::GetCurrentPosition\n");
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pCurrent, sizeof(LONGLONG), &BytesReturned);
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ hr = E_NOTIMPL;
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // get current position
+ hr = pSeek->GetCurrentPosition(pCurrent);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (hr != S_FALSE) // plugin implements it
+ break;
+ }
+ }
+ }
+ return hr;
}
HRESULT
@@ -655,8 +1288,74 @@ CKsProxy::ConvertTimeFormat(
LONGLONG Source,
const GUID *pSourceFormat)
{
- OutputDebugStringW(L"CKsProxy::ConvertTimeFormat NotImplemented\n");
- return E_NOTIMPL;
+ KSP_TIMEFORMAT Property;
+ ULONG BytesReturned, Index;
+ GUID SourceFormat, TargetFormat;
+ HRESULT hr;
+
+ Property.Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Property.Id = KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT;
+ Property.Property.Flags = KSPROPERTY_TYPE_GET;
+
+ OutputDebugStringW(L"CKsProxy::ConvertTimeFormat\n");
+
+ if (!pTargetFormat)
+ {
+ // get current format
+ hr = GetTimeFormat(&TargetFormat);
+ if (FAILED(hr))
+ return hr;
+
+ pTargetFormat = &TargetFormat;
+ }
+
+ if (!pSourceFormat)
+ {
+ // get current format
+ hr = GetTimeFormat(&SourceFormat);
+ if (FAILED(hr))
+ return hr;
+
+ pSourceFormat = &SourceFormat;
+ }
+
+ Property.SourceFormat = *pSourceFormat;
+ Property.TargetFormat = *pTargetFormat;
+ Property.Time = Source;
+
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_TIMEFORMAT), (PVOID)pTarget, sizeof(LONGLONG), &BytesReturned);
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ //default error
+ hr = E_NOTIMPL;
+
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // convert time format
+ hr = pSeek->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (hr != S_FALSE) // plugin implements it
+ break;
+ }
+ }
+ }
+
+ return hr;
}
HRESULT
@@ -667,8 +1366,71 @@ CKsProxy::SetPositions(
LONGLONG *pStop,
DWORD dwStopFlags)
{
- OutputDebugStringW(L"CKsProxy::SetPositions NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ KSPROPERTY_POSITIONS Positions;
+ ULONG BytesReturned, Index;
+ HRESULT hr;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_POSITIONS;
+ Property.Flags = KSPROPERTY_TYPE_SET;
+
+ Positions.Current = *pCurrent;
+ Positions.CurrentFlags = (KS_SEEKING_FLAGS)dwCurrentFlags;
+ Positions.Stop = *pStop;
+ Positions.StopFlags = (KS_SEEKING_FLAGS)dwStopFlags;
+
+ OutputDebugStringW(L"CKsProxy::SetPositions\n");
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Positions, sizeof(KSPROPERTY_POSITIONS), &BytesReturned);
+ if (SUCCEEDED(hr))
+ {
+ if (dwCurrentFlags & AM_SEEKING_ReturnTime)
+ {
+ // retrieve current position
+ hr = GetCurrentPosition(pCurrent);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (dwStopFlags & AM_SEEKING_ReturnTime)
+ {
+ // retrieve current position
+ hr = GetStopPosition(pStop);
+ }
+ }
+ return hr;
+ }
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ hr = E_NOTIMPL;
+
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // set positions
+ hr = pSeek->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (FAILED(hr))
+ break;
+ }
+ }
+ }
+
+ return hr;
}
HRESULT
@@ -677,8 +1439,15 @@ CKsProxy::GetPositions(
LONGLONG *pCurrent,
LONGLONG *pStop)
{
- OutputDebugStringW(L"CKsProxy::GetPositions NotImplemented\n");
- return E_NOTIMPL;
+ HRESULT hr;
+
+ OutputDebugStringW(L"CKsProxy::GetPositions\n");
+
+ hr = GetCurrentPosition(pCurrent);
+ if (SUCCEEDED(hr))
+ hr = GetStopPosition(pStop);
+
+ return hr;
}
HRESULT
@@ -687,8 +1456,52 @@ CKsProxy::GetAvailable(
LONGLONG *pEarliest,
LONGLONG *pLatest)
{
- OutputDebugStringW(L"CKsProxy::GetAvailable NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ KSPROPERTY_MEDIAAVAILABLE Media;
+ ULONG BytesReturned, Index;
+ HRESULT hr;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_AVAILABLE;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ OutputDebugStringW(L"CKsProxy::GetAvailable\n");
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Media, sizeof(KSPROPERTY_MEDIAAVAILABLE), &BytesReturned);
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ // check if plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ hr = E_NOTIMPL;
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // delegate call
+ hr = pSeek->GetAvailable(pEarliest, pLatest);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (hr != S_FALSE) // plugin implements it
+ break;
+ }
+ }
+ }
+ else if (SUCCEEDED(hr))
+ {
+ *pEarliest = Media.Earliest;
+ *pLatest = Media.Latest;
+ }
+
+ return hr;
}
HRESULT
@@ -696,7 +1509,7 @@ STDMETHODCALLTYPE
CKsProxy::SetRate(
double dRate)
{
- OutputDebugStringW(L"CKsProxy::SetRate NotImplemented\n");
+ OutputDebugStringW(L"CKsProxy::SetRate\n");
return E_NOTIMPL;
}
@@ -705,7 +1518,7 @@ STDMETHODCALLTYPE
CKsProxy::GetRate(
double *pdRate)
{
- OutputDebugStringW(L"CKsProxy::GetRate NotImplemented\n");
+ OutputDebugStringW(L"CKsProxy::GetRate\n");
return E_NOTIMPL;
}
@@ -714,8 +1527,45 @@ STDMETHODCALLTYPE
CKsProxy::GetPreroll(
LONGLONG *pllPreroll)
{
- OutputDebugStringW(L"CKsProxy::GetPreroll NotImplemented\n");
- return E_NOTIMPL;
+ KSPROPERTY Property;
+ ULONG BytesReturned, Index;
+ HRESULT hr;
+
+ Property.Set = KSPROPSETID_MediaSeeking;
+ Property.Id = KSPROPERTY_MEDIASEEKING_PREROLL;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ OutputDebugStringW(L"CKsProxy::GetPreroll\n");
+
+ hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pllPreroll, sizeof(LONGLONG), &BytesReturned);
+ if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+ {
+ // check if all plugins support it
+ for(Index = 0; Index < m_Plugins.size(); Index++)
+ {
+ // get plugin
+ IUnknown * Plugin = m_Plugins[Index];
+
+ if (!Plugin)
+ continue;
+
+ // query for IMediaSeeking interface
+ IMediaSeeking *pSeek = NULL;
+ hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+ if (SUCCEEDED(hr))
+ {
+ // get preroll
+ hr = pSeek->GetPreroll(pllPreroll);
+ // release IMediaSeeking interface
+ pSeek->Release();
+
+ if (hr != S_FALSE) // plugin implements it
+ break;
+ }
+ }
+ hr = E_NOTIMPL;
+ }
+ return hr;
}
//-------------------------------------------------------------------
@@ -771,6 +1621,7 @@ CKsProxy::KsProperty(
ULONG* BytesReturned)
{
assert(m_hDevice != 0);
+ OutputDebugStringW(L"CKsProxy::KsProperty\n");
return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
}
@@ -784,6 +1635,7 @@ CKsProxy::KsMethod(
ULONG* BytesReturned)
{
assert(m_hDevice != 0);
+ OutputDebugStringW(L"CKsProxy::KsMethod\n");
return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
}
@@ -797,7 +1649,7 @@ CKsProxy::KsEvent(
ULONG* BytesReturned)
{
assert(m_hDevice != 0);
-
+ OutputDebugStringW(L"CKsProxy::KsEvent\n");
if (EventLength)
return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
else
@@ -820,6 +1672,8 @@ CKsProxy::Set(
{
ULONG BytesReturned;
+ OutputDebugStringW(L"CKsProxy::Set\n");
+
if (cbInstanceData)
{
PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
@@ -862,6 +1716,8 @@ CKsProxy::Get(
{
ULONG BytesReturned;
+ OutputDebugStringW(L"CKsProxy::Get\n");
+
if (cbInstanceData)
{
PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
@@ -901,6 +1757,8 @@ CKsProxy::QuerySupported(
KSPROPERTY Property;
ULONG BytesReturned;
+ OutputDebugStringW(L"CKsProxy::QuerySupported\n");
+
Property.Set = guidPropSet;
Property.Id = dwPropID;
Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
@@ -922,8 +1780,23 @@ CKsProxy::CreateNodeInstance(
REFGUID InterfaceId,
LPVOID* Interface)
{
- OutputDebugStringW(L"CKsProxy::CreateNodeInstance NotImplemented\n");
- return E_NOTIMPL;
+ HRESULT hr;
+
+ OutputDebugStringW(L"CKsProxy::CreateNodeInstance\n");
+
+ *Interface = NULL;
+
+ if (IsEqualIID(IID_IUnknown, InterfaceId) || !UnkOuter)
+ {
+ hr = CKsNode_Constructor(UnkOuter, m_hDevice, NodeId, DesiredAccess, InterfaceId, Interface);
+ }
+ else
+ {
+ // interface not supported
+ hr = E_NOINTERFACE;
+ }
+
+ return hr;
}
//-------------------------------------------------------------------
@@ -1067,6 +1940,9 @@ HRESULT
STDMETHODCALLTYPE
CKsProxy::DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink)
{
+
+ OutputDebugStringW(L"CKsProxy::DeviceInfo\n");
+
if (!m_DevicePath)
{
// object not initialized
@@ -1090,6 +1966,8 @@ HRESULT
STDMETHODCALLTYPE
CKsProxy::Reassociate(void)
{
+ OutputDebugStringW(L"CKsProxy::Reassociate\n");
+
if (!m_DevicePath || m_hDevice)
{
// file path not available
@@ -1111,6 +1989,8 @@ HRESULT
STDMETHODCALLTYPE
CKsProxy::Disassociate(void)
{
+ OutputDebugStringW(L"CKsProxy::Disassociate\n");
+
if (!m_hDevice)
return E_HANDLE;
@@ -1119,7 +1999,17 @@ CKsProxy::Disassociate(void)
return NOERROR;
}
+//-------------------------------------------------------------------
+// IKsClock interface
+//
+HANDLE
+STDMETHODCALLTYPE
+CKsProxy::KsGetClockHandle()
+{
+ OutputDebugStringW(L"CKsProxy::KsGetClockHandle\n");
+ return m_hClock;
+}
//-------------------------------------------------------------------
@@ -1130,6 +2020,7 @@ HANDLE
STDMETHODCALLTYPE
CKsProxy::KsGetObjectHandle()
{
+ OutputDebugStringW(L"CKsProxy::KsGetObjectHandle\n");
return m_hDevice;
}
@@ -1140,6 +2031,7 @@ HRESULT
STDMETHODCALLTYPE
CKsProxy::InitNew( void)
{
+ OutputDebugStringW(L"CKsProxy::InitNew\n");
return S_OK;
}
@@ -1512,6 +2404,7 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
HDEVINFO hList;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+ OutputDebugStringW(L"CKsProxy::Load\n");
// read device path
varName.vt = VT_BSTR;
@@ -1524,6 +2417,10 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
}
+ OutputDebugStringW(L"DevicePath: ");
+ OutputDebugStringW(varName.bstrVal);
+ OutputDebugStringW(L"\n");
+
// create device list
hList = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
if (hList == INVALID_HANDLE_VALUE)
@@ -1591,6 +2488,7 @@ HRESULT
STDMETHODCALLTYPE
CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
{
+ OutputDebugStringW(L"CKsProxy::Save\n");
return E_NOTIMPL;
}
@@ -1603,8 +2501,10 @@ STDMETHODCALLTYPE
CKsProxy::GetClassID(
CLSID *pClassID)
{
- OutputDebugStringW(L"CKsProxy::GetClassID : NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::GetClassID\n");
+ CopyMemory(pClassID, &CLSID_Proxy, sizeof(GUID));
+
+ return S_OK;
}
HRESULT
@@ -1647,6 +2547,90 @@ STDMETHODCALLTYPE
CKsProxy::SetSyncSource(
IReferenceClock *pClock)
{
+ HRESULT hr;
+ IKsClock *pKsClock;
+ HANDLE hClock, hPin;
+ ULONG Index;
+ IPin * pin;
+ IKsObject * pObject;
+ KSPROPERTY Property;
+ ULONG BytesReturned;
+ PIN_DIRECTION PinDir;
+
+// Plug In Distributor: IKsClock
+ OutputDebugStringW(L"CKsProxy::SetSyncSource\n");
+
+ // FIXME
+ // need locks
+
+ if (!pClock)
+ return E_POINTER;
+
+ hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock);
+ if (FAILED(hr))
+ return hr;
+
+ // get clock handle
+ hClock = pKsClock->KsGetClockHandle();
+ if (!hClock || hClock == INVALID_HANDLE_VALUE)
+ {
+ // failed
+ pKsClock->Release();
+ return E_FAIL;
+ }
+
+ // distribute clock to all pins
+ for(Index = 0; Index < m_Pins.size(); Index++)
+ {
+ // get current pin
+ pin = m_Pins[Index];
+ if (!pin)
+ continue;
+
+ // get IKsObject interface
+ hr = pin->QueryInterface(IID_IKsObject, (void **)&pObject);
+ if (SUCCEEDED(hr))
+ {
+ // get pin handle
+ hPin = pObject->KsGetObjectHandle();
+ if (hPin != INVALID_HANDLE_VALUE && hPin)
+ {
+ // set clock
+ Property.Set = KSPROPSETID_Stream;
+ Property.Id = KSPROPERTY_STREAM_MASTERCLOCK;
+ Property.Flags = KSPROPERTY_TYPE_SET;
+
+ // set master clock
+ hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)hClock, sizeof(HANDLE), &BytesReturned);
+
+ if (FAILED(hr))
+ {
+ if (hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND) &&
+ hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
+ {
+ // failed to set master clock
+ pKsClock->Release();
+ pObject->Release();
+ return hr;
+ }
+ }
+ }
+ // release IKsObject
+ pObject->Release();
+ }
+
+ // now get the direction
+ hr = pin->QueryDirection(&PinDir);
+ if (SUCCEEDED(hr))
+ {
+ if (PinDir == PINDIR_OUTPUT)
+ {
+ // notify pin via
+ //CBaseStreamControl::SetSyncSource(pClock)
+ }
+ }
+ }
+
if (pClock)
{
pClock->AddRef();
@@ -1666,6 +2650,8 @@ STDMETHODCALLTYPE
CKsProxy::GetSyncSource(
IReferenceClock **pClock)
{
+ OutputDebugStringW(L"CKsProxy::GetSyncSource\n");
+
if (!pClock)
return E_POINTER;
@@ -1681,6 +2667,7 @@ STDMETHODCALLTYPE
CKsProxy::EnumPins(
IEnumPins **ppEnum)
{
+ OutputDebugStringW(L"CKsProxy::EnumPins\n");
return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum);
}
@@ -1691,6 +2678,8 @@ CKsProxy::FindPin(
{
ULONG PinId;
+ OutputDebugStringW(L"CKsProxy::FindPin\n");
+
if (!ppPin)
return E_POINTER;
@@ -1725,9 +2714,14 @@ CKsProxy::QueryFilterInfo(
if (!pInfo)
return E_POINTER;
+ OutputDebugStringW(L"CKsProxy::QueryFilterInfo\n");
+
pInfo->achName[0] = L'\0';
pInfo->pGraph = m_pGraph;
+ if (m_pGraph)
+ m_pGraph->AddRef();
+
return S_OK;
}
@@ -1737,6 +2731,8 @@ CKsProxy::JoinFilterGraph(
IFilterGraph *pGraph,
LPCWSTR pName)
{
+ OutputDebugStringW(L"CKsProxy::JoinFilterGraph\n");
+
if (pGraph)
{
// joining filter graph
@@ -1757,8 +2753,8 @@ STDMETHODCALLTYPE
CKsProxy::QueryVendorInfo(
LPWSTR *pVendorInfo)
{
- OutputDebugStringW(L"CKsProxy::QueryVendorInfo : NotImplemented\n");
- return E_NOTIMPL;
+ OutputDebugStringW(L"CKsProxy::QueryVendorInfo\n");
+ return StringFromCLSID(CLSID_Proxy, pVendorInfo);
}
//-------------------------------------------------------------------
diff --git a/dll/directx/ksuser/ksuser.c b/dll/directx/ksuser/ksuser.c
index 8d565231c70..8f62abf950d 100644
--- a/dll/directx/ksuser/ksuser.c
+++ b/dll/directx/ksuser/ksuser.c
@@ -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,
diff --git a/dll/win32/advapi32/reg/reg.c b/dll/win32/advapi32/reg/reg.c
index 4a2ce7e96d6..686101e7f1b 100644
--- a/dll/win32/advapi32/reg/reg.c
+++ b/dll/win32/advapi32/reg/reg.c
@@ -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)
diff --git a/dll/win32/advapi32/sec/sid.c b/dll/win32/advapi32/sec/sid.c
index 6dac3dac683..ed466a58914 100644
--- a/dll/win32/advapi32/sec/sid.c
+++ b/dll/win32/advapi32/sec/sid.c
@@ -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 */
{
diff --git a/dll/win32/advapi32/service/eventlog.c b/dll/win32/advapi32/service/eventlog.c
index 7327532b74b..8cb4b22664e 100644
--- a/dll/win32/advapi32/service/eventlog.c
+++ b/dll/win32/advapi32/service/eventlog.c
@@ -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,
diff --git a/dll/win32/advapi32/service/scm.c b/dll/win32/advapi32/service/scm.c
index e10e7f1fb4c..c3a05da4bf9 100644
--- a/dll/win32/advapi32/service/scm.c
+++ b/dll/win32/advapi32/service/scm.c
@@ -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)
{
diff --git a/dll/win32/advapi32/service/sctrl.c b/dll/win32/advapi32/service/sctrl.c
index ca6f1648fe0..90810bcca3c 100644
--- a/dll/win32/advapi32/service/sctrl.c
+++ b/dll/win32/advapi32/service/sctrl.c
@@ -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 */
diff --git a/dll/win32/dbghelp/coff.c b/dll/win32/dbghelp/coff.c
index ef8632b0f09..720f00b58af 100644
--- a/dll/win32/dbghelp/coff.c
+++ b/dll/win32/dbghelp/coff.c
@@ -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);
diff --git a/dll/win32/dbghelp/cpu_i386.c b/dll/win32/dbghelp/cpu_i386.c
new file mode 100644
index 00000000000..f3de6523539
--- /dev/null
+++ b/dll/win32/dbghelp/cpu_i386.c
@@ -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
+
+#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,
+};
diff --git a/dll/win32/dbghelp/cpu_ppc.c b/dll/win32/dbghelp/cpu_ppc.c
new file mode 100644
index 00000000000..fca5ec76ccf
--- /dev/null
+++ b/dll/win32/dbghelp/cpu_ppc.c
@@ -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
+
+#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,
+};
diff --git a/dll/win32/dbghelp/cpu_x86_64.c b/dll/win32/dbghelp/cpu_x86_64.c
new file mode 100644
index 00000000000..cd0e32c5081
--- /dev/null
+++ b/dll/win32/dbghelp/cpu_x86_64.c
@@ -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
+
+#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,
+};
diff --git a/dll/win32/dbghelp/crc32.c b/dll/win32/dbghelp/crc32.c
new file mode 100644
index 00000000000..edd42eacfba
--- /dev/null
+++ b/dll/win32/dbghelp/crc32.c
@@ -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
+
+#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
+}
diff --git a/dll/win32/dbghelp/dbghelp.c b/dll/win32/dbghelp/dbghelp.c
index 1bfc338e596..d9a828fcef9 100644
--- a/dll/win32/dbghelp/dbghelp.c
+++ b/dll/win32/dbghelp/dbghelp.c
@@ -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 !! */
diff --git a/dll/win32/dbghelp/dbghelp.rbuild b/dll/win32/dbghelp/dbghelp.rbuild
index 59bf735bcf0..26b829a0fe4 100644
--- a/dll/win32/dbghelp/dbghelp.rbuild
+++ b/dll/win32/dbghelp/dbghelp.rbuild
@@ -9,10 +9,15 @@
coff.c
+ cpu_i386.c
+ cpu_ppc.c
+ cpu_x86_64.c
+ crc32.c
dbghelp.c
dwarf.c
elf_module.c
image.c
+ macho_module.c
memory.c
minidump.c
module.c
@@ -27,6 +32,7 @@
storage.c
symbol.c
type.c
+ version.rc
wine
psapi
version
diff --git a/dll/win32/dbghelp/dbghelp_private.h b/dll/win32/dbghelp/dbghelp_private.h
index 31dc7027e3b..e7e3c7c3c37 100644
--- a/dll/win32/dbghelp/dbghelp_private.h
+++ b/dll/win32/dbghelp/dbghelp_private.h
@@ -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,
diff --git a/dll/win32/dbghelp/dwarf.c b/dll/win32/dbghelp/dwarf.c
index 3667c6769cc..433dca88ff4 100644
--- a/dll/win32/dbghelp/dwarf.c
+++ b/dll/win32/dbghelp/dwarf.c
@@ -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);
diff --git a/dll/win32/dbghelp/dwarf.h b/dll/win32/dbghelp/dwarf.h
index e7a0a7e4824..a590df2c9f0 100644
--- a/dll/win32/dbghelp/dwarf.h
+++ b/dll/win32/dbghelp/dwarf.h
@@ -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
diff --git a/dll/win32/dbghelp/elf_module.c b/dll/win32/dbghelp/elf_module.c
index 30b7a3c0102..6a8a1515f9d 100644
--- a/dll/win32/dbghelp/elf_module.c
+++ b/dll/win32/dbghelp/elf_module.c
@@ -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;
}
diff --git a/dll/win32/dbghelp/macho_module.c b/dll/win32/dbghelp/macho_module.c
new file mode 100644
index 00000000000..379596b2f58
--- /dev/null
+++ b/dll/win32/dbghelp/macho_module.c
@@ -0,0 +1,1434 @@
+/*
+ * File macho_module.c - processing of Mach-O files
+ * Originally based on elf_module.c
+ *
+ * Copyright (C) 1996, Eric Youngdale.
+ * 1999-2007 Eric Pouech
+ * 2009 Ken Thomases, CodeWeavers Inc.
+ *
+ * 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 "dbghelp_private.h"
+
+#ifdef __MACH__
+
+#include
+#include
+#ifdef HAVE_SYS_STAT_H
+# include
+#endif
+#ifdef HAVE_SYS_MMAN_H
+# include
+#endif
+
+#include
+#include
+#include
+
+#ifdef HAVE_MACH_O_DYLD_IMAGES_H
+#include
+#else
+struct dyld_image_info {
+ const struct mach_header *imageLoadAddress;
+ const char *imageFilePath;
+ uintptr_t imageFileModDate;
+};
+
+struct dyld_all_image_infos {
+ uint32_t version;
+ uint32_t infoArrayCount;
+ const struct dyld_image_info *infoArray;
+ void* notification;
+ int processDetachedFromSharedRegion;
+};
+#endif
+
+#include "winternl.h"
+#include "wine/library.h"
+#include "wine/debug.h"
+
+#ifdef WORDS_BIGENDIAN
+#define swap_ulong_be_to_host(n) (n)
+#else
+#define swap_ulong_be_to_host(n) (RtlUlongByteSwap(n))
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_macho);
+
+
+struct macho_module_info
+{
+ unsigned long load_addr;
+ unsigned short in_use : 1,
+ is_loader : 1;
+};
+
+#define MACHO_INFO_DEBUG_HEADER 0x0001
+#define MACHO_INFO_MODULE 0x0002
+#define MACHO_INFO_NAME 0x0004
+
+struct macho_info
+{
+ unsigned flags; /* IN one (or several) of the MACHO_INFO constants */
+ unsigned long dbg_hdr_addr; /* OUT address of debug header (if MACHO_INFO_DEBUG_HEADER is set) */
+ struct module* module; /* OUT loaded module (if MACHO_INFO_MODULE is set) */
+ const WCHAR* module_name; /* OUT found module name (if MACHO_INFO_NAME is set) */
+};
+
+/* structure holding information while handling a Mach-O image */
+#define BITS_PER_ULONG (sizeof(ULONG) * 8)
+#define ULONGS_FOR_BITS(nbits) (((nbits) + BITS_PER_ULONG - 1) / BITS_PER_ULONG)
+struct macho_file_map
+{
+ /* A copy of the Mach-O header for an individual architecture. */
+ struct mach_header mach_header;
+
+ /* The mapped load commands. */
+ const struct load_command* load_commands;
+
+ /* The portion of the file which is this architecture. mach_header was
+ * read from arch_offset. */
+ unsigned arch_offset;
+ unsigned arch_size;
+
+ /* The range of address space covered by all segments. */
+ size_t segs_start;
+ size_t segs_size;
+
+ /* Map of which sections contain code. Sections are accessed using 1-based
+ * index. Bit 0 of this bitset indicates if the bitset has been initialized. */
+ RTL_BITMAP sect_is_code;
+ ULONG sect_is_code_buff[ULONGS_FOR_BITS(MAX_SECT + 1)];
+
+ /* The file. */
+ int fd;
+};
+
+static void macho_unmap_file(struct macho_file_map* fmap);
+
+/******************************************************************
+ * macho_calc_range
+ *
+ * For a range (offset & length) of a single architecture within
+ * a Mach-O file, calculate the page-aligned range of the whole file
+ * that encompasses it. For a fat binary, the architecture will
+ * itself be offset within the file, so take that into account.
+ */
+static void macho_calc_range(const struct macho_file_map* fmap, unsigned offset,
+ unsigned len, unsigned* out_aligned_offset,
+ unsigned* out_aligned_end, unsigned* out_aligned_len,
+ unsigned* out_misalign)
+{
+ unsigned pagemask = getpagesize() - 1;
+ unsigned file_offset, misalign;
+
+ file_offset = fmap->arch_offset + offset;
+ misalign = file_offset & pagemask;
+ *out_aligned_offset = file_offset - misalign;
+ *out_aligned_end = (file_offset + len + pagemask) & ~pagemask;
+ if (out_aligned_len)
+ *out_aligned_len = *out_aligned_end - *out_aligned_offset;
+ if (out_misalign)
+ *out_misalign = misalign;
+}
+
+/******************************************************************
+ * macho_map_range
+ *
+ * Maps a range (offset, length in bytes) from a Mach-O file into memory
+ */
+static const char* macho_map_range(const struct macho_file_map* fmap, unsigned offset, unsigned len)
+{
+ unsigned misalign, aligned_offset, aligned_map_end, map_size;
+ const void* aligned_ptr;
+
+ TRACE("(%p/%d, 0x%08x, 0x%08x)\n", fmap, fmap->fd, offset, len);
+
+ macho_calc_range(fmap, offset, len, &aligned_offset, &aligned_map_end,
+ &map_size, &misalign);
+
+ aligned_ptr = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, fmap->fd, aligned_offset);
+
+ TRACE("Mapped (0x%08x - 0x%08x) to %p\n", aligned_offset, aligned_map_end, aligned_ptr);
+
+ if (aligned_ptr == MAP_FAILED) return MACHO_NO_MAP;
+ return (const char*)aligned_ptr + misalign;
+}
+
+/******************************************************************
+ * macho_unmap_range
+ *
+ * Unmaps a range (offset, length in bytes) of a Mach-O file from memory
+ */
+static void macho_unmap_range(const void** mapped, const struct macho_file_map* fmap,
+ unsigned offset, unsigned len)
+{
+ TRACE("(%p, %p/%d, 0x%08x, 0x%08x)\n", mapped, fmap, fmap->fd, offset, len);
+
+ if (mapped && *mapped != MACHO_NO_MAP)
+ {
+ unsigned misalign, aligned_offset, aligned_map_end, map_size;
+ void* aligned_ptr;
+
+ macho_calc_range(fmap, offset, len, &aligned_offset, &aligned_map_end,
+ &map_size, &misalign);
+
+ aligned_ptr = (char*)*mapped - misalign;
+ if (munmap(aligned_ptr, map_size) < 0)
+ WARN("Couldn't unmap the range\n");
+ TRACE("Unmapped (0x%08x - 0x%08x) from %p - %p\n", aligned_offset, aligned_map_end, aligned_ptr, (char*)aligned_ptr + map_size);
+ *mapped = MACHO_NO_MAP;
+ }
+}
+
+/******************************************************************
+ * macho_map_ranges
+ *
+ * Maps two ranges (offset, length in bytes) from a Mach-O file
+ * into memory. If the two ranges overlap, use one mmap so that
+ * the munmap doesn't fragment the mapping.
+ */
+static BOOL macho_map_ranges(const struct macho_file_map* fmap,
+ unsigned offset1, unsigned len1,
+ unsigned offset2, unsigned len2,
+ const void** mapped1, const void** mapped2)
+{
+ unsigned aligned_offset1, aligned_map_end1;
+ unsigned aligned_offset2, aligned_map_end2;
+
+ TRACE("(%p/%d, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %p, %p)\n", fmap, fmap->fd,
+ offset1, len1, offset2, len2, mapped1, mapped2);
+
+ macho_calc_range(fmap, offset1, len1, &aligned_offset1, &aligned_map_end1, NULL, NULL);
+ macho_calc_range(fmap, offset2, len2, &aligned_offset2, &aligned_map_end2, NULL, NULL);
+
+ if (aligned_map_end1 < aligned_offset2 || aligned_map_end2 < aligned_offset1)
+ {
+ *mapped1 = macho_map_range(fmap, offset1, len1);
+ if (*mapped1 != MACHO_NO_MAP)
+ {
+ *mapped2 = macho_map_range(fmap, offset2, len2);
+ if (*mapped2 == MACHO_NO_MAP)
+ macho_unmap_range(mapped1, fmap, offset1, len1);
+ }
+ }
+ else
+ {
+ if (offset1 < offset2)
+ {
+ *mapped1 = macho_map_range(fmap, offset1, offset2 + len2 - offset1);
+ if (*mapped1 != MACHO_NO_MAP)
+ *mapped2 = (const char*)*mapped1 + offset2 - offset1;
+ }
+ else
+ {
+ *mapped2 = macho_map_range(fmap, offset2, offset1 + len1 - offset2);
+ if (*mapped2 != MACHO_NO_MAP)
+ *mapped1 = (const char*)*mapped2 + offset1 - offset2;
+ }
+ }
+
+ TRACE(" => %p, %p\n", *mapped1, *mapped2);
+
+ return (*mapped1 != MACHO_NO_MAP) && (*mapped2 != MACHO_NO_MAP);
+}
+
+/******************************************************************
+ * macho_unmap_ranges
+ *
+ * Unmaps two ranges (offset, length in bytes) of a Mach-O file
+ * from memory. Use for ranges which were mapped by
+ * macho_map_ranges.
+ */
+static void macho_unmap_ranges(const struct macho_file_map* fmap,
+ unsigned offset1, unsigned len1,
+ unsigned offset2, unsigned len2,
+ const void** mapped1, const void** mapped2)
+{
+ unsigned aligned_offset1, aligned_map_end1;
+ unsigned aligned_offset2, aligned_map_end2;
+
+ TRACE("(%p/%d, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %p/%p, %p/%p)\n", fmap, fmap->fd,
+ offset1, len1, offset2, len2, mapped1, *mapped1, mapped2, *mapped2);
+
+ macho_calc_range(fmap, offset1, len1, &aligned_offset1, &aligned_map_end1, NULL, NULL);
+ macho_calc_range(fmap, offset2, len2, &aligned_offset2, &aligned_map_end2, NULL, NULL);
+
+ if (aligned_map_end1 < aligned_offset2 || aligned_map_end2 < aligned_offset1)
+ {
+ macho_unmap_range(mapped1, fmap, offset1, len1);
+ macho_unmap_range(mapped2, fmap, offset2, len2);
+ }
+ else
+ {
+ if (offset1 < offset2)
+ {
+ macho_unmap_range(mapped1, fmap, offset1, offset2 + len2 - offset1);
+ *mapped2 = MACHO_NO_MAP;
+ }
+ else
+ {
+ macho_unmap_range(mapped2, fmap, offset2, offset1 + len1 - offset2);
+ *mapped1 = MACHO_NO_MAP;
+ }
+ }
+}
+
+/******************************************************************
+ * macho_map_load_commands
+ *
+ * Maps the load commands from a Mach-O file into memory
+ */
+static const struct load_command* macho_map_load_commands(struct macho_file_map* fmap)
+{
+ if (fmap->load_commands == MACHO_NO_MAP)
+ {
+ fmap->load_commands = (const struct load_command*) macho_map_range(
+ fmap, sizeof(fmap->mach_header), fmap->mach_header.sizeofcmds);
+ TRACE("Mapped load commands: %p\n", fmap->load_commands);
+ }
+
+ return fmap->load_commands;
+}
+
+/******************************************************************
+ * macho_unmap_load_commands
+ *
+ * Unmaps the load commands of a Mach-O file from memory
+ */
+static void macho_unmap_load_commands(struct macho_file_map* fmap)
+{
+ if (fmap->load_commands != MACHO_NO_MAP)
+ {
+ TRACE("Unmapping load commands: %p\n", fmap->load_commands);
+ macho_unmap_range((const void**)&fmap->load_commands, fmap,
+ sizeof(fmap->mach_header), fmap->mach_header.sizeofcmds);
+ }
+}
+
+/******************************************************************
+ * macho_next_load_command
+ *
+ * Advance to the next load command
+ */
+static const struct load_command* macho_next_load_command(const struct load_command* lc)
+{
+ return (const struct load_command*)((const char*)lc + lc->cmdsize);
+}
+
+/******************************************************************
+ * macho_enum_load_commands
+ *
+ * Enumerates the load commands for a Mach-O file, selecting by
+ * the command type, calling a callback for each. If the callback
+ * returns <0, that indicates an error. If it returns >0, that means
+ * it's not interested in getting any more load commands.
+ * If this function returns <0, that's an error produced by the
+ * callback. If >=0, that's the count of load commands successfully
+ * processed.
+ */
+static int macho_enum_load_commands(struct macho_file_map* fmap, unsigned cmd,
+ int (*cb)(struct macho_file_map*, const struct load_command*, void*),
+ void* user)
+{
+ const struct load_command* lc;
+ int i;
+ int count = 0;
+
+ TRACE("(%p/%d, %u, %p, %p)\n", fmap, fmap->fd, cmd, cb, user);
+
+ if ((lc = macho_map_load_commands(fmap)) == MACHO_NO_MAP) return -1;
+
+ TRACE("%d total commands\n", fmap->mach_header.ncmds);
+
+ for (i = 0; i < fmap->mach_header.ncmds; i++, lc = macho_next_load_command(lc))
+ {
+ int result;
+
+ if (cmd && cmd != lc->cmd) continue;
+ count++;
+
+ result = cb(fmap, lc, user);
+ TRACE("load_command[%d] (%p), cmd %u; callback => %d\n", i, lc, lc->cmd, result);
+ if (result) return (result < 0) ? result : count;
+ }
+
+ return count;
+}
+
+/******************************************************************
+ * macho_accum_segs_range
+ *
+ * Callback for macho_enum_load_commands. Accumulates the address
+ * range covered by the segments of a Mach-O file. All commands
+ * are expected to be of LC_SEGMENT type.
+ */
+static int macho_accum_segs_range(struct macho_file_map* fmap,
+ const struct load_command* lc, void* user)
+{
+ const struct segment_command* sc = (const struct segment_command*)lc;
+ unsigned tmp, page_mask = getpagesize() - 1;
+
+ TRACE("(%p/%d, %p, %p) before: 0x%08x - 0x%08x\n", fmap, fmap->fd, lc, user,
+ (unsigned)fmap->segs_start, (unsigned)fmap->segs_size);
+ TRACE("Segment command vm: 0x%08x - 0x%08x\n", (unsigned)sc->vmaddr,
+ (unsigned)sc->vmaddr + sc->vmsize);
+
+ if (!strncmp(sc->segname, "WINE_", 5))
+ {
+ TRACE("Ignoring special Wine segment %s\n", debugstr_an(sc->segname, sizeof(sc->segname)));
+ return 0;
+ }
+
+ /* If this segment starts before previously-known earliest, record
+ * new earliest. */
+ if (sc->vmaddr < fmap->segs_start)
+ fmap->segs_start = sc->vmaddr;
+
+ /* If this segment extends beyond previously-known furthest, record
+ * new furthest. */
+ tmp = (sc->vmaddr + sc->vmsize + page_mask) & ~page_mask;
+ if (fmap->segs_size < tmp) fmap->segs_size = tmp;
+
+ TRACE("after: 0x%08x - 0x%08x\n", (unsigned)fmap->segs_start, (unsigned)fmap->segs_size);
+
+ return 0;
+}
+
+/******************************************************************
+ * macho_map_file
+ *
+ * Maps a Mach-O file into memory (and checks it's a real Mach-O file)
+ */
+static BOOL macho_map_file(const WCHAR* filenameW, struct macho_file_map* fmap)
+{
+ struct fat_header fat_header;
+ struct stat statbuf;
+ int i;
+ char* filename;
+ unsigned len;
+ BOOL ret = FALSE;
+
+ TRACE("(%s, %p)\n", debugstr_w(filenameW), fmap);
+
+ fmap->fd = -1;
+ fmap->load_commands = MACHO_NO_MAP;
+ RtlInitializeBitMap(&fmap->sect_is_code, fmap->sect_is_code_buff, MAX_SECT + 1);
+
+ len = WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, NULL, 0, NULL, NULL);
+ if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE;
+ WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL);
+
+ /* check that the file exists */
+ if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done;
+
+ /* Now open the file, so that we can mmap() it. */
+ if ((fmap->fd = open(filename, O_RDONLY)) == -1) goto done;
+
+ if (read(fmap->fd, &fat_header, sizeof(fat_header)) != sizeof(fat_header))
+ goto done;
+ TRACE("... got possible fat header\n");
+
+ /* Fat header is always in big-endian order. */
+ if (swap_ulong_be_to_host(fat_header.magic) == FAT_MAGIC)
+ {
+ int narch = swap_ulong_be_to_host(fat_header.nfat_arch);
+ for (i = 0; i < narch; i++)
+ {
+ struct fat_arch fat_arch;
+ if (read(fmap->fd, &fat_arch, sizeof(fat_arch)) != sizeof(fat_arch))
+ goto done;
+ if (swap_ulong_be_to_host(fat_arch.cputype) == CPU_TYPE_X86)
+ {
+ fmap->arch_offset = swap_ulong_be_to_host(fat_arch.offset);
+ fmap->arch_size = swap_ulong_be_to_host(fat_arch.size);
+ break;
+ }
+ }
+ if (i >= narch) goto done;
+ TRACE("... found x86 arch\n");
+ }
+ else
+ {
+ fmap->arch_offset = 0;
+ fmap->arch_size = statbuf.st_size;
+ TRACE("... not a fat header\n");
+ }
+
+ /* Individual architecture (standalone or within a fat file) is in its native byte order. */
+ lseek(fmap->fd, fmap->arch_offset, SEEK_SET);
+ if (read(fmap->fd, &fmap->mach_header, sizeof(fmap->mach_header)) != sizeof(fmap->mach_header))
+ goto done;
+ TRACE("... got possible Mach header\n");
+ /* and check for a Mach-O header */
+ if (fmap->mach_header.magic != MH_MAGIC ||
+ fmap->mach_header.cputype != CPU_TYPE_X86) goto done;
+ /* Make sure the file type is one of the ones we expect. */
+ switch (fmap->mach_header.filetype)
+ {
+ case MH_EXECUTE:
+ case MH_DYLIB:
+ case MH_DYLINKER:
+ case MH_BUNDLE:
+ break;
+ default:
+ goto done;
+ }
+ TRACE("... verified Mach x86 header\n");
+
+ fmap->segs_size = 0;
+ fmap->segs_start = ~0L;
+
+ if (macho_enum_load_commands(fmap, LC_SEGMENT, macho_accum_segs_range, NULL) < 0)
+ goto done;
+
+ fmap->segs_size -= fmap->segs_start;
+ TRACE("segs_start: 0x%08x, segs_size: 0x%08x\n", (unsigned)fmap->segs_start,
+ (unsigned)fmap->segs_size);
+
+ ret = TRUE;
+done:
+ if (!ret)
+ macho_unmap_file(fmap);
+ HeapFree(GetProcessHeap(), 0, filename);
+ return ret;
+}
+
+/******************************************************************
+ * macho_unmap_file
+ *
+ * Unmaps a Mach-O file from memory (previously mapped with macho_map_file)
+ */
+static void macho_unmap_file(struct macho_file_map* fmap)
+{
+ TRACE("(%p/%d)\n", fmap, fmap->fd);
+ if (fmap->fd != -1)
+ {
+ macho_unmap_load_commands(fmap);
+ close(fmap->fd);
+ fmap->fd = -1;
+ }
+}
+
+/******************************************************************
+ * macho_fill_sect_is_code
+ *
+ * Callback for macho_enum_load_commands. Determines which segments
+ * of a Mach-O file contain code. All commands are expected to be
+ * of LC_SEGMENT type.
+ */
+static int macho_fill_sect_is_code(struct macho_file_map* fmap,
+ const struct load_command* lc, void* user)
+{
+ const struct segment_command* sc = (const struct segment_command*)lc;
+ const struct section* sections;
+ int* cursect = user;
+ int i;
+
+ TRACE("(%p/%d, %p, %p/%d) scanning %u sections\n", fmap, fmap->fd, lc,
+ cursect, *cursect, sc->nsects);
+
+ sections = (const struct section*)(sc + 1);
+ for (i = 0; i < sc->nsects; i++)
+ {
+ if (*cursect > MAX_SECT) return -1;
+ (*cursect)++;
+
+ if (!(sections[i].flags & SECTION_TYPE) &&
+ (sections[i].flags & (S_ATTR_PURE_INSTRUCTIONS|S_ATTR_SOME_INSTRUCTIONS)))
+ RtlSetBits(&fmap->sect_is_code, *cursect, 1);
+ else
+ RtlClearBits(&fmap->sect_is_code, *cursect, 1);
+ TRACE("Section %d (%d of this segment) is%s code\n", *cursect, i,
+ (RtlAreBitsSet(&fmap->sect_is_code, *cursect, 1) ? "" : " not"));
+ }
+
+ return 0;
+}
+
+/******************************************************************
+ * macho_sect_is_code
+ *
+ * Checks if a section, identified by sectidx which is a 1-based
+ * index into the sections of all segments, in order of load
+ * commands, contains code.
+ */
+static BOOL macho_sect_is_code(struct macho_file_map* fmap, unsigned char sectidx)
+{
+ TRACE("(%p/%d, %u)\n", fmap, fmap->fd, sectidx);
+
+ if (!RtlAreBitsSet(&fmap->sect_is_code, 0, 1))
+ {
+ int cursect = 0;
+ if (macho_enum_load_commands(fmap, LC_SEGMENT, macho_fill_sect_is_code, &cursect) < 0)
+ WARN("Couldn't load sect_is_code map\n");
+ RtlSetBits(&fmap->sect_is_code, 0, 1);
+ }
+
+ return RtlAreBitsSet(&fmap->sect_is_code, sectidx, 1);
+}
+
+struct symtab_elt
+{
+ struct hash_table_elt ht_elt;
+ struct symt_compiland* compiland;
+ unsigned long addr;
+ unsigned char is_code:1,
+ is_public:1,
+ is_global:1,
+ used:1;
+};
+
+struct macho_debug_info
+{
+ struct macho_file_map* fmap;
+ struct module* module;
+ struct pool pool;
+ struct hash_table ht_symtab;
+};
+
+/******************************************************************
+ * macho_stabs_def_cb
+ *
+ * Callback for stabs_parse. Collect symbol definitions.
+ */
+static void macho_stabs_def_cb(struct module* module, unsigned long load_offset,
+ const char* name, unsigned long offset,
+ BOOL is_public, BOOL is_global, unsigned char sectidx,
+ struct symt_compiland* compiland, void* user)
+{
+ struct macho_debug_info* mdi = user;
+ struct symtab_elt* ste;
+
+ TRACE("(%p, 0x%08lx, %s, 0x%08lx, %d, %d, %u, %p, %p/%p/%d)\n", module, load_offset,
+ debugstr_a(name), offset, is_public, is_global, sectidx,
+ compiland, mdi, mdi->fmap, mdi->fmap->fd);
+
+ /* Defer the creation of new non-debugging symbols until after we've
+ * finished parsing the stabs. */
+ ste = pool_alloc(&mdi->pool, sizeof(*ste));
+ ste->ht_elt.name = pool_strdup(&mdi->pool, name);
+ ste->compiland = compiland;
+ ste->addr = load_offset + offset;
+ ste->is_code = !!macho_sect_is_code(mdi->fmap, sectidx);
+ ste->is_public = !!is_public;
+ ste->is_global = !!is_global;
+ ste->used = 0;
+ hash_table_add(&mdi->ht_symtab, &ste->ht_elt);
+}
+
+/******************************************************************
+ * macho_parse_symtab
+ *
+ * Callback for macho_enum_load_commands. Processes the LC_SYMTAB
+ * load commands from the Mach-O file.
+ */
+static int macho_parse_symtab(struct macho_file_map* fmap,
+ const struct load_command* lc, void* user)
+{
+ const struct symtab_command* sc = (const struct symtab_command*)lc;
+ struct macho_debug_info* mdi = user;
+ const struct nlist* stab;
+ const char* stabstr;
+ int ret = 0;
+
+ TRACE("(%p/%d, %p, %p) %u syms at 0x%08x, strings 0x%08x - 0x%08x\n", fmap, fmap->fd, lc,
+ user, sc->nsyms, sc->symoff, sc->stroff, sc->stroff + sc->strsize);
+
+ if (!macho_map_ranges(fmap, sc->symoff, sc->nsyms * sizeof(struct nlist),
+ sc->stroff, sc->strsize, (const void**)&stab, (const void**)&stabstr))
+ return 0;
+
+ if (!stabs_parse(mdi->module, mdi->module->macho_info->load_addr - fmap->segs_start,
+ stab, sc->nsyms * sizeof(struct nlist),
+ stabstr, sc->strsize, macho_stabs_def_cb, mdi))
+ ret = -1;
+
+ macho_unmap_ranges(fmap, sc->symoff, sc->nsyms * sizeof(struct nlist),
+ sc->stroff, sc->strsize, (const void**)&stab, (const void**)&stabstr);
+
+ return ret;
+}
+
+/******************************************************************
+ * macho_finish_stabs
+ *
+ * Integrate the non-debugging symbols we've gathered into the
+ * symbols that were generated during stabs parsing.
+ */
+static void macho_finish_stabs(struct module* module, struct hash_table* ht_symtab)
+{
+ struct hash_table_iter hti_ours;
+ struct symtab_elt* ste;
+ BOOL adjusted = FALSE;
+
+ TRACE("(%p, %p)\n", module, ht_symtab);
+
+ /* For each of our non-debugging symbols, see if it can provide some
+ * missing details to one of the module's known symbols. */
+ hash_table_iter_init(ht_symtab, &hti_ours, NULL);
+ while ((ste = hash_table_iter_up(&hti_ours)))
+ {
+ struct hash_table_iter hti_modules;
+ void* ptr;
+ struct symt_ht* sym;
+ struct symt_function* func;
+ struct symt_data* data;
+
+ hash_table_iter_init(&module->ht_symbols, &hti_modules, ste->ht_elt.name);
+ while ((ptr = hash_table_iter_up(&hti_modules)))
+ {
+ sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
+
+ if (strcmp(sym->hash_elt.name, ste->ht_elt.name))
+ continue;
+
+ switch (sym->symt.tag)
+ {
+ case SymTagFunction:
+ func = (struct symt_function*)sym;
+ if (func->address == module->macho_info->load_addr)
+ {
+ TRACE("Adjusting function %p/%s!%s from 0x%08lx to 0x%08lx\n", func,
+ debugstr_w(module->module.ModuleName), sym->hash_elt.name,
+ func->address, ste->addr);
+ func->address = ste->addr;
+ adjusted = TRUE;
+ }
+ if (func->address == ste->addr)
+ ste->used = 1;
+ break;
+ case SymTagData:
+ data = (struct symt_data*)sym;
+ switch (data->kind)
+ {
+ case DataIsGlobal:
+ case DataIsFileStatic:
+ if (data->u.var.offset == module->macho_info->load_addr)
+ {
+ TRACE("Adjusting data symbol %p/%s!%s from 0x%08lx to 0x%08lx\n",
+ data, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
+ data->u.var.offset, ste->addr);
+ data->u.var.offset = ste->addr;
+ adjusted = TRUE;
+ }
+ if (data->u.var.offset == ste->addr)
+ {
+ enum DataKind new_kind;
+
+ new_kind = ste->is_global ? DataIsGlobal : DataIsFileStatic;
+ if (data->kind != new_kind)
+ {
+ WARN("Changing kind for %p/%s!%s from %d to %d\n", sym,
+ debugstr_w(module->module.ModuleName), sym->hash_elt.name,
+ (int)data->kind, (int)new_kind);
+ data->kind = new_kind;
+ adjusted = TRUE;
+ }
+ ste->used = 1;
+ }
+ break;
+ default:;
+ }
+ break;
+ default:
+ TRACE("Ignoring tag %u\n", sym->symt.tag);
+ break;
+ }
+ }
+ }
+
+ if (adjusted)
+ {
+ /* since we may have changed some addresses, mark the module to be resorted */
+ module->sortlist_valid = FALSE;
+ }
+
+ /* Mark any of our non-debugging symbols which fall on an already-used
+ * address as "used". This allows us to skip them in the next loop,
+ * below. We do this in separate loops because symt_new_* marks the
+ * list as needing sorting and symt_find_nearest sorts if needed,
+ * causing thrashing. */
+ if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
+ {
+ hash_table_iter_init(ht_symtab, &hti_ours, NULL);
+ while ((ste = hash_table_iter_up(&hti_ours)))
+ {
+ struct symt_ht* sym;
+ ULONG64 addr;
+
+ if (ste->used) continue;
+
+ sym = symt_find_nearest(module, ste->addr);
+ if (sym)
+ symt_get_info(module, &sym->symt, TI_GET_ADDRESS, &addr);
+ if (sym && ste->addr == addr)
+ {
+ ULONG64 size = 0;
+ DWORD kind = -1;
+
+ ste->used = 1;
+
+ /* If neither symbol has a correct size (ours never does), we
+ * consider them both to be markers. No warning is needed in
+ * that case.
+ * Also, we check that we don't have two symbols, one local, the other
+ * global, which is legal.
+ */
+ symt_get_info(module, &sym->symt, TI_GET_LENGTH, &size);
+ symt_get_info(module, &sym->symt, TI_GET_DATAKIND, &kind);
+ if (size && kind == (ste->is_global ? DataIsGlobal : DataIsFileStatic))
+ FIXME("Duplicate in %s: %s<%08lx> %s<%s-%s>\n",
+ debugstr_w(module->module.ModuleName),
+ ste->ht_elt.name, ste->addr,
+ sym->hash_elt.name,
+ wine_dbgstr_longlong(addr), wine_dbgstr_longlong(size));
+ }
+ }
+ }
+
+ /* For any of our remaining non-debugging symbols which have no match
+ * among the module's known symbols, add them as new symbols. */
+ hash_table_iter_init(ht_symtab, &hti_ours, NULL);
+ while ((ste = hash_table_iter_up(&hti_ours)))
+ {
+ if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY) && !ste->used)
+ {
+ if (ste->is_code)
+ {
+ symt_new_function(module, ste->compiland, ste->ht_elt.name,
+ ste->addr, 0, NULL);
+ }
+ else
+ {
+ symt_new_global_variable(module, ste->compiland, ste->ht_elt.name,
+ !ste->is_global, ste->addr, 0, NULL);
+ }
+
+ ste->used = 1;
+ }
+
+ if (ste->is_public && !(dbghelp_options & SYMOPT_NO_PUBLICS))
+ {
+ symt_new_public(module, ste->compiland, ste->ht_elt.name, ste->addr, 0);
+ }
+ }
+}
+
+/******************************************************************
+ * macho_load_debug_info_from_map
+ *
+ * Loads the symbolic information from a Mach-O module.
+ * Returns
+ * FALSE if the file doesn't contain symbolic info (or this info
+ * cannot be read or parsed)
+ * TRUE on success
+ */
+static BOOL macho_load_debug_info_from_map(struct module* module,
+ struct macho_file_map* fmap)
+{
+ BOOL ret = FALSE;
+ struct macho_debug_info mdi;
+ int result;
+
+ TRACE("(%p, %p/%d)\n", module, fmap, fmap->fd);
+
+ module->module.SymType = SymExport;
+
+ mdi.fmap = fmap;
+ mdi.module = module;
+ pool_init(&mdi.pool, 65536);
+ hash_table_init(&mdi.pool, &mdi.ht_symtab, 256);
+ result = macho_enum_load_commands(fmap, LC_SYMTAB, macho_parse_symtab, &mdi);
+ if (result > 0)
+ ret = TRUE;
+ else if (result < 0)
+ WARN("Couldn't correctly read stabs\n");
+
+ macho_finish_stabs(module, &mdi.ht_symtab);
+
+ pool_destroy(&mdi.pool);
+ return ret;
+}
+
+/******************************************************************
+ * macho_load_debug_info
+ *
+ * Loads Mach-O debugging information from the module image file.
+ */
+BOOL macho_load_debug_info(struct module* module, struct macho_file_map* fmap)
+{
+ BOOL ret = TRUE;
+ struct macho_file_map my_fmap;
+
+ TRACE("(%p, %p/%d)\n", module, fmap, fmap ? fmap->fd : -1);
+
+ if (module->type != DMT_MACHO || !module->macho_info)
+ {
+ ERR("Bad Mach-O module '%s'\n", debugstr_w(module->module.LoadedImageName));
+ return FALSE;
+ }
+
+ if (!fmap)
+ {
+ fmap = &my_fmap;
+ ret = macho_map_file(module->module.LoadedImageName, fmap);
+ }
+ if (ret)
+ ret = macho_load_debug_info_from_map(module, fmap);
+
+ if (fmap == &my_fmap) macho_unmap_file(fmap);
+ return ret;
+}
+
+/******************************************************************
+ * macho_fetch_file_info
+ *
+ * Gathers some more information for a Mach-O module from a given file
+ */
+BOOL macho_fetch_file_info(const WCHAR* name, DWORD* base,
+ DWORD* size, DWORD* checksum)
+{
+ struct macho_file_map fmap;
+
+ TRACE("(%s, %p, %p, %p)\n", debugstr_w(name), base, size, checksum);
+
+ if (!macho_map_file(name, &fmap)) return FALSE;
+ if (base) *base = fmap.segs_start;
+ *size = fmap.segs_size;
+ *checksum = calc_crc32(fmap.fd);
+ macho_unmap_file(&fmap);
+ return TRUE;
+}
+
+/******************************************************************
+ * macho_load_file
+ *
+ * Loads the information for Mach-O module stored in 'filename'.
+ * The module has been loaded at 'load_addr' address.
+ * returns
+ * FALSE if the file cannot be found/opened or if the file doesn't
+ * contain symbolic info (or this info cannot be read or parsed)
+ * TRUE on success
+ */
+static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
+ unsigned long load_addr, struct macho_info* macho_info)
+{
+ BOOL ret = TRUE;
+ struct macho_file_map fmap;
+
+ TRACE("(%p/%p, %s, 0x%08lx, %p/0x%08x)\n", pcs, pcs->handle, debugstr_w(filename),
+ load_addr, macho_info, macho_info->flags);
+
+ if (!macho_map_file(filename, &fmap)) return FALSE;
+
+ /* Find the dynamic loader's table of images loaded into the process.
+ */
+ if (macho_info->flags & MACHO_INFO_DEBUG_HEADER)
+ {
+ static void* dyld_all_image_infos_addr;
+
+ /* This symbol should be in the same place in all processes. */
+ if (!dyld_all_image_infos_addr)
+ {
+ struct nlist nl[2];
+ memset(nl, 0, sizeof(nl));
+ nl[0].n_un.n_name = (char*)"_dyld_all_image_infos";
+ if (!nlist("/usr/lib/dyld", nl))
+ dyld_all_image_infos_addr = (void*)nl[0].n_value;
+ }
+
+ if (dyld_all_image_infos_addr)
+ macho_info->dbg_hdr_addr = (unsigned long)dyld_all_image_infos_addr;
+ else
+ ret = FALSE;
+ TRACE("dbg_hdr_addr = 0x%08lx\n", macho_info->dbg_hdr_addr);
+ }
+
+ if (macho_info->flags & MACHO_INFO_MODULE)
+ {
+ struct macho_module_info *macho_module_info =
+ HeapAlloc(GetProcessHeap(), 0, sizeof(struct macho_module_info));
+ if (!macho_module_info) goto leave;
+ macho_info->module = module_new(pcs, filename, DMT_MACHO, FALSE, load_addr,
+ fmap.segs_size, 0, calc_crc32(fmap.fd));
+ if (!macho_info->module)
+ {
+ HeapFree(GetProcessHeap(), 0, macho_module_info);
+ goto leave;
+ }
+ macho_info->module->macho_info = macho_module_info;
+ macho_info->module->macho_info->load_addr = load_addr;
+
+ if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
+ macho_info->module->module.SymType = SymDeferred;
+ else if (!macho_load_debug_info(macho_info->module, &fmap))
+ ret = FALSE;
+
+ macho_info->module->macho_info->in_use = 1;
+ macho_info->module->macho_info->is_loader = 0;
+ TRACE("module = %p\n", macho_info->module);
+ }
+
+ if (macho_info->flags & MACHO_INFO_NAME)
+ {
+ WCHAR* ptr;
+ ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR));
+ if (ptr)
+ {
+ strcpyW(ptr, filename);
+ macho_info->module_name = ptr;
+ }
+ else ret = FALSE;
+ TRACE("module_name = %p %s\n", macho_info->module_name, debugstr_w(macho_info->module_name));
+ }
+leave:
+ macho_unmap_file(&fmap);
+
+ TRACE(" => %d\n", ret);
+ return ret;
+}
+
+/******************************************************************
+ * macho_load_file_from_path
+ * Tries to load a Mach-O file from a set of paths (separated by ':')
+ */
+static BOOL macho_load_file_from_path(HANDLE hProcess,
+ const WCHAR* filename,
+ unsigned long load_addr,
+ const char* path,
+ struct macho_info* macho_info)
+{
+ BOOL ret = FALSE;
+ WCHAR *s, *t, *fn;
+ WCHAR* pathW = NULL;
+ unsigned len;
+
+ TRACE("(%p, %s, 0x%08lx, %s, %p)\n", hProcess, debugstr_w(filename), load_addr,
+ debugstr_a(path), macho_info);
+
+ if (!path) return FALSE;
+
+ len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
+ pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!pathW) return FALSE;
+ MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len);
+
+ for (s = pathW; s && *s; s = (t) ? (t+1) : NULL)
+ {
+ t = strchrW(s, ':');
+ if (t) *t = '\0';
+ fn = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1 + lstrlenW(s) + 1) * sizeof(WCHAR));
+ if (!fn) break;
+ strcpyW(fn, s);
+ strcatW(fn, S_SlashW);
+ strcatW(fn, filename);
+ ret = macho_load_file(hProcess, fn, load_addr, macho_info);
+ HeapFree(GetProcessHeap(), 0, fn);
+ if (ret) break;
+ s = (t) ? (t+1) : NULL;
+ }
+
+ TRACE(" => %d\n", ret);
+ HeapFree(GetProcessHeap(), 0, pathW);
+ return ret;
+}
+
+/******************************************************************
+ * macho_load_file_from_dll_path
+ *
+ * Tries to load a Mach-O file from the dll path
+ */
+static BOOL macho_load_file_from_dll_path(HANDLE hProcess,
+ const WCHAR* filename,
+ unsigned long load_addr,
+ struct macho_info* macho_info)
+{
+ BOOL ret = FALSE;
+ unsigned int index = 0;
+ const char *path;
+
+ TRACE("(%p, %s, 0x%08lx, %p)\n", hProcess, debugstr_w(filename), load_addr,
+ macho_info);
+
+ while (!ret && (path = wine_dll_enum_load_path( index++ )))
+ {
+ WCHAR *name;
+ unsigned len;
+
+ len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
+
+ name = HeapAlloc( GetProcessHeap(), 0,
+ (len + lstrlenW(filename) + 2) * sizeof(WCHAR) );
+
+ if (!name) break;
+ MultiByteToWideChar(CP_UNIXCP, 0, path, -1, name, len);
+ strcatW( name, S_SlashW );
+ strcatW( name, filename );
+ ret = macho_load_file(hProcess, name, load_addr, macho_info);
+ HeapFree( GetProcessHeap(), 0, name );
+ }
+ TRACE(" => %d\n", ret);
+ return ret;
+}
+
+/******************************************************************
+ * macho_search_and_load_file
+ *
+ * Lookup a file in standard Mach-O locations, and if found, load it
+ */
+static BOOL macho_search_and_load_file(struct process* pcs, const WCHAR* filename,
+ unsigned long load_addr,
+ struct macho_info* macho_info)
+{
+ BOOL ret = FALSE;
+ struct module* module;
+ static WCHAR S_libstdcPPW[] = {'l','i','b','s','t','d','c','+','+','\0'};
+ const WCHAR* p;
+
+ TRACE("(%p/%p, %s, 0x%08lx, %p)\n", pcs, pcs->handle, debugstr_w(filename), load_addr,
+ macho_info);
+
+ if (filename == NULL || *filename == '\0') return FALSE;
+ if ((module = module_is_already_loaded(pcs, filename)))
+ {
+ macho_info->module = module;
+ module->macho_info->in_use = 1;
+ return module->module.SymType;
+ }
+
+ if (strstrW(filename, S_libstdcPPW)) return FALSE; /* We know we can't do it */
+
+ /* If has no directories, try LD_LIBRARY_PATH first. */
+ if (!strchrW(filename, '/'))
+ {
+ ret = macho_load_file_from_path(pcs, filename, load_addr,
+ getenv("PATH"), macho_info);
+ }
+ /* Try DYLD_LIBRARY_PATH, with just the filename (no directories). */
+ if (!ret)
+ {
+ if ((p = strrchrW(filename, '/'))) p++;
+ else p = filename;
+ ret = macho_load_file_from_path(pcs, p, load_addr,
+ getenv("DYLD_LIBRARY_PATH"), macho_info);
+ }
+ /* Try the path as given. */
+ if (!ret)
+ ret = macho_load_file(pcs, filename, load_addr, macho_info);
+ /* Try DYLD_FALLBACK_LIBRARY_PATH, with just the filename (no directories). */
+ if (!ret)
+ {
+ ret = macho_load_file_from_path(pcs, p, load_addr,
+ getenv("DYLD_FALLBACK_LIBRARY_PATH"), macho_info);
+ }
+ if (!ret && !strchrW(filename, '/'))
+ ret = macho_load_file_from_dll_path(pcs, filename, load_addr, macho_info);
+
+ return ret;
+}
+
+/******************************************************************
+ * macho_enum_modules_internal
+ *
+ * Enumerate Mach-O modules from a running process
+ */
+static BOOL macho_enum_modules_internal(const struct process* pcs,
+ const WCHAR* main_name,
+ enum_modules_cb cb, void* user)
+{
+ struct dyld_all_image_infos image_infos;
+ struct dyld_image_info* info_array = NULL;
+ unsigned long len;
+ int i;
+ char bufstr[256];
+ WCHAR bufstrW[MAX_PATH];
+ BOOL ret = FALSE;
+
+ TRACE("(%p/%p, %s, %p, %p)\n", pcs, pcs->handle, debugstr_w(main_name), cb,
+ user);
+
+ if (!pcs->dbg_hdr_addr ||
+ !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr,
+ &image_infos, sizeof(image_infos), NULL) ||
+ !image_infos.infoArray)
+ goto done;
+ TRACE("Process has %u image infos at %p\n", image_infos.infoArrayCount, image_infos.infoArray);
+
+ len = image_infos.infoArrayCount * sizeof(info_array[0]);
+ info_array = HeapAlloc(GetProcessHeap(), 0, len);
+ if (!info_array ||
+ !ReadProcessMemory(pcs->handle, image_infos.infoArray,
+ info_array, len, NULL))
+ goto done;
+ TRACE("... read image infos\n");
+
+ for (i = 0; i < image_infos.infoArrayCount; i++)
+ {
+ if (info_array[i].imageFilePath != NULL &&
+ ReadProcessMemory(pcs->handle, info_array[i].imageFilePath, bufstr, sizeof(bufstr), NULL))
+ {
+ bufstr[sizeof(bufstr) - 1] = '\0';
+ TRACE("[%d] image file %s\n", i, debugstr_a(bufstr));
+ MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, sizeof(bufstrW) / sizeof(WCHAR));
+ if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name);
+ if (!cb(bufstrW, (unsigned long)info_array[i].imageLoadAddress, user)) break;
+ }
+ }
+
+ ret = TRUE;
+done:
+ HeapFree(GetProcessHeap(), 0, info_array);
+ return ret;
+}
+
+struct macho_sync
+{
+ struct process* pcs;
+ struct macho_info macho_info;
+};
+
+static BOOL macho_enum_sync_cb(const WCHAR* name, unsigned long addr, void* user)
+{
+ struct macho_sync* ms = user;
+
+ TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user);
+ macho_search_and_load_file(ms->pcs, name, addr, &ms->macho_info);
+ return TRUE;
+}
+
+/******************************************************************
+ * macho_synchronize_module_list
+ *
+ * Rescans the debuggee's modules list and synchronizes it with
+ * the one from 'pcs', ie:
+ * - if a module is in debuggee and not in pcs, it's loaded into pcs
+ * - if a module is in pcs and not in debuggee, it's unloaded from pcs
+ */
+BOOL macho_synchronize_module_list(struct process* pcs)
+{
+ struct module* module;
+ struct macho_sync ms;
+
+ TRACE("(%p/%p)\n", pcs, pcs->handle);
+
+ for (module = pcs->lmodules; module; module = module->next)
+ {
+ if (module->type == DMT_MACHO && !module->is_virtual)
+ module->macho_info->in_use = 0;
+ }
+
+ ms.pcs = pcs;
+ ms.macho_info.flags = MACHO_INFO_MODULE;
+ if (!macho_enum_modules_internal(pcs, NULL, macho_enum_sync_cb, &ms))
+ return FALSE;
+
+ module = pcs->lmodules;
+ while (module)
+ {
+ if (module->type == DMT_MACHO && !module->is_virtual &&
+ !module->macho_info->in_use && !module->macho_info->is_loader)
+ {
+ module_remove(pcs, module);
+ /* restart all over */
+ module = pcs->lmodules;
+ }
+ else module = module->next;
+ }
+ return TRUE;
+}
+
+/******************************************************************
+ * macho_search_loader
+ *
+ * Lookup in a running Mach-O process the loader, and sets its Mach-O link
+ * address (for accessing the list of loaded images) in pcs.
+ * If flags is MACHO_INFO_MODULE, the module for the loader is also
+ * added as a module into pcs.
+ */
+static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_info)
+{
+ BOOL ret;
+ const char* ptr;
+
+ TRACE("(%p/%p, %p)\n", pcs, pcs->handle, macho_info);
+
+ /* All binaries are loaded with WINELOADER (if run from tree) or by the
+ * main executable
+ */
+ if ((ptr = getenv("WINELOADER")))
+ {
+ WCHAR tmp[MAX_PATH];
+ MultiByteToWideChar(CP_UNIXCP, 0, ptr, -1, tmp, sizeof(tmp) / sizeof(WCHAR));
+ ret = macho_search_and_load_file(pcs, tmp, 0, macho_info);
+ }
+ else
+ {
+ ret = macho_search_and_load_file(pcs, S_WineW, 0, macho_info);
+ }
+ return ret;
+}
+
+/******************************************************************
+ * macho_read_wine_loader_dbg_info
+ *
+ * Try to find a decent wine executable which could have loaded the debuggee
+ */
+BOOL macho_read_wine_loader_dbg_info(struct process* pcs)
+{
+ struct macho_info macho_info;
+
+ TRACE("(%p/%p)\n", pcs, pcs->handle);
+ macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_MODULE;
+ if (!macho_search_loader(pcs, &macho_info)) return FALSE;
+ macho_info.module->macho_info->is_loader = 1;
+ module_set_module(macho_info.module, S_WineLoaderW);
+ return (pcs->dbg_hdr_addr = macho_info.dbg_hdr_addr) != 0;
+}
+
+/******************************************************************
+ * macho_enum_modules
+ *
+ * Enumerates the Mach-O loaded modules from a running target (hProc)
+ * This function doesn't require that someone has called SymInitialize
+ * on this very process.
+ */
+BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user)
+{
+ struct process pcs;
+ struct macho_info macho_info;
+ BOOL ret;
+
+ TRACE("(%p, %p, %p)\n", hProc, cb, user);
+ memset(&pcs, 0, sizeof(pcs));
+ pcs.handle = hProc;
+ macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_NAME;
+ if (!macho_search_loader(&pcs, &macho_info)) return FALSE;
+ pcs.dbg_hdr_addr = macho_info.dbg_hdr_addr;
+ ret = macho_enum_modules_internal(&pcs, macho_info.module_name, cb, user);
+ HeapFree(GetProcessHeap(), 0, (char*)macho_info.module_name);
+ return ret;
+}
+
+struct macho_load
+{
+ struct process* pcs;
+ struct macho_info macho_info;
+ const WCHAR* name;
+ BOOL ret;
+};
+
+/******************************************************************
+ * macho_load_cb
+ *
+ * Callback for macho_load_module, used to walk the list of loaded
+ * modules.
+ */
+static BOOL macho_load_cb(const WCHAR* name, unsigned long addr, void* user)
+{
+ struct macho_load* ml = user;
+ const WCHAR* p;
+
+ TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user);
+
+ /* memcmp is needed for matches when bufstr contains also version information
+ * ml->name: libc.so, name: libc.so.6.0
+ */
+ p = strrchrW(name, '/');
+ if (!p++) p = name;
+ if (!memcmp(p, ml->name, lstrlenW(ml->name) * sizeof(WCHAR)))
+ {
+ ml->ret = macho_search_and_load_file(ml->pcs, name, addr, &ml->macho_info);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/******************************************************************
+ * macho_load_module
+ *
+ * Loads a Mach-O module and stores it in process' module list.
+ * Also, find module real name and load address from
+ * the real loaded modules list in pcs address space.
+ */
+struct module* macho_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
+{
+ struct macho_load ml;
+
+ TRACE("(%p/%p, %s, 0x%08lx)\n", pcs, pcs->handle, debugstr_w(name), addr);
+
+ ml.macho_info.flags = MACHO_INFO_MODULE;
+ ml.ret = FALSE;
+
+ if (pcs->dbg_hdr_addr) /* we're debugging a live target */
+ {
+ ml.pcs = pcs;
+ /* do only the lookup from the filename, not the path (as we lookup module
+ * name in the process' loaded module list)
+ */
+ ml.name = strrchrW(name, '/');
+ if (!ml.name++) ml.name = name;
+ ml.ret = FALSE;
+
+ if (!macho_enum_modules_internal(pcs, NULL, macho_load_cb, &ml))
+ return NULL;
+ }
+ else if (addr)
+ {
+ ml.name = name;
+ ml.ret = macho_search_and_load_file(pcs, ml.name, addr, &ml.macho_info);
+ }
+ if (!ml.ret) return NULL;
+ assert(ml.macho_info.module);
+ return ml.macho_info.module;
+}
+
+#else /* !__MACH__ */
+
+BOOL macho_synchronize_module_list(struct process* pcs)
+{
+ return FALSE;
+}
+
+BOOL macho_fetch_file_info(const WCHAR* name, DWORD* base,
+ DWORD* size, DWORD* checksum)
+{
+ return FALSE;
+}
+
+BOOL macho_read_wine_loader_dbg_info(struct process* pcs)
+{
+ return FALSE;
+}
+
+BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user)
+{
+ return FALSE;
+}
+
+struct module* macho_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
+{
+ return NULL;
+}
+
+BOOL macho_load_debug_info(struct module* module, struct macho_file_map* fmap)
+{
+ return FALSE;
+}
+#endif /* __MACH__ */
diff --git a/dll/win32/dbghelp/minidump.c b/dll/win32/dbghelp/minidump.c
index cc124157544..3cddb72ee03 100644
--- a/dll/win32/dbghelp/minidump.c
+++ b/dll/win32/dbghelp/minidump.c
@@ -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;
}
}
diff --git a/dll/win32/dbghelp/module.c b/dll/win32/dbghelp/module.c
index ddc6d3d89bd..53f56c25129 100644
--- a/dll/win32/dbghelp/module.c
+++ b/dll/win32/dbghelp/module.c
@@ -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);
+}
diff --git a/dll/win32/dbghelp/msc.c b/dll/win32/dbghelp/msc.c
index 47998549bde..ee394cd946c 100644
--- a/dll/win32/dbghelp/msc.c
+++ b/dll/win32/dbghelp/msc.c
@@ -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)
diff --git a/dll/win32/dbghelp/path.c b/dll/win32/dbghelp/path.c
index e0cfc97a082..12c595b4d1e 100644
--- a/dll/win32/dbghelp/path.c
+++ b/dll/win32/dbghelp/path.c
@@ -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)
{
diff --git a/dll/win32/dbghelp/pe_module.c b/dll/win32/dbghelp/pe_module.c
index a79396f5191..76d81ee5512 100644
--- a/dll/win32/dbghelp/pe_module.c
+++ b/dll/win32/dbghelp/pe_module.c
@@ -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 );
}
/***********************************************************************
diff --git a/dll/win32/dbghelp/rosstubs.c b/dll/win32/dbghelp/rosstubs.c
index d6084612536..f4917899f6d 100644
--- a/dll/win32/dbghelp/rosstubs.c
+++ b/dll/win32/dbghelp/rosstubs.c
@@ -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,
diff --git a/dll/win32/dbghelp/source.c b/dll/win32/dbghelp/source.c
index 8eef33727cd..c8ecf26c9fc 100644
--- a/dll/win32/dbghelp/source.c
+++ b/dll/win32/dbghelp/source.c
@@ -26,9 +26,6 @@
#include "dbghelp_private.h"
#include "wine/debug.h"
-#ifdef HAVE_REGEX_H
-# include
-#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; ivlines); 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.@)
*
diff --git a/dll/win32/dbghelp/stabs.c b/dll/win32/dbghelp/stabs.c
index a7f0fefae8c..367b04c72dd 100644
--- a/dll/win32/dbghelp/stabs.c
+++ b/dll/win32/dbghelp/stabs.c
@@ -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
#include
+#ifdef HAVE_MACH_O_NLIST_H
+# include
+#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;
}
diff --git a/dll/win32/dbghelp/stack.c b/dll/win32/dbghelp/stack.c
index 3c66fcbc04c..d53629e80b4 100644
--- a/dll/win32/dbghelp/stack.c
+++ b/dll/win32/dbghelp/stack.c
@@ -27,40 +27,45 @@
#include
#include
-#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;
}
/******************************************************************
diff --git a/dll/win32/dbghelp/storage.c b/dll/win32/dbghelp/storage.c
index baca0530b34..c7f06cc11bd 100644
--- a/dll/win32/dbghelp/storage.c
+++ b/dll/win32/dbghelp/storage.c
@@ -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)
diff --git a/dll/win32/dbghelp/symbol.c b/dll/win32/dbghelp/symbol.c
index 280666d0694..07ba9a37cef 100644
--- a/dll/win32/dbghelp/symbol.c
+++ b/dll/win32/dbghelp/symbol.c
@@ -48,31 +48,99 @@ static inline int cmp_addr(ULONG64 a1, ULONG64 a2)
return 0;
}
-static inline int cmp_sorttab_addr(const struct module* module, int idx, ULONG64 addr)
+static inline int cmp_sorttab_addr(struct module* module, int idx, ULONG64 addr)
{
ULONG64 ref;
- symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_ADDRESS, &ref);
+ symt_get_info(module, &module->addr_sorttab[idx]->symt, TI_GET_ADDRESS, &ref);
return cmp_addr(ref, addr);
}
+struct module* symt_cmp_addr_module = NULL;
+
int symt_cmp_addr(const void* p1, const void* p2)
{
const struct symt* sym1 = *(const struct symt* const *)p1;
const struct symt* sym2 = *(const struct symt* const *)p2;
ULONG64 a1, a2;
- symt_get_info(sym1, TI_GET_ADDRESS, &a1);
- symt_get_info(sym2, TI_GET_ADDRESS, &a2);
+ symt_get_info(symt_cmp_addr_module, sym1, TI_GET_ADDRESS, &a1);
+ symt_get_info(symt_cmp_addr_module, sym2, TI_GET_ADDRESS, &a2);
return cmp_addr(a1, a2);
}
-static inline void re_append(char** mask, unsigned* len, char ch)
+DWORD symt_ptr2index(struct module* module, const struct symt* sym)
{
- *mask = HeapReAlloc(GetProcessHeap(), 0, *mask, ++(*len));
- (*mask)[*len - 2] = ch;
+#ifdef _WIN64
+ const struct symt** c;
+ int len = vector_length(&module->vsymt), i;
+
+ /* FIXME: this is inefficient */
+ for (i = 0; i < len; i++)
+ {
+ if (*(struct symt**)vector_at(&module->vsymt, i) == sym)
+ return i + 1;
+ }
+ /* not found */
+ c = vector_add(&module->vsymt, &module->pool);
+ if (c) *c = sym;
+ return len + 1;
+#else
+ return (DWORD)sym;
+#endif
}
+struct symt* symt_index2ptr(struct module* module, DWORD id)
+{
+#ifdef _WIN64
+ if (!id-- || id >= vector_length(&module->vsymt)) return NULL;
+ return *(struct symt**)vector_at(&module->vsymt, id);
+#else
+ return (struct symt*)id;
+#endif
+}
+
+static BOOL symt_grow_sorttab(struct module* module, unsigned sz)
+{
+ struct symt_ht** new;
+ unsigned int size;
+
+ if (sz <= module->sorttab_size) return TRUE;
+ if (module->addr_sorttab)
+ {
+ size = module->sorttab_size * 2;
+ new = HeapReAlloc(GetProcessHeap(), 0, module->addr_sorttab,
+ size * sizeof(struct symt_ht*));
+ }
+ else
+ {
+ size = 64;
+ new = HeapAlloc(GetProcessHeap(), 0, size * sizeof(struct symt_ht*));
+ }
+ if (!new) return FALSE;
+ module->sorttab_size = size;
+ module->addr_sorttab = new;
+ return TRUE;
+}
+
+static void symt_add_module_ht(struct module* module, struct symt_ht* ht)
+{
+ ULONG64 addr;
+
+ hash_table_add(&module->ht_symbols, &ht->hash_elt);
+ /* Don't store in sorttab a symbol without address, they are of
+ * no use here (e.g. constant values)
+ */
+ if (symt_get_info(module, &ht->symt, TI_GET_ADDRESS, &addr) &&
+ symt_grow_sorttab(module, module->num_symbols + 1))
+ {
+ module->addr_sorttab[module->num_symbols++] = ht;
+ module->sortlist_valid = FALSE;
+ }
+}
+
+#ifdef HAVE_REGEX_H
+
/* transforms a dbghelp's regular expression into a POSIX one
* Here are the valid dbghelp reg ex characters:
* * 0 or more characters
@@ -84,47 +152,138 @@ static inline void re_append(char** mask, unsigned* len, char ch)
*/
static void compile_regex(const char* str, int numchar, regex_t* re, BOOL _case)
{
- char* mask = HeapAlloc(GetProcessHeap(), 0, 1);
- unsigned len = 1;
+ char *mask, *p;
BOOL in_escape = FALSE;
unsigned flags = REG_NOSUB;
- re_append(&mask, &len, '^');
+ if (numchar == -1) numchar = strlen( str );
+
+ p = mask = HeapAlloc( GetProcessHeap(), 0, 2 * numchar + 3 );
+ *p++ = '^';
while (*str && numchar--)
{
/* FIXME: this shouldn't be valid on '-' */
if (in_escape)
{
- re_append(&mask, &len, '\\');
- re_append(&mask, &len, *str);
+ *p++ = '\\';
+ *p++ = *str;
in_escape = FALSE;
}
else switch (*str)
{
case '\\': in_escape = TRUE; break;
- case '*': re_append(&mask, &len, '.'); re_append(&mask, &len, '*'); break;
- case '?': re_append(&mask, &len, '.'); break;
- case '#': re_append(&mask, &len, '*'); break;
+ case '*': *p++ = '.'; *p++ = '*'; break;
+ case '?': *p++ = '.'; break;
+ case '#': *p++ = '*'; break;
/* escape some valid characters in dbghelp reg exp:s */
- case '$': re_append(&mask, &len, '\\'); re_append(&mask, &len, '$'); break;
+ case '$': *p++ = '\\'; *p++ = '$'; break;
/* +, [, ], - are the same in dbghelp & POSIX, use them as any other char */
- default: re_append(&mask, &len, *str); break;
+ default: *p++ = *str; break;
}
str++;
}
if (in_escape)
{
- re_append(&mask, &len, '\\');
- re_append(&mask, &len, '\\');
+ *p++ = '\\';
+ *p++ = '\\';
}
- re_append(&mask, &len, '$');
- mask[len - 1] = '\0';
+ *p++ = '$';
+ *p = 0;
if (_case) flags |= REG_ICASE;
if (regcomp(re, mask, flags)) FIXME("Couldn't compile %s\n", mask);
HeapFree(GetProcessHeap(), 0, mask);
}
+static BOOL compile_file_regex(regex_t* re, const char* srcfile)
+{
+ char *mask, *p;
+ BOOL ret;
+
+ if (!srcfile || !*srcfile) return regcomp(re, ".*", REG_NOSUB);
+
+ p = mask = HeapAlloc(GetProcessHeap(), 0, 5 * strlen(srcfile) + 4);
+ *p++ = '^';
+ while (*srcfile)
+ {
+ switch (*srcfile)
+ {
+ case '\\':
+ case '/':
+ *p++ = '[';
+ *p++ = '\\';
+ *p++ = '\\';
+ *p++ = '/';
+ *p++ = ']';
+ break;
+ case '.':
+ *p++ = '\\';
+ *p++ = '.';
+ break;
+ default:
+ *p++ = *srcfile;
+ break;
+ }
+ srcfile++;
+ }
+ *p++ = '$';
+ *p = 0;
+ ret = !regcomp(re, mask, REG_NOSUB);
+ HeapFree(GetProcessHeap(), 0, mask);
+ if (!ret)
+ {
+ FIXME("Couldn't compile %s\n", mask);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ }
+ return ret;
+}
+
+static int match_regexp( const regex_t *re, const char *str )
+{
+ return !regexec( re, str, 0, NULL, 0 );
+}
+
+#else /* HAVE_REGEX_H */
+
+/* if we don't have regexp support, fall back to a simple string comparison */
+
+typedef struct
+{
+ char *str;
+ BOOL icase;
+} regex_t;
+
+static void compile_regex(const char* str, int numchar, regex_t* re, BOOL _case)
+{
+ if (numchar == -1) numchar = strlen( str );
+
+ re->str = HeapAlloc( GetProcessHeap(), 0, numchar + 1 );
+ memcpy( re->str, str, numchar );
+ re->str[numchar] = 0;
+ re->icase = _case;
+}
+
+static BOOL compile_file_regex(regex_t* re, const char* srcfile)
+{
+ if (!srcfile || !*srcfile) re->str = NULL;
+ else compile_regex( srcfile, -1, re, FALSE );
+ return TRUE;
+}
+
+static int match_regexp( const regex_t *re, const char *str )
+{
+ if (!re->str) return 1;
+ if (re->icase) return !lstrcmpiA( re->str, str );
+ return !strcmp( re->str, str );
+}
+
+static void regfree( regex_t *re )
+{
+ HeapFree( GetProcessHeap(), 0, re->str );
+}
+
+#endif /* HAVE_REGEX_H */
+
struct symt_compiland* symt_new_compiland(struct module* module,
unsigned long address, unsigned src_idx)
{
@@ -145,8 +304,7 @@ struct symt_compiland* symt_new_compiland(struct module* module,
struct symt_public* symt_new_public(struct module* module,
struct symt_compiland* compiland,
const char* name,
- unsigned long address, unsigned size,
- BOOL in_code, BOOL is_func)
+ unsigned long address, unsigned size)
{
struct symt_public* sym;
struct symt** p;
@@ -160,13 +318,10 @@ struct symt_public* symt_new_public(struct module* module,
{
sym->symt.tag = SymTagPublicSymbol;
sym->hash_elt.name = pool_strdup(&module->pool, name);
- hash_table_add(&module->ht_symbols, &sym->hash_elt);
- module->sortlist_valid = FALSE;
sym->container = compiland ? &compiland->symt : NULL;
sym->address = address;
sym->size = size;
- sym->in_code = in_code;
- sym->is_function = is_func;
+ symt_add_module_ht(module, (struct symt_ht*)sym);
if (compiland)
{
p = vector_add(&compiland->vchildren, &module->pool);
@@ -192,19 +347,18 @@ struct symt_data* symt_new_global_variable(struct module* module,
{
sym->symt.tag = SymTagData;
sym->hash_elt.name = pool_strdup(&module->pool, name);
- hash_table_add(&module->ht_symbols, &sym->hash_elt);
- module->sortlist_valid = FALSE;
sym->kind = is_static ? DataIsFileStatic : DataIsGlobal;
sym->container = compiland ? &compiland->symt : NULL;
sym->type = type;
sym->u.var.offset = addr;
- if (type && size && symt_get_info(type, TI_GET_LENGTH, &tsz))
+ if (type && size && symt_get_info(module, type, TI_GET_LENGTH, &tsz))
{
if (tsz != size)
FIXME("Size mismatch for %s.%s between type (%s) and src (%lu)\n",
debugstr_w(module->module.ModuleName), name,
wine_dbgstr_longlong(tsz), size);
}
+ symt_add_module_ht(module, (struct symt_ht*)sym);
if (compiland)
{
p = vector_add(&compiland->vchildren, &module->pool);
@@ -231,14 +385,13 @@ struct symt_function* symt_new_function(struct module* module,
{
sym->symt.tag = SymTagFunction;
sym->hash_elt.name = pool_strdup(&module->pool, name);
- hash_table_add(&module->ht_symbols, &sym->hash_elt);
- module->sortlist_valid = FALSE;
sym->container = &compiland->symt;
sym->address = addr;
sym->type = sig_type;
sym->size = size;
vector_init(&sym->vlines, sizeof(struct line_info), 64);
vector_init(&sym->vchildren, sizeof(struct symt*), 8);
+ symt_add_module_ht(module, (struct symt_ht*)sym);
if (compiland)
{
p = vector_add(&compiland->vchildren, &module->pool);
@@ -363,7 +516,7 @@ struct symt_block* symt_open_func_block(struct module* module,
}
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)
{
assert(func);
@@ -395,7 +548,7 @@ struct symt_hierarchy_point* symt_add_function_point(struct module* module,
return sym;
}
-BOOL symt_normalize_function(struct module* module, struct symt_function* func)
+BOOL symt_normalize_function(struct module* module, const struct symt_function* func)
{
unsigned len;
struct line_info* dli;
@@ -432,12 +585,11 @@ struct symt_thunk* symt_new_thunk(struct module* module,
{
sym->symt.tag = SymTagThunk;
sym->hash_elt.name = pool_strdup(&module->pool, name);
- hash_table_add(&module->ht_symbols, &sym->hash_elt);
- module->sortlist_valid = FALSE;
sym->container = &compiland->symt;
sym->address = addr;
sym->size = size;
sym->ordinal = ord;
+ symt_add_module_ht(module, (struct symt_ht*)sym);
if (compiland)
{
struct symt** p;
@@ -462,12 +614,11 @@ struct symt_data* symt_new_constant(struct module* module,
{
sym->symt.tag = SymTagData;
sym->hash_elt.name = pool_strdup(&module->pool, name);
- hash_table_add(&module->ht_symbols, &sym->hash_elt);
- module->sortlist_valid = FALSE;
sym->kind = DataIsConstant;
sym->container = compiland ? &compiland->symt : NULL;
sym->type = type;
sym->u.value = *v;
+ symt_add_module_ht(module, (struct symt_ht*)sym);
if (compiland)
{
struct symt** p;
@@ -491,11 +642,10 @@ struct symt_hierarchy_point* symt_new_label(struct module* module,
{
sym->symt.tag = SymTagLabel;
sym->hash_elt.name = pool_strdup(&module->pool, name);
- hash_table_add(&module->ht_symbols, &sym->hash_elt);
- module->sortlist_valid = FALSE;
sym->loc.kind = loc_absolute;
sym->loc.offset = address;
sym->parent = compiland ? &compiland->symt : NULL;
+ symt_add_module_ht(module, (struct symt_ht*)sym);
if (compiland)
{
struct symt** p;
@@ -507,20 +657,21 @@ struct symt_hierarchy_point* symt_new_label(struct module* module,
}
/* expect sym_info->MaxNameLen to be set before being called */
-static void symt_fill_sym_info(const struct module_pair* pair,
+static void symt_fill_sym_info(struct module_pair* pair,
const struct symt_function* func,
const struct symt* sym, SYMBOL_INFO* sym_info)
{
const char* name;
DWORD64 size;
- if (!symt_get_info(sym, TI_GET_TYPE, &sym_info->TypeIndex))
+ if (!symt_get_info(pair->effective, sym, TI_GET_TYPE, &sym_info->TypeIndex))
sym_info->TypeIndex = 0;
- sym_info->info = (DWORD)sym;
+ sym_info->info = symt_ptr2index(pair->effective, sym);
sym_info->Reserved[0] = sym_info->Reserved[1] = 0;
- if (!symt_get_info(sym, TI_GET_LENGTH, &size) &&
+ if (!symt_get_info(pair->effective, sym, TI_GET_LENGTH, &size) &&
(!sym_info->TypeIndex ||
- !symt_get_info((struct symt*)sym_info->TypeIndex, TI_GET_LENGTH, &size)))
+ !symt_get_info(pair->effective, symt_index2ptr(pair->effective, sym_info->TypeIndex),
+ TI_GET_LENGTH, &size)))
size = 0;
sym_info->Size = (DWORD)size;
sym_info->ModBase = pair->requested->module.BaseOfImage;
@@ -569,7 +720,7 @@ static void symt_fill_sym_info(const struct module_pair* pair,
break;
case DataIsGlobal:
case DataIsFileStatic:
- symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
+ symt_get_info(pair->effective, sym, TI_GET_ADDRESS, &sym_info->Address);
sym_info->Register = 0;
break;
case DataIsConstant:
@@ -582,7 +733,8 @@ static void symt_fill_sym_info(const struct module_pair* pair,
case VT_UI4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.ulVal; break;
case VT_UI2: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.uiVal; break;
case VT_UI1: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.bVal; break;
- case VT_I1 | VT_BYREF: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.byref; break;
+ case VT_I1 | VT_BYREF: sym_info->Value = (ULONG64)(DWORD_PTR)data->u.value.n1.n2.n3.byref; break;
+ case VT_EMPTY: sym_info->Value = 0; break;
default:
FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt);
sym_info->Value = 0;
@@ -596,18 +748,18 @@ static void symt_fill_sym_info(const struct module_pair* pair,
break;
case SymTagPublicSymbol:
sym_info->Flags |= SYMFLAG_EXPORT;
- symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
+ symt_get_info(pair->effective, sym, TI_GET_ADDRESS, &sym_info->Address);
break;
case SymTagFunction:
sym_info->Flags |= SYMFLAG_FUNCTION;
- symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
+ symt_get_info(pair->effective, sym, TI_GET_ADDRESS, &sym_info->Address);
break;
case SymTagThunk:
sym_info->Flags |= SYMFLAG_THUNK;
- symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
+ symt_get_info(pair->effective, sym, TI_GET_ADDRESS, &sym_info->Address);
break;
default:
- symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
+ symt_get_info(pair->effective, sym, TI_GET_ADDRESS, &sym_info->Address);
sym_info->Register = 0;
break;
}
@@ -641,7 +793,7 @@ struct sym_enum
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
};
-static BOOL send_symbol(const struct sym_enum* se, const struct module_pair* pair,
+static BOOL send_symbol(const struct sym_enum* se, struct module_pair* pair,
const struct symt_function* func, const struct symt* sym)
{
symt_fill_sym_info(pair, func, sym, se->sym_info);
@@ -662,8 +814,7 @@ static BOOL symt_enum_module(struct module_pair* pair, const regex_t* regex,
while ((ptr = hash_table_iter_up(&hti)))
{
sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
- if (sym->hash_elt.name &&
- regexec(regex, sym->hash_elt.name, 0, NULL, 0) == 0)
+ if (sym->hash_elt.name && match_regexp(regex, sym->hash_elt.name))
{
se->sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO);
@@ -673,6 +824,26 @@ static BOOL symt_enum_module(struct module_pair* pair, const regex_t* regex,
return FALSE;
}
+static inline unsigned where_to_insert(struct module* module, unsigned high, const struct symt_ht* elt)
+{
+ unsigned low = 0, mid = high / 2;
+ ULONG64 addr;
+
+ if (!high) return 0;
+ symt_get_info(module, &elt->symt, TI_GET_ADDRESS, &addr);
+ do
+ {
+ switch (cmp_sorttab_addr(module, mid, addr))
+ {
+ case 0: return mid;
+ case -1: low = mid + 1; break;
+ case 1: high = mid; break;
+ }
+ mid = low + (high - low) / 2;
+ } while (low < high);
+ return mid;
+}
+
/***********************************************************************
* resort_symbols
*
@@ -680,55 +851,53 @@ static BOOL symt_enum_module(struct module_pair* pair, const regex_t* regex,
*/
static BOOL resort_symbols(struct module* module)
{
- void* ptr;
- struct symt_ht* sym;
- struct hash_table_iter hti;
- ULONG64 addr;
-
- if (!(module->module.NumSyms = module->ht_symbols.num_elts))
+ if (!(module->module.NumSyms = module->num_symbols))
return FALSE;
-
- if (module->addr_sorttab)
- module->addr_sorttab = HeapReAlloc(GetProcessHeap(), 0,
- module->addr_sorttab,
- module->module.NumSyms * sizeof(struct symt_ht*));
- else
- module->addr_sorttab = HeapAlloc(GetProcessHeap(), 0,
- module->module.NumSyms * sizeof(struct symt_ht*));
- if (!module->addr_sorttab) return FALSE;
- module->num_sorttab = 0;
- hash_table_iter_init(&module->ht_symbols, &hti, NULL);
- while ((ptr = hash_table_iter_up(&hti)))
+ /* FIXME: what's the optimal value here ??? */
+ if (module->num_sorttab && module->num_symbols <= module->num_sorttab + 30)
{
- sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
- assert(sym);
- /* Don't store in sorttab symbol without address, they are of
- * no use here (e.g. constant values)
- * As the number of those symbols is very couple (a couple per module)
- * we don't bother for the unused spots at the end of addr_sorttab
- */
- if (symt_get_info(&sym->symt, TI_GET_ADDRESS, &addr))
- module->addr_sorttab[module->num_sorttab++] = sym;
+ int i, delta, ins_idx = module->num_sorttab, prev_ins_idx;
+ struct symt_ht* tmp[30];
+
+ delta = module->num_symbols - module->num_sorttab;
+ memcpy(tmp, &module->addr_sorttab[module->num_sorttab], delta * sizeof(struct symt_ht*));
+ symt_cmp_addr_module = module;
+ qsort(tmp, delta, sizeof(struct symt_ht*), symt_cmp_addr);
+
+ for (i = delta - 1; i >= 0; i--)
+ {
+ prev_ins_idx = ins_idx;
+ ins_idx = where_to_insert(module, prev_ins_idx = ins_idx, tmp[i]);
+ memmove(&module->addr_sorttab[ins_idx + i + 1],
+ &module->addr_sorttab[ins_idx],
+ (prev_ins_idx - ins_idx) * sizeof(struct symt_ht*));
+ module->addr_sorttab[ins_idx + i] = tmp[i];
+ }
}
- qsort(module->addr_sorttab, module->num_sorttab, sizeof(struct symt_ht*), symt_cmp_addr);
+ else
+ {
+ symt_cmp_addr_module = module;
+ qsort(module->addr_sorttab, module->num_symbols, sizeof(struct symt_ht*), symt_cmp_addr);
+ }
+ module->num_sorttab = module->num_symbols;
return module->sortlist_valid = TRUE;
}
-static void symt_get_length(struct symt* symt, ULONG64* size)
+static void symt_get_length(struct module* module, const struct symt* symt, ULONG64* size)
{
DWORD type_index;
- if (symt_get_info(symt, TI_GET_LENGTH, size) && *size)
+ if (symt_get_info(module, symt, TI_GET_LENGTH, size) && *size)
return;
- if (symt_get_info(symt, TI_GET_TYPE, &type_index) &&
- symt_get_info((struct symt*)type_index, TI_GET_LENGTH, size)) return;
+ if (symt_get_info(module, symt, TI_GET_TYPE, &type_index) &&
+ symt_get_info(module, symt_index2ptr(module, type_index), TI_GET_LENGTH, size)) return;
*size = 0x1000; /* arbitrary value */
}
/* assume addr is in module */
-struct symt_ht* symt_find_nearest(struct module* module, DWORD addr)
+struct symt_ht* symt_find_nearest(struct module* module, DWORD_PTR addr)
{
int mid, high, low;
ULONG64 ref_addr, ref_size;
@@ -744,12 +913,12 @@ struct symt_ht* symt_find_nearest(struct module* module, DWORD addr)
low = 0;
high = module->num_sorttab;
- symt_get_info(&module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref_addr);
+ symt_get_info(module, &module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref_addr);
if (addr < ref_addr) return NULL;
if (high)
{
- symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref_addr);
- symt_get_length(&module->addr_sorttab[high - 1]->symt, &ref_size);
+ symt_get_info(module, &module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref_addr);
+ symt_get_length(module, &module->addr_sorttab[high - 1]->symt, &ref_size);
if (addr >= ref_addr + ref_size) return NULL;
}
@@ -770,7 +939,7 @@ struct symt_ht* symt_find_nearest(struct module* module, DWORD addr)
*/
if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
{
- symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
+ symt_get_info(module, &module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
if (low > 0 &&
module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
!cmp_sorttab_addr(module, low - 1, ref_addr))
@@ -781,9 +950,9 @@ struct symt_ht* symt_find_nearest(struct module* module, DWORD addr)
low++;
}
/* finally check that we fit into the found symbol */
- symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
+ symt_get_info(module, &module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
if (addr < ref_addr) return NULL;
- symt_get_length(&module->addr_sorttab[low]->symt, &ref_size);
+ symt_get_length(module, &module->addr_sorttab[low]->symt, &ref_size);
if (addr >= ref_addr + ref_size) return NULL;
return module->addr_sorttab[low];
@@ -812,7 +981,7 @@ static BOOL symt_enum_locals_helper(struct module_pair* pair,
}
break;
case SymTagData:
- if (regexec(preg, symt_get_name(lsym), 0, NULL, 0) == 0)
+ if (match_regexp(preg, symt_get_name(lsym)))
{
if (send_symbol(se, pair, func, lsym)) return FALSE;
}
@@ -900,6 +1069,7 @@ static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
regex_t mod_regex, sym_regex;
pair.pcs = process_find_by_handle(hProcess);
+ if (!pair.pcs) return FALSE;
if (BaseOfDll == 0)
{
/* do local variables ? */
@@ -916,22 +1086,22 @@ static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
{
if (pair.requested->type == DMT_PE && module_get_debug(&pair))
{
- if (regexec(&mod_regex, pair.requested->module_name, 0, NULL, 0) == 0 &&
+ if (match_regexp(&mod_regex, pair.requested->module_name) &&
symt_enum_module(&pair, &sym_regex, se))
break;
}
}
/* not found in PE modules, retry on the ELF ones
*/
- if (!pair.requested && (dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES))
+ if (!pair.requested && (dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES))
{
for (pair.requested = pair.pcs->lmodules; pair.requested; pair.requested = pair.requested->next)
{
- if (pair.requested->type == DMT_ELF &&
+ if ((pair.requested->type == DMT_ELF || pair.requested->type == DMT_MACHO) &&
!module_get_containee(pair.pcs, pair.requested) &&
module_get_debug(&pair))
{
- if (regexec(&mod_regex, pair.requested->module_name, 0, NULL, 0) == 0 &&
+ if (match_regexp(&mod_regex, pair.requested->module_name) &&
symt_enum_module(&pair, &sym_regex, se))
break;
}
@@ -1046,7 +1216,7 @@ struct sym_enumerate
static BOOL CALLBACK sym_enumerate_cb(PSYMBOL_INFO syminfo, ULONG size, void* ctx)
{
- struct sym_enumerate* se = (struct sym_enumerate*)ctx;
+ struct sym_enumerate* se = ctx;
return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx);
}
@@ -1073,7 +1243,7 @@ struct sym_enumerate64
static BOOL CALLBACK sym_enumerate_cb64(PSYMBOL_INFO syminfo, ULONG size, void* ctx)
{
- struct sym_enumerate64* se = (struct sym_enumerate64*)ctx;
+ struct sym_enumerate64* se = ctx;
return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx);
}
@@ -1250,11 +1420,12 @@ BOOL WINAPI SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol)
}
/* not found in PE modules, retry on the ELF ones
*/
- if (dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES)
+ if (dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES)
{
for (module = pcs->lmodules; module; module = module->next)
{
- if (module->type == DMT_ELF && !module_get_containee(pcs, module) &&
+ if ((module->type == DMT_ELF || module->type == DMT_MACHO) &&
+ !module_get_containee(pcs, module) &&
find_name(pcs, module, Name, Symbol))
return TRUE;
}
@@ -1262,6 +1433,28 @@ BOOL WINAPI SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol)
return FALSE;
}
+/***********************************************************************
+ * SymGetSymFromName64 (DBGHELP.@)
+ */
+BOOL WINAPI SymGetSymFromName64(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL64 Symbol)
+{
+ char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
+ SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
+ size_t len;
+
+ if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
+ si->SizeOfStruct = sizeof(*si);
+ si->MaxNameLen = MAX_SYM_NAME;
+ if (!SymFromName(hProcess, Name, si)) return FALSE;
+
+ Symbol->Address = si->Address;
+ Symbol->Size = si->Size;
+ Symbol->Flags = si->Flags;
+ len = min(Symbol->MaxNameLength, si->MaxNameLen);
+ lstrcpynA(Symbol->Name, si->Name, len);
+ return TRUE;
+}
+
/***********************************************************************
* SymGetSymFromName (DBGHELP.@)
*/
@@ -1290,7 +1483,7 @@ BOOL WINAPI SymGetSymFromName(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL Symb
* fills information about a file
*/
BOOL symt_fill_func_line_info(const struct module* module, const struct symt_function* func,
- DWORD addr, IMAGEHLP_LINE* line)
+ DWORD64 addr, IMAGEHLP_LINE64* line)
{
struct line_info* dli = NULL;
BOOL found = FALSE;
@@ -1320,9 +1513,9 @@ BOOL symt_fill_func_line_info(const struct module* module, const struct symt_fun
}
/***********************************************************************
- * SymGetSymNext (DBGHELP.@)
+ * SymGetSymNext64 (DBGHELP.@)
*/
-BOOL WINAPI SymGetSymNext(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
+BOOL WINAPI SymGetSymNext64(HANDLE hProcess, PIMAGEHLP_SYMBOL64 Symbol)
{
/* algo:
* get module from Symbol.Address
@@ -1336,41 +1529,33 @@ BOOL WINAPI SymGetSymNext(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
}
/***********************************************************************
- * SymGetSymPrev (DBGHELP.@)
+ * SymGetSymNext (DBGHELP.@)
*/
-
-BOOL WINAPI SymGetSymPrev(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
+BOOL WINAPI SymGetSymNext(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
{
FIXME("(%p, %p): stub\n", hProcess, Symbol);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
-/******************************************************************
- * SymGetLineFromAddr (DBGHELP.@)
- *
+/***********************************************************************
+ * SymGetSymPrev64 (DBGHELP.@)
*/
-BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr,
- PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
+BOOL WINAPI SymGetSymPrev64(HANDLE hProcess, PIMAGEHLP_SYMBOL64 Symbol)
{
- struct module_pair pair;
- struct symt_ht* symt;
+ FIXME("(%p, %p): stub\n", hProcess, Symbol);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
- TRACE("%p %08x %p %p\n", hProcess, dwAddr, pdwDisplacement, Line);
-
- if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
-
- pair.pcs = process_find_by_handle(hProcess);
- if (!pair.pcs) return FALSE;
- pair.requested = module_find_by_addr(pair.pcs, dwAddr, DMT_UNKNOWN);
- if (!module_get_debug(&pair)) return FALSE;
- if ((symt = symt_find_nearest(pair.effective, dwAddr)) == NULL) return FALSE;
-
- if (symt->symt.tag != SymTagFunction) return FALSE;
- if (!symt_fill_func_line_info(pair.effective, (struct symt_function*)symt,
- dwAddr, Line)) return FALSE;
- *pdwDisplacement = dwAddr - Line->Address;
- return TRUE;
+/***********************************************************************
+ * SymGetSymPrev (DBGHELP.@)
+ */
+BOOL WINAPI SymGetSymPrev(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
+{
+ FIXME("(%p, %p): stub\n", hProcess, Symbol);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
}
/******************************************************************
@@ -1390,16 +1575,16 @@ static void copy_line_64_from_32(IMAGEHLP_LINE64* l64, const IMAGEHLP_LINE* l32)
* copy_line_W64_from_32 (internal)
*
*/
-static void copy_line_W64_from_32(struct process* pcs, IMAGEHLP_LINEW64* l64, const IMAGEHLP_LINE* l32)
+static void copy_line_W64_from_64(struct process* pcs, IMAGEHLP_LINEW64* l64w, const IMAGEHLP_LINE64* l64)
{
unsigned len;
- l64->Key = l32->Key;
- l64->LineNumber = l32->LineNumber;
- len = MultiByteToWideChar(CP_ACP, 0, l32->FileName, -1, NULL, 0);
- if ((l64->FileName = fetch_buffer(pcs, len * sizeof(WCHAR))))
- MultiByteToWideChar(CP_ACP, 0, l32->FileName, -1, l64->FileName, len);
- l64->Address = l32->Address;
+ l64w->Key = l64->Key;
+ l64w->LineNumber = l64->LineNumber;
+ len = MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, NULL, 0);
+ if ((l64w->FileName = fetch_buffer(pcs, len * sizeof(WCHAR))))
+ MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, l64w->FileName, len);
+ l64w->Address = l64->Address;
}
/******************************************************************
@@ -1415,6 +1600,22 @@ static void copy_line_32_from_64(IMAGEHLP_LINE* l32, const IMAGEHLP_LINE64* l64)
l32->Address = l64->Address;
}
+/******************************************************************
+ * SymGetLineFromAddr (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr,
+ PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
+{
+ IMAGEHLP_LINE64 il64;
+
+ il64.SizeOfStruct = sizeof(il64);
+ if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64))
+ return FALSE;
+ copy_line_32_from_64(Line, &il64);
+ return TRUE;
+}
+
/******************************************************************
* SymGetLineFromAddr64 (DBGHELP.@)
*
@@ -1422,14 +1623,23 @@ static void copy_line_32_from_64(IMAGEHLP_LINE* l32, const IMAGEHLP_LINE64* l64)
BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr,
PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line)
{
- IMAGEHLP_LINE line32;
+ struct module_pair pair;
+ struct symt_ht* symt;
+
+ TRACE("%p %s %p %p\n", hProcess, wine_dbgstr_longlong(dwAddr), pdwDisplacement, Line);
if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
- if (!validate_addr64(dwAddr)) return FALSE;
- line32.SizeOfStruct = sizeof(line32);
- if (!SymGetLineFromAddr(hProcess, (DWORD)dwAddr, pdwDisplacement, &line32))
- return FALSE;
- copy_line_64_from_32(Line, &line32);
+
+ pair.pcs = process_find_by_handle(hProcess);
+ if (!pair.pcs) return FALSE;
+ pair.requested = module_find_by_addr(pair.pcs, dwAddr, DMT_UNKNOWN);
+ if (!module_get_debug(&pair)) return FALSE;
+ if ((symt = symt_find_nearest(pair.effective, dwAddr)) == NULL) return FALSE;
+
+ if (symt->symt.tag != SymTagFunction) return FALSE;
+ if (!symt_fill_func_line_info(pair.effective, (struct symt_function*)symt,
+ dwAddr, Line)) return FALSE;
+ *pdwDisplacement = dwAddr - Line->Address;
return TRUE;
}
@@ -1440,24 +1650,20 @@ BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr,
BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr,
PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line)
{
- struct process* pcs = process_find_by_handle(hProcess);
- IMAGEHLP_LINE line32;
+ IMAGEHLP_LINE64 il64;
- if (!pcs) return FALSE;
- if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
- if (!validate_addr64(dwAddr)) return FALSE;
- line32.SizeOfStruct = sizeof(line32);
- if (!SymGetLineFromAddr(hProcess, (DWORD)dwAddr, pdwDisplacement, &line32))
+ il64.SizeOfStruct = sizeof(il64);
+ if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64))
return FALSE;
- copy_line_W64_from_32(pcs, Line, &line32);
+ copy_line_W64_from_64(process_find_by_handle(hProcess), Line, &il64);
return TRUE;
}
/******************************************************************
- * SymGetLinePrev (DBGHELP.@)
+ * SymGetLinePrev64 (DBGHELP.@)
*
*/
-BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
+BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line)
{
struct module_pair pair;
struct line_info* li;
@@ -1473,7 +1679,7 @@ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
if (!module_get_debug(&pair)) return FALSE;
if (Line->Key == 0) return FALSE;
- li = (struct line_info*)Line->Key;
+ li = Line->Key;
/* things are a bit complicated because when we encounter a DLIT_SOURCEFILE
* element we have to go back until we find the prev one to get the real
* source file name for the DLIT_OFFSET element just before
@@ -1504,26 +1710,26 @@ BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
}
/******************************************************************
- * SymGetLinePrev64 (DBGHELP.@)
+ * SymGetLinePrev (DBGHELP.@)
*
*/
-BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line)
+BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
{
- IMAGEHLP_LINE line32;
+ IMAGEHLP_LINE64 line64;
- line32.SizeOfStruct = sizeof(line32);
- copy_line_32_from_64(&line32, Line);
- if (!SymGetLinePrev(hProcess, &line32)) return FALSE;
- copy_line_64_from_32(Line, &line32);
+ line64.SizeOfStruct = sizeof(line64);
+ copy_line_64_from_32(&line64, Line);
+ if (!SymGetLinePrev64(hProcess, &line64)) return FALSE;
+ copy_line_32_from_64(Line, &line64);
return TRUE;
}
-
-BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE line)
+
+BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line)
{
struct line_info* li;
if (line->Key == 0) return FALSE;
- li = (struct line_info*)line->Key;
+ li = line->Key;
while (!li->is_last)
{
li++;
@@ -1540,10 +1746,10 @@ BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE line)
}
/******************************************************************
- * SymGetLineNext (DBGHELP.@)
+ * SymGetLineNext64 (DBGHELP.@)
*
*/
-BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line)
+BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line)
{
struct module_pair pair;
@@ -1561,20 +1767,20 @@ BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line)
}
/******************************************************************
- * SymGetLineNext64 (DBGHELP.@)
+ * SymGetLineNext (DBGHELP.@)
*
*/
-BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line)
+BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line)
{
- IMAGEHLP_LINE line32;
+ IMAGEHLP_LINE64 line64;
- line32.SizeOfStruct = sizeof(line32);
- copy_line_32_from_64(&line32, Line);
- if (!SymGetLineNext(hProcess, &line32)) return FALSE;
- copy_line_64_from_32(Line, &line32);
+ line64.SizeOfStruct = sizeof(line64);
+ copy_line_64_from_32(&line64, Line);
+ if (!SymGetLineNext64(hProcess, &line64)) return FALSE;
+ copy_line_32_from_64(Line, &line64);
return TRUE;
}
-
+
/***********************************************************************
* SymFunctionTableAccess (DBGHELP.@)
*/
@@ -1598,7 +1804,15 @@ PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
*/
BOOL WINAPI SymUnDName(PIMAGEHLP_SYMBOL sym, PSTR UnDecName, DWORD UnDecNameLength)
{
- TRACE("(%p %s %u)\n", sym, UnDecName, UnDecNameLength);
+ return UnDecorateSymbolName(sym->Name, UnDecName, UnDecNameLength,
+ UNDNAME_COMPLETE) != 0;
+}
+
+/***********************************************************************
+ * SymUnDName64 (DBGHELP.@)
+ */
+BOOL WINAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym, PSTR UnDecName, DWORD UnDecNameLength)
+{
return UnDecorateSymbolName(sym->Name, UnDecName, UnDecNameLength,
UNDNAME_COMPLETE) != 0;
}
@@ -1645,7 +1859,7 @@ BOOL WINAPI SymMatchString(PCSTR string, PCSTR re, BOOL _case)
TRACE("%s %s %c\n", string, re, _case ? 'Y' : 'N');
compile_regex(re, -1, &preg, _case);
- ret = regexec(&preg, string, 0, NULL, 0) == 0;
+ ret = match_regexp(&preg, string);
regfree(&preg);
return ret;
}
@@ -1762,3 +1976,88 @@ BOOL WINAPI SymSetScopeFromAddr(HANDLE hProcess, ULONG64 addr)
if (!(pcs = process_find_by_handle(hProcess))) 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_file_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; ivlines); 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 (!match_regexp(&re, file)) 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;
+}
+
+BOOL WINAPI SymGetLineFromName(HANDLE hProcess, PCSTR ModuleName, PCSTR FileName,
+ DWORD dwLineNumber, PLONG plDisplacement, PIMAGEHLP_LINE Line)
+{
+ FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, ModuleName, FileName,
+ dwLineNumber, plDisplacement, Line);
+ return FALSE;
+}
+
+BOOL WINAPI SymGetLineFromName64(HANDLE hProcess, PCSTR ModuleName, PCSTR FileName,
+ DWORD dwLineNumber, PLONG lpDisplacement, PIMAGEHLP_LINE64 Line)
+{
+ FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, ModuleName, FileName,
+ dwLineNumber, lpDisplacement, Line);
+ return FALSE;
+}
+
+BOOL WINAPI SymGetLineFromNameW64(HANDLE hProcess, PCWSTR ModuleName, PCWSTR FileName,
+ DWORD dwLineNumber, PLONG plDisplacement, PIMAGEHLP_LINEW64 Line)
+{
+ FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, debugstr_w(ModuleName), debugstr_w(FileName),
+ dwLineNumber, plDisplacement, Line);
+ return FALSE;
+}
diff --git a/dll/win32/dbghelp/type.c b/dll/win32/dbghelp/type.c
index 947eb49095e..2ef4bb45095 100644
--- a/dll/win32/dbghelp/type.c
+++ b/dll/win32/dbghelp/type.c
@@ -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; ivtypes); 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;
}
diff --git a/dll/win32/dbghelp/version.rc b/dll/win32/dbghelp/version.rc
new file mode 100644
index 00000000000..1818010180e
--- /dev/null
+++ b/dll/win32/dbghelp/version.rc
@@ -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"
diff --git a/dll/win32/faultrep/faultrep.c b/dll/win32/faultrep/faultrep.c
new file mode 100644
index 00000000000..d4bd7131bbb
--- /dev/null
+++ b/dll/win32/faultrep/faultrep.c
@@ -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
+
+#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;
+}
diff --git a/dll/win32/faultrep/faultrep.rbuild b/dll/win32/faultrep/faultrep.rbuild
new file mode 100644
index 00000000000..aeeb3afeca5
--- /dev/null
+++ b/dll/win32/faultrep/faultrep.rbuild
@@ -0,0 +1,9 @@
+
+
+ .
+ include/reactos/wine
+
+ wine
+ advapi32
+ faultrep.c
+
diff --git a/dll/win32/faultrep/faultrep.spec b/dll/win32/faultrep/faultrep.spec
new file mode 100644
index 00000000000..77e543fa779
--- /dev/null
+++ b/dll/win32/faultrep/faultrep.spec
@@ -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
diff --git a/dll/win32/kernel32/file/dir.c b/dll/win32/kernel32/file/dir.c
index c89afb6e465..97c04470e75 100644
--- a/dll/win32/kernel32/file/dir.c
+++ b/dll/win32/kernel32/file/dir.c
@@ -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))
{
diff --git a/dll/win32/kernel32/misc/profile.c b/dll/win32/kernel32/misc/profile.c
index 09b7c76806a..e327029f378 100644
--- a/dll/win32/kernel32/misc/profile.c
+++ b/dll/win32/kernel32/misc/profile.c
@@ -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);
diff --git a/dll/win32/kernel32/misc/stubs.c b/dll/win32/kernel32/misc/stubs.c
index ecc9010d57d..d22e9baed17 100644
--- a/dll/win32/kernel32/misc/stubs.c
+++ b/dll/win32/kernel32/misc/stubs.c
@@ -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)
diff --git a/dll/win32/shell32/shell32_main.c b/dll/win32/shell32/shell32_main.c
index f4ae815ade4..2bf6502443f 100644
--- a/dll/win32/shell32/shell32_main.c
+++ b/dll/win32/shell32/shell32_main.c
@@ -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) &&
diff --git a/dll/win32/shell32/shellord.c b/dll/win32/shell32/shellord.c
index ff9025c4e0e..c25ddff3803 100644
--- a/dll/win32/shell32/shellord.c
+++ b/dll/win32/shell32/shellord.c
@@ -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]
*/
diff --git a/dll/win32/shell32/shlfileop.c b/dll/win32/shell32/shlfileop.c
index e3bdf6eac31..6992d187ee4 100644
--- a/dll/win32/shell32/shlfileop.c
+++ b/dll/win32/shell32/shlfileop.c
@@ -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);
}
}
diff --git a/dll/win32/user32/windows/menu.c b/dll/win32/user32/windows/menu.c
index 3f3916c6481..58c4a95243e 100644
--- a/dll/win32/user32/windows/menu.c
+++ b/dll/win32/user32/windows/menu.c
@@ -12,15 +12,25 @@
/* INCLUDES ******************************************************************/
#include
-
#include
-WINE_DEFAULT_DEBUG_CHANNEL(user32);
LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
+WINE_DEFAULT_DEBUG_CHANNEL(menu);
+
/* internal popup menu window messages */
-#define MM_SETMENUHANDLE (WM_USER + 0)
-#define MM_GETMENUHANDLE (WM_USER + 1)
+
+#define MM_SETMENUHANDLE (WM_USER + 0)
+#define MM_GETMENUHANDLE (WM_USER + 1)
+
+/* internal flags for menu tracking */
+
+#define TF_ENDMENU 0x10000
+#define TF_SUSPENDPOPUP 0x20000
+#define TF_SKIPREMOVE 0x40000
+
+#define ITEM_PREV -1
+#define ITEM_NEXT 1
/* Internal MenuTrackMenu() flags */
#define TPM_INTERNAL 0xF0000000
@@ -28,13 +38,14 @@ LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
-/* TYPES *********************************************************************/
#define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)
#define MENU_ITEM_TYPE(flags) ((flags) & MENU_TYPE_MASK)
+
+/* macro to test that flags do not indicate bitmap, ownerdraw or separator */
#define IS_STRING_ITEM(flags) (MF_STRING == MENU_ITEM_TYPE(flags))
-#define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags))
+#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
#define IS_SYSTEM_MENU(MenuInfo) \
(0 == ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))
@@ -42,27 +53,25 @@ LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
#define IS_SYSTEM_POPUP(MenuInfo) \
(0 != ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU))
-#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
+#define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags))
+
+/* Use global popup window because there's no way 2 menus can
+ * be tracked at the same time. */
+static HWND top_popup;
+
+/* Flag set by EndMenu() to force an exit from menu tracking */
+static BOOL fEndMenu = FALSE;
#define MENU_ITEM_HBMP_SPACE (5)
#define MENU_BAR_ITEMS_SPACE (12)
#define SEPARATOR_HEIGHT (5)
#define MENU_TAB_SPACE (8)
-#define ITEM_PREV -1
-#define ITEM_NEXT 1
-
#define MAKEINTATOMA(atom) ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
#define MAKEINTATOMW(atom) ((LPCWSTR)((ULONG_PTR)((WORD)(atom))))
#define POPUPMENU_CLASS_ATOMA MAKEINTATOMA(32768) /* PopupMenu */
#define POPUPMENU_CLASS_ATOMW MAKEINTATOMW(32768) /* PopupMenu */
-/* internal flags for menu tracking */
-
-#define TF_ENDMENU 0x0001
-#define TF_SUSPENDPOPUP 0x0002
-#define TF_SKIPREMOVE 0x0004
-
typedef struct
{
UINT TrackFlags;
@@ -72,8 +81,6 @@ typedef struct
POINT Pt;
} MTRACKER;
-//static LRESULT WINAPI PopupMenuWndProcA(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
-//static LRESULT WINAPI PopupMenuWndProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
/*********************************************************************
* PopupMenu class descriptor
@@ -89,14 +96,6 @@ const struct builtin_class_descr POPUPMENU_builtin_class =
(HBRUSH)(COLOR_MENU + 1) /* brush */
};
-
-/* INTERNAL FUNCTIONS ********************************************************/
-
-/* Rip the fun and easy to use and fun WINE unicode string manipulation routines.
- * Of course I didnt copy the ASM code because we want this to be portable
- * and it needs to go away.
- */
-
#ifndef GET_WORD
#define GET_WORD(ptr) (*(WORD *)(ptr))
#endif
@@ -107,13 +106,6 @@ const struct builtin_class_descr POPUPMENU_builtin_class =
HFONT hMenuFont = NULL;
HFONT hMenuFontBold = NULL;
-/* Flag set by EndMenu() to force an exit from menu tracking */
-static BOOL fEndMenu = FALSE;
-
-/* Use global popup window because there's no way 2 menus can
- * be tracked at the same time. */
-static HWND TopPopup;
-
/* Dimension of the menu bitmaps */
static HBITMAP BmpSysMenu = NULL;
@@ -276,6 +268,157 @@ MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
HeapFree(GetProcessHeap(), 0, ItemInfo);
}
+/***********************************************************************
+ * MenuInitSysMenuPopup
+ *
+ * Grey the appropriate items in System menu.
+ */
+void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LONG HitTest )
+{
+ BOOL gray;
+ UINT DefItem;
+ #if 0
+ MENUITEMINFOW mii;
+ #endif
+
+ gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
+ EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = ((style & WS_MAXIMIZE) != 0);
+ EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
+ EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
+ EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
+ EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
+ gray = (clsStyle & CS_NOCLOSE) != 0;
+
+ /* The menu item must keep its state if it's disabled */
+ if(gray)
+ EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
+
+ /* Set default menu item */
+ if(style & WS_MINIMIZE) DefItem = SC_RESTORE;
+ else if(HitTest == HTCAPTION) DefItem = ((style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE);
+ else DefItem = SC_CLOSE;
+#if 0
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask |= MIIM_STATE;
+ if((DefItem != SC_CLOSE) && GetMenuItemInfoW(hmenu, DefItem, FALSE, &mii) &&
+ (mii.fState & (MFS_GRAYED | MFS_DISABLED))) DefItem = SC_CLOSE;
+#endif
+ SetMenuDefaultItem(hmenu, DefItem, MF_BYCOMMAND);
+}
+
+/******************************************************************************
+ *
+ * UINT MenuGetStartOfNextColumn(
+ * PROSMENUINFO MenuInfo)
+ *
+ *****************************************************************************/
+static UINT MenuGetStartOfNextColumn(
+ PROSMENUINFO MenuInfo)
+{
+ PROSMENUITEMINFO MenuItems;
+ UINT i;
+
+ i = MenuInfo->FocusedItem;
+ if ( i == NO_SELECTED_ITEM )
+ return i;
+
+ if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
+ return NO_SELECTED_ITEM;
+
+ for (i++ ; i < MenuInfo->MenuItemCount; i++)
+ if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
+ return i;
+
+ return NO_SELECTED_ITEM;
+}
+
+/******************************************************************************
+ *
+ * UINT MenuGetStartOfPrevColumn(
+ * PROSMENUINFO MenuInfo)
+ *
+ *****************************************************************************/
+
+static UINT FASTCALL MenuGetStartOfPrevColumn(
+ PROSMENUINFO MenuInfo)
+{
+ PROSMENUITEMINFO MenuItems;
+ UINT i;
+
+ if (!MenuInfo->FocusedItem || MenuInfo->FocusedItem == NO_SELECTED_ITEM)
+ return NO_SELECTED_ITEM;
+
+ if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
+ return NO_SELECTED_ITEM;
+
+ /* Find the start of the column */
+ for (i = MenuInfo->FocusedItem;
+ 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+ --i)
+ {
+ ; /* empty */
+ }
+
+ if (i == 0)
+ {
+ MenuCleanupAllRosMenuItemInfo(MenuItems);
+ return NO_SELECTED_ITEM;
+ }
+
+ for (--i; 0 != i; --i)
+ if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+ break;
+
+ MenuCleanupAllRosMenuItemInfo(MenuItems);
+ TRACE("ret %d.\n", i );
+
+ return i;
+}
+
+/***********************************************************************
+ * MenuFindSubMenu
+ *
+ * Find a Sub menu. Return the position of the submenu, and modifies
+ * *hmenu in case it is found in another sub-menu.
+ * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
+ */
+static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget )
+{
+ ROSMENUINFO menu;
+ UINT i;
+ ROSMENUITEMINFO item;
+ if (((*hmenu)==(HMENU)0xffff) ||
+ (!MenuGetRosMenuInfo(&menu, *hmenu)))
+ return NO_SELECTED_ITEM;
+
+ MenuInitRosMenuItemInfo(&item);
+ for (i = 0; i < menu.MenuItemCount; i++) {
+ if (! MenuGetRosMenuItemInfo(menu.Self, i, &item))
+ {
+ MenuCleanupRosMenuItemInfo(&item);
+ return NO_SELECTED_ITEM;
+ }
+ if (!(item.fType & MF_POPUP)) continue;
+ if (item.hSubMenu == hSubTarget) {
+ MenuCleanupRosMenuItemInfo(&item);
+ return i;
+ }
+ else {
+ HMENU hsubmenu = item.hSubMenu;
+ UINT pos = MenuFindSubMenu(&hsubmenu, hSubTarget );
+ if (pos != NO_SELECTED_ITEM) {
+ *hmenu = hsubmenu;
+ return pos;
+ }
+ }
+ }
+ MenuCleanupRosMenuItemInfo(&item);
+ return NO_SELECTED_ITEM;
+}
/***********************************************************************
* MenuLoadBitmaps
@@ -293,71 +436,6 @@ MenuLoadBitmaps(VOID)
}
}
-/***********************************************************************
- * MenuGetBitmapItemSize
- *
- * Get the size of a bitmap item.
- */
-static void FASTCALL
-MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *Size, HWND WndOwner)
-{
- BITMAP Bm;
- HBITMAP Bmp = lpitem->hbmpItem;
-
- Size->cx = Size->cy = 0;
-
- /* check if there is a magic menu item associated with this item */
- if (IS_MAGIC_BITMAP(Bmp))
- {
- switch((INT_PTR) Bmp)
- {
- case (INT_PTR)HBMMENU_CALLBACK:
- {
- MEASUREITEMSTRUCT measItem;
- measItem.CtlType = ODT_MENU;
- measItem.CtlID = 0;
- measItem.itemID = lpitem->wID;
- measItem.itemWidth = lpitem->Rect.right - lpitem->Rect.left;
- measItem.itemHeight = lpitem->Rect.bottom - lpitem->Rect.top;
- measItem.itemData = lpitem->dwItemData;
- SendMessageW( WndOwner, WM_MEASUREITEM, lpitem->wID, (LPARAM)&measItem);
- Size->cx = measItem.itemWidth;
- Size->cy = measItem.itemHeight;
- return;
- }
- break;
-
- case (INT_PTR) HBMMENU_SYSTEM:
- if (0 != lpitem->dwItemData)
- {
- Bmp = (HBITMAP) lpitem->dwItemData;
- break;
- }
- /* fall through */
- case (INT_PTR) HBMMENU_MBAR_RESTORE:
- case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
- case (INT_PTR) HBMMENU_MBAR_CLOSE:
- case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
- case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
- case (INT_PTR) HBMMENU_POPUP_CLOSE:
- case (INT_PTR) HBMMENU_POPUP_RESTORE:
- case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
- case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
- /* FIXME: Why we need to subtract these magic values? */
- /* to make them smaller than the menu bar? */
- Size->cx = GetSystemMetrics(SM_CXSIZE) - 2;
- Size->cy = GetSystemMetrics(SM_CYSIZE) - 4;
- return;
- }
- }
-
- if (GetObjectW(Bmp, sizeof(BITMAP), &Bm))
- {
- Size->cx = Bm.bmWidth;
- Size->cy = Bm.bmHeight;
- }
-}
-
/***********************************************************************
* MenuDrawPopupGlyph
*
@@ -422,96 +500,225 @@ MenuDrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hil
DeleteObject(hFont);
}
+/***********************************************************************
+ * MenuFindItemByKey
+ *
+ * Find the menu item selected by a key press.
+ * Return item id, -1 if none, -2 if we should close the menu.
+ */
+static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
+ WCHAR Key, BOOL ForceMenuChar)
+{
+ ROSMENUINFO SysMenuInfo;
+ PROSMENUITEMINFO Items, ItemInfo;
+ LRESULT MenuChar;
+ UINT i;
+
+ TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
+
+ if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self))
+ {
+ if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE)))
+ {
+ MenuInfo = &SysMenuInfo;
+ }
+ else
+ {
+ MenuInfo = NULL;
+ }
+ }
+
+ if (NULL != MenuInfo)
+ {
+ if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0)
+ {
+ return -1;
+ }
+ if (! ForceMenuChar)
+ {
+ Key = toupperW(Key);
+ ItemInfo = Items;
+ for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++)
+ {
+ if ((ItemInfo->Text) && NULL != ItemInfo->dwTypeData)
+ {
+ WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
+ do
+ {
+ p = strchrW(p + 2, '&');
+ }
+ while (NULL != p && L'&' == p[1]);
+ if (NULL != p && (toupperW(p[1]) == Key))
+ {
+ return i;
+ }
+ }
+ }
+ }
+
+ MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
+ MAKEWPARAM(Key, MenuInfo->Flags), (LPARAM) MenuInfo->Self);
+ if (2 == HIWORD(MenuChar))
+ {
+ return LOWORD(MenuChar);
+ }
+ if (1 == HIWORD(MenuChar))
+ {
+ return (UINT) (-2);
+ }
+ }
+
+ return (UINT)(-1);
+}
+
+/***********************************************************************
+ * MenuGetBitmapItemSize
+ *
+ * Get the size of a bitmap item.
+ */
+static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size,
+ HWND WndOwner)
+{
+ BITMAP bm;
+ HBITMAP bmp = lpitem->hbmpItem;
+
+ size->cx = size->cy = 0;
+
+ /* check if there is a magic menu item associated with this item */
+ if (IS_MAGIC_BITMAP(bmp))
+ {
+ switch((INT_PTR) bmp)
+ {
+ case (INT_PTR)HBMMENU_CALLBACK:
+ {
+ MEASUREITEMSTRUCT measItem;
+ measItem.CtlType = ODT_MENU;
+ measItem.CtlID = 0;
+ measItem.itemID = lpitem->wID;
+ measItem.itemWidth = lpitem->Rect.right - lpitem->Rect.left;
+ measItem.itemHeight = lpitem->Rect.bottom - lpitem->Rect.top;
+ measItem.itemData = lpitem->dwItemData;
+ SendMessageW( WndOwner, WM_MEASUREITEM, lpitem->wID, (LPARAM)&measItem);
+ size->cx = measItem.itemWidth;
+ size->cy = measItem.itemHeight;
+ return;
+ }
+ break;
+
+ case (INT_PTR) HBMMENU_SYSTEM:
+ if (0 != lpitem->dwItemData)
+ {
+ bmp = (HBITMAP) lpitem->dwItemData;
+ break;
+ }
+ /* fall through */
+ case (INT_PTR) HBMMENU_MBAR_RESTORE:
+ case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
+ case (INT_PTR) HBMMENU_MBAR_CLOSE:
+ case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
+ case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
+ case (INT_PTR) HBMMENU_POPUP_CLOSE:
+ case (INT_PTR) HBMMENU_POPUP_RESTORE:
+ case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
+ case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
+ /* FIXME: Why we need to subtract these magic values? */
+ /* to make them smaller than the menu bar? */
+ size->cx = GetSystemMetrics(SM_CXSIZE) - 2;
+ size->cy = GetSystemMetrics(SM_CYSIZE) - 4;
+ return;
+ }
+ }
+
+ if (GetObjectW(bmp, sizeof(BITMAP), &bm))
+ {
+ size->cx = bm.bmWidth;
+ size->cy = bm.bmHeight;
+ }
+}
+
/***********************************************************************
* MenuDrawBitmapItem
*
* Draw a bitmap item.
*/
-static void FASTCALL
-MenuDrawBitmapItem(HDC Dc, PROSMENUITEMINFO Item, const RECT *Rect,
+static void FASTCALL MenuDrawBitmapItem(HDC hdc, PROSMENUITEMINFO lpitem, const RECT *rect,
HMENU hmenu, HWND WndOwner, UINT odaction, BOOL MenuBar)
{
- BITMAP Bm;
- DWORD Rop;
- HDC DcMem;
- HBITMAP Bmp;
- int w = Rect->right - Rect->left;
- int h = Rect->bottom - Rect->top;
- int BmpXoffset = 0;
- int Left, Top;
- HBITMAP hbmpToDraw = (HBITMAP) Item->hbmpItem;
- Bmp = hbmpToDraw;
+ BITMAP bm;
+ DWORD rop;
+ HDC hdcMem;
+ HBITMAP bmp;
+ int w = rect->right - rect->left;
+ int h = rect->bottom - rect->top;
+ int bmp_xoffset = 0;
+ int left, top;
+ HBITMAP hbmToDraw = lpitem->hbmpItem;
+ bmp = hbmToDraw;
- /* Check if there is a magic menu item associated with this item */
- if (IS_MAGIC_BITMAP(hbmpToDraw))
+ /* Check if there is a magic menu item associated with this item */
+ if (IS_MAGIC_BITMAP(hbmToDraw))
{
- UINT Flags = 0;
- RECT r;
+ UINT flags = 0;
+ RECT r;
- r = *Rect;
- switch ((INT_PTR)hbmpToDraw)
+ r = *rect;
+ switch ((INT_PTR)hbmToDraw)
{
- case (INT_PTR) HBMMENU_SYSTEM:
- if (NULL != Item->dwTypeData)
- {
- Bmp = (HBITMAP)Item->dwTypeData;
- if (! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
- {
- return;
- }
- }
+ case (INT_PTR)HBMMENU_SYSTEM:
+ if (lpitem->dwTypeData)
+ {
+ bmp = (HBITMAP)lpitem->dwTypeData;
+ if (!GetObjectW( bmp, sizeof(bm), &bm )) return;
+ }
else
- {
+ {
if (!BmpSysMenu) BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
- Bmp = BmpSysMenu;
- if (! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
- {
- return;
- }
+ bmp = BmpSysMenu;
+ if (! GetObjectW(bmp, sizeof(bm), &bm)) return;
/* only use right half of the bitmap */
- BmpXoffset = Bm.bmWidth / 2;
- Bm.bmWidth -= BmpXoffset;
- }
+ bmp_xoffset = bm.bmWidth / 2;
+ bm.bmWidth -= bmp_xoffset;
+ }
goto got_bitmap;
- case (INT_PTR) HBMMENU_MBAR_RESTORE:
- Flags = DFCS_CAPTIONRESTORE;
+ case (INT_PTR)HBMMENU_MBAR_RESTORE:
+ flags = DFCS_CAPTIONRESTORE;
break;
- case (INT_PTR) HBMMENU_MBAR_MINIMIZE:
+ case (INT_PTR)HBMMENU_MBAR_MINIMIZE:
r.right += 1;
- Flags = DFCS_CAPTIONMIN;
+ flags = DFCS_CAPTIONMIN;
break;
- case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D:
+ case (INT_PTR)HBMMENU_MBAR_MINIMIZE_D:
r.right += 1;
- Flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
+ flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
break;
- case (INT_PTR) HBMMENU_MBAR_CLOSE:
- Flags = DFCS_CAPTIONCLOSE;
+ case (INT_PTR)HBMMENU_MBAR_CLOSE:
+ flags = DFCS_CAPTIONCLOSE;
break;
- case (INT_PTR) HBMMENU_MBAR_CLOSE_D:
- Flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
+ case (INT_PTR)HBMMENU_MBAR_CLOSE_D:
+ flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
break;
- case (INT_PTR) HBMMENU_CALLBACK:
+ case (INT_PTR)HBMMENU_CALLBACK:
{
DRAWITEMSTRUCT drawItem;
POINT origorg;
drawItem.CtlType = ODT_MENU;
drawItem.CtlID = 0;
- drawItem.itemID = Item->wID;
+ drawItem.itemID = lpitem->wID;
drawItem.itemAction = odaction;
- drawItem.itemState = (Item->fState & MF_CHECKED)?ODS_CHECKED:0;
- drawItem.itemState |= (Item->fState & MF_DEFAULT)?ODS_DEFAULT:0;
- drawItem.itemState |= (Item->fState & MF_DISABLED)?ODS_DISABLED:0;
- drawItem.itemState |= (Item->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
- drawItem.itemState |= (Item->fState & MF_HILITE)?ODS_SELECTED:0;
+ drawItem.itemState = (lpitem->fState & MF_CHECKED)?ODS_CHECKED:0;
+ drawItem.itemState |= (lpitem->fState & MF_DEFAULT)?ODS_DEFAULT:0;
+ drawItem.itemState |= (lpitem->fState & MF_DISABLED)?ODS_DISABLED:0;
+ drawItem.itemState |= (lpitem->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0;
+ drawItem.itemState |= (lpitem->fState & MF_HILITE)?ODS_SELECTED:0;
drawItem.hwndItem = (HWND)hmenu;
- drawItem.hDC = Dc;
- drawItem.rcItem = *Rect;
- drawItem.itemData = Item->dwItemData;
+ drawItem.hDC = hdc;
+ drawItem.rcItem = *rect;
+ drawItem.itemData = lpitem->dwItemData;
/* some applications make this assumption on the DC's origin */
- SetViewportOrgEx( Dc, Item->Rect.left, Item->Rect.top, &origorg);
- OffsetRect( &drawItem.rcItem, - Item->Rect.left, - Item->Rect.top);
+ SetViewportOrgEx( hdc, lpitem->Rect.left, lpitem->Rect.top, &origorg);
+ OffsetRect( &drawItem.rcItem, - lpitem->Rect.left, - lpitem->Rect.top);
SendMessageW( WndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem);
- SetViewportOrgEx( Dc, origorg.x, origorg.y, NULL);
+ SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL);
return;
}
break;
@@ -520,37 +727,413 @@ MenuDrawBitmapItem(HDC Dc, PROSMENUITEMINFO Item, const RECT *Rect,
case (INT_PTR) HBMMENU_POPUP_RESTORE:
case (INT_PTR) HBMMENU_POPUP_MAXIMIZE:
case (INT_PTR) HBMMENU_POPUP_MINIMIZE:
- MenuDrawPopupGlyph(Dc, &r, (INT_PTR)hbmpToDraw, Item->fState & MF_GRAYED, Item->fState & MF_HILITE);
+ MenuDrawPopupGlyph(hdc, &r, (INT_PTR)hbmToDraw, lpitem->fState & MF_GRAYED, lpitem->fState & MF_HILITE);
return;
}
InflateRect(&r, -1, -1);
- if (0 != (Item->fState & MF_HILITE))
- {
- Flags |= DFCS_PUSHED;
+ if (0 != (lpitem->fState & MF_HILITE))
+ {
+ flags |= DFCS_PUSHED;
+ }
+ DrawFrameControl(hdc, &r, DFC_CAPTION, flags);
+ return;
+ }
+
+ if (!bmp || !GetObjectW( bmp, sizeof(bm), &bm )) return;
+
+ got_bitmap:
+ hdcMem = CreateCompatibleDC( hdc );
+ SelectObject( hdcMem, bmp );
+
+ /* handle fontsize > bitmap_height */
+ top = (h>bm.bmHeight) ? rect->top+(h-bm.bmHeight)/2 : rect->top;
+ left=rect->left;
+ rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_BITMAP(hbmToDraw)) ? NOTSRCCOPY : SRCCOPY;
+ if ((lpitem->fState & MF_HILITE) && lpitem->hbmpItem)
+ SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
+ BitBlt( hdc, left, top, w, h, hdcMem, bmp_xoffset, 0, rop );
+ DeleteDC( hdcMem );
+}
+
+/***********************************************************************
+ * MenuCalcItemSize
+ *
+ * Calculate the size of the menu item and store it in lpitem->rect.
+ */
+static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMENUINFO MenuInfo, HWND hwndOwner,
+ INT orgX, INT orgY, BOOL menuBar)
+{
+ WCHAR *p;
+ UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
+ INT itemheight = 0;
+
+ TRACE("dc=%x owner=%x (%d,%d)\n", hdc, hwndOwner, orgX, orgY);
+
+ MenuCharSize.cx = GdiGetCharDimensions( hdc, NULL, &MenuCharSize.cy );
+
+ SetRect( &lpitem->Rect, orgX, orgY, orgX, orgY );
+
+ if (lpitem->fType & MF_OWNERDRAW)
+ {
+ MEASUREITEMSTRUCT mis;
+ mis.CtlType = ODT_MENU;
+ mis.CtlID = 0;
+ mis.itemID = lpitem->wID;
+ mis.itemData = lpitem->dwItemData;
+ mis.itemHeight = HIWORD( GetDialogBaseUnits());
+ mis.itemWidth = 0;
+ SendMessageW( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
+ /* Tests reveal that Windows ( Win95 thru WinXP) adds twice the average
+ * width of a menufont character to the width of an owner-drawn menu.
+ */
+ lpitem->Rect.right += mis.itemWidth + 2 * MenuCharSize.cx;
+
+ if (menuBar) {
+ /* under at least win95 you seem to be given a standard
+ height for the menu and the height value is ignored */
+ lpitem->Rect.bottom += GetSystemMetrics(SM_CYMENUSIZE);
+ } else
+ lpitem->Rect.bottom += mis.itemHeight;
+
+ TRACE("id=%04lx size=%dx%d\n",
+ lpitem->wID, mis.itemWidth, mis.itemHeight);
+ return;
+ }
+
+ if (lpitem->fType & MF_SEPARATOR)
+ {
+ lpitem->Rect.bottom += SEPARATOR_HEIGHT;
+ if( !menuBar)
+ lpitem->Rect.right += check_bitmap_width + MenuCharSize.cx;
+ return;
+ }
+
+ lpitem->XTab = 0;
+
+ if (lpitem->hbmpItem)
+ {
+ SIZE size;
+
+ if (!menuBar) {
+ MenuGetBitmapItemSize(lpitem, &size, hwndOwner );
+ /* Keep the size of the bitmap in callback mode to be able
+ * to draw it correctly */
+ lpitem->Rect.right = lpitem->Rect.left + size.cx;
+ if (MenuInfo->maxBmpSize.cx < abs(size.cx) + MENU_ITEM_HBMP_SPACE ||
+ MenuInfo->maxBmpSize.cy < abs(size.cy))
+ {
+ MenuInfo->maxBmpSize.cx = abs(size.cx) + MENU_ITEM_HBMP_SPACE;
+ MenuInfo->maxBmpSize.cy = abs(size.cy);
+ }
+ MenuSetRosMenuInfo(MenuInfo);
+ itemheight = size.cy + 2;
+
+ if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+ lpitem->Rect.right += 2 * check_bitmap_width;
+ lpitem->Rect.right += 4 + MenuCharSize.cx;
+ lpitem->XTab = lpitem->Rect.right;
+ lpitem->Rect.right += check_bitmap_width;
+ } else /* hbmpItem & MenuBar */ {
+ MenuGetBitmapItemSize(lpitem, &size, hwndOwner );
+ lpitem->Rect.right += size.cx;
+ if( lpitem->Text) lpitem->Rect.right += 2;
+ itemheight = size.cy;
+
+ /* Special case: Minimize button doesn't have a space behind it. */
+ if (lpitem->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE ||
+ lpitem->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D)
+ lpitem->Rect.right -= 1;
}
- DrawFrameControl(Dc, &r, DFC_CAPTION, Flags);
- return;
+ }
+ else if (!menuBar) {
+ if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+ lpitem->Rect.right += check_bitmap_width;
+ lpitem->Rect.right += 4 + MenuCharSize.cx;
+ lpitem->XTab = lpitem->Rect.right;
+ lpitem->Rect.right += check_bitmap_width;
}
- if (NULL == Bmp || ! GetObjectW(Bmp, sizeof(BITMAP), &Bm))
+ /* it must be a text item - unless it's the system menu */
+ if (!(lpitem->fType & MF_SYSMENU) && lpitem->Text) {
+ HFONT hfontOld = NULL;
+ RECT rc = lpitem->Rect;
+ LONG txtheight, txtwidth;
+
+ if ( lpitem->fState & MFS_DEFAULT ) {
+ hfontOld = SelectObject( hdc, hMenuFontBold );
+ }
+ if (menuBar) {
+ txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ lpitem->Rect.right += rc.right - rc.left;
+ itemheight = max( max( itemheight, txtheight),
+ GetSystemMetrics( SM_CYMENU) - 1);
+ lpitem->Rect.right += 2 * MenuCharSize.cx;
+ } else {
+ if ((p = strchrW( lpitem->dwTypeData, '\t' )) != NULL) {
+ RECT tmprc = rc;
+ LONG tmpheight;
+ int n = (int)( p - lpitem->dwTypeData);
+ /* Item contains a tab (only meaningful in popup menus) */
+ /* get text size before the tab */
+ txtheight = DrawTextW( hdc, lpitem->dwTypeData, n, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ txtwidth = rc.right - rc.left;
+ p += 1; /* advance past the Tab */
+ /* get text size after the tab */
+ tmpheight = DrawTextW( hdc, p, -1, &tmprc,
+ DT_SINGLELINE|DT_CALCRECT);
+ lpitem->XTab += txtwidth;
+ txtheight = max( txtheight, tmpheight);
+ txtwidth += MenuCharSize.cx + /* space for the tab */
+ tmprc.right - tmprc.left; /* space for the short cut */
+ } else {
+ txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc,
+ DT_SINGLELINE|DT_CALCRECT);
+ txtwidth = rc.right - rc.left;
+ lpitem->XTab += txtwidth;
+ }
+ lpitem->Rect.right += 2 + txtwidth;
+ itemheight = max( itemheight,
+ max( txtheight + 2, MenuCharSize.cy + 4));
+ }
+ if (hfontOld) SelectObject (hdc, hfontOld);
+ } else if( menuBar) {
+ itemheight = max( itemheight, GetSystemMetrics(SM_CYMENU)-1);
+ }
+ lpitem->Rect.bottom += itemheight;
+ TRACE("(%ld,%ld)-(%ld,%ld)\n", lpitem->Rect.left, lpitem->Rect.top, lpitem->Rect.right, lpitem->Rect.bottom);
+}
+
+/***********************************************************************
+ * MenuPopupMenuCalcSize
+ *
+ * Calculate the size of a popup menu.
+ */
+static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner)
+{
+ ROSMENUITEMINFO lpitem;
+ HDC hdc;
+ int start, i;
+ int orgX, orgY, maxX, maxTab, maxTabWidth;
+
+ MenuInfo->Width = MenuInfo->Height = 0;
+ if (MenuInfo->MenuItemCount == 0)
{
- return;
+ MenuSetRosMenuInfo(MenuInfo);
+ return;
}
-got_bitmap:
- DcMem = CreateCompatibleDC(Dc);
- SelectObject(DcMem, Bmp);
+ hdc = GetDC(NULL);
+ SelectObject( hdc, hMenuFont );
- /* handle fontsize > bitmap_height */
- Top = (Bm.bmHeight < h) ? Rect->top + (h - Bm.bmHeight) / 2 : Rect->top;
- Left = Rect->left;
- Rop= ((Item->fState & MF_HILITE) && !IS_MAGIC_BITMAP(hbmpToDraw)) ? NOTSRCCOPY : SRCCOPY;
- if ((Item->fState & MF_HILITE) && Item->hbmpItem)
+ start = 0;
+ maxX = 2 + 1;
+
+ MenuInfo->maxBmpSize.cx = 0;
+ MenuInfo->maxBmpSize.cy = 0;
+
+ MenuInitRosMenuItemInfo(&lpitem);
+ while (start < MenuInfo->MenuItemCount)
{
- SetBkColor(Dc, GetSysColor(COLOR_HIGHLIGHT));
+ orgX = maxX;
+ orgY = 2;
+
+ maxTab = maxTabWidth = 0;
+
+ /* Parse items until column break or end of menu */
+ for (i = start; i < MenuInfo->MenuItemCount; i++)
+ {
+ if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i, &lpitem))
+ {
+ MenuCleanupRosMenuItemInfo(&lpitem);
+ MenuSetRosMenuInfo(MenuInfo);
+ return;
+ }
+ if (i != start &&
+ (lpitem.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
+
+ MenuCalcItemSize(hdc, &lpitem, MenuInfo, WndOwner, orgX, orgY, FALSE);
+ if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &lpitem))
+ {
+ MenuCleanupRosMenuItemInfo(&lpitem);
+ MenuSetRosMenuInfo(MenuInfo);
+ return;
+ }
+// Not sure here,, The patch from wine removes this.
+// if ((lpitem.fType & MF_MENUBARBREAK) != 0)
+// {
+// OrgX++;
+// }
+ maxX = max(maxX, lpitem.Rect.right);
+ orgY = lpitem.Rect.bottom;
+ if ((lpitem.Text) && lpitem.XTab )
+ {
+ maxTab = max( maxTab, lpitem.XTab );
+ maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.XTab);
+ }
+ }
+
+ /* Finish the column (set all items to the largest width found) */
+ maxX = max( maxX, maxTab + maxTabWidth );
+ while (start < i)
+ {
+ if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &lpitem))
+ {
+ lpitem.Rect.right = maxX;
+ if ((lpitem.Text) && 0 != lpitem.XTab)
+ {
+ lpitem.XTab = maxTab;
+ }
+ MenuSetRosMenuItemInfo(MenuInfo->Self, start, &lpitem);
+ }
+ start++;
+ }
+ MenuInfo->Height = max(MenuInfo->Height, orgY);
}
- BitBlt(Dc, Left, Top, w, h, DcMem, BmpXoffset, 0, Rop);
- DeleteDC(DcMem);
+
+ MenuInfo->Width = maxX;
+
+ /* space for 3d border */
+ MenuInfo->Height += 2;
+ MenuInfo->Width += 2;
+
+ MenuCleanupRosMenuItemInfo(&lpitem);
+ MenuSetRosMenuInfo(MenuInfo);
+ ReleaseDC( 0, hdc );
+}
+
+/***********************************************************************
+ * MenuMenuBarCalcSize
+ *
+ * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
+ * height is off by 1 pixel which causes lengthy window relocations when
+ * active document window is maximized/restored.
+ *
+ * Calculate the size of the menu bar.
+ */
+static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect,
+ PROSMENUINFO MenuInfo, HWND hwndOwner )
+{
+ ROSMENUITEMINFO ItemInfo;
+ int start, i, orgX, orgY, maxY, helpPos;
+
+ if ((lprect == NULL) || (MenuInfo == NULL)) return;
+ if (MenuInfo->MenuItemCount == 0) return;
+ TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom);
+ MenuInfo->Width = lprect->right - lprect->left;
+ MenuInfo->Height = 0;
+ maxY = lprect->top + 1;
+ start = 0;
+ helpPos = -1;
+
+ MenuInfo->maxBmpSize.cx = 0;
+ MenuInfo->maxBmpSize.cy = 0;
+
+ MenuInitRosMenuItemInfo(&ItemInfo);
+ while (start < MenuInfo->MenuItemCount)
+ {
+ if (! MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ orgX = lprect->left;
+ orgY = maxY;
+
+ /* Parse items until line break or end of menu */
+ for (i = start; i < MenuInfo->MenuItemCount; i++)
+ {
+ if ((helpPos == -1) && (ItemInfo.fType & MF_RIGHTJUSTIFY)) helpPos = i;
+ if ((i != start) &&
+ (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
+
+ TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY);
+ MenuCalcItemSize(hdc, &ItemInfo, MenuInfo, hwndOwner, orgX, orgY, TRUE);
+ if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+
+ if (ItemInfo.Rect.right > lprect->right)
+ {
+ if (i != start) break;
+ else ItemInfo.Rect.right = lprect->right;
+ }
+ maxY = max( maxY, ItemInfo.Rect.bottom );
+ orgX = ItemInfo.Rect.right;
+ if (i + 1 < MenuInfo->MenuItemCount)
+ {
+ if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i + 1, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ }
+ }
+
+/* FIXME: Is this really needed? */ /*NO! it is not needed, why make the
+HBMMENU_MBAR_CLOSE, MINIMIZE & RESTORE, look the same size as the menu bar! */
+#if 0
+ /* Finish the line (set all items to the largest height found) */
+ while (start < i)
+ {
+ if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo))
+ {
+ ItemInfo.Rect.bottom = maxY;
+ MenuSetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo);
+ }
+ start++;
+ }
+#else
+ start = i; /* This works! */
+#endif
+ }
+
+ lprect->bottom = maxY;
+ MenuInfo->Height = lprect->bottom - lprect->top;
+ MenuSetRosMenuInfo(MenuInfo);
+
+ if (helpPos != -1)
+ {
+ /* Flush right all items between the MF_RIGHTJUSTIFY and */
+ /* the last item (if several lines, only move the last line) */
+ if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->MenuItemCount - 1, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ orgY = ItemInfo.Rect.top;
+ orgX = lprect->right;
+ for (i = MenuInfo->MenuItemCount - 1; helpPos <= i; i--)
+ {
+ if (i < helpPos)
+ {
+ break; /* done */
+ }
+ if (ItemInfo.Rect.top != orgY)
+ {
+ break; /* Other line */
+ }
+ if (orgX <= ItemInfo.Rect.right)
+ {
+ break; /* Too far right already */
+ }
+ ItemInfo.Rect.left += orgX - ItemInfo.Rect.right;
+ ItemInfo.Rect.right = orgX;
+ orgX = ItemInfo.Rect.left;
+ MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo);
+ if (helpPos + 1 <= i &&
+ ! MenuGetRosMenuItemInfo(MenuInfo->Self, i - 1, &ItemInfo))
+ {
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ }
+ }
+
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
}
/***********************************************************************
@@ -558,358 +1141,322 @@ got_bitmap:
*
* Draw a single menu item.
*/
-static void FASTCALL
-MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC Dc,
- PROSMENUITEMINFO Item, UINT Height, BOOL MenuBar, UINT Action)
+static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC hdc,
+ PROSMENUITEMINFO lpitem, UINT Height, BOOL menuBar, UINT odaction)
{
- RECT Rect;
- PWCHAR Text;
- BOOL flat_menu = FALSE;
- int bkgnd;
- PWND Wnd = ValidateHwnd(hWnd);
+ RECT rect;
+ PWCHAR Text;
+ BOOL flat_menu = FALSE;
+ int bkgnd;
+ PWND Wnd = ValidateHwnd(hWnd);
- if (!Wnd)
+ if (!Wnd)
return;
- if (0 != (Item->fType & MF_SYSMENU))
+ if (lpitem->fType & MF_SYSMENU)
{
- if ( (Wnd->style & WS_MINIMIZE))
+ if ( (Wnd->style & WS_MINIMIZE))
{
- UserGetInsideRectNC(Wnd, &Rect);
- UserDrawSysMenuButton(hWnd, Dc, &Rect,
- Item->fState & (MF_HILITE | MF_MOUSESELECT));
- }
- return;
+ UserGetInsideRectNC(Wnd, &rect);
+ UserDrawSysMenuButton(hWnd, hdc, &rect,
+ lpitem->fState & (MF_HILITE | MF_MOUSESELECT));
+ }
+ return;
}
SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
- bkgnd = (MenuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
+ bkgnd = (menuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
+
+ /* Setup colors */
- /* Setup colors */
-
- if (0 != (Item->fState & MF_HILITE))
+ if (lpitem->fState & MF_HILITE)
{
- if (MenuBar && !flat_menu)
- {
- SetTextColor(Dc, GetSysColor(COLOR_MENUTEXT));
- SetBkColor(Dc, GetSysColor(COLOR_MENU));
+ if(menuBar && !flat_menu) {
+ SetTextColor(hdc, GetSysColor(COLOR_MENUTEXT));
+ SetBkColor(hdc, GetSysColor(COLOR_MENU));
+ } else {
+ if (lpitem->fState & MF_GRAYED)
+ SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
+ else
+ SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
}
- else
- {
- if (0 != (Item->fState & MF_GRAYED))
- {
- SetTextColor(Dc, GetSysColor(COLOR_GRAYTEXT));
- }
- else
- {
- SetTextColor(Dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
- }
- SetBkColor(Dc, GetSysColor(COLOR_HIGHLIGHT));
- }
- }
- else
- {
- if (0 != (Item->fState & MF_GRAYED))
- {
- SetTextColor(Dc, GetSysColor(COLOR_GRAYTEXT));
- }
- else
- {
- SetTextColor(Dc, GetSysColor(COLOR_MENUTEXT));
- }
- SetBkColor(Dc, GetSysColor(bkgnd));
- }
-
- Rect = Item->Rect;
-
- if (Item->fType & MF_OWNERDRAW)
- {
- /*
- ** Experimentation under Windows reveals that an owner-drawn
- ** menu is given the rectangle which includes the space it requested
- ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
- ** and a popup-menu arrow. This is the value of lpitem->rect.
- ** Windows will leave all drawing to the application except for
- ** the popup-menu arrow. Windows always draws that itself, after
- ** the menu owner has finished drawing.
- */
- DRAWITEMSTRUCT dis;
-
- dis.CtlType = ODT_MENU;
- dis.CtlID = 0;
- dis.itemID = Item->wID;
- dis.itemData = (DWORD)Item->dwItemData;
- dis.itemState = 0;
- if (0 != (Item->fState & MF_CHECKED))
- {
- dis.itemState |= ODS_CHECKED;
- }
- if (0 != (Item->fState & MF_GRAYED))
- {
- dis.itemState |= ODS_GRAYED | ODS_DISABLED;
- }
- if (0 != (Item->fState & MF_HILITE))
- {
- dis.itemState |= ODS_SELECTED;
- }
- dis.itemAction = Action; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
- dis.hwndItem = (HWND) MenuInfo->Self;
- dis.hDC = Dc;
- dis.rcItem = Rect;
- TRACE("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
- "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", hWnd,
- dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
- dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
- dis.rcItem.bottom);
- SendMessageW(WndOwner, WM_DRAWITEM, 0, (LPARAM) &dis);
- /* Draw the popup-menu arrow */
- if (0 != (Item->fType & MF_POPUP))
- {
- RECT rectTemp;
- CopyRect(&rectTemp, &Rect);
- rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
- DrawFrameControl(Dc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
- }
- return;
- }
-
- TRACE("rect={%ld,%ld,%ld,%ld}\n", Item->Rect.left, Item->Rect.top,
- Item->Rect.right, Item->Rect.bottom);
-
- if (MenuBar && 0 != (Item->fType & MF_SEPARATOR))
- {
- return;
- }
-
- if (Item->fState & MF_HILITE)
- {
- if (flat_menu)
- {
- InflateRect (&Rect, -1, -1);
- FillRect(Dc, &Rect, GetSysColorBrush(COLOR_MENUHILIGHT));
- InflateRect (&Rect, 1, 1);
- FrameRect(Dc, &Rect, GetSysColorBrush(COLOR_HIGHLIGHT));
}
else
{
- if (MenuBar)
- {
- DrawEdge(Dc, &Rect, BDR_SUNKENOUTER, BF_RECT);
- }
- else
- {
- FillRect(Dc, &Rect, GetSysColorBrush(COLOR_HIGHLIGHT));
- }
+ if (lpitem->fState & MF_GRAYED)
+ SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+ else
+ SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
+ SetBkColor( hdc, GetSysColor( bkgnd ) );
}
- }
- else
- {
- FillRect(Dc, &Rect, GetSysColorBrush(bkgnd));
- }
- SetBkMode(Dc, TRANSPARENT);
+ rect = lpitem->Rect;
- /* vertical separator */
- if (! MenuBar && 0 != (Item->fType & MF_MENUBARBREAK))
- {
- HPEN oldPen;
- RECT rc = Rect;
- rc.left -= 3;
- rc.top = 3;
- rc.bottom = Height - 3;
- if (flat_menu)
+ if (lpitem->fType & MF_OWNERDRAW)
{
- oldPen = SelectObject( Dc, GetStockObject(DC_PEN) );
- SetDCPenColor(Dc, GetSysColor(COLOR_BTNSHADOW));
- MoveToEx( Dc, rc.left, rc.top, NULL );
- LineTo( Dc, rc.left, rc.bottom );
- SelectObject( Dc, oldPen );
+ /*
+ ** Experimentation under Windows reveals that an owner-drawn
+ ** menu is given the rectangle which includes the space it requested
+ ** in its response to WM_MEASUREITEM _plus_ width for a checkmark
+ ** and a popup-menu arrow. This is the value of lpitem->rect.
+ ** Windows will leave all drawing to the application except for
+ ** the popup-menu arrow. Windows always draws that itself, after
+ ** the menu owner has finished drawing.
+ */
+ DRAWITEMSTRUCT dis;
+
+ dis.CtlType = ODT_MENU;
+ dis.CtlID = 0;
+ dis.itemID = lpitem->wID;
+ dis.itemData = (DWORD)lpitem->dwItemData;
+ dis.itemState = 0;
+ if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
+ if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED | ODS_DISABLED;
+ if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
+ dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
+ dis.hwndItem = (HWND) MenuInfo->Self;
+ dis.hDC = hdc;
+ dis.rcItem = rect;
+ TRACE("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
+ "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", hWnd,
+ dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
+ dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right,
+ dis.rcItem.bottom);
+ SendMessageW(WndOwner, WM_DRAWITEM, 0, (LPARAM) &dis);
+ /* Draw the popup-menu arrow */
+ if (lpitem->fType & MF_POPUP)
+ {
+ RECT rectTemp;
+ CopyRect(&rectTemp, &rect);
+ rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
+ DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
+ }
+ return;
+ }
+
+ if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
+
+ if (lpitem->fState & MF_HILITE)
+ {
+ if (flat_menu)
+ {
+ InflateRect (&rect, -1, -1);
+ FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENUHILIGHT));
+ InflateRect (&rect, 1, 1);
+ FrameRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
+ else
+ {
+ if(menuBar)
+ DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT);
+ else
+ FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
}
else
- DrawEdge(Dc, &rc, EDGE_ETCHED, BF_LEFT);
- }
+ FillRect( hdc, &rect, GetSysColorBrush(bkgnd) );
- /* horizontal separator */
- if (0 != (Item->fType & MF_SEPARATOR))
- {
- HPEN oldPen;
- RECT rc = Rect;
- rc.left++;
- rc.right--;
- rc.top += SEPARATOR_HEIGHT / 2;
- if (flat_menu)
+ SetBkMode( hdc, TRANSPARENT );
+
+ /* vertical separator */
+ if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
{
- oldPen = SelectObject( Dc, GetStockObject(DC_PEN) );
- SetDCPenColor(Dc, GetSysColor(COLOR_BTNSHADOW));
- MoveToEx( Dc, rc.left, rc.top, NULL );
- LineTo( Dc, rc.right, rc.top );
- SelectObject( Dc, oldPen );
+ HPEN oldPen;
+ RECT rc = rect;
+
+ rc.left -= 3;
+ rc.top = 3;
+ rc.bottom = Height - 3;
+ if (flat_menu)
+ {
+ oldPen = SelectObject( hdc, GetStockObject(DC_PEN) );
+ SetDCPenColor(hdc, GetSysColor(COLOR_BTNSHADOW));
+ MoveToEx( hdc, rc.left, rc.top, NULL );
+ LineTo( hdc, rc.left, rc.bottom );
+ SelectObject( hdc, oldPen );
+ }
+ else
+ DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
+ }
+
+ /* horizontal separator */
+ if (lpitem->fType & MF_SEPARATOR)
+ {
+ HPEN oldPen;
+ RECT rc = rect;
+
+ rc.left++;
+ rc.right--;
+ rc.top += SEPARATOR_HEIGHT / 2;
+ if (flat_menu)
+ {
+ oldPen = SelectObject( hdc, GetStockObject(DC_PEN) );
+ SetDCPenColor( hdc, GetSysColor(COLOR_BTNSHADOW));
+ MoveToEx( hdc, rc.left, rc.top, NULL );
+ LineTo( hdc, rc.right, rc.top );
+ SelectObject( hdc, oldPen );
+ }
+ else
+ DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
+ return;
}
- else
- DrawEdge(Dc, &rc, EDGE_ETCHED, BF_TOP);
- return;
- }
#if 0
- /* helper lines for debugging */
- /* This is a very good test tool when hacking menus! (JT) 07/16/2006 */
- FrameRect(Dc, &Rect, GetStockObject(BLACK_BRUSH));
- SelectObject(Dc, GetStockObject(DC_PEN));
- SetDCPenColor(Dc, GetSysColor(COLOR_WINDOWFRAME));
- MoveToEx(Dc, Rect.left, (Rect.top + Rect.bottom) / 2, NULL);
- LineTo(Dc, Rect.right, (Rect.top + Rect.bottom) / 2);
+ /* helper lines for debugging */
+ /* This is a very good test tool when hacking menus! (JT) 07/16/2006 */
+ FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
+ SelectObject(hdc, GetStockObject(DC_PEN));
+ SetDCPenColor(hdc, GetSysColor(COLOR_WINDOWFRAME));
+ MoveToEx(hdc, rect.left, (rect.top + rect.bottom) / 2, NULL);
+ LineTo(hdc, rect.right, (rect.top + rect.bottom) / 2);
#endif
- if (! MenuBar)
- {
- INT y = Rect.top + Rect.bottom;
- RECT Rc = Rect;
- UINT CheckBitmapWidth = GetSystemMetrics(SM_CXMENUCHECK);
- UINT CheckBitmapHeight = GetSystemMetrics(SM_CYMENUCHECK);
- int checked = FALSE;
- /* Draw the check mark
- *
- * FIXME:
- * Custom checkmark bitmaps are monochrome but not always 1bpp.
- */
- if( !(MenuInfo->dwStyle & MNS_NOCHECK))
- {
- HBITMAP bm = 0 != (Item->fState & MF_CHECKED) ? Item->hbmpChecked : Item->hbmpUnchecked;
- if (NULL != bm) /* we have a custom bitmap */
- {
- HDC DcMem = CreateCompatibleDC(Dc);
- SelectObject(DcMem, bm);
- BitBlt(Dc, Rc.left, (y - CheckBitmapHeight) / 2,
- CheckBitmapWidth, CheckBitmapHeight,
- DcMem, 0, 0, SRCCOPY);
- DeleteDC(DcMem);
- checked = TRUE;
- }
- else if (0 != (Item->fState & MF_CHECKED)) /* standard bitmaps */
- {
- RECT rectTemp;
- CopyRect(&rectTemp, &Rect);
- rectTemp.right = rectTemp.left + GetSystemMetrics(SM_CXMENUCHECK);
- DrawFrameControl(Dc, &rectTemp, DFC_MENU,
- 0 != (Item->fType & MFT_RADIOCHECK) ?
+ if (!menuBar)
+ {
+ HBITMAP bm;
+ INT y = rect.top + rect.bottom;
+ RECT rc = rect;
+ int checked = FALSE;
+ UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
+ UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
+ /* Draw the check mark
+ *
+ * FIXME:
+ * Custom checkmark bitmaps are monochrome but not always 1bpp.
+ */
+ if( !(MenuInfo->dwStyle & MNS_NOCHECK)) {
+ bm = (lpitem->fState & MF_CHECKED) ? lpitem->hbmpChecked :
+ lpitem->hbmpUnchecked;
+ if (bm) /* we have a custom bitmap */
+ {
+ HDC hdcMem = CreateCompatibleDC( hdc );
+
+ SelectObject( hdcMem, bm );
+ BitBlt( hdc, rc.left, (y - check_bitmap_height) / 2,
+ check_bitmap_width, check_bitmap_height,
+ hdcMem, 0, 0, SRCCOPY );
+ DeleteDC( hdcMem );
+ checked = TRUE;
+ }
+ else if (lpitem->fState & MF_CHECKED) /* standard bitmaps */
+ {
+ RECT r;
+ CopyRect(&r, &rect);
+ r.right = r.left + GetSystemMetrics(SM_CXMENUCHECK);
+ DrawFrameControl( hdc, &r, DFC_MENU,
+ (lpitem->fType & MFT_RADIOCHECK) ?
DFCS_MENUBULLET : DFCS_MENUCHECK);
- checked = TRUE;
- }
- }
- if (Item->hbmpItem)
- {
- RECT bmpRect;
- CopyRect(&bmpRect, &Rect);
- if (!(MenuInfo->dwStyle & MNS_CHECKORBMP) && !(MenuInfo->dwStyle & MNS_NOCHECK))
- bmpRect.left += CheckBitmapWidth + 2;
- if (!(checked && (MenuInfo->dwStyle & MNS_CHECKORBMP)))
- {
- bmpRect.right = bmpRect.left + MenuInfo->maxBmpSize.cx;
- MenuDrawBitmapItem(Dc, Item, &bmpRect, MenuInfo->Self, WndOwner, Action, MenuBar);
- }
- }
- /* Draw the popup-menu arrow */
- if (0 != (Item->fType & MF_POPUP))
- {
- RECT rectTemp;
- CopyRect(&rectTemp, &Rect);
- rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
- DrawFrameControl(Dc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
- }
- Rect.left += 4;
- if( !(MenuInfo->dwStyle & MNS_NOCHECK))
- Rect.left += CheckBitmapWidth;
- Rect.right -= CheckBitmapWidth;
- }
- else if (Item->hbmpItem) /* Draw the bitmap */
- {
- MenuDrawBitmapItem(Dc, Item, &Rect, MenuInfo->Self, WndOwner, Action, MenuBar);
- }
-
- /* No bitmap - process text if present */
- if (Item->Text)
- {
- register int i = 0;
- HFONT FontOld = NULL;
-
- UINT uFormat = MenuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE
- : DT_LEFT | DT_VCENTER | DT_SINGLELINE;
-
- if(MenuInfo->dwStyle & MNS_CHECKORBMP)
- Rect.left += max(0, MenuInfo->maxBmpSize.cx - GetSystemMetrics(SM_CXMENUCHECK));
- else
- Rect.left += MenuInfo->maxBmpSize.cx;
-
- if (0 != (Item->fState & MFS_DEFAULT))
- {
- FontOld = SelectObject(Dc, hMenuFontBold);
- }
-
- if (MenuBar)
- {
- Rect.left += MENU_BAR_ITEMS_SPACE / 2;
- Rect.right -= MENU_BAR_ITEMS_SPACE / 2;
- }
-
- Text = (PWCHAR) Item->dwTypeData;
- if(Text)
- {
- for (i = 0; L'\0' != Text[i]; i++)
- {
- if (L'\t' == Text[i] || L'\b' == Text[i])
- {
- break;
+ checked = TRUE;
}
}
- }
+ if ( lpitem->hbmpItem )
+ {
+ RECT bmpRect;
+ CopyRect(&bmpRect, &rect);
+ if (!(MenuInfo->dwStyle & MNS_CHECKORBMP) && !(MenuInfo->dwStyle & MNS_NOCHECK))
+ bmpRect.left += check_bitmap_width + 2;
+ if (!(checked && (MenuInfo->dwStyle & MNS_CHECKORBMP)))
+ {
+ bmpRect.right = bmpRect.left + MenuInfo->maxBmpSize.cx;
+ MenuDrawBitmapItem(hdc, lpitem, &bmpRect, MenuInfo->Self, WndOwner, odaction, menuBar);
+ }
+ }
+ /* Draw the popup-menu arrow */
+ if (lpitem->fType & MF_POPUP)
+ {
+ RECT rectTemp;
+ CopyRect(&rectTemp, &rect);
+ rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK);
+ DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW);
+ }
+ rect.left += 4;
+ if( !(MenuInfo->dwStyle & MNS_NOCHECK))
+ rect.left += check_bitmap_width;
+ rect.right -= check_bitmap_width;
+ }
+ else if( lpitem->hbmpItem)
+ { /* Draw the bitmap */
+ MenuDrawBitmapItem(hdc, lpitem, &rect, MenuInfo->Self, WndOwner, odaction, menuBar);
+ }
- if (0 != (Item->fState & MF_GRAYED))
- {
- if (0 == (Item->fState & MF_HILITE))
- {
- ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
- SetTextColor(Dc, RGB(0xff, 0xff, 0xff));
- DrawTextW(Dc, Text, i, &Rect, uFormat);
- --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
- }
- SetTextColor(Dc, RGB(0x80, 0x80, 0x80));
+ /* process text if present */
+ if (lpitem->Text)
+ {
+ register int i = 0;
+ HFONT hfontOld = 0;
+
+ UINT uFormat = menuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE
+ : DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+
+ if(MenuInfo->dwStyle & MNS_CHECKORBMP)
+ rect.left += max(0, MenuInfo->maxBmpSize.cx - GetSystemMetrics(SM_CXMENUCHECK));
+ else
+ rect.left += MenuInfo->maxBmpSize.cx;
+
+ if ( lpitem->fState & MFS_DEFAULT )
+ {
+ hfontOld = SelectObject(hdc, hMenuFontBold);
}
- DrawTextW(Dc, Text, i, &Rect, uFormat);
+ if (menuBar) {
+ rect.left += MENU_BAR_ITEMS_SPACE / 2;
+ rect.right -= MENU_BAR_ITEMS_SPACE / 2;
+ }
- /* paint the shortcut text */
- if (! MenuBar && L'\0' != Text[i]) /* There's a tab or flush-right char */
+ Text = (PWCHAR) lpitem->dwTypeData;
+ if(Text)
{
- if (L'\t' == Text[i])
+ for (i = 0; L'\0' != Text[i]; i++)
+ if (Text[i] == L'\t' || Text[i] == L'\b')
+ break;
+ }
+
+ if(lpitem->fState & MF_GRAYED)
+ {
+ if (!(lpitem->fState & MF_HILITE) )
{
- Rect.left = Item->XTab;
- uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
+ ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
+ SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
+ DrawTextW( hdc, Text, i, &rect, uFormat );
+ --rect.left; --rect.top; --rect.right; --rect.bottom;
+ }
+ SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
+ }
+
+ DrawTextW( hdc, Text, i, &rect, uFormat);
+
+ /* paint the shortcut text */
+ if (!menuBar && L'\0' != Text[i]) /* There's a tab or flush-right char */
+ {
+ if (L'\t' == Text[i])
+ {
+ rect.left = lpitem->XTab;
+ uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
}
- else
+ else
{
- Rect.right = Item->XTab;
- uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
+ rect.right = lpitem->XTab;
+ uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
}
- if (0 != (Item->fState & MF_GRAYED))
+ if (lpitem->fState & MF_GRAYED)
{
- if (0 == (Item->fState & MF_HILITE))
+ if (!(lpitem->fState & MF_HILITE) )
{
- ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
- SetTextColor(Dc, RGB(0xff, 0xff, 0xff));
- DrawTextW(Dc, Text + i + 1, -1, &Rect, uFormat);
- --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
+ ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
+ SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
+ DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat);
+ --rect.left; --rect.top; --rect.right; --rect.bottom;
}
- SetTextColor(Dc, RGB(0x80, 0x80, 0x80));
- }
- DrawTextW(Dc, Text + i + 1, -1, &Rect, uFormat);
+ SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
+ }
+ DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat );
}
- if (NULL != FontOld)
- {
- SelectObject(Dc, FontOld);
- }
- }
+ if (hfontOld)
+ SelectObject (hdc, hfontOld);
+ }
}
/***********************************************************************
@@ -917,63 +1464,337 @@ MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC Dc,
*
* Paint a popup menu.
*/
-static void FASTCALL
-MenuDrawPopupMenu(HWND Wnd, HDC Dc, HMENU Menu)
+static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu )
{
- HBRUSH PrevBrush = NULL;
- HPEN PrevPen;
- RECT Rect;
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO ItemInfo;
- UINT u;
+ HBRUSH hPrevBrush = 0;
+ RECT rect;
- TRACE("wnd=%x dc=%x menu=%x\n", Wnd, Dc, Menu);
+ TRACE("wnd=%p dc=%p menu=%p\n", hwnd, hdc, hmenu);
- GetClientRect(Wnd, &Rect);
+ GetClientRect( hwnd, &rect );
- if (NULL != (PrevBrush = SelectObject(Dc, GetSysColorBrush(COLOR_MENU)))
- && NULL != SelectObject(Dc, hMenuFont))
+ if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
+ && (SelectObject( hdc, hMenuFont)))
{
- Rectangle(Dc, Rect.left, Rect.top, Rect.right, Rect.bottom);
+ HPEN hPrevPen;
- PrevPen = SelectObject(Dc, GetStockObject(NULL_PEN));
- if (NULL != PrevPen)
+ Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
+
+ hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
+ if ( hPrevPen )
{
- BOOL flat_menu = FALSE;
+ BOOL flat_menu = FALSE;
+ ROSMENUINFO MenuInfo;
+ ROSMENUITEMINFO ItemInfo;
- SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
- if (flat_menu)
- FrameRect(Dc, &Rect, GetSysColorBrush(COLOR_BTNSHADOW));
- else
- DrawEdge(Dc, &Rect, EDGE_RAISED, BF_RECT);
+ SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
+ if (flat_menu)
+ FrameRect(hdc, &rect, GetSysColorBrush(COLOR_BTNSHADOW));
+ else
+ DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
- /* draw menu items */
-
- if (MenuGetRosMenuInfo(&MenuInfo, Menu) && 0 != MenuInfo.MenuItemCount)
+ /* draw menu items */
+ if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.MenuItemCount)
{
- MenuInitRosMenuItemInfo(&ItemInfo);
+ UINT u;
+
+ MenuInitRosMenuItemInfo(&ItemInfo);
- for (u = 0; u < MenuInfo.MenuItemCount; u++)
+ for (u = 0; u < MenuInfo.MenuItemCount; u++)
{
- if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo))
+ if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo))
{
- MenuDrawMenuItem(Wnd, &MenuInfo, MenuInfo.WndOwner, Dc, &ItemInfo,
- MenuInfo.Height, FALSE, ODA_DRAWENTIRE);
+ MenuDrawMenuItem(hwnd, &MenuInfo, MenuInfo.WndOwner, hdc, &ItemInfo,
+ MenuInfo.Height, FALSE, ODA_DRAWENTIRE);
}
}
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- }
- }
- else
- {
- SelectObject(Dc, PrevBrush);
- }
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ }
+ } else
+ {
+ SelectObject( hdc, hPrevBrush );
+ }
}
}
-LRESULT WINAPI
-PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
+/***********************************************************************
+ * MenuDrawMenuBar
+ *
+ * Paint a menu bar. Returns the height of the menu bar.
+ * called from [windows/nonclient.c]
+ */
+UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
+ BOOL suppress_draw)
+{
+ ROSMENUINFO lppop;
+ HFONT hfontOld = 0;
+ HMENU hMenu = GetMenu(hwnd);
+
+ if (! MenuGetRosMenuInfo(&lppop, hMenu) || lprect == NULL)
+ {
+ return GetSystemMetrics(SM_CYMENU);
+ }
+
+ if (suppress_draw)
+ {
+ hfontOld = SelectObject(hDC, hMenuFont);
+
+ MenuMenuBarCalcSize(hDC, lprect, &lppop, hwnd);
+
+ lprect->bottom = lprect->top + lppop.Height;
+
+ if (hfontOld) SelectObject( hDC, hfontOld);
+ return lppop.Height;
+ }
+ else
+ return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL);
+}
+
+/***********************************************************************
+ * MenuShowPopup
+ *
+ * Display a popup menu.
+ */
+static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT flags,
+ INT x, INT y, INT xanchor, INT yanchor )
+{
+ ROSMENUINFO MenuInfo;
+ ROSMENUITEMINFO ItemInfo;
+ UINT width, height;
+ POINT pt;
+ HMONITOR monitor;
+ MONITORINFO info;
+
+ TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
+ hwndOwner, hmenu, id, x, y, xanchor, yanchor);
+
+ if (! MenuGetRosMenuInfo(&MenuInfo, hmenu)) return FALSE;
+ if (MenuInfo.FocusedItem != NO_SELECTED_ITEM)
+ {
+ MenuInitRosMenuItemInfo(&ItemInfo);
+ if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo))
+ {
+ ItemInfo.fMask |= MIIM_STATE;
+ ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT);
+ MenuSetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo);
+ }
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ MenuInfo.FocusedItem = NO_SELECTED_ITEM;
+ }
+
+ /* store the owner for DrawItem */
+ MenuInfo.WndOwner = hwndOwner;
+ MenuSetRosMenuInfo(&MenuInfo);
+
+ MenuPopupMenuCalcSize(&MenuInfo, hwndOwner);
+
+ /* adjust popup menu pos so that it fits within the desktop */
+
+ width = MenuInfo.Width + GetSystemMetrics(SM_CXBORDER);
+ height = MenuInfo.Height + GetSystemMetrics(SM_CYBORDER);
+
+ /* FIXME: should use item rect */
+ pt.x = x;
+ pt.y = y;
+ monitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
+ info.cbSize = sizeof(info);
+ GetMonitorInfoW( monitor, &info );
+
+ if( flags & TPM_RIGHTALIGN ) x -= width;
+ if( flags & TPM_CENTERALIGN ) x -= width / 2;
+
+ if( flags & TPM_BOTTOMALIGN ) y -= height;
+ if( flags & TPM_VCENTERALIGN ) y -= height / 2;
+
+ if( x + width > info.rcWork.right)
+ {
+ if( xanchor && x >= width - xanchor )
+ x -= width - xanchor;
+
+ if( x + width > info.rcWork.right)
+ x = info.rcWork.right - width;
+ }
+ if( x < info.rcWork.left ) x = info.rcWork.left;
+
+ if( y + height > info.rcWork.bottom)
+ {
+ if( yanchor && y >= height + yanchor )
+ y -= height + yanchor;
+
+ if( y + height > info.rcWork.bottom)
+ y = info.rcWork.bottom - height;
+ }
+ if( y < info.rcWork.top ) y = info.rcWork.top;
+
+ /* NOTE: In Windows, top menu popup is not owned. */
+ MenuInfo.Wnd = CreateWindowExW( 0, POPUPMENU_CLASS_ATOMW, NULL,
+ WS_POPUP, x, y, width, height,
+ hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
+ (LPVOID) MenuInfo.Self);
+ if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE;
+ if (!top_popup) {
+ top_popup = MenuInfo.Wnd;
+ }
+
+ /* Display the window */
+
+ SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+ UpdateWindow( MenuInfo.Wnd );
+ return TRUE;
+}
+
+/***********************************************************************
+ * MenuSelectItem
+ */
+static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIndex,
+ BOOL sendMenuSelect, HMENU topmenu)
+{
+ ROSMENUITEMINFO ItemInfo;
+ ROSMENUINFO TopMenuInfo;
+ HDC hdc;
+
+ TRACE("owner=%p menu=%p index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect);
+
+ if (!hmenu || !hmenu->MenuItemCount || !hmenu->Wnd) return;
+ if (hmenu->FocusedItem == wIndex) return;
+ if (hmenu->Flags & MF_POPUP) hdc = GetDC(hmenu->Wnd);
+ else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW);
+ if (!top_popup) {
+ top_popup = hmenu->Wnd;
+ }
+
+ SelectObject( hdc, hMenuFont );
+
+ MenuInitRosMenuItemInfo(&ItemInfo);
+
+ /* Clear previous highlighted item */
+ if (hmenu->FocusedItem != NO_SELECTED_ITEM)
+ {
+ if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo))
+ {
+ ItemInfo.fMask |= MIIM_STATE;
+ ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT);
+ MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo);
+ }
+ MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, &ItemInfo,
+ hmenu->Height, ! (hmenu->Flags & MF_POPUP),
+ ODA_SELECT);
+ }
+
+ /* Highlight new item (if any) */
+ hmenu->FocusedItem = wIndex;
+ MenuSetRosMenuInfo(hmenu);
+ if (hmenu->FocusedItem != NO_SELECTED_ITEM)
+ {
+ if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo))
+ {
+ if (!(ItemInfo.fType & MF_SEPARATOR))
+ {
+ ItemInfo.fMask |= MIIM_STATE;
+ ItemInfo.fState |= MF_HILITE;
+ MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo);
+ MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc,
+ &ItemInfo, hmenu->Height, ! (hmenu->Flags & MF_POPUP),
+ ODA_SELECT);
+ }
+ if (sendMenuSelect)
+ {
+ SendMessageW(hwndOwner, WM_MENUSELECT,
+ MAKELONG(ItemInfo.fType & MF_POPUP ? wIndex : ItemInfo.wID,
+ ItemInfo.fType | ItemInfo.fState | MF_MOUSESELECT |
+ (hmenu->Flags & MF_SYSMENU)), (LPARAM) hmenu->Self);
+ }
+ }
+ }
+ else if (sendMenuSelect) {
+ if(topmenu) {
+ int pos;
+ pos = MenuFindSubMenu(&topmenu, hmenu->Self);
+ if (pos != NO_SELECTED_ITEM)
+ {
+ if (MenuGetRosMenuInfo(&TopMenuInfo, topmenu)
+ && MenuGetRosMenuItemInfo(topmenu, pos, &ItemInfo))
+ {
+ SendMessageW(hwndOwner, WM_MENUSELECT,
+ MAKELONG(Pos, ItemInfo.fType | ItemInfo.fState
+ | MF_MOUSESELECT
+ | (TopMenuInfo.Flags & MF_SYSMENU)),
+ (LPARAM) topmenu);
+ }
+ }
+ }
+ }
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ ReleaseDC(hmenu->Wnd, hdc);
+}
+
+/***********************************************************************
+ * MenuMoveSelection
+ *
+ * Moves currently selected item according to the Offset parameter.
+ * If there is no selection then it should select the last item if
+ * Offset is ITEM_PREV or the first item if Offset is ITEM_NEXT.
+ */
+static void FASTCALL
+MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset)
+{
+ INT i;
+ ROSMENUITEMINFO ItemInfo;
+ INT OrigPos;
+
+ TRACE("hwnd=%x menu=%x off=0x%04x\n", WndOwner, MenuInfo, Offset);
+
+ /* Prevent looping */
+ if (0 == MenuInfo->MenuItemCount || 0 == Offset)
+ return;
+ else if (Offset < -1)
+ Offset = -1;
+ else if (Offset > 1)
+ Offset = 1;
+
+ MenuInitRosMenuItemInfo(&ItemInfo);
+
+ OrigPos = MenuInfo->FocusedItem;
+ if (OrigPos == NO_SELECTED_ITEM) /* NO_SELECTED_ITEM is not -1 ! */
+ {
+ OrigPos = 0;
+ i = -1;
+ }
+ else
+ {
+ i = MenuInfo->FocusedItem;
+ }
+
+ do
+ {
+ /* Step */
+ i += Offset;
+ /* Clip and wrap around */
+ if (i < 0)
+ {
+ i = MenuInfo->MenuItemCount - 1;
+ }
+ else if (i >= MenuInfo->MenuItemCount)
+ {
+ i = 0;
+ }
+ /* If this is a good candidate; */
+ if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) &&
+ 0 == (ItemInfo.fType & MF_SEPARATOR))
+ {
+ MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL);
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+ return;
+ }
+ } while (i != OrigPos);
+
+ /* Not found */
+ MenuCleanupRosMenuItemInfo(&ItemInfo);
+}
+
+LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
TRACE("YES! hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam);
@@ -1010,9 +1831,9 @@ PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
case WM_DESTROY:
/* zero out global pointer in case resident popup window was destroyed. */
- if (Wnd == TopPopup)
+ if (Wnd == top_popup)
{
- TopPopup = NULL;
+ top_popup = NULL;
}
break;
@@ -1082,9 +1903,9 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
case WM_DESTROY:
/* zero out global pointer in case resident popup window was destroyed. */
- if (Wnd == TopPopup)
+ if (Wnd == top_popup)
{
- TopPopup = NULL;
+ top_popup = NULL;
}
break;
@@ -1117,66 +1938,6 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
return 0;
}
-/**********************************************************************
- * MENUEX_ParseResource
- *
- * Parse an extended menu resource and add items to the menu.
- * Return a pointer to the end of the resource.
- *
- * FIXME - should we be passing an LPCSTR to a predominantly UNICODE function?
- */
-static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
-{
- WORD resinfo;
-
- do
- {
- MENUITEMINFOW mii;
-
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
- mii.fType = GET_DWORD(res);
- res += sizeof(DWORD);
- mii.fState = GET_DWORD(res);
- res += sizeof(DWORD);
- mii.wID = GET_DWORD(res);
- res += sizeof(DWORD);
- resinfo = GET_WORD(res);
- res += sizeof(WORD);
- /* Align the text on a word boundary. */
- res += (~((int)res - 1)) & 1;
- mii.dwTypeData = (LPWSTR) res;
- res += (1 + strlenW(mii.dwTypeData)) * sizeof(WCHAR);
- /* Align the following fields on a dword boundary. */
- res += (~((int)res - 1)) & 3;
-
- if (resinfo & 1) /* Pop-up? */
- {
- /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
- res += sizeof(DWORD);
- mii.hSubMenu = CreatePopupMenu();
- if (!mii.hSubMenu)
- return NULL;
- if (!(res = MENUEX_ParseResource(res, mii.hSubMenu)))
- {
- DestroyMenu(mii.hSubMenu);
- return NULL;
- }
- mii.fMask |= MIIM_SUBMENU;
- mii.fType |= MF_POPUP;
- mii.wID = (UINT) mii.hSubMenu;
- }
- else if(!*mii.dwTypeData && !(mii.fType & MF_SEPARATOR))
- {
- mii.fType |= MF_SEPARATOR;
- }
- InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
- }
- while (!(resinfo & MF_END));
- return res;
-}
-
-
/**********************************************************************
* MENU_ParseResource
*
@@ -1187,72 +1948,126 @@ static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
*/
static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
{
- WORD flags, id = 0;
- HMENU hSubMenu;
- LPCSTR str;
- BOOL end = FALSE;
+ WORD flags, id = 0;
+ HMENU hSubMenu;
+ LPCSTR str;
+ BOOL end = FALSE;
- do
- {
- flags = GET_WORD(res);
-
- /* remove MF_END flag before passing it to AppendMenu()! */
- end = (flags & MF_END);
- if(end) flags ^= MF_END;
-
- res += sizeof(WORD);
- if(!(flags & MF_POPUP))
+ do
{
- id = GET_WORD(res);
- res += sizeof(WORD);
- }
- str = res;
- if(!unicode)
- res += strlen(str) + 1;
- else
- res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
- if (flags & MF_POPUP)
- {
- hSubMenu = CreatePopupMenu();
- if(!hSubMenu) return NULL;
- if(!(res = MENU_ParseResource(res, hSubMenu, unicode)))
- return NULL;
- if(!unicode)
- AppendMenuA(hMenu, flags, (UINT)hSubMenu, str);
- else
- AppendMenuW(hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str);
- }
- else /* Not a popup */
- {
- if(!unicode)
- {
- if (*str == 0)
- flags = MF_SEPARATOR;
- }
- else
- {
- if (*(LPCWSTR)str == 0)
- flags = MF_SEPARATOR;
- }
+ flags = GET_WORD(res);
- if (flags & MF_SEPARATOR)
- {
- if (!(flags & (MF_GRAYED | MF_DISABLED)))
- flags |= MF_GRAYED | MF_DISABLED;
- }
+ /* remove MF_END flag before passing it to AppendMenu()! */
+ end = (flags & MF_END);
+ if(end) flags ^= MF_END;
- if(!unicode)
- AppendMenuA(hMenu, flags, id, *str ? str : NULL);
- else
- AppendMenuW(hMenu, flags, id,
+ res += sizeof(WORD);
+ if(!(flags & MF_POPUP))
+ {
+ id = GET_WORD(res);
+ res += sizeof(WORD);
+ }
+ str = res;
+ if(!unicode)
+ res += strlen(str) + 1;
+ else
+ res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
+ if (flags & MF_POPUP)
+ {
+ hSubMenu = CreatePopupMenu();
+ if(!hSubMenu) return NULL;
+ if(!(res = MENU_ParseResource(res, hSubMenu, unicode)))
+ return NULL;
+ if(!unicode)
+ AppendMenuA(hMenu, flags, (UINT)hSubMenu, str);
+ else
+ AppendMenuW(hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str);
+ }
+ else /* Not a popup */
+ {
+ if(!unicode)
+ {
+ if (*str == 0)
+ flags = MF_SEPARATOR;
+ }
+ else
+ {
+ if (*(LPCWSTR)str == 0)
+ flags = MF_SEPARATOR;
+ }
+
+ if (flags & MF_SEPARATOR)
+ {
+ if (!(flags & (MF_GRAYED | MF_DISABLED)))
+ flags |= MF_GRAYED | MF_DISABLED;
+ }
+
+ if(!unicode)
+ AppendMenuA(hMenu, flags, id, *str ? str : NULL);
+ else
+ AppendMenuW(hMenu, flags, id,
*(LPCWSTR)str ? (LPCWSTR)str : NULL);
- }
- } while(!end);
-
- return res;
+ }
+ } while(!end);
+ return res;
}
+/**********************************************************************
+ * MENUEX_ParseResource
+ *
+ * Parse an extended menu resource and add items to the menu.
+ * Return a pointer to the end of the resource.
+ */
+static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
+{
+ WORD resinfo;
+ do {
+ MENUITEMINFOW mii;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
+ mii.fType = GET_DWORD(res);
+ res += sizeof(DWORD);
+ mii.fState = GET_DWORD(res);
+ res += sizeof(DWORD);
+ mii.wID = GET_DWORD(res);
+ res += sizeof(DWORD);
+ resinfo = GET_WORD(res);
+ res += sizeof(WORD);
+ /* Align the text on a word boundary. */
+ res += (~((UINT_PTR)res - 1)) & 1;
+ mii.dwTypeData = (LPWSTR) res;
+ res += (1 + strlenW(mii.dwTypeData)) * sizeof(WCHAR);
+ /* Align the following fields on a dword boundary. */
+ res += (~((UINT_PTR)res - 1)) & 3;
+
+ TRACE("Menu item: [%08x,%08x,%04x,%04x,%S]\n",
+ mii.fType, mii.fState, mii.wID, resinfo, mii.dwTypeData);
+
+ if (resinfo & 1) { /* Pop-up? */
+ /* DWORD helpid = GET_DWORD(res); FIXME: use this. */
+ res += sizeof(DWORD);
+ mii.hSubMenu = CreatePopupMenu();
+ if (!mii.hSubMenu)
+ return NULL;
+ if (!(res = MENUEX_ParseResource(res, mii.hSubMenu))) {
+ DestroyMenu(mii.hSubMenu);
+ return NULL;
+ }
+ mii.fMask |= MIIM_SUBMENU;
+ mii.fType |= MF_POPUP;
+ mii.wID = (UINT) mii.hSubMenu;
+ }
+ else if(!*mii.dwTypeData && !(mii.fType & MF_SEPARATOR))
+ {
+ mii.fType |= MF_SEPARATOR;
+ }
+ InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
+ } while (!(resinfo & MF_END));
+ return res;
+}
+
NTSTATUS WINAPI
User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
{
@@ -1320,7 +2135,6 @@ MenuInit(VOID)
return TRUE;
}
-
VOID
MenuCleanup(VOID)
{
@@ -1337,435 +2151,6 @@ MenuCleanup(VOID)
}
}
-
-
-/***********************************************************************
- * MenuCalcItemSize
- *
- * Calculate the size of the menu item and store it in ItemInfo->rect.
- */
-static void FASTCALL
-MenuCalcItemSize(HDC Dc, PROSMENUITEMINFO ItemInfo, PROSMENUINFO MenuInfo, HWND WndOwner,
- INT OrgX, INT OrgY, BOOL MenuBar)
-{
- PWCHAR p;
- INT itemheight = 0;
- UINT CheckBitmapWidth = GetSystemMetrics(SM_CXMENUCHECK);
-
- TRACE("dc=%x owner=%x (%d,%d)\n", Dc, WndOwner, OrgX, OrgY);
-
- MenuCharSize.cx = GdiGetCharDimensions( Dc, NULL, &MenuCharSize.cy );
-
- SetRect(&ItemInfo->Rect, OrgX, OrgY, OrgX, OrgY);
-
- if (0 != (ItemInfo->fType & MF_OWNERDRAW))
- {
- /*
- ** Experimentation under Windows reveals that an owner-drawn
- ** menu is expected to return the size of the content part of
- ** the menu item, not including the checkmark nor the submenu
- ** arrow. Windows adds those values itself and returns the
- ** enlarged rectangle on subsequent WM_DRAWITEM messages.
- */
- MEASUREITEMSTRUCT mis;
- mis.CtlType = ODT_MENU;
- mis.CtlID = 0;
- mis.itemID = ItemInfo->wID;
- mis.itemData = (DWORD)ItemInfo->dwItemData;
- mis.itemHeight = HIWORD( GetDialogBaseUnits());
- mis.itemWidth = 0;
- SendMessageW(WndOwner, WM_MEASUREITEM, 0, (LPARAM) &mis);
- /* Tests reveal that Windows ( Win95 thru WinXP) adds twice the average
- * width of a menufont character to the width of an owner-drawn menu.
- */
- ItemInfo->Rect.right += mis.itemWidth + 2 * MenuCharSize.cx;
-
- if (MenuBar)
- {
- /* under at least win95 you seem to be given a standard
- height for the menu and the height value is ignored */
- ItemInfo->Rect.bottom += GetSystemMetrics(SM_CYMENUSIZE);
- }
- else
- {
- ItemInfo->Rect.bottom += mis.itemHeight;
- }
-
- TRACE("id=%04x size=%dx%d\n", ItemInfo->wID, mis.itemWidth, mis.itemHeight);
- return;
- }
-
- if (0 != (ItemInfo->fType & MF_SEPARATOR))
- {
- ItemInfo->Rect.bottom += SEPARATOR_HEIGHT;
- if( !MenuBar)
- ItemInfo->Rect.right += CheckBitmapWidth + MenuCharSize.cx;
- return;
- }
-
- ItemInfo->XTab = 0;
-
- if (ItemInfo->hbmpItem)
- {
- SIZE Size;
-
- if (!MenuBar) /* hbmpItem */
- {
- MenuGetBitmapItemSize(ItemInfo, &Size, WndOwner );
- /* Keep the size of the bitmap in callback mode to be able
- * to draw it correctly */
- ItemInfo->Rect.right = ItemInfo->Rect.left + Size.cx;
- if (MenuInfo->maxBmpSize.cx < abs(Size.cx) + MENU_ITEM_HBMP_SPACE ||
- MenuInfo->maxBmpSize.cy < abs(Size.cy))
- {
- MenuInfo->maxBmpSize.cx = abs(Size.cx) + MENU_ITEM_HBMP_SPACE;
- MenuInfo->maxBmpSize.cy = abs(Size.cy);
- }
- MenuSetRosMenuInfo(MenuInfo);
- itemheight = Size.cy + 2;
-
- if( !(MenuInfo->dwStyle & MNS_NOCHECK))
- ItemInfo->Rect.right += 2 * CheckBitmapWidth;
- ItemInfo->Rect.right += 4 + MenuCharSize.cx;
- ItemInfo->XTab = ItemInfo->Rect.right;
- ItemInfo->Rect.right += CheckBitmapWidth;
- }
- else /* hbmpItem & MenuBar */
- {
- MenuGetBitmapItemSize(ItemInfo, &Size, WndOwner );
- ItemInfo->Rect.right += Size.cx;
- if( ItemInfo->Text) ItemInfo->Rect.right += 2;
- itemheight = Size.cy;
-
- /* Special case: Minimize button doesn't have a space behind it. */
- if (ItemInfo->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE ||
- ItemInfo->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D)
- ItemInfo->Rect.right -= 1;
- }
- }
- else if (!MenuBar)
- {
- if( !(MenuInfo->dwStyle & MNS_NOCHECK))
- ItemInfo->Rect.right += CheckBitmapWidth;
- ItemInfo->Rect.right += 4 + MenuCharSize.cx;
- ItemInfo->XTab = ItemInfo->Rect.right;
- ItemInfo->Rect.right += CheckBitmapWidth;
- }
-
- /* it must be a text item - unless it's the system menu */
- if (0 == (ItemInfo->fType & MF_SYSMENU) && ItemInfo->Text)
- {
- HFONT hfontOld = NULL;
- RECT rc = ItemInfo->Rect;
- LONG txtheight, txtwidth;
-
- if ( ItemInfo->fState & MFS_DEFAULT )
- {
- hfontOld = SelectObject( Dc, hMenuFontBold );
- }
- if (MenuBar)
- {
- txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, -1, &rc,
- DT_SINGLELINE|DT_CALCRECT);
- ItemInfo->Rect.right += rc.right - rc.left;
- itemheight = max( max( itemheight, txtheight),
- GetSystemMetrics( SM_CYMENU) - 1);
- ItemInfo->Rect.right += 2 * MenuCharSize.cx;
- }
- else
- {
- if ((p = strchrW( ItemInfo->dwTypeData, '\t' )) != NULL)
- {
- RECT tmprc = rc;
- LONG tmpheight;
- int n = (int)( p - ItemInfo->dwTypeData);
- /* Item contains a tab (only meaningful in popup menus) */
- /* get text size before the tab */
- txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, n, &rc,
- DT_SINGLELINE|DT_CALCRECT);
- txtwidth = rc.right - rc.left;
- p += 1; /* advance past the Tab */
- /* get text size after the tab */
- tmpheight = DrawTextW( Dc, p, -1, &tmprc, DT_SINGLELINE|DT_CALCRECT);
- ItemInfo->XTab += txtwidth;
- txtheight = max( txtheight, tmpheight);
- txtwidth += MenuCharSize.cx + /* space for the tab */
- tmprc.right - tmprc.left; /* space for the short cut */
- }
- else
- {
- txtheight = DrawTextW( Dc, ItemInfo->dwTypeData, -1, &rc,
- DT_SINGLELINE|DT_CALCRECT);
- txtwidth = rc.right - rc.left;
- ItemInfo->XTab += txtwidth;
- }
- ItemInfo->Rect.right += 2 + txtwidth;
- itemheight = max( itemheight, max( txtheight + 2, MenuCharSize.cy + 4));
- }
- if (hfontOld) SelectObject (Dc, hfontOld);
- }
- else if( MenuBar)
- {
- itemheight = max( itemheight, GetSystemMetrics(SM_CYMENU)-1);
- }
- ItemInfo->Rect.bottom += itemheight;
- TRACE("(%ld,%ld)-(%ld,%ld)\n", ItemInfo->Rect.left, ItemInfo->Rect.top, ItemInfo->Rect.right, ItemInfo->Rect.bottom);
-}
-
-/***********************************************************************
- * MenuPopupMenuCalcSize
- *
- * Calculate the size of a popup menu.
- */
-static void FASTCALL
-MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner)
-{
- ROSMENUITEMINFO ItemInfo;
- HDC Dc;
- int Start, i;
- int OrgX, OrgY, MaxX, MaxTab, MaxTabWidth;
-
- MenuInfo->Width = MenuInfo->Height = 0;
- if (0 == MenuInfo->MenuItemCount)
- {
- MenuSetRosMenuInfo(MenuInfo);
- return;
- }
-
- Dc = GetDC(NULL);
- SelectObject(Dc, hMenuFont);
-
- Start = 0;
- MaxX = 2 + 1;
-
- MenuInfo->maxBmpSize.cx = 0;
- MenuInfo->maxBmpSize.cy = 0;
-
- MenuInitRosMenuItemInfo(&ItemInfo);
- while (Start < MenuInfo->MenuItemCount)
- {
- OrgX = MaxX;
- OrgY = 2;
-
- MaxTab = MaxTabWidth = 0;
-
- /* Parse items until column break or end of menu */
- for (i = Start; i < MenuInfo->MenuItemCount; i++)
- {
- if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- MenuSetRosMenuInfo(MenuInfo);
- return;
- }
- if (i != Start &&
- 0 != (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
- {
- break;
- }
- MenuCalcItemSize(Dc, &ItemInfo, MenuInfo, WndOwner, OrgX, OrgY, FALSE);
- if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- MenuSetRosMenuInfo(MenuInfo);
- return;
- }
-// Not sure here,, The patch from wine removes this.
-// if (0 != (ItemInfo.fType & MF_MENUBARBREAK))
-// {
-// OrgX++;
-// }
- MaxX = max(MaxX, ItemInfo.Rect.right);
- OrgY = ItemInfo.Rect.bottom;
- if ((ItemInfo.Text) && 0 != ItemInfo.XTab)
- {
- MaxTab = max(MaxTab, ItemInfo.XTab);
- MaxTabWidth = max(MaxTabWidth, ItemInfo.Rect.right - ItemInfo.XTab);
- }
- }
-
- /* Finish the column (set all items to the largest width found) */
- MaxX = max(MaxX, MaxTab + MaxTabWidth);
- while (Start < i)
- {
- if (MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
- {
- ItemInfo.Rect.right = MaxX;
- if ((ItemInfo.Text) && 0 != ItemInfo.XTab)
- {
- ItemInfo.XTab = MaxTab;
- }
- MenuSetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo);
- }
- Start++;
- }
- MenuInfo->Height = max(MenuInfo->Height, OrgY);
- }
-
- MenuInfo->Width = MaxX;
-
- /* space for 3d border */
- MenuInfo->Height += 2;
- MenuInfo->Width += 2;
-
- ReleaseDC(NULL, Dc);
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- MenuSetRosMenuInfo(MenuInfo);
-}
-
-/***********************************************************************
- * MenuMenuBarCalcSize
- *
- * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
- * height is off by 1 pixel which causes lengthy window relocations when
- * active document window is maximized/restored.
- *
- * Calculate the size of the menu bar.
- */
-static void FASTCALL
-MenuMenuBarCalcSize(HDC Dc, LPRECT Rect, PROSMENUINFO MenuInfo, HWND WndOwner)
-{
- ROSMENUITEMINFO ItemInfo;
- int Start, i, OrgX, OrgY, MaxY, HelpPos;
-
- if (NULL == Rect || NULL == MenuInfo)
- {
- return;
- }
- if (0 == MenuInfo->MenuItemCount)
- {
- return;
- }
-
- TRACE("left=%ld top=%ld right=%ld bottom=%ld\n",
- Rect->left, Rect->top, Rect->right, Rect->bottom);
- MenuInfo->Width = Rect->right - Rect->left;
- MenuInfo->Height = 0;
- MaxY = Rect->top + 1;
- Start = 0;
- HelpPos = -1;
-
- MenuInfo->maxBmpSize.cx = 0;
- MenuInfo->maxBmpSize.cy = 0;
-
- MenuInitRosMenuItemInfo(&ItemInfo);
- while (Start < MenuInfo->MenuItemCount)
- {
- if (! MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return;
- }
- OrgX = Rect->left;
- OrgY = MaxY;
-
- /* Parse items until line break or end of menu */
- for (i = Start; i < MenuInfo->MenuItemCount; i++)
- {
- if (-1 == HelpPos && 0 != (ItemInfo.fType & MF_RIGHTJUSTIFY))
- {
- HelpPos = i;
- }
- if (i != Start &&
- 0 != (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
- {
- break;
- }
-
- TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", OrgX, OrgY);
- MenuCalcItemSize(Dc, &ItemInfo, MenuInfo, WndOwner, OrgX, OrgY, TRUE);
- if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return;
- }
-
- if (ItemInfo.Rect.right > Rect->right)
- {
- if (i != Start)
- {
- break;
- }
- else
- {
- ItemInfo.Rect.right = Rect->right;
- }
- }
- MaxY = max(MaxY, ItemInfo.Rect.bottom );
- OrgX = ItemInfo.Rect.right;
- if (i + 1 < MenuInfo->MenuItemCount)
- {
- if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i + 1, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return;
- }
- }
- }
-
-/* FIXME: Is this really needed? */ /*NO! it is not needed, why make the
-HBMMENU_MBAR_CLOSE, MINIMIZE & RESTORE, look the same size as the menu bar! */
-#if 0
- /* Finish the line (set all items to the largest height found) */
- while (Start < i)
- {
- if (MenuGetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo))
- {
- ItemInfo.Rect.bottom = MaxY;
- MenuSetRosMenuItemInfo(MenuInfo->Self, Start, &ItemInfo);
- }
- Start++;
- }
-#else
- Start = i; /* This works! */
-#endif
- }
-
- Rect->bottom = MaxY;
- MenuInfo->Height = Rect->bottom - Rect->top;
- MenuSetRosMenuInfo(MenuInfo);
-
- if (-1 != HelpPos)
- {
- /* Flush right all items between the MF_RIGHTJUSTIFY and */
- /* the last item (if several lines, only move the last line) */
- if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->MenuItemCount - 1, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return;
- }
- OrgY = ItemInfo.Rect.top;
- OrgX = Rect->right;
- for (i = MenuInfo->MenuItemCount - 1; HelpPos <= i; i--)
- {
- if (i < HelpPos)
- {
- break; /* done */
- }
- if (ItemInfo.Rect.top != OrgY)
- {
- break; /* Other line */
- }
- if (OrgX <= ItemInfo.Rect.right)
- {
- break; /* Too far right already */
- }
- ItemInfo.Rect.left += OrgX - ItemInfo.Rect.right;
- ItemInfo.Rect.right = OrgX;
- OrgX = ItemInfo.Rect.left;
- MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo);
- if (HelpPos + 1 <= i &&
- ! MenuGetRosMenuItemInfo(MenuInfo->Self, i - 1, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return;
- }
- }
- }
-
- MenuCleanupRosMenuItemInfo(&ItemInfo);
-}
-
/***********************************************************************
* DrawMenuBarTemp (USER32.@)
*
@@ -1843,476 +2228,6 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font)
return MenuInfo.Height;
}
-
-/***********************************************************************
- * MenuDrawMenuBar
- *
- * Paint a menu bar. Returns the height of the menu bar.
- * called from [windows/nonclient.c]
- */
-UINT MenuDrawMenuBar(HDC DC, LPRECT Rect, HWND Wnd, BOOL SuppressDraw)
-{
- ROSMENUINFO MenuInfo;
- HFONT FontOld = NULL;
- HMENU Menu = GetMenu(Wnd);
-
- if (NULL == Rect || ! MenuGetRosMenuInfo(&MenuInfo, Menu))
- {
- return GetSystemMetrics(SM_CYMENU);
- }
-
- if (SuppressDraw)
- {
- FontOld = SelectObject(DC, hMenuFont);
-
- MenuMenuBarCalcSize(DC, Rect, &MenuInfo, Wnd);
-
- Rect->bottom = Rect->top + MenuInfo.Height;
-
- if (NULL != FontOld)
- {
- SelectObject(DC, FontOld);
- }
- return MenuInfo.Height;
- }
- else
- {
- return DrawMenuBarTemp(Wnd, DC, Rect, Menu, NULL);
- }
-}
-
-/***********************************************************************
- * MenuInitTracking
- */
-static BOOL FASTCALL
-MenuInitTracking(HWND Wnd, HMENU Menu, BOOL Popup, UINT Flags)
-{
- TRACE("Wnd=%p Menu=%p\n", Wnd, Menu);
-
- HideCaret(0);
-
- /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
- if (0 == (Flags & TPM_NONOTIFY))
- {
- SendMessageW(Wnd, WM_ENTERMENULOOP, Popup, 0);
- }
-
- SendMessageW(Wnd, WM_SETCURSOR, (WPARAM) Wnd, HTCAPTION);
-
- if (0 == (Flags & TPM_NONOTIFY))
- {
- ROSMENUINFO MenuInfo;
-
- SendMessageW(Wnd, WM_INITMENU, (WPARAM)Menu, 0);
-
- MenuGetRosMenuInfo(&MenuInfo, Menu);
-
- if (0 == MenuInfo.Height)
- {
- /* app changed/recreated menu bar entries in WM_INITMENU
- Recalculate menu sizes else clicks will not work */
- SetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
- SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
-
- }
- /* This makes the menus of applications built with Delphi work.
- * It also enables menus to be displayed in more than one window,
- * but there are some bugs left that need to be fixed in this case.
- */
- if(MenuInfo.Self == Menu)
- {
- MenuInfo.Wnd = Wnd;
- MenuSetRosMenuInfo(&MenuInfo);
- }
- }
-
- return TRUE;
-}
-
-
-/***********************************************************************
- * MenuShowPopup
- *
- * Display a popup menu.
- */
-static BOOL FASTCALL
-MenuShowPopup(HWND WndOwner, HMENU Menu, UINT Id, UINT flags,
- INT X, INT Y, INT XAnchor, INT YAnchor )
-{
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO ItemInfo;
- UINT Width, Height;
- POINT pt;
- HMONITOR monitor;
- MONITORINFO info;
-
- TRACE("owner=%x hmenu=%x id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
- WndOwner, Menu, Id, X, Y, XAnchor, YAnchor);
-
- if (! MenuGetRosMenuInfo(&MenuInfo, Menu))
- {
- return FALSE;
- }
-
- if (NO_SELECTED_ITEM != MenuInfo.FocusedItem)
- {
- MenuInitRosMenuItemInfo(&ItemInfo);
- if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo))
- {
- ItemInfo.fMask |= MIIM_STATE;
- ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT);
- MenuSetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo);
- }
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- MenuInfo.FocusedItem = NO_SELECTED_ITEM;
- }
-
- /* store the owner for DrawItem */
- MenuInfo.WndOwner = WndOwner;
- MenuSetRosMenuInfo(&MenuInfo);
-
- MenuPopupMenuCalcSize(&MenuInfo, WndOwner);
-
- /* adjust popup menu pos so that it fits within the desktop */
-
- Width = MenuInfo.Width + GetSystemMetrics(SM_CXBORDER);
- Height = MenuInfo.Height + GetSystemMetrics(SM_CYBORDER);
-
- /* FIXME: should use item rect */
- pt.x = X;
- pt.y = Y;
- monitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
- info.cbSize = sizeof(info);
- GetMonitorInfoW( monitor, &info );
-
- if( flags & TPM_RIGHTALIGN ) X -= Width;
- if( flags & TPM_CENTERALIGN ) X -= Width / 2;
-
- if( flags & TPM_BOTTOMALIGN ) Y -= Height;
- if( flags & TPM_VCENTERALIGN ) Y -= Height / 2;
-
- if (X + Width > info.rcWork.right)
- {
- if ( XAnchor && X >= Width - XAnchor)
- X -= Width - XAnchor;
-
- if ( X + Width > info.rcWork.right)
- X = info.rcWork.right - Width;
- }
-
- if ( X < info.rcWork.left ) X = info.rcWork.left;
-
- if (Y + Height > info.rcWork.bottom)
- {
- if ( YAnchor && Y >= Height + YAnchor)
- Y -= Height + YAnchor;
-
- if ( Y + Height > info.rcWork.bottom)
- Y = info.rcWork.bottom - Height;
- }
-
- if ( Y < info.rcWork.top ) Y = info.rcWork.top;
-
- /* NOTE: In Windows, top menu popup is not owned. */
- MenuInfo.Wnd = CreateWindowExW(0, POPUPMENU_CLASS_ATOMW, NULL,
- WS_POPUP, X, Y, Width, Height,
- WndOwner, 0, (HINSTANCE) GetWindowLongPtrW(WndOwner, GWLP_HINSTANCE),
- (LPVOID) MenuInfo.Self);
- if (NULL == MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo))
- {
- return FALSE;
- }
- if (NULL == TopPopup)
- {
- TopPopup = MenuInfo.Wnd;
- }
-
- /* Display the window */
- SetWindowPos(MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
- SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
- UpdateWindow(MenuInfo.Wnd);
-
- return TRUE;
-}
-
-/***********************************************************************
- * MenuFindSubMenu
- *
- * Find a Sub menu. Return the position of the submenu, and modifies
- * *hmenu in case it is found in another sub-menu.
- * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
- */
-static UINT FASTCALL
-MenuFindSubMenu(HMENU *Menu, HMENU SubTarget)
-{
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO ItemInfo;
- UINT i;
- HMENU SubMenu;
- UINT Pos;
-
- if ((HMENU) 0xffff == *Menu
- || ! MenuGetRosMenuInfo(&MenuInfo, *Menu))
- {
- return NO_SELECTED_ITEM;
- }
-
- MenuInitRosMenuItemInfo(&ItemInfo);
- for (i = 0; i < MenuInfo.MenuItemCount; i++)
- {
- if (! MenuGetRosMenuItemInfo(MenuInfo.Self, i, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return NO_SELECTED_ITEM;
- }
- if (0 == (ItemInfo.fType & MF_POPUP))
- {
- continue;
- }
- if (ItemInfo.hSubMenu == SubTarget)
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return i;
- }
- SubMenu = ItemInfo.hSubMenu;
- Pos = MenuFindSubMenu(&SubMenu, SubTarget);
- if (NO_SELECTED_ITEM != Pos)
- {
- *Menu = SubMenu;
- return Pos;
- }
- }
- MenuCleanupRosMenuItemInfo(&ItemInfo);
-
- return NO_SELECTED_ITEM;
-}
-
-/***********************************************************************
- * MenuSelectItem
- */
-static void FASTCALL
-MenuSelectItem(HWND WndOwner, PROSMENUINFO MenuInfo, UINT Index,
- BOOL SendMenuSelect, HMENU TopMenu)
-{
- HDC Dc;
- ROSMENUITEMINFO ItemInfo;
- ROSMENUINFO TopMenuInfo;
- int Pos;
-
- TRACE("owner=%x menu=%p index=0x%04x select=0x%04x\n", WndOwner, MenuInfo, Index, SendMenuSelect);
-
- if (NULL == MenuInfo || 0 == MenuInfo->MenuItemCount || NULL == MenuInfo->Wnd)
- {
- return;
- }
-
- if (MenuInfo->FocusedItem == Index)
- {
- return;
- }
-
- if (0 != (MenuInfo->Flags & MF_POPUP))
- {
- Dc = GetDC(MenuInfo->Wnd);
- }
- else
- {
- Dc = GetDCEx(MenuInfo->Wnd, 0, DCX_CACHE | DCX_WINDOW);
- }
-
- if (NULL == TopPopup)
- {
- TopPopup = MenuInfo->Wnd;
- }
-
- SelectObject(Dc, hMenuFont);
- MenuInitRosMenuItemInfo(&ItemInfo);
- /* Clear previous highlighted item */
- if (NO_SELECTED_ITEM != MenuInfo->FocusedItem)
- {
- if (MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo))
- {
- ItemInfo.fMask |= MIIM_STATE;
- ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT);
- MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo);
- }
- MenuDrawMenuItem(MenuInfo->Wnd, MenuInfo, WndOwner, Dc, &ItemInfo,
- MenuInfo->Height, ! (MenuInfo->Flags & MF_POPUP),
- ODA_SELECT);
- }
-
- /* Highlight new item (if any) */
- MenuInfo->FocusedItem = Index;
- MenuSetRosMenuInfo(MenuInfo);
- if (NO_SELECTED_ITEM != MenuInfo->FocusedItem)
- {
- if (MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo))
- {
- if (0 == (ItemInfo.fType & MF_SEPARATOR))
- {
- ItemInfo.fMask |= MIIM_STATE;
- ItemInfo.fState |= MF_HILITE;
- MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo);
- MenuDrawMenuItem(MenuInfo->Wnd, MenuInfo, WndOwner, Dc,
- &ItemInfo, MenuInfo->Height, ! (MenuInfo->Flags & MF_POPUP),
- ODA_SELECT);
- }
- if (SendMenuSelect)
- {
- SendMessageW(WndOwner, WM_MENUSELECT,
- MAKELONG(ItemInfo.fType & MF_POPUP ? Index : ItemInfo.wID,
- ItemInfo.fType | ItemInfo.fState | MF_MOUSESELECT |
- (MenuInfo->Flags & MF_SYSMENU)), (LPARAM) MenuInfo->Self);
- }
- }
- }
- else if (SendMenuSelect)
- {
- if (NULL != TopMenu)
- {
- Pos = MenuFindSubMenu(&TopMenu, MenuInfo->Self);
- if (NO_SELECTED_ITEM != Pos)
- {
- if (MenuGetRosMenuInfo(&TopMenuInfo, TopMenu)
- && MenuGetRosMenuItemInfo(TopMenu, Pos, &ItemInfo))
- {
- SendMessageW(WndOwner, WM_MENUSELECT,
- MAKELONG(Pos, ItemInfo.fType | ItemInfo.fState
- | MF_MOUSESELECT
- | (TopMenuInfo.Flags & MF_SYSMENU)),
- (LPARAM) TopMenu);
- }
- }
- }
- }
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- ReleaseDC(MenuInfo->Wnd, Dc);
-}
-
-/***********************************************************************
- * MenuMoveSelection
- *
- * Moves currently selected item according to the Offset parameter.
- * If there is no selection then it should select the last item if
- * Offset is ITEM_PREV or the first item if Offset is ITEM_NEXT.
- */
-static void FASTCALL
-MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset)
-{
- INT i;
- ROSMENUITEMINFO ItemInfo;
- INT OrigPos;
-
- TRACE("hwnd=%x menu=%x off=0x%04x\n", WndOwner, MenuInfo, Offset);
-
- /* Prevent looping */
- if (0 == MenuInfo->MenuItemCount || 0 == Offset)
- return;
- else if (Offset < -1)
- Offset = -1;
- else if (Offset > 1)
- Offset = 1;
-
- MenuInitRosMenuItemInfo(&ItemInfo);
-
- OrigPos = MenuInfo->FocusedItem;
- if (OrigPos == NO_SELECTED_ITEM) /* NO_SELECTED_ITEM is not -1 ! */
- {
- OrigPos = 0;
- i = -1;
- }
- else
- {
- i = MenuInfo->FocusedItem;
- }
-
- do
- {
- /* Step */
- i += Offset;
- /* Clip and wrap around */
- if (i < 0)
- {
- i = MenuInfo->MenuItemCount - 1;
- }
- else if (i >= MenuInfo->MenuItemCount)
- {
- i = 0;
- }
- /* If this is a good candidate; */
- if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) &&
- 0 == (ItemInfo.fType & MF_SEPARATOR))
- {
- MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL);
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return;
- }
- } while (i != OrigPos);
-
- /* Not found */
- MenuCleanupRosMenuItemInfo(&ItemInfo);
-}
-
-/***********************************************************************
- * MenuInitSysMenuPopup
- *
- * Grey the appropriate items in System menu.
- */
-void FASTCALL
-MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest )
-{
- BOOL Gray;
- UINT DefItem;
- #if 0
- MENUITEMINFOW mii;
- #endif
-
- Gray = 0 == (Style & WS_THICKFRAME) || 0 != (Style & (WS_MAXIMIZE | WS_MINIMIZE));
- EnableMenuItem(Menu, SC_SIZE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 != (Style & WS_MAXIMIZE);
- EnableMenuItem(Menu, SC_MOVE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 == (Style & WS_MINIMIZEBOX) || 0 != (Style & WS_MINIMIZE);
- EnableMenuItem(Menu, SC_MINIMIZE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 == (Style & WS_MAXIMIZEBOX) || 0 != (Style & WS_MAXIMIZE);
- EnableMenuItem(Menu, SC_MAXIMIZE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 == (Style & (WS_MAXIMIZE | WS_MINIMIZE));
- EnableMenuItem(Menu, SC_RESTORE, (Gray ? MF_GRAYED : MF_ENABLED));
- Gray = 0 != (ClsStyle & CS_NOCLOSE);
-
- /* The menu item must keep its state if it's disabled */
- if (Gray)
- {
- EnableMenuItem(Menu, SC_CLOSE, MF_GRAYED);
- }
-
- /* Set default menu item */
- if(Style & WS_MINIMIZE)
- {
- DefItem = SC_RESTORE;
- }
- else
- {
- if(HitTest == HTCAPTION)
- {
- DefItem = ((Style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE);
- }
- else
- {
- DefItem = SC_CLOSE;
- }
- }
- #if 0
- mii.cbSize = sizeof(MENUITEMINFOW);
- mii.fMask |= MIIM_STATE;
- if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) &&
- (mii.fState & (MFS_GRAYED | MFS_DISABLED)))
- {
- DefItem = SC_CLOSE;
- }
- #endif
- SetMenuDefaultItem(Menu, DefItem, MF_BYCOMMAND);
-}
-
/***********************************************************************
* MenuShowSubPopup
*
@@ -2452,7 +2367,7 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SendMenuSelect)
TRACE("owner=%x menu=%x 0x%04x\n", WndOwner, MenuInfo, SendMenuSelect);
- if (NULL != MenuInfo && NULL != TopPopup && NO_SELECTED_ITEM != MenuInfo->FocusedItem)
+ if (NULL != MenuInfo && NULL != top_popup && NO_SELECTED_ITEM != MenuInfo->FocusedItem)
{
MenuInitRosMenuItemInfo(&ItemInfo);
ItemInfo.fMask |= MIIM_FTYPE | MIIM_STATE;
@@ -2809,86 +2724,6 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
return TRUE;
}
-/******************************************************************************
- *
- * UINT MenuGetStartOfNextColumn(PROSMENUINFO MenuInfo)
- */
-static UINT MenuGetStartOfNextColumn(PROSMENUINFO MenuInfo)
-{
- UINT i;
- PROSMENUITEMINFO MenuItems;
-
- i = MenuInfo->FocusedItem;
- if (NO_SELECTED_ITEM == i)
- {
- return i;
- }
-
- if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
- {
- return NO_SELECTED_ITEM;
- }
-
- for (i++ ; i < MenuInfo->MenuItemCount; i++)
- {
- if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
- {
- return i;
- }
- }
-
- return NO_SELECTED_ITEM;
-}
-
-/******************************************************************************
- *
- * UINT MenuGetStartOfPrevColumn(PROSMENUINFO MenuInfo)
- */
-static UINT FASTCALL
-MenuGetStartOfPrevColumn(PROSMENUINFO MenuInfo)
-{
- UINT i;
- PROSMENUITEMINFO MenuItems;
-
- if (0 == MenuInfo->FocusedItem || NO_SELECTED_ITEM == MenuInfo->FocusedItem)
- {
- return NO_SELECTED_ITEM;
- }
-
- if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
- {
- return NO_SELECTED_ITEM;
- }
-
- /* Find the start of the column */
-
- for (i = MenuInfo->FocusedItem;
- 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
- --i)
- {
- ; /* empty */
- }
-
- if (0 == i)
- {
- MenuCleanupAllRosMenuItemInfo(MenuItems);
- return NO_SELECTED_ITEM;
- }
-
- for (--i; 0 != i; --i)
- {
- if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
- {
- break;
- }
- }
-
- MenuCleanupAllRosMenuItemInfo(MenuItems);
- TRACE("ret %d.\n", i );
-
- return i;
-}
-
/***********************************************************************
* MenuGetSubPopup
*
@@ -3202,36 +3037,29 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags)
*
* Handle a VK_RIGHT key event in a menu.
*/
-static void FASTCALL
-MenuKeyRight(MTRACKER *Mt, UINT Flags)
+static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags)
{
- HMENU MenuTmp;
- ROSMENUINFO MenuInfo;
- ROSMENUINFO CurrentMenuInfo;
- UINT NextCol;
+ HMENU hmenutmp;
+ ROSMENUINFO MenuInfo;
+ ROSMENUINFO CurrentMenuInfo;
+ UINT NextCol;
- TRACE("MenuKeyRight called, cur %p, top %p.\n",
+ TRACE("MenuKeyRight called, cur %p, top %p.\n",
Mt->CurrentMenu, Mt->TopMenu);
- if (! MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu))
- {
- return;
- }
- if (0 != (MenuInfo.Flags & MF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu))
+ if (! MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu)) return;
+ if ((MenuInfo.Flags & MF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu))
{
/* If already displaying a popup, try to display sub-popup */
- MenuTmp = Mt->CurrentMenu;
+ hmenutmp = Mt->CurrentMenu;
if (MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu))
{
Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &CurrentMenuInfo, TRUE, Flags);
}
/* if subpopup was displayed then we are done */
- if (MenuTmp != Mt->CurrentMenu)
- {
- return;
- }
+ if (hmenutmp != Mt->CurrentMenu) return;
}
if (! MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu))
@@ -3255,20 +3083,18 @@ MenuKeyRight(MTRACKER *Mt, UINT Flags)
if (Mt->CurrentMenu != Mt->TopMenu)
{
MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE );
- MenuTmp = Mt->CurrentMenu = Mt->TopMenu;
+ hmenutmp = Mt->CurrentMenu = Mt->TopMenu;
}
else
{
- MenuTmp = NULL;
+ hmenutmp = NULL;
}
/* try to move to the next item */
- if (! MenuDoNextMenu(Mt, VK_RIGHT))
- {
+ if ( !MenuDoNextMenu(Mt, VK_RIGHT))
MenuMoveSelection(Mt->OwnerWnd, &MenuInfo, ITEM_NEXT);
- }
- if (NULL != MenuTmp || 0 != (Mt->TrackFlags & TF_SUSPENDPOPUP))
+ if ( hmenutmp || Mt->TrackFlags & TF_SUSPENDPOPUP )
{
if (! MenuSuspendPopup(Mt, WM_KEYDOWN)
&& MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu))
@@ -3280,525 +3106,466 @@ MenuKeyRight(MTRACKER *Mt, UINT Flags)
}
}
-/***********************************************************************
- * MenuFindItemByKey
- *
- * Find the menu item selected by a key press.
- * Return item id, -1 if none, -2 if we should close the menu.
- */
-static UINT FASTCALL
-MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
- WCHAR Key, BOOL ForceMenuChar)
-{
- ROSMENUINFO SysMenuInfo;
- PROSMENUITEMINFO Items, ItemInfo;
- LRESULT MenuChar;
- UINT i;
-
- TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
-
- if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self))
- {
- if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE)))
- {
- MenuInfo = &SysMenuInfo;
- }
- else
- {
- MenuInfo = NULL;
- }
- }
-
- if (NULL != MenuInfo)
- {
- if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0)
- {
- return -1;
- }
- if (! ForceMenuChar)
- {
- Key = toupperW(Key);
- ItemInfo = Items;
- for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++)
- {
- if ((ItemInfo->Text) && NULL != ItemInfo->dwTypeData)
- {
- WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
- do
- {
- p = strchrW(p + 2, '&');
- }
- while (NULL != p && L'&' == p[1]);
- if (NULL != p && (toupperW(p[1]) == Key))
- {
- return i;
- }
- }
- }
- }
-
- MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
- MAKEWPARAM(Key, MenuInfo->Flags), (LPARAM) MenuInfo->Self);
- if (2 == HIWORD(MenuChar))
- {
- return LOWORD(MenuChar);
- }
- if (1 == HIWORD(MenuChar))
- {
- return (UINT) (-2);
- }
- }
-
- return (UINT)(-1);
-}
-
/***********************************************************************
* MenuTrackMenu
*
* Menu tracking code.
*/
-static INT FASTCALL
-MenuTrackMenu(HMENU Menu, UINT Flags, INT x, INT y,
- HWND Wnd, const RECT *Rect )
+static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
+ HWND hwnd, const RECT *lprect )
{
- MSG Msg;
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO ItemInfo;
- BOOL fRemove;
- INT ExecutedMenuId = -1;
- MTRACKER Mt;
- BOOL EnterIdleSent = FALSE;
+ MSG msg;
+ ROSMENUINFO MenuInfo;
+ ROSMENUITEMINFO ItemInfo;
+ BOOL fRemove;
+ INT executedMenuId = -1;
+ MTRACKER mt;
+ BOOL enterIdleSent = FALSE;
- Mt.TrackFlags = 0;
- Mt.CurrentMenu = Menu;
- Mt.TopMenu = Menu;
- Mt.OwnerWnd = Wnd;
- Mt.Pt.x = x;
- Mt.Pt.y = y;
+ mt.TrackFlags = 0;
+ mt.CurrentMenu = hmenu;
+ mt.TopMenu = hmenu;
+ mt.OwnerWnd = hwnd;
+ mt.Pt.x = x;
+ mt.Pt.y = y;
- TRACE("Menu=%x Flags=0x%08x (%d,%d) Wnd=%x (%ld,%ld)-(%ld,%ld)\n",
- Menu, Flags, x, y, Wnd, Rect ? Rect->left : 0, Rect ? Rect->top : 0,
- Rect ? Rect->right : 0, Rect ? Rect->bottom : 0);
+ TRACE("hmenu=%p flags=0x%08x (%d,%d) hwnd=%x (%ld,%ld)-(%ld,%ld)\n",
+ hmenu, wFlags, x, y, hwnd, lprect ? lprect->left : 0, lprect ? lprect->top : 0,
+ lprect ? lprect->right : 0, lprect ? lprect->bottom : 0);
- if (!IsMenu(Menu))
- {
- SetLastError( ERROR_INVALID_MENU_HANDLE );
- return FALSE;
- }
-
- fEndMenu = FALSE;
- if (! MenuGetRosMenuInfo(&MenuInfo, Menu))
+ if (!IsMenu(hmenu))
{
- return FALSE;
+ SetLastError( ERROR_INVALID_MENU_HANDLE );
+ return FALSE;
}
- if (0 != (Flags & TPM_BUTTONDOWN))
+ fEndMenu = FALSE;
+ if (! MenuGetRosMenuInfo(&MenuInfo, hmenu))
{
- /* Get the result in order to start the tracking or not */
- fRemove = MenuButtonDown(&Mt, Menu, Flags);
- fEndMenu = ! fRemove;
+ return FALSE;
}
- SetCapture(Mt.OwnerWnd);
- (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, Mt.OwnerWnd);
-
- ERR("MenuTrackMenu 1\n");
- while (! fEndMenu)
+ if (wFlags & TPM_BUTTONDOWN)
{
- PVOID menu = ValidateHandle(Mt.CurrentMenu, VALIDATE_TYPE_MENU);
- if (!menu) /* sometimes happens if I do a window manager close */
- break;
+ /* Get the result in order to start the tracking or not */
+ fRemove = MenuButtonDown( &mt, hmenu, wFlags );
+ fEndMenu = !fRemove;
+ }
- /* we have to keep the message in the queue until it's
- * clear that menu loop is not over yet. */
+ SetCapture(mt.OwnerWnd);
+ (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, mt.OwnerWnd);
- for (;;)
+ ERR("MenuTrackMenu 1\n");
+ while (! fEndMenu)
+ {
+ PVOID menu = ValidateHandle(mt.CurrentMenu, VALIDATE_TYPE_MENU);
+ if (!menu) /* sometimes happens if I do a window manager close */
+ break;
+
+ /* we have to keep the message in the queue until it's
+ * clear that menu loop is not over yet. */
+
+ for (;;)
{
- if (PeekMessageW(&Msg, 0, 0, 0, PM_NOREMOVE))
+ if (PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE ))
{
- if (! CallMsgFilterW(&Msg, MSGF_MENU))
- {
- break;
- }
- /* remove the message from the queue */
- PeekMessageW(&Msg, 0, Msg.message, Msg.message, PM_REMOVE );
+ if (!CallMsgFilterW( &msg, MSGF_MENU )) break;
+ /* remove the message from the queue */
+ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
}
- else
+ else
{
- if (! EnterIdleSent)
+ if (!enterIdleSent)
{
- HWND Win = (0 != (Flags & TPM_ENTERIDLEEX)
- && 0 != (MenuInfo.Flags & MF_POPUP)) ? MenuInfo.Wnd : NULL;
- EnterIdleSent = TRUE;
- SendMessageW(Mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) Win);
+ HWND win = (wFlags & TPM_ENTERIDLEEX) && (MenuInfo.Flags & MF_POPUP) ? MenuInfo.Wnd : NULL;
+ enterIdleSent = TRUE;
+ SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win);
}
- WaitMessage();
+ WaitMessage();
}
}
- /* check if EndMenu() tried to cancel us, by posting this message */
- if (WM_CANCELMODE == Msg.message)
+ /* check if EndMenu() tried to cancel us, by posting this message */
+ if (msg.message == WM_CANCELMODE)
{
- /* we are now out of the loop */
- fEndMenu = TRUE;
+ /* we are now out of the loop */
+ fEndMenu = TRUE;
- /* remove the message from the queue */
- PeekMessageW(&Msg, 0, Msg.message, Msg.message, PM_REMOVE);
+ /* remove the message from the queue */
+ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
- /* break out of internal loop, ala ESCAPE */
- break;
+ /* break out of internal loop, ala ESCAPE */
+ break;
}
- TranslateMessage(&Msg);
- Mt.Pt = Msg.pt;
+ TranslateMessage( &msg );
+ mt.Pt = msg.pt;
- if (Msg.hwnd == MenuInfo.Wnd || WM_TIMER != Msg.message)
+ if ( (msg.hwnd == MenuInfo.Wnd) || (msg.message!=WM_TIMER) )
+ enterIdleSent=FALSE;
+
+ fRemove = FALSE;
+ if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
{
- EnterIdleSent = FALSE;
- }
+ /*
+ * Use the mouse coordinates in lParam instead of those in the MSG
+ * struct to properly handle synthetic messages. They are already
+ * in screen coordinates.
+ */
+ mt.Pt.x = (short)LOWORD(msg.lParam);
+ mt.Pt.y = (short)HIWORD(msg.lParam);
- fRemove = FALSE;
- if (WM_MOUSEFIRST <= Msg.message && Msg.message <= WM_MOUSELAST)
- {
- /*
- * Use the mouse coordinates in lParam instead of those in the MSG
- * struct to properly handle synthetic messages. They are already
- * in screen coordinates.
- */
- Mt.Pt.x = (short) LOWORD(Msg.lParam);
- Mt.Pt.y = (short) HIWORD(Msg.lParam);
+ /* Find a menu for this mouse event */
+ hmenu = MenuPtMenu(mt.TopMenu, mt.Pt);
- /* Find a menu for this mouse event */
- Menu = MenuPtMenu(Mt.TopMenu, Mt.Pt);
-
- switch(Msg.message)
+ switch(msg.message)
{
- /* no WM_NC... messages in captured state */
+ /* no WM_NC... messages in captured state */
- case WM_RBUTTONDBLCLK:
- case WM_RBUTTONDOWN:
- if (0 == (Flags & TPM_RIGHTBUTTON))
- {
+ case WM_RBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ if (!(wFlags & TPM_RIGHTBUTTON)) break;
+ /* fall through */
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONDOWN:
+ /* If the message belongs to the menu, removes it from the queue */
+ /* Else, end menu tracking */
+ fRemove = MenuButtonDown(&mt, hmenu, wFlags);
+ fEndMenu = !fRemove;
break;
- }
- /* fall through */
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- /* If the message belongs to the menu, removes it from the queue */
- /* Else, end menu tracking */
- fRemove = MenuButtonDown(&Mt, Menu, Flags);
- fEndMenu = ! fRemove;
- break;
- case WM_RBUTTONUP:
- if (0 == (Flags & TPM_RIGHTBUTTON))
- {
- break;
- }
- /* fall through */
- case WM_LBUTTONUP:
- /* Check if a menu was selected by the mouse */
- if (NULL != Menu)
- {
- ExecutedMenuId = MenuButtonUp(&Mt, Menu, Flags);
+ case WM_RBUTTONUP:
+ if (!(wFlags & TPM_RIGHTBUTTON)) break;
+ /* fall through */
+ case WM_LBUTTONUP:
+ /* Check if a menu was selected by the mouse */
+ if (hmenu)
+ {
+ executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
- /* End the loop if ExecutedMenuId is an item ID */
- /* or if the job was done (ExecutedMenuId = 0). */
- fEndMenu = fRemove = (-1 != ExecutedMenuId);
- }
- else
- {
+ /* End the loop if executedMenuId is an item ID */
+ /* or if the job was done (executedMenuId = 0). */
+ fEndMenu = fRemove = (executedMenuId != -1);
+ }
/* No menu was selected by the mouse */
/* if the function was called by TrackPopupMenu, continue
with the menu tracking. If not, stop it */
- fEndMenu = (0 != (Flags & TPM_POPUPMENU) ? FALSE : TRUE);
- }
- break;
+ else
+ fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
- case WM_MOUSEMOVE:
- if (Menu)
- {
- fEndMenu |= ! MenuMouseMove(&Mt, Menu, Flags);
- }
- break;
+ break;
- } /* switch(Msg.message) - mouse */
- }
- else if (WM_KEYFIRST <= Msg.message && Msg.message <= WM_KEYLAST)
- {
- fRemove = TRUE; /* Keyboard messages are always removed */
- switch(Msg.message)
+ case WM_MOUSEMOVE:
+ /* the selected menu item must be changed every time */
+ /* the mouse moves. */
+
+ if (hmenu)
+ fEndMenu |= !MenuMouseMove( &mt, hmenu, wFlags );
+ break;
+
+ } /* switch(msg.message) - mouse */
+ }
+ else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
+ {
+ fRemove = TRUE; /* Keyboard messages are always removed */
+ switch(msg.message)
{
- case WM_SYSKEYDOWN:
- case WM_KEYDOWN:
- switch(Msg.wParam)
- {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ switch(msg.wParam)
+ {
case VK_MENU:
- fEndMenu = TRUE;
- break;
+ case VK_F10:
+ fEndMenu = TRUE;
+ break;
+
case VK_HOME:
case VK_END:
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
{
- MenuSelectItem(Mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM,
- FALSE, 0 );
- MenuMoveSelection(Mt.OwnerWnd, &MenuInfo,
- VK_HOME == Msg.wParam ? ITEM_NEXT : ITEM_PREV);
+ MenuSelectItem(mt.OwnerWnd, &MenuInfo,
+ NO_SELECTED_ITEM, FALSE, 0 );
+ MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
+ VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
}
- break;
+ break;
case VK_UP:
case VK_DOWN: /* If on menu bar, pull-down the menu */
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
{
- if (0 == (MenuInfo.Flags & MF_POPUP))
+ if (!(MenuInfo.Flags & MF_POPUP))
{
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.TopMenu))
- {
- Mt.CurrentMenu = MenuShowSubPopup(Mt.OwnerWnd, &MenuInfo,
- TRUE, Flags);
- }
- }
- else /* otherwise try to move selection */
- {
- MenuMoveSelection(Mt.OwnerWnd, &MenuInfo,
- VK_DOWN == Msg.wParam ? ITEM_NEXT : ITEM_PREV);
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
+ mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags);
}
+ else /* otherwise try to move selection */
+ MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
+ (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
}
- break;
+ break;
case VK_LEFT:
- MenuKeyLeft(&Mt, Flags);
- break;
+ MenuKeyLeft( &mt, wFlags );
+ break;
case VK_RIGHT:
- MenuKeyRight(&Mt, Flags);
- break;
+ MenuKeyRight( &mt, wFlags );
+ break;
case VK_ESCAPE:
- fEndMenu = MenuKeyEscape(&Mt, Flags);
- break;
+ fEndMenu = MenuKeyEscape(&mt, wFlags);
+ break;
case VK_F1:
- {
+ {
HELPINFO hi;
hi.cbSize = sizeof(HELPINFO);
hi.iContextType = HELPINFO_MENUITEM;
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
- {
- if (NO_SELECTED_ITEM == MenuInfo.FocusedItem)
- {
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
+ {
+ if (MenuInfo.FocusedItem == NO_SELECTED_ITEM)
hi.iCtrlId = 0;
- }
else
- {
+ {
MenuInitRosMenuItemInfo(&ItemInfo);
if (MenuGetRosMenuItemInfo(MenuInfo.Self,
MenuInfo.FocusedItem,
&ItemInfo))
- {
+ {
hi.iCtrlId = ItemInfo.wID;
- }
+ }
else
- {
+ {
hi.iCtrlId = 0;
- }
+ }
MenuCleanupRosMenuItemInfo(&ItemInfo);
- }
- }
- hi.hItemHandle = Menu;
- hi.dwContextId = MenuInfo.dwContextHelpID;
- hi.MousePos = Msg.pt;
- SendMessageW(Wnd, WM_HELP, 0, (LPARAM) &hi);
+ }
+ }
+ hi.hItemHandle = hmenu;
+ hi.dwContextId = MenuInfo.dwContextHelpID;
+ hi.MousePos = msg.pt;
+ SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi);
break;
- }
+ }
default:
- break;
- }
+ break;
+ }
break; /* WM_KEYDOWN */
- case WM_CHAR:
- case WM_SYSCHAR:
+ case WM_CHAR:
+ case WM_SYSCHAR:
{
- UINT Pos;
+ UINT pos;
- if (! MenuGetRosMenuInfo(&MenuInfo, Mt.CurrentMenu))
+ if (! MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) break;
+ if (msg.wParam == L'\r' || msg.wParam == L' ')
{
- break;
- }
- if (L'\r' == Msg.wParam || L' ' == Msg.wParam)
- {
- ExecutedMenuId = MenuExecFocusedItem(&Mt, &MenuInfo, Flags);
- fEndMenu = (ExecutedMenuId != -2);
- break;
+ executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags);
+ fEndMenu = (executedMenuId != -2);
+ break;
}
- /* Hack to avoid control chars. */
- /* We will find a better way real soon... */
- if (Msg.wParam < 32)
- {
- break;
- }
+ /* Hack to avoid control chars. */
+ /* We will find a better way real soon... */
+ if (msg.wParam < 32) break;
- Pos = MenuFindItemByKey(Mt.OwnerWnd, &MenuInfo,
- LOWORD(Msg.wParam), FALSE);
- if ((UINT) -2 == Pos)
+ pos = MenuFindItemByKey(mt.OwnerWnd, &MenuInfo,
+ LOWORD(msg.wParam), FALSE);
+ if (pos == (UINT)-2) fEndMenu = TRUE;
+ else if (pos == (UINT)-1) MessageBeep(0);
+ else
{
- fEndMenu = TRUE;
+ MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos,
+ TRUE, 0);
+ executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags);
+ fEndMenu = (executedMenuId != -2);
}
- else if ((UINT) -1 == Pos)
- {
- MessageBeep(0);
- }
- else
- {
- MenuSelectItem(Mt.OwnerWnd, &MenuInfo, Pos, TRUE, 0);
- ExecutedMenuId = MenuExecFocusedItem(&Mt, &MenuInfo, Flags);
- fEndMenu = (-2 != ExecutedMenuId);
- }
- }
- break;
+ }
+ break;
} /* switch(msg.message) - kbd */
}
- else
+ else
{
- PeekMessageW( &Msg, 0, Msg.message, Msg.message, PM_REMOVE );
- DispatchMessageW(&Msg);
- continue;
+ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
+ DispatchMessageW( &msg );
+ continue;
}
- if (! fEndMenu)
- {
- fRemove = TRUE;
- }
+ if (!fEndMenu) fRemove = TRUE;
- /* finally remove message from the queue */
+ /* finally remove message from the queue */
- if (fRemove && 0 == (Mt.TrackFlags & TF_SKIPREMOVE))
- {
- PeekMessageW(&Msg, 0, Msg.message, Msg.message, PM_REMOVE);
- }
- else
- {
- Mt.TrackFlags &= ~TF_SKIPREMOVE;
- }
+ if (fRemove && !(mt.TrackFlags & TF_SKIPREMOVE) )
+ PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
+ else mt.TrackFlags &= ~TF_SKIPREMOVE;
}
- ERR("MenuTrackMenu 2\n");
- (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
- SetCapture(NULL); /* release the capture */
+ (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
+ SetCapture(NULL); /* release the capture */
- /* If dropdown is still painted and the close box is clicked on
- then the menu will be destroyed as part of the DispatchMessage above.
- This will then invalidate the menu handle in Mt.hTopMenu. We should
- check for this first. */
- if (IsMenu(Mt.TopMenu))
+ /* If dropdown is still painted and the close box is clicked on
+ then the menu will be destroyed as part of the DispatchMessage above.
+ This will then invalidate the menu handle in mt.hTopMenu. We should
+ check for this first. */
+ if( IsMenu( mt.TopMenu ) )
{
- if (IsWindow(Mt.OwnerWnd))
+ if (IsWindow(mt.OwnerWnd))
{
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.TopMenu))
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
{
- MenuHideSubPopups(Mt.OwnerWnd, &MenuInfo, FALSE);
+ MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE);
- if (0 != (MenuInfo.Flags & MF_POPUP))
+ if (MenuInfo.Flags & MF_POPUP)
{
- DestroyWindow(MenuInfo.Wnd);
- MenuInfo.Wnd = NULL;
+ DestroyWindow(MenuInfo.Wnd);
+ MenuInfo.Wnd = NULL;
- if (!(MenuInfo.Flags & TPM_NONOTIFY))
- SendMessageW( Mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)Mt.TopMenu,
+ if (!(MenuInfo.Flags & TPM_NONOTIFY))
+ SendMessageW( mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)mt.TopMenu,
MAKELPARAM(0, IS_SYSTEM_MENU(&MenuInfo)) );
}
- MenuSelectItem(Mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, NULL);
+ MenuSelectItem( mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 );
}
- SendMessageW(Mt.OwnerWnd, WM_MENUSELECT, MAKELONG(0, 0xffff), 0);
+ SendMessageW( mt.OwnerWnd, WM_MENUSELECT, MAKEWPARAM(0, 0xffff), 0 );
}
- if (MenuGetRosMenuInfo(&MenuInfo, Mt.TopMenu))
+ /* Reset the variable for hiding menu */
+ if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
{
- /* Reset the variable for hiding menu */
- MenuInfo.TimeToHide = FALSE;
- MenuSetRosMenuInfo(&MenuInfo);
+ MenuInfo.TimeToHide = FALSE;
+ MenuSetRosMenuInfo(&MenuInfo);
}
}
- /* The return value is only used by TrackPopupMenu */
- if (!(Flags & TPM_RETURNCMD)) return TRUE;
- if (ExecutedMenuId < 0) ExecutedMenuId = 0;
- return ExecutedMenuId;
+ /* The return value is only used by TrackPopupMenu */
+ if (!(wFlags & TPM_RETURNCMD)) return TRUE;
+ if (executedMenuId == -1) executedMenuId = 0;
+ return executedMenuId;
}
+/***********************************************************************
+ * MenuInitTracking
+ */
+static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
+{
+ ROSMENUINFO MenuInfo;
+
+ TRACE("hwnd=%p hmenu=%p\n", hWnd, hMenu);
+
+ HideCaret(0);
+
+ /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
+ if (!(wFlags & TPM_NONOTIFY))
+ SendMessageW( hWnd, WM_ENTERMENULOOP, bPopup, 0 );
+
+ SendMessageW( hWnd, WM_SETCURSOR, (WPARAM)hWnd, HTCAPTION );
+
+ if (!(wFlags & TPM_NONOTIFY))
+ {
+ SendMessageW( hWnd, WM_INITMENU, (WPARAM)hMenu, 0 );
+
+ MenuGetRosMenuInfo(&MenuInfo, hMenu);
+
+ if (!MenuInfo.Height)
+ {
+ /* app changed/recreated menu bar entries in WM_INITMENU
+ Recalculate menu sizes else clicks will not work */
+ SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+
+ }
+ /* This makes the menus of applications built with Delphi work.
+ * It also enables menus to be displayed in more than one window,
+ * but there are some bugs left that need to be fixed in this case.
+ */
+ if(MenuInfo.Self == hMenu)
+ {
+ MenuInfo.Wnd = hWnd;
+ MenuSetRosMenuInfo(&MenuInfo);
+ }
+ }
+
+ return TRUE;
+}
/***********************************************************************
* MenuExitTracking
*/
-static BOOL FASTCALL
-MenuExitTracking(HWND Wnd)
+static BOOL FASTCALL MenuExitTracking(HWND hWnd)
{
- TRACE("hwnd=%p\n", Wnd);
+ TRACE("hwnd=%p\n", hWnd);
- SendMessageW(Wnd, WM_EXITMENULOOP, 0, 0);
- ShowCaret(0);
- return TRUE;
+ SendMessageW( hWnd, WM_EXITMENULOOP, 0, 0 );
+ ShowCaret(0);
+ top_popup = 0;
+ return TRUE;
}
-
-VOID
-MenuTrackMouseMenuBar(HWND Wnd, ULONG Ht, POINT Pt)
+/***********************************************************************
+ * MenuTrackMouseMenuBar
+ *
+ * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
+ */
+VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt)
{
- HMENU Menu = (HTSYSMENU == Ht) ? NtUserGetSystemMenu(Wnd, FALSE) : GetMenu(Wnd);
- UINT Flags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
+ HMENU hMenu = (ht == HTSYSMENU) ? NtUserGetSystemMenu( hWnd, FALSE) : GetMenu(hWnd);
+ UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
- TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", Wnd, Ht, Pt.x, Pt.y);
+ TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y);
- if (IsMenu(Menu))
+ if (IsMenu(hMenu))
{
- /* map point to parent client coordinates */
- HWND Parent = GetAncestor(Wnd, GA_PARENT );
- if (Parent != GetDesktopWindow())
+ /* map point to parent client coordinates */
+ HWND Parent = GetAncestor(hWnd, GA_PARENT );
+ if (Parent != GetDesktopWindow())
{
- ScreenToClient(Parent, &Pt);
+ ScreenToClient(Parent, &pt);
}
- MenuInitTracking(Wnd, Menu, FALSE, Flags);
- MenuTrackMenu(Menu, Flags, Pt.x, Pt.y, Wnd, NULL);
- MenuExitTracking(Wnd);
+ MenuInitTracking(hWnd, hMenu, FALSE, wFlags);
+ MenuTrackMenu(hMenu, wFlags, pt.x, pt.y, hWnd, NULL);
+ MenuExitTracking(hWnd);
}
}
-VOID
-MenuTrackKbdMenuBar(HWND hWnd, UINT wParam, WCHAR wChar)
+/***********************************************************************
+ * MenuTrackKbdMenuBar
+ *
+ * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
+ */
+VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar)
{
UINT uItem = NO_SELECTED_ITEM;
HMENU hTrackMenu;
ROSMENUINFO MenuInfo;
UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON;
- TRACE("hwnd %p wParam 0x%04x wChar 0x%04x\n", hWnd, wParam, wChar);
+ TRACE("hwnd %p wParam 0x%04x wChar 0x%04x\n", hwnd, wParam, wChar);
/* find window that has a menu */
- while (!((GetWindowLongPtrW( hWnd, GWL_STYLE ) &
+ while (!((GetWindowLongPtrW( hwnd, GWL_STYLE ) &
(WS_CHILD | WS_POPUP)) != WS_CHILD))
- if (!(hWnd = GetAncestor( hWnd, GA_PARENT ))) return;
+ if (!(hwnd = GetAncestor( hwnd, GA_PARENT ))) return;
/* check if we have to track a system menu */
- hTrackMenu = GetMenu( hWnd );
- if (!hTrackMenu || IsIconic(hWnd) || wChar == ' ' )
+ hTrackMenu = GetMenu( hwnd );
+ if (!hTrackMenu || IsIconic(hwnd) || wChar == ' ' )
{
- if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_SYSMENU)) return;
- hTrackMenu = NtUserGetSystemMenu(hWnd, FALSE);
+ if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_SYSMENU)) return;
+ hTrackMenu = NtUserGetSystemMenu(hwnd, FALSE);
uItem = 0;
wParam |= HTSYSMENU; /* prevent item lookup */
}
if (!IsMenu( hTrackMenu )) return;
- MenuInitTracking( hWnd, hTrackMenu, FALSE, wFlags );
+ MenuInitTracking( hwnd, hTrackMenu, FALSE, wFlags );
if (! MenuGetRosMenuInfo(&MenuInfo, hTrackMenu))
{
@@ -3807,7 +3574,7 @@ MenuTrackKbdMenuBar(HWND hWnd, UINT wParam, WCHAR wChar)
if( wChar && wChar != ' ' )
{
- uItem = MenuFindItemByKey( hWnd, &MenuInfo, wChar, (wParam & HTSYSMENU) );
+ uItem = MenuFindItemByKey( hwnd, &MenuInfo, wChar, (wParam & HTSYSMENU) );
if ( uItem >= (UINT)(-2) )
{
if( uItem == (UINT)(-1) ) MessageBeep(0);
@@ -3817,7 +3584,7 @@ MenuTrackKbdMenuBar(HWND hWnd, UINT wParam, WCHAR wChar)
}
}
- MenuSelectItem( hWnd, &MenuInfo, uItem, TRUE, 0 );
+ MenuSelectItem( hwnd, &MenuInfo, uItem, TRUE, 0 );
if (wParam & HTSYSMENU)
{
@@ -3828,17 +3595,54 @@ MenuTrackKbdMenuBar(HWND hWnd, UINT wParam, WCHAR wChar)
else
{
if( uItem == NO_SELECTED_ITEM )
- MenuMoveSelection( hWnd, &MenuInfo, ITEM_NEXT );
+ MenuMoveSelection( hwnd, &MenuInfo, ITEM_NEXT );
else
- PostMessageW( hWnd, WM_KEYDOWN, VK_DOWN, 0L );
+ PostMessageW( hwnd, WM_KEYDOWN, VK_DOWN, 0L );
}
track_menu:
- MenuTrackMenu( hTrackMenu, wFlags, 0, 0, hWnd, NULL );
- MenuExitTracking( hWnd );
+ MenuTrackMenu( hTrackMenu, wFlags, 0, 0, hwnd, NULL );
+ MenuExitTracking( hwnd );
}
+/**********************************************************************
+ * TrackPopupMenuEx (USER32.@)
+ */
+BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
+ HWND Wnd, LPTPMPARAMS Tpm)
+{
+ /* Not fully implemented */
+ return TrackPopupMenu(Menu, Flags, x, y, 0, Wnd,
+ NULL != Tpm ? &Tpm->rcExclude : NULL);
+}
+
+/**********************************************************************
+ * TrackPopupMenu (USER32.@)
+ */
+BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y,
+ int Reserved, HWND Wnd, CONST RECT *Rect)
+{
+ BOOL ret = FALSE;
+
+ if (!IsMenu(Menu))
+ {
+ SetLastError( ERROR_INVALID_MENU_HANDLE );
+ return FALSE;
+ }
+
+ MenuInitTracking(Wnd, Menu, TRUE, Flags);
+
+ /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
+ if (!(Flags & TPM_NONOTIFY))
+ SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
+
+ if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
+ ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, Rect);
+ MenuExitTracking(Wnd);
+ return ret;
+}
+
/*
* From MSDN:
* The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined
@@ -5193,64 +4997,6 @@ SetSystemMenu (
return NtUserSetSystemMenu(hwnd, hMenu);
}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-TrackPopupMenu(
- HMENU Menu,
- UINT Flags,
- int x,
- int y,
- int Reserved,
- HWND Wnd,
- CONST RECT *Rect)
-{
- BOOL ret = FALSE;
-
- if (!IsMenu(Menu))
- {
- SetLastError( ERROR_INVALID_MENU_HANDLE );
- return FALSE;
- }
-
- MenuInitTracking(Wnd, Menu, TRUE, Flags);
-
- /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
- if (0 == (Flags & TPM_NONOTIFY))
- {
- SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
- }
-
- if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
- {
- ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, Rect);
- }
- MenuExitTracking(Wnd);
- return ret;
-}
-
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-TrackPopupMenuEx(
- HMENU Menu,
- UINT Flags,
- int x,
- int y,
- HWND Wnd,
- LPTPMPARAMS Tpm)
-{
- /* Not fully implemented */
- return TrackPopupMenu(Menu, Flags, x, y, 0, Wnd,
- NULL != Tpm ? &Tpm->rcExclude : NULL);
-}
-
//
// Example for the Win32/User32 rewrite.
// Def = TrackPopupMenuEx@24=NtUserTrackPopupMenuEx@24
diff --git a/dll/win32/win32.rbuild b/dll/win32/win32.rbuild
index c68742612de..9ff3319d54f 100644
--- a/dll/win32/win32.rbuild
+++ b/dll/win32/win32.rbuild
@@ -103,6 +103,9 @@
+
+
+
diff --git a/dll/win32/wininet/cookie.c b/dll/win32/wininet/cookie.c
index 12d841bc7b9..75cf049308b 100644
--- a/dll/win32/wininet/cookie.c
+++ b/dll/win32/wininet/cookie.c
@@ -23,6 +23,10 @@
#include "config.h"
#include "wine/port.h"
+#if defined(__MINGW32__) || defined (_MSC_VER)
+#include
+#endif
+
#include
#include
#include
@@ -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;
+}
diff --git a/dll/win32/wininet/dialogs.c b/dll/win32/wininet/dialogs.c
index dd5aa315a63..2c4a5278569 100644
--- a/dll/win32/wininet/dialogs.c
+++ b/dll/win32/wininet/dialogs.c
@@ -21,6 +21,10 @@
#include "config.h"
#include "wine/port.h"
+#if defined(__MINGW32__) || defined (_MSC_VER)
+#include
+#endif
+
#include
#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:
diff --git a/dll/win32/wininet/ftp.c b/dll/win32/wininet/ftp.c
index 770fef2886a..1f031996811 100644
--- a/dll/win32/wininet/ftp.c
+++ b/dll/win32/wininet/ftp.c
@@ -30,6 +30,10 @@
#include "config.h"
#include "wine/port.h"
+#if defined(__MINGW32__) || defined (_MSC_VER)
+#include
+#endif
+
#include
#include
#include
@@ -39,9 +43,15 @@
#ifdef HAVE_SYS_SOCKET_H
# include
#endif
+#ifdef HAVE_ARPA_INET_H
+# include
+#endif
#ifdef HAVE_UNISTD_H
# include
#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include
+#endif
#include
#include
@@ -61,43 +71,47 @@
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
-typedef struct _WININETFTPSESSIONW WININETFTPSESSIONW;
+typedef struct _ftp_session_t ftp_session_t;
typedef struct
{
- WININETHANDLEHEADER hdr;
- WININETFTPSESSIONW *lpFtpSession;
+ object_header_t hdr;
+ ftp_session_t *lpFtpSession;
BOOL session_deleted;
int nDataSocket;
-} WININETFTPFILE, *LPWININETFTPFILE;
+ WCHAR *cache_file;
+ HANDLE cache_file_handle;
+} ftp_file_t;
-typedef struct _WININETFTPSESSIONW
+struct _ftp_session_t
{
- WININETHANDLEHEADER hdr;
- WININETAPPINFOW *lpAppInfo;
+ object_header_t hdr;
+ appinfo_t *lpAppInfo;
int sndSocket;
int lstnSocket;
int pasvSocket; /* data socket connected by us in case of passive FTP */
- LPWININETFTPFILE download_in_progress;
+ ftp_file_t *download_in_progress;
struct sockaddr_in socketAddress;
struct sockaddr_in lstnSocketAddress;
+ LPWSTR servername;
+ INTERNET_PORT serverport;
LPWSTR lpszPassword;
LPWSTR lpszUserName;
-} *LPWININETFTPSESSIONW;
+};
typedef struct
{
BOOL bIsDirectory;
LPWSTR lpszName;
DWORD nSize;
- struct tm tmLastModified;
+ SYSTEMTIME tmLastModified;
unsigned short permissions;
} FILEPROPERTIESW, *LPFILEPROPERTIESW;
typedef struct
{
- WININETHANDLEHEADER hdr;
- WININETFTPSESSIONW *lpFtpSession;
+ object_header_t hdr;
+ ftp_session_t *lpFtpSession;
DWORD index;
DWORD size;
LPFILEPROPERTIESW lpafp;
@@ -165,46 +179,51 @@ static const CHAR szMonths[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
static const WCHAR szNoAccount[] = {'n','o','a','c','c','o','u','n','t','\0'};
static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
- INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext);
-static BOOL FTP_SendStore(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType);
-static BOOL FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs, LPINT nDataSocket);
-static BOOL FTP_SendData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile);
-static INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD_PTR dwContext);
-static BOOL FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType);
-static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile);
-static BOOL FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs);
-static BOOL FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs);
-static BOOL FTP_SendPassword(LPWININETFTPSESSIONW lpwfs);
-static BOOL FTP_SendAccount(LPWININETFTPSESSIONW lpwfs);
-static BOOL FTP_SendType(LPWININETFTPSESSIONW lpwfs, DWORD dwType);
-static BOOL FTP_SendPort(LPWININETFTPSESSIONW lpwfs);
-static BOOL FTP_DoPassive(LPWININETFTPSESSIONW lpwfs);
-static BOOL FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs);
+ INTERNET_STATUS_CALLBACK lpfnStatusCB, object_header_t *hdr, DWORD_PTR dwContext);
+static BOOL FTP_SendStore(ftp_session_t*, LPCWSTR lpszRemoteFile, DWORD dwType);
+static BOOL FTP_GetDataSocket(ftp_session_t*, LPINT nDataSocket);
+static BOOL FTP_SendData(ftp_session_t*, INT nDataSocket, HANDLE hFile);
+static INT FTP_ReceiveResponse(ftp_session_t*, DWORD_PTR dwContext);
+static BOOL FTP_SendRetrieve(ftp_session_t*, LPCWSTR lpszRemoteFile, DWORD dwType);
+static BOOL FTP_RetrieveFileData(ftp_session_t*, INT nDataSocket, HANDLE hFile);
+static BOOL FTP_InitListenSocket(ftp_session_t*);
+static BOOL FTP_ConnectToHost(ftp_session_t*);
+static BOOL FTP_SendPassword(ftp_session_t*);
+static BOOL FTP_SendAccount(ftp_session_t*);
+static BOOL FTP_SendType(ftp_session_t*, DWORD dwType);
+static BOOL FTP_SendPort(ftp_session_t*);
+static BOOL FTP_DoPassive(ftp_session_t*);
+static BOOL FTP_SendPortOrPasv(ftp_session_t*);
static BOOL FTP_ParsePermission(LPCSTR lpszPermission, LPFILEPROPERTIESW lpfp);
static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERTIESW fileprop);
-static BOOL FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
+static BOOL FTP_ParseDirectory(ftp_session_t*, INT nSocket, LPCWSTR lpszSearchFile,
LPFILEPROPERTIESW *lpafp, LPDWORD dwfp);
-static HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
+static HINTERNET FTP_ReceiveFileList(ftp_session_t*, INT nSocket, LPCWSTR lpszSearchFile,
LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext);
static DWORD FTP_SetResponseError(DWORD dwResponse);
static BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileData);
-static BOOL FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile,
+static BOOL FTP_FtpPutFileW(ftp_session_t*, LPCWSTR lpszLocalFile,
LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext);
-static BOOL FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory);
-static BOOL FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory);
-static HINTERNET FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs,
+static BOOL FTP_FtpSetCurrentDirectoryW(ftp_session_t*, LPCWSTR lpszDirectory);
+static BOOL FTP_FtpCreateDirectoryW(ftp_session_t*, LPCWSTR lpszDirectory);
+static HINTERNET FTP_FtpFindFirstFileW(ftp_session_t*,
LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext);
-static BOOL FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszCurrentDirectory,
+static BOOL FTP_FtpGetCurrentDirectoryW(ftp_session_t*, LPWSTR lpszCurrentDirectory,
LPDWORD lpdwCurrentDirectory);
-static BOOL FTP_FtpRenameFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszSrc, LPCWSTR lpszDest);
-static BOOL FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory);
-static BOOL FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName);
-static HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName,
- DWORD fdwAccess, DWORD dwFlags, DWORD_PTR dwContext);
-static BOOL FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
+static BOOL FTP_FtpRenameFileW(ftp_session_t*, LPCWSTR lpszSrc, LPCWSTR lpszDest);
+static BOOL FTP_FtpRemoveDirectoryW(ftp_session_t*, LPCWSTR lpszDirectory);
+static BOOL FTP_FtpDeleteFileW(ftp_session_t*, LPCWSTR lpszFileName);
+static BOOL FTP_FtpGetFileW(ftp_session_t*, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
DWORD_PTR dwContext);
+/* A temporary helper until we get rid of INTERNET_GetLastError calls */
+static BOOL res_to_le(DWORD res)
+{
+ if(res != ERROR_SUCCESS)
+ INTERNET_SetLastError(res);
+ return res == ERROR_SUCCESS;
+}
/***********************************************************************
* FtpPutFileA (WININET.@)
@@ -223,8 +242,8 @@ BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
LPWSTR lpwzNewRemoteFile;
BOOL ret;
- lpwzLocalFile = lpszLocalFile?WININET_strdup_AtoW(lpszLocalFile):NULL;
- lpwzNewRemoteFile = lpszNewRemoteFile?WININET_strdup_AtoW(lpszNewRemoteFile):NULL;
+ lpwzLocalFile = heap_strdupAtoW(lpszLocalFile);
+ lpwzNewRemoteFile = heap_strdupAtoW(lpszNewRemoteFile);
ret = FtpPutFileW(hConnect, lpwzLocalFile, lpwzNewRemoteFile,
dwFlags, dwContext);
HeapFree(GetProcessHeap(), 0, lpwzLocalFile);
@@ -235,7 +254,7 @@ BOOL WINAPI FtpPutFileA(HINTERNET hConnect, LPCSTR lpszLocalFile,
static void AsyncFtpPutFileProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPPUTFILEW const *req = &workRequest->u.FtpPutFileW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -259,8 +278,8 @@ static void AsyncFtpPutFileProc(WORKREQUEST *workRequest)
BOOL WINAPI FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile,
LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
BOOL r = FALSE;
if (!lpszLocalFile || !lpszNewRemoteFile)
@@ -269,7 +288,7 @@ BOOL WINAPI FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile,
return FALSE;
}
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hConnect );
if (!lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -302,12 +321,12 @@ BOOL WINAPI FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile,
workRequest.asyncproc = AsyncFtpPutFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
- req->lpszLocalFile = WININET_strdupW(lpszLocalFile);
- req->lpszNewRemoteFile = WININET_strdupW(lpszNewRemoteFile);
+ req->lpszLocalFile = heap_strdupW(lpszLocalFile);
+ req->lpszNewRemoteFile = heap_strdupW(lpszNewRemoteFile);
req->dwFlags = dwFlags;
req->dwContext = dwContext;
- r = INTERNET_AsyncCall(&workRequest);
+ r = res_to_le(INTERNET_AsyncCall(&workRequest));
}
else
{
@@ -331,12 +350,12 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile,
+static BOOL FTP_FtpPutFileW(ftp_session_t *lpwfs, LPCWSTR lpszLocalFile,
LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD_PTR dwContext)
{
HANDLE hFile;
BOOL bSuccess = FALSE;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
INT nResCode;
TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", debugstr_w(lpszLocalFile), debugstr_w(lpszNewRemoteFile));
@@ -375,7 +394,10 @@ static BOOL FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile,
}
if (lpwfs->lstnSocket != -1)
+ {
closesocket(lpwfs->lstnSocket);
+ lpwfs->lstnSocket = -1;
+ }
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
@@ -408,7 +430,7 @@ BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
LPWSTR lpwzDirectory;
BOOL ret;
- lpwzDirectory = lpszDirectory?WININET_strdup_AtoW(lpszDirectory):NULL;
+ lpwzDirectory = heap_strdupAtoW(lpszDirectory);
ret = FtpSetCurrentDirectoryW(hConnect, lpwzDirectory);
HeapFree(GetProcessHeap(), 0, lpwzDirectory);
return ret;
@@ -418,7 +440,7 @@ BOOL WINAPI FtpSetCurrentDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
static void AsyncFtpSetCurrentDirectoryProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPSETCURRENTDIRECTORYW const *req = &workRequest->u.FtpSetCurrentDirectoryW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -438,8 +460,8 @@ static void AsyncFtpSetCurrentDirectoryProc(WORKREQUEST *workRequest)
*/
BOOL WINAPI FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
{
- LPWININETFTPSESSIONW lpwfs = NULL;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs = NULL;
+ appinfo_t *hIC = NULL;
BOOL r = FALSE;
if (!lpszDirectory)
@@ -448,7 +470,7 @@ BOOL WINAPI FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
goto lend;
}
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hConnect );
if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
@@ -472,9 +494,9 @@ BOOL WINAPI FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
workRequest.asyncproc = AsyncFtpSetCurrentDirectoryProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpSetCurrentDirectoryW;
- req->lpszDirectory = WININET_strdupW(lpszDirectory);
+ req->lpszDirectory = heap_strdupW(lpszDirectory);
- r = INTERNET_AsyncCall(&workRequest);
+ r = res_to_le(INTERNET_AsyncCall(&workRequest));
}
else
{
@@ -499,10 +521,10 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory)
+static BOOL FTP_FtpSetCurrentDirectoryW(ftp_session_t *lpwfs, LPCWSTR lpszDirectory)
{
INT nResCode;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
DWORD bSuccess = FALSE;
TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
@@ -554,7 +576,7 @@ BOOL WINAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
LPWSTR lpwzDirectory;
BOOL ret;
- lpwzDirectory = lpszDirectory?WININET_strdup_AtoW(lpszDirectory):NULL;
+ lpwzDirectory = heap_strdupAtoW(lpszDirectory);
ret = FtpCreateDirectoryW(hConnect, lpwzDirectory);
HeapFree(GetProcessHeap(), 0, lpwzDirectory);
return ret;
@@ -564,7 +586,7 @@ BOOL WINAPI FtpCreateDirectoryA(HINTERNET hConnect, LPCSTR lpszDirectory)
static void AsyncFtpCreateDirectoryProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPCREATEDIRECTORYW const *req = &workRequest->u.FtpCreateDirectoryW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE(" %p\n", lpwfs);
@@ -584,11 +606,11 @@ static void AsyncFtpCreateDirectoryProc(WORKREQUEST *workRequest)
*/
BOOL WINAPI FtpCreateDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
BOOL r = FALSE;
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hConnect );
if (!lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -622,9 +644,9 @@ BOOL WINAPI FtpCreateDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
workRequest.asyncproc = AsyncFtpCreateDirectoryProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpCreateDirectoryW;
- req->lpszDirectory = WININET_strdupW(lpszDirectory);
+ req->lpszDirectory = heap_strdupW(lpszDirectory);
- r = INTERNET_AsyncCall(&workRequest);
+ r = res_to_le(INTERNET_AsyncCall(&workRequest));
}
else
{
@@ -647,11 +669,11 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory)
+static BOOL FTP_FtpCreateDirectoryW(ftp_session_t *lpwfs, LPCWSTR lpszDirectory)
{
INT nResCode;
BOOL bSuccess = FALSE;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
@@ -703,14 +725,14 @@ HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect,
LPWIN32_FIND_DATAW lpFindFileDataW;
HINTERNET ret;
- lpwzSearchFile = lpszSearchFile?WININET_strdup_AtoW(lpszSearchFile):NULL;
+ lpwzSearchFile = heap_strdupAtoW(lpszSearchFile);
lpFindFileDataW = lpFindFileData?&wfd:NULL;
ret = FtpFindFirstFileW(hConnect, lpwzSearchFile, lpFindFileDataW, dwFlags, dwContext);
HeapFree(GetProcessHeap(), 0, lpwzSearchFile);
if (ret && lpFindFileData)
WININET_find_data_WtoA(lpFindFileDataW, lpFindFileData);
-
+
return ret;
}
@@ -718,7 +740,7 @@ HINTERNET WINAPI FtpFindFirstFileA(HINTERNET hConnect,
static void AsyncFtpFindFirstFileProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPFINDFIRSTFILEW const *req = &workRequest->u.FtpFindFirstFileW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -740,11 +762,11 @@ static void AsyncFtpFindFirstFileProc(WORKREQUEST *workRequest)
HINTERNET WINAPI FtpFindFirstFileW(HINTERNET hConnect,
LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
HINTERNET r = NULL;
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hConnect );
if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
@@ -766,7 +788,7 @@ HINTERNET WINAPI FtpFindFirstFileW(HINTERNET hConnect,
workRequest.asyncproc = AsyncFtpFindFirstFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpFindFirstFileW;
- req->lpszSearchFile = (lpszSearchFile == NULL) ? NULL : WININET_strdupW(lpszSearchFile);
+ req->lpszSearchFile = (lpszSearchFile == NULL) ? NULL : heap_strdupW(lpszSearchFile);
req->lpFindFileData = lpFindFileData;
req->dwFlags = dwFlags;
req->dwContext= dwContext;
@@ -797,11 +819,11 @@ lend:
* NULL on failure
*
*/
-static HINTERNET FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs,
+static HINTERNET FTP_FtpFindFirstFileW(ftp_session_t *lpwfs,
LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD_PTR dwContext)
{
INT nResCode;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
HINTERNET hFindNext = NULL;
TRACE("\n");
@@ -845,7 +867,10 @@ static HINTERNET FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs,
lend:
if (lpwfs->lstnSocket != -1)
+ {
closesocket(lpwfs->lstnSocket);
+ lpwfs->lstnSocket = -1;
+ }
hIC = lpwfs->lpAppInfo;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
@@ -854,13 +879,13 @@ lend:
if (hFindNext)
{
- iar.dwResult = (DWORD)hFindNext;
+ iar.dwResult = (DWORD_PTR)hFindNext;
iar.dwError = ERROR_SUCCESS;
SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
&iar, sizeof(INTERNET_ASYNC_RESULT));
}
- iar.dwResult = (DWORD)hFindNext;
+ iar.dwResult = (DWORD_PTR)hFindNext;
iar.dwError = hFindNext ? ERROR_SUCCESS : INTERNET_GetLastError();
SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
&iar, sizeof(INTERNET_ASYNC_RESULT));
@@ -913,7 +938,7 @@ BOOL WINAPI FtpGetCurrentDirectoryA(HINTERNET hFtpSession, LPSTR lpszCurrentDire
static void AsyncFtpGetCurrentDirectoryProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPGETCURRENTDIRECTORYW const *req = &workRequest->u.FtpGetCurrentDirectoryW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -933,13 +958,13 @@ static void AsyncFtpGetCurrentDirectoryProc(WORKREQUEST *workRequest)
BOOL WINAPI FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDirectory,
LPDWORD lpdwCurrentDirectory)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
BOOL r = FALSE;
TRACE("%p %p %p\n", hFtpSession, lpszCurrentDirectory, lpdwCurrentDirectory);
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hFtpSession );
if (NULL == lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -982,7 +1007,7 @@ BOOL WINAPI FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDir
req->lpszDirectory = lpszCurrentDirectory;
req->lpdwDirectory = lpdwCurrentDirectory;
- r = INTERNET_AsyncCall(&workRequest);
+ r = res_to_le(INTERNET_AsyncCall(&workRequest));
}
else
{
@@ -1008,11 +1033,11 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszCurrentDirectory,
+static BOOL FTP_FtpGetCurrentDirectoryW(ftp_session_t *lpwfs, LPWSTR lpszCurrentDirectory,
LPDWORD lpdwCurrentDirectory)
{
INT nResCode;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
DWORD bSuccess = FALSE;
/* Clear any error information */
@@ -1029,7 +1054,7 @@ static BOOL FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszC
if (nResCode == 257) /* Extract directory name */
{
DWORD firstpos, lastpos, len;
- LPWSTR lpszResponseBuffer = WININET_strdup_AtoW(INTERNET_GetResponseBuffer());
+ LPWSTR lpszResponseBuffer = heap_strdupAtoW(INTERNET_GetResponseBuffer());
for (firstpos = 0, lastpos = 0; lpszResponseBuffer[lastpos]; lastpos++)
{
@@ -1071,6 +1096,354 @@ lend:
return bSuccess;
}
+
+/***********************************************************************
+ * FTPFILE_Destroy(internal)
+ *
+ * Closes the file transfer handle. This also 'cleans' the data queue of
+ * the 'transfer complete' message (this is a bit of a hack though :-/ )
+ *
+ */
+static void FTPFILE_Destroy(object_header_t *hdr)
+{
+ ftp_file_t *lpwh = (ftp_file_t*) hdr;
+ ftp_session_t *lpwfs = lpwh->lpFtpSession;
+ INT nResCode;
+
+ TRACE("\n");
+
+ if (lpwh->cache_file_handle != INVALID_HANDLE_VALUE)
+ CloseHandle(lpwh->cache_file_handle);
+
+ HeapFree(GetProcessHeap(), 0, lpwh->cache_file);
+
+ if (!lpwh->session_deleted)
+ lpwfs->download_in_progress = NULL;
+
+ if (lpwh->nDataSocket != -1)
+ closesocket(lpwh->nDataSocket);
+
+ nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
+ if (nResCode > 0 && nResCode != 226) WARN("server reports failed transfer\n");
+
+ WININET_Release(&lpwh->lpFtpSession->hdr);
+
+ HeapFree(GetProcessHeap(), 0, lpwh);
+}
+
+static DWORD FTPFILE_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
+{
+ switch(option) {
+ case INTERNET_OPTION_HANDLE_TYPE:
+ TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
+
+ if (*size < sizeof(ULONG))
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ *size = sizeof(DWORD);
+ *(DWORD*)buffer = INTERNET_HANDLE_TYPE_FTP_FILE;
+ return ERROR_SUCCESS;
+ case INTERNET_OPTION_DATAFILE_NAME:
+ {
+ DWORD required;
+ ftp_file_t *file = (ftp_file_t *)hdr;
+
+ TRACE("INTERNET_OPTION_DATAFILE_NAME\n");
+
+ if (!file->cache_file)
+ {
+ *size = 0;
+ return ERROR_INTERNET_ITEM_NOT_FOUND;
+ }
+ if (unicode)
+ {
+ required = (lstrlenW(file->cache_file) + 1) * sizeof(WCHAR);
+ if (*size < required)
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ *size = required;
+ memcpy(buffer, file->cache_file, *size);
+ return ERROR_SUCCESS;
+ }
+ else
+ {
+ required = WideCharToMultiByte(CP_ACP, 0, file->cache_file, -1, NULL, 0, NULL, NULL);
+ if (required > *size)
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ *size = WideCharToMultiByte(CP_ACP, 0, file->cache_file, -1, buffer, *size, NULL, NULL);
+ return ERROR_SUCCESS;
+ }
+ }
+ }
+ return INET_QueryOption(option, buffer, size, unicode);
+}
+
+static DWORD FTPFILE_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read)
+{
+ ftp_file_t *file = (ftp_file_t*)hdr;
+ int res;
+ DWORD error;
+
+ if (file->nDataSocket == -1)
+ return ERROR_INTERNET_DISCONNECTED;
+
+ /* FIXME: FTP should use NETCON_ stuff */
+ res = recv(file->nDataSocket, buffer, size, MSG_WAITALL);
+ *read = res>0 ? res : 0;
+
+ error = res >= 0 ? ERROR_SUCCESS : INTERNET_ERROR_BASE; /* FIXME */
+ if (error == ERROR_SUCCESS && file->cache_file)
+ {
+ DWORD bytes_written;
+
+ if (!WriteFile(file->cache_file_handle, buffer, *read, &bytes_written, NULL))
+ WARN("WriteFile failed: %u\n", GetLastError());
+ }
+ return error;
+}
+
+static DWORD FTPFILE_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffers,
+ DWORD flags, DWORD_PTR context)
+{
+ return FTPFILE_ReadFile(hdr, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength);
+}
+
+static DWORD FTPFILE_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffers,
+ DWORD flags, DWORD_PTR context)
+{
+ return FTPFILE_ReadFile(hdr, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength);
+}
+
+static DWORD FTPFILE_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
+{
+ ftp_file_t *lpwh = (ftp_file_t*) hdr;
+ int res;
+
+ res = send(lpwh->nDataSocket, buffer, size, 0);
+
+ *written = res>0 ? res : 0;
+ return res >= 0 ? ERROR_SUCCESS : sock_get_error(errno);
+}
+
+static void FTP_ReceiveRequestData(ftp_file_t *file, BOOL first_notif)
+{
+ INTERNET_ASYNC_RESULT iar;
+ BYTE buffer[4096];
+ int available;
+
+ TRACE("%p\n", file);
+
+ available = recv(file->nDataSocket, buffer, sizeof(buffer), MSG_PEEK);
+
+ if(available != -1) {
+ iar.dwResult = (DWORD_PTR)file->hdr.hInternet;
+ iar.dwError = first_notif ? 0 : available;
+ }else {
+ iar.dwResult = 0;
+ iar.dwError = INTERNET_GetLastError();
+ }
+
+ INTERNET_SendCallback(&file->hdr, file->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
+}
+
+static void FTPFILE_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest)
+{
+ ftp_file_t *file = (ftp_file_t*)workRequest->hdr;
+
+ FTP_ReceiveRequestData(file, FALSE);
+}
+
+static DWORD FTPFILE_QueryDataAvailable(object_header_t *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx)
+{
+ ftp_file_t *file = (ftp_file_t*) hdr;
+ int retval, unread = 0;
+
+ TRACE("(%p %p %x %lx)\n", file, available, flags, ctx);
+
+#ifdef FIONREAD
+ retval = ioctlsocket(file->nDataSocket, FIONREAD, &unread);
+ if (!retval)
+ TRACE("%d bytes of queued, but unread data\n", unread);
+#else
+ FIXME("FIONREAD not available\n");
+#endif
+
+ *available = unread;
+
+ if(!unread) {
+ BYTE byte;
+
+ *available = 0;
+
+ retval = recv(file->nDataSocket, &byte, 1, MSG_PEEK);
+ if(retval > 0) {
+ WORKREQUEST workRequest;
+
+ *available = 0;
+ workRequest.asyncproc = FTPFILE_AsyncQueryDataAvailableProc;
+ workRequest.hdr = WININET_AddRef( &file->hdr );
+
+ INTERNET_AsyncCall(&workRequest);
+
+ return ERROR_IO_PENDING;
+ }
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+static const object_vtbl_t FTPFILEVtbl = {
+ FTPFILE_Destroy,
+ NULL,
+ FTPFILE_QueryOption,
+ NULL,
+ FTPFILE_ReadFile,
+ FTPFILE_ReadFileExA,
+ FTPFILE_ReadFileExW,
+ FTPFILE_WriteFile,
+ FTPFILE_QueryDataAvailable,
+ NULL
+};
+
+/***********************************************************************
+ * FTP_FtpOpenFileW (Internal)
+ *
+ * Open a remote file for writing or reading
+ *
+ * RETURNS
+ * HINTERNET handle on success
+ * NULL on failure
+ *
+ */
+static HINTERNET FTP_FtpOpenFileW(ftp_session_t *lpwfs,
+ LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
+ DWORD_PTR dwContext)
+{
+ INT nDataSocket;
+ BOOL bSuccess = FALSE;
+ ftp_file_t *lpwh = NULL;
+ appinfo_t *hIC = NULL;
+ HINTERNET handle = NULL;
+
+ TRACE("\n");
+
+ /* Clear any error information */
+ INTERNET_SetLastError(0);
+
+ if (GENERIC_READ == fdwAccess)
+ {
+ /* Set up socket to retrieve data */
+ bSuccess = FTP_SendRetrieve(lpwfs, lpszFileName, dwFlags);
+ }
+ else if (GENERIC_WRITE == fdwAccess)
+ {
+ /* Set up socket to send data */
+ bSuccess = FTP_SendStore(lpwfs, lpszFileName, dwFlags);
+ }
+
+ /* Get data socket to server */
+ if (bSuccess && FTP_GetDataSocket(lpwfs, &nDataSocket))
+ {
+ lpwh = HeapAlloc(GetProcessHeap(), 0, sizeof(ftp_file_t));
+ lpwh->hdr.htype = WH_HFILE;
+ lpwh->hdr.vtbl = &FTPFILEVtbl;
+ lpwh->hdr.dwFlags = dwFlags;
+ lpwh->hdr.dwContext = dwContext;
+ lpwh->hdr.dwInternalFlags = 0;
+ lpwh->hdr.refs = 1;
+ lpwh->hdr.lpfnStatusCB = lpwfs->hdr.lpfnStatusCB;
+ lpwh->nDataSocket = nDataSocket;
+ lpwh->cache_file = NULL;
+ lpwh->cache_file_handle = INVALID_HANDLE_VALUE;
+ lpwh->session_deleted = FALSE;
+
+ WININET_AddRef( &lpwfs->hdr );
+ lpwh->lpFtpSession = lpwfs;
+ list_add_head( &lpwfs->hdr.children, &lpwh->hdr.entry );
+
+ handle = WININET_AllocHandle( &lpwh->hdr );
+ if( !handle )
+ goto lend;
+
+ /* Indicate that a download is currently in progress */
+ lpwfs->download_in_progress = lpwh;
+ }
+
+ if (lpwfs->lstnSocket != -1)
+ {
+ closesocket(lpwfs->lstnSocket);
+ lpwfs->lstnSocket = -1;
+ }
+
+ if (bSuccess && fdwAccess == GENERIC_READ)
+ {
+ WCHAR filename[MAX_PATH + 1];
+ URL_COMPONENTSW uc;
+ DWORD len;
+
+ memset(&uc, 0, sizeof(uc));
+ uc.dwStructSize = sizeof(uc);
+ uc.nScheme = INTERNET_SCHEME_FTP;
+ uc.lpszHostName = lpwfs->servername;
+ uc.nPort = lpwfs->serverport;
+ uc.lpszUserName = lpwfs->lpszUserName;
+ uc.lpszUrlPath = heap_strdupW(lpszFileName);
+
+ if (!InternetCreateUrlW(&uc, 0, NULL, &len) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ WCHAR *url = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+
+ if (url && InternetCreateUrlW(&uc, 0, url, &len) && CreateUrlCacheEntryW(url, 0, NULL, filename, 0))
+ {
+ lpwh->cache_file = heap_strdupW(filename);
+ lpwh->cache_file_handle = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (lpwh->cache_file_handle == INVALID_HANDLE_VALUE)
+ {
+ WARN("Could not create cache file: %u\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, lpwh->cache_file);
+ lpwh->cache_file = NULL;
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, url);
+ }
+ HeapFree(GetProcessHeap(), 0, uc.lpszUrlPath);
+ }
+
+ hIC = lpwfs->lpAppInfo;
+ if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ INTERNET_ASYNC_RESULT iar;
+
+ if (lpwh)
+ {
+ iar.dwResult = (DWORD_PTR)handle;
+ iar.dwError = ERROR_SUCCESS;
+ SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
+ &iar, sizeof(INTERNET_ASYNC_RESULT));
+ }
+
+ if(bSuccess) {
+ FTP_ReceiveRequestData(lpwh, TRUE);
+ }else {
+ iar.dwResult = 0;
+ iar.dwError = INTERNET_GetLastError();
+ SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+ &iar, sizeof(INTERNET_ASYNC_RESULT));
+ }
+ }
+
+lend:
+ if( lpwh )
+ WININET_Release( &lpwh->hdr );
+
+ return handle;
+}
+
+
/***********************************************************************
* FtpOpenFileA (WININET.@)
*
@@ -1087,8 +1460,8 @@ HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
{
LPWSTR lpwzFileName;
HINTERNET ret;
-
- lpwzFileName = lpszFileName?WININET_strdup_AtoW(lpszFileName):NULL;
+
+ lpwzFileName = heap_strdupAtoW(lpszFileName);
ret = FtpOpenFileW(hFtpSession, lpwzFileName, fdwAccess, dwFlags, dwContext);
HeapFree(GetProcessHeap(), 0, lpwzFileName);
return ret;
@@ -1098,7 +1471,7 @@ HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
static void AsyncFtpOpenFileProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPOPENFILEW const *req = &workRequest->u.FtpOpenFileW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -1121,14 +1494,14 @@ HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession,
LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
DWORD_PTR dwContext)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
HINTERNET r = NULL;
-
+
TRACE("(%p,%s,0x%08x,0x%08x,0x%08lx)\n", hFtpSession,
debugstr_w(lpszFileName), fdwAccess, dwFlags, dwContext);
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hFtpSession );
if (!lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -1164,7 +1537,7 @@ HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession,
workRequest.asyncproc = AsyncFtpOpenFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpOpenFileW;
- req->lpszFilename = WININET_strdupW(lpszFileName);
+ req->lpszFilename = heap_strdupW(lpszFileName);
req->dwAccess = fdwAccess;
req->dwFlags = dwFlags;
req->dwContext = dwContext;
@@ -1184,181 +1557,6 @@ lend:
}
-/***********************************************************************
- * FTPFILE_Destroy(internal)
- *
- * Closes the file transfer handle. This also 'cleans' the data queue of
- * the 'transfer complete' message (this is a bit of a hack though :-/ )
- *
- */
-static void FTPFILE_Destroy(WININETHANDLEHEADER *hdr)
-{
- LPWININETFTPFILE lpwh = (LPWININETFTPFILE) hdr;
- LPWININETFTPSESSIONW lpwfs = lpwh->lpFtpSession;
- INT nResCode;
-
- TRACE("\n");
-
- WININET_Release(&lpwh->lpFtpSession->hdr);
-
- if (!lpwh->session_deleted)
- lpwfs->download_in_progress = NULL;
-
- if (lpwh->nDataSocket != -1)
- closesocket(lpwh->nDataSocket);
-
- nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
- if (nResCode > 0 && nResCode != 226) WARN("server reports failed transfer\n");
-
- HeapFree(GetProcessHeap(), 0, lpwh);
-}
-
-static DWORD FTPFILE_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
-{
- switch(option) {
- case INTERNET_OPTION_HANDLE_TYPE:
- TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
-
- if (*size < sizeof(ULONG))
- return ERROR_INSUFFICIENT_BUFFER;
-
- *size = sizeof(DWORD);
- *(DWORD*)buffer = INTERNET_HANDLE_TYPE_FTP_FILE;
- return ERROR_SUCCESS;
- }
-
- return INET_QueryOption(option, buffer, size, unicode);
-}
-
-static DWORD FTPFILE_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size, DWORD *read)
-{
- WININETFTPFILE *file = (WININETFTPFILE*)hdr;
- int res;
-
- if (file->nDataSocket == -1)
- return ERROR_INTERNET_DISCONNECTED;
-
- /* FIXME: FTP should use NETCON_ stuff */
- res = recv(file->nDataSocket, buffer, size, MSG_WAITALL);
- *read = res>0 ? res : 0;
-
- return res>=0 ? ERROR_SUCCESS : INTERNET_ERROR_BASE; /* FIXME*/
-}
-
-static BOOL FTPFILE_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWORD size, DWORD *written)
-{
- LPWININETFTPFILE lpwh = (LPWININETFTPFILE) hdr;
- int res;
-
- res = send(lpwh->nDataSocket, buffer, size, 0);
-
- *written = res>0 ? res : 0;
- return res >= 0;
-}
-
-static const HANDLEHEADERVtbl FTPFILEVtbl = {
- FTPFILE_Destroy,
- NULL,
- FTPFILE_QueryOption,
- NULL,
- FTPFILE_ReadFile,
- NULL,
- FTPFILE_WriteFile,
- NULL,
- NULL
-};
-
-/***********************************************************************
- * FTP_FtpOpenFileW (Internal)
- *
- * Open a remote file for writing or reading
- *
- * RETURNS
- * HINTERNET handle on success
- * NULL on failure
- *
- */
-HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs,
- LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
- DWORD_PTR dwContext)
-{
- INT nDataSocket;
- BOOL bSuccess = FALSE;
- LPWININETFTPFILE lpwh = NULL;
- LPWININETAPPINFOW hIC = NULL;
- HINTERNET handle = NULL;
-
- TRACE("\n");
-
- /* Clear any error information */
- INTERNET_SetLastError(0);
-
- if (GENERIC_READ == fdwAccess)
- {
- /* Set up socket to retrieve data */
- bSuccess = FTP_SendRetrieve(lpwfs, lpszFileName, dwFlags);
- }
- else if (GENERIC_WRITE == fdwAccess)
- {
- /* Set up socket to send data */
- bSuccess = FTP_SendStore(lpwfs, lpszFileName, dwFlags);
- }
-
- /* Get data socket to server */
- if (bSuccess && FTP_GetDataSocket(lpwfs, &nDataSocket))
- {
- lpwh = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPFILE));
- lpwh->hdr.htype = WH_HFILE;
- lpwh->hdr.vtbl = &FTPFILEVtbl;
- lpwh->hdr.dwFlags = dwFlags;
- lpwh->hdr.dwContext = dwContext;
- lpwh->hdr.refs = 1;
- lpwh->hdr.lpfnStatusCB = lpwfs->hdr.lpfnStatusCB;
- lpwh->nDataSocket = nDataSocket;
- lpwh->session_deleted = FALSE;
-
- WININET_AddRef( &lpwfs->hdr );
- lpwh->lpFtpSession = lpwfs;
- list_add_head( &lpwfs->hdr.children, &lpwh->hdr.entry );
-
- handle = WININET_AllocHandle( &lpwh->hdr );
- if( !handle )
- goto lend;
-
- /* Indicate that a download is currently in progress */
- lpwfs->download_in_progress = lpwh;
- }
-
- if (lpwfs->lstnSocket != -1)
- closesocket(lpwfs->lstnSocket);
-
- hIC = lpwfs->lpAppInfo;
- if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- INTERNET_ASYNC_RESULT iar;
-
- if (lpwh)
- {
- iar.dwResult = (DWORD)handle;
- iar.dwError = ERROR_SUCCESS;
- SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
- &iar, sizeof(INTERNET_ASYNC_RESULT));
- }
-
- iar.dwResult = (DWORD)bSuccess;
- iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
- SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
- &iar, sizeof(INTERNET_ASYNC_RESULT));
- }
-
-lend:
- if( lpwh )
- WININET_Release( &lpwh->hdr );
-
- return handle;
-}
-
-
/***********************************************************************
* FtpGetFileA (WININET.@)
*
@@ -1377,8 +1575,8 @@ BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszN
LPWSTR lpwzNewFile;
BOOL ret;
- lpwzRemoteFile = lpszRemoteFile?WININET_strdup_AtoW(lpszRemoteFile):NULL;
- lpwzNewFile = lpszNewFile?WININET_strdup_AtoW(lpszNewFile):NULL;
+ lpwzRemoteFile = heap_strdupAtoW(lpszRemoteFile);
+ lpwzNewFile = heap_strdupAtoW(lpszNewFile);
ret = FtpGetFileW(hInternet, lpwzRemoteFile, lpwzNewFile, fFailIfExists,
dwLocalFlagsAttribute, dwInternetFlags, dwContext);
HeapFree(GetProcessHeap(), 0, lpwzRemoteFile);
@@ -1390,7 +1588,7 @@ BOOL WINAPI FtpGetFileA(HINTERNET hInternet, LPCSTR lpszRemoteFile, LPCSTR lpszN
static void AsyncFtpGetFileProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPGETFILEW const *req = &workRequest->u.FtpGetFileW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -1416,8 +1614,8 @@ BOOL WINAPI FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lps
BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
DWORD_PTR dwContext)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
BOOL r = FALSE;
if (!lpszRemoteFile || !lpszNewFile)
@@ -1426,7 +1624,7 @@ BOOL WINAPI FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lps
return FALSE;
}
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hInternet );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hInternet );
if (!lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -1460,14 +1658,14 @@ BOOL WINAPI FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lps
workRequest.asyncproc = AsyncFtpGetFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpGetFileW;
- req->lpszRemoteFile = WININET_strdupW(lpszRemoteFile);
- req->lpszNewFile = WININET_strdupW(lpszNewFile);
+ req->lpszRemoteFile = heap_strdupW(lpszRemoteFile);
+ req->lpszNewFile = heap_strdupW(lpszNewFile);
req->dwLocalFlagsAttribute = dwLocalFlagsAttribute;
req->fFailIfExists = fFailIfExists;
req->dwFlags = dwInternetFlags;
req->dwContext = dwContext;
- r = INTERNET_AsyncCall(&workRequest);
+ r = res_to_le(INTERNET_AsyncCall(&workRequest));
}
else
{
@@ -1492,13 +1690,13 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
+static BOOL FTP_FtpGetFileW(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
DWORD_PTR dwContext)
{
BOOL bSuccess = FALSE;
HANDLE hFile;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", debugstr_w(lpszRemoteFile), debugstr_w(lpszNewFile));
@@ -1537,7 +1735,10 @@ static BOOL FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile,
}
if (lpwfs->lstnSocket != -1)
+ {
closesocket(lpwfs->lstnSocket);
+ lpwfs->lstnSocket = -1;
+ }
CloseHandle(hFile);
@@ -1584,7 +1785,7 @@ BOOL WINAPI FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
LPWSTR lpwzFileName;
BOOL ret;
- lpwzFileName = lpszFileName?WININET_strdup_AtoW(lpszFileName):NULL;
+ lpwzFileName = heap_strdupAtoW(lpszFileName);
ret = FtpDeleteFileW(hFtpSession, lpwzFileName);
HeapFree(GetProcessHeap(), 0, lpwzFileName);
return ret;
@@ -1593,7 +1794,7 @@ BOOL WINAPI FtpDeleteFileA(HINTERNET hFtpSession, LPCSTR lpszFileName)
static void AsyncFtpDeleteFileProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPDELETEFILEW const *req = &workRequest->u.FtpDeleteFileW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -1613,11 +1814,11 @@ static void AsyncFtpDeleteFileProc(WORKREQUEST *workRequest)
*/
BOOL WINAPI FtpDeleteFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
BOOL r = FALSE;
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hFtpSession );
if (!lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -1651,9 +1852,9 @@ BOOL WINAPI FtpDeleteFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName)
workRequest.asyncproc = AsyncFtpDeleteFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpDeleteFileW;
- req->lpszFilename = WININET_strdupW(lpszFileName);
+ req->lpszFilename = heap_strdupW(lpszFileName);
- r = INTERNET_AsyncCall(&workRequest);
+ r = res_to_le(INTERNET_AsyncCall(&workRequest));
}
else
{
@@ -1676,11 +1877,11 @@ lend:
* FALSE on failure
*
*/
-BOOL FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName)
+BOOL FTP_FtpDeleteFileW(ftp_session_t *lpwfs, LPCWSTR lpszFileName)
{
INT nResCode;
BOOL bSuccess = FALSE;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
TRACE("%p\n", lpwfs);
@@ -1729,7 +1930,7 @@ BOOL WINAPI FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
LPWSTR lpwzDirectory;
BOOL ret;
- lpwzDirectory = lpszDirectory?WININET_strdup_AtoW(lpszDirectory):NULL;
+ lpwzDirectory = heap_strdupAtoW(lpszDirectory);
ret = FtpRemoveDirectoryW(hFtpSession, lpwzDirectory);
HeapFree(GetProcessHeap(), 0, lpwzDirectory);
return ret;
@@ -1738,7 +1939,7 @@ BOOL WINAPI FtpRemoveDirectoryA(HINTERNET hFtpSession, LPCSTR lpszDirectory)
static void AsyncFtpRemoveDirectoryProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPREMOVEDIRECTORYW const *req = &workRequest->u.FtpRemoveDirectoryW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -1758,11 +1959,11 @@ static void AsyncFtpRemoveDirectoryProc(WORKREQUEST *workRequest)
*/
BOOL WINAPI FtpRemoveDirectoryW(HINTERNET hFtpSession, LPCWSTR lpszDirectory)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
BOOL r = FALSE;
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hFtpSession );
if (!lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -1796,9 +1997,9 @@ BOOL WINAPI FtpRemoveDirectoryW(HINTERNET hFtpSession, LPCWSTR lpszDirectory)
workRequest.asyncproc = AsyncFtpRemoveDirectoryProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpRemoveDirectoryW;
- req->lpszDirectory = WININET_strdupW(lpszDirectory);
+ req->lpszDirectory = heap_strdupW(lpszDirectory);
- r = INTERNET_AsyncCall(&workRequest);
+ r = res_to_le(INTERNET_AsyncCall(&workRequest));
}
else
{
@@ -1821,11 +2022,11 @@ lend:
* FALSE on failure
*
*/
-BOOL FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory)
+BOOL FTP_FtpRemoveDirectoryW(ftp_session_t *lpwfs, LPCWSTR lpszDirectory)
{
INT nResCode;
BOOL bSuccess = FALSE;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
TRACE("\n");
@@ -1876,8 +2077,8 @@ BOOL WINAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDes
LPWSTR lpwzDest;
BOOL ret;
- lpwzSrc = lpszSrc?WININET_strdup_AtoW(lpszSrc):NULL;
- lpwzDest = lpszDest?WININET_strdup_AtoW(lpszDest):NULL;
+ lpwzSrc = heap_strdupAtoW(lpszSrc);
+ lpwzDest = heap_strdupAtoW(lpszDest);
ret = FtpRenameFileW(hFtpSession, lpwzSrc, lpwzDest);
HeapFree(GetProcessHeap(), 0, lpwzSrc);
HeapFree(GetProcessHeap(), 0, lpwzDest);
@@ -1887,7 +2088,7 @@ BOOL WINAPI FtpRenameFileA(HINTERNET hFtpSession, LPCSTR lpszSrc, LPCSTR lpszDes
static void AsyncFtpRenameFileProc(WORKREQUEST *workRequest)
{
struct WORKREQ_FTPRENAMEFILEW const *req = &workRequest->u.FtpRenameFileW;
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) workRequest->hdr;
TRACE("%p\n", lpwfs);
@@ -1908,11 +2109,11 @@ static void AsyncFtpRenameFileProc(WORKREQUEST *workRequest)
*/
BOOL WINAPI FtpRenameFileW(HINTERNET hFtpSession, LPCWSTR lpszSrc, LPCWSTR lpszDest)
{
- LPWININETFTPSESSIONW lpwfs;
- LPWININETAPPINFOW hIC = NULL;
+ ftp_session_t *lpwfs;
+ appinfo_t *hIC = NULL;
BOOL r = FALSE;
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hFtpSession );
if (!lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -1946,10 +2147,10 @@ BOOL WINAPI FtpRenameFileW(HINTERNET hFtpSession, LPCWSTR lpszSrc, LPCWSTR lpszD
workRequest.asyncproc = AsyncFtpRenameFileProc;
workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
req = &workRequest.u.FtpRenameFileW;
- req->lpszSrcFile = WININET_strdupW(lpszSrc);
- req->lpszDestFile = WININET_strdupW(lpszDest);
+ req->lpszSrcFile = heap_strdupW(lpszSrc);
+ req->lpszDestFile = heap_strdupW(lpszDest);
- r = INTERNET_AsyncCall(&workRequest);
+ r = res_to_le(INTERNET_AsyncCall(&workRequest));
}
else
{
@@ -1972,12 +2173,11 @@ lend:
* FALSE on failure
*
*/
-BOOL FTP_FtpRenameFileW( LPWININETFTPSESSIONW lpwfs,
- LPCWSTR lpszSrc, LPCWSTR lpszDest)
+BOOL FTP_FtpRenameFileW(ftp_session_t *lpwfs, LPCWSTR lpszSrc, LPCWSTR lpszDest)
{
INT nResCode;
BOOL bSuccess = FALSE;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
TRACE("\n");
@@ -2040,7 +2240,7 @@ BOOL WINAPI FtpCommandA( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags
return FALSE;
}
- if (!(cmdW = WININET_strdup_AtoW(lpszCommand)))
+ if (!(cmdW = heap_strdupAtoW(lpszCommand)))
{
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
@@ -2059,7 +2259,7 @@ BOOL WINAPI FtpCommandW( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags
LPCWSTR lpszCommand, DWORD_PTR dwContext, HINTERNET* phFtpCommand )
{
BOOL r = FALSE;
- LPWININETFTPSESSIONW lpwfs;
+ ftp_session_t *lpwfs;
LPSTR cmd = NULL;
DWORD len, nBytesSent= 0;
INT nResCode, nRC = 0;
@@ -2079,7 +2279,7 @@ BOOL WINAPI FtpCommandW( HINTERNET hConnect, BOOL fExpectResponse, DWORD dwFlags
return FALSE;
}
- lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
+ lpwfs = (ftp_session_t*) WININET_GetObject( hConnect );
if (!lpwfs)
{
INTERNET_SetLastError(ERROR_INVALID_HANDLE);
@@ -2142,9 +2342,9 @@ lend:
*
* Deallocate session handle
*/
-static void FTPSESSION_Destroy(WININETHANDLEHEADER *hdr)
+static void FTPSESSION_Destroy(object_header_t *hdr)
{
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) hdr;
TRACE("\n");
@@ -2152,12 +2352,13 @@ static void FTPSESSION_Destroy(WININETHANDLEHEADER *hdr)
HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword);
HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName);
+ HeapFree(GetProcessHeap(), 0, lpwfs->servername);
HeapFree(GetProcessHeap(), 0, lpwfs);
}
-static void FTPSESSION_CloseConnection(WININETHANDLEHEADER *hdr)
+static void FTPSESSION_CloseConnection(object_header_t *hdr)
{
- LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr;
+ ftp_session_t *lpwfs = (ftp_session_t*) hdr;
TRACE("\n");
@@ -2180,7 +2381,7 @@ static void FTPSESSION_CloseConnection(WININETHANDLEHEADER *hdr)
INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
}
-static DWORD FTPSESSION_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
+static DWORD FTPSESSION_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
{
switch(option) {
case INTERNET_OPTION_HANDLE_TYPE:
@@ -2197,7 +2398,7 @@ static DWORD FTPSESSION_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void
return INET_QueryOption(option, buffer, size, unicode);
}
-static const HANDLEHEADERVtbl FTPSESSIONVtbl = {
+static const object_vtbl_t FTPSESSIONVtbl = {
FTPSESSION_Destroy,
FTPSESSION_CloseConnection,
FTPSESSION_QueryOption,
@@ -2230,7 +2431,7 @@ static const HANDLEHEADERVtbl FTPSESSIONVtbl = {
*
*/
-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)
@@ -2247,8 +2448,9 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
INT nsocket = -1;
UINT sock_namelen;
BOOL bSuccess = FALSE;
- LPWININETFTPSESSIONW lpwfs = NULL;
+ ftp_session_t *lpwfs = NULL;
HINTERNET handle = NULL;
+ char szaddr[INET_ADDRSTRLEN];
TRACE("%p Server(%s) Port(%d) User(%s) Paswd(%s)\n",
hIC, debugstr_w(lpszServerName),
@@ -2256,13 +2458,13 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
assert( hIC->hdr.htype == WH_HINIT );
- if (NULL == lpszUserName && NULL != lpszPassword)
+ if ((!lpszUserName || !*lpszUserName) && lpszPassword && *lpszPassword)
{
INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
goto lerror;
}
- lpwfs = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFTPSESSIONW));
+ lpwfs = HeapAlloc(GetProcessHeap(), 0, sizeof(ftp_session_t));
if (NULL == lpwfs)
{
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
@@ -2270,7 +2472,9 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
}
if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
- nServerPort = INTERNET_DEFAULT_FTP_PORT;
+ lpwfs->serverport = INTERNET_DEFAULT_FTP_PORT;
+ else
+ lpwfs->serverport = nServerPort;
lpwfs->hdr.htype = WH_HFTPSESSION;
lpwfs->hdr.vtbl = &FTPSESSIONVtbl;
@@ -2302,12 +2506,12 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
if(hIC->lpszProxyBypass)
FIXME("Proxy bypass is ignored.\n");
}
- if ( !lpszUserName) {
+ if (!lpszUserName || !strlenW(lpszUserName)) {
HKEY key;
WCHAR szPassword[MAX_PATH];
DWORD len = sizeof(szPassword);
- lpwfs->lpszUserName = WININET_strdupW(szDefaultUsername);
+ lpwfs->lpszUserName = heap_strdupW(szDefaultUsername);
RegOpenKeyW(HKEY_CURRENT_USER, szKey, &key);
if (RegQueryValueExW(key, szValue, NULL, NULL, (LPBYTE)szPassword, &len)) {
@@ -2320,23 +2524,20 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
RegCloseKey(key);
TRACE("Password used for anonymous ftp : (%s)\n", debugstr_w(szPassword));
- lpwfs->lpszPassword = WININET_strdupW(szPassword);
+ lpwfs->lpszPassword = heap_strdupW(szPassword);
}
else {
- lpwfs->lpszUserName = WININET_strdupW(lpszUserName);
-
- if (lpszPassword)
- lpwfs->lpszPassword = WININET_strdupW(lpszPassword);
- else
- lpwfs->lpszPassword = WININET_strdupW(szEmpty);
+ lpwfs->lpszUserName = heap_strdupW(lpszUserName);
+ lpwfs->lpszPassword = heap_strdupW(lpszPassword ? lpszPassword : szEmpty);
}
+ lpwfs->servername = heap_strdupW(lpszServerName);
/* Don't send a handle created callback if this handle was created with InternetOpenUrl */
if (!(lpwfs->hdr.dwInternalFlags & INET_OPENURL))
{
INTERNET_ASYNC_RESULT iar;
- iar.dwResult = (DWORD)handle;
+ iar.dwResult = (DWORD_PTR)handle;
iar.dwError = ERROR_SUCCESS;
SendAsyncCallback(&hIC->hdr, dwContext,
@@ -2345,16 +2546,25 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
}
SendAsyncCallback(&hIC->hdr, dwContext, INTERNET_STATUS_RESOLVING_NAME,
- (LPWSTR) lpszServerName, strlenW(lpszServerName));
+ (LPWSTR) lpszServerName, (strlenW(lpszServerName)+1) * sizeof(WCHAR));
- if (!GetAddress(lpszServerName, nServerPort, &socketAddr))
+ sock_namelen = sizeof(socketAddr);
+ if (!GetAddress(lpszServerName, lpwfs->serverport, (struct sockaddr *)&socketAddr, &sock_namelen))
{
INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
goto lerror;
}
+ if (socketAddr.sin_family != AF_INET)
+ {
+ WARN("unsupported address family %d\n", socketAddr.sin_family);
+ INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
+ goto lerror;
+ }
+
+ inet_ntop(socketAddr.sin_family, &socketAddr.sin_addr, szaddr, sizeof(szaddr));
SendAsyncCallback(&hIC->hdr, dwContext, INTERNET_STATUS_NAME_RESOLVED,
- (LPWSTR) lpszServerName, strlenW(lpszServerName));
+ szaddr, strlen(szaddr)+1);
nsocket = socket(AF_INET,SOCK_STREAM,0);
if (nsocket == -1)
@@ -2364,19 +2574,20 @@ HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
}
SendAsyncCallback(&hIC->hdr, dwContext, INTERNET_STATUS_CONNECTING_TO_SERVER,
- &socketAddr, sizeof(struct sockaddr_in));
+ szaddr, strlen(szaddr)+1);
- if (connect(nsocket, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) < 0)
+ if (connect(nsocket, (struct sockaddr *)&socketAddr, sock_namelen) < 0)
{
ERR("Unable to connect (%s)\n", strerror(errno));
INTERNET_SetLastError(ERROR_INTERNET_CANNOT_CONNECT);
+ closesocket(nsocket);
}
else
{
TRACE("Connected to server\n");
lpwfs->sndSocket = nsocket;
SendAsyncCallback(&hIC->hdr, dwContext, INTERNET_STATUS_CONNECTED_TO_SERVER,
- &socketAddr, sizeof(struct sockaddr_in));
+ szaddr, strlen(szaddr)+1);
sock_namelen = sizeof(lpwfs->socketAddress);
getsockname(nsocket, (struct sockaddr *) &lpwfs->socketAddress, &sock_namelen);
@@ -2397,16 +2608,6 @@ lerror:
handle = NULL;
}
- if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- INTERNET_ASYNC_RESULT iar;
-
- iar.dwResult = bSuccess ? (DWORD_PTR)lpwfs : 0;
- iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
- SendAsyncCallback(&hIC->hdr, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
- &iar, sizeof(INTERNET_ASYNC_RESULT));
- }
-
return handle;
}
@@ -2421,7 +2622,7 @@ lerror:
* NULL on failure
*
*/
-static BOOL FTP_ConnectToHost(LPWININETFTPSESSIONW lpwfs)
+static BOOL FTP_ConnectToHost(ftp_session_t *lpwfs)
{
INT nResCode;
BOOL bSuccess = FALSE;
@@ -2465,7 +2666,7 @@ lend:
*
*/
static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
- INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext)
+ INTERNET_STATUS_CALLBACK lpfnStatusCB, object_header_t *hdr, DWORD_PTR dwContext)
{
DWORD len;
CHAR *buf;
@@ -2520,10 +2721,10 @@ static BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
*
*/
static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
- INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD_PTR dwContext)
+ INTERNET_STATUS_CALLBACK lpfnStatusCB, object_header_t *hdr, DWORD_PTR dwContext)
{
BOOL ret;
- LPSTR lpszParamA = lpszParam?WININET_strdup_WtoA(lpszParam):NULL;
+ LPSTR lpszParamA = heap_strdupWtoA(lpszParam);
ret = FTP_SendCommandA(nSocket, ftpCmd, lpszParamA, lpfnStatusCB, hdr, dwContext);
HeapFree(GetProcessHeap(), 0, lpszParamA);
return ret;
@@ -2539,7 +2740,7 @@ static BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
* 0 on failure
*
*/
-INT FTP_ReceiveResponse(LPWININETFTPSESSIONW lpwfs, DWORD_PTR dwContext)
+INT FTP_ReceiveResponse(ftp_session_t *lpwfs, DWORD_PTR dwContext)
{
LPSTR lpszResponse = INTERNET_GetResponseBuffer();
DWORD nRecv;
@@ -2602,7 +2803,7 @@ lerror:
* NULL on failure
*
*/
-static BOOL FTP_SendPassword(LPWININETFTPSESSIONW lpwfs)
+static BOOL FTP_SendPassword(ftp_session_t *lpwfs)
{
INT nResCode;
BOOL bSuccess = FALSE;
@@ -2642,7 +2843,7 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_SendAccount(LPWININETFTPSESSIONW lpwfs)
+static BOOL FTP_SendAccount(ftp_session_t *lpwfs)
{
INT nResCode;
BOOL bSuccess = FALSE;
@@ -2672,7 +2873,7 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_SendStore(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
+static BOOL FTP_SendStore(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
{
INT nResCode;
BOOL bSuccess = FALSE;
@@ -2719,10 +2920,10 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs)
+static BOOL FTP_InitListenSocket(ftp_session_t *lpwfs)
{
BOOL bSuccess = FALSE;
- socklen_t namelen = sizeof(struct sockaddr_in);
+ socklen_t namelen = sizeof(lpwfs->lstnSocketAddress);
TRACE("\n");
@@ -2737,9 +2938,9 @@ static BOOL FTP_InitListenSocket(LPWININETFTPSESSIONW lpwfs)
lpwfs->lstnSocketAddress = lpwfs->socketAddress;
/* and get the system to assign us a port */
- lpwfs->lstnSocketAddress.sin_port = htons((u_short) 0);
+ lpwfs->lstnSocketAddress.sin_port = htons(0);
- if (bind(lpwfs->lstnSocket,(struct sockaddr *) &lpwfs->lstnSocketAddress, sizeof(struct sockaddr_in)) == -1)
+ if (bind(lpwfs->lstnSocket,(struct sockaddr *) &lpwfs->lstnSocketAddress, sizeof(lpwfs->lstnSocketAddress)) == -1)
{
TRACE("Unable to bind socket\n");
goto lend;
@@ -2778,7 +2979,7 @@ lend:
* (i.e. it sends it always),
* so we probably don't want to do that either.
*/
-static BOOL FTP_SendType(LPWININETFTPSESSIONW lpwfs, DWORD dwType)
+static BOOL FTP_SendType(ftp_session_t *lpwfs, DWORD dwType)
{
INT nResCode;
WCHAR type[] = { 'I','\0' };
@@ -2816,7 +3017,7 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_GetFileSize(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD *dwSize)
+static BOOL FTP_GetFileSize(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD *dwSize)
{
INT nResCode;
BOOL bSuccess = FALSE;
@@ -2860,7 +3061,7 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_SendPort(LPWININETFTPSESSIONW lpwfs)
+static BOOL FTP_SendPort(ftp_session_t *lpwfs)
{
static const WCHAR szIPFormat[] = {'%','d',',','%','d',',','%','d',',','%','d',',','%','d',',','%','d','\0'};
INT nResCode;
@@ -2904,7 +3105,7 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_DoPassive(LPWININETFTPSESSIONW lpwfs)
+static BOOL FTP_DoPassive(ftp_session_t *lpwfs)
{
INT nResCode;
BOOL bSuccess = FALSE;
@@ -2976,7 +3177,7 @@ lend:
}
-static BOOL FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs)
+static BOOL FTP_SendPortOrPasv(ftp_session_t *lpwfs)
{
if (lpwfs->hdr.dwFlags & INTERNET_FLAG_PASSIVE)
{
@@ -3005,7 +3206,7 @@ static BOOL FTP_SendPortOrPasv(LPWININETFTPSESSIONW lpwfs)
* FALSE on failure
*
*/
-static BOOL FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs, LPINT nDataSocket)
+static BOOL FTP_GetDataSocket(ftp_session_t *lpwfs, LPINT nDataSocket)
{
struct sockaddr_in saddr;
socklen_t addrlen = sizeof(struct sockaddr);
@@ -3014,6 +3215,7 @@ static BOOL FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs, LPINT nDataSocket)
if (lpwfs->hdr.dwFlags & INTERNET_FLAG_PASSIVE)
{
*nDataSocket = lpwfs->pasvSocket;
+ lpwfs->pasvSocket = -1;
}
else
{
@@ -3035,7 +3237,7 @@ static BOOL FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs, LPINT nDataSocket)
* FALSE on failure
*
*/
-static BOOL FTP_SendData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile)
+static BOOL FTP_SendData(ftp_session_t *lpwfs, INT nDataSocket, HANDLE hFile)
{
BY_HANDLE_FILE_INFORMATION fi;
DWORD nBytesRead = 0;
@@ -3116,7 +3318,7 @@ static BOOL FTP_SendData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFi
* 0 on failure
*
*/
-static BOOL FTP_SendRetrieve(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
+static BOOL FTP_SendRetrieve(ftp_session_t *lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType)
{
INT nResCode;
BOOL ret;
@@ -3162,7 +3364,7 @@ lend:
* FALSE on failure
*
*/
-static BOOL FTP_RetrieveFileData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile)
+static BOOL FTP_RetrieveFileData(ftp_session_t *lpwfs, INT nDataSocket, HANDLE hFile)
{
DWORD nBytesWritten;
INT nRC = 0;
@@ -3202,7 +3404,7 @@ recv_end:
*
* Deallocate session handle
*/
-static void FTPFINDNEXT_Destroy(WININETHANDLEHEADER *hdr)
+static void FTPFINDNEXT_Destroy(object_header_t *hdr)
{
LPWININETFTPFINDNEXTW lpwfn = (LPWININETFTPFINDNEXTW) hdr;
DWORD i;
@@ -3220,7 +3422,7 @@ static void FTPFINDNEXT_Destroy(WININETHANDLEHEADER *hdr)
HeapFree(GetProcessHeap(), 0, lpwfn);
}
-static DWORD WINAPI FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW *find, LPVOID data)
+static DWORD FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW *find, LPVOID data)
{
WIN32_FIND_DATAW *find_data = data;
DWORD res = ERROR_SUCCESS;
@@ -3260,7 +3462,7 @@ static void FTPFINDNEXT_AsyncFindNextFileProc(WORKREQUEST *workRequest)
FTPFINDNEXT_FindNextFileProc((WININETFTPFINDNEXTW*)workRequest->hdr, req->lpFindFileData);
}
-static DWORD FTPFINDNEXT_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
+static DWORD FTPFINDNEXT_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
{
switch(option) {
case INTERNET_OPTION_HANDLE_TYPE:
@@ -3277,7 +3479,7 @@ static DWORD FTPFINDNEXT_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, voi
return INET_QueryOption(option, buffer, size, unicode);
}
-static DWORD FTPFINDNEXT_FindNextFileW(WININETHANDLEHEADER *hdr, void *data)
+static DWORD FTPFINDNEXT_FindNextFileW(object_header_t *hdr, void *data)
{
WININETFTPFINDNEXTW *find = (WININETFTPFINDNEXTW*)hdr;
@@ -3299,7 +3501,7 @@ static DWORD FTPFINDNEXT_FindNextFileW(WININETHANDLEHEADER *hdr, void *data)
return FTPFINDNEXT_FindNextFileProc(find, data);
}
-static const HANDLEHEADERVtbl FTPFINDNEXTVtbl = {
+static const object_vtbl_t FTPFINDNEXTVtbl = {
FTPFINDNEXT_Destroy,
NULL,
FTPFINDNEXT_QueryOption,
@@ -3308,6 +3510,7 @@ static const HANDLEHEADERVtbl FTPFINDNEXTVtbl = {
NULL,
NULL,
NULL,
+ NULL,
FTPFINDNEXT_FindNextFileW
};
@@ -3321,7 +3524,7 @@ static const HANDLEHEADERVtbl FTPFINDNEXTVtbl = {
* NULL on failure
*
*/
-static HINTERNET FTP_ReceiveFileList(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
+static HINTERNET FTP_ReceiveFileList(ftp_session_t *lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
LPWIN32_FIND_DATAW lpFindFileData, DWORD_PTR dwContext)
{
DWORD dwSize = 0;
@@ -3382,9 +3585,7 @@ static BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFi
if (lpafp)
{
- /* Convert 'Unix' time to Windows time */
- RtlSecondsSince1970ToTime(mktime(&lpafp->tmLastModified),
- (LARGE_INTEGER *) &(lpFindFileData->ftLastAccessTime));
+ SystemTimeToFileTime( &lpafp->tmLastModified, &lpFindFileData->ftLastAccessTime );
lpFindFileData->ftLastWriteTime = lpFindFileData->ftLastAccessTime;
lpFindFileData->ftCreationTime = lpFindFileData->ftLastAccessTime;
@@ -3452,12 +3653,12 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT
lpfp->nSize = atol(pszToken);
}
- lpfp->tmLastModified.tm_sec = 0;
- lpfp->tmLastModified.tm_min = 0;
- lpfp->tmLastModified.tm_hour = 0;
- lpfp->tmLastModified.tm_mday = 0;
- lpfp->tmLastModified.tm_mon = 0;
- lpfp->tmLastModified.tm_year = 0;
+ lpfp->tmLastModified.wSecond = 0;
+ lpfp->tmLastModified.wMinute = 0;
+ lpfp->tmLastModified.wHour = 0;
+ lpfp->tmLastModified.wDay = 0;
+ lpfp->tmLastModified.wMonth = 0;
+ lpfp->tmLastModified.wYear = 0;
/* Determine month */
pszToken = strtok(NULL, szSpace);
@@ -3465,38 +3666,35 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT
if(strlen(pszToken) >= 3) {
pszToken[3] = 0;
if((pszTmp = StrStrIA(szMonths, pszToken)))
- lpfp->tmLastModified.tm_mon = ((pszTmp - szMonths) / 3)+1;
+ lpfp->tmLastModified.wMonth = ((pszTmp - szMonths) / 3)+1;
}
/* Determine day */
pszToken = strtok(NULL, szSpace);
if(!pszToken) continue;
- lpfp->tmLastModified.tm_mday = atoi(pszToken);
+ lpfp->tmLastModified.wDay = atoi(pszToken);
/* Determine time or year */
pszToken = strtok(NULL, szSpace);
if(!pszToken) continue;
if((pszTmp = strchr(pszToken, ':'))) {
- struct tm* apTM;
- time_t aTime;
+ SYSTEMTIME curr_time;
*pszTmp = 0;
pszTmp++;
- lpfp->tmLastModified.tm_min = atoi(pszTmp);
- lpfp->tmLastModified.tm_hour = atoi(pszToken);
- time(&aTime);
- apTM = localtime(&aTime);
- lpfp->tmLastModified.tm_year = apTM->tm_year;
+ lpfp->tmLastModified.wMinute = atoi(pszTmp);
+ lpfp->tmLastModified.wHour = atoi(pszToken);
+ GetLocalTime( &curr_time );
+ lpfp->tmLastModified.wYear = curr_time.wYear;
}
else {
- lpfp->tmLastModified.tm_year = atoi(pszToken) - 1900;
- lpfp->tmLastModified.tm_hour = 12;
+ lpfp->tmLastModified.wYear = atoi(pszToken);
+ lpfp->tmLastModified.wHour = 12;
}
- TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
- lpfp->tmLastModified.tm_hour, lpfp->tmLastModified.tm_min, lpfp->tmLastModified.tm_sec,
- (lpfp->tmLastModified.tm_year >= 100) ? lpfp->tmLastModified.tm_year - 100 : lpfp->tmLastModified.tm_year,
- lpfp->tmLastModified.tm_mon, lpfp->tmLastModified.tm_mday);
+ TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n",
+ lpfp->tmLastModified.wHour, lpfp->tmLastModified.wMinute, lpfp->tmLastModified.wSecond,
+ lpfp->tmLastModified.wYear, lpfp->tmLastModified.wMonth, lpfp->tmLastModified.wDay);
pszToken = strtok(NULL, szSpace);
if(!pszToken) continue;
- lpfp->lpszName = WININET_strdup_AtoW(pszToken);
+ lpfp->lpszName = heap_strdupAtoW(pszToken);
TRACE("File: %s\n", debugstr_w(lpfp->lpszName));
}
/* NT way of parsing ... :
@@ -3505,32 +3703,31 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT
05-09-03 06:02PM 12656686 2003-04-21bgm_cmd_e.rgz
*/
else if(isdigit(pszToken[0]) && 8 == strlen(pszToken)) {
+ int mon, mday, year, hour, min;
lpfp->permissions = 0xFFFF; /* No idea, put full permission :-) */
- sscanf(pszToken, "%d-%d-%d",
- &lpfp->tmLastModified.tm_mon,
- &lpfp->tmLastModified.tm_mday,
- &lpfp->tmLastModified.tm_year);
+ sscanf(pszToken, "%d-%d-%d", &mon, &mday, &year);
+ lpfp->tmLastModified.wDay = mday;
+ lpfp->tmLastModified.wMonth = mon;
+ lpfp->tmLastModified.wYear = year;
/* Hacky and bad Y2K protection :-) */
- if (lpfp->tmLastModified.tm_year < 70)
- lpfp->tmLastModified.tm_year += 100;
-
+ if (lpfp->tmLastModified.wYear < 70) lpfp->tmLastModified.wYear += 2000;
+
pszToken = strtok(NULL, szSpace);
if(!pszToken) continue;
- sscanf(pszToken, "%d:%d",
- &lpfp->tmLastModified.tm_hour,
- &lpfp->tmLastModified.tm_min);
+ sscanf(pszToken, "%d:%d", &hour, &min);
+ lpfp->tmLastModified.wHour = hour;
+ lpfp->tmLastModified.wMinute = min;
if((pszToken[5] == 'P') && (pszToken[6] == 'M')) {
- lpfp->tmLastModified.tm_hour += 12;
+ lpfp->tmLastModified.wHour += 12;
}
- lpfp->tmLastModified.tm_sec = 0;
+ lpfp->tmLastModified.wSecond = 0;
+
+ TRACE("Mod time: %02d:%02d:%02d %04d/%02d/%02d\n",
+ lpfp->tmLastModified.wHour, lpfp->tmLastModified.wMinute, lpfp->tmLastModified.wSecond,
+ lpfp->tmLastModified.wYear, lpfp->tmLastModified.wMonth, lpfp->tmLastModified.wDay);
- TRACE("Mod time: %02d:%02d:%02d %02d/%02d/%02d\n",
- lpfp->tmLastModified.tm_hour, lpfp->tmLastModified.tm_min, lpfp->tmLastModified.tm_sec,
- (lpfp->tmLastModified.tm_year >= 100) ? lpfp->tmLastModified.tm_year - 100 : lpfp->tmLastModified.tm_year,
- lpfp->tmLastModified.tm_mon, lpfp->tmLastModified.tm_mday);
-
pszToken = strtok(NULL, szSpace);
if(!pszToken) continue;
if(!strcasecmp(pszToken, "")) {
@@ -3546,7 +3743,7 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT
pszToken = strtok(NULL, szSpace);
if(!pszToken) continue;
- lpfp->lpszName = WININET_strdup_AtoW(pszToken);
+ lpfp->lpszName = heap_strdupAtoW(pszToken);
TRACE("Name: %s\n", debugstr_w(lpfp->lpszName));
}
/* EPLF format - http://cr.yp.to/ftp/list/eplf.html */
@@ -3578,7 +3775,7 @@ static BOOL FTP_ParseNextFile(INT nSocket, LPCWSTR lpszSearchFile, LPFILEPROPERT
* TRUE on success
* FALSE on failure
*/
-static BOOL FTP_ParseDirectory(LPWININETFTPSESSIONW lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
+static BOOL FTP_ParseDirectory(ftp_session_t *lpwfs, INT nSocket, LPCWSTR lpszSearchFile,
LPFILEPROPERTIESW *lpafp, LPDWORD dwfp)
{
BOOL bSuccess = TRUE;
diff --git a/dll/win32/wininet/http.c b/dll/win32/wininet/http.c
index f0ad6beddc1..5b7459db6f7 100644
--- a/dll/win32/wininet/http.c
+++ b/dll/win32/wininet/http.c
@@ -29,6 +29,10 @@
#include "config.h"
#include "wine/port.h"
+#if defined(__MINGW32__) || defined (_MSC_VER)
+#include
+#endif
+
#include
#ifdef HAVE_SYS_SOCKET_H
# include
@@ -44,6 +48,9 @@
#endif
#include
#include
+#ifdef HAVE_ZLIB
+# include
+#endif
#include "windef.h"
#include "winbase.h"
@@ -59,6 +66,7 @@
#include "internet.h"
#include "wine/debug.h"
+#include "wine/exception.h"
#include "wine/unicode.h"
#include "inet_ntop.c"
@@ -67,23 +75,77 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet);
static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0};
static const WCHAR g_szHttp1_1[] = {'H','T','T','P','/','1','.','1',0};
-static const WCHAR g_szReferer[] = {'R','e','f','e','r','e','r',0};
-static const WCHAR g_szAccept[] = {'A','c','c','e','p','t',0};
-static const WCHAR g_szUserAgent[] = {'U','s','e','r','-','A','g','e','n','t',0};
-static const WCHAR szHost[] = { 'H','o','s','t',0 };
+static const WCHAR szOK[] = {'O','K',0};
+static const WCHAR szDefaultHeader[] = {'H','T','T','P','/','1','.','0',' ','2','0','0',' ','O','K',0};
+static const WCHAR hostW[] = { 'H','o','s','t',0 };
static const WCHAR szAuthorization[] = { 'A','u','t','h','o','r','i','z','a','t','i','o','n',0 };
static const WCHAR szProxy_Authorization[] = { 'P','r','o','x','y','-','A','u','t','h','o','r','i','z','a','t','i','o','n',0 };
static const WCHAR szStatus[] = { 'S','t','a','t','u','s',0 };
static const WCHAR szKeepAlive[] = {'K','e','e','p','-','A','l','i','v','e',0};
static const WCHAR szGET[] = { 'G','E','T', 0 };
+static const WCHAR szHEAD[] = { 'H','E','A','D', 0 };
+static const WCHAR szCrLf[] = {'\r','\n', 0};
+
+static const WCHAR szAccept[] = { 'A','c','c','e','p','t',0 };
+static const WCHAR szAccept_Charset[] = { 'A','c','c','e','p','t','-','C','h','a','r','s','e','t', 0 };
+static const WCHAR szAccept_Encoding[] = { 'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',0 };
+static const WCHAR szAccept_Language[] = { 'A','c','c','e','p','t','-','L','a','n','g','u','a','g','e',0 };
+static const WCHAR szAccept_Ranges[] = { 'A','c','c','e','p','t','-','R','a','n','g','e','s',0 };
+static const WCHAR szAge[] = { 'A','g','e',0 };
+static const WCHAR szAllow[] = { 'A','l','l','o','w',0 };
+static const WCHAR szCache_Control[] = { 'C','a','c','h','e','-','C','o','n','t','r','o','l',0 };
+static const WCHAR szConnection[] = { 'C','o','n','n','e','c','t','i','o','n',0 };
+static const WCHAR szContent_Base[] = { 'C','o','n','t','e','n','t','-','B','a','s','e',0 };
+static const WCHAR szContent_Encoding[] = { 'C','o','n','t','e','n','t','-','E','n','c','o','d','i','n','g',0 };
+static const WCHAR szContent_ID[] = { 'C','o','n','t','e','n','t','-','I','D',0 };
+static const WCHAR szContent_Language[] = { 'C','o','n','t','e','n','t','-','L','a','n','g','u','a','g','e',0 };
+static const WCHAR szContent_Length[] = { 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0 };
+static const WCHAR szContent_Location[] = { 'C','o','n','t','e','n','t','-','L','o','c','a','t','i','o','n',0 };
+static const WCHAR szContent_MD5[] = { 'C','o','n','t','e','n','t','-','M','D','5',0 };
+static const WCHAR szContent_Range[] = { 'C','o','n','t','e','n','t','-','R','a','n','g','e',0 };
+static const WCHAR szContent_Transfer_Encoding[] = { 'C','o','n','t','e','n','t','-','T','r','a','n','s','f','e','r','-','E','n','c','o','d','i','n','g',0 };
+static const WCHAR szContent_Type[] = { 'C','o','n','t','e','n','t','-','T','y','p','e',0 };
+static const WCHAR szCookie[] = { 'C','o','o','k','i','e',0 };
+static const WCHAR szDate[] = { 'D','a','t','e',0 };
+static const WCHAR szFrom[] = { 'F','r','o','m',0 };
+static const WCHAR szETag[] = { 'E','T','a','g',0 };
+static const WCHAR szExpect[] = { 'E','x','p','e','c','t',0 };
+static const WCHAR szExpires[] = { 'E','x','p','i','r','e','s',0 };
+static const WCHAR szIf_Match[] = { 'I','f','-','M','a','t','c','h',0 };
+static const WCHAR szIf_Modified_Since[] = { 'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0 };
+static const WCHAR szIf_None_Match[] = { 'I','f','-','N','o','n','e','-','M','a','t','c','h',0 };
+static const WCHAR szIf_Range[] = { 'I','f','-','R','a','n','g','e',0 };
+static const WCHAR szIf_Unmodified_Since[] = { 'I','f','-','U','n','m','o','d','i','f','i','e','d','-','S','i','n','c','e',0 };
+static const WCHAR szLast_Modified[] = { 'L','a','s','t','-','M','o','d','i','f','i','e','d',0 };
+static const WCHAR szLocation[] = { 'L','o','c','a','t','i','o','n',0 };
+static const WCHAR szMax_Forwards[] = { 'M','a','x','-','F','o','r','w','a','r','d','s',0 };
+static const WCHAR szMime_Version[] = { 'M','i','m','e','-','V','e','r','s','i','o','n',0 };
+static const WCHAR szPragma[] = { 'P','r','a','g','m','a',0 };
+static const WCHAR szProxy_Authenticate[] = { 'P','r','o','x','y','-','A','u','t','h','e','n','t','i','c','a','t','e',0 };
+static const WCHAR szProxy_Connection[] = { 'P','r','o','x','y','-','C','o','n','n','e','c','t','i','o','n',0 };
+static const WCHAR szPublic[] = { 'P','u','b','l','i','c',0 };
+static const WCHAR szRange[] = { 'R','a','n','g','e',0 };
+static const WCHAR szReferer[] = { 'R','e','f','e','r','e','r',0 };
+static const WCHAR szRetry_After[] = { 'R','e','t','r','y','-','A','f','t','e','r',0 };
+static const WCHAR szServer[] = { 'S','e','r','v','e','r',0 };
+static const WCHAR szSet_Cookie[] = { 'S','e','t','-','C','o','o','k','i','e',0 };
+static const WCHAR szTransfer_Encoding[] = { 'T','r','a','n','s','f','e','r','-','E','n','c','o','d','i','n','g',0 };
+static const WCHAR szUnless_Modified_Since[] = { 'U','n','l','e','s','s','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0 };
+static const WCHAR szUpgrade[] = { 'U','p','g','r','a','d','e',0 };
+static const WCHAR szURI[] = { 'U','R','I',0 };
+static const WCHAR szUser_Agent[] = { 'U','s','e','r','-','A','g','e','n','t',0 };
+static const WCHAR szVary[] = { 'V','a','r','y',0 };
+static const WCHAR szVia[] = { 'V','i','a',0 };
+static const WCHAR szWarning[] = { 'W','a','r','n','i','n','g',0 };
+static const WCHAR szWWW_Authenticate[] = { 'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',0 };
#define MAXHOSTNAME 100
#define MAX_FIELD_VALUE_LEN 256
#define MAX_FIELD_LEN 256
-#define HTTP_REFERER g_szReferer
-#define HTTP_ACCEPT g_szAccept
-#define HTTP_USERAGENT g_szUserAgent
+#define HTTP_REFERER szReferer
+#define HTTP_ACCEPT szAccept
+#define HTTP_USERAGENT szUser_Agent
#define HTTP_ADDHDR_FLAG_ADD 0x20000000
#define HTTP_ADDHDR_FLAG_ADD_IF_NEW 0x10000000
@@ -108,23 +170,54 @@ struct HttpAuthInfo
BOOL finished; /* finished authenticating */
};
-static BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr);
-static BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear);
-static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR value, DWORD dwModifier);
-static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer);
-static BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr);
-static INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField, INT index, BOOL Request);
-static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index);
-static LPWSTR HTTP_build_req( LPCWSTR *list, int len );
-static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD
- dwInfoLevel, LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD
- lpdwIndex);
-static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl);
-static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin);
-static BOOL HTTP_VerifyValidHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field);
-static void HTTP_DrainContent(WININETHTTPREQW *req);
-LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW req, LPCWSTR head)
+struct gzip_stream_t {
+#ifdef HAVE_ZLIB
+ z_stream zstream;
+#endif
+ BYTE buf[8192];
+ DWORD buf_size;
+ DWORD buf_pos;
+ BOOL end_of_data;
+};
+
+typedef struct _authorizationData
+{
+ struct list entry;
+
+ LPWSTR lpszwHost;
+ LPWSTR lpszwRealm;
+ LPSTR lpszAuthorization;
+ UINT AuthorizationLen;
+} authorizationData;
+
+static struct list basicAuthorizationCache = LIST_INIT(basicAuthorizationCache);
+
+static CRITICAL_SECTION authcache_cs;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+ 0, 0, &authcache_cs,
+ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": authcache_cs") }
+};
+static CRITICAL_SECTION authcache_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+static DWORD HTTP_OpenConnection(http_request_t *req);
+static BOOL HTTP_GetResponseHeaders(http_request_t *req, BOOL clear);
+static DWORD HTTP_ProcessHeader(http_request_t *req, LPCWSTR field, LPCWSTR value, DWORD dwModifier);
+static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer);
+static DWORD HTTP_InsertCustomHeader(http_request_t *req, LPHTTPHEADERW lpHdr);
+static INT HTTP_GetCustomHeaderIndex(http_request_t *req, LPCWSTR lpszField, INT index, BOOL Request);
+static BOOL HTTP_DeleteCustomHeader(http_request_t *req, DWORD index);
+static LPWSTR HTTP_build_req( LPCWSTR *list, int len );
+static DWORD HTTP_HttpQueryInfoW(http_request_t*, DWORD, LPVOID, LPDWORD, LPDWORD);
+static LPWSTR HTTP_GetRedirectURL(http_request_t *req, LPCWSTR lpszUrl);
+static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin);
+static BOOL HTTP_VerifyValidHeader(http_request_t *req, LPCWSTR field);
+static void HTTP_DrainContent(http_request_t *req);
+static BOOL HTTP_FinishedReading(http_request_t *req);
+
+static LPHTTPHEADERW HTTP_GetHeader(http_request_t *req, LPCWSTR head)
{
int HeaderIndex = 0;
HeaderIndex = HTTP_GetCustomHeaderIndex(req, head, 0, TRUE);
@@ -134,6 +227,91 @@ LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW req, LPCWSTR head)
return &req->pCustHeaders[HeaderIndex];
}
+#ifdef HAVE_ZLIB
+
+static voidpf wininet_zalloc(voidpf opaque, uInt items, uInt size)
+{
+ return HeapAlloc(GetProcessHeap(), 0, items*size);
+}
+
+static void wininet_zfree(voidpf opaque, voidpf address)
+{
+ HeapFree(GetProcessHeap(), 0, address);
+}
+
+static void init_gzip_stream(http_request_t *req)
+{
+ gzip_stream_t *gzip_stream;
+ int index, zres;
+
+ gzip_stream = HeapAlloc(GetProcessHeap(), 0, sizeof(gzip_stream_t));
+ gzip_stream->zstream.zalloc = wininet_zalloc;
+ gzip_stream->zstream.zfree = wininet_zfree;
+ gzip_stream->zstream.opaque = NULL;
+ gzip_stream->zstream.next_in = NULL;
+ gzip_stream->zstream.avail_in = 0;
+ gzip_stream->zstream.next_out = NULL;
+ gzip_stream->zstream.avail_out = 0;
+ gzip_stream->buf_pos = 0;
+ gzip_stream->buf_size = 0;
+ gzip_stream->end_of_data = FALSE;
+
+ zres = inflateInit2(&gzip_stream->zstream, 0x1f);
+ if(zres != Z_OK) {
+ ERR("inflateInit failed: %d\n", zres);
+ HeapFree(GetProcessHeap(), 0, gzip_stream);
+ return;
+ }
+
+ req->gzip_stream = gzip_stream;
+
+ index = HTTP_GetCustomHeaderIndex(req, szContent_Length, 0, FALSE);
+ if(index != -1)
+ HTTP_DeleteCustomHeader(req, index);
+}
+
+#else
+
+static void init_gzip_stream(http_request_t *req)
+{
+ ERR("gzip stream not supported, missing zlib.\n");
+}
+
+#endif
+
+/* set the request content length based on the headers */
+static DWORD set_content_length( http_request_t *lpwhr )
+{
+ static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0};
+ WCHAR encoding[20];
+ DWORD size;
+
+ size = sizeof(lpwhr->dwContentLength);
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
+ &lpwhr->dwContentLength, &size, NULL) != ERROR_SUCCESS)
+ lpwhr->dwContentLength = ~0u;
+
+ size = sizeof(encoding);
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_TRANSFER_ENCODING, encoding, &size, NULL) == ERROR_SUCCESS &&
+ !strcmpiW(encoding, szChunked))
+ {
+ lpwhr->dwContentLength = ~0u;
+ lpwhr->read_chunked = TRUE;
+ }
+
+ if(lpwhr->decoding) {
+ int encoding_idx;
+
+ static const WCHAR gzipW[] = {'g','z','i','p',0};
+
+ encoding_idx = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Encoding, 0, FALSE);
+ if(encoding_idx != -1 && !strcmpiW(lpwhr->pCustHeaders[encoding_idx].lpszValue, gzipW))
+ init_gzip_stream(lpwhr);
+ }
+
+ return lpwhr->dwContentLength;
+}
+
/***********************************************************************
* HTTP_Tokenize (internal)
*
@@ -146,21 +324,26 @@ static LPWSTR * HTTP_Tokenize(LPCWSTR string, LPCWSTR token_string)
int i;
LPCWSTR next_token;
- /* empty string has no tokens */
- if (*string)
- tokens++;
- /* count tokens */
- for (i = 0; string[i]; i++)
- if (!strncmpW(string+i, token_string, strlenW(token_string)))
- {
- DWORD j;
+ if (string)
+ {
+ /* empty string has no tokens */
+ if (*string)
tokens++;
- /* we want to skip over separators, but not the null terminator */
- for (j = 0; j < strlenW(token_string) - 1; j++)
- if (!string[i+j])
- break;
- i += j;
+ /* count tokens */
+ for (i = 0; string[i]; i++)
+ {
+ if (!strncmpW(string+i, token_string, strlenW(token_string)))
+ {
+ DWORD j;
+ tokens++;
+ /* we want to skip over separators, but not the null terminator */
+ for (j = 0; j < strlenW(token_string) - 1; j++)
+ if (!string[i+j])
+ break;
+ i += j;
+ }
}
+ }
/* add 1 for terminating NULL */
token_array = HeapAlloc(GetProcessHeap(), 0, (tokens+1) * sizeof(*token_array));
@@ -194,33 +377,14 @@ static void HTTP_FreeTokens(LPWSTR * token_array)
HeapFree(GetProcessHeap(), 0, token_array);
}
-/* **********************************************************************
- *
- * Helper functions for the HttpSendRequest(Ex) functions
- *
- */
-static void AsyncHttpSendRequestProc(WORKREQUEST *workRequest)
-{
- struct WORKREQ_HTTPSENDREQUESTW const *req = &workRequest->u.HttpSendRequestW;
- LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) workRequest->hdr;
-
- TRACE("%p\n", lpwhr);
-
- HTTP_HttpSendRequestW(lpwhr, req->lpszHeader,
- req->dwHeaderLength, req->lpOptional, req->dwOptionalLength,
- req->dwContentLength, req->bEndRequest);
-
- HeapFree(GetProcessHeap(), 0, req->lpszHeader);
-}
-
-static void HTTP_FixURL( LPWININETHTTPREQW lpwhr)
+static void HTTP_FixURL(http_request_t *lpwhr)
{
static const WCHAR szSlash[] = { '/',0 };
static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/', 0 };
/* If we don't have a path we set it to root */
if (NULL == lpwhr->lpszPath)
- lpwhr->lpszPath = WININET_strdupW(szSlash);
+ lpwhr->lpszPath = heap_strdupW(szSlash);
else /* remove \r and \n*/
{
int nLen = strlenW(lpwhr->lpszPath);
@@ -249,7 +413,7 @@ static void HTTP_FixURL( LPWININETHTTPREQW lpwhr)
}
}
-static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR verb, LPCWSTR path, LPCWSTR version )
+static LPWSTR HTTP_BuildHeaderRequestString( http_request_t *lpwhr, LPCWSTR verb, LPCWSTR path, LPCWSTR version )
{
LPWSTR requestString;
DWORD len, n;
@@ -258,7 +422,6 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve
LPWSTR p;
static const WCHAR szSpace[] = { ' ',0 };
- static const WCHAR szcrlf[] = {'\r','\n', 0};
static const WCHAR szColon[] = { ':',' ',0 };
static const WCHAR sztwocrlf[] = {'\r','\n','\r','\n', 0};
@@ -279,7 +442,7 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve
{
if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
{
- req[n++] = szcrlf;
+ req[n++] = szCrLf;
req[n++] = lpwhr->pCustHeaders[i].lpszField;
req[n++] = szColon;
req[n++] = lpwhr->pCustHeaders[i].lpszValue;
@@ -309,103 +472,176 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve
return requestString;
}
-static void HTTP_ProcessCookies( LPWININETHTTPREQW lpwhr )
+static void HTTP_ProcessCookies( http_request_t *lpwhr )
{
- static const WCHAR szSet_Cookie[] = { 'S','e','t','-','C','o','o','k','i','e',0 };
int HeaderIndex;
+ int numCookies = 0;
LPHTTPHEADERW setCookieHeader;
- HeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSet_Cookie, 0, FALSE);
- if (HeaderIndex == -1)
- return;
- setCookieHeader = &lpwhr->pCustHeaders[HeaderIndex];
-
- if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && setCookieHeader->lpszValue)
+ while((HeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSet_Cookie, numCookies, FALSE)) != -1)
{
- int nPosStart = 0, nPosEnd = 0, len;
- static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','/',0};
+ setCookieHeader = &lpwhr->pCustHeaders[HeaderIndex];
- while (setCookieHeader->lpszValue[nPosEnd] != '\0')
+ if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && setCookieHeader->lpszValue)
{
- LPWSTR buf_cookie, cookie_name, cookie_data;
+ int len;
+ static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','%','s',0};
LPWSTR buf_url;
- LPWSTR domain = NULL;
LPHTTPHEADERW Host;
- int nEqualPos = 0;
- while (setCookieHeader->lpszValue[nPosEnd] != ';' && setCookieHeader->lpszValue[nPosEnd] != ',' &&
- setCookieHeader->lpszValue[nPosEnd] != '\0')
- {
- nPosEnd++;
- }
- if (setCookieHeader->lpszValue[nPosEnd] == ';')
- {
- /* fixme: not case sensitive, strcasestr is gnu only */
- int nDomainPosEnd = 0;
- int nDomainPosStart = 0, nDomainLength = 0;
- static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0};
- LPWSTR lpszDomain = strstrW(&setCookieHeader->lpszValue[nPosEnd], szDomain);
- if (lpszDomain)
- { /* they have specified their own domain, lets use it */
- while (lpszDomain[nDomainPosEnd] != ';' && lpszDomain[nDomainPosEnd] != ',' &&
- lpszDomain[nDomainPosEnd] != '\0')
- {
- nDomainPosEnd++;
- }
- nDomainPosStart = strlenW(szDomain);
- nDomainLength = (nDomainPosEnd - nDomainPosStart) + 1;
- domain = HeapAlloc(GetProcessHeap(), 0, (nDomainLength + 1)*sizeof(WCHAR));
- lstrcpynW(domain, &lpszDomain[nDomainPosStart], nDomainLength + 1);
- }
- }
- if (setCookieHeader->lpszValue[nPosEnd] == '\0') break;
- buf_cookie = HeapAlloc(GetProcessHeap(), 0, ((nPosEnd - nPosStart) + 1)*sizeof(WCHAR));
- lstrcpynW(buf_cookie, &setCookieHeader->lpszValue[nPosStart], (nPosEnd - nPosStart) + 1);
- TRACE("%s\n", debugstr_w(buf_cookie));
- while (buf_cookie[nEqualPos] != '=' && buf_cookie[nEqualPos] != '\0')
- {
- nEqualPos++;
- }
- if (buf_cookie[nEqualPos] == '\0' || buf_cookie[nEqualPos + 1] == '\0')
- {
- HeapFree(GetProcessHeap(), 0, buf_cookie);
- break;
- }
-
- cookie_name = HeapAlloc(GetProcessHeap(), 0, (nEqualPos + 1)*sizeof(WCHAR));
- lstrcpynW(cookie_name, buf_cookie, nEqualPos + 1);
- cookie_data = &buf_cookie[nEqualPos + 1];
-
- Host = HTTP_GetHeader(lpwhr,szHost);
- len = lstrlenW((domain ? domain : (Host?Host->lpszValue:NULL))) +
- strlenW(lpwhr->lpszPath) + 9;
+ Host = HTTP_GetHeader(lpwhr, hostW);
+ len = lstrlenW(Host->lpszValue) + 9 + lstrlenW(lpwhr->lpszPath);
buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- sprintfW(buf_url, szFmt, (domain ? domain : (Host?Host->lpszValue:NULL))); /* FIXME PATH!!! */
- InternetSetCookieW(buf_url, cookie_name, cookie_data);
+ sprintfW(buf_url, szFmt, Host->lpszValue, lpwhr->lpszPath);
+ InternetSetCookieW(buf_url, NULL, setCookieHeader->lpszValue);
HeapFree(GetProcessHeap(), 0, buf_url);
- HeapFree(GetProcessHeap(), 0, buf_cookie);
- HeapFree(GetProcessHeap(), 0, cookie_name);
- HeapFree(GetProcessHeap(), 0, domain);
- nPosStart = nPosEnd;
}
+ numCookies++;
}
}
-static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue )
+static void strip_spaces(LPWSTR start)
{
- static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
- return !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) &&
- ((pszAuthValue[ARRAYSIZE(szBasic)] == ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]);
+ LPWSTR str = start;
+ LPWSTR end;
+
+ while (*str == ' ' && *str != '\0')
+ str++;
+
+ if (str != start)
+ memmove(start, str, sizeof(WCHAR) * (strlenW(str) + 1));
+
+ end = start + strlenW(start) - 1;
+ while (end >= start && *end == ' ')
+ {
+ *end = '\0';
+ end--;
+ }
}
-static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
+static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue, LPWSTR *pszRealm )
+{
+ static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
+ static const WCHAR szRealm[] = {'r','e','a','l','m'}; /* Note: not nul-terminated */
+ BOOL is_basic;
+ is_basic = !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) &&
+ ((pszAuthValue[ARRAYSIZE(szBasic)] == ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]);
+ if (is_basic && pszRealm)
+ {
+ LPCWSTR token;
+ LPCWSTR ptr = &pszAuthValue[ARRAYSIZE(szBasic)];
+ LPCWSTR realm;
+ ptr++;
+ *pszRealm=NULL;
+ token = strchrW(ptr,'=');
+ if (!token)
+ return TRUE;
+ realm = ptr;
+ while (*realm == ' ' && *realm != '\0')
+ realm++;
+ if(!strncmpiW(realm, szRealm, ARRAYSIZE(szRealm)) &&
+ (realm[ARRAYSIZE(szRealm)] == ' ' || realm[ARRAYSIZE(szRealm)] == '='))
+ {
+ token++;
+ while (*token == ' ' && *token != '\0')
+ token++;
+ if (*token == '\0')
+ return TRUE;
+ *pszRealm = heap_strdupW(token);
+ strip_spaces(*pszRealm);
+ }
+ }
+
+ return is_basic;
+}
+
+static void destroy_authinfo( struct HttpAuthInfo *authinfo )
+{
+ if (!authinfo) return;
+
+ if (SecIsValidHandle(&authinfo->ctx))
+ DeleteSecurityContext(&authinfo->ctx);
+ if (SecIsValidHandle(&authinfo->cred))
+ FreeCredentialsHandle(&authinfo->cred);
+
+ HeapFree(GetProcessHeap(), 0, authinfo->auth_data);
+ HeapFree(GetProcessHeap(), 0, authinfo->scheme);
+ HeapFree(GetProcessHeap(), 0, authinfo);
+}
+
+static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR *auth_data)
+{
+ authorizationData *ad;
+ UINT rc = 0;
+
+ TRACE("Looking for authorization for %s:%s\n",debugstr_w(host),debugstr_w(realm));
+
+ EnterCriticalSection(&authcache_cs);
+ LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, authorizationData, entry)
+ {
+ if (!strcmpiW(host,ad->lpszwHost) && !strcmpW(realm,ad->lpszwRealm))
+ {
+ TRACE("Authorization found in cache\n");
+ *auth_data = HeapAlloc(GetProcessHeap(),0,ad->AuthorizationLen);
+ memcpy(*auth_data,ad->lpszAuthorization,ad->AuthorizationLen);
+ rc = ad->AuthorizationLen;
+ break;
+ }
+ }
+ LeaveCriticalSection(&authcache_cs);
+ return rc;
+}
+
+static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len)
+{
+ struct list *cursor;
+ authorizationData* ad = NULL;
+
+ TRACE("caching authorization for %s:%s = %s\n",debugstr_w(host),debugstr_w(realm),debugstr_an(auth_data,auth_data_len));
+
+ EnterCriticalSection(&authcache_cs);
+ LIST_FOR_EACH(cursor, &basicAuthorizationCache)
+ {
+ authorizationData *check = LIST_ENTRY(cursor,authorizationData,entry);
+ if (!strcmpiW(host,check->lpszwHost) && !strcmpW(realm,check->lpszwRealm))
+ {
+ ad = check;
+ break;
+ }
+ }
+
+ if (ad)
+ {
+ TRACE("Found match in cache, replacing\n");
+ HeapFree(GetProcessHeap(),0,ad->lpszAuthorization);
+ ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
+ memcpy(ad->lpszAuthorization, auth_data, auth_data_len);
+ ad->AuthorizationLen = auth_data_len;
+ }
+ else
+ {
+ ad = HeapAlloc(GetProcessHeap(),0,sizeof(authorizationData));
+ ad->lpszwHost = heap_strdupW(host);
+ ad->lpszwRealm = heap_strdupW(realm);
+ ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
+ memcpy(ad->lpszAuthorization, auth_data, auth_data_len);
+ ad->AuthorizationLen = auth_data_len;
+ list_add_head(&basicAuthorizationCache,&ad->entry);
+ TRACE("authorization cached\n");
+ }
+ LeaveCriticalSection(&authcache_cs);
+}
+
+static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue,
struct HttpAuthInfo **ppAuthInfo,
- LPWSTR domain_and_username, LPWSTR password )
+ LPWSTR domain_and_username, LPWSTR password,
+ LPWSTR host )
{
SECURITY_STATUS sec_status;
struct HttpAuthInfo *pAuthInfo = *ppAuthInfo;
BOOL first = FALSE;
+ LPWSTR szRealm = NULL;
TRACE("%s\n", debugstr_w(pszAuthValue));
@@ -426,10 +662,10 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
pAuthInfo->auth_data_len = 0;
pAuthInfo->finished = FALSE;
- if (is_basic_auth_value(pszAuthValue))
+ if (is_basic_auth_value(pszAuthValue,NULL))
{
static const WCHAR szBasic[] = {'B','a','s','i','c',0};
- pAuthInfo->scheme = WININET_strdupW(szBasic);
+ pAuthInfo->scheme = heap_strdupW(szBasic);
if (!pAuthInfo->scheme)
{
HeapFree(GetProcessHeap(), 0, pAuthInfo);
@@ -441,7 +677,7 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
PVOID pAuthData;
SEC_WINNT_AUTH_IDENTITY_W nt_auth_identity;
- pAuthInfo->scheme = WININET_strdupW(pszAuthValue);
+ pAuthInfo->scheme = heap_strdupW(pszAuthValue);
if (!pAuthInfo->scheme)
{
HeapFree(GetProcessHeap(), 0, pAuthInfo);
@@ -513,33 +749,50 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
return FALSE;
}
- if (is_basic_auth_value(pszAuthValue))
+ if (is_basic_auth_value(pszAuthValue,&szRealm))
{
int userlen;
int passlen;
- char *auth_data;
+ char *auth_data = NULL;
+ UINT auth_data_len = 0;
- TRACE("basic authentication\n");
+ TRACE("basic authentication realm %s\n",debugstr_w(szRealm));
- /* we don't cache credentials for basic authentication, so we can't
- * retrieve them if the application didn't pass us any credentials */
- if (!domain_and_username) return FALSE;
+ if (!domain_and_username)
+ {
+ if (host && szRealm)
+ auth_data_len = retrieve_cached_basic_authorization(host, szRealm,&auth_data);
+ if (auth_data_len == 0)
+ {
+ HeapFree(GetProcessHeap(),0,szRealm);
+ return FALSE;
+ }
+ }
+ else
+ {
+ userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
+ passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
- userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
- passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
+ /* length includes a nul terminator, which will be re-used for the ':' */
+ auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen);
+ if (!auth_data)
+ {
+ HeapFree(GetProcessHeap(),0,szRealm);
+ return FALSE;
+ }
- /* length includes a nul terminator, which will be re-used for the ':' */
- auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen);
- if (!auth_data)
- return FALSE;
-
- WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
- auth_data[userlen] = ':';
- WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
+ auth_data[userlen] = ':';
+ WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
+ auth_data_len = userlen + 1 + passlen;
+ if (host && szRealm)
+ cache_basic_authorization(host, szRealm, auth_data, auth_data_len);
+ }
pAuthInfo->auth_data = auth_data;
- pAuthInfo->auth_data_len = userlen + 1 + passlen;
+ pAuthInfo->auth_data_len = auth_data_len;
pAuthInfo->finished = TRUE;
+ HeapFree(GetProcessHeap(),0,szRealm);
return TRUE;
}
@@ -602,8 +855,9 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
else
{
ERR("InitializeSecurityContextW returned error 0x%08x\n", sec_status);
- pAuthInfo->finished = TRUE;
HeapFree(GetProcessHeap(), 0, out.pvBuffer);
+ destroy_authinfo(pAuthInfo);
+ *ppAuthInfo = NULL;
return FALSE;
}
}
@@ -614,14 +868,13 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
/***********************************************************************
* HTTP_HttpAddRequestHeadersW (internal)
*/
-static BOOL WINAPI HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr,
+static DWORD HTTP_HttpAddRequestHeadersW(http_request_t *lpwhr,
LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
{
LPWSTR lpszStart;
LPWSTR lpszEnd;
LPWSTR buffer;
- BOOL bSuccess = FALSE;
- DWORD len;
+ DWORD len, res = ERROR_HTTP_INVALID_HEADER;
TRACE("copying header: %s\n", debugstr_wn(lpszHeader, dwHeaderLength));
@@ -642,7 +895,7 @@ static BOOL WINAPI HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr,
while (*lpszEnd != '\0')
{
- if (*lpszEnd == '\r' && *(lpszEnd + 1) == '\n')
+ if (*lpszEnd == '\r' || *lpszEnd == '\n')
break;
lpszEnd++;
}
@@ -650,28 +903,35 @@ static BOOL WINAPI HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr,
if (*lpszStart == '\0')
break;
- if (*lpszEnd == '\r')
+ if (*lpszEnd == '\r' || *lpszEnd == '\n')
{
*lpszEnd = '\0';
- lpszEnd += 2; /* Jump over \r\n */
+ lpszEnd++; /* Jump over newline */
}
TRACE("interpreting header %s\n", debugstr_w(lpszStart));
+ if (*lpszStart == '\0')
+ {
+ /* Skip 0-length headers */
+ lpszStart = lpszEnd;
+ res = ERROR_SUCCESS;
+ continue;
+ }
pFieldAndValue = HTTP_InterpretHttpHeader(lpszStart);
if (pFieldAndValue)
{
- bSuccess = HTTP_VerifyValidHeader(lpwhr, pFieldAndValue[0]);
- if (bSuccess)
- bSuccess = HTTP_ProcessHeader(lpwhr, pFieldAndValue[0],
+ res = HTTP_VerifyValidHeader(lpwhr, pFieldAndValue[0]);
+ if (res == ERROR_SUCCESS)
+ res = HTTP_ProcessHeader(lpwhr, pFieldAndValue[0],
pFieldAndValue[1], dwModifier | HTTP_ADDHDR_FLAG_REQ);
HTTP_FreeTokens(pFieldAndValue);
}
lpszStart = lpszEnd;
- } while (bSuccess);
+ } while (res == ERROR_SUCCESS);
HeapFree(GetProcessHeap(), 0, buffer);
- return bSuccess;
+ return res;
}
/***********************************************************************
@@ -693,26 +953,23 @@ static BOOL WINAPI HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr,
BOOL WINAPI HttpAddRequestHeadersW(HINTERNET hHttpRequest,
LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
{
- BOOL bSuccess = FALSE;
- LPWININETHTTPREQW lpwhr;
+ http_request_t *lpwhr;
+ DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
TRACE("%p, %s, %i, %i\n", hHttpRequest, debugstr_wn(lpszHeader, dwHeaderLength), dwHeaderLength, dwModifier);
if (!lpszHeader)
return TRUE;
- lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hHttpRequest );
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto lend;
- }
- bSuccess = HTTP_HttpAddRequestHeadersW( lpwhr, lpszHeader, dwHeaderLength, dwModifier );
-lend:
+ lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
+ if (lpwhr && lpwhr->hdr.htype == WH_HHTTPREQ)
+ res = HTTP_HttpAddRequestHeadersW( lpwhr, lpszHeader, dwHeaderLength, dwModifier );
if( lpwhr )
WININET_Release( &lpwhr->hdr );
- return bSuccess;
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
}
/***********************************************************************
@@ -747,208 +1004,6 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest,
return r;
}
-/***********************************************************************
- * HttpEndRequestA (WININET.@)
- *
- * Ends an HTTP request that was started by HttpSendRequestEx
- *
- * RETURNS
- * TRUE if successful
- * FALSE on failure
- *
- */
-BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
- LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
-{
- LPINTERNET_BUFFERSA ptr;
- LPINTERNET_BUFFERSW lpBuffersOutW,ptrW;
- BOOL rc = FALSE;
-
- TRACE("(%p, %p, %08x, %08lx): stub\n", hRequest, lpBuffersOut, dwFlags,
- dwContext);
-
- ptr = lpBuffersOut;
- if (ptr)
- lpBuffersOutW = (LPINTERNET_BUFFERSW)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY, sizeof(INTERNET_BUFFERSW));
- else
- lpBuffersOutW = NULL;
-
- ptrW = lpBuffersOutW;
- while (ptr)
- {
- if (ptr->lpvBuffer && ptr->dwBufferLength)
- ptrW->lpvBuffer = HeapAlloc(GetProcessHeap(),0,ptr->dwBufferLength);
- ptrW->dwBufferLength = ptr->dwBufferLength;
- ptrW->dwBufferTotal= ptr->dwBufferTotal;
-
- if (ptr->Next)
- ptrW->Next = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
- sizeof(INTERNET_BUFFERSW));
-
- ptr = ptr->Next;
- ptrW = ptrW->Next;
- }
-
- rc = HttpEndRequestW(hRequest, lpBuffersOutW, dwFlags, dwContext);
-
- if (lpBuffersOutW)
- {
- ptrW = lpBuffersOutW;
- while (ptrW)
- {
- LPINTERNET_BUFFERSW ptrW2;
-
- FIXME("Do we need to translate info out of these buffer?\n");
-
- HeapFree(GetProcessHeap(),0,ptrW->lpvBuffer);
- ptrW2 = ptrW->Next;
- HeapFree(GetProcessHeap(),0,ptrW);
- ptrW = ptrW2;
- }
- }
-
- return rc;
-}
-
-/***********************************************************************
- * HttpEndRequestW (WININET.@)
- *
- * Ends an HTTP request that was started by HttpSendRequestEx
- *
- * RETURNS
- * TRUE if successful
- * FALSE on failure
- *
- */
-BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
- LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
-{
- BOOL rc = FALSE;
- LPWININETHTTPREQW lpwhr;
- INT responseLen;
- DWORD dwBufferSize;
-
- TRACE("-->\n");
- lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
-
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- if (lpwhr)
- WININET_Release( &lpwhr->hdr );
- return FALSE;
- }
-
- lpwhr->hdr.dwFlags |= dwFlags;
- lpwhr->hdr.dwContext = dwContext;
-
- /* We appear to do nothing with lpBuffersOut.. is that correct? */
-
- SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
-
- responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
- if (responseLen)
- rc = TRUE;
-
- SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
-
- /* process cookies here. Is this right? */
- HTTP_ProcessCookies(lpwhr);
-
- dwBufferSize = sizeof(lpwhr->dwContentLength);
- if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
- &lpwhr->dwContentLength,&dwBufferSize,NULL))
- lpwhr->dwContentLength = -1;
-
- if (lpwhr->dwContentLength == 0)
- HTTP_FinishedReading(lpwhr);
-
- if(!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
- {
- DWORD dwCode,dwCodeLength=sizeof(DWORD);
- if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,NULL) &&
- (dwCode==302 || dwCode==301))
- {
- WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH];
- dwBufferSize=sizeof(szNewLocation);
- if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
- {
- /* redirects are always GETs */
- HeapFree(GetProcessHeap(),0,lpwhr->lpszVerb);
- lpwhr->lpszVerb = WININET_strdupW(szGET);
- HTTP_DrainContent(lpwhr);
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_REDIRECT, szNewLocation,
- dwBufferSize);
- rc = HTTP_HandleRedirect(lpwhr, szNewLocation);
- if (rc)
- rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
- }
- }
- }
-
- WININET_Release( &lpwhr->hdr );
- TRACE("%i <--\n",rc);
- return rc;
-}
-
-/***********************************************************************
- * HttpOpenRequestW (WININET.@)
- *
- * Open a HTTP request handle
- *
- * RETURNS
- * HINTERNET a HTTP request handle on success
- * NULL on failure
- *
- */
-HINTERNET WINAPI HttpOpenRequestW(HINTERNET hHttpSession,
- LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
- LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
- DWORD dwFlags, DWORD_PTR dwContext)
-{
- LPWININETHTTPSESSIONW lpwhs;
- HINTERNET handle = NULL;
-
- TRACE("(%p, %s, %s, %s, %s, %p, %08x, %08lx)\n", hHttpSession,
- debugstr_w(lpszVerb), debugstr_w(lpszObjectName),
- debugstr_w(lpszVersion), debugstr_w(lpszReferrer), lpszAcceptTypes,
- dwFlags, dwContext);
- if(lpszAcceptTypes!=NULL)
- {
- int i;
- for(i=0;lpszAcceptTypes[i]!=NULL;i++)
- TRACE("\taccept type: %s\n",debugstr_w(lpszAcceptTypes[i]));
- }
-
- lpwhs = (LPWININETHTTPSESSIONW) WININET_GetObject( hHttpSession );
- if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto lend;
- }
-
- /*
- * My tests seem to show that the windows version does not
- * become asynchronous until after this point. And anyhow
- * if this call was asynchronous then how would you get the
- * necessary HINTERNET pointer returned by this function.
- *
- */
- handle = HTTP_HttpOpenRequestW(lpwhs, lpszVerb, lpszObjectName,
- lpszVersion, lpszReferrer, lpszAcceptTypes,
- dwFlags, dwContext);
-lend:
- if( lpwhs )
- WININET_Release( &lpwhs->hdr );
- TRACE("returning %p\n", handle);
- return handle;
-}
-
-
/***********************************************************************
* HttpOpenRequestA (WININET.@)
*
@@ -966,7 +1021,7 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
{
LPWSTR szVerb = NULL, szObjectName = NULL;
LPWSTR szVersion = NULL, szReferrer = NULL, *szAcceptTypes = NULL;
- INT len, acceptTypesCount;
+ INT acceptTypesCount;
HINTERNET rc = FALSE;
LPCSTR *types;
@@ -977,38 +1032,30 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
if (lpszVerb)
{
- len = MultiByteToWideChar(CP_ACP, 0, lpszVerb, -1, NULL, 0 );
- szVerb = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR) );
+ szVerb = heap_strdupAtoW(lpszVerb);
if ( !szVerb )
goto end;
- MultiByteToWideChar(CP_ACP, 0, lpszVerb, -1, szVerb, len);
}
if (lpszObjectName)
{
- len = MultiByteToWideChar(CP_ACP, 0, lpszObjectName, -1, NULL, 0 );
- szObjectName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR) );
+ szObjectName = heap_strdupAtoW(lpszObjectName);
if ( !szObjectName )
goto end;
- MultiByteToWideChar(CP_ACP, 0, lpszObjectName, -1, szObjectName, len );
}
if (lpszVersion)
{
- len = MultiByteToWideChar(CP_ACP, 0, lpszVersion, -1, NULL, 0 );
- szVersion = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ szVersion = heap_strdupAtoW(lpszVersion);
if ( !szVersion )
goto end;
- MultiByteToWideChar(CP_ACP, 0, lpszVersion, -1, szVersion, len );
}
if (lpszReferrer)
{
- len = MultiByteToWideChar(CP_ACP, 0, lpszReferrer, -1, NULL, 0 );
- szReferrer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ szReferrer = heap_strdupAtoW(lpszReferrer);
if ( !szReferrer )
goto end;
- MultiByteToWideChar(CP_ACP, 0, lpszReferrer, -1, szReferrer, len );
}
if (lpszAcceptTypes)
@@ -1017,12 +1064,20 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
types = lpszAcceptTypes;
while (*types)
{
- /* find out how many there are */
- if (((ULONG_PTR)*types >> 16) && **types)
+ __TRY
{
- TRACE("accept type: %s\n", debugstr_a(*types));
- acceptTypesCount++;
+ /* find out how many there are */
+ if (*types && **types)
+ {
+ TRACE("accept type: %s\n", debugstr_a(*types));
+ acceptTypesCount++;
+ }
}
+ __EXCEPT_PAGE_FAULT
+ {
+ WARN("invalid accept type pointer\n");
+ }
+ __ENDTRY;
types++;
}
szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1));
@@ -1032,20 +1087,20 @@ HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
types = lpszAcceptTypes;
while (*types)
{
- if (((ULONG_PTR)*types >> 16) && **types)
+ __TRY
{
- len = MultiByteToWideChar(CP_ACP, 0, *types, -1, NULL, 0 );
- szAcceptTypes[acceptTypesCount] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
- if (!szAcceptTypes[acceptTypesCount]) goto end;
-
- MultiByteToWideChar(CP_ACP, 0, *types, -1, szAcceptTypes[acceptTypesCount], len);
- acceptTypesCount++;
+ if (*types && **types)
+ szAcceptTypes[acceptTypesCount++] = heap_strdupAtoW(*types);
}
+ __EXCEPT_PAGE_FAULT
+ {
+ /* ignore invalid pointer */
+ }
+ __ENDTRY;
types++;
}
szAcceptTypes[acceptTypesCount] = NULL;
}
- else szAcceptTypes = 0;
rc = HttpOpenRequestW(hHttpSession, szVerb, szObjectName,
szVersion, szReferrer,
@@ -1207,7 +1262,7 @@ static UINT HTTP_DecodeBase64( LPCWSTR base64, LPSTR bin )
*
* Insert or delete the authorization field in the request header.
*/
-static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr, struct HttpAuthInfo *pAuthInfo, LPCWSTR header )
+static BOOL HTTP_InsertAuthorization( http_request_t *lpwhr, struct HttpAuthInfo *pAuthInfo, LPCWSTR header )
{
if (pAuthInfo)
{
@@ -1250,13 +1305,13 @@ static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr, struct HttpAuthIn
return TRUE;
}
-static WCHAR *HTTP_BuildProxyRequestUrl(WININETHTTPREQW *req)
+static WCHAR *HTTP_BuildProxyRequestUrl(http_request_t *req)
{
WCHAR new_location[INTERNET_MAX_URL_LENGTH], *url;
DWORD size;
size = sizeof(new_location);
- if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_LOCATION, new_location, &size, NULL))
+ if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_LOCATION, new_location, &size, NULL) == ERROR_SUCCESS)
{
if (!(url = HeapAlloc( GetProcessHeap(), 0, size + sizeof(WCHAR) ))) return NULL;
strcpyW( url, new_location );
@@ -1266,7 +1321,7 @@ static WCHAR *HTTP_BuildProxyRequestUrl(WININETHTTPREQW *req)
static const WCHAR slash[] = { '/',0 };
static const WCHAR format[] = { 'h','t','t','p',':','/','/','%','s',':','%','d',0 };
static const WCHAR formatSSL[] = { 'h','t','t','p','s',':','/','/','%','s',':','%','d',0 };
- WININETHTTPSESSIONW *session = req->lpHttpSession;
+ http_session_t *session = req->lpHttpSession;
size = 16; /* "https://" + sizeof(port#) + ":/\0" */
size += strlenW( session->lpszHostName ) + strlenW( req->lpszPath );
@@ -1287,8 +1342,7 @@ static WCHAR *HTTP_BuildProxyRequestUrl(WININETHTTPREQW *req)
/***********************************************************************
* HTTP_DealWithProxy
*/
-static BOOL HTTP_DealWithProxy( LPWININETAPPINFOW hIC,
- LPWININETHTTPSESSIONW lpwhs, LPWININETHTTPREQW lpwhr)
+static BOOL HTTP_DealWithProxy(appinfo_t *hIC, http_session_t *lpwhs, http_request_t *lpwhr)
{
WCHAR buf[MAXHOSTNAME];
WCHAR proxy[MAXHOSTNAME + 15]; /* 15 == "http://" + sizeof(port#) + ":/\0" */
@@ -1319,38 +1373,52 @@ static BOOL HTTP_DealWithProxy( LPWININETAPPINFOW hIC,
UrlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
- lpwhs->lpszServerName = WININET_strdupW(UrlComponents.lpszHostName);
+ lpwhs->lpszServerName = heap_strdupW(UrlComponents.lpszHostName);
lpwhs->nServerPort = UrlComponents.nPort;
TRACE("proxy server=%s port=%d\n", debugstr_w(lpwhs->lpszServerName), lpwhs->nServerPort);
return TRUE;
}
-static BOOL HTTP_ResolveName(LPWININETHTTPREQW lpwhr)
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
+static DWORD HTTP_ResolveName(http_request_t *lpwhr)
{
- char szaddr[32];
- LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession;
+ char szaddr[INET6_ADDRSTRLEN];
+ http_session_t *lpwhs = lpwhr->lpHttpSession;
+ const void *addr;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESOLVING_NAME,
lpwhs->lpszServerName,
- strlenW(lpwhs->lpszServerName)+1);
+ (strlenW(lpwhs->lpszServerName)+1) * sizeof(WCHAR));
+ lpwhs->sa_len = sizeof(lpwhs->socketAddress);
if (!GetAddress(lpwhs->lpszServerName, lpwhs->nServerPort,
- &lpwhs->socketAddress))
- {
- INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
- return FALSE;
- }
+ (struct sockaddr *)&lpwhs->socketAddress, &lpwhs->sa_len))
+ return ERROR_INTERNET_NAME_NOT_RESOLVED;
- inet_ntop(lpwhs->socketAddress.sin_family, &lpwhs->socketAddress.sin_addr,
- szaddr, sizeof(szaddr));
+ switch (lpwhs->socketAddress.ss_family)
+ {
+ case AF_INET:
+ addr = &((struct sockaddr_in *)&lpwhs->socketAddress)->sin_addr;
+ break;
+ case AF_INET6:
+ addr = &((struct sockaddr_in6 *)&lpwhs->socketAddress)->sin6_addr;
+ break;
+ default:
+ WARN("unsupported family %d\n", lpwhs->socketAddress.ss_family);
+ return ERROR_INTERNET_NAME_NOT_RESOLVED;
+ }
+ inet_ntop(lpwhs->socketAddress.ss_family, addr, szaddr, sizeof(szaddr));
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_NAME_RESOLVED,
szaddr, strlen(szaddr)+1);
TRACE("resolved %s to %s\n", debugstr_w(lpwhs->lpszServerName), szaddr);
- return TRUE;
+ return ERROR_SUCCESS;
}
@@ -1360,9 +1428,9 @@ static BOOL HTTP_ResolveName(LPWININETHTTPREQW lpwhr)
* Deallocate request handle
*
*/
-static void HTTPREQ_Destroy(WININETHANDLEHEADER *hdr)
+static void HTTPREQ_Destroy(object_header_t *hdr)
{
- LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) hdr;
+ http_request_t *lpwhr = (http_request_t*) hdr;
DWORD i;
TRACE("\n");
@@ -1370,13 +1438,14 @@ static void HTTPREQ_Destroy(WININETHANDLEHEADER *hdr)
if(lpwhr->hCacheFile)
CloseHandle(lpwhr->hCacheFile);
- if(lpwhr->lpszCacheFile) {
- DeleteFileW(lpwhr->lpszCacheFile); /* FIXME */
- HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
- }
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
+ DeleteCriticalSection( &lpwhr->read_section );
WININET_Release(&lpwhr->lpHttpSession->hdr);
+ destroy_authinfo(lpwhr->pAuthInfo);
+ destroy_authinfo(lpwhr->pProxyAuthInfo);
+
HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders);
@@ -1389,44 +1458,27 @@ static void HTTPREQ_Destroy(WININETHANDLEHEADER *hdr)
HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[i].lpszValue);
}
+#ifdef HAVE_ZLIB
+ if(lpwhr->gzip_stream) {
+ if(!lpwhr->gzip_stream->end_of_data)
+ inflateEnd(&lpwhr->gzip_stream->zstream);
+ HeapFree(GetProcessHeap(), 0, lpwhr->gzip_stream);
+ }
+#endif
+
HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders);
HeapFree(GetProcessHeap(), 0, lpwhr);
}
-static void HTTPREQ_CloseConnection(WININETHANDLEHEADER *hdr)
+static void HTTPREQ_CloseConnection(object_header_t *hdr)
{
- LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) hdr;
+ http_request_t *lpwhr = (http_request_t*) hdr;
TRACE("%p\n",lpwhr);
if (!NETCON_connected(&lpwhr->netConnection))
return;
- if (lpwhr->pAuthInfo)
- {
- if (SecIsValidHandle(&lpwhr->pAuthInfo->ctx))
- DeleteSecurityContext(&lpwhr->pAuthInfo->ctx);
- if (SecIsValidHandle(&lpwhr->pAuthInfo->cred))
- FreeCredentialsHandle(&lpwhr->pAuthInfo->cred);
-
- HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->auth_data);
- HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->scheme);
- HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo);
- lpwhr->pAuthInfo = NULL;
- }
- if (lpwhr->pProxyAuthInfo)
- {
- if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->ctx))
- DeleteSecurityContext(&lpwhr->pProxyAuthInfo->ctx);
- if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->cred))
- FreeCredentialsHandle(&lpwhr->pProxyAuthInfo->cred);
-
- HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->auth_data);
- HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->scheme);
- HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo);
- lpwhr->pProxyAuthInfo = NULL;
- }
-
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
@@ -1436,11 +1488,95 @@ static void HTTPREQ_CloseConnection(WININETHANDLEHEADER *hdr)
INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
}
-static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
+static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
{
- WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
+ LPHTTPHEADERW host_header;
+
+ static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
+
+ host_header = HTTP_GetHeader(req, hostW);
+ if(!host_header)
+ return FALSE;
+
+ sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
+ return TRUE;
+}
+
+static BOOL HTTP_KeepAlive(http_request_t *lpwhr)
+{
+ WCHAR szVersion[10];
+ WCHAR szConnectionResponse[20];
+ DWORD dwBufferSize = sizeof(szVersion);
+ BOOL keepalive = FALSE;
+
+ /* as per RFC 2068, S8.1.2.1, if the client is HTTP/1.1 then assume that
+ * the connection is keep-alive by default */
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion, &dwBufferSize, NULL) == ERROR_SUCCESS
+ && !strcmpiW(szVersion, g_szHttp1_1))
+ {
+ keepalive = TRUE;
+ }
+
+ dwBufferSize = sizeof(szConnectionResponse);
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_PROXY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) == ERROR_SUCCESS
+ || HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) == ERROR_SUCCESS)
+ {
+ keepalive = !strcmpiW(szConnectionResponse, szKeepAlive);
+ }
+
+ return keepalive;
+}
+
+static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
+{
+ http_request_t *req = (http_request_t*)hdr;
switch(option) {
+ case INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO:
+ {
+ http_session_t *lpwhs = req->lpHttpSession;
+ INTERNET_DIAGNOSTIC_SOCKET_INFO *info = buffer;
+
+ FIXME("INTERNET_DIAGNOSTIC_SOCKET_INFO stub\n");
+
+ if (*size < sizeof(INTERNET_DIAGNOSTIC_SOCKET_INFO))
+ return ERROR_INSUFFICIENT_BUFFER;
+ *size = sizeof(INTERNET_DIAGNOSTIC_SOCKET_INFO);
+ /* FIXME: can't get a SOCKET from our connection since we don't use
+ * winsock
+ */
+ info->Socket = 0;
+ /* FIXME: get source port from req->netConnection */
+ info->SourcePort = 0;
+ info->DestPort = lpwhs->nHostPort;
+ info->Flags = 0;
+ if (HTTP_KeepAlive(req))
+ info->Flags |= IDSI_FLAG_KEEP_ALIVE;
+ if (lpwhs->lpAppInfo->lpszProxy && lpwhs->lpAppInfo->lpszProxy[0] != 0)
+ info->Flags |= IDSI_FLAG_PROXY;
+ if (req->netConnection.useSSL)
+ info->Flags |= IDSI_FLAG_SECURE;
+
+ return ERROR_SUCCESS;
+ }
+
+ case INTERNET_OPTION_SECURITY_FLAGS:
+ {
+ http_session_t *lpwhs;
+ lpwhs = req->lpHttpSession;
+
+ if (*size < sizeof(ULONG))
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ *size = sizeof(DWORD);
+ if (lpwhs->hdr.dwFlags & INTERNET_FLAG_SECURE)
+ *(DWORD*)buffer = SECURITY_FLAG_SECURE;
+ else
+ *(DWORD*)buffer = 0;
+ FIXME("Semi-STUB INTERNET_OPTION_SECURITY_FLAGS: %x\n",*(DWORD*)buffer);
+ return ERROR_SUCCESS;
+ }
+
case INTERNET_OPTION_HANDLE_TYPE:
TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
@@ -1458,7 +1594,6 @@ static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b
WCHAR *pch;
static const WCHAR httpW[] = {'h','t','t','p',':','/','/',0};
- static const WCHAR hostW[] = {'H','o','s','t',0};
TRACE("INTERNET_OPTION_URL\n");
@@ -1489,6 +1624,41 @@ static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b
}
}
+ case INTERNET_OPTION_CACHE_TIMESTAMPS: {
+ INTERNET_CACHE_ENTRY_INFOW *info;
+ INTERNET_CACHE_TIMESTAMPS *ts = buffer;
+ WCHAR url[INTERNET_MAX_URL_LENGTH];
+ DWORD nbytes, error;
+ BOOL ret;
+
+ TRACE("INTERNET_OPTION_CACHE_TIMESTAMPS\n");
+
+ if (*size < sizeof(*ts))
+ {
+ *size = sizeof(*ts);
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+ nbytes = 0;
+ HTTP_GetRequestURL(req, url);
+ ret = GetUrlCacheEntryInfoW(url, NULL, &nbytes);
+ error = GetLastError();
+ if (!ret && error == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if (!(info = HeapAlloc(GetProcessHeap(), 0, nbytes)))
+ return ERROR_OUTOFMEMORY;
+
+ GetUrlCacheEntryInfoW(url, info, &nbytes);
+
+ ts->ftExpires = info->ExpireTime;
+ ts->ftLastModified = info->LastModifiedTime;
+
+ HeapFree(GetProcessHeap(), 0, info);
+ *size = sizeof(*ts);
+ return ERROR_SUCCESS;
+ }
+ return error;
+ }
+
case INTERNET_OPTION_DATAFILE_NAME: {
DWORD req_size;
@@ -1584,9 +1754,9 @@ static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b
return INET_QueryOption(option, buffer, size, unicode);
}
-static DWORD HTTPREQ_SetOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD size)
+static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer, DWORD size)
{
- WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
+ http_request_t *req = (http_request_t*)hdr;
switch(option) {
case INTERNET_OPTION_SEND_TIMEOUT:
@@ -1598,30 +1768,340 @@ static DWORD HTTPREQ_SetOption(WININETHANDLEHEADER *hdr, DWORD option, void *buf
return NETCON_set_timeout(&req->netConnection, option == INTERNET_OPTION_SEND_TIMEOUT,
*(DWORD*)buffer);
+
+ case INTERNET_OPTION_USERNAME:
+ HeapFree(GetProcessHeap(), 0, req->lpHttpSession->lpszUserName);
+ if (!(req->lpHttpSession->lpszUserName = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
+ return ERROR_SUCCESS;
+
+ case INTERNET_OPTION_PASSWORD:
+ HeapFree(GetProcessHeap(), 0, req->lpHttpSession->lpszPassword);
+ if (!(req->lpHttpSession->lpszPassword = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
+ return ERROR_SUCCESS;
+ case INTERNET_OPTION_HTTP_DECODING:
+ if(size != sizeof(BOOL))
+ return ERROR_INVALID_PARAMETER;
+ req->decoding = *(BOOL*)buffer;
+ return ERROR_SUCCESS;
}
return ERROR_INTERNET_INVALID_OPTION;
}
-static DWORD HTTP_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
+/* read some more data into the read buffer (the read section must be held) */
+static DWORD read_more_data( http_request_t *req, int maxlen )
{
- int bytes_read;
+ DWORD res;
+ int len;
- if(!NETCON_recv(&req->netConnection, buffer, min(size, req->dwContentLength - req->dwContentRead),
- sync ? MSG_WAITALL : 0, &bytes_read)) {
- if(req->dwContentLength != -1 && req->dwContentRead != req->dwContentLength)
- ERR("not all data received %d/%d\n", req->dwContentRead, req->dwContentLength);
-
- /* always return success, even if the network layer returns an error */
- *read = 0;
- HTTP_FinishedReading(req);
- return ERROR_SUCCESS;
+ if (req->read_pos)
+ {
+ /* move existing data to the start of the buffer */
+ if(req->read_size)
+ memmove( req->read_buf, req->read_buf + req->read_pos, req->read_size );
+ req->read_pos = 0;
}
- req->dwContentRead += bytes_read;
+ if (maxlen == -1) maxlen = sizeof(req->read_buf);
+
+ res = NETCON_recv( &req->netConnection, req->read_buf + req->read_size,
+ maxlen - req->read_size, 0, &len );
+ if(res == ERROR_SUCCESS)
+ req->read_size += len;
+
+ return res;
+}
+
+/* remove some amount of data from the read buffer (the read section must be held) */
+static void remove_data( http_request_t *req, int count )
+{
+ if (!(req->read_size -= count)) req->read_pos = 0;
+ else req->read_pos += count;
+}
+
+static BOOL read_line( http_request_t *req, LPSTR buffer, DWORD *len )
+{
+ int count, bytes_read, pos = 0;
+ DWORD res;
+
+ EnterCriticalSection( &req->read_section );
+ for (;;)
+ {
+ BYTE *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size );
+
+ if (eol)
+ {
+ count = eol - (req->read_buf + req->read_pos);
+ bytes_read = count + 1;
+ }
+ else count = bytes_read = req->read_size;
+
+ count = min( count, *len - pos );
+ memcpy( buffer + pos, req->read_buf + req->read_pos, count );
+ pos += count;
+ remove_data( req, bytes_read );
+ if (eol) break;
+
+ if ((res = read_more_data( req, -1 )) != ERROR_SUCCESS || !req->read_size)
+ {
+ *len = 0;
+ TRACE( "returning empty string\n" );
+ LeaveCriticalSection( &req->read_section );
+ INTERNET_SetLastError(res);
+ return FALSE;
+ }
+ }
+ LeaveCriticalSection( &req->read_section );
+
+ if (pos < *len)
+ {
+ if (pos && buffer[pos - 1] == '\r') pos--;
+ *len = pos + 1;
+ }
+ buffer[*len - 1] = 0;
+ TRACE( "returning %s\n", debugstr_a(buffer));
+ return TRUE;
+}
+
+/* discard data contents until we reach end of line (the read section must be held) */
+static DWORD discard_eol( http_request_t *req )
+{
+ DWORD res;
+
+ do
+ {
+ BYTE *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size );
+ if (eol)
+ {
+ remove_data( req, (eol + 1) - (req->read_buf + req->read_pos) );
+ break;
+ }
+ req->read_pos = req->read_size = 0; /* discard everything */
+ if ((res = read_more_data( req, -1 )) != ERROR_SUCCESS) return res;
+ } while (req->read_size);
+ return ERROR_SUCCESS;
+}
+
+/* read the size of the next chunk (the read section must be held) */
+static DWORD start_next_chunk( http_request_t *req )
+{
+ DWORD chunk_size = 0, res;
+
+ if (!req->dwContentLength) return ERROR_SUCCESS;
+ if (req->dwContentLength == req->dwContentRead)
+ {
+ /* read terminator for the previous chunk */
+ if ((res = discard_eol( req )) != ERROR_SUCCESS) return res;
+ req->dwContentLength = ~0u;
+ req->dwContentRead = 0;
+ }
+ for (;;)
+ {
+ while (req->read_size)
+ {
+ char ch = req->read_buf[req->read_pos];
+ if (ch >= '0' && ch <= '9') chunk_size = chunk_size * 16 + ch - '0';
+ else if (ch >= 'a' && ch <= 'f') chunk_size = chunk_size * 16 + ch - 'a' + 10;
+ else if (ch >= 'A' && ch <= 'F') chunk_size = chunk_size * 16 + ch - 'A' + 10;
+ else if (ch == ';' || ch == '\r' || ch == '\n')
+ {
+ TRACE( "reading %u byte chunk\n", chunk_size );
+ req->dwContentLength = chunk_size;
+ req->dwContentRead = 0;
+ return discard_eol( req );
+ }
+ remove_data( req, 1 );
+ }
+ if ((res = read_more_data( req, -1 )) != ERROR_SUCCESS) return res;
+ if (!req->read_size)
+ {
+ req->dwContentLength = req->dwContentRead = 0;
+ return ERROR_SUCCESS;
+ }
+ }
+}
+
+/* check if we have reached the end of the data to read (the read section must be held) */
+static BOOL end_of_read_data( http_request_t *req )
+{
+ if (req->gzip_stream) return req->gzip_stream->end_of_data && !req->gzip_stream->buf_size;
+ if (req->read_chunked) return (req->dwContentLength == 0);
+ if (req->dwContentLength == ~0u) return FALSE;
+ return (req->dwContentLength == req->dwContentRead);
+}
+
+/* fetch some more data into the read buffer (the read section must be held) */
+static DWORD refill_buffer( http_request_t *req )
+{
+ int len = sizeof(req->read_buf);
+ DWORD res;
+
+ if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
+ {
+ if ((res = start_next_chunk( req )) != ERROR_SUCCESS) return res;
+ }
+
+ if (req->dwContentLength != ~0u) len = min( len, req->dwContentLength - req->dwContentRead );
+ if (len <= req->read_size) return ERROR_SUCCESS;
+
+ if ((res = read_more_data( req, len )) != ERROR_SUCCESS) return res;
+ if (!req->read_size) req->dwContentLength = req->dwContentRead = 0;
+ return ERROR_SUCCESS;
+}
+
+static DWORD read_gzip_data(http_request_t *req, BYTE *buf, int size, BOOL sync, int *read_ret)
+{
+ DWORD ret = ERROR_SUCCESS;
+ int read = 0;
+
+#ifdef HAVE_ZLIB
+ z_stream *zstream = &req->gzip_stream->zstream;
+ DWORD buf_avail;
+ int zres;
+
+ while(read < size && !req->gzip_stream->end_of_data) {
+ if(!req->read_size) {
+ if(!sync || refill_buffer(req) != ERROR_SUCCESS)
+ break;
+ }
+
+ buf_avail = req->dwContentLength == ~0 ? req->read_size : min(req->read_size, req->dwContentLength-req->dwContentRead);
+
+ zstream->next_in = req->read_buf+req->read_pos;
+ zstream->avail_in = buf_avail;
+ zstream->next_out = buf+read;
+ zstream->avail_out = size-read;
+ zres = inflate(zstream, Z_FULL_FLUSH);
+ read = size - zstream->avail_out;
+ req->dwContentRead += buf_avail-zstream->avail_in;
+ remove_data(req, buf_avail-zstream->avail_in);
+ if(zres == Z_STREAM_END) {
+ TRACE("end of data\n");
+ req->gzip_stream->end_of_data = TRUE;
+ inflateEnd(&req->gzip_stream->zstream);
+ }else if(zres != Z_OK) {
+ WARN("inflate failed %d\n", zres);
+ if(!read)
+ ret = ERROR_INTERNET_DECODING_FAILED;
+ break;
+ }
+ }
+#endif
+
+ *read_ret = read;
+ return ret;
+}
+
+static void refill_gzip_buffer(http_request_t *req)
+{
+ DWORD res;
+ int len;
+
+ if(!req->gzip_stream || !req->read_size || req->gzip_stream->buf_size == sizeof(req->gzip_stream->buf))
+ return;
+
+ if(req->gzip_stream->buf_pos) {
+ if(req->gzip_stream->buf_size)
+ memmove(req->gzip_stream->buf, req->gzip_stream->buf + req->gzip_stream->buf_pos, req->gzip_stream->buf_size);
+ req->gzip_stream->buf_pos = 0;
+ }
+
+ res = read_gzip_data(req, req->gzip_stream->buf + req->gzip_stream->buf_size,
+ sizeof(req->gzip_stream->buf) - req->gzip_stream->buf_size, FALSE, &len);
+ if(res == ERROR_SUCCESS)
+ req->gzip_stream->buf_size += len;
+}
+
+/* return the size of data available to be read immediately (the read section must be held) */
+static DWORD get_avail_data( http_request_t *req )
+{
+ if (req->gzip_stream) {
+ refill_gzip_buffer(req);
+ return req->gzip_stream->buf_size;
+ }
+ if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
+ return 0;
+ return min( req->read_size, req->dwContentLength - req->dwContentRead );
+}
+
+static void HTTP_ReceiveRequestData(http_request_t *req, BOOL first_notif)
+{
+ INTERNET_ASYNC_RESULT iar;
+ DWORD res;
+
+ TRACE("%p\n", req);
+
+ EnterCriticalSection( &req->read_section );
+ if ((res = refill_buffer( req )) == ERROR_SUCCESS) {
+ iar.dwResult = (DWORD_PTR)req->hdr.hInternet;
+ iar.dwError = first_notif ? 0 : get_avail_data(req);
+ }else {
+ iar.dwResult = 0;
+ iar.dwError = res;
+ }
+ LeaveCriticalSection( &req->read_section );
+
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
+}
+
+/* read data from the http connection (the read section must be held) */
+static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
+{
+ BOOL finished_reading = FALSE;
+ int len, bytes_read = 0;
+ DWORD ret = ERROR_SUCCESS;
+
+ EnterCriticalSection( &req->read_section );
+
+ if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
+ {
+ if (start_next_chunk( req ) != ERROR_SUCCESS) goto done;
+ }
+
+ if(req->gzip_stream) {
+ if(req->gzip_stream->buf_size) {
+ bytes_read = min(req->gzip_stream->buf_size, size);
+ memcpy(buffer, req->gzip_stream->buf + req->gzip_stream->buf_pos, bytes_read);
+ req->gzip_stream->buf_pos += bytes_read;
+ req->gzip_stream->buf_size -= bytes_read;
+ }else if(!req->read_size && !req->gzip_stream->end_of_data) {
+ refill_buffer(req);
+ }
+
+ if(size > bytes_read) {
+ ret = read_gzip_data(req, (BYTE*)buffer+bytes_read, size-bytes_read, sync, &len);
+ if(ret == ERROR_SUCCESS)
+ bytes_read += len;
+ }
+
+ finished_reading = req->gzip_stream->end_of_data && !req->gzip_stream->buf_size;
+ }else {
+ if (req->dwContentLength != ~0u) size = min( size, req->dwContentLength - req->dwContentRead );
+
+ if (req->read_size) {
+ bytes_read = min( req->read_size, size );
+ memcpy( buffer, req->read_buf + req->read_pos, bytes_read );
+ remove_data( req, bytes_read );
+ }
+
+ if (size > bytes_read && (!bytes_read || sync)) {
+ if (NETCON_recv( &req->netConnection, (char *)buffer + bytes_read, size - bytes_read,
+ sync ? MSG_WAITALL : 0, &len) == ERROR_SUCCESS)
+ bytes_read += len;
+ /* always return success, even if the network layer returns an error */
+ }
+
+ finished_reading = !bytes_read && req->dwContentRead == req->dwContentLength;
+ req->dwContentRead += bytes_read;
+ }
+done:
*read = bytes_read;
- if(req->lpszCacheFile) {
+ TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, req->dwContentRead, req->dwContentLength );
+ LeaveCriticalSection( &req->read_section );
+
+ if(ret == ERROR_SUCCESS && req->lpszCacheFile) {
BOOL res;
DWORD dwBytesWritten;
@@ -1630,119 +2110,23 @@ static DWORD HTTP_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *re
WARN("WriteFile failed: %u\n", GetLastError());
}
- if(!bytes_read && (req->dwContentRead == req->dwContentLength))
+ if(finished_reading)
HTTP_FinishedReading(req);
- return ERROR_SUCCESS;
+ return ret;
}
-static DWORD get_chunk_size(const char *buffer)
+
+static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read)
{
- const char *p;
- DWORD size = 0;
-
- for (p = buffer; *p; p++)
- {
- if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0';
- else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10;
- else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10;
- else if (*p == ';') break;
- }
- return size;
-}
-
-static DWORD HTTP_ReadChunked(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
-{
- char reply[MAX_REPLY_LEN], *p = buffer;
- DWORD buflen, to_read, to_write = size;
- int bytes_read;
-
- *read = 0;
- for (;;)
- {
- if (*read == size) break;
-
- if (req->dwContentLength == ~0UL) /* new chunk */
- {
- buflen = sizeof(reply);
- if (!NETCON_getNextLine(&req->netConnection, reply, &buflen)) break;
-
- if (!(req->dwContentLength = get_chunk_size(reply)))
- {
- /* zero sized chunk marks end of transfer; read any trailing headers and return */
- HTTP_GetResponseHeaders(req, FALSE);
- break;
- }
- }
- to_read = min(to_write, req->dwContentLength - req->dwContentRead);
-
- if (!NETCON_recv(&req->netConnection, p, to_read, sync ? MSG_WAITALL : 0, &bytes_read))
- {
- if (bytes_read != to_read)
- ERR("Not all data received %d/%d\n", bytes_read, to_read);
-
- /* always return success, even if the network layer returns an error */
- *read = 0;
- break;
- }
- if (!bytes_read) break;
-
- req->dwContentRead += bytes_read;
- to_write -= bytes_read;
- *read += bytes_read;
-
- if (req->lpszCacheFile)
- {
- DWORD dwBytesWritten;
-
- if (!WriteFile(req->hCacheFile, p, bytes_read, &dwBytesWritten, NULL))
- WARN("WriteFile failed: %u\n", GetLastError());
- }
- p += bytes_read;
-
- if (req->dwContentRead == req->dwContentLength) /* chunk complete */
- {
- req->dwContentRead = 0;
- req->dwContentLength = ~0UL;
-
- buflen = sizeof(reply);
- if (!NETCON_getNextLine(&req->netConnection, reply, &buflen))
- {
- ERR("Malformed chunk\n");
- *read = 0;
- break;
- }
- }
- }
- if (!*read) HTTP_FinishedReading(req);
- return ERROR_SUCCESS;
-}
-
-static DWORD HTTPREQ_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
-{
- WCHAR encoding[20];
- DWORD buflen = sizeof(encoding);
- static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0};
-
- if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_TRANSFER_ENCODING, encoding, &buflen, NULL) &&
- !strcmpiW(encoding, szChunked))
- {
- return HTTP_ReadChunked(req, buffer, size, read, sync);
- }
- else
- return HTTP_Read(req, buffer, size, read, sync);
-}
-
-static DWORD HTTPREQ_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size, DWORD *read)
-{
- WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
+ http_request_t *req = (http_request_t*)hdr;
return HTTPREQ_Read(req, buffer, size, read, TRUE);
}
-static void HTTPREQ_AsyncReadFileExProc(WORKREQUEST *workRequest)
+static void HTTPREQ_AsyncReadFileExAProc(WORKREQUEST *workRequest)
{
struct WORKREQ_INTERNETREADFILEEXA const *data = &workRequest->u.InternetReadFileExA;
- WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr;
+ http_request_t *req = (http_request_t*)workRequest->hdr;
INTERNET_ASYNC_RESULT iar;
DWORD res;
@@ -1759,11 +2143,10 @@ static void HTTPREQ_AsyncReadFileExProc(WORKREQUEST *workRequest)
sizeof(INTERNET_ASYNC_RESULT));
}
-static DWORD HTTPREQ_ReadFileExA(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSA *buffers,
+static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffers,
DWORD flags, DWORD_PTR context)
{
-
- WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
+ http_request_t *req = (http_request_t*)hdr;
DWORD res;
if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
@@ -1774,27 +2157,35 @@ static DWORD HTTPREQ_ReadFileExA(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSA *bu
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
- if (hdr->dwFlags & INTERNET_FLAG_ASYNC) {
- DWORD available = 0;
+ if ((hdr->dwFlags & INTERNET_FLAG_ASYNC) && !get_avail_data(req))
+ {
+ WORKREQUEST workRequest;
- NETCON_query_data_available(&req->netConnection, &available);
- if (!available)
+ if (TryEnterCriticalSection( &req->read_section ))
{
- WORKREQUEST workRequest;
-
- workRequest.asyncproc = HTTPREQ_AsyncReadFileExProc;
- workRequest.hdr = WININET_AddRef(&req->hdr);
- workRequest.u.InternetReadFileExA.lpBuffersOut = buffers;
-
- INTERNET_AsyncCall(&workRequest);
-
- return ERROR_IO_PENDING;
+ if (get_avail_data(req))
+ {
+ res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
+ &buffers->dwBufferLength, FALSE);
+ LeaveCriticalSection( &req->read_section );
+ goto done;
+ }
+ LeaveCriticalSection( &req->read_section );
}
+
+ workRequest.asyncproc = HTTPREQ_AsyncReadFileExAProc;
+ workRequest.hdr = WININET_AddRef(&req->hdr);
+ workRequest.u.InternetReadFileExA.lpBuffersOut = buffers;
+
+ INTERNET_AsyncCall(&workRequest);
+
+ return ERROR_IO_PENDING;
}
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
!(flags & IRF_NO_WAIT));
+done:
if (res == ERROR_SUCCESS) {
DWORD size = buffers->dwBufferLength;
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
@@ -1804,52 +2195,120 @@ static DWORD HTTPREQ_ReadFileExA(WININETHANDLEHEADER *hdr, INTERNET_BUFFERSA *bu
return res;
}
-static BOOL HTTPREQ_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWORD size, DWORD *written)
+static void HTTPREQ_AsyncReadFileExWProc(WORKREQUEST *workRequest)
{
- LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW)hdr;
+ struct WORKREQ_INTERNETREADFILEEXW const *data = &workRequest->u.InternetReadFileExW;
+ http_request_t *req = (http_request_t*)workRequest->hdr;
+ INTERNET_ASYNC_RESULT iar;
+ DWORD res;
- return NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written);
+ TRACE("INTERNETREADFILEEXW %p\n", workRequest->hdr);
+
+ res = HTTPREQ_Read(req, data->lpBuffersOut->lpvBuffer,
+ data->lpBuffersOut->dwBufferLength, &data->lpBuffersOut->dwBufferLength, TRUE);
+
+ iar.dwResult = res == ERROR_SUCCESS;
+ iar.dwError = res;
+
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
+ INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
+}
+
+static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffers,
+ DWORD flags, DWORD_PTR context)
+{
+
+ http_request_t *req = (http_request_t*)hdr;
+ DWORD res;
+
+ if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
+ FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
+
+ if (buffers->dwStructSize != sizeof(*buffers))
+ return ERROR_INVALID_PARAMETER;
+
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+
+ if (hdr->dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ WORKREQUEST workRequest;
+
+ if (TryEnterCriticalSection( &req->read_section ))
+ {
+ if (get_avail_data(req))
+ {
+ res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
+ &buffers->dwBufferLength, FALSE);
+ LeaveCriticalSection( &req->read_section );
+ goto done;
+ }
+ LeaveCriticalSection( &req->read_section );
+ }
+
+ workRequest.asyncproc = HTTPREQ_AsyncReadFileExWProc;
+ workRequest.hdr = WININET_AddRef(&req->hdr);
+ workRequest.u.InternetReadFileExW.lpBuffersOut = buffers;
+
+ INTERNET_AsyncCall(&workRequest);
+
+ return ERROR_IO_PENDING;
+ }
+
+ res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
+ !(flags & IRF_NO_WAIT));
+
+done:
+ if (res == ERROR_SUCCESS) {
+ DWORD size = buffers->dwBufferLength;
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
+ &size, sizeof(size));
+ }
+
+ return res;
+}
+
+static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
+{
+ DWORD res;
+ http_request_t *lpwhr = (http_request_t*)hdr;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
+
+ *written = 0;
+ res = NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written);
+ if (res == ERROR_SUCCESS)
+ lpwhr->dwBytesWritten += *written;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_SENT, written, sizeof(DWORD));
+ return res;
}
static void HTTPREQ_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest)
{
- WININETHTTPREQW *req = (WININETHTTPREQW*)workRequest->hdr;
- INTERNET_ASYNC_RESULT iar;
- char buffer[4048];
+ http_request_t *req = (http_request_t*)workRequest->hdr;
- TRACE("%p\n", workRequest->hdr);
-
- iar.dwResult = NETCON_recv(&req->netConnection, buffer,
- min(sizeof(buffer), req->dwContentLength - req->dwContentRead),
- MSG_PEEK, (int *)&iar.dwError);
-
- INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar,
- sizeof(INTERNET_ASYNC_RESULT));
+ HTTP_ReceiveRequestData(req, FALSE);
}
-static DWORD HTTPREQ_QueryDataAvailable(WININETHANDLEHEADER *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx)
+static DWORD HTTPREQ_QueryDataAvailable(object_header_t *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx)
{
- WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
- BYTE buffer[4048];
- BOOL async;
+ http_request_t *req = (http_request_t*)hdr;
TRACE("(%p %p %x %lx)\n", req, available, flags, ctx);
- if(!NETCON_query_data_available(&req->netConnection, available) || *available)
- return ERROR_SUCCESS;
-
- /* Even if we are in async mode, we need to determine whether
- * there is actually more data available. We do this by trying
- * to peek only a single byte in async mode. */
- async = (req->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) != 0;
-
- if (NETCON_recv(&req->netConnection, buffer,
- min(async ? 1 : sizeof(buffer), req->dwContentLength - req->dwContentRead),
- MSG_PEEK, (int *)available) && async && *available)
+ if (req->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
- *available = 0;
+ /* never wait, if we can't enter the section we queue an async request right away */
+ if (TryEnterCriticalSection( &req->read_section ))
+ {
+ if ((*available = get_avail_data( req ))) goto done;
+ if (end_of_read_data( req )) goto done;
+ LeaveCriticalSection( &req->read_section );
+ }
+
workRequest.asyncproc = HTTPREQ_AsyncQueryDataAvailableProc;
workRequest.hdr = WININET_AddRef( &req->hdr );
@@ -1858,16 +2317,35 @@ static DWORD HTTPREQ_QueryDataAvailable(WININETHANDLEHEADER *hdr, DWORD *availab
return ERROR_IO_PENDING;
}
+ EnterCriticalSection( &req->read_section );
+
+ if (!(*available = get_avail_data( req )) && !end_of_read_data( req ))
+ {
+ refill_buffer( req );
+ *available = get_avail_data( req );
+ }
+
+done:
+ if (*available == sizeof(req->read_buf) && !req->gzip_stream) /* check if we have even more pending in the socket */
+ {
+ DWORD extra;
+ if (NETCON_query_data_available(&req->netConnection, &extra))
+ *available = min( *available + extra, req->dwContentLength - req->dwContentRead );
+ }
+ LeaveCriticalSection( &req->read_section );
+
+ TRACE( "returning %u\n", *available );
return ERROR_SUCCESS;
}
-static const HANDLEHEADERVtbl HTTPREQVtbl = {
+static const object_vtbl_t HTTPREQVtbl = {
HTTPREQ_Destroy,
HTTPREQ_CloseConnection,
HTTPREQ_QueryOption,
HTTPREQ_SetOption,
HTTPREQ_ReadFile,
HTTPREQ_ReadFileExA,
+ HTTPREQ_ReadFileExW,
HTTPREQ_WriteFile,
HTTPREQ_QueryDataAvailable,
NULL
@@ -1883,27 +2361,27 @@ static const HANDLEHEADERVtbl HTTPREQVtbl = {
* NULL on failure
*
*/
-HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
- LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
- LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
- DWORD dwFlags, DWORD_PTR dwContext)
+static DWORD HTTP_HttpOpenRequestW(http_session_t *lpwhs,
+ LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
+ LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
+ DWORD dwFlags, DWORD_PTR dwContext, HINTERNET *ret)
{
- LPWININETAPPINFOW hIC = NULL;
- LPWININETHTTPREQW lpwhr;
+ appinfo_t *hIC = NULL;
+ http_request_t *lpwhr;
LPWSTR lpszHostName = NULL;
HINTERNET handle = NULL;
static const WCHAR szHostForm[] = {'%','s',':','%','u',0};
- DWORD len;
+ DWORD len, res;
TRACE("-->\n");
assert( lpwhs->hdr.htype == WH_HHTTPSESSION );
hIC = lpwhs->lpAppInfo;
- lpwhr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPREQW));
+ lpwhr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(http_request_t));
if (NULL == lpwhr)
{
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+ res = ERROR_OUTOFMEMORY;
goto lend;
}
lpwhr->hdr.htype = WH_HHTTPREQ;
@@ -1913,6 +2391,8 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
lpwhr->hdr.refs = 1;
lpwhr->hdr.lpfnStatusCB = lpwhs->hdr.lpfnStatusCB;
lpwhr->hdr.dwInternalFlags = lpwhs->hdr.dwInternalFlags & INET_CALLBACKW;
+ lpwhr->dwContentLength = ~0u;
+ InitializeCriticalSection( &lpwhr->read_section );
WININET_AddRef( &lpwhs->hdr );
lpwhr->lpHttpSession = lpwhs;
@@ -1922,18 +2402,18 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
(strlenW(lpwhs->lpszHostName) + 7 /* length of ":65535" + 1 */));
if (NULL == lpszHostName)
{
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+ res = ERROR_OUTOFMEMORY;
goto lend;
}
handle = WININET_AllocHandle( &lpwhr->hdr );
if (NULL == handle)
{
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+ res = ERROR_OUTOFMEMORY;
goto lend;
}
- if (!NETCON_init(&lpwhr->netConnection, dwFlags & INTERNET_FLAG_SECURE))
+ if ((res = NETCON_init(&lpwhr->netConnection, dwFlags & INTERNET_FLAG_SECURE)) != ERROR_SUCCESS)
{
InternetCloseHandle( handle );
handle = NULL;
@@ -1950,11 +2430,15 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
rc = UrlEscapeW(lpszObjectName, lpwhr->lpszPath, &len,
URL_ESCAPE_SPACES_ONLY);
- if (rc)
+ if (rc != S_OK)
{
ERR("Unable to escape string!(%s) (%d)\n",debugstr_w(lpszObjectName),rc);
strcpyW(lpwhr->lpszPath,lpszObjectName);
}
+ }else {
+ static const WCHAR slashW[] = {'/',0};
+
+ lpwhr->lpszPath = heap_strdupW(slashW);
}
if (lpszReferrer && *lpszReferrer)
@@ -1973,23 +2457,19 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
}
}
- lpwhr->lpszVerb = WININET_strdupW(lpszVerb && *lpszVerb ? lpszVerb : szGET);
-
- if (lpszVersion)
- lpwhr->lpszVersion = WININET_strdupW(lpszVersion);
- else
- lpwhr->lpszVersion = WININET_strdupW(g_szHttp1_1);
+ lpwhr->lpszVerb = heap_strdupW(lpszVerb && *lpszVerb ? lpszVerb : szGET);
+ lpwhr->lpszVersion = heap_strdupW(lpszVersion ? lpszVersion : g_szHttp1_1);
if (lpwhs->nHostPort != INTERNET_INVALID_PORT_NUMBER &&
lpwhs->nHostPort != INTERNET_DEFAULT_HTTP_PORT &&
lpwhs->nHostPort != INTERNET_DEFAULT_HTTPS_PORT)
{
sprintfW(lpszHostName, szHostForm, lpwhs->lpszHostName, lpwhs->nHostPort);
- HTTP_ProcessHeader(lpwhr, szHost, lpszHostName,
+ HTTP_ProcessHeader(lpwhr, hostW, lpszHostName,
HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REQ);
}
else
- HTTP_ProcessHeader(lpwhr, szHost, lpwhs->lpszHostName,
+ HTTP_ProcessHeader(lpwhr, hostW, lpwhs->lpszHostName,
HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REQ);
if (lpwhs->nServerPort == INTERNET_INVALID_PORT_NUMBER)
@@ -2015,81 +2495,89 @@ lend:
WININET_Release( &lpwhr->hdr );
TRACE("<-- %p (%p)\n", handle, lpwhr);
+ *ret = handle;
+ return res;
+}
+
+/***********************************************************************
+ * HttpOpenRequestW (WININET.@)
+ *
+ * Open a HTTP request handle
+ *
+ * RETURNS
+ * HINTERNET a HTTP request handle on success
+ * NULL on failure
+ *
+ */
+HINTERNET WINAPI HttpOpenRequestW(HINTERNET hHttpSession,
+ LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
+ LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
+ DWORD dwFlags, DWORD_PTR dwContext)
+{
+ http_session_t *lpwhs;
+ HINTERNET handle = NULL;
+ DWORD res;
+
+ TRACE("(%p, %s, %s, %s, %s, %p, %08x, %08lx)\n", hHttpSession,
+ debugstr_w(lpszVerb), debugstr_w(lpszObjectName),
+ debugstr_w(lpszVersion), debugstr_w(lpszReferrer), lpszAcceptTypes,
+ dwFlags, dwContext);
+ if(lpszAcceptTypes!=NULL)
+ {
+ int i;
+ for(i=0;lpszAcceptTypes[i]!=NULL;i++)
+ TRACE("\taccept type: %s\n",debugstr_w(lpszAcceptTypes[i]));
+ }
+
+ lpwhs = (http_session_t*) WININET_GetObject( hHttpSession );
+ if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ /*
+ * My tests seem to show that the windows version does not
+ * become asynchronous until after this point. And anyhow
+ * if this call was asynchronous then how would you get the
+ * necessary HINTERNET pointer returned by this function.
+ *
+ */
+ res = HTTP_HttpOpenRequestW(lpwhs, lpszVerb, lpszObjectName,
+ lpszVersion, lpszReferrer, lpszAcceptTypes,
+ dwFlags, dwContext, &handle);
+lend:
+ if( lpwhs )
+ WININET_Release( &lpwhs->hdr );
+ TRACE("returning %p\n", handle);
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
return handle;
}
/* read any content returned by the server so that the connection can be
* reused */
-static void HTTP_DrainContent(WININETHTTPREQW *req)
+static void HTTP_DrainContent(http_request_t *req)
{
DWORD bytes_read;
if (!NETCON_connected(&req->netConnection)) return;
if (req->dwContentLength == -1)
+ {
NETCON_close(&req->netConnection);
+ return;
+ }
+ if (!strcmpW(req->lpszVerb, szHEAD)) return;
do
{
char buffer[2048];
- if (HTTP_Read(req, buffer, sizeof(buffer), &bytes_read, TRUE) != ERROR_SUCCESS)
+ if (HTTPREQ_Read(req, buffer, sizeof(buffer), &bytes_read, TRUE) != ERROR_SUCCESS)
return;
} while (bytes_read);
}
-static const WCHAR szAccept[] = { 'A','c','c','e','p','t',0 };
-static const WCHAR szAccept_Charset[] = { 'A','c','c','e','p','t','-','C','h','a','r','s','e','t', 0 };
-static const WCHAR szAccept_Encoding[] = { 'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',0 };
-static const WCHAR szAccept_Language[] = { 'A','c','c','e','p','t','-','L','a','n','g','u','a','g','e',0 };
-static const WCHAR szAccept_Ranges[] = { 'A','c','c','e','p','t','-','R','a','n','g','e','s',0 };
-static const WCHAR szAge[] = { 'A','g','e',0 };
-static const WCHAR szAllow[] = { 'A','l','l','o','w',0 };
-static const WCHAR szCache_Control[] = { 'C','a','c','h','e','-','C','o','n','t','r','o','l',0 };
-static const WCHAR szConnection[] = { 'C','o','n','n','e','c','t','i','o','n',0 };
-static const WCHAR szContent_Base[] = { 'C','o','n','t','e','n','t','-','B','a','s','e',0 };
-static const WCHAR szContent_Encoding[] = { 'C','o','n','t','e','n','t','-','E','n','c','o','d','i','n','g',0 };
-static const WCHAR szContent_ID[] = { 'C','o','n','t','e','n','t','-','I','D',0 };
-static const WCHAR szContent_Language[] = { 'C','o','n','t','e','n','t','-','L','a','n','g','u','a','g','e',0 };
-static const WCHAR szContent_Length[] = { 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0 };
-static const WCHAR szContent_Location[] = { 'C','o','n','t','e','n','t','-','L','o','c','a','t','i','o','n',0 };
-static const WCHAR szContent_MD5[] = { 'C','o','n','t','e','n','t','-','M','D','5',0 };
-static const WCHAR szContent_Range[] = { 'C','o','n','t','e','n','t','-','R','a','n','g','e',0 };
-static const WCHAR szContent_Transfer_Encoding[] = { 'C','o','n','t','e','n','t','-','T','r','a','n','s','f','e','r','-','E','n','c','o','d','i','n','g',0 };
-static const WCHAR szContent_Type[] = { 'C','o','n','t','e','n','t','-','T','y','p','e',0 };
-static const WCHAR szCookie[] = { 'C','o','o','k','i','e',0 };
-static const WCHAR szDate[] = { 'D','a','t','e',0 };
-static const WCHAR szFrom[] = { 'F','r','o','m',0 };
-static const WCHAR szETag[] = { 'E','T','a','g',0 };
-static const WCHAR szExpect[] = { 'E','x','p','e','c','t',0 };
-static const WCHAR szExpires[] = { 'E','x','p','i','r','e','s',0 };
-static const WCHAR szIf_Match[] = { 'I','f','-','M','a','t','c','h',0 };
-static const WCHAR szIf_Modified_Since[] = { 'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0 };
-static const WCHAR szIf_None_Match[] = { 'I','f','-','N','o','n','e','-','M','a','t','c','h',0 };
-static const WCHAR szIf_Range[] = { 'I','f','-','R','a','n','g','e',0 };
-static const WCHAR szIf_Unmodified_Since[] = { 'I','f','-','U','n','m','o','d','i','f','i','e','d','-','S','i','n','c','e',0 };
-static const WCHAR szLast_Modified[] = { 'L','a','s','t','-','M','o','d','i','f','i','e','d',0 };
-static const WCHAR szLocation[] = { 'L','o','c','a','t','i','o','n',0 };
-static const WCHAR szMax_Forwards[] = { 'M','a','x','-','F','o','r','w','a','r','d','s',0 };
-static const WCHAR szMime_Version[] = { 'M','i','m','e','-','V','e','r','s','i','o','n',0 };
-static const WCHAR szPragma[] = { 'P','r','a','g','m','a',0 };
-static const WCHAR szProxy_Authenticate[] = { 'P','r','o','x','y','-','A','u','t','h','e','n','t','i','c','a','t','e',0 };
-static const WCHAR szProxy_Connection[] = { 'P','r','o','x','y','-','C','o','n','n','e','c','t','i','o','n',0 };
-static const WCHAR szPublic[] = { 'P','u','b','l','i','c',0 };
-static const WCHAR szRange[] = { 'R','a','n','g','e',0 };
-static const WCHAR szReferer[] = { 'R','e','f','e','r','e','r',0 };
-static const WCHAR szRetry_After[] = { 'R','e','t','r','y','-','A','f','t','e','r',0 };
-static const WCHAR szServer[] = { 'S','e','r','v','e','r',0 };
-static const WCHAR szSet_Cookie[] = { 'S','e','t','-','C','o','o','k','i','e',0 };
-static const WCHAR szTransfer_Encoding[] = { 'T','r','a','n','s','f','e','r','-','E','n','c','o','d','i','n','g',0 };
-static const WCHAR szUnless_Modified_Since[] = { 'U','n','l','e','s','s','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0 };
-static const WCHAR szUpgrade[] = { 'U','p','g','r','a','d','e',0 };
-static const WCHAR szURI[] = { 'U','R','I',0 };
-static const WCHAR szUser_Agent[] = { 'U','s','e','r','-','A','g','e','n','t',0 };
-static const WCHAR szVary[] = { 'V','a','r','y',0 };
-static const WCHAR szVia[] = { 'V','i','a',0 };
-static const WCHAR szWarning[] = { 'W','a','r','n','i','n','g',0 };
-static const WCHAR szWWW_Authenticate[] = { 'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',0 };
-
static const LPCWSTR header_lookup[] = {
szMime_Version, /* HTTP_QUERY_MIME_VERSION = 0 */
szContent_Type, /* HTTP_QUERY_CONTENT_TYPE = 1 */
@@ -2146,7 +2634,7 @@ static const LPCWSTR header_lookup[] = {
szContent_MD5, /* HTTP_QUERY_CONTENT_MD5 = 52 */
szContent_Range, /* HTTP_QUERY_CONTENT_RANGE = 53 */
szETag, /* HTTP_QUERY_ETAG = 54 */
- szHost, /* HTTP_QUERY_HOST = 55 */
+ hostW, /* HTTP_QUERY_HOST = 55 */
szIf_Match, /* HTTP_QUERY_IF_MATCH = 56 */
szIf_None_Match, /* HTTP_QUERY_IF_NONE_MATCH = 57 */
szIf_Range, /* HTTP_QUERY_IF_RANGE = 58 */
@@ -2169,58 +2657,64 @@ static const LPCWSTR header_lookup[] = {
/***********************************************************************
* HTTP_HttpQueryInfoW (internal)
*/
-static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel,
- LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
+static DWORD HTTP_HttpQueryInfoW(http_request_t *lpwhr, DWORD dwInfoLevel,
+ LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
{
LPHTTPHEADERW lphttpHdr = NULL;
- BOOL bSuccess = FALSE;
BOOL request_only = dwInfoLevel & HTTP_QUERY_FLAG_REQUEST_HEADERS;
INT requested_index = lpdwIndex ? *lpdwIndex : 0;
- INT level = (dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK);
+ DWORD level = (dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK);
INT index = -1;
/* Find requested header structure */
switch (level)
{
case HTTP_QUERY_CUSTOM:
+ if (!lpBuffer) return ERROR_INVALID_PARAMETER;
index = HTTP_GetCustomHeaderIndex(lpwhr, lpBuffer, requested_index, request_only);
break;
-
case HTTP_QUERY_RAW_HEADERS_CRLF:
{
LPWSTR headers;
- DWORD len;
- BOOL ret = FALSE;
+ DWORD len = 0;
+ DWORD res = ERROR_INVALID_PARAMETER;
if (request_only)
headers = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, lpwhr->lpszVersion);
else
headers = lpwhr->lpszRawHeaders;
- len = (strlenW(headers) + 1) * sizeof(WCHAR);
- if (len > *lpdwBufferLength)
+ if (headers)
+ len = strlenW(headers) * sizeof(WCHAR);
+
+ if (len + sizeof(WCHAR) > *lpdwBufferLength)
{
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- ret = FALSE;
+ len += sizeof(WCHAR);
+ res = ERROR_INSUFFICIENT_BUFFER;
}
else if (lpBuffer)
{
- memcpy(lpBuffer, headers, len);
+ if (headers)
+ memcpy(lpBuffer, headers, len + sizeof(WCHAR));
+ else
+ {
+ len = strlenW(szCrLf) * sizeof(WCHAR);
+ memcpy(lpBuffer, szCrLf, sizeof(szCrLf));
+ }
TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len / sizeof(WCHAR)));
- ret = TRUE;
+ res = ERROR_SUCCESS;
}
*lpdwBufferLength = len;
if (request_only)
HeapFree(GetProcessHeap(), 0, headers);
- return ret;
+ return res;
}
case HTTP_QUERY_RAW_HEADERS:
{
- static const WCHAR szCrLf[] = {'\r','\n',0};
LPWSTR * ppszRawHeaderLines = HTTP_Tokenize(lpwhr->lpszRawHeaders, szCrLf);
DWORD i, size = 0;
- LPWSTR pszString = (WCHAR*)lpBuffer;
+ LPWSTR pszString = lpBuffer;
for (i = 0; ppszRawHeaderLines[i]; i++)
size += strlenW(ppszRawHeaderLines[i]) + 1;
@@ -2229,24 +2723,23 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev
{
HTTP_FreeTokens(ppszRawHeaderLines);
*lpdwBufferLength = (size + 1) * sizeof(WCHAR);
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
+ return ERROR_INSUFFICIENT_BUFFER;
}
-
- for (i = 0; ppszRawHeaderLines[i]; i++)
+ if (pszString)
{
- DWORD len = strlenW(ppszRawHeaderLines[i]);
- memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR));
- pszString += len+1;
+ for (i = 0; ppszRawHeaderLines[i]; i++)
+ {
+ DWORD len = strlenW(ppszRawHeaderLines[i]);
+ memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR));
+ pszString += len+1;
+ }
+ *pszString = '\0';
+ TRACE("returning data: %s\n", debugstr_wn(lpBuffer, size));
}
- *pszString = '\0';
-
- TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, size));
-
*lpdwBufferLength = size * sizeof(WCHAR);
HTTP_FreeTokens(ppszRawHeaderLines);
- return TRUE;
+ return ERROR_SUCCESS;
}
case HTTP_QUERY_STATUS_TEXT:
if (lpwhr->lpszStatusText)
@@ -2255,15 +2748,15 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev
if (len + 1 > *lpdwBufferLength/sizeof(WCHAR))
{
*lpdwBufferLength = (len + 1) * sizeof(WCHAR);
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+ if (lpBuffer)
+ {
+ memcpy(lpBuffer, lpwhr->lpszStatusText, (len + 1) * sizeof(WCHAR));
+ TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len));
}
- memcpy(lpBuffer, lpwhr->lpszStatusText, (len+1)*sizeof(WCHAR));
*lpdwBufferLength = len * sizeof(WCHAR);
-
- TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, len));
-
- return TRUE;
+ return ERROR_SUCCESS;
}
break;
case HTTP_QUERY_VERSION:
@@ -2273,21 +2766,25 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev
if (len + 1 > *lpdwBufferLength/sizeof(WCHAR))
{
*lpdwBufferLength = (len + 1) * sizeof(WCHAR);
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+ if (lpBuffer)
+ {
+ memcpy(lpBuffer, lpwhr->lpszVersion, (len + 1) * sizeof(WCHAR));
+ TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len));
}
- memcpy(lpBuffer, lpwhr->lpszVersion, (len+1)*sizeof(WCHAR));
*lpdwBufferLength = len * sizeof(WCHAR);
-
- TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, len));
-
- return TRUE;
+ return ERROR_SUCCESS;
}
break;
+ case HTTP_QUERY_CONTENT_ENCODING:
+ index = HTTP_GetCustomHeaderIndex(lpwhr, header_lookup[lpwhr->gzip_stream ? HTTP_QUERY_CONTENT_TYPE : level],
+ requested_index,request_only);
+ break;
default:
assert (LAST_TABLE_HEADER == (HTTP_QUERY_UNLESS_MODIFIED_SINCE + 1));
- if (level >= 0 && level < LAST_TABLE_HEADER && header_lookup[level])
+ if (level < LAST_TABLE_HEADER && header_lookup[level])
index = HTTP_GetCustomHeaderIndex(lpwhr, header_lookup[level],
requested_index,request_only);
}
@@ -2300,22 +2797,18 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev
((dwInfoLevel & HTTP_QUERY_FLAG_REQUEST_HEADERS) &&
(~lphttpHdr->wFlags & HDR_ISREQUEST)))
{
- INTERNET_SetLastError(ERROR_HTTP_HEADER_NOT_FOUND);
- return bSuccess;
+ return ERROR_HTTP_HEADER_NOT_FOUND;
}
- if (lpdwIndex)
- (*lpdwIndex)++;
+ if (lpdwIndex && level != HTTP_QUERY_STATUS_CODE) (*lpdwIndex)++;
/* coalesce value to requested type */
- if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER)
+ if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER && lpBuffer)
{
- *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue);
- bSuccess = TRUE;
-
- TRACE(" returning number : %d\n", *(int *)lpBuffer);
- }
- else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME)
+ *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue);
+ TRACE(" returning number: %d\n", *(int *)lpBuffer);
+ }
+ else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer)
{
time_t tmpTime;
struct tm tmpTM;
@@ -2324,24 +2817,19 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev
tmpTime = ConvertTimeString(lphttpHdr->lpszValue);
tmpTM = *gmtime(&tmpTime);
- STHook = (SYSTEMTIME *) lpBuffer;
- if(STHook==NULL)
- return bSuccess;
+ STHook = (SYSTEMTIME *)lpBuffer;
+ STHook->wDay = tmpTM.tm_mday;
+ STHook->wHour = tmpTM.tm_hour;
+ STHook->wMilliseconds = 0;
+ STHook->wMinute = tmpTM.tm_min;
+ STHook->wDayOfWeek = tmpTM.tm_wday;
+ STHook->wMonth = tmpTM.tm_mon + 1;
+ STHook->wSecond = tmpTM.tm_sec;
+ STHook->wYear = tmpTM.tm_year;
- STHook->wDay = tmpTM.tm_mday;
- STHook->wHour = tmpTM.tm_hour;
- STHook->wMilliseconds = 0;
- STHook->wMinute = tmpTM.tm_min;
- STHook->wDayOfWeek = tmpTM.tm_wday;
- STHook->wMonth = tmpTM.tm_mon + 1;
- STHook->wSecond = tmpTM.tm_sec;
- STHook->wYear = tmpTM.tm_year;
-
- bSuccess = TRUE;
-
- TRACE(" returning time : %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
- STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek,
- STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds);
+ TRACE(" returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
+ STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek,
+ STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds);
}
else if (lphttpHdr->lpszValue)
{
@@ -2350,17 +2838,16 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev
if (len > *lpdwBufferLength)
{
*lpdwBufferLength = len;
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return bSuccess;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+ if (lpBuffer)
+ {
+ memcpy(lpBuffer, lphttpHdr->lpszValue, len);
+ TRACE("! returning string: %s\n", debugstr_w(lpBuffer));
}
-
- memcpy(lpBuffer, lphttpHdr->lpszValue, len);
*lpdwBufferLength = len - sizeof(WCHAR);
- bSuccess = TRUE;
-
- TRACE(" returning string : %s\n", debugstr_w(lpBuffer));
}
- return bSuccess;
+ return ERROR_SUCCESS;
}
/***********************************************************************
@@ -2374,10 +2861,10 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev
*
*/
BOOL WINAPI HttpQueryInfoW(HINTERNET hHttpRequest, DWORD dwInfoLevel,
- LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
+ LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
{
- BOOL bSuccess = FALSE;
- LPWININETHTTPREQW lpwhr;
+ http_request_t *lpwhr;
+ DWORD res;
if (TRACE_ON(wininet)) {
#define FE(x) { x, #x }
@@ -2463,7 +2950,7 @@ BOOL WINAPI HttpQueryInfoW(HINTERNET hHttpRequest, DWORD dwInfoLevel,
DWORD info = dwInfoLevel & HTTP_QUERY_HEADER_MASK;
DWORD i;
- TRACE("(%p, 0x%08x)--> %d\n", hHttpRequest, dwInfoLevel, dwInfoLevel);
+ TRACE("(%p, 0x%08x)--> %d\n", hHttpRequest, dwInfoLevel, info);
TRACE(" Attribute:");
for (i = 0; i < (sizeof(query_flags) / sizeof(query_flags[0])); i++) {
if (query_flags[i].val == info) {
@@ -2489,24 +2976,26 @@ BOOL WINAPI HttpQueryInfoW(HINTERNET hHttpRequest, DWORD dwInfoLevel,
TRACE("\n");
}
- lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hHttpRequest );
+ lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto lend;
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
}
if (lpBuffer == NULL)
*lpdwBufferLength = 0;
- bSuccess = HTTP_HttpQueryInfoW( lpwhr, dwInfoLevel,
- lpBuffer, lpdwBufferLength, lpdwIndex);
+ res = HTTP_HttpQueryInfoW( lpwhr, dwInfoLevel,
+ lpBuffer, lpdwBufferLength, lpdwIndex);
lend:
if( lpwhr )
WININET_Release( &lpwhr->hdr );
- TRACE("%d <--\n", bSuccess);
- return bSuccess;
+ TRACE("%u <--\n", res);
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
}
/***********************************************************************
@@ -2577,287 +3066,74 @@ BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel,
}
/***********************************************************************
- * HttpSendRequestExA (WININET.@)
- *
- * Sends the specified request to the HTTP server and allows chunked
- * transfers.
- *
- * RETURNS
- * Success: TRUE
- * Failure: FALSE, call GetLastError() for more information.
+ * HTTP_GetRedirectURL (internal)
*/
-BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
- LPINTERNET_BUFFERSA lpBuffersIn,
- LPINTERNET_BUFFERSA lpBuffersOut,
- DWORD dwFlags, DWORD_PTR dwContext)
+static LPWSTR HTTP_GetRedirectURL(http_request_t *lpwhr, LPCWSTR lpszUrl)
{
- INTERNET_BUFFERSW BuffersInW;
- BOOL rc = FALSE;
- DWORD headerlen;
- LPWSTR header = NULL;
+ static WCHAR szHttp[] = {'h','t','t','p',0};
+ static WCHAR szHttps[] = {'h','t','t','p','s',0};
+ http_session_t *lpwhs = lpwhr->lpHttpSession;
+ URL_COMPONENTSW urlComponents;
+ DWORD url_length = 0;
+ LPWSTR orig_url;
+ LPWSTR combined_url;
- TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
- lpBuffersOut, dwFlags, dwContext);
+ urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
+ urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
+ urlComponents.dwSchemeLength = 0;
+ urlComponents.lpszHostName = lpwhs->lpszHostName;
+ urlComponents.dwHostNameLength = 0;
+ urlComponents.nPort = lpwhs->nHostPort;
+ urlComponents.lpszUserName = lpwhs->lpszUserName;
+ urlComponents.dwUserNameLength = 0;
+ urlComponents.lpszPassword = NULL;
+ urlComponents.dwPasswordLength = 0;
+ urlComponents.lpszUrlPath = lpwhr->lpszPath;
+ urlComponents.dwUrlPathLength = 0;
+ urlComponents.lpszExtraInfo = NULL;
+ urlComponents.dwExtraInfoLength = 0;
- if (lpBuffersIn)
+ if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) &&
+ (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+ return NULL;
+
+ orig_url = HeapAlloc(GetProcessHeap(), 0, url_length);
+
+ /* convert from bytes to characters */
+ url_length = url_length / sizeof(WCHAR) - 1;
+ if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length))
{
- BuffersInW.dwStructSize = sizeof(LPINTERNET_BUFFERSW);
- if (lpBuffersIn->lpcszHeader)
- {
- headerlen = MultiByteToWideChar(CP_ACP,0,lpBuffersIn->lpcszHeader,
- lpBuffersIn->dwHeadersLength,0,0);
- header = HeapAlloc(GetProcessHeap(),0,headerlen*sizeof(WCHAR));
- if (!(BuffersInW.lpcszHeader = header))
- {
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
- return FALSE;
- }
- BuffersInW.dwHeadersLength = MultiByteToWideChar(CP_ACP, 0,
- lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
- header, headerlen);
- }
- else
- BuffersInW.lpcszHeader = NULL;
- BuffersInW.dwHeadersTotal = lpBuffersIn->dwHeadersTotal;
- BuffersInW.lpvBuffer = lpBuffersIn->lpvBuffer;
- BuffersInW.dwBufferLength = lpBuffersIn->dwBufferLength;
- BuffersInW.dwBufferTotal = lpBuffersIn->dwBufferTotal;
- BuffersInW.Next = NULL;
+ HeapFree(GetProcessHeap(), 0, orig_url);
+ return NULL;
}
- rc = HttpSendRequestExW(hRequest, lpBuffersIn ? &BuffersInW : NULL, NULL, dwFlags, dwContext);
+ url_length = 0;
+ if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) &&
+ (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+ {
+ HeapFree(GetProcessHeap(), 0, orig_url);
+ return NULL;
+ }
+ combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR));
- HeapFree(GetProcessHeap(),0,header);
-
- return rc;
+ if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY))
+ {
+ HeapFree(GetProcessHeap(), 0, orig_url);
+ HeapFree(GetProcessHeap(), 0, combined_url);
+ return NULL;
+ }
+ HeapFree(GetProcessHeap(), 0, orig_url);
+ return combined_url;
}
-/***********************************************************************
- * HttpSendRequestExW (WININET.@)
- *
- * Sends the specified request to the HTTP server and allows chunked
- * transfers
- *
- * RETURNS
- * Success: TRUE
- * Failure: FALSE, call GetLastError() for more information.
- */
-BOOL WINAPI HttpSendRequestExW(HINTERNET hRequest,
- LPINTERNET_BUFFERSW lpBuffersIn,
- LPINTERNET_BUFFERSW lpBuffersOut,
- DWORD dwFlags, DWORD_PTR dwContext)
-{
- BOOL ret = FALSE;
- LPWININETHTTPREQW lpwhr;
- LPWININETHTTPSESSIONW lpwhs;
- LPWININETAPPINFOW hIC;
-
- TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
- lpBuffersOut, dwFlags, dwContext);
-
- lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
-
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto lend;
- }
-
- lpwhs = lpwhr->lpHttpSession;
- assert(lpwhs->hdr.htype == WH_HHTTPSESSION);
- hIC = lpwhs->lpAppInfo;
- assert(hIC->hdr.htype == WH_HINIT);
-
- if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- WORKREQUEST workRequest;
- struct WORKREQ_HTTPSENDREQUESTW *req;
-
- workRequest.asyncproc = AsyncHttpSendRequestProc;
- workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
- req = &workRequest.u.HttpSendRequestW;
- if (lpBuffersIn)
- {
- if (lpBuffersIn->lpcszHeader)
- /* FIXME: this should use dwHeadersLength or may not be necessary at all */
- req->lpszHeader = WININET_strdupW(lpBuffersIn->lpcszHeader);
- else
- req->lpszHeader = NULL;
- req->dwHeaderLength = lpBuffersIn->dwHeadersLength;
- req->lpOptional = lpBuffersIn->lpvBuffer;
- req->dwOptionalLength = lpBuffersIn->dwBufferLength;
- req->dwContentLength = lpBuffersIn->dwBufferTotal;
- }
- else
- {
- req->lpszHeader = NULL;
- req->dwHeaderLength = 0;
- req->lpOptional = NULL;
- req->dwOptionalLength = 0;
- req->dwContentLength = 0;
- }
-
- req->bEndRequest = FALSE;
-
- INTERNET_AsyncCall(&workRequest);
- /*
- * This is from windows.
- */
- INTERNET_SetLastError(ERROR_IO_PENDING);
- }
- else
- {
- if (lpBuffersIn)
- ret = HTTP_HttpSendRequestW(lpwhr, lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
- lpBuffersIn->lpvBuffer, lpBuffersIn->dwBufferLength,
- lpBuffersIn->dwBufferTotal, FALSE);
- else
- ret = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, FALSE);
- }
-
-lend:
- if ( lpwhr )
- WININET_Release( &lpwhr->hdr );
-
- TRACE("<---\n");
- return ret;
-}
-
-/***********************************************************************
- * HttpSendRequestW (WININET.@)
- *
- * Sends the specified request to the HTTP server
- *
- * RETURNS
- * TRUE on success
- * FALSE on failure
- *
- */
-BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
- DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
-{
- LPWININETHTTPREQW lpwhr;
- LPWININETHTTPSESSIONW lpwhs = NULL;
- LPWININETAPPINFOW hIC = NULL;
- BOOL r;
-
- TRACE("%p, %s, %i, %p, %i)\n", hHttpRequest,
- debugstr_wn(lpszHeaders, dwHeaderLength), dwHeaderLength, lpOptional, dwOptionalLength);
-
- lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hHttpRequest );
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- r = FALSE;
- goto lend;
- }
-
- lpwhs = lpwhr->lpHttpSession;
- if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- r = FALSE;
- goto lend;
- }
-
- hIC = lpwhs->lpAppInfo;
- if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- r = FALSE;
- goto lend;
- }
-
- if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- WORKREQUEST workRequest;
- struct WORKREQ_HTTPSENDREQUESTW *req;
-
- workRequest.asyncproc = AsyncHttpSendRequestProc;
- workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
- req = &workRequest.u.HttpSendRequestW;
- if (lpszHeaders)
- {
- req->lpszHeader = HeapAlloc(GetProcessHeap(), 0, dwHeaderLength * sizeof(WCHAR));
- memcpy(req->lpszHeader, lpszHeaders, dwHeaderLength * sizeof(WCHAR));
- }
- else
- req->lpszHeader = 0;
- req->dwHeaderLength = dwHeaderLength;
- req->lpOptional = lpOptional;
- req->dwOptionalLength = dwOptionalLength;
- req->dwContentLength = dwOptionalLength;
- req->bEndRequest = TRUE;
-
- INTERNET_AsyncCall(&workRequest);
- /*
- * This is from windows.
- */
- INTERNET_SetLastError(ERROR_IO_PENDING);
- r = FALSE;
- }
- else
- {
- r = HTTP_HttpSendRequestW(lpwhr, lpszHeaders,
- dwHeaderLength, lpOptional, dwOptionalLength,
- dwOptionalLength, TRUE);
- }
-lend:
- if( lpwhr )
- WININET_Release( &lpwhr->hdr );
- return r;
-}
-
-/***********************************************************************
- * HttpSendRequestA (WININET.@)
- *
- * Sends the specified request to the HTTP server
- *
- * RETURNS
- * TRUE on success
- * FALSE on failure
- *
- */
-BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
- DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
-{
- BOOL result;
- LPWSTR szHeaders=NULL;
- DWORD nLen=dwHeaderLength;
- if(lpszHeaders!=NULL)
- {
- nLen=MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,NULL,0);
- szHeaders=HeapAlloc(GetProcessHeap(),0,nLen*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,szHeaders,nLen);
- }
- result=HttpSendRequestW(hHttpRequest, szHeaders, nLen, lpOptional, dwOptionalLength);
- HeapFree(GetProcessHeap(),0,szHeaders);
- return result;
-}
-
-static BOOL HTTP_GetRequestURL(WININETHTTPREQW *req, LPWSTR buf)
-{
- LPHTTPHEADERW host_header;
-
- static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
-
- host_header = HTTP_GetHeader(req, szHost);
- if(!host_header)
- return FALSE;
-
- sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
- return TRUE;
-}
/***********************************************************************
* HTTP_HandleRedirect (internal)
*/
-static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl)
+static DWORD HTTP_HandleRedirect(http_request_t *lpwhr, LPCWSTR lpszUrl)
{
- static const WCHAR szContentType[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
- static const WCHAR szContentLength[] = {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0};
- LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession;
- LPWININETAPPINFOW hIC = lpwhs->lpAppInfo;
+ http_session_t *lpwhs = lpwhr->lpHttpSession;
+ appinfo_t *hIC = lpwhs->lpAppInfo;
BOOL using_proxy = hIC->lpszProxy && hIC->lpszProxy[0];
WCHAR path[INTERNET_MAX_URL_LENGTH];
int index;
@@ -2873,55 +3149,6 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl)
WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024];
static WCHAR szHttp[] = {'h','t','t','p',0};
static WCHAR szHttps[] = {'h','t','t','p','s',0};
- DWORD url_length = 0;
- LPWSTR orig_url;
- LPWSTR combined_url;
-
- urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
- urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
- urlComponents.dwSchemeLength = 0;
- urlComponents.lpszHostName = lpwhs->lpszHostName;
- urlComponents.dwHostNameLength = 0;
- urlComponents.nPort = lpwhs->nHostPort;
- urlComponents.lpszUserName = lpwhs->lpszUserName;
- urlComponents.dwUserNameLength = 0;
- urlComponents.lpszPassword = NULL;
- urlComponents.dwPasswordLength = 0;
- urlComponents.lpszUrlPath = lpwhr->lpszPath;
- urlComponents.dwUrlPathLength = 0;
- urlComponents.lpszExtraInfo = NULL;
- urlComponents.dwExtraInfoLength = 0;
-
- if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) &&
- (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
- return FALSE;
-
- orig_url = HeapAlloc(GetProcessHeap(), 0, url_length);
-
- /* convert from bytes to characters */
- url_length = url_length / sizeof(WCHAR) - 1;
- if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
- return FALSE;
- }
-
- url_length = 0;
- if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) &&
- (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
- return FALSE;
- }
- combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR));
-
- if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
- HeapFree(GetProcessHeap(), 0, combined_url);
- return FALSE;
- }
- HeapFree(GetProcessHeap(), 0, orig_url);
userName[0] = 0;
hostName[0] = 0;
@@ -2940,13 +3167,8 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl)
urlComponents.dwUrlPathLength = 2048;
urlComponents.lpszExtraInfo = NULL;
urlComponents.dwExtraInfoLength = 0;
- if(!InternetCrackUrlW(combined_url, strlenW(combined_url), 0, &urlComponents))
- {
- HeapFree(GetProcessHeap(), 0, combined_url);
- return FALSE;
- }
-
- HeapFree(GetProcessHeap(), 0, combined_url);
+ if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents))
+ return INTERNET_GetLastError();
if (!strncmpW(szHttp, urlComponents.lpszScheme, strlenW(szHttp)) &&
(lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE))
@@ -3000,26 +3222,35 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl)
sprintfW(lpwhs->lpszHostName, fmt, hostName, urlComponents.nPort);
}
else
- lpwhs->lpszHostName = WININET_strdupW(hostName);
+ lpwhs->lpszHostName = heap_strdupW(hostName);
- HTTP_ProcessHeader(lpwhr, szHost, lpwhs->lpszHostName, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ);
+ HTTP_ProcessHeader(lpwhr, hostW, lpwhs->lpszHostName, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ);
HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
lpwhs->lpszUserName = NULL;
if (userName[0])
- lpwhs->lpszUserName = WININET_strdupW(userName);
+ lpwhs->lpszUserName = heap_strdupW(userName);
if (!using_proxy)
{
if (strcmpiW(lpwhs->lpszServerName, hostName) || lpwhs->nServerPort != urlComponents.nPort)
{
+ DWORD res;
+
HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
- lpwhs->lpszServerName = WININET_strdupW(hostName);
+ lpwhs->lpszServerName = heap_strdupW(hostName);
lpwhs->nServerPort = urlComponents.nPort;
NETCON_close(&lpwhr->netConnection);
- if (!HTTP_ResolveName(lpwhr)) return FALSE;
- if (!NETCON_init(&lpwhr->netConnection, lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE)) return FALSE;
+ if ((res = HTTP_ResolveName(lpwhr)) != ERROR_SUCCESS)
+ return res;
+
+ res = NETCON_init(&lpwhr->netConnection, lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE);
+ if (res != ERROR_SUCCESS)
+ return res;
+
+ lpwhr->read_pos = lpwhr->read_size = 0;
+ lpwhr->read_chunked = FALSE;
}
}
else
@@ -3039,7 +3270,7 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl)
lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, needed*sizeof(WCHAR));
rc = UrlEscapeW(path, lpwhr->lpszPath, &needed,
URL_ESCAPE_SPACES_ONLY);
- if (rc)
+ if (rc != S_OK)
{
ERR("Unable to escape string!(%s) (%d)\n",debugstr_w(path),rc);
strcpyW(lpwhr->lpszPath,path);
@@ -3047,14 +3278,14 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl)
}
/* Remove custom content-type/length headers on redirects. */
- index = HTTP_GetCustomHeaderIndex(lpwhr, szContentType, 0, TRUE);
+ index = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Type, 0, TRUE);
if (0 <= index)
HTTP_DeleteCustomHeader(lpwhr, index);
- index = HTTP_GetCustomHeaderIndex(lpwhr, szContentLength, 0, TRUE);
+ index = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Length, 0, TRUE);
if (0 <= index)
HTTP_DeleteCustomHeader(lpwhr, index);
- return TRUE;
+ return ERROR_SUCCESS;
}
/***********************************************************************
@@ -3080,7 +3311,7 @@ static LPWSTR HTTP_build_req( LPCWSTR *list, int len )
return str;
}
-static BOOL HTTP_SecureProxyConnect(LPWININETHTTPREQW lpwhr)
+static DWORD HTTP_SecureProxyConnect(http_request_t *lpwhr)
{
LPWSTR lpszPath;
LPWSTR requestString;
@@ -3088,10 +3319,10 @@ static BOOL HTTP_SecureProxyConnect(LPWININETHTTPREQW lpwhr)
INT cnt;
INT responseLen;
char *ascii_req;
- BOOL ret;
+ DWORD res;
static const WCHAR szConnect[] = {'C','O','N','N','E','C','T',0};
static const WCHAR szFormat[] = {'%','s',':','%','d',0};
- LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession;
+ http_session_t *lpwhs = lpwhr->lpHttpSession;
TRACE("\n");
@@ -3110,43 +3341,42 @@ static BOOL HTTP_SecureProxyConnect(LPWININETHTTPREQW lpwhr)
TRACE("full request -> %s\n", debugstr_an( ascii_req, len ) );
- ret = NETCON_send( &lpwhr->netConnection, ascii_req, len, 0, &cnt );
+ res = NETCON_send( &lpwhr->netConnection, ascii_req, len, 0, &cnt );
HeapFree( GetProcessHeap(), 0, ascii_req );
- if (!ret || cnt < 0)
- return FALSE;
+ if (res != ERROR_SUCCESS)
+ return res;
responseLen = HTTP_GetResponseHeaders( lpwhr, TRUE );
if (!responseLen)
- return FALSE;
+ return ERROR_HTTP_INVALID_HEADER;
- return TRUE;
+ return ERROR_SUCCESS;
}
-static void HTTP_InsertCookies(LPWININETHTTPREQW lpwhr)
+static void HTTP_InsertCookies(http_request_t *lpwhr)
{
- static const WCHAR szUrlForm[] = {'h','t','t','p',':','/','/','%','s',0};
+ static const WCHAR szUrlForm[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
LPWSTR lpszCookies, lpszUrl = NULL;
DWORD nCookieSize, size;
- LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr,szHost);
+ LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
- size = (strlenW(Host->lpszValue) + strlenW(szUrlForm)) * sizeof(WCHAR);
+ size = (strlenW(Host->lpszValue) + strlenW(szUrlForm) + strlenW(lpwhr->lpszPath)) * sizeof(WCHAR);
if (!(lpszUrl = HeapAlloc(GetProcessHeap(), 0, size))) return;
- sprintfW( lpszUrl, szUrlForm, Host->lpszValue );
+ sprintfW( lpszUrl, szUrlForm, Host->lpszValue, lpwhr->lpszPath);
if (InternetGetCookieW(lpszUrl, NULL, NULL, &nCookieSize))
{
int cnt = 0;
static const WCHAR szCookie[] = {'C','o','o','k','i','e',':',' ',0};
- static const WCHAR szcrlf[] = {'\r','\n',0};
- size = sizeof(szCookie) + nCookieSize * sizeof(WCHAR) + sizeof(szcrlf);
+ size = sizeof(szCookie) + nCookieSize * sizeof(WCHAR) + sizeof(szCrLf);
if ((lpszCookies = HeapAlloc(GetProcessHeap(), 0, size)))
{
cnt += sprintfW(lpszCookies, szCookie);
InternetGetCookieW(lpszUrl, NULL, lpszCookies + cnt, &nCookieSize);
- strcatW(lpszCookies, szcrlf);
+ strcatW(lpszCookies, szCrLf);
- HTTP_HttpAddRequestHeadersW(lpwhr, lpszCookies, strlenW(lpszCookies), HTTP_ADDREQ_FLAG_ADD);
+ HTTP_HttpAddRequestHeadersW(lpwhr, lpszCookies, strlenW(lpszCookies), HTTP_ADDREQ_FLAG_REPLACE);
HeapFree(GetProcessHeap(), 0, lpszCookies);
}
}
@@ -3163,12 +3393,12 @@ static void HTTP_InsertCookies(LPWININETHTTPREQW lpwhr)
* FALSE on failure
*
*/
-BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
+static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength,
DWORD dwContentLength, BOOL bEndRequest)
{
INT cnt;
- BOOL bSuccess = FALSE;
+ BOOL redirected = FALSE;
LPWSTR requestString = NULL;
INT responseLen;
BOOL loop_next;
@@ -3177,6 +3407,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
static const WCHAR szContentLength[] =
{ 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','l','i','\r','\n',0 };
WCHAR contentLengthStr[sizeof szContentLength/2 /* includes \r\n */ + 20 /* int */ ];
+ DWORD res;
TRACE("--> %p\n", lpwhr);
@@ -3184,12 +3415,13 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
/* if the verb is NULL default to GET */
if (!lpwhr->lpszVerb)
- lpwhr->lpszVerb = WININET_strdupW(szGET);
+ lpwhr->lpszVerb = heap_strdupW(szGET);
- if (dwContentLength || !strcmpW(lpwhr->lpszVerb, szPost))
+ if (dwContentLength || strcmpW(lpwhr->lpszVerb, szGET))
{
sprintfW(contentLengthStr, szContentLength, dwContentLength);
- HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
+ HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_REPLACE);
+ lpwhr->dwBytesToWrite = dwContentLength;
}
if (lpwhr->lpHttpSession->lpAppInfo->lpszAgent)
{
@@ -3230,7 +3462,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
if (TRACE_ON(wininet))
{
- LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr,szHost);
+ LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
TRACE("Going to url %s %s\n", debugstr_w(Host->lpszValue), debugstr_w(lpwhr->lpszPath));
}
@@ -3265,11 +3497,11 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
TRACE("Request header -> %s\n", debugstr_w(requestString) );
/* Send the request and store the results */
- if (!HTTP_OpenConnection(lpwhr))
+ if ((res = HTTP_OpenConnection(lpwhr)) != ERROR_SUCCESS)
goto lend;
/* send the request as ASCII, tack on the optional data */
- if( !lpOptional )
+ if (!lpOptional || redirected)
dwOptionalLength = 0;
len = WideCharToMultiByte( CP_ACP, 0, requestString, -1,
NULL, 0, NULL, NULL );
@@ -3285,9 +3517,11 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
- NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt);
+ res = NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt);
HeapFree( GetProcessHeap(), 0, ascii_req );
+ lpwhr->dwBytesWritten = dwOptionalLength;
+
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_SENT,
&len, sizeof(DWORD));
@@ -3296,18 +3530,14 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
{
DWORD dwBufferSize;
DWORD dwStatusCode;
- WCHAR encoding[20];
- static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0};
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
- if (cnt < 0)
+ if (res != ERROR_SUCCESS)
goto lend;
responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
- if (responseLen)
- bSuccess = TRUE;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
@@ -3315,61 +3545,58 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
HTTP_ProcessCookies(lpwhr);
- dwBufferSize = sizeof(lpwhr->dwContentLength);
- if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
- &lpwhr->dwContentLength,&dwBufferSize,NULL))
- lpwhr->dwContentLength = -1;
-
- if (lpwhr->dwContentLength == 0)
- HTTP_FinishedReading(lpwhr);
-
- /* Correct the case where both a Content-Length and Transfer-encoding = chunked are set */
-
- dwBufferSize = sizeof(encoding);
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_TRANSFER_ENCODING, encoding, &dwBufferSize, NULL) &&
- !strcmpiW(encoding, szChunked))
- {
- lpwhr->dwContentLength = -1;
- }
+ if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
dwBufferSize = sizeof(dwStatusCode);
- if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
- &dwStatusCode,&dwBufferSize,NULL))
+ if (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
+ &dwStatusCode,&dwBufferSize,NULL) != ERROR_SUCCESS)
dwStatusCode = 0;
- if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess)
+ if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && responseLen)
{
- WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH];
+ WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
dwBufferSize=sizeof(szNewLocation);
if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) &&
- HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
+ HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL) == ERROR_SUCCESS)
{
- HTTP_DrainContent(lpwhr);
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_REDIRECT, szNewLocation,
- dwBufferSize);
- bSuccess = HTTP_HandleRedirect(lpwhr, szNewLocation);
- if (bSuccess)
+ if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
{
- HeapFree(GetProcessHeap(), 0, requestString);
- loop_next = TRUE;
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
+ lpwhr->lpszVerb = heap_strdupW(szGET);
}
+ HTTP_DrainContent(lpwhr);
+ if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
+ {
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
+ new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
+ res = HTTP_HandleRedirect(lpwhr, new_url);
+ if (res == ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, requestString);
+ loop_next = TRUE;
+ }
+ HeapFree( GetProcessHeap(), 0, new_url );
+ }
+ redirected = TRUE;
}
}
- if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && bSuccess)
+ if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && res == ERROR_SUCCESS)
{
WCHAR szAuthValue[2048];
dwBufferSize=2048;
if (dwStatusCode == HTTP_STATUS_DENIED)
{
+ LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
DWORD dwIndex = 0;
- while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_WWW_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
+ while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_WWW_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex) == ERROR_SUCCESS)
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pAuthInfo,
lpwhr->lpHttpSession->lpszUserName,
- lpwhr->lpHttpSession->lpszPassword))
+ lpwhr->lpHttpSession->lpszPassword,
+ Host->lpszValue))
{
+ HeapFree(GetProcessHeap(), 0, requestString);
loop_next = TRUE;
break;
}
@@ -3378,12 +3605,13 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ)
{
DWORD dwIndex = 0;
- while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_PROXY_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
+ while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_PROXY_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex) == ERROR_SUCCESS)
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pProxyAuthInfo,
lpwhr->lpHttpSession->lpAppInfo->lpszProxyUsername,
- lpwhr->lpHttpSession->lpAppInfo->lpszProxyPassword))
+ lpwhr->lpHttpSession->lpAppInfo->lpszProxyPassword,
+ NULL))
{
loop_next = TRUE;
break;
@@ -3393,12 +3621,11 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
}
}
else
- bSuccess = TRUE;
+ res = ERROR_SUCCESS;
}
while (loop_next);
- /* FIXME: Better check, when we have to create the cache file */
- if(bSuccess && (lpwhr->hdr.dwFlags & INTERNET_FLAG_NEED_FILE)) {
+ if(res == ERROR_SUCCESS) {
WCHAR url[INTERNET_MAX_URL_LENGTH];
WCHAR cacheFileName[MAX_PATH+1];
BOOL b;
@@ -3411,7 +3638,10 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
b = CreateUrlCacheEntryW(url, lpwhr->dwContentLength > 0 ? lpwhr->dwContentLength : 0, NULL, cacheFileName, 0);
if(b) {
- lpwhr->lpszCacheFile = WININET_strdupW(cacheFileName);
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
+ CloseHandle(lpwhr->hCacheFile);
+
+ lpwhr->lpszCacheFile = heap_strdupW(cacheFileName);
lpwhr->hCacheFile = CreateFileW(lpwhr->lpszCacheFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(lpwhr->hCacheFile == INVALID_HANDLE_VALUE) {
@@ -3429,16 +3659,469 @@ lend:
/* TODO: send notification for P3P header */
+ if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ if (res == ERROR_SUCCESS && lpwhr->dwBytesWritten == lpwhr->dwBytesToWrite)
+ HTTP_ReceiveRequestData(lpwhr, TRUE);
+ else
+ {
+ iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
+ iar.dwError = res;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
+ }
+ }
+
+ TRACE("<--\n");
+ return res;
+}
+
+/***********************************************************************
+ *
+ * Helper functions for the HttpSendRequest(Ex) functions
+ *
+ */
+static void AsyncHttpSendRequestProc(WORKREQUEST *workRequest)
+{
+ struct WORKREQ_HTTPSENDREQUESTW const *req = &workRequest->u.HttpSendRequestW;
+ http_request_t *lpwhr = (http_request_t*) workRequest->hdr;
+
+ TRACE("%p\n", lpwhr);
+
+ HTTP_HttpSendRequestW(lpwhr, req->lpszHeader,
+ req->dwHeaderLength, req->lpOptional, req->dwOptionalLength,
+ req->dwContentLength, req->bEndRequest);
+
+ HeapFree(GetProcessHeap(), 0, req->lpszHeader);
+}
+
+
+static DWORD HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PTR dwContext)
+{
+ INT responseLen;
+ DWORD dwBufferSize;
+ INTERNET_ASYNC_RESULT iar;
+ DWORD res = ERROR_SUCCESS;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+
+ responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
+ if (!responseLen)
+ res = ERROR_HTTP_HEADER_NOT_FOUND;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
+
+ /* process cookies here. Is this right? */
+ HTTP_ProcessCookies(lpwhr);
+
+ if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
+
+ if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
+ {
+ DWORD dwCode,dwCodeLength = sizeof(DWORD);
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwCode, &dwCodeLength, NULL) == ERROR_SUCCESS
+ && (dwCode == 302 || dwCode == 301 || dwCode == 303))
+ {
+ WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
+ dwBufferSize=sizeof(szNewLocation);
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL) == ERROR_SUCCESS)
+ {
+ if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
+ {
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
+ lpwhr->lpszVerb = heap_strdupW(szGET);
+ }
+ HTTP_DrainContent(lpwhr);
+ if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
+ {
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
+ new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
+ res = HTTP_HandleRedirect(lpwhr, new_url);
+ if (res == ERROR_SUCCESS)
+ res = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
+ HeapFree( GetProcessHeap(), 0, new_url );
+ }
+ }
+ }
+ }
+
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
- iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
+ iar.dwError = res;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_COMPLETE, &iar,
sizeof(INTERNET_ASYNC_RESULT));
+ return res;
+}
- TRACE("<--\n");
- if (bSuccess) INTERNET_SetLastError(ERROR_SUCCESS);
- return bSuccess;
+/***********************************************************************
+ * HttpEndRequestA (WININET.@)
+ *
+ * Ends an HTTP request that was started by HttpSendRequestEx
+ *
+ * RETURNS
+ * TRUE if successful
+ * FALSE on failure
+ *
+ */
+BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
+ LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
+{
+ TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
+
+ if (lpBuffersOut)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
+}
+
+static void AsyncHttpEndRequestProc(WORKREQUEST *work)
+{
+ struct WORKREQ_HTTPENDREQUESTW const *req = &work->u.HttpEndRequestW;
+ http_request_t *lpwhr = (http_request_t*)work->hdr;
+
+ TRACE("%p\n", lpwhr);
+
+ HTTP_HttpEndRequestW(lpwhr, req->dwFlags, req->dwContext);
+}
+
+/***********************************************************************
+ * HttpEndRequestW (WININET.@)
+ *
+ * Ends an HTTP request that was started by HttpSendRequestEx
+ *
+ * RETURNS
+ * TRUE if successful
+ * FALSE on failure
+ *
+ */
+BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
+ LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
+{
+ http_request_t *lpwhr;
+ DWORD res;
+
+ TRACE("-->\n");
+
+ if (lpBuffersOut)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ lpwhr = (http_request_t*) WININET_GetObject( hRequest );
+
+ if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
+ {
+ SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
+ if (lpwhr)
+ WININET_Release( &lpwhr->hdr );
+ return FALSE;
+ }
+ lpwhr->hdr.dwFlags |= dwFlags;
+
+ if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ WORKREQUEST work;
+ struct WORKREQ_HTTPENDREQUESTW *request;
+
+ work.asyncproc = AsyncHttpEndRequestProc;
+ work.hdr = WININET_AddRef( &lpwhr->hdr );
+
+ request = &work.u.HttpEndRequestW;
+ request->dwFlags = dwFlags;
+ request->dwContext = dwContext;
+
+ INTERNET_AsyncCall(&work);
+ res = ERROR_IO_PENDING;
+ }
+ else
+ res = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext);
+
+ WININET_Release( &lpwhr->hdr );
+ TRACE("%u <--\n", res);
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * HttpSendRequestExA (WININET.@)
+ *
+ * Sends the specified request to the HTTP server and allows chunked
+ * transfers.
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE, call GetLastError() for more information.
+ */
+BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
+ LPINTERNET_BUFFERSA lpBuffersIn,
+ LPINTERNET_BUFFERSA lpBuffersOut,
+ DWORD dwFlags, DWORD_PTR dwContext)
+{
+ INTERNET_BUFFERSW BuffersInW;
+ BOOL rc = FALSE;
+ DWORD headerlen;
+ LPWSTR header = NULL;
+
+ TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
+ lpBuffersOut, dwFlags, dwContext);
+
+ if (lpBuffersIn)
+ {
+ BuffersInW.dwStructSize = sizeof(LPINTERNET_BUFFERSW);
+ if (lpBuffersIn->lpcszHeader)
+ {
+ headerlen = MultiByteToWideChar(CP_ACP,0,lpBuffersIn->lpcszHeader,
+ lpBuffersIn->dwHeadersLength,0,0);
+ header = HeapAlloc(GetProcessHeap(),0,headerlen*sizeof(WCHAR));
+ if (!(BuffersInW.lpcszHeader = header))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ BuffersInW.dwHeadersLength = MultiByteToWideChar(CP_ACP, 0,
+ lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
+ header, headerlen);
+ }
+ else
+ BuffersInW.lpcszHeader = NULL;
+ BuffersInW.dwHeadersTotal = lpBuffersIn->dwHeadersTotal;
+ BuffersInW.lpvBuffer = lpBuffersIn->lpvBuffer;
+ BuffersInW.dwBufferLength = lpBuffersIn->dwBufferLength;
+ BuffersInW.dwBufferTotal = lpBuffersIn->dwBufferTotal;
+ BuffersInW.Next = NULL;
+ }
+
+ rc = HttpSendRequestExW(hRequest, lpBuffersIn ? &BuffersInW : NULL, NULL, dwFlags, dwContext);
+
+ HeapFree(GetProcessHeap(),0,header);
+
+ return rc;
+}
+
+/***********************************************************************
+ * HttpSendRequestExW (WININET.@)
+ *
+ * Sends the specified request to the HTTP server and allows chunked
+ * transfers
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE, call GetLastError() for more information.
+ */
+BOOL WINAPI HttpSendRequestExW(HINTERNET hRequest,
+ LPINTERNET_BUFFERSW lpBuffersIn,
+ LPINTERNET_BUFFERSW lpBuffersOut,
+ DWORD dwFlags, DWORD_PTR dwContext)
+{
+ http_request_t *lpwhr;
+ http_session_t *lpwhs;
+ appinfo_t *hIC;
+ DWORD res;
+
+ TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
+ lpBuffersOut, dwFlags, dwContext);
+
+ lpwhr = (http_request_t*) WININET_GetObject( hRequest );
+
+ if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ lpwhs = lpwhr->lpHttpSession;
+ assert(lpwhs->hdr.htype == WH_HHTTPSESSION);
+ hIC = lpwhs->lpAppInfo;
+ assert(hIC->hdr.htype == WH_HINIT);
+
+ if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ WORKREQUEST workRequest;
+ struct WORKREQ_HTTPSENDREQUESTW *req;
+
+ workRequest.asyncproc = AsyncHttpSendRequestProc;
+ workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
+ req = &workRequest.u.HttpSendRequestW;
+ if (lpBuffersIn)
+ {
+ DWORD size = 0;
+
+ if (lpBuffersIn->lpcszHeader)
+ {
+ if (lpBuffersIn->dwHeadersLength == ~0u)
+ size = (strlenW( lpBuffersIn->lpcszHeader ) + 1) * sizeof(WCHAR);
+ else
+ size = lpBuffersIn->dwHeadersLength * sizeof(WCHAR);
+
+ req->lpszHeader = HeapAlloc( GetProcessHeap(), 0, size );
+ memcpy( req->lpszHeader, lpBuffersIn->lpcszHeader, size );
+ }
+ else req->lpszHeader = NULL;
+
+ req->dwHeaderLength = size / sizeof(WCHAR);
+ req->lpOptional = lpBuffersIn->lpvBuffer;
+ req->dwOptionalLength = lpBuffersIn->dwBufferLength;
+ req->dwContentLength = lpBuffersIn->dwBufferTotal;
+ }
+ else
+ {
+ req->lpszHeader = NULL;
+ req->dwHeaderLength = 0;
+ req->lpOptional = NULL;
+ req->dwOptionalLength = 0;
+ req->dwContentLength = 0;
+ }
+
+ req->bEndRequest = FALSE;
+
+ INTERNET_AsyncCall(&workRequest);
+ /*
+ * This is from windows.
+ */
+ res = ERROR_IO_PENDING;
+ }
+ else
+ {
+ if (lpBuffersIn)
+ res = HTTP_HttpSendRequestW(lpwhr, lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
+ lpBuffersIn->lpvBuffer, lpBuffersIn->dwBufferLength,
+ lpBuffersIn->dwBufferTotal, FALSE);
+ else
+ res = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, FALSE);
+ }
+
+lend:
+ if ( lpwhr )
+ WININET_Release( &lpwhr->hdr );
+
+ TRACE("<---\n");
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * HttpSendRequestW (WININET.@)
+ *
+ * Sends the specified request to the HTTP server
+ *
+ * RETURNS
+ * TRUE on success
+ * FALSE on failure
+ *
+ */
+BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
+ DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
+{
+ http_request_t *lpwhr;
+ http_session_t *lpwhs = NULL;
+ appinfo_t *hIC = NULL;
+ DWORD res = ERROR_SUCCESS;
+
+ TRACE("%p, %s, %i, %p, %i)\n", hHttpRequest,
+ debugstr_wn(lpszHeaders, dwHeaderLength), dwHeaderLength, lpOptional, dwOptionalLength);
+
+ lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
+ if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ lpwhs = lpwhr->lpHttpSession;
+ if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ hIC = lpwhs->lpAppInfo;
+ if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ WORKREQUEST workRequest;
+ struct WORKREQ_HTTPSENDREQUESTW *req;
+
+ workRequest.asyncproc = AsyncHttpSendRequestProc;
+ workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
+ req = &workRequest.u.HttpSendRequestW;
+ if (lpszHeaders)
+ {
+ DWORD size;
+
+ if (dwHeaderLength == ~0u) size = (strlenW(lpszHeaders) + 1) * sizeof(WCHAR);
+ else size = dwHeaderLength * sizeof(WCHAR);
+
+ req->lpszHeader = HeapAlloc(GetProcessHeap(), 0, size);
+ memcpy(req->lpszHeader, lpszHeaders, size);
+ }
+ else
+ req->lpszHeader = 0;
+ req->dwHeaderLength = dwHeaderLength;
+ req->lpOptional = lpOptional;
+ req->dwOptionalLength = dwOptionalLength;
+ req->dwContentLength = dwOptionalLength;
+ req->bEndRequest = TRUE;
+
+ INTERNET_AsyncCall(&workRequest);
+ /*
+ * This is from windows.
+ */
+ res = ERROR_IO_PENDING;
+ }
+ else
+ {
+ res = HTTP_HttpSendRequestW(lpwhr, lpszHeaders,
+ dwHeaderLength, lpOptional, dwOptionalLength,
+ dwOptionalLength, TRUE);
+ }
+lend:
+ if( lpwhr )
+ WININET_Release( &lpwhr->hdr );
+
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * HttpSendRequestA (WININET.@)
+ *
+ * Sends the specified request to the HTTP server
+ *
+ * RETURNS
+ * TRUE on success
+ * FALSE on failure
+ *
+ */
+BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
+ DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
+{
+ BOOL result;
+ LPWSTR szHeaders=NULL;
+ DWORD nLen=dwHeaderLength;
+ if(lpszHeaders!=NULL)
+ {
+ nLen=MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,NULL,0);
+ szHeaders=HeapAlloc(GetProcessHeap(),0,nLen*sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,szHeaders,nLen);
+ }
+ result=HttpSendRequestW(hHttpRequest, szHeaders, nLen, lpOptional, dwOptionalLength);
+ HeapFree(GetProcessHeap(),0,szHeaders);
+ return result;
}
/***********************************************************************
@@ -3447,9 +4130,9 @@ lend:
* Deallocate session handle
*
*/
-static void HTTPSESSION_Destroy(WININETHANDLEHEADER *hdr)
+static void HTTPSESSION_Destroy(object_header_t *hdr)
{
- LPWININETHTTPSESSIONW lpwhs = (LPWININETHTTPSESSIONW) hdr;
+ http_session_t *lpwhs = (http_session_t*) hdr;
TRACE("%p\n", lpwhs);
@@ -3462,7 +4145,7 @@ static void HTTPSESSION_Destroy(WININETHANDLEHEADER *hdr)
HeapFree(GetProcessHeap(), 0, lpwhs);
}
-static DWORD HTTPSESSION_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
+static DWORD HTTPSESSION_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
{
switch(option) {
case INTERNET_OPTION_HANDLE_TYPE:
@@ -3479,11 +4162,34 @@ static DWORD HTTPSESSION_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, voi
return INET_QueryOption(option, buffer, size, unicode);
}
-static const HANDLEHEADERVtbl HTTPSESSIONVtbl = {
+static DWORD HTTPSESSION_SetOption(object_header_t *hdr, DWORD option, void *buffer, DWORD size)
+{
+ http_session_t *ses = (http_session_t*)hdr;
+
+ switch(option) {
+ case INTERNET_OPTION_USERNAME:
+ {
+ HeapFree(GetProcessHeap(), 0, ses->lpszUserName);
+ if (!(ses->lpszUserName = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
+ return ERROR_SUCCESS;
+ }
+ case INTERNET_OPTION_PASSWORD:
+ {
+ HeapFree(GetProcessHeap(), 0, ses->lpszPassword);
+ if (!(ses->lpszPassword = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
+ return ERROR_SUCCESS;
+ }
+ default: break;
+ }
+
+ return ERROR_INTERNET_INVALID_OPTION;
+}
+
+static const object_vtbl_t HTTPSESSIONVtbl = {
HTTPSESSION_Destroy,
NULL,
HTTPSESSION_QueryOption,
- NULL,
+ HTTPSESSION_SetOption,
NULL,
NULL,
NULL,
@@ -3502,30 +4208,25 @@ static const HANDLEHEADERVtbl HTTPSESSIONVtbl = {
* NULL on failure
*
*/
-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 *hIC, LPCWSTR lpszServerName,
+ INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
+ LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext,
+ DWORD dwInternalFlags, HINTERNET *ret)
{
- LPWININETHTTPSESSIONW lpwhs = NULL;
+ http_session_t *lpwhs = NULL;
HINTERNET handle = NULL;
+ DWORD res = ERROR_SUCCESS;
TRACE("-->\n");
if (!lpszServerName || !lpszServerName[0])
- {
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
- goto lerror;
- }
+ return ERROR_INVALID_PARAMETER;
assert( hIC->hdr.htype == WH_HINIT );
- lpwhs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPSESSIONW));
- if (NULL == lpwhs)
- {
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
- goto lerror;
- }
+ lpwhs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(http_session_t));
+ if (!lpwhs)
+ return ERROR_OUTOFMEMORY;
/*
* According to my tests. The name is not resolved until a request is sent
@@ -3547,8 +4248,8 @@ HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
if (NULL == handle)
{
ERR("Failed to alloc handle\n");
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
- goto lerror;
+ res = ERROR_OUTOFMEMORY;
+ goto lerror;
}
if(hIC->lpszProxy && hIC->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
@@ -3559,13 +4260,13 @@ HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
}
if (lpszServerName && lpszServerName[0])
{
- lpwhs->lpszServerName = WININET_strdupW(lpszServerName);
- lpwhs->lpszHostName = WININET_strdupW(lpszServerName);
+ lpwhs->lpszServerName = heap_strdupW(lpszServerName);
+ lpwhs->lpszHostName = heap_strdupW(lpszServerName);
}
if (lpszUserName && lpszUserName[0])
- lpwhs->lpszUserName = WININET_strdupW(lpszUserName);
+ lpwhs->lpszUserName = heap_strdupW(lpszUserName);
if (lpszPassword && lpszPassword[0])
- lpwhs->lpszPassword = WININET_strdupW(lpszPassword);
+ lpwhs->lpszPassword = heap_strdupW(lpszPassword);
lpwhs->nServerPort = nServerPort;
lpwhs->nHostPort = nServerPort;
@@ -3587,7 +4288,10 @@ lerror:
*/
TRACE("%p --> %p (%p)\n", hIC, handle, lpwhs);
- return handle;
+
+ if(res == ERROR_SUCCESS)
+ *ret = handle;
+ return res;
}
@@ -3601,48 +4305,58 @@ lerror:
* TRUE on success
* FALSE on failure
*/
-static BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr)
+static DWORD HTTP_OpenConnection(http_request_t *lpwhr)
{
- BOOL bSuccess = FALSE;
- LPWININETHTTPSESSIONW lpwhs;
- LPWININETAPPINFOW hIC = NULL;
- char szaddr[32];
+ http_session_t *lpwhs;
+ appinfo_t *hIC = NULL;
+ char szaddr[INET6_ADDRSTRLEN];
+ const void *addr;
+ DWORD res = ERROR_SUCCESS;
TRACE("-->\n");
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
+ if (lpwhr->hdr.htype != WH_HHTTPREQ)
{
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+ res = ERROR_INVALID_PARAMETER;
goto lend;
}
if (NETCON_connected(&lpwhr->netConnection))
- {
- bSuccess = TRUE;
goto lend;
- }
- if (!HTTP_ResolveName(lpwhr)) goto lend;
+ if ((res = HTTP_ResolveName(lpwhr)) != ERROR_SUCCESS) goto lend;
lpwhs = lpwhr->lpHttpSession;
hIC = lpwhs->lpAppInfo;
- inet_ntop(lpwhs->socketAddress.sin_family, &lpwhs->socketAddress.sin_addr,
- szaddr, sizeof(szaddr));
+ switch (lpwhs->socketAddress.ss_family)
+ {
+ case AF_INET:
+ addr = &((struct sockaddr_in *)&lpwhs->socketAddress)->sin_addr;
+ break;
+ case AF_INET6:
+ addr = &((struct sockaddr_in6 *)&lpwhs->socketAddress)->sin6_addr;
+ break;
+ default:
+ WARN("unsupported family %d\n", lpwhs->socketAddress.ss_family);
+ return ERROR_INTERNET_NAME_NOT_RESOLVED;
+ }
+ inet_ntop(lpwhs->socketAddress.ss_family, addr, szaddr, sizeof(szaddr));
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_CONNECTING_TO_SERVER,
szaddr,
strlen(szaddr)+1);
- if (!NETCON_create(&lpwhr->netConnection, lpwhs->socketAddress.sin_family,
- SOCK_STREAM, 0))
+ res = NETCON_create(&lpwhr->netConnection, lpwhs->socketAddress.ss_family, SOCK_STREAM, 0);
+ if (res != ERROR_SUCCESS)
{
- WARN("Socket creation failed: %u\n", INTERNET_GetLastError());
+ WARN("Socket creation failed: %u\n", res);
goto lend;
}
- if (!NETCON_connect(&lpwhr->netConnection, (struct sockaddr *)&lpwhs->socketAddress,
- sizeof(lpwhs->socketAddress)))
+ res = NETCON_connect(&lpwhr->netConnection, (struct sockaddr *)&lpwhs->socketAddress,
+ lpwhs->sa_len);
+ if(res != ERROR_SUCCESS)
goto lend;
if (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE)
@@ -3653,10 +4367,11 @@ static BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr)
* behaviour to be more correct and to not cause any incompatibilities
* because using a secure connection through a proxy server is a rare
* case that would be hard for anyone to depend on */
- if (hIC->lpszProxy && !HTTP_SecureProxyConnect(lpwhr))
+ if (hIC->lpszProxy && (res = HTTP_SecureProxyConnect(lpwhr)) != ERROR_SUCCESS)
goto lend;
- if (!NETCON_secure_connect(&lpwhr->netConnection, lpwhs->lpszHostName))
+ res = NETCON_secure_connect(&lpwhr->netConnection, lpwhs->lpszHostName);
+ if(res != ERROR_SUCCESS)
{
WARN("Couldn't connect securely to host\n");
goto lend;
@@ -3667,11 +4382,12 @@ static BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr)
INTERNET_STATUS_CONNECTED_TO_SERVER,
szaddr, strlen(szaddr)+1);
- bSuccess = TRUE;
-
lend:
- TRACE("%d <--\n", bSuccess);
- return bSuccess;
+ lpwhr->read_pos = lpwhr->read_size = 0;
+ lpwhr->read_chunked = FALSE;
+
+ TRACE("%d <--\n", res);
+ return res;
}
@@ -3680,7 +4396,7 @@ lend:
*
* clear out any old response headers
*/
-static void HTTP_clear_response_headers( LPWININETHTTPREQW lpwhr )
+static void HTTP_clear_response_headers( http_request_t *lpwhr )
{
DWORD i;
@@ -3707,20 +4423,20 @@ static void HTTP_clear_response_headers( LPWININETHTTPREQW lpwhr )
* TRUE on success
* FALSE on error
*/
-static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear)
+static INT HTTP_GetResponseHeaders(http_request_t *lpwhr, BOOL clear)
{
INT cbreaks = 0;
WCHAR buffer[MAX_REPLY_LEN];
DWORD buflen = MAX_REPLY_LEN;
BOOL bSuccess = FALSE;
INT rc = 0;
- static const WCHAR szCrLf[] = {'\r','\n',0};
- static const WCHAR szHundred[] = {'1','0','0',0};
char bufferA[MAX_REPLY_LEN];
- LPWSTR status_code, status_text;
+ LPWSTR status_code = NULL, status_text = NULL;
DWORD cchMaxRawHeaders = 1024;
- LPWSTR lpszRawHeaders = HeapAlloc(GetProcessHeap(), 0, (cchMaxRawHeaders+1)*sizeof(WCHAR));
+ LPWSTR lpszRawHeaders = NULL;
+ LPWSTR temp;
DWORD cchRawHeaders = 0;
+ BOOL codeHundred = FALSE;
TRACE("-->\n");
@@ -3731,36 +4447,52 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear)
goto lend;
do {
- /*
- * HACK peek at the buffer
- */
- buflen = MAX_REPLY_LEN;
- NETCON_recv(&lpwhr->netConnection, buffer, buflen, MSG_PEEK, &rc);
-
+ static const WCHAR szHundred[] = {'1','0','0',0};
/*
* We should first receive 'HTTP/1.x nnn OK' where nnn is the status code.
*/
- memset(buffer, 0, MAX_REPLY_LEN);
- if (!NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen))
+ buflen = MAX_REPLY_LEN;
+ if (!read_line(lpwhr, bufferA, &buflen))
goto lend;
+ rc += buflen;
MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
+ /* check is this a status code line? */
+ if (!strncmpW(buffer, g_szHttp1_0, 4))
+ {
+ /* split the version from the status code */
+ status_code = strchrW( buffer, ' ' );
+ if( !status_code )
+ goto lend;
+ *status_code++=0;
- /* split the version from the status code */
- status_code = strchrW( buffer, ' ' );
- if( !status_code )
+ /* split the status code from the status text */
+ status_text = strchrW( status_code, ' ' );
+ if( !status_text )
+ goto lend;
+ *status_text++=0;
+
+ TRACE("version [%s] status code [%s] status text [%s]\n",
+ debugstr_w(buffer), debugstr_w(status_code), debugstr_w(status_text) );
+
+ codeHundred = (!strcmpW(status_code, szHundred));
+ }
+ else if (!codeHundred)
+ {
+ WARN("No status line at head of response (%s)\n", debugstr_w(buffer));
+
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszVersion);
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszStatusText);
+
+ lpwhr->lpszVersion = heap_strdupW(g_szHttp1_0);
+ lpwhr->lpszStatusText = heap_strdupW(szOK);
+
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders);
+ lpwhr->lpszRawHeaders = heap_strdupW(szDefaultHeader);
+
+ bSuccess = TRUE;
goto lend;
- *status_code++=0;
-
- /* split the status code from the status text */
- status_text = strchrW( status_code, ' ' );
- if( !status_text )
- goto lend;
- *status_text++=0;
-
- TRACE("version [%s] status code [%s] status text [%s]\n",
- debugstr_w(buffer), debugstr_w(status_code), debugstr_w(status_text) );
-
- } while (!strcmpW(status_code, szHundred)); /* ignore "100 Continue" responses */
+ }
+ } while (codeHundred);
/* Add status code */
HTTP_ProcessHeader(lpwhr, szStatus, status_code,
@@ -3769,19 +4501,22 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear)
HeapFree(GetProcessHeap(),0,lpwhr->lpszVersion);
HeapFree(GetProcessHeap(),0,lpwhr->lpszStatusText);
- lpwhr->lpszVersion= WININET_strdupW(buffer);
- lpwhr->lpszStatusText = WININET_strdupW(status_text);
+ lpwhr->lpszVersion = heap_strdupW(buffer);
+ lpwhr->lpszStatusText = heap_strdupW(status_text);
/* Restore the spaces */
*(status_code-1) = ' ';
*(status_text-1) = ' ';
/* regenerate raw headers */
+ lpszRawHeaders = HeapAlloc(GetProcessHeap(), 0, (cchMaxRawHeaders + 1) * sizeof(WCHAR));
+ if (!lpszRawHeaders) goto lend;
+
while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
- {
cchMaxRawHeaders *= 2;
- lpszRawHeaders = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
- }
+ temp = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
+ if (temp == NULL) goto lend;
+ lpszRawHeaders = temp;
memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
cchRawHeaders += (buflen-1);
memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
@@ -3792,33 +4527,35 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear)
do
{
buflen = MAX_REPLY_LEN;
- if (NETCON_getNextLine(&lpwhr->netConnection, bufferA, &buflen))
+ if (read_line(lpwhr, bufferA, &buflen))
{
LPWSTR * pFieldAndValue;
TRACE("got line %s, now interpreting\n", debugstr_a(bufferA));
+
+ if (!bufferA[0]) break;
MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
- while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
- {
- cchMaxRawHeaders *= 2;
- lpszRawHeaders = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
- }
- memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
- cchRawHeaders += (buflen-1);
- memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
- cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
- lpszRawHeaders[cchRawHeaders] = '\0';
-
pFieldAndValue = HTTP_InterpretHttpHeader(buffer);
- if (!pFieldAndValue)
- break;
+ if (pFieldAndValue)
+ {
+ while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
+ cchMaxRawHeaders *= 2;
+ temp = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
+ if (temp == NULL) goto lend;
+ lpszRawHeaders = temp;
+ memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
+ cchRawHeaders += (buflen-1);
+ memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
+ cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
+ lpszRawHeaders[cchRawHeaders] = '\0';
- HTTP_ProcessHeader(lpwhr, pFieldAndValue[0], pFieldAndValue[1],
- HTTP_ADDREQ_FLAG_ADD );
+ HTTP_ProcessHeader(lpwhr, pFieldAndValue[0], pFieldAndValue[1],
+ HTTP_ADDREQ_FLAG_ADD );
- HTTP_FreeTokens(pFieldAndValue);
- }
+ HTTP_FreeTokens(pFieldAndValue);
+ }
+ }
else
{
cbreaks++;
@@ -3827,6 +4564,19 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr, BOOL clear)
}
}while(1);
+ /* make sure the response header is terminated with an empty line. Some apps really
+ truly care about that empty line being there for some reason. Just add it to the
+ header. */
+ if (cchRawHeaders + strlenW(szCrLf) > cchMaxRawHeaders)
+ {
+ cchMaxRawHeaders = cchRawHeaders + strlenW(szCrLf);
+ temp = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders + 1) * sizeof(WCHAR));
+ if (temp == NULL) goto lend;
+ lpszRawHeaders = temp;
+ }
+
+ memcpy(&lpszRawHeaders[cchRawHeaders], szCrLf, sizeof(szCrLf));
+
HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders);
lpwhr->lpszRawHeaders = lpszRawHeaders;
TRACE("raw headers: %s\n", debugstr_w(lpszRawHeaders));
@@ -3844,27 +4594,6 @@ lend:
}
}
-
-static void strip_spaces(LPWSTR start)
-{
- LPWSTR str = start;
- LPWSTR end;
-
- while (*str == ' ' && *str != '\0')
- str++;
-
- if (str != start)
- memmove(start, str, sizeof(WCHAR) * (strlenW(str) + 1));
-
- end = start + strlenW(start) - 1;
- while (end >= start && *end == ' ')
- {
- *end = '\0';
- end--;
- }
-}
-
-
/***********************************************************************
* HTTP_InterpretHttpHeader (internal)
*
@@ -3929,12 +4658,12 @@ static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer)
#define COALESCEFLAGS (HTTP_ADDHDR_FLAG_COALESCE|HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA|HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
-static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR value, DWORD dwModifier)
+static DWORD HTTP_ProcessHeader(http_request_t *lpwhr, LPCWSTR field, LPCWSTR value, DWORD dwModifier)
{
LPHTTPHEADERW lphttpHdr = NULL;
- BOOL bSuccess = FALSE;
INT index = -1;
BOOL request_only = dwModifier & HTTP_ADDHDR_FLAG_REQ;
+ DWORD res = ERROR_HTTP_INVALID_HEADER;
TRACE("--> %s: %s - 0x%08x\n", debugstr_w(field), debugstr_w(value), dwModifier);
@@ -3950,9 +4679,7 @@ static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR v
if (index >= 0)
{
if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
- {
- return FALSE;
- }
+ return ERROR_HTTP_INVALID_HEADER;
lphttpHdr = &lpwhr->pCustHeaders[index];
}
else if (value)
@@ -3969,7 +4696,7 @@ static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR v
return HTTP_InsertCustomHeader(lpwhr, &hdr);
}
/* no value to delete */
- else return TRUE;
+ else return ERROR_SUCCESS;
if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
lphttpHdr->wFlags |= HDR_ISREQUEST;
@@ -3994,7 +4721,7 @@ static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR v
return HTTP_InsertCustomHeader(lpwhr, &hdr);
}
- return TRUE;
+ return ERROR_SUCCESS;
}
else if (dwModifier & COALESCEFLAGS)
{
@@ -4032,16 +4759,16 @@ static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR v
memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
lphttpHdr->lpszValue[len] = '\0';
- bSuccess = TRUE;
+ res = ERROR_SUCCESS;
}
else
{
WARN("HeapReAlloc (%d bytes) failed\n",len+1);
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+ res = ERROR_OUTOFMEMORY;
}
}
- TRACE("<-- %d\n",bSuccess);
- return bSuccess;
+ TRACE("<-- %d\n", res);
+ return res;
}
@@ -4051,30 +4778,12 @@ static BOOL HTTP_ProcessHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field, LPCWSTR v
* Called when all content from server has been read by client.
*
*/
-BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr)
+static BOOL HTTP_FinishedReading(http_request_t *lpwhr)
{
- WCHAR szVersion[10];
- WCHAR szConnectionResponse[20];
- DWORD dwBufferSize = sizeof(szVersion);
- BOOL keepalive = FALSE;
+ BOOL keepalive = HTTP_KeepAlive(lpwhr);
TRACE("\n");
- /* as per RFC 2068, S8.1.2.1, if the client is HTTP/1.1 then assume that
- * the connection is keep-alive by default */
- if (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion,
- &dwBufferSize, NULL) ||
- strcmpiW(szVersion, g_szHttp1_1))
- {
- keepalive = TRUE;
- }
-
- dwBufferSize = sizeof(szConnectionResponse);
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_PROXY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) ||
- HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL))
- {
- keepalive = !strcmpiW(szConnectionResponse, szKeepAlive);
- }
if (!keepalive)
{
@@ -4093,12 +4802,12 @@ BOOL HTTP_FinishedReading(LPWININETHTTPREQW lpwhr)
* Return index of custom header from header array
*
*/
-static INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField,
+static INT HTTP_GetCustomHeaderIndex(http_request_t *lpwhr, LPCWSTR lpszField,
int requested_index, BOOL request_only)
{
DWORD index;
- TRACE("%s\n", debugstr_w(lpszField));
+ TRACE("%s, %d, %d\n", debugstr_w(lpszField), requested_index, request_only);
for (index = 0; index < lpwhr->nCustHeaders; index++)
{
@@ -4130,11 +4839,10 @@ static INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField,
* Insert header into array
*
*/
-static BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr)
+static DWORD HTTP_InsertCustomHeader(http_request_t *lpwhr, LPHTTPHEADERW lpHdr)
{
INT count;
LPHTTPHEADERW lph = NULL;
- BOOL r = FALSE;
TRACE("--> %s: %s\n", debugstr_w(lpHdr->lpszField), debugstr_w(lpHdr->lpszValue));
count = lpwhr->nCustHeaders + 1;
@@ -4143,22 +4851,17 @@ static BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr
else
lph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HTTPHEADERW) * count);
- if (NULL != lph)
- {
- lpwhr->pCustHeaders = lph;
- lpwhr->pCustHeaders[count-1].lpszField = WININET_strdupW(lpHdr->lpszField);
- lpwhr->pCustHeaders[count-1].lpszValue = WININET_strdupW(lpHdr->lpszValue);
- lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags;
- lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount;
- lpwhr->nCustHeaders++;
- r = TRUE;
- }
- else
- {
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
- }
+ if (!lph)
+ return ERROR_OUTOFMEMORY;
- return r;
+ lpwhr->pCustHeaders = lph;
+ lpwhr->pCustHeaders[count-1].lpszField = heap_strdupW(lpHdr->lpszField);
+ lpwhr->pCustHeaders[count-1].lpszValue = heap_strdupW(lpHdr->lpszValue);
+ lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags;
+ lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount;
+ lpwhr->nCustHeaders++;
+
+ return ERROR_SUCCESS;
}
@@ -4168,7 +4871,7 @@ static BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr
* Delete header from array
* If this function is called, the indexs may change.
*/
-static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index)
+static BOOL HTTP_DeleteCustomHeader(http_request_t *lpwhr, DWORD index)
{
if( lpwhr->nCustHeaders <= 0 )
return FALSE;
@@ -4193,13 +4896,13 @@ static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index)
* Verify the given header is not invalid for the given http request
*
*/
-static BOOL HTTP_VerifyValidHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field)
+static BOOL HTTP_VerifyValidHeader(http_request_t *lpwhr, LPCWSTR field)
{
/* Accept-Encoding is stripped from HTTP/1.0 requests. It is invalid */
if (!strcmpW(lpwhr->lpszVersion, g_szHttp1_0) && !strcmpiW(field, szAccept_Encoding))
- return FALSE;
+ return ERROR_HTTP_INVALID_HEADER;
- return TRUE;
+ return ERROR_SUCCESS;
}
/***********************************************************************
diff --git a/dll/win32/wininet/internet.c b/dll/win32/wininet/internet.c
index bad795ddbd4..45b6aa791f3 100644
--- a/dll/win32/wininet/internet.c
+++ b/dll/win32/wininet/internet.c
@@ -31,6 +31,10 @@
#define MAXHOSTNAME 100 /* from http.c */
+#if defined(__MINGW32__) || defined (_MSC_VER)
+#include
+#endif
+
#include
#include
#include
@@ -97,13 +101,27 @@ static CRITICAL_SECTION_DEBUG WININET_cs_debug =
};
static CRITICAL_SECTION WININET_cs = { &WININET_cs_debug, -1, 0, 0, 0, 0 };
-static LPWININETHANDLEHEADER *WININET_Handles;
+static object_header_t **WININET_Handles;
static UINT WININET_dwNextHandle;
static UINT WININET_dwMaxHandles;
-HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info )
+typedef struct
{
- LPWININETHANDLEHEADER *p;
+ DWORD dwProxyEnabled;
+ LPWSTR lpszProxyServer;
+ LPWSTR lpszProxyBypass;
+} proxyinfo_t;
+
+static const WCHAR szInternetSettings[] =
+ { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
+ 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+ 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s',0 };
+static const WCHAR szProxyServer[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 };
+static const WCHAR szProxyEnable[] = { 'P','r','o','x','y','E','n','a','b','l','e', 0 };
+
+HINTERNET WININET_AllocHandle( object_header_t *info )
+{
+ object_header_t **p;
UINT handle = 0, num;
list_init( &info->children );
@@ -113,7 +131,7 @@ HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info )
{
num = HANDLE_CHUNK_SIZE;
p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof (UINT)* num);
+ sizeof (*WININET_Handles)* num);
if( !p )
goto end;
WININET_Handles = p;
@@ -123,7 +141,7 @@ HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info )
{
num = WININET_dwMaxHandles + HANDLE_CHUNK_SIZE;
p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- WININET_Handles, sizeof (UINT)* num);
+ WININET_Handles, sizeof (*WININET_Handles)* num);
if( !p )
goto end;
WININET_Handles = p;
@@ -145,16 +163,16 @@ end:
return info->hInternet = (HINTERNET) (handle+1);
}
-LPWININETHANDLEHEADER WININET_AddRef( LPWININETHANDLEHEADER info )
+object_header_t *WININET_AddRef( object_header_t *info )
{
ULONG refs = InterlockedIncrement(&info->refs);
TRACE("%p -> refcount = %d\n", info, refs );
return info;
}
-LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet )
+object_header_t *WININET_GetObject( HINTERNET hinternet )
{
- LPWININETHANDLEHEADER info = NULL;
+ object_header_t *info = NULL;
UINT handle = (UINT) hinternet;
EnterCriticalSection( &WININET_cs );
@@ -170,7 +188,7 @@ LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet )
return info;
}
-BOOL WININET_Release( LPWININETHANDLEHEADER info )
+BOOL WININET_Release( object_header_t *info )
{
ULONG refs = InterlockedDecrement(&info->refs);
TRACE( "object %p refcount = %d\n", info, refs );
@@ -182,7 +200,8 @@ BOOL WININET_Release( LPWININETHANDLEHEADER info )
info->vtbl->CloseConnection( info );
}
/* Don't send a callback if this is a session handle created with InternetOpenUrl */
- if (info->htype != WH_HHTTPSESSION || !(info->dwInternalFlags & INET_OPENURL))
+ if ((info->htype != WH_HHTTPSESSION && info->htype != WH_HFTPSESSION)
+ || !(info->dwInternalFlags & INET_OPENURL))
{
INTERNET_SendCallback(info, info->dwContext,
INTERNET_STATUS_HANDLE_CLOSING, &info->hInternet,
@@ -200,7 +219,7 @@ BOOL WININET_FreeHandle( HINTERNET hinternet )
{
BOOL ret = FALSE;
UINT handle = (UINT) hinternet;
- LPWININETHANDLEHEADER info = NULL, child, next;
+ object_header_t *info = NULL, *child, *next;
EnterCriticalSection( &WININET_cs );
@@ -224,7 +243,7 @@ BOOL WININET_FreeHandle( HINTERNET hinternet )
if( info )
{
/* Free all children as native does */
- LIST_FOR_EACH_ENTRY_SAFE( child, next, &info->children, WININETHANDLEHEADER, entry )
+ LIST_FOR_EACH_ENTRY_SAFE( child, next, &info->children, object_header_t, entry )
{
TRACE( "freeing child handle %d for parent handle %d\n",
(UINT)child->hInternet, handle+1);
@@ -285,6 +304,8 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
case DLL_PROCESS_DETACH:
+ NETCON_unload();
+
URLCacheContainers_DeleteAll();
if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
@@ -298,6 +319,48 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return TRUE;
}
+/***********************************************************************
+ * INTERNET_SaveProxySettings
+ *
+ * Stores the proxy settings given by lpwai into the registry
+ *
+ * RETURNS
+ * ERROR_SUCCESS if no error, or error code on fail
+ */
+static LONG INTERNET_SaveProxySettings( proxyinfo_t *lpwpi )
+{
+ HKEY key;
+ LONG ret;
+
+ if ((ret = RegOpenKeyW( HKEY_CURRENT_USER, szInternetSettings, &key )))
+ return ret;
+
+ if ((ret = RegSetValueExW( key, szProxyEnable, 0, REG_DWORD, (BYTE*)&lpwpi->dwProxyEnabled, sizeof(DWORD))))
+ {
+ RegCloseKey( key );
+ return ret;
+ }
+
+ if (lpwpi->lpszProxyServer)
+ {
+ if ((ret = RegSetValueExW( key, szProxyServer, 0, REG_SZ, (BYTE*)lpwpi->lpszProxyServer, sizeof(WCHAR) * (lstrlenW(lpwpi->lpszProxyServer) + 1))))
+ {
+ RegCloseKey( key );
+ return ret;
+ }
+ }
+ else
+ {
+ if ((ret = RegDeleteValueW( key, szProxyServer )))
+ {
+ RegCloseKey( key );
+ return ret;
+ }
+ }
+
+ RegCloseKey(key);
+ return ERROR_SUCCESS;
+}
/***********************************************************************
* InternetInitializeAutoProxyDll (WININET.@)
@@ -314,7 +377,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
BOOL WINAPI InternetInitializeAutoProxyDll(DWORD dwReserved)
{
FIXME("STUB\n");
- INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
@@ -331,37 +394,49 @@ BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl,
DWORD dwAutoProxyUrlLength, DWORD dwDetectFlags)
{
FIXME("STUB\n");
- INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
+static void FreeProxyInfo( proxyinfo_t *lpwpi )
+{
+ HeapFree(GetProcessHeap(), 0, lpwpi->lpszProxyServer);
+ HeapFree(GetProcessHeap(), 0, lpwpi->lpszProxyBypass);
+}
/***********************************************************************
- * INTERNET_ConfigureProxy
+ * INTERNET_LoadProxySettings
+ *
+ * Loads proxy information from the registry or environment into lpwpi.
+ *
+ * The caller should call FreeProxyInfo when done with lpwpi.
*
* FIXME:
* The proxy may be specified in the form 'http=proxy.my.org'
* Presumably that means there can be ftp=ftpproxy.my.org too.
*/
-static BOOL INTERNET_ConfigureProxy( LPWININETAPPINFOW lpwai )
+static LONG INTERNET_LoadProxySettings( proxyinfo_t *lpwpi )
{
HKEY key;
- DWORD type, len, enabled = 0;
+ DWORD type, len;
LPCSTR envproxy;
- static const WCHAR szInternetSettings[] =
- { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
- 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
- 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s',0 };
- static const WCHAR szProxyServer[] = { 'P','r','o','x','y','S','e','r','v','e','r', 0 };
- static const WCHAR szProxyEnable[] = { 'P','r','o','x','y','E','n','a','b','l','e', 0 };
+ LONG ret;
- if (RegOpenKeyW( HKEY_CURRENT_USER, szInternetSettings, &key )) return FALSE;
+ if ((ret = RegOpenKeyW( HKEY_CURRENT_USER, szInternetSettings, &key )))
+ return ret;
- len = sizeof enabled;
- if (RegQueryValueExW( key, szProxyEnable, NULL, &type, (BYTE *)&enabled, &len ) || type != REG_DWORD)
- RegSetValueExW( key, szProxyEnable, 0, REG_DWORD, (BYTE *)&enabled, sizeof(REG_DWORD) );
+ len = sizeof(DWORD);
+ if (RegQueryValueExW( key, szProxyEnable, NULL, &type, (BYTE *)&lpwpi->dwProxyEnabled, &len ) || type != REG_DWORD)
+ {
+ lpwpi->dwProxyEnabled = 0;
+ if((ret = RegSetValueExW( key, szProxyEnable, 0, REG_DWORD, (BYTE *)&lpwpi->dwProxyEnabled, sizeof(DWORD) )))
+ {
+ RegCloseKey( key );
+ return ret;
+ }
+ }
- if (enabled)
+ if (!(envproxy = getenv( "http_proxy" )) || lpwpi->dwProxyEnabled)
{
TRACE("Proxy is enabled.\n");
@@ -374,7 +449,7 @@ static BOOL INTERNET_ConfigureProxy( LPWININETAPPINFOW lpwai )
if (!(szProxy = HeapAlloc( GetProcessHeap(), 0, len )))
{
RegCloseKey( key );
- return FALSE;
+ return ERROR_OUTOFMEMORY;
}
RegQueryValueExW( key, szProxyServer, NULL, &type, (BYTE*)szProxy, &len );
@@ -388,32 +463,56 @@ static BOOL INTERNET_ConfigureProxy( LPWININETAPPINFOW lpwai )
p = strchrW( szProxy, ' ' );
if (p) *p = 0;
- lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY;
- lpwai->lpszProxy = szProxy;
+ lpwpi->lpszProxyServer = szProxy;
- TRACE("http proxy = %s\n", debugstr_w(lpwai->lpszProxy));
+ TRACE("http proxy = %s\n", debugstr_w(lpwpi->lpszProxyServer));
}
else
- ERR("Couldn't read proxy server settings from registry.\n");
+ {
+ TRACE("No proxy server settings in registry.\n");
+ lpwpi->lpszProxyServer = NULL;
+ }
}
- else if ((envproxy = getenv( "http_proxy" )))
+ else if (envproxy)
{
WCHAR *envproxyW;
len = MultiByteToWideChar( CP_UNIXCP, 0, envproxy, -1, NULL, 0 );
- if (!(envproxyW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR)))) return FALSE;
+ if (!(envproxyW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR))))
+ return ERROR_OUTOFMEMORY;
MultiByteToWideChar( CP_UNIXCP, 0, envproxy, -1, envproxyW, len );
- lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY;
- lpwai->lpszProxy = envproxyW;
+ lpwpi->dwProxyEnabled = 1;
+ lpwpi->lpszProxyServer = envproxyW;
- TRACE("http proxy (from environment) = %s\n", debugstr_w(lpwai->lpszProxy));
- enabled = 1;
+ TRACE("http proxy (from environment) = %s\n", debugstr_w(lpwpi->lpszProxyServer));
}
- if (!enabled) TRACE("Proxy is not enabled.\n");
-
RegCloseKey( key );
- return (enabled > 0);
+
+ lpwpi->lpszProxyBypass = NULL;
+
+ return ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * INTERNET_ConfigureProxy
+ */
+static BOOL INTERNET_ConfigureProxy( appinfo_t *lpwai )
+{
+ proxyinfo_t wpi;
+
+ if (INTERNET_LoadProxySettings( &wpi ))
+ return FALSE;
+
+ if (wpi.dwProxyEnabled)
+ {
+ lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY;
+ lpwai->lpszProxy = wpi.lpszProxyServer;
+ return TRUE;
+ }
+
+ lpwai->dwAccessType = INTERNET_OPEN_TYPE_DIRECT;
+ return FALSE;
}
/***********************************************************************
@@ -459,8 +558,8 @@ static void dump_INTERNET_FLAGS(DWORD dwFlags)
FE(INTERNET_FLAG_TRANSFER_BINARY)
};
#undef FE
- int i;
-
+ unsigned int i;
+
for (i = 0; i < (sizeof(flag) / sizeof(flag[0])); i++) {
if (flag[i].val & dwFlags) {
TRACE(" %s", flag[i].name);
@@ -479,9 +578,9 @@ static void dump_INTERNET_FLAGS(DWORD dwFlags)
* Close internet handle
*
*/
-static VOID APPINFO_Destroy(WININETHANDLEHEADER *hdr)
+static VOID APPINFO_Destroy(object_header_t *hdr)
{
- LPWININETAPPINFOW lpwai = (LPWININETAPPINFOW) hdr;
+ appinfo_t *lpwai = (appinfo_t*)hdr;
TRACE("%p\n",lpwai);
@@ -493,9 +592,9 @@ static VOID APPINFO_Destroy(WININETHANDLEHEADER *hdr)
HeapFree(GetProcessHeap(), 0, lpwai);
}
-static DWORD APPINFO_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
+static DWORD APPINFO_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
{
- LPWININETAPPINFOW ai = (LPWININETAPPINFOW)hdr;
+ appinfo_t *ai = (appinfo_t*)hdr;
switch(option) {
case INTERNET_OPTION_HANDLE_TYPE:
@@ -516,17 +615,36 @@ static DWORD APPINFO_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b
bufsize = *size;
if (unicode) {
- *size = (strlenW(ai->lpszAgent) + 1) * sizeof(WCHAR);
+ DWORD len = ai->lpszAgent ? strlenW(ai->lpszAgent) : 0;
+
+ *size = (len + 1) * sizeof(WCHAR);
if(!buffer || bufsize < *size)
return ERROR_INSUFFICIENT_BUFFER;
- strcpyW(buffer, ai->lpszAgent);
+ if (ai->lpszAgent)
+ strcpyW(buffer, ai->lpszAgent);
+ else
+ *(WCHAR *)buffer = 0;
+ /* If the buffer is copied, the returned length doesn't include
+ * the NULL terminator.
+ */
+ *size = len * sizeof(WCHAR);
}else {
- *size = WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, NULL, 0, NULL, NULL);
+ if (ai->lpszAgent)
+ *size = WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, NULL, 0, NULL, NULL);
+ else
+ *size = 1;
if(!buffer || bufsize < *size)
return ERROR_INSUFFICIENT_BUFFER;
- WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, buffer, *size, NULL, NULL);
+ if (ai->lpszAgent)
+ WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, buffer, *size, NULL, NULL);
+ else
+ *(char *)buffer = 0;
+ /* If the buffer is copied, the returned length doesn't include
+ * the NULL terminator.
+ */
+ *size -= 1;
}
return ERROR_SUCCESS;
@@ -543,8 +661,10 @@ static DWORD APPINFO_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b
if (ai->lpszProxyBypass)
proxyBypassBytesRequired = (lstrlenW(ai->lpszProxyBypass) + 1) * sizeof(WCHAR);
if (*size < sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired)
- return ERROR_INSUFFICIENT_BUFFER;
-
+ {
+ *size = sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired + proxyBypassBytesRequired;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
proxy = (LPWSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOW));
proxy_bypass = (LPWSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOW) + proxyBytesRequired);
@@ -574,8 +694,10 @@ static DWORD APPINFO_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b
proxyBypassBytesRequired = WideCharToMultiByte(CP_ACP, 0, ai->lpszProxyBypass, -1,
NULL, 0, NULL, NULL);
if (*size < sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired)
+ {
+ *size = sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired + proxyBypassBytesRequired;
return ERROR_INSUFFICIENT_BUFFER;
-
+ }
proxy = (LPSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOA));
proxy_bypass = (LPSTR)((LPBYTE)buffer + sizeof(INTERNET_PROXY_INFOA) + proxyBytesRequired);
@@ -601,7 +723,7 @@ static DWORD APPINFO_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b
return INET_QueryOption(option, buffer, size, unicode);
}
-static const HANDLEHEADERVtbl APPINFOVtbl = {
+static const object_vtbl_t APPINFOVtbl = {
APPINFO_Destroy,
NULL,
APPINFO_QueryOption,
@@ -627,7 +749,7 @@ static const HANDLEHEADERVtbl APPINFOVtbl = {
HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags)
{
- LPWININETAPPINFOW lpwai = NULL;
+ appinfo_t *lpwai = NULL;
HINTERNET handle = NULL;
if (TRACE_ON(wininet)) {
@@ -658,7 +780,7 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
/* Clear any error information */
INTERNET_SetLastError(0);
- lpwai = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETAPPINFOW));
+ lpwai = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(appinfo_t));
if (NULL == lpwai)
{
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
@@ -681,30 +803,12 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR lpszAgent, DWORD dwAccessType,
goto lend;
}
- if (NULL != lpszAgent)
- {
- lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,
- (strlenW(lpszAgent)+1)*sizeof(WCHAR));
- if (lpwai->lpszAgent)
- lstrcpyW( lpwai->lpszAgent, lpszAgent );
- }
+ lpwai->lpszAgent = heap_strdupW(lpszAgent);
if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
INTERNET_ConfigureProxy( lpwai );
- else if (NULL != lpszProxy)
- {
- lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0,
- (strlenW(lpszProxy)+1)*sizeof(WCHAR));
- if (lpwai->lpszProxy)
- lstrcpyW( lpwai->lpszProxy, lpszProxy );
- }
-
- if (NULL != lpszProxyBypass)
- {
- lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0,
- (strlenW(lpszProxyBypass)+1)*sizeof(WCHAR));
- if (lpwai->lpszProxyBypass)
- lstrcpyW( lpwai->lpszProxyBypass, lpszProxyBypass );
- }
+ else
+ lpwai->lpszProxy = heap_strdupW(lpszProxy);
+ lpwai->lpszProxyBypass = heap_strdupW(lpszProxyBypass);
lend:
if( lpwai )
@@ -729,33 +833,15 @@ lend:
HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType,
LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags)
{
- HINTERNET rc = NULL;
- INT len;
- WCHAR *szAgent = NULL, *szProxy = NULL, *szBypass = NULL;
+ WCHAR *szAgent, *szProxy, *szBypass;
+ HINTERNET rc;
TRACE("(%s, 0x%08x, %s, %s, 0x%08x)\n", debugstr_a(lpszAgent),
dwAccessType, debugstr_a(lpszProxy), debugstr_a(lpszProxyBypass), dwFlags);
- if( lpszAgent )
- {
- len = MultiByteToWideChar(CP_ACP, 0, lpszAgent, -1, NULL, 0);
- szAgent = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpszAgent, -1, szAgent, len);
- }
-
- if( lpszProxy )
- {
- len = MultiByteToWideChar(CP_ACP, 0, lpszProxy, -1, NULL, 0);
- szProxy = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpszProxy, -1, szProxy, len);
- }
-
- if( lpszProxyBypass )
- {
- len = MultiByteToWideChar(CP_ACP, 0, lpszProxyBypass, -1, NULL, 0);
- szBypass = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpszProxyBypass, -1, szBypass, len);
- }
+ szAgent = heap_strdupAtoW(lpszAgent);
+ szProxy = heap_strdupAtoW(lpszProxy);
+ szBypass = heap_strdupAtoW(lpszProxyBypass);
rc = InternetOpenW(szAgent, dwAccessType, szProxy, szBypass, dwFlags);
@@ -779,7 +865,7 @@ HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType,
BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
{
- LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
+ LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex);
TRACE("\n");
@@ -816,7 +902,7 @@ BOOL WINAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
BOOL WINAPI InternetGetLastResponseInfoW(LPDWORD lpdwError,
LPWSTR lpszBuffer, LPDWORD lpdwBufferLength)
{
- LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
+ LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex);
TRACE("\n");
@@ -856,7 +942,7 @@ BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved)
TRACE("(%p, 0x%08x)\n", lpdwStatus, dwReserved);
if (lpdwStatus) {
- FIXME("always returning LAN connection.\n");
+ WARN("always returning LAN connection.\n");
*lpdwStatus = INTERNET_CONNECTION_LAN;
}
return TRUE;
@@ -900,7 +986,7 @@ BOOL WINAPI InternetGetConnectedStateExW(LPDWORD lpdwStatus, LPWSTR lpszConnecti
return FALSE;
if (lpdwStatus) {
- FIXME("always returning LAN connection.\n");
+ WARN("always returning LAN connection.\n");
*lpdwStatus = INTERNET_CONNECTION_LAN;
}
return LoadStringW(WININET_hModule, IDS_LANCONNECTION, lpszConnectionName, dwNameLen);
@@ -950,8 +1036,9 @@ HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
LPCWSTR lpszUserName, LPCWSTR lpszPassword,
DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext)
{
- LPWININETAPPINFOW hIC;
+ appinfo_t *hIC;
HINTERNET rc = NULL;
+ DWORD res = ERROR_SUCCESS;
TRACE("(%p, %s, %i, %s, %s, %i, %i, %lx)\n", hInternet, debugstr_w(lpszServerName),
nServerPort, debugstr_w(lpszUserName), debugstr_w(lpszPassword),
@@ -959,16 +1046,14 @@ HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
if (!lpszServerName)
{
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+ SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
- /* Clear any error information */
- INTERNET_SetLastError(0);
- hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
+ hIC = (appinfo_t*)WININET_GetObject( hInternet );
if ( (hIC == NULL) || (hIC->hdr.htype != WH_HINIT) )
{
- INTERNET_SetLastError(ERROR_INVALID_HANDLE);
+ res = ERROR_INVALID_HANDLE;
goto lend;
}
@@ -977,11 +1062,13 @@ HINTERNET WINAPI InternetConnectW(HINTERNET hInternet,
case INTERNET_SERVICE_FTP:
rc = FTP_Connect(hIC, lpszServerName, nServerPort,
lpszUserName, lpszPassword, dwFlags, dwContext, 0);
+ if(!rc)
+ res = INTERNET_GetLastError();
break;
case INTERNET_SERVICE_HTTP:
- rc = HTTP_Connect(hIC, lpszServerName, nServerPort,
- lpszUserName, lpszPassword, dwFlags, dwContext, 0);
+ res = HTTP_Connect(hIC, lpszServerName, nServerPort,
+ lpszUserName, lpszPassword, dwFlags, dwContext, 0, &rc);
break;
case INTERNET_SERVICE_GOPHER:
@@ -993,6 +1080,7 @@ lend:
WININET_Release( &hIC->hdr );
TRACE("returning %p\n", rc);
+ SetLastError(res);
return rc;
}
@@ -1013,30 +1101,13 @@ HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext)
{
HINTERNET rc = NULL;
- INT len = 0;
- LPWSTR szServerName = NULL;
- LPWSTR szUserName = NULL;
- LPWSTR szPassword = NULL;
-
- if (lpszServerName)
- {
- len = MultiByteToWideChar(CP_ACP, 0, lpszServerName, -1, NULL, 0);
- szServerName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpszServerName, -1, szServerName, len);
- }
- if (lpszUserName)
- {
- len = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
- szUserName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, szUserName, len);
- }
- if (lpszPassword)
- {
- len = MultiByteToWideChar(CP_ACP, 0, lpszPassword, -1, NULL, 0);
- szPassword = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpszPassword, -1, szPassword, len);
- }
+ LPWSTR szServerName;
+ LPWSTR szUserName;
+ LPWSTR szPassword;
+ szServerName = heap_strdupAtoW(lpszServerName);
+ szUserName = heap_strdupAtoW(lpszUserName);
+ szPassword = heap_strdupAtoW(lpszPassword);
rc = InternetConnectW(hInternet, szServerName, nServerPort,
szUserName, szPassword, dwService, dwFlags, dwContext);
@@ -1081,7 +1152,7 @@ BOOL WINAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
*/
BOOL WINAPI InternetFindNextFileW(HINTERNET hFind, LPVOID lpvFindData)
{
- WININETHANDLEHEADER *hdr;
+ object_header_t *hdr;
DWORD res;
TRACE("\n");
@@ -1119,7 +1190,7 @@ BOOL WINAPI InternetFindNextFileW(HINTERNET hFind, LPVOID lpvFindData)
*/
BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
{
- LPWININETHANDLEHEADER lpwh;
+ object_header_t *lpwh;
TRACE("%p\n",hInternet);
@@ -1153,11 +1224,14 @@ static void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentL
DWORD nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL);
if (*lppszComponent == NULL)
{
- int nASCIIOffset=WideCharToMultiByte(CP_ACP,0,lpwszStart,lpwszComponent-lpwszStart,NULL,0,NULL,NULL);
if (lpwszComponent)
- *lppszComponent = (LPSTR)lpszStart+nASCIIOffset;
+ {
+ int offset = WideCharToMultiByte(CP_ACP, 0, lpwszStart, lpwszComponent-lpwszStart, NULL, 0, NULL, NULL);
+ *lppszComponent = (LPSTR)lpszStart + offset;
+ }
else
*lppszComponent = NULL;
+
*dwComponentLen = nASCIILength;
}
else
@@ -1204,7 +1278,7 @@ BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
InternetCrackUrlW should not include it */
if (dwUrlLength == -1) nLength--;
- lpwszUrl=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR)*nLength);
+ lpwszUrl = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,nLength);
memset(&UCW,0,sizeof(UCW));
@@ -1443,7 +1517,7 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
/* Determine if the URI is absolute. */
while (lpszap - lpszUrl < dwUrlLength)
{
- if (isalnumW(*lpszap))
+ if (isalnumW(*lpszap) || *lpszap == '+' || *lpszap == '.' || *lpszap == '-')
{
lpszap++;
continue;
@@ -1465,8 +1539,11 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
lpUC->nPort = INTERNET_INVALID_PORT_NUMBER;
/* Parse */
- if (!(lpszParam = memchrW(lpszap, ';', dwUrlLength - (lpszap - lpszUrl))))
+ lpszParam = memchrW(lpszap, ';', dwUrlLength - (lpszap - lpszUrl));
+ if(!lpszParam)
lpszParam = memchrW(lpszap, '?', dwUrlLength - (lpszap - lpszUrl));
+ if(!lpszParam)
+ lpszParam = memchrW(lpszap, '#', dwUrlLength - (lpszap - lpszUrl));
SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength,
lpszParam, lpszParam ? dwUrlLength-(lpszParam-lpszUrl) : 0);
@@ -1564,7 +1641,7 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
}
/* If the scheme is "file" and the host is just one letter, it's not a host */
- if(lpUC->nScheme==INTERNET_SCHEME_FILE && (lpszPort-lpszHost)==1)
+ if(lpUC->nScheme==INTERNET_SCHEME_FILE && lpszPort <= lpszHost+1)
{
lpszcp=lpszHost;
SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength,
@@ -1617,7 +1694,7 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR
* :[//][/path][;][?][#]
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*/
- if (lpszcp != 0 && lpszcp - lpszUrl < dwUrlLength && (!lpszParam || lpszcp < lpszParam))
+ if (lpszcp != 0 && lpszcp - lpszUrl < dwUrlLength && (!lpszParam || lpszcp <= lpszParam))
{
INT len;
@@ -1783,7 +1860,7 @@ BOOL WINAPI InternetCanonicalizeUrlW(LPCWSTR lpszUrl, LPWSTR lpszBuffer,
/* #################################################### */
static INTERNET_STATUS_CALLBACK set_status_callback(
- LPWININETHANDLEHEADER lpwh, INTERNET_STATUS_CALLBACK callback, BOOL unicode)
+ object_header_t *lpwh, INTERNET_STATUS_CALLBACK callback, BOOL unicode)
{
INTERNET_STATUS_CALLBACK ret;
@@ -1811,10 +1888,10 @@ INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA(
HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
{
INTERNET_STATUS_CALLBACK retVal;
- LPWININETHANDLEHEADER lpwh;
+ object_header_t *lpwh;
+
+ TRACE("%p\n", hInternet);
- TRACE("0x%08x\n", (ULONG)hInternet);
-
if (!(lpwh = WININET_GetObject(hInternet)))
return INTERNET_INVALID_STATUS_CALLBACK;
@@ -1839,9 +1916,9 @@ INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackW(
HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
{
INTERNET_STATUS_CALLBACK retVal;
- LPWININETHANDLEHEADER lpwh;
+ object_header_t *lpwh;
- TRACE("0x%08x\n", (ULONG)hInternet);
+ TRACE("%p\n", hInternet);
if (!(lpwh = WININET_GetObject(hInternet)))
return INTERNET_INVALID_STATUS_CALLBACK;
@@ -1875,8 +1952,8 @@ DWORD WINAPI InternetSetFilePointer(HINTERNET hFile, LONG lDistanceToMove,
BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer,
DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
{
- LPWININETHANDLEHEADER lpwh;
- BOOL retval = FALSE;
+ object_header_t *lpwh;
+ BOOL res;
TRACE("(%p %p %d %p)\n", hFile, lpBuffer, dwNumOfBytesToWrite, lpdwNumOfBytesWritten);
@@ -1888,16 +1965,17 @@ BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer,
}
if(lpwh->vtbl->WriteFile) {
- retval = lpwh->vtbl->WriteFile(lpwh, lpBuffer, dwNumOfBytesToWrite, lpdwNumOfBytesWritten);
+ res = lpwh->vtbl->WriteFile(lpwh, lpBuffer, dwNumOfBytesToWrite, lpdwNumOfBytesWritten);
}else {
WARN("No Writefile method.\n");
- SetLastError(ERROR_INVALID_HANDLE);
- retval = FALSE;
+ res = ERROR_INVALID_HANDLE;
}
WININET_Release( lpwh );
- return retval;
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
}
@@ -1914,7 +1992,7 @@ BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer,
BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
DWORD dwNumOfBytesToRead, LPDWORD pdwNumOfBytesRead)
{
- LPWININETHANDLEHEADER hdr;
+ object_header_t *hdr;
DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
TRACE("%p %p %d %p\n", hFile, lpBuffer, dwNumOfBytesToRead, pdwNumOfBytesRead);
@@ -1968,7 +2046,7 @@ BOOL WINAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffersOut,
DWORD dwFlags, DWORD_PTR dwContext)
{
- LPWININETHANDLEHEADER hdr;
+ object_header_t *hdr;
DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffersOut, dwFlags, dwContext);
@@ -1994,33 +2072,40 @@ BOOL WINAPI InternetReadFileExA(HINTERNET hFile, LPINTERNET_BUFFERSA lpBuffersOu
/***********************************************************************
* InternetReadFileExW (WININET.@)
- *
- * Read data from an open internet file.
- *
- * PARAMS
- * hFile [I] Handle returned by InternetOpenUrl() or HttpOpenRequest().
- * lpBuffersOut [I/O] Buffer.
- * dwFlags [I] Flags.
- * dwContext [I] Context for callbacks.
- *
- * RETURNS
- * FALSE, last error is set to ERROR_CALL_NOT_IMPLEMENTED
- *
- * NOTES
- * Not implemented in Wine or native either (as of IE6 SP2).
- *
+ * SEE
+ * InternetReadFileExA()
*/
BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
DWORD dwFlags, DWORD_PTR dwContext)
{
- ERR("(%p, %p, 0x%x, 0x%lx): not implemented in native\n", hFile, lpBuffer, dwFlags, dwContext);
+ object_header_t *hdr;
+ DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
- INTERNET_SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffer, dwFlags, dwContext);
+
+ hdr = WININET_GetObject(hFile);
+ if (!hdr) {
+ INTERNET_SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if(hdr->vtbl->ReadFileExW)
+ res = hdr->vtbl->ReadFileExW(hdr, lpBuffer, dwFlags, dwContext);
+
+ WININET_Release(hdr);
+
+ TRACE("-- %s (%u, bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE",
+ res, lpBuffer->dwBufferLength);
+
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
}
DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
{
+ static BOOL warn = TRUE;
+
switch(option) {
case INTERNET_OPTION_REQUEST_FLAGS:
TRACE("INTERNET_OPTION_REQUEST_FLAGS\n");
@@ -2047,8 +2132,10 @@ DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
return ERROR_SUCCESS;
case INTERNET_OPTION_CONNECTED_STATE:
- FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n");
-
+ if (warn) {
+ FIXME("INTERNET_OPTION_CONNECTED_STATE: semi-stub\n");
+ warn = FALSE;
+ }
if (*size < sizeof(ULONG))
return ERROR_INSUFFICIENT_BUFFER;
@@ -2058,13 +2145,16 @@ DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
return ERROR_SUCCESS;
case INTERNET_OPTION_PROXY: {
- WININETAPPINFOW ai;
+ appinfo_t ai;
+ BOOL ret;
TRACE("Getting global proxy info\n");
- memset(&ai, 0, sizeof(WININETAPPINFOW));
+ memset(&ai, 0, sizeof(appinfo_t));
INTERNET_ConfigureProxy(&ai);
- return APPINFO_QueryOption(&ai.hdr, INTERNET_OPTION_PROXY, buffer, size, unicode); /* FIXME */
+ ret = APPINFO_QueryOption(&ai.hdr, INTERNET_OPTION_PROXY, buffer, size, unicode); /* FIXME */
+ APPINFO_Destroy(&ai.hdr);
+ return ret;
}
case INTERNET_OPTION_MAX_CONNS_PER_SERVER:
@@ -2109,23 +2199,48 @@ DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
case INTERNET_OPTION_PER_CONNECTION_OPTION: {
INTERNET_PER_CONN_OPTION_LISTW *con = buffer;
+ INTERNET_PER_CONN_OPTION_LISTA *conA = buffer;
DWORD res = ERROR_SUCCESS, i;
+ proxyinfo_t pi;
+ LONG ret;
+
+ TRACE("Getting global proxy info\n");
+ if((ret = INTERNET_LoadProxySettings(&pi)))
+ return ret;
FIXME("INTERNET_OPTION_PER_CONNECTION_OPTION stub\n");
- if (*size < sizeof(INTERNET_PER_CONN_OPTION_LISTW))
+ if (*size < sizeof(INTERNET_PER_CONN_OPTION_LISTW)) {
+ FreeProxyInfo(&pi);
return ERROR_INSUFFICIENT_BUFFER;
+ }
for (i = 0; i < con->dwOptionCount; i++) {
INTERNET_PER_CONN_OPTIONW *option = con->pOptions + i;
+ INTERNET_PER_CONN_OPTIONA *optionA = conA->pOptions + i;
switch (option->dwOption) {
case INTERNET_PER_CONN_FLAGS:
- option->Value.dwValue = PROXY_TYPE_DIRECT;
+ if(pi.dwProxyEnabled)
+ option->Value.dwValue = PROXY_TYPE_PROXY;
+ else
+ option->Value.dwValue = PROXY_TYPE_DIRECT;
break;
case INTERNET_PER_CONN_PROXY_SERVER:
+ if (unicode)
+ option->Value.pszValue = heap_strdupW(pi.lpszProxyServer);
+ else
+ optionA->Value.pszValue = heap_strdupWtoA(pi.lpszProxyServer);
+ break;
+
case INTERNET_PER_CONN_PROXY_BYPASS:
+ if (unicode)
+ option->Value.pszValue = heap_strdupW(pi.lpszProxyBypass);
+ else
+ optionA->Value.pszValue = heap_strdupWtoA(pi.lpszProxyBypass);
+ break;
+
case INTERNET_PER_CONN_AUTOCONFIG_URL:
case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
@@ -2133,8 +2248,7 @@ DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
FIXME("Unhandled dwOption %d\n", option->dwOption);
- option->Value.dwValue = 0;
- res = ERROR_INVALID_PARAMETER;
+ memset(&option->Value, 0, sizeof(option->Value));
break;
default:
@@ -2143,9 +2257,14 @@ DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
break;
}
}
+ FreeProxyInfo(&pi);
return res;
}
+ case INTERNET_OPTION_USER_AGENT:
+ return ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ case INTERNET_OPTION_POLICY:
+ return ERROR_INVALID_PARAMETER;
}
FIXME("Stub for %d\n", option);
@@ -2165,7 +2284,7 @@ DWORD INET_QueryOption(DWORD option, void *buffer, DWORD *size, BOOL unicode)
BOOL WINAPI InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption,
LPVOID lpBuffer, LPDWORD lpdwBufferLength)
{
- LPWININETHANDLEHEADER hdr;
+ object_header_t *hdr;
DWORD res = ERROR_INVALID_HANDLE;
TRACE("%p %d %p %p\n", hInternet, dwOption, lpBuffer, lpdwBufferLength);
@@ -2198,7 +2317,7 @@ BOOL WINAPI InternetQueryOptionW(HINTERNET hInternet, DWORD dwOption,
BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
LPVOID lpBuffer, LPDWORD lpdwBufferLength)
{
- LPWININETHANDLEHEADER hdr;
+ object_header_t *hdr;
DWORD res = ERROR_INVALID_HANDLE;
TRACE("%p %d %p %p\n", hInternet, dwOption, lpBuffer, lpdwBufferLength);
@@ -2232,12 +2351,12 @@ BOOL WINAPI InternetQueryOptionA(HINTERNET hInternet, DWORD dwOption,
BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
LPVOID lpBuffer, DWORD dwBufferLength)
{
- LPWININETHANDLEHEADER lpwhh;
+ object_header_t *lpwhh;
BOOL ret = TRUE;
TRACE("(%p %d %p %d)\n", hInternet, dwOption, lpBuffer, dwBufferLength);
- lpwhh = (LPWININETHANDLEHEADER) WININET_GetObject( hInternet );
+ lpwhh = (object_header_t*) WININET_GetObject( hInternet );
if(lpwhh && lpwhh->vtbl->SetOption) {
DWORD res;
@@ -2256,9 +2375,14 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
{
case INTERNET_OPTION_CALLBACK:
{
- INTERNET_STATUS_CALLBACK callback = *(INTERNET_STATUS_CALLBACK *)lpBuffer;
- ret = (set_status_callback(lpwhh, callback, TRUE) != INTERNET_INVALID_STATUS_CALLBACK);
- break;
+ if (!lpwhh)
+ {
+ SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
+ return FALSE;
+ }
+ WININET_Release(lpwhh);
+ SetLastError(ERROR_INTERNET_OPTION_NOT_SETTABLE);
+ return FALSE;
}
case INTERNET_OPTION_HTTP_VERSION:
{
@@ -2342,12 +2466,96 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
case INTERNET_OPTION_DISABLE_AUTODIAL:
FIXME("Option INTERNET_OPTION_DISABLE_AUTODIAL; STUB\n");
break;
- case 86:
- FIXME("86\n");
+ case INTERNET_OPTION_HTTP_DECODING:
+ FIXME("INTERNET_OPTION_HTTP_DECODING; STUB\n");
+ SetLastError(ERROR_INTERNET_INVALID_OPTION);
+ ret = FALSE;
break;
+ case INTERNET_OPTION_COOKIES_3RD_PARTY:
+ FIXME("INTERNET_OPTION_COOKIES_3RD_PARTY; STUB\n");
+ SetLastError(ERROR_INTERNET_INVALID_OPTION);
+ ret = FALSE;
+ break;
+ case INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY:
+ FIXME("INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY; STUB\n");
+ SetLastError(ERROR_INTERNET_INVALID_OPTION);
+ ret = FALSE;
+ break;
+ case INTERNET_OPTION_CODEPAGE_PATH:
+ FIXME("INTERNET_OPTION_CODEPAGE_PATH; STUB\n");
+ SetLastError(ERROR_INTERNET_INVALID_OPTION);
+ ret = FALSE;
+ break;
+ case INTERNET_OPTION_CODEPAGE_EXTRA:
+ FIXME("INTERNET_OPTION_CODEPAGE_EXTRA; STUB\n");
+ SetLastError(ERROR_INTERNET_INVALID_OPTION);
+ ret = FALSE;
+ break;
+ case INTERNET_OPTION_IDN:
+ FIXME("INTERNET_OPTION_IDN; STUB\n");
+ SetLastError(ERROR_INTERNET_INVALID_OPTION);
+ ret = FALSE;
+ break;
+ case INTERNET_OPTION_POLICY:
+ SetLastError(ERROR_INVALID_PARAMETER);
+ ret = FALSE;
+ break;
+ case INTERNET_OPTION_PER_CONNECTION_OPTION: {
+ INTERNET_PER_CONN_OPTION_LISTW *con = lpBuffer;
+ LONG res;
+ int i;
+ proxyinfo_t pi;
+
+ INTERNET_LoadProxySettings(&pi);
+
+ for (i = 0; i < con->dwOptionCount; i++) {
+ INTERNET_PER_CONN_OPTIONW *option = con->pOptions + i;
+
+ switch (option->dwOption) {
+ case INTERNET_PER_CONN_PROXY_SERVER:
+ HeapFree(GetProcessHeap(), 0, pi.lpszProxyServer);
+ pi.lpszProxyServer = heap_strdupW(option->Value.pszValue);
+ break;
+
+ case INTERNET_PER_CONN_FLAGS:
+ if(option->Value.dwValue & PROXY_TYPE_PROXY)
+ pi.dwProxyEnabled = 1;
+ else
+ {
+ if(option->Value.dwValue != PROXY_TYPE_DIRECT)
+ FIXME("Unhandled flags: 0x%x\n", option->Value.dwValue);
+ pi.dwProxyEnabled = 0;
+ }
+ break;
+
+ case INTERNET_PER_CONN_AUTOCONFIG_URL:
+ case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
+ case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
+ case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
+ case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
+ case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
+ case INTERNET_PER_CONN_PROXY_BYPASS:
+ FIXME("Unhandled dwOption %d\n", option->dwOption);
+ break;
+
+ default:
+ FIXME("Unknown dwOption %d\n", option->dwOption);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ break;
+ }
+ }
+
+ if ((res = INTERNET_SaveProxySettings(&pi)))
+ SetLastError(res);
+
+ FreeProxyInfo(&pi);
+
+ ret = (res == ERROR_SUCCESS);
+ break;
+ }
default:
FIXME("Option %d STUB\n",dwOption);
- INTERNET_SetLastError(ERROR_INTERNET_INVALID_OPTION);
+ SetLastError(ERROR_INTERNET_INVALID_OPTION);
ret = FALSE;
break;
}
@@ -2380,13 +2588,16 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
{
case INTERNET_OPTION_CALLBACK:
{
- LPWININETHANDLEHEADER lpwh;
- INTERNET_STATUS_CALLBACK callback = *(INTERNET_STATUS_CALLBACK *)lpBuffer;
+ object_header_t *lpwh;
- if (!(lpwh = WININET_GetObject(hInternet))) return FALSE;
- r = (set_status_callback(lpwh, callback, FALSE) != INTERNET_INVALID_STATUS_CALLBACK);
+ if (!(lpwh = WININET_GetObject(hInternet)))
+ {
+ INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
+ return FALSE;
+ }
WININET_Release(lpwh);
- return r;
+ INTERNET_SetLastError(ERROR_INTERNET_OPTION_NOT_SETTABLE);
+ return FALSE;
}
case INTERNET_OPTION_PROXY:
{
@@ -2418,6 +2629,63 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
MultiByteToWideChar( CP_ACP, 0, lpBuffer, dwBufferLength,
wbuffer, wlen );
break;
+ case INTERNET_OPTION_PER_CONNECTION_OPTION: {
+ int i;
+ INTERNET_PER_CONN_OPTION_LISTW *listW;
+ INTERNET_PER_CONN_OPTION_LISTA *listA = lpBuffer;
+ wlen = sizeof(INTERNET_PER_CONN_OPTION_LISTW);
+ wbuffer = HeapAlloc( GetProcessHeap(), 0, wlen );
+ listW = wbuffer;
+
+ listW->dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTW);
+ if (listA->pszConnection)
+ {
+ wlen = MultiByteToWideChar( CP_ACP, 0, listA->pszConnection, -1, NULL, 0 );
+ listW->pszConnection = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, listA->pszConnection, -1, listW->pszConnection, wlen );
+ }
+ else
+ listW->pszConnection = NULL;
+ listW->dwOptionCount = listA->dwOptionCount;
+ listW->dwOptionError = listA->dwOptionError;
+ listW->pOptions = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNET_PER_CONN_OPTIONW) * listA->dwOptionCount );
+
+ for (i = 0; i < listA->dwOptionCount; ++i) {
+ INTERNET_PER_CONN_OPTIONA *optA = listA->pOptions + i;
+ INTERNET_PER_CONN_OPTIONW *optW = listW->pOptions + i;
+
+ optW->dwOption = optA->dwOption;
+
+ switch (optA->dwOption) {
+ case INTERNET_PER_CONN_AUTOCONFIG_URL:
+ case INTERNET_PER_CONN_PROXY_BYPASS:
+ case INTERNET_PER_CONN_PROXY_SERVER:
+ case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
+ case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
+ if (optA->Value.pszValue)
+ {
+ wlen = MultiByteToWideChar( CP_ACP, 0, optA->Value.pszValue, -1, NULL, 0 );
+ optW->Value.pszValue = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, optA->Value.pszValue, -1, optW->Value.pszValue, wlen );
+ }
+ else
+ optW->Value.pszValue = NULL;
+ break;
+ case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
+ case INTERNET_PER_CONN_FLAGS:
+ case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
+ optW->Value.dwValue = optA->Value.dwValue;
+ break;
+ case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
+ optW->Value.ftValue = optA->Value.ftValue;
+ default:
+ WARN("Unknown PER_CONN dwOption: %d, guessing at conversion to Wide\n", optA->dwOption);
+ optW->Value.dwValue = optA->Value.dwValue;
+ break;
+ }
+ }
+ }
+ break;
default:
wbuffer = lpBuffer;
wlen = dwBufferLength;
@@ -2426,7 +2694,29 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption,
r = InternetSetOptionW(hInternet,dwOption, wbuffer, wlen);
if( lpBuffer != wbuffer )
+ {
+ if (dwOption == INTERNET_OPTION_PER_CONNECTION_OPTION)
+ {
+ INTERNET_PER_CONN_OPTION_LISTW *list = wbuffer;
+ int i;
+ for (i = 0; i < list->dwOptionCount; ++i) {
+ INTERNET_PER_CONN_OPTIONW *opt = list->pOptions + i;
+ switch (opt->dwOption) {
+ case INTERNET_PER_CONN_AUTOCONFIG_URL:
+ case INTERNET_PER_CONN_PROXY_BYPASS:
+ case INTERNET_PER_CONN_PROXY_SERVER:
+ case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
+ case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
+ HeapFree( GetProcessHeap(), 0, opt->Value.pszValue );
+ break;
+ default:
+ break;
+ }
+ }
+ HeapFree( GetProcessHeap(), 0, list->pOptions );
+ }
HeapFree( GetProcessHeap(), 0, wbuffer );
+ }
return r;
}
@@ -2451,7 +2741,7 @@ BOOL WINAPI InternetSetOptionExW(HINTERNET hInternet, DWORD dwOption,
FIXME("Flags %08x ignored\n", dwFlags);
if( dwFlags & ~ISO_VALID_FLAGS )
{
- INTERNET_SetLastError( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
return InternetSetOptionW( hInternet, dwOption, lpBuffer, dwBufferLength );
@@ -2475,6 +2765,18 @@ BOOL WINAPI InternetTimeFromSystemTimeA( const SYSTEMTIME* time, DWORD format, L
TRACE( "%p 0x%08x %p 0x%08x\n", time, format, string, size );
+ if (!time || !string || format != INTERNET_RFC1123_FORMAT)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if (size < INTERNET_RFC1123_BUFSIZE * sizeof(*string))
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
ret = InternetTimeFromSystemTimeW( time, format, stringW, sizeof(stringW) );
if (ret) WideCharToMultiByte( CP_ACP, 0, stringW, -1, string, size, NULL, NULL );
@@ -2492,10 +2794,17 @@ BOOL WINAPI InternetTimeFromSystemTimeW( const SYSTEMTIME* time, DWORD format, L
TRACE( "%p 0x%08x %p 0x%08x\n", time, format, string, size );
- if (!time || !string) return FALSE;
-
- if (format != INTERNET_RFC1123_FORMAT || size < INTERNET_RFC1123_BUFSIZE * sizeof(WCHAR))
+ if (!time || !string || format != INTERNET_RFC1123_FORMAT)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
+ }
+
+ if (size < INTERNET_RFC1123_BUFSIZE * sizeof(*string))
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
sprintfW( string, date,
WININET_wkday[time->wDayOfWeek],
@@ -2516,16 +2825,12 @@ BOOL WINAPI InternetTimeToSystemTimeA( LPCSTR string, SYSTEMTIME* time, DWORD re
{
BOOL ret = FALSE;
WCHAR *stringW;
- int len;
TRACE( "%s %p 0x%08x\n", debugstr_a(string), time, reserved );
- len = MultiByteToWideChar( CP_ACP, 0, string, -1, NULL, 0 );
- stringW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-
+ stringW = heap_strdupAtoW(string);
if (stringW)
{
- MultiByteToWideChar( CP_ACP, 0, string, -1, stringW, len );
ret = InternetTimeToSystemTimeW( stringW, time, reserved );
HeapFree( GetProcessHeap(), 0, stringW );
}
@@ -2674,15 +2979,16 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe
if (dwFlags & FLAG_ICC_FORCE_CONNECTION)
{
- struct sockaddr_in sin;
+ struct sockaddr_storage saddr;
+ socklen_t sa_len = sizeof(saddr);
int fd;
- if (!GetAddress(hostW, port, &sin))
+ if (!GetAddress(hostW, port, (struct sockaddr *)&saddr, &sa_len))
goto End;
- fd = socket(sin.sin_family, SOCK_STREAM, 0);
+ fd = socket(saddr.ss_family, SOCK_STREAM, 0);
if (fd != -1)
{
- if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == 0)
+ if (connect(fd, (struct sockaddr *)&saddr, sa_len) == 0)
rc = TRUE;
close(fd);
}
@@ -2731,17 +3037,18 @@ End:
*/
BOOL WINAPI InternetCheckConnectionA(LPCSTR lpszUrl, DWORD dwFlags, DWORD dwReserved)
{
- WCHAR *szUrl;
- INT len;
+ WCHAR *url = NULL;
BOOL rc;
- len = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0);
- if (!(szUrl = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR))))
- return FALSE;
- MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, szUrl, len);
- rc = InternetCheckConnectionW(szUrl, dwFlags, dwReserved);
- HeapFree(GetProcessHeap(), 0, szUrl);
-
+ if(lpszUrl) {
+ url = heap_strdupAtoW(lpszUrl);
+ if(!url)
+ return FALSE;
+ }
+
+ rc = InternetCheckConnectionW(url, dwFlags, dwReserved);
+
+ HeapFree(GetProcessHeap(), 0, url);
return rc;
}
@@ -2754,13 +3061,14 @@ BOOL WINAPI InternetCheckConnectionA(LPCSTR lpszUrl, DWORD dwFlags, DWORD dwRese
* RETURNS
* handle of connection or NULL on failure
*/
-static HINTERNET INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl,
+static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl,
LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext)
{
URL_COMPONENTSW urlComponents;
WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024];
WCHAR password[1024], path[2048], extra[1024];
HINTERNET client = NULL, client1 = NULL;
+ DWORD res;
TRACE("(%p, %s, %s, %08x, %08x, %08lx)\n", hIC, debugstr_w(lpszUrl), debugstr_w(lpszHeaders),
dwHeadersLength, dwFlags, dwContext);
@@ -2805,11 +3113,15 @@ static HINTERNET INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUr
else
urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
}
+ if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS) dwFlags |= INTERNET_FLAG_SECURE;
+
/* FIXME: should use pointers, not handles, as handles are not thread-safe */
- client = HTTP_Connect(hIC, hostName, urlComponents.nPort,
- userName, password, dwFlags, dwContext, INET_OPENURL);
- if(client == NULL)
+ res = HTTP_Connect(hIC, hostName, urlComponents.nPort,
+ userName, password, dwFlags, dwContext, INET_OPENURL, &client);
+ if(res != ERROR_SUCCESS) {
+ INTERNET_SetLastError(res);
break;
+ }
if (urlComponents.dwExtraInfoLength) {
WCHAR *path_extra;
@@ -2844,7 +3156,7 @@ static HINTERNET INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUr
/* gopher doesn't seem to be implemented in wine, but it's supposed
* to be supported by InternetOpenUrlA. */
default:
- INTERNET_SetLastError(ERROR_INTERNET_UNRECOGNIZED_SCHEME);
+ SetLastError(ERROR_INTERNET_UNRECOGNIZED_SCHEME);
break;
}
@@ -2864,7 +3176,7 @@ static HINTERNET INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUr
static void AsyncInternetOpenUrlProc(WORKREQUEST *workRequest)
{
struct WORKREQ_INTERNETOPENURLW const *req = &workRequest->u.InternetOpenUrlW;
- LPWININETAPPINFOW hIC = (LPWININETAPPINFOW) workRequest->hdr;
+ appinfo_t *hIC = (appinfo_t*) workRequest->hdr;
TRACE("%p\n", hIC);
@@ -2878,7 +3190,7 @@ HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext)
{
HINTERNET ret = NULL;
- LPWININETAPPINFOW hIC = NULL;
+ appinfo_t *hIC = NULL;
if (TRACE_ON(wininet)) {
TRACE("(%p, %s, %s, %08x, %08x, %08lx)\n", hInternet, debugstr_w(lpszUrl), debugstr_w(lpszHeaders),
@@ -2889,13 +3201,13 @@ HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
if (!lpszUrl)
{
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+ SetLastError(ERROR_INVALID_PARAMETER);
goto lend;
}
- hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
+ hIC = (appinfo_t*)WININET_GetObject( hInternet );
if (NULL == hIC || hIC->hdr.htype != WH_HINIT) {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
+ SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
goto lend;
}
@@ -2905,12 +3217,9 @@ HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
workRequest.asyncproc = AsyncInternetOpenUrlProc;
workRequest.hdr = WININET_AddRef( &hIC->hdr );
- req = &workRequest.u.InternetOpenUrlW;
- req->lpszUrl = WININET_strdupW(lpszUrl);
- if (lpszHeaders)
- req->lpszHeaders = WININET_strdupW(lpszHeaders);
- else
- req->lpszHeaders = 0;
+ req = &workRequest.u.InternetOpenUrlW;
+ req->lpszUrl = heap_strdupW(lpszUrl);
+ req->lpszHeaders = heap_strdupW(lpszHeaders);
req->dwHeadersLength = dwHeadersLength;
req->dwFlags = dwFlags;
req->dwContext = dwContext;
@@ -2919,7 +3228,7 @@ HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
/*
* This is from windows.
*/
- INTERNET_SetLastError(ERROR_IO_PENDING);
+ SetLastError(ERROR_IO_PENDING);
} else {
ret = INTERNET_InternetOpenUrlW(hIC, lpszUrl, lpszHeaders, dwHeadersLength, dwFlags, dwContext);
}
@@ -2944,20 +3253,16 @@ HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl,
LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext)
{
HINTERNET rc = NULL;
-
- INT lenUrl;
- INT lenHeaders = 0;
+ DWORD lenHeaders = 0;
LPWSTR szUrl = NULL;
LPWSTR szHeaders = NULL;
TRACE("\n");
if(lpszUrl) {
- lenUrl = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0 );
- szUrl = HeapAlloc(GetProcessHeap(), 0, lenUrl*sizeof(WCHAR));
+ szUrl = heap_strdupAtoW(lpszUrl);
if(!szUrl)
return NULL;
- MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, szUrl, lenUrl);
}
if(lpszHeaders) {
@@ -3010,7 +3315,7 @@ static LPWITHREADERROR INTERNET_AllocThreadError(void)
*/
void INTERNET_SetLastError(DWORD dwError)
{
- LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
+ LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex);
if (!lpwite)
lpwite = INTERNET_AllocThreadError();
@@ -3031,7 +3336,7 @@ void INTERNET_SetLastError(DWORD dwError)
*/
DWORD INTERNET_GetLastError(void)
{
- LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
+ LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex);
if (!lpwite) return 0;
/* TlsGetValue clears last error, so set it again here */
SetLastError(lpwite->dwError);
@@ -3058,8 +3363,13 @@ static DWORD CALLBACK INTERNET_WorkerThreadFunc(LPVOID lpvParam)
HeapFree(GetProcessHeap(), 0, lpRequest);
workRequest.asyncproc(&workRequest);
-
WININET_Release( workRequest.hdr );
+
+ if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
+ {
+ HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
+ TlsSetValue(g_dwTlsErrIndex, NULL);
+ }
return TRUE;
}
@@ -3072,7 +3382,7 @@ static DWORD CALLBACK INTERNET_WorkerThreadFunc(LPVOID lpvParam)
* RETURNS
*
*/
-BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
+DWORD INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
{
BOOL bSuccess;
LPWORKREQUEST lpNewRequest;
@@ -3081,7 +3391,7 @@ BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
if (!lpNewRequest)
- return FALSE;
+ return ERROR_OUTOFMEMORY;
*lpNewRequest = *lpWorkRequest;
@@ -3089,10 +3399,10 @@ BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
if (!bSuccess)
{
HeapFree(GetProcessHeap(), 0, lpNewRequest);
- INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
+ return ERROR_INTERNET_ASYNC_THREAD_FAILED;
}
- return bSuccess;
+ return ERROR_SUCCESS;
}
@@ -3104,7 +3414,7 @@ BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
*/
LPSTR INTERNET_GetResponseBuffer(void)
{
- LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
+ LPWITHREADERROR lpwite = TlsGetValue(g_dwTlsErrIndex);
if (!lpwite)
lpwite = INTERNET_AllocThreadError();
TRACE("\n");
@@ -3193,14 +3503,14 @@ BOOL WINAPI InternetQueryDataAvailable( HINTERNET hFile,
LPDWORD lpdwNumberOfBytesAvailble,
DWORD dwFlags, DWORD_PTR dwContext)
{
- WININETHANDLEHEADER *hdr;
+ object_header_t *hdr;
DWORD res;
TRACE("(%p %p %x %lx)\n", hFile, lpdwNumberOfBytesAvailble, dwFlags, dwContext);
hdr = WININET_GetObject( hFile );
if (!hdr) {
- INTERNET_SetLastError(ERROR_INVALID_HANDLE);
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
@@ -3451,6 +3761,9 @@ static BOOL calc_url_length(LPURL_COMPONENTSW lpUrlComponents,
if (lpUrlComponents->lpszUrlPath)
*lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, UrlPath);
+ if (lpUrlComponents->lpszExtraInfo)
+ *lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, ExtraInfo);
+
return TRUE;
}
@@ -3535,7 +3848,7 @@ BOOL WINAPI InternetCreateUrlA(LPURL_COMPONENTSA lpUrlComponents, DWORD dwFlags,
if (!lpUrlComponents || lpUrlComponents->dwStructSize != sizeof(URL_COMPONENTSW) || !lpdwUrlLength)
{
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+ SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
@@ -3699,7 +4012,6 @@ BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags,
}
}
-
if (lpUrlComponents->lpszUrlPath)
{
dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, UrlPath);
@@ -3707,6 +4019,13 @@ BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags,
lpszUrl += dwLen;
}
+ if (lpUrlComponents->lpszExtraInfo)
+ {
+ dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, ExtraInfo);
+ memcpy(lpszUrl, lpUrlComponents->lpszExtraInfo, dwLen * sizeof(WCHAR));
+ lpszUrl += dwLen;
+ }
+
*lpszUrl = '\0';
return TRUE;
@@ -3732,6 +4051,31 @@ DWORD WINAPI InternetConfirmZoneCrossingW( HWND hWnd, LPWSTR szUrlPrev, LPWSTR s
return ERROR_SUCCESS;
}
+static DWORD zone_preference = 3;
+
+/***********************************************************************
+ * PrivacySetZonePreferenceW (WININET.@)
+ */
+DWORD WINAPI PrivacySetZonePreferenceW( DWORD zone, DWORD type, DWORD template, LPCWSTR preference )
+{
+ FIXME( "%x %x %x %s: stub\n", zone, type, template, debugstr_w(preference) );
+
+ zone_preference = template;
+ return 0;
+}
+
+/***********************************************************************
+ * PrivacyGetZonePreferenceW (WININET.@)
+ */
+DWORD WINAPI PrivacyGetZonePreferenceW( DWORD zone, DWORD type, LPDWORD template,
+ LPWSTR preference, LPDWORD length )
+{
+ FIXME( "%x %x %p %p %p: stub\n", zone, type, template, preference, length );
+
+ if (template) *template = zone_preference;
+ return 0;
+}
+
DWORD WINAPI InternetDialA( HWND hwndParent, LPSTR lpszConnectoid, DWORD dwFlags,
DWORD_PTR* lpdwConnection, DWORD dwReserved )
{
diff --git a/dll/win32/wininet/internet.h b/dll/win32/wininet/internet.h
index 0dcf5a22ce6..e45176bb2c0 100644
--- a/dll/win32/wininet/internet.h
+++ b/dll/win32/wininet/internet.h
@@ -42,12 +42,7 @@
# include
#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);
diff --git a/dll/win32/wininet/netconnection.c b/dll/win32/wininet/netconnection.c
index 5d8b4d75534..c2560b5da37 100644
--- a/dll/win32/wininet/netconnection.c
+++ b/dll/win32/wininet/netconnection.c
@@ -23,6 +23,12 @@
#include "config.h"
#include "wine/port.h"
+#define NONAMELESSUNION
+
+#if defined(__MINGW32__) || defined (_MSC_VER)
+#include
+#endif
+
#include
#ifdef HAVE_POLL_H
#include
@@ -33,10 +39,12 @@
#ifdef HAVE_SYS_TIME_H
# include
#endif
-#include
#ifdef HAVE_SYS_SOCKET_H
# include
#endif
+#ifdef HAVE_SYS_FILIO_H
+# include
+#endif
#ifdef HAVE_UNISTD_H
# include
#endif
@@ -55,9 +63,6 @@
#undef FAR
#undef DSA
#endif
-#ifdef HAVE_SYS_SOCKET_H
-# include
-#endif
#include
#include
@@ -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
+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)
diff --git a/dll/win32/wininet/resource.h b/dll/win32/wininet/resource.h
index 8a6e4d152e2..279c1123db8 100644
--- a/dll/win32/wininet/resource.h
+++ b/dll/win32/wininet/resource.h
@@ -18,6 +18,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include
+#include
+
+#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
diff --git a/dll/win32/wininet/rsrc.rc b/dll/win32/wininet/rsrc.rc
index 5a815116b03..52ea8d4e8d2 100644
--- a/dll/win32/wininet/rsrc.rc
+++ b/dll/win32/wininet/rsrc.rc
@@ -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"
+
diff --git a/dll/win32/wininet/urlcache.c b/dll/win32/wininet/urlcache.c
index c839419f136..29d26ab0b6b 100644
--- a/dll/win32/wininet/urlcache.c
+++ b/dll/win32/wininet/urlcache.c
@@ -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;
+}
diff --git a/dll/win32/wininet/utility.c b/dll/win32/wininet/utility.c
index b0d9c9c91c6..66fbecdd653 100644
--- a/dll/win32/wininet/utility.c
+++ b/dll/win32/wininet/utility.c
@@ -25,6 +25,10 @@
#include "config.h"
#include "wine/port.h"
+#if defined(__MINGW32__) || defined (_MSC_VER)
+#include
+#endif
+
#include
#include
#include
@@ -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)
{
diff --git a/dll/win32/wininet/wininet.rbuild b/dll/win32/wininet/wininet.rbuild
index 4a83d0b0ac4..45b87b18665 100644
--- a/dll/win32/wininet/wininet.rbuild
+++ b/dll/win32/wininet/wininet.rbuild
@@ -22,6 +22,7 @@
secur32
crypt32
ws2_32
+ pseh
cookie.c
dialogs.c
ftp.c
diff --git a/dll/win32/wininet/wininet.spec b/dll/win32/wininet/wininet.spec
index dfbc38c02fc..46dd04334e6 100644
--- a/dll/win32/wininet/wininet.spec
+++ b/dll/win32/wininet/wininet.spec
@@ -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)
diff --git a/dll/win32/wininet/wininet_Bg.rc b/dll/win32/wininet/wininet_Bg.rc
index 52d797ed751..b25356e074e 100644
--- a/dll/win32/wininet/wininet_Bg.rc
+++ b/dll/win32/wininet/wininet_Bg.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Cs.rc b/dll/win32/wininet/wininet_Cs.rc
index 9ca75397c4f..443c0175190 100644
--- a/dll/win32/wininet/wininet_Cs.rc
+++ b/dll/win32/wininet/wininet_Cs.rc
@@ -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 */
diff --git a/dll/win32/wininet/wininet_Da.rc b/dll/win32/wininet/wininet_Da.rc
index 515dcabd8b3..6b37857ed54 100644
--- a/dll/win32/wininet/wininet_Da.rc
+++ b/dll/win32/wininet/wininet_Da.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_De.rc b/dll/win32/wininet/wininet_De.rc
index 9fb6be58c8d..f602a97a97d 100644
--- a/dll/win32/wininet/wininet_De.rc
+++ b/dll/win32/wininet/wininet_De.rc
@@ -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"
diff --git a/dll/win32/wininet/wininet_En.rc b/dll/win32/wininet/wininet_En.rc
index 66837dabc8e..d22d249f1cd 100644
--- a/dll/win32/wininet/wininet_En.rc
+++ b/dll/win32/wininet/wininet_En.rc
@@ -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"
diff --git a/dll/win32/wininet/wininet_Eo.rc b/dll/win32/wininet/wininet_Eo.rc
index a145e263621..3fa19f37897 100644
--- a/dll/win32/wininet/wininet_Eo.rc
+++ b/dll/win32/wininet/wininet_Eo.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Es.rc b/dll/win32/wininet/wininet_Es.rc
index bbf08aeb2f6..c9ce2cebbe2 100644
--- a/dll/win32/wininet/wininet_Es.rc
+++ b/dll/win32/wininet/wininet_Es.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Fi.rc b/dll/win32/wininet/wininet_Fi.rc
index 176a00337ce..df5ca723044 100644
--- a/dll/win32/wininet/wininet_Fi.rc
+++ b/dll/win32/wininet/wininet_Fi.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Fr.rc b/dll/win32/wininet/wininet_Fr.rc
index 0435b8eb711..74ee208a7ee 100644
--- a/dll/win32/wininet/wininet_Fr.rc
+++ b/dll/win32/wininet/wininet_Fr.rc
@@ -3,8 +3,9 @@
* French language support
*
* Copyright 2003 Mike McCormack for CodeWeavers
- * Copyright 2003 Vincent Bron
+ * 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 rseau"
+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)"
}
diff --git a/dll/win32/wininet/wininet_Hu.rc b/dll/win32/wininet/wininet_Hu.rc
index c9704f9080b..b19e03dc007 100644
--- a/dll/win32/wininet/wininet_Hu.rc
+++ b/dll/win32/wininet/wininet_Hu.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_It.rc b/dll/win32/wininet/wininet_It.rc
index 45045460c33..04f71c5f177 100644
--- a/dll/win32/wininet/wininet_It.rc
+++ b/dll/win32/wininet/wininet_It.rc
@@ -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"
diff --git a/dll/win32/wininet/wininet_Ja.rc b/dll/win32/wininet/wininet_Ja.rc
index 615d7be1c86..e179b849254 100644
--- a/dll/win32/wininet/wininet_Ja.rc
+++ b/dll/win32/wininet/wininet_Ja.rc
@@ -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)
diff --git a/dll/win32/wininet/wininet_Ko.rc b/dll/win32/wininet/wininet_Ko.rc
index 26ed4a2fad2..5c2595a9b37 100644
--- a/dll/win32/wininet/wininet_Ko.rc
+++ b/dll/win32/wininet/wininet_Ko.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Lt.rc b/dll/win32/wininet/wininet_Lt.rc
new file mode 100644
index 00000000000..cd4bf482e35
--- /dev/null
+++ b/dll/win32/wininet/wininet_Lt.rc
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2009 Aurimas Fišeras
+ *
+ * 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"
+}
diff --git a/dll/win32/wininet/wininet_Nl.rc b/dll/win32/wininet/wininet_Nl.rc
index 16c80ccaad8..f0e891c7e19 100644
--- a/dll/win32/wininet/wininet_Nl.rc
+++ b/dll/win32/wininet/wininet_Nl.rc
@@ -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"
diff --git a/dll/win32/wininet/wininet_No.rc b/dll/win32/wininet/wininet_No.rc
index fb885e9030d..1dfa544e4aa 100644
--- a/dll/win32/wininet/wininet_No.rc
+++ b/dll/win32/wininet/wininet_No.rc
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Alexander N. Srnes
+ * Copyright 2005-2009 Alexander N. Sørnes
*
* 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 "Omrde", -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"
diff --git a/dll/win32/wininet/wininet_Pl.rc b/dll/win32/wininet/wininet_Pl.rc
index 7ddb399a584..0c76d5335aa 100644
--- a/dll/win32/wininet/wininet_Pl.rc
+++ b/dll/win32/wininet/wininet_Pl.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Pt.rc b/dll/win32/wininet/wininet_Pt.rc
index 57dd625a740..95e06e6d6e8 100644
--- a/dll/win32/wininet/wininet_Pt.rc
+++ b/dll/win32/wininet/wininet_Pt.rc
@@ -1,6 +1,7 @@
/*
* Copyright 2003 Marcelo Duarte
- * Copyright 2006-2007 Amrico 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 usurio 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 "Usurio", -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 "Conexo LAN"
+ IDS_LANCONNECTION "Conexão LAN"
}
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE
STRINGTABLE DISCARDABLE
{
- IDS_LANCONNECTION "Ligao LAN"
+ IDS_LANCONNECTION "Ligação LAN"
}
diff --git a/dll/win32/wininet/wininet_Ro.rc b/dll/win32/wininet/wininet_Ro.rc
index 367bbb5955a..13403eec1a6 100644
--- a/dll/win32/wininet/wininet_Ro.rc
+++ b/dll/win32/wininet/wininet_Ro.rc
@@ -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)
diff --git a/dll/win32/wininet/wininet_Ru.rc b/dll/win32/wininet/wininet_Ru.rc
index d75985ba1b7..8d35fe40aab 100644
--- a/dll/win32/wininet/wininet_Ru.rc
+++ b/dll/win32/wininet/wininet_Ru.rc
@@ -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 "Сетевое подключение"
}
diff --git a/dll/win32/wininet/wininet_Si.rc b/dll/win32/wininet/wininet_Si.rc
index 93ac9e1f33b..b5bf2914328 100644
--- a/dll/win32/wininet/wininet_Si.rc
+++ b/dll/win32/wininet/wininet_Si.rc
@@ -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)
diff --git a/dll/win32/wininet/wininet_Sv.rc b/dll/win32/wininet/wininet_Sv.rc
index 6d71f2ef842..8d3291ec750 100644
--- a/dll/win32/wininet/wininet_Sv.rc
+++ b/dll/win32/wininet/wininet_Sv.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Tr.rc b/dll/win32/wininet/wininet_Tr.rc
index dd796777236..8d26cf21694 100644
--- a/dll/win32/wininet/wininet_Tr.rc
+++ b/dll/win32/wininet/wininet_Tr.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Uk.rc b/dll/win32/wininet/wininet_Uk.rc
index be58bb621f2..94a9611888b 100644
--- a/dll/win32/wininet/wininet_Uk.rc
+++ b/dll/win32/wininet/wininet_Uk.rc
@@ -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
diff --git a/dll/win32/wininet/wininet_Zh.rc b/dll/win32/wininet/wininet_Zh.rc
index 4406bd87c1a..e2e36ded277 100644
--- a/dll/win32/wininet/wininet_Zh.rc
+++ b/dll/win32/wininet/wininet_Zh.rc
@@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include "resource.h"
+
/* Chinese text is encoded in UTF-8 */
#pragma code_page(65001)
@@ -74,5 +76,3 @@ STRINGTABLE DISCARDABLE
{
IDS_LANCONNECTION "局域網連接"
}
-
-#pragma code_page(default)
diff --git a/drivers/bus/acpi/acpi.rbuild b/drivers/bus/acpi/acpi.rbuild
index f2b6a13cbca..cbc124a26f5 100644
--- a/drivers/bus/acpi/acpi.rbuild
+++ b/drivers/bus/acpi/acpi.rbuild
@@ -4,6 +4,9 @@
+
+
+
diff --git a/drivers/bus/acpi/acpica/acpica.rbuild b/drivers/bus/acpi/acpica/acpica.rbuild
index b23eed8d5b2..ce6fee8791f 100644
--- a/drivers/bus/acpi/acpica/acpica.rbuild
+++ b/drivers/bus/acpi/acpica/acpica.rbuild
@@ -83,9 +83,6 @@
nsxfname.c
nsxfobj.c
-
psargs.c
psloop.c
diff --git a/drivers/bus/acpi/acpica/events/evgpe.c b/drivers/bus/acpi/acpica/events/evgpe.c
index 17738b38404..00d72e54722 100644
--- a/drivers/bus/acpi/acpica/events/evgpe.c
+++ b/drivers/bus/acpi/acpica/events/evgpe.c
@@ -505,7 +505,7 @@ AcpiEvGpeDetect (
UINT8 EnabledStatusByte;
UINT32 StatusReg;
UINT32 EnableReg;
- ACPI_CPU_FLAGS Flags;
+ //ACPI_CPU_FLAGS Flags;
UINT32 i;
UINT32 j;
@@ -524,7 +524,7 @@ AcpiEvGpeDetect (
* Note: Not necessary to obtain the hardware lock, since the GPE
* registers are owned by the GpeLock.
*/
- Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
+ //Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
/* Examine all GPE blocks attached to this interrupt level */
@@ -596,7 +596,7 @@ AcpiEvGpeDetect (
UnlockAndExit:
- AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
+ //AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
return (IntStatus);
}
diff --git a/drivers/bus/acpi/acpica/osl/osl.c b/drivers/bus/acpi/acpica/osl/osl.c
deleted file mode 100644
index a8c240a77d2..00000000000
--- a/drivers/bus/acpi/acpica/osl/osl.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/*******************************************************************************
-* *
-* ACPI Component Architecture Operating System Layer (OSL) for ReactOS *
-* *
-*******************************************************************************/
-
-#include
-
-#define NDEBUG
-#include
-
-#define NUM_SEMAPHORES 128
-
-static PKINTERRUPT AcpiInterrupt;
-static BOOLEAN AcpiInterruptHandlerRegistered = FALSE;
-static ACPI_OSD_HANDLER AcpiIrqHandler = NULL;
-static PVOID AcpiIrqContext = NULL;
-static ULONG AcpiIrqNumber = 0;
-static KDPC AcpiDpc;
-static PVOID IVTVirtualAddress = NULL;
-
-
-typedef struct semaphore_entry
-{
- UINT16 MaxUnits;
- UINT16 CurrentUnits;
- void *OsHandle;
-} SEMAPHORE_ENTRY;
-
-static SEMAPHORE_ENTRY AcpiGbl_Semaphores[NUM_SEMAPHORES];
-
-VOID NTAPI
-OslDpcStub(
- IN PKDPC Dpc,
- IN PVOID DeferredContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2)
-{
- ACPI_OSD_EXEC_CALLBACK Routine = (ACPI_OSD_EXEC_CALLBACK)SystemArgument1;
-
- DPRINT("OslDpcStub()\n");
- DPRINT("Calling [%p]([%p])\n", Routine, SystemArgument2);
- (*Routine)(SystemArgument2);
-}
-
-BOOLEAN NTAPI
-OslIsrStub(
- PKINTERRUPT Interrupt,
- PVOID ServiceContext)
-{
- INT32 Status;
-
- Status = (*AcpiIrqHandler)(AcpiIrqContext);
-
- if (ACPI_SUCCESS(Status))
- return TRUE;
- else
- return FALSE;
-}
-
-ACPI_STATUS
-AcpiOsRemoveInterruptHandler (
- UINT32 InterruptNumber,
- ACPI_OSD_HANDLER ServiceRoutine);
-
-ACPI_STATUS
-AcpiOsInitialize (void)
-{
- DPRINT("AcpiOsInitialize called\n");
-
-#ifndef NDEBUG
- /* Verboseness level of the acpica core */
- AcpiDbgLevel = 0x00FFFFFF;
- AcpiDbgLayer = 0xFFFFFFFF;
-#endif
-
- UINT32 i;
-
- for (i = 0; i < NUM_SEMAPHORES; i++)
- {
- AcpiGbl_Semaphores[i].OsHandle = NULL;
- }
-
- KeInitializeDpc(&AcpiDpc, OslDpcStub, NULL);
-
- return AE_OK;
-}
-
-ACPI_STATUS
-AcpiOsTerminate(void)
-{
- DPRINT1("AcpiOsTerminate() called\n");
-
- if (AcpiInterruptHandlerRegistered)
- AcpiOsRemoveInterruptHandler(AcpiIrqNumber, AcpiIrqHandler);
-
- return AE_OK;
-}
-
-void ACPI_INTERNAL_VAR_XFACE
-AcpiOsPrintf (
- const char *Fmt,
- ...)
-{
- va_list Args;
- va_start (Args, Fmt);
-
- AcpiOsVprintf (Fmt, Args);
-
- va_end (Args);
- return;
-}
-
-void
-AcpiOsVprintf (
- const char *Fmt,
- va_list Args)
-{
- vDbgPrintEx (-1, DPFLTR_ERROR_LEVEL, Fmt, Args);
- return;
-}
-
-void *
-AcpiOsAllocate (ACPI_SIZE size)
-{
- DPRINT("AcpiOsAllocate size %d\n",size);
- return ExAllocatePool(NonPagedPool, size);
-}
-
-void *
-AcpiOsCallocate(ACPI_SIZE size)
-{
- PVOID ptr = ExAllocatePool(NonPagedPool, size);
- if (ptr)
- memset(ptr, 0, size);
- return ptr;
-}
-
-void
-AcpiOsFree(void *ptr)
-{
- if (!ptr)
- DPRINT1("Attempt to free null pointer!!!\n");
- ExFreePool(ptr);
-}
-
-#ifndef ACPI_USE_LOCAL_CACHE
-
-void*
-AcpiOsAcquireObjectHelper (
- POOL_TYPE PoolType,
- SIZE_T NumberOfBytes,
- ULONG Tag)
-{
- void* Alloc = ExAllocatePool(PoolType, NumberOfBytes);
-
- /* acpica expects memory allocated from cache to be zeroed */
- RtlZeroMemory(Alloc,NumberOfBytes);
- return Alloc;
-}
-
-ACPI_STATUS
-AcpiOsCreateCache (
- char *CacheName,
- UINT16 ObjectSize,
- UINT16 MaxDepth,
- ACPI_CACHE_T **ReturnCache)
-{
- PNPAGED_LOOKASIDE_LIST Lookaside =
- ExAllocatePool(NonPagedPool,sizeof(NPAGED_LOOKASIDE_LIST));
-
- ExInitializeNPagedLookasideList(Lookaside,
- (PALLOCATE_FUNCTION)AcpiOsAcquireObjectHelper,// custom memory allocator
- NULL,
- 0,
- ObjectSize,
- 'IPCA',
- 0);
- *ReturnCache = (ACPI_CACHE_T *)Lookaside;
-
- DPRINT("AcpiOsCreateCache %p\n", Lookaside);
- return (AE_OK);
-}
-
-ACPI_STATUS
-AcpiOsDeleteCache (
- ACPI_CACHE_T *Cache)
-{
- DPRINT("AcpiOsDeleteCache %p\n", Cache);
- ExDeleteNPagedLookasideList(
- (PNPAGED_LOOKASIDE_LIST) Cache);
- ExFreePool(Cache);
- return (AE_OK);
-}
-
-ACPI_STATUS
-AcpiOsPurgeCache (
- ACPI_CACHE_T *Cache)
-{
- DPRINT("AcpiOsPurgeCache\n");
- /* No such functionality for LookAside lists */
- return (AE_OK);
-}
-
-void *
-AcpiOsAcquireObject (
- ACPI_CACHE_T *Cache)
-{
- PNPAGED_LOOKASIDE_LIST List = (PNPAGED_LOOKASIDE_LIST)Cache;
- DPRINT("AcpiOsAcquireObject from %p\n", Cache);
- void* ptr =
- ExAllocateFromNPagedLookasideList(List);
- ASSERT(ptr);
-
- RtlZeroMemory(ptr,List->L.Size);
- return ptr;
-}
-
-ACPI_STATUS
-AcpiOsReleaseObject (
- ACPI_CACHE_T *Cache,
- void *Object)
-{
- DPRINT("AcpiOsReleaseObject %p from %p\n",Object, Cache);
- ExFreeToNPagedLookasideList(
- (PNPAGED_LOOKASIDE_LIST)Cache,
- Object);
- return (AE_OK);
-}
-
-#endif
-
-void *
-AcpiOsMapMemory (
- ACPI_PHYSICAL_ADDRESS phys,
- ACPI_SIZE length)
-{
- PHYSICAL_ADDRESS Address;
-
- DPRINT("AcpiOsMapMemory(phys 0x%X size 0x%X)\n", (ULONG)phys, length);
- if (phys == 0x0)
- {
- IVTVirtualAddress = ExAllocatePool(NonPagedPool, length);
- return IVTVirtualAddress;
- }
-
- Address.QuadPart = (ULONG)phys;
- return MmMapIoSpace(Address, length, MmNonCached);
-}
-
-void
-AcpiOsUnmapMemory (
- void *virt,
- ACPI_SIZE length)
-{
- DPRINT("AcpiOsUnmapMemory()\n");
-
- if (virt == 0x0)
- {
- ExFreePool(IVTVirtualAddress);
- return;
- }
- MmUnmapIoSpace(virt, length);
-}
-
-UINT32
-AcpiOsInstallInterruptHandler (
- UINT32 InterruptNumber,
- ACPI_OSD_HANDLER ServiceRoutine,
- void *Context)
-{
- ULONG Vector;
- KIRQL DIrql;
- KAFFINITY Affinity;
- NTSTATUS Status;
-
- DPRINT("AcpiOsInstallInterruptHandler()\n");
- Vector = HalGetInterruptVector(
- Internal,
- 0,
- InterruptNumber,
- 0,
- &DIrql,
- &Affinity);
-
- AcpiIrqNumber = InterruptNumber;
- AcpiIrqHandler = ServiceRoutine;
- AcpiIrqContext = Context;
- AcpiInterruptHandlerRegistered = TRUE;
-
- Status = IoConnectInterrupt(
- &AcpiInterrupt,
- OslIsrStub,
- NULL,
- NULL,
- Vector,
- DIrql,
- DIrql,
- LevelSensitive, /* FIXME: LevelSensitive or Latched? */
- TRUE,
- Affinity,
- FALSE);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not connect to interrupt %d\n", Vector);
- return AE_ERROR;
- }
- return AE_OK;
-}
-
-ACPI_STATUS
-AcpiOsRemoveInterruptHandler (
- UINT32 InterruptNumber,
- ACPI_OSD_HANDLER ServiceRoutine)
-{
- DPRINT("AcpiOsRemoveInterruptHandler()\n");
- if (AcpiInterruptHandlerRegistered)
- {
- IoDisconnectInterrupt(AcpiInterrupt);
- AcpiInterrupt = NULL;
- AcpiInterruptHandlerRegistered = FALSE;
- }
-
- return AE_OK;
-}
-
-void
-AcpiOsStall (UINT32 microseconds)
-{
- DPRINT1("AcpiOsStall %d\n",microseconds);
- KeStallExecutionProcessor(microseconds);
- return;
-}
-
-void
-AcpiOsSleep (ACPI_INTEGER milliseconds)
-{
- DPRINT1("AcpiOsSleep %d\n", milliseconds);
- KeStallExecutionProcessor(milliseconds*1000);
- return;
-}
-
-ACPI_STATUS
-AcpiOsReadPort (
- ACPI_IO_ADDRESS Address,
- UINT32 *Value,
- UINT32 Width)
-{
- DPRINT("AcpiOsReadPort %p, width %d\n",Address,Width);
-
- switch (Width)
- {
- case 8:
- *Value = READ_PORT_UCHAR((PUCHAR)Address);
- break;
-
- case 16:
- *Value = READ_PORT_USHORT((PUSHORT)Address);
- break;
-
- case 32:
- *Value = READ_PORT_ULONG((PULONG)Address);
- break;
- default:
- DPRINT1("AcpiOsReadPort got bad width: %d\n",Width);
- return (AE_BAD_PARAMETER);
- break;
- }
- return (AE_OK);
-}
-
-ACPI_STATUS
-AcpiOsWritePort (
- ACPI_IO_ADDRESS Address,
- UINT32 Value,
- UINT32 Width)
-{
- DPRINT("AcpiOsWritePort %p, width %d\n",Address,Width);
- switch (Width)
- {
- case 8:
- WRITE_PORT_UCHAR((PUCHAR)Address, Value);
- break;
-
- case 16:
- WRITE_PORT_USHORT((PUSHORT)Address, Value);
- break;
-
- case 32:
- WRITE_PORT_ULONG((PULONG)Address, Value);
- break;
-
- default:
- DPRINT1("AcpiOsWritePort got bad width: %d\n",Width);
- return (AE_BAD_PARAMETER);
- break;
- }
- return (AE_OK);
-}
-
-ACPI_STATUS
-AcpiOsReadMemory (
- ACPI_PHYSICAL_ADDRESS Address,
- UINT32 *Value,
- UINT32 Width)
-{
- DPRINT("AcpiOsReadMemory %p\n", Address);
- switch (Width)
- {
- case 8:
- *Value = (*(PUCHAR)(ULONG)Address);
- break;
- case 16:
- *Value = (*(PUSHORT)(ULONG)Address);
- break;
- case 32:
- *Value = (*(PULONG)(ULONG)Address);
- break;
-
- default:
- DPRINT1("AcpiOsReadMemory got bad width: %d\n",Width);
- return (AE_BAD_PARAMETER);
- break;
- }
- return (AE_OK);
-}
-
-
-ACPI_STATUS
-AcpiOsWriteMemory (
- ACPI_PHYSICAL_ADDRESS Address,
- UINT32 Value,
- UINT32 Width)
-{
- DPRINT("AcpiOsWriteMemory %p\n", Address);
- switch (Width)
- {
- case 8:
- *(PUCHAR)(ULONG)Address = Value;
- break;
- case 16:
- *(PUSHORT)(ULONG)Address = Value;
- break;
- case 32:
- *(PULONG)(ULONG)Address = Value;
- break;
-
- default:
- DPRINT1("AcpiOsWriteMemory got bad width: %d\n",Width);
- return (AE_BAD_PARAMETER);
- break;
- }
-
- return (AE_OK);
-}
-
-ACPI_STATUS
-AcpiOsReadPciConfiguration (
- ACPI_PCI_ID *PciId,
- UINT32 Register,
- void *Value,
- UINT32 Width)
-{
- NTSTATUS Status;
- PCI_SLOT_NUMBER slot;
-
- if (Register == 0)
- return AE_ERROR;
-
- slot.u.AsULONG = 0;
- slot.u.bits.DeviceNumber = PciId->Bus;
- slot.u.bits.FunctionNumber = PciId->Function;
-
- DPRINT("AcpiOsReadPciConfiguration, slot=0x%X, func=0x%X\n", slot.u.AsULONG, Register);
- Status = HalGetBusDataByOffset(PCIConfiguration,
- PciId->Bus,
- slot.u.AsULONG,
- Value,
- Register,
- Width);
-
- if (NT_SUCCESS(Status))
- return AE_OK;
- else
- return AE_ERROR;
-}
-
-ACPI_STATUS
-AcpiOsWritePciConfiguration (
- ACPI_PCI_ID *PciId,
- UINT32 Register,
- ACPI_INTEGER Value,
- UINT32 Width)
-{
- NTSTATUS Status;
- ULONG buf = Value;
- PCI_SLOT_NUMBER slot;
-
- if (Register == 0)
- return AE_ERROR;
-
- slot.u.AsULONG = 0;
- slot.u.bits.DeviceNumber = PciId->Bus;
- slot.u.bits.FunctionNumber = PciId->Function;
-
- DPRINT("AcpiOsWritePciConfiguration, slot=0x%x\n", slot.u.AsULONG);
- Status = HalSetBusDataByOffset(PCIConfiguration,
- PciId->Bus,
- slot.u.AsULONG,
- &buf,
- Register,
- Width);
-
- if (NT_SUCCESS(Status))
- return AE_OK;
- else
- return AE_ERROR;
-}
-
-ACPI_STATUS
-AcpiOsCreateSemaphore (
- UINT32 MaxUnits,
- UINT32 InitialUnits,
- ACPI_SEMAPHORE *OutHandle)
-{
- PFAST_MUTEX Mutex;
-
- Mutex = ExAllocatePool(NonPagedPool, sizeof(FAST_MUTEX));
- if (!Mutex)
- return AE_NO_MEMORY;
-
- DPRINT("AcpiOsCreateSemaphore() at 0x%X\n", Mutex);
-
- ExInitializeFastMutex(Mutex);
-
- *OutHandle = Mutex;
- return AE_OK;
-}
-
-ACPI_STATUS
-AcpiOsDeleteSemaphore (
- ACPI_SEMAPHORE Handle)
-{
- PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
-
- DPRINT("AcpiOsDeleteSemaphore(handle 0x%X)\n", Handle);
-
- if (!Mutex)
- return AE_BAD_PARAMETER;
-
- ExFreePool(Mutex);
- return AE_OK;
-}
-
-ACPI_STATUS
-AcpiOsWaitSemaphore(
- ACPI_SEMAPHORE Handle,
- UINT32 units,
- UINT16 timeout)
-{
- PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
-
- if (!Mutex || (units < 1))
- {
- DPRINT("AcpiOsWaitSemaphore(handle 0x%X, units %d) Bad parameters\n",
- Mutex, units);
- return AE_BAD_PARAMETER;
- }
-
- DPRINT("Waiting for semaphore %p\n", Handle);
- ASSERT(Mutex);
-
- ExAcquireFastMutex(Mutex);
- return AE_OK;
-}
-
-ACPI_STATUS
-AcpiOsSignalSemaphore (
- ACPI_HANDLE Handle,
- UINT32 Units)
-{
- PFAST_MUTEX Mutex = (PFAST_MUTEX)Handle;
-
- DPRINT("AcpiOsSignalSemaphore %p\n",Handle);
- ASSERT(Mutex);
-
- ExReleaseFastMutex(Mutex);
- return AE_OK;
-}
-
-ACPI_STATUS
-AcpiOsCreateLock (
- ACPI_SPINLOCK *OutHandle)
-{
- DPRINT("AcpiOsCreateLock\n");
- return (AcpiOsCreateSemaphore (1, 1, OutHandle));
-}
-
-void
-AcpiOsDeleteLock (
- ACPI_SPINLOCK Handle)
-{
- DPRINT("AcpiOsDeleteLock %p\n", Handle);
- AcpiOsDeleteSemaphore (Handle);
-}
-
-
-ACPI_CPU_FLAGS
-AcpiOsAcquireLock (
- ACPI_HANDLE Handle)
-{
- DPRINT("AcpiOsAcquireLock, %p\n", Handle);
- AcpiOsWaitSemaphore (Handle, 1, 0xFFFF);
- return (0);
-}
-
-
-void
-AcpiOsReleaseLock (
- ACPI_SPINLOCK Handle,
- ACPI_CPU_FLAGS Flags)
-{
- DPRINT("AcpiOsReleaseLock %p\n",Handle);
- AcpiOsSignalSemaphore (Handle, 1);
-}
-
-ACPI_STATUS
-AcpiOsSignal (
- UINT32 Function,
- void *Info)
-{
-
- switch (Function)
- {
- case ACPI_SIGNAL_FATAL:
- if (Info)
- AcpiOsPrintf ("AcpiOsBreakpoint: %s ****\n", Info);
- else
- AcpiOsPrintf ("AcpiOsBreakpoint ****\n");
- break;
- case ACPI_SIGNAL_BREAKPOINT:
- if (Info)
- AcpiOsPrintf ("AcpiOsBreakpoint: %s ****\n", Info);
- else
- AcpiOsPrintf ("AcpiOsBreakpoint ****\n");
- break;
- }
-
- return (AE_OK);
-}
-
-
-ACPI_THREAD_ID
-AcpiOsGetThreadId (void)
-{
- return (ULONG)PsGetCurrentThreadId();
-}
-
-ACPI_STATUS
-AcpiOsExecute (
- ACPI_EXECUTE_TYPE Type,
- ACPI_OSD_EXEC_CALLBACK Function,
- void *Context)
-{
- DPRINT1("AcpiOsExecute\n");
-
- KeInsertQueueDpc(&AcpiDpc, (PVOID)Function, (PVOID)Context);
-
-#ifdef _MULTI_THREADED
- //_beginthread (Function, (unsigned) 0, Context);
-#endif
-
- return 0;
-}
-
-UINT64
-AcpiOsGetTimer (void)
-{
- DPRINT("AcpiOsGetTimer\n");
- LARGE_INTEGER Timer;
- KeQueryTickCount(&Timer);
-
- return Timer.QuadPart;
-}
-
-void
-AcpiOsDerivePciId(
- ACPI_HANDLE rhandle,
- ACPI_HANDLE chandle,
- ACPI_PCI_ID **PciId)
-{
- DPRINT("AcpiOsDerivePciId\n");
- return;
-}
-
-ACPI_STATUS
-AcpiOsPredefinedOverride (
- const ACPI_PREDEFINED_NAMES *InitVal,
- ACPI_STRING *NewVal)
-{
- if (!InitVal || !NewVal)
- return AE_BAD_PARAMETER;
-
- *NewVal = ACPI_OS_NAME;
- DPRINT("AcpiOsPredefinedOverride\n");
- return AE_OK;
-}
-
-ACPI_PHYSICAL_ADDRESS
-AcpiOsGetRootPointer (
- void);
-
-ACPI_STATUS
-AcpiOsTableOverride (
- ACPI_TABLE_HEADER *ExistingTable,
- ACPI_TABLE_HEADER **NewTable)
-{
- DPRINT("AcpiOsTableOverride\n");
- *NewTable = NULL;
- return (AE_OK);
-}
-
-ACPI_STATUS
-AcpiOsValidateInterface (
- char *Interface)
-{
- DPRINT("AcpiOsValidateInterface\n");
- return (AE_OK);
-}
-
-ACPI_STATUS
-AcpiOsValidateAddress (
- UINT8 SpaceId,
- ACPI_PHYSICAL_ADDRESS Address,
- ACPI_SIZE Length)
-{
- DPRINT("AcpiOsValidateAddress\n");
- return (AE_OK);
-}
-
-ACPI_PHYSICAL_ADDRESS
-AcpiOsGetRootPointer (
- void)
-{
- DPRINT("AcpiOsGetRootPointer\n");
- ACPI_PHYSICAL_ADDRESS pa = 0;
-
- AcpiFindRootPointer(&pa);
- return pa;
-}
diff --git a/drivers/bus/acpi/acpienum.c b/drivers/bus/acpi/acpienum.c
index 50ab9eeee4b..c011dbadd63 100644
--- a/drivers/bus/acpi/acpienum.c
+++ b/drivers/bus/acpi/acpienum.c
@@ -13,7 +13,7 @@
#include
#include
-//#define NDEBUG
+#define NDEBUG
#include
#define HAS_CHILDREN(d) ((d)->children.next != &((d)->children))
@@ -37,6 +37,10 @@ Bus_PlugInDevice (
PAGED_CODE ();
+ //Don't enumerate the root device
+ if (Device->handle == ACPI_ROOT_OBJECT)
+ return STATUS_SUCCESS;
+
/* Check we didnt add this already */
for (entry = FdoData->ListOfPDOs.Flink;
entry != &FdoData->ListOfPDOs; entry = entry->Flink)
diff --git a/drivers/bus/acpi/busmgr/bus.c b/drivers/bus/acpi/busmgr/bus.c
index 949cfd2bd65..34aa0766c04 100644
--- a/drivers/bus/acpi/busmgr/bus.c
+++ b/drivers/bus/acpi/busmgr/bus.c
@@ -34,7 +34,7 @@
#include
#include
-//#define NDEBUG
+#define NDEBUG
#include
#define _COMPONENT ACPI_BUS_COMPONENT
diff --git a/drivers/bus/acpi/busmgr/power.c b/drivers/bus/acpi/busmgr/power.c
index 6c6bc0814bf..77a37198ed7 100644
--- a/drivers/bus/acpi/busmgr/power.c
+++ b/drivers/bus/acpi/busmgr/power.c
@@ -46,7 +46,7 @@
#include
#include
-//#define NDEBUG
+#define NDEBUG
#include
diff --git a/drivers/bus/acpi/busmgr/system.c b/drivers/bus/acpi/busmgr/system.c
index d0f0503f366..ca5a0852bf9 100644
--- a/drivers/bus/acpi/busmgr/system.c
+++ b/drivers/bus/acpi/busmgr/system.c
@@ -32,7 +32,7 @@
#include
#include "list.h"
-//#define NDEBUG
+#define NDEBUG
#include
ACPI_STATUS acpi_system_save_state(UINT32);
diff --git a/drivers/bus/acpi/busmgr/utils.c b/drivers/bus/acpi/busmgr/utils.c
index 67eaed017ca..2a82e49604c 100644
--- a/drivers/bus/acpi/busmgr/utils.c
+++ b/drivers/bus/acpi/busmgr/utils.c
@@ -30,7 +30,7 @@
#include
#include
-//#define NDEBUG
+#define NDEBUG
#include
/* Modified for ReactOS and latest ACPICA
diff --git a/drivers/bus/acpi/buspdo.c b/drivers/bus/acpi/buspdo.c
index eb8f6686086..4a9498e7ad4 100644
--- a/drivers/bus/acpi/buspdo.c
+++ b/drivers/bus/acpi/buspdo.c
@@ -8,7 +8,7 @@
#include
#include
-//#define NDEBUG
+#define NDEBUG
#include
#ifdef ALLOC_PRAGMA
@@ -325,6 +325,7 @@ Bus_PDO_QueryDeviceCaps(
deviceCapabilities->UniqueID = device->flags.unique_id;
deviceCapabilities->NoDisplayInUI = !device->status.show_in_ui;
deviceCapabilities->Address = device->pnp.bus_address;
+ deviceCapabilities->RawDeviceOK = FALSE;
}
else
{
@@ -335,6 +336,9 @@ Bus_PDO_QueryDeviceCaps(
deviceCapabilities->UniqueID = FALSE;
deviceCapabilities->NoDisplayInUI = FALSE;
deviceCapabilities->Address = 0;
+
+ /* The ACPI driver will run fixed buttons */
+ deviceCapabilities->RawDeviceOK = TRUE;
}
deviceCapabilities->SilentInstall = FALSE;
@@ -548,8 +552,6 @@ Bus_PDO_QueryDeviceText(
Buffer = L"ACPI Power Resource";
else if (wcsstr(DeviceData->HardwareIDs, L"Processor") != 0)
Buffer = L"Processor";
- else if (wcsstr(DeviceData->HardwareIDs, L"ACPI_SYS") != 0)
- Buffer = L"ACPI System";
else if (wcsstr(DeviceData->HardwareIDs, L"ThermalZone") != 0)
Buffer = L"ACPI Thermal Zone";
else if (wcsstr(DeviceData->HardwareIDs, L"ACPI0002") != 0)
@@ -621,6 +623,12 @@ Bus_PDO_QueryResources(
{
switch (resource->Type)
{
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ {
+ ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
+ NumberOfResources += irq_data->InterruptCount;
+ break;
+ }
case ACPI_RESOURCE_TYPE_IRQ:
{
ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
@@ -633,6 +641,12 @@ Bus_PDO_QueryResources(
NumberOfResources += dma_data->ChannelCount;
break;
}
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ case ACPI_RESOURCE_TYPE_MEMORY32:
case ACPI_RESOURCE_TYPE_IO:
{
NumberOfResources++;
@@ -665,10 +679,30 @@ Bus_PDO_QueryResources(
ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
/* Fill resources list structure */
+ resource = Buffer.Pointer;
while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
{
switch (resource->Type)
{
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ {
+ ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
+ for (i = 0; i < irq_data->InterruptCount; i++)
+ {
+ ResourceDescriptor->Type = CmResourceTypeInterrupt;
+
+ ResourceDescriptor->ShareDisposition =
+ (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
+ ResourceDescriptor->Flags =
+ (irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
+ ResourceDescriptor->u.Interrupt.Level = irq_data->Interrupts[i];
+ ResourceDescriptor->u.Interrupt.Vector = 0;
+ ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1);
+
+ ResourceDescriptor++;
+ }
+ break;
+ }
case ACPI_RESOURCE_TYPE_IRQ:
{
ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
@@ -725,13 +759,214 @@ Bus_PDO_QueryResources(
ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
else
ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
- ResourceDescriptor->u.Port.Start.u.HighPart = 0;
- ResourceDescriptor->u.Port.Start.u.LowPart = io_data->Minimum;
+ ResourceDescriptor->u.Port.Start.QuadPart = io_data->Minimum;
ResourceDescriptor->u.Port.Length = io_data->AddressLength;
ResourceDescriptor++;
break;
}
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ {
+ ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
+ if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
+ {
+ ResourceDescriptor->Type = CmResourceTypeBusNumber;
+ ResourceDescriptor->ShareDisposition = CmResourceShareShared;
+ ResourceDescriptor->Flags = 0;
+ ResourceDescriptor->u.BusNumber.Start = addr16_data->Minimum;
+ ResourceDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
+ }
+ else if (addr16_data->ResourceType == ACPI_IO_RANGE)
+ {
+ ResourceDescriptor->Type = CmResourceTypePort;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ if (addr16_data->Decode == ACPI_POS_DECODE)
+ ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
+ ResourceDescriptor->u.Port.Start.QuadPart = addr16_data->Minimum;
+ ResourceDescriptor->u.Port.Length = addr16_data->AddressLength;
+ }
+ else
+ {
+ ResourceDescriptor->Type = CmResourceTypeMemory;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = 0;
+ if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ switch (addr16_data->Info.Mem.Caching)
+ {
+ case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
+ case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
+ case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
+ }
+ ResourceDescriptor->u.Memory.Start.QuadPart = addr16_data->Minimum;
+ ResourceDescriptor->u.Memory.Length = addr16_data->AddressLength;
+ }
+ ResourceDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ {
+ ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
+ if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
+ {
+ ResourceDescriptor->Type = CmResourceTypeBusNumber;
+ ResourceDescriptor->ShareDisposition = CmResourceShareShared;
+ ResourceDescriptor->Flags = 0;
+ ResourceDescriptor->u.BusNumber.Start = addr32_data->Minimum;
+ ResourceDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
+ }
+ else if (addr32_data->ResourceType == ACPI_IO_RANGE)
+ {
+ ResourceDescriptor->Type = CmResourceTypePort;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ if (addr32_data->Decode == ACPI_POS_DECODE)
+ ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
+ ResourceDescriptor->u.Port.Start.QuadPart = addr32_data->Minimum;
+ ResourceDescriptor->u.Port.Length = addr32_data->AddressLength;
+ }
+ else
+ {
+ ResourceDescriptor->Type = CmResourceTypeMemory;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = 0;
+ if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ switch (addr32_data->Info.Mem.Caching)
+ {
+ case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
+ case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
+ case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
+ }
+ ResourceDescriptor->u.Memory.Start.QuadPart = addr32_data->Minimum;
+ ResourceDescriptor->u.Memory.Length = addr32_data->AddressLength;
+ }
+ ResourceDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ {
+ ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
+ if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
+ {
+ DPRINT1("64-bit bus address is not supported!\n");
+ ResourceDescriptor->Type = CmResourceTypeBusNumber;
+ ResourceDescriptor->ShareDisposition = CmResourceShareShared;
+ ResourceDescriptor->Flags = 0;
+ ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Minimum;
+ ResourceDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
+ }
+ else if (addr64_data->ResourceType == ACPI_IO_RANGE)
+ {
+ ResourceDescriptor->Type = CmResourceTypePort;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ if (addr64_data->Decode == ACPI_POS_DECODE)
+ ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
+ ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Minimum;
+ ResourceDescriptor->u.Port.Length = addr64_data->AddressLength;
+ }
+ else
+ {
+ ResourceDescriptor->Type = CmResourceTypeMemory;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = 0;
+ if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ switch (addr64_data->Info.Mem.Caching)
+ {
+ case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
+ case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
+ case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
+ }
+ ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Minimum;
+ ResourceDescriptor->u.Memory.Length = addr64_data->AddressLength;
+ }
+ ResourceDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ {
+ ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
+ if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
+ {
+ DPRINT1("64-bit bus address is not supported!\n");
+ ResourceDescriptor->Type = CmResourceTypeBusNumber;
+ ResourceDescriptor->ShareDisposition = CmResourceShareShared;
+ ResourceDescriptor->Flags = 0;
+ ResourceDescriptor->u.BusNumber.Start = (ULONG)addr64_data->Minimum;
+ ResourceDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
+ }
+ else if (addr64_data->ResourceType == ACPI_IO_RANGE)
+ {
+ ResourceDescriptor->Type = CmResourceTypePort;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ if (addr64_data->Decode == ACPI_POS_DECODE)
+ ResourceDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
+ ResourceDescriptor->u.Port.Start.QuadPart = addr64_data->Minimum;
+ ResourceDescriptor->u.Port.Length = addr64_data->AddressLength;
+ }
+ else
+ {
+ ResourceDescriptor->Type = CmResourceTypeMemory;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = 0;
+ if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ switch (addr64_data->Info.Mem.Caching)
+ {
+ case ACPI_CACHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
+ case ACPI_WRITE_COMBINING_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
+ case ACPI_PREFETCHABLE_MEMORY: ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
+ }
+ ResourceDescriptor->u.Memory.Start.QuadPart = addr64_data->Minimum;
+ ResourceDescriptor->u.Memory.Length = addr64_data->AddressLength;
+ }
+ ResourceDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ {
+ ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
+ ResourceDescriptor->Type = CmResourceTypeMemory;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_24;
+ if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ ResourceDescriptor->u.Memory.Start.QuadPart = mem24_data->Minimum;
+ ResourceDescriptor->u.Memory.Length = mem24_data->AddressLength;
+
+ ResourceDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+ {
+ ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
+ ResourceDescriptor->Type = CmResourceTypeMemory;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ ResourceDescriptor->Flags = 0;
+ if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ ResourceDescriptor->u.Memory.Start.QuadPart = mem32_data->Minimum;
+ ResourceDescriptor->u.Memory.Length = mem32_data->AddressLength;
+
+ ResourceDescriptor++;
+ break;
+ }
default:
{
break;
@@ -803,6 +1038,12 @@ Bus_PDO_QueryResourceRequirements(
{
switch (resource->Type)
{
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ {
+ ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
+ NumberOfResources += irq_data->InterruptCount;
+ break;
+ }
case ACPI_RESOURCE_TYPE_IRQ:
{
ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
@@ -815,6 +1056,12 @@ Bus_PDO_QueryResourceRequirements(
NumberOfResources += dma_data->ChannelCount;
break;
}
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ case ACPI_RESOURCE_TYPE_MEMORY32:
case ACPI_RESOURCE_TYPE_IO:
{
NumberOfResources++;
@@ -847,10 +1094,27 @@ Bus_PDO_QueryResourceRequirements(
RequirementDescriptor = RequirementsList->List[0].Descriptors;
/* Fill resources list structure */
+ resource = Buffer.Pointer;
while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG)
{
switch (resource->Type)
{
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ {
+ ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*) &resource->Data;
+ for (i = 0; i < irq_data->InterruptCount; i++)
+ {
+ RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
+ RequirementDescriptor->Type = CmResourceTypeInterrupt;
+ RequirementDescriptor->ShareDisposition = (irq_data->Sharable == ACPI_SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
+ RequirementDescriptor->Flags =(irq_data->Triggering == ACPI_LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
+ RequirementDescriptor->u.Interrupt.MinimumVector =
+ RequirementDescriptor->u.Interrupt.MaximumVector = irq_data->Interrupts[i];
+
+ RequirementDescriptor++;
+ }
+ break;
+ }
case ACPI_RESOURCE_TYPE_IRQ:
{
ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*) &resource->Data;
@@ -905,9 +1169,7 @@ Bus_PDO_QueryResourceRequirements(
RequirementDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
else
RequirementDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
-
RequirementDescriptor->u.Port.Length = io_data->AddressLength;
-
RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
RequirementDescriptor->Type = CmResourceTypePort;
RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
@@ -918,6 +1180,228 @@ Bus_PDO_QueryResourceRequirements(
RequirementDescriptor++;
break;
}
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ {
+ ACPI_RESOURCE_ADDRESS16 *addr16_data = (ACPI_RESOURCE_ADDRESS16*) &resource->Data;
+ RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
+ if (addr16_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
+ {
+ RequirementDescriptor->Type = CmResourceTypeBusNumber;
+ RequirementDescriptor->ShareDisposition = CmResourceShareShared;
+ RequirementDescriptor->Flags = 0;
+ RequirementDescriptor->u.BusNumber.MinBusNumber = addr16_data->Minimum;
+ RequirementDescriptor->u.BusNumber.MaxBusNumber = addr16_data->Maximum;
+ RequirementDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
+ }
+ else if (addr16_data->ResourceType == ACPI_IO_RANGE)
+ {
+ RequirementDescriptor->Type = CmResourceTypePort;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ if (addr16_data->Decode == ACPI_POS_DECODE)
+ RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
+ RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr16_data->Minimum;
+ RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr16_data->Maximum;
+ RequirementDescriptor->u.Port.Length = addr16_data->AddressLength;
+ }
+ else
+ {
+ RequirementDescriptor->Type = CmResourceTypeMemory;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = 0;
+ if (addr16_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ switch (addr16_data->Info.Mem.Caching)
+ {
+ case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
+ case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
+ case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
+ }
+ RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr16_data->Minimum;
+ RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr16_data->Maximum;
+ RequirementDescriptor->u.Memory.Length = addr16_data->AddressLength;
+ }
+ RequirementDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ {
+ ACPI_RESOURCE_ADDRESS32 *addr32_data = (ACPI_RESOURCE_ADDRESS32*) &resource->Data;
+ RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
+ if (addr32_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
+ {
+ RequirementDescriptor->Type = CmResourceTypeBusNumber;
+ RequirementDescriptor->ShareDisposition = CmResourceShareShared;
+ RequirementDescriptor->Flags = 0;
+ RequirementDescriptor->u.BusNumber.MinBusNumber = addr32_data->Minimum;
+ RequirementDescriptor->u.BusNumber.MaxBusNumber = addr32_data->Maximum;
+ RequirementDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
+ }
+ else if (addr32_data->ResourceType == ACPI_IO_RANGE)
+ {
+ RequirementDescriptor->Type = CmResourceTypePort;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ if (addr32_data->Decode == ACPI_POS_DECODE)
+ RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
+ RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr32_data->Minimum;
+ RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr32_data->Maximum;
+ RequirementDescriptor->u.Port.Length = addr32_data->AddressLength;
+ }
+ else
+ {
+ RequirementDescriptor->Type = CmResourceTypeMemory;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = 0;
+ if (addr32_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ switch (addr32_data->Info.Mem.Caching)
+ {
+ case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
+ case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
+ case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
+ }
+ RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr32_data->Minimum;
+ RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr32_data->Maximum;
+ RequirementDescriptor->u.Memory.Length = addr32_data->AddressLength;
+ }
+ RequirementDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ {
+ ACPI_RESOURCE_ADDRESS64 *addr64_data = (ACPI_RESOURCE_ADDRESS64*) &resource->Data;
+ RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
+ if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
+ {
+ DPRINT1("64-bit bus address is not supported!\n");
+ RequirementDescriptor->Type = CmResourceTypeBusNumber;
+ RequirementDescriptor->ShareDisposition = CmResourceShareShared;
+ RequirementDescriptor->Flags = 0;
+ RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
+ RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum;
+ RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
+ }
+ else if (addr64_data->ResourceType == ACPI_IO_RANGE)
+ {
+ RequirementDescriptor->Type = CmResourceTypePort;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ if (addr64_data->Decode == ACPI_POS_DECODE)
+ RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
+ RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
+ RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum;
+ RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
+ }
+ else
+ {
+ RequirementDescriptor->Type = CmResourceTypeMemory;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = 0;
+ if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ switch (addr64_data->Info.Mem.Caching)
+ {
+ case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
+ case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
+ case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
+ }
+ RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
+ RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum;
+ RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
+ }
+ RequirementDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ {
+ ACPI_RESOURCE_EXTENDED_ADDRESS64 *addr64_data = (ACPI_RESOURCE_EXTENDED_ADDRESS64*) &resource->Data;
+ RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
+ if (addr64_data->ResourceType == ACPI_BUS_NUMBER_RANGE)
+ {
+ DPRINT1("64-bit bus address is not supported!\n");
+ RequirementDescriptor->Type = CmResourceTypeBusNumber;
+ RequirementDescriptor->ShareDisposition = CmResourceShareShared;
+ RequirementDescriptor->Flags = 0;
+ RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
+ RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum;
+ RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
+ }
+ else if (addr64_data->ResourceType == ACPI_IO_RANGE)
+ {
+ RequirementDescriptor->Type = CmResourceTypePort;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ if (addr64_data->Decode == ACPI_POS_DECODE)
+ RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
+ RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
+ RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum;
+ RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
+ }
+ else
+ {
+ RequirementDescriptor->Type = CmResourceTypeMemory;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = 0;
+ if (addr64_data->Info.Mem.WriteProtect == ACPI_READ_ONLY_MEMORY)
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ switch (addr64_data->Info.Mem.Caching)
+ {
+ case ACPI_CACHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_CACHEABLE; break;
+ case ACPI_WRITE_COMBINING_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_COMBINEDWRITE; break;
+ case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
+ }
+ RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
+ RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum;
+ RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
+ }
+ RequirementDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ {
+ ACPI_RESOURCE_MEMORY24 *mem24_data = (ACPI_RESOURCE_MEMORY24*) &resource->Data;
+ RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
+ RequirementDescriptor->Type = CmResourceTypeMemory;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = CM_RESOURCE_MEMORY_24;
+ if (mem24_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem24_data->Minimum;
+ RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem24_data->Maximum;
+ RequirementDescriptor->u.Memory.Length = mem24_data->AddressLength;
+
+ RequirementDescriptor++;
+ break;
+ }
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+ {
+ ACPI_RESOURCE_MEMORY32 *mem32_data = (ACPI_RESOURCE_MEMORY32*) &resource->Data;
+ RequirementDescriptor->Option = CurrentRes ? 0 : IO_RESOURCE_PREFERRED;
+ RequirementDescriptor->Type = CmResourceTypeMemory;
+ RequirementDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ RequirementDescriptor->Flags = 0;
+ if (mem32_data->WriteProtect == ACPI_READ_ONLY_MEMORY)
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
+ else
+ RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
+ RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem32_data->Minimum;
+ RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem32_data->Maximum;
+ RequirementDescriptor->u.Memory.Length = mem32_data->AddressLength;
+
+ RequirementDescriptor++;
+ break;
+ }
default:
{
break;
diff --git a/drivers/bus/acpi/cmbatt/cmbatt.c b/drivers/bus/acpi/cmbatt/cmbatt.c
new file mode 100644
index 00000000000..1957597a678
--- /dev/null
+++ b/drivers/bus/acpi/cmbatt/cmbatt.c
@@ -0,0 +1,149 @@
+/*
+ * PROJECT: ReactOS ACPI-Compliant Control Method Battery
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: boot/drivers/bus/acpi/cmbatt/cmbatt.c
+ * PURPOSE: Main Initialization Code and IRP Handling
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "cmbatt.h"
+
+/* GLOBALS ********************************************************************/
+
+ULONG CmBattDebug;
+
+/* FUNCTIONS ******************************************************************/
+
+VOID
+NTAPI
+CmBattPowerCallBack(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ PVOID Argument1,
+ PVOID Argument2)
+{
+ UNIMPLEMENTED;
+}
+
+VOID
+NTAPI
+CmBattWakeDpc(PKDPC Dpc,
+ PCMBATT_DEVICE_EXTENSION FdoExtension,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2)
+{
+ UNIMPLEMENTED;
+}
+
+VOID
+NTAPI
+CmBattNotifyHandler(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ ULONG NotifyValue)
+{
+ UNIMPLEMENTED;
+}
+
+VOID
+NTAPI
+CmBattUnload(PDEVICE_OBJECT DeviceObject)
+{
+ UNIMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattVerifyStaticInfo(ULONG StaData,
+ ULONG BatteryTag)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattOpenClose(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattIoctl(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattQueryTag(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ PULONG BatteryTag)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattDisableStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattSetStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ ULONG BatteryTag,
+ PBATTERY_NOTIFY BatteryNotify)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattGetBatteryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ ULONG BatteryTag)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattQueryInformation(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ ULONG BatteryTag,
+ BATTERY_QUERY_INFORMATION_LEVEL Level,
+ OPTIONAL LONG AtRate,
+ PVOID Buffer,
+ ULONG BufferLength,
+ PULONG ReturnedLength)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattQueryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ ULONG BatteryTag,
+ PBATTERY_STATUS BatteryStatus)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/* EOF */
diff --git a/drivers/bus/acpi/cmbatt/cmbatt.h b/drivers/bus/acpi/cmbatt/cmbatt.h
new file mode 100644
index 00000000000..0443c4c86bb
--- /dev/null
+++ b/drivers/bus/acpi/cmbatt/cmbatt.h
@@ -0,0 +1,105 @@
+/*
+ * PROJECT: ReactOS ACPI-Compliant Control Method Battery
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: boot/drivers/bus/acpi/cmbatt/cmbatt.h
+ * PURPOSE: Main Header File
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define CMBATT_GENERIC_STATUS 0x01
+#define CMBATT_GENERIC_INFO 0x02
+#define CMBATT_GENERIC_WARNING 0x04
+#define CMBATT_ACPI_WARNING 0x08
+#define CMBATT_POWER_INFO 0x10
+#define CMBATT_PNP_INFO 0x20
+#define CMBATT_ACPI_ENTRY_EXIT 0x40
+#define CMBATT_PNP_ENTRY_EXIT 0x200
+#define CMBATT_ACPI_ASSERT 0x400
+
+typedef enum _CMBATT_EXTENSION_TYPE
+{
+ CmBattAcAdapter,
+ CmBattBattery
+} CMBATT_EXTENSION_TYPE;
+
+typedef struct _ACPI_BST_DATA
+{
+ ULONG State;
+ ULONG PresentRate;
+ ULONG RemainingCapacity;
+ ULONG PresentVoltage;
+} ACPI_BST_DATA, *PACPI_BST_DATA;
+
+typedef struct _ACPI_BIF_DATA
+{
+ ULONG PowerUnit;
+ ULONG DesignCapacity;
+ ULONG LastFullCapacity;
+ ULONG BatteryTechnology;
+ ULONG DesignVoltage;
+ ULONG DesignCapacityWarning;
+ ULONG DesignCapacityLow;
+ ULONG BatteryCapacityGranularity1;
+ ULONG BatteryCapacityGranularity2;
+ CHAR ModelNumber[256];
+ CHAR SerialNubmer[256];
+ CHAR BatteryType[256];
+ CHAR OemInfo[256];
+} ACPI_BIF_DATA, *PACPI_BIF_DATA;
+
+typedef struct _CMBATT_DEVICE_EXTENSION
+{
+ CMBATT_EXTENSION_TYPE FdoType;
+ PDEVICE_OBJECT DeviceObject;
+ PDEVICE_OBJECT FdoDeviceObject;
+ PDEVICE_OBJECT PdoDeviceObject;
+ PDEVICE_OBJECT AttachedDevice;
+ FAST_MUTEX FastMutex;
+ ULONG HandleCount;
+ PIRP PowerIrp;
+ POWER_STATE PowerState;
+ WMILIB_CONTEXT WmiLibInfo;
+ ULONG WaitWakeEnable;
+ ULONG WmiCount;
+ KEVENT WmiEvent;
+ ULONG DeviceId;
+ PUNICODE_STRING DeviceName;
+ ACPI_INTERFACE_STANDARD2 AcpiInterface;
+ BOOLEAN DelayAr;
+ BOOLEAN DelayedArFlag;
+ PVOID ClassData;
+ BOOLEAN Started;
+ BOOLEAN NotifySent;
+ ULONG ArLock;
+ ULONG TagData;
+ ULONG Tag;
+ ULONG ModelNumberLength;
+ PCHAR ModelNumber;
+ ULONG SerialNumberLength;
+ PCHAR SerialNumber;
+ ULONG OemInfoLength;
+ PCHAR OemInfo;
+ ACPI_BST_DATA BstData;
+ ACPI_BIF_DATA BifData;
+ ULONG Id;
+ ULONG State;
+ ULONG RemainingCapacity;
+ ULONG PresentVoltage;
+ ULONG Rate;
+ BATTERY_INFORMATION StaticBatteryInformation;
+ ULONG BatteryCapacityGranularity1;
+ ULONG BatteryCapacityGranularity2;
+ BOOLEAN TripPointSet;
+ ULONG TripPointValue;
+ ULONG TripPointOld;
+ ULONGLONG InterruptTime;
+} CMBATT_DEVICE_EXTENSION, *PCMBATT_DEVICE_EXTENSION;
+
+/* EOF */
diff --git a/drivers/bus/acpi/cmbatt/cmbatt.rbuild b/drivers/bus/acpi/cmbatt/cmbatt.rbuild
new file mode 100644
index 00000000000..c8a09e31b44
--- /dev/null
+++ b/drivers/bus/acpi/cmbatt/cmbatt.rbuild
@@ -0,0 +1,13 @@
+
+
+
+ ntoskrnl
+ hal
+ battc
+ .
+ cmbatt.c
+ cmexec.c
+ cmbpnp.c
+ cmbwmi.c
+ cmbatt.rc
+
diff --git a/drivers/bus/acpi/cmbatt/cmbatt.rc b/drivers/bus/acpi/cmbatt/cmbatt.rc
new file mode 100644
index 00000000000..d1542f9019e
--- /dev/null
+++ b/drivers/bus/acpi/cmbatt/cmbatt.rc
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION "Control Method Battery Miniclass Driver\0"
+#define REACTOS_STR_INTERNAL_NAME "cmbatt\0"
+#define REACTOS_STR_ORIGINAL_FILENAME "cmbatt.sys\0"
+#include
diff --git a/drivers/bus/acpi/cmbatt/cmbpnp.c b/drivers/bus/acpi/cmbatt/cmbpnp.c
new file mode 100644
index 00000000000..fee3ec80b47
--- /dev/null
+++ b/drivers/bus/acpi/cmbatt/cmbpnp.c
@@ -0,0 +1,104 @@
+/*
+ * PROJECT: ReactOS ACPI-Compliant Control Method Battery
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: boot/drivers/bus/acpi/cmbatt/cmbpnp.c
+ * PURPOSE: Plug-and-Play IOCTL/IRP Handling
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "cmbatt.h"
+
+/* FUNCTIONS ******************************************************************/
+
+NTSTATUS
+NTAPI
+CmBattIoCompletion(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PKEVENT Event)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattGetAcpiInterfaces(PDEVICE_OBJECT DeviceObject,
+ PACPI_INTERFACE_STANDARD2 *AcpiInterface)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+VOID
+NTAPI
+CmBattDestroyFdo(PDEVICE_OBJECT DeviceObject)
+{
+ UNIMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattRemoveDevice(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattPowerDispatch(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattCreateFdo(PDRIVER_OBJECT DriverObject,
+ PDEVICE_OBJECT DeviceObject,
+ ULONG DeviceExtensionSize,
+ PDEVICE_OBJECT *NewDeviceObject)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattPnpDispatch(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattAddBattery(PDRIVER_OBJECT DriverObject,
+ PDEVICE_OBJECT DeviceObject)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattAddAcAdapter(PDRIVER_OBJECT DriverObject,
+ PDEVICE_OBJECT DeviceObject)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS NTAPI CmBattAddDevice(PDRIVER_OBJECT DriverObject,
+ PDEVICE_OBJECT DeviceObject)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/* EOF */
diff --git a/drivers/bus/acpi/cmbatt/cmbwmi.c b/drivers/bus/acpi/cmbatt/cmbwmi.c
new file mode 100644
index 00000000000..848c920dd0b
--- /dev/null
+++ b/drivers/bus/acpi/cmbatt/cmbwmi.c
@@ -0,0 +1,94 @@
+/*
+ * PROJECT: ReactOS ACPI-Compliant Control Method Battery
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: boot/drivers/bus/acpi/cmbatt/cmbwmi.c
+ * PURPOSE: WMI Interface
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "cmbatt.h"
+
+/* FUNCTIONS ******************************************************************/
+
+NTSTATUS
+NTAPI
+CmBattQueryWmiRegInfo(PDEVICE_OBJECT DeviceObject,
+ PULONG RegFlags,
+ PUNICODE_STRING InstanceName,
+ PUNICODE_STRING *RegistryPath,
+ PUNICODE_STRING MofResourceName,
+ PDEVICE_OBJECT *Pdo)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattQueryWmiDataBlock(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ ULONG GuidIndex,
+ ULONG InstanceIndex,
+ ULONG InstanceCount,
+ PULONG InstanceLengthArray,
+ ULONG BufferAvail,
+ PUCHAR Buffer)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattSetWmiDataBlock(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ ULONG GuidIndex,
+ ULONG InstanceIndex,
+ ULONG BufferSize,
+ PUCHAR Buffer)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattSetWmiDataItem(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ ULONG GuidIndex,
+ ULONG InstanceIndex,
+ ULONG DataItemId,
+ ULONG BufferSize,
+ PUCHAR Buffer)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattWmiDeRegistration(PCMBATT_DEVICE_EXTENSION DeviceExtension)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattWmiRegistration(PCMBATT_DEVICE_EXTENSION DeviceExtension)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/* EOF */
diff --git a/drivers/bus/acpi/cmbatt/cmexec.c b/drivers/bus/acpi/cmbatt/cmexec.c
new file mode 100644
index 00000000000..a41865c5e4c
--- /dev/null
+++ b/drivers/bus/acpi/cmbatt/cmexec.c
@@ -0,0 +1,100 @@
+/*
+ * PROJECT: ReactOS ACPI-Compliant Control Method Battery
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: boot/drivers/bus/acpi/cmbatt/cmexec.c
+ * PURPOSE: ACPI Method Execution/Evaluation Glue
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "cmbatt.h"
+
+/* FUNCTIONS ******************************************************************/
+
+NTSTATUS
+NTAPI
+GetDwordElement(PACPI_METHOD_ARGUMENT Argument,
+ PULONG Value)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+GetStringElement(PACPI_METHOD_ARGUMENT Argument,
+ PCHAR Value)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattGetPsrData(PDEVICE_OBJECT DeviceObject,
+ PULONG PsrData)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattGetBifData(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ PACPI_BIF_DATA BifData)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattGetBstData(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ PACPI_BST_DATA BstData)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattGetStaData(PDEVICE_OBJECT DeviceObject,
+ PULONG StaData)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattGetUniqueId(PDEVICE_OBJECT DeviceObject,
+ PULONG UniqueId)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattSetTripPpoint(PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ ULONG AlarmValue)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattSendDownStreamIrp(PDEVICE_OBJECT DeviceObject,
+ ULONG IoControlCode,
+ PVOID InputBuffer,
+ ULONG InputBufferLength,
+ PACPI_EVAL_OUTPUT_BUFFER OutputBuffer,
+ ULONG OutputBufferLength)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/* EOF */
diff --git a/drivers/bus/acpi/main.c b/drivers/bus/acpi/main.c
index d8d8b3e7dad..3d1170eefd6 100644
--- a/drivers/bus/acpi/main.c
+++ b/drivers/bus/acpi/main.c
@@ -6,7 +6,7 @@
#include
#include
-//#define NDEBUG
+#define NDEBUG
#include
#ifdef ALLOC_PRAGMA
@@ -35,7 +35,7 @@ Bus_AddDevice(
DPRINT("Add Device: 0x%p\n", PhysicalDeviceObject);
- DPRINT1("#################### Bus_CreateClose Creating FDO Device ####################\n");
+ DPRINT("#################### Bus_CreateClose Creating FDO Device ####################\n");
status = IoCreateDevice(DriverObject,
sizeof(FDO_DEVICE_DATA),
NULL,
@@ -134,7 +134,7 @@ Bus_AddDevice(
goto End;
}
- DPRINT1("AddDevice: %p to %p->%p (%ws) \n",
+ DPRINT("AddDevice: %p to %p->%p (%ws) \n",
deviceObject,
deviceData->NextLowerDriver,
PhysicalDeviceObject,
diff --git a/drivers/bus/acpi/osl.c b/drivers/bus/acpi/osl.c
index be26a0811f9..f2549951e7e 100644
--- a/drivers/bus/acpi/osl.c
+++ b/drivers/bus/acpi/osl.c
@@ -90,7 +90,7 @@ AcpiOsInitialize (void)
ACPI_STATUS
AcpiOsTerminate(void)
{
- DPRINT1("AcpiOsTerminate() called\n");
+ DPRINT("AcpiOsTerminate() called\n");
if (AcpiInterruptHandlerRegistered)
AcpiOsRemoveInterruptHandler(AcpiIrqNumber, AcpiIrqHandler);
@@ -117,7 +117,9 @@ AcpiOsVprintf (
const char *Fmt,
va_list Args)
{
+#ifndef NDEBUG
vDbgPrintEx (-1, DPFLTR_ERROR_LEVEL, Fmt, Args);
+#endif
return;
}
@@ -329,7 +331,7 @@ AcpiOsRemoveInterruptHandler (
void
AcpiOsStall (UINT32 microseconds)
{
- DPRINT1("AcpiOsStall %d\n",microseconds);
+ DPRINT("AcpiOsStall %d\n",microseconds);
KeStallExecutionProcessor(microseconds);
return;
}
@@ -337,7 +339,7 @@ AcpiOsStall (UINT32 microseconds)
void
AcpiOsSleep (ACPI_INTEGER milliseconds)
{
- DPRINT1("AcpiOsSleep %d\n", milliseconds);
+ DPRINT("AcpiOsSleep %d\n", milliseconds);
KeStallExecutionProcessor(milliseconds*1000);
return;
}
@@ -466,11 +468,12 @@ AcpiOsReadPciConfiguration (
NTSTATUS Status;
PCI_SLOT_NUMBER slot;
- if (Register == 0)
+ if (Register == 0 || PciId->Device == 0 ||
+ Register + Width > PCI_COMMON_HDR_LENGTH)
return AE_ERROR;
slot.u.AsULONG = 0;
- slot.u.bits.DeviceNumber = PciId->Bus;
+ slot.u.bits.DeviceNumber = PciId->Device;
slot.u.bits.FunctionNumber = PciId->Function;
DPRINT("AcpiOsReadPciConfiguration, slot=0x%X, func=0x%X\n", slot.u.AsULONG, Register);
@@ -498,11 +501,12 @@ AcpiOsWritePciConfiguration (
ULONG buf = Value;
PCI_SLOT_NUMBER slot;
- if (Register == 0)
+ if (Register == 0 || PciId->Device == 0 ||
+ Register + Width > PCI_COMMON_HDR_LENGTH)
return AE_ERROR;
slot.u.AsULONG = 0;
- slot.u.bits.DeviceNumber = PciId->Bus;
+ slot.u.bits.DeviceNumber = PciId->Device;
slot.u.bits.FunctionNumber = PciId->Function;
DPRINT("AcpiOsWritePciConfiguration, slot=0x%x\n", slot.u.AsULONG);
@@ -664,7 +668,7 @@ AcpiOsExecute (
ACPI_OSD_EXEC_CALLBACK Function,
void *Context)
{
- DPRINT1("AcpiOsExecute\n");
+ DPRINT("AcpiOsExecute\n");
KeInsertQueueDpc(&AcpiDpc, (PVOID)Function, (PVOID)Context);
diff --git a/drivers/bus/acpi/pnp.c b/drivers/bus/acpi/pnp.c
index 4778dc66c2e..c82a3905023 100644
--- a/drivers/bus/acpi/pnp.c
+++ b/drivers/bus/acpi/pnp.c
@@ -7,7 +7,7 @@
#include
#include
-//#define NDEBUG
+#define NDEBUG
#include
#ifdef ALLOC_PRAGMA
diff --git a/drivers/bus/acpi/power.c b/drivers/bus/acpi/power.c
index 3af99c96402..2f7175c74ad 100644
--- a/drivers/bus/acpi/power.c
+++ b/drivers/bus/acpi/power.c
@@ -6,7 +6,7 @@
#include
#include
-//#define NDEBUG
+#define NDEBUG
#include
NTSTATUS
diff --git a/drivers/storage/port/buslogic/BusLogic958.c b/drivers/storage/port/buslogic/BusLogic958.c
index 22c5838b99b..0bf439e06b9 100644
--- a/drivers/storage/port/buslogic/BusLogic958.c
+++ b/drivers/storage/port/buslogic/BusLogic958.c
@@ -79,40 +79,6 @@ v1.2.0.2 // Fix PR 40284 correctly, disable interrupts in the initialization ro
#include "BusLogic958.h"
-int strcmp(const char* s1, const char* s2)
-{
- while(*s1 == *s2)
- {
- if(*s1 == 0) return 0;
-
- s1 ++;
- s2 ++;
- }
-
- return *s1 - *s2;
-}
-
-char * strcat(char * s, const char * append)
-{
- char * save = s;
-
- for(; *s; ++s);
-
- while((*s++ = *append++));
-
- return save;
-}
-
-char * strcpy(char * to, const char * from)
-{
- char *save = to;
-
- for (; (*to = *from); ++from, ++to);
-
- return save;
-}
-
-
ULONG
NTAPI
DriverEntry(IN PVOID DriverObject,
diff --git a/drivers/storage/port/buslogic/buslogic.rbuild b/drivers/storage/port/buslogic/buslogic.rbuild
index 3a197ce05de..3347f10b98d 100644
--- a/drivers/storage/port/buslogic/buslogic.rbuild
+++ b/drivers/storage/port/buslogic/buslogic.rbuild
@@ -1,6 +1,6 @@
-
+
.
scsiport
diff --git a/drivers/video/font/ftfd/freetype.def b/drivers/video/font/ftfd/freetype.def
index 78f842588ee..883a977f464 100644
--- a/drivers/video/font/ftfd/freetype.def
+++ b/drivers/video/font/ftfd/freetype.def
@@ -1,5 +1,8 @@
LIBRARY ftfd.dll
EXPORTS
+ FT_Bitmap_Convert
+ FT_Bitmap_Done
+ FT_Bitmap_New
FT_Done_Face
FT_Done_Glyph
FT_Get_Char_Index
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 36ff1c3fb34..0a75b5ec14d 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -4763,6 +4763,71 @@ typedef enum _WORK_QUEUE_TYPE {
MaximumWorkQueue
} WORK_QUEUE_TYPE;
+typedef BOOLEAN
+(*PGPE_SERVICE_ROUTINE2)(
+ PVOID ObjectContext,
+ PVOID ServiceContext);
+
+typedef NTSTATUS
+(*PGPE_CONNECT_VECTOR2)(
+ PVOID Context,
+ ULONG GpeNumber,
+ KINTERRUPT_MODE Mode,
+ BOOLEAN Shareable,
+ PGPE_SERVICE_ROUTINE2 ServiceRoutine,
+ PVOID ServiceContext,
+ PVOID *ObjectContext);
+
+typedef NTSTATUS
+(*PGPE_DISCONNECT_VECTOR2)(
+ PVOID Context,
+ PVOID ObjectContext);
+
+typedef NTSTATUS
+(*PGPE_ENABLE_EVENT2)(
+ PVOID Context,
+ PVOID ObjectContext);
+
+typedef NTSTATUS
+(*PGPE_DISABLE_EVENT2)(
+ PVOID Context,
+ PVOID ObjectContext);
+
+typedef NTSTATUS
+(*PGPE_CLEAR_STATUS2)(
+ PVOID Context,
+ PVOID ObjectContext);
+
+typedef VOID
+(*PDEVICE_NOTIFY_CALLBACK2)(
+ PVOID NotificationContext,
+ ULONG NotifyCode);
+
+typedef NTSTATUS
+(*PREGISTER_FOR_DEVICE_NOTIFICATIONS2)(
+ PVOID Context,
+ PDEVICE_NOTIFY_CALLBACK2 NotificationHandler,
+ PVOID NotificationContext);
+
+typedef VOID
+(*PUNREGISTER_FOR_DEVICE_NOTIFICATIONS2)(
+ PVOID Context);
+
+typedef struct _ACPI_INTERFACE_STANDARD2 {
+ USHORT Size;
+ USHORT Version;
+ PVOID Context;
+ PINTERFACE_REFERENCE InterfaceReference;
+ PINTERFACE_DEREFERENCE InterfaceDereference;
+ PGPE_CONNECT_VECTOR2 GpeConnectVector;
+ PGPE_DISCONNECT_VECTOR2 GpeDisconnectVector;
+ PGPE_ENABLE_EVENT2 GpeEnableEvent;
+ PGPE_DISABLE_EVENT2 GpeDisableEvent;
+ PGPE_CLEAR_STATUS2 GpeClearStatus;
+ PREGISTER_FOR_DEVICE_NOTIFICATIONS2 RegisterForDeviceNotifications;
+ PUNREGISTER_FOR_DEVICE_NOTIFICATIONS2 UnregisterForDeviceNotifications;
+} ACPI_INTERFACE_STANDARD2, *PACPI_INTERFACE_STANDARD2;
+
#if !defined(_AMD64_) && !defined(_IA64_)
#include
#endif
diff --git a/include/dxsdk/axextend.idl b/include/dxsdk/axextend.idl
index 66e43f151ca..72e37ce47c7 100644
--- a/include/dxsdk/axextend.idl
+++ b/include/dxsdk/axextend.idl
@@ -1070,6 +1070,22 @@ interface IAMFilterMiscFlags : IUnknown
ULONG GetMiscFlags();
};
+[
+ local,
+ object,
+ uuid(56ED71A0-AF5F-11D0-B3F0-00AA003761C5),
+ pointer_default(unique)
+]
+interface IAMBufferNegotiation : IUnknown
+{
+ HRESULT SuggestAllocatorProperties (
+ [in] const ALLOCATOR_PROPERTIES *pprop);
+
+ HRESULT GetAllocatorProperties (
+ [out] ALLOCATOR_PROPERTIES *pprop);
+
+}
+
#include
[
diff --git a/include/psdk/ks.h b/include/psdk/ks.h
index a86d4a87c1a..2249af3711a 100644
--- a/include/psdk/ks.h
+++ b/include/psdk/ks.h
@@ -336,22 +336,28 @@ DEFINE_GUIDSTRUCT("4747B320-62CE-11CF-A5D6-28DB04C10000", KSMEDIUMSETID_Standard
Clock Properties/Methods/Events
*/
-#define KSPROPSETID_Clock \
+#define STATIC_KSPROPSETID_Clock \
0xDF12A4C0L, 0xAC17, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00
+DEFINE_GUIDSTRUCT("DF12A4C0-AC17-11CF-A5D6-28DB04C10000", KSPROPSETID_Clock);
+#define KSPROPSETID_Clock DEFINE_GUIDNAMED(KSPROPSETID_Clock)
typedef enum
{
KSPROPERTY_CLOCK_TIME,
KSPROPERTY_CLOCK_PHYSICALTIME,
- KSPROPERTY_CORRELATEDTIME,
- KSPROPERTY_CORRELATEDPHYSICALTIME,
+ KSPROPERTY_CLOCK_CORRELATEDTIME,
+ KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME,
KSPROPERTY_CLOCK_RESOLUTION,
KSPROPERTY_CLOCK_STATE,
+#if defined(_NTDDK_)
KSPROPERTY_CLOCK_FUNCTIONTABLE
+#endif // defined(_NTDDK_)
} KSPROPERTY_CLOCK;
-#define KSEVENTSETID_Clock \
+#define STATIC_KSEVENTSETID_Clock \
0x364D8E20L, 0x62C7, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00
+DEFINE_GUIDSTRUCT("364D8E20-62C7-11CF-A5D6-28DB04C10000", KSEVENTSETID_Clock);
+#define KSEVENTSETID_Clock DEFINE_GUIDNAMED(KSEVENTSETID_Clock)
typedef enum
{
@@ -718,8 +724,10 @@ typedef enum
Properties/Methods/Events
*/
-#define KSPROPSETID_Stream \
+#define STATIC_KSPROPSETID_Stream\
0x65aaba60L, 0x98ae, 0x11cf, 0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4
+DEFINE_GUIDSTRUCT("65aaba60-98ae-11cf-a10d-0020afd156e4", KSPROPSETID_Stream);
+#define KSPROPSETID_Stream DEFINE_GUIDNAMED(KSPROPSETID_Stream)
typedef enum
{
@@ -1838,11 +1846,32 @@ typedef struct
KSEVENTDATA EventData;
} KSRELATIVEEVENT, *PKSRELATIVEEVENT;
+#define KSRELATIVEEVENT_FLAG_HANDLE 0x00000001
+#define KSRELATIVEEVENT_FLAG_POINTER 0x00000002
/* ===============================================================
Timing
*/
+
+typedef struct {
+ KSEVENTDATA EventData;
+ LONGLONG MarkTime;
+} KSEVENT_TIME_MARK, *PKSEVENT_TIME_MARK;
+
+typedef struct {
+ KSEVENTDATA EventData;
+ LONGLONG TimeBase;
+ LONGLONG Interval;
+} KSEVENT_TIME_INTERVAL, *PKSEVENT_TIME_INTERVAL;
+
+typedef struct {
+ LONGLONG TimeBase;
+ LONGLONG Interval;
+} KSINTERVAL, *PKSINTERVAL;
+
+
+
typedef struct
{
LONGLONG Time;
@@ -1856,12 +1885,6 @@ typedef struct
LONGLONG SystemTime;
} KSCORRELATED_TIME, *PKSCORRELATED_TIME;
-typedef struct
-{
- LONGLONG TimeBase;
- LONGLONG Interval;
-} KSINTERVAL, *PKSINTERVAL;
-
typedef struct
{
LONGLONG Duration;
@@ -2070,19 +2093,7 @@ typedef struct {
typedef struct _KSEVENT_ENTRY KSEVENT_ENTRY, *PKSEVENT_ENTRY;
#if defined(_NTDDK_)
-typedef struct
-{
- KSEVENTDATA EventData;
- LONGLONG MarkTime;
-} KSEVENT_TIME_MARK, *PKSEVENT_TIME_MARK;
-
-typedef struct
-{
- KSEVENTDATA EventData;
- LONGLONG TimeBase;
- LONGLONG Interval;
-} KSEVENT_TIME_INTERVAL, *PKSEVENT_TIME_INTERVAL;
-
+
typedef NTSTATUS (NTAPI *PFNKSADDEVENT)(
IN PIRP Irp,
IN PKSEVENTDATA EventData,
@@ -3867,6 +3878,26 @@ KsPinGetConnectedPinFileObject(
#else
+#if !defined( KS_NO_CREATE_FUNCTIONS )
+
+KSDDKAPI
+DWORD
+WINAPI
+KsCreateAllocator(
+ IN HANDLE ConnectionHandle,
+ IN PKSALLOCATOR_FRAMING AllocatorFraming,
+ OUT PHANDLE AllocatorHandle
+ );
+
+KSDDKAPI
+DWORD
+NTAPI
+KsCreateClock(
+ IN HANDLE ConnectionHandle,
+ IN PKSCLOCK_CREATE ClockCreate,
+ OUT PHANDLE ClockHandle
+ );
+
KSDDKAPI
DWORD
WINAPI
@@ -3877,6 +3908,17 @@ KsCreatePin(
OUT PHANDLE ConnectionHandle
);
+KSDDKAPI
+DWORD
+WINAPI
+KsCreateTopologyNode(
+ IN HANDLE ParentHandle,
+ IN PKSNODE_CREATE NodeCreate,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PHANDLE NodeHandle
+ );
+
+#endif
#endif
diff --git a/include/psdk/winternl.h b/include/psdk/winternl.h
index f101f04bc74..7f1a739b53d 100644
--- a/include/psdk/winternl.h
+++ b/include/psdk/winternl.h
@@ -871,20 +871,20 @@ typedef struct _UNWIND_HISTORY_TABLE {
*/
/* This is used by NtQuerySystemInformation */
-typedef struct _SYSTEM_THREAD_INFORMATION{
- FILETIME ftKernelTime;
- FILETIME ftUserTime;
- FILETIME ftCreateTime;
- DWORD dwTickCount;
- DWORD dwStartAddress;
- DWORD dwOwningPID;
- DWORD dwThreadID;
- DWORD dwCurrentPriority;
- DWORD dwBasePriority;
- DWORD dwContextSwitches;
- DWORD dwThreadState;
- DWORD dwWaitReason;
- DWORD dwUnknown;
+typedef struct _SYSTEM_THREAD_INFORMATION
+{ /* win32/win64 */
+ LARGE_INTEGER KernelTime; /* 00/00 */
+ LARGE_INTEGER UserTime; /* 08/08 */
+ LARGE_INTEGER CreateTime; /* 10/10 */
+ DWORD dwTickCount; /* 18/18 */
+ LPVOID StartAddress; /* 1c/20 */
+ CLIENT_ID ClientId; /* 20/28 */
+ DWORD dwCurrentPriority; /* 28/38 */
+ DWORD dwBasePriority; /* 2c/3c */
+ DWORD dwContextSwitches; /* 30/40 */
+ DWORD dwThreadState; /* 34/44 */
+ DWORD dwWaitReason; /* 38/48 */
+ DWORD dwUnknown; /* 3c/4c */
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
typedef struct _IO_STATUS_BLOCK {
@@ -1195,38 +1195,39 @@ typedef struct _VM_COUNTERS_ {
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
+ SIZE_T PrivatePageCount;
} VM_COUNTERS, *PVM_COUNTERS;
typedef struct _SYSTEM_PROCESS_INFORMATION {
-#ifdef __WINESRC__
- DWORD dwOffset;
- DWORD dwThreadCount;
- DWORD dwUnknown1[6];
- FILETIME ftCreationTime;
- FILETIME ftUserTime;
- FILETIME ftKernelTime;
- UNICODE_STRING ProcessName;
- DWORD dwBasePriority;
- DWORD dwProcessID;
- DWORD dwParentProcessID;
- DWORD dwHandleCount;
- DWORD dwUnknown3;
- DWORD dwUnknown4;
- VM_COUNTERS vmCounters;
- IO_COUNTERS ioCounters;
- SYSTEM_THREAD_INFORMATION ti[1];
+#ifdef __WINESRC__ /* win32/win64 */
+ ULONG NextEntryOffset; /* 00/00 */
+ DWORD dwThreadCount; /* 04/04 */
+ DWORD dwUnknown1[6]; /* 08/08 */
+ LARGE_INTEGER CreationTime; /* 20/20 */
+ LARGE_INTEGER UserTime; /* 28/28 */
+ LARGE_INTEGER KernelTime; /* 30/30 */
+ UNICODE_STRING ProcessName; /* 38/38 */
+ DWORD dwBasePriority; /* 40/48 */
+ HANDLE UniqueProcessId; /* 44/50 */
+ HANDLE ParentProcessId; /* 48/58 */
+ ULONG HandleCount; /* 4c/60 */
+ DWORD dwUnknown3; /* 50/64 */
+ DWORD dwUnknown4; /* 54/68 */
+ VM_COUNTERS vmCounters; /* 58/70 */
+ IO_COUNTERS ioCounters; /* 88/d0 */
+ SYSTEM_THREAD_INFORMATION ti[1]; /* b8/100 */
#else
- ULONG NextEntryOffset;
- BYTE Reserved1[52];
- PVOID Reserved2[3];
- HANDLE UniqueProcessId;
- PVOID Reserved3;
- ULONG HandleCount;
- BYTE Reserved4[4];
- PVOID Reserved5[11];
- SIZE_T PeakPagefileUsage;
- SIZE_T PrivatePageCount;
- LARGE_INTEGER Reserved6[6];
+ ULONG NextEntryOffset; /* 00/00 */
+ BYTE Reserved1[52]; /* 04/04 */
+ PVOID Reserved2[3]; /* 38/38 */
+ HANDLE UniqueProcessId; /* 44/50 */
+ PVOID Reserved3; /* 48/58 */
+ ULONG HandleCount; /* 4c/60 */
+ BYTE Reserved4[4]; /* 50/64 */
+ PVOID Reserved5[11]; /* 54/68 */
+ SIZE_T PeakPagefileUsage; /* 80/c0 */
+ SIZE_T PrivatePageCount; /* 84/c8 */
+ LARGE_INTEGER Reserved6[6]; /* 88/d0 */
#endif
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
@@ -1553,7 +1554,7 @@ typedef struct _KEY_MULTIPLE_VALUE_INFORMATION
ULONG Type;
} KEY_MULTIPLE_VALUE_INFORMATION, *PKEY_MULTIPLE_VALUE_INFORMATION;
-typedef VOID (*PTIMER_APC_ROUTINE) ( PVOID, ULONG, LONG );
+typedef VOID (CALLBACK *PTIMER_APC_ROUTINE) ( PVOID, ULONG, LONG );
typedef enum _EVENT_TYPE {
NotificationEvent,
diff --git a/include/reactos/wine/mscvpdb.h b/include/reactos/wine/mscvpdb.h
index 9d52a655b56..2aefa879a90 100644
--- a/include/reactos/wine/mscvpdb.h
+++ b/include/reactos/wine/mscvpdb.h
@@ -1642,14 +1642,28 @@ struct startend
unsigned int end;
};
+#define LT2_LINES_BLOCK 0x000000f2
+#define LT2_FILES_BLOCK 0x000000f4
+
/* there's a new line tab structure from MS Studio 2005 and after
- * it's made of:
- * DWORD 000000f4
- * DWORD lineblk_offset (counting bytes after this field)
- * an array of codeview_linetab2_file structures
- * an array (starting at ) of codeview_linetab2_block structures
+ * it's made of a list of codeview_linetab2 blocks.
+ * We've only seen (so far) list with a single LT2_FILES_BLOCK and several
+ * LT2_LINES_BLOCK. The LT2_FILES block has been encountered either as first
+ * or last block of the list.
+ * A LT2_FILES contains one or several codeview_linetab2_file:s
*/
+struct codeview_linetab2
+{
+ DWORD header;
+ DWORD size_of_block;
+};
+
+static inline const struct codeview_linetab2* codeview_linetab2_next_block(const struct codeview_linetab2* lt2)
+{
+ return (const struct codeview_linetab2*)((const char*)(lt2 + 1) + lt2->size_of_block);
+}
+
struct codeview_linetab2_file
{
DWORD offset; /* offset in string table for filename */
@@ -1658,16 +1672,21 @@ struct codeview_linetab2_file
WORD pad0; /* always 0 */
};
-struct codeview_linetab2_block
+struct codeview_lt2blk_files
{
- DWORD header; /* 0x000000f2 */
- DWORD size_of_block; /* next block is at # bytes after this field */
- DWORD start; /* start address of function with line numbers */
- DWORD seg; /* segment of function with line numbers */
- DWORD size; /* size of function with line numbers */
- DWORD file_offset; /* offset for accessing corresponding codeview_linetab2_file */
- DWORD nlines; /* number of lines in this block */
- DWORD size_lines; /* number of bytes following for line number information */
+ struct codeview_linetab2 lt2; /* LT2_FILES */
+ struct codeview_linetab2_file file[1];
+};
+
+struct codeview_lt2blk_lines
+{
+ struct codeview_linetab2 lt2; /* LT2_LINE_BLOCK */
+ DWORD start; /* start address of function with line numbers */
+ DWORD seg; /* segment of function with line numbers */
+ DWORD size; /* size of function with line numbers */
+ DWORD file_offset; /* offset for accessing corresponding codeview_linetab2_file */
+ DWORD nlines; /* number of lines in this block */
+ DWORD size_lines; /* number of bytes following for line number information */
struct {
DWORD offset; /* offset (from :) for line number */
DWORD lineno; /* the line number (OR:ed with 0x80000000 why ???) */
diff --git a/include/xdk/iotypes.h b/include/xdk/iotypes.h
index a2bce0be3f9..4bdc140512a 100644
--- a/include/xdk/iotypes.h
+++ b/include/xdk/iotypes.h
@@ -2151,6 +2151,71 @@ typedef enum _WORK_QUEUE_TYPE {
MaximumWorkQueue
} WORK_QUEUE_TYPE;
+typedef BOOLEAN
+(*PGPE_SERVICE_ROUTINE2)(
+ PVOID ObjectContext,
+ PVOID ServiceContext);
+
+typedef NTSTATUS
+(*PGPE_CONNECT_VECTOR2)(
+ PVOID Context,
+ ULONG GpeNumber,
+ KINTERRUPT_MODE Mode,
+ BOOLEAN Shareable,
+ PGPE_SERVICE_ROUTINE2 ServiceRoutine,
+ PVOID ServiceContext,
+ PVOID *ObjectContext);
+
+typedef NTSTATUS
+(*PGPE_DISCONNECT_VECTOR2)(
+ PVOID Context,
+ PVOID ObjectContext);
+
+typedef NTSTATUS
+(*PGPE_ENABLE_EVENT2)(
+ PVOID Context,
+ PVOID ObjectContext);
+
+typedef NTSTATUS
+(*PGPE_DISABLE_EVENT2)(
+ PVOID Context,
+ PVOID ObjectContext);
+
+typedef NTSTATUS
+(*PGPE_CLEAR_STATUS2)(
+ PVOID Context,
+ PVOID ObjectContext);
+
+typedef VOID
+(*PDEVICE_NOTIFY_CALLBACK2)(
+ PVOID NotificationContext,
+ ULONG NotifyCode);
+
+typedef NTSTATUS
+(*PREGISTER_FOR_DEVICE_NOTIFICATIONS2)(
+ PVOID Context,
+ PDEVICE_NOTIFY_CALLBACK2 NotificationHandler,
+ PVOID NotificationContext);
+
+typedef VOID
+(*PUNREGISTER_FOR_DEVICE_NOTIFICATIONS2)(
+ PVOID Context);
+
+typedef struct _ACPI_INTERFACE_STANDARD2 {
+ USHORT Size;
+ USHORT Version;
+ PVOID Context;
+ PINTERFACE_REFERENCE InterfaceReference;
+ PINTERFACE_DEREFERENCE InterfaceDereference;
+ PGPE_CONNECT_VECTOR2 GpeConnectVector;
+ PGPE_DISCONNECT_VECTOR2 GpeDisconnectVector;
+ PGPE_ENABLE_EVENT2 GpeEnableEvent;
+ PGPE_DISABLE_EVENT2 GpeDisableEvent;
+ PGPE_CLEAR_STATUS2 GpeClearStatus;
+ PREGISTER_FOR_DEVICE_NOTIFICATIONS2 RegisterForDeviceNotifications;
+ PUNREGISTER_FOR_DEVICE_NOTIFICATIONS2 UnregisterForDeviceNotifications;
+} ACPI_INTERFACE_STANDARD2, *PACPI_INTERFACE_STANDARD2;
+
#if !defined(_AMD64_) && !defined(_IA64_)
#include
#endif
diff --git a/lib/3rdparty/freetype/src/base/ftbitmap.c b/lib/3rdparty/freetype/src/base/ftbitmap.c
index 4c1cdf21888..c847eb00d24 100644
--- a/lib/3rdparty/freetype/src/base/ftbitmap.c
+++ b/lib/3rdparty/freetype/src/base/ftbitmap.c
@@ -445,15 +445,15 @@
{
FT_Int val = ss[0]; /* avoid a byte->int cast on each line */
+ tt[0] = (FT_Byte)( ( val & 0x80 ) ? 0xff : 0);
+ tt[1] = (FT_Byte)( ( val & 0x40 ) ? 0xff : 0);
+ tt[2] = (FT_Byte)( ( val & 0x20 ) ? 0xff : 0);
+ tt[3] = (FT_Byte)( ( val & 0x10 ) ? 0xff : 0);
+ tt[4] = (FT_Byte)( ( val & 0x08 ) ? 0xff : 0);
+ tt[5] = (FT_Byte)( ( val & 0x04 ) ? 0xff : 0);
+ tt[6] = (FT_Byte)( ( val & 0x02 ) ? 0xff : 0);
+ tt[7] = (FT_Byte)( ( val & 0x01 ) ? 0xff : 0);
- tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
- tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
- tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
- tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
- tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
- tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
- tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
- tt[7] = (FT_Byte)( val & 0x01 );
tt += 8;
ss += 1;
@@ -468,7 +468,7 @@
for ( ; j > 0; j-- )
{
- tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
+ tt[0] = (FT_Byte)( ( val & 0x80 ) ? 0xff : 0);
val <<= 1;
tt += 1;
}
diff --git a/ntoskrnl/include/internal/i386/asmmacro.S b/ntoskrnl/include/internal/i386/asmmacro.S
index d8ca99da594..6ddb9d015ad 100644
--- a/ntoskrnl/include/internal/i386/asmmacro.S
+++ b/ntoskrnl/include/internal/i386/asmmacro.S
@@ -179,6 +179,14 @@ set_sane_segs:
mov fs, ax
endif
+#if DBG
+ /* Keep the frame chain intact */
+ mov eax, [esp + KTRAP_FRAME_EIP]
+ mov [esp + KTRAP_FRAME_DEBUGEIP], eax
+ mov [esp + KTRAP_FRAME_DEBUGEBP], ebp
+ mov ebp, esp
+#endif
+
/* Set parameter 1 (ECX) to point to the frame */
mov ecx, esp
@@ -187,11 +195,157 @@ set_sane_segs:
ENDM
+MACRO(KiCallHandler, Handler)
+#if DBG
+ /* Use a call to get the return address for back traces */
+ call Handler
+#else
+ /* Use the faster jmp */
+ jmp Handler
+#endif
+ nop
+ENDM
+
MACRO(TRAP_ENTRY, Trap, Flags)
EXTERN @&Trap&Handler@4 :PROC
PUBLIC _&Trap
_&Trap:
KiEnterTrap Flags
- jmp @&Trap&Handler@4
+ KiCallHandler @&Trap&Handler@4
+ENDM
+
+#define KI_RESTORE_EAX HEX(001)
+#define KI_RESTORE_ECX_EDX HEX(002)
+#define KI_RESTORE_FS HEX(004)
+#define KI_RESTORE_SEGMENTS HEX(008)
+#define KI_RESTORE_EFLAGS HEX(010)
+#define KI_EXIT_SYSCALL HEX(020)
+#define KI_EXIT_JMP HEX(040)
+#define KI_EXIT_RET HEX(080)
+#define KI_EXIT_IRET HEX(100)
+#define KI_EDITED_FRAME HEX(200)
+#define KI_RESTORE_VOLATILES (KI_RESTORE_EAX OR KI_RESTORE_ECX_EDX)
+
+MACRO(KiTrapExitStub, Name, Flags)
+
+PUBLIC @&Name&@4
+@&Name&@4:
+
+ if (Flags AND KI_RESTORE_EFLAGS)
+
+ /* We will pop EFlags off the stack */
+ OffsetEsp = KTRAP_FRAME_EFLAGS
+
+ elseif (Flags AND KI_EXIT_IRET)
+
+ /* This is the IRET frame */
+ OffsetEsp = KTRAP_FRAME_EIP
+
+ else
+
+ OffsetEsp = 0
+
+ endif
+
+ if (Flags AND KI_EDITED_FRAME)
+
+ /* Load the requested ESP */
+ mov esp, [ecx + KTRAP_FRAME_TEMPESP]
+
+ /* Put return address on the new stack */
+ push [ecx + KTRAP_FRAME_EIP]
+
+ /* Put EFLAGS on the new stack */
+ push [ecx + KTRAP_FRAME_EFLAGS]
+
+ else
+
+ /* Point esp to an appropriate member of the frame */
+ lea esp, [ecx + OffsetEsp]
+
+ endif
+
+ /* Restore non volatiles */
+ mov ebx, [ecx + KTRAP_FRAME_EBX]
+ mov esi, [ecx + KTRAP_FRAME_ESI]
+ mov edi, [ecx + KTRAP_FRAME_EDI]
+ mov ebp, [ecx + KTRAP_FRAME_EBP]
+
+ if (Flags AND KI_RESTORE_EAX)
+
+ /* Restore eax */
+ mov eax, [ecx + KTRAP_FRAME_EAX]
+
+ endif
+
+ if (Flags AND KI_RESTORE_ECX_EDX)
+
+ /* Restore volatiles */
+ mov edx, [ecx + KTRAP_FRAME_EDX]
+ mov ecx, [ecx + KTRAP_FRAME_ECX]
+
+ elseif (Flags AND KI_EXIT_JMP)
+
+ /* Load return address into edx */
+ mov edx, [esp - OffsetEsp + KTRAP_FRAME_EIP]
+
+ elseif (Flags AND KI_EXIT_SYSCALL)
+
+ /* Set sysexit parameters */
+ mov edx, [esp - OffsetEsp + KTRAP_FRAME_EIP]
+ mov ecx, [esp - OffsetEsp + KTRAP_FRAME_ESP]
+
+ /* Keep interrupts disabled until the sti / sysexit */
+ and byte ptr [esp - OffsetEsp + KTRAP_FRAME_EFLAGS + 1], ~(EFLAGS_INTERRUPT_MASK >> 8)
+
+ endif
+
+ if (Flags AND KI_RESTORE_SEGMENTS)
+
+ /* Restore segments for user mode */
+ mov ds, [esp - OffsetEsp + KTRAP_FRAME_DS]
+ mov es, [esp - OffsetEsp + KTRAP_FRAME_ES]
+ mov gs, [esp - OffsetEsp + KTRAP_FRAME_GS]
+
+ endif
+
+ if ((Flags AND KI_RESTORE_FS) OR (Flags AND KI_RESTORE_SEGMENTS))
+
+ /* Restore user mode FS */
+ mov fs, [esp - OffsetEsp + KTRAP_FRAME_FS]
+
+ endif
+
+ if (Flags AND KI_RESTORE_EFLAGS)
+
+ /* Restore EFLAGS */
+ popf
+
+ endif
+
+ if (Flags AND KI_EXIT_SYSCALL)
+
+ /* Enable interrupts and return to user mode.
+ Both must follow directly after another to be "atomic". */
+ sti
+ sysexit
+
+ elseif (Flags AND KI_EXIT_IRET)
+
+ /* Return with iret */
+ iret
+
+ elseif (Flags AND KI_EXIT_JMP)
+
+ /* Return to kernel mode with a jmp */
+ jmp edx
+
+ elseif (Flags AND KI_EXIT_RET)
+
+ /* Return to kernel mode with a ret */
+ ret
+
+ endif
+
ENDM
diff --git a/ntoskrnl/include/internal/trap_x.h b/ntoskrnl/include/internal/trap_x.h
index 26e39e4484b..93c5d1fc6c0 100644
--- a/ntoskrnl/include/internal/trap_x.h
+++ b/ntoskrnl/include/internal/trap_x.h
@@ -8,6 +8,8 @@
#pragma once
+//#define TRAP_DEBUG 1
+
//
// Unreachable code hint for GCC 4.5.x, older GCC versions, and MSVC
//
@@ -23,6 +25,17 @@
#define UNREACHABLE
#endif
+//
+// Helper Code
+//
+BOOLEAN
+FORCEINLINE
+KiUserTrap(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Anything else but Ring 0 is Ring 3 */
+ return (TrapFrame->SegCs & MODE_MASK);
+}
+
//
// Debug Macros
//
@@ -78,18 +91,19 @@ KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
TrapFrame->DbgArgMark = 0xBADB0D00;
TrapFrame->DbgEip = TrapFrame->Eip;
TrapFrame->DbgEbp = TrapFrame->Ebp;
+ TrapFrame->PreviousPreviousMode = -1;
}
VOID
FORCEINLINE
KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
- IN KTRAP_STATE_BITS SkipBits)
+ IN KTRAP_EXIT_SKIP_BITS SkipBits)
{
/* Make sure interrupts are disabled */
if (__readeflags() & EFLAGS_INTERRUPT_MASK)
{
DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
- while (TRUE);
+ __debugbreak();
}
/* Make sure this is a real trap frame */
@@ -97,35 +111,35 @@ KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
{
DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
KiDumpTrapFrame(TrapFrame);
- while (TRUE);
+ __debugbreak();
}
/* Make sure we're not in user-mode or something */
if (Ke386GetFs() != KGDT_R0_PCR)
{
DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
- while (TRUE);
+ __debugbreak();
}
/* Make sure we have a valid SEH chain */
if (KeGetPcr()->NtTib.ExceptionList == 0)
{
DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib.ExceptionList);
- while (TRUE);
+ __debugbreak();
}
/* Make sure we're restoring a valid SEH chain */
if (TrapFrame->ExceptionList == 0)
{
DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
- while (TRUE);
+ __debugbreak();
}
/* If we're ignoring previous mode, make sure caller doesn't actually want it */
if ((SkipBits.SkipPreviousMode) && (TrapFrame->PreviousPreviousMode != -1))
{
- DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx", TrapFrame->PreviousPreviousMode);
- while (TRUE);
+ DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame->PreviousPreviousMode);
+ __debugbreak();
}
}
@@ -137,14 +151,14 @@ KiExitSystemCallDebugChecks(IN ULONG SystemCall,
KIRQL OldIrql;
/* Check if this was a user call */
- if (KiUserMode(TrapFrame))
+ if (KiUserTrap(TrapFrame))
{
/* Make sure we are not returning with elevated IRQL */
OldIrql = KeGetCurrentIrql();
if (OldIrql != PASSIVE_LEVEL)
{
/* Forcibly put us in a sane state */
- KeGetPcr()->CurrentIrql = PASSIVE_LEVEL;
+ KeGetPcr()->Irql = PASSIVE_LEVEL;
_disable();
/* Fail */
@@ -154,7 +168,7 @@ KiExitSystemCallDebugChecks(IN ULONG SystemCall,
0,
0);
}
-
+#if 0
/* Make sure we're not attached and that APCs are not disabled */
if ((KeGetCurrentThread()->ApcStateIndex != CurrentApcEnvironment) ||
(KeGetCurrentThread()->CombinedApcDisable != 0))
@@ -166,6 +180,7 @@ KiExitSystemCallDebugChecks(IN ULONG SystemCall,
KeGetCurrentThread()->CombinedApcDisable,
0);
}
+#endif
}
}
#else
@@ -174,340 +189,29 @@ KiExitSystemCallDebugChecks(IN ULONG SystemCall,
#define KiExitSystemCallDebugChecks(x, y)
#endif
-//
-// Helper Code
-//
-BOOLEAN
-FORCEINLINE
-KiUserTrap(IN PKTRAP_FRAME TrapFrame)
-{
- /* Anything else but Ring 0 is Ring 3 */
- return (TrapFrame->SegCs & MODE_MASK);
-}
-
-//
-// "BOP" code used by VDM and V8086 Mode
-//
-VOID
-FORCEINLINE
-KiIssueBop(VOID)
-{
- /* Invalid instruction that an invalid opcode handler must trap and handle */
- asm volatile(".byte 0xC4\n.byte 0xC4\n");
-}
-
-VOID
-FORCEINLINE
-KiUserSystemCall(IN PKTRAP_FRAME TrapFrame)
-{
- /*
- * Kernel call or user call?
- *
- * This decision is made in inlined assembly because we need to patch
- * the relative offset of the user-mode jump to point to the SYSEXIT
- * routine if the CPU supports it. The only way to guarantee that a
- * relative jnz/jz instruction is generated is to force it with the
- * inline assembler.
- */
- asm volatile
- (
- "test $1, %0\n" /* MODE_MASK */
- ".globl _KiSystemCallExitBranch\n_KiSystemCallExitBranch:\n"
- "jnz _KiSystemCallExit\n"
- :
- : "r"(TrapFrame->SegCs)
- );
-}
-
-//
-// Generates an Exit Epilog Stub for the given name
-//
-#define KI_FUNCTION_CALL 0x1
-#define KI_EDITED_FRAME 0x2
-#define KI_DIRECT_EXIT 0x4
-#define KI_FAST_SYSTEM_CALL_EXIT 0x8
-#define KI_SYSTEM_CALL_EXIT 0x10
-#define KI_SYSTEM_CALL_JUMP 0x20
-#define KiTrapExitStub(x, y) VOID FORCEINLINE DECLSPEC_NORETURN x(IN PKTRAP_FRAME TrapFrame) { KiTrapExit(TrapFrame, y); UNREACHABLE; }
-#define KiTrapExitStub2(x, y) VOID FORCEINLINE x(IN PKTRAP_FRAME TrapFrame) { KiTrapExit(TrapFrame, y); }
-
-//
-// How volatiles will be restored
-//
-#define KI_EAX_NO_VOLATILES 0x0
-#define KI_EAX_ONLY 0x1
-#define KI_ALL_VOLATILES 0x2
-
-//
-// Exit mechanism to use
-//
-#define KI_EXIT_IRET 0x0
-#define KI_EXIT_SYSEXIT 0x1
-#define KI_EXIT_JMP 0x2
-#define KI_EXIT_RET 0x3
-
-//
-// Master Trap Epilog
-//
-VOID
-FORCEINLINE
-KiTrapExit(IN PKTRAP_FRAME TrapFrame,
- IN ULONG Flags)
-{
- ULONG FrameSize = FIELD_OFFSET(KTRAP_FRAME, Eip);
- ULONG ExitMechanism = KI_EXIT_IRET, Volatiles = KI_ALL_VOLATILES, NonVolatiles = TRUE;
- ULONG EcxField = FIELD_OFFSET(KTRAP_FRAME, Ecx), EdxField = FIELD_OFFSET(KTRAP_FRAME, Edx);
-
- /* System call exit needs a special label */
- if (Flags & KI_SYSTEM_CALL_EXIT) __asm__ __volatile__
- (
- ".globl _KiSystemCallExit\n_KiSystemCallExit:\n"
- );
-
- /* Start by making the trap frame equal to the stack */
- __asm__ __volatile__
- (
- "movl %0, %%esp\n"
- :
- : "r"(TrapFrame)
- : "%esp"
- );
-
- /* Check what kind of trap frame this trap requires */
- if (Flags & KI_FUNCTION_CALL)
- {
- /* These calls have an EIP on the stack they need */
- ExitMechanism = KI_EXIT_RET;
- Volatiles = FALSE;
- }
- else if (Flags & KI_EDITED_FRAME)
- {
- /* Edited frames store a new ESP in the error code field */
- FrameSize = FIELD_OFFSET(KTRAP_FRAME, ErrCode);
- }
- else if (Flags & KI_DIRECT_EXIT)
- {
- /* Exits directly without restoring anything, interrupt frame on stack */
- NonVolatiles = Volatiles = FALSE;
- }
- else if (Flags & KI_FAST_SYSTEM_CALL_EXIT)
- {
- /* We have a fake interrupt stack with a ring transition */
- FrameSize = FIELD_OFFSET(KTRAP_FRAME, V86Es);
- ExitMechanism = KI_EXIT_SYSEXIT;
-
- /* SYSEXIT wants EIP in EDX and ESP in ECX */
- EcxField = FIELD_OFFSET(KTRAP_FRAME, HardwareEsp);
- EdxField = FIELD_OFFSET(KTRAP_FRAME, Eip);
- }
- else if (Flags & KI_SYSTEM_CALL_EXIT)
- {
- /* Only restore EAX */
- NonVolatiles = KI_EAX_ONLY;
- }
- else if (Flags & KI_SYSTEM_CALL_JUMP)
- {
- /* We have a fake interrupt stack with no ring transition */
- FrameSize = FIELD_OFFSET(KTRAP_FRAME, HardwareEsp);
- NonVolatiles = KI_EAX_ONLY;
- ExitMechanism = KI_EXIT_JMP;
- }
-
- /* Restore the non volatiles */
- if (NonVolatiles) __asm__ __volatile__
- (
- "movl %c[b](%%esp), %%ebx\n"
- "movl %c[s](%%esp), %%esi\n"
- "movl %c[i](%%esp), %%edi\n"
- "movl %c[p](%%esp), %%ebp\n"
- :
- : [b] "i"(FIELD_OFFSET(KTRAP_FRAME, Ebx)),
- [s] "i"(FIELD_OFFSET(KTRAP_FRAME, Esi)),
- [i] "i"(FIELD_OFFSET(KTRAP_FRAME, Edi)),
- [p] "i"(FIELD_OFFSET(KTRAP_FRAME, Ebp))
- : "%esp"
- );
-
- /* Restore EAX if volatiles must be restored */
- if (Volatiles) __asm__ __volatile__
- (
- "movl %c[a](%%esp), %%eax\n":: [a] "i"(FIELD_OFFSET(KTRAP_FRAME, Eax)) : "%esp"
- );
-
- /* Restore the other volatiles if needed */
- if (Volatiles == KI_ALL_VOLATILES) __asm__ __volatile__
- (
- "movl %c[c](%%esp), %%ecx\n"
- "movl %c[d](%%esp), %%edx\n"
- :
- : [c] "i"(EcxField),
- [d] "i"(EdxField)
- : "%esp"
- );
-
- /* Ring 0 system calls jump back to EDX */
- if (Flags & KI_SYSTEM_CALL_JUMP) __asm__ __volatile__
- (
- "movl %c[d](%%esp), %%edx\n":: [d] "i"(FIELD_OFFSET(KTRAP_FRAME, Eip)) : "%esp"
- );
-
- /* Now destroy the trap frame on the stack */
- __asm__ __volatile__ ("addl $%c[e],%%esp\n":: [e] "i"(FrameSize) : "%esp");
-
- /* Edited traps need to change to a new ESP */
- if (Flags & KI_EDITED_FRAME) __asm__ __volatile__ ("movl (%%esp), %%esp\n":::"%esp");
-
- /* Check the exit mechanism and apply it */
- if (ExitMechanism == KI_EXIT_RET) __asm__ __volatile__("ret\n"::: "%esp");
- else if (ExitMechanism == KI_EXIT_IRET) __asm__ __volatile__("iret\n"::: "%esp");
- else if (ExitMechanism == KI_EXIT_JMP) __asm__ __volatile__("jmp *%%edx\n.globl _KiSystemCallExit2\n_KiSystemCallExit2:\n"::: "%esp");
- else if (ExitMechanism == KI_EXIT_SYSEXIT) __asm__ __volatile__("sti\nsysexit\n"::: "%esp");
-}
-
-//
-// All the specific trap epilog stubs
-//
-KiTrapExitStub (KiTrapReturn, 0);
-KiTrapExitStub (KiDirectTrapReturn, KI_DIRECT_EXIT);
-KiTrapExitStub (KiCallReturn, KI_FUNCTION_CALL);
-KiTrapExitStub (KiEditedTrapReturn, KI_EDITED_FRAME);
-KiTrapExitStub2(KiSystemCallReturn, KI_SYSTEM_CALL_JUMP);
-KiTrapExitStub (KiSystemCallSysExitReturn, KI_FAST_SYSTEM_CALL_EXIT);
-KiTrapExitStub (KiSystemCallTrapReturn, KI_SYSTEM_CALL_EXIT);
-
//
// Generic Exit Routine
//
+VOID FASTCALL DECLSPEC_NORETURN KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame);
+VOID FASTCALL DECLSPEC_NORETURN KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame);
+VOID FASTCALL DECLSPEC_NORETURN KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame);
+VOID FASTCALL DECLSPEC_NORETURN KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame);
+VOID FASTCALL DECLSPEC_NORETURN KiTrapReturn(IN PKTRAP_FRAME TrapFrame);
+VOID FASTCALL DECLSPEC_NORETURN KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame);
+
+typedef
VOID
-FORCEINLINE
-DECLSPEC_NORETURN
-KiExitTrap(IN PKTRAP_FRAME TrapFrame,
- IN UCHAR Skip)
-{
- KTRAP_EXIT_SKIP_BITS SkipBits = { .Bits = Skip };
- PULONG ReturnStack;
-
- /* Debugging checks */
- KiExitTrapDebugChecks(TrapFrame, SkipBits);
+(FASTCALL
+*PFAST_SYSTEM_CALL_EXIT)(IN PKTRAP_FRAME TrapFrame) DECLSPEC_NORETURN;
- /* Restore the SEH handler chain */
- KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList;
-
- /* Check if the previous mode must be restored */
- if (__builtin_expect(!SkipBits.SkipPreviousMode, 0)) /* More INTS than SYSCALLs */
- {
- /* Restore it */
- KeGetCurrentThread()->PreviousMode = TrapFrame->PreviousPreviousMode;
- }
-
- /* Check if there are active debug registers */
- if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
- {
- /* Not handled yet */
- DbgPrint("Need Hardware Breakpoint Support!\n");
- DbgBreakPoint();
- while (TRUE);
- }
-
- /* Check if this was a V8086 trap */
- if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0)) KiTrapReturn(TrapFrame);
-
- /* Check if the trap frame was edited */
- if (__builtin_expect(!(TrapFrame->SegCs & FRAME_EDITED), 0))
- {
- /*
- * An edited trap frame happens when we need to modify CS and/or ESP but
- * don't actually have a ring transition. This happens when a kernelmode
- * caller wants to perform an NtContinue to another kernel address, such
- * as in the case of SEH (basically, a longjmp), or to a user address.
- *
- * Therefore, the CPU never saved CS/ESP on the stack because we did not
- * get a trap frame due to a ring transition (there was no interrupt).
- * Even if we didn't want to restore CS to a new value, a problem occurs
- * due to the fact a normal RET would not work if we restored ESP since
- * RET would then try to read the result off the stack.
- *
- * The NT kernel solves this by adding 12 bytes of stack to the exiting
- * trap frame, in which EFLAGS, CS, and EIP are stored, and then saving
- * the ESP that's being requested into the ErrorCode field. It will then
- * exit with an IRET. This fixes both issues, because it gives the stack
- * some space where to hold the return address and then end up with the
- * wanted stack, and it uses IRET which allows a new CS to be inputted.
- *
- */
-
- /* Set CS that is requested */
- TrapFrame->SegCs = TrapFrame->TempSegCs;
-
- /* First make space on requested stack */
- ReturnStack = (PULONG)(TrapFrame->TempEsp - 12);
- TrapFrame->ErrCode = (ULONG_PTR)ReturnStack;
-
- /* Now copy IRET frame */
- ReturnStack[0] = TrapFrame->Eip;
- ReturnStack[1] = TrapFrame->SegCs;
- ReturnStack[2] = TrapFrame->EFlags;
-
- /* Do special edited return */
- KiEditedTrapReturn(TrapFrame);
- }
-
- /* Check if this is a user trap */
- if (__builtin_expect(KiUserTrap(TrapFrame), 1)) /* Ring 3 is where we spend time */
- {
- /* Check if segments should be restored */
- if (!SkipBits.SkipSegments)
- {
- /* Restore segments */
- Ke386SetGs(TrapFrame->SegGs);
- Ke386SetEs(TrapFrame->SegEs);
- Ke386SetDs(TrapFrame->SegDs);
- Ke386SetFs(TrapFrame->SegFs);
- }
-
- /* Always restore FS since it goes from KPCR to TEB */
- Ke386SetFs(TrapFrame->SegFs);
- }
-
- /* Check for system call -- a system call skips volatiles! */
- if (__builtin_expect(SkipBits.SkipVolatiles, 0)) /* More INTs than SYSCALLs */
- {
- /* User or kernel call? */
- KiUserSystemCall(TrapFrame);
-
- /* Restore EFLags */
- __writeeflags(TrapFrame->EFlags);
-
- /* Call is kernel, so do a jump back since this wasn't a real INT */
- KiSystemCallReturn(TrapFrame);
-
- /* If we got here, this is SYSEXIT: are we stepping code? */
- if (!(TrapFrame->EFlags & EFLAGS_TF))
- {
- /* Restore user FS */
- Ke386SetFs(KGDT_R3_TEB | RPL_MASK);
-
- /* Remove interrupt flag */
- TrapFrame->EFlags &= ~EFLAGS_INTERRUPT_MASK;
- __writeeflags(TrapFrame->EFlags);
-
- /* Exit through SYSEXIT */
- KiSystemCallSysExitReturn(TrapFrame);
- }
-
- /* Exit through IRETD, either due to debugging or due to lack of SYSEXIT */
- KiSystemCallTrapReturn(TrapFrame);
- }
-
- /* Return from interrupt */
- KiTrapReturn(TrapFrame);
-}
+extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
//
// Virtual 8086 Mode Optimized Trap Exit
//
VOID
FORCEINLINE
+DECLSPEC_NORETURN
KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
{
PKTHREAD Thread;
@@ -517,6 +221,9 @@ KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
Thread = KeGetCurrentThread();
while (TRUE)
{
+ /* Return if this isn't V86 mode anymore */
+ if (!(TrapFrame->EFlags & EFLAGS_V86_MASK)) KiEoiHelper(TrapFrame);;
+
/* Turn off the alerted state for kernel mode */
Thread->Alerted[KernelMode] = FALSE;
@@ -533,9 +240,6 @@ KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
/* Restore IRQL and disable interrupts once again */
KfLowerIrql(OldIrql);
_disable();
-
- /* Return if this isn't V86 mode anymore */
- if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0)) return;
}
/* If we got here, we're still in a valid V8086 context, so quit it */
@@ -547,7 +251,7 @@ KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
}
/* Return from interrupt */
- KiTrapReturn(TrapFrame);
+ KiTrapReturnNoSegments(TrapFrame);
}
//
diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c
index c9925d5eb28..ef1b78969fb 100644
--- a/ntoskrnl/io/iomgr/driver.c
+++ b/ntoskrnl/io/iomgr/driver.c
@@ -149,6 +149,39 @@ IopGetDriverObject(
return STATUS_SUCCESS;
}
+/*
+ * RETURNS
+ * TRUE if String2 contains String1 as a suffix.
+ */
+BOOLEAN
+NTAPI
+IopSuffixUnicodeString(
+ IN PCUNICODE_STRING String1,
+ IN PCUNICODE_STRING String2)
+{
+ PWCHAR pc1;
+ PWCHAR pc2;
+ ULONG Length;
+
+ if (String2->Length < String1->Length)
+ return FALSE;
+
+ Length = String1->Length / 2;
+ pc1 = String1->Buffer;
+ pc2 = &String2->Buffer[String2->Length / sizeof(WCHAR) - Length];
+
+ if (pc1 && pc2)
+ {
+ while (Length--)
+ {
+ if( *pc1++ != *pc2++ )
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
/*
* IopDisplayLoadingMessage
*
@@ -158,35 +191,19 @@ IopGetDriverObject(
VOID
FASTCALL
INIT_FUNCTION
-IopDisplayLoadingMessage(PVOID ServiceName,
- BOOLEAN Unicode)
+IopDisplayLoadingMessage(PUNICODE_STRING ServiceName)
{
CHAR TextBuffer[256];
- PCHAR Extra = ".sys";
+ UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS");
if (ExpInTextModeSetup) return;
- if (Unicode)
- {
- if (wcsstr(_wcsupr(ServiceName), L".SYS")) Extra = "";
- sprintf(TextBuffer,
- "%s%s%s\\%S%s\n",
- KeLoaderBlock->ArcBootDeviceName,
- KeLoaderBlock->NtBootPathName,
- "System32\\Drivers",
- (PWCHAR)ServiceName,
- Extra);
- }
- else
- {
- if (strstr(_strupr(ServiceName), ".SYS")) Extra = "";
- sprintf(TextBuffer,
- "%s%s%s\\%s%s\n",
- KeLoaderBlock->ArcBootDeviceName,
- KeLoaderBlock->NtBootPathName,
- "System32\\Drivers",
- (PCHAR)ServiceName,
- Extra);
- }
+ RtlUpcaseUnicodeString(ServiceName, ServiceName, FALSE);
+ snprintf(TextBuffer, sizeof(TextBuffer),
+ "%s%sSystem32\\Drivers\\%wZ%s\n",
+ KeLoaderBlock->ArcBootDeviceName,
+ KeLoaderBlock->NtBootPathName,
+ ServiceName,
+ IopSuffixUnicodeString(&DotSys, ServiceName) ? "" : ".SYS");
HalDisplayString(TextBuffer);
}
@@ -788,7 +805,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
/*
* Display 'Loading XXX...' message
*/
- IopDisplayLoadingMessage(ModuleName->Buffer, TRUE);
+ IopDisplayLoadingMessage(ModuleName);
InbvIndicateProgress();
/*
diff --git a/ntoskrnl/io/iomgr/drvrlist.c b/ntoskrnl/io/iomgr/drvrlist.c
index 42b69c6e2bd..ecc9980db46 100644
--- a/ntoskrnl/io/iomgr/drvrlist.c
+++ b/ntoskrnl/io/iomgr/drvrlist.c
@@ -48,8 +48,7 @@ extern BOOLEAN NoGuiBoot;
VOID
FASTCALL
INIT_FUNCTION
-IopDisplayLoadingMessage(PVOID ServiceName,
- BOOLEAN Unicode);
+IopDisplayLoadingMessage(PUNICODE_STRING ServiceName);
/* PRIVATE FUNCTIONS **********************************************************/
@@ -416,7 +415,7 @@ IopLoadDriver(PSERVICE Service)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
- IopDisplayLoadingMessage(Service->ServiceName.Buffer, TRUE);
+ IopDisplayLoadingMessage(&Service->ServiceName);
Status = ZwLoadDriver(&Service->RegistryPath);
IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE);
if (!NT_SUCCESS(Status))
diff --git a/ntoskrnl/io/pnpmgr/pnpmgr.c b/ntoskrnl/io/pnpmgr/pnpmgr.c
index 890fd60d12a..e6346378566 100644
--- a/ntoskrnl/io/pnpmgr/pnpmgr.c
+++ b/ntoskrnl/io/pnpmgr/pnpmgr.c
@@ -13,7 +13,7 @@
#define NDEBUG
#include
-//#define ENABLE_ACPI
+#define ENABLE_ACPI
/* GLOBALS *******************************************************************/
@@ -1893,7 +1893,7 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
RtlInitUnicodeString(&ClassGUID, NULL);
QueryTable[0].Name = L"Service";
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[0].EntryContext = Service;
QueryTable[1].Name = L"ClassGUID";
diff --git a/ntoskrnl/ke/i386/cpu.c b/ntoskrnl/ke/i386/cpu.c
index 21d49c90123..e05a8960470 100644
--- a/ntoskrnl/ke/i386/cpu.c
+++ b/ntoskrnl/ke/i386/cpu.c
@@ -995,56 +995,6 @@ KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context)
return 0;
}
-VOID
-NTAPI
-KiDisableFastSyscallReturn(VOID)
-{
- /* Was it applied? */
- if (KiSystemCallExitAdjusted)
- {
- /* Restore the original value */
- KiSystemCallExitBranch[1] = KiSystemCallExitBranch[1] - KiSystemCallExitAdjusted;
-
- /* It's not adjusted anymore */
- KiSystemCallExitAdjusted = FALSE;
- }
-}
-
-VOID
-NTAPI
-KiEnableFastSyscallReturn(VOID)
-{
- /* Check if the patch has already been done */
- if ((KiSystemCallExitAdjusted == KiSystemCallExitAdjust) &&
- (KiFastCallCopyDoneOnce))
- {
- return;
- }
-
- /* Make sure the offset is within the distance of a Jxx SHORT */
- if ((KiSystemCallExitBranch[1] - KiSystemCallExitAdjust) < 0x80)
- {
- /* Remove any existing code patch */
- KiDisableFastSyscallReturn();
-
- /* We should have a JNZ there */
- ASSERT(KiSystemCallExitBranch[0] == 0x75);
-
- /* Do the patch */
- KiSystemCallExitAdjusted = KiSystemCallExitAdjust;
- KiSystemCallExitBranch[1] -= KiSystemCallExitAdjusted;
-
- /* Remember that we've done it */
- KiFastCallCopyDoneOnce = TRUE;
- }
- else
- {
- /* This shouldn't happen unless we've messed the macros up */
- DPRINT1("Your compiled kernel is broken!\n");
- DbgBreakPoint();
- }
-}
-
VOID
NTAPI
KiRestoreFastSyscallReturnState(VOID)
@@ -1055,28 +1005,27 @@ KiRestoreFastSyscallReturnState(VOID)
/* Check if it has been disabled */
if (!KiFastSystemCallDisable)
{
- /* KiSystemCallExit2 should come BEFORE KiSystemCallExit */
- ASSERT(KiSystemCallExit2 < KiSystemCallExit);
-
- /* It's enabled, so we'll have to do a code patch */
- KiSystemCallExitAdjust = KiSystemCallExit - KiSystemCallExit2;
+ /* Do an IPI to enable it */
+ KeIpiGenericCall(KiLoadFastSyscallMachineSpecificRegisters, 0);
+
+ /* It's enabled, so use the proper exit stub */
+ KiFastCallExitHandler = KiSystemCallSysExitReturn;
+ DPRINT1("Support for SYSENTER detected.\n");
}
else
{
/* Disable fast system call */
KeFeatureBits &= ~KF_FAST_SYSCALL;
+ KiFastCallExitHandler = KiSystemCallTrapReturn;
+ DPRINT1("Support for SYSENTER disabled.\n");
}
}
-
- /* Now check if all CPUs support fast system call, and the registry allows it */
- if (KeFeatureBits & KF_FAST_SYSCALL)
+ else
{
- /* Do an IPI to enable it */
- KeIpiGenericCall(KiLoadFastSyscallMachineSpecificRegisters, 0);
+ /* Use the IRET handler */
+ KiFastCallExitHandler = KiSystemCallTrapReturn;
+ DPRINT1("No support for SYSENTER detected.\n");
}
-
- /* Perform the code patch that is required */
- KiEnableFastSyscallReturn();
}
ULONG_PTR
diff --git a/ntoskrnl/ke/i386/trap.s b/ntoskrnl/ke/i386/trap.s
index 5f24877eeac..adfcd322dd9 100644
--- a/ntoskrnl/ke/i386/trap.s
+++ b/ntoskrnl/ke/i386/trap.s
@@ -124,13 +124,13 @@ EXTERN @KiSystemServiceHandler@8:PROC
PUBLIC _KiSystemService
_KiSystemService:
KiEnterTrap (KI_PUSH_FAKE_ERROR_CODE OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
- jmp @KiSystemServiceHandler@8
+ KiCallHandler @KiSystemServiceHandler@8
EXTERN @KiFastCallEntryHandler@8:PROC
PUBLIC _KiFastCallEntry
_KiFastCallEntry:
KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
- jmp @KiFastCallEntryHandler@8
+ KiCallHandler @KiFastCallEntryHandler@8
PUBLIC _KiStartUnexpectedRange@0
_KiStartUnexpectedRange@0:
@@ -143,4 +143,15 @@ PUBLIC _KiEndUnexpectedRange@0
_KiEndUnexpectedRange@0:
jmp _KiUnexpectedInterruptTail
+
+/* EXIT CODE *****************************************************************/
+
+KiTrapExitStub KiSystemCallReturn, (KI_RESTORE_EAX OR KI_RESTORE_EFLAGS OR KI_EXIT_JMP)
+KiTrapExitStub KiSystemCallSysExitReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_RESTORE_EFLAGS OR KI_EXIT_SYSCALL)
+KiTrapExitStub KiSystemCallTrapReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_EXIT_IRET)
+
+KiTrapExitStub KiEditedTrapReturn, (KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EDITED_FRAME OR KI_EXIT_RET)
+KiTrapExitStub KiTrapReturn, (KI_RESTORE_VOLATILES OR KI_RESTORE_SEGMENTS OR KI_EXIT_IRET)
+KiTrapExitStub KiTrapReturnNoSegments, (KI_RESTORE_VOLATILES OR KI_EXIT_IRET)
+
END
diff --git a/ntoskrnl/ke/i386/traphdlr.c b/ntoskrnl/ke/i386/traphdlr.c
index f85eb7f878c..f9a954ec298 100644
--- a/ntoskrnl/ke/i386/traphdlr.c
+++ b/ntoskrnl/ke/i386/traphdlr.c
@@ -45,6 +45,11 @@ UCHAR KiTrapIoTable[] =
0x6F, /* OUTS */
};
+PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
+
+
+/* TRAP EXIT CODE *************************************************************/
+
BOOLEAN
FORCEINLINE
KiVdmTrap(IN PKTRAP_FRAME TrapFrame)
@@ -62,12 +67,18 @@ KiV86Trap(IN PKTRAP_FRAME TrapFrame)
return ((TrapFrame->EFlags & EFLAGS_V86_MASK) != 0);
}
-/* TRAP EXIT CODE *************************************************************/
+BOOLEAN
+FORCEINLINE
+KiIsFrameEdited(IN PKTRAP_FRAME TrapFrame)
+{
+ /* An edited frame changes esp. It is marked by clearing the bits
+ defined by FRAME_EDITED in the SegCs field of the trap frame */
+ return ((TrapFrame->SegCs & FRAME_EDITED) == 0);
+}
VOID
-FASTCALL
-DECLSPEC_NORETURN
-KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
+FORCEINLINE
+KiCommonExit(IN PKTRAP_FRAME TrapFrame, const ULONG Flags)
{
/* Disable interrupts until we return */
_disable();
@@ -75,8 +86,41 @@ KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
/* Check for APC delivery */
KiCheckForApcDelivery(TrapFrame);
- /* Now exit the trap for real */
- KiExitTrap(TrapFrame, KTE_SKIP_PM_BIT);
+ /* Debugging checks */
+ KiExitTrapDebugChecks(TrapFrame, Flags);
+
+ /* Restore the SEH handler chain */
+ KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList;
+
+ /* Check if there are active debug registers */
+ if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
+ {
+ /* Not handled yet */
+ DbgPrint("Need Hardware Breakpoint Support!\n");
+ DbgBreakPoint();
+ while (TRUE);
+ }
+}
+
+VOID
+FASTCALL
+DECLSPEC_NORETURN
+KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Common trap exit code */
+ KiCommonExit(TrapFrame, 0);
+
+ /* Check if this was a V8086 trap */
+ if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame);
+
+ /* Check for user mode exit */
+ if (TrapFrame->SegCs & MODE_MASK) KiTrapReturn(TrapFrame);
+
+ /* Check for edited frame */
+ if (KiIsFrameEdited(TrapFrame)) KiEditedTrapReturn(TrapFrame);
+
+ /* Exit the trap to kernel mode */
+ KiTrapReturnNoSegments(TrapFrame);
}
VOID
@@ -85,17 +129,36 @@ DECLSPEC_NORETURN
KiServiceExit(IN PKTRAP_FRAME TrapFrame,
IN NTSTATUS Status)
{
- /* Disable interrupts until we return */
- _disable();
-
- /* Check for APC delivery */
- KiCheckForApcDelivery(TrapFrame);
+ ASSERT((TrapFrame->EFlags & EFLAGS_V86_MASK) == 0);
+ ASSERT(!KiIsFrameEdited(TrapFrame));
/* Copy the status into EAX */
TrapFrame->Eax = Status;
- /* Now exit the trap for real */
- KiExitTrap(TrapFrame, KTE_SKIP_SEG_BIT | KTE_SKIP_VOL_BIT);
+ /* Common trap exit code */
+ KiCommonExit(TrapFrame, 0);
+
+ /* Restore previous mode */
+ KeGetCurrentThread()->PreviousMode = TrapFrame->PreviousPreviousMode;
+
+ /* Check for user mode exit */
+ if (TrapFrame->SegCs & MODE_MASK)
+ {
+ /* Check if we were single stepping */
+ if (TrapFrame->EFlags & EFLAGS_TF)
+ {
+ /* Must use the IRET handler */
+ KiSystemCallTrapReturn(TrapFrame);
+ }
+ else
+ {
+ /* We can use the sysexit handler */
+ KiFastCallExitHandler(TrapFrame);
+ }
+ }
+
+ /* Exit to kernel mode */
+ KiSystemCallReturn(TrapFrame);
}
VOID
@@ -103,16 +166,26 @@ FASTCALL
DECLSPEC_NORETURN
KiServiceExit2(IN PKTRAP_FRAME TrapFrame)
{
- /* Disable interrupts until we return */
- _disable();
+ /* Common trap exit code */
+ KiCommonExit(TrapFrame, 0);
- /* Check for APC delivery */
- KiCheckForApcDelivery(TrapFrame);
+ /* Restore previous mode */
+ KeGetCurrentThread()->PreviousMode = TrapFrame->PreviousPreviousMode;
- /* Now exit the trap for real */
- KiExitTrap(TrapFrame, 0);
+ /* Check if this was a V8086 trap */
+ if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame);
+
+ /* Check for user mode exit */
+ if (TrapFrame->SegCs & MODE_MASK) KiTrapReturn(TrapFrame);
+
+ /* Check for edited frame */
+ if (KiIsFrameEdited(TrapFrame)) KiEditedTrapReturn(TrapFrame);
+
+ /* Exit the trap to kernel mode */
+ KiTrapReturnNoSegments(TrapFrame);
}
+
/* TRAP HANDLERS **************************************************************/
VOID
@@ -582,10 +655,7 @@ KiTrap06Handler(IN PKTRAP_FRAME TrapFrame)
_disable();
/* Do a quick V86 exit if possible */
- if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 1)) KiExitV86Trap(TrapFrame);
-
- /* Exit trap the slow way */
- KiEoiHelper(TrapFrame);
+ KiExitV86Trap(TrapFrame);
}
/* Save trap frame */
@@ -842,10 +912,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
_disable();
/* Do a quick V86 exit if possible */
- if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 1)) KiExitV86Trap(TrapFrame);
-
- /* Exit trap the slow way */
- KiEoiHelper(TrapFrame);
+ KiExitV86Trap(TrapFrame);
}
/* Save trap frame */
@@ -909,7 +976,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
(((Instructions[i + 2] & 0x38) == 0x10) || // LLDT
(Instructions[i + 2] == 0x18))) || // LTR
((Instructions[i + 1] == 0x01) && // LGDT or LIDT or LMSW
- (((Instructions[i + 2] & 0x38) == 0x10) || // LLGT
+ (((Instructions[i + 2] & 0x38) == 0x10) || // LGDT
(Instructions[i + 2] == 0x18) || // LIDT
(Instructions[i + 2] == 0x30))) || // LMSW
(Instructions[i + 1] == 0x08) || // INVD
@@ -921,6 +988,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
(Instructions[i + 1] == 0x24) || // MOV YYY, DR
(Instructions[i + 1] == 0x30) || // WRMSR
(Instructions[i + 1] == 0x33)) // RDPMC
+ // INVLPG, INVLPGA, SYSRET
{
/* These are all privileged */
Privileged = TRUE;
@@ -993,7 +1061,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
* a POP , which could cause an invalid segment if someone had messed
* with the segment values.
*
- * Another case is a bogus SS, which would hit a GPF when doing the ired.
+ * Another case is a bogus SS, which would hit a GPF when doing the iret.
* This could only be done through a buggy or malicious driver, or perhaps
* the kernel debugger.
*
@@ -1067,9 +1135,14 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
/* Fix it */
TrapFrame->SegEs = (KGDT_R3_DATA | RPL_MASK);
}
-
- /* Do a direct trap exit: restore volatiles only */
- KiExitTrap(TrapFrame, KTE_SKIP_PM_BIT | KTE_SKIP_SEG_BIT);
+ else
+ {
+ /* Whatever it is, we can't handle it */
+ KiSystemFatalException(EXCEPTION_GP_FAULT, TrapFrame);
+ }
+
+ /* Return to where we came from */
+ KiTrapReturn(TrapFrame);
}
VOID
@@ -1377,55 +1450,89 @@ KiDebugServiceHandler(IN PKTRAP_FRAME TrapFrame)
}
VOID
-FASTCALL
+FORCEINLINE
DECLSPEC_NORETURN
-KiSystemCall(IN ULONG SystemCallNumber,
+KiSystemCall(IN PKTRAP_FRAME TrapFrame,
IN PVOID Arguments)
{
PKTHREAD Thread;
- PKTRAP_FRAME TrapFrame;
PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
ULONG Id, Offset, StackBytes, Result;
PVOID Handler;
+ ULONG SystemCallNumber = TrapFrame->Eax;
- /* Loop because we might need to try this twice in case of a GUI call */
- while (TRUE)
+ /* Get the current thread */
+ Thread = KeGetCurrentThread();
+
+ /* Set debug header */
+ KiFillTrapFrameDebug(TrapFrame);
+
+ /* Chain trap frames */
+ TrapFrame->Edx = (ULONG_PTR)Thread->TrapFrame;
+
+ /* No error code */
+ TrapFrame->ErrCode = 0;
+
+ /* Save previous mode */
+ TrapFrame->PreviousPreviousMode = Thread->PreviousMode;
+
+ /* Save the SEH chain and terminate it for now */
+ TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+ KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
+
+ /* Clear DR7 and check for debugging */
+ TrapFrame->Dr7 = 0;
+ if (__builtin_expect(Thread->DispatcherHeader.DebugActive & 0xFF, 0))
{
- /* Decode the system call number */
- Offset = (SystemCallNumber >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK;
- Id = SystemCallNumber & SERVICE_NUMBER_MASK;
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+
+ /* Set thread fields */
+ Thread->TrapFrame = TrapFrame;
+ Thread->PreviousMode = KiUserTrap(TrapFrame);
+
+ /* Enable interrupts */
+ _enable();
+
+ /* Decode the system call number */
+ Offset = (SystemCallNumber >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK;
+ Id = SystemCallNumber & SERVICE_NUMBER_MASK;
- /* Get current thread, trap frame, and descriptor table */
- Thread = KeGetCurrentThread();
- TrapFrame = Thread->TrapFrame;
- DescriptorTable = (PVOID)((ULONG_PTR)Thread->ServiceTable + Offset);
+ /* Get descriptor table */
+ DescriptorTable = (PVOID)((ULONG_PTR)Thread->ServiceTable + Offset);
- /* Validate the system call number */
- if (__builtin_expect(Id >= DescriptorTable->Limit, 0))
+ /* Validate the system call number */
+ if (__builtin_expect(Id >= DescriptorTable->Limit, 0))
+ {
+ /* Check if this is a GUI call */
+ if (!(Offset & SERVICE_TABLE_TEST))
{
- /* Check if this is a GUI call */
- if (__builtin_expect(!(Offset & SERVICE_TABLE_TEST), 0))
- {
- /* Fail the call */
- Result = STATUS_INVALID_SYSTEM_SERVICE;
- goto ExitCall;
- }
-
- /* Convert us to a GUI thread -- must wrap in ASM to get new EBP */
- Result = KiConvertToGuiThread();
- if (__builtin_expect(!NT_SUCCESS(Result), 0))
- {
- /* Figure out how we should fail to the user */
- UNIMPLEMENTED;
- while (TRUE);
- }
-
- /* Try the call again */
- continue;
+ /* Fail the call */
+ Result = STATUS_INVALID_SYSTEM_SERVICE;
+ goto ExitCall;
}
+
+ /* Convert us to a GUI thread -- must wrap in ASM to get new EBP */
+ Result = KiConvertToGuiThread();
+ if (!NT_SUCCESS(Result))
+ {
+ /* Set the last error and fail */
+ //SetLastWin32Error(RtlNtStatusToDosError(Result));
+ goto ExitCall;
+ }
+
+ /* Reload trap frame and descriptor table pointer from new stack */
+ TrapFrame = *(volatile PVOID*)&Thread->TrapFrame;
+ DescriptorTable = (PVOID)(*(volatile ULONG_PTR*)&Thread->ServiceTable + Offset);
- /* If we made it here, the call is good */
- break;
+ /* Validate the system call number again */
+ if (Id >= DescriptorTable->Limit)
+ {
+ /* Fail the call */
+ Result = STATUS_INVALID_SYSTEM_SERVICE;
+ goto ExitCall;
+ }
}
/* Check if this is a GUI call */
@@ -1468,45 +1575,13 @@ ExitCall:
}
VOID
-FORCEINLINE
+FASTCALL
DECLSPEC_NORETURN
-KiSystemCallHandler(IN PKTRAP_FRAME TrapFrame,
- IN ULONG ServiceNumber,
- IN PVOID Arguments,
- IN PKTHREAD Thread,
- IN KPROCESSOR_MODE PreviousMode,
- IN KPROCESSOR_MODE PreviousPreviousMode,
- IN USHORT SegFs)
+KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
+ IN PVOID Arguments)
{
- /* No error code */
- TrapFrame->ErrCode = 0;
-
- /* Save previous mode and FS segment */
- TrapFrame->PreviousPreviousMode = PreviousPreviousMode;
- TrapFrame->SegFs = SegFs;
-
- /* Save the SEH chain and terminate it for now */
- TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
- KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
-
- /* Clear DR7 and check for debugging */
- TrapFrame->Dr7 = 0;
- if (__builtin_expect(Thread->DispatcherHeader.DebugActive & 0xFF, 0))
- {
- UNIMPLEMENTED;
- while (TRUE);
- }
-
- /* Set thread fields */
- Thread->TrapFrame = TrapFrame;
- Thread->PreviousMode = PreviousMode;
-
- /* Set debug header */
- KiFillTrapFrameDebug(TrapFrame);
-
- /* Enable interrupts and make the call */
- _enable();
- KiSystemCall(ServiceNumber, Arguments);
+ /* Call the shared handler (inline) */
+ KiSystemCall(TrapFrame, Arguments);
}
VOID
@@ -1515,54 +1590,20 @@ DECLSPEC_NORETURN
KiFastCallEntryHandler(IN PKTRAP_FRAME TrapFrame,
IN PVOID Arguments)
{
- PKTHREAD Thread;
-
/* Set up a fake INT Stack and enable interrupts */
TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->HardwareEsp = (ULONG_PTR)Arguments;
TrapFrame->EFlags = __readeflags() | EFLAGS_INTERRUPT_MASK;
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
TrapFrame->Eip = SharedUserData->SystemCallReturn;
+ TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK;
__writeeflags(0x2);
- /* Get the current thread */
- Thread = KeGetCurrentThread();
-
/* Arguments are actually 2 frames down (because of the double indirection) */
Arguments = (PVOID)(TrapFrame->HardwareEsp + 8);
/* Call the shared handler (inline) */
- KiSystemCallHandler(TrapFrame,
- TrapFrame->Eax,
- Arguments,
- Thread,
- UserMode,
- Thread->PreviousMode,
- KGDT_R3_TEB | RPL_MASK);
-}
-
-VOID
-FASTCALL
-DECLSPEC_NORETURN
-KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
- IN PVOID Arguments)
-{
- PKTHREAD Thread;
-
- /* Get the current thread */
- Thread = KeGetCurrentThread();
-
- /* Chain trap frames */
- TrapFrame->Edx = (ULONG_PTR)Thread->TrapFrame;
-
- /* Call the shared handler (inline) */
- KiSystemCallHandler(TrapFrame,
- TrapFrame->Eax,
- Arguments,
- Thread,
- KiUserTrap(TrapFrame),
- Thread->PreviousMode,
- TrapFrame->SegFs);
+ KiSystemCall(TrapFrame, Arguments);
}
/*
diff --git a/subsystems/win32/csrss/csrsrv/init.c b/subsystems/win32/csrss/csrsrv/init.c
index c6fa69b42de..51adb2cacca 100644
--- a/subsystems/win32/csrss/csrsrv/init.c
+++ b/subsystems/win32/csrss/csrsrv/init.c
@@ -622,7 +622,7 @@ CsrpLoadKernelModeDriver (int argc, char ** argv, char ** envp)
WCHAR ImagePath [MAX_PATH + 1] = {0};
UNICODE_STRING ModuleName;
- wcscpy (ImagePath, L"\\??\\c:\\reactos\\system32\\win32k.sys");
+ wcscpy (ImagePath, L"\\SYSTEMROOT\\system32\\win32k.sys");
// wcscat (ImagePath, Data);
RtlInitUnicodeString (& ModuleName, ImagePath);
Status = NtSetSystemInformation(/* FIXME: SystemLoadAndCallImage */
diff --git a/subsystems/win32/win32k/eng/surface.c b/subsystems/win32/win32k/eng/surface.c
index 126347bff98..464e7d0c3c1 100644
--- a/subsystems/win32/win32k/eng/surface.c
+++ b/subsystems/win32/win32k/eng/surface.c
@@ -613,9 +613,6 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
/* For topdown, the base address starts with the bits */
pso->pvScan0 = pso->pvBits;
pso->lDelta = ScanLine;
-
- /* Hack for FreeType/Font Rendering, cannot use the Aligned ScanLine */
- if (BitmapInfo->Format == BMF_1BPP) pso->lDelta = BitmapInfo->Width / 8;
}
else
{
diff --git a/subsystems/win32/win32k/objects/freetype.c b/subsystems/win32/win32k/objects/freetype.c
index bdda9c20cc6..fea0c101ee9 100644
--- a/subsystems/win32/win32k/objects/freetype.c
+++ b/subsystems/win32/win32k/objects/freetype.c
@@ -44,6 +44,7 @@
#include
#include
#include
+#include
#include
#include
@@ -81,7 +82,7 @@ typedef struct _FONT_CACHE_ENTRY
LIST_ENTRY ListEntry;
int GlyphIndex;
FT_Face Face;
- FT_Glyph Glyph;
+ FT_BitmapGlyph BitmapGlyph;
int Height;
} FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY;
static LIST_ENTRY FontCacheListHead;
@@ -1349,7 +1350,7 @@ ftGdiGetRasterizerCaps(LPRASTERIZER_STATUS lprs)
}
-FT_Glyph APIENTRY
+FT_BitmapGlyph APIENTRY
ftGdiGlyphCacheGet(
FT_Face Face,
INT GlyphIndex,
@@ -1376,10 +1377,10 @@ ftGdiGlyphCacheGet(
RemoveEntryList(CurrentEntry);
InsertHeadList(&FontCacheListHead, CurrentEntry);
- return FontEntry->Glyph;
+ return FontEntry->BitmapGlyph;
}
-FT_Glyph APIENTRY
+FT_BitmapGlyph APIENTRY
ftGdiGlyphCacheSet(
FT_Face Face,
INT GlyphIndex,
@@ -1390,6 +1391,8 @@ ftGdiGlyphCacheSet(
FT_Glyph GlyphCopy;
INT error;
PFONT_CACHE_ENTRY NewEntry;
+ FT_Bitmap AlignedBitmap;
+ FT_BitmapGlyph BitmapGlyph;
error = FT_Get_Glyph(GlyphSlot, &GlyphCopy);
if (error)
@@ -1397,6 +1400,7 @@ ftGdiGlyphCacheSet(
DPRINT1("Failure caching glyph.\n");
return NULL;
};
+
error = FT_Glyph_To_Bitmap(&GlyphCopy, RenderMode, 0, 1);
if (error)
{
@@ -1412,22 +1416,34 @@ ftGdiGlyphCacheSet(
return NULL;
}
+ BitmapGlyph = (FT_BitmapGlyph)GlyphCopy;
+ FT_Bitmap_New(&AlignedBitmap);
+ if(FT_Bitmap_Convert(GlyphSlot->library, &BitmapGlyph->bitmap, &AlignedBitmap, 4))
+ {
+ DPRINT1("Conversion failed\n");
+ FT_Done_Glyph((FT_Glyph)BitmapGlyph);
+ return NULL;
+ }
+
+ FT_Bitmap_Done(GlyphSlot->library, &BitmapGlyph->bitmap);
+ BitmapGlyph->bitmap = AlignedBitmap;
+
NewEntry->GlyphIndex = GlyphIndex;
NewEntry->Face = Face;
- NewEntry->Glyph = GlyphCopy;
+ NewEntry->BitmapGlyph = BitmapGlyph;
NewEntry->Height = Height;
InsertHeadList(&FontCacheListHead, &NewEntry->ListEntry);
if (FontCacheNumEntries++ > MAX_FONT_CACHE)
{
NewEntry = (PFONT_CACHE_ENTRY)FontCacheListHead.Blink;
- FT_Done_Glyph(NewEntry->Glyph);
+ FT_Done_Glyph((FT_Glyph)NewEntry->BitmapGlyph);
RemoveTailList(&FontCacheListHead);
ExFreePool(NewEntry);
FontCacheNumEntries--;
}
- return GlyphCopy;
+ return BitmapGlyph;
}
@@ -2112,7 +2128,7 @@ TextIntGetTextExtentPoint(PDC dc,
PFONTGDI FontGDI;
FT_Face face;
FT_GlyphSlot glyph;
- FT_Glyph realglyph;
+ FT_BitmapGlyph realglyph;
INT error, n, glyph_index, i, previous;
ULONGLONG TotalWidth = 0;
FT_CharMap charmap, found = NULL;
@@ -2208,7 +2224,7 @@ TextIntGetTextExtentPoint(PDC dc,
TotalWidth += delta.x;
}
- TotalWidth += realglyph->advance.x >> 10;
+ TotalWidth += realglyph->root.advance.x >> 10;
if (((TotalWidth + 32) >> 6) <= MaxExtent && NULL != Fit)
{
@@ -3133,8 +3149,7 @@ GreExtTextOutW(
int error, glyph_index, n, i;
FT_Face face;
FT_GlyphSlot glyph;
- FT_Glyph realglyph;
- FT_BitmapGlyph realglyph2;
+ FT_BitmapGlyph realglyph;
LONGLONG TextLeft, RealXStart;
ULONG TextTop, previous, BackgroundLeft;
FT_Bool use_kerning;
@@ -3400,7 +3415,7 @@ GreExtTextOutW(
TextWidth += delta.x;
}
- TextWidth += realglyph->advance.x >> 10;
+ TextWidth += realglyph->root.advance.x >> 10;
previous = glyph_index;
TempText++;
@@ -3475,26 +3490,12 @@ GreExtTextOutW(
}
DPRINT("TextLeft: %d\n", TextLeft);
DPRINT("TextTop: %d\n", TextTop);
-
- if (realglyph->format == ft_glyph_format_outline)
- {
- DPRINT1("Should already be done\n");
-// error = FT_Render_Glyph(glyph, RenderMode);
- error = FT_Glyph_To_Bitmap(&realglyph, RenderMode, 0, 0);
- if (error)
- {
- DPRINT1("WARNING: Failed to render glyph!\n");
- goto fail2;
- }
- }
- realglyph2 = (FT_BitmapGlyph)realglyph;
-
- DPRINT("Advance: %d\n", realglyph->advance.x);
+ DPRINT("Advance: %d\n", realglyph->root.advance.x);
if (fuOptions & ETO_OPAQUE)
{
DestRect.left = BackgroundLeft;
- DestRect.right = (TextLeft + (realglyph->advance.x >> 10) + 32) >> 6;
+ DestRect.right = (TextLeft + (realglyph->root.advance.x >> 10) + 32) >> 6;
DestRect.top = TextTop + yoff - ((face->size->metrics.ascender + 32) >> 6);
DestRect.bottom = TextTop + yoff + ((32 - face->size->metrics.descender) >> 6);
IntEngBitBlt(
@@ -3512,31 +3513,25 @@ GreExtTextOutW(
BackgroundLeft = DestRect.right;
}
- DestRect.left = ((TextLeft + 32) >> 6) + realglyph2->left;
- DestRect.right = DestRect.left + realglyph2->bitmap.width;
- DestRect.top = TextTop + yoff - realglyph2->top;
- DestRect.bottom = DestRect.top + realglyph2->bitmap.rows;
+ DestRect.left = ((TextLeft + 32) >> 6) + realglyph->left;
+ DestRect.right = DestRect.left + realglyph->bitmap.width;
+ DestRect.top = TextTop + yoff - realglyph->top;
+ DestRect.bottom = DestRect.top + realglyph->bitmap.rows;
- bitSize.cx = realglyph2->bitmap.width;
- bitSize.cy = realglyph2->bitmap.rows;
- MaskRect.right = realglyph2->bitmap.width;
- MaskRect.bottom = realglyph2->bitmap.rows;
+ bitSize.cx = realglyph->bitmap.width;
+ bitSize.cy = realglyph->bitmap.rows;
+ MaskRect.right = realglyph->bitmap.width;
+ MaskRect.bottom = realglyph->bitmap.rows;
/*
* We should create the bitmap out of the loop at the biggest possible
* glyph size. Then use memset with 0 to clear it and sourcerect to
* limit the work of the transbitblt.
- *
- * FIXME: DIB bitmaps should have an lDelta which is a multiple of 4.
- * Here we pass in the pitch from the FreeType bitmap, which is not
- * guaranteed to be a multiple of 4. If it's not, we should expand
- * the FreeType bitmap to a temporary bitmap.
*/
- HSourceGlyph = EngCreateBitmap(bitSize, realglyph2->bitmap.pitch,
- (realglyph2->bitmap.pixel_mode == ft_pixel_mode_grays) ?
- BMF_8BPP : BMF_1BPP, BMF_TOPDOWN,
- realglyph2->bitmap.buffer);
+ HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
+ BMF_8BPP, BMF_TOPDOWN,
+ realglyph->bitmap.buffer);
if ( !HSourceGlyph )
{
DPRINT1("WARNING: EngLockSurface() failed!\n");
@@ -3590,7 +3585,7 @@ GreExtTextOutW(
if (NULL == Dx)
{
- TextLeft += realglyph->advance.x >> 10;
+ TextLeft += realglyph->root.advance.x >> 10;
DPRINT("new TextLeft: %d\n", TextLeft);
}
else