Sync with trunk r62529.

svn path=/branches/shell-experiments/; revision=62530
This commit is contained in:
David Quintana 2014-03-18 14:39:04 +00:00
commit 64227df624
33 changed files with 1151 additions and 401 deletions

View file

@ -4,6 +4,7 @@ add_subdirectory(find)
add_subdirectory(help) add_subdirectory(help)
add_subdirectory(hostname) add_subdirectory(hostname)
add_subdirectory(lodctr) add_subdirectory(lodctr)
add_subdirectory(mode)
add_subdirectory(more) add_subdirectory(more)
add_subdirectory(reg) add_subdirectory(reg)
add_subdirectory(taskkill) add_subdirectory(taskkill)

View file

@ -2,7 +2,7 @@
#include "doskey.h" #include "doskey.h"
#define REACTOS_STR_FILE_DESCRIPTION "W32 doskey command" #define REACTOS_STR_FILE_DESCRIPTION "ReactOS Doskey Command"
#define REACTOS_STR_INTERNAL_NAME "doskey" #define REACTOS_STR_INTERNAL_NAME "doskey"
#define REACTOS_STR_ORIGINAL_FILENAME "doskey.exe" #define REACTOS_STR_ORIGINAL_FILENAME "doskey.exe"
#include <reactos/version.rc> #include <reactos/version.rc>

View file

@ -2,7 +2,7 @@
#include "resource.h" #include "resource.h"
#define REACTOS_STR_FILE_DESCRIPTION "W32 find command" #define REACTOS_STR_FILE_DESCRIPTION "ReactOS Find Command"
#define REACTOS_STR_INTERNAL_NAME "find" #define REACTOS_STR_INTERNAL_NAME "find"
#define REACTOS_STR_ORIGINAL_FILENAME "find.exe" #define REACTOS_STR_ORIGINAL_FILENAME "find.exe"
#include <reactos/version.rc> #include <reactos/version.rc>

View file

@ -0,0 +1,7 @@
add_executable(mode mode.c mode.rc)
set_module_type(mode win32cui UNICODE)
set_target_properties(mode PROPERTIES SUFFIX ".com")
add_importlibs(mode user32 msvcrt kernel32)
add_cd_file(TARGET mode DESTINATION reactos/system32 FOR all)

View file

@ -0,0 +1,551 @@
/*
* ReactOS mode console command
*
* mode.c
*
* Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <windows.h>
#include <stdio.h>
#define MAX_PORTNAME_LEN 20
#define MAX_COMPORT_NUM 10
#define MAX_COMPARAM_LEN 20
#define NUM_ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
#define ASSERT(a)
const WCHAR* const usage_strings[] =
{
L"Device Status: MODE [device] [/STATUS]",
L"Select code page: MODE CON[:] CP SELECT=yyy",
L"Code page status: MODE CON[:] CP [/STATUS]",
L"Display mode: MODE CON[:] [COLS=c] [LINES=n]",
L"Typematic rate: MODE CON[:] [RATE=r DELAY=d]",
L"Redirect printing: MODE LPTn[:]=COMm[:]",
L"Serial port: MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s]\n" \
L" [to=on|off] [xon=on|off] [odsr=on|off]\n" \
L" [octs=on|off] [dtr=on|off|hs]\n" \
L" [rts=on|off|hs|tg] [idsr=on|off]",
};
const WCHAR* const parity_strings[] =
{
L"None", // default
L"Odd", // only symbol in this set to have a 'd' in it
L"Even", // ... 'v' in it
L"Mark", // ... 'm' in it
L"Space" // ... 's' and/or a 'c' in it
};
const WCHAR* const control_strings[] = { L"OFF", L"ON", L"HANDSHAKE", L"TOGGLE" };
const WCHAR* const stopbit_strings[] = { L"1", L"1.5", L"2" };
int Usage()
{
int i;
wprintf(L"\nConfigures system devices.\n\n");
for (i = 0; i < NUM_ELEMENTS(usage_strings); i++)
{
wprintf(L"%s\n", usage_strings[i]);
}
wprintf(L"\n");
return 0;
}
int QueryDevices()
{
WCHAR buffer[20240];
int len;
WCHAR* ptr = buffer;
*ptr = L'\0';
if (QueryDosDeviceW(NULL, buffer, NUM_ELEMENTS(buffer)))
{
while (*ptr != L'\0')
{
len = wcslen(ptr);
if (wcsstr(ptr, L"COM"))
{
wprintf(L" Found serial device - %s\n", ptr);
}
else if (wcsstr(ptr, L"PRN"))
{
wprintf(L" Found printer device - %s\n", ptr);
}
else if (wcsstr(ptr, L"LPT"))
{
wprintf(L" Found parallel device - %s\n", ptr);
}
else
{
// wprintf(L" Found other device - %s\n", ptr);
}
ptr += (len+1);
}
}
else
{
wprintf(L" ERROR: QueryDosDeviceW(...) failed: 0x%lx\n", GetLastError());
}
return 1;
}
int ShowParallelStatus(int nPortNum)
{
WCHAR buffer[250];
WCHAR szPortName[MAX_PORTNAME_LEN];
swprintf(szPortName, L"LPT%d", nPortNum);
wprintf(L"\nStatus for device LPT%d:\n", nPortNum);
wprintf(L"-----------------------\n");
if (QueryDosDeviceW(szPortName, buffer, NUM_ELEMENTS(buffer)))
{
WCHAR* ptr = wcsrchr(buffer, L'\\');
if (ptr != NULL)
{
if (0 == wcscmp(szPortName, ++ptr))
{
wprintf(L" Printer output is not being rerouted.\n");
}
else
{
wprintf(L" Printer output is being rerouted to serial port %s\n", ptr);
}
return 0;
}
else
{
wprintf(L" QueryDosDeviceW(%s) returned unrecognised form %s.\n", szPortName, buffer);
}
}
else
{
wprintf(L" ERROR: QueryDosDeviceW(%s) failed: 0x%lx\n", szPortName, GetLastError());
}
return 1;
}
int ShowConsoleStatus()
{
DWORD dwKbdDelay;
DWORD dwKbdSpeed;
CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
wprintf(L"\nStatus for device CON:\n");
wprintf(L"-----------------------\n");
if (GetConsoleScreenBufferInfo(hConsoleOutput, &ConsoleScreenBufferInfo))
{
wprintf(L" Lines: %d\n", ConsoleScreenBufferInfo.dwSize.Y);
wprintf(L" Columns: %d\n", ConsoleScreenBufferInfo.dwSize.X);
}
if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &dwKbdDelay, 0))
{
wprintf(L" Keyboard delay: %ld\n", dwKbdDelay);
}
if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &dwKbdSpeed, 0))
{
wprintf(L" Keyboard rate: %ld\n", dwKbdSpeed);
}
wprintf(L" Code page: %d\n", GetConsoleOutputCP());
return 0;
}
static
BOOL SerialPortQuery(int nPortNum, LPDCB pDCB, LPCOMMTIMEOUTS pCommTimeouts, BOOL bWrite)
{
BOOL result;
HANDLE hPort;
WCHAR szPortName[MAX_PORTNAME_LEN];
ASSERT(pDCB);
ASSERT(pCommTimeouts);
swprintf(szPortName, L"COM%d", nPortNum);
hPort = CreateFileW(szPortName,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive
NULL, // sec attr
OPEN_EXISTING,
0, // no attributes
NULL); // no template
if (hPort == INVALID_HANDLE_VALUE)
{
wprintf(L"Illegal device name - %s\n", szPortName);
wprintf(L"Last error = 0x%lx\n", GetLastError());
return FALSE;
}
result = bWrite ? SetCommState(hPort, pDCB)
: GetCommState(hPort, pDCB);
if (!result)
{
wprintf(L"Failed to %s the status for device COM%d:\n", bWrite ? L"set" : L"get", nPortNum);
CloseHandle(hPort);
return FALSE;
}
result = bWrite ? SetCommTimeouts(hPort, pCommTimeouts)
: GetCommTimeouts(hPort, pCommTimeouts);
if (!result)
{
wprintf(L"Failed to %s Timeout status for device COM%d:\n", bWrite ? L"set" : L"get", nPortNum);
CloseHandle(hPort);
return FALSE;
}
CloseHandle(hPort);
return TRUE;
}
int ShowSerialStatus(int nPortNum)
{
DCB dcb;
COMMTIMEOUTS CommTimeouts;
if (!SerialPortQuery(nPortNum, &dcb, &CommTimeouts, FALSE))
{
return 1;
}
if (dcb.Parity > NUM_ELEMENTS(parity_strings))
{
wprintf(L"ERROR: Invalid value for Parity Bits %d:\n", dcb.Parity);
dcb.Parity = 0;
}
if (dcb.StopBits > NUM_ELEMENTS(stopbit_strings))
{
wprintf(L"ERROR: Invalid value for Stop Bits %d:\n", dcb.StopBits);
dcb.StopBits = 0;
}
wprintf(L"\nStatus for device COM%d:\n", nPortNum);
wprintf(L"-----------------------\n");
wprintf(L" Baud: %ld\n", dcb.BaudRate);
wprintf(L" Parity: %s\n", parity_strings[dcb.Parity]);
wprintf(L" Data Bits: %d\n", dcb.ByteSize);
wprintf(L" Stop Bits: %s\n", stopbit_strings[dcb.StopBits]);
wprintf(L" Timeout: %s\n", CommTimeouts.ReadIntervalTimeout ? L"ON" : L"OFF");
wprintf(L" XON/XOFF: %s\n", dcb.fOutX ? L"ON" : L"OFF");
wprintf(L" CTS handshaking: %s\n", dcb.fOutxCtsFlow ? L"ON" : L"OFF");
wprintf(L" DSR handshaking: %s\n", dcb.fOutxDsrFlow ? L"ON" : L"OFF");
wprintf(L" DSR sensitivity: %s\n", dcb.fDsrSensitivity ? L"ON" : L"OFF");
wprintf(L" DTR circuit: %s\n", control_strings[dcb.fDtrControl]);
wprintf(L" RTS circuit: %s\n", control_strings[dcb.fRtsControl]);
return 0;
}
int SetParallelState(int nPortNum)
{
WCHAR szPortName[MAX_PORTNAME_LEN];
WCHAR szTargetPath[MAX_PORTNAME_LEN];
swprintf(szPortName, L"LPT%d", nPortNum);
swprintf(szTargetPath, L"COM%d", nPortNum);
if (!DefineDosDeviceW(DDD_REMOVE_DEFINITION, szPortName, szTargetPath))
{
wprintf(L"SetParallelState(%d) - DefineDosDevice(%s) failed: 0x%lx\n", nPortNum, szPortName, GetLastError());
}
return 0;
}
/*
\??\COM1
\Device\NamedPipe\Spooler\LPT1
BOOL DefineDosDevice(
DWORD dwFlags, // options
LPCTSTR lpDeviceName, // device name
LPCTSTR lpTargetPath // path string
);
DWORD QueryDosDevice(
LPCTSTR lpDeviceName, // MS-DOS device name string
LPTSTR lpTargetPath, // query results buffer
DWORD ucchMax // maximum size of buffer
);
*/
int SetConsoleState()
{
/*
"Select code page: MODE CON[:] CP SELECT=yyy",
"Code page status: MODE CON[:] CP [/STATUS]",
"Display mode: MODE CON[:] [COLS=c] [LINES=n]",
"Typematic rate: MODE CON[:] [RATE=r DELAY=d]",
*/
return 0;
}
static
int ExtractModeSerialParams(const WCHAR* param)
{
if (wcsstr(param, L"OFF"))
return 0;
else if (wcsstr(param, L"ON"))
return 1;
else if (wcsstr(param, L"HS"))
return 2;
else if (wcsstr(param, L"TG"))
return 3;
return -1;
}
int SetSerialState(int nPortNum, int args, WCHAR *argv[])
{
int arg;
int value;
DCB dcb;
COMMTIMEOUTS CommTimeouts;
WCHAR buf[MAX_COMPARAM_LEN+1];
if (SerialPortQuery(nPortNum, &dcb, &CommTimeouts, FALSE))
{
for (arg = 2; arg < args; arg++)
{
if (wcslen(argv[arg]) > MAX_COMPARAM_LEN)
{
wprintf(L"Invalid parameter (too long) - %s\n", argv[arg]);
return 1;
}
wcscpy(buf, argv[arg]);
_wcslwr(buf);
if (wcsstr(buf, L"baud="))
{
wscanf(buf+5, L"%lu", &dcb.BaudRate);
}
else if (wcsstr(buf, L"parity="))
{
if (wcschr(buf, L'D'))
dcb.Parity = 1;
else if (wcschr(buf, L'V'))
dcb.Parity = 2;
else if (wcschr(buf, L'M'))
dcb.Parity = 3;
else if (wcschr(buf, L'S'))
dcb.Parity = 4;
else
dcb.Parity = 0;
}
else if (wcsstr(buf, L"data="))
{
wscanf(buf+5, L"%lu", &dcb.ByteSize);
}
else if (wcsstr(buf, L"stop="))
{
if (wcschr(buf, L'5'))
dcb.StopBits = 1;
else if (wcschr(buf, L'2'))
dcb.StopBits = 2;
else
dcb.StopBits = 0;
}
else if (wcsstr(buf, L"to=")) // to=on|off
{
value = ExtractModeSerialParams(buf);
if (value != -1)
{
}
else
{
goto invalid_serial_parameter;
}
}
else if (wcsstr(buf, L"xon=")) // xon=on|off
{
value = ExtractModeSerialParams(buf);
if (value != -1)
{
dcb.fOutX = value;
dcb.fInX = value;
}
else
{
goto invalid_serial_parameter;
}
}
else if (wcsstr(buf, L"odsr=")) // odsr=on|off
{
value = ExtractModeSerialParams(buf);
if (value != -1)
{
dcb.fOutxDsrFlow = value;
}
else
{
goto invalid_serial_parameter;
}
}
else if (wcsstr(buf, L"octs=")) // octs=on|off
{
value = ExtractModeSerialParams(buf);
if (value != -1)
{
dcb.fOutxCtsFlow = value;
}
else
{
goto invalid_serial_parameter;
}
}
else if (wcsstr(buf, L"dtr=")) // dtr=on|off|hs
{
value = ExtractModeSerialParams(buf);
if (value != -1)
{
dcb.fDtrControl = value;
}
else
{
goto invalid_serial_parameter;
}
}
else if (wcsstr(buf, L"rts=")) // rts=on|off|hs|tg
{
value = ExtractModeSerialParams(buf);
if (value != -1)
{
dcb.fRtsControl = value;
}
else
{
goto invalid_serial_parameter;
}
}
else if (wcsstr(buf, L"idsr=")) // idsr=on|off
{
value = ExtractModeSerialParams(buf);
if (value != -1)
{
dcb.fDsrSensitivity = value;
}
else
{
goto invalid_serial_parameter;
}
}
else
{
invalid_serial_parameter:;
wprintf(L"Invalid parameter - %s\n", buf);
return 1;
}
}
SerialPortQuery(nPortNum, &dcb, &CommTimeouts, TRUE);
}
return 0;
}
int find_portnum(const WCHAR* cmdverb)
{
int portnum = -1;
if (cmdverb[3] >= L'0' && cmdverb[3] <= L'9')
{
portnum = cmdverb[3] - L'0';
if (cmdverb[4] >= L'0' && cmdverb[4] <= L'9')
{
portnum *= 10;
portnum += cmdverb[4] - L'0';
}
}
return portnum;
}
int wmain(int argc, WCHAR* argv[])
{
int nPortNum;
WCHAR param1[MAX_COMPARAM_LEN+1];
WCHAR param2[MAX_COMPARAM_LEN+1];
if (argc > 1)
{
if (wcslen(argv[1]) > MAX_COMPARAM_LEN)
{
wprintf(L"Invalid parameter (too long) - %s\n", argv[1]);
return 1;
}
wcscpy(param1, argv[1]);
_wcslwr(param1);
if (argc > 2)
{
if (wcslen(argv[2]) > MAX_COMPARAM_LEN)
{
wprintf(L"Invalid parameter (too long) - %s\n", argv[2]);
return 1;
}
wcscpy(param2, argv[2]);
_wcslwr(param2);
}
else
{
param2[0] = L'\0';
}
if (wcsstr(param1, L"/?") || wcsstr(param1, L"-?"))
{
return Usage();
}
else if (wcsstr(param1, L"/status"))
{
goto show_status;
}
else if (wcsstr(param1, L"lpt"))
{
nPortNum = find_portnum(param1);
if (nPortNum != -1)
return ShowParallelStatus(nPortNum);
}
else if (wcsstr(param1, L"con"))
{
return ShowConsoleStatus();
}
else if (wcsstr(param1, L"com"))
{
nPortNum = find_portnum(param1);
if (nPortNum != -1)
{
if (param2[0] == L'\0' || wcsstr(param2, L"/status"))
{
return ShowSerialStatus(nPortNum);
}
else
{
return SetSerialState(nPortNum, argc, argv);
}
}
}
wprintf(L"Invalid parameter - %s\n", param1);
return 1;
}
else
{
show_status:;
QueryDevices();
/*
ShowParallelStatus(1);
for (nPortNum = 0; nPortNum < MAX_COMPORT_NUM; nPortNum++)
{
ShowSerialStatus(nPortNum + 1);
}
ShowConsoleStatus();
*/
}
return 0;
}

