diff --git a/reactos/base/applications/msconfig/srvpage.c b/reactos/base/applications/msconfig/srvpage.c index 3e9e43cb250..4b13ee3f0a7 100644 --- a/reactos/base/applications/msconfig/srvpage.c +++ b/reactos/base/applications/msconfig/srvpage.c @@ -145,7 +145,7 @@ GetServices ( void ) if (hService != INVALID_HANDLE_VALUE) { /* check if service is required by the system*/ - if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)pServiceFailureActions, 0, &BytesNeeded)) + if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)NULL, 0, &BytesNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { @@ -156,11 +156,17 @@ GetServices ( void ) if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)pServiceFailureActions, BytesNeeded, &BytesNeeded)) { HeapFree(GetProcessHeap(), 0, pServiceFailureActions); + HeapFree(GetProcessHeap(), 0, pServiceStatus); + CloseServiceHandle(hService); + CloseServiceHandle(ScHandle); return; } } else /* exit on failure */ { + HeapFree(GetProcessHeap(), 0, pServiceStatus); + CloseServiceHandle(hService); + CloseServiceHandle(ScHandle); return; } } @@ -183,22 +189,32 @@ GetServices ( void ) /* get vendor of service binary */ BytesNeeded = 0; - if (!QueryServiceConfig(hService, pServiceConfig, 0, &BytesNeeded)) + if (!QueryServiceConfig(hService, NULL, 0, &BytesNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pServiceConfig = (LPQUERY_SERVICE_CONFIG) HeapAlloc(GetProcessHeap(), 0, BytesNeeded); if (pServiceConfig == NULL) + { + HeapFree(GetProcessHeap(), 0, pServiceStatus); + CloseServiceHandle(hService); + CloseServiceHandle(ScHandle); return; - + } if (!QueryServiceConfig(hService, pServiceConfig, BytesNeeded, &BytesNeeded)) { HeapFree(GetProcessHeap(), 0, pServiceConfig); + HeapFree(GetProcessHeap(), 0, pServiceStatus); + CloseServiceHandle(hService); + CloseServiceHandle(ScHandle); return; } } else /* exit on failure */ { + HeapFree(GetProcessHeap(), 0, pServiceStatus); + CloseServiceHandle(hService); + CloseServiceHandle(ScHandle); return; } } @@ -221,11 +237,18 @@ GetServices ( void ) { lpData = (TCHAR*) HeapAlloc(GetProcessHeap(), 0, dwLen); if (lpData == NULL) + { + HeapFree(GetProcessHeap(), 0, pServiceStatus); + CloseServiceHandle(hService); + CloseServiceHandle(ScHandle); return; - + } if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) { HeapFree(GetProcessHeap(), 0, lpData); + HeapFree(GetProcessHeap(), 0, pServiceStatus); + CloseServiceHandle(hService); + CloseServiceHandle(ScHandle); return; } diff --git a/reactos/base/applications/mscutils/eventvwr/eventvwr.c b/reactos/base/applications/mscutils/eventvwr/eventvwr.c index 9877d0f01cc..505302b50ea 100644 --- a/reactos/base/applications/mscutils/eventvwr/eventvwr.c +++ b/reactos/base/applications/mscutils/eventvwr/eventvwr.c @@ -296,6 +296,10 @@ BOOL GetEventMessage( // Allocate space for parameters szArguments = (LPTSTR*)malloc(sizeof(LPVOID)* pevlr->NumStrings); + if (!szArguments) + { + return FALSE; + } for (i = 0; i < pevlr->NumStrings ; i++) { @@ -372,6 +376,8 @@ BOOL GetEventMessage( wsprintf (EventText, szStringIDNotFound , (DWORD)(pevlr->EventID & 0xFFFF) , SourceName ); } + free(szArguments); + // No more dlls to try , return result return bDone; } diff --git a/reactos/base/applications/network/finger/finger.c b/reactos/base/applications/network/finger/finger.c index 358bb4fa95a..ddb4bebaf1d 100644 --- a/reactos/base/applications/network/finger/finger.c +++ b/reactos/base/applications/network/finger/finger.c @@ -122,7 +122,7 @@ main(int argc, char **argv) static void userlist(int argc, char **argv) { - int *used; + int *used = NULL; char **ap, **nargv, **np, **p; WORD wVersionRequested; WSADATA wsaData; @@ -166,6 +166,8 @@ userlist(int argc, char **argv) /* Bring down winsock */ WSACleanup(); + free(nargv); + free(used); exit(0); } diff --git a/reactos/base/applications/network/ipconfig/ipconfig.c b/reactos/base/applications/network/ipconfig/ipconfig.c index 4d496d53d49..a44fcc2a4f9 100644 --- a/reactos/base/applications/network/ipconfig/ipconfig.c +++ b/reactos/base/applications/network/ipconfig/ipconfig.c @@ -454,7 +454,10 @@ VOID ShowInfo(BOOL bAll) _tprintf(_T("\tIP Address. . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpAddress.String); _tprintf(_T("\tSubnet Mask . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpMask.String); - _tprintf(_T("\tDefault Gateway . . . . . . . . . : %s\n"), pAdapter->GatewayList.IpAddress.String); + if (pAdapter->GatewayList.IpAddress.String[0] != '0') + _tprintf(_T("\tDefault Gateway . . . . . . . . . : %s\n"), pAdapter->GatewayList.IpAddress.String); + else + _tprintf(_T("\tDefault Gateway . . . . . . . . . :\n")); if (bAll) { diff --git a/reactos/base/services/dhcp/dhclient.c b/reactos/base/services/dhcp/dhclient.c index ed7ff2d6eab..2e2a34510cc 100644 --- a/reactos/base/services/dhcp/dhclient.c +++ b/reactos/base/services/dhcp/dhclient.c @@ -525,7 +525,7 @@ void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) { &Adapter->NteContext, &Adapter->NteInstance ); if (hkey) { - RegSetValueExA(hkey, "DhcpIPAddress", 0, REG_SZ, (LPBYTE)new_lease->address.iabuf, strlen(new_lease->address.iabuf)+1); + RegSetValueExA(hkey, "DhcpIPAddress", 0, REG_SZ, (LPBYTE)piaddr(new_lease->address), strlen(piaddr(new_lease->address))+1); Buffer[0] = '\0'; for(i = 0; i < new_lease->options[DHO_SUBNET_MASK].len; i++) { diff --git a/reactos/base/shell/explorer-new/traywnd.c b/reactos/base/shell/explorer-new/traywnd.c index e42e61f1892..21b80429ba8 100644 --- a/reactos/base/shell/explorer-new/traywnd.c +++ b/reactos/base/shell/explorer-new/traywnd.c @@ -699,6 +699,15 @@ ITrayWindowImpl_RegLoadSettings(IN OUT ITrayWindowImpl *This) /* FIXME: Are there more flags? */ + if (This->hWnd != NULL) + SetWindowPos (This->hWnd, + This->AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, + 0, + 0, + 0, + 0, + SWP_NOMOVE | SWP_NOSIZE); + if (sr.Position > ABE_BOTTOM) This->Position = ABE_BOTTOM; else diff --git a/reactos/base/system/smss/smss.h b/reactos/base/system/smss/smss.h index 23e3cd0a46a..2db83d39ebb 100644 --- a/reactos/base/system/smss/smss.h +++ b/reactos/base/system/smss/smss.h @@ -2,6 +2,7 @@ #define _SMSS_H_INCLUDED_ #include +#include #define WIN32_NO_STATUS #include #define NTOS_MODE_USER diff --git a/reactos/dll/win32/iphlpapi/iphlpapi_main.c b/reactos/dll/win32/iphlpapi/iphlpapi_main.c index 0f3c04b16bb..49ca1740bc7 100644 --- a/reactos/dll/win32/iphlpapi/iphlpapi_main.c +++ b/reactos/dll/win32/iphlpapi/iphlpapi_main.c @@ -1367,7 +1367,7 @@ DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) if (!resInfo) return ERROR_OUTOFMEMORY; - size = sizeof(FIXED_INFO) + (resInfo->riCount > 0 ? (resInfo->riCount - 1) * + size = sizeof(FIXED_INFO) + (resInfo->riCount > 1 ? (resInfo->riCount-1) * sizeof(IP_ADDR_STRING) : 0); if (!pFixedInfo || *pOutBufLen < size) { *pOutBufLen = size; @@ -1383,25 +1383,16 @@ DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName); - if (resInfo->riCount > 0) { - PIP_ADDR_STRING ptr; - int i; - - for (i = 0, ptr = &pFixedInfo->DnsServerList; i < resInfo->riCount && ptr; - i++, ptr = ptr->Next) { - struct sockaddr_in *addr_v4 = - (struct sockaddr_in *)&resInfo->riAddressList[i]; - toIPAddressString - (addr_v4->sin_addr.s_addr, - ptr->IpAddress.String); - if (i == resInfo->riCount - 1) - ptr->Next = NULL; - else if (i == 0) - ptr->Next = (PIP_ADDR_STRING)((LPBYTE)pFixedInfo + sizeof(FIXED_INFO)); - else - ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDR_STRING)); + if (resInfo->riCount > 0) + { + CopyMemory(&pFixedInfo->DnsServerList, resInfo->DnsList, sizeof(IP_ADDR_STRING)); + if (resInfo->riCount > 1) + { + pFixedInfo->DnsServerList.Next = (struct _IP_ADDR_STRING*)((char*)pFixedInfo + sizeof(FIXED_INFO)); + CopyMemory(pFixedInfo->DnsServerList.Next, resInfo->DnsList->Next, sizeof(IP_ADDR_STRING) * (resInfo->riCount-1)); } } + pFixedInfo->NodeType = HYBRID_NODETYPE; regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey); @@ -1490,7 +1481,7 @@ static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server, Context->uSizeRequired += sizeof(IP_ADDR_STRING); if (Context->uSizeAvailable >= Context->uSizeRequired) { - pNext = ((char*)Context->pLastAddr) + sizeof(IP_ADDR_STRING); + pNext = (IP_ADDR_STRING*)(((char*)Context->pLastAddr) + sizeof(IP_ADDR_STRING)); WideCharToMultiByte(CP_ACP, 0, Server, -1, pNext->IpAddress.String, 16, NULL, NULL); pNext->IpAddress.String[15] = '\0'; Context->pLastAddr->Next = pNext; diff --git a/reactos/dll/win32/iphlpapi/resinfo.h b/reactos/dll/win32/iphlpapi/resinfo.h index 415f39eb5ce..789026803c1 100644 --- a/reactos/dll/win32/iphlpapi/resinfo.h +++ b/reactos/dll/win32/iphlpapi/resinfo.h @@ -23,6 +23,7 @@ typedef struct _IPHLP_RES_INFO { DWORD riCount; + IP_ADDR_STRING * DnsList; struct sockaddr_in *riAddressList; } IPHLP_RES_INFO, *PIPHLP_RES_INFO; diff --git a/reactos/dll/win32/iphlpapi/resinfo_reactos.c b/reactos/dll/win32/iphlpapi/resinfo_reactos.c index 81ddec8fe3f..5a8a2313a22 100644 --- a/reactos/dll/win32/iphlpapi/resinfo_reactos.c +++ b/reactos/dll/win32/iphlpapi/resinfo_reactos.c @@ -49,8 +49,7 @@ typedef struct _NAME_SERVER_LIST_PRIVATE { UINT NumServers; - UINT CurrentName; - PIP_ADDRESS_STRING AddrString; + IP_ADDR_STRING * pCurrent; } NAME_SERVER_LIST_PRIVATE, *PNAME_SERVER_LIST_PRIVATE; NTSYSAPI @@ -177,22 +176,23 @@ static void CreateNameServerListEnumIfFuncCount( HKEY RegHandle, CreateNameServerListEnumNamesFuncCount); } -VOID CreateNameServerListEnumNamesFunc( PWCHAR Interface, - PWCHAR Server, - PVOID _Data ) { +VOID CreateNameServerListEnumNamesFunc( + PWCHAR Interface, + PWCHAR Server, + PVOID _Data ) +{ PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data; - if (WideCharToMultiByte(CP_ACP, 0, Server, -1, - Data->AddrString[Data->CurrentName].String, - 16, NULL, NULL)) - { - Data->AddrString[Data->CurrentName].String[15] = '\0'; - Data->CurrentName++; - } - else - { - Data->AddrString[Data->CurrentName].String[0] = '\0'; - } + if (WideCharToMultiByte(CP_ACP, 0, Server, -1, Data->pCurrent->IpAddress.String, 16, NULL, NULL)) + { + Data->pCurrent->Next = (struct _IP_ADDR_STRING*)(char*)Data->pCurrent + sizeof(IP_ADDR_STRING); + Data->pCurrent = Data->pCurrent->Next; + Data->NumServers++; + } + else + { + Data->pCurrent->IpAddress.String[0] = '\0'; + } } static void CreateNameServerListEnumIfFunc( HKEY RegHandle, @@ -213,51 +213,37 @@ static void MakeNameServerList( PNAME_SERVER_LIST_PRIVATE PrivateData ) { } PIPHLP_RES_INFO getResInfo() { - DWORD i, ServerCount; - NAME_SERVER_LIST_PRIVATE PrivateNSEnum = { 0 }; + DWORD ServerCount; + NAME_SERVER_LIST_PRIVATE PrivateNSEnum; PIPHLP_RES_INFO ResInfo; - struct sockaddr_in *AddrList; + IP_ADDR_STRING * DnsList; + PrivateNSEnum.NumServers = 0; ServerCount = CountNameServers( &PrivateNSEnum ); PrivateNSEnum.NumServers = ServerCount; - PrivateNSEnum.AddrString = - (PIP_ADDRESS_STRING) - RtlAllocateHeap( GetProcessHeap(), 0, - ServerCount * sizeof(IP_ADDRESS_STRING) ); - PrivateNSEnum.CurrentName = 0; + DnsList = HeapAlloc(GetProcessHeap(), 0, ServerCount * sizeof(IP_ADDR_STRING)); + ZeroMemory(DnsList, ServerCount * sizeof(IP_ADDR_STRING)); - ResInfo = - (PIPHLP_RES_INFO)RtlAllocateHeap - ( GetProcessHeap(), 0, - sizeof(IPHLP_RES_INFO) + - (ServerCount * sizeof(struct sockaddr_in)) ); - - if( !ResInfo ) { - RtlFreeHeap( GetProcessHeap(), 0, PrivateNSEnum.AddrString ); - return NULL; + ResInfo = (PIPHLP_RES_INFO)RtlAllocateHeap ( GetProcessHeap(), 0, sizeof(IPHLP_RES_INFO)); + if( !ResInfo ) + { + HeapFree( GetProcessHeap(), 0, DnsList ); + return NULL; } - ResInfo->riCount = ServerCount; - AddrList = (struct sockaddr_in *) - (((PCHAR)ResInfo) + sizeof(IPHLP_RES_INFO)); - ResInfo->riAddressList = AddrList; + PrivateNSEnum.NumServers = 0; + PrivateNSEnum.pCurrent = DnsList; MakeNameServerList( &PrivateNSEnum ); - - for( i = 0; i < PrivateNSEnum.CurrentName; i++ ) { - /* Hmm seems that dns servers are always AF_INET but ... */ - ResInfo->riAddressList[i].sin_family = AF_INET; - ResInfo->riAddressList[i].sin_addr.s_addr = - inet_addr(PrivateNSEnum.AddrString[i].String ); - ResInfo->riAddressList[i].sin_port = 0; - } - - RtlFreeHeap( GetProcessHeap(), 0, PrivateNSEnum.AddrString ); + ResInfo->DnsList = DnsList; + ResInfo->riCount = PrivateNSEnum.NumServers; return ResInfo; } -VOID disposeResInfo( PIPHLP_RES_INFO InfoPtr ) { +VOID disposeResInfo( PIPHLP_RES_INFO InfoPtr ) +{ RtlFreeHeap( GetProcessHeap(), 0, InfoPtr ); + HeapFree(GetProcessHeap(), 0, InfoPtr->DnsList); } diff --git a/reactos/dll/win32/netcfgx/inetcfgcomp_iface.c b/reactos/dll/win32/netcfgx/inetcfgcomp_iface.c index 738558a38a3..f44b7ff3eb6 100644 --- a/reactos/dll/win32/netcfgx/inetcfgcomp_iface.c +++ b/reactos/dll/win32/netcfgx/inetcfgcomp_iface.c @@ -7,7 +7,6 @@ typedef struct LONG ref; NetCfgComponentItem * pItem; INetCfgComponentPropertyUi * pProperty; - INetCfgComponentControl * pNCCC; INetCfg * pNCfg; }INetCfgComponentImpl; @@ -20,8 +19,6 @@ typedef struct INetCfg * pNCfg; }IEnumNetCfgComponentImpl; - - HRESULT STDCALL INetCfgComponent_fnQueryInterface( @@ -43,7 +40,6 @@ INetCfgComponent_fnQueryInterface( return E_NOINTERFACE; } - ULONG STDCALL INetCfgComponent_fnAddRef( @@ -420,7 +416,7 @@ CreateNotificationObject( return hr; } This->pProperty = pNCCPU; - This->pNCCC = pNCCC; + This->pItem->pNCCC = pNCCC; return S_OK; } @@ -467,20 +463,14 @@ INetCfgComponent_fnRaisePropertyUi( pinfo.pszCaption = This->pItem->szDisplayName; iResult = PropertySheetW(&pinfo); - CoTaskMemFree(hppages); - if (iResult < 0) + if (iResult > 0) { - //FIXME - INetCfgComponentControl_CancelChanges(This->pNCCC); - return E_ABORT; - } - else - { - //FIXME - INetCfgComponentControl_ApplyRegistryChanges(This->pNCCC); + /* indicate that settings should be stored */ + This->pItem->bChanged = TRUE; return S_OK; } + return S_FALSE; } static const INetCfgComponentVtbl vt_NetCfgComponent = { diff --git a/reactos/dll/win32/netcfgx/netcfg_iface.c b/reactos/dll/win32/netcfgx/netcfg_iface.c index c7412c68bea..026e6a64ec5 100644 --- a/reactos/dll/win32/netcfgx/netcfg_iface.c +++ b/reactos/dll/win32/netcfgx/netcfg_iface.c @@ -533,6 +533,56 @@ INetCfg_fnInitialize( return S_OK; } +VOID +ApplyOrCancelChanges( + NetCfgComponentItem *pHead, + const CLSID * lpClassGUID, + BOOL bApply) +{ + HKEY hKey; + WCHAR szName[200]; + LPOLESTR pszGuid; + + while(pHead) + { + if (pHead->bChanged) + { + if (IsEqualGUID(lpClassGUID, &GUID_DEVCLASS_NET)) + { + if (bApply) + { + if (StringFromCLSID(&pHead->InstanceId, &pszGuid) == NOERROR) + { + swprintf(szName, L"SYSTEM\\CurrentControlSet\\Control\\Network\\%s", pszGuid); + CoTaskMemFree(pszGuid); + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)pHead->szDisplayName, (wcslen(pHead->szDisplayName)+1) * sizeof(WCHAR)); + RegCloseKey(hKey); + } + } + } + } + else if (pHead->pNCCC) + { + if (bApply) + { + INetCfgComponentControl_ApplyRegistryChanges(pHead->pNCCC); + //FIXME + // implement INetCfgPnpReconfigCallback and pass it to + //INetCfgComponentControl_ApplyPnpChanges(pHead->pNCCC, NULL); + } + else + { + INetCfgComponentControl_CancelChanges(pHead->pNCCC); + } + } + } + pHead = pHead->pNext; + } +} + HRESULT STDCALL INetCfg_fnUninitialize( @@ -557,8 +607,12 @@ INetCfg_fnApply( if (!This->bInitialized) return NETCFG_E_NOT_INITIALIZED; + ApplyOrCancelChanges(This->pNet, &GUID_DEVCLASS_NET, TRUE); + ApplyOrCancelChanges(This->pClient, &GUID_DEVCLASS_NETCLIENT, TRUE); + ApplyOrCancelChanges(This->pService, &GUID_DEVCLASS_NETSERVICE, TRUE); + ApplyOrCancelChanges(This->pProtocol, &GUID_DEVCLASS_NETTRANS, TRUE); - return E_NOTIMPL; + return S_OK; } HRESULT @@ -571,7 +625,11 @@ INetCfg_fnCancel( if (!This->bInitialized) return NETCFG_E_NOT_INITIALIZED; - return E_NOTIMPL; + ApplyOrCancelChanges(This->pClient, &GUID_DEVCLASS_NETCLIENT, FALSE); + ApplyOrCancelChanges(This->pService, &GUID_DEVCLASS_NETSERVICE, FALSE); + ApplyOrCancelChanges(This->pProtocol, &GUID_DEVCLASS_NETTRANS, FALSE); + + return S_OK; } HRESULT diff --git a/reactos/dll/win32/netcfgx/netcfgx.rbuild b/reactos/dll/win32/netcfgx/netcfgx.rbuild index c6d7998e184..f520bd7149f 100644 --- a/reactos/dll/win32/netcfgx/netcfgx.rbuild +++ b/reactos/dll/win32/netcfgx/netcfgx.rbuild @@ -14,6 +14,7 @@ ole32 user32 comctl32 + ws2_32 netcfgx.c netcfgx.spec classfactory.c diff --git a/reactos/dll/win32/netcfgx/precomp.h b/reactos/dll/win32/netcfgx/precomp.h index 7c9233e86c3..42b7afafab2 100644 --- a/reactos/dll/win32/netcfgx/precomp.h +++ b/reactos/dll/win32/netcfgx/precomp.h @@ -34,6 +34,7 @@ typedef struct tagNetCfgComponentItem ULONG Status; //Y BOOL bChanged; //Y struct tagNetCfgComponentItem * pNext; + INetCfgComponentControl * pNCCC; }NetCfgComponentItem; /* netcfg_iface.c */ diff --git a/reactos/dll/win32/netcfgx/tcpipconf_notify.c b/reactos/dll/win32/netcfgx/tcpipconf_notify.c index 270f432d702..6aa9b69b5fa 100644 --- a/reactos/dll/win32/netcfgx/tcpipconf_notify.c +++ b/reactos/dll/win32/netcfgx/tcpipconf_notify.c @@ -34,6 +34,7 @@ typedef struct tagIP_ADDR DWORD Subnetmask; USHORT Metric; }u; + ULONG NTEContext; struct tagIP_ADDR * Next; }IP_ADDR; @@ -115,6 +116,7 @@ INT GetSelectedItem(HWND hDlgCtrl); HRESULT InitializeTcpipBasicDlgCtrls(HWND hwndDlg, TcpipSettings * pCurSettings); VOID InsertColumnToListView(HWND hDlgCtrl, UINT ResId, UINT SubItem, UINT Size); INT_PTR StoreTcpipBasicSettings(HWND hwndDlg, TcpipConfNotifyImpl * This, BOOL bApply); +HRESULT Initialize(TcpipConfNotifyImpl * This); VOID DisplayError(UINT ResTxt, UINT ResTitle, UINT Type) @@ -2172,6 +2174,15 @@ StoreTcpipBasicSettings( /* store default gateway */ This->pCurrentConfig->Gw->IpAddress = dwIpAddr; } + else + { + if (This->pCurrentConfig->Gw) + { + IP_ADDR * pNextGw = This->pCurrentConfig->Gw->Next; + CoTaskMemFree(This->pCurrentConfig->Gw); + This->pCurrentConfig->Gw = pNextGw; + } + } } else { @@ -2302,7 +2313,7 @@ InitializeTcpipBasicDlgCtrls( /* set current hostmask */ SendDlgItemMessageA(hwndDlg, IDC_SUBNETMASK, IPM_SETADDRESS, 0, (LPARAM)pCurSettings->Ip->u.Subnetmask); } - if (pCurSettings->Gw->IpAddress) + if (pCurSettings->Gw && pCurSettings->Gw->IpAddress) { /* set current gateway */ SendDlgItemMessageA(hwndDlg, IDC_DEFGATEWAY, IPM_SETADDRESS, 0, (LPARAM)pCurSettings->Gw->IpAddress); @@ -2373,6 +2384,7 @@ CopyIpAddrString( if (Type == SUBMASK) { pNew->u.Subnetmask = GetIpAddressFromStringA(pCurrent->IpMask.String); + pNew->NTEContext = pCurrent->Context; } else if (Type == METRIC) { @@ -2632,6 +2644,7 @@ LoadDNSSettings( HKEY hKey; DWORD dwSize; + This->pCurrentConfig->pDNS = (TcpipAdvancedDNSDlgSettings*) CoTaskMemAlloc(sizeof(TcpipAdvancedDNSDlgSettings)); if (!This->pCurrentConfig->pDNS) return E_FAIL; @@ -2748,7 +2761,7 @@ LoadFilterSettings( HRESULT -InitializeTcpipBasicDlg(TcpipConfNotifyImpl * This) +Initialize(TcpipConfNotifyImpl * This) { DWORD dwSize; WCHAR szBuffer[50]; @@ -2876,7 +2889,7 @@ INetCfgComponentPropertyUi_fnMergePropPages( HRESULT hr; TcpipConfNotifyImpl * This = (TcpipConfNotifyImpl*)iface; - hr = InitializeTcpipBasicDlg(This); + hr = Initialize(This); if (FAILED(hr)) return hr; @@ -3092,24 +3105,37 @@ INetCfgComponentControl_fnApplyRegistryChanges( LPOLESTR pStr; DWORD dwSize; WCHAR szBuffer[200]; + TcpipSettings * pCurrentConfig, *pOldConfig; + ULONG NTEInstance; TcpipConfNotifyImpl * This = impl_from_INetCfgComponentControl(iface); + pCurrentConfig = This->pCurrentConfig; + This->pCurrentConfig = NULL; + + if (FAILED(Initialize(This))) + { + This->pCurrentConfig = pCurrentConfig; + return E_FAIL; + } + pOldConfig = This->pCurrentConfig; + This->pCurrentConfig = pCurrentConfig; + //MessageBoxW(NULL, L"INetCfgComponentControl_fnApplyRegistryChanges", NULL, MB_OK); if (RegCreateKeyExW(hKey, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) { - if (This->pCurrentConfig->pDNS) + if (pCurrentConfig->pDNS) { - RegSetValueExW(hKey, L"UseDomainNameDevolution", 0, REG_DWORD, (LPBYTE)&This->pCurrentConfig->pDNS->UseDomainNameDevolution, sizeof(DWORD)); - RegSetValueExW(hKey, L"SearchList", 0, REG_SZ, (LPBYTE)This->pCurrentConfig->pDNS->szSearchList, - (wcslen(This->pCurrentConfig->pDNS->szSearchList)+1) * sizeof(WCHAR)); + RegSetValueExW(hKey, L"UseDomainNameDevolution", 0, REG_DWORD, (LPBYTE)&pCurrentConfig->pDNS->UseDomainNameDevolution, sizeof(DWORD)); + RegSetValueExW(hKey, L"SearchList", 0, REG_SZ, (LPBYTE)pCurrentConfig->pDNS->szSearchList, + (wcslen(pCurrentConfig->pDNS->szSearchList)+1) * sizeof(WCHAR)); } - if (This->pCurrentConfig->pFilter) + if (pCurrentConfig->pFilter) { RegSetValueExW(hKey, L"EnableSecurityFilters", 0, REG_DWORD, - (LPBYTE)&This->pCurrentConfig->pFilter->EnableSecurityFilters, sizeof(DWORD)); + (LPBYTE)&pCurrentConfig->pFilter->EnableSecurityFilters, sizeof(DWORD)); } RegCloseKey(hKey); } @@ -3122,86 +3148,154 @@ INetCfgComponentControl_fnApplyRegistryChanges( if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szBuffer, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) { - if (This->pCurrentConfig->pDNS) + if (pCurrentConfig->pDNS) { RegSetValueExW(hKey, L"RegisterAdapterName", 0, REG_DWORD, (LPBYTE)&This->pCurrentConfig->pDNS->RegisterAdapterName, sizeof(DWORD)); RegSetValueExW(hKey, L"RegistrationEnabled", 0, REG_DWORD, (LPBYTE)&This->pCurrentConfig->pDNS->RegistrationEnabled, sizeof(DWORD)); RegSetValueExW(hKey, L"Domain", 0, REG_SZ, (LPBYTE)This->pCurrentConfig->pDNS->szDomain, (wcslen(This->pCurrentConfig->pDNS->szDomain)+1) * sizeof(WCHAR)); } - - if (This->pCurrentConfig->pFilter) +#if 0 + if (pCurrentConfig->pFilter) { - RegSetValueExW(hKey, L"TCPAllowedPorts", 0, REG_MULTI_SZ, - (LPBYTE)This->pCurrentConfig->pFilter->szTCPAllowedPorts, - This->pCurrentConfig->pFilter->TCPSize); - - RegSetValueExW(hKey, L"UDPAllowedPorts", 0, REG_MULTI_SZ, - (LPBYTE)This->pCurrentConfig->pFilter->szUDPAllowedPorts, - This->pCurrentConfig->pFilter->UDPSize); - - RegSetValueExW(hKey, L"RawIPAllowedProtocols", 0, REG_MULTI_SZ, - (LPBYTE)This->pCurrentConfig->pFilter->szRawIPAllowedProtocols, - This->pCurrentConfig->pFilter->IPSize); + if (pCurrentConfig->pFilter->szTCPAllowedPorts) + { + RegSetValueExW(hKey, L"TCPAllowedPorts", 0, REG_MULTI_SZ, + (LPBYTE)pCurrentConfig->pFilter->szTCPAllowedPorts, + pCurrentConfig->pFilter->TCPSize); + } + if (pCurrentConfig->pFilter->szUDPAllowedPorts) + { + RegSetValueExW(hKey, L"UDPAllowedPorts", 0, REG_MULTI_SZ, + (LPBYTE)pCurrentConfig->pFilter->szUDPAllowedPorts, + pCurrentConfig->pFilter->UDPSize); + } + if (pCurrentConfig->pFilter->szRawIPAllowedProtocols) + { + RegSetValueExW(hKey, L"RawIPAllowedProtocols", 0, REG_MULTI_SZ, + (LPBYTE)pCurrentConfig->pFilter->szRawIPAllowedProtocols, + pCurrentConfig->pFilter->IPSize); + } } - - RegSetValueExW(hKey, L"EnableDHCP", 0, REG_DWORD, (LPBYTE)&This->pCurrentConfig->DhcpEnabled, sizeof(DWORD)); - if (This->pCurrentConfig->DhcpEnabled) +#endif + RegSetValueExW(hKey, L"EnableDHCP", 0, REG_DWORD, (LPBYTE)&pCurrentConfig->DhcpEnabled, sizeof(DWORD)); + if (pCurrentConfig->DhcpEnabled) { RegSetValueExW(hKey, L"IPAddress", 0, REG_MULTI_SZ, (LPBYTE)L"0.0.0.0\0", 9 * sizeof(WCHAR)); RegSetValueExW(hKey, L"SubnetMask", 0, REG_MULTI_SZ, (LPBYTE)L"0.0.0.0\0", 9 * sizeof(WCHAR)); RegSetValueExW(hKey, L"DefaultGateway", 0, REG_MULTI_SZ, (LPBYTE)L"\0", 2 * sizeof(WCHAR)); RegSetValueExW(hKey, L"DefaultGatewayMetric", 0, REG_MULTI_SZ, (LPBYTE)L"\0", 2 * sizeof(WCHAR)); + if (!pOldConfig->DhcpEnabled) + { + DeleteIPAddress(pOldConfig->Ip->NTEContext); + //FIXME + // start dhcp client service for the adapter + } } else { - pStr = CreateMultiSzString(This->pCurrentConfig->Ip, IPADDR, &dwSize, FALSE); - if(pStr) + if (!pOldConfig->DhcpEnabled) { - RegSetValueExW(hKey, L"IPAddress", 0, REG_MULTI_SZ, (LPBYTE)pStr, dwSize); - CoTaskMemFree(pStr); + DeleteIPAddress(pOldConfig->Ip->NTEContext); + //TODO + //delete multiple ip addresses when required } - pStr = CreateMultiSzString(This->pCurrentConfig->Ip, SUBMASK, &dwSize, FALSE); - if(pStr) + //TODO + // add multiple ip addresses when required + if (AddIPAddress(htonl(pCurrentConfig->Ip->IpAddress), htonl(pCurrentConfig->Ip->u.Subnetmask), pCurrentConfig->Index, &pCurrentConfig->Ip->NTEContext, &NTEInstance) == NO_ERROR) { - RegSetValueExW(hKey, L"SubnetMask", 0, REG_MULTI_SZ, (LPBYTE)pStr, dwSize); - CoTaskMemFree(pStr); + pStr = CreateMultiSzString(pCurrentConfig->Ip, IPADDR, &dwSize, FALSE); + if(pStr) + { + RegSetValueExW(hKey, L"IPAddress", 0, REG_MULTI_SZ, (LPBYTE)pStr, dwSize); + CoTaskMemFree(pStr); + } + + pStr = CreateMultiSzString(pCurrentConfig->Ip, SUBMASK, &dwSize, FALSE); + if(pStr) + { + RegSetValueExW(hKey, L"SubnetMask", 0, REG_MULTI_SZ, (LPBYTE)pStr, dwSize); + CoTaskMemFree(pStr); + } } - pStr = CreateMultiSzString(This->pCurrentConfig->Gw, IPADDR, &dwSize, FALSE); - if(pStr) + if (pOldConfig->Gw) { - RegSetValueExW(hKey, L"DefaultGateway", 0, REG_MULTI_SZ, (LPBYTE)pStr, dwSize); - CoTaskMemFree(pStr); + dwSize = 0; + if (GetIpForwardTable(NULL, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) + { + DWORD Index; + PMIB_IPFORWARDTABLE pIpForwardTable = (PMIB_IPFORWARDTABLE)CoTaskMemAlloc(dwSize); + if (pIpForwardTable) + { + if (GetIpForwardTable(pIpForwardTable, &dwSize, FALSE) == NO_ERROR) + { + for (Index = 0; Index < pIpForwardTable->dwNumEntries; Index++) + { + if (pIpForwardTable->table[Index].dwForwardIfIndex == pOldConfig->Index) + { + DeleteIpForwardEntry(&pIpForwardTable->table[Index]); + } + } + } + CoTaskMemFree(pIpForwardTable); + } + } } - pStr = CreateMultiSzString(This->pCurrentConfig->Gw, METRIC, &dwSize, FALSE); - if(pStr) + if (pCurrentConfig->Gw) { - RegSetValueExW(hKey, L"DefaultGatewayMetric", 0, REG_MULTI_SZ, (LPBYTE)pStr, dwSize); - CoTaskMemFree(pStr); + MIB_IPFORWARDROW RouterMib; + ZeroMemory(&RouterMib, sizeof(MIB_IPFORWARDROW)); + + RouterMib.dwForwardMetric1 = 1; + RouterMib.dwForwardIfIndex = pOldConfig->Index; + RouterMib.dwForwardNextHop = htonl(pCurrentConfig->Gw->IpAddress); + + //TODO + // add multiple gw addresses when required + + if (CreateIpForwardEntry(&RouterMib) == NO_ERROR) + { + pStr = CreateMultiSzString(pCurrentConfig->Gw, IPADDR, &dwSize, FALSE); + if(pStr) + { + RegSetValueExW(hKey, L"DefaultGateway", 0, REG_MULTI_SZ, (LPBYTE)pStr, dwSize); + CoTaskMemFree(pStr); + } + + pStr = CreateMultiSzString(pCurrentConfig->Gw, METRIC, &dwSize, FALSE); + if(pStr) + { + RegSetValueExW(hKey, L"DefaultGatewayMetric", 0, REG_MULTI_SZ, (LPBYTE)pStr, dwSize); + CoTaskMemFree(pStr); + } + } } + else + { + RegSetValueExW(hKey, L"DefaultGateway", 0, REG_MULTI_SZ, (LPBYTE)L"", 1 * sizeof(WCHAR)); + RegSetValueExW(hKey, L"DefaultGatewayMetric", 0, REG_MULTI_SZ, (LPBYTE)L"\0", sizeof(WCHAR) * 2); + } + + if (!pCurrentConfig->Ns || pCurrentConfig->AutoconfigActive) + { + RegSetValueExW(hKey, L"NameServer", 0, REG_SZ, (LPBYTE)L"", 1 * sizeof(WCHAR)); + } + else + { + pStr = CreateMultiSzString(pCurrentConfig->Ns, IPADDR, &dwSize, TRUE); + if(pStr) + { + RegSetValueExW(hKey, L"NameServer", 0, REG_SZ, (LPBYTE)pStr, dwSize); + RegDeleteValueW(hKey, L"DhcpNameServer"); + CoTaskMemFree(pStr); + } + } + RegCloseKey(hKey); } - - if (!This->pCurrentConfig->Ns || This->pCurrentConfig->AutoconfigActive) - { - RegSetValueExW(hKey, L"NameServer", 0, REG_SZ, (LPBYTE)L"", 1 * sizeof(WCHAR)); - } - else - { - pStr = CreateMultiSzString(This->pCurrentConfig->Ns, IPADDR, &dwSize, TRUE); - if(pStr) - { - RegSetValueExW(hKey, L"NameServer", 0, REG_SZ, (LPBYTE)pStr, dwSize); - RegDeleteValueW(hKey, L"DhcpNameServer"); - CoTaskMemFree(pStr); - } - } - RegCloseKey(hKey); } - - return S_OK; } diff --git a/reactos/dll/win32/netshell/lang/bg-BG.rc b/reactos/dll/win32/netshell/lang/bg-BG.rc index 990a2ae89c7..b63d03fcf35 100644 --- a/reactos/dll/win32/netshell/lang/bg-BG.rc +++ b/reactos/dll/win32/netshell/lang/bg-BG.rc @@ -63,13 +63,13 @@ BEGIN RTEXT "Íåíàëè÷íî", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Ïîäðîáíîñòè...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/cs-CZ.rc b/reactos/dll/win32/netshell/lang/cs-CZ.rc index 1ee4842ba96..896d9975bdb 100644 --- a/reactos/dll/win32/netshell/lang/cs-CZ.rc +++ b/reactos/dll/win32/netshell/lang/cs-CZ.rc @@ -62,13 +62,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Detaily...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/da-DK.rc b/reactos/dll/win32/netshell/lang/da-DK.rc index 2cf64a4966f..682914a6d5a 100644 --- a/reactos/dll/win32/netshell/lang/da-DK.rc +++ b/reactos/dll/win32/netshell/lang/da-DK.rc @@ -62,13 +62,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/de-DE.rc b/reactos/dll/win32/netshell/lang/de-DE.rc index 4d1fd057f1b..5026f25ae39 100644 --- a/reactos/dll/win32/netshell/lang/de-DE.rc +++ b/reactos/dll/win32/netshell/lang/de-DE.rc @@ -63,13 +63,13 @@ BEGIN RTEXT "Nicht verfügbar", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/el-GR.rc b/reactos/dll/win32/netshell/lang/el-GR.rc index a5d731b9fad..9df47c3fc46 100644 --- a/reactos/dll/win32/netshell/lang/el-GR.rc +++ b/reactos/dll/win32/netshell/lang/el-GR.rc @@ -62,13 +62,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/en-US.rc b/reactos/dll/win32/netshell/lang/en-US.rc index b9e369ef61e..525b5c07b56 100644 --- a/reactos/dll/win32/netshell/lang/en-US.rc +++ b/reactos/dll/win32/netshell/lang/en-US.rc @@ -63,13 +63,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/es-ES.rc b/reactos/dll/win32/netshell/lang/es-ES.rc index 63af8a01ae3..64000115d4a 100644 --- a/reactos/dll/win32/netshell/lang/es-ES.rc +++ b/reactos/dll/win32/netshell/lang/es-ES.rc @@ -57,13 +57,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 110, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 110, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 110, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 110, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 110, 62, 80, 8 PUSHBUTTON "&Detalles...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/fr-FR.rc b/reactos/dll/win32/netshell/lang/fr-FR.rc index ddfda855668..23dfe47b6bf 100644 --- a/reactos/dll/win32/netshell/lang/fr-FR.rc +++ b/reactos/dll/win32/netshell/lang/fr-FR.rc @@ -62,13 +62,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Détails...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/hu-HU.rc b/reactos/dll/win32/netshell/lang/hu-HU.rc index e4643445413..dc6b75047a4 100644 --- a/reactos/dll/win32/netshell/lang/hu-HU.rc +++ b/reactos/dll/win32/netshell/lang/hu-HU.rc @@ -63,13 +63,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/id-ID.rc b/reactos/dll/win32/netshell/lang/id-ID.rc index e555ac7ed95..b6936192f0c 100644 --- a/reactos/dll/win32/netshell/lang/id-ID.rc +++ b/reactos/dll/win32/netshell/lang/id-ID.rc @@ -62,13 +62,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Detil...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/it-IT.rc b/reactos/dll/win32/netshell/lang/it-IT.rc index 7dce9bfda50..b4c895c0502 100644 --- a/reactos/dll/win32/netshell/lang/it-IT.rc +++ b/reactos/dll/win32/netshell/lang/it-IT.rc @@ -67,13 +67,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Dettagli...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/ja-JP.rc b/reactos/dll/win32/netshell/lang/ja-JP.rc index 41586c80409..12c4544be5e 100644 --- a/reactos/dll/win32/netshell/lang/ja-JP.rc +++ b/reactos/dll/win32/netshell/lang/ja-JP.rc @@ -62,13 +62,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/nl-NL.rc b/reactos/dll/win32/netshell/lang/nl-NL.rc index e96a830aa85..70d8e064299 100644 --- a/reactos/dll/win32/netshell/lang/nl-NL.rc +++ b/reactos/dll/win32/netshell/lang/nl-NL.rc @@ -62,13 +62,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/no-NO.rc b/reactos/dll/win32/netshell/lang/no-NO.rc index 3042245d057..6577ebd956e 100644 --- a/reactos/dll/win32/netshell/lang/no-NO.rc +++ b/reactos/dll/win32/netshell/lang/no-NO.rc @@ -66,13 +66,13 @@ BEGIN RTEXT "Ikke tilgjengelig", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Detaljer...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/pl-PL.rc b/reactos/dll/win32/netshell/lang/pl-PL.rc index 04eeae89095..a389342b0c4 100644 --- a/reactos/dll/win32/netshell/lang/pl-PL.rc +++ b/reactos/dll/win32/netshell/lang/pl-PL.rc @@ -63,13 +63,13 @@ BEGIN RTEXT "n/d", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Szczegó³y...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/ru-RU.rc b/reactos/dll/win32/netshell/lang/ru-RU.rc index 80f2b34ed82..1356c31f9a0 100644 --- a/reactos/dll/win32/netshell/lang/ru-RU.rc +++ b/reactos/dll/win32/netshell/lang/ru-RU.rc @@ -63,13 +63,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Äîïîëíèòåëüíî...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/sk-SK.rc b/reactos/dll/win32/netshell/lang/sk-SK.rc index 11bb32ecdfd..3555bac4795 100644 --- a/reactos/dll/win32/netshell/lang/sk-SK.rc +++ b/reactos/dll/win32/netshell/lang/sk-SK.rc @@ -68,13 +68,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "Po&drobnosti...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/sv-SE.rc b/reactos/dll/win32/netshell/lang/sv-SE.rc index db65eef9647..d7243c4e8be 100644 --- a/reactos/dll/win32/netshell/lang/sv-SE.rc +++ b/reactos/dll/win32/netshell/lang/sv-SE.rc @@ -63,13 +63,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/uk-UA.rc b/reactos/dll/win32/netshell/lang/uk-UA.rc index 0a0eecbad2c..8c83b7e4956 100644 --- a/reactos/dll/win32/netshell/lang/uk-UA.rc +++ b/reactos/dll/win32/netshell/lang/uk-UA.rc @@ -65,13 +65,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Ñêëàä...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lang/zh-CN.rc b/reactos/dll/win32/netshell/lang/zh-CN.rc index cb98d3d6ba5..184a73c0f7a 100644 --- a/reactos/dll/win32/netshell/lang/zh-CN.rc +++ b/reactos/dll/win32/netshell/lang/zh-CN.rc @@ -62,13 +62,13 @@ BEGIN RTEXT "N/A", IDC_DETAILSTYPE, 122, 20, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSIP, 122, 34, 80, 8 RTEXT "000.000.000.000", IDC_DETAILSSUBNET, 122, 48, 80, 8 - RTEXT "000.000.000.000", IDC_DETAILSGATEWAY, 122, 62, 80, 8 + RTEXT "", IDC_DETAILSGATEWAY, 122, 62, 80, 8 PUSHBUTTON "&Details...", IDC_DETAILS, 22, 76, 62, 14 END IDD_LAN_NETSTATUSDETAILS DIALOGEX DISCARDABLE 0, 0, 200,200 -STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION CAPTION "Network Connection Details" FONT 8, "MS Shell Dlg" BEGIN diff --git a/reactos/dll/win32/netshell/lanstatusui.c b/reactos/dll/win32/netshell/lanstatusui.c index 84f52f7a7ca..9d8f8232864 100644 --- a/reactos/dll/win32/netshell/lanstatusui.c +++ b/reactos/dll/win32/netshell/lanstatusui.c @@ -336,7 +336,7 @@ AddIPAddressToListView( { ZeroMemory(&li, sizeof(LVITEMW)); li.mask = LVIF_TEXT; - li.iItem = ListView_GetItemCount(hDlgCtrl); + li.iItem = Index; li.iSubItem = 0; li.pszText = L""; li.iItem = SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li); @@ -346,7 +346,7 @@ AddIPAddressToListView( { li.pszText = szBuffer; li.iSubItem = 1; - li.iItem = ListView_GetItemCount(hDlgCtrl); + li.iItem = Index++; SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); } SubIndex++; @@ -365,7 +365,7 @@ InsertItemToListView( ZeroMemory(&li, sizeof(LVITEMW)); li.mask = LVIF_TEXT; li.iItem = ListView_GetItemCount(hDlgCtrl); - if (LoadStringW(netshell_hInstance, IDS_PHYSICAL_ADDRESS, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) + if (LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { li.pszText = szBuffer; return (INT)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li); @@ -429,9 +429,11 @@ LANStatusUiDetailsDlg( { li.iItem = InsertItemToListView(hDlgCtrl, IDS_PHYSICAL_ADDRESS); if (li.iItem >= 0) - if (MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pCurAdapter->Address, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) - SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); - + { + swprintf(szBuffer, L"%02x-%02x-%02x-%02x-%02x-%02x",pCurAdapter->Address[0], pCurAdapter->Address[1], + pCurAdapter->Address[2], pCurAdapter->Address[3], pCurAdapter->Address[4], pCurAdapter->Address[5]); + SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); + } li.iItem = InsertItemToListView(hDlgCtrl, IDS_IP_ADDRESS); if (li.iItem >= 0) if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) @@ -443,10 +445,11 @@ LANStatusUiDetailsDlg( SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); li.iItem = InsertItemToListView(hDlgCtrl, IDS_DEF_GATEWAY); - if (li.iItem >= 0) - if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->DhcpServer.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) + if (li.iItem >= 0 && pCurAdapter->GatewayList.IpAddress.String[0] != '0') + { + if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->GatewayList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); - + } #if 0 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_OBTAINED); li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_EXPIRES); @@ -478,6 +481,12 @@ LANStatusUiDetailsDlg( #endif CoTaskMemFree(pAdapterInfo); break; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_CLOSE) + { + EndDialog(hwndDlg, FALSE); + break; + } } return FALSE; } @@ -523,10 +532,12 @@ LANStatusUiAdvancedDlg( SendDlgItemMessageW(hwndDlg, IDC_DETAILSSUBNET, WM_SETTEXT, 0, (LPARAM)szBuffer); dwIpAddr = ntohl(pContext->Gateway); - swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr), - THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr)); - SendDlgItemMessageW(hwndDlg, IDC_DETAILSGATEWAY, WM_SETTEXT, 0, (LPARAM)szBuffer); - + if (dwIpAddr) + { + swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr), + THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr)); + SendDlgItemMessageW(hwndDlg, IDC_DETAILSGATEWAY, WM_SETTEXT, 0, (LPARAM)szBuffer); + } return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDC_DETAILS) diff --git a/reactos/dll/win32/ole32/moniker.c b/reactos/dll/win32/ole32/moniker.c index 4e5646279b2..a4d2a5efc59 100644 --- a/reactos/dll/win32/ole32/moniker.c +++ b/reactos/dll/win32/ole32/moniker.c @@ -19,11 +19,14 @@ * 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 + * + * TODO: + * - IRunningObjectTable should work interprocess, but currently doesn't. + * Native (on Win2k at least) uses an undocumented RPC interface, IROT, to + * communicate with RPCSS which contains the table of marshalled data. */ -#include "config.h" -#include "wine/port.h" - +#include #include #include @@ -39,33 +42,25 @@ #include "wine/list.h" #include "wine/debug.h" #include "wine/unicode.h" -#include "wine/exception.h" #include "compobj_private.h" #include "moniker.h" -#include "irot.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); /* see MSDN docs for IROTData::GetComparisonData, which states what this - * constant is - */ + * constant is (http://msdn2.microsoft.com/en-us/library/ms693773.aspx) */ #define MAX_COMPARISON_DATA 2048 -static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr) -{ - return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode); -} - /* define the structure of the running object table elements */ struct rot_entry { struct list entry; - InterfaceData* object; /* marshaled running object*/ - MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */ + MInterfacePointer* object; /* marshaled running object*/ + MInterfacePointer* moniker; /* marshaled moniker that identifies this object */ + MInterfacePointer* moniker_data; /* moniker comparison data that identifies this object */ DWORD cookie; /* cookie identifying this object */ FILETIME last_modified; - IrotContextHandle ctxt_handle; }; /* define the RunningObjectTableImpl structure */ @@ -79,7 +74,16 @@ typedef struct RunningObjectTableImpl } RunningObjectTableImpl; static RunningObjectTableImpl* runningObjectTableInstance = NULL; -static IrotHandle irot_handle; + + + +static inline HRESULT WINAPI +IrotRegister(DWORD *cookie) +{ + static LONG last_cookie = 1; + *cookie = InterlockedIncrement(&last_cookie); + return S_OK; +} /* define the EnumMonikerImpl structure */ typedef struct EnumMonikerImpl @@ -87,79 +91,17 @@ typedef struct EnumMonikerImpl const IEnumMonikerVtbl *lpVtbl; LONG ref; - InterfaceList *moniker_list; + MInterfacePointer **monikers; + ULONG moniker_count; ULONG pos; } EnumMonikerImpl; /* IEnumMoniker Local functions*/ -static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list, - ULONG pos, IEnumMoniker **ppenumMoniker); +static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers, + ULONG moniker_count, ULONG pos, IEnumMoniker **ppenumMoniker); -static IrotHandle get_irot_handle(void) -{ - if (!irot_handle) - { - RPC_STATUS status; - RPC_WSTR binding; - IrotHandle new_handle; - unsigned short ncacn_np[] = IROT_PROTSEQ; - unsigned short endpoint[] = IROT_ENDPOINT; - status = RpcStringBindingComposeW(NULL, ncacn_np, NULL, endpoint, NULL, &binding); - if (status == RPC_S_OK) - { - status = RpcBindingFromStringBindingW(binding, &new_handle); - RpcStringFreeW(&binding); - } - if (status != RPC_S_OK) - return NULL; - if (InterlockedCompareExchangePointer(&irot_handle, new_handle, NULL)) - /* another thread beat us to it */ - RpcBindingFree(&new_handle); - } - return irot_handle; -} - -static BOOL start_rpcss(void) -{ - PROCESS_INFORMATION pi; - STARTUPINFOW si; - static WCHAR cmd[6]; - static const WCHAR rpcss[] = {'r','p','c','s','s',0}; - BOOL rslt; - - TRACE("\n"); - - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - ZeroMemory(&si, sizeof(STARTUPINFOA)); - si.cb = sizeof(STARTUPINFOA); - - memcpy(cmd, rpcss, sizeof(rpcss)); - - rslt = CreateProcessW( - NULL, /* executable */ - cmd, /* command line */ - NULL, /* process security attributes */ - NULL, /* primary thread security attributes */ - FALSE, /* inherit handles */ - 0, /* creation flags */ - NULL, /* use parent's environment */ - NULL, /* use parent's current directory */ - &si, /* STARTUPINFO pointer */ - &pi /* PROCESS_INFORMATION */ - ); - - if (rslt) - { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - Sleep(100); - } - - return rslt; -} - -static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream) +static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream) { HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData); void *pv = GlobalLock(hglobal); @@ -170,33 +112,7 @@ static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **strea static inline void rot_entry_delete(struct rot_entry *rot_entry) { - if (rot_entry->cookie) - { - InterfaceData *object = NULL; - InterfaceData *moniker = NULL; - __TRY - { - IrotRevoke(get_irot_handle(), rot_entry->cookie, - &rot_entry->ctxt_handle, &object, &moniker); - } - __EXCEPT(rpc_filter) - { - } - __ENDTRY - MIDL_user_free(object); - if (moniker) - { - IStream *stream; - HRESULT hr; - hr = create_stream_on_mip_ro(moniker, &stream); - if (hr == S_OK) - { - CoReleaseMarshalData(stream); - IUnknown_Release(stream); - } - } - MIDL_user_free(moniker); - } + /* FIXME: revoke entry from rpcss's copy of the ROT */ if (rot_entry->object) { IStream *stream; @@ -208,13 +124,25 @@ static inline void rot_entry_delete(struct rot_entry *rot_entry) IUnknown_Release(stream); } } + if (rot_entry->moniker) + { + IStream *stream; + HRESULT hr; + hr = create_stream_on_mip_ro(rot_entry->moniker, &stream); + if (hr == S_OK) + { + CoReleaseMarshalData(stream); + IUnknown_Release(stream); + } + } HeapFree(GetProcessHeap(), 0, rot_entry->object); + HeapFree(GetProcessHeap(), 0, rot_entry->moniker); HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data); HeapFree(GetProcessHeap(), 0, rot_entry); } /* moniker_data must be freed with HeapFree when no longer in use */ -static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparisonData **moniker_data) +static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer **moniker_data) { HRESULT hr; IROTData *pROTData = NULL; @@ -222,14 +150,8 @@ static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparison if (SUCCEEDED(hr)) { ULONG size = MAX_COMPARISON_DATA; - *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[size])); - if (!*moniker_data) - { - IROTData_Release(pROTData); - return E_OUTOFMEMORY; - } + *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size); - IROTData_Release(pROTData); if (hr != S_OK) { ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr); @@ -263,7 +185,7 @@ static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparison len = strlenW(pszDisplayName); *moniker_data = HeapAlloc(GetProcessHeap(), 0, - FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)])); + FIELD_OFFSET(MInterfacePointer, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)])); if (!*moniker_data) { CoTaskMemFree(pszDisplayName); @@ -273,7 +195,6 @@ static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparison memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid)); memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR)); - CoTaskMemFree(pszDisplayName); } return S_OK; } @@ -346,7 +267,6 @@ static HRESULT WINAPI RunningObjectTableImpl_Destroy(void) { struct list *cursor, *cursor2; - IrotHandle old_handle; TRACE("()\n"); @@ -368,11 +288,6 @@ RunningObjectTableImpl_Destroy(void) HeapFree(GetProcessHeap(),0,runningObjectTableInstance); runningObjectTableInstance = NULL; - old_handle = irot_handle; - irot_handle = NULL; - if (old_handle) - RpcBindingFree(&old_handle); - return S_OK; } @@ -426,7 +341,6 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, IStream *pStream = NULL; DWORD mshlflags; IBindCtx *pbc; - InterfaceData *moniker = NULL; TRACE("(%p,%d,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister); @@ -464,7 +378,7 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, const void *pv = GlobalLock(hglobal); rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); rot_entry->object->ulCntData = size; - memcpy(rot_entry->object->abData, pv, size); + memcpy(&rot_entry->object->abData, pv, size); GlobalUnlock(hglobal); } } @@ -528,9 +442,9 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, { SIZE_T size = GlobalSize(hglobal); const void *pv = GlobalLock(hglobal); - moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size])); - moniker->ulCntData = size; - memcpy(moniker->abData, pv, size); + rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); + rot_entry->moniker->ulCntData = size; + memcpy(&rot_entry->moniker->abData, pv, size); GlobalUnlock(hglobal); } } @@ -538,35 +452,13 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, IMoniker_Release(pmkObjectName); if (hr != S_OK) { - HeapFree(GetProcessHeap(), 0, moniker); rot_entry_delete(rot_entry); return hr; } - - while (TRUE) - { - __TRY - { - hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data, - rot_entry->object, moniker, - &rot_entry->last_modified, grfFlags, - &rot_entry->cookie, &rot_entry->ctxt_handle); - } - __EXCEPT(rpc_filter) - { - hr = HRESULT_FROM_WIN32(GetExceptionCode()); - } - __ENDTRY - if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) - { - if (start_rpcss()) - continue; - } - break; - } - HeapFree(GetProcessHeap(), 0, moniker); - if (FAILED(hr)) + /* FIXME: not the right signature of IrotRegister function */ + hr = IrotRegister(&rot_entry->cookie); + if (hr != S_OK) { rot_entry_delete(rot_entry); return hr; @@ -576,6 +468,7 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, *pdwRegister = rot_entry->cookie; EnterCriticalSection(&This->lock); + /* FIXME: see if object was registered before and return MK_S_MONIKERALREADYREGISTERED */ list_add_tail(&This->rot, &rot_entry->entry); LeaveCriticalSection(&This->lock); @@ -623,9 +516,9 @@ static HRESULT WINAPI RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName) { RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - MonikerComparisonData *moniker_data; + MInterfacePointer *moniker_data; HRESULT hr; - const struct rot_entry *rot_entry; + struct rot_entry *rot_entry; TRACE("(%p,%p)\n",This,pmkObjectName); @@ -639,10 +532,10 @@ RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjec hr = S_FALSE; EnterCriticalSection(&This->lock); - LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry) + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) { if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && - !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) + !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData)) { hr = S_OK; break; @@ -650,27 +543,7 @@ RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjec } LeaveCriticalSection(&This->lock); - if (hr == S_FALSE) - { - while (TRUE) - { - __TRY - { - hr = IrotIsRunning(get_irot_handle(), moniker_data); - } - __EXCEPT(rpc_filter) - { - hr = HRESULT_FROM_WIN32(GetExceptionCode()); - } - __ENDTRY - if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) - { - if (start_rpcss()) - continue; - } - break; - } - } + /* FIXME: call IrotIsRunning */ HeapFree(GetProcessHeap(), 0, moniker_data); @@ -689,9 +562,7 @@ RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, IMoniker *pmkObjectName, IUnknown **ppunkObject) { RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - MonikerComparisonData *moniker_data; - InterfaceData *object = NULL; - IrotCookie cookie; + MInterfacePointer *moniker_data; HRESULT hr; struct rot_entry *rot_entry; @@ -714,7 +585,7 @@ RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) { if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && - !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) + !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData)) { IStream *pStream; hr = create_stream_on_mip_ro(rot_entry->object, &pStream); @@ -732,39 +603,9 @@ RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, } LeaveCriticalSection(&This->lock); - TRACE("moniker unavailable locally, calling SCM\n"); - - while (TRUE) - { - __TRY - { - hr = IrotGetObject(get_irot_handle(), moniker_data, &object, &cookie); - } - __EXCEPT(rpc_filter) - { - hr = HRESULT_FROM_WIN32(GetExceptionCode()); - } - __ENDTRY - if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) - { - if (start_rpcss()) - continue; - } - break; - } - - if (SUCCEEDED(hr)) - { - IStream *pStream; - hr = create_stream_on_mip_ro(object, &pStream); - if (hr == S_OK) - { - hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject); - IStream_Release(pStream); - } - } - else - WARN("Moniker unavailable, IrotGetObject returned 0x%08x\n", hr); + /* FIXME: call IrotGetObject */ + WARN("Moniker unavailable - app may require interprocess running object table\n"); + hr = MK_E_UNAVAILABLE; HeapFree(GetProcessHeap(), 0, moniker_data); @@ -784,7 +625,6 @@ RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, { RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; struct rot_entry *rot_entry; - HRESULT hr = E_INVALIDARG; TRACE("(%p,%d,%p)\n",This,dwRegister,pfiletime); @@ -795,34 +635,14 @@ RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, { rot_entry->last_modified = *pfiletime; LeaveCriticalSection(&This->lock); - - while (TRUE) - { - __TRY - { - hr = IrotNoteChangeTime(get_irot_handle(), dwRegister, pfiletime); - } - __EXCEPT(rpc_filter) - { - hr = HRESULT_FROM_WIN32(GetExceptionCode()); - } - __ENDTRY - if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) - { - if (start_rpcss()) - continue; - } - break; - } - - goto done; + return S_OK; } } LeaveCriticalSection(&This->lock); -done: - TRACE("-- 0x08%x\n", hr); - return hr; + /* FIXME: call IrotNoteChangeTime */ + + return E_INVALIDARG; } /*********************************************************************** @@ -838,8 +658,8 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, { HRESULT hr = MK_E_UNAVAILABLE; RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - MonikerComparisonData *moniker_data; - const struct rot_entry *rot_entry; + MInterfacePointer *moniker_data; + struct rot_entry *rot_entry; TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime); @@ -857,10 +677,10 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, hr = MK_E_UNAVAILABLE; EnterCriticalSection(&This->lock); - LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry) + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) { if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && - !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) + !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData)) { *pfiletime = rot_entry->last_modified; hr = S_OK; @@ -869,31 +689,9 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, } LeaveCriticalSection(&This->lock); - if (hr != S_OK) - { - while (TRUE) - { - __TRY - { - hr = IrotGetTimeOfLastChange(get_irot_handle(), moniker_data, pfiletime); - } - __EXCEPT(rpc_filter) - { - hr = HRESULT_FROM_WIN32(GetExceptionCode()); - } - __ENDTRY - if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) - { - if (start_rpcss()) - continue; - } - break; - } - } + /* FIXME: if (hr != S_OK) call IrotGetTimeOfLastChange */ HeapFree(GetProcessHeap(), 0, moniker_data); - - TRACE("-- 0x%08x\n", hr); return hr; } @@ -907,36 +705,33 @@ static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker **ppenumMoniker) { - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - InterfaceList *interface_list = NULL; HRESULT hr; + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer **monikers; + ULONG moniker_count = 0; + const struct rot_entry *rot_entry; + ULONG i = 0; - TRACE("(%p, %p)\n", This, ppenumMoniker); + EnterCriticalSection(&This->lock); - *ppenumMoniker = NULL; + LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry ) + moniker_count++; - while (TRUE) + monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers)); + + LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry ) { - __TRY - { - hr = IrotEnumRunning(get_irot_handle(), &interface_list); - } - __EXCEPT(rpc_filter) - { - hr = HRESULT_FROM_WIN32(GetExceptionCode()); - } - __ENDTRY - if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) - { - if (start_rpcss()) - continue; - } - break; + SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[rot_entry->moniker->ulCntData]); + monikers[i] = HeapAlloc(GetProcessHeap(), 0, size); + memcpy(monikers[i], rot_entry->moniker, size); + i++; } - if (SUCCEEDED(hr)) - hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list, - 0, ppenumMoniker); + LeaveCriticalSection(&This->lock); + + /* FIXME: call IrotEnumRunning and append data */ + + hr = EnumMonikerImpl_CreateEnumROTMoniker(monikers, moniker_count, 0, ppenumMoniker); return hr; } @@ -972,9 +767,9 @@ HRESULT WINAPI RunningObjectTableImpl_Initialize(void) /* initialize the virtual table function */ runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl; - /* the initial reference is set to "1" so that it isn't destroyed after its - * first use until the process is destroyed, as the running object table is - * a process-wide cache of a global table */ + /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */ + /* the ROT referred many times not in the same time (all the objects in the ROT will */ + /* be removed every time the ROT is removed ) */ runningObjectTableInstance->ref = 1; list_init(&runningObjectTableInstance->rot); @@ -1078,21 +873,6 @@ static HRESULT get_moniker_for_progid_display_name(LPBC pbc, IParseDisplayName *pdn; hr = IMoniker_BindToObject(class_moniker, pbc, NULL, &IID_IParseDisplayName, (void **)&pdn); - /* fallback to using IClassFactory to get IParseDisplayName - - * adsldp.dll depends on this */ - if (FAILED(hr)) - { - IClassFactory *pcf; - hr = IMoniker_BindToObject(class_moniker, pbc, NULL, - &IID_IClassFactory, (void **)&pcf); - if (SUCCEEDED(hr)) - { - hr = IClassFactory_CreateInstance(pcf, NULL, - &IID_IParseDisplayName, - (void **)&pdn); - IClassFactory_Release(pcf); - } - } IMoniker_Release(class_moniker); if (SUCCEEDED(hr)) { @@ -1211,9 +991,9 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid) return res; } - /* If the file is not a storage object then attempt to match various bits in the file against a - pattern in the registry. This case is not frequently used, so I present only the pseudocode for - this case. + /* if the file is not a storage object then attemps to match various bits in the file against a + pattern in the registry. this case is not frequently used ! so I present only the psodocode for + this case for(i=0;imoniker_list->size; i++) - HeapFree(GetProcessHeap(), 0, This->moniker_list->interfaces[i]); - HeapFree(GetProcessHeap(), 0, This->moniker_list); + for (i = 0; i < This->moniker_count; i++) + HeapFree(GetProcessHeap(), 0, This->monikers[i]); + HeapFree(GetProcessHeap(), 0, This->monikers); HeapFree(GetProcessHeap(), 0, This); } @@ -1352,13 +1132,13 @@ static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IM EnumMonikerImpl *This = (EnumMonikerImpl *)iface; HRESULT hr = S_OK; - TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_list->size); + TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_count); /* retrieve the requested number of moniker from the current position */ - for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++) + for(i = 0; (This->pos < This->moniker_count) && (i < celt); i++) { IStream *stream; - hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream); + hr = create_stream_on_mip_ro(This->monikers[This->pos++], &stream); if (hr != S_OK) break; hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]); IStream_Release(stream); @@ -1387,7 +1167,7 @@ static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt) TRACE("(%p)\n",This); - if (This->pos + celt >= This->moniker_list->size) + if (This->pos + celt >= This->moniker_count) return S_FALSE; This->pos += celt; @@ -1415,35 +1195,21 @@ static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface) static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum) { EnumMonikerImpl *This = (EnumMonikerImpl *)iface; - InterfaceList *moniker_list; + MInterfacePointer **monikers = HeapAlloc(GetProcessHeap(), 0, sizeof(*monikers)*This->moniker_count); ULONG i; TRACE("(%p)\n",This); - *ppenum = NULL; - - moniker_list = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size])); - if (!moniker_list) - return E_OUTOFMEMORY; - - moniker_list->size = This->moniker_list->size; - for (i = 0; i < This->moniker_list->size; i++) + for (i = 0; i < This->moniker_count; i++) { - SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]); - moniker_list->interfaces[i] = HeapAlloc(GetProcessHeap(), 0, size); - if (!moniker_list->interfaces[i]) - { - ULONG end = i; - for (i = 0; i < end; i++) - HeapFree(GetProcessHeap(), 0, moniker_list->interfaces[i]); - HeapFree(GetProcessHeap(), 0, moniker_list); - return E_OUTOFMEMORY; - } - memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size); + SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[This->monikers[i]->ulCntData]); + monikers[i] = HeapAlloc(GetProcessHeap(), 0, size); + memcpy(monikers[i], This->monikers[i], size); } /* copy the enum structure */ - return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum); + return EnumMonikerImpl_CreateEnumROTMoniker(monikers, This->moniker_count, + This->pos, ppenum); } /* Virtual function table for the IEnumMoniker class. */ @@ -1463,7 +1229,8 @@ static const IEnumMonikerVtbl VT_EnumMonikerImpl = * Used by EnumRunning to create the structure and EnumClone * to copy the structure */ -static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list, +static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers, + ULONG moniker_count, ULONG current_pos, IEnumMoniker **ppenumMoniker) { @@ -1483,7 +1250,8 @@ static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *monike /* the initial reference is set to "1" */ This->ref = 1; /* set the ref count to one */ This->pos = current_pos; /* Set the list start posn */ - This->moniker_list = moniker_list; + This->moniker_count = moniker_count; /* Need the same size table as ROT */ + This->monikers = monikers; *ppenumMoniker = (IEnumMoniker*)This; @@ -1659,13 +1427,3 @@ HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer) *outer = (IUnknown *)&This->lpVtbl; return S_OK; } - -void * __RPC_USER MIDL_user_allocate(size_t size) -{ - return HeapAlloc(GetProcessHeap(), 0, size); -} - -void __RPC_USER MIDL_user_free(void *p) -{ - HeapFree(GetProcessHeap(), 0, p); -} diff --git a/reactos/dll/win32/ole32/ole32.rbuild b/reactos/dll/win32/ole32/ole32.rbuild index d88805ed2c4..275b9d0bdb0 100644 --- a/reactos/dll/win32/ole32/ole32.rbuild +++ b/reactos/dll/win32/ole32/ole32.rbuild @@ -14,7 +14,6 @@ advapi32 user32 gdi32 - ole32_irot_client ole32_proxy rpcrt4 kernel32 diff --git a/reactos/dll/win32/shell32/drive.c b/reactos/dll/win32/shell32/drive.c index 53932de01f0..63083b2f2bc 100644 --- a/reactos/dll/win32/shell32/drive.c +++ b/reactos/dll/win32/shell32/drive.c @@ -678,7 +678,7 @@ SH_ShowDriveProperties(WCHAR * drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * PROPSHEETHEADERW psh; BOOL ret; UINT i; - WCHAR szName[MAX_PATH]; + WCHAR szName[MAX_PATH+6]; DWORD dwMaxComponent, dwFileSysFlags; IDataObject * pDataObj = NULL; @@ -700,8 +700,8 @@ SH_ShowDriveProperties(WCHAR * drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * /* FIXME * check if disk is a really a local hdd */ - i = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szName, sizeof(szName)/sizeof(WCHAR)); - if (i > 0 && i < (sizeof(szName)/sizeof(WCHAR)) + 6) + i = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, szName, sizeof(szName)/sizeof(WCHAR)-6); + if (i > 0 && i < (sizeof(szName)/sizeof(WCHAR)) - 6) { szName[i] = L' '; szName[i+1] = L'('; @@ -929,6 +929,8 @@ InitializeFormatDriveDlg(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext) HWND hDlgCtrl; Length = GetWindowTextW(hwndDlg, szText, sizeof(szText)/sizeof(WCHAR)); + if (Length < 0) + Length = 0; szDrive[0] = pContext->Drive + L'A'; if (GetVolumeInformationW(szDrive, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2, &dwSerial, &dwMaxComp, &dwFileSys, szFs, sizeof(szFs)/sizeof(WCHAR))) { diff --git a/reactos/dll/win32/shell32/enumidlist.c b/reactos/dll/win32/shell32/enumidlist.c index 9ae675e6f28..22daeaf1720 100644 --- a/reactos/dll/win32/shell32/enumidlist.c +++ b/reactos/dll/win32/shell32/enumidlist.c @@ -97,8 +97,8 @@ BOOL HasItemWithCLSID(IEnumIDList *iface, LPITEMIDLIST pidl) while(pCur) { - REFIID curid = _ILGetGUIDPointer(pCur->pidl); - if (IsEqualIID(curid, refid)) + LPGUID curid = _ILGetGUIDPointer(pCur->pidl); + if (curid && IsEqualGUID(curid, refid)) { return TRUE; } diff --git a/reactos/dll/win32/shell32/shfldr_admintools.c b/reactos/dll/win32/shell32/shfldr_admintools.c index 8ceb80b5cf1..10fdf94c58f 100644 --- a/reactos/dll/win32/shell32/shfldr_admintools.c +++ b/reactos/dll/win32/shell32/shfldr_admintools.c @@ -424,8 +424,8 @@ static HRESULT WINAPI ISF_AdminTools_fnGetDisplayNameOf (IShellFolder2 * iface, if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING)) wcscpy(pszPath, This->szTarget); - else - HCR_GetClassNameW(&CLSID_AdminFolderShortcut, pszPath, MAX_PATH); + else if (!HCR_GetClassNameW(&CLSID_AdminFolderShortcut, pszPath, MAX_PATH)) + hr = E_FAIL; } else if (_ILIsPidlSimple(pidl)) { @@ -436,12 +436,23 @@ static HRESULT WINAPI ISF_AdminTools_fnGetDisplayNameOf (IShellFolder2 * iface, wcscpy(pszPath, This->szTarget); pOffset = PathAddBackslashW(pszPath); if (pOffset) - _ILSimpleGetTextW(pidl, pOffset, MAX_PATH + 1 - (pOffset - pszPath)); + { + if (!_ILSimpleGetTextW(pidl, pOffset, MAX_PATH + 1 - (pOffset - pszPath))) + hr = E_FAIL; + } + else + hr = E_FAIL; } else - { - _ILSimpleGetTextW(pidl, pszPath, MAX_PATH + 1); - } + { + if (_ILSimpleGetTextW(pidl, pszPath, MAX_PATH + 1)) + { + if (SHELL_FS_HideExtension(pszPath)) + PathRemoveExtensionW(pszPath); + } + else + hr = E_FAIL; + } } else if (_ILIsSpecialFolder(pidl)) { @@ -449,10 +460,10 @@ static HRESULT WINAPI ISF_AdminTools_fnGetDisplayNameOf (IShellFolder2 * iface, if (bSimplePidl) { - _ILSimpleGetTextW(pidl, pszPath, MAX_PATH); - } - - if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) + if (!_ILSimpleGetTextW(pidl, pszPath, MAX_PATH)) + hr = E_FAIL; + } + else if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { int len = 0; @@ -473,11 +484,11 @@ static HRESULT WINAPI ISF_AdminTools_fnGetDisplayNameOf (IShellFolder2 * iface, { strRet->uType = STRRET_WSTR; strRet->u.pOleStr = pszPath; + TRACE ("-- (%p)->(%s,0x%08x)\n", This, debugstr_w(strRet->u.pOleStr), hr); } else CoTaskMemFree(pszPath); - TRACE ("-- (%p)->(%s,0x%08x)\n", This, debugstr_w(strRet->u.pOleStr), hr); return hr; } diff --git a/reactos/dll/win32/shell32/shfldr_recyclebin.c b/reactos/dll/win32/shell32/shfldr_recyclebin.c index 3b462efc15f..f9ca46e822f 100644 --- a/reactos/dll/win32/shell32/shfldr_recyclebin.c +++ b/reactos/dll/win32/shell32/shfldr_recyclebin.c @@ -1218,7 +1218,7 @@ InitializeBitBucketDlg(HWND hwndDlg, WCHAR DefaultDrive) li.iSubItem = 0; li.pszText = szVolume; li.iItem = itemCount; - (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMN, 0, (LPARAM)&li); + (void)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li); if (GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailable , &TotalNumberOfBytes, &TotalNumberOfFreeBytes)) { if (StrFormatByteSizeW(TotalNumberOfFreeBytes.QuadPart, szVolume, sizeof(szVolume) / sizeof(WCHAR))) @@ -1383,11 +1383,17 @@ BitBucketDlg( PDRIVE_ITEM_CONTEXT pItem; BOOL bSuccess; UINT uResult; + PROPSHEETPAGE * page; + DWORD dwStyle; switch(uMsg) { - case WM_INITDIALOG: - InitializeBitBucketDlg(hwndDlg, (WCHAR)lParam); + case WM_INITDIALOG: + page = (PROPSHEETPAGE*)lParam; + InitializeBitBucketDlg(hwndDlg, (WCHAR)page->lParam); + dwStyle = (DWORD) SendDlgItemMessage(hwndDlg, 14000, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); + dwStyle = dwStyle | LVS_EX_FULLROWSELECT; + SendDlgItemMessage(hwndDlg, 14000, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle); if (GetDlgCtrlID((HWND)wParam) != 14000) { SetFocus(GetDlgItem(hwndDlg, 14000)); diff --git a/reactos/dll/win32/shell32/shlview.c b/reactos/dll/win32/shell32/shlview.c index 4a69665b178..4dc6260672b 100644 --- a/reactos/dll/win32/shell32/shlview.c +++ b/reactos/dll/win32/shell32/shlview.c @@ -835,6 +835,8 @@ static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This) static UINT CF_IDLIST = 0; HRESULT hr; IDataObject* selection; + IContextMenu * cm; + HMENU hmenu; FORMATETC fetc; STGMEDIUM stgm; LPIDA pIDList; @@ -843,14 +845,68 @@ static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This) LPCWSTR parent_dir = NULL; SFGAOF attribs; int i; + CMINVOKECOMMANDINFOEX ici; + MENUITEMINFOW info; if (0 == ShellView_GetSelections(This)) { return S_OK; } + + hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, + (LPCITEMIDLIST*)This->apidl, &IID_IContextMenu, + 0, (LPVOID *)&cm); + + if (SUCCEEDED(hr)) + { + hmenu = CreatePopupMenu(); + if (hmenu) + { + if (SUCCEEDED(IContextMenu_QueryContextMenu( cm, hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY))) + { + INT def = -1, n = GetMenuItemCount(hmenu); + + for ( i = 0; i < n; i++ ) + { + memset( &info, 0, sizeof info ); + info.cbSize = sizeof info; + info.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_ID; + if (GetMenuItemInfoW( hmenu, i, TRUE, &info)) + { + if (info.fState & MFS_DEFAULT) + { + def = info.wID; + break; + } + } + } + if (def != -1) + { + memset( &ici, 0, sizeof ici ); + ici.cbSize = sizeof ici; + ici.lpVerb = MAKEINTRESOURCEA( def ); + ici.hwnd = This->hWnd; + + IContextMenu_InvokeCommand(cm, (LPCMINVOKECOMMANDINFO) &ici ); + IContextMenu_Release(cm); + DestroyMenu( hmenu ); + return S_OK; + } + + } + DestroyMenu( hmenu ); + } + IContextMenu_Release(cm); + } + + + hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject, 0, (LPVOID *)&selection); + + + if (FAILED(hr)) return hr; diff --git a/reactos/dll/win32/shell32/shv_def_cmenu.c b/reactos/dll/win32/shell32/shv_def_cmenu.c index 1acd018b71f..3336ba521cf 100644 --- a/reactos/dll/win32/shell32/shv_def_cmenu.c +++ b/reactos/dll/win32/shell32/shv_def_cmenu.c @@ -1404,10 +1404,10 @@ DoProperties( } else if (_ILIsNetHood(This->dcm.apidl[0])) { - /* FIXME - * implement nethood properties - */ - FIXME("implement network connection shell folder\n"); + //FIXME path! + ShellExecuteW(NULL, L"open", L"explorer.exe", + L"/n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}", + NULL, SW_SHOWDEFAULT); return S_OK; } else if (_ILIsBitBucket(This->dcm.apidl[0])) diff --git a/reactos/drivers/bus/acpi/include/platform/acmsc.h b/reactos/drivers/bus/acpi/include/platform/acmsc.h new file mode 100644 index 00000000000..612edf938c2 --- /dev/null +++ b/reactos/drivers/bus/acpi/include/platform/acmsc.h @@ -0,0 +1,67 @@ +#ifndef __ACMSC_H__ +#define __ACMSC_H__ + +#define COMPILER_DEPENDENT_UINT64 unsigned __int64 + +#if defined(_M_IX86) + +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define halt() { __asm { sti } __asm { hlt } } +#define wbinvd() + +__forceinline void _ACPI_ACQUIRE_GLOBAL_LOCK(void * GLptr, unsigned char * Acq_) +{ + unsigned char Acq; + + __asm + { + mov ecx, [GLptr] + + L1: mov eax, [ecx] + mov edx, eax + and edx, ecx + bts edx, 1 + adc edx, 0 + lock cmpxchg [ecx], edx + jne L1 + cmp dl, 3 + sbb eax, eax + + mov [Acq], al + }; + + *Acq_ = Acq; +} + +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + _ACPI_ACQUIRE_GLOBAL_LOCK((GLptr), (unsigned char *)&(Acq)) + +__forceinline void _ACPI_RELEASE_GLOBAL_LOCK(void * GLptr, unsigned char * Acq_) +{ + unsigned char Acq; + + __asm + { + mov ecx, [GLptr] + + L1: mov eax, [ecx] + mov edx, eax + and edx, ecx + lock cmpxchg [ecx], edx + jnz L1 + and eax, 1 + + mov [Acq], al + }; + + *Acq_ = Acq; +} + +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + _ACPI_RELEASE_GLOBAL_LOCK((GLptr), (unsigned char *)&(Acq)) + +#endif + +#endif /* __ACMSC_H__ */ diff --git a/reactos/drivers/bus/acpi/include/platform/acwin.h b/reactos/drivers/bus/acpi/include/platform/acwin.h index 297f29f6ae9..cfab7728f6f 100644 --- a/reactos/drivers/bus/acpi/include/platform/acwin.h +++ b/reactos/drivers/bus/acpi/include/platform/acwin.h @@ -47,14 +47,25 @@ #endif -/* ReactOS uses GCC */ +#if defined(__GNUC__) #include "acgcc.h" #undef disable -#define disable() __asm__("cli\n\t"); +#define disable() __asm__("cli\n\t") #undef enable -#define enable() __asm__("sti\n\t"); +#define enable() __asm__("sti\n\t") + +#elif defined(_MSC_VER) + +#include "acmsc.h" + +#undef disable +#define disable() __asm { cli } +#undef enable +#define enable() __asm { sti } + +#endif #undef DEBUGGER_THREADING #define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED diff --git a/reactos/hal/hal/hal.spec b/reactos/hal/hal/hal.pspec similarity index 99% rename from reactos/hal/hal/hal.spec rename to reactos/hal/hal/hal.pspec index b3ccd27b812..2d5ec886f52 100644 --- a/reactos/hal/hal/hal.spec +++ b/reactos/hal/hal/hal.pspec @@ -20,7 +20,6 @@ @ fastcall KfRaiseIrql(long) @ fastcall KfReleaseSpinLock(ptr long) - @ stdcall HalAcquireDisplayOwnership(ptr) @ stdcall HalAdjustResourceList(ptr) @ stdcall HalAllProcessorsStarted() diff --git a/reactos/hal/hal/hal.rbuild b/reactos/hal/hal/hal.rbuild index de3da9915b3..b78559a5a3c 100644 --- a/reactos/hal/hal/hal.rbuild +++ b/reactos/hal/hal/hal.rbuild @@ -9,18 +9,18 @@ hal.c hal.rc - hal.spec + hal.pspec - + include ntoskrnl hal.c hal.rc - hal.spec + hal.pspec diff --git a/reactos/hal/halarm/up/halup.rbuild b/reactos/hal/halarm/up/halup.rbuild index c2950733365..6f4179dd923 100644 --- a/reactos/hal/halarm/up/halup.rbuild +++ b/reactos/hal/halarm/up/halup.rbuild @@ -1,7 +1,7 @@ - + ../include include diff --git a/reactos/hal/halx86/halmp.rbuild b/reactos/hal/halx86/halmp.rbuild index 724e7896531..d8064067569 100644 --- a/reactos/hal/halx86/halmp.rbuild +++ b/reactos/hal/halx86/halmp.rbuild @@ -2,7 +2,7 @@ - + include include diff --git a/reactos/hal/halx86/halup.rbuild b/reactos/hal/halx86/halup.rbuild index c206b7ed8a7..26ed54613a9 100644 --- a/reactos/hal/halx86/halup.rbuild +++ b/reactos/hal/halx86/halup.rbuild @@ -2,7 +2,7 @@ - + include include diff --git a/reactos/hal/halx86/halxbox.rbuild b/reactos/hal/halx86/halxbox.rbuild index 923583a7e6a..f1573b8398e 100644 --- a/reactos/hal/halx86/halxbox.rbuild +++ b/reactos/hal/halx86/halxbox.rbuild @@ -2,7 +2,7 @@ - + include include diff --git a/reactos/include/reactos/win32k/ntgdityp.h b/reactos/include/reactos/win32k/ntgdityp.h index 8dbb9ee2ad7..671d435aca0 100644 --- a/reactos/include/reactos/win32k/ntgdityp.h +++ b/reactos/include/reactos/win32k/ntgdityp.h @@ -218,11 +218,11 @@ typedef PVOID PUMDHPDEV; typedef D3DNTHAL_CONTEXTCREATEDATA D3DNTHAL_CONTEXTCREATEI; typedef LONG FIX; -typedef struct _CHWIDTHINFO +typedef struct _CHWIDTHINFO // Based on FD_DEVICEMETRICS { - LONG lMaxNegA; - LONG lMaxNegC; - LONG lMinWidthD; + LONG lMinA; + LONG lMinC; + LONG lMinD; } CHWIDTHINFO, *PCHWIDTHINFO; typedef struct _UNIVERSAL_FONT_ID diff --git a/reactos/lib/rtl/debug.c b/reactos/lib/rtl/debug.c index bfde2e0f2f3..a17367fc39f 100644 --- a/reactos/lib/rtl/debug.c +++ b/reactos/lib/rtl/debug.c @@ -79,7 +79,7 @@ vDbgPrintExWithPrefixInternal(IN LPCSTR Prefix, /* Copy it */ strncpy(Buffer, Prefix, PrefixLength); - + /* Do the printf */ Length = _vsnprintf(Buffer + PrefixLength, sizeof(Buffer) - PrefixLength, @@ -109,7 +109,7 @@ vDbgPrintExWithPrefixInternal(IN LPCSTR Prefix, /* Add the prefix */ Length += PrefixLength; } - + /* Build the string */ DebugString.Length = Length; DebugString.Buffer = Buffer; @@ -202,17 +202,19 @@ __cdecl DbgPrint(PCCH Format, ...) { + ULONG n; va_list ap; /* Call the internal routine that also handles ControlC */ va_start(ap, Format); - return vDbgPrintExWithPrefixInternal("", + n = vDbgPrintExWithPrefixInternal("", -1, DPFLTR_ERROR_LEVEL, Format, ap, TRUE); va_end(ap); + return n; } /* @@ -225,17 +227,19 @@ DbgPrintEx(IN ULONG ComponentId, IN PCCH Format, ...) { + ULONG n; va_list ap; /* Call the internal routine that also handles ControlC */ va_start(ap, Format); - return vDbgPrintExWithPrefixInternal("", + n = vDbgPrintExWithPrefixInternal("", ComponentId, Level, Format, ap, TRUE); va_end(ap); + return n; } /* @@ -246,16 +250,19 @@ __cdecl DbgPrintReturnControlC(PCH Format, ...) { + ULONG n; va_list ap; /* Call the internal routine that also handles ControlC */ va_start(ap, Format); - return vDbgPrintExWithPrefixInternal("", + n = vDbgPrintExWithPrefixInternal("", -1, DPFLTR_ERROR_LEVEL, Format, ap, FALSE); + va_end(ap); + return n; } /* diff --git a/reactos/lib/rtl/res.c b/reactos/lib/rtl/res.c index 900e1efecd0..4714ae68775 100644 --- a/reactos/lib/rtl/res.c +++ b/reactos/lib/rtl/res.c @@ -60,7 +60,7 @@ static int is_data_file_module( PVOID BaseAddress ) */ int push_language( USHORT *list, ULONG pos, WORD lang ) { - int i; + ULONG i; for (i = 0; i < pos; i++) if (list[i] == lang) return pos; list[pos++] = lang; return pos; diff --git a/reactos/lib/rtl/rtl.h b/reactos/lib/rtl/rtl.h index 7f1eaf73ad7..81d82686a70 100644 --- a/reactos/lib/rtl/rtl.h +++ b/reactos/lib/rtl/rtl.h @@ -31,9 +31,7 @@ #include #include -#ifndef _MSC_VER #include -#endif #endif /* RTL_H */ diff --git a/reactos/lib/sdk/crt/math/i386/ci.c b/reactos/lib/sdk/crt/math/i386/ci.c index b0a58eb2d5c..0aeb0d1379c 100644 --- a/reactos/lib/sdk/crt/math/i386/ci.c +++ b/reactos/lib/sdk/crt/math/i386/ci.c @@ -1,11 +1,19 @@ #include #include +#if defined(__GNUC__) #define FPU_DOUBLE(var) double var; \ __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : ) #define FPU_DOUBLES(var1,var2) double var1,var2; \ __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \ __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : ) +#elif defined(_MSC_VER) +#define FPU_DOUBLE(var) double var; \ + __asm { fstp [var] }; __asm { fwait }; +#define FPU_DOUBLES(var1,var2) double var1,var2; \ + __asm { fstp [var1] }; __asm { fwait }; \ + __asm { fstp [var2] }; __asm { fwait }; +#endif /* * @implemented diff --git a/reactos/lib/sdk/crt/string/ctype.c b/reactos/lib/sdk/crt/string/ctype.c index 2606a39d9f8..a4873cebdd4 100644 --- a/reactos/lib/sdk/crt/string/ctype.c +++ b/reactos/lib/sdk/crt/string/ctype.c @@ -594,7 +594,7 @@ int toupper(int c) /* * @implemented */ -wchar_t towlower(wchar_t c) +wint_t towlower(wint_t c) { if (iswctype (c, _UPPER)) return (c - upalpha); @@ -604,7 +604,7 @@ wchar_t towlower(wchar_t c) /* * @implemented */ -wchar_t towupper(wchar_t c) +wint_t towupper(wint_t c) { if (iswctype (c, _LOWER)) return (c + upalpha); diff --git a/reactos/ntoskrnl/include/internal/ke_x.h b/reactos/ntoskrnl/include/internal/ke_x.h index b6a77383dfa..c28b1a795bc 100644 --- a/reactos/ntoskrnl/include/internal/ke_x.h +++ b/reactos/ntoskrnl/include/internal/ke_x.h @@ -88,6 +88,48 @@ Ke386SanitizeDr(IN PVOID DrAddress, } #endif /* _M_IX86 */ +#ifndef _M_ARM +PRKTHREAD +FORCEINLINE +KeGetCurrentThread(VOID) +{ +#ifdef _M_IX86 + /* Return the current thread */ + return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread; +#elif defined (_M_AMD64) + return (PRKTHREAD)__readgsqword(FIELD_OFFSET(KIPCR, Prcb.CurrentThread)); +#else + PKPRCB Prcb = KeGetCurrentPrcb(); + return Prcb->CurrentThread; +#endif +} + +UCHAR +FORCEINLINE +KeGetPreviousMode(VOID) +{ + /* Return the current mode */ + return KeGetCurrentThread()->PreviousMode; +} +#endif + +VOID +FORCEINLINE +KeFlushProcessTb(VOID) +{ + /* Flush the TLB by resetting CR3 */ +#ifdef _M_PPC + __asm__("sync\n\tisync\n\t"); +#elif _M_ARM + // + // We need to implement this! + // + ASSERTMSG("Need ARM flush routine\n", FALSE); +#else + __writecr3(__readcr3()); +#endif +} + // // Enters a Guarded Region // @@ -411,7 +453,10 @@ KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock) { #ifdef DBG /* On debug builds, we use a much slower but useful routine */ - Kii386SpinOnSpinLock(SpinLock, 5); + //Kii386SpinOnSpinLock(SpinLock, 5); + + /* FIXME: Do normal yield for now */ + YieldProcessor(); #else /* Otherwise, just yield and keep looping */ YieldProcessor(); @@ -422,7 +467,7 @@ KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock) { #ifdef DBG /* On debug builds, we OR in the KTHREAD */ - *SpinLock = KeGetCurrentThread() | 1; + *SpinLock = (KSPIN_LOCK)KeGetCurrentThread() | 1; #endif /* All is well, break out */ break; @@ -439,21 +484,21 @@ KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock) { #ifdef DBG /* Make sure that the threads match */ - if ((KeGetCurrentThread() | 1) != *SpinLock) + if (((KSPIN_LOCK)KeGetCurrentThread() | 1) != *SpinLock) { /* They don't, bugcheck */ - KeBugCheckEx(SPIN_LOCK_NOT_OWNED, SpinLock, 0, 0, 0); + KeBugCheckEx(SPIN_LOCK_NOT_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0); } #endif /* Clear the lock */ - InterlockedAnd(SpinLock, 0); + InterlockedAnd((PLONG)SpinLock, 0); } -KIRQL +VOID FORCEINLINE KiAcquireDispatcherObject(IN DISPATCHER_HEADER* Object) { - LONG OldValue, NewValue; + LONG OldValue; /* Make sure we're at a safe level to touch the lock */ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); @@ -462,20 +507,23 @@ KiAcquireDispatcherObject(IN DISPATCHER_HEADER* Object) do { /* Loop until the other CPU releases it */ - while ((UCHAR)Object->Lock & KOBJECT_LOCK_BIT) + while (TRUE) { + /* Check if it got released */ + OldValue = Object->Lock; + if ((OldValue & KOBJECT_LOCK_BIT) == 0) break; + /* Let the CPU know that this is a loop */ YieldProcessor(); - }; + } /* Try acquiring the lock now */ - NewValue = InterlockedCompareExchange(&Object->Lock, - OldValue | KOBJECT_LOCK_BIT, - OldValue); - } while (NewValue != OldValue); + } while (InterlockedCompareExchange(&Object->Lock, + OldValue | KOBJECT_LOCK_BIT, + OldValue) != OldValue); } -KIRQL +VOID FORCEINLINE KiReleaseDispatcherObject(IN DISPATCHER_HEADER* Object) { @@ -506,6 +554,22 @@ KiReleaseDispatcherLock(IN KIRQL OldIrql) KiExitDispatcher(OldIrql); } +VOID +FORCEINLINE +KiAcquireDispatcherLockAtDpcLevel(VOID) +{ + /* Acquire the dispatcher lock */ + KeAcquireQueuedSpinLockAtDpcLevel(LockQueueDispatcherLock); +} + +VOID +FORCEINLINE +KiReleaseDispatcherLockFromDpcLevel(VOID) +{ + /* Release the dispatcher lock */ + KeReleaseQueuedSpinLockFromDpcLevel(LockQueueDispatcherLock); +} + // // This routine inserts a thread into the deferred ready list of the given CPU // @@ -569,7 +633,7 @@ KiAcquirePrcbLock(IN PKPRCB Prcb) for (;;) { /* Acquire the lock and break out if we acquired it first */ - if (!InterlockedExchange(&Prcb->PrcbLock, 1)) break; + if (!InterlockedExchange((PLONG)&Prcb->PrcbLock, 1)) break; /* Loop until the other CPU releases it */ do @@ -595,7 +659,7 @@ KiReleasePrcbLock(IN PKPRCB Prcb) ASSERT(Prcb->PrcbLock != 0); /* Release it */ - InterlockedAnd(&Prcb->PrcbLock, 0); + InterlockedAnd((PLONG)&Prcb->PrcbLock, 0); } // @@ -616,7 +680,7 @@ KiAcquireThreadLock(IN PKTHREAD Thread) for (;;) { /* Acquire the lock and break out if we acquired it first */ - if (!InterlockedExchange(&Thread->ThreadLock, 1)) break; + if (!InterlockedExchange((PLONG)&Thread->ThreadLock, 1)) break; /* Loop until the other CPU releases it */ do @@ -639,7 +703,7 @@ VOID KiReleaseThreadLock(IN PKTHREAD Thread) { /* Release it */ - InterlockedAnd(&Thread->ThreadLock, 0); + InterlockedAnd((PLONG)&Thread->ThreadLock, 0); } FORCEINLINE @@ -653,7 +717,7 @@ KiTryThreadLock(IN PKTHREAD Thread) /* Otherwise, try to acquire it and check the result */ Value = 1; - Value = InterlockedExchange(&Thread->ThreadLock, &Value); + Value = InterlockedExchange((PLONG)&Thread->ThreadLock, Value); /* Return the lock state */ return (Value == TRUE); @@ -667,6 +731,16 @@ KiCheckDeferredReadyList(IN PKPRCB Prcb) if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb); } +FORCEINLINE +VOID +KiRundownThread(IN PKTHREAD Thread) +{ +#if defined(_M_IX86) || defined(_M_AMD64) + /* FIXME: TODO */ + ASSERTMSG("Not yet implemented\n", FALSE); +#endif +} + FORCEINLINE VOID KiRequestApcInterrupt(IN BOOLEAN NeedApc, @@ -676,10 +750,10 @@ KiRequestApcInterrupt(IN BOOLEAN NeedApc, if (NeedApc) { /* Check if it's on another CPU */ - if (KeGetPcr()->Number != Cpu) + if (KeGetPcr()->Number != Processor) { /* Send an IPI to request delivery */ - KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC); + KiIpiSendRequest(AFFINITY_MASK(Processor), IPI_APC); } else { @@ -689,6 +763,36 @@ KiRequestApcInterrupt(IN BOOLEAN NeedApc, } } +FORCEINLINE +PKSPIN_LOCK_QUEUE +KiAcquireTimerLock(IN ULONG Hand) +{ + PKSPIN_LOCK_QUEUE LockQueue; + ULONG LockIndex; + ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); + + /* Get the lock index */ + LockIndex = Hand >> LOCK_QUEUE_TIMER_LOCK_SHIFT; + LockIndex &= (LOCK_QUEUE_TIMER_TABLE_LOCKS - 1); + + /* Now get the lock */ + LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueueTimerTableLock + LockIndex]; + + /* Acquire it and return */ + KeAcquireQueuedSpinLockAtDpcLevel(LockQueue); + return LockQueue; +} + +FORCEINLINE +VOID +KiReleaseTimerLock(IN PKSPIN_LOCK_QUEUE LockQueue) +{ + ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); + + /* Release the lock */ + KeReleaseQueuedSpinLockFromDpcLevel(LockQueue); +} + #endif FORCEINLINE @@ -1525,46 +1629,3 @@ KiComputeNewPriority(IN PKTHREAD Thread, /* Return the new priority */ return Priority; } - -#ifndef _M_ARM -PRKTHREAD -FORCEINLINE -KeGetCurrentThread(VOID) -{ -#ifdef _M_IX86 - /* Return the current thread */ - return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread; -#elif defined (_M_AMD64) - return (PRKTHREAD)__readgsqword(FIELD_OFFSET(KIPCR, Prcb.CurrentThread)); -#else - PKPRCB Prcb = KeGetCurrentPrcb(); - return Prcb->CurrentThread; -#endif -} - -UCHAR -FORCEINLINE -KeGetPreviousMode(VOID) -{ - /* Return the current mode */ - return KeGetCurrentThread()->PreviousMode; -} -#endif - -VOID -FORCEINLINE -KeFlushProcessTb(VOID) -{ - /* Flush the TLB by resetting CR3 */ -#ifdef _M_PPC - __asm__("sync\n\tisync\n\t"); -#elif _M_ARM - // - // We need to implement this! - // - ASSERTMSG("Need ARM flush routine\n", FALSE); -#else - __writecr3(__readcr3()); -#endif -} - diff --git a/reactos/ntoskrnl/ke/timerobj.c b/reactos/ntoskrnl/ke/timerobj.c index 77f9038976a..5f6aeb94aa0 100644 --- a/reactos/ntoskrnl/ke/timerobj.c +++ b/reactos/ntoskrnl/ke/timerobj.c @@ -398,6 +398,10 @@ KeSetTimerEx(IN OUT PKTIMER Timer, /* Check if we need to do an interrupt */ if (RequestInterrupt) HalRequestSoftwareInterrupt(DISPATCH_LEVEL); + + /* Exit the dispatcher and return the old state */ + KiExitDispatcher(OldIrql); + return Inserted; } /* Set the time as Absolute */ @@ -419,7 +423,7 @@ KeSetTimerEx(IN OUT PKTIMER Timer, Timer->Header.SignalState = FALSE; KxInsertTimer(Timer, Hand); - /* Release Dispatcher Lock */ + /* Exit the dispatcher */ KiExitDispatcher(OldIrql); /* Return old state */ diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index 3a7073904dc..c4d6ad65430 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -4644,18 +4644,21 @@ MmMapViewOfSection(IN PVOID SectionObject, if ((Protect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE)) && !(Section->SectionPageProtection & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE))) { + MmUnlockAddressSpace(AddressSpace); return STATUS_SECTION_PROTECTION; } /* check for read access */ if ((Protect & (PAGE_READONLY|PAGE_WRITECOPY|PAGE_EXECUTE_READ|PAGE_EXECUTE_WRITECOPY)) && !(Section->SectionPageProtection & (PAGE_READONLY|PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY))) { + MmUnlockAddressSpace(AddressSpace); return STATUS_SECTION_PROTECTION; } /* check for execute access */ if ((Protect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)) && !(Section->SectionPageProtection & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY))) { + MmUnlockAddressSpace(AddressSpace); return STATUS_SECTION_PROTECTION; } diff --git a/reactos/ntoskrnl/mm/virtual.c b/reactos/ntoskrnl/mm/virtual.c index 4ea2fddaf78..a17d2666008 100644 --- a/reactos/ntoskrnl/mm/virtual.c +++ b/reactos/ntoskrnl/mm/virtual.c @@ -947,6 +947,9 @@ NtQueryVirtualMemory(IN HANDLE ProcessHandle, NTSTATUS Status = STATUS_SUCCESS; SIZE_T ResultLength = 0; KPROCESSOR_MODE PreviousMode; + WCHAR ModuleFileNameBuffer[MAX_PATH] = {0}; + UNICODE_STRING ModuleFileName; + PMEMORY_SECTION_NAME SectionName = NULL; union { MEMORY_BASIC_INFORMATION BasicInfo; @@ -985,13 +988,58 @@ NtQueryVirtualMemory(IN HANDLE ProcessHandle, return STATUS_INVALID_PARAMETER; } - Status = MiQueryVirtualMemory(ProcessHandle, - Address, - VirtualMemoryInformationClass, - &VirtualMemoryInfo, - Length, - &ResultLength ); - + /* FIXME: Move this inside MiQueryVirtualMemory */ + if (VirtualMemoryInformationClass == MemorySectionName) + { + RtlInitEmptyUnicodeString(&ModuleFileName, ModuleFileNameBuffer, sizeof(ModuleFileNameBuffer)); + Status = MmGetFileNameForAddress(Address, &ModuleFileName); + + if (NT_SUCCESS(Status)) + { + SectionName = VirtualMemoryInformation; + if (PreviousMode != KernelMode) + { + _SEH_TRY + { + RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer); + SectionName->SectionFileName.MaximumLength = Length; + RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName); + + if (UnsafeResultLength != NULL) + { + *UnsafeResultLength = ModuleFileName.Length; + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + else + { + RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer); + SectionName->SectionFileName.MaximumLength = Length; + RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName); + + if (UnsafeResultLength != NULL) + { + *UnsafeResultLength = ModuleFileName.Length; + } + } + } + return Status; + } + else + { + Status = MiQueryVirtualMemory(ProcessHandle, + Address, + VirtualMemoryInformationClass, + &VirtualMemoryInfo, + Length, + &ResultLength); + } + if (NT_SUCCESS(Status)) { if (PreviousMode != KernelMode) diff --git a/reactos/ntoskrnl/ntoskrnl-amd64hack.rbuild b/reactos/ntoskrnl/ntoskrnl-amd64hack.rbuild index fe0109bb631..1e39788ea0d 100644 --- a/reactos/ntoskrnl/ntoskrnl-amd64hack.rbuild +++ b/reactos/ntoskrnl/ntoskrnl-amd64hack.rbuild @@ -2,7 +2,7 @@ - + @@ -483,7 +483,7 @@ wmi.c ntoskrnl.rc - ntoskrnl.spec + ntoskrnl.pspec ntoskrnl_$(ARCH).lnk diff --git a/reactos/ntoskrnl/ntoskrnl-generic.rbuild b/reactos/ntoskrnl/ntoskrnl-generic.rbuild index 2387103809a..99f6c8f8242 100644 --- a/reactos/ntoskrnl/ntoskrnl-generic.rbuild +++ b/reactos/ntoskrnl/ntoskrnl-generic.rbuild @@ -2,7 +2,7 @@ - + @@ -466,6 +466,6 @@ wmi.c ntoskrnl.rc - ntoskrnl.spec + ntoskrnl.pspec ntoskrnl_$(ARCH).lnk diff --git a/reactos/ntoskrnl/ntoskrnl.pspec b/reactos/ntoskrnl/ntoskrnl.pspec new file mode 100644 index 00000000000..9fb2550a30c --- /dev/null +++ b/reactos/ntoskrnl/ntoskrnl.pspec @@ -0,0 +1,1660 @@ +#include "include/reactos/msvctarget.h" + +@ stdcall CcCanIWrite(ptr long long long) +@ stdcall CcCopyRead(ptr ptr long long ptr ptr) +@ stdcall CcCopyWrite(ptr ptr long long ptr) +@ stdcall CcDeferWrite(ptr ptr ptr ptr long long) +@ stdcall CcFastCopyRead(ptr long long long ptr ptr) +@ stdcall CcFastCopyWrite(ptr long long ptr) +@ extern CcFastMdlReadWait +@ extern CcFastReadNotPossible +@ extern CcFastReadWait +@ stdcall CcFlushCache(ptr ptr long ptr) +@ stdcall CcGetDirtyPages(ptr ptr ptr ptr) +@ stdcall CcGetFileObjectFromBcb(ptr) +@ stdcall CcGetFileObjectFromSectionPtrs(ptr) +@ stdcall CcGetFlushedValidData(ptr long) +@ stdcall CcGetLsnForFileObject(ptr ptr) +@ stdcall CcInitializeCacheMap(ptr ptr long ptr ptr) +@ stdcall CcIsThereDirtyData(ptr) +@ stdcall CcMapData(ptr ptr long long ptr ptr) +@ stdcall CcMdlRead(ptr ptr long ptr ptr) +@ stdcall CcMdlReadComplete(ptr ptr) +@ stdcall CcMdlWriteAbort(ptr ptr) +@ stdcall CcMdlWriteComplete(ptr ptr ptr) +@ stdcall CcPinMappedData(ptr ptr long long ptr) +@ stdcall CcPinRead(ptr ptr long long ptr ptr) +@ stdcall CcPrepareMdlWrite(ptr ptr long ptr ptr) +@ stdcall CcPreparePinWrite(ptr ptr long long long ptr ptr) +@ stdcall CcPurgeCacheSection(ptr ptr long long) +@ stdcall CcRemapBcb(ptr) +@ stdcall CcRepinBcb(ptr) +@ stdcall CcScheduleReadAhead(ptr ptr long) +@ stdcall CcSetAdditionalCacheAttributes(ptr long long) +@ stdcall CcSetBcbOwnerPointer(ptr ptr) +@ stdcall CcSetDirtyPageThreshold(ptr long) +@ stdcall CcSetDirtyPinnedData(ptr ptr) +@ stdcall CcSetFileSizes(ptr ptr) +@ stdcall CcSetLogHandleForFile(ptr ptr ptr) +@ stdcall CcSetReadAheadGranularity(ptr long) +@ stdcall CcUninitializeCacheMap(ptr ptr ptr) +@ stdcall CcUnpinData(ptr) +@ stdcall CcUnpinDataForThread(ptr ptr) +@ stdcall CcUnpinRepinnedBcb(ptr long ptr) +@ stdcall CcWaitForCurrentLazyWriterActivity() +@ stdcall CcZeroData(ptr ptr ptr long) +@ stdcall CmRegisterCallback(ptr ptr ptr) +@ stdcall CmUnRegisterCallback(long long) +@ stdcall DbgBreakPoint() +@ stdcall DbgBreakPointWithStatus(long) +;DbgCommandString +@ stdcall DbgLoadImageSymbols(ptr ptr long) +@ cdecl DbgPrint(str) +@ cdecl DbgPrintEx(long long str) +@ cdecl DbgPrintReturnControlC(str) +@ stdcall DbgPrompt(str ptr long) +@ stdcall DbgQueryDebugFilterState(long long) +@ stdcall DbgSetDebugFilterState(long long long) +#ifdef __x86_64__ +@ fastcall ExAcquireFastMutex(ptr) +#endif +@ fastcall ExAcquireFastMutexUnsafe(ptr) +@ stdcall ExAcquireResourceExclusiveLite(ptr long) +@ stdcall ExAcquireResourceSharedLite(ptr long) +@ fastcall ExAcquireRundownProtection(ptr) ExfAcquireRundownProtection +@ fastcall ExAcquireRundownProtectionCacheAware(ptr) ExfAcquireRundownProtectionCacheAware +@ fastcall ExAcquireRundownProtectionCacheAwareEx(ptr long) ExfAcquireRundownProtectionCacheAwareEx +@ fastcall ExAcquireRundownProtectionEx(ptr long) ExfAcquireRundownProtectionEx +@ stdcall ExAcquireSharedStarveExclusive(ptr long) +@ stdcall ExAcquireSharedWaitForExclusive(ptr long) +@ stdcall ExAllocateCacheAwareRundownProtection(long long) +@ stdcall ExAllocateFromPagedLookasideList(ptr) ExiAllocateFromPagedLookasideList +@ stdcall ExAllocatePool(long long) +@ stdcall ExAllocatePoolWithQuota(long long) +@ stdcall ExAllocatePoolWithQuotaTag(long long long) +@ stdcall ExAllocatePoolWithTag(long long long) +@ stdcall ExAllocatePoolWithTagPriority(long long long long) +@ stdcall ExConvertExclusiveToSharedLite(ptr) +@ stdcall ExCreateCallback(ptr ptr long long) +@ stdcall ExDeleteNPagedLookasideList(ptr) +@ stdcall ExDeletePagedLookasideList(ptr) +@ stdcall ExDeleteResourceLite(ptr) +@ extern ExDesktopObjectType +@ stdcall ExDisableResourceBoostLite(ptr) +@ fastcall ExEnterCriticalRegionAndAcquireFastMutexUnsafe(ptr) +@ stdcall ExEnterCriticalRegionAndAcquireResourceExclusive(ptr) +;ExEnterCriticalRegionAndAcquireResourceShared +;ExEnterCriticalRegionAndAcquireSharedWaitForExclusive +@ stdcall ExEnumHandleTable(ptr ptr ptr ptr) +@ extern ExEventObjectType _ExEventObjectType +@ stdcall ExExtendZone(ptr ptr long) +@ stdcall ExFreeCacheAwareRundownProtection(ptr) +@ stdcall ExFreePool(ptr) +@ stdcall ExFreePoolWithTag(ptr long) +@ stdcall ExFreeToPagedLookasideList(ptr ptr) ExiFreeToPagedLookasideList +@ stdcall ExGetCurrentProcessorCounts(ptr ptr ptr) +@ stdcall ExGetCurrentProcessorCpuUsage(ptr) +@ stdcall ExGetExclusiveWaiterCount(ptr) +@ stdcall ExGetPreviousMode() +@ stdcall ExGetSharedWaiterCount(ptr) +@ stdcall ExInitializeNPagedLookasideList(ptr ptr ptr long long long long) +@ stdcall ExInitializePagedLookasideList(ptr ptr ptr long long long long) +@ stdcall ExInitializeResourceLite(ptr) +@ fastcall ExInitializeRundownProtection(ptr) ExfInitializeRundownProtection +@ stdcall ExInitializeRundownProtectionCacheAware(ptr long) +@ stdcall ExInitializeZone(ptr long ptr long) +@ stdcall ExInterlockedAddLargeInteger(ptr long long ptr) +@ fastcall ExInterlockedAddLargeStatistic(ptr long) +@ stdcall ExInterlockedAddUlong(ptr long ptr) +#ifndef __x86_64__ +@ fastcall ExInterlockedCompareExchange64(ptr ptr ptr ptr) +@ stdcall ExInterlockedDecrementLong(ptr ptr) +@ stdcall ExInterlockedExchangeUlong(ptr long ptr) +#endif +@ stdcall ExInterlockedExtendZone(ptr ptr long ptr) +#ifndef __x86_64__ +@ fastcall ExInterlockedFlushSList(ptr) +@ stdcall ExInterlockedIncrementLong(ptr ptr) +#endif +@ stdcall ExInterlockedInsertHeadList(ptr ptr ptr) +@ stdcall ExInterlockedInsertTailList(ptr ptr ptr) +@ stdcall ExInterlockedPopEntryList(ptr ptr) +#ifndef __x86_64__ +@ fastcall ExInterlockedPopEntrySList(ptr ptr) +#endif +@ stdcall ExInterlockedPushEntryList(ptr ptr ptr) +#ifndef __x86_64__ +@ fastcall ExInterlockedPushEntrySList(ptr ptr ptr) +#endif +@ stdcall ExInterlockedRemoveHeadList(ptr ptr) +@ stdcall ExIsProcessorFeaturePresent(long) +@ stdcall ExIsResourceAcquiredExclusiveLite(ptr) +@ stdcall ExIsResourceAcquiredSharedLite(ptr) +@ stdcall ExLocalTimeToSystemTime(ptr ptr) +@ stdcall ExNotifyCallback(ptr ptr ptr) +@ stdcall ExQueryPoolBlockSize(ptr ptr) +@ stdcall ExQueueWorkItem(ptr long) +@ stdcall ExRaiseAccessViolation() +@ stdcall ExRaiseDatatypeMisalignment() +@ stdcall ExRaiseException(ptr) RtlRaiseException +@ stdcall ExRaiseHardError(long long long ptr long ptr) +@ stdcall ExRaiseStatus(long) RtlRaiseStatus +@ fastcall ExReInitializeRundownProtection(ptr) ExfReInitializeRundownProtection +@ fastcall ExReInitializeRundownProtectionCacheAware(ptr) ExfReInitializeRundownProtectionCacheAware +@ stdcall ExRegisterCallback(ptr ptr ptr) +@ stdcall ExReinitializeResourceLite(ptr) +#ifdef __x86_64__ +@ fastcall ExReleaseFastMutex(ptr) +#endif +@ fastcall ExReleaseFastMutexUnsafe(ptr) +@ fastcall ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(ptr) +@ fastcall ExReleaseResourceAndLeaveCriticalRegion(ptr) +@ stdcall ExReleaseResourceForThreadLite(ptr long) +@ fastcall ExReleaseResourceLite(ptr) +@ fastcall ExReleaseRundownProtection(ptr) ExfReleaseRundownProtection +@ fastcall ExReleaseRundownProtectionCacheAware(ptr) ExfReleaseRundownProtectionCacheAware +@ fastcall ExReleaseRundownProtectionCacheAwareEx(ptr long) ExfReleaseRundownProtectionCacheAwareEx +@ fastcall ExReleaseRundownProtectionEx(ptr long) ExfReleaseRundownProtectionEx +@ fastcall ExRundownCompleted(ptr) ExfRundownCompleted +@ fastcall ExRundownCompletedCacheAware(ptr) ExfRundownCompletedCacheAware +@ extern ExSemaphoreObjectType _ExSemaphoreObjectType +@ stdcall ExSetResourceOwnerPointer(ptr ptr) +@ stdcall ExSetTimerResolution(long long) +@ stdcall ExSizeOfRundownProtectionCacheAware() +@ stdcall ExSystemExceptionFilter() +@ stdcall ExSystemTimeToLocalTime(ptr ptr) +#ifdef __x86_64__ +@ fastcall ExTryToAcquireFastMutex(ptr) +#endif +@ stdcall ExUnregisterCallback(ptr) +@ stdcall ExUuidCreate(ptr) +@ stdcall ExVerifySuite(long) +@ fastcall ExWaitForRundownProtectionRelease(ptr) ExfWaitForRundownProtectionRelease +@ fastcall ExWaitForRundownProtectionReleaseCacheAware(ptr) ExfWaitForRundownProtectionReleaseCacheAware +@ extern ExWindowStationObjectType +@ fastcall ExfAcquirePushLockExclusive(ptr) +@ fastcall ExfAcquirePushLockShared(ptr) +#ifndef __x86_64__ +@ fastcall ExfInterlockedAddUlong(ptr long ptr) +@ fastcall ExfInterlockedCompareExchange64(ptr ptr ptr) +@ fastcall ExfInterlockedInsertHeadList(ptr ptr ptr) +@ fastcall ExfInterlockedInsertTailList(ptr ptr ptr) +@ fastcall ExfInterlockedPopEntryList(ptr ptr) +@ fastcall ExfInterlockedPushEntryList(ptr ptr ptr) +@ fastcall ExfInterlockedRemoveHeadList(ptr ptr) +#endif +@ fastcall ExfReleasePushLock(ptr) +@ fastcall ExfReleasePushLockExclusive(ptr) +@ fastcall ExfReleasePushLockShared(ptr) +@ fastcall ExfTryToWakePushLock(ptr) +@ fastcall ExfUnblockPushLock(ptr ptr) +#ifdef __x86_64__ +@ stdcall ExpInterlockedFlushSList(ptr) +@ stdcall ExpInterlockedPopEntrySList(ptr ptr) +@ stdcall ExpInterlockedPushEntrySList(ptr ptr) +#endif +#ifdef _M_IX86 +@ fastcall Exfi386InterlockedDecrementLong(ptr) +@ fastcall Exfi386InterlockedExchangeUlong(ptr long) +@ fastcall Exfi386InterlockedIncrementLong(ptr) +@ stdcall Exi386InterlockedDecrementLong(ptr) +@ stdcall Exi386InterlockedExchangeUlong(ptr long long) +@ stdcall Exi386InterlockedIncrementLong(ptr) +#endif +#ifdef _M_IX86 +@ fastcall ExiAcquireFastMutex(ptr) ExAcquireFastMutex +@ fastcall ExiReleaseFastMutex(ptr) ExReleaseFastMutex +@ fastcall ExiTryToAcquireFastMutex(ptr) ExTryToAcquireFastMutex +#endif +@ stdcall FsRtlAcquireFileExclusive(ptr) +;FsRtlAddBaseMcbEntry +@ stdcall FsRtlAddLargeMcbEntry(ptr long long long long long long) +@ stdcall FsRtlAddMcbEntry(ptr long long long) +@ stdcall FsRtlAddToTunnelCache(ptr long long ptr ptr long long ptr) +@ stdcall FsRtlAllocateFileLock(ptr ptr) +@ stdcall FsRtlAllocatePool(long long) +@ stdcall FsRtlAllocatePoolWithQuota(long long) +@ stdcall FsRtlAllocatePoolWithQuotaTag(long long long) +@ stdcall FsRtlAllocatePoolWithTag(long long long) +@ stdcall FsRtlAllocateResource() +@ stdcall FsRtlAreNamesEqual(ptr ptr long wstr) +@ stdcall FsRtlBalanceReads(ptr) +@ stdcall FsRtlCheckLockForReadAccess(ptr ptr) +@ stdcall FsRtlCheckLockForWriteAccess(ptr ptr) +@ stdcall FsRtlCheckOplock(ptr ptr ptr ptr ptr) +@ stdcall FsRtlCopyRead(ptr ptr long long long ptr ptr ptr) +@ stdcall FsRtlCopyWrite(ptr ptr long long long ptr ptr ptr) +@ stdcall FsRtlCreateSectionForDataScan(ptr ptr ptr ptr long ptr ptr long long long) +@ stdcall FsRtlCurrentBatchOplock(ptr) +@ stdcall FsRtlDeleteKeyFromTunnelCache(ptr long long) +@ stdcall FsRtlDeleteTunnelCache(ptr) +@ stdcall FsRtlDeregisterUncProvider(ptr) +@ stdcall FsRtlDissectDbcs(long ptr ptr ptr) +@ stdcall FsRtlDissectName(long ptr ptr ptr) +@ stdcall FsRtlDoesDbcsContainWildCards(ptr) +@ stdcall FsRtlDoesNameContainWildCards(ptr) +@ stdcall FsRtlFastCheckLockForRead(ptr ptr ptr long ptr ptr) +@ stdcall FsRtlFastCheckLockForWrite(ptr ptr ptr long ptr ptr) +@ stdcall FsRtlFastUnlockAll(ptr ptr ptr ptr) +@ stdcall FsRtlFastUnlockAllByKey(ptr ptr ptr long ptr) +@ stdcall FsRtlFastUnlockSingle(ptr ptr ptr ptr ptr long ptr long) +@ stdcall FsRtlFindInTunnelCache(ptr long long ptr ptr ptr ptr ptr) +@ stdcall FsRtlFreeFileLock(ptr) +@ stdcall FsRtlGetFileSize(ptr ptr) +;FsRtlGetNextBaseMcbEntry +@ stdcall FsRtlGetNextFileLock(ptr long) +@ stdcall FsRtlGetNextLargeMcbEntry(ptr long ptr ptr ptr) +@ stdcall FsRtlGetNextMcbEntry(ptr long ptr ptr ptr) +@ stdcall FsRtlIncrementCcFastReadNoWait() +@ stdcall FsRtlIncrementCcFastReadNotPossible() +@ stdcall FsRtlIncrementCcFastReadResourceMiss() +@ stdcall FsRtlIncrementCcFastReadWait() +;FsRtlInitializeBaseMcb +@ stdcall FsRtlInitializeFileLock(ptr ptr ptr) +@ stdcall FsRtlInitializeLargeMcb(ptr long) +@ stdcall FsRtlInitializeMcb(ptr long) +@ stdcall FsRtlInitializeOplock(ptr) +@ stdcall FsRtlInitializeTunnelCache(ptr) +@ stdcall FsRtlInsertPerFileObjectContext(ptr ptr) +@ stdcall FsRtlInsertPerStreamContext(ptr ptr) +@ stdcall FsRtlIsDbcsInExpression(ptr ptr) +@ stdcall FsRtlIsFatDbcsLegal(long ptr long long long) +@ stdcall FsRtlIsHpfsDbcsLegal(long ptr long long long) +@ stdcall FsRtlIsNameInExpression(ptr ptr long wstr) +@ stdcall FsRtlIsNtstatusExpected(long) +@ stdcall FsRtlIsPagingFile(ptr) +@ stdcall FsRtlIsTotalDeviceFailure(ptr) +@ extern FsRtlLegalAnsiCharacterArray _FsRtlLegalAnsiCharacterArray +;FsRtlLookupBaseMcbEntry +@ stdcall FsRtlLookupLargeMcbEntry(ptr long long ptr ptr ptr ptr ptr) +;FsRtlLookupLastBaseMcbEntry +;FsRtlLookupLastBaseMcbEntryAndIndex +@ stdcall FsRtlLookupLastLargeMcbEntry(ptr ptr ptr) +@ stdcall FsRtlLookupLastLargeMcbEntryAndIndex(ptr ptr ptr ptr) +@ stdcall FsRtlLookupLastMcbEntry(ptr ptr ptr) +@ stdcall FsRtlLookupMcbEntry(ptr long ptr ptr ptr) +@ stdcall FsRtlLookupPerFileObjectContext(ptr ptr ptr) +@ stdcall FsRtlLookupPerStreamContextInternal(ptr ptr ptr) +@ stdcall FsRtlMdlRead(ptr ptr long long ptr ptr) +@ stdcall FsRtlMdlReadComplete(ptr ptr) +@ stdcall FsRtlMdlReadCompleteDev(ptr ptr ptr) +@ stdcall FsRtlMdlReadDev(ptr ptr long long ptr ptr ptr) +@ stdcall FsRtlMdlWriteComplete(ptr ptr ptr) +@ stdcall FsRtlMdlWriteCompleteDev(ptr ptr ptr ptr) +@ stdcall FsRtlNormalizeNtstatus(long long) +@ stdcall FsRtlNotifyChangeDirectory(ptr ptr ptr ptr long long ptr) +@ stdcall FsRtlNotifyCleanup(ptr ptr ptr) +@ stdcall FsRtlNotifyFilterChangeDirectory(ptr ptr ptr ptr long long long ptr ptr ptr ptr) +@ stdcall FsRtlNotifyFilterReportChange(ptr ptr ptr long ptr ptr long long ptr ptr) +@ stdcall FsRtlNotifyFullChangeDirectory(ptr ptr ptr ptr long long long ptr ptr ptr) +@ stdcall FsRtlNotifyFullReportChange(ptr ptr ptr long ptr ptr long long ptr) +@ stdcall FsRtlNotifyInitializeSync(ptr) +@ stdcall FsRtlNotifyReportChange(ptr ptr ptr ptr long) +@ stdcall FsRtlNotifyUninitializeSync(ptr) +@ stdcall FsRtlNotifyVolumeEvent(ptr long) +;FsRtlNumberOfRunsInBaseMcb +@ stdcall FsRtlNumberOfRunsInLargeMcb(ptr) +@ stdcall FsRtlNumberOfRunsInMcb(ptr) +@ stdcall FsRtlOplockFsctrl(ptr ptr long) +@ stdcall FsRtlOplockIsFastIoPossible(ptr) +@ stdcall FsRtlPostPagingFileStackOverflow(ptr ptr ptr) +@ stdcall FsRtlPostStackOverflow(ptr ptr ptr) +@ stdcall FsRtlPrepareMdlWrite(ptr ptr long long ptr ptr) +@ stdcall FsRtlPrepareMdlWriteDev(ptr ptr long long ptr ptr ptr) +@ stdcall FsRtlPrivateLock(ptr ptr ptr ptr ptr long long long ptr ptr ptr long) +@ stdcall FsRtlProcessFileLock(ptr ptr ptr) +@ stdcall FsRtlRegisterFileSystemFilterCallbacks(ptr ptr) +@ stdcall FsRtlRegisterUncProvider(ptr ptr long) +@ stdcall FsRtlReleaseFile(ptr) +;FsRtlRemoveBaseMcbEntry +@ stdcall FsRtlRemoveLargeMcbEntry(ptr long long long long) +@ stdcall FsRtlRemoveMcbEntry(ptr long long) +@ stdcall FsRtlRemovePerFileObjectContext(ptr ptr ptr) +@ stdcall FsRtlRemovePerStreamContext(ptr ptr ptr) +;FsRtlResetBaseMcb +@ stdcall FsRtlResetLargeMcb(ptr long) +;FsRtlSplitBaseMcb +@ stdcall FsRtlSplitLargeMcb(ptr long long long long) +@ stdcall FsRtlSyncVolumes(long long long) +@ stdcall FsRtlTeardownPerStreamContexts(ptr) +;FsRtlTruncateBaseMcb +@ stdcall FsRtlTruncateLargeMcb(ptr long long) +@ stdcall FsRtlTruncateMcb(ptr long) +;FsRtlUninitializeBaseMcb +@ stdcall FsRtlUninitializeFileLock(ptr) +@ stdcall FsRtlUninitializeLargeMcb(ptr) +@ stdcall FsRtlUninitializeMcb(ptr) +@ stdcall FsRtlUninitializeOplock(ptr) +@ extern HalDispatchTable _HalDispatchTable +@ fastcall HalExamineMBR(ptr long long ptr) +@ extern HalPrivateDispatchTable +;HeadlessDispatch +@ stdcall InbvAcquireDisplayOwnership() +@ stdcall InbvCheckDisplayOwnership() +@ stdcall InbvDisplayString(str) +@ stdcall InbvEnableBootDriver(long) +@ stdcall InbvEnableDisplayString(long) +@ stdcall InbvInstallDisplayStringFilter(ptr) +@ stdcall InbvIsBootDriverInstalled() +@ stdcall InbvNotifyDisplayOwnershipLost(ptr) +@ stdcall InbvResetDisplay() +@ stdcall InbvSetScrollRegion(long long long long) +@ stdcall InbvSetTextColor(long) +@ stdcall InbvSolidColorFill(long long long long long) +@ extern InitSafeBootMode +@ fastcall InterlockedCompareExchange(ptr long long) +@ fastcall InterlockedDecrement(ptr) +@ fastcall InterlockedExchange(ptr long) +@ fastcall InterlockedExchangeAdd(ptr long) +@ fastcall InterlockedIncrement(ptr) +#ifndef __x86_64__ +@ fastcall InterlockedPopEntrySList(ptr) +@ fastcall InterlockedPushEntrySList(ptr ptr) +#endif +@ stdcall IoAcquireCancelSpinLock(ptr) +@ stdcall IoAcquireRemoveLockEx(ptr ptr str long long) +@ stdcall IoAcquireVpbSpinLock(ptr) +@ extern IoAdapterObjectType +@ stdcall IoAllocateAdapterChannel(ptr ptr long ptr ptr) +@ stdcall IoAllocateController(ptr ptr ptr ptr) +@ stdcall IoAllocateDriverObjectExtension(ptr ptr long ptr) +@ stdcall IoAllocateErrorLogEntry(ptr long) +@ stdcall IoAllocateIrp(long long) +@ stdcall IoAllocateMdl(ptr long long long ptr) +@ stdcall IoAllocateWorkItem(ptr) +@ fastcall IoAssignDriveLetters(ptr ptr ptr ptr) +@ stdcall IoAssignResources(ptr ptr ptr ptr ptr ptr) +@ stdcall IoAttachDevice(ptr ptr ptr) +@ stdcall IoAttachDeviceByPointer(ptr ptr) +@ stdcall IoAttachDeviceToDeviceStack(ptr ptr) +@ stdcall IoAttachDeviceToDeviceStackSafe(ptr ptr ptr) +@ stdcall IoBuildAsynchronousFsdRequest(long ptr ptr long ptr ptr) +@ stdcall IoBuildDeviceIoControlRequest(long ptr ptr long ptr long long ptr ptr) +@ stdcall IoBuildPartialMdl(ptr ptr ptr long) +@ stdcall IoBuildSynchronousFsdRequest(long ptr ptr long ptr ptr ptr) +@ stdcall IoCallDriver(ptr ptr) +@ stdcall IoCancelFileOpen(ptr ptr) +@ stdcall IoCancelIrp(ptr) +@ stdcall IoCheckDesiredAccess(ptr long) +@ stdcall IoCheckEaBufferValidity(ptr long ptr) +@ stdcall IoCheckFunctionAccess(long long long long ptr ptr) +@ stdcall IoCheckQuerySetFileInformation(long long long) +@ stdcall IoCheckQuerySetVolumeInformation(long long long) +@ stdcall IoCheckQuotaBufferValidity(ptr long ptr) +@ stdcall IoCheckShareAccess(long long ptr ptr long) +@ stdcall IoCompleteRequest(ptr long) +@ stdcall IoConnectInterrupt(ptr ptr ptr ptr long long long long long long long) +@ stdcall IoCreateController(long) +@ stdcall IoCreateDevice(ptr long ptr long long long ptr) +@ stdcall IoCreateDisk(ptr ptr) +@ stdcall IoCreateDriver(ptr ptr) +@ stdcall IoCreateFile(ptr long ptr ptr ptr long long long long ptr long long ptr long) +@ stdcall IoCreateFileSpecifyDeviceObjectHint(ptr long ptr ptr ptr long long long long ptr long long ptr long ptr) +@ stdcall IoCreateNotificationEvent(ptr ptr) +@ stdcall IoCreateStreamFileObject(ptr ptr) +@ stdcall IoCreateStreamFileObjectEx(ptr ptr ptr) +@ stdcall IoCreateStreamFileObjectLite(ptr ptr) +@ stdcall IoCreateSymbolicLink(ptr ptr) +@ stdcall IoCreateSynchronizationEvent(ptr ptr) +@ stdcall IoCreateUnprotectedSymbolicLink(ptr ptr) +@ stdcall IoCsqInitialize(ptr ptr ptr ptr ptr ptr ptr) +@ stdcall IoCsqInitializeEx(ptr ptr ptr ptr ptr ptr ptr) +@ stdcall IoCsqInsertIrp(ptr ptr ptr) +@ stdcall IoCsqInsertIrpEx(ptr ptr ptr ptr) +@ stdcall IoCsqRemoveIrp(ptr ptr) +@ stdcall IoCsqRemoveNextIrp(ptr ptr) +@ stdcall IoDeleteController(ptr) +@ stdcall IoDeleteDevice(ptr) +@ stdcall IoDeleteDriver(ptr) +@ stdcall IoDeleteSymbolicLink(ptr) +@ stdcall IoDetachDevice(ptr) +@ extern IoDeviceHandlerObjectSize +@ extern IoDeviceHandlerObjectType +@ extern IoDeviceObjectType +@ stdcall IoDisconnectInterrupt(ptr) +@ extern IoDriverObjectType +@ stdcall IoEnqueueIrp(ptr) +@ stdcall IoEnumerateDeviceObjectList(ptr ptr long ptr) +@ stdcall IoEnumerateRegisteredFiltersList(ptr long ptr) +@ stdcall IoFastQueryNetworkAttributes(ptr long long ptr ptr) +@ extern IoFileObjectType _IoFileObjectType +@ stdcall IoForwardAndCatchIrp(ptr ptr) IoForwardIrpSynchronously +@ stdcall IoForwardIrpSynchronously(ptr ptr) +@ stdcall IoFreeController(ptr) +@ stdcall IoFreeErrorLogEntry(ptr) +@ stdcall IoFreeIrp(ptr) +@ stdcall IoFreeMdl(ptr) +@ stdcall IoFreeWorkItem(ptr) +@ stdcall IoGetAttachedDevice(ptr) +@ stdcall IoGetAttachedDeviceReference(ptr) +@ stdcall IoGetBaseFileSystemDeviceObject(ptr) +@ stdcall IoGetBootDiskInformation(ptr long) +@ stdcall IoGetConfigurationInformation() +@ stdcall IoGetCurrentProcess() +@ stdcall IoGetDeviceAttachmentBaseRef(ptr) +@ stdcall IoGetDeviceInterfaceAlias(ptr ptr ptr) +@ stdcall IoGetDeviceInterfaces(ptr ptr long ptr) +@ stdcall IoGetDeviceObjectPointer(ptr long ptr ptr) +@ stdcall IoGetDeviceProperty(ptr long long ptr ptr) +@ stdcall IoGetDeviceToVerify(ptr) +@ stdcall IoGetDiskDeviceObject(ptr ptr) +@ stdcall IoGetDmaAdapter(ptr ptr ptr) +@ stdcall IoGetDriverObjectExtension(ptr ptr) +@ stdcall IoGetFileObjectGenericMapping() +@ stdcall IoGetInitialStack() +@ stdcall IoGetLowerDeviceObject(ptr) +@ fastcall IoGetPagingIoPriority(ptr) +@ stdcall IoGetRelatedDeviceObject(ptr) +@ stdcall IoGetRequestorProcess(ptr) +@ stdcall IoGetRequestorProcessId(ptr) +@ stdcall IoGetRequestorSessionId(ptr ptr) +@ stdcall IoGetStackLimits(ptr ptr) +@ stdcall IoGetTopLevelIrp() +@ stdcall IoInitializeIrp(ptr long long) +@ stdcall IoInitializeRemoveLockEx(ptr long long long long) +@ stdcall IoInitializeTimer(ptr ptr ptr) +@ stdcall IoInvalidateDeviceRelations(ptr long) +@ stdcall IoInvalidateDeviceState(ptr) +@ stdcall IoIsFileOriginRemote(ptr) +@ stdcall IoIsOperationSynchronous(ptr) +@ stdcall IoIsSystemThread(ptr) +@ stdcall IoIsValidNameGraftingBuffer(ptr ptr) +@ stdcall IoIsWdmVersionAvailable(long long) +@ stdcall IoMakeAssociatedIrp(ptr long) +@ stdcall IoOpenDeviceInterfaceRegistryKey(ptr long ptr) +@ stdcall IoOpenDeviceRegistryKey(ptr long long ptr) +@ stdcall IoPageRead(ptr ptr ptr ptr ptr) +@ stdcall IoPnPDeliverServicePowerNotification(long long long long) +@ stdcall IoQueryDeviceDescription(ptr ptr ptr ptr ptr ptr ptr ptr) +@ stdcall IoQueryFileDosDeviceName(ptr ptr) +@ stdcall IoQueryFileInformation(ptr long long ptr ptr) +@ stdcall IoQueryVolumeInformation(ptr long long ptr ptr) +@ stdcall IoQueueThreadIrp(ptr) +@ stdcall IoQueueWorkItem(ptr ptr long ptr) +@ stdcall IoRaiseHardError(ptr ptr ptr) +@ stdcall IoRaiseInformationalHardError(long ptr ptr) +@ stdcall IoReadDiskSignature(ptr long ptr) +@ extern IoReadOperationCount +@ fastcall IoReadPartitionTable(ptr long long ptr) +@ stdcall IoReadPartitionTableEx(ptr ptr) +@ extern IoReadTransferCount +@ stdcall IoRegisterBootDriverReinitialization(ptr ptr ptr) +@ stdcall IoRegisterDeviceInterface(ptr ptr ptr ptr) +@ stdcall IoRegisterDriverReinitialization(ptr ptr ptr) +@ stdcall IoRegisterFileSystem(ptr) +@ stdcall IoRegisterFsRegistrationChange(ptr ptr) +@ stdcall IoRegisterLastChanceShutdownNotification(ptr) +@ stdcall IoRegisterPlugPlayNotification(long long ptr ptr ptr ptr ptr) +@ stdcall IoRegisterShutdownNotification(ptr) +@ stdcall IoReleaseCancelSpinLock(long) +@ stdcall IoReleaseRemoveLockAndWaitEx(ptr ptr long) +@ stdcall IoReleaseRemoveLockEx(ptr ptr long) +@ stdcall IoReleaseVpbSpinLock(long) +@ stdcall IoRemoveShareAccess(ptr ptr) +@ stdcall IoReportDetectedDevice(ptr long long long ptr ptr long ptr) +@ stdcall IoReportHalResourceUsage(ptr ptr ptr long) +@ stdcall IoReportResourceForDetection(ptr ptr long ptr ptr long ptr) +@ stdcall IoReportResourceUsage(ptr ptr ptr long ptr ptr long long ptr) +@ stdcall IoReportTargetDeviceChange(ptr ptr) +@ stdcall IoReportTargetDeviceChangeAsynchronous(ptr ptr ptr ptr) +@ stdcall IoRequestDeviceEject(ptr) +@ stdcall IoReuseIrp(ptr long) +@ stdcall IoSetCompletionRoutineEx(ptr ptr ptr ptr long long long) +@ stdcall IoSetDeviceInterfaceState(ptr long) +@ stdcall IoSetDeviceToVerify(ptr ptr) +@ stdcall IoSetFileOrigin(ptr long) +@ stdcall IoSetHardErrorOrVerifyDevice(ptr ptr) +@ stdcall IoSetInformation(ptr ptr long ptr) +@ stdcall IoSetIoCompletion(ptr ptr ptr long ptr long) +@ fastcall IoSetPartitionInformation(ptr long long long) +@ stdcall IoSetPartitionInformationEx(ptr long ptr) +@ stdcall IoSetShareAccess(long long ptr ptr) +@ stdcall IoSetStartIoAttributes(ptr long long) +@ stdcall IoSetSystemPartition(ptr) +@ stdcall IoSetThreadHardErrorMode(long) +@ stdcall IoSetTopLevelIrp(ptr) +@ stdcall IoStartNextPacket(ptr long) +@ stdcall IoStartNextPacketByKey(ptr long long) +@ stdcall IoStartPacket(ptr ptr ptr ptr) +@ stdcall IoStartTimer(ptr) +@ extern IoStatisticsLock +@ stdcall IoStopTimer(ptr) +@ stdcall IoSynchronousInvalidateDeviceRelations(ptr long) +@ stdcall IoSynchronousPageWrite(ptr ptr ptr ptr ptr) +@ stdcall IoThreadToProcess(ptr) +;IoTranslateBusAddress +@ stdcall IoUnregisterFileSystem(ptr) +@ stdcall IoUnregisterFsRegistrationChange(ptr ptr) +@ stdcall IoUnregisterPlugPlayNotification(ptr) +@ stdcall IoUnregisterShutdownNotification(ptr) +@ stdcall IoUpdateShareAccess(ptr ptr) +@ stdcall IoValidateDeviceIoControlAccess(ptr long) +@ stdcall IoVerifyPartitionTable(ptr long) +@ stdcall IoVerifyVolume(ptr long) +@ stdcall IoVolumeDeviceToDosName(ptr ptr) +@ stdcall IoWMIAllocateInstanceIds(ptr long ptr) +@ stdcall IoWMIDeviceObjectToInstanceName(ptr ptr ptr) +@ stdcall IoWMIExecuteMethod(ptr ptr long long ptr ptr) +@ stdcall IoWMIHandleToInstanceName(ptr ptr ptr) +@ stdcall IoWMIOpenBlock(ptr long ptr) +@ stdcall IoWMIQueryAllData(ptr ptr ptr) +@ stdcall IoWMIQueryAllDataMultiple(ptr long ptr ptr) +@ stdcall IoWMIQuerySingleInstance(ptr ptr ptr ptr) +@ stdcall IoWMIQuerySingleInstanceMultiple(ptr ptr long ptr ptr) +@ stdcall IoWMIRegistrationControl(ptr long) +@ stdcall IoWMISetNotificationCallback(ptr ptr ptr) +@ stdcall IoWMISetSingleInstance(ptr ptr long long ptr) +@ stdcall IoWMISetSingleItem(ptr ptr long long long ptr) +@ stdcall IoWMISuggestInstanceName(ptr ptr long ptr) +@ stdcall IoWMIWriteEvent(ptr) +@ stdcall IoWriteErrorLogEntry(ptr) +@ extern IoWriteOperationCount +@ fastcall IoWritePartitionTable(ptr long long long ptr) +@ stdcall IoWritePartitionTableEx(ptr ptr) +@ extern IoWriteTransferCount +@ fastcall IofCallDriver(ptr ptr) +@ fastcall IofCompleteRequest(ptr long) +@ stdcall KdChangeOption(long long ptr long ptr ptr) +@ extern KdDebuggerEnabled _KdDebuggerEnabled +@ extern KdDebuggerNotPresent _KdDebuggerNotPresent +@ stdcall KdDisableDebugger() +@ stdcall KdEnableDebugger() +@ extern KdEnteredDebugger +@ stdcall KdPollBreakIn() +@ stdcall KdPowerTransition(long) +@ stdcall KdRefreshDebuggerNotPresent() +@ stdcall KdSystemDebugControl(long ptr long ptr long ptr long) +#ifdef _M_IX86 +@ stdcall Ke386CallBios(long ptr) +;Ke386IoSetAccessProcess +;Ke386QueryIoAccessMap +;Ke386SetIoAccessMap +#endif +@ fastcall KeAcquireGuardedMutex(ptr) +@ fastcall KeAcquireGuardedMutexUnsafe(ptr) +@ fastcall KeAcquireInStackQueuedSpinLockAtDpcLevel(ptr ptr) +@ fastcall KeAcquireInStackQueuedSpinLockForDpc(ptr ptr) +@ stdcall KeAcquireInterruptSpinLock(ptr) +@ stdcall KeAcquireSpinLockAtDpcLevel(ptr) +@ fastcall KeAcquireSpinLockForDpc(ptr) +#ifdef __x86_64__ +@ stdcall KeAcquireSpinLockRaiseToDpc(ptr) +#endif +@ stdcall KeAddSystemServiceTable(ptr ptr long ptr long) +@ stdcall KeAreAllApcsDisabled() +@ stdcall KeAreApcsDisabled() +@ stdcall KeAttachProcess(ptr) +@ stdcall KeBugCheck(long) +@ stdcall KeBugCheckEx(long ptr ptr ptr ptr) +@ stdcall KeCancelTimer(ptr) +@ stdcall KeCapturePersistentThreadState(ptr long long long long long ptr) +@ stdcall KeClearEvent(ptr) +@ stdcall KeConnectInterrupt(ptr) +@ stdcall KeDelayExecutionThread(long long ptr) +@ stdcall KeDeregisterBugCheckCallback(ptr) +@ stdcall KeDeregisterBugCheckReasonCallback(ptr) +@ stdcall KeDeregisterNmiCallback(ptr) +@ stdcall KeDetachProcess() +@ stdcall KeDisconnectInterrupt(ptr) +@ stdcall KeEnterCriticalRegion() _KeEnterCriticalRegion +@ stdcall KeEnterGuardedRegion() _KeEnterGuardedRegion +@ stdcall KeEnterKernelDebugger() +@ stdcall KeFindConfigurationEntry(ptr long long ptr) +@ stdcall KeFindConfigurationNextEntry(ptr long long ptr ptr) +@ stdcall KeFlushEntireTb(long long) +@ stdcall KeFlushQueuedDpcs() +;KeGenericCallDpc +@ stdcall KeGetCurrentThread() +@ stdcall KeGetPreviousMode() +@ stdcall KeGetRecommendedSharedDataAlignment() +#ifdef _M_IX86 +;KeI386AbiosCall +@ stdcall KeI386AllocateGdtSelectors(ptr long) +;KeI386Call16BitCStyleFunction +;KeI386Call16BitFunction +@ stdcall KeI386FlatToGdtSelector(long long long) +;KeI386GetLid +@ extern KeI386MachineType +@ stdcall KeI386ReleaseGdtSelectors(ptr long) +;KeI386ReleaseLid +;KeI386SetGdtSelector +#endif +@ stdcall KeInitializeApc(ptr ptr long ptr ptr ptr long ptr) +@ stdcall KeInitializeCrashDumpHeader(long long ptr long ptr) +@ stdcall KeInitializeDeviceQueue(ptr) +@ stdcall KeInitializeDpc(ptr ptr ptr) +@ stdcall KeInitializeEvent(ptr long long) +@ fastcall KeInitializeGuardedMutex(ptr) +@ stdcall KeInitializeInterrupt(ptr ptr ptr ptr long long long long long long long) +@ stdcall KeInitializeMutant(ptr long) +@ stdcall KeInitializeMutex(ptr long) +@ stdcall KeInitializeQueue(ptr long) +@ stdcall KeInitializeSemaphore(ptr long long) +#ifndef __x86_64__ +@ stdcall KeInitializeSpinLock(ptr) +#endif +@ stdcall KeInitializeThreadedDpc(ptr ptr ptr) +@ stdcall KeInitializeTimer(ptr) +@ stdcall KeInitializeTimerEx(ptr long) +@ stdcall KeInsertByKeyDeviceQueue(ptr ptr long) +@ stdcall KeInsertDeviceQueue(ptr ptr) +@ stdcall KeInsertHeadQueue(ptr ptr) +@ stdcall KeInsertQueue(ptr ptr) +@ stdcall KeInsertQueueApc(ptr ptr ptr long) +@ stdcall KeInsertQueueDpc(ptr ptr ptr) +@ stdcall KeInvalidateAllCaches() +@ stdcall KeIpiGenericCall(ptr ptr) +@ stdcall KeIsAttachedProcess() +@ stdcall KeIsExecutingDpc() +;KeIsWaitListEmpty +@ stdcall KeLeaveCriticalRegion() _KeLeaveCriticalRegion +@ stdcall KeLeaveGuardedRegion() _KeLeaveGuardedRegion +@ extern KeLoaderBlock +@ extern KeNumberProcessors +@ stdcall KeProfileInterrupt(ptr) +@ stdcall KeProfileInterruptWithSource(ptr long) +@ stdcall KePulseEvent(ptr long long) +@ stdcall KeQueryActiveProcessors() +#ifndef __x86_64__ +@ stdcall KeQueryInterruptTime() +#endif +@ stdcall KeQueryPriorityThread(ptr) +@ stdcall KeQueryRuntimeThread(ptr ptr) +#ifndef __x86_64__ +@ stdcall KeQuerySystemTime(ptr) +#endif +@ stdcall KeQueryTickCount(ptr) +@ stdcall KeQueryTimeIncrement() +@ stdcall KeRaiseUserException(long) +@ stdcall KeReadStateEvent(ptr) +@ stdcall KeReadStateMutant(ptr) +@ stdcall KeReadStateMutex(ptr) KeReadStateMutant +@ stdcall KeReadStateQueue(ptr) +@ stdcall KeReadStateSemaphore(ptr) +@ stdcall KeReadStateTimer(ptr) +@ stdcall KeRegisterBugCheckCallback(ptr ptr ptr long ptr) +@ stdcall KeRegisterBugCheckReasonCallback(ptr ptr ptr ptr) +@ stdcall KeRegisterNmiCallback(ptr ptr) +@ fastcall KeReleaseGuardedMutex(ptr) +@ fastcall KeReleaseGuardedMutexUnsafe(ptr) +@ fastcall KeReleaseInStackQueuedSpinLockForDpc(ptr) +@ fastcall KeReleaseInStackQueuedSpinLockFromDpcLevel(ptr) +@ stdcall KeReleaseInterruptSpinLock(ptr long) +@ stdcall KeReleaseMutant(ptr long long long) +@ stdcall KeReleaseMutex(ptr long) +@ stdcall KeReleaseSemaphore(ptr long long long) +#ifdef __x86_64__ +@ stdcall KeReleaseSpinLock(ptr long) +#endif +@ fastcall KeReleaseSpinLockForDpc(ptr long) +@ stdcall KeReleaseSpinLockFromDpcLevel(ptr) +@ stdcall KeRemoveByKeyDeviceQueue(ptr long) +@ stdcall KeRemoveByKeyDeviceQueueIfBusy(ptr long) +@ stdcall KeRemoveDeviceQueue(ptr) +@ stdcall KeRemoveEntryDeviceQueue(ptr ptr) +@ stdcall KeRemoveQueue(ptr long ptr) +@ stdcall KeRemoveQueueDpc(ptr) +@ stdcall KeRemoveSystemServiceTable(long) +@ stdcall KeResetEvent(ptr) +@ stdcall KeRestoreFloatingPointState(ptr) +@ stdcall KeRevertToUserAffinityThread() +@ stdcall KeRundownQueue(ptr) +@ stdcall KeSaveFloatingPointState(ptr) +@ cdecl KeSaveStateForHibernate(ptr) +@ extern KeServiceDescriptorTable +@ stdcall KeSetAffinityThread(ptr long) +@ stdcall KeSetBasePriorityThread(ptr long) +@ stdcall KeSetDmaIoCoherency(long) +@ stdcall KeSetEvent(ptr long long) +@ stdcall KeSetEventBoostPriority(ptr ptr) +@ stdcall KeSetIdealProcessorThread(ptr long) +@ stdcall KeSetImportanceDpc(ptr long) +@ stdcall KeSetKernelStackSwapEnable(long) +@ stdcall KeSetPriorityThread(ptr long) +@ stdcall KeSetProfileIrql(long) +@ stdcall KeSetSystemAffinityThread(long) +@ stdcall KeSetTargetProcessorDpc(ptr long) +@ stdcall KeSetTimeIncrement(long long) +@ stdcall KeSetTimer(ptr long long ptr) +@ stdcall KeSetTimerEx(ptr long long long ptr) +;KeSignalCallDpcDone +;KeSignalCallDpcSynchronize +@ stdcall KeStackAttachProcess(ptr ptr) +@ stdcall KeSynchronizeExecution(ptr ptr ptr) +@ stdcall KeTerminateThread(long) +@ fastcall KeTestSpinLock(ptr) +@ extern KeTickCount +@ fastcall KeTryToAcquireGuardedMutex(ptr) +@ fastcall KeTryToAcquireSpinLockAtDpcLevel(ptr) +@ stdcall KeUnstackDetachProcess(ptr) +@ stdcall KeUpdateRunTime(ptr long) +#ifdef _M_IX86 +@ stdcall KeUpdateSystemTime() +#else +@ stdcall KeUpdateSystemTime(ptr long long) +#endif +@ stdcall KeUserModeCallback(long ptr long ptr ptr) +@ stdcall KeWaitForMultipleObjects(long ptr long long long long ptr ptr) +@ stdcall KeWaitForMutexObject(ptr long long long ptr) KeWaitForSingleObject +@ stdcall KeWaitForSingleObject(ptr long long long ptr) +@ fastcall KefAcquireSpinLockAtDpcLevel(ptr) +@ fastcall KefReleaseSpinLockFromDpcLevel(ptr) +#ifdef _M_IX86 +@ stdcall Kei386EoiHelper() +#endif +@ fastcall KiAcquireSpinLock(ptr) +@ extern KiBugCheckData +@ stdcall KiCheckForKernelApcDelivery() +#ifdef _M_IX86 +@ stdcall KiCoprocessorError() +#endif +@ stdcall KiDeliverApc(long ptr ptr) +#ifdef _M_IX86 +@ stdcall KiDispatchInterrupt() +#endif +@ extern KiEnableTimerWatchdog +@ stdcall KiIpiServiceRoutine(ptr ptr) +@ fastcall KiReleaseSpinLock(ptr) +@ cdecl KiUnexpectedInterrupt() +#ifdef _M_IX86 +;Kii386SpinOnSpinLock +#endif +@ stdcall LdrAccessResource(ptr ptr ptr ptr) +@ stdcall LdrEnumResources(ptr ptr long ptr ptr) +@ stdcall LdrFindResourceDirectory_U(ptr ptr long ptr) +@ stdcall LdrFindResource_U(ptr ptr long ptr) +@ extern LpcPortObjectType +@ stdcall LpcRequestPort(ptr ptr) +@ stdcall LpcRequestWaitReplyPort(ptr ptr ptr) +@ stdcall LsaCallAuthenticationPackage(long long long long long long long) +@ stdcall LsaDeregisterLogonProcess(long long) +@ stdcall LsaFreeReturnBuffer(ptr) +@ stdcall LsaLogonUser(ptr ptr long long ptr long ptr ptr ptr ptr ptr ptr ptr ptr) +@ stdcall LsaLookupAuthenticationPackage(long long long) +@ stdcall LsaRegisterLogonProcess(ptr ptr ptr) +@ extern Mm64BitPhysicalAddress +@ stdcall MmAddPhysicalMemory(ptr ptr) +@ stdcall MmAddVerifierThunks(ptr long) +@ stdcall MmAdjustWorkingSetSize(long long long long) +@ stdcall MmAdvanceMdl(ptr long) +@ stdcall MmAllocateContiguousMemory(long long long) +@ stdcall MmAllocateContiguousMemorySpecifyCache(long long long long long long long long) +@ stdcall MmAllocateMappingAddress(long long) +@ stdcall MmAllocateNonCachedMemory(long) +@ stdcall MmAllocatePagesForMdl(ptr ptr ptr ptr ptr ptr ptr) +@ stdcall MmAllocatePagesForMdlEx(long long long long long long long long long) +@ stdcall MmBuildMdlForNonPagedPool(ptr) +@ stdcall MmCanFileBeTruncated(ptr ptr) +;MmCommitSessionMappedView +@ stdcall MmCreateMdl(ptr ptr long) +;MmCreateMirror +@ stdcall MmCreateSection(ptr long ptr ptr long long ptr ptr) +@ stdcall MmDisableModifiedWriteOfSection(long) +@ stdcall MmFlushImageSection(ptr long) +@ stdcall MmForceSectionClosed(ptr long) +@ stdcall MmFreeContiguousMemory(ptr) +@ stdcall MmFreeContiguousMemorySpecifyCache(ptr long long) +@ stdcall MmFreeMappingAddress(ptr long) +@ stdcall MmFreeNonCachedMemory(ptr long) +@ stdcall MmFreePagesFromMdl(ptr) +@ stdcall MmGetPhysicalAddress(ptr) +@ stdcall MmGetPhysicalMemoryRanges() +@ stdcall MmGetSystemRoutineAddress(ptr) +@ stdcall MmGetVirtualForPhysical(long long) +@ stdcall MmGrowKernelStack(ptr) +@ extern MmHighestUserAddress +@ stdcall MmIsAddressValid(ptr) +@ stdcall MmIsDriverVerifying(ptr) +;MmIsIoSpaceActive +@ stdcall MmIsNonPagedSystemAddressValid(ptr) +@ stdcall MmIsRecursiveIoFault() +@ stdcall MmIsThisAnNtAsSystem() +@ stdcall MmIsVerifierEnabled(ptr) +@ stdcall MmLockPagableDataSection(ptr) +@ stdcall MmLockPagableImageSection(ptr) MmLockPagableDataSection +@ stdcall MmLockPagableSectionByHandle(ptr) +@ stdcall MmMapIoSpace(long long long long) +@ stdcall MmMapLockedPages(ptr long) +@ stdcall MmMapLockedPagesSpecifyCache(ptr long long ptr long long) +@ stdcall MmMapLockedPagesWithReservedMapping(ptr long ptr long) +@ stdcall MmMapMemoryDumpMdl(ptr) +@ stdcall MmMapUserAddressesToPage(ptr long ptr) +@ stdcall MmMapVideoDisplay(long long long long) +@ stdcall MmMapViewInSessionSpace(ptr ptr ptr) +@ stdcall MmMapViewInSystemSpace(ptr ptr ptr) +@ stdcall MmMapViewOfSection(ptr ptr ptr long long ptr ptr long long long) +@ stdcall MmMarkPhysicalMemoryAsBad(ptr ptr) +@ stdcall MmMarkPhysicalMemoryAsGood(ptr ptr) +@ stdcall MmPageEntireDriver(ptr) +@ stdcall MmPrefetchPages(long ptr) +@ stdcall MmProbeAndLockPages(ptr long long) +@ stdcall MmProbeAndLockProcessPages(ptr ptr long long) +@ stdcall MmProbeAndLockSelectedPages(ptr ptr long long) +@ stdcall MmProtectMdlSystemAddress(ptr long) +@ stdcall MmQuerySystemSize() +@ stdcall MmRemovePhysicalMemory(ptr ptr) +@ stdcall MmResetDriverPaging(ptr) +@ extern MmSectionObjectType +@ stdcall MmSecureVirtualMemory(ptr long long) +@ stdcall MmSetAddressRangeModified(ptr long) +@ stdcall MmSetBankedSection(long long long long long long) +@ stdcall MmSizeOfMdl(ptr long) +@ extern MmSystemRangeStart +@ stdcall MmTrimAllSystemPagableMemory(long) +@ stdcall MmUnlockPagableImageSection(ptr) +@ stdcall MmUnlockPages(ptr) +@ stdcall MmUnmapIoSpace(ptr long) +@ stdcall MmUnmapLockedPages(ptr ptr) +@ stdcall MmUnmapReservedMapping(ptr long ptr) +@ stdcall MmUnmapVideoDisplay(ptr long) +@ stdcall MmUnmapViewInSessionSpace(ptr) +@ stdcall MmUnmapViewInSystemSpace(ptr) +@ stdcall MmUnmapViewOfSection(ptr ptr) +@ stdcall MmUnsecureVirtualMemory(ptr) +@ extern MmUserProbeAddress +@ extern NlsAnsiCodePage +@ extern NlsLeadByteInfo +@ extern NlsMbCodePageTag +@ extern NlsMbOemCodePageTag +@ extern NlsOemCodePage +@ extern NlsOemLeadByteInfo _NlsOemLeadByteInfo +@ stdcall NtAddAtom(wstr long ptr) +@ stdcall NtAdjustPrivilegesToken(ptr long ptr long ptr ptr) +@ stdcall NtAlertThread(ptr) +@ stdcall NtAllocateLocallyUniqueId(ptr) +@ stdcall NtAllocateUuids(ptr ptr ptr ptr) +@ stdcall NtAllocateVirtualMemory(ptr ptr long ptr long long) +@ extern NtBuildNumber +@ stdcall NtClose(ptr) +@ stdcall NtConnectPort(ptr ptr ptr ptr ptr ptr ptr ptr) +@ stdcall NtCreateEvent(ptr long ptr long long) +@ stdcall NtCreateFile(ptr long ptr ptr ptr long long long long ptr long) +@ stdcall NtCreateSection(ptr long ptr ptr long long ptr) +@ stdcall NtCreateTimer(ptr long ptr long) +@ stdcall NtDeleteAtom(ptr) +@ stdcall NtDeleteFile(ptr) +@ stdcall NtDeviceIoControlFile(ptr ptr ptr ptr ptr long ptr long ptr long) +@ stdcall NtDuplicateObject(ptr ptr ptr ptr long long long) +@ stdcall NtDuplicateToken(ptr long ptr long long ptr) +@ stdcall NtFindAtom(wstr long ptr) +@ stdcall NtFreeVirtualMemory(ptr ptr ptr long) +@ stdcall NtFsControlFile(ptr ptr ptr ptr ptr long ptr long ptr long) +@ extern NtGlobalFlag +@ stdcall NtLockFile(ptr ptr ptr ptr ptr ptr ptr long long long) +@ stdcall NtMakePermanentObject(ptr) +@ stdcall NtMapViewOfSection(ptr ptr ptr long long ptr ptr long long long) +@ stdcall NtNotifyChangeDirectoryFile(ptr ptr ptr ptr ptr ptr long long long) +@ stdcall NtOpenEvent(ptr long ptr) +@ stdcall NtOpenFile(ptr long ptr ptr long long) +@ stdcall NtOpenProcess(ptr long ptr ptr) +@ stdcall NtOpenProcessToken(ptr long ptr) +@ stdcall NtOpenProcessTokenEx(ptr long long ptr) +@ stdcall NtOpenThread(ptr long ptr ptr) +@ stdcall NtOpenThreadToken(ptr long long ptr) +@ stdcall NtOpenThreadTokenEx(ptr long long long ptr) +@ stdcall NtQueryDirectoryFile(ptr ptr ptr ptr ptr ptr long long long ptr long) +@ stdcall NtQueryEaFile(ptr ptr ptr long long ptr long ptr long) +@ stdcall NtQueryInformationAtom(ptr long ptr long ptr) +@ stdcall NtQueryInformationFile(ptr ptr ptr long long) +@ stdcall NtQueryInformationProcess(ptr ptr ptr long ptr) +@ stdcall NtQueryInformationThread(ptr long ptr long ptr) +@ stdcall NtQueryInformationToken(ptr long ptr long ptr) +@ stdcall NtQueryQuotaInformationFile(ptr ptr ptr long long ptr long ptr long) +@ stdcall NtQuerySecurityObject(ptr long ptr long ptr) +@ stdcall NtQuerySystemInformation(long ptr long ptr) +@ stdcall NtQueryVolumeInformationFile(ptr ptr ptr long long) +@ stdcall NtReadFile(ptr ptr ptr ptr ptr ptr long ptr ptr) +@ stdcall NtRequestPort(ptr ptr) +@ stdcall NtRequestWaitReplyPort(ptr ptr ptr) +@ stdcall NtSetEaFile(ptr ptr ptr long) +@ stdcall NtSetEvent(ptr ptr) +@ stdcall NtSetInformationFile(ptr ptr ptr long long) +@ stdcall NtSetInformationProcess(ptr ptr ptr long) +@ stdcall NtSetInformationThread(ptr long ptr long) +@ stdcall NtSetQuotaInformationFile(ptr ptr ptr long) +@ stdcall NtSetSecurityObject(ptr long ptr) +@ stdcall NtSetVolumeInformationFile(ptr ptr ptr long long) +@ stdcall NtShutdownSystem(long) +@ stdcall NtTraceEvent(long long long ptr) +@ stdcall NtUnlockFile(ptr ptr ptr ptr long) +@ stdcall NtVdmControl(long ptr) +@ stdcall NtWaitForSingleObject(ptr long ptr) +@ stdcall NtWriteFile(ptr ptr ptr ptr ptr ptr long ptr ptr) +@ stdcall ObAssignSecurity(ptr ptr ptr ptr) +@ stdcall ObCheckCreateObjectAccess(ptr long ptr ptr long long ptr) +@ stdcall ObCheckObjectAccess(ptr ptr long long ptr) +@ stdcall ObCloseHandle(ptr long) +@ stdcall ObCreateObject(long ptr ptr long ptr long long long ptr) +@ stdcall ObCreateObjectType(ptr ptr ptr ptr) +;ObDeleteCapturedInsertInfo +@ stdcall ObDereferenceObject(ptr) +@ stdcall ObDereferenceObjectDeferDelete(ptr) +@ stdcall ObDereferenceSecurityDescriptor(ptr long) +@ stdcall ObFindHandleForObject(ptr ptr ptr ptr ptr) +@ stdcall ObGetObjectSecurity(ptr ptr ptr) +@ stdcall ObInsertObject(ptr ptr long long ptr ptr) +@ stdcall ObIsKernelHandle(ptr) +@ stdcall ObLogSecurityDescriptor(ptr ptr long) +@ stdcall ObMakeTemporaryObject(ptr) +@ stdcall ObOpenObjectByName(ptr ptr long ptr long ptr ptr) +@ stdcall ObOpenObjectByPointer(ptr long ptr long ptr long ptr) +@ stdcall ObQueryNameString(ptr ptr long ptr) +@ stdcall ObQueryObjectAuditingByHandle(ptr ptr) +@ stdcall ObReferenceObjectByHandle(ptr long ptr long ptr ptr) +@ stdcall ObReferenceObjectByName(ptr long ptr long ptr long ptr ptr) +@ stdcall ObReferenceObjectByPointer(ptr long ptr long) +@ stdcall ObReferenceSecurityDescriptor(ptr long) +@ stdcall ObReleaseObjectSecurity(ptr long) +;ObSetHandleAttributes@12 +@ stdcall ObSetSecurityDescriptorInfo(ptr ptr ptr ptr long ptr) +@ stdcall ObSetSecurityObjectByPointer(ptr long ptr) +@ fastcall ObfDereferenceObject(ptr) +@ fastcall ObfReferenceObject(ptr) +;PfxFindPrefix +;PfxInitialize +;PfxInsertPrefix +;PfxRemovePrefix +@ stdcall PoCallDriver(ptr ptr) +;PoCancelDeviceNotify +@ stdcall PoQueueShutdownWorkItem(ptr) +@ stdcall PoRegisterDeviceForIdleDetection(ptr long long long) +;PoRegisterDeviceNotify +@ stdcall PoRegisterSystemState(ptr long) +@ stdcall PoRequestPowerIrp(ptr long long ptr ptr ptr) +;PoRequestShutdownEvent +;PoSetHiberRange +@ stdcall PoSetPowerState(ptr long long) +@ stdcall PoSetSystemState(long) +;PoShutdownBugCheck +@ stdcall PoStartNextPowerIrp(ptr) +@ stdcall PoUnregisterSystemState(ptr) +@ stdcall ProbeForRead(ptr long long) +@ stdcall ProbeForWrite(ptr long long) +@ stdcall PsAssignImpersonationToken(ptr ptr) +@ stdcall PsChargePoolQuota(ptr long long) +@ stdcall PsChargeProcessNonPagedPoolQuota(ptr long) +@ stdcall PsChargeProcessPagedPoolQuota(ptr long) +@ stdcall PsChargeProcessPoolQuota(ptr long long) +@ stdcall PsCreateSystemProcess(ptr long ptr) +@ stdcall PsCreateSystemThread(ptr long ptr ptr ptr ptr ptr) +@ stdcall PsDereferenceImpersonationToken(ptr) PsDereferencePrimaryToken +@ stdcall PsDereferencePrimaryToken(ptr) +@ stdcall PsDisableImpersonation(ptr ptr) +@ stdcall PsEstablishWin32Callouts(ptr) +@ stdcall PsGetContextThread(ptr ptr long) +@ stdcall PsGetCurrentProcess() IoGetCurrentProcess +@ stdcall PsGetCurrentProcessId() +@ stdcall PsGetCurrentProcessSessionId() +@ stdcall PsGetCurrentProcessWin32Process() +@ stdcall PsGetCurrentThread() KeGetCurrentThread +@ stdcall PsGetCurrentThreadId() +@ stdcall PsGetCurrentThreadPreviousMode() +;PsGetCurrentThreadProcess +;PsGetCurrentThreadProcessId +@ stdcall PsGetCurrentThreadStackBase() +@ stdcall PsGetCurrentThreadStackLimit() +;PsGetCurrentThreadTeb +@ stdcall PsGetCurrentThreadWin32Thread() +;PsGetCurrentThreadWin32ThreadAndEnterCriticalRegion +@ stdcall PsGetJobLock(ptr) +@ stdcall PsGetJobSessionId(ptr) +@ stdcall PsGetJobUIRestrictionsClass(ptr) +@ stdcall PsGetProcessCreateTimeQuadPart(ptr) +@ stdcall PsGetProcessDebugPort(ptr) +@ stdcall PsGetProcessExitProcessCalled(ptr) +@ stdcall PsGetProcessExitStatus(ptr) +@ stdcall PsGetProcessExitTime() +@ stdcall PsGetProcessId(ptr) +@ stdcall PsGetProcessImageFileName(ptr) +@ stdcall PsGetProcessInheritedFromUniqueProcessId(ptr) +@ stdcall PsGetProcessJob(ptr) +@ stdcall PsGetProcessPeb(ptr) +@ stdcall PsGetProcessPriorityClass(ptr) +@ stdcall PsGetProcessSectionBaseAddress(ptr) +@ stdcall PsGetProcessSecurityPort(ptr) +@ stdcall PsGetProcessSessionId(ptr) +;PsGetProcessSessionIdEx +@ stdcall PsGetProcessWin32Process(ptr) +@ stdcall PsGetProcessWin32WindowStation(ptr) +@ stdcall PsGetThreadFreezeCount(ptr) +@ stdcall PsGetThreadHardErrorsAreDisabled(ptr) +@ stdcall PsGetThreadId(ptr) +@ stdcall PsGetThreadProcess(ptr) +@ stdcall PsGetThreadProcessId(ptr) +@ stdcall PsGetThreadSessionId(ptr) +@ stdcall PsGetThreadTeb(ptr) +@ stdcall PsGetThreadWin32Thread(ptr) +@ stdcall PsGetVersion(ptr ptr ptr ptr) +@ stdcall PsImpersonateClient(ptr ptr long long long) +@ extern PsInitialSystemProcess +@ stdcall PsIsProcessBeingDebugged(ptr) +@ stdcall PsIsSystemProcess(ptr) +@ stdcall PsIsSystemThread(ptr) +@ stdcall PsIsThreadImpersonating(ptr) +@ stdcall PsIsThreadTerminating(ptr) +@ extern PsJobType +@ stdcall PsLookupProcessByProcessId(ptr ptr) +@ stdcall PsLookupProcessThreadByCid(ptr ptr ptr) +@ stdcall PsLookupThreadByThreadId(ptr ptr) +@ extern PsProcessType _PsProcessType +@ stdcall PsReferenceImpersonationToken(ptr ptr ptr ptr) +@ stdcall PsReferencePrimaryToken(ptr) +@ stdcall PsRemoveCreateThreadNotifyRoutine(ptr) +@ stdcall PsRemoveLoadImageNotifyRoutine(ptr) +@ stdcall PsRestoreImpersonation(ptr ptr) +@ stdcall PsReturnPoolQuota(ptr long long) +@ stdcall PsReturnProcessNonPagedPoolQuota(ptr long) +@ stdcall PsReturnProcessPagedPoolQuota(ptr long) +@ stdcall PsRevertThreadToSelf(ptr) +@ stdcall PsRevertToSelf() +@ stdcall PsSetContextThread(ptr ptr long) +@ stdcall PsSetCreateProcessNotifyRoutine(ptr long) +@ stdcall PsSetCreateThreadNotifyRoutine(ptr) +@ stdcall PsSetJobUIRestrictionsClass(ptr long) +@ stdcall PsSetLegoNotifyRoutine(ptr) +@ stdcall PsSetLoadImageNotifyRoutine(ptr) +@ stdcall PsSetProcessPriorityByClass(ptr ptr) +@ stdcall PsSetProcessPriorityClass(ptr long) +@ stdcall PsSetProcessSecurityPort(ptr ptr) +@ stdcall PsSetProcessWin32Process(ptr ptr) +@ stdcall PsSetProcessWindowStation(ptr ptr) +@ stdcall PsSetThreadHardErrorsAreDisabled(ptr long) +@ stdcall PsSetThreadWin32Thread(ptr ptr) +@ stdcall PsTerminateSystemThread(long) +@ extern PsThreadType _PsThreadType +;PsWrapApcWow64Thread +#ifndef __x86_64__ +@ stdcall READ_REGISTER_BUFFER_UCHAR(ptr ptr long) +@ stdcall READ_REGISTER_BUFFER_ULONG(ptr ptr long) +@ stdcall READ_REGISTER_BUFFER_USHORT(ptr ptr long) +@ stdcall READ_REGISTER_UCHAR(ptr) +@ stdcall READ_REGISTER_ULONG(ptr) +@ stdcall READ_REGISTER_USHORT(ptr) +#endif +@ stdcall KeRosDumpStackFrames(ptr long) +@ stdcall RtlAbsoluteToSelfRelativeSD(ptr ptr ptr) +@ stdcall RtlAddAccessAllowedAce(ptr long long ptr) +@ stdcall RtlAddAccessAllowedAceEx(ptr long long long ptr) +@ stdcall RtlAddAce(ptr long long ptr long) +@ stdcall RtlAddAtomToAtomTable(ptr wstr ptr) +@ stdcall RtlAddRange(ptr long long long long long long ptr ptr) +@ stdcall RtlAllocateAndInitializeSid(ptr long long long long long long long long long ptr) +@ stdcall RtlAllocateHeap(ptr long long) +@ stdcall RtlAnsiCharToUnicodeChar(ptr) +@ stdcall RtlAnsiStringToUnicodeSize(ptr) RtlxAnsiStringToUnicodeSize +@ stdcall RtlAnsiStringToUnicodeString(ptr ptr long) +@ stdcall RtlAppendAsciizToString(ptr str) +@ stdcall RtlAppendStringToString(ptr ptr) +@ stdcall RtlAppendUnicodeStringToString(ptr ptr) +@ stdcall RtlAppendUnicodeToString(ptr wstr) +@ stdcall RtlAreAllAccessesGranted(long long) +@ stdcall RtlAreAnyAccessesGranted(long long) +@ stdcall RtlAreBitsClear(ptr long long) +@ stdcall RtlAreBitsSet(ptr long long) +@ stdcall RtlAssert(str str long str) +@ stdcall RtlCaptureContext(ptr) +@ stdcall RtlCaptureStackBackTrace(long long ptr ptr) +@ stdcall RtlCharToInteger(str long ptr) +@ stdcall RtlCheckRegistryKey(long wstr) +@ stdcall RtlClearAllBits(ptr) +@ stdcall RtlClearBit(ptr long) +@ stdcall RtlClearBits(ptr long long) +@ stdcall RtlCompareMemory(ptr ptr long) +@ stdcall RtlCompareMemoryUlong(ptr long long) +@ stdcall RtlCompareString(ptr ptr long) +@ stdcall RtlCompareUnicodeString(ptr ptr long) +@ stdcall RtlCompressBuffer(long ptr long ptr long long ptr ptr) +@ stdcall RtlCompressChunks(ptr long ptr long ptr long ptr) +@ stdcall RtlConvertLongToLargeInteger(long) +@ stdcall RtlConvertSidToUnicodeString(ptr ptr long) +@ stdcall RtlConvertUlongToLargeInteger(long) +@ stdcall RtlCopyLuid(ptr ptr) +@ stdcall RtlCopyRangeList(ptr ptr) +@ stdcall RtlCopySid(long ptr ptr) +@ stdcall RtlCopyString(ptr ptr) +@ stdcall RtlCopyUnicodeString(ptr ptr) +@ stdcall RtlCreateAcl(ptr long long) +@ stdcall RtlCreateAtomTable(long ptr) +@ stdcall RtlCreateHeap(long ptr long long ptr ptr) +@ stdcall RtlCreateRegistryKey(long wstr) +@ stdcall RtlCreateSecurityDescriptor(ptr long) +@ stdcall RtlCreateSystemVolumeInformationFolder(ptr) +@ stdcall RtlCreateUnicodeString(ptr wstr) +@ stdcall RtlCustomCPToUnicodeN(ptr wstr long ptr ptr long) +@ stdcall RtlDecompressBuffer(long ptr long ptr long ptr) +@ stdcall RtlDecompressChunks(ptr long ptr long ptr long ptr) +@ stdcall RtlDecompressFragment(long ptr long ptr long long ptr ptr) +@ stdcall RtlDelete(ptr) +@ stdcall RtlDeleteAce(ptr long) +@ stdcall RtlDeleteAtomFromAtomTable(ptr ptr) +@ stdcall RtlDeleteElementGenericTable(ptr ptr) +@ stdcall RtlDeleteElementGenericTableAvl(ptr ptr) +@ stdcall RtlDeleteNoSplay(ptr ptr) +@ stdcall RtlDeleteOwnersRanges(ptr ptr) +@ stdcall RtlDeleteRange(ptr long long long long ptr) +@ stdcall RtlDeleteRegistryValue(long wstr wstr) +@ stdcall RtlDescribeChunk(long ptr ptr ptr ptr) +@ stdcall RtlDestroyAtomTable(ptr) +@ stdcall RtlDestroyHeap(ptr) +@ stdcall RtlDowncaseUnicodeString(ptr ptr long) +@ stdcall RtlEmptyAtomTable(ptr long) +@ stdcall RtlEnlargedIntegerMultiply(long long) +@ stdcall RtlEnlargedUnsignedDivide(long long long ptr) +@ stdcall RtlEnlargedUnsignedMultiply(long long) +@ stdcall RtlEnumerateGenericTable(ptr long) +@ stdcall RtlEnumerateGenericTableAvl(ptr long) +@ stdcall RtlEnumerateGenericTableLikeADirectory(ptr ptr ptr long ptr ptr ptr) +@ stdcall RtlEnumerateGenericTableWithoutSplaying(ptr ptr) +@ stdcall RtlEnumerateGenericTableWithoutSplayingAvl(ptr ptr) +@ stdcall RtlEqualLuid(ptr ptr) +@ stdcall RtlEqualSid(ptr ptr) +@ stdcall RtlEqualString(ptr ptr long) +@ stdcall RtlEqualUnicodeString(ptr ptr long) +@ stdcall RtlExtendedIntegerMultiply(long long long) +@ stdcall RtlExtendedLargeIntegerDivide(long long long ptr) +@ stdcall RtlExtendedMagicDivide(long long long long long) +@ stdcall RtlFillMemory(ptr long long) +@ stdcall RtlFillMemoryUlong(ptr long long) +@ stdcall RtlFindClearBits(ptr long long) +@ stdcall RtlFindClearBitsAndSet(ptr long long) +@ stdcall RtlFindClearRuns(ptr ptr long long) +@ stdcall RtlFindFirstRunClear(ptr ptr) +@ stdcall RtlFindLastBackwardRunClear(ptr long ptr) +@ stdcall RtlFindLeastSignificantBit(long long) +@ stdcall RtlFindLongestRunClear(ptr ptr) +@ stdcall RtlFindMessage(ptr long long long ptr) +@ stdcall RtlFindMostSignificantBit(long long) +@ stdcall RtlFindNextForwardRunClear(ptr long ptr) +@ stdcall RtlFindRange(ptr long long long long long long long long ptr ptr ptr) +@ stdcall RtlFindSetBits(ptr long long) +@ stdcall RtlFindSetBitsAndClear(ptr long long) +@ stdcall RtlFindUnicodePrefix(ptr ptr long) +@ stdcall RtlFormatCurrentUserKeyPath(ptr) +@ stdcall RtlFreeAnsiString(ptr) +@ stdcall RtlFreeHeap(ptr long ptr) +@ stdcall RtlFreeOemString(ptr) +@ stdcall RtlFreeRangeList(ptr) +@ stdcall RtlFreeUnicodeString(ptr) +@ stdcall RtlGUIDFromString(ptr ptr) +@ stdcall RtlGenerate8dot3Name(ptr ptr long ptr) +@ stdcall RtlGetAce(ptr long ptr) +@ stdcall RtlGetCallersAddress(ptr ptr) +@ stdcall RtlGetCompressionWorkSpaceSize(long ptr ptr) +@ stdcall RtlGetDaclSecurityDescriptor(ptr ptr ptr ptr) +@ stdcall RtlGetDefaultCodePage(ptr ptr) +@ stdcall RtlGetElementGenericTable(ptr long) +@ stdcall RtlGetElementGenericTableAvl(ptr long) +@ stdcall RtlGetFirstRange(ptr ptr ptr) +@ stdcall RtlGetGroupSecurityDescriptor(ptr ptr ptr) +@ stdcall RtlGetNextRange(ptr ptr long) +@ stdcall RtlGetNtGlobalFlags() +@ stdcall RtlGetOwnerSecurityDescriptor(ptr ptr ptr) +@ stdcall RtlGetSaclSecurityDescriptor(ptr ptr ptr ptr) +@ stdcall RtlGetSetBootStatusData(ptr long long ptr long long) +@ stdcall RtlGetVersion(ptr) +@ stdcall RtlHashUnicodeString(ptr long long ptr) +@ stdcall RtlImageDirectoryEntryToData(ptr long long ptr) +@ stdcall RtlImageNtHeader(ptr) +@ stdcall RtlInitAnsiString(ptr str) +@ stdcall RtlInitAnsiStringEx(ptr str) +@ stdcall RtlInitCodePageTable(ptr ptr) +@ stdcall RtlInitString(ptr str) +@ stdcall RtlInitUnicodeString(ptr wstr) +@ stdcall RtlInitUnicodeStringEx(ptr wstr) +@ stdcall RtlInitializeBitMap(ptr ptr long) +@ stdcall RtlInitializeGenericTable(ptr ptr ptr ptr ptr) +@ stdcall RtlInitializeGenericTableAvl(ptr ptr ptr ptr ptr) +@ stdcall RtlInitializeRangeList(ptr) +@ stdcall RtlInitializeSid(ptr ptr long) +@ stdcall RtlInitializeUnicodePrefix(ptr) +@ stdcall RtlInsertElementGenericTable(ptr ptr long ptr) +@ stdcall RtlInsertElementGenericTableAvl(ptr ptr long ptr) +@ stdcall RtlInsertElementGenericTableFull(ptr ptr long ptr ptr long) +@ stdcall RtlInsertElementGenericTableFullAvl(ptr ptr long ptr ptr ptr) +@ stdcall RtlInsertUnicodePrefix(ptr ptr ptr) +@ stdcall RtlInt64ToUnicodeString(long long long ptr) +@ stdcall RtlIntegerToChar(long long long ptr) +@ stdcall RtlIntegerToUnicode(long long long ptr) +@ stdcall RtlIntegerToUnicodeString(long long ptr) +@ stdcall RtlInvertRangeList(ptr ptr) +@ stdcall RtlIpv4AddressToStringA(ptr ptr) +@ stdcall RtlIpv4AddressToStringExA(ptr long ptr ptr) +@ stdcall RtlIpv4AddressToStringExW(ptr long ptr ptr) +@ stdcall RtlIpv4AddressToStringW(ptr ptr) +@ stdcall RtlIpv4StringToAddressA(str long ptr ptr) +@ stdcall RtlIpv4StringToAddressExA(str long ptr ptr) +@ stdcall RtlIpv4StringToAddressExW(wstr long ptr ptr) +@ stdcall RtlIpv4StringToAddressW(wstr long ptr ptr) +@ stdcall RtlIpv6AddressToStringA(ptr ptr) +@ stdcall RtlIpv6AddressToStringExA(ptr long long ptr ptr) +@ stdcall RtlIpv6AddressToStringExW(ptr long long ptr ptr) +@ stdcall RtlIpv6AddressToStringW(ptr ptr) +@ stdcall RtlIpv6StringToAddressA(str ptr ptr) +@ stdcall RtlIpv6StringToAddressExA(str ptr ptr ptr) +@ stdcall RtlIpv6StringToAddressExW(wstr ptr ptr ptr) +@ stdcall RtlIpv6StringToAddressW(wstr ptr ptr) +@ stdcall RtlIsGenericTableEmpty(ptr) +@ stdcall RtlIsGenericTableEmptyAvl(ptr) +@ stdcall RtlIsNameLegalDOS8Dot3(ptr ptr ptr) +@ stdcall RtlIsRangeAvailable(ptr long long long long long long ptr ptr ptr) +@ stdcall RtlIsValidOemCharacter(ptr) +@ stdcall RtlLargeIntegerAdd(long long long long) +@ stdcall RtlLargeIntegerArithmeticShift(long long long) +@ stdcall RtlLargeIntegerDivide(long long long long ptr) +@ stdcall RtlLargeIntegerNegate(long long) +@ stdcall RtlLargeIntegerShiftLeft(long long long) +@ stdcall RtlLargeIntegerShiftRight(long long long) +@ stdcall RtlLargeIntegerSubtract(long long long long) +@ stdcall RtlLengthRequiredSid(long) +@ stdcall RtlLengthSecurityDescriptor(ptr) +@ stdcall RtlLengthSid(ptr) +@ stdcall RtlLockBootStatusData(ptr) +@ stdcall RtlLookupAtomInAtomTable(ptr wstr ptr) +@ stdcall RtlLookupElementGenericTable(ptr ptr) +@ stdcall RtlLookupElementGenericTableAvl(ptr ptr) +@ stdcall RtlLookupElementGenericTableFull(ptr ptr ptr ptr) +@ stdcall RtlLookupElementGenericTableFullAvl(ptr ptr ptr ptr) +@ stdcall RtlMapGenericMask(ptr ptr) +@ stdcall RtlMapSecurityErrorToNtStatus(long) +@ stdcall RtlMergeRangeLists(ptr ptr ptr long) +@ stdcall RtlMoveMemory(ptr ptr long) +@ stdcall RtlMultiByteToUnicodeN(ptr long ptr str long) +@ stdcall RtlMultiByteToUnicodeSize(ptr str long) +@ stdcall RtlNextUnicodePrefix(ptr long) +@ stdcall RtlNtStatusToDosError(long) +@ stdcall RtlNtStatusToDosErrorNoTeb(long) +@ stdcall RtlNumberGenericTableElements(ptr) +@ stdcall RtlNumberGenericTableElementsAvl(ptr) +@ stdcall RtlNumberOfClearBits(ptr) +@ stdcall RtlNumberOfSetBits(ptr) +@ stdcall RtlOemStringToCountedUnicodeString(ptr ptr long) +@ stdcall RtlOemStringToUnicodeSize(ptr) RtlxOemStringToUnicodeSize +@ stdcall RtlOemStringToUnicodeString(ptr ptr long) +@ stdcall RtlOemToUnicodeN(wstr long ptr ptr long) +@ stdcall RtlPinAtomInAtomTable(ptr ptr) +@ fastcall RtlPrefetchMemoryNonTemporal(ptr long) +@ stdcall RtlPrefixString(ptr ptr long) +@ stdcall RtlPrefixUnicodeString(ptr ptr long) +@ stdcall RtlQueryAtomInAtomTable(ptr ptr ptr ptr ptr ptr) +@ stdcall RtlQueryRegistryValues(long wstr ptr ptr ptr) +@ stdcall RtlQueryTimeZoneInformation(ptr) +@ stdcall RtlRaiseException(ptr) +@ stdcall RtlRandom(ptr) +@ stdcall RtlRandomEx(ptr) +@ stdcall RtlRealPredecessor(ptr) +@ stdcall RtlRealSuccessor(ptr) +@ stdcall RtlRemoveUnicodePrefix(ptr ptr) +@ stdcall RtlReserveChunk(long ptr ptr ptr long) +@ stdcall RtlSecondsSince1970ToTime(long ptr) +@ stdcall RtlSecondsSince1980ToTime(long ptr) +@ stdcall RtlSelfRelativeToAbsoluteSD(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) +@ stdcall RtlSelfRelativeToAbsoluteSD2(ptr long) +@ stdcall RtlSetAllBits(ptr) +@ stdcall RtlSetBit(ptr long) +@ stdcall RtlSetBits(ptr long long) +@ stdcall RtlSetDaclSecurityDescriptor(ptr long ptr long) +@ stdcall RtlSetGroupSecurityDescriptor(ptr ptr long) +@ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long) +@ stdcall RtlSetSaclSecurityDescriptor(ptr long ptr long) +@ stdcall RtlSetTimeZoneInformation(ptr) +@ stdcall RtlSizeHeap(ptr long ptr) +@ stdcall RtlSplay(ptr) +@ stdcall RtlStringFromGUID(ptr ptr) +@ stdcall RtlSubAuthorityCountSid(ptr) +@ stdcall RtlSubAuthoritySid(ptr long) +@ stdcall RtlSubtreePredecessor(ptr) +@ stdcall RtlSubtreeSuccessor(ptr) +@ stdcall RtlTestBit(ptr long) +@ stdcall RtlTimeFieldsToTime(ptr ptr) +@ stdcall RtlTimeToElapsedTimeFields(ptr ptr) +@ stdcall RtlTimeToSecondsSince1970(ptr ptr) +@ stdcall RtlTimeToSecondsSince1980(ptr ptr) +@ stdcall RtlTimeToTimeFields(ptr ptr) +;RtlTraceDatabaseAdd +;RtlTraceDatabaseCreate +;RtlTraceDatabaseDestroy +;RtlTraceDatabaseEnumerate +;RtlTraceDatabaseFind +;RtlTraceDatabaseLock +;RtlTraceDatabaseUnlock +;RtlTraceDatabaseValidate +#ifndef __x86_64__ +@ fastcall RtlUlongByteSwap(long) +@ fastcall RtlUlonglongByteSwap(long long) +#endif +@ stdcall RtlUnicodeStringToAnsiSize(ptr) RtlxUnicodeStringToAnsiSize +@ stdcall RtlUnicodeStringToAnsiString(ptr ptr long) +@ stdcall RtlUnicodeStringToCountedOemString(ptr ptr long) +@ stdcall RtlUnicodeStringToInteger(ptr long ptr) +@ stdcall RtlUnicodeStringToOemSize(ptr) RtlxUnicodeStringToOemSize +@ stdcall RtlUnicodeStringToOemString(ptr ptr long) +@ stdcall RtlUnicodeToCustomCPN(ptr ptr long ptr wstr long) +@ stdcall RtlUnicodeToMultiByteN(ptr long ptr wstr long) +@ stdcall RtlUnicodeToMultiByteSize(ptr wstr long) +@ stdcall RtlUnicodeToOemN(ptr long ptr wstr long) +@ stdcall RtlUnlockBootStatusData(ptr) +@ stdcall RtlUnwind(ptr ptr ptr ptr) +@ stdcall RtlUpcaseUnicodeChar(long) +@ stdcall RtlUpcaseUnicodeString(ptr ptr long) +@ stdcall RtlUpcaseUnicodeStringToAnsiString(ptr ptr long) +@ stdcall RtlUpcaseUnicodeStringToCountedOemString(ptr ptr long) +@ stdcall RtlUpcaseUnicodeStringToOemString(ptr ptr long) +@ stdcall RtlUpcaseUnicodeToCustomCPN(ptr ptr long ptr wstr long) +@ stdcall RtlUpcaseUnicodeToMultiByteN(ptr long ptr wstr long) +@ stdcall RtlUpcaseUnicodeToOemN(ptr long ptr wstr long) +@ stdcall RtlUpperChar(long) +@ stdcall RtlUpperString(ptr ptr) +#ifndef __x86_64__ +@ fastcall RtlUshortByteSwap(long) +#endif +@ stdcall RtlValidRelativeSecurityDescriptor(ptr long long) +@ stdcall RtlValidSecurityDescriptor(ptr) +@ stdcall RtlValidSid(ptr) +@ stdcall RtlVerifyVersionInfo(ptr long long long) +@ stdcall RtlVolumeDeviceToDosName(ptr ptr) +@ stdcall RtlWalkFrameChain(ptr long long) +@ stdcall RtlWriteRegistryValue(long wstr wstr long ptr long) +@ stdcall RtlZeroHeap(ptr long) +@ stdcall RtlZeroMemory(ptr long) +@ stdcall RtlxAnsiStringToUnicodeSize(ptr) +@ stdcall RtlxOemStringToUnicodeSize(ptr) +@ stdcall RtlxUnicodeStringToAnsiSize(ptr) +@ stdcall RtlxUnicodeStringToOemSize(ptr) +@ stdcall SeAccessCheck(ptr ptr ptr long long ptr ptr long ptr ptr) +@ stdcall SeAppendPrivileges(ptr ptr) +@ stdcall SeAssignSecurity(ptr ptr ptr long ptr ptr ptr) +@ stdcall SeAssignSecurityEx(ptr ptr ptr ptr long long ptr ptr ptr) +@ stdcall SeAuditHardLinkCreation(ptr ptr long) +@ stdcall SeAuditingFileEvents(long ptr) +@ stdcall SeAuditingFileEventsWithContext(long ptr ptr) +@ stdcall SeAuditingFileOrGlobalEvents(long ptr ptr) +@ stdcall SeAuditingHardLinkEvents(long ptr) +@ stdcall SeAuditingHardLinkEventsWithContext(long ptr ptr) +@ stdcall SeCaptureSecurityDescriptor(ptr long long long ptr) +@ stdcall SeCaptureSubjectContext(ptr) +@ stdcall SeCloseObjectAuditAlarm(ptr ptr long) +@ stdcall SeCreateAccessState(ptr ptr long ptr) +@ stdcall SeCreateClientSecurity(ptr ptr long ptr) +@ stdcall SeCreateClientSecurityFromSubjectContext(ptr ptr long ptr) +@ stdcall SeDeassignSecurity(ptr) +@ stdcall SeDeleteAccessState(ptr) +@ stdcall SeDeleteObjectAuditAlarm(ptr ptr) +@ extern SeExports +@ stdcall SeFilterToken(ptr long ptr ptr ptr ptr) +@ stdcall SeFreePrivileges(ptr) +@ stdcall SeImpersonateClient(ptr ptr) +@ stdcall SeImpersonateClientEx(ptr ptr) +@ stdcall SeLockSubjectContext(ptr) +@ stdcall SeMarkLogonSessionForTerminationNotification(ptr) +@ stdcall SeOpenObjectAuditAlarm(ptr ptr ptr ptr ptr long long long ptr) +@ stdcall SeOpenObjectForDeleteAuditAlarm(ptr ptr ptr ptr ptr long long long ptr) +@ stdcall SePrivilegeCheck(ptr ptr long) +@ stdcall SePrivilegeObjectAuditAlarm(ptr ptr long ptr long long) +@ extern SePublicDefaultDacl +@ stdcall SeQueryAuthenticationIdToken(ptr ptr) +@ stdcall SeQueryInformationToken(ptr long ptr) +@ stdcall SeQuerySecurityDescriptorInfo(ptr ptr ptr ptr) +@ stdcall SeQuerySessionIdToken(ptr ptr) +@ stdcall SeRegisterLogonSessionTerminatedRoutine(ptr) +@ stdcall SeReleaseSecurityDescriptor(ptr long long) +@ stdcall SeReleaseSubjectContext(ptr) +@ stdcall SeSetAccessStateGenericMapping(ptr ptr) +;SeSetAuditParameter +@ stdcall SeSetSecurityDescriptorInfo(ptr ptr ptr ptr long ptr) +@ stdcall SeSetSecurityDescriptorInfoEx(ptr ptr ptr ptr long long ptr) +@ stdcall SeSinglePrivilegeCheck(long long long) +@ extern SeSystemDefaultDacl +@ stdcall SeTokenImpersonationLevel(ptr) +@ stdcall SeTokenIsAdmin(ptr) +@ stdcall SeTokenIsRestricted(ptr) +@ stdcall SeTokenIsWriteRestricted(ptr) +@ stdcall SeTokenType(ptr) +@ stdcall SeUnlockSubjectContext(ptr) +@ stdcall SeUnregisterLogonSessionTerminatedRoutine(ptr) +@ stdcall SeValidSecurityDescriptor(long ptr) +@ stdcall VerSetConditionMask(long long long long) +;VfFailDeviceNode +;VfFailDriver +;VfFailSystemBIOS +;VfIsVerificationEnabled +#ifndef __x86_64__ +@ stdcall WRITE_REGISTER_BUFFER_UCHAR(ptr ptr long) +@ stdcall WRITE_REGISTER_BUFFER_ULONG(ptr ptr long) +@ stdcall WRITE_REGISTER_BUFFER_USHORT(ptr ptr long) +@ stdcall WRITE_REGISTER_UCHAR(ptr long) +@ stdcall WRITE_REGISTER_ULONG(ptr long) +@ stdcall WRITE_REGISTER_USHORT(ptr long) +#endif +;WmiFlushTrace +;WmiGetClock +;WmiQueryTrace +@ stdcall WmiQueryTraceInformation(long ptr long ptr ptr) +;WmiStartTrace +;WmiStopTrace +;WmiTraceFastEvent +@ cdecl WmiTraceMessage() +@ stdcall WmiTraceMessageVa(ptr long ptr long long) +;WmiUpdateTrace +;XIPDispatch +@ stdcall ZwAccessCheckAndAuditAlarm(ptr ptr ptr ptr ptr long ptr long ptr ptr ptr) +@ stdcall ZwAddBootEntry(ptr long) +@ stdcall ZwAddDriverEntry(ptr long) +@ stdcall ZwAdjustPrivilegesToken(ptr long ptr long ptr ptr) +@ stdcall ZwAlertThread(ptr) +@ stdcall ZwAllocateVirtualMemory(ptr ptr long ptr long long) +@ stdcall ZwAssignProcessToJobObject(ptr ptr) +@ stdcall ZwCancelIoFile(ptr ptr) +@ stdcall ZwCancelTimer(ptr ptr) +@ stdcall ZwClearEvent(ptr) +@ stdcall ZwClose(ptr) +@ stdcall ZwCloseObjectAuditAlarm(ptr ptr long) +@ stdcall ZwConnectPort(ptr ptr ptr ptr ptr ptr ptr ptr) +@ stdcall ZwCreateDirectoryObject(ptr long ptr) +@ stdcall ZwCreateEvent(ptr long ptr long long) +@ stdcall ZwCreateFile(ptr long ptr ptr ptr long long long long ptr long) +@ stdcall ZwCreateJobObject(ptr long ptr) +@ stdcall ZwCreateKey(ptr long ptr long ptr long ptr) +@ stdcall ZwCreateSection(ptr long ptr ptr long long ptr) +@ stdcall ZwCreateSymbolicLinkObject(ptr long ptr ptr) +@ stdcall ZwCreateTimer(ptr long ptr long) +@ stdcall ZwDeleteBootEntry(long) +@ stdcall ZwDeleteDriverEntry(long) +@ stdcall ZwDeleteFile(ptr) +@ stdcall ZwDeleteKey(ptr) +@ stdcall ZwDeleteValueKey(ptr ptr) +@ stdcall ZwDeviceIoControlFile(ptr ptr ptr ptr ptr long ptr long ptr long) +@ stdcall ZwDisplayString(ptr) +@ stdcall ZwDuplicateObject(ptr ptr ptr ptr long long long) +@ stdcall ZwDuplicateToken(ptr long ptr long long ptr) +@ stdcall ZwEnumerateBootEntries(ptr ptr) +@ stdcall ZwEnumerateDriverEntries(ptr ptr) +@ stdcall ZwEnumerateKey(ptr long long ptr long ptr) +@ stdcall ZwEnumerateValueKey(ptr long long ptr long ptr) +@ stdcall ZwFlushInstructionCache(ptr ptr long) +@ stdcall ZwFlushKey(ptr) +@ stdcall ZwFlushVirtualMemory(ptr ptr ptr ptr) +@ stdcall ZwFreeVirtualMemory(ptr ptr ptr long) +@ stdcall ZwFsControlFile(ptr ptr ptr ptr ptr long ptr long ptr long) +@ stdcall ZwInitiatePowerAction(long long long long) +@ stdcall ZwIsProcessInJob(ptr ptr) +@ stdcall ZwLoadDriver(ptr) +@ stdcall ZwLoadKey(ptr ptr) +@ stdcall ZwMakeTemporaryObject(ptr) +@ stdcall ZwMapViewOfSection(ptr ptr ptr long long ptr ptr long long long) +@ stdcall ZwModifyBootEntry(ptr) +@ stdcall ZwModifyDriverEntry(ptr) +@ stdcall ZwNotifyChangeKey(ptr ptr ptr ptr ptr long long ptr long long) +@ stdcall ZwOpenDirectoryObject(ptr long ptr) +@ stdcall ZwOpenEvent(ptr long ptr) +@ stdcall ZwOpenFile(ptr long ptr ptr long long) +@ stdcall ZwOpenJobObject(ptr long ptr) +@ stdcall ZwOpenKey(ptr long ptr) +@ stdcall ZwOpenProcess(ptr long ptr ptr) +@ stdcall ZwOpenProcessToken(ptr long ptr) +@ stdcall ZwOpenProcessTokenEx(ptr long long ptr) +@ stdcall ZwOpenSection(ptr long ptr) +@ stdcall ZwOpenSymbolicLinkObject(ptr long ptr) +@ stdcall ZwOpenThread(ptr long ptr ptr) +@ stdcall ZwOpenThreadToken(ptr long long ptr) +@ stdcall ZwOpenThreadTokenEx(ptr long long long ptr) +@ stdcall ZwOpenTimer(ptr long ptr) +@ stdcall ZwPowerInformation(long ptr long ptr long) +@ stdcall ZwPulseEvent(ptr ptr) +@ stdcall ZwQueryBootEntryOrder(ptr ptr) +@ stdcall ZwQueryBootOptions(ptr ptr) +@ stdcall ZwQueryDefaultLocale(long ptr) +@ stdcall ZwQueryDefaultUILanguage(ptr) +@ stdcall ZwQueryDirectoryFile(ptr ptr ptr ptr ptr ptr long long long ptr long) +@ stdcall ZwQueryDirectoryObject(ptr ptr long long long ptr ptr) +@ stdcall ZwQueryDriverEntryOrder(ptr ptr) +@ stdcall ZwQueryEaFile(ptr ptr ptr long long ptr long ptr long) +@ stdcall ZwQueryFullAttributesFile(ptr ptr) +@ stdcall ZwQueryInformationAtom(ptr long ptr long ptr) +@ stdcall ZwQueryInformationFile(ptr ptr ptr long long) +@ stdcall ZwQueryInformationJobObject(ptr long ptr long ptr) +@ stdcall ZwQueryInformationProcess(ptr long ptr long ptr) +@ stdcall ZwQueryInformationThread(ptr long ptr long ptr) +@ stdcall ZwQueryInformationToken(ptr long long long ptr) +@ stdcall ZwQueryInstallUILanguage(ptr) +@ stdcall ZwQueryKey(ptr long ptr long ptr) +@ stdcall ZwQueryObject(ptr long ptr long ptr) +@ stdcall ZwQuerySection(ptr long ptr long ptr) +@ stdcall ZwQuerySecurityObject(ptr long ptr long ptr) +@ stdcall ZwQuerySymbolicLinkObject(ptr ptr ptr) +@ stdcall ZwQuerySystemInformation(long ptr long ptr) +@ stdcall ZwQueryValueKey(ptr ptr long ptr long ptr) +@ stdcall ZwQueryVolumeInformationFile(ptr ptr ptr long long) +@ stdcall ZwReadFile(ptr ptr ptr ptr ptr ptr long ptr ptr) +@ stdcall ZwReplaceKey(ptr ptr ptr) +@ stdcall ZwRequestWaitReplyPort(ptr ptr ptr) +@ stdcall ZwResetEvent(ptr ptr) +@ stdcall ZwRestoreKey(ptr ptr long) +@ stdcall ZwSaveKey(ptr ptr) +@ stdcall ZwSaveKeyEx(ptr ptr long) +@ stdcall ZwSecureConnectPort(ptr ptr ptr ptr ptr ptr ptr ptr ptr) +@ stdcall ZwSetBootEntryOrder(ptr ptr) +@ stdcall ZwSetBootOptions(ptr long) +@ stdcall ZwSetDefaultLocale(long long) +@ stdcall ZwSetDefaultUILanguage(long) +@ stdcall ZwSetDriverEntryOrder(ptr ptr) +@ stdcall ZwSetEaFile(ptr ptr ptr long) +@ stdcall ZwSetEvent(ptr ptr) +@ stdcall ZwSetInformationFile(ptr ptr ptr long long) +@ stdcall ZwSetInformationJobObject(ptr long ptr long) +@ stdcall ZwSetInformationObject(ptr long ptr long) +@ stdcall ZwSetInformationProcess(ptr long ptr long) +@ stdcall ZwSetInformationThread(ptr long ptr long) +@ stdcall ZwSetSecurityObject(ptr long ptr) +@ stdcall ZwSetSystemInformation(long ptr long) +@ stdcall ZwSetSystemTime(ptr ptr) +@ stdcall ZwSetTimer(ptr ptr ptr ptr long long ptr) +@ stdcall ZwSetValueKey(ptr ptr long long ptr long) +@ stdcall ZwSetVolumeInformationFile(ptr ptr ptr long long) +@ stdcall ZwTerminateJobObject(ptr long) +@ stdcall ZwTerminateProcess(ptr long) +@ stdcall ZwTranslateFilePath(ptr long ptr long) +@ stdcall ZwUnloadDriver(ptr) +@ stdcall ZwUnloadKey(ptr) +@ stdcall ZwUnmapViewOfSection(ptr ptr) +@ stdcall ZwWaitForMultipleObjects(long ptr long long ptr) +@ stdcall ZwWaitForSingleObject(ptr long ptr) +@ stdcall ZwWriteFile(ptr ptr ptr ptr ptr ptr long ptr ptr) +@ stdcall ZwYieldExecution() +;_CIcos +;_CIsin +;_CIsqrt +#ifndef __x86_64 +@ cdecl _abnormal_termination() +#endif +#ifdef _M_IX86 +@ cdecl _alldiv() +@ cdecl _alldvrm() +@ cdecl _allmul() +@ cdecl _alloca_probe() +@ cdecl _allrem() +@ cdecl _allshl() +@ cdecl _allshr() +@ cdecl _aulldiv() +@ cdecl _aulldvrm() +@ cdecl _aullrem() +@ cdecl _aullshr() +#endif +#ifndef __x86_64 +@ cdecl _except_handler2() +@ cdecl _except_handler3() +@ cdecl _global_unwind2() +#endif +@ cdecl _itoa() +@ cdecl _itow() +#ifndef __x86_64 +@ cdecl _local_unwind2() +#endif +@ cdecl _purecall() +@ cdecl _snprintf() +@ cdecl _snwprintf() +@ cdecl _stricmp() +@ cdecl _strlwr() +@ cdecl _strnicmp() +@ cdecl _strnset() +@ cdecl _strrev() +@ cdecl _strset() +@ cdecl _strupr() +@ cdecl _vsnprintf() +@ cdecl _vsnwprintf() +@ cdecl _wcsicmp() +@ cdecl _wcslwr() +@ cdecl _wcsnicmp() +@ cdecl _wcsnset() +@ cdecl _wcsrev() +@ cdecl _wcsupr() +@ cdecl atoi() +@ cdecl atol() +@ cdecl isdigit() +@ cdecl islower() +@ cdecl isprint() +@ cdecl isspace() +@ cdecl isupper() +@ cdecl isxdigit() +@ cdecl mbstowcs() +@ cdecl mbtowc() +@ cdecl memchr() +@ cdecl memcpy() +@ cdecl memmove() +@ cdecl memset() +@ cdecl qsort() +@ cdecl rand() +@ cdecl sprintf() +@ cdecl srand() +@ cdecl strcat() +@ cdecl strchr() +@ cdecl strcmp() +@ cdecl strcpy() +@ cdecl strlen() +@ cdecl strncat() +@ cdecl strncmp() +@ cdecl strncpy() +@ cdecl strrchr() +@ cdecl strspn() +@ cdecl strstr() +@ cdecl swprintf() +@ cdecl tolower() +@ cdecl toupper() +@ cdecl towlower() +@ cdecl towupper() +@ stdcall vDbgPrintEx(long long str ptr) +@ stdcall vDbgPrintExWithPrefix(str long long str ptr) +@ cdecl vsprintf() +@ cdecl wcscat() +@ cdecl wcschr() +@ cdecl wcscmp() +@ cdecl wcscpy() +@ cdecl wcscspn() +@ cdecl wcslen() +@ cdecl wcsncat() +@ cdecl wcsncmp() +@ cdecl wcsncpy() +@ cdecl wcsrchr() +@ cdecl wcsspn() +@ cdecl wcsstr() +@ cdecl wcstombs() +@ cdecl wctomb() diff --git a/reactos/subsystems/win32/win32k/objects/dc.c b/reactos/subsystems/win32/win32k/objects/dc.c index f0cd7c1fa66..81096bd59a3 100644 --- a/reactos/subsystems/win32/win32k/objects/dc.c +++ b/reactos/subsystems/win32/win32k/objects/dc.c @@ -2167,6 +2167,7 @@ NtGdiSelectBrush( if (pBrush == NULL) { SetLastWin32Error(ERROR_INVALID_HANDLE); + DC_UnlockDc(pDC); return NULL; } @@ -2174,6 +2175,7 @@ NtGdiSelectBrush( BRUSHOBJ_UnlockBrush(pBrush); if(bFailed) { + DC_UnlockDc(pDC); return NULL; } diff --git a/reactos/subsystems/win32/win32k/objects/font.c b/reactos/subsystems/win32/win32k/objects/font.c index dd31a49f10a..1a838e8a51f 100644 --- a/reactos/subsystems/win32/win32k/objects/font.c +++ b/reactos/subsystems/win32/win32k/objects/font.c @@ -1,2 +1,151 @@ -/* EMPTY FOR NOW */ -/* Hope I didn't delete existing defs!! Check CVS version of this file.. */ +/* + * PROJECT: ReactOS win32 kernel mode subsystem + * LICENSE: GPL - See COPYING in the top level directory + * FILE: subsystems/win32/win32k/objects/font.c + * PURPOSE: Font + * PROGRAMMER: + */ + +/** Includes ******************************************************************/ + +#include + +#define NDEBUG +#include + +// +// FIXME PLEASE!!!! +// Why are these here? Well there is a problem with drivers/directx. +// 1st: It does not belong there. +// 2nd: Due to being placed outside Win32k build environment, it creates +// compiling issues. +// Until svn mv drivers/directx subsystem/win32/win32k/drivers/directx, +// it will not get fixed. +// +ULONG +FASTCALL +ftGdiGetGlyphOutline( + IN PDC pdc, + IN WCHAR wch, + IN UINT iFormat, + OUT LPGLYPHMETRICS pgm, + IN ULONG cjBuf, + OUT OPTIONAL PVOID UnsafeBuf, + IN LPMAT2 pmat2, + IN BOOL bIgnoreRotation); + +INT +FASTCALL +IntGetOutlineTextMetrics(PFONTGDI FontGDI, UINT Size, OUTLINETEXTMETRICW *Otm); + +/** Functions ******************************************************************/ + +ULONG +APIENTRY +NtGdiGetGlyphOutline( + IN HDC hdc, + IN WCHAR wch, + IN UINT iFormat, + OUT LPGLYPHMETRICS pgm, + IN ULONG cjBuf, + OUT OPTIONAL PVOID UnsafeBuf, + IN LPMAT2 pmat2, + IN BOOL bIgnoreRotation) +{ + ULONG Ret; + PDC dc; + dc = DC_LockDc(hdc); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return GDI_ERROR; + } + Ret = ftGdiGetGlyphOutline( dc, + wch, + iFormat, + pgm, + cjBuf, + UnsafeBuf, + pmat2, + bIgnoreRotation); + DC_UnlockDc(dc); + return Ret; +} + +DWORD +STDCALL +NtGdiGetKerningPairs(HDC hDC, + ULONG NumPairs, + LPKERNINGPAIR krnpair) +{ + UNIMPLEMENTED; + return 0; +} + +/* + From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page + 472, this is NtGdiGetOutlineTextMetricsInternalW. + */ +ULONG +STDCALL +NtGdiGetOutlineTextMetricsInternalW (HDC hDC, + ULONG Data, + OUTLINETEXTMETRICW *otm, + TMDIFF *Tmd) +{ + PDC dc; + PDC_ATTR Dc_Attr; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + HFONT hFont = 0; + ULONG Size; + OUTLINETEXTMETRICW *potm; + NTSTATUS Status; + + dc = DC_LockDc(hDC); + if (dc == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + hFont = Dc_Attr->hlfntNew; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc(dc); + if (TextObj == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + FontGDI = ObjToGDI(TextObj->Font, FONT); + TEXTOBJ_UnlockText(TextObj); + Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); + if (!otm) return Size; + if (Size > Data) + { + SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); + if (NULL == potm) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + IntGetOutlineTextMetrics(FontGDI, Size, potm); + if (otm) + { + Status = MmCopyToCaller(otm, potm, Size); + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + ExFreePool(potm); + return 0; + } + } + ExFreePool(potm); + return Size; +} + +/* EOF */ diff --git a/reactos/subsystems/win32/win32k/objects/freetype.c b/reactos/subsystems/win32/win32k/objects/freetype.c new file mode 100644 index 00000000000..f3861691013 --- /dev/null +++ b/reactos/subsystems/win32/win32k/objects/freetype.c @@ -0,0 +1,4190 @@ +/* + * PROJECT: ReactOS win32 kernel mode subsystem + * LICENSE: GPL - See COPYING in the top level directory + * FILE: subsystems/win32/win32k/objects/freetype.c + * PURPOSE: Freetype library support + * PROGRAMMER: + */ + +/** Includes ******************************************************************/ + +#include + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +FT_Library library; + +typedef struct _FONT_ENTRY { + LIST_ENTRY ListEntry; + FONTGDI *Font; + UNICODE_STRING FaceName; + BYTE NotEnum; +} FONT_ENTRY, *PFONT_ENTRY; + +/* The FreeType library is not thread safe, so we have + to serialize access to it */ +static FAST_MUTEX FreeTypeLock; + +static LIST_ENTRY FontListHead; +static FAST_MUTEX FontListLock; +static BOOL RenderingEnabled = TRUE; + +#define MAX_FONT_CACHE 256 +UINT Hits; +UINT Misses; + +SHORT ftLanguageID = 0; + +typedef struct _FONT_CACHE_ENTRY { + LIST_ENTRY ListEntry; + int GlyphIndex; + FT_Face Face; + FT_Glyph Glyph; + int Height; +} FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY; +static LIST_ENTRY FontCacheListHead; +static UINT FontCacheNumEntries; + +static PWCHAR ElfScripts[32] = { /* these are in the order of the fsCsb[0] bits */ + L"Western", /*00*/ + L"Central_European", + L"Cyrillic", + L"Greek", + L"Turkish", + L"Hebrew", + L"Arabic", + L"Baltic", + L"Vietnamese", /*08*/ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/ + L"Thai", + L"Japanese", + L"CHINESE_GB2312", + L"Hangul", + L"CHINESE_BIG5", + L"Hangul(Johab)", + NULL, NULL, /*23*/ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + L"Symbol" /*31*/ +}; + +/* + * For NtGdiTranslateCharsetInfo + */ +#define FS(x) {{0,0,0,0},{0x1<<(x),0}} +#define MAXTCIINDEX 32 +static CHARSETINFO FontTci[MAXTCIINDEX] = { + /* ANSI */ + { ANSI_CHARSET, 1252, FS(0)}, + { EASTEUROPE_CHARSET, 1250, FS(1)}, + { RUSSIAN_CHARSET, 1251, FS(2)}, + { GREEK_CHARSET, 1253, FS(3)}, + { TURKISH_CHARSET, 1254, FS(4)}, + { HEBREW_CHARSET, 1255, FS(5)}, + { ARABIC_CHARSET, 1256, FS(6)}, + { BALTIC_CHARSET, 1257, FS(7)}, + { VIETNAMESE_CHARSET, 1258, FS(8)}, + /* reserved by ANSI */ + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + /* ANSI and OEM */ + { THAI_CHARSET, 874, FS(16)}, + { SHIFTJIS_CHARSET, 932, FS(17)}, + { GB2312_CHARSET, 936, FS(18)}, + { HANGEUL_CHARSET, 949, FS(19)}, + { CHINESEBIG5_CHARSET, 950, FS(20)}, + { JOHAB_CHARSET, 1361, FS(21)}, + /* reserved for alternate ANSI and OEM */ + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + { DEFAULT_CHARSET, 0, FS(0)}, + /* reserved for system */ + { DEFAULT_CHARSET, 0, FS(0)}, + { SYMBOL_CHARSET, 42 /* CP_SYMBOL */, FS(31)}, +}; + +BOOL FASTCALL +InitFontSupport(VOID) +{ + ULONG ulError; + + InitializeListHead(&FontListHead); + InitializeListHead(&FontCacheListHead); + FontCacheNumEntries = 0; + ExInitializeFastMutex(&FontListLock); + ExInitializeFastMutex(&FreeTypeLock); + + ulError = FT_Init_FreeType(&library); + if (ulError) { + DPRINT1("FT_Init_FreeType failed with error code 0x%x\n", ulError); + return FALSE; + } + + IntLoadSystemFonts(); + + return TRUE; +} + +/* + * IntLoadSystemFonts + * + * Search the system font directory and adds each font found. + */ + +VOID FASTCALL +IntLoadSystemFonts(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING Directory, SearchPattern, FileName, TempString; + IO_STATUS_BLOCK Iosb; + HANDLE hDirectory; + BYTE *DirInfoBuffer; + PFILE_DIRECTORY_INFORMATION DirInfo; + BOOLEAN bRestartScan = TRUE; + NTSTATUS Status; + + RtlInitUnicodeString(&Directory, L"\\SystemRoot\\Fonts\\"); + /* FIXME: Add support for other font types */ + RtlInitUnicodeString(&SearchPattern, L"*.ttf"); + + InitializeObjectAttributes( + &ObjectAttributes, + &Directory, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwOpenFile( + &hDirectory, + SYNCHRONIZE | FILE_LIST_DIRECTORY, + &ObjectAttributes, + &Iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE); + + if (NT_SUCCESS(Status)) + { + DirInfoBuffer = ExAllocatePool(PagedPool, 0x4000); + if (DirInfoBuffer == NULL) + { + ZwClose(hDirectory); + return; + } + + FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH * sizeof(WCHAR)); + if (FileName.Buffer == NULL) + { + ExFreePool(DirInfoBuffer); + ZwClose(hDirectory); + return; + } + FileName.Length = 0; + FileName.MaximumLength = MAX_PATH * sizeof(WCHAR); + + while (1) + { + Status = ZwQueryDirectoryFile( + hDirectory, + NULL, + NULL, + NULL, + &Iosb, + DirInfoBuffer, + 0x4000, + FileDirectoryInformation, + FALSE, + &SearchPattern, + bRestartScan); + + if (!NT_SUCCESS(Status) || Status == STATUS_NO_MORE_FILES) + { + break; + } + + DirInfo = (PFILE_DIRECTORY_INFORMATION)DirInfoBuffer; + while (1) + { + TempString.Buffer = DirInfo->FileName; + TempString.Length = + TempString.MaximumLength = DirInfo->FileNameLength; + RtlCopyUnicodeString(&FileName, &Directory); + RtlAppendUnicodeStringToString(&FileName, &TempString); + IntGdiAddFontResource(&FileName, 0); + if (DirInfo->NextEntryOffset == 0) + break; + DirInfo = (PFILE_DIRECTORY_INFORMATION)((ULONG_PTR)DirInfo + DirInfo->NextEntryOffset); + } + + bRestartScan = FALSE; + } + + ExFreePool(FileName.Buffer); + ExFreePool(DirInfoBuffer); + ZwClose(hDirectory); + } +} + +/* + * IntGdiAddFontResource + * + * Adds the font resource from the specified file to the system. + */ + +INT FASTCALL +IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics) +{ + FONTGDI *FontGDI; + NTSTATUS Status; + HANDLE FileHandle, KeyHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + PVOID Buffer = NULL; + IO_STATUS_BLOCK Iosb; + INT Error; + FT_Face Face; + ANSI_STRING AnsiFaceName; + PFONT_ENTRY Entry; + PSECTION_OBJECT SectionObject; + ULONG ViewSize = 0; + LARGE_INTEGER SectionSize; + FT_Fixed XScale, YScale; + UNICODE_STRING FontRegPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"); + + /* Open the font file */ + + InitializeObjectAttributes(&ObjectAttributes, FileName, 0, NULL, NULL); + Status = ZwOpenFile( + &FileHandle, + FILE_GENERIC_READ | SYNCHRONIZE, + &ObjectAttributes, + &Iosb, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not load font file: %wZ\n", FileName); + return 0; + } + + SectionSize.QuadPart = 0LL; + Status = MmCreateSection((PVOID)&SectionObject, SECTION_ALL_ACCESS, + NULL, &SectionSize, PAGE_READONLY, + SEC_COMMIT, FileHandle, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not map file: %wZ\n", FileName); + ZwClose(FileHandle); + return 0; + } + + ZwClose(FileHandle); + + Status = MmMapViewInSystemSpace(SectionObject, &Buffer, &ViewSize); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not map file: %wZ\n", FileName); + return Status; + } + + IntLockFreeType; + Error = FT_New_Memory_Face( + library, + Buffer, + ViewSize, + 0, + &Face); + IntUnLockFreeType; + + if (Error) + { + if (Error == FT_Err_Unknown_File_Format) + DPRINT("Unknown font file format\n"); + else + DPRINT("Error reading font file (error code: %u)\n", Error); + ObDereferenceObject(SectionObject); + return 0; + } + + Entry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY), TAG_FONT); + if (!Entry) + { + FT_Done_Face(Face); + ObDereferenceObject(SectionObject); + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), TAG_FONTOBJ); + if(FontGDI == NULL) + { + FT_Done_Face(Face); + ObDereferenceObject(SectionObject); + ExFreePool(Entry); + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + FontGDI->Filename = ExAllocatePoolWithTag(PagedPool, FileName->Length + sizeof(WCHAR), TAG_PFF); + if (FontGDI->Filename == NULL) + { + EngFreeMem(FontGDI); + FT_Done_Face(Face); + ObDereferenceObject(SectionObject); + ExFreePool(Entry); + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + memcpy(FontGDI->Filename, FileName->Buffer, FileName->Length); + FontGDI->Filename[FileName->Length / sizeof(WCHAR)] = L'\0'; + FontGDI->face = Face; + + /* FIXME: Complete text metrics */ + XScale = Face->size->metrics.x_scale; + YScale = Face->size->metrics.y_scale; +#if 0 /* This (Wine) code doesn't seem to work correctly for us */ + FontGDI->TextMetric.tmAscent = (FT_MulFix(Face->ascender, YScale) + 32) >> 6; + FontGDI->TextMetric.tmDescent = (FT_MulFix(Face->descender, YScale) + 32) >> 6; + FontGDI->TextMetric.tmHeight = (FT_MulFix(Face->ascender, YScale) - + FT_MulFix(Face->descender, YScale)) >> 6; +#else + FontGDI->TextMetric.tmAscent = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */ + FontGDI->TextMetric.tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */ + FontGDI->TextMetric.tmHeight = (Face->size->metrics.ascender - Face->size->metrics.descender) >> 6; +#endif + + + + DPRINT("Font loaded: %s (%s)\n", Face->family_name, Face->style_name); + DPRINT("Num glyphs: %u\n", Face->num_glyphs); + + /* Add this font resource to the font table */ + + Entry->Font = FontGDI; + Entry->NotEnum = (Characteristics & FR_NOT_ENUM); + RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name); + RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE); + + if (Characteristics & FR_PRIVATE) + { + PW32PROCESS Win32Process = PsGetCurrentProcessWin32Process(); + IntLockProcessPrivateFonts(Win32Process); + InsertTailList(&Win32Process->PrivateFontListHead, &Entry->ListEntry); + IntUnLockProcessPrivateFonts(Win32Process); + } + else + { + IntLockGlobalFonts; + InsertTailList(&FontListHead, &Entry->ListEntry); + InitializeObjectAttributes(&ObjectAttributes, &FontRegPath, OBJ_CASE_INSENSITIVE, NULL, NULL); + Status = ZwOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + LPWSTR pName = wcsrchr(FileName->Buffer, L'\\'); + if (pName) + { + pName++; + ZwSetValueKey(KeyHandle, &Entry->FaceName, 0, REG_SZ, pName, (wcslen(pName) + 1) * sizeof(WCHAR)); + } + ZwClose(KeyHandle); + } + IntUnLockGlobalFonts; + } + return 1; +} + +BOOL FASTCALL +IntIsFontRenderingEnabled(VOID) +{ + BOOL Ret = RenderingEnabled; + HDC hDC; + + hDC = IntGetScreenDC(); + if (hDC) + Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && RenderingEnabled; + + return Ret; +} + +VOID FASTCALL +IntEnableFontRendering(BOOL Enable) +{ + RenderingEnabled = Enable; +} + +FT_Render_Mode FASTCALL +IntGetFontRenderMode(LOGFONTW *logfont) +{ + switch(logfont->lfQuality) + { + case NONANTIALIASED_QUALITY: + return FT_RENDER_MODE_MONO; + case DRAFT_QUALITY: + return FT_RENDER_MODE_LIGHT; +/* case CLEARTYPE_QUALITY: + return FT_RENDER_MODE_LCD; */ + } + return FT_RENDER_MODE_NORMAL; +} + +INT +APIENTRY +NtGdiAddFontResourceW( + IN WCHAR *pwszFiles, + IN ULONG cwc, + IN ULONG cFiles, + IN FLONG fl, + IN DWORD dwPidTid, + IN OPTIONAL DESIGNVECTOR *pdv) +{ + UNICODE_STRING SafeFileName; + PWSTR src; + NTSTATUS Status; + int Ret; + + /* FIXME - Protect with SEH? */ + RtlInitUnicodeString(&SafeFileName, pwszFiles); + + /* Reserve for prepending '\??\' */ + SafeFileName.Length += 4 * sizeof(WCHAR); + SafeFileName.MaximumLength += 4 * sizeof(WCHAR); + + src = SafeFileName.Buffer; + SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING); + if(!SafeFileName.Buffer) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + /* Prepend '\??\' */ + RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR)); + + Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR))); + if(!NT_SUCCESS(Status)) + { + ExFreePool(SafeFileName.Buffer); + SetLastNtError(Status); + return 0; + } + + Ret = IntGdiAddFontResource(&SafeFileName, (DWORD)fl); + + ExFreePool(SafeFileName.Buffer); + return Ret; +} + +NTSTATUS FASTCALL +TextIntCreateFontIndirect(CONST LPLOGFONTW lf, HFONT *NewFont) +{ + PTEXTOBJ TextObj; + + TextObj = TEXTOBJ_AllocTextWithHandle(); + if (!TextObj) + { + return STATUS_NO_MEMORY; + } + + *NewFont = TextObj->BaseObject.hHmgr; + memcpy(&TextObj->logfont.elfEnumLogfontEx.elfLogFont, lf, sizeof(LOGFONTW)); + if (lf->lfEscapement != lf->lfOrientation) + { + /* this should really depend on whether GM_ADVANCED is set */ + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation = + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement; + } + TEXTOBJ_UnlockText(TextObj); + + return STATUS_SUCCESS; +} + +HFONT +STDCALL +NtGdiHfontCreate( + IN PENUMLOGFONTEXDVW pelfw, + IN ULONG cjElfw, + IN LFTYPE lft, + IN FLONG fl, + IN PVOID pvCliData ) +{ + ENUMLOGFONTEXDVW SafeLogfont; + HFONT hNewFont; + PTEXTOBJ TextObj; + NTSTATUS Status = STATUS_SUCCESS; + + if (!pelfw) + { + return NULL; + } + + _SEH_TRY + { + ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1); + RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END + + if (!NT_SUCCESS(Status)) + { + return NULL; + } + + TextObj = TEXTOBJ_AllocTextWithHandle(); + if (!TextObj) + { + return NULL; + } + hNewFont = TextObj->BaseObject.hHmgr; + + RtlCopyMemory (&TextObj->logfont, &SafeLogfont, sizeof(ENUMLOGFONTEXDVW)); + + if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement != + SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation) + { + /* this should really depend on whether GM_ADVANCED is set */ + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation = + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement; + } + TEXTOBJ_UnlockText(TextObj); + + return hNewFont; + +} + +/************************************************************************* + * TranslateCharsetInfo + * + * Fills a CHARSETINFO structure for a character set, code page, or + * font. This allows making the correspondance between different labelings + * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges) + * of the same encoding. + * + * Only one codepage will be set in Cs->fs. If TCI_SRCFONTSIG is used, + * only one codepage should be set in *Src. + * + * RETURNS + * TRUE on success, FALSE on failure. + * + */ +static BOOLEAN STDCALL +IntTranslateCharsetInfo(PDWORD Src, /* [in] + if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE + if flags == TCI_SRCCHARSET: a character set value + if flags == TCI_SRCCODEPAGE: a code page value */ + LPCHARSETINFO Cs, /* [out] structure to receive charset information */ + DWORD Flags /* [in] determines interpretation of lpSrc */) +{ + int Index = 0; + + switch (Flags) + { + case TCI_SRCFONTSIG: + while (0 == (*Src >> Index & 0x0001) && Index < MAXTCIINDEX) + { + Index++; + } + break; + case TCI_SRCCODEPAGE: + while ((UINT) (Src) != FontTci[Index].ciACP && Index < MAXTCIINDEX) + { + Index++; + } + break; + case TCI_SRCCHARSET: + while ((UINT) (Src) != FontTci[Index].ciCharset && Index < MAXTCIINDEX) + { + Index++; + } + break; + default: + return FALSE; + } + + if (MAXTCIINDEX <= Index || DEFAULT_CHARSET == FontTci[Index].ciCharset) + { + return FALSE; + } + + memcpy(Cs, &FontTci[Index], sizeof(CHARSETINFO)); + + return TRUE; +} + + +static void FASTCALL +FillTM(TEXTMETRICW *TM, FT_Face Face, TT_OS2 *pOS2, TT_HoriHeader *pHori) +{ + FT_Fixed XScale, YScale; + int Ascent, Descent; + + XScale = Face->size->metrics.x_scale; + YScale = Face->size->metrics.y_scale; + + if (0 == pOS2->usWinAscent + pOS2->usWinDescent) + { + Ascent = pHori->Ascender; + Descent = -pHori->Descender; + } + else + { + Ascent = pOS2->usWinAscent; + Descent = pOS2->usWinDescent; + } + +#if 0 /* This (Wine) code doesn't seem to work correctly for us, cmd issue */ + TM->tmAscent = (FT_MulFix(Ascent, YScale) + 32) >> 6; + TM->tmDescent = (FT_MulFix(Descent, YScale) + 32) >> 6; +#else /* This (ros) code was previously affected by a FreeType bug, but it works now */ + TM->tmAscent = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */ + TM->tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */ +#endif + + TM->tmInternalLeading = (FT_MulFix(Ascent + Descent - Face->units_per_EM, YScale) + 32) >> 6; + TM->tmHeight = TM->tmAscent + TM->tmDescent; // we need add 1 height more after scale it right + + /* MSDN says: + * el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender))) + */ + TM->tmExternalLeading = max(0, (FT_MulFix(pHori->Line_Gap + - ((Ascent + Descent) + - (pHori->Ascender - pHori->Descender)), + YScale) + 32) >> 6); + + TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6; + if (0 == TM->tmAveCharWidth) + { + TM->tmAveCharWidth = 1; + } + + /* Correct forumla to get the maxcharwidth from unicode and ansi font */ + TM->tmMaxCharWidth = (FT_MulFix(Face->max_advance_width, XScale) + 32) >> 6; + + TM->tmWeight = pOS2->usWeightClass; + TM->tmOverhang = 0; + TM->tmDigitizedAspectX = 300; + TM->tmDigitizedAspectY = 300; + TM->tmFirstChar = pOS2->usFirstCharIndex; + TM->tmLastChar = pOS2->usLastCharIndex; + TM->tmDefaultChar = pOS2->usDefaultChar; + TM->tmBreakChar = L'\0' != pOS2->usBreakChar ? pOS2->usBreakChar : ' '; + TM->tmItalic = (Face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0; + TM->tmUnderlined = 0; /* entry in OS2 table */ + TM->tmStruckOut = 0; /* entry in OS2 table */ + + /* Yes TPMF_FIXED_PITCH is correct; braindead api */ + if (! FT_IS_FIXED_WIDTH(Face)) + { + TM->tmPitchAndFamily = TMPF_FIXED_PITCH; + } + else + { + TM->tmPitchAndFamily = 0; + } + + switch (pOS2->panose[PAN_FAMILYTYPE_INDEX]) + { + case PAN_FAMILY_SCRIPT: + TM->tmPitchAndFamily |= FF_SCRIPT; + break; + case PAN_FAMILY_DECORATIVE: + case PAN_FAMILY_PICTORIAL: + TM->tmPitchAndFamily |= FF_DECORATIVE; + break; + case PAN_FAMILY_TEXT_DISPLAY: + if (0 == TM->tmPitchAndFamily) /* fixed */ + { + TM->tmPitchAndFamily = FF_MODERN; + } + else + { + switch (pOS2->panose[PAN_SERIFSTYLE_INDEX]) + { + case PAN_SERIF_NORMAL_SANS: + case PAN_SERIF_OBTUSE_SANS: + case PAN_SERIF_PERP_SANS: + TM->tmPitchAndFamily |= FF_SWISS; + break; + default: + TM->tmPitchAndFamily |= FF_ROMAN; + break; + } + } + break; + default: + TM->tmPitchAndFamily |= FF_DONTCARE; + } + + if (FT_IS_SCALABLE(Face)) + { + TM->tmPitchAndFamily |= TMPF_VECTOR; + } + if (FT_IS_SFNT(Face)) + { + TM->tmPitchAndFamily |= TMPF_TRUETYPE; + } + + TM->tmCharSet = DEFAULT_CHARSET; +} + +/************************************************************* + * IntGetOutlineTextMetrics + * + */ +INT FASTCALL +IntGetOutlineTextMetrics(PFONTGDI FontGDI, UINT Size, + OUTLINETEXTMETRICW *Otm) +{ + unsigned Needed; + TT_OS2 *pOS2; + TT_HoriHeader *pHori; + TT_Postscript *pPost; + FT_Fixed XScale, YScale; + ANSI_STRING FamilyNameA, StyleNameA; + UNICODE_STRING FamilyNameW, StyleNameW, Regular; + char *Cp; + + Needed = sizeof(OUTLINETEXTMETRICW); + + RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name); + RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE); + + RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name); + RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE); + + /* These names should be read from the TT name table */ + + /* length of otmpFamilyName */ + Needed += FamilyNameW.Length + sizeof(WCHAR); + + RtlInitUnicodeString(&Regular, L"regular"); + /* length of otmpFaceName */ + if (0 == RtlCompareUnicodeString(&StyleNameW, &Regular, TRUE)) + { + Needed += FamilyNameW.Length + sizeof(WCHAR); /* just the family name */ + } + else + { + Needed += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1); /* family + " " + style */ + } + + /* length of otmpStyleName */ + Needed += StyleNameW.Length + sizeof(WCHAR); + + /* length of otmpFullName */ + Needed += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1); + + if (Size < Needed) + { + RtlFreeUnicodeString(&FamilyNameW); + RtlFreeUnicodeString(&StyleNameW); + return Needed; + } + + XScale = FontGDI->face->size->metrics.x_scale; + YScale = FontGDI->face->size->metrics.y_scale; + + IntLockFreeType; + pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2); + if (NULL == pOS2) + { + IntUnLockFreeType; + DPRINT1("Can't find OS/2 table - not TT font?\n"); + RtlFreeUnicodeString(&StyleNameW); + RtlFreeUnicodeString(&FamilyNameW); + return 0; + } + + pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea); + if (NULL == pHori) + { + IntUnLockFreeType; + DPRINT1("Can't find HHEA table - not TT font?\n"); + RtlFreeUnicodeString(&StyleNameW); + RtlFreeUnicodeString(&FamilyNameW); + return 0; + } + + pPost = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_post); /* we can live with this failing */ + + Otm->otmSize = Needed; + + FillTM(&Otm->otmTextMetrics, FontGDI->face, pOS2, pHori); + + Otm->otmFiller = 0; + memcpy(&Otm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT); + Otm->otmfsSelection = pOS2->fsSelection; + Otm->otmfsType = pOS2->fsType; + Otm->otmsCharSlopeRise = pHori->caret_Slope_Rise; + Otm->otmsCharSlopeRun = pHori->caret_Slope_Run; + Otm->otmItalicAngle = 0; /* POST table */ + Otm->otmEMSquare = FontGDI->face->units_per_EM; + Otm->otmAscent = (FT_MulFix(pOS2->sTypoAscender, YScale) + 32) >> 6; + Otm->otmDescent = (FT_MulFix(pOS2->sTypoDescender, YScale) + 32) >> 6; + Otm->otmLineGap = (FT_MulFix(pOS2->sTypoLineGap, YScale) + 32) >> 6; + Otm->otmsCapEmHeight = (FT_MulFix(pOS2->sCapHeight, YScale) + 32) >> 6; + Otm->otmsXHeight = (FT_MulFix(pOS2->sxHeight, YScale) + 32) >> 6; + Otm->otmrcFontBox.left = (FT_MulFix(FontGDI->face->bbox.xMin, XScale) + 32) >> 6; + Otm->otmrcFontBox.right = (FT_MulFix(FontGDI->face->bbox.xMax, XScale) + 32) >> 6; + Otm->otmrcFontBox.top = (FT_MulFix(FontGDI->face->bbox.yMax, YScale) + 32) >> 6; + Otm->otmrcFontBox.bottom = (FT_MulFix(FontGDI->face->bbox.yMin, YScale) + 32) >> 6; + Otm->otmMacAscent = 0; /* where do these come from ? */ + Otm->otmMacDescent = 0; + Otm->otmMacLineGap = 0; + Otm->otmusMinimumPPEM = 0; /* TT Header */ + Otm->otmptSubscriptSize.x = (FT_MulFix(pOS2->ySubscriptXSize, XScale) + 32) >> 6; + Otm->otmptSubscriptSize.y = (FT_MulFix(pOS2->ySubscriptYSize, YScale) + 32) >> 6; + Otm->otmptSubscriptOffset.x = (FT_MulFix(pOS2->ySubscriptXOffset, XScale) + 32) >> 6; + Otm->otmptSubscriptOffset.y = (FT_MulFix(pOS2->ySubscriptYOffset, YScale) + 32) >> 6; + Otm->otmptSuperscriptSize.x = (FT_MulFix(pOS2->ySuperscriptXSize, XScale) + 32) >> 6; + Otm->otmptSuperscriptSize.y = (FT_MulFix(pOS2->ySuperscriptYSize, YScale) + 32) >> 6; + Otm->otmptSuperscriptOffset.x = (FT_MulFix(pOS2->ySuperscriptXOffset, XScale) + 32) >> 6; + Otm->otmptSuperscriptOffset.y = (FT_MulFix(pOS2->ySuperscriptYOffset, YScale) + 32) >> 6; + Otm->otmsStrikeoutSize = (FT_MulFix(pOS2->yStrikeoutSize, YScale) + 32) >> 6; + Otm->otmsStrikeoutPosition = (FT_MulFix(pOS2->yStrikeoutPosition, YScale) + 32) >> 6; + if (NULL == pPost) + { + Otm->otmsUnderscoreSize = 0; + Otm->otmsUnderscorePosition = 0; + } + else + { + Otm->otmsUnderscoreSize = (FT_MulFix(pPost->underlineThickness, YScale) + 32) >> 6; + Otm->otmsUnderscorePosition = (FT_MulFix(pPost->underlinePosition, YScale) + 32) >> 6; + } + + IntUnLockFreeType; + + /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */ + Cp = (char*) Otm + sizeof(OUTLINETEXTMETRICW); + Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, FamilyNameW.Buffer); + Cp += FamilyNameW.Length + sizeof(WCHAR); + Otm->otmpStyleName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, StyleNameW.Buffer); + Cp += StyleNameW.Length + sizeof(WCHAR); + Otm->otmpFaceName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, FamilyNameW.Buffer); + if (0 != RtlCompareUnicodeString(&StyleNameW, &Regular, TRUE)) + { + wcscat((WCHAR*) Cp, L" "); + wcscat((WCHAR*) Cp, StyleNameW.Buffer); + Cp += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1); + } + else + { + Cp += FamilyNameW.Length + sizeof(WCHAR); + } + Otm->otmpFullName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, FamilyNameW.Buffer); + wcscat((WCHAR*) Cp, L" "); + wcscat((WCHAR*) Cp, StyleNameW.Buffer); + + RtlFreeUnicodeString(&StyleNameW); + RtlFreeUnicodeString(&FamilyNameW); + + return Needed; +} + +static PFONTGDI FASTCALL +FindFaceNameInList(PUNICODE_STRING FaceName, PLIST_ENTRY Head) +{ + PLIST_ENTRY Entry; + PFONT_ENTRY CurrentEntry; + ANSI_STRING EntryFaceNameA; + UNICODE_STRING EntryFaceNameW; + FONTGDI *FontGDI; + + Entry = Head->Flink; + while (Entry != Head) + { + CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry); + + FontGDI = CurrentEntry->Font; + ASSERT(FontGDI); + + RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); + RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); + if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length) + { + EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR); + EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0'; + } + + if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE)) + { + RtlFreeUnicodeString(&EntryFaceNameW); + return FontGDI; + } + + RtlFreeUnicodeString(&EntryFaceNameW); + Entry = Entry->Flink; + } + + return NULL; +} + +static PFONTGDI FASTCALL +FindFaceNameInLists(PUNICODE_STRING FaceName) +{ + PW32PROCESS Win32Process; + PFONTGDI Font; + + /* Search the process local list */ + Win32Process = PsGetCurrentProcessWin32Process(); + IntLockProcessPrivateFonts(Win32Process); + Font = FindFaceNameInList(FaceName, &Win32Process->PrivateFontListHead); + IntUnLockProcessPrivateFonts(Win32Process); + if (NULL != Font) + { + return Font; + } + + /* Search the global list */ + IntLockGlobalFonts; + Font = FindFaceNameInList(FaceName, &FontListHead); + IntUnLockGlobalFonts; + + return Font; +} + +static void FASTCALL +FontFamilyFillInfo(PFONTFAMILYINFO Info, PCWSTR FaceName, PFONTGDI FontGDI) +{ + ANSI_STRING StyleA; + UNICODE_STRING StyleW; + TT_OS2 *pOS2; + FONTSIGNATURE fs; + DWORD fs_fsCsb0; + CHARSETINFO CharSetInfo; + unsigned i, Size; + OUTLINETEXTMETRICW *Otm; + LOGFONTW *Lf; + TEXTMETRICW *TM; + NEWTEXTMETRICW *Ntm; + + RtlZeroMemory(Info, sizeof(FONTFAMILYINFO)); + Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); + Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); + if (NULL == Otm) + { + return; + } + IntGetOutlineTextMetrics(FontGDI, Size, Otm); + + Lf = &Info->EnumLogFontEx.elfLogFont; + TM = &Otm->otmTextMetrics; + + Lf->lfHeight = TM->tmHeight; + Lf->lfWidth = TM->tmAveCharWidth; + Lf->lfWeight = TM->tmWeight; + Lf->lfItalic = TM->tmItalic; + Lf->lfPitchAndFamily = (TM->tmPitchAndFamily & 0xf1) + 1; + Lf->lfCharSet = TM->tmCharSet; + Lf->lfOutPrecision = OUT_OUTLINE_PRECIS; + Lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + Lf->lfQuality = PROOF_QUALITY; + + Ntm = &Info->NewTextMetricEx.ntmTm; + Ntm->tmHeight = TM->tmHeight; + Ntm->tmAscent = TM->tmAscent; + Ntm->tmDescent = TM->tmDescent; + Ntm->tmInternalLeading = TM->tmInternalLeading; + Ntm->tmExternalLeading = TM->tmExternalLeading; + Ntm->tmAveCharWidth = TM->tmAveCharWidth; + Ntm->tmMaxCharWidth = TM->tmMaxCharWidth; + Ntm->tmWeight = TM->tmWeight; + Ntm->tmOverhang = TM->tmOverhang; + Ntm->tmDigitizedAspectX = TM->tmDigitizedAspectX; + Ntm->tmDigitizedAspectY = TM->tmDigitizedAspectY; + Ntm->tmFirstChar = TM->tmFirstChar; + Ntm->tmLastChar = TM->tmLastChar; + Ntm->tmDefaultChar = TM->tmDefaultChar; + Ntm->tmBreakChar = TM->tmBreakChar; + Ntm->tmItalic = TM->tmItalic; + Ntm->tmUnderlined = TM->tmUnderlined; + Ntm->tmStruckOut = TM->tmStruckOut; + Ntm->tmPitchAndFamily = TM->tmPitchAndFamily; + Ntm->tmCharSet = TM->tmCharSet; + Ntm->ntmFlags = TM->tmItalic ? NTM_ITALIC : 0; + if (550 < TM->tmWeight) + { + Ntm->ntmFlags |= NTM_BOLD; + } + if (0 == Ntm->ntmFlags) + { + Ntm->ntmFlags = NTM_REGULAR; + } + + Ntm->ntmSizeEM = Otm->otmEMSquare; + Ntm->ntmCellHeight = 0; + Ntm->ntmAvgWidth = 0; + + Info->FontType = (0 != (TM->tmPitchAndFamily & TMPF_TRUETYPE) + ? TRUETYPE_FONTTYPE : 0); + if (0 == (TM->tmPitchAndFamily & TMPF_VECTOR)) + { + Info->FontType |= RASTER_FONTTYPE; + } + + ExFreePool(Otm); + + wcsncpy(Info->EnumLogFontEx.elfLogFont.lfFaceName, FaceName, LF_FACESIZE); + wcsncpy(Info->EnumLogFontEx.elfFullName, FaceName, LF_FULLFACESIZE); + RtlInitAnsiString(&StyleA, FontGDI->face->style_name); + RtlAnsiStringToUnicodeString(&StyleW, &StyleA, TRUE); + wcsncpy(Info->EnumLogFontEx.elfStyle, StyleW.Buffer, LF_FACESIZE); + RtlFreeUnicodeString(&StyleW); + + Info->EnumLogFontEx.elfLogFont.lfCharSet = DEFAULT_CHARSET; + Info->EnumLogFontEx.elfScript[0] = L'\0'; + IntLockFreeType; + pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2); + IntUnLockFreeType; + if (NULL != pOS2) + { + Info->NewTextMetricEx.ntmFontSig.fsCsb[0] = pOS2->ulCodePageRange1; + Info->NewTextMetricEx.ntmFontSig.fsCsb[1] = pOS2->ulCodePageRange2; + Info->NewTextMetricEx.ntmFontSig.fsUsb[0] = pOS2->ulUnicodeRange1; + Info->NewTextMetricEx.ntmFontSig.fsUsb[1] = pOS2->ulUnicodeRange2; + Info->NewTextMetricEx.ntmFontSig.fsUsb[2] = pOS2->ulUnicodeRange3; + Info->NewTextMetricEx.ntmFontSig.fsUsb[3] = pOS2->ulUnicodeRange4; + + fs_fsCsb0 = pOS2->ulCodePageRange1; + if (0 == pOS2->version) + { + FT_UInt Dummy; + + if (FT_Get_First_Char(FontGDI->face, &Dummy) < 0x100) + { + fs_fsCsb0 |= 1; + } + else + { + fs_fsCsb0 |= 1L << 31; + } + } + if (0 == fs_fsCsb0) + { /* let's see if we can find any interesting cmaps */ + for (i = 0; i < FontGDI->face->num_charmaps; i++) + { + switch (FontGDI->face->charmaps[i]->encoding) + { + case ft_encoding_unicode: + case ft_encoding_apple_roman: + fs_fsCsb0 |= 1; + break; + case ft_encoding_symbol: + fs_fsCsb0 |= 1L << 31; + break; + default: + break; + } + } + } + + for(i = 0; i < 32; i++) + { + if (0 != (fs_fsCsb0 & (1L << i))) + { + fs.fsCsb[0] = 1L << i; + fs.fsCsb[1] = 0; + if (! IntTranslateCharsetInfo(fs.fsCsb, &CharSetInfo, TCI_SRCFONTSIG)) + { + CharSetInfo.ciCharset = DEFAULT_CHARSET; + } + if (31 == i) + { + CharSetInfo.ciCharset = SYMBOL_CHARSET; + } + if (DEFAULT_CHARSET != CharSetInfo.ciCharset) + { + Info->EnumLogFontEx.elfLogFont.lfCharSet = CharSetInfo.ciCharset; + if (NULL != ElfScripts[i]) + { + wcscpy(Info->EnumLogFontEx.elfScript, ElfScripts[i]); + } + else + { + DPRINT1("Unknown elfscript for bit %d\n", i); + } + } + } + } + } +} + +static int FASTCALL +FindFaceNameInInfo(PUNICODE_STRING FaceName, PFONTFAMILYINFO Info, DWORD InfoEntries) +{ + DWORD i; + UNICODE_STRING InfoFaceName; + + for (i = 0; i < InfoEntries; i++) + { + RtlInitUnicodeString(&InfoFaceName, Info[i].EnumLogFontEx.elfLogFont.lfFaceName); + if (0 == RtlCompareUnicodeString(&InfoFaceName, FaceName, TRUE)) + { + return i; + } + } + + return -1; +} + +static BOOLEAN FASTCALL +FontFamilyInclude(LPLOGFONTW LogFont, PUNICODE_STRING FaceName, + PFONTFAMILYINFO Info, DWORD InfoEntries) +{ + UNICODE_STRING LogFontFaceName; + + RtlInitUnicodeString(&LogFontFaceName, LogFont->lfFaceName); + if (0 != LogFontFaceName.Length + && 0 != RtlCompareUnicodeString(&LogFontFaceName, FaceName, TRUE)) + { + return FALSE; + } + + return FindFaceNameInInfo(FaceName, Info, InfoEntries) < 0; +} + +static BOOLEAN FASTCALL +GetFontFamilyInfoForList(LPLOGFONTW LogFont, + PFONTFAMILYINFO Info, + DWORD *Count, + DWORD Size, + PLIST_ENTRY Head) +{ + PLIST_ENTRY Entry; + PFONT_ENTRY CurrentEntry; + ANSI_STRING EntryFaceNameA; + UNICODE_STRING EntryFaceNameW; + FONTGDI *FontGDI; + + Entry = Head->Flink; + while (Entry != Head) + { + CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry); + + FontGDI = CurrentEntry->Font; + ASSERT(FontGDI); + + RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); + RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); + if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length) + { + EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR); + EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0'; + } + + if (FontFamilyInclude(LogFont, &EntryFaceNameW, Info, min(*Count, Size))) + { + if (*Count < Size) + { + FontFamilyFillInfo(Info + *Count, EntryFaceNameW.Buffer, FontGDI); + } + (*Count)++; + } + RtlFreeUnicodeString(&EntryFaceNameW); + Entry = Entry->Flink; + } + + return TRUE; +} + +typedef struct FontFamilyInfoCallbackContext +{ + LPLOGFONTW LogFont; + PFONTFAMILYINFO Info; + DWORD Count; + DWORD Size; +} FONT_FAMILY_INFO_CALLBACK_CONTEXT, *PFONT_FAMILY_INFO_CALLBACK_CONTEXT; + +static NTSTATUS STDCALL +FontFamilyInfoQueryRegistryCallback(IN PWSTR ValueName, IN ULONG ValueType, + IN PVOID ValueData, IN ULONG ValueLength, + IN PVOID Context, IN PVOID EntryContext) +{ + PFONT_FAMILY_INFO_CALLBACK_CONTEXT InfoContext; + UNICODE_STRING RegistryName, RegistryValue; + int Existing; + PFONTGDI FontGDI; + + if (REG_SZ != ValueType) + { + return STATUS_SUCCESS; + } + InfoContext = (PFONT_FAMILY_INFO_CALLBACK_CONTEXT) Context; + RtlInitUnicodeString(&RegistryName, ValueName); + + /* Do we need to include this font family? */ + if (FontFamilyInclude(InfoContext->LogFont, &RegistryName, InfoContext->Info, + min(InfoContext->Count, InfoContext->Size))) + { + RtlInitUnicodeString(&RegistryValue, (PCWSTR) ValueData); + Existing = FindFaceNameInInfo(&RegistryValue, InfoContext->Info, + min(InfoContext->Count, InfoContext->Size)); + if (0 <= Existing) + { + /* We already have the information about the "real" font. Just copy it */ + if (InfoContext->Count < InfoContext->Size) + { + InfoContext->Info[InfoContext->Count] = InfoContext->Info[Existing]; + wcsncpy(InfoContext->Info[InfoContext->Count].EnumLogFontEx.elfLogFont.lfFaceName, + RegistryName.Buffer, LF_FACESIZE); + } + InfoContext->Count++; + return STATUS_SUCCESS; + } + + /* Try to find information about the "real" font */ + FontGDI = FindFaceNameInLists(&RegistryValue); + if (NULL == FontGDI) + { + /* "Real" font not found, discard this registry entry */ + return STATUS_SUCCESS; + } + + /* Return info about the "real" font but with the name of the alias */ + if (InfoContext->Count < InfoContext->Size) + { + FontFamilyFillInfo(InfoContext->Info + InfoContext->Count, + RegistryName.Buffer, FontGDI); + } + InfoContext->Count++; + return STATUS_SUCCESS; + } + + return STATUS_SUCCESS; +} + +static BOOLEAN FASTCALL +GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont, + PFONTFAMILYINFO Info, + DWORD *Count, + DWORD Size) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}}; + FONT_FAMILY_INFO_CALLBACK_CONTEXT Context; + NTSTATUS Status; + + /* Enumerate font families found in HKLM\Software\Microsoft\Windows NT\CurrentVersion\SysFontSubstitutes + The real work is done in the registry callback function */ + Context.LogFont = LogFont; + Context.Info = Info; + Context.Count = *Count; + Context.Size = Size; + + QueryTable[0].QueryRoutine = FontFamilyInfoQueryRegistryCallback; + QueryTable[0].Flags = 0; + QueryTable[0].Name = NULL; + QueryTable[0].EntryContext = NULL; + QueryTable[0].DefaultType = REG_NONE; + QueryTable[0].DefaultData = NULL; + QueryTable[0].DefaultLength = 0; + + QueryTable[1].QueryRoutine = NULL; + QueryTable[1].Name = NULL; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT, + L"SysFontSubstitutes", + QueryTable, + &Context, + NULL); + if (NT_SUCCESS(Status)) + { + *Count = Context.Count; + } + + return NT_SUCCESS(Status) || STATUS_OBJECT_NAME_NOT_FOUND == Status; +} + +BOOL +FASTCALL +ftGdiGetRasterizerCaps(LPRASTERIZER_STATUS lprs) +{ + if ( lprs ) + { + lprs->nSize = sizeof(RASTERIZER_STATUS); + lprs->wFlags = TT_AVAILABLE | TT_ENABLED; + lprs->nLanguageID = ftLanguageID; + return TRUE; + } + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; +} + +int STDCALL +NtGdiGetFontFamilyInfo(HDC Dc, + LPLOGFONTW UnsafeLogFont, + PFONTFAMILYINFO UnsafeInfo, + DWORD Size) +{ + NTSTATUS Status; + LOGFONTW LogFont; + PFONTFAMILYINFO Info; + DWORD Count; + PW32PROCESS Win32Process; + + /* Make a safe copy */ + Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW)); + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return -1; + } + + /* Allocate space for a safe copy */ + Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), TAG_GDITEXT); + if (NULL == Info) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return -1; + } + + /* Enumerate font families in the global list */ + IntLockGlobalFonts; + Count = 0; + if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size, &FontListHead) ) + { + IntUnLockGlobalFonts; + ExFreePool(Info); + return -1; + } + IntUnLockGlobalFonts; + + /* Enumerate font families in the process local list */ + Win32Process = PsGetCurrentProcessWin32Process(); + IntLockProcessPrivateFonts(Win32Process); + if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size, + &Win32Process->PrivateFontListHead)) + { + IntUnLockProcessPrivateFonts(Win32Process); + ExFreePool(Info); + return -1; + } + IntUnLockProcessPrivateFonts(Win32Process); + + /* Enumerate font families in the registry */ + if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size)) + { + ExFreePool(Info); + return -1; + } + + /* Return data to caller */ + if (0 != Count) + { + Status = MmCopyToCaller(UnsafeInfo, Info, + (Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO)); + if (! NT_SUCCESS(Status)) + { + ExFreePool(Info); + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return -1; + } + } + + ExFreePool(Info); + + return Count; +} + +FT_Glyph STDCALL +NtGdiGlyphCacheGet( + FT_Face Face, + INT GlyphIndex, + INT Height) +{ + PLIST_ENTRY CurrentEntry; + PFONT_CACHE_ENTRY FontEntry; + +// DbgPrint("CacheGet\n"); + + CurrentEntry = FontCacheListHead.Flink; + while (CurrentEntry != &FontCacheListHead) + { + FontEntry = (PFONT_CACHE_ENTRY)CurrentEntry; + if (FontEntry->Face == Face && + FontEntry->GlyphIndex == GlyphIndex && + FontEntry->Height == Height) + break; + CurrentEntry = CurrentEntry->Flink; + } + + if (CurrentEntry == &FontCacheListHead) { +// DbgPrint("Miss! %x\n", FontEntry->Glyph); +/* + Misses++; + if (Misses>100) { + DbgPrint ("Hits: %d Misses: %d\n", Hits, Misses); + Hits = Misses = 0; + } +*/ + return NULL; + } + + RemoveEntryList(CurrentEntry); + InsertHeadList(&FontCacheListHead, CurrentEntry); + +// DbgPrint("Hit! %x\n", FontEntry->Glyph); +/* + Hits++; + + if (Hits>100) { + DbgPrint ("Hits: %d Misses: %d\n", Hits, Misses); + Hits = Misses = 0; + } +*/ + return FontEntry->Glyph; +} + +FT_Glyph STDCALL +NtGdiGlyphCacheSet( + FT_Face Face, + INT GlyphIndex, + INT Height, + FT_GlyphSlot GlyphSlot, + FT_Render_Mode RenderMode) +{ + FT_Glyph GlyphCopy; + INT error; + PFONT_CACHE_ENTRY NewEntry; + +// DbgPrint("CacheSet.\n"); + + error = FT_Get_Glyph(GlyphSlot, &GlyphCopy); + if (error) + { + DbgPrint("Failure caching glyph.\n"); + return NULL; + }; + error = FT_Glyph_To_Bitmap(&GlyphCopy, RenderMode, 0, 1); + if (error) + { + DbgPrint("Failure rendering glyph.\n"); + return NULL; + }; + + NewEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_CACHE_ENTRY), TAG_FONT); + if (!NewEntry) + { + DbgPrint("Alloc failure caching glyph.\n"); + FT_Done_Glyph(GlyphCopy); + return NULL; + } + + NewEntry->GlyphIndex = GlyphIndex; + NewEntry->Face = Face; + NewEntry->Glyph = GlyphCopy; + NewEntry->Height = Height; + + InsertHeadList(&FontCacheListHead, &NewEntry->ListEntry); + if (FontCacheNumEntries++ > MAX_FONT_CACHE) { + NewEntry = (PFONT_CACHE_ENTRY)FontCacheListHead.Blink; + FT_Done_Glyph(NewEntry->Glyph); + RemoveTailList(&FontCacheListHead); + ExFreePool(NewEntry); + FontCacheNumEntries--; + } + +// DbgPrint("Returning the glyphcopy: %x\n", GlyphCopy); + + return GlyphCopy; +} + +BOOL +APIENTRY +NtGdiExtTextOutW( + IN HDC hDC, + IN INT XStart, + IN INT YStart, + IN UINT fuOptions, + IN OPTIONAL LPRECT lprc, + IN LPWSTR UnsafeString, + IN INT Count, + IN OPTIONAL LPINT UnsafeDx, + IN DWORD dwCodePage) +{ + /* + * FIXME: + * Call EngTextOut, which does the real work (calling DrvTextOut where + * appropriate) + */ + + DC *dc; + PDC_ATTR Dc_Attr; + SURFOBJ *SurfObj; + BITMAPOBJ *BitmapObj = NULL; + int error, glyph_index, n, i; + FT_Face face; + FT_GlyphSlot glyph; + FT_Glyph realglyph; + FT_BitmapGlyph realglyph2; + LONGLONG TextLeft, RealXStart; + ULONG TextTop, previous, BackgroundLeft; + FT_Bool use_kerning; + RECTL DestRect, MaskRect, SpecifiedDestRect; + POINTL SourcePoint, BrushOrigin; + HBRUSH hBrushFg = NULL; + PGDIBRUSHOBJ BrushFg = NULL; + GDIBRUSHINST BrushFgInst; + HBRUSH hBrushBg = NULL; + PGDIBRUSHOBJ BrushBg = NULL; + GDIBRUSHINST BrushBgInst; + HBITMAP HSourceGlyph; + SURFOBJ *SourceGlyphSurf; + SIZEL bitSize; + FT_CharMap found = 0, charmap; + INT yoff; + FONTOBJ *FontObj; + PFONTGDI FontGDI; + PTEXTOBJ TextObj = NULL; + PPALGDI PalDestGDI; + XLATEOBJ *XlateObj=NULL, *XlateObj2=NULL; + ULONG Mode; + FT_Render_Mode RenderMode; + BOOLEAN Render; + NTSTATUS Status; + INT *Dx = NULL; + POINT Start; + BOOL DoBreak = FALSE; + LPCWSTR String, SafeString = NULL; + HPALETTE hDestPalette; + + // TODO: Write test-cases to exactly match real Windows in different + // bad parameters (e.g. does Windows check the DC or the RECT first?). + dc = DC_LockDc(hDC); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + if (dc->DC_Type == DC_TYPE_INFO) + { + DC_UnlockDc(dc); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + + /* Check if String is valid */ + if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + goto fail; + } + if (Count > 0) + { + SafeString = ExAllocatePoolWithTag(PagedPool, Count * sizeof(WCHAR), TAG_GDITEXT); + if (!SafeString) + { + goto fail; + } + Status = MmCopyFromCaller(SafeString, UnsafeString, Count * sizeof(WCHAR)); + if (! NT_SUCCESS(Status)) + { + goto fail; + } + } + String = SafeString; + + if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED))) + { + // At least one of the two flags were specified. Copy lprc. Once. + Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT)); + if (!NT_SUCCESS(Status)) + { + DC_UnlockDc(dc); + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2); + } + + if (NULL != UnsafeDx && Count > 0) + { + Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT); + if (NULL == Dx) + { + goto fail; + } + Status = MmCopyFromCaller(Dx, UnsafeDx, Count * sizeof(INT)); + if (! NT_SUCCESS(Status)) + { + goto fail; + } + } + + BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap); + if ( !BitmapObj ) + { + goto fail; + } + SurfObj = &BitmapObj->SurfObj; + ASSERT(SurfObj); + + Start.x = XStart; Start.y = YStart; + IntLPtoDP(dc, &Start, 1); + + RealXStart = (Start.x + dc->ptlDCOrig.x) << 6; + YStart = Start.y + dc->ptlDCOrig.y; + + /* Create the brushes */ + hDestPalette = BitmapObj->hDIBPalette; + if (!hDestPalette) hDestPalette = pPrimarySurface->DevInfo.hpalDefault; + PalDestGDI = PALETTE_LockPalette(hDestPalette); + if ( !PalDestGDI ) + Mode = PAL_RGB; + else + { + Mode = PalDestGDI->Mode; + PALETTE_UnlockPalette(PalDestGDI); + } + XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, hDestPalette, NULL); + if ( !XlateObj ) + { + goto fail; + } + hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, Dc_Attr->crForegroundClr), 0); + if ( !hBrushFg ) + { + goto fail; + } + BrushFg = BRUSHOBJ_LockBrush(hBrushFg); + if ( !BrushFg ) + { + goto fail; + } + IntGdiInitBrushInstance(&BrushFgInst, BrushFg, NULL); + if ((fuOptions & ETO_OPAQUE) || Dc_Attr->jBkMode == OPAQUE) + { + hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, Dc_Attr->crBackgroundClr), 0); + if ( !hBrushBg ) + { + goto fail; + } + BrushBg = BRUSHOBJ_LockBrush(hBrushBg); + if ( !BrushBg ) + { + goto fail; + } + IntGdiInitBrushInstance(&BrushBgInst, BrushBg, NULL); + } + XlateObj2 = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, hDestPalette); + if ( !XlateObj2 ) + { + goto fail; + } + + SourcePoint.x = 0; + SourcePoint.y = 0; + MaskRect.left = 0; + MaskRect.top = 0; + BrushOrigin.x = 0; + BrushOrigin.y = 0; + + if ((fuOptions & ETO_OPAQUE) && lprc) + { + DestRect.left = SpecifiedDestRect.left + dc->ptlDCOrig.x; + DestRect.top = SpecifiedDestRect.top + dc->ptlDCOrig.y; + DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x; + DestRect.bottom = SpecifiedDestRect.bottom + dc->ptlDCOrig.y; + IntLPtoDP(dc, (LPPOINT)&DestRect, 2); + IntEngBitBlt( + &BitmapObj->SurfObj, + NULL, + NULL, + dc->CombinedClip, + NULL, + &DestRect, + &SourcePoint, + &SourcePoint, + &BrushBgInst.BrushObject, + &BrushOrigin, + ROP3_TO_ROP4(PATCOPY)); + fuOptions &= ~ETO_OPAQUE; + } + else + { + if (Dc_Attr->jBkMode == OPAQUE) + { + fuOptions |= ETO_OPAQUE; + } + } + + TextObj = TEXTOBJ_LockText(Dc_Attr->hlfntNew); + if(TextObj == NULL) + { + goto fail; + } + + FontObj = TextObj->Font; + ASSERT(FontObj); + FontGDI = ObjToGDI(FontObj, FONT); + ASSERT(FontGDI); + + IntLockFreeType; + face = FontGDI->face; + if (face->charmap == NULL) + { + DPRINT("WARNING: No charmap selected!\n"); + DPRINT("This font face has %d charmaps\n", face->num_charmaps); + + for (n = 0; n < face->num_charmaps; n++) + { + charmap = face->charmaps[n]; + DPRINT("found charmap encoding: %u\n", charmap->encoding); + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + if (!found) + { + DPRINT1("WARNING: Could not find desired charmap!\n"); + } + error = FT_Set_Charmap(face, found); + if (error) + { + DPRINT1("WARNING: Could not set the charmap!\n"); + } + } + + Render = IntIsFontRenderingEnabled(); + if (Render) + RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont); + else + RenderMode = FT_RENDER_MODE_MONO; + + error = FT_Set_Pixel_Sizes( + face, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, + /* FIXME should set character height if neg */ + (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? + - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); + if (error) + { + DPRINT1("Error in setting pixel sizes: %u\n", error); + IntUnLockFreeType; + goto fail; + } + + /* + * Process the vertical alignment and determine the yoff. + */ + + if (Dc_Attr->lTextAlign & TA_BASELINE) + yoff = 0; + else if (Dc_Attr->lTextAlign & TA_BOTTOM) + yoff = -face->size->metrics.descender >> 6; + else /* TA_TOP */ + yoff = face->size->metrics.ascender >> 6; + + use_kerning = FT_HAS_KERNING(face); + previous = 0; + + /* + * Process the horizontal alignment and modify XStart accordingly. + */ + + if (Dc_Attr->lTextAlign & (TA_RIGHT | TA_CENTER)) + { + ULONGLONG TextWidth = 0; + LPCWSTR TempText = String; + int Start; + + /* + * Calculate width of the text. + */ + + if (NULL != Dx) + { + Start = Count < 2 ? 0 : Count - 2; + TextWidth = Count < 2 ? 0 : (Dx[Count - 2] << 6); + } + else + { + Start = 0; + } + TempText = String + Start; + + for (i = Start; i < Count; i++) + { + if (fuOptions & ETO_GLYPH_INDEX) + glyph_index = *TempText; + else + glyph_index = FT_Get_Char_Index(face, *TempText); + + if (!(realglyph = NtGdiGlyphCacheGet(face, glyph_index, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight))) + { + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (error) + { + DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index); + } + + glyph = face->glyph; + realglyph = NtGdiGlyphCacheSet(face, glyph_index, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode); + if (!realglyph) + { + DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index); + IntUnLockFreeType; + goto fail; + } + + } + /* retrieve kerning distance */ + if (use_kerning && previous && glyph_index) + { + FT_Vector delta; + FT_Get_Kerning(face, previous, glyph_index, 0, &delta); + TextWidth += delta.x; + } + + TextWidth += realglyph->advance.x >> 10; + + previous = glyph_index; + TempText++; + } + + previous = 0; + + if (Dc_Attr->lTextAlign & TA_RIGHT) + { + RealXStart -= TextWidth; + } + else + { + RealXStart -= TextWidth / 2; + } + } + + TextLeft = RealXStart; + TextTop = YStart; + BackgroundLeft = (RealXStart + 32) >> 6; + + /* + * The main rendering loop. + */ + + for (i = 0; i < Count; i++) + { + if (fuOptions & ETO_GLYPH_INDEX) + glyph_index = *String; + else + glyph_index = FT_Get_Char_Index(face, *String); + + if (!(realglyph = NtGdiGlyphCacheGet(face, glyph_index, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight))) + { + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (error) + { + DPRINT1("Failed to load and render glyph! [index: %u]\n", glyph_index); + IntUnLockFreeType; + goto fail; + } + glyph = face->glyph; + realglyph = NtGdiGlyphCacheSet(face, + glyph_index, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, + glyph, + RenderMode); + if (!realglyph) + { + DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index); + IntUnLockFreeType; + goto fail; + } + } +// DbgPrint("realglyph: %x\n", realglyph); +// DbgPrint("TextLeft: %d\n", TextLeft); + + /* retrieve kerning distance and move pen position */ + if (use_kerning && previous && glyph_index && NULL == Dx) + { + FT_Vector delta; + FT_Get_Kerning(face, previous, glyph_index, 0, &delta); + TextLeft += delta.x; + } +// DPRINT1("TextLeft: %d\n", TextLeft); +// DPRINT1("TextTop: %d\n", TextTop); + + if (realglyph->format == ft_glyph_format_outline) + { + DbgPrint("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 fail; + } + } + realglyph2 = (FT_BitmapGlyph)realglyph; + +// DPRINT1("Pitch: %d\n", pitch); +// DPRINT1("Advance: %d\n", realglyph->advance.x); + + if (fuOptions & ETO_OPAQUE) + { + DestRect.left = BackgroundLeft; + DestRect.right = (TextLeft + (realglyph->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( + &BitmapObj->SurfObj, + NULL, + NULL, + dc->CombinedClip, + NULL, + &DestRect, + &SourcePoint, + &SourcePoint, + &BrushBgInst.BrushObject, + &BrushOrigin, + ROP3_TO_ROP4(PATCOPY)); + 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; + + bitSize.cx = realglyph2->bitmap.width; + bitSize.cy = realglyph2->bitmap.rows; + MaskRect.right = realglyph2->bitmap.width; + MaskRect.bottom = realglyph2->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); + if ( !HSourceGlyph ) + { + DPRINT1("WARNING: EngLockSurface() failed!\n"); + // FT_Done_Glyph(realglyph); + IntUnLockFreeType; + goto fail; + } + SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph); + if ( !SourceGlyphSurf ) + { + EngDeleteSurface((HSURF)HSourceGlyph); + DPRINT1("WARNING: EngLockSurface() failed!\n"); + IntUnLockFreeType; + goto fail; + } + + /* + * Use the font data as a mask to paint onto the DCs surface using a + * brush. + */ + + if (lprc && + (fuOptions & ETO_CLIPPED) && + DestRect.right >= SpecifiedDestRect.right + dc->ptlDCOrig.x) + { + // We do the check '>=' instead of '>' to possibly save an iteration + // through this loop, since it's breaking after the drawing is done, + // and x is always incremented. + DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x; + DoBreak = TRUE; + } + + IntEngMaskBlt( + SurfObj, + SourceGlyphSurf, + dc->CombinedClip, + XlateObj, + XlateObj2, + &DestRect, + &SourcePoint, + (PPOINTL)&MaskRect, + &BrushFgInst.BrushObject, + &BrushOrigin); + + EngUnlockSurface(SourceGlyphSurf); + EngDeleteSurface((HSURF)HSourceGlyph); + + if (DoBreak) + { + break; + } + + if (NULL == Dx) + { + TextLeft += realglyph->advance.x >> 10; +// DbgPrint("new TextLeft: %d\n", TextLeft); + } + else + { + TextLeft += Dx[i] << 6; +// DbgPrint("new TextLeft2: %d\n", TextLeft); + } + previous = glyph_index; + + String++; + } + + IntUnLockFreeType; + + EngDeleteXlate(XlateObj); + EngDeleteXlate(XlateObj2); + BITMAPOBJ_UnlockBitmap(BitmapObj); + if(TextObj != NULL) + TEXTOBJ_UnlockText(TextObj); + if (hBrushBg != NULL) + { + BRUSHOBJ_UnlockBrush(BrushBg); + NtGdiDeleteObject(hBrushBg); + } + BRUSHOBJ_UnlockBrush(BrushFg); + NtGdiDeleteObject(hBrushFg); + if (NULL != SafeString) + { + ExFreePool((void*)SafeString); + } + if (NULL != Dx) + { + ExFreePool(Dx); + } + DC_UnlockDc( dc ); + + return TRUE; + +fail: + if ( XlateObj2 != NULL ) + EngDeleteXlate(XlateObj2); + if ( XlateObj != NULL ) + EngDeleteXlate(XlateObj); + if(TextObj != NULL) + TEXTOBJ_UnlockText(TextObj); + if (BitmapObj != NULL) + BITMAPOBJ_UnlockBitmap(BitmapObj); + if (hBrushBg != NULL) + { + BRUSHOBJ_UnlockBrush(BrushBg); + NtGdiDeleteObject(hBrushBg); + } + if (hBrushFg != NULL) + { + BRUSHOBJ_UnlockBrush(BrushFg); + NtGdiDeleteObject(hBrushFg); + } + if (NULL != SafeString) + { + ExFreePool((void*)SafeString); + } + if (NULL != Dx) + { + ExFreePool(Dx); + } + DC_UnlockDc(dc); + + return FALSE; +} + + /* + * @implemented + */ +BOOL +STDCALL +NtGdiGetCharABCWidthsW( + IN HDC hDC, + IN UINT FirstChar, + IN ULONG Count, + IN OPTIONAL PWCHAR pwch, + IN FLONG fl, + OUT PVOID Buffer) +{ + LPABC SafeBuff; + LPABCFLOAT SafeBuffF = NULL; + PDC dc; + PDC_ATTR Dc_Attr; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + FT_Face face; + FT_CharMap charmap, found = NULL; + UINT i, glyph_index, BufferSize; + HFONT hFont = 0; + NTSTATUS Status = STATUS_SUCCESS; + + if(pwch) + { + _SEH_TRY + { + ProbeForRead(pwch, + sizeof(PWSTR), + 1); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + if (!NT_SUCCESS(Status)) + { + SetLastWin32Error(Status); + return FALSE; + } + + BufferSize = Count * sizeof(ABC); // Same size! + SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT); + if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff; + if (SafeBuff == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + dc = DC_LockDc(hDC); + if (dc == NULL) + { + ExFreePool(SafeBuff); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + hFont = Dc_Attr->hlfntNew; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc(dc); + + if (TextObj == NULL) + { + ExFreePool(SafeBuff); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + FontGDI = ObjToGDI(TextObj->Font, FONT); + + face = FontGDI->face; + if (face->charmap == NULL) + { + for (i = 0; i < face->num_charmaps; i++) + { + charmap = face->charmaps[i]; + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + + if (!found) + { + DPRINT1("WARNING: Could not find desired charmap!\n"); + ExFreePool(SafeBuff); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + IntLockFreeType; + FT_Set_Charmap(face, found); + IntUnLockFreeType; + } + + IntLockFreeType; + FT_Set_Pixel_Sizes(face, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, + /* FIXME should set character height if neg */ + (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); + + for (i = FirstChar; i < FirstChar+Count; i++) + { + int adv, lsb, bbx, left, right; + + if (pwch) + { + if (fl & GCABCW_INDICES) + glyph_index = pwch[i - FirstChar]; + else + glyph_index = FT_Get_Char_Index(face, pwch[i - FirstChar]); + } + else + { + if (fl & GCABCW_INDICES) + glyph_index = i; + else + glyph_index = FT_Get_Char_Index(face, i); + } + FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + + left = (INT)face->glyph->metrics.horiBearingX & -64; + right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64; + adv = (face->glyph->advance.x + 32) >> 6; + +// int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6; +// DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same!*/ + + lsb = left >> 6; + bbx = (right - left) >> 6; +/* + DPRINT1("lsb %d and bbx %d\n", lsb, bbx ); + */ + if (!fl) + { + SafeBuffF[i - FirstChar].abcfA = (FLOAT) lsb; + SafeBuffF[i - FirstChar].abcfB = (FLOAT) bbx; + SafeBuffF[i - FirstChar].abcfC = (FLOAT) (adv - lsb - bbx); + } + else + { + SafeBuff[i - FirstChar].abcA = lsb; + SafeBuff[i - FirstChar].abcB = bbx; + SafeBuff[i - FirstChar].abcC = adv - lsb - bbx; + } + } + IntUnLockFreeType; + TEXTOBJ_UnlockText(TextObj); + Status = MmCopyToCaller(Buffer, SafeBuff, BufferSize); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + ExFreePool(SafeBuff); + return FALSE; + } + ExFreePool(SafeBuff); + DPRINT("NtGdiGetCharABCWidths Worked!\n"); + return TRUE; +} + + /* + * @implemented + */ +BOOL +STDCALL +NtGdiGetCharWidthW( + IN HDC hDC, + IN UINT FirstChar, + IN UINT Count, + IN OPTIONAL PWCHAR pwc, + IN FLONG fl, + OUT PVOID Buffer) +{ + NTSTATUS Status = STATUS_SUCCESS; + LPINT SafeBuff; + PFLOAT SafeBuffF = NULL; + PDC dc; + PDC_ATTR Dc_Attr; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + FT_Face face; + FT_CharMap charmap, found = NULL; + UINT i, glyph_index, BufferSize; + HFONT hFont = 0; + + if(pwc) + { + _SEH_TRY + { + ProbeForRead(pwc, + sizeof(PWSTR), + 1); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + if (!NT_SUCCESS(Status)) + { + SetLastWin32Error(Status); + return FALSE; + } + + BufferSize = Count * sizeof(INT); // Same size! + SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT); + if (!fl) SafeBuffF = (PFLOAT) SafeBuff; + if (SafeBuff == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + dc = DC_LockDc(hDC); + if (dc == NULL) + { + ExFreePool(SafeBuff); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + hFont = Dc_Attr->hlfntNew; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc(dc); + + if (TextObj == NULL) + { + ExFreePool(SafeBuff); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + FontGDI = ObjToGDI(TextObj->Font, FONT); + + face = FontGDI->face; + if (face->charmap == NULL) + { + for (i = 0; i < face->num_charmaps; i++) + { + charmap = face->charmaps[i]; + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + + if (!found) + { + DPRINT1("WARNING: Could not find desired charmap!\n"); + ExFreePool(SafeBuff); + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + IntLockFreeType; + FT_Set_Charmap(face, found); + IntUnLockFreeType; + } + + IntLockFreeType; + FT_Set_Pixel_Sizes(face, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, + /* FIXME should set character height if neg */ + (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? + - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); + + for (i = FirstChar; i < FirstChar+Count; i++) + { + if (pwc) + { + if (fl & GCW_INDICES) + glyph_index = pwc[i - FirstChar]; + else + glyph_index = FT_Get_Char_Index(face, pwc[i - FirstChar]); + } + else + { + if (fl & GCW_INDICES) + glyph_index = i; + else + glyph_index = FT_Get_Char_Index(face, i); + } + FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (!fl) + SafeBuffF[i - FirstChar] = (FLOAT) ((face->glyph->advance.x + 32) >> 6); + else + SafeBuff[i - FirstChar] = (face->glyph->advance.x + 32) >> 6; + } + IntUnLockFreeType; + TEXTOBJ_UnlockText(TextObj); + MmCopyToCaller(Buffer, SafeBuff, BufferSize); + ExFreePool(SafeBuff); + return TRUE; +} + + + /* + * @implemented + */ +DWORD +STDCALL +NtGdiGetGlyphIndicesW( + IN HDC hdc, + IN OPTIONAL LPWSTR UnSafepwc, + IN INT cwc, + OUT OPTIONAL LPWORD UnSafepgi, + IN DWORD iMode) +{ + PDC dc; + PDC_ATTR Dc_Attr; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + HFONT hFont = 0; + NTSTATUS Status = STATUS_SUCCESS; + OUTLINETEXTMETRICW *potm; + INT i; + FT_Face face; + WCHAR DefChar = 0; + PWSTR Buffer = NULL; + ULONG Size; + + if ((!UnSafepwc) && (!UnSafepgi)) return cwc; + + dc = DC_LockDc(hdc); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return GDI_ERROR; + } + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + hFont = Dc_Attr->hlfntNew; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc(dc); + if (!TextObj) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return GDI_ERROR; + } + + FontGDI = ObjToGDI(TextObj->Font, FONT); + TEXTOBJ_UnlockText(TextObj); + + Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), TAG_GDITEXT); + if (!Buffer) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return GDI_ERROR; + } + + if (iMode & GGI_MARK_NONEXISTING_GLYPHS) DefChar = 0x001f; /* Indicate non existence */ + else + { + Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); + potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); + if (!potm) + { + Status = ERROR_NOT_ENOUGH_MEMORY; + goto ErrorRet; + } + IntGetOutlineTextMetrics(FontGDI, Size, potm); + DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this. + ExFreePool(potm); + } + + _SEH_TRY + { + ProbeForRead(UnSafepwc, + sizeof(PWSTR), + 1); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) goto ErrorRet; + + IntLockFreeType; + face = FontGDI->face; + + for (i = 0; i < cwc; i++) + { + Buffer[i] = FT_Get_Char_Index(face, UnSafepwc[i]); + if (Buffer[i] == 0) Buffer[i] = DefChar; + } + + IntUnLockFreeType; + + _SEH_TRY + { + ProbeForWrite(UnSafepgi, + sizeof(WORD), + 1); + RtlCopyMemory(UnSafepgi, + Buffer, + cwc*sizeof(WORD)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + +ErrorRet: + ExFreePool(Buffer); + if (NT_SUCCESS(Status)) return cwc; + SetLastWin32Error(Status); + return GDI_ERROR; +} + +static +void +FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt) +{ + pt->x.value = vec->x >> 6; + pt->x.fract = (vec->x & 0x3f) << 10; + pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12)); + pt->y.value = vec->y >> 6; + pt->y.fract = (vec->y & 0x3f) << 10; + pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12)); + return; +} + +/* + This function builds an FT_Fixed from a float. It puts the integer part + in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed. + It fails if the integer part of the float number is greater than SHORT_MAX. +*/ +static __inline FT_Fixed FT_FixedFromFloat(float f) +{ + short value = f; + unsigned short fract = (f - value) * 0xFFFF; + return (FT_Fixed)((long)value << 16 | (unsigned long)fract); +} + +/* + This function builds an FT_Fixed from a FIXED. It simply put f.value + in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed. +*/ +static __inline FT_Fixed FT_FixedFromFIXED(FIXED f) +{ + return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract); +} + +/* + * Based on WineEngGetGlyphOutline + * + */ +ULONG +FASTCALL +ftGdiGetGlyphOutline( + IN PDC dc, + IN WCHAR wch, + IN UINT iFormat, + OUT LPGLYPHMETRICS pgm, + IN ULONG cjBuf, + OUT OPTIONAL PVOID UnsafeBuf, + IN LPMAT2 pmat2, + IN BOOL bIgnoreRotation) +{ + static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)}; + PDC_ATTR Dc_Attr; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + HFONT hFont = 0; + NTSTATUS Status; + GLYPHMETRICS gm; + ULONG Size; + FT_Face ft_face; + FT_UInt glyph_index; + DWORD width, height, pitch, needed = 0; + FT_Bitmap ft_bitmap; + FT_Error error; + INT left, right, top = 0, bottom = 0; + FT_Angle angle = 0; + FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; + FLOAT eM11, widthRatio = 1.0; + FT_Matrix transMat = identityMat; + BOOL needsTransform = FALSE; + INT orientation; + LONG aveWidth; + INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */ + OUTLINETEXTMETRICW *potm; + PVOID pvBuf = NULL; + int n = 0; + FT_CharMap found = 0, charmap; + XFORM xForm; + + DPRINT("%d, %08x, %p, %08lx, %p, %p\n", wch, iFormat, pgm, + cjBuf, UnsafeBuf, pmat2); + + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + + MatrixS2XForm(&xForm, &dc->DcLevel.mxWorldToDevice); + eM11 = xForm.eM11; + + hFont = Dc_Attr->hlfntNew; + TextObj = TEXTOBJ_LockText(hFont); +// DC_UnlockDc(dc); + if (!TextObj) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return GDI_ERROR; + } + FontGDI = ObjToGDI(TextObj->Font, FONT); + ft_face = FontGDI->face; + + aveWidth = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth: 0; + orientation = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation: 0; + + Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); + potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); + if (!potm) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + TEXTOBJ_UnlockText(TextObj); + return GDI_ERROR; + } + IntGetOutlineTextMetrics(FontGDI, Size, potm); + + IntLockFreeType; + + /* During testing, I never saw this used. In here just incase.*/ + if (ft_face->charmap == NULL) + { + DPRINT("WARNING: No charmap selected!\n"); + DPRINT("This font face has %d charmaps\n", ft_face->num_charmaps); + + + + for (n = 0; n < ft_face->num_charmaps; n++) + { + charmap = ft_face->charmaps[n]; + DPRINT("found charmap encoding: %u\n", charmap->encoding); + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + if (!found) + { + DPRINT1("WARNING: Could not find desired charmap!\n"); + } + error = FT_Set_Charmap(ft_face, found); + if (error) + { + DPRINT1("WARNING: Could not set the charmap!\n"); + } + } + +// FT_Set_Pixel_Sizes(ft_face, +// TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, + /* FIXME should set character height if neg */ +// (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : +// TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); + + TEXTOBJ_UnlockText(TextObj); + + if (iFormat & GGO_GLYPH_INDEX) + { + glyph_index = wch; + iFormat &= ~GGO_GLYPH_INDEX; + } + else glyph_index = FT_Get_Char_Index(ft_face, wch); + + if (orientation || (iFormat != GGO_METRICS && iFormat != GGO_BITMAP) || aveWidth || pmat2) + load_flags |= FT_LOAD_NO_BITMAP; + + if (iFormat & GGO_UNHINTED) + { + load_flags |= FT_LOAD_NO_HINTING; + iFormat &= ~GGO_UNHINTED; + } + + error = FT_Load_Glyph(ft_face, glyph_index, load_flags); + if (error) + { + DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index); + IntUnLockFreeType; + if (potm) ExFreePool(potm); + return GDI_ERROR; + } + IntUnLockFreeType; + + if (aveWidth && potm) + { + widthRatio = (FLOAT)aveWidth * eM11 / + (FLOAT) potm->otmTextMetrics.tmAveCharWidth; + } + + left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64; + right = (INT)((ft_face->glyph->metrics.horiBearingX + + ft_face->glyph->metrics.width) * widthRatio + 63) & -64; + + adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6; + lsb = left >> 6; + bbx = (right - left) >> 6; + + DPRINT("Advance = %d, lsb = %d, bbx = %d\n",adv, lsb, bbx); + + IntLockFreeType; + + /* Scaling transform */ + if (aveWidth) + { + FT_Matrix scaleMat; + DPRINT("Scaling Trans!\n"); + scaleMat.xx = FT_FixedFromFloat(widthRatio); + scaleMat.xy = 0; + scaleMat.yx = 0; + scaleMat.yy = (1 << 16); + FT_Matrix_Multiply(&scaleMat, &transMat); + needsTransform = TRUE; + } + + /* Slant transform */ + if (potm->otmTextMetrics.tmItalic) + { + FT_Matrix slantMat; + DPRINT("Slant Trans!\n"); + slantMat.xx = (1 << 16); + slantMat.xy = ((1 << 16) >> 2); + slantMat.yx = 0; + slantMat.yy = (1 << 16); + FT_Matrix_Multiply(&slantMat, &transMat); + needsTransform = TRUE; + } + + /* Rotation transform */ + if (orientation) + { + FT_Matrix rotationMat; + FT_Vector vecAngle; + DPRINT("Rotation Trans!\n"); + angle = FT_FixedFromFloat((float)orientation / 10.0); + FT_Vector_Unit(&vecAngle, angle); + rotationMat.xx = vecAngle.x; + rotationMat.xy = -vecAngle.y; + rotationMat.yx = -rotationMat.xy; + rotationMat.yy = rotationMat.xx; + FT_Matrix_Multiply(&rotationMat, &transMat); + needsTransform = TRUE; + } + + /* Extra transformation specified by caller */ + if (pmat2) + { + FT_Matrix extraMat; + DPRINT("MAT2 Matrix Trans!\n"); + extraMat.xx = FT_FixedFromFIXED(pmat2->eM11); + extraMat.xy = FT_FixedFromFIXED(pmat2->eM21); + extraMat.yx = FT_FixedFromFIXED(pmat2->eM12); + extraMat.yy = FT_FixedFromFIXED(pmat2->eM22); + FT_Matrix_Multiply(&extraMat, &transMat); + needsTransform = TRUE; + } + + if (potm) ExFreePool(potm); /* It looks like we are finished with potm ATM.*/ + + if (!needsTransform) + { + DPRINT("No Need to be Transformed!\n"); + top = (ft_face->glyph->metrics.horiBearingY + 63) & -64; + bottom = (ft_face->glyph->metrics.horiBearingY - + ft_face->glyph->metrics.height) & -64; + gm.gmCellIncX = adv; + gm.gmCellIncY = 0; + } + else + { + INT xc, yc; + FT_Vector vec; + for(xc = 0; xc < 2; xc++) + { + for(yc = 0; yc < 2; yc++) + { + vec.x = (ft_face->glyph->metrics.horiBearingX + + xc * ft_face->glyph->metrics.width); + vec.y = ft_face->glyph->metrics.horiBearingY - + yc * ft_face->glyph->metrics.height; + DPRINT("Vec %ld,%ld\n", vec.x, vec.y); + FT_Vector_Transform(&vec, &transMat); + if(xc == 0 && yc == 0) + { + left = right = vec.x; + top = bottom = vec.y; + } + else + { + if(vec.x < left) left = vec.x; + else if(vec.x > right) right = vec.x; + if(vec.y < bottom) bottom = vec.y; + else if(vec.y > top) top = vec.y; + } + } + } + left = left & -64; + right = (right + 63) & -64; + bottom = bottom & -64; + top = (top + 63) & -64; + + DPRINT("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom); + vec.x = ft_face->glyph->metrics.horiAdvance; + vec.y = 0; + FT_Vector_Transform(&vec, &transMat); + gm.gmCellIncX = (vec.x+63) >> 6; + gm.gmCellIncY = -((vec.y+63) >> 6); + } + gm.gmBlackBoxX = (right - left) >> 6; + gm.gmBlackBoxY = (top - bottom) >> 6; + gm.gmptGlyphOrigin.x = left >> 6; + gm.gmptGlyphOrigin.y = top >> 6; + + DPRINT("CX %d CY %d BBX %d BBY %d GOX %d GOY %d\n", + gm.gmCellIncX, gm.gmCellIncY, + gm.gmBlackBoxX, gm.gmBlackBoxY, + gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y); + + IntUnLockFreeType; + + if (pgm) + { + Status = MmCopyToCaller(pgm, &gm, sizeof(GLYPHMETRICS)); + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return GDI_ERROR; + } + DPRINT("Copied GLYPHMETRICS to User!\n"); + } + + if (iFormat == GGO_METRICS) + { + DPRINT("GGO_METRICS Exit!\n"); + return 1; /* FIXME */ + } + + if (ft_face->glyph->format != ft_glyph_format_outline && iFormat != GGO_BITMAP) + { + DPRINT1("loaded a bitmap\n"); + return GDI_ERROR; + } + + if (UnsafeBuf && cjBuf) + { + pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT); + if (pvBuf == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return GDI_ERROR; + } + RtlZeroMemory(pvBuf, cjBuf); + } + + + switch(iFormat) + { + case GGO_BITMAP: + width = gm.gmBlackBoxX; + height = gm.gmBlackBoxY; + pitch = ((width + 31) >> 5) << 2; + needed = pitch * height; + + if(!pvBuf || !cjBuf) break; + + switch(ft_face->glyph->format) + { + case ft_glyph_format_bitmap: + { + BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf; + INT w = (ft_face->glyph->bitmap.width + 7) >> 3; + INT h = ft_face->glyph->bitmap.rows; + while(h--) + { + RtlCopyMemory(dst, src, w); + src += ft_face->glyph->bitmap.pitch; + dst += pitch; + } + break; + } + + case ft_glyph_format_outline: + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = pitch; + ft_bitmap.pixel_mode = ft_pixel_mode_mono; + ft_bitmap.buffer = pvBuf; + + IntLockFreeType; + if(needsTransform) + { + FT_Outline_Transform(&ft_face->glyph->outline, &transMat); + } + FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); + /* Note: FreeType will only set 'black' bits for us. */ + RtlZeroMemory(pvBuf, needed); + FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); + IntUnLockFreeType; + break; + + default: + DPRINT1("loaded glyph format %x\n", ft_face->glyph->format); + if(pvBuf) ExFreePool(pvBuf); + return GDI_ERROR; + } + break; + + case GGO_GRAY2_BITMAP: + case GGO_GRAY4_BITMAP: + case GGO_GRAY8_BITMAP: + { + unsigned int mult, row, col; + BYTE *start, *ptr; + + width = gm.gmBlackBoxX; + height = gm.gmBlackBoxY; + pitch = (width + 3) / 4 * 4; + needed = pitch * height; + + if(!pvBuf || !cjBuf) break; + + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = pitch; + ft_bitmap.pixel_mode = ft_pixel_mode_grays; + ft_bitmap.buffer = pvBuf; + + IntLockFreeType; + if(needsTransform) + { + FT_Outline_Transform(&ft_face->glyph->outline, &transMat); + } + FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); + RtlZeroMemory(ft_bitmap.buffer, cjBuf); + FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); + IntUnLockFreeType; + + if(iFormat == GGO_GRAY2_BITMAP) + mult = 4; + else if(iFormat == GGO_GRAY4_BITMAP) + mult = 16; + else if(iFormat == GGO_GRAY8_BITMAP) + mult = 64; + else + { + ASSERT(0); + break; + } + + start = pvBuf; + for(row = 0; row < height; row++) + { + ptr = start; + for(col = 0; col < width; col++, ptr++) + { + *ptr = (((int)*ptr) * mult + 128) / 256; + } + start += pitch; + } + break; + } + + case GGO_NATIVE: + { + int contour, point = 0, first_pt; + FT_Outline *outline = &ft_face->glyph->outline; + TTPOLYGONHEADER *pph; + TTPOLYCURVE *ppc; + DWORD pph_start, cpfx, type; + + if(cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */ + + IntLockFreeType; + if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat); + + for(contour = 0; contour < outline->n_contours; contour++) + { + pph_start = needed; + pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed); + first_pt = point; + if(pvBuf) + { + pph->dwType = TT_POLYGON_TYPE; + FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart); + } + needed += sizeof(*pph); + point++; + while(point <= outline->contours[contour]) + { + ppc = (TTPOLYCURVE *)((char *)pvBuf + needed); + type = (outline->tags[point] & FT_Curve_Tag_On) ? + TT_PRIM_LINE : TT_PRIM_QSPLINE; + cpfx = 0; + do + { + if(pvBuf) + FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); + cpfx++; + point++; + } while(point <= outline->contours[contour] && + (outline->tags[point] & FT_Curve_Tag_On) == + (outline->tags[point-1] & FT_Curve_Tag_On)); + + /* At the end of a contour Windows adds the start point, but + only for Beziers */ + if(point > outline->contours[contour] && + !(outline->tags[point-1] & FT_Curve_Tag_On)) + { + if(pvBuf) + FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]); + cpfx++; + } + else if(point <= outline->contours[contour] && + outline->tags[point] & FT_Curve_Tag_On) + { + /* add closing pt for bezier */ + if(pvBuf) + FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); + cpfx++; + point++; + } + if(pvBuf) + { + ppc->wType = type; + ppc->cpfx = cpfx; + } + needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX); + } + if(pvBuf) pph->cb = needed - pph_start; + } + IntUnLockFreeType; + break; + } + case GGO_BEZIER: + { + /* Convert the quadratic Beziers to cubic Beziers. + The parametric eqn for a cubic Bezier is, from PLRM: + r(t) = at^3 + bt^2 + ct + r0 + with the control points: + r1 = r0 + c/3 + r2 = r1 + (c + b)/3 + r3 = r0 + c + b + a + + A quadratic Beizer has the form: + p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2 + + So equating powers of t leads to: + r1 = 2/3 p1 + 1/3 p0 + r2 = 2/3 p1 + 1/3 p2 + and of course r0 = p0, r3 = p2 + */ + + int contour, point = 0, first_pt; + FT_Outline *outline = &ft_face->glyph->outline; + TTPOLYGONHEADER *pph; + TTPOLYCURVE *ppc; + DWORD pph_start, cpfx, type; + FT_Vector cubic_control[4]; + if(cjBuf == 0) pvBuf = NULL; + + if (needsTransform && pvBuf) + { + IntLockFreeType; + FT_Outline_Transform(outline, &transMat); + IntUnLockFreeType; + } + + for(contour = 0; contour < outline->n_contours; contour++) + { + pph_start = needed; + pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed); + first_pt = point; + if(pvBuf) + { + pph->dwType = TT_POLYGON_TYPE; + FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart); + } + needed += sizeof(*pph); + point++; + while(point <= outline->contours[contour]) + { + ppc = (TTPOLYCURVE *)((char *)pvBuf + needed); + type = (outline->tags[point] & FT_Curve_Tag_On) ? + TT_PRIM_LINE : TT_PRIM_CSPLINE; + cpfx = 0; + do + { + if(type == TT_PRIM_LINE) + { + if(pvBuf) + FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); + cpfx++; + point++; + } + else + { + /* Unlike QSPLINEs, CSPLINEs always have their endpoint + so cpfx = 3n */ + + /* FIXME: Possible optimization in endpoint calculation + if there are two consecutive curves */ + cubic_control[0] = outline->points[point-1]; + if(!(outline->tags[point-1] & FT_Curve_Tag_On)) + { + cubic_control[0].x += outline->points[point].x + 1; + cubic_control[0].y += outline->points[point].y + 1; + cubic_control[0].x >>= 1; + cubic_control[0].y >>= 1; + } + if(point+1 > outline->contours[contour]) + cubic_control[3] = outline->points[first_pt]; + else + { + cubic_control[3] = outline->points[point+1]; + if(!(outline->tags[point+1] & FT_Curve_Tag_On)) + { + cubic_control[3].x += outline->points[point].x + 1; + cubic_control[3].y += outline->points[point].y + 1; + cubic_control[3].x >>= 1; + cubic_control[3].y >>= 1; + } + } + /* r1 = 1/3 p0 + 2/3 p1 + r2 = 1/3 p2 + 2/3 p1 */ + cubic_control[1].x = (2 * outline->points[point].x + 1) / 3; + cubic_control[1].y = (2 * outline->points[point].y + 1) / 3; + cubic_control[2] = cubic_control[1]; + cubic_control[1].x += (cubic_control[0].x + 1) / 3; + cubic_control[1].y += (cubic_control[0].y + 1) / 3; + cubic_control[2].x += (cubic_control[3].x + 1) / 3; + cubic_control[2].y += (cubic_control[3].y + 1) / 3; + if(pvBuf) + { + FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]); + FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]); + FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]); + } + cpfx += 3; + point++; + } + } + while(point <= outline->contours[contour] && + (outline->tags[point] & FT_Curve_Tag_On) == + (outline->tags[point-1] & FT_Curve_Tag_On)); + /* At the end of a contour Windows adds the start point, + but only for Beziers and we've already done that. + */ + if(point <= outline->contours[contour] && + outline->tags[point] & FT_Curve_Tag_On) + { + /* This is the closing pt of a bezier, but we've already + added it, so just inc point and carry on */ + point++; + } + if(pvBuf) + { + ppc->wType = type; + ppc->cpfx = cpfx; + } + needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX); + } + if(pvBuf) pph->cb = needed - pph_start; + } + break; + } + + default: + DPRINT1("Unsupported format %d\n", iFormat); + if(pvBuf) ExFreePool(pvBuf); + return GDI_ERROR; + } + + if (pvBuf) + { + Status = MmCopyToCaller(UnsafeBuf, pvBuf, cjBuf); + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + ExFreePool(pvBuf); + return GDI_ERROR; + } + DPRINT("NtGdiGetGlyphOutline K -> U worked!\n"); + ExFreePool(pvBuf); + } + + DPRINT("NtGdiGetGlyphOutline END and needed %d\n", needed); + return needed; +} + +BOOL +FASTCALL +TextIntGetTextExtentPoint(PDC dc, + PTEXTOBJ TextObj, + LPCWSTR String, + int Count, + int MaxExtent, + LPINT Fit, + LPINT Dx, + LPSIZE Size) +{ + PFONTGDI FontGDI; + FT_Face face; + FT_GlyphSlot glyph; + FT_Glyph realglyph; + INT error, n, glyph_index, i, previous; + ULONGLONG TotalWidth = 0; + FT_CharMap charmap, found = NULL; + BOOL use_kerning; + FT_Render_Mode RenderMode; + BOOLEAN Render; + + FontGDI = ObjToGDI(TextObj->Font, FONT); + + face = FontGDI->face; + if (NULL != Fit) + { + *Fit = 0; + } + + IntLockFreeType; + if (face->charmap == NULL) + { + DPRINT("WARNING: No charmap selected!\n"); + DPRINT("This font face has %d charmaps\n", face->num_charmaps); + + for (n = 0; n < face->num_charmaps; n++) + { + charmap = face->charmaps[n]; + DPRINT("found charmap encoding: %u\n", charmap->encoding); + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + + if (! found) + { + DPRINT1("WARNING: Could not find desired charmap!\n"); + } + + error = FT_Set_Charmap(face, found); + if (error) + { + DPRINT1("WARNING: Could not set the charmap!\n"); + } + } + + Render = IntIsFontRenderingEnabled(); + if (Render) + RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont); + else + RenderMode = FT_RENDER_MODE_MONO; + + error = FT_Set_Pixel_Sizes(face, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, + /* FIXME should set character height if neg */ + (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? + - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); + if (error) + { + DPRINT1("Error in setting pixel sizes: %u\n", error); + } + + use_kerning = FT_HAS_KERNING(face); + previous = 0; + + for (i = 0; i < Count; i++) + { + glyph_index = FT_Get_Char_Index(face, *String); + if (!(realglyph = NtGdiGlyphCacheGet(face, glyph_index, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight))) + { + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (error) + { + DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index); + break; + } + + glyph = face->glyph; + realglyph = NtGdiGlyphCacheSet(face, glyph_index, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode); + if (!realglyph) + { + DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index); + break; + } + } + + /* retrieve kerning distance */ + if (use_kerning && previous && glyph_index) + { + FT_Vector delta; + FT_Get_Kerning(face, previous, glyph_index, 0, &delta); + TotalWidth += delta.x; + } + + TotalWidth += realglyph->advance.x >> 10; + + if (((TotalWidth + 32) >> 6) <= MaxExtent && NULL != Fit) + { + *Fit = i + 1; + } + if (NULL != Dx) + { + Dx[i] = (TotalWidth + 32) >> 6; + } + + previous = glyph_index; + String++; + } + IntUnLockFreeType; + + Size->cx = (TotalWidth + 32) >> 6; + Size->cy = (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight); + Size->cy = EngMulDiv(Size->cy, IntGdiGetDeviceCaps(dc, LOGPIXELSY), 72); + + return TRUE; +} + + +DWORD +FASTCALL +IntGdiGetCharSet(HDC hDC) +{ + UINT cp = 0; + CHARSETINFO csi; + DWORD charset = NtGdiGetTextCharsetInfo(hDC,NULL,0); + if (IntTranslateCharsetInfo(&charset, &csi, TCI_SRCCHARSET)) + cp = csi.ciACP; + else + { + switch(charset) + { + case OEM_CHARSET: + cp = 1; + break; + case DEFAULT_CHARSET: + cp = 0; + break; + default: + DPRINT1("Can't find codepage for charset %d\n", charset); + break; + } + } + DPRINT("charset %d => cp %d\n", charset, LOWORD(cp)); + return (MAKELONG(cp, charset)); +} + + +DWORD +APIENTRY +NtGdiGetCharSet(HDC hDC) +{ + PDC Dc; + PDC_ATTR Dc_Attr; + DWORD cscp = IntGdiGetCharSet(hDC); + // If here, update everything! + Dc = DC_LockDc(hDC); + if (!Dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return 0; + } + Dc_Attr = Dc->pDc_Attr; + if (!Dc_Attr) Dc_Attr = &Dc->Dc_Attr; + Dc_Attr->iCS_CP = cscp; + Dc_Attr->ulDirty_ &= ~DIRTY_CHARSET; + DC_UnlockDc( Dc ); + return cscp; +} + + +INT +APIENTRY +NtGdiGetTextCharsetInfo( + IN HDC hdc, + OUT OPTIONAL LPFONTSIGNATURE lpSig, + IN DWORD dwFlags) +{ + PDC Dc; + PDC_ATTR Dc_Attr; + UINT Ret = DEFAULT_CHARSET, i = 0, fs_fsCsb0 = 0; + HFONT hFont; + PTEXTOBJ TextObj; + PFONTGDI FontGdi; + FONTSIGNATURE fs; + TT_OS2 *pOS2; + FT_Face Face; + NTSTATUS Status; + + Dc = DC_LockDc(hdc); + if (!Dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return Ret; + } + Dc_Attr = Dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr; + hFont = Dc_Attr->hlfntNew; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc( Dc ); + if ( TextObj == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return Ret; + } + FontGdi = ObjToGDI(TextObj->Font, FONT); + Face = FontGdi->face; + TEXTOBJ_UnlockText(TextObj); + IntLockFreeType; + pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2); + IntUnLockFreeType; + memset(&fs, 0, sizeof(FONTSIGNATURE)); + if (NULL != pOS2) + { + fs.fsCsb[0] = pOS2->ulCodePageRange1; + fs.fsCsb[1] = pOS2->ulCodePageRange2; + fs.fsUsb[0] = pOS2->ulUnicodeRange1; + fs.fsUsb[1] = pOS2->ulUnicodeRange2; + fs.fsUsb[2] = pOS2->ulUnicodeRange3; + fs.fsUsb[3] = pOS2->ulUnicodeRange4; + fs_fsCsb0 = pOS2->ulCodePageRange1; + if (pOS2->version == 0) + { + FT_UInt dummy; + + if(FT_Get_First_Char( Face, &dummy ) < 0x100) + fs_fsCsb0 |= 1; + else + fs_fsCsb0 |= 1L << 31; + } + } + DPRINT("Csb 1=%x 0=%x\n", fs.fsCsb[1],fs.fsCsb[0]); + if (lpSig) + { + Status = MmCopyToCaller(lpSig, &fs, sizeof(FONTSIGNATURE)); + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return Ret; + } + } + if (0 == fs_fsCsb0) + { /* let's see if we can find any interesting cmaps */ + for (i = 0; i < Face->num_charmaps; i++) + { + switch (Face->charmaps[i]->encoding) + { + case ft_encoding_unicode: + case ft_encoding_apple_roman: + fs_fsCsb0 |= 1; + break; + case ft_encoding_symbol: + fs_fsCsb0 |= 1L << 31; + break; + default: + break; + } + } + } + while (0 == (fs_fsCsb0 >> i & 0x0001) && i < MAXTCIINDEX) + { + i++; + } + Ret = FontTci[i].ciCharset; + DPRINT("CharSet %d\n",Ret); + return Ret; +} + +W32KAPI +BOOL +APIENTRY +NtGdiGetTextMetricsW( + IN HDC hDC, + OUT TMW_INTERNAL * pUnsafeTmwi, + IN ULONG cj +) +{ + PDC dc; + PDC_ATTR Dc_Attr; + PTEXTOBJ TextObj; + PFONTGDI FontGDI; + NTSTATUS Status = STATUS_SUCCESS; + TMW_INTERNAL tmwi; + FT_Face Face; + TT_OS2 *pOS2; + TT_HoriHeader *pHori; + ULONG Error; + + if (NULL == pUnsafeTmwi) + { + SetLastWin32Error(STATUS_INVALID_PARAMETER); + return FALSE; + } + + /* FIXME: check cj ? */ + + if(!(dc = DC_LockDc(hDC))) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + TextObj = TEXTOBJ_LockText(Dc_Attr->hlfntNew); + if (NULL != TextObj) + { + FontGDI = ObjToGDI(TextObj->Font, FONT); + + Face = FontGDI->face; + IntLockFreeType; + Error = FT_Set_Pixel_Sizes(Face, + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, + /* FIXME should set character height if neg */ + (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? + - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); + IntUnLockFreeType; + if (0 != Error) + { + DPRINT1("Error in setting pixel sizes: %u\n", Error); + Status = STATUS_UNSUCCESSFUL; + } + else + { + memcpy(&tmwi.TextMetric, &FontGDI->TextMetric, sizeof(TEXTMETRICW)); + /* FIXME: Fill Diff member */ + RtlZeroMemory(&tmwi.Diff, sizeof(tmwi.Diff)); + + Status = STATUS_SUCCESS; + IntLockFreeType; + pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2); + if (NULL == pOS2) + { + DPRINT1("Can't find OS/2 table - not TT font?\n"); + Status = STATUS_INTERNAL_ERROR; + } + + pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea); + if (NULL == pHori) + { + DPRINT1("Can't find HHEA table - not TT font?\n"); + Status = STATUS_INTERNAL_ERROR; + } + + IntUnLockFreeType; + + if (NT_SUCCESS(Status)) + { + FillTM(&tmwi.TextMetric, FontGDI->face, pOS2, pHori); + + if (cj > sizeof(TMW_INTERNAL)) + cj = sizeof(TMW_INTERNAL); + + Status = STATUS_SUCCESS; + _SEH_TRY + { + ProbeForWrite(pUnsafeTmwi, cj, 1); + RtlCopyMemory(pUnsafeTmwi,&tmwi,cj); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END + } + } + TEXTOBJ_UnlockText(TextObj); + } + else + { + Status = STATUS_INVALID_HANDLE; + } + DC_UnlockDc(dc); + + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + + return TRUE; +} + + +DWORD STDCALL +NtGdiGetFontData( + HDC hDC, + DWORD Table, + DWORD Offset, + LPVOID Buffer, + DWORD Size) +{ + PDC Dc; + PDC_ATTR Dc_Attr; + HFONT hFont; + PTEXTOBJ TextObj; + PFONTGDI FontGdi; + DWORD Result = GDI_ERROR; + + Dc = DC_LockDc(hDC); + if (Dc == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return GDI_ERROR; + } + Dc_Attr = Dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr; + hFont = Dc_Attr->hlfntNew; + TextObj = TEXTOBJ_LockText(hFont); + DC_UnlockDc(Dc); + + if (TextObj == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return GDI_ERROR; + } + + FontGdi = ObjToGDI(TextObj->Font, FONT); + + IntLockFreeType; + + if (FT_IS_SFNT(FontGdi->face)) + { + if (Table) + Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) | + (Table << 8 & 0xFF0000); + + if (Buffer == NULL) + Size = 0; + + if (!FT_Load_Sfnt_Table(FontGdi->face, Table, Offset, Buffer, &Size)) + Result = Size; + } + + IntUnLockFreeType; + + TEXTOBJ_UnlockText(TextObj); + + return Result; +} + +static UINT FASTCALL +GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI) +{ + ANSI_STRING EntryFaceNameA; + UNICODE_STRING EntryFaceNameW; + unsigned Size; + OUTLINETEXTMETRICW *Otm; + LONG WeightDiff; + NTSTATUS Status; + UINT Score = 1; + + RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); + Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); + if (NT_SUCCESS(Status)) + { + if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length) + { + EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR); + EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0'; + } + if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE)) + { + Score += 49; + } + RtlFreeUnicodeString(&EntryFaceNameW); + } + + Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); + Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); + if (NULL == Otm) + { + return Score; + } + IntGetOutlineTextMetrics(FontGDI, Size, Otm); + + if ((0 != LogFont->lfItalic && 0 != Otm->otmTextMetrics.tmItalic) || + (0 == LogFont->lfItalic && 0 == Otm->otmTextMetrics.tmItalic)) + { + Score += 25; + } + if (LogFont->lfWeight != FW_DONTCARE) + { + if (LogFont->lfWeight < Otm->otmTextMetrics.tmWeight) + { + WeightDiff = Otm->otmTextMetrics.tmWeight - LogFont->lfWeight; + } + else + { + WeightDiff = LogFont->lfWeight - Otm->otmTextMetrics.tmWeight; + } + Score += (1000 - WeightDiff) / (1000 / 25); + } + else + { + Score += 25; + } + + ExFreePool(Otm); + + return Score; +} + +static __inline VOID +FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont, + PUNICODE_STRING FaceName, PLIST_ENTRY Head) +{ + PLIST_ENTRY Entry; + PFONT_ENTRY CurrentEntry; + FONTGDI *FontGDI; + UINT Score; + + Entry = Head->Flink; + while (Entry != Head) + { + CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry); + + FontGDI = CurrentEntry->Font; + ASSERT(FontGDI); + + Score = GetFontScore(LogFont, FaceName, FontGDI); + if (*MatchScore == 0 || *MatchScore < Score) + { + *FontObj = GDIToObj(FontGDI, FONT); + *MatchScore = Score; + } + Entry = Entry->Flink; + } +} + +static __inline BOOLEAN +SubstituteFontFamilyKey(PUNICODE_STRING FaceName, + LPCWSTR Key) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}}; + NTSTATUS Status; + UNICODE_STRING Value; + + RtlInitUnicodeString(&Value, NULL); + + QueryTable[0].QueryRoutine = NULL; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND | + RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].Name = FaceName->Buffer; + QueryTable[0].EntryContext = &Value; + QueryTable[0].DefaultType = REG_NONE; + QueryTable[0].DefaultData = NULL; + QueryTable[0].DefaultLength = 0; + + QueryTable[1].QueryRoutine = NULL; + QueryTable[1].Name = NULL; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT, + Key, + QueryTable, + NULL, + NULL); + if (NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(FaceName); + *FaceName = Value; + } + + return NT_SUCCESS(Status); +} + +static __inline void +SubstituteFontFamily(PUNICODE_STRING FaceName, UINT Level) +{ + if (10 < Level) /* Enough is enough */ + { + return; + } + + if (SubstituteFontFamilyKey(FaceName, L"SysFontSubstitutes") || + SubstituteFontFamilyKey(FaceName, L"FontSubstitutes")) + { + SubstituteFontFamily(FaceName, Level + 1); + } +} + +NTSTATUS FASTCALL +TextIntRealizeFont(HFONT FontHandle) +{ + NTSTATUS Status = STATUS_SUCCESS; + PTEXTOBJ TextObj; + UNICODE_STRING FaceName; + PW32PROCESS Win32Process; + UINT MatchScore; + + TextObj = TEXTOBJ_LockText(FontHandle); + if (NULL == TextObj) + { + return STATUS_INVALID_HANDLE; + } + + if (TextObj->Initialized) + { + TEXTOBJ_UnlockText(TextObj); + return STATUS_SUCCESS; + } + + if (! RtlCreateUnicodeString(&FaceName, TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName)) + { + TEXTOBJ_UnlockText(TextObj); + return STATUS_NO_MEMORY; + } + SubstituteFontFamily(&FaceName, 0); + MatchScore = 0; + TextObj->Font = NULL; + + /* First search private fonts */ + Win32Process = PsGetCurrentProcessWin32Process(); + IntLockProcessPrivateFonts(Win32Process); + FindBestFontFromList(&TextObj->Font, &MatchScore, + &TextObj->logfont.elfEnumLogfontEx.elfLogFont, &FaceName, + &Win32Process->PrivateFontListHead); + IntUnLockProcessPrivateFonts(Win32Process); + + /* Search system fonts */ + IntLockGlobalFonts; + FindBestFontFromList(&TextObj->Font, &MatchScore, + &TextObj->logfont.elfEnumLogfontEx.elfLogFont, &FaceName, + &FontListHead); + IntUnLockGlobalFonts; + + if (NULL == TextObj->Font) + { + DPRINT1("Requested font %S not found, no fonts loaded at all\n", + TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName); + Status = STATUS_NOT_FOUND; + } + else + { + TextObj->Initialized = TRUE; + Status = STATUS_SUCCESS; + } + + RtlFreeUnicodeString(&FaceName); + TEXTOBJ_UnlockText(TextObj); + + ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0); + + return Status; +} + +INT FASTCALL +FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer) +{ + if( Buffer == NULL ) return sizeof(LOGFONTW); + + switch (Count) + { + + case sizeof(ENUMLOGFONTEXDVW): + RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer, + &TFont->logfont, + sizeof(ENUMLOGFONTEXDVW)); + break; + case sizeof(ENUMLOGFONTEXW): + RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer, + &TFont->logfont.elfEnumLogfontEx, + sizeof(ENUMLOGFONTEXW)); + break; + + case sizeof(EXTLOGFONTW): + case sizeof(ENUMLOGFONTW): + RtlCopyMemory((LPENUMLOGFONTW) Buffer, + &TFont->logfont.elfEnumLogfontEx.elfLogFont, + sizeof(ENUMLOGFONTW)); + break; + + case sizeof(LOGFONTW): + RtlCopyMemory((LPLOGFONTW) Buffer, + &TFont->logfont.elfEnumLogfontEx.elfLogFont, + sizeof(LOGFONTW)); + break; + + default: + SetLastWin32Error(ERROR_BUFFER_OVERFLOW); + return 0; + } + return Count; +} + + +static BOOL FASTCALL +IntGetFullFileName( + POBJECT_NAME_INFORMATION NameInfo, + ULONG Size, + PUNICODE_STRING FileName) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hFile; + IO_STATUS_BLOCK IoStatusBlock; + ULONG Desired; + + InitializeObjectAttributes(&ObjectAttributes, + FileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwOpenFile( + &hFile, + 0, //FILE_READ_ATTRIBUTES, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0); + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenFile() failed (Status = 0x%lx)\n", Status); + return FALSE; + } + + Status = ZwQueryObject(hFile, ObjectNameInformation, NameInfo, Size, &Desired); + ZwClose(hFile); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwQueryObject() failed (Status = %lx)\n", Status); + return FALSE; + } + + return TRUE; +} + +static BOOL FASTCALL +IntGdiGetFontResourceInfo( + IN PUNICODE_STRING FileName, + OUT void *pBuffer, + OUT DWORD *pdwBytes, + IN DWORD dwType) +{ + UNICODE_STRING EntryFileName; + POBJECT_NAME_INFORMATION NameInfo1, NameInfo2; + PLIST_ENTRY ListEntry; + PFONT_ENTRY FontEntry; + FONTFAMILYINFO Info; + ULONG Size; + BOOL bFound = FALSE; + + /* Create buffer for full path name */ + Size = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR); + NameInfo1 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF); + if (!NameInfo1) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Get the full path name */ + if (!IntGetFullFileName(NameInfo1, Size, FileName)) + { + ExFreePool(NameInfo1); + return FALSE; + } + + /* Create a buffer for the entries' names */ + NameInfo2 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF); + if (!NameInfo2) + { + ExFreePool(NameInfo1); + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Try to find the pathname in the global font list */ + IntLockGlobalFonts; + for (ListEntry = FontListHead.Flink; + ListEntry != &FontListHead; + ListEntry = ListEntry->Flink) + { + FontEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY, ListEntry); + if (FontEntry->Font->Filename != NULL) + { + RtlInitUnicodeString(&EntryFileName , FontEntry->Font->Filename); + if (IntGetFullFileName(NameInfo2, Size, &EntryFileName)) + { + if (RtlEqualUnicodeString(&NameInfo1->Name, &NameInfo2->Name, FALSE)) + { + /* found */ + FontFamilyFillInfo(&Info, FontEntry->FaceName.Buffer, FontEntry->Font); + bFound = TRUE; + break; + } + } + } + } + IntUnLockGlobalFonts; + + /* Free the buffers */ + ExFreePool(NameInfo1); + ExFreePool(NameInfo2); + + if (!bFound && dwType != 5) + { + /* Font could not be found in system table + dwType == 5 will still handle this */ + return FALSE; + } + + switch(dwType) + { + case 0: /* FIXME: returns 1 or 2, don't know what this is atm */ + *(DWORD*)pBuffer = 1; + *pdwBytes = sizeof(DWORD); + break; + + case 1: /* Copy the full font name */ + Size = wcslen(Info.EnumLogFontEx.elfFullName) + 1; + Size = min(Size , LF_FULLFACESIZE) * sizeof(WCHAR); + memcpy(pBuffer, Info.EnumLogFontEx.elfFullName, Size); + // FIXME: Do we have to zeroterminate? + *pdwBytes = Size; + break; + + case 2: /* Copy a LOGFONTW structure */ + Info.EnumLogFontEx.elfLogFont.lfWidth = 0; + memcpy(pBuffer, &Info.EnumLogFontEx.elfLogFont, sizeof(LOGFONTW)); + *pdwBytes = sizeof(LOGFONTW); + break; + + case 3: /* FIXME: What exactly is copied here? */ + *(DWORD*)pBuffer = 1; + *pdwBytes = sizeof(DWORD*); + break; + + case 5: /* Looks like a BOOL that is copied, TRUE, if the font was not found */ + *(BOOL*)pBuffer = !bFound; + *pdwBytes = sizeof(BOOL); + break; + + default: + return FALSE; + } + + return TRUE; +} + +W32KAPI BOOL APIENTRY +NtGdiGetFontResourceInfoInternalW( + IN LPWSTR pwszFiles, + IN ULONG cwc, + IN ULONG cFiles, + IN UINT cjIn, + OUT LPDWORD pdwBytes, + OUT LPVOID pvBuf, + IN DWORD dwType) +{ + NTSTATUS Status = STATUS_SUCCESS; + DWORD dwBytes; + UNICODE_STRING SafeFileNames; + BOOL bRet = FALSE; + ULONG cbStringSize; + + union + { + LOGFONTW logfontw; + WCHAR FullName[LF_FULLFACESIZE]; + } Buffer; + + /* FIXME: handle cFiles > 0 */ + + /* Check for valid dwType values + dwType == 4 seems to be handled by gdi32 only */ + if (dwType == 4 || dwType > 5) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Allocate a safe unicode string buffer */ + cbStringSize = cwc * sizeof(WCHAR); + SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR); + SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool, + cbStringSize, + TAG('R','T','S','U')); + if (!SafeFileNames.Buffer) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Check buffers and copy pwszFiles to safe unicode string */ + _SEH_TRY + { + ProbeForRead(pwszFiles, cbStringSize, 1); + ProbeForWrite(pdwBytes, sizeof(DWORD), 1); + ProbeForWrite(pvBuf, cjIn, 1); + + RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END + + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + /* Free the string buffer for the safe filename */ + ExFreePool(SafeFileNames.Buffer); + return FALSE; + } + + /* Do the actual call */ + bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType); + + /* Check if succeeded and the buffer is big enough */ + if (bRet && cjIn >= dwBytes) + { + /* Copy the data back to caller */ + _SEH_TRY + { + /* Buffers are already probed */ + RtlCopyMemory(pvBuf, &Buffer, dwBytes); + *pdwBytes = dwBytes; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END + + if(!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + bRet = FALSE; + } + } + + /* Free the string for the safe filenames */ + ExFreePool(SafeFileNames.Buffer); + + return bRet; +} + +/* EOF */ diff --git a/reactos/subsystems/win32/win32k/objects/text.c b/reactos/subsystems/win32/win32k/objects/text.c index efe392475e3..e1c729b1229 100644 --- a/reactos/subsystems/win32/win32k/objects/text.c +++ b/reactos/subsystems/win32/win32k/objects/text.c @@ -1,3473 +1,23 @@ /* - * ReactOS W32 Subsystem - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team - * - * Parts based on Wine code - * Copyright 1993 Alexandre Julliard - * 1997 Alex Korobka - * Copyright 2002,2003 Shachar Shemesh - * Copyright 2001 Huw D M Davies for CodeWeavers. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * PROJECT: ReactOS win32 kernel mode subsystem + * LICENSE: GPL - See COPYING in the top level directory + * FILE: subsystems/win32/win32k/objects/text.c + * PURPOSE: Text/Font + * PROGRAMMER: */ -/* $Id$ */ + +/** Includes ******************************************************************/ #include -#include -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include -#include -#include -#include -#include - #define NDEBUG #include -FT_Library library; - -typedef struct _FONT_ENTRY { - LIST_ENTRY ListEntry; - FONTGDI *Font; - UNICODE_STRING FaceName; - BYTE NotEnum; -} FONT_ENTRY, *PFONT_ENTRY; - -/* The FreeType library is not thread safe, so we have - to serialize access to it */ -static FAST_MUTEX FreeTypeLock; - -static LIST_ENTRY FontListHead; -static FAST_MUTEX FontListLock; -static BOOL RenderingEnabled = TRUE; - -#define MAX_FONT_CACHE 256 -UINT Hits; -UINT Misses; - -typedef struct _FONT_CACHE_ENTRY { - LIST_ENTRY ListEntry; - int GlyphIndex; - FT_Face Face; - FT_Glyph Glyph; - int Height; -} FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY; -static LIST_ENTRY FontCacheListHead; -static UINT FontCacheNumEntries; - -static PWCHAR ElfScripts[32] = { /* these are in the order of the fsCsb[0] bits */ - L"Western", /*00*/ - L"Central_European", - L"Cyrillic", - L"Greek", - L"Turkish", - L"Hebrew", - L"Arabic", - L"Baltic", - L"Vietnamese", /*08*/ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/ - L"Thai", - L"Japanese", - L"CHINESE_GB2312", - L"Hangul", - L"CHINESE_BIG5", - L"Hangul(Johab)", - NULL, NULL, /*23*/ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - L"Symbol" /*31*/ -}; - -/* - * For NtGdiTranslateCharsetInfo - */ -#define FS(x) {{0,0,0,0},{0x1<<(x),0}} -#define MAXTCIINDEX 32 -static CHARSETINFO FontTci[MAXTCIINDEX] = { - /* ANSI */ - { ANSI_CHARSET, 1252, FS(0)}, - { EASTEUROPE_CHARSET, 1250, FS(1)}, - { RUSSIAN_CHARSET, 1251, FS(2)}, - { GREEK_CHARSET, 1253, FS(3)}, - { TURKISH_CHARSET, 1254, FS(4)}, - { HEBREW_CHARSET, 1255, FS(5)}, - { ARABIC_CHARSET, 1256, FS(6)}, - { BALTIC_CHARSET, 1257, FS(7)}, - { VIETNAMESE_CHARSET, 1258, FS(8)}, - /* reserved by ANSI */ - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - /* ANSI and OEM */ - { THAI_CHARSET, 874, FS(16)}, - { SHIFTJIS_CHARSET, 932, FS(17)}, - { GB2312_CHARSET, 936, FS(18)}, - { HANGEUL_CHARSET, 949, FS(19)}, - { CHINESEBIG5_CHARSET, 950, FS(20)}, - { JOHAB_CHARSET, 1361, FS(21)}, - /* reserved for alternate ANSI and OEM */ - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - { DEFAULT_CHARSET, 0, FS(0)}, - /* reserved for system */ - { DEFAULT_CHARSET, 0, FS(0)}, - { SYMBOL_CHARSET, 42 /* CP_SYMBOL */, FS(31)}, -}; - -BOOL FASTCALL -InitFontSupport(VOID) -{ - ULONG ulError; - - InitializeListHead(&FontListHead); - InitializeListHead(&FontCacheListHead); - FontCacheNumEntries = 0; - ExInitializeFastMutex(&FontListLock); - ExInitializeFastMutex(&FreeTypeLock); - - ulError = FT_Init_FreeType(&library); - if (ulError) { - DPRINT1("FT_Init_FreeType failed with error code 0x%x\n", ulError); - return FALSE; - } - - IntLoadSystemFonts(); - - return TRUE; -} - -/* - * IntLoadSystemFonts - * - * Search the system font directory and adds each font found. - */ - -VOID FASTCALL -IntLoadSystemFonts(VOID) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING Directory, SearchPattern, FileName, TempString; - IO_STATUS_BLOCK Iosb; - HANDLE hDirectory; - BYTE *DirInfoBuffer; - PFILE_DIRECTORY_INFORMATION DirInfo; - BOOLEAN bRestartScan = TRUE; - NTSTATUS Status; - - RtlInitUnicodeString(&Directory, L"\\SystemRoot\\Fonts\\"); - /* FIXME: Add support for other font types */ - RtlInitUnicodeString(&SearchPattern, L"*.ttf"); - - InitializeObjectAttributes( - &ObjectAttributes, - &Directory, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwOpenFile( - &hDirectory, - SYNCHRONIZE | FILE_LIST_DIRECTORY, - &ObjectAttributes, - &Iosb, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE); - - if (NT_SUCCESS(Status)) - { - DirInfoBuffer = ExAllocatePool(PagedPool, 0x4000); - if (DirInfoBuffer == NULL) - { - ZwClose(hDirectory); - return; - } - - FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH * sizeof(WCHAR)); - if (FileName.Buffer == NULL) - { - ExFreePool(DirInfoBuffer); - ZwClose(hDirectory); - return; - } - FileName.Length = 0; - FileName.MaximumLength = MAX_PATH * sizeof(WCHAR); - - while (1) - { - Status = ZwQueryDirectoryFile( - hDirectory, - NULL, - NULL, - NULL, - &Iosb, - DirInfoBuffer, - 0x4000, - FileDirectoryInformation, - FALSE, - &SearchPattern, - bRestartScan); - - if (!NT_SUCCESS(Status) || Status == STATUS_NO_MORE_FILES) - { - break; - } - - DirInfo = (PFILE_DIRECTORY_INFORMATION)DirInfoBuffer; - while (1) - { - TempString.Buffer = DirInfo->FileName; - TempString.Length = - TempString.MaximumLength = DirInfo->FileNameLength; - RtlCopyUnicodeString(&FileName, &Directory); - RtlAppendUnicodeStringToString(&FileName, &TempString); - IntGdiAddFontResource(&FileName, 0); - if (DirInfo->NextEntryOffset == 0) - break; - DirInfo = (PFILE_DIRECTORY_INFORMATION)((ULONG_PTR)DirInfo + DirInfo->NextEntryOffset); - } - - bRestartScan = FALSE; - } - - ExFreePool(FileName.Buffer); - ExFreePool(DirInfoBuffer); - ZwClose(hDirectory); - } -} - -/* - * IntGdiAddFontResource - * - * Adds the font resource from the specified file to the system. - */ - -INT FASTCALL -IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics) -{ - FONTGDI *FontGDI; - NTSTATUS Status; - HANDLE FileHandle, KeyHandle; - OBJECT_ATTRIBUTES ObjectAttributes; - PVOID Buffer = NULL; - IO_STATUS_BLOCK Iosb; - INT Error; - FT_Face Face; - ANSI_STRING AnsiFaceName; - PFONT_ENTRY Entry; - PSECTION_OBJECT SectionObject; - ULONG ViewSize = 0; - LARGE_INTEGER SectionSize; - FT_Fixed XScale, YScale; - UNICODE_STRING FontRegPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"); - - /* Open the font file */ - - InitializeObjectAttributes(&ObjectAttributes, FileName, 0, NULL, NULL); - Status = ZwOpenFile( - &FileHandle, - FILE_GENERIC_READ | SYNCHRONIZE, - &ObjectAttributes, - &Iosb, - FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Could not load font file: %wZ\n", FileName); - return 0; - } - - SectionSize.QuadPart = 0LL; - Status = MmCreateSection((PVOID)&SectionObject, SECTION_ALL_ACCESS, - NULL, &SectionSize, PAGE_READONLY, - SEC_COMMIT, FileHandle, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("Could not map file: %wZ\n", FileName); - ZwClose(FileHandle); - return 0; - } - - ZwClose(FileHandle); - - Status = MmMapViewInSystemSpace(SectionObject, &Buffer, &ViewSize); - if (!NT_SUCCESS(Status)) - { - DPRINT("Could not map file: %wZ\n", FileName); - return Status; - } - - IntLockFreeType; - Error = FT_New_Memory_Face( - library, - Buffer, - ViewSize, - 0, - &Face); - IntUnLockFreeType; - - if (Error) - { - if (Error == FT_Err_Unknown_File_Format) - DPRINT("Unknown font file format\n"); - else - DPRINT("Error reading font file (error code: %u)\n", Error); - ObDereferenceObject(SectionObject); - return 0; - } - - Entry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY), TAG_FONT); - if (!Entry) - { - FT_Done_Face(Face); - ObDereferenceObject(SectionObject); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), TAG_FONTOBJ); - if(FontGDI == NULL) - { - FT_Done_Face(Face); - ObDereferenceObject(SectionObject); - ExFreePool(Entry); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - FontGDI->Filename = ExAllocatePoolWithTag(PagedPool, FileName->Length + sizeof(WCHAR), TAG_PFF); - if (FontGDI->Filename == NULL) - { - EngFreeMem(FontGDI); - FT_Done_Face(Face); - ObDereferenceObject(SectionObject); - ExFreePool(Entry); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - memcpy(FontGDI->Filename, FileName->Buffer, FileName->Length); - FontGDI->Filename[FileName->Length / sizeof(WCHAR)] = L'\0'; - FontGDI->face = Face; - - /* FIXME: Complete text metrics */ - XScale = Face->size->metrics.x_scale; - YScale = Face->size->metrics.y_scale; -#if 0 /* This (Wine) code doesn't seem to work correctly for us */ - FontGDI->TextMetric.tmAscent = (FT_MulFix(Face->ascender, YScale) + 32) >> 6; - FontGDI->TextMetric.tmDescent = (FT_MulFix(Face->descender, YScale) + 32) >> 6; - FontGDI->TextMetric.tmHeight = (FT_MulFix(Face->ascender, YScale) - - FT_MulFix(Face->descender, YScale)) >> 6; -#else - FontGDI->TextMetric.tmAscent = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */ - FontGDI->TextMetric.tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */ - FontGDI->TextMetric.tmHeight = (Face->size->metrics.ascender - Face->size->metrics.descender) >> 6; -#endif - - - - DPRINT("Font loaded: %s (%s)\n", Face->family_name, Face->style_name); - DPRINT("Num glyphs: %u\n", Face->num_glyphs); - - /* Add this font resource to the font table */ - - Entry->Font = FontGDI; - Entry->NotEnum = (Characteristics & FR_NOT_ENUM); - RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name); - RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE); - - if (Characteristics & FR_PRIVATE) - { - PW32PROCESS Win32Process = PsGetCurrentProcessWin32Process(); - IntLockProcessPrivateFonts(Win32Process); - InsertTailList(&Win32Process->PrivateFontListHead, &Entry->ListEntry); - IntUnLockProcessPrivateFonts(Win32Process); - } - else - { - IntLockGlobalFonts; - InsertTailList(&FontListHead, &Entry->ListEntry); - InitializeObjectAttributes(&ObjectAttributes, &FontRegPath, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = ZwOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes); - if (NT_SUCCESS(Status)) - { - LPWSTR pName = wcsrchr(FileName->Buffer, L'\\'); - if (pName) - { - pName++; - ZwSetValueKey(KeyHandle, &Entry->FaceName, 0, REG_SZ, pName, (wcslen(pName) + 1) * sizeof(WCHAR)); - } - ZwClose(KeyHandle); - } - IntUnLockGlobalFonts; - } - return 1; -} - -BOOL FASTCALL -IntIsFontRenderingEnabled(VOID) -{ - BOOL Ret = RenderingEnabled; - HDC hDC; - - hDC = IntGetScreenDC(); - if (hDC) - Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && RenderingEnabled; - - return Ret; -} - -VOID FASTCALL -IntEnableFontRendering(BOOL Enable) -{ - RenderingEnabled = Enable; -} - -FT_Render_Mode FASTCALL -IntGetFontRenderMode(LOGFONTW *logfont) -{ - switch(logfont->lfQuality) - { - case NONANTIALIASED_QUALITY: - return FT_RENDER_MODE_MONO; - case DRAFT_QUALITY: - return FT_RENDER_MODE_LIGHT; -/* case CLEARTYPE_QUALITY: - return FT_RENDER_MODE_LCD; */ - } - return FT_RENDER_MODE_NORMAL; -} - -INT -APIENTRY -NtGdiAddFontResourceW( - IN WCHAR *pwszFiles, - IN ULONG cwc, - IN ULONG cFiles, - IN FLONG fl, - IN DWORD dwPidTid, - IN OPTIONAL DESIGNVECTOR *pdv) -{ - UNICODE_STRING SafeFileName; - PWSTR src; - NTSTATUS Status; - int Ret; - - /* FIXME - Protect with SEH? */ - RtlInitUnicodeString(&SafeFileName, pwszFiles); - - /* Reserve for prepending '\??\' */ - SafeFileName.Length += 4 * sizeof(WCHAR); - SafeFileName.MaximumLength += 4 * sizeof(WCHAR); - - src = SafeFileName.Buffer; - SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING); - if(!SafeFileName.Buffer) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - /* Prepend '\??\' */ - RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR)); - - Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR))); - if(!NT_SUCCESS(Status)) - { - ExFreePool(SafeFileName.Buffer); - SetLastNtError(Status); - return 0; - } - - Ret = IntGdiAddFontResource(&SafeFileName, (DWORD)fl); - - ExFreePool(SafeFileName.Buffer); - return Ret; -} - -NTSTATUS FASTCALL -TextIntCreateFontIndirect(CONST LPLOGFONTW lf, HFONT *NewFont) -{ - PTEXTOBJ TextObj; - - TextObj = TEXTOBJ_AllocTextWithHandle(); - if (!TextObj) - { - return STATUS_NO_MEMORY; - } - - *NewFont = TextObj->BaseObject.hHmgr; - memcpy(&TextObj->logfont.elfEnumLogfontEx.elfLogFont, lf, sizeof(LOGFONTW)); - if (lf->lfEscapement != lf->lfOrientation) - { - /* this should really depend on whether GM_ADVANCED is set */ - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation = - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement; - } - TEXTOBJ_UnlockText(TextObj); - - return STATUS_SUCCESS; -} - -HFONT -STDCALL -NtGdiHfontCreate( - IN PENUMLOGFONTEXDVW pelfw, - IN ULONG cjElfw, - IN LFTYPE lft, - IN FLONG fl, - IN PVOID pvCliData ) -{ - ENUMLOGFONTEXDVW SafeLogfont; - HFONT hNewFont; - PTEXTOBJ TextObj; - NTSTATUS Status = STATUS_SUCCESS; - - if (!pelfw) - { - return NULL; - } - - _SEH_TRY - { - ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1); - RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END - - if (!NT_SUCCESS(Status)) - { - return NULL; - } - - TextObj = TEXTOBJ_AllocTextWithHandle(); - if (!TextObj) - { - return NULL; - } - hNewFont = TextObj->BaseObject.hHmgr; - - RtlCopyMemory (&TextObj->logfont, &SafeLogfont, sizeof(ENUMLOGFONTEXDVW)); - - if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement != - SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation) - { - /* this should really depend on whether GM_ADVANCED is set */ - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation = - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement; - } - TEXTOBJ_UnlockText(TextObj); - - return hNewFont; - -} - -/************************************************************************* - * TranslateCharsetInfo - * - * Fills a CHARSETINFO structure for a character set, code page, or - * font. This allows making the correspondance between different labelings - * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges) - * of the same encoding. - * - * Only one codepage will be set in Cs->fs. If TCI_SRCFONTSIG is used, - * only one codepage should be set in *Src. - * - * RETURNS - * TRUE on success, FALSE on failure. - * - */ -static BOOLEAN STDCALL -IntTranslateCharsetInfo(PDWORD Src, /* [in] - if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE - if flags == TCI_SRCCHARSET: a character set value - if flags == TCI_SRCCODEPAGE: a code page value */ - LPCHARSETINFO Cs, /* [out] structure to receive charset information */ - DWORD Flags /* [in] determines interpretation of lpSrc */) -{ - int Index = 0; - - switch (Flags) - { - case TCI_SRCFONTSIG: - while (0 == (*Src >> Index & 0x0001) && Index < MAXTCIINDEX) - { - Index++; - } - break; - case TCI_SRCCODEPAGE: - while ((UINT) (Src) != FontTci[Index].ciACP && Index < MAXTCIINDEX) - { - Index++; - } - break; - case TCI_SRCCHARSET: - while ((UINT) (Src) != FontTci[Index].ciCharset && Index < MAXTCIINDEX) - { - Index++; - } - break; - default: - return FALSE; - } - - if (MAXTCIINDEX <= Index || DEFAULT_CHARSET == FontTci[Index].ciCharset) - { - return FALSE; - } - - memcpy(Cs, &FontTci[Index], sizeof(CHARSETINFO)); - - return TRUE; -} - - -static void FASTCALL -FillTM(TEXTMETRICW *TM, FT_Face Face, TT_OS2 *pOS2, TT_HoriHeader *pHori) -{ - FT_Fixed XScale, YScale; - int Ascent, Descent; - - XScale = Face->size->metrics.x_scale; - YScale = Face->size->metrics.y_scale; - - if (0 == pOS2->usWinAscent + pOS2->usWinDescent) - { - Ascent = pHori->Ascender; - Descent = -pHori->Descender; - } - else - { - Ascent = pOS2->usWinAscent; - Descent = pOS2->usWinDescent; - } - -#if 0 /* This (Wine) code doesn't seem to work correctly for us, cmd issue */ - TM->tmAscent = (FT_MulFix(Ascent, YScale) + 32) >> 6; - TM->tmDescent = (FT_MulFix(Descent, YScale) + 32) >> 6; -#else /* This (ros) code was previously affected by a FreeType bug, but it works now */ - TM->tmAscent = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */ - TM->tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */ -#endif - - TM->tmInternalLeading = (FT_MulFix(Ascent + Descent - Face->units_per_EM, YScale) + 32) >> 6; - TM->tmHeight = TM->tmAscent + TM->tmDescent; // we need add 1 height more after scale it right - - /* MSDN says: - * el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender))) - */ - TM->tmExternalLeading = max(0, (FT_MulFix(pHori->Line_Gap - - ((Ascent + Descent) - - (pHori->Ascender - pHori->Descender)), - YScale) + 32) >> 6); - - TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6; - if (0 == TM->tmAveCharWidth) - { - TM->tmAveCharWidth = 1; - } - - /* Correct forumla to get the maxcharwidth from unicode and ansi font */ - TM->tmMaxCharWidth = (FT_MulFix(Face->max_advance_width, XScale) + 32) >> 6; - - TM->tmWeight = pOS2->usWeightClass; - TM->tmOverhang = 0; - TM->tmDigitizedAspectX = 300; - TM->tmDigitizedAspectY = 300; - TM->tmFirstChar = pOS2->usFirstCharIndex; - TM->tmLastChar = pOS2->usLastCharIndex; - TM->tmDefaultChar = pOS2->usDefaultChar; - TM->tmBreakChar = L'\0' != pOS2->usBreakChar ? pOS2->usBreakChar : ' '; - TM->tmItalic = (Face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0; - TM->tmUnderlined = 0; /* entry in OS2 table */ - TM->tmStruckOut = 0; /* entry in OS2 table */ - - /* Yes TPMF_FIXED_PITCH is correct; braindead api */ - if (! FT_IS_FIXED_WIDTH(Face)) - { - TM->tmPitchAndFamily = TMPF_FIXED_PITCH; - } - else - { - TM->tmPitchAndFamily = 0; - } - - switch (pOS2->panose[PAN_FAMILYTYPE_INDEX]) - { - case PAN_FAMILY_SCRIPT: - TM->tmPitchAndFamily |= FF_SCRIPT; - break; - case PAN_FAMILY_DECORATIVE: - case PAN_FAMILY_PICTORIAL: - TM->tmPitchAndFamily |= FF_DECORATIVE; - break; - case PAN_FAMILY_TEXT_DISPLAY: - if (0 == TM->tmPitchAndFamily) /* fixed */ - { - TM->tmPitchAndFamily = FF_MODERN; - } - else - { - switch (pOS2->panose[PAN_SERIFSTYLE_INDEX]) - { - case PAN_SERIF_NORMAL_SANS: - case PAN_SERIF_OBTUSE_SANS: - case PAN_SERIF_PERP_SANS: - TM->tmPitchAndFamily |= FF_SWISS; - break; - default: - TM->tmPitchAndFamily |= FF_ROMAN; - break; - } - } - break; - default: - TM->tmPitchAndFamily |= FF_DONTCARE; - } - - if (FT_IS_SCALABLE(Face)) - { - TM->tmPitchAndFamily |= TMPF_VECTOR; - } - if (FT_IS_SFNT(Face)) - { - TM->tmPitchAndFamily |= TMPF_TRUETYPE; - } - - TM->tmCharSet = DEFAULT_CHARSET; -} - -/************************************************************* - * IntGetOutlineTextMetrics - * - */ -static unsigned FASTCALL -IntGetOutlineTextMetrics(PFONTGDI FontGDI, UINT Size, - OUTLINETEXTMETRICW *Otm) -{ - unsigned Needed; - TT_OS2 *pOS2; - TT_HoriHeader *pHori; - TT_Postscript *pPost; - FT_Fixed XScale, YScale; - ANSI_STRING FamilyNameA, StyleNameA; - UNICODE_STRING FamilyNameW, StyleNameW, Regular; - char *Cp; - - Needed = sizeof(OUTLINETEXTMETRICW); - - RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name); - RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE); - - RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name); - RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE); - - /* These names should be read from the TT name table */ - - /* length of otmpFamilyName */ - Needed += FamilyNameW.Length + sizeof(WCHAR); - - RtlInitUnicodeString(&Regular, L"regular"); - /* length of otmpFaceName */ - if (0 == RtlCompareUnicodeString(&StyleNameW, &Regular, TRUE)) - { - Needed += FamilyNameW.Length + sizeof(WCHAR); /* just the family name */ - } - else - { - Needed += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1); /* family + " " + style */ - } - - /* length of otmpStyleName */ - Needed += StyleNameW.Length + sizeof(WCHAR); - - /* length of otmpFullName */ - Needed += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1); - - if (Size < Needed) - { - RtlFreeUnicodeString(&FamilyNameW); - RtlFreeUnicodeString(&StyleNameW); - return Needed; - } - - XScale = FontGDI->face->size->metrics.x_scale; - YScale = FontGDI->face->size->metrics.y_scale; - - IntLockFreeType; - pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2); - if (NULL == pOS2) - { - IntUnLockFreeType; - DPRINT1("Can't find OS/2 table - not TT font?\n"); - RtlFreeUnicodeString(&StyleNameW); - RtlFreeUnicodeString(&FamilyNameW); - return 0; - } - - pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea); - if (NULL == pHori) - { - IntUnLockFreeType; - DPRINT1("Can't find HHEA table - not TT font?\n"); - RtlFreeUnicodeString(&StyleNameW); - RtlFreeUnicodeString(&FamilyNameW); - return 0; - } - - pPost = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_post); /* we can live with this failing */ - - Otm->otmSize = Needed; - - FillTM(&Otm->otmTextMetrics, FontGDI->face, pOS2, pHori); - - Otm->otmFiller = 0; - memcpy(&Otm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT); - Otm->otmfsSelection = pOS2->fsSelection; - Otm->otmfsType = pOS2->fsType; - Otm->otmsCharSlopeRise = pHori->caret_Slope_Rise; - Otm->otmsCharSlopeRun = pHori->caret_Slope_Run; - Otm->otmItalicAngle = 0; /* POST table */ - Otm->otmEMSquare = FontGDI->face->units_per_EM; - Otm->otmAscent = (FT_MulFix(pOS2->sTypoAscender, YScale) + 32) >> 6; - Otm->otmDescent = (FT_MulFix(pOS2->sTypoDescender, YScale) + 32) >> 6; - Otm->otmLineGap = (FT_MulFix(pOS2->sTypoLineGap, YScale) + 32) >> 6; - Otm->otmsCapEmHeight = (FT_MulFix(pOS2->sCapHeight, YScale) + 32) >> 6; - Otm->otmsXHeight = (FT_MulFix(pOS2->sxHeight, YScale) + 32) >> 6; - Otm->otmrcFontBox.left = (FT_MulFix(FontGDI->face->bbox.xMin, XScale) + 32) >> 6; - Otm->otmrcFontBox.right = (FT_MulFix(FontGDI->face->bbox.xMax, XScale) + 32) >> 6; - Otm->otmrcFontBox.top = (FT_MulFix(FontGDI->face->bbox.yMax, YScale) + 32) >> 6; - Otm->otmrcFontBox.bottom = (FT_MulFix(FontGDI->face->bbox.yMin, YScale) + 32) >> 6; - Otm->otmMacAscent = 0; /* where do these come from ? */ - Otm->otmMacDescent = 0; - Otm->otmMacLineGap = 0; - Otm->otmusMinimumPPEM = 0; /* TT Header */ - Otm->otmptSubscriptSize.x = (FT_MulFix(pOS2->ySubscriptXSize, XScale) + 32) >> 6; - Otm->otmptSubscriptSize.y = (FT_MulFix(pOS2->ySubscriptYSize, YScale) + 32) >> 6; - Otm->otmptSubscriptOffset.x = (FT_MulFix(pOS2->ySubscriptXOffset, XScale) + 32) >> 6; - Otm->otmptSubscriptOffset.y = (FT_MulFix(pOS2->ySubscriptYOffset, YScale) + 32) >> 6; - Otm->otmptSuperscriptSize.x = (FT_MulFix(pOS2->ySuperscriptXSize, XScale) + 32) >> 6; - Otm->otmptSuperscriptSize.y = (FT_MulFix(pOS2->ySuperscriptYSize, YScale) + 32) >> 6; - Otm->otmptSuperscriptOffset.x = (FT_MulFix(pOS2->ySuperscriptXOffset, XScale) + 32) >> 6; - Otm->otmptSuperscriptOffset.y = (FT_MulFix(pOS2->ySuperscriptYOffset, YScale) + 32) >> 6; - Otm->otmsStrikeoutSize = (FT_MulFix(pOS2->yStrikeoutSize, YScale) + 32) >> 6; - Otm->otmsStrikeoutPosition = (FT_MulFix(pOS2->yStrikeoutPosition, YScale) + 32) >> 6; - if (NULL == pPost) - { - Otm->otmsUnderscoreSize = 0; - Otm->otmsUnderscorePosition = 0; - } - else - { - Otm->otmsUnderscoreSize = (FT_MulFix(pPost->underlineThickness, YScale) + 32) >> 6; - Otm->otmsUnderscorePosition = (FT_MulFix(pPost->underlinePosition, YScale) + 32) >> 6; - } - - IntUnLockFreeType; - - /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */ - Cp = (char*) Otm + sizeof(OUTLINETEXTMETRICW); - Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm); - wcscpy((WCHAR*) Cp, FamilyNameW.Buffer); - Cp += FamilyNameW.Length + sizeof(WCHAR); - Otm->otmpStyleName = (LPSTR)(Cp - (char*) Otm); - wcscpy((WCHAR*) Cp, StyleNameW.Buffer); - Cp += StyleNameW.Length + sizeof(WCHAR); - Otm->otmpFaceName = (LPSTR)(Cp - (char*) Otm); - wcscpy((WCHAR*) Cp, FamilyNameW.Buffer); - if (0 != RtlCompareUnicodeString(&StyleNameW, &Regular, TRUE)) - { - wcscat((WCHAR*) Cp, L" "); - wcscat((WCHAR*) Cp, StyleNameW.Buffer); - Cp += FamilyNameW.Length + StyleNameW.Length + (sizeof(WCHAR) << 1); - } - else - { - Cp += FamilyNameW.Length + sizeof(WCHAR); - } - Otm->otmpFullName = (LPSTR)(Cp - (char*) Otm); - wcscpy((WCHAR*) Cp, FamilyNameW.Buffer); - wcscat((WCHAR*) Cp, L" "); - wcscat((WCHAR*) Cp, StyleNameW.Buffer); - - RtlFreeUnicodeString(&StyleNameW); - RtlFreeUnicodeString(&FamilyNameW); - - return Needed; -} - -static PFONTGDI FASTCALL -FindFaceNameInList(PUNICODE_STRING FaceName, PLIST_ENTRY Head) -{ - PLIST_ENTRY Entry; - PFONT_ENTRY CurrentEntry; - ANSI_STRING EntryFaceNameA; - UNICODE_STRING EntryFaceNameW; - FONTGDI *FontGDI; - - Entry = Head->Flink; - while (Entry != Head) - { - CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry); - - FontGDI = CurrentEntry->Font; - ASSERT(FontGDI); - - RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); - RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); - if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length) - { - EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR); - EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0'; - } - - if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE)) - { - RtlFreeUnicodeString(&EntryFaceNameW); - return FontGDI; - } - - RtlFreeUnicodeString(&EntryFaceNameW); - Entry = Entry->Flink; - } - - return NULL; -} - -static PFONTGDI FASTCALL -FindFaceNameInLists(PUNICODE_STRING FaceName) -{ - PW32PROCESS Win32Process; - PFONTGDI Font; - - /* Search the process local list */ - Win32Process = PsGetCurrentProcessWin32Process(); - IntLockProcessPrivateFonts(Win32Process); - Font = FindFaceNameInList(FaceName, &Win32Process->PrivateFontListHead); - IntUnLockProcessPrivateFonts(Win32Process); - if (NULL != Font) - { - return Font; - } - - /* Search the global list */ - IntLockGlobalFonts; - Font = FindFaceNameInList(FaceName, &FontListHead); - IntUnLockGlobalFonts; - - return Font; -} - -static void FASTCALL -FontFamilyFillInfo(PFONTFAMILYINFO Info, PCWSTR FaceName, PFONTGDI FontGDI) -{ - ANSI_STRING StyleA; - UNICODE_STRING StyleW; - TT_OS2 *pOS2; - FONTSIGNATURE fs; - DWORD fs_fsCsb0; - CHARSETINFO CharSetInfo; - unsigned i, Size; - OUTLINETEXTMETRICW *Otm; - LOGFONTW *Lf; - TEXTMETRICW *TM; - NEWTEXTMETRICW *Ntm; - - RtlZeroMemory(Info, sizeof(FONTFAMILYINFO)); - Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); - Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); - if (NULL == Otm) - { - return; - } - IntGetOutlineTextMetrics(FontGDI, Size, Otm); - - Lf = &Info->EnumLogFontEx.elfLogFont; - TM = &Otm->otmTextMetrics; - - Lf->lfHeight = TM->tmHeight; - Lf->lfWidth = TM->tmAveCharWidth; - Lf->lfWeight = TM->tmWeight; - Lf->lfItalic = TM->tmItalic; - Lf->lfPitchAndFamily = (TM->tmPitchAndFamily & 0xf1) + 1; - Lf->lfCharSet = TM->tmCharSet; - Lf->lfOutPrecision = OUT_OUTLINE_PRECIS; - Lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; - Lf->lfQuality = PROOF_QUALITY; - - Ntm = &Info->NewTextMetricEx.ntmTm; - Ntm->tmHeight = TM->tmHeight; - Ntm->tmAscent = TM->tmAscent; - Ntm->tmDescent = TM->tmDescent; - Ntm->tmInternalLeading = TM->tmInternalLeading; - Ntm->tmExternalLeading = TM->tmExternalLeading; - Ntm->tmAveCharWidth = TM->tmAveCharWidth; - Ntm->tmMaxCharWidth = TM->tmMaxCharWidth; - Ntm->tmWeight = TM->tmWeight; - Ntm->tmOverhang = TM->tmOverhang; - Ntm->tmDigitizedAspectX = TM->tmDigitizedAspectX; - Ntm->tmDigitizedAspectY = TM->tmDigitizedAspectY; - Ntm->tmFirstChar = TM->tmFirstChar; - Ntm->tmLastChar = TM->tmLastChar; - Ntm->tmDefaultChar = TM->tmDefaultChar; - Ntm->tmBreakChar = TM->tmBreakChar; - Ntm->tmItalic = TM->tmItalic; - Ntm->tmUnderlined = TM->tmUnderlined; - Ntm->tmStruckOut = TM->tmStruckOut; - Ntm->tmPitchAndFamily = TM->tmPitchAndFamily; - Ntm->tmCharSet = TM->tmCharSet; - Ntm->ntmFlags = TM->tmItalic ? NTM_ITALIC : 0; - if (550 < TM->tmWeight) - { - Ntm->ntmFlags |= NTM_BOLD; - } - if (0 == Ntm->ntmFlags) - { - Ntm->ntmFlags = NTM_REGULAR; - } - - Ntm->ntmSizeEM = Otm->otmEMSquare; - Ntm->ntmCellHeight = 0; - Ntm->ntmAvgWidth = 0; - - Info->FontType = (0 != (TM->tmPitchAndFamily & TMPF_TRUETYPE) - ? TRUETYPE_FONTTYPE : 0); - if (0 == (TM->tmPitchAndFamily & TMPF_VECTOR)) - { - Info->FontType |= RASTER_FONTTYPE; - } - - ExFreePool(Otm); - - wcsncpy(Info->EnumLogFontEx.elfLogFont.lfFaceName, FaceName, LF_FACESIZE); - wcsncpy(Info->EnumLogFontEx.elfFullName, FaceName, LF_FULLFACESIZE); - RtlInitAnsiString(&StyleA, FontGDI->face->style_name); - RtlAnsiStringToUnicodeString(&StyleW, &StyleA, TRUE); - wcsncpy(Info->EnumLogFontEx.elfStyle, StyleW.Buffer, LF_FACESIZE); - RtlFreeUnicodeString(&StyleW); - - Info->EnumLogFontEx.elfLogFont.lfCharSet = DEFAULT_CHARSET; - Info->EnumLogFontEx.elfScript[0] = L'\0'; - IntLockFreeType; - pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2); - IntUnLockFreeType; - if (NULL != pOS2) - { - Info->NewTextMetricEx.ntmFontSig.fsCsb[0] = pOS2->ulCodePageRange1; - Info->NewTextMetricEx.ntmFontSig.fsCsb[1] = pOS2->ulCodePageRange2; - Info->NewTextMetricEx.ntmFontSig.fsUsb[0] = pOS2->ulUnicodeRange1; - Info->NewTextMetricEx.ntmFontSig.fsUsb[1] = pOS2->ulUnicodeRange2; - Info->NewTextMetricEx.ntmFontSig.fsUsb[2] = pOS2->ulUnicodeRange3; - Info->NewTextMetricEx.ntmFontSig.fsUsb[3] = pOS2->ulUnicodeRange4; - - fs_fsCsb0 = pOS2->ulCodePageRange1; - if (0 == pOS2->version) - { - FT_UInt Dummy; - - if (FT_Get_First_Char(FontGDI->face, &Dummy) < 0x100) - { - fs_fsCsb0 |= 1; - } - else - { - fs_fsCsb0 |= 1L << 31; - } - } - if (0 == fs_fsCsb0) - { /* let's see if we can find any interesting cmaps */ - for (i = 0; i < FontGDI->face->num_charmaps; i++) - { - switch (FontGDI->face->charmaps[i]->encoding) - { - case ft_encoding_unicode: - case ft_encoding_apple_roman: - fs_fsCsb0 |= 1; - break; - case ft_encoding_symbol: - fs_fsCsb0 |= 1L << 31; - break; - default: - break; - } - } - } - - for(i = 0; i < 32; i++) - { - if (0 != (fs_fsCsb0 & (1L << i))) - { - fs.fsCsb[0] = 1L << i; - fs.fsCsb[1] = 0; - if (! IntTranslateCharsetInfo(fs.fsCsb, &CharSetInfo, TCI_SRCFONTSIG)) - { - CharSetInfo.ciCharset = DEFAULT_CHARSET; - } - if (31 == i) - { - CharSetInfo.ciCharset = SYMBOL_CHARSET; - } - if (DEFAULT_CHARSET != CharSetInfo.ciCharset) - { - Info->EnumLogFontEx.elfLogFont.lfCharSet = CharSetInfo.ciCharset; - if (NULL != ElfScripts[i]) - { - wcscpy(Info->EnumLogFontEx.elfScript, ElfScripts[i]); - } - else - { - DPRINT1("Unknown elfscript for bit %d\n", i); - } - } - } - } - } -} - -static int FASTCALL -FindFaceNameInInfo(PUNICODE_STRING FaceName, PFONTFAMILYINFO Info, DWORD InfoEntries) -{ - DWORD i; - UNICODE_STRING InfoFaceName; - - for (i = 0; i < InfoEntries; i++) - { - RtlInitUnicodeString(&InfoFaceName, Info[i].EnumLogFontEx.elfLogFont.lfFaceName); - if (0 == RtlCompareUnicodeString(&InfoFaceName, FaceName, TRUE)) - { - return i; - } - } - - return -1; -} - -static BOOLEAN FASTCALL -FontFamilyInclude(LPLOGFONTW LogFont, PUNICODE_STRING FaceName, - PFONTFAMILYINFO Info, DWORD InfoEntries) -{ - UNICODE_STRING LogFontFaceName; - - RtlInitUnicodeString(&LogFontFaceName, LogFont->lfFaceName); - if (0 != LogFontFaceName.Length - && 0 != RtlCompareUnicodeString(&LogFontFaceName, FaceName, TRUE)) - { - return FALSE; - } - - return FindFaceNameInInfo(FaceName, Info, InfoEntries) < 0; -} - -static BOOLEAN FASTCALL -GetFontFamilyInfoForList(LPLOGFONTW LogFont, - PFONTFAMILYINFO Info, - DWORD *Count, - DWORD Size, - PLIST_ENTRY Head) -{ - PLIST_ENTRY Entry; - PFONT_ENTRY CurrentEntry; - ANSI_STRING EntryFaceNameA; - UNICODE_STRING EntryFaceNameW; - FONTGDI *FontGDI; - - Entry = Head->Flink; - while (Entry != Head) - { - CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry); - - FontGDI = CurrentEntry->Font; - ASSERT(FontGDI); - - RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); - RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); - if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length) - { - EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR); - EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0'; - } - - if (FontFamilyInclude(LogFont, &EntryFaceNameW, Info, min(*Count, Size))) - { - if (*Count < Size) - { - FontFamilyFillInfo(Info + *Count, EntryFaceNameW.Buffer, FontGDI); - } - (*Count)++; - } - RtlFreeUnicodeString(&EntryFaceNameW); - Entry = Entry->Flink; - } - - return TRUE; -} - -typedef struct FontFamilyInfoCallbackContext -{ - LPLOGFONTW LogFont; - PFONTFAMILYINFO Info; - DWORD Count; - DWORD Size; -} FONT_FAMILY_INFO_CALLBACK_CONTEXT, *PFONT_FAMILY_INFO_CALLBACK_CONTEXT; - -static NTSTATUS STDCALL -FontFamilyInfoQueryRegistryCallback(IN PWSTR ValueName, IN ULONG ValueType, - IN PVOID ValueData, IN ULONG ValueLength, - IN PVOID Context, IN PVOID EntryContext) -{ - PFONT_FAMILY_INFO_CALLBACK_CONTEXT InfoContext; - UNICODE_STRING RegistryName, RegistryValue; - int Existing; - PFONTGDI FontGDI; - - if (REG_SZ != ValueType) - { - return STATUS_SUCCESS; - } - InfoContext = (PFONT_FAMILY_INFO_CALLBACK_CONTEXT) Context; - RtlInitUnicodeString(&RegistryName, ValueName); - - /* Do we need to include this font family? */ - if (FontFamilyInclude(InfoContext->LogFont, &RegistryName, InfoContext->Info, - min(InfoContext->Count, InfoContext->Size))) - { - RtlInitUnicodeString(&RegistryValue, (PCWSTR) ValueData); - Existing = FindFaceNameInInfo(&RegistryValue, InfoContext->Info, - min(InfoContext->Count, InfoContext->Size)); - if (0 <= Existing) - { - /* We already have the information about the "real" font. Just copy it */ - if (InfoContext->Count < InfoContext->Size) - { - InfoContext->Info[InfoContext->Count] = InfoContext->Info[Existing]; - wcsncpy(InfoContext->Info[InfoContext->Count].EnumLogFontEx.elfLogFont.lfFaceName, - RegistryName.Buffer, LF_FACESIZE); - } - InfoContext->Count++; - return STATUS_SUCCESS; - } - - /* Try to find information about the "real" font */ - FontGDI = FindFaceNameInLists(&RegistryValue); - if (NULL == FontGDI) - { - /* "Real" font not found, discard this registry entry */ - return STATUS_SUCCESS; - } - - /* Return info about the "real" font but with the name of the alias */ - if (InfoContext->Count < InfoContext->Size) - { - FontFamilyFillInfo(InfoContext->Info + InfoContext->Count, - RegistryName.Buffer, FontGDI); - } - InfoContext->Count++; - return STATUS_SUCCESS; - } - - return STATUS_SUCCESS; -} - -static BOOLEAN FASTCALL -GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont, - PFONTFAMILYINFO Info, - DWORD *Count, - DWORD Size) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}}; - FONT_FAMILY_INFO_CALLBACK_CONTEXT Context; - NTSTATUS Status; - - /* Enumerate font families found in HKLM\Software\Microsoft\Windows NT\CurrentVersion\SysFontSubstitutes - The real work is done in the registry callback function */ - Context.LogFont = LogFont; - Context.Info = Info; - Context.Count = *Count; - Context.Size = Size; - - QueryTable[0].QueryRoutine = FontFamilyInfoQueryRegistryCallback; - QueryTable[0].Flags = 0; - QueryTable[0].Name = NULL; - QueryTable[0].EntryContext = NULL; - QueryTable[0].DefaultType = REG_NONE; - QueryTable[0].DefaultData = NULL; - QueryTable[0].DefaultLength = 0; - - QueryTable[1].QueryRoutine = NULL; - QueryTable[1].Name = NULL; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT, - L"SysFontSubstitutes", - QueryTable, - &Context, - NULL); - if (NT_SUCCESS(Status)) - { - *Count = Context.Count; - } - - return NT_SUCCESS(Status) || STATUS_OBJECT_NAME_NOT_FOUND == Status; -} - -int STDCALL -NtGdiGetFontFamilyInfo(HDC Dc, - LPLOGFONTW UnsafeLogFont, - PFONTFAMILYINFO UnsafeInfo, - DWORD Size) -{ - NTSTATUS Status; - LOGFONTW LogFont; - PFONTFAMILYINFO Info; - DWORD Count; - PW32PROCESS Win32Process; - - /* Make a safe copy */ - Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW)); - if (! NT_SUCCESS(Status)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return -1; - } - - /* Allocate space for a safe copy */ - Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), TAG_GDITEXT); - if (NULL == Info) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return -1; - } - - /* Enumerate font families in the global list */ - IntLockGlobalFonts; - Count = 0; - if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size, &FontListHead) ) - { - IntUnLockGlobalFonts; - ExFreePool(Info); - return -1; - } - IntUnLockGlobalFonts; - - /* Enumerate font families in the process local list */ - Win32Process = PsGetCurrentProcessWin32Process(); - IntLockProcessPrivateFonts(Win32Process); - if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size, - &Win32Process->PrivateFontListHead)) - { - IntUnLockProcessPrivateFonts(Win32Process); - ExFreePool(Info); - return -1; - } - IntUnLockProcessPrivateFonts(Win32Process); - - /* Enumerate font families in the registry */ - if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size)) - { - ExFreePool(Info); - return -1; - } - - /* Return data to caller */ - if (0 != Count) - { - Status = MmCopyToCaller(UnsafeInfo, Info, - (Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO)); - if (! NT_SUCCESS(Status)) - { - ExFreePool(Info); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return -1; - } - } - - ExFreePool(Info); - - return Count; -} - -FT_Glyph STDCALL -NtGdiGlyphCacheGet( - FT_Face Face, - INT GlyphIndex, - INT Height) -{ - PLIST_ENTRY CurrentEntry; - PFONT_CACHE_ENTRY FontEntry; - -// DbgPrint("CacheGet\n"); - - CurrentEntry = FontCacheListHead.Flink; - while (CurrentEntry != &FontCacheListHead) - { - FontEntry = (PFONT_CACHE_ENTRY)CurrentEntry; - if (FontEntry->Face == Face && - FontEntry->GlyphIndex == GlyphIndex && - FontEntry->Height == Height) - break; - CurrentEntry = CurrentEntry->Flink; - } - - if (CurrentEntry == &FontCacheListHead) { -// DbgPrint("Miss! %x\n", FontEntry->Glyph); -/* - Misses++; - if (Misses>100) { - DbgPrint ("Hits: %d Misses: %d\n", Hits, Misses); - Hits = Misses = 0; - } -*/ - return NULL; - } - - RemoveEntryList(CurrentEntry); - InsertHeadList(&FontCacheListHead, CurrentEntry); - -// DbgPrint("Hit! %x\n", FontEntry->Glyph); -/* - Hits++; - - if (Hits>100) { - DbgPrint ("Hits: %d Misses: %d\n", Hits, Misses); - Hits = Misses = 0; - } -*/ - return FontEntry->Glyph; -} - -FT_Glyph STDCALL -NtGdiGlyphCacheSet( - FT_Face Face, - INT GlyphIndex, - INT Height, - FT_GlyphSlot GlyphSlot, - FT_Render_Mode RenderMode) -{ - FT_Glyph GlyphCopy; - INT error; - PFONT_CACHE_ENTRY NewEntry; - -// DbgPrint("CacheSet.\n"); - - error = FT_Get_Glyph(GlyphSlot, &GlyphCopy); - if (error) - { - DbgPrint("Failure caching glyph.\n"); - return NULL; - }; - error = FT_Glyph_To_Bitmap(&GlyphCopy, RenderMode, 0, 1); - if (error) - { - DbgPrint("Failure rendering glyph.\n"); - return NULL; - }; - - NewEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_CACHE_ENTRY), TAG_FONT); - if (!NewEntry) - { - DbgPrint("Alloc failure caching glyph.\n"); - FT_Done_Glyph(GlyphCopy); - return NULL; - } - - NewEntry->GlyphIndex = GlyphIndex; - NewEntry->Face = Face; - NewEntry->Glyph = GlyphCopy; - NewEntry->Height = Height; - - InsertHeadList(&FontCacheListHead, &NewEntry->ListEntry); - if (FontCacheNumEntries++ > MAX_FONT_CACHE) { - NewEntry = (PFONT_CACHE_ENTRY)FontCacheListHead.Blink; - FT_Done_Glyph(NewEntry->Glyph); - RemoveTailList(&FontCacheListHead); - ExFreePool(NewEntry); - FontCacheNumEntries--; - } - -// DbgPrint("Returning the glyphcopy: %x\n", GlyphCopy); - - return GlyphCopy; -} - BOOL -APIENTRY -NtGdiExtTextOutW( - IN HDC hDC, - IN INT XStart, - IN INT YStart, - IN UINT fuOptions, - IN OPTIONAL LPRECT lprc, - IN LPWSTR UnsafeString, - IN INT Count, - IN OPTIONAL LPINT UnsafeDx, - IN DWORD dwCodePage) -{ - /* - * FIXME: - * Call EngTextOut, which does the real work (calling DrvTextOut where - * appropriate) - */ - - DC *dc; - PDC_ATTR Dc_Attr; - SURFOBJ *SurfObj; - BITMAPOBJ *BitmapObj = NULL; - int error, glyph_index, n, i; - FT_Face face; - FT_GlyphSlot glyph; - FT_Glyph realglyph; - FT_BitmapGlyph realglyph2; - LONGLONG TextLeft, RealXStart; - ULONG TextTop, previous, BackgroundLeft; - FT_Bool use_kerning; - RECTL DestRect, MaskRect, SpecifiedDestRect; - POINTL SourcePoint, BrushOrigin; - HBRUSH hBrushFg = NULL; - PGDIBRUSHOBJ BrushFg = NULL; - GDIBRUSHINST BrushFgInst; - HBRUSH hBrushBg = NULL; - PGDIBRUSHOBJ BrushBg = NULL; - GDIBRUSHINST BrushBgInst; - HBITMAP HSourceGlyph; - SURFOBJ *SourceGlyphSurf; - SIZEL bitSize; - FT_CharMap found = 0, charmap; - INT yoff; - FONTOBJ *FontObj; - PFONTGDI FontGDI; - PTEXTOBJ TextObj = NULL; - PPALGDI PalDestGDI; - XLATEOBJ *XlateObj=NULL, *XlateObj2=NULL; - ULONG Mode; - FT_Render_Mode RenderMode; - BOOLEAN Render; - NTSTATUS Status; - INT *Dx = NULL; - POINT Start; - BOOL DoBreak = FALSE; - LPCWSTR String, SafeString = NULL; - HPALETTE hDestPalette; - - // TODO: Write test-cases to exactly match real Windows in different - // bad parameters (e.g. does Windows check the DC or the RECT first?). - dc = DC_LockDc(hDC); - if (!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - if (dc->DC_Type == DC_TYPE_INFO) - { - DC_UnlockDc(dc); - /* Yes, Windows really returns TRUE in this case */ - return TRUE; - } - - Dc_Attr = dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; - - /* Check if String is valid */ - if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - goto fail; - } - if (Count > 0) - { - SafeString = ExAllocatePoolWithTag(PagedPool, Count * sizeof(WCHAR), TAG_GDITEXT); - if (!SafeString) - { - goto fail; - } - Status = MmCopyFromCaller(SafeString, UnsafeString, Count * sizeof(WCHAR)); - if (! NT_SUCCESS(Status)) - { - goto fail; - } - } - String = SafeString; - - if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED))) - { - // At least one of the two flags were specified. Copy lprc. Once. - Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT)); - if (!NT_SUCCESS(Status)) - { - DC_UnlockDc(dc); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2); - } - - if (NULL != UnsafeDx && Count > 0) - { - Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT); - if (NULL == Dx) - { - goto fail; - } - Status = MmCopyFromCaller(Dx, UnsafeDx, Count * sizeof(INT)); - if (! NT_SUCCESS(Status)) - { - goto fail; - } - } - - BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap); - if ( !BitmapObj ) - { - goto fail; - } - SurfObj = &BitmapObj->SurfObj; - ASSERT(SurfObj); - - Start.x = XStart; Start.y = YStart; - IntLPtoDP(dc, &Start, 1); - - RealXStart = (Start.x + dc->ptlDCOrig.x) << 6; - YStart = Start.y + dc->ptlDCOrig.y; - - /* Create the brushes */ - hDestPalette = BitmapObj->hDIBPalette; - if (!hDestPalette) hDestPalette = pPrimarySurface->DevInfo.hpalDefault; - PalDestGDI = PALETTE_LockPalette(hDestPalette); - if ( !PalDestGDI ) - Mode = PAL_RGB; - else - { - Mode = PalDestGDI->Mode; - PALETTE_UnlockPalette(PalDestGDI); - } - XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, hDestPalette, NULL); - if ( !XlateObj ) - { - goto fail; - } - hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, Dc_Attr->crForegroundClr), 0); - if ( !hBrushFg ) - { - goto fail; - } - BrushFg = BRUSHOBJ_LockBrush(hBrushFg); - if ( !BrushFg ) - { - goto fail; - } - IntGdiInitBrushInstance(&BrushFgInst, BrushFg, NULL); - if ((fuOptions & ETO_OPAQUE) || Dc_Attr->jBkMode == OPAQUE) - { - hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, Dc_Attr->crBackgroundClr), 0); - if ( !hBrushBg ) - { - goto fail; - } - BrushBg = BRUSHOBJ_LockBrush(hBrushBg); - if ( !BrushBg ) - { - goto fail; - } - IntGdiInitBrushInstance(&BrushBgInst, BrushBg, NULL); - } - XlateObj2 = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, hDestPalette); - if ( !XlateObj2 ) - { - goto fail; - } - - SourcePoint.x = 0; - SourcePoint.y = 0; - MaskRect.left = 0; - MaskRect.top = 0; - BrushOrigin.x = 0; - BrushOrigin.y = 0; - - if ((fuOptions & ETO_OPAQUE) && lprc) - { - DestRect.left = SpecifiedDestRect.left + dc->ptlDCOrig.x; - DestRect.top = SpecifiedDestRect.top + dc->ptlDCOrig.y; - DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x; - DestRect.bottom = SpecifiedDestRect.bottom + dc->ptlDCOrig.y; - IntLPtoDP(dc, (LPPOINT)&DestRect, 2); - IntEngBitBlt( - &BitmapObj->SurfObj, - NULL, - NULL, - dc->CombinedClip, - NULL, - &DestRect, - &SourcePoint, - &SourcePoint, - &BrushBgInst.BrushObject, - &BrushOrigin, - ROP3_TO_ROP4(PATCOPY)); - fuOptions &= ~ETO_OPAQUE; - } - else - { - if (Dc_Attr->jBkMode == OPAQUE) - { - fuOptions |= ETO_OPAQUE; - } - } - - TextObj = TEXTOBJ_LockText(Dc_Attr->hlfntNew); - if(TextObj == NULL) - { - goto fail; - } - - FontObj = TextObj->Font; - ASSERT(FontObj); - FontGDI = ObjToGDI(FontObj, FONT); - ASSERT(FontGDI); - - IntLockFreeType; - face = FontGDI->face; - if (face->charmap == NULL) - { - DPRINT("WARNING: No charmap selected!\n"); - DPRINT("This font face has %d charmaps\n", face->num_charmaps); - - for (n = 0; n < face->num_charmaps; n++) - { - charmap = face->charmaps[n]; - DPRINT("found charmap encoding: %u\n", charmap->encoding); - if (charmap->encoding != 0) - { - found = charmap; - break; - } - } - if (!found) - { - DPRINT1("WARNING: Could not find desired charmap!\n"); - } - error = FT_Set_Charmap(face, found); - if (error) - { - DPRINT1("WARNING: Could not set the charmap!\n"); - } - } - - Render = IntIsFontRenderingEnabled(); - if (Render) - RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont); - else - RenderMode = FT_RENDER_MODE_MONO; - - error = FT_Set_Pixel_Sizes( - face, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, - /* FIXME should set character height if neg */ - (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); - if (error) - { - DPRINT1("Error in setting pixel sizes: %u\n", error); - IntUnLockFreeType; - goto fail; - } - - /* - * Process the vertical alignment and determine the yoff. - */ - - if (Dc_Attr->lTextAlign & TA_BASELINE) - yoff = 0; - else if (Dc_Attr->lTextAlign & TA_BOTTOM) - yoff = -face->size->metrics.descender >> 6; - else /* TA_TOP */ - yoff = face->size->metrics.ascender >> 6; - - use_kerning = FT_HAS_KERNING(face); - previous = 0; - - /* - * Process the horizontal alignment and modify XStart accordingly. - */ - - if (Dc_Attr->lTextAlign & (TA_RIGHT | TA_CENTER)) - { - ULONGLONG TextWidth = 0; - LPCWSTR TempText = String; - int Start; - - /* - * Calculate width of the text. - */ - - if (NULL != Dx) - { - Start = Count < 2 ? 0 : Count - 2; - TextWidth = Count < 2 ? 0 : (Dx[Count - 2] << 6); - } - else - { - Start = 0; - } - TempText = String + Start; - - for (i = Start; i < Count; i++) - { - if (fuOptions & ETO_GLYPH_INDEX) - glyph_index = *TempText; - else - glyph_index = FT_Get_Char_Index(face, *TempText); - - if (!(realglyph = NtGdiGlyphCacheGet(face, glyph_index, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight))) - { - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - if (error) - { - DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index); - } - - glyph = face->glyph; - realglyph = NtGdiGlyphCacheSet(face, glyph_index, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode); - if (!realglyph) - { - DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index); - IntUnLockFreeType; - goto fail; - } - - } - /* retrieve kerning distance */ - if (use_kerning && previous && glyph_index) - { - FT_Vector delta; - FT_Get_Kerning(face, previous, glyph_index, 0, &delta); - TextWidth += delta.x; - } - - TextWidth += realglyph->advance.x >> 10; - - previous = glyph_index; - TempText++; - } - - previous = 0; - - if (Dc_Attr->lTextAlign & TA_RIGHT) - { - RealXStart -= TextWidth; - } - else - { - RealXStart -= TextWidth / 2; - } - } - - TextLeft = RealXStart; - TextTop = YStart; - BackgroundLeft = (RealXStart + 32) >> 6; - - /* - * The main rendering loop. - */ - - for (i = 0; i < Count; i++) - { - if (fuOptions & ETO_GLYPH_INDEX) - glyph_index = *String; - else - glyph_index = FT_Get_Char_Index(face, *String); - - if (!(realglyph = NtGdiGlyphCacheGet(face, glyph_index, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight))) - { - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - if (error) - { - DPRINT1("Failed to load and render glyph! [index: %u]\n", glyph_index); - IntUnLockFreeType; - goto fail; - } - glyph = face->glyph; - realglyph = NtGdiGlyphCacheSet(face, - glyph_index, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, - glyph, - RenderMode); - if (!realglyph) - { - DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index); - IntUnLockFreeType; - goto fail; - } - } -// DbgPrint("realglyph: %x\n", realglyph); -// DbgPrint("TextLeft: %d\n", TextLeft); - - /* retrieve kerning distance and move pen position */ - if (use_kerning && previous && glyph_index && NULL == Dx) - { - FT_Vector delta; - FT_Get_Kerning(face, previous, glyph_index, 0, &delta); - TextLeft += delta.x; - } -// DPRINT1("TextLeft: %d\n", TextLeft); -// DPRINT1("TextTop: %d\n", TextTop); - - if (realglyph->format == ft_glyph_format_outline) - { - DbgPrint("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 fail; - } - } - realglyph2 = (FT_BitmapGlyph)realglyph; - -// DPRINT1("Pitch: %d\n", pitch); -// DPRINT1("Advance: %d\n", realglyph->advance.x); - - if (fuOptions & ETO_OPAQUE) - { - DestRect.left = BackgroundLeft; - DestRect.right = (TextLeft + (realglyph->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( - &BitmapObj->SurfObj, - NULL, - NULL, - dc->CombinedClip, - NULL, - &DestRect, - &SourcePoint, - &SourcePoint, - &BrushBgInst.BrushObject, - &BrushOrigin, - ROP3_TO_ROP4(PATCOPY)); - 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; - - bitSize.cx = realglyph2->bitmap.width; - bitSize.cy = realglyph2->bitmap.rows; - MaskRect.right = realglyph2->bitmap.width; - MaskRect.bottom = realglyph2->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); - if ( !HSourceGlyph ) - { - DPRINT1("WARNING: EngLockSurface() failed!\n"); - // FT_Done_Glyph(realglyph); - IntUnLockFreeType; - goto fail; - } - SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph); - if ( !SourceGlyphSurf ) - { - EngDeleteSurface((HSURF)HSourceGlyph); - DPRINT1("WARNING: EngLockSurface() failed!\n"); - IntUnLockFreeType; - goto fail; - } - - /* - * Use the font data as a mask to paint onto the DCs surface using a - * brush. - */ - - if (lprc && - (fuOptions & ETO_CLIPPED) && - DestRect.right >= SpecifiedDestRect.right + dc->ptlDCOrig.x) - { - // We do the check '>=' instead of '>' to possibly save an iteration - // through this loop, since it's breaking after the drawing is done, - // and x is always incremented. - DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x; - DoBreak = TRUE; - } - - IntEngMaskBlt( - SurfObj, - SourceGlyphSurf, - dc->CombinedClip, - XlateObj, - XlateObj2, - &DestRect, - &SourcePoint, - (PPOINTL)&MaskRect, - &BrushFgInst.BrushObject, - &BrushOrigin); - - EngUnlockSurface(SourceGlyphSurf); - EngDeleteSurface((HSURF)HSourceGlyph); - - if (DoBreak) - { - break; - } - - if (NULL == Dx) - { - TextLeft += realglyph->advance.x >> 10; -// DbgPrint("new TextLeft: %d\n", TextLeft); - } - else - { - TextLeft += Dx[i] << 6; -// DbgPrint("new TextLeft2: %d\n", TextLeft); - } - previous = glyph_index; - - String++; - } - - IntUnLockFreeType; - - EngDeleteXlate(XlateObj); - EngDeleteXlate(XlateObj2); - BITMAPOBJ_UnlockBitmap(BitmapObj); - if(TextObj != NULL) - TEXTOBJ_UnlockText(TextObj); - if (hBrushBg != NULL) - { - BRUSHOBJ_UnlockBrush(BrushBg); - NtGdiDeleteObject(hBrushBg); - } - BRUSHOBJ_UnlockBrush(BrushFg); - NtGdiDeleteObject(hBrushFg); - if (NULL != SafeString) - { - ExFreePool((void*)SafeString); - } - if (NULL != Dx) - { - ExFreePool(Dx); - } - DC_UnlockDc( dc ); - - return TRUE; - -fail: - if ( XlateObj2 != NULL ) - EngDeleteXlate(XlateObj2); - if ( XlateObj != NULL ) - EngDeleteXlate(XlateObj); - if(TextObj != NULL) - TEXTOBJ_UnlockText(TextObj); - if (BitmapObj != NULL) - BITMAPOBJ_UnlockBitmap(BitmapObj); - if (hBrushBg != NULL) - { - BRUSHOBJ_UnlockBrush(BrushBg); - NtGdiDeleteObject(hBrushBg); - } - if (hBrushFg != NULL) - { - BRUSHOBJ_UnlockBrush(BrushFg); - NtGdiDeleteObject(hBrushFg); - } - if (NULL != SafeString) - { - ExFreePool((void*)SafeString); - } - if (NULL != Dx) - { - ExFreePool(Dx); - } - DC_UnlockDc(dc); - - return FALSE; -} - - /* - * @implemented - */ -BOOL -STDCALL -NtGdiGetCharABCWidthsW( - IN HDC hDC, - IN UINT FirstChar, - IN ULONG Count, - IN OPTIONAL PWCHAR pwch, - IN FLONG fl, - OUT PVOID Buffer) -{ - LPABC SafeBuff; - LPABCFLOAT SafeBuffF = NULL; - PDC dc; - PDC_ATTR Dc_Attr; - PTEXTOBJ TextObj; - PFONTGDI FontGDI; - FT_Face face; - FT_CharMap charmap, found = NULL; - UINT i, glyph_index, BufferSize; - HFONT hFont = 0; - NTSTATUS Status = STATUS_SUCCESS; - - if(pwch) - { - _SEH_TRY - { - ProbeForRead(pwch, - sizeof(PWSTR), - 1); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - if (!NT_SUCCESS(Status)) - { - SetLastWin32Error(Status); - return FALSE; - } - - BufferSize = Count * sizeof(ABC); // Same size! - SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT); - if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff; - if (SafeBuff == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - dc = DC_LockDc(hDC); - if (dc == NULL) - { - ExFreePool(SafeBuff); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - Dc_Attr = dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; - hFont = Dc_Attr->hlfntNew; - TextObj = TEXTOBJ_LockText(hFont); - DC_UnlockDc(dc); - - if (TextObj == NULL) - { - ExFreePool(SafeBuff); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - FontGDI = ObjToGDI(TextObj->Font, FONT); - - face = FontGDI->face; - if (face->charmap == NULL) - { - for (i = 0; i < face->num_charmaps; i++) - { - charmap = face->charmaps[i]; - if (charmap->encoding != 0) - { - found = charmap; - break; - } - } - - if (!found) - { - DPRINT1("WARNING: Could not find desired charmap!\n"); - ExFreePool(SafeBuff); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - IntLockFreeType; - FT_Set_Charmap(face, found); - IntUnLockFreeType; - } - - IntLockFreeType; - FT_Set_Pixel_Sizes(face, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, - /* FIXME should set character height if neg */ - (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); - - for (i = FirstChar; i < FirstChar+Count; i++) - { - int adv, lsb, bbx, left, right; - - if (pwch) - { - if (fl & GCABCW_INDICES) - glyph_index = pwch[i - FirstChar]; - else - glyph_index = FT_Get_Char_Index(face, pwch[i - FirstChar]); - } - else - { - if (fl & GCABCW_INDICES) - glyph_index = i; - else - glyph_index = FT_Get_Char_Index(face, i); - } - FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - - left = (INT)face->glyph->metrics.horiBearingX & -64; - right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64; - adv = (face->glyph->advance.x + 32) >> 6; - -// int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6; -// DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same!*/ - - lsb = left >> 6; - bbx = (right - left) >> 6; -/* - DPRINT1("lsb %d and bbx %d\n", lsb, bbx ); - */ - if (!fl) - { - SafeBuffF[i - FirstChar].abcfA = (FLOAT) lsb; - SafeBuffF[i - FirstChar].abcfB = (FLOAT) bbx; - SafeBuffF[i - FirstChar].abcfC = (FLOAT) (adv - lsb - bbx); - } - else - { - SafeBuff[i - FirstChar].abcA = lsb; - SafeBuff[i - FirstChar].abcB = bbx; - SafeBuff[i - FirstChar].abcC = adv - lsb - bbx; - } - } - IntUnLockFreeType; - TEXTOBJ_UnlockText(TextObj); - Status = MmCopyToCaller(Buffer, SafeBuff, BufferSize); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - ExFreePool(SafeBuff); - return FALSE; - } - ExFreePool(SafeBuff); - DPRINT("NtGdiGetCharABCWidths Worked!\n"); - return TRUE; -} - - /* - * @implemented - */ -BOOL -STDCALL -NtGdiGetCharWidthW( - IN HDC hDC, - IN UINT FirstChar, - IN UINT Count, - IN OPTIONAL PWCHAR pwc, - IN FLONG fl, - OUT PVOID Buffer) -{ - NTSTATUS Status = STATUS_SUCCESS; - LPINT SafeBuff; - PFLOAT SafeBuffF = NULL; - PDC dc; - PDC_ATTR Dc_Attr; - PTEXTOBJ TextObj; - PFONTGDI FontGDI; - FT_Face face; - FT_CharMap charmap, found = NULL; - UINT i, glyph_index, BufferSize; - HFONT hFont = 0; - - if(pwc) - { - _SEH_TRY - { - ProbeForRead(pwc, - sizeof(PWSTR), - 1); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - if (!NT_SUCCESS(Status)) - { - SetLastWin32Error(Status); - return FALSE; - } - - BufferSize = Count * sizeof(INT); // Same size! - SafeBuff = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT); - if (!fl) SafeBuffF = (PFLOAT) SafeBuff; - if (SafeBuff == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - dc = DC_LockDc(hDC); - if (dc == NULL) - { - ExFreePool(SafeBuff); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - Dc_Attr = dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; - hFont = Dc_Attr->hlfntNew; - TextObj = TEXTOBJ_LockText(hFont); - DC_UnlockDc(dc); - - if (TextObj == NULL) - { - ExFreePool(SafeBuff); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - FontGDI = ObjToGDI(TextObj->Font, FONT); - - face = FontGDI->face; - if (face->charmap == NULL) - { - for (i = 0; i < face->num_charmaps; i++) - { - charmap = face->charmaps[i]; - if (charmap->encoding != 0) - { - found = charmap; - break; - } - } - - if (!found) - { - DPRINT1("WARNING: Could not find desired charmap!\n"); - ExFreePool(SafeBuff); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - IntLockFreeType; - FT_Set_Charmap(face, found); - IntUnLockFreeType; - } - - IntLockFreeType; - FT_Set_Pixel_Sizes(face, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, - /* FIXME should set character height if neg */ - (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); - - for (i = FirstChar; i < FirstChar+Count; i++) - { - if (pwc) - { - if (fl & GCW_INDICES) - glyph_index = pwc[i - FirstChar]; - else - glyph_index = FT_Get_Char_Index(face, pwc[i - FirstChar]); - } - else - { - if (fl & GCW_INDICES) - glyph_index = i; - else - glyph_index = FT_Get_Char_Index(face, i); - } - FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - if (!fl) - SafeBuffF[i - FirstChar] = (FLOAT) ((face->glyph->advance.x + 32) >> 6); - else - SafeBuff[i - FirstChar] = (face->glyph->advance.x + 32) >> 6; - } - IntUnLockFreeType; - TEXTOBJ_UnlockText(TextObj); - MmCopyToCaller(Buffer, SafeBuff, BufferSize); - ExFreePool(SafeBuff); - return TRUE; -} - - - /* - * @implemented - */ -DWORD -STDCALL -NtGdiGetGlyphIndicesW( - IN HDC hdc, - IN OPTIONAL LPWSTR UnSafepwc, - IN INT cwc, - OUT OPTIONAL LPWORD UnSafepgi, - IN DWORD iMode) -{ - PDC dc; - PDC_ATTR Dc_Attr; - PTEXTOBJ TextObj; - PFONTGDI FontGDI; - HFONT hFont = 0; - NTSTATUS Status = STATUS_SUCCESS; - OUTLINETEXTMETRICW *potm; - INT i; - FT_Face face; - WCHAR DefChar = 0; - PWSTR Buffer = NULL; - ULONG Size; - - if ((!UnSafepwc) && (!UnSafepgi)) return cwc; - - dc = DC_LockDc(hdc); - if (!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return GDI_ERROR; - } - Dc_Attr = dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; - hFont = Dc_Attr->hlfntNew; - TextObj = TEXTOBJ_LockText(hFont); - DC_UnlockDc(dc); - if (!TextObj) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return GDI_ERROR; - } - - FontGDI = ObjToGDI(TextObj->Font, FONT); - TEXTOBJ_UnlockText(TextObj); - - Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), TAG_GDITEXT); - if (!Buffer) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return GDI_ERROR; - } - - if (iMode & GGI_MARK_NONEXISTING_GLYPHS) DefChar = 0x001f; /* Indicate non existence */ - else - { - Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); - potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); - if (!potm) - { - Status = ERROR_NOT_ENOUGH_MEMORY; - goto ErrorRet; - } - IntGetOutlineTextMetrics(FontGDI, Size, potm); - DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this. - ExFreePool(potm); - } - - _SEH_TRY - { - ProbeForRead(UnSafepwc, - sizeof(PWSTR), - 1); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) goto ErrorRet; - - IntLockFreeType; - face = FontGDI->face; - - for (i = 0; i < cwc; i++) - { - Buffer[i] = FT_Get_Char_Index(face, UnSafepwc[i]); - if (Buffer[i] == 0) Buffer[i] = DefChar; - } - - IntUnLockFreeType; - - _SEH_TRY - { - ProbeForWrite(UnSafepgi, - sizeof(WORD), - 1); - RtlCopyMemory(UnSafepgi, - Buffer, - cwc*sizeof(WORD)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - -ErrorRet: - ExFreePool(Buffer); - if (NT_SUCCESS(Status)) return cwc; - SetLastWin32Error(Status); - return GDI_ERROR; -} - -static -void -FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt) -{ - pt->x.value = vec->x >> 6; - pt->x.fract = (vec->x & 0x3f) << 10; - pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12)); - pt->y.value = vec->y >> 6; - pt->y.fract = (vec->y & 0x3f) << 10; - pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12)); - return; -} - -/* - This function builds an FT_Fixed from a float. It puts the integer part - in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed. - It fails if the integer part of the float number is greater than SHORT_MAX. -*/ -static __inline FT_Fixed FT_FixedFromFloat(float f) -{ - short value = f; - unsigned short fract = (f - value) * 0xFFFF; - return (FT_Fixed)((long)value << 16 | (unsigned long)fract); -} - -/* - This function builds an FT_Fixed from a FIXED. It simply put f.value - in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed. -*/ -static __inline FT_Fixed FT_FixedFromFIXED(FIXED f) -{ - return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract); -} - -/* - * Based on WineEngGetGlyphOutline - * - */ -ULONG -APIENTRY -NtGdiGetGlyphOutline( - IN HDC hdc, - IN WCHAR wch, - IN UINT iFormat, - OUT LPGLYPHMETRICS pgm, - IN ULONG cjBuf, - OUT OPTIONAL PVOID UnsafeBuf, - IN LPMAT2 pmat2, - IN BOOL bIgnoreRotation) -{ - static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)}; - PDC dc; - PDC_ATTR Dc_Attr; - PTEXTOBJ TextObj; - PFONTGDI FontGDI; - HFONT hFont = 0; - NTSTATUS Status; - GLYPHMETRICS gm; - ULONG Size; - FT_Face ft_face; - FT_UInt glyph_index; - DWORD width, height, pitch, needed = 0; - FT_Bitmap ft_bitmap; - FT_Error error; - INT left, right, top = 0, bottom = 0; - FT_Angle angle = 0; - FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; - FLOAT eM11, widthRatio = 1.0; - FT_Matrix transMat = identityMat; - BOOL needsTransform = FALSE; - INT orientation; - LONG aveWidth; - INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */ - OUTLINETEXTMETRICW *potm; - PVOID pvBuf = NULL; - int n = 0; - FT_CharMap found = 0, charmap; - XFORM xForm; - - DPRINT("%p, %d, %08x, %p, %08lx, %p, %p\n", hdc, wch, iFormat, pgm, - cjBuf, UnsafeBuf, pmat2); - - dc = DC_LockDc(hdc); - if (!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return GDI_ERROR; - } - Dc_Attr = dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; - - MatrixS2XForm(&xForm, &dc->DcLevel.mxWorldToDevice); - eM11 = xForm.eM11; - - hFont = Dc_Attr->hlfntNew; - TextObj = TEXTOBJ_LockText(hFont); - DC_UnlockDc(dc); - if (!TextObj) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return GDI_ERROR; - } - FontGDI = ObjToGDI(TextObj->Font, FONT); - ft_face = FontGDI->face; - - aveWidth = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth: 0; - orientation = FT_IS_SCALABLE(ft_face) ? TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation: 0; - - Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); - potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); - if (!potm) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - TEXTOBJ_UnlockText(TextObj); - return GDI_ERROR; - } - IntGetOutlineTextMetrics(FontGDI, Size, potm); - - IntLockFreeType; - - /* During testing, I never saw this used. In here just incase.*/ - if (ft_face->charmap == NULL) - { - DPRINT("WARNING: No charmap selected!\n"); - DPRINT("This font face has %d charmaps\n", ft_face->num_charmaps); - - - - for (n = 0; n < ft_face->num_charmaps; n++) - { - charmap = ft_face->charmaps[n]; - DPRINT("found charmap encoding: %u\n", charmap->encoding); - if (charmap->encoding != 0) - { - found = charmap; - break; - } - } - if (!found) - { - DPRINT1("WARNING: Could not find desired charmap!\n"); - } - error = FT_Set_Charmap(ft_face, found); - if (error) - { - DPRINT1("WARNING: Could not set the charmap!\n"); - } - } - -// FT_Set_Pixel_Sizes(ft_face, -// TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, - /* FIXME should set character height if neg */ -// (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : -// TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); - - TEXTOBJ_UnlockText(TextObj); - - if (iFormat & GGO_GLYPH_INDEX) - { - glyph_index = wch; - iFormat &= ~GGO_GLYPH_INDEX; - } - else glyph_index = FT_Get_Char_Index(ft_face, wch); - - if (orientation || (iFormat != GGO_METRICS && iFormat != GGO_BITMAP) || aveWidth || pmat2) - load_flags |= FT_LOAD_NO_BITMAP; - - error = FT_Load_Glyph(ft_face, glyph_index, load_flags); - if (error) - { - DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index); - IntUnLockFreeType; - if (potm) ExFreePool(potm); - return GDI_ERROR; - } - IntUnLockFreeType; - - if (aveWidth && potm) - { - widthRatio = (FLOAT)aveWidth * eM11 / - (FLOAT) potm->otmTextMetrics.tmAveCharWidth; - } - - left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64; - right = (INT)((ft_face->glyph->metrics.horiBearingX + - ft_face->glyph->metrics.width) * widthRatio + 63) & -64; - - adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6; - lsb = left >> 6; - bbx = (right - left) >> 6; - - DPRINT("Advance = %d, lsb = %d, bbx = %d\n",adv, lsb, bbx); - - IntLockFreeType; - - /* Scaling transform */ - if (aveWidth) - { - FT_Matrix scaleMat; - DPRINT("Scaling Trans!\n"); - scaleMat.xx = FT_FixedFromFloat(widthRatio); - scaleMat.xy = 0; - scaleMat.yx = 0; - scaleMat.yy = (1 << 16); - FT_Matrix_Multiply(&scaleMat, &transMat); - needsTransform = TRUE; - } - - /* Slant transform */ - if (potm->otmTextMetrics.tmItalic) - { - FT_Matrix slantMat; - DPRINT("Slant Trans!\n"); - slantMat.xx = (1 << 16); - slantMat.xy = ((1 << 16) >> 2); - slantMat.yx = 0; - slantMat.yy = (1 << 16); - FT_Matrix_Multiply(&slantMat, &transMat); - needsTransform = TRUE; - } - - /* Rotation transform */ - if (orientation) - { - FT_Matrix rotationMat; - FT_Vector vecAngle; - DPRINT("Rotation Trans!\n"); - angle = FT_FixedFromFloat((float)orientation / 10.0); - FT_Vector_Unit(&vecAngle, angle); - rotationMat.xx = vecAngle.x; - rotationMat.xy = -vecAngle.y; - rotationMat.yx = -rotationMat.xy; - rotationMat.yy = rotationMat.xx; - FT_Matrix_Multiply(&rotationMat, &transMat); - needsTransform = TRUE; - } - - /* Extra transformation specified by caller */ - if (pmat2) - { - FT_Matrix extraMat; - DPRINT("MAT2 Matrix Trans!\n"); - extraMat.xx = FT_FixedFromFIXED(pmat2->eM11); - extraMat.xy = FT_FixedFromFIXED(pmat2->eM21); - extraMat.yx = FT_FixedFromFIXED(pmat2->eM12); - extraMat.yy = FT_FixedFromFIXED(pmat2->eM22); - FT_Matrix_Multiply(&extraMat, &transMat); - needsTransform = TRUE; - } - - if (potm) ExFreePool(potm); /* It looks like we are finished with potm ATM.*/ - - if (!needsTransform) - { - DPRINT("No Need to be Transformed!\n"); - top = (ft_face->glyph->metrics.horiBearingY + 63) & -64; - bottom = (ft_face->glyph->metrics.horiBearingY - - ft_face->glyph->metrics.height) & -64; - gm.gmCellIncX = adv; - gm.gmCellIncY = 0; - } - else - { - INT xc, yc; - FT_Vector vec; - for(xc = 0; xc < 2; xc++) - { - for(yc = 0; yc < 2; yc++) - { - vec.x = (ft_face->glyph->metrics.horiBearingX + - xc * ft_face->glyph->metrics.width); - vec.y = ft_face->glyph->metrics.horiBearingY - - yc * ft_face->glyph->metrics.height; - DPRINT("Vec %ld,%ld\n", vec.x, vec.y); - FT_Vector_Transform(&vec, &transMat); - if(xc == 0 && yc == 0) - { - left = right = vec.x; - top = bottom = vec.y; - } - else - { - if(vec.x < left) left = vec.x; - else if(vec.x > right) right = vec.x; - if(vec.y < bottom) bottom = vec.y; - else if(vec.y > top) top = vec.y; - } - } - } - left = left & -64; - right = (right + 63) & -64; - bottom = bottom & -64; - top = (top + 63) & -64; - - DPRINT("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom); - vec.x = ft_face->glyph->metrics.horiAdvance; - vec.y = 0; - FT_Vector_Transform(&vec, &transMat); - gm.gmCellIncX = (vec.x+63) >> 6; - gm.gmCellIncY = -((vec.y+63) >> 6); - } - gm.gmBlackBoxX = (right - left) >> 6; - gm.gmBlackBoxY = (top - bottom) >> 6; - gm.gmptGlyphOrigin.x = left >> 6; - gm.gmptGlyphOrigin.y = top >> 6; - - DPRINT("CX %d CY %d BBX %d BBY %d GOX %d GOY %d\n", - gm.gmCellIncX, gm.gmCellIncY, - gm.gmBlackBoxX, gm.gmBlackBoxY, - gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y); - - IntUnLockFreeType; - - if (pgm) - { - Status = MmCopyToCaller(pgm, &gm, sizeof(GLYPHMETRICS)); - if (! NT_SUCCESS(Status)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return GDI_ERROR; - } - DPRINT("Copied GLYPHMETRICS to User!\n"); - } - - if (iFormat == GGO_METRICS) - { - DPRINT("GGO_METRICS Exit!\n"); - return 1; /* FIXME */ - } - - if (ft_face->glyph->format != ft_glyph_format_outline && iFormat != GGO_BITMAP) - { - DPRINT1("loaded a bitmap\n"); - return GDI_ERROR; - } - - if (UnsafeBuf && cjBuf) - { - pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT); - if (pvBuf == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return GDI_ERROR; - } - RtlZeroMemory(pvBuf, cjBuf); - } - - - switch(iFormat) - { - case GGO_BITMAP: - width = gm.gmBlackBoxX; - height = gm.gmBlackBoxY; - pitch = ((width + 31) >> 5) << 2; - needed = pitch * height; - - if(!pvBuf || !cjBuf) break; - - switch(ft_face->glyph->format) - { - case ft_glyph_format_bitmap: - { - BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf; - INT w = (ft_face->glyph->bitmap.width + 7) >> 3; - INT h = ft_face->glyph->bitmap.rows; - while(h--) - { - RtlCopyMemory(dst, src, w); - src += ft_face->glyph->bitmap.pitch; - dst += pitch; - } - break; - } - - case ft_glyph_format_outline: - ft_bitmap.width = width; - ft_bitmap.rows = height; - ft_bitmap.pitch = pitch; - ft_bitmap.pixel_mode = ft_pixel_mode_mono; - ft_bitmap.buffer = pvBuf; - - IntLockFreeType; - if(needsTransform) - { - FT_Outline_Transform(&ft_face->glyph->outline, &transMat); - } - FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); - /* Note: FreeType will only set 'black' bits for us. */ - RtlZeroMemory(pvBuf, needed); - FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); - IntUnLockFreeType; - break; - - default: - DPRINT1("loaded glyph format %x\n", ft_face->glyph->format); - if(pvBuf) ExFreePool(pvBuf); - return GDI_ERROR; - } - break; - - case GGO_GRAY2_BITMAP: - case GGO_GRAY4_BITMAP: - case GGO_GRAY8_BITMAP: - { - unsigned int mult, row, col; - BYTE *start, *ptr; - - width = gm.gmBlackBoxX; - height = gm.gmBlackBoxY; - pitch = (width + 3) / 4 * 4; - needed = pitch * height; - - if(!pvBuf || !cjBuf) break; - - ft_bitmap.width = width; - ft_bitmap.rows = height; - ft_bitmap.pitch = pitch; - ft_bitmap.pixel_mode = ft_pixel_mode_grays; - ft_bitmap.buffer = pvBuf; - - IntLockFreeType; - if(needsTransform) - { - FT_Outline_Transform(&ft_face->glyph->outline, &transMat); - } - FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); - RtlZeroMemory(ft_bitmap.buffer, cjBuf); - FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); - IntUnLockFreeType; - - if(iFormat == GGO_GRAY2_BITMAP) - mult = 4; - else if(iFormat == GGO_GRAY4_BITMAP) - mult = 16; - else if(iFormat == GGO_GRAY8_BITMAP) - mult = 64; - else - { - ASSERT(0); - break; - } - - start = pvBuf; - for(row = 0; row < height; row++) - { - ptr = start; - for(col = 0; col < width; col++, ptr++) - { - *ptr = (((int)*ptr) * mult + 128) / 256; - } - start += pitch; - } - break; - } - - case GGO_NATIVE: - { - int contour, point = 0, first_pt; - FT_Outline *outline = &ft_face->glyph->outline; - TTPOLYGONHEADER *pph; - TTPOLYCURVE *ppc; - DWORD pph_start, cpfx, type; - - if(cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */ - - IntLockFreeType; - if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat); - - for(contour = 0; contour < outline->n_contours; contour++) - { - pph_start = needed; - pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed); - first_pt = point; - if(pvBuf) - { - pph->dwType = TT_POLYGON_TYPE; - FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart); - } - needed += sizeof(*pph); - point++; - while(point <= outline->contours[contour]) - { - ppc = (TTPOLYCURVE *)((char *)pvBuf + needed); - type = (outline->tags[point] & FT_Curve_Tag_On) ? - TT_PRIM_LINE : TT_PRIM_QSPLINE; - cpfx = 0; - do - { - if(pvBuf) - FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); - cpfx++; - point++; - } while(point <= outline->contours[contour] && - (outline->tags[point] & FT_Curve_Tag_On) == - (outline->tags[point-1] & FT_Curve_Tag_On)); - - /* At the end of a contour Windows adds the start point, but - only for Beziers */ - if(point > outline->contours[contour] && - !(outline->tags[point-1] & FT_Curve_Tag_On)) - { - if(pvBuf) - FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]); - cpfx++; - } - else if(point <= outline->contours[contour] && - outline->tags[point] & FT_Curve_Tag_On) - { - /* add closing pt for bezier */ - if(pvBuf) - FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); - cpfx++; - point++; - } - if(pvBuf) - { - ppc->wType = type; - ppc->cpfx = cpfx; - } - needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX); - } - if(pvBuf) pph->cb = needed - pph_start; - } - IntUnLockFreeType; - break; - } - case GGO_BEZIER: - { - /* Convert the quadratic Beziers to cubic Beziers. - The parametric eqn for a cubic Bezier is, from PLRM: - r(t) = at^3 + bt^2 + ct + r0 - with the control points: - r1 = r0 + c/3 - r2 = r1 + (c + b)/3 - r3 = r0 + c + b + a - - A quadratic Beizer has the form: - p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2 - - So equating powers of t leads to: - r1 = 2/3 p1 + 1/3 p0 - r2 = 2/3 p1 + 1/3 p2 - and of course r0 = p0, r3 = p2 - */ - - int contour, point = 0, first_pt; - FT_Outline *outline = &ft_face->glyph->outline; - TTPOLYGONHEADER *pph; - TTPOLYCURVE *ppc; - DWORD pph_start, cpfx, type; - FT_Vector cubic_control[4]; - if(cjBuf == 0) pvBuf = NULL; - - if (needsTransform && pvBuf) - { - IntLockFreeType; - FT_Outline_Transform(outline, &transMat); - IntUnLockFreeType; - } - - for(contour = 0; contour < outline->n_contours; contour++) - { - pph_start = needed; - pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed); - first_pt = point; - if(pvBuf) - { - pph->dwType = TT_POLYGON_TYPE; - FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart); - } - needed += sizeof(*pph); - point++; - while(point <= outline->contours[contour]) - { - ppc = (TTPOLYCURVE *)((char *)pvBuf + needed); - type = (outline->tags[point] & FT_Curve_Tag_On) ? - TT_PRIM_LINE : TT_PRIM_CSPLINE; - cpfx = 0; - do - { - if(type == TT_PRIM_LINE) - { - if(pvBuf) - FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); - cpfx++; - point++; - } - else - { - /* Unlike QSPLINEs, CSPLINEs always have their endpoint - so cpfx = 3n */ - - /* FIXME: Possible optimization in endpoint calculation - if there are two consecutive curves */ - cubic_control[0] = outline->points[point-1]; - if(!(outline->tags[point-1] & FT_Curve_Tag_On)) - { - cubic_control[0].x += outline->points[point].x + 1; - cubic_control[0].y += outline->points[point].y + 1; - cubic_control[0].x >>= 1; - cubic_control[0].y >>= 1; - } - if(point+1 > outline->contours[contour]) - cubic_control[3] = outline->points[first_pt]; - else - { - cubic_control[3] = outline->points[point+1]; - if(!(outline->tags[point+1] & FT_Curve_Tag_On)) - { - cubic_control[3].x += outline->points[point].x + 1; - cubic_control[3].y += outline->points[point].y + 1; - cubic_control[3].x >>= 1; - cubic_control[3].y >>= 1; - } - } - /* r1 = 1/3 p0 + 2/3 p1 - r2 = 1/3 p2 + 2/3 p1 */ - cubic_control[1].x = (2 * outline->points[point].x + 1) / 3; - cubic_control[1].y = (2 * outline->points[point].y + 1) / 3; - cubic_control[2] = cubic_control[1]; - cubic_control[1].x += (cubic_control[0].x + 1) / 3; - cubic_control[1].y += (cubic_control[0].y + 1) / 3; - cubic_control[2].x += (cubic_control[3].x + 1) / 3; - cubic_control[2].y += (cubic_control[3].y + 1) / 3; - if(pvBuf) - { - FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]); - FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]); - FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]); - } - cpfx += 3; - point++; - } - } - while(point <= outline->contours[contour] && - (outline->tags[point] & FT_Curve_Tag_On) == - (outline->tags[point-1] & FT_Curve_Tag_On)); - /* At the end of a contour Windows adds the start point, - but only for Beziers and we've already done that. - */ - if(point <= outline->contours[contour] && - outline->tags[point] & FT_Curve_Tag_On) - { - /* This is the closing pt of a bezier, but we've already - added it, so just inc point and carry on */ - point++; - } - if(pvBuf) - { - ppc->wType = type; - ppc->cpfx = cpfx; - } - needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX); - } - if(pvBuf) pph->cb = needed - pph_start; - } - break; - } - - default: - DPRINT1("Unsupported format %d\n", iFormat); - if(pvBuf) ExFreePool(pvBuf); - return GDI_ERROR; - } - - if (pvBuf) - { - Status = MmCopyToCaller(UnsafeBuf, pvBuf, cjBuf); - if (! NT_SUCCESS(Status)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - ExFreePool(pvBuf); - return GDI_ERROR; - } - DPRINT("NtGdiGetGlyphOutline K -> U worked!\n"); - ExFreePool(pvBuf); - } - - DPRINT("NtGdiGetGlyphOutline END and needed %d\n", needed); - return needed; -} - -DWORD -STDCALL -NtGdiGetKerningPairs(HDC hDC, - ULONG NumPairs, - LPKERNINGPAIR krnpair) -{ - UNIMPLEMENTED; - return 0; -} - -/* - From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page - 472, this is NtGdiGetOutlineTextMetricsInternalW. - */ -ULONG -STDCALL -NtGdiGetOutlineTextMetricsInternalW (HDC hDC, - ULONG Data, - OUTLINETEXTMETRICW *otm, - TMDIFF *Tmd) -{ - PDC dc; - PDC_ATTR Dc_Attr; - PTEXTOBJ TextObj; - PFONTGDI FontGDI; - HFONT hFont = 0; - ULONG Size; - OUTLINETEXTMETRICW *potm; - NTSTATUS Status; - - dc = DC_LockDc(hDC); - if (dc == NULL) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return 0; - } - Dc_Attr = dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; - hFont = Dc_Attr->hlfntNew; - TextObj = TEXTOBJ_LockText(hFont); - DC_UnlockDc(dc); - if (TextObj == NULL) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return 0; - } - FontGDI = ObjToGDI(TextObj->Font, FONT); - TEXTOBJ_UnlockText(TextObj); - Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); - if (!otm) return Size; - if (Size > Data) - { - SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER); - return 0; - } - potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); - if (NULL == potm) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - IntGetOutlineTextMetrics(FontGDI, Size, potm); - if (otm) - { - Status = MmCopyToCaller(otm, potm, Size); - if (! NT_SUCCESS(Status)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - ExFreePool(potm); - return 0; - } - } - ExFreePool(potm); - return Size; -} - - -BOOL -APIENTRY -NtGdiGetRasterizerCaps( - OUT LPRASTERIZER_STATUS praststat, - IN ULONG cjBytes) -{ - UNIMPLEMENTED; - return FALSE; -} - - -DWORD FASTCALL -IntGdiGetCharSet(HDC hDC) -{ - UINT cp = 0; - CHARSETINFO csi; - DWORD charset = NtGdiGetTextCharsetInfo(hDC,NULL,0); - if (IntTranslateCharsetInfo(&charset, &csi, TCI_SRCCHARSET)) - cp = csi.ciACP; - else - { - switch(charset) - { - case OEM_CHARSET: - cp = 1; - break; - case DEFAULT_CHARSET: - cp = 0; - break; - default: - DPRINT1("Can't find codepage for charset %d\n", charset); - break; - } - } - DPRINT("charset %d => cp %d\n", charset, LOWORD(cp)); - return (MAKELONG(cp, charset)); -} +ftGdiGetRasterizerCaps(LPRASTERIZER_STATUS lprs); - -DWORD -APIENTRY -NtGdiGetCharSet(HDC hDC) -{ - PDC Dc; - PDC_ATTR Dc_Attr; - DWORD cscp = IntGdiGetCharSet(hDC); - // If here, update everything! - Dc = DC_LockDc(hDC); - if (!Dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return 0; - } - Dc_Attr = Dc->pDc_Attr; - if (!Dc_Attr) Dc_Attr = &Dc->Dc_Attr; - Dc_Attr->iCS_CP = cscp; - Dc_Attr->ulDirty_ &= ~DIRTY_CHARSET; - DC_UnlockDc( Dc ); - return cscp; -} - - -INT -APIENTRY -NtGdiGetTextCharsetInfo( - IN HDC hdc, - OUT OPTIONAL LPFONTSIGNATURE lpSig, - IN DWORD dwFlags) -{ - PDC Dc; - PDC_ATTR Dc_Attr; - UINT Ret = DEFAULT_CHARSET, i = 0, fs_fsCsb0 = 0; - HFONT hFont; - PTEXTOBJ TextObj; - PFONTGDI FontGdi; - FONTSIGNATURE fs; - TT_OS2 *pOS2; - FT_Face Face; - NTSTATUS Status; - - Dc = DC_LockDc(hdc); - if (!Dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return Ret; - } - Dc_Attr = Dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr; - hFont = Dc_Attr->hlfntNew; - TextObj = TEXTOBJ_LockText(hFont); - DC_UnlockDc( Dc ); - if ( TextObj == NULL) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return Ret; - } - FontGdi = ObjToGDI(TextObj->Font, FONT); - Face = FontGdi->face; - TEXTOBJ_UnlockText(TextObj); - IntLockFreeType; - pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2); - IntUnLockFreeType; - memset(&fs, 0, sizeof(FONTSIGNATURE)); - if (NULL != pOS2) - { - fs.fsCsb[0] = pOS2->ulCodePageRange1; - fs.fsCsb[1] = pOS2->ulCodePageRange2; - fs.fsUsb[0] = pOS2->ulUnicodeRange1; - fs.fsUsb[1] = pOS2->ulUnicodeRange2; - fs.fsUsb[2] = pOS2->ulUnicodeRange3; - fs.fsUsb[3] = pOS2->ulUnicodeRange4; - fs_fsCsb0 = pOS2->ulCodePageRange1; - if (pOS2->version == 0) - { - FT_UInt dummy; - - if(FT_Get_First_Char( Face, &dummy ) < 0x100) - fs_fsCsb0 |= 1; - else - fs_fsCsb0 |= 1L << 31; - } - } - DPRINT("Csb 1=%x 0=%x\n", fs.fsCsb[1],fs.fsCsb[0]); - if (lpSig) - { - Status = MmCopyToCaller(lpSig, &fs, sizeof(FONTSIGNATURE)); - if (! NT_SUCCESS(Status)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return Ret; - } - } - if (0 == fs_fsCsb0) - { /* let's see if we can find any interesting cmaps */ - for (i = 0; i < Face->num_charmaps; i++) - { - switch (Face->charmaps[i]->encoding) - { - case ft_encoding_unicode: - case ft_encoding_apple_roman: - fs_fsCsb0 |= 1; - break; - case ft_encoding_symbol: - fs_fsCsb0 |= 1L << 31; - break; - default: - break; - } - } - } - while (0 == (fs_fsCsb0 >> i & 0x0001) && i < MAXTCIINDEX) - { - i++; - } - Ret = FontTci[i].ciCharset; - DPRINT("CharSet %d\n",Ret); - return Ret; -} - -static BOOL +BOOL FASTCALL TextIntGetTextExtentPoint(PDC dc, PTEXTOBJ TextObj, @@ -3476,128 +26,46 @@ TextIntGetTextExtentPoint(PDC dc, int MaxExtent, LPINT Fit, LPINT Dx, - LPSIZE Size) + LPSIZE Size); + + +/** Functions ******************************************************************/ + +BOOL +APIENTRY +NtGdiGetRasterizerCaps( + OUT LPRASTERIZER_STATUS praststat, + IN ULONG cjBytes) { - PFONTGDI FontGDI; - FT_Face face; - FT_GlyphSlot glyph; - FT_Glyph realglyph; - INT error, n, glyph_index, i, previous; - ULONGLONG TotalWidth = 0; - FT_CharMap charmap, found = NULL; - BOOL use_kerning; - FT_Render_Mode RenderMode; - BOOLEAN Render; + NTSTATUS Status = STATUS_SUCCESS; + RASTERIZER_STATUS rsSafe; - FontGDI = ObjToGDI(TextObj->Font, FONT); - - face = FontGDI->face; - if (NULL != Fit) - { - *Fit = 0; - } - - IntLockFreeType; - if (face->charmap == NULL) - { - DPRINT("WARNING: No charmap selected!\n"); - DPRINT("This font face has %d charmaps\n", face->num_charmaps); - - for (n = 0; n < face->num_charmaps; n++) - { - charmap = face->charmaps[n]; - DPRINT("found charmap encoding: %u\n", charmap->encoding); - if (charmap->encoding != 0) - { - found = charmap; - break; - } - } - - if (! found) - { - DPRINT1("WARNING: Could not find desired charmap!\n"); - } - - error = FT_Set_Charmap(face, found); - if (error) - { - DPRINT1("WARNING: Could not set the charmap!\n"); - } - } - - Render = IntIsFontRenderingEnabled(); - if (Render) - RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont); - else - RenderMode = FT_RENDER_MODE_MONO; - - error = FT_Set_Pixel_Sizes(face, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, - /* FIXME should set character height if neg */ - (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); - if (error) - { - DPRINT1("Error in setting pixel sizes: %u\n", error); - } - - use_kerning = FT_HAS_KERNING(face); - previous = 0; - - for (i = 0; i < Count; i++) - { - glyph_index = FT_Get_Char_Index(face, *String); - if (!(realglyph = NtGdiGlyphCacheGet(face, glyph_index, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight))) + if (praststat && cjBytes) + { + if ( cjBytes >= sizeof(RASTERIZER_STATUS) ) cjBytes = sizeof(RASTERIZER_STATUS); + if ( ftGdiGetRasterizerCaps(&rsSafe)) + { + _SEH_TRY { - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - if (error) - { - DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index); - break; - } - - glyph = face->glyph; - realglyph = NtGdiGlyphCacheSet(face, glyph_index, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode); - if (!realglyph) - { - DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index); - break; - } + ProbeForWrite( praststat, + sizeof(RASTERIZER_STATUS), + 1); + RtlCopyMemory(praststat, &rsSafe, cjBytes ); } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; - /* retrieve kerning distance */ - if (use_kerning && previous && glyph_index) - { - FT_Vector delta; - FT_Get_Kerning(face, previous, glyph_index, 0, &delta); - TotalWidth += delta.x; - } - - TotalWidth += realglyph->advance.x >> 10; - - if (((TotalWidth + 32) >> 6) <= MaxExtent && NULL != Fit) - { - *Fit = i + 1; - } - if (NULL != Dx) - { - Dx[i] = (TotalWidth + 32) >> 6; - } - - previous = glyph_index; - String++; - } - IntUnLockFreeType; - - Size->cx = (TotalWidth + 32) >> 6; - Size->cy = (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight); - Size->cy = EngMulDiv(Size->cy, IntGdiGetDeviceCaps(dc, LOGPIXELSY), 72); - - return TRUE; + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + } + } + return FALSE; } W32KAPI @@ -3760,6 +228,33 @@ NtGdiGetTextExtent(HDC hdc, return NtGdiGetTextExtentExW(hdc, lpwsz, cwc, 0, NULL, NULL, psize, 0); } +BOOL +STDCALL +NtGdiSetTextJustification(HDC hDC, + int BreakExtra, + int BreakCount) +{ + PDC pDc; + PDC_ATTR pDc_Attr; + + pDc = DC_LockDc(hDC); + if (!pDc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + pDc_Attr = pDc->pDc_Attr; + if(!pDc_Attr) pDc_Attr = &pDc->Dc_Attr; + + pDc_Attr->lBreakExtra = BreakExtra; + pDc_Attr->cBreak = BreakCount; + + DC_UnlockDc(pDc); + return TRUE; +} + + W32KAPI INT APIENTRY @@ -3803,686 +298,4 @@ NtGdiGetTextFaceW( return Count; } -W32KAPI -BOOL -APIENTRY -NtGdiGetTextMetricsW( - IN HDC hDC, - OUT TMW_INTERNAL * pUnsafeTmwi, - IN ULONG cj -) -{ - PDC dc; - PDC_ATTR Dc_Attr; - PTEXTOBJ TextObj; - PFONTGDI FontGDI; - NTSTATUS Status = STATUS_SUCCESS; - TMW_INTERNAL tmwi; - FT_Face Face; - TT_OS2 *pOS2; - TT_HoriHeader *pHori; - ULONG Error; - - if (NULL == pUnsafeTmwi) - { - SetLastWin32Error(STATUS_INVALID_PARAMETER); - return FALSE; - } - - /* FIXME: check cj ? */ - - if(!(dc = DC_LockDc(hDC))) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - Dc_Attr = dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; - TextObj = TEXTOBJ_LockText(Dc_Attr->hlfntNew); - if (NULL != TextObj) - { - FontGDI = ObjToGDI(TextObj->Font, FONT); - - Face = FontGDI->face; - IntLockFreeType; - Error = FT_Set_Pixel_Sizes(Face, - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth, - /* FIXME should set character height if neg */ - (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)); - IntUnLockFreeType; - if (0 != Error) - { - DPRINT1("Error in setting pixel sizes: %u\n", Error); - Status = STATUS_UNSUCCESSFUL; - } - else - { - memcpy(&tmwi.TextMetric, &FontGDI->TextMetric, sizeof(TEXTMETRICW)); - /* FIXME: Fill Diff member */ - RtlZeroMemory(&tmwi.Diff, sizeof(tmwi.Diff)); - - Status = STATUS_SUCCESS; - IntLockFreeType; - pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2); - if (NULL == pOS2) - { - DPRINT1("Can't find OS/2 table - not TT font?\n"); - Status = STATUS_INTERNAL_ERROR; - } - - pHori = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_hhea); - if (NULL == pHori) - { - DPRINT1("Can't find HHEA table - not TT font?\n"); - Status = STATUS_INTERNAL_ERROR; - } - - IntUnLockFreeType; - - if (NT_SUCCESS(Status)) - { - FillTM(&tmwi.TextMetric, FontGDI->face, pOS2, pHori); - - if (cj > sizeof(TMW_INTERNAL)) - cj = sizeof(TMW_INTERNAL); - - Status = STATUS_SUCCESS; - _SEH_TRY - { - ProbeForWrite(pUnsafeTmwi, cj, 1); - RtlCopyMemory(pUnsafeTmwi,&tmwi,cj); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END - } - } - TEXTOBJ_UnlockText(TextObj); - } - else - { - Status = STATUS_INVALID_HANDLE; - } - DC_UnlockDc(dc); - - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return FALSE; - } - - return TRUE; -} - -BOOL -STDCALL -NtGdiSetTextJustification(HDC hDC, - int BreakExtra, - int BreakCount) -{ - UNIMPLEMENTED; - return FALSE; -} - -DWORD STDCALL -NtGdiGetFontData( - HDC hDC, - DWORD Table, - DWORD Offset, - LPVOID Buffer, - DWORD Size) -{ - PDC Dc; - PDC_ATTR Dc_Attr; - HFONT hFont; - PTEXTOBJ TextObj; - PFONTGDI FontGdi; - DWORD Result = GDI_ERROR; - - Dc = DC_LockDc(hDC); - if (Dc == NULL) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return GDI_ERROR; - } - Dc_Attr = Dc->pDc_Attr; - if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr; - hFont = Dc_Attr->hlfntNew; - TextObj = TEXTOBJ_LockText(hFont); - DC_UnlockDc(Dc); - - if (TextObj == NULL) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return GDI_ERROR; - } - - FontGdi = ObjToGDI(TextObj->Font, FONT); - - IntLockFreeType; - - if (FT_IS_SFNT(FontGdi->face)) - { - if (Table) - Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) | - (Table << 8 & 0xFF0000); - - if (Buffer == NULL) - Size = 0; - - if (!FT_Load_Sfnt_Table(FontGdi->face, Table, Offset, Buffer, &Size)) - Result = Size; - } - - IntUnLockFreeType; - - TEXTOBJ_UnlockText(TextObj); - - return Result; -} - -static UINT FASTCALL -GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI) -{ - ANSI_STRING EntryFaceNameA; - UNICODE_STRING EntryFaceNameW; - unsigned Size; - OUTLINETEXTMETRICW *Otm; - LONG WeightDiff; - NTSTATUS Status; - UINT Score = 1; - - RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); - Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); - if (NT_SUCCESS(Status)) - { - if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length) - { - EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR); - EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0'; - } - if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE)) - { - Score += 49; - } - RtlFreeUnicodeString(&EntryFaceNameW); - } - - Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); - Otm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT); - if (NULL == Otm) - { - return Score; - } - IntGetOutlineTextMetrics(FontGDI, Size, Otm); - - if ((0 != LogFont->lfItalic && 0 != Otm->otmTextMetrics.tmItalic) || - (0 == LogFont->lfItalic && 0 == Otm->otmTextMetrics.tmItalic)) - { - Score += 25; - } - if (LogFont->lfWeight != FW_DONTCARE) - { - if (LogFont->lfWeight < Otm->otmTextMetrics.tmWeight) - { - WeightDiff = Otm->otmTextMetrics.tmWeight - LogFont->lfWeight; - } - else - { - WeightDiff = LogFont->lfWeight - Otm->otmTextMetrics.tmWeight; - } - Score += (1000 - WeightDiff) / (1000 / 25); - } - else - { - Score += 25; - } - - ExFreePool(Otm); - - return Score; -} - -static __inline VOID -FindBestFontFromList(FONTOBJ **FontObj, UINT *MatchScore, LOGFONTW *LogFont, - PUNICODE_STRING FaceName, PLIST_ENTRY Head) -{ - PLIST_ENTRY Entry; - PFONT_ENTRY CurrentEntry; - FONTGDI *FontGDI; - UINT Score; - - Entry = Head->Flink; - while (Entry != Head) - { - CurrentEntry = (PFONT_ENTRY) CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry); - - FontGDI = CurrentEntry->Font; - ASSERT(FontGDI); - - Score = GetFontScore(LogFont, FaceName, FontGDI); - if (*MatchScore == 0 || *MatchScore < Score) - { - *FontObj = GDIToObj(FontGDI, FONT); - *MatchScore = Score; - } - Entry = Entry->Flink; - } -} - -static __inline BOOLEAN -SubstituteFontFamilyKey(PUNICODE_STRING FaceName, - LPCWSTR Key) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}}; - NTSTATUS Status; - UNICODE_STRING Value; - - RtlInitUnicodeString(&Value, NULL); - - QueryTable[0].QueryRoutine = NULL; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND | - RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[0].Name = FaceName->Buffer; - QueryTable[0].EntryContext = &Value; - QueryTable[0].DefaultType = REG_NONE; - QueryTable[0].DefaultData = NULL; - QueryTable[0].DefaultLength = 0; - - QueryTable[1].QueryRoutine = NULL; - QueryTable[1].Name = NULL; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT, - Key, - QueryTable, - NULL, - NULL); - if (NT_SUCCESS(Status)) - { - RtlFreeUnicodeString(FaceName); - *FaceName = Value; - } - - return NT_SUCCESS(Status); -} - -static __inline void -SubstituteFontFamily(PUNICODE_STRING FaceName, UINT Level) -{ - if (10 < Level) /* Enough is enough */ - { - return; - } - - if (SubstituteFontFamilyKey(FaceName, L"SysFontSubstitutes") || - SubstituteFontFamilyKey(FaceName, L"FontSubstitutes")) - { - SubstituteFontFamily(FaceName, Level + 1); - } -} - -NTSTATUS FASTCALL -TextIntRealizeFont(HFONT FontHandle) -{ - NTSTATUS Status = STATUS_SUCCESS; - PTEXTOBJ TextObj; - UNICODE_STRING FaceName; - PW32PROCESS Win32Process; - UINT MatchScore; - - TextObj = TEXTOBJ_LockText(FontHandle); - if (NULL == TextObj) - { - return STATUS_INVALID_HANDLE; - } - - if (TextObj->Initialized) - { - TEXTOBJ_UnlockText(TextObj); - return STATUS_SUCCESS; - } - - if (! RtlCreateUnicodeString(&FaceName, TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName)) - { - TEXTOBJ_UnlockText(TextObj); - return STATUS_NO_MEMORY; - } - SubstituteFontFamily(&FaceName, 0); - MatchScore = 0; - TextObj->Font = NULL; - - /* First search private fonts */ - Win32Process = PsGetCurrentProcessWin32Process(); - IntLockProcessPrivateFonts(Win32Process); - FindBestFontFromList(&TextObj->Font, &MatchScore, - &TextObj->logfont.elfEnumLogfontEx.elfLogFont, &FaceName, - &Win32Process->PrivateFontListHead); - IntUnLockProcessPrivateFonts(Win32Process); - - /* Search system fonts */ - IntLockGlobalFonts; - FindBestFontFromList(&TextObj->Font, &MatchScore, - &TextObj->logfont.elfEnumLogfontEx.elfLogFont, &FaceName, - &FontListHead); - IntUnLockGlobalFonts; - - if (NULL == TextObj->Font) - { - DPRINT1("Requested font %S not found, no fonts loaded at all\n", - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName); - Status = STATUS_NOT_FOUND; - } - else - { - TextObj->Initialized = TRUE; - Status = STATUS_SUCCESS; - } - - RtlFreeUnicodeString(&FaceName); - TEXTOBJ_UnlockText(TextObj); - - ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0); - - return Status; -} - -INT FASTCALL -FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer) -{ - if( Buffer == NULL ) return sizeof(LOGFONTW); - - switch (Count) - { - - case sizeof(ENUMLOGFONTEXDVW): - RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer, - &TFont->logfont, - sizeof(ENUMLOGFONTEXDVW)); - break; - case sizeof(ENUMLOGFONTEXW): - RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer, - &TFont->logfont.elfEnumLogfontEx, - sizeof(ENUMLOGFONTEXW)); - break; - - case sizeof(EXTLOGFONTW): - case sizeof(ENUMLOGFONTW): - RtlCopyMemory((LPENUMLOGFONTW) Buffer, - &TFont->logfont.elfEnumLogfontEx.elfLogFont, - sizeof(ENUMLOGFONTW)); - break; - - case sizeof(LOGFONTW): - RtlCopyMemory((LPLOGFONTW) Buffer, - &TFont->logfont.elfEnumLogfontEx.elfLogFont, - sizeof(LOGFONTW)); - break; - - default: - SetLastWin32Error(ERROR_BUFFER_OVERFLOW); - return 0; - } - return Count; -} - - -static BOOL FASTCALL -IntGetFullFileName( - POBJECT_NAME_INFORMATION NameInfo, - ULONG Size, - PUNICODE_STRING FileName) -{ - NTSTATUS Status; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE hFile; - IO_STATUS_BLOCK IoStatusBlock; - ULONG Desired; - - InitializeObjectAttributes(&ObjectAttributes, - FileName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwOpenFile( - &hFile, - 0, //FILE_READ_ATTRIBUTES, - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - 0); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenFile() failed (Status = 0x%lx)\n", Status); - return FALSE; - } - - Status = ZwQueryObject(hFile, ObjectNameInformation, NameInfo, Size, &Desired); - ZwClose(hFile); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwQueryObject() failed (Status = %lx)\n", Status); - return FALSE; - } - - return TRUE; -} - -static BOOL FASTCALL -IntGdiGetFontResourceInfo( - IN PUNICODE_STRING FileName, - OUT void *pBuffer, - OUT DWORD *pdwBytes, - IN DWORD dwType) -{ - UNICODE_STRING EntryFileName; - POBJECT_NAME_INFORMATION NameInfo1, NameInfo2; - PLIST_ENTRY ListEntry; - PFONT_ENTRY FontEntry; - FONTFAMILYINFO Info; - ULONG Size; - BOOL bFound = FALSE; - - /* Create buffer for full path name */ - Size = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR); - NameInfo1 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF); - if (!NameInfo1) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Get the full path name */ - if (!IntGetFullFileName(NameInfo1, Size, FileName)) - { - ExFreePool(NameInfo1); - return FALSE; - } - - /* Create a buffer for the entries' names */ - NameInfo2 = ExAllocatePoolWithTag(PagedPool, Size, TAG_FINF); - if (!NameInfo2) - { - ExFreePool(NameInfo1); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Try to find the pathname in the global font list */ - IntLockGlobalFonts; - for (ListEntry = FontListHead.Flink; - ListEntry != &FontListHead; - ListEntry = ListEntry->Flink) - { - FontEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY, ListEntry); - if (FontEntry->Font->Filename != NULL) - { - RtlInitUnicodeString(&EntryFileName , FontEntry->Font->Filename); - if (IntGetFullFileName(NameInfo2, Size, &EntryFileName)) - { - if (RtlEqualUnicodeString(&NameInfo1->Name, &NameInfo2->Name, FALSE)) - { - /* found */ - FontFamilyFillInfo(&Info, FontEntry->FaceName.Buffer, FontEntry->Font); - bFound = TRUE; - break; - } - } - } - } - IntUnLockGlobalFonts; - - /* Free the buffers */ - ExFreePool(NameInfo1); - ExFreePool(NameInfo2); - - if (!bFound && dwType != 5) - { - /* Font could not be found in system table - dwType == 5 will still handle this */ - return FALSE; - } - - switch(dwType) - { - case 0: /* FIXME: returns 1 or 2, don't know what this is atm */ - *(DWORD*)pBuffer = 1; - *pdwBytes = sizeof(DWORD); - break; - - case 1: /* Copy the full font name */ - Size = wcslen(Info.EnumLogFontEx.elfFullName) + 1; - Size = min(Size , LF_FULLFACESIZE) * sizeof(WCHAR); - memcpy(pBuffer, Info.EnumLogFontEx.elfFullName, Size); - // FIXME: Do we have to zeroterminate? - *pdwBytes = Size; - break; - - case 2: /* Copy a LOGFONTW structure */ - Info.EnumLogFontEx.elfLogFont.lfWidth = 0; - memcpy(pBuffer, &Info.EnumLogFontEx.elfLogFont, sizeof(LOGFONTW)); - *pdwBytes = sizeof(LOGFONTW); - break; - - case 3: /* FIXME: What exactly is copied here? */ - *(DWORD*)pBuffer = 1; - *pdwBytes = sizeof(DWORD*); - break; - - case 5: /* Looks like a BOOL that is copied, TRUE, if the font was not found */ - *(BOOL*)pBuffer = !bFound; - *pdwBytes = sizeof(BOOL); - break; - - default: - return FALSE; - } - - return TRUE; -} - -W32KAPI BOOL APIENTRY -NtGdiGetFontResourceInfoInternalW( - IN LPWSTR pwszFiles, - IN ULONG cwc, - IN ULONG cFiles, - IN UINT cjIn, - OUT LPDWORD pdwBytes, - OUT LPVOID pvBuf, - IN DWORD dwType) -{ - NTSTATUS Status = STATUS_SUCCESS; - DWORD dwBytes; - UNICODE_STRING SafeFileNames; - BOOL bRet = FALSE; - ULONG cbStringSize; - - union - { - LOGFONTW logfontw; - WCHAR FullName[LF_FULLFACESIZE]; - } Buffer; - - /* FIXME: handle cFiles > 0 */ - - /* Check for valid dwType values - dwType == 4 seems to be handled by gdi32 only */ - if (dwType == 4 || dwType > 5) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* Allocate a safe unicode string buffer */ - cbStringSize = cwc * sizeof(WCHAR); - SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR); - SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool, - cbStringSize, - TAG('R','T','S','U')); - if (!SafeFileNames.Buffer) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Check buffers and copy pwszFiles to safe unicode string */ - _SEH_TRY - { - ProbeForRead(pwszFiles, cbStringSize, 1); - ProbeForWrite(pdwBytes, sizeof(DWORD), 1); - ProbeForWrite(pvBuf, cjIn, 1); - - RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END - - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - /* Free the string buffer for the safe filename */ - ExFreePool(SafeFileNames.Buffer); - return FALSE; - } - - /* Do the actual call */ - bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType); - - /* Check if succeeded and the buffer is big enough */ - if (bRet && cjIn >= dwBytes) - { - /* Copy the data back to caller */ - _SEH_TRY - { - /* Buffers are already probed */ - RtlCopyMemory(pvBuf, &Buffer, dwBytes); - *pdwBytes = dwBytes; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END - - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - bRet = FALSE; - } - } - - /* Free the string for the safe filenames */ - ExFreePool(SafeFileNames.Buffer); - - return bRet; -} - /* EOF */ diff --git a/reactos/subsystems/win32/win32k/win32k.spec b/reactos/subsystems/win32/win32k/win32k.pspec similarity index 100% rename from reactos/subsystems/win32/win32k/win32k.spec rename to reactos/subsystems/win32/win32k/win32k.pspec diff --git a/reactos/subsystems/win32/win32k/win32k.rbuild b/reactos/subsystems/win32/win32k/win32k.rbuild index 97f210a1160..5dd14c6504e 100644 --- a/reactos/subsystems/win32/win32k/win32k.rbuild +++ b/reactos/subsystems/win32/win32k/win32k.rbuild @@ -161,6 +161,8 @@ dibobj.c drawing.c fillshap.c + font.c + freetype.c gdibatch.c gdiobj.c icm.c @@ -183,7 +185,7 @@ - + win32k_base pseh ntoskrnl diff --git a/reactos/tools/rbuild/backend/codeblocks/codeblocks.cpp b/reactos/tools/rbuild/backend/codeblocks/codeblocks.cpp index 2a79d3a9ce0..73502e8fdb5 100644 --- a/reactos/tools/rbuild/backend/codeblocks/codeblocks.cpp +++ b/reactos/tools/rbuild/backend/codeblocks/codeblocks.cpp @@ -685,7 +685,7 @@ CBBackend::_generate_cbproj ( const Module& module ) #if 0 if ( dll ) { - if (IsWineModule( module )) + if (IsSpecDefinitionFile( module )) fprintf ( OUT, "\t\t\t\t\t\r\n", outdir.c_str(), module.importLibrary->definition.c_str(), module.name.c_str()); fprintf ( OUT, "\t\t\t\t\t\r\n", module.GetTargetName ().c_str(), module.importLibrary->definition.c_str(), module.name.c_str(), module.mangledSymbols ? "" : "--kill-at" ); fprintf ( OUT, "\t\t\t\t\t\r\n", outdir.c_str() ); @@ -902,11 +902,11 @@ CBBackend::_lookup_property ( const Module& module, const std::string& name ) co } bool -CBBackend::IsWineModule ( const Module& module ) const +CBBackend::IsSpecDefinitionFile ( const Module& module ) const { if ( module.importLibrary == NULL) return false; - size_t index = module.importLibrary->source->name.rfind ( ".spec.def" ); + size_t index = module.importLibrary->source->name.rfind ( ".spec" ); return ( index != string::npos ); } diff --git a/reactos/tools/rbuild/backend/codeblocks/codeblocks.h b/reactos/tools/rbuild/backend/codeblocks/codeblocks.h index 22d03122062..6ab399ef638 100644 --- a/reactos/tools/rbuild/backend/codeblocks/codeblocks.h +++ b/reactos/tools/rbuild/backend/codeblocks/codeblocks.h @@ -74,7 +74,7 @@ class CBBackend : public Backend std::string DependFileName ( const Module& module ) const; std::string GenerateProjectLinkerFlags () const; void MingwAddImplicitLibraries( Module &module ); - bool IsWineModule ( const Module& module ) const; + bool IsSpecDefinitionFile ( const Module& module ) const; std::vector m_configurations; std::vector m_fileUnits; diff --git a/reactos/tools/rbuild/backend/mingw/modulehandler.cpp b/reactos/tools/rbuild/backend/mingw/modulehandler.cpp index 0e68730afd3..dce48779b8d 100644 --- a/reactos/tools/rbuild/backend/mingw/modulehandler.cpp +++ b/reactos/tools/rbuild/backend/mingw/modulehandler.cpp @@ -416,13 +416,13 @@ MingwModuleHandler::GetObjectFilename ( if ( module.type == BootSector ) return new FileLocation ( *module.output ); - else if ( extension == ".rc" || extension == ".RC" ) + else if (extension == ".rc") newExtension = "_" + module.name + ".coff"; - else if ( extension == ".mc" || extension == ".MC" ) + else if (extension == ".mc") newExtension = ".rc"; - else if ( extension == ".spec" || extension == ".SPEC" ) + else if (extension == ".spec" || extension == ".pspec") newExtension = "_" + module.name + ".stubs.o"; - else if ( extension == ".idl" || extension == ".IDL" ) + else if (extension == ".idl") { if ( module.type == RpcServer ) newExtension = "_s.o"; @@ -1056,28 +1056,28 @@ Rule wmcRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).rc "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).rc", "$(INTERMEDIATE)$(SEP)include$(SEP)reactos$(SEP)$(source_name_noext).h", "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL ); -Rule winebuildKMDefRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).spec.def: $(source)$(dependencies) $(WINEBUILD_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n" - "\t$(ECHO_WINEBLD)\n" - "\t${gcc} -xc -E $(source) -I. > $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec\n" - "\t$(Q)$(WINEBUILD_TARGET) $(WINEBUILD_FLAGS) -o $(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext)_$(module_name).spec.def --def -E $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec\n\n", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).spec.def", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL ); -Rule winebuildKMRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.c:\n" - "\t${cp} $(NUL) $@ 1>$(NUL)\n" - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.o: $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.c$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n" - "\t$(ECHO_CC)\n" - "\t${gcc} -o $@ $($(module_name)_CFLAGS)$(compiler_flags) -c $<\n", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.c", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.o", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL ); -Rule winebuildDefRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).spec.def: $(source)$(dependencies) $(WINEBUILD_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n" - "\t$(ECHO_WINEBLD)\n" - "\t$(Q)$(WINEBUILD_TARGET) $(WINEBUILD_FLAGS) -o $(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext)_$(module_name).spec.def --def -E $(source)\n\n", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).spec.def", - "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL ); +Rule winebuildPDefRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).auto.def: $(source)$(dependencies) $(WINEBUILD_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n" + "\t$(ECHO_WINEBLD)\n" + "\t${gcc} -xc -E $(source) -I. > $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec\n" + "\t$(Q)$(WINEBUILD_TARGET) $(WINEBUILD_FLAGS) -o $(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext)_$(module_name).auto.def --def -E $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec\n\n", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).auto.def", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL ); +Rule winebuildPRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.c:\n" + "\t${cp} $(NUL) $@ 1>$(NUL)\n" + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.o: $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.c$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n" + "\t$(ECHO_CC)\n" + "\t${gcc} -o $@ $($(module_name)_CFLAGS)$(compiler_flags) -c $<\n", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.c", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).stubs.o", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL ); +Rule winebuildDefRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).auto.def: $(source)$(dependencies) $(WINEBUILD_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n" + "\t$(ECHO_WINEBLD)\n" + "\t$(Q)$(WINEBUILD_TARGET) $(WINEBUILD_FLAGS) -o $(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext)_$(module_name).auto.def --def -E $(source)\n\n", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).auto.def", + "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL ); Rule winebuildRule ( "$(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext)_$(module_name).stubs.c: $(source_path)$(SEP)$(source_name_noext).spec $(WINEBUILD_TARGET)\n" "\t$(ECHO_WINEBLD)\n" "\t$(Q)$(WINEBUILD_TARGET) $(WINEBUILD_FLAGS) -o $(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext)_$(module_name).stubs.c --pedll $(source_path)$(SEP)$(source_name_noext).spec\n" @@ -1256,8 +1256,7 @@ MingwModuleHandler::GenerateCommands ( { HostDontCare, TypeDontCare, ".asm", &nasmRule }, { HostDontCare, TypeDontCare, ".rc", &windresRule }, { HostDontCare, TypeDontCare, ".mc", &wmcRule }, - { HostFalse, Kernel, ".spec", &winebuildKMRule }, - { HostFalse, KernelModeDLL, ".spec", &winebuildKMRule }, + { HostDontCare, TypeDontCare, ".pspec", &winebuildPRule }, { HostDontCare, TypeDontCare, ".spec", &winebuildRule }, { HostDontCare, RpcServer, ".idl", &widlServerRule }, { HostDontCare, RpcClient, ".idl", &widlClientRule }, @@ -1856,7 +1855,7 @@ MingwModuleHandler::GenerateOtherMacros () used_defs ); } - if ( IsWineModule() ) + if ( IsSpecDefinitionFile() ) { vector s; GetSpecImplibDependencies ( s, module.importLibrary->source ); @@ -1988,6 +1987,8 @@ MingwModuleHandler::GenerateOtherMacros () void MingwModuleHandler::GenerateRules () { + SpecFileType spec; + fprintf ( fMakefile, "# RULES\n" ); string targetMacro = GetTargetMacro ( module ); //CLEAN_FILE ( targetMacro ); @@ -2015,12 +2016,15 @@ MingwModuleHandler::GenerateRules () delete ar_target; } - if ( IsWineModule() ) + + spec = IsSpecDefinitionFile(); + + if(spec) { Rule * defRule; - if ( module.type == Kernel || module.type == KernelModeDLL || module.type == KernelModeDriver ) - defRule = &winebuildKMDefRule; + if (spec == PSpec) + defRule = &winebuildPDefRule; else defRule = &winebuildDefRule; @@ -2172,14 +2176,19 @@ MingwModuleHandler::GeneratePreconditionDependencies () fprintf ( fMakefile, "\n" ); } -bool -MingwModuleHandler::IsWineModule () const +SpecFileType +MingwModuleHandler::IsSpecDefinitionFile () const { - if ( module.importLibrary == NULL) - return false; + if(!module.importLibrary) + return None; - size_t index = module.importLibrary->source->name.rfind ( ".spec" ); - return ( index != string::npos ); + if(module.importLibrary->source->name.rfind(".spec") != string::npos) + return Spec; + + if(module.importLibrary->source->name.rfind(".pspec") != string::npos) + return PSpec; + + return None; } /* caller needs to delete the returned object */ @@ -2189,11 +2198,11 @@ MingwModuleHandler::GetDefinitionFilename () const if ( module.importLibrary == NULL ) return NULL; - if ( IsWineModule () ) + if ( IsSpecDefinitionFile () ) { return new FileLocation ( IntermediateDirectory, module.importLibrary->source->relative_path, - GetBasename ( module.importLibrary->source->name ) + "_" + module.name + ".spec.def" ); + GetBasename ( module.importLibrary->source->name ) + "_" + module.name + ".auto.def" ); } else { @@ -2268,7 +2277,7 @@ MingwModuleHandler::GetSpecImplibDependencies ( { dependencies.push_back ( FileLocation ( IntermediateDirectory, file->relative_path, - GetBasename ( file->name ) + "_" + module.name + ".spec.def" ) ); + GetBasename ( file->name ) + "_" + module.name + ".auto.def" ) ); } void @@ -2316,9 +2325,11 @@ MingwModuleHandler::GetDefinitionDependencies ( const CompilationUnit& compilationUnit = *compilationUnits[i]; const FileLocation& sourceFile = compilationUnit.GetFilename (); string extension = GetExtension ( sourceFile ); - if ( extension == ".spec" || extension == ".SPEC" ) + + if (extension == ".spec" || extension == ".pspec") GetSpecObjectDependencies ( dependencies, &sourceFile ); - if ( extension == ".idl" || extension == ".IDL" ) + + if (extension == ".idl") { if ( ( module.type == RpcServer ) || ( module.type == RpcClient ) || ( module.type == RpcProxy ) ) GetWidlObjectDependencies ( dependencies, &sourceFile ); diff --git a/reactos/tools/rbuild/backend/mingw/modulehandler.h b/reactos/tools/rbuild/backend/mingw/modulehandler.h index 556cf5d3cc3..331335f375b 100644 --- a/reactos/tools/rbuild/backend/mingw/modulehandler.h +++ b/reactos/tools/rbuild/backend/mingw/modulehandler.h @@ -32,6 +32,13 @@ PrefixFilename ( const std::string& filename, const std::string& prefix ); +enum SpecFileType +{ + None, + Spec = 1, + PSpec = 2 +}; + class MingwModuleHandler { public: @@ -150,7 +157,7 @@ private: const FileLocation *file ) const; void GetDefaultDependencies ( string_list& dependencies ) const; void GetInvocationDependencies ( const Module& module, string_list& dependencies ); - bool IsWineModule () const; + SpecFileType IsSpecDefinitionFile () const; const FileLocation* GetDefinitionFilename () const; void GenerateBuildNonSymbolStrippedCode (); void CleanupCompilationUnitVector ( std::vector& compilationUnits ); diff --git a/reactos/tools/rbuild/compilationunit.cpp b/reactos/tools/rbuild/compilationunit.cpp index 0fa05c0daf3..35d0311fea0 100644 --- a/reactos/tools/rbuild/compilationunit.cpp +++ b/reactos/tools/rbuild/compilationunit.cpp @@ -77,7 +77,7 @@ CompilationUnit::IsGeneratedFile () const return false; const File* file = files[0]; string extension = GetExtension ( file->file ); - return ( extension == ".spec" || extension == ".SPEC" || extension == ".mc" || extension == ".MC"); + return ( extension == ".spec" || extension == ".pspec" || extension == ".mc"); } bool