23 #elif defined(_MSC_VER) 28 #include "../tapctl/error.h" 29 #include "../tapctl/tap.h" 37 #pragma comment(lib, "msi.lib") 38 #pragma comment(lib, "ole32.lib") 67 seq->head = seq->head->
next;
118 size_t value_size = (_tcslen(value) + 1) *
sizeof(TCHAR);
129 memcpy(op->
value, value, value_size);
140 _In_ va_list arglist)
150 size_t value_size = 1;
151 for (va_list a = arglist; (str = va_arg(a, LPCTSTR)) != NULL; value_size += _tcslen(str) + 1)
154 value_size *=
sizeof(TCHAR);
168 for (va_list a = arglist; (str = va_arg(a, LPCTSTR)) != NULL;)
170 size_t size = _tcslen(str) + 1;
171 memcpy(value, str, size*
sizeof(TCHAR));
185 _In_ const GUID *value)
204 memcpy(&op->
value, value,
sizeof(GUID));
215 _In_ const GUID *value_guid,
225 size_t value_str_size = (_tcslen(value_str) + 1) *
sizeof(TCHAR);
236 memcpy(&op->
value_guid, value_guid,
sizeof(GUID));
237 memcpy(op->
value_str, value_str, value_str_size);
248 if (seq == NULL || operation == NULL)
255 for (op = operation; op->
next; op = op->
next)
258 op->
next = seq->head;
261 seq->head = operation;
262 if (seq->tail == NULL)
274 if (seq == NULL || operation == NULL)
281 for (op = operation; op->
next; op = op->
next)
286 seq->tail->
next = operation;
290 seq->head = operation;
302 for (
const struct msica_op *op = seq->head; op; op = op->
next)
306 hdr.
ticks = op->ticks;
318 +(DWORD)(_tcslen(((struct msica_op_string *)op)->value) + 1) *
sizeof(TCHAR);
329 +(DWORD)(str + 1 - ((struct msica_op_multistring *)op)->
value) *
sizeof(TCHAR);
340 +(DWORD)(_tcslen(((struct msica_op_guid_string *)op)->value_str) + 1) *
sizeof(TCHAR);
345 return ERROR_BAD_ARGUMENTS;
348 if (!WriteFile(hFile, &hdr,
sizeof(
struct msica_op_hdr), &dwWritten, NULL)
349 || !WriteFile(hFile, op + 1, hdr.
size_data, &dwWritten, NULL))
351 DWORD dwResult = GetLastError();
357 return ERROR_SUCCESS;
370 return ERROR_BAD_ARGUMENTS;
373 seq->head = seq->tail = NULL;
378 if (!ReadFile(hFile, &hdr,
sizeof(
struct msica_op_hdr), &dwRead, NULL))
380 DWORD dwResult = GetLastError();
384 else if (dwRead == 0)
387 return ERROR_SUCCESS;
392 return ERROR_INVALID_DATA;
399 return ERROR_OUTOFMEMORY;
406 if (!ReadFile(hFile, op + 1, hdr.
size_data, &dwRead, NULL))
408 DWORD dwResult = GetLastError();
416 return ERROR_INVALID_DATA;
429 if (op == NULL || session == NULL)
431 return ERROR_BAD_ARGUMENTS;
436 MSIHANDLE hRecord = MsiCreateRecord(3);
437 MsiRecordSetString(hRecord, 1, TEXT(
"Creating TAP interface"));
438 MsiRecordSetString(hRecord, 2, op->value);
439 int iResult = MsiProcessMessage(session->hInstall, INSTALLMESSAGE_ACTIONDATA, hRecord);
440 MsiCloseHandle(hRecord);
441 if (iResult == IDCANCEL)
443 return ERROR_INSTALL_USEREXIT;
450 if (dwResult == ERROR_SUCCESS)
455 if (pInterfaceOther == NULL)
458 BOOL bRebootRequired = FALSE;
461 if (dwResult == ERROR_SUCCESS)
465 if (dwResult == ERROR_SUCCESS)
467 if (session->rollback_enabled)
486 MsiSetMode(session->hInstall, MSIRUNMODE_REBOOTATEND, TRUE);
491 else if (_tcsicmp(op->value, pInterfaceOther->szName) == 0)
494 for (LPCTSTR hwid = pInterfaceOther->szzHardwareIDs;; hwid += _tcslen(hwid) + 1)
499 msg(
M_NONFATAL,
"%s: Interface with name \"%" PRIsLPTSTR "\" already exists", __FUNCTION__, pInterfaceOther->szName);
500 dwResult = ERROR_ALREADY_EXISTS;
508 dwResult = ERROR_SUCCESS;
529 if (pInterfaceList == NULL || pInterface == NULL || session == NULL)
531 return ERROR_BAD_ARGUMENTS;
537 BOOL bRebootRequired = FALSE;
541 MsiSetMode(session->hInstall, MSIRUNMODE_REBOOTATEND, TRUE);
544 if (session->rollback_enabled)
572 pInterface->szName));
584 if (op == NULL || session == NULL)
586 return ERROR_BAD_ARGUMENTS;
591 MSIHANDLE hRecord = MsiCreateRecord(3);
592 MsiRecordSetString(hRecord, 1, TEXT(
"Deleting interface"));
593 MsiRecordSetString(hRecord, 2, op->value);
594 int iResult = MsiProcessMessage(session->hInstall, INSTALLMESSAGE_ACTIONDATA, hRecord);
595 MsiCloseHandle(hRecord);
596 if (iResult == IDCANCEL)
598 return ERROR_INSTALL_USEREXIT;
605 if (dwResult == ERROR_SUCCESS)
610 if (pInterface == NULL)
613 dwResult = ERROR_SUCCESS;
616 else if (_tcsicmp(op->value, pInterface->szName) == 0)
639 if (op == NULL || session == NULL)
641 return ERROR_BAD_ARGUMENTS;
646 MSIHANDLE hRecord = MsiCreateRecord(3);
647 LPOLESTR szInterfaceId = NULL;
648 StringFromIID((REFIID)&op->value, &szInterfaceId);
649 MsiRecordSetString(hRecord, 1, TEXT(
"Deleting interface"));
650 MsiRecordSetString(hRecord, 2, szInterfaceId);
651 int iResult = MsiProcessMessage(session->hInstall, INSTALLMESSAGE_ACTIONDATA, hRecord);
652 CoTaskMemFree(szInterfaceId);
653 MsiCloseHandle(hRecord);
654 if (iResult == IDCANCEL)
656 return ERROR_INSTALL_USEREXIT;
663 if (dwResult == ERROR_SUCCESS)
668 if (pInterface == NULL)
671 dwResult = ERROR_SUCCESS;
674 else if (memcmp(&op->value, &pInterface->guid,
sizeof(GUID)) == 0)
697 if (op == NULL || session == NULL)
699 return ERROR_BAD_ARGUMENTS;
704 MSIHANDLE hRecord = MsiCreateRecord(3);
705 LPOLESTR szInterfaceId = NULL;
706 StringFromIID((REFIID)&op->value_guid, &szInterfaceId);
707 MsiRecordSetString(hRecord, 1, TEXT(
"Setting interface name"));
708 MsiRecordSetString(hRecord, 2, szInterfaceId);
709 MsiRecordSetString(hRecord, 3, op->value_str);
710 int iResult = MsiProcessMessage(session->hInstall, INSTALLMESSAGE_ACTIONDATA, hRecord);
711 CoTaskMemFree(szInterfaceId);
712 MsiCloseHandle(hRecord);
713 if (iResult == IDCANCEL)
715 return ERROR_INSTALL_USEREXIT;
722 if (dwResult == ERROR_SUCCESS)
727 if (pInterface == NULL)
730 LPOLESTR szInterfaceId = NULL;
731 StringFromIID((REFIID)&op->value_guid, &szInterfaceId);
733 CoTaskMemFree(szInterfaceId);
734 dwResult = ERROR_FILE_NOT_FOUND;
737 else if (memcmp(&op->value_guid, &pInterface->guid,
sizeof(GUID)) == 0)
742 if (pInterfaceOther == NULL)
746 if (dwResult == ERROR_SUCCESS)
748 if (session->rollback_enabled)
758 pInterface->szName));
763 else if (_tcsicmp(op->value_str, pInterfaceOther->szName) == 0)
766 msg(
M_NONFATAL,
"%s: Interface with name \"%" PRIsLPTSTR "\" already exists", __FUNCTION__, pInterfaceOther->szName);
767 dwResult = ERROR_ALREADY_EXISTS;
787 if (op == NULL || session == NULL)
789 return ERROR_BAD_ARGUMENTS;
794 MSIHANDLE hRecord = MsiCreateRecord(3);
795 MsiRecordSetString(hRecord, 1, TEXT(
"Deleting file"));
796 MsiRecordSetString(hRecord, 2, op->value);
797 int iResult = MsiProcessMessage(session->hInstall, INSTALLMESSAGE_ACTIONDATA, hRecord);
798 MsiCloseHandle(hRecord);
799 if (iResult == IDCANCEL)
801 return ERROR_INSTALL_USEREXIT;
807 if (session->rollback_enabled)
809 size_t sizeNameBackupLenZ = _tcslen(op->value) + 7 + 10 + 1 + 1 ;
810 LPTSTR szNameBackup = (LPTSTR)
malloc(sizeNameBackupLenZ *
sizeof(TCHAR));
811 if (szNameBackup == NULL)
813 msg(
M_FATAL,
"%s: malloc(%u) failed", __FUNCTION__, sizeNameBackupLenZ *
sizeof(TCHAR));
814 return ERROR_OUTOFMEMORY;
823 szNameBackup, sizeNameBackupLenZ,
824 TEXT(
"%s (orig %i)"),
827 dwResult = MoveFile(op->value, szNameBackup) ? ERROR_SUCCESS : GetLastError();
828 }
while (dwResult == ERROR_ALREADY_EXISTS);
830 if (dwResult == ERROR_SUCCESS)
852 else if (dwResult == ERROR_FILE_NOT_FOUND)
854 dwResult = ERROR_SUCCESS;
866 dwResult = DeleteFile(op->value) ? ERROR_SUCCESS : GetLastError();
867 if (dwResult == ERROR_FILE_NOT_FOUND)
869 dwResult = ERROR_SUCCESS;
871 else if (dwResult != ERROR_SUCCESS)
886 if (op == NULL || session == NULL)
888 return ERROR_BAD_ARGUMENTS;
892 LPCTSTR szNameSrc = op->value;
893 if (szNameSrc[0] == 0)
895 return ERROR_BAD_ARGUMENTS;
899 LPCTSTR szNameDst = szNameSrc + _tcslen(szNameSrc) + 1;
900 if (szNameDst[0] == 0)
902 return ERROR_BAD_ARGUMENTS;
907 MSIHANDLE hRecord = MsiCreateRecord(3);
908 MsiRecordSetString(hRecord, 1, TEXT(
"Moving file"));
909 MsiRecordSetString(hRecord, 2, szNameSrc);
910 MsiRecordSetString(hRecord, 3, szNameDst);
911 int iResult = MsiProcessMessage(session->hInstall, INSTALLMESSAGE_ACTIONDATA, hRecord);
912 MsiCloseHandle(hRecord);
913 if (iResult == IDCANCEL)
915 return ERROR_INSTALL_USEREXIT;
919 DWORD dwResult = MoveFile(szNameSrc, szNameDst) ? ERROR_SUCCESS : GetLastError();
920 if (dwResult == ERROR_SUCCESS)
922 if (session->rollback_enabled)
948 _In_ MSIHANDLE hInstall,
949 _In_ bool continue_on_error,
950 _In_ bool rollback_enabled)
952 session->hInstall = hInstall;
953 session->continue_on_error = continue_on_error;
954 session->rollback_enabled = rollback_enabled;
969 if (seq == NULL || session == NULL)
971 return ERROR_BAD_ARGUMENTS;
975 MSIHANDLE hRecordProg = MsiCreateRecord(3);
976 MsiRecordSetInteger(hRecordProg, 1, 1);
977 MsiRecordSetInteger(hRecordProg, 2, 1);
978 MsiRecordSetInteger(hRecordProg, 3, 0);
979 MsiProcessMessage(session->hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg);
982 MsiRecordSetInteger(hRecordProg, 1, 2);
983 MsiRecordSetInteger(hRecordProg, 3, 0);
985 for (
const struct msica_op *op = seq->head; op; op = op->
next)
990 session->rollback_enabled = ((
const struct msica_op_bool *)op)->value;
991 dwResult = ERROR_SUCCESS;
1019 msg(
M_NONFATAL,
"%s: Unknown operation type (%x)", __FUNCTION__, op->type);
1020 dwResult = ERROR_FILE_NOT_FOUND;
1023 if (!session->continue_on_error && dwResult != ERROR_SUCCESS)
1026 goto cleanup_hRecordProg;
1030 MsiRecordSetInteger(hRecordProg, 2, op->ticks);
1031 if (MsiProcessMessage(session->hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL)
1033 dwResult = ERROR_INSTALL_USEREXIT;
1034 goto cleanup_hRecordProg;
1038 dwResult = ERROR_SUCCESS;
1040 cleanup_hRecordProg:
1041 MsiCloseHandle(hRecordProg);
DWORD msica_op_seq_load(_Inout_ struct msica_op_seq *seq, _In_ HANDLE hFile)
Loads the operation sequence from the file.
static DWORD msica_op_tap_interface_set_name_exec(_Inout_ const struct msica_op_guid_string *op, _Inout_ struct msica_session *session)
static DWORD msica_op_tap_interface_delete(_In_ struct tap_interface_node *pInterfaceList, _In_ struct tap_interface_node *pInterface, _Inout_ struct msica_session *session)
msica_op_type
Operation types.
Delete TAP/TUN interface | msica_op_string.
TCHAR value[]
Common operation data.
DWORD tap_delete_interface(_In_opt_ HWND hwndParent, _In_ LPCGUID pguidInterface, _Inout_ LPBOOL pbRebootRequired)
Deletes an interface.
DWORD tap_set_interface_name(_In_ LPCGUID pguidInterface, _In_ LPCTSTR szName)
Sets interface name.
DWORD msica_op_seq_process(_Inout_ const struct msica_op_seq *seq, _Inout_ struct msica_session *session)
Executes all operations in sequence.
static DWORD msica_op_tap_interface_create_exec(_Inout_ const struct msica_op_string *op, _Inout_ struct msica_session *session)
static DWORD msica_op_tap_interface_delete_by_guid_exec(_Inout_ const struct msica_op_guid *op, _Inout_ struct msica_session *session)
Operation data (bool, 0x1)
TCHAR value_str[]
Operation data GUID.
DWORD size_data
Number of ticks on the progress indicator this operation represents.
#define MSICA_CLEANUP_ACTION_ROLLBACK
void openvpnmsica_session_init(_Inout_ struct msica_session *session, _In_ MSIHANDLE hInstall, _In_ bool continue_on_error, _In_ bool rollback_enabled)
Initializes execution session.
GUID value
Common operation data.
DWORD tap_list_interfaces(_In_opt_ HWND hwndParent, _In_opt_ LPCTSTR szHwId, _Out_ struct tap_interface_node **ppInterface, _In_ BOOL bAll)
Creates a list of available network interfaces.
#define MSICA_CLEANUP_ACTION_COUNT
Operation data (guid-string, 0x5)
static DWORD msica_op_tap_interface_delete_by_name_exec(_Inout_ const struct msica_op_string *op, _Inout_ struct msica_session *session)
struct msica_op * msica_op_create_bool(_In_ enum msica_op_type type, _In_ int ticks, _In_opt_ struct msica_op *next, _In_ bool value)
Allocates and fills a new msica_op_bool operation.
Create TAP/TUN interface | msica_op_string.
Operation data (GUID, 0x4)
TCHAR value[]
Common operation data.
struct msica_op * msica_op_create_multistring_va(_In_ enum msica_op_type type, _In_ int ticks, _In_opt_ struct msica_op *next, _In_ va_list arglist)
Allocates and fills a new msica_op_multistring operation.
static DWORD msica_op_file_delete_exec(_Inout_ const struct msica_op_string *op, _Inout_ struct msica_session *session)
struct tap_interface_node * pNext
Interface name.
void msica_op_seq_init(_Inout_ struct msica_op_seq *seq)
Initializes operation sequence.
DWORD msica_op_seq_save(_In_ const struct msica_op_seq *seq, _In_ HANDLE hFile)
Saves the operation sequence to the file.
Operation data (multi-string, 0x3)
#define TAP_WIN_COMPONENT_ID
struct msica_op * msica_op_create_guid(_In_ enum msica_op_type type, _In_ int ticks, _In_opt_ struct msica_op *next, _In_ const GUID *value)
Allocates and fills a new msica_op_guid operation.
void msica_op_seq_add_tail(_Inout_ struct msica_op_seq *seq, _Inout_ struct msica_op *operation)
Appends operation(s) to the end of the operation sequence.
Operation data (string, 0x2)
static struct msica_op * msica_op_create_multistring(_In_ enum msica_op_type type, _In_ int ticks, _In_opt_ struct msica_op *next,...)
Allocates and fills a new msica_op_multistring operation.
Network interface list node.
Delete TAP/TUN interface | msica_op_guid.
Enable/disable rollback | msica_op_bool.
struct msica_op * msica_op_create_string(_In_ enum msica_op_type type, _In_ int ticks, _In_opt_ struct msica_op *next, _In_z_ LPCTSTR value)
Allocates and fills a new msica_op_string operation.
void tap_free_interface_list(_In_ struct tap_interface_node *pInterfaceList)
Frees a list of network interfaces.
Delete file | msica_op_string.
struct msica_op * next
Number of ticks on the progress indicator this operation represents.
Rename TAP/TUN interface | msica_op_guid_string.
static DWORD msica_op_file_move_exec(_Inout_ const struct msica_op_multistring *op, _Inout_ struct msica_session *session)
GUID value_guid
Common operation data.
#define MSICA_OP_TYPE_DATA(type)
#define MSICA_CLEANUP_ACTION_COMMIT
Execution session constants.
void msica_op_seq_free(_Inout_ struct msica_op_seq *seq)
Frees operation sequence.
struct msica_op * msica_op_create_guid_string(_In_ enum msica_op_type type, _In_ int ticks, _In_opt_ struct msica_op *next, _In_ const GUID *value_guid, _In_z_ LPCTSTR value_str)
Allocates and fills a new msica_op_guid_string operation.
bool value
Common operation data.
Operation data persist header.
DWORD tap_create_interface(_In_opt_ HWND hwndParent, _In_opt_ LPCTSTR szDeviceDescription, _In_opt_ LPCTSTR szHwId, _Inout_ LPBOOL pbRebootRequired, _Out_ LPGUID pguidInterface)
Creates a TUN/TAP interface.
void msica_op_seq_add_head(_Inout_ struct msica_op_seq *seq, _Inout_ struct msica_op *operation)
Inserts operation(s) to the beginning of the operation sequence.