View file

@ -0,0 +1,5 @@
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Mode Utility"
#define REACTOS_STR_INTERNAL_NAME "mode"
#define REACTOS_STR_ORIGINAL_FILENAME "mode.com"
#include <reactos/version.rc>

View file

@ -1,5 +1,7 @@
add_executable(more more.c more.rc) add_executable(more more.c more.rc)
set_module_type(more win32cui) set_module_type(more win32cui)
set_target_properties(more PROPERTIES SUFFIX ".com")
add_importlibs(more user32 msvcrt kernel32) add_importlibs(more user32 msvcrt kernel32)
add_cd_file(TARGET more DESTINATION reactos/system32 FOR all) add_cd_file(TARGET more DESTINATION reactos/system32 FOR all)

View file

@ -2,9 +2,9 @@
#include "resource.h" #include "resource.h"
#define REACTOS_STR_FILE_DESCRIPTION "W32 more command" #define REACTOS_STR_FILE_DESCRIPTION "ReactOS More Command"
#define REACTOS_STR_INTERNAL_NAME "more" #define REACTOS_STR_INTERNAL_NAME "more"
#define REACTOS_STR_ORIGINAL_FILENAME "more.exe" #define REACTOS_STR_ORIGINAL_FILENAME "more.com"
#include <reactos/version.rc> #include <reactos/version.rc>
/* UTF-8 */ /* UTF-8 */

View file

@ -20,7 +20,7 @@
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#define REACTOS_STR_FILE_DESCRIPTION "xcopy command" #define REACTOS_STR_FILE_DESCRIPTION "ReactOS Xcopy Command"
#define REACTOS_STR_INTERNAL_NAME "xcopy" #define REACTOS_STR_INTERNAL_NAME "xcopy"
#define REACTOS_STR_ORIGINAL_FILENAME "xcopy.exe" #define REACTOS_STR_ORIGINAL_FILENAME "xcopy.exe"
#include <reactos/version.rc> #include <reactos/version.rc>

View file

@ -182,7 +182,7 @@ ajustes previos anteponiendo a cualquier modificador - (hyphen)--por ejemplo, /-
STRING_DIR_HELP3 " El volumen en la unidad %c no tiene etiqueta.\n" STRING_DIR_HELP3 " El volumen en la unidad %c no tiene etiqueta.\n"
STRING_DIR_HELP4 " El volumen Serial Number is %04X-%04X\n" STRING_DIR_HELP4 " El volumen Serial Number is %04X-%04X\n"
STRING_DIR_HELP5 "\n Total de archivos mostrados:\n%16i archivo(s)% 14s bytes\n" STRING_DIR_HELP5 "\n Total de archivos mostrados:\n%16i archivo(s)% 14s bytes\n"
STRING_DIR_HELP6 "%16i Directorio(s)% 15s bytes\n" STRING_DIR_HELP6 "%16i Directorio(s)% 15s bytes libres\n"
STRING_DIR_HELP7 "\n Directorio %s\n\n" STRING_DIR_HELP7 "\n Directorio %s\n\n"
STRING_DIR_HELP8 "%16i archivo(s)% 14s bytes\n" STRING_DIR_HELP8 "%16i archivo(s)% 14s bytes\n"
STRING_DIRSTACK_HELP1 "Almacena el directorio actual para usarlo por el comando, \n\ STRING_DIRSTACK_HELP1 "Almacena el directorio actual para usarlo por el comando, \n\

View file

@ -192,7 +192,7 @@ Modifier les paramètres mémorisés avec un - (tiret)--par exemple, /-W.\n"
STRING_DIR_HELP3 " Le lecteur %c n'a pas de nom de volume\n" STRING_DIR_HELP3 " Le lecteur %c n'a pas de nom de volume\n"
STRING_DIR_HELP4 " Le numéro de série du volume est %04X-%04X\n" STRING_DIR_HELP4 " Le numéro de série du volume est %04X-%04X\n"
STRING_DIR_HELP5 "\n Total de fichiers listés :\n%16i Fichier(s)% 14s octets\n" STRING_DIR_HELP5 "\n Total de fichiers listés :\n%16i Fichier(s)% 14s octets\n"
STRING_DIR_HELP6 "%16i Rep(s)% 15s octets\n" STRING_DIR_HELP6 "%16i Rep(s)% 15s octets libres\n"
STRING_DIR_HELP7 "\n Répertoire de %s\n\n" STRING_DIR_HELP7 "\n Répertoire de %s\n\n"
STRING_DIR_HELP8 "%16i Fichier(s)% 14s octets\n" STRING_DIR_HELP8 "%16i Fichier(s)% 14s octets\n"
STRING_DIRSTACK_HELP1 "Stocke le répertoire courant pour utilisation avec la commande POPD,\n\ STRING_DIRSTACK_HELP1 "Stocke le répertoire courant pour utilisation avec la commande POPD,\n\

View file

@ -170,7 +170,7 @@ A kapcsolók a DIRCMD környezeti változóban is lehetnek.\n"
STRING_DIR_HELP3 " A (%c) meghajtóban található kötetnek nincs címkéje.\n" STRING_DIR_HELP3 " A (%c) meghajtóban található kötetnek nincs címkéje.\n"
STRING_DIR_HELP4 " A kötet sorozatszáma: %04X-%04X\n" STRING_DIR_HELP4 " A kötet sorozatszáma: %04X-%04X\n"
STRING_DIR_HELP5 "\n Összes állomány:\n%16i Állomány(ok)% 14s bájt\n" STRING_DIR_HELP5 "\n Összes állomány:\n%16i Állomány(ok)% 14s bájt\n"
STRING_DIR_HELP6 "%16i Mappa %15s bájt" STRING_DIR_HELP6 "%16i Mappa %15s bájt szabad"
STRING_DIR_HELP7 "\n %s tartalma\n\n" STRING_DIR_HELP7 "\n %s tartalma\n\n"
STRING_DIR_HELP8 "%16i Állomány %14s bájt\n" STRING_DIR_HELP8 "%16i Állomány %14s bájt\n"
STRING_DIRSTACK_HELP1 "Megjegyzi az aktuális mappát, majd átvált egy máasikra.\n\n\ STRING_DIRSTACK_HELP1 "Megjegyzi az aktuális mappát, majd átvált egy máasikra.\n\n\

View file

