# 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
# 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.
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);
}
/// 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();
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)
{
SendMessage(_right_hwnd, WM_SYSCOLORCHANGE, 0, 0);
break;
+ case PM_TRANSLATE_MSG:
+ return _shellBrowser->TranslateAccelerator((MSG*)lparam);
+
default:
return super::WndProc(nmsg, wparam, lparam);
}
void invalidate_cache();
+ bool TranslateAccelerator(LPMSG lpmsg);
+
protected:
HWND _hwnd;
HWND _hwndFrame;
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;
#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);
#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().
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
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
* Created 01/11/98
*/
-/* INCLUDES ****************************************************************/
+/* INCLUDES *******************************************************************/
#include <ntdll.h>
#define NDEBUG
#include <debug.h>
-/* 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
*
* @implemented
*/
-
BOOLEAN NTAPI
RtlGetNtProductType(PNT_PRODUCT_TYPE ProductType)
{
- *ProductType = SharedUserData->NtProductType;
- return(TRUE);
+ *ProductType = SharedUserData->NtProductType;
+ return TRUE;
}
/**********************************************************************
*
* @implemented
*/
-
VOID NTAPI
RtlGetNtVersionNumbers(OUT LPDWORD pdwMajorVersion,
OUT LPDWORD pdwMinorVersion,
}
/*
-* @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;
-
- if (Info->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOW) ||
- Info->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)
+ LONG i, MaxLength;
+
+ if (lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOW) ||
+ lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW))
+ {
+ PPEB Peb = NtCurrentPeb();
+
+ 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;
- }
-
- return STATUS_INVALID_PARAMETER;
+
+ 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;
+
+ /* HACK: ReactOS specific changes, see bug-reports CORE-6611 and CORE-4620 (aka. #5003) */
+ SetRosSpecificInfo(InfoEx);
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_PARAMETER;
}
/* EOF */
#define FN_PROGRESSA FN_PROGRESS
#endif
-/* sid.c */
-
-BOOL ADVAPI_GetComputerSid(PSID sid);
-
/* rpc.c */
RPC_STATUS EvtBindRpc(LPCWSTR pszMachine,
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;
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 */
{
LPWSTR wstr;
ULONG len;
+
if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
{
int lenA;
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++;
if (!lpaf->wstr)
return 0;
- flags |= lpaf->value;
+ flags |= lpaf->value;
szAcl += len;
}
{
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
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;
}
}
*
* 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;
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);
/* 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;
/* Parse ACE account sid */
if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
- {
+ {
while (*StringAcl && *StringAcl != ')')
StringAcl++;
- }
+ }
if (*StringAcl != ')')
goto 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;
{
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;
tok[len] = 0;
switch (toktype)
- {
+ {
case 'O':
{
DWORD bytes;
lpNext += bytes; /* Advance to next token */
}
- *cBytes += bytes;
+ *cBytes += bytes;
break;
}
lpNext += bytes; /* Advance to next token */
}
- *cBytes += bytes;
+ *cBytes += bytes;
break;
}
case 'D':
- {
+ {
DWORD flags;
DWORD bytes;
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':
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;
}
* 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;
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;
(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;
* 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;
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
EqualPrefixSid(PSID pSid1,
PSID pSid2)
{
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
EqualSid(PSID pSid1,
PSID pSid2)
{
* 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);
/*
* @implemented
*/
-DWORD WINAPI
+DWORD
+WINAPI
GetLengthSid(PSID pSid)
{
return (DWORD)RtlLengthSid(pSid);
/*
* @implemented
*/
-PSID_IDENTIFIER_AUTHORITY WINAPI
+PSID_IDENTIFIER_AUTHORITY
+WINAPI
GetSidIdentifierAuthority(PSID pSid)
{
return RtlIdentifierAuthoritySid(pSid);
/*
* @implemented
*/
-DWORD WINAPI
+DWORD
+WINAPI
GetSidLengthRequired(UCHAR nSubAuthorityCount)
{
return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
/*
* @implemented
*/
-PDWORD WINAPI
+PDWORD
+WINAPI
GetSidSubAuthority(PSID pSid,
DWORD nSubAuthority)
{
/*
* @implemented
*/
-PUCHAR WINAPI
+PUCHAR
+WINAPI
GetSidSubAuthorityCount(PSID pSid)
{
return RtlSubAuthorityCountSid(pSid);
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
InitializeSid(PSID Sid,
PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
BYTE nSubAuthorityCount)
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
IsValidSid(PSID pSid)
{
return (BOOL)RtlValidSid(pSid);
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
ConvertSidToStringSidW(PSID Sid,
LPWSTR *StringSid)
{
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
ConvertSidToStringSidA(PSID Sid,
LPSTR *StringSid)
{
/*
* @unimplemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
EqualDomainSid(IN PSID pSid1,
IN PSID pSid2,
OUT BOOL* pfEqual)
/*
* @unimplemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
GetWindowsAccountDomainSid(IN PSID pSid,
OUT PSID ppDomainSid,
IN OUT DWORD* cbSid)
/*
* @unimplemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
IN PSID DomainSid OPTIONAL,
OUT PSID pSid,
/*
* @unimplemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
IsWellKnownSid(IN PSID pSid,
IN WELL_KNOWN_SID_TYPE WellKnownSidType)
{
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
ConvertStringSidToSidA(IN LPCSTR StringSid,
OUT PSID* sid)
{
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
ConvertStringSidToSidW(IN LPCWSTR StringSid,
OUT PSID* sid)
{
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;
- }
- }
-
- /* That's probably a string S-R-I-S-S... */
- if (StringSid[0] != 'S' || StringSid[1] != '-')
- {
- SetLastError(ERROR_INVALID_SID);
- return FALSE;
- }
+ 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;
+ }
+ }
+
+ /* 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 );
return ret;
}
-
/* EOF */
/* 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
*/
{
lpVersionInformationEx = (PVOID)lpVersionInformation;
lpVersionInformationEx->wReserved = 0;
-
- /* ReactOS specific changes */
- SetRosSpecificInfo(lpVersionInformationEx);
}
return TRUE;
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)
#include "wine/debug.h"
#include "wine/unicode.h"
+#define NTOS_MODE_USER
+#include <ndk/rtlfuncs.h>
+#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.@)
*/
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;
}
/************************************************************
* 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 <ndk/rtlfuncs.h>
+#include "netapi32.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(netbios);
static HMODULE NETAPI32_hModule;
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)
{
--- /dev/null
+
+#ifndef __WINE_NETAPI32_H__
+#define __WINE_NETAPI32_H__
+
+NET_API_STATUS
+WINAPI
+NetpNtStatusToApiStatus(NTSTATUS Status);
+
+
+#endif
\ No newline at end of file
@ stub NetpNetBiosReset
@ stub NetpNetBiosSend
@ stdcall NetpNetBiosStatusToApiStatus(long)
-@ stub NetpNtStatusToApiStatus
+@ stdcall NetpNtStatusToApiStatus(long)
@ stub NetpOpenConfigData
@ stub NetpPackString
@ stub NetpReleasePrivilege
return STATUS_NOT_IMPLEMENTED;
}
+
/* Function 5 */
NTSTATUS
NTAPI
return Status;
}
+
/* Function 6 */
NTSTATUS
NTAPI
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;
* PURPOSE: Runtime code
* FILE: lib/rtl/version.c
* PROGRAMERS: Filip Navara
- * Hermes BELUSCA - MAITO
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *****************************************************************/
NTSTATUS
NTAPI
-RtlGetVersion(
- OUT PRTL_OSVERSIONINFOW lpVersionInformation
- );
+RtlGetVersion(OUT PRTL_OSVERSIONINFOW lpVersionInformation);
/* FUNCTIONS ****************************************************************/
*/
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;
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;
//
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)
+ {
+ 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(RTL_OSVERSIONINFOEXW))
{
- /* null-terminate if it was overflowed */
- lpVersionInformation->szCSDVersion[MaxLength] = L'\0';
+ 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;
}
- }
- 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;
- }
+ return STATUS_SUCCESS;
+ }
- return STATUS_INVALID_PARAMETER;
+ return STATUS_INVALID_PARAMETER;
}
+/* EOF */
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)
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)
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)
BOOL
NTAPI
NtUserDestroyCursor(
- HANDLE Handle,
- DWORD Unknown);
+ _In_ HANDLE Handle,
+ _In_ BOOL bForce);
DWORD
NTAPI
HDC hDC,
HBRUSH hBrush);
-HICON
-NTAPI
-NtUserFindExistingCursorIcon(
- HMODULE hModule,
- HRSRC hRsrc,
- LONG cx,
- LONG cy);
-
HWND
NTAPI
NtUserFindWindowEx(
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
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
HMODULE hModule,
HRSRC hRsrc,
HRSRC hGroupRsrc);
+
+HICON
+NTAPI
+NtUserFindExistingCursorIcon(
+ HMODULE hModule,
+ HRSRC hRsrc,
+ LONG cx,
+ LONG cy);
#endif
DWORD
typedef struct
{ union
- { ICONRESDIR icon;
- CURSORDIR cursor;
+ {
+ ICONRESDIR icon;
+ CURSORDIR cursor;
} ResInfo;
WORD wPlanes;
WORD wBitCount;
_Must_inspect_result_
NTSTATUS
NTAPI
-CaptureUnicodeStringOrAtom(
+ProbeAndCaptureUnicodeStringOrAtom(
_Out_ PUNICODE_STRING pustrOut,
__in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
{
NTSTATUS Status;
BOOL Ret;
- Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
+ Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
if (!NT_SUCCESS(Status))
{
ERR("Error capturing the class name\n");
}
_SEH2_END;
- Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
+ Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
if (!NT_SUCCESS(Status))
{
ERR("Error capturing the class name\n");
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");
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 */
}
PCURICON_OBJECT
-IntCreateCurIconHandle()
+IntCreateCurIconHandle(DWORD dwNumber)
{
PCURICON_OBJECT CurIcon;
HANDLE hCurIcon;
BOOL
APIENTRY
NtUserDestroyCursor(
- HANDLE hCurIcon,
- DWORD Unknown)
+ _In_ HANDLE hCurIcon,
+ _In_ BOOL bForce)
{
PCURICON_OBJECT CurIcon;
BOOL ret;
LIST_ENTRY ListEntry;
HANDLE Self;
LIST_ENTRY ProcessList;
- HMODULE hModule;
- HRSRC hRsrc;
+ UNICODE_STRING ustrModule;
+ UNICODE_STRING ustrRsrc;
SIZE Size;
BYTE Shadow;
BOOL bIcon;
} 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,
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);
- continue;
+ if(CurIcon->ustrRsrc.Buffer != pustrRsrc->Buffer)
+ continue;
}
- if (! ReferenceCurIconByProcess(CurIcon))
+ else if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer) || IS_INTRESOURCE(pustrRsrc->Buffer))
+ continue;
+ 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)
{
}
CurIcon->Self = hCurIcon;
+ CurIcon->bIcon = bIcon;
InitializeListHead(&CurIcon->ProcessList);
if (! ReferenceCurIconByProcess(CurIcon))
}
BOOLEAN FASTCALL
-IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi)
+IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi, BOOLEAN bForce)
{
PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor, bmpAlpha;
{
/* 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);
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);
LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
{
UserReferenceObject(CurIcon);
- IntDestroyCurIconObject(CurIcon, Win32Process);
+ IntDestroyCurIconObject(CurIcon, Win32Process, TRUE);
}
}
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;
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;
+ /* Give back the icon information */
+ if(IconInfo)
+ {
+ /* 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);
+ /* 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)
- {
- PSURFACE psurfBmp;
+ if (pbpp)
+ {
+ PSURFACE psurfBmp;
- psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor);
- if (psurfBmp)
+ psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor);
+ if (psurfBmp)
+ {
+ colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
+ SURFACE_ShareUnlockSurface(psurfBmp);
+ }
+ }
+
+ /* Copy fields */
+ _SEH2_TRY
{
- colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
- SURFACE_ShareUnlockSurface(psurfBmp);
+ 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
}
- /* Copy fields */
- _SEH2_TRY
+ if (!NT_SUCCESS(Status))
{
- ProbeForWrite(IconInfo, sizeof(ICONINFO), 1);
- RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO));
+ WARN("Status: 0x%08x.\n", Status);
+ SetLastNtError(Status);
+ goto leave;
+ }
- if (pbpp)
+ /* Give back the module name */
+ if(lpModule)
+ {
+ if(!CurIcon->ustrModule.Buffer)
{
- ProbeForWrite(pbpp, sizeof(DWORD), 1);
- *pbpp = colorBpp;
+ 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
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+
+ if (!NT_SUCCESS(Status))
{
- Status = _SEH2_GetExceptionCode();
+ 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
}
- _SEH2_END
- if (NT_SUCCESS(Status))
- Ret = TRUE;
- else
+ if (!NT_SUCCESS(Status))
+ {
SetLastNtError(Status);
+ goto leave;
+ }
+
+ Ret = TRUE;
+leave:
UserDereferenceObject(CurIcon);
-leave:
TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret);
UserLeave();
BOOL
APIENTRY
NtUserDestroyCursor(
- HANDLE hCurIcon,
- DWORD Unknown)
+ _In_ HANDLE hCurIcon,
+ _In_ BOOL bForce)
{
PCURICON_OBJECT CurIcon;
BOOL ret;
RETURN(FALSE);
}
- ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
+ ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process(), bForce);
/* Note: IntDestroyCurIconObject will remove our reference for us! */
RETURN(ret);
* @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;
}
done:
- if(!Ret)
- {
- IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
- CurIcon = NULL;
- }
-
if (CurIcon)
{
UserDereferenceObject(CurIcon);
/*
* @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);
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:
GreDeleteObject(CurIcon->aFrame[0].hbmColor);
CurIcon->aFrame[0].hbmColor = NULL;
}
- }
- RETURN(Ret);
-
-CLEANUP:
- TRACE("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-#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(!IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer))
+ ExFreePoolWithTag(CurIcon->ustrRsrc.Buffer, TAG_STRING);
+ if(CurIcon->ustrModule.Buffer)
+ ReleaseCapturedUnicodeString(&CurIcon->ustrModule, UserMode);
}
- 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_);
+ TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret);
UserLeave();
- END_CLEANUP;
+
+ return Ret;
}
-#endif
/* Mostly inspired from wine code.
* We use low level functions because:
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;
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);
}
/* 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)
{
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 */
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 */
}
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);
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);
if (!(pIcon = UserGetCurIconObject(hIcon)))
{
- ERR("UserGetCurIconObject() failed!\n");
+ ERR("UserGetCurIconObject(0x%08x) failed!\n", hIcon);
UserLeave();
return FALSE;
}
PCURICON_OBJECT CurIcon;
DWORD_PTR Result ;
- if (!(CurIcon = IntCreateCurIconHandle()))
+ if (!(CurIcon = IntCreateCurIconHandle((DWORD)Param)))
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
RETURN(0);
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
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)
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);
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);
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(cursor);
-//WINE_DECLARE_DEBUG_CHANNEL(icon);
+WINE_DECLARE_DEBUG_CHANNEL(icon);
//WINE_DECLARE_DEBUG_CHANNEL(resource);
/************* USER32 INTERNAL FUNCTIONS **********/
/************* 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 );
}
}
+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(
{
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);
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 );
}
static
-HANDLE
+HBITMAP
BITMAP_LoadImageW(
_In_opt_ HINSTANCE hinst,
_In_ LPCWSTR lpszName,
_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; i<numColors; i++)
+ {
+ ptr = (RGBTRIPLE*)(pbmiColors + i*incr);
+ if((ptr->rgbtBlue == 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; i<dir->idCount; 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
_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;
+ UNICODE_STRING ustrRsrc;
+ UNICODE_STRING ustrModule = {0, 0, NULL};
+
+ /* Fix width/height */
+ if(fuLoad & LR_DEFAULTSIZE)
+ {
+ if(!cxDesired) cxDesired = GetSystemMetrics(bIcon ? SM_CXICON : SM_CXCURSOR);
+ if(!cyDesired) cyDesired = GetSystemMetrics(bIcon ? SM_CYICON : SM_CYCURSOR);
+ }
if(fuLoad & LR_LOADFROMFILE)
{
- UNIMPLEMENTED;
- return NULL;
+ 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,
/* We let FindResource, LoadResource, etc. call SetLastError */
if(!hrsrc)
- return NULL;
-
- /* Fix width/height */
- if(fuLoad & LR_DEFAULTSIZE)
- {
- if(!cxDesired) cxDesired = GetSystemMetrics(bIcon ? SM_CXICON : SM_CXCURSOR);
- 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;
+ 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];
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);
}
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(
_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;
}
_In_ UINT diFlags
)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
+ istepIfAniCur, hbrFlickerFreeDraw, diFlags,
+ 0, 0);
}
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(
_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(
_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(
_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(
_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(
_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(
_Out_ LPPOINT lpPoint
)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserxGetCursorPos(lpPoint);
}
int WINAPI ShowCursor(
_In_ HCURSOR hCursor
)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserDestroyCursor(hCursor, FALSE);
}
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
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;
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)
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) */
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;
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 */
{
#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:
}
HeapFree( GetProcessHeap(), 0, list );
}
- MapWindowPoints( 0, hwnd, (POINT *)&childRect, 2 );
UnionRect( &childRect, &clientRect, &childRect );
/* set common info values */