diff --git a/Doxyfile b/Doxyfile index 386ca57fdf4..75a2bcb4f8f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -196,7 +196,7 @@ ALIASES = # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. -OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for @@ -236,7 +236,7 @@ EXTENSION_MAPPING = # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. -BUILTIN_STL_SUPPORT = NO +BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. diff --git a/base/shell/explorer/desktop/desktop.cpp b/base/shell/explorer/desktop/desktop.cpp index ed613576fd3..c00308ff00a 100644 --- a/base/shell/explorer/desktop/desktop.cpp +++ b/base/shell/explorer/desktop/desktop.cpp @@ -479,6 +479,26 @@ LRESULT DesktopWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) SendMessage(g_Globals._hwndShellView, nmsg, wparam, lparam); break; + case PM_TRANSLATE_MSG: + { + /* TranslateAccelerator is called for all explorer windows that are open + so we have to decide if this is the correct recipient */ + LPMSG lpmsg = (LPMSG)lparam; + HWND hwnd = lpmsg->hwnd; + + while(hwnd) + { + if(hwnd == _hwnd) + break; + + hwnd = GetParent(hwnd); + } + + if (hwnd) + return _pShellView->TranslateAccelerator(lpmsg) == S_OK; + return false; + } + default: def: return super::WndProc(nmsg, wparam, lparam); } diff --git a/base/shell/explorer/desktop/desktop.h b/base/shell/explorer/desktop/desktop.h index ab46611eb1a..2fffb4cd9f0 100644 --- a/base/shell/explorer/desktop/desktop.h +++ b/base/shell/explorer/desktop/desktop.h @@ -48,9 +48,9 @@ protected: /// Implementation of the Explorer desktop window -struct DesktopWindow : public Window, public IShellBrowserImpl +struct DesktopWindow : public PreTranslateWindow, public IShellBrowserImpl { - typedef Window super; + typedef PreTranslateWindow super; DesktopWindow(HWND hwnd); ~DesktopWindow(); diff --git a/base/shell/explorer/shell/shellbrowser.cpp b/base/shell/explorer/shell/shellbrowser.cpp index 44ba3750ff0..1c74c86393c 100644 --- a/base/shell/explorer/shell/shellbrowser.cpp +++ b/base/shell/explorer/shell/shellbrowser.cpp @@ -599,6 +599,27 @@ bool ShellBrowser::jump_to_pidl(LPCITEMIDLIST pidl) return false; } +bool ShellBrowser::TranslateAccelerator(LPMSG lpmsg) +{ + HWND hwnd; + + /* TranslateAccelerator is called for all explorer windows that are open + so we have to decide if this is the correct recipient */ + hwnd = lpmsg->hwnd; + + while(hwnd) + { + if(hwnd == _hwnd) + break; + + hwnd = GetParent(hwnd); + } + + if (hwnd) + return _pShellView->TranslateAccelerator(lpmsg) == S_OK; + + return false; +} bool ShellBrowser::select_folder(Entry* entry, bool expand) { @@ -707,6 +728,9 @@ LRESULT MDIShellBrowserChild::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) SendMessage(_right_hwnd, WM_SYSCOLORCHANGE, 0, 0); break; + case PM_TRANSLATE_MSG: + return _shellBrowser->TranslateAccelerator((MSG*)lparam); + default: return super::WndProc(nmsg, wparam, lparam); } diff --git a/base/shell/explorer/shell/shellbrowser.h b/base/shell/explorer/shell/shellbrowser.h index 886d5ce24c9..be910f1beb5 100644 --- a/base/shell/explorer/shell/shellbrowser.h +++ b/base/shell/explorer/shell/shellbrowser.h @@ -141,6 +141,8 @@ struct ShellBrowser : public IShellBrowserImpl void invalidate_cache(); + bool TranslateAccelerator(LPMSG lpmsg); + protected: HWND _hwnd; HWND _hwndFrame; diff --git a/base/shell/explorer/utility/window.cpp b/base/shell/explorer/utility/window.cpp index 4ad750f7a8c..bb0814d07ef 100644 --- a/base/shell/explorer/utility/window.cpp +++ b/base/shell/explorer/utility/window.cpp @@ -591,6 +591,14 @@ void Window::unregister_pretranslate(HWND hwnd) BOOL Window::pretranslate_msg(LPMSG pmsg) { + if ((pmsg->message != WM_KEYDOWN) && + (pmsg->message != WM_SYSKEYDOWN) && + (pmsg->message != WM_SYSCHAR) && + (pmsg->message != WM_CHAR)) + { + return FALSE; + } + for(WindowSet::const_iterator it=Window::s_pretranslate_windows.begin(); it!=s_pretranslate_windows.end(); ++it) if (SendMessage(*it, PM_TRANSLATE_MSG, 0, (LPARAM)pmsg)) return TRUE; diff --git a/base/shell/explorer/utility/window.h b/base/shell/explorer/utility/window.h index 3f556b956db..3bf913adfbc 100644 --- a/base/shell/explorer/utility/window.h +++ b/base/shell/explorer/utility/window.h @@ -282,13 +282,28 @@ struct MenuInfo #define Frame_GetMenuInfo(hwnd) ((MenuInfo*)SNDMSG(hwnd, PM_FRM_GET_MENUINFO, 0, 0)) + /** + PreTranslateWindow is used to register windows to be called by Window::pretranslate_msg(). + This way you get PM_TRANSLATE_MSG messages before the message loop dispatches messages. + You can then for example use TranslateAccelerator() to implement key shortcuts. + */ +struct PreTranslateWindow : public Window +{ + typedef Window super; + + PreTranslateWindow(HWND); + ~PreTranslateWindow(); +}; + + + /** Class ChildWindow represents MDI child windows. It is used with class MainFrame. */ -struct ChildWindow : public Window +struct ChildWindow : public PreTranslateWindow { - typedef Window super; + typedef PreTranslateWindow super; ChildWindow(HWND hwnd, const ChildWndInfo& info); @@ -325,20 +340,6 @@ protected: #define PM_SETSTATUSTEXT (WM_APP+0x1E) - /** - PreTranslateWindow is used to register windows to be called by Window::pretranslate_msg(). - This way you get PM_TRANSLATE_MSG messages before the message loop dispatches messages. - You can then for example use TranslateAccelerator() to implement key shortcuts. - */ -struct PreTranslateWindow : public Window -{ - typedef Window super; - - PreTranslateWindow(HWND); - ~PreTranslateWindow(); -}; - - /** The class DialogWindow implements modeless dialogs, which are managed by Window::dispatch_dialog_msg() in Window::MessageLoop(). diff --git a/boot/bootdata/hivesys_amd64.inf b/boot/bootdata/hivesys_amd64.inf index ad480cb0329..a6585af2958 100644 --- a/boot/bootdata/hivesys_amd64.inf +++ b/boot/bootdata/hivesys_amd64.inf @@ -1130,8 +1130,11 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors",,0x00000012 HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors\Local Port","Driver",2,"localspl.dll" HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers",,0x00000012 -HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductType",2,"WinNT" -HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductSuite",0x00010002,"" +HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductType",2,"ServerNT" +HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductSuite",0x00010002,"Terminal Server" +; ReactOS specific - by default we report ourselves as Server for the user, +; but we can also report as Workstation if some application needs it. +HKLM,"SYSTEM\CurrentControlSet\Control\ReactOS\Settings\Version","ReportAsWorkstation",0x00010001,0x00000000 ; Some installers check for SP1 HKLM,"SYSTEM\CurrentControlSet\Control\Windows","CSDVersion",0x00010001,0x00000100 diff --git a/boot/bootdata/hivesys_i386.inf b/boot/bootdata/hivesys_i386.inf index ad480cb0329..a6585af2958 100644 --- a/boot/bootdata/hivesys_i386.inf +++ b/boot/bootdata/hivesys_i386.inf @@ -1130,8 +1130,11 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors",,0x00000012 HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors\Local Port","Driver",2,"localspl.dll" HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers",,0x00000012 -HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductType",2,"WinNT" -HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductSuite",0x00010002,"" +HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductType",2,"ServerNT" +HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductSuite",0x00010002,"Terminal Server" +; ReactOS specific - by default we report ourselves as Server for the user, +; but we can also report as Workstation if some application needs it. +HKLM,"SYSTEM\CurrentControlSet\Control\ReactOS\Settings\Version","ReportAsWorkstation",0x00010001,0x00000000 ; Some installers check for SP1 HKLM,"SYSTEM\CurrentControlSet\Control\Windows","CSDVersion",0x00010001,0x00000100 diff --git a/dll/ntdll/rtl/version.c b/dll/ntdll/rtl/version.c index ce832c3e4fc..66193febb70 100644 --- a/dll/ntdll/rtl/version.c +++ b/dll/ntdll/rtl/version.c @@ -8,13 +8,64 @@ * Created 01/11/98 */ -/* INCLUDES ****************************************************************/ +/* INCLUDES *******************************************************************/ #include #define NDEBUG #include -/* FUNCTIONS ****************************************************************/ +/* FUNCTIONS ******************************************************************/ + +/* HACK: ReactOS specific changes, see bug-reports CORE-6611 and CORE-4620 (aka. #5003) */ +static VOID NTAPI +SetRosSpecificInfo(IN OUT PRTL_OSVERSIONINFOEXW VersionInformation) +{ + CHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; + PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = (PVOID)Buffer; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG ReportAsWorkstation = 0; + HANDLE hKey; + ULONG Length; + NTSTATUS Status; + UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version"); + UNICODE_STRING ValName = RTL_CONSTANT_STRING(L"ReportAsWorkstation"); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_OPENIF | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Don't change anything if the key doesn't exist */ + Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + /* Get the value from the registry and make sure it's a 32-bit value */ + Status = NtQueryValueKey(hKey, + &ValName, + KeyValuePartialInformation, + kvpInfo, + sizeof(Buffer), + &Length); + if (NT_SUCCESS(Status) && + (kvpInfo->Type == REG_DWORD) && + (kvpInfo->DataLength == sizeof(ULONG))) + { + /* Is the value set? */ + ReportAsWorkstation = *(PULONG)kvpInfo->Data; + if ((VersionInformation->wProductType == VER_NT_SERVER) && + (ReportAsWorkstation != 0)) + { + /* It is, modify the product type to report a workstation */ + VersionInformation->wProductType = VER_NT_WORKSTATION; + DPRINT1("We modified the reported OS from NtProductServer to NtProductWinNt\n"); + } + } + + /* Close the handle */ + NtClose(hKey); + } +} /********************************************************************** * NAME EXPORTED @@ -40,12 +91,11 @@ * * @implemented */ - BOOLEAN NTAPI RtlGetNtProductType(PNT_PRODUCT_TYPE ProductType) { - *ProductType = SharedUserData->NtProductType; - return(TRUE); + *ProductType = SharedUserData->NtProductType; + return TRUE; } /********************************************************************** @@ -71,7 +121,6 @@ RtlGetNtProductType(PNT_PRODUCT_TYPE ProductType) * * @implemented */ - VOID NTAPI RtlGetNtVersionNumbers(OUT LPDWORD pdwMajorVersion, OUT LPDWORD pdwMinorVersion, @@ -101,49 +150,56 @@ RtlGetNtVersionNumbers(OUT LPDWORD pdwMajorVersion, } /* -* @implemented -*/ + * @implemented + * @note User-mode version of RtlGetVersion in ntoskrnl/rtl/misc.c + */ NTSTATUS NTAPI -RtlGetVersion(RTL_OSVERSIONINFOW *Info) +RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation) { - LONG i, MaxLength; + LONG i, MaxLength; - if (Info->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOW) || - Info->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW)) - { - PPEB Peb = NtCurrentPeb(); + if (lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOW) || + lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW)) + { + PPEB Peb = NtCurrentPeb(); - Info->dwMajorVersion = Peb->OSMajorVersion; - Info->dwMinorVersion = Peb->OSMinorVersion; - Info->dwBuildNumber = Peb->OSBuildNumber; - Info->dwPlatformId = Peb->OSPlatformId; - RtlZeroMemory(Info->szCSDVersion, sizeof(Info->szCSDVersion)); - if(((Peb->OSCSDVersion >> 8) & 0xFF) != 0) - { - MaxLength = (sizeof(Info->szCSDVersion) / sizeof(Info->szCSDVersion[0])) - 1; - i = _snwprintf(Info->szCSDVersion, - MaxLength, - L"Service Pack %d", - ((Peb->OSCSDVersion >> 8) & 0xFF)); - if (i < 0) + lpVersionInformation->dwMajorVersion = Peb->OSMajorVersion; + lpVersionInformation->dwMinorVersion = Peb->OSMinorVersion; + lpVersionInformation->dwBuildNumber = Peb->OSBuildNumber; + lpVersionInformation->dwPlatformId = Peb->OSPlatformId; + RtlZeroMemory(lpVersionInformation->szCSDVersion, sizeof(lpVersionInformation->szCSDVersion)); + + if(((Peb->OSCSDVersion >> 8) & 0xFF) != 0) { - /* null-terminate if it was overflowed */ - Info->szCSDVersion[MaxLength] = L'\0'; + MaxLength = (sizeof(lpVersionInformation->szCSDVersion) / sizeof(lpVersionInformation->szCSDVersion[0])) - 1; + i = _snwprintf(lpVersionInformation->szCSDVersion, + MaxLength, + L"Service Pack %d", + ((Peb->OSCSDVersion >> 8) & 0xFF)); + if (i < 0) + { + /* Null-terminate if it was overflowed */ + lpVersionInformation->szCSDVersion[MaxLength] = L'\0'; + } } - } - if (Info->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW)) - { - RTL_OSVERSIONINFOEXW *InfoEx = (RTL_OSVERSIONINFOEXW *)Info; - InfoEx->wServicePackMajor = (Peb->OSCSDVersion >> 8) & 0xFF; - InfoEx->wServicePackMinor = Peb->OSCSDVersion & 0xFF; - InfoEx->wSuiteMask = SharedUserData->SuiteMask & 0xFFFF; - InfoEx->wProductType = SharedUserData->NtProductType; - } - return STATUS_SUCCESS; - } + if (lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW)) + { + PRTL_OSVERSIONINFOEXW InfoEx = (PRTL_OSVERSIONINFOEXW)lpVersionInformation; + InfoEx->wServicePackMajor = (Peb->OSCSDVersion >> 8) & 0xFF; + InfoEx->wServicePackMinor = Peb->OSCSDVersion & 0xFF; + InfoEx->wSuiteMask = SharedUserData->SuiteMask & 0xFFFF; + InfoEx->wProductType = SharedUserData->NtProductType; + InfoEx->wReserved = 0; - return STATUS_INVALID_PARAMETER; + /* HACK: ReactOS specific changes, see bug-reports CORE-6611 and CORE-4620 (aka. #5003) */ + SetRosSpecificInfo(InfoEx); + } + + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; } /* EOF */ diff --git a/dll/win32/advapi32/advapi32.h b/dll/win32/advapi32/advapi32.h index 3c7d2a9375b..22c87c49843 100644 --- a/dll/win32/advapi32/advapi32.h +++ b/dll/win32/advapi32/advapi32.h @@ -57,10 +57,6 @@ #define FN_PROGRESSA FN_PROGRESS #endif -/* sid.c */ - -BOOL ADVAPI_GetComputerSid(PSID sid); - /* rpc.c */ RPC_STATUS EvtBindRpc(LPCWSTR pszMachine, diff --git a/dll/win32/advapi32/sec/sid.c b/dll/win32/advapi32/sec/sid.c index 91b5db6fb21..c289010d199 100644 --- a/dll/win32/advapi32/sec/sid.c +++ b/dll/win32/advapi32/sec/sid.c @@ -18,17 +18,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(advapi); BOOL WINAPI AddAuditAccessAceEx(PACL pAcl, - DWORD dwAceRevision, - DWORD AceFlags, - DWORD dwAccessMask, - PSID pSid, - BOOL bAuditSuccess, - BOOL bAuditFailure); + DWORD dwAceRevision, + DWORD AceFlags, + DWORD dwAccessMask, + PSID pSid, + BOOL bAuditSuccess, + BOOL bAuditFailure); typedef struct RECORD { - LPCWSTR key; - DWORD value; + LPCWSTR key; + DWORD value; } RECORD; @@ -299,67 +299,6 @@ static __inline BOOL set_ntstatus( NTSTATUS status ) return !status; } -/************************************************************ - * ADVAPI_GetComputerSid - * - * Reads the computer SID from the registry. - */ -BOOL ADVAPI_GetComputerSid(PSID sid) -{ - HKEY key; - LONG ret; - BOOL retval = FALSE; - static const WCHAR Account[] = { 'S','E','C','U','R','I','T','Y','\\','S','A','M','\\','D','o','m','a','i','n','s','\\','A','c','c','o','u','n','t',0 }; - static const WCHAR V[] = { 'V',0 }; - - if ((ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, Account, 0, - KEY_READ, &key)) == ERROR_SUCCESS) - { - DWORD size = 0; - ret = RegQueryValueExW(key, V, NULL, NULL, NULL, &size); - if (ret == ERROR_MORE_DATA || ret == ERROR_SUCCESS) - { - BYTE * data = HeapAlloc(GetProcessHeap(), 0, size); - if (data) - { - if ((ret = RegQueryValueExW(key, V, NULL, NULL, - data, &size)) == ERROR_SUCCESS) - { - /* the SID is in the last 24 bytes of the binary data */ - CopyMemory(sid, &data[size-24], 24); - retval = TRUE; - } - HeapFree(GetProcessHeap(), 0, data); - } - } - RegCloseKey(key); - } - - if(retval == TRUE) return retval; - - /* create a new random SID */ - if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, Account, - 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL) == ERROR_SUCCESS) - { - PSID new_sid; - SID_IDENTIFIER_AUTHORITY identifierAuthority = {SECURITY_NT_AUTHORITY}; - DWORD id[3]; - - if (RtlGenRandom(id, sizeof(id))) - { - if (AllocateAndInitializeSid(&identifierAuthority, 4, SECURITY_NT_NON_UNIQUE, id[0], id[1], id[2], 0, 0, 0, 0, &new_sid)) - { - if (RegSetValueExW(key, V, 0, REG_BINARY, new_sid, GetLengthSid(new_sid)) == ERROR_SUCCESS) - retval = CopySid(GetLengthSid(new_sid), sid, new_sid); - - FreeSid(new_sid); - } - } - RegCloseKey(key); - } - - return retval; -} /* Exported functions */ @@ -794,6 +733,7 @@ ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR Securi { LPWSTR wstr; ULONG len; + if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len)) { int lenA; @@ -971,15 +911,15 @@ static DWORD ParseAclStringFlags(LPCWSTR* StringAcl) while (*szAcl != '(') { if (*szAcl == 'P') - { + { flags |= SE_DACL_PROTECTED; - } + } else if (*szAcl == 'A') { szAcl++; if (*szAcl == 'R') flags |= SE_DACL_AUTO_INHERIT_REQ; - else if (*szAcl == 'I') + else if (*szAcl == 'I') flags |= SE_DACL_AUTO_INHERITED; } szAcl++; @@ -1059,7 +999,7 @@ static BYTE ParseAceStringFlags(LPCWSTR* StringAcl) if (!lpaf->wstr) return 0; - flags |= lpaf->value; + flags |= lpaf->value; szAcl += len; } @@ -1081,15 +1021,15 @@ static DWORD ParseAceStringRights(LPCWSTR* StringAcl) { LPCWSTR p = szAcl; - while (*p && *p != ';') + while (*p && *p != ';') p++; - if (p - szAcl <= 10 /* 8 hex digits + "0x" */ ) - { - rights = strtoulW(szAcl, NULL, 16); - szAcl = p; - } - else + if (p - szAcl <= 10 /* 8 hex digits + "0x" */ ) + { + rights = strtoulW(szAcl, NULL, 16); + szAcl = p; + } + else WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl)); } else @@ -1099,16 +1039,16 @@ static DWORD ParseAceStringRights(LPCWSTR* StringAcl) const ACEFLAG *lpaf = AceRights; while (lpaf->wstr && - (len = strlenW(lpaf->wstr)) && - strncmpW(lpaf->wstr, szAcl, len)) - { - lpaf++; - } + (len = strlenW(lpaf->wstr)) && + strncmpW(lpaf->wstr, szAcl, len)) + { + lpaf++; + } if (!lpaf->wstr) return 0; - rights |= lpaf->value; + rights |= lpaf->value; szAcl += len; } } @@ -1123,8 +1063,11 @@ static DWORD ParseAceStringRights(LPCWSTR* StringAcl) * * dacl_flags(string_ace1)(string_ace2)... (string_acen) */ -static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, - PACL pAcl, LPDWORD cBytes) +static BOOL +ParseStringAclToAcl(LPCWSTR StringAcl, + LPDWORD lpdwFlags, + PACL pAcl, + LPDWORD cBytes) { DWORD val; DWORD sidlen; @@ -1136,7 +1079,7 @@ static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, TRACE("%s\n", debugstr_w(StringAcl)); if (!StringAcl) - return FALSE; + return FALSE; if (pAcl) /* pAce is only useful if we're setting values */ pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1); @@ -1151,23 +1094,23 @@ static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, /* Parse ACE type */ val = ParseAceStringType(&StringAcl); - if (pAce) + if (pAce) pAce->Header.AceType = (BYTE) val; if (*StringAcl != ';') goto lerr; StringAcl++; /* Parse ACE flags */ - val = ParseAceStringFlags(&StringAcl); - if (pAce) + val = ParseAceStringFlags(&StringAcl); + if (pAce) pAce->Header.AceFlags = (BYTE) val; if (*StringAcl != ';') goto lerr; StringAcl++; /* Parse ACE rights */ - val = ParseAceStringRights(&StringAcl); - if (pAce) + val = ParseAceStringRights(&StringAcl); + if (pAce) pAce->Mask = val; if (*StringAcl != ';') goto lerr; @@ -1191,10 +1134,10 @@ static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, /* Parse ACE account sid */ if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen)) - { + { while (*StringAcl && *StringAcl != ')') StringAcl++; - } + } if (*StringAcl != ')') goto lerr; @@ -1238,10 +1181,10 @@ lerr: /****************************************************************************** * ParseStringSecurityDescriptorToSecurityDescriptor */ -static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( - LPCWSTR StringSecurityDescriptor, - SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor, - LPDWORD cBytes) +static BOOL +ParseStringSecurityDescriptorToSecurityDescriptor(LPCWSTR StringSecurityDescriptor, + SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor, + LPDWORD cBytes) { BOOL bret = FALSE; WCHAR toktype; @@ -1259,21 +1202,21 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( { toktype = *StringSecurityDescriptor; - /* Expect char identifier followed by ':' */ - StringSecurityDescriptor++; + /* Expect char identifier followed by ':' */ + StringSecurityDescriptor++; if (*StringSecurityDescriptor != ':') { SetLastError(ERROR_INVALID_PARAMETER); goto lend; } - StringSecurityDescriptor++; + StringSecurityDescriptor++; - /* Extract token */ - lptoken = StringSecurityDescriptor; - while (*lptoken && *lptoken != ':') + /* Extract token */ + lptoken = StringSecurityDescriptor; + while (*lptoken && *lptoken != ':') lptoken++; - if (*lptoken) + if (*lptoken) lptoken--; len = lptoken - StringSecurityDescriptor; @@ -1281,7 +1224,7 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( tok[len] = 0; switch (toktype) - { + { case 'O': { DWORD bytes; @@ -1295,7 +1238,7 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( lpNext += bytes; /* Advance to next token */ } - *cBytes += bytes; + *cBytes += bytes; break; } @@ -1313,13 +1256,13 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( lpNext += bytes; /* Advance to next token */ } - *cBytes += bytes; + *cBytes += bytes; break; } case 'D': - { + { DWORD flags; DWORD bytes; @@ -1331,11 +1274,11 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( SecurityDescriptor->Control |= SE_DACL_PRESENT | flags; SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor; lpNext += bytes; /* Advance to next token */ - } + } - *cBytes += bytes; + *cBytes += bytes; - break; + break; } case 'S': @@ -1351,18 +1294,18 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( SecurityDescriptor->Control |= SE_SACL_PRESENT | flags; SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor; lpNext += bytes; /* Advance to next token */ - } + } - *cBytes += bytes; + *cBytes += bytes; - break; + break; } default: FIXME("Unknown token\n"); SetLastError(ERROR_INVALID_PARAMETER); - goto lend; - } + goto lend; + } StringSecurityDescriptor = lptoken; } @@ -1378,11 +1321,11 @@ lend: * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@] * @implemented */ -BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW( - LPCWSTR StringSecurityDescriptor, - DWORD StringSDRevision, - PSECURITY_DESCRIPTOR* SecurityDescriptor, - PULONG SecurityDescriptorSize) +BOOL WINAPI +ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor, + DWORD StringSDRevision, + PSECURITY_DESCRIPTOR* SecurityDescriptor, + PULONG SecurityDescriptorSize) { DWORD cBytes; SECURITY_DESCRIPTOR* psd; @@ -1403,13 +1346,13 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW( else if (StringSDRevision != SID_REVISION) { SetLastError(ERROR_UNKNOWN_REVISION); - goto lend; + goto lend; } /* Compute security descriptor length */ if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor, NULL, &cBytes)) - goto lend; + goto lend; psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes); if (!psd) goto lend; @@ -1421,14 +1364,14 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW( (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes)) { LocalFree(psd); - goto lend; + goto lend; } if (SecurityDescriptorSize) *SecurityDescriptorSize = cBytes; bret = TRUE; - + lend: TRACE(" ret=%d\n", bret); return bret; @@ -1440,11 +1383,12 @@ lend: * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@] * @implemented */ -BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA( - LPCSTR StringSecurityDescriptor, - DWORD StringSDRevision, - PSECURITY_DESCRIPTOR* SecurityDescriptor, - PULONG SecurityDescriptorSize) +BOOL +WINAPI +ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor, + DWORD StringSDRevision, + PSECURITY_DESCRIPTOR* SecurityDescriptor, + PULONG SecurityDescriptorSize) { UINT len; BOOL ret = FALSE; @@ -1469,7 +1413,8 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA( /* * @implemented */ -BOOL WINAPI +BOOL +WINAPI EqualPrefixSid(PSID pSid1, PSID pSid2) { @@ -1480,7 +1425,8 @@ EqualPrefixSid(PSID pSid1, /* * @implemented */ -BOOL WINAPI +BOOL +WINAPI EqualSid(PSID pSid1, PSID pSid2) { @@ -1495,7 +1441,8 @@ EqualSid(PSID pSid1, * Docs says this function does NOT return a value * even thou it's defined to return a PVOID... */ -PVOID WINAPI +PVOID +WINAPI FreeSid(PSID pSid) { return RtlFreeSid(pSid); @@ -1505,7 +1452,8 @@ FreeSid(PSID pSid) /* * @implemented */ -DWORD WINAPI +DWORD +WINAPI GetLengthSid(PSID pSid) { return (DWORD)RtlLengthSid(pSid); @@ -1515,7 +1463,8 @@ GetLengthSid(PSID pSid) /* * @implemented */ -PSID_IDENTIFIER_AUTHORITY WINAPI +PSID_IDENTIFIER_AUTHORITY +WINAPI GetSidIdentifierAuthority(PSID pSid) { return RtlIdentifierAuthoritySid(pSid); @@ -1525,7 +1474,8 @@ GetSidIdentifierAuthority(PSID pSid) /* * @implemented */ -DWORD WINAPI +DWORD +WINAPI GetSidLengthRequired(UCHAR nSubAuthorityCount) { return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount); @@ -1535,7 +1485,8 @@ GetSidLengthRequired(UCHAR nSubAuthorityCount) /* * @implemented */ -PDWORD WINAPI +PDWORD +WINAPI GetSidSubAuthority(PSID pSid, DWORD nSubAuthority) { @@ -1546,7 +1497,8 @@ GetSidSubAuthority(PSID pSid, /* * @implemented */ -PUCHAR WINAPI +PUCHAR +WINAPI GetSidSubAuthorityCount(PSID pSid) { return RtlSubAuthorityCountSid(pSid); @@ -1556,7 +1508,8 @@ GetSidSubAuthorityCount(PSID pSid) /* * @implemented */ -BOOL WINAPI +BOOL +WINAPI InitializeSid(PSID Sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount) @@ -1579,7 +1532,8 @@ InitializeSid(PSID Sid, /* * @implemented */ -BOOL WINAPI +BOOL +WINAPI IsValidSid(PSID pSid) { return (BOOL)RtlValidSid(pSid); @@ -1589,7 +1543,8 @@ IsValidSid(PSID pSid) /* * @implemented */ -BOOL WINAPI +BOOL +WINAPI ConvertSidToStringSidW(PSID Sid, LPWSTR *StringSid) { @@ -1643,7 +1598,8 @@ ConvertSidToStringSidW(PSID Sid, /* * @implemented */ -BOOL WINAPI +BOOL +WINAPI ConvertSidToStringSidA(PSID Sid, LPSTR *StringSid) { @@ -1687,7 +1643,8 @@ ConvertSidToStringSidA(PSID Sid, /* * @unimplemented */ -BOOL WINAPI +BOOL +WINAPI EqualDomainSid(IN PSID pSid1, IN PSID pSid2, OUT BOOL* pfEqual) @@ -1700,7 +1657,8 @@ EqualDomainSid(IN PSID pSid1, /* * @unimplemented */ -BOOL WINAPI +BOOL +WINAPI GetWindowsAccountDomainSid(IN PSID pSid, OUT PSID ppDomainSid, IN OUT DWORD* cbSid) @@ -1713,7 +1671,8 @@ GetWindowsAccountDomainSid(IN PSID pSid, /* * @unimplemented */ -BOOL WINAPI +BOOL +WINAPI CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType, IN PSID DomainSid OPTIONAL, OUT PSID pSid, @@ -1787,7 +1746,8 @@ CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType, /* * @unimplemented */ -BOOL WINAPI +BOOL +WINAPI IsWellKnownSid(IN PSID pSid, IN WELL_KNOWN_SID_TYPE WellKnownSidType) { @@ -1810,7 +1770,8 @@ IsWellKnownSid(IN PSID pSid, /* * @implemented */ -BOOL WINAPI +BOOL +WINAPI ConvertStringSidToSidA(IN LPCSTR StringSid, OUT PSID* sid) { @@ -1879,7 +1840,8 @@ static const RECORD SidTable[] = /* * @implemented */ -BOOL WINAPI +BOOL +WINAPI ConvertStringSidToSidW(IN LPCWSTR StringSid, OUT PSID* sid) { @@ -1890,43 +1852,43 @@ ConvertStringSidToSidW(IN LPCWSTR StringSid, TRACE("%s %p\n", debugstr_w(StringSid), sid); - if (!StringSid) - { - SetLastError(ERROR_INVALID_SID); - return FALSE; - } - for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++) - { - if (wcscmp(StringSid, SidTable[i].key) == 0) - { - WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value; - size = SECURITY_MAX_SID_SIZE; - *sid = LocalAlloc(0, size); - if (!*sid) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - ret = CreateWellKnownSid( - knownSid, - NULL, - *sid, - &size); - if (!ret) - { - SetLastError(ERROR_INVALID_SID); - LocalFree(*sid); - } - return ret; - } - } + if (!StringSid) + { + SetLastError(ERROR_INVALID_SID); + return FALSE; + } - /* That's probably a string S-R-I-S-S... */ - if (StringSid[0] != 'S' || StringSid[1] != '-') - { - SetLastError(ERROR_INVALID_SID); - return FALSE; - } + for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++) + { + if (wcscmp(StringSid, SidTable[i].key) == 0) + { + WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value; + size = SECURITY_MAX_SID_SIZE; + *sid = LocalAlloc(0, size); + if (!*sid) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + ret = CreateWellKnownSid(knownSid, + NULL, + *sid, + &size); + if (!ret) + { + SetLastError(ERROR_INVALID_SID); + LocalFree(*sid); + } + return ret; + } + } + + /* That's probably a string S-R-I-S-S... */ + if (StringSid[0] != 'S' || StringSid[1] != '-') + { + SetLastError(ERROR_INVALID_SID); + return FALSE; + } cBytes = ComputeStringSidSize(StringSid); pisid = (SID*)LocalAlloc( 0, cBytes ); @@ -2005,5 +1967,4 @@ lend: return ret; } - /* EOF */ diff --git a/dll/win32/kernel32/client/version.c b/dll/win32/kernel32/client/version.c index e8303086bb8..c0afdbf9ce5 100644 --- a/dll/win32/kernel32/client/version.c +++ b/dll/win32/kernel32/client/version.c @@ -14,57 +14,6 @@ /* FUNCTIONS ******************************************************************/ -VOID -NTAPI -SetRosSpecificInfo(IN LPOSVERSIONINFOEXW VersionInformation) -{ - CHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)]; - PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = (PVOID)Buffer; - OBJECT_ATTRIBUTES ObjectAttributes; - DWORD ReportAsWorkstation = 0; - HANDLE hKey; - DWORD dwSize; - NTSTATUS Status; - UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version"); - UNICODE_STRING ValName = RTL_CONSTANT_STRING(L"ReportAsWorkstation"); - - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_OPENIF | OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - /* Don't change anything if the key doesn't exist */ - Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes); - if (NT_SUCCESS(Status)) - { - /* Get the value from the registry and make sure it's a 32-bit value */ - Status = NtQueryValueKey(hKey, - &ValName, - KeyValuePartialInformation, - kvpInfo, - sizeof(Buffer), - &dwSize); - if ((NT_SUCCESS(Status)) && - (kvpInfo->Type == REG_DWORD) && - (kvpInfo->DataLength == sizeof(DWORD))) - { - /* Is the value set? */ - ReportAsWorkstation = *(PULONG)kvpInfo->Data; - if ((VersionInformation->wProductType == VER_NT_SERVER) && - (ReportAsWorkstation)) - { - /* It is, modify the product type to report a workstation */ - VersionInformation->wProductType = VER_NT_WORKSTATION; - DPRINT1("We modified the reported OS from NtProductServer to NtProductWinNt\n"); - } - } - - /* Close the handle */ - NtClose(hKey); - } -} - /* * @implemented */ @@ -104,9 +53,6 @@ GetVersionExW(IN LPOSVERSIONINFOW lpVersionInformation) { lpVersionInformationEx = (PVOID)lpVersionInformation; lpVersionInformationEx->wReserved = 0; - - /* ReactOS specific changes */ - SetRosSpecificInfo(lpVersionInformationEx); } return TRUE; diff --git a/dll/win32/netapi32/CMakeLists.txt b/dll/win32/netapi32/CMakeLists.txt index 219f4f9dfed..50ae272e06d 100644 --- a/dll/win32/netapi32/CMakeLists.txt +++ b/dll/win32/netapi32/CMakeLists.txt @@ -28,5 +28,7 @@ target_link_libraries(netapi32 wine) add_importlibs(netapi32 iphlpapi ws2_32 advapi32 msvcrt kernel32 ntdll) +add_delay_importlibs(netapi32 samlib) + add_cd_file(TARGET netapi32 DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/netapi32/local_group.c b/dll/win32/netapi32/local_group.c index e125de5b9ff..a02d1cceb84 100644 --- a/dll/win32/netapi32/local_group.c +++ b/dll/win32/netapi32/local_group.c @@ -34,8 +34,122 @@ #include "wine/debug.h" #include "wine/unicode.h" +#define NTOS_MODE_USER +#include +#include "ntsam.h" +#include "netapi32.h" + WINE_DEFAULT_DEBUG_CHANNEL(netapi32); + +typedef struct _ENUM_CONTEXT +{ + SAM_HANDLE ServerHandle; + SAM_HANDLE BuiltinDomainHandle; + SAM_HANDLE AccountDomainHandle; + + SAM_ENUMERATE_HANDLE EnumerationContext; + PSAM_RID_ENUMERATION Buffer; + ULONG Returned; + ULONG Index; + BOOLEAN BuiltinDone; + +} ENUM_CONTEXT, *PENUM_CONTEXT; + +static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; + + +static +NTSTATUS +GetAccountDomainSid(PSID *AccountDomainSid) +{ + PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL; + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + LSA_HANDLE PolicyHandle = NULL; + ULONG Length = 0; + NTSTATUS Status; + + memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES)); + + Status = LsaOpenPolicy(NULL, + &ObjectAttributes, + POLICY_VIEW_LOCAL_INFORMATION, + &PolicyHandle); + if (!NT_SUCCESS(Status)) + { + ERR("LsaOpenPolicy failed (Status %08lx)\n", Status); + return Status; + } + + Status = LsaQueryInformationPolicy(PolicyHandle, + PolicyAccountDomainInformation, + (PVOID *)&AccountDomainInfo); + if (!NT_SUCCESS(Status)) + { + ERR("LsaQueryInformationPolicy failed (Status %08lx)\n", Status); + goto done; + } + + Length = RtlLengthSid(AccountDomainInfo->DomainSid); + + *AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length); + if (*AccountDomainSid == NULL) + { + ERR("Failed to allocate SID\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + memcpy(*AccountDomainSid, AccountDomainInfo->DomainSid, Length); + +done: + if (AccountDomainInfo != NULL) + LsaFreeMemory(AccountDomainInfo); + + LsaClose(PolicyHandle); + + return Status; +} + + +static +NTSTATUS +GetBuiltinDomainSid(PSID *BuiltinDomainSid) +{ + PSID Sid = NULL; + PULONG Ptr; + NTSTATUS Status = STATUS_SUCCESS; + + *BuiltinDomainSid = NULL; + + Sid = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + RtlLengthRequiredSid(1)); + if (Sid == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + Status = RtlInitializeSid(Sid, + &NtAuthority, + 1); + if (!NT_SUCCESS(Status)) + goto done; + + Ptr = RtlSubAuthoritySid(Sid, 0); + *Ptr = SECURITY_BUILTIN_DOMAIN_RID; + + *BuiltinDomainSid = Sid; + +done: + if (!NT_SUCCESS(Status)) + { + if (Sid != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, Sid); + } + + return Status; +} + + /************************************************************ * NetLocalGroupAdd (NETAPI32.@) */ @@ -129,11 +243,236 @@ NET_API_STATUS WINAPI NetLocalGroupEnum( LPDWORD totalentries, PDWORD_PTR resumehandle) { + PSAM_RID_ENUMERATION CurrentAlias; + PENUM_CONTEXT EnumContext = NULL; + PSID DomainSid = NULL; + ULONG i; + SAM_HANDLE AliasHandle = NULL; + PALIAS_GENERAL_INFORMATION AliasInfo = NULL; + + NET_API_STATUS ApiStatus = NERR_Success; + NTSTATUS Status = STATUS_SUCCESS; + + FIXME("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername), level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle); + *entriesread = 0; *totalentries = 0; - return NERR_Success; + *bufptr = NULL; + + if (resumehandle != NULL && *resumehandle != 0) + { + EnumContext = (PENUM_CONTEXT)resumehandle; + } + else + { + ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext); + if (ApiStatus != NERR_Success) + goto done; + + EnumContext->EnumerationContext = 0; + EnumContext->Buffer = NULL; + EnumContext->Returned = 0; + EnumContext->Index = 0; + EnumContext->BuiltinDone = FALSE; + + Status = SamConnect(NULL, + &EnumContext->ServerHandle, + SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, + NULL); + if (!NT_SUCCESS(Status)) + { + ERR("SamConnect failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + Status = GetAccountDomainSid(&DomainSid); + if (!NT_SUCCESS(Status)) + { + ERR("GetAccountDomainSid failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + Status = SamOpenDomain(EnumContext->ServerHandle, + DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, + DomainSid, + &EnumContext->AccountDomainHandle); + + RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid); + + if (!NT_SUCCESS(Status)) + { + ERR("SamOpenDomain failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + Status = GetBuiltinDomainSid(&DomainSid); + if (!NT_SUCCESS(Status)) + { + ERR("GetAccountDomainSid failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + Status = SamOpenDomain(EnumContext->ServerHandle, + DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, + DomainSid, + &EnumContext->BuiltinDomainHandle); + + RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid); + + if (!NT_SUCCESS(Status)) + { + ERR("SamOpenDomain failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + } + + + while (TRUE) + { + + if (EnumContext->Index >= EnumContext->Returned) + { + if (EnumContext->BuiltinDone == TRUE) + { + ApiStatus = NERR_Success; + goto done; + } + + TRACE("Calling SamEnumerateAliasesInDomain\n"); + + Status = SamEnumerateAliasesInDomain(EnumContext->BuiltinDomainHandle, + &EnumContext->EnumerationContext, + (PVOID *)&EnumContext->Buffer, + prefmaxlen, + &EnumContext->Returned); + + TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status); + if (!NT_SUCCESS(Status)) + { + ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + if (Status == STATUS_MORE_ENTRIES) + { + ApiStatus = NERR_BufTooSmall; + goto done; + } + else + { + EnumContext->BuiltinDone = TRUE; + } + } + + TRACE("EnumContext: %lu\n", EnumContext); + TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned); + TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer); + + /* Get a pointer to the current alias */ + CurrentAlias = &EnumContext->Buffer[EnumContext->Index]; + + TRACE("RID: %lu\n", CurrentAlias->RelativeId); + + Status = SamOpenAlias(EnumContext->BuiltinDomainHandle, + ALIAS_READ_INFORMATION, + CurrentAlias->RelativeId, + &AliasHandle); + if (!NT_SUCCESS(Status)) + { + ERR("SamOpenAlias failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + Status = SamQueryInformationAlias(AliasHandle, + AliasGeneralInformation, + (PVOID *)&AliasInfo); + if (!NT_SUCCESS(Status)) + { + ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + SamCloseHandle(AliasHandle); + AliasHandle = NULL; + + TRACE("Name: %S\n", AliasInfo->Name.Buffer); + TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer); + + + if (AliasInfo != NULL) + { + if (AliasInfo->Name.Buffer != NULL) + SamFreeMemory(AliasInfo->Name.Buffer); + + if (AliasInfo->AdminComment.Buffer != NULL) + SamFreeMemory(AliasInfo->AdminComment.Buffer); + + SamFreeMemory(AliasInfo); + AliasInfo = NULL; + } + + + EnumContext->Index++; + } + + +done: + if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA) + { + if (EnumContext != NULL) + { + if (EnumContext->BuiltinDomainHandle != NULL) + SamCloseHandle(EnumContext->BuiltinDomainHandle); + + if (EnumContext->AccountDomainHandle != NULL) + SamCloseHandle(EnumContext->AccountDomainHandle); + + if (EnumContext->ServerHandle != NULL) + SamCloseHandle(EnumContext->ServerHandle); + + if (EnumContext->Buffer != NULL) + { + for (i = 0; i < EnumContext->Returned; i++) + { + SamFreeMemory(EnumContext->Buffer[i].Name.Buffer); + } + + SamFreeMemory(EnumContext->Buffer); + } + + NetApiBufferFree(EnumContext); + EnumContext = NULL; + } + } + + if (AliasHandle != NULL) + SamCloseHandle(AliasHandle); + + if (AliasInfo != NULL) + { + if (AliasInfo->Name.Buffer != NULL) + SamFreeMemory(AliasInfo->Name.Buffer); + + if (AliasInfo->AdminComment.Buffer != NULL) + SamFreeMemory(AliasInfo->AdminComment.Buffer); + + SamFreeMemory(AliasInfo); + } + + if (resumehandle != NULL) + *resumehandle = (DWORD_PTR)EnumContext; + + return ApiStatus; } /************************************************************ diff --git a/dll/win32/netapi32/netapi32.c b/dll/win32/netapi32/netapi32.c index fb4468f6950..a0a83470635 100644 --- a/dll/win32/netapi32/netapi32.c +++ b/dll/win32/netapi32/netapi32.c @@ -16,12 +16,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define WIN32_NO_STATUS #include "config.h" #include "wine/debug.h" #include "lm.h" #include "netbios.h" +#define NTOS_MODE_USER +#include +#include "netapi32.h" + WINE_DEFAULT_DEBUG_CHANNEL(netbios); static HMODULE NETAPI32_hModule; @@ -211,6 +216,13 @@ DWORD WINAPI NetpNetBiosStatusToApiStatus(DWORD nrc) return ret; } +NET_API_STATUS +WINAPI +NetpNtStatusToApiStatus(NTSTATUS Status) +{ + return RtlNtStatusToDosError(Status); +} + NET_API_STATUS WINAPI NetUseEnum(LMSTR server, DWORD level, LPBYTE* bufptr, DWORD prefmaxsize, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resumehandle) { diff --git a/dll/win32/netapi32/netapi32.h b/dll/win32/netapi32/netapi32.h new file mode 100644 index 00000000000..f7a0a7a57e3 --- /dev/null +++ b/dll/win32/netapi32/netapi32.h @@ -0,0 +1,10 @@ + +#ifndef __WINE_NETAPI32_H__ +#define __WINE_NETAPI32_H__ + +NET_API_STATUS +WINAPI +NetpNtStatusToApiStatus(NTSTATUS Status); + + +#endif \ No newline at end of file diff --git a/dll/win32/netapi32/netapi32.spec b/dll/win32/netapi32/netapi32.spec index 647028079dc..1fb5ccf14ba 100644 --- a/dll/win32/netapi32/netapi32.spec +++ b/dll/win32/netapi32/netapi32.spec @@ -261,7 +261,7 @@ @ stub NetpNetBiosReset @ stub NetpNetBiosSend @ stdcall NetpNetBiosStatusToApiStatus(long) -@ stub NetpNtStatusToApiStatus +@ stdcall NetpNtStatusToApiStatus(long) @ stub NetpOpenConfigData @ stub NetpPackString @ stub NetpReleasePrivilege diff --git a/dll/win32/samsrv/samrpc.c b/dll/win32/samsrv/samrpc.c index fc885fd02b1..68b886a7e11 100644 --- a/dll/win32/samsrv/samrpc.c +++ b/dll/win32/samsrv/samrpc.c @@ -155,6 +155,7 @@ SamrShutdownSamServer(IN SAMPR_HANDLE ServerHandle) return STATUS_NOT_IMPLEMENTED; } + /* Function 5 */ NTSTATUS NTAPI @@ -264,6 +265,7 @@ SamrLookupDomainInSamServer(IN SAMPR_HANDLE ServerHandle, return Status; } + /* Function 6 */ NTSTATUS NTAPI @@ -3868,17 +3870,24 @@ SampQueryAliasGeneral(PSAM_DB_OBJECT AliasObject, L"Members", KEY_READ, &MembersKeyHandle); - if (!NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) { - TRACE("Status 0x%08lx\n", Status); - goto done; + /* Retrieve the number of members of the alias */ + Status = SampRegQueryKeyInfo(MembersKeyHandle, + NULL, + &InfoBuffer->General.MemberCount); + if (!NT_SUCCESS(Status)) + { + TRACE("Status 0x%08lx\n", Status); + goto done; + } } - - /* Retrieve the number of members of the alias */ - Status = SampRegQueryKeyInfo(MembersKeyHandle, - NULL, - &InfoBuffer->General.MemberCount); - if (!NT_SUCCESS(Status)) + else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + InfoBuffer->General.MemberCount = 0; + Status = STATUS_SUCCESS; + } + else { TRACE("Status 0x%08lx\n", Status); goto done; diff --git a/lib/rtl/version.c b/lib/rtl/version.c index e81509cd96f..b2e82108a62 100644 --- a/lib/rtl/version.c +++ b/lib/rtl/version.c @@ -4,7 +4,7 @@ * PURPOSE: Runtime code * FILE: lib/rtl/version.c * PROGRAMERS: Filip Navara - * Hermes BELUSCA - MAITO + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *****************************************************************/ @@ -18,9 +18,7 @@ NTSTATUS NTAPI -RtlGetVersion( - OUT PRTL_OSVERSIONINFOW lpVersionInformation - ); +RtlGetVersion(OUT PRTL_OSVERSIONINFOW lpVersionInformation); /* FUNCTIONS ****************************************************************/ @@ -54,11 +52,9 @@ RtlpVerCompare(ULONG left, ULONG right, UCHAR condition) */ NTSTATUS NTAPI -RtlVerifyVersionInfo( - IN PRTL_OSVERSIONINFOEXW VersionInfo, - IN ULONG TypeMask, - IN ULONGLONG ConditionMask - ) +RtlVerifyVersionInfo(IN PRTL_OSVERSIONINFOEXW VersionInfo, + IN ULONG TypeMask, + IN ULONGLONG ConditionMask) { RTL_OSVERSIONINFOEXW ver; NTSTATUS status; diff --git a/ntoskrnl/mm/ARM3/procsup.c b/ntoskrnl/mm/ARM3/procsup.c index ae5d496e9f9..27660f72180 100644 --- a/ntoskrnl/mm/ARM3/procsup.c +++ b/ntoskrnl/mm/ARM3/procsup.c @@ -678,7 +678,7 @@ MmCreatePeb(IN PEPROCESS Process, Peb->OSMajorVersion = NtMajorVersion; Peb->OSMinorVersion = NtMinorVersion; Peb->OSBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF); - Peb->OSPlatformId = 2; /* VER_PLATFORM_WIN32_NT */ + Peb->OSPlatformId = VER_PLATFORM_WIN32_NT; Peb->OSCSDVersion = (USHORT)CmNtCSDVersion; // diff --git a/ntoskrnl/rtl/misc.c b/ntoskrnl/rtl/misc.c index 2ad6931fda7..d7c09b1b9b7 100644 --- a/ntoskrnl/rtl/misc.c +++ b/ntoskrnl/rtl/misc.c @@ -29,51 +29,55 @@ ULONG NTAPI RtlGetNtGlobalFlags(VOID) { - return(NtGlobalFlag); + return NtGlobalFlag; } - /* * @implemented */ NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation) { - LONG i; - ULONG MaxLength; - if (lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOW) || - lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW)) - { - lpVersionInformation->dwMajorVersion = NtMajorVersion; - lpVersionInformation->dwMinorVersion = NtMinorVersion; - lpVersionInformation->dwBuildNumber = NtBuildNumber; - lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT; - RtlZeroMemory(lpVersionInformation->szCSDVersion, sizeof(lpVersionInformation->szCSDVersion)); - if(((CmNtCSDVersion >> 8) & 0xFF) != 0) - { - MaxLength = (sizeof(lpVersionInformation->szCSDVersion) / sizeof(lpVersionInformation->szCSDVersion[0])) - 1; - i = _snwprintf(lpVersionInformation->szCSDVersion, - MaxLength, - L"Service Pack %d", - ((CmNtCSDVersion >> 8) & 0xFF)); - if (i < 0) + LONG i; + ULONG MaxLength; + + if (lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOW) || + lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW)) + { + lpVersionInformation->dwMajorVersion = NtMajorVersion; + lpVersionInformation->dwMinorVersion = NtMinorVersion; + lpVersionInformation->dwBuildNumber = NtBuildNumber; + lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT; + RtlZeroMemory(lpVersionInformation->szCSDVersion, sizeof(lpVersionInformation->szCSDVersion)); + + if(((CmNtCSDVersion >> 8) & 0xFF) != 0) { - /* null-terminate if it was overflowed */ - lpVersionInformation->szCSDVersion[MaxLength] = L'\0'; + MaxLength = (sizeof(lpVersionInformation->szCSDVersion) / sizeof(lpVersionInformation->szCSDVersion[0])) - 1; + i = _snwprintf(lpVersionInformation->szCSDVersion, + MaxLength, + L"Service Pack %d", + ((CmNtCSDVersion >> 8) & 0xFF)); + if (i < 0) + { + /* Null-terminate if it was overflowed */ + lpVersionInformation->szCSDVersion[MaxLength] = L'\0'; + } } - } - if (lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW)) - { - RTL_OSVERSIONINFOEXW *InfoEx = (RTL_OSVERSIONINFOEXW *)lpVersionInformation; - InfoEx->wServicePackMajor = (USHORT)(CmNtCSDVersion >> 8) & 0xFF; - InfoEx->wServicePackMinor = (USHORT)(CmNtCSDVersion & 0xFF); - InfoEx->wSuiteMask = (USHORT)(SharedUserData->SuiteMask & 0xFFFF); - InfoEx->wProductType = SharedUserData->NtProductType; - } - return STATUS_SUCCESS; - } + if (lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW)) + { + PRTL_OSVERSIONINFOEXW InfoEx = (PRTL_OSVERSIONINFOEXW)lpVersionInformation; + InfoEx->wServicePackMajor = (USHORT)(CmNtCSDVersion >> 8) & 0xFF; + InfoEx->wServicePackMinor = (USHORT)(CmNtCSDVersion & 0xFF); + InfoEx->wSuiteMask = (USHORT)(SharedUserData->SuiteMask & 0xFFFF); + InfoEx->wProductType = SharedUserData->NtProductType; + InfoEx->wReserved = 0; + } - return STATUS_INVALID_PARAMETER; + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; } +/* EOF */ diff --git a/win32ss/CMakeLists.txt b/win32ss/CMakeLists.txt index 25e4df5da55..38a2a0ffb21 100644 --- a/win32ss/CMakeLists.txt +++ b/win32ss/CMakeLists.txt @@ -11,6 +11,10 @@ if(USE_DIBLIB) add_subdirectory(gdi/diblib) endif() +if(USE_NEW_CURSORICON) + add_definitions(-DNEW_CURSORICON) +endif() + add_subdirectory(gdi/gdi32) add_subdirectory(reactx) add_subdirectory(user/consrv) @@ -190,7 +194,6 @@ else() endif() if(USE_NEW_CURSORICON) - add_definitions(-DNEW_CURSORICON) list(APPEND SOURCE user/ntuser/cursoricon_new.c) else() list(APPEND SOURCE user/ntuser/cursoricon.c) diff --git a/win32ss/gdi/gdi32/CMakeLists.txt b/win32ss/gdi/gdi32/CMakeLists.txt index 184f81f64cf..0e4ba75bb2c 100644 --- a/win32ss/gdi/gdi32/CMakeLists.txt +++ b/win32ss/gdi/gdi32/CMakeLists.txt @@ -48,14 +48,17 @@ list(APPEND SOURCE add_library(gdi32 SHARED ${SOURCE}) -set_module_type(gdi32 win32dll UNICODE) +set_module_type(gdi32 + win32dll + ENTRYPOINT DllMain 12 + UNICODE) target_link_libraries(gdi32 win32ksys dxguid ${PSEH_LIB}) -add_importlibs(gdi32 user32 advapi32 msvcrt kernel32 ntdll) +add_importlibs(gdi32 user32 advapi32 kernel32 ntdll) add_pch(gdi32 include/precomp.h) add_cd_file(TARGET gdi32 DESTINATION reactos/system32 FOR all) diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index 84f315b0e88..5e7bf2ca53e 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -1659,8 +1659,8 @@ NtUserDestroyAcceleratorTable( BOOL NTAPI NtUserDestroyCursor( - HANDLE Handle, - DWORD Unknown); + _In_ HANDLE Handle, + _In_ BOOL bForce); DWORD NTAPI @@ -1818,14 +1818,6 @@ NtUserFillWindow( HDC hDC, HBRUSH hBrush); -HICON -NTAPI -NtUserFindExistingCursorIcon( - HMODULE hModule, - HRSRC hRsrc, - LONG cx, - LONG cy); - HWND NTAPI NtUserFindWindowEx( @@ -1998,12 +1990,12 @@ NtUserGetGUIThreadInfo( BOOL NTAPI NtUserGetIconInfo( - HANDLE hCurIcon, - PICONINFO IconInfo, - PUNICODE_STRING lpInstName, - PUNICODE_STRING lpResName, - LPDWORD pbpp, - BOOL bInternal); + _In_ HANDLE hCurIcon, + _Out_opt_ PICONINFO IconInfo, + _Out_opt_ PUNICODE_STRING lpInstName, + _Out_opt_ PUNICODE_STRING lpResName, + _Out_opt_ LPDWORD pbpp, + _In_ BOOL bInternal); BOOL NTAPI @@ -2743,9 +2735,17 @@ BOOL NTAPI NtUserSetCursorIconData( _In_ HCURSOR hCursor, - _In_ HINSTANCE hinst, - _In_ HRSRC hrsrc, + _In_ PUNICODE_STRING pustrModule, + _In_ PUNICODE_STRING puSrcName, _In_ PICONINFO pii); + +HICON +NTAPI +NtUserFindExistingCursorIcon( + _In_ PUNICODE_STRING pustrModule, + _In_ PUNICODE_STRING pustrRsrc, + _In_ LONG cxDesired, + _In_ LONG cyDesired); #else BOOL NTAPI @@ -2756,6 +2756,14 @@ NtUserSetCursorIconData( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc); + +HICON +NTAPI +NtUserFindExistingCursorIcon( + HMODULE hModule, + HRSRC hRsrc, + LONG cx, + LONG cy); #endif DWORD diff --git a/win32ss/include/ntusrtyp.h b/win32ss/include/ntusrtyp.h index b54bc9bc7e1..27a5aad4840 100644 --- a/win32ss/include/ntusrtyp.h +++ b/win32ss/include/ntusrtyp.h @@ -88,8 +88,9 @@ typedef struct typedef struct { union - { ICONRESDIR icon; - CURSORDIR cursor; + { + ICONRESDIR icon; + CURSORDIR cursor; } ResInfo; WORD wPlanes; WORD wBitCount; diff --git a/win32ss/user/ntuser/class.c b/win32ss/user/ntuser/class.c index afba9eb9399..209dccc674f 100644 --- a/win32ss/user/ntuser/class.c +++ b/win32ss/user/ntuser/class.c @@ -124,7 +124,7 @@ LookupFnIdToiCls(int FnId, int *iCls ) _Must_inspect_result_ NTSTATUS NTAPI -CaptureUnicodeStringOrAtom( +ProbeAndCaptureUnicodeStringOrAtom( _Out_ PUNICODE_STRING pustrOut, __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe) { @@ -2294,7 +2294,7 @@ NtUserUnregisterClass( NTSTATUS Status; BOOL Ret; - Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom); + Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom); if (!NT_SUCCESS(Status)) { ERR("Error capturing the class name\n"); @@ -2346,7 +2346,7 @@ NtUserGetClassInfo( } _SEH2_END; - Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassName); + Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName); if (!NT_SUCCESS(Status)) { ERR("Error capturing the class name\n"); @@ -2480,7 +2480,7 @@ NtUserGetWOWClass( RTL_ATOM ClassAtom = 0; NTSTATUS Status; - Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassName); + Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName); if (!NT_SUCCESS(Status)) { ERR("Error capturing the class name\n"); diff --git a/win32ss/user/ntuser/class.h b/win32ss/user/ntuser/class.h index f2d79781902..901f2b4ce8d 100644 --- a/win32ss/user/ntuser/class.h +++ b/win32ss/user/ntuser/class.h @@ -59,4 +59,11 @@ IntCheckProcessDesktopClasses(IN PDESKTOP Desktop, ULONG_PTR FASTCALL UserGetCPD(PVOID,GETCPD,ULONG_PTR); +_Must_inspect_result_ +NTSTATUS +NTAPI +ProbeAndCaptureUnicodeStringOrAtom( + _Out_ PUNICODE_STRING pustrOut, + __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe); + /* EOF */ diff --git a/win32ss/user/ntuser/cursoricon.c b/win32ss/user/ntuser/cursoricon.c index 7ba56db0700..84d8c76b4e3 100644 --- a/win32ss/user/ntuser/cursoricon.c +++ b/win32ss/user/ntuser/cursoricon.c @@ -204,7 +204,7 @@ IntFindExistingCurIconObject(HMODULE hModule, } PCURICON_OBJECT -IntCreateCurIconHandle() +IntCreateCurIconHandle(DWORD dwNumber) { PCURICON_OBJECT CurIcon; HANDLE hCurIcon; @@ -613,8 +613,8 @@ NtUserClipCursor( BOOL APIENTRY NtUserDestroyCursor( - HANDLE hCurIcon, - DWORD Unknown) + _In_ HANDLE hCurIcon, + _In_ BOOL bForce) { PCURICON_OBJECT CurIcon; BOOL ret; diff --git a/win32ss/user/ntuser/cursoricon.h b/win32ss/user/ntuser/cursoricon.h index 3bf5e19c4be..842392d890f 100644 --- a/win32ss/user/ntuser/cursoricon.h +++ b/win32ss/user/ntuser/cursoricon.h @@ -22,8 +22,8 @@ typedef struct _CURICON_OBJECT LIST_ENTRY ListEntry; HANDLE Self; LIST_ENTRY ProcessList; - HMODULE hModule; - HRSRC hRsrc; + UNICODE_STRING ustrModule; + UNICODE_STRING ustrRsrc; SIZE Size; BYTE Shadow; BOOL bIcon; @@ -88,7 +88,7 @@ typedef struct _SYSTEM_CURSORINFO } SYSTEM_CURSORINFO, *PSYSTEM_CURSORINFO; BOOL InitCursorImpl(VOID); -PCURICON_OBJECT IntCreateCurIconHandle(VOID); +PCURICON_OBJECT IntCreateCurIconHandle(DWORD dwNumber); VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process); BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth, diff --git a/win32ss/user/ntuser/cursoricon_new.c b/win32ss/user/ntuser/cursoricon_new.c index 0c772a2155d..e5d25ba4a05 100644 --- a/win32ss/user/ntuser/cursoricon_new.c +++ b/win32ss/user/ntuser/cursoricon_new.c @@ -169,47 +169,61 @@ ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon) return TRUE; } -PCURICON_OBJECT FASTCALL -IntFindExistingCurIconObject(HMODULE hModule, - HRSRC hRsrc, LONG cx, LONG cy) +static +PCURICON_OBJECT +FASTCALL +IntFindExistingCurIconObject( + PUNICODE_STRING pustrModule, + PUNICODE_STRING pustrRsrc, + FINDEXISTINGCURICONPARAM* param) { PCURICON_OBJECT CurIcon; LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry) { - - // if (NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) // <- huh???? -// UserReferenceObject( CurIcon); -// { - if ((CurIcon->hModule == hModule) && (CurIcon->hRsrc == hRsrc)) + /* See if we are looking for an icon or a cursor */ + if(CurIcon->bIcon != param->bIcon) + continue; + /* See if module names match */ + if(RtlCompareUnicodeString(pustrModule, &CurIcon->ustrModule, TRUE) == 0) { - if (cx && ((cx != CurIcon->Size.cx) || (cy != CurIcon->Size.cy))) + /* They do. Now see if this is the same resource */ + if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer) && IS_INTRESOURCE(pustrRsrc->Buffer)) { -// UserDereferenceObject(CurIcon); + if(CurIcon->ustrRsrc.Buffer != pustrRsrc->Buffer) + continue; + } + else if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer) || IS_INTRESOURCE(pustrRsrc->Buffer)) continue; - } - if (! ReferenceCurIconByProcess(CurIcon)) + else if(RtlCompareUnicodeString(pustrRsrc, &CurIcon->ustrRsrc, TRUE) != 0) + continue; + + if ((param->cx == CurIcon->Size.cx) &&(param->cy == CurIcon->Size.cy)) { - return NULL; + if (! ReferenceCurIconByProcess(CurIcon)) + { + return NULL; + } + + return CurIcon; } - - return CurIcon; } -// } -// UserDereferenceObject(CurIcon); - } return NULL; } PCURICON_OBJECT -IntCreateCurIconHandle() +IntCreateCurIconHandle(DWORD dwNumber) { PCURICON_OBJECT CurIcon; + BOOLEAN bIcon = dwNumber == 0; HANDLE hCurIcon; + + if(dwNumber == 0) + dwNumber = 1; - CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT)); + CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, FIELD_OFFSET(CURICON_OBJECT, aFrame[dwNumber])); if (!CurIcon) { @@ -218,6 +232,7 @@ IntCreateCurIconHandle() } CurIcon->Self = hCurIcon; + CurIcon->bIcon = bIcon; InitializeListHead(&CurIcon->ProcessList); if (! ReferenceCurIconByProcess(CurIcon)) @@ -234,7 +249,7 @@ IntCreateCurIconHandle() } BOOLEAN FASTCALL -IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi) +IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi, BOOLEAN bForce) { PSYSTEM_CURSORINFO CurInfo; HBITMAP bmpMask, bmpColor, bmpAlpha; @@ -261,8 +276,18 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi) { /* This object doesn't belong to this process */ EngSetLastError(ERROR_INVALID_HANDLE); + /* Caller expects us to dereference! */ + UserDereferenceObject(CurIcon); return FALSE; } + + /* We found our process, but we're told to not destroy it in case it is shared */ + if((CurIcon->ustrModule.Buffer != NULL) && !bForce) + { + /* Tests show this is a valid call */ + UserDereferenceObject(CurIcon); + return TRUE; + } ExFreeToPagedLookasideList(pgProcessLookasideList, Current); @@ -314,6 +339,11 @@ emptyList: GreDeleteObject(bmpAlpha); CurIcon->aFrame[0].hbmAlpha = NULL; } + + if(!IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer)) + ExFreePoolWithTag(CurIcon->ustrRsrc.Buffer, TAG_STRING); + if(CurIcon->ustrModule.Buffer) + ReleaseCapturedUnicodeString(&CurIcon->ustrModule, UserMode); /* We were given a pointer, no need to keep the reference anylonger! */ UserDereferenceObject(CurIcon); @@ -331,7 +361,7 @@ IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process) LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry) { UserReferenceObject(CurIcon); - IntDestroyCurIconObject(CurIcon, Win32Process); + IntDestroyCurIconObject(CurIcon, Win32Process, TRUE); } } @@ -342,12 +372,12 @@ IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process) BOOL APIENTRY NtUserGetIconInfo( - HANDLE hCurIcon, - PICONINFO IconInfo, - PUNICODE_STRING lpInstName, // Optional - PUNICODE_STRING lpResName, // Optional - LPDWORD pbpp, // Optional - BOOL bInternal) + _In_ HANDLE hCurIcon, + _Out_opt_ PICONINFO IconInfo, + _Out_opt_ PUNICODE_STRING lpModule, // Optional + _Out_opt_ PUNICODE_STRING lpResName, // Optional + _Out_opt_ LPDWORD pbpp, // Optional + _In_ BOOL bInternal) { ICONINFO ii; PCURICON_OBJECT CurIcon; @@ -356,66 +386,145 @@ NtUserGetIconInfo( DWORD colorBpp = 0; TRACE("Enter NtUserGetIconInfo\n"); - UserEnterExclusive(); - if (!IconInfo) + /* Check if something was actually asked */ + if (!IconInfo && !lpModule && !lpResName) { + WARN("Nothing to fill.\n"); EngSetLastError(ERROR_INVALID_PARAMETER); - goto leave; + return FALSE; } + + UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(hCurIcon))) { - goto leave; + WARN("UserGetIconObject(0x%08x) Failed.\n", hCurIcon); + UserLeave(); + return FALSE; } - /* Fill data */ - ii.fIcon = CurIcon->bIcon; - ii.xHotspot = CurIcon->ptlHotspot.x; - ii.yHotspot = CurIcon->ptlHotspot.y; - - /* Copy bitmaps */ - ii.hbmMask = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmMask); - ii.hbmColor = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmColor); - - if (pbpp) + /* Give back the icon information */ + if(IconInfo) { - PSURFACE psurfBmp; + /* Fill data */ + ii.fIcon = CurIcon->bIcon; + ii.xHotspot = CurIcon->ptlHotspot.x; + ii.yHotspot = CurIcon->ptlHotspot.y; - psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor); - if (psurfBmp) - { - colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat); - SURFACE_ShareUnlockSurface(psurfBmp); - } - } - - /* Copy fields */ - _SEH2_TRY - { - ProbeForWrite(IconInfo, sizeof(ICONINFO), 1); - RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO)); + /* Copy bitmaps */ + ii.hbmMask = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmMask); + GreSetObjectOwner(ii.hbmMask, GDI_OBJ_HMGR_POWNED); + ii.hbmColor = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmColor); + GreSetObjectOwner(ii.hbmColor, GDI_OBJ_HMGR_POWNED); if (pbpp) { - ProbeForWrite(pbpp, sizeof(DWORD), 1); - *pbpp = colorBpp; + PSURFACE psurfBmp; + + psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor); + if (psurfBmp) + { + colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat); + SURFACE_ShareUnlockSurface(psurfBmp); + } } + + /* Copy fields */ + _SEH2_TRY + { + ProbeForWrite(IconInfo, sizeof(ICONINFO), 1); + RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO)); + + if (pbpp) + { + ProbeForWrite(pbpp, sizeof(DWORD), 1); + *pbpp = colorBpp; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + + if (!NT_SUCCESS(Status)) { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END - - if (NT_SUCCESS(Status)) - Ret = TRUE; - else + WARN("Status: 0x%08x.\n", Status); SetLastNtError(Status); + goto leave; + } - UserDereferenceObject(CurIcon); + /* Give back the module name */ + if(lpModule) + { + if(!CurIcon->ustrModule.Buffer) + { + EngSetLastError(ERROR_INVALID_HANDLE); + goto leave; + } + /* Copy what we can */ + _SEH2_TRY + { + ProbeForWrite(lpModule, sizeof(UNICODE_STRING), 1); + ProbeForWrite(lpModule->Buffer, lpModule->MaximumLength, 1); + lpModule->Length = min(lpModule->MaximumLength, CurIcon->ustrModule.Length); + RtlCopyMemory(lpModule->Buffer, CurIcon->ustrModule.Buffer, lpModule->Length); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END + } + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + goto leave; + } + + if(lpResName) + { + if(!CurIcon->ustrRsrc.Buffer) + { + EngSetLastError(ERROR_INVALID_HANDLE); + goto leave; + } + /* Copy it */ + _SEH2_TRY + { + ProbeForWrite(lpResName, sizeof(UNICODE_STRING), 1); + if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer)) + { + lpResName->Buffer = CurIcon->ustrRsrc.Buffer; + lpResName->Length = 0; + } + else + { + lpResName->Length = min(lpResName->MaximumLength, CurIcon->ustrRsrc.Length); + RtlCopyMemory(lpResName->Buffer, CurIcon->ustrRsrc.Buffer, lpResName->Length); + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END + } + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + goto leave; + } + + Ret = TRUE; leave: + UserDereferenceObject(CurIcon); + TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret); UserLeave(); @@ -623,8 +732,8 @@ NtUserClipCursor( BOOL APIENTRY NtUserDestroyCursor( - HANDLE hCurIcon, - DWORD Unknown) + _In_ HANDLE hCurIcon, + _In_ BOOL bForce) { PCURICON_OBJECT CurIcon; BOOL ret; @@ -638,7 +747,7 @@ NtUserDestroyCursor( RETURN(FALSE); } - ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); + ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process(), bForce); /* Note: IntDestroyCurIconObject will remove our reference for us! */ RETURN(ret); @@ -654,36 +763,51 @@ CLEANUP: * @implemented */ HICON -APIENTRY +NTAPI NtUserFindExistingCursorIcon( - HMODULE hModule, - HRSRC hRsrc, - LONG cx, - LONG cy) + _In_ PUNICODE_STRING pustrModule, + _In_ PUNICODE_STRING pustrRsrc, + _In_ FINDEXISTINGCURICONPARAM* param) { PCURICON_OBJECT CurIcon; - HANDLE Ret = (HANDLE)0; - DECLARE_RETURN(HICON); + HICON Ret = NULL; + UNICODE_STRING ustrModuleSafe, ustrRsrcSafe; + FINDEXISTINGCURICONPARAM paramSafe; + NTSTATUS Status; TRACE("Enter NtUserFindExistingCursorIcon\n"); - UserEnterExclusive(); - - CurIcon = IntFindExistingCurIconObject(hModule, hRsrc, cx, cy); - if (CurIcon) + + /* Capture resource name (it can be an INTRESOURCE == ATOM) */ + Status = ProbeAndCaptureUnicodeStringOrAtom(&ustrRsrcSafe, pustrRsrc); + if(!NT_SUCCESS(Status)) + return NULL; + Status = ProbeAndCaptureUnicodeString(&ustrModuleSafe, UserMode, pustrModule); + if(!NT_SUCCESS(Status)) + goto done; + + _SEH2_TRY { - Ret = CurIcon->Self; - -// IntReleaseCurIconObject(CurIcon); // FIXME: Is this correct? Does IntFindExistingCurIconObject add a ref? - RETURN(Ret); + ProbeForRead(param, sizeof(*param), 1); + paramSafe = *param; } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END - EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); - RETURN((HANDLE)0); - -CLEANUP: - TRACE("Leave NtUserFindExistingCursorIcon, ret=%p\n",_ret_); + UserEnterExclusive(); + CurIcon = IntFindExistingCurIconObject(&ustrModuleSafe, &ustrRsrcSafe, ¶mSafe); + if (CurIcon) + Ret = CurIcon->Self; UserLeave(); - END_CLEANUP; + +done: + if(!IS_INTRESOURCE(ustrRsrcSafe.Buffer)) + ExFreePoolWithTag(ustrRsrcSafe.Buffer, TAG_STRING); + ReleaseCapturedUnicodeString(&ustrModuleSafe, UserMode); + + return Ret; } @@ -920,12 +1044,6 @@ NtUserSetCursorContents( done: - if(!Ret) - { - IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); - CurIcon = NULL; - } - if (CurIcon) { UserDereferenceObject(CurIcon); @@ -942,33 +1060,35 @@ CLEANUP: /* * @implemented */ -#ifdef NEW_CURSORICON BOOL APIENTRY NtUserSetCursorIconData( - _In_ HCURSOR Handle, - _In_ HINSTANCE hinst, - _In_ HRSRC hrsrc, - _In_ PICONINFO pIconInfo) + _In_ HCURSOR Handle, + _In_opt_ PUNICODE_STRING pustrModule, + _In_opt_ PUNICODE_STRING pustrRsrc, + _In_ PICONINFO pIconInfo) { PCURICON_OBJECT CurIcon; PSURFACE psurfBmp; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = FALSE; - DECLARE_RETURN(BOOL); ICONINFO ii; - + TRACE("Enter NtUserSetCursorIconData\n"); + + /* If a module name is provided, we need a resource name, and vice versa */ + if((pustrModule && !pustrRsrc) || (!pustrModule && pustrRsrc)) + return FALSE; + UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(Handle))) { - RETURN(FALSE); + UserLeave(); + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; } - CurIcon->hModule = hinst; - CurIcon->hRsrc =hrsrc; - _SEH2_TRY { ProbeForRead(pIconInfo, sizeof(ICONINFO), 1); @@ -1014,29 +1134,38 @@ NtUserSetCursorIconData( if (CurIcon->aFrame[0].hbmColor) { - if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor))) - { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; - SURFACE_ShareUnlockSurface(psurfBmp); - GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); - } - else + psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor); + if(!psurfBmp) goto done; + + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; + SURFACE_ShareUnlockSurface(psurfBmp); + GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_PUBLIC); } else { - if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask))) - { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy/2; - SURFACE_ShareUnlockSurface(psurfBmp); - } - else + psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask); + if(!psurfBmp) goto done; + + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy/2; + SURFACE_ShareUnlockSurface(psurfBmp); } GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); + if(pustrModule) + { + /* We use this convenient function, because INTRESOURCEs and ATOMs are the same */ + Status = ProbeAndCaptureUnicodeStringOrAtom(&CurIcon->ustrRsrc, pustrRsrc); + if(!NT_SUCCESS(Status)) + goto done; + Status = ProbeAndCaptureUnicodeString(&CurIcon->ustrModule, UserMode, pustrModule); + if(!NT_SUCCESS(Status)) + goto done; + } + Ret = TRUE; done: @@ -1055,97 +1184,17 @@ done: GreDeleteObject(CurIcon->aFrame[0].hbmColor); CurIcon->aFrame[0].hbmColor = NULL; } + if(!IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer)) + ExFreePoolWithTag(CurIcon->ustrRsrc.Buffer, TAG_STRING); + if(CurIcon->ustrModule.Buffer) + ReleaseCapturedUnicodeString(&CurIcon->ustrModule, UserMode); } - RETURN(Ret); -CLEANUP: - TRACE("Leave NtUserSetCursorIconData, ret=%i\n",_ret_); + TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret); UserLeave(); - END_CLEANUP; + + return Ret; } -#else -BOOL -APIENTRY -NtUserSetCursorIconData( - HANDLE hCurIcon, - PBOOL fIcon, - POINT *Hotspot, - HMODULE hModule, - HRSRC hRsrc, - HRSRC hGroupRsrc) -{ - PCURICON_OBJECT CurIcon; - NTSTATUS Status; - BOOL Ret = FALSE; - DECLARE_RETURN(BOOL); - - TRACE("Enter NtUserSetCursorIconData\n"); - UserEnterExclusive(); - - if (!(CurIcon = UserGetCurIconObject(hCurIcon))) - { - RETURN(FALSE); - } - - CurIcon->hModule = hModule; - CurIcon->hRsrc = hRsrc; - CurIcon->hGroupRsrc = hGroupRsrc; - - /* Copy fields */ - if (fIcon) - { - Status = MmCopyFromCaller(&CurIcon->bIcon, fIcon, sizeof(BOOL)); - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - goto done; - } - } - else - { - if (!Hotspot) - Ret = TRUE; - } - - if (Hotspot) - { - Status = MmCopyFromCaller(&CurIcon->ptlHotspot, Hotspot, sizeof(POINT)); - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - goto done; - } - } - - if (!fIcon && !Hotspot) - { - Ret = TRUE; - } - -done: - if(Ret) - { - /* This icon is shared now */ - GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); - if(CurIcon->aFrame[0].hbmColor) - { - GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_PUBLIC); - } - if(CurIcon->aFrame[0].hbmAlpha) - { - GreSetObjectOwner(CurIcon->aFrame[0].hbmAlpha, GDI_OBJ_HMGR_PUBLIC); - } - } - UserDereferenceObject(CurIcon); - RETURN(Ret); - - -CLEANUP: - TRACE("Leave NtUserSetCursorIconData, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} -#endif /* Mostly inspired from wine code. * We use low level functions because: @@ -1167,7 +1216,7 @@ UserDrawIconEx( HBRUSH hbrFlickerFreeDraw, UINT diFlags) { - PSURFACE psurfDest, psurfMask, psurfColor, psurfOffScreen; + PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL; PDC pdc = NULL; BOOL Ret = FALSE; HBITMAP hbmMask, hbmColor, hbmAlpha; @@ -1215,6 +1264,35 @@ UserDrawIconEx( return FALSE; } + pdc = DC_LockDc(hDc); + if(!pdc) + { + ERR("Could not lock the destination DC.\n"); + SURFACE_ShareUnlockSurface(psurfMask); + if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + return FALSE; + } + /* Calculate destination rectangle */ + RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); + IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); + RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); + + /* Prepare the underlying surface */ + DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); + + /* We now have our destination surface and rectangle */ + psurfDest = pdc->dclevel.pSurface; + + if(psurfDest == NULL) + { + /* Empty DC */ + DC_vFinishBlit(pdc, NULL); + DC_UnlockDc(pdc); + SURFACE_ShareUnlockSurface(psurfMask); + if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + return FALSE; + } + /* Set source rect */ RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy); @@ -1239,7 +1317,8 @@ UserDrawIconEx( } /* Should we render off-screen? */ - bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH); + bOffScreen = hbrFlickerFreeDraw && + (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH); if (bOffScreen) { @@ -1252,21 +1331,18 @@ UserDrawIconEx( if(!pbrush) { ERR("Failed to get brush object.\n"); - SURFACE_ShareUnlockSurface(psurfMask); - if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); - return FALSE; + goto Cleanup; } +#if 0 //We lock the hdc surface during the whole function it makes no sense to use an offscreen surface for "flicker free" drawing psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP, - cxWidth, cyHeight, psurfColor->SurfObj.iBitmapFormat, + cxWidth, cyHeight, psurfDest->SurfObj.iBitmapFormat, 0, 0, NULL); if(!psurfOffScreen) { ERR("Failed to allocate the off-screen surface.\n"); - SURFACE_ShareUnlockSurface(psurfMask); - if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); BRUSH_ShareUnlockBrush(pbrush); - return FALSE; + goto Cleanup; } /* Paint the brush */ @@ -1292,52 +1368,45 @@ UserDrawIconEx( if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); - SURFACE_ShareUnlockSurface(psurfMask); - if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); - GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); - return FALSE; + goto Cleanup; } /* We now have our destination surface */ psurfDest = psurfOffScreen; +#else + pdcClipObj = pdc->rosdc.CombinedClip; + /* Paint the brush */ + EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL); + + Ret = IntEngBitBlt(&psurfDest->SurfObj, + NULL, + NULL, + pdcClipObj, + NULL, + &rcDest, + NULL, + NULL, + &eboFill.BrushObject, + &pbrush->ptOrigin, + ROP4_PATCOPY); + + /* Clean up everything */ + EBRUSHOBJ_vCleanup(&eboFill); + BRUSH_ShareUnlockBrush(pbrush); + + if(!Ret) + { + ERR("Failed to paint the off-screen surface.\n"); + goto Cleanup; + } +#endif } else { /* We directly draw to the DC */ TRACE("Performing on screen rendering.\n"); - - psurfOffScreen = NULL; - pdc = DC_LockDc(hDc); - if(!pdc) - { - ERR("Could not lock the destination DC.\n"); - SURFACE_ShareUnlockSurface(psurfMask); - if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); - return FALSE; - } - /* Calculate destination rectangle */ - RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); - IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); - RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); - - /* Prepare the underlying surface */ - DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); - - /* Get the clip object */ pdcClipObj = pdc->rosdc.CombinedClip; - - /* We now have our destination surface and rectangle */ - psurfDest = pdc->dclevel.pSurface; - - if(psurfDest == NULL) - { - /* Empty DC */ - DC_vFinishBlit(pdc, NULL); - DC_UnlockDc(pdc); - SURFACE_ShareUnlockSurface(psurfMask); - if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); - return FALSE; - } + // psurfOffScreen = NULL; } /* Now do the rendering */ @@ -1460,36 +1529,23 @@ NoAlpha: } done: +#if 0 /* We're done. Was it a double buffered draw ? */ if(bOffScreen) { /* Yes. Draw it back to our DC */ POINTL ptSrc = {0, 0}; - pdc = DC_LockDc(hDc); - if(!pdc) - { - ERR("Could not lock the destination DC.\n"); - return FALSE; - } + /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); - /* Prepare the underlying surface */ - DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); - /* Get the clip object */ pdcClipObj = pdc->rosdc.CombinedClip; /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; - if(!psurfDest) - { - /* So, you did all of this for an empty DC. */ - DC_UnlockDc(pdc); - goto Cleanup2; - } /* Color translation */ EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); @@ -1509,18 +1565,20 @@ done: EXLATEOBJ_vCleanup(&exlo); } +#endif Cleanup: if(pdc) { DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); } - -Cleanup2: + +#if 0 /* Delete off screen rendering surface */ if(psurfOffScreen) GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); - +#endif + /* Unlock other surfaces */ SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); @@ -1554,7 +1612,7 @@ NtUserDrawIconEx( if (!(pIcon = UserGetCurIconObject(hIcon))) { - ERR("UserGetCurIconObject() failed!\n"); + ERR("UserGetCurIconObject(0x%08x) failed!\n", hIcon); UserLeave(); return FALSE; } diff --git a/win32ss/user/ntuser/simplecall.c b/win32ss/user/ntuser/simplecall.c index cc0e6a9eed9..3b65d98f358 100644 --- a/win32ss/user/ntuser/simplecall.c +++ b/win32ss/user/ntuser/simplecall.c @@ -236,7 +236,7 @@ NtUserCallOneParam( PCURICON_OBJECT CurIcon; DWORD_PTR Result ; - if (!(CurIcon = IntCreateCurIconHandle())) + if (!(CurIcon = IntCreateCurIconHandle((DWORD)Param))) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); RETURN(0); diff --git a/win32ss/user/user32/CMakeLists.txt b/win32ss/user/user32/CMakeLists.txt index 8c5930d14a9..d7bfe869d73 100644 --- a/win32ss/user/user32/CMakeLists.txt +++ b/win32ss/user/user32/CMakeLists.txt @@ -71,7 +71,10 @@ else() endif() add_library(user32 SHARED ${SOURCE}) -set_module_type(user32 win32dll UNICODE) +set_module_type(user32 + win32dll + ENTRYPOINT DllMain 12 + UNICODE) target_link_libraries(user32 user32_wsprintf @@ -79,8 +82,13 @@ target_link_libraries(user32 win32ksys ${PSEH_LIB}) +if(MSVC) + # for __ftol2_sse, float to int cast helper + target_link_libraries(user32 msvcrtex) +endif() + add_delay_importlibs(user32 imm32 usp10) -add_importlibs(user32 gdi32 advapi32 msvcrt kernel32 ntdll) +add_importlibs(user32 gdi32 advapi32 kernel32 ntdll) add_pch(user32 include/user32.h) add_cd_file(TARGET user32 DESTINATION reactos/system32 FOR all) diff --git a/win32ss/user/user32/controls/edit.c b/win32ss/user/user32/controls/edit.c index 511f049788f..a70c4fdeb13 100644 --- a/win32ss/user/user32/controls/edit.c +++ b/win32ss/user/user32/controls/edit.c @@ -400,7 +400,7 @@ static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData_linedef(EDITSTATE *es, HD tabdef.pTabStops = es->tabs; tabdef.iTabOrigin = 0; - ScriptStringAnalyse(udc, &es->text[index], line_def->net_length, (1.5*line_def->net_length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_TAB, -1, NULL, NULL, NULL, &tabdef, NULL, &line_def->ssa); + ScriptStringAnalyse(udc, &es->text[index], line_def->net_length, (3*line_def->net_length/2+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_TAB, -1, NULL, NULL, NULL, &tabdef, NULL, &line_def->ssa); if (es->font) SelectObject(udc, old_font); @@ -435,9 +435,9 @@ static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData(EDITSTATE *es, HDC dc, IN old_font = SelectObject(udc, es->font); if (es->style & ES_PASSWORD) - ScriptStringAnalyse(udc, &es->password_char, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_PASSWORD, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa); + ScriptStringAnalyse(udc, &es->password_char, length, (3*length/2+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_PASSWORD, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa); else - ScriptStringAnalyse(udc, es->text, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa); + ScriptStringAnalyse(udc, es->text, length, (3*length/2+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa); if (es->font) SelectObject(udc, old_font); diff --git a/win32ss/user/user32/windows/cursoricon_new.c b/win32ss/user/user32/windows/cursoricon_new.c index d1276192ad6..3635dbcdbe6 100644 --- a/win32ss/user/user32/windows/cursoricon_new.c +++ b/win32ss/user/user32/windows/cursoricon_new.c @@ -11,7 +11,7 @@ #include WINE_DEFAULT_DEBUG_CHANNEL(cursor); -//WINE_DECLARE_DEBUG_CHANNEL(icon); +WINE_DECLARE_DEBUG_CHANNEL(icon); //WINE_DECLARE_DEBUG_CHANNEL(resource); /************* USER32 INTERNAL FUNCTIONS **********/ @@ -55,6 +55,30 @@ HCURSOR CursorIconToCursor(HICON hIcon, BOOL SemiTransparent) /************* IMPLEMENTATION HELPERS ******************/ +static const WCHAR DISPLAYW[] = L"DISPLAY"; + +static void *map_fileW( LPCWSTR name, LPDWORD filesize ) +{ + HANDLE hFile, hMapping; + LPVOID ptr = NULL; + + hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 ); + if (hFile != INVALID_HANDLE_VALUE) + { + hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); + if (hMapping) + { + ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 ); + CloseHandle( hMapping ); + if (filesize) + *filesize = GetFileSize( hFile, NULL ); + } + CloseHandle( hFile ); + } + return ptr; +} + static int get_dib_image_size( int width, int height, int depth ) { return (((width * depth + 31) / 8) & ~3) * abs( height ); @@ -121,6 +145,32 @@ static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) } } +static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width, + LONG *height, WORD *bpp, DWORD *compr ) +{ + if (header->biSize == sizeof(BITMAPCOREHEADER)) + { + const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header; + *width = core->bcWidth; + *height = core->bcHeight; + *bpp = core->bcBitCount; + *compr = 0; + return 0; + } + else if (header->biSize == sizeof(BITMAPINFOHEADER) || + header->biSize == sizeof(BITMAPV4HEADER) || + header->biSize == sizeof(BITMAPV5HEADER)) + { + *width = header->biWidth; + *height = header->biHeight; + *bpp = header->biBitCount; + *compr = header->biCompression; + return 1; + } + ERR("(%d): unknown/wrong size for header\n", header->biSize ); + return -1; +} + /************* IMPLEMENTATION CORE ****************/ static BOOL CURSORICON_GetIconInfoFromBMI( @@ -132,28 +182,35 @@ static BOOL CURSORICON_GetIconInfoFromBMI( { UINT ubmiSize = bitmap_info_size(pbmi, DIB_RGB_COLORS); BOOL monochrome = is_dib_monochrome(pbmi); + LONG width, height; + WORD bpp; + DWORD compr; + int ibmpType; HDC hdc, hdcScreen; BITMAPINFO* pbmiCopy; HBITMAP hbmpOld = NULL; BOOL bResult = FALSE; const VOID *pvColor, *pvMask; - /* Check for invalid data */ - if ( (pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER) && - pbmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) || - pbmi->bmiHeader.biCompression != BI_RGB ) - { - WARN("Invalid resource bitmap header.\n"); - return FALSE; - } + ibmpType = DIB_GetBitmapInfo(&pbmi->bmiHeader, &width, &height, &bpp, &compr); + /* Invalid data */ + if(ibmpType < 0) + return FALSE; + + /* No compression for icons */ + if(compr != BI_RGB) + return FALSE; /* Fix the hotspot coords */ - if(cxDesired != pbmi->bmiHeader.biWidth) - pii->xHotspot = (pii->xHotspot * cxDesired) / pbmi->bmiHeader.biWidth; - if(cxDesired != (pbmi->bmiHeader.biHeight/2)) - pii->yHotspot = (pii->yHotspot * cyDesired * 2) / pbmi->bmiHeader.biHeight; + if(!pii->fIcon) + { + if(cxDesired != pbmi->bmiHeader.biWidth) + pii->xHotspot = (pii->xHotspot * cxDesired) / pbmi->bmiHeader.biWidth; + if(cxDesired != (pbmi->bmiHeader.biHeight/2)) + pii->yHotspot = (pii->yHotspot * cyDesired * 2) / pbmi->bmiHeader.biHeight; + } - hdcScreen = CreateDCW(L"DISPLAY", NULL, NULL, NULL); + hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL); if(!hdcScreen) return FALSE; hdc = CreateCompatibleDC(hdcScreen); @@ -167,8 +224,13 @@ static BOOL CURSORICON_GetIconInfoFromBMI( if(!pbmiCopy) goto done; RtlCopyMemory(pbmiCopy, pbmi, ubmiSize); - pbmiCopy->bmiHeader.biHeight /= 2; + /* In an icon/cursor, the BITMAPINFO holds twice the height */ + if(pbmiCopy->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + ((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcHeight /= 2; + else + pbmiCopy->bmiHeader.biHeight /= 2; + pvColor = (const char*)pbmi + ubmiSize; pvMask = (const char*)pvColor + get_dib_image_size(pbmi->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight, pbmi->bmiHeader.biBitCount ); @@ -250,7 +312,7 @@ done: } static -HANDLE +HBITMAP BITMAP_LoadImageW( _In_opt_ HINSTANCE hinst, _In_ LPCWSTR lpszName, @@ -259,8 +321,400 @@ BITMAP_LoadImageW( _In_ UINT fuLoad ) { - UNIMPLEMENTED; - return NULL; + const BITMAPINFO* pbmi; + BITMAPINFO* pbmiScaled = NULL; + BITMAPINFO* pbmiCopy = NULL; + const VOID* pvMapping; + DWORD dwOffset = 0; + HGLOBAL hgRsrc; + int iBMISize; + PVOID pvBits; + HDC hdcScreen = NULL; + HDC hdc = NULL; + HBITMAP hbmpRet, hbmpOld; + + /* Map the bitmap info */ + if(fuLoad & LR_LOADFROMFILE) + { + const BITMAPFILEHEADER* pbmfh; + + pvMapping = map_fileW(lpszName, NULL); + if(!pvMapping) + return NULL; + pbmfh = pvMapping; + if (pbmfh->bfType != 0x4d42 /* 'BM' */) + { + WARN("Invalid/unsupported bitmap format!\n"); + goto end; + } + pbmi = (const BITMAPINFO*)(pbmfh + 1); + + /* Get the image bits */ + if(pbmfh->bfOffBits) + dwOffset = pbmfh->bfOffBits - sizeof(BITMAPFILEHEADER); + } + else + { + HRSRC hrsrc; + + /* Caller wants an OEM bitmap */ + if(!hinst) + hinst = User32Instance; + hrsrc = FindResourceW(hinst, lpszName, (LPWSTR)RT_BITMAP); + if(!hrsrc) + return NULL; + hgRsrc = LoadResource(hinst, hrsrc); + if(!hgRsrc) + return NULL; + pbmi = LockResource(hgRsrc); + if(!pbmi) + return NULL; + } + + /* See if we must scale the bitmap */ + iBMISize = bitmap_info_size(pbmi, DIB_RGB_COLORS); + + /* Get a pointer to the image data */ + pvBits = (char*)pbmi + (dwOffset ? dwOffset : iBMISize); + + /* Create a copy of the info describing the bitmap in the file */ + pbmiCopy = HeapAlloc(GetProcessHeap(), 0, iBMISize); + if(!pbmiCopy) + goto end; + CopyMemory(pbmiCopy, pbmi, iBMISize); + + /* Fix it up, if needed */ + if(fuLoad & (LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS)) + { + WORD bpp, incr, numColors; + char* pbmiColors; + RGBTRIPLE* ptr; + COLORREF crWindow, cr3DShadow, cr3DFace, cr3DLight; + BYTE pixel = *((BYTE*)pvBits); + UINT i; + + if(pbmiCopy->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + bpp = ((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcBitCount; + numColors = 1 << bpp; + /* BITMAPCOREINFO holds RGBTRIPLEs */ + incr = 3; + } + else + { + bpp = pbmiCopy->bmiHeader.biBitCount; + /* BITMAPINFOHEADER holds RGBQUADs */ + incr = 4; + numColors = pbmiCopy->bmiHeader.biClrUsed; + if(numColors > 256) numColors = 256; + if (!numColors && (bpp <= 8)) numColors = 1 << bpp; + } + + if(bpp > 8) + goto create_bitmap; + + pbmiColors = (char*)pbmiCopy + pbmiCopy->bmiHeader.biSize; + + /* Get the relevant colors */ + crWindow = GetSysColor(COLOR_WINDOW); + cr3DShadow = GetSysColor(COLOR_3DSHADOW); + cr3DFace = GetSysColor(COLOR_3DFACE); + cr3DLight = GetSysColor(COLOR_3DLIGHT); + + /* Fix the transparent palette entry */ + if(fuLoad & LR_LOADTRANSPARENT) + { + switch(bpp) + { + case 1: pixel >>= 7; break; + case 4: pixel >>= 4; break; + case 8: break; + default: + FIXME("Unhandled bit depth %d.\n", bpp); + goto create_bitmap; + } + + if(pixel >= numColors) + { + ERR("Wrong pixel passed in.\n"); + goto create_bitmap; + } + + /* If both flags are set, we must use COLOR_3DFACE */ + if(fuLoad & LR_LOADMAP3DCOLORS) crWindow = cr3DFace; + + /* Define the color */ + ptr = (RGBTRIPLE*)(pbmiColors + pixel*incr); + ptr->rgbtBlue = GetBValue(crWindow); + ptr->rgbtGreen = GetGValue(crWindow); + ptr->rgbtRed = GetRValue(crWindow); + goto create_bitmap; + } + + /* If we are here, then LR_LOADMAP3DCOLORS is set without LR_TRANSPARENT */ + for(i = 0; irgbtBlue == ptr->rgbtRed) && (ptr->rgbtBlue == ptr->rgbtGreen)) + { + if(ptr->rgbtBlue == 128) + { + ptr->rgbtBlue = GetBValue(cr3DShadow); + ptr->rgbtGreen = GetGValue(cr3DShadow); + ptr->rgbtRed = GetRValue(cr3DShadow); + } + if(ptr->rgbtBlue == 192) + { + ptr->rgbtBlue = GetBValue(cr3DFace); + ptr->rgbtGreen = GetGValue(cr3DFace); + ptr->rgbtRed = GetRValue(cr3DFace); + } + if(ptr->rgbtBlue == 223) + { + ptr->rgbtBlue = GetBValue(cr3DLight); + ptr->rgbtGreen = GetGValue(cr3DLight); + ptr->rgbtRed = GetRValue(cr3DLight); + } + } + } + } + +create_bitmap: + if(fuLoad & LR_CREATEDIBSECTION) + { + /* Allocate the BMI describing the new bitmap */ + pbmiScaled = HeapAlloc(GetProcessHeap(), 0, iBMISize); + if(!pbmiScaled) + goto end; + CopyMemory(pbmiScaled, pbmiCopy, iBMISize); + + /* Fix it up */ + if(pbmiScaled->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + BITMAPCOREHEADER* pbmch = (BITMAPCOREHEADER*)&pbmiScaled->bmiHeader; + if(cxDesired == 0) + cxDesired = pbmch->bcWidth; + if(cyDesired == 0) + cyDesired == pbmch->bcHeight; + else if(pbmch->bcHeight < 0) + cyDesired = -cyDesired; + + pbmch->bcWidth = cxDesired; + pbmch->bcHeight = cyDesired; + } + else + { + if ((pbmi->bmiHeader.biHeight > 65535) || (pbmi->bmiHeader.biWidth > 65535)) { + WARN("Broken BITMAPINFO!\n"); + goto end; + } + + if(cxDesired == 0) + cxDesired = pbmi->bmiHeader.biWidth; + if(cyDesired == 0) + cyDesired = pbmi->bmiHeader.biHeight; + else if(pbmi->bmiHeader.biHeight < 0) + cyDesired = -cyDesired; + + pbmiScaled->bmiHeader.biWidth = cxDesired; + pbmiScaled->bmiHeader.biHeight = cyDesired; + /* No compression for DIB sections */ + if(fuLoad & LR_CREATEDIBSECTION) + pbmiScaled->bmiHeader.biCompression = BI_RGB; + } + } + + /* Top-down image */ + if(cyDesired < 0) cyDesired = -cyDesired; + + /* We need a device context */ + hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL); + if(!hdcScreen) + goto end; + hdc = CreateCompatibleDC(hdcScreen); + if(!hdc) + goto end; + + /* Now create the bitmap */ + if(fuLoad & LR_CREATEDIBSECTION) + hbmpRet = CreateDIBSection(hdc, pbmiScaled, DIB_RGB_COLORS, NULL, 0, 0); + else + { + if(is_dib_monochrome(pbmiCopy) || (fuLoad & LR_MONOCHROME)) + hbmpRet = CreateBitmap(cxDesired, cyDesired, 1, 1, NULL); + else + hbmpRet = CreateCompatibleBitmap(hdcScreen, cxDesired, cyDesired); + } + + if(!hbmpRet) + goto end; + + hbmpOld = SelectObject(hdc, hbmpRet); + if(!hbmpOld) + goto end; + if(!StretchDIBits(hdc, 0, 0, cxDesired, cyDesired, + 0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biWidth, + pvBits, pbmiCopy, DIB_RGB_COLORS, SRCCOPY)) + { + ERR("StretchDIBits failed!.\n"); + SelectObject(hdc, hbmpOld); + DeleteObject(hbmpRet); + hbmpRet = NULL; + goto end; + } + + SelectObject(hdc, hbmpOld); + +end: + if(hdcScreen) + DeleteDC(hdcScreen); + if(hdc) + DeleteDC(hdc); + if(pbmiScaled) + HeapFree(GetProcessHeap(), 0, pbmiScaled); + if(pbmiCopy) + HeapFree(GetProcessHeap(), 0, pbmiCopy); + if (fuLoad & LR_LOADFROMFILE) + UnmapViewOfFile( pvMapping ); + else + FreeResource(hgRsrc); + + return hbmpRet; +} + +#include "pshpack1.h" + +typedef struct { + BYTE bWidth; + BYTE bHeight; + BYTE bColorCount; + BYTE bReserved; + WORD xHotspot; + WORD yHotspot; + DWORD dwDIBSize; + DWORD dwDIBOffset; +} CURSORICONFILEDIRENTRY; + +typedef struct +{ + WORD idReserved; + WORD idType; + WORD idCount; + CURSORICONFILEDIRENTRY idEntries[1]; +} CURSORICONFILEDIR; + +#include "poppack.h" + +static +HANDLE +CURSORICON_LoadFromFileW( + _In_ LPCWSTR lpszName, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT fuLoad, + _In_ BOOL bIcon +) +{ + CURSORICONDIR* fakeDir; + CURSORICONDIRENTRY* fakeEntry; + CURSORICONFILEDIRENTRY *entry; + CURSORICONFILEDIR *dir; + DWORD filesize = 0; + LPBYTE bits; + HANDLE hRet = NULL; + WORD i; + ICONINFO ii; + + TRACE("loading %s\n", debugstr_w( lpszName )); + + bits = map_fileW( lpszName, &filesize ); + if (!bits) + return NULL; + + /* Check for .ani. */ + if (memcmp( bits, "RIFF", 4 ) == 0) + { + UNIMPLEMENTED; + goto end; + } + + dir = (CURSORICONFILEDIR*) bits; + if ( filesize < sizeof(*dir) ) + goto end; + + if ( filesize < (sizeof(*dir) + sizeof(dir->idEntries[0])*(dir->idCount-1)) ) + goto end; + + /* + * Cute little hack: + * We allocate a buffer, fake it as if it was a pointer to a resource in a module, + * pass it to LookupIconIdFromDirectoryEx and get back the index we have to use + */ + fakeDir = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(CURSORICONDIR, idEntries[dir->idCount])); + if(!fakeDir) + goto end; + fakeDir->idReserved = 0; + fakeDir->idType = dir->idType; + fakeDir->idCount = dir->idCount; + for(i = 0; iidCount; i++) + { + fakeEntry = &fakeDir->idEntries[i]; + entry = &dir->idEntries[i]; + /* Take this as an occasion to perform a size check */ + if((entry->dwDIBOffset + entry->dwDIBSize) > filesize) + goto end; + /* File icon/cursors are not like resource ones */ + if(bIcon) + { + fakeEntry->ResInfo.icon.bWidth = entry->bWidth; + fakeEntry->ResInfo.icon.bHeight = entry->bHeight; + fakeEntry->ResInfo.icon.bColorCount = 0; + fakeEntry->ResInfo.icon.bReserved = 0; + } + else + { + fakeEntry->ResInfo.cursor.wWidth = entry->bWidth; + fakeEntry->ResInfo.cursor.wHeight = entry->bHeight; + } + /* Let's assume there's always one plane */ + fakeEntry->wPlanes = 1; + /* We must get the bitcount from the BITMAPINFOHEADER itself */ + fakeEntry->wBitCount = ((BITMAPINFOHEADER *)((char *)dir + entry->dwDIBOffset))->biBitCount; + fakeEntry->dwBytesInRes = entry->dwDIBSize; + fakeEntry->wResId = i + 1; + } + + /* Now call LookupIconIdFromResourceEx */ + i = LookupIconIdFromDirectoryEx((PBYTE)fakeDir, bIcon, cxDesired, cyDesired, fuLoad & LR_MONOCHROME); + /* We don't need this anymore */ + HeapFree(GetProcessHeap(), 0, fakeDir); + if(i == 0) + { + WARN("Unable to get a fit entry index.\n"); + goto end; + } + + /* Get our entry */ + entry = &dir->idEntries[i-1]; + /* A bit of preparation */ + ii.xHotspot = entry->xHotspot; + ii.yHotspot = entry->yHotspot; + ii.fIcon = bIcon; + + /* Do the dance */ + if(!CURSORICON_GetIconInfoFromBMI(&ii, (BITMAPINFO*)&bits[entry->dwDIBOffset], cxDesired, cyDesired)) + goto end; + + /* Create the icon. NOTE: there's no LR_SHARED icons if they are created from file */ + hRet = CreateIconIndirect(&ii); + + /* Clean up */ + DeleteObject(ii.hbmMask); + DeleteObject(ii.hbmColor); + +end: + UnmapViewOfFile(bits); + return hRet; } static @@ -274,33 +728,15 @@ CURSORICON_LoadImageW( _In_ BOOL bIcon ) { - HRSRC hrsrc, hrsrc2; - HANDLE handle, hCurIcon; + HRSRC hrsrc; + HANDLE handle, hCurIcon = NULL; CURSORICONDIR* dir; WORD wResId; LPBYTE bits; ICONINFO ii; BOOL bStatus; - - if(fuLoad & LR_LOADFROMFILE) - { - UNIMPLEMENTED; - return NULL; - } - - /* Check if caller wants OEM icons */ - if(!hinst) - hinst = User32Instance; - - /* Find resource ID */ - hrsrc = FindResourceW( - hinst, - lpszName, - (LPWSTR)(bIcon ? RT_GROUP_ICON : RT_GROUP_CURSOR)); - - /* We let FindResource, LoadResource, etc. call SetLastError */ - if(!hrsrc) - return NULL; + UNICODE_STRING ustrRsrc; + UNICODE_STRING ustrModule = {0, 0, NULL}; /* Fix width/height */ if(fuLoad & LR_DEFAULTSIZE) @@ -309,48 +745,113 @@ CURSORICON_LoadImageW( if(!cyDesired) cyDesired = GetSystemMetrics(bIcon ? SM_CYICON : SM_CYCURSOR); } - /* If LR_SHARED is set, we must check for the cache */ - hCurIcon = NtUserFindExistingCursorIcon(hinst, hrsrc, cxDesired, cyDesired); - if(hCurIcon) - return hCurIcon; + if(fuLoad & LR_LOADFROMFILE) + { + return CURSORICON_LoadFromFileW(lpszName, cxDesired, cyDesired, fuLoad, bIcon); + } + + /* Check if caller wants OEM icons */ + if(!hinst) + hinst = User32Instance; + + if(fuLoad & LR_SHARED) + { + DWORD size = MAX_PATH; + FINDEXISTINGCURICONPARAM param; + + TRACE("Checking for an LR_SHARED cursor/icon.\n"); + /* Prepare the resource name string */ + if(IS_INTRESOURCE(lpszName)) + { + ustrRsrc.Buffer = (LPWSTR)lpszName; + ustrRsrc.Length = 0; + ustrRsrc.MaximumLength = 0; + } + else + RtlInitUnicodeString(&ustrRsrc, lpszName); + + /* Prepare the module name string */ + ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR)); + /* Get it */ + do + { + DWORD ret = GetModuleFileName(hinst, ustrModule.Buffer, size); + if(ret == 0) + { + HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); + return NULL; + } + if(ret < size) + { + ustrModule.Length = ret; + ustrModule.MaximumLength = size; + break; + } + size *= 2; + ustrModule.Buffer = HeapReAlloc(GetProcessHeap(), 0, ustrModule.Buffer, size*sizeof(WCHAR)); + } while(TRUE); + + /* Ask win32k */ + param.bIcon = bIcon; + param.cx = cxDesired; + param.cy = cyDesired; + hCurIcon = NtUserFindExistingCursorIcon(&ustrModule, &ustrRsrc, ¶m); + if(hCurIcon) + { + /* Woohoo, got it! */ + TRACE("MATCH!\n"); + HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); + return hCurIcon; + } + } + + /* Find resource ID */ + hrsrc = FindResourceW( + hinst, + lpszName, + (LPWSTR)(bIcon ? RT_GROUP_ICON : RT_GROUP_CURSOR)); + + /* We let FindResource, LoadResource, etc. call SetLastError */ + if(!hrsrc) + goto done; handle = LoadResource(hinst, hrsrc); if(!handle) - return NULL; + goto done; dir = LockResource(handle); - if(!dir) return NULL; + if(!dir) + goto done; - /* For now, take the first entry */ - wResId = dir->idEntries[0].wResId; + wResId = LookupIconIdFromDirectoryEx((PBYTE)dir, bIcon, cxDesired, cyDesired, fuLoad & LR_MONOCHROME); FreeResource(handle); /* Get the relevant resource pointer */ - hrsrc2 = FindResourceW( + hrsrc = FindResourceW( hinst, MAKEINTRESOURCEW(wResId), (LPWSTR)(bIcon ? RT_ICON : RT_CURSOR)); - if(!hrsrc2) - return NULL; + if(!hrsrc) + goto done; - handle = LoadResource(hinst, hrsrc2); + handle = LoadResource(hinst, hrsrc); if(!handle) - return NULL; + goto done; bits = LockResource(handle); if(!bits) { FreeResource(handle); - return NULL; + goto done; } - /* Get the hospot */ + /* Get the hotspot */ if(bIcon) { ii.xHotspot = cxDesired/2; ii.yHotspot = cyDesired/2; } - else + if(!bIcon) { SHORT* ptr = (SHORT*)bits; ii.xHotspot = ptr[0]; @@ -369,16 +870,20 @@ CURSORICON_LoadImageW( FreeResource( handle ); if(!bStatus) - return NULL; + goto done; /* Create the handle */ hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1); if(!hCurIcon) - return NULL; + { + DeleteObject(ii.hbmMask); + if(ii.hbmColor) DeleteObject(ii.hbmColor); + goto done; + } /* Tell win32k */ if(fuLoad & LR_SHARED) - bStatus = NtUserSetCursorIconData(hCurIcon, hinst, hrsrc, &ii); + bStatus = NtUserSetCursorIconData(hCurIcon, &ustrModule, &ustrRsrc, &ii); else bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &ii); @@ -389,11 +894,334 @@ CURSORICON_LoadImageW( } DeleteObject(ii.hbmMask); - DeleteObject(ii.hbmColor); - + if(ii.hbmColor) DeleteObject(ii.hbmColor); + +done: + if(ustrModule.Buffer) + HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); return hCurIcon; } +static +HBITMAP +BITMAP_CopyImage( + _In_ HBITMAP hbmp, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT fuFlags +) +{ + HBITMAP res = NULL; + DIBSECTION ds; + int objSize; + BITMAPINFO * bi; + + objSize = GetObjectW( hbmp, sizeof(ds), &ds ); + if (!objSize) return 0; + if ((cxDesired < 0) || (cyDesired < 0)) return 0; + + if (fuFlags & LR_COPYFROMRESOURCE) + { + FIXME("The flag LR_COPYFROMRESOURCE is not implemented for bitmaps\n"); + } + + if (fuFlags & LR_COPYRETURNORG) + { + FIXME("The flag LR_COPYRETURNORG is not implemented for bitmaps\n"); + } + + if (cxDesired == 0) cxDesired = ds.dsBm.bmWidth; + if (cyDesired == 0) cyDesired = ds.dsBm.bmHeight; + + /* Allocate memory for a BITMAPINFOHEADER structure and a + color table. The maximum number of colors in a color table + is 256 which corresponds to a bitmap with depth 8. + Bitmaps with higher depths don't have color tables. */ + bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + if (!bi) return 0; + + bi->bmiHeader.biSize = sizeof(bi->bmiHeader); + bi->bmiHeader.biPlanes = ds.dsBm.bmPlanes; + bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel; + bi->bmiHeader.biCompression = BI_RGB; + + if (fuFlags & LR_CREATEDIBSECTION) + { + /* Create a DIB section. LR_MONOCHROME is ignored */ + void * bits; + HDC dc = CreateCompatibleDC(NULL); + + if (objSize == sizeof(DIBSECTION)) + { + /* The source bitmap is a DIB. + Get its attributes to create an exact copy */ + memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER)); + } + + /* Get the color table or the color masks */ + GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + + bi->bmiHeader.biWidth = cxDesired; + bi->bmiHeader.biHeight = cyDesired; + bi->bmiHeader.biSizeImage = 0; + + res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0); + DeleteDC(dc); + } + else + { + /* Create a device-dependent bitmap */ + + BOOL monochrome = (fuFlags & LR_MONOCHROME); + + if (objSize == sizeof(DIBSECTION)) + { + /* The source bitmap is a DIB section. + Get its attributes */ + HDC dc = CreateCompatibleDC(NULL); + bi->bmiHeader.biSize = sizeof(bi->bmiHeader); + bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel; + GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + DeleteDC(dc); + + if (!monochrome && ds.dsBm.bmBitsPixel == 1) + { + /* Look if the colors of the DIB are black and white */ + + monochrome = + (bi->bmiColors[0].rgbRed == 0xff + && bi->bmiColors[0].rgbGreen == 0xff + && bi->bmiColors[0].rgbBlue == 0xff + && bi->bmiColors[0].rgbReserved == 0 + && bi->bmiColors[1].rgbRed == 0 + && bi->bmiColors[1].rgbGreen == 0 + && bi->bmiColors[1].rgbBlue == 0 + && bi->bmiColors[1].rgbReserved == 0) + || + (bi->bmiColors[0].rgbRed == 0 + && bi->bmiColors[0].rgbGreen == 0 + && bi->bmiColors[0].rgbBlue == 0 + && bi->bmiColors[0].rgbReserved == 0 + && bi->bmiColors[1].rgbRed == 0xff + && bi->bmiColors[1].rgbGreen == 0xff + && bi->bmiColors[1].rgbBlue == 0xff + && bi->bmiColors[1].rgbReserved == 0); + } + } + else if (!monochrome) + { + monochrome = ds.dsBm.bmBitsPixel == 1; + } + + if (monochrome) + { + res = CreateBitmap(cxDesired, cyDesired, 1, 1, NULL); + } + else + { + HDC screenDC = GetDC(NULL); + res = CreateCompatibleBitmap(screenDC, cxDesired, cyDesired); + ReleaseDC(NULL, screenDC); + } + } + + if (res) + { + /* Only copy the bitmap if it's a DIB section or if it's + compatible to the screen */ + BOOL copyContents; + + if (objSize == sizeof(DIBSECTION)) + { + copyContents = TRUE; + } + else + { + HDC screenDC = GetDC(NULL); + int screen_depth = GetDeviceCaps(screenDC, BITSPIXEL); + ReleaseDC(NULL, screenDC); + + copyContents = (ds.dsBm.bmBitsPixel == 1 || ds.dsBm.bmBitsPixel == screen_depth); + } + + if (copyContents) + { + /* The source bitmap may already be selected in a device context, + use GetDIBits/StretchDIBits and not StretchBlt */ + + HDC dc; + void * bits; + + dc = CreateCompatibleDC(NULL); + + bi->bmiHeader.biWidth = ds.dsBm.bmWidth; + bi->bmiHeader.biHeight = ds.dsBm.bmHeight; + bi->bmiHeader.biSizeImage = 0; + bi->bmiHeader.biClrUsed = 0; + bi->bmiHeader.biClrImportant = 0; + + /* Fill in biSizeImage */ + GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bi->bmiHeader.biSizeImage); + + if (bits) + { + HBITMAP oldBmp; + + /* Get the image bits of the source bitmap */ + GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS); + + /* Copy it to the destination bitmap */ + oldBmp = SelectObject(dc, res); + StretchDIBits(dc, 0, 0, cxDesired, cyDesired, + 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, + bits, bi, DIB_RGB_COLORS, SRCCOPY); + SelectObject(dc, oldBmp); + + HeapFree(GetProcessHeap(), 0, bits); + } + + DeleteDC(dc); + } + + if (fuFlags & LR_COPYDELETEORG) + { + DeleteObject(hbmp); + } + } + HeapFree(GetProcessHeap(), 0, bi); + return res; +} + +static +HICON +CURSORICON_CopyImage( + _In_ HICON hicon, + _In_ BOOL bIcon, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT fuFlags +) +{ + HICON ret = NULL; + ICONINFO ii; + + if(fuFlags & LR_COPYFROMRESOURCE) + { + /* Get the icon module/resource names */ + UNICODE_STRING ustrModule; + UNICODE_STRING ustrRsrc; + PVOID pvBuf; + HMODULE hModule; + + ustrModule.MaximumLength = MAX_PATH; + ustrRsrc.MaximumLength = 256; + + ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength * sizeof(WCHAR)); + if(!ustrModule.Buffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + /* Keep track of the buffer for the resource, NtUserGetIconInfo might overwrite it */ + pvBuf = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WCHAR)); + if(!pvBuf) + { + HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + ustrRsrc.Buffer = pvBuf; + + do + { + if(!NtUserGetIconInfo(hicon, NULL, &ustrModule, &ustrRsrc, NULL, FALSE)) + { + HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); + HeapFree(GetProcessHeap(), 0, pvBuf); + return NULL; + } + + if((ustrModule.Length < ustrModule.MaximumLength) && (ustrRsrc.Length < ustrRsrc.MaximumLength)) + { + /* Buffers were big enough */ + break; + } + + /* Find which buffer were too small */ + if(ustrModule.Length == ustrModule.MaximumLength) + { + PWSTR newBuffer; + ustrModule.MaximumLength *= 2; + newBuffer = HeapReAlloc(GetProcessHeap(), 0, ustrModule.Buffer, ustrModule.MaximumLength * sizeof(WCHAR)); + if(!ustrModule.Buffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto leave; + } + ustrModule.Buffer = newBuffer; + } + + if(ustrRsrc.Length == ustrRsrc.MaximumLength) + { + ustrRsrc.MaximumLength *= 2; + pvBuf = HeapReAlloc(GetProcessHeap(), 0, ustrRsrc.Buffer, ustrRsrc.MaximumLength * sizeof(WCHAR)); + if(!pvBuf) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto leave; + } + ustrRsrc.Buffer = pvBuf; + } + } while(TRUE); + + /* NULL-terminate our strings */ + ustrModule.Buffer[ustrModule.Length] = 0; + if(!IS_INTRESOURCE(ustrRsrc.Buffer)) + ustrRsrc.Buffer[ustrRsrc.Length] = 0; + + /* Get the module handle */ + if(!GetModuleHandleExW(0, ustrModule.Buffer, &hModule)) + { + /* This hould never happen */ + SetLastError(ERROR_INVALID_PARAMETER); + goto leave; + } + + /* Call the relevant function */ + ret = CURSORICON_LoadImageW(hModule, ustrRsrc.Buffer, cxDesired, cyDesired, fuFlags & LR_DEFAULTSIZE, bIcon); + + FreeLibrary(hModule); + + /* If we're here, that means that the passed icon is shared. Don't destroy it, even if LR_COPYDELETEORG is specified */ + leave: + HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); + HeapFree(GetProcessHeap(), 0, pvBuf); + + return ret; + } + + /* This is a regular copy */ + if(fuFlags & ~LR_COPYDELETEORG) + FIXME("Unimplemented flags: 0x%08x\n", fuFlags); + + if(!GetIconInfo(hicon, &ii)) + { + ERR("GetIconInfo failed.\n"); + return NULL; + } + + ret = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmMask); + if(ii.hbmColor) DeleteObject(ii.hbmColor); + + if(ret && (fuFlags & LR_COPYDELETEORG)) + DestroyIcon(hicon); + + return hicon; +} + /************* PUBLIC FUNCTIONS *******************/ HANDLE WINAPI CopyImage( @@ -404,7 +1232,19 @@ HANDLE WINAPI CopyImage( _In_ UINT fuFlags ) { - UNIMPLEMENTED; + TRACE("hImage=%p, uType=%u, cxDesired=%d, cyDesired=%d, fuFlags=%x\n", + hImage, uType, cxDesired, cyDesired, fuFlags); + switch(uType) + { + case IMAGE_BITMAP: + return BITMAP_CopyImage(hImage, cxDesired, cyDesired, fuFlags); + case IMAGE_CURSOR: + case IMAGE_ICON: + return CURSORICON_CopyImage(hImage, uType == IMAGE_ICON, cxDesired, cyDesired, fuFlags); + default: + SetLastError(ERROR_INVALID_PARAMETER); + break; + } return NULL; } @@ -438,8 +1278,9 @@ BOOL WINAPI DrawIconEx( _In_ UINT diFlags ) { - UNIMPLEMENTED; - return FALSE; + return NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, + istepIfAniCur, hbrFlickerFreeDraw, diFlags, + 0, 0); } BOOL WINAPI GetIconInfo( @@ -447,16 +1288,14 @@ BOOL WINAPI GetIconInfo( _Out_ PICONINFO piconinfo ) { - UNIMPLEMENTED; - return FALSE; + return NtUserGetIconInfo(hIcon, piconinfo, NULL, NULL, NULL, FALSE); } BOOL WINAPI DestroyIcon( _In_ HICON hIcon ) { - UNIMPLEMENTED; - return FALSE; + return NtUserDestroyCursor(hIcon, FALSE); } HICON WINAPI LoadIconA( @@ -631,8 +1470,9 @@ int WINAPI LookupIconIdFromDirectory( _In_ BOOL fIcon ) { - UNIMPLEMENTED; - return 0; + return LookupIconIdFromDirectoryEx( presbits, fIcon, + fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR), + fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), fIcon ? 0 : LR_MONOCHROME ); } int WINAPI LookupIconIdFromDirectoryEx( @@ -643,8 +1483,134 @@ int WINAPI LookupIconIdFromDirectoryEx( _In_ UINT Flags ) { - UNIMPLEMENTED; - return 0; + WORD bppDesired; + CURSORICONDIR* dir = (CURSORICONDIR*)presbits; + CURSORICONDIRENTRY* entry; + int i, numMatch, iIndex = -1; + WORD width, height; + USHORT bitcount; + ULONG cxyDiff, cxyDiffTmp; + + TRACE("%p, %x, %i, %i, %x.\n", presbits, fIcon, cxDesired, cyDesired, Flags); + + if(!(dir && !dir->idReserved && (dir->idType & 3))) + { + WARN("Invalid resource.\n"); + return 0; + } + + /* idType == 2 is for cursors, 1 for icons */ + /*if(fIcon) + { + if(dir->idType == 2) + { + WARN("An icon was asked for a cursor resource.\n"); + return 0; + } + } + else if(dir->idType == 1) + { + WARN("A cursor was asked for an icon resource.\n"); + return 0; + }*/ + + if(Flags & LR_MONOCHROME) + bppDesired = 1; + else + { + HDC icScreen; + icScreen = CreateICW(DISPLAYW, NULL, NULL, NULL); + if(!icScreen) + return FALSE; + + bppDesired = GetDeviceCaps(icScreen, BITSPIXEL); + DeleteDC(icScreen); + } + + /* Find the best match for the desired size */ + cxyDiff = 0xFFFFFFFF; + numMatch = 0; + for(i = 0; i < dir->idCount; i++) + { + entry = &dir->idEntries[i]; + width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth; + /* Height is twice as big in cursor resources */ + height = fIcon ? entry->ResInfo.icon.bHeight : entry->ResInfo.cursor.wHeight/2; + /* 0 represents 256 */ + if(!width) width = 256; + if(!height) height = 256; + /* Let it be a 1-norm */ + cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired)); + if( cxyDiffTmp > cxyDiff) + continue; + if( cxyDiffTmp == cxyDiff) + { + numMatch++; + continue; + } + iIndex = i; + numMatch = 1; + cxyDiff = cxyDiffTmp; + } + + if(numMatch == 1) + { + /* Only one entry fit the asked dimensions */ + return dir->idEntries[iIndex].wResId; + } + + bitcount = 0; + iIndex = -1; + /* Now find the entry with the best depth */ + for(i = 0; i < dir->idCount; i++) + { + entry = &dir->idEntries[i]; + width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth; + height = fIcon ? entry->ResInfo.icon.bHeight : entry->ResInfo.cursor.wHeight/2; + /* 0 represents 256 */ + if(!width) width = 256; + if(!height) height = 256; + /* Check if this is the best match we had */ + cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired)); + if(cxyDiffTmp != cxyDiff) + continue; + /* Exact match? */ + if(entry->wBitCount == bppDesired) + return entry->wResId; + /* We take the highest possible but smaller than the display depth */ + if((entry->wBitCount > bitcount) && (entry->wBitCount < bppDesired)) + { + iIndex = i; + bitcount = entry->wBitCount; + } + } + + if(iIndex >= 0) + return dir->idEntries[iIndex].wResId; + + /* No inferior or equal depth available. Get the smallest one */ + bitcount = 0x7FFF; + for(i = 0; i < dir->idCount; i++) + { + entry = &dir->idEntries[i]; + width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth; + height = fIcon ? entry->ResInfo.icon.bHeight : entry->ResInfo.cursor.wHeight/2; + /* 0 represents 256 */ + if(!width) width = 256; + if(!height) height = 256; + /* Check if this is the best match we had */ + cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired)); + if(cxyDiffTmp != cxyDiff) + continue; + /* Check the bit depth */ + if(entry->wBitCount < bitcount) + { + iIndex = i; + bitcount = entry->wBitCount; + } + } + + return dir->idEntries[iIndex].wResId; } HICON WINAPI CreateIcon( @@ -657,8 +1623,32 @@ HICON WINAPI CreateIcon( _In_ const BYTE *lpbXORbits ) { - UNIMPLEMENTED; - return NULL; + ICONINFO iinfo; + HICON hIcon; + + TRACE_(icon)("%dx%d, planes %d, bpp %d, xor %p, and %p\n", + nWidth, nHeight, cPlanes, cBitsPixel, lpbXORbits, lpbANDbits); + + iinfo.fIcon = TRUE; + iinfo.xHotspot = nWidth / 2; + iinfo.yHotspot = nHeight / 2; + if (cPlanes * cBitsPixel > 1) + { + iinfo.hbmColor = CreateBitmap( nWidth, nHeight, cPlanes, cBitsPixel, lpbXORbits ); + iinfo.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, lpbANDbits ); + } + else + { + iinfo.hbmMask = CreateBitmap( nWidth, nHeight * 2, 1, 1, lpbANDbits ); + iinfo.hbmColor = NULL; + } + + hIcon = CreateIconIndirect( &iinfo ); + + DeleteObject( iinfo.hbmMask ); + if (iinfo.hbmColor) DeleteObject( iinfo.hbmColor ); + + return hIcon; } HICON WINAPI CreateIconFromResource( @@ -681,16 +1671,60 @@ HICON WINAPI CreateIconFromResourceEx( _In_ UINT uFlags ) { - UNIMPLEMENTED; - return NULL; + ICONINFO ii; + HICON hIcon; + + if(uFlags) + FIXME("uFlags 0x%08x ignored.\n", uFlags); + + if(fIcon) + { + ii.xHotspot = cxDesired/2; + ii.yHotspot = cyDesired/2; + } + else + { + WORD* pt = (WORD*)pbIconBits; + ii.xHotspot = *pt++; + ii.yHotspot = *pt++; + pbIconBits = (PBYTE)pt; + } + ii.fIcon = fIcon; + + if(!CURSORICON_GetIconInfoFromBMI(&ii, (BITMAPINFO*)pbIconBits, cxDesired, cyDesired)) + return NULL; + + hIcon = CreateIconIndirect(&ii); + + /* Clean up */ + DeleteObject(ii.hbmMask); + if(ii.hbmColor) DeleteObject(ii.hbmColor); + + return hIcon; } HICON WINAPI CreateIconIndirect( _In_ PICONINFO piconinfo ) { - UNIMPLEMENTED; - return NULL; + /* As simple as creating a handle, and let win32k deal with the bitmaps */ + HICON hiconRet; + + TRACE("%p.\n", piconinfo); + + hiconRet = NtUserxCreateEmptyCurObject(piconinfo->fIcon ? 0 : 1); + if(!hiconRet) + return NULL; + + if(!NtUserSetCursorIconData(hiconRet, NULL, NULL, piconinfo)) + { + NtUserDestroyCursor(hiconRet, FALSE); + hiconRet = NULL; + } + + TRACE("Returning 0x%08x.\n", hiconRet); + + return hiconRet; } HCURSOR WINAPI CreateCursor( @@ -703,8 +1737,21 @@ HCURSOR WINAPI CreateCursor( _In_ const VOID *pvXORPlane ) { - UNIMPLEMENTED; - return NULL; + ICONINFO info; + HCURSOR hCursor; + + TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n", + nWidth, nHeight, xHotSpot, yHotSpot, pvXORPlane, pvANDPlane); + + info.fIcon = FALSE; + info.xHotspot = xHotSpot; + info.yHotspot = yHotSpot; + info.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, pvANDPlane ); + info.hbmColor = CreateBitmap( nWidth, nHeight, 1, 1, pvXORPlane ); + hCursor = CreateIconIndirect( &info ); + DeleteObject( info.hbmMask ); + DeleteObject( info.hbmColor ); + return hCursor; } BOOL WINAPI SetSystemCursor( @@ -729,8 +1776,7 @@ BOOL WINAPI GetCursorPos( _Out_ LPPOINT lpPoint ) { - UNIMPLEMENTED; - return FALSE; + return NtUserxGetCursorPos(lpPoint); } int WINAPI ShowCursor( @@ -751,6 +1797,5 @@ BOOL WINAPI DestroyCursor( _In_ HCURSOR hCursor ) { - UNIMPLEMENTED; - return FALSE; + return NtUserDestroyCursor(hCursor, FALSE); } diff --git a/win32ss/user/user32/windows/dialog.c b/win32ss/user/user32/windows/dialog.c index 1ce55fd6f3a..0df3dd3b930 100644 --- a/win32ss/user/user32/windows/dialog.c +++ b/win32ss/user/user32/windows/dialog.c @@ -2162,7 +2162,7 @@ GetDlgItemInt( result = strtol( str, &endptr, 10 ); if (!endptr || (endptr == str)) /* Conversion was unsuccessful */ return 0; - if (((result == LONG_MIN) || (result == LONG_MAX)) && (errno == ERANGE) ) + if (((result == LONG_MIN) || (result == LONG_MAX))) return 0; } else @@ -2170,7 +2170,7 @@ GetDlgItemInt( result = strtoul( str, &endptr, 10 ); if (!endptr || (endptr == str)) /* Conversion was unsuccessful */ return 0; - if ((result == ULONG_MAX) && (errno == ERANGE) ) return 0; + if (result == ULONG_MAX) return 0; } if (lpTranslated) *lpTranslated = TRUE; return (UINT)result; diff --git a/win32ss/user/user32/windows/mdi.c b/win32ss/user/user32/windows/mdi.c index d24eb037af8..783d7c8aea8 100644 --- a/win32ss/user/user32/windows/mdi.c +++ b/win32ss/user/user32/windows/mdi.c @@ -792,7 +792,7 @@ static LONG MDICascade( HWND client, MDICLIENTINFO *ci ) static void MDITile( HWND client, MDICLIENTINFO *ci, WPARAM wParam ) { HWND *win_array; - int i, total; + int i, total, rows, columns; BOOL has_icons = FALSE; if (ci->hwndChildMaximized) @@ -803,7 +803,7 @@ static void MDITile( HWND client, MDICLIENTINFO *ci, WPARAM wParam ) if (!(win_array = WIN_ListChildren( client ))) return; /* remove all the windows we don't want */ - for (i = total = 0; win_array[i]; i++) + for (i = total = rows = 0; win_array[i]; i++) { if (!IsWindowVisible( win_array[i] )) continue; if (GetWindow( win_array[i], GW_OWNER )) continue; /* skip owned windows (icon titles) */ @@ -813,6 +813,7 @@ static void MDITile( HWND client, MDICLIENTINFO *ci, WPARAM wParam ) continue; } if ((wParam & MDITILE_SKIPDISABLED) && !IsWindowEnabled( win_array[i] )) continue; + if(total == (rows * (rows + 2))) rows++; /* total+1 == (rows+1)*(rows+1) */ win_array[total++] = win_array[i]; } win_array[total] = 0; @@ -824,11 +825,11 @@ static void MDITile( HWND client, MDICLIENTINFO *ci, WPARAM wParam ) HWND *pWnd = win_array; RECT rect; int x, y, xsize, ysize; - int rows, columns, r, c, i; + int r, c, i; GetClientRect(client,&rect); - rows = (int) sqrt((double)total); - columns = total / rows; + columns = total/rows; + //while(total < rows*columns) rows++; if( wParam & MDITILE_HORIZONTAL ) /* version >= 3.1 */ { @@ -1604,8 +1605,8 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message, #ifndef __REACTOS__ case WM_SETVISIBLE: #endif - if (ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE; - else MDI_PostUpdate(client, ci, SB_BOTH+1); + /*if (ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE; + else*/ MDI_PostUpdate(client, ci, SB_BOTH+1); break; case WM_SIZE: @@ -1843,7 +1844,6 @@ void WINAPI CalcChildScroll( HWND hwnd, INT scroll ) } HeapFree( GetProcessHeap(), 0, list ); } - MapWindowPoints( 0, hwnd, (POINT *)&childRect, 2 ); UnionRect( &childRect, &clientRect, &childRect ); /* set common info values */