@ -181,7 +181,7 @@ preset dengan mengawali setiap saklar dengan - (minus)--contohnya, /-W.\n"
STRING_DIR_HELP3 " Volume di drive %c tidak berlabel.\n" STRING_DIR_HELP3 " Volume di drive %c tidak berlabel.\n"
STRING_DIR_HELP4 " Nomor Seri Volume adalah %04X-%04X\n" STRING_DIR_HELP4 " Nomor Seri Volume adalah %04X-%04X\n"
STRING_DIR_HELP5 "\n Total File Didaftar:\n%16i File% 14s byte\n" STRING_DIR_HELP5 "\n Total File Didaftar:\n%16i File% 14s byte\n"
STRING_DIR_HELP6 "%16i Dir% 15s byte\n" STRING_DIR_HELP6 "%16i Dir% 15s byte tersisa\n"
STRING_DIR_HELP7 "\n Direktori %s\n\n" STRING_DIR_HELP7 "\n Direktori %s\n\n"
STRING_DIR_HELP8 "%16i File% 14s byte\n" STRING_DIR_HELP8 "%16i File% 14s byte\n"
STRING_DIRSTACK_HELP1 "Menyimpan direktori sekarang untuk digunakan oleh perintah POPD, lalu\n\ STRING_DIRSTACK_HELP1 "Menyimpan direktori sekarang untuk digunakan oleh perintah POPD, lalu\n\

View file

@ -178,7 +178,7 @@ le selezioni preimpostate mettendo - (trattino) prima della selezione per esempi
STRING_DIR_HELP3 " Il Volume nel disco %c non ha etichetta.\n" STRING_DIR_HELP3 " Il Volume nel disco %c non ha etichetta.\n"
STRING_DIR_HELP4 " Il numero di serie del Volume è %04X-%04X\n" STRING_DIR_HELP4 " Il numero di serie del Volume è %04X-%04X\n"
STRING_DIR_HELP5 "\n Numero dei file elencati:\n%16i % 14s byte\n" STRING_DIR_HELP5 "\n Numero dei file elencati:\n%16i % 14s byte\n"
STRING_DIR_HELP6 "%16i Cartelle% 15s byte\n" STRING_DIR_HELP6 "%16i Cartelle% 15s byte liberi\n"
STRING_DIR_HELP7 "\n Cartelle di %s\n\n" STRING_DIR_HELP7 "\n Cartelle di %s\n\n"
STRING_DIR_HELP8 "%16i File% 14s byte\n" STRING_DIR_HELP8 "%16i File% 14s byte\n"
STRING_DIRSTACK_HELP1 "Salva la cartella corrente per l'uso con il comando POPD, poi\n\ STRING_DIRSTACK_HELP1 "Salva la cartella corrente per l'uso con il comando POPD, poi\n\

View file

@ -179,7 +179,7 @@ forhåndsinnstilte brytere ved å sette en bindestrek (-) foran, for eksempel, /
STRING_DIR_HELP3 " Volumet i stasjon %c er uten navn.\n" STRING_DIR_HELP3 " Volumet i stasjon %c er uten navn.\n"
STRING_DIR_HELP4 " Volumserienummeret er %04X-%04X\n" STRING_DIR_HELP4 " Volumserienummeret er %04X-%04X\n"
STRING_DIR_HELP5 "\n Totalt filer listet:\n%16i fil(er)% 14s byte\n" STRING_DIR_HELP5 "\n Totalt filer listet:\n%16i fil(er)% 14s byte\n"
STRING_DIR_HELP6 "%16i mappe(r)% 15s byte\n" STRING_DIR_HELP6 "%16i mappe(r)% 15s byte ledig\n"
STRING_DIR_HELP7 "\n mappe av %s\n\n" STRING_DIR_HELP7 "\n mappe av %s\n\n"
STRING_DIR_HELP8 "%16i fil(er)% 14s byte\n" STRING_DIR_HELP8 "%16i fil(er)% 14s byte\n"
STRING_DIRSTACK_HELP1 "Lagrer gjeldende mappe for bruk av POPD kommando, og\n\ STRING_DIRSTACK_HELP1 "Lagrer gjeldende mappe for bruk av POPD kommando, og\n\

View file

@ -187,7 +187,7 @@ odwrócić działanie parametrów przedrostkiem - (myślnik)-- na przykład, /-W
STRING_DIR_HELP3 " Wolumin w napędzie %c nie posiada etykiety.\n" STRING_DIR_HELP3 " Wolumin w napędzie %c nie posiada etykiety.\n"
STRING_DIR_HELP4 " Numer seryjny woluminu to: %04X-%04X\n" STRING_DIR_HELP4 " Numer seryjny woluminu to: %04X-%04X\n"
STRING_DIR_HELP5 "\n Ogółem wyświetonych:\n%16i plik(ów)% 14s bajtów\n" STRING_DIR_HELP5 "\n Ogółem wyświetonych:\n%16i plik(ów)% 14s bajtów\n"
STRING_DIR_HELP6 "%16i katalog(ów)% 15s bajtów\n" STRING_DIR_HELP6 "%16i katalog(ów)% 15s bajtów wolne\n"
STRING_DIR_HELP7 "\n katalog %s\n\n" STRING_DIR_HELP7 "\n katalog %s\n\n"
STRING_DIR_HELP8 "%16i plik(ów)% 14s bajtów\n" STRING_DIR_HELP8 "%16i plik(ów)% 14s bajtów\n"
STRING_DIRSTACK_HELP1 "Przechowuje obecny katalog dla potrzeb komendy POPD, następnie\n\ STRING_DIRSTACK_HELP1 "Przechowuje obecny katalog dla potrzeb komendy POPD, następnie\n\

View file

@ -180,7 +180,7 @@ DELAY [/m]n\n\n\
STRING_DIR_HELP3 " Том в устройстве %c не имеет метки.\n" STRING_DIR_HELP3 " Том в устройстве %c не имеет метки.\n"
STRING_DIR_HELP4 " Серийный номер тома: %04X-%04X\n" STRING_DIR_HELP4 " Серийный номер тома: %04X-%04X\n"
STRING_DIR_HELP5 "\n Всего:\n%16i Файл(ов)% 14s байт\n" STRING_DIR_HELP5 "\n Всего:\n%16i Файл(ов)% 14s байт\n"
STRING_DIR_HELP6 "%16i Dir(s)% 15s байт\n" STRING_DIR_HELP6 "%16i Dir(s)% 15s байт свободно\n"
STRING_DIR_HELP7 "\n Каталог of %s\n\n" STRING_DIR_HELP7 "\n Каталог of %s\n\n"
STRING_DIR_HELP8 "%16i файл(ов)% 14s байт\n" STRING_DIR_HELP8 "%16i файл(ов)% 14s байт\n"
STRING_DIRSTACK_HELP1 "Сохраняет текущую директорию для использования командой POPD, затем\n\ STRING_DIRSTACK_HELP1 "Сохраняет текущую директорию для использования командой POPD, затем\n\

View file

@ -179,7 +179,7 @@ förinställda växlar med ett bindestreck (-) före, till exempel, /-W.\n"
STRING_DIR_HELP3 " Volumet i enhet %c är utan namn.\n" STRING_DIR_HELP3 " Volumet i enhet %c är utan namn.\n"
STRING_DIR_HELP4 " Volymens serienummer är %04X-%04X\n" STRING_DIR_HELP4 " Volymens serienummer är %04X-%04X\n"
STRING_DIR_HELP5 "\n Totalt filer listet:\n%16i fil(är)% 14s byte\n" STRING_DIR_HELP5 "\n Totalt filer listet:\n%16i fil(är)% 14s byte\n"
STRING_DIR_HELP6 "%16i mapp(ar)% 15s byte\n" STRING_DIR_HELP6 "%16i mapp(ar)% 15s byte ledigt\n"
STRING_DIR_HELP7 "\n mapp av %s\n\n" STRING_DIR_HELP7 "\n mapp av %s\n\n"
STRING_DIR_HELP8 "%16i fil(er)% 14s byte\n" STRING_DIR_HELP8 "%16i fil(er)% 14s byte\n"
STRING_DIRSTACK_HELP1 "Sparar aktuell mapp for användning av POPD kommandot, och\n\ STRING_DIRSTACK_HELP1 "Sparar aktuell mapp for användning av POPD kommandot, och\n\

View file

@ -302,7 +302,7 @@ function(spec2def _dllname _spec_file)
endfunction() endfunction()
macro(macro_mc FLAG FILE) macro(macro_mc FLAG FILE)
set(COMMAND_MC ${CMAKE_MC_COMPILER} ${FLAG} -r ${REACTOS_BINARY_DIR}/include/reactos -h ${REACTOS_BINARY_DIR}/include/reactos ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.mc) set(COMMAND_MC ${CMAKE_MC_COMPILER} ${FLAG} -b ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.mc -r ${REACTOS_BINARY_DIR}/include/reactos -h ${REACTOS_BINARY_DIR}/include/reactos)
endmacro() endmacro()
#pseh workaround #pseh workaround

View file

@ -966,6 +966,10 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
PSAMPR_USER_INFO_BUFFER UserInfo = NULL; PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
UNICODE_STRING LogonServer; UNICODE_STRING LogonServer;
BOOLEAN SessionCreated = FALSE; BOOLEAN SessionCreated = FALSE;
LARGE_INTEGER LogonTime;
// LARGE_INTEGER AccountExpires;
LARGE_INTEGER PasswordMustChange;
LARGE_INTEGER PasswordLastSet;
NTSTATUS Status; NTSTATUS Status;
TRACE("()\n"); TRACE("()\n");
@ -1005,6 +1009,10 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
/* Get the logon time */
NtQuerySystemTime(&LogonTime);
/* Get the domain SID */
Status = GetDomainSid(&AccountDomainSid); Status = GetDomainSid(&AccountDomainSid);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -1080,9 +1088,20 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
goto done; goto done;
} }
TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer); TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);
/* Check the password */
if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
{
Status = MsvpCheckPassword(&(LogonInfo->Password),
UserInfo);
if (!NT_SUCCESS(Status))
{
TRACE("MsvpCheckPassword failed (Status %08lx)\n", Status);
goto done;
}
}
/* Check account restrictions for non-administrator accounts */ /* Check account restrictions for non-administrator accounts */
if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN) if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
{ {
@ -1098,29 +1117,48 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
/* Check if the account has been locked */ /* Check if the account has been locked */
if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED) if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
{ {
ERR("Account disabled!\n"); ERR("Account locked!\n");
*SubStatus = STATUS_ACCOUNT_LOCKED_OUT; *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
Status = STATUS_ACCOUNT_RESTRICTION; Status = STATUS_ACCOUNT_RESTRICTION;
goto done; goto done;
} }
/* FIXME: more checks */ #if 0
// *SubStatus = STATUS_PASSWORD_EXPIRED; /* Check if the account expired */
// *SubStatus = STATUS_INVALID_LOGON_HOURS; AccountExpires.LowPart = UserInfo->All.AccountExpires.LowPart;
// *SubStatus = STATUS_INVALID_WORKSTATION; AccountExpires.HighPart = UserInfo->All.AccountExpires.HighPart;
} if (AccountExpires.QuadPart != 0 &&
LogonTime.QuadPart >= AccountExpires.QuadPart)
/* Check the password */
if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
{ {
Status = MsvpCheckPassword(&(LogonInfo->Password), ERR("Account expired!\n");
UserInfo); *SubStatus = STATUS_ACCOUNT_EXPIRED;
if (!NT_SUCCESS(Status)) Status = STATUS_ACCOUNT_RESTRICTION;
{
TRACE("MsvpCheckPassword failed (Status %08lx)\n", Status);
goto done; goto done;
} }
#endif
/* Check if the password expired */
PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
{
ERR("Password expired!\n");
if (PasswordLastSet.QuadPart == 0)
*SubStatus = STATUS_PASSWORD_MUST_CHANGE;
else
*SubStatus = STATUS_PASSWORD_EXPIRED;
Status = STATUS_ACCOUNT_RESTRICTION;
goto done;
}
/* FIXME: more checks */
// STATUS_INVALID_LOGON_HOURS;
// STATUS_INVALID_WORKSTATION;
} }
/* Return logon information */ /* Return logon information */
@ -1220,7 +1258,7 @@ done:
Status = STATUS_LOGON_FAILURE; Status = STATUS_LOGON_FAILURE;
} }
TRACE("LsaApLogonUser done (Status %08lx)\n", Status); TRACE("LsaApLogonUser done (Status 0x%08lx SubStatus 0x%08lx)\n", Status, *SubStatus);
return Status; return Status;
} }

