diff --git a/reactos/lib/setupapi/Cs.rc b/reactos/lib/setupapi/Cs.rc index 54d5ab0fa29..330eeddd797 100644 --- a/reactos/lib/setupapi/Cs.rc +++ b/reactos/lib/setupapi/Cs.rc @@ -1,35 +1,35 @@ -/* - * Czech resources for SETUPAPI - * - * Copyright 2001 Andreas Mohr - * Copyright 2004 David Kredba - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_CZECH, SUBLANG_DEFAULT - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Kopruji soubory..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Storno", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Zdroj:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Cl:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * Czech resources for SETUPAPI + * + * Copyright 2001 Andreas Mohr + * Copyright 2004 David Kredba + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Kopruji soubory..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Storno", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Zdroj:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Cl:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/De.rc b/reactos/lib/setupapi/De.rc index 08507396a41..0fd9555a97f 100644 --- a/reactos/lib/setupapi/De.rc +++ b/reactos/lib/setupapi/De.rc @@ -1,34 +1,34 @@ -/* - * German resources for SETUPAPI - * - * Copyright 2004 Henning Gerhardt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Dateien kopieren..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Abbrechen", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Quelle:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Ziel:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * German resources for SETUPAPI + * + * Copyright 2004 Henning Gerhardt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Dateien kopieren..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Abbrechen", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Quelle:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Ziel:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/En.rc b/reactos/lib/setupapi/En.rc index bd142fa9b30..aa504ca13d8 100644 --- a/reactos/lib/setupapi/En.rc +++ b/reactos/lib/setupapi/En.rc @@ -1,34 +1,34 @@ -/* - * English resources for SETUPAPI - * - * Copyright 2001 Andreas Mohr - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Copying Files..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Cancel", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Source:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Destination:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * English resources for SETUPAPI + * + * Copyright 2001 Andreas Mohr + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Copying Files..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Cancel", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Source:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Destination:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/Es.rc b/reactos/lib/setupapi/Es.rc index 6ccd146b4c3..3c7c7e219f2 100644 --- a/reactos/lib/setupapi/Es.rc +++ b/reactos/lib/setupapi/Es.rc @@ -1,34 +1,34 @@ -/* - * Spanish resources for SETUPAPI - * - * Copyright 2003 Jos Manuel Ferrer Ortiz - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Copiando archivos..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Cancelar", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Origen:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Destino:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * Spanish resources for SETUPAPI + * + * Copyright 2003 Jos Manuel Ferrer Ortiz + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Copiando archivos..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Cancelar", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Origen:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Destino:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/Fr.rc b/reactos/lib/setupapi/Fr.rc index 43d4fb3d99a..40f01716a23 100644 --- a/reactos/lib/setupapi/Fr.rc +++ b/reactos/lib/setupapi/Fr.rc @@ -1,35 +1,35 @@ -/* - * French resources for SETUPAPI - * - * Copyright 2001 Andreas Mohr - * Copyright 2003 Vincent Bron - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Copie de fichiers..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Annuler", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Source:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Destination:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * French resources for SETUPAPI + * + * Copyright 2001 Andreas Mohr + * Copyright 2003 Vincent Bron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Copie de fichiers..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Annuler", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Source:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Destination:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/It.rc b/reactos/lib/setupapi/It.rc index 7a47c7e4347..dc7b679e315 100644 --- a/reactos/lib/setupapi/It.rc +++ b/reactos/lib/setupapi/It.rc @@ -1,35 +1,35 @@ -/* - * Italian resources for SETUPAPI - * - * Copyright 2001 Andreas Mohr - * Copyright 2003 Ivan Leo Puoti - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Copia dei file in corso..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Anulla", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Origine:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Destinazione:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * Italian resources for SETUPAPI + * + * Copyright 2001 Andreas Mohr + * Copyright 2003 Ivan Leo Puoti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Copia dei file in corso..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Anulla", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Origine:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Destinazione:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/Ja.rc b/reactos/lib/setupapi/Ja.rc index 96cb39c9cc7..03513668ace 100644 --- a/reactos/lib/setupapi/Ja.rc +++ b/reactos/lib/setupapi/Ja.rc @@ -1,34 +1,34 @@ -/* - * Japanese resources for SETUPAPI - * - * Copyright 2004 Hajime Segawa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "t@CRs[Ă܂..." -FONT 9, "MS UI Gothic" -BEGIN - PUSHBUTTON "LZ", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Rs[:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Rs[:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * Japanese resources for SETUPAPI + * + * Copyright 2004 Hajime Segawa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "t@CRs[Ă܂..." +FONT 9, "MS UI Gothic" +BEGIN + PUSHBUTTON "LZ", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Rs[:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Rs[:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/Makefile.in b/reactos/lib/setupapi/Makefile.in index 26dde89eccd..d65bd717ace 100644 --- a/reactos/lib/setupapi/Makefile.in +++ b/reactos/lib/setupapi/Makefile.in @@ -1,39 +1,39 @@ -EXTRADEFS = -D_SETUPAPI_ -TOPSRCDIR = @top_srcdir@ -TOPOBJDIR = ../.. -SRCDIR = @srcdir@ -VPATH = @srcdir@ -MODULE = setupapi.dll -IMPORTLIB = libsetupapi.$(IMPLIBEXT) -IMPORTS = user32 version advapi32 rpcrt4 kernel32 ntdll -DELAYIMPORTS = shell32 -EXTRALIBS = $(LIBUNICODE) - -C_SRCS = \ - pnp_c.c \ - cfgmgr.c \ - devinst.c \ - dirid.c \ - diskspace.c \ - install.c \ - misc.c \ - parser.c \ - queue.c \ - setupcab.c \ - stringtable.c \ - stubs.c \ - rpc.c - -C_SRCS16 = \ - devinst16.c \ - infparse.c \ - setupx_main.c \ - virtcopy.c - -SPEC_SRCS16 = setupx.spec - -RC_SRCS= setupapi.rc - -@MAKE_DLL_RULES@ - -### Dependencies: +EXTRADEFS = -D_SETUPAPI_ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = setupapi.dll +IMPORTLIB = libsetupapi.$(IMPLIBEXT) +IMPORTS = user32 version advapi32 rpcrt4 kernel32 ntdll +DELAYIMPORTS = shell32 +EXTRALIBS = $(LIBUNICODE) + +C_SRCS = \ + pnp_c.c \ + cfgmgr.c \ + devinst.c \ + dirid.c \ + diskspace.c \ + install.c \ + misc.c \ + parser.c \ + queue.c \ + setupcab.c \ + stringtable.c \ + stubs.c \ + rpc.c + +C_SRCS16 = \ + devinst16.c \ + infparse.c \ + setupx_main.c \ + virtcopy.c + +SPEC_SRCS16 = setupx.spec + +RC_SRCS= setupapi.rc + +@MAKE_DLL_RULES@ + +### Dependencies: diff --git a/reactos/lib/setupapi/Nl.rc b/reactos/lib/setupapi/Nl.rc index d7c6f13bb49..bb86ca5cd34 100644 --- a/reactos/lib/setupapi/Nl.rc +++ b/reactos/lib/setupapi/Nl.rc @@ -1,34 +1,34 @@ -/* - * setupapi (Dutch resources) - * - * Copyright 2003 Hans Leidekker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Bestanden worden gekopierd..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Annuleren", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Bron:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Bestemming:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * setupapi (Dutch resources) + * + * Copyright 2003 Hans Leidekker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Bestanden worden gekopierd..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Annuleren", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Bron:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Bestemming:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/Pt.rc b/reactos/lib/setupapi/Pt.rc index dacb2b4228c..4b6768f3c98 100644 --- a/reactos/lib/setupapi/Pt.rc +++ b/reactos/lib/setupapi/Pt.rc @@ -1,50 +1,50 @@ -/* - * Portuguese resources for SETUPAPI - * - * Copyright 2003 Marcelo Duarte - * Copyright 2004 Amrico Jos Melo - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Copiando arquivos..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Cancelar", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Origem:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Destino:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END - -LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "A copiar ficheiros..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Cancelar", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Origem:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Destino:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * Portuguese resources for SETUPAPI + * + * Copyright 2003 Marcelo Duarte + * Copyright 2004 Amrico Jos Melo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Copiando arquivos..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Cancelar", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Origem:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Destino:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END + +LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "A copiar ficheiros..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Cancelar", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Origem:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Destino:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/Ru.rc b/reactos/lib/setupapi/Ru.rc index 09ee4f637c1..3efa2424097 100644 --- a/reactos/lib/setupapi/Ru.rc +++ b/reactos/lib/setupapi/Ru.rc @@ -1,34 +1,34 @@ -/* - * SETUPAPI (Russian resources) - * - * Copyright 2003 Igor Stepin - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION " ..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT ":", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT ":", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * SETUPAPI (Russian resources) + * + * Copyright 2003 Igor Stepin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION " ..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT ":", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT ":", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/Sv.rc b/reactos/lib/setupapi/Sv.rc index ad5a681b975..4ac8501fae2 100644 --- a/reactos/lib/setupapi/Sv.rc +++ b/reactos/lib/setupapi/Sv.rc @@ -1,34 +1,34 @@ -/* - * Swedish resources for SETUPAPI - * - * Copyright 2005 Anders Bergh - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT - -COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 -STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION -CAPTION "Kopierar filer..." -FONT 8, "MS Shell Dlg" -BEGIN - PUSHBUTTON "Avbryt", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP - LTEXT "Klla:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Destination:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP - CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP -END +/* + * Swedish resources for SETUPAPI + * + * Copyright 2005 Anders Bergh + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT + +COPYFILEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 20, 20, 208, 105 +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Kopierar filer..." +FONT 8, "MS Shell Dlg" +BEGIN + PUSHBUTTON "Avbryt", IDCANCEL, 79, 84, 50, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + LTEXT "Klla:", -1, 7, 7, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", SOURCESTRORD, 7, 18, 194, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Destination:", -1, 7, 30, 77, 11, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "", DESTSTRORD, 7, 41, 194, 22, WS_CHILD | WS_VISIBLE | WS_GROUP + CONTROL "", PROGRESSORD, "setupx_progress", 7, 63, 194, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END diff --git a/reactos/lib/setupapi/cfgmgr.c b/reactos/lib/setupapi/cfgmgr.c index 517a7b9e96f..4b40fea6c9d 100644 --- a/reactos/lib/setupapi/cfgmgr.c +++ b/reactos/lib/setupapi/cfgmgr.c @@ -1,362 +1,362 @@ -/* - * Configuration manager functions - * - * Copyright 2000 James Hatheway - * Copyright 2005 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "winreg.h" -#include "setupapi.h" -#include "cfgmgr32.h" -#include "setupapi_private.h" - -#include "rpc.h" - -#include "pnp_c.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -typedef struct _MACHINE_INFO -{ - RPC_BINDING_HANDLE BindingHandle; -} MACHINE_INFO, *PMACHINE_INFO; - - -/*********************************************************************** - * CM_Connect_MachineA [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Connect_MachineA(PCSTR UNCServerName, PHMACHINE phMachine) -{ - PWSTR pServerNameW; - CONFIGRET ret; - - TRACE("%s %p\n", UNCServerName, phMachine); - - if (UNCServerName == NULL || *UNCServerName == 0) - return CM_Connect_MachineW(NULL, phMachine); - - if (CaptureAndConvertAnsiArg(UNCServerName, &pServerNameW)) - return CR_INVALID_DATA; - - ret = CM_Connect_MachineW(pServerNameW, phMachine); - - MyFree(pServerNameW); - - return ret; -} - - -/*********************************************************************** - * CM_Connect_MachineW [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Connect_MachineW(PCWSTR UNCServerName, PHMACHINE phMachine) -{ - PMACHINE_INFO pMachine; - - TRACE("%s %p\n", debugstr_w(UNCServerName), phMachine); - - pMachine = (PMACHINE_INFO)GlobalAlloc(GPTR, sizeof(MACHINE_INFO)); - if (pMachine == NULL) - return CR_OUT_OF_MEMORY; - - if (!PnpBindRpc(UNCServerName, &pMachine->BindingHandle)) - { - GlobalFree(pMachine); - return CR_INVALID_MACHINENAME; - } - - phMachine = (PHMACHINE)pMachine; - - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Disconnect_Machine [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Disconnect_Machine(HMACHINE hMachine) -{ - PMACHINE_INFO pMachine; - - TRACE("%lx\n", hMachine); - - if (hMachine == NULL) - return CR_SUCCESS; - - pMachine = (PMACHINE_INFO)hMachine; - if (!PnpUnbindRpc(pMachine->BindingHandle)) - return CR_ACCESS_DENIED; - - GlobalFree(pMachine); - - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Child [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Child( - PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) -{ - TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags); - return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL); -} - - -/*********************************************************************** - * CM_Get_Child_Ex [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Child_Ex( - PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine) -{ - TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine); - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Device_ID_ListA [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Device_ID_ListA( - PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags ) -{ - FIXME("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags); - memset(Buffer,0,2); - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Device_ID_ListW [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Device_ID_ListW( - PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags ) -{ - TRACE("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags); - return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen, - ulFlags, NULL); -} - - -/*********************************************************************** - * CM_Get_Device_ID_List_ExA [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Device_ID_List_ExA( - PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags, - HMACHINE hMachine ) -{ - FIXME("%p %p %ld %ld %lx\n", - pszFilter, Buffer, BufferLen, ulFlags, hMachine); - memset(Buffer,0,2); - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Device_ID_List_ExW [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Device_ID_List_ExW( - PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags, - HMACHINE hMachine ) -{ - FIXME("%p %p %ld %ld %lx\n", - pszFilter, Buffer, BufferLen, ulFlags, hMachine); - memset(Buffer,0,2); - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Device_ID_List_SizeA [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Device_ID_List_SizeA( - PULONG pulLen, PCSTR pszFilter, ULONG ulFlags) -{ - FIXME("%p %s %ld\n", pulLen, pszFilter, ulFlags); - *pulLen = 2; - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Device_ID_List_SizeW [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Device_ID_List_SizeW( - PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags) -{ - TRACE("%p %s %ld\n", pulLen, debugstr_w(pszFilter), ulFlags); - return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL); -} - - -/*********************************************************************** - * CM_Get_Device_ID_List_Size_ExA [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExA( - PULONG pulLen, PCSTR pszFilter, ULONG ulFlags, HMACHINE hMachine) -{ - FIXME("%p %s %ld %lx\n", pulLen, pszFilter, ulFlags, hMachine); - *pulLen = 2; - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Device_ID_List_Size_ExW [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExW( - PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags, HMACHINE hMachine) -{ - FIXME("%p %s %ld %lx\n", pulLen, debugstr_w(pszFilter), ulFlags, hMachine); - *pulLen = 2; - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Parent [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Parent( - PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) -{ - TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags); - return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL); -} - - -/*********************************************************************** - * CM_Get_Parent_Ex [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Parent_Ex( - PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine) -{ - TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine); - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Sibling [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Sibling( - PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) -{ - TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags); - return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL); -} - - -/*********************************************************************** - * CM_Get_Sibling_Ex [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Get_Sibling_Ex( - PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine) -{ - TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine); - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Get_Version [SETUPAPI.@] - */ -WORD WINAPI CM_Get_Version(VOID) -{ - TRACE("\n"); - return CM_Get_Version_Ex(NULL); -} - - -/*********************************************************************** - * CM_Get_Version_Ex [SETUPAPI.@] - */ -WORD WINAPI CM_Get_Version_Ex(HMACHINE hMachine) -{ - RPC_BINDING_HANDLE BindingHandle = NULL; - RPC_STATUS Status; - - FIXME("%lx\n", hMachine); - - if (hMachine != NULL) - { - BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle; - if (BindingHandle == NULL) - return 0; - } - else - { - Status = PnpGetLocalBindingHandle(&BindingHandle); - if (Status != RPC_S_OK) - return 0; - } - - return PNP_GetVersion(BindingHandle); -} - - -/*********************************************************************** - * CM_Locate_DevNodeA [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Locate_DevNodeA( - PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags) -{ - FIXME("%p %p %lu\n", pdnDevInst, pDeviceID, ulFlags); - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Locate_DevNodeW [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Locate_DevNodeW( - PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags) -{ - TRACE("%p %p %lu\n", pdnDevInst, pDeviceID, ulFlags); - return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL); -} - - -/*********************************************************************** - * CM_Locate_DevNode_ExA [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Locate_DevNode_ExA( - PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags, HMACHINE hMachine) -{ - FIXME("%p %p %lu %lx\n", pdnDevInst, pDeviceID, ulFlags, hMachine); - return CR_SUCCESS; -} - - -/*********************************************************************** - * CM_Locate_DevNode_ExW [SETUPAPI.@] - */ -CONFIGRET WINAPI CM_Locate_DevNode_ExW( - PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags, HMACHINE hMachine) -{ - FIXME("%p %p %lu %lx\n", pdnDevInst, pDeviceID, ulFlags, hMachine); - return CR_SUCCESS; -} +/* + * Configuration manager functions + * + * Copyright 2000 James Hatheway + * Copyright 2005 Eric Kohl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "winreg.h" +#include "setupapi.h" +#include "cfgmgr32.h" +#include "setupapi_private.h" + +#include "rpc.h" + +#include "pnp_c.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +typedef struct _MACHINE_INFO +{ + RPC_BINDING_HANDLE BindingHandle; +} MACHINE_INFO, *PMACHINE_INFO; + + +/*********************************************************************** + * CM_Connect_MachineA [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Connect_MachineA(PCSTR UNCServerName, PHMACHINE phMachine) +{ + PWSTR pServerNameW; + CONFIGRET ret; + + TRACE("%s %p\n", UNCServerName, phMachine); + + if (UNCServerName == NULL || *UNCServerName == 0) + return CM_Connect_MachineW(NULL, phMachine); + + if (CaptureAndConvertAnsiArg(UNCServerName, &pServerNameW)) + return CR_INVALID_DATA; + + ret = CM_Connect_MachineW(pServerNameW, phMachine); + + MyFree(pServerNameW); + + return ret; +} + + +/*********************************************************************** + * CM_Connect_MachineW [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Connect_MachineW(PCWSTR UNCServerName, PHMACHINE phMachine) +{ + PMACHINE_INFO pMachine; + + TRACE("%s %p\n", debugstr_w(UNCServerName), phMachine); + + pMachine = (PMACHINE_INFO)GlobalAlloc(GPTR, sizeof(MACHINE_INFO)); + if (pMachine == NULL) + return CR_OUT_OF_MEMORY; + + if (!PnpBindRpc(UNCServerName, &pMachine->BindingHandle)) + { + GlobalFree(pMachine); + return CR_INVALID_MACHINENAME; + } + + phMachine = (PHMACHINE)pMachine; + + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Disconnect_Machine [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Disconnect_Machine(HMACHINE hMachine) +{ + PMACHINE_INFO pMachine; + + TRACE("%lx\n", hMachine); + + if (hMachine == NULL) + return CR_SUCCESS; + + pMachine = (PMACHINE_INFO)hMachine; + if (!PnpUnbindRpc(pMachine->BindingHandle)) + return CR_ACCESS_DENIED; + + GlobalFree(pMachine); + + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Child [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Child( + PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) +{ + TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags); + return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL); +} + + +/*********************************************************************** + * CM_Get_Child_Ex [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Child_Ex( + PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine) +{ + TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine); + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Device_ID_ListA [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Device_ID_ListA( + PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags ) +{ + FIXME("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags); + memset(Buffer,0,2); + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Device_ID_ListW [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Device_ID_ListW( + PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags ) +{ + TRACE("%p %p %ld %ld\n", pszFilter, Buffer, BufferLen, ulFlags); + return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen, + ulFlags, NULL); +} + + +/*********************************************************************** + * CM_Get_Device_ID_List_ExA [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Device_ID_List_ExA( + PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags, + HMACHINE hMachine ) +{ + FIXME("%p %p %ld %ld %lx\n", + pszFilter, Buffer, BufferLen, ulFlags, hMachine); + memset(Buffer,0,2); + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Device_ID_List_ExW [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Device_ID_List_ExW( + PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags, + HMACHINE hMachine ) +{ + FIXME("%p %p %ld %ld %lx\n", + pszFilter, Buffer, BufferLen, ulFlags, hMachine); + memset(Buffer,0,2); + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Device_ID_List_SizeA [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Device_ID_List_SizeA( + PULONG pulLen, PCSTR pszFilter, ULONG ulFlags) +{ + FIXME("%p %s %ld\n", pulLen, pszFilter, ulFlags); + *pulLen = 2; + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Device_ID_List_SizeW [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Device_ID_List_SizeW( + PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags) +{ + TRACE("%p %s %ld\n", pulLen, debugstr_w(pszFilter), ulFlags); + return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL); +} + + +/*********************************************************************** + * CM_Get_Device_ID_List_Size_ExA [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExA( + PULONG pulLen, PCSTR pszFilter, ULONG ulFlags, HMACHINE hMachine) +{ + FIXME("%p %s %ld %lx\n", pulLen, pszFilter, ulFlags, hMachine); + *pulLen = 2; + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Device_ID_List_Size_ExW [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExW( + PULONG pulLen, PCWSTR pszFilter, ULONG ulFlags, HMACHINE hMachine) +{ + FIXME("%p %s %ld %lx\n", pulLen, debugstr_w(pszFilter), ulFlags, hMachine); + *pulLen = 2; + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Parent [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Parent( + PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) +{ + TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags); + return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL); +} + + +/*********************************************************************** + * CM_Get_Parent_Ex [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Parent_Ex( + PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine) +{ + TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine); + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Sibling [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Sibling( + PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) +{ + TRACE("%p %p %lx\n", pdnDevInst, dnDevInst, ulFlags); + return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL); +} + + +/*********************************************************************** + * CM_Get_Sibling_Ex [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Get_Sibling_Ex( + PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags, HMACHINE hMachine) +{ + TRACE("%p %lx %lx %lx\n", pdnDevInst, dnDevInst, ulFlags, hMachine); + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Get_Version [SETUPAPI.@] + */ +WORD WINAPI CM_Get_Version(VOID) +{ + TRACE("\n"); + return CM_Get_Version_Ex(NULL); +} + + +/*********************************************************************** + * CM_Get_Version_Ex [SETUPAPI.@] + */ +WORD WINAPI CM_Get_Version_Ex(HMACHINE hMachine) +{ + RPC_BINDING_HANDLE BindingHandle = NULL; + RPC_STATUS Status; + + FIXME("%lx\n", hMachine); + + if (hMachine != NULL) + { + BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle; + if (BindingHandle == NULL) + return 0; + } + else + { + Status = PnpGetLocalBindingHandle(&BindingHandle); + if (Status != RPC_S_OK) + return 0; + } + + return PNP_GetVersion(BindingHandle); +} + + +/*********************************************************************** + * CM_Locate_DevNodeA [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Locate_DevNodeA( + PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags) +{ + FIXME("%p %p %lu\n", pdnDevInst, pDeviceID, ulFlags); + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Locate_DevNodeW [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Locate_DevNodeW( + PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags) +{ + TRACE("%p %p %lu\n", pdnDevInst, pDeviceID, ulFlags); + return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL); +} + + +/*********************************************************************** + * CM_Locate_DevNode_ExA [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Locate_DevNode_ExA( + PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags, HMACHINE hMachine) +{ + FIXME("%p %p %lu %lx\n", pdnDevInst, pDeviceID, ulFlags, hMachine); + return CR_SUCCESS; +} + + +/*********************************************************************** + * CM_Locate_DevNode_ExW [SETUPAPI.@] + */ +CONFIGRET WINAPI CM_Locate_DevNode_ExW( + PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags, HMACHINE hMachine) +{ + FIXME("%p %p %lu %lx\n", pdnDevInst, pDeviceID, ulFlags, hMachine); + return CR_SUCCESS; +} diff --git a/reactos/lib/setupapi/devinst.c b/reactos/lib/setupapi/devinst.c index 2402b126bb8..ea1f3acd066 100644 --- a/reactos/lib/setupapi/devinst.c +++ b/reactos/lib/setupapi/devinst.c @@ -1,1537 +1,1537 @@ -/* - * SetupAPI device installer - * - * Copyright 2000 Andreas Mohr for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include - -#include "windef.h" -#include "winbase.h" -#include "winnt.h" -#include "winreg.h" -#include "winternl.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "setupapi.h" -#include "wine/debug.h" -#include "wine/unicode.h" -#include "cfgmgr32.h" -#include "initguid.h" -#include "winioctl.h" -#include "rpc.h" -#include "rpcdce.h" - -#include "setupapi_private.h" - - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -/* Unicode constants */ -static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; -static const WCHAR Class[] = {'C','l','a','s','s',0}; -static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0}; -static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0}; -static const WCHAR NoInstallClass[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0}; -static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0}; -static const WCHAR NtExtension[] = {'.','N','T',0}; -static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0}; -static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; -static const WCHAR WinExtension[] = {'.','W','i','n',0}; - -/* Registry key and value names */ -static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\', - 'C','l','a','s','s',0}; - -static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\', - 'D','e','v','i','c','e','C','l','a','s','s','e','s',0}; - -/*********************************************************************** - * SetupDiBuildClassInfoList (SETUPAPI.@) - */ -BOOL WINAPI SetupDiBuildClassInfoList( - DWORD Flags, - LPGUID ClassGuidList, - DWORD ClassGuidListSize, - PDWORD RequiredSize) -{ - TRACE("\n"); - return SetupDiBuildClassInfoListExW(Flags, ClassGuidList, - ClassGuidListSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiBuildClassInfoListExA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiBuildClassInfoListExA( - DWORD Flags, - LPGUID ClassGuidList, - DWORD ClassGuidListSize, - PDWORD RequiredSize, - LPCSTR MachineName, - PVOID Reserved) -{ - LPWSTR MachineNameW = NULL; - BOOL bResult; - - TRACE("\n"); - - if (MachineName) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (MachineNameW == NULL) return FALSE; - } - - bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList, - ClassGuidListSize, RequiredSize, - MachineNameW, Reserved); - - if (MachineNameW) - MyFree(MachineNameW); - - return bResult; -} - -/*********************************************************************** - * SetupDiBuildClassInfoListExW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiBuildClassInfoListExW( - DWORD Flags, - LPGUID ClassGuidList, - DWORD ClassGuidListSize, - PDWORD RequiredSize, - LPCWSTR MachineName, - PVOID Reserved) -{ - WCHAR szKeyName[40]; - HKEY hClassesKey; - HKEY hClassKey; - DWORD dwLength; - DWORD dwIndex; - LONG lError; - DWORD dwGuidListIndex = 0; - - TRACE("\n"); - - if (RequiredSize != NULL) - *RequiredSize = 0; - - hClassesKey = SetupDiOpenClassRegKeyExW(NULL, - KEY_ALL_ACCESS, - DIOCR_INSTALLER, - MachineName, - Reserved); - if (hClassesKey == INVALID_HANDLE_VALUE) - { - return FALSE; - } - - for (dwIndex = 0; ; dwIndex++) - { - dwLength = 40; - lError = RegEnumKeyExW(hClassesKey, - dwIndex, - szKeyName, - &dwLength, - NULL, - NULL, - NULL, - NULL); - TRACE("RegEnumKeyExW() returns %ld\n", lError); - if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) - { - TRACE("Key name: %p\n", szKeyName); - - if (RegOpenKeyExW(hClassesKey, - szKeyName, - 0, - KEY_ALL_ACCESS, - &hClassKey)) - { - RegCloseKey(hClassesKey); - return FALSE; - } - - if (!RegQueryValueExW(hClassKey, - NoUseClass, - NULL, - NULL, - NULL, - NULL)) - { - TRACE("'NoUseClass' value found!\n"); - RegCloseKey(hClassKey); - continue; - } - - if ((Flags & DIBCI_NOINSTALLCLASS) && - (!RegQueryValueExW(hClassKey, - NoInstallClass, - NULL, - NULL, - NULL, - NULL))) - { - TRACE("'NoInstallClass' value found!\n"); - RegCloseKey(hClassKey); - continue; - } - - if ((Flags & DIBCI_NODISPLAYCLASS) && - (!RegQueryValueExW(hClassKey, - NoDisplayClass, - NULL, - NULL, - NULL, - NULL))) - { - TRACE("'NoDisplayClass' value found!\n"); - RegCloseKey(hClassKey); - continue; - } - - RegCloseKey(hClassKey); - - TRACE("Guid: %p\n", szKeyName); - if (dwGuidListIndex < ClassGuidListSize) - { - if (szKeyName[0] == L'{' && szKeyName[37] == L'}') - { - szKeyName[37] = 0; - } - TRACE("Guid: %p\n", &szKeyName[1]); - - UuidFromStringW(&szKeyName[1], - &ClassGuidList[dwGuidListIndex]); - } - - dwGuidListIndex++; - } - - if (lError != ERROR_SUCCESS) - break; - } - - RegCloseKey(hClassesKey); - - if (RequiredSize != NULL) - *RequiredSize = dwGuidListIndex; - - if (ClassGuidListSize < dwGuidListIndex) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - return TRUE; -} - -/*********************************************************************** - * SetupDiClassGuidsFromNameA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassGuidsFromNameA( - LPCSTR ClassName, - LPGUID ClassGuidList, - DWORD ClassGuidListSize, - PDWORD RequiredSize) -{ - return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, - ClassGuidListSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiClassGuidsFromNameW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassGuidsFromNameW( - LPCWSTR ClassName, - LPGUID ClassGuidList, - DWORD ClassGuidListSize, - PDWORD RequiredSize) -{ - return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, - ClassGuidListSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiClassGuidsFromNameExA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassGuidsFromNameExA( - LPCSTR ClassName, - LPGUID ClassGuidList, - DWORD ClassGuidListSize, - PDWORD RequiredSize, - LPCSTR MachineName, - PVOID Reserved) -{ - LPWSTR ClassNameW = NULL; - LPWSTR MachineNameW = NULL; - BOOL bResult; - - FIXME("\n"); - - ClassNameW = MultiByteToUnicode(ClassName, CP_ACP); - if (ClassNameW == NULL) - return FALSE; - - if (MachineNameW) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (MachineNameW == NULL) - { - MyFree(ClassNameW); - return FALSE; - } - } - - bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, - ClassGuidListSize, RequiredSize, - MachineNameW, Reserved); - - if (MachineNameW) - MyFree(MachineNameW); - - MyFree(ClassNameW); - - return bResult; -} - -/*********************************************************************** - * SetupDiClassGuidsFromNameExW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassGuidsFromNameExW( - LPCWSTR ClassName, - LPGUID ClassGuidList, - DWORD ClassGuidListSize, - PDWORD RequiredSize, - LPCWSTR MachineName, - PVOID Reserved) -{ - WCHAR szKeyName[40]; - WCHAR szClassName[256]; - HKEY hClassesKey; - HKEY hClassKey; - DWORD dwLength; - DWORD dwIndex; - LONG lError; - DWORD dwGuidListIndex = 0; - - if (RequiredSize != NULL) - *RequiredSize = 0; - - hClassesKey = SetupDiOpenClassRegKeyExW(NULL, - KEY_ALL_ACCESS, - DIOCR_INSTALLER, - MachineName, - Reserved); - if (hClassesKey == INVALID_HANDLE_VALUE) - { - return FALSE; - } - - for (dwIndex = 0; ; dwIndex++) - { - dwLength = 40; - lError = RegEnumKeyExW(hClassesKey, - dwIndex, - szKeyName, - &dwLength, - NULL, - NULL, - NULL, - NULL); - TRACE("RegEnumKeyExW() returns %ld\n", lError); - if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) - { - TRACE("Key name: %p\n", szKeyName); - - if (RegOpenKeyExW(hClassesKey, - szKeyName, - 0, - KEY_ALL_ACCESS, - &hClassKey)) - { - RegCloseKey(hClassesKey); - return FALSE; - } - - dwLength = 256 * sizeof(WCHAR); - if (!RegQueryValueExW(hClassKey, - Class, - NULL, - NULL, - (LPBYTE)szClassName, - &dwLength)) - { - TRACE("Class name: %p\n", szClassName); - - if (strcmpiW(szClassName, ClassName) == 0) - { - TRACE("Found matching class name\n"); - - TRACE("Guid: %p\n", szKeyName); - if (dwGuidListIndex < ClassGuidListSize) - { - if (szKeyName[0] == L'{' && szKeyName[37] == L'}') - { - szKeyName[37] = 0; - } - TRACE("Guid: %p\n", &szKeyName[1]); - - UuidFromStringW(&szKeyName[1], - &ClassGuidList[dwGuidListIndex]); - } - - dwGuidListIndex++; - } - } - - RegCloseKey(hClassKey); - } - - if (lError != ERROR_SUCCESS) - break; - } - - RegCloseKey(hClassesKey); - - if (RequiredSize != NULL) - *RequiredSize = dwGuidListIndex; - - if (ClassGuidListSize < dwGuidListIndex) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - return TRUE; -} - -/*********************************************************************** - * SetupDiClassNameFromGuidA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassNameFromGuidA( - const GUID* ClassGuid, - PSTR ClassName, - DWORD ClassNameSize, - PDWORD RequiredSize) -{ - return SetupDiClassNameFromGuidExA(ClassGuid, ClassName, - ClassNameSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiClassNameFromGuidW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassNameFromGuidW( - const GUID* ClassGuid, - PWSTR ClassName, - DWORD ClassNameSize, - PDWORD RequiredSize) -{ - return SetupDiClassNameFromGuidExW(ClassGuid, ClassName, - ClassNameSize, RequiredSize, - NULL, NULL); -} - -/*********************************************************************** - * SetupDiClassNameFromGuidExA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassNameFromGuidExA( - const GUID* ClassGuid, - PSTR ClassName, - DWORD ClassNameSize, - PDWORD RequiredSize, - PCSTR MachineName, - PVOID Reserved) -{ - WCHAR ClassNameW[MAX_CLASS_NAME_LEN]; - LPWSTR MachineNameW = NULL; - BOOL ret; - - if (MachineName) - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN, - NULL, MachineNameW, Reserved); - if (ret) - { - int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, - ClassNameSize, NULL, NULL); - - if (!ClassNameSize && RequiredSize) - *RequiredSize = len; - } - MyFree(MachineNameW); - return ret; -} - -/*********************************************************************** - * SetupDiClassNameFromGuidExW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiClassNameFromGuidExW( - const GUID* ClassGuid, - PWSTR ClassName, - DWORD ClassNameSize, - PDWORD RequiredSize, - PCWSTR MachineName, - PVOID Reserved) -{ - HKEY hKey; - DWORD dwLength; - - hKey = SetupDiOpenClassRegKeyExW(ClassGuid, - KEY_ALL_ACCESS, - DIOCR_INSTALLER, - MachineName, - Reserved); - if (hKey == INVALID_HANDLE_VALUE) - { - return FALSE; - } - - if (RequiredSize != NULL) - { - dwLength = 0; - if (RegQueryValueExW(hKey, - Class, - NULL, - NULL, - NULL, - &dwLength)) - { - RegCloseKey(hKey); - return FALSE; - } - - *RequiredSize = dwLength / sizeof(WCHAR); - } - - dwLength = ClassNameSize * sizeof(WCHAR); - if (RegQueryValueExW(hKey, - Class, - NULL, - NULL, - (LPBYTE)ClassName, - &dwLength)) - { - RegCloseKey(hKey); - return FALSE; - } - - RegCloseKey(hKey); - - return TRUE; -} - -/*********************************************************************** - * SetupDiCreateDeviceInfoList (SETUPAPI.@) - */ -HDEVINFO WINAPI -SetupDiCreateDeviceInfoList(const GUID *ClassGuid, - HWND hwndParent) -{ - return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL); -} - -/*********************************************************************** - * SetupDiCreateDeviceInfoListExA (SETUPAPI.@) - */ -HDEVINFO WINAPI -SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid, - HWND hwndParent, - PCSTR MachineName, - PVOID Reserved) -{ - LPWSTR MachineNameW = NULL; - HDEVINFO hDevInfo; - - TRACE("\n"); - - if (MachineName) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (MachineNameW == NULL) - return (HDEVINFO)INVALID_HANDLE_VALUE; - } - - hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, - MachineNameW, Reserved); - - if (MachineNameW) - MyFree(MachineNameW); - - return hDevInfo; -} - -/*********************************************************************** - * SetupDiCreateDeviceInfoListExW (SETUPAPI.@) - */ -HDEVINFO WINAPI -SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid, - HWND hwndParent, - PCWSTR MachineName, - PVOID Reserved) -{ - FIXME("\n"); - return (HDEVINFO)INVALID_HANDLE_VALUE; -} - -/*********************************************************************** - * SetupDiEnumDeviceInfo (SETUPAPI.@) - */ -BOOL WINAPI SetupDiEnumDeviceInfo( - HDEVINFO devinfo, - DWORD index, - PSP_DEVINFO_DATA info) -{ - FIXME("%p %ld %p\n", devinfo, index, info); - - if(info==NULL) - return FALSE; - if(info->cbSize < sizeof(*info)) - return FALSE; - - return FALSE; -} - -/*********************************************************************** - * SetupDiGetActualSectionToInstallA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetActualSectionToInstallA( - HINF InfHandle, - PCSTR InfSectionName, - PSTR InfSectionWithExt, - DWORD InfSectionWithExtSize, - PDWORD RequiredSize, - PSTR *Extension) -{ - FIXME("\n"); - return FALSE; -} - -/*********************************************************************** - * SetupDiGetActualSectionToInstallW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetActualSectionToInstallW( - HINF InfHandle, - PCWSTR InfSectionName, - PWSTR InfSectionWithExt, - DWORD InfSectionWithExtSize, - PDWORD RequiredSize, - PWSTR *Extension) -{ - WCHAR szBuffer[MAX_PATH]; - DWORD dwLength; - DWORD dwFullLength; - LONG lLineCount = -1; - - lstrcpyW(szBuffer, InfSectionName); - dwLength = lstrlenW(szBuffer); - - if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) - { - /* Test section name with '.NTx86' extension */ - lstrcpyW(&szBuffer[dwLength], NtPlatformExtension); - lLineCount = SetupGetLineCountW(InfHandle, szBuffer); - - if (lLineCount == -1) - { - /* Test section name with '.NT' extension */ - lstrcpyW(&szBuffer[dwLength], NtExtension); - lLineCount = SetupGetLineCountW(InfHandle, szBuffer); - } - } - else - { - /* Test section name with '.Win' extension */ - lstrcpyW(&szBuffer[dwLength], WinExtension); - lLineCount = SetupGetLineCountW(InfHandle, szBuffer); - } - - if (lLineCount == -1) - { - /* Test section name without extension */ - szBuffer[dwLength] = 0; - lLineCount = SetupGetLineCountW(InfHandle, szBuffer); - } - - if (lLineCount == -1) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - dwFullLength = lstrlenW(szBuffer); - - if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0) - { - if (InfSectionWithExtSize < (dwFullLength + 1)) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - lstrcpyW(InfSectionWithExt, szBuffer); - if (Extension != NULL) - { - *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength]; - } - } - - if (RequiredSize != NULL) - { - *RequiredSize = dwFullLength + 1; - } - - return TRUE; -} - -/*********************************************************************** - * SetupDiGetClassDescriptionA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetClassDescriptionA( - const GUID* ClassGuid, - PSTR ClassDescription, - DWORD ClassDescriptionSize, - PDWORD RequiredSize) -{ - return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription, - ClassDescriptionSize, - RequiredSize, NULL, NULL); -} - -/*********************************************************************** - * SetupDiGetClassDescriptionW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetClassDescriptionW( - const GUID* ClassGuid, - PWSTR ClassDescription, - DWORD ClassDescriptionSize, - PDWORD RequiredSize) -{ - return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription, - ClassDescriptionSize, - RequiredSize, NULL, NULL); -} - -/*********************************************************************** - * SetupDiGetClassDescriptionExA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetClassDescriptionExA( - const GUID* ClassGuid, - PSTR ClassDescription, - DWORD ClassDescriptionSize, - PDWORD RequiredSize, - PCSTR MachineName, - PVOID Reserved) -{ - FIXME("\n"); - return FALSE; -} - -/*********************************************************************** - * SetupDiGetClassDescriptionExW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetClassDescriptionExW( - const GUID* ClassGuid, - PWSTR ClassDescription, - DWORD ClassDescriptionSize, - PDWORD RequiredSize, - PCWSTR MachineName, - PVOID Reserved) -{ - HKEY hKey; - DWORD dwLength; - - hKey = SetupDiOpenClassRegKeyExW(ClassGuid, - KEY_ALL_ACCESS, - DIOCR_INSTALLER, - MachineName, - Reserved); - if (hKey == INVALID_HANDLE_VALUE) - { - WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError()); - return FALSE; - } - - if (RequiredSize != NULL) - { - dwLength = 0; - if (RegQueryValueExW(hKey, - NULL, - NULL, - NULL, - NULL, - &dwLength)) - { - RegCloseKey(hKey); - return FALSE; - } - - *RequiredSize = dwLength / sizeof(WCHAR); - } - - dwLength = ClassDescriptionSize * sizeof(WCHAR); - if (RegQueryValueExW(hKey, - NULL, - NULL, - NULL, - (LPBYTE)ClassDescription, - &dwLength)) - { - RegCloseKey(hKey); - return FALSE; - } - - RegCloseKey(hKey); - - return TRUE; -} - -/*********************************************************************** - * SetupDiGetClassDevsA (SETUPAPI.@) - */ -HDEVINFO WINAPI SetupDiGetClassDevsA( - CONST GUID *class, - LPCSTR enumstr, - HWND parent, - DWORD flags) -{ - HDEVINFO ret; - LPWSTR enumstrW = NULL; - - if (enumstr) - { - int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0); - enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - if (!enumstrW) - { - ret = (HDEVINFO)INVALID_HANDLE_VALUE; - goto end; - } - MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len); - } - ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags); - HeapFree(GetProcessHeap(), 0, enumstrW); - -end: - return ret; -} - -#define SETUP_SERIAL_PORT_MAGIC 0xd00ff055 - -typedef struct _SerialPortName -{ - WCHAR name[5]; -} SerialPortName; - -typedef struct _SerialPortList -{ - DWORD magic; - UINT numPorts; - SerialPortName names[1]; -} SerialPortList; - -static HDEVINFO SETUP_CreateSerialDeviceList(void) -{ - static const size_t initialSize = 100; - size_t size; - WCHAR buf[initialSize]; - LPWSTR devices; - HDEVINFO ret; - BOOL failed = FALSE; - - devices = buf; - size = initialSize; - do { - if (QueryDosDeviceW(NULL, devices, size) == 0) - { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - size *= 2; - if (devices != buf) - HeapFree(GetProcessHeap(), 0, devices); - devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); - if (!devices) - failed = TRUE; - else - *devices = 0; - } - else - failed = TRUE; - } - } while (!*devices && !failed); - if (!failed) - { - static const WCHAR comW[] = { 'C','O','M',0 }; - LPWSTR ptr; - UINT numSerialPorts = 0; - SerialPortList *list; - - for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1) - { - if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1)) - numSerialPorts++; - } - list = HeapAlloc(GetProcessHeap(), 0, sizeof(SerialPortList) + - numSerialPorts ? (numSerialPorts - 1) * sizeof(SerialPortName) : 0); - if (list) - { - list->magic = SETUP_SERIAL_PORT_MAGIC; - list->numPorts = 0; - for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1) - { - if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1)) - { - lstrcpynW(list->names[list->numPorts].name, ptr, - sizeof(list->names[list->numPorts].name) / - sizeof(list->names[list->numPorts].name[0])); - TRACE("Adding %s to list\n", - debugstr_w(list->names[list->numPorts].name)); - list->numPorts++; - } - } - TRACE("list->numPorts is %d\n", list->numPorts); - } - ret = (HDEVINFO)list; - } - else - ret = (HDEVINFO)INVALID_HANDLE_VALUE; - if (devices != buf) - HeapFree(GetProcessHeap(), 0, devices); - TRACE("returning %p\n", ret); - return ret; -} - -/*********************************************************************** - * SetupDiGetClassDevsW (SETUPAPI.@) - */ -HDEVINFO WINAPI SetupDiGetClassDevsW( - CONST GUID *class, - LPCWSTR enumstr, - HWND parent, - DWORD flags) -{ - HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE; - - TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr), - parent, flags); - - if (enumstr) - FIXME(": unimplemented for enumerator strings (%s)\n", - debugstr_w(enumstr)); - else if (flags & DIGCF_ALLCLASSES) - FIXME(": unimplemented for DIGCF_ALLCLASSES\n"); - else - { - if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT)) - ret = SETUP_CreateSerialDeviceList(); - else if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR)) - ret = SETUP_CreateSerialDeviceList(); - else - FIXME("(%s): stub\n", debugstr_guid(class)); - } - return ret; -} - -/*********************************************************************** - * SetupDiEnumDeviceInterfaces (SETUPAPI.@) - */ -BOOL WINAPI SetupDiEnumDeviceInterfaces( - HDEVINFO DeviceInfoSet, - PSP_DEVINFO_DATA DeviceInfoData, - CONST GUID * InterfaceClassGuid, - DWORD MemberIndex, - PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) -{ - BOOL ret = FALSE; - - TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData, - debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); - if (!DeviceInterfaceData) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInfoData) - FIXME(": unimplemented with PSP_DEVINFO_DATA set\n"); - else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE) - { - /* FIXME: this assumes the only possible enumeration is of serial - * ports. - */ - SerialPortList *list = (SerialPortList *)DeviceInfoSet; - - if (list->magic == SETUP_SERIAL_PORT_MAGIC) - { - if (MemberIndex >= list->numPorts) - SetLastError(ERROR_NO_MORE_ITEMS); - else - { - DeviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - memcpy(&DeviceInterfaceData->InterfaceClassGuid, - &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, - sizeof(DeviceInterfaceData->InterfaceClassGuid)); - DeviceInterfaceData->Flags = 0; - /* Note: this appears to be dangerous, passing a private - * pointer a heap-allocated datum to the caller. However, the - * expected lifetime of the device data is the same as the - * HDEVINFO; once that is closed, the data are no longer valid. - */ - DeviceInterfaceData->Reserved = - (ULONG_PTR)&list->names[MemberIndex].name; - ret = TRUE; - } - } - else - SetLastError(ERROR_INVALID_HANDLE); - } - else - SetLastError(ERROR_INVALID_HANDLE); - return ret; -} - -/*********************************************************************** - * SetupDiDestroyDeviceInfoList (SETUPAPI.@) - */ -BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) -{ - BOOL ret = FALSE; - - TRACE("%p\n", devinfo); - if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE) - { - /* FIXME: this assumes the only possible enumeration is of serial - * ports. - */ - SerialPortList *list = (SerialPortList *)devinfo; - - if (list->magic == SETUP_SERIAL_PORT_MAGIC) - { - HeapFree(GetProcessHeap(), 0, list); - ret = TRUE; - } - else - SetLastError(ERROR_INVALID_HANDLE); - } - else - SetLastError(ERROR_INVALID_HANDLE); - return ret; -} - -/*********************************************************************** - * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetDeviceInterfaceDetailA( - HDEVINFO DeviceInfoSet, - PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, - PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, - DWORD DeviceInterfaceDetailDataSize, - PDWORD RequiredSize, - PSP_DEVINFO_DATA DeviceInfoData) -{ - BOOL ret = FALSE; - - TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet, - DeviceInterfaceData, DeviceInterfaceDetailData, - DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); - if (!DeviceInterfaceData) - SetLastError(ERROR_INVALID_PARAMETER); - else if ((DeviceInterfaceDetailDataSize && !DeviceInterfaceDetailData) || - (DeviceInterfaceDetailData && !DeviceInterfaceDetailDataSize)) - SetLastError(ERROR_INVALID_PARAMETER); - else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE) - { - /* FIXME: this assumes the only possible enumeration is of serial - * ports. - */ - SerialPortList *list = (SerialPortList *)DeviceInfoSet; - - if (list->magic == SETUP_SERIAL_PORT_MAGIC) - { - LPCWSTR devName = (LPCWSTR)DeviceInterfaceData->Reserved; - DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A) + - lstrlenW(devName); - - if (sizeRequired > DeviceInterfaceDetailDataSize) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - if (RequiredSize) - *RequiredSize = sizeRequired; - } - else - { - LPSTR dst = DeviceInterfaceDetailData->DevicePath; - LPCWSTR src = devName; - - /* MSDN claims cbSize must be set by the caller, but it lies */ - DeviceInterfaceDetailData->cbSize = - sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - for ( ; *src; src++, dst++) - *dst = *src; - *dst = '\0'; - TRACE("DevicePath is %s\n", - debugstr_a(DeviceInterfaceDetailData->DevicePath)); - if (DeviceInfoData) - { - DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA); - memcpy(&DeviceInfoData->ClassGuid, - &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, - sizeof(DeviceInfoData->ClassGuid)); - DeviceInfoData->DevInst = 0; - DeviceInfoData->Reserved = (ULONG_PTR)devName; - } - ret = TRUE; - } - } - else - SetLastError(ERROR_INVALID_HANDLE); - } - else - SetLastError(ERROR_INVALID_HANDLE); - TRACE("Returning %d\n", ret); - return ret; -} - -/*********************************************************************** - * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetDeviceInterfaceDetailW( - HDEVINFO DeviceInfoSet, - PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, - PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData, - DWORD DeviceInterfaceDetailDataSize, - PDWORD RequiredSize, - PSP_DEVINFO_DATA DeviceInfoData) -{ - FIXME("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet, - DeviceInterfaceData, DeviceInterfaceDetailData, - DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); - return FALSE; -} - -/*********************************************************************** - * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetDeviceRegistryPropertyA( - HDEVINFO devinfo, - PSP_DEVINFO_DATA DeviceInfoData, - DWORD Property, - PDWORD PropertyRegDataType, - PBYTE PropertyBuffer, - DWORD PropertyBufferSize, - PDWORD RequiredSize) -{ - FIXME("%04lx %p %ld %p %p %ld %p\n", (DWORD)devinfo, DeviceInfoData, - Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, - RequiredSize); - return FALSE; -} - -/*********************************************************************** - * SetupDiInstallClassA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiInstallClassA( - HWND hwndParent, - PCSTR InfFileName, - DWORD Flags, - HSPFILEQ FileQueue) -{ - UNICODE_STRING FileNameW; - BOOL Result; - - if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName)) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue); - - RtlFreeUnicodeString(&FileNameW); - - return Result; -} - -static HKEY CreateClassKey(HINF hInf) -{ - WCHAR FullBuffer[MAX_PATH]; - WCHAR Buffer[MAX_PATH]; - DWORD RequiredSize; - HKEY hClassKey; - - Buffer[0] = '\\'; - if (!SetupGetLineTextW(NULL, - hInf, - Version, - ClassGUID, - &Buffer[1], - MAX_PATH - 1, - &RequiredSize)) - { - return INVALID_HANDLE_VALUE; - } - - lstrcpyW(FullBuffer, ControlClass); - lstrcatW(FullBuffer, Buffer); - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - FullBuffer, - 0, - KEY_ALL_ACCESS, - &hClassKey)) - { - if (!SetupGetLineTextW(NULL, - hInf, - Version, - Class, - Buffer, - MAX_PATH, - &RequiredSize)) - { - return INVALID_HANDLE_VALUE; - } - - if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, - FullBuffer, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &hClassKey, - NULL)) - { - return INVALID_HANDLE_VALUE; - } - - } - - if (RegSetValueExW(hClassKey, - Class, - 0, - REG_SZ, - (LPBYTE)Buffer, - RequiredSize * sizeof(WCHAR))) - { - RegCloseKey(hClassKey); - RegDeleteKeyW(HKEY_LOCAL_MACHINE, - FullBuffer); - return INVALID_HANDLE_VALUE; - } - - return hClassKey; -} - -/*********************************************************************** - * SetupDiInstallClassW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiInstallClassW( - HWND hwndParent, - PCWSTR InfFileName, - DWORD Flags, - HSPFILEQ FileQueue) -{ - WCHAR SectionName[MAX_PATH]; - DWORD SectionNameLength = 0; - HINF hInf; - BOOL bFileQueueCreated = FALSE; - HKEY hClassKey; - - FIXME("not fully implemented\n"); - - if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* Open the .inf file */ - hInf = SetupOpenInfFileW(InfFileName, - NULL, - INF_STYLE_WIN4, - NULL); - if (hInf == INVALID_HANDLE_VALUE) - { - - return FALSE; - } - - /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */ - hClassKey = CreateClassKey(hInf); - if (hClassKey == INVALID_HANDLE_VALUE) - { - SetupCloseInfFile(hInf); - return FALSE; - } - - - /* Try to append a layout file */ -#if 0 - SetupOpenAppendInfFileW(NULL, hInf, NULL); -#endif - - /* Retrieve the actual section name */ - SetupDiGetActualSectionToInstallW(hInf, - ClassInstall32, - SectionName, - MAX_PATH, - &SectionNameLength, - NULL); - -#if 0 - if (!(Flags & DI_NOVCP)) - { - FileQueue = SetupOpenFileQueue(); - if (FileQueue == INVALID_HANDLE_VALUE) - { - SetupCloseInfFile(hInf); - return FALSE; - } - - bFileQueueCreated = TRUE; - - } -#endif - - SetupInstallFromInfSectionW(NULL, - hInf, - SectionName, - SPINST_REGISTRY, - hClassKey, - NULL, - 0, - NULL, - NULL, - INVALID_HANDLE_VALUE, - NULL); - - /* FIXME: More code! */ - - if (bFileQueueCreated) - SetupCloseFileQueue(FileQueue); - - SetupCloseInfFile(hInf); - - return TRUE; -} - - -/*********************************************************************** - * SetupDiOpenClassRegKey (SETUPAPI.@) - */ -HKEY WINAPI SetupDiOpenClassRegKey( - const GUID* ClassGuid, - REGSAM samDesired) -{ - return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, - DIOCR_INSTALLER, NULL, NULL); -} - - -/*********************************************************************** - * SetupDiOpenClassRegKeyExA (SETUPAPI.@) - */ -HKEY WINAPI SetupDiOpenClassRegKeyExA( - const GUID* ClassGuid, - REGSAM samDesired, - DWORD Flags, - PCSTR MachineName, - PVOID Reserved) -{ - PWSTR MachineNameW = NULL; - HKEY hKey; - - TRACE("\n"); - - if (MachineName) - { - MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); - if (MachineNameW == NULL) - return INVALID_HANDLE_VALUE; - } - - hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, - Flags, MachineNameW, Reserved); - - if (MachineNameW) - MyFree(MachineNameW); - - return hKey; -} - - -/*********************************************************************** - * SetupDiOpenClassRegKeyExW (SETUPAPI.@) - */ -HKEY WINAPI SetupDiOpenClassRegKeyExW( - const GUID* ClassGuid, - REGSAM samDesired, - DWORD Flags, - PCWSTR MachineName, - PVOID Reserved) -{ - LPWSTR lpGuidString; - HKEY hClassesKey; - HKEY hClassKey; - LPCWSTR lpKeyName; - - if (MachineName != NULL) - { - FIXME("Remote access not supported yet!\n"); - return INVALID_HANDLE_VALUE; - } - - if (Flags == DIOCR_INSTALLER) - { - lpKeyName = ControlClass; - } - else if (Flags == DIOCR_INTERFACE) - { - lpKeyName = DeviceClasses; - } - else - { - ERR("Invalid Flags parameter!\n"); - SetLastError(ERROR_INVALID_PARAMETER); - return INVALID_HANDLE_VALUE; - } - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - lpKeyName, - 0, - KEY_ALL_ACCESS, - &hClassesKey)) - { - return INVALID_HANDLE_VALUE; - } - - if (ClassGuid == NULL) - return hClassesKey; - - if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK) - { - RegCloseKey(hClassesKey); - return INVALID_HANDLE_VALUE; - } - - if (RegOpenKeyExW(hClassesKey, - lpGuidString, - 0, - KEY_ALL_ACCESS, - &hClassKey)) - { - RpcStringFreeW(&lpGuidString); - RegCloseKey(hClassesKey); - return INVALID_HANDLE_VALUE; - } - - RpcStringFreeW(&lpGuidString); - RegCloseKey(hClassesKey); - - return hClassKey; -} - -/*********************************************************************** - * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiOpenDeviceInterfaceW( - HDEVINFO DeviceInfoSet, - PCWSTR DevicePath, - DWORD OpenFlags, - PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) -{ - FIXME("%p %s %08lx %p\n", - DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData); - return FALSE; -} - -/*********************************************************************** - * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiOpenDeviceInterfaceA( - HDEVINFO DeviceInfoSet, - PCSTR DevicePath, - DWORD OpenFlags, - PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) -{ - FIXME("%p %s %08lx %p\n", DeviceInfoSet, - debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData); - return FALSE; -} - -/*********************************************************************** - * SetupDiSetClassInstallParamsA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiSetClassInstallParamsA( - HDEVINFO DeviceInfoSet, - PSP_DEVINFO_DATA DeviceInfoData, - PSP_CLASSINSTALL_HEADER ClassInstallParams, - DWORD ClassInstallParamsSize) -{ - FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData, - ClassInstallParams->InstallFunction, ClassInstallParamsSize); - return FALSE; -} - -/*********************************************************************** - * SetupDiCallClassInstaller (SETUPAPI.@) - */ -BOOL WINAPI SetupDiCallClassInstaller( - DWORD InstallFunction, - HDEVINFO DeviceInfoSet, - PSP_DEVINFO_DATA DeviceInfoData) -{ - FIXME("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData); - return FALSE; -} - -/*********************************************************************** - * SetupDiGetDeviceInstallParamsA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetDeviceInstallParamsA( - HDEVINFO DeviceInfoSet, - PSP_DEVINFO_DATA DeviceInfoData, - PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) -{ - FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); - return FALSE; -} - -/*********************************************************************** - * SetupDiOpenDevRegKey (SETUPAPI.@) - */ -HKEY WINAPI SetupDiOpenDevRegKey( - HDEVINFO DeviceInfoSet, - PSP_DEVINFO_DATA DeviceInfoData, - DWORD Scope, - DWORD HwProfile, - DWORD KeyType, - REGSAM samDesired) -{ - FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData, - Scope, HwProfile, KeyType, samDesired); - return INVALID_HANDLE_VALUE; -} +/* + * SetupAPI device installer + * + * Copyright 2000 Andreas Mohr for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include + +#include "windef.h" +#include "winbase.h" +#include "winnt.h" +#include "winreg.h" +#include "winternl.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "setupapi.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "cfgmgr32.h" +#include "initguid.h" +#include "winioctl.h" +#include "rpc.h" +#include "rpcdce.h" + +#include "setupapi_private.h" + + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +/* Unicode constants */ +static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; +static const WCHAR Class[] = {'C','l','a','s','s',0}; +static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0}; +static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0}; +static const WCHAR NoInstallClass[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0}; +static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0}; +static const WCHAR NtExtension[] = {'.','N','T',0}; +static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0}; +static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; +static const WCHAR WinExtension[] = {'.','W','i','n',0}; + +/* Registry key and value names */ +static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\', + 'C','l','a','s','s',0}; + +static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\', + 'D','e','v','i','c','e','C','l','a','s','s','e','s',0}; + +/*********************************************************************** + * SetupDiBuildClassInfoList (SETUPAPI.@) + */ +BOOL WINAPI SetupDiBuildClassInfoList( + DWORD Flags, + LPGUID ClassGuidList, + DWORD ClassGuidListSize, + PDWORD RequiredSize) +{ + TRACE("\n"); + return SetupDiBuildClassInfoListExW(Flags, ClassGuidList, + ClassGuidListSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiBuildClassInfoListExA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiBuildClassInfoListExA( + DWORD Flags, + LPGUID ClassGuidList, + DWORD ClassGuidListSize, + PDWORD RequiredSize, + LPCSTR MachineName, + PVOID Reserved) +{ + LPWSTR MachineNameW = NULL; + BOOL bResult; + + TRACE("\n"); + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) return FALSE; + } + + bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList, + ClassGuidListSize, RequiredSize, + MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return bResult; +} + +/*********************************************************************** + * SetupDiBuildClassInfoListExW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiBuildClassInfoListExW( + DWORD Flags, + LPGUID ClassGuidList, + DWORD ClassGuidListSize, + PDWORD RequiredSize, + LPCWSTR MachineName, + PVOID Reserved) +{ + WCHAR szKeyName[40]; + HKEY hClassesKey; + HKEY hClassKey; + DWORD dwLength; + DWORD dwIndex; + LONG lError; + DWORD dwGuidListIndex = 0; + + TRACE("\n"); + + if (RequiredSize != NULL) + *RequiredSize = 0; + + hClassesKey = SetupDiOpenClassRegKeyExW(NULL, + KEY_ALL_ACCESS, + DIOCR_INSTALLER, + MachineName, + Reserved); + if (hClassesKey == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + for (dwIndex = 0; ; dwIndex++) + { + dwLength = 40; + lError = RegEnumKeyExW(hClassesKey, + dwIndex, + szKeyName, + &dwLength, + NULL, + NULL, + NULL, + NULL); + TRACE("RegEnumKeyExW() returns %ld\n", lError); + if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) + { + TRACE("Key name: %p\n", szKeyName); + + if (RegOpenKeyExW(hClassesKey, + szKeyName, + 0, + KEY_ALL_ACCESS, + &hClassKey)) + { + RegCloseKey(hClassesKey); + return FALSE; + } + + if (!RegQueryValueExW(hClassKey, + NoUseClass, + NULL, + NULL, + NULL, + NULL)) + { + TRACE("'NoUseClass' value found!\n"); + RegCloseKey(hClassKey); + continue; + } + + if ((Flags & DIBCI_NOINSTALLCLASS) && + (!RegQueryValueExW(hClassKey, + NoInstallClass, + NULL, + NULL, + NULL, + NULL))) + { + TRACE("'NoInstallClass' value found!\n"); + RegCloseKey(hClassKey); + continue; + } + + if ((Flags & DIBCI_NODISPLAYCLASS) && + (!RegQueryValueExW(hClassKey, + NoDisplayClass, + NULL, + NULL, + NULL, + NULL))) + { + TRACE("'NoDisplayClass' value found!\n"); + RegCloseKey(hClassKey); + continue; + } + + RegCloseKey(hClassKey); + + TRACE("Guid: %p\n", szKeyName); + if (dwGuidListIndex < ClassGuidListSize) + { + if (szKeyName[0] == L'{' && szKeyName[37] == L'}') + { + szKeyName[37] = 0; + } + TRACE("Guid: %p\n", &szKeyName[1]); + + UuidFromStringW(&szKeyName[1], + &ClassGuidList[dwGuidListIndex]); + } + + dwGuidListIndex++; + } + + if (lError != ERROR_SUCCESS) + break; + } + + RegCloseKey(hClassesKey); + + if (RequiredSize != NULL) + *RequiredSize = dwGuidListIndex; + + if (ClassGuidListSize < dwGuidListIndex) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + return TRUE; +} + +/*********************************************************************** + * SetupDiClassGuidsFromNameA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassGuidsFromNameA( + LPCSTR ClassName, + LPGUID ClassGuidList, + DWORD ClassGuidListSize, + PDWORD RequiredSize) +{ + return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, + ClassGuidListSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiClassGuidsFromNameW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassGuidsFromNameW( + LPCWSTR ClassName, + LPGUID ClassGuidList, + DWORD ClassGuidListSize, + PDWORD RequiredSize) +{ + return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, + ClassGuidListSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiClassGuidsFromNameExA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassGuidsFromNameExA( + LPCSTR ClassName, + LPGUID ClassGuidList, + DWORD ClassGuidListSize, + PDWORD RequiredSize, + LPCSTR MachineName, + PVOID Reserved) +{ + LPWSTR ClassNameW = NULL; + LPWSTR MachineNameW = NULL; + BOOL bResult; + + FIXME("\n"); + + ClassNameW = MultiByteToUnicode(ClassName, CP_ACP); + if (ClassNameW == NULL) + return FALSE; + + if (MachineNameW) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + { + MyFree(ClassNameW); + return FALSE; + } + } + + bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, + ClassGuidListSize, RequiredSize, + MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + MyFree(ClassNameW); + + return bResult; +} + +/*********************************************************************** + * SetupDiClassGuidsFromNameExW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassGuidsFromNameExW( + LPCWSTR ClassName, + LPGUID ClassGuidList, + DWORD ClassGuidListSize, + PDWORD RequiredSize, + LPCWSTR MachineName, + PVOID Reserved) +{ + WCHAR szKeyName[40]; + WCHAR szClassName[256]; + HKEY hClassesKey; + HKEY hClassKey; + DWORD dwLength; + DWORD dwIndex; + LONG lError; + DWORD dwGuidListIndex = 0; + + if (RequiredSize != NULL) + *RequiredSize = 0; + + hClassesKey = SetupDiOpenClassRegKeyExW(NULL, + KEY_ALL_ACCESS, + DIOCR_INSTALLER, + MachineName, + Reserved); + if (hClassesKey == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + for (dwIndex = 0; ; dwIndex++) + { + dwLength = 40; + lError = RegEnumKeyExW(hClassesKey, + dwIndex, + szKeyName, + &dwLength, + NULL, + NULL, + NULL, + NULL); + TRACE("RegEnumKeyExW() returns %ld\n", lError); + if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) + { + TRACE("Key name: %p\n", szKeyName); + + if (RegOpenKeyExW(hClassesKey, + szKeyName, + 0, + KEY_ALL_ACCESS, + &hClassKey)) + { + RegCloseKey(hClassesKey); + return FALSE; + } + + dwLength = 256 * sizeof(WCHAR); + if (!RegQueryValueExW(hClassKey, + Class, + NULL, + NULL, + (LPBYTE)szClassName, + &dwLength)) + { + TRACE("Class name: %p\n", szClassName); + + if (strcmpiW(szClassName, ClassName) == 0) + { + TRACE("Found matching class name\n"); + + TRACE("Guid: %p\n", szKeyName); + if (dwGuidListIndex < ClassGuidListSize) + { + if (szKeyName[0] == L'{' && szKeyName[37] == L'}') + { + szKeyName[37] = 0; + } + TRACE("Guid: %p\n", &szKeyName[1]); + + UuidFromStringW(&szKeyName[1], + &ClassGuidList[dwGuidListIndex]); + } + + dwGuidListIndex++; + } + } + + RegCloseKey(hClassKey); + } + + if (lError != ERROR_SUCCESS) + break; + } + + RegCloseKey(hClassesKey); + + if (RequiredSize != NULL) + *RequiredSize = dwGuidListIndex; + + if (ClassGuidListSize < dwGuidListIndex) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + return TRUE; +} + +/*********************************************************************** + * SetupDiClassNameFromGuidA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassNameFromGuidA( + const GUID* ClassGuid, + PSTR ClassName, + DWORD ClassNameSize, + PDWORD RequiredSize) +{ + return SetupDiClassNameFromGuidExA(ClassGuid, ClassName, + ClassNameSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiClassNameFromGuidW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassNameFromGuidW( + const GUID* ClassGuid, + PWSTR ClassName, + DWORD ClassNameSize, + PDWORD RequiredSize) +{ + return SetupDiClassNameFromGuidExW(ClassGuid, ClassName, + ClassNameSize, RequiredSize, + NULL, NULL); +} + +/*********************************************************************** + * SetupDiClassNameFromGuidExA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassNameFromGuidExA( + const GUID* ClassGuid, + PSTR ClassName, + DWORD ClassNameSize, + PDWORD RequiredSize, + PCSTR MachineName, + PVOID Reserved) +{ + WCHAR ClassNameW[MAX_CLASS_NAME_LEN]; + LPWSTR MachineNameW = NULL; + BOOL ret; + + if (MachineName) + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN, + NULL, MachineNameW, Reserved); + if (ret) + { + int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, + ClassNameSize, NULL, NULL); + + if (!ClassNameSize && RequiredSize) + *RequiredSize = len; + } + MyFree(MachineNameW); + return ret; +} + +/*********************************************************************** + * SetupDiClassNameFromGuidExW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiClassNameFromGuidExW( + const GUID* ClassGuid, + PWSTR ClassName, + DWORD ClassNameSize, + PDWORD RequiredSize, + PCWSTR MachineName, + PVOID Reserved) +{ + HKEY hKey; + DWORD dwLength; + + hKey = SetupDiOpenClassRegKeyExW(ClassGuid, + KEY_ALL_ACCESS, + DIOCR_INSTALLER, + MachineName, + Reserved); + if (hKey == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + if (RequiredSize != NULL) + { + dwLength = 0; + if (RegQueryValueExW(hKey, + Class, + NULL, + NULL, + NULL, + &dwLength)) + { + RegCloseKey(hKey); + return FALSE; + } + + *RequiredSize = dwLength / sizeof(WCHAR); + } + + dwLength = ClassNameSize * sizeof(WCHAR); + if (RegQueryValueExW(hKey, + Class, + NULL, + NULL, + (LPBYTE)ClassName, + &dwLength)) + { + RegCloseKey(hKey); + return FALSE; + } + + RegCloseKey(hKey); + + return TRUE; +} + +/*********************************************************************** + * SetupDiCreateDeviceInfoList (SETUPAPI.@) + */ +HDEVINFO WINAPI +SetupDiCreateDeviceInfoList(const GUID *ClassGuid, + HWND hwndParent) +{ + return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL); +} + +/*********************************************************************** + * SetupDiCreateDeviceInfoListExA (SETUPAPI.@) + */ +HDEVINFO WINAPI +SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid, + HWND hwndParent, + PCSTR MachineName, + PVOID Reserved) +{ + LPWSTR MachineNameW = NULL; + HDEVINFO hDevInfo; + + TRACE("\n"); + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + return (HDEVINFO)INVALID_HANDLE_VALUE; + } + + hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, + MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return hDevInfo; +} + +/*********************************************************************** + * SetupDiCreateDeviceInfoListExW (SETUPAPI.@) + */ +HDEVINFO WINAPI +SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid, + HWND hwndParent, + PCWSTR MachineName, + PVOID Reserved) +{ + FIXME("\n"); + return (HDEVINFO)INVALID_HANDLE_VALUE; +} + +/*********************************************************************** + * SetupDiEnumDeviceInfo (SETUPAPI.@) + */ +BOOL WINAPI SetupDiEnumDeviceInfo( + HDEVINFO devinfo, + DWORD index, + PSP_DEVINFO_DATA info) +{ + FIXME("%p %ld %p\n", devinfo, index, info); + + if(info==NULL) + return FALSE; + if(info->cbSize < sizeof(*info)) + return FALSE; + + return FALSE; +} + +/*********************************************************************** + * SetupDiGetActualSectionToInstallA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetActualSectionToInstallA( + HINF InfHandle, + PCSTR InfSectionName, + PSTR InfSectionWithExt, + DWORD InfSectionWithExtSize, + PDWORD RequiredSize, + PSTR *Extension) +{ + FIXME("\n"); + return FALSE; +} + +/*********************************************************************** + * SetupDiGetActualSectionToInstallW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetActualSectionToInstallW( + HINF InfHandle, + PCWSTR InfSectionName, + PWSTR InfSectionWithExt, + DWORD InfSectionWithExtSize, + PDWORD RequiredSize, + PWSTR *Extension) +{ + WCHAR szBuffer[MAX_PATH]; + DWORD dwLength; + DWORD dwFullLength; + LONG lLineCount = -1; + + lstrcpyW(szBuffer, InfSectionName); + dwLength = lstrlenW(szBuffer); + + if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + /* Test section name with '.NTx86' extension */ + lstrcpyW(&szBuffer[dwLength], NtPlatformExtension); + lLineCount = SetupGetLineCountW(InfHandle, szBuffer); + + if (lLineCount == -1) + { + /* Test section name with '.NT' extension */ + lstrcpyW(&szBuffer[dwLength], NtExtension); + lLineCount = SetupGetLineCountW(InfHandle, szBuffer); + } + } + else + { + /* Test section name with '.Win' extension */ + lstrcpyW(&szBuffer[dwLength], WinExtension); + lLineCount = SetupGetLineCountW(InfHandle, szBuffer); + } + + if (lLineCount == -1) + { + /* Test section name without extension */ + szBuffer[dwLength] = 0; + lLineCount = SetupGetLineCountW(InfHandle, szBuffer); + } + + if (lLineCount == -1) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + dwFullLength = lstrlenW(szBuffer); + + if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0) + { + if (InfSectionWithExtSize < (dwFullLength + 1)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + lstrcpyW(InfSectionWithExt, szBuffer); + if (Extension != NULL) + { + *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength]; + } + } + + if (RequiredSize != NULL) + { + *RequiredSize = dwFullLength + 1; + } + + return TRUE; +} + +/*********************************************************************** + * SetupDiGetClassDescriptionA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetClassDescriptionA( + const GUID* ClassGuid, + PSTR ClassDescription, + DWORD ClassDescriptionSize, + PDWORD RequiredSize) +{ + return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription, + ClassDescriptionSize, + RequiredSize, NULL, NULL); +} + +/*********************************************************************** + * SetupDiGetClassDescriptionW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetClassDescriptionW( + const GUID* ClassGuid, + PWSTR ClassDescription, + DWORD ClassDescriptionSize, + PDWORD RequiredSize) +{ + return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription, + ClassDescriptionSize, + RequiredSize, NULL, NULL); +} + +/*********************************************************************** + * SetupDiGetClassDescriptionExA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetClassDescriptionExA( + const GUID* ClassGuid, + PSTR ClassDescription, + DWORD ClassDescriptionSize, + PDWORD RequiredSize, + PCSTR MachineName, + PVOID Reserved) +{ + FIXME("\n"); + return FALSE; +} + +/*********************************************************************** + * SetupDiGetClassDescriptionExW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetClassDescriptionExW( + const GUID* ClassGuid, + PWSTR ClassDescription, + DWORD ClassDescriptionSize, + PDWORD RequiredSize, + PCWSTR MachineName, + PVOID Reserved) +{ + HKEY hKey; + DWORD dwLength; + + hKey = SetupDiOpenClassRegKeyExW(ClassGuid, + KEY_ALL_ACCESS, + DIOCR_INSTALLER, + MachineName, + Reserved); + if (hKey == INVALID_HANDLE_VALUE) + { + WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError()); + return FALSE; + } + + if (RequiredSize != NULL) + { + dwLength = 0; + if (RegQueryValueExW(hKey, + NULL, + NULL, + NULL, + NULL, + &dwLength)) + { + RegCloseKey(hKey); + return FALSE; + } + + *RequiredSize = dwLength / sizeof(WCHAR); + } + + dwLength = ClassDescriptionSize * sizeof(WCHAR); + if (RegQueryValueExW(hKey, + NULL, + NULL, + NULL, + (LPBYTE)ClassDescription, + &dwLength)) + { + RegCloseKey(hKey); + return FALSE; + } + + RegCloseKey(hKey); + + return TRUE; +} + +/*********************************************************************** + * SetupDiGetClassDevsA (SETUPAPI.@) + */ +HDEVINFO WINAPI SetupDiGetClassDevsA( + CONST GUID *class, + LPCSTR enumstr, + HWND parent, + DWORD flags) +{ + HDEVINFO ret; + LPWSTR enumstrW = NULL; + + if (enumstr) + { + int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0); + enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!enumstrW) + { + ret = (HDEVINFO)INVALID_HANDLE_VALUE; + goto end; + } + MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len); + } + ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags); + HeapFree(GetProcessHeap(), 0, enumstrW); + +end: + return ret; +} + +#define SETUP_SERIAL_PORT_MAGIC 0xd00ff055 + +typedef struct _SerialPortName +{ + WCHAR name[5]; +} SerialPortName; + +typedef struct _SerialPortList +{ + DWORD magic; + UINT numPorts; + SerialPortName names[1]; +} SerialPortList; + +static HDEVINFO SETUP_CreateSerialDeviceList(void) +{ + static const size_t initialSize = 100; + size_t size; + WCHAR buf[initialSize]; + LPWSTR devices; + HDEVINFO ret; + BOOL failed = FALSE; + + devices = buf; + size = initialSize; + do { + if (QueryDosDeviceW(NULL, devices, size) == 0) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + size *= 2; + if (devices != buf) + HeapFree(GetProcessHeap(), 0, devices); + devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); + if (!devices) + failed = TRUE; + else + *devices = 0; + } + else + failed = TRUE; + } + } while (!*devices && !failed); + if (!failed) + { + static const WCHAR comW[] = { 'C','O','M',0 }; + LPWSTR ptr; + UINT numSerialPorts = 0; + SerialPortList *list; + + for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1) + { + if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1)) + numSerialPorts++; + } + list = HeapAlloc(GetProcessHeap(), 0, sizeof(SerialPortList) + + numSerialPorts ? (numSerialPorts - 1) * sizeof(SerialPortName) : 0); + if (list) + { + list->magic = SETUP_SERIAL_PORT_MAGIC; + list->numPorts = 0; + for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1) + { + if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1)) + { + lstrcpynW(list->names[list->numPorts].name, ptr, + sizeof(list->names[list->numPorts].name) / + sizeof(list->names[list->numPorts].name[0])); + TRACE("Adding %s to list\n", + debugstr_w(list->names[list->numPorts].name)); + list->numPorts++; + } + } + TRACE("list->numPorts is %d\n", list->numPorts); + } + ret = (HDEVINFO)list; + } + else + ret = (HDEVINFO)INVALID_HANDLE_VALUE; + if (devices != buf) + HeapFree(GetProcessHeap(), 0, devices); + TRACE("returning %p\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiGetClassDevsW (SETUPAPI.@) + */ +HDEVINFO WINAPI SetupDiGetClassDevsW( + CONST GUID *class, + LPCWSTR enumstr, + HWND parent, + DWORD flags) +{ + HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE; + + TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr), + parent, flags); + + if (enumstr) + FIXME(": unimplemented for enumerator strings (%s)\n", + debugstr_w(enumstr)); + else if (flags & DIGCF_ALLCLASSES) + FIXME(": unimplemented for DIGCF_ALLCLASSES\n"); + else + { + if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT)) + ret = SETUP_CreateSerialDeviceList(); + else if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR)) + ret = SETUP_CreateSerialDeviceList(); + else + FIXME("(%s): stub\n", debugstr_guid(class)); + } + return ret; +} + +/*********************************************************************** + * SetupDiEnumDeviceInterfaces (SETUPAPI.@) + */ +BOOL WINAPI SetupDiEnumDeviceInterfaces( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + CONST GUID * InterfaceClassGuid, + DWORD MemberIndex, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) +{ + BOOL ret = FALSE; + + TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData, + debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); + if (!DeviceInterfaceData) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInfoData) + FIXME(": unimplemented with PSP_DEVINFO_DATA set\n"); + else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE) + { + /* FIXME: this assumes the only possible enumeration is of serial + * ports. + */ + SerialPortList *list = (SerialPortList *)DeviceInfoSet; + + if (list->magic == SETUP_SERIAL_PORT_MAGIC) + { + if (MemberIndex >= list->numPorts) + SetLastError(ERROR_NO_MORE_ITEMS); + else + { + DeviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + memcpy(&DeviceInterfaceData->InterfaceClassGuid, + &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, + sizeof(DeviceInterfaceData->InterfaceClassGuid)); + DeviceInterfaceData->Flags = 0; + /* Note: this appears to be dangerous, passing a private + * pointer a heap-allocated datum to the caller. However, the + * expected lifetime of the device data is the same as the + * HDEVINFO; once that is closed, the data are no longer valid. + */ + DeviceInterfaceData->Reserved = + (ULONG_PTR)&list->names[MemberIndex].name; + ret = TRUE; + } + } + else + SetLastError(ERROR_INVALID_HANDLE); + } + else + SetLastError(ERROR_INVALID_HANDLE); + return ret; +} + +/*********************************************************************** + * SetupDiDestroyDeviceInfoList (SETUPAPI.@) + */ +BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) +{ + BOOL ret = FALSE; + + TRACE("%p\n", devinfo); + if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE) + { + /* FIXME: this assumes the only possible enumeration is of serial + * ports. + */ + SerialPortList *list = (SerialPortList *)devinfo; + + if (list->magic == SETUP_SERIAL_PORT_MAGIC) + { + HeapFree(GetProcessHeap(), 0, list); + ret = TRUE; + } + else + SetLastError(ERROR_INVALID_HANDLE); + } + else + SetLastError(ERROR_INVALID_HANDLE); + return ret; +} + +/*********************************************************************** + * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetDeviceInterfaceDetailA( + HDEVINFO DeviceInfoSet, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, + DWORD DeviceInterfaceDetailDataSize, + PDWORD RequiredSize, + PSP_DEVINFO_DATA DeviceInfoData) +{ + BOOL ret = FALSE; + + TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet, + DeviceInterfaceData, DeviceInterfaceDetailData, + DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); + if (!DeviceInterfaceData) + SetLastError(ERROR_INVALID_PARAMETER); + else if ((DeviceInterfaceDetailDataSize && !DeviceInterfaceDetailData) || + (DeviceInterfaceDetailData && !DeviceInterfaceDetailDataSize)) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE) + { + /* FIXME: this assumes the only possible enumeration is of serial + * ports. + */ + SerialPortList *list = (SerialPortList *)DeviceInfoSet; + + if (list->magic == SETUP_SERIAL_PORT_MAGIC) + { + LPCWSTR devName = (LPCWSTR)DeviceInterfaceData->Reserved; + DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A) + + lstrlenW(devName); + + if (sizeRequired > DeviceInterfaceDetailDataSize) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + if (RequiredSize) + *RequiredSize = sizeRequired; + } + else + { + LPSTR dst = DeviceInterfaceDetailData->DevicePath; + LPCWSTR src = devName; + + /* MSDN claims cbSize must be set by the caller, but it lies */ + DeviceInterfaceDetailData->cbSize = + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + for ( ; *src; src++, dst++) + *dst = *src; + *dst = '\0'; + TRACE("DevicePath is %s\n", + debugstr_a(DeviceInterfaceDetailData->DevicePath)); + if (DeviceInfoData) + { + DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA); + memcpy(&DeviceInfoData->ClassGuid, + &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, + sizeof(DeviceInfoData->ClassGuid)); + DeviceInfoData->DevInst = 0; + DeviceInfoData->Reserved = (ULONG_PTR)devName; + } + ret = TRUE; + } + } + else + SetLastError(ERROR_INVALID_HANDLE); + } + else + SetLastError(ERROR_INVALID_HANDLE); + TRACE("Returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetDeviceInterfaceDetailW( + HDEVINFO DeviceInfoSet, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData, + DWORD DeviceInterfaceDetailDataSize, + PDWORD RequiredSize, + PSP_DEVINFO_DATA DeviceInfoData) +{ + FIXME("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet, + DeviceInterfaceData, DeviceInterfaceDetailData, + DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); + return FALSE; +} + +/*********************************************************************** + * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetDeviceRegistryPropertyA( + HDEVINFO devinfo, + PSP_DEVINFO_DATA DeviceInfoData, + DWORD Property, + PDWORD PropertyRegDataType, + PBYTE PropertyBuffer, + DWORD PropertyBufferSize, + PDWORD RequiredSize) +{ + FIXME("%04lx %p %ld %p %p %ld %p\n", (DWORD)devinfo, DeviceInfoData, + Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, + RequiredSize); + return FALSE; +} + +/*********************************************************************** + * SetupDiInstallClassA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiInstallClassA( + HWND hwndParent, + PCSTR InfFileName, + DWORD Flags, + HSPFILEQ FileQueue) +{ + UNICODE_STRING FileNameW; + BOOL Result; + + if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName)) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue); + + RtlFreeUnicodeString(&FileNameW); + + return Result; +} + +static HKEY CreateClassKey(HINF hInf) +{ + WCHAR FullBuffer[MAX_PATH]; + WCHAR Buffer[MAX_PATH]; + DWORD RequiredSize; + HKEY hClassKey; + + Buffer[0] = '\\'; + if (!SetupGetLineTextW(NULL, + hInf, + Version, + ClassGUID, + &Buffer[1], + MAX_PATH - 1, + &RequiredSize)) + { + return INVALID_HANDLE_VALUE; + } + + lstrcpyW(FullBuffer, ControlClass); + lstrcatW(FullBuffer, Buffer); + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + FullBuffer, + 0, + KEY_ALL_ACCESS, + &hClassKey)) + { + if (!SetupGetLineTextW(NULL, + hInf, + Version, + Class, + Buffer, + MAX_PATH, + &RequiredSize)) + { + return INVALID_HANDLE_VALUE; + } + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, + FullBuffer, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hClassKey, + NULL)) + { + return INVALID_HANDLE_VALUE; + } + + } + + if (RegSetValueExW(hClassKey, + Class, + 0, + REG_SZ, + (LPBYTE)Buffer, + RequiredSize * sizeof(WCHAR))) + { + RegCloseKey(hClassKey); + RegDeleteKeyW(HKEY_LOCAL_MACHINE, + FullBuffer); + return INVALID_HANDLE_VALUE; + } + + return hClassKey; +} + +/*********************************************************************** + * SetupDiInstallClassW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiInstallClassW( + HWND hwndParent, + PCWSTR InfFileName, + DWORD Flags, + HSPFILEQ FileQueue) +{ + WCHAR SectionName[MAX_PATH]; + DWORD SectionNameLength = 0; + HINF hInf; + BOOL bFileQueueCreated = FALSE; + HKEY hClassKey; + + FIXME("not fully implemented\n"); + + if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Open the .inf file */ + hInf = SetupOpenInfFileW(InfFileName, + NULL, + INF_STYLE_WIN4, + NULL); + if (hInf == INVALID_HANDLE_VALUE) + { + + return FALSE; + } + + /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */ + hClassKey = CreateClassKey(hInf); + if (hClassKey == INVALID_HANDLE_VALUE) + { + SetupCloseInfFile(hInf); + return FALSE; + } + + + /* Try to append a layout file */ +#if 0 + SetupOpenAppendInfFileW(NULL, hInf, NULL); +#endif + + /* Retrieve the actual section name */ + SetupDiGetActualSectionToInstallW(hInf, + ClassInstall32, + SectionName, + MAX_PATH, + &SectionNameLength, + NULL); + +#if 0 + if (!(Flags & DI_NOVCP)) + { + FileQueue = SetupOpenFileQueue(); + if (FileQueue == INVALID_HANDLE_VALUE) + { + SetupCloseInfFile(hInf); + return FALSE; + } + + bFileQueueCreated = TRUE; + + } +#endif + + SetupInstallFromInfSectionW(NULL, + hInf, + SectionName, + SPINST_REGISTRY, + hClassKey, + NULL, + 0, + NULL, + NULL, + INVALID_HANDLE_VALUE, + NULL); + + /* FIXME: More code! */ + + if (bFileQueueCreated) + SetupCloseFileQueue(FileQueue); + + SetupCloseInfFile(hInf); + + return TRUE; +} + + +/*********************************************************************** + * SetupDiOpenClassRegKey (SETUPAPI.@) + */ +HKEY WINAPI SetupDiOpenClassRegKey( + const GUID* ClassGuid, + REGSAM samDesired) +{ + return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, + DIOCR_INSTALLER, NULL, NULL); +} + + +/*********************************************************************** + * SetupDiOpenClassRegKeyExA (SETUPAPI.@) + */ +HKEY WINAPI SetupDiOpenClassRegKeyExA( + const GUID* ClassGuid, + REGSAM samDesired, + DWORD Flags, + PCSTR MachineName, + PVOID Reserved) +{ + PWSTR MachineNameW = NULL; + HKEY hKey; + + TRACE("\n"); + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + return INVALID_HANDLE_VALUE; + } + + hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, + Flags, MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return hKey; +} + + +/*********************************************************************** + * SetupDiOpenClassRegKeyExW (SETUPAPI.@) + */ +HKEY WINAPI SetupDiOpenClassRegKeyExW( + const GUID* ClassGuid, + REGSAM samDesired, + DWORD Flags, + PCWSTR MachineName, + PVOID Reserved) +{ + LPWSTR lpGuidString; + HKEY hClassesKey; + HKEY hClassKey; + LPCWSTR lpKeyName; + + if (MachineName != NULL) + { + FIXME("Remote access not supported yet!\n"); + return INVALID_HANDLE_VALUE; + } + + if (Flags == DIOCR_INSTALLER) + { + lpKeyName = ControlClass; + } + else if (Flags == DIOCR_INTERFACE) + { + lpKeyName = DeviceClasses; + } + else + { + ERR("Invalid Flags parameter!\n"); + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + lpKeyName, + 0, + KEY_ALL_ACCESS, + &hClassesKey)) + { + return INVALID_HANDLE_VALUE; + } + + if (ClassGuid == NULL) + return hClassesKey; + + if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK) + { + RegCloseKey(hClassesKey); + return INVALID_HANDLE_VALUE; + } + + if (RegOpenKeyExW(hClassesKey, + lpGuidString, + 0, + KEY_ALL_ACCESS, + &hClassKey)) + { + RpcStringFreeW(&lpGuidString); + RegCloseKey(hClassesKey); + return INVALID_HANDLE_VALUE; + } + + RpcStringFreeW(&lpGuidString); + RegCloseKey(hClassesKey); + + return hClassKey; +} + +/*********************************************************************** + * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiOpenDeviceInterfaceW( + HDEVINFO DeviceInfoSet, + PCWSTR DevicePath, + DWORD OpenFlags, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) +{ + FIXME("%p %s %08lx %p\n", + DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData); + return FALSE; +} + +/*********************************************************************** + * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiOpenDeviceInterfaceA( + HDEVINFO DeviceInfoSet, + PCSTR DevicePath, + DWORD OpenFlags, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) +{ + FIXME("%p %s %08lx %p\n", DeviceInfoSet, + debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData); + return FALSE; +} + +/*********************************************************************** + * SetupDiSetClassInstallParamsA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiSetClassInstallParamsA( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + PSP_CLASSINSTALL_HEADER ClassInstallParams, + DWORD ClassInstallParamsSize) +{ + FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData, + ClassInstallParams->InstallFunction, ClassInstallParamsSize); + return FALSE; +} + +/*********************************************************************** + * SetupDiCallClassInstaller (SETUPAPI.@) + */ +BOOL WINAPI SetupDiCallClassInstaller( + DWORD InstallFunction, + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData) +{ + FIXME("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData); + return FALSE; +} + +/*********************************************************************** + * SetupDiGetDeviceInstallParamsA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetDeviceInstallParamsA( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) +{ + FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); + return FALSE; +} + +/*********************************************************************** + * SetupDiOpenDevRegKey (SETUPAPI.@) + */ +HKEY WINAPI SetupDiOpenDevRegKey( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + DWORD Scope, + DWORD HwProfile, + DWORD KeyType, + REGSAM samDesired) +{ + FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData, + Scope, HwProfile, KeyType, samDesired); + return INVALID_HANDLE_VALUE; +} diff --git a/reactos/lib/setupapi/devinst16.c b/reactos/lib/setupapi/devinst16.c index b746b1aafaf..f0c51544218 100644 --- a/reactos/lib/setupapi/devinst16.c +++ b/reactos/lib/setupapi/devinst16.c @@ -1,134 +1,134 @@ -/* - * SetupAPI device installer - * - * Copyright 2000 Andreas Mohr for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "setupx16.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -/*********************************************************************** - * DiGetClassDevs (SETUPX.304) - * Return a list of installed system devices. - * Uses HKLM\\ENUM to list devices. - */ -RETERR16 WINAPI DiGetClassDevs16(LPLPDEVICE_INFO16 lplpdi, - LPCSTR lpszClassName, HWND16 hwndParent, INT16 iFlags) -{ - LPDEVICE_INFO16 lpdi; - - FIXME("(%p, '%s', %04x, %04x), semi-stub.\n", - lplpdi, lpszClassName, hwndParent, iFlags); - lpdi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEVICE_INFO16)); - lpdi->cbSize = sizeof(DEVICE_INFO16); - *lplpdi = (LPDEVICE_INFO16)MapLS(lpdi); - return OK; -} - -/*********************************************************************** - * DiBuildCompatDrvList (SETUPX.300) - */ -RETERR16 WINAPI DiBuildCompatDrvList16(LPDEVICE_INFO16 lpdi) -{ - FIXME("(%p): stub\n", lpdi); - lpdi->lpCompatDrvList = NULL; - return FALSE; -} - -/*********************************************************************** - * DiBuildClassDrvList (SETUPX.301) - */ -RETERR16 WINAPI DiBuildClassDrvList16(LPDEVICE_INFO16 lpdi) -{ - FIXME("(%p): stub\n", lpdi); - lpdi->lpCompatDrvList = NULL; - return FALSE; -} - -/*********************************************************************** - * DiCallClassInstaller (SETUPX.308) - */ -RETERR16 WINAPI DiCallClassInstaller16(DI_FUNCTION16 diFctn, LPDEVICE_INFO16 lpdi) -{ - FIXME("(%x, %p): stub\n", diFctn, lpdi); - return FALSE; -} - -/*********************************************************************** - * DiCreateDevRegKey (SETUPX.318) - */ -RETERR16 WINAPI DiCreateDevRegKey16(LPDEVICE_INFO16 lpdi, - VOID* p2, WORD w3, - LPCSTR s4, WORD w5) -{ - FIXME("(%p, %p, %x, %s, %x): stub\n", lpdi, p2, w3, debugstr_a(s4), w5); - return FALSE; -} - -/*********************************************************************** - * DiDeleteDevRegKey (SETUPX.344) - */ -RETERR16 WINAPI DiDeleteDevRegKey16(LPDEVICE_INFO16 lpdi, INT16 iFlags) -{ - FIXME("(%p, %x): stub\n", lpdi, iFlags); - return FALSE; -} - -/*********************************************************************** - * DiCreateDeviceInfo (SETUPX.303) - */ -RETERR16 WINAPI DiCreateDeviceInfo16(LPLPDEVICE_INFO16 lplpdi, - LPCSTR lpszDescription, DWORD dnDevnode, - HKEY16 hkey, LPCSTR lpszRegsubkey, - LPCSTR lpszClassName, HWND16 hwndParent) -{ - LPDEVICE_INFO16 lpdi; - FIXME("(%p %s %08lx %x %s %s %x): stub\n", lplpdi, - debugstr_a(lpszDescription), dnDevnode, hkey, - debugstr_a(lpszRegsubkey), debugstr_a(lpszClassName), hwndParent); - lpdi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEVICE_INFO16)); - lpdi->cbSize = sizeof(DEVICE_INFO16); - strcpy(lpdi->szClassName, lpszClassName); - lpdi->hwndParent = hwndParent; - *lplpdi = (LPDEVICE_INFO16)MapLS(lpdi); - return OK; -} - -/*********************************************************************** - * DiDestroyDeviceInfoList (SETUPX.305) - */ -RETERR16 WINAPI DiDestroyDeviceInfoList16(LPDEVICE_INFO16 lpdi) -{ - FIXME("(%p): stub\n", lpdi); - return FALSE; -} - -/*********************************************************************** - * DiOpenDevRegKey (SETUPX.319) - */ -RETERR16 WINAPI DiOpenDevRegKey16(LPDEVICE_INFO16 lpdi, - LPHKEY16 lphk,INT16 iFlags) -{ - FIXME("(%p %p %d): stub\n", lpdi, lphk, iFlags); - return FALSE; -} +/* + * SetupAPI device installer + * + * Copyright 2000 Andreas Mohr for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "setupx16.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +/*********************************************************************** + * DiGetClassDevs (SETUPX.304) + * Return a list of installed system devices. + * Uses HKLM\\ENUM to list devices. + */ +RETERR16 WINAPI DiGetClassDevs16(LPLPDEVICE_INFO16 lplpdi, + LPCSTR lpszClassName, HWND16 hwndParent, INT16 iFlags) +{ + LPDEVICE_INFO16 lpdi; + + FIXME("(%p, '%s', %04x, %04x), semi-stub.\n", + lplpdi, lpszClassName, hwndParent, iFlags); + lpdi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEVICE_INFO16)); + lpdi->cbSize = sizeof(DEVICE_INFO16); + *lplpdi = (LPDEVICE_INFO16)MapLS(lpdi); + return OK; +} + +/*********************************************************************** + * DiBuildCompatDrvList (SETUPX.300) + */ +RETERR16 WINAPI DiBuildCompatDrvList16(LPDEVICE_INFO16 lpdi) +{ + FIXME("(%p): stub\n", lpdi); + lpdi->lpCompatDrvList = NULL; + return FALSE; +} + +/*********************************************************************** + * DiBuildClassDrvList (SETUPX.301) + */ +RETERR16 WINAPI DiBuildClassDrvList16(LPDEVICE_INFO16 lpdi) +{ + FIXME("(%p): stub\n", lpdi); + lpdi->lpCompatDrvList = NULL; + return FALSE; +} + +/*********************************************************************** + * DiCallClassInstaller (SETUPX.308) + */ +RETERR16 WINAPI DiCallClassInstaller16(DI_FUNCTION16 diFctn, LPDEVICE_INFO16 lpdi) +{ + FIXME("(%x, %p): stub\n", diFctn, lpdi); + return FALSE; +} + +/*********************************************************************** + * DiCreateDevRegKey (SETUPX.318) + */ +RETERR16 WINAPI DiCreateDevRegKey16(LPDEVICE_INFO16 lpdi, + VOID* p2, WORD w3, + LPCSTR s4, WORD w5) +{ + FIXME("(%p, %p, %x, %s, %x): stub\n", lpdi, p2, w3, debugstr_a(s4), w5); + return FALSE; +} + +/*********************************************************************** + * DiDeleteDevRegKey (SETUPX.344) + */ +RETERR16 WINAPI DiDeleteDevRegKey16(LPDEVICE_INFO16 lpdi, INT16 iFlags) +{ + FIXME("(%p, %x): stub\n", lpdi, iFlags); + return FALSE; +} + +/*********************************************************************** + * DiCreateDeviceInfo (SETUPX.303) + */ +RETERR16 WINAPI DiCreateDeviceInfo16(LPLPDEVICE_INFO16 lplpdi, + LPCSTR lpszDescription, DWORD dnDevnode, + HKEY16 hkey, LPCSTR lpszRegsubkey, + LPCSTR lpszClassName, HWND16 hwndParent) +{ + LPDEVICE_INFO16 lpdi; + FIXME("(%p %s %08lx %x %s %s %x): stub\n", lplpdi, + debugstr_a(lpszDescription), dnDevnode, hkey, + debugstr_a(lpszRegsubkey), debugstr_a(lpszClassName), hwndParent); + lpdi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEVICE_INFO16)); + lpdi->cbSize = sizeof(DEVICE_INFO16); + strcpy(lpdi->szClassName, lpszClassName); + lpdi->hwndParent = hwndParent; + *lplpdi = (LPDEVICE_INFO16)MapLS(lpdi); + return OK; +} + +/*********************************************************************** + * DiDestroyDeviceInfoList (SETUPX.305) + */ +RETERR16 WINAPI DiDestroyDeviceInfoList16(LPDEVICE_INFO16 lpdi) +{ + FIXME("(%p): stub\n", lpdi); + return FALSE; +} + +/*********************************************************************** + * DiOpenDevRegKey (SETUPX.319) + */ +RETERR16 WINAPI DiOpenDevRegKey16(LPDEVICE_INFO16 lpdi, + LPHKEY16 lphk,INT16 iFlags) +{ + FIXME("(%p %p %d): stub\n", lpdi, lphk, iFlags); + return FALSE; +} diff --git a/reactos/lib/setupapi/dirid.c b/reactos/lib/setupapi/dirid.c index cec3373dfc3..639da022258 100644 --- a/reactos/lib/setupapi/dirid.c +++ b/reactos/lib/setupapi/dirid.c @@ -1,288 +1,288 @@ -/* - * Directory id handling - * - * Copyright 2002 Alexandre Julliard for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winternl.h" -#include "winerror.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "setupapi.h" -#include "shlobj.h" -#include "wine/unicode.h" -#include "setupapi_private.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -#define MAX_SYSTEM_DIRID DIRID_PRINTPROCESSOR -#define MIN_CSIDL_DIRID 0x4000 -#define MAX_CSIDL_DIRID 0x403f - -struct user_dirid -{ - int id; - WCHAR *str; -}; - -static int nb_user_dirids; /* number of user dirids in use */ -static int alloc_user_dirids; /* number of allocated user dirids */ -static struct user_dirid *user_dirids; -static const WCHAR *system_dirids[MAX_SYSTEM_DIRID+1]; -static const WCHAR *csidl_dirids[MAX_CSIDL_DIRID-MIN_CSIDL_DIRID+1]; - -/* retrieve the string for unknown dirids */ -static const WCHAR *get_unknown_dirid(void) -{ - static WCHAR *unknown_dirid; - static const WCHAR unknown_str[] = {'\\','u','n','k','n','o','w','n',0}; - - if (!unknown_dirid) - { - UINT len = GetSystemDirectoryW( NULL, 0 ) + strlenW(unknown_str); - if (!(unknown_dirid = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL; - GetSystemDirectoryW( unknown_dirid, len ); - strcatW( unknown_dirid, unknown_str ); - } - return unknown_dirid; -} - -static const WCHAR *get_csidl_dir(DWORD csidl); - -/* create the string for a system dirid */ -static const WCHAR *create_system_dirid( int dirid ) -{ - static const WCHAR Null[] = {0}; - static const WCHAR C_Root[] = {'C',':','\\',0}; - static const WCHAR Drivers[] = {'\\','d','r','i','v','e','r','s',0}; - static const WCHAR Inf[] = {'\\','i','n','f',0}; - static const WCHAR Help[] = {'\\','h','e','l','p',0}; - static const WCHAR Fonts[] = {'\\','f','o','n','t','s',0}; - static const WCHAR Viewers[] = {'\\','v','i','e','w','e','r','s',0}; - static const WCHAR System[] = {'\\','s','y','s','t','e','m',0}; - static const WCHAR Spool[] = {'\\','s','p','o','o','l',0}; - static const WCHAR UserProfile[] = {'U','S','E','R','P','R','O','F','I','L','E',0}; - - WCHAR buffer[MAX_PATH+32], *str; - int len; - - switch(dirid) - { - case DIRID_NULL: - return Null; - case DIRID_WINDOWS: - GetWindowsDirectoryW( buffer, MAX_PATH ); - break; - case DIRID_SYSTEM: - GetSystemDirectoryW( buffer, MAX_PATH ); - break; - case DIRID_DRIVERS: - GetSystemDirectoryW( buffer, MAX_PATH ); - strcatW( buffer, Drivers ); - break; - case DIRID_INF: - GetWindowsDirectoryW( buffer, MAX_PATH ); - strcatW( buffer, Inf ); - break; - case DIRID_HELP: - GetWindowsDirectoryW( buffer, MAX_PATH ); - strcatW( buffer, Help ); - break; - case DIRID_FONTS: - GetWindowsDirectoryW( buffer, MAX_PATH ); - strcatW( buffer, Fonts ); - break; - case DIRID_VIEWERS: - GetSystemDirectoryW( buffer, MAX_PATH ); - strcatW( buffer, Viewers ); - break; - case DIRID_APPS: - return C_Root; /* FIXME */ - case DIRID_SHARED: - GetWindowsDirectoryW( buffer, MAX_PATH ); - break; - case DIRID_BOOT: - return C_Root; /* FIXME */ - case DIRID_SYSTEM16: - GetWindowsDirectoryW( buffer, MAX_PATH ); - strcatW( buffer, System ); - break; - case DIRID_SPOOL: - case DIRID_SPOOLDRIVERS: /* FIXME */ - GetWindowsDirectoryW( buffer, MAX_PATH ); - strcatW( buffer, Spool ); - break; - case DIRID_USERPROFILE: - if (GetEnvironmentVariableW( UserProfile, buffer, MAX_PATH )) break; - return get_csidl_dir(CSIDL_PROFILE); - case DIRID_LOADER: - return C_Root; /* FIXME */ - case DIRID_COLOR: /* FIXME */ - case DIRID_PRINTPROCESSOR: /* FIXME */ - default: - FIXME( "unknown dirid %d\n", dirid ); - return get_unknown_dirid(); - } - len = (strlenW(buffer) + 1) * sizeof(WCHAR); - if ((str = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( str, buffer, len ); - return str; -} - -static const WCHAR *get_csidl_dir( DWORD csidl ) -{ - WCHAR buffer[MAX_PATH], *str; - int len; - - if (!SHGetSpecialFolderPathW( NULL, buffer, csidl, TRUE )) - { - FIXME( "CSIDL %lx not found\n", csidl ); - return get_unknown_dirid(); - } - len = (strlenW(buffer) + 1) * sizeof(WCHAR); - if ((str = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( str, buffer, len ); - return str; -} - -/* retrieve the string corresponding to a dirid, or NULL if none */ -const WCHAR *DIRID_get_string( HINF hinf, int dirid ) -{ - int i; - - if (dirid == DIRID_ABSOLUTE || dirid == DIRID_ABSOLUTE_16BIT) dirid = DIRID_NULL; - - if (dirid >= DIRID_USER) - { - for (i = 0; i < nb_user_dirids; i++) - if (user_dirids[i].id == dirid) return user_dirids[i].str; - ERR("user id %d not found\n", dirid ); - return NULL; - } - else if (dirid >= MIN_CSIDL_DIRID) - { - if (dirid > MAX_CSIDL_DIRID) return get_unknown_dirid(); - dirid -= MIN_CSIDL_DIRID; - if (!csidl_dirids[dirid]) csidl_dirids[dirid] = get_csidl_dir( dirid ); - return csidl_dirids[dirid]; - } - else - { - if (dirid > MAX_SYSTEM_DIRID) return get_unknown_dirid(); - if (dirid == DIRID_SRCPATH) return PARSER_get_src_root( hinf ); - if (!system_dirids[dirid]) system_dirids[dirid] = create_system_dirid( dirid ); - return system_dirids[dirid]; - } -} - -/* store a user dirid string */ -static BOOL store_user_dirid( HINF hinf, int id, WCHAR *str ) -{ - int i; - - for (i = 0; i < nb_user_dirids; i++) if (user_dirids[i].id == id) break; - - if (i < nb_user_dirids) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); - else - { - if (nb_user_dirids >= alloc_user_dirids) - { - int new_size = max( 32, alloc_user_dirids * 2 ); - - struct user_dirid *new; - - if (user_dirids) - new = HeapReAlloc( GetProcessHeap(), 0, user_dirids, - new_size * sizeof(*new) ); - else - new = HeapAlloc( GetProcessHeap(), 0, - new_size * sizeof(*new) ); - - if (!new) return FALSE; - user_dirids = new; - alloc_user_dirids = new_size; - } - nb_user_dirids++; - } - user_dirids[i].id = id; - user_dirids[i].str = str; - TRACE("id %d -> %s\n", id, debugstr_w(str) ); - return TRUE; -} - - -/*********************************************************************** - * SetupSetDirectoryIdA (SETUPAPI.@) - */ -BOOL WINAPI SetupSetDirectoryIdA( HINF hinf, DWORD id, PCSTR dir ) -{ - UNICODE_STRING dirW; - int i; - - if (!id) /* clear everything */ - { - for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); - nb_user_dirids = 0; - return TRUE; - } - if (id < DIRID_USER) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - /* duplicate the string */ - if (!RtlCreateUnicodeStringFromAsciiz( &dirW, dir )) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - } - return store_user_dirid( hinf, id, dirW.Buffer ); -} - - -/*********************************************************************** - * SetupSetDirectoryIdW (SETUPAPI.@) - */ -BOOL WINAPI SetupSetDirectoryIdW( HINF hinf, DWORD id, PCWSTR dir ) -{ - int i, len; - WCHAR *str; - - if (!id) /* clear everything */ - { - for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); - nb_user_dirids = 0; - return TRUE; - } - if (id < DIRID_USER) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - /* duplicate the string */ - len = (strlenW(dir)+1) * sizeof(WCHAR); - if (!(str = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE; - memcpy( str, dir, len ); - return store_user_dirid( hinf, id, str ); -} +/* + * Directory id handling + * + * Copyright 2002 Alexandre Julliard for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winternl.h" +#include "winerror.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "setupapi.h" +#include "shlobj.h" +#include "wine/unicode.h" +#include "setupapi_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +#define MAX_SYSTEM_DIRID DIRID_PRINTPROCESSOR +#define MIN_CSIDL_DIRID 0x4000 +#define MAX_CSIDL_DIRID 0x403f + +struct user_dirid +{ + int id; + WCHAR *str; +}; + +static int nb_user_dirids; /* number of user dirids in use */ +static int alloc_user_dirids; /* number of allocated user dirids */ +static struct user_dirid *user_dirids; +static const WCHAR *system_dirids[MAX_SYSTEM_DIRID+1]; +static const WCHAR *csidl_dirids[MAX_CSIDL_DIRID-MIN_CSIDL_DIRID+1]; + +/* retrieve the string for unknown dirids */ +static const WCHAR *get_unknown_dirid(void) +{ + static WCHAR *unknown_dirid; + static const WCHAR unknown_str[] = {'\\','u','n','k','n','o','w','n',0}; + + if (!unknown_dirid) + { + UINT len = GetSystemDirectoryW( NULL, 0 ) + strlenW(unknown_str); + if (!(unknown_dirid = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL; + GetSystemDirectoryW( unknown_dirid, len ); + strcatW( unknown_dirid, unknown_str ); + } + return unknown_dirid; +} + +static const WCHAR *get_csidl_dir(DWORD csidl); + +/* create the string for a system dirid */ +static const WCHAR *create_system_dirid( int dirid ) +{ + static const WCHAR Null[] = {0}; + static const WCHAR C_Root[] = {'C',':','\\',0}; + static const WCHAR Drivers[] = {'\\','d','r','i','v','e','r','s',0}; + static const WCHAR Inf[] = {'\\','i','n','f',0}; + static const WCHAR Help[] = {'\\','h','e','l','p',0}; + static const WCHAR Fonts[] = {'\\','f','o','n','t','s',0}; + static const WCHAR Viewers[] = {'\\','v','i','e','w','e','r','s',0}; + static const WCHAR System[] = {'\\','s','y','s','t','e','m',0}; + static const WCHAR Spool[] = {'\\','s','p','o','o','l',0}; + static const WCHAR UserProfile[] = {'U','S','E','R','P','R','O','F','I','L','E',0}; + + WCHAR buffer[MAX_PATH+32], *str; + int len; + + switch(dirid) + { + case DIRID_NULL: + return Null; + case DIRID_WINDOWS: + GetWindowsDirectoryW( buffer, MAX_PATH ); + break; + case DIRID_SYSTEM: + GetSystemDirectoryW( buffer, MAX_PATH ); + break; + case DIRID_DRIVERS: + GetSystemDirectoryW( buffer, MAX_PATH ); + strcatW( buffer, Drivers ); + break; + case DIRID_INF: + GetWindowsDirectoryW( buffer, MAX_PATH ); + strcatW( buffer, Inf ); + break; + case DIRID_HELP: + GetWindowsDirectoryW( buffer, MAX_PATH ); + strcatW( buffer, Help ); + break; + case DIRID_FONTS: + GetWindowsDirectoryW( buffer, MAX_PATH ); + strcatW( buffer, Fonts ); + break; + case DIRID_VIEWERS: + GetSystemDirectoryW( buffer, MAX_PATH ); + strcatW( buffer, Viewers ); + break; + case DIRID_APPS: + return C_Root; /* FIXME */ + case DIRID_SHARED: + GetWindowsDirectoryW( buffer, MAX_PATH ); + break; + case DIRID_BOOT: + return C_Root; /* FIXME */ + case DIRID_SYSTEM16: + GetWindowsDirectoryW( buffer, MAX_PATH ); + strcatW( buffer, System ); + break; + case DIRID_SPOOL: + case DIRID_SPOOLDRIVERS: /* FIXME */ + GetWindowsDirectoryW( buffer, MAX_PATH ); + strcatW( buffer, Spool ); + break; + case DIRID_USERPROFILE: + if (GetEnvironmentVariableW( UserProfile, buffer, MAX_PATH )) break; + return get_csidl_dir(CSIDL_PROFILE); + case DIRID_LOADER: + return C_Root; /* FIXME */ + case DIRID_COLOR: /* FIXME */ + case DIRID_PRINTPROCESSOR: /* FIXME */ + default: + FIXME( "unknown dirid %d\n", dirid ); + return get_unknown_dirid(); + } + len = (strlenW(buffer) + 1) * sizeof(WCHAR); + if ((str = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( str, buffer, len ); + return str; +} + +static const WCHAR *get_csidl_dir( DWORD csidl ) +{ + WCHAR buffer[MAX_PATH], *str; + int len; + + if (!SHGetSpecialFolderPathW( NULL, buffer, csidl, TRUE )) + { + FIXME( "CSIDL %lx not found\n", csidl ); + return get_unknown_dirid(); + } + len = (strlenW(buffer) + 1) * sizeof(WCHAR); + if ((str = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( str, buffer, len ); + return str; +} + +/* retrieve the string corresponding to a dirid, or NULL if none */ +const WCHAR *DIRID_get_string( HINF hinf, int dirid ) +{ + int i; + + if (dirid == DIRID_ABSOLUTE || dirid == DIRID_ABSOLUTE_16BIT) dirid = DIRID_NULL; + + if (dirid >= DIRID_USER) + { + for (i = 0; i < nb_user_dirids; i++) + if (user_dirids[i].id == dirid) return user_dirids[i].str; + ERR("user id %d not found\n", dirid ); + return NULL; + } + else if (dirid >= MIN_CSIDL_DIRID) + { + if (dirid > MAX_CSIDL_DIRID) return get_unknown_dirid(); + dirid -= MIN_CSIDL_DIRID; + if (!csidl_dirids[dirid]) csidl_dirids[dirid] = get_csidl_dir( dirid ); + return csidl_dirids[dirid]; + } + else + { + if (dirid > MAX_SYSTEM_DIRID) return get_unknown_dirid(); + if (dirid == DIRID_SRCPATH) return PARSER_get_src_root( hinf ); + if (!system_dirids[dirid]) system_dirids[dirid] = create_system_dirid( dirid ); + return system_dirids[dirid]; + } +} + +/* store a user dirid string */ +static BOOL store_user_dirid( HINF hinf, int id, WCHAR *str ) +{ + int i; + + for (i = 0; i < nb_user_dirids; i++) if (user_dirids[i].id == id) break; + + if (i < nb_user_dirids) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); + else + { + if (nb_user_dirids >= alloc_user_dirids) + { + int new_size = max( 32, alloc_user_dirids * 2 ); + + struct user_dirid *new; + + if (user_dirids) + new = HeapReAlloc( GetProcessHeap(), 0, user_dirids, + new_size * sizeof(*new) ); + else + new = HeapAlloc( GetProcessHeap(), 0, + new_size * sizeof(*new) ); + + if (!new) return FALSE; + user_dirids = new; + alloc_user_dirids = new_size; + } + nb_user_dirids++; + } + user_dirids[i].id = id; + user_dirids[i].str = str; + TRACE("id %d -> %s\n", id, debugstr_w(str) ); + return TRUE; +} + + +/*********************************************************************** + * SetupSetDirectoryIdA (SETUPAPI.@) + */ +BOOL WINAPI SetupSetDirectoryIdA( HINF hinf, DWORD id, PCSTR dir ) +{ + UNICODE_STRING dirW; + int i; + + if (!id) /* clear everything */ + { + for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); + nb_user_dirids = 0; + return TRUE; + } + if (id < DIRID_USER) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + /* duplicate the string */ + if (!RtlCreateUnicodeStringFromAsciiz( &dirW, dir )) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + return store_user_dirid( hinf, id, dirW.Buffer ); +} + + +/*********************************************************************** + * SetupSetDirectoryIdW (SETUPAPI.@) + */ +BOOL WINAPI SetupSetDirectoryIdW( HINF hinf, DWORD id, PCWSTR dir ) +{ + int i, len; + WCHAR *str; + + if (!id) /* clear everything */ + { + for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str ); + nb_user_dirids = 0; + return TRUE; + } + if (id < DIRID_USER) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + /* duplicate the string */ + len = (strlenW(dir)+1) * sizeof(WCHAR); + if (!(str = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE; + memcpy( str, dir, len ); + return store_user_dirid( hinf, id, str ); +} diff --git a/reactos/lib/setupapi/diskspace.c b/reactos/lib/setupapi/diskspace.c index c3b303e8896..0b42056528c 100644 --- a/reactos/lib/setupapi/diskspace.c +++ b/reactos/lib/setupapi/diskspace.c @@ -1,153 +1,153 @@ -/* - * SetupAPI DiskSpace functions - * - * Copyright 2004 CodeWeavers (Aric Stewart) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "winreg.h" -#include "setupapi.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -typedef struct { - WCHAR lpzName[20]; - LONGLONG dwFreeSpace; - LONGLONG dwWantedSpace; -} DRIVE_ENTRY, *LPDRIVE_ENTRY; - -typedef struct { - DWORD dwDriveCount; - DRIVE_ENTRY Drives[26]; -} DISKSPACELIST, *LPDISKSPACELIST; - - -/*********************************************************************** - * SetupCreateDiskSpaceListW (SETUPAPI.@) - */ -HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID Reserved1, DWORD Reserved2, UINT Flags) -{ - WCHAR drives[255]; - DWORD rc; - WCHAR *ptr; - LPDISKSPACELIST list=NULL; - - rc = GetLogicalDriveStringsW(255,drives); - - if (rc == 0) - return NULL; - - list = HeapAlloc(GetProcessHeap(),0,sizeof(DISKSPACELIST)); - - list->dwDriveCount = 0; - - ptr = drives; - - while (*ptr) - { - DWORD type = GetDriveTypeW(ptr); - DWORD len; - if (type == DRIVE_FIXED) - { - DWORD clusters; - DWORD sectors; - DWORD bytes; - DWORD total; - lstrcpyW(list->Drives[list->dwDriveCount].lpzName,ptr); - GetDiskFreeSpaceW(ptr,§ors,&bytes,&clusters,&total); - list->Drives[list->dwDriveCount].dwFreeSpace = clusters * sectors * - bytes; - list->Drives[list->dwDriveCount].dwWantedSpace = 0; - list->dwDriveCount++; - } - len = lstrlenW(ptr); - len++; - ptr+=sizeof(WCHAR)*len; - } - return (HANDLE)list; -} - - -/*********************************************************************** - * SetupCreateDiskSpaceListA (SETUPAPI.@) - */ -HDSKSPC WINAPI SetupCreateDiskSpaceListA(PVOID Reserved1, DWORD Reserved2, UINT Flags) -{ - return SetupCreateDiskSpaceListW( Reserved1, Reserved2, Flags ); -} - - -/*********************************************************************** - * SetupAddInstallSectionToDiskSpaceListA (SETUPAPI.@) - */ -BOOL WINAPI SetupAddInstallSectionToDiskSpaceListA(HDSKSPC DiskSpace, - HINF InfHandle, HINF LayoutInfHandle, - LPSTR SectionName, PVOID Reserved1, UINT Reserved2) -{ - FIXME ("Stub\n"); - return TRUE; -} - -/*********************************************************************** -* SetupQuerySpaceRequiredOnDriveA (SETUPAPI.@) -*/ -BOOL WINAPI SetupQuerySpaceRequiredOnDriveA(HDSKSPC DiskSpace, - LPSTR DriveSpec, LONGLONG* SpaceRequired, - PVOID Reserved1, UINT Reserved2) -{ - WCHAR driveW[20]; - unsigned int i; - LPDISKSPACELIST list = (LPDISKSPACELIST)DiskSpace; - BOOL rc = FALSE; - static const WCHAR bkslsh[]= {'\\',0}; - - MultiByteToWideChar(CP_ACP,0,DriveSpec,-1,driveW,20); - - lstrcatW(driveW,bkslsh); - - TRACE("Looking for drive %s\n",debugstr_w(driveW)); - - for (i = 0; i < list->dwDriveCount; i++) - { - TRACE("checking drive %s\n",debugstr_w(list->Drives[i].lpzName)); - if (lstrcmpW(driveW,list->Drives[i].lpzName)==0) - { - rc = TRUE; - *SpaceRequired = list->Drives[i].dwWantedSpace; - break; - } - } - - return rc; -} - -/*********************************************************************** -* SetupDestroyDiskSpaceList (SETUPAPI.@) -*/ -BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC DiskSpace) -{ - LPDISKSPACELIST list = (LPDISKSPACELIST)DiskSpace; - HeapFree(GetProcessHeap(),0,list); - return TRUE; -} +/* + * SetupAPI DiskSpace functions + * + * Copyright 2004 CodeWeavers (Aric Stewart) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "winreg.h" +#include "setupapi.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +typedef struct { + WCHAR lpzName[20]; + LONGLONG dwFreeSpace; + LONGLONG dwWantedSpace; +} DRIVE_ENTRY, *LPDRIVE_ENTRY; + +typedef struct { + DWORD dwDriveCount; + DRIVE_ENTRY Drives[26]; +} DISKSPACELIST, *LPDISKSPACELIST; + + +/*********************************************************************** + * SetupCreateDiskSpaceListW (SETUPAPI.@) + */ +HDSKSPC WINAPI SetupCreateDiskSpaceListW(PVOID Reserved1, DWORD Reserved2, UINT Flags) +{ + WCHAR drives[255]; + DWORD rc; + WCHAR *ptr; + LPDISKSPACELIST list=NULL; + + rc = GetLogicalDriveStringsW(255,drives); + + if (rc == 0) + return NULL; + + list = HeapAlloc(GetProcessHeap(),0,sizeof(DISKSPACELIST)); + + list->dwDriveCount = 0; + + ptr = drives; + + while (*ptr) + { + DWORD type = GetDriveTypeW(ptr); + DWORD len; + if (type == DRIVE_FIXED) + { + DWORD clusters; + DWORD sectors; + DWORD bytes; + DWORD total; + lstrcpyW(list->Drives[list->dwDriveCount].lpzName,ptr); + GetDiskFreeSpaceW(ptr,§ors,&bytes,&clusters,&total); + list->Drives[list->dwDriveCount].dwFreeSpace = clusters * sectors * + bytes; + list->Drives[list->dwDriveCount].dwWantedSpace = 0; + list->dwDriveCount++; + } + len = lstrlenW(ptr); + len++; + ptr+=sizeof(WCHAR)*len; + } + return (HANDLE)list; +} + + +/*********************************************************************** + * SetupCreateDiskSpaceListA (SETUPAPI.@) + */ +HDSKSPC WINAPI SetupCreateDiskSpaceListA(PVOID Reserved1, DWORD Reserved2, UINT Flags) +{ + return SetupCreateDiskSpaceListW( Reserved1, Reserved2, Flags ); +} + + +/*********************************************************************** + * SetupAddInstallSectionToDiskSpaceListA (SETUPAPI.@) + */ +BOOL WINAPI SetupAddInstallSectionToDiskSpaceListA(HDSKSPC DiskSpace, + HINF InfHandle, HINF LayoutInfHandle, + LPSTR SectionName, PVOID Reserved1, UINT Reserved2) +{ + FIXME ("Stub\n"); + return TRUE; +} + +/*********************************************************************** +* SetupQuerySpaceRequiredOnDriveA (SETUPAPI.@) +*/ +BOOL WINAPI SetupQuerySpaceRequiredOnDriveA(HDSKSPC DiskSpace, + LPSTR DriveSpec, LONGLONG* SpaceRequired, + PVOID Reserved1, UINT Reserved2) +{ + WCHAR driveW[20]; + unsigned int i; + LPDISKSPACELIST list = (LPDISKSPACELIST)DiskSpace; + BOOL rc = FALSE; + static const WCHAR bkslsh[]= {'\\',0}; + + MultiByteToWideChar(CP_ACP,0,DriveSpec,-1,driveW,20); + + lstrcatW(driveW,bkslsh); + + TRACE("Looking for drive %s\n",debugstr_w(driveW)); + + for (i = 0; i < list->dwDriveCount; i++) + { + TRACE("checking drive %s\n",debugstr_w(list->Drives[i].lpzName)); + if (lstrcmpW(driveW,list->Drives[i].lpzName)==0) + { + rc = TRUE; + *SpaceRequired = list->Drives[i].dwWantedSpace; + break; + } + } + + return rc; +} + +/*********************************************************************** +* SetupDestroyDiskSpaceList (SETUPAPI.@) +*/ +BOOL WINAPI SetupDestroyDiskSpaceList(HDSKSPC DiskSpace) +{ + LPDISKSPACELIST list = (LPDISKSPACELIST)DiskSpace; + HeapFree(GetProcessHeap(),0,list); + return TRUE; +} diff --git a/reactos/lib/setupapi/infparse.c b/reactos/lib/setupapi/infparse.c index 467f3760f63..c508db613ae 100644 --- a/reactos/lib/setupapi/infparse.c +++ b/reactos/lib/setupapi/infparse.c @@ -1,198 +1,198 @@ -/* - * SetupX .inf file parsing functions - * - * Copyright 2000 Andreas Mohr for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * FIXME: - * - return values ??? - * - this should be reimplemented at some point to have its own - * file parsing instead of using profile functions, - * as some SETUPX exports probably demand that - * (IpSaveRestorePosition, IpFindNextMatchLine, ...). - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winternl.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "setupapi.h" -#include "setupx16.h" -#include "setupapi_private.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -#define MAX_HANDLES 16384 -#define FIRST_HANDLE 32 - -static HINF handles[MAX_HANDLES]; - - -static RETERR16 alloc_hinf16( HINF hinf, HINF16 *hinf16 ) -{ - int i; - for (i = 0; i < MAX_HANDLES; i++) - { - if (!handles[i]) - { - handles[i] = hinf; - *hinf16 = i + FIRST_HANDLE; - return OK; - } - } - return ERR_IP_OUT_OF_HANDLES; -} - -static HINF get_hinf( HINF16 hinf16 ) -{ - int idx = hinf16 - FIRST_HANDLE; - if (idx < 0 || idx >= MAX_HANDLES) return 0; - return handles[idx]; -} - - -static HINF free_hinf16( HINF16 hinf16 ) -{ - HINF ret; - int idx = hinf16 - FIRST_HANDLE; - - if (idx < 0 || idx >= MAX_HANDLES) return 0; - ret = handles[idx]; - handles[idx] = 0; - return ret; -} - -/* convert last error code to a RETERR16 value */ -static RETERR16 get_last_error(void) -{ - switch(GetLastError()) - { - case ERROR_EXPECTED_SECTION_NAME: - case ERROR_BAD_SECTION_NAME_LINE: - case ERROR_SECTION_NAME_TOO_LONG: return ERR_IP_INVALID_SECT_NAME; - case ERROR_SECTION_NOT_FOUND: return ERR_IP_SECT_NOT_FOUND; - case ERROR_LINE_NOT_FOUND: return ERR_IP_LINE_NOT_FOUND; - default: return IP_ERROR; /* FIXME */ - } -} - - -/*********************************************************************** - * IpOpen (SETUPX.2) - * - */ -RETERR16 WINAPI IpOpen16( LPCSTR filename, HINF16 *hinf16 ) -{ - HINF hinf = SetupOpenInfFileA( filename, NULL, INF_STYLE_WIN4, NULL ); - if (hinf == (HINF)INVALID_HANDLE_VALUE) return get_last_error(); - return alloc_hinf16( hinf, hinf16 ); -} - - -/*********************************************************************** - * IpClose (SETUPX.4) - */ -RETERR16 WINAPI IpClose16( HINF16 hinf16 ) -{ - HINF hinf = free_hinf16( hinf16 ); - if (!hinf) return ERR_IP_INVALID_HINF; - SetupCloseInfFile( hinf ); - return OK; -} - - -/*********************************************************************** - * IpGetProfileString (SETUPX.210) - */ -RETERR16 WINAPI IpGetProfileString16( HINF16 hinf16, LPCSTR section, LPCSTR entry, - LPSTR buffer, WORD buflen ) -{ - DWORD required_size; - HINF hinf = get_hinf( hinf16 ); - - if (!hinf) return ERR_IP_INVALID_HINF; - if (!SetupGetLineTextA( NULL, hinf, section, entry, buffer, buflen, &required_size )) - return get_last_error(); - TRACE("%p: section %s entry %s ret %s\n", - hinf, debugstr_a(section), debugstr_a(entry), debugstr_a(buffer) ); - return OK; -} - - -/*********************************************************************** - * GenFormStrWithoutPlaceHolders (SETUPX.103) - * - * ought to be pretty much implemented, I guess... - */ -void WINAPI GenFormStrWithoutPlaceHolders16( LPSTR dst, LPCSTR src, HINF16 hinf16 ) -{ - UNICODE_STRING srcW; - HINF hinf = get_hinf( hinf16 ); - - if (!hinf) return; - - if (!RtlCreateUnicodeStringFromAsciiz( &srcW, src )) return; - PARSER_string_substA( hinf, srcW.Buffer, dst, MAX_INF_STRING_LENGTH ); - RtlFreeUnicodeString( &srcW ); - TRACE( "%s -> %s\n", debugstr_a(src), debugstr_a(dst) ); -} - -/*********************************************************************** - * GenInstall (SETUPX.101) - * - * generic installer function for .INF file sections - * - * This is not perfect - patch whenever you can ! - * - * wFlags == GENINSTALL_DO_xxx - * e.g. NetMeeting: - * first call GENINSTALL_DO_REGSRCPATH | GENINSTALL_DO_FILES, - * second call GENINSTALL_DO_LOGCONFIG | CFGAUTO | INI2REG | REG | INI - */ -RETERR16 WINAPI GenInstall16( HINF16 hinf16, LPCSTR section, WORD genflags ) -{ - UINT flags = 0; - HINF hinf = get_hinf( hinf16 ); - RETERR16 ret = OK; - void *context; - - if (!hinf) return ERR_IP_INVALID_HINF; - - if (genflags & GENINSTALL_DO_FILES) flags |= SPINST_FILES; - if (genflags & GENINSTALL_DO_INI) flags |= SPINST_INIFILES; - if (genflags & GENINSTALL_DO_REG) flags |= SPINST_REGISTRY; - if (genflags & GENINSTALL_DO_INI2REG) flags |= SPINST_INI2REG; - if (genflags & GENINSTALL_DO_LOGCONFIG) flags |= SPINST_LOGCONFIG; - if (genflags & GENINSTALL_DO_REGSRCPATH) FIXME( "unsupported flag: GENINSTALL_DO_REGSRCPATH\n" ); - if (genflags & GENINSTALL_DO_CFGAUTO) FIXME( "unsupported flag: GENINSTALL_DO_CFGAUTO\n" ); - if (genflags & GENINSTALL_DO_PERUSER) FIXME( "unsupported flag: GENINSTALL_DO_PERUSER\n" ); - - context = SetupInitDefaultQueueCallback( 0 ); - if (!SetupInstallFromInfSectionA( 0, hinf, section, flags, 0, NULL, - SP_COPY_NEWER_OR_SAME, SetupDefaultQueueCallbackA, - context, 0, 0 )) - ret = get_last_error(); - - SetupTermDefaultQueueCallback( context ); - return ret; -} +/* + * SetupX .inf file parsing functions + * + * Copyright 2000 Andreas Mohr for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FIXME: + * - return values ??? + * - this should be reimplemented at some point to have its own + * file parsing instead of using profile functions, + * as some SETUPX exports probably demand that + * (IpSaveRestorePosition, IpFindNextMatchLine, ...). + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winternl.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "setupapi.h" +#include "setupx16.h" +#include "setupapi_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +#define MAX_HANDLES 16384 +#define FIRST_HANDLE 32 + +static HINF handles[MAX_HANDLES]; + + +static RETERR16 alloc_hinf16( HINF hinf, HINF16 *hinf16 ) +{ + int i; + for (i = 0; i < MAX_HANDLES; i++) + { + if (!handles[i]) + { + handles[i] = hinf; + *hinf16 = i + FIRST_HANDLE; + return OK; + } + } + return ERR_IP_OUT_OF_HANDLES; +} + +static HINF get_hinf( HINF16 hinf16 ) +{ + int idx = hinf16 - FIRST_HANDLE; + if (idx < 0 || idx >= MAX_HANDLES) return 0; + return handles[idx]; +} + + +static HINF free_hinf16( HINF16 hinf16 ) +{ + HINF ret; + int idx = hinf16 - FIRST_HANDLE; + + if (idx < 0 || idx >= MAX_HANDLES) return 0; + ret = handles[idx]; + handles[idx] = 0; + return ret; +} + +/* convert last error code to a RETERR16 value */ +static RETERR16 get_last_error(void) +{ + switch(GetLastError()) + { + case ERROR_EXPECTED_SECTION_NAME: + case ERROR_BAD_SECTION_NAME_LINE: + case ERROR_SECTION_NAME_TOO_LONG: return ERR_IP_INVALID_SECT_NAME; + case ERROR_SECTION_NOT_FOUND: return ERR_IP_SECT_NOT_FOUND; + case ERROR_LINE_NOT_FOUND: return ERR_IP_LINE_NOT_FOUND; + default: return IP_ERROR; /* FIXME */ + } +} + + +/*********************************************************************** + * IpOpen (SETUPX.2) + * + */ +RETERR16 WINAPI IpOpen16( LPCSTR filename, HINF16 *hinf16 ) +{ + HINF hinf = SetupOpenInfFileA( filename, NULL, INF_STYLE_WIN4, NULL ); + if (hinf == (HINF)INVALID_HANDLE_VALUE) return get_last_error(); + return alloc_hinf16( hinf, hinf16 ); +} + + +/*********************************************************************** + * IpClose (SETUPX.4) + */ +RETERR16 WINAPI IpClose16( HINF16 hinf16 ) +{ + HINF hinf = free_hinf16( hinf16 ); + if (!hinf) return ERR_IP_INVALID_HINF; + SetupCloseInfFile( hinf ); + return OK; +} + + +/*********************************************************************** + * IpGetProfileString (SETUPX.210) + */ +RETERR16 WINAPI IpGetProfileString16( HINF16 hinf16, LPCSTR section, LPCSTR entry, + LPSTR buffer, WORD buflen ) +{ + DWORD required_size; + HINF hinf = get_hinf( hinf16 ); + + if (!hinf) return ERR_IP_INVALID_HINF; + if (!SetupGetLineTextA( NULL, hinf, section, entry, buffer, buflen, &required_size )) + return get_last_error(); + TRACE("%p: section %s entry %s ret %s\n", + hinf, debugstr_a(section), debugstr_a(entry), debugstr_a(buffer) ); + return OK; +} + + +/*********************************************************************** + * GenFormStrWithoutPlaceHolders (SETUPX.103) + * + * ought to be pretty much implemented, I guess... + */ +void WINAPI GenFormStrWithoutPlaceHolders16( LPSTR dst, LPCSTR src, HINF16 hinf16 ) +{ + UNICODE_STRING srcW; + HINF hinf = get_hinf( hinf16 ); + + if (!hinf) return; + + if (!RtlCreateUnicodeStringFromAsciiz( &srcW, src )) return; + PARSER_string_substA( hinf, srcW.Buffer, dst, MAX_INF_STRING_LENGTH ); + RtlFreeUnicodeString( &srcW ); + TRACE( "%s -> %s\n", debugstr_a(src), debugstr_a(dst) ); +} + +/*********************************************************************** + * GenInstall (SETUPX.101) + * + * generic installer function for .INF file sections + * + * This is not perfect - patch whenever you can ! + * + * wFlags == GENINSTALL_DO_xxx + * e.g. NetMeeting: + * first call GENINSTALL_DO_REGSRCPATH | GENINSTALL_DO_FILES, + * second call GENINSTALL_DO_LOGCONFIG | CFGAUTO | INI2REG | REG | INI + */ +RETERR16 WINAPI GenInstall16( HINF16 hinf16, LPCSTR section, WORD genflags ) +{ + UINT flags = 0; + HINF hinf = get_hinf( hinf16 ); + RETERR16 ret = OK; + void *context; + + if (!hinf) return ERR_IP_INVALID_HINF; + + if (genflags & GENINSTALL_DO_FILES) flags |= SPINST_FILES; + if (genflags & GENINSTALL_DO_INI) flags |= SPINST_INIFILES; + if (genflags & GENINSTALL_DO_REG) flags |= SPINST_REGISTRY; + if (genflags & GENINSTALL_DO_INI2REG) flags |= SPINST_INI2REG; + if (genflags & GENINSTALL_DO_LOGCONFIG) flags |= SPINST_LOGCONFIG; + if (genflags & GENINSTALL_DO_REGSRCPATH) FIXME( "unsupported flag: GENINSTALL_DO_REGSRCPATH\n" ); + if (genflags & GENINSTALL_DO_CFGAUTO) FIXME( "unsupported flag: GENINSTALL_DO_CFGAUTO\n" ); + if (genflags & GENINSTALL_DO_PERUSER) FIXME( "unsupported flag: GENINSTALL_DO_PERUSER\n" ); + + context = SetupInitDefaultQueueCallback( 0 ); + if (!SetupInstallFromInfSectionA( 0, hinf, section, flags, 0, NULL, + SP_COPY_NEWER_OR_SAME, SetupDefaultQueueCallbackA, + context, 0, 0 )) + ret = get_last_error(); + + SetupTermDefaultQueueCallback( context ); + return ret; +} diff --git a/reactos/lib/setupapi/install.c b/reactos/lib/setupapi/install.c index 5215d1f096c..344e91934ce 100644 --- a/reactos/lib/setupapi/install.c +++ b/reactos/lib/setupapi/install.c @@ -1,955 +1,955 @@ -/* - * Setupapi install routines - * - * Copyright 2002 Alexandre Julliard for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winternl.h" -#include "winerror.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "setupapi.h" -#include "setupapi_private.h" -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -/* info passed to callback functions dealing with files */ -struct files_callback_info -{ - HSPFILEQ queue; - PCWSTR src_root; - UINT copy_flags; - HINF layout; -}; - -/* info passed to callback functions dealing with the registry */ -struct registry_callback_info -{ - HKEY default_root; - BOOL delete; -}; - -/* info passed to callback functions dealing with registering dlls */ -struct register_dll_info -{ - PSP_FILE_CALLBACK_W callback; - PVOID callback_context; - BOOL unregister; -}; - -typedef BOOL (*iterate_fields_func)( HINF hinf, PCWSTR field, void *arg ); - -/* Unicode constants */ -static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0}; -static const WCHAR DelFiles[] = {'D','e','l','F','i','l','e','s',0}; -static const WCHAR RenFiles[] = {'R','e','n','F','i','l','e','s',0}; -static const WCHAR Ini2Reg[] = {'I','n','i','2','R','e','g',0}; -static const WCHAR LogConf[] = {'L','o','g','C','o','n','f',0}; -static const WCHAR AddReg[] = {'A','d','d','R','e','g',0}; -static const WCHAR DelReg[] = {'D','e','l','R','e','g',0}; -static const WCHAR BitReg[] = {'B','i','t','R','e','g',0}; -static const WCHAR UpdateInis[] = {'U','p','d','a','t','e','I','n','i','s',0}; -static const WCHAR CopyINF[] = {'C','o','p','y','I','N','F',0}; -static const WCHAR UpdateIniFields[] = {'U','p','d','a','t','e','I','n','i','F','i','e','l','d','s',0}; -static const WCHAR RegisterDlls[] = {'R','e','g','i','s','t','e','r','D','l','l','s',0}; -static const WCHAR UnregisterDlls[] = {'U','n','r','e','g','i','s','t','e','r','D','l','l','s',0}; -static const WCHAR ProfileItems[] = {'P','r','o','f','i','l','e','I','t','e','m','s',0}; - - -/*********************************************************************** - * get_field_string - * - * Retrieve the contents of a field, dynamically growing the buffer if necessary. - */ -static WCHAR *get_field_string( INFCONTEXT *context, DWORD index, WCHAR *buffer, - WCHAR *static_buffer, DWORD *size ) -{ - DWORD required; - - if (SetupGetStringFieldW( context, index, buffer, *size, &required )) return buffer; - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - /* now grow the buffer */ - if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer ); - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, required*sizeof(WCHAR) ))) return NULL; - *size = required; - if (SetupGetStringFieldW( context, index, buffer, *size, &required )) return buffer; - } - if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer ); - return NULL; -} - - -/*********************************************************************** - * copy_files_callback - * - * Called once for each CopyFiles entry in a given section. - */ -static BOOL copy_files_callback( HINF hinf, PCWSTR field, void *arg ) -{ - struct files_callback_info *info = arg; - - if (field[0] == '@') /* special case: copy single file */ - SetupQueueDefaultCopyW( info->queue, info->layout, info->src_root, NULL, field, info->copy_flags ); - else - SetupQueueCopySectionW( info->queue, info->src_root, info->layout, hinf, field, info->copy_flags ); - return TRUE; -} - - -/*********************************************************************** - * delete_files_callback - * - * Called once for each DelFiles entry in a given section. - */ -static BOOL delete_files_callback( HINF hinf, PCWSTR field, void *arg ) -{ - struct files_callback_info *info = arg; - SetupQueueDeleteSectionW( info->queue, hinf, 0, field ); - return TRUE; -} - - -/*********************************************************************** - * rename_files_callback - * - * Called once for each RenFiles entry in a given section. - */ -static BOOL rename_files_callback( HINF hinf, PCWSTR field, void *arg ) -{ - struct files_callback_info *info = arg; - SetupQueueRenameSectionW( info->queue, hinf, 0, field ); - return TRUE; -} - - -/*********************************************************************** - * get_root_key - * - * Retrieve the registry root key from its name. - */ -static HKEY get_root_key( const WCHAR *name, HKEY def_root ) -{ - static const WCHAR HKCR[] = {'H','K','C','R',0}; - static const WCHAR HKCU[] = {'H','K','C','U',0}; - static const WCHAR HKLM[] = {'H','K','L','M',0}; - static const WCHAR HKU[] = {'H','K','U',0}; - static const WCHAR HKR[] = {'H','K','R',0}; - - if (!strcmpiW( name, HKCR )) return HKEY_CLASSES_ROOT; - if (!strcmpiW( name, HKCU )) return HKEY_CURRENT_USER; - if (!strcmpiW( name, HKLM )) return HKEY_LOCAL_MACHINE; - if (!strcmpiW( name, HKU )) return HKEY_USERS; - if (!strcmpiW( name, HKR )) return def_root; - return 0; -} - - -/*********************************************************************** - * append_multi_sz_value - * - * Append a multisz string to a multisz registry value. - */ -static void append_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *strings, - DWORD str_size ) -{ - DWORD size, type, total; - WCHAR *buffer, *p; - - if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return; - if (type != REG_MULTI_SZ) return; - - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size + str_size) * sizeof(WCHAR) ))) return; - if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done; - - /* compare each string against all the existing ones */ - total = size; - while (*strings) - { - int len = strlenW(strings) + 1; - - for (p = buffer; *p; p += strlenW(p) + 1) - if (!strcmpiW( p, strings )) break; - - if (!*p) /* not found, need to append it */ - { - memcpy( p, strings, len * sizeof(WCHAR) ); - p[len] = 0; - total += len; - } - strings += len; - } - if (total != size) - { - TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer) ); - RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, (BYTE *)buffer, total ); - } - done: - HeapFree( GetProcessHeap(), 0, buffer ); -} - - -/*********************************************************************** - * delete_multi_sz_value - * - * Remove a string from a multisz registry value. - */ -static void delete_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *string ) -{ - DWORD size, type; - WCHAR *buffer, *src, *dst; - - if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return; - if (type != REG_MULTI_SZ) return; - /* allocate double the size, one for value before and one for after */ - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size * 2 * sizeof(WCHAR) ))) return; - if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done; - src = buffer; - dst = buffer + size; - while (*src) - { - int len = strlenW(src) + 1; - if (strcmpiW( src, string )) - { - memcpy( dst, src, len * sizeof(WCHAR) ); - dst += len; - } - src += len; - } - *dst++ = 0; - if (dst != buffer + 2*size) /* did we remove something? */ - { - TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer + size) ); - RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, - (BYTE *)(buffer + size), dst - (buffer + size) ); - } - done: - HeapFree( GetProcessHeap(), 0, buffer ); -} - - -/*********************************************************************** - * do_reg_operation - * - * Perform an add/delete registry operation depending on the flags. - */ -static BOOL do_reg_operation( HKEY hkey, const WCHAR *value, INFCONTEXT *context, INT flags ) -{ - DWORD type, size; - - if (flags & (FLG_ADDREG_DELREG_BIT | FLG_ADDREG_DELVAL)) /* deletion */ - { - if (*value && !(flags & FLG_DELREG_KEYONLY_COMMON)) - { - if ((flags & FLG_DELREG_MULTI_SZ_DELSTRING) == FLG_DELREG_MULTI_SZ_DELSTRING) - { - WCHAR *str; - - if (!SetupGetStringFieldW( context, 5, NULL, 0, &size ) || !size) return TRUE; - if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE; - SetupGetStringFieldW( context, 5, str, size, NULL ); - delete_multi_sz_value( hkey, value, str ); - HeapFree( GetProcessHeap(), 0, str ); - } - else RegDeleteValueW( hkey, value ); - } - else RegDeleteKeyW( hkey, NULL ); - return TRUE; - } - - if (flags & (FLG_ADDREG_KEYONLY|FLG_ADDREG_KEYONLY_COMMON)) return TRUE; - - if (flags & (FLG_ADDREG_NOCLOBBER|FLG_ADDREG_OVERWRITEONLY)) - { - BOOL exists = !RegQueryValueExW( hkey, value, NULL, NULL, NULL, NULL ); - if (exists && (flags & FLG_ADDREG_NOCLOBBER)) return TRUE; - if (!exists & (flags & FLG_ADDREG_OVERWRITEONLY)) return TRUE; - } - - switch(flags & FLG_ADDREG_TYPE_MASK) - { - case FLG_ADDREG_TYPE_SZ: type = REG_SZ; break; - case FLG_ADDREG_TYPE_MULTI_SZ: type = REG_MULTI_SZ; break; - case FLG_ADDREG_TYPE_EXPAND_SZ: type = REG_EXPAND_SZ; break; - case FLG_ADDREG_TYPE_BINARY: type = REG_BINARY; break; - case FLG_ADDREG_TYPE_DWORD: type = REG_DWORD; break; - case FLG_ADDREG_TYPE_NONE: type = REG_NONE; break; - default: type = flags >> 16; break; - } - - if (!(flags & FLG_ADDREG_BINVALUETYPE) || - (type == REG_DWORD && SetupGetFieldCount(context) == 5)) - { - static const WCHAR empty; - WCHAR *str = NULL; - - if (type == REG_MULTI_SZ) - { - if (!SetupGetMultiSzFieldW( context, 5, NULL, 0, &size )) size = 0; - if (size) - { - if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE; - SetupGetMultiSzFieldW( context, 5, str, size, NULL ); - } - if (flags & FLG_ADDREG_APPEND) - { - if (!str) return TRUE; - append_multi_sz_value( hkey, value, str, size ); - HeapFree( GetProcessHeap(), 0, str ); - return TRUE; - } - /* else fall through to normal string handling */ - } - else - { - if (!SetupGetStringFieldW( context, 5, NULL, 0, &size )) size = 0; - if (size) - { - if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE; - SetupGetStringFieldW( context, 5, str, size, NULL ); - } - } - - if (type == REG_DWORD) - { - DWORD dw = str ? strtoulW( str, NULL, 16 ) : 0; - TRACE( "setting dword %s to %lx\n", debugstr_w(value), dw ); - RegSetValueExW( hkey, value, 0, type, (BYTE *)&dw, sizeof(dw) ); - } - else - { - TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(str) ); - if (str) RegSetValueExW( hkey, value, 0, type, (BYTE *)str, size * sizeof(WCHAR) ); - else RegSetValueExW( hkey, value, 0, type, (const BYTE *)&empty, sizeof(WCHAR) ); - } - HeapFree( GetProcessHeap(), 0, str ); - return TRUE; - } - else /* get the binary data */ - { - BYTE *data = NULL; - - if (!SetupGetBinaryField( context, 5, NULL, 0, &size )) size = 0; - if (size) - { - if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE; - TRACE( "setting binary data %s len %ld\n", debugstr_w(value), size ); - SetupGetBinaryField( context, 5, data, size, NULL ); - } - RegSetValueExW( hkey, value, 0, type, data, size ); - HeapFree( GetProcessHeap(), 0, data ); - return TRUE; - } -} - - -/*********************************************************************** - * registry_callback - * - * Called once for each AddReg and DelReg entry in a given section. - */ -static BOOL registry_callback( HINF hinf, PCWSTR field, void *arg ) -{ - struct registry_callback_info *info = arg; - INFCONTEXT context; - HKEY root_key, hkey; - - BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context ); - - for (; ok; ok = SetupFindNextLine( &context, &context )) - { - WCHAR buffer[MAX_INF_STRING_LENGTH]; - INT flags; - - /* get root */ - if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) - continue; - if (!(root_key = get_root_key( buffer, info->default_root ))) - continue; - - /* get key */ - if (!SetupGetStringFieldW( &context, 2, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) - *buffer = 0; - - /* get flags */ - if (!SetupGetIntField( &context, 4, &flags )) flags = 0; - - if (!info->delete) - { - if (flags & FLG_ADDREG_DELREG_BIT) continue; /* ignore this entry */ - } - else - { - if (!flags) flags = FLG_ADDREG_DELREG_BIT; - else if (!(flags & FLG_ADDREG_DELREG_BIT)) continue; /* ignore this entry */ - } - - if (info->delete || (flags & FLG_ADDREG_OVERWRITEONLY)) - { - if (RegOpenKeyW( root_key, buffer, &hkey )) continue; /* ignore if it doesn't exist */ - } - else if (RegCreateKeyW( root_key, buffer, &hkey )) - { - ERR( "could not create key %p %s\n", root_key, debugstr_w(buffer) ); - continue; - } - TRACE( "key %p %s\n", root_key, debugstr_w(buffer) ); - - /* get value name */ - if (!SetupGetStringFieldW( &context, 3, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) - *buffer = 0; - - /* and now do it */ - if (!do_reg_operation( hkey, buffer, &context, flags )) - { - RegCloseKey( hkey ); - return FALSE; - } - RegCloseKey( hkey ); - } - return TRUE; -} - - -/*********************************************************************** - * do_register_dll - * - * Register or unregister a dll. - */ -static BOOL do_register_dll( const struct register_dll_info *info, const WCHAR *path, - INT flags, INT timeout, const WCHAR *args ) -{ - HMODULE module; - HRESULT res; - SP_REGISTER_CONTROL_STATUSW status; - - status.cbSize = sizeof(status); - status.FileName = path; - status.FailureCode = SPREG_SUCCESS; - status.Win32Error = ERROR_SUCCESS; - - if (info->callback) - { - switch(info->callback( info->callback_context, SPFILENOTIFY_STARTREGISTRATION, - (UINT_PTR)&status, !info->unregister )) - { - case FILEOP_ABORT: - SetLastError( ERROR_OPERATION_ABORTED ); - return FALSE; - case FILEOP_SKIP: - return TRUE; - case FILEOP_DOIT: - break; - } - } - - if (!(module = LoadLibraryExW( path, 0, LOAD_WITH_ALTERED_SEARCH_PATH ))) - { - WARN( "could not load %s\n", debugstr_w(path) ); - status.FailureCode = SPREG_LOADLIBRARY; - status.Win32Error = GetLastError(); - goto done; - } - - if (flags & FLG_REGSVR_DLLREGISTER) - { - const char *entry_point = info->unregister ? "DllUnregisterServer" : "DllRegisterServer"; - HRESULT (WINAPI *func)(void) = (void *)GetProcAddress( module, entry_point ); - - if (!func) - { - status.FailureCode = SPREG_GETPROCADDR; - status.Win32Error = GetLastError(); - goto done; - } - - TRACE( "calling %s in %s\n", entry_point, debugstr_w(path) ); - res = func(); - - if (FAILED(res)) - { - WARN( "calling %s in %s returned error %lx\n", entry_point, debugstr_w(path), res ); - status.FailureCode = SPREG_REGSVR; - status.Win32Error = res; - goto done; - } - } - - if (flags & FLG_REGSVR_DLLINSTALL) - { - HRESULT (WINAPI *func)(BOOL,LPCWSTR) = (void *)GetProcAddress( module, "DllInstall" ); - - if (!func) - { - status.FailureCode = SPREG_GETPROCADDR; - status.Win32Error = GetLastError(); - goto done; - } - - TRACE( "calling DllInstall(%d,%s) in %s\n", - !info->unregister, debugstr_w(args), debugstr_w(path) ); - res = func( !info->unregister, args ); - - if (FAILED(res)) - { - WARN( "calling DllInstall in %s returned error %lx\n", debugstr_w(path), res ); - status.FailureCode = SPREG_REGSVR; - status.Win32Error = res; - goto done; - } - } - -done: - if (module) FreeLibrary( module ); - if (info->callback) info->callback( info->callback_context, SPFILENOTIFY_ENDREGISTRATION, - (UINT_PTR)&status, !info->unregister ); - return TRUE; -} - - -/*********************************************************************** - * register_dlls_callback - * - * Called once for each RegisterDlls entry in a given section. - */ -static BOOL register_dlls_callback( HINF hinf, PCWSTR field, void *arg ) -{ - struct register_dll_info *info = arg; - INFCONTEXT context; - BOOL ret = TRUE; - BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context ); - - for (; ok; ok = SetupFindNextLine( &context, &context )) - { - WCHAR *path, *args, *p; - WCHAR buffer[MAX_INF_STRING_LENGTH]; - INT flags, timeout; - - /* get directory */ - if (!(path = PARSER_get_dest_dir( &context ))) continue; - - /* get dll name */ - if (!SetupGetStringFieldW( &context, 3, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) - goto done; - if (!(p = HeapReAlloc( GetProcessHeap(), 0, path, - (strlenW(path) + strlenW(buffer) + 2) * sizeof(WCHAR) ))) goto done; - path = p; - p += strlenW(p); - if (p == path || p[-1] != '\\') *p++ = '\\'; - strcpyW( p, buffer ); - - /* get flags */ - if (!SetupGetIntField( &context, 4, &flags )) flags = 0; - - /* get timeout */ - if (!SetupGetIntField( &context, 5, &timeout )) timeout = 60; - - /* get command line */ - args = NULL; - if (SetupGetStringFieldW( &context, 6, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) - args = buffer; - - ret = do_register_dll( info, path, flags, timeout, args ); - - done: - HeapFree( GetProcessHeap(), 0, path ); - if (!ret) break; - } - return ret; -} - -/*********************************************************************** - * update_ini_callback - * - * Called once for each UpdateInis entry in a given section. - */ -static BOOL update_ini_callback( HINF hinf, PCWSTR field, void *arg ) -{ - INFCONTEXT context; - - BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context ); - - for (; ok; ok = SetupFindNextLine( &context, &context )) - { - WCHAR buffer[MAX_INF_STRING_LENGTH]; - WCHAR filename[MAX_INF_STRING_LENGTH]; - WCHAR section[MAX_INF_STRING_LENGTH]; - WCHAR entry[MAX_INF_STRING_LENGTH]; - WCHAR string[MAX_INF_STRING_LENGTH]; - LPWSTR divider; - - if (!SetupGetStringFieldW( &context, 1, filename, - sizeof(filename)/sizeof(WCHAR), NULL )) - continue; - - if (!SetupGetStringFieldW( &context, 2, section, - sizeof(section)/sizeof(WCHAR), NULL )) - continue; - - if (!SetupGetStringFieldW( &context, 4, buffer, - sizeof(buffer)/sizeof(WCHAR), NULL )) - continue; - - divider = strchrW(buffer,'='); - if (divider) - { - *divider = 0; - strcpyW(entry,buffer); - divider++; - strcpyW(string,divider); - } - else - { - strcpyW(entry,buffer); - string[0]=0; - } - - TRACE("Writing %s = %s in %s of file %s\n",debugstr_w(entry), - debugstr_w(string),debugstr_w(section),debugstr_w(filename)); - WritePrivateProfileStringW(section,entry,string,filename); - - } - return TRUE; -} - -static BOOL update_ini_fields_callback( HINF hinf, PCWSTR field, void *arg ) -{ - FIXME( "should update ini fields %s\n", debugstr_w(field) ); - return TRUE; -} - -static BOOL ini2reg_callback( HINF hinf, PCWSTR field, void *arg ) -{ - FIXME( "should do ini2reg %s\n", debugstr_w(field) ); - return TRUE; -} - -static BOOL logconf_callback( HINF hinf, PCWSTR field, void *arg ) -{ - FIXME( "should do logconf %s\n", debugstr_w(field) ); - return TRUE; -} - -static BOOL bitreg_callback( HINF hinf, PCWSTR field, void *arg ) -{ - FIXME( "should do bitreg %s\n", debugstr_w(field) ); - return TRUE; -} - -static BOOL profile_items_callback( HINF hinf, PCWSTR field, void *arg ) -{ - FIXME( "should do profile items %s\n", debugstr_w(field) ); - return TRUE; -} - -static BOOL copy_inf_callback( HINF hinf, PCWSTR field, void *arg ) -{ - FIXME( "should do copy inf %s\n", debugstr_w(field) ); - return TRUE; -} - - -/*********************************************************************** - * iterate_section_fields - * - * Iterate over all fields of a certain key of a certain section - */ -static BOOL iterate_section_fields( HINF hinf, PCWSTR section, PCWSTR key, - iterate_fields_func callback, void *arg ) -{ - WCHAR static_buffer[200]; - WCHAR *buffer = static_buffer; - DWORD size = sizeof(static_buffer)/sizeof(WCHAR); - INFCONTEXT context; - BOOL ret = FALSE; - - BOOL ok = SetupFindFirstLineW( hinf, section, key, &context ); - while (ok) - { - UINT i, count = SetupGetFieldCount( &context ); - for (i = 1; i <= count; i++) - { - if (!(buffer = get_field_string( &context, i, buffer, static_buffer, &size ))) - goto done; - if (!callback( hinf, buffer, arg )) - { - WARN("callback failed for %s %s err %ld\n", - debugstr_w(section), debugstr_w(buffer), GetLastError() ); - goto done; - } - } - ok = SetupFindNextMatchLineW( &context, key, &context ); - } - ret = TRUE; - done: - if (buffer && buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer ); - return ret; -} - - -/*********************************************************************** - * SetupInstallFilesFromInfSectionA (SETUPAPI.@) - */ -BOOL WINAPI SetupInstallFilesFromInfSectionA( HINF hinf, HINF hlayout, HSPFILEQ queue, - PCSTR section, PCSTR src_root, UINT flags ) -{ - UNICODE_STRING sectionW; - BOOL ret = FALSE; - - if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - } - if (!src_root) - ret = SetupInstallFilesFromInfSectionW( hinf, hlayout, queue, sectionW.Buffer, - NULL, flags ); - else - { - UNICODE_STRING srcW; - if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root )) - { - ret = SetupInstallFilesFromInfSectionW( hinf, hlayout, queue, sectionW.Buffer, - srcW.Buffer, flags ); - RtlFreeUnicodeString( &srcW ); - } - else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - } - RtlFreeUnicodeString( §ionW ); - return ret; -} - - -/*********************************************************************** - * SetupInstallFilesFromInfSectionW (SETUPAPI.@) - */ -BOOL WINAPI SetupInstallFilesFromInfSectionW( HINF hinf, HINF hlayout, HSPFILEQ queue, - PCWSTR section, PCWSTR src_root, UINT flags ) -{ - struct files_callback_info info; - - info.queue = queue; - info.src_root = src_root; - info.copy_flags = flags; - info.layout = hlayout; - return iterate_section_fields( hinf, section, CopyFiles, copy_files_callback, &info ); -} - - -/*********************************************************************** - * SetupInstallFromInfSectionA (SETUPAPI.@) - */ -BOOL WINAPI SetupInstallFromInfSectionA( HWND owner, HINF hinf, PCSTR section, UINT flags, - HKEY key_root, PCSTR src_root, UINT copy_flags, - PSP_FILE_CALLBACK_A callback, PVOID context, - HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data ) -{ - UNICODE_STRING sectionW, src_rootW; - struct callback_WtoA_context ctx; - BOOL ret = FALSE; - - src_rootW.Buffer = NULL; - if (src_root && !RtlCreateUnicodeStringFromAsciiz( &src_rootW, src_root )) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - } - - if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) - { - ctx.orig_context = context; - ctx.orig_handler = callback; - ret = SetupInstallFromInfSectionW( owner, hinf, sectionW.Buffer, flags, key_root, - src_rootW.Buffer, copy_flags, QUEUE_callback_WtoA, - &ctx, devinfo, devinfo_data ); - RtlFreeUnicodeString( §ionW ); - } - else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - - RtlFreeUnicodeString( &src_rootW ); - return ret; -} - - -/*********************************************************************** - * SetupInstallFromInfSectionW (SETUPAPI.@) - */ -BOOL WINAPI SetupInstallFromInfSectionW( HWND owner, HINF hinf, PCWSTR section, UINT flags, - HKEY key_root, PCWSTR src_root, UINT copy_flags, - PSP_FILE_CALLBACK_W callback, PVOID context, - HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data ) -{ - if (flags & SPINST_FILES) - { - struct files_callback_info info; - HSPFILEQ queue; - BOOL ret; - - if (!(queue = SetupOpenFileQueue())) return FALSE; - info.queue = queue; - info.src_root = src_root; - info.copy_flags = copy_flags; - info.layout = hinf; - ret = (iterate_section_fields( hinf, section, CopyFiles, copy_files_callback, &info ) && - iterate_section_fields( hinf, section, DelFiles, delete_files_callback, &info ) && - iterate_section_fields( hinf, section, RenFiles, rename_files_callback, &info ) && - SetupCommitFileQueueW( owner, queue, callback, context )); - SetupCloseFileQueue( queue ); - if (!ret) return FALSE; - } - if (flags & SPINST_INIFILES) - { - if (!iterate_section_fields( hinf, section, UpdateInis, update_ini_callback, NULL ) || - !iterate_section_fields( hinf, section, UpdateIniFields, - update_ini_fields_callback, NULL )) - return FALSE; - } - if (flags & SPINST_INI2REG) - { - if (!iterate_section_fields( hinf, section, Ini2Reg, ini2reg_callback, NULL )) - return FALSE; - } - if (flags & SPINST_LOGCONFIG) - { - if (!iterate_section_fields( hinf, section, LogConf, logconf_callback, NULL )) - return FALSE; - } - if (flags & SPINST_REGSVR) - { - struct register_dll_info info; - - info.unregister = FALSE; - if (flags & SPINST_REGISTERCALLBACKAWARE) - { - info.callback = callback; - info.callback_context = context; - } - else info.callback = NULL; - - if (!iterate_section_fields( hinf, section, RegisterDlls, register_dlls_callback, &info )) - return FALSE; - } - if (flags & SPINST_UNREGSVR) - { - struct register_dll_info info; - - info.unregister = TRUE; - if (flags & SPINST_REGISTERCALLBACKAWARE) - { - info.callback = callback; - info.callback_context = context; - } - else info.callback = NULL; - - if (!iterate_section_fields( hinf, section, UnregisterDlls, register_dlls_callback, &info )) - return FALSE; - } - if (flags & SPINST_REGISTRY) - { - struct registry_callback_info info; - - info.default_root = key_root; - info.delete = TRUE; - if (!iterate_section_fields( hinf, section, DelReg, registry_callback, &info )) - return FALSE; - info.delete = FALSE; - if (!iterate_section_fields( hinf, section, AddReg, registry_callback, &info )) - return FALSE; - } - if (flags & SPINST_BITREG) - { - if (!iterate_section_fields( hinf, section, BitReg, bitreg_callback, NULL )) - return FALSE; - } - if (flags & SPINST_PROFILEITEMS) - { - if (!iterate_section_fields( hinf, section, ProfileItems, profile_items_callback, NULL )) - return FALSE; - } - if (flags & SPINST_COPYINF) - { - if (!iterate_section_fields( hinf, section, CopyINF, copy_inf_callback, NULL )) - return FALSE; - } - - return TRUE; -} - - -/*********************************************************************** - * InstallHinfSectionW (SETUPAPI.@) - * - * NOTE: 'cmdline' is
from - * RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection
- */ -void WINAPI InstallHinfSectionW( HWND hwnd, HINSTANCE handle, LPCWSTR cmdline, INT show ) -{ - WCHAR *p, *path, section[MAX_PATH]; - void *callback_context; - UINT mode; - HINF hinf; - - TRACE("hwnd %p, handle %p, cmdline %s\n", hwnd, handle, debugstr_w(cmdline)); - - lstrcpynW( section, cmdline, sizeof(section)/sizeof(WCHAR) ); - - if (!(p = strchrW( section, ' ' ))) return; - *p++ = 0; - while (*p == ' ') p++; - mode = atoiW( p ); - - if (!(p = strchrW( p, ' ' ))) return; - path = p + 1; - while (*path == ' ') path++; - - hinf = SetupOpenInfFileW( path, NULL, INF_STYLE_WIN4, NULL ); - if (hinf == INVALID_HANDLE_VALUE) return; - - callback_context = SetupInitDefaultQueueCallback( hwnd ); - SetupInstallFromInfSectionW( hwnd, hinf, section, SPINST_ALL, NULL, NULL, SP_COPY_NEWER, - SetupDefaultQueueCallbackW, callback_context, - NULL, NULL ); - SetupTermDefaultQueueCallback( callback_context ); - SetupCloseInfFile( hinf ); - - /* FIXME: should check the mode and maybe reboot */ - /* there isn't much point in doing that since we */ - /* don't yet handle deferred file copies anyway. */ -} - - -/*********************************************************************** - * InstallHinfSectionA (SETUPAPI.@) - */ -void WINAPI InstallHinfSectionA( HWND hwnd, HINSTANCE handle, LPCSTR cmdline, INT show ) -{ - UNICODE_STRING cmdlineW; - - if (RtlCreateUnicodeStringFromAsciiz( &cmdlineW, cmdline )) - { - InstallHinfSectionW( hwnd, handle, cmdlineW.Buffer, show ); - RtlFreeUnicodeString( &cmdlineW ); - } -} +/* + * Setupapi install routines + * + * Copyright 2002 Alexandre Julliard for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winternl.h" +#include "winerror.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "setupapi.h" +#include "setupapi_private.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +/* info passed to callback functions dealing with files */ +struct files_callback_info +{ + HSPFILEQ queue; + PCWSTR src_root; + UINT copy_flags; + HINF layout; +}; + +/* info passed to callback functions dealing with the registry */ +struct registry_callback_info +{ + HKEY default_root; + BOOL delete; +}; + +/* info passed to callback functions dealing with registering dlls */ +struct register_dll_info +{ + PSP_FILE_CALLBACK_W callback; + PVOID callback_context; + BOOL unregister; +}; + +typedef BOOL (*iterate_fields_func)( HINF hinf, PCWSTR field, void *arg ); + +/* Unicode constants */ +static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0}; +static const WCHAR DelFiles[] = {'D','e','l','F','i','l','e','s',0}; +static const WCHAR RenFiles[] = {'R','e','n','F','i','l','e','s',0}; +static const WCHAR Ini2Reg[] = {'I','n','i','2','R','e','g',0}; +static const WCHAR LogConf[] = {'L','o','g','C','o','n','f',0}; +static const WCHAR AddReg[] = {'A','d','d','R','e','g',0}; +static const WCHAR DelReg[] = {'D','e','l','R','e','g',0}; +static const WCHAR BitReg[] = {'B','i','t','R','e','g',0}; +static const WCHAR UpdateInis[] = {'U','p','d','a','t','e','I','n','i','s',0}; +static const WCHAR CopyINF[] = {'C','o','p','y','I','N','F',0}; +static const WCHAR UpdateIniFields[] = {'U','p','d','a','t','e','I','n','i','F','i','e','l','d','s',0}; +static const WCHAR RegisterDlls[] = {'R','e','g','i','s','t','e','r','D','l','l','s',0}; +static const WCHAR UnregisterDlls[] = {'U','n','r','e','g','i','s','t','e','r','D','l','l','s',0}; +static const WCHAR ProfileItems[] = {'P','r','o','f','i','l','e','I','t','e','m','s',0}; + + +/*********************************************************************** + * get_field_string + * + * Retrieve the contents of a field, dynamically growing the buffer if necessary. + */ +static WCHAR *get_field_string( INFCONTEXT *context, DWORD index, WCHAR *buffer, + WCHAR *static_buffer, DWORD *size ) +{ + DWORD required; + + if (SetupGetStringFieldW( context, index, buffer, *size, &required )) return buffer; + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + /* now grow the buffer */ + if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer ); + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, required*sizeof(WCHAR) ))) return NULL; + *size = required; + if (SetupGetStringFieldW( context, index, buffer, *size, &required )) return buffer; + } + if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer ); + return NULL; +} + + +/*********************************************************************** + * copy_files_callback + * + * Called once for each CopyFiles entry in a given section. + */ +static BOOL copy_files_callback( HINF hinf, PCWSTR field, void *arg ) +{ + struct files_callback_info *info = arg; + + if (field[0] == '@') /* special case: copy single file */ + SetupQueueDefaultCopyW( info->queue, info->layout, info->src_root, NULL, field, info->copy_flags ); + else + SetupQueueCopySectionW( info->queue, info->src_root, info->layout, hinf, field, info->copy_flags ); + return TRUE; +} + + +/*********************************************************************** + * delete_files_callback + * + * Called once for each DelFiles entry in a given section. + */ +static BOOL delete_files_callback( HINF hinf, PCWSTR field, void *arg ) +{ + struct files_callback_info *info = arg; + SetupQueueDeleteSectionW( info->queue, hinf, 0, field ); + return TRUE; +} + + +/*********************************************************************** + * rename_files_callback + * + * Called once for each RenFiles entry in a given section. + */ +static BOOL rename_files_callback( HINF hinf, PCWSTR field, void *arg ) +{ + struct files_callback_info *info = arg; + SetupQueueRenameSectionW( info->queue, hinf, 0, field ); + return TRUE; +} + + +/*********************************************************************** + * get_root_key + * + * Retrieve the registry root key from its name. + */ +static HKEY get_root_key( const WCHAR *name, HKEY def_root ) +{ + static const WCHAR HKCR[] = {'H','K','C','R',0}; + static const WCHAR HKCU[] = {'H','K','C','U',0}; + static const WCHAR HKLM[] = {'H','K','L','M',0}; + static const WCHAR HKU[] = {'H','K','U',0}; + static const WCHAR HKR[] = {'H','K','R',0}; + + if (!strcmpiW( name, HKCR )) return HKEY_CLASSES_ROOT; + if (!strcmpiW( name, HKCU )) return HKEY_CURRENT_USER; + if (!strcmpiW( name, HKLM )) return HKEY_LOCAL_MACHINE; + if (!strcmpiW( name, HKU )) return HKEY_USERS; + if (!strcmpiW( name, HKR )) return def_root; + return 0; +} + + +/*********************************************************************** + * append_multi_sz_value + * + * Append a multisz string to a multisz registry value. + */ +static void append_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *strings, + DWORD str_size ) +{ + DWORD size, type, total; + WCHAR *buffer, *p; + + if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return; + if (type != REG_MULTI_SZ) return; + + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size + str_size) * sizeof(WCHAR) ))) return; + if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done; + + /* compare each string against all the existing ones */ + total = size; + while (*strings) + { + int len = strlenW(strings) + 1; + + for (p = buffer; *p; p += strlenW(p) + 1) + if (!strcmpiW( p, strings )) break; + + if (!*p) /* not found, need to append it */ + { + memcpy( p, strings, len * sizeof(WCHAR) ); + p[len] = 0; + total += len; + } + strings += len; + } + if (total != size) + { + TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer) ); + RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, (BYTE *)buffer, total ); + } + done: + HeapFree( GetProcessHeap(), 0, buffer ); +} + + +/*********************************************************************** + * delete_multi_sz_value + * + * Remove a string from a multisz registry value. + */ +static void delete_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *string ) +{ + DWORD size, type; + WCHAR *buffer, *src, *dst; + + if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return; + if (type != REG_MULTI_SZ) return; + /* allocate double the size, one for value before and one for after */ + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size * 2 * sizeof(WCHAR) ))) return; + if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done; + src = buffer; + dst = buffer + size; + while (*src) + { + int len = strlenW(src) + 1; + if (strcmpiW( src, string )) + { + memcpy( dst, src, len * sizeof(WCHAR) ); + dst += len; + } + src += len; + } + *dst++ = 0; + if (dst != buffer + 2*size) /* did we remove something? */ + { + TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer + size) ); + RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, + (BYTE *)(buffer + size), dst - (buffer + size) ); + } + done: + HeapFree( GetProcessHeap(), 0, buffer ); +} + + +/*********************************************************************** + * do_reg_operation + * + * Perform an add/delete registry operation depending on the flags. + */ +static BOOL do_reg_operation( HKEY hkey, const WCHAR *value, INFCONTEXT *context, INT flags ) +{ + DWORD type, size; + + if (flags & (FLG_ADDREG_DELREG_BIT | FLG_ADDREG_DELVAL)) /* deletion */ + { + if (*value && !(flags & FLG_DELREG_KEYONLY_COMMON)) + { + if ((flags & FLG_DELREG_MULTI_SZ_DELSTRING) == FLG_DELREG_MULTI_SZ_DELSTRING) + { + WCHAR *str; + + if (!SetupGetStringFieldW( context, 5, NULL, 0, &size ) || !size) return TRUE; + if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE; + SetupGetStringFieldW( context, 5, str, size, NULL ); + delete_multi_sz_value( hkey, value, str ); + HeapFree( GetProcessHeap(), 0, str ); + } + else RegDeleteValueW( hkey, value ); + } + else RegDeleteKeyW( hkey, NULL ); + return TRUE; + } + + if (flags & (FLG_ADDREG_KEYONLY|FLG_ADDREG_KEYONLY_COMMON)) return TRUE; + + if (flags & (FLG_ADDREG_NOCLOBBER|FLG_ADDREG_OVERWRITEONLY)) + { + BOOL exists = !RegQueryValueExW( hkey, value, NULL, NULL, NULL, NULL ); + if (exists && (flags & FLG_ADDREG_NOCLOBBER)) return TRUE; + if (!exists & (flags & FLG_ADDREG_OVERWRITEONLY)) return TRUE; + } + + switch(flags & FLG_ADDREG_TYPE_MASK) + { + case FLG_ADDREG_TYPE_SZ: type = REG_SZ; break; + case FLG_ADDREG_TYPE_MULTI_SZ: type = REG_MULTI_SZ; break; + case FLG_ADDREG_TYPE_EXPAND_SZ: type = REG_EXPAND_SZ; break; + case FLG_ADDREG_TYPE_BINARY: type = REG_BINARY; break; + case FLG_ADDREG_TYPE_DWORD: type = REG_DWORD; break; + case FLG_ADDREG_TYPE_NONE: type = REG_NONE; break; + default: type = flags >> 16; break; + } + + if (!(flags & FLG_ADDREG_BINVALUETYPE) || + (type == REG_DWORD && SetupGetFieldCount(context) == 5)) + { + static const WCHAR empty; + WCHAR *str = NULL; + + if (type == REG_MULTI_SZ) + { + if (!SetupGetMultiSzFieldW( context, 5, NULL, 0, &size )) size = 0; + if (size) + { + if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE; + SetupGetMultiSzFieldW( context, 5, str, size, NULL ); + } + if (flags & FLG_ADDREG_APPEND) + { + if (!str) return TRUE; + append_multi_sz_value( hkey, value, str, size ); + HeapFree( GetProcessHeap(), 0, str ); + return TRUE; + } + /* else fall through to normal string handling */ + } + else + { + if (!SetupGetStringFieldW( context, 5, NULL, 0, &size )) size = 0; + if (size) + { + if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE; + SetupGetStringFieldW( context, 5, str, size, NULL ); + } + } + + if (type == REG_DWORD) + { + DWORD dw = str ? strtoulW( str, NULL, 16 ) : 0; + TRACE( "setting dword %s to %lx\n", debugstr_w(value), dw ); + RegSetValueExW( hkey, value, 0, type, (BYTE *)&dw, sizeof(dw) ); + } + else + { + TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(str) ); + if (str) RegSetValueExW( hkey, value, 0, type, (BYTE *)str, size * sizeof(WCHAR) ); + else RegSetValueExW( hkey, value, 0, type, (const BYTE *)&empty, sizeof(WCHAR) ); + } + HeapFree( GetProcessHeap(), 0, str ); + return TRUE; + } + else /* get the binary data */ + { + BYTE *data = NULL; + + if (!SetupGetBinaryField( context, 5, NULL, 0, &size )) size = 0; + if (size) + { + if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE; + TRACE( "setting binary data %s len %ld\n", debugstr_w(value), size ); + SetupGetBinaryField( context, 5, data, size, NULL ); + } + RegSetValueExW( hkey, value, 0, type, data, size ); + HeapFree( GetProcessHeap(), 0, data ); + return TRUE; + } +} + + +/*********************************************************************** + * registry_callback + * + * Called once for each AddReg and DelReg entry in a given section. + */ +static BOOL registry_callback( HINF hinf, PCWSTR field, void *arg ) +{ + struct registry_callback_info *info = arg; + INFCONTEXT context; + HKEY root_key, hkey; + + BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context ); + + for (; ok; ok = SetupFindNextLine( &context, &context )) + { + WCHAR buffer[MAX_INF_STRING_LENGTH]; + INT flags; + + /* get root */ + if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) + continue; + if (!(root_key = get_root_key( buffer, info->default_root ))) + continue; + + /* get key */ + if (!SetupGetStringFieldW( &context, 2, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) + *buffer = 0; + + /* get flags */ + if (!SetupGetIntField( &context, 4, &flags )) flags = 0; + + if (!info->delete) + { + if (flags & FLG_ADDREG_DELREG_BIT) continue; /* ignore this entry */ + } + else + { + if (!flags) flags = FLG_ADDREG_DELREG_BIT; + else if (!(flags & FLG_ADDREG_DELREG_BIT)) continue; /* ignore this entry */ + } + + if (info->delete || (flags & FLG_ADDREG_OVERWRITEONLY)) + { + if (RegOpenKeyW( root_key, buffer, &hkey )) continue; /* ignore if it doesn't exist */ + } + else if (RegCreateKeyW( root_key, buffer, &hkey )) + { + ERR( "could not create key %p %s\n", root_key, debugstr_w(buffer) ); + continue; + } + TRACE( "key %p %s\n", root_key, debugstr_w(buffer) ); + + /* get value name */ + if (!SetupGetStringFieldW( &context, 3, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) + *buffer = 0; + + /* and now do it */ + if (!do_reg_operation( hkey, buffer, &context, flags )) + { + RegCloseKey( hkey ); + return FALSE; + } + RegCloseKey( hkey ); + } + return TRUE; +} + + +/*********************************************************************** + * do_register_dll + * + * Register or unregister a dll. + */ +static BOOL do_register_dll( const struct register_dll_info *info, const WCHAR *path, + INT flags, INT timeout, const WCHAR *args ) +{ + HMODULE module; + HRESULT res; + SP_REGISTER_CONTROL_STATUSW status; + + status.cbSize = sizeof(status); + status.FileName = path; + status.FailureCode = SPREG_SUCCESS; + status.Win32Error = ERROR_SUCCESS; + + if (info->callback) + { + switch(info->callback( info->callback_context, SPFILENOTIFY_STARTREGISTRATION, + (UINT_PTR)&status, !info->unregister )) + { + case FILEOP_ABORT: + SetLastError( ERROR_OPERATION_ABORTED ); + return FALSE; + case FILEOP_SKIP: + return TRUE; + case FILEOP_DOIT: + break; + } + } + + if (!(module = LoadLibraryExW( path, 0, LOAD_WITH_ALTERED_SEARCH_PATH ))) + { + WARN( "could not load %s\n", debugstr_w(path) ); + status.FailureCode = SPREG_LOADLIBRARY; + status.Win32Error = GetLastError(); + goto done; + } + + if (flags & FLG_REGSVR_DLLREGISTER) + { + const char *entry_point = info->unregister ? "DllUnregisterServer" : "DllRegisterServer"; + HRESULT (WINAPI *func)(void) = (void *)GetProcAddress( module, entry_point ); + + if (!func) + { + status.FailureCode = SPREG_GETPROCADDR; + status.Win32Error = GetLastError(); + goto done; + } + + TRACE( "calling %s in %s\n", entry_point, debugstr_w(path) ); + res = func(); + + if (FAILED(res)) + { + WARN( "calling %s in %s returned error %lx\n", entry_point, debugstr_w(path), res ); + status.FailureCode = SPREG_REGSVR; + status.Win32Error = res; + goto done; + } + } + + if (flags & FLG_REGSVR_DLLINSTALL) + { + HRESULT (WINAPI *func)(BOOL,LPCWSTR) = (void *)GetProcAddress( module, "DllInstall" ); + + if (!func) + { + status.FailureCode = SPREG_GETPROCADDR; + status.Win32Error = GetLastError(); + goto done; + } + + TRACE( "calling DllInstall(%d,%s) in %s\n", + !info->unregister, debugstr_w(args), debugstr_w(path) ); + res = func( !info->unregister, args ); + + if (FAILED(res)) + { + WARN( "calling DllInstall in %s returned error %lx\n", debugstr_w(path), res ); + status.FailureCode = SPREG_REGSVR; + status.Win32Error = res; + goto done; + } + } + +done: + if (module) FreeLibrary( module ); + if (info->callback) info->callback( info->callback_context, SPFILENOTIFY_ENDREGISTRATION, + (UINT_PTR)&status, !info->unregister ); + return TRUE; +} + + +/*********************************************************************** + * register_dlls_callback + * + * Called once for each RegisterDlls entry in a given section. + */ +static BOOL register_dlls_callback( HINF hinf, PCWSTR field, void *arg ) +{ + struct register_dll_info *info = arg; + INFCONTEXT context; + BOOL ret = TRUE; + BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context ); + + for (; ok; ok = SetupFindNextLine( &context, &context )) + { + WCHAR *path, *args, *p; + WCHAR buffer[MAX_INF_STRING_LENGTH]; + INT flags, timeout; + + /* get directory */ + if (!(path = PARSER_get_dest_dir( &context ))) continue; + + /* get dll name */ + if (!SetupGetStringFieldW( &context, 3, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) + goto done; + if (!(p = HeapReAlloc( GetProcessHeap(), 0, path, + (strlenW(path) + strlenW(buffer) + 2) * sizeof(WCHAR) ))) goto done; + path = p; + p += strlenW(p); + if (p == path || p[-1] != '\\') *p++ = '\\'; + strcpyW( p, buffer ); + + /* get flags */ + if (!SetupGetIntField( &context, 4, &flags )) flags = 0; + + /* get timeout */ + if (!SetupGetIntField( &context, 5, &timeout )) timeout = 60; + + /* get command line */ + args = NULL; + if (SetupGetStringFieldW( &context, 6, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) + args = buffer; + + ret = do_register_dll( info, path, flags, timeout, args ); + + done: + HeapFree( GetProcessHeap(), 0, path ); + if (!ret) break; + } + return ret; +} + +/*********************************************************************** + * update_ini_callback + * + * Called once for each UpdateInis entry in a given section. + */ +static BOOL update_ini_callback( HINF hinf, PCWSTR field, void *arg ) +{ + INFCONTEXT context; + + BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context ); + + for (; ok; ok = SetupFindNextLine( &context, &context )) + { + WCHAR buffer[MAX_INF_STRING_LENGTH]; + WCHAR filename[MAX_INF_STRING_LENGTH]; + WCHAR section[MAX_INF_STRING_LENGTH]; + WCHAR entry[MAX_INF_STRING_LENGTH]; + WCHAR string[MAX_INF_STRING_LENGTH]; + LPWSTR divider; + + if (!SetupGetStringFieldW( &context, 1, filename, + sizeof(filename)/sizeof(WCHAR), NULL )) + continue; + + if (!SetupGetStringFieldW( &context, 2, section, + sizeof(section)/sizeof(WCHAR), NULL )) + continue; + + if (!SetupGetStringFieldW( &context, 4, buffer, + sizeof(buffer)/sizeof(WCHAR), NULL )) + continue; + + divider = strchrW(buffer,'='); + if (divider) + { + *divider = 0; + strcpyW(entry,buffer); + divider++; + strcpyW(string,divider); + } + else + { + strcpyW(entry,buffer); + string[0]=0; + } + + TRACE("Writing %s = %s in %s of file %s\n",debugstr_w(entry), + debugstr_w(string),debugstr_w(section),debugstr_w(filename)); + WritePrivateProfileStringW(section,entry,string,filename); + + } + return TRUE; +} + +static BOOL update_ini_fields_callback( HINF hinf, PCWSTR field, void *arg ) +{ + FIXME( "should update ini fields %s\n", debugstr_w(field) ); + return TRUE; +} + +static BOOL ini2reg_callback( HINF hinf, PCWSTR field, void *arg ) +{ + FIXME( "should do ini2reg %s\n", debugstr_w(field) ); + return TRUE; +} + +static BOOL logconf_callback( HINF hinf, PCWSTR field, void *arg ) +{ + FIXME( "should do logconf %s\n", debugstr_w(field) ); + return TRUE; +} + +static BOOL bitreg_callback( HINF hinf, PCWSTR field, void *arg ) +{ + FIXME( "should do bitreg %s\n", debugstr_w(field) ); + return TRUE; +} + +static BOOL profile_items_callback( HINF hinf, PCWSTR field, void *arg ) +{ + FIXME( "should do profile items %s\n", debugstr_w(field) ); + return TRUE; +} + +static BOOL copy_inf_callback( HINF hinf, PCWSTR field, void *arg ) +{ + FIXME( "should do copy inf %s\n", debugstr_w(field) ); + return TRUE; +} + + +/*********************************************************************** + * iterate_section_fields + * + * Iterate over all fields of a certain key of a certain section + */ +static BOOL iterate_section_fields( HINF hinf, PCWSTR section, PCWSTR key, + iterate_fields_func callback, void *arg ) +{ + WCHAR static_buffer[200]; + WCHAR *buffer = static_buffer; + DWORD size = sizeof(static_buffer)/sizeof(WCHAR); + INFCONTEXT context; + BOOL ret = FALSE; + + BOOL ok = SetupFindFirstLineW( hinf, section, key, &context ); + while (ok) + { + UINT i, count = SetupGetFieldCount( &context ); + for (i = 1; i <= count; i++) + { + if (!(buffer = get_field_string( &context, i, buffer, static_buffer, &size ))) + goto done; + if (!callback( hinf, buffer, arg )) + { + WARN("callback failed for %s %s err %ld\n", + debugstr_w(section), debugstr_w(buffer), GetLastError() ); + goto done; + } + } + ok = SetupFindNextMatchLineW( &context, key, &context ); + } + ret = TRUE; + done: + if (buffer && buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer ); + return ret; +} + + +/*********************************************************************** + * SetupInstallFilesFromInfSectionA (SETUPAPI.@) + */ +BOOL WINAPI SetupInstallFilesFromInfSectionA( HINF hinf, HINF hlayout, HSPFILEQ queue, + PCSTR section, PCSTR src_root, UINT flags ) +{ + UNICODE_STRING sectionW; + BOOL ret = FALSE; + + if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + if (!src_root) + ret = SetupInstallFilesFromInfSectionW( hinf, hlayout, queue, sectionW.Buffer, + NULL, flags ); + else + { + UNICODE_STRING srcW; + if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root )) + { + ret = SetupInstallFilesFromInfSectionW( hinf, hlayout, queue, sectionW.Buffer, + srcW.Buffer, flags ); + RtlFreeUnicodeString( &srcW ); + } + else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + } + RtlFreeUnicodeString( §ionW ); + return ret; +} + + +/*********************************************************************** + * SetupInstallFilesFromInfSectionW (SETUPAPI.@) + */ +BOOL WINAPI SetupInstallFilesFromInfSectionW( HINF hinf, HINF hlayout, HSPFILEQ queue, + PCWSTR section, PCWSTR src_root, UINT flags ) +{ + struct files_callback_info info; + + info.queue = queue; + info.src_root = src_root; + info.copy_flags = flags; + info.layout = hlayout; + return iterate_section_fields( hinf, section, CopyFiles, copy_files_callback, &info ); +} + + +/*********************************************************************** + * SetupInstallFromInfSectionA (SETUPAPI.@) + */ +BOOL WINAPI SetupInstallFromInfSectionA( HWND owner, HINF hinf, PCSTR section, UINT flags, + HKEY key_root, PCSTR src_root, UINT copy_flags, + PSP_FILE_CALLBACK_A callback, PVOID context, + HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data ) +{ + UNICODE_STRING sectionW, src_rootW; + struct callback_WtoA_context ctx; + BOOL ret = FALSE; + + src_rootW.Buffer = NULL; + if (src_root && !RtlCreateUnicodeStringFromAsciiz( &src_rootW, src_root )) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) + { + ctx.orig_context = context; + ctx.orig_handler = callback; + ret = SetupInstallFromInfSectionW( owner, hinf, sectionW.Buffer, flags, key_root, + src_rootW.Buffer, copy_flags, QUEUE_callback_WtoA, + &ctx, devinfo, devinfo_data ); + RtlFreeUnicodeString( §ionW ); + } + else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + + RtlFreeUnicodeString( &src_rootW ); + return ret; +} + + +/*********************************************************************** + * SetupInstallFromInfSectionW (SETUPAPI.@) + */ +BOOL WINAPI SetupInstallFromInfSectionW( HWND owner, HINF hinf, PCWSTR section, UINT flags, + HKEY key_root, PCWSTR src_root, UINT copy_flags, + PSP_FILE_CALLBACK_W callback, PVOID context, + HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data ) +{ + if (flags & SPINST_FILES) + { + struct files_callback_info info; + HSPFILEQ queue; + BOOL ret; + + if (!(queue = SetupOpenFileQueue())) return FALSE; + info.queue = queue; + info.src_root = src_root; + info.copy_flags = copy_flags; + info.layout = hinf; + ret = (iterate_section_fields( hinf, section, CopyFiles, copy_files_callback, &info ) && + iterate_section_fields( hinf, section, DelFiles, delete_files_callback, &info ) && + iterate_section_fields( hinf, section, RenFiles, rename_files_callback, &info ) && + SetupCommitFileQueueW( owner, queue, callback, context )); + SetupCloseFileQueue( queue ); + if (!ret) return FALSE; + } + if (flags & SPINST_INIFILES) + { + if (!iterate_section_fields( hinf, section, UpdateInis, update_ini_callback, NULL ) || + !iterate_section_fields( hinf, section, UpdateIniFields, + update_ini_fields_callback, NULL )) + return FALSE; + } + if (flags & SPINST_INI2REG) + { + if (!iterate_section_fields( hinf, section, Ini2Reg, ini2reg_callback, NULL )) + return FALSE; + } + if (flags & SPINST_LOGCONFIG) + { + if (!iterate_section_fields( hinf, section, LogConf, logconf_callback, NULL )) + return FALSE; + } + if (flags & SPINST_REGSVR) + { + struct register_dll_info info; + + info.unregister = FALSE; + if (flags & SPINST_REGISTERCALLBACKAWARE) + { + info.callback = callback; + info.callback_context = context; + } + else info.callback = NULL; + + if (!iterate_section_fields( hinf, section, RegisterDlls, register_dlls_callback, &info )) + return FALSE; + } + if (flags & SPINST_UNREGSVR) + { + struct register_dll_info info; + + info.unregister = TRUE; + if (flags & SPINST_REGISTERCALLBACKAWARE) + { + info.callback = callback; + info.callback_context = context; + } + else info.callback = NULL; + + if (!iterate_section_fields( hinf, section, UnregisterDlls, register_dlls_callback, &info )) + return FALSE; + } + if (flags & SPINST_REGISTRY) + { + struct registry_callback_info info; + + info.default_root = key_root; + info.delete = TRUE; + if (!iterate_section_fields( hinf, section, DelReg, registry_callback, &info )) + return FALSE; + info.delete = FALSE; + if (!iterate_section_fields( hinf, section, AddReg, registry_callback, &info )) + return FALSE; + } + if (flags & SPINST_BITREG) + { + if (!iterate_section_fields( hinf, section, BitReg, bitreg_callback, NULL )) + return FALSE; + } + if (flags & SPINST_PROFILEITEMS) + { + if (!iterate_section_fields( hinf, section, ProfileItems, profile_items_callback, NULL )) + return FALSE; + } + if (flags & SPINST_COPYINF) + { + if (!iterate_section_fields( hinf, section, CopyINF, copy_inf_callback, NULL )) + return FALSE; + } + + return TRUE; +} + + +/*********************************************************************** + * InstallHinfSectionW (SETUPAPI.@) + * + * NOTE: 'cmdline' is
from + * RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection
+ */ +void WINAPI InstallHinfSectionW( HWND hwnd, HINSTANCE handle, LPCWSTR cmdline, INT show ) +{ + WCHAR *p, *path, section[MAX_PATH]; + void *callback_context; + UINT mode; + HINF hinf; + + TRACE("hwnd %p, handle %p, cmdline %s\n", hwnd, handle, debugstr_w(cmdline)); + + lstrcpynW( section, cmdline, sizeof(section)/sizeof(WCHAR) ); + + if (!(p = strchrW( section, ' ' ))) return; + *p++ = 0; + while (*p == ' ') p++; + mode = atoiW( p ); + + if (!(p = strchrW( p, ' ' ))) return; + path = p + 1; + while (*path == ' ') path++; + + hinf = SetupOpenInfFileW( path, NULL, INF_STYLE_WIN4, NULL ); + if (hinf == INVALID_HANDLE_VALUE) return; + + callback_context = SetupInitDefaultQueueCallback( hwnd ); + SetupInstallFromInfSectionW( hwnd, hinf, section, SPINST_ALL, NULL, NULL, SP_COPY_NEWER, + SetupDefaultQueueCallbackW, callback_context, + NULL, NULL ); + SetupTermDefaultQueueCallback( callback_context ); + SetupCloseInfFile( hinf ); + + /* FIXME: should check the mode and maybe reboot */ + /* there isn't much point in doing that since we */ + /* don't yet handle deferred file copies anyway. */ +} + + +/*********************************************************************** + * InstallHinfSectionA (SETUPAPI.@) + */ +void WINAPI InstallHinfSectionA( HWND hwnd, HINSTANCE handle, LPCSTR cmdline, INT show ) +{ + UNICODE_STRING cmdlineW; + + if (RtlCreateUnicodeStringFromAsciiz( &cmdlineW, cmdline )) + { + InstallHinfSectionW( hwnd, handle, cmdlineW.Buffer, show ); + RtlFreeUnicodeString( &cmdlineW ); + } +} diff --git a/reactos/lib/setupapi/misc.c b/reactos/lib/setupapi/misc.c index e5b9b542b10..fe9189b8cd6 100644 --- a/reactos/lib/setupapi/misc.c +++ b/reactos/lib/setupapi/misc.c @@ -1,1046 +1,1046 @@ -/* - * Setupapi miscellaneous functions - * - * Copyright 2005 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winreg.h" -#include "setupapi.h" - -#include "wine/unicode.h" -#include "wine/debug.h" - -#include "setupapi_private.h" - - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - - -/************************************************************************** - * MyFree [SETUPAPI.@] - * - * Frees an allocated memory block from the process heap. - * - * PARAMS - * lpMem [I] pointer to memory block which will be freed - * - * RETURNS - * None - */ -VOID WINAPI MyFree(LPVOID lpMem) -{ - TRACE("%p\n", lpMem); - HeapFree(GetProcessHeap(), 0, lpMem); -} - - -/************************************************************************** - * MyMalloc [SETUPAPI.@] - * - * Allocates memory block from the process heap. - * - * PARAMS - * dwSize [I] size of the allocated memory block - * - * RETURNS - * Success: pointer to allocated memory block - * Failure: NULL - */ -LPVOID WINAPI MyMalloc(DWORD dwSize) -{ - TRACE("%lu\n", dwSize); - return HeapAlloc(GetProcessHeap(), 0, dwSize); -} - - -/************************************************************************** - * MyRealloc [SETUPAPI.@] - * - * Changes the size of an allocated memory block or allocates a memory - * block from the process heap. - * - * PARAMS - * lpSrc [I] pointer to memory block which will be resized - * dwSize [I] new size of the memory block - * - * RETURNS - * Success: pointer to the resized memory block - * Failure: NULL - * - * NOTES - * If lpSrc is a NULL-pointer, then MyRealloc allocates a memory - * block like MyMalloc. - */ -LPVOID WINAPI MyRealloc(LPVOID lpSrc, DWORD dwSize) -{ - TRACE("%p %lu\n", lpSrc, dwSize); - - if (lpSrc == NULL) - return HeapAlloc(GetProcessHeap(), 0, dwSize); - - return HeapReAlloc(GetProcessHeap(), 0, lpSrc, dwSize); -} - - -/************************************************************************** - * DuplicateString [SETUPAPI.@] - * - * Duplicates a unicode string. - * - * PARAMS - * lpSrc [I] pointer to the unicode string that will be duplicated - * - * RETURNS - * Success: pointer to the duplicated unicode string - * Failure: NULL - * - * NOTES - * Call MyFree() to release the duplicated string. - */ -LPWSTR WINAPI DuplicateString(LPCWSTR lpSrc) -{ - LPWSTR lpDst; - - TRACE("%s\n", debugstr_w(lpSrc)); - - lpDst = MyMalloc((lstrlenW(lpSrc) + 1) * sizeof(WCHAR)); - if (lpDst == NULL) - return NULL; - - strcpyW(lpDst, lpSrc); - - return lpDst; -} - - -/************************************************************************** - * QueryRegistryValue [SETUPAPI.@] - * - * Retrieves value data from the registry and allocates memory for the - * value data. - * - * PARAMS - * hKey [I] Handle of the key to query - * lpValueName [I] Name of value under hkey to query - * lpData [O] Destination for the values contents, - * lpType [O] Destination for the value type - * lpcbData [O] Destination for the size of data - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: Otherwise - * - * NOTES - * Use MyFree to release the lpData buffer. - */ -LONG WINAPI QueryRegistryValue(HKEY hKey, - LPCWSTR lpValueName, - LPBYTE *lpData, - LPDWORD lpType, - LPDWORD lpcbData) -{ - LONG lError; - - TRACE("%lx %s %p %p %p\n", - hKey, debugstr_w(lpValueName), lpData, lpType, lpcbData); - - /* Get required buffer size */ - *lpcbData = 0; - lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, NULL, lpcbData); - if (lError != ERROR_SUCCESS) - return lError; - - /* Allocate buffer */ - *lpData = MyMalloc(*lpcbData); - if (*lpData == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - /* Query registry value */ - lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, *lpData, lpcbData); - if (lError != ERROR_SUCCESS) - MyFree(*lpData); - - return lError; -} - - -/************************************************************************** - * IsUserAdmin [SETUPAPI.@] - * - * Checks whether the current user is a member of the Administrators group. - * - * PARAMS - * None - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI IsUserAdmin(VOID) -{ - SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY}; - HANDLE hToken; - DWORD dwSize; - PTOKEN_GROUPS lpGroups; - PSID lpSid; - DWORD i; - BOOL bResult = FALSE; - - TRACE("\n"); - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - { - return FALSE; - } - - if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) - { - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - { - CloseHandle(hToken); - return FALSE; - } - } - - lpGroups = MyMalloc(dwSize); - if (lpGroups == NULL) - { - CloseHandle(hToken); - return FALSE; - } - - if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize)) - { - MyFree(lpGroups); - CloseHandle(hToken); - return FALSE; - } - - CloseHandle(hToken); - - if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, - &lpSid)) - { - MyFree(lpGroups); - return FALSE; - } - - for (i = 0; i < lpGroups->GroupCount; i++) - { - if (EqualSid(lpSid, &lpGroups->Groups[i].Sid)) - { - bResult = TRUE; - break; - } - } - - FreeSid(lpSid); - MyFree(lpGroups); - - return bResult; -} - - -/************************************************************************** - * MultiByteToUnicode [SETUPAPI.@] - * - * Converts a multi-byte string to a Unicode string. - * - * PARAMS - * lpMultiByteStr [I] Multi-byte string to be converted - * uCodePage [I] Code page - * - * RETURNS - * Success: pointer to the converted Unicode string - * Failure: NULL - * - * NOTE - * Use MyFree to release the returned Unicode string. - */ -LPWSTR WINAPI MultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage) -{ - LPWSTR lpUnicodeStr; - int nLength; - - TRACE("%s %lu\n", debugstr_a(lpMultiByteStr), uCodePage); - - nLength = MultiByteToWideChar(uCodePage, 0, lpMultiByteStr, - -1, NULL, 0); - if (nLength == 0) - return NULL; - - lpUnicodeStr = MyMalloc(nLength * sizeof(WCHAR)); - if (lpUnicodeStr == NULL) - return NULL; - - if (!MultiByteToWideChar(uCodePage, 0, lpMultiByteStr, - nLength, lpUnicodeStr, nLength)) - { - MyFree(lpUnicodeStr); - return NULL; - } - - return lpUnicodeStr; -} - - -/************************************************************************** - * UnicodeToMultiByte [SETUPAPI.@] - * - * Converts a Unicode string to a multi-byte string. - * - * PARAMS - * lpUnicodeStr [I] Unicode string to be converted - * uCodePage [I] Code page - * - * RETURNS - * Success: pointer to the converted multi-byte string - * Failure: NULL - * - * NOTE - * Use MyFree to release the returned multi-byte string. - */ -LPSTR WINAPI UnicodeToMultiByte(LPCWSTR lpUnicodeStr, UINT uCodePage) -{ - LPSTR lpMultiByteStr; - int nLength; - - TRACE("%s %lu\n", debugstr_w(lpUnicodeStr), uCodePage); - - nLength = WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1, - NULL, 0, NULL, NULL); - if (nLength == 0) - return NULL; - - lpMultiByteStr = MyMalloc(nLength); - if (lpMultiByteStr == NULL) - return NULL; - - if (!WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1, - lpMultiByteStr, nLength, NULL, NULL)) - { - MyFree(lpMultiByteStr); - return NULL; - } - - return lpMultiByteStr; -} - - -/************************************************************************** - * DoesUserHavePrivilege [SETUPAPI.@] - * - * Check whether the current user has got a given privilege. - * - * PARAMS - * lpPrivilegeName [I] Name of the privilege to be checked - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DoesUserHavePrivilege(LPCWSTR lpPrivilegeName) -{ - HANDLE hToken; - DWORD dwSize; - PTOKEN_PRIVILEGES lpPrivileges; - LUID PrivilegeLuid; - DWORD i; - BOOL bResult = FALSE; - - TRACE("%s\n", debugstr_w(lpPrivilegeName)); - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - return FALSE; - - if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) - { - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - { - CloseHandle(hToken); - return FALSE; - } - } - - lpPrivileges = MyMalloc(dwSize); - if (lpPrivileges == NULL) - { - CloseHandle(hToken); - return FALSE; - } - - if (!GetTokenInformation(hToken, TokenPrivileges, lpPrivileges, dwSize, &dwSize)) - { - MyFree(lpPrivileges); - CloseHandle(hToken); - return FALSE; - } - - CloseHandle(hToken); - - if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &PrivilegeLuid)) - { - MyFree(lpPrivileges); - return FALSE; - } - - for (i = 0; i < lpPrivileges->PrivilegeCount; i++) - { - if (lpPrivileges->Privileges[i].Luid.HighPart == PrivilegeLuid.HighPart && - lpPrivileges->Privileges[i].Luid.LowPart == PrivilegeLuid.LowPart) - { - bResult = TRUE; - } - } - - MyFree(lpPrivileges); - - return bResult; -} - - -/************************************************************************** - * EnablePrivilege [SETUPAPI.@] - * - * Enables or disables one of the current users privileges. - * - * PARAMS - * lpPrivilegeName [I] Name of the privilege to be changed - * bEnable [I] TRUE: Enables the privilege - * FALSE: Disables the privilege - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI EnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable) -{ - TOKEN_PRIVILEGES Privileges; - HANDLE hToken; - BOOL bResult; - - TRACE("%s %s\n", debugstr_w(lpPrivilegeName), bEnable ? "TRUE" : "FALSE"); - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - return FALSE; - - Privileges.PrivilegeCount = 1; - Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0; - - if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, - &Privileges.Privileges[0].Luid)) - { - CloseHandle(hToken); - return FALSE; - } - - bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL); - - CloseHandle(hToken); - - return bResult; -} - - -/************************************************************************** - * DelayedMove [SETUPAPI.@] - * - * Moves a file upon the next reboot. - * - * PARAMS - * lpExistingFileName [I] Current file name - * lpNewFileName [I] New file name - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName) -{ - if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT) - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - - return MoveFileExW(lpExistingFileName, lpNewFileName, - MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT); -} - - -/************************************************************************** - * FileExists [SETUPAPI.@] - * - * Checks whether a file exists. - * - * PARAMS - * lpFileName [I] Name of the file to check - * lpNewFileName [O] Optional information about the existing file - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData) -{ - WIN32_FIND_DATAW FindData; - HANDLE hFind; - UINT uErrorMode; - DWORD dwError; - - uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); - - hFind = FindFirstFileW(lpFileName, &FindData); - if (hFind == INVALID_HANDLE_VALUE) - { - dwError = GetLastError(); - SetErrorMode(uErrorMode); - SetLastError(dwError); - return FALSE; - } - - FindClose(hFind); - - if (lpFileFindData) - memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW)); - - SetErrorMode(uErrorMode); - - return TRUE; -} - - -/************************************************************************** - * CaptureStringArg [SETUPAPI.@] - * - * Captures a UNICODE string. - * - * PARAMS - * lpSrc [I] UNICODE string to be captured - * lpDst [O] Pointer to the captured UNICODE string - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: ERROR_INVALID_PARAMETER - * - * NOTE - * Call MyFree to release the captured UNICODE string. - */ -DWORD WINAPI CaptureStringArg(LPCWSTR pSrc, LPWSTR *pDst) -{ - if (pDst == NULL) - return ERROR_INVALID_PARAMETER; - - *pDst = DuplicateString(pSrc); - - return ERROR_SUCCESS; -} - - -/************************************************************************** - * CaptureAndConvertAnsiArg [SETUPAPI.@] - * - * Captures an ANSI string and converts it to a UNICODE string. - * - * PARAMS - * lpSrc [I] ANSI string to be captured - * lpDst [O] Pointer to the captured UNICODE string - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: ERROR_INVALID_PARAMETER - * - * NOTE - * Call MyFree to release the captured UNICODE string. - */ -DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst) -{ - if (pDst == NULL) - return ERROR_INVALID_PARAMETER; - - *pDst = MultiByteToUnicode(pSrc, CP_ACP); - - return ERROR_SUCCESS; -} - - -/************************************************************************** - * OpenAndMapFileForRead [SETUPAPI.@] - * - * Open and map a file to a buffer. - * - * PARAMS - * lpFileName [I] Name of the file to be opened - * lpSize [O] Pointer to the file size - * lpFile [0] Pointer to the file handle - * lpMapping [0] Pointer to the mapping handle - * lpBuffer [0] Pointer to the file buffer - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: Other - * - * NOTE - * Call UnmapAndCloseFile to release the file. - */ -DWORD WINAPI OpenAndMapFileForRead(LPCWSTR lpFileName, - LPDWORD lpSize, - LPHANDLE lpFile, - LPHANDLE lpMapping, - LPVOID *lpBuffer) -{ - DWORD dwError; - - TRACE("%s %p %p %p %p\n", - debugstr_w(lpFileName), lpSize, lpFile, lpMapping, lpBuffer); - - *lpFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, 0, NULL); - if (*lpFile == INVALID_HANDLE_VALUE) - return GetLastError(); - - *lpSize = GetFileSize(*lpFile, NULL); - if (*lpSize == INVALID_FILE_SIZE) - { - dwError = GetLastError(); - CloseHandle(*lpFile); - return dwError; - } - - *lpMapping = CreateFileMappingW(*lpFile, NULL, PAGE_READONLY, 0, - *lpSize, NULL); - if (*lpMapping == NULL) - { - dwError = GetLastError(); - CloseHandle(*lpFile); - return dwError; - } - - *lpBuffer = MapViewOfFile(*lpMapping, FILE_MAP_READ, 0, 0, *lpSize); - if (*lpBuffer == NULL) - { - dwError = GetLastError(); - CloseHandle(*lpMapping); - CloseHandle(*lpFile); - return dwError; - } - - return ERROR_SUCCESS; -} - - -/************************************************************************** - * UnmapAndCloseFile [SETUPAPI.@] - * - * Unmap and close a mapped file. - * - * PARAMS - * hFile [I] Handle to the file - * hMapping [I] Handle to the file mapping - * lpBuffer [I] Pointer to the file buffer - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI UnmapAndCloseFile(HANDLE hFile, HANDLE hMapping, LPVOID lpBuffer) -{ - TRACE("%x %x %p\n", - hFile, hMapping, lpBuffer); - - if (!UnmapViewOfFile(lpBuffer)) - return FALSE; - - if (!CloseHandle(hMapping)) - return FALSE; - - if (!CloseHandle(hFile)) - return FALSE; - - return TRUE; -} - - -/************************************************************************** - * StampFileSecurity [SETUPAPI.@] - * - * Assign a new security descriptor to the given file. - * - * PARAMS - * lpFileName [I] Name of the file - * pSecurityDescriptor [I] New security descriptor - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: other - */ -DWORD WINAPI StampFileSecurity(LPCWSTR lpFileName, PSECURITY_DESCRIPTOR pSecurityDescriptor) -{ - TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor); - - if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, - pSecurityDescriptor)) - return GetLastError(); - - return ERROR_SUCCESS; -} - - -/************************************************************************** - * TakeOwnershipOfFile [SETUPAPI.@] - * - * Takes the ownership of the given file. - * - * PARAMS - * lpFileName [I] Name of the file - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: other - */ -DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName) -{ - SECURITY_DESCRIPTOR SecDesc; - HANDLE hToken = NULL; - PTOKEN_OWNER pOwner = NULL; - DWORD dwError; - DWORD dwSize; - - TRACE("%s\n", debugstr_w(lpFileName)); - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - return GetLastError(); - - if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &dwSize)) - { - goto fail; - } - - pOwner = (PTOKEN_OWNER)MyMalloc(dwSize); - if (pOwner == NULL) - { - CloseHandle(hToken); - return ERROR_NOT_ENOUGH_MEMORY; - } - - if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize)) - { - goto fail; - } - - if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION)) - { - goto fail; - } - - if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE)) - { - goto fail; - } - - if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc)) - { - goto fail; - } - - MyFree(pOwner); - CloseHandle(hToken); - - return ERROR_SUCCESS; - -fail:; - dwError = GetLastError(); - - if (pOwner != NULL) - MyFree(pOwner); - - if (hToken != NULL) - CloseHandle(hToken); - - return dwError; -} - - -/************************************************************************** - * RetreiveFileSecurity [SETUPAPI.@] - * - * Retrieve the security descriptor that is associated with the given file. - * - * PARAMS - * lpFileName [I] Name of the file - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: other - */ -DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName, - PSECURITY_DESCRIPTOR *pSecurityDescriptor) -{ - PSECURITY_DESCRIPTOR SecDesc; - DWORD dwSize = 0x100; - DWORD dwError; - - TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor); - - SecDesc = (PSECURITY_DESCRIPTOR)MyMalloc(dwSize); - if (SecDesc == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, - SecDesc, dwSize, &dwSize)) - { - *pSecurityDescriptor = SecDesc; - return ERROR_SUCCESS; - } - - dwError = GetLastError(); - if (dwError != ERROR_INSUFFICIENT_BUFFER) - { - MyFree(SecDesc); - return dwError; - } - - SecDesc = (PSECURITY_DESCRIPTOR)MyRealloc(SecDesc, dwSize); - if (SecDesc == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, - SecDesc, dwSize, &dwSize)) - { - *pSecurityDescriptor = SecDesc; - return ERROR_SUCCESS; - } - - dwError = GetLastError(); - MyFree(SecDesc); - - return dwError; -} - - -/************************************************************************** - * AssertFail [SETUPAPI.@] - * - * Display an assertion message. - * - * PARAMS - * lpFile [I] File name - * uLine [I] Line number - * lpMessage [I] Assertion message - * - * RETURNS - * Nothing - */ -VOID WINAPI AssertFail(LPSTR lpFile, UINT uLine, LPSTR lpMessage) -{ - CHAR szModule[MAX_PATH]; - CHAR szBuffer[2048]; - LPSTR lpName; - LPSTR lpBuffer; - - TRACE("%s %u %s\n", lpFile, uLine, lpMessage); - - GetModuleFileNameA(hInstance, szModule, MAX_PATH); - lpName = strrchr(szModule, '\\'); - if (lpName != NULL) - lpName++; - else - lpName = szModule; - - wsprintfA(szBuffer, - "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?", - uLine, lpFile, lpMessage); - - if (MessageBoxA(NULL, szBuffer, lpName, MB_SETFOREGROUND | - MB_TASKMODAL | MB_ICONERROR | MB_YESNO) == IDYES) - DebugBreak(); -} - - -/************************************************************************** - * GetSetFileTimestamp [SETUPAPI.@] - * - * Gets or sets a files timestamp. - * - * PARAMS - * lpFileName [I] File name - * lpCreationTime [I/O] Creation time - * lpLastAccessTime [I/O] Last access time - * lpLastWriteTime [I/O] Last write time - * bSetFileTime [I] TRUE: Set file times - * FALSE: Get file times - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: other - */ -DWORD WINAPI GetSetFileTimestamp(LPCWSTR lpFileName, - LPFILETIME lpCreationTime, - LPFILETIME lpLastAccessTime, - LPFILETIME lpLastWriteTime, - BOOLEAN bSetFileTime) -{ - HANDLE hFile; - BOOLEAN bRet; - DWORD dwError = ERROR_SUCCESS; - - TRACE("%s %p %p %p %x\n", debugstr_w(lpFileName), lpCreationTime, - lpLastAccessTime, lpLastWriteTime, bSetFileTime); - - hFile = CreateFileW(lpFileName, - bSetFileTime ? GENERIC_WRITE : GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL); - - if (hFile == INVALID_HANDLE_VALUE) - return GetLastError(); - - if (bSetFileTime) - bRet = SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); - else - bRet = GetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); - - if (bRet == FALSE) - dwError = GetLastError(); - - CloseHandle(hFile); - - return dwError; -} - - -/************************************************************************** - * MyGetFileTitle [SETUPAPI.@] - * - * Returns a pointer to the last part of a fully qualified file name. - * - * PARAMS - * lpFileName [I] File name - * - * RETURNS - * Pointer to a files name. - */ -LPWSTR WINAPI -MyGetFileTitle(LPCWSTR lpFileName) -{ - LPWSTR ptr; - LPWSTR ret; - WCHAR c; - - TRACE("%s\n", debugstr_w(lpFileName)); - - ptr = (LPWSTR)lpFileName; - ret = ptr; - while (TRUE) - { - c = *ptr; - - if (c == 0) - break; - - ptr++; - if (c == (WCHAR)'\\' || c == (WCHAR)'/' || c == (WCHAR)':') - ret = ptr; - } - - return ret; -} - - -/************************************************************************** - * ConcatenatePaths [SETUPAPI.@] - * - * Concatenates two paths. - * - * PARAMS - * lpPath [I/O] Path to append path to - * lpAppend [I] Path to append - * dwBufferSize [I] Size of the path buffer - * lpRequiredSize [O] Required size for the concatenated path. Optional - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI -ConcatenatePaths(LPWSTR lpPath, - LPCWSTR lpAppend, - DWORD dwBufferSize, - LPDWORD lpRequiredSize) -{ - DWORD dwPathSize; - DWORD dwAppendSize; - DWORD dwTotalSize; - BOOL bBackslash = FALSE; - - TRACE("%s %s %lu %p\n", debugstr_w(lpPath), debugstr_w(lpAppend), - dwBufferSize, lpRequiredSize); - - dwPathSize = lstrlenW(lpPath); - - /* Ignore trailing backslash */ - if (lpPath[dwPathSize - 1] == (WCHAR)'\\') - dwPathSize--; - - dwAppendSize = lstrlenW(lpAppend); - - /* Does the source string have a leading backslash? */ - if (lpAppend[0] == (WCHAR)'\\') - { - bBackslash = TRUE; - dwAppendSize--; - } - - dwTotalSize = dwPathSize + dwAppendSize + 2; - if (lpRequiredSize != NULL) - *lpRequiredSize = dwTotalSize; - - /* Append a backslash to the destination string */ - if (bBackslash == FALSE) - { - if (dwPathSize < dwBufferSize) - { - lpPath[dwPathSize - 1] = (WCHAR)'\\'; - dwPathSize++; - } - } - - if (dwPathSize + dwAppendSize < dwBufferSize) - { - lstrcpynW(&lpPath[dwPathSize], - lpAppend, - dwAppendSize); - } - - if (dwBufferSize >= dwTotalSize) - lpPath[dwTotalSize - 1] = 0; - - return (dwBufferSize >= dwTotalSize); -} +/* + * Setupapi miscellaneous functions + * + * Copyright 2005 Eric Kohl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winreg.h" +#include "setupapi.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +#include "setupapi_private.h" + + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + + +/************************************************************************** + * MyFree [SETUPAPI.@] + * + * Frees an allocated memory block from the process heap. + * + * PARAMS + * lpMem [I] pointer to memory block which will be freed + * + * RETURNS + * None + */ +VOID WINAPI MyFree(LPVOID lpMem) +{ + TRACE("%p\n", lpMem); + HeapFree(GetProcessHeap(), 0, lpMem); +} + + +/************************************************************************** + * MyMalloc [SETUPAPI.@] + * + * Allocates memory block from the process heap. + * + * PARAMS + * dwSize [I] size of the allocated memory block + * + * RETURNS + * Success: pointer to allocated memory block + * Failure: NULL + */ +LPVOID WINAPI MyMalloc(DWORD dwSize) +{ + TRACE("%lu\n", dwSize); + return HeapAlloc(GetProcessHeap(), 0, dwSize); +} + + +/************************************************************************** + * MyRealloc [SETUPAPI.@] + * + * Changes the size of an allocated memory block or allocates a memory + * block from the process heap. + * + * PARAMS + * lpSrc [I] pointer to memory block which will be resized + * dwSize [I] new size of the memory block + * + * RETURNS + * Success: pointer to the resized memory block + * Failure: NULL + * + * NOTES + * If lpSrc is a NULL-pointer, then MyRealloc allocates a memory + * block like MyMalloc. + */ +LPVOID WINAPI MyRealloc(LPVOID lpSrc, DWORD dwSize) +{ + TRACE("%p %lu\n", lpSrc, dwSize); + + if (lpSrc == NULL) + return HeapAlloc(GetProcessHeap(), 0, dwSize); + + return HeapReAlloc(GetProcessHeap(), 0, lpSrc, dwSize); +} + + +/************************************************************************** + * DuplicateString [SETUPAPI.@] + * + * Duplicates a unicode string. + * + * PARAMS + * lpSrc [I] pointer to the unicode string that will be duplicated + * + * RETURNS + * Success: pointer to the duplicated unicode string + * Failure: NULL + * + * NOTES + * Call MyFree() to release the duplicated string. + */ +LPWSTR WINAPI DuplicateString(LPCWSTR lpSrc) +{ + LPWSTR lpDst; + + TRACE("%s\n", debugstr_w(lpSrc)); + + lpDst = MyMalloc((lstrlenW(lpSrc) + 1) * sizeof(WCHAR)); + if (lpDst == NULL) + return NULL; + + strcpyW(lpDst, lpSrc); + + return lpDst; +} + + +/************************************************************************** + * QueryRegistryValue [SETUPAPI.@] + * + * Retrieves value data from the registry and allocates memory for the + * value data. + * + * PARAMS + * hKey [I] Handle of the key to query + * lpValueName [I] Name of value under hkey to query + * lpData [O] Destination for the values contents, + * lpType [O] Destination for the value type + * lpcbData [O] Destination for the size of data + * + * RETURNS + * Success: ERROR_SUCCESS + * Failure: Otherwise + * + * NOTES + * Use MyFree to release the lpData buffer. + */ +LONG WINAPI QueryRegistryValue(HKEY hKey, + LPCWSTR lpValueName, + LPBYTE *lpData, + LPDWORD lpType, + LPDWORD lpcbData) +{ + LONG lError; + + TRACE("%lx %s %p %p %p\n", + hKey, debugstr_w(lpValueName), lpData, lpType, lpcbData); + + /* Get required buffer size */ + *lpcbData = 0; + lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, NULL, lpcbData); + if (lError != ERROR_SUCCESS) + return lError; + + /* Allocate buffer */ + *lpData = MyMalloc(*lpcbData); + if (*lpData == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + /* Query registry value */ + lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, *lpData, lpcbData); + if (lError != ERROR_SUCCESS) + MyFree(*lpData); + + return lError; +} + + +/************************************************************************** + * IsUserAdmin [SETUPAPI.@] + * + * Checks whether the current user is a member of the Administrators group. + * + * PARAMS + * None + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI IsUserAdmin(VOID) +{ + SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY}; + HANDLE hToken; + DWORD dwSize; + PTOKEN_GROUPS lpGroups; + PSID lpSid; + DWORD i; + BOOL bResult = FALSE; + + TRACE("\n"); + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + CloseHandle(hToken); + return FALSE; + } + } + + lpGroups = MyMalloc(dwSize); + if (lpGroups == NULL) + { + CloseHandle(hToken); + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize)) + { + MyFree(lpGroups); + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + + if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, + &lpSid)) + { + MyFree(lpGroups); + return FALSE; + } + + for (i = 0; i < lpGroups->GroupCount; i++) + { + if (EqualSid(lpSid, &lpGroups->Groups[i].Sid)) + { + bResult = TRUE; + break; + } + } + + FreeSid(lpSid); + MyFree(lpGroups); + + return bResult; +} + + +/************************************************************************** + * MultiByteToUnicode [SETUPAPI.@] + * + * Converts a multi-byte string to a Unicode string. + * + * PARAMS + * lpMultiByteStr [I] Multi-byte string to be converted + * uCodePage [I] Code page + * + * RETURNS + * Success: pointer to the converted Unicode string + * Failure: NULL + * + * NOTE + * Use MyFree to release the returned Unicode string. + */ +LPWSTR WINAPI MultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage) +{ + LPWSTR lpUnicodeStr; + int nLength; + + TRACE("%s %lu\n", debugstr_a(lpMultiByteStr), uCodePage); + + nLength = MultiByteToWideChar(uCodePage, 0, lpMultiByteStr, + -1, NULL, 0); + if (nLength == 0) + return NULL; + + lpUnicodeStr = MyMalloc(nLength * sizeof(WCHAR)); + if (lpUnicodeStr == NULL) + return NULL; + + if (!MultiByteToWideChar(uCodePage, 0, lpMultiByteStr, + nLength, lpUnicodeStr, nLength)) + { + MyFree(lpUnicodeStr); + return NULL; + } + + return lpUnicodeStr; +} + + +/************************************************************************** + * UnicodeToMultiByte [SETUPAPI.@] + * + * Converts a Unicode string to a multi-byte string. + * + * PARAMS + * lpUnicodeStr [I] Unicode string to be converted + * uCodePage [I] Code page + * + * RETURNS + * Success: pointer to the converted multi-byte string + * Failure: NULL + * + * NOTE + * Use MyFree to release the returned multi-byte string. + */ +LPSTR WINAPI UnicodeToMultiByte(LPCWSTR lpUnicodeStr, UINT uCodePage) +{ + LPSTR lpMultiByteStr; + int nLength; + + TRACE("%s %lu\n", debugstr_w(lpUnicodeStr), uCodePage); + + nLength = WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1, + NULL, 0, NULL, NULL); + if (nLength == 0) + return NULL; + + lpMultiByteStr = MyMalloc(nLength); + if (lpMultiByteStr == NULL) + return NULL; + + if (!WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1, + lpMultiByteStr, nLength, NULL, NULL)) + { + MyFree(lpMultiByteStr); + return NULL; + } + + return lpMultiByteStr; +} + + +/************************************************************************** + * DoesUserHavePrivilege [SETUPAPI.@] + * + * Check whether the current user has got a given privilege. + * + * PARAMS + * lpPrivilegeName [I] Name of the privilege to be checked + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DoesUserHavePrivilege(LPCWSTR lpPrivilegeName) +{ + HANDLE hToken; + DWORD dwSize; + PTOKEN_PRIVILEGES lpPrivileges; + LUID PrivilegeLuid; + DWORD i; + BOOL bResult = FALSE; + + TRACE("%s\n", debugstr_w(lpPrivilegeName)); + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + return FALSE; + + if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + CloseHandle(hToken); + return FALSE; + } + } + + lpPrivileges = MyMalloc(dwSize); + if (lpPrivileges == NULL) + { + CloseHandle(hToken); + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenPrivileges, lpPrivileges, dwSize, &dwSize)) + { + MyFree(lpPrivileges); + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + + if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &PrivilegeLuid)) + { + MyFree(lpPrivileges); + return FALSE; + } + + for (i = 0; i < lpPrivileges->PrivilegeCount; i++) + { + if (lpPrivileges->Privileges[i].Luid.HighPart == PrivilegeLuid.HighPart && + lpPrivileges->Privileges[i].Luid.LowPart == PrivilegeLuid.LowPart) + { + bResult = TRUE; + } + } + + MyFree(lpPrivileges); + + return bResult; +} + + +/************************************************************************** + * EnablePrivilege [SETUPAPI.@] + * + * Enables or disables one of the current users privileges. + * + * PARAMS + * lpPrivilegeName [I] Name of the privilege to be changed + * bEnable [I] TRUE: Enables the privilege + * FALSE: Disables the privilege + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI EnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable) +{ + TOKEN_PRIVILEGES Privileges; + HANDLE hToken; + BOOL bResult; + + TRACE("%s %s\n", debugstr_w(lpPrivilegeName), bEnable ? "TRUE" : "FALSE"); + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + return FALSE; + + Privileges.PrivilegeCount = 1; + Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0; + + if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, + &Privileges.Privileges[0].Luid)) + { + CloseHandle(hToken); + return FALSE; + } + + bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL); + + CloseHandle(hToken); + + return bResult; +} + + +/************************************************************************** + * DelayedMove [SETUPAPI.@] + * + * Moves a file upon the next reboot. + * + * PARAMS + * lpExistingFileName [I] Current file name + * lpNewFileName [I] New file name + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName) +{ + if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + return MoveFileExW(lpExistingFileName, lpNewFileName, + MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT); +} + + +/************************************************************************** + * FileExists [SETUPAPI.@] + * + * Checks whether a file exists. + * + * PARAMS + * lpFileName [I] Name of the file to check + * lpNewFileName [O] Optional information about the existing file + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData) +{ + WIN32_FIND_DATAW FindData; + HANDLE hFind; + UINT uErrorMode; + DWORD dwError; + + uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); + + hFind = FindFirstFileW(lpFileName, &FindData); + if (hFind == INVALID_HANDLE_VALUE) + { + dwError = GetLastError(); + SetErrorMode(uErrorMode); + SetLastError(dwError); + return FALSE; + } + + FindClose(hFind); + + if (lpFileFindData) + memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW)); + + SetErrorMode(uErrorMode); + + return TRUE; +} + + +/************************************************************************** + * CaptureStringArg [SETUPAPI.@] + * + * Captures a UNICODE string. + * + * PARAMS + * lpSrc [I] UNICODE string to be captured + * lpDst [O] Pointer to the captured UNICODE string + * + * RETURNS + * Success: ERROR_SUCCESS + * Failure: ERROR_INVALID_PARAMETER + * + * NOTE + * Call MyFree to release the captured UNICODE string. + */ +DWORD WINAPI CaptureStringArg(LPCWSTR pSrc, LPWSTR *pDst) +{ + if (pDst == NULL) + return ERROR_INVALID_PARAMETER; + + *pDst = DuplicateString(pSrc); + + return ERROR_SUCCESS; +} + + +/************************************************************************** + * CaptureAndConvertAnsiArg [SETUPAPI.@] + * + * Captures an ANSI string and converts it to a UNICODE string. + * + * PARAMS + * lpSrc [I] ANSI string to be captured + * lpDst [O] Pointer to the captured UNICODE string + * + * RETURNS + * Success: ERROR_SUCCESS + * Failure: ERROR_INVALID_PARAMETER + * + * NOTE + * Call MyFree to release the captured UNICODE string. + */ +DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst) +{ + if (pDst == NULL) + return ERROR_INVALID_PARAMETER; + + *pDst = MultiByteToUnicode(pSrc, CP_ACP); + + return ERROR_SUCCESS; +} + + +/************************************************************************** + * OpenAndMapFileForRead [SETUPAPI.@] + * + * Open and map a file to a buffer. + * + * PARAMS + * lpFileName [I] Name of the file to be opened + * lpSize [O] Pointer to the file size + * lpFile [0] Pointer to the file handle + * lpMapping [0] Pointer to the mapping handle + * lpBuffer [0] Pointer to the file buffer + * + * RETURNS + * Success: ERROR_SUCCESS + * Failure: Other + * + * NOTE + * Call UnmapAndCloseFile to release the file. + */ +DWORD WINAPI OpenAndMapFileForRead(LPCWSTR lpFileName, + LPDWORD lpSize, + LPHANDLE lpFile, + LPHANDLE lpMapping, + LPVOID *lpBuffer) +{ + DWORD dwError; + + TRACE("%s %p %p %p %p\n", + debugstr_w(lpFileName), lpSize, lpFile, lpMapping, lpBuffer); + + *lpFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, NULL); + if (*lpFile == INVALID_HANDLE_VALUE) + return GetLastError(); + + *lpSize = GetFileSize(*lpFile, NULL); + if (*lpSize == INVALID_FILE_SIZE) + { + dwError = GetLastError(); + CloseHandle(*lpFile); + return dwError; + } + + *lpMapping = CreateFileMappingW(*lpFile, NULL, PAGE_READONLY, 0, + *lpSize, NULL); + if (*lpMapping == NULL) + { + dwError = GetLastError(); + CloseHandle(*lpFile); + return dwError; + } + + *lpBuffer = MapViewOfFile(*lpMapping, FILE_MAP_READ, 0, 0, *lpSize); + if (*lpBuffer == NULL) + { + dwError = GetLastError(); + CloseHandle(*lpMapping); + CloseHandle(*lpFile); + return dwError; + } + + return ERROR_SUCCESS; +} + + +/************************************************************************** + * UnmapAndCloseFile [SETUPAPI.@] + * + * Unmap and close a mapped file. + * + * PARAMS + * hFile [I] Handle to the file + * hMapping [I] Handle to the file mapping + * lpBuffer [I] Pointer to the file buffer + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI UnmapAndCloseFile(HANDLE hFile, HANDLE hMapping, LPVOID lpBuffer) +{ + TRACE("%x %x %p\n", + hFile, hMapping, lpBuffer); + + if (!UnmapViewOfFile(lpBuffer)) + return FALSE; + + if (!CloseHandle(hMapping)) + return FALSE; + + if (!CloseHandle(hFile)) + return FALSE; + + return TRUE; +} + + +/************************************************************************** + * StampFileSecurity [SETUPAPI.@] + * + * Assign a new security descriptor to the given file. + * + * PARAMS + * lpFileName [I] Name of the file + * pSecurityDescriptor [I] New security descriptor + * + * RETURNS + * Success: ERROR_SUCCESS + * Failure: other + */ +DWORD WINAPI StampFileSecurity(LPCWSTR lpFileName, PSECURITY_DESCRIPTOR pSecurityDescriptor) +{ + TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor); + + if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + pSecurityDescriptor)) + return GetLastError(); + + return ERROR_SUCCESS; +} + + +/************************************************************************** + * TakeOwnershipOfFile [SETUPAPI.@] + * + * Takes the ownership of the given file. + * + * PARAMS + * lpFileName [I] Name of the file + * + * RETURNS + * Success: ERROR_SUCCESS + * Failure: other + */ +DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName) +{ + SECURITY_DESCRIPTOR SecDesc; + HANDLE hToken = NULL; + PTOKEN_OWNER pOwner = NULL; + DWORD dwError; + DWORD dwSize; + + TRACE("%s\n", debugstr_w(lpFileName)); + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + return GetLastError(); + + if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &dwSize)) + { + goto fail; + } + + pOwner = (PTOKEN_OWNER)MyMalloc(dwSize); + if (pOwner == NULL) + { + CloseHandle(hToken); + return ERROR_NOT_ENOUGH_MEMORY; + } + + if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize)) + { + goto fail; + } + + if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION)) + { + goto fail; + } + + if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE)) + { + goto fail; + } + + if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc)) + { + goto fail; + } + + MyFree(pOwner); + CloseHandle(hToken); + + return ERROR_SUCCESS; + +fail:; + dwError = GetLastError(); + + if (pOwner != NULL) + MyFree(pOwner); + + if (hToken != NULL) + CloseHandle(hToken); + + return dwError; +} + + +/************************************************************************** + * RetreiveFileSecurity [SETUPAPI.@] + * + * Retrieve the security descriptor that is associated with the given file. + * + * PARAMS + * lpFileName [I] Name of the file + * + * RETURNS + * Success: ERROR_SUCCESS + * Failure: other + */ +DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName, + PSECURITY_DESCRIPTOR *pSecurityDescriptor) +{ + PSECURITY_DESCRIPTOR SecDesc; + DWORD dwSize = 0x100; + DWORD dwError; + + TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor); + + SecDesc = (PSECURITY_DESCRIPTOR)MyMalloc(dwSize); + if (SecDesc == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + SecDesc, dwSize, &dwSize)) + { + *pSecurityDescriptor = SecDesc; + return ERROR_SUCCESS; + } + + dwError = GetLastError(); + if (dwError != ERROR_INSUFFICIENT_BUFFER) + { + MyFree(SecDesc); + return dwError; + } + + SecDesc = (PSECURITY_DESCRIPTOR)MyRealloc(SecDesc, dwSize); + if (SecDesc == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + SecDesc, dwSize, &dwSize)) + { + *pSecurityDescriptor = SecDesc; + return ERROR_SUCCESS; + } + + dwError = GetLastError(); + MyFree(SecDesc); + + return dwError; +} + + +/************************************************************************** + * AssertFail [SETUPAPI.@] + * + * Display an assertion message. + * + * PARAMS + * lpFile [I] File name + * uLine [I] Line number + * lpMessage [I] Assertion message + * + * RETURNS + * Nothing + */ +VOID WINAPI AssertFail(LPSTR lpFile, UINT uLine, LPSTR lpMessage) +{ + CHAR szModule[MAX_PATH]; + CHAR szBuffer[2048]; + LPSTR lpName; + LPSTR lpBuffer; + + TRACE("%s %u %s\n", lpFile, uLine, lpMessage); + + GetModuleFileNameA(hInstance, szModule, MAX_PATH); + lpName = strrchr(szModule, '\\'); + if (lpName != NULL) + lpName++; + else + lpName = szModule; + + wsprintfA(szBuffer, + "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?", + uLine, lpFile, lpMessage); + + if (MessageBoxA(NULL, szBuffer, lpName, MB_SETFOREGROUND | + MB_TASKMODAL | MB_ICONERROR | MB_YESNO) == IDYES) + DebugBreak(); +} + + +/************************************************************************** + * GetSetFileTimestamp [SETUPAPI.@] + * + * Gets or sets a files timestamp. + * + * PARAMS + * lpFileName [I] File name + * lpCreationTime [I/O] Creation time + * lpLastAccessTime [I/O] Last access time + * lpLastWriteTime [I/O] Last write time + * bSetFileTime [I] TRUE: Set file times + * FALSE: Get file times + * + * RETURNS + * Success: ERROR_SUCCESS + * Failure: other + */ +DWORD WINAPI GetSetFileTimestamp(LPCWSTR lpFileName, + LPFILETIME lpCreationTime, + LPFILETIME lpLastAccessTime, + LPFILETIME lpLastWriteTime, + BOOLEAN bSetFileTime) +{ + HANDLE hFile; + BOOLEAN bRet; + DWORD dwError = ERROR_SUCCESS; + + TRACE("%s %p %p %p %x\n", debugstr_w(lpFileName), lpCreationTime, + lpLastAccessTime, lpLastWriteTime, bSetFileTime); + + hFile = CreateFileW(lpFileName, + bSetFileTime ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return GetLastError(); + + if (bSetFileTime) + bRet = SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); + else + bRet = GetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); + + if (bRet == FALSE) + dwError = GetLastError(); + + CloseHandle(hFile); + + return dwError; +} + + +/************************************************************************** + * MyGetFileTitle [SETUPAPI.@] + * + * Returns a pointer to the last part of a fully qualified file name. + * + * PARAMS + * lpFileName [I] File name + * + * RETURNS + * Pointer to a files name. + */ +LPWSTR WINAPI +MyGetFileTitle(LPCWSTR lpFileName) +{ + LPWSTR ptr; + LPWSTR ret; + WCHAR c; + + TRACE("%s\n", debugstr_w(lpFileName)); + + ptr = (LPWSTR)lpFileName; + ret = ptr; + while (TRUE) + { + c = *ptr; + + if (c == 0) + break; + + ptr++; + if (c == (WCHAR)'\\' || c == (WCHAR)'/' || c == (WCHAR)':') + ret = ptr; + } + + return ret; +} + + +/************************************************************************** + * ConcatenatePaths [SETUPAPI.@] + * + * Concatenates two paths. + * + * PARAMS + * lpPath [I/O] Path to append path to + * lpAppend [I] Path to append + * dwBufferSize [I] Size of the path buffer + * lpRequiredSize [O] Required size for the concatenated path. Optional + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI +ConcatenatePaths(LPWSTR lpPath, + LPCWSTR lpAppend, + DWORD dwBufferSize, + LPDWORD lpRequiredSize) +{ + DWORD dwPathSize; + DWORD dwAppendSize; + DWORD dwTotalSize; + BOOL bBackslash = FALSE; + + TRACE("%s %s %lu %p\n", debugstr_w(lpPath), debugstr_w(lpAppend), + dwBufferSize, lpRequiredSize); + + dwPathSize = lstrlenW(lpPath); + + /* Ignore trailing backslash */ + if (lpPath[dwPathSize - 1] == (WCHAR)'\\') + dwPathSize--; + + dwAppendSize = lstrlenW(lpAppend); + + /* Does the source string have a leading backslash? */ + if (lpAppend[0] == (WCHAR)'\\') + { + bBackslash = TRUE; + dwAppendSize--; + } + + dwTotalSize = dwPathSize + dwAppendSize + 2; + if (lpRequiredSize != NULL) + *lpRequiredSize = dwTotalSize; + + /* Append a backslash to the destination string */ + if (bBackslash == FALSE) + { + if (dwPathSize < dwBufferSize) + { + lpPath[dwPathSize - 1] = (WCHAR)'\\'; + dwPathSize++; + } + } + + if (dwPathSize + dwAppendSize < dwBufferSize) + { + lstrcpynW(&lpPath[dwPathSize], + lpAppend, + dwAppendSize); + } + + if (dwBufferSize >= dwTotalSize) + lpPath[dwTotalSize - 1] = 0; + + return (dwBufferSize >= dwTotalSize); +} diff --git a/reactos/lib/setupapi/parser.c b/reactos/lib/setupapi/parser.c index 74664bd4b82..53c9e3968b8 100644 --- a/reactos/lib/setupapi/parser.c +++ b/reactos/lib/setupapi/parser.c @@ -1,1839 +1,1839 @@ -/* - * INF file parsing - * - * Copyright 2002 Alexandre Julliard for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "winreg.h" -#include "winternl.h" -#include "winerror.h" -#include "setupapi.h" -#include "setupapi_private.h" - -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -#define CONTROL_Z '\x1a' -#define MAX_SECTION_NAME_LEN 255 -#define MAX_FIELD_LEN 511 /* larger fields get silently truncated */ -/* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */ -#define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1) - -/* inf file structure definitions */ - -struct field -{ - const WCHAR *text; /* field text */ -}; - -struct line -{ - int first_field; /* index of first field in field array */ - int nb_fields; /* number of fields in line */ - int key_field; /* index of field for key or -1 if no key */ -}; - -struct section -{ - const WCHAR *name; /* section name */ - unsigned int nb_lines; /* number of used lines */ - unsigned int alloc_lines; /* total number of allocated lines in array below */ - struct line lines[16]; /* lines information (grown dynamically, 16 is initial size) */ -}; - -struct inf_file -{ - struct inf_file *next; /* next appended file */ - WCHAR *strings; /* buffer for string data (section names and field values) */ - WCHAR *string_pos; /* position of next available string in buffer */ - unsigned int nb_sections; /* number of used sections */ - unsigned int alloc_sections; /* total number of allocated section pointers */ - struct section **sections; /* section pointers array */ - unsigned int nb_fields; - unsigned int alloc_fields; - struct field *fields; - int strings_section; /* index of [Strings] section or -1 if none */ - WCHAR *src_root; /* source root directory */ -}; - -/* parser definitions */ - -enum parser_state -{ - LINE_START, /* at beginning of a line */ - SECTION_NAME, /* parsing a section name */ - KEY_NAME, /* parsing a key name */ - VALUE_NAME, /* parsing a value name */ - EOL_BACKSLASH, /* backslash at end of line */ - QUOTES, /* inside quotes */ - LEADING_SPACES, /* leading spaces */ - TRAILING_SPACES, /* trailing spaces */ - COMMENT, /* inside a comment */ - NB_PARSER_STATES -}; - -struct parser -{ - const WCHAR *start; /* start position of item being parsed */ - const WCHAR *end; /* end of buffer */ - struct inf_file *file; /* file being built */ - enum parser_state state; /* current parser state */ - enum parser_state stack[4]; /* state stack */ - int stack_pos; /* current pos in stack */ - - int cur_section; /* index of section being parsed*/ - struct line *line; /* current line */ - unsigned int line_pos; /* current line position in file */ - unsigned int error; /* error code */ - unsigned int token_len; /* current token len */ - WCHAR token[MAX_FIELD_LEN+1]; /* current token */ -}; - -typedef const WCHAR * (*parser_state_func)( struct parser *parser, const WCHAR *pos ); - -/* parser state machine functions */ -static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos ); -static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos ); -static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos ); -static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos ); -static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos ); -static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos ); -static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos ); -static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos ); -static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos ); - -static const parser_state_func parser_funcs[NB_PARSER_STATES] = -{ - line_start_state, /* LINE_START */ - section_name_state, /* SECTION_NAME */ - key_name_state, /* KEY_NAME */ - value_name_state, /* VALUE_NAME */ - eol_backslash_state, /* EOL_BACKSLASH */ - quotes_state, /* QUOTES */ - leading_spaces_state, /* LEADING_SPACES */ - trailing_spaces_state, /* TRAILING_SPACES */ - comment_state /* COMMENT */ -}; - - -/* Unicode string constants */ -static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; -static const WCHAR Signature[] = {'S','i','g','n','a','t','u','r','e',0}; -static const WCHAR Chicago[] = {'$','C','h','i','c','a','g','o','$',0}; -static const WCHAR WindowsNT[] = {'$','W','i','n','d','o','w','s',' ','N','T','$',0}; -static const WCHAR Windows95[] = {'$','W','i','n','d','o','w','s',' ','9','5','$',0}; -static const WCHAR LayoutFile[] = {'L','a','y','o','u','t','F','i','l','e',0}; - -/* extend an array, allocating more memory if necessary */ -static void *grow_array( void *array, unsigned int *count, size_t elem ) -{ - void *new_array; - unsigned int new_count = *count + *count / 2; - if (new_count < 32) new_count = 32; - - if (array) - new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, array, new_count * elem ); - else - new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * elem ); - - if (new_array) - *count = new_count; - else - HeapFree( GetProcessHeap(), 0, array ); - return new_array; -} - - -/* find a section by name */ -static int find_section( struct inf_file *file, const WCHAR *name ) -{ - unsigned int i; - - for (i = 0; i < file->nb_sections; i++) - if (!strcmpiW( name, file->sections[i]->name )) return i; - return -1; -} - - -/* find a line by name */ -static struct line *find_line( struct inf_file *file, int section_index, const WCHAR *name ) -{ - struct section *section; - struct line *line; - int i; - - if (section_index < 0 || section_index >= file->nb_sections) return NULL; - section = file->sections[section_index]; - for (i = 0, line = section->lines; i < section->nb_lines; i++, line++) - { - if (line->key_field == -1) continue; - if (!strcmpiW( name, file->fields[line->key_field].text )) return line; - } - return NULL; -} - - -/* add a section to the file and return the section index */ -static int add_section( struct inf_file *file, const WCHAR *name ) -{ - struct section *section; - - if (file->nb_sections >= file->alloc_sections) - { - if (!(file->sections = grow_array( file->sections, &file->alloc_sections, - sizeof(file->sections[0]) ))) return -1; - } - if (!(section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) ))) return -1; - section->name = name; - section->nb_lines = 0; - section->alloc_lines = sizeof(section->lines)/sizeof(section->lines[0]); - file->sections[file->nb_sections] = section; - return file->nb_sections++; -} - - -/* add a line to a given section */ -static struct line *add_line( struct inf_file *file, int section_index ) -{ - struct section *section; - struct line *line; - - assert( section_index >= 0 && section_index < file->nb_sections ); - - section = file->sections[section_index]; - if (section->nb_lines == section->alloc_lines) /* need to grow the section */ - { - int size = sizeof(*section) - sizeof(section->lines) + 2*section->alloc_lines*sizeof(*line); - if (!(section = HeapReAlloc( GetProcessHeap(), 0, section, size ))) return NULL; - section->alloc_lines *= 2; - file->sections[section_index] = section; - } - line = §ion->lines[section->nb_lines++]; - line->first_field = file->nb_fields; - line->nb_fields = 0; - line->key_field = -1; - return line; -} - - -/* retrieve a given line from section/line index */ -inline static struct line *get_line( struct inf_file *file, unsigned int section_index, - unsigned int line_index ) -{ - struct section *section; - - if (section_index >= file->nb_sections) return NULL; - section = file->sections[section_index]; - if (line_index >= section->nb_lines) return NULL; - return §ion->lines[line_index]; -} - - -/* retrieve a given field from section/line/field index */ -static struct field *get_field( struct inf_file *file, int section_index, int line_index, - int field_index ) -{ - struct line *line = get_line( file, section_index, line_index ); - - if (!line) return NULL; - if (!field_index) /* get the key */ - { - if (line->key_field == -1) return NULL; - return &file->fields[line->key_field]; - } - field_index--; - if (field_index >= line->nb_fields) return NULL; - return &file->fields[line->first_field + field_index]; -} - - -/* allocate a new field, growing the array if necessary */ -static struct field *add_field( struct inf_file *file, const WCHAR *text ) -{ - struct field *field; - - if (file->nb_fields >= file->alloc_fields) - { - if (!(file->fields = grow_array( file->fields, &file->alloc_fields, - sizeof(file->fields[0]) ))) return NULL; - } - field = &file->fields[file->nb_fields++]; - field->text = text; - return field; -} - - -/* retrieve the string substitution for a directory id */ -static const WCHAR *get_dirid_subst( int dirid, unsigned int *len ) -{ - extern const WCHAR *DIRID_get_string( HINF hinf, int dirid ); - const WCHAR *ret = DIRID_get_string( 0, dirid ); - if (ret) *len = strlenW(ret); - return ret; -} - - -/* retrieve the string substitution for a given string, or NULL if not found */ -/* if found, len is set to the substitution length */ -static const WCHAR *get_string_subst( struct inf_file *file, const WCHAR *str, unsigned int *len ) -{ - static const WCHAR percent = '%'; - - struct section *strings_section; - struct line *line; - struct field *field; - unsigned int i; - int dirid; - WCHAR *dirid_str, *end; - const WCHAR *ret = NULL; - - if (!*len) /* empty string (%%) is replaced by single percent */ - { - *len = 1; - return &percent; - } - if (file->strings_section == -1) goto not_found; - strings_section = file->sections[file->strings_section]; - for (i = 0, line = strings_section->lines; i < strings_section->nb_lines; i++, line++) - { - if (line->key_field == -1) continue; - if (strncmpiW( str, file->fields[line->key_field].text, *len )) continue; - if (!file->fields[line->key_field].text[*len]) break; - } - if (i == strings_section->nb_lines || !line->nb_fields) goto not_found; - field = &file->fields[line->first_field]; - *len = strlenW( field->text ); - return field->text; - - not_found: /* check for integer id */ - if ((dirid_str = HeapAlloc( GetProcessHeap(), 0, (*len+1) * sizeof(WCHAR) ))) - { - memcpy( dirid_str, str, *len * sizeof(WCHAR) ); - dirid_str[*len] = 0; - dirid = strtolW( dirid_str, &end, 10 ); - if (!*end) ret = get_dirid_subst( dirid, len ); - HeapFree( GetProcessHeap(), 0, dirid_str ); - return ret; - } - return NULL; -} - - -/* do string substitutions on the specified text */ -/* the buffer is assumed to be large enough */ -/* returns necessary length not including terminating null */ -unsigned int PARSER_string_substW( struct inf_file *file, const WCHAR *text, WCHAR *buffer, - unsigned int size ) -{ - const WCHAR *start, *subst, *p; - unsigned int len, total = 0; - int inside = 0; - - if (!buffer) size = MAX_STRING_LEN + 1; - for (p = start = text; *p; p++) - { - if (*p != '%') continue; - inside = !inside; - if (inside) /* start of a %xx% string */ - { - len = p - start; - if (len > size - 1) len = size - 1; - if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) ); - total += len; - size -= len; - start = p; - } - else /* end of the %xx% string, find substitution */ - { - len = p - start - 1; - subst = get_string_subst( file, start + 1, &len ); - if (!subst) - { - subst = start; - len = p - start + 1; - } - if (len > size - 1) len = size - 1; - if (buffer) memcpy( buffer + total, subst, len * sizeof(WCHAR) ); - total += len; - size -= len; - start = p + 1; - } - } - - if (start != p) /* unfinished string, copy it */ - { - len = p - start; - if (len > size - 1) len = size - 1; - if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) ); - total += len; - } - if (buffer && size) buffer[total] = 0; - return total; -} - - -/* do string substitutions on the specified text */ -/* the buffer is assumed to be large enough */ -/* returns necessary length not including terminating null */ -unsigned int PARSER_string_substA( struct inf_file *file, const WCHAR *text, char *buffer, - unsigned int size ) -{ - WCHAR buffW[MAX_STRING_LEN+1]; - DWORD ret; - - unsigned int len = PARSER_string_substW( file, text, buffW, sizeof(buffW)/sizeof(WCHAR) ); - if (!buffer) RtlUnicodeToMultiByteSize( &ret, buffW, len * sizeof(WCHAR) ); - else - { - RtlUnicodeToMultiByteN( buffer, size-1, &ret, buffW, len * sizeof(WCHAR) ); - buffer[ret] = 0; - } - return ret; -} - - -/* push some string data into the strings buffer */ -static WCHAR *push_string( struct inf_file *file, const WCHAR *string ) -{ - WCHAR *ret = file->string_pos; - strcpyW( ret, string ); - file->string_pos += strlenW( ret ) + 1; - return ret; -} - - -/* push the current state on the parser stack */ -inline static void push_state( struct parser *parser, enum parser_state state ) -{ - assert( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) ); - parser->stack[parser->stack_pos++] = state; -} - - -/* pop the current state */ -inline static void pop_state( struct parser *parser ) -{ - assert( parser->stack_pos ); - parser->state = parser->stack[--parser->stack_pos]; -} - - -/* set the parser state and return the previous one */ -inline static enum parser_state set_state( struct parser *parser, enum parser_state state ) -{ - enum parser_state ret = parser->state; - parser->state = state; - return ret; -} - - -/* check if the pointer points to an end of file */ -inline static int is_eof( struct parser *parser, const WCHAR *ptr ) -{ - return (ptr >= parser->end || *ptr == CONTROL_Z); -} - - -/* check if the pointer points to an end of line */ -inline static int is_eol( struct parser *parser, const WCHAR *ptr ) -{ - return (ptr >= parser->end || *ptr == CONTROL_Z || *ptr == '\n'); -} - - -/* push data from current token start up to pos into the current token */ -static int push_token( struct parser *parser, const WCHAR *pos ) -{ - int len = pos - parser->start; - const WCHAR *src = parser->start; - WCHAR *dst = parser->token + parser->token_len; - - if (len > MAX_FIELD_LEN - parser->token_len) len = MAX_FIELD_LEN - parser->token_len; - - parser->token_len += len; - for ( ; len > 0; len--, dst++, src++) *dst = *src ? *src : ' '; - *dst = 0; - parser->start = pos; - return 0; -} - - -/* add a section with the current token as name */ -static int add_section_from_token( struct parser *parser ) -{ - int section_index; - - if (parser->token_len > MAX_SECTION_NAME_LEN) - { - parser->error = ERROR_SECTION_NAME_TOO_LONG; - return -1; - } - if ((section_index = find_section( parser->file, parser->token )) == -1) - { - /* need to create a new one */ - const WCHAR *name = push_string( parser->file, parser->token ); - if ((section_index = add_section( parser->file, name )) == -1) - { - parser->error = ERROR_NOT_ENOUGH_MEMORY; - return -1; - } - } - parser->token_len = 0; - parser->cur_section = section_index; - return section_index; -} - - -/* add a field containing the current token to the current line */ -static struct field *add_field_from_token( struct parser *parser, int is_key ) -{ - struct field *field; - WCHAR *text; - - if (!parser->line) /* need to start a new line */ - { - if (parser->cur_section == -1) /* got a line before the first section */ - { - parser->error = ERROR_WRONG_INF_STYLE; - return NULL; - } - if (!(parser->line = add_line( parser->file, parser->cur_section ))) goto error; - } - else assert(!is_key); - - text = push_string( parser->file, parser->token ); - if ((field = add_field( parser->file, text ))) - { - if (!is_key) parser->line->nb_fields++; - else - { - /* replace first field by key field */ - parser->line->key_field = parser->line->first_field; - parser->line->first_field++; - } - parser->token_len = 0; - return field; - } - error: - parser->error = ERROR_NOT_ENOUGH_MEMORY; - return NULL; -} - - -/* close the current line and prepare for parsing a new one */ -static void close_current_line( struct parser *parser ) -{ - struct line *cur_line = parser->line; - - if (cur_line) - { - /* if line has a single field and no key, the field is the key too */ - if (cur_line->nb_fields == 1 && cur_line->key_field == -1) - cur_line->key_field = cur_line->first_field; - } - parser->line = NULL; -} - - -/* handler for parser LINE_START state */ -static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p; - - for (p = pos; !is_eof( parser, p ); p++) - { - switch(*p) - { - case '\n': - parser->line_pos++; - close_current_line( parser ); - break; - case ';': - push_state( parser, LINE_START ); - set_state( parser, COMMENT ); - return p + 1; - case '[': - parser->start = p + 1; - set_state( parser, SECTION_NAME ); - return p + 1; - default: - if (!isspaceW(*p)) - { - parser->start = p; - set_state( parser, KEY_NAME ); - return p; - } - break; - } - } - close_current_line( parser ); - return NULL; -} - - -/* handler for parser SECTION_NAME state */ -static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p; - - for (p = pos; !is_eol( parser, p ); p++) - { - if (*p == ']') - { - push_token( parser, p ); - if (add_section_from_token( parser ) == -1) return NULL; - push_state( parser, LINE_START ); - set_state( parser, COMMENT ); /* ignore everything else on the line */ - return p + 1; - } - } - parser->error = ERROR_BAD_SECTION_NAME_LINE; /* unfinished section name */ - return NULL; -} - - -/* handler for parser KEY_NAME state */ -static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p, *token_end = parser->start; - - for (p = pos; !is_eol( parser, p ); p++) - { - if (*p == ',') break; - switch(*p) - { - - case '=': - push_token( parser, token_end ); - if (!add_field_from_token( parser, 1 )) return NULL; - parser->start = p + 1; - push_state( parser, VALUE_NAME ); - set_state( parser, LEADING_SPACES ); - return p + 1; - case ';': - push_token( parser, token_end ); - if (!add_field_from_token( parser, 0 )) return NULL; - push_state( parser, LINE_START ); - set_state( parser, COMMENT ); - return p + 1; - case '"': - push_token( parser, token_end ); - parser->start = p + 1; - push_state( parser, KEY_NAME ); - set_state( parser, QUOTES ); - return p + 1; - case '\\': - push_token( parser, token_end ); - parser->start = p; - push_state( parser, KEY_NAME ); - set_state( parser, EOL_BACKSLASH ); - return p; - default: - if (!isspaceW(*p)) token_end = p + 1; - else - { - push_token( parser, p ); - push_state( parser, KEY_NAME ); - set_state( parser, TRAILING_SPACES ); - return p; - } - break; - } - } - push_token( parser, token_end ); - set_state( parser, VALUE_NAME ); - return p; -} - - -/* handler for parser VALUE_NAME state */ -static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p, *token_end = parser->start; - - for (p = pos; !is_eol( parser, p ); p++) - { - switch(*p) - { - case ';': - push_token( parser, token_end ); - if (!add_field_from_token( parser, 0 )) return NULL; - push_state( parser, LINE_START ); - set_state( parser, COMMENT ); - return p + 1; - case ',': - push_token( parser, token_end ); - if (!add_field_from_token( parser, 0 )) return NULL; - parser->start = p + 1; - push_state( parser, VALUE_NAME ); - set_state( parser, LEADING_SPACES ); - return p + 1; - case '"': - push_token( parser, token_end ); - parser->start = p + 1; - push_state( parser, VALUE_NAME ); - set_state( parser, QUOTES ); - return p + 1; - case '\\': - push_token( parser, token_end ); - parser->start = p; - push_state( parser, VALUE_NAME ); - set_state( parser, EOL_BACKSLASH ); - return p; - default: - if (!isspaceW(*p)) token_end = p + 1; - else - { - push_token( parser, p ); - push_state( parser, VALUE_NAME ); - set_state( parser, TRAILING_SPACES ); - return p; - } - break; - } - } - push_token( parser, token_end ); - if (!add_field_from_token( parser, 0 )) return NULL; - set_state( parser, LINE_START ); - return p; -} - - -/* handler for parser EOL_BACKSLASH state */ -static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p; - - for (p = pos; !is_eof( parser, p ); p++) - { - switch(*p) - { - case '\n': - parser->line_pos++; - parser->start = p + 1; - set_state( parser, LEADING_SPACES ); - return p + 1; - case '\\': - continue; - case ';': - push_state( parser, EOL_BACKSLASH ); - set_state( parser, COMMENT ); - return p + 1; - default: - if (isspaceW(*p)) continue; - push_token( parser, p ); - pop_state( parser ); - return p; - } - } - parser->start = p; - pop_state( parser ); - return p; -} - - -/* handler for parser QUOTES state */ -static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p, *token_end = parser->start; - - for (p = pos; !is_eol( parser, p ); p++) - { - if (*p == '"') - { - if (p+1 < parser->end && p[1] == '"') /* double quotes */ - { - push_token( parser, p + 1 ); - parser->start = token_end = p + 2; - p++; - } - else /* end of quotes */ - { - push_token( parser, p ); - parser->start = p + 1; - pop_state( parser ); - return p + 1; - } - } - } - push_token( parser, p ); - pop_state( parser ); - return p; -} - - -/* handler for parser LEADING_SPACES state */ -static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p; - - for (p = pos; !is_eol( parser, p ); p++) - { - if (*p == '\\') - { - parser->start = p; - set_state( parser, EOL_BACKSLASH ); - return p; - } - if (!isspaceW(*p)) break; - } - parser->start = p; - pop_state( parser ); - return p; -} - - -/* handler for parser TRAILING_SPACES state */ -static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p; - - for (p = pos; !is_eol( parser, p ); p++) - { - if (*p == '\\') - { - set_state( parser, EOL_BACKSLASH ); - return p; - } - if (!isspaceW(*p)) break; - } - pop_state( parser ); - return p; -} - - -/* handler for parser COMMENT state */ -static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos ) -{ - const WCHAR *p = pos; - - while (!is_eol( parser, p )) p++; - pop_state( parser ); - return p; -} - - -/* parse a complete buffer */ -static DWORD parse_buffer( struct inf_file *file, const WCHAR *buffer, const WCHAR *end, - UINT *error_line ) -{ - static const WCHAR Strings[] = {'S','t','r','i','n','g','s',0}; - - struct parser parser; - const WCHAR *pos = buffer; - - parser.start = buffer; - parser.end = end; - parser.file = file; - parser.line = NULL; - parser.state = LINE_START; - parser.stack_pos = 0; - parser.cur_section = -1; - parser.line_pos = 1; - parser.error = 0; - parser.token_len = 0; - - /* parser main loop */ - while (pos) pos = (parser_funcs[parser.state])( &parser, pos ); - - /* trim excess buffer space */ - if (file->alloc_sections > file->nb_sections) - { - file->sections = HeapReAlloc( GetProcessHeap(), 0, file->sections, - file->nb_sections * sizeof(file->sections[0]) ); - file->alloc_sections = file->nb_sections; - } - if (file->alloc_fields > file->nb_fields) - { - file->fields = HeapReAlloc( GetProcessHeap(), 0, file->fields, - file->nb_fields * sizeof(file->fields[0]) ); - file->alloc_fields = file->nb_fields; - } - file->strings = HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, file->strings, - (file->string_pos - file->strings) * sizeof(WCHAR) ); - - if (parser.error) - { - if (error_line) *error_line = parser.line_pos; - return parser.error; - } - - /* find the [strings] section */ - file->strings_section = find_section( file, Strings ); - return 0; -} - - -/* append a child INF file to its parent list, in a thread-safe manner */ -static void append_inf_file( struct inf_file *parent, struct inf_file *child ) -{ - struct inf_file **ppnext = &parent->next; - child->next = NULL; - - for (;;) - { - struct inf_file *next = InterlockedCompareExchangePointer( (void **)ppnext, child, NULL ); - if (!next) return; - ppnext = &next->next; - } -} - - -/*********************************************************************** - * parse_file - * - * parse an INF file. - */ -static struct inf_file *parse_file( HANDLE handle, const WCHAR *class, UINT *error_line ) -{ - void *buffer; - DWORD err = 0; - struct inf_file *file; - - DWORD size = GetFileSize( handle, NULL ); - HANDLE mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, size, NULL ); - if (!mapping) return NULL; - buffer = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, size ); - NtClose( mapping ); - if (!buffer) return NULL; - - if (class) FIXME( "class %s not supported yet\n", debugstr_w(class) ); - - if (!(file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*file) ))) - { - err = ERROR_NOT_ENOUGH_MEMORY; - goto done; - } - - /* we won't need more strings space than the size of the file, - * so we can preallocate it here - */ - if (!(file->strings = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) - { - err = ERROR_NOT_ENOUGH_MEMORY; - goto done; - } - file->string_pos = file->strings; - file->strings_section = -1; - - if (!RtlIsTextUnicode( buffer, size, NULL )) - { - WCHAR *new_buff = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ); - if (new_buff) - { - DWORD len = MultiByteToWideChar( CP_ACP, 0, buffer, size, new_buff, - size * sizeof(WCHAR) ); - err = parse_buffer( file, new_buff, new_buff + len, error_line ); - HeapFree( GetProcessHeap(), 0, new_buff ); - } - } - else err = parse_buffer( file, buffer, (WCHAR *)((char *)buffer + size), error_line ); - - if (!err) /* now check signature */ - { - int version_index = find_section( file, Version ); - if (version_index != -1) - { - struct line *line = find_line( file, version_index, Signature ); - if (line && line->nb_fields > 0) - { - struct field *field = file->fields + line->first_field; - if (!strcmpiW( field->text, Chicago )) goto done; - if (!strcmpiW( field->text, WindowsNT )) goto done; - if (!strcmpiW( field->text, Windows95 )) goto done; - } - } - err = ERROR_WRONG_INF_STYLE; - } - - done: - UnmapViewOfFile( buffer ); - if (err) - { - HeapFree( GetProcessHeap(), 0, file ); - SetLastError( err ); - file = NULL; - } - return file; -} - - -/*********************************************************************** - * PARSER_get_src_root - * - * Retrieve the source directory of an inf file. - */ -const WCHAR *PARSER_get_src_root( HINF hinf ) -{ - struct inf_file *file = hinf; - return file->src_root; -} - - -/*********************************************************************** - * PARSER_get_dest_dir - * - * retrieve a destination dir of the form "dirid,relative_path" in the given entry. - * returned buffer must be freed by caller. - */ -WCHAR *PARSER_get_dest_dir( INFCONTEXT *context ) -{ - const WCHAR *dir; - WCHAR *ptr, *ret; - INT dirid; - DWORD len1, len2; - - if (!SetupGetIntField( context, 1, &dirid )) return NULL; - if (!(dir = DIRID_get_string( context->Inf, dirid ))) return NULL; - len1 = strlenW(dir) + 1; - if (!SetupGetStringFieldW( context, 2, NULL, 0, &len2 )) len2 = 0; - if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len1+len2) * sizeof(WCHAR) ))) return NULL; - strcpyW( ret, dir ); - ptr = ret + strlenW(ret); - if (len2 && ptr > ret && ptr[-1] != '\\') *ptr++ = '\\'; - if (!SetupGetStringFieldW( context, 2, ptr, len2, NULL )) *ptr = 0; - return ret; -} - - -/*********************************************************************** - * SetupOpenInfFileA (SETUPAPI.@) - */ -HINF WINAPI SetupOpenInfFileA( PCSTR name, PCSTR class, DWORD style, UINT *error ) -{ - UNICODE_STRING nameW, classW; - HINF ret = (HINF)INVALID_HANDLE_VALUE; - - classW.Buffer = NULL; - if (class && !RtlCreateUnicodeStringFromAsciiz( &classW, class )) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return ret; - } - if (RtlCreateUnicodeStringFromAsciiz( &nameW, name )) - { - ret = SetupOpenInfFileW( nameW.Buffer, classW.Buffer, style, error ); - RtlFreeUnicodeString( &nameW ); - } - RtlFreeUnicodeString( &classW ); - return ret; -} - - -/*********************************************************************** - * SetupOpenInfFileW (SETUPAPI.@) - */ -HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR class, DWORD style, UINT *error ) -{ - struct inf_file *file = NULL; - HANDLE handle; - WCHAR *path, *p; - UINT len; - - if (strchrW( name, '\\' ) || strchrW( name, '/' )) - { - if (!(len = GetFullPathNameW( name, 0, NULL, NULL ))) return (HINF)INVALID_HANDLE_VALUE; - if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return (HINF)INVALID_HANDLE_VALUE; - } - GetFullPathNameW( name, len, path, NULL ); - handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); - } - else /* try Windows directory */ - { - static const WCHAR Inf[] = {'\\','i','n','f','\\',0}; - static const WCHAR System32[] = {'\\','s','y','s','t','e','m','3','2','\\',0}; - - len = GetWindowsDirectoryW( NULL, 0 ) + strlenW(name) + 12; - if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return (HINF)INVALID_HANDLE_VALUE; - } - GetWindowsDirectoryW( path, len ); - p = path + strlenW(path); - strcpyW( p, Inf ); - strcatW( p, name ); - handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); - if (handle == INVALID_HANDLE_VALUE) - { - strcpyW( p, System32 ); - strcatW( p, name ); - handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); - } - } - - if (handle != INVALID_HANDLE_VALUE) - { - file = parse_file( handle, class, error ); - CloseHandle( handle ); - } - if (!file) - { - HeapFree( GetProcessHeap(), 0, path ); - return (HINF)INVALID_HANDLE_VALUE; - } - TRACE( "%s -> %p\n", debugstr_w(path), file ); - file->src_root = path; - if ((p = strrchrW( path, '\\' ))) p[1] = 0; /* remove file name */ - SetLastError( 0 ); - return (HINF)file; -} - - -/*********************************************************************** - * SetupOpenAppendInfFileA (SETUPAPI.@) - */ -BOOL WINAPI SetupOpenAppendInfFileA( PCSTR name, HINF parent_hinf, UINT *error ) -{ - HINF child_hinf; - - if (!name) return SetupOpenAppendInfFileW( NULL, parent_hinf, error ); - child_hinf = SetupOpenInfFileA( name, NULL, INF_STYLE_WIN4, error ); - if (child_hinf == (HINF)INVALID_HANDLE_VALUE) return FALSE; - append_inf_file( parent_hinf, child_hinf ); - TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_a(name), child_hinf ); - return TRUE; -} - - -/*********************************************************************** - * SetupOpenAppendInfFileW (SETUPAPI.@) - */ -BOOL WINAPI SetupOpenAppendInfFileW( PCWSTR name, HINF parent_hinf, UINT *error ) -{ - HINF child_hinf; - - if (!name) - { - INFCONTEXT context; - WCHAR filename[MAX_PATH]; - int idx = 1; - - if (!SetupFindFirstLineW( parent_hinf, Version, LayoutFile, &context )) return FALSE; - while (SetupGetStringFieldW( &context, idx++, filename, - sizeof(filename)/sizeof(WCHAR), NULL )) - { - child_hinf = SetupOpenInfFileW( filename, NULL, INF_STYLE_WIN4, error ); - if (child_hinf == (HINF)INVALID_HANDLE_VALUE) return FALSE; - append_inf_file( parent_hinf, child_hinf ); - TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_w(filename), child_hinf ); - } - return TRUE; - } - child_hinf = SetupOpenInfFileW( name, NULL, INF_STYLE_WIN4, error ); - if (child_hinf == (HINF)INVALID_HANDLE_VALUE) return FALSE; - append_inf_file( parent_hinf, child_hinf ); - TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_w(name), child_hinf ); - return TRUE; -} - - -/*********************************************************************** - * SetupOpenMasterInf (SETUPAPI.@) - */ -HINF WINAPI SetupOpenMasterInf( VOID ) -{ - static const WCHAR Layout[] = {'\\','i','n','f','\\', 'l', 'a', 'y', 'o', 'u', 't', '.', 'i', 'n', 'f', 0}; - WCHAR Buffer[MAX_PATH]; - - GetWindowsDirectoryW( Buffer, MAX_PATH ); - strcatW( Buffer, Layout ); - return SetupOpenInfFileW( Buffer, NULL, INF_STYLE_WIN4, NULL); -} - - - -/*********************************************************************** - * SetupCloseInfFile (SETUPAPI.@) - */ -void WINAPI SetupCloseInfFile( HINF hinf ) -{ - struct inf_file *file = hinf; - unsigned int i; - - for (i = 0; i < file->nb_sections; i++) HeapFree( GetProcessHeap(), 0, file->sections[i] ); - HeapFree( GetProcessHeap(), 0, file->src_root ); - HeapFree( GetProcessHeap(), 0, file->sections ); - HeapFree( GetProcessHeap(), 0, file->fields ); - HeapFree( GetProcessHeap(), 0, file->strings ); - HeapFree( GetProcessHeap(), 0, file ); -} - - -/*********************************************************************** - * SetupGetLineCountA (SETUPAPI.@) - */ -LONG WINAPI SetupGetLineCountA( HINF hinf, PCSTR name ) -{ - UNICODE_STRING sectionW; - LONG ret = -1; - - if (!RtlCreateUnicodeStringFromAsciiz( §ionW, name )) - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - else - { - ret = SetupGetLineCountW( hinf, sectionW.Buffer ); - RtlFreeUnicodeString( §ionW ); - } - return ret; -} - - -/*********************************************************************** - * SetupGetLineCountW (SETUPAPI.@) - */ -LONG WINAPI SetupGetLineCountW( HINF hinf, PCWSTR section ) -{ - struct inf_file *file = hinf; - int section_index; - LONG ret = -1; - - for (file = hinf; file; file = file->next) - { - if ((section_index = find_section( file, section )) == -1) continue; - if (ret == -1) ret = 0; - ret += file->sections[section_index]->nb_lines; - } - TRACE( "(%p,%s) returning %ld\n", hinf, debugstr_w(section), ret ); - SetLastError( (ret == -1) ? ERROR_SECTION_NOT_FOUND : 0 ); - return ret; -} - - -/*********************************************************************** - * SetupGetLineByIndexA (SETUPAPI.@) - */ -BOOL WINAPI SetupGetLineByIndexA( HINF hinf, PCSTR section, DWORD index, INFCONTEXT *context ) -{ - UNICODE_STRING sectionW; - BOOL ret = FALSE; - - if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - else - { - ret = SetupGetLineByIndexW( hinf, sectionW.Buffer, index, context ); - RtlFreeUnicodeString( §ionW ); - } - return ret; -} - - -/*********************************************************************** - * SetupGetLineByIndexW (SETUPAPI.@) - */ -BOOL WINAPI SetupGetLineByIndexW( HINF hinf, PCWSTR section, DWORD index, INFCONTEXT *context ) -{ - struct inf_file *file = hinf; - int section_index; - - SetLastError( ERROR_SECTION_NOT_FOUND ); - for (file = hinf; file; file = file->next) - { - if ((section_index = find_section( file, section )) == -1) continue; - SetLastError( ERROR_LINE_NOT_FOUND ); - if (index < file->sections[section_index]->nb_lines) - { - context->Inf = hinf; - context->CurrentInf = file; - context->Section = section_index; - context->Line = index; - SetLastError( 0 ); - TRACE( "(%p,%s): returning %d/%ld\n", - hinf, debugstr_w(section), section_index, index ); - return TRUE; - } - index -= file->sections[section_index]->nb_lines; - } - TRACE( "(%p,%s) not found\n", hinf, debugstr_w(section) ); - return FALSE; -} - - -/*********************************************************************** - * SetupFindFirstLineA (SETUPAPI.@) - */ -BOOL WINAPI SetupFindFirstLineA( HINF hinf, PCSTR section, PCSTR key, INFCONTEXT *context ) -{ - UNICODE_STRING sectionW, keyW; - BOOL ret = FALSE; - - if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - } - - if (!key) ret = SetupFindFirstLineW( hinf, sectionW.Buffer, NULL, context ); - else - { - if (RtlCreateUnicodeStringFromAsciiz( &keyW, key )) - { - ret = SetupFindFirstLineW( hinf, sectionW.Buffer, keyW.Buffer, context ); - RtlFreeUnicodeString( &keyW ); - } - else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - } - RtlFreeUnicodeString( §ionW ); - return ret; -} - - -/*********************************************************************** - * SetupFindFirstLineW (SETUPAPI.@) - */ -BOOL WINAPI SetupFindFirstLineW( HINF hinf, PCWSTR section, PCWSTR key, INFCONTEXT *context ) -{ - struct inf_file *file; - int section_index; - - SetLastError( ERROR_SECTION_NOT_FOUND ); - for (file = hinf; file; file = file->next) - { - if ((section_index = find_section( file, section )) == -1) continue; - if (key) - { - INFCONTEXT ctx; - ctx.Inf = hinf; - ctx.CurrentInf = file; - ctx.Section = section_index; - ctx.Line = -1; - return SetupFindNextMatchLineW( &ctx, key, context ); - } - SetLastError( ERROR_LINE_NOT_FOUND ); /* found at least one section */ - if (file->sections[section_index]->nb_lines) - { - context->Inf = hinf; - context->CurrentInf = file; - context->Section = section_index; - context->Line = 0; - SetLastError( 0 ); - TRACE( "(%p,%s,%s): returning %d/0\n", - hinf, debugstr_w(section), debugstr_w(key), section_index ); - return TRUE; - } - } - TRACE( "(%p,%s,%s): not found\n", hinf, debugstr_w(section), debugstr_w(key) ); - return FALSE; -} - - -/*********************************************************************** - * SetupFindNextLine (SETUPAPI.@) - */ -BOOL WINAPI SetupFindNextLine( PINFCONTEXT context_in, PINFCONTEXT context_out ) -{ - struct inf_file *file = context_in->CurrentInf; - struct section *section; - - if (context_in->Section >= file->nb_sections) goto error; - - section = file->sections[context_in->Section]; - if (context_in->Line+1 < section->nb_lines) - { - if (context_out != context_in) *context_out = *context_in; - context_out->Line++; - SetLastError( 0 ); - return TRUE; - } - - /* now search the appended files */ - - for (file = file->next; file; file = file->next) - { - int section_index = find_section( file, section->name ); - if (section_index == -1) continue; - if (file->sections[section_index]->nb_lines) - { - context_out->Inf = context_in->Inf; - context_out->CurrentInf = file; - context_out->Section = section_index; - context_out->Line = 0; - SetLastError( 0 ); - return TRUE; - } - } - error: - SetLastError( ERROR_LINE_NOT_FOUND ); - return FALSE; -} - - -/*********************************************************************** - * SetupFindNextMatchLineA (SETUPAPI.@) - */ -BOOL WINAPI SetupFindNextMatchLineA( PINFCONTEXT context_in, PCSTR key, - PINFCONTEXT context_out ) -{ - UNICODE_STRING keyW; - BOOL ret = FALSE; - - if (!key) return SetupFindNextLine( context_in, context_out ); - - if (!RtlCreateUnicodeStringFromAsciiz( &keyW, key )) - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - else - { - ret = SetupFindNextMatchLineW( context_in, keyW.Buffer, context_out ); - RtlFreeUnicodeString( &keyW ); - } - return ret; -} - - -/*********************************************************************** - * SetupFindNextMatchLineW (SETUPAPI.@) - */ -BOOL WINAPI SetupFindNextMatchLineW( PINFCONTEXT context_in, PCWSTR key, - PINFCONTEXT context_out ) -{ - struct inf_file *file = context_in->CurrentInf; - struct section *section; - struct line *line; - unsigned int i; - - if (!key) return SetupFindNextLine( context_in, context_out ); - - if (context_in->Section >= file->nb_sections) goto error; - - section = file->sections[context_in->Section]; - - for (i = context_in->Line+1, line = §ion->lines[i]; i < section->nb_lines; i++, line++) - { - if (line->key_field == -1) continue; - if (!strcmpiW( key, file->fields[line->key_field].text )) - { - if (context_out != context_in) *context_out = *context_in; - context_out->Line = i; - SetLastError( 0 ); - TRACE( "(%p,%s,%s): returning %d\n", - file, debugstr_w(section->name), debugstr_w(key), i ); - return TRUE; - } - } - - /* now search the appended files */ - - for (file = file->next; file; file = file->next) - { - int section_index = find_section( file, section->name ); - if (section_index == -1) continue; - section = file->sections[section_index]; - for (i = 0, line = section->lines; i < section->nb_lines; i++, line++) - { - if (line->key_field == -1) continue; - if (!strcmpiW( key, file->fields[line->key_field].text )) - { - context_out->Inf = context_in->Inf; - context_out->CurrentInf = file; - context_out->Section = section_index; - context_out->Line = i; - SetLastError( 0 ); - TRACE( "(%p,%s,%s): returning %d/%d\n", - file, debugstr_w(section->name), debugstr_w(key), section_index, i ); - return TRUE; - } - } - } - TRACE( "(%p,%s,%s): not found\n", - context_in->CurrentInf, debugstr_w(section->name), debugstr_w(key) ); - error: - SetLastError( ERROR_LINE_NOT_FOUND ); - return FALSE; -} - - -/*********************************************************************** - * SetupGetLineTextW (SETUPAPI.@) - */ -BOOL WINAPI SetupGetLineTextW( PINFCONTEXT context, HINF hinf, PCWSTR section_name, - PCWSTR key_name, PWSTR buffer, DWORD size, PDWORD required ) -{ - struct inf_file *file; - struct line *line; - struct field *field; - int i; - DWORD total = 0; - - if (!context) - { - INFCONTEXT new_context; - if (!SetupFindFirstLineW( hinf, section_name, key_name, &new_context )) return FALSE; - file = new_context.CurrentInf; - line = get_line( file, new_context.Section, new_context.Line ); - } - else - { - file = context->CurrentInf; - if (!(line = get_line( file, context->Section, context->Line ))) - { - SetLastError( ERROR_LINE_NOT_FOUND ); - return FALSE; - } - } - - for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) - total += PARSER_string_substW( file, field->text, NULL, 0 ) + 1; - - if (required) *required = total; - if (buffer) - { - if (total > size) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } - for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) - { - unsigned int len = PARSER_string_substW( file, field->text, buffer, size ); - if (i+1 < line->nb_fields) buffer[len] = ','; - buffer += len + 1; - } - } - return TRUE; -} - - -/*********************************************************************** - * SetupGetLineTextA (SETUPAPI.@) - */ -BOOL WINAPI SetupGetLineTextA( PINFCONTEXT context, HINF hinf, PCSTR section_name, - PCSTR key_name, PSTR buffer, DWORD size, PDWORD required ) -{ - struct inf_file *file; - struct line *line; - struct field *field; - int i; - DWORD total = 0; - - if (!context) - { - INFCONTEXT new_context; - if (!SetupFindFirstLineA( hinf, section_name, key_name, &new_context )) return FALSE; - file = new_context.CurrentInf; - line = get_line( file, new_context.Section, new_context.Line ); - } - else - { - file = context->CurrentInf; - if (!(line = get_line( file, context->Section, context->Line ))) - { - SetLastError( ERROR_LINE_NOT_FOUND ); - return FALSE; - } - } - - for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) - total += PARSER_string_substA( file, field->text, NULL, 0 ) + 1; - - if (required) *required = total; - if (buffer) - { - if (total > size) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } - for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) - { - unsigned int len = PARSER_string_substA( file, field->text, buffer, size ); - if (i+1 < line->nb_fields) buffer[len] = ','; - buffer += len + 1; - } - } - return TRUE; -} - - -/*********************************************************************** - * SetupGetFieldCount (SETUPAPI.@) - */ -DWORD WINAPI SetupGetFieldCount( PINFCONTEXT context ) -{ - struct inf_file *file = context->CurrentInf; - struct line *line = get_line( file, context->Section, context->Line ); - - if (!line) return 0; - return line->nb_fields; -} - - -/*********************************************************************** - * SetupGetStringFieldA (SETUPAPI.@) - */ -BOOL WINAPI SetupGetStringFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, - DWORD size, PDWORD required ) -{ - struct inf_file *file = context->CurrentInf; - struct field *field = get_field( file, context->Section, context->Line, index ); - unsigned int len; - - SetLastError(0); - if (!field) return FALSE; - len = PARSER_string_substA( file, field->text, NULL, 0 ); - if (required) *required = len + 1; - if (buffer) - { - if (size <= len) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } - PARSER_string_substA( file, field->text, buffer, size ); - - TRACE( "context %p/%p/%d/%d index %ld returning %s\n", - context->Inf, context->CurrentInf, context->Section, context->Line, - index, debugstr_a(buffer) ); - } - return TRUE; -} - - -/*********************************************************************** - * SetupGetStringFieldW (SETUPAPI.@) - */ -BOOL WINAPI SetupGetStringFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, - DWORD size, PDWORD required ) -{ - struct inf_file *file = context->CurrentInf; - struct field *field = get_field( file, context->Section, context->Line, index ); - unsigned int len; - - SetLastError(0); - if (!field) return FALSE; - len = PARSER_string_substW( file, field->text, NULL, 0 ); - if (required) *required = len + 1; - if (buffer) - { - if (size <= len) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } - PARSER_string_substW( file, field->text, buffer, size ); - - TRACE( "context %p/%p/%d/%d index %ld returning %s\n", - context->Inf, context->CurrentInf, context->Section, context->Line, - index, debugstr_w(buffer) ); - } - return TRUE; -} - - -/*********************************************************************** - * SetupGetIntField (SETUPAPI.@) - */ -BOOL WINAPI SetupGetIntField( PINFCONTEXT context, DWORD index, PINT result ) -{ - char localbuff[20]; - char *end, *buffer = localbuff; - DWORD required; - INT res; - BOOL ret = FALSE; - - if (!SetupGetStringFieldA( context, index, localbuff, sizeof(localbuff), &required )) - { - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, required ))) return FALSE; - if (!SetupGetStringFieldA( context, index, buffer, required, NULL )) goto done; - } - res = strtol( buffer, &end, 0 ); - if (end != buffer && !*end) - { - *result = res; - ret = TRUE; - } - else SetLastError( ERROR_INVALID_DATA ); - - done: - if (buffer != localbuff) HeapFree( GetProcessHeap(), 0, buffer ); - return ret; -} - - -/*********************************************************************** - * SetupGetBinaryField (SETUPAPI.@) - */ -BOOL WINAPI SetupGetBinaryField( PINFCONTEXT context, DWORD index, BYTE *buffer, - DWORD size, LPDWORD required ) -{ - struct inf_file *file = context->CurrentInf; - struct line *line = get_line( file, context->Section, context->Line ); - struct field *field; - int i; - - if (!line) - { - SetLastError( ERROR_LINE_NOT_FOUND ); - return FALSE; - } - if (!index || index >= line->nb_fields) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - index--; /* fields start at 0 */ - if (required) *required = line->nb_fields - index; - if (!buffer) return TRUE; - if (size < line->nb_fields - index) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } - field = &file->fields[line->first_field + index]; - for (i = index; i < line->nb_fields; i++, field++) - { - const WCHAR *p; - DWORD value = 0; - for (p = field->text; *p && isxdigitW(*p); p++) - { - if ((value <<= 4) > 255) - { - SetLastError( ERROR_INVALID_DATA ); - return FALSE; - } - if (*p <= '9') value |= (*p - '0'); - else value |= (tolowerW(*p) - 'a' + 10); - } - buffer[i - index] = value; - } - if (TRACE_ON(setupapi)) - { - TRACE( "%p/%p/%d/%d index %ld returning", - context->Inf, context->CurrentInf, context->Section, context->Line, index ); - for (i = index; i < line->nb_fields; i++) TRACE( " %02x", buffer[i - index] ); - TRACE( "\n" ); - } - return TRUE; -} - - -/*********************************************************************** - * SetupGetMultiSzFieldA (SETUPAPI.@) - */ -BOOL WINAPI SetupGetMultiSzFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, - DWORD size, LPDWORD required ) -{ - struct inf_file *file = context->CurrentInf; - struct line *line = get_line( file, context->Section, context->Line ); - struct field *field; - unsigned int len; - int i; - DWORD total = 1; - - if (!line) - { - SetLastError( ERROR_LINE_NOT_FOUND ); - return FALSE; - } - if (!index || index >= line->nb_fields) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - index--; /* fields start at 0 */ - field = &file->fields[line->first_field + index]; - for (i = index; i < line->nb_fields; i++, field++) - { - if (!(len = PARSER_string_substA( file, field->text, NULL, 0 ))) break; - total += len + 1; - } - - if (required) *required = total; - if (!buffer) return TRUE; - if (total > size) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } - field = &file->fields[line->first_field + index]; - for (i = index; i < line->nb_fields; i++, field++) - { - if (!(len = PARSER_string_substA( file, field->text, buffer, size ))) break; - buffer += len + 1; - } - *buffer = 0; /* add final null */ - return TRUE; -} - - -/*********************************************************************** - * SetupGetMultiSzFieldW (SETUPAPI.@) - */ -BOOL WINAPI SetupGetMultiSzFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, - DWORD size, LPDWORD required ) -{ - struct inf_file *file = context->CurrentInf; - struct line *line = get_line( file, context->Section, context->Line ); - struct field *field; - unsigned int len; - int i; - DWORD total = 1; - - if (!line) - { - SetLastError( ERROR_LINE_NOT_FOUND ); - return FALSE; - } - if (!index || index >= line->nb_fields) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - index--; /* fields start at 0 */ - field = &file->fields[line->first_field + index]; - for (i = index; i < line->nb_fields; i++, field++) - { - if (!(len = PARSER_string_substW( file, field->text, NULL, 0 ))) break; - total += len + 1; - } - - if (required) *required = total; - if (!buffer) return TRUE; - if (total > size) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } - field = &file->fields[line->first_field + index]; - for (i = index; i < line->nb_fields; i++, field++) - { - if (!(len = PARSER_string_substW( file, field->text, buffer, size ))) break; - buffer += len + 1; - } - *buffer = 0; /* add final null */ - return TRUE; -} +/* + * INF file parsing + * + * Copyright 2002 Alexandre Julliard for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "winreg.h" +#include "winternl.h" +#include "winerror.h" +#include "setupapi.h" +#include "setupapi_private.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +#define CONTROL_Z '\x1a' +#define MAX_SECTION_NAME_LEN 255 +#define MAX_FIELD_LEN 511 /* larger fields get silently truncated */ +/* actual string limit is MAX_INF_STRING_LENGTH+1 (plus terminating null) under Windows */ +#define MAX_STRING_LEN (MAX_INF_STRING_LENGTH+1) + +/* inf file structure definitions */ + +struct field +{ + const WCHAR *text; /* field text */ +}; + +struct line +{ + int first_field; /* index of first field in field array */ + int nb_fields; /* number of fields in line */ + int key_field; /* index of field for key or -1 if no key */ +}; + +struct section +{ + const WCHAR *name; /* section name */ + unsigned int nb_lines; /* number of used lines */ + unsigned int alloc_lines; /* total number of allocated lines in array below */ + struct line lines[16]; /* lines information (grown dynamically, 16 is initial size) */ +}; + +struct inf_file +{ + struct inf_file *next; /* next appended file */ + WCHAR *strings; /* buffer for string data (section names and field values) */ + WCHAR *string_pos; /* position of next available string in buffer */ + unsigned int nb_sections; /* number of used sections */ + unsigned int alloc_sections; /* total number of allocated section pointers */ + struct section **sections; /* section pointers array */ + unsigned int nb_fields; + unsigned int alloc_fields; + struct field *fields; + int strings_section; /* index of [Strings] section or -1 if none */ + WCHAR *src_root; /* source root directory */ +}; + +/* parser definitions */ + +enum parser_state +{ + LINE_START, /* at beginning of a line */ + SECTION_NAME, /* parsing a section name */ + KEY_NAME, /* parsing a key name */ + VALUE_NAME, /* parsing a value name */ + EOL_BACKSLASH, /* backslash at end of line */ + QUOTES, /* inside quotes */ + LEADING_SPACES, /* leading spaces */ + TRAILING_SPACES, /* trailing spaces */ + COMMENT, /* inside a comment */ + NB_PARSER_STATES +}; + +struct parser +{ + const WCHAR *start; /* start position of item being parsed */ + const WCHAR *end; /* end of buffer */ + struct inf_file *file; /* file being built */ + enum parser_state state; /* current parser state */ + enum parser_state stack[4]; /* state stack */ + int stack_pos; /* current pos in stack */ + + int cur_section; /* index of section being parsed*/ + struct line *line; /* current line */ + unsigned int line_pos; /* current line position in file */ + unsigned int error; /* error code */ + unsigned int token_len; /* current token len */ + WCHAR token[MAX_FIELD_LEN+1]; /* current token */ +}; + +typedef const WCHAR * (*parser_state_func)( struct parser *parser, const WCHAR *pos ); + +/* parser state machine functions */ +static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos ); +static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos ); +static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos ); +static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos ); +static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos ); +static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos ); +static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos ); +static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos ); +static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos ); + +static const parser_state_func parser_funcs[NB_PARSER_STATES] = +{ + line_start_state, /* LINE_START */ + section_name_state, /* SECTION_NAME */ + key_name_state, /* KEY_NAME */ + value_name_state, /* VALUE_NAME */ + eol_backslash_state, /* EOL_BACKSLASH */ + quotes_state, /* QUOTES */ + leading_spaces_state, /* LEADING_SPACES */ + trailing_spaces_state, /* TRAILING_SPACES */ + comment_state /* COMMENT */ +}; + + +/* Unicode string constants */ +static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; +static const WCHAR Signature[] = {'S','i','g','n','a','t','u','r','e',0}; +static const WCHAR Chicago[] = {'$','C','h','i','c','a','g','o','$',0}; +static const WCHAR WindowsNT[] = {'$','W','i','n','d','o','w','s',' ','N','T','$',0}; +static const WCHAR Windows95[] = {'$','W','i','n','d','o','w','s',' ','9','5','$',0}; +static const WCHAR LayoutFile[] = {'L','a','y','o','u','t','F','i','l','e',0}; + +/* extend an array, allocating more memory if necessary */ +static void *grow_array( void *array, unsigned int *count, size_t elem ) +{ + void *new_array; + unsigned int new_count = *count + *count / 2; + if (new_count < 32) new_count = 32; + + if (array) + new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, array, new_count * elem ); + else + new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * elem ); + + if (new_array) + *count = new_count; + else + HeapFree( GetProcessHeap(), 0, array ); + return new_array; +} + + +/* find a section by name */ +static int find_section( struct inf_file *file, const WCHAR *name ) +{ + unsigned int i; + + for (i = 0; i < file->nb_sections; i++) + if (!strcmpiW( name, file->sections[i]->name )) return i; + return -1; +} + + +/* find a line by name */ +static struct line *find_line( struct inf_file *file, int section_index, const WCHAR *name ) +{ + struct section *section; + struct line *line; + int i; + + if (section_index < 0 || section_index >= file->nb_sections) return NULL; + section = file->sections[section_index]; + for (i = 0, line = section->lines; i < section->nb_lines; i++, line++) + { + if (line->key_field == -1) continue; + if (!strcmpiW( name, file->fields[line->key_field].text )) return line; + } + return NULL; +} + + +/* add a section to the file and return the section index */ +static int add_section( struct inf_file *file, const WCHAR *name ) +{ + struct section *section; + + if (file->nb_sections >= file->alloc_sections) + { + if (!(file->sections = grow_array( file->sections, &file->alloc_sections, + sizeof(file->sections[0]) ))) return -1; + } + if (!(section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) ))) return -1; + section->name = name; + section->nb_lines = 0; + section->alloc_lines = sizeof(section->lines)/sizeof(section->lines[0]); + file->sections[file->nb_sections] = section; + return file->nb_sections++; +} + + +/* add a line to a given section */ +static struct line *add_line( struct inf_file *file, int section_index ) +{ + struct section *section; + struct line *line; + + assert( section_index >= 0 && section_index < file->nb_sections ); + + section = file->sections[section_index]; + if (section->nb_lines == section->alloc_lines) /* need to grow the section */ + { + int size = sizeof(*section) - sizeof(section->lines) + 2*section->alloc_lines*sizeof(*line); + if (!(section = HeapReAlloc( GetProcessHeap(), 0, section, size ))) return NULL; + section->alloc_lines *= 2; + file->sections[section_index] = section; + } + line = §ion->lines[section->nb_lines++]; + line->first_field = file->nb_fields; + line->nb_fields = 0; + line->key_field = -1; + return line; +} + + +/* retrieve a given line from section/line index */ +inline static struct line *get_line( struct inf_file *file, unsigned int section_index, + unsigned int line_index ) +{ + struct section *section; + + if (section_index >= file->nb_sections) return NULL; + section = file->sections[section_index]; + if (line_index >= section->nb_lines) return NULL; + return §ion->lines[line_index]; +} + + +/* retrieve a given field from section/line/field index */ +static struct field *get_field( struct inf_file *file, int section_index, int line_index, + int field_index ) +{ + struct line *line = get_line( file, section_index, line_index ); + + if (!line) return NULL; + if (!field_index) /* get the key */ + { + if (line->key_field == -1) return NULL; + return &file->fields[line->key_field]; + } + field_index--; + if (field_index >= line->nb_fields) return NULL; + return &file->fields[line->first_field + field_index]; +} + + +/* allocate a new field, growing the array if necessary */ +static struct field *add_field( struct inf_file *file, const WCHAR *text ) +{ + struct field *field; + + if (file->nb_fields >= file->alloc_fields) + { + if (!(file->fields = grow_array( file->fields, &file->alloc_fields, + sizeof(file->fields[0]) ))) return NULL; + } + field = &file->fields[file->nb_fields++]; + field->text = text; + return field; +} + + +/* retrieve the string substitution for a directory id */ +static const WCHAR *get_dirid_subst( int dirid, unsigned int *len ) +{ + extern const WCHAR *DIRID_get_string( HINF hinf, int dirid ); + const WCHAR *ret = DIRID_get_string( 0, dirid ); + if (ret) *len = strlenW(ret); + return ret; +} + + +/* retrieve the string substitution for a given string, or NULL if not found */ +/* if found, len is set to the substitution length */ +static const WCHAR *get_string_subst( struct inf_file *file, const WCHAR *str, unsigned int *len ) +{ + static const WCHAR percent = '%'; + + struct section *strings_section; + struct line *line; + struct field *field; + unsigned int i; + int dirid; + WCHAR *dirid_str, *end; + const WCHAR *ret = NULL; + + if (!*len) /* empty string (%%) is replaced by single percent */ + { + *len = 1; + return &percent; + } + if (file->strings_section == -1) goto not_found; + strings_section = file->sections[file->strings_section]; + for (i = 0, line = strings_section->lines; i < strings_section->nb_lines; i++, line++) + { + if (line->key_field == -1) continue; + if (strncmpiW( str, file->fields[line->key_field].text, *len )) continue; + if (!file->fields[line->key_field].text[*len]) break; + } + if (i == strings_section->nb_lines || !line->nb_fields) goto not_found; + field = &file->fields[line->first_field]; + *len = strlenW( field->text ); + return field->text; + + not_found: /* check for integer id */ + if ((dirid_str = HeapAlloc( GetProcessHeap(), 0, (*len+1) * sizeof(WCHAR) ))) + { + memcpy( dirid_str, str, *len * sizeof(WCHAR) ); + dirid_str[*len] = 0; + dirid = strtolW( dirid_str, &end, 10 ); + if (!*end) ret = get_dirid_subst( dirid, len ); + HeapFree( GetProcessHeap(), 0, dirid_str ); + return ret; + } + return NULL; +} + + +/* do string substitutions on the specified text */ +/* the buffer is assumed to be large enough */ +/* returns necessary length not including terminating null */ +unsigned int PARSER_string_substW( struct inf_file *file, const WCHAR *text, WCHAR *buffer, + unsigned int size ) +{ + const WCHAR *start, *subst, *p; + unsigned int len, total = 0; + int inside = 0; + + if (!buffer) size = MAX_STRING_LEN + 1; + for (p = start = text; *p; p++) + { + if (*p != '%') continue; + inside = !inside; + if (inside) /* start of a %xx% string */ + { + len = p - start; + if (len > size - 1) len = size - 1; + if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) ); + total += len; + size -= len; + start = p; + } + else /* end of the %xx% string, find substitution */ + { + len = p - start - 1; + subst = get_string_subst( file, start + 1, &len ); + if (!subst) + { + subst = start; + len = p - start + 1; + } + if (len > size - 1) len = size - 1; + if (buffer) memcpy( buffer + total, subst, len * sizeof(WCHAR) ); + total += len; + size -= len; + start = p + 1; + } + } + + if (start != p) /* unfinished string, copy it */ + { + len = p - start; + if (len > size - 1) len = size - 1; + if (buffer) memcpy( buffer + total, start, len * sizeof(WCHAR) ); + total += len; + } + if (buffer && size) buffer[total] = 0; + return total; +} + + +/* do string substitutions on the specified text */ +/* the buffer is assumed to be large enough */ +/* returns necessary length not including terminating null */ +unsigned int PARSER_string_substA( struct inf_file *file, const WCHAR *text, char *buffer, + unsigned int size ) +{ + WCHAR buffW[MAX_STRING_LEN+1]; + DWORD ret; + + unsigned int len = PARSER_string_substW( file, text, buffW, sizeof(buffW)/sizeof(WCHAR) ); + if (!buffer) RtlUnicodeToMultiByteSize( &ret, buffW, len * sizeof(WCHAR) ); + else + { + RtlUnicodeToMultiByteN( buffer, size-1, &ret, buffW, len * sizeof(WCHAR) ); + buffer[ret] = 0; + } + return ret; +} + + +/* push some string data into the strings buffer */ +static WCHAR *push_string( struct inf_file *file, const WCHAR *string ) +{ + WCHAR *ret = file->string_pos; + strcpyW( ret, string ); + file->string_pos += strlenW( ret ) + 1; + return ret; +} + + +/* push the current state on the parser stack */ +inline static void push_state( struct parser *parser, enum parser_state state ) +{ + assert( parser->stack_pos < sizeof(parser->stack)/sizeof(parser->stack[0]) ); + parser->stack[parser->stack_pos++] = state; +} + + +/* pop the current state */ +inline static void pop_state( struct parser *parser ) +{ + assert( parser->stack_pos ); + parser->state = parser->stack[--parser->stack_pos]; +} + + +/* set the parser state and return the previous one */ +inline static enum parser_state set_state( struct parser *parser, enum parser_state state ) +{ + enum parser_state ret = parser->state; + parser->state = state; + return ret; +} + + +/* check if the pointer points to an end of file */ +inline static int is_eof( struct parser *parser, const WCHAR *ptr ) +{ + return (ptr >= parser->end || *ptr == CONTROL_Z); +} + + +/* check if the pointer points to an end of line */ +inline static int is_eol( struct parser *parser, const WCHAR *ptr ) +{ + return (ptr >= parser->end || *ptr == CONTROL_Z || *ptr == '\n'); +} + + +/* push data from current token start up to pos into the current token */ +static int push_token( struct parser *parser, const WCHAR *pos ) +{ + int len = pos - parser->start; + const WCHAR *src = parser->start; + WCHAR *dst = parser->token + parser->token_len; + + if (len > MAX_FIELD_LEN - parser->token_len) len = MAX_FIELD_LEN - parser->token_len; + + parser->token_len += len; + for ( ; len > 0; len--, dst++, src++) *dst = *src ? *src : ' '; + *dst = 0; + parser->start = pos; + return 0; +} + + +/* add a section with the current token as name */ +static int add_section_from_token( struct parser *parser ) +{ + int section_index; + + if (parser->token_len > MAX_SECTION_NAME_LEN) + { + parser->error = ERROR_SECTION_NAME_TOO_LONG; + return -1; + } + if ((section_index = find_section( parser->file, parser->token )) == -1) + { + /* need to create a new one */ + const WCHAR *name = push_string( parser->file, parser->token ); + if ((section_index = add_section( parser->file, name )) == -1) + { + parser->error = ERROR_NOT_ENOUGH_MEMORY; + return -1; + } + } + parser->token_len = 0; + parser->cur_section = section_index; + return section_index; +} + + +/* add a field containing the current token to the current line */ +static struct field *add_field_from_token( struct parser *parser, int is_key ) +{ + struct field *field; + WCHAR *text; + + if (!parser->line) /* need to start a new line */ + { + if (parser->cur_section == -1) /* got a line before the first section */ + { + parser->error = ERROR_WRONG_INF_STYLE; + return NULL; + } + if (!(parser->line = add_line( parser->file, parser->cur_section ))) goto error; + } + else assert(!is_key); + + text = push_string( parser->file, parser->token ); + if ((field = add_field( parser->file, text ))) + { + if (!is_key) parser->line->nb_fields++; + else + { + /* replace first field by key field */ + parser->line->key_field = parser->line->first_field; + parser->line->first_field++; + } + parser->token_len = 0; + return field; + } + error: + parser->error = ERROR_NOT_ENOUGH_MEMORY; + return NULL; +} + + +/* close the current line and prepare for parsing a new one */ +static void close_current_line( struct parser *parser ) +{ + struct line *cur_line = parser->line; + + if (cur_line) + { + /* if line has a single field and no key, the field is the key too */ + if (cur_line->nb_fields == 1 && cur_line->key_field == -1) + cur_line->key_field = cur_line->first_field; + } + parser->line = NULL; +} + + +/* handler for parser LINE_START state */ +static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p; + + for (p = pos; !is_eof( parser, p ); p++) + { + switch(*p) + { + case '\n': + parser->line_pos++; + close_current_line( parser ); + break; + case ';': + push_state( parser, LINE_START ); + set_state( parser, COMMENT ); + return p + 1; + case '[': + parser->start = p + 1; + set_state( parser, SECTION_NAME ); + return p + 1; + default: + if (!isspaceW(*p)) + { + parser->start = p; + set_state( parser, KEY_NAME ); + return p; + } + break; + } + } + close_current_line( parser ); + return NULL; +} + + +/* handler for parser SECTION_NAME state */ +static const WCHAR *section_name_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p; + + for (p = pos; !is_eol( parser, p ); p++) + { + if (*p == ']') + { + push_token( parser, p ); + if (add_section_from_token( parser ) == -1) return NULL; + push_state( parser, LINE_START ); + set_state( parser, COMMENT ); /* ignore everything else on the line */ + return p + 1; + } + } + parser->error = ERROR_BAD_SECTION_NAME_LINE; /* unfinished section name */ + return NULL; +} + + +/* handler for parser KEY_NAME state */ +static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p, *token_end = parser->start; + + for (p = pos; !is_eol( parser, p ); p++) + { + if (*p == ',') break; + switch(*p) + { + + case '=': + push_token( parser, token_end ); + if (!add_field_from_token( parser, 1 )) return NULL; + parser->start = p + 1; + push_state( parser, VALUE_NAME ); + set_state( parser, LEADING_SPACES ); + return p + 1; + case ';': + push_token( parser, token_end ); + if (!add_field_from_token( parser, 0 )) return NULL; + push_state( parser, LINE_START ); + set_state( parser, COMMENT ); + return p + 1; + case '"': + push_token( parser, token_end ); + parser->start = p + 1; + push_state( parser, KEY_NAME ); + set_state( parser, QUOTES ); + return p + 1; + case '\\': + push_token( parser, token_end ); + parser->start = p; + push_state( parser, KEY_NAME ); + set_state( parser, EOL_BACKSLASH ); + return p; + default: + if (!isspaceW(*p)) token_end = p + 1; + else + { + push_token( parser, p ); + push_state( parser, KEY_NAME ); + set_state( parser, TRAILING_SPACES ); + return p; + } + break; + } + } + push_token( parser, token_end ); + set_state( parser, VALUE_NAME ); + return p; +} + + +/* handler for parser VALUE_NAME state */ +static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p, *token_end = parser->start; + + for (p = pos; !is_eol( parser, p ); p++) + { + switch(*p) + { + case ';': + push_token( parser, token_end ); + if (!add_field_from_token( parser, 0 )) return NULL; + push_state( parser, LINE_START ); + set_state( parser, COMMENT ); + return p + 1; + case ',': + push_token( parser, token_end ); + if (!add_field_from_token( parser, 0 )) return NULL; + parser->start = p + 1; + push_state( parser, VALUE_NAME ); + set_state( parser, LEADING_SPACES ); + return p + 1; + case '"': + push_token( parser, token_end ); + parser->start = p + 1; + push_state( parser, VALUE_NAME ); + set_state( parser, QUOTES ); + return p + 1; + case '\\': + push_token( parser, token_end ); + parser->start = p; + push_state( parser, VALUE_NAME ); + set_state( parser, EOL_BACKSLASH ); + return p; + default: + if (!isspaceW(*p)) token_end = p + 1; + else + { + push_token( parser, p ); + push_state( parser, VALUE_NAME ); + set_state( parser, TRAILING_SPACES ); + return p; + } + break; + } + } + push_token( parser, token_end ); + if (!add_field_from_token( parser, 0 )) return NULL; + set_state( parser, LINE_START ); + return p; +} + + +/* handler for parser EOL_BACKSLASH state */ +static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p; + + for (p = pos; !is_eof( parser, p ); p++) + { + switch(*p) + { + case '\n': + parser->line_pos++; + parser->start = p + 1; + set_state( parser, LEADING_SPACES ); + return p + 1; + case '\\': + continue; + case ';': + push_state( parser, EOL_BACKSLASH ); + set_state( parser, COMMENT ); + return p + 1; + default: + if (isspaceW(*p)) continue; + push_token( parser, p ); + pop_state( parser ); + return p; + } + } + parser->start = p; + pop_state( parser ); + return p; +} + + +/* handler for parser QUOTES state */ +static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p, *token_end = parser->start; + + for (p = pos; !is_eol( parser, p ); p++) + { + if (*p == '"') + { + if (p+1 < parser->end && p[1] == '"') /* double quotes */ + { + push_token( parser, p + 1 ); + parser->start = token_end = p + 2; + p++; + } + else /* end of quotes */ + { + push_token( parser, p ); + parser->start = p + 1; + pop_state( parser ); + return p + 1; + } + } + } + push_token( parser, p ); + pop_state( parser ); + return p; +} + + +/* handler for parser LEADING_SPACES state */ +static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p; + + for (p = pos; !is_eol( parser, p ); p++) + { + if (*p == '\\') + { + parser->start = p; + set_state( parser, EOL_BACKSLASH ); + return p; + } + if (!isspaceW(*p)) break; + } + parser->start = p; + pop_state( parser ); + return p; +} + + +/* handler for parser TRAILING_SPACES state */ +static const WCHAR *trailing_spaces_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p; + + for (p = pos; !is_eol( parser, p ); p++) + { + if (*p == '\\') + { + set_state( parser, EOL_BACKSLASH ); + return p; + } + if (!isspaceW(*p)) break; + } + pop_state( parser ); + return p; +} + + +/* handler for parser COMMENT state */ +static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos ) +{ + const WCHAR *p = pos; + + while (!is_eol( parser, p )) p++; + pop_state( parser ); + return p; +} + + +/* parse a complete buffer */ +static DWORD parse_buffer( struct inf_file *file, const WCHAR *buffer, const WCHAR *end, + UINT *error_line ) +{ + static const WCHAR Strings[] = {'S','t','r','i','n','g','s',0}; + + struct parser parser; + const WCHAR *pos = buffer; + + parser.start = buffer; + parser.end = end; + parser.file = file; + parser.line = NULL; + parser.state = LINE_START; + parser.stack_pos = 0; + parser.cur_section = -1; + parser.line_pos = 1; + parser.error = 0; + parser.token_len = 0; + + /* parser main loop */ + while (pos) pos = (parser_funcs[parser.state])( &parser, pos ); + + /* trim excess buffer space */ + if (file->alloc_sections > file->nb_sections) + { + file->sections = HeapReAlloc( GetProcessHeap(), 0, file->sections, + file->nb_sections * sizeof(file->sections[0]) ); + file->alloc_sections = file->nb_sections; + } + if (file->alloc_fields > file->nb_fields) + { + file->fields = HeapReAlloc( GetProcessHeap(), 0, file->fields, + file->nb_fields * sizeof(file->fields[0]) ); + file->alloc_fields = file->nb_fields; + } + file->strings = HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, file->strings, + (file->string_pos - file->strings) * sizeof(WCHAR) ); + + if (parser.error) + { + if (error_line) *error_line = parser.line_pos; + return parser.error; + } + + /* find the [strings] section */ + file->strings_section = find_section( file, Strings ); + return 0; +} + + +/* append a child INF file to its parent list, in a thread-safe manner */ +static void append_inf_file( struct inf_file *parent, struct inf_file *child ) +{ + struct inf_file **ppnext = &parent->next; + child->next = NULL; + + for (;;) + { + struct inf_file *next = InterlockedCompareExchangePointer( (void **)ppnext, child, NULL ); + if (!next) return; + ppnext = &next->next; + } +} + + +/*********************************************************************** + * parse_file + * + * parse an INF file. + */ +static struct inf_file *parse_file( HANDLE handle, const WCHAR *class, UINT *error_line ) +{ + void *buffer; + DWORD err = 0; + struct inf_file *file; + + DWORD size = GetFileSize( handle, NULL ); + HANDLE mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, size, NULL ); + if (!mapping) return NULL; + buffer = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, size ); + NtClose( mapping ); + if (!buffer) return NULL; + + if (class) FIXME( "class %s not supported yet\n", debugstr_w(class) ); + + if (!(file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*file) ))) + { + err = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + /* we won't need more strings space than the size of the file, + * so we can preallocate it here + */ + if (!(file->strings = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) + { + err = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + file->string_pos = file->strings; + file->strings_section = -1; + + if (!RtlIsTextUnicode( buffer, size, NULL )) + { + WCHAR *new_buff = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ); + if (new_buff) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, buffer, size, new_buff, + size * sizeof(WCHAR) ); + err = parse_buffer( file, new_buff, new_buff + len, error_line ); + HeapFree( GetProcessHeap(), 0, new_buff ); + } + } + else err = parse_buffer( file, buffer, (WCHAR *)((char *)buffer + size), error_line ); + + if (!err) /* now check signature */ + { + int version_index = find_section( file, Version ); + if (version_index != -1) + { + struct line *line = find_line( file, version_index, Signature ); + if (line && line->nb_fields > 0) + { + struct field *field = file->fields + line->first_field; + if (!strcmpiW( field->text, Chicago )) goto done; + if (!strcmpiW( field->text, WindowsNT )) goto done; + if (!strcmpiW( field->text, Windows95 )) goto done; + } + } + err = ERROR_WRONG_INF_STYLE; + } + + done: + UnmapViewOfFile( buffer ); + if (err) + { + HeapFree( GetProcessHeap(), 0, file ); + SetLastError( err ); + file = NULL; + } + return file; +} + + +/*********************************************************************** + * PARSER_get_src_root + * + * Retrieve the source directory of an inf file. + */ +const WCHAR *PARSER_get_src_root( HINF hinf ) +{ + struct inf_file *file = hinf; + return file->src_root; +} + + +/*********************************************************************** + * PARSER_get_dest_dir + * + * retrieve a destination dir of the form "dirid,relative_path" in the given entry. + * returned buffer must be freed by caller. + */ +WCHAR *PARSER_get_dest_dir( INFCONTEXT *context ) +{ + const WCHAR *dir; + WCHAR *ptr, *ret; + INT dirid; + DWORD len1, len2; + + if (!SetupGetIntField( context, 1, &dirid )) return NULL; + if (!(dir = DIRID_get_string( context->Inf, dirid ))) return NULL; + len1 = strlenW(dir) + 1; + if (!SetupGetStringFieldW( context, 2, NULL, 0, &len2 )) len2 = 0; + if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len1+len2) * sizeof(WCHAR) ))) return NULL; + strcpyW( ret, dir ); + ptr = ret + strlenW(ret); + if (len2 && ptr > ret && ptr[-1] != '\\') *ptr++ = '\\'; + if (!SetupGetStringFieldW( context, 2, ptr, len2, NULL )) *ptr = 0; + return ret; +} + + +/*********************************************************************** + * SetupOpenInfFileA (SETUPAPI.@) + */ +HINF WINAPI SetupOpenInfFileA( PCSTR name, PCSTR class, DWORD style, UINT *error ) +{ + UNICODE_STRING nameW, classW; + HINF ret = (HINF)INVALID_HANDLE_VALUE; + + classW.Buffer = NULL; + if (class && !RtlCreateUnicodeStringFromAsciiz( &classW, class )) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return ret; + } + if (RtlCreateUnicodeStringFromAsciiz( &nameW, name )) + { + ret = SetupOpenInfFileW( nameW.Buffer, classW.Buffer, style, error ); + RtlFreeUnicodeString( &nameW ); + } + RtlFreeUnicodeString( &classW ); + return ret; +} + + +/*********************************************************************** + * SetupOpenInfFileW (SETUPAPI.@) + */ +HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR class, DWORD style, UINT *error ) +{ + struct inf_file *file = NULL; + HANDLE handle; + WCHAR *path, *p; + UINT len; + + if (strchrW( name, '\\' ) || strchrW( name, '/' )) + { + if (!(len = GetFullPathNameW( name, 0, NULL, NULL ))) return (HINF)INVALID_HANDLE_VALUE; + if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return (HINF)INVALID_HANDLE_VALUE; + } + GetFullPathNameW( name, len, path, NULL ); + handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); + } + else /* try Windows directory */ + { + static const WCHAR Inf[] = {'\\','i','n','f','\\',0}; + static const WCHAR System32[] = {'\\','s','y','s','t','e','m','3','2','\\',0}; + + len = GetWindowsDirectoryW( NULL, 0 ) + strlenW(name) + 12; + if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return (HINF)INVALID_HANDLE_VALUE; + } + GetWindowsDirectoryW( path, len ); + p = path + strlenW(path); + strcpyW( p, Inf ); + strcatW( p, name ); + handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); + if (handle == INVALID_HANDLE_VALUE) + { + strcpyW( p, System32 ); + strcatW( p, name ); + handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); + } + } + + if (handle != INVALID_HANDLE_VALUE) + { + file = parse_file( handle, class, error ); + CloseHandle( handle ); + } + if (!file) + { + HeapFree( GetProcessHeap(), 0, path ); + return (HINF)INVALID_HANDLE_VALUE; + } + TRACE( "%s -> %p\n", debugstr_w(path), file ); + file->src_root = path; + if ((p = strrchrW( path, '\\' ))) p[1] = 0; /* remove file name */ + SetLastError( 0 ); + return (HINF)file; +} + + +/*********************************************************************** + * SetupOpenAppendInfFileA (SETUPAPI.@) + */ +BOOL WINAPI SetupOpenAppendInfFileA( PCSTR name, HINF parent_hinf, UINT *error ) +{ + HINF child_hinf; + + if (!name) return SetupOpenAppendInfFileW( NULL, parent_hinf, error ); + child_hinf = SetupOpenInfFileA( name, NULL, INF_STYLE_WIN4, error ); + if (child_hinf == (HINF)INVALID_HANDLE_VALUE) return FALSE; + append_inf_file( parent_hinf, child_hinf ); + TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_a(name), child_hinf ); + return TRUE; +} + + +/*********************************************************************** + * SetupOpenAppendInfFileW (SETUPAPI.@) + */ +BOOL WINAPI SetupOpenAppendInfFileW( PCWSTR name, HINF parent_hinf, UINT *error ) +{ + HINF child_hinf; + + if (!name) + { + INFCONTEXT context; + WCHAR filename[MAX_PATH]; + int idx = 1; + + if (!SetupFindFirstLineW( parent_hinf, Version, LayoutFile, &context )) return FALSE; + while (SetupGetStringFieldW( &context, idx++, filename, + sizeof(filename)/sizeof(WCHAR), NULL )) + { + child_hinf = SetupOpenInfFileW( filename, NULL, INF_STYLE_WIN4, error ); + if (child_hinf == (HINF)INVALID_HANDLE_VALUE) return FALSE; + append_inf_file( parent_hinf, child_hinf ); + TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_w(filename), child_hinf ); + } + return TRUE; + } + child_hinf = SetupOpenInfFileW( name, NULL, INF_STYLE_WIN4, error ); + if (child_hinf == (HINF)INVALID_HANDLE_VALUE) return FALSE; + append_inf_file( parent_hinf, child_hinf ); + TRACE( "%p: appended %s (%p)\n", parent_hinf, debugstr_w(name), child_hinf ); + return TRUE; +} + + +/*********************************************************************** + * SetupOpenMasterInf (SETUPAPI.@) + */ +HINF WINAPI SetupOpenMasterInf( VOID ) +{ + static const WCHAR Layout[] = {'\\','i','n','f','\\', 'l', 'a', 'y', 'o', 'u', 't', '.', 'i', 'n', 'f', 0}; + WCHAR Buffer[MAX_PATH]; + + GetWindowsDirectoryW( Buffer, MAX_PATH ); + strcatW( Buffer, Layout ); + return SetupOpenInfFileW( Buffer, NULL, INF_STYLE_WIN4, NULL); +} + + + +/*********************************************************************** + * SetupCloseInfFile (SETUPAPI.@) + */ +void WINAPI SetupCloseInfFile( HINF hinf ) +{ + struct inf_file *file = hinf; + unsigned int i; + + for (i = 0; i < file->nb_sections; i++) HeapFree( GetProcessHeap(), 0, file->sections[i] ); + HeapFree( GetProcessHeap(), 0, file->src_root ); + HeapFree( GetProcessHeap(), 0, file->sections ); + HeapFree( GetProcessHeap(), 0, file->fields ); + HeapFree( GetProcessHeap(), 0, file->strings ); + HeapFree( GetProcessHeap(), 0, file ); +} + + +/*********************************************************************** + * SetupGetLineCountA (SETUPAPI.@) + */ +LONG WINAPI SetupGetLineCountA( HINF hinf, PCSTR name ) +{ + UNICODE_STRING sectionW; + LONG ret = -1; + + if (!RtlCreateUnicodeStringFromAsciiz( §ionW, name )) + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + else + { + ret = SetupGetLineCountW( hinf, sectionW.Buffer ); + RtlFreeUnicodeString( §ionW ); + } + return ret; +} + + +/*********************************************************************** + * SetupGetLineCountW (SETUPAPI.@) + */ +LONG WINAPI SetupGetLineCountW( HINF hinf, PCWSTR section ) +{ + struct inf_file *file = hinf; + int section_index; + LONG ret = -1; + + for (file = hinf; file; file = file->next) + { + if ((section_index = find_section( file, section )) == -1) continue; + if (ret == -1) ret = 0; + ret += file->sections[section_index]->nb_lines; + } + TRACE( "(%p,%s) returning %ld\n", hinf, debugstr_w(section), ret ); + SetLastError( (ret == -1) ? ERROR_SECTION_NOT_FOUND : 0 ); + return ret; +} + + +/*********************************************************************** + * SetupGetLineByIndexA (SETUPAPI.@) + */ +BOOL WINAPI SetupGetLineByIndexA( HINF hinf, PCSTR section, DWORD index, INFCONTEXT *context ) +{ + UNICODE_STRING sectionW; + BOOL ret = FALSE; + + if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + else + { + ret = SetupGetLineByIndexW( hinf, sectionW.Buffer, index, context ); + RtlFreeUnicodeString( §ionW ); + } + return ret; +} + + +/*********************************************************************** + * SetupGetLineByIndexW (SETUPAPI.@) + */ +BOOL WINAPI SetupGetLineByIndexW( HINF hinf, PCWSTR section, DWORD index, INFCONTEXT *context ) +{ + struct inf_file *file = hinf; + int section_index; + + SetLastError( ERROR_SECTION_NOT_FOUND ); + for (file = hinf; file; file = file->next) + { + if ((section_index = find_section( file, section )) == -1) continue; + SetLastError( ERROR_LINE_NOT_FOUND ); + if (index < file->sections[section_index]->nb_lines) + { + context->Inf = hinf; + context->CurrentInf = file; + context->Section = section_index; + context->Line = index; + SetLastError( 0 ); + TRACE( "(%p,%s): returning %d/%ld\n", + hinf, debugstr_w(section), section_index, index ); + return TRUE; + } + index -= file->sections[section_index]->nb_lines; + } + TRACE( "(%p,%s) not found\n", hinf, debugstr_w(section) ); + return FALSE; +} + + +/*********************************************************************** + * SetupFindFirstLineA (SETUPAPI.@) + */ +BOOL WINAPI SetupFindFirstLineA( HINF hinf, PCSTR section, PCSTR key, INFCONTEXT *context ) +{ + UNICODE_STRING sectionW, keyW; + BOOL ret = FALSE; + + if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + if (!key) ret = SetupFindFirstLineW( hinf, sectionW.Buffer, NULL, context ); + else + { + if (RtlCreateUnicodeStringFromAsciiz( &keyW, key )) + { + ret = SetupFindFirstLineW( hinf, sectionW.Buffer, keyW.Buffer, context ); + RtlFreeUnicodeString( &keyW ); + } + else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + } + RtlFreeUnicodeString( §ionW ); + return ret; +} + + +/*********************************************************************** + * SetupFindFirstLineW (SETUPAPI.@) + */ +BOOL WINAPI SetupFindFirstLineW( HINF hinf, PCWSTR section, PCWSTR key, INFCONTEXT *context ) +{ + struct inf_file *file; + int section_index; + + SetLastError( ERROR_SECTION_NOT_FOUND ); + for (file = hinf; file; file = file->next) + { + if ((section_index = find_section( file, section )) == -1) continue; + if (key) + { + INFCONTEXT ctx; + ctx.Inf = hinf; + ctx.CurrentInf = file; + ctx.Section = section_index; + ctx.Line = -1; + return SetupFindNextMatchLineW( &ctx, key, context ); + } + SetLastError( ERROR_LINE_NOT_FOUND ); /* found at least one section */ + if (file->sections[section_index]->nb_lines) + { + context->Inf = hinf; + context->CurrentInf = file; + context->Section = section_index; + context->Line = 0; + SetLastError( 0 ); + TRACE( "(%p,%s,%s): returning %d/0\n", + hinf, debugstr_w(section), debugstr_w(key), section_index ); + return TRUE; + } + } + TRACE( "(%p,%s,%s): not found\n", hinf, debugstr_w(section), debugstr_w(key) ); + return FALSE; +} + + +/*********************************************************************** + * SetupFindNextLine (SETUPAPI.@) + */ +BOOL WINAPI SetupFindNextLine( PINFCONTEXT context_in, PINFCONTEXT context_out ) +{ + struct inf_file *file = context_in->CurrentInf; + struct section *section; + + if (context_in->Section >= file->nb_sections) goto error; + + section = file->sections[context_in->Section]; + if (context_in->Line+1 < section->nb_lines) + { + if (context_out != context_in) *context_out = *context_in; + context_out->Line++; + SetLastError( 0 ); + return TRUE; + } + + /* now search the appended files */ + + for (file = file->next; file; file = file->next) + { + int section_index = find_section( file, section->name ); + if (section_index == -1) continue; + if (file->sections[section_index]->nb_lines) + { + context_out->Inf = context_in->Inf; + context_out->CurrentInf = file; + context_out->Section = section_index; + context_out->Line = 0; + SetLastError( 0 ); + return TRUE; + } + } + error: + SetLastError( ERROR_LINE_NOT_FOUND ); + return FALSE; +} + + +/*********************************************************************** + * SetupFindNextMatchLineA (SETUPAPI.@) + */ +BOOL WINAPI SetupFindNextMatchLineA( PINFCONTEXT context_in, PCSTR key, + PINFCONTEXT context_out ) +{ + UNICODE_STRING keyW; + BOOL ret = FALSE; + + if (!key) return SetupFindNextLine( context_in, context_out ); + + if (!RtlCreateUnicodeStringFromAsciiz( &keyW, key )) + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + else + { + ret = SetupFindNextMatchLineW( context_in, keyW.Buffer, context_out ); + RtlFreeUnicodeString( &keyW ); + } + return ret; +} + + +/*********************************************************************** + * SetupFindNextMatchLineW (SETUPAPI.@) + */ +BOOL WINAPI SetupFindNextMatchLineW( PINFCONTEXT context_in, PCWSTR key, + PINFCONTEXT context_out ) +{ + struct inf_file *file = context_in->CurrentInf; + struct section *section; + struct line *line; + unsigned int i; + + if (!key) return SetupFindNextLine( context_in, context_out ); + + if (context_in->Section >= file->nb_sections) goto error; + + section = file->sections[context_in->Section]; + + for (i = context_in->Line+1, line = §ion->lines[i]; i < section->nb_lines; i++, line++) + { + if (line->key_field == -1) continue; + if (!strcmpiW( key, file->fields[line->key_field].text )) + { + if (context_out != context_in) *context_out = *context_in; + context_out->Line = i; + SetLastError( 0 ); + TRACE( "(%p,%s,%s): returning %d\n", + file, debugstr_w(section->name), debugstr_w(key), i ); + return TRUE; + } + } + + /* now search the appended files */ + + for (file = file->next; file; file = file->next) + { + int section_index = find_section( file, section->name ); + if (section_index == -1) continue; + section = file->sections[section_index]; + for (i = 0, line = section->lines; i < section->nb_lines; i++, line++) + { + if (line->key_field == -1) continue; + if (!strcmpiW( key, file->fields[line->key_field].text )) + { + context_out->Inf = context_in->Inf; + context_out->CurrentInf = file; + context_out->Section = section_index; + context_out->Line = i; + SetLastError( 0 ); + TRACE( "(%p,%s,%s): returning %d/%d\n", + file, debugstr_w(section->name), debugstr_w(key), section_index, i ); + return TRUE; + } + } + } + TRACE( "(%p,%s,%s): not found\n", + context_in->CurrentInf, debugstr_w(section->name), debugstr_w(key) ); + error: + SetLastError( ERROR_LINE_NOT_FOUND ); + return FALSE; +} + + +/*********************************************************************** + * SetupGetLineTextW (SETUPAPI.@) + */ +BOOL WINAPI SetupGetLineTextW( PINFCONTEXT context, HINF hinf, PCWSTR section_name, + PCWSTR key_name, PWSTR buffer, DWORD size, PDWORD required ) +{ + struct inf_file *file; + struct line *line; + struct field *field; + int i; + DWORD total = 0; + + if (!context) + { + INFCONTEXT new_context; + if (!SetupFindFirstLineW( hinf, section_name, key_name, &new_context )) return FALSE; + file = new_context.CurrentInf; + line = get_line( file, new_context.Section, new_context.Line ); + } + else + { + file = context->CurrentInf; + if (!(line = get_line( file, context->Section, context->Line ))) + { + SetLastError( ERROR_LINE_NOT_FOUND ); + return FALSE; + } + } + + for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) + total += PARSER_string_substW( file, field->text, NULL, 0 ) + 1; + + if (required) *required = total; + if (buffer) + { + if (total > size) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) + { + unsigned int len = PARSER_string_substW( file, field->text, buffer, size ); + if (i+1 < line->nb_fields) buffer[len] = ','; + buffer += len + 1; + } + } + return TRUE; +} + + +/*********************************************************************** + * SetupGetLineTextA (SETUPAPI.@) + */ +BOOL WINAPI SetupGetLineTextA( PINFCONTEXT context, HINF hinf, PCSTR section_name, + PCSTR key_name, PSTR buffer, DWORD size, PDWORD required ) +{ + struct inf_file *file; + struct line *line; + struct field *field; + int i; + DWORD total = 0; + + if (!context) + { + INFCONTEXT new_context; + if (!SetupFindFirstLineA( hinf, section_name, key_name, &new_context )) return FALSE; + file = new_context.CurrentInf; + line = get_line( file, new_context.Section, new_context.Line ); + } + else + { + file = context->CurrentInf; + if (!(line = get_line( file, context->Section, context->Line ))) + { + SetLastError( ERROR_LINE_NOT_FOUND ); + return FALSE; + } + } + + for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) + total += PARSER_string_substA( file, field->text, NULL, 0 ) + 1; + + if (required) *required = total; + if (buffer) + { + if (total > size) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) + { + unsigned int len = PARSER_string_substA( file, field->text, buffer, size ); + if (i+1 < line->nb_fields) buffer[len] = ','; + buffer += len + 1; + } + } + return TRUE; +} + + +/*********************************************************************** + * SetupGetFieldCount (SETUPAPI.@) + */ +DWORD WINAPI SetupGetFieldCount( PINFCONTEXT context ) +{ + struct inf_file *file = context->CurrentInf; + struct line *line = get_line( file, context->Section, context->Line ); + + if (!line) return 0; + return line->nb_fields; +} + + +/*********************************************************************** + * SetupGetStringFieldA (SETUPAPI.@) + */ +BOOL WINAPI SetupGetStringFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, + DWORD size, PDWORD required ) +{ + struct inf_file *file = context->CurrentInf; + struct field *field = get_field( file, context->Section, context->Line, index ); + unsigned int len; + + SetLastError(0); + if (!field) return FALSE; + len = PARSER_string_substA( file, field->text, NULL, 0 ); + if (required) *required = len + 1; + if (buffer) + { + if (size <= len) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + PARSER_string_substA( file, field->text, buffer, size ); + + TRACE( "context %p/%p/%d/%d index %ld returning %s\n", + context->Inf, context->CurrentInf, context->Section, context->Line, + index, debugstr_a(buffer) ); + } + return TRUE; +} + + +/*********************************************************************** + * SetupGetStringFieldW (SETUPAPI.@) + */ +BOOL WINAPI SetupGetStringFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, + DWORD size, PDWORD required ) +{ + struct inf_file *file = context->CurrentInf; + struct field *field = get_field( file, context->Section, context->Line, index ); + unsigned int len; + + SetLastError(0); + if (!field) return FALSE; + len = PARSER_string_substW( file, field->text, NULL, 0 ); + if (required) *required = len + 1; + if (buffer) + { + if (size <= len) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + PARSER_string_substW( file, field->text, buffer, size ); + + TRACE( "context %p/%p/%d/%d index %ld returning %s\n", + context->Inf, context->CurrentInf, context->Section, context->Line, + index, debugstr_w(buffer) ); + } + return TRUE; +} + + +/*********************************************************************** + * SetupGetIntField (SETUPAPI.@) + */ +BOOL WINAPI SetupGetIntField( PINFCONTEXT context, DWORD index, PINT result ) +{ + char localbuff[20]; + char *end, *buffer = localbuff; + DWORD required; + INT res; + BOOL ret = FALSE; + + if (!SetupGetStringFieldA( context, index, localbuff, sizeof(localbuff), &required )) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, required ))) return FALSE; + if (!SetupGetStringFieldA( context, index, buffer, required, NULL )) goto done; + } + res = strtol( buffer, &end, 0 ); + if (end != buffer && !*end) + { + *result = res; + ret = TRUE; + } + else SetLastError( ERROR_INVALID_DATA ); + + done: + if (buffer != localbuff) HeapFree( GetProcessHeap(), 0, buffer ); + return ret; +} + + +/*********************************************************************** + * SetupGetBinaryField (SETUPAPI.@) + */ +BOOL WINAPI SetupGetBinaryField( PINFCONTEXT context, DWORD index, BYTE *buffer, + DWORD size, LPDWORD required ) +{ + struct inf_file *file = context->CurrentInf; + struct line *line = get_line( file, context->Section, context->Line ); + struct field *field; + int i; + + if (!line) + { + SetLastError( ERROR_LINE_NOT_FOUND ); + return FALSE; + } + if (!index || index >= line->nb_fields) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + index--; /* fields start at 0 */ + if (required) *required = line->nb_fields - index; + if (!buffer) return TRUE; + if (size < line->nb_fields - index) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + field = &file->fields[line->first_field + index]; + for (i = index; i < line->nb_fields; i++, field++) + { + const WCHAR *p; + DWORD value = 0; + for (p = field->text; *p && isxdigitW(*p); p++) + { + if ((value <<= 4) > 255) + { + SetLastError( ERROR_INVALID_DATA ); + return FALSE; + } + if (*p <= '9') value |= (*p - '0'); + else value |= (tolowerW(*p) - 'a' + 10); + } + buffer[i - index] = value; + } + if (TRACE_ON(setupapi)) + { + TRACE( "%p/%p/%d/%d index %ld returning", + context->Inf, context->CurrentInf, context->Section, context->Line, index ); + for (i = index; i < line->nb_fields; i++) TRACE( " %02x", buffer[i - index] ); + TRACE( "\n" ); + } + return TRUE; +} + + +/*********************************************************************** + * SetupGetMultiSzFieldA (SETUPAPI.@) + */ +BOOL WINAPI SetupGetMultiSzFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, + DWORD size, LPDWORD required ) +{ + struct inf_file *file = context->CurrentInf; + struct line *line = get_line( file, context->Section, context->Line ); + struct field *field; + unsigned int len; + int i; + DWORD total = 1; + + if (!line) + { + SetLastError( ERROR_LINE_NOT_FOUND ); + return FALSE; + } + if (!index || index >= line->nb_fields) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + index--; /* fields start at 0 */ + field = &file->fields[line->first_field + index]; + for (i = index; i < line->nb_fields; i++, field++) + { + if (!(len = PARSER_string_substA( file, field->text, NULL, 0 ))) break; + total += len + 1; + } + + if (required) *required = total; + if (!buffer) return TRUE; + if (total > size) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + field = &file->fields[line->first_field + index]; + for (i = index; i < line->nb_fields; i++, field++) + { + if (!(len = PARSER_string_substA( file, field->text, buffer, size ))) break; + buffer += len + 1; + } + *buffer = 0; /* add final null */ + return TRUE; +} + + +/*********************************************************************** + * SetupGetMultiSzFieldW (SETUPAPI.@) + */ +BOOL WINAPI SetupGetMultiSzFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, + DWORD size, LPDWORD required ) +{ + struct inf_file *file = context->CurrentInf; + struct line *line = get_line( file, context->Section, context->Line ); + struct field *field; + unsigned int len; + int i; + DWORD total = 1; + + if (!line) + { + SetLastError( ERROR_LINE_NOT_FOUND ); + return FALSE; + } + if (!index || index >= line->nb_fields) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + index--; /* fields start at 0 */ + field = &file->fields[line->first_field + index]; + for (i = index; i < line->nb_fields; i++, field++) + { + if (!(len = PARSER_string_substW( file, field->text, NULL, 0 ))) break; + total += len + 1; + } + + if (required) *required = total; + if (!buffer) return TRUE; + if (total > size) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + field = &file->fields[line->first_field + index]; + for (i = index; i < line->nb_fields; i++, field++) + { + if (!(len = PARSER_string_substW( file, field->text, buffer, size ))) break; + buffer += len + 1; + } + *buffer = 0; /* add final null */ + return TRUE; +} diff --git a/reactos/lib/setupapi/queue.c b/reactos/lib/setupapi/queue.c index 3144707132c..d205e927c37 100644 --- a/reactos/lib/setupapi/queue.c +++ b/reactos/lib/setupapi/queue.c @@ -1,1427 +1,1427 @@ -/* - * Setupapi file queue routines - * - * Copyright 2002 Alexandre Julliard for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winternl.h" -#include "winerror.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "setupapi.h" -#include "wine/unicode.h" -#include "setupapi_private.h" -#include "winver.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -/* context structure for the default queue callback */ -struct default_callback_context -{ - HWND owner; - HWND progress; - UINT message; -}; - -struct file_op -{ - struct file_op *next; - UINT style; - WCHAR *src_root; - WCHAR *src_path; - WCHAR *src_file; - WCHAR *src_descr; - WCHAR *src_tag; - WCHAR *dst_path; - WCHAR *dst_file; -}; - -struct file_op_queue -{ - struct file_op *head; - struct file_op *tail; - unsigned int count; -}; - -struct file_queue -{ - struct file_op_queue copy_queue; - struct file_op_queue delete_queue; - struct file_op_queue rename_queue; - DWORD flags; -}; - - -inline static WCHAR *strdupW( const WCHAR *str ) -{ - WCHAR *ret = NULL; - if (str) - { - int len = (strlenW(str) + 1) * sizeof(WCHAR); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len ); - } - return ret; -} - - -inline static WCHAR *strdupAtoW( const char *str ) -{ - WCHAR *ret = NULL; - if (str) - { - DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); - } - return ret; -} - -inline static char *strdupWtoA( const WCHAR *str ) -{ - char *ret = NULL; - if (str) - { - DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) - WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); - } - return ret; -} - -/* append a file operation to a queue */ -inline static void queue_file_op( struct file_op_queue *queue, struct file_op *op ) -{ - op->next = NULL; - if (queue->tail) queue->tail->next = op; - else queue->head = op; - queue->tail = op; - queue->count++; -} - -/* free all the file operations on a given queue */ -static void free_file_op_queue( struct file_op_queue *queue ) -{ - struct file_op *t, *op = queue->head; - - while( op ) - { - HeapFree( GetProcessHeap(), 0, op->src_root ); - HeapFree( GetProcessHeap(), 0, op->src_path ); - HeapFree( GetProcessHeap(), 0, op->src_file ); - HeapFree( GetProcessHeap(), 0, op->src_descr ); - HeapFree( GetProcessHeap(), 0, op->src_tag ); - HeapFree( GetProcessHeap(), 0, op->dst_path ); - if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file ); - t = op; - op = op->next; - HeapFree( GetProcessHeap(), 0, t ); - } -} - -/* concat 3 strings to make a path, handling separators correctly */ -static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 ) -{ - *buffer = 0; - if (src1 && *src1) - { - strcpyW( buffer, src1 ); - buffer += strlenW(buffer ); - if (buffer[-1] != '\\') *buffer++ = '\\'; - if (src2) while (*src2 == '\\') src2++; - } - - if (src2) - { - strcpyW( buffer, src2 ); - buffer += strlenW(buffer ); - if (buffer[-1] != '\\') *buffer++ = '\\'; - if (src3) while (*src3 == '\\') src3++; - } - if (src3) - { - strcpyW( buffer, src3 ); - buffer += strlenW(buffer ); - } -} - - -/*********************************************************************** - * build_filepathsW - * - * Build a FILEPATHS_W structure for a given file operation. - */ -static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths ) -{ - unsigned int src_len = 1, dst_len = 1; - WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target; - - if (op->src_root) src_len += strlenW(op->src_root) + 1; - if (op->src_path) src_len += strlenW(op->src_path) + 1; - if (op->src_file) src_len += strlenW(op->src_file) + 1; - if (op->dst_path) dst_len += strlenW(op->dst_path) + 1; - if (op->dst_file) dst_len += strlenW(op->dst_file) + 1; - src_len *= sizeof(WCHAR); - dst_len *= sizeof(WCHAR); - - if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len ) - { - HeapFree( GetProcessHeap(), 0, source ); - paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len ); - } - if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len ) - { - HeapFree( GetProcessHeap(), 0, target ); - paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len ); - } - if (!source || !target) return FALSE; - concat_W( source, op->src_root, op->src_path, op->src_file ); - concat_W( target, NULL, op->dst_path, op->dst_file ); - paths->Win32Error = 0; - paths->Flags = 0; - return TRUE; -} - - -/*********************************************************************** - * QUEUE_callback_WtoA - * - * Map a file callback parameters from W to A and call the A callback. - */ -UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, - UINT_PTR param1, UINT_PTR param2 ) -{ - struct callback_WtoA_context *callback_ctx = context; - char buffer[MAX_PATH]; - UINT ret; - UINT_PTR old_param2 = param2; - - switch(notification) - { - case SPFILENOTIFY_COPYERROR: - param2 = (UINT_PTR)&buffer; - /* fall through */ - case SPFILENOTIFY_STARTDELETE: - case SPFILENOTIFY_ENDDELETE: - case SPFILENOTIFY_DELETEERROR: - case SPFILENOTIFY_STARTRENAME: - case SPFILENOTIFY_ENDRENAME: - case SPFILENOTIFY_RENAMEERROR: - case SPFILENOTIFY_STARTCOPY: - case SPFILENOTIFY_ENDCOPY: - { - FILEPATHS_W *pathsW = (FILEPATHS_W *)param1; - FILEPATHS_A pathsA; - - pathsA.Source = strdupWtoA( pathsW->Source ); - pathsA.Target = strdupWtoA( pathsW->Target ); - pathsA.Win32Error = pathsW->Win32Error; - pathsA.Flags = pathsW->Flags; - ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, - (UINT_PTR)&pathsA, param2 ); - HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source ); - HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target ); - } - if (notification == SPFILENOTIFY_COPYERROR) - MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH ); - break; - - case SPFILENOTIFY_STARTREGISTRATION: - case SPFILENOTIFY_ENDREGISTRATION: - { - SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1; - SP_REGISTER_CONTROL_STATUSA statusA; - - statusA.cbSize = sizeof(statusA); - statusA.FileName = strdupWtoA( statusW->FileName ); - statusA.Win32Error = statusW->Win32Error; - statusA.FailureCode = statusW->FailureCode; - ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, - (UINT_PTR)&statusA, param2 ); - HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName ); - } - break; - - case SPFILENOTIFY_NEEDMEDIA: - case SPFILENOTIFY_QUEUESCAN: - FIXME("mapping for %d not implemented\n",notification); - case SPFILENOTIFY_STARTQUEUE: - case SPFILENOTIFY_ENDQUEUE: - case SPFILENOTIFY_STARTSUBQUEUE: - case SPFILENOTIFY_ENDSUBQUEUE: - default: - ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 ); - break; - } - return ret; -} - - -/*********************************************************************** - * get_src_file_info - * - * Retrieve the source file information for a given file. - */ -static void get_src_file_info( HINF hinf, struct file_op *op ) -{ - static const WCHAR SourceDisksNames[] = - {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0}; - static const WCHAR SourceDisksFiles[] = - {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0}; - - INFCONTEXT file_ctx, disk_ctx; - INT id, diskid; - DWORD len, len2; - - /* find the SourceDisksFiles entry */ - if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx )) - { - const WCHAR *dir; - - if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return; - /* no specific info, use .inf file source directory */ - if (!op->src_root && (dir = DIRID_get_string( hinf, DIRID_SRCPATH ))) - op->src_root = strdupW( dir ); - return; - } - if (!SetupGetIntField( &file_ctx, 1, &diskid )) return; - - /* now find the diskid in the SourceDisksNames section */ - if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return; - for (;;) - { - if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break; - if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return; - } - - /* and fill in the missing info */ - - if (!op->src_descr) - { - if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) && - (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ))) - SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL ); - } - if (!op->src_tag) - { - if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) && - (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ))) - SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL ); - } - if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE)) - { - if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE)) - { - /* retrieve relative path for this disk */ - if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0; - } - /* retrieve relative path for this file */ - if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0; - - if ((len || len2) && - (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) ))) - { - WCHAR *ptr = op->src_path; - if (len) - { - SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL ); - ptr = op->src_path + strlenW(op->src_path); - if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\'; - } - if (!SetupGetStringFieldW( &disk_ctx, 4, ptr, len2, NULL )) *ptr = 0; - } - } - if (!op->src_root) op->src_root = strdupW( PARSER_get_src_root(hinf) ); -} - - -/*********************************************************************** - * get_destination_dir - * - * Retrieve the destination dir for a given section. - */ -static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section ) -{ - static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0}; - static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0}; - INFCONTEXT context; - - if (!SetupFindFirstLineW( hinf, Dest, section, &context ) && - !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL; - return PARSER_get_dest_dir( &context ); -} - - -static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD ); - -/*********************************************************************** - * extract_cabinet_file - * - * Extract a file from a .cab file. - */ -static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root, - const WCHAR *src, const WCHAR *dst ) -{ - static const WCHAR extW[] = {'.','c','a','b',0}; - static HMODULE advpack; - - char *cab_path, *cab_file; - int len = strlenW( cabinet ); - - /* make sure the cabinet file has a .cab extension */ - if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE; - if (!pExtractFiles) - { - if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" ))) - { - ERR( "could not load advpack.dll\n" ); - return FALSE; - } - if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" ))) - { - ERR( "could not find ExtractFiles in advpack.dll\n" ); - return FALSE; - } - } - - if (!(cab_path = strdupWtoA( root ))) return FALSE; - len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL ); - if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 ))) - { - HeapFree( GetProcessHeap(), 0, cab_path ); - return FALSE; - } - strcpy( cab_file, cab_path ); - if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" ); - WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL ); - FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) ); - pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 ); - HeapFree( GetProcessHeap(), 0, cab_file ); - HeapFree( GetProcessHeap(), 0, cab_path ); - return CopyFileW( src, dst, FALSE /*FIXME*/ ); -} - - -/*********************************************************************** - * SetupOpenFileQueue (SETUPAPI.@) - */ -HSPFILEQ WINAPI SetupOpenFileQueue(void) -{ - struct file_queue *queue; - - if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue)))) - return (HSPFILEQ)INVALID_HANDLE_VALUE; - return queue; -} - - -/*********************************************************************** - * SetupCloseFileQueue (SETUPAPI.@) - */ -BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle ) -{ - struct file_queue *queue = handle; - - free_file_op_queue( &queue->copy_queue ); - free_file_op_queue( &queue->rename_queue ); - free_file_op_queue( &queue->delete_queue ); - HeapFree( GetProcessHeap(), 0, queue ); - return TRUE; -} - - -/*********************************************************************** - * SetupQueueCopyIndirectA (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params ) -{ - struct file_queue *queue = params->QueueHandle; - struct file_op *op; - - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = params->CopyStyle; - op->src_root = strdupAtoW( params->SourceRootPath ); - op->src_path = strdupAtoW( params->SourcePath ); - op->src_file = strdupAtoW( params->SourceFilename ); - op->src_descr = strdupAtoW( params->SourceDescription ); - op->src_tag = strdupAtoW( params->SourceTagfile ); - op->dst_path = strdupAtoW( params->TargetDirectory ); - op->dst_file = strdupAtoW( params->TargetFilename ); - - /* some defaults */ - if (!op->src_file) op->src_file = op->dst_file; - if (params->LayoutInf) - { - get_src_file_info( params->LayoutInf, op ); - if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file ); - } - - TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n", - debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file), - debugstr_w(op->dst_path), debugstr_w(op->dst_file), - debugstr_w(op->src_descr), debugstr_w(op->src_tag) ); - - queue_file_op( &queue->copy_queue, op ); - return TRUE; -} - - -/*********************************************************************** - * SetupQueueCopyIndirectW (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params ) -{ - struct file_queue *queue = params->QueueHandle; - struct file_op *op; - - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = params->CopyStyle; - op->src_root = strdupW( params->SourceRootPath ); - op->src_path = strdupW( params->SourcePath ); - op->src_file = strdupW( params->SourceFilename ); - op->src_descr = strdupW( params->SourceDescription ); - op->src_tag = strdupW( params->SourceTagfile ); - op->dst_path = strdupW( params->TargetDirectory ); - op->dst_file = strdupW( params->TargetFilename ); - - /* some defaults */ - if (!op->src_file) op->src_file = op->dst_file; - if (params->LayoutInf) - { - get_src_file_info( params->LayoutInf, op ); - if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file ); - } - - TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n", - debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file), - debugstr_w(op->dst_path), debugstr_w(op->dst_file), - debugstr_w(op->src_descr), debugstr_w(op->src_tag) ); - - queue_file_op( &queue->copy_queue, op ); - return TRUE; -} - - -/*********************************************************************** - * SetupQueueCopyA (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file, - PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file, - DWORD style ) -{ - SP_FILE_COPY_PARAMS_A params; - - params.cbSize = sizeof(params); - params.QueueHandle = queue; - params.SourceRootPath = src_root; - params.SourcePath = src_path; - params.SourceFilename = src_file; - params.SourceDescription = src_descr; - params.SourceTagfile = src_tag; - params.TargetDirectory = dst_dir; - params.TargetFilename = dst_file; - params.CopyStyle = style; - params.LayoutInf = 0; - params.SecurityDescriptor = NULL; - return SetupQueueCopyIndirectA( ¶ms ); -} - - -/*********************************************************************** - * SetupQueueCopyW (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file, - PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file, - DWORD style ) -{ - SP_FILE_COPY_PARAMS_W params; - - params.cbSize = sizeof(params); - params.QueueHandle = queue; - params.SourceRootPath = src_root; - params.SourcePath = src_path; - params.SourceFilename = src_file; - params.SourceDescription = src_descr; - params.SourceTagfile = src_tag; - params.TargetDirectory = dst_dir; - params.TargetFilename = dst_file; - params.CopyStyle = style; - params.LayoutInf = 0; - params.SecurityDescriptor = NULL; - return SetupQueueCopyIndirectW( ¶ms ); -} - - -/*********************************************************************** - * SetupQueueDefaultCopyA (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file, - PCSTR dst_file, DWORD style ) -{ - SP_FILE_COPY_PARAMS_A params; - - params.cbSize = sizeof(params); - params.QueueHandle = queue; - params.SourceRootPath = src_root; - params.SourcePath = NULL; - params.SourceFilename = src_file; - params.SourceDescription = NULL; - params.SourceTagfile = NULL; - params.TargetDirectory = NULL; - params.TargetFilename = dst_file; - params.CopyStyle = style; - params.LayoutInf = hinf; - params.SecurityDescriptor = NULL; - return SetupQueueCopyIndirectA( ¶ms ); -} - - -/*********************************************************************** - * SetupQueueDefaultCopyW (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file, - PCWSTR dst_file, DWORD style ) -{ - SP_FILE_COPY_PARAMS_W params; - - params.cbSize = sizeof(params); - params.QueueHandle = queue; - params.SourceRootPath = src_root; - params.SourcePath = NULL; - params.SourceFilename = src_file; - params.SourceDescription = NULL; - params.SourceTagfile = NULL; - params.TargetDirectory = NULL; - params.TargetFilename = dst_file; - params.CopyStyle = style; - params.LayoutInf = hinf; - params.SecurityDescriptor = NULL; - return SetupQueueCopyIndirectW( ¶ms ); -} - - -/*********************************************************************** - * SetupQueueDeleteA (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 ) -{ - struct file_queue *queue = handle; - struct file_op *op; - - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = 0; - op->src_root = NULL; - op->src_path = NULL; - op->src_file = NULL; - op->src_descr = NULL; - op->src_tag = NULL; - op->dst_path = strdupAtoW( part1 ); - op->dst_file = strdupAtoW( part2 ); - queue_file_op( &queue->delete_queue, op ); - return TRUE; -} - - -/*********************************************************************** - * SetupQueueDeleteW (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 ) -{ - struct file_queue *queue = handle; - struct file_op *op; - - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = 0; - op->src_root = NULL; - op->src_path = NULL; - op->src_file = NULL; - op->src_descr = NULL; - op->src_tag = NULL; - op->dst_path = strdupW( part1 ); - op->dst_file = strdupW( part2 ); - queue_file_op( &queue->delete_queue, op ); - return TRUE; -} - - -/*********************************************************************** - * SetupQueueRenameA (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename, - PCSTR TargetPath, PCSTR TargetFilename ) -{ - struct file_queue *queue = handle; - struct file_op *op; - - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = 0; - op->src_root = NULL; - op->src_path = strdupAtoW( SourcePath ); - op->src_file = strdupAtoW( SourceFilename ); - op->src_descr = NULL; - op->src_tag = NULL; - op->dst_path = strdupAtoW( TargetPath ); - op->dst_file = strdupAtoW( TargetFilename ); - queue_file_op( &queue->rename_queue, op ); - return TRUE; -} - - -/*********************************************************************** - * SetupQueueRenameW (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename, - PCWSTR TargetPath, PCWSTR TargetFilename ) -{ - struct file_queue *queue = handle; - struct file_op *op; - - if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; - op->style = 0; - op->src_root = NULL; - op->src_path = strdupW( SourcePath ); - op->src_file = strdupW( SourceFilename ); - op->src_descr = NULL; - op->src_tag = NULL; - op->dst_path = strdupW( TargetPath ); - op->dst_file = strdupW( TargetFilename ); - queue_file_op( &queue->rename_queue, op ); - return TRUE; -} - - -/*********************************************************************** - * SetupQueueCopySectionA (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist, - PCSTR section, DWORD style ) -{ - UNICODE_STRING sectionW; - BOOL ret = FALSE; - - if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - } - if (!src_root) - ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style ); - else - { - UNICODE_STRING srcW; - if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root )) - { - ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style ); - RtlFreeUnicodeString( &srcW ); - } - else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - } - RtlFreeUnicodeString( §ionW ); - return ret; -} - - -/*********************************************************************** - * SetupQueueCopySectionW (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist, - PCWSTR section, DWORD style ) -{ - SP_FILE_COPY_PARAMS_W params; - INFCONTEXT context; - WCHAR dest[MAX_PATH], src[MAX_PATH]; - INT flags; - - TRACE( "hinf=%p/%p section=%s root=%s\n", - hinf, hlist, debugstr_w(section), debugstr_w(src_root) ); - - params.cbSize = sizeof(params); - params.QueueHandle = queue; - params.SourceRootPath = src_root; - params.SourcePath = NULL; - params.SourceDescription = NULL; - params.SourceTagfile = NULL; - params.TargetFilename = dest; - params.CopyStyle = style; - params.LayoutInf = hinf; - params.SecurityDescriptor = NULL; - - if (!hlist) hlist = hinf; - if (!hinf) hinf = hlist; - if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; - if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE; - do - { - if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL )) - return FALSE; - if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0; - if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */ - - params.SourceFilename = *src ? src : NULL; - if (!SetupQueueCopyIndirectW( ¶ms )) return FALSE; - } while (SetupFindNextLine( &context, &context )); - return TRUE; -} - - -/*********************************************************************** - * SetupQueueDeleteSectionA (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section ) -{ - UNICODE_STRING sectionW; - BOOL ret = FALSE; - - if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) - { - ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer ); - RtlFreeUnicodeString( §ionW ); - } - else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return ret; -} - - -/*********************************************************************** - * SetupQueueDeleteSectionW (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section ) -{ - INFCONTEXT context; - WCHAR *dest_dir; - WCHAR buffer[MAX_PATH]; - BOOL ret = FALSE; - INT flags; - - TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) ); - - if (!hlist) hlist = hinf; - if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; - if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE; - do - { - if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) - goto done; - if (!SetupGetIntField( &context, 4, &flags )) flags = 0; - if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done; - } while (SetupFindNextLine( &context, &context )); - - ret = TRUE; - done: - HeapFree( GetProcessHeap(), 0, dest_dir ); - return ret; -} - - -/*********************************************************************** - * SetupQueueRenameSectionA (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section ) -{ - UNICODE_STRING sectionW; - BOOL ret = FALSE; - - if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) - { - ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer ); - RtlFreeUnicodeString( §ionW ); - } - else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return ret; -} - - -/*********************************************************************** - * SetupQueueRenameSectionW (SETUPAPI.@) - */ -BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section ) -{ - INFCONTEXT context; - WCHAR *dest_dir; - WCHAR src[MAX_PATH], dst[MAX_PATH]; - BOOL ret = FALSE; - - TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) ); - - if (!hlist) hlist = hinf; - if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; - if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE; - do - { - if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL )) - goto done; - if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) - goto done; - if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done; - } while (SetupFindNextLine( &context, &context )); - - ret = TRUE; - done: - HeapFree( GetProcessHeap(), 0, dest_dir ); - return ret; -} - - -/*********************************************************************** - * SetupCommitFileQueueA (SETUPAPI.@) - */ -BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler, - PVOID context ) -{ - struct callback_WtoA_context ctx; - - ctx.orig_context = context; - ctx.orig_handler = handler; - return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx ); -} - - -/*********************************************************************** - * create_full_pathW - * - * Recursively create all directories in the path. - */ -static BOOL create_full_pathW(const WCHAR *path) -{ - BOOL ret = TRUE; - int len; - WCHAR *new_path; - - new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR)); - strcpyW(new_path, path); - - while((len = strlenW(new_path)) && new_path[len - 1] == '\\') - new_path[len - 1] = 0; - - while(!CreateDirectoryW(new_path, NULL)) - { - WCHAR *slash; - DWORD last_error = GetLastError(); - - if(last_error == ERROR_ALREADY_EXISTS) - break; - - if(last_error != ERROR_PATH_NOT_FOUND) - { - ret = FALSE; - break; - } - - if(!(slash = strrchrW(new_path, '\\'))) - { - ret = FALSE; - break; - } - - len = slash - new_path; - new_path[len] = 0; - if(!create_full_pathW(new_path)) - { - ret = FALSE; - break; - } - new_path[len] = '\\'; - } - - HeapFree(GetProcessHeap(), 0, new_path); - return ret; -} - -BOOL static do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style) -{ - BOOL rc = FALSE; - BOOL docopy = TRUE; - - TRACE("copy %s to %s style 0x%lx\n",debugstr_w(source),debugstr_w(target),style); - - /* before copy processing */ - if (style & SP_COPY_REPLACEONLY) - { - if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES) - docopy = FALSE; - } - if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER)) - { - DWORD VersionSizeSource=0; - DWORD VersionSizeTarget=0; - DWORD zero=0; - - /* - * This is sort of an interesting workaround. You see, calling - * GetVersionInfoSize on a builtin dll loads that dll into memory - * and we do not properly unload builtin dlls.. so we effectively - * lock into memory all the targets we are replacing. This leads - * to problems when we try to register the replaced dlls. - * - * So I will test for the existence of the files first so that - * we just basically unconditionally replace the builtin versions. - */ - if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) && - (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES)) - { - VersionSizeSource = GetFileVersionInfoSizeW(source,&zero); - VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero); - } - - TRACE("SizeTarget %li ... SizeSource %li\n",VersionSizeTarget, - VersionSizeSource); - - if (VersionSizeSource && VersionSizeTarget) - { - LPVOID VersionSource; - LPVOID VersionTarget; - VS_FIXEDFILEINFO *TargetInfo; - VS_FIXEDFILEINFO *SourceInfo; - UINT length; - WCHAR SubBlock[2]={'\\',0}; - DWORD ret; - - VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource); - VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget); - - ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource); - if (ret) - ret = GetFileVersionInfoW(target, 0, VersionSizeTarget, - VersionTarget); - - if (ret) - { - ret = VerQueryValueW(VersionSource, SubBlock, - (LPVOID*)&SourceInfo, &length); - if (ret) - ret = VerQueryValueW(VersionTarget, SubBlock, - (LPVOID*)&TargetInfo, &length); - - if (ret) - { - TRACE("Versions: Source %li.%li target %li.%li\n", - SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS, - TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS); - - if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS) - { - FIXME("Notify that target version is greater..\n"); - docopy = FALSE; - } - else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS) - && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS)) - { - FIXME("Notify that target version is greater..\n"); - docopy = FALSE; - } - else if ((style & SP_COPY_NEWER_ONLY) && - (TargetInfo->dwFileVersionMS == - SourceInfo->dwFileVersionMS) - &&(TargetInfo->dwFileVersionLS == - SourceInfo->dwFileVersionLS)) - { - FIXME("Notify that target version is greater..\n"); - docopy = FALSE; - } - } - } - HeapFree(GetProcessHeap(),0,VersionSource); - HeapFree(GetProcessHeap(),0,VersionTarget); - } - } - if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE)) - { - if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) - { - FIXME("Notify user target file exists\n"); - docopy = FALSE; - } - } - if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE | - SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP)) - { - ERR("Unsupported style(s) 0x%lx\n",style); - } - - if (docopy) - { - rc = CopyFileW(source,target,FALSE); - TRACE("Did copy... rc was %i\n",rc); - } - - /* after copy processing */ - if (style & SP_COPY_DELETESOURCE) - { - if (rc) - DeleteFileW(source); - } - - return rc; -} - -/*********************************************************************** - * SetupCommitFileQueueW (SETUPAPI.@) - */ -BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler, - PVOID context ) -{ - struct file_queue *queue = handle; - struct file_op *op; - BOOL result = FALSE; - FILEPATHS_W paths; - UINT op_result; - - paths.Source = paths.Target = NULL; - - if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count) - return TRUE; /* nothing to do */ - - if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT)owner, 0 )) return FALSE; - - /* perform deletes */ - - if (queue->delete_queue.count) - { - if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE, - queue->delete_queue.count ))) goto done; - for (op = queue->delete_queue.head; op; op = op->next) - { - build_filepathsW( op, &paths ); - op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE); - if (op_result == FILEOP_ABORT) goto done; - while (op_result == FILEOP_DOIT) - { - TRACE( "deleting file %s\n", debugstr_w(paths.Target) ); - if (DeleteFileW( paths.Target )) break; /* success */ - paths.Win32Error = GetLastError(); - op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 ); - if (op_result == FILEOP_ABORT) goto done; - } - handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 ); - } - handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 ); - } - - /* perform renames */ - - if (queue->rename_queue.count) - { - if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME, - queue->rename_queue.count ))) goto done; - for (op = queue->rename_queue.head; op; op = op->next) - { - build_filepathsW( op, &paths ); - op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME); - if (op_result == FILEOP_ABORT) goto done; - while (op_result == FILEOP_DOIT) - { - TRACE( "renaming file %s -> %s\n", - debugstr_w(paths.Source), debugstr_w(paths.Target) ); - if (MoveFileW( paths.Source, paths.Target )) break; /* success */ - paths.Win32Error = GetLastError(); - op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 ); - if (op_result == FILEOP_ABORT) goto done; - } - handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 ); - } - handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 ); - } - - /* perform copies */ - - if (queue->copy_queue.count) - { - if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY, - queue->copy_queue.count ))) goto done; - for (op = queue->copy_queue.head; op; op = op->next) - { - WCHAR newpath[MAX_PATH]; - - build_filepathsW( op, &paths ); - op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY ); - if (op_result == FILEOP_ABORT) goto done; - if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT; - while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH) - { - TRACE( "copying file %s -> %s\n", - debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ), - debugstr_w(paths.Target) ); - if (op->dst_path) - { - if (!create_full_pathW( op->dst_path )) - { - paths.Win32Error = GetLastError(); - op_result = handler( context, SPFILENOTIFY_COPYERROR, - (UINT_PTR)&paths, (UINT_PTR)newpath ); - if (op_result == FILEOP_ABORT) goto done; - } - } - if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source, - paths.Target, op->style )) break; /* success */ - /* try to extract it from the cabinet file */ - if (op->src_tag) - { - if (extract_cabinet_file( op->src_tag, op->src_root, - paths.Source, paths.Target )) break; - } - paths.Win32Error = GetLastError(); - op_result = handler( context, SPFILENOTIFY_COPYERROR, - (UINT_PTR)&paths, (UINT_PTR)newpath ); - if (op_result == FILEOP_ABORT) goto done; - } - handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 ); - } - handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 ); - } - - - result = TRUE; - - done: - handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 ); - HeapFree( GetProcessHeap(), 0, (void *)paths.Source ); - HeapFree( GetProcessHeap(), 0, (void *)paths.Target ); - return result; -} - - -/*********************************************************************** - * SetupScanFileQueueA (SETUPAPI.@) - */ -BOOL WINAPI SetupScanFileQueueA( HSPFILEQ queue, DWORD flags, HWND window, - PSP_FILE_CALLBACK_A callback, PVOID context, PDWORD result ) -{ - FIXME("stub\n"); - return FALSE; -} - - -/*********************************************************************** - * SetupScanFileQueueW (SETUPAPI.@) - */ -BOOL WINAPI SetupScanFileQueueW( HSPFILEQ queue, DWORD flags, HWND window, - PSP_FILE_CALLBACK_W callback, PVOID context, PDWORD result ) -{ - FIXME("stub\n"); - return FALSE; -} - - -/*********************************************************************** - * SetupGetFileQueueCount (SETUPAPI.@) - */ -BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result ) -{ - struct file_queue *queue = handle; - - switch(op) - { - case FILEOP_COPY: - *result = queue->copy_queue.count; - return TRUE; - case FILEOP_RENAME: - *result = queue->rename_queue.count; - return TRUE; - case FILEOP_DELETE: - *result = queue->delete_queue.count; - return TRUE; - } - return FALSE; -} - - -/*********************************************************************** - * SetupGetFileQueueFlags (SETUPAPI.@) - */ -BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags ) -{ - struct file_queue *queue = handle; - *flags = queue->flags; - return TRUE; -} - - -/*********************************************************************** - * SetupSetFileQueueFlags (SETUPAPI.@) - */ -BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags ) -{ - struct file_queue *queue = handle; - queue->flags = (queue->flags & ~mask) | flags; - return TRUE; -} - - -/*********************************************************************** - * SetupInitDefaultQueueCallback (SETUPAPI.@) - */ -PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner ) -{ - return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL ); -} - - -/*********************************************************************** - * SetupInitDefaultQueueCallbackEx (SETUPAPI.@) - */ -PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg, - DWORD reserved1, PVOID reserved2 ) -{ - struct default_callback_context *context; - - if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) ))) - { - context->owner = owner; - context->progress = progress; - context->message = msg; - } - return context; -} - - -/*********************************************************************** - * SetupTermDefaultQueueCallback (SETUPAPI.@) - */ -void WINAPI SetupTermDefaultQueueCallback( PVOID context ) -{ - HeapFree( GetProcessHeap(), 0, context ); -} - - -/*********************************************************************** - * SetupDefaultQueueCallbackA (SETUPAPI.@) - */ -UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification, - UINT_PTR param1, UINT_PTR param2 ) -{ - FILEPATHS_A *paths = (FILEPATHS_A *)param1; - - switch(notification) - { - case SPFILENOTIFY_STARTQUEUE: - TRACE( "start queue\n" ); - return TRUE; - case SPFILENOTIFY_ENDQUEUE: - TRACE( "end queue\n" ); - return 0; - case SPFILENOTIFY_STARTSUBQUEUE: - TRACE( "start subqueue %d count %d\n", param1, param2 ); - return TRUE; - case SPFILENOTIFY_ENDSUBQUEUE: - TRACE( "end subqueue %d\n", param1 ); - return 0; - case SPFILENOTIFY_STARTDELETE: - TRACE( "start delete %s\n", debugstr_a(paths->Target) ); - return FILEOP_DOIT; - case SPFILENOTIFY_ENDDELETE: - TRACE( "end delete %s\n", debugstr_a(paths->Target) ); - return 0; - case SPFILENOTIFY_DELETEERROR: - ERR( "delete error %d %s\n", paths->Win32Error, debugstr_a(paths->Target) ); - return FILEOP_SKIP; - case SPFILENOTIFY_STARTRENAME: - TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); - return FILEOP_DOIT; - case SPFILENOTIFY_ENDRENAME: - TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); - return 0; - case SPFILENOTIFY_RENAMEERROR: - ERR( "rename error %d %s -> %s\n", paths->Win32Error, - debugstr_a(paths->Source), debugstr_a(paths->Target) ); - return FILEOP_SKIP; - case SPFILENOTIFY_STARTCOPY: - TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); - return FILEOP_DOIT; - case SPFILENOTIFY_ENDCOPY: - TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); - return 0; - case SPFILENOTIFY_COPYERROR: - ERR( "copy error %d %s -> %s\n", paths->Win32Error, - debugstr_a(paths->Source), debugstr_a(paths->Target) ); - return FILEOP_SKIP; - case SPFILENOTIFY_NEEDMEDIA: - TRACE( "need media\n" ); - return FILEOP_SKIP; - default: - FIXME( "notification %d params %x,%x\n", notification, param1, param2 ); - break; - } - return 0; -} - - -/*********************************************************************** - * SetupDefaultQueueCallbackW (SETUPAPI.@) - */ -UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification, - UINT_PTR param1, UINT_PTR param2 ) -{ - FILEPATHS_W *paths = (FILEPATHS_W *)param1; - - switch(notification) - { - case SPFILENOTIFY_STARTQUEUE: - TRACE( "start queue\n" ); - return TRUE; - case SPFILENOTIFY_ENDQUEUE: - TRACE( "end queue\n" ); - return 0; - case SPFILENOTIFY_STARTSUBQUEUE: - TRACE( "start subqueue %d count %d\n", param1, param2 ); - return TRUE; - case SPFILENOTIFY_ENDSUBQUEUE: - TRACE( "end subqueue %d\n", param1 ); - return 0; - case SPFILENOTIFY_STARTDELETE: - TRACE( "start delete %s\n", debugstr_w(paths->Target) ); - return FILEOP_DOIT; - case SPFILENOTIFY_ENDDELETE: - TRACE( "end delete %s\n", debugstr_w(paths->Target) ); - return 0; - case SPFILENOTIFY_DELETEERROR: - ERR( "delete error %d %s\n", paths->Win32Error, debugstr_w(paths->Target) ); - return FILEOP_SKIP; - case SPFILENOTIFY_STARTRENAME: - TRACE( "start rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); - return FILEOP_DOIT; - case SPFILENOTIFY_ENDRENAME: - TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); - return 0; - case SPFILENOTIFY_RENAMEERROR: - ERR( "rename error %d %s -> %s\n", paths->Win32Error, - debugstr_w(paths->Source), debugstr_w(paths->Target) ); - return FILEOP_SKIP; - case SPFILENOTIFY_STARTCOPY: - TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); - return FILEOP_DOIT; - case SPFILENOTIFY_ENDCOPY: - TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); - return 0; - case SPFILENOTIFY_COPYERROR: - ERR( "copy error %d %s -> %s\n", paths->Win32Error, - debugstr_w(paths->Source), debugstr_w(paths->Target) ); - return FILEOP_SKIP; - case SPFILENOTIFY_NEEDMEDIA: - TRACE( "need media\n" ); - return FILEOP_SKIP; - default: - FIXME( "notification %d params %x,%x\n", notification, param1, param2 ); - break; - } - return 0; -} +/* + * Setupapi file queue routines + * + * Copyright 2002 Alexandre Julliard for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winternl.h" +#include "winerror.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "setupapi.h" +#include "wine/unicode.h" +#include "setupapi_private.h" +#include "winver.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +/* context structure for the default queue callback */ +struct default_callback_context +{ + HWND owner; + HWND progress; + UINT message; +}; + +struct file_op +{ + struct file_op *next; + UINT style; + WCHAR *src_root; + WCHAR *src_path; + WCHAR *src_file; + WCHAR *src_descr; + WCHAR *src_tag; + WCHAR *dst_path; + WCHAR *dst_file; +}; + +struct file_op_queue +{ + struct file_op *head; + struct file_op *tail; + unsigned int count; +}; + +struct file_queue +{ + struct file_op_queue copy_queue; + struct file_op_queue delete_queue; + struct file_op_queue rename_queue; + DWORD flags; +}; + + +inline static WCHAR *strdupW( const WCHAR *str ) +{ + WCHAR *ret = NULL; + if (str) + { + int len = (strlenW(str) + 1) * sizeof(WCHAR); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len ); + } + return ret; +} + + +inline static WCHAR *strdupAtoW( const char *str ) +{ + WCHAR *ret = NULL; + if (str) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); + } + return ret; +} + +inline static char *strdupWtoA( const WCHAR *str ) +{ + char *ret = NULL; + if (str) + { + DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) + WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); + } + return ret; +} + +/* append a file operation to a queue */ +inline static void queue_file_op( struct file_op_queue *queue, struct file_op *op ) +{ + op->next = NULL; + if (queue->tail) queue->tail->next = op; + else queue->head = op; + queue->tail = op; + queue->count++; +} + +/* free all the file operations on a given queue */ +static void free_file_op_queue( struct file_op_queue *queue ) +{ + struct file_op *t, *op = queue->head; + + while( op ) + { + HeapFree( GetProcessHeap(), 0, op->src_root ); + HeapFree( GetProcessHeap(), 0, op->src_path ); + HeapFree( GetProcessHeap(), 0, op->src_file ); + HeapFree( GetProcessHeap(), 0, op->src_descr ); + HeapFree( GetProcessHeap(), 0, op->src_tag ); + HeapFree( GetProcessHeap(), 0, op->dst_path ); + if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file ); + t = op; + op = op->next; + HeapFree( GetProcessHeap(), 0, t ); + } +} + +/* concat 3 strings to make a path, handling separators correctly */ +static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 ) +{ + *buffer = 0; + if (src1 && *src1) + { + strcpyW( buffer, src1 ); + buffer += strlenW(buffer ); + if (buffer[-1] != '\\') *buffer++ = '\\'; + if (src2) while (*src2 == '\\') src2++; + } + + if (src2) + { + strcpyW( buffer, src2 ); + buffer += strlenW(buffer ); + if (buffer[-1] != '\\') *buffer++ = '\\'; + if (src3) while (*src3 == '\\') src3++; + } + if (src3) + { + strcpyW( buffer, src3 ); + buffer += strlenW(buffer ); + } +} + + +/*********************************************************************** + * build_filepathsW + * + * Build a FILEPATHS_W structure for a given file operation. + */ +static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths ) +{ + unsigned int src_len = 1, dst_len = 1; + WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target; + + if (op->src_root) src_len += strlenW(op->src_root) + 1; + if (op->src_path) src_len += strlenW(op->src_path) + 1; + if (op->src_file) src_len += strlenW(op->src_file) + 1; + if (op->dst_path) dst_len += strlenW(op->dst_path) + 1; + if (op->dst_file) dst_len += strlenW(op->dst_file) + 1; + src_len *= sizeof(WCHAR); + dst_len *= sizeof(WCHAR); + + if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len ) + { + HeapFree( GetProcessHeap(), 0, source ); + paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len ); + } + if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len ) + { + HeapFree( GetProcessHeap(), 0, target ); + paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len ); + } + if (!source || !target) return FALSE; + concat_W( source, op->src_root, op->src_path, op->src_file ); + concat_W( target, NULL, op->dst_path, op->dst_file ); + paths->Win32Error = 0; + paths->Flags = 0; + return TRUE; +} + + +/*********************************************************************** + * QUEUE_callback_WtoA + * + * Map a file callback parameters from W to A and call the A callback. + */ +UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, + UINT_PTR param1, UINT_PTR param2 ) +{ + struct callback_WtoA_context *callback_ctx = context; + char buffer[MAX_PATH]; + UINT ret; + UINT_PTR old_param2 = param2; + + switch(notification) + { + case SPFILENOTIFY_COPYERROR: + param2 = (UINT_PTR)&buffer; + /* fall through */ + case SPFILENOTIFY_STARTDELETE: + case SPFILENOTIFY_ENDDELETE: + case SPFILENOTIFY_DELETEERROR: + case SPFILENOTIFY_STARTRENAME: + case SPFILENOTIFY_ENDRENAME: + case SPFILENOTIFY_RENAMEERROR: + case SPFILENOTIFY_STARTCOPY: + case SPFILENOTIFY_ENDCOPY: + { + FILEPATHS_W *pathsW = (FILEPATHS_W *)param1; + FILEPATHS_A pathsA; + + pathsA.Source = strdupWtoA( pathsW->Source ); + pathsA.Target = strdupWtoA( pathsW->Target ); + pathsA.Win32Error = pathsW->Win32Error; + pathsA.Flags = pathsW->Flags; + ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, + (UINT_PTR)&pathsA, param2 ); + HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source ); + HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target ); + } + if (notification == SPFILENOTIFY_COPYERROR) + MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH ); + break; + + case SPFILENOTIFY_STARTREGISTRATION: + case SPFILENOTIFY_ENDREGISTRATION: + { + SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1; + SP_REGISTER_CONTROL_STATUSA statusA; + + statusA.cbSize = sizeof(statusA); + statusA.FileName = strdupWtoA( statusW->FileName ); + statusA.Win32Error = statusW->Win32Error; + statusA.FailureCode = statusW->FailureCode; + ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, + (UINT_PTR)&statusA, param2 ); + HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName ); + } + break; + + case SPFILENOTIFY_NEEDMEDIA: + case SPFILENOTIFY_QUEUESCAN: + FIXME("mapping for %d not implemented\n",notification); + case SPFILENOTIFY_STARTQUEUE: + case SPFILENOTIFY_ENDQUEUE: + case SPFILENOTIFY_STARTSUBQUEUE: + case SPFILENOTIFY_ENDSUBQUEUE: + default: + ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 ); + break; + } + return ret; +} + + +/*********************************************************************** + * get_src_file_info + * + * Retrieve the source file information for a given file. + */ +static void get_src_file_info( HINF hinf, struct file_op *op ) +{ + static const WCHAR SourceDisksNames[] = + {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0}; + static const WCHAR SourceDisksFiles[] = + {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0}; + + INFCONTEXT file_ctx, disk_ctx; + INT id, diskid; + DWORD len, len2; + + /* find the SourceDisksFiles entry */ + if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx )) + { + const WCHAR *dir; + + if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return; + /* no specific info, use .inf file source directory */ + if (!op->src_root && (dir = DIRID_get_string( hinf, DIRID_SRCPATH ))) + op->src_root = strdupW( dir ); + return; + } + if (!SetupGetIntField( &file_ctx, 1, &diskid )) return; + + /* now find the diskid in the SourceDisksNames section */ + if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return; + for (;;) + { + if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break; + if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return; + } + + /* and fill in the missing info */ + + if (!op->src_descr) + { + if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) && + (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ))) + SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL ); + } + if (!op->src_tag) + { + if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) && + (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ))) + SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL ); + } + if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE)) + { + if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE)) + { + /* retrieve relative path for this disk */ + if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0; + } + /* retrieve relative path for this file */ + if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0; + + if ((len || len2) && + (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) ))) + { + WCHAR *ptr = op->src_path; + if (len) + { + SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL ); + ptr = op->src_path + strlenW(op->src_path); + if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\'; + } + if (!SetupGetStringFieldW( &disk_ctx, 4, ptr, len2, NULL )) *ptr = 0; + } + } + if (!op->src_root) op->src_root = strdupW( PARSER_get_src_root(hinf) ); +} + + +/*********************************************************************** + * get_destination_dir + * + * Retrieve the destination dir for a given section. + */ +static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section ) +{ + static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0}; + static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0}; + INFCONTEXT context; + + if (!SetupFindFirstLineW( hinf, Dest, section, &context ) && + !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL; + return PARSER_get_dest_dir( &context ); +} + + +static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD ); + +/*********************************************************************** + * extract_cabinet_file + * + * Extract a file from a .cab file. + */ +static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root, + const WCHAR *src, const WCHAR *dst ) +{ + static const WCHAR extW[] = {'.','c','a','b',0}; + static HMODULE advpack; + + char *cab_path, *cab_file; + int len = strlenW( cabinet ); + + /* make sure the cabinet file has a .cab extension */ + if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE; + if (!pExtractFiles) + { + if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" ))) + { + ERR( "could not load advpack.dll\n" ); + return FALSE; + } + if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" ))) + { + ERR( "could not find ExtractFiles in advpack.dll\n" ); + return FALSE; + } + } + + if (!(cab_path = strdupWtoA( root ))) return FALSE; + len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL ); + if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 ))) + { + HeapFree( GetProcessHeap(), 0, cab_path ); + return FALSE; + } + strcpy( cab_file, cab_path ); + if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" ); + WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL ); + FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) ); + pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 ); + HeapFree( GetProcessHeap(), 0, cab_file ); + HeapFree( GetProcessHeap(), 0, cab_path ); + return CopyFileW( src, dst, FALSE /*FIXME*/ ); +} + + +/*********************************************************************** + * SetupOpenFileQueue (SETUPAPI.@) + */ +HSPFILEQ WINAPI SetupOpenFileQueue(void) +{ + struct file_queue *queue; + + if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue)))) + return (HSPFILEQ)INVALID_HANDLE_VALUE; + return queue; +} + + +/*********************************************************************** + * SetupCloseFileQueue (SETUPAPI.@) + */ +BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle ) +{ + struct file_queue *queue = handle; + + free_file_op_queue( &queue->copy_queue ); + free_file_op_queue( &queue->rename_queue ); + free_file_op_queue( &queue->delete_queue ); + HeapFree( GetProcessHeap(), 0, queue ); + return TRUE; +} + + +/*********************************************************************** + * SetupQueueCopyIndirectA (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params ) +{ + struct file_queue *queue = params->QueueHandle; + struct file_op *op; + + if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; + op->style = params->CopyStyle; + op->src_root = strdupAtoW( params->SourceRootPath ); + op->src_path = strdupAtoW( params->SourcePath ); + op->src_file = strdupAtoW( params->SourceFilename ); + op->src_descr = strdupAtoW( params->SourceDescription ); + op->src_tag = strdupAtoW( params->SourceTagfile ); + op->dst_path = strdupAtoW( params->TargetDirectory ); + op->dst_file = strdupAtoW( params->TargetFilename ); + + /* some defaults */ + if (!op->src_file) op->src_file = op->dst_file; + if (params->LayoutInf) + { + get_src_file_info( params->LayoutInf, op ); + if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file ); + } + + TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n", + debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file), + debugstr_w(op->dst_path), debugstr_w(op->dst_file), + debugstr_w(op->src_descr), debugstr_w(op->src_tag) ); + + queue_file_op( &queue->copy_queue, op ); + return TRUE; +} + + +/*********************************************************************** + * SetupQueueCopyIndirectW (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params ) +{ + struct file_queue *queue = params->QueueHandle; + struct file_op *op; + + if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; + op->style = params->CopyStyle; + op->src_root = strdupW( params->SourceRootPath ); + op->src_path = strdupW( params->SourcePath ); + op->src_file = strdupW( params->SourceFilename ); + op->src_descr = strdupW( params->SourceDescription ); + op->src_tag = strdupW( params->SourceTagfile ); + op->dst_path = strdupW( params->TargetDirectory ); + op->dst_file = strdupW( params->TargetFilename ); + + /* some defaults */ + if (!op->src_file) op->src_file = op->dst_file; + if (params->LayoutInf) + { + get_src_file_info( params->LayoutInf, op ); + if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file ); + } + + TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n", + debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file), + debugstr_w(op->dst_path), debugstr_w(op->dst_file), + debugstr_w(op->src_descr), debugstr_w(op->src_tag) ); + + queue_file_op( &queue->copy_queue, op ); + return TRUE; +} + + +/*********************************************************************** + * SetupQueueCopyA (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file, + PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file, + DWORD style ) +{ + SP_FILE_COPY_PARAMS_A params; + + params.cbSize = sizeof(params); + params.QueueHandle = queue; + params.SourceRootPath = src_root; + params.SourcePath = src_path; + params.SourceFilename = src_file; + params.SourceDescription = src_descr; + params.SourceTagfile = src_tag; + params.TargetDirectory = dst_dir; + params.TargetFilename = dst_file; + params.CopyStyle = style; + params.LayoutInf = 0; + params.SecurityDescriptor = NULL; + return SetupQueueCopyIndirectA( ¶ms ); +} + + +/*********************************************************************** + * SetupQueueCopyW (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file, + PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file, + DWORD style ) +{ + SP_FILE_COPY_PARAMS_W params; + + params.cbSize = sizeof(params); + params.QueueHandle = queue; + params.SourceRootPath = src_root; + params.SourcePath = src_path; + params.SourceFilename = src_file; + params.SourceDescription = src_descr; + params.SourceTagfile = src_tag; + params.TargetDirectory = dst_dir; + params.TargetFilename = dst_file; + params.CopyStyle = style; + params.LayoutInf = 0; + params.SecurityDescriptor = NULL; + return SetupQueueCopyIndirectW( ¶ms ); +} + + +/*********************************************************************** + * SetupQueueDefaultCopyA (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file, + PCSTR dst_file, DWORD style ) +{ + SP_FILE_COPY_PARAMS_A params; + + params.cbSize = sizeof(params); + params.QueueHandle = queue; + params.SourceRootPath = src_root; + params.SourcePath = NULL; + params.SourceFilename = src_file; + params.SourceDescription = NULL; + params.SourceTagfile = NULL; + params.TargetDirectory = NULL; + params.TargetFilename = dst_file; + params.CopyStyle = style; + params.LayoutInf = hinf; + params.SecurityDescriptor = NULL; + return SetupQueueCopyIndirectA( ¶ms ); +} + + +/*********************************************************************** + * SetupQueueDefaultCopyW (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file, + PCWSTR dst_file, DWORD style ) +{ + SP_FILE_COPY_PARAMS_W params; + + params.cbSize = sizeof(params); + params.QueueHandle = queue; + params.SourceRootPath = src_root; + params.SourcePath = NULL; + params.SourceFilename = src_file; + params.SourceDescription = NULL; + params.SourceTagfile = NULL; + params.TargetDirectory = NULL; + params.TargetFilename = dst_file; + params.CopyStyle = style; + params.LayoutInf = hinf; + params.SecurityDescriptor = NULL; + return SetupQueueCopyIndirectW( ¶ms ); +} + + +/*********************************************************************** + * SetupQueueDeleteA (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 ) +{ + struct file_queue *queue = handle; + struct file_op *op; + + if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; + op->style = 0; + op->src_root = NULL; + op->src_path = NULL; + op->src_file = NULL; + op->src_descr = NULL; + op->src_tag = NULL; + op->dst_path = strdupAtoW( part1 ); + op->dst_file = strdupAtoW( part2 ); + queue_file_op( &queue->delete_queue, op ); + return TRUE; +} + + +/*********************************************************************** + * SetupQueueDeleteW (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 ) +{ + struct file_queue *queue = handle; + struct file_op *op; + + if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; + op->style = 0; + op->src_root = NULL; + op->src_path = NULL; + op->src_file = NULL; + op->src_descr = NULL; + op->src_tag = NULL; + op->dst_path = strdupW( part1 ); + op->dst_file = strdupW( part2 ); + queue_file_op( &queue->delete_queue, op ); + return TRUE; +} + + +/*********************************************************************** + * SetupQueueRenameA (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename, + PCSTR TargetPath, PCSTR TargetFilename ) +{ + struct file_queue *queue = handle; + struct file_op *op; + + if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; + op->style = 0; + op->src_root = NULL; + op->src_path = strdupAtoW( SourcePath ); + op->src_file = strdupAtoW( SourceFilename ); + op->src_descr = NULL; + op->src_tag = NULL; + op->dst_path = strdupAtoW( TargetPath ); + op->dst_file = strdupAtoW( TargetFilename ); + queue_file_op( &queue->rename_queue, op ); + return TRUE; +} + + +/*********************************************************************** + * SetupQueueRenameW (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename, + PCWSTR TargetPath, PCWSTR TargetFilename ) +{ + struct file_queue *queue = handle; + struct file_op *op; + + if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; + op->style = 0; + op->src_root = NULL; + op->src_path = strdupW( SourcePath ); + op->src_file = strdupW( SourceFilename ); + op->src_descr = NULL; + op->src_tag = NULL; + op->dst_path = strdupW( TargetPath ); + op->dst_file = strdupW( TargetFilename ); + queue_file_op( &queue->rename_queue, op ); + return TRUE; +} + + +/*********************************************************************** + * SetupQueueCopySectionA (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist, + PCSTR section, DWORD style ) +{ + UNICODE_STRING sectionW; + BOOL ret = FALSE; + + if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + if (!src_root) + ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style ); + else + { + UNICODE_STRING srcW; + if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root )) + { + ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style ); + RtlFreeUnicodeString( &srcW ); + } + else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + } + RtlFreeUnicodeString( §ionW ); + return ret; +} + + +/*********************************************************************** + * SetupQueueCopySectionW (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist, + PCWSTR section, DWORD style ) +{ + SP_FILE_COPY_PARAMS_W params; + INFCONTEXT context; + WCHAR dest[MAX_PATH], src[MAX_PATH]; + INT flags; + + TRACE( "hinf=%p/%p section=%s root=%s\n", + hinf, hlist, debugstr_w(section), debugstr_w(src_root) ); + + params.cbSize = sizeof(params); + params.QueueHandle = queue; + params.SourceRootPath = src_root; + params.SourcePath = NULL; + params.SourceDescription = NULL; + params.SourceTagfile = NULL; + params.TargetFilename = dest; + params.CopyStyle = style; + params.LayoutInf = hinf; + params.SecurityDescriptor = NULL; + + if (!hlist) hlist = hinf; + if (!hinf) hinf = hlist; + if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; + if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) return FALSE; + do + { + if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL )) + return FALSE; + if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0; + if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */ + + params.SourceFilename = *src ? src : NULL; + if (!SetupQueueCopyIndirectW( ¶ms )) return FALSE; + } while (SetupFindNextLine( &context, &context )); + return TRUE; +} + + +/*********************************************************************** + * SetupQueueDeleteSectionA (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section ) +{ + UNICODE_STRING sectionW; + BOOL ret = FALSE; + + if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) + { + ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer ); + RtlFreeUnicodeString( §ionW ); + } + else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return ret; +} + + +/*********************************************************************** + * SetupQueueDeleteSectionW (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section ) +{ + INFCONTEXT context; + WCHAR *dest_dir; + WCHAR buffer[MAX_PATH]; + BOOL ret = FALSE; + INT flags; + + TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) ); + + if (!hlist) hlist = hinf; + if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; + if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE; + do + { + if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) + goto done; + if (!SetupGetIntField( &context, 4, &flags )) flags = 0; + if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done; + } while (SetupFindNextLine( &context, &context )); + + ret = TRUE; + done: + HeapFree( GetProcessHeap(), 0, dest_dir ); + return ret; +} + + +/*********************************************************************** + * SetupQueueRenameSectionA (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section ) +{ + UNICODE_STRING sectionW; + BOOL ret = FALSE; + + if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) + { + ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer ); + RtlFreeUnicodeString( §ionW ); + } + else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return ret; +} + + +/*********************************************************************** + * SetupQueueRenameSectionW (SETUPAPI.@) + */ +BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section ) +{ + INFCONTEXT context; + WCHAR *dest_dir; + WCHAR src[MAX_PATH], dst[MAX_PATH]; + BOOL ret = FALSE; + + TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) ); + + if (!hlist) hlist = hinf; + if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; + if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE; + do + { + if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL )) + goto done; + if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) + goto done; + if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done; + } while (SetupFindNextLine( &context, &context )); + + ret = TRUE; + done: + HeapFree( GetProcessHeap(), 0, dest_dir ); + return ret; +} + + +/*********************************************************************** + * SetupCommitFileQueueA (SETUPAPI.@) + */ +BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler, + PVOID context ) +{ + struct callback_WtoA_context ctx; + + ctx.orig_context = context; + ctx.orig_handler = handler; + return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx ); +} + + +/*********************************************************************** + * create_full_pathW + * + * Recursively create all directories in the path. + */ +static BOOL create_full_pathW(const WCHAR *path) +{ + BOOL ret = TRUE; + int len; + WCHAR *new_path; + + new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR)); + strcpyW(new_path, path); + + while((len = strlenW(new_path)) && new_path[len - 1] == '\\') + new_path[len - 1] = 0; + + while(!CreateDirectoryW(new_path, NULL)) + { + WCHAR *slash; + DWORD last_error = GetLastError(); + + if(last_error == ERROR_ALREADY_EXISTS) + break; + + if(last_error != ERROR_PATH_NOT_FOUND) + { + ret = FALSE; + break; + } + + if(!(slash = strrchrW(new_path, '\\'))) + { + ret = FALSE; + break; + } + + len = slash - new_path; + new_path[len] = 0; + if(!create_full_pathW(new_path)) + { + ret = FALSE; + break; + } + new_path[len] = '\\'; + } + + HeapFree(GetProcessHeap(), 0, new_path); + return ret; +} + +BOOL static do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style) +{ + BOOL rc = FALSE; + BOOL docopy = TRUE; + + TRACE("copy %s to %s style 0x%lx\n",debugstr_w(source),debugstr_w(target),style); + + /* before copy processing */ + if (style & SP_COPY_REPLACEONLY) + { + if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES) + docopy = FALSE; + } + if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER)) + { + DWORD VersionSizeSource=0; + DWORD VersionSizeTarget=0; + DWORD zero=0; + + /* + * This is sort of an interesting workaround. You see, calling + * GetVersionInfoSize on a builtin dll loads that dll into memory + * and we do not properly unload builtin dlls.. so we effectively + * lock into memory all the targets we are replacing. This leads + * to problems when we try to register the replaced dlls. + * + * So I will test for the existence of the files first so that + * we just basically unconditionally replace the builtin versions. + */ + if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) && + (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES)) + { + VersionSizeSource = GetFileVersionInfoSizeW(source,&zero); + VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero); + } + + TRACE("SizeTarget %li ... SizeSource %li\n",VersionSizeTarget, + VersionSizeSource); + + if (VersionSizeSource && VersionSizeTarget) + { + LPVOID VersionSource; + LPVOID VersionTarget; + VS_FIXEDFILEINFO *TargetInfo; + VS_FIXEDFILEINFO *SourceInfo; + UINT length; + WCHAR SubBlock[2]={'\\',0}; + DWORD ret; + + VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource); + VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget); + + ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource); + if (ret) + ret = GetFileVersionInfoW(target, 0, VersionSizeTarget, + VersionTarget); + + if (ret) + { + ret = VerQueryValueW(VersionSource, SubBlock, + (LPVOID*)&SourceInfo, &length); + if (ret) + ret = VerQueryValueW(VersionTarget, SubBlock, + (LPVOID*)&TargetInfo, &length); + + if (ret) + { + TRACE("Versions: Source %li.%li target %li.%li\n", + SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS, + TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS); + + if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS) + { + FIXME("Notify that target version is greater..\n"); + docopy = FALSE; + } + else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS) + && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS)) + { + FIXME("Notify that target version is greater..\n"); + docopy = FALSE; + } + else if ((style & SP_COPY_NEWER_ONLY) && + (TargetInfo->dwFileVersionMS == + SourceInfo->dwFileVersionMS) + &&(TargetInfo->dwFileVersionLS == + SourceInfo->dwFileVersionLS)) + { + FIXME("Notify that target version is greater..\n"); + docopy = FALSE; + } + } + } + HeapFree(GetProcessHeap(),0,VersionSource); + HeapFree(GetProcessHeap(),0,VersionTarget); + } + } + if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE)) + { + if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) + { + FIXME("Notify user target file exists\n"); + docopy = FALSE; + } + } + if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE | + SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP)) + { + ERR("Unsupported style(s) 0x%lx\n",style); + } + + if (docopy) + { + rc = CopyFileW(source,target,FALSE); + TRACE("Did copy... rc was %i\n",rc); + } + + /* after copy processing */ + if (style & SP_COPY_DELETESOURCE) + { + if (rc) + DeleteFileW(source); + } + + return rc; +} + +/*********************************************************************** + * SetupCommitFileQueueW (SETUPAPI.@) + */ +BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler, + PVOID context ) +{ + struct file_queue *queue = handle; + struct file_op *op; + BOOL result = FALSE; + FILEPATHS_W paths; + UINT op_result; + + paths.Source = paths.Target = NULL; + + if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count) + return TRUE; /* nothing to do */ + + if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT)owner, 0 )) return FALSE; + + /* perform deletes */ + + if (queue->delete_queue.count) + { + if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE, + queue->delete_queue.count ))) goto done; + for (op = queue->delete_queue.head; op; op = op->next) + { + build_filepathsW( op, &paths ); + op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE); + if (op_result == FILEOP_ABORT) goto done; + while (op_result == FILEOP_DOIT) + { + TRACE( "deleting file %s\n", debugstr_w(paths.Target) ); + if (DeleteFileW( paths.Target )) break; /* success */ + paths.Win32Error = GetLastError(); + op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 ); + if (op_result == FILEOP_ABORT) goto done; + } + handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 ); + } + handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 ); + } + + /* perform renames */ + + if (queue->rename_queue.count) + { + if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME, + queue->rename_queue.count ))) goto done; + for (op = queue->rename_queue.head; op; op = op->next) + { + build_filepathsW( op, &paths ); + op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME); + if (op_result == FILEOP_ABORT) goto done; + while (op_result == FILEOP_DOIT) + { + TRACE( "renaming file %s -> %s\n", + debugstr_w(paths.Source), debugstr_w(paths.Target) ); + if (MoveFileW( paths.Source, paths.Target )) break; /* success */ + paths.Win32Error = GetLastError(); + op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 ); + if (op_result == FILEOP_ABORT) goto done; + } + handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 ); + } + handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 ); + } + + /* perform copies */ + + if (queue->copy_queue.count) + { + if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY, + queue->copy_queue.count ))) goto done; + for (op = queue->copy_queue.head; op; op = op->next) + { + WCHAR newpath[MAX_PATH]; + + build_filepathsW( op, &paths ); + op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY ); + if (op_result == FILEOP_ABORT) goto done; + if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT; + while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH) + { + TRACE( "copying file %s -> %s\n", + debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ), + debugstr_w(paths.Target) ); + if (op->dst_path) + { + if (!create_full_pathW( op->dst_path )) + { + paths.Win32Error = GetLastError(); + op_result = handler( context, SPFILENOTIFY_COPYERROR, + (UINT_PTR)&paths, (UINT_PTR)newpath ); + if (op_result == FILEOP_ABORT) goto done; + } + } + if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source, + paths.Target, op->style )) break; /* success */ + /* try to extract it from the cabinet file */ + if (op->src_tag) + { + if (extract_cabinet_file( op->src_tag, op->src_root, + paths.Source, paths.Target )) break; + } + paths.Win32Error = GetLastError(); + op_result = handler( context, SPFILENOTIFY_COPYERROR, + (UINT_PTR)&paths, (UINT_PTR)newpath ); + if (op_result == FILEOP_ABORT) goto done; + } + handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 ); + } + handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 ); + } + + + result = TRUE; + + done: + handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 ); + HeapFree( GetProcessHeap(), 0, (void *)paths.Source ); + HeapFree( GetProcessHeap(), 0, (void *)paths.Target ); + return result; +} + + +/*********************************************************************** + * SetupScanFileQueueA (SETUPAPI.@) + */ +BOOL WINAPI SetupScanFileQueueA( HSPFILEQ queue, DWORD flags, HWND window, + PSP_FILE_CALLBACK_A callback, PVOID context, PDWORD result ) +{ + FIXME("stub\n"); + return FALSE; +} + + +/*********************************************************************** + * SetupScanFileQueueW (SETUPAPI.@) + */ +BOOL WINAPI SetupScanFileQueueW( HSPFILEQ queue, DWORD flags, HWND window, + PSP_FILE_CALLBACK_W callback, PVOID context, PDWORD result ) +{ + FIXME("stub\n"); + return FALSE; +} + + +/*********************************************************************** + * SetupGetFileQueueCount (SETUPAPI.@) + */ +BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result ) +{ + struct file_queue *queue = handle; + + switch(op) + { + case FILEOP_COPY: + *result = queue->copy_queue.count; + return TRUE; + case FILEOP_RENAME: + *result = queue->rename_queue.count; + return TRUE; + case FILEOP_DELETE: + *result = queue->delete_queue.count; + return TRUE; + } + return FALSE; +} + + +/*********************************************************************** + * SetupGetFileQueueFlags (SETUPAPI.@) + */ +BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags ) +{ + struct file_queue *queue = handle; + *flags = queue->flags; + return TRUE; +} + + +/*********************************************************************** + * SetupSetFileQueueFlags (SETUPAPI.@) + */ +BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags ) +{ + struct file_queue *queue = handle; + queue->flags = (queue->flags & ~mask) | flags; + return TRUE; +} + + +/*********************************************************************** + * SetupInitDefaultQueueCallback (SETUPAPI.@) + */ +PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner ) +{ + return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL ); +} + + +/*********************************************************************** + * SetupInitDefaultQueueCallbackEx (SETUPAPI.@) + */ +PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg, + DWORD reserved1, PVOID reserved2 ) +{ + struct default_callback_context *context; + + if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) ))) + { + context->owner = owner; + context->progress = progress; + context->message = msg; + } + return context; +} + + +/*********************************************************************** + * SetupTermDefaultQueueCallback (SETUPAPI.@) + */ +void WINAPI SetupTermDefaultQueueCallback( PVOID context ) +{ + HeapFree( GetProcessHeap(), 0, context ); +} + + +/*********************************************************************** + * SetupDefaultQueueCallbackA (SETUPAPI.@) + */ +UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification, + UINT_PTR param1, UINT_PTR param2 ) +{ + FILEPATHS_A *paths = (FILEPATHS_A *)param1; + + switch(notification) + { + case SPFILENOTIFY_STARTQUEUE: + TRACE( "start queue\n" ); + return TRUE; + case SPFILENOTIFY_ENDQUEUE: + TRACE( "end queue\n" ); + return 0; + case SPFILENOTIFY_STARTSUBQUEUE: + TRACE( "start subqueue %d count %d\n", param1, param2 ); + return TRUE; + case SPFILENOTIFY_ENDSUBQUEUE: + TRACE( "end subqueue %d\n", param1 ); + return 0; + case SPFILENOTIFY_STARTDELETE: + TRACE( "start delete %s\n", debugstr_a(paths->Target) ); + return FILEOP_DOIT; + case SPFILENOTIFY_ENDDELETE: + TRACE( "end delete %s\n", debugstr_a(paths->Target) ); + return 0; + case SPFILENOTIFY_DELETEERROR: + ERR( "delete error %d %s\n", paths->Win32Error, debugstr_a(paths->Target) ); + return FILEOP_SKIP; + case SPFILENOTIFY_STARTRENAME: + TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); + return FILEOP_DOIT; + case SPFILENOTIFY_ENDRENAME: + TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); + return 0; + case SPFILENOTIFY_RENAMEERROR: + ERR( "rename error %d %s -> %s\n", paths->Win32Error, + debugstr_a(paths->Source), debugstr_a(paths->Target) ); + return FILEOP_SKIP; + case SPFILENOTIFY_STARTCOPY: + TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); + return FILEOP_DOIT; + case SPFILENOTIFY_ENDCOPY: + TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); + return 0; + case SPFILENOTIFY_COPYERROR: + ERR( "copy error %d %s -> %s\n", paths->Win32Error, + debugstr_a(paths->Source), debugstr_a(paths->Target) ); + return FILEOP_SKIP; + case SPFILENOTIFY_NEEDMEDIA: + TRACE( "need media\n" ); + return FILEOP_SKIP; + default: + FIXME( "notification %d params %x,%x\n", notification, param1, param2 ); + break; + } + return 0; +} + + +/*********************************************************************** + * SetupDefaultQueueCallbackW (SETUPAPI.@) + */ +UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification, + UINT_PTR param1, UINT_PTR param2 ) +{ + FILEPATHS_W *paths = (FILEPATHS_W *)param1; + + switch(notification) + { + case SPFILENOTIFY_STARTQUEUE: + TRACE( "start queue\n" ); + return TRUE; + case SPFILENOTIFY_ENDQUEUE: + TRACE( "end queue\n" ); + return 0; + case SPFILENOTIFY_STARTSUBQUEUE: + TRACE( "start subqueue %d count %d\n", param1, param2 ); + return TRUE; + case SPFILENOTIFY_ENDSUBQUEUE: + TRACE( "end subqueue %d\n", param1 ); + return 0; + case SPFILENOTIFY_STARTDELETE: + TRACE( "start delete %s\n", debugstr_w(paths->Target) ); + return FILEOP_DOIT; + case SPFILENOTIFY_ENDDELETE: + TRACE( "end delete %s\n", debugstr_w(paths->Target) ); + return 0; + case SPFILENOTIFY_DELETEERROR: + ERR( "delete error %d %s\n", paths->Win32Error, debugstr_w(paths->Target) ); + return FILEOP_SKIP; + case SPFILENOTIFY_STARTRENAME: + TRACE( "start rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); + return FILEOP_DOIT; + case SPFILENOTIFY_ENDRENAME: + TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); + return 0; + case SPFILENOTIFY_RENAMEERROR: + ERR( "rename error %d %s -> %s\n", paths->Win32Error, + debugstr_w(paths->Source), debugstr_w(paths->Target) ); + return FILEOP_SKIP; + case SPFILENOTIFY_STARTCOPY: + TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); + return FILEOP_DOIT; + case SPFILENOTIFY_ENDCOPY: + TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); + return 0; + case SPFILENOTIFY_COPYERROR: + ERR( "copy error %d %s -> %s\n", paths->Win32Error, + debugstr_w(paths->Source), debugstr_w(paths->Target) ); + return FILEOP_SKIP; + case SPFILENOTIFY_NEEDMEDIA: + TRACE( "need media\n" ); + return FILEOP_SKIP; + default: + FIXME( "notification %d params %x,%x\n", notification, param1, param2 ); + break; + } + return 0; +} diff --git a/reactos/lib/setupapi/rpc.c b/reactos/lib/setupapi/rpc.c index 1f7ab620a02..b29cdc4367e 100644 --- a/reactos/lib/setupapi/rpc.c +++ b/reactos/lib/setupapi/rpc.c @@ -1,82 +1,82 @@ -/* rpc.c */ - -#include -#include -#include - - -static RPC_BINDING_HANDLE LocalBindingHandle = NULL; - - -RPC_STATUS -PnpBindRpc(LPWSTR pszMachine, - RPC_BINDING_HANDLE* BindingHandle) -{ - PWSTR pszStringBinding = NULL; - RPC_STATUS Status; - - Status = RpcStringBindingComposeW(NULL, - L"ncacn_np", - pszMachine, - L"\\pipe\\umpnpmgr", - NULL, - &pszStringBinding); - if (Status != RPC_S_OK) - return Status; - - Status = RpcBindingFromStringBindingW(pszStringBinding, - BindingHandle); - - RpcStringFreeW(&pszStringBinding); - - return Status; -} - - -RPC_STATUS -PnpUnbindRpc(RPC_BINDING_HANDLE *BindingHandle) -{ - if (BindingHandle != NULL) - { - RpcBindingFree(*BindingHandle); - *BindingHandle = NULL; - } - - return RPC_S_OK; -} - - -RPC_STATUS -PnpGetLocalBindingHandle(RPC_BINDING_HANDLE *BindingHandle) -{ - if (LocalBindingHandle != NULL) - { - BindingHandle = LocalBindingHandle; - return RPC_S_OK; - } - - return PnpBindRpc(NULL, BindingHandle); -} - - -RPC_STATUS -PnpUnbindLocalBindingHandle(VOID) -{ - return PnpUnbindRpc(&LocalBindingHandle); -} - - -void __RPC_FAR * __RPC_USER -midl_user_allocate(size_t len) -{ - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); -} - - -void __RPC_USER -midl_user_free(void __RPC_FAR * ptr) -{ - HeapFree(GetProcessHeap(), 0, ptr); -} - -/* EOF */ +/* rpc.c */ + +#include +#include +#include + + +static RPC_BINDING_HANDLE LocalBindingHandle = NULL; + + +RPC_STATUS +PnpBindRpc(LPWSTR pszMachine, + RPC_BINDING_HANDLE* BindingHandle) +{ + PWSTR pszStringBinding = NULL; + RPC_STATUS Status; + + Status = RpcStringBindingComposeW(NULL, + L"ncacn_np", + pszMachine, + L"\\pipe\\umpnpmgr", + NULL, + &pszStringBinding); + if (Status != RPC_S_OK) + return Status; + + Status = RpcBindingFromStringBindingW(pszStringBinding, + BindingHandle); + + RpcStringFreeW(&pszStringBinding); + + return Status; +} + + +RPC_STATUS +PnpUnbindRpc(RPC_BINDING_HANDLE *BindingHandle) +{ + if (BindingHandle != NULL) + { + RpcBindingFree(*BindingHandle); + *BindingHandle = NULL; + } + + return RPC_S_OK; +} + + +RPC_STATUS +PnpGetLocalBindingHandle(RPC_BINDING_HANDLE *BindingHandle) +{ + if (LocalBindingHandle != NULL) + { + BindingHandle = LocalBindingHandle; + return RPC_S_OK; + } + + return PnpBindRpc(NULL, BindingHandle); +} + + +RPC_STATUS +PnpUnbindLocalBindingHandle(VOID) +{ + return PnpUnbindRpc(&LocalBindingHandle); +} + + +void __RPC_FAR * __RPC_USER +midl_user_allocate(size_t len) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); +} + + +void __RPC_USER +midl_user_free(void __RPC_FAR * ptr) +{ + HeapFree(GetProcessHeap(), 0, ptr); +} + +/* EOF */ diff --git a/reactos/lib/setupapi/setupapi.rc b/reactos/lib/setupapi/setupapi.rc index c33178e19e5..7cd2b0c979f 100644 --- a/reactos/lib/setupapi/setupapi.rc +++ b/reactos/lib/setupapi/setupapi.rc @@ -1,38 +1,38 @@ -/* - * Top level resource file for SETUPX - * - * Copyright 2001 Andreas Mohr - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "winnls.h" -#include "setupapi_private.h" - -#include "Cs.rc" -#include "Da.rc" -#include "De.rc" -#include "En.rc" -#include "Es.rc" -#include "Fr.rc" -#include "It.rc" -#include "Ja.rc" -#include "Nl.rc" -#include "Pt.rc" -#include "Ru.rc" -#include "Sv.rc" +/* + * Top level resource file for SETUPX + * + * Copyright 2001 Andreas Mohr + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winnls.h" +#include "setupapi_private.h" + +#include "Cs.rc" +#include "Da.rc" +#include "De.rc" +#include "En.rc" +#include "Es.rc" +#include "Fr.rc" +#include "It.rc" +#include "Ja.rc" +#include "Nl.rc" +#include "Pt.rc" +#include "Ru.rc" +#include "Sv.rc" diff --git a/reactos/lib/setupapi/setupapi.spec b/reactos/lib/setupapi/setupapi.spec index 834e000e36d..42c19fff93b 100644 --- a/reactos/lib/setupapi/setupapi.spec +++ b/reactos/lib/setupapi/setupapi.spec @@ -1,553 +1,553 @@ -@ stub AcquireSCMLock -@ stub AddMiniIconToList -@ stub AddTagToGroupOrderListEntry -@ stub AppendStringToMultiSz -@ stdcall AssertFail(str long str) -@ stub CMP_Init_Detection -@ stub CMP_RegisterNotification -@ stub CMP_Report_LogOn -@ stub CMP_UnregisterNotification -@ stub CMP_WaitNoPendingInstallEvents -@ stub CMP_WaitServices -@ stub CM_Add_Empty_Log_Conf -@ stub CM_Add_Empty_Log_Conf_Ex -@ stub CM_Add_IDA -@ stub CM_Add_IDW -@ stub CM_Add_ID_ExA -@ stub CM_Add_ID_ExW -@ stub CM_Add_Range -@ stub CM_Add_Res_Des -@ stub CM_Add_Res_Des_Ex -@ stdcall CM_Connect_MachineA(str ptr) -@ stdcall CM_Connect_MachineW(wstr ptr) -@ stub CM_Create_DevNodeA -@ stub CM_Create_DevNodeW -@ stub CM_Create_DevNode_ExA -@ stub CM_Create_DevNode_ExW -@ stub CM_Create_Range_List -@ stub CM_Delete_Class_Key -@ stub CM_Delete_Class_Key_Ex -@ stub CM_Delete_DevNode_Key -@ stub CM_Delete_DevNode_Key_Ex -@ stub CM_Delete_Range -@ stub CM_Detect_Resource_Conflict -@ stub CM_Detect_Resource_Conflict_Ex -@ stub CM_Disable_DevNode -@ stub CM_Disable_DevNode_Ex -@ stdcall CM_Disconnect_Machine(long) -@ stub CM_Dup_Range_List -@ stub CM_Enable_DevNode -@ stub CM_Enable_DevNode_Ex -@ stub CM_Enumerate_Classes -@ stub CM_Enumerate_Classes_Ex -@ stub CM_Enumerate_EnumeratorsA -@ stub CM_Enumerate_EnumeratorsW -@ stub CM_Enumerate_Enumerators_ExA -@ stub CM_Enumerate_Enumerators_ExW -@ stub CM_Find_Range -@ stub CM_First_Range -@ stub CM_Free_Log_Conf -@ stub CM_Free_Log_Conf_Ex -@ stub CM_Free_Log_Conf_Handle -@ stub CM_Free_Range_List -@ stub CM_Free_Res_Des -@ stub CM_Free_Res_Des_Ex -@ stub CM_Free_Res_Des_Handle -@ stdcall CM_Get_Child(ptr long long) -@ stdcall CM_Get_Child_Ex(ptr long long long) -@ stub CM_Get_Class_Key_NameA -@ stub CM_Get_Class_Key_NameW -@ stub CM_Get_Class_Key_Name_ExA -@ stub CM_Get_Class_Key_Name_ExW -@ stub CM_Get_Class_NameA -@ stub CM_Get_Class_NameW -@ stub CM_Get_Class_Name_ExA -@ stub CM_Get_Class_Name_ExW -@ stub CM_Get_Depth -@ stub CM_Get_Depth_Ex -@ stub CM_Get_DevNode_Registry_PropertyA -@ stub CM_Get_DevNode_Registry_PropertyW -@ stub CM_Get_DevNode_Registry_Property_ExA -@ stub CM_Get_DevNode_Registry_Property_ExW -@ stub CM_Get_DevNode_Status -@ stub CM_Get_DevNode_Status_Ex -@ stub CM_Get_Device_IDA -@ stub CM_Get_Device_IDW -@ stub CM_Get_Device_ID_ExA -@ stub CM_Get_Device_ID_ExW -@ stdcall CM_Get_Device_ID_ListA(str str long long) -@ stdcall CM_Get_Device_ID_ListW(wstr wstr long long) -@ stdcall CM_Get_Device_ID_List_ExA(str str long long long) -@ stdcall CM_Get_Device_ID_List_ExW(wstr wstr long long long) -@ stdcall CM_Get_Device_ID_List_SizeA(ptr str long) -@ stdcall CM_Get_Device_ID_List_SizeW(ptr wstr long) -@ stdcall CM_Get_Device_ID_List_Size_ExA(ptr str long long) -@ stdcall CM_Get_Device_ID_List_Size_ExW(ptr wstr long long) -@ stub CM_Get_Device_ID_Size -@ stub CM_Get_Device_ID_Size_Ex -@ stub CM_Get_Device_Interface_AliasA -@ stub CM_Get_Device_Interface_AliasW -@ stub CM_Get_Device_Interface_Alias_ExA -@ stub CM_Get_Device_Interface_Alias_ExW -@ stub CM_Get_Device_Interface_ListA -@ stub CM_Get_Device_Interface_ListW -@ stub CM_Get_Device_Interface_List_ExA -@ stub CM_Get_Device_Interface_List_ExW -@ stub CM_Get_Device_Interface_List_SizeA -@ stub CM_Get_Device_Interface_List_SizeW -@ stub CM_Get_Device_Interface_List_Size_ExA -@ stub CM_Get_Device_Interface_List_Size_ExW -@ stub CM_Get_First_Log_Conf -@ stub CM_Get_First_Log_Conf_Ex -@ stub CM_Get_Global_State -@ stub CM_Get_Global_State_Ex -@ stub CM_Get_HW_Prof_FlagsA -@ stub CM_Get_HW_Prof_FlagsW -@ stub CM_Get_HW_Prof_Flags_ExA -@ stub CM_Get_HW_Prof_Flags_ExW -@ stub CM_Get_Hardware_Profile_InfoA -@ stub CM_Get_Hardware_Profile_InfoW -@ stub CM_Get_Hardware_Profile_Info_ExA -@ stub CM_Get_Hardware_Profile_Info_ExW -@ stub CM_Get_Log_Conf_Priority -@ stub CM_Get_Log_Conf_Priority_Ex -@ stub CM_Get_Next_Log_Conf -@ stub CM_Get_Next_Log_Conf_Ex -@ stub CM_Get_Next_Res_Des -@ stub CM_Get_Next_Res_Des_Ex -@ stdcall CM_Get_Parent(ptr long long) -@ stdcall CM_Get_Parent_Ex(ptr long long long) -@ stub CM_Get_Res_Des_Data -@ stub CM_Get_Res_Des_Data_Ex -@ stub CM_Get_Res_Des_Data_Size -@ stub CM_Get_Res_Des_Data_Size_Ex -@ stdcall CM_Get_Sibling(ptr long long) -@ stdcall CM_Get_Sibling_Ex(ptr long long long) -@ stdcall CM_Get_Version() -@ stdcall CM_Get_Version_Ex(long) -@ stub CM_Intersect_Range_List -@ stub CM_Invert_Range_List -@ stub CM_Is_Dock_Station_Present -@ stdcall CM_Locate_DevNodeA(ptr str long) -@ stdcall CM_Locate_DevNodeW(ptr wstr long) -@ stdcall CM_Locate_DevNode_ExA(ptr str long long) -@ stdcall CM_Locate_DevNode_ExW(ptr wstr long long) -@ stub CM_Merge_Range_List -@ stub CM_Modify_Res_Des -@ stub CM_Modify_Res_Des_Ex -@ stub CM_Move_DevNode -@ stub CM_Move_DevNode_Ex -@ stub CM_Next_Range -@ stub CM_Open_Class_KeyA -@ stub CM_Open_Class_KeyW -@ stub CM_Open_Class_Key_ExA -@ stub CM_Open_Class_Key_ExW -@ stub CM_Open_DevNode_Key -@ stub CM_Open_DevNode_Key_Ex -@ stub CM_Query_Arbitrator_Free_Data -@ stub CM_Query_Arbitrator_Free_Data_Ex -@ stub CM_Query_Arbitrator_Free_Size -@ stub CM_Query_Arbitrator_Free_Size_Ex -@ stub CM_Query_Remove_SubTree -@ stub CM_Query_Remove_SubTree_Ex -@ stub CM_Reenumerate_DevNode -@ stub CM_Reenumerate_DevNode_Ex -@ stub CM_Register_Device_Driver -@ stub CM_Register_Device_Driver_Ex -@ stub CM_Register_Device_InterfaceA -@ stub CM_Register_Device_InterfaceW -@ stub CM_Register_Device_Interface_ExA -@ stub CM_Register_Device_Interface_ExW -@ stub CM_Remove_SubTree -@ stub CM_Remove_SubTree_Ex -@ stub CM_Remove_Unmarked_Children -@ stub CM_Remove_Unmarked_Children_Ex -@ stub CM_Request_Device_EjectA -@ stub CM_Request_Device_EjectW -@ stub CM_Request_Eject_PC -@ stub CM_Reset_Children_Marks -@ stub CM_Reset_Children_Marks_Ex -@ stub CM_Run_Detection -@ stub CM_Run_Detection_Ex -@ stub CM_Set_DevNode_Problem -@ stub CM_Set_DevNode_Problem_Ex -@ stub CM_Set_DevNode_Registry_PropertyA -@ stub CM_Set_DevNode_Registry_PropertyW -@ stub CM_Set_DevNode_Registry_Property_ExA -@ stub CM_Set_DevNode_Registry_Property_ExW -@ stub CM_Set_HW_Prof -@ stub CM_Set_HW_Prof_Ex -@ stub CM_Set_HW_Prof_FlagsA -@ stub CM_Set_HW_Prof_FlagsW -@ stub CM_Set_HW_Prof_Flags_ExA -@ stub CM_Set_HW_Prof_Flags_ExW -@ stub CM_Setup_DevNode -@ stub CM_Setup_DevNode_Ex -@ stub CM_Test_Range_Available -@ stub CM_Uninstall_DevNode -@ stub CM_Uninstall_DevNode_Ex -@ stub CM_Unregister_Device_InterfaceA -@ stub CM_Unregister_Device_InterfaceW -@ stub CM_Unregister_Device_Interface_ExA -@ stub CM_Unregister_Device_Interface_ExW -@ stdcall CaptureAndConvertAnsiArg(str ptr) -@ stdcall CaptureStringArg(wstr ptr) -@ stub CenterWindowRelativeToParent -@ stdcall ConcatenatePaths(wstr wstr long ptr) -@ stdcall DelayedMove(wstr wstr) -@ stub DelimStringToMultiSz -@ stub DestroyTextFileReadBuffer -@ stdcall DoesUserHavePrivilege(wstr) -@ stdcall DuplicateString(wstr) -@ stdcall EnablePrivilege(wstr long) -@ stub ExtensionPropSheetPageProc -@ stdcall FileExists(wstr ptr) -@ stub FreeStringArray -@ stub GetCurrentDriverSigningPolicy -@ stub GetNewInfName -@ stdcall GetSetFileTimestamp(wstr ptr ptr ptr long) -@ stub GetVersionInfoFromImage -@ stub InfIsFromOemLocation -@ stub InstallCatalog -@ stdcall InstallHinfSection(long long str long) InstallHinfSectionA -@ stdcall InstallHinfSectionA(long long str long) -@ stdcall InstallHinfSectionW(long long wstr long) -@ stub InstallStop -@ stub InstallStopEx -@ stdcall IsUserAdmin() -@ stub LookUpStringInTable -@ stub MemoryInitialize -@ stdcall MultiByteToUnicode(str long) -@ stub MultiSzFromSearchControl -@ stdcall MyFree(ptr) -@ stdcall MyGetFileTitle(wstr) -@ stdcall MyMalloc(long) -@ stdcall MyRealloc(ptr long) -@ stdcall OpenAndMapFileForRead(wstr ptr ptr ptr ptr) -@ stub OutOfMemory -@ stub QueryMultiSzValueToArray -@ stdcall QueryRegistryValue(long wstr ptr ptr ptr) -@ stub ReadAsciiOrUnicodeTextFile -@ stub RegistryDelnode -@ stdcall RetreiveFileSecurity(wstr ptr) -@ stub RetrieveServiceConfig -@ stub SearchForInfFile -@ stub SetArrayToMultiSzValue -@ stdcall SetupAddInstallSectionToDiskSpaceListA(long long long str ptr long) -@ stub SetupAddInstallSectionToDiskSpaceListW -@ stub SetupAddSectionToDiskSpaceListA -@ stub SetupAddSectionToDiskSpaceListW -@ stub SetupAddToDiskSpaceListA -@ stub SetupAddToDiskSpaceListW -@ stub SetupAddToSourceListA -@ stub SetupAddToSourceListW -@ stub SetupAdjustDiskSpaceListA -@ stub SetupAdjustDiskSpaceListW -@ stub SetupCancelTemporarySourceList -@ stdcall SetupCloseFileQueue(ptr) -@ stdcall SetupCloseInfFile(long) -@ stub SetupCloseLog -@ stdcall SetupCommitFileQueue(long long ptr ptr) SetupCommitFileQueueW -@ stdcall SetupCommitFileQueueA(long long ptr ptr) -@ stdcall SetupCommitFileQueueW(long long ptr ptr) -@ stub SetupCopyErrorA -@ stub SetupCopyErrorW -@ stdcall SetupCopyOEMInfA(str str long long ptr long ptr ptr) -@ stdcall SetupCopyOEMInfW(wstr wstr long long ptr long ptr ptr) -@ stdcall SetupCreateDiskSpaceListA(ptr long long) -@ stdcall SetupCreateDiskSpaceListW(ptr long long) -@ stub SetupDecompressOrCopyFileA -@ stub SetupDecompressOrCopyFileW -@ stub SetupDefaultQueueCallback -@ stdcall SetupDefaultQueueCallbackA(ptr long long long) -@ stdcall SetupDefaultQueueCallbackW(ptr long long long) -@ stub SetupDeleteErrorA -@ stub SetupDeleteErrorW -@ stdcall SetupDestroyDiskSpaceList(long) -@ stub SetupDiAskForOEMDisk -@ stdcall SetupDiBuildClassInfoList(long ptr long ptr) -@ stdcall SetupDiBuildClassInfoListExA(long ptr long ptr str ptr) -@ stdcall SetupDiBuildClassInfoListExW(long ptr long ptr wstr ptr) -@ stub SetupDiBuildDriverInfoList -@ stdcall SetupDiCallClassInstaller(long ptr ptr) -@ stub SetupDiCancelDriverInfoSearch -@ stub SetupDiChangeState -@ stdcall SetupDiClassGuidsFromNameA(str ptr long ptr) -@ stdcall SetupDiClassGuidsFromNameExA(str ptr long ptr str ptr) -@ stdcall SetupDiClassGuidsFromNameExW(wstr ptr long ptr wstr ptr) -@ stdcall SetupDiClassGuidsFromNameW(wstr ptr long ptr) -@ stdcall SetupDiClassNameFromGuidA(ptr str long ptr) -@ stdcall SetupDiClassNameFromGuidExA(ptr str long ptr wstr ptr) -@ stdcall SetupDiClassNameFromGuidExW(ptr wstr long ptr wstr ptr) -@ stdcall SetupDiClassNameFromGuidW(ptr wstr long ptr) -@ stub SetupDiCreateDevRegKeyA -@ stub SetupDiCreateDevRegKeyW -@ stub SetupDiCreateDeviceInfoA -@ stdcall SetupDiCreateDeviceInfoList(ptr ptr) -@ stdcall SetupDiCreateDeviceInfoListExA(ptr long str ptr) -@ stdcall SetupDiCreateDeviceInfoListExW(ptr long str ptr) -@ stub SetupDiCreateDeviceInfoW -@ stub SetupDiDeleteDevRegKey -@ stub SetupDiDeleteDeviceInfo -@ stub SetupDiDeleteDeviceInterfaceData -@ stub SetupDiDeleteDeviceRegKey -@ stub SetupDiDestroyClassImageList -@ stdcall SetupDiDestroyDeviceInfoList(long) -@ stub SetupDiDestroyDriverInfoList -@ stub SetupDiDrawMiniIcon -@ stdcall SetupDiEnumDeviceInfo(long long ptr) -@ stdcall SetupDiEnumDeviceInterfaces(long ptr ptr long ptr) -@ stub SetupDiEnumDriverInfoA -@ stub SetupDiEnumDriverInfoW -@ stdcall SetupDiGetActualSectionToInstallA(long str str long ptr ptr) -@ stdcall SetupDiGetActualSectionToInstallW(long wstr wstr long ptr ptr) -@ stub SetupDiGetClassBitmapIndex -@ stdcall SetupDiGetClassDescriptionA(ptr str long ptr) -@ stdcall SetupDiGetClassDescriptionExA(ptr str long ptr str ptr) -@ stdcall SetupDiGetClassDescriptionExW(ptr wstr long ptr wstr ptr) -@ stdcall SetupDiGetClassDescriptionW(ptr wstr long ptr) -@ stub SetupDiGetClassDevPropertySheetsA -@ stub SetupDiGetClassDevPropertySheetsW -@ stdcall SetupDiGetClassDevsA(ptr ptr long long) -@ stdcall SetupDiGetClassDevsExA(ptr str ptr long ptr str ptr) -@ stdcall SetupDiGetClassDevsExW(ptr wstr ptr long ptr wstr ptr) -@ stdcall SetupDiGetClassDevsW(ptr ptr long long) -@ stub SetupDiGetClassImageIndex -@ stub SetupDiGetClassImageList -@ stub SetupDiGetClassImageListExA -@ stub SetupDiGetClassImageListExW -@ stub SetupDiGetClassInstallParamsA -@ stub SetupDiGetClassInstallParamsW -@ stub SetupDiGetDeviceInfoListClass -@ stdcall SetupDiGetDeviceInfoListDetailA(ptr ptr) -@ stdcall SetupDiGetDeviceInfoListDetailW(ptr ptr) -@ stdcall SetupDiGetDeviceInstallParamsA(ptr ptr ptr) -@ stub SetupDiGetDeviceInstallParamsW -@ stub SetupDiGetDeviceInstanceIdA -@ stub SetupDiGetDeviceInstanceIdW -@ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr) -@ stub SetupDiGetDeviceRegistryPropertyW -@ stub SetupDiGetDriverInfoDetailA -@ stub SetupDiGetDriverInfoDetailW -@ stub SetupDiGetDriverInstallParamsA -@ stub SetupDiGetDriverInstallParamsW -@ stub SetupDiGetDeviceInterfaceAlias -@ stdcall SetupDiGetDeviceInterfaceDetailA(long ptr ptr long ptr ptr) -@ stdcall SetupDiGetDeviceInterfaceDetailW(long ptr ptr long ptr ptr) -@ stub SetupDiGetHwProfileFriendlyNameA -@ stub SetupDiGetHwProfileFriendlyNameExA -@ stub SetupDiGetHwProfileFriendlyNameExW -@ stub SetupDiGetHwProfileFriendlyNameW -@ stub SetupDiGetHwProfileList -@ stub SetupDiGetHwProfileListExA -@ stub SetupDiGetHwProfileListExW -@ stub SetupDiGetINFClassA -@ stub SetupDiGetINFClassW -@ stub SetupDiGetSelectedDevice -@ stub SetupDiGetSelectedDriverA -@ stub SetupDiGetSelectedDriverW -@ stub SetupDiGetWizardPage -@ stdcall SetupDiInstallClassA(long str long ptr) -@ stub SetupDiInstallClassExA -@ stub SetupDiInstallClassExW -@ stdcall SetupDiInstallClassW(long wstr long ptr) -@ stub SetupDiInstallDevice -@ stub SetupDiInstallDriverFiles -@ stub SetupDiLoadClassIcon -@ stub SetupDiMoveDuplicateDevice -@ stdcall SetupDiOpenClassRegKey(ptr long) -@ stdcall SetupDiOpenClassRegKeyExA(ptr long long str ptr) -@ stdcall SetupDiOpenClassRegKeyExW(ptr long long wstr ptr) -@ stdcall SetupDiOpenDevRegKey(ptr ptr long long long long) -@ stub SetupDiOpenDeviceInfoA -@ stub SetupDiOpenDeviceInfoW -@ stdcall SetupDiOpenDeviceInterfaceA(ptr str long ptr) -@ stub SetupDiOpenDeviceInterfaceRegKey -@ stdcall SetupDiOpenDeviceInterfaceW(ptr wstr long ptr) -@ stub SetupDiRegisterDeviceInfo -@ stub SetupDiRemoveDevice -@ stub SetupDiRemoveDeviceInterface -@ stub SetupDiSelectDevice -@ stub SetupDiSelectOEMDrv -@ stdcall SetupDiSetClassInstallParamsA(ptr ptr ptr long) -@ stub SetupDiSetClassInstallParamsW -@ stub SetupDiSetDeviceInstallParamsA -@ stub SetupDiSetDeviceInstallParamsW -@ stub SetupDiSetDeviceRegistryPropertyA -@ stub SetupDiSetDeviceRegistryPropertyW -@ stub SetupDiSetDriverInstallParamsA -@ stub SetupDiSetDriverInstallParamsW -@ stub SetupDiSetSelectedDevice -@ stub SetupDiSetSelectedDriverA -@ stub SetupDiSetSelectedDriverW -@ stub SetupDiUnremoveDevice -@ stub SetupDuplicateDiskSpaceListA -@ stub SetupDuplicateDiskSpaceListW -@ stdcall SetupFindFirstLineA(long str str ptr) -@ stdcall SetupFindFirstLineW(long wstr wstr ptr) -@ stdcall SetupFindNextLine(ptr ptr) -@ stdcall SetupFindNextMatchLineA(ptr str ptr) -@ stdcall SetupFindNextMatchLineW(ptr wstr ptr) -@ stub SetupFreeSourceListA -@ stub SetupFreeSourceListW -@ stub SetupGetBackupInformationA -@ stub SetupGetBackupInformationW -@ stdcall SetupGetBinaryField(ptr long ptr long ptr) -@ stdcall SetupGetFieldCount(ptr) -@ stub SetupGetFileCompressionInfoA -@ stub SetupGetFileCompressionInfoW -@ stdcall SetupGetFileQueueCount(long long ptr) -@ stdcall SetupGetFileQueueFlags(long ptr) -@ stub SetupGetInfFileListA -@ stub SetupGetInfFileListW -@ stdcall SetupGetInfInformationA(ptr long ptr long ptr) -@ stub SetupGetInfInformationW -@ stub SetupGetInfSections -@ stdcall SetupGetIntField(ptr long ptr) -@ stdcall SetupGetLineByIndexA(long str long ptr) -@ stdcall SetupGetLineByIndexW(long wstr long ptr) -@ stdcall SetupGetLineCountA(long str) -@ stdcall SetupGetLineCountW(long wstr) -@ stdcall SetupGetLineTextA(ptr long str str ptr long ptr) -@ stdcall SetupGetLineTextW(ptr long wstr wstr ptr long ptr) -@ stdcall SetupGetMultiSzFieldA(ptr long ptr long ptr) -@ stdcall SetupGetMultiSzFieldW(ptr long ptr long ptr) -@ stub SetupGetSourceFileLocationA -@ stub SetupGetSourceFileLocationW -@ stub SetupGetSourceFileSizeA -@ stub SetupGetSourceFileSizeW -@ stub SetupGetSourceInfoA -@ stub SetupGetSourceInfoW -@ stdcall SetupGetStringFieldA(ptr long ptr long ptr) -@ stdcall SetupGetStringFieldW(ptr long ptr long ptr) -@ stub SetupGetTargetPathA -@ stub SetupGetTargetPathW -@ stdcall SetupInitDefaultQueueCallback(long) -@ stdcall SetupInitDefaultQueueCallbackEx(long long long long ptr) -@ stdcall SetupInitializeFileLogA(str long) -@ stdcall SetupInitializeFileLogW(wstr long) -@ stub SetupInstallFileA -@ stub SetupInstallFileExA -@ stub SetupInstallFileExW -@ stub SetupInstallFileW -@ stdcall SetupInstallFilesFromInfSectionA(long long long str str long) -@ stdcall SetupInstallFilesFromInfSectionW(long long long wstr wstr long) -@ stdcall SetupInstallFromInfSectionA(long long str long long str long ptr ptr long ptr) -@ stdcall SetupInstallFromInfSectionW(long long wstr long long wstr long ptr ptr long ptr) -@ stub SetupInstallServicesFromInfSectionA -@ stub SetupInstallServicesFromInfSectionExA -@ stub SetupInstallServicesFromInfSectionExW -@ stub SetupInstallServicesFromInfSectionW -@ stdcall SetupIterateCabinetA(str long ptr ptr) -@ stdcall SetupIterateCabinetW(wstr long ptr ptr) -@ stub SetupLogErrorA -@ stub SetupLogErrorW -@ stub SetupLogFileA -@ stub SetupLogFileW -@ stdcall SetupOpenAppendInfFileA(str long ptr) -@ stdcall SetupOpenAppendInfFileW(wstr long ptr) -@ stdcall SetupOpenFileQueue() -@ stdcall SetupOpenInfFileA(str str long ptr) -@ stdcall SetupOpenInfFileW(wstr wstr long ptr) -@ stdcall SetupOpenMasterInf() -@ stub SetupPromptForDiskA -@ stub SetupPromptForDiskW -@ stub SetupPromptReboot -@ stub SetupQueryDrivesInDiskSpaceListA -@ stub SetupQueryDrivesInDiskSpaceListW -@ stub SetupQueryFileLogA -@ stub SetupQueryFileLogW -@ stub SetupQueryInfFileInformationA -@ stub SetupQueryInfFileInformationW -@ stub SetupQueryInfOriginalFileInformationA -@ stub SetupQueryInfOriginalFileInformationW -@ stub SetupQueryInfVersionInformationA -@ stub SetupQueryInfVersionInformationW -@ stub SetupQuerySourceListA -@ stub SetupQuerySourceListW -@ stdcall SetupQuerySpaceRequiredOnDriveA(long str ptr ptr long) -@ stub SetupQuerySpaceRequiredOnDriveW -@ stdcall SetupQueueCopyA(long str str str str str str str long) -@ stdcall SetupQueueCopyIndirectA(ptr) -@ stdcall SetupQueueCopyIndirectW(ptr) -@ stdcall SetupQueueCopySectionA(long str long long str long) -@ stdcall SetupQueueCopySectionW(long wstr long long wstr long) -@ stdcall SetupQueueCopyW(long wstr wstr wstr wstr wstr wstr wstr long) -@ stdcall SetupQueueDefaultCopyA(long long str str str long) -@ stdcall SetupQueueDefaultCopyW(long long wstr wstr wstr long) -@ stdcall SetupQueueDeleteA(long str str) -@ stdcall SetupQueueDeleteSectionA(long long long str) -@ stdcall SetupQueueDeleteSectionW(long long long wstr) -@ stdcall SetupQueueDeleteW(long wstr wstr) -@ stdcall SetupQueueRenameA(long str str str str) -@ stdcall SetupQueueRenameSectionA(long long long str) -@ stdcall SetupQueueRenameSectionW(long long long wstr) -@ stdcall SetupQueueRenameW(long wstr wstr wstr wstr) -@ stub SetupRemoveFileLogEntryA -@ stub SetupRemoveFileLogEntryW -@ stub SetupRemoveFromDiskSpaceListA -@ stub SetupRemoveFromDiskSpaceListW -@ stub SetupRemoveFromSourceListA -@ stub SetupRemoveFromSourceListW -@ stub SetupRemoveInstallSectionFromDiskSpaceListA -@ stub SetupRemoveInstallSectionFromDiskSpaceListW -@ stub SetupRemoveSectionFromDiskSpaceListA -@ stub SetupRemoveSectionFromDiskSpaceListW -@ stub SetupRenameErrorA -@ stub SetupRenameErrorW -@ stub SetupScanFileQueue -@ stdcall SetupScanFileQueueA(long long long ptr ptr ptr) -@ stdcall SetupScanFileQueueW(long long long ptr ptr ptr) -@ stdcall SetupSetDirectoryIdA(long long str) -@ stub SetupSetDirectoryIdExA -@ stub SetupSetDirectoryIdExW -@ stdcall SetupSetDirectoryIdW(long long wstr) -@ stub SetupFileQueueAlternatePlatformA -@ stub SetupFileQueueAlternatePlatformW -@ stdcall SetupSetFileQueueFlags(long long long) -@ stub SetupSetPlatformPathOverrideA -@ stub SetupSetPlatformPathOverrideW -@ stub SetupSetSourceListA -@ stub SetupSetSourceListW -@ stdcall SetupTermDefaultQueueCallback(ptr) -@ stdcall SetupTerminateFileLog(long) -@ stub ShouldDeviceBeExcluded -@ stdcall StampFileSecurity(wstr ptr) -@ stdcall StringTableAddString(ptr wstr long) -@ stub StringTableAddStringEx -@ stdcall StringTableDestroy(ptr) -@ stub StringTableDuplicate -@ stub StringTableEnum -@ stub StringTableGetExtraData -@ stdcall StringTableInitialize() -@ stub StringTableInitializeEx -@ stdcall StringTableLookUpString(ptr wstr long) -@ stub StringTableLookUpStringEx -@ stub StringTableSetExtraData -@ stdcall StringTableStringFromId(ptr long) -@ stdcall StringTableStringFromIdEx(ptr long ptr ptr) -@ stdcall StringTableTrim(ptr) -@ stdcall TakeOwnershipOfFile(wstr) -@ stdcall UnicodeToMultiByte(wstr long) -@ stdcall UnmapAndCloseFile(long long ptr) -@ stub VerifyCatalogFile -@ stub VerifyFile -@ stub pSetupAccessRunOnceNodeList -@ stub pSetupAddMiniIconToList -@ stub pSetupAddTagToGroupOrderListEntry -@ stub pSetupAppendStringToMultiSz -@ stub pSetupDestroyRunOnceNodeList -@ stub pSetupDirectoryIdToPath -@ stub pSetupGetField -@ stub pSetupGetGlobalFlags -@ stub pSetupGetOsLoaderDriveAndPath -@ stub pSetupGetQueueFlags -@ stub pSetupGetVersionDatum -@ stub pSetupGuidFromString -@ stub pSetupIsGuidNull -@ stub pSetupMakeSurePathExists -@ stub pSetupSetGlobalFlags -@ stub pSetupSetQueueFlags -@ stub pSetupSetSystemSourceFlags -@ stub pSetupStringFromGuid -@ stub pSetupVerifyQueuedCatalogs +@ stub AcquireSCMLock +@ stub AddMiniIconToList +@ stub AddTagToGroupOrderListEntry +@ stub AppendStringToMultiSz +@ stdcall AssertFail(str long str) +@ stub CMP_Init_Detection +@ stub CMP_RegisterNotification +@ stub CMP_Report_LogOn +@ stub CMP_UnregisterNotification +@ stub CMP_WaitNoPendingInstallEvents +@ stub CMP_WaitServices +@ stub CM_Add_Empty_Log_Conf +@ stub CM_Add_Empty_Log_Conf_Ex +@ stub CM_Add_IDA +@ stub CM_Add_IDW +@ stub CM_Add_ID_ExA +@ stub CM_Add_ID_ExW +@ stub CM_Add_Range +@ stub CM_Add_Res_Des +@ stub CM_Add_Res_Des_Ex +@ stdcall CM_Connect_MachineA(str ptr) +@ stdcall CM_Connect_MachineW(wstr ptr) +@ stub CM_Create_DevNodeA +@ stub CM_Create_DevNodeW +@ stub CM_Create_DevNode_ExA +@ stub CM_Create_DevNode_ExW +@ stub CM_Create_Range_List +@ stub CM_Delete_Class_Key +@ stub CM_Delete_Class_Key_Ex +@ stub CM_Delete_DevNode_Key +@ stub CM_Delete_DevNode_Key_Ex +@ stub CM_Delete_Range +@ stub CM_Detect_Resource_Conflict +@ stub CM_Detect_Resource_Conflict_Ex +@ stub CM_Disable_DevNode +@ stub CM_Disable_DevNode_Ex +@ stdcall CM_Disconnect_Machine(long) +@ stub CM_Dup_Range_List +@ stub CM_Enable_DevNode +@ stub CM_Enable_DevNode_Ex +@ stub CM_Enumerate_Classes +@ stub CM_Enumerate_Classes_Ex +@ stub CM_Enumerate_EnumeratorsA +@ stub CM_Enumerate_EnumeratorsW +@ stub CM_Enumerate_Enumerators_ExA +@ stub CM_Enumerate_Enumerators_ExW +@ stub CM_Find_Range +@ stub CM_First_Range +@ stub CM_Free_Log_Conf +@ stub CM_Free_Log_Conf_Ex +@ stub CM_Free_Log_Conf_Handle +@ stub CM_Free_Range_List +@ stub CM_Free_Res_Des +@ stub CM_Free_Res_Des_Ex +@ stub CM_Free_Res_Des_Handle +@ stdcall CM_Get_Child(ptr long long) +@ stdcall CM_Get_Child_Ex(ptr long long long) +@ stub CM_Get_Class_Key_NameA +@ stub CM_Get_Class_Key_NameW +@ stub CM_Get_Class_Key_Name_ExA +@ stub CM_Get_Class_Key_Name_ExW +@ stub CM_Get_Class_NameA +@ stub CM_Get_Class_NameW +@ stub CM_Get_Class_Name_ExA +@ stub CM_Get_Class_Name_ExW +@ stub CM_Get_Depth +@ stub CM_Get_Depth_Ex +@ stub CM_Get_DevNode_Registry_PropertyA +@ stub CM_Get_DevNode_Registry_PropertyW +@ stub CM_Get_DevNode_Registry_Property_ExA +@ stub CM_Get_DevNode_Registry_Property_ExW +@ stub CM_Get_DevNode_Status +@ stub CM_Get_DevNode_Status_Ex +@ stub CM_Get_Device_IDA +@ stub CM_Get_Device_IDW +@ stub CM_Get_Device_ID_ExA +@ stub CM_Get_Device_ID_ExW +@ stdcall CM_Get_Device_ID_ListA(str str long long) +@ stdcall CM_Get_Device_ID_ListW(wstr wstr long long) +@ stdcall CM_Get_Device_ID_List_ExA(str str long long long) +@ stdcall CM_Get_Device_ID_List_ExW(wstr wstr long long long) +@ stdcall CM_Get_Device_ID_List_SizeA(ptr str long) +@ stdcall CM_Get_Device_ID_List_SizeW(ptr wstr long) +@ stdcall CM_Get_Device_ID_List_Size_ExA(ptr str long long) +@ stdcall CM_Get_Device_ID_List_Size_ExW(ptr wstr long long) +@ stub CM_Get_Device_ID_Size +@ stub CM_Get_Device_ID_Size_Ex +@ stub CM_Get_Device_Interface_AliasA +@ stub CM_Get_Device_Interface_AliasW +@ stub CM_Get_Device_Interface_Alias_ExA +@ stub CM_Get_Device_Interface_Alias_ExW +@ stub CM_Get_Device_Interface_ListA +@ stub CM_Get_Device_Interface_ListW +@ stub CM_Get_Device_Interface_List_ExA +@ stub CM_Get_Device_Interface_List_ExW +@ stub CM_Get_Device_Interface_List_SizeA +@ stub CM_Get_Device_Interface_List_SizeW +@ stub CM_Get_Device_Interface_List_Size_ExA +@ stub CM_Get_Device_Interface_List_Size_ExW +@ stub CM_Get_First_Log_Conf +@ stub CM_Get_First_Log_Conf_Ex +@ stub CM_Get_Global_State +@ stub CM_Get_Global_State_Ex +@ stub CM_Get_HW_Prof_FlagsA +@ stub CM_Get_HW_Prof_FlagsW +@ stub CM_Get_HW_Prof_Flags_ExA +@ stub CM_Get_HW_Prof_Flags_ExW +@ stub CM_Get_Hardware_Profile_InfoA +@ stub CM_Get_Hardware_Profile_InfoW +@ stub CM_Get_Hardware_Profile_Info_ExA +@ stub CM_Get_Hardware_Profile_Info_ExW +@ stub CM_Get_Log_Conf_Priority +@ stub CM_Get_Log_Conf_Priority_Ex +@ stub CM_Get_Next_Log_Conf +@ stub CM_Get_Next_Log_Conf_Ex +@ stub CM_Get_Next_Res_Des +@ stub CM_Get_Next_Res_Des_Ex +@ stdcall CM_Get_Parent(ptr long long) +@ stdcall CM_Get_Parent_Ex(ptr long long long) +@ stub CM_Get_Res_Des_Data +@ stub CM_Get_Res_Des_Data_Ex +@ stub CM_Get_Res_Des_Data_Size +@ stub CM_Get_Res_Des_Data_Size_Ex +@ stdcall CM_Get_Sibling(ptr long long) +@ stdcall CM_Get_Sibling_Ex(ptr long long long) +@ stdcall CM_Get_Version() +@ stdcall CM_Get_Version_Ex(long) +@ stub CM_Intersect_Range_List +@ stub CM_Invert_Range_List +@ stub CM_Is_Dock_Station_Present +@ stdcall CM_Locate_DevNodeA(ptr str long) +@ stdcall CM_Locate_DevNodeW(ptr wstr long) +@ stdcall CM_Locate_DevNode_ExA(ptr str long long) +@ stdcall CM_Locate_DevNode_ExW(ptr wstr long long) +@ stub CM_Merge_Range_List +@ stub CM_Modify_Res_Des +@ stub CM_Modify_Res_Des_Ex +@ stub CM_Move_DevNode +@ stub CM_Move_DevNode_Ex +@ stub CM_Next_Range +@ stub CM_Open_Class_KeyA +@ stub CM_Open_Class_KeyW +@ stub CM_Open_Class_Key_ExA +@ stub CM_Open_Class_Key_ExW +@ stub CM_Open_DevNode_Key +@ stub CM_Open_DevNode_Key_Ex +@ stub CM_Query_Arbitrator_Free_Data +@ stub CM_Query_Arbitrator_Free_Data_Ex +@ stub CM_Query_Arbitrator_Free_Size +@ stub CM_Query_Arbitrator_Free_Size_Ex +@ stub CM_Query_Remove_SubTree +@ stub CM_Query_Remove_SubTree_Ex +@ stub CM_Reenumerate_DevNode +@ stub CM_Reenumerate_DevNode_Ex +@ stub CM_Register_Device_Driver +@ stub CM_Register_Device_Driver_Ex +@ stub CM_Register_Device_InterfaceA +@ stub CM_Register_Device_InterfaceW +@ stub CM_Register_Device_Interface_ExA +@ stub CM_Register_Device_Interface_ExW +@ stub CM_Remove_SubTree +@ stub CM_Remove_SubTree_Ex +@ stub CM_Remove_Unmarked_Children +@ stub CM_Remove_Unmarked_Children_Ex +@ stub CM_Request_Device_EjectA +@ stub CM_Request_Device_EjectW +@ stub CM_Request_Eject_PC +@ stub CM_Reset_Children_Marks +@ stub CM_Reset_Children_Marks_Ex +@ stub CM_Run_Detection +@ stub CM_Run_Detection_Ex +@ stub CM_Set_DevNode_Problem +@ stub CM_Set_DevNode_Problem_Ex +@ stub CM_Set_DevNode_Registry_PropertyA +@ stub CM_Set_DevNode_Registry_PropertyW +@ stub CM_Set_DevNode_Registry_Property_ExA +@ stub CM_Set_DevNode_Registry_Property_ExW +@ stub CM_Set_HW_Prof +@ stub CM_Set_HW_Prof_Ex +@ stub CM_Set_HW_Prof_FlagsA +@ stub CM_Set_HW_Prof_FlagsW +@ stub CM_Set_HW_Prof_Flags_ExA +@ stub CM_Set_HW_Prof_Flags_ExW +@ stub CM_Setup_DevNode +@ stub CM_Setup_DevNode_Ex +@ stub CM_Test_Range_Available +@ stub CM_Uninstall_DevNode +@ stub CM_Uninstall_DevNode_Ex +@ stub CM_Unregister_Device_InterfaceA +@ stub CM_Unregister_Device_InterfaceW +@ stub CM_Unregister_Device_Interface_ExA +@ stub CM_Unregister_Device_Interface_ExW +@ stdcall CaptureAndConvertAnsiArg(str ptr) +@ stdcall CaptureStringArg(wstr ptr) +@ stub CenterWindowRelativeToParent +@ stdcall ConcatenatePaths(wstr wstr long ptr) +@ stdcall DelayedMove(wstr wstr) +@ stub DelimStringToMultiSz +@ stub DestroyTextFileReadBuffer +@ stdcall DoesUserHavePrivilege(wstr) +@ stdcall DuplicateString(wstr) +@ stdcall EnablePrivilege(wstr long) +@ stub ExtensionPropSheetPageProc +@ stdcall FileExists(wstr ptr) +@ stub FreeStringArray +@ stub GetCurrentDriverSigningPolicy +@ stub GetNewInfName +@ stdcall GetSetFileTimestamp(wstr ptr ptr ptr long) +@ stub GetVersionInfoFromImage +@ stub InfIsFromOemLocation +@ stub InstallCatalog +@ stdcall InstallHinfSection(long long str long) InstallHinfSectionA +@ stdcall InstallHinfSectionA(long long str long) +@ stdcall InstallHinfSectionW(long long wstr long) +@ stub InstallStop +@ stub InstallStopEx +@ stdcall IsUserAdmin() +@ stub LookUpStringInTable +@ stub MemoryInitialize +@ stdcall MultiByteToUnicode(str long) +@ stub MultiSzFromSearchControl +@ stdcall MyFree(ptr) +@ stdcall MyGetFileTitle(wstr) +@ stdcall MyMalloc(long) +@ stdcall MyRealloc(ptr long) +@ stdcall OpenAndMapFileForRead(wstr ptr ptr ptr ptr) +@ stub OutOfMemory +@ stub QueryMultiSzValueToArray +@ stdcall QueryRegistryValue(long wstr ptr ptr ptr) +@ stub ReadAsciiOrUnicodeTextFile +@ stub RegistryDelnode +@ stdcall RetreiveFileSecurity(wstr ptr) +@ stub RetrieveServiceConfig +@ stub SearchForInfFile +@ stub SetArrayToMultiSzValue +@ stdcall SetupAddInstallSectionToDiskSpaceListA(long long long str ptr long) +@ stub SetupAddInstallSectionToDiskSpaceListW +@ stub SetupAddSectionToDiskSpaceListA +@ stub SetupAddSectionToDiskSpaceListW +@ stub SetupAddToDiskSpaceListA +@ stub SetupAddToDiskSpaceListW +@ stub SetupAddToSourceListA +@ stub SetupAddToSourceListW +@ stub SetupAdjustDiskSpaceListA +@ stub SetupAdjustDiskSpaceListW +@ stub SetupCancelTemporarySourceList +@ stdcall SetupCloseFileQueue(ptr) +@ stdcall SetupCloseInfFile(long) +@ stub SetupCloseLog +@ stdcall SetupCommitFileQueue(long long ptr ptr) SetupCommitFileQueueW +@ stdcall SetupCommitFileQueueA(long long ptr ptr) +@ stdcall SetupCommitFileQueueW(long long ptr ptr) +@ stub SetupCopyErrorA +@ stub SetupCopyErrorW +@ stdcall SetupCopyOEMInfA(str str long long ptr long ptr ptr) +@ stdcall SetupCopyOEMInfW(wstr wstr long long ptr long ptr ptr) +@ stdcall SetupCreateDiskSpaceListA(ptr long long) +@ stdcall SetupCreateDiskSpaceListW(ptr long long) +@ stub SetupDecompressOrCopyFileA +@ stub SetupDecompressOrCopyFileW +@ stub SetupDefaultQueueCallback +@ stdcall SetupDefaultQueueCallbackA(ptr long long long) +@ stdcall SetupDefaultQueueCallbackW(ptr long long long) +@ stub SetupDeleteErrorA +@ stub SetupDeleteErrorW +@ stdcall SetupDestroyDiskSpaceList(long) +@ stub SetupDiAskForOEMDisk +@ stdcall SetupDiBuildClassInfoList(long ptr long ptr) +@ stdcall SetupDiBuildClassInfoListExA(long ptr long ptr str ptr) +@ stdcall SetupDiBuildClassInfoListExW(long ptr long ptr wstr ptr) +@ stub SetupDiBuildDriverInfoList +@ stdcall SetupDiCallClassInstaller(long ptr ptr) +@ stub SetupDiCancelDriverInfoSearch +@ stub SetupDiChangeState +@ stdcall SetupDiClassGuidsFromNameA(str ptr long ptr) +@ stdcall SetupDiClassGuidsFromNameExA(str ptr long ptr str ptr) +@ stdcall SetupDiClassGuidsFromNameExW(wstr ptr long ptr wstr ptr) +@ stdcall SetupDiClassGuidsFromNameW(wstr ptr long ptr) +@ stdcall SetupDiClassNameFromGuidA(ptr str long ptr) +@ stdcall SetupDiClassNameFromGuidExA(ptr str long ptr wstr ptr) +@ stdcall SetupDiClassNameFromGuidExW(ptr wstr long ptr wstr ptr) +@ stdcall SetupDiClassNameFromGuidW(ptr wstr long ptr) +@ stub SetupDiCreateDevRegKeyA +@ stub SetupDiCreateDevRegKeyW +@ stub SetupDiCreateDeviceInfoA +@ stdcall SetupDiCreateDeviceInfoList(ptr ptr) +@ stdcall SetupDiCreateDeviceInfoListExA(ptr long str ptr) +@ stdcall SetupDiCreateDeviceInfoListExW(ptr long str ptr) +@ stub SetupDiCreateDeviceInfoW +@ stub SetupDiDeleteDevRegKey +@ stub SetupDiDeleteDeviceInfo +@ stub SetupDiDeleteDeviceInterfaceData +@ stub SetupDiDeleteDeviceRegKey +@ stub SetupDiDestroyClassImageList +@ stdcall SetupDiDestroyDeviceInfoList(long) +@ stub SetupDiDestroyDriverInfoList +@ stub SetupDiDrawMiniIcon +@ stdcall SetupDiEnumDeviceInfo(long long ptr) +@ stdcall SetupDiEnumDeviceInterfaces(long ptr ptr long ptr) +@ stub SetupDiEnumDriverInfoA +@ stub SetupDiEnumDriverInfoW +@ stdcall SetupDiGetActualSectionToInstallA(long str str long ptr ptr) +@ stdcall SetupDiGetActualSectionToInstallW(long wstr wstr long ptr ptr) +@ stub SetupDiGetClassBitmapIndex +@ stdcall SetupDiGetClassDescriptionA(ptr str long ptr) +@ stdcall SetupDiGetClassDescriptionExA(ptr str long ptr str ptr) +@ stdcall SetupDiGetClassDescriptionExW(ptr wstr long ptr wstr ptr) +@ stdcall SetupDiGetClassDescriptionW(ptr wstr long ptr) +@ stub SetupDiGetClassDevPropertySheetsA +@ stub SetupDiGetClassDevPropertySheetsW +@ stdcall SetupDiGetClassDevsA(ptr ptr long long) +@ stdcall SetupDiGetClassDevsExA(ptr str ptr long ptr str ptr) +@ stdcall SetupDiGetClassDevsExW(ptr wstr ptr long ptr wstr ptr) +@ stdcall SetupDiGetClassDevsW(ptr ptr long long) +@ stub SetupDiGetClassImageIndex +@ stub SetupDiGetClassImageList +@ stub SetupDiGetClassImageListExA +@ stub SetupDiGetClassImageListExW +@ stub SetupDiGetClassInstallParamsA +@ stub SetupDiGetClassInstallParamsW +@ stub SetupDiGetDeviceInfoListClass +@ stdcall SetupDiGetDeviceInfoListDetailA(ptr ptr) +@ stdcall SetupDiGetDeviceInfoListDetailW(ptr ptr) +@ stdcall SetupDiGetDeviceInstallParamsA(ptr ptr ptr) +@ stub SetupDiGetDeviceInstallParamsW +@ stub SetupDiGetDeviceInstanceIdA +@ stub SetupDiGetDeviceInstanceIdW +@ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr) +@ stub SetupDiGetDeviceRegistryPropertyW +@ stub SetupDiGetDriverInfoDetailA +@ stub SetupDiGetDriverInfoDetailW +@ stub SetupDiGetDriverInstallParamsA +@ stub SetupDiGetDriverInstallParamsW +@ stub SetupDiGetDeviceInterfaceAlias +@ stdcall SetupDiGetDeviceInterfaceDetailA(long ptr ptr long ptr ptr) +@ stdcall SetupDiGetDeviceInterfaceDetailW(long ptr ptr long ptr ptr) +@ stub SetupDiGetHwProfileFriendlyNameA +@ stub SetupDiGetHwProfileFriendlyNameExA +@ stub SetupDiGetHwProfileFriendlyNameExW +@ stub SetupDiGetHwProfileFriendlyNameW +@ stub SetupDiGetHwProfileList +@ stub SetupDiGetHwProfileListExA +@ stub SetupDiGetHwProfileListExW +@ stub SetupDiGetINFClassA +@ stub SetupDiGetINFClassW +@ stub SetupDiGetSelectedDevice +@ stub SetupDiGetSelectedDriverA +@ stub SetupDiGetSelectedDriverW +@ stub SetupDiGetWizardPage +@ stdcall SetupDiInstallClassA(long str long ptr) +@ stub SetupDiInstallClassExA +@ stub SetupDiInstallClassExW +@ stdcall SetupDiInstallClassW(long wstr long ptr) +@ stub SetupDiInstallDevice +@ stub SetupDiInstallDriverFiles +@ stub SetupDiLoadClassIcon +@ stub SetupDiMoveDuplicateDevice +@ stdcall SetupDiOpenClassRegKey(ptr long) +@ stdcall SetupDiOpenClassRegKeyExA(ptr long long str ptr) +@ stdcall SetupDiOpenClassRegKeyExW(ptr long long wstr ptr) +@ stdcall SetupDiOpenDevRegKey(ptr ptr long long long long) +@ stub SetupDiOpenDeviceInfoA +@ stub SetupDiOpenDeviceInfoW +@ stdcall SetupDiOpenDeviceInterfaceA(ptr str long ptr) +@ stub SetupDiOpenDeviceInterfaceRegKey +@ stdcall SetupDiOpenDeviceInterfaceW(ptr wstr long ptr) +@ stub SetupDiRegisterDeviceInfo +@ stub SetupDiRemoveDevice +@ stub SetupDiRemoveDeviceInterface +@ stub SetupDiSelectDevice +@ stub SetupDiSelectOEMDrv +@ stdcall SetupDiSetClassInstallParamsA(ptr ptr ptr long) +@ stub SetupDiSetClassInstallParamsW +@ stub SetupDiSetDeviceInstallParamsA +@ stub SetupDiSetDeviceInstallParamsW +@ stub SetupDiSetDeviceRegistryPropertyA +@ stub SetupDiSetDeviceRegistryPropertyW +@ stub SetupDiSetDriverInstallParamsA +@ stub SetupDiSetDriverInstallParamsW +@ stub SetupDiSetSelectedDevice +@ stub SetupDiSetSelectedDriverA +@ stub SetupDiSetSelectedDriverW +@ stub SetupDiUnremoveDevice +@ stub SetupDuplicateDiskSpaceListA +@ stub SetupDuplicateDiskSpaceListW +@ stdcall SetupFindFirstLineA(long str str ptr) +@ stdcall SetupFindFirstLineW(long wstr wstr ptr) +@ stdcall SetupFindNextLine(ptr ptr) +@ stdcall SetupFindNextMatchLineA(ptr str ptr) +@ stdcall SetupFindNextMatchLineW(ptr wstr ptr) +@ stub SetupFreeSourceListA +@ stub SetupFreeSourceListW +@ stub SetupGetBackupInformationA +@ stub SetupGetBackupInformationW +@ stdcall SetupGetBinaryField(ptr long ptr long ptr) +@ stdcall SetupGetFieldCount(ptr) +@ stub SetupGetFileCompressionInfoA +@ stub SetupGetFileCompressionInfoW +@ stdcall SetupGetFileQueueCount(long long ptr) +@ stdcall SetupGetFileQueueFlags(long ptr) +@ stub SetupGetInfFileListA +@ stub SetupGetInfFileListW +@ stdcall SetupGetInfInformationA(ptr long ptr long ptr) +@ stub SetupGetInfInformationW +@ stub SetupGetInfSections +@ stdcall SetupGetIntField(ptr long ptr) +@ stdcall SetupGetLineByIndexA(long str long ptr) +@ stdcall SetupGetLineByIndexW(long wstr long ptr) +@ stdcall SetupGetLineCountA(long str) +@ stdcall SetupGetLineCountW(long wstr) +@ stdcall SetupGetLineTextA(ptr long str str ptr long ptr) +@ stdcall SetupGetLineTextW(ptr long wstr wstr ptr long ptr) +@ stdcall SetupGetMultiSzFieldA(ptr long ptr long ptr) +@ stdcall SetupGetMultiSzFieldW(ptr long ptr long ptr) +@ stub SetupGetSourceFileLocationA +@ stub SetupGetSourceFileLocationW +@ stub SetupGetSourceFileSizeA +@ stub SetupGetSourceFileSizeW +@ stub SetupGetSourceInfoA +@ stub SetupGetSourceInfoW +@ stdcall SetupGetStringFieldA(ptr long ptr long ptr) +@ stdcall SetupGetStringFieldW(ptr long ptr long ptr) +@ stub SetupGetTargetPathA +@ stub SetupGetTargetPathW +@ stdcall SetupInitDefaultQueueCallback(long) +@ stdcall SetupInitDefaultQueueCallbackEx(long long long long ptr) +@ stdcall SetupInitializeFileLogA(str long) +@ stdcall SetupInitializeFileLogW(wstr long) +@ stub SetupInstallFileA +@ stub SetupInstallFileExA +@ stub SetupInstallFileExW +@ stub SetupInstallFileW +@ stdcall SetupInstallFilesFromInfSectionA(long long long str str long) +@ stdcall SetupInstallFilesFromInfSectionW(long long long wstr wstr long) +@ stdcall SetupInstallFromInfSectionA(long long str long long str long ptr ptr long ptr) +@ stdcall SetupInstallFromInfSectionW(long long wstr long long wstr long ptr ptr long ptr) +@ stub SetupInstallServicesFromInfSectionA +@ stub SetupInstallServicesFromInfSectionExA +@ stub SetupInstallServicesFromInfSectionExW +@ stub SetupInstallServicesFromInfSectionW +@ stdcall SetupIterateCabinetA(str long ptr ptr) +@ stdcall SetupIterateCabinetW(wstr long ptr ptr) +@ stub SetupLogErrorA +@ stub SetupLogErrorW +@ stub SetupLogFileA +@ stub SetupLogFileW +@ stdcall SetupOpenAppendInfFileA(str long ptr) +@ stdcall SetupOpenAppendInfFileW(wstr long ptr) +@ stdcall SetupOpenFileQueue() +@ stdcall SetupOpenInfFileA(str str long ptr) +@ stdcall SetupOpenInfFileW(wstr wstr long ptr) +@ stdcall SetupOpenMasterInf() +@ stub SetupPromptForDiskA +@ stub SetupPromptForDiskW +@ stub SetupPromptReboot +@ stub SetupQueryDrivesInDiskSpaceListA +@ stub SetupQueryDrivesInDiskSpaceListW +@ stub SetupQueryFileLogA +@ stub SetupQueryFileLogW +@ stub SetupQueryInfFileInformationA +@ stub SetupQueryInfFileInformationW +@ stub SetupQueryInfOriginalFileInformationA +@ stub SetupQueryInfOriginalFileInformationW +@ stub SetupQueryInfVersionInformationA +@ stub SetupQueryInfVersionInformationW +@ stub SetupQuerySourceListA +@ stub SetupQuerySourceListW +@ stdcall SetupQuerySpaceRequiredOnDriveA(long str ptr ptr long) +@ stub SetupQuerySpaceRequiredOnDriveW +@ stdcall SetupQueueCopyA(long str str str str str str str long) +@ stdcall SetupQueueCopyIndirectA(ptr) +@ stdcall SetupQueueCopyIndirectW(ptr) +@ stdcall SetupQueueCopySectionA(long str long long str long) +@ stdcall SetupQueueCopySectionW(long wstr long long wstr long) +@ stdcall SetupQueueCopyW(long wstr wstr wstr wstr wstr wstr wstr long) +@ stdcall SetupQueueDefaultCopyA(long long str str str long) +@ stdcall SetupQueueDefaultCopyW(long long wstr wstr wstr long) +@ stdcall SetupQueueDeleteA(long str str) +@ stdcall SetupQueueDeleteSectionA(long long long str) +@ stdcall SetupQueueDeleteSectionW(long long long wstr) +@ stdcall SetupQueueDeleteW(long wstr wstr) +@ stdcall SetupQueueRenameA(long str str str str) +@ stdcall SetupQueueRenameSectionA(long long long str) +@ stdcall SetupQueueRenameSectionW(long long long wstr) +@ stdcall SetupQueueRenameW(long wstr wstr wstr wstr) +@ stub SetupRemoveFileLogEntryA +@ stub SetupRemoveFileLogEntryW +@ stub SetupRemoveFromDiskSpaceListA +@ stub SetupRemoveFromDiskSpaceListW +@ stub SetupRemoveFromSourceListA +@ stub SetupRemoveFromSourceListW +@ stub SetupRemoveInstallSectionFromDiskSpaceListA +@ stub SetupRemoveInstallSectionFromDiskSpaceListW +@ stub SetupRemoveSectionFromDiskSpaceListA +@ stub SetupRemoveSectionFromDiskSpaceListW +@ stub SetupRenameErrorA +@ stub SetupRenameErrorW +@ stub SetupScanFileQueue +@ stdcall SetupScanFileQueueA(long long long ptr ptr ptr) +@ stdcall SetupScanFileQueueW(long long long ptr ptr ptr) +@ stdcall SetupSetDirectoryIdA(long long str) +@ stub SetupSetDirectoryIdExA +@ stub SetupSetDirectoryIdExW +@ stdcall SetupSetDirectoryIdW(long long wstr) +@ stub SetupFileQueueAlternatePlatformA +@ stub SetupFileQueueAlternatePlatformW +@ stdcall SetupSetFileQueueFlags(long long long) +@ stub SetupSetPlatformPathOverrideA +@ stub SetupSetPlatformPathOverrideW +@ stub SetupSetSourceListA +@ stub SetupSetSourceListW +@ stdcall SetupTermDefaultQueueCallback(ptr) +@ stdcall SetupTerminateFileLog(long) +@ stub ShouldDeviceBeExcluded +@ stdcall StampFileSecurity(wstr ptr) +@ stdcall StringTableAddString(ptr wstr long) +@ stub StringTableAddStringEx +@ stdcall StringTableDestroy(ptr) +@ stub StringTableDuplicate +@ stub StringTableEnum +@ stub StringTableGetExtraData +@ stdcall StringTableInitialize() +@ stub StringTableInitializeEx +@ stdcall StringTableLookUpString(ptr wstr long) +@ stub StringTableLookUpStringEx +@ stub StringTableSetExtraData +@ stdcall StringTableStringFromId(ptr long) +@ stdcall StringTableStringFromIdEx(ptr long ptr ptr) +@ stdcall StringTableTrim(ptr) +@ stdcall TakeOwnershipOfFile(wstr) +@ stdcall UnicodeToMultiByte(wstr long) +@ stdcall UnmapAndCloseFile(long long ptr) +@ stub VerifyCatalogFile +@ stub VerifyFile +@ stub pSetupAccessRunOnceNodeList +@ stub pSetupAddMiniIconToList +@ stub pSetupAddTagToGroupOrderListEntry +@ stub pSetupAppendStringToMultiSz +@ stub pSetupDestroyRunOnceNodeList +@ stub pSetupDirectoryIdToPath +@ stub pSetupGetField +@ stub pSetupGetGlobalFlags +@ stub pSetupGetOsLoaderDriveAndPath +@ stub pSetupGetQueueFlags +@ stub pSetupGetVersionDatum +@ stub pSetupGuidFromString +@ stub pSetupIsGuidNull +@ stub pSetupMakeSurePathExists +@ stub pSetupSetGlobalFlags +@ stub pSetupSetQueueFlags +@ stub pSetupSetSystemSourceFlags +@ stub pSetupStringFromGuid +@ stub pSetupVerifyQueuedCatalogs diff --git a/reactos/lib/setupapi/setupapi.xml b/reactos/lib/setupapi/setupapi.xml index 7950ec95431..1a81bbdc321 100644 --- a/reactos/lib/setupapi/setupapi.xml +++ b/reactos/lib/setupapi/setupapi.xml @@ -1,37 +1,37 @@ - - - . - include/wine - . - - - - - 0x600 - 0x501 - 0x501 - - - pnp_client - wine - ntdll - kernel32 - advapi32 - user32 - rpcrt4 - version - cfgmgr.c - devinst.c - dirid.c - diskspace.c - install.c - misc.c - parser.c - queue.c - setupcab.c - stringtable.c - stubs.c - rpc.c - setupapi.rc - setupapi.spec - + + + . + include/wine + . + + + + + 0x600 + 0x501 + 0x501 + + + pnp_client + wine + ntdll + kernel32 + advapi32 + user32 + rpcrt4 + version + cfgmgr.c + devinst.c + dirid.c + diskspace.c + install.c + misc.c + parser.c + queue.c + setupcab.c + stringtable.c + stubs.c + rpc.c + setupapi.rc + setupapi.spec + diff --git a/reactos/lib/setupapi/setupapi_private.h b/reactos/lib/setupapi/setupapi_private.h index bd5ea9b6db1..69ac9326ad3 100644 --- a/reactos/lib/setupapi/setupapi_private.h +++ b/reactos/lib/setupapi/setupapi_private.h @@ -1,62 +1,62 @@ -/* - * Copyright 2001 Andreas Mohr - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __SETUPAPI_PRIVATE_H -#define __SETUPAPI_PRIVATE_H - -#define COPYFILEDLGORD 1000 -#define SOURCESTRORD 500 -#define DESTSTRORD 501 -#define PROGRESSORD 502 - - -#define REG_INSTALLEDFILES "System\\CurrentControlSet\\Control\\InstalledFiles" -#define REGPART_RENAME "\\Rename" -#define REG_VERSIONCONFLICT "Software\\Microsoft\\VersionConflictManager" - -/* string substitutions */ - -struct inf_file; -extern const WCHAR *DIRID_get_string( HINF hinf, int dirid ); -extern unsigned int PARSER_string_substA( struct inf_file *file, const WCHAR *text, - char *buffer, unsigned int size ); -extern unsigned int PARSER_string_substW( struct inf_file *file, const WCHAR *text, - WCHAR *buffer, unsigned int size ); -extern const WCHAR *PARSER_get_src_root( HINF hinf ); -extern WCHAR *PARSER_get_dest_dir( INFCONTEXT *context ); - -/* support for Ascii queue callback functions */ - -struct callback_WtoA_context -{ - void *orig_context; - PSP_FILE_CALLBACK_A orig_handler; -}; - -UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, UINT_PTR, UINT_PTR ); - -/* from msvcrt/sys/stat.h */ -#define _S_IWRITE 0x0080 -#define _S_IREAD 0x0100 - -extern HINSTANCE hInstance; -extern OSVERSIONINFOW OsVersionInfo; - -DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst); - -#endif /* __SETUPAPI_PRIVATE_H */ +/* + * Copyright 2001 Andreas Mohr + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SETUPAPI_PRIVATE_H +#define __SETUPAPI_PRIVATE_H + +#define COPYFILEDLGORD 1000 +#define SOURCESTRORD 500 +#define DESTSTRORD 501 +#define PROGRESSORD 502 + + +#define REG_INSTALLEDFILES "System\\CurrentControlSet\\Control\\InstalledFiles" +#define REGPART_RENAME "\\Rename" +#define REG_VERSIONCONFLICT "Software\\Microsoft\\VersionConflictManager" + +/* string substitutions */ + +struct inf_file; +extern const WCHAR *DIRID_get_string( HINF hinf, int dirid ); +extern unsigned int PARSER_string_substA( struct inf_file *file, const WCHAR *text, + char *buffer, unsigned int size ); +extern unsigned int PARSER_string_substW( struct inf_file *file, const WCHAR *text, + WCHAR *buffer, unsigned int size ); +extern const WCHAR *PARSER_get_src_root( HINF hinf ); +extern WCHAR *PARSER_get_dest_dir( INFCONTEXT *context ); + +/* support for Ascii queue callback functions */ + +struct callback_WtoA_context +{ + void *orig_context; + PSP_FILE_CALLBACK_A orig_handler; +}; + +UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, UINT_PTR, UINT_PTR ); + +/* from msvcrt/sys/stat.h */ +#define _S_IWRITE 0x0080 +#define _S_IREAD 0x0100 + +extern HINSTANCE hInstance; +extern OSVERSIONINFOW OsVersionInfo; + +DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst); + +#endif /* __SETUPAPI_PRIVATE_H */ diff --git a/reactos/lib/setupapi/setupcab.c b/reactos/lib/setupapi/setupcab.c index 8bdf6e578c3..db45f77e666 100644 --- a/reactos/lib/setupapi/setupcab.c +++ b/reactos/lib/setupapi/setupcab.c @@ -1,689 +1,689 @@ -/* - * Setupapi cabinet routines - * - * Copyright 2003 Gregory M. Turner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Many useful traces are commented in code, uncomment them if you have - * trouble and run with WINEDEBUG=+setupapi - * - */ - -#include -#include -#include - -#include "wine/debug.h" -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "winreg.h" -#include "setupapi.h" -#include "setupapi_private.h" -#include "fdi.h" -#include "wine/unicode.h" - -#include "fcntl.h" -#include "share.h" - -#include "wine/debug.h" - -HINSTANCE hInstance = 0; -OSVERSIONINFOW OsVersionInfo; - -static HINSTANCE CABINET_hInstance = 0; - -static HFDI (__cdecl *sc_FDICreate)(PFNALLOC, PFNFREE, PFNOPEN, - PFNREAD, PFNWRITE, PFNCLOSE, PFNSEEK, int, PERF); - -static BOOL (__cdecl *sc_FDICopy)(HFDI, char *, char *, int, - PFNFDINOTIFY, PFNFDIDECRYPT, void *); - -static BOOL (__cdecl *sc_FDIDestroy)(HFDI); - -#define SC_HSC_A_MAGIC 0xACABFEED -typedef struct { - UINT magic; - HFDI hfdi; - PSP_FILE_CALLBACK_A msghandler; - PVOID context; - CHAR most_recent_cabinet_name[MAX_PATH]; -} SC_HSC_A, *PSC_HSC_A; - -#define SC_HSC_W_MAGIC 0x0CABFEED -typedef struct { - UINT magic; - HFDI hfdi; - PSP_FILE_CALLBACK_W msghandler; - PVOID context; - WCHAR most_recent_cabinet_name[MAX_PATH]; -} SC_HSC_W, *PSC_HSC_W; - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -static BOOL LoadCABINETDll(void) -{ - if (!CABINET_hInstance) { - CABINET_hInstance = LoadLibraryA("cabinet.dll"); - if (CABINET_hInstance) { - sc_FDICreate = (void *)GetProcAddress(CABINET_hInstance, "FDICreate"); - sc_FDICopy = (void *)GetProcAddress(CABINET_hInstance, "FDICopy"); - sc_FDIDestroy = (void *)GetProcAddress(CABINET_hInstance, "FDIDestroy"); - return TRUE; - } else { - ERR("load cabinet dll failed.\n"); - return FALSE; - } - } else - return TRUE; -} - -static void UnloadCABINETDll(void) -{ - if (CABINET_hInstance) { - FreeLibrary(CABINET_hInstance); - CABINET_hInstance = 0; - } -} - -/* FDICreate callbacks */ - -static void *sc_cb_alloc(ULONG cb) -{ - return malloc(cb); -} - -static void sc_cb_free(void *pv) -{ - free(pv); -} - -static INT_PTR sc_cb_open(char *pszFile, int oflag, int pmode) -{ - DWORD creation = 0, sharing = 0; - int ioflag = 0; - INT_PTR ret = 0; - SECURITY_ATTRIBUTES sa; - - /* TRACE("(pszFile == %s, oflag == %d, pmode == %d)\n", debugstr_a(pszFile), oflag, pmode); */ - - switch(oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { - case _O_RDONLY: - ioflag |= GENERIC_READ; - break; - case _O_WRONLY: - ioflag |= GENERIC_WRITE; - break; - case _O_RDWR: - ioflag |= GENERIC_READ & GENERIC_WRITE; - break; - case _O_WRONLY | _O_RDWR: /* hmmm.. */ - ERR("_O_WRONLY & _O_RDWR in oflag?\n"); - return -1; - } - - if (oflag & _O_CREAT) { - if (oflag & _O_EXCL) - creation = CREATE_NEW; - else if (oflag & _O_TRUNC) - creation = CREATE_ALWAYS; - else - creation = OPEN_ALWAYS; - } else /* no _O_CREAT */ { - if (oflag & _O_TRUNC) - creation = TRUNCATE_EXISTING; - else - creation = OPEN_EXISTING; - } - - switch( pmode & 0x70 ) { - case _SH_DENYRW: - sharing = 0L; - break; - case _SH_DENYWR: - sharing = FILE_SHARE_READ; - break; - case _SH_DENYRD: - sharing = FILE_SHARE_WRITE; - break; - case _SH_COMPAT: - case _SH_DENYNO: - sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; - break; - default: - ERR("<-- -1 (Unhandled pmode 0x%x)\n", pmode); - return -1; - } - - if (oflag & ~(_O_BINARY | _O_TRUNC | _O_EXCL | _O_CREAT | _O_RDWR | _O_WRONLY | _O_NOINHERIT)) - WARN("unsupported oflag 0x%04x\n",oflag); - - sa.nLength = sizeof( SECURITY_ATTRIBUTES ); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = (ioflag & _O_NOINHERIT) ? FALSE : TRUE; - - ret = (INT_PTR) CreateFileA(pszFile, ioflag, sharing, &sa, creation, FILE_ATTRIBUTE_NORMAL, NULL); - - /* TRACE("<-- %d\n", ret); */ - - return ret; -} - -static UINT sc_cb_read(INT_PTR hf, void *pv, UINT cb) -{ - DWORD num_read; - BOOL rslt; - - /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */ - - rslt = ReadFile((HANDLE) hf, pv, cb, &num_read, NULL); - - - /* eof and failure both give "-1" return */ - if ((! rslt) || ((cb > 0) && (num_read == 0))) { - /* TRACE("<-- -1\n"); */ - return -1; - } - - /* TRACE("<-- %lu\n", num_read); */ - return num_read; -} - -static UINT sc_cb_write(INT_PTR hf, void *pv, UINT cb) -{ - DWORD num_written; - /* BOOL rv; */ - - /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */ - - if ( /* (rv = */ WriteFile((HANDLE) hf, pv, cb, &num_written, NULL) /* ) */ - && (num_written == cb)) { - /* TRACE("<-- %lu\n", num_written); */ - return num_written; - } else { - /* TRACE("rv == %d, num_written == %lu, cb == %u\n", rv, num_written,cb); */ - /* TRACE("<-- -1\n"); */ - return -1; - } -} - -static int sc_cb_close(INT_PTR hf) -{ - /* TRACE("(hf == %d)\n", hf); */ - - if (CloseHandle((HANDLE) hf)) - return 0; - else - return -1; -} - -static long sc_cb_lseek(INT_PTR hf, long dist, int seektype) -{ - DWORD ret; - - /* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */ - - if (seektype < 0 || seektype > 2) - return -1; - - if (((ret = SetFilePointer((HANDLE) hf, dist, NULL, seektype)) != INVALID_SET_FILE_POINTER) || !GetLastError()) { - /* TRACE("<-- %lu\n", ret); */ - return ret; - } else { - /* TRACE("<-- -1\n"); */ - return -1; - } -} - -#define SIZEOF_MYSTERIO (MAX_PATH*3) - -/* FDICopy callbacks */ - -static INT_PTR sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) -{ - FILE_IN_CABINET_INFO_A fici; - PSC_HSC_A phsc; - CABINET_INFO_A ci; - FILEPATHS_A fp; - UINT err; - - CHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! probably 256... */ - - memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO); - - TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin); - - if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_A_MAGIC)) - phsc = (PSC_HSC_A) pfdin->pv; - else { - ERR("pv %p is not an SC_HSC_A.\n", (pfdin) ? pfdin->pv : NULL); - return -1; - } - - switch (fdint) { - case fdintCABINET_INFO: - TRACE("Cabinet info notification\n"); - /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); - TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); - TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); - TRACE(" Cabinet Set#: %d\n", pfdin->setID); - TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ - WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n"); - ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]); - ci.CabinetPath = pfdin->psz3; - ci.DiskName = pfdin->psz2; - ci.SetId = pfdin->setID; - ci.CabinetNumber = pfdin->iCabinet; - phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0); - return 0; - case fdintPARTIAL_FILE: - TRACE("Partial file notification\n"); - /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */ - return 0; - case fdintCOPY_FILE: - TRACE("Copy file notification\n"); - TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); - /* TRACE(" File size: %ld\n", pfdin->cb); - TRACE(" File date: %u\n", pfdin->date); - TRACE(" File time: %u\n", pfdin->time); - TRACE(" File attr: %u\n", pfdin->attribs); */ - fici.NameInCabinet = pfdin->psz1; - fici.FileSize = pfdin->cb; - fici.Win32Error = 0; - fici.DosDate = pfdin->date; - fici.DosTime = pfdin->time; - fici.DosAttribs = pfdin->attribs; - memset(&(fici.FullTargetName[0]), 0, MAX_PATH); - err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET, - (UINT) &fici, (UINT) pfdin->psz1); - if (err == FILEOP_DOIT) { - TRACE(" Callback specified filename: %s\n", debugstr_a(&(fici.FullTargetName[0]))); - if (!fici.FullTargetName[0]) { - WARN(" Empty return string causing abort.\n"); - SetLastError(ERROR_PATH_NOT_FOUND); - return -1; - } - return sc_cb_open(&(fici.FullTargetName[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE); - } else { - TRACE(" Callback skipped file.\n"); - return 0; - } - case fdintCLOSE_FILE_INFO: - TRACE("Close file notification\n"); - /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); - TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No"); - TRACE(" File hndl: %d\n", pfdin->hf); */ - fp.Source = &(phsc->most_recent_cabinet_name[0]); - fp.Target = pfdin->psz1; - fp.Win32Error = 0; - fp.Flags = 0; - /* the following should be a fixme -- but it occurs too many times */ - WARN("Should set file date/time/attribs (and execute files?)\n"); - err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0); - if (sc_cb_close(pfdin->hf)) - WARN("_close failed.\n"); - if (err) { - SetLastError(err); - return FALSE; - } else - return TRUE; - case fdintNEXT_CABINET: - TRACE("Next cabinet notification\n"); - /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); - TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); - TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); - TRACE(" Cabinet Set#: %d\n", pfdin->setID); - TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ - ci.CabinetFile = pfdin->psz1; - ci.CabinetPath = pfdin->psz3; - ci.DiskName = pfdin->psz2; - ci.SetId = pfdin->setID; - ci.CabinetNumber = pfdin->iCabinet; - /* remember the new cabinet name */ - strcpy(&(phsc->most_recent_cabinet_name[0]), pfdin->psz1); - err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0])); - if (err) { - SetLastError(err); - return -1; - } else { - if (mysterio[0]) { - /* some easy paranoia. no such carefulness exists on the wide API IIRC */ - lstrcpynA(pfdin->psz3, &(mysterio[0]), SIZEOF_MYSTERIO); - } - return 0; - } - default: - FIXME("Unknown notification type %d.\n", fdint); - return 0; - } -} - -static INT_PTR sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) -{ - FILE_IN_CABINET_INFO_W fici; - PSC_HSC_W phsc; - CABINET_INFO_W ci; - FILEPATHS_W fp; - UINT err; - int len; - - WCHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! */ - WCHAR buf[MAX_PATH], buf2[MAX_PATH]; - CHAR charbuf[MAX_PATH]; - - memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO * sizeof(WCHAR)); - memset(&(buf[0]), 0, MAX_PATH * sizeof(WCHAR)); - memset(&(buf2[0]), 0, MAX_PATH * sizeof(WCHAR)); - memset(&(charbuf[0]), 0, MAX_PATH); - - TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin); - - if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_W_MAGIC)) - phsc = (PSC_HSC_W) pfdin->pv; - else { - ERR("pv %p is not an SC_HSC_W.\n", (pfdin) ? pfdin->pv : NULL); - return -1; - } - - switch (fdint) { - case fdintCABINET_INFO: - TRACE("Cabinet info notification\n"); - /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); - TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); - TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); - TRACE(" Cabinet Set#: %d\n", pfdin->setID); - TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ - WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n"); - ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]); - len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH); - if ((len > MAX_PATH) || (len <= 1)) - buf[0] = '\0'; - ci.CabinetPath = &(buf[0]); - len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH); - if ((len > MAX_PATH) || (len <= 1)) - buf2[0] = '\0'; - ci.DiskName = &(buf2[0]); - ci.SetId = pfdin->setID; - ci.CabinetNumber = pfdin->iCabinet; - phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0); - return 0; - case fdintPARTIAL_FILE: - TRACE("Partial file notification\n"); - /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */ - return 0; - case fdintCOPY_FILE: - TRACE("Copy file notification\n"); - TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); - /* TRACE(" File size: %ld\n", pfdin->cb); - TRACE(" File date: %u\n", pfdin->date); - TRACE(" File time: %u\n", pfdin->time); - TRACE(" File attr: %u\n", pfdin->attribs); */ - len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf2[0]), MAX_PATH); - if ((len > MAX_PATH) || (len <= 1)) - buf2[0] = '\0'; - fici.NameInCabinet = &(buf2[0]); - fici.FileSize = pfdin->cb; - fici.Win32Error = 0; - fici.DosDate = pfdin->date; - fici.DosTime = pfdin->time; - fici.DosAttribs = pfdin->attribs; - memset(&(fici.FullTargetName[0]), 0, MAX_PATH * sizeof(WCHAR)); - err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET, - (UINT) &fici, (UINT) pfdin->psz1); - if (err == FILEOP_DOIT) { - TRACE(" Callback specified filename: %s\n", debugstr_w(&(fici.FullTargetName[0]))); - if (fici.FullTargetName[0]) { - len = strlenW(&(fici.FullTargetName[0])) + 1; - if ((len > MAX_PATH ) || (len <= 1)) - return 0; - if (!WideCharToMultiByte(CP_ACP, 0, &(fici.FullTargetName[0]), len, &(charbuf[0]), MAX_PATH, 0, 0)) - return 0; - } else { - WARN("Empty buffer string caused abort.\n"); - SetLastError(ERROR_PATH_NOT_FOUND); - return -1; - } - return sc_cb_open(&(charbuf[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE); - } else { - TRACE(" Callback skipped file.\n"); - return 0; - } - case fdintCLOSE_FILE_INFO: - TRACE("Close file notification\n"); - /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); - TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No"); - TRACE(" File hndl: %d\n", pfdin->hf); */ - fp.Source = &(phsc->most_recent_cabinet_name[0]); - len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf[0]), MAX_PATH); - if ((len > MAX_PATH) || (len <= 1)) - buf[0] = '\0'; - fp.Target = &(buf[0]); - fp.Win32Error = 0; - fp.Flags = 0; - /* a valid fixme -- but occurs too many times */ - /* FIXME("Should set file date/time/attribs (and execute files?)\n"); */ - err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0); - if (sc_cb_close(pfdin->hf)) - WARN("_close failed.\n"); - if (err) { - SetLastError(err); - return FALSE; - } else - return TRUE; - case fdintNEXT_CABINET: - TRACE("Next cabinet notification\n"); - /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); - TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); - TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); - TRACE(" Cabinet Set#: %d\n", pfdin->setID); - TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ - /* remember the new cabinet name */ - len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(phsc->most_recent_cabinet_name[0]), MAX_PATH); - if ((len > MAX_PATH) || (len <= 1)) - phsc->most_recent_cabinet_name[0] = '\0'; - ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]); - len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH); - if ((len > MAX_PATH) || (len <= 1)) - buf[0] = '\0'; - ci.CabinetPath = &(buf[0]); - len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH); - if ((len > MAX_PATH) || (len <= 1)) - buf2[0] = '\0'; - ci.DiskName = &(buf2[0]); - ci.SetId = pfdin->setID; - ci.CabinetNumber = pfdin->iCabinet; - err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0])); - if (err) { - SetLastError(err); - return -1; - } else { - if (mysterio[0]) { - len = strlenW(&(mysterio[0])) + 1; - if ((len > 255) || (len <= 1)) - return 0; - if (!WideCharToMultiByte(CP_ACP, 0, &(mysterio[0]), len, pfdin->psz3, 255, 0, 0)) - return 0; - } - return 0; - } - default: - FIXME("Unknown notification type %d.\n", fdint); - return 0; - } -} - -/*********************************************************************** - * SetupIterateCabinetA (SETUPAPI.@) - */ -BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved, - PSP_FILE_CALLBACK_A MsgHandler, PVOID Context) -{ - - SC_HSC_A my_hsc; - ERF erf; - CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *p; - DWORD fpnsize; - BOOL ret; - - - TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n", - debugstr_a(CabinetFile), Reserved, MsgHandler, Context); - - if (! LoadCABINETDll()) - return FALSE; - - memset(&my_hsc, 0, sizeof(SC_HSC_A)); - pszCabinet[0] = '\0'; - pszCabPath[0] = '\0'; - - fpnsize = strlen(CabinetFile); - if (fpnsize >= MAX_PATH) { - SetLastError(ERROR_BAD_PATHNAME); - return FALSE; - } - - fpnsize = GetFullPathNameA(CabinetFile, MAX_PATH, &(pszCabPath[0]), &p); - if (fpnsize > MAX_PATH) { - SetLastError(ERROR_BAD_PATHNAME); - return FALSE; - } - - if (p) { - strcpy(pszCabinet, p); - *p = '\0'; - } else { - strcpy(pszCabinet, CabinetFile); - pszCabPath[0] = '\0'; - } - - TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet)); - - /* remember the cabinet name */ - strcpy(&(my_hsc.most_recent_cabinet_name[0]), pszCabinet); - - my_hsc.magic = SC_HSC_A_MAGIC; - my_hsc.msghandler = MsgHandler; - my_hsc.context = Context; - my_hsc.hfdi = sc_FDICreate( sc_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read, - sc_cb_write, sc_cb_close, sc_cb_lseek, cpuUNKNOWN, &erf ); - - if (!my_hsc.hfdi) return FALSE; - - ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath, - 0, sc_FNNOTIFY_A, NULL, &my_hsc) ) ? TRUE : FALSE; - - sc_FDIDestroy(my_hsc.hfdi); - return ret; -} - - -/*********************************************************************** - * SetupIterateCabinetW (SETUPAPI.@) - */ -BOOL WINAPI SetupIterateCabinetW(PCWSTR CabinetFile, DWORD Reserved, - PSP_FILE_CALLBACK_W MsgHandler, PVOID Context) -{ - CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH]; - UINT len; - SC_HSC_W my_hsc; - ERF erf; - WCHAR pszCabPathW[MAX_PATH], *p; - DWORD fpnsize; - BOOL ret; - - TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n", - debugstr_w(CabinetFile), Reserved, MsgHandler, Context); - - if (!LoadCABINETDll()) - return FALSE; - - if (!CabinetFile) return FALSE; - - memset(&my_hsc, 0, sizeof(SC_HSC_W)); - - fpnsize = GetFullPathNameW(CabinetFile, MAX_PATH, pszCabPathW, &p); - if (fpnsize > MAX_PATH) { - SetLastError(ERROR_BAD_PATHNAME); - return FALSE; - } - - if (p) { - strcpyW(my_hsc.most_recent_cabinet_name, p); - *p = 0; - len = WideCharToMultiByte(CP_ACP, 0, pszCabPathW, -1, pszCabPath, - MAX_PATH, 0, 0); - if (!len) return FALSE; - } else { - strcpyW(my_hsc.most_recent_cabinet_name, CabinetFile); - pszCabPath[0] = '\0'; - } - - len = WideCharToMultiByte(CP_ACP, 0, my_hsc.most_recent_cabinet_name, -1, - pszCabinet, MAX_PATH, 0, 0); - if (!len) return FALSE; - - TRACE("path: %s, cabfile: %s\n", - debugstr_a(pszCabPath), debugstr_a(pszCabinet)); - - my_hsc.magic = SC_HSC_W_MAGIC; - my_hsc.msghandler = MsgHandler; - my_hsc.context = Context; - my_hsc.hfdi = sc_FDICreate( sc_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read, - sc_cb_write, sc_cb_close, sc_cb_lseek, cpuUNKNOWN, &erf ); - - if (!my_hsc.hfdi) return FALSE; - - ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath, - 0, sc_FNNOTIFY_W, NULL, &my_hsc) ) ? TRUE : FALSE; - - sc_FDIDestroy(my_hsc.hfdi); - return ret; -} - - -/*********************************************************************** - * DllMain - * - * PARAMS - * hinstDLL [I] handle to the DLL's instance - * fdwReason [I] - * lpvReserved [I] reserved, must be NULL - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hinstDLL); - OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); - if (!GetVersionExW(&OsVersionInfo)) - return FALSE; - hInstance = (HINSTANCE)hinstDLL; - break; - case DLL_PROCESS_DETACH: - UnloadCABINETDll(); - break; - } - - return TRUE; -} +/* + * Setupapi cabinet routines + * + * Copyright 2003 Gregory M. Turner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Many useful traces are commented in code, uncomment them if you have + * trouble and run with WINEDEBUG=+setupapi + * + */ + +#include +#include +#include + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "winreg.h" +#include "setupapi.h" +#include "setupapi_private.h" +#include "fdi.h" +#include "wine/unicode.h" + +#include "fcntl.h" +#include "share.h" + +#include "wine/debug.h" + +HINSTANCE hInstance = 0; +OSVERSIONINFOW OsVersionInfo; + +static HINSTANCE CABINET_hInstance = 0; + +static HFDI (__cdecl *sc_FDICreate)(PFNALLOC, PFNFREE, PFNOPEN, + PFNREAD, PFNWRITE, PFNCLOSE, PFNSEEK, int, PERF); + +static BOOL (__cdecl *sc_FDICopy)(HFDI, char *, char *, int, + PFNFDINOTIFY, PFNFDIDECRYPT, void *); + +static BOOL (__cdecl *sc_FDIDestroy)(HFDI); + +#define SC_HSC_A_MAGIC 0xACABFEED +typedef struct { + UINT magic; + HFDI hfdi; + PSP_FILE_CALLBACK_A msghandler; + PVOID context; + CHAR most_recent_cabinet_name[MAX_PATH]; +} SC_HSC_A, *PSC_HSC_A; + +#define SC_HSC_W_MAGIC 0x0CABFEED +typedef struct { + UINT magic; + HFDI hfdi; + PSP_FILE_CALLBACK_W msghandler; + PVOID context; + WCHAR most_recent_cabinet_name[MAX_PATH]; +} SC_HSC_W, *PSC_HSC_W; + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +static BOOL LoadCABINETDll(void) +{ + if (!CABINET_hInstance) { + CABINET_hInstance = LoadLibraryA("cabinet.dll"); + if (CABINET_hInstance) { + sc_FDICreate = (void *)GetProcAddress(CABINET_hInstance, "FDICreate"); + sc_FDICopy = (void *)GetProcAddress(CABINET_hInstance, "FDICopy"); + sc_FDIDestroy = (void *)GetProcAddress(CABINET_hInstance, "FDIDestroy"); + return TRUE; + } else { + ERR("load cabinet dll failed.\n"); + return FALSE; + } + } else + return TRUE; +} + +static void UnloadCABINETDll(void) +{ + if (CABINET_hInstance) { + FreeLibrary(CABINET_hInstance); + CABINET_hInstance = 0; + } +} + +/* FDICreate callbacks */ + +static void *sc_cb_alloc(ULONG cb) +{ + return malloc(cb); +} + +static void sc_cb_free(void *pv) +{ + free(pv); +} + +static INT_PTR sc_cb_open(char *pszFile, int oflag, int pmode) +{ + DWORD creation = 0, sharing = 0; + int ioflag = 0; + INT_PTR ret = 0; + SECURITY_ATTRIBUTES sa; + + /* TRACE("(pszFile == %s, oflag == %d, pmode == %d)\n", debugstr_a(pszFile), oflag, pmode); */ + + switch(oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { + case _O_RDONLY: + ioflag |= GENERIC_READ; + break; + case _O_WRONLY: + ioflag |= GENERIC_WRITE; + break; + case _O_RDWR: + ioflag |= GENERIC_READ & GENERIC_WRITE; + break; + case _O_WRONLY | _O_RDWR: /* hmmm.. */ + ERR("_O_WRONLY & _O_RDWR in oflag?\n"); + return -1; + } + + if (oflag & _O_CREAT) { + if (oflag & _O_EXCL) + creation = CREATE_NEW; + else if (oflag & _O_TRUNC) + creation = CREATE_ALWAYS; + else + creation = OPEN_ALWAYS; + } else /* no _O_CREAT */ { + if (oflag & _O_TRUNC) + creation = TRUNCATE_EXISTING; + else + creation = OPEN_EXISTING; + } + + switch( pmode & 0x70 ) { + case _SH_DENYRW: + sharing = 0L; + break; + case _SH_DENYWR: + sharing = FILE_SHARE_READ; + break; + case _SH_DENYRD: + sharing = FILE_SHARE_WRITE; + break; + case _SH_COMPAT: + case _SH_DENYNO: + sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; + break; + default: + ERR("<-- -1 (Unhandled pmode 0x%x)\n", pmode); + return -1; + } + + if (oflag & ~(_O_BINARY | _O_TRUNC | _O_EXCL | _O_CREAT | _O_RDWR | _O_WRONLY | _O_NOINHERIT)) + WARN("unsupported oflag 0x%04x\n",oflag); + + sa.nLength = sizeof( SECURITY_ATTRIBUTES ); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = (ioflag & _O_NOINHERIT) ? FALSE : TRUE; + + ret = (INT_PTR) CreateFileA(pszFile, ioflag, sharing, &sa, creation, FILE_ATTRIBUTE_NORMAL, NULL); + + /* TRACE("<-- %d\n", ret); */ + + return ret; +} + +static UINT sc_cb_read(INT_PTR hf, void *pv, UINT cb) +{ + DWORD num_read; + BOOL rslt; + + /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */ + + rslt = ReadFile((HANDLE) hf, pv, cb, &num_read, NULL); + + + /* eof and failure both give "-1" return */ + if ((! rslt) || ((cb > 0) && (num_read == 0))) { + /* TRACE("<-- -1\n"); */ + return -1; + } + + /* TRACE("<-- %lu\n", num_read); */ + return num_read; +} + +static UINT sc_cb_write(INT_PTR hf, void *pv, UINT cb) +{ + DWORD num_written; + /* BOOL rv; */ + + /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */ + + if ( /* (rv = */ WriteFile((HANDLE) hf, pv, cb, &num_written, NULL) /* ) */ + && (num_written == cb)) { + /* TRACE("<-- %lu\n", num_written); */ + return num_written; + } else { + /* TRACE("rv == %d, num_written == %lu, cb == %u\n", rv, num_written,cb); */ + /* TRACE("<-- -1\n"); */ + return -1; + } +} + +static int sc_cb_close(INT_PTR hf) +{ + /* TRACE("(hf == %d)\n", hf); */ + + if (CloseHandle((HANDLE) hf)) + return 0; + else + return -1; +} + +static long sc_cb_lseek(INT_PTR hf, long dist, int seektype) +{ + DWORD ret; + + /* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */ + + if (seektype < 0 || seektype > 2) + return -1; + + if (((ret = SetFilePointer((HANDLE) hf, dist, NULL, seektype)) != INVALID_SET_FILE_POINTER) || !GetLastError()) { + /* TRACE("<-- %lu\n", ret); */ + return ret; + } else { + /* TRACE("<-- -1\n"); */ + return -1; + } +} + +#define SIZEOF_MYSTERIO (MAX_PATH*3) + +/* FDICopy callbacks */ + +static INT_PTR sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) +{ + FILE_IN_CABINET_INFO_A fici; + PSC_HSC_A phsc; + CABINET_INFO_A ci; + FILEPATHS_A fp; + UINT err; + + CHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! probably 256... */ + + memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO); + + TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin); + + if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_A_MAGIC)) + phsc = (PSC_HSC_A) pfdin->pv; + else { + ERR("pv %p is not an SC_HSC_A.\n", (pfdin) ? pfdin->pv : NULL); + return -1; + } + + switch (fdint) { + case fdintCABINET_INFO: + TRACE("Cabinet info notification\n"); + /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); + TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); + TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); + TRACE(" Cabinet Set#: %d\n", pfdin->setID); + TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ + WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n"); + ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]); + ci.CabinetPath = pfdin->psz3; + ci.DiskName = pfdin->psz2; + ci.SetId = pfdin->setID; + ci.CabinetNumber = pfdin->iCabinet; + phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0); + return 0; + case fdintPARTIAL_FILE: + TRACE("Partial file notification\n"); + /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */ + return 0; + case fdintCOPY_FILE: + TRACE("Copy file notification\n"); + TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); + /* TRACE(" File size: %ld\n", pfdin->cb); + TRACE(" File date: %u\n", pfdin->date); + TRACE(" File time: %u\n", pfdin->time); + TRACE(" File attr: %u\n", pfdin->attribs); */ + fici.NameInCabinet = pfdin->psz1; + fici.FileSize = pfdin->cb; + fici.Win32Error = 0; + fici.DosDate = pfdin->date; + fici.DosTime = pfdin->time; + fici.DosAttribs = pfdin->attribs; + memset(&(fici.FullTargetName[0]), 0, MAX_PATH); + err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET, + (UINT) &fici, (UINT) pfdin->psz1); + if (err == FILEOP_DOIT) { + TRACE(" Callback specified filename: %s\n", debugstr_a(&(fici.FullTargetName[0]))); + if (!fici.FullTargetName[0]) { + WARN(" Empty return string causing abort.\n"); + SetLastError(ERROR_PATH_NOT_FOUND); + return -1; + } + return sc_cb_open(&(fici.FullTargetName[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE); + } else { + TRACE(" Callback skipped file.\n"); + return 0; + } + case fdintCLOSE_FILE_INFO: + TRACE("Close file notification\n"); + /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); + TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No"); + TRACE(" File hndl: %d\n", pfdin->hf); */ + fp.Source = &(phsc->most_recent_cabinet_name[0]); + fp.Target = pfdin->psz1; + fp.Win32Error = 0; + fp.Flags = 0; + /* the following should be a fixme -- but it occurs too many times */ + WARN("Should set file date/time/attribs (and execute files?)\n"); + err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0); + if (sc_cb_close(pfdin->hf)) + WARN("_close failed.\n"); + if (err) { + SetLastError(err); + return FALSE; + } else + return TRUE; + case fdintNEXT_CABINET: + TRACE("Next cabinet notification\n"); + /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); + TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); + TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); + TRACE(" Cabinet Set#: %d\n", pfdin->setID); + TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ + ci.CabinetFile = pfdin->psz1; + ci.CabinetPath = pfdin->psz3; + ci.DiskName = pfdin->psz2; + ci.SetId = pfdin->setID; + ci.CabinetNumber = pfdin->iCabinet; + /* remember the new cabinet name */ + strcpy(&(phsc->most_recent_cabinet_name[0]), pfdin->psz1); + err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0])); + if (err) { + SetLastError(err); + return -1; + } else { + if (mysterio[0]) { + /* some easy paranoia. no such carefulness exists on the wide API IIRC */ + lstrcpynA(pfdin->psz3, &(mysterio[0]), SIZEOF_MYSTERIO); + } + return 0; + } + default: + FIXME("Unknown notification type %d.\n", fdint); + return 0; + } +} + +static INT_PTR sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) +{ + FILE_IN_CABINET_INFO_W fici; + PSC_HSC_W phsc; + CABINET_INFO_W ci; + FILEPATHS_W fp; + UINT err; + int len; + + WCHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! */ + WCHAR buf[MAX_PATH], buf2[MAX_PATH]; + CHAR charbuf[MAX_PATH]; + + memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO * sizeof(WCHAR)); + memset(&(buf[0]), 0, MAX_PATH * sizeof(WCHAR)); + memset(&(buf2[0]), 0, MAX_PATH * sizeof(WCHAR)); + memset(&(charbuf[0]), 0, MAX_PATH); + + TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin); + + if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_W_MAGIC)) + phsc = (PSC_HSC_W) pfdin->pv; + else { + ERR("pv %p is not an SC_HSC_W.\n", (pfdin) ? pfdin->pv : NULL); + return -1; + } + + switch (fdint) { + case fdintCABINET_INFO: + TRACE("Cabinet info notification\n"); + /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); + TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); + TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); + TRACE(" Cabinet Set#: %d\n", pfdin->setID); + TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ + WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n"); + ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]); + len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH); + if ((len > MAX_PATH) || (len <= 1)) + buf[0] = '\0'; + ci.CabinetPath = &(buf[0]); + len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH); + if ((len > MAX_PATH) || (len <= 1)) + buf2[0] = '\0'; + ci.DiskName = &(buf2[0]); + ci.SetId = pfdin->setID; + ci.CabinetNumber = pfdin->iCabinet; + phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0); + return 0; + case fdintPARTIAL_FILE: + TRACE("Partial file notification\n"); + /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */ + return 0; + case fdintCOPY_FILE: + TRACE("Copy file notification\n"); + TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); + /* TRACE(" File size: %ld\n", pfdin->cb); + TRACE(" File date: %u\n", pfdin->date); + TRACE(" File time: %u\n", pfdin->time); + TRACE(" File attr: %u\n", pfdin->attribs); */ + len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf2[0]), MAX_PATH); + if ((len > MAX_PATH) || (len <= 1)) + buf2[0] = '\0'; + fici.NameInCabinet = &(buf2[0]); + fici.FileSize = pfdin->cb; + fici.Win32Error = 0; + fici.DosDate = pfdin->date; + fici.DosTime = pfdin->time; + fici.DosAttribs = pfdin->attribs; + memset(&(fici.FullTargetName[0]), 0, MAX_PATH * sizeof(WCHAR)); + err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET, + (UINT) &fici, (UINT) pfdin->psz1); + if (err == FILEOP_DOIT) { + TRACE(" Callback specified filename: %s\n", debugstr_w(&(fici.FullTargetName[0]))); + if (fici.FullTargetName[0]) { + len = strlenW(&(fici.FullTargetName[0])) + 1; + if ((len > MAX_PATH ) || (len <= 1)) + return 0; + if (!WideCharToMultiByte(CP_ACP, 0, &(fici.FullTargetName[0]), len, &(charbuf[0]), MAX_PATH, 0, 0)) + return 0; + } else { + WARN("Empty buffer string caused abort.\n"); + SetLastError(ERROR_PATH_NOT_FOUND); + return -1; + } + return sc_cb_open(&(charbuf[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE); + } else { + TRACE(" Callback skipped file.\n"); + return 0; + } + case fdintCLOSE_FILE_INFO: + TRACE("Close file notification\n"); + /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1)); + TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No"); + TRACE(" File hndl: %d\n", pfdin->hf); */ + fp.Source = &(phsc->most_recent_cabinet_name[0]); + len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf[0]), MAX_PATH); + if ((len > MAX_PATH) || (len <= 1)) + buf[0] = '\0'; + fp.Target = &(buf[0]); + fp.Win32Error = 0; + fp.Flags = 0; + /* a valid fixme -- but occurs too many times */ + /* FIXME("Should set file date/time/attribs (and execute files?)\n"); */ + err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0); + if (sc_cb_close(pfdin->hf)) + WARN("_close failed.\n"); + if (err) { + SetLastError(err); + return FALSE; + } else + return TRUE; + case fdintNEXT_CABINET: + TRACE("Next cabinet notification\n"); + /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1)); + TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2)); + TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3)); + TRACE(" Cabinet Set#: %d\n", pfdin->setID); + TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */ + /* remember the new cabinet name */ + len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(phsc->most_recent_cabinet_name[0]), MAX_PATH); + if ((len > MAX_PATH) || (len <= 1)) + phsc->most_recent_cabinet_name[0] = '\0'; + ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]); + len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH); + if ((len > MAX_PATH) || (len <= 1)) + buf[0] = '\0'; + ci.CabinetPath = &(buf[0]); + len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH); + if ((len > MAX_PATH) || (len <= 1)) + buf2[0] = '\0'; + ci.DiskName = &(buf2[0]); + ci.SetId = pfdin->setID; + ci.CabinetNumber = pfdin->iCabinet; + err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0])); + if (err) { + SetLastError(err); + return -1; + } else { + if (mysterio[0]) { + len = strlenW(&(mysterio[0])) + 1; + if ((len > 255) || (len <= 1)) + return 0; + if (!WideCharToMultiByte(CP_ACP, 0, &(mysterio[0]), len, pfdin->psz3, 255, 0, 0)) + return 0; + } + return 0; + } + default: + FIXME("Unknown notification type %d.\n", fdint); + return 0; + } +} + +/*********************************************************************** + * SetupIterateCabinetA (SETUPAPI.@) + */ +BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved, + PSP_FILE_CALLBACK_A MsgHandler, PVOID Context) +{ + + SC_HSC_A my_hsc; + ERF erf; + CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *p; + DWORD fpnsize; + BOOL ret; + + + TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n", + debugstr_a(CabinetFile), Reserved, MsgHandler, Context); + + if (! LoadCABINETDll()) + return FALSE; + + memset(&my_hsc, 0, sizeof(SC_HSC_A)); + pszCabinet[0] = '\0'; + pszCabPath[0] = '\0'; + + fpnsize = strlen(CabinetFile); + if (fpnsize >= MAX_PATH) { + SetLastError(ERROR_BAD_PATHNAME); + return FALSE; + } + + fpnsize = GetFullPathNameA(CabinetFile, MAX_PATH, &(pszCabPath[0]), &p); + if (fpnsize > MAX_PATH) { + SetLastError(ERROR_BAD_PATHNAME); + return FALSE; + } + + if (p) { + strcpy(pszCabinet, p); + *p = '\0'; + } else { + strcpy(pszCabinet, CabinetFile); + pszCabPath[0] = '\0'; + } + + TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet)); + + /* remember the cabinet name */ + strcpy(&(my_hsc.most_recent_cabinet_name[0]), pszCabinet); + + my_hsc.magic = SC_HSC_A_MAGIC; + my_hsc.msghandler = MsgHandler; + my_hsc.context = Context; + my_hsc.hfdi = sc_FDICreate( sc_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read, + sc_cb_write, sc_cb_close, sc_cb_lseek, cpuUNKNOWN, &erf ); + + if (!my_hsc.hfdi) return FALSE; + + ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath, + 0, sc_FNNOTIFY_A, NULL, &my_hsc) ) ? TRUE : FALSE; + + sc_FDIDestroy(my_hsc.hfdi); + return ret; +} + + +/*********************************************************************** + * SetupIterateCabinetW (SETUPAPI.@) + */ +BOOL WINAPI SetupIterateCabinetW(PCWSTR CabinetFile, DWORD Reserved, + PSP_FILE_CALLBACK_W MsgHandler, PVOID Context) +{ + CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH]; + UINT len; + SC_HSC_W my_hsc; + ERF erf; + WCHAR pszCabPathW[MAX_PATH], *p; + DWORD fpnsize; + BOOL ret; + + TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n", + debugstr_w(CabinetFile), Reserved, MsgHandler, Context); + + if (!LoadCABINETDll()) + return FALSE; + + if (!CabinetFile) return FALSE; + + memset(&my_hsc, 0, sizeof(SC_HSC_W)); + + fpnsize = GetFullPathNameW(CabinetFile, MAX_PATH, pszCabPathW, &p); + if (fpnsize > MAX_PATH) { + SetLastError(ERROR_BAD_PATHNAME); + return FALSE; + } + + if (p) { + strcpyW(my_hsc.most_recent_cabinet_name, p); + *p = 0; + len = WideCharToMultiByte(CP_ACP, 0, pszCabPathW, -1, pszCabPath, + MAX_PATH, 0, 0); + if (!len) return FALSE; + } else { + strcpyW(my_hsc.most_recent_cabinet_name, CabinetFile); + pszCabPath[0] = '\0'; + } + + len = WideCharToMultiByte(CP_ACP, 0, my_hsc.most_recent_cabinet_name, -1, + pszCabinet, MAX_PATH, 0, 0); + if (!len) return FALSE; + + TRACE("path: %s, cabfile: %s\n", + debugstr_a(pszCabPath), debugstr_a(pszCabinet)); + + my_hsc.magic = SC_HSC_W_MAGIC; + my_hsc.msghandler = MsgHandler; + my_hsc.context = Context; + my_hsc.hfdi = sc_FDICreate( sc_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read, + sc_cb_write, sc_cb_close, sc_cb_lseek, cpuUNKNOWN, &erf ); + + if (!my_hsc.hfdi) return FALSE; + + ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath, + 0, sc_FNNOTIFY_W, NULL, &my_hsc) ) ? TRUE : FALSE; + + sc_FDIDestroy(my_hsc.hfdi); + return ret; +} + + +/*********************************************************************** + * DllMain + * + * PARAMS + * hinstDLL [I] handle to the DLL's instance + * fdwReason [I] + * lpvReserved [I] reserved, must be NULL + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + if (!GetVersionExW(&OsVersionInfo)) + return FALSE; + hInstance = (HINSTANCE)hinstDLL; + break; + case DLL_PROCESS_DETACH: + UnloadCABINETDll(); + break; + } + + return TRUE; +} diff --git a/reactos/lib/setupapi/setupx.spec b/reactos/lib/setupapi/setupx.spec index 07966296bd0..7243a9749d7 100644 --- a/reactos/lib/setupapi/setupx.spec +++ b/reactos/lib/setupapi/setupx.spec @@ -1,269 +1,269 @@ -#1 stub WEP -2 pascal -ret16 IpOpen(str ptr) IpOpen16 -3 stub IpOpenAppend #(str word) -4 pascal -ret16 IpClose(word) IpClose16 -5 stub IpGetLongField #(word ptr word ptr) -6 stub IpGetStringField #(word ptr word ptr word ptr) -7 stub IpFindFirstLine #(word str str ptr) -8 stub IpGetLineCount #(word str ptr) -9 stub IpGetFieldCount #(word ptr ptr) -10 stub IpGetIntField #(word ptr word ptr) -11 stub IpFindNextLine #(word ptr) -12 stub IpGetFileName #(word ptr word) -13 pascal -ret16 VcpQueueCopy(str str str str word word ptr word long) VcpQueueCopy16 -14 stub NOAUTORUNWNDPROC -15 stub __DEBUGMSG -16 stub __ASSERTMSG -17 pascal -ret16 VcpQueueDelete(str str word long) VcpQueueDelete16 -18 stub TpOpenFile #(str ptr word) -19 stub TpCloseFile #(word) -20 stub TpOpenSection #(word ptr str word) -21 stub TpCloseSection #(word) -22 stub TpCommitSection #(word word str word) -23 stub TpGetLine #(word str str word word ptr) -24 stub TpGetNextLine #(word str str ptr) -25 stub TpInsertLine #(word str str word word word) -26 stub TpReplaceLine #(word str str word word word) -27 stub TpDeleteLine #(word word word word) -28 stub TpMoveLine #(word word word word word word) -29 stub TpGetLineContents #(word ptr word ptr word word word) -30 stub TpGetPrivateProfileString #(str str str ptr word str) -31 stub TpWritePrivateProfileString #(str str str str) -32 stub TpGetProfileString #(str str str ptr word) -33 pascal -ret16 CtlSetLdd(ptr) CtlSetLdd16 -34 pascal -ret16 CtlGetLdd(ptr) CtlGetLdd16 -35 pascal -ret16 CtlFindLdd(ptr) CtlFindLdd16 -36 pascal -ret16 CtlAddLdd(ptr) CtlAddLdd16 -37 pascal -ret16 CtlDelLdd(word) CtlDelLdd16 -38 pascal -ret16 CtlGetLddPath(word ptr) CtlGetLddPath16 -39 stub SURegCloseKey #(word) -40 stub SURegCreateKey #(word) -41 stub SURegDeleteKey #(word str) -42 stub SURegDeleteValue #(word str) -43 stub SURegEnumKey #(word long ptr long) -44 stub SURegEnumValue #(word long str ptr ptr ptr ptr ptr) -45 stub SURegFlush #() -46 stub SURegInit #() -47 pascal SURegOpenKey(word str ptr) SURegOpenKey -48 stub SURegQueryValue -49 stub SURegQueryValue16 #(word str ptr ptr) -50 pascal SURegQueryValueEx(long str ptr ptr ptr ptr) SURegQueryValueEx -51 stub SURegSetValue -52 stub SURegSetValue16 #(word str long ptr long) -53 stub SURegSetValueEx #(word str long long ptr long) -54 stub SURegSaveKey #(word str ptr) -55 stub SURegLoadKey #(word str str) -56 stub SURegUnLoadKey #(word str) -60 stub DiskInfoFromLdid #(word ptr) -61 pascal suErrorToIds(word word) suErrorToIds16 -62 pascal -ret16 TPWriteProfileString(str str str) TPWriteProfileString16 -63 stub SURPLSETUP -# does SUSTORELDIDPATH set the path of an LDID in the registry ? -64 stub SUSTORELDIDPATH -65 stub WILDCARDSTRCMPI -101 pascal -ret16 GenInstall(word str word) GenInstall16 -102 stub GenWinInitRename #(str str word) -103 pascal GenFormStrWithoutPlaceHolders(str str word) GenFormStrWithoutPlaceHolders16 -104 stub SETUPX -105 stub CfgSetupMerge #(word) -106 stub INITDEPENDANTLDIDS -107 stub CFGOBJFINDKEYCMD -108 stub GenSURegSetValueEx -109 stub GENINSTALLWITHQUEUE -110 stub GenInstallEx #(word str word word ptr long) -111 stub GenCopyLogConfig2Reg #(word word str) -112 stub SUGetSetSetupFlags #(ptr word) -114 stub CFGPARSELINE # returns array -115 stub CFGSETAUTOPROCESS -116 stub CFGOBJTOSTR -117 stub CFGLNTOOBJ -118 stub MATCHCMDEXT -119 stub IpFindNextMatchLine #(word str ptr) -120 stub P_SETDEFAULTOPTION -121 stub CFGCLEANBOOT -122 stub CFGMATCHCMDEXT -123 stub CFGWASFILEUPDATED -124 stub AUTOMATCHCMDEXT -125 stub P_VALIDATEOC -126 stub GENMAPROOTREGSTR2KEY -127 stub P_CDROMOC -128 stub P_MEDIAOC -129 stub CFGCLEAN1STBOOT -130 stub suFormatMessage -131 stub suvFormatMessage #(word str str word ptr) -132 stub suFormatMessageBox -#133 stub suHelp # W98SE conflict !! -135 stub suHelp #(word word) -#135 stub P_WEBTVOC # W98SE conflict !! -136 stub P_WBEMOC -137 stub P_THEMESOC -138 stub P_IMAGINGOC -139 stub P_SCHEMESOC -140 stub suVerConflict #(word ptr word ptr) -141 stub suVerConflictInit #(word) -142 stub suVerConflictTerm #(ptr) -# Emergency Boot Disk -143 stub suCreateEBD #(word ptr long) -144 stub suCopyToEBD -145 stub sxIsMSDOS7Running #() -150 stub DS_INIT -151 stub DS_DESTROY -152 stub DS_SSYNCDRIVES -153 stub DS_GETDRIVEDATA -154 stub DS_ADDSECTION -155 stub DS_ENABLESECTION -156 stub DS_DISABLESECTION -157 stub DS_SETSWAPSIZE -158 stub DS_SETREQUIREDPAD -159 stub DS_SETAVAILABLEPAD -160 stub SXUPDATEDS -170 stub SUSETMEM -171 stub WriteDMFBootData #(word ptr word) -200 pascal VcpOpen(segptr ptr) VcpOpen16 -201 pascal VcpClose(word str) VcpClose16 -202 pascal -ret16 vcpDefCallbackProc(ptr word word long long) vcpDefCallbackProc16 -203 stub vcpEnumFiles #(ptr long) -204 pascal -ret16 VcpQueueRename(str str str str word word long) VcpQueueRename16 -205 pascal -ret16 vsmGetStringName(word ptr word) vsmGetStringName16 -206 pascal -ret16 vsmStringDelete(word) vsmStringDelete16 -207 pascal -ret16 vsmStringAdd(str) vsmStringAdd16 -208 pascal vsmGetStringRawName(word) vsmGetStringRawName16 -209 stub IpSaveRestorePosition #(word word) -210 pascal -ret16 IpGetProfileString(word str str ptr word) IpGetProfileString16 -211 stub IpOpenEx #(str ptr word) -212 stub IpOpenAppendEx #(str word word) -213 pascal -ret16 vcpUICallbackProc(ptr word word long long) vcpUICallbackProc16 -214 stub VcpAddMRUPath #(str) -300 pascal -ret16 DiBuildCompatDrvList (ptr) DiBuildCompatDrvList16 -301 pascal -ret16 DiBuildClassDrvList (ptr) DiBuildClassDrvList16 -302 stub DiDestroyDriverNodeList #(ptr) -303 pascal -ret16 DiCreateDeviceInfo (ptr str long long str str word) DiCreateDeviceInfo16 -304 pascal -ret16 DiGetClassDevs(ptr str word word) DiGetClassDevs16 -305 pascal -ret16 DiDestroyDeviceInfoList (ptr) DiDestroyDeviceInfoList16 -306 stub DiRemoveDevice #(ptr) -308 pascal -ret16 DiCallClassInstaller (word ptr) DiCallClassInstaller16 -309 stub DiCreateDriverNode #(ptr word word word str str str str str str long) -310 stub DiDrawMiniIcon -311 stub DiGetClassBitmapIndex #(str ptr) -312 stub DiSelectDevice #(ptr) -313 stub DiInstallDevice #(ptr) -314 stub DiLoadClassIcon #(str ptr ptr) -315 stub DiAskForOEMDisk #(ptr) -316 stub Display_SetMode #(ptr word word word) -317 stub Display_ClassInstaller #(word ptr) -318 pascal -ret16 DiCreateDevRegKey (ptr ptr word str word) DiCreateDevRegKey16 -319 pascal -ret16 DiOpenDevRegKey (ptr ptr word) DiOpenDevRegKey16 -320 stub DiInstallDrvSection #(str str str str long) -321 stub DiInstallClass #(str long) -322 stub DiOpenClassRegKey #(ptr str) -323 stub Display_SetFontSize #(str) -324 stub Display_OpenFontSizeKey #(ptr) -325 stub DiBuildClassDrvListFromOldInf #(ptr str ptr long) -326 stub DiIsThereNeedToCopy #(word long) -333 stub DiChangeState #(ptr long long long) -334 stub WALKSUBTREE -340 stub GetFctn #(word str str ptr ptr) -341 stub DiBuildClassInfoList #(ptr) -342 stub DiDestroyClassInfoList #(ptr) -343 stub DiGetDeviceClassInfo #(ptr ptr) -344 pascal -ret16 DiDeleteDevRegKey (ptr word) DiDeleteDevRegKey16 -350 stub DiSelectOEMDrv #(word ptr) -351 stub DiGetINFClass #(str word str long) -353 stub DIPICKBESTDRIVER -355 stub COPYINFFILE -360 stub GenInfLCToDevNode #(word str word word long) -361 stub GETDOSMESSAGE -362 stub Mouse_ClassInstaller #(word ptr) -363 stub sxCompareDosAppVer #(str str) -364 stub MONITOR_CLASSINSTALLER -365 stub FCEGETRESDESOFFSET -366 stub FCEGETALLOCVALUE -367 stub FCEADDRESDES -368 stub FCEDELETERESDES -369 stub FCEINIT -370 stub FCEGETRESDES -371 stub FCEGETFIRSTVALUE -372 stub FCEGETOTHERVALUE -373 stub FCEGETVALIDATEVALUE -374 stub FCEWRITETHISFORCEDCONFIGNOW -375 stub SUCreatePropertySheetPage #(ptr) -376 stub SUDestroyPropertySheetPage #(word) -377 stub SUPropertySheet #(ptr) -380 stub DiReadRegLogConf #(ptr str ptr ptr) -381 stub DiReadRegConf #(ptr ptr ptr long) -390 stub DiBuildPotentialDuplicatesList #(ptr ptr long ptr ptr) -395 stub InitSubstrData #(ptr str) -396 stub GetFirstSubstr #(ptr) -397 stub GetNextSubstr #(ptr) -398 stub INITSUBSTRDATAEX -400 stub bIsFileInVMM32 #(str) -401 stub DiInstallDriverFiles #(ptr) -405 stub DiBuildClassInfoListEx #(ptr long) -406 stub DiGetClassDevsEx #(ptr str str word word) -407 stub DiCopyRegSubKeyValue #(word str str str) -408 stub IPGETDRIVERDATE -409 stub IPGETDRIVERVERSION -410 stub IpGetVersionString #(str str ptr word str) -411 pascal VcpExplain(ptr long) VcpExplain16 -412 stub DiBuildDriverIndex #(word) -413 stub DiAddSingleInfToDrvIdx #(str word word) -414 stub FCEGETFLAGS -450 stub UiMakeDlgNonBold #(word) -451 stub UiDeleteNonBoldFont #(word) -500 stub SUEBDPAGE -501 stub SUOCPAGE -502 stub SXLISTSUBPROC -503 stub SXFILLLB -504 stub SXOCPAGEDLG -506 stub SXOCBATCHSETTINGS -507 stub SXOCFIXNEEDS -508 pascal -ret16 CtlSetLddPath(word str) CtlSetLddPath16 -509 stub SXCALLOCPROC -510 stub BUILDINFOCS -511 stub BUILDREGOCS -512 stub DELETEOCS -520 stub DiBuildClassDrvInfoList #(ptr) -521 stub DiBuildCompatDrvInfoList #(ptr) -522 stub DiDestroyDrvInfoList #(ptr) -523 stub DiConvertDriverInfoToDriverNode #(ptr ptr) -524 stub DISELECTBESTCOMPATDRV -525 stub FirstBootMoveToDOSSTART #(str word) -526 stub DOSOptEnableCurCfg #(str) -527 pascal -ret16 InstallHinfSection(word word str word) InstallHinfSection16 -528 stub SXMAKEUNCPATH -529 stub SXISSBSSERVERFILE -530 stub SXFINDBATCHFILES -531 stub ISPANEUROPEAN -532 stub UPGRADENIGGLINGS -533 stub DISPLAY_ISSECONDDISPLAY -534 stub ISWINDOWSFILE -540 stub VERIFYSELECTEDDRIVER -575 stub SXCALLMIGRATIONDLLS -576 stub SXCALLMIGRATIONDLLS_RUNDLL -600 stub PidConstruct #(str str str word) -601 stub PidValidate #(str str) -602 stub GETJAPANESEKEYBOARDTYPE -610 stub CRC32COMPUTE -621 stub SXSAVEINFO -622 stub SXADDPAGEEX -623 stub OPKREMOVEINSTALLEDNETDEVICE -640 stub DOFIRSTRUNSCREENS -700 stub SXSHOWREBOOTDLG -701 stub SXSHOWREBOOTDLG_RUNDLL -750 stub UIPOSITIONDIALOG -775 stub ASPICLEAN -800 stub EXTRACTCABFILE -825 stub PIDGEN3 -826 stub GETSETUPINFO -827 stub SETSETUPINFO -828 stub GETKEYBOARDOPTIONS -829 stub GETLOCALEOPTIONS -830 stub SETINTLOPTIONS -831 stub GETPRODUCTTYPE -832 stub ISOPKMODE -833 stub AUDITONETIMEINSTALL -834 stub DISKDUP -835 stub OPKPREINSTALL -836 stub ISAUDITMODE -837 stub ISAUDITAUTO -838 stub GETVALIDEULA +#1 stub WEP +2 pascal -ret16 IpOpen(str ptr) IpOpen16 +3 stub IpOpenAppend #(str word) +4 pascal -ret16 IpClose(word) IpClose16 +5 stub IpGetLongField #(word ptr word ptr) +6 stub IpGetStringField #(word ptr word ptr word ptr) +7 stub IpFindFirstLine #(word str str ptr) +8 stub IpGetLineCount #(word str ptr) +9 stub IpGetFieldCount #(word ptr ptr) +10 stub IpGetIntField #(word ptr word ptr) +11 stub IpFindNextLine #(word ptr) +12 stub IpGetFileName #(word ptr word) +13 pascal -ret16 VcpQueueCopy(str str str str word word ptr word long) VcpQueueCopy16 +14 stub NOAUTORUNWNDPROC +15 stub __DEBUGMSG +16 stub __ASSERTMSG +17 pascal -ret16 VcpQueueDelete(str str word long) VcpQueueDelete16 +18 stub TpOpenFile #(str ptr word) +19 stub TpCloseFile #(word) +20 stub TpOpenSection #(word ptr str word) +21 stub TpCloseSection #(word) +22 stub TpCommitSection #(word word str word) +23 stub TpGetLine #(word str str word word ptr) +24 stub TpGetNextLine #(word str str ptr) +25 stub TpInsertLine #(word str str word word word) +26 stub TpReplaceLine #(word str str word word word) +27 stub TpDeleteLine #(word word word word) +28 stub TpMoveLine #(word word word word word word) +29 stub TpGetLineContents #(word ptr word ptr word word word) +30 stub TpGetPrivateProfileString #(str str str ptr word str) +31 stub TpWritePrivateProfileString #(str str str str) +32 stub TpGetProfileString #(str str str ptr word) +33 pascal -ret16 CtlSetLdd(ptr) CtlSetLdd16 +34 pascal -ret16 CtlGetLdd(ptr) CtlGetLdd16 +35 pascal -ret16 CtlFindLdd(ptr) CtlFindLdd16 +36 pascal -ret16 CtlAddLdd(ptr) CtlAddLdd16 +37 pascal -ret16 CtlDelLdd(word) CtlDelLdd16 +38 pascal -ret16 CtlGetLddPath(word ptr) CtlGetLddPath16 +39 stub SURegCloseKey #(word) +40 stub SURegCreateKey #(word) +41 stub SURegDeleteKey #(word str) +42 stub SURegDeleteValue #(word str) +43 stub SURegEnumKey #(word long ptr long) +44 stub SURegEnumValue #(word long str ptr ptr ptr ptr ptr) +45 stub SURegFlush #() +46 stub SURegInit #() +47 pascal SURegOpenKey(word str ptr) SURegOpenKey +48 stub SURegQueryValue +49 stub SURegQueryValue16 #(word str ptr ptr) +50 pascal SURegQueryValueEx(long str ptr ptr ptr ptr) SURegQueryValueEx +51 stub SURegSetValue +52 stub SURegSetValue16 #(word str long ptr long) +53 stub SURegSetValueEx #(word str long long ptr long) +54 stub SURegSaveKey #(word str ptr) +55 stub SURegLoadKey #(word str str) +56 stub SURegUnLoadKey #(word str) +60 stub DiskInfoFromLdid #(word ptr) +61 pascal suErrorToIds(word word) suErrorToIds16 +62 pascal -ret16 TPWriteProfileString(str str str) TPWriteProfileString16 +63 stub SURPLSETUP +# does SUSTORELDIDPATH set the path of an LDID in the registry ? +64 stub SUSTORELDIDPATH +65 stub WILDCARDSTRCMPI +101 pascal -ret16 GenInstall(word str word) GenInstall16 +102 stub GenWinInitRename #(str str word) +103 pascal GenFormStrWithoutPlaceHolders(str str word) GenFormStrWithoutPlaceHolders16 +104 stub SETUPX +105 stub CfgSetupMerge #(word) +106 stub INITDEPENDANTLDIDS +107 stub CFGOBJFINDKEYCMD +108 stub GenSURegSetValueEx +109 stub GENINSTALLWITHQUEUE +110 stub GenInstallEx #(word str word word ptr long) +111 stub GenCopyLogConfig2Reg #(word word str) +112 stub SUGetSetSetupFlags #(ptr word) +114 stub CFGPARSELINE # returns array +115 stub CFGSETAUTOPROCESS +116 stub CFGOBJTOSTR +117 stub CFGLNTOOBJ +118 stub MATCHCMDEXT +119 stub IpFindNextMatchLine #(word str ptr) +120 stub P_SETDEFAULTOPTION +121 stub CFGCLEANBOOT +122 stub CFGMATCHCMDEXT +123 stub CFGWASFILEUPDATED +124 stub AUTOMATCHCMDEXT +125 stub P_VALIDATEOC +126 stub GENMAPROOTREGSTR2KEY +127 stub P_CDROMOC +128 stub P_MEDIAOC +129 stub CFGCLEAN1STBOOT +130 stub suFormatMessage +131 stub suvFormatMessage #(word str str word ptr) +132 stub suFormatMessageBox +#133 stub suHelp # W98SE conflict !! +135 stub suHelp #(word word) +#135 stub P_WEBTVOC # W98SE conflict !! +136 stub P_WBEMOC +137 stub P_THEMESOC +138 stub P_IMAGINGOC +139 stub P_SCHEMESOC +140 stub suVerConflict #(word ptr word ptr) +141 stub suVerConflictInit #(word) +142 stub suVerConflictTerm #(ptr) +# Emergency Boot Disk +143 stub suCreateEBD #(word ptr long) +144 stub suCopyToEBD +145 stub sxIsMSDOS7Running #() +150 stub DS_INIT +151 stub DS_DESTROY +152 stub DS_SSYNCDRIVES +153 stub DS_GETDRIVEDATA +154 stub DS_ADDSECTION +155 stub DS_ENABLESECTION +156 stub DS_DISABLESECTION +157 stub DS_SETSWAPSIZE +158 stub DS_SETREQUIREDPAD +159 stub DS_SETAVAILABLEPAD +160 stub SXUPDATEDS +170 stub SUSETMEM +171 stub WriteDMFBootData #(word ptr word) +200 pascal VcpOpen(segptr ptr) VcpOpen16 +201 pascal VcpClose(word str) VcpClose16 +202 pascal -ret16 vcpDefCallbackProc(ptr word word long long) vcpDefCallbackProc16 +203 stub vcpEnumFiles #(ptr long) +204 pascal -ret16 VcpQueueRename(str str str str word word long) VcpQueueRename16 +205 pascal -ret16 vsmGetStringName(word ptr word) vsmGetStringName16 +206 pascal -ret16 vsmStringDelete(word) vsmStringDelete16 +207 pascal -ret16 vsmStringAdd(str) vsmStringAdd16 +208 pascal vsmGetStringRawName(word) vsmGetStringRawName16 +209 stub IpSaveRestorePosition #(word word) +210 pascal -ret16 IpGetProfileString(word str str ptr word) IpGetProfileString16 +211 stub IpOpenEx #(str ptr word) +212 stub IpOpenAppendEx #(str word word) +213 pascal -ret16 vcpUICallbackProc(ptr word word long long) vcpUICallbackProc16 +214 stub VcpAddMRUPath #(str) +300 pascal -ret16 DiBuildCompatDrvList (ptr) DiBuildCompatDrvList16 +301 pascal -ret16 DiBuildClassDrvList (ptr) DiBuildClassDrvList16 +302 stub DiDestroyDriverNodeList #(ptr) +303 pascal -ret16 DiCreateDeviceInfo (ptr str long long str str word) DiCreateDeviceInfo16 +304 pascal -ret16 DiGetClassDevs(ptr str word word) DiGetClassDevs16 +305 pascal -ret16 DiDestroyDeviceInfoList (ptr) DiDestroyDeviceInfoList16 +306 stub DiRemoveDevice #(ptr) +308 pascal -ret16 DiCallClassInstaller (word ptr) DiCallClassInstaller16 +309 stub DiCreateDriverNode #(ptr word word word str str str str str str long) +310 stub DiDrawMiniIcon +311 stub DiGetClassBitmapIndex #(str ptr) +312 stub DiSelectDevice #(ptr) +313 stub DiInstallDevice #(ptr) +314 stub DiLoadClassIcon #(str ptr ptr) +315 stub DiAskForOEMDisk #(ptr) +316 stub Display_SetMode #(ptr word word word) +317 stub Display_ClassInstaller #(word ptr) +318 pascal -ret16 DiCreateDevRegKey (ptr ptr word str word) DiCreateDevRegKey16 +319 pascal -ret16 DiOpenDevRegKey (ptr ptr word) DiOpenDevRegKey16 +320 stub DiInstallDrvSection #(str str str str long) +321 stub DiInstallClass #(str long) +322 stub DiOpenClassRegKey #(ptr str) +323 stub Display_SetFontSize #(str) +324 stub Display_OpenFontSizeKey #(ptr) +325 stub DiBuildClassDrvListFromOldInf #(ptr str ptr long) +326 stub DiIsThereNeedToCopy #(word long) +333 stub DiChangeState #(ptr long long long) +334 stub WALKSUBTREE +340 stub GetFctn #(word str str ptr ptr) +341 stub DiBuildClassInfoList #(ptr) +342 stub DiDestroyClassInfoList #(ptr) +343 stub DiGetDeviceClassInfo #(ptr ptr) +344 pascal -ret16 DiDeleteDevRegKey (ptr word) DiDeleteDevRegKey16 +350 stub DiSelectOEMDrv #(word ptr) +351 stub DiGetINFClass #(str word str long) +353 stub DIPICKBESTDRIVER +355 stub COPYINFFILE +360 stub GenInfLCToDevNode #(word str word word long) +361 stub GETDOSMESSAGE +362 stub Mouse_ClassInstaller #(word ptr) +363 stub sxCompareDosAppVer #(str str) +364 stub MONITOR_CLASSINSTALLER +365 stub FCEGETRESDESOFFSET +366 stub FCEGETALLOCVALUE +367 stub FCEADDRESDES +368 stub FCEDELETERESDES +369 stub FCEINIT +370 stub FCEGETRESDES +371 stub FCEGETFIRSTVALUE +372 stub FCEGETOTHERVALUE +373 stub FCEGETVALIDATEVALUE +374 stub FCEWRITETHISFORCEDCONFIGNOW +375 stub SUCreatePropertySheetPage #(ptr) +376 stub SUDestroyPropertySheetPage #(word) +377 stub SUPropertySheet #(ptr) +380 stub DiReadRegLogConf #(ptr str ptr ptr) +381 stub DiReadRegConf #(ptr ptr ptr long) +390 stub DiBuildPotentialDuplicatesList #(ptr ptr long ptr ptr) +395 stub InitSubstrData #(ptr str) +396 stub GetFirstSubstr #(ptr) +397 stub GetNextSubstr #(ptr) +398 stub INITSUBSTRDATAEX +400 stub bIsFileInVMM32 #(str) +401 stub DiInstallDriverFiles #(ptr) +405 stub DiBuildClassInfoListEx #(ptr long) +406 stub DiGetClassDevsEx #(ptr str str word word) +407 stub DiCopyRegSubKeyValue #(word str str str) +408 stub IPGETDRIVERDATE +409 stub IPGETDRIVERVERSION +410 stub IpGetVersionString #(str str ptr word str) +411 pascal VcpExplain(ptr long) VcpExplain16 +412 stub DiBuildDriverIndex #(word) +413 stub DiAddSingleInfToDrvIdx #(str word word) +414 stub FCEGETFLAGS +450 stub UiMakeDlgNonBold #(word) +451 stub UiDeleteNonBoldFont #(word) +500 stub SUEBDPAGE +501 stub SUOCPAGE +502 stub SXLISTSUBPROC +503 stub SXFILLLB +504 stub SXOCPAGEDLG +506 stub SXOCBATCHSETTINGS +507 stub SXOCFIXNEEDS +508 pascal -ret16 CtlSetLddPath(word str) CtlSetLddPath16 +509 stub SXCALLOCPROC +510 stub BUILDINFOCS +511 stub BUILDREGOCS +512 stub DELETEOCS +520 stub DiBuildClassDrvInfoList #(ptr) +521 stub DiBuildCompatDrvInfoList #(ptr) +522 stub DiDestroyDrvInfoList #(ptr) +523 stub DiConvertDriverInfoToDriverNode #(ptr ptr) +524 stub DISELECTBESTCOMPATDRV +525 stub FirstBootMoveToDOSSTART #(str word) +526 stub DOSOptEnableCurCfg #(str) +527 pascal -ret16 InstallHinfSection(word word str word) InstallHinfSection16 +528 stub SXMAKEUNCPATH +529 stub SXISSBSSERVERFILE +530 stub SXFINDBATCHFILES +531 stub ISPANEUROPEAN +532 stub UPGRADENIGGLINGS +533 stub DISPLAY_ISSECONDDISPLAY +534 stub ISWINDOWSFILE +540 stub VERIFYSELECTEDDRIVER +575 stub SXCALLMIGRATIONDLLS +576 stub SXCALLMIGRATIONDLLS_RUNDLL +600 stub PidConstruct #(str str str word) +601 stub PidValidate #(str str) +602 stub GETJAPANESEKEYBOARDTYPE +610 stub CRC32COMPUTE +621 stub SXSAVEINFO +622 stub SXADDPAGEEX +623 stub OPKREMOVEINSTALLEDNETDEVICE +640 stub DOFIRSTRUNSCREENS +700 stub SXSHOWREBOOTDLG +701 stub SXSHOWREBOOTDLG_RUNDLL +750 stub UIPOSITIONDIALOG +775 stub ASPICLEAN +800 stub EXTRACTCABFILE +825 stub PIDGEN3 +826 stub GETSETUPINFO +827 stub SETSETUPINFO +828 stub GETKEYBOARDOPTIONS +829 stub GETLOCALEOPTIONS +830 stub SETINTLOPTIONS +831 stub GETPRODUCTTYPE +832 stub ISOPKMODE +833 stub AUDITONETIMEINSTALL +834 stub DISKDUP +835 stub OPKPREINSTALL +836 stub ISAUDITMODE +837 stub ISAUDITAUTO +838 stub GETVALIDEULA diff --git a/reactos/lib/setupapi/setupx16.h b/reactos/lib/setupapi/setupx16.h index 6fd50df07e6..4b5468fd5a3 100644 --- a/reactos/lib/setupapi/setupx16.h +++ b/reactos/lib/setupapi/setupx16.h @@ -1,563 +1,563 @@ -/* - * Copyright 2000 Andreas Mohr for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __SETUPX16_H -#define __SETUPX16_H - -#include "wine/windef16.h" - -typedef UINT16 DI_FUNCTION16; -typedef UINT16 HINF16; -typedef UINT16 LOGDISKID16; -typedef UINT16 VHSTR; - -#define LINE_LEN 256 - -/* error codes stuff */ - -typedef UINT16 RETERR16; -#define OK 0 -#define IP_ERROR (UINT16)100 -#define TP_ERROR (UINT16)200 -#define VCP_ERROR (UINT16)300 -#define GEN_ERROR (UINT16)400 -#define DI_ERROR (UINT16)500 - -enum { - ERR_IP_INVALID_FILENAME = IP_ERROR+1, - ERR_IP_ALLOC_ERR, - ERR_IP_INVALID_SECT_NAME, - ERR_IP_OUT_OF_HANDLES, - ERR_IP_INF_NOT_FOUND, - ERR_IP_INVALID_INFFILE, - ERR_IP_INVALID_HINF, - ERR_IP_INVALID_FIELD, - ERR_IP_SECT_NOT_FOUND, - ERR_IP_END_OF_SECTION, - ERR_IP_PROFILE_NOT_FOUND, - ERR_IP_LINE_NOT_FOUND, - ERR_IP_FILEREAD, - ERR_IP_TOOMANYINFFILES, - ERR_IP_INVALID_SAVERESTORE, - ERR_IP_INVALID_INFTYPE -}; - -/****** virtual copy operations ******/ - -typedef DWORD LPEXPANDVTBL; - -typedef struct { - DWORD dwSoFar; - DWORD dwTotal; -} VCPPROGRESS, *LPVCPPROGRESS; - -typedef struct { - WORD cbSize; - LOGDISKID16 ldid; - VHSTR vhstrRoot; - VHSTR vhstrVolumeLabel; - VHSTR vhstrDiskName; - WORD wVolumeTime; - WORD wVolumeDate; - DWORD dwSerialNumber; - WORD fl; - LPARAM lparamRef; - - VCPPROGRESS prgFileRead; - VCPPROGRESS prgByteRead; - - VCPPROGRESS prgFileWrite; - VCPPROGRESS prgByteWrite; -} VCPDISKINFO, *LPVCPDISKINFO; - -typedef struct { - LOGDISKID16 ldid; - VHSTR vhstrDir; - VHSTR vhstrFileName; -} VCPFILESPEC, *LPVCPFILESPEC; - -typedef struct { - UINT16 uiMDate; - UINT16 uiMTime; - UINT16 uiADate; - UINT16 uiATime; - UINT16 uiAttr; - DWORD llenIn; - DWORD llenOut; -} VCPFATTR, *LPVCPFATTR; - -typedef struct { - UINT16 uDate; - UINT16 uTime; - DWORD dwSize; -} VCPFILESTAT, *LPVCPFILESTAT; - -typedef struct -{ - HFILE16 hFileSrc; - HFILE16 hFileDst; - VCPFATTR fAttr; - WORD dosError; - VHSTR vhstrFileName; - WPARAM vcpm; -} VIRTNODEEX, *LPVIRTNODEEX; - -typedef struct { - WORD cbSize; - VCPFILESPEC vfsSrc; - VCPFILESPEC vfsDst; - WORD fl; - LPARAM lParam; - LPEXPANDVTBL lpExpandVtbl; - LPVIRTNODEEX lpvnex; - VHSTR vhstrDstFinalName; - VCPFILESTAT vFileStat; -} VIRTNODE, *LPVIRTNODE; - -typedef struct { - WORD cbSize; - VCPPROGRESS prgDiskRead; - VCPPROGRESS prgFileRead; - VCPPROGRESS prgByteRead; - - VCPPROGRESS prgDiskWrite; - VCPPROGRESS prgFileWrite; - VCPPROGRESS prgByteWrite; - - LPVCPDISKINFO lpvdiIn; - LPVCPDISKINFO lpvdiOut; - LPVIRTNODE lpvn; -} VCPSTATUS, *LPVCPSTATUS; - -#define CNFL_BACKUP 0x0001 -#define CNFL_DELETEONFAILURE 0x0002 -#define CNFL_RENAMEONSUCCESS 0x0004 -#define CNFL_CONTINUATION 0x0008 -#define CNFL_SKIPPED 0x0010 -#define CNFL_IGNOREERRORS 0x0020 -#define CNFL_RETRYFILE 0x0040 -#define CNFL_COPIED 0x0080 -#define VNFL_UNIQUE 0x0000 -#define VNFL_MULTIPLEOK 0x0100 -#define VNFL_DESTROYOLD 0x0200 -#define VNFL_COPY 0x0000 -#define VNFL_DELETE 0x0800 -#define VNFL_RENAME 0x1000 -#define VNFL_NODE_TYPE (VNFL_RENAME|VNFL_DELETE|VNFL_COPY) -#define VNFL_CREATED 0x2000 -#define VNFL_REJECTED 0x4000 -#define VNFL_DEVICEINSTALLER 0x8000 - -enum { - ERR_VCP_IOFAIL = VCP_ERROR+1, - ERR_VCP_STRINGTOOLONG, - ERR_VCP_NOMEM, - ERR_VCP_QUEUEFULL, - ERR_VCP_NOVHSTR, - ERR_VCP_OVERFLOW, - ERR_VCP_BADARG, - ERR_VCP_UNINIT, - ERR_VCP_NOTFOUND, - ERR_VCP_BUSY, - ERR_VCP_INTERRUPTED, - ERR_VCP_BADDEST, - ERR_VCP_SKIPPED, - ERR_VCP_IO, - ERR_VCP_LOCKED, - ERR_VCP_WRONGDISK, - ERR_VCP_CHANGEMODE, - ERR_VCP_LDDINVALID, - ERR_VCP_LDDFIND, - ERR_VCP_LDDUNINIT, - ERR_VCP_LDDPATH_INVALID, - ERR_VCP_NOEXPANSION, - ERR_VCP_NOTOPEN, - ERR_VCP_NO_DIGITAL_SIGNATURE_CATALOG, - ERR_VCP_NO_DIGITAL_SIGNATURE_FILE -}; - -#define VCPN_OK 0 -#define VCPN_PROCEED 0 -#define VCPN_ABORT -1 -#define VCPN_RETRY -2 -#define VCPN_IGNORE -3 -#define VCPN_SKIP -4 -#define VCPN_FORCE -5 -#define VCPN_DEFER -6 -#define VCPN_FAIL -7 -#define VCPN_RETRYFILE -8 - -#define VCPFL_ABANDON 0x00 -#define VCPFL_BACKUP 0x01 -#define VCPFL_COPY 0x02 -#define VCPFL_BACKUPANDCOPY (VCPFL_BACKUP|VCPFL_COPY) -#define VCPFL_INSPECIFIEDORDER 0x04 -#define VCPFL_DELETE 0x08 -#define VCPFL_RENAME 0x10 -#define VCPFL_ALL (VCPFL_COPY|VCPFL_DELETE|VCPFL_RENAME) - -#define CFNL_BACKUP 0x0001 -#define CFNL_DELETEONFAILURE 0x0002 -#define CFNL_RENAMEONSUCCESS 0x0004 -#define CFNL_CONTINUATION 0x0008 -#define CFNL_SKIPPED 0x0010 -#define CFNL_IGNOREERRORS 0x0020 -#define CFNL_RETRYFILE 0x0040 -#define CFNL_COPIED 0x0080 -#define VFNL_MULTIPLEOK 0x0100 -#define VFNL_DESTROYOLD 0x0200 -#define VFNL_NOW 0x0400 -#define VFNL_COPY 0x0000 -#define VFNL_DELETE 0x0800 -#define VFNL_RENAME 0x1000 -#define VFNL_CREATED 0x2000 -#define VFNL_REJECTED 0x4000 -#define VCPM_DISKCLASS 0x01 -#define VCPM_DISKFIRST 0x0100 -#define VCPM_DISKLAST 0x01ff - -enum { - VCPM_DISKCREATEINFO = VCPM_DISKFIRST, - VCPM_DISKGETINFO, - VCPM_DISKDESTROYINFO, - VCPM_DISKPREPINFO, - VCPM_DISKENSURE, - VCPM_DISKPROMPT, - VCPM_DISKFORMATBEGIN, - VCPM_DISKFORMATTING, - VCPM_DISKFORMATEND -}; - -#define VCPM_FILEINCLASS 0x02 -#define VCPM_FILEOUTCLASS 0x03 -#define VCPM_FILEFIRSTIN 0x0200 -#define VCPM_FILEFIRSTOUT 0x0300 -#define VCPM_FILELAST 0x03ff - -enum { - VCPM_FILEOPENIN = VCPM_FILEFIRSTIN, - VCPM_FILEGETFATTR, - VCPM_FILECLOSEIN, - VCPM_FILECOPY, - VCPM_FILENEEDED, - - VCPM_FILEOPENOUT = VCPM_FILEFIRSTOUT, - VCPM_FILESETFATTR, - VCPM_FILECLOSEOUT, - VCPM_FILEFINALIZE, - VCPM_FILEDELETE, - VCPM_FILERENAME -}; - -#define VCPM_NODECLASS 0x04 -#define VCPM_NODEFIRST 0x0400 -#define VCPM_NODELAST 0x04ff - -enum { - VCPM_NODECREATE = VCPM_NODEFIRST, - VCPM_NODEACCEPT, - VCPM_NODEREJECT, - VCPM_NODEDESTROY, - VCPM_NODECHANGEDESTDIR, - VCPM_NODECOMPARE -}; - -#define VCPM_TALLYCLASS 0x05 -#define VCPM_TALLYFIRST 0x0500 -#define VCPM_TALLYLAST 0x05ff - -enum { - VCPM_TALLYSTART = VCPM_TALLYFIRST, - VCPM_TALLYEND, - VCPM_TALLYFILE, - VCPM_TALLYDISK -}; - -#define VCPM_VERCLASS 0x06 -#define VCPM_VERFIRST 0x0600 -#define VCPM_VERLAST 0x06ff - -enum { - VCPM_VERCHECK = VCPM_VERFIRST, - VCPM_VERCHECKDONE, - VCPM_VERRESOLVECONFLICT -}; - -#define VCPM_VSTATCLASS 0x07 -#define VCPM_VSTATFIRST 0x0700 -#define VCPM_VSTATLAST 0x07ff - -enum { - VCPM_VSTATSTART = VCPM_VSTATFIRST, - VCPM_VSTATEND, - VCPM_VSTATREAD, - VCPM_VSTATWRITE, - VCPM_VSTATNEWDISK, - VCPM_VSTATCLOSESTART, - VCPM_VSTATCLOSEEND, - VCPM_VSTATBACKUPSTART, - VCPM_VSTATBACKUPEND, - VCPM_VSTATRENAMESTART, - VCPM_VSTATRENAMEEND, - VCPM_VSTATCOPYSTART, - VCPM_VSTATCOPYEND, - VCPM_VSTATDELETESTART, - VCPM_VSTATDELETEEND, - VCPM_VSTATPATHCHECKSTART, - VCPM_VSTATPATHCHECKEND, - VCPM_VSTATCERTIFYSTART, - VCPM_VSTATCERTIFYEND, - VCPM_VSTATUSERABORT, - VCPM_VSTATYIELD -}; - -#define VCPM_PATHCLASS 0x08 -#define VCPM_PATHFIRST 0x0800 -#define VCPM_PATHLAST 0x08ff - -enum { - VCPM_BUILDPATH = VCPM_PATHFIRST, - VCPM_UNIQUEPATH, - VCPM_CHECKPATH -}; - -#define VCPM_PATCHCLASS 0x09 -#define VCPM_PATCHFIRST 0x0900 -#define VCPM_PATCHLAST 0x09ff - -enum { - VCPM_FILEPATCHBEFORECPY = VCPM_PATCHFIRST, - VCPM_FILEPATCHAFTERCPY, - VCPM_FILEPATCHINFOPEN, - VCPM_FILEPATCHINFCLOSE -}; - -#define VCPM_CERTCLASS 0x0a -#define VCPM_CERTFIRST 0x0a00 -#define VCPM_CERTLAST 0x0aff - -enum { - VCPM_FILECERTIFY = VCPM_CERTFIRST, - VCPM_FILECERTIFYWARN -}; - -typedef LRESULT (CALLBACK *VIFPROC)(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, LPARAM lParam, LPARAM lparamRef); - -typedef int (CALLBACK *VCPENUMPROC)(LPVIRTNODE lpvn, LPARAM lparamRef); - -RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef); - -/* VcpQueueCopy flags */ -#define VNLP_SYSCRITICAL 0x0001 -#define VNLP_SETUPCRITICAL 0x0002 -#define VNLP_NOVERCHECK 0x0004 -#define VNLP_FORCETEMP 0x0008 -#define VNLP_IFEXISTS 0x0010 -#define VNLP_KEEPNEWER 0x0020 -#define VNLP_PATCHIFEXIST 0x0040 -#define VNLP_NOPATCH 0x0080 -#define VNLP_CATALOGCERT 0x0100 -#define VNLP_NEEDCERTIFY 0x0200 -#define VNLP_COPYIFEXISTS 0x0400 - -RETERR16 WINAPI VcpQueueCopy16( - LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, - LPCSTR lpszSrcDir, LPCSTR lpszDstDir, - LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, - LPEXPANDVTBL lpExpandVtbl, - WORD fl, LPARAM lParam -); -RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest); -RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest); - -/* VcpExplain flags */ -enum { - VCPEX_SRC_DISK, - VCPEX_SRC_CABINET, - VCPEX_SRC_LOCN, - VCPEX_DST_LOCN, - VCPEX_SRC_FILE, - VCPEX_DST_FILE, - VCPEX_DST_FILE_FINAL, - VCPEX_DOS_ERROR, - VCPEX_MESSAGE, - VCPEX_DOS_SOLUTION, - VCPEX_SRC_FULL, - VCPEX_DST_FULL, - VCPEX_DST_FULL_FINAL -}; - -LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat); - -/****** logical disk management ******/ - -typedef struct _LOGDISKDESC_S { /* ldd */ - WORD cbSize; /* struct size */ - LOGDISKID16 ldid; /* logical disk ID */ - LPSTR pszPath; /* path this descriptor points to */ - LPSTR pszVolLabel; /* volume label of the disk related to it */ - LPSTR pszDiskName; /* name of this disk */ - WORD wVolTime; /* modification time of volume label */ - WORD wVolDate; /* modification date */ - DWORD dwSerNum; /* serial number of disk */ - WORD wFlags; -} LOGDISKDESC_S, *LPLOGDISKDESC; - -/** logical disk identifiers (LDID) **/ - -/* predefined LDIDs */ -#define LDID_PREDEF_START 0x0001 -#define LDID_PREDEF_END 0x7fff - -/* registry-assigned LDIDs */ -#define LDID_VAR_START 0x7000 -#define LDID_VAR_END 0x7fff - -/* dynamically assigned LDIDs */ -#define LDID_ASSIGN_START 0x8000 -#define LDID_ASSIGN_END 0xbfff - -#define LDID_NULL 0 -#define LDID_ABSOLUTE ((UINT)-1) -#define LDID_SRCPATH 1 /* setup source path */ -#define LDID_SETUPTEMP 2 /* setup temp dir */ -#define LDID_UNINSTALL 3 /* uninstall dir */ -#define LDID_BACKUP 4 /* backup dir */ -#define LDID_SETUPSCRATCH 5 /* setup scratch dir */ -#define LDID_WIN 10 /* win dir */ -#define LDID_SYS 11 /* win system dir */ -#define LDID_IOS 12 /* win Iosubsys dir */ -#define LDID_CMD 13 /* win command dir */ -#define LDID_CPL 14 /* win control panel dir */ -#define LDID_PRINT 15 /* win printer dir */ -#define LDID_MAIL 16 /* win mail dir */ -#define LDID_INF 17 /* win inf dir */ -#define LDID_HELP 18 /* win help dir */ -#define LDID_WINADMIN 19 /* admin dir */ -#define LDID_FONTS 20 /* win fonts dir */ -#define LDID_VIEWERS 21 /* win viewers dir */ -#define LDID_VMM32 22 /* win VMM32 dir */ -#define LDID_COLOR 23 /* win color mngment dir */ -#define LDID_APPS 24 /* win apps dir */ -#define LDID_SHARED 25 /* win shared dir */ -#define LDID_WINBOOT 26 /* guaranteed win boot drive */ -#define LDID_MACHINE 27 /* machine specific files */ -#define LDID_HOST_WINBOOT 28 -#define LDID_BOOT 30 /* boot drive root dir */ -#define LDID_BOOT_HOST 31 /* boot drive host root dir */ -#define LDID_OLD_WINBOOT 32 /* root subdir */ -#define LDID_OLD_WIN 33 /* old windows dir */ - -/* flags for GenInstall() */ -#define GENINSTALL_DO_FILES 1 -#define GENINSTALL_DO_INI 2 -#define GENINSTALL_DO_REG 4 -#define GENINSTALL_DO_INI2REG 8 -#define GENINSTALL_DO_CFGAUTO 16 -#define GENINSTALL_DO_LOGCONFIG 32 -#define GENINSTALL_DO_REGSRCPATH 64 -#define GENINSTALL_DO_PERUSER 128 - -#define GEINISTALL_DO_INIREG 14 -#define GENINSTALL_DO_ALL 255 - -/* - * flags for InstallHinfSection() - * 128 can be added, too. This means that the .inf file is provided by you - * instead of being a 32 bit file (i.e. Windows .inf file). - * In this case all files you install must be in the same dir - * as your .inf file on the install disk. - */ -#define HOW_NEVER_REBOOT 0 -#define HOW_ALWAYS_SILENT_REBOOT 1 -#define HOW_ALWAYS_PROMPT_REBOOT 2 -#define HOW_SILENT_REBOOT 3 -#define HOW_PROMPT_REBOOT 4 - -/****** device installation stuff ******/ - -#define MAX_CLASS_NAME_LEN 32 -#define MAX_DEVNODE_ID_LEN 256 -#define MAX_GUID_STR 50 - -typedef struct _DEVICE_INFO -{ - UINT16 cbSize; - struct _DEVICE_INFO *lpNextDi; - char szDescription[LINE_LEN]; - DWORD dnDevnode; - HKEY hRegKey; - char szRegSubkey[MAX_DEVNODE_ID_LEN]; - char szClassName[MAX_CLASS_NAME_LEN]; - DWORD Flags; - HWND16 hwndParent; - /*LPDRIVER_NODE*/ LPVOID lpCompatDrvList; - /*LPDRIVER_NODE*/ LPVOID lpClassDrvList; - /*LPDRIVER_NODE*/ LPVOID lpSelectedDriver; - ATOM atDriverPath; - ATOM atTempInfFile; - HINSTANCE16 hinstClassInstaller; - HINSTANCE16 hinstClassPropProvidor; - HINSTANCE16 hinstDevicePropProvidor; - HINSTANCE16 hinstBasicPropProvidor; - FARPROC16 fpClassInstaller; - FARPROC16 fpClassEnumPropPages; - FARPROC16 fpDeviceEnumPropPages; - FARPROC16 fpEnumBasicProperties; - DWORD dwSetupReserved; - DWORD dwClassInstallReserved; - /*GENCALLBACKPROC*/ LPVOID gicpGenInstallCallBack; - - LPARAM gicplParam; - UINT16 InfType; - - HINSTANCE16 hinstPrivateProblemHandler; - FARPROC16 fpPrivateProblemHandler; - LPARAM lpClassInstallParams; - struct _DEVICE_INFO *lpdiChildList; - DWORD dwFlagsEx; - /*LPDRIVER_INFO*/ LPVOID lpCompatDrvInfoList; - /*LPDRIVER_INFO*/ LPVOID lpClassDrvInfoList; - char szClassGUID[MAX_GUID_STR]; -} DEVICE_INFO16, *LPDEVICE_INFO16, **LPLPDEVICE_INFO16; - - -extern void WINAPI GenFormStrWithoutPlaceHolders16(LPSTR,LPCSTR,HINF16); -extern RETERR16 WINAPI IpOpen16(LPCSTR,HINF16 *); -extern RETERR16 WINAPI IpClose16(HINF16); -extern RETERR16 WINAPI CtlSetLdd16(LPLOGDISKDESC); -extern RETERR16 WINAPI CtlGetLdd16(LPLOGDISKDESC); -extern RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC); -extern RETERR16 WINAPI CtlAddLdd16(LPLOGDISKDESC); -extern RETERR16 WINAPI CtlDelLdd16(LOGDISKID16); -extern RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath); -extern RETERR16 WINAPI GenInstall16(HINF16,LPCSTR,WORD); - -typedef struct tagLDD_LIST { - LPLOGDISKDESC pldd; - struct tagLDD_LIST *next; -} LDD_LIST; - -#define INIT_LDD(ldd, LDID) \ - do { \ - memset(&(ldd), 0, sizeof(LOGDISKDESC_S)); \ - (ldd).cbSize = sizeof(LOGDISKDESC_S); \ - ldd.ldid = LDID; \ - } while(0) - -#endif /* __SETUPX16_H */ +/* + * Copyright 2000 Andreas Mohr for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SETUPX16_H +#define __SETUPX16_H + +#include "wine/windef16.h" + +typedef UINT16 DI_FUNCTION16; +typedef UINT16 HINF16; +typedef UINT16 LOGDISKID16; +typedef UINT16 VHSTR; + +#define LINE_LEN 256 + +/* error codes stuff */ + +typedef UINT16 RETERR16; +#define OK 0 +#define IP_ERROR (UINT16)100 +#define TP_ERROR (UINT16)200 +#define VCP_ERROR (UINT16)300 +#define GEN_ERROR (UINT16)400 +#define DI_ERROR (UINT16)500 + +enum { + ERR_IP_INVALID_FILENAME = IP_ERROR+1, + ERR_IP_ALLOC_ERR, + ERR_IP_INVALID_SECT_NAME, + ERR_IP_OUT_OF_HANDLES, + ERR_IP_INF_NOT_FOUND, + ERR_IP_INVALID_INFFILE, + ERR_IP_INVALID_HINF, + ERR_IP_INVALID_FIELD, + ERR_IP_SECT_NOT_FOUND, + ERR_IP_END_OF_SECTION, + ERR_IP_PROFILE_NOT_FOUND, + ERR_IP_LINE_NOT_FOUND, + ERR_IP_FILEREAD, + ERR_IP_TOOMANYINFFILES, + ERR_IP_INVALID_SAVERESTORE, + ERR_IP_INVALID_INFTYPE +}; + +/****** virtual copy operations ******/ + +typedef DWORD LPEXPANDVTBL; + +typedef struct { + DWORD dwSoFar; + DWORD dwTotal; +} VCPPROGRESS, *LPVCPPROGRESS; + +typedef struct { + WORD cbSize; + LOGDISKID16 ldid; + VHSTR vhstrRoot; + VHSTR vhstrVolumeLabel; + VHSTR vhstrDiskName; + WORD wVolumeTime; + WORD wVolumeDate; + DWORD dwSerialNumber; + WORD fl; + LPARAM lparamRef; + + VCPPROGRESS prgFileRead; + VCPPROGRESS prgByteRead; + + VCPPROGRESS prgFileWrite; + VCPPROGRESS prgByteWrite; +} VCPDISKINFO, *LPVCPDISKINFO; + +typedef struct { + LOGDISKID16 ldid; + VHSTR vhstrDir; + VHSTR vhstrFileName; +} VCPFILESPEC, *LPVCPFILESPEC; + +typedef struct { + UINT16 uiMDate; + UINT16 uiMTime; + UINT16 uiADate; + UINT16 uiATime; + UINT16 uiAttr; + DWORD llenIn; + DWORD llenOut; +} VCPFATTR, *LPVCPFATTR; + +typedef struct { + UINT16 uDate; + UINT16 uTime; + DWORD dwSize; +} VCPFILESTAT, *LPVCPFILESTAT; + +typedef struct +{ + HFILE16 hFileSrc; + HFILE16 hFileDst; + VCPFATTR fAttr; + WORD dosError; + VHSTR vhstrFileName; + WPARAM vcpm; +} VIRTNODEEX, *LPVIRTNODEEX; + +typedef struct { + WORD cbSize; + VCPFILESPEC vfsSrc; + VCPFILESPEC vfsDst; + WORD fl; + LPARAM lParam; + LPEXPANDVTBL lpExpandVtbl; + LPVIRTNODEEX lpvnex; + VHSTR vhstrDstFinalName; + VCPFILESTAT vFileStat; +} VIRTNODE, *LPVIRTNODE; + +typedef struct { + WORD cbSize; + VCPPROGRESS prgDiskRead; + VCPPROGRESS prgFileRead; + VCPPROGRESS prgByteRead; + + VCPPROGRESS prgDiskWrite; + VCPPROGRESS prgFileWrite; + VCPPROGRESS prgByteWrite; + + LPVCPDISKINFO lpvdiIn; + LPVCPDISKINFO lpvdiOut; + LPVIRTNODE lpvn; +} VCPSTATUS, *LPVCPSTATUS; + +#define CNFL_BACKUP 0x0001 +#define CNFL_DELETEONFAILURE 0x0002 +#define CNFL_RENAMEONSUCCESS 0x0004 +#define CNFL_CONTINUATION 0x0008 +#define CNFL_SKIPPED 0x0010 +#define CNFL_IGNOREERRORS 0x0020 +#define CNFL_RETRYFILE 0x0040 +#define CNFL_COPIED 0x0080 +#define VNFL_UNIQUE 0x0000 +#define VNFL_MULTIPLEOK 0x0100 +#define VNFL_DESTROYOLD 0x0200 +#define VNFL_COPY 0x0000 +#define VNFL_DELETE 0x0800 +#define VNFL_RENAME 0x1000 +#define VNFL_NODE_TYPE (VNFL_RENAME|VNFL_DELETE|VNFL_COPY) +#define VNFL_CREATED 0x2000 +#define VNFL_REJECTED 0x4000 +#define VNFL_DEVICEINSTALLER 0x8000 + +enum { + ERR_VCP_IOFAIL = VCP_ERROR+1, + ERR_VCP_STRINGTOOLONG, + ERR_VCP_NOMEM, + ERR_VCP_QUEUEFULL, + ERR_VCP_NOVHSTR, + ERR_VCP_OVERFLOW, + ERR_VCP_BADARG, + ERR_VCP_UNINIT, + ERR_VCP_NOTFOUND, + ERR_VCP_BUSY, + ERR_VCP_INTERRUPTED, + ERR_VCP_BADDEST, + ERR_VCP_SKIPPED, + ERR_VCP_IO, + ERR_VCP_LOCKED, + ERR_VCP_WRONGDISK, + ERR_VCP_CHANGEMODE, + ERR_VCP_LDDINVALID, + ERR_VCP_LDDFIND, + ERR_VCP_LDDUNINIT, + ERR_VCP_LDDPATH_INVALID, + ERR_VCP_NOEXPANSION, + ERR_VCP_NOTOPEN, + ERR_VCP_NO_DIGITAL_SIGNATURE_CATALOG, + ERR_VCP_NO_DIGITAL_SIGNATURE_FILE +}; + +#define VCPN_OK 0 +#define VCPN_PROCEED 0 +#define VCPN_ABORT -1 +#define VCPN_RETRY -2 +#define VCPN_IGNORE -3 +#define VCPN_SKIP -4 +#define VCPN_FORCE -5 +#define VCPN_DEFER -6 +#define VCPN_FAIL -7 +#define VCPN_RETRYFILE -8 + +#define VCPFL_ABANDON 0x00 +#define VCPFL_BACKUP 0x01 +#define VCPFL_COPY 0x02 +#define VCPFL_BACKUPANDCOPY (VCPFL_BACKUP|VCPFL_COPY) +#define VCPFL_INSPECIFIEDORDER 0x04 +#define VCPFL_DELETE 0x08 +#define VCPFL_RENAME 0x10 +#define VCPFL_ALL (VCPFL_COPY|VCPFL_DELETE|VCPFL_RENAME) + +#define CFNL_BACKUP 0x0001 +#define CFNL_DELETEONFAILURE 0x0002 +#define CFNL_RENAMEONSUCCESS 0x0004 +#define CFNL_CONTINUATION 0x0008 +#define CFNL_SKIPPED 0x0010 +#define CFNL_IGNOREERRORS 0x0020 +#define CFNL_RETRYFILE 0x0040 +#define CFNL_COPIED 0x0080 +#define VFNL_MULTIPLEOK 0x0100 +#define VFNL_DESTROYOLD 0x0200 +#define VFNL_NOW 0x0400 +#define VFNL_COPY 0x0000 +#define VFNL_DELETE 0x0800 +#define VFNL_RENAME 0x1000 +#define VFNL_CREATED 0x2000 +#define VFNL_REJECTED 0x4000 +#define VCPM_DISKCLASS 0x01 +#define VCPM_DISKFIRST 0x0100 +#define VCPM_DISKLAST 0x01ff + +enum { + VCPM_DISKCREATEINFO = VCPM_DISKFIRST, + VCPM_DISKGETINFO, + VCPM_DISKDESTROYINFO, + VCPM_DISKPREPINFO, + VCPM_DISKENSURE, + VCPM_DISKPROMPT, + VCPM_DISKFORMATBEGIN, + VCPM_DISKFORMATTING, + VCPM_DISKFORMATEND +}; + +#define VCPM_FILEINCLASS 0x02 +#define VCPM_FILEOUTCLASS 0x03 +#define VCPM_FILEFIRSTIN 0x0200 +#define VCPM_FILEFIRSTOUT 0x0300 +#define VCPM_FILELAST 0x03ff + +enum { + VCPM_FILEOPENIN = VCPM_FILEFIRSTIN, + VCPM_FILEGETFATTR, + VCPM_FILECLOSEIN, + VCPM_FILECOPY, + VCPM_FILENEEDED, + + VCPM_FILEOPENOUT = VCPM_FILEFIRSTOUT, + VCPM_FILESETFATTR, + VCPM_FILECLOSEOUT, + VCPM_FILEFINALIZE, + VCPM_FILEDELETE, + VCPM_FILERENAME +}; + +#define VCPM_NODECLASS 0x04 +#define VCPM_NODEFIRST 0x0400 +#define VCPM_NODELAST 0x04ff + +enum { + VCPM_NODECREATE = VCPM_NODEFIRST, + VCPM_NODEACCEPT, + VCPM_NODEREJECT, + VCPM_NODEDESTROY, + VCPM_NODECHANGEDESTDIR, + VCPM_NODECOMPARE +}; + +#define VCPM_TALLYCLASS 0x05 +#define VCPM_TALLYFIRST 0x0500 +#define VCPM_TALLYLAST 0x05ff + +enum { + VCPM_TALLYSTART = VCPM_TALLYFIRST, + VCPM_TALLYEND, + VCPM_TALLYFILE, + VCPM_TALLYDISK +}; + +#define VCPM_VERCLASS 0x06 +#define VCPM_VERFIRST 0x0600 +#define VCPM_VERLAST 0x06ff + +enum { + VCPM_VERCHECK = VCPM_VERFIRST, + VCPM_VERCHECKDONE, + VCPM_VERRESOLVECONFLICT +}; + +#define VCPM_VSTATCLASS 0x07 +#define VCPM_VSTATFIRST 0x0700 +#define VCPM_VSTATLAST 0x07ff + +enum { + VCPM_VSTATSTART = VCPM_VSTATFIRST, + VCPM_VSTATEND, + VCPM_VSTATREAD, + VCPM_VSTATWRITE, + VCPM_VSTATNEWDISK, + VCPM_VSTATCLOSESTART, + VCPM_VSTATCLOSEEND, + VCPM_VSTATBACKUPSTART, + VCPM_VSTATBACKUPEND, + VCPM_VSTATRENAMESTART, + VCPM_VSTATRENAMEEND, + VCPM_VSTATCOPYSTART, + VCPM_VSTATCOPYEND, + VCPM_VSTATDELETESTART, + VCPM_VSTATDELETEEND, + VCPM_VSTATPATHCHECKSTART, + VCPM_VSTATPATHCHECKEND, + VCPM_VSTATCERTIFYSTART, + VCPM_VSTATCERTIFYEND, + VCPM_VSTATUSERABORT, + VCPM_VSTATYIELD +}; + +#define VCPM_PATHCLASS 0x08 +#define VCPM_PATHFIRST 0x0800 +#define VCPM_PATHLAST 0x08ff + +enum { + VCPM_BUILDPATH = VCPM_PATHFIRST, + VCPM_UNIQUEPATH, + VCPM_CHECKPATH +}; + +#define VCPM_PATCHCLASS 0x09 +#define VCPM_PATCHFIRST 0x0900 +#define VCPM_PATCHLAST 0x09ff + +enum { + VCPM_FILEPATCHBEFORECPY = VCPM_PATCHFIRST, + VCPM_FILEPATCHAFTERCPY, + VCPM_FILEPATCHINFOPEN, + VCPM_FILEPATCHINFCLOSE +}; + +#define VCPM_CERTCLASS 0x0a +#define VCPM_CERTFIRST 0x0a00 +#define VCPM_CERTLAST 0x0aff + +enum { + VCPM_FILECERTIFY = VCPM_CERTFIRST, + VCPM_FILECERTIFYWARN +}; + +typedef LRESULT (CALLBACK *VIFPROC)(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, LPARAM lParam, LPARAM lparamRef); + +typedef int (CALLBACK *VCPENUMPROC)(LPVIRTNODE lpvn, LPARAM lparamRef); + +RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef); + +/* VcpQueueCopy flags */ +#define VNLP_SYSCRITICAL 0x0001 +#define VNLP_SETUPCRITICAL 0x0002 +#define VNLP_NOVERCHECK 0x0004 +#define VNLP_FORCETEMP 0x0008 +#define VNLP_IFEXISTS 0x0010 +#define VNLP_KEEPNEWER 0x0020 +#define VNLP_PATCHIFEXIST 0x0040 +#define VNLP_NOPATCH 0x0080 +#define VNLP_CATALOGCERT 0x0100 +#define VNLP_NEEDCERTIFY 0x0200 +#define VNLP_COPYIFEXISTS 0x0400 + +RETERR16 WINAPI VcpQueueCopy16( + LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, + LPCSTR lpszSrcDir, LPCSTR lpszDstDir, + LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, + LPEXPANDVTBL lpExpandVtbl, + WORD fl, LPARAM lParam +); +RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest); +RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest); + +/* VcpExplain flags */ +enum { + VCPEX_SRC_DISK, + VCPEX_SRC_CABINET, + VCPEX_SRC_LOCN, + VCPEX_DST_LOCN, + VCPEX_SRC_FILE, + VCPEX_DST_FILE, + VCPEX_DST_FILE_FINAL, + VCPEX_DOS_ERROR, + VCPEX_MESSAGE, + VCPEX_DOS_SOLUTION, + VCPEX_SRC_FULL, + VCPEX_DST_FULL, + VCPEX_DST_FULL_FINAL +}; + +LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat); + +/****** logical disk management ******/ + +typedef struct _LOGDISKDESC_S { /* ldd */ + WORD cbSize; /* struct size */ + LOGDISKID16 ldid; /* logical disk ID */ + LPSTR pszPath; /* path this descriptor points to */ + LPSTR pszVolLabel; /* volume label of the disk related to it */ + LPSTR pszDiskName; /* name of this disk */ + WORD wVolTime; /* modification time of volume label */ + WORD wVolDate; /* modification date */ + DWORD dwSerNum; /* serial number of disk */ + WORD wFlags; +} LOGDISKDESC_S, *LPLOGDISKDESC; + +/** logical disk identifiers (LDID) **/ + +/* predefined LDIDs */ +#define LDID_PREDEF_START 0x0001 +#define LDID_PREDEF_END 0x7fff + +/* registry-assigned LDIDs */ +#define LDID_VAR_START 0x7000 +#define LDID_VAR_END 0x7fff + +/* dynamically assigned LDIDs */ +#define LDID_ASSIGN_START 0x8000 +#define LDID_ASSIGN_END 0xbfff + +#define LDID_NULL 0 +#define LDID_ABSOLUTE ((UINT)-1) +#define LDID_SRCPATH 1 /* setup source path */ +#define LDID_SETUPTEMP 2 /* setup temp dir */ +#define LDID_UNINSTALL 3 /* uninstall dir */ +#define LDID_BACKUP 4 /* backup dir */ +#define LDID_SETUPSCRATCH 5 /* setup scratch dir */ +#define LDID_WIN 10 /* win dir */ +#define LDID_SYS 11 /* win system dir */ +#define LDID_IOS 12 /* win Iosubsys dir */ +#define LDID_CMD 13 /* win command dir */ +#define LDID_CPL 14 /* win control panel dir */ +#define LDID_PRINT 15 /* win printer dir */ +#define LDID_MAIL 16 /* win mail dir */ +#define LDID_INF 17 /* win inf dir */ +#define LDID_HELP 18 /* win help dir */ +#define LDID_WINADMIN 19 /* admin dir */ +#define LDID_FONTS 20 /* win fonts dir */ +#define LDID_VIEWERS 21 /* win viewers dir */ +#define LDID_VMM32 22 /* win VMM32 dir */ +#define LDID_COLOR 23 /* win color mngment dir */ +#define LDID_APPS 24 /* win apps dir */ +#define LDID_SHARED 25 /* win shared dir */ +#define LDID_WINBOOT 26 /* guaranteed win boot drive */ +#define LDID_MACHINE 27 /* machine specific files */ +#define LDID_HOST_WINBOOT 28 +#define LDID_BOOT 30 /* boot drive root dir */ +#define LDID_BOOT_HOST 31 /* boot drive host root dir */ +#define LDID_OLD_WINBOOT 32 /* root subdir */ +#define LDID_OLD_WIN 33 /* old windows dir */ + +/* flags for GenInstall() */ +#define GENINSTALL_DO_FILES 1 +#define GENINSTALL_DO_INI 2 +#define GENINSTALL_DO_REG 4 +#define GENINSTALL_DO_INI2REG 8 +#define GENINSTALL_DO_CFGAUTO 16 +#define GENINSTALL_DO_LOGCONFIG 32 +#define GENINSTALL_DO_REGSRCPATH 64 +#define GENINSTALL_DO_PERUSER 128 + +#define GEINISTALL_DO_INIREG 14 +#define GENINSTALL_DO_ALL 255 + +/* + * flags for InstallHinfSection() + * 128 can be added, too. This means that the .inf file is provided by you + * instead of being a 32 bit file (i.e. Windows .inf file). + * In this case all files you install must be in the same dir + * as your .inf file on the install disk. + */ +#define HOW_NEVER_REBOOT 0 +#define HOW_ALWAYS_SILENT_REBOOT 1 +#define HOW_ALWAYS_PROMPT_REBOOT 2 +#define HOW_SILENT_REBOOT 3 +#define HOW_PROMPT_REBOOT 4 + +/****** device installation stuff ******/ + +#define MAX_CLASS_NAME_LEN 32 +#define MAX_DEVNODE_ID_LEN 256 +#define MAX_GUID_STR 50 + +typedef struct _DEVICE_INFO +{ + UINT16 cbSize; + struct _DEVICE_INFO *lpNextDi; + char szDescription[LINE_LEN]; + DWORD dnDevnode; + HKEY hRegKey; + char szRegSubkey[MAX_DEVNODE_ID_LEN]; + char szClassName[MAX_CLASS_NAME_LEN]; + DWORD Flags; + HWND16 hwndParent; + /*LPDRIVER_NODE*/ LPVOID lpCompatDrvList; + /*LPDRIVER_NODE*/ LPVOID lpClassDrvList; + /*LPDRIVER_NODE*/ LPVOID lpSelectedDriver; + ATOM atDriverPath; + ATOM atTempInfFile; + HINSTANCE16 hinstClassInstaller; + HINSTANCE16 hinstClassPropProvidor; + HINSTANCE16 hinstDevicePropProvidor; + HINSTANCE16 hinstBasicPropProvidor; + FARPROC16 fpClassInstaller; + FARPROC16 fpClassEnumPropPages; + FARPROC16 fpDeviceEnumPropPages; + FARPROC16 fpEnumBasicProperties; + DWORD dwSetupReserved; + DWORD dwClassInstallReserved; + /*GENCALLBACKPROC*/ LPVOID gicpGenInstallCallBack; + + LPARAM gicplParam; + UINT16 InfType; + + HINSTANCE16 hinstPrivateProblemHandler; + FARPROC16 fpPrivateProblemHandler; + LPARAM lpClassInstallParams; + struct _DEVICE_INFO *lpdiChildList; + DWORD dwFlagsEx; + /*LPDRIVER_INFO*/ LPVOID lpCompatDrvInfoList; + /*LPDRIVER_INFO*/ LPVOID lpClassDrvInfoList; + char szClassGUID[MAX_GUID_STR]; +} DEVICE_INFO16, *LPDEVICE_INFO16, **LPLPDEVICE_INFO16; + + +extern void WINAPI GenFormStrWithoutPlaceHolders16(LPSTR,LPCSTR,HINF16); +extern RETERR16 WINAPI IpOpen16(LPCSTR,HINF16 *); +extern RETERR16 WINAPI IpClose16(HINF16); +extern RETERR16 WINAPI CtlSetLdd16(LPLOGDISKDESC); +extern RETERR16 WINAPI CtlGetLdd16(LPLOGDISKDESC); +extern RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC); +extern RETERR16 WINAPI CtlAddLdd16(LPLOGDISKDESC); +extern RETERR16 WINAPI CtlDelLdd16(LOGDISKID16); +extern RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath); +extern RETERR16 WINAPI GenInstall16(HINF16,LPCSTR,WORD); + +typedef struct tagLDD_LIST { + LPLOGDISKDESC pldd; + struct tagLDD_LIST *next; +} LDD_LIST; + +#define INIT_LDD(ldd, LDID) \ + do { \ + memset(&(ldd), 0, sizeof(LOGDISKDESC_S)); \ + (ldd).cbSize = sizeof(LOGDISKDESC_S); \ + ldd.ldid = LDID; \ + } while(0) + +#endif /* __SETUPX16_H */ diff --git a/reactos/lib/setupapi/setupx_main.c b/reactos/lib/setupapi/setupx_main.c index df1a5daadc0..8610ce0a55f 100644 --- a/reactos/lib/setupapi/setupx_main.c +++ b/reactos/lib/setupapi/setupx_main.c @@ -1,615 +1,615 @@ -/* - * SETUPX library - * - * Copyright 1998,2000 Andreas Mohr - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * FIXME: Rather non-functional functions for now. - * - * See: - * http://www.geocities.com/SiliconValley/Network/5317/drivers.html - * http://willemer.de/informatik/windows/inf_info.htm (German) - * http://www.microsoft.com/ddk/ddkdocs/win98ddk/devinst_12uw.htm - * DDK: setupx.h - * http://mmatrix.tripod.com/customsystemfolder/infsysntaxfull.html - * http://www.rdrop.com/~cary/html/inf_faq.html - * http://support.microsoft.com/support/kb/articles/q194/6/40.asp - * - * Stuff tested with: - * - rs405deu.exe (German Acroread 4.05 setup) - * - ie5setup.exe - * - Netmeeting - * - * FIXME: - * - string handling is... weird ;) (buflen etc.) - * - memory leaks ? - * - separate that mess (but probably only when it's done completely) - * - * SETUPX consists of several parts with the following acronyms/prefixes: - * Di device installer (devinst.c ?) - * Gen generic installer (geninst.c ?) - * Ip .INF parsing (infparse.c) - * LDD logical device descriptor (ldd.c ?) - * LDID logical device ID - * SU setup (setup.c ?) - * Tp text processing (textproc.c ?) - * Vcp virtual copy module (vcp.c ?) - * ... - * - * The SETUPX DLL is NOT thread-safe. That's why many installers urge you to - * "close all open applications". - * All in all the design of it seems to be a bit weak. - * Not sure whether my implementation of it is better, though ;-) - */ - -#include -#include -#include -#include -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winerror.h" -#include "wine/winuser16.h" -#include "wownt32.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "setupapi.h" -#include "setupx16.h" -#include "setupapi_private.h" -#include "winerror.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -#define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16)) - -/*********************************************************************** - * SURegOpenKey (SETUPX.47) - */ -DWORD WINAPI SURegOpenKey( HKEY hkey, LPCSTR lpszSubKey, PHKEY retkey ) -{ - FIXME("(%p,%s,%p), semi-stub.\n",hkey,debugstr_a(lpszSubKey),retkey); - return RegOpenKeyA( hkey, lpszSubKey, retkey ); -} - -/*********************************************************************** - * SURegQueryValueEx (SETUPX.50) - */ -DWORD WINAPI SURegQueryValueEx( HKEY hkey, LPSTR lpszValueName, - LPDWORD lpdwReserved, LPDWORD lpdwType, - LPBYTE lpbData, LPDWORD lpcbData ) -{ - FIXME("(%p,%s,%p,%p,%p,%ld), semi-stub.\n",hkey,debugstr_a(lpszValueName), - lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0); - return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType, - lpbData, lpcbData ); -} - - -/*********************************************************************** - * InstallHinfSection (SETUPX.527) - * - * hwnd = parent window - * hinst = instance of SETUPX.DLL - * lpszCmdLine = e.g. "DefaultInstall 132 C:\MYINSTALL\MYDEV.INF" - * Here "DefaultInstall" is the .inf file section to be installed (optional). - * The 132 value is made of the HOW_xxx flags and sometimes 128 (-> setupx16.h). - * - * nCmdShow = nCmdShow of CreateProcess - */ -RETERR16 WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lpszCmdLine, INT16 nCmdShow) -{ - InstallHinfSectionA( HWND_32(hwnd), HINSTANCE_32(hinst), lpszCmdLine, nCmdShow ); - return OK; -} - -typedef struct -{ - LPCSTR RegValName; - LPCSTR StdString; /* fallback string; sub dir of windows directory */ -} LDID_DATA; - -static const LDID_DATA LDID_Data[34] = -{ - { /* 0 (LDID_NULL) -- not defined */ - NULL, - NULL - }, - { /* 1 (LDID_SRCPATH) = source of installation. hmm, what to do here ? */ - "SourcePath", /* hmm, does SETUPX have to care about updating it ?? */ - NULL - }, - { /* 2 (LDID_SETUPTEMP) = setup temp dir */ - "SetupTempDir", - NULL - }, - { /* 3 (LDID_UNINSTALL) = uninstall backup dir */ - "UninstallDir", - NULL - }, - { /* 4 (LDID_BACKUP) = backup dir */ - "BackupDir", - NULL - }, - { /* 5 (LDID_SETUPSCRATCH) = setup scratch dir */ - "SetupScratchDir", - NULL - }, - { /* 6 -- not defined */ - NULL, - NULL - }, - { /* 7 -- not defined */ - NULL, - NULL - }, - { /* 8 -- not defined */ - NULL, - NULL - }, - { /* 9 -- not defined */ - NULL, - NULL - }, - { /* 10 (LDID_WIN) = windows dir */ - "WinDir", - "" - }, - { /* 11 (LDID_SYS) = system dir */ - "SysDir", - NULL /* call GetSystemDirectory() instead */ - }, - { /* 12 (LDID_IOS) = IOSubSys dir */ - NULL, /* FIXME: registry string ? */ - "SYSTEM\\IOSUBSYS" - }, - { /* 13 (LDID_CMD) = COMMAND dir */ - NULL, /* FIXME: registry string ? */ - "COMMAND" - }, - { /* 14 (LDID_CPL) = control panel dir */ - NULL, - "" - }, - { /* 15 (LDID_PRINT) = windows printer dir */ - NULL, - "SYSTEM" /* correct ?? */ - }, - { /* 16 (LDID_MAIL) = destination mail dir */ - NULL, - "" - }, - { /* 17 (LDID_INF) = INF dir */ - "SetupScratchDir", /* correct ? */ - "INF" - }, - { /* 18 (LDID_HELP) = HELP dir */ - NULL, /* ??? */ - "HELP" - }, - { /* 19 (LDID_WINADMIN) = Admin dir */ - "WinAdminDir", - "" - }, - { /* 20 (LDID_FONTS) = Fonts dir */ - NULL, /* ??? */ - "FONTS" - }, - { /* 21 (LDID_VIEWERS) = Viewers */ - NULL, /* ??? */ - "SYSTEM\\VIEWERS" - }, - { /* 22 (LDID_VMM32) = VMM32 dir */ - NULL, /* ??? */ - "SYSTEM\\VMM32" - }, - { /* 23 (LDID_COLOR) = ICM dir */ - "ICMPath", - "SYSTEM\\COLOR" - }, - { /* 24 (LDID_APPS) = root of boot drive ? */ - "AppsDir", - "C:\\" - }, - { /* 25 (LDID_SHARED) = shared dir */ - "SharedDir", - "" - }, - { /* 26 (LDID_WINBOOT) = Windows boot dir */ - "WinBootDir", - "" - }, - { /* 27 (LDID_MACHINE) = machine specific files */ - "MachineDir", - NULL - }, - { /* 28 (LDID_HOST_WINBOOT) = Host Windows boot dir */ - "HostWinBootDir", - NULL - }, - { /* 29 -- not defined */ - NULL, - NULL - }, - { /* 30 (LDID_BOOT) = Root of boot drive */ - "BootDir", - NULL - }, - { /* 31 (LDID_BOOT_HOST) = Root of boot drive host */ - "BootHost", - NULL - }, - { /* 32 (LDID_OLD_WINBOOT) = subdir of root */ - "OldWinBootDir", - NULL - }, - { /* 33 (LDID_OLD_WIN) = old win dir */ - "OldWinDir", - NULL - } - /* the rest (34-38) isn't too interesting, so I'll forget about it */ -}; - -/* - * LDD == Logical Device Descriptor - * LDID == Logical Device ID - * - * The whole LDD/LDID business might go into a separate file named - * ldd.c. - * At the moment I don't know what the hell these functions are really doing. - * That's why I added reporting stubs. - * The only thing I do know is that I need them for the LDD/LDID infrastructure. - * That's why I implemented them in a way that's suitable for my purpose. - */ -static LDD_LIST *pFirstLDD = NULL; - -static BOOL std_LDDs_done = FALSE; - -void SETUPX_CreateStandardLDDs(void) -{ - HKEY hKey = 0; - WORD n; - DWORD type, len; - LOGDISKDESC_S ldd; - char buffer[MAX_PATH]; - - /* has to be here, otherwise loop */ - std_LDDs_done = TRUE; - - RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", &hKey); - - for (n=0; n < sizeof(LDID_Data)/sizeof(LDID_DATA); n++) - { - buffer[0] = '\0'; - - len = MAX_PATH; - if ( (hKey) && (LDID_Data[n].RegValName) - && (RegQueryValueExA(hKey, LDID_Data[n].RegValName, - NULL, &type, buffer, &len) == ERROR_SUCCESS) - && (type == REG_SZ) ) - { - TRACE("found value '%s' for LDID %d\n", buffer, n); - } - else - switch(n) - { - case LDID_SRCPATH: - FIXME("LDID_SRCPATH: what exactly do we have to do here ?\n"); - strcpy(buffer, "X:\\FIXME"); - break; - case LDID_SYS: - GetSystemDirectoryA(buffer, MAX_PATH); - break; - case LDID_APPS: - case LDID_MACHINE: - case LDID_HOST_WINBOOT: - case LDID_BOOT: - case LDID_BOOT_HOST: - strcpy(buffer, "C:\\"); - break; - default: - if (LDID_Data[n].StdString) - { - DWORD len = GetWindowsDirectoryA(buffer, MAX_PATH); - LPSTR p; - p = buffer + len; - *p++ = '\\'; - strcpy(p, LDID_Data[n].StdString); - } - break; - } - if (buffer[0]) - { - INIT_LDD(ldd, n); - ldd.pszPath = buffer; - TRACE("LDID %d -> '%s'\n", ldd.ldid, ldd.pszPath); - CtlSetLdd16(&ldd); - } - } - if (hKey) RegCloseKey(hKey); -} - -/*********************************************************************** - * CtlDelLdd (SETUPX.37) - * - * RETURN - * ERR_VCP_LDDINVALID if ldid < LDID_ASSIGN_START. - */ -RETERR16 SETUPX_DelLdd(LOGDISKID16 ldid) -{ - LDD_LIST *pCurr, *pPrev = NULL; - - TRACE("(%d)\n", ldid); - - if (!std_LDDs_done) - SETUPX_CreateStandardLDDs(); - - if (ldid < LDID_ASSIGN_START) - return ERR_VCP_LDDINVALID; - - pCurr = pFirstLDD; - /* search until we find the appropriate LDD or hit the end */ - while ((pCurr != NULL) && (ldid > pCurr->pldd->ldid)) - { - pPrev = pCurr; - pCurr = pCurr->next; - } - if ( (pCurr == NULL) /* hit end of list */ - || (ldid != pCurr->pldd->ldid) ) - return ERR_VCP_LDDFIND; /* correct ? */ - - /* ok, found our victim: eliminate it */ - - if (pPrev) - pPrev->next = pCurr->next; - - if (pCurr == pFirstLDD) - pFirstLDD = NULL; - HeapFree(GetProcessHeap(), 0, pCurr); - - return OK; -} - -/*********************************************************************** - * CtlDelLdd (SETUPX.37) - */ -RETERR16 WINAPI CtlDelLdd16(LOGDISKID16 ldid) -{ - FIXME("(%d); - please report this!\n", ldid); - return SETUPX_DelLdd(ldid); -} - -/*********************************************************************** - * CtlFindLdd (SETUPX.35) - * - * doesn't check pldd ptr validity: crash (W98SE) - * - * RETURN - * ERR_VCP_LDDINVALID if pldd->cbSize != structsize - * 1 in all other cases ?? - * - */ -RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC pldd) -{ - LDD_LIST *pCurr, *pPrev = NULL; - - TRACE("(%p)\n", pldd); - - if (!std_LDDs_done) - SETUPX_CreateStandardLDDs(); - - if (pldd->cbSize != sizeof(LOGDISKDESC_S)) - return ERR_VCP_LDDINVALID; - - pCurr = pFirstLDD; - /* search until we find the appropriate LDD or hit the end */ - while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid)) - { - pPrev = pCurr; - pCurr = pCurr->next; - } - if ( (pCurr == NULL) /* hit end of list */ - || (pldd->ldid != pCurr->pldd->ldid) ) - return ERR_VCP_LDDFIND; /* correct ? */ - - memcpy(pldd, pCurr->pldd, pldd->cbSize); - /* hmm, we probably ought to strcpy() the string ptrs here */ - - return 1; /* what is this ?? */ -} - -/*********************************************************************** - * CtlSetLdd (SETUPX.33) - * - * Set an LDD entry. - * - * RETURN - * ERR_VCP_LDDINVALID if pldd.cbSize != sizeof(LOGDISKDESC_S) - * - */ -RETERR16 WINAPI CtlSetLdd16(LPLOGDISKDESC pldd) -{ - LDD_LIST *pCurr, *pPrev = NULL; - LPLOGDISKDESC pCurrLDD; - HANDLE heap; - BOOL is_new = FALSE; - - TRACE("(%p)\n", pldd); - - if (!std_LDDs_done) - SETUPX_CreateStandardLDDs(); - - if (pldd->cbSize != sizeof(LOGDISKDESC_S)) - return ERR_VCP_LDDINVALID; - - heap = GetProcessHeap(); - pCurr = pFirstLDD; - /* search until we find the appropriate LDD or hit the end */ - while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid)) - { - pPrev = pCurr; - pCurr = pCurr->next; - } - if (!pCurr || pldd->ldid != pCurr->pldd->ldid) - { - is_new = TRUE; - pCurr = HeapAlloc(heap, 0, sizeof(LDD_LIST)); - pCurr->pldd = HeapAlloc(heap, 0, sizeof(LOGDISKDESC_S)); - pCurr->next = NULL; - pCurrLDD = pCurr->pldd; - } - else - { - pCurrLDD = pCurr->pldd; - HeapFree(heap, 0, pCurrLDD->pszPath); - HeapFree(heap, 0, pCurrLDD->pszVolLabel); - HeapFree(heap, 0, pCurrLDD->pszDiskName); - } - - memcpy(pCurrLDD, pldd, sizeof(LOGDISKDESC_S)); - - if (pldd->pszPath) - { - pCurrLDD->pszPath = HeapAlloc( heap, 0, strlen(pldd->pszPath)+1 ); - strcpy( pCurrLDD->pszPath, pldd->pszPath ); - } - if (pldd->pszVolLabel) - { - pCurrLDD->pszVolLabel = HeapAlloc( heap, 0, strlen(pldd->pszVolLabel)+1 ); - strcpy( pCurrLDD->pszVolLabel, pldd->pszVolLabel ); - } - if (pldd->pszDiskName) - { - pCurrLDD->pszDiskName = HeapAlloc( heap, 0, strlen(pldd->pszDiskName)+1 ); - strcpy( pCurrLDD->pszDiskName, pldd->pszDiskName ); - } - - if (is_new) /* link into list */ - { - if (pPrev) - { - pCurr->next = pPrev->next; - pPrev->next = pCurr; - } - if (!pFirstLDD) - pFirstLDD = pCurr; - } - - return OK; -} - - -/*********************************************************************** - * CtlAddLdd (SETUPX.36) - * - * doesn't check pldd ptr validity: crash (W98SE) - * - */ -static LOGDISKID16 ldid_to_add = LDID_ASSIGN_START; -RETERR16 WINAPI CtlAddLdd16(LPLOGDISKDESC pldd) -{ - pldd->ldid = ldid_to_add++; - return CtlSetLdd16(pldd); -} - -/*********************************************************************** - * CtlGetLdd (SETUPX.34) - * - * doesn't check pldd ptr validity: crash (W98SE) - * What the !@#$%&*( is the difference between CtlFindLdd() and CtlGetLdd() ?? - * - * RETURN - * ERR_VCP_LDDINVALID if pldd->cbSize != structsize - * - */ -static RETERR16 SETUPX_GetLdd(LPLOGDISKDESC pldd) -{ - LDD_LIST *pCurr, *pPrev = NULL; - - if (!std_LDDs_done) - SETUPX_CreateStandardLDDs(); - - if (pldd->cbSize != sizeof(LOGDISKDESC_S)) - return ERR_VCP_LDDINVALID; - - pCurr = pFirstLDD; - /* search until we find the appropriate LDD or hit the end */ - while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid)) - { - pPrev = pCurr; - pCurr = pCurr->next; - } - if (pCurr == NULL) /* hit end of list */ - return ERR_VCP_LDDFIND; /* correct ? */ - - memcpy(pldd, pCurr->pldd, pldd->cbSize); - /* hmm, we probably ought to strcpy() the string ptrs here */ - - return OK; -} - -/**********************************************************************/ - -RETERR16 WINAPI CtlGetLdd16(LPLOGDISKDESC pldd) -{ - FIXME("(%p); - please report this!\n", pldd); - return SETUPX_GetLdd(pldd); -} - -/*********************************************************************** - * CtlGetLddPath (SETUPX.38) - * - * Gets the path of an LDD. - * No crash if szPath == NULL. - * szPath has to be at least MAX_PATH_LEN bytes long. - * RETURN - * ERR_VCP_LDDUNINIT if LDD for LDID not found. - */ -RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath) -{ - TRACE("(%d, %p);\n", ldid, szPath); - - if (szPath) - { - LOGDISKDESC_S ldd; - INIT_LDD(ldd, ldid); - if (CtlFindLdd16(&ldd) == ERR_VCP_LDDFIND) - return ERR_VCP_LDDUNINIT; - SETUPX_GetLdd(&ldd); - strcpy(szPath, ldd.pszPath); - TRACE("ret '%s' for LDID %d\n", szPath, ldid); - } - return OK; -} - -/*********************************************************************** - * CtlSetLddPath (SETUPX.508) - * - * Sets the path of an LDD. - * Creates LDD for LDID if not existing yet. - */ -RETERR16 WINAPI CtlSetLddPath16(LOGDISKID16 ldid, LPSTR szPath) -{ - LOGDISKDESC_S ldd; - TRACE("(%d, '%s');\n", ldid, szPath); - - SetupSetDirectoryIdA( 0, ldid, szPath ); - INIT_LDD(ldd, ldid); - ldd.pszPath = szPath; - return CtlSetLdd16(&ldd); -} +/* + * SETUPX library + * + * Copyright 1998,2000 Andreas Mohr + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FIXME: Rather non-functional functions for now. + * + * See: + * http://www.geocities.com/SiliconValley/Network/5317/drivers.html + * http://willemer.de/informatik/windows/inf_info.htm (German) + * http://www.microsoft.com/ddk/ddkdocs/win98ddk/devinst_12uw.htm + * DDK: setupx.h + * http://mmatrix.tripod.com/customsystemfolder/infsysntaxfull.html + * http://www.rdrop.com/~cary/html/inf_faq.html + * http://support.microsoft.com/support/kb/articles/q194/6/40.asp + * + * Stuff tested with: + * - rs405deu.exe (German Acroread 4.05 setup) + * - ie5setup.exe + * - Netmeeting + * + * FIXME: + * - string handling is... weird ;) (buflen etc.) + * - memory leaks ? + * - separate that mess (but probably only when it's done completely) + * + * SETUPX consists of several parts with the following acronyms/prefixes: + * Di device installer (devinst.c ?) + * Gen generic installer (geninst.c ?) + * Ip .INF parsing (infparse.c) + * LDD logical device descriptor (ldd.c ?) + * LDID logical device ID + * SU setup (setup.c ?) + * Tp text processing (textproc.c ?) + * Vcp virtual copy module (vcp.c ?) + * ... + * + * The SETUPX DLL is NOT thread-safe. That's why many installers urge you to + * "close all open applications". + * All in all the design of it seems to be a bit weak. + * Not sure whether my implementation of it is better, though ;-) + */ + +#include +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winerror.h" +#include "wine/winuser16.h" +#include "wownt32.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "setupapi.h" +#include "setupx16.h" +#include "setupapi_private.h" +#include "winerror.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +#define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16)) + +/*********************************************************************** + * SURegOpenKey (SETUPX.47) + */ +DWORD WINAPI SURegOpenKey( HKEY hkey, LPCSTR lpszSubKey, PHKEY retkey ) +{ + FIXME("(%p,%s,%p), semi-stub.\n",hkey,debugstr_a(lpszSubKey),retkey); + return RegOpenKeyA( hkey, lpszSubKey, retkey ); +} + +/*********************************************************************** + * SURegQueryValueEx (SETUPX.50) + */ +DWORD WINAPI SURegQueryValueEx( HKEY hkey, LPSTR lpszValueName, + LPDWORD lpdwReserved, LPDWORD lpdwType, + LPBYTE lpbData, LPDWORD lpcbData ) +{ + FIXME("(%p,%s,%p,%p,%p,%ld), semi-stub.\n",hkey,debugstr_a(lpszValueName), + lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0); + return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType, + lpbData, lpcbData ); +} + + +/*********************************************************************** + * InstallHinfSection (SETUPX.527) + * + * hwnd = parent window + * hinst = instance of SETUPX.DLL + * lpszCmdLine = e.g. "DefaultInstall 132 C:\MYINSTALL\MYDEV.INF" + * Here "DefaultInstall" is the .inf file section to be installed (optional). + * The 132 value is made of the HOW_xxx flags and sometimes 128 (-> setupx16.h). + * + * nCmdShow = nCmdShow of CreateProcess + */ +RETERR16 WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lpszCmdLine, INT16 nCmdShow) +{ + InstallHinfSectionA( HWND_32(hwnd), HINSTANCE_32(hinst), lpszCmdLine, nCmdShow ); + return OK; +} + +typedef struct +{ + LPCSTR RegValName; + LPCSTR StdString; /* fallback string; sub dir of windows directory */ +} LDID_DATA; + +static const LDID_DATA LDID_Data[34] = +{ + { /* 0 (LDID_NULL) -- not defined */ + NULL, + NULL + }, + { /* 1 (LDID_SRCPATH) = source of installation. hmm, what to do here ? */ + "SourcePath", /* hmm, does SETUPX have to care about updating it ?? */ + NULL + }, + { /* 2 (LDID_SETUPTEMP) = setup temp dir */ + "SetupTempDir", + NULL + }, + { /* 3 (LDID_UNINSTALL) = uninstall backup dir */ + "UninstallDir", + NULL + }, + { /* 4 (LDID_BACKUP) = backup dir */ + "BackupDir", + NULL + }, + { /* 5 (LDID_SETUPSCRATCH) = setup scratch dir */ + "SetupScratchDir", + NULL + }, + { /* 6 -- not defined */ + NULL, + NULL + }, + { /* 7 -- not defined */ + NULL, + NULL + }, + { /* 8 -- not defined */ + NULL, + NULL + }, + { /* 9 -- not defined */ + NULL, + NULL + }, + { /* 10 (LDID_WIN) = windows dir */ + "WinDir", + "" + }, + { /* 11 (LDID_SYS) = system dir */ + "SysDir", + NULL /* call GetSystemDirectory() instead */ + }, + { /* 12 (LDID_IOS) = IOSubSys dir */ + NULL, /* FIXME: registry string ? */ + "SYSTEM\\IOSUBSYS" + }, + { /* 13 (LDID_CMD) = COMMAND dir */ + NULL, /* FIXME: registry string ? */ + "COMMAND" + }, + { /* 14 (LDID_CPL) = control panel dir */ + NULL, + "" + }, + { /* 15 (LDID_PRINT) = windows printer dir */ + NULL, + "SYSTEM" /* correct ?? */ + }, + { /* 16 (LDID_MAIL) = destination mail dir */ + NULL, + "" + }, + { /* 17 (LDID_INF) = INF dir */ + "SetupScratchDir", /* correct ? */ + "INF" + }, + { /* 18 (LDID_HELP) = HELP dir */ + NULL, /* ??? */ + "HELP" + }, + { /* 19 (LDID_WINADMIN) = Admin dir */ + "WinAdminDir", + "" + }, + { /* 20 (LDID_FONTS) = Fonts dir */ + NULL, /* ??? */ + "FONTS" + }, + { /* 21 (LDID_VIEWERS) = Viewers */ + NULL, /* ??? */ + "SYSTEM\\VIEWERS" + }, + { /* 22 (LDID_VMM32) = VMM32 dir */ + NULL, /* ??? */ + "SYSTEM\\VMM32" + }, + { /* 23 (LDID_COLOR) = ICM dir */ + "ICMPath", + "SYSTEM\\COLOR" + }, + { /* 24 (LDID_APPS) = root of boot drive ? */ + "AppsDir", + "C:\\" + }, + { /* 25 (LDID_SHARED) = shared dir */ + "SharedDir", + "" + }, + { /* 26 (LDID_WINBOOT) = Windows boot dir */ + "WinBootDir", + "" + }, + { /* 27 (LDID_MACHINE) = machine specific files */ + "MachineDir", + NULL + }, + { /* 28 (LDID_HOST_WINBOOT) = Host Windows boot dir */ + "HostWinBootDir", + NULL + }, + { /* 29 -- not defined */ + NULL, + NULL + }, + { /* 30 (LDID_BOOT) = Root of boot drive */ + "BootDir", + NULL + }, + { /* 31 (LDID_BOOT_HOST) = Root of boot drive host */ + "BootHost", + NULL + }, + { /* 32 (LDID_OLD_WINBOOT) = subdir of root */ + "OldWinBootDir", + NULL + }, + { /* 33 (LDID_OLD_WIN) = old win dir */ + "OldWinDir", + NULL + } + /* the rest (34-38) isn't too interesting, so I'll forget about it */ +}; + +/* + * LDD == Logical Device Descriptor + * LDID == Logical Device ID + * + * The whole LDD/LDID business might go into a separate file named + * ldd.c. + * At the moment I don't know what the hell these functions are really doing. + * That's why I added reporting stubs. + * The only thing I do know is that I need them for the LDD/LDID infrastructure. + * That's why I implemented them in a way that's suitable for my purpose. + */ +static LDD_LIST *pFirstLDD = NULL; + +static BOOL std_LDDs_done = FALSE; + +void SETUPX_CreateStandardLDDs(void) +{ + HKEY hKey = 0; + WORD n; + DWORD type, len; + LOGDISKDESC_S ldd; + char buffer[MAX_PATH]; + + /* has to be here, otherwise loop */ + std_LDDs_done = TRUE; + + RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", &hKey); + + for (n=0; n < sizeof(LDID_Data)/sizeof(LDID_DATA); n++) + { + buffer[0] = '\0'; + + len = MAX_PATH; + if ( (hKey) && (LDID_Data[n].RegValName) + && (RegQueryValueExA(hKey, LDID_Data[n].RegValName, + NULL, &type, buffer, &len) == ERROR_SUCCESS) + && (type == REG_SZ) ) + { + TRACE("found value '%s' for LDID %d\n", buffer, n); + } + else + switch(n) + { + case LDID_SRCPATH: + FIXME("LDID_SRCPATH: what exactly do we have to do here ?\n"); + strcpy(buffer, "X:\\FIXME"); + break; + case LDID_SYS: + GetSystemDirectoryA(buffer, MAX_PATH); + break; + case LDID_APPS: + case LDID_MACHINE: + case LDID_HOST_WINBOOT: + case LDID_BOOT: + case LDID_BOOT_HOST: + strcpy(buffer, "C:\\"); + break; + default: + if (LDID_Data[n].StdString) + { + DWORD len = GetWindowsDirectoryA(buffer, MAX_PATH); + LPSTR p; + p = buffer + len; + *p++ = '\\'; + strcpy(p, LDID_Data[n].StdString); + } + break; + } + if (buffer[0]) + { + INIT_LDD(ldd, n); + ldd.pszPath = buffer; + TRACE("LDID %d -> '%s'\n", ldd.ldid, ldd.pszPath); + CtlSetLdd16(&ldd); + } + } + if (hKey) RegCloseKey(hKey); +} + +/*********************************************************************** + * CtlDelLdd (SETUPX.37) + * + * RETURN + * ERR_VCP_LDDINVALID if ldid < LDID_ASSIGN_START. + */ +RETERR16 SETUPX_DelLdd(LOGDISKID16 ldid) +{ + LDD_LIST *pCurr, *pPrev = NULL; + + TRACE("(%d)\n", ldid); + + if (!std_LDDs_done) + SETUPX_CreateStandardLDDs(); + + if (ldid < LDID_ASSIGN_START) + return ERR_VCP_LDDINVALID; + + pCurr = pFirstLDD; + /* search until we find the appropriate LDD or hit the end */ + while ((pCurr != NULL) && (ldid > pCurr->pldd->ldid)) + { + pPrev = pCurr; + pCurr = pCurr->next; + } + if ( (pCurr == NULL) /* hit end of list */ + || (ldid != pCurr->pldd->ldid) ) + return ERR_VCP_LDDFIND; /* correct ? */ + + /* ok, found our victim: eliminate it */ + + if (pPrev) + pPrev->next = pCurr->next; + + if (pCurr == pFirstLDD) + pFirstLDD = NULL; + HeapFree(GetProcessHeap(), 0, pCurr); + + return OK; +} + +/*********************************************************************** + * CtlDelLdd (SETUPX.37) + */ +RETERR16 WINAPI CtlDelLdd16(LOGDISKID16 ldid) +{ + FIXME("(%d); - please report this!\n", ldid); + return SETUPX_DelLdd(ldid); +} + +/*********************************************************************** + * CtlFindLdd (SETUPX.35) + * + * doesn't check pldd ptr validity: crash (W98SE) + * + * RETURN + * ERR_VCP_LDDINVALID if pldd->cbSize != structsize + * 1 in all other cases ?? + * + */ +RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC pldd) +{ + LDD_LIST *pCurr, *pPrev = NULL; + + TRACE("(%p)\n", pldd); + + if (!std_LDDs_done) + SETUPX_CreateStandardLDDs(); + + if (pldd->cbSize != sizeof(LOGDISKDESC_S)) + return ERR_VCP_LDDINVALID; + + pCurr = pFirstLDD; + /* search until we find the appropriate LDD or hit the end */ + while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid)) + { + pPrev = pCurr; + pCurr = pCurr->next; + } + if ( (pCurr == NULL) /* hit end of list */ + || (pldd->ldid != pCurr->pldd->ldid) ) + return ERR_VCP_LDDFIND; /* correct ? */ + + memcpy(pldd, pCurr->pldd, pldd->cbSize); + /* hmm, we probably ought to strcpy() the string ptrs here */ + + return 1; /* what is this ?? */ +} + +/*********************************************************************** + * CtlSetLdd (SETUPX.33) + * + * Set an LDD entry. + * + * RETURN + * ERR_VCP_LDDINVALID if pldd.cbSize != sizeof(LOGDISKDESC_S) + * + */ +RETERR16 WINAPI CtlSetLdd16(LPLOGDISKDESC pldd) +{ + LDD_LIST *pCurr, *pPrev = NULL; + LPLOGDISKDESC pCurrLDD; + HANDLE heap; + BOOL is_new = FALSE; + + TRACE("(%p)\n", pldd); + + if (!std_LDDs_done) + SETUPX_CreateStandardLDDs(); + + if (pldd->cbSize != sizeof(LOGDISKDESC_S)) + return ERR_VCP_LDDINVALID; + + heap = GetProcessHeap(); + pCurr = pFirstLDD; + /* search until we find the appropriate LDD or hit the end */ + while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid)) + { + pPrev = pCurr; + pCurr = pCurr->next; + } + if (!pCurr || pldd->ldid != pCurr->pldd->ldid) + { + is_new = TRUE; + pCurr = HeapAlloc(heap, 0, sizeof(LDD_LIST)); + pCurr->pldd = HeapAlloc(heap, 0, sizeof(LOGDISKDESC_S)); + pCurr->next = NULL; + pCurrLDD = pCurr->pldd; + } + else + { + pCurrLDD = pCurr->pldd; + HeapFree(heap, 0, pCurrLDD->pszPath); + HeapFree(heap, 0, pCurrLDD->pszVolLabel); + HeapFree(heap, 0, pCurrLDD->pszDiskName); + } + + memcpy(pCurrLDD, pldd, sizeof(LOGDISKDESC_S)); + + if (pldd->pszPath) + { + pCurrLDD->pszPath = HeapAlloc( heap, 0, strlen(pldd->pszPath)+1 ); + strcpy( pCurrLDD->pszPath, pldd->pszPath ); + } + if (pldd->pszVolLabel) + { + pCurrLDD->pszVolLabel = HeapAlloc( heap, 0, strlen(pldd->pszVolLabel)+1 ); + strcpy( pCurrLDD->pszVolLabel, pldd->pszVolLabel ); + } + if (pldd->pszDiskName) + { + pCurrLDD->pszDiskName = HeapAlloc( heap, 0, strlen(pldd->pszDiskName)+1 ); + strcpy( pCurrLDD->pszDiskName, pldd->pszDiskName ); + } + + if (is_new) /* link into list */ + { + if (pPrev) + { + pCurr->next = pPrev->next; + pPrev->next = pCurr; + } + if (!pFirstLDD) + pFirstLDD = pCurr; + } + + return OK; +} + + +/*********************************************************************** + * CtlAddLdd (SETUPX.36) + * + * doesn't check pldd ptr validity: crash (W98SE) + * + */ +static LOGDISKID16 ldid_to_add = LDID_ASSIGN_START; +RETERR16 WINAPI CtlAddLdd16(LPLOGDISKDESC pldd) +{ + pldd->ldid = ldid_to_add++; + return CtlSetLdd16(pldd); +} + +/*********************************************************************** + * CtlGetLdd (SETUPX.34) + * + * doesn't check pldd ptr validity: crash (W98SE) + * What the !@#$%&*( is the difference between CtlFindLdd() and CtlGetLdd() ?? + * + * RETURN + * ERR_VCP_LDDINVALID if pldd->cbSize != structsize + * + */ +static RETERR16 SETUPX_GetLdd(LPLOGDISKDESC pldd) +{ + LDD_LIST *pCurr, *pPrev = NULL; + + if (!std_LDDs_done) + SETUPX_CreateStandardLDDs(); + + if (pldd->cbSize != sizeof(LOGDISKDESC_S)) + return ERR_VCP_LDDINVALID; + + pCurr = pFirstLDD; + /* search until we find the appropriate LDD or hit the end */ + while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid)) + { + pPrev = pCurr; + pCurr = pCurr->next; + } + if (pCurr == NULL) /* hit end of list */ + return ERR_VCP_LDDFIND; /* correct ? */ + + memcpy(pldd, pCurr->pldd, pldd->cbSize); + /* hmm, we probably ought to strcpy() the string ptrs here */ + + return OK; +} + +/**********************************************************************/ + +RETERR16 WINAPI CtlGetLdd16(LPLOGDISKDESC pldd) +{ + FIXME("(%p); - please report this!\n", pldd); + return SETUPX_GetLdd(pldd); +} + +/*********************************************************************** + * CtlGetLddPath (SETUPX.38) + * + * Gets the path of an LDD. + * No crash if szPath == NULL. + * szPath has to be at least MAX_PATH_LEN bytes long. + * RETURN + * ERR_VCP_LDDUNINIT if LDD for LDID not found. + */ +RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath) +{ + TRACE("(%d, %p);\n", ldid, szPath); + + if (szPath) + { + LOGDISKDESC_S ldd; + INIT_LDD(ldd, ldid); + if (CtlFindLdd16(&ldd) == ERR_VCP_LDDFIND) + return ERR_VCP_LDDUNINIT; + SETUPX_GetLdd(&ldd); + strcpy(szPath, ldd.pszPath); + TRACE("ret '%s' for LDID %d\n", szPath, ldid); + } + return OK; +} + +/*********************************************************************** + * CtlSetLddPath (SETUPX.508) + * + * Sets the path of an LDD. + * Creates LDD for LDID if not existing yet. + */ +RETERR16 WINAPI CtlSetLddPath16(LOGDISKID16 ldid, LPSTR szPath) +{ + LOGDISKDESC_S ldd; + TRACE("(%d, '%s');\n", ldid, szPath); + + SetupSetDirectoryIdA( 0, ldid, szPath ); + INIT_LDD(ldd, ldid); + ldd.pszPath = szPath; + return CtlSetLdd16(&ldd); +} diff --git a/reactos/lib/setupapi/stringtable.c b/reactos/lib/setupapi/stringtable.c index 3615edeee26..9269340e779 100644 --- a/reactos/lib/setupapi/stringtable.c +++ b/reactos/lib/setupapi/stringtable.c @@ -1,389 +1,389 @@ -/* - * Setupapi string table functions - * - * Copyright 2005 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winreg.h" -#include "setupapi.h" - -#include "wine/debug.h" - - -#define TABLE_DEFAULT_SIZE 256 - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -typedef struct _STRING_TABLE -{ - LPWSTR *pSlots; /* 0x00 */ - DWORD dwUsedSlots; /* 0x04 */ - DWORD dwMaxSlots; /* 0x08 */ -} STRING_TABLE, *PSTRING_TABLE; - - -/************************************************************************** - * StringTableInitialize [SETUPAPI.@] - * - * Creates a new string table and initializes it. - * - * PARAMS - * None - * - * RETURNS - * Success: Handle to the string table - * Failure: NULL - */ -HSTRING_TABLE WINAPI -StringTableInitialize(VOID) -{ - PSTRING_TABLE pStringTable; - - TRACE("\n"); - - pStringTable = MyMalloc(sizeof(STRING_TABLE)); - if (pStringTable == NULL) - { - ERR("Invalid hStringTable!\n"); - return NULL; - } - - memset(pStringTable, 0, sizeof(STRING_TABLE)); - - pStringTable->pSlots = MyMalloc(sizeof(LPWSTR) * TABLE_DEFAULT_SIZE); - if (pStringTable->pSlots == NULL) - { - MyFree(pStringTable->pSlots); - return NULL; - } - - memset(pStringTable->pSlots, 0, sizeof(LPWSTR) * TABLE_DEFAULT_SIZE); - - pStringTable->dwUsedSlots = 0; - pStringTable->dwMaxSlots = TABLE_DEFAULT_SIZE; - - TRACE("Done\n"); - - return (HSTRING_TABLE)pStringTable; -} - - -/************************************************************************** - * StringTableDestroy [SETUPAPI.@] - * - * Destroys a string table. - * - * PARAMS - * hStringTable [I] Handle to the string table to be destroyed - * - * RETURNS - * None - */ -VOID WINAPI -StringTableDestroy(HSTRING_TABLE hStringTable) -{ - PSTRING_TABLE pStringTable; - DWORD i; - - TRACE("%p\n", (PVOID)hStringTable); - - pStringTable = (PSTRING_TABLE)hStringTable; - if (pStringTable == NULL) - return; - - if (pStringTable->pSlots != NULL) - { - for (i = 0; i < pStringTable->dwMaxSlots; i++) - { - if (pStringTable->pSlots[i] != NULL) - { - MyFree(pStringTable->pSlots[i]); - pStringTable->pSlots[i] = NULL; - } - } - - MyFree(pStringTable->pSlots); - } - - MyFree(pStringTable); -} - - -/************************************************************************** - * StringTableAddString [SETUPAPI.@] - * - * Adds a new string to the string table. - * - * PARAMS - * hStringTable [I] Handle to the string table - * lpString [I] String to be added to the string table - * dwFlags [I] Flags - * 1: case sensitive compare - * - * RETURNS - * Success: String ID - * Failure: -1 - * - * NOTES - * If the given string already exists in the string table it will not - * be added again. The ID of the existing string will be returned in - * this case. - */ -DWORD WINAPI -StringTableAddString(HSTRING_TABLE hStringTable, - LPWSTR lpString, - DWORD dwFlags) -{ - PSTRING_TABLE pStringTable; - DWORD i; - - TRACE("%p %s %lx\n", (PVOID)hStringTable, debugstr_w(lpString), dwFlags); - - pStringTable = (PSTRING_TABLE)hStringTable; - if (pStringTable == NULL) - { - ERR("Invalid hStringTable!\n"); - return (DWORD)-1; - } - - /* Search for existing string in the string table */ - for (i = 0; i < pStringTable->dwMaxSlots; i++) - { - if (pStringTable->pSlots[i] != NULL) - { - if (dwFlags & 1) - { - if (!lstrcmpW(pStringTable->pSlots[i], lpString)) - { - return i; - } - } - else - { - if (!lstrcmpiW(pStringTable->pSlots[i], lpString)) - { - return i; - } - } - } - } - - /* Check for filled slot table */ - if (pStringTable->dwUsedSlots == pStringTable->dwMaxSlots) - { - FIXME("Resize the string table!\n"); - return (DWORD)-1; - } - - /* Search for an empty slot */ - for (i = 0; i < pStringTable->dwMaxSlots; i++) - { - if (pStringTable->pSlots[i] == NULL) - { - pStringTable->pSlots[i] = MyMalloc(lstrlenW(lpString) + sizeof(WCHAR)); - if (pStringTable->pSlots[i] == NULL) - { - TRACE("Couldn't allocate memory for a new string!\n"); - return (DWORD)-1; - } - - lstrcpyW(pStringTable->pSlots[i], lpString); - - pStringTable->dwUsedSlots++; - - return i; - } - } - - TRACE("Couldn't find an empty slot!\n"); - - return (DWORD)-1; -} - - -/************************************************************************** - * StringTableLookUpString [SETUPAPI.@] - * - * Searches a string table for a given string. - * - * PARAMS - * hStringTable [I] Handle to the string table - * lpString [I] String to be searched for - * dwFlags [I] Flags - * 1: case sensitive compare - * - * RETURNS - * Success: String ID - * Failure: -1 - */ -DWORD WINAPI -StringTableLookUpString(HSTRING_TABLE hStringTable, - LPWSTR lpString, - DWORD dwFlags) -{ - PSTRING_TABLE pStringTable; - DWORD i; - - TRACE("%p %s %lx\n", (PVOID)hStringTable, debugstr_w(lpString), dwFlags); - - pStringTable = (PSTRING_TABLE)hStringTable; - if (pStringTable == NULL) - { - ERR("Invalid hStringTable!\n"); - return (DWORD)-1; - } - - /* Search for existing string in the string table */ - for (i = 0; i < pStringTable->dwMaxSlots; i++) - { - if (pStringTable->pSlots[i] != NULL) - { - if (dwFlags & 1) - { - if (!lstrcmpW(pStringTable->pSlots[i], lpString)) - { - return i; - } - } - else - { - if (!lstrcmpiW(pStringTable->pSlots[i], lpString)) - { - return i; - } - } - } - } - - return (DWORD)-1; -} - - -/************************************************************************** - * StringTableStringFromId [SETUPAPI.@] - * - * Returns a pointer to a string for the given string ID. - * - * PARAMS - * hStringTable [I] Handle to the string table. - * dwId [I] String ID - * - * RETURNS - * Success: Pointer to the string - * Failure: NULL - */ -LPWSTR WINAPI -StringTableStringFromId(HSTRING_TABLE hStringTable, - DWORD dwId) -{ - PSTRING_TABLE pStringTable; - - TRACE("%p %lx\n", (PVOID)hStringTable, dwId); - - pStringTable = (PSTRING_TABLE)hStringTable; - if (pStringTable == NULL) - { - ERR("Invalid hStringTable!\n"); - return NULL; - } - - if (dwId >= pStringTable->dwMaxSlots) - return NULL; - - return pStringTable->pSlots[dwId]; -} - - -/************************************************************************** - * StringTableStringFromIdEx [SETUPAPI.@] - * - * Returns a string for the given string ID. - * - * PARAMS - * hStringTable [I] Handle to the string table - * dwId [I] String ID - * lpBuffer [I] Pointer to string buffer - * lpBufferSize [I/O] Pointer to the size of the string buffer - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI -StringTableStringFromIdEx(HSTRING_TABLE hStringTable, - DWORD dwId, - LPWSTR lpBuffer, - LPDWORD lpBufferLength) -{ - PSTRING_TABLE pStringTable; - DWORD dwLength; - BOOL bResult = FALSE; - - TRACE("%p %lx %p %p\n", - (PVOID)hStringTable, dwId, lpBuffer, lpBufferLength); - - pStringTable = (PSTRING_TABLE)hStringTable; - if (pStringTable == NULL) - { - ERR("Invalid hStringTable!\n"); - *lpBufferLength = 0; - return FALSE; - } - - if (dwId >= pStringTable->dwMaxSlots || - pStringTable->pSlots[dwId] == NULL) - { - WARN("Invalid string ID!\n"); - *lpBufferLength = 0; - return FALSE; - } - - dwLength = lstrlenW(pStringTable->pSlots[dwId]) + sizeof(WCHAR); - if (dwLength <= *lpBufferLength) - { - lstrcpyW(lpBuffer, pStringTable->pSlots[dwId]); - bResult = TRUE; - } - - *lpBufferLength = dwLength; - - return bResult; -} - - -/************************************************************************** - * StringTableTrim [SETUPAPI.@] - * - * ... - * - * PARAMS - * hStringTable [I] Handle to the string table - * - * RETURNS - * None - */ -VOID WINAPI -StringTableTrim(HSTRING_TABLE hStringTable) -{ - FIXME("%p\n", (PVOID)hStringTable); -} +/* + * Setupapi string table functions + * + * Copyright 2005 Eric Kohl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winreg.h" +#include "setupapi.h" + +#include "wine/debug.h" + + +#define TABLE_DEFAULT_SIZE 256 + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +typedef struct _STRING_TABLE +{ + LPWSTR *pSlots; /* 0x00 */ + DWORD dwUsedSlots; /* 0x04 */ + DWORD dwMaxSlots; /* 0x08 */ +} STRING_TABLE, *PSTRING_TABLE; + + +/************************************************************************** + * StringTableInitialize [SETUPAPI.@] + * + * Creates a new string table and initializes it. + * + * PARAMS + * None + * + * RETURNS + * Success: Handle to the string table + * Failure: NULL + */ +HSTRING_TABLE WINAPI +StringTableInitialize(VOID) +{ + PSTRING_TABLE pStringTable; + + TRACE("\n"); + + pStringTable = MyMalloc(sizeof(STRING_TABLE)); + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return NULL; + } + + memset(pStringTable, 0, sizeof(STRING_TABLE)); + + pStringTable->pSlots = MyMalloc(sizeof(LPWSTR) * TABLE_DEFAULT_SIZE); + if (pStringTable->pSlots == NULL) + { + MyFree(pStringTable->pSlots); + return NULL; + } + + memset(pStringTable->pSlots, 0, sizeof(LPWSTR) * TABLE_DEFAULT_SIZE); + + pStringTable->dwUsedSlots = 0; + pStringTable->dwMaxSlots = TABLE_DEFAULT_SIZE; + + TRACE("Done\n"); + + return (HSTRING_TABLE)pStringTable; +} + + +/************************************************************************** + * StringTableDestroy [SETUPAPI.@] + * + * Destroys a string table. + * + * PARAMS + * hStringTable [I] Handle to the string table to be destroyed + * + * RETURNS + * None + */ +VOID WINAPI +StringTableDestroy(HSTRING_TABLE hStringTable) +{ + PSTRING_TABLE pStringTable; + DWORD i; + + TRACE("%p\n", (PVOID)hStringTable); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + return; + + if (pStringTable->pSlots != NULL) + { + for (i = 0; i < pStringTable->dwMaxSlots; i++) + { + if (pStringTable->pSlots[i] != NULL) + { + MyFree(pStringTable->pSlots[i]); + pStringTable->pSlots[i] = NULL; + } + } + + MyFree(pStringTable->pSlots); + } + + MyFree(pStringTable); +} + + +/************************************************************************** + * StringTableAddString [SETUPAPI.@] + * + * Adds a new string to the string table. + * + * PARAMS + * hStringTable [I] Handle to the string table + * lpString [I] String to be added to the string table + * dwFlags [I] Flags + * 1: case sensitive compare + * + * RETURNS + * Success: String ID + * Failure: -1 + * + * NOTES + * If the given string already exists in the string table it will not + * be added again. The ID of the existing string will be returned in + * this case. + */ +DWORD WINAPI +StringTableAddString(HSTRING_TABLE hStringTable, + LPWSTR lpString, + DWORD dwFlags) +{ + PSTRING_TABLE pStringTable; + DWORD i; + + TRACE("%p %s %lx\n", (PVOID)hStringTable, debugstr_w(lpString), dwFlags); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return (DWORD)-1; + } + + /* Search for existing string in the string table */ + for (i = 0; i < pStringTable->dwMaxSlots; i++) + { + if (pStringTable->pSlots[i] != NULL) + { + if (dwFlags & 1) + { + if (!lstrcmpW(pStringTable->pSlots[i], lpString)) + { + return i; + } + } + else + { + if (!lstrcmpiW(pStringTable->pSlots[i], lpString)) + { + return i; + } + } + } + } + + /* Check for filled slot table */ + if (pStringTable->dwUsedSlots == pStringTable->dwMaxSlots) + { + FIXME("Resize the string table!\n"); + return (DWORD)-1; + } + + /* Search for an empty slot */ + for (i = 0; i < pStringTable->dwMaxSlots; i++) + { + if (pStringTable->pSlots[i] == NULL) + { + pStringTable->pSlots[i] = MyMalloc(lstrlenW(lpString) + sizeof(WCHAR)); + if (pStringTable->pSlots[i] == NULL) + { + TRACE("Couldn't allocate memory for a new string!\n"); + return (DWORD)-1; + } + + lstrcpyW(pStringTable->pSlots[i], lpString); + + pStringTable->dwUsedSlots++; + + return i; + } + } + + TRACE("Couldn't find an empty slot!\n"); + + return (DWORD)-1; +} + + +/************************************************************************** + * StringTableLookUpString [SETUPAPI.@] + * + * Searches a string table for a given string. + * + * PARAMS + * hStringTable [I] Handle to the string table + * lpString [I] String to be searched for + * dwFlags [I] Flags + * 1: case sensitive compare + * + * RETURNS + * Success: String ID + * Failure: -1 + */ +DWORD WINAPI +StringTableLookUpString(HSTRING_TABLE hStringTable, + LPWSTR lpString, + DWORD dwFlags) +{ + PSTRING_TABLE pStringTable; + DWORD i; + + TRACE("%p %s %lx\n", (PVOID)hStringTable, debugstr_w(lpString), dwFlags); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return (DWORD)-1; + } + + /* Search for existing string in the string table */ + for (i = 0; i < pStringTable->dwMaxSlots; i++) + { + if (pStringTable->pSlots[i] != NULL) + { + if (dwFlags & 1) + { + if (!lstrcmpW(pStringTable->pSlots[i], lpString)) + { + return i; + } + } + else + { + if (!lstrcmpiW(pStringTable->pSlots[i], lpString)) + { + return i; + } + } + } + } + + return (DWORD)-1; +} + + +/************************************************************************** + * StringTableStringFromId [SETUPAPI.@] + * + * Returns a pointer to a string for the given string ID. + * + * PARAMS + * hStringTable [I] Handle to the string table. + * dwId [I] String ID + * + * RETURNS + * Success: Pointer to the string + * Failure: NULL + */ +LPWSTR WINAPI +StringTableStringFromId(HSTRING_TABLE hStringTable, + DWORD dwId) +{ + PSTRING_TABLE pStringTable; + + TRACE("%p %lx\n", (PVOID)hStringTable, dwId); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return NULL; + } + + if (dwId >= pStringTable->dwMaxSlots) + return NULL; + + return pStringTable->pSlots[dwId]; +} + + +/************************************************************************** + * StringTableStringFromIdEx [SETUPAPI.@] + * + * Returns a string for the given string ID. + * + * PARAMS + * hStringTable [I] Handle to the string table + * dwId [I] String ID + * lpBuffer [I] Pointer to string buffer + * lpBufferSize [I/O] Pointer to the size of the string buffer + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI +StringTableStringFromIdEx(HSTRING_TABLE hStringTable, + DWORD dwId, + LPWSTR lpBuffer, + LPDWORD lpBufferLength) +{ + PSTRING_TABLE pStringTable; + DWORD dwLength; + BOOL bResult = FALSE; + + TRACE("%p %lx %p %p\n", + (PVOID)hStringTable, dwId, lpBuffer, lpBufferLength); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + *lpBufferLength = 0; + return FALSE; + } + + if (dwId >= pStringTable->dwMaxSlots || + pStringTable->pSlots[dwId] == NULL) + { + WARN("Invalid string ID!\n"); + *lpBufferLength = 0; + return FALSE; + } + + dwLength = lstrlenW(pStringTable->pSlots[dwId]) + sizeof(WCHAR); + if (dwLength <= *lpBufferLength) + { + lstrcpyW(lpBuffer, pStringTable->pSlots[dwId]); + bResult = TRUE; + } + + *lpBufferLength = dwLength; + + return bResult; +} + + +/************************************************************************** + * StringTableTrim [SETUPAPI.@] + * + * ... + * + * PARAMS + * hStringTable [I] Handle to the string table + * + * RETURNS + * None + */ +VOID WINAPI +StringTableTrim(HSTRING_TABLE hStringTable) +{ + FIXME("%p\n", (PVOID)hStringTable); +} diff --git a/reactos/lib/setupapi/stubs.c b/reactos/lib/setupapi/stubs.c index 3790ebc8e62..67ad32be14c 100644 --- a/reactos/lib/setupapi/stubs.c +++ b/reactos/lib/setupapi/stubs.c @@ -1,157 +1,157 @@ -/* - * SetupAPI stubs - * - * Copyright 2000 James Hatheway - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "wine/debug.h" -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "winreg.h" -#include "setupapi.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -/*********************************************************************** - * TPWriteProfileString (SETUPX.62) - */ -BOOL WINAPI TPWriteProfileString16( LPCSTR section, LPCSTR entry, LPCSTR string ) -{ - FIXME( "%s %s %s: stub\n", debugstr_a(section), debugstr_a(entry), debugstr_a(string) ); - return TRUE; -} - - -/*********************************************************************** - * suErrorToIds (SETUPX.61) - */ -DWORD WINAPI suErrorToIds16( WORD w1, WORD w2 ) -{ - FIXME( "%x %x: stub\n", w1, w2 ); - return 0; -} - -/*********************************************************************** - * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetDeviceInfoListDetailA(HDEVINFO devinfo, PSP_DEVINFO_LIST_DETAIL_DATA_A devinfo_data ) -{ - FIXME("\n"); - return FALSE; -} - -/*********************************************************************** - * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetDeviceInfoListDetailW(HDEVINFO devinfo, PSP_DEVINFO_LIST_DETAIL_DATA_W devinfo_data ) -{ - FIXME("\n"); - return FALSE; -} - -/*********************************************************************** - * (SETUPAPI.@) - * - * NO WINAPI in description given - */ -HDEVINFO WINAPI SetupDiGetClassDevsExA(const GUID *class, PCSTR filter, HWND parent, DWORD flags, HDEVINFO deviceset, PCSTR machine, PVOID reserved) -{ - FIXME("filter %s machine %s\n",debugstr_a(filter),debugstr_a(machine)); - return FALSE; -} - -/*********************************************************************** - * (SETUPAPI.@) - * - * NO WINAPI in description given - */ -HDEVINFO WINAPI SetupDiGetClassDevsExW(const GUID *class, PCWSTR filter, HWND parent, DWORD flags, HDEVINFO deviceset, PCWSTR machine, PVOID reserved) -{ - FIXME("\n"); - return FALSE; -} - - -/*********************************************************************** - * SetupCopyOEMInfA (SETUPAPI.@) - */ -BOOL WINAPI SetupCopyOEMInfA(PCSTR sourceinffile, PCSTR sourcemedialoc, - DWORD mediatype, DWORD copystyle, PSTR destinfname, - DWORD destnamesize, PDWORD required, - PSTR *destinfnamecomponent) -{ - FIXME("stub: source %s location %s ...\n", debugstr_a(sourceinffile), - debugstr_a(sourcemedialoc)); - return FALSE; -} - -/*********************************************************************** - * SetupCopyOEMInfW (SETUPAPI.@) - */ -BOOL WINAPI SetupCopyOEMInfW(PCWSTR sourceinffile, PCWSTR sourcemedialoc, - DWORD mediatype, DWORD copystyle, PWSTR destinfname, - DWORD destnamesize, PDWORD required, - PWSTR *destinfnamecomponent) -{ - FIXME("stub: source %s location %s ...\n", debugstr_w(sourceinffile), - debugstr_w(sourcemedialoc)); - return FALSE; -} - -/*********************************************************************** - * SetupGetInfInformationA (SETUPAPI.@) - */ -BOOL WINAPI SetupGetInfInformationA( LPCVOID InfSpec, DWORD SearchControl, - PSP_INF_INFORMATION ReturnBuffer, - DWORD ReturnBufferSize, PDWORD RequiredSize) -{ - FIXME("(%p, %ld, %p, %ld, %p) Stub!\n", - InfSpec, SearchControl, ReturnBuffer, ReturnBufferSize, RequiredSize ); - return TRUE; -} - -/*********************************************************************** - * SetupInitializeFileLogW(SETUPAPI.@) - */ -HANDLE WINAPI SetupInitializeFileLogW(LPWSTR LogFileName, DWORD Flags) -{ - FIXME("Stub %s, 0x%lx\n",debugstr_w(LogFileName),Flags); - return INVALID_HANDLE_VALUE; -} - -/*********************************************************************** - * SetupInitializeFileLogA(SETUPAPI.@) - */ -HANDLE WINAPI SetupInitializeFileLogA(LPSTR LogFileName, DWORD Flags) -{ - FIXME("Stub %s, 0x%lx\n",debugstr_a(LogFileName),Flags); - return INVALID_HANDLE_VALUE; -} - -/*********************************************************************** - * SetupTerminateFileLog(SETUPAPI.@) - */ -BOOL WINAPI SetupTerminateFileLog(HANDLE FileLogHandle) -{ - FIXME ("Stub %p\n",FileLogHandle); - return TRUE; -} +/* + * SetupAPI stubs + * + * Copyright 2000 James Hatheway + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "winreg.h" +#include "setupapi.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +/*********************************************************************** + * TPWriteProfileString (SETUPX.62) + */ +BOOL WINAPI TPWriteProfileString16( LPCSTR section, LPCSTR entry, LPCSTR string ) +{ + FIXME( "%s %s %s: stub\n", debugstr_a(section), debugstr_a(entry), debugstr_a(string) ); + return TRUE; +} + + +/*********************************************************************** + * suErrorToIds (SETUPX.61) + */ +DWORD WINAPI suErrorToIds16( WORD w1, WORD w2 ) +{ + FIXME( "%x %x: stub\n", w1, w2 ); + return 0; +} + +/*********************************************************************** + * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetDeviceInfoListDetailA(HDEVINFO devinfo, PSP_DEVINFO_LIST_DETAIL_DATA_A devinfo_data ) +{ + FIXME("\n"); + return FALSE; +} + +/*********************************************************************** + * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetDeviceInfoListDetailW(HDEVINFO devinfo, PSP_DEVINFO_LIST_DETAIL_DATA_W devinfo_data ) +{ + FIXME("\n"); + return FALSE; +} + +/*********************************************************************** + * (SETUPAPI.@) + * + * NO WINAPI in description given + */ +HDEVINFO WINAPI SetupDiGetClassDevsExA(const GUID *class, PCSTR filter, HWND parent, DWORD flags, HDEVINFO deviceset, PCSTR machine, PVOID reserved) +{ + FIXME("filter %s machine %s\n",debugstr_a(filter),debugstr_a(machine)); + return FALSE; +} + +/*********************************************************************** + * (SETUPAPI.@) + * + * NO WINAPI in description given + */ +HDEVINFO WINAPI SetupDiGetClassDevsExW(const GUID *class, PCWSTR filter, HWND parent, DWORD flags, HDEVINFO deviceset, PCWSTR machine, PVOID reserved) +{ + FIXME("\n"); + return FALSE; +} + + +/*********************************************************************** + * SetupCopyOEMInfA (SETUPAPI.@) + */ +BOOL WINAPI SetupCopyOEMInfA(PCSTR sourceinffile, PCSTR sourcemedialoc, + DWORD mediatype, DWORD copystyle, PSTR destinfname, + DWORD destnamesize, PDWORD required, + PSTR *destinfnamecomponent) +{ + FIXME("stub: source %s location %s ...\n", debugstr_a(sourceinffile), + debugstr_a(sourcemedialoc)); + return FALSE; +} + +/*********************************************************************** + * SetupCopyOEMInfW (SETUPAPI.@) + */ +BOOL WINAPI SetupCopyOEMInfW(PCWSTR sourceinffile, PCWSTR sourcemedialoc, + DWORD mediatype, DWORD copystyle, PWSTR destinfname, + DWORD destnamesize, PDWORD required, + PWSTR *destinfnamecomponent) +{ + FIXME("stub: source %s location %s ...\n", debugstr_w(sourceinffile), + debugstr_w(sourcemedialoc)); + return FALSE; +} + +/*********************************************************************** + * SetupGetInfInformationA (SETUPAPI.@) + */ +BOOL WINAPI SetupGetInfInformationA( LPCVOID InfSpec, DWORD SearchControl, + PSP_INF_INFORMATION ReturnBuffer, + DWORD ReturnBufferSize, PDWORD RequiredSize) +{ + FIXME("(%p, %ld, %p, %ld, %p) Stub!\n", + InfSpec, SearchControl, ReturnBuffer, ReturnBufferSize, RequiredSize ); + return TRUE; +} + +/*********************************************************************** + * SetupInitializeFileLogW(SETUPAPI.@) + */ +HANDLE WINAPI SetupInitializeFileLogW(LPWSTR LogFileName, DWORD Flags) +{ + FIXME("Stub %s, 0x%lx\n",debugstr_w(LogFileName),Flags); + return INVALID_HANDLE_VALUE; +} + +/*********************************************************************** + * SetupInitializeFileLogA(SETUPAPI.@) + */ +HANDLE WINAPI SetupInitializeFileLogA(LPSTR LogFileName, DWORD Flags) +{ + FIXME("Stub %s, 0x%lx\n",debugstr_a(LogFileName),Flags); + return INVALID_HANDLE_VALUE; +} + +/*********************************************************************** + * SetupTerminateFileLog(SETUPAPI.@) + */ +BOOL WINAPI SetupTerminateFileLog(HANDLE FileLogHandle) +{ + FIXME ("Stub %p\n",FileLogHandle); + return TRUE; +} diff --git a/reactos/lib/setupapi/virtcopy.c b/reactos/lib/setupapi/virtcopy.c index 2771fcbe1e8..14c017fa804 100644 --- a/reactos/lib/setupapi/virtcopy.c +++ b/reactos/lib/setupapi/virtcopy.c @@ -1,788 +1,788 @@ -/* - * SetupAPI virtual copy operations - * - * Copyright 2001 Andreas Mohr - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * FIXME: we now rely on builtin setupapi.dll for dialog resources. - * This is bad ! We ought to have 16bit resource handling working. - */ - -#include -#include -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "winreg.h" -#include "wownt32.h" -#include "wingdi.h" -#include "winnls.h" -#include "setupapi.h" -#include "setupx16.h" -#include "setupapi_private.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(setupapi); - -static FARPROC16 VCP_Proc = NULL; -static LPARAM VCP_MsgRef = 0; - -static BOOL VCP_opened = FALSE; - -static VCPSTATUS vcp_status; - -static HINSTANCE SETUPAPI_hInstance; - -static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef ) -{ - WORD args[8]; - DWORD ret = OK; - if (VCP_Proc) - { - args[7] = HIWORD(obj); - args[6] = LOWORD(obj); - args[5] = msg; - args[4] = wParam; - args[3] = HIWORD(lParam); - args[2] = LOWORD(lParam); - args[1] = HIWORD(lParamRef); - args[0] = LOWORD(lParamRef); - WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret ); - } - return (WORD)ret; -} - -/****************************** VHSTR management ******************************/ - -/* - * This is a totally braindead implementation for now; - * I don't care about speed at all ! Size and implementation time - * is much more important IMHO. I could have created some sophisticated - * tree structure, but... what the hell ! :-) - */ -typedef struct { - DWORD refcount; - LPCSTR pStr; -} VHSTR_STRUCT; - -static VHSTR_STRUCT **vhstrlist = NULL; -static VHSTR vhstr_alloc = 0; - -#define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount)) - -/*********************************************************************** - * vsmStringAdd (SETUPX.207) - */ -VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName) -{ - VHSTR n; - VHSTR index = 0xffff; - HANDLE heap; - - TRACE("add string '%s'\n", lpszName); - /* search whether string already inserted */ - TRACE("searching for existing string...\n"); - for (n = 0; n < vhstr_alloc; n++) - { - if ((vhstrlist[n]) && (vhstrlist[n]->refcount)) - { - TRACE("checking item: %d\n", n); - if (!strcmp(vhstrlist[n]->pStr, lpszName)) - { - TRACE("found\n"); - vhstrlist[n]->refcount++; - return n; - } - } - } - - /* hmm, not found yet, let's insert it */ - TRACE("inserting item\n"); - for (n = 0; n < vhstr_alloc; n++) - { - if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount))) - { - index = n; - break; - } - } - heap = GetProcessHeap(); - if (n == vhstr_alloc) /* hmm, no free index found yet */ - { - index = vhstr_alloc; - vhstr_alloc += 20; - - if (vhstrlist) - vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist, - sizeof(VHSTR_STRUCT *) * vhstr_alloc); - else - vhstrlist = HeapAlloc(heap, HEAP_ZERO_MEMORY, - sizeof(VHSTR_STRUCT *) * vhstr_alloc); - } - if (index == 0xffff) - return 0xffff; /* failure */ - if (!vhstrlist[index]) - vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT)); - vhstrlist[index]->refcount = 1; - vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1); - strcpy((LPSTR)vhstrlist[index]->pStr, lpszName); - return index; -} - -/*********************************************************************** - * vsmStringDelete (SETUPX.206) - */ -INT16 WINAPI vsmStringDelete16(VHSTR vhstr) -{ - if (VALID_VHSTR(vhstr)) - { - vhstrlist[vhstr]->refcount--; - if (!vhstrlist[vhstr]->refcount) - { - HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr); - vhstrlist[vhstr]->pStr = NULL; - } - return VCPN_OK; - } - - /* string not found */ - return VCPN_FAIL; -} - -/* - * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems - */ -VHSTR WINAPI vsmStringFind16(LPCSTR lpszName) -{ - WORD n; - for (n = 0; n < vhstr_alloc; n++) - if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName))) - return n; - return 0xffff; -} - -/*********************************************************************** - * vsmGetStringName (SETUPX.205) - * - * Pretty correct, I guess - */ -INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer) -{ - if (VALID_VHSTR(vhstr)) - { - int len = strlen(vhstrlist[vhstr]->pStr)+1; - if (cbBuffer >= len) - { - if (lpszBuffer) - strcpy(lpszBuffer, vhstrlist[vhstr]->pStr); - return len; - } - } - return VCPN_FAIL; -} - -/*********************************************************************** - * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems) - */ -INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB) -{ - if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB))) - return VCPN_FAIL; /* correct ? */ - return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr); -} - -/*********************************************************************** - * vsmGetStringRawName (SETUPX.208) - */ -LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr) -{ - return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL; -} - - -/***************************** VIRTNODE management ****************************/ -static LPVIRTNODE *pvnlist = NULL; -static DWORD vn_num = 0; -static DWORD vn_last = 0; - -RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl) -{ - HANDLE heap; - LPVIRTNODE lpvn; - RETERR16 cbres; - - while (vn_last < vn_num) - { - if (pvnlist[vn_last] == NULL) - break; - vn_last++; - } - heap = GetProcessHeap(); - if (vn_last == vn_num) - { - vn_num += 20; - if (pvnlist) - pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist, - sizeof(LPVIRTNODE *) * vn_num); - else - pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY, - sizeof(LPVIRTNODE *) * vn_num); - } - pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE)); - lpvn = pvnlist[vn_last]; - vn_last++; - - lpvn->cbSize = sizeof(VIRTNODE); - - if (vfsSrc) - memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC)); - - if (vfsDst) - memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC)); - - lpvn->fl = fl; - lpvn->lParam = lParam; - lpvn->lpExpandVtbl = lpExpandVtbl; - - lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */ - - cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef); - lpvn->fl |= VFNL_CREATED; - cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef); - - return OK; -} - -BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel) -{ - DWORD n; - RETERR16 cbres; - - for (n = 0; n < vn_last; n++) - { - if (pvnlist[n] == lpvnDel) - { - cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef); - HeapFree(GetProcessHeap(), 0, lpvnDel); - pvnlist[n] = NULL; - return TRUE; - } - } - return FALSE; -} - -/*********************************************************************** - * VcpOpen (SETUPX.200) - * - * Sets up a virtual copy operation. - * This means that functions such as GenInstall() - * create a VIRTNODE struct for every file to be touched in a .INF file - * instead of actually touching the file. - * The actual copy/move/rename gets started when VcpClose or - * VcpFlush is called; several different callbacks are made - * (copy, rename, open, close, version conflicts, ...) on every file copied. - */ -RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef) -{ - TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef); - if (VCP_opened) - return ERR_VCP_BUSY; - - VCP_Proc = (FARPROC16)vifproc; - VCP_MsgRef = lparamMsgRef; - - /* load SETUPAPI needed for dialog resources etc. */ - SETUPAPI_hInstance = GetModuleHandleA("setupapi.dll"); - if (!SETUPAPI_hInstance) - { - ERR("Could not load sibling setupapi.dll\n"); - return ERR_VCP_NOMEM; - } - VCP_opened = TRUE; - return OK; -} - -/*********************************************************************** - * VcpQueueCopy [SETUPX.13] - * - * lpExpandVtbl seems to be deprecated. - * fl are the CNFL_xxx and VNFL_xxx flags. - * lParam are the VNLP_xxx flags. - */ -RETERR16 WINAPI VcpQueueCopy16( - LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, - LPCSTR lpszSrcDir, LPCSTR lpszDstDir, - LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, - LPEXPANDVTBL lpExpandVtbl, - WORD fl, LPARAM lParam -) -{ - VCPFILESPEC vfsSrc, vfsDst; - - if (!VCP_opened) - return ERR_VCP_NOTOPEN; - - TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n", - lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName); - - TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst); - - vfsSrc.ldid = ldidSrc; - vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir); - vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName); - - vfsDst.ldid = ldidDst; - vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); - vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); - - return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam, - lpExpandVtbl); -} - -/*********************************************************************** - * VcpQueueDelete [SETUPX.17] - * - * Is lParamRef the same as lParam in VcpQueueCopy ? - * Damn docu !! Err... which docu ? - */ -RETERR16 WINAPI VcpQueueDelete16( - LPCSTR lpszDstFileName, - LPCSTR lpszDstDir, - LOGDISKID16 ldidDst, - LPARAM lParamRef -) -{ - VCPFILESPEC vfsDst; - - if (!VCP_opened) - return ERR_VCP_NOTOPEN; - - vfsDst.ldid = ldidDst; - vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); - vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); - - return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0); -} - -/*********************************************************************** - * VcpQueueRename [SETUPX.204] - * - */ -RETERR16 WINAPI VcpQueueRename16( - LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, - LPCSTR lpszSrcDir, LPCSTR lpszDstDir, - LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, - LPARAM lParam -) -{ - VCPFILESPEC vfsSrc, vfsDst; - - if (!VCP_opened) - return ERR_VCP_NOTOPEN; - - vfsSrc.ldid = ldidSrc; - vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir); - vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName); - - vfsDst.ldid = ldidDst; - vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); - vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); - - return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam, - 0); -} - -/*********************************************************************** - * VcpEnumFiles (SETUPX.@) - */ -INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef) -{ - WORD n; - - for (n = 0; n < vn_last; n++) - vep(pvnlist[n], lParamRef); - - return 0; /* FIXME: return value ? */ -} - -/*********************************************************************** - * VcpExplain (SETUPX.411) - */ -LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat) -{ - static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */ - buffer[0] = '\0'; - switch (dwWhat) - { - case VCPEX_SRC_FULL: - case VCPEX_DST_FULL: - { - LPVCPFILESPEC lpvfs = - (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst; - - /* if we have an ldid, use it, otherwise use the string */ - /* from the vhstrlist array */ - if (lpvfs->ldid != 0xffff) - CtlGetLddPath16(lpvfs->ldid, buffer); - else - strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir)); - - strcat(buffer, "\\"); - strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName)); - } - break; - default: - FIXME("%ld unimplemented !\n", dwWhat); - strcpy(buffer, "Unknown error"); - break; - } - return buffer; -} - -RETERR16 VCP_CheckPaths(void) -{ - DWORD n; - LPVIRTNODE lpvn; - RETERR16 cbres; - - cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef); - for (n = 0; n < vn_num; n++) - { - lpvn = pvnlist[n]; - if (!lpvn) continue; - /* FIXME: check paths of all VIRTNODEs here ! */ - cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef); - } - cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef); - return OK; -} - -RETERR16 VCP_CopyFiles(void) -{ - char fn_src[MAX_PATH], fn_dst[MAX_PATH]; - RETERR16 res = OK, cbres; - DWORD n; - LPVIRTNODE lpvn; - - cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef); - for (n = 0; n < vn_num; n++) - { - lpvn = pvnlist[n]; - if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue; - /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */ - strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL)); - strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL)); - /* FIXME: what is this VCPM_VSTATWRITE here for ? - * I guess it's to signal successful destination file creation */ - cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef); - - /* FIXME: need to do the file copy in small chunks for notifications */ - TRACE("copying '%s' to '%s'\n", fn_src, fn_dst); - /* perform the file copy */ - if (!(CopyFileA(fn_src, fn_dst, - (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE ))) - { - ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst); - res = ERR_VCP_IOFAIL; - } - - vcp_status.prgFileRead.dwSoFar++; - cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef); - vcp_status.prgFileWrite.dwSoFar++; - cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef); - } - - cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef); - return res; -} - -/*********************************************************************** - * VcpFlush - internal (not exported), but documented - * - * VNFL_NOW is used for VcpFlush. - */ -RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest) -{ - return OK; -} - -/*********************************************************************** - * VcpClose (SETUPX.201) - * - * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART, - * VCPM_VSTATCLOSEEND. - * - * fl gets VCPFL_xxx flags to indicate what to do with the - * VIRTNODEs (files to mess with) created by e.g. GenInstall() - */ -RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest) -{ - RETERR16 res = OK; - WORD cbres = VCPN_PROCEED; - - TRACE("(%04x, '%s')\n", fl, lpszBackupDest); - - /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER - * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */ - - TRACE("#1\n"); - memset(&vcp_status, 0, sizeof(VCPSTATUS)); - /* yes, vcp_status.cbSize is 0 ! */ - TRACE("#2\n"); - cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef); - TRACE("#3\n"); - - res = VCP_CheckPaths(); - TRACE("#4\n"); - if (res != OK) - return res; /* is this ok ? */ - VCP_CopyFiles(); - - TRACE("#5\n"); - cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef); - TRACE("#6\n"); - VCP_Proc = NULL; - VCP_opened = FALSE; - return OK; -} - -RETERR16 VCP_RenameFiles(void) -{ - char fn_src[MAX_PATH], fn_dst[MAX_PATH]; - RETERR16 res = OK, cbres; - DWORD n; - LPVIRTNODE lpvn; - - cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef); - for (n = 0; n < vn_num; n++) - { - lpvn = pvnlist[n]; - if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue; - strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL)); - strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL)); - cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef); - if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING))) - res = ERR_VCP_IOFAIL; - else - VCP_VirtnodeDelete(lpvn); - } - cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef); - return res; -} - -/*********************************************************************** - * vcpDefCallbackProc (SETUPX.202) - */ -RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, - LPARAM lParam, LPARAM lParamRef) -{ - static int count = 0; - if (count < 10) - FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n", - lpvObj, uMsg, wParam, lParam, lParamRef); - count++; - return OK; -} - -/********************* point-and-click stuff from here ***********************/ - -static HWND hDlgCopy = 0; -static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0; -static char BackupDir[12]; - -static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) -{ - INT_PTR retval = FALSE; - - if (iMsg == WM_INITDIALOG) - { - ShowWindow(hWndDlg, SW_SHOWNORMAL); - UpdateWindow(hWndDlg); - retval = TRUE; - } - return retval; -} - -BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32) -{ - HRSRC hResInfo; - HGLOBAL hDlgTmpl32; - - if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG))) - return FALSE; - if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) || - !(*template32 = LockResource( hDlgTmpl32 ))) - return FALSE; - return TRUE; -} - -static LRESULT WINAPI -VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg != WM_CREATE) - return DefWindowProcA (hwnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case WM_CREATE: - return 0; - default: - FIXME("%04x: unhandled.\n", uMsg); - } - - return 0; -} - -void VCP_UI_RegisterProgressClass(void) -{ - static BOOL registered = FALSE; - WNDCLASSA wndClass; - - if (registered) - return; - - registered = TRUE; - ZeroMemory (&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; - wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 0; - wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW); - wndClass.hbrBackground = NULL; - wndClass.lpszClassName = "setupx_progress"; - - RegisterClassA (&wndClass); -} - -RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2) -{ - LPCSTR file1, file2; - file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName); - file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName); - return (RETERR16)strcmp(file1, file2); -} - -RETERR16 VCP_UI_CopyStart(void) -{ - LPCVOID template32; - char buf[256]; /* plenty */ - BOOL dirty; - DWORD len; - - /* FIXME: should be registered at DLL startup instead */ - VCP_UI_RegisterProgressClass(); - if (!(VCP_UI_GetDialogTemplate(&template32))) - return VCPN_FAIL; - - if (vn_num > 10) /* hack */ - { - hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0, - VCP_UI_FileCopyDlgProc, 0); - if (!hDlgCopy) - return VCPN_FAIL; - SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ..."); - SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET"); - } - strcpy(buf, REG_INSTALLEDFILES); - if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles)) - return VCPN_FAIL; - strcat(buf, REGPART_RENAME); - if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename)) - return VCPN_FAIL; - if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict)) - return VCPN_FAIL; - len = 1; - if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len))) - { - /* FIXME: what does SETUPX.DLL do in this case ? */ - MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n"); - return VCPN_FAIL; - } - dirty = TRUE; - if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1)) - return VCPN_FAIL; - len = 12; - if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len))) - strcpy(BackupDir, "VCM"); - - /* create C:\WINDOWS\[BackupDir] and set registry key to it */ - GetWindowsDirectoryA(buf, 256); - strcat(buf, "\\"); - strcat(buf, BackupDir); - if (!(CreateDirectoryA(buf, NULL))) - return VCPN_FAIL; - if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1)) - return VCPN_FAIL; - RegCloseKey(hKeyConflict); - - return VCPN_OK; -} - -/*********************************************************************** - * vcpUICallbackProc (SETUPX.213) - */ -RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, - LPARAM lParam, LPARAM lParamRef) -{ - static int count = 0; - RETERR16 res = VCPN_OK, cbres; - - if (count < 5) - FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n", - lpvObj, uMsg, wParam, lParam, lParamRef); - count++; - switch (uMsg) - { - /* unused messages, it seems */ - case VCPM_DISKPREPINFO: - - case VCPM_FILENEEDED: - - case VCPM_NODECREATE: - case VCPM_NODEACCEPT: - - case VCPM_VSTATCLOSESTART: - case VCPM_VSTATPATHCHECKSTART: - case VCPM_VSTATPATHCHECKEND: - - case VCPM_CHECKPATH: - break; - - /* the real stuff */ - case VCPM_NODECOMPARE: - res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam); - break; - case VCPM_VSTATREAD: - break; - case VCPM_VSTATWRITE: - cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef); - break; - case VCPM_VSTATCLOSEEND: - RegCloseKey(hKeyFiles); - RegCloseKey(hKeyRename); - RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT); - break; - case VCPM_VSTATCOPYSTART: - res = VCP_UI_CopyStart(); - break; - case VCPM_VSTATCOPYEND: - if (hDlgCopy) DestroyWindow(hDlgCopy); - break; - default: - FIXME("unhandled msg 0x%04x\n", uMsg); - } - return res; -} +/* + * SetupAPI virtual copy operations + * + * Copyright 2001 Andreas Mohr + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FIXME: we now rely on builtin setupapi.dll for dialog resources. + * This is bad ! We ought to have 16bit resource handling working. + */ + +#include +#include +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "wownt32.h" +#include "wingdi.h" +#include "winnls.h" +#include "setupapi.h" +#include "setupx16.h" +#include "setupapi_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +static FARPROC16 VCP_Proc = NULL; +static LPARAM VCP_MsgRef = 0; + +static BOOL VCP_opened = FALSE; + +static VCPSTATUS vcp_status; + +static HINSTANCE SETUPAPI_hInstance; + +static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef ) +{ + WORD args[8]; + DWORD ret = OK; + if (VCP_Proc) + { + args[7] = HIWORD(obj); + args[6] = LOWORD(obj); + args[5] = msg; + args[4] = wParam; + args[3] = HIWORD(lParam); + args[2] = LOWORD(lParam); + args[1] = HIWORD(lParamRef); + args[0] = LOWORD(lParamRef); + WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret ); + } + return (WORD)ret; +} + +/****************************** VHSTR management ******************************/ + +/* + * This is a totally braindead implementation for now; + * I don't care about speed at all ! Size and implementation time + * is much more important IMHO. I could have created some sophisticated + * tree structure, but... what the hell ! :-) + */ +typedef struct { + DWORD refcount; + LPCSTR pStr; +} VHSTR_STRUCT; + +static VHSTR_STRUCT **vhstrlist = NULL; +static VHSTR vhstr_alloc = 0; + +#define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount)) + +/*********************************************************************** + * vsmStringAdd (SETUPX.207) + */ +VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName) +{ + VHSTR n; + VHSTR index = 0xffff; + HANDLE heap; + + TRACE("add string '%s'\n", lpszName); + /* search whether string already inserted */ + TRACE("searching for existing string...\n"); + for (n = 0; n < vhstr_alloc; n++) + { + if ((vhstrlist[n]) && (vhstrlist[n]->refcount)) + { + TRACE("checking item: %d\n", n); + if (!strcmp(vhstrlist[n]->pStr, lpszName)) + { + TRACE("found\n"); + vhstrlist[n]->refcount++; + return n; + } + } + } + + /* hmm, not found yet, let's insert it */ + TRACE("inserting item\n"); + for (n = 0; n < vhstr_alloc; n++) + { + if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount))) + { + index = n; + break; + } + } + heap = GetProcessHeap(); + if (n == vhstr_alloc) /* hmm, no free index found yet */ + { + index = vhstr_alloc; + vhstr_alloc += 20; + + if (vhstrlist) + vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist, + sizeof(VHSTR_STRUCT *) * vhstr_alloc); + else + vhstrlist = HeapAlloc(heap, HEAP_ZERO_MEMORY, + sizeof(VHSTR_STRUCT *) * vhstr_alloc); + } + if (index == 0xffff) + return 0xffff; /* failure */ + if (!vhstrlist[index]) + vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT)); + vhstrlist[index]->refcount = 1; + vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1); + strcpy((LPSTR)vhstrlist[index]->pStr, lpszName); + return index; +} + +/*********************************************************************** + * vsmStringDelete (SETUPX.206) + */ +INT16 WINAPI vsmStringDelete16(VHSTR vhstr) +{ + if (VALID_VHSTR(vhstr)) + { + vhstrlist[vhstr]->refcount--; + if (!vhstrlist[vhstr]->refcount) + { + HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr); + vhstrlist[vhstr]->pStr = NULL; + } + return VCPN_OK; + } + + /* string not found */ + return VCPN_FAIL; +} + +/* + * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems + */ +VHSTR WINAPI vsmStringFind16(LPCSTR lpszName) +{ + WORD n; + for (n = 0; n < vhstr_alloc; n++) + if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName))) + return n; + return 0xffff; +} + +/*********************************************************************** + * vsmGetStringName (SETUPX.205) + * + * Pretty correct, I guess + */ +INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer) +{ + if (VALID_VHSTR(vhstr)) + { + int len = strlen(vhstrlist[vhstr]->pStr)+1; + if (cbBuffer >= len) + { + if (lpszBuffer) + strcpy(lpszBuffer, vhstrlist[vhstr]->pStr); + return len; + } + } + return VCPN_FAIL; +} + +/*********************************************************************** + * vsmStringCompare (not exported from a standard SETUPX.DLL, it seems) + */ +INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB) +{ + if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB))) + return VCPN_FAIL; /* correct ? */ + return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr); +} + +/*********************************************************************** + * vsmGetStringRawName (SETUPX.208) + */ +LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr) +{ + return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL; +} + + +/***************************** VIRTNODE management ****************************/ +static LPVIRTNODE *pvnlist = NULL; +static DWORD vn_num = 0; +static DWORD vn_last = 0; + +RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl) +{ + HANDLE heap; + LPVIRTNODE lpvn; + RETERR16 cbres; + + while (vn_last < vn_num) + { + if (pvnlist[vn_last] == NULL) + break; + vn_last++; + } + heap = GetProcessHeap(); + if (vn_last == vn_num) + { + vn_num += 20; + if (pvnlist) + pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist, + sizeof(LPVIRTNODE *) * vn_num); + else + pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY, + sizeof(LPVIRTNODE *) * vn_num); + } + pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE)); + lpvn = pvnlist[vn_last]; + vn_last++; + + lpvn->cbSize = sizeof(VIRTNODE); + + if (vfsSrc) + memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC)); + + if (vfsDst) + memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC)); + + lpvn->fl = fl; + lpvn->lParam = lParam; + lpvn->lpExpandVtbl = lpExpandVtbl; + + lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */ + + cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef); + lpvn->fl |= VFNL_CREATED; + cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef); + + return OK; +} + +BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel) +{ + DWORD n; + RETERR16 cbres; + + for (n = 0; n < vn_last; n++) + { + if (pvnlist[n] == lpvnDel) + { + cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef); + HeapFree(GetProcessHeap(), 0, lpvnDel); + pvnlist[n] = NULL; + return TRUE; + } + } + return FALSE; +} + +/*********************************************************************** + * VcpOpen (SETUPX.200) + * + * Sets up a virtual copy operation. + * This means that functions such as GenInstall() + * create a VIRTNODE struct for every file to be touched in a .INF file + * instead of actually touching the file. + * The actual copy/move/rename gets started when VcpClose or + * VcpFlush is called; several different callbacks are made + * (copy, rename, open, close, version conflicts, ...) on every file copied. + */ +RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef) +{ + TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef); + if (VCP_opened) + return ERR_VCP_BUSY; + + VCP_Proc = (FARPROC16)vifproc; + VCP_MsgRef = lparamMsgRef; + + /* load SETUPAPI needed for dialog resources etc. */ + SETUPAPI_hInstance = GetModuleHandleA("setupapi.dll"); + if (!SETUPAPI_hInstance) + { + ERR("Could not load sibling setupapi.dll\n"); + return ERR_VCP_NOMEM; + } + VCP_opened = TRUE; + return OK; +} + +/*********************************************************************** + * VcpQueueCopy [SETUPX.13] + * + * lpExpandVtbl seems to be deprecated. + * fl are the CNFL_xxx and VNFL_xxx flags. + * lParam are the VNLP_xxx flags. + */ +RETERR16 WINAPI VcpQueueCopy16( + LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, + LPCSTR lpszSrcDir, LPCSTR lpszDstDir, + LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, + LPEXPANDVTBL lpExpandVtbl, + WORD fl, LPARAM lParam +) +{ + VCPFILESPEC vfsSrc, vfsDst; + + if (!VCP_opened) + return ERR_VCP_NOTOPEN; + + TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n", + lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName); + + TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst); + + vfsSrc.ldid = ldidSrc; + vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir); + vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName); + + vfsDst.ldid = ldidDst; + vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); + vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); + + return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam, + lpExpandVtbl); +} + +/*********************************************************************** + * VcpQueueDelete [SETUPX.17] + * + * Is lParamRef the same as lParam in VcpQueueCopy ? + * Damn docu !! Err... which docu ? + */ +RETERR16 WINAPI VcpQueueDelete16( + LPCSTR lpszDstFileName, + LPCSTR lpszDstDir, + LOGDISKID16 ldidDst, + LPARAM lParamRef +) +{ + VCPFILESPEC vfsDst; + + if (!VCP_opened) + return ERR_VCP_NOTOPEN; + + vfsDst.ldid = ldidDst; + vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); + vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); + + return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0); +} + +/*********************************************************************** + * VcpQueueRename [SETUPX.204] + * + */ +RETERR16 WINAPI VcpQueueRename16( + LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName, + LPCSTR lpszSrcDir, LPCSTR lpszDstDir, + LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst, + LPARAM lParam +) +{ + VCPFILESPEC vfsSrc, vfsDst; + + if (!VCP_opened) + return ERR_VCP_NOTOPEN; + + vfsSrc.ldid = ldidSrc; + vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir); + vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName); + + vfsDst.ldid = ldidDst; + vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir); + vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName); + + return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam, + 0); +} + +/*********************************************************************** + * VcpEnumFiles (SETUPX.@) + */ +INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef) +{ + WORD n; + + for (n = 0; n < vn_last; n++) + vep(pvnlist[n], lParamRef); + + return 0; /* FIXME: return value ? */ +} + +/*********************************************************************** + * VcpExplain (SETUPX.411) + */ +LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat) +{ + static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */ + buffer[0] = '\0'; + switch (dwWhat) + { + case VCPEX_SRC_FULL: + case VCPEX_DST_FULL: + { + LPVCPFILESPEC lpvfs = + (dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst; + + /* if we have an ldid, use it, otherwise use the string */ + /* from the vhstrlist array */ + if (lpvfs->ldid != 0xffff) + CtlGetLddPath16(lpvfs->ldid, buffer); + else + strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir)); + + strcat(buffer, "\\"); + strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName)); + } + break; + default: + FIXME("%ld unimplemented !\n", dwWhat); + strcpy(buffer, "Unknown error"); + break; + } + return buffer; +} + +RETERR16 VCP_CheckPaths(void) +{ + DWORD n; + LPVIRTNODE lpvn; + RETERR16 cbres; + + cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef); + for (n = 0; n < vn_num; n++) + { + lpvn = pvnlist[n]; + if (!lpvn) continue; + /* FIXME: check paths of all VIRTNODEs here ! */ + cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef); + } + cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef); + return OK; +} + +RETERR16 VCP_CopyFiles(void) +{ + char fn_src[MAX_PATH], fn_dst[MAX_PATH]; + RETERR16 res = OK, cbres; + DWORD n; + LPVIRTNODE lpvn; + + cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef); + for (n = 0; n < vn_num; n++) + { + lpvn = pvnlist[n]; + if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue; + /* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */ + strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL)); + strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL)); + /* FIXME: what is this VCPM_VSTATWRITE here for ? + * I guess it's to signal successful destination file creation */ + cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef); + + /* FIXME: need to do the file copy in small chunks for notifications */ + TRACE("copying '%s' to '%s'\n", fn_src, fn_dst); + /* perform the file copy */ + if (!(CopyFileA(fn_src, fn_dst, + (lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE ))) + { + ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst); + res = ERR_VCP_IOFAIL; + } + + vcp_status.prgFileRead.dwSoFar++; + cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef); + vcp_status.prgFileWrite.dwSoFar++; + cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef); + } + + cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef); + return res; +} + +/*********************************************************************** + * VcpFlush - internal (not exported), but documented + * + * VNFL_NOW is used for VcpFlush. + */ +RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest) +{ + return OK; +} + +/*********************************************************************** + * VcpClose (SETUPX.201) + * + * Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART, + * VCPM_VSTATCLOSEEND. + * + * fl gets VCPFL_xxx flags to indicate what to do with the + * VIRTNODEs (files to mess with) created by e.g. GenInstall() + */ +RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest) +{ + RETERR16 res = OK; + WORD cbres = VCPN_PROCEED; + + TRACE("(%04x, '%s')\n", fl, lpszBackupDest); + + /* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER + * is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */ + + TRACE("#1\n"); + memset(&vcp_status, 0, sizeof(VCPSTATUS)); + /* yes, vcp_status.cbSize is 0 ! */ + TRACE("#2\n"); + cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef); + TRACE("#3\n"); + + res = VCP_CheckPaths(); + TRACE("#4\n"); + if (res != OK) + return res; /* is this ok ? */ + VCP_CopyFiles(); + + TRACE("#5\n"); + cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef); + TRACE("#6\n"); + VCP_Proc = NULL; + VCP_opened = FALSE; + return OK; +} + +RETERR16 VCP_RenameFiles(void) +{ + char fn_src[MAX_PATH], fn_dst[MAX_PATH]; + RETERR16 res = OK, cbres; + DWORD n; + LPVIRTNODE lpvn; + + cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef); + for (n = 0; n < vn_num; n++) + { + lpvn = pvnlist[n]; + if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue; + strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL)); + strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL)); + cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef); + if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING))) + res = ERR_VCP_IOFAIL; + else + VCP_VirtnodeDelete(lpvn); + } + cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef); + return res; +} + +/*********************************************************************** + * vcpDefCallbackProc (SETUPX.202) + */ +RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, + LPARAM lParam, LPARAM lParamRef) +{ + static int count = 0; + if (count < 10) + FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n", + lpvObj, uMsg, wParam, lParam, lParamRef); + count++; + return OK; +} + +/********************* point-and-click stuff from here ***********************/ + +static HWND hDlgCopy = 0; +static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0; +static char BackupDir[12]; + +static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + INT_PTR retval = FALSE; + + if (iMsg == WM_INITDIALOG) + { + ShowWindow(hWndDlg, SW_SHOWNORMAL); + UpdateWindow(hWndDlg); + retval = TRUE; + } + return retval; +} + +BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32) +{ + HRSRC hResInfo; + HGLOBAL hDlgTmpl32; + + if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG))) + return FALSE; + if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) || + !(*template32 = LockResource( hDlgTmpl32 ))) + return FALSE; + return TRUE; +} + +static LRESULT WINAPI +VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg != WM_CREATE) + return DefWindowProcA (hwnd, uMsg, wParam, lParam); + + switch (uMsg) + { + case WM_CREATE: + return 0; + default: + FIXME("%04x: unhandled.\n", uMsg); + } + + return 0; +} + +void VCP_UI_RegisterProgressClass(void) +{ + static BOOL registered = FALSE; + WNDCLASSA wndClass; + + if (registered) + return; + + registered = TRUE; + ZeroMemory (&wndClass, sizeof(WNDCLASSA)); + wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = VCP_UI_FileCopyWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW); + wndClass.hbrBackground = NULL; + wndClass.lpszClassName = "setupx_progress"; + + RegisterClassA (&wndClass); +} + +RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2) +{ + LPCSTR file1, file2; + file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName); + file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName); + return (RETERR16)strcmp(file1, file2); +} + +RETERR16 VCP_UI_CopyStart(void) +{ + LPCVOID template32; + char buf[256]; /* plenty */ + BOOL dirty; + DWORD len; + + /* FIXME: should be registered at DLL startup instead */ + VCP_UI_RegisterProgressClass(); + if (!(VCP_UI_GetDialogTemplate(&template32))) + return VCPN_FAIL; + + if (vn_num > 10) /* hack */ + { + hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0, + VCP_UI_FileCopyDlgProc, 0); + if (!hDlgCopy) + return VCPN_FAIL; + SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ..."); + SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET"); + } + strcpy(buf, REG_INSTALLEDFILES); + if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles)) + return VCPN_FAIL; + strcat(buf, REGPART_RENAME); + if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename)) + return VCPN_FAIL; + if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict)) + return VCPN_FAIL; + len = 1; + if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len))) + { + /* FIXME: what does SETUPX.DLL do in this case ? */ + MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n"); + return VCPN_FAIL; + } + dirty = TRUE; + if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1)) + return VCPN_FAIL; + len = 12; + if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len))) + strcpy(BackupDir, "VCM"); + + /* create C:\WINDOWS\[BackupDir] and set registry key to it */ + GetWindowsDirectoryA(buf, 256); + strcat(buf, "\\"); + strcat(buf, BackupDir); + if (!(CreateDirectoryA(buf, NULL))) + return VCPN_FAIL; + if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1)) + return VCPN_FAIL; + RegCloseKey(hKeyConflict); + + return VCPN_OK; +} + +/*********************************************************************** + * vcpUICallbackProc (SETUPX.213) + */ +RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, + LPARAM lParam, LPARAM lParamRef) +{ + static int count = 0; + RETERR16 res = VCPN_OK, cbres; + + if (count < 5) + FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n", + lpvObj, uMsg, wParam, lParam, lParamRef); + count++; + switch (uMsg) + { + /* unused messages, it seems */ + case VCPM_DISKPREPINFO: + + case VCPM_FILENEEDED: + + case VCPM_NODECREATE: + case VCPM_NODEACCEPT: + + case VCPM_VSTATCLOSESTART: + case VCPM_VSTATPATHCHECKSTART: + case VCPM_VSTATPATHCHECKEND: + + case VCPM_CHECKPATH: + break; + + /* the real stuff */ + case VCPM_NODECOMPARE: + res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam); + break; + case VCPM_VSTATREAD: + break; + case VCPM_VSTATWRITE: + cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef); + break; + case VCPM_VSTATCLOSEEND: + RegCloseKey(hKeyFiles); + RegCloseKey(hKeyRename); + RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT); + break; + case VCPM_VSTATCOPYSTART: + res = VCP_UI_CopyStart(); + break; + case VCPM_VSTATCOPYEND: + if (hDlgCopy) DestroyWindow(hDlgCopy); + break; + default: + FIXME("unhandled msg 0x%04x\n", uMsg); + } + return res; +}