View file

@ -437,6 +437,7 @@ StartProcedure(
Status = EnableInterrupts(DeviceExtension, FlagsToDisable, FlagsToEnable); Status = EnableInterrupts(DeviceExtension, FlagsToDisable, FlagsToEnable);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
WARN_(I8042PRT, "EnableInterrupts failed: %lx\n", Status);
DeviceExtension->Flags &= ~(KEYBOARD_PRESENT | MOUSE_PRESENT); DeviceExtension->Flags &= ~(KEYBOARD_PRESENT | MOUSE_PRESENT);
return Status; return Status;
} }
@ -454,6 +455,10 @@ StartProcedure(
{ {
DeviceExtension->Flags |= KEYBOARD_INITIALIZED; DeviceExtension->Flags |= KEYBOARD_INITIALIZED;
} }
else
{
WARN_(I8042PRT, "i8042ConnectKeyboardInterrupt failed: %lx\n", Status);
}
} }
if (DeviceExtension->Flags & MOUSE_PRESENT && if (DeviceExtension->Flags & MOUSE_PRESENT &&
@ -467,6 +472,10 @@ StartProcedure(
{ {
DeviceExtension->Flags |= MOUSE_INITIALIZED; DeviceExtension->Flags |= MOUSE_INITIALIZED;
} }
else
{
WARN_(I8042PRT, "i8042ConnectMouseInterrupt failed: %lx\n", Status);
}
/* Start the mouse */ /* Start the mouse */
Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt); Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt);
@ -533,7 +542,7 @@ i8042PnpStartDevice(
{ {
if (ResourceDescriptor->u.Port.Length == 1) if (ResourceDescriptor->u.Port.Length == 1)
{ {
/* We assume that the first ressource will /* We assume that the first resource will
* be the control port and the second one * be the control port and the second one
* will be the data port... * will be the data port...
*/ */
@ -551,8 +560,8 @@ i8042PnpStartDevice(
} }
else else
{ {
WARN_(I8042PRT, "Too much I/O ranges provided: 0x%lx\n", ResourceDescriptor->u.Port.Length); /* FIXME: implement PS/2 Active Multiplexing */
return STATUS_INVALID_PARAMETER; ERR_(I8042PRT, "Unhandled I/O ranges provided: 0x%lx\n", ResourceDescriptor->u.Port.Length);
} }
} }
else else

View file

@ -17,7 +17,7 @@
* Notes: * Notes:
* This driver was obsoleted in Windows XP and most functions * This driver was obsoleted in Windows XP and most functions
* became pure stubs. But some of them were retained for backward * became pure stubs. But some of them were retained for backward
* compatibilty with existing drivers. * compatibility with existing drivers.
* *
* Preserved functions: * Preserved functions:
* *

View file

@ -648,7 +648,7 @@ IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
ASSERT(!(DeviceNode->Flags & DNF_DISABLED)); ASSERT(!(DeviceNode->Flags & DNF_DISABLED));
/* Build the I/O stack locaiton */ /* Build the I/O stack location */
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION)); RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP; Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_START_DEVICE; Stack.MinorFunction = IRP_MN_START_DEVICE;

View file

@ -271,7 +271,7 @@ IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
Menu->MenuInfo.dwMenuData = 0; /* Default */ Menu->MenuInfo.dwMenuData = 0; /* Default */
Menu->MenuInfo.Self = *Handle; Menu->MenuInfo.Self = *Handle;
Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM; Menu->MenuInfo.FocusedItem = NO_SELECTED_ITEM;
Menu->MenuInfo.Flags = (IsMenuBar ? 0 : MF_POPUP); Menu->MenuInfo.Flags = (IsMenuBar ? 0 : MNF_POPUP);
Menu->MenuInfo.Wnd = NULL; Menu->MenuInfo.Wnd = NULL;
Menu->MenuInfo.WndOwner = NULL; Menu->MenuInfo.WndOwner = NULL;
Menu->MenuInfo.Height = 0; Menu->MenuInfo.Height = 0;
@ -454,7 +454,17 @@ IntSetMenuInfo(PMENU_OBJECT Menu, PROSMENUINFO lpmi)
Menu->MenuInfo.dwStyle = lpmi->dwStyle; Menu->MenuInfo.dwStyle = lpmi->dwStyle;
if(lpmi->fMask & MIM_APPLYTOSUBMENUS) if(lpmi->fMask & MIM_APPLYTOSUBMENUS)
{ {
/* FIXME */ int i;
PMENU_ITEM item = Menu->MenuItemList;
for ( i = Menu->MenuInfo.MenuItemCount; i; i--, item = item->Next)
{
if ( item->hSubMenu )
{
PMENU_OBJECT SubMenu;
if (!(SubMenu = UserGetMenuObject(item->hSubMenu))) continue;
IntSetMenuInfo( SubMenu, lpmi);
}
}
} }
if (sizeof(MENUINFO) < lpmi->cbSize) if (sizeof(MENUINFO) < lpmi->cbSize)
{ {
@ -741,7 +751,7 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF
SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu); SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu);
if (SubMenuObject != NULL) if (SubMenuObject != NULL)
{ {
SubMenuObject->MenuInfo.Flags |= MF_POPUP; SubMenuObject->MenuInfo.Flags |= MNF_POPUP;
} }
} }
} }
@ -775,7 +785,7 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF
} }
else else
{ {
if (0 == (MenuObject->MenuInfo.Flags & MF_SYSMENU)) if (0 == (MenuObject->MenuInfo.Flags & MNF_SYSDESKMN))
{ {
MenuItem->fType |= MF_SEPARATOR; MenuItem->fType |= MF_SEPARATOR;
} }
@ -1724,6 +1734,50 @@ CLEANUP:
END_CLEANUP; END_CLEANUP;
} }
BOOL FASTCALL
IntGetMenuItemRect(
PWND pWnd,
PMENU_OBJECT Menu,
UINT uItem,
PRECTL Rect)
{
LONG XMove, YMove;
PMENU_ITEM MenuItem;
int p = 0;
if (!pWnd)
{
HWND hWnd = Menu->MenuInfo.Wnd;
if (!(pWnd = UserGetWindowObject(hWnd))) return FALSE;
}
if ((p = IntGetMenuItemByFlag(Menu, uItem, MF_BYPOSITION, NULL, &MenuItem, NULL)) > -1)
*Rect = MenuItem->Rect;
else
{
ERR("Failed Item Lookup! %d\n", p);
return FALSE;
}
if (Menu->MenuInfo.Flags & MNF_POPUP)
{
XMove = pWnd->rcClient.left;
YMove = pWnd->rcClient.top;
}
else
{
XMove = pWnd->rcWindow.left;
YMove = pWnd->rcWindow.top;
}
Rect->left += XMove;
Rect->top += YMove;
Rect->right += XMove;
Rect->bottom += YMove;
return TRUE;
}
/* /*
* @implemented * @implemented
*/ */
@ -1734,219 +1788,126 @@ NtUserGetMenuBarInfo(
LONG idItem, LONG idItem,
PMENUBARINFO pmbi) PMENUBARINFO pmbi)
{ {
BOOL Res = TRUE; PWND pWnd;
PMENU_OBJECT MenuObject;
PMENU_ITEM mi;
PWND WindowObject;
HMENU hMenu; HMENU hMenu;
POINT Offset;
RECTL Rect;
MENUBARINFO kmbi; MENUBARINFO kmbi;
BOOL Ret;
NTSTATUS Status = STATUS_SUCCESS;
PMENU_OBJECT Menu = NULL;
DECLARE_RETURN(BOOL); DECLARE_RETURN(BOOL);
TRACE("Enter NtUserGetMenuBarInfo\n"); TRACE("Enter NtUserGetMenuBarInfo\n");
UserEnterShared(); UserEnterShared();
if (!(WindowObject = UserGetWindowObject(hwnd))) if (!(pWnd = UserGetWindowObject(hwnd)))
{ {
EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
RETURN(FALSE); RETURN(FALSE);
} }
hMenu = (HMENU)(DWORD_PTR)WindowObject->IDMenu; switch (idObject)
if (!(MenuObject = UserGetMenuObject(hMenu)))
{ {
case OBJID_CLIENT:
if (!pWnd->pcls->fnid)
RETURN(FALSE);
if (pWnd->pcls->fnid != FNID_MENU)
{
WARN("called on invalid window: %d\n", pWnd->pcls->fnid);
EngSetLastError(ERROR_INVALID_MENU_HANDLE); EngSetLastError(ERROR_INVALID_MENU_HANDLE);
RETURN(FALSE); RETURN(FALSE);
} }
// Windows does this! Wine checks for Atom and uses GetWindowLongPtrW.
hMenu = (HMENU)co_IntSendMessage(hwnd, MN_GETHMENU, 0, 0);
break;
case OBJID_MENU:
hMenu = UlongToHandle(pWnd->IDMenu);
break;
case OBJID_SYSMENU:
if (!(pWnd->style & WS_SYSMENU)) RETURN(FALSE);
Menu = IntGetSystemMenu(pWnd, FALSE, FALSE);
hMenu = Menu->MenuInfo.Self;
break;
default:
RETURN(FALSE);
}
if (pmbi->cbSize != sizeof(MENUBARINFO)) if (!hMenu)
RETURN(FALSE);
_SEH2_TRY
{
kmbi.cbSize = pmbi->cbSize;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
kmbi.cbSize = 0;
}
_SEH2_END
if (kmbi.cbSize != sizeof(MENUBARINFO))
{ {
EngSetLastError(ERROR_INVALID_PARAMETER); EngSetLastError(ERROR_INVALID_PARAMETER);
RETURN(FALSE); RETURN(FALSE);
} }
kmbi.cbSize = sizeof(MENUBARINFO); if (!Menu) Menu = UserGetMenuObject(hMenu);
kmbi.fBarFocused = FALSE; if (!Menu)
kmbi.fFocused = FALSE; RETURN(FALSE);
kmbi.hwndMenu = NULL;
switch (idObject) if (idItem < 0 || idItem > Menu->MenuInfo.MenuItemCount)
RETURN(FALSE);
RECTL_vSetEmptyRect(&kmbi.rcBar);
if (idItem == 0)
{ {
case OBJID_MENU: Ret = IntGetMenuItemRect(pWnd, Menu, -1, &kmbi.rcBar);
kmbi.rcBar.right = kmbi.rcBar.left + Menu->MenuInfo.Width;
kmbi.rcBar.bottom = kmbi.rcBar.top + Menu->MenuInfo.Height;
ERR("idItem 0 %d\n",Ret);
}
else
{
Ret = IntGetMenuItemRect(pWnd, Menu, idItem-1, &kmbi.rcBar);
ERR("idItem X %d\n", Ret);
}
kmbi.hMenu = hMenu;
kmbi.hwndMenu = NULL;
//kmbi.fBarFocused = top_popup_hmenu == hMenu;
if (idItem)
{ {
PMENU_OBJECT SubMenuObject; PMENU_OBJECT SubMenuObject;
kmbi.hMenu = hMenu; kmbi.fFocused = Menu->MenuInfo.FocusedItem == idItem-1;
if (idItem) /* Non-Zero-Based. */
{
if (IntGetMenuItemByFlag(MenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
kmbi.rcBar = mi->Rect;
else
{
Res = FALSE;
break;
}
}
else
{
/* If items is zero we assume info for the menu itself. */
if (!(IntGetClientOrigin(WindowObject, &Offset)))
{
Res = FALSE;
break;
}
Rect.left = Offset.x;
Rect.right = Offset.x + MenuObject->MenuInfo.Width;
Rect.bottom = Offset.y;
Rect.top = Offset.y - MenuObject->MenuInfo.Height;
kmbi.rcBar = Rect;
TRACE("Rect top = %d bottom = %d left = %d right = %d \n",
Rect.top, Rect.bottom, Rect.left, Rect.right);
}
if (idItem)
{
if (idItem-1 == MenuObject->MenuInfo.FocusedItem)
kmbi.fFocused = TRUE;
}
if (MenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
kmbi.fBarFocused = TRUE;
if (MenuObject->MenuItemList) if ( kmbi.fFocused && Menu->MenuItemList->hSubMenu )
{ {
SubMenuObject = UserGetMenuObject(MenuObject->MenuItemList->hSubMenu); SubMenuObject = UserGetMenuObject(Menu->MenuItemList->hSubMenu);
if(SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd; if (SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd;
} }
TRACE("OBJID_MENU, idItem = %d\n",idItem);
break;
} }
case OBJID_CLIENT: /* else
{ {
PMENU_OBJECT SubMenuObject, XSubMenuObject; kmbi.fFocused = kmbi.fBarFocused;
HMENU hMenuChk; }
// Windows does this! Wine checks for Atom and uses GetWindowLongPtrW. */
hMenuChk = (HMENU)co_IntSendMessage(hwnd, MN_GETHMENU, 0, 0); _SEH2_TRY
{
RtlCopyMemory(pmbi, &kmbi, sizeof(MENUBARINFO));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!(MenuObject = UserGetMenuObject(hMenuChk))) if (!NT_SUCCESS(Status))
{
ERR("Window does not have a Popup Menu!\n");
EngSetLastError(ERROR_INVALID_MENU_HANDLE);
RETURN(FALSE);
}
SubMenuObject = UserGetMenuObject(MenuObject->MenuItemList->hSubMenu);
if(SubMenuObject) kmbi.hMenu = SubMenuObject->MenuInfo.Self;
else
{
Res = FALSE;
ERR("OBJID_CLIENT, No SubMenu!\n");
break;
}
if (idItem)
{
if (IntGetMenuItemByFlag(SubMenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
kmbi.rcBar = mi->Rect;
else
{
Res = FALSE;
break;
}
}
else
{
PWND SubWinObj;
if (!(SubWinObj = UserGetWindowObject(SubMenuObject->MenuInfo.Wnd)))
{
Res = FALSE;
break;
}
if (!(IntGetClientOrigin(SubWinObj, &Offset)))
{
Res = FALSE;
break;
}
Rect.left = Offset.x;
Rect.right = Offset.x + SubMenuObject->MenuInfo.Width;
Rect.top = Offset.y;
Rect.bottom = Offset.y + SubMenuObject->MenuInfo.Height;
kmbi.rcBar = Rect;
}
if (idItem)
{
if (idItem-1 == SubMenuObject->MenuInfo.FocusedItem)
kmbi.fFocused = TRUE;
}
if (SubMenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
kmbi.fBarFocused = TRUE;
XSubMenuObject = UserGetMenuObject(SubMenuObject->MenuItemList->hSubMenu);
if (XSubMenuObject) kmbi.hwndMenu = XSubMenuObject->MenuInfo.Wnd;
TRACE("OBJID_CLIENT, idItem = %d\n",idItem);
break;
}
case OBJID_SYSMENU:
{
PMENU_OBJECT SysMenuObject, SubMenuObject;
if(!(SysMenuObject = IntGetSystemMenu(WindowObject, FALSE, FALSE)))
{
Res = FALSE;
break;
}
kmbi.hMenu = SysMenuObject->MenuInfo.Self;
if (idItem)
{
if (IntGetMenuItemByFlag(SysMenuObject, idItem-1, MF_BYPOSITION, NULL, &mi, NULL) > -1)
kmbi.rcBar = mi->Rect;
else
{
Res = FALSE;
break;
}
}
else
{
PWND SysWinObj;
if (!(SysWinObj = UserGetWindowObject(SysMenuObject->MenuInfo.Wnd)))
{
Res = FALSE;
break;
}
if (!(IntGetClientOrigin(SysWinObj, &Offset)))
{
Res = FALSE;
break;
}
Rect.left = Offset.x;
Rect.right = Offset.x + SysMenuObject->MenuInfo.Width;
Rect.top = Offset.y;
Rect.bottom = Offset.y + SysMenuObject->MenuInfo.Height;
kmbi.rcBar = Rect;
}
if (idItem)
{
if (idItem-1 == SysMenuObject->MenuInfo.FocusedItem)
kmbi.fFocused = TRUE;
}
if (SysMenuObject->MenuInfo.FocusedItem != NO_SELECTED_ITEM)
kmbi.fBarFocused = TRUE;
SubMenuObject = UserGetMenuObject(SysMenuObject->MenuItemList->hSubMenu);
if(SubMenuObject) kmbi.hwndMenu = SubMenuObject->MenuInfo.Wnd;
TRACE("OBJID_SYSMENU, idItem = %d\n",idItem);
break;
}
default:
Res = FALSE;
ERR("Unknown idObject = %d, idItem = %d\n",idObject,idItem);
}
if (Res)
{
NTSTATUS Status = MmCopyToCaller(pmbi, &kmbi, sizeof(MENUBARINFO));
if (! NT_SUCCESS(Status))
{ {
SetLastNtError(Status); SetLastNtError(Status);
RETURN(FALSE); RETURN(FALSE);
} }
}
RETURN(Res); RETURN(TRUE);
CLEANUP: CLEANUP:
TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_); TRACE("Leave NtUserGetMenuBarInfo, ret=%i\n",_ret_);
@ -2002,9 +1963,9 @@ NtUserGetMenuItemRect(
PWND ReferenceWnd; PWND ReferenceWnd;
LONG XMove, YMove; LONG XMove, YMove;
RECTL Rect; RECTL Rect;
NTSTATUS Status;
PMENU_OBJECT Menu; PMENU_OBJECT Menu;
PMENU_ITEM MenuItem; PMENU_ITEM MenuItem;
NTSTATUS Status = STATUS_SUCCESS;
DECLARE_RETURN(BOOL); DECLARE_RETURN(BOOL);
TRACE("Enter NtUserGetMenuItemRect\n"); TRACE("Enter NtUserGetMenuItemRect\n");
@ -2029,7 +1990,7 @@ NtUserGetMenuItemRect(
if (!(ReferenceWnd = UserGetWindowObject(hWnd))) RETURN( FALSE); if (!(ReferenceWnd = UserGetWindowObject(hWnd))) RETURN( FALSE);
if(MenuItem->hSubMenu) if (Menu->MenuInfo.Flags & MNF_POPUP)
{ {
XMove = ReferenceWnd->rcClient.left; XMove = ReferenceWnd->rcClient.left;
YMove = ReferenceWnd->rcClient.top; YMove = ReferenceWnd->rcClient.top;
@ -2045,13 +2006,22 @@ NtUserGetMenuItemRect(
Rect.right += XMove; Rect.right += XMove;
Rect.bottom += YMove; Rect.bottom += YMove;
Status = MmCopyToCaller(lprcItem, &Rect, sizeof(RECT)); _SEH2_TRY
if (! NT_SUCCESS(Status)) {
RtlCopyMemory(lprcItem, &Rect, sizeof(RECTL));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{ {
SetLastNtError(Status); SetLastNtError(Status);
RETURN( FALSE); RETURN(FALSE);
} }
RETURN( TRUE); RETURN(TRUE);
CLEANUP: CLEANUP:
TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_); TRACE("Leave NtUserGetMenuItemRect, ret=%i\n",_ret_);

View file

@ -931,7 +931,7 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
if(NewMenu) if(NewMenu)
{ {
Window->SystemMenu = NewMenu->MenuInfo.Self; Window->SystemMenu = NewMenu->MenuInfo.Self;
NewMenu->MenuInfo.Flags |= MF_SYSMENU; NewMenu->MenuInfo.Flags |= MNF_SYSDESKMN;
NewMenu->MenuInfo.Wnd = Window->head.h; NewMenu->MenuInfo.Wnd = Window->head.h;
ret = NewMenu; ret = NewMenu;
//IntReleaseMenuObject(NewMenu); //IntReleaseMenuObject(NewMenu);
@ -950,7 +950,7 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
UserDestroyMenu(hSysMenu); UserDestroyMenu(hSysMenu);
return NULL; return NULL;
} }
SysMenu->MenuInfo.Flags |= MF_SYSMENU; SysMenu->MenuInfo.Flags |= MNF_SYSDESKMN;
SysMenu->MenuInfo.Wnd = Window->head.h; SysMenu->MenuInfo.Wnd = Window->head.h;
hNewMenu = co_IntLoadSysMenuTemplate(); hNewMenu = co_IntLoadSysMenuTemplate();
if(!hNewMenu) if(!hNewMenu)
@ -970,7 +970,8 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
NewMenu = IntCloneMenu(Menu); NewMenu = IntCloneMenu(Menu);
if(NewMenu) if(NewMenu)
{ {
NewMenu->MenuInfo.Flags |= MF_SYSMENU | MF_POPUP; NewMenu->MenuInfo.Flags |= MNF_SYSDESKMN | MNF_POPUP;
NewMenu->MenuInfo.dwStyle = MNS_CHECKORBMP;
IntReleaseMenuObject(NewMenu); IntReleaseMenuObject(NewMenu);
UserSetMenuDefaultItem(NewMenu, SC_CLOSE, FALSE); UserSetMenuDefaultItem(NewMenu, SC_CLOSE, FALSE);
@ -1426,7 +1427,7 @@ IntSetSystemMenu(PWND Window, PMENU_OBJECT Menu)
OldMenu = IntGetMenuObject(Window->SystemMenu); OldMenu = IntGetMenuObject(Window->SystemMenu);
if(OldMenu) if(OldMenu)
{ {
OldMenu->MenuInfo.Flags &= ~ MF_SYSMENU; OldMenu->MenuInfo.Flags &= ~ MNF_SYSDESKMN;
IntReleaseMenuObject(OldMenu); IntReleaseMenuObject(OldMenu);
} }
} }
@ -1435,7 +1436,7 @@ IntSetSystemMenu(PWND Window, PMENU_OBJECT Menu)
{ {
/* FIXME: Check window style, propably return FALSE? */ /* FIXME: Check window style, propably return FALSE? */
Window->SystemMenu = Menu->MenuInfo.Self; Window->SystemMenu = Menu->MenuInfo.Self;
Menu->MenuInfo.Flags |= MF_SYSMENU; Menu->MenuInfo.Flags |= MNF_SYSDESKMN;
} }
else else
Window->SystemMenu = (HMENU)0; Window->SystemMenu = (HMENU)0;

View file

@ -36,6 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu);
#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */ #define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */ #define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
/* top and bottom margins for popup menus */
#define MENU_TOP_MARGIN 3
#define MENU_BOTTOM_MARGIN 2
#define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR) #define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)
@ -46,10 +49,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu);
#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1)) #define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
#define IS_SYSTEM_MENU(MenuInfo) \ #define IS_SYSTEM_MENU(MenuInfo) \
(0 == ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU)) (0 == ((MenuInfo)->Flags & MNF_POPUP) && 0 != ((MenuInfo)->Flags & MNF_SYSDESKMN))
#define IS_SYSTEM_POPUP(MenuInfo) \ #define IS_SYSTEM_POPUP(MenuInfo) \
(0 != ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU)) (0 != ((MenuInfo)->Flags & MNF_POPUP) && 0 != ((MenuInfo)->Flags & MNF_SYSDESKMN))
#define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags)) #define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags))
@ -507,6 +510,7 @@ static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
PROSMENUITEMINFO Items, ItemInfo; PROSMENUITEMINFO Items, ItemInfo;
LRESULT MenuChar; LRESULT MenuChar;
UINT i; UINT i;
WORD Flags = 0;
TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo); TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
@ -546,8 +550,11 @@ static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
} }
} }
Flags |= MenuInfo->Flags & MNF_POPUP ? MF_POPUP : 0;
Flags |= MenuInfo->Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0;
MenuChar = SendMessageW(WndOwner, WM_MENUCHAR, MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
MAKEWPARAM(Key, MenuInfo->Flags), (LPARAM) MenuInfo->Self); MAKEWPARAM(Key, Flags), (LPARAM) MenuInfo->Self);
if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar); if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar);
if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2); if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2);
} }
@ -1299,7 +1306,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
HBITMAP bm; HBITMAP bm;
INT y = rect.top + rect.bottom; INT y = rect.top + rect.bottom;
RECT rc = rect; RECT rc = rect;
int checked = FALSE; BOOL checked = FALSE;
UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK ); UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
/* Draw the check mark /* Draw the check mark
@ -1547,6 +1554,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
POINT pt; POINT pt;
HMONITOR monitor; HMONITOR monitor;
MONITORINFO info; MONITORINFO info;
DWORD ex_style = 0;
TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n", TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
hwndOwner, hmenu, id, x, y, xanchor, yanchor); hwndOwner, hmenu, id, x, y, xanchor, yanchor);
@ -1588,6 +1596,11 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
info.cbSize = sizeof(info); info.cbSize = sizeof(info);
GetMonitorInfoW( monitor, &info ); GetMonitorInfoW( monitor, &info );
if (flags & TPM_LAYOUTRTL)
{
ex_style = WS_EX_LAYOUTRTL;
flags ^= TPM_RIGHTALIGN;
}
if( flags & TPM_RIGHTALIGN ) x -= width; if( flags & TPM_RIGHTALIGN ) x -= width;
if( flags & TPM_CENTERALIGN ) x -= width / 2; if( flags & TPM_CENTERALIGN ) x -= width / 2;
@ -1615,7 +1628,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
if( y < info.rcMonitor.top ) y = info.rcMonitor.top; if( y < info.rcMonitor.top ) y = info.rcMonitor.top;
/* NOTE: In Windows, top menu popup is not owned. */ /* NOTE: In Windows, top menu popup is not owned. */
MenuInfo.Wnd = CreateWindowExW( 0, WC_MENU, NULL, MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL,
WS_POPUP, x, y, width, height, WS_POPUP, x, y, width, height,
hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
(LPVOID) MenuInfo.Self); (LPVOID) MenuInfo.Self);
@ -1650,7 +1663,7 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn
if (!hmenu || !hmenu->MenuItemCount || !hmenu->Wnd) return; if (!hmenu || !hmenu->MenuItemCount || !hmenu->Wnd) return;
if (hmenu->FocusedItem == wIndex) return; if (hmenu->FocusedItem == wIndex) return;
if (hmenu->Flags & MF_POPUP) hdc = GetDC(hmenu->Wnd); if (hmenu->Flags & MNF_POPUP) hdc = GetDC(hmenu->Wnd);
else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW); else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW);
if (!top_popup) { if (!top_popup) {
top_popup = hmenu->Wnd; top_popup = hmenu->Wnd;
@ -1671,7 +1684,7 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn
MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo); MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo);
} }
MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, &ItemInfo, MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, &ItemInfo,
hmenu->Height, ! (hmenu->Flags & MF_POPUP), hmenu->Height, !(hmenu->Flags & MNF_POPUP),
ODA_SELECT); ODA_SELECT);
} }
@ -1688,20 +1701,24 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn
ItemInfo.fState |= MF_HILITE; ItemInfo.fState |= MF_HILITE;
MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo); MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo);
MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc,
&ItemInfo, hmenu->Height, ! (hmenu->Flags & MF_POPUP), &ItemInfo, hmenu->Height, !(hmenu->Flags & MNF_POPUP),
ODA_SELECT); ODA_SELECT);
} }
if (sendMenuSelect) if (sendMenuSelect)
{ {
SendMessageW(hwndOwner, WM_MENUSELECT, WPARAM wParam = MAKEWPARAM( ItemInfo.hSubMenu ? wIndex : ItemInfo.wID,
MAKELONG(ItemInfo.hSubMenu ? wIndex : ItemInfo.wID, ItemInfo.fType | ItemInfo.fState |
ItemInfo.fType | ItemInfo.fState | MF_MOUSESELECT | (ItemInfo.hSubMenu ? MF_POPUP : 0) |
(hmenu->Flags & (MF_SYSMENU|MF_POPUP))), (LPARAM) hmenu->Self); (hmenu->Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) );
SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) hmenu->Self);
} }
} }
} }
else if (sendMenuSelect) { else if (sendMenuSelect)
if(topmenu) { {
if(topmenu)
{
int pos; int pos;
pos = MenuFindSubMenu(&topmenu, hmenu->Self); pos = MenuFindSubMenu(&topmenu, hmenu->Self);
if (pos != NO_SELECTED_ITEM) if (pos != NO_SELECTED_ITEM)
@ -1709,11 +1726,11 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn
if (MenuGetRosMenuInfo(&TopMenuInfo, topmenu) if (MenuGetRosMenuInfo(&TopMenuInfo, topmenu)
&& MenuGetRosMenuItemInfo(topmenu, pos, &ItemInfo)) && MenuGetRosMenuItemInfo(topmenu, pos, &ItemInfo))
{ {
SendMessageW(hwndOwner, WM_MENUSELECT, WPARAM wParam = MAKEWPARAM( Pos, ItemInfo.fType | ItemInfo.fState |
MAKELONG(Pos, ItemInfo.fType | ItemInfo.fState (ItemInfo.hSubMenu ? MF_POPUP : 0) |
| MF_MOUSESELECT (TopMenuInfo.Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) );
| (TopMenuInfo.Flags & MF_SYSMENU)),
(LPARAM) topmenu); SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) topmenu);
} }
} }
} }
@ -1995,11 +2012,11 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
* *
* NOTE: flags is equivalent to the mtOption field * NOTE: flags is equivalent to the mtOption field
*/ */
static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode ) static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu)
{ {
WORD flags, id = 0; WORD flags, id = 0;
HMENU hSubMenu; HMENU hSubMenu;
LPCSTR str; LPCWSTR str;
BOOL end = FALSE; BOOL end = FALSE;
do do
@ -2016,46 +2033,19 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
id = GET_WORD(res); id = GET_WORD(res);
res += sizeof(WORD); res += sizeof(WORD);
} }
str = res; str = (LPCWSTR)res;
if(!unicode) res += (strlenW(str) + 1) * sizeof(WCHAR);
res += strlen(str) + 1;
else
res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
if (flags & MF_POPUP) if (flags & MF_POPUP)
{ {
hSubMenu = CreatePopupMenu(); hSubMenu = CreatePopupMenu();
if(!hSubMenu) return NULL; if(!hSubMenu) return NULL;
if(!(res = MENU_ParseResource(res, hSubMenu, unicode))) if(!(res = MENU_ParseResource(res, hSubMenu))) return NULL;
return NULL; AppendMenuW(hMenu, flags, (UINT_PTR)hSubMenu, (LPCWSTR)str);
if(!unicode)
AppendMenuA(hMenu, flags, (UINT)hSubMenu, str);
else
AppendMenuW(hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str);
} }
else /* Not a popup */ else /* Not a popup */
{ {
if(!unicode) AppendMenuW(hMenu, flags, id, *(LPCWSTR)str ? (LPCWSTR)str : NULL);
{
if (*str == 0)
flags = MF_SEPARATOR;
}
else
{
if (*(LPCWSTR)str == 0)
flags = MF_SEPARATOR;
}
if (flags & MF_SEPARATOR)
{
if (!(flags & (MF_GRAYED | MF_DISABLED)))
flags |= MF_GRAYED | MF_DISABLED;
}
if(!unicode)
AppendMenuA(hMenu, flags, id, *str ? str : NULL);
else
AppendMenuW(hMenu, flags, id,
*(LPCWSTR)str ? (LPCWSTR)str : NULL);
} }
} while(!end); } while(!end);
return res; return res;
@ -2071,10 +2061,10 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu) static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu)
{ {
WORD resinfo; WORD resinfo;
MENUITEMINFOW mii;
do do
{ {
MENUITEMINFOW mii;
mii.cbSize = sizeof(mii); mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE; mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
mii.fType = GET_DWORD(res); mii.fType = GET_DWORD(res);
@ -2114,13 +2104,12 @@ static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu)
return NULL; return NULL;
} }
mii.fMask |= MIIM_SUBMENU; mii.fMask |= MIIM_SUBMENU;
/*mii.wID = (UINT)mii.hSubMenu;*/
} }
else if (!mii.dwTypeData[0]) else if (!mii.dwTypeData[0] && !(mii.fType & MF_SEPARATOR))
{
mii.fType |= MF_SEPARATOR; mii.fType |= MF_SEPARATOR;
}
if (!InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii)) InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
ERR("InsertMenuItemW failed\n");
} while (!(resinfo & MF_END)); } while (!(resinfo & MF_END));
return res; return res;
} }
@ -2327,7 +2316,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
if (0 == (Flags & TPM_NONOTIFY)) if (0 == (Flags & TPM_NONOTIFY))
{ {
SendMessageW(WndOwner, WM_INITMENUPOPUP, (WPARAM) ItemInfo.hSubMenu, SendMessageW(WndOwner, WM_INITMENUPOPUP, (WPARAM) ItemInfo.hSubMenu,
MAKELONG(MenuInfo->FocusedItem, IS_SYSTEM_MENU(MenuInfo))); MAKELPARAM(MenuInfo->FocusedItem, IS_SYSTEM_MENU(MenuInfo)));
} }
if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo))
@ -2340,7 +2329,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
/* correct item if modified as a reaction to WM_INITMENUPOPUP message */ /* correct item if modified as a reaction to WM_INITMENUPOPUP message */
if (0 == (ItemInfo.fState & MF_HILITE)) if (0 == (ItemInfo.fState & MF_HILITE))
{ {
if (0 != (MenuInfo->Flags & MF_POPUP)) if (0 != (MenuInfo->Flags & MNF_POPUP))
{ {
Dc = GetDC(MenuInfo->Wnd); Dc = GetDC(MenuInfo->Wnd);
} }
@ -2354,7 +2343,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
ItemInfo.fState |= MF_HILITE; ItemInfo.fState |= MF_HILITE;
MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo); MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo);
MenuDrawMenuItem(MenuInfo->Wnd, MenuInfo, WndOwner, Dc, &ItemInfo, MenuInfo->Height, MenuDrawMenuItem(MenuInfo->Wnd, MenuInfo, WndOwner, Dc, &ItemInfo, MenuInfo->Height,
! (MenuInfo->Flags & MF_POPUP), ODA_DRAWENTIRE); ! (MenuInfo->Flags & MNF_POPUP), ODA_DRAWENTIRE);
ReleaseDC(MenuInfo->Wnd, Dc); ReleaseDC(MenuInfo->Wnd, Dc);
} }
@ -2372,7 +2361,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
{ {
MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongPtrW(MenuInfo->Wnd, GWL_STYLE), MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongPtrW(MenuInfo->Wnd, GWL_STYLE),
GetClassLongPtrW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU); GetClassLongPtrW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU);
if (Flags & TPM_LAYOUTRTL) Rect.left;
NcGetSysPopupPos(MenuInfo->Wnd, &Rect); NcGetSysPopupPos(MenuInfo->Wnd, &Rect);
Rect.top = Rect.bottom; Rect.top = Rect.bottom;
Rect.right = GetSystemMetrics(SM_CXSIZE); Rect.right = GetSystemMetrics(SM_CXSIZE);
@ -2381,16 +2370,22 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
else else
{ {
GetWindowRect(MenuInfo->Wnd, &Rect); GetWindowRect(MenuInfo->Wnd, &Rect);
if (0 != (MenuInfo->Flags & MF_POPUP)) if (0 != (MenuInfo->Flags & MNF_POPUP))
{ {
Rect.left += ItemInfo.Rect.right - GetSystemMetrics(SM_CXBORDER); if(Flags & TPM_LAYOUTRTL)
Rect.top += ItemInfo.Rect.top - 3; Rect.left += GetSystemMetrics(SM_CXBORDER);
else
Rect.left += ItemInfo.Rect.right- GetSystemMetrics(SM_CXBORDER);
Rect.top += ItemInfo.Rect.top - MENU_TOP_MARGIN;//3;
Rect.right = ItemInfo.Rect.left - ItemInfo.Rect.right + GetSystemMetrics(SM_CXBORDER); Rect.right = ItemInfo.Rect.left - ItemInfo.Rect.right + GetSystemMetrics(SM_CXBORDER);
Rect.bottom = ItemInfo.Rect.top - ItemInfo.Rect.bottom - 3 - 2 Rect.bottom = ItemInfo.Rect.top - ItemInfo.Rect.bottom - MENU_TOP_MARGIN - MENU_BOTTOM_MARGIN/*2*/
- GetSystemMetrics(SM_CYBORDER); - GetSystemMetrics(SM_CYBORDER);
} }
else else
{ {
if(Flags & TPM_LAYOUTRTL)
Rect.left += Rect.right - ItemInfo.Rect.left;
else
Rect.left += ItemInfo.Rect.left; Rect.left += ItemInfo.Rect.left;
Rect.top += ItemInfo.Rect.bottom; Rect.top += ItemInfo.Rect.bottom;
Rect.right = ItemInfo.Rect.right - ItemInfo.Rect.left; Rect.right = ItemInfo.Rect.right - ItemInfo.Rect.left;
@ -2398,6 +2393,9 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
} }
} }
/* use default alignment for submenus */
Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN);
MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem, Flags, MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem, Flags,
Rect.left, Rect.top, Rect.right, Rect.bottom ); Rect.left, Rect.top, Rect.right, Rect.bottom );
if (SelectFirst && MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu)) if (SelectFirst && MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu))
@ -2484,7 +2482,7 @@ MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index, UINT wFlag
if (MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu) && if (MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu) &&
Mt->TopMenu != PtMenuInfo->Self && Mt->TopMenu != PtMenuInfo->Self &&
0 == ((PtMenuInfo->Flags | TopMenuInfo.Flags) & MF_POPUP)) 0 == ((PtMenuInfo->Flags | TopMenuInfo.Flags) & MNF_POPUP))
{ {
/* both are top level menus (system and menu-bar) */ /* both are top level menus (system and menu-bar) */
MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags); MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags);
@ -2540,17 +2538,20 @@ MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags)
do not send a message to the owner */ do not send a message to the owner */
if (0 == (Flags & TPM_RETURNCMD)) if (0 == (Flags & TPM_RETURNCMD))
{ {
if (0 != (MenuInfo->Flags & MF_SYSMENU)) if (0 != (MenuInfo->Flags & MNF_SYSDESKMN))
{ {
PostMessageW(Mt->OwnerWnd, WM_SYSCOMMAND, ItemInfo.wID, PostMessageW(Mt->OwnerWnd, WM_SYSCOMMAND, ItemInfo.wID,
MAKELPARAM((SHORT) Mt->Pt.x, (SHORT) Mt->Pt.y)); MAKELPARAM((SHORT) Mt->Pt.x, (SHORT) Mt->Pt.y));
} }
else else
{ {
if (MenuInfo->dwStyle & MNS_NOTIFYBYPOS) BOOL ret;
PostMessageW(Mt->OwnerWnd, WM_MENUCOMMAND, ROSMENUINFO topmenuI;
MenuInfo->FocusedItem, ret = MenuGetRosMenuInfo(&topmenuI, Mt->TopMenu);
(LPARAM)MenuInfo->Self); DWORD dwStyle = MenuInfo->dwStyle | (ret ? topmenuI.dwStyle : 0);
if (dwStyle & MNS_NOTIFYBYPOS)
PostMessageW(Mt->OwnerWnd, WM_MENUCOMMAND, MenuInfo->FocusedItem, (LPARAM)MenuInfo->Self);
else else
PostMessageW(Mt->OwnerWnd, WM_COMMAND, ItemInfo.wID, 0); PostMessageW(Mt->OwnerWnd, WM_COMMAND, ItemInfo.wID, 0);
} }
@ -2726,7 +2727,7 @@ MenuPtMenu(HMENU Menu, POINT Pt)
/* check the current window (avoiding WM_HITTEST) */ /* check the current window (avoiding WM_HITTEST) */
Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt); Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt);
if (0 != (MenuInfo.Flags & MF_POPUP)) if (0 != (MenuInfo.Flags & MNF_POPUP))
{ {
if (HTNOWHERE != Ht && HTERROR != Ht) if (HTNOWHERE != Ht && HTERROR != Ht)
{ {
@ -3012,7 +3013,7 @@ MenuKeyEscape(MTRACKER *Mt, UINT Flags)
if (Mt->CurrentMenu != Mt->TopMenu) if (Mt->CurrentMenu != Mt->TopMenu)
{ {
if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu) if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)
&& 0 != (MenuInfo.Flags & MF_POPUP)) && 0 != (MenuInfo.Flags & MNF_POPUP))
{ {
MenuPrev = MenuTmp = Mt->TopMenu; MenuPrev = MenuTmp = Mt->TopMenu;
@ -3084,7 +3085,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags)
{ {
return; return;
} }
if ((MenuPrev == Mt->TopMenu) && !(TopMenuInfo.Flags & MF_POPUP)) if ((MenuPrev == Mt->TopMenu) && !(TopMenuInfo.Flags & MNF_POPUP))
{ {
/* move menu bar selection if no more popups are left */ /* move menu bar selection if no more popups are left */
@ -3124,7 +3125,7 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags)
Mt->CurrentMenu, Mt->TopMenu); Mt->CurrentMenu, Mt->TopMenu);
if (! MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu)) return; if (! MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu)) return;
if ((MenuInfo.Flags & MF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu)) if ((MenuInfo.Flags & MNF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu))
{ {
/* If already displaying a popup, try to display sub-popup */ /* If already displaying a popup, try to display sub-popup */
@ -3154,7 +3155,7 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags)
return; return;
} }
if (!(MenuInfo.Flags & MF_POPUP)) /* menu bar tracking */ if (!(MenuInfo.Flags & MNF_POPUP)) /* menu bar tracking */
{ {
if (Mt->CurrentMenu != Mt->TopMenu) if (Mt->CurrentMenu != Mt->TopMenu)
{ {
@ -3265,7 +3266,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
} }
if (!enterIdleSent) if (!enterIdleSent)
{ {
HWND win = MenuInfo.Flags & MF_POPUP ? MenuInfo.Wnd : NULL; HWND win = MenuInfo.Flags & MNF_POPUP ? MenuInfo.Wnd : NULL;
enterIdleSent = TRUE; enterIdleSent = TRUE;
SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win); SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win);
} }
@ -3384,7 +3385,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
case VK_DOWN: /* If on menu bar, pull-down the menu */ case VK_DOWN: /* If on menu bar, pull-down the menu */
if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
{ {
if (!(MenuInfo.Flags & MF_POPUP)) if (!(MenuInfo.Flags & MNF_POPUP))
{ {
if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu)) if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags); mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags);
@ -3507,16 +3508,15 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
{ {
MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE, wFlags); MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE, wFlags);
if (MenuInfo.Flags & MF_POPUP) if (MenuInfo.Flags & MNF_POPUP)
{ {
IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
DestroyWindow(MenuInfo.Wnd); DestroyWindow(MenuInfo.Wnd);
MenuInfo.Wnd = NULL; MenuInfo.Wnd = NULL;
if (!(MenuInfo.Flags & TPM_NONOTIFY)) if (!(wFlags & TPM_NONOTIFY))
SendMessageW( mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)mt.TopMenu, SendMessageW( mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)mt.TopMenu,
MAKELPARAM(0, IS_SYSTEM_MENU(&MenuInfo)) ); MAKELPARAM(0, IS_SYSTEM_MENU(&MenuInfo)) );
} }
MenuSelectItem( mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 ); MenuSelectItem( mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 );
} }
@ -3584,7 +3584,7 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT
IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART, IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART,
hWnd, hWnd,
MenuInfo.Flags & MF_SYSMENU ? OBJID_SYSMENU : OBJID_MENU, MenuInfo.Flags & MNF_SYSDESKMN ? OBJID_SYSMENU : OBJID_MENU,
CHILDID_SELF, 0); CHILDID_SELF, 0);
return TRUE; return TRUE;
} }
@ -3615,6 +3615,7 @@ VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt)
TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y); TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y);
if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) wFlags |= TPM_LAYOUTRTL;
if (IsMenu(hMenu)) if (IsMenu(hMenu))
{ {
/* map point to parent client coordinates */ /* map point to parent client coordinates */
@ -3716,6 +3717,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
/* ReactOS Check */ /* ReactOS Check */
if (!ValidateHwnd(Wnd)) if (!ValidateHwnd(Wnd))
{ {
/* invalid window see wine menu.c test_menu_trackpopupmenu line 3146 */
return FALSE; return FALSE;
} }
@ -4815,7 +4817,7 @@ LoadMenuIndirectW(CONST MENUTEMPLATE *lpMenuTemplate)
offset = GET_WORD(p); offset = GET_WORD(p);
p += sizeof(WORD) + offset; p += sizeof(WORD) + offset;
if (!(hMenu = CreateMenu())) return 0; if (!(hMenu = CreateMenu())) return 0;
if (!MENU_ParseResource(p, hMenu, TRUE)) if (!MENU_ParseResource(p, hMenu))
{ {
DestroyMenu(hMenu); DestroyMenu(hMenu);
return 0; return 0;
@ -4897,7 +4899,7 @@ ModifyMenuA(
if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE; if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE;
if ((rmii.hSubMenu) && (uFlags & MF_POPUP) && (rmii.hSubMenu != (HMENU)uIDNewItem)) if (rmii.hSubMenu && (uFlags & MF_POPUP) && (rmii.hSubMenu != (HMENU)uIDNewItem))
NtUserDestroyMenu( rmii.hSubMenu ); /* ModifyMenu() spec */ NtUserDestroyMenu( rmii.hSubMenu ); /* ModifyMenu() spec */
MenuCleanupRosMenuItemInfo( &rmii ); MenuCleanupRosMenuItemInfo( &rmii );
@ -4944,7 +4946,7 @@ ModifyMenuW(
if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE; if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE;
if ((rmii.hSubMenu) && (uFlags & MF_POPUP) && (rmii.hSubMenu != (HMENU)uIDNewItem)) if (rmii.hSubMenu && (uFlags & MF_POPUP) && (rmii.hSubMenu != (HMENU)uIDNewItem))
NtUserDestroyMenu( rmii.hSubMenu ); /* ModifyMenu() spec */ NtUserDestroyMenu( rmii.hSubMenu ); /* ModifyMenu() spec */
MenuCleanupRosMenuItemInfo( &rmii ); MenuCleanupRosMenuItemInfo( &rmii );

View file

@ -88,7 +88,8 @@ GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
/* We do not use anything else than uncompressed bitmaps */ /* We do not use anything else than uncompressed bitmaps */
if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB) if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB)
{ {
DPRINT1("biCompression == %d != BI_RGB, correct that!\n", GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression); DPRINT1("biCompression == %d != BI_RGB, fix that!\n",
GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression);
GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB; GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB;
} }

View file

@ -585,6 +585,78 @@ ConioWriteConsole(PCONSOLE Console,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTAPI
ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console,
IN PTEXTMODE_SCREEN_BUFFER Buffer,
IN USHORT NewScreenAttrib,
IN USHORT NewPopupAttrib)
{
DWORD X, Y, Length;
PCHAR_INFO Ptr;
COORD TopLeft = {0};
ULONG NumCodesToWrite = Buffer->ScreenBufferSize.X * Buffer->ScreenBufferSize.Y;
USHORT OldScreenAttrib = Buffer->ScreenDefaultAttrib;
if (Console == NULL || Buffer == NULL)
{
return STATUS_INVALID_PARAMETER;
}
/* Validity check */
ASSERT(Console == Buffer->Header.Console);
X = TopLeft.X;
Y = (TopLeft.Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
Length = NumCodesToWrite;
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
// Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
while (Length--)
{
// Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X];
/*
* Change the current colors only if they are the old ones.
*/
/* Foreground color */
if ((Ptr->Attributes & 0x0F) == (OldScreenAttrib & 0x0F))
Ptr->Attributes = (Ptr->Attributes & 0xFFF0) | (NewScreenAttrib & 0x0F);
/* Background color */
if ((Ptr->Attributes & 0xF0) == (OldScreenAttrib & 0xF0))
Ptr->Attributes = (Ptr->Attributes & 0xFF0F) | (NewScreenAttrib & 0xF0);
// ++Ptr;
if (++X == Buffer->ScreenBufferSize.X)
{
X = 0;
if (++Y == Buffer->ScreenBufferSize.Y)
{
Y = 0;
}
}
}
/* Save foreground and background colors for both screen and popup */
Buffer->ScreenDefaultAttrib = (NewScreenAttrib & 0x00FF);
Buffer->PopupDefaultAttrib = (NewPopupAttrib & 0x00FF);
/* Refresh the display if needed */
if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
{
SMALL_RECT UpdateRect;
ConioComputeUpdateRect(Buffer, &UpdateRect, &TopLeft, NumCodesToWrite);
TermDrawRegion(Console, &UpdateRect);
}
return STATUS_SUCCESS;
}
/* PUBLIC DRIVER APIS *********************************************************/ /* PUBLIC DRIVER APIS *********************************************************/
@ -947,7 +1019,6 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
PWCHAR tmpString = NULL; PWCHAR tmpString = NULL;
DWORD X, Y, Length; // , Written = 0; DWORD X, Y, Length; // , Written = 0;
ULONG CodeSize; ULONG CodeSize;
SMALL_RECT UpdateRect;
PCHAR_INFO Ptr; PCHAR_INFO Ptr;
if (Console == NULL || Buffer == NULL || if (Console == NULL || Buffer == NULL ||
@ -1046,6 +1117,7 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
{ {
SMALL_RECT UpdateRect;
ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite); ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite);
TermDrawRegion(Console, &UpdateRect); TermDrawRegion(Console, &UpdateRect);
} }
@ -1071,7 +1143,6 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
{ {
DWORD X, Y, Length; // , Written = 0; DWORD X, Y, Length; // , Written = 0;
PCHAR_INFO Ptr; PCHAR_INFO Ptr;
SMALL_RECT UpdateRect;
if (Console == NULL || Buffer == NULL || Code == NULL || if (Console == NULL || Buffer == NULL || Code == NULL ||
WriteCoord == NULL /* || CodesWritten == NULL */) WriteCoord == NULL /* || CodesWritten == NULL */)
@ -1144,6 +1215,7 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console,
if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) if ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer)
{ {
SMALL_RECT UpdateRect;
ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite); ConioComputeUpdateRect(Buffer, &UpdateRect, WriteCoord, NumCodesToWrite);
TermDrawRegion(Console, &UpdateRect); TermDrawRegion(Console, &UpdateRect);
} }

View file

@ -16,19 +16,100 @@
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
VOID VOID
GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer) GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData)
{ {
/* /*
* This function supposes that the system clipboard was opened. * This function supposes that the system clipboard was opened.
*/ */
// PCONSOLE Console = Buffer->Header.Console; PCONSOLE Console = Buffer->Header.Console;
UNIMPLEMENTED; HDC hMemDC;
HBITMAP hBitmapTarget, hBitmapOld;
HPALETTE hPalette, hPaletteOld;
ULONG selWidth, selHeight;
if (Buffer->BitMap == NULL) return;
selWidth = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
DPRINT1("Selection is (%d|%d) to (%d|%d)\n",
Console->Selection.srSelection.Left,
Console->Selection.srSelection.Top,
Console->Selection.srSelection.Right,
Console->Selection.srSelection.Bottom);
hMemDC = CreateCompatibleDC(GuiData->hMemDC);
if (hMemDC == NULL) return;
/* Allocate a bitmap to be given to the clipboard, so it will not be freed here */
hBitmapTarget = CreateCompatibleBitmap(GuiData->hMemDC, selWidth, selHeight);
if (hBitmapTarget == NULL)
{
DeleteDC(hMemDC);
return;
}
/* Select the new bitmap */
hBitmapOld = SelectObject(hMemDC, hBitmapTarget);
/* Change the palette in hMemDC if the current palette does exist */
if (Buffer->PaletteHandle == NULL)
hPalette = GuiData->hSysPalette;
else
hPalette = Buffer->PaletteHandle;
if (hPalette) hPaletteOld = SelectPalette(hMemDC, hPalette, FALSE);
/* Grab the mutex */
NtWaitForSingleObject(Buffer->Mutex, FALSE, NULL);
// The equivalent of a SetDIBitsToDevice call...
// It seems to be broken: it does not copy the tail of the bitmap.
// http://wiki.allegro.cc/index.php?title=StretchDIBits
#if 0
StretchDIBits(hMemDC,
0, 0,
selWidth, selHeight,
Console->Selection.srSelection.Left,
Console->Selection.srSelection.Top,
selWidth, selHeight,
Buffer->BitMap,
Buffer->BitMapInfo,
Buffer->BitMapUsage,
SRCCOPY);
#else
SetDIBitsToDevice(hMemDC,
/* Coordinates / size of the repainted rectangle, in the framebuffer's frame */
0, 0,
selWidth, selHeight,
/* Coordinates / size of the corresponding image portion, in the graphics screen-buffer's frame */
Console->Selection.srSelection.Left,
Console->Selection.srSelection.Top,
0,
Buffer->ScreenBufferSize.Y, // == Buffer->BitMapInfo->bmiHeader.biHeight
Buffer->BitMap,
Buffer->BitMapInfo,
Buffer->BitMapUsage);
#endif
/* Release the mutex */
NtReleaseMutant(Buffer->Mutex, NULL);
/* Restore the palette and the old bitmap */
if (hPalette) SelectPalette(hMemDC, hPaletteOld, FALSE);
SelectObject(hMemDC, hBitmapOld);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBitmapTarget);
DeleteDC(hMemDC);
} }
VOID VOID
GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer) GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData)
{ {
/* /*
* This function supposes that the system clipboard was opened. * This function supposes that the system clipboard was opened.

View file

@ -1333,8 +1333,12 @@ Quit:
return 0; return 0;
} }
VOID GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer); VOID
VOID GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer); GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData);
VOID
GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData);
static VOID static VOID
GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData) GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
@ -1346,11 +1350,11 @@ GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
if (GetType(Buffer) == TEXTMODE_BUFFER) if (GetType(Buffer) == TEXTMODE_BUFFER)
{ {
GuiCopyFromTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer); GuiCopyFromTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer, GuiData);
} }
else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */ else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
{ {
GuiCopyFromGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer); GuiCopyFromGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer, GuiData);
} }
CloseClipboard(); CloseClipboard();
@ -1361,8 +1365,12 @@ GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
} }
} }
VOID GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer); VOID
VOID GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer); GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData);
VOID
GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData);
static VOID static VOID
GuiConsolePaste(PGUI_CONSOLE_DATA GuiData) GuiConsolePaste(PGUI_CONSOLE_DATA GuiData)
@ -1373,11 +1381,11 @@ GuiConsolePaste(PGUI_CONSOLE_DATA GuiData)
if (GetType(Buffer) == TEXTMODE_BUFFER) if (GetType(Buffer) == TEXTMODE_BUFFER)
{ {
GuiPasteToTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer); GuiPasteToTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer, GuiData);
} }
else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */ else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
{ {
GuiPasteToGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer); GuiPasteToGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer, GuiData);
} }
CloseClipboard(); CloseClipboard();
@ -1909,6 +1917,8 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
EnableMenuItem(hMenu, ID_SYSTEM_EDIT_COPY , MF_BYCOMMAND | EnableMenuItem(hMenu, ID_SYSTEM_EDIT_COPY , MF_BYCOMMAND |
((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) && ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) ? MF_ENABLED : MF_GRAYED)); (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) ? MF_ENABLED : MF_GRAYED));
// FIXME: Following whether the active screen buffer is text-mode
// or graphics-mode, search for CF_UNICODETEXT or CF_BITMAP formats.
EnableMenuItem(hMenu, ID_SYSTEM_EDIT_PASTE, MF_BYCOMMAND | EnableMenuItem(hMenu, ID_SYSTEM_EDIT_PASTE, MF_BYCOMMAND |
(!(Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) && (!(Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED)); IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));

View file

@ -30,7 +30,8 @@ COLORREF RGBFromAttrib2(PCONSOLE Console, WORD Attribute)
} }
VOID VOID
GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer) GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData)
{ {
/* /*
* This function supposes that the system clipboard was opened. * This function supposes that the system clipboard was opened.
@ -72,12 +73,16 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
size += 1; /* Null-termination */ size += 1; /* Null-termination */
size *= sizeof(WCHAR); size *= sizeof(WCHAR);
/* Allocate memory, it will be passed to the system and may not be freed here */ /* Allocate some memory area to be given to the clipboard, so it will not be freed here */
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size); hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
if (hData == NULL) return; if (hData == NULL) return;
data = GlobalLock(hData); data = GlobalLock(hData);
if (data == NULL) return; if (data == NULL)
{
GlobalFree(hData);
return;
}
DPRINT("Copying %dx%d selection\n", selWidth, selHeight); DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
dstPos = data; dstPos = data;
@ -121,7 +126,8 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
} }
VOID VOID
GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer) GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
PGUI_CONSOLE_DATA GuiData)
{ {
/* /*
* This function supposes that the system clipboard was opened. * This function supposes that the system clipboard was opened.

View file

@ -436,7 +436,11 @@ ConSrvGetDefaultSettings(IN OUT PCONSOLE_INFO ConsoleInfo,
} }
} }
NTSTATUS NTAPI
ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console,
IN PTEXTMODE_SCREEN_BUFFER Buffer,
IN USHORT NewScreenAttrib,
IN USHORT NewPopupAttrib);
/* /*
* NOTE: This function explicitely references Console->ActiveBuffer. * NOTE: This function explicitely references Console->ActiveBuffer.
* It is possible that it should go into some frontend... * It is possible that it should go into some frontend...
@ -455,26 +459,10 @@ ConSrvApplyUserSettings(IN PCONSOLE Console,
Console->QuickEdit = ConsoleInfo->QuickEdit; Console->QuickEdit = ConsoleInfo->QuickEdit;
Console->InsertMode = ConsoleInfo->InsertMode; Console->InsertMode = ConsoleInfo->InsertMode;
/* /* Copy the new console palette */
* Apply foreground and background colors for both screen and popup
* and copy the new palette.
*/
if (GetType(ActiveBuffer) == TEXTMODE_BUFFER)
{
PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer;
Buffer->ScreenDefaultAttrib = ConsoleInfo->ScreenAttrib;
Buffer->PopupDefaultAttrib = ConsoleInfo->PopupAttrib;
}
else // if (Console->ActiveBuffer->Header.Type == GRAPHICS_BUFFER)
{
}
// FIXME: Possible buffer overflow if s_colors is bigger than pConInfo->Colors. // FIXME: Possible buffer overflow if s_colors is bigger than pConInfo->Colors.
memcpy(Console->Colors, ConsoleInfo->Colors, sizeof(s_Colors)); memcpy(Console->Colors, ConsoleInfo->Colors, sizeof(s_Colors));
// TODO: Really update the screen attributes as FillConsoleOutputAttribute does.
/* Apply cursor size */ /* Apply cursor size */
ActiveBuffer->CursorInfo.bVisible = (ConsoleInfo->CursorSize != 0); ActiveBuffer->CursorInfo.bVisible = (ConsoleInfo->CursorSize != 0);
ActiveBuffer->CursorInfo.dwSize = min(max(ConsoleInfo->CursorSize, 0), 100); ActiveBuffer->CursorInfo.dwSize = min(max(ConsoleInfo->CursorSize, 0), 100);
@ -537,6 +525,12 @@ ConSrvApplyUserSettings(IN PCONSOLE Console,
if (SizeChanged) TermResizeTerminal(Console); if (SizeChanged) TermResizeTerminal(Console);
} }
/* Apply foreground and background colors for both screen and popup */
ConDrvChangeScreenBufferAttributes(Console,
Buffer,
ConsoleInfo->ScreenAttrib,
ConsoleInfo->PopupAttrib);
} }
else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER)
